diff --git a/UNITTESTS/features/cellular/framework/AT/at_cellularcontext/at_cellularcontexttest.cpp b/UNITTESTS/features/cellular/framework/AT/at_cellularcontext/at_cellularcontexttest.cpp index a8acae727c3d..451c3a571cc0 100644 --- a/UNITTESTS/features/cellular/framework/AT/at_cellularcontext/at_cellularcontexttest.cpp +++ b/UNITTESTS/features/cellular/framework/AT/at_cellularcontext/at_cellularcontexttest.cpp @@ -537,7 +537,7 @@ TEST_F(TestAT_CellularContext, connect_disconnect_sync) ATHandler_stub::read_string_index = 2; ASSERT_EQ(ctx1.connect(), NSAPI_ERROR_OK); - ASSERT_EQ(network_cb_count, 5); + ASSERT_EQ(network_cb_count, 4); ASSERT_EQ(ctx1.disconnect(), NSAPI_ERROR_OK); ATHandler_stub::resp_info_true_counter = 1; @@ -704,7 +704,7 @@ TEST_F(TestAT_CellularContext, connect_disconnect_async) data.status_data = CellularNetwork::Attached; ctx1.cellular_callback((nsapi_event_t)CellularAttachNetwork, (intptr_t)&data); - ASSERT_EQ(network_cb_count, 5); + ASSERT_EQ(network_cb_count, 4); ASSERT_EQ(ctx1.connect(), NSAPI_ERROR_IS_CONNECTED); EXPECT_TRUE(ctx1.is_connected() == true); ASSERT_EQ(ctx1.disconnect(), NSAPI_ERROR_NO_MEMORY); diff --git a/UNITTESTS/features/cellular/framework/AT/at_cellularstack/at_cellularstacktest.cpp b/UNITTESTS/features/cellular/framework/AT/at_cellularstack/at_cellularstacktest.cpp index 214ab1c8928b..57ad8519f526 100644 --- a/UNITTESTS/features/cellular/framework/AT/at_cellularstack/at_cellularstacktest.cpp +++ b/UNITTESTS/features/cellular/framework/AT/at_cellularstack/at_cellularstacktest.cpp @@ -175,7 +175,7 @@ TEST_F(TestAT_CellularStack, test_AT_CellularStack_get_ip_address) ATHandler at(&fh1, que, 0, ","); MyStack st(at, 0, IPV6_STACK); - EXPECT_EQ(strlen(st.get_ip_address()), 0); + EXPECT_TRUE(st.get_ip_address() == NULL); char table[] = "1.2.3.4.5.65.7.8.9.10.11\0"; ATHandler_stub::ssize_value = -1; diff --git a/UNITTESTS/features/cellular/framework/AT/at_cellularstack/unittest.cmake b/UNITTESTS/features/cellular/framework/AT/at_cellularstack/unittest.cmake index 2f1a243e02c8..f0525045d708 100644 --- a/UNITTESTS/features/cellular/framework/AT/at_cellularstack/unittest.cmake +++ b/UNITTESTS/features/cellular/framework/AT/at_cellularstack/unittest.cmake @@ -28,4 +28,5 @@ set(unittest-test-sources stubs/NetworkStack_stub.cpp stubs/SocketAddress_stub.cpp stubs/mbed_assert_stub.c + stubs/ThisThread_stub.cpp ) diff --git a/features/cellular/framework/API/CellularContext.h b/features/cellular/framework/API/CellularContext.h index 7f5c1ceb40b4..ab4f9bd99daf 100644 --- a/features/cellular/framework/API/CellularContext.h +++ b/features/cellular/framework/API/CellularContext.h @@ -344,6 +344,12 @@ class CellularContext : public CellularInterface { */ virtual void do_connect(); + /** After we have connected successfully we must check that we have a valid IP address. + * Some modems/networks don't give IP address right after connect so we must poll it for a while. + * Whether we get IP address or not, this methods sends NSAPI_STATUS_GLOBAL_UP to application. + */ + void validate_ip_address(); + // member variables needed in target override methods NetworkStack *_stack; // must be pointer because of PPP pdp_type_t _pdp_type; diff --git a/features/cellular/framework/AT/AT_CellularContext.cpp b/features/cellular/framework/AT/AT_CellularContext.cpp index 04dbe60cb562..498a44e32aec 100644 --- a/features/cellular/framework/AT/AT_CellularContext.cpp +++ b/features/cellular/framework/AT/AT_CellularContext.cpp @@ -587,7 +587,6 @@ void AT_CellularContext::do_connect() } #else _is_connected = true; - call_network_cb(NSAPI_STATUS_GLOBAL_UP); #endif } diff --git a/features/cellular/framework/AT/AT_CellularStack.cpp b/features/cellular/framework/AT/AT_CellularStack.cpp index 31417a98d82e..d2420075306b 100644 --- a/features/cellular/framework/AT/AT_CellularStack.cpp +++ b/features/cellular/framework/AT/AT_CellularStack.cpp @@ -18,6 +18,7 @@ #include "AT_CellularStack.h" #include "CellularUtil.h" #include "CellularLog.h" +#include "ThisThread.h" using namespace mbed_cellular_util; using namespace mbed; @@ -54,41 +55,31 @@ int AT_CellularStack::find_socket_index(nsapi_socket_t handle) /** NetworkStack */ - const char *AT_CellularStack::get_ip_address() { _at.lock(); _at.cmd_start_stop("+CGPADDR", "=", "%d", _cid); - _at.resp_start("+CGPADDR:"); + int len = -1; if (_at.info_resp()) { - _at.skip_param(); - int len = _at.read_string(_ip, NSAPI_IPv4_SIZE); - if (len == -1) { - _ip[0] = '\0'; - _at.resp_stop(); - _at.unlock(); - // no IPV4 address, return - return NULL; - } + len = _at.read_string(_ip, NSAPI_IPv4_SIZE); - // in case stack type is not IPV4 only, try to look also for IPV6 address - if (_stack_type != IPV4_STACK) { + if (len != -1 && _stack_type != IPV4_STACK) { + // in case stack type is not IPV4 only, try to look also for IPV6 address (void)_at.read_string(_ip, PDP_IPV6_SIZE); } } - _at.resp_stop(); _at.unlock(); // we have at least IPV4 address convert_ipv6(_ip); - return _ip; + return len != -1 ? _ip : NULL; } nsapi_error_t AT_CellularStack::socket_stack_init() diff --git a/features/cellular/framework/device/CellularContext.cpp b/features/cellular/framework/device/CellularContext.cpp index 0b4ea68bd949..7b7f2b330b07 100644 --- a/features/cellular/framework/device/CellularContext.cpp +++ b/features/cellular/framework/device/CellularContext.cpp @@ -87,6 +87,30 @@ void CellularContext::set_authentication_type(AuthenticationType type) _authentication_type = type; } +void CellularContext::validate_ip_address() +{ + const int IP_MAX_TRIES = 10; // maximum of 2 seconds as we wait 200ms between tries + const int IP_WAIT_INTERVAL = 200; // 200 ms between retries + const char *ip = NULL; + int i = 0; + + while (1) { + ip = get_ip_address(); + if (ip || i >= IP_MAX_TRIES) { + if (ip == NULL) { + tr_warning("Connected but no local ip address"); + } else { + tr_info("Cellular local IP: %s", ip); + } + break; + } + rtos::ThisThread::sleep_for(IP_WAIT_INTERVAL); + i++; + } + + call_network_cb(NSAPI_STATUS_GLOBAL_UP); +} + void CellularContext::do_connect_with_retry() { if (_cb_data.final_try) { @@ -97,6 +121,9 @@ void CellularContext::do_connect_with_retry() } do_connect(); if (_cb_data.error == NSAPI_ERROR_OK) { + // Some modems don't get the ip address right after connect so we must + // validate it but even if we don't get ip we still send NSAPI_STATUS_GLOBAL_UP + validate_ip_address(); return; }