diff --git a/.travis.yml b/.travis.yml index c4abf81f7c8..dc3c2fdb09f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -141,7 +141,7 @@ matrix: after_success: # run astyle for all files on the branch - git checkout -- . - - find -regex '.*\.\(h\|c\|hpp\|cpp\)' -type f | fgrep -v -f .astyleignore | xargs -n 100 -I {} bash -c "astyle -n --options=.astylerc \"{}\"" > astyle-branch.out; + - find -regex '.*\.\(h\|c\|hpp\|cpp\)$' -type f | fgrep -v -f .astyleignore | xargs -n 100 -I {} bash -c "astyle -n --options=.astylerc \"{}\"" > astyle-branch.out; # update status if we succeeded, compare with master if possible - | CURR=$(cat astyle-branch.out | grep Formatted | wc -l) diff --git a/TESTS/netsocket/dns/asynchronous_dns_non_async_and_async.cpp b/TESTS/netsocket/dns/asynchronous_dns_non_async_and_async.cpp index 37831b511b8..a565ed50b99 100644 --- a/TESTS/netsocket/dns/asynchronous_dns_non_async_and_async.cpp +++ b/TESTS/netsocket/dns/asynchronous_dns_non_async_and_async.cpp @@ -45,7 +45,7 @@ void ASYNCHRONOUS_DNS_NON_ASYNC_AND_ASYNC() TEST_ASSERT(strlen(addr.get_ip_address()) > 1); } - semaphore.wait(); + semaphore.wait(100); TEST_ASSERT(data.result == NSAPI_ERROR_OK); diff --git a/TESTS/netsocket/tcp/tcp_tests.h b/TESTS/netsocket/tcp/tcp_tests.h index c2e34e4bc4c..2c694948f01 100644 --- a/TESTS/netsocket/tcp/tcp_tests.h +++ b/TESTS/netsocket/tcp/tcp_tests.h @@ -30,7 +30,7 @@ nsapi_error_t tcpsocket_connect_to_discard_srv(TCPSocket &sock); int split2half_rmng_tcp_test_time(); // [s] namespace tcp_global { -static const int TESTS_TIMEOUT = 960; +static const int TESTS_TIMEOUT = 480; static const int TCP_OS_STACK_SIZE = 2048; static const int RX_BUFF_SIZE = 1220; diff --git a/TESTS/netsocket/tcp/tcpsocket_recv_timeout.cpp b/TESTS/netsocket/tcp/tcpsocket_recv_timeout.cpp index 4fd0008c032..4254d06c863 100644 --- a/TESTS/netsocket/tcp/tcpsocket_recv_timeout.cpp +++ b/TESTS/netsocket/tcp/tcpsocket_recv_timeout.cpp @@ -66,8 +66,8 @@ void TCPSOCKET_RECV_TIMEOUT() TEST_FAIL(); goto CLEANUP; } - printf("MBED: recv() took: %dms\n", timer.read_ms()); - TEST_ASSERT_INT_WITHIN(50, 150, timer.read_ms()); + printf("MBED: recv() took: %dus\n", timer.read_us()); + TEST_ASSERT_INT_WITHIN(51, 150, (timer.read_us() + 500) / 1000); continue; } else if (recvd < 0) { printf("[pkt#%02d] network error %d\n", i, recvd); diff --git a/TESTS/network/interface/networkinterface_status.cpp b/TESTS/network/interface/networkinterface_status.cpp index c0d509d516e..32d1a2bd8e9 100644 --- a/TESTS/network/interface/networkinterface_status.cpp +++ b/TESTS/network/interface/networkinterface_status.cpp @@ -89,7 +89,8 @@ void NETWORKINTERFACE_STATUS() } TEST_ASSERT_EQUAL(NSAPI_STATUS_GLOBAL_UP, status); - net->disconnect(); + err = net->disconnect(); + TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, err); status = wait_status_callback(); TEST_ASSERT_EQUAL(NSAPI_STATUS_DISCONNECTED, status); @@ -123,7 +124,8 @@ void NETWORKINTERFACE_STATUS_NONBLOCK() } TEST_ASSERT_EQUAL(NSAPI_STATUS_GLOBAL_UP, status); - net->disconnect(); + err = net->disconnect(); + TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, err); status = wait_status_callback(); TEST_ASSERT_EQUAL(NSAPI_STATUS_DISCONNECTED, status); @@ -150,7 +152,8 @@ void NETWORKINTERFACE_STATUS_GET() wait(0.5); } - net->disconnect(); + err = net->disconnect(); + TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, err); TEST_ASSERT_EQUAL(NSAPI_STATUS_DISCONNECTED, net->get_connection_status()); } diff --git a/TESTS/network/wifi/wifi_connect_params_null.cpp b/TESTS/network/wifi/wifi_connect_params_null.cpp index 30f82a891cc..21bb8cc96ed 100644 --- a/TESTS/network/wifi/wifi_connect_params_null.cpp +++ b/TESTS/network/wifi/wifi_connect_params_null.cpp @@ -30,7 +30,7 @@ void wifi_connect_params_null(void) error = wifi->connect(NULL, NULL); wifi->disconnect(); TEST_ASSERT(error == NSAPI_ERROR_PARAMETER); - error = wifi->connect("", ""); + error = wifi->connect("", ""); wifi->disconnect(); TEST_ASSERT(error == NSAPI_ERROR_PARAMETER); } diff --git a/TESTS/network/wifi/wifi_connect_secure.cpp b/TESTS/network/wifi/wifi_connect_secure.cpp index 6a2e8e36fef..18f8da004bb 100644 --- a/TESTS/network/wifi/wifi_connect_secure.cpp +++ b/TESTS/network/wifi/wifi_connect_secure.cpp @@ -32,7 +32,7 @@ void wifi_connect_secure(void) TEST_ASSERT_EQUAL_INT(NSAPI_ERROR_OK, wifi->set_credentials(MBED_CONF_APP_WIFI_SECURE_SSID, MBED_CONF_APP_WIFI_PASSWORD, get_security())); TEST_ASSERT_EQUAL_INT(NSAPI_ERROR_OK, wifi->connect()); - + TEST_ASSERT_EQUAL_INT(NSAPI_ERROR_OK, wifi->disconnect()); } diff --git a/UNITTESTS/features/cellular/framework/AT/at_cellularnetwork/at_cellularnetworktest.cpp b/UNITTESTS/features/cellular/framework/AT/at_cellularnetwork/at_cellularnetworktest.cpp index faad7ccd247..28c80e11267 100644 --- a/UNITTESTS/features/cellular/framework/AT/at_cellularnetwork/at_cellularnetworktest.cpp +++ b/UNITTESTS/features/cellular/framework/AT/at_cellularnetwork/at_cellularnetworktest.cpp @@ -185,12 +185,12 @@ TEST_F(TestAT_CellularNetwork, test_AT_CellularNetwork_get_registration_params) reg_params._periodic_tau = 3; EXPECT_TRUE(NSAPI_ERROR_DEVICE_ERROR == cn.get_registration_params(CellularNetwork::C_EREG, reg_params)); - EXPECT_TRUE(reg_params._status == CellularNetwork::StatusNotAvailable); + EXPECT_TRUE(reg_params._status == CellularNetwork::NotRegistered); EXPECT_TRUE(reg_params._act == CellularNetwork::RAT_UNKNOWN); EXPECT_TRUE(reg_params._cell_id == -1 && reg_params._active_time == -1 && reg_params._periodic_tau == -1); EXPECT_TRUE(NSAPI_ERROR_DEVICE_ERROR == cn.get_registration_params(CellularNetwork::C_GREG, reg_params)); - EXPECT_TRUE(reg_params._status == CellularNetwork::StatusNotAvailable); + EXPECT_TRUE(reg_params._status == CellularNetwork::NotRegistered); EXPECT_TRUE(reg_params._act == CellularNetwork::RAT_UNKNOWN); EXPECT_TRUE(reg_params._cell_id == -1); @@ -201,12 +201,12 @@ TEST_F(TestAT_CellularNetwork, test_AT_CellularNetwork_get_registration_params) reg_params._periodic_tau = 3; EXPECT_TRUE(NSAPI_ERROR_DEVICE_ERROR == nw.get_registration_params(CellularNetwork::C_EREG, reg_params)); - EXPECT_TRUE(reg_params._status == CellularNetwork::StatusNotAvailable); + EXPECT_TRUE(reg_params._status == CellularNetwork::NotRegistered); EXPECT_TRUE(reg_params._act == CellularNetwork::RAT_UNKNOWN); EXPECT_TRUE(reg_params._cell_id == -1 && reg_params._active_time == -1 && reg_params._periodic_tau == -1); // Check get_registration_params without specifying the registration type EXPECT_TRUE(NSAPI_ERROR_OK == cn.get_registration_params(reg_params_check)); - EXPECT_TRUE(reg_params_check._status == CellularNetwork::StatusNotAvailable); + EXPECT_TRUE(reg_params_check._status == CellularNetwork::NotRegistered); EXPECT_TRUE(reg_params_check._act == CellularNetwork::RAT_UNKNOWN); EXPECT_TRUE(reg_params_check._cell_id == -1 && reg_params_check._active_time == -1 && reg_params_check._periodic_tau == -1); } @@ -497,7 +497,7 @@ TEST_F(TestAT_CellularNetwork, test_AT_CellularNetwork_get_signal_quality) ATHandler_stub::int_value = 1; ATHandler_stub::nsapi_error_value = NSAPI_ERROR_OK; EXPECT_TRUE(NSAPI_ERROR_OK == cn.get_signal_quality(rs, ber)); - EXPECT_TRUE(rs == 1 && ber == 1); + EXPECT_TRUE(rs == -111 && ber == 1); } TEST_F(TestAT_CellularNetwork, test_AT_CellularNetwork_get_3gpp_error) diff --git a/UNITTESTS/features/netsocket/DTLSSocket/dtls_test_config.h b/UNITTESTS/features/netsocket/DTLSSocket/dtls_test_config.h new file mode 100644 index 00000000000..c53b2e40504 --- /dev/null +++ b/UNITTESTS/features/netsocket/DTLSSocket/dtls_test_config.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2018, Arm Limited and affiliates + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 UNITTESTS_FEATURES_NETSOCKET_DTLSSOCKET_DTLS_TEST_CONFIG_H_ +#define UNITTESTS_FEATURES_NETSOCKET_DTLSSOCKET_DTLS_TEST_CONFIG_H_ + +#define MBEDTLS_SSL_CLI_C + + +#endif /* UNITTESTS_FEATURES_NETSOCKET_DTLSSOCKET_DTLS_TEST_CONFIG_H_ */ diff --git a/UNITTESTS/features/netsocket/DTLSSocket/test_DTLSSocket.cpp b/UNITTESTS/features/netsocket/DTLSSocket/test_DTLSSocket.cpp new file mode 100644 index 00000000000..cc4bdc2aecd --- /dev/null +++ b/UNITTESTS/features/netsocket/DTLSSocket/test_DTLSSocket.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018, Arm Limited and affiliates + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "gtest/gtest.h" +#include "features/netsocket/DTLSSocket.h" +#include "NetworkStack_stub.h" + +#include "mbed_error.h" +mbed_error_status_t mbed_error(mbed_error_status_t error_status, const char *error_msg, unsigned int error_value, const char *filename, int line_number) +{ + return 0; +} + +// Control the rtos EventFlags stub. See EventFlags_stub.cpp +extern std::list eventFlagsStubNextRetval; + +class TestDTLSSocket : public testing::Test { +public: + unsigned int dataSize = 10; + char dataBuf[10]; +protected: + DTLSSocket *socket; + NetworkStackstub stack; + + virtual void SetUp() + { + socket = new DTLSSocket(); + } + + virtual void TearDown() + { + stack.return_values.clear(); + eventFlagsStubNextRetval.clear(); + delete socket; + } +}; + +TEST_F(TestDTLSSocket, constructor) +{ + EXPECT_TRUE(socket); +} + +/* connect */ + +TEST_F(TestDTLSSocket, connect) +{ + socket->open((NetworkStack *)&stack); + + stack.return_value = NSAPI_ERROR_OK; + EXPECT_EQ(socket->connect("127.0.0.1", 1024), NSAPI_ERROR_OK); +} + +TEST_F(TestDTLSSocket, connect_error) +{ + socket->open((NetworkStack *)&stack); + + stack.return_value = NSAPI_ERROR_DNS_FAILURE; + EXPECT_EQ(socket->connect("127.0.0.1", 1024), NSAPI_ERROR_DNS_FAILURE); +} diff --git a/UNITTESTS/features/netsocket/DTLSSocket/unittest.cmake b/UNITTESTS/features/netsocket/DTLSSocket/unittest.cmake new file mode 100644 index 00000000000..6588d4ed2a5 --- /dev/null +++ b/UNITTESTS/features/netsocket/DTLSSocket/unittest.cmake @@ -0,0 +1,40 @@ + +#################### +# UNIT TESTS +#################### + +set(unittest-sources + ../features/netsocket/SocketAddress.cpp + ../features/netsocket/NetworkStack.cpp + ../features/netsocket/InternetSocket.cpp + ../features/netsocket/UDPSocket.cpp + ../features/netsocket/DTLSSocket.cpp + ../features/netsocket/DTLSSocketWrapper.cpp + ../features/netsocket/TLSSocketWrapper.cpp + ../features/frameworks/nanostack-libservice/source/libip4string/ip4tos.c + ../features/frameworks/nanostack-libservice/source/libip6string/ip6tos.c + ../features/frameworks/nanostack-libservice/source/libip4string/stoip4.c + ../features/frameworks/nanostack-libservice/source/libip6string/stoip6.c + ../features/frameworks/nanostack-libservice/source/libBits/common_functions.c +) + +set(unittest-test-sources + features/netsocket/DTLSSocket/test_DTLSSocket.cpp + stubs/Mutex_stub.cpp + stubs/mbed_assert_stub.c + stubs/equeue_stub.c + ../features/nanostack/coap-service/test/coap-service/unittest/stub/mbedtls_stub.c + stubs/EventQueue_stub.cpp + stubs/mbed_shared_queues_stub.cpp + stubs/nsapi_dns_stub.cpp + stubs/EventFlags_stub.cpp + stubs/stoip4_stub.c + stubs/ip4tos_stub.c + stubs/Kernel_stub.cpp +) + +set(MBEDTLS_USER_CONFIG_FILE_PATH "\"../UNITTESTS/features/netsocket/DTLSSocket/dtls_test_config.h\"") +set_source_files_properties(features/netsocket/DTLSSocket/test_DTLSSocket.cpp PROPERTIES COMPILE_DEFINITIONS MBEDTLS_USER_CONFIG_FILE=${MBEDTLS_USER_CONFIG_FILE_PATH}) +set_source_files_properties(../features/netsocket/DTLSSocket.cpp PROPERTIES COMPILE_DEFINITIONS MBEDTLS_USER_CONFIG_FILE=${MBEDTLS_USER_CONFIG_FILE_PATH}) +set_source_files_properties(../features/netsocket/DTLSSocketWrapper.cpp PROPERTIES COMPILE_DEFINITIONS MBEDTLS_USER_CONFIG_FILE=${MBEDTLS_USER_CONFIG_FILE_PATH}) + diff --git a/UNITTESTS/features/netsocket/DTLSSocketWrapper/dtls_test_config.h b/UNITTESTS/features/netsocket/DTLSSocketWrapper/dtls_test_config.h new file mode 100644 index 00000000000..ab0c902f6f1 --- /dev/null +++ b/UNITTESTS/features/netsocket/DTLSSocketWrapper/dtls_test_config.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2018, Arm Limited and affiliates + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 UNITTESTS_FEATURES_NETSOCKET_DTLSSOCKETWRAPPER_TLS_TEST_CONFIG_H_ +#define UNITTESTS_FEATURES_NETSOCKET_DTLSSOCKETWRAPPER_TLS_TEST_CONFIG_H_ + +#define MBEDTLS_SSL_CLI_C + + +#endif /* UNITTESTS_FEATURES_NETSOCKET_DTLSSOCKETWRAPPER_TLS_TEST_CONFIG_H_ */ diff --git a/UNITTESTS/features/netsocket/DTLSSocketWrapper/test_DTLSSocketWrapper.cpp b/UNITTESTS/features/netsocket/DTLSSocketWrapper/test_DTLSSocketWrapper.cpp new file mode 100644 index 00000000000..00c250c268b --- /dev/null +++ b/UNITTESTS/features/netsocket/DTLSSocketWrapper/test_DTLSSocketWrapper.cpp @@ -0,0 +1,406 @@ +/* + * Copyright (c) 2018, Arm Limited and affiliates + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "gtest/gtest.h" +#include "features/netsocket/UDPSocket.h" +#include "features/netsocket/DTLSSocketWrapper.h" +#include "NetworkStack_stub.h" +#include "features/nanostack/coap-service/test/coap-service/unittest/stub/mbedtls_stub.h" +#include //memset + +#include "mbed_error.h" +mbed_error_status_t mbed_error(mbed_error_status_t error_status, const char *error_msg, unsigned int error_value, const char *filename, int line_number) +{ + return 0; +} + +// Control the rtos EventFlags stub. See EventFlags_stub.cpp +extern std::list eventFlagsStubNextRetval; + +class TestDTLSSocketWrapper : public testing::Test { +public: + unsigned int dataSize = 10; + char dataBuf[10]; +protected: + UDPSocket *transport; + DTLSSocketWrapper *wrapper; + NetworkStackstub stack; + + virtual void SetUp() + { + memset(mbedtls_stub.retArray, 0, sizeof(mbedtls_stub.retArray)); + mbedtls_stub.useCounter = false; + mbedtls_stub.counter = 0; + mbedtls_stub.crt_expected_int = 0; + mbedtls_stub.expected_int = 0; + transport = new UDPSocket(); + wrapper = new DTLSSocketWrapper(transport); + } + + virtual void TearDown() + { + mbedtls_stub.useCounter = false; + stack.return_values.clear(); + stack.return_socketAddress = SocketAddress(); + eventFlagsStubNextRetval.clear(); + delete wrapper; + } + + char *cert = "-----BEGIN CERTIFICATE-----\ + MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/\ + MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT\ + DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow\ + SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT\ + GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC\ + AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF\ + q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8\ + SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0\ + Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA\ + a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj\ + /PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T\ + AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG\ + CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv\ + bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k\ + c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw\ + VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC\ + ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz\ + MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu\ + Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF\ + AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo\ + uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/\ + wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu\ + X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG\ + PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6\ + KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==\ + -----END CERTIFICATE-----"; +}; + +static bool callback_is_called; +static void my_callback() +{ + callback_is_called = true; +} + +TEST_F(TestDTLSSocketWrapper, constructor) +{ + EXPECT_TRUE(wrapper); +} + +TEST_F(TestDTLSSocketWrapper, constructor_hostname) +{ + DTLSSocketWrapper *wrapper2 = new DTLSSocketWrapper(transport, "localhost"); +} + +/* connect */ + +TEST_F(TestDTLSSocketWrapper, connect) +{ + transport->open((NetworkStack *)&stack); + const SocketAddress a("127.0.0.1", 1024); + stack.return_socketAddress = a; + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK); + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_IS_CONNECTED); +} + +TEST_F(TestDTLSSocketWrapper, connect_no_open) +{ + stack.return_value = NSAPI_ERROR_OK; + const SocketAddress a("127.0.0.1", 1024); + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK); //UDP doesn't mind. +} + +/* connect: SSL-related errors */ + +TEST_F(TestDTLSSocketWrapper, connect_handshake_fail_ssl_handshake) +{ + transport->open((NetworkStack *)&stack); + mbedtls_stub.useCounter = true; + mbedtls_stub.retArray[1] = -1; // mbedtls_ssl_handshake error + const SocketAddress a("127.0.0.1", 1024); + stack.return_socketAddress = a; + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_AUTH_FAILURE); +} + +TEST_F(TestDTLSSocketWrapper, connect_handshake_fail_ssl_handshake_in_progress) +{ + EXPECT_EQ(transport->open((NetworkStack *)&stack), NSAPI_ERROR_OK); + mbedtls_stub.useCounter = true; + wrapper->set_timeout(1); + eventFlagsStubNextRetval.push_back(osFlagsError); // Break the wait loop + mbedtls_stub.retArray[1] = MBEDTLS_ERR_SSL_WANT_READ; // mbedtls_ssl_handshake error + const SocketAddress a("127.0.0.1", 1024); + stack.return_socketAddress = a; + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_IN_PROGRESS); +} + +TEST_F(TestDTLSSocketWrapper, connect_handshake_fail_ssl_get_verify_result) +{ + transport->open((NetworkStack *)&stack); + mbedtls_stub.uint32_value = 1; // mbedtls_ssl_get_verify_result error + const SocketAddress a("127.0.0.1", 1024); + stack.return_socketAddress = a; + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK); +} + +TEST_F(TestDTLSSocketWrapper, connect_fail_ctr_drbg_seed) +{ + transport->open((NetworkStack *)&stack); + mbedtls_stub.crt_expected_int = 1; // mbedtls_ctr_drbg_seed error + stack.return_value = NSAPI_ERROR_OK; + const SocketAddress a("127.0.0.1", 1024); + stack.return_socketAddress = a; + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_PARAMETER); + mbedtls_stub.crt_expected_int = 0; +} + +TEST_F(TestDTLSSocketWrapper, connect_fail_ssl_setup) +{ + transport->open((NetworkStack *)&stack); + mbedtls_stub.useCounter = true; + mbedtls_stub.retArray[0] = 2; // mbedtls_ssl_setup error + stack.return_value = NSAPI_ERROR_OK; + const SocketAddress a("127.0.0.1", 1024); + stack.return_socketAddress = a; + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_PARAMETER); +} + +/* send */ + +TEST_F(TestDTLSSocketWrapper, send_no_open) +{ + stack.return_value = NSAPI_ERROR_OK; + EXPECT_EQ(wrapper->send(dataBuf, dataSize), NSAPI_ERROR_NO_CONNECTION); +} + +TEST_F(TestDTLSSocketWrapper, send_in_one_chunk) +{ + mbedtls_stub.useCounter = true; + mbedtls_stub.retArray[2] = dataSize; // mbedtls_ssl_write + transport->open((NetworkStack *)&stack); + const SocketAddress a("127.0.0.1", 1024); + stack.return_socketAddress = a; + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK); + EXPECT_EQ(wrapper->send(dataBuf, dataSize), dataSize); +} + +TEST_F(TestDTLSSocketWrapper, send_in_two_chunks) +{ + mbedtls_stub.useCounter = true; + mbedtls_stub.retArray[2] = dataSize; // mbedtls_ssl_write + transport->open((NetworkStack *)&stack); + const SocketAddress a("127.0.0.1", 1024); + stack.return_socketAddress = a; + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK); + EXPECT_EQ(wrapper->send(dataBuf, dataSize), dataSize); +} + +TEST_F(TestDTLSSocketWrapper, send_error_would_block) +{ + transport->open((NetworkStack *)&stack); + mbedtls_stub.useCounter = true; + mbedtls_stub.retArray[2] = MBEDTLS_ERR_SSL_WANT_WRITE; // mbedtls_ssl_write + eventFlagsStubNextRetval.push_back(osFlagsError); // Break the wait loop + const SocketAddress a("127.0.0.1", 1024); + stack.return_socketAddress = a; + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK); + EXPECT_EQ(wrapper->send(dataBuf, dataSize), NSAPI_ERROR_WOULD_BLOCK); +} + +TEST_F(TestDTLSSocketWrapper, send_to) +{ + transport->open((NetworkStack *)&stack); + mbedtls_stub.useCounter = true; + + mbedtls_stub.retArray[2] = dataSize; // mbedtls_ssl_write + const SocketAddress a("127.0.0.1", 1024); + stack.return_socketAddress = a; + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK); + EXPECT_EQ(wrapper->sendto(a, dataBuf, dataSize), dataSize); +} + +/* recv */ + +TEST_F(TestDTLSSocketWrapper, recv_no_open) +{ + stack.return_value = NSAPI_ERROR_OK; + EXPECT_EQ(wrapper->recv(dataBuf, dataSize), NSAPI_ERROR_NO_CONNECTION); +} + +TEST_F(TestDTLSSocketWrapper, recv_all_data) +{ + transport->open((NetworkStack *)&stack); + mbedtls_stub.useCounter = true; + mbedtls_stub.retArray[2] = dataSize; // mbedtls_ssl_write + const SocketAddress a("127.0.0.1", 1024); + stack.return_socketAddress = a; + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK); + EXPECT_EQ(wrapper->recv(dataBuf, dataSize), dataSize); +} + +TEST_F(TestDTLSSocketWrapper, recv_less_than_expected) +{ + transport->open((NetworkStack *)&stack); + unsigned int lessThanDataSize = dataSize - 1; + mbedtls_stub.useCounter = true; + mbedtls_stub.retArray[2] = lessThanDataSize; // mbedtls_ssl_write + const SocketAddress a("127.0.0.1", 1024); + stack.return_socketAddress = a; + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK); + EXPECT_EQ(wrapper->recv(dataBuf, dataSize), lessThanDataSize); +} + +TEST_F(TestDTLSSocketWrapper, recv_would_block) +{ + transport->open((NetworkStack *)&stack); + mbedtls_stub.useCounter = true; + mbedtls_stub.retArray[2] = MBEDTLS_ERR_SSL_WANT_WRITE; // mbedtls_ssl_write + const SocketAddress a("127.0.0.1", 1024); + stack.return_socketAddress = a; + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK); + eventFlagsStubNextRetval.push_back(osFlagsError); // Break the wait loop + EXPECT_EQ(wrapper->recv(dataBuf, dataSize), NSAPI_ERROR_WOULD_BLOCK); +} + +TEST_F(TestDTLSSocketWrapper, recv_from_no_socket) +{ + SocketAddress a("127.0.0.1", 1024); + EXPECT_EQ(wrapper->recvfrom(&a, dataBuf, dataSize), NSAPI_ERROR_NO_CONNECTION); +} + +TEST_F(TestDTLSSocketWrapper, recv_from) +{ + SocketAddress a("127.0.0.1", 1024); + EXPECT_EQ(transport->open((NetworkStack *)&stack), NSAPI_ERROR_OK); + stack.return_socketAddress = a; + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK); + SocketAddress b; + EXPECT_EQ(wrapper->recvfrom(&b, dataBuf, dataSize), NSAPI_ERROR_OK); +} + +TEST_F(TestDTLSSocketWrapper, recv_from_null) +{ + SocketAddress a("127.0.0.1", 1024); + EXPECT_EQ(transport->open((NetworkStack *)&stack), NSAPI_ERROR_OK); + stack.return_socketAddress = a; + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK); + EXPECT_EQ(wrapper->recvfrom(NULL, dataBuf, dataSize), NSAPI_ERROR_OK); +} + +/* set_root_ca_cert */ + +TEST_F(TestDTLSSocketWrapper, set_root_ca_cert) +{ + EXPECT_EQ(wrapper->get_ca_chain(), static_cast(NULL)); + EXPECT_EQ(transport->open((NetworkStack *)&stack), NSAPI_ERROR_OK); + EXPECT_EQ(wrapper->set_root_ca_cert(cert, strlen(cert)), NSAPI_ERROR_OK); + EXPECT_NE(wrapper->get_ca_chain(), static_cast(NULL)); +} + +TEST_F(TestDTLSSocketWrapper, set_root_ca_cert_nolen) +{ + EXPECT_EQ(transport->open((NetworkStack *)&stack), NSAPI_ERROR_OK); + EXPECT_EQ(wrapper->set_root_ca_cert(cert), NSAPI_ERROR_OK); +} + +TEST_F(TestDTLSSocketWrapper, set_root_ca_cert_invalid) +{ + EXPECT_EQ(transport->open((NetworkStack *)&stack), NSAPI_ERROR_OK); + mbedtls_stub.useCounter = true; + mbedtls_stub.counter = 0; + mbedtls_stub.retArray[0] = 1; // mbedtls_x509_crt_parse error + EXPECT_EQ(wrapper->set_root_ca_cert(cert, strlen(cert)), NSAPI_ERROR_PARAMETER); +} + +TEST_F(TestDTLSSocketWrapper, set_client_cert_key) +{ + EXPECT_EQ(wrapper->get_own_cert(), static_cast(NULL)); + EXPECT_EQ(transport->open((NetworkStack *)&stack), NSAPI_ERROR_OK); + EXPECT_EQ(wrapper->set_client_cert_key(cert, cert), NSAPI_ERROR_OK); + EXPECT_NE(wrapper->get_own_cert(), static_cast(NULL)); +} + +TEST_F(TestDTLSSocketWrapper, set_client_cert_key_invalid) +{ + EXPECT_EQ(transport->open((NetworkStack *)&stack), NSAPI_ERROR_OK); + mbedtls_stub.useCounter = true; + mbedtls_stub.retArray[0] = 1; // mbedtls_x509_crt_parse error + EXPECT_EQ(wrapper->set_client_cert_key(cert, cert), NSAPI_ERROR_PARAMETER); +} + +TEST_F(TestDTLSSocketWrapper, set_client_cert_key_invalid_pem) +{ + EXPECT_EQ(transport->open((NetworkStack *)&stack), NSAPI_ERROR_OK); + mbedtls_stub.useCounter = true; + mbedtls_stub.retArray[0] = 0; // mbedtls_x509_crt_parse ok + mbedtls_stub.retArray[1] = 1; // mbedtls_pk_parse_key error + EXPECT_EQ(wrapper->set_client_cert_key(cert, cert), NSAPI_ERROR_PARAMETER); +} + +TEST_F(TestDTLSSocketWrapper, bind) +{ + transport->open((NetworkStack *)&stack); + SocketAddress a("127.0.0.1", 1024); + EXPECT_EQ(wrapper->bind(a), NSAPI_ERROR_OK); +} + +TEST_F(TestDTLSSocketWrapper, bind_no_open) +{ + SocketAddress a("127.0.0.1", 1024); + EXPECT_EQ(wrapper->bind(a), NSAPI_ERROR_NO_SOCKET); +} + +TEST_F(TestDTLSSocketWrapper, sigio) +{ + transport->open((NetworkStack *)&stack); + callback_is_called = false; + wrapper->sigio(mbed::callback(my_callback)); + SocketAddress a("127.0.0.1", 1024); + wrapper->close(); //trigger events. + EXPECT_EQ(callback_is_called, true); +} + +TEST_F(TestDTLSSocketWrapper, setsockopt) +{ + transport->open((NetworkStack *)&stack); + EXPECT_EQ(wrapper->setsockopt(0, 0, 0, 0), NSAPI_ERROR_UNSUPPORTED); +} + +TEST_F(TestDTLSSocketWrapper, getsockopt_no_stack) +{ + EXPECT_EQ(wrapper->getsockopt(0, 0, 0, 0), NSAPI_ERROR_NO_SOCKET); +} + +TEST_F(TestDTLSSocketWrapper, getsockopt) +{ + transport->open((NetworkStack *)&stack); + EXPECT_EQ(wrapper->getsockopt(0, 0, 0, 0), NSAPI_ERROR_UNSUPPORTED); +} + +/* unsupported */ + +TEST_F(TestDTLSSocketWrapper, listen_unsupported) +{ + EXPECT_EQ(wrapper->listen(1), NSAPI_ERROR_UNSUPPORTED); +} + +TEST_F(TestDTLSSocketWrapper, accept_unsupported) +{ + nsapi_error_t error; + EXPECT_EQ(wrapper->accept(&error), static_cast(NULL)); + EXPECT_EQ(error, NSAPI_ERROR_UNSUPPORTED); +} + diff --git a/UNITTESTS/features/netsocket/DTLSSocketWrapper/unittest.cmake b/UNITTESTS/features/netsocket/DTLSSocketWrapper/unittest.cmake new file mode 100644 index 00000000000..7e5e68119a1 --- /dev/null +++ b/UNITTESTS/features/netsocket/DTLSSocketWrapper/unittest.cmake @@ -0,0 +1,38 @@ + +#################### +# UNIT TESTS +#################### + +set(unittest-sources + ../features/netsocket/SocketAddress.cpp + ../features/netsocket/NetworkStack.cpp + ../features/netsocket/InternetSocket.cpp + ../features/netsocket/UDPSocket.cpp + ../features/netsocket/DTLSSocketWrapper.cpp + ../features/netsocket/TLSSocketWrapper.cpp + ../features/frameworks/nanostack-libservice/source/libip4string/ip4tos.c + ../features/frameworks/nanostack-libservice/source/libip6string/ip6tos.c + ../features/frameworks/nanostack-libservice/source/libip4string/stoip4.c + ../features/frameworks/nanostack-libservice/source/libip6string/stoip6.c + ../features/frameworks/nanostack-libservice/source/libBits/common_functions.c +) + +set(unittest-test-sources + features/netsocket/DTLSSocketWrapper/test_DTLSSocketWrapper.cpp + stubs/Mutex_stub.cpp + stubs/mbed_assert_stub.c + stubs/equeue_stub.c + ../features/nanostack/coap-service/test/coap-service/unittest/stub/mbedtls_stub.c + stubs/EventQueue_stub.cpp + stubs/mbed_shared_queues_stub.cpp + stubs/nsapi_dns_stub.cpp + stubs/EventFlags_stub.cpp + stubs/stoip4_stub.c + stubs/ip4tos_stub.c + stubs/Kernel_stub.cpp +) + +set(MBEDTLS_USER_CONFIG_FILE_PATH "\"../UNITTESTS/features/netsocket/DTLSSocketWrapper/dtls_test_config.h\"") +set_source_files_properties(features/netsocket/DTLSSocketWrapper/test_DTLSSocketWrapper.cpp PROPERTIES COMPILE_DEFINITIONS MBEDTLS_USER_CONFIG_FILE=${MBEDTLS_USER_CONFIG_FILE_PATH}) +set_source_files_properties(../features/netsocket/DTLSSocketWrapper.cpp PROPERTIES COMPILE_DEFINITIONS MBEDTLS_USER_CONFIG_FILE=${MBEDTLS_USER_CONFIG_FILE_PATH}) + diff --git a/UNITTESTS/features/netsocket/TCPSocket/test_TCPSocket.cpp b/UNITTESTS/features/netsocket/TCPSocket/test_TCPSocket.cpp index abd7cc41eb3..6dcd1999abc 100644 --- a/UNITTESTS/features/netsocket/TCPSocket/test_TCPSocket.cpp +++ b/UNITTESTS/features/netsocket/TCPSocket/test_TCPSocket.cpp @@ -62,7 +62,8 @@ TEST_F(TestTCPSocket, constructor) TEST_F(TestTCPSocket, constructor_parameters) { - TCPSocket socketParam = TCPSocket(dynamic_cast(&stack)); + TCPSocket socketParam = TCPSocket(); + socketParam.open(dynamic_cast(&stack)); const SocketAddress a("127.0.0.1", 1024); EXPECT_EQ(socketParam.connect(a), NSAPI_ERROR_OK); } diff --git a/UNITTESTS/features/netsocket/TLSSocket/test_TLSSocket.cpp b/UNITTESTS/features/netsocket/TLSSocket/test_TLSSocket.cpp new file mode 100644 index 00000000000..0d278125fa5 --- /dev/null +++ b/UNITTESTS/features/netsocket/TLSSocket/test_TLSSocket.cpp @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, Arm Limited and affiliates + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "gtest/gtest.h" +#include "features/netsocket/TLSSocket.h" +#include "NetworkStack_stub.h" + +#include "mbed_error.h" +mbed_error_status_t mbed_error(mbed_error_status_t error_status, const char *error_msg, unsigned int error_value, const char *filename, int line_number) +{ + return 0; +} + +// Control the rtos EventFlags stub. See EventFlags_stub.cpp +extern std::list eventFlagsStubNextRetval; + +class TestTLSSocket : public testing::Test { +public: + unsigned int dataSize = 10; + char dataBuf[10]; +protected: + TLSSocket *socket; + NetworkStackstub stack; + + virtual void SetUp() + { + socket = new TLSSocket(); + } + + virtual void TearDown() + { + stack.return_values.clear(); + eventFlagsStubNextRetval.clear(); + delete socket; + } +}; + +TEST_F(TestTLSSocket, constructor) +{ + EXPECT_TRUE(socket); +} + +/* connect */ + +TEST_F(TestTLSSocket, connect) +{ + socket->open((NetworkStack *)&stack); + + stack.return_value = NSAPI_ERROR_OK; + EXPECT_EQ(socket->connect("127.0.0.1", 1024), NSAPI_ERROR_OK); +} + +TEST_F(TestTLSSocket, connect_no_open) +{ + stack.return_value = NSAPI_ERROR_OK; + EXPECT_EQ(socket->connect("127.0.0.1", 1024), NSAPI_ERROR_NO_SOCKET); +} diff --git a/UNITTESTS/features/netsocket/TLSSocket/tls_test_config.h b/UNITTESTS/features/netsocket/TLSSocket/tls_test_config.h new file mode 100644 index 00000000000..35a88ad7719 --- /dev/null +++ b/UNITTESTS/features/netsocket/TLSSocket/tls_test_config.h @@ -0,0 +1,11 @@ +/* + * tls_test_config.h + */ + +#ifndef UNITTESTS_FEATURES_NETSOCKET_TLSSOCKET_TLS_TEST_CONFIG_H_ +#define UNITTESTS_FEATURES_NETSOCKET_TLSSOCKET_TLS_TEST_CONFIG_H_ + +#define MBEDTLS_SSL_CLI_C + + +#endif /* UNITTESTS_FEATURES_NETSOCKET_TLSSOCKET_TLS_TEST_CONFIG_H_ */ diff --git a/UNITTESTS/features/netsocket/TLSSocket/unittest.cmake b/UNITTESTS/features/netsocket/TLSSocket/unittest.cmake new file mode 100644 index 00000000000..d6ccdc59e18 --- /dev/null +++ b/UNITTESTS/features/netsocket/TLSSocket/unittest.cmake @@ -0,0 +1,38 @@ + +#################### +# UNIT TESTS +#################### + +set(unittest-sources + ../features/netsocket/SocketAddress.cpp + ../features/netsocket/NetworkStack.cpp + ../features/netsocket/InternetSocket.cpp + ../features/netsocket/TCPSocket.cpp + ../features/netsocket/TLSSocket.cpp + ../features/netsocket/TLSSocketWrapper.cpp + ../features/frameworks/nanostack-libservice/source/libip4string/ip4tos.c + ../features/frameworks/nanostack-libservice/source/libip6string/ip6tos.c + ../features/frameworks/nanostack-libservice/source/libip4string/stoip4.c + ../features/frameworks/nanostack-libservice/source/libip6string/stoip6.c + ../features/frameworks/nanostack-libservice/source/libBits/common_functions.c +) + +set(unittest-test-sources + features/netsocket/TLSSocket/test_TLSSocket.cpp + stubs/Mutex_stub.cpp + stubs/mbed_assert_stub.c + stubs/equeue_stub.c + ../features/nanostack/coap-service/test/coap-service/unittest/stub/mbedtls_stub.c + stubs/EventQueue_stub.cpp + stubs/mbed_shared_queues_stub.cpp + stubs/nsapi_dns_stub.cpp + stubs/EventFlags_stub.cpp + stubs/stoip4_stub.c + stubs/ip4tos_stub.c +) + +set(MBEDTLS_USER_CONFIG_FILE_PATH "\"../UNITTESTS/features/netsocket/TLSSocket/tls_test_config.h\"") +set_source_files_properties(features/netsocket/TLSSocket/test_TLSSocket.cpp PROPERTIES COMPILE_DEFINITIONS MBEDTLS_USER_CONFIG_FILE=${MBEDTLS_USER_CONFIG_FILE_PATH}) +set_source_files_properties(../features/netsocket/TLSSocket.cpp PROPERTIES COMPILE_DEFINITIONS MBEDTLS_USER_CONFIG_FILE=${MBEDTLS_USER_CONFIG_FILE_PATH}) +set_source_files_properties(../features/netsocket/TLSSocketWrapper.cpp PROPERTIES COMPILE_DEFINITIONS MBEDTLS_USER_CONFIG_FILE=${MBEDTLS_USER_CONFIG_FILE_PATH}) + diff --git a/UNITTESTS/features/netsocket/TLSSocketWrapper/test_TLSSocketWrapper.cpp b/UNITTESTS/features/netsocket/TLSSocketWrapper/test_TLSSocketWrapper.cpp new file mode 100644 index 00000000000..98ff4b88fb4 --- /dev/null +++ b/UNITTESTS/features/netsocket/TLSSocketWrapper/test_TLSSocketWrapper.cpp @@ -0,0 +1,420 @@ +/* + * Copyright (c) 2018, Arm Limited and affiliates + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "gtest/gtest.h" +#include "features/netsocket/TCPSocket.h" +#include "features/netsocket/TLSSocketWrapper.h" +#include "NetworkStack_stub.h" +#include "features/nanostack/coap-service/test/coap-service/unittest/stub/mbedtls_stub.h" +#include //memset + +#include "mbed_error.h" +mbed_error_status_t mbed_error(mbed_error_status_t error_status, const char *error_msg, unsigned int error_value, const char *filename, int line_number) +{ + return 0; +} + +// Control the rtos EventFlags stub. See EventFlags_stub.cpp +extern std::list eventFlagsStubNextRetval; + +class TestTLSSocketWrapper : public testing::Test { +public: + unsigned int dataSize = 10; + char dataBuf[10]; +protected: + TCPSocket *transport; + TLSSocketWrapper *wrapper; + NetworkStackstub stack; + + virtual void SetUp() + { + memset(mbedtls_stub.retArray, 0, sizeof(mbedtls_stub.retArray)); + mbedtls_stub.useCounter = false; + mbedtls_stub.counter = 0; + mbedtls_stub.crt_expected_int = 0; + mbedtls_stub.expected_int = 0; + transport = new TCPSocket(); + wrapper = new TLSSocketWrapper(transport); + } + + virtual void TearDown() + { + stack.return_values.clear(); + eventFlagsStubNextRetval.clear(); + delete wrapper; + } + + char *cert = "-----BEGIN CERTIFICATE-----\ + MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/\ + MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT\ + DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow\ + SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT\ + GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC\ + AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF\ + q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8\ + SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0\ + Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA\ + a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj\ + /PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T\ + AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG\ + CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv\ + bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k\ + c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw\ + VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC\ + ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz\ + MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu\ + Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF\ + AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo\ + uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/\ + wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu\ + X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG\ + PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6\ + KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==\ + -----END CERTIFICATE-----"; +}; + +static bool callback_is_called; +static void my_callback() +{ + callback_is_called = true; +} + +TEST_F(TestTLSSocketWrapper, constructor) +{ + EXPECT_TRUE(wrapper); +} + +TEST_F(TestTLSSocketWrapper, constructor_hostname) +{ + TLSSocketWrapper *wrapper2 = new TLSSocketWrapper(transport, "localhost"); +} + +/* connect */ + +TEST_F(TestTLSSocketWrapper, connect) +{ + transport->open((NetworkStack *)&stack); + const SocketAddress a("127.0.0.1", 1024); + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK); + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_IS_CONNECTED); +} + +/* connect: TCP-related errors */ + +TEST_F(TestTLSSocketWrapper, connect_no_open) +{ + stack.return_value = NSAPI_ERROR_OK; + const SocketAddress a("127.0.0.1", 1024); + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_NO_SOCKET); +} + +TEST_F(TestTLSSocketWrapper, connect_error_in_progress_no_timeout) +{ + transport->open((NetworkStack *)&stack); + stack.return_value = NSAPI_ERROR_IN_PROGRESS; + const SocketAddress a("127.0.0.1", 1024); + eventFlagsStubNextRetval.push_back(osFlagsError); // Break the wait loop + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_IN_PROGRESS); +} + +TEST_F(TestTLSSocketWrapper, connect_with_timeout) +{ + transport->open((NetworkStack *)&stack); + stack.return_value = NSAPI_ERROR_IN_PROGRESS; + const SocketAddress a("127.0.0.1", 1024); + eventFlagsStubNextRetval.push_back(osFlagsError); // Break the wait loop + wrapper->set_blocking(true); + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_IN_PROGRESS); +} + +TEST_F(TestTLSSocketWrapper, connect_error_is_connected) +{ + transport->open((NetworkStack *)&stack); + const SocketAddress a("127.0.0.1", 1024); + wrapper->set_timeout(1); + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK); + mbedtls_stub.useCounter = true; + mbedtls_stub.retArray[0] = 1; // mbedtls_ctr_drbg_seed error +} + +/* connect: SSL-related errors */ + +TEST_F(TestTLSSocketWrapper, connect_fail_ctr_drbg_seed) +{ + transport->open((NetworkStack *)&stack); + mbedtls_stub.crt_expected_int = 1; // mbedtls_ctr_drbg_seed error + stack.return_value = NSAPI_ERROR_OK; + const SocketAddress a("127.0.0.1", 1024); + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_PARAMETER); + mbedtls_stub.crt_expected_int = 0; +} + +TEST_F(TestTLSSocketWrapper, connect_fail_ssl_setup) +{ + transport->open((NetworkStack *)&stack); + mbedtls_stub.useCounter = true; + mbedtls_stub.retArray[0] = 0; // mbedtls_ssl_config_defaults ok + mbedtls_stub.retArray[1] = 2; // mbedtls_ssl_setup error + stack.return_value = NSAPI_ERROR_OK; + const SocketAddress a("127.0.0.1", 1024); + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_PARAMETER); +} + +TEST_F(TestTLSSocketWrapper, connect_handshake_fail_ssl_handshake) +{ + transport->open((NetworkStack *)&stack); + mbedtls_stub.useCounter = true; + mbedtls_stub.retArray[2] = -1; // mbedtls_ssl_handshake error + const SocketAddress a("127.0.0.1", 1024); + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_AUTH_FAILURE); +} + +TEST_F(TestTLSSocketWrapper, connect_handshake_fail_ssl_handshake_in_progress) +{ + transport->open((NetworkStack *)&stack); + mbedtls_stub.useCounter = true; + wrapper->set_timeout(1); + eventFlagsStubNextRetval.push_back(osFlagsError); // Break the wait loop + mbedtls_stub.retArray[2] = MBEDTLS_ERR_SSL_WANT_READ; // mbedtls_ssl_handshake error + const SocketAddress a("127.0.0.1", 1024); + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_IN_PROGRESS); +} + +TEST_F(TestTLSSocketWrapper, connect_handshake_fail_ssl_get_verify_result) +{ + transport->open((NetworkStack *)&stack); + mbedtls_stub.uint32_value = 1; // mbedtls_ssl_get_verify_result error + const SocketAddress a("127.0.0.1", 1024); + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK); +} + +/* send */ + +TEST_F(TestTLSSocketWrapper, send_no_open) +{ + stack.return_value = NSAPI_ERROR_OK; + EXPECT_EQ(wrapper->send(dataBuf, dataSize), NSAPI_ERROR_NO_CONNECTION); +} + +TEST_F(TestTLSSocketWrapper, send_in_one_chunk) +{ + mbedtls_stub.useCounter = true; + mbedtls_stub.retArray[3] = dataSize; // mbedtls_ssl_write + transport->open((NetworkStack *)&stack); + const SocketAddress a("127.0.0.1", 1024); + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK); + EXPECT_EQ(wrapper->send(dataBuf, dataSize), dataSize); +} + +TEST_F(TestTLSSocketWrapper, send_in_two_chunks) +{ + mbedtls_stub.useCounter = true; + mbedtls_stub.retArray[3] = dataSize; // mbedtls_ssl_write + transport->open((NetworkStack *)&stack); + const SocketAddress a("127.0.0.1", 1024); + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK); + EXPECT_EQ(wrapper->send(dataBuf, dataSize), dataSize); +} + +TEST_F(TestTLSSocketWrapper, send_error_would_block) +{ + transport->open((NetworkStack *)&stack); + mbedtls_stub.useCounter = true; + mbedtls_stub.retArray[3] = MBEDTLS_ERR_SSL_WANT_WRITE; // mbedtls_ssl_write + eventFlagsStubNextRetval.push_back(osFlagsError); // Break the wait loop + const SocketAddress a("127.0.0.1", 1024); + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK); + EXPECT_EQ(wrapper->send(dataBuf, dataSize), NSAPI_ERROR_WOULD_BLOCK); +} + +TEST_F(TestTLSSocketWrapper, send_to) +{ + transport->open((NetworkStack *)&stack); + mbedtls_stub.useCounter = true; + + mbedtls_stub.retArray[3] = dataSize; // mbedtls_ssl_write + const SocketAddress a("127.0.0.1", 1024); + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK); + EXPECT_EQ(wrapper->sendto(a, dataBuf, dataSize), dataSize); +} + +/* recv */ + +TEST_F(TestTLSSocketWrapper, recv_no_open) +{ + stack.return_value = NSAPI_ERROR_OK; + EXPECT_EQ(wrapper->recv(dataBuf, dataSize), NSAPI_ERROR_NO_CONNECTION); +} + +TEST_F(TestTLSSocketWrapper, recv_all_data) +{ + transport->open((NetworkStack *)&stack); + mbedtls_stub.useCounter = true; + mbedtls_stub.retArray[3] = dataSize; // mbedtls_ssl_write + const SocketAddress a("127.0.0.1", 1024); + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK); + EXPECT_EQ(wrapper->recv(dataBuf, dataSize), dataSize); +} + +TEST_F(TestTLSSocketWrapper, recv_less_than_expected) +{ + transport->open((NetworkStack *)&stack); + unsigned int lessThanDataSize = dataSize - 1; + mbedtls_stub.useCounter = true; + mbedtls_stub.retArray[3] = lessThanDataSize; // mbedtls_ssl_write + const SocketAddress a("127.0.0.1", 1024); + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK); + EXPECT_EQ(wrapper->recv(dataBuf, dataSize), lessThanDataSize); +} + +TEST_F(TestTLSSocketWrapper, recv_would_block) +{ + transport->open((NetworkStack *)&stack); + mbedtls_stub.useCounter = true; + mbedtls_stub.retArray[3] = MBEDTLS_ERR_SSL_WANT_WRITE; // mbedtls_ssl_write + const SocketAddress a("127.0.0.1", 1024); + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK); + eventFlagsStubNextRetval.push_back(osFlagsError); // Break the wait loop + EXPECT_EQ(wrapper->recv(dataBuf, dataSize), NSAPI_ERROR_WOULD_BLOCK); +} + +TEST_F(TestTLSSocketWrapper, recv_from_no_socket) +{ + SocketAddress a("127.0.0.1", 1024); + EXPECT_EQ(wrapper->recvfrom(&a, dataBuf, dataSize), NSAPI_ERROR_NO_CONNECTION); +} + +TEST_F(TestTLSSocketWrapper, recv_from) +{ + SocketAddress a("127.0.0.1", 1024); + EXPECT_EQ(transport->open((NetworkStack *)&stack), NSAPI_ERROR_OK); + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK); + SocketAddress b; + EXPECT_EQ(wrapper->recvfrom(&b, dataBuf, dataSize), NSAPI_ERROR_OK); +} + +TEST_F(TestTLSSocketWrapper, recv_from_null) +{ + SocketAddress a("127.0.0.1", 1024); + EXPECT_EQ(transport->open((NetworkStack *)&stack), NSAPI_ERROR_OK); + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK); + EXPECT_EQ(wrapper->recvfrom(NULL, dataBuf, dataSize), NSAPI_ERROR_OK); +} + +/* set_root_ca_cert */ + +TEST_F(TestTLSSocketWrapper, set_root_ca_cert) +{ + EXPECT_EQ(wrapper->get_ca_chain(), static_cast(NULL)); + EXPECT_EQ(transport->open((NetworkStack *)&stack), NSAPI_ERROR_OK); + EXPECT_EQ(wrapper->set_root_ca_cert(cert, strlen(cert)), NSAPI_ERROR_OK); + EXPECT_NE(wrapper->get_ca_chain(), static_cast(NULL)); +} + +TEST_F(TestTLSSocketWrapper, set_root_ca_cert_nolen) +{ + EXPECT_EQ(transport->open((NetworkStack *)&stack), NSAPI_ERROR_OK); + EXPECT_EQ(wrapper->set_root_ca_cert(cert), NSAPI_ERROR_OK); +} + +TEST_F(TestTLSSocketWrapper, set_root_ca_cert_invalid) +{ + EXPECT_EQ(transport->open((NetworkStack *)&stack), NSAPI_ERROR_OK); + mbedtls_stub.useCounter = true; + mbedtls_stub.retArray[0] = 1; // mbedtls_x509_crt_parse error + EXPECT_EQ(wrapper->set_root_ca_cert(cert, strlen(cert)), NSAPI_ERROR_PARAMETER); +} + +TEST_F(TestTLSSocketWrapper, set_client_cert_key) +{ + EXPECT_EQ(wrapper->get_own_cert(), static_cast(NULL)); + EXPECT_EQ(transport->open((NetworkStack *)&stack), NSAPI_ERROR_OK); + EXPECT_EQ(wrapper->set_client_cert_key(cert, cert), NSAPI_ERROR_OK); + EXPECT_NE(wrapper->get_own_cert(), static_cast(NULL)); +} + +TEST_F(TestTLSSocketWrapper, set_client_cert_key_invalid) +{ + EXPECT_EQ(transport->open((NetworkStack *)&stack), NSAPI_ERROR_OK); + mbedtls_stub.useCounter = true; + mbedtls_stub.retArray[0] = 1; // mbedtls_x509_crt_parse error + EXPECT_EQ(wrapper->set_client_cert_key(cert, cert), NSAPI_ERROR_PARAMETER); +} + +TEST_F(TestTLSSocketWrapper, set_client_cert_key_invalid_pem) +{ + EXPECT_EQ(transport->open((NetworkStack *)&stack), NSAPI_ERROR_OK); + mbedtls_stub.useCounter = true; + mbedtls_stub.retArray[0] = 0; // mbedtls_x509_crt_parse ok + mbedtls_stub.retArray[1] = 1; // mbedtls_pk_parse_key error + EXPECT_EQ(wrapper->set_client_cert_key(cert, cert), NSAPI_ERROR_PARAMETER); +} + +TEST_F(TestTLSSocketWrapper, bind) +{ + transport->open((NetworkStack *)&stack); + SocketAddress a("127.0.0.1", 1024); + EXPECT_EQ(wrapper->bind(a), NSAPI_ERROR_OK); +} + +TEST_F(TestTLSSocketWrapper, bind_no_open) +{ + SocketAddress a("127.0.0.1", 1024); + EXPECT_EQ(wrapper->bind(a), NSAPI_ERROR_NO_SOCKET); +} + +TEST_F(TestTLSSocketWrapper, sigio) +{ + transport->open((NetworkStack *)&stack); + callback_is_called = false; + wrapper->sigio(mbed::callback(my_callback)); + SocketAddress a("127.0.0.1", 1024); + wrapper->close(); //trigger events. + EXPECT_EQ(callback_is_called, true); +} + +TEST_F(TestTLSSocketWrapper, setsockopt) +{ + transport->open((NetworkStack *)&stack); + EXPECT_EQ(wrapper->setsockopt(0, 0, 0, 0), NSAPI_ERROR_UNSUPPORTED); +} + +TEST_F(TestTLSSocketWrapper, getsockopt_no_stack) +{ + EXPECT_EQ(wrapper->getsockopt(0, 0, 0, 0), NSAPI_ERROR_NO_SOCKET); +} + +TEST_F(TestTLSSocketWrapper, getsockopt) +{ + transport->open((NetworkStack *)&stack); + EXPECT_EQ(wrapper->getsockopt(0, 0, 0, 0), NSAPI_ERROR_UNSUPPORTED); +} + +/* unsupported */ + +TEST_F(TestTLSSocketWrapper, listen_unsupported) +{ + EXPECT_EQ(wrapper->listen(1), NSAPI_ERROR_UNSUPPORTED); +} + +TEST_F(TestTLSSocketWrapper, accept_unsupported) +{ + nsapi_error_t error; + EXPECT_EQ(wrapper->accept(&error), static_cast(NULL)); + EXPECT_EQ(error, NSAPI_ERROR_UNSUPPORTED); +} + diff --git a/UNITTESTS/features/netsocket/TLSSocketWrapper/tls_test_config.h b/UNITTESTS/features/netsocket/TLSSocketWrapper/tls_test_config.h new file mode 100644 index 00000000000..35a88ad7719 --- /dev/null +++ b/UNITTESTS/features/netsocket/TLSSocketWrapper/tls_test_config.h @@ -0,0 +1,11 @@ +/* + * tls_test_config.h + */ + +#ifndef UNITTESTS_FEATURES_NETSOCKET_TLSSOCKET_TLS_TEST_CONFIG_H_ +#define UNITTESTS_FEATURES_NETSOCKET_TLSSOCKET_TLS_TEST_CONFIG_H_ + +#define MBEDTLS_SSL_CLI_C + + +#endif /* UNITTESTS_FEATURES_NETSOCKET_TLSSOCKET_TLS_TEST_CONFIG_H_ */ diff --git a/UNITTESTS/features/netsocket/TLSSocketWrapper/unittest.cmake b/UNITTESTS/features/netsocket/TLSSocketWrapper/unittest.cmake new file mode 100644 index 00000000000..4676f1f9aca --- /dev/null +++ b/UNITTESTS/features/netsocket/TLSSocketWrapper/unittest.cmake @@ -0,0 +1,36 @@ + +#################### +# UNIT TESTS +#################### + +set(unittest-sources + ../features/netsocket/SocketAddress.cpp + ../features/netsocket/NetworkStack.cpp + ../features/netsocket/InternetSocket.cpp + ../features/netsocket/TCPSocket.cpp + ../features/netsocket/TLSSocketWrapper.cpp + ../features/frameworks/nanostack-libservice/source/libip4string/ip4tos.c + ../features/frameworks/nanostack-libservice/source/libip6string/ip6tos.c + ../features/frameworks/nanostack-libservice/source/libip4string/stoip4.c + ../features/frameworks/nanostack-libservice/source/libip6string/stoip6.c + ../features/frameworks/nanostack-libservice/source/libBits/common_functions.c +) + +set(unittest-test-sources + features/netsocket/TLSSocketWrapper/test_TLSSocketWrapper.cpp + stubs/Mutex_stub.cpp + stubs/mbed_assert_stub.c + stubs/equeue_stub.c + ../features/nanostack/coap-service/test/coap-service/unittest/stub/mbedtls_stub.c + stubs/EventQueue_stub.cpp + stubs/mbed_shared_queues_stub.cpp + stubs/nsapi_dns_stub.cpp + stubs/EventFlags_stub.cpp + stubs/stoip4_stub.c + stubs/ip4tos_stub.c +) + +set(MBEDTLS_USER_CONFIG_FILE_PATH "\"../UNITTESTS/features/netsocket/TLSSocketWrapper/tls_test_config.h\"") +set_source_files_properties(features/netsocket/TLSSocketWrapper/test_TLSSocketWrapper.cpp PROPERTIES COMPILE_DEFINITIONS MBEDTLS_USER_CONFIG_FILE=${MBEDTLS_USER_CONFIG_FILE_PATH}) +set_source_files_properties(../features/netsocket/TLSSocketWrapper.cpp PROPERTIES COMPILE_DEFINITIONS MBEDTLS_USER_CONFIG_FILE=${MBEDTLS_USER_CONFIG_FILE_PATH}) + diff --git a/UNITTESTS/stubs/NetworkStack_stub.h b/UNITTESTS/stubs/NetworkStack_stub.h index cb245ab46d4..7612bd5efd5 100644 --- a/UNITTESTS/stubs/NetworkStack_stub.h +++ b/UNITTESTS/stubs/NetworkStack_stub.h @@ -25,6 +25,7 @@ class NetworkStackstub : public NetworkStack { public: std::list return_values; nsapi_error_t return_value; + SocketAddress return_socketAddress; NetworkStackstub() { @@ -113,6 +114,9 @@ class NetworkStackstub : public NetworkStack { virtual nsapi_size_or_error_t socket_recvfrom(nsapi_socket_t handle, SocketAddress *address, void *buffer, nsapi_size_t size) { + if (return_socketAddress != SocketAddress()) { + *address = return_socketAddress; + } if (!return_values.empty()) { nsapi_error_t ret = return_values.front(); return_values.pop_front(); diff --git a/features/cellular/framework/API/CellularNetwork.h b/features/cellular/framework/API/CellularNetwork.h index c3f3855e041..084e335a88a 100644 --- a/features/cellular/framework/API/CellularNetwork.h +++ b/features/cellular/framework/API/CellularNetwork.h @@ -79,7 +79,8 @@ class CellularNetwork { AttachedEmergencyOnly, RegisteredCSFBNotPreferredHome, RegisteredCSFBNotPreferredRoaming, - AlreadyRegistered = 11 // our our definition when modem says that we are not registered but we have active PDP Context + AlreadyRegistered = 11, // our definition when modem says that we are not registered but we have active PDP Context + RegistrationStatusMax }; /* Network registration type */ @@ -107,7 +108,8 @@ class CellularNetwork { RAT_E_UTRAN, RAT_CATM1, RAT_NB1, - RAT_UNKNOWN + RAT_UNKNOWN, + RAT_MAX = 11 // to reserve string array }; // 3GPP TS 27.007 - 7.3 PLMN selection +COPS @@ -342,7 +344,7 @@ class CellularNetwork { */ virtual bool is_active_context() = 0; - /** Gets current network registration parameters: + /** Gets the latest received registration parameters from the network: * type, status, access technology, cell_id, lac, active_time, periodic_tau. * * @param reg_params see registration_params_t @@ -351,7 +353,7 @@ class CellularNetwork { */ virtual nsapi_error_t get_registration_params(registration_params_t ®_params) = 0; - /** Gets the network registration parameters based on required registration type: + /** Gets the current network registration parameters from the network with type: * status, access technology, cell_id, lac, active_time, periodic_tau. * * @param type see RegistrationType values diff --git a/features/cellular/framework/AT/ATHandler.cpp b/features/cellular/framework/AT/ATHandler.cpp index 840bf5cfff9..2e258363586 100644 --- a/features/cellular/framework/AT/ATHandler.cpp +++ b/features/cellular/framework/AT/ATHandler.cpp @@ -36,6 +36,9 @@ using namespace mbed_cellular_util; // URCs should be handled fast, if you add debug traces within URC processing then you also need to increase this time #define PROCESS_URC_TIME 20 +// Suppress logging of very big packet payloads, maxlen is approximate due to write/read are cached +#define DEBUG_MAXLEN 80 + const char *mbed::OK = "OK\r\n"; const uint8_t OK_LENGTH = 4; const char *mbed::CRLF = "\r\n"; @@ -281,8 +284,8 @@ void ATHandler::process_oob() return; } lock(); - tr_debug("process_oob readable=%d, pos=%u, len=%u", _fileHandle->readable(), _recv_pos, _recv_len); if (_fileHandle->readable() || (_recv_pos < _recv_len)) { + tr_debug("AT OoB readable %d, len %u", _fileHandle->readable(), _recv_len - _recv_pos); _current_scope = NotSet; uint32_t timeout = _at_timeout; _at_timeout = PROCESS_URC_TIME; @@ -302,8 +305,8 @@ void ATHandler::process_oob() } } _at_timeout = timeout; + tr_debug("AT OoB done"); } - tr_debug("process_oob exit"); unlock(); } @@ -355,6 +358,7 @@ bool ATHandler::fill_buffer(bool wait_for_timeout) // Reset buffer when full if (sizeof(_recv_buff) == _recv_len) { tr_error("AT overflow"); + debug_print(_recv_buff, _recv_len); reset_buffer(); } @@ -443,15 +447,22 @@ ssize_t ATHandler::read_bytes(uint8_t *buf, size_t len) return -1; } + bool debug_on = _debug_on; size_t read_len = 0; for (; read_len < len; read_len++) { int c = get_char(); if (c == -1) { set_error(NSAPI_ERROR_DEVICE_ERROR); + _debug_on = debug_on; return -1; } buf[read_len] = c; + if (_debug_on && read_len >= DEBUG_MAXLEN) { + debug_print("..", sizeof("..")); + _debug_on = false; + } } + _debug_on = debug_on; return read_len; } @@ -739,13 +750,13 @@ device_err_t ATHandler::get_last_device_error() const void ATHandler::set_error(nsapi_error_t err) { + if (err != NSAPI_ERROR_OK) { + tr_debug("AT error %d", err); + } if (_last_err == NSAPI_ERROR_OK) { _last_err = err; } - if (_last_err != err) { - tr_warn("AT error code changed from %d to %d!", _last_err, err); - } } int ATHandler::get_3gpp_error() @@ -977,7 +988,7 @@ bool ATHandler::consume_to_stop_tag() return true; } - tr_warn("AT stop tag not found"); + tr_debug("AT stop tag not found"); set_error(NSAPI_ERROR_DEVICE_ERROR); return false; } @@ -1130,20 +1141,31 @@ size_t ATHandler::write(const void *data, size_t len) fhs.fh = _fileHandle; fhs.events = POLLOUT; size_t write_len = 0; + bool debug_on = _debug_on; for (; write_len < len;) { int count = poll(&fhs, 1, poll_timeout()); if (count <= 0 || !(fhs.revents & POLLOUT)) { set_error(NSAPI_ERROR_DEVICE_ERROR); + _debug_on = debug_on; return 0; } ssize_t ret = _fileHandle->write((uint8_t *)data + write_len, len - write_len); if (ret < 0) { set_error(NSAPI_ERROR_DEVICE_ERROR); + _debug_on = debug_on; return 0; } - debug_print((char *)data + write_len, ret); + if (_debug_on && write_len < DEBUG_MAXLEN) { + if (write_len + ret < DEBUG_MAXLEN) { + debug_print((char *)data + write_len, ret); + } else { + debug_print("..", sizeof("..")); + _debug_on = false; + } + } write_len += (size_t)ret; } + _debug_on = debug_on; return write_len; } @@ -1175,13 +1197,14 @@ bool ATHandler::check_cmd_send() void ATHandler::flush() { + tr_debug("AT flush"); reset_buffer(); while (fill_buffer(false)) { reset_buffer(); } } -void ATHandler::debug_print(char *p, int len) +void ATHandler::debug_print(const char *p, int len) { #if MBED_CONF_CELLULAR_DEBUG_AT if (_debug_on) { diff --git a/features/cellular/framework/AT/ATHandler.h b/features/cellular/framework/AT/ATHandler.h index 1e9952a4f75..54adb20921d 100644 --- a/features/cellular/framework/AT/ATHandler.h +++ b/features/cellular/framework/AT/ATHandler.h @@ -524,7 +524,7 @@ class ATHandler { bool find_urc_handler(const char *prefix); // print contents of a buffer to trace log - void debug_print(char *p, int len); + void debug_print(const char *p, int len); }; } // namespace mbed diff --git a/features/cellular/framework/AT/AT_CellularContext.cpp b/features/cellular/framework/AT/AT_CellularContext.cpp index cd201ced175..b3d2c6004bb 100644 --- a/features/cellular/framework/AT/AT_CellularContext.cpp +++ b/features/cellular/framework/AT/AT_CellularContext.cpp @@ -44,7 +44,7 @@ AT_CellularContext::AT_CellularContext(ATHandler &at, CellularDevice *device, co AT_CellularBase(at), _ip_stack_type_requested(DEFAULT_STACK), _is_connected(false), _is_blocking(true), _current_op(OP_INVALID), _device(device), _nw(0), _fh(0) { - tr_debug("AT_CellularContext::AT_CellularContext(): apn: %s", apn); + tr_info("New CellularContext %s (%p)", apn ? apn : "", this); _stack = NULL; _ip_stack_type = DEFAULT_STACK; _authentication_type = CellularContext::CHAP; @@ -62,6 +62,8 @@ AT_CellularContext::AT_CellularContext(ATHandler &at, CellularDevice *device, co AT_CellularContext::~AT_CellularContext() { + tr_info("Delete CellularContext %s (%p)", _apn ? _apn : "", this); + (void)disconnect(); if (_nw) { @@ -71,12 +73,14 @@ AT_CellularContext::~AT_CellularContext() void AT_CellularContext::set_file_handle(FileHandle *fh) { + tr_info("CellularContext filehandle %p", fh); _fh = fh; _at.set_file_handle(_fh); } nsapi_error_t AT_CellularContext::connect() { + tr_info("CellularContext connect"); if (_is_connected) { return NSAPI_ERROR_IS_CONNECTED; } @@ -200,6 +204,7 @@ void AT_CellularContext::attach(Callback status_c nsapi_error_t AT_CellularContext::set_blocking(bool blocking) { nsapi_error_t err = NSAPI_ERROR_OK; + tr_info("CellularContext set blocking %d", blocking); #if NSAPI_PPP_AVAILABLE err = nsapi_ppp_set_blocking(blocking); #endif @@ -209,6 +214,7 @@ nsapi_error_t AT_CellularContext::set_blocking(bool blocking) void AT_CellularContext::set_plmn(const char *plmn) { + tr_info("CellularContext plmn %s", plmn); _device->set_plmn(plmn); } @@ -301,12 +307,6 @@ nsapi_error_t AT_CellularContext::do_user_authentication() bool AT_CellularContext::get_context() { - if (_apn) { - tr_debug("APN in use: %s", _apn); - } else { - tr_debug("NO APN"); - } - _at.cmd_start("AT+CGDCONT?"); _at.cmd_stop(); _at.resp_start("+CGDCONT:"); @@ -388,7 +388,8 @@ bool AT_CellularContext::get_context() memcpy(_found_apn, apn, apn_len + 1); } - tr_debug("Context id %d", _cid); + tr_info("Found PDP context %d", _cid); + return true; } @@ -450,7 +451,7 @@ bool AT_CellularContext::set_new_context(int cid) _ip_stack_type = tmp_stack; _cid = cid; _new_context_set = true; - tr_info("New PDP context id %d was created", _cid); + tr_info("New PDP context %d, stack %s", _cid, pdp_type); } return success; @@ -468,9 +469,10 @@ nsapi_error_t AT_CellularContext::do_activate_context() _at.unlock(); // in PPP we don't activate any context but leave it to PPP stack return err; -#endif // NSAPI_PPP_AVAILABLE +#else // try to authenticate user before activating or modifying context err = do_user_authentication(); +#endif // NSAPI_PPP_AVAILABLE } else { err = NSAPI_ERROR_NO_CONNECTION; } @@ -566,7 +568,7 @@ void AT_CellularContext::do_connect() #if NSAPI_PPP_AVAILABLE nsapi_error_t AT_CellularContext::open_data_channel() { - tr_info("Open data channel in PPP mode"); + tr_info("CellularContext PPP connect"); if (is_supported(AT_CGDATA)) { _at.cmd_start("AT+CGDATA=\"PPP\","); _at.write_int(_cid); @@ -596,7 +598,7 @@ nsapi_error_t AT_CellularContext::open_data_channel() void AT_CellularContext::ppp_status_cb(nsapi_event_t ev, intptr_t ptr) { - tr_debug("AT_CellularContext::ppp_status_cb, network_callback called with event: %d, ptr: %d", ev, ptr); + tr_debug("ppp_status_cb: event %d, ptr %d", ev, ptr); if (ev == NSAPI_EVENT_CONNECTION_STATUS_CHANGE && ptr == NSAPI_STATUS_GLOBAL_UP) { _is_connected = true; } else { @@ -613,13 +615,14 @@ void AT_CellularContext::ppp_status_cb(nsapi_event_t ev, intptr_t ptr) nsapi_error_t AT_CellularContext::disconnect() { + tr_info("CellularContext disconnect"); if (!_nw || !_is_connected) { return NSAPI_ERROR_NO_CONNECTION; } #if NSAPI_PPP_AVAILABLE nsapi_error_t err = nsapi_ppp_disconnect(_at.get_file_handle()); if (err != NSAPI_ERROR_OK) { - tr_error("Cellular disconnect failed!"); + tr_error("CellularContext disconnect failed!"); // continue even in failure due to ppp disconnect in any case releases filehandle } // after ppp disconnect if we wan't to use same at handler we need to set filehandle again to athandler so it @@ -710,7 +713,6 @@ nsapi_error_t AT_CellularContext::get_rate_control( int next_element = _at.read_int(); if (next_element >= 0) { reports = (RateControlExceptionReports)next_element; - tr_debug("reports %d", reports); next_element = _at.read_int(); } else { comma_found = false; @@ -718,7 +720,6 @@ nsapi_error_t AT_CellularContext::get_rate_control( if (comma_found && next_element >= 0) { timeUnit = (RateControlUplinkTimeUnit)next_element; - tr_debug("time %d", timeUnit); next_element = _at.read_int(); } else { comma_found = false; @@ -726,7 +727,9 @@ nsapi_error_t AT_CellularContext::get_rate_control( if (comma_found && next_element >= 0) { uplinkRate = next_element; - tr_debug("rate %d", uplinkRate); + } + if (_at.get_last_error() == NSAPI_ERROR_OK) { + tr_debug("CGAPNRC: reports %d, time %d, rate %d", reports, timeUnit, uplinkRate); } } _at.resp_stop(); @@ -813,7 +816,7 @@ void AT_CellularContext::cellular_callback(nsapi_event_t ev, intptr_t ptr) cell_callback_data_t *data = (cell_callback_data_t *)ptr; cellular_connection_status_t st = (cellular_connection_status_t)ev; _cb_data.error = data->error; - tr_debug("AT_CellularContext::cellular_callback, network_callback called with event: %d, err: %d, data: %d", ev, data->error, data->status_data); + tr_debug("CellularContext: event %d, err %d, data %d", ev, data->error, data->status_data); #if USE_APN_LOOKUP if (st == CellularSIMStatusChanged && data->status_data == CellularSIM::SimStateReady && _cb_data.error == NSAPI_ERROR_OK) { @@ -880,13 +883,15 @@ void AT_CellularContext::cellular_callback(nsapi_event_t ev, intptr_t ptr) } } } else { - tr_debug("AT_CellularContext::cellular_callback, network_callback called with event: %d, ptr: %d", ev, ptr); + tr_debug("CellularContext: event %d, ptr %d", ev, ptr); #if NSAPI_PPP_AVAILABLE if (_is_blocking) { if (ev == NSAPI_EVENT_CONNECTION_STATUS_CHANGE && ptr == NSAPI_STATUS_GLOBAL_UP) { + tr_info("CellularContext IP %s", get_ip_address()); _cb_data.error = NSAPI_ERROR_OK; _semaphore.release(); } else if (ev == NSAPI_EVENT_CONNECTION_STATUS_CHANGE && ptr == NSAPI_STATUS_DISCONNECTED) { + tr_info("PPP disconnected"); _cb_data.error = NSAPI_ERROR_NO_CONNECTION; _semaphore.release(); } @@ -907,5 +912,8 @@ void AT_CellularContext::call_network_cb(nsapi_connection_status_t status) if (_status_cb) { _status_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, _connect_status); } + if (_nw && _connect_status == NSAPI_STATUS_DISCONNECTED) { + tr_info("CellularContext disconnected"); + } } } diff --git a/features/cellular/framework/AT/AT_CellularDevice.cpp b/features/cellular/framework/AT/AT_CellularDevice.cpp index f33e3cd9985..d04a15b113c 100644 --- a/features/cellular/framework/AT/AT_CellularDevice.cpp +++ b/features/cellular/framework/AT/AT_CellularDevice.cpp @@ -365,5 +365,17 @@ void AT_CellularDevice::modem_debug_on(bool on) nsapi_error_t AT_CellularDevice::init_module() { +#if MBED_CONF_MBED_TRACE_ENABLE + CellularInformation *information = open_information(); + if (information) { + char *pbuf = new char[100]; + nsapi_error_t ret = information->get_model(pbuf, sizeof(*pbuf)); + close_information(); + if (ret == NSAPI_ERROR_OK) { + tr_info("Model %s", pbuf); + } + delete[] pbuf; + } +#endif return NSAPI_ERROR_OK; } diff --git a/features/cellular/framework/AT/AT_CellularNetwork.cpp b/features/cellular/framework/AT/AT_CellularNetwork.cpp index dcb14804829..b9de98c82bb 100644 --- a/features/cellular/framework/AT/AT_CellularNetwork.cpp +++ b/features/cellular/framework/AT/AT_CellularNetwork.cpp @@ -37,6 +37,39 @@ static const at_reg_t at_reg[] = { { CellularNetwork::C_REG, "AT+CREG", "+CREG:"} }; +#if MBED_CONF_MBED_TRACE_ENABLE +static const char *const reg_type_str[(int)AT_CellularNetwork::RegistrationStatusMax] = { + "NotRegistered", + "RegisteredHomeNetwork", + "SearchingNetwork", + "RegistrationDenied", + "RegistrationUnknown", + "RegisteredRoaming", + "RegisteredSMSOnlyHome", + "RegisteredSMSOnlyRoaming", + "AttachedEmergencyOnly", + "RegisteredCSFBNotPreferredHome", + "RegisteredCSFBNotPreferredRoaming", + "AlreadyRegistered" +}; + +static const char *const rat_str[AT_CellularNetwork::RAT_MAX] = { + "GSM", + "GSM_COMPACT", + "UTRAN", + "EGPRS", + "HSDPA", + "HSUPA", + "HSDPA_HSUPA", + "E_UTRAN", + "CATM1", + "NB1", + "RAT unknown", +}; + +#endif + + AT_CellularNetwork::AT_CellularNetwork(ATHandler &atHandler) : AT_CellularBase(atHandler), _connection_status_cb(NULL), _op_act(RAT_UNKNOWN), _connect_status(NSAPI_STATUS_DISCONNECTED) { @@ -79,7 +112,7 @@ AT_CellularNetwork::~AT_CellularNetwork() void AT_CellularNetwork::urc_no_carrier() { - tr_error("Data call failed: no carrier"); + tr_info("NO CARRIER"); call_network_cb(NSAPI_STATUS_DISCONNECTED); } @@ -89,7 +122,7 @@ void AT_CellularNetwork::urc_cgev() if (_at.read_string(buf, 13) < 8) { // smallest string length we wan't to compare is 8 return; } - tr_debug("urc_cgev: %s", buf); + tr_debug("CGEV: %s", buf); bool call_cb = false; // NOTE! If in future there will be 2 or more active contexts we might wan't to read context id also but not for now. @@ -116,26 +149,9 @@ void AT_CellularNetwork::urc_cgev() void AT_CellularNetwork::read_reg_params_and_compare(RegistrationType type) { registration_params_t reg_params; - read_reg_params(reg_params); - -#if MBED_CONF_MBED_TRACE_ENABLE - switch (reg_params._status) { - case NotRegistered: - tr_warn("not registered"); - break; - case RegistrationDenied: - tr_warn("registration denied"); - break; - case Unknown: - tr_warn("registration status unknown"); - break; - default: - break; - } -#endif + read_reg_params(type, reg_params); if (_at.get_last_error() == NSAPI_ERROR_OK && _connection_status_cb) { - tr_debug("type: %d, status: %d, lac: %d, cellID: %d, act: %d", type, reg_params._status, reg_params._lac, reg_params._cell_id, reg_params._act); _reg_params._type = type; cell_callback_data_t data; data.error = NSAPI_ERROR_OK; @@ -159,19 +175,16 @@ void AT_CellularNetwork::read_reg_params_and_compare(RegistrationType type) void AT_CellularNetwork::urc_creg() { - tr_debug("urc_creg"); read_reg_params_and_compare(C_REG); } void AT_CellularNetwork::urc_cereg() { - tr_debug("urc_cereg"); read_reg_params_and_compare(C_EREG); } void AT_CellularNetwork::urc_cgreg() { - tr_debug("urc_cgreg"); read_reg_params_and_compare(C_GREG); } @@ -258,18 +271,19 @@ nsapi_error_t AT_CellularNetwork::set_registration(const char *plmn) return _at.unlock_return_error(); } -void AT_CellularNetwork::read_reg_params(registration_params_t ®_params) +void AT_CellularNetwork::read_reg_params(RegistrationType type, registration_params_t ®_params) { const int MAX_STRING_LENGTH = 9; char string_param[MAX_STRING_LENGTH] = {0}; + reg_params._type = type; + int int_param = _at.read_int(); - reg_params._status = (RegistrationStatus)int_param; + reg_params._status = (int_param >= 0 && int_param < RegistrationStatusMax) ? (RegistrationStatus)int_param : NotRegistered; int len = _at.read_string(string_param, TWO_BYTES_HEX + 1); if (len > 0) { reg_params._lac = hex_str_to_int(string_param, TWO_BYTES_HEX); - tr_debug("lac %s %d", string_param, reg_params._lac); } else { reg_params._lac = -1; } @@ -277,28 +291,25 @@ void AT_CellularNetwork::read_reg_params(registration_params_t ®_params) len = _at.read_string(string_param, FOUR_BYTES_HEX + 1); if (len > 0) { reg_params._cell_id = hex_str_to_int(string_param, FOUR_BYTES_HEX); - tr_debug("cell_id %s %d", string_param, reg_params._cell_id); } else { reg_params._cell_id = -1; } int_param = _at.read_int(); - reg_params._act = (int_param == -1) ? RAT_UNKNOWN : (RadioAccessTechnology)int_param; + reg_params._act = (int_param >= 0 && int_param < RAT_MAX) ? (RadioAccessTechnology)int_param : RAT_UNKNOWN ; // Skip [],[] _at.skip_param(2); len = _at.read_string(string_param, ONE_BYTE_BINARY + 1); reg_params._active_time = calculate_active_time(string_param, len); - if (reg_params._active_time != -1) { - tr_debug("active_time %s %d", string_param, reg_params._active_time); - } len = _at.read_string(string_param, ONE_BYTE_BINARY + 1); reg_params._periodic_tau = calculate_periodic_tau(string_param, len); - if (reg_params._periodic_tau == -1) { - tr_debug("periodic_tau %s %d", string_param, reg_params._periodic_tau); - } + +#if MBED_CONF_MBED_TRACE_ENABLE + tr_debug("%s %s, LAC %d, cell %d, %s", at_reg[(int)type].urc_prefix, reg_type_str[reg_params._status], reg_params._lac, reg_params._cell_id, rat_str[reg_params._act]); +#endif } AT_CellularNetwork::RegistrationMode AT_CellularNetwork::has_registration(RegistrationType reg_type) @@ -485,6 +496,12 @@ nsapi_error_t AT_CellularNetwork::get_signal_quality(int &rssi, int &ber) return NSAPI_ERROR_DEVICE_ERROR; } + if (rssi == 99) { + rssi = 0; + } else { + rssi = -113 + 2 * rssi; + } + return _at.unlock_return_error(); } @@ -593,8 +610,7 @@ nsapi_error_t AT_CellularNetwork::get_registration_params(RegistrationType type, _at.resp_start(rsp[i]); (void)_at.read_int(); // ignore urc mode subparam - _reg_params._type = type; - read_reg_params(reg_params); + read_reg_params(type, reg_params); _at.resp_stop(); _reg_params = reg_params; diff --git a/features/cellular/framework/AT/AT_CellularNetwork.h b/features/cellular/framework/AT/AT_CellularNetwork.h index fc597ecd2fd..21b30546a24 100644 --- a/features/cellular/framework/AT/AT_CellularNetwork.h +++ b/features/cellular/framework/AT/AT_CellularNetwork.h @@ -117,7 +117,7 @@ class AT_CellularNetwork : public CellularNetwork, public AT_CellularBase { void urc_cgev(); void read_reg_params_and_compare(RegistrationType type); - void read_reg_params(registration_params_t ®_params); + void read_reg_params(RegistrationType type, registration_params_t ®_params); // Returns active time(Table 10.5.163/3GPP TS 24.008: GPRS Timer 2 information element) in seconds int calculate_active_time(const char *active_time_string, int active_time_length); diff --git a/features/cellular/framework/AT/AT_CellularStack.cpp b/features/cellular/framework/AT/AT_CellularStack.cpp index 5cc0118ee7b..5008884f61b 100644 --- a/features/cellular/framework/AT/AT_CellularStack.cpp +++ b/features/cellular/framework/AT/AT_CellularStack.cpp @@ -41,6 +41,18 @@ AT_CellularStack::~AT_CellularStack() _socket = NULL; } +int AT_CellularStack::find_socket_index(nsapi_socket_t handle) +{ + int max_socket_count = get_max_socket_count(); + for (int i = 0; i < max_socket_count; i++) { + if (_socket[i] == handle) { + return i; + } + } + return -1; +} + + /** NetworkStack */ @@ -115,21 +127,14 @@ nsapi_error_t AT_CellularStack::socket_open(nsapi_socket_t *handle, nsapi_protoc } } - int index = -1; - for (int i = 0; i < max_socket_count; i++) { - if (!_socket[i]) { - index = i; - break; - } - } - + int index = find_socket_index(0); if (index == -1) { - tr_error("No socket found!"); + tr_error("No free sockets!"); _socket_mutex.unlock(); return NSAPI_ERROR_NO_SOCKET; } - tr_info("Socket open index: %d", index); + tr_info("Socket %d open", index); // create local socket structure, socket on modem is created when app calls sendto/recvfrom _socket[index] = new CellularSocket; CellularSocket *psock; @@ -156,18 +161,8 @@ nsapi_error_t AT_CellularStack::socket_close(nsapi_socket_t handle) } int sock_id = socket->id; bool sock_created = socket->created; - int max_socket_count = get_max_socket_count(); - - int index = -1; - for (int i = 0; i < max_socket_count; i++) { - if (_socket[i] == socket) { - index = i; - break; - } - } - - tr_info("Close socket index: %d id: %d created: %d", index, sock_id, socket->created); + int index = find_socket_index(handle); if (index == -1) { tr_error("No socket found to be closed"); return err; @@ -181,6 +176,12 @@ nsapi_error_t AT_CellularStack::socket_close(nsapi_socket_t handle) err = socket_close_impl(sock_id); } + if (!err) { + tr_info("Socket %d closed", index); + } else { + tr_info("Socket %d close (id %d, created %d, started %d, error %d)", index, sock_id, socket->created, socket->started, err); + } + _socket[index] = NULL; delete socket; @@ -260,10 +261,8 @@ nsapi_size_or_error_t AT_CellularStack::socket_sendto(nsapi_socket_t handle, con _at.unlock(); if (ret_val != NSAPI_ERROR_OK) { - tr_error("Error creating socket to send to: %s error code: %d", addr.get_ip_address(), ret_val); + tr_error("Socket %d create %s error %d", find_socket_index(socket), addr.get_ip_address(), ret_val); return ret_val; - } else { - tr_info("Success creating socket to send to: %s", addr.get_ip_address()); } } @@ -276,14 +275,14 @@ nsapi_size_or_error_t AT_CellularStack::socket_sendto(nsapi_socket_t handle, con ret_val = socket_sendto_impl(socket, addr, data, size); - if (ret_val > 0) { - tr_info("Success sending %d Bytes to: %s", ret_val, addr.get_ip_address()); + _at.unlock(); + + if (ret_val >= 0) { + tr_info("Socket %d sent %d bytes to %s port %d", find_socket_index(socket), ret_val, addr.get_ip_address(), addr.get_port()); } else if (ret_val != NSAPI_ERROR_WOULD_BLOCK) { - tr_error("Error sending to: %s error code: %d", addr.get_ip_address(), ret_val); + tr_error("Socket %d sendto %s error %d", find_socket_index(socket), addr.get_ip_address(), ret_val); } - _at.unlock(); - return ret_val; } @@ -308,6 +307,7 @@ nsapi_size_or_error_t AT_CellularStack::socket_recvfrom(nsapi_socket_t handle, S _at.unlock(); if (ret_val != NSAPI_ERROR_OK) { + tr_error("Socket %d create %s error %d", find_socket_index(socket), addr->get_ip_address(), ret_val); return ret_val; } } @@ -318,6 +318,12 @@ nsapi_size_or_error_t AT_CellularStack::socket_recvfrom(nsapi_socket_t handle, S _at.unlock(); + if (ret_val >= 0) { + tr_info("Socket %d recv %d bytes from %s port %d", find_socket_index(socket), ret_val, addr->get_ip_address(), addr->get_port()); + } else if (ret_val != NSAPI_ERROR_WOULD_BLOCK) { + tr_error("Socket %d recv error %d", find_socket_index(socket), ret_val); + } + return ret_val; } diff --git a/features/cellular/framework/AT/AT_CellularStack.h b/features/cellular/framework/AT/AT_CellularStack.h index 7a61409862a..2c25da15796 100644 --- a/features/cellular/framework/AT/AT_CellularStack.h +++ b/features/cellular/framework/AT/AT_CellularStack.h @@ -182,6 +182,8 @@ class AT_CellularStack : public NetworkStack, public AT_CellularBase { nsapi_ip_stack_t _stack_type; private: + int find_socket_index(nsapi_socket_t handle); + // mutex for write/read to a _socket array, needed when multiple threads may open sockets simultaneously PlatformMutex _socket_mutex; }; diff --git a/features/cellular/framework/device/CellularDevice.cpp b/features/cellular/framework/device/CellularDevice.cpp index 7ebd1f14ef3..6ad46ddc67d 100644 --- a/features/cellular/framework/device/CellularDevice.cpp +++ b/features/cellular/framework/device/CellularDevice.cpp @@ -162,7 +162,7 @@ void CellularDevice::cellular_callback(nsapi_event_t ev, intptr_t ptr) { if (ev >= NSAPI_EVENT_CELLULAR_STATUS_BASE && ev <= NSAPI_EVENT_CELLULAR_STATUS_END) { cell_callback_data_t *ptr_data = (cell_callback_data_t *)ptr; - tr_debug("Device: network_callback called with event: %d, err: %d, data: %d", ev, ptr_data->error, ptr_data->status_data); + tr_debug("callback: %d, err: %d, data: %d", ev, ptr_data->error, ptr_data->status_data); cellular_connection_status_t cell_ev = (cellular_connection_status_t)ev; if (cell_ev == CellularRegistrationStatusChanged && _state_machine) { // broadcast only network registration changes to state machine @@ -185,7 +185,7 @@ void CellularDevice::cellular_callback(nsapi_event_t ev, intptr_t ptr) } } } else { - tr_debug("Device: network_callback called with event: %d, ptr: %d", ev, ptr); + tr_debug("callback: %d, ptr: %d", ev, ptr); if (ev == NSAPI_EVENT_CONNECTION_STATUS_CHANGE && ptr == NSAPI_STATUS_DISCONNECTED) { // we have been disconnected, reset state machine so that application can start connect sequence again if (_state_machine) { diff --git a/features/cellular/framework/device/CellularStateMachine.cpp b/features/cellular/framework/device/CellularStateMachine.cpp index 08603736ef6..3e7dd5ef8cb 100644 --- a/features/cellular/framework/device/CellularStateMachine.cpp +++ b/features/cellular/framework/device/CellularStateMachine.cpp @@ -89,6 +89,7 @@ void CellularStateMachine::reset() void CellularStateMachine::stop() { + tr_debug("CellularStateMachine stop"); if (_queue_thread) { _queue.break_dispatch(); _queue_thread->terminate(); @@ -118,10 +119,10 @@ bool CellularStateMachine::power_on() { _cb_data.error = _power->on(); if (_cb_data.error != NSAPI_ERROR_OK && _cb_data.error != NSAPI_ERROR_UNSUPPORTED) { - tr_warn("Cellular start failed. Power off/on."); + tr_warn("Power on failed. Try to power off/on."); _cb_data.error = _power->off(); if (_cb_data.error != NSAPI_ERROR_OK && _cb_data.error != NSAPI_ERROR_UNSUPPORTED) { - tr_error("Cellular power down failing after failed power up attempt!"); + tr_error("Power off failed!"); } return false; } @@ -162,14 +163,14 @@ bool CellularStateMachine::open_sim() if (state == CellularSIM::SimStatePinNeeded) { if (strlen(_sim_pin)) { - tr_info("Entering PIN to open SIM"); + tr_info("Entering PIN to open SIM."); _cb_data.error = _sim->set_pin(_sim_pin); if (_cb_data.error) { - tr_error("SIM pin set failed with: %d", _cb_data.error); + tr_error("Failed to set PIN: error %d", _cb_data.error); } } else { // No sim pin provided even it's needed, stop state machine - tr_error("PIN required but No SIM pin provided."); + tr_error("PIN required but no SIM pin provided."); _retry_count = RETRY_ARRAY_SIZE; return false; } @@ -185,7 +186,6 @@ bool CellularStateMachine::is_registered() for (int type = 0; type < CellularNetwork::C_MAX; type++) { if (get_network_registration((CellularNetwork::RegistrationType) type, status, is_registered)) { - tr_debug("get_network_registration: type=%d, status=%d", type, status); if (is_registered) { break; } @@ -242,7 +242,7 @@ bool CellularStateMachine::get_network_registration(CellularNetwork::Registratio } if (is_roaming) { - tr_warn("Roaming cellular network!"); + tr_info("Roaming network."); } return true; @@ -250,7 +250,7 @@ bool CellularStateMachine::get_network_registration(CellularNetwork::Registratio void CellularStateMachine::report_failure(const char *msg) { - tr_error("Cellular stm failed with: %s", msg); + tr_error("CellularStateMachine failure: %s", msg); _event_id = -1; if (_event_status_cb) { @@ -258,7 +258,7 @@ void CellularStateMachine::report_failure(const char *msg) _event_status_cb(_current_event, (intptr_t)&_cb_data); } - tr_error("Target state %s was not reached. Returning from state: %s", get_state_string(_target_state), get_state_string(_state)); + tr_error("CellularStateMachine target state %s, current state %s", get_state_string(_target_state), get_state_string(_state)); } const char *CellularStateMachine::get_state_string(CellularState state) const @@ -332,7 +332,7 @@ void CellularStateMachine::enter_to_state(CellularState state) void CellularStateMachine::retry_state_or_fail() { if (++_retry_count < RETRY_ARRAY_SIZE) { - tr_debug("Retry State %s, retry %d/%d", get_state_string(_state), _retry_count, RETRY_ARRAY_SIZE); + tr_debug("%s: retry %d/%d", get_state_string(_state), _retry_count, RETRY_ARRAY_SIZE); _event_timeout = _retry_timeout_array[_retry_count]; _is_retry = true; } else { @@ -343,19 +343,19 @@ void CellularStateMachine::retry_state_or_fail() void CellularStateMachine::state_init() { - // we should check that if power is already on then we can jump to device ready state _cellularDevice.set_timeout(TIMEOUT_POWER_ON); - tr_info("Cellular state init (timeout %d ms)", TIMEOUT_POWER_ON); + tr_info("Start connecting (timeout %d s)", TIMEOUT_POWER_ON / 1000); if (!_power) { _power = _cellularDevice.open_power(); } _cb_data.error = _power->is_device_ready(); if (_cb_data.error != NSAPI_ERROR_OK) { _event_timeout = _start_time; - tr_info("Init state, waiting %d ms before POWER state)", _start_time); + if (_start_time > 0) { + tr_info("Startup delay %d ms", _start_time); + } enter_to_state(STATE_POWER_ON); } else { - tr_info("Device was ready to accept commands, jump to device ready"); enter_to_state(STATE_DEVICE_READY); } } @@ -363,7 +363,7 @@ void CellularStateMachine::state_init() void CellularStateMachine::state_power_on() { _cellularDevice.set_timeout(TIMEOUT_POWER_ON); - tr_info("Cellular power ON (timeout %d ms)", TIMEOUT_POWER_ON); + tr_info("Modem power ON (timeout %d s)", TIMEOUT_POWER_ON / 1000); if (power_on()) { enter_to_state(STATE_DEVICE_READY); } else { @@ -374,7 +374,7 @@ void CellularStateMachine::state_power_on() bool CellularStateMachine::device_ready() { - tr_info("Cellular device ready"); + tr_info("Modem ready"); if (_cellularDevice.init_module() != NSAPI_ERROR_OK) { return false; } @@ -408,7 +408,7 @@ void CellularStateMachine::state_device_ready() void CellularStateMachine::state_sim_pin() { _cellularDevice.set_timeout(TIMEOUT_SIM_PIN); - tr_info("Sim state (timeout %d ms)", TIMEOUT_SIM_PIN); + tr_info("Setup SIM (timeout %d s)", TIMEOUT_SIM_PIN / 1000); if (open_sim()) { if (!_network) { _network = _cellularDevice.open_network(); @@ -442,8 +442,8 @@ void CellularStateMachine::state_sim_pin() void CellularStateMachine::state_registering() { _cellularDevice.set_timeout(TIMEOUT_NETWORK); + tr_info("Network registration (timeout %d s)", TIMEOUT_REGISTRATION / 1000); if (is_registered()) { - tr_info("Sending Registration changed from plmn"); _cb_data.status_data = CellularNetwork::AlreadyRegistered; _cb_data.error = NSAPI_ERROR_OK; _event_status_cb(_current_event, (intptr_t)&_cb_data); @@ -463,11 +463,10 @@ void CellularStateMachine::state_registering() void CellularStateMachine::state_manual_registering_network() { _cellularDevice.set_timeout(TIMEOUT_REGISTRATION); - tr_info("state_manual_registering_network"); + tr_info("Manual registration %s (timeout %d s)", _plmn, TIMEOUT_REGISTRATION / 1000); if (!_plmn_network_found) { if (is_registered() && is_registered_to_plmn()) { // we have to send registration changed event as network thinks that we are not registered even we have active PDP context - tr_info("Sending REgistration changed from plmn"); _cb_data.status_data = CellularNetwork::AlreadyRegistered; _cb_data.error = NSAPI_ERROR_OK; _event_status_cb(_current_event, (intptr_t)&_cb_data); @@ -486,8 +485,8 @@ void CellularStateMachine::state_manual_registering_network() void CellularStateMachine::state_attaching() { _cellularDevice.set_timeout(TIMEOUT_CONNECT); + tr_info("Attaching network (timeout %d s)", TIMEOUT_CONNECT / 1000); _cb_data.error = _network->set_attach(); - tr_info("CellularStateMachine::state_attaching(): %d", _cb_data.error); if (_cb_data.error == NSAPI_ERROR_OK) { _cellularDevice.close_sim(); _sim = NULL; @@ -503,7 +502,7 @@ void CellularStateMachine::state_attaching() void CellularStateMachine::continue_from_state(CellularState state) { _mutex.lock(); - tr_info("Continue state from %s to %s", get_state_string((CellularStateMachine::CellularState)_state), + tr_info("%s => %s", get_state_string((CellularStateMachine::CellularState)_state), get_state_string((CellularStateMachine::CellularState)state)); _state = state; enter_to_state(state); @@ -533,7 +532,6 @@ nsapi_error_t CellularStateMachine::run_to_state(CellularStateMachine::CellularS void CellularStateMachine::pre_event(CellularState state) { - tr_debug("CellularStateMachine::pre_event, state: %s, _target_state: %s, _event_id: %d", get_state_string(state), get_state_string(_target_state), _event_id); if (_target_state < state) { // new wanted state will not be achieved with current _target_state so update it _target_state = state; @@ -571,7 +569,20 @@ bool CellularStateMachine::get_current_status(CellularStateMachine::CellularStat void CellularStateMachine::event() { - tr_debug("CellularStateMachine::event(): %s", get_state_string(_state)); +#if MBED_CONF_MBED_TRACE_ENABLE + if (_network) { + int rssi; + int ber; + if (_network->get_signal_quality(rssi, ber) == NSAPI_ERROR_OK) { + if (rssi == 0) { + tr_info("RSSI unknown"); + } else { + tr_info("RSSI %d dBm", rssi); + } + } + } +#endif + _event_timeout = -1; _is_retry = false; @@ -610,17 +621,16 @@ void CellularStateMachine::event() } if ((_target_state == _state && _cb_data.error == NSAPI_ERROR_OK && !_is_retry) || _event_id == STM_STOPPED) { - tr_info("Target state reached: %s, _cb_data.error: %d, _event_id: %d", get_state_string(_target_state), _cb_data.error, _event_id); _event_id = -1; return; } if (_next_state != _state || _event_timeout >= 0) { if (_next_state != _state) { // state exit condition - tr_info("Cellular state from %s to %s", get_state_string((CellularStateMachine::CellularState)_state), - get_state_string((CellularStateMachine::CellularState)_next_state)); + tr_debug("%s => %s", get_state_string((CellularStateMachine::CellularState)_state), + get_state_string((CellularStateMachine::CellularState)_next_state)); } else { - tr_info("Cellular event in %d seconds", _event_timeout); + tr_info("Continue after %d seconds", _event_timeout); } _state = _next_state; if (_event_timeout == -1) { @@ -629,7 +639,7 @@ void CellularStateMachine::event() _event_id = _queue.call_in(_event_timeout * 1000, callback(this, &CellularStateMachine::event)); if (!_event_id) { _cb_data.error = NSAPI_ERROR_NO_MEMORY; - report_failure("Cellular event failure!"); + report_failure("CellularStateMachine event failure!"); return; } } @@ -656,12 +666,6 @@ void CellularStateMachine::set_cellular_callback(mbed::Callback= NSAPI_EVENT_CELLULAR_STATUS_BASE && ev <= NSAPI_EVENT_CELLULAR_STATUS_END) { - tr_debug("FSM: cellular_event_changed called with event: %d, err: %d, data: %d _state: %s", ev, data->error, data->status_data, get_state_string(_state)); - } else { - tr_debug("FSM: cellular_event_changed called with event: %d, ptr: %d _state: %s", ev, ptr, get_state_string(_state)); - } - if ((cellular_connection_status_t)ev == CellularRegistrationStatusChanged && (_state == STATE_REGISTERING_NETWORK || _state == STATE_MANUAL_REGISTERING_NETWORK)) { // expect packet data so only these states are valid diff --git a/features/cellular/framework/targets/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.cpp b/features/cellular/framework/targets/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.cpp index d79604de4b9..1c0128ea914 100644 --- a/features/cellular/framework/targets/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.cpp +++ b/features/cellular/framework/targets/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.cpp @@ -154,6 +154,8 @@ bool GEMALTO_CINTERION_CellularStack::is_protocol_supported(nsapi_protocol_t pro nsapi_error_t GEMALTO_CINTERION_CellularStack::socket_close_impl(int sock_id) { + tr_debug("Cinterion close %d", sock_id); + _at.set_at_timeout(FAILURE_TIMEOUT); _at.cmd_start("AT^SISC="); @@ -169,7 +171,6 @@ nsapi_error_t GEMALTO_CINTERION_CellularStack::socket_close_impl(int sock_id) _at.restore_at_timeout(); - tr_debug("Closed socket %d (err %d)", sock_id, _at.get_last_error()); return _at.get_last_error(); } @@ -210,7 +211,7 @@ nsapi_error_t GEMALTO_CINTERION_CellularStack::socket_open_defer(CellularSocket } socket->created = true; - tr_debug("Socket %d created (err %d)", socket->id, _at.get_last_error()); + tr_debug("Cinterion open %d (err %d)", socket->id, _at.get_last_error()); return _at.get_last_error(); } @@ -247,20 +248,17 @@ nsapi_error_t GEMALTO_CINTERION_CellularStack::create_socket_impl(CellularSocket if (paramValueLen >= 0) { if (strcmp(paramTag, "srvType") == 0) { if (strcmp(paramValue, "Socket") == 0) { - tr_debug("srvType %s", paramValue); foundSrvType = true; } } if (strcmp(paramTag, "address") == 0) { if (strncmp(paramValue, "sock", sizeof("sock")) == 0) { - tr_debug("address %s", paramValue); foundSrvType = true; } } if (strcmp(paramTag, "conId") == 0) { char buf[10]; std::sprintf(buf, "%d", connection_profile_id); - tr_debug("conId %s", paramValue); if (strcmp(paramValue, buf) == 0) { foundConIdType = true; } @@ -287,8 +285,6 @@ nsapi_error_t GEMALTO_CINTERION_CellularStack::create_socket_impl(CellularSocket _at.cmd_stop_read_resp(); } - tr_debug("Internet service %d (err %d)", internet_service_id, _at.get_last_error()); - if (socket->proto == NSAPI_UDP) { if (GEMALTO_CINTERION_Module::get_model() != GEMALTO_CINTERION_Module::ModelBGS2) { return socket_open_defer(socket); @@ -301,8 +297,6 @@ nsapi_error_t GEMALTO_CINTERION_CellularStack::create_socket_impl(CellularSocket nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_sendto_impl(CellularSocket *socket, const SocketAddress &address, const void *data, nsapi_size_t size) { - tr_debug("Socket %d, sendto %s, len %d", socket->id, address.get_ip_address(), size); - if (socket->proto == NSAPI_UDP) { const int ip_version = address.get_ip_version(); if ((ip_version == NSAPI_IPv4 && _stack_type != IPV4_STACK) || @@ -404,8 +398,6 @@ nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_sendto_impl(Cellul _at.resp_stop(); _at.restore_at_timeout(); - tr_debug("Socket %d sendto %s, %d bytes (err %d)", socket->id, address.get_ip_address(), accept_len, _at.get_last_error()); - if (_at.get_last_error() == NSAPI_ERROR_OK) { socket->tx_ready = false; } @@ -416,8 +408,6 @@ nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_sendto_impl(Cellul nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_recvfrom_impl(CellularSocket *socket, SocketAddress *address, void *buffer, nsapi_size_t size) { - tr_debug("Socket %d recvfrom %d bytes", socket->id, size); - // we must use this flag, otherwise ^SISR URC can come while we are reading response and there is // no way to detect if that is really an URC or response if (!socket->rx_avail) { @@ -504,7 +494,6 @@ nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_recvfrom_impl(Cell port_start++; // skip ':' int port = std::strtol(port_start, NULL, 10); address->set_port(port); - tr_debug("IP address %s, port %d", address->get_ip_address(), address->get_port()); *ip_stop = tmp_ch; // restore original IP string } } @@ -518,8 +507,6 @@ nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_recvfrom_impl(Cell _at.resp_stop(); - tr_debug("Socket %d, recvfrom %s, %d bytes (err %d)", socket->id, socket->remoteAddress.get_ip_address(), len, _at.get_last_error()); - return (_at.get_last_error() == NSAPI_ERROR_OK) ? (recv_len ? recv_len : NSAPI_ERROR_WOULD_BLOCK) : NSAPI_ERROR_DEVICE_ERROR; } @@ -543,7 +530,6 @@ nsapi_error_t GEMALTO_CINTERION_CellularStack::create_connection_profile(int con char paramTag[16]; int paramTagLen = _at.read_string(paramTag, sizeof(paramTag)); if (paramTagLen > 0) { - tr_debug("paramTag %s", paramTag); char paramValue[100 + 1]; // APN may be up to 100 chars int paramValueLen = _at.read_string(paramValue, sizeof(paramValue)); if (paramValueLen >= 0) { @@ -587,7 +573,7 @@ nsapi_error_t GEMALTO_CINTERION_CellularStack::create_connection_profile(int con _at.cmd_stop_read_resp(); } - tr_debug("Connection profile %d, stack_type %d (err %d)", connection_profile_id, _stack_type, _at.get_last_error()); + tr_debug("Cinterion profile %d, %s (err %d)", connection_profile_id, (_stack_type == IPV4_STACK) ? "IPv4" : "IPv6", _at.get_last_error()); return _at.get_last_error(); } diff --git a/features/frameworks/mbed-coap/CHANGELOG.md b/features/frameworks/mbed-coap/CHANGELOG.md index e47bf914509..230a23d44b7 100644 --- a/features/frameworks/mbed-coap/CHANGELOG.md +++ b/features/frameworks/mbed-coap/CHANGELOG.md @@ -1,5 +1,17 @@ # Change Log +## [v4.7.2](https://github.com/ARMmbed/mbed-coap/releases/tag/v4.7.2) + +- Fix handling of duplicate blockwise ACK's + CoAP data buffer was not added into duplication info store when creating response for blockwise request. + This leads to case where whole bootstrap flow just timeouts if received any duplicate messages during blockwise operation. + Fixes error: IOTCLT-3188 - UDP connection fails for lost ACK sending + +- Remove error trace when building reset message without options + This makes it possible to build the reset message without allocating option or getting error message. + +-[Full Changelog](https://github.com/ARMmbed/mbed-coap/compare/v4.7.1...v4.7.2) + ## [v4.7.1](https://github.com/ARMmbed/mbed-coap/releases/tag/v4.7.1) - Fix CoAP stored blockwise message release and list continue diff --git a/features/frameworks/mbed-coap/module.json b/features/frameworks/mbed-coap/module.json index 0e3d536135f..c170db093c0 100644 --- a/features/frameworks/mbed-coap/module.json +++ b/features/frameworks/mbed-coap/module.json @@ -1,6 +1,6 @@ { "name": "mbed-coap", - "version": "4.7.1", + "version": "4.7.2", "description": "COAP library", "keywords": [ "coap", diff --git a/features/frameworks/mbed-coap/source/sn_coap_builder.c b/features/frameworks/mbed-coap/source/sn_coap_builder.c index 6d5f5c50bcd..d663efb40f7 100644 --- a/features/frameworks/mbed-coap/source/sn_coap_builder.c +++ b/features/frameworks/mbed-coap/source/sn_coap_builder.c @@ -547,7 +547,10 @@ static int8_t sn_coap_builder_options_build(uint8_t **dst_packet_data_pptr, sn_c /* * * * 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_format == COAP_CT_NONE && src_coap_msg_ptr->options_list_ptr == NULL) { - tr_error("sn_coap_builder_options_build - options not used!"); + /* If the empty message is confirmable it is CoAP ping. */ + if (src_coap_msg_ptr->msg_type != COAP_MSG_TYPE_CONFIRMABLE) { + tr_error("sn_coap_builder_options_build - options not used!"); + } return 0; } diff --git a/features/frameworks/mbed-coap/source/sn_coap_protocol.c b/features/frameworks/mbed-coap/source/sn_coap_protocol.c index 8122660f4e1..caca1f1e902 100644 --- a/features/frameworks/mbed-coap/source/sn_coap_protocol.c +++ b/features/frameworks/mbed-coap/source/sn_coap_protocol.c @@ -49,10 +49,12 @@ #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, void *param); -static coap_duplication_info_s *sn_coap_protocol_linked_list_duplication_info_search(struct coap_s *handle, sn_nsdl_addr_s *scr_addr_ptr, uint16_t msg_id); +static coap_duplication_info_s *sn_coap_protocol_linked_list_duplication_info_search(const struct coap_s *handle, const sn_nsdl_addr_s *scr_addr_ptr, const 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); +static bool sn_coap_protocol_update_duplicate_package_data(const struct coap_s *handle, const sn_nsdl_addr_s *dst_addr_ptr, const sn_coap_hdr_s *coap_msg_ptr, const int16_t data_size, const uint8_t *dst_packet_data_ptr); #endif + #if SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwising is not enabled, 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, uint8_t *token_ptr, uint8_t token_len, uint32_t block_number); @@ -65,6 +67,7 @@ static void sn_coap_protocol_handle_blockwise_timout(struct coa 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 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 uint8_t 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); 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); @@ -506,23 +509,12 @@ int16_t sn_coap_protocol_build(struct coap_s *handle, sn_nsdl_addr_s *dst_addr_p #endif /* ENABLE_RESENDINGS */ #if SN_COAP_DUPLICATION_MAX_MSGS_COUNT - if (src_coap_msg_ptr->msg_type == COAP_MSG_TYPE_ACKNOWLEDGEMENT && - handle->sn_coap_duplication_buffer_size != 0) { - coap_duplication_info_s* info = sn_coap_protocol_linked_list_duplication_info_search(handle, - dst_addr_ptr, - src_coap_msg_ptr->msg_id); - /* Update package data to duplication info struct if it's not there yet */ - if (info && info->packet_ptr == NULL) { - info->packet_ptr = handle->sn_coap_protocol_malloc(byte_count_built); - if (info->packet_ptr) { - memcpy(info->packet_ptr, dst_packet_data_ptr, byte_count_built); - info->packet_len = byte_count_built; - } else { - tr_error("sn_coap_protocol_build - failed to allocate duplication info!"); - return -4; - } - } + + // copy coap data buffer to duplicate list for resending purposes + if (!sn_coap_protocol_update_duplicate_package_data(handle, dst_addr_ptr, src_coap_msg_ptr, byte_count_built, dst_packet_data_ptr)) { + return -4; } + #endif #if SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwising is not enabled, this part of code will not be compiled */ @@ -725,6 +717,7 @@ sn_coap_hdr_s *sn_coap_protocol_parse(struct coap_s *handle, sn_nsdl_addr_s *src if (response) { /* Check that response has been created */ if (response->packet_ptr) { + tr_debug("sn_coap_protocol_parse - send ack for duplicate message"); response->coap->sn_coap_tx_callback(response->packet_ptr, response->packet_len, response->address, response->param); } @@ -1154,7 +1147,7 @@ static void sn_coap_protocol_linked_list_duplication_info_store(struct coap_s *h } /**************************************************************************//** - * \fn static int8_t sn_coap_protocol_linked_list_duplication_info_search(sn_nsdl_addr_s *addr_ptr, uint16_t msg_id) + * \fn static coap_duplication_info_s *sn_coap_protocol_linked_list_duplication_info_search(const struct coap_s *handle, const sn_nsdl_addr_s *scr_addr_ptr, const uint16_t msg_id) * * \brief Searches stored message from Linked list (Address and Message ID as key) * @@ -1164,8 +1157,8 @@ static void sn_coap_protocol_linked_list_duplication_info_store(struct coap_s *h * \return Return value is 0 when message found and -1 if not found *****************************************************************************/ -static coap_duplication_info_s* sn_coap_protocol_linked_list_duplication_info_search(struct coap_s *handle, - sn_nsdl_addr_s *addr_ptr, uint16_t msg_id) +static coap_duplication_info_s* sn_coap_protocol_linked_list_duplication_info_search(const struct coap_s *handle, + const sn_nsdl_addr_s *addr_ptr, const 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) { @@ -2013,6 +2006,19 @@ static sn_coap_hdr_s *sn_coap_handle_blockwise_message(struct coap_s *handle, sn } sn_coap_builder_2(dst_ack_packet_data_ptr, src_coap_blockwise_ack_msg_ptr, handle->sn_coap_block_data_size); + +#if SN_COAP_DUPLICATION_MAX_MSGS_COUNT + // copy coap data buffer to duplicate list for resending purposes + if (!sn_coap_protocol_update_duplicate_package_data(handle, + src_addr_ptr, + src_coap_blockwise_ack_msg_ptr, + dst_packed_data_needed_mem, + dst_ack_packet_data_ptr)) { + 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); + return NULL; + } +#endif 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); @@ -2509,3 +2515,32 @@ static sn_coap_hdr_s *sn_coap_protocol_copy_header(struct coap_s *handle, sn_coa return destination_header_ptr; } #endif + +#if SN_COAP_DUPLICATION_MAX_MSGS_COUNT +static bool sn_coap_protocol_update_duplicate_package_data(const struct coap_s *handle, + const sn_nsdl_addr_s *dst_addr_ptr, + const sn_coap_hdr_s *coap_msg_ptr, + const int16_t data_size, + const uint8_t *dst_packet_data_ptr) +{ + if (coap_msg_ptr->msg_type == COAP_MSG_TYPE_ACKNOWLEDGEMENT && + handle->sn_coap_duplication_buffer_size != 0) { + coap_duplication_info_s* info = sn_coap_protocol_linked_list_duplication_info_search(handle, + dst_addr_ptr, + coap_msg_ptr->msg_id); + + /* Update package data to duplication info struct if it's not there yet */ + if (info && info->packet_ptr == NULL) { + info->packet_ptr = handle->sn_coap_protocol_malloc(data_size); + if (info->packet_ptr) { + memcpy(info->packet_ptr, dst_packet_data_ptr, data_size); + info->packet_len = data_size; + } else { + tr_error("sn_coap_protocol_update_duplication_package_data - failed to allocate duplication info!"); + return false; + } + } + } + return true; +} +#endif diff --git a/features/nanostack/coap-service/test/coap-service/unittest/stub/mbedtls_stub.c b/features/nanostack/coap-service/test/coap-service/unittest/stub/mbedtls_stub.c index f02fba1f9c2..ba97c62e9fb 100644 --- a/features/nanostack/coap-service/test/coap-service/unittest/stub/mbedtls_stub.c +++ b/features/nanostack/coap-service/test/coap-service/unittest/stub/mbedtls_stub.c @@ -59,7 +59,12 @@ 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_transport( mbedtls_ssl_config *conf, int transport ) +{ + +} + +void mbedtls_ssl_config_init( mbedtls_ssl_config *a ) { } @@ -198,6 +203,16 @@ int mbedtls_ssl_write(mbedtls_ssl_context *a, const unsigned char *b, size_t c) return mbedtls_stub.expected_int; } +int mbedtls_ssl_set_hostname( mbedtls_ssl_context *ssl, const char *hostname ) +{ + return 0; +} + +const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert( const mbedtls_ssl_context *ssl ) +{ + return NULL; +} + //From crt_drbg.h @@ -252,6 +267,18 @@ int mbedtls_x509_crt_parse(mbedtls_x509_crt *a, const unsigned char *b, size_t c return mbedtls_stub.expected_int; } +int mbedtls_x509_crt_info( char *buf, size_t size, const char *prefix, + const mbedtls_x509_crt *crt ) +{ + return 0; +} + +int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix, + uint32_t flags ) +{ + return 0; +} + //From entropy.h void mbedtls_entropy_init(mbedtls_entropy_context *a) { @@ -356,3 +383,6 @@ int mbedtls_ssl_session_reset(mbedtls_ssl_context *ssl) } return mbedtls_stub.expected_int; } + +void mbedtls_strerror( int ret, char *buf, size_t buflen ){ +} diff --git a/features/netsocket/DTLSSocket.cpp b/features/netsocket/DTLSSocket.cpp new file mode 100644 index 00000000000..5bb2f3d8114 --- /dev/null +++ b/features/netsocket/DTLSSocket.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2018 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "DTLSSocket.h" + +#define TRACE_GROUP "TLSS" +#include "mbed-trace/mbed_trace.h" + +// This class requires Mbed TLS SSL/TLS client code +#if defined(MBEDTLS_SSL_CLI_C) + +nsapi_error_t DTLSSocket::connect(const char *host, uint16_t port) +{ + SocketAddress addr; + nsapi_error_t ret; + + ret = _udp_socket.getpeername(&addr); + if (ret != NSAPI_ERROR_NO_CONNECTION) { + return ret; + } + + if (!addr || ret == NSAPI_ERROR_NO_CONNECTION) { + nsapi_error_t err = _udp_socket._stack->gethostbyname(host, &addr); + if (err) { + return NSAPI_ERROR_DNS_FAILURE; + } + + addr.set_port(port); + + set_hostname(host); + _udp_socket.connect(addr); // UDPSocket::connect() cannot fail + } + + return connect(addr); +} + +DTLSSocket::~DTLSSocket() +{ + // Make sure that DTLSSocketWrapper::close() is called before the transport is + // destroyed. + close(); +} + +#endif // MBEDTLS_SSL_CLI_C diff --git a/features/netsocket/DTLSSocket.h b/features/netsocket/DTLSSocket.h new file mode 100644 index 00000000000..d7c8db3de29 --- /dev/null +++ b/features/netsocket/DTLSSocket.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2018 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 DTLSSOCKET_H +#define DTLSSOCKET_H + +#include "DTLSSocketWrapper.h" +#include "SocketAddress.h" +#include "UDPSocket.h" + +// This class requires Mbed TLS SSL/TLS client code +#if defined(MBEDTLS_SSL_CLI_C) || defined(DOXYGEN_ONLY) + +class DTLSSocket : public DTLSSocketWrapper { +public: + /** Create an uninitialized DTLS socket + * + * Must call open to initialize the socket on a network stack. + */ + DTLSSocket() : DTLSSocketWrapper(&_udp_socket) {} + + /** Destroy the DTLSSocket and closes the transport. + */ + virtual ~DTLSSocket(); + + /** Create a socket on a network interface + * + * Creates and opens a socket on the network stack of the given + * network interface. + * If hostname is also given, user is not required to call set_hostname() later. + * + * @param stack Network stack as target for socket + * @param hostname Hostname used for certificate verification + */ + template + DTLSSocket(S *stack, const char *hostname = NULL) : DTLSSocketWrapper(&_udp_socket, hostname) + { + nsapi_error_t ret = _udp_socket.open(stack); + MBED_ASSERT(ret == NSAPI_ERROR_OK); + } + + /** Opens a socket + * + * Creates a network socket on the network stack of the given + * network interface. Not needed if stack is passed to the + * socket's constructor. + * + * @param stack Network stack as target for socket + * @return 0 on success, negative error code on failure + */ + virtual nsapi_error_t open(NetworkStack *stack) + { + return _udp_socket.open(stack); + } + + template + nsapi_error_t open(S *stack) + { + return open(nsapi_create_stack(stack)); + } + + using DTLSSocketWrapper::connect; + + /** Connects TCP socket to a remote host + * + * Initiates a connection to a remote server specified by either + * a domain name or an IP address and a port. + * + * @param host Hostname of the remote host + * @param port Port of the remote host + * @return 0 on success, negative error code on failure + */ + nsapi_error_t connect(const char *host, uint16_t port); + +private: + UDPSocket _udp_socket; +}; + +#endif +#endif diff --git a/features/netsocket/DTLSSocketWrapper.cpp b/features/netsocket/DTLSSocketWrapper.cpp new file mode 100644 index 00000000000..f567e31bbd7 --- /dev/null +++ b/features/netsocket/DTLSSocketWrapper.cpp @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2018 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "DTLSSocketWrapper.h" +#include "platform/Callback.h" +#include "drivers/Timer.h" +#include "events/mbed_events.h" +#include "rtos/Kernel.h" + +#if defined(MBEDTLS_SSL_CLI_C) + +DTLSSocketWrapper::DTLSSocketWrapper(Socket *transport, const char *hostname, control_transport control) : + TLSSocketWrapper(transport, hostname, control), + _int_ms_tick(0), + _timer_event_id(0), + _timer_expired(false) +{ + mbedtls_ssl_conf_transport(get_ssl_config(), MBEDTLS_SSL_TRANSPORT_DATAGRAM); + mbedtls_ssl_set_timer_cb(get_ssl_context(), this, timing_set_delay, timing_get_delay); +} + +void DTLSSocketWrapper::timing_set_delay(void *ctx, uint32_t int_ms, uint32_t fin_ms) +{ + DTLSSocketWrapper *context = static_cast(ctx); + + if (context->_timer_event_id) { + mbed::mbed_event_queue()->cancel(context->_timer_event_id); + context->_timer_expired = false; + } + + if (fin_ms == 0) { + context->_timer_event_id = 0; + return; + } + + context->_int_ms_tick = rtos::Kernel::get_ms_count() + int_ms; + context->_timer_event_id = mbed::mbed_event_queue()->call_in(fin_ms, context, &DTLSSocketWrapper::timer_event); +} + +int DTLSSocketWrapper::timing_get_delay(void *ctx) +{ + DTLSSocketWrapper *context = static_cast(ctx); + + /* See documentation of "typedef int mbedtls_ssl_get_timer_t( void * ctx );" from ssl.h */ + + if (context->_timer_event_id == 0) { + return -1; + } else if (context->_timer_expired) { + return 2; + } else if (context->_int_ms_tick < rtos::Kernel::get_ms_count()) { + return 1; + } else { + return 0; + } +} + +void DTLSSocketWrapper::timer_event(void) +{ + _timer_expired = true; + event(); +} + +#endif /* MBEDTLS_SSL_CLI_C */ diff --git a/features/netsocket/DTLSSocketWrapper.h b/features/netsocket/DTLSSocketWrapper.h new file mode 100644 index 00000000000..7322c2d017c --- /dev/null +++ b/features/netsocket/DTLSSocketWrapper.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2018 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 DTLSSOCKETWRAPPER_H +#define DTLSSOCKETWRAPPER_H + +#include "TLSSocketWrapper.h" + +// This class requires Mbed TLS SSL/TLS client code +#if defined(MBEDTLS_SSL_CLI_C) || defined(DOXYGEN_ONLY) + +class DTLSSocketWrapper : public TLSSocketWrapper { +public: + DTLSSocketWrapper(Socket *transport, const char *hostname = NULL, control_transport control = TRANSPORT_CONNECT_AND_CLOSE); +private: + static void timing_set_delay(void *ctx, uint32_t int_ms, uint32_t fin_ms); + static int timing_get_delay(void *ctx); + void timer_event(); + uint64_t _int_ms_tick; + int _timer_event_id; + bool _timer_expired : 1; +}; + +#endif +#endif diff --git a/features/netsocket/InternetSocket.h b/features/netsocket/InternetSocket.h index 168a10c21eb..c08d90a3b87 100644 --- a/features/netsocket/InternetSocket.h +++ b/features/netsocket/InternetSocket.h @@ -175,6 +175,8 @@ class InternetSocket : public Socket { static const int WRITE_FLAG = 0x2u; static const int FINISHED_FLAG = 0x3u; + friend class DTLSSocket; // Allow DTLSSocket::connect() to do name resolution on the _stack + #endif //!defined(DOXYGEN_ONLY) }; diff --git a/features/netsocket/TCPSocket.cpp b/features/netsocket/TCPSocket.cpp index ce29384de9c..6765d9d0bfa 100644 --- a/features/netsocket/TCPSocket.cpp +++ b/features/netsocket/TCPSocket.cpp @@ -103,6 +103,9 @@ nsapi_error_t TCPSocket::connect(const SocketAddress &address) nsapi_error_t TCPSocket::connect(const char *host, uint16_t port) { SocketAddress address; + if (!_socket) { + return NSAPI_ERROR_NO_SOCKET; + } nsapi_error_t err = _stack->gethostbyname(host, &address); if (err) { return NSAPI_ERROR_DNS_FAILURE; diff --git a/features/netsocket/TCPSocket.h b/features/netsocket/TCPSocket.h index bde477cafbe..c52a5fc0947 100644 --- a/features/netsocket/TCPSocket.h +++ b/features/netsocket/TCPSocket.h @@ -42,8 +42,14 @@ class TCPSocket : public InternetSocket { * network interface. * * @param stack Network stack as target for socket + * + * @deprecated since mbed-os-5.11 */ template + MBED_DEPRECATED_SINCE("mbed-os-5.11", + "The TCPSocket(S *stack) constructor is deprecated." + "It discards the open() call return value." + "Use another constructor and call open() explicitly, instead.") TCPSocket(S *stack) { open(stack); diff --git a/features/netsocket/TLSSocket.cpp b/features/netsocket/TLSSocket.cpp index bf53be6d2c4..bb0c7eb9e4e 100644 --- a/features/netsocket/TLSSocket.cpp +++ b/features/netsocket/TLSSocket.cpp @@ -25,14 +25,17 @@ nsapi_error_t TLSSocket::connect(const char *host, uint16_t port) { - set_hostname(host); - - nsapi_error_t ret = tcp_socket.connect(host, port); - if (ret) { - return ret; + nsapi_error_t ret = NSAPI_ERROR_OK; + if (!is_handshake_started()) { + ret = tcp_socket.connect(host, port); + if (ret == NSAPI_ERROR_OK || ret == NSAPI_ERROR_IN_PROGRESS) { + set_hostname(host); + } + if (ret != NSAPI_ERROR_OK && ret != NSAPI_ERROR_IS_CONNECTED) { + return ret; + } } - - return TLSSocketWrapper::do_handshake(); + return TLSSocketWrapper::start_handshake(ret == NSAPI_ERROR_OK); } TLSSocket::~TLSSocket() @@ -44,4 +47,4 @@ TLSSocket::~TLSSocket() close(); } -#endif // MBEDTLS_SSL_CLI_C \ No newline at end of file +#endif // MBEDTLS_SSL_CLI_C diff --git a/features/netsocket/TLSSocket.h b/features/netsocket/TLSSocket.h index 3a759dc9e9a..f868865f1d2 100644 --- a/features/netsocket/TLSSocket.h +++ b/features/netsocket/TLSSocket.h @@ -28,7 +28,7 @@ #include "mbedtls/error.h" // This class requires Mbed TLS SSL/TLS client code -#if defined(MBEDTLS_SSL_CLI_C) +#if defined(MBEDTLS_SSL_CLI_C) || defined(DOXYGEN_ONLY) /** * \brief TLSSocket a wrapper around TCPSocket for interacting with TLS servers @@ -45,28 +45,15 @@ class TLSSocket : public TLSSocketWrapper { */ virtual ~TLSSocket(); - /** Create a socket on a network interface - * - * Creates and opens a socket on the network stack of the given - * network interface. - * If hostname is also given, user is not required to call set_hostname() later. - * - * @param stack Network stack as target for socket - * @param hostname Hostname used for certificate verification - */ - template - TLSSocket(S *stack, const char *hostname = NULL) : TLSSocketWrapper(&tcp_socket, hostname) - { - nsapi_error_t ret = tcp_socket.open(stack); - MBED_ASSERT(ret == NSAPI_ERROR_OK); - } - /** Opens a socket * * Creates a network socket on the network stack of the given * network interface. Not needed if stack is passed to the * socket's constructor. * + * @note TLSSocket cannot be reopened after closing. It should be destructed to + * clear internal TLS memory structures. + * * @param stack Network stack as target for socket * @return 0 on success, negative error code on failure */ diff --git a/features/netsocket/TLSSocketWrapper.cpp b/features/netsocket/TLSSocketWrapper.cpp index ef080adc9cb..eb75479a841 100644 --- a/features/netsocket/TLSSocketWrapper.cpp +++ b/features/netsocket/TLSSocketWrapper.cpp @@ -16,18 +16,22 @@ */ #include "TLSSocketWrapper.h" +#include "platform/Callback.h" #include "drivers/Timer.h" +#include "events/mbed_events.h" #define TRACE_GROUP "TLSW" #include "mbed-trace/mbed_trace.h" #include "mbedtls/debug.h" #include "mbed_error.h" +#include "Kernel.h" // This class requires Mbed TLS SSL/TLS client code #if defined(MBEDTLS_SSL_CLI_C) TLSSocketWrapper::TLSSocketWrapper(Socket *transport, const char *hostname, control_transport control) : _transport(transport), + _timeout(-1), #ifdef MBEDTLS_X509_CRT_PARSE_C _cacert(NULL), _clicert(NULL), @@ -35,6 +39,7 @@ TLSSocketWrapper::TLSSocketWrapper(Socket *transport, const char *hostname, cont _ssl_conf(NULL), _connect_transport(control == TRANSPORT_CONNECT || control == TRANSPORT_CONNECT_AND_CLOSE), _close_transport(control == TRANSPORT_CLOSE || control == TRANSPORT_CONNECT_AND_CLOSE), + _tls_initialized(false), _handshake_completed(false), _cacert_allocated(false), _clicert_allocated(false), @@ -43,7 +48,9 @@ TLSSocketWrapper::TLSSocketWrapper(Socket *transport, const char *hostname, cont mbedtls_entropy_init(&_entropy); mbedtls_ctr_drbg_init(&_ctr_drbg); mbedtls_ssl_init(&_ssl); +#if defined(MBEDTLS_X509_CRT_PARSE_C) mbedtls_pk_init(&_pkctx); +#endif if (hostname) { set_hostname(hostname); @@ -58,9 +65,8 @@ TLSSocketWrapper::~TLSSocketWrapper() mbedtls_entropy_free(&_entropy); mbedtls_ctr_drbg_free(&_ctr_drbg); mbedtls_ssl_free(&_ssl); +#if defined(MBEDTLS_X509_CRT_PARSE_C) mbedtls_pk_free(&_pkctx); - -#ifdef MBEDTLS_X509_CRT_PARSE_C set_own_cert(NULL); set_ca_chain(NULL); #endif @@ -114,7 +120,7 @@ nsapi_error_t TLSSocketWrapper::set_client_cert_key(const char *client_cert_pem, nsapi_error_t TLSSocketWrapper::set_client_cert_key(const void *client_cert, size_t client_cert_len, const void *client_private_key_pem, size_t client_private_key_len) { -#if !defined(MBEDTLS_X509_CRT_PARSE_C) +#if !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_PK_C) return NSAPI_ERROR_UNSUPPORTED; #else @@ -140,29 +146,34 @@ nsapi_error_t TLSSocketWrapper::set_client_cert_key(const void *client_cert, siz } -nsapi_error_t TLSSocketWrapper::do_handshake() +nsapi_error_t TLSSocketWrapper::start_handshake(bool first_call) { - nsapi_error_t _error; const char DRBG_PERS[] = "mbed TLS client"; + int ret; if (!_transport) { return NSAPI_ERROR_NO_SOCKET; } - _transport->set_blocking(true); + if (_tls_initialized) { + return continue_handshake(); + } + +#ifdef MBEDTLS_X509_CRT_PARSE_C + tr_info("Starting TLS handshake with %s", _ssl.hostname); +#else + tr_info("Starting TLS handshake"); +#endif /* * Initialize TLS-related stuf. */ - int ret; if ((ret = mbedtls_ctr_drbg_seed(&_ctr_drbg, mbedtls_entropy_func, &_entropy, (const unsigned char *) DRBG_PERS, sizeof(DRBG_PERS))) != 0) { print_mbedtls_error("mbedtls_crt_drbg_init", ret); - _error = ret; - return _error; + return NSAPI_ERROR_PARAMETER; } - tr_info("mbedtls_ssl_conf_rng()"); mbedtls_ssl_conf_rng(get_ssl_config(), mbedtls_ctr_drbg_random, &_ctr_drbg); @@ -172,29 +183,62 @@ nsapi_error_t TLSSocketWrapper::do_handshake() mbedtls_debug_set_threshold(MBED_CONF_TLS_SOCKET_DEBUG_LEVEL); #endif - tr_info("mbedtls_ssl_setup()"); + tr_debug("mbedtls_ssl_setup()"); if ((ret = mbedtls_ssl_setup(&_ssl, get_ssl_config())) != 0) { print_mbedtls_error("mbedtls_ssl_setup", ret); - _error = ret; - return _error; + return NSAPI_ERROR_PARAMETER; } + _transport->set_blocking(false); + _transport->sigio(mbed::callback(this, &TLSSocketWrapper::event)); mbedtls_ssl_set_bio(&_ssl, this, ssl_send, ssl_recv, NULL); -#ifdef MBEDTLS_X509_CRT_PARSE_C - /* Start the handshake, the rest will be done in onReceive() */ - tr_info("Starting TLS handshake with %s", _ssl.hostname); -#else - tr_info("Starting TLS handshake"); -#endif + _tls_initialized = true; + + ret = continue_handshake(); + if (first_call) { + if (ret == NSAPI_ERROR_ALREADY) { + ret = NSAPI_ERROR_IN_PROGRESS; // If first call should return IN_PROGRESS + } + if (ret == NSAPI_ERROR_IS_CONNECTED) { + ret = NSAPI_ERROR_OK; // If we happened to complete the request on the first call, return OK. + } + } + return ret; +} + +nsapi_error_t TLSSocketWrapper::continue_handshake() +{ + int ret; + + if (_handshake_completed) { + return NSAPI_ERROR_IS_CONNECTED; + } + + if (!_tls_initialized) { + return NSAPI_ERROR_NO_CONNECTION; + } - do { + while (true) { ret = mbedtls_ssl_handshake(&_ssl); - } while (ret != 0 && (ret == MBEDTLS_ERR_SSL_WANT_READ || - ret == MBEDTLS_ERR_SSL_WANT_WRITE)); + if (_timeout && (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE)) { + uint32_t flag; + flag = _event_flag.wait_any(1, _timeout); + if (flag & osFlagsError) { + break; + } + } else { + break; + } + } + if (ret < 0) { print_mbedtls_error("mbedtls_ssl_handshake", ret); - return ret; + if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE) { + return NSAPI_ERROR_ALREADY; + } else { + return NSAPI_ERROR_AUTH_FAILURE; + } } #ifdef MBEDTLS_X509_CRT_PARSE_C @@ -225,8 +269,7 @@ nsapi_error_t TLSSocketWrapper::do_handshake() #endif _handshake_completed = true; - - return 0; + return NSAPI_ERROR_IS_CONNECTED; } @@ -239,15 +282,42 @@ nsapi_error_t TLSSocketWrapper::send(const void *data, nsapi_size_t size) } tr_debug("send %d", size); - ret = mbedtls_ssl_write(&_ssl, (const unsigned char *) data, size); + while (true) { + if (!_handshake_completed) { + ret = continue_handshake(); + if (ret != NSAPI_ERROR_IS_CONNECTED) { + if (ret == NSAPI_ERROR_ALREADY) { + ret = NSAPI_ERROR_NO_CONNECTION; + } + return ret; + } + } + + ret = mbedtls_ssl_write(&_ssl, (const unsigned char *) data, size); + + if (_timeout == 0) { + break; + } else if (ret == MBEDTLS_ERR_SSL_WANT_WRITE || ret == MBEDTLS_ERR_SSL_WANT_READ) { + uint32_t flag; + flag = _event_flag.wait_any(1, _timeout); + if (flag & osFlagsError) { + // Timeout break + break; + } + } else { + break; + } + } if (ret == MBEDTLS_ERR_SSL_WANT_WRITE || ret == MBEDTLS_ERR_SSL_WANT_READ) { // translate to socket error return NSAPI_ERROR_WOULD_BLOCK; } + if (ret < 0) { print_mbedtls_error("mbedtls_ssl_write", ret); + return NSAPI_ERROR_DEVICE_ERROR; } return ret; // Assume "non negative errorcode" to be propagated from Socket layer } @@ -266,15 +336,39 @@ nsapi_size_or_error_t TLSSocketWrapper::recv(void *data, nsapi_size_t size) return NSAPI_ERROR_NO_SOCKET; } - ret = mbedtls_ssl_read(&_ssl, (unsigned char *) data, size); + while (true) { + if (!_handshake_completed) { + ret = continue_handshake(); + if (ret != NSAPI_ERROR_IS_CONNECTED) { + if (ret == NSAPI_ERROR_ALREADY) { + ret = NSAPI_ERROR_NO_CONNECTION; + } + return ret; + } + } + ret = mbedtls_ssl_read(&_ssl, (unsigned char *) data, size); + + if (_timeout == 0) { + break; + } else if (ret == MBEDTLS_ERR_SSL_WANT_WRITE || ret == MBEDTLS_ERR_SSL_WANT_READ) { + uint32_t flag; + flag = _event_flag.wait_any(1, _timeout); + if (flag & osFlagsError) { + // Timeout break + break; + } + } else { + break; + } + } if (ret == MBEDTLS_ERR_SSL_WANT_WRITE || ret == MBEDTLS_ERR_SSL_WANT_READ) { // translate to socket error return NSAPI_ERROR_WOULD_BLOCK; } else if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { /* MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY is not considered as error. - * Just ignre here. Once connection is closed, mbedtls_ssl_read() + * Just ignore here. Once connection is closed, mbedtls_ssl_read() * will return 0. */ return 0; @@ -390,7 +484,7 @@ int TLSSocketWrapper::ssl_send(void *ctx, const unsigned char *buf, size_t len) return size; } -#ifdef MBEDTLS_X509_CRT_PARSE_C +#if defined(MBEDTLS_X509_CRT_PARSE_C) mbedtls_x509_crt *TLSSocketWrapper::get_own_cert() { @@ -427,7 +521,7 @@ void TLSSocketWrapper::set_ca_chain(mbedtls_x509_crt *crt) _cacert_allocated = false; } _cacert = crt; - tr_info("mbedtls_ssl_conf_ca_chain()"); + tr_debug("mbedtls_ssl_conf_ca_chain()"); mbedtls_ssl_conf_ca_chain(get_ssl_config(), _cacert, NULL); } @@ -441,7 +535,6 @@ mbedtls_ssl_config *TLSSocketWrapper::get_ssl_config() mbedtls_ssl_config_init(_ssl_conf); _ssl_conf_allocated = true; - tr_info("mbedtls_ssl_config_defaults()"); if ((ret = mbedtls_ssl_config_defaults(_ssl_conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, @@ -454,7 +547,6 @@ mbedtls_ssl_config *TLSSocketWrapper::get_ssl_config() /* It is possible to disable authentication by passing * MBEDTLS_SSL_VERIFY_NONE in the call to mbedtls_ssl_conf_authmode() */ - tr_info("mbedtls_ssl_conf_authmode()"); mbedtls_ssl_conf_authmode(get_ssl_config(), MBEDTLS_SSL_VERIFY_REQUIRED); } return _ssl_conf; @@ -470,6 +562,11 @@ void TLSSocketWrapper::set_ssl_config(mbedtls_ssl_config *conf) _ssl_conf = conf; } +mbedtls_ssl_context *TLSSocketWrapper::get_ssl_context() +{ + return &_ssl; +} + nsapi_error_t TLSSocketWrapper::close() { if (!_transport) { @@ -502,17 +599,18 @@ nsapi_error_t TLSSocketWrapper::close() nsapi_error_t TLSSocketWrapper::connect(const SocketAddress &address) { + nsapi_error_t ret = NSAPI_ERROR_OK; if (!_transport) { return NSAPI_ERROR_NO_SOCKET; } - if (_connect_transport) { - nsapi_error_t ret = _transport->connect(address); - if (ret) { + if (!is_handshake_started() && _connect_transport) { + ret = _transport->connect(address); + if (ret && ret != NSAPI_ERROR_IS_CONNECTED) { return ret; } } - return do_handshake(); + return start_handshake(ret == NSAPI_ERROR_OK); } nsapi_error_t TLSSocketWrapper::bind(const SocketAddress &address) @@ -525,18 +623,17 @@ nsapi_error_t TLSSocketWrapper::bind(const SocketAddress &address) void TLSSocketWrapper::set_blocking(bool blocking) { - if (!_transport) { - return; - } - _transport->set_blocking(blocking); + set_timeout(blocking ? -1 : 0); } void TLSSocketWrapper::set_timeout(int timeout) { - if (!_transport) { - return; + _timeout = timeout; + if (!is_handshake_started() && timeout != -1 && _connect_transport) { + // If we have not yet connected the transport, we need to modify its blocking mode as well. + // After connection is initiated, it is already set to non blocking mode + _transport->set_timeout(timeout); } - _transport->set_timeout(timeout); } void TLSSocketWrapper::sigio(mbed::Callback func) @@ -544,8 +641,8 @@ void TLSSocketWrapper::sigio(mbed::Callback func) if (!_transport) { return; } - // Allow sigio() to propagate to upper level and handle errors on recv() and send() - _transport->sigio(func); + _sigio = func; + _transport->sigio(mbed::callback(this, &TLSSocketWrapper::event)); } nsapi_error_t TLSSocketWrapper::setsockopt(int level, int optname, const void *optval, unsigned optlen) @@ -577,6 +674,20 @@ nsapi_error_t TLSSocketWrapper::listen(int) return NSAPI_ERROR_UNSUPPORTED; } +void TLSSocketWrapper::event() +{ + _event_flag.set(1); + if (_sigio) { + _sigio(); + } +} + +bool TLSSocketWrapper::is_handshake_started() const +{ + return _tls_initialized; +} + + nsapi_error_t TLSSocketWrapper::getpeername(SocketAddress *address) { if (!_handshake_completed) { diff --git a/features/netsocket/TLSSocketWrapper.h b/features/netsocket/TLSSocketWrapper.h index 60b86c96761..bffdd97d2bc 100644 --- a/features/netsocket/TLSSocketWrapper.h +++ b/features/netsocket/TLSSocketWrapper.h @@ -19,7 +19,8 @@ #define _MBED_HTTPS_TLS_SOCKET_WRAPPER_H_ #include "netsocket/Socket.h" - +#include "rtos/EventFlags.h" +#include "platform/Callback.h" #include "mbedtls/platform.h" #include "mbedtls/ssl.h" #include "mbedtls/entropy.h" @@ -27,7 +28,7 @@ #include "mbedtls/error.h" // This class requires Mbed TLS SSL/TLS client code -#if defined(MBEDTLS_SSL_CLI_C) +#if defined(MBEDTLS_SSL_CLI_C) || defined(DOXYGEN_ONLY) /** * \brief TLSSocket a wrapper around Socket for interacting with TLS servers @@ -134,7 +135,7 @@ class TLSSocketWrapper : public Socket { virtual nsapi_error_t listen(int backlog = 1); virtual nsapi_error_t getpeername(SocketAddress *address); -#if defined(MBEDTLS_X509_CRT_PARSE_C) || defined(DOXYGEN) +#if defined(MBEDTLS_X509_CRT_PARSE_C) || defined(DOXYGEN_ONLY) /** Get own certificate directly from Mbed TLS * @return internal Mbed TLS X509 structure */ @@ -167,12 +168,12 @@ class TLSSocketWrapper : public Socket { */ void set_ssl_config(mbedtls_ssl_config *conf); -protected: - /** - * Helper for pretty-printing mbed TLS error codes + /** Get internal Mbed TLS contect structure. + * @return SSL context */ - static void print_mbedtls_error(const char *name, int err); + mbedtls_ssl_context *get_ssl_context(); +protected: /** Initiates TLS Handshake * * Initiates a TLS handshake to a remote peer @@ -181,9 +182,28 @@ class TLSSocketWrapper : public Socket { * Root CA certification must be set by set_ssl_ca_pem() before * call this function. * + * For non-blocking purposes, this functions needs to know whether this + * was a first call to Socket::connect() API so that NSAPI_ERROR_INPROGRESS + * does not happen twice. + * + * @parameter first_call is this a first call to Socket::connect() API. * @return 0 on success, negative error code on failure */ - nsapi_error_t do_handshake(); + nsapi_error_t start_handshake(bool first_call); + + bool is_handshake_started() const; + + void event(); + + + +private: + /** Continue already initialised handshake */ + nsapi_error_t continue_handshake(); + /** + * Helper for pretty-printing mbed TLS error codes + */ + static void print_mbedtls_error(const char *name, int err); #if MBED_CONF_TLS_SOCKET_DEBUG_LEVEL > 0 /** @@ -211,13 +231,17 @@ class TLSSocketWrapper : public Socket { */ static int ssl_send(void *ctx, const unsigned char *buf, size_t len); -private: mbedtls_ssl_context _ssl; +#ifdef MBEDTLS_X509_CRT_PARSE_C mbedtls_pk_context _pkctx; +#endif mbedtls_ctr_drbg_context _ctr_drbg; mbedtls_entropy_context _entropy; + rtos::EventFlags _event_flag; + mbed::Callback _sigio; Socket *_transport; + int _timeout; #ifdef MBEDTLS_X509_CRT_PARSE_C mbedtls_x509_crt *_cacert; @@ -227,6 +251,7 @@ class TLSSocketWrapper : public Socket { bool _connect_transport: 1; bool _close_transport: 1; + bool _tls_initialized: 1; bool _handshake_completed: 1; bool _cacert_allocated: 1; bool _clicert_allocated: 1; diff --git a/features/netsocket/UDPSocket.h b/features/netsocket/UDPSocket.h index 49a90fd75a9..44025389d22 100644 --- a/features/netsocket/UDPSocket.h +++ b/features/netsocket/UDPSocket.h @@ -41,8 +41,13 @@ class UDPSocket : public InternetSocket { * * @tparam S Type of the Network stack. * @param stack Network stack as target for socket. + * @deprecated since mbed-os-5.11 */ template + MBED_DEPRECATED_SINCE("mbed-os-5.11", + "The UDPSocket(S *stack) constructor is deprecated" + "It discards the open() call return value." + "Use another constructor and call open() explicitly, instead.") UDPSocket(S *stack) { open(stack); diff --git a/features/netsocket/nsapi.h b/features/netsocket/nsapi.h index a9b41932ec7..8e91c4afb41 100644 --- a/features/netsocket/nsapi.h +++ b/features/netsocket/nsapi.h @@ -40,9 +40,12 @@ #include "netsocket/UDPSocket.h" #include "netsocket/TCPSocket.h" #include "netsocket/TCPServer.h" +#include "netsocket/TLSSocketWrapper.h" +#include "netsocket/DTLSSocketWrapper.h" #include "netsocket/TLSSocket.h" +#include "netsocket/DTLSSocket.h" -#endif +#endif // __cplusplus #endif diff --git a/features/storage/TESTS/blockdevice/general_block_device/main.cpp b/features/storage/TESTS/blockdevice/general_block_device/main.cpp index 1dde9d67fbc..d177d51a39c 100644 --- a/features/storage/TESTS/blockdevice/general_block_device/main.cpp +++ b/features/storage/TESTS/blockdevice/general_block_device/main.cpp @@ -24,6 +24,7 @@ #include "mbed_trace.h" #include #include +#include "BufferedBlockDevice.h" using namespace utest::v1; @@ -99,10 +100,7 @@ void test_random_program_read_erase() BlockDevice *block_device = BlockDevice::get_default_instance(); - if (!block_device) { - utest_printf("\nno block device found.\n"); - return; - } + TEST_SKIP_UNLESS_MESSAGE(block_device != NULL, "\nno block device found.\n"); int err = block_device->init(); TEST_ASSERT_EQUAL(0, err); @@ -173,10 +171,7 @@ void test_multi_threads() BlockDevice *block_device = BlockDevice::get_default_instance(); - if (!block_device) { - utest_printf("\nno block device found.\n"); - return; - } + TEST_SKIP_UNLESS_MESSAGE(block_device != NULL, "\nno block device found.\n"); int err = block_device->init(); TEST_ASSERT_EQUAL(0, err); @@ -297,7 +292,7 @@ void test_contiguous_erase_write_read() // - Tests contiguous erase // 2. Write smaller memory area // - Tests contiguous sector writes - // 3. Rerun step 2 for whole erase region + // 3. Return step 2 for whole erase region BlockDevice *block_device = BlockDevice::get_default_instance(); TEST_SKIP_UNLESS_MESSAGE(block_device != NULL, "\nno block device found.\n"); @@ -326,7 +321,8 @@ void test_contiguous_erase_write_read() if (write_read_buf_size < program_size * 2) { write_read_buf_size = program_size * 2; // going over 10k } - bd_size_t contiguous_write_read_blocks_per_region = write_read_buf_size / program_size; // 2 is minimum to test contiguous write + bd_size_t contiguous_write_read_blocks_per_region = write_read_buf_size / + program_size; // 2 is minimum to test contiguous write write_read_buf_size = contiguous_write_read_blocks_per_region * program_size; utest_printf("\ncontiguous_write_read_blocks_per_region=%" PRIu64, contiguous_write_read_blocks_per_region); utest_printf("\nwrite_read_buf_size=%" PRIu64, write_read_buf_size); @@ -365,7 +361,8 @@ void test_contiguous_erase_write_read() for (size_t i = 0; i < write_read_buf_size; i++) { write_read_buf[i] = (uint8_t)rand(); } - utest_printf("\npre-filling memory, from 0x%" PRIx64 " of size 0x%" PRIx64, start_address + offset, write_read_buf_size); + utest_printf("\npre-filling memory, from 0x%" PRIx64 " of size 0x%" PRIx64, start_address + offset, + write_read_buf_size); err = block_device->program((const void *)write_read_buf, start_address + offset, write_read_buf_size); TEST_ASSERT_EQUAL(0, err); } @@ -420,6 +417,61 @@ void test_contiguous_erase_write_read() TEST_ASSERT_EQUAL(0, err); } +void test_program_read_small_data_sizes() +{ + utest_printf("\nTest program-read small data sizes, from 1 to 7 bytes..\n"); + + BlockDevice *bd = BlockDevice::get_default_instance(); + + TEST_SKIP_UNLESS_MESSAGE(bd != NULL, "\nno block device found.\n"); + + // use BufferedBlockDevice for better handling of block devices program and read + BufferedBlockDevice *block_device = new BufferedBlockDevice(bd); + + // BlockDevice initialization + int err = block_device->init(); + TEST_ASSERT_EQUAL(0, err); + + const char write_buffer[] = "1234567"; + char read_buffer[7] = {}; + + bd_size_t erase_size = block_device->get_erase_size(); + bd_size_t program_size = block_device->get_program_size(); + TEST_ASSERT(program_size > 0); + + // Determine starting address + bd_addr_t start_address = 0; + + for (int i = 1; i <= 7; i++) { + err = block_device->erase(start_address, erase_size); + TEST_ASSERT_EQUAL(0, err); + + err = block_device->program((const void *)write_buffer, start_address, i); + TEST_ASSERT_EQUAL(0, err); + + err = block_device->sync(); + TEST_ASSERT_EQUAL(0, err); + + err = block_device->read(read_buffer, start_address, i); + TEST_ASSERT_EQUAL(0, err); + + err = memcmp(write_buffer, read_buffer, i); + TEST_ASSERT_EQUAL(0, err); + } + + // BlockDevice deinitialization + err = block_device->deinit(); + TEST_ASSERT_EQUAL(0, err); + + delete block_device; +} + +utest::v1::status_t greentea_failure_handler(const Case *const source, const failure_t reason) +{ + greentea_case_failure_abort_handler(source, reason); + return STATUS_CONTINUE; +} + // Test setup utest::v1::status_t test_setup(const size_t number_of_cases) { @@ -428,10 +480,11 @@ utest::v1::status_t test_setup(const size_t number_of_cases) } Case cases[] = { - Case("Testing read write random blocks", test_random_program_read_erase), - Case("Testing Multi Threads Erase Program Read", test_multi_threads), - Case("Testing contiguous erase, write and read", test_contiguous_erase_write_read), - Case("Test BlockDevice::get_erase_value()", test_get_erase_value) + Case("Testing read write random blocks", test_random_program_read_erase, greentea_failure_handler), + Case("Testing multi threads erase program read", test_multi_threads, greentea_failure_handler), + Case("Testing contiguous erase, write and read", test_contiguous_erase_write_read, greentea_failure_handler), + Case("Testing BlockDevice::get_erase_value()", test_get_erase_value, greentea_failure_handler), + Case("Testing program read small data sizes", test_program_read_small_data_sizes, greentea_failure_handler) }; Specification specification(test_setup, cases); diff --git a/targets/TARGET_Realtek/TARGET_AMEBA/sdk/common/api/wifi/wifi_ind.h b/targets/TARGET_Realtek/TARGET_AMEBA/sdk/common/api/wifi/wifi_ind.h index b3225f2f43e..2c5f042d091 100644 --- a/targets/TARGET_Realtek/TARGET_AMEBA/sdk/common/api/wifi/wifi_ind.h +++ b/targets/TARGET_Realtek/TARGET_AMEBA/sdk/common/api/wifi/wifi_ind.h @@ -32,6 +32,10 @@ #include "wifi_conf.h" +#ifdef __cplusplus + extern "C" { +#endif + typedef void (*rtw_event_handler_t)(char *buf, int buf_len, int flags, void* handler_user_data ); typedef struct @@ -90,6 +94,10 @@ extern void wifi_reg_event_handler(unsigned int event_cmds, rtw_event_handler_t */ extern void wifi_unreg_event_handler(unsigned int event_cmds, rtw_event_handler_t handler_func); +#ifdef __cplusplus + } +#endif + /*\@}*/ #endif //_WIFI_INDICATE_H