Skip to content

Add property API to InternetSocket #12522

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

Merged
merged 5 commits into from
Apr 28, 2020
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
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,18 @@ TEST_F(TestInternetSocket, modify_multicast_group)
EXPECT_EQ(socket->leave_multicast_group(a), NSAPI_ERROR_UNSUPPORTED);
}

TEST_F(TestInternetSocket, network_property)
{
SocketAddress a("fd00:db8::ff", 1024);
uint32_t rtt_estimate;
uint16_t stagger_min, stagger_max, stagger_rand;
stack.return_value = NSAPI_ERROR_OK;
socket->open(&stack);
EXPECT_EQ(socket->get_rtt_estimate_to_address(a, &rtt_estimate), NSAPI_ERROR_UNSUPPORTED);
EXPECT_EQ(socket->get_rtt_estimate_to_address(a, NULL), NSAPI_ERROR_PARAMETER);
EXPECT_EQ(socket->get_stagger_estimate_to_address(a, 1, &stagger_min, &stagger_max, &stagger_rand), NSAPI_ERROR_UNSUPPORTED);
}

// set_blocking and set_timeout are tested within TCPSocket.

TEST_F(TestInternetSocket, bind_no_socket)
Expand Down
42 changes: 41 additions & 1 deletion features/nanostack/nanostack-interface/Nanostack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -838,18 +838,58 @@ nsapi_error_t Nanostack::setsockopt(void *handle, int level, int optname, const
nsapi_error_t Nanostack::getsockopt(void *handle, int level, int optname, void *optval, unsigned *optlen)
{
NanostackSocket *socket = static_cast<NanostackSocket *>(handle);

if (handle == NULL) {
MBED_ASSERT(false);
return NSAPI_ERROR_NO_SOCKET;
}

NanostackLockGuard lock;
// pointers to Mbed OS structures
nsapi_latency_req_t *ns_latency_r = static_cast<nsapi_latency_req_t *>(optval);
nsapi_stagger_req_t *ns_stagger_r = static_cast<nsapi_stagger_req_t *>(optval);
// Nanostack internal structures
ns_ipv6_latency_t nanostack_latency;
ns_ipv6_stagger_t nanostack_stagger;
int nanostack_optname = optname;

void *ns_option_value = optval;

if (level == NSAPI_SOCKET) {
if (optname == NSAPI_LATENCY) {
if (*optlen < sizeof(nsapi_latency_req_t)) {
return NSAPI_ERROR_PARAMETER;
}
// Adjust to Nanostack namespace
level = SOCKET_IPPROTO_IPV6;
nanostack_optname = SOCKET_LATENCY;
memcpy(nanostack_latency.dest_addr, ns_latency_r->addr, 16);
ns_option_value = &nanostack_latency;
} else if (optname == NSAPI_STAGGER) {
if (*optlen < sizeof(nsapi_stagger_req_t)) {
return NSAPI_ERROR_PARAMETER;
}
// Adjust to Nanostack namespace
level = SOCKET_IPPROTO_IPV6;
nanostack_optname = SOCKET_STAGGER;
memcpy(nanostack_stagger.dest_addr, ns_stagger_r->addr, 16);
nanostack_stagger.data_amount = ns_stagger_r->data_amount;
ns_option_value = &nanostack_stagger;
}
}

uint16_t optlen16 = *optlen;

int retcode = ::socket_getsockopt(socket->socket_id, level, optname, optval, &optlen16);
int retcode = ::socket_getsockopt(socket->socket_id, level, nanostack_optname, ns_option_value, &optlen16);
if (retcode == 0) {
*optlen = optlen16;
if (optname == NSAPI_LATENCY) {
ns_latency_r->latency = nanostack_latency.latency;
} else if (optname == NSAPI_STAGGER) {
ns_stagger_r->stagger_min = nanostack_stagger.stagger_min;
ns_stagger_r->stagger_max = nanostack_stagger.stagger_max;
ns_stagger_r->stagger_rand = nanostack_stagger.stagger_rand;
}
return NSAPI_ERROR_OK;
} else if (retcode == -2) {
return NSAPI_ERROR_UNSUPPORTED;
Expand Down
48 changes: 48 additions & 0 deletions features/netsocket/InternetSocket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,54 @@ int InternetSocket::leave_multicast_group(const SocketAddress &address)
return modify_multicast_group(address, NSAPI_DROP_MEMBERSHIP);
}

int InternetSocket::get_rtt_estimate_to_address(const SocketAddress &address, uint32_t *rtt_estimate)
{
nsapi_error_t ret;
nsapi_latency_req_t ns_api_latency_req;
unsigned opt_len = sizeof(nsapi_latency_req_t);

if (!rtt_estimate) {
return NSAPI_ERROR_PARAMETER;
}

// Set up address
memcpy(ns_api_latency_req.addr, address.get_ip_bytes(), 16);

ret = this->getsockopt(NSAPI_SOCKET, NSAPI_LATENCY, &ns_api_latency_req, &opt_len);
if (ret == NSAPI_ERROR_OK) {
// success, latency found. Convert to RTT.
*rtt_estimate = ns_api_latency_req.latency * 2;
}

return ret;
}

int InternetSocket::get_stagger_estimate_to_address(const SocketAddress &address, uint16_t data_amount, uint16_t *stagger_min, uint16_t *stagger_max, uint16_t *stagger_rand)
{
nsapi_error_t ret;
nsapi_stagger_req_t nsapi_stagger;
unsigned opt_len = sizeof(nsapi_stagger_req_t);

// Set up address
memcpy(nsapi_stagger.addr, address.get_ip_bytes(), 16);
nsapi_stagger.data_amount = data_amount;

ret = this->getsockopt(NSAPI_SOCKET, NSAPI_STAGGER, &nsapi_stagger, &opt_len);
if (ret == NSAPI_ERROR_OK) {
// success, stagger found
if (stagger_min) {
*stagger_min = nsapi_stagger.stagger_min;
}
if (stagger_max) {
*stagger_max = nsapi_stagger.stagger_max;
}
if (stagger_rand) {
*stagger_rand = nsapi_stagger.stagger_rand;
}
}

return ret;
}

nsapi_error_t InternetSocket::bind(uint16_t port)
{
Expand Down
29 changes: 29 additions & 0 deletions features/netsocket/InternetSocket.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,35 @@ class InternetSocket : public Socket {
*/
int leave_multicast_group(const SocketAddress &address);

/** Get estimated round trip time to destination address.
*
* Use estimated round trip time to adjust application retry timers to work in networks
* that have low data rate and high latency.
*
* @param address Destination address to use in rtt estimate.
* @param rtt_estimate Returned round trip time value in milliseconds.
* @return NSAPI_ERROR_OK on success.
* @return NSAPI_ERROR_PARAMETER if the provided pointer is invalid.
* @return negative error code on other failures (@see InternetSocket::getsockopt).
*/
int get_rtt_estimate_to_address(const SocketAddress &address, uint32_t *rtt_estimate);

/** Get estimated stagger value.
*
* Stagger value is a time that application should wait before using heavy network operations after connecting to network.
* Purpose of staggering is to avoid network congestion that may happen in low bandwith networks if multiple
* applications simultaneously start heavy network usage after joining to the network.
*
* @param address Destination added used to estimate stagger value.
* @param data_amount Amount of bytes to transfer in kilobytes.
* @param stagger_min Minimum stagger value in seconds.
* @param stagger_max Maximum stagger value in seconds.
* @param stagger_rand Randomized stagger value between stagger_min and stagger_max in seconds.
* @return NSAPI_ERROR_OK on success.
* @return negative error code on other failures (@see InternetSocket::getsockopt).
*/
int get_stagger_estimate_to_address(const SocketAddress &address, uint16_t data_amount, uint16_t *stagger_min, uint16_t *stagger_max, uint16_t *stagger_rand);

/** Bind the socket to a port on which to receive data.
*
* @param port Local port to bind.
Expand Down
21 changes: 20 additions & 1 deletion features/netsocket/nsapi_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,9 @@ typedef enum nsapi_socket_option {
NSAPI_RCVBUF, /*!< Sets recv buffer size */
NSAPI_ADD_MEMBERSHIP, /*!< Add membership to multicast address */
NSAPI_DROP_MEMBERSHIP, /*!< Drop membership to multicast address */
NSAPI_BIND_TO_DEVICE, /*!< Bind socket network interface name*/
NSAPI_BIND_TO_DEVICE, /*!< Bind socket network interface name*/
NSAPI_LATENCY, /*!< Read estimated latency to destination */
NSAPI_STAGGER, /*!< Read estimated stagger value to destination */
} nsapi_socket_option_t;

typedef enum nsapi_tlssocket_level {
Expand Down Expand Up @@ -340,6 +342,23 @@ typedef struct nsapi_ip_mreq {
nsapi_addr_t imr_interface; /* local IP address of interface */
} nsapi_ip_mreq_t;

/** nsapi_latency_req structure
*/
typedef struct nsapi_latency_req {
uint8_t addr[16]; /* [IN] Destination address to estimate latency */
uint32_t latency; /* [OUT] Latency value */
} nsapi_latency_req_t;

/** nsapi_stagger_req structure
*/
typedef struct nsapi_stagger_req {
uint8_t addr[16]; /* [IN] Destination address to estimate stagger */
uint16_t data_amount; /* [IN] Amount of data to be sent in kilobytes */
uint16_t stagger_min; /* [OUT] Minimum stagger value in seconds */
uint16_t stagger_max; /* [OUT] Maximum stagger value in seconds */
uint16_t stagger_rand; /* [OUT] Randomized stagger value in seconds */
} nsapi_stagger_req_t;

/** nsapi_stack_api structure
*
* Common api structure for network stack operations. A network stack
Expand Down