diff --git a/net/devif/devif.h b/net/devif/devif.h index 122e5bf6be4..17bb068720f 100644 --- a/net/devif/devif.h +++ b/net/devif/devif.h @@ -390,7 +390,7 @@ void devif_dev_callback_free(FAR struct net_driver_s *dev, * dev - The network device state structure associated with the network * device that initiated the callback event. * pvconn - Holds a reference to the TCP connection structure or the UDP - * port structure. May be NULL if the even is not related to a TCP + * port structure. It can be NULL if the event is not related to a TCP * connection or UDP port. * flags - The bit set of events to be notified. * list - The list to traverse in performing the notifications @@ -416,7 +416,7 @@ uint16_t devif_conn_event(FAR struct net_driver_s *dev, FAR void *pvconn, * dev - The network device state structure associated with the network * device that initiated the callback event. * pvconn - Holds a reference to the TCP connection structure or the UDP - * port structure. May be NULL if the even is not related to a TCP + * port structure. It can be NULL if the event is not related to a TCP * connection or UDP port. * flags - The bit set of events to be notified. * diff --git a/net/devif/devif_callback.c b/net/devif/devif_callback.c index 8ee7ec114d7..aac3695f71e 100644 --- a/net/devif/devif_callback.c +++ b/net/devif/devif_callback.c @@ -466,7 +466,7 @@ void devif_dev_callback_free(FAR struct net_driver_s *dev, * dev - The network device state structure associated with the network * device that initiated the callback event. * pvconn - Holds a reference to the TCP connection structure or the UDP - * port structure. May be NULL if the even is not related to a TCP + * port structure. It can be NULL if the event is not related to a TCP * connection or UDP port. * flags - The bit set of events to be notified. * list - The list to traverse in performing the notifications @@ -529,7 +529,7 @@ uint16_t devif_conn_event(FAR struct net_driver_s *dev, void *pvconn, * dev - The network device state structure associated with the network * device that initiated the callback event. * pvconn - Holds a reference to the TCP connection structure or the UDP - * port structure. May be NULL if the even is not related to a TCP + * port structure. It can be NULL if the event is not related to a TCP * connection or UDP port. * flags - The bit set of events to be notified. * diff --git a/net/tcp/tcp_send_buffered.c b/net/tcp/tcp_send_buffered.c index 389cc8a4741..f857a835d6d 100644 --- a/net/tcp/tcp_send_buffered.c +++ b/net/tcp/tcp_send_buffered.c @@ -355,10 +355,39 @@ static uint16_t psock_send_eventhandler(FAR struct net_driver_s *dev, FAR void *pvconn, FAR void *pvpriv, uint16_t flags) { - FAR struct tcp_conn_s *conn = (FAR struct tcp_conn_s *)pvconn; + /* FAR struct tcp_conn_s *conn = (FAR struct tcp_conn_s *)pvconn; + * + * Do not use pvconn argument to get the TCP connection pointer (the above + * commented line) because pvconn is normally NULL for some events like + * NETDEV_DOWN. Instead, the TCP connection pointer can be reliably + * obtained from the corresponding TCP socket. + */ + FAR struct socket *psock = (FAR struct socket *)pvpriv; + FAR struct tcp_conn_s *conn; bool rexmit = false; + DEBUGASSERT(psock != NULL); + + /* Get the TCP connection pointer reliably from + * the corresponding TCP socket. + */ + + conn = psock->s_conn; + DEBUGASSERT(conn != NULL); + + /* The TCP socket is connected and, hence, should be bound to a device. + * Make sure that the polling device is the one that we are bound to. + */ + + DEBUGASSERT(conn->dev != NULL); + if (dev != conn->dev) + { + return flags; + } + + ninfo("flags: %04x\n", flags); + /* Check for a loss of connection */ if ((flags & TCP_DISCONN_EVENTS) != 0) @@ -383,23 +412,11 @@ static uint16_t psock_send_eventhandler(FAR struct net_driver_s *dev, return flags; } - /* The TCP socket is connected and, hence, should be bound to a device. - * Make sure that the polling device is the one that we are bound to. - */ - - DEBUGASSERT(conn->dev != NULL); - if (dev != conn->dev) - { - return flags; - } - - ninfo("flags: %04x\n", flags); - /* If this packet contains an acknowledgment, then update the count of * acknowledged bytes. */ - if ((flags & TCP_ACKDATA) != 0) + else if ((flags & TCP_ACKDATA) != 0) { FAR struct tcp_wrbuffer_s *wrb; FAR struct tcp_hdr_s *tcp; diff --git a/net/tcp/tcp_send_unbuffered.c b/net/tcp/tcp_send_unbuffered.c index 01f505529bf..4fc690f22a9 100644 --- a/net/tcp/tcp_send_unbuffered.c +++ b/net/tcp/tcp_send_unbuffered.c @@ -170,8 +170,29 @@ static uint16_t tcpsend_eventhandler(FAR struct net_driver_s *dev, FAR void *pvconn, FAR void *pvpriv, uint16_t flags) { - FAR struct tcp_conn_s *conn = (FAR struct tcp_conn_s *)pvconn; + /* FAR struct tcp_conn_s *conn = (FAR struct tcp_conn_s *)pvconn; + * + * Do not use pvconn argument to get the TCP connection pointer (the above + * commented line) because pvconn is normally NULL for some events like + * NETDEV_DOWN. Instead, the TCP connection pointer can be reliably + * obtained from the corresponding TCP socket. + */ + FAR struct send_s *pstate = (FAR struct send_s *)pvpriv; + FAR struct socket *psock; + FAR struct tcp_conn_s *conn; + + DEBUGASSERT(pstate != NULL); + + psock = pstate->snd_sock; + DEBUGASSERT(psock != NULL); + + /* Get the TCP connection pointer reliably from + * the corresponding TCP socket. + */ + + conn = psock->s_conn; + DEBUGASSERT(conn != NULL); /* The TCP socket is connected and, hence, should be bound to a device. * Make sure that the polling device is the one that we are bound to. @@ -315,8 +336,6 @@ static uint16_t tcpsend_eventhandler(FAR struct net_driver_s *dev, else if ((flags & TCP_DISCONN_EVENTS) != 0) { - FAR struct socket *psock = pstate->snd_sock; - ninfo("Lost connection\n"); /* We could get here recursively through the callback actions of @@ -324,7 +343,6 @@ static uint16_t tcpsend_eventhandler(FAR struct net_driver_s *dev, * already been disconnected. */ - DEBUGASSERT(psock != NULL); if (_SS_ISCONNECTED(psock->s_flags)) { /* Report not connected */ @@ -403,6 +421,8 @@ end_wait: /* Do not allow any further callbacks */ + DEBUGASSERT(pstate->snd_cb != NULL); + pstate->snd_cb->flags = 0; pstate->snd_cb->priv = NULL; pstate->snd_cb->event = NULL; @@ -509,7 +529,6 @@ ssize_t psock_tcp_send(FAR struct socket *psock, /* Make sure that we have the IP address mapping */ conn = (FAR struct tcp_conn_s *)psock->s_conn; - DEBUGASSERT(conn); #if defined(CONFIG_NET_ARP_SEND) || defined(CONFIG_NET_ICMPv6_NEIGHBOR) #ifdef CONFIG_NET_ARP_SEND diff --git a/net/tcp/tcp_sendfile.c b/net/tcp/tcp_sendfile.c index ffb435fc010..745a489f39f 100644 --- a/net/tcp/tcp_sendfile.c +++ b/net/tcp/tcp_sendfile.c @@ -161,11 +161,44 @@ static uint16_t sendfile_eventhandler(FAR struct net_driver_s *dev, FAR void *pvconn, FAR void *pvpriv, uint16_t flags) { - FAR struct tcp_conn_s *conn = (FAR struct tcp_conn_s *)pvconn; + /* FAR struct tcp_conn_s *conn = (FAR struct tcp_conn_s *)pvconn; + * + * Do not use pvconn argument to get the TCP connection pointer (the above + * commented line) because pvconn is normally NULL for some events like + * NETDEV_DOWN. Instead, the TCP connection pointer can be reliably + * obtained from the corresponding TCP socket. + */ + FAR struct sendfile_s *pstate = (FAR struct sendfile_s *)pvpriv; - FAR struct socket *psock = pstate->snd_sock; + FAR struct socket *psock; + FAR struct tcp_conn_s *conn; int ret; + DEBUGASSERT(pstate != NULL); + + psock = pstate->snd_sock; + DEBUGASSERT(psock != NULL); + + /* Get the TCP connection pointer reliably from + * the corresponding TCP socket. + */ + + conn = psock->s_conn; + DEBUGASSERT(conn != NULL); + + /* The TCP socket is connected and, hence, should be bound to a device. + * Make sure that the polling device is the own that we are bound to. + */ + + DEBUGASSERT(conn->dev != NULL); + if (dev != conn->dev) + { + return flags; + } + + ninfo("flags: %04x acked: %" PRId32 " sent: %zd\n", + flags, pstate->snd_acked, pstate->snd_sent); + /* Check for a loss of connection */ if ((flags & TCP_DISCONN_EVENTS) != 0) @@ -177,7 +210,6 @@ static uint16_t sendfile_eventhandler(FAR struct net_driver_s *dev, * already been disconnected. */ - DEBUGASSERT(psock != NULL); if (_SS_ISCONNECTED(psock->s_flags)) { /* Report not connected */ @@ -191,25 +223,11 @@ static uint16_t sendfile_eventhandler(FAR struct net_driver_s *dev, goto end_wait; } - /* The TCP socket is connected and, hence, should be bound to a device. - * Make sure that the polling device is the own that we are bound to. - */ - - DEBUGASSERT(conn); - DEBUGASSERT(conn->dev != NULL); - if (dev != conn->dev) - { - return flags; - } - - ninfo("flags: %04x acked: %" PRId32 " sent: %zd\n", - flags, pstate->snd_acked, pstate->snd_sent); - /* If this packet contains an acknowledgement, then update the count of * acknowledged bytes. */ - if ((flags & TCP_ACKDATA) != 0) + else if ((flags & TCP_ACKDATA) != 0) { FAR struct tcp_hdr_s *tcp; @@ -363,6 +381,8 @@ end_wait: /* Do not allow any further callbacks */ + DEBUGASSERT(pstate->snd_cb != NULL); + pstate->snd_cb->flags = 0; pstate->snd_cb->priv = NULL; pstate->snd_cb->event = NULL;