mirror of
https://github.com/apache/nuttx.git
synced 2026-05-30 21:36:28 +08:00
net: Implement shutdown() interface and tcp shutdown
Signed-off-by: Zhe Weng <wengzhe@xiaomi.com>
This commit is contained in:
+1
-1
@@ -53,7 +53,7 @@ endif
|
||||
NET_CSRCS += tcp_conn.c tcp_seqno.c tcp_devpoll.c tcp_finddev.c tcp_timer.c
|
||||
NET_CSRCS += tcp_send.c tcp_input.c tcp_appsend.c tcp_listen.c tcp_close.c
|
||||
NET_CSRCS += tcp_monitor.c tcp_callback.c tcp_backlog.c tcp_ipselect.c
|
||||
NET_CSRCS += tcp_recvwindow.c tcp_netpoll.c tcp_ioctl.c
|
||||
NET_CSRCS += tcp_recvwindow.c tcp_netpoll.c tcp_ioctl.c tcp_shutdown.c
|
||||
|
||||
# TCP write buffering
|
||||
|
||||
|
||||
+19
-1
@@ -344,8 +344,9 @@ struct tcp_conn_s
|
||||
FAR struct devif_callback_s *connevents;
|
||||
FAR struct devif_callback_s *connevents_tail;
|
||||
|
||||
/* Reference to TCP close callback instance */
|
||||
/* Reference to TCP shutdown/close callback instance */
|
||||
|
||||
FAR struct devif_callback_s *shdcb;
|
||||
FAR struct devif_callback_s *clscb;
|
||||
struct work_s clswork;
|
||||
|
||||
@@ -767,6 +768,23 @@ void tcp_lost_connection(FAR struct tcp_conn_s *conn,
|
||||
|
||||
int tcp_close(FAR struct socket *psock);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: tcp_shutdown
|
||||
*
|
||||
* Description:
|
||||
* Gracefully shutdown a TCP connection by sending a SYN
|
||||
*
|
||||
* Input Parameters:
|
||||
* psock - An instance of the internal socket structure.
|
||||
* how - Specifies the type of shutdown.
|
||||
*
|
||||
* Assumptions:
|
||||
* Called from normal user-level logic
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int tcp_shutdown(FAR struct socket *psock, int how);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: tcp_ipv4_select
|
||||
*
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
/****************************************************************************
|
||||
* net/tcp/tcp_shutdown.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#ifdef CONFIG_NET_TCP
|
||||
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <nuttx/net/net.h>
|
||||
#include <nuttx/net/netdev.h>
|
||||
#include <nuttx/net/tcp.h>
|
||||
|
||||
#include "netdev/netdev.h"
|
||||
#include "devif/devif.h"
|
||||
#include "tcp/tcp.h"
|
||||
#include "socket/socket.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: tcp_shutdown_eventhandler
|
||||
****************************************************************************/
|
||||
|
||||
static uint16_t tcp_shutdown_eventhandler(FAR struct net_driver_s *dev,
|
||||
FAR void *pvpriv, uint16_t flags)
|
||||
{
|
||||
FAR struct tcp_conn_s *conn = pvpriv;
|
||||
|
||||
ninfo("flags: %04x\n", flags);
|
||||
|
||||
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
|
||||
/* We don't need the send callback anymore. */
|
||||
|
||||
if (conn->sndcb != NULL)
|
||||
{
|
||||
conn->sndcb->flags = 0;
|
||||
conn->sndcb->event = NULL;
|
||||
|
||||
/* The callback will be freed by tcp_free. */
|
||||
|
||||
conn->sndcb = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
dev->d_len = 0;
|
||||
flags = (flags & ~TCP_NEWDATA) | TCP_CLOSE;
|
||||
|
||||
if (conn->shdcb != NULL)
|
||||
{
|
||||
tcp_callback_free(conn, conn->shdcb);
|
||||
conn->shdcb = NULL;
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: tcp_send_fin
|
||||
*
|
||||
* Description:
|
||||
* Send a FIN for TCP connection
|
||||
*
|
||||
* Input Parameters:
|
||||
* conn - TCP connection structure
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
* Assumptions:
|
||||
* Called from normal user-level logic
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static inline int tcp_send_fin(FAR struct socket *psock)
|
||||
{
|
||||
FAR struct tcp_conn_s *conn;
|
||||
int ret = OK;
|
||||
|
||||
/* Interrupts are disabled here to avoid race conditions */
|
||||
|
||||
net_lock();
|
||||
|
||||
conn = (FAR struct tcp_conn_s *)psock->s_conn;
|
||||
DEBUGASSERT(conn != NULL);
|
||||
|
||||
if ((conn->tcpstateflags == TCP_ESTABLISHED ||
|
||||
conn->tcpstateflags == TCP_SYN_SENT ||
|
||||
conn->tcpstateflags == TCP_SYN_RCVD))
|
||||
{
|
||||
if ((conn->shdcb = tcp_callback_alloc(conn)) == NULL)
|
||||
{
|
||||
ret = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Set up to receive TCP data event callbacks */
|
||||
|
||||
conn->shdcb->flags = TCP_POLL;
|
||||
conn->shdcb->event = tcp_shutdown_eventhandler;
|
||||
conn->shdcb->priv = conn; /* reference for event handler to free cb */
|
||||
|
||||
/* Notify the device driver of the availability of TX data */
|
||||
|
||||
tcp_send_txnotify(psock, conn);
|
||||
}
|
||||
|
||||
out:
|
||||
net_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: tcp_shutdown
|
||||
*
|
||||
* Description:
|
||||
* Gracefully shutdown a TCP connection by sending a FIN
|
||||
*
|
||||
* Input Parameters:
|
||||
* psock - An instance of the internal socket structure.
|
||||
* how - Specifies the type of shutdown.
|
||||
*
|
||||
* Assumptions:
|
||||
* Called from normal user-level logic
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int tcp_shutdown(FAR struct socket *psock, int how)
|
||||
{
|
||||
if (!(how & SHUT_WR))
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
tcp_unlisten(psock->s_conn); /* No longer accepting connections */
|
||||
|
||||
return tcp_send_fin(psock);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NET_TCP */
|
||||
Reference in New Issue
Block a user