diff --git a/net/local/local.h b/net/local/local.h index 7c0cf44a2f..44a5b24093 100644 --- a/net/local/local.h +++ b/net/local/local.h @@ -582,7 +582,7 @@ int local_open_receiver(FAR struct local_conn_s *conn); * ****************************************************************************/ -int local_open_sender(FAR struct local_conn_s *conn); +int local_open_sender(FAR struct local_conn_s *conn, FAR char *path); #undef EXTERN #ifdef __cplusplus diff --git a/net/local/local_fifo.c b/net/local/local_fifo.c index 0817f33bc9..24439e1dcd 100644 --- a/net/local/local_fifo.c +++ b/net/local/local_fifo.c @@ -79,7 +79,7 @@ static inline void local_cs_name(FAR struct local_conn_s *conn, { (void)snprintf(path, LOCAL_FULLPATH_LEN-1, "%s" LOCAL_CS_SUFFIX, conn->lc_path); - path[LOCAL_FULLPATH_LEN-1] = '\0'; + path[LOCAL_FULLPATH_LEN-1] = '\0'; } /**************************************************************************** @@ -95,7 +95,7 @@ static inline void local_sc_name(FAR struct local_conn_s *conn, { (void)snprintf(path, LOCAL_FULLPATH_LEN-1, "%s" LOCAL_SC_SUFFIX, conn->lc_path); - path[LOCAL_FULLPATH_LEN-1] = '\0'; + path[LOCAL_FULLPATH_LEN-1] = '\0'; } /**************************************************************************** @@ -106,12 +106,10 @@ static inline void local_sc_name(FAR struct local_conn_s *conn, * ****************************************************************************/ -static inline void local_hd_name(FAR struct local_conn_s *conn, - FAR char *path) +static inline void local_hd_name(FAR const char *inpath, FAR char *outpath) { - (void)snprintf(path, LOCAL_FULLPATH_LEN-1, "%s" LOCAL_HD_SUFFIX, - conn->lc_path); - path[LOCAL_FULLPATH_LEN-1] = '\0'; + (void)snprintf(outpath, LOCAL_FULLPATH_LEN-1, "%s" LOCAL_HD_SUFFIX, inpath); + outpath[LOCAL_FULLPATH_LEN-1] = '\0'; } /**************************************************************************** @@ -328,7 +326,7 @@ int local_create_halfduplex(FAR struct local_conn_s *conn) /* Create the half duplex FIFO if it does not already exist. */ - local_hd_name(conn, path); + local_hd_name(conn->lc_path, path); return local_create_fifo(path); } @@ -375,7 +373,7 @@ int local_destroy_halfduplex(FAR struct local_conn_s *conn) /* Destroy the half duplex FIFO if it exists. */ - local_hd_name(conn, path); + local_hd_name(conn->lc_path, path); return local_destroy_fifo(path); } @@ -477,7 +475,7 @@ int local_open_receiver(FAR struct local_conn_s *conn) /* Get the server-to-client path name */ - local_hd_name(conn, path); + local_hd_name(conn->lc_path, path); /* Then open the file for read-only access */ @@ -492,17 +490,17 @@ int local_open_receiver(FAR struct local_conn_s *conn) * ****************************************************************************/ -int local_open_sender(FAR struct local_conn_s *conn) +int local_open_sender(FAR struct local_conn_s *conn, FAR char *path) { - char path[LOCAL_FULLPATH_LEN]; + char fullpath[LOCAL_FULLPATH_LEN]; /* Get the server-to-client path name */ - local_hd_name(conn, path); + local_hd_name(path, fullpath); /* Then open the file for read-only access */ - return local_tx_open(conn, path); + return local_tx_open(conn, fullpath); } #endif /* CONFIG_NET && CONFIG_NET_LOCAL */ diff --git a/net/local/local_sendto.c b/net/local/local_sendto.c index 625ccb8be8..57871b2d9c 100644 --- a/net/local/local_sendto.c +++ b/net/local/local_sendto.c @@ -42,7 +42,10 @@ #include #include +#include #include +#include +#include #include @@ -81,8 +84,76 @@ ssize_t psock_local_sendto(FAR struct socket *psock, FAR const void *buf, size_t len, int flags, FAR const struct sockaddr *to, socklen_t tolen) { -#warning Missing logic - return -ENOSYS; + FAR struct local_conn_s *conn = (FAR struct local_conn_s *)psock->s_conn; + FAR struct sockaddr_un *unaddr = (FAR struct sockaddr_un *)to; + ssize_t nsent; + int ret; + + /* We keep packet sizes in a uint16_t, so there is a upper limit to the + * 'len' that can be supported. + */ + + DEBUGASSERT(buf && len <= UINT16_MAX); + + /* Verify that this is a bound, un-connected peer socket */ + + if (conn->lc_state != LOCAL_STATE_BOUND) + { + /* Either not bound to address or it is connected */ + + ndbg("ERROR: Connected or not bound\n"); + return -EISCONN; + } + + /* The outgoing FIFO should not be open */ + + DEBUGASSERT(conn->lc_outfd < 0); + + /* At present, only standard pathname type address are support */ + + if (tolen < sizeof(sa_family_t) + 2) + { + /* EFAULT - An invalid user space address was specified for a parameter */ + + return -EFAULT; + } + + /* Make sure that half duplex FIFO has been created. + * REVISIT: Or should be just make sure that it already exists? + */ + + ret = local_create_halfduplex(conn); + if (ret < 0) + { + ndbg("ERROR: Failed to create FIFO for %s: %d\n", + conn->lc_path, ret); + return ret; + } + + /* Open the sending side of the transfer */ + + ret = local_open_sender(conn, unaddr->sun_path); + if (ret < 0) + { + ndbg("ERROR: Failed to open FIFO for %s: %d\n", + unaddr->sun_path, ret); + return ret; + } + + /* Send the packet */ + + nsent = local_send_packet(conn->lc_outfd, buf, len); + if (nsent < 0) + { + ndbg("ERROR: Failed to send the packet: %d\n", ret); + } + + /* Now we can close the write-only socket descriptor */ + + close(conn->lc_outfd); + conn->lc_outfd = -1; + + return nsent; } #endif /* CONFIG_NET && CONFIG_NET_LOCAL */