Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ACM] Perform cloud ping or reachability test on network events; non-blocking background reachability test #2811

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions build/arm-tools.mk
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,11 @@ endif
# We are using newlib-nano for all the platforms
CFLAGS += --specs=nano.specs

ifneq ($(LTO_EXTRA_OPTIMIZATIONS),)
CFLAGS += -fmerge-all-constants
LDFLAGS += -fmerge-all-constants
endif

# Check if the compiler version is the minimum required
version_to_number=$(shell v=$1; v=($${v//./ }); echo $$((v[0] * 10000 + v[1] * 100 + v[2])))
get_major_version=$(shell v=$1; v=($${v//./ }); echo $${v[0]})
Expand Down
3 changes: 3 additions & 0 deletions hal/network/lwip/lwiphooks.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,6 @@ __attribute__((weak)) struct netif* lwip_hook_ip6_route(const ip6_addr_t* src, c
return NULL;
}

__attribute__((weak)) struct netif* lwip_hook_dns_get_netif_for_server_index(int index) {
return NULL;
}
8 changes: 8 additions & 0 deletions hal/network/lwip/resolvapi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "logging.h"
#include "ifapi.h"
#include <algorithm>
#include "lwiphooks.h"

using namespace particle::net;

Expand Down Expand Up @@ -221,3 +222,10 @@ int resolv_get_dns_server_priority_for_iface(if_t iface, int priority) {
index = index * LWIP_DNS_SERVERS_PER_NETIF + std::min<int>(LWIP_DNS_SERVERS_PER_NETIF, priority);
return index;
}

struct netif* lwip_hook_dns_get_netif_for_server_index(int index) {
uint8_t netifIdx = index / LWIP_DNS_SERVERS_PER_NETIF;
if_t iface = nullptr;
if_get_by_index(netifIdx, &iface);
return (netif*)iface;
}
3 changes: 3 additions & 0 deletions hal/src/nRF52840/lwip/lwiphooks.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ int lwip_hook_ip4_input(struct pbuf *p, struct netif *inp);
int lwip_hook_ip4_input_post_validation(struct pbuf* p, struct netif* inp);
struct netif* lwip_hook_ip4_route_src(const ip4_addr_t* src, const ip4_addr_t* dst);
int lwip_hook_ip4_input_pre_upper_layers(struct pbuf* p, const struct ip_hdr* iphdr, struct netif* inp);
struct netif* lwip_hook_dns_get_netif_for_server_index(int index);
#endif /* LWIP_IPV4 */

/* IPv6 hooks */
Expand All @@ -48,6 +49,8 @@ void lwip_hook_memp_free(memp_t type, unsigned available, unsigned size);
}
#endif /* __cplusplus */

#define LWIP_HOOK_DNS_GET_NETIF_FOR_SERVER_INDEX(index) lwip_hook_dns_get_netif_for_server_index(index)

/**
* LWIP_HOOK_TCP_ISN:
* Hook for generation of the Initial Sequence Number (ISN) for a new TCP
Expand Down
7 changes: 7 additions & 0 deletions hal/src/nRF52840/lwip/lwipopts.h
Original file line number Diff line number Diff line change
Expand Up @@ -753,6 +753,13 @@ void sys_unlock_tcpip_core(void);
* LWIP_NETBUF_RECVINFO==1: append destination addr and port to every netbuf.
*/
#define LWIP_NETBUF_RECVINFO 0


/**
* LWIP_NETBUF_TIMESTAMP==1: append timestamp to netbufs
*/
#define LWIP_NETBUF_TIMESTAMP 1

/**
* @}
*/
Expand Down
9 changes: 8 additions & 1 deletion hal/src/nRF52840/lwip/sys_arch.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include "FreeRTOS.h"
#include "semphr.h"
#include "task.h"
#include "timer_hal.h"

/** Set this to 1 if you want the stack size passed to sys_thread_new() to be
* interpreted as number of stack words (FreeRTOS-like).
Expand Down Expand Up @@ -78,7 +79,7 @@
* Default is 1, where FreeRTOS ticks are used to calculate back to ms.
*/
#ifndef LWIP_FREERTOS_SYS_NOW_FROM_FREERTOS
#define LWIP_FREERTOS_SYS_NOW_FROM_FREERTOS 1
#define LWIP_FREERTOS_SYS_NOW_FROM_FREERTOS 0
#endif

#if !configSUPPORT_DYNAMIC_ALLOCATION
Expand Down Expand Up @@ -135,6 +136,12 @@ sys_now(void)
{
return xTaskGetTickCount() * portTICK_PERIOD_MS;
}
#else
u32_t
sys_now(void)
{
return HAL_Timer_Get_Milli_Seconds();
}
#endif

u32_t
Expand Down
3 changes: 3 additions & 0 deletions hal/src/rtl872x/lwip/lwiphooks.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ int lwip_hook_ip4_input(struct pbuf *p, struct netif *inp);
int lwip_hook_ip4_input_post_validation(struct pbuf* p, struct netif* inp);
struct netif* lwip_hook_ip4_route_src(const ip4_addr_t* src, const ip4_addr_t* dst);
int lwip_hook_ip4_input_pre_upper_layers(struct pbuf* p, const struct ip_hdr* iphdr, struct netif* inp);
struct netif* lwip_hook_dns_get_netif_for_server_index(int index);
#endif /* LWIP_IPV4 */

/* IPv6 hooks */
Expand All @@ -48,6 +49,8 @@ void lwip_hook_memp_free(memp_t type, unsigned available, unsigned size);
}
#endif /* __cplusplus */

#define LWIP_HOOK_DNS_GET_NETIF_FOR_SERVER_INDEX(index) lwip_hook_dns_get_netif_for_server_index(index)

/**
* LWIP_HOOK_TCP_ISN:
* Hook for generation of the Initial Sequence Number (ISN) for a new TCP
Expand Down
5 changes: 5 additions & 0 deletions hal/src/rtl872x/lwip/lwipopts.h
Original file line number Diff line number Diff line change
Expand Up @@ -751,6 +751,11 @@ void sys_unlock_tcpip_core(void);
* LWIP_NETBUF_RECVINFO==1: append destination addr and port to every netbuf.
*/
#define LWIP_NETBUF_RECVINFO 0

/**
* LWIP_NETBUF_TIMESTAMP==1: append timestamp to netbufs
*/
#define LWIP_NETBUF_TIMESTAMP 1
/**
* @}
*/
Expand Down
9 changes: 8 additions & 1 deletion hal/src/rtl872x/lwip/sys_arch.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include "FreeRTOS.h"
#include "semphr.h"
#include "task.h"
#include "timer_hal.h"

/** Set this to 1 if you want the stack size passed to sys_thread_new() to be
* interpreted as number of stack words (FreeRTOS-like).
Expand Down Expand Up @@ -78,7 +79,7 @@
* Default is 1, where FreeRTOS ticks are used to calculate back to ms.
*/
#ifndef LWIP_FREERTOS_SYS_NOW_FROM_FREERTOS
#define LWIP_FREERTOS_SYS_NOW_FROM_FREERTOS 1
#define LWIP_FREERTOS_SYS_NOW_FROM_FREERTOS 0
#endif

#if !configSUPPORT_DYNAMIC_ALLOCATION
Expand Down Expand Up @@ -135,6 +136,12 @@ sys_now(void)
{
return xTaskGetTickCount() * portTICK_PERIOD_MS;
}
#else
u32_t
sys_now(void)
{
return HAL_Timer_Get_Milli_Seconds();
}
#endif

u32_t
Expand Down
2 changes: 2 additions & 0 deletions modules/argon/system-part1/makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ NCP_FIRMWARE_MODULE_VERSION=4
DEPENDENCIES = newlib_nano modules/argon/user-part modules/argon/system-part1 dynalib services hal platform system wiring communication rt-dynalib crypto proto_defs
LIB_DEPENDENCIES = services system wiring communication hal platform crypto proto_defs

export LTO_EXTRA_OPTIMIZATIONS=1

# newlib_nano is special in that it's linked automatically by the system, so no need to add it to the library path here
MAKE_DEPENDENCIES = newlib_nano $(LIB_DEPENDENCIES)
include ../modular.mk
Expand Down
2 changes: 2 additions & 0 deletions modules/b5som/system-part1/makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ BUILD_PATH_EXT = $(BUILD_TARGET_PLATFORM)
HAL_LINK :=
PLATFORM_DFU = 0x30000

export LTO_EXTRA_OPTIMIZATIONS=1

DEPENDENCIES = newlib_nano modules/b5som/user-part modules/b5som/system-part1 dynalib services hal platform system wiring communication rt-dynalib crypto proto_defs wiring_globals
LIB_DEPENDENCIES = services system wiring communication hal platform crypto proto_defs wiring_globals
# newlib_nano is special in that it's linked automatically by the system, so no need to add it to the library path here
Expand Down
2 changes: 2 additions & 0 deletions modules/boron/system-part1/makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ BUILD_PATH_EXT = $(BUILD_TARGET_PLATFORM)
HAL_LINK :=
PLATFORM_DFU = 0x30000

export LTO_EXTRA_OPTIMIZATIONS=1

DEPENDENCIES = newlib_nano modules/boron/user-part modules/boron/system-part1 dynalib services hal platform system wiring communication rt-dynalib crypto proto_defs wiring_globals
LIB_DEPENDENCIES = services system wiring communication hal platform crypto proto_defs wiring_globals
# newlib_nano is special in that it's linked automatically by the system, so no need to add it to the library path here
Expand Down
2 changes: 2 additions & 0 deletions modules/tracker/system-part1/makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ BUILD_PATH_EXT = $(BUILD_TARGET_PLATFORM)
HAL_LINK :=
PLATFORM_DFU = 0x30000

export LTO_EXTRA_OPTIMIZATIONS=1

DEPENDENCIES = newlib_nano modules/tracker/user-part modules/tracker/system-part1 dynalib services hal platform system wiring communication rt-dynalib crypto proto_defs wiring_globals
LIB_DEPENDENCIES = services system wiring communication hal platform crypto proto_defs wiring_globals
# newlib_nano is special in that it's linked automatically by the system, so no need to add it to the library path here
Expand Down
14 changes: 14 additions & 0 deletions system/src/system_cloud_connection.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
#include "ota_flash_hal.h"
#include "socket_hal.h"
#include <type_traits>
#if HAL_PLATFORM_IFAPI
#include "netdb_hal.h"
#endif // HAL_PLATFORM_IFAPI

#ifdef __cplusplus
extern "C" {
Expand All @@ -33,6 +36,13 @@ typedef enum {
SYSTEM_CLOUD_DISCONNECT_GRACEFULLY = 1
} system_cloud_connection_flags_t;

typedef enum CloudServerAddressType {
CLOUD_SERVER_ADDRESS_TYPE_NONE = 0,
CLOUD_SERVER_ADDRESS_TYPE_CACHED = 1,
CLOUD_SERVER_ADDRESS_TYPE_CACHED_ADDRINFO = 2,
CLOUD_SERVER_ADDRESS_TYPE_NEW_ADDRINFO = 3
} CloudServerAddressType;

int system_cloud_connect(int protocol, const ServerAddress* address, sockaddr* saddrCache);
int system_cloud_disconnect(int flags);
int system_cloud_send(const uint8_t* buf, size_t buflen, int flags);
Expand All @@ -44,6 +54,10 @@ int system_cloud_set_inet_family_keepalive(int af, unsigned int value, int flags
int system_cloud_get_inet_family_keepalive(int af, unsigned int* value);
sock_handle_t system_cloud_get_socket_handle();

#if HAL_PLATFORM_IFAPI
int system_cloud_resolv_address(int protocol, const ServerAddress* address, sockaddr* saddrCache, addrinfo** info, CloudServerAddressType* type, bool useCachedAddrInfo);
#endif // HAL_PLATFORM_IFAPI

#ifdef __cplusplus
}
#endif /* __cplusplus */
Expand Down
54 changes: 29 additions & 25 deletions system/src/system_cloud_connection_posix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,6 @@

namespace {

enum CloudServerAddressType {
CLOUD_SERVER_ADDRESS_TYPE_NONE = 0,
CLOUD_SERVER_ADDRESS_TYPE_CACHED = 1,
CLOUD_SERVER_ADDRESS_TYPE_CACHED_ADDRINFO = 2,
CLOUD_SERVER_ADDRESS_TYPE_NEW_ADDRINFO = 3
};

struct SystemCloudState {
int socket = -1;
struct addrinfo* addr = nullptr;
Expand All @@ -54,11 +47,10 @@ const unsigned CLOUD_SOCKET_HALF_CLOSED_WAIT_TIMEOUT = 5000;

} /* anonymous */

int system_cloud_connect(int protocol, const ServerAddress* address, sockaddr* saddrCache)
{
struct addrinfo* info = nullptr;
CloudServerAddressType type = CLOUD_SERVER_ADDRESS_TYPE_NONE;
bool clean = true;
int system_cloud_resolv_address(int protocol, const ServerAddress* address, sockaddr* saddrCache, addrinfo** info, CloudServerAddressType* type, bool useCachedAddrInfo) {
CHECK_TRUE(info, SYSTEM_ERROR_INVALID_ARGUMENT);

*type = CLOUD_SERVER_ADDRESS_TYPE_NONE;

if (saddrCache && /* protocol == IPPROTO_UDP && */ saddrCache->sa_family != AF_UNSPEC) {
char tmphost[INET6_ADDRSTRLEN] = {};
Expand All @@ -73,21 +65,21 @@ int system_cloud_connect(int protocol, const ServerAddress* address, sockaddr* s
/* FIXME: */
hints.ai_socktype = hints.ai_protocol == IPPROTO_UDP ? SOCK_DGRAM : SOCK_STREAM;

if (!netdb_getaddrinfo(tmphost, tmpserv, &hints, &info)) {
type = CLOUD_SERVER_ADDRESS_TYPE_CACHED;
if (!netdb_getaddrinfo(tmphost, tmpserv, &hints, info)) {
*type = CLOUD_SERVER_ADDRESS_TYPE_CACHED;
}
}
}

if (type == CLOUD_SERVER_ADDRESS_TYPE_NONE) {
if (*type == CLOUD_SERVER_ADDRESS_TYPE_NONE && useCachedAddrInfo) {
/* Check if we have another address to try from the cached addrinfo list */
if (s_state.addr && s_state.next) {
info = s_state.next;
type = CLOUD_SERVER_ADDRESS_TYPE_CACHED_ADDRINFO;
*info = s_state.next;
*type = CLOUD_SERVER_ADDRESS_TYPE_CACHED_ADDRINFO;
}
}

if ((type == CLOUD_SERVER_ADDRESS_TYPE_NONE) && address) {
if ((*type == CLOUD_SERVER_ADDRESS_TYPE_NONE) && address) {
/* Use passed ServerAddress */
switch (address->addr_type) {
case IP_ADDRESS: {
Expand All @@ -107,8 +99,8 @@ int system_cloud_connect(int protocol, const ServerAddress* address, sockaddr* s
if (inet_inet_ntop(AF_INET, &in, tmphost, sizeof(tmphost))) {
snprintf(tmpserv, sizeof(tmpserv), "%u", address->port);

netdb_getaddrinfo(tmphost, tmpserv, &hints, &info);
type = CLOUD_SERVER_ADDRESS_TYPE_NEW_ADDRINFO;
netdb_getaddrinfo(tmphost, tmpserv, &hints, info);
*type = CLOUD_SERVER_ADDRESS_TYPE_NEW_ADDRINFO;
}
break;
}
Expand All @@ -126,19 +118,31 @@ int system_cloud_connect(int protocol, const ServerAddress* address, sockaddr* s
system_string_interpolate(address->domain, tmphost, sizeof(tmphost), system_interpolate_cloud_server_hostname);
snprintf(tmpserv, sizeof(tmpserv), "%u", address->port);
LOG(TRACE, "Resolving %s#%s", tmphost, tmpserv);
netdb_getaddrinfo(tmphost, tmpserv, &hints, &info);
type = CLOUD_SERVER_ADDRESS_TYPE_NEW_ADDRINFO;
netdb_getaddrinfo(tmphost, tmpserv, &hints, info);
*type = CLOUD_SERVER_ADDRESS_TYPE_NEW_ADDRINFO;
break;
}
}
}

int r = SYSTEM_ERROR_NETWORK;

if (info == nullptr) {
if (*info == nullptr) {
LOG(ERROR, "Failed to determine server address");
return SYSTEM_ERROR_NOT_FOUND;
}

return 0;
}

int system_cloud_connect(int protocol, const ServerAddress* address, sockaddr* saddrCache)
{
struct addrinfo* info = nullptr;
CloudServerAddressType type = CLOUD_SERVER_ADDRESS_TYPE_NONE;
bool clean = true;

system_cloud_resolv_address(protocol, address, saddrCache, &info, &type, true /* useCachedAddrInfo */);

int r = SYSTEM_ERROR_NETWORK;

LOG(TRACE, "Address type: %d", type);

for (struct addrinfo* a = info; a != nullptr; a = a->ai_next) {
Expand Down
13 changes: 11 additions & 2 deletions system/src/system_cloud_internal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1335,8 +1335,17 @@ void Spark_Process_Events()
{
if (SPARK_CLOUD_SOCKETED && !Spark_Communication_Loop())
{
WARN("Communication loop error, closing cloud socket");
cloud_disconnect(HAL_PLATFORM_MAY_LEAK_SOCKETS ? CLOUD_DISCONNECT_DONT_CLOSE : 0, CLOUD_DISCONNECT_REASON_ERROR);
// The error is only handled here if we are already out of handshake (or sesssion resume)
// In case of handshake/session resume errors the error is handled in handle_cloud_connection()
// and cloud_disconnect() will also eventually be called with CLOUD_DISCONNECT_REASON_ERROR.
if (SPARK_CLOUD_CONNECTED) {
WARN("Communication loop error, closing cloud socket");
cloud_disconnect(HAL_PLATFORM_MAY_LEAK_SOCKETS ? CLOUD_DISCONNECT_DONT_CLOSE : 0, CLOUD_DISCONNECT_REASON_ERROR);
} else if (SPARK_CLOUD_HANDSHAKE_PENDING) {
// FIXME: this is a temporary workaround. communication layer should call the appropriate callback on its own in case of errors (?)
SPARK_CLOUD_HANDSHAKE_PENDING = 0;
SPARK_CLOUD_HANDSHAKE_NOTIFY_DONE = 1;
}
}
else
{
Expand Down
Loading