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

View file

@ -15,8 +15,8 @@ config NET_NACTIVESOCKETS
int "Max socket operations"
default 16
---help---
Maximum number of concurrent socket operations (recv, send, etc.).
Default: 16
Maximum number of concurrent socket operations (recv, send,
connection monitoring, etc.). Default: 16
config NET_SOCKOPTS
bool "Socket options"

View file

@ -58,7 +58,9 @@
* 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
@ -70,6 +72,7 @@ static void connection_event(FAR struct tcp_conn_s *conn, uint16_t flags);
* Some connection related event has occurred
*
* Parameters:
* dev The device which as active when the event was detected.
* conn The connection structure associated with the socket
* 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
*
* 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)
{
@ -108,6 +113,8 @@ static void connection_event(FAR struct tcp_conn_s *conn, uint16_t flags)
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.
*
* 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)
{
FAR struct tcp_conn_s *conn = psock->s_conn;
FAR struct devif_callback_s *cb;
net_lock_t save;
DEBUGASSERT(psock && conn);
@ -144,30 +154,51 @@ int net_startmonitor(FAR struct socket *psock)
* registered the monitoring callback.)
*/
save = net_lock();
if (!(conn->tcpstateflags == TCP_ESTABLISHED ||
conn->tcpstateflags == TCP_SYN_RCVD))
{
/* 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 */
conn->connection_private = NULL;
conn->connection_devcb = NULL;
conn->connection_event = NULL;
/* And return -ENOTCONN to indicate the the monitor was not started
* because the socket was already disconnected.
*/
net_unlock(save);
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 */
conn->connection_private = (void*)psock;
conn->connection_event = connection_event;
net_unlock(save);
return OK;
}
@ -183,14 +214,32 @@ int net_startmonitor(FAR struct socket *psock)
* Returned Value:
* 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)
{
net_lock_t save;
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_devcb = NULL;
conn->connection_event = NULL;
net_unlock(save);
}
/****************************************************************************
@ -207,7 +256,7 @@ void net_stopmonitor(FAR struct tcp_conn_s *conn)
* None
*
* Assumptions:
* Running at the interrupt level
* The caller holds the network lock.
*
****************************************************************************/

View file

@ -237,7 +237,8 @@ FAR struct socket *sockfd_socket(int sockfd);
* case, -ENOTCONN is returned.
*
* 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:
* None
*
* Assumptions:
* The caller holds the network lock (if not, it will be locked momentarily
* by this function).
*
****************************************************************************/
#ifdef CONFIG_NET_TCP
@ -277,7 +282,7 @@ void net_stopmonitor(FAR struct tcp_conn_s *conn);
* None
*
* Assumptions:
* Running at the interrupt level
* The caller holds the network lock.
*
****************************************************************************/

View file

@ -63,15 +63,42 @@
/* Allocate a new TCP data callback */
#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) \
devif_callback_alloc(conn->dev, &conn->list)
# define tcp_callback_free(conn,cb) \
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
/* These macros allocate and free callback structures used for receiving
* notifications of TCP data-related events.
*/
# define tcp_callback_alloc(conn) \
devif_callback_alloc(g_netdevices, &conn->list)
# define tcp_callback_free(conn,cb) \
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
/* 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;
/* 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;
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 the pointer to the connection event
* handler.
*/
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 */

View file

@ -201,7 +201,8 @@ uint16_t tcp_callback(FAR struct net_driver_s *dev,
{
/* Perform the callback */
conn->connection_event(conn, flags);
flags = conn->connection_event(dev, conn, conn->connection_private,
flags);
}
return flags;