Networking: TCP disconnection callbacks are not retained in a list. This will support mutiple callbacks per lower-level TCP connection structure. That is necessary for the cae where a socket is dup'ed and shares the same lower-level connection structure. NOTE: There still needs to be a call to tcp_start_monitor() when the socket is dup'ed.
This commit is contained in:
parent
ed58536c3a
commit
9db65dea78
@ -74,15 +74,6 @@
|
|||||||
#define tcp_callback_free(conn,cb) \
|
#define tcp_callback_free(conn,cb) \
|
||||||
devif_conn_callback_free((conn)->dev, (cb), &(conn)->list)
|
devif_conn_callback_free((conn)->dev, (cb), &(conn)->list)
|
||||||
|
|
||||||
/* These macros allocate and free callback structures used for receiving
|
|
||||||
* notifications of device-related events.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define tcp_monitor_callback_alloc(conn) \
|
|
||||||
devif_callback_alloc((conn)->dev, NULL)
|
|
||||||
#define tcp_monitor_callback_free(conn,cb) \
|
|
||||||
devif_conn_callback_free((conn)->dev, (cb), NULL)
|
|
||||||
|
|
||||||
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
|
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
|
||||||
/* TCP write buffer access macros */
|
/* TCP write buffer access macros */
|
||||||
|
|
||||||
@ -231,6 +222,14 @@ struct tcp_conn_s
|
|||||||
|
|
||||||
FAR struct devif_callback_s *list;
|
FAR struct devif_callback_s *list;
|
||||||
|
|
||||||
|
/* connevents is a list of callbacks for each socket the uses this
|
||||||
|
* connection (there can be more that one in the event that the the socket
|
||||||
|
* was dup'ed). It is used with the network monitor to handle
|
||||||
|
* asynchronous loss-of-connection events.
|
||||||
|
*/
|
||||||
|
|
||||||
|
FAR struct devif_callback_s *connevents;
|
||||||
|
|
||||||
/* accept() is called when the TCP logic has created a connection
|
/* accept() is called when the TCP logic has created a connection
|
||||||
*
|
*
|
||||||
* accept_private: This is private data that will be available to the
|
* accept_private: This is private data that will be available to the
|
||||||
@ -241,24 +240,6 @@ struct tcp_conn_s
|
|||||||
|
|
||||||
FAR void *accept_private;
|
FAR void *accept_private;
|
||||||
int (*accept)(FAR struct tcp_conn_s *listener, FAR struct tcp_conn_s *conn);
|
int (*accept)(FAR struct tcp_conn_s *listener, FAR struct tcp_conn_s *conn);
|
||||||
|
|
||||||
/* connection_event() is called on any of the subset of connection-related
|
|
||||||
* events.
|
|
||||||
*
|
|
||||||
* connection_private: This is private data that will be available to
|
|
||||||
* the connection_event() handler when it is invoked with a point to
|
|
||||||
* this structure as an argument.
|
|
||||||
* connection_devcb: this is the allocated callback structure that is
|
|
||||||
* used to
|
|
||||||
* connection_event: This is the pointer to the connection event
|
|
||||||
* handler.
|
|
||||||
*/
|
|
||||||
|
|
||||||
FAR void *connection_private;
|
|
||||||
FAR struct devif_callback_s *connection_devcb;
|
|
||||||
uint16_t (*connection_event)(FAR struct net_driver_s *dev,
|
|
||||||
FAR void *pvconn, FAR void *pvpriv,
|
|
||||||
uint16_t flags);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* This structure supports TCP write buffering */
|
/* This structure supports TCP write buffering */
|
||||||
|
@ -193,12 +193,11 @@ uint16_t tcp_callback(FAR struct net_driver_s *dev,
|
|||||||
* callback.
|
* callback.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (((flags & TCP_CONN_EVENTS) != 0) && conn->connection_event)
|
if ((flags & TCP_CONN_EVENTS) != 0)
|
||||||
{
|
{
|
||||||
/* Perform the callback */
|
/* Perform the callback disconnect callbacks */
|
||||||
|
|
||||||
flags = conn->connection_event(dev, conn, conn->connection_private,
|
flags = devif_conn_event(dev, conn, flags, conn->connevents);
|
||||||
flags);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return flags;
|
return flags;
|
||||||
|
@ -56,8 +56,8 @@
|
|||||||
* Private Function Prototypes
|
* Private Function Prototypes
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static void connection_closed(FAR struct socket *psock, uint16_t flags);
|
static void tcp_close_connection(FAR struct socket *psock, uint16_t flags);
|
||||||
static uint16_t connection_event(FAR struct net_driver_s *dev,
|
static uint16_t tcp_disconnect_event(FAR struct net_driver_s *dev,
|
||||||
FAR void *pvconn, FAR void *pvpriv,
|
FAR void *pvconn, FAR void *pvpriv,
|
||||||
uint16_t flags);
|
uint16_t flags);
|
||||||
|
|
||||||
@ -66,7 +66,7 @@ static uint16_t connection_event(FAR struct net_driver_s *dev,
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: connection_closed
|
* Name: tcp_close_connection
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Called when a loss-of-connection event has occurred.
|
* Called when a loss-of-connection event has occurred.
|
||||||
@ -83,7 +83,7 @@ static uint16_t connection_event(FAR struct net_driver_s *dev,
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static void connection_closed(FAR struct socket *psock, uint16_t flags)
|
static void tcp_close_connection(FAR struct socket *psock, uint16_t flags)
|
||||||
{
|
{
|
||||||
/* These loss-of-connection events may be reported:
|
/* These loss-of-connection events may be reported:
|
||||||
*
|
*
|
||||||
@ -121,7 +121,7 @@ static void connection_closed(FAR struct socket *psock, uint16_t flags)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: connection_event
|
* Name: tcp_disconnect_event
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Some connection related event has occurred
|
* Some connection related event has occurred
|
||||||
@ -139,13 +139,13 @@ static void connection_closed(FAR struct socket *psock, uint16_t flags)
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static uint16_t connection_event(FAR struct net_driver_s *dev,
|
static uint16_t tcp_disconnect_event(FAR struct net_driver_s *dev,
|
||||||
FAR void *pvconn, FAR void *pvpriv,
|
FAR void *pvconn, FAR void *pvpriv,
|
||||||
uint16_t flags)
|
uint16_t flags)
|
||||||
{
|
{
|
||||||
FAR struct socket *psock = (FAR struct socket *)pvpriv;
|
FAR struct socket *psock = (FAR struct socket *)pvpriv;
|
||||||
|
|
||||||
if (psock)
|
if (psock != NULL)
|
||||||
{
|
{
|
||||||
ninfo("flags: %04x s_flags: %02x\n", flags, psock->s_flags);
|
ninfo("flags: %04x s_flags: %02x\n", flags, psock->s_flags);
|
||||||
|
|
||||||
@ -155,7 +155,7 @@ static uint16_t connection_event(FAR struct net_driver_s *dev,
|
|||||||
|
|
||||||
if ((flags & TCP_DISCONN_EVENTS) != 0)
|
if ((flags & TCP_DISCONN_EVENTS) != 0)
|
||||||
{
|
{
|
||||||
connection_closed(psock, flags);
|
tcp_close_connection(psock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TCP_CONNECTED: The socket is successfully connected */
|
/* TCP_CONNECTED: The socket is successfully connected */
|
||||||
@ -188,9 +188,51 @@ static uint16_t connection_event(FAR struct net_driver_s *dev,
|
|||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: tcp_shutdown_monitor
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Stop monitoring TCP connection changes for a given socket.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* conn - The TCP connection of interest
|
||||||
|
* flags - Indicates the type of shutdown. TCP_CLOSE or TCP_ABORT
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
* Assumptions:
|
||||||
|
* The caller holds the network lock (if not, it will be locked momentarily
|
||||||
|
* by this function).
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void tcp_shutdown_monitor(FAR struct tcp_conn_s *conn, uint16_t flags)
|
||||||
|
{
|
||||||
|
DEBUGASSERT(conn);
|
||||||
|
|
||||||
|
/* Perform callbacks to assure that all sockets, including dup'ed copies,
|
||||||
|
* are informed of the loss of connection event.
|
||||||
|
*/
|
||||||
|
|
||||||
|
net_lock();
|
||||||
|
(void)tcp_callback(conn->dev, conn, flags);
|
||||||
|
|
||||||
|
/* Free all allocated connection event callback structure s*/
|
||||||
|
|
||||||
|
while (conn->connevents != NULL)
|
||||||
|
{
|
||||||
|
devif_conn_callback_free(conn->dev, conn->connevents,
|
||||||
|
&conn->connevents);
|
||||||
|
}
|
||||||
|
|
||||||
|
net_unlock();
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Functions
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: tcp_start_monitor
|
* Name: tcp_start_monitor
|
||||||
*
|
*
|
||||||
@ -231,13 +273,7 @@ int tcp_start_monitor(FAR struct socket *psock)
|
|||||||
{
|
{
|
||||||
/* Invoke the TCP_CLOSE connection event now */
|
/* Invoke the TCP_CLOSE connection event now */
|
||||||
|
|
||||||
(void)connection_event(NULL, conn, psock, TCP_CLOSE);
|
tcp_shutdown_monitor(conn, TCP_CLOSE);
|
||||||
|
|
||||||
/* Make sure that the monitor is stopped */
|
|
||||||
|
|
||||||
conn->connection_private = NULL;
|
|
||||||
conn->connection_devcb = NULL;
|
|
||||||
conn->connection_event = NULL;
|
|
||||||
|
|
||||||
/* And return -ENOTCONN to indicate the monitor was not started
|
/* And return -ENOTCONN to indicate the monitor was not started
|
||||||
* because the socket was already disconnected.
|
* because the socket was already disconnected.
|
||||||
@ -247,28 +283,18 @@ int tcp_start_monitor(FAR struct socket *psock)
|
|||||||
return -ENOTCONN;
|
return -ENOTCONN;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUGASSERT(conn->connection_event == NULL &&
|
|
||||||
conn->connection_devcb == NULL);
|
|
||||||
|
|
||||||
/* Allocate a callback structure that we will use to get callbacks if
|
/* Allocate a callback structure that we will use to get callbacks if
|
||||||
* the network goes down.
|
* the network goes down.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
cb = tcp_monitor_callback_alloc(conn);
|
cb = devif_callback_alloc(conn->dev, &conn->connevents);
|
||||||
if (cb != NULL)
|
if (cb != NULL)
|
||||||
{
|
{
|
||||||
cb->event = connection_event;
|
cb->event = tcp_disconnect_event;
|
||||||
cb->priv = (FAR void *)psock;
|
cb->priv = (FAR void *)psock;
|
||||||
cb->flags = NETDEV_DOWN;
|
cb->flags = TCP_DISCONN_EVENTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
conn->connection_devcb = cb;
|
|
||||||
|
|
||||||
/* Set up to receive callbacks on connection-related events */
|
|
||||||
|
|
||||||
conn->connection_private = (FAR void *)psock;
|
|
||||||
conn->connection_event = connection_event;
|
|
||||||
|
|
||||||
net_unlock();
|
net_unlock();
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
@ -277,7 +303,8 @@ int tcp_start_monitor(FAR struct socket *psock)
|
|||||||
* Name: tcp_stop_monitor
|
* Name: tcp_stop_monitor
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Stop monitoring TCP connection changes for a given socket
|
* Stop monitoring TCP connection changes for a given socket. This is part
|
||||||
|
* of a graceful shutdown.
|
||||||
*
|
*
|
||||||
* Input Parameters:
|
* Input Parameters:
|
||||||
* conn - The TCP connection of interest
|
* conn - The TCP connection of interest
|
||||||
@ -293,33 +320,23 @@ int tcp_start_monitor(FAR struct socket *psock)
|
|||||||
|
|
||||||
void tcp_stop_monitor(FAR struct tcp_conn_s *conn)
|
void tcp_stop_monitor(FAR struct tcp_conn_s *conn)
|
||||||
{
|
{
|
||||||
DEBUGASSERT(conn);
|
DEBUGASSERT(conn != NULL);
|
||||||
|
|
||||||
/* Free any allocated device event callback structure */
|
/* Stop the network monitor */
|
||||||
|
|
||||||
net_lock();
|
tcp_shutdown_monitor(conn, TCP_CLOSE);
|
||||||
if (conn->connection_devcb)
|
|
||||||
{
|
|
||||||
tcp_monitor_callback_free(conn, conn->connection_devcb);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Nullify all connection event data */
|
|
||||||
|
|
||||||
conn->connection_private = NULL;
|
|
||||||
conn->connection_devcb = NULL;
|
|
||||||
conn->connection_event = NULL;
|
|
||||||
net_unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: tcp_lost_connection
|
* Name: tcp_lost_connection
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Called when a loss-of-connection event has occurred.
|
* Called when a loss-of-connection event has occurred. This is for an
|
||||||
|
* unexpected disconnection of some sort from the host.
|
||||||
*
|
*
|
||||||
* Parameters:
|
* Parameters:
|
||||||
* psock The TCP socket structure associated.
|
* psock - The TCP socket structure associated.
|
||||||
* flags Set of connection events events
|
* flags - Set of connection events events
|
||||||
*
|
*
|
||||||
* Returned Value:
|
* Returned Value:
|
||||||
* None
|
* None
|
||||||
@ -334,15 +351,9 @@ void tcp_lost_connection(FAR struct socket *psock, uint16_t flags)
|
|||||||
{
|
{
|
||||||
DEBUGASSERT(psock != NULL && psock->s_conn != NULL);
|
DEBUGASSERT(psock != NULL && psock->s_conn != NULL);
|
||||||
|
|
||||||
/* Close the connection */
|
|
||||||
|
|
||||||
net_lock();
|
|
||||||
connection_closed(psock, flags);
|
|
||||||
|
|
||||||
/* Stop the network monitor */
|
/* Stop the network monitor */
|
||||||
|
|
||||||
tcp_stop_monitor((FAR struct tcp_conn_s *)psock->s_conn);
|
tcp_shutdown_monitor((FAR struct tcp_conn_s *)psock->s_conn, flags);
|
||||||
net_unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* NET_TCP_HAVE_STACK */
|
#endif /* NET_TCP_HAVE_STACK */
|
||||||
|
Loading…
Reference in New Issue
Block a user