net: websocket: Fix poll handling for offloaded sockets

ZFD_IOCTL_POLL_OFFLOAD operation needed special handling, as it needed
to modify the fds table for the offloaded implementation, overwriting
websocket file descriptors with the underlying offloaded ones. This is
only needed for the offloaded sockets, as the native implmentation use
POLL_PREPARE/UPDATE operations instead.

Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
This commit is contained in:
Robert Lubos 2021-08-03 16:11:56 +02:00 committed by Carles Cufí
parent a6a9d7a368
commit bbc6c66ed8

View file

@ -434,23 +434,88 @@ static int websocket_close_vmeth(void *obj)
return ret;
}
static inline int websocket_poll_offload(struct zsock_pollfd *fds, int nfds,
int timeout)
{
int fd_backup[CONFIG_NET_SOCKETS_POLL_MAX];
const struct fd_op_vtable *vtable;
void *ctx;
int ret = 0;
int i;
/* Overwrite websocket file decriptors with underlying ones. */
for (i = 0; i < nfds; i++) {
fd_backup[i] = fds[i].fd;
ctx = z_get_fd_obj(fds[i].fd,
(const struct fd_op_vtable *)
&websocket_fd_op_vtable,
0);
if (ctx == NULL) {
continue;
}
fds[i].fd = ((struct websocket_context *)ctx)->real_sock;
}
/* Get offloaded sockets vtable. */
ctx = z_get_fd_obj_and_vtable(fds[0].fd,
(const struct fd_op_vtable **)&vtable,
NULL);
if (ctx == NULL) {
errno = EINVAL;
ret = -1;
goto exit;
}
ret = z_fdtable_call_ioctl(vtable, ctx, ZFD_IOCTL_POLL_OFFLOAD,
fds, nfds, timeout);
exit:
/* Restore original fds. */
for (i = 0; i < nfds; i++) {
fds[i].fd = fd_backup[i];
}
return ret;
}
static int websocket_ioctl_vmeth(void *obj, unsigned int request, va_list args)
{
struct websocket_context *ctx = obj;
const struct fd_op_vtable *vtable;
void *core_obj;
core_obj = z_get_fd_obj_and_vtable(
ctx->real_sock,
(const struct fd_op_vtable **)&vtable,
NULL);
if (core_obj == NULL) {
errno = EBADF;
return -1;
switch (request) {
case ZFD_IOCTL_POLL_OFFLOAD: {
struct zsock_pollfd *fds;
int nfds;
int timeout;
fds = va_arg(args, struct zsock_pollfd *);
nfds = va_arg(args, int);
timeout = va_arg(args, int);
return websocket_poll_offload(fds, nfds, timeout);
}
/* Pass the call to the core socket implementation. */
return vtable->ioctl(core_obj, request, args);
default: {
const struct fd_op_vtable *vtable;
void *core_obj;
core_obj = z_get_fd_obj_and_vtable(
ctx->real_sock,
(const struct fd_op_vtable **)&vtable,
NULL);
if (core_obj == NULL) {
errno = EBADF;
return -1;
}
/* Pass the call to the core socket implementation. */
return vtable->ioctl(core_obj, request, args);
}
}
return 0;
}
static int websocket_prepare_and_send(struct websocket_context *ctx,