net: lib: coap_client: check poll() condition before retrying CoAP msg

Refactor the CoAP retry handling into the handle_poll() function,
so that we only try to send retries if the socket reports POLLOUT.

Also move the receiving into same loop, so when poll() reports POLLIN
we recv() the message and handle it before proceeding to other sockets.

Also fix tests to handle POLLOUT flag and add support for testing
multiple clients.

Signed-off-by: Seppo Takalo <seppo.takalo@nordicsemi.no>
This commit is contained in:
Seppo Takalo 2024-10-24 13:25:37 +03:00 committed by Mahesh Mahadevan
commit 4c6dd4c7b7
6 changed files with 194 additions and 147 deletions

View file

@ -108,14 +108,12 @@ struct coap_client {
int fd; int fd;
struct sockaddr address; struct sockaddr address;
socklen_t socklen; socklen_t socklen;
bool response_ready;
struct k_mutex lock; struct k_mutex lock;
uint8_t send_buf[MAX_COAP_MSG_LEN]; uint8_t send_buf[MAX_COAP_MSG_LEN];
uint8_t recv_buf[MAX_COAP_MSG_LEN]; uint8_t recv_buf[MAX_COAP_MSG_LEN];
struct coap_client_internal_request requests[CONFIG_COAP_CLIENT_MAX_REQUESTS]; struct coap_client_internal_request requests[CONFIG_COAP_CLIENT_MAX_REQUESTS];
struct coap_option echo_option; struct coap_option echo_option;
bool send_echo; bool send_echo;
int socket_error;
}; };
/** @endcond */ /** @endcond */

View file

