diff --git a/net/rpmsg/rpmsg_sockif.c b/net/rpmsg/rpmsg_sockif.c index 50c2bc7ec3..ac589ff241 100644 --- a/net/rpmsg/rpmsg_sockif.c +++ b/net/rpmsg/rpmsg_sockif.c @@ -52,6 +52,7 @@ #define RPMSG_SOCKET_CMD_SYNC 1 #define RPMSG_SOCKET_CMD_DATA 2 +#define RPMSG_SOCKET_CMD_SHUTDOWN 3 #define RPMSG_SOCKET_NAME_PREFIX "sk:" #define RPMSG_SOCKET_NAME_PREFIX_LEN 3 #define RPMSG_SOCKET_NAME_ID_LEN 13 @@ -83,6 +84,12 @@ begin_packed_struct struct rpmsg_socket_data_s char data[0]; } end_packed_struct; +begin_packed_struct struct rpmsg_socket_shutdown_s +{ + uint32_t cmd; + uint32_t how; +} end_packed_struct; + struct rpmsg_socket_conn_s { /* Common prologue of all connection structures. */ @@ -95,6 +102,7 @@ struct rpmsg_socket_conn_s struct sockaddr_rpmsg rpaddr; char nameid[RPMSG_SOCKET_NAME_ID_LEN]; uint16_t crefs; + uint32_t how; FAR struct pollfd *fds[CONFIG_NET_RPMSG_NPOLLWAITERS]; mutex_t polllock; @@ -172,6 +180,7 @@ static ssize_t rpmsg_socket_recvmsg(FAR struct socket *psock, static int rpmsg_socket_close(FAR struct socket *psock); static int rpmsg_socket_ioctl(FAR struct socket *psock, int cmd, unsigned long arg); +static int rpmsg_socket_shutdown(FAR struct socket *psock, int how); #ifdef CONFIG_NET_SOCKOPTS static int rpmsg_socket_getsockopt(FAR struct socket *psock, int level, int option, @@ -204,7 +213,7 @@ const struct sock_intf_s g_rpmsg_sockif = rpmsg_socket_close, /* si_close */ rpmsg_socket_ioctl, /* si_ioctl */ NULL, /* si_socketpair */ - NULL /* si_shutdown */ + rpmsg_socket_shutdown /* si_shutdown */ #ifdef CONFIG_NET_SOCKOPTS , rpmsg_socket_getsockopt /* si_getsockopt */ , rpmsg_socket_setsockopt /* si_setsockopt */ @@ -340,7 +349,7 @@ static int rpmsg_socket_ept_cb(FAR struct rpmsg_endpoint *ept, rpmsg_socket_poll_notify(conn, POLLOUT); nxmutex_unlock(&conn->recvlock); } - else + else if (head->cmd == RPMSG_SOCKET_CMD_DATA) { FAR struct rpmsg_socket_data_s *msg = data; FAR uint8_t *buf = (FAR uint8_t *)msg->data; @@ -408,6 +417,26 @@ static int rpmsg_socket_ept_cb(FAR struct rpmsg_endpoint *ept, nxmutex_unlock(&conn->recvlock); } } + else if (head->cmd == RPMSG_SOCKET_CMD_SHUTDOWN) + { + FAR struct rpmsg_socket_shutdown_s *msg = data; + + if (msg->how & SHUT_WR) + { + conn->how |= SHUT_RD; + + rpmsg_socket_post(&conn->recvsem); + rpmsg_socket_poll_notify(conn, POLLIN | POLLHUP); + } + + if (msg->how & SHUT_RD) + { + conn->how |= SHUT_WR; + + rpmsg_socket_post(&conn->sendsem); + rpmsg_socket_poll_notify(conn, POLLOUT | POLLHUP); + } + } return 0; } @@ -1221,6 +1250,11 @@ static ssize_t rpmsg_socket_sendmsg(FAR struct socket *psock, return -ECONNRESET; } + if (conn->how & SHUT_WR) + { + return -EPIPE; + } + nonblock = _SS_ISNONBLOCK(conn->sconn.s_flags) || (flags & MSG_DONTWAIT) != 0; @@ -1259,6 +1293,11 @@ static ssize_t rpmsg_socket_recvmsg(FAR struct socket *psock, return -EISCONN; } + if (conn->how & SHUT_RD) + { + return 0; + } + nxmutex_lock(&conn->recvlock); if (psock->s_type != SOCK_STREAM) @@ -1425,6 +1464,29 @@ static int rpmsg_socket_ioctl(FAR struct socket *psock, return ret; } +static int rpmsg_socket_shutdown(FAR struct socket *psock, int how) +{ + FAR struct rpmsg_socket_conn_s *conn = psock->s_conn; + struct rpmsg_socket_shutdown_s msg; + int ret; + + if (!conn->ept.rdev || conn->unbind) + { + return -ENOTCONN; + } + + conn->how |= how; + + msg.cmd = RPMSG_SOCKET_CMD_SHUTDOWN; + msg.how = how; + + ret = rpmsg_send(&conn->ept, &msg, sizeof(msg)); + if (ret < 0) + return ret; + + return OK; +} + #ifdef CONFIG_NET_SOCKOPTS static int rpmsg_socket_getsockopt(FAR struct socket *psock, int level, int option, FAR void *value,