net: sockets: Implement poll() operation.
poll() allows to (efficiently) wait for available data on sockets, and is essential operation for working with non-blocking sockets. This is initial, very basic implementation, effectively supporting just POLLIN operation. (POLLOUT implementation is dummy - it's assumed that socket is always writable, as there's currently no reasonable way to test that.) Signed-off-by: Paul Sokolovsky <paul.sokolovsky@linaro.org>
This commit is contained in:
parent
74afcb67ae
commit
2c2e8b26b4
3 changed files with 98 additions and 0 deletions
|
@ -15,6 +15,16 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct zsock_pollfd {
|
||||
int fd;
|
||||
short events;
|
||||
short revents;
|
||||
};
|
||||
|
||||
/* Values are compatible with Linux */
|
||||
#define ZSOCK_POLLIN 1
|
||||
#define ZSOCK_POLLOUT 4
|
||||
|
||||
int zsock_socket(int family, int type, int proto);
|
||||
int zsock_close(int sock);
|
||||
int zsock_bind(int sock, const struct sockaddr *addr, socklen_t addrlen);
|
||||
|
@ -24,6 +34,7 @@ int zsock_accept(int sock, struct sockaddr *addr, socklen_t *addrlen);
|
|||
ssize_t zsock_send(int sock, const void *buf, size_t len, int flags);
|
||||
ssize_t zsock_recv(int sock, void *buf, size_t max_len, int flags);
|
||||
int zsock_fcntl(int sock, int cmd, int flags);
|
||||
int zsock_poll(struct zsock_pollfd *fds, int nfds, int timeout);
|
||||
|
||||
#if defined(CONFIG_NET_SOCKETS_POSIX_NAMES)
|
||||
#define socket zsock_socket
|
||||
|
@ -36,6 +47,11 @@ int zsock_fcntl(int sock, int cmd, int flags);
|
|||
#define recv zsock_recv
|
||||
#define fcntl zsock_fcntl
|
||||
|
||||
#define poll zsock_poll
|
||||
#define pollfd zsock_pollfd
|
||||
#define POLLIN ZSOCK_POLLIN
|
||||
#define POLLOUT ZSOCK_POLLOUT
|
||||
|
||||
#define inet_ntop net_addr_ntop
|
||||
#define inet_pton net_addr_pton
|
||||
#endif
|
||||
|
|
|
@ -25,6 +25,13 @@ config NET_SOCKETS_POSIX_NAMES
|
|||
attention, as in POSIX it closes any file descriptor, while with this
|
||||
option enaled, it will still apply only to sockets.
|
||||
|
||||
config NET_SOCKETS_POLL_MAX
|
||||
int
|
||||
prompt "Max number of supported poll() entries"
|
||||
default 3
|
||||
help
|
||||
Maximum number of entries supported for poll() call.
|
||||
|
||||
config NET_DEBUG_SOCKETS
|
||||
bool "Debug BSD Sockets like API calls"
|
||||
default n
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <sys/fcntl.h>
|
||||
|
||||
/* Zephyr headers */
|
||||
#include <kernel.h>
|
||||
#include <net/net_context.h>
|
||||
#include <net/net_pkt.h>
|
||||
#include <net/socket.h>
|
||||
|
@ -23,6 +24,8 @@
|
|||
#define SET_ERRNO(x) \
|
||||
{ int _err = x; if (_err < 0) { errno = -_err; return -1; } }
|
||||
|
||||
static struct k_poll_event poll_events[CONFIG_NET_SOCKETS_POLL_MAX];
|
||||
|
||||
static inline void sock_set_flag(struct net_context *ctx, u32_t mask,
|
||||
u32_t flag)
|
||||
{
|
||||
|
@ -375,3 +378,75 @@ int zsock_fcntl(int sock, int cmd, int flags)
|
|||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int zsock_poll(struct zsock_pollfd *fds, int nfds, int timeout)
|
||||
{
|
||||
int i;
|
||||
int ret = 0;
|
||||
struct zsock_pollfd *pfd;
|
||||
struct k_poll_event *pev;
|
||||
struct k_poll_event *pev_end = poll_events + ARRAY_SIZE(poll_events);
|
||||
|
||||
if (timeout < 0) {
|
||||
timeout = K_FOREVER;
|
||||
}
|
||||
|
||||
pev = poll_events;
|
||||
for (pfd = fds, i = nfds; i--; pfd++) {
|
||||
|
||||
/* Per POSIX, negative fd's are just ignored */
|
||||
if (pfd->fd < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pfd->events & POLLIN) {
|
||||
struct net_context *ctx = INT_TO_POINTER(pfd->fd);
|
||||
|
||||
if (pev == pev_end) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
pev->obj = &ctx->recv_q;
|
||||
pev->type = K_POLL_TYPE_FIFO_DATA_AVAILABLE;
|
||||
pev->mode = K_POLL_MODE_NOTIFY_ONLY;
|
||||
pev->state = K_POLL_STATE_NOT_READY;
|
||||
pev++;
|
||||
}
|
||||
}
|
||||
|
||||
ret = k_poll(poll_events, pev - poll_events, timeout);
|
||||
if (ret != 0 && ret != -EAGAIN) {
|
||||
errno = -ret;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
pev = poll_events;
|
||||
for (pfd = fds, i = nfds; i--; pfd++) {
|
||||
pfd->revents = 0;
|
||||
|
||||
if (pfd->fd < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* For now, assume that socket is always writable */
|
||||
if (pfd->events & POLLOUT) {
|
||||
pfd->revents |= POLLOUT;
|
||||
}
|
||||
|
||||
if (pfd->events & POLLIN) {
|
||||
if (pev->state != K_POLL_STATE_NOT_READY) {
|
||||
pfd->revents |= POLLIN;
|
||||
}
|
||||
pev++;
|
||||
}
|
||||
|
||||
if (pfd->revents != 0) {
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue