Skip to content

Commit

Permalink
Cellular: notify global up after we have IP address
Browse files Browse the repository at this point in the history
CellularContext now tries to get an IP address after connect and before
sending NSAPI_STATUS_GLOBAL_UP. Even if we don't the IP address from
the modem we will send NSAPI_STATUS_GLOBAL_UP and return success.
Modem has an ip address but for some reason some modems don't
give it to us.
  • Loading branch information
Teppo Järvelin committed Aug 14, 2019
1 parent ce36104 commit 84bb815
Show file tree
Hide file tree
Showing 7 changed files with 43 additions and 19 deletions.
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
Expand Up @@ -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;
Expand Down
Expand Up @@ -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
)
6 changes: 6 additions & 0 deletions features/cellular/framework/API/CellularContext.h
Expand Up @@ -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;
Expand Down
1 change: 0 additions & 1 deletion features/cellular/framework/AT/AT_CellularContext.cpp
Expand Up @@ -587,7 +587,6 @@ void AT_CellularContext::do_connect()
}
#else
_is_connected = true;
call_network_cb(NSAPI_STATUS_GLOBAL_UP);
#endif
}

Expand Down
21 changes: 6 additions & 15 deletions features/cellular/framework/AT/AT_CellularStack.cpp
Expand Up @@ -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;
Expand Down Expand Up @@ -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()
Expand Down
27 changes: 27 additions & 0 deletions features/cellular/framework/device/CellularContext.cpp
Expand Up @@ -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) {
Expand All @@ -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;
}

Expand Down

0 comments on commit 84bb815

Please sign in to comment.