net: Implement shutdown() for usrsock
Signed-off-by: Zhe Weng <wengzhe@xiaomi.com>
This commit is contained in:
parent
8819eeaf15
commit
d3dd349649
@ -469,6 +469,26 @@ int host_usrsock_ioctl(int fd, unsigned long request, ...)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int host_usrsock_shutdown(int sockfd, int how)
|
||||
{
|
||||
switch (how)
|
||||
{
|
||||
case NUTTX_SHUT_RD:
|
||||
how = SHUT_RD;
|
||||
break;
|
||||
case NUTTX_SHUT_WR:
|
||||
how = SHUT_WR;
|
||||
break;
|
||||
case NUTTX_SHUT_RDWR:
|
||||
how = SHUT_RDWR;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return shutdown(sockfd, how) < 0 ? -errno : 0;
|
||||
}
|
||||
|
||||
void host_usrsock_loop(void)
|
||||
{
|
||||
struct timeval timeout;
|
||||
|
@ -285,6 +285,7 @@ int host_usrsock_listen(int sockfd, int backlog);
|
||||
int host_usrsock_accept(int sockfd, struct nuttx_sockaddr *addr,
|
||||
nuttx_socklen_t *addrlen);
|
||||
int host_usrsock_ioctl(int fd, unsigned long request, ...);
|
||||
int host_usrsock_shutdown(int sockfd, int how);
|
||||
#else
|
||||
int host_usrsock_socket(int domain, int type, int protocol);
|
||||
int host_usrsock_close(int sockfd);
|
||||
@ -311,6 +312,7 @@ int host_usrsock_listen(int sockfd, int backlog);
|
||||
int host_usrsock_accept(int sockfd, struct sockaddr *addr,
|
||||
socklen_t *addrlen);
|
||||
int host_usrsock_ioctl(int fd, unsigned long request, ...);
|
||||
int host_usrsock_shutdown(int sockfd, int how);
|
||||
void host_usrsock_loop(void);
|
||||
#endif /* __SIM__ */
|
||||
|
||||
|
@ -361,6 +361,15 @@ static int usrsock_ioctl_handler(struct usrsock_s *usrsock,
|
||||
req->arglen, req->arglen);
|
||||
}
|
||||
|
||||
static int usrsock_shutdown_handler(struct usrsock_s *usrsock,
|
||||
const void *data, size_t len)
|
||||
{
|
||||
const struct usrsock_request_shutdown_s *req = data;
|
||||
int ret = host_usrsock_shutdown(req->usockid, req->how);
|
||||
|
||||
return usrsock_send_ack(usrsock, req->head.xid, ret);
|
||||
}
|
||||
|
||||
static const usrsock_handler_t g_usrsock_handler[] =
|
||||
{
|
||||
[USRSOCK_REQUEST_SOCKET] = usrsock_socket_handler,
|
||||
@ -376,6 +385,7 @@ static const usrsock_handler_t g_usrsock_handler[] =
|
||||
[USRSOCK_REQUEST_LISTEN] = usrsock_listen_handler,
|
||||
[USRSOCK_REQUEST_ACCEPT] = usrsock_accept_handler,
|
||||
[USRSOCK_REQUEST_IOCTL] = usrsock_ioctl_handler,
|
||||
[USRSOCK_REQUEST_SHUTDOWN] = usrsock_shutdown_handler,
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -110,6 +110,9 @@ static int usrsock_rpmsg_accept_handler(FAR struct rpmsg_endpoint *ept,
|
||||
static int usrsock_rpmsg_ioctl_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv_);
|
||||
static int usrsock_rpmsg_shutdown_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv_);
|
||||
static int usrsock_rpmsg_dns_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv_);
|
||||
@ -148,6 +151,7 @@ static const rpmsg_ept_cb g_usrsock_rpmsg_handler[] =
|
||||
usrsock_rpmsg_listen_handler,
|
||||
usrsock_rpmsg_accept_handler,
|
||||
usrsock_rpmsg_ioctl_handler,
|
||||
usrsock_rpmsg_shutdown_handler,
|
||||
usrsock_rpmsg_dns_handler,
|
||||
};
|
||||
|
||||
@ -880,6 +884,23 @@ static int usrsock_rpmsg_ioctl_handler(FAR struct rpmsg_endpoint *ept,
|
||||
ack, 0, req->head.xid, ret, req->arglen, req->arglen, ret);
|
||||
}
|
||||
|
||||
static int usrsock_rpmsg_shutdown_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv_)
|
||||
{
|
||||
FAR struct usrsock_request_shutdown_s *req = data;
|
||||
FAR struct usrsock_rpmsg_s *priv = priv_;
|
||||
int ret = -EBADF;
|
||||
|
||||
if (req->usockid >= 0 &&
|
||||
req->usockid < CONFIG_NET_USRSOCK_RPMSG_SERVER_NSOCKS)
|
||||
{
|
||||
ret = psock_shutdown(&priv->socks[req->usockid], req->how);
|
||||
}
|
||||
|
||||
return usrsock_rpmsg_send_ack(ept, 0, req->head.xid, ret);
|
||||
}
|
||||
|
||||
static int usrsock_rpmsg_dns_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv_)
|
||||
|
@ -1269,6 +1269,40 @@ int psock_getpeername(FAR struct socket *psock, FAR struct sockaddr *addr,
|
||||
int psock_vioctl(FAR struct socket *psock, int cmd, va_list ap);
|
||||
int psock_ioctl(FAR struct socket *psock, int cmd, ...);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: psock_shutdown
|
||||
*
|
||||
* Description:
|
||||
* The shutdown() function will cause all or part of a full-duplex
|
||||
* connection on the socket associated with the file descriptor socket to
|
||||
* be shut down.
|
||||
*
|
||||
* The shutdown() function disables subsequent send and/or receive
|
||||
* operations on a socket, depending on the value of the how argument.
|
||||
*
|
||||
* Input Parameters:
|
||||
* sockfd - Specifies the file descriptor of the socket.
|
||||
* how - Specifies the type of shutdown. The values are as follows:
|
||||
*
|
||||
* SHUT_RD - Disables further receive operations.
|
||||
* SHUT_WR - Disables further send operations.
|
||||
* SHUT_RDWR - Disables further send and receive operations.
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, returns the number of characters sent. On any failure, a
|
||||
* negated errno value is returned. One of:
|
||||
*
|
||||
* EINVAL - The how argument is invalid.
|
||||
* ENOTCONN - The socket is not connected.
|
||||
* ENOTSOCK - The socket argument does not refer to a socket.
|
||||
* ENOBUFS - Insufficient resources were available in the system to
|
||||
* perform the operation.
|
||||
* EOPNOTSUPP - The operation is not supported for this socket's protocol
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int psock_shutdown(FAR struct socket *psock, int how);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: psock_poll
|
||||
*
|
||||
|
@ -85,6 +85,7 @@ enum usrsock_request_types_e
|
||||
USRSOCK_REQUEST_LISTEN,
|
||||
USRSOCK_REQUEST_ACCEPT,
|
||||
USRSOCK_REQUEST_IOCTL,
|
||||
USRSOCK_REQUEST_SHUTDOWN,
|
||||
USRSOCK_REQUEST__MAX
|
||||
};
|
||||
|
||||
@ -219,6 +220,14 @@ begin_packed_struct struct usrsock_request_ioctl_s
|
||||
uint16_t arglen;
|
||||
} end_packed_struct;
|
||||
|
||||
begin_packed_struct struct usrsock_request_shutdown_s
|
||||
{
|
||||
struct usrsock_request_common_s head;
|
||||
|
||||
int16_t usockid;
|
||||
int16_t how;
|
||||
} end_packed_struct;
|
||||
|
||||
/* Response/event message structures (kernel <= /dev/usrsock <= daemon) */
|
||||
|
||||
begin_packed_struct struct usrsock_message_common_s
|
||||
|
@ -55,12 +55,15 @@
|
||||
* SHUT_RDWR - Disables further send and receive operations.
|
||||
*
|
||||
* Returned Value:
|
||||
* EINVAL - The how argument is invalid.
|
||||
* ENOTCONN - The socket is not connected.
|
||||
* ENOTSOCK - The socket argument does not refer to a socket.
|
||||
* ENOBUFS - Insufficient resources were available in the system to
|
||||
* perform the operation.
|
||||
* EOPNOTSUPP - The operation is not supported for this socket's protocol.
|
||||
* On success, returns the number of characters sent. On any failure, a
|
||||
* negated errno value is returned. One of:
|
||||
*
|
||||
* EINVAL - The how argument is invalid.
|
||||
* ENOTCONN - The socket is not connected.
|
||||
* ENOTSOCK - The socket argument does not refer to a socket.
|
||||
* ENOBUFS - Insufficient resources were available in the system to
|
||||
* perform the operation.
|
||||
* EOPNOTSUPP - The operation is not supported for this socket's protocol
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
|
@ -23,7 +23,7 @@
|
||||
ifeq ($(CONFIG_NET_USRSOCK),y)
|
||||
|
||||
NET_CSRCS += usrsock_close.c usrsock_conn.c usrsock_bind.c usrsock_connect.c
|
||||
NET_CSRCS += usrsock_getpeername.c usrsock_devif.c
|
||||
NET_CSRCS += usrsock_getpeername.c usrsock_devif.c usrsock_shutdown.c
|
||||
NET_CSRCS += usrsock_event.c usrsock_getsockname.c usrsock_getsockopt.c
|
||||
NET_CSRCS += usrsock_poll.c usrsock_recvmsg.c usrsock_sendmsg.c
|
||||
NET_CSRCS += usrsock_setsockopt.c usrsock_socket.c usrsock_sockif.c
|
||||
|
@ -642,6 +642,29 @@ int usrsock_getpeername(FAR struct socket *psock,
|
||||
|
||||
int usrsock_ioctl(FAR struct socket *psock, int cmd, unsigned long arg);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: usrsock_shutdown
|
||||
*
|
||||
* Description:
|
||||
* The shutdown() function will cause all or part of a full-duplex
|
||||
* connection on the socket associated with the file descriptor socket to
|
||||
* be shut down.
|
||||
*
|
||||
* The shutdown() function disables subsequent send and/or receive
|
||||
* operations on a socket, depending on the value of the how argument.
|
||||
*
|
||||
* Input Parameters:
|
||||
* psock A reference to the socket structure of the socket
|
||||
* how Specifies the type of shutdown. The values are as follows:
|
||||
*
|
||||
* SHUT_RD - Disables further receive operations.
|
||||
* SHUT_WR - Disables further send operations.
|
||||
* SHUT_RDWR - Disables further send and receive operations.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int usrsock_shutdown(FAR struct socket *psock, int how);
|
||||
|
||||
#undef EXTERN
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
188
net/usrsock/usrsock_shutdown.c
Normal file
188
net/usrsock/usrsock_shutdown.c
Normal file
@ -0,0 +1,188 @@
|
||||
/****************************************************************************
|
||||
* net/usrsock/usrsock_shutdown.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#if defined(CONFIG_NET) && defined(CONFIG_NET_USRSOCK)
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <arch/irq.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <nuttx/net/net.h>
|
||||
#include <nuttx/net/usrsock.h>
|
||||
|
||||
#include "usrsock/usrsock.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static uint16_t shutdown_event(FAR struct net_driver_s *dev,
|
||||
FAR void *pvpriv, uint16_t flags)
|
||||
{
|
||||
FAR struct usrsock_reqstate_s *pstate = pvpriv;
|
||||
FAR struct usrsock_conn_s *conn = pstate->conn;
|
||||
|
||||
if (flags & USRSOCK_EVENT_ABORT)
|
||||
{
|
||||
ninfo("socket aborted.\n");
|
||||
|
||||
pstate->result = -ECONNABORTED;
|
||||
|
||||
/* Stop further callbacks */
|
||||
|
||||
pstate->cb->flags = 0;
|
||||
pstate->cb->priv = NULL;
|
||||
pstate->cb->event = NULL;
|
||||
|
||||
/* Wake up the waiting thread */
|
||||
|
||||
nxsem_post(&pstate->recvsem);
|
||||
}
|
||||
else if (flags & USRSOCK_EVENT_REQ_COMPLETE)
|
||||
{
|
||||
ninfo("request completed.\n");
|
||||
|
||||
pstate->result = conn->resp.result;
|
||||
|
||||
/* Stop further callbacks */
|
||||
|
||||
pstate->cb->flags = 0;
|
||||
pstate->cb->priv = NULL;
|
||||
pstate->cb->event = NULL;
|
||||
|
||||
/* Wake up the waiting thread */
|
||||
|
||||
nxsem_post(&pstate->recvsem);
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: do_shutdown_request
|
||||
****************************************************************************/
|
||||
|
||||
static int do_shutdown_request(FAR struct usrsock_conn_s *conn, int how)
|
||||
{
|
||||
struct usrsock_request_shutdown_s req =
|
||||
{
|
||||
};
|
||||
|
||||
struct iovec bufs[1];
|
||||
|
||||
/* Prepare request for daemon to read. */
|
||||
|
||||
req.head.reqid = USRSOCK_REQUEST_SHUTDOWN;
|
||||
req.usockid = conn->usockid;
|
||||
req.how = how;
|
||||
|
||||
bufs[0].iov_base = (FAR void *)&req;
|
||||
bufs[0].iov_len = sizeof(req);
|
||||
|
||||
return usrsock_do_request(conn, bufs, ARRAY_SIZE(bufs));
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: usrsock_shutdown
|
||||
*
|
||||
* Description:
|
||||
* The shutdown() function will cause all or part of a full-duplex
|
||||
* connection on the socket associated with the file descriptor socket to
|
||||
* be shut down.
|
||||
*
|
||||
* The shutdown() function disables subsequent send and/or receive
|
||||
* operations on a socket, depending on the value of the how argument.
|
||||
*
|
||||
* Input Parameters:
|
||||
* psock A reference to the socket structure of the socket
|
||||
* how Specifies the type of shutdown. The values are as follows:
|
||||
*
|
||||
* SHUT_RD - Disables further receive operations.
|
||||
* SHUT_WR - Disables further send operations.
|
||||
* SHUT_RDWR - Disables further send and receive operations.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int usrsock_shutdown(FAR struct socket *psock, int how)
|
||||
{
|
||||
FAR struct usrsock_conn_s *conn = psock->s_conn;
|
||||
struct usrsock_reqstate_s state =
|
||||
{
|
||||
};
|
||||
|
||||
int ret;
|
||||
|
||||
net_lock();
|
||||
|
||||
if (conn->state == USRSOCK_CONN_STATE_UNINITIALIZED ||
|
||||
conn->state == USRSOCK_CONN_STATE_ABORTED)
|
||||
{
|
||||
/* Already closed? */
|
||||
|
||||
ninfo("usockid=%d; already closed.\n", conn->usockid);
|
||||
|
||||
ret = OK;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Set up event callback for usrsock. */
|
||||
|
||||
ret = usrsock_setup_request_callback(conn, &state, shutdown_event,
|
||||
USRSOCK_EVENT_ABORT |
|
||||
USRSOCK_EVENT_REQ_COMPLETE);
|
||||
if (ret < 0)
|
||||
{
|
||||
nwarn("usrsock_setup_request_callback failed: %d\n", ret);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Request user-space daemon to shutdown socket. */
|
||||
|
||||
ret = do_shutdown_request(conn, how);
|
||||
if (ret >= 0)
|
||||
{
|
||||
/* Wait for completion of request. */
|
||||
|
||||
net_sem_wait_uninterruptible(&state.recvsem);
|
||||
ret = state.result;
|
||||
}
|
||||
|
||||
usrsock_teardown_request_callback(&state);
|
||||
|
||||
errout:
|
||||
net_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NET && CONFIG_NET_USRSOCK */
|
@ -68,7 +68,7 @@ const struct sock_intf_s g_usrsock_sockif =
|
||||
usrsock_sockif_close, /* si_close */
|
||||
usrsock_ioctl, /* si_ioctl */
|
||||
NULL, /* si_socketpair */
|
||||
NULL /* si_shutdown */
|
||||
usrsock_shutdown /* si_shutdown */
|
||||
#ifdef CONFIG_NET_SOCKOPTS
|
||||
, usrsock_getsockopt /* si_getsockopt */
|
||||
, usrsock_setsockopt /* si_setsockopt */
|
||||
|
Loading…
Reference in New Issue
Block a user