mirror of https://github.com/ARMmbed/mbed-os.git
Cellular: notify global up after we have IP address
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.pull/11220/head
parent
ce36104ab3
commit
6a17d74b55
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -21,7 +21,7 @@ using namespace mbed;
|
|||
|
||||
AT_CellularContext::AT_CellularContext(ATHandler &at, CellularDevice *device, const char *apn, bool cp_req, bool nonip_req) :
|
||||
AT_CellularBase(at), _is_connected(false),
|
||||
_current_op(OP_INVALID), _fh(0), _cp_req(cp_req), _nonip_req(nonip_req), _cp_in_use(false)
|
||||
_current_op(OP_INVALID), _fh(0), _cp_req(cp_req)
|
||||
{
|
||||
_stack = NULL;
|
||||
_pdp_type = DEFAULT_PDP_TYPE;
|
||||
|
@ -43,6 +43,8 @@ AT_CellularContext::AT_CellularContext(ATHandler &at, CellularDevice *device, co
|
|||
_is_blocking = true;
|
||||
_device = device;
|
||||
_nw = NULL;
|
||||
_nonip_req = nonip_req;
|
||||
_cp_in_use = false;
|
||||
}
|
||||
|
||||
AT_CellularContext::~AT_CellularContext()
|
||||
|
|
|
@ -344,6 +344,11 @@ protected: // Device specific implementations might need these so protected
|
|||
*/
|
||||
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.
|
||||
*/
|
||||
void validate_ip_address();
|
||||
|
||||
// member variables needed in target override methods
|
||||
NetworkStack *_stack; // must be pointer because of PPP
|
||||
pdp_type_t _pdp_type;
|
||||
|
@ -368,6 +373,10 @@ protected: // Device specific implementations might need these so protected
|
|||
CellularDevice *_device;
|
||||
CellularNetwork *_nw;
|
||||
bool _is_blocking;
|
||||
// flag indicating if Non-IP context was requested to be setup
|
||||
bool _nonip_req;
|
||||
// tells if CCIOTOPTI received green from network for CP optimization use
|
||||
bool _cp_in_use;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -48,10 +48,10 @@ using namespace mbed;
|
|||
using namespace rtos;
|
||||
|
||||
AT_CellularContext::AT_CellularContext(ATHandler &at, CellularDevice *device, const char *apn, bool cp_req, bool nonip_req) :
|
||||
AT_CellularBase(at), _is_connected(false), _current_op(OP_INVALID), _fh(0), _cp_req(cp_req),
|
||||
_nonip_req(nonip_req), _cp_in_use(false)
|
||||
AT_CellularBase(at), _is_connected(false), _current_op(OP_INVALID), _fh(0), _cp_req(cp_req)
|
||||
{
|
||||
tr_info("New CellularContext %s (%p)", apn ? apn : "", this);
|
||||
_nonip_req = nonip_req;
|
||||
_apn = apn;
|
||||
_device = device;
|
||||
}
|
||||
|
@ -587,7 +587,6 @@ void AT_CellularContext::do_connect()
|
|||
}
|
||||
#else
|
||||
_is_connected = true;
|
||||
call_network_cb(NSAPI_STATUS_GLOBAL_UP);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -131,10 +131,6 @@ protected:
|
|||
char _found_apn[MAX_APN_LENGTH];
|
||||
// flag indicating if CP was requested to be setup
|
||||
bool _cp_req;
|
||||
// flag indicating if Non-IP context was requested to be setup
|
||||
bool _nonip_req;
|
||||
// tells if CCIOTOPTI received green from network for CP optimization use
|
||||
bool _cp_in_use;
|
||||
};
|
||||
|
||||
} // namespace mbed
|
||||
|
|
|
@ -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, PDP_IPV6_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()
|
||||
|
|
|
@ -62,7 +62,7 @@ CellularContext::CellularContext() : _next(0), _stack(0), _pdp_type(DEFAULT_PDP_
|
|||
_authentication_type(CellularContext::CHAP), _connect_status(NSAPI_STATUS_DISCONNECTED), _status_cb(0),
|
||||
_cid(-1), _new_context_set(false), _is_context_active(false), _is_context_activated(false),
|
||||
_apn(0), _uname(0), _pwd(0), _dcd_pin(NC), _active_high(false), _cp_netif(0), _retry_array_length(0),
|
||||
_retry_count(0), _device(0), _nw(0), _is_blocking(true)
|
||||
_retry_count(0), _device(0), _nw(0), _is_blocking(true), _nonip_req(false), _cp_in_use(false)
|
||||
{
|
||||
memset(_retry_timeout_array, 0, CELLULAR_RETRY_ARRAY_SIZE);
|
||||
}
|
||||
|
@ -87,6 +87,28 @@ 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++;
|
||||
}
|
||||
}
|
||||
|
||||
void CellularContext::do_connect_with_retry()
|
||||
{
|
||||
if (_cb_data.final_try) {
|
||||
|
@ -97,6 +119,12 @@ 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
|
||||
if (!_nonip_req && !_cp_in_use) { // don't validate if non-ip case
|
||||
validate_ip_address();
|
||||
}
|
||||
call_network_cb(NSAPI_STATUS_GLOBAL_UP);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue