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:
parent
a6a9d7a368
commit
bbc6c66ed8
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue