TCP networking: Hook the network monitor into the device event notification logic

This commit is contained in:
Gregory Nutt
2015-05-30 11:29:47 -06:00
parent 5142a1a1db
commit 8b029fbbee
5 changed files with 113 additions and 14 deletions
+2 -2
View File
@@ -15,8 +15,8 @@ config NET_NACTIVESOCKETS
int "Max socket operations" int "Max socket operations"
default 16 default 16
---help--- ---help---
Maximum number of concurrent socket operations (recv, send, etc.). Maximum number of concurrent socket operations (recv, send,
Default: 16 connection monitoring, etc.). Default: 16
config NET_SOCKOPTS config NET_SOCKOPTS
bool "Socket options" bool "Socket options"
+56 -7
View File
@@ -58,7 +58,9 @@
* Private Function Prototypes * Private Function Prototypes
****************************************************************************/ ****************************************************************************/
static void connection_event(FAR struct tcp_conn_s *conn, uint16_t flags); static uint16_t connection_event(FAR struct net_driver_s *dev,
FAR void *pvconn, FAR void *pvpriv,
uint16_t flags);
/**************************************************************************** /****************************************************************************
* Private Functions * Private Functions
@@ -70,6 +72,7 @@ static void connection_event(FAR struct tcp_conn_s *conn, uint16_t flags);
* Some connection related event has occurred * Some connection related event has occurred
* *
* Parameters: * Parameters:
* dev The device which as active when the event was detected.
* conn The connection structure associated with the socket * conn The connection structure associated with the socket
* flags Set of events describing why the callback was invoked * flags Set of events describing why the callback was invoked
* *
@@ -77,13 +80,15 @@ static void connection_event(FAR struct tcp_conn_s *conn, uint16_t flags);
* None * None
* *
* Assumptions: * Assumptions:
* Running at the interrupt level * The network is locked.
* *
****************************************************************************/ ****************************************************************************/
static void connection_event(FAR struct tcp_conn_s *conn, uint16_t flags) static uint16_t connection_event(FAR struct net_driver_s *dev,
FAR void *pvconn, FAR void *pvpriv,
uint16_t flags)
{ {
FAR struct socket *psock = (FAR struct socket *)conn->connection_private; FAR struct socket *psock = (FAR struct socket *)pvpriv;
if (psock) if (psock)
{ {
@@ -108,6 +113,8 @@ static void connection_event(FAR struct tcp_conn_s *conn, uint16_t flags)
psock->s_flags &= ~_SF_CLOSED; psock->s_flags &= ~_SF_CLOSED;
} }
} }
return flags;
} }
/**************************************************************************** /****************************************************************************
@@ -129,13 +136,16 @@ static void connection_event(FAR struct tcp_conn_s *conn, uint16_t flags)
* case, -ENOTCONN is returned. * case, -ENOTCONN is returned.
* *
* Assumptions: * Assumptions:
* The caller holds the network lock. * The caller holds the network lock (if not, it will be locked momentarily
* by this function).
* *
****************************************************************************/ ****************************************************************************/
int net_startmonitor(FAR struct socket *psock) int net_startmonitor(FAR struct socket *psock)
{ {
FAR struct tcp_conn_s *conn = psock->s_conn; FAR struct tcp_conn_s *conn = psock->s_conn;
FAR struct devif_callback_s *cb;
net_lock_t save;
DEBUGASSERT(psock && conn); DEBUGASSERT(psock && conn);
@@ -144,30 +154,51 @@ int net_startmonitor(FAR struct socket *psock)
* registered the monitoring callback.) * registered the monitoring callback.)
*/ */
save = net_lock();
if (!(conn->tcpstateflags == TCP_ESTABLISHED || if (!(conn->tcpstateflags == TCP_ESTABLISHED ||
conn->tcpstateflags == TCP_SYN_RCVD)) conn->tcpstateflags == TCP_SYN_RCVD))
{ {
/* Invoke the TCP_CLOSE connection event now */ /* Invoke the TCP_CLOSE connection event now */
connection_event(conn, TCP_CLOSE); (void)connection_event(NULL, conn, psock, TCP_CLOSE);
/* Make sure that the monitor is stopped */ /* Make sure that the monitor is stopped */
conn->connection_private = NULL; conn->connection_private = NULL;
conn->connection_devcb = NULL;
conn->connection_event = NULL; conn->connection_event = NULL;
/* And return -ENOTCONN to indicate the the monitor was not started /* And return -ENOTCONN to indicate the the monitor was not started
* because the socket was already disconnected. * because the socket was already disconnected.
*/ */
net_unlock(save);
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
* the network goes down.
*/
cb = tcp_monitor_callback_alloc(conn);
if (cb != NULL)
{
cb->event = connection_event;
cb->priv = (void*)psock;
cb->flags = NETDEV_DOWN;
}
conn->connection_devcb = cb;
/* Set up to receive callbacks on connection-related events */ /* Set up to receive callbacks on connection-related events */
conn->connection_private = (void*)psock; conn->connection_private = (void*)psock;
conn->connection_event = connection_event; conn->connection_event = connection_event;
net_unlock(save);
return OK; return OK;
} }
@@ -183,14 +214,32 @@ int net_startmonitor(FAR struct socket *psock)
* Returned Value: * Returned Value:
* None * None
* *
* Assumptions:
* The caller holds the network lock (if not, it will be locked momentarily
* by this function).
*
****************************************************************************/ ****************************************************************************/
void net_stopmonitor(FAR struct tcp_conn_s *conn) void net_stopmonitor(FAR struct tcp_conn_s *conn)
{ {
net_lock_t save;
DEBUGASSERT(conn); DEBUGASSERT(conn);
/* Free any allocated device event callback structure */
save = net_lock();
if (conn->connection_devcb)
{
tcp_monitor_callback_free(conn, conn->connection_devcb);
}
/* Nullify all connection event data */
conn->connection_private = NULL; conn->connection_private = NULL;
conn->connection_devcb = NULL;
conn->connection_event = NULL; conn->connection_event = NULL;
net_unlock(save);
} }
/**************************************************************************** /****************************************************************************
@@ -207,7 +256,7 @@ void net_stopmonitor(FAR struct tcp_conn_s *conn)
* None * None
* *
* Assumptions: * Assumptions:
* Running at the interrupt level * The caller holds the network lock.
* *
****************************************************************************/ ****************************************************************************/
+7 -2
View File
@@ -237,7 +237,8 @@ FAR struct socket *sockfd_socket(int sockfd);
* case, -ENOTCONN is returned. * case, -ENOTCONN is returned.
* *
* Assumptions: * Assumptions:
* The caller holds the network lock. * The caller holds the network lock (if not, it will be locked momentarily
* by this function).
* *
****************************************************************************/ ****************************************************************************/
@@ -257,6 +258,10 @@ int net_startmonitor(FAR struct socket *psock);
* Returned Value: * Returned Value:
* None * None
* *
* Assumptions:
* The caller holds the network lock (if not, it will be locked momentarily
* by this function).
*
****************************************************************************/ ****************************************************************************/
#ifdef CONFIG_NET_TCP #ifdef CONFIG_NET_TCP
@@ -277,7 +282,7 @@ void net_stopmonitor(FAR struct tcp_conn_s *conn);
* None * None
* *
* Assumptions: * Assumptions:
* Running at the interrupt level * The caller holds the network lock.
* *
****************************************************************************/ ****************************************************************************/
+46 -2
View File
@@ -63,15 +63,42 @@
/* Allocate a new TCP data callback */ /* Allocate a new TCP data callback */
#ifdef CONFIG_NETDEV_MULTINIC #ifdef CONFIG_NETDEV_MULTINIC
/* These macros allocate and free callback structures used for receiving
* notifications of TCP data-related events.
*/
# define tcp_callback_alloc(conn) \ # define tcp_callback_alloc(conn) \
devif_callback_alloc(conn->dev, &conn->list) devif_callback_alloc(conn->dev, &conn->list)
# define tcp_callback_free(conn,cb) \ # define tcp_callback_free(conn,cb) \
devif_callback_free(conn->dev, cb, &conn->list) devif_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_callback_free(conn->dev, cb, NULL)
#else #else
/* These macros allocate and free callback structures used for receiving
* notifications of TCP data-related events.
*/
# define tcp_callback_alloc(conn) \ # define tcp_callback_alloc(conn) \
devif_callback_alloc(g_netdevices, &conn->list) devif_callback_alloc(g_netdevices, &conn->list)
# define tcp_callback_free(conn,cb) \ # define tcp_callback_free(conn,cb) \
devif_callback_free(g_netdevices, cb, &conn->list) devif_callback_free(g_netdevices, 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(g_netdevices, NULL)
# define tcp_monitor_callback_free(conn,cb) \
devif_callback_free(g_netdevices, cb, NULL)
#endif #endif
/* Get the current maximum segment size that can be sent on the current /* Get the current maximum segment size that can be sent on the current
@@ -227,17 +254,34 @@ struct tcp_conn_s
FAR struct devif_callback_s *list; FAR struct devif_callback_s *list;
/* 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() handler when it is invoked with a point to this structure
* as an argument.
* accept: This is the the pointer to the accept handler.
*/
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 /* connection_event() is called on any of the subset of connection-related
* events. * 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 the pointer to the connection event
* handler.
*/ */
FAR void *connection_private; FAR void *connection_private;
void (*connection_event)(FAR struct tcp_conn_s *conn, uint16_t flags); 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 */
+2 -1
View File
@@ -201,7 +201,8 @@ uint16_t tcp_callback(FAR struct net_driver_s *dev,
{ {
/* Perform the callback */ /* Perform the callback */
conn->connection_event(conn, flags); flags = conn->connection_event(dev, conn, conn->connection_private,
flags);
} }
return flags; return flags;