@ -26,6 +26,13 @@ static int num_clients;
static K_SEM_DEFINE(coap_client_recv_sem, 0, 1); static K_SEM_DEFINE(coap_client_recv_sem, 0, 1);
static atomic_t coap_client_recv_active; static atomic_t coap_client_recv_active;
static bool timeout_expired(struct coap_client_internal_request *internal_req);
static void cancel_requests_with(struct coap_client *client, int error);
static int recv_response(struct coap_client *client, struct coap_packet *response, bool *truncated);
static int handle_response(struct coap_client *client, const struct coap_packet *response,
bool response_truncated);
static int send_request(int sock, const void *buf, size_t len, int flags, static int send_request(int sock, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen) const struct sockaddr *dest_addr, socklen_t addrlen)
{ {
@ -127,6 +134,16 @@ static bool has_ongoing_exchange(struct coap_client *client)
return false; return false;
} }
static bool has_timeout_expired(struct coap_client *client)
{
for (int i = 0; i < CONFIG_COAP_CLIENT_MAX_REQUESTS; i++) {
if (timeout_expired(&client->requests[i])) {
return true;
}
}
return false;
}
static struct coap_client_internal_request *get_free_request(struct coap_client *client) static struct coap_client_internal_request *get_free_request(struct coap_client *client)
{ {
for (int i = 0; i < CONFIG_COAP_CLIENT_MAX_REQUESTS; i++) { for (int i = 0; i < CONFIG_COAP_CLIENT_MAX_REQUESTS; i++) {
@ -139,17 +156,6 @@ static struct coap_client_internal_request *get_free_request(struct coap_client
return NULL; return NULL;
} }
static bool has_ongoing_requests(void)
{
for (int i = 0; i < num_clients; i++) {
if (has_ongoing_request(clients[i])) {
return true;
}
}
return false;
}
static bool has_ongoing_exchanges(void) static bool has_ongoing_exchanges(void)
{ {
for (int i = 0; i < num_clients; i++) { for (int i = 0; i < num_clients; i++) {
@ -498,86 +504,91 @@ static int resend_request(struct coap_client *client,
return ret; return ret;
} }
static int coap_client_resend_handler(void) static void coap_client_resend_handler(struct coap_client *client)
{ {
int ret = 0; int ret = 0;
for (int i = 0; i < num_clients; i++) { k_mutex_lock(&client->lock, K_FOREVER);
k_mutex_lock(&clients[i]->lock, K_FOREVER);
for (int j = 0; j < CONFIG_COAP_CLIENT_MAX_REQUESTS; j++) { for (int i = 0; i < CONFIG_COAP_CLIENT_MAX_REQUESTS; i++) {
if (timeout_expired(&clients[i]->requests[j])) { if (timeout_expired(&client->requests[i])) {
ret = resend_request(clients[i], &clients[i]->requests[j]); ret = resend_request(client, &client->requests[i]);
if (ret < 0) {
report_callback_error(&client->requests[i], ret);
reset_internal_request(&client->requests[i]);
} }
} }
k_mutex_unlock(&clients[i]->lock);
} }
return ret; k_mutex_unlock(&client->lock);
} }
static int handle_poll(void) static int handle_poll(void)
{ {
int ret = 0; int ret = 0;
while (1) { struct zsock_pollfd fds[CONFIG_COAP_CLIENT_MAX_INSTANCES] = {0};
struct zsock_pollfd fds[CONFIG_COAP_CLIENT_MAX_INSTANCES] = {0}; int nfds = 0;
int nfds = 0;
/* Use periodic timeouts */ /* Use periodic timeouts */
for (int i = 0; i < num_clients; i++) { for (int i = 0; i < num_clients; i++) {
fds[i].fd = clients[i]->fd; fds[i].fd = clients[i]->fd;
fds[i].events = ZSOCK_POLLIN; fds[i].events = (has_ongoing_exchange(clients[i]) ? ZSOCK_POLLIN : 0) |
fds[i].revents = 0; (has_timeout_expired(clients[i]) ? ZSOCK_POLLOUT : 0);
nfds++; fds[i].revents = 0;
nfds++;
}
ret = zsock_poll(fds, nfds, COAP_PERIODIC_TIMEOUT);
if (ret < 0) {
ret = -errno;
LOG_ERR("Error in poll:%d", ret);
return ret;
} else if (ret == 0) {
return 0;
}
for (int i = 0; i < nfds; i++) {
if (fds[i].revents & ZSOCK_POLLOUT) {
coap_client_resend_handler(clients[i]);
} }
if (fds[i].revents & ZSOCK_POLLIN) {
struct coap_packet response;
bool response_truncated = false;
ret = zsock_poll(fds, nfds, COAP_PERIODIC_TIMEOUT); k_mutex_lock(&clients[i]->lock, K_FOREVER);
if (ret < 0) {
LOG_ERR("Error in poll:%d", errno);
errno = 0;
return ret;
} else if (ret == 0) {
/* Resend all the expired pending messages */
ret = coap_client_resend_handler();
ret = recv_response(clients[i], &response, &response_truncated);
if (ret < 0) { if (ret < 0) {
LOG_ERR("Error resending request: %d", ret); LOG_ERR("Error receiving response");
cancel_requests_with(clients[i], -EIO);
k_mutex_unlock(&clients[i]->lock);
continue;
} }
if (!has_ongoing_requests()) { ret = handle_response(clients[i], &response, response_truncated);
return ret; if (ret < 0) {
LOG_ERR("Error handling response");
} }
} else { k_mutex_unlock(&clients[i]->lock);
for (int i = 0; i < nfds; i++) { }
if (fds[i].revents & ZSOCK_POLLERR) {
if (fds[i].revents & ZSOCK_POLLERR) { LOG_ERR("Error in poll for socket %d", fds[i].fd);
LOG_ERR("Error in poll for socket %d", fds[i].fd); cancel_requests_with(clients[i], -EIO);
clients[i]->socket_error = -EIO; }
} if (fds[i].revents & ZSOCK_POLLHUP) {
if (fds[i].revents & ZSOCK_POLLHUP) { LOG_ERR("Error in poll: POLLHUP for socket %d", fds[i].fd);
LOG_ERR("Error in poll: POLLHUP for socket %d", fds[i].fd); cancel_requests_with(clients[i], -EIO);
clients[i]->socket_error = -ENOTCONN; }
} if (fds[i].revents & ZSOCK_POLLNVAL) {
if (fds[i].revents & ZSOCK_POLLNVAL) { LOG_ERR("Error in poll: POLLNVAL - fd %d not open", fds[i].fd);
LOG_ERR("Error in poll: POLLNVAL - fd %d not open", cancel_requests_with(clients[i], -EIO);
fds[i].fd);
clients[i]->socket_error = -EINVAL;
}
if (fds[i].revents & ZSOCK_POLLIN) {
clients[i]->response_ready = true;
}
}
return 0;
} }
} }
return ret; return 0;
} }
static bool token_compare(struct coap_client_internal_request *internal_req, static bool token_compare(struct coap_client_internal_request *internal_req,
@ -895,14 +906,13 @@ static int handle_response(struct coap_client *client, const struct coap_packet
} }
} }
fail: fail:
client->response_ready = false;
if (ret < 0 || !internal_req->is_observe) { if (ret < 0 || !internal_req->is_observe) {
internal_req->request_ongoing = false; internal_req->request_ongoing = false;
} }
return ret; return ret;
} }
void coap_client_cancel_requests(struct coap_client *client) static void cancel_requests_with(struct coap_client *client, int error)
{ {
k_mutex_lock(&client->lock, K_FOREVER); k_mutex_lock(&client->lock, K_FOREVER);
@ -914,33 +924,20 @@ void coap_client_cancel_requests(struct coap_client *client)
* do not reenter it. In that case, the user knows their * do not reenter it. In that case, the user knows their
* request was cancelled anyway. * request was cancelled anyway.
*/ */
report_callback_error(&client->requests[i], -ECANCELED); report_callback_error(&client->requests[i], error);
client->requests[i].request_ongoing = false; reset_internal_request(&client->requests[i]);
client->requests[i].is_observe = false;
} }
} }
atomic_clear(&coap_client_recv_active); atomic_clear(&coap_client_recv_active);
k_mutex_unlock(&client->lock); k_mutex_unlock(&client->lock);
/* Wait until after zsock_poll() can time out and return. */
k_sleep(K_MSEC(COAP_PERIODIC_TIMEOUT));
} }
static void signal_socket_error(struct coap_client *cli) void coap_client_cancel_requests(struct coap_client *client)
{ {
for (int i = 0; i < CONFIG_COAP_CLIENT_MAX_REQUESTS; i++) { cancel_requests_with(client, -ECANCELED);
struct coap_client_internal_request *req = &cli->requests[i]; /* Wait until after zsock_poll() can time out and return. */
k_sleep(K_MSEC(COAP_PERIODIC_TIMEOUT));
if (!req->request_ongoing) {
continue;
}
req->request_ongoing = false;
if (req->coap_request.cb) {
req->coap_request.cb(cli->socket_error, 0, NULL, 0,
true, req->coap_request.user_data);
}
}
} }
void coap_client_recv(void *coap_cl, void *a, void *b) void coap_client_recv(void *coap_cl, void *a, void *b)
@ -957,41 +954,6 @@ void coap_client_recv(void *coap_cl, void *a, void *b)
goto idle; goto idle;
} }
for (int i = 0; i < num_clients; i++) {
if (clients[i]->response_ready) {
struct coap_packet response;
bool response_truncated = false;
k_mutex_lock(&clients[i]->lock, K_FOREVER);
ret = recv_response(clients[i], &response, &response_truncated);
if (ret < 0) {
LOG_ERR("Error receiving response");
clients[i]->response_ready = false;
k_mutex_unlock(&clients[i]->lock);
if (ret == -EOPNOTSUPP) {
LOG_ERR("Socket misconfigured.");
goto idle;
}
continue;
}
ret = handle_response(clients[i], &response, response_truncated);
if (ret < 0) {
LOG_ERR("Error handling response");
}
clients[i]->response_ready = false;
k_mutex_unlock(&clients[i]->lock);
}
if (clients[i]->socket_error) {
signal_socket_error(clients[i]);
clients[i]->socket_error = 0;
}
}
/* There are more messages coming */ /* There are more messages coming */
if (has_ongoing_exchanges()) { if (has_ongoing_exchanges()) {
continue; continue;

View file

@ -31,3 +31,4 @@ add_compile_definitions(CONFIG_COAP_CLIENT_MAX_REQUESTS=2)
add_compile_definitions(CONFIG_COAP_CLIENT_MAX_INSTANCES=2) add_compile_definitions(CONFIG_COAP_CLIENT_MAX_INSTANCES=2)
add_compile_definitions(CONFIG_COAP_MAX_RETRANSMIT=4) add_compile_definitions(CONFIG_COAP_MAX_RETRANSMIT=4)
add_compile_definitions(CONFIG_COAP_BACKOFF_PERCENT=200) add_compile_definitions(CONFIG_COAP_BACKOFF_PERCENT=200)
add_compile_definitions(CONFIG_COAP_LOG_LEVEL=4)

View file

@ -77,7 +77,7 @@ static ssize_t z_impl_zsock_recvfrom_custom_fake(int sock, void *buf, size_t max
memcpy(buf, ack_data, sizeof(ack_data)); memcpy(buf, ack_data, sizeof(ack_data));
clear_socket_events(); clear_socket_events(ZSOCK_POLLIN);
return sizeof(ack_data); return sizeof(ack_data);
} }
@ -205,7 +205,7 @@ static ssize_t z_impl_zsock_recvfrom_custom_fake_response(int sock, void *buf, s
memcpy(buf, ack_data, sizeof(ack_data)); memcpy(buf, ack_data, sizeof(ack_data));
clear_socket_events(); clear_socket_events(ZSOCK_POLLIN);
return sizeof(ack_data); return sizeof(ack_data);
} }
@ -247,7 +247,7 @@ static ssize_t z_impl_zsock_recvfrom_custom_fake_unmatching(int sock, void *buf,
memcpy(buf, ack_data, sizeof(ack_data)); memcpy(buf, ack_data, sizeof(ack_data));
clear_socket_events(); clear_socket_events(ZSOCK_POLLIN);
return sizeof(ack_data); return sizeof(ack_data);
} }
@ -273,7 +273,7 @@ static ssize_t z_impl_zsock_recvfrom_custom_fake_echo(int sock, void *buf, size_
z_impl_zsock_recvfrom_fake.custom_fake = z_impl_zsock_recvfrom_custom_fake_response; z_impl_zsock_recvfrom_fake.custom_fake = z_impl_zsock_recvfrom_custom_fake_response;
z_impl_zsock_sendto_fake.custom_fake = z_impl_zsock_sendto_custom_fake_echo; z_impl_zsock_sendto_fake.custom_fake = z_impl_zsock_sendto_custom_fake_echo;
clear_socket_events(); clear_socket_events(ZSOCK_POLLIN);
return sizeof(ack_data); return sizeof(ack_data);
} }
@ -299,7 +299,7 @@ static ssize_t z_impl_zsock_recvfrom_custom_fake_echo_next_req(int sock, void *b
z_impl_zsock_recvfrom_fake.custom_fake = z_impl_zsock_recvfrom_custom_fake_response; z_impl_zsock_recvfrom_fake.custom_fake = z_impl_zsock_recvfrom_custom_fake_response;
z_impl_zsock_sendto_fake.custom_fake = z_impl_zsock_sendto_custom_fake_echo_next_req; z_impl_zsock_sendto_fake.custom_fake = z_impl_zsock_sendto_custom_fake_echo_next_req;
clear_socket_events(); clear_socket_events(ZSOCK_POLLIN);
return sizeof(ack_data); return sizeof(ack_data);
} }
@ -335,6 +335,9 @@ void coap_callback(int16_t code, size_t offset, const uint8_t *payload, size_t l
{ {
LOG_INF("CoAP response callback, %d", code); LOG_INF("CoAP response callback, %d", code);
last_response_code = code; last_response_code = code;
if (user_data) {
k_sem_give((struct k_sem *) user_data);
}
} }
ZTEST_SUITE(coap_client, NULL, suite_setup, test_setup, NULL, NULL); ZTEST_SUITE(coap_client, NULL, suite_setup, test_setup, NULL, NULL);
@ -392,7 +395,7 @@ ZTEST(coap_client, test_resend_request)
ret = coap_client_req(&client, 0, &address, &client_request, NULL); ret = coap_client_req(&client, 0, &address, &client_request, NULL);
zassert_true(ret >= 0, "Sending request failed, %d", ret); zassert_true(ret >= 0, "Sending request failed, %d", ret);
k_sleep(K_MSEC(MORE_THAN_ACK_TIMEOUT_MS)); k_sleep(K_MSEC(MORE_THAN_ACK_TIMEOUT_MS));
set_socket_events(ZSOCK_POLLIN); set_socket_events(ZSOCK_POLLIN | ZSOCK_POLLOUT);
k_sleep(K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS)); k_sleep(K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS));
zassert_equal(last_response_code, COAP_RESPONSE_CODE_OK, "Unexpected response"); zassert_equal(last_response_code, COAP_RESPONSE_CODE_OK, "Unexpected response");
@ -547,6 +550,7 @@ ZTEST(coap_client, test_no_response)
client_request.len = strlen(short_payload); client_request.len = strlen(short_payload);
z_impl_zsock_sendto_fake.custom_fake = z_impl_zsock_sendto_custom_fake_no_reply; z_impl_zsock_sendto_fake.custom_fake = z_impl_zsock_sendto_custom_fake_no_reply;
set_socket_events(ZSOCK_POLLOUT);
k_sleep(K_MSEC(1)); k_sleep(K_MSEC(1));
@ -592,30 +596,35 @@ ZTEST(coap_client, test_multiple_requests)
{ {
int ret = 0; int ret = 0;
int retry = MORE_THAN_EXCHANGE_LIFETIME_MS; int retry = MORE_THAN_EXCHANGE_LIFETIME_MS;
struct k_sem sem1, sem2;
struct sockaddr address = {0}; struct sockaddr address = {0};
struct coap_client_request client_request = { struct coap_client_request req1 = {
.method = COAP_METHOD_GET, .method = COAP_METHOD_GET,
.confirmable = true, .confirmable = true,
.path = test_path, .path = test_path,
.fmt = COAP_CONTENT_FORMAT_TEXT_PLAIN, .fmt = COAP_CONTENT_FORMAT_TEXT_PLAIN,
.cb = coap_callback, .cb = coap_callback,
.payload = NULL, .payload = short_payload,
.len = 0 .len = strlen(short_payload),
.user_data = &sem1
}; };
struct coap_client_request req2 = req1;
client_request.payload = short_payload; req2.user_data = &sem2;
client_request.len = strlen(short_payload);
k_sem_init(&sem1, 0, 1);
k_sem_init(&sem2, 0, 1);
z_impl_zsock_sendto_fake.custom_fake = z_impl_zsock_sendto_custom_fake_no_reply; z_impl_zsock_sendto_fake.custom_fake = z_impl_zsock_sendto_custom_fake_no_reply;
k_sleep(K_MSEC(1)); k_sleep(K_MSEC(1));
LOG_INF("Send request"); LOG_INF("Send request");
ret = coap_client_req(&client, 0, &address, &client_request, NULL); ret = coap_client_req(&client, 0, &address, &req1, NULL);
zassert_true(ret >= 0, "Sending request failed, %d", ret); zassert_true(ret >= 0, "Sending request failed, %d", ret);
ret = coap_client_req(&client, 0, &address, &client_request, NULL); ret = coap_client_req(&client, 0, &address, &req2, NULL);
zassert_true(ret >= 0, "Sending request failed, %d", ret); zassert_true(ret >= 0, "Sending request failed, %d", ret);
set_socket_events(ZSOCK_POLLIN); set_socket_events(ZSOCK_POLLIN);
@ -625,8 +634,10 @@ ZTEST(coap_client, test_multiple_requests)
} }
zassert_equal(last_response_code, COAP_RESPONSE_CODE_OK, "Unexpected response"); zassert_equal(last_response_code, COAP_RESPONSE_CODE_OK, "Unexpected response");
last_response_code = 0;
set_socket_events(ZSOCK_POLLIN); set_socket_events(ZSOCK_POLLIN);
k_sleep(K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS)); zassert_ok(k_sem_take(&sem1, K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS)));
zassert_ok(k_sem_take(&sem2, K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS)));
zassert_equal(last_response_code, COAP_RESPONSE_CODE_OK, "Unexpected response"); zassert_equal(last_response_code, COAP_RESPONSE_CODE_OK, "Unexpected response");
} }
@ -653,6 +664,7 @@ ZTEST(coap_client, test_unmatching_tokens)
client_request.len = strlen(short_payload); client_request.len = strlen(short_payload);
z_impl_zsock_recvfrom_fake.custom_fake = z_impl_zsock_recvfrom_custom_fake_unmatching; z_impl_zsock_recvfrom_fake.custom_fake = z_impl_zsock_recvfrom_custom_fake_unmatching;
set_socket_events(ZSOCK_POLLIN | ZSOCK_POLLOUT);
k_sleep(K_MSEC(1)); k_sleep(K_MSEC(1));
@ -663,3 +675,57 @@ ZTEST(coap_client, test_unmatching_tokens)
k_sleep(K_MSEC(MORE_THAN_LONG_EXCHANGE_LIFETIME_MS)); k_sleep(K_MSEC(MORE_THAN_LONG_EXCHANGE_LIFETIME_MS));
zassert_equal(last_response_code, -ETIMEDOUT, "Unexpected response"); zassert_equal(last_response_code, -ETIMEDOUT, "Unexpected response");
} }
ZTEST(coap_client, test_multiple_clients)
{
int ret;
int retry = MORE_THAN_EXCHANGE_LIFETIME_MS;
static struct coap_client client2 = {
.fd = 2,
};
struct k_sem sem1, sem2;
struct sockaddr address = {0};
struct coap_client_request req1 = {
.method = COAP_METHOD_GET,
.confirmable = true,
.path = test_path,
.fmt = COAP_CONTENT_FORMAT_TEXT_PLAIN,
.cb = coap_callback,
.payload = short_payload,
.len = strlen(short_payload),
.user_data = &sem1
};
struct coap_client_request req2 = req1;
req2.user_data = &sem2;
req2.payload = long_payload;
req2.len = strlen(long_payload);
zassert_ok(k_sem_init(&sem1, 0, 1));
zassert_ok(k_sem_init(&sem2, 0, 1));
zassert_ok(coap_client_init(&client2, NULL));
k_sleep(K_MSEC(1));
LOG_INF("Sending requests");
ret = coap_client_req(&client, 1, &address, &req1, NULL);
zassert_true(ret >= 0, "Sending request failed, %d", ret);
ret = coap_client_req(&client2, 2, &address, &req2, NULL);
zassert_true(ret >= 0, "Sending request failed, %d", ret);
while (last_response_code == 0 && retry > 0) {
retry--;
k_sleep(K_MSEC(1));
}
set_socket_events(ZSOCK_POLLIN);
k_sleep(K_SECONDS(1));
/* ensure we got both responses */
zassert_ok(k_sem_take(&sem1, K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS)));
zassert_ok(k_sem_take(&sem2, K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS)));
zassert_equal(last_response_code, COAP_RESPONSE_CODE_OK, "Unexpected response");
}

