You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by gn...@apache.org on 2020/06/02 14:09:43 UTC
[incubator-nuttx] 25/31: Socket: Control message addded initial
stubs for sendmsg()
This is an automated email from the ASF dual-hosted git repository.
gnutt pushed a commit to branch SocketCAN
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit b37b61614d4a843568bbac4dc4a0f92f5738224b
Author: Peter van der Perk <pe...@nxp.com>
AuthorDate: Fri Mar 13 18:12:29 2020 +0100
Socket: Control message addded initial stubs for sendmsg()
---
arch/arm/src/s32k1xx/Kconfig | 1 +
arch/arm/src/s32k1xx/s32k1xx_flexcan.c | 9 +-
include/netpacket/can.h | 2 +
include/nuttx/net/net.h | 8 +-
libs/libc/net/lib_recvmsg.c | 4 +-
libs/libc/net/lib_sendmsg.c | 4 +-
net/bluetooth/bluetooth_sockif.c | 3 +-
net/can/Kconfig | 20 ++++
net/can/can.h | 16 +--
net/can/can_getsockopt.c | 21 ++++
net/can/can_recvfrom.c | 191 +++++++++++++++------------------
net/can/can_send.c | 4 +
net/can/can_setsockopt.c | 10 ++
net/can/can_sockif.c | 51 ++++++++-
net/icmp/icmp_sockif.c | 3 +-
net/icmpv6/icmpv6_sockif.c | 3 +-
net/ieee802154/ieee802154_sockif.c | 3 +-
net/inet/inet_sockif.c | 3 +-
net/local/local_sockif.c | 3 +-
net/netlink/netlink_sockif.c | 3 +-
net/pkt/pkt_sockif.c | 3 +-
net/socket/Kconfig | 14 +--
net/socket/Make.defs | 5 +-
net/socket/recvmsg.c | 4 +-
net/socket/{recvmsg.c => sendmsg.c} | 68 ++++++------
25 files changed, 280 insertions(+), 176 deletions(-)
diff --git a/arch/arm/src/s32k1xx/Kconfig b/arch/arm/src/s32k1xx/Kconfig
index 68f9bb6..41638d0 100644
--- a/arch/arm/src/s32k1xx/Kconfig
+++ b/arch/arm/src/s32k1xx/Kconfig
@@ -152,6 +152,7 @@ config S32K1XX_ENET
config S32K1XX_FLEXCAN
bool "FLEXCAN"
+ select NET_CAN_HAVE_TX_DEADLINE
default n
menuconfig S32K1XX_LPI2C0
diff --git a/arch/arm/src/s32k1xx/s32k1xx_flexcan.c b/arch/arm/src/s32k1xx/s32k1xx_flexcan.c
index 15e5b62..5c02aa0 100644
--- a/arch/arm/src/s32k1xx/s32k1xx_flexcan.c
+++ b/arch/arm/src/s32k1xx/s32k1xx_flexcan.c
@@ -433,10 +433,7 @@ static int s32k1xx_transmit(FAR struct s32k1xx_driver_s *priv)
mb->id.std = frame->can_id & MASKSTDID;
}
- #if 0
- /* cs.rtr = frame.isRemoteTransmissionRequest(); */
- #endif
-
+ cs.rtr = frame->can_id & FLAGRTR ? 1 : 0;
cs.dlc = frame->can_dlc;
mb->data[0].w00 = __builtin_bswap32(*(uint32_t *)&frame->data[0]);
@@ -458,9 +455,7 @@ static int s32k1xx_transmit(FAR struct s32k1xx_driver_s *priv)
mb->id.std = frame->can_id & MASKSTDID;
}
-#if 0
- /* cs.rtr = frame.isRemoteTransmissionRequest(); */
-#endif
+ cs.rtr = frame->can_id & FLAGRTR ? 1 : 0;
if (frame->len < 9)
{
diff --git a/include/netpacket/can.h b/include/netpacket/can.h
index 4ea2104..bd0442d 100644
--- a/include/netpacket/can.h
+++ b/include/netpacket/can.h
@@ -75,6 +75,8 @@
/* allow CAN FD frames (default:off) */
#define CAN_RAW_JOIN_FILTERS (__SO_PROTOCOL + 5)
/* all filters must match to trigger */
+#define CAN_RAW_TX_DEADLINE (__SO_PROTOCOL + 6)
+ /* Abort frame when deadline has been passed */
/****************************************************************************
* Public Types
diff --git a/include/nuttx/net/net.h b/include/nuttx/net/net.h
index 27c5fe9..055c865 100644
--- a/include/nuttx/net/net.h
+++ b/include/nuttx/net/net.h
@@ -217,7 +217,7 @@ struct sock_intf_s
FAR socklen_t *fromlen);
#ifdef CONFIG_NET_RECVMSG_CMSG
CODE ssize_t (*si_recvmsg)(FAR struct socket *psock,
- FAR struct msghdr *msg, int flags);
+ FAR struct msghdr *msg, int flags);
#endif
CODE int (*si_close)(FAR struct socket *psock);
#ifdef CONFIG_NET_USRSOCK
@@ -507,9 +507,9 @@ FAR struct iob_s *net_ioballoc(bool throttled, enum iob_user_e consumerid);
* Description:
* Check if the socket descriptor is valid for the provided TCB and if it
* supports the requested access. This trivial operation is part of the
- * fdopen() operation when the fdopen() is performed on a socket
- * descriptor. It simply performs some sanity checking before permitting
- * the socket descriptor to be wrapped as a C FILE stream.
+ * fdopen() operation when the fdopen() is performed on a socket descriptor.
+ * It simply performs some sanity checking before permitting the socket
+ * descriptor to be wrapped as a C FILE stream.
*
****************************************************************************/
diff --git a/libs/libc/net/lib_recvmsg.c b/libs/libc/net/lib_recvmsg.c
index 5200acd..071c189 100644
--- a/libs/libc/net/lib_recvmsg.c
+++ b/libs/libc/net/lib_recvmsg.c
@@ -39,7 +39,7 @@
#include <nuttx/config.h>
-#if defined(CONFIG_NET) && !defined(CONFIG_NET_RECVMSG_CMSG)
+#if defined(CONFIG_NET) && !defined(CONFIG_NET_CMSG)
#include <sys/types.h>
#include <sys/socket.h>
@@ -87,4 +87,4 @@ ssize_t recvmsg(int sockfd, FAR struct msghdr *msg, int flags)
}
}
-#endif /* CONFIG_NET && !CONFIG_NET_RECVMSG_CMSG */
+#endif /* CONFIG_NET && !CONFIG_NET_CMSG */
diff --git a/libs/libc/net/lib_sendmsg.c b/libs/libc/net/lib_sendmsg.c
index 0d09faa..9f98e51 100644
--- a/libs/libc/net/lib_sendmsg.c
+++ b/libs/libc/net/lib_sendmsg.c
@@ -39,7 +39,7 @@
#include <nuttx/config.h>
-#ifdef CONFIG_NET
+#if defined(CONFIG_NET) && !defined(CONFIG_NET_CMSG)
#include <sys/types.h>
#include <sys/socket.h>
@@ -86,4 +86,4 @@ ssize_t sendmsg(int sockfd, FAR struct msghdr *msg, int flags)
}
}
-#endif /* CONFIG_NET */
+#endif /* CONFIG_NET && !CONFIG_NET_CMSG */
diff --git a/net/bluetooth/bluetooth_sockif.c b/net/bluetooth/bluetooth_sockif.c
index fd6d95f..4057d93 100644
--- a/net/bluetooth/bluetooth_sockif.c
+++ b/net/bluetooth/bluetooth_sockif.c
@@ -109,8 +109,9 @@ const struct sock_intf_s g_bluetooth_sockif =
NULL, /* si_sendfile */
#endif
bluetooth_recvfrom, /* si_recvfrom */
-#ifdef CONFIG_NET_RECVMSG_CMSG
+#ifdef CONFIG_NET_CMSG
NULL, /* si_recvmsg */
+ NULL, /* si_sendmsg */
#endif
bluetooth_close /* si_close */
};
diff --git a/net/can/Kconfig b/net/can/Kconfig
index 3b2e450..ac94021 100644
--- a/net/can/Kconfig
+++ b/net/can/Kconfig
@@ -18,6 +18,10 @@ config NET_CAN
if NET_CAN
+config NET_CAN_HAVE_TX_DEADLINE
+ bool
+ default n
+
config CAN_CONNS
int "Number of CAN connections"
default 4
@@ -27,9 +31,25 @@ config CAN_CONNS
config NET_CAN_SOCK_OPTS
bool "sockopt support"
default n
+ select NET_SOCKOPTS
select NET_CANPROTO_OPTIONS
---help---
Enable support for the CAN socket options
+
+config NET_CAN_RAW_TX_DEADLINE
+ bool "TX deadline sockopt"
+ default n
+ depends on NET_CAN_SOCK_OPTS && NET_CAN_HAVE_TX_DEADLINE
+ select NET_CMSG
+ ---help---
+ Note: Non-standard SocketCAN sockopt, but this options helps us in
+ real-time use cases.
+
+ When the CAN_RAW_TX_DEADLINE sockopt is enabled. The user can send
+ CAN frames using sendmsg() function and add a deadline timespec
+ value in the CMSG data. When the deadline has been passed and the
+ CAN frame is still in the HW TX mailbox then the CAN driver will
+ discard the CAN frame automatically.
config NET_CAN_RAW_FILTER_MAX
int "CAN_RAW_FILTER max filter count"
diff --git a/net/can/can.h b/net/can/can.h
index 7c6b614..00c297d 100644
--- a/net/can/can.h
+++ b/net/can/can.h
@@ -104,20 +104,23 @@ struct can_conn_s
*/
struct can_poll_s pollinfo[4]; /* FIXME make dynamic */
-
+
#ifdef CONFIG_NET_CANPROTO_OPTIONS
int32_t loopback;
int32_t recv_own_msgs;
int32_t fd_frames;
struct can_filter filters[CONFIG_NET_CAN_RAW_FILTER_MAX];
int32_t filter_count;
-
- /* TODO add filter support */
+# ifdef CONFIG_NET_CAN_RAW_TX_DEADLINE
+ int32_t tx_deadline;
+# endif
#endif
-
+
#ifdef CONFIG_NET_TIMESTAMP
FAR struct socket *psock; /* Needed to get SO_TIMESTAMP value */
#endif
+
+
};
/****************************************************************************
@@ -166,8 +169,8 @@ FAR struct can_conn_s *can_alloc(void);
* Name: can_free()
*
* Description:
- * Free a NetLink connection structure that is no longer in use. This
- * should be done by the implementation of close().
+ * Free a NetLink connection structure that is no longer in use. This should
+ * be done by the implementation of close().
*
****************************************************************************/
@@ -256,6 +259,7 @@ uint16_t can_datahandler(FAR struct can_conn_s *conn, FAR uint8_t *buffer,
*
****************************************************************************/
+
ssize_t can_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
int flags, FAR struct sockaddr *from,
FAR socklen_t *fromlen);
diff --git a/net/can/can_getsockopt.c b/net/can/can_getsockopt.c
index 238695c..17184e2 100644
--- a/net/can/can_getsockopt.c
+++ b/net/can/can_getsockopt.c
@@ -188,6 +188,27 @@ int can_getsockopt(FAR struct socket *psock, int option,
case CAN_RAW_JOIN_FILTERS:
break;
+#ifdef CONFIG_NET_CAN_RAW_TX_DEADLINE
+ case CAN_RAW_TX_DEADLINE:
+ if (*value_len < sizeof(conn->tx_deadline))
+ {
+ /* REVISIT: POSIX says that we should truncate the value if it
+ * is larger than value_len. That just doesn't make sense
+ * to me in this case.
+ */
+
+ ret = -EINVAL;
+ }
+ else
+ {
+ FAR int *tx_deadline = (FAR int32_t *)value;
+ *tx_deadline = conn->tx_deadline;
+ *value_len = sizeof(conn->tx_deadline);
+ ret = OK;
+ }
+ break;
+#endif
+
default:
nerr("ERROR: Unrecognized RAW CAN socket option: %d\n", option);
ret = -ENOPROTOOPT;
diff --git a/net/can/can_recvfrom.c b/net/can/can_recvfrom.c
index 2211ed0..d9ed8cb 100644
--- a/net/can/can_recvfrom.c
+++ b/net/can/can_recvfrom.c
@@ -50,19 +50,20 @@
#include <sys/time.h>
#endif
+
/****************************************************************************
* Private Types
****************************************************************************/
struct can_recvfrom_s
{
- FAR struct socket *pr_sock; /* The parent socket structure */
+ FAR struct socket *pr_sock; /* The parent socket structure */
FAR struct devif_callback_s *pr_cb; /* Reference to callback instance */
sem_t pr_sem; /* Semaphore signals recv completion */
size_t pr_buflen; /* Length of receive buffer */
FAR uint8_t *pr_buffer; /* Pointer to receive buffer */
ssize_t pr_recvlen; /* The received length */
-#ifdef CONFIG_NET_RECVMSG_CMSG
+#ifdef CONFIG_NET_CMSG
size_t pr_msglen; /* Length of msg buffer */
FAR uint8_t *pr_msgbuf; /* Pointer to msg buffer */
#endif
@@ -232,15 +233,14 @@ static inline void can_newdata(FAR struct net_driver_s *dev,
static inline int can_readahead(struct can_recvfrom_s *pstate)
{
- FAR struct can_conn_s *conn =
- (FAR struct can_conn_s *) pstate->pr_sock->s_conn;
+ FAR struct can_conn_s *conn = (FAR struct can_conn_s *)pstate->pr_sock->s_conn;
FAR struct iob_s *iob;
int recvlen;
/* Check there is any CAN data already buffered in a read-ahead
* buffer.
*/
-
+
pstate->pr_recvlen = -1;
if ((iob = iob_peek_queue(&conn->readahead)) != NULL &&
@@ -287,16 +287,15 @@ static inline int can_readahead(struct can_recvfrom_s *pstate)
IOBUSER_NET_CAN_READAHEAD);
}
- /* do not pass frames with DLC > 8 to a legacy socket */
-
- if (!conn->fd_frames)
- {
- struct canfd_frame *cfd = (struct canfd_frame *)pstate->pr_buffer;
- if (cfd->len > CAN_MAX_DLEN)
- {
- return 0;
- }
- }
+ /* do not pass frames with DLC > 8 to a legacy socket */
+ if (!conn->fd_frames)
+ {
+ struct canfd_frame *cfd = (struct canfd_frame *)pstate->pr_buffer;
+ if (cfd->len > CAN_MAX_DLEN)
+ {
+ return 0;
+ }
+ }
return recvlen;
}
@@ -320,14 +319,13 @@ static inline int can_readahead(struct can_recvfrom_s *pstate)
* The network is locked.
*
****************************************************************************/
-
#ifdef CONFIG_NET_TIMESTAMP
-static inline int can_readahead_timestamp(struct can_conn_s *conn,
- FAR uint8_t *buffer)
+static inline int can_readahead_timestamp(struct can_conn_s *conn, FAR uint8_t *buffer)
{
FAR struct iob_s *iob;
int recvlen;
+
if ((iob = iob_peek_queue(&conn->readahead)) != NULL)
{
DEBUGASSERT(iob->io_pktlen > 0);
@@ -381,27 +379,26 @@ static inline int can_readahead_timestamp(struct can_conn_s *conn,
#ifdef CONFIG_NET_CANPROTO_OPTIONS
static int can_recv_filter(struct can_conn_s *conn, canid_t id)
{
- for (int i = 0; i < conn->filter_count; i++)
+ for(int i = 0; i < conn->filter_count; i++)
{
- if (conn->filters[i].can_id & CAN_INV_FILTER)
- {
- if ((id & conn->filters[i].can_mask) !=
- ((conn->filters[i].can_id & ~CAN_INV_FILTER) &
- conn->filters[i].can_mask))
- {
- return 1;
- }
- }
- else
- {
- if ((id & conn->filters[i].can_mask) ==
- (conn->filters[i].can_id & conn->filters[i].can_mask))
- {
- return 1;
- }
- }
+ if (conn->filters[i].can_id & CAN_INV_FILTER)
+ {
+ if((id & conn->filters[i].can_mask) !=
+ ((conn->filters[i].can_id & ~CAN_INV_FILTER)
+ & conn->filters[i].can_mask))
+ {
+ return 1;
+ }
+ }
+ else
+ {
+ if((id & conn->filters[i].can_mask) ==
+ (conn->filters[i].can_id & conn->filters[i].can_mask))
+ {
+ return 1;
+ }
+ }
}
-
return 0;
}
#endif
@@ -419,50 +416,46 @@ static uint16_t can_recvfrom_eventhandler(FAR struct net_driver_s *dev,
{
if ((flags & CAN_NEWDATA) != 0)
{
- /* If a new packet is available, check receive filters
- * when is valid then complete the read action.
- */
+ /* If a new packet is available, check receive filters
+ * when is valid then complete the read action. */
#ifdef CONFIG_NET_CANPROTO_OPTIONS
- if (can_recv_filter(conn, (canid_t) *dev->d_appdata) == 0)
- {
- flags &= ~CAN_NEWDATA;
- return flags;
- }
+ if(can_recv_filter(conn,(canid_t)*dev->d_appdata) == 0)
+ {
+ flags &= ~CAN_NEWDATA;
+ return flags;
+ }
#endif
- /* do not pass frames with DLC > 8 to a legacy socket */
-
- if (!conn->fd_frames)
- {
- struct canfd_frame *cfd = (struct canfd_frame *)dev->d_appdata;
- if (cfd->len > CAN_MAX_DLEN)
- {
- /* DO WE NEED TO CLEAR FLAGS?? */
-
- flags &= ~CAN_NEWDATA;
- return flags;
- }
- }
+ /* do not pass frames with DLC > 8 to a legacy socket */
+ if (!conn->fd_frames)
+ {
+ struct canfd_frame *cfd = (struct canfd_frame*)dev->d_appdata;
+ if (cfd->len > CAN_MAX_DLEN)
+ {
+ /* DO WE NEED TO CLEAR FLAGS?? */
+ flags &= ~CAN_NEWDATA;
+ return flags;
+ }
+ }
/* Copy the packet */
can_newdata(dev, pstate);
#ifdef CONFIG_NET_TIMESTAMP
- if (pstate->pr_sock->s_timestamp)
- {
- if (pstate->pr_msglen == sizeof(struct timeval))
- {
- can_readahead_timestamp(conn, pstate->pr_msgbuf);
- }
- else
- {
- /* We still have to consume the data otherwise IOB gets full */
-
- uint8_t dummy_buf[sizeof(struct timeval)];
- can_readahead_timestamp(conn, &dummy_buf);
- }
- }
+ if(pstate->pr_sock->s_timestamp)
+ {
+ if(pstate->pr_msglen == sizeof(struct timeval))
+ {
+ can_readahead_timestamp(conn, pstate->pr_msgbuf);
+ }
+ else
+ {
+ /* We still have to consume the data otherwise IOB gets full */
+ uint8_t dummy_buf[sizeof(struct timeval)];
+ can_readahead_timestamp(conn, &dummy_buf);
+ }
+ }
#endif
/* We are finished. */
@@ -515,7 +508,6 @@ static ssize_t can_recvfrom_result(int result,
if (pstate->pr_result < 0)
{
/* This might return EAGAIN on a timeout */
-
return pstate->pr_result;
}
@@ -600,10 +592,10 @@ ssize_t can_recvfrom(FAR struct socket *psock, FAR void *buf,
ret = can_readahead(&state);
if (ret > 0)
- {
+ {
goto errout_with_state;
}
-
+
ret = state.pr_recvlen;
/* Handle non-blocking CAN sockets */
@@ -618,7 +610,7 @@ ssize_t can_recvfrom(FAR struct socket *psock, FAR void *buf,
{
/* Nothing was received */
- ret = -EAGAIN;
+ ret = -EAGAIN;
goto errout_with_state;
}
}
@@ -683,7 +675,6 @@ errout_with_state:
* flags Receive flags (ignored)
*
****************************************************************************/
-
#ifdef CONFIG_NET_RECVMSG_CMSG
ssize_t can_recvmsg(FAR struct socket *psock, FAR struct msghdr *msg,
size_t len, int flags)
@@ -716,22 +707,20 @@ ssize_t can_recvmsg(FAR struct socket *psock, FAR struct msghdr *msg,
nxsem_init(&state.pr_sem, 0, 0); /* Doesn't really fail */
nxsem_setprotocol(&state.pr_sem, SEM_PRIO_NONE);
+
state.pr_buflen = msg->msg_iov->iov_len;
state.pr_buffer = msg->msg_iov->iov_base;
-
#ifdef CONFIG_NET_TIMESTAMP
- if (psock->s_timestamp && msg->msg_controllen ==
- (sizeof(struct cmsghdr) + sizeof(struct timeval)))
+ if(psock->s_timestamp && msg->msg_controllen == (sizeof(struct cmsghdr) + sizeof(struct timeval)))
{
- struct cmsghdr *cmsg = CMSG_FIRSTHDR(msg);
- state.pr_msglen = sizeof(struct timeval);
- state.pr_msgbuf = CMSG_DATA(cmsg);
- cmsg->cmsg_level = SOL_SOCKET;
- cmsg->cmsg_type = SO_TIMESTAMP;
- cmsg->cmsg_len = state.pr_msglen;
+ struct cmsghdr* cmsg = CMSG_FIRSTHDR(msg);
+ state.pr_msglen = sizeof(struct timeval);
+ state.pr_msgbuf = CMSG_DATA(cmsg);
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SO_TIMESTAMP;
+ cmsg->cmsg_len = state.pr_msglen;
}
#endif
-
state.pr_sock = psock;
/* Handle any any CAN data already buffered in a read-ahead buffer. NOTE
@@ -743,22 +732,20 @@ ssize_t can_recvmsg(FAR struct socket *psock, FAR struct msghdr *msg,
if (ret > 0)
{
#ifdef CONFIG_NET_TIMESTAMP
- if (psock->s_timestamp)
- {
- if (state.pr_msglen == sizeof(struct timeval))
- {
- can_readahead_timestamp(conn, state.pr_msgbuf);
- }
- else
- {
- /* We still have to consume the data otherwise IOB gets full */
-
- uint8_t dummy_buf[sizeof(struct timeval)];
- can_readahead_timestamp(conn, &dummy_buf);
- }
- }
+ if(psock->s_timestamp)
+ {
+ if(state.pr_msglen == sizeof(struct timeval))
+ {
+ can_readahead_timestamp(conn, state.pr_msgbuf);
+ }
+ else
+ {
+ /* We still have to consume the data otherwise IOB gets full */
+ uint8_t dummy_buf[sizeof(struct timeval)];
+ can_readahead_timestamp(conn, &dummy_buf);
+ }
+ }
#endif
-
goto errout_with_state;
}
diff --git a/net/can/can_send.c b/net/can/can_send.c
index 644adc3..dfb03d0 100644
--- a/net/can/can_send.c
+++ b/net/can/can_send.c
@@ -76,6 +76,10 @@ struct send_s
sem_t snd_sem; /* Used to wake up the waiting thread */
FAR const uint8_t *snd_buffer; /* Points to the buffer of data to send */
size_t snd_buflen; /* Number of bytes in the buffer to send */
+#ifdef CONFIG_NET_CMSG
+ size_t pr_msglen; /* Length of msg buffer */
+ FAR uint8_t *pr_msgbuf; /* Pointer to msg buffer */
+#endif
ssize_t snd_sent; /* The number of bytes sent */
};
diff --git a/net/can/can_setsockopt.c b/net/can/can_setsockopt.c
index 6858c1a..ac9f912 100644
--- a/net/can/can_setsockopt.c
+++ b/net/can/can_setsockopt.c
@@ -147,6 +147,16 @@ int can_setsockopt(FAR struct socket *psock, int option,
case CAN_RAW_JOIN_FILTERS:
break;
+#ifdef CONFIG_NET_CAN_RAW_TX_DEADLINE
+ case CAN_RAW_TX_DEADLINE:
+ if (value_len != sizeof(conn->tx_deadline))
+ return -EINVAL;
+
+ conn->tx_deadline = *(FAR int32_t *)value;
+
+ break;
+#endif
+
default:
nerr("ERROR: Unrecognized CAN option: %d\n", option);
ret = -ENOPROTOOPT;
diff --git a/net/can/can_sockif.c b/net/can/can_sockif.c
index 737788e..09a61d0 100644
--- a/net/can/can_sockif.c
+++ b/net/can/can_sockif.c
@@ -69,6 +69,10 @@ static ssize_t can_send(FAR struct socket *psock,
static ssize_t can_sendto(FAR struct socket *psock, FAR const void *buf,
size_t len, int flags, FAR const struct sockaddr *to,
socklen_t tolen);
+#ifdef CONFIG_NET_CMSG
+static ssize_t can_sendmsg(FAR struct socket *psock, FAR struct msghdr *msg,
+ size_t len, int flags);
+#endif
static int can_close(FAR struct socket *psock);
/****************************************************************************
@@ -93,8 +97,9 @@ const struct sock_intf_s g_can_sockif =
NULL, /* si_sendfile */
#endif
can_recvfrom, /* si_recvfrom */
-#ifdef CONFIG_NET_RECVMSG_CMSG
+#ifdef CONFIG_NET_CMSG
can_recvmsg, /* si_recvmsg */
+ can_sendmsg, /* si_sendmsg */
#endif
can_close /* si_close */
};
@@ -774,6 +779,50 @@ static ssize_t can_sendto(FAR struct socket *psock, FAR const void *buf,
}
/****************************************************************************
+ * Name: can_sendmsg
+ *
+ * Description:
+ * The can_sendmsg() send a CAN frame to psock
+ *
+ * Input Parameters:
+ * psock - An instance of the internal socket structure.
+ * msg - CAN frame and optional CMSG
+ * flags - Send flags (ignored)
+ *
+ * Returned Value:
+ * On success, returns the number of characters sent. On error, a negated
+ * errno value is returned (see send() for the list of appropriate error
+ * values.
+ *
+ ****************************************************************************/
+#ifdef CONFIG_NET_CMSG
+static ssize_t can_sendmsg(FAR struct socket *psock, FAR struct msghdr *msg,
+ size_t len, int flags);
+{
+ ssize_t ret;
+
+ /* Only SOCK_RAW is supported */
+
+ if (psock->s_type == SOCK_RAW)
+ {
+ /* Raw packet send */
+
+ ret = psock_can_send(psock, buf, len);
+ }
+ else
+ {
+ /* EDESTADDRREQ. Signifies that the socket is not connection-mode and
+ * no peer address is set.
+ */
+
+ ret = -EDESTADDRREQ;
+ }
+
+ return ret;
+}
+#endif
+
+/****************************************************************************
* Name: can_close
*
* Description:
diff --git a/net/icmp/icmp_sockif.c b/net/icmp/icmp_sockif.c
index c81592e..ebe2bab 100644
--- a/net/icmp/icmp_sockif.c
+++ b/net/icmp/icmp_sockif.c
@@ -102,8 +102,9 @@ const struct sock_intf_s g_icmp_sockif =
NULL, /* si_sendfile */
#endif
icmp_recvfrom, /* si_recvfrom */
-#ifdef CONFIG_NET_RECVMSG_CMSG
+#ifdef CONFIG_NET_CMSG
NULL, /* si_recvmsg */
+ NULL, /* si_sendmsg */
#endif
icmp_close /* si_close */
};
diff --git a/net/icmpv6/icmpv6_sockif.c b/net/icmpv6/icmpv6_sockif.c
index 29e5e47..5adae60 100644
--- a/net/icmpv6/icmpv6_sockif.c
+++ b/net/icmpv6/icmpv6_sockif.c
@@ -102,8 +102,9 @@ const struct sock_intf_s g_icmpv6_sockif =
NULL, /* si_sendfile */
#endif
icmpv6_recvfrom, /* si_recvfrom */
-#ifdef CONFIG_NET_RECVMSG_CMSG
+#ifdef CONFIG_NET_CMSG
NULL, /* si_recvmsg */
+ NULL, /* si_sendmsg */
#endif
icmpv6_close /* si_close */
};
diff --git a/net/ieee802154/ieee802154_sockif.c b/net/ieee802154/ieee802154_sockif.c
index d1ac29b..6c0f88a 100644
--- a/net/ieee802154/ieee802154_sockif.c
+++ b/net/ieee802154/ieee802154_sockif.c
@@ -107,8 +107,9 @@ const struct sock_intf_s g_ieee802154_sockif =
NULL, /* si_sendfile */
#endif
ieee802154_recvfrom, /* si_recvfrom */
-#ifdef CONFIG_NET_RECVMSG_CMSG
+#ifdef CONFIG_NET_CMSG
NULL, /* si_recvmsg */
+ NULL, /* si_sendmsg */
#endif
ieee802154_close /* si_close */
};
diff --git a/net/inet/inet_sockif.c b/net/inet/inet_sockif.c
index 2a09c45..488f2d1 100644
--- a/net/inet/inet_sockif.c
+++ b/net/inet/inet_sockif.c
@@ -117,8 +117,9 @@ static const struct sock_intf_s g_inet_sockif =
inet_sendfile, /* si_sendfile */
#endif
inet_recvfrom, /* si_recvfrom */
-#ifdef CONFIG_NET_RECVMSG_CMSG
+#ifdef CONFIG_NET_CMSG
NULL, /* si_recvmsg */
+ NULL, /* si_sendmsg */
#endif
inet_close /* si_close */
};
diff --git a/net/local/local_sockif.c b/net/local/local_sockif.c
index 62d56b5..cd9bd66 100644
--- a/net/local/local_sockif.c
+++ b/net/local/local_sockif.c
@@ -110,8 +110,9 @@ const struct sock_intf_s g_local_sockif =
NULL, /* si_sendfile */
#endif
local_recvfrom, /* si_recvfrom */
-#ifdef CONFIG_NET_RECVMSG_CMSG
+#ifdef CONFIG_NET_CMSG
NULL, /* si_recvmsg */
+ NULL, /* si_sendmsg */
#endif
local_close /* si_close */
};
diff --git a/net/netlink/netlink_sockif.c b/net/netlink/netlink_sockif.c
index 970aed4..34b011a 100644
--- a/net/netlink/netlink_sockif.c
+++ b/net/netlink/netlink_sockif.c
@@ -111,8 +111,9 @@ const struct sock_intf_s g_netlink_sockif =
NULL, /* si_sendfile */
#endif
netlink_recvfrom, /* si_recvfrom */
-#ifdef CONFIG_NET_RECVMSG_CMSG
+#ifdef CONFIG_NET_CMSG
NULL, /* si_recvmsg */
+ NULL, /* si_sendmsg */
#endif
netlink_close /* si_close */
};
diff --git a/net/pkt/pkt_sockif.c b/net/pkt/pkt_sockif.c
index bbabf42..dbf3e3c 100644
--- a/net/pkt/pkt_sockif.c
+++ b/net/pkt/pkt_sockif.c
@@ -108,8 +108,9 @@ const struct sock_intf_s g_pkt_sockif =
NULL, /* si_sendfile */
#endif
pkt_recvfrom, /* si_recvfrom */
-#ifdef CONFIG_NET_RECVMSG_CMSG
+#ifdef CONFIG_NET_CMSG
NULL, /* si_recvmsg */
+ NULL, /* si_sendmsg */
#endif
pkt_close /* si_close */
};
diff --git a/net/socket/Kconfig b/net/socket/Kconfig
index f4c9408..f13e22d 100644
--- a/net/socket/Kconfig
+++ b/net/socket/Kconfig
@@ -58,18 +58,20 @@ config NET_SOLINGER
config NET_TIMESTAMP
bool "SO_TIMESTAMP socket option"
default n
- depends on NET_CAN && NET_RECVMSG_CMSG
+ depends on NET_CAN
+ select NET_CMSG
---help---
Enable or disable support for the SO_TIMESTAMP socket option. Currently only tested & implemented in SocketCAN but should work on all sockets
endif # NET_SOCKOPTS
-config NET_RECVMSG_CMSG
- bool "recvmsg() control messages (CMSG) support"
+config NET_CMSG
+ bool "Control messages (CMSG) support"
default n
---help---
- Enable or disable support for control messages in the recvmsg function.
- Control messages (also defined in POSIX 1003.1g as ancillary data object information).
- Includes additional information on the packet received.
+ Enable or disable support for control messages in the recvmsg() and
+ sendmsg() function. Control messages (also defined in POSIX 1003.1g
+ as ancillary data object information). Includes additional
+ information on the packet received or to be transmitted.
endmenu # Socket Support
diff --git a/net/socket/Make.defs b/net/socket/Make.defs
index 2be9dbf..6bf79ed 100644
--- a/net/socket/Make.defs
+++ b/net/socket/Make.defs
@@ -75,7 +75,8 @@ endif
DEPPATH += --dep-path socket
VPATH += :socket
-# Support for recvmsg() with control messages (CMSG)
-ifeq ($(CONFIG_NET_RECVMSG_CMSG),y)
+# Support for control messages (CMSG)
+ifeq ($(CONFIG_NET_CMSG),y)
SOCK_CSRCS += recvmsg.c
+SOCK_CSRCS += sendmsg.c
endif
diff --git a/net/socket/recvmsg.c b/net/socket/recvmsg.c
index 17d4dfe..800eeb1 100644
--- a/net/socket/recvmsg.c
+++ b/net/socket/recvmsg.c
@@ -47,7 +47,7 @@
#include "socket/socket.h"
-#ifdef CONFIG_NET_RECVMSG_CMSG
+#ifdef CONFIG_NET_CMSG
/****************************************************************************
* Public Functions
@@ -235,4 +235,4 @@ ssize_t recvmsg(int sockfd, FAR struct msghdr *msg, int flags)
return ret;
}
-#endif /* CONFIG_NET_RECVMSG_CMSG */
+#endif /* CONFIG_NET_CMSG */
diff --git a/net/socket/recvmsg.c b/net/socket/sendmsg.c
similarity index 78%
copy from net/socket/recvmsg.c
copy to net/socket/sendmsg.c
index 17d4dfe..3bc32e8 100644
--- a/net/socket/recvmsg.c
+++ b/net/socket/sendmsg.c
@@ -1,5 +1,5 @@
/****************************************************************************
- * net/socket/recvmsg.c
+ * net/socket/sendmsg.c
*
* Copyright (C) 2007-2009, 2011-2017, 2019 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gn...@nuttx.org>
@@ -47,20 +47,20 @@
#include "socket/socket.h"
-#ifdef CONFIG_NET_RECVMSG_CMSG
+#ifdef CONFIG_NET_CMSG
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
- * Name: psock_recvmsg
+ * Name: psock_sendmsg
*
* Description:
- * psock_recvfrom() receives messages from a socket, and may be used to
- * receive data on a socket whether or not it is connection-oriented.
+ * psock_sendfrom() sends messages to a socket, and may be used to
+ * send data on a socket whether or not it is connection-oriented.
* This is an internal OS interface. It is functionally equivalent to
- * recvfrom() except that:
+ * sendfrom() except that:
*
* - It is not a cancellation point,
* - It does not modify the errno variable, and
@@ -69,20 +69,20 @@
*
* Input Parameters:
* psock - A pointer to a NuttX-specific, internal socket structure
- * msg Buffer to receive msg
+ * msg - Buffer to of the msg
* len - Length of buffer
* flags - Receive flags
*
* Returned Value:
* On success, returns the number of characters sent. If no data is
* available to be received and the peer has performed an orderly shutdown,
- * recv() will return 0. Otherwise, on any failure, a negated errno value
+ * send() will return 0. Otherwise, on any failure, a negated errno value
* is returned (see comments with send() for a list of appropriate errno
* values).
*
****************************************************************************/
-ssize_t psock_recvmsg(FAR struct socket *psock, FAR struct msghdr *msg,
+ssize_t psock_sendmsg(FAR struct socket *psock, FAR struct msghdr *msg,
int flags)
{
/* Verify that non-NULL pointers were passed */
@@ -103,38 +103,38 @@ ssize_t psock_recvmsg(FAR struct socket *psock, FAR struct msghdr *msg,
return -EBADF;
}
- /* Let logic specific to this address family handle the recvfrom()
+ /* Let logic specific to this address family handle the sendfrom()
* operation.
*/
DEBUGASSERT(psock->s_sockif != NULL &&
- (psock->s_sockif->si_recvmsg != NULL ||
- psock->s_sockif->si_recvfrom != NULL));
+ (psock->s_sockif->si_sendmsg != NULL ||
+ psock->s_sockif->si_sendto != NULL));
- if(psock->s_sockif->si_recvmsg != NULL)
+ if(psock->s_sockif->si_sendmsg != NULL)
{
- return psock->s_sockif->si_recvmsg(psock, msg, flags);
+ return psock->s_sockif->si_sendmsg(psock, msg, flags);
}
else
{
- /* Socket doesn't implement si_recvmsg fallback to si_recvfrom */
- FAR void *buf = msg->msg_iov->iov_base;
- FAR struct sockaddr *from = msg->msg_name;
- FAR socklen_t *fromlen = (FAR socklen_t *)&msg->msg_namelen;
- size_t len = msg->msg_iov->iov_len;
- return psock->s_sockif->si_recvfrom(psock, buf, len, flags, from, fromlen);
+ /* Socket doesn't implement si_sendmsg fallback to si_sendto */
+ FAR void *buf = msg->msg_iov->iov_base;
+ FAR struct sockaddr *to = msg->msg_name;
+ socklen_t tolen = msg->msg_namelen;
+ size_t len = msg->msg_iov->iov_len;
+ return psock->s_sockif->si_sendto(psock, buf, len, flags, to, tolen);
}
}
/****************************************************************************
- * Name: nx_recvfrom
+ * Name: nx_sendfrom
*
* Description:
- * nx_recvfrom() receives messages from a socket, and may be used to
+ * nx_sendfrom() receives messages from a socket, and may be used to
* receive data on a socket whether or not it is connection-oriented.
* This is an internal OS interface. It is functionally equivalent to
- * recvfrom() except that:
+ * sendfrom() except that:
*
* - It is not a cancellation point, and
* - It does not modify the errno variable.
@@ -148,13 +148,13 @@ ssize_t psock_recvmsg(FAR struct socket *psock, FAR struct msghdr *msg,
* Returned Value:
* On success, returns the number of characters sent. If no data is
* available to be received and the peer has performed an orderly shutdown,
- * recv() will return 0. Otherwise, on any failure, a negated errno value
+ * send() will return 0. Otherwise, on any failure, a negated errno value
* is returned (see comments with send() for a list of appropriate errno
* values).
*
****************************************************************************/
-ssize_t nx_recvmsg(int sockfd, FAR struct msghdr *msg, int flags)
+ssize_t nx_sendmsg(int sockfd, FAR struct msghdr *msg, int flags)
{
FAR struct socket *psock;
@@ -162,16 +162,16 @@ ssize_t nx_recvmsg(int sockfd, FAR struct msghdr *msg, int flags)
psock = sockfd_socket(sockfd);
- /* Then let psock_recvmsg() do all of the work */
+ /* Then let psock_sendmsg() do all of the work */
- return psock_recvmsg(psock, msg, flags);
+ return psock_sendmsg(psock, msg, flags);
}
/****************************************************************************
- * Function: recvmsg
+ * Function: sendmsg
*
* Description:
- * The recvmsg() call is identical to recvfrom() with a NULL from parameter.
+ * The sendmsg() call is identical to sendfrom() with a NULL from parameter.
*
* Parameters:
* sockfd Socket descriptor of socket
@@ -209,12 +209,12 @@ ssize_t nx_recvmsg(int sockfd, FAR struct msghdr *msg, int flags)
*
****************************************************************************/
-ssize_t recvmsg(int sockfd, FAR struct msghdr *msg, int flags)
+ssize_t sendmsg(int sockfd, FAR struct msghdr *msg, int flags)
{
FAR struct socket *psock;
ssize_t ret;
- /* recvfrom() is a cancellation point */
+ /* sendfrom() is a cancellation point */
enter_cancellation_point();
@@ -222,9 +222,9 @@ ssize_t recvmsg(int sockfd, FAR struct msghdr *msg, int flags)
psock = sockfd_socket(sockfd);
- /* Let psock_recvfrom() do all of the work */
+ /* Let psock_sendfrom() do all of the work */
- ret = psock_recvmsg(psock, msg, flags);
+ ret = psock_sendmsg(psock, msg, flags);
if (ret < 0)
{
_SO_SETERRNO(psock, -ret);
@@ -235,4 +235,4 @@ ssize_t recvmsg(int sockfd, FAR struct msghdr *msg, int flags)
return ret;
}
-#endif /* CONFIG_NET_RECVMSG_CMSG */
+#endif /* CONFIG_NET_CMSG */