View file

@ -29,9 +29,9 @@ void set_socket_events(short events)
my_events |= events; my_events |= events;
} }
void clear_socket_events(void) void clear_socket_events(short events)
{ {
my_events = 0; my_events &= ~events;
} }
int z_impl_zsock_socket(int family, int type, int proto) int z_impl_zsock_socket(int family, int type, int proto)
@ -41,13 +41,14 @@ int z_impl_zsock_socket(int family, int type, int proto)
int z_impl_zvfs_poll(struct zvfs_pollfd *fds, int nfds, int poll_timeout) int z_impl_zvfs_poll(struct zvfs_pollfd *fds, int nfds, int poll_timeout)
{ {
LOG_INF("Polling, events %d", my_events); int events = 0;
k_sleep(K_MSEC(1)); k_sleep(K_MSEC(1));
fds->revents = my_events; for (int i = 0; i < nfds; i++) {
fds[i].revents = my_events & (fds[i].events | ZSOCK_POLLERR | ZSOCK_POLLHUP);
if (my_events) { if (fds[i].revents) {
return 1; events++;
}
} }
return 0; return events;
} }

View file

@ -15,11 +15,30 @@
#include <zephyr/net/coap_client.h> #include <zephyr/net/coap_client.h>
#define ZSOCK_POLLIN 1
/* Copy from zephyr/include/zephyr/net/socket.h */
/**
* @name Options for poll()
* @{
*/
/* ZSOCK_POLL* values are compatible with Linux */
/** zsock_poll: Poll for readability */
#define ZSOCK_POLLIN 1
/** zsock_poll: Poll for exceptional condition */
#define ZSOCK_POLLPRI 2
/** zsock_poll: Poll for writability */
#define ZSOCK_POLLOUT 4 #define ZSOCK_POLLOUT 4
/** zsock_poll: Poll results in error condition (output value only) */
#define ZSOCK_POLLERR 8
/** zsock_poll: Poll detected closed connection (output value only) */
#define ZSOCK_POLLHUP 0x10
/** zsock_poll: Invalid socket (output value only) */
#define ZSOCK_POLLNVAL 0x20
/** @} */
void set_socket_events(short events); void set_socket_events(short events);
void clear_socket_events(void); void clear_socket_events(short events);
DECLARE_FAKE_VALUE_FUNC(uint32_t, z_impl_sys_rand32_get); DECLARE_FAKE_VALUE_FUNC(uint32_t, z_impl_sys_rand32_get);
DECLARE_FAKE_VOID_FUNC(z_impl_sys_rand_get, void *, size_t); DECLARE_FAKE_VOID_FUNC(z_impl_sys_rand_get, void *, size_t);