mirror of
https://github.com/apache/nuttx.git
synced 2025-01-13 10:58:49 +08:00
Add uIP support more multi-threaded socket access
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@858 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
parent
462becfbbb
commit
ad1e5e145b
23 changed files with 758 additions and 333 deletions
|
@ -428,7 +428,8 @@
|
|||
* Added telnet NSH configuration for Neuros OSD.
|
||||
* Basic integration of concurrent telnet/serial NSH functional on Neuros
|
||||
OSD.
|
||||
* Fixed a critical bug that effects the way that environement variables are
|
||||
* Fixed a critical bug that effects the way that environment variables are
|
||||
shared amongst pthreads.
|
||||
|
||||
|
||||
* uIP port enhance to support multi-threaded, concurrent socket access. So,
|
||||
for example, one thread can be reading from a socket while another is
|
||||
writing to the socket.
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<tr align="center" bgcolor="#e4e4e4">
|
||||
<td>
|
||||
<h1><big><font color="#3c34ec"><i>NuttX RTOS</i></font></big></h1>
|
||||
<p>Last Updated: August 30, 2008</p>
|
||||
<p>Last Updated: September 1, 2008</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
@ -1062,8 +1062,11 @@ nuttx-0.3.13 2008-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr>
|
|||
* Added telnet NSH configuration for Neuros OSD.
|
||||
* Basic integration of concurrent telnet/serial NSH functional on Neuros
|
||||
OSD.
|
||||
* Fixed a critical bug that effects the way that environement variables are
|
||||
* Fixed a critical bug that effects the way that environment variables are
|
||||
shared amongst pthreads.
|
||||
* uIP port enhance to support multi-threaded, concurrent socket access. So,
|
||||
for example, one thread can be reading from a socket while another is
|
||||
writing to the socket.
|
||||
|
||||
pascal-0.1.3 2008-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
</b></big></h1>
|
||||
<p><small>by</small></p>
|
||||
<p>Gregory Nutt</p>
|
||||
<p><small>Last Update: July 21, 2008</small></p>
|
||||
<p><small>Last Update: September 1, 2008</small></p>
|
||||
</center>
|
||||
|
||||
<center><h1>Table of Contents</h1></center>
|
||||
|
@ -1527,6 +1527,10 @@ The system can be re-made subsequently by just typing <code>make</code>.
|
|||
<li>
|
||||
<code>CONFIG_NSOCKET_DESCRIPTORS</code>: Maximum number of socket descriptors per task/thread.
|
||||
</li>
|
||||
<li>
|
||||
<code>CONFIG_NET_NACTIVESOCKETS</code>: Maximum number of concurrent socket operations (recv, send, etc.).
|
||||
Default: <code>CONFIG_NET_TCP_CONNS</code>+<code>CONFIG_NET_UDP_CONNS</code>.
|
||||
</li>
|
||||
<li>
|
||||
<code>CONFIG_NET_SOCKOPTS</code>: Enable or disable support for socket options.
|
||||
</li>
|
||||
|
|
12
TODO
12
TODO
|
@ -7,7 +7,7 @@ NuttX TODO List (Last updated July 31, 2008)
|
|||
(1) Signals (sched/, arch/)
|
||||
(1) pthreads (sched/)
|
||||
(1) C++ Support
|
||||
(11) Network (net/, netutils/)
|
||||
(10) Network (net/, netutils/)
|
||||
(2) USB (drivers/usbdev)
|
||||
(3) Libraries (lib/)
|
||||
(4) File system/Generic drivers (fs/, drivers/)
|
||||
|
@ -148,16 +148,6 @@ o Network (net/, netutils/)
|
|||
Priority: Medium, The feature is not important, but it is important
|
||||
for NuttX to resolve the architectural issues.
|
||||
|
||||
Description: uIP/Socket callback logic is not thread safe. This means that
|
||||
a socket cannot be used concurrently by two threads. Minimal
|
||||
fix: Add mutex to support exclusion for protection.
|
||||
Status: Open
|
||||
Priority: Low. The currently socket design cannot be use concurrently
|
||||
by threads with out a major redesign. The feature is not
|
||||
of great value since the use model for multi-thread sockets
|
||||
is not common. Adding mutex support would only mask the
|
||||
underlying issue.
|
||||
|
||||
Description: IPv6 support is incomplete
|
||||
Status: Open
|
||||
Priority: Medium
|
||||
|
|
|
@ -247,6 +247,8 @@ defconfig -- This is a configuration file similar to the Linux
|
|||
CONFIG_NET_IPv6 - Build in support for IPv6
|
||||
CONFIG_NSOCKET_DESCRIPTORS - Maximum number of socket descriptors
|
||||
per task/thread.
|
||||
CONFIG_NET_NACTIVESOCKETS - Maximum number of concurrent socket
|
||||
operations (recv, send, etc.). Default: CONFIG_NET_TCP_CONNS+CONFIG_NET_UDP_CONNS
|
||||
CONFIG_NET_SOCKOPTS - Enable or disable support for socket options
|
||||
|
||||
CONFIG_NET_BUFSIZE - uIP buffer size
|
||||
|
|
|
@ -95,6 +95,7 @@
|
|||
*/
|
||||
|
||||
struct uip_driver_s; /* Forward reference */
|
||||
struct uip_callback_s; /* Forward reference */
|
||||
struct uip_conn
|
||||
{
|
||||
dq_entry_t node; /* Implements a doubly linked list */
|
||||
|
@ -121,9 +122,6 @@ struct uip_conn
|
|||
uint8 timer; /* The retransmission timer (units: half-seconds) */
|
||||
uint8 nrtx; /* The number of retransmissions for the last
|
||||
* segment sent */
|
||||
uint8 data_flags; /* Flags that will be handled by the data_event()
|
||||
* callback function (see data_event() discussion below).
|
||||
*/
|
||||
|
||||
/* Read-ahead buffering */
|
||||
|
||||
|
@ -131,37 +129,41 @@ struct uip_conn
|
|||
sq_queue_t readahead;
|
||||
#endif
|
||||
|
||||
/* Higher level logic can retain application specific information
|
||||
* in the following:
|
||||
/* Application callbacks:
|
||||
*
|
||||
* data_event() is called on all events. Normally, the input flags are
|
||||
* returned, however, the implemenation may set one of the following:
|
||||
* Data transfer events are retained in 'list'. Event handlers in 'list'
|
||||
* are called for events specified in the flags set within struct
|
||||
* uip_callback_s
|
||||
*
|
||||
* UIP_CLOSE - Gracefully close the current connection
|
||||
* UIP_ABORT - Abort (reset) the current connection on an error that
|
||||
* prevents UIP_CLOSE from working.
|
||||
* When an callback is executed from 'list', the input flags are normally
|
||||
* returned, however, the implementation may set one of the following:
|
||||
*
|
||||
* Or clear the following:
|
||||
* UIP_CLOSE - Gracefully close the current connection
|
||||
* UIP_ABORT - Abort (reset) the current connection on an error that
|
||||
* prevents UIP_CLOSE from working.
|
||||
*
|
||||
* UIP_NEWDATA - May be cleared to suppress returning the ACK response.
|
||||
* (dev->d_len should also be set to zero in this case).
|
||||
* And/Or set/clear the following:
|
||||
*
|
||||
*
|
||||
* The provider of the data_event callback must also set data_flags. This
|
||||
* will inform the uIP layer which flags are and are not handled by the
|
||||
* callback.
|
||||
* accept() is called when the TCP logic has created a connection
|
||||
* connection_event() is called on any of the subset of connection-related events
|
||||
* UIP_NEWDATA - May be cleared to indicate that the data was consumed
|
||||
* and that no further process of the new data should be
|
||||
* attempted.
|
||||
* UIP_SNDACK - If UIP_NEWDATA is cleared, then UIP_SNDACK may be set
|
||||
* to indicate that an ACK should be included in the response.
|
||||
* (In UIP_NEWDATA is cleared bu UIP_SNDACK is not set, then
|
||||
* dev->d_len should also be cleared).
|
||||
*/
|
||||
|
||||
void *data_private;
|
||||
uint8 (*data_event)(struct uip_driver_s *dev, struct uip_conn *conn, uint8 flags);
|
||||
struct uip_callback_s *list;
|
||||
|
||||
/* accept() is called when the TCP logic has created a connection */
|
||||
|
||||
void *accept_private;
|
||||
int (*accept)(struct uip_conn *listener, struct uip_conn *conn);
|
||||
|
||||
/* connection_event() is called on any of the subset of connection-related events */
|
||||
|
||||
void *connection_private;
|
||||
void (*connection_event)(struct uip_conn *conn, uint8 flags);
|
||||
void (*connection_event)(struct uip_conn *conn, uint16 flags);
|
||||
};
|
||||
|
||||
/* The following structure is used to handle read-ahead buffering for TCP
|
||||
|
@ -267,6 +269,11 @@ struct uip_tcpip_hdr
|
|||
|
||||
extern struct uip_conn *uip_tcpalloc(void);
|
||||
|
||||
/* Allocate a new TCP data callback */
|
||||
|
||||
#define uip_tcpcallbackalloc(conn) uip_callbackalloc(&conn->list)
|
||||
#define uip_tcpcallbackfree(conn,cb) uip_callbackfree(cb, &conn->list)
|
||||
|
||||
/* Free a connection structure that is no longer in use. This should
|
||||
* be done by the implementation of close()
|
||||
*/
|
||||
|
|
|
@ -69,6 +69,7 @@
|
|||
/* Representation of a uIP UDP connection */
|
||||
|
||||
struct uip_driver_s; /* Forward reference */
|
||||
struct uip_callback_s; /* Forward reference */
|
||||
struct uip_udp_conn
|
||||
{
|
||||
dq_entry_t node; /* Supports a doubly linked list */
|
||||
|
@ -77,10 +78,9 @@ struct uip_udp_conn
|
|||
uint16 rport; /* The remote port number in network byte order */
|
||||
uint8 ttl; /* Default time-to-live */
|
||||
|
||||
/* Defines the UDP callback */
|
||||
/* Defines the list of UDP callbacks */
|
||||
|
||||
void *private;
|
||||
void (*event)(struct uip_driver_s *dev, struct uip_udp_conn *conn, uint8 flags);
|
||||
struct uip_callback_s *list;
|
||||
};
|
||||
|
||||
/* The UDP and IP headers */
|
||||
|
@ -159,6 +159,11 @@ struct uip_udp_stats_s
|
|||
|
||||
extern struct uip_udp_conn *uip_udpalloc(void);
|
||||
|
||||
/* Allocate a new TCP data callback */
|
||||
|
||||
#define uip_udpcallbackalloc(conn) uip_callbackalloc(&conn->list)
|
||||
#define uip_udpcallbackfree(conn,cb) uip_callbackfree(cb, &conn->list)
|
||||
|
||||
/* Free a connection structure that is no longer in use. This should
|
||||
* be done by the implementation of close()
|
||||
*/
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* are used by uIP programs as well as internal uIP structures and function
|
||||
* declarations.
|
||||
*
|
||||
* Copyright (C) 2007 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
*
|
||||
* This logic was leveraged from uIP which also has a BSD-style license:
|
||||
|
@ -55,6 +55,7 @@
|
|||
#include <arpa/inet.h>
|
||||
|
||||
#include <net/uip/uipopt.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Definitions
|
||||
****************************************************************************/
|
||||
|
@ -62,26 +63,52 @@
|
|||
/* The following flags may be set in the set of flags before calling the
|
||||
* application callback. The UIP_ACKDATA, UIP_NEWDATA, and UIP_CLOSE flags
|
||||
* may be set at the same time, whereas the others are mutualy exclusive.
|
||||
*
|
||||
* UIP_ACKDATA IN: Signifies that the outstanding data was acked and
|
||||
* the application should send out new data instead
|
||||
* of retransmitting the last data
|
||||
* OUT: Input state must be preserved on output.
|
||||
* UIP_NEWDATA IN: Set to indicate that the peer has sent us new data.
|
||||
* OUT: Cleared (only) by the application logic to indicate
|
||||
* that the new data was consumed, suppressing further
|
||||
* attempts to process the new data.
|
||||
* UIP_SNDACK IN: Not used; always zero
|
||||
* OUT: Set by the application if the new data was consumed
|
||||
* and an ACK should be sent in the response.
|
||||
* UIP_REXMIT IN: Tells the application to retransmit the data that
|
||||
* was last sent
|
||||
* OUT: Not used
|
||||
* UIP_POLL IN: Used for polling the application. This is provided
|
||||
* periodically from the drivers to support (1) timed
|
||||
* operations, and (2) to check if the application has
|
||||
* data that it wants to send
|
||||
* OUT: Not used
|
||||
* UIP_CLOSE IN: The remote host has closed the connection, thus the
|
||||
* connection has gone away.
|
||||
* OUT: The application signals that it wants to close the
|
||||
* connection
|
||||
* UIP_ABORT IN: The remote host has aborted the connection, thus the
|
||||
* connection has gone away.
|
||||
* OUT: The application signals that it wants to abort the
|
||||
* connection
|
||||
* UIP_CONNECTED IN: We have got a connection from a remote host and have
|
||||
* set up a new connection for it, or an active connection
|
||||
* has been successfully established
|
||||
* OUT: Not used
|
||||
* UIP_TIMEDOUT IN: The connection has been aborted due to too many
|
||||
* retransmissions
|
||||
* OUT: Not used
|
||||
*/
|
||||
|
||||
#define UIP_ACKDATA (1 << 0) /* Signifies that the outstanding data was acked and the
|
||||
* application should send out new data instead of retransmitting
|
||||
* the last data */
|
||||
#define UIP_NEWDATA (1 << 1) /* Flags the fact that the peer has sent us new data */
|
||||
#define UIP_REXMIT (1 << 2) /* Tells the application to retransmit the data that was last
|
||||
* sent */
|
||||
#define UIP_POLL (1 << 3) /* Used for polling the application, to check if the application
|
||||
* has data that it wants to send */
|
||||
#define UIP_CLOSE (1 << 4) /* The remote host has closed the connection, thus the connection
|
||||
* has gone away. Or the application signals that it wants to
|
||||
* close the connection */
|
||||
#define UIP_ABORT (1 << 5) /* The remote host has aborted the connection, thus the connection
|
||||
* has gone away. Or the application signals that it wants to
|
||||
* abort the connection */
|
||||
#define UIP_CONNECTED (1 << 6) /* We have got a connection from a remote host and have set up a
|
||||
* new connection for it, or an active connection has been
|
||||
* successfully established */
|
||||
#define UIP_TIMEDOUT (1 << 7) /* The connection has been aborted due to too many retransmissions */
|
||||
#define UIP_ACKDATA (1 << 0)
|
||||
#define UIP_NEWDATA (1 << 1)
|
||||
#define UIP_SNDACK (1 << 2)
|
||||
#define UIP_REXMIT (1 << 3)
|
||||
#define UIP_POLL (1 << 4)
|
||||
#define UIP_CLOSE (1 << 5)
|
||||
#define UIP_ABORT (1 << 6)
|
||||
#define UIP_CONNECTED (1 << 7)
|
||||
#define UIP_TIMEDOUT (1 << 8)
|
||||
|
||||
#define UIP_DATA_EVENTS (UIP_ACKDATA|UIP_NEWDATA|UIP_REXMIT|UIP_POLL)
|
||||
#define UIP_CONN_EVENTS (UIP_CLOSE|UIP_ABORT|UIP_CONNECTED|UIP_TIMEDOUT)
|
||||
|
@ -116,7 +143,7 @@
|
|||
* Public Type Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* Repressentation of an IP address */
|
||||
/* Representation of an IP address */
|
||||
|
||||
typedef in_addr_t uip_ip4addr_t;
|
||||
typedef uint16 uip_ip6addr_t[8];
|
||||
|
@ -162,6 +189,26 @@ struct uip_ip_hdr
|
|||
#endif /* CONFIG_NET_IPv6 */
|
||||
};
|
||||
|
||||
/* Describes a uIP callback
|
||||
*
|
||||
* flink - Supports a singly linked list
|
||||
* event - Provides the address of the callback function entry point.
|
||||
* pvconn is a pointer to one of struct uip_conn or struct uip_udp_conn.
|
||||
* private - Holds a reference to application specific data that will
|
||||
* provided
|
||||
* flags - Set by the application to inform the uIP layer which flags
|
||||
* are and are not handled by the callback.
|
||||
*/
|
||||
|
||||
struct uip_driver_s; /* Forward reference */
|
||||
struct uip_callback_s
|
||||
{
|
||||
FAR struct uip_callback_s *flink;
|
||||
uint16 (*event)(struct uip_driver_s *dev, void *pvconn, void *pvprivate, uint16 flags);
|
||||
void *private;
|
||||
uint16 flags;
|
||||
};
|
||||
|
||||
/* Protocol-specific support */
|
||||
|
||||
#include <net/uip/uip-tcp.h>
|
||||
|
|
|
@ -103,7 +103,11 @@
|
|||
/* The maximum amount of concurrent UDP connection, Default: 10 */
|
||||
|
||||
#ifndef CONFIG_NET_UDP_CONNS
|
||||
# define CONFIG_NET_UDP_CONNS 10
|
||||
# ifdef CONFIG_NET_UDP
|
||||
# define CONFIG_NET_UDP_CONNS 10
|
||||
# else
|
||||
# define CONFIG_NET_UDP_CONNS 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* TCP configuration options */
|
||||
|
@ -116,7 +120,11 @@
|
|||
*/
|
||||
|
||||
#ifndef CONFIG_NET_TCP_CONNS
|
||||
# define CONFIG_NET_TCP_CONNS 10
|
||||
# ifdef CONFIG_NET_TCP
|
||||
# define CONFIG_NET_TCP_CONNS 10
|
||||
# else
|
||||
# define CONFIG_NET_TCP_CONNS 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* The maximum number of simultaneously listening TCP ports.
|
||||
|
@ -128,6 +136,15 @@
|
|||
# define CONFIG_NET_MAX_LISTENPORTS 20
|
||||
#endif
|
||||
|
||||
/* Define the maximum number of concurrently active UDP and TCP
|
||||
* ports. This number must be greater than the number of open
|
||||
* sockets in order to support multi-threaded read/write operations.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_NET_NACTIVESOCKETS
|
||||
# define CONFIG_NET_NACTIVESOCKETS (CONFIG_NET_TCP_CONNS + CONFIG_NET_UDP_CONNS)
|
||||
#endif
|
||||
|
||||
/* The initial retransmission timeout counted in timer pulses.
|
||||
*
|
||||
* This should not be changed.
|
||||
|
|
155
net/connect.c
155
net/connect.c
|
@ -50,6 +50,7 @@
|
|||
#include <net/uip/uip-arch.h>
|
||||
|
||||
#include "net-internal.h"
|
||||
#include "uip/uip-internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
|
@ -58,9 +59,10 @@
|
|||
#ifdef CONFIG_NET_TCP
|
||||
struct tcp_connect_s
|
||||
{
|
||||
FAR struct uip_conn *tc_conn; /* Reference to TCP connection structure */
|
||||
sem_t tc_sem; /* Semaphore signals recv completion */
|
||||
int tc_result; /* OK on success, otherwise a negated errno. */
|
||||
FAR struct uip_conn *tc_conn; /* Reference to TCP connection structure */
|
||||
FAR struct uip_callback_s *tc_cb; /* Reference to callback instance */
|
||||
sem_t tc_sem; /* Semaphore signals recv completion */
|
||||
int tc_result; /* OK on success, otherwise a negated errno. */
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -69,12 +71,12 @@ struct tcp_connect_s
|
|||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_TCP
|
||||
static void connection_event(struct uip_conn *conn, uint8 flags);
|
||||
static inline void tcp_setup_callbacks(struct uip_conn *conn, FAR struct socket *psock,
|
||||
FAR struct tcp_connect_s *pstate);
|
||||
static inline void tcp_teardown_callbacks(struct uip_conn *conn, int status);
|
||||
static uint8 tcp_connect_interrupt(struct uip_driver_s *dev,
|
||||
struct uip_conn *conn, uint8 flags);
|
||||
static void connection_event(struct uip_conn *conn, uint16 flags);
|
||||
static inline int tcp_setup_callbacks(FAR struct socket *psock,
|
||||
FAR struct tcp_connect_s *pstate);
|
||||
static inline void tcp_teardown_callbacks(struct tcp_connect_s *pstate, int status);
|
||||
static uint16 tcp_connect_interrupt(struct uip_driver_s *dev, void *pvconn,
|
||||
void *pvprivate, uint16 flags);
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
static inline int tcp_connect(FAR struct socket *psock, const struct sockaddr_in6 *inaddr);
|
||||
#else
|
||||
|
@ -105,13 +107,13 @@ static inline int tcp_connect(FAR struct socket *psock, const struct sockaddr_in
|
|||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_TCP
|
||||
static void connection_event(struct uip_conn *conn, uint8 flags)
|
||||
static void connection_event(struct uip_conn *conn, uint16 flags)
|
||||
{
|
||||
FAR struct socket *psock = (FAR struct socket *)conn->connection_private;
|
||||
|
||||
if (psock)
|
||||
{
|
||||
nvdbg("flags: %02x s_flags: %02x\n", flags, psock->s_flags);
|
||||
nvdbg("flags: %04x s_flags: %02x\n", flags, psock->s_flags);
|
||||
|
||||
/* UIP_CLOSE: The remote host has closed the connection
|
||||
* UIP_ABORT: The remote host has aborted the connection
|
||||
|
@ -141,19 +143,34 @@ static void connection_event(struct uip_conn *conn, uint8 flags)
|
|||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_TCP
|
||||
static inline void tcp_setup_callbacks(struct uip_conn *conn, FAR struct socket *psock,
|
||||
static inline int tcp_setup_callbacks(FAR struct socket *psock,
|
||||
FAR struct tcp_connect_s *pstate)
|
||||
{
|
||||
FAR struct uip_conn *conn = psock->s_conn;
|
||||
int ret = -EBUSY;
|
||||
|
||||
/* Initialize the TCP state structure */
|
||||
|
||||
(void)sem_init(&pstate->tc_sem, 0, 0); /* Doesn't really fail */
|
||||
pstate->tc_conn = conn;
|
||||
pstate->tc_result = -EAGAIN;
|
||||
|
||||
/* Set up the callbacks in the connection */
|
||||
|
||||
conn->data_flags = UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT|UIP_CONNECTED;
|
||||
conn->data_private = (void*)pstate;
|
||||
conn->data_event = tcp_connect_interrupt;
|
||||
pstate->tc_cb = uip_tcpcallbackalloc(conn);
|
||||
if (pstate->tc_cb)
|
||||
{
|
||||
pstate->tc_cb->flags = UIP_NEWDATA|UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT|UIP_CONNECTED;
|
||||
pstate->tc_cb->private = (void*)pstate;
|
||||
pstate->tc_cb->event = tcp_connect_interrupt;
|
||||
|
||||
/* 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_event = connection_event;
|
||||
conn->connection_private = (void*)psock;
|
||||
conn->connection_event = connection_event;
|
||||
ret = OK;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_NET_TCP */
|
||||
|
||||
|
@ -162,13 +179,13 @@ static inline void tcp_setup_callbacks(struct uip_conn *conn, FAR struct socket
|
|||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_TCP
|
||||
static inline void tcp_teardown_callbacks(struct uip_conn *conn, int status)
|
||||
static inline void tcp_teardown_callbacks(struct tcp_connect_s *pstate, int status)
|
||||
{
|
||||
struct uip_conn *conn = pstate->tc_conn;
|
||||
|
||||
/* Make sure that no further interrupts are processed */
|
||||
|
||||
conn->data_flags = 0;
|
||||
conn->data_private = NULL;
|
||||
conn->data_event = NULL;
|
||||
uip_tcpcallbackfree(conn, pstate->tc_cb);
|
||||
|
||||
/* If we successfully connected, we will continue to monitor the connection state
|
||||
* via callbacks.
|
||||
|
@ -193,11 +210,11 @@ static inline void tcp_teardown_callbacks(struct uip_conn *conn, int status)
|
|||
*
|
||||
* Parameters:
|
||||
* dev The sructure of the network driver that caused the interrupt
|
||||
* conn The connection structure associated with the socket
|
||||
* pvconn The connection structure associated with the socket
|
||||
* flags Set of events describing why the callback was invoked
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
* The new flags setting
|
||||
*
|
||||
* Assumptions:
|
||||
* Running at the interrupt level
|
||||
|
@ -205,12 +222,12 @@ static inline void tcp_teardown_callbacks(struct uip_conn *conn, int status)
|
|||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_TCP
|
||||
static uint8 tcp_connect_interrupt(struct uip_driver_s *dev,
|
||||
struct uip_conn *conn, uint8 flags)
|
||||
static uint16 tcp_connect_interrupt(struct uip_driver_s *dev, void *pvconn,
|
||||
void *pvprivate, uint16 flags)
|
||||
{
|
||||
struct tcp_connect_s *pstate = (struct tcp_connect_s *)conn->data_private;
|
||||
struct tcp_connect_s *pstate = (struct tcp_connect_s *)pvprivate;
|
||||
|
||||
nvdbg("flags: %02x\n", flags);
|
||||
nvdbg("flags: %04x\n", flags);
|
||||
|
||||
/* 'private' might be null in some race conditions (?) */
|
||||
|
||||
|
@ -270,7 +287,7 @@ static uint8 tcp_connect_interrupt(struct uip_driver_s *dev,
|
|||
|
||||
/* Stop further callbacks */
|
||||
|
||||
tcp_teardown_callbacks(pstate->tc_conn, pstate->tc_result);
|
||||
tcp_teardown_callbacks(pstate, pstate->tc_result);
|
||||
|
||||
/* Wake up the waiting thread */
|
||||
|
||||
|
@ -306,7 +323,6 @@ static inline int tcp_connect(FAR struct socket *psock, const struct sockaddr_in
|
|||
static inline int tcp_connect(FAR struct socket *psock, const struct sockaddr_in *inaddr)
|
||||
#endif
|
||||
{
|
||||
FAR struct uip_conn *conn;
|
||||
struct tcp_connect_s state;
|
||||
irqstate_t flags;
|
||||
int ret = OK;
|
||||
|
@ -320,8 +336,7 @@ static inline int tcp_connect(FAR struct socket *psock, const struct sockaddr_in
|
|||
|
||||
/* Get the connection reference from the socket */
|
||||
|
||||
conn = psock->s_conn;
|
||||
if (!conn) /* Should always be non-NULL */
|
||||
if (!psock->s_conn) /* Should always be non-NULL */
|
||||
{
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
@ -329,60 +344,62 @@ static inline int tcp_connect(FAR struct socket *psock, const struct sockaddr_in
|
|||
{
|
||||
/* Perform the uIP connection operation */
|
||||
|
||||
ret = uip_tcpconnect(conn, inaddr);
|
||||
ret = uip_tcpconnect(psock->s_conn, inaddr);
|
||||
}
|
||||
|
||||
if (ret >= 0)
|
||||
{
|
||||
/* Initialize the TCP state structure */
|
||||
|
||||
(void)sem_init(&state.tc_sem, 0, 0); /* Doesn't really fail */
|
||||
state.tc_conn = conn;
|
||||
state.tc_result = -EAGAIN;
|
||||
|
||||
/* Set up the callbacks in the connection */
|
||||
|
||||
tcp_setup_callbacks(conn, psock, &state);
|
||||
|
||||
/* Wait for either the connect to complete or for an error/timeout to occur.
|
||||
* NOTES: (1) sem_wait will also terminate if a signal is received, (2)
|
||||
* interrupts are disabled! They will be re-enabled while the task sleeps
|
||||
* and automatically re-enabled when the task restarts.
|
||||
*/
|
||||
|
||||
ret = sem_wait(&state.tc_sem);
|
||||
|
||||
/* Uninitialize the state structure */
|
||||
|
||||
(void)sem_destroy(&state.tc_sem);
|
||||
|
||||
/* If sem_wait failed, recover the negated error (probably -EINTR) */
|
||||
|
||||
if (ret < 0)
|
||||
ret = tcp_setup_callbacks(psock, &state);
|
||||
if (ret >= 0)
|
||||
{
|
||||
int err = *get_errno_ptr();
|
||||
if (err >= 0)
|
||||
/* Wait for either the connect to complete or for an error/timeout
|
||||
* to occur. NOTES: (1) sem_wait will also terminate if a signal
|
||||
* is received, (2) interrupts are disabled! They will be re-
|
||||
* enabled while the task sleeps and automatically re-disabled
|
||||
* when the task restarts.
|
||||
*/
|
||||
|
||||
ret = sem_wait(&state.tc_sem);
|
||||
|
||||
/* Uninitialize the state structure */
|
||||
|
||||
(void)sem_destroy(&state.tc_sem);
|
||||
|
||||
/* If sem_wait failed, recover the negated error (probably -EINTR) */
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
err = ENOSYS;
|
||||
int err = errno;
|
||||
if (err >= 0)
|
||||
{
|
||||
err = ENOSYS;
|
||||
}
|
||||
ret = -err;
|
||||
}
|
||||
ret = -err;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If the wait succeeded, then get the new error value from the state structure */
|
||||
else
|
||||
{
|
||||
/* If the wait succeeded, then get the new error value from
|
||||
* the state structure
|
||||
*/
|
||||
|
||||
ret = state.tc_result;
|
||||
}
|
||||
ret = state.tc_result;
|
||||
}
|
||||
|
||||
/* Make sure that no further interrupts are processed */
|
||||
tcp_teardown_callbacks(conn, ret);
|
||||
/* Make sure that no further interrupts are processed */
|
||||
|
||||
tcp_teardown_callbacks(&state, ret);
|
||||
}
|
||||
|
||||
/* Mark the connection bound and connected */
|
||||
|
||||
if (ret >= 0)
|
||||
{
|
||||
psock->s_flags |= (_SF_BOUND|_SF_CONNECTED);
|
||||
}
|
||||
}
|
||||
|
||||
irqrestore(flags);
|
||||
return ret;
|
||||
}
|
||||
|
@ -543,7 +560,7 @@ int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
|
|||
return OK;
|
||||
|
||||
errout:
|
||||
*get_errno_ptr() = err;
|
||||
errno = err;
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
#include <net/uip/uip-arch.h>
|
||||
|
||||
#include "net-internal.h"
|
||||
#include "uip/uip-internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
|
@ -58,8 +59,9 @@
|
|||
#ifdef CONFIG_NET_TCP
|
||||
struct tcp_close_s
|
||||
{
|
||||
FAR struct socket *cl_psock; /* Reference to the TCP socket */
|
||||
sem_t cl_sem; /* Semaphore signals disconnect completion */
|
||||
FAR struct socket *cl_psock; /* Reference to the TCP socket */
|
||||
FAR struct uip_callback_s *cl_cb; /* Reference to TCP callback instance */
|
||||
sem_t cl_sem; /* Semaphore signals disconnect completion */
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -85,12 +87,12 @@ struct tcp_close_s
|
|||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_TCP
|
||||
static uint8 netclose_interrupt(struct uip_driver_s *dev,
|
||||
struct uip_conn *conn, uint8 flags)
|
||||
static uint16 netclose_interrupt(struct uip_driver_s *dev, void *pvconn,
|
||||
void *pvprivate, uint16 flags)
|
||||
{
|
||||
struct tcp_close_s *pstate = (struct tcp_close_s *)conn->data_private;
|
||||
struct tcp_close_s *pstate = (struct tcp_close_s *)pvprivate;
|
||||
|
||||
nvdbg("flags: %02x\n", flags);
|
||||
nvdbg("flags: %04x\n", flags);
|
||||
|
||||
if (pstate)
|
||||
{
|
||||
|
@ -102,9 +104,9 @@ static uint8 netclose_interrupt(struct uip_driver_s *dev,
|
|||
{
|
||||
/* The disconnection is complete */
|
||||
|
||||
conn->data_flags = 0;
|
||||
conn->data_private = NULL;
|
||||
conn->data_event = NULL;
|
||||
pstate->cl_cb->flags = 0;
|
||||
pstate->cl_cb->private = NULL;
|
||||
pstate->cl_cb->event = NULL;
|
||||
sem_post(&pstate->cl_sem);
|
||||
nvdbg("Resuming\n");
|
||||
}
|
||||
|
@ -144,7 +146,6 @@ static uint8 netclose_interrupt(struct uip_driver_s *dev,
|
|||
static inline void netclose_disconnect(FAR struct socket *psock)
|
||||
{
|
||||
struct tcp_close_s state;
|
||||
struct uip_conn *conn;
|
||||
irqstate_t flags;
|
||||
|
||||
/* Interrupts are disabled here to avoid race conditions */
|
||||
|
@ -155,30 +156,33 @@ static inline void netclose_disconnect(FAR struct socket *psock)
|
|||
|
||||
if (_SS_ISCONNECTED(psock->s_flags))
|
||||
{
|
||||
/* Set up to receive TCP data events */
|
||||
struct uip_conn *conn = (struct uip_conn*)psock->s_conn;
|
||||
|
||||
state.cl_psock = psock;
|
||||
sem_init(&state.cl_sem, 0, 0);
|
||||
/* Set up to receive TCP data event callbacks */
|
||||
|
||||
conn = psock->s_conn;
|
||||
conn->data_flags = UIP_NEWDATA|UIP_CLOSE|UIP_ABORT;
|
||||
conn->data_private = (void*)&state;
|
||||
conn->data_event = netclose_interrupt;
|
||||
state.cl_cb = uip_tcpcallbackalloc(conn);
|
||||
if (state.cl_cb)
|
||||
{
|
||||
state.cl_psock = psock;
|
||||
sem_init(&state.cl_sem, 0, 0);
|
||||
|
||||
/* Notify the device driver of the availaibilty of TX data */
|
||||
state.cl_cb->flags = UIP_NEWDATA|UIP_POLL|UIP_CLOSE|UIP_ABORT;
|
||||
state.cl_cb->private = (void*)&state;
|
||||
state.cl_cb->event = netclose_interrupt;
|
||||
|
||||
netdev_txnotify(&conn->ripaddr);
|
||||
/* Notify the device driver of the availaibilty of TX data */
|
||||
|
||||
/* Wait for the disconnect event */
|
||||
netdev_txnotify(&conn->ripaddr);
|
||||
|
||||
(void)sem_wait(&state.cl_sem);
|
||||
/* Wait for the disconnect event */
|
||||
|
||||
/* We are now disconnected */
|
||||
(void)sem_wait(&state.cl_sem);
|
||||
|
||||
sem_destroy(&state.cl_sem);
|
||||
conn->data_flags = 0;
|
||||
conn->data_private = NULL;
|
||||
conn->data_event = NULL;
|
||||
/* We are now disconnected */
|
||||
|
||||
sem_destroy(&state.cl_sem);
|
||||
uip_tcpcallbackfree(conn, state.cl_cb);
|
||||
}
|
||||
}
|
||||
|
||||
irqrestore(flags);
|
||||
|
|
167
net/recvfrom.c
167
net/recvfrom.c
|
@ -52,6 +52,7 @@
|
|||
#include <net/uip/uip-arch.h>
|
||||
|
||||
#include "net-internal.h"
|
||||
#include "uip/uip-internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Definitions
|
||||
|
@ -70,19 +71,20 @@
|
|||
struct recvfrom_s
|
||||
{
|
||||
#if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK)
|
||||
FAR struct socket *rf_sock; /* The parent socket structure */
|
||||
uint32 rf_starttime; /* rcv start time for determining timeout */
|
||||
FAR struct socket *rf_sock; /* The parent socket structure */
|
||||
uint32 rf_starttime; /* rcv start time for determining timeout */
|
||||
#endif
|
||||
sem_t rf_sem; /* Semaphore signals recv completion */
|
||||
size_t rf_buflen; /* Length of receive buffer */
|
||||
char *rf_buffer; /* Pointer to receive buffer */
|
||||
FAR struct uip_callback_s *rf_cb; /* Reference to callback instance */
|
||||
sem_t rf_sem; /* Semaphore signals recv completion */
|
||||
size_t rf_buflen; /* Length of receive buffer */
|
||||
char *rf_buffer; /* Pointer to receive buffer */
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
FAR struct sockaddr_in6 *rf_from; /* Address of sender */
|
||||
FAR struct sockaddr_in6 *rf_from; /* Address of sender */
|
||||
#else
|
||||
FAR struct sockaddr_in *rf_from; /* Address of sender */
|
||||
FAR struct sockaddr_in *rf_from; /* Address of sender */
|
||||
#endif
|
||||
size_t rf_recvlen; /* The received length */
|
||||
int rf_result; /* OK:success, failure:negated errno */
|
||||
size_t rf_recvlen; /* The received length */
|
||||
int rf_result; /* OK:success, failure:negated errno */
|
||||
};
|
||||
#endif /* CONFIG_NET_UDP || CONFIG_NET_TCP */
|
||||
|
||||
|
@ -356,12 +358,12 @@ static inline void recvfrom_tcpsender(struct uip_driver_s *dev, struct recvfrom_
|
|||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_TCP
|
||||
static uint8 recvfrom_tcpinterrupt(struct uip_driver_s *dev,
|
||||
struct uip_conn *conn, uint8 flags)
|
||||
static uint16 recvfrom_tcpinterrupt(struct uip_driver_s *dev, void *conn,
|
||||
void *pvprivate, uint16 flags)
|
||||
{
|
||||
struct recvfrom_s *pstate = (struct recvfrom_s *)conn->data_private;
|
||||
struct recvfrom_s *pstate = (struct recvfrom_s *)pvprivate;
|
||||
|
||||
nvdbg("flags: %02x\n", flags);
|
||||
nvdbg("flags: %04x\n", flags);
|
||||
|
||||
/* 'private' might be null in some race conditions (?) */
|
||||
|
||||
|
@ -379,6 +381,12 @@ static uint8 recvfrom_tcpinterrupt(struct uip_driver_s *dev,
|
|||
|
||||
recvfrom_tcpsender(dev, pstate);
|
||||
|
||||
/* Indicate that the data has been consumed and that an ACK
|
||||
* should be sent.
|
||||
*/
|
||||
|
||||
flags = (flags & ~UIP_NEWDATA) | UIP_SNDACK;
|
||||
|
||||
/* If the user buffer has been filled, then we are finished. */
|
||||
|
||||
if (pstate->rf_buflen == 0)
|
||||
|
@ -391,9 +399,9 @@ static uint8 recvfrom_tcpinterrupt(struct uip_driver_s *dev,
|
|||
* Don't allow any further TCP call backs.
|
||||
*/
|
||||
|
||||
conn->data_flags = 0;
|
||||
conn->data_private = NULL;
|
||||
conn->data_event = NULL;
|
||||
pstate->rf_cb->flags = 0;
|
||||
pstate->rf_cb->private = NULL;
|
||||
pstate->rf_cb->event = NULL;
|
||||
|
||||
/* Wake up the waiting thread, returning the number of bytes
|
||||
* actually read.
|
||||
|
@ -419,9 +427,9 @@ static uint8 recvfrom_tcpinterrupt(struct uip_driver_s *dev,
|
|||
|
||||
/* Stop further callbacks */
|
||||
|
||||
conn->data_flags = 0;
|
||||
conn->data_private = NULL;
|
||||
conn->data_event = NULL;
|
||||
pstate->rf_cb->flags = 0;
|
||||
pstate->rf_cb->private = NULL;
|
||||
pstate->rf_cb->event = NULL;
|
||||
|
||||
/* Report not connected */
|
||||
|
||||
|
@ -445,9 +453,9 @@ static uint8 recvfrom_tcpinterrupt(struct uip_driver_s *dev,
|
|||
|
||||
nvdbg("TCP timeout\n");
|
||||
|
||||
conn->data_flags = 0;
|
||||
conn->data_private = NULL;
|
||||
conn->data_event = NULL;
|
||||
pstate->rf_cb->flags = 0;
|
||||
pstate->rf_cb->private = NULL;
|
||||
pstate->rf_cb->event = NULL;
|
||||
|
||||
/* Report an error only if no data has been received */
|
||||
|
||||
|
@ -533,12 +541,13 @@ static inline void recvfrom_udpsender(struct uip_driver_s *dev, struct recvfrom_
|
|||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_UDP
|
||||
static void recvfrom_udpinterrupt(struct uip_driver_s *dev,
|
||||
struct uip_udp_conn *conn, uint8 flags)
|
||||
static uint16 recvfrom_udpinterrupt(struct uip_driver_s *dev, void *pvconn,
|
||||
void *pvprivate, uint16 flags)
|
||||
{
|
||||
struct recvfrom_s *pstate = (struct recvfrom_s *)conn->private;
|
||||
struct uip_udp_conn *conn = (struct uip_udp_conn *)pvconn;
|
||||
struct recvfrom_s *pstate = (struct recvfrom_s *)pvprivate;
|
||||
|
||||
nvdbg("flags: %02x\n", flags);
|
||||
nvdbg("flags: %04x\n", flags);
|
||||
|
||||
/* 'private' might be null in some race conditions (?) */
|
||||
|
||||
|
@ -558,14 +567,19 @@ static void recvfrom_udpinterrupt(struct uip_driver_s *dev,
|
|||
|
||||
/* Don't allow any further UDP call backs. */
|
||||
|
||||
conn->private = NULL;
|
||||
conn->event = NULL;
|
||||
pstate->rf_cb->flags = 0;
|
||||
pstate->rf_cb->private = NULL;
|
||||
pstate->rf_cb->event = NULL;
|
||||
|
||||
/* Save the sender's address in the caller's 'from' location */
|
||||
|
||||
recvfrom_udpsender(dev, pstate);
|
||||
|
||||
/* Wake up the waiting thread, returning the number of bytes
|
||||
/* Indicate that the data has been consumed */
|
||||
|
||||
flags &= ~UIP_NEWDATA;
|
||||
|
||||
/* Wake up the waiting thread, returning the number of bytes
|
||||
* actually read.
|
||||
*/
|
||||
|
||||
|
@ -580,8 +594,9 @@ static void recvfrom_udpinterrupt(struct uip_driver_s *dev,
|
|||
|
||||
/* Stop further callbacks */
|
||||
|
||||
conn->private = NULL;
|
||||
conn->event = NULL;
|
||||
pstate->rf_cb->flags = 0;
|
||||
pstate->rf_cb->private = NULL;
|
||||
pstate->rf_cb->event = NULL;
|
||||
|
||||
/* Report not connected */
|
||||
|
||||
|
@ -607,8 +622,9 @@ static void recvfrom_udpinterrupt(struct uip_driver_s *dev,
|
|||
|
||||
/* Stop further callbacks */
|
||||
|
||||
conn->private = NULL;
|
||||
conn->event = NULL;
|
||||
pstate->rf_cb->flags = 0;
|
||||
pstate->rf_cb->private = NULL;
|
||||
pstate->rf_cb->event = NULL;
|
||||
|
||||
/* Report a timeout error */
|
||||
|
||||
|
@ -620,6 +636,7 @@ static void recvfrom_udpinterrupt(struct uip_driver_s *dev,
|
|||
}
|
||||
#endif /* CONFIG_NET_SOCKOPTS && !CONFIG_DISABLE_CLOCK */
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
#endif /* CONFIG_NET_UDP */
|
||||
|
||||
|
@ -773,29 +790,40 @@ static ssize_t udp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
|
|||
|
||||
/* Set up the callback in the connection */
|
||||
|
||||
udp_conn->private = (void*)&state;
|
||||
udp_conn->event = recvfrom_udpinterrupt;
|
||||
state.rf_cb = uip_udpcallbackalloc(psock->s_conn);
|
||||
if (state.rf_cb)
|
||||
{
|
||||
/* Set up the callback in the connection */
|
||||
|
||||
/* Enable the UDP socket */
|
||||
state.rf_cb->flags = UIP_NEWDATA|UIP_POLL|UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT;
|
||||
state.rf_cb->private = (void*)&state;
|
||||
state.rf_cb->event = recvfrom_udpinterrupt;
|
||||
|
||||
uip_udpenable(udp_conn);
|
||||
/* Enable the UDP socket */
|
||||
|
||||
/* Wait for either the receive to complete or for an error/timeout to occur.
|
||||
* NOTES: (1) sem_wait will also terminate if a signal is received, (2)
|
||||
* interrupts are disabled! They will be re-enabled while the task sleeps
|
||||
* and automatically re-enabled when the task restarts.
|
||||
*/
|
||||
uip_udpenable(udp_conn);
|
||||
|
||||
ret = sem_wait(&state. rf_sem);
|
||||
/* Wait for either the receive to complete or for an error/timeout to occur.
|
||||
* NOTES: (1) sem_wait will also terminate if a signal is received, (2)
|
||||
* interrupts are disabled! They will be re-enabled while the task sleeps
|
||||
* and automatically re-enabled when the task restarts.
|
||||
*/
|
||||
|
||||
/* Make sure that no further interrupts are processed */
|
||||
ret = sem_wait(&state. rf_sem);
|
||||
|
||||
uip_udpdisable(udp_conn);
|
||||
udp_conn->private = NULL;
|
||||
udp_conn->event = NULL;
|
||||
irqrestore(save);
|
||||
/* Make sure that no further interrupts are processed */
|
||||
|
||||
return recvfrom_result(ret, &state);
|
||||
uip_udpdisable(udp_conn);
|
||||
uip_udpcallbackfree(psock->s_conn, state.rf_cb);
|
||||
irqrestore(save);
|
||||
ret = recvfrom_result(ret, &state);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = -EBUSY;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_NET_UDP */
|
||||
|
||||
|
@ -828,7 +856,6 @@ static ssize_t tcp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
|
|||
FAR struct sockaddr_in *infrom )
|
||||
#endif
|
||||
{
|
||||
struct uip_conn *conn;
|
||||
struct recvfrom_s state;
|
||||
irqstate_t save;
|
||||
int ret = OK;
|
||||
|
@ -864,30 +891,38 @@ static ssize_t tcp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
|
|||
if (state.rf_buflen > 0)
|
||||
#endif
|
||||
{
|
||||
struct uip_conn *conn = (struct uip_conn *)psock->s_conn;
|
||||
|
||||
/* Set up the callback in the connection */
|
||||
|
||||
conn = (struct uip_conn *)psock->s_conn;
|
||||
conn->data_flags = UIP_NEWDATA|UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT;
|
||||
conn->data_private = (void*)&state;
|
||||
conn->data_event = recvfrom_tcpinterrupt;
|
||||
state.rf_cb = uip_tcpcallbackalloc(conn);
|
||||
if (state.rf_cb)
|
||||
{
|
||||
state.rf_cb->flags = UIP_NEWDATA|UIP_POLL|UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT;
|
||||
state.rf_cb->private = (void*)&state;
|
||||
state.rf_cb->event = recvfrom_tcpinterrupt;
|
||||
|
||||
/* Wait for either the receive to complete or for an error/timeout to occur.
|
||||
* NOTES: (1) sem_wait will also terminate if a signal is received, (2)
|
||||
* interrupts are disabled! They will be re-enabled while the task sleeps
|
||||
* and automatically re-enabled when the task restarts.
|
||||
*/
|
||||
/* Wait for either the receive to complete or for an error/timeout to occur.
|
||||
* NOTES: (1) sem_wait will also terminate if a signal is received, (2)
|
||||
* interrupts are disabled! They will be re-enabled while the task sleeps
|
||||
* and automatically re-enabled when the task restarts.
|
||||
*/
|
||||
|
||||
ret = sem_wait(&state.rf_sem);
|
||||
ret = sem_wait(&state.rf_sem);
|
||||
|
||||
/* Make sure that no further interrupts are processed */
|
||||
/* Make sure that no further interrupts are processed */
|
||||
|
||||
conn->data_flags = 0;
|
||||
conn->data_private = NULL;
|
||||
conn->data_event = NULL;
|
||||
uip_tcpcallbackfree(conn, state.rf_cb);
|
||||
ret = recvfrom_result(ret, &state);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = -EBUSY;
|
||||
}
|
||||
}
|
||||
irqrestore(save);
|
||||
|
||||
return recvfrom_result(ret, &state);
|
||||
irqrestore(save);
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_NET_TCP */
|
||||
|
||||
|
|
77
net/send.c
77
net/send.c
|
@ -51,6 +51,7 @@
|
|||
#include <net/uip/uip-arch.h>
|
||||
|
||||
#include "net-internal.h"
|
||||
#include "uip/uip-internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Definitions
|
||||
|
@ -68,15 +69,16 @@
|
|||
|
||||
struct send_s
|
||||
{
|
||||
FAR struct socket *snd_sock; /* Points to the parent socket structure */
|
||||
sem_t snd_sem; /* Used to wake up the waiting thread */
|
||||
FAR const uint8 *snd_buffer; /* Points to the buffer of data to send */
|
||||
size_t snd_buflen; /* Number of bytes in the buffer to send */
|
||||
ssize_t snd_sent; /* The number of bytes sent */
|
||||
uint32 snd_isn; /* Initial sequence number */
|
||||
uint32 snd_acked; /* The number of bytes acked */
|
||||
FAR struct socket *snd_sock; /* Points to the parent socket structure */
|
||||
FAR struct uip_callback_s *snd_cb; /* Reference to callback instance */
|
||||
sem_t snd_sem; /* Used to wake up the waiting thread */
|
||||
FAR const uint8 *snd_buffer; /* Points to the buffer of data to send */
|
||||
size_t snd_buflen; /* Number of bytes in the buffer to send */
|
||||
ssize_t snd_sent; /* The number of bytes sent */
|
||||
uint32 snd_isn; /* Initial sequence number */
|
||||
uint32 snd_acked; /* The number of bytes acked */
|
||||
#if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK)
|
||||
uint32 snd_time; /* last send time for determining timeout */
|
||||
uint32 snd_time; /* last send time for determining timeout */
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -192,12 +194,13 @@ static inline int send_timeout(struct send_s *pstate)
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
static uint8 send_interrupt(struct uip_driver_s *dev, struct uip_conn *conn,
|
||||
uint8 flags)
|
||||
static uint16 send_interrupt(struct uip_driver_s *dev, void *pvconn,
|
||||
void *pvprivate, uint16 flags)
|
||||
{
|
||||
struct send_s *pstate = (struct send_s *)conn->data_private;
|
||||
struct uip_conn *conn = (struct uip_conn*)pvconn;
|
||||
struct send_s *pstate = (struct send_s *)pvprivate;
|
||||
|
||||
nvdbg("flags: %02x acked: %d sent: %d\n", flags, pstate->snd_acked, pstate->snd_sent);
|
||||
nvdbg("flags: %04x acked: %d sent: %d\n", flags, pstate->snd_acked, pstate->snd_sent);
|
||||
|
||||
/* If this packet contains an acknowledgement, then update the count of
|
||||
* acknowldged bytes.
|
||||
|
@ -301,9 +304,9 @@ static uint8 send_interrupt(struct uip_driver_s *dev, struct uip_conn *conn,
|
|||
end_wait:
|
||||
/* Do not allow any further callbacks */
|
||||
|
||||
conn->data_flags = 0;
|
||||
conn->data_private = NULL;
|
||||
conn->data_event = NULL;
|
||||
pstate->snd_cb->flags = 0;
|
||||
pstate->snd_cb->private = NULL;
|
||||
pstate->snd_cb->event = NULL;
|
||||
|
||||
/* Wake up the waiting thread */
|
||||
|
||||
|
@ -382,7 +385,6 @@ end_wait:
|
|||
ssize_t send(int sockfd, const void *buf, size_t len, int flags)
|
||||
{
|
||||
FAR struct socket *psock = sockfd_socket(sockfd);
|
||||
struct uip_conn *conn;
|
||||
struct send_s state;
|
||||
irqstate_t save;
|
||||
int err;
|
||||
|
@ -424,34 +426,39 @@ ssize_t send(int sockfd, const void *buf, size_t len, int flags)
|
|||
|
||||
if (len > 0)
|
||||
{
|
||||
/* Get the initial sequence number that will be used */
|
||||
struct uip_conn *conn = (struct uip_conn*)psock->s_conn;
|
||||
|
||||
conn = (struct uip_conn *)psock->s_conn;
|
||||
state.snd_isn = send_getisn(conn); /* Initial sequence number */
|
||||
/* Allocate resources to receive a callback */
|
||||
|
||||
/* Set up the callback in the connection */
|
||||
state.snd_cb = uip_tcpcallbackalloc(conn);
|
||||
if (state.snd_cb)
|
||||
{
|
||||
/* Get the initial sequence number that will be used */
|
||||
|
||||
conn->data_flags = UIP_REXMIT|UIP_ACKDATA|UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT;
|
||||
conn->data_private = (void*)&state;
|
||||
conn->data_event = send_interrupt;
|
||||
state.snd_isn = send_getisn(conn); /* Initial sequence number */
|
||||
|
||||
/* Notify the device driver of the availaibilty of TX data */
|
||||
/* Set up the callback in the connection */
|
||||
|
||||
netdev_txnotify(&conn->ripaddr);
|
||||
state.snd_cb->flags = UIP_ACKDATA|UIP_REXMIT|UIP_POLL|UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT;
|
||||
state.snd_cb->private = (void*)&state;
|
||||
state.snd_cb->event = send_interrupt;
|
||||
|
||||
/* Wait for the send to complete or an error to occur: NOTES: (1)
|
||||
* sem_wait will also terminate if a signal is received, (2) interrupts
|
||||
* are disabled! They will be re-enabled while the task sleeps and
|
||||
* automatically re-enabled when the task restarts.
|
||||
*/
|
||||
/* Notify the device driver of the availaibilty of TX data */
|
||||
|
||||
ret = sem_wait(&state. snd_sem);
|
||||
netdev_txnotify(&conn->ripaddr);
|
||||
|
||||
/* Make sure that no further interrupts are processed */
|
||||
/* Wait for the send to complete or an error to occur: NOTES: (1)
|
||||
* sem_wait will also terminate if a signal is received, (2) interrupts
|
||||
* are disabled! They will be re-enabled while the task sleeps and
|
||||
* automatically re-enabled when the task restarts.
|
||||
*/
|
||||
|
||||
conn->data_flags = 0;
|
||||
conn->data_private = NULL;
|
||||
conn->data_event = NULL;
|
||||
ret = sem_wait(&state. snd_sem);
|
||||
|
||||
/* Make sure that no further interrupts are processed */
|
||||
|
||||
uip_tcpcallbackfree(conn, state.snd_cb);
|
||||
}
|
||||
}
|
||||
|
||||
sem_destroy(&state. snd_sem);
|
||||
|
|
25
net/sendto.c
25
net/sendto.c
|
@ -60,6 +60,7 @@
|
|||
|
||||
struct sendto_s
|
||||
{
|
||||
FAR struct uip_callback_s *snd_cb; /* Reference to callback instance */
|
||||
sem_t st_sem; /* Semaphore signals sendto completion */
|
||||
uint16 st_buflen; /* Length of send buffer (error if <0) */
|
||||
const char *st_buffer; /* Pointer to send buffer */
|
||||
|
@ -95,7 +96,7 @@ void sendto_interrupt(struct uip_driver_s *dev, struct uip_udp_conn *conn, uint8
|
|||
{
|
||||
struct sendto_s *pstate = (struct sendto_s *)conn->private;
|
||||
|
||||
nvdbg("flags: %02x\n");
|
||||
nvdbg("flags: %04x\n", flags);
|
||||
if (pstate)
|
||||
{
|
||||
/* Check if the connection was rejected */
|
||||
|
@ -116,8 +117,9 @@ void sendto_interrupt(struct uip_driver_s *dev, struct uip_udp_conn *conn, uint8
|
|||
|
||||
/* Don't allow any further call backs. */
|
||||
|
||||
conn->private = NULL;
|
||||
conn->event = NULL;
|
||||
pstate->st_cb->flags = 0;
|
||||
pstate->st_cb->private = NULL;
|
||||
pstate->st_cb->event = NULL;
|
||||
|
||||
/* Wake up the waiting thread */
|
||||
|
||||
|
@ -205,7 +207,6 @@ ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
|
|||
#else
|
||||
FAR const struct sockaddr_in *into = (const struct sockaddr_in *)to;
|
||||
#endif
|
||||
struct uip_udp_conn *udp_conn;
|
||||
struct sendto_s state;
|
||||
irqstate_t save;
|
||||
int ret;
|
||||
|
@ -286,9 +287,13 @@ ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
|
|||
|
||||
/* Set up the callback in the connection */
|
||||
|
||||
udp_conn = (struct uip_udp_conn *)psock->s_conn;
|
||||
udp_conn->private = (void*)&state;
|
||||
udp_conn->event = sendto_interrupt;
|
||||
state.st_cb = uip_udpcallbackalloc((struct uip_udp_conn *)psock->s_conn);
|
||||
if (state.st_cb)
|
||||
{
|
||||
state.st_cb->flags = UIP_POLL|UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT;
|
||||
state.st_cb->flags = 0;
|
||||
state.st_cb->private = (void*)&state;
|
||||
state.st_cb->event = sendto_interrupt;
|
||||
|
||||
/* Enable the UDP socket */
|
||||
|
||||
|
@ -309,8 +314,8 @@ ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
|
|||
/* Make sure that no further interrupts are processed */
|
||||
|
||||
uip_udpdisable(psock->s_conn);
|
||||
udp_conn->private = NULL;
|
||||
udp_conn->event = NULL;
|
||||
uip_udpcallbackfree(psock->s_conn, state.st_cb);
|
||||
}
|
||||
irqrestore(save);
|
||||
|
||||
sem_destroy(&state.st_sem);
|
||||
|
@ -335,7 +340,7 @@ ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
|
|||
#endif
|
||||
|
||||
errout:
|
||||
*get_errno_ptr() = err;
|
||||
errno = err;
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ ifeq ($(CONFIG_NET),y)
|
|||
# Common IP source files
|
||||
|
||||
UIP_CSRCS += uip-initialize.c uip-setipid.c uip-arp.c uip-input.c uip-send.c \
|
||||
uip-poll.c uip-chksum.c
|
||||
uip-poll.c uip-chksum.c uip-callback.c
|
||||
|
||||
ifeq ($(CONFIG_NET_IPv6),y)
|
||||
UIP_CSRCS += uip-neighbor.c
|
||||
|
|
252
net/uip/uip-callback.c
Normal file
252
net/uip/uip-callback.c
Normal file
|
@ -0,0 +1,252 @@
|
|||
/****************************************************************************
|
||||
* net/uip/uip-callback.c
|
||||
*
|
||||
* Copyright (C) 2008 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
*
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#if defined(CONFIG_NET)
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <net/uip/uipopt.h>
|
||||
#include <net/uip/uip.h>
|
||||
#include <net/uip/uip-arch.h>
|
||||
|
||||
#include "uip-internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static struct uip_callback_s g_cbprealloc[CONFIG_NET_NACTIVESOCKETS];
|
||||
static FAR struct uip_callback_s *g_cbfreelist = NULL;
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Function: uip_callbackinit
|
||||
*
|
||||
* Description:
|
||||
* Configure the pre-allocated callaback structures into a free list.
|
||||
* This is called internally as part of uIP initialization and should not
|
||||
* be accessed from the application or socket layer.
|
||||
*
|
||||
* Assumptions:
|
||||
* This function is called with interrupts disabled.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void uip_callbackinit(void)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < CONFIG_NET_NACTIVESOCKETS; i++)
|
||||
{
|
||||
g_cbprealloc[i].flink = g_cbfreelist;
|
||||
g_cbfreelist = &g_cbprealloc[i];
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Function: uip_callbackalloc
|
||||
*
|
||||
* Description:
|
||||
* Allocate a callback container from the free list.
|
||||
* This is called internally as part of uIP initialization and should not
|
||||
* be accessed from the application or socket layer.
|
||||
*
|
||||
* Assumptions:
|
||||
* This function is called with interrupts disabled.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR struct uip_callback_s *uip_callbackalloc(FAR struct uip_callback_s **list)
|
||||
{
|
||||
struct uip_callback_s *ret;
|
||||
irqstate_t save;
|
||||
|
||||
/* Check the head of the free list */
|
||||
|
||||
save = irqsave();
|
||||
ret = g_cbfreelist;
|
||||
if (ret)
|
||||
{
|
||||
/* Remove the next instance from the head of the free list */
|
||||
|
||||
g_cbfreelist = ret->flink;
|
||||
memset(ret, 0, sizeof(struct uip_callback_s));
|
||||
|
||||
/* Add the newly allocated instance to the head of the specified list */
|
||||
|
||||
if (list)
|
||||
{
|
||||
ret->flink = *list;
|
||||
*list = ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret->flink = NULL;
|
||||
}
|
||||
}
|
||||
#ifdef CONFIG_DEBUG
|
||||
else
|
||||
{
|
||||
dbg("Failed to allocate callback\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
irqrestore(save);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Function: uip_callbackfree
|
||||
*
|
||||
* Description:
|
||||
* Return a callback container to the free list.
|
||||
* This is called internally as part of uIP initialization and should not
|
||||
* be accessed from the application or socket layer.
|
||||
*
|
||||
* Assumptions:
|
||||
* This function is called with interrupts disabled.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void uip_callbackfree(FAR struct uip_callback_s *cb, FAR struct uip_callback_s **list)
|
||||
{
|
||||
FAR struct uip_callback_s *prev;
|
||||
FAR struct uip_callback_s *curr;
|
||||
irqstate_t save;
|
||||
|
||||
if (cb)
|
||||
{
|
||||
/* Find the callback structure in the connection's list */
|
||||
|
||||
save = irqsave();
|
||||
if (list)
|
||||
{
|
||||
for (prev = NULL, curr = *list;
|
||||
curr && curr != cb;
|
||||
prev = curr, curr = curr->flink);
|
||||
|
||||
/* Remove the structure from the connection's list */
|
||||
|
||||
if (curr)
|
||||
{
|
||||
if (prev)
|
||||
{
|
||||
prev->flink = cb->flink;
|
||||
}
|
||||
else
|
||||
{
|
||||
*list = cb->flink;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Put the structure into the free list */
|
||||
|
||||
cb->flink = g_cbfreelist;
|
||||
g_cbfreelist = cb;
|
||||
irqrestore(save);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Function: uip_callbackexecute
|
||||
*
|
||||
* Description:
|
||||
* Execute a list of callbacks.
|
||||
* This is called internally as part of uIP initialization and should not
|
||||
* be accessed from the application or socket layer.
|
||||
*
|
||||
* Assumptions:
|
||||
* This function is called with interrupts disabled.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
uint16 uip_callbackexecute(FAR struct uip_driver_s *dev, void *pvconn, uint16 flags,
|
||||
FAR struct uip_callback_s *list)
|
||||
{
|
||||
FAR struct uip_callback_s *next;
|
||||
irqstate_t save;
|
||||
|
||||
/* Loop for each callback in the list and while there are still events
|
||||
* set in the flags set.
|
||||
*/
|
||||
|
||||
save = irqsave();
|
||||
while (list && flags)
|
||||
{
|
||||
/* Save the pointer to the next callback in the lists. This is done
|
||||
* because the callback action might delete the entry pointed to by
|
||||
* list.
|
||||
*/
|
||||
|
||||
next = list->flink;
|
||||
|
||||
/* Check if this callback handles any of the events in the flag set */
|
||||
|
||||
if (list->event && (flags & list->flags) != 0)
|
||||
{
|
||||
/* Yes.. perform the callback. Actions perform by the callback
|
||||
* may delete the current list entry or add a new list entry to
|
||||
* beginning of the list (which will be ignored on this pass)
|
||||
*/
|
||||
|
||||
vdbg("Call event=%p with flags=%04x\n", list->event, flags);
|
||||
flags = list->event(dev, pvconn, list->private, flags);
|
||||
}
|
||||
|
||||
/* Set up for the next time through the loop */
|
||||
|
||||
list = next;
|
||||
}
|
||||
|
||||
irqrestore(save);
|
||||
return flags;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NET */
|
|
@ -1,7 +1,7 @@
|
|||
/****************************************************************************
|
||||
* net/uip/uip-initialize.c
|
||||
*
|
||||
* Copyright (C) 2007 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
*
|
||||
* Adapted for NuttX from logic in uIP which also has a BSD-like license:
|
||||
|
@ -114,6 +114,10 @@ uint8 uip_reasstmr;
|
|||
|
||||
void uip_initialize(void)
|
||||
{
|
||||
/* Initialize callback support */
|
||||
|
||||
uip_callbackinit();
|
||||
|
||||
/* Initialize the listening port structures */
|
||||
|
||||
#ifdef CONFIG_NET_TCP
|
||||
|
|
|
@ -118,6 +118,14 @@ extern "C" {
|
|||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
/* Defined in uip_callback.c ************************************************/
|
||||
|
||||
EXTERN void uip_callbackinit(void);
|
||||
EXTERN FAR struct uip_callback_s *uip_callbackalloc(struct uip_callback_s **list);
|
||||
EXTERN void uip_callbackfree(FAR struct uip_callback_s *cb, struct uip_callback_s **list);
|
||||
EXTERN uint16 uip_callbackexecute(FAR struct uip_driver_s *dev, void *pvconn,
|
||||
uint16 flags, FAR struct uip_callback_s *list);
|
||||
|
||||
#ifdef CONFIG_NET_TCP
|
||||
/* Defined in uip_tcpconn.c *************************************************/
|
||||
|
||||
|
@ -145,7 +153,7 @@ EXTERN int uip_accept(struct uip_conn *conn, uint16 portno);
|
|||
/* Defined in uip-tcpsend.c *************************************************/
|
||||
|
||||
EXTERN void uip_tcpsend(struct uip_driver_s *dev, struct uip_conn *conn,
|
||||
uint8 flags, uint16 len);
|
||||
uint16 flags, uint16 len);
|
||||
EXTERN void uip_tcpreset(struct uip_driver_s *dev);
|
||||
EXTERN void uip_tcpack(struct uip_driver_s *dev, struct uip_conn *conn,
|
||||
uint8 ack);
|
||||
|
@ -153,9 +161,9 @@ EXTERN void uip_tcpack(struct uip_driver_s *dev, struct uip_conn *conn,
|
|||
/* Defined in uip-tcpappsend.c **********************************************/
|
||||
|
||||
EXTERN void uip_tcpappsend(struct uip_driver_s *dev, struct uip_conn *conn,
|
||||
uint8 result);
|
||||
uint16 result);
|
||||
EXTERN void uip_tcprexmit(struct uip_driver_s *dev, struct uip_conn *conn,
|
||||
uint8 result);
|
||||
uint16 result);
|
||||
|
||||
/* Defined in uip-tcpinput.c ************************************************/
|
||||
|
||||
|
@ -163,8 +171,8 @@ EXTERN void uip_tcpinput(struct uip_driver_s *dev);
|
|||
|
||||
/* Defined in uip_tcpcallback.c *********************************************/
|
||||
|
||||
EXTERN uint8 uip_tcpcallback(struct uip_driver_s *dev,
|
||||
struct uip_conn *conn, uint8 flags);
|
||||
EXTERN uint16 uip_tcpcallback(struct uip_driver_s *dev,
|
||||
struct uip_conn *conn, uint16 flags);
|
||||
|
||||
/* Defined in uip-tcpreadahead.c ********************************************/
|
||||
|
||||
|
@ -195,10 +203,10 @@ EXTERN void uip_udpsend(struct uip_driver_s *dev, struct uip_udp_conn *conn);
|
|||
|
||||
EXTERN void uip_udpinput(struct uip_driver_s *dev);
|
||||
|
||||
/* Defined in uip_uipcallback.c *********************************************/
|
||||
/* Defined in uip_udpcallback.c *********************************************/
|
||||
|
||||
EXTERN void uip_udpcallback(struct uip_driver_s *dev,
|
||||
struct uip_udp_conn *conn, uint8 flags);
|
||||
struct uip_udp_conn *conn, uint16 flags);
|
||||
#endif /* CONFIG_NET_UDP */
|
||||
|
||||
#ifdef CONFIG_NET_ICMP
|
||||
|
|
|
@ -94,11 +94,11 @@
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
void uip_tcpappsend(struct uip_driver_s *dev, struct uip_conn *conn, uint8 result)
|
||||
void uip_tcpappsend(struct uip_driver_s *dev, struct uip_conn *conn, uint16 result)
|
||||
{
|
||||
/* Handle the result based on the application response */
|
||||
|
||||
nvdbg("result: %02x\n", result);
|
||||
nvdbg("result: %04x\n", result);
|
||||
|
||||
/* Check for connection aborted */
|
||||
|
||||
|
@ -202,9 +202,9 @@ void uip_tcpappsend(struct uip_driver_s *dev, struct uip_conn *conn, uint8 resul
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
void uip_tcprexmit(struct uip_driver_s *dev, struct uip_conn *conn, uint8 result)
|
||||
void uip_tcprexmit(struct uip_driver_s *dev, struct uip_conn *conn, uint16 result)
|
||||
{
|
||||
nvdbg("result: %02x\n", result);
|
||||
nvdbg("result: %04x\n", result);
|
||||
|
||||
dev->d_appdata = dev->d_snddata;
|
||||
|
||||
|
@ -221,9 +221,9 @@ void uip_tcprexmit(struct uip_driver_s *dev, struct uip_conn *conn, uint8 result
|
|||
uip_tcpsend(dev, conn, TCP_ACK | TCP_PSH, conn->len + UIP_TCPIP_HLEN);
|
||||
}
|
||||
|
||||
/* If there is no data to send, just send out a pure ACK if there is newdata. */
|
||||
/* If there is no data to send, just send out a pure ACK if one is requested`. */
|
||||
|
||||
else if (result & UIP_NEWDATA)
|
||||
else if (result & UIP_SNDACK)
|
||||
{
|
||||
uip_tcpsend(dev, conn, TCP_ACK, UIP_TCPIP_HLEN);
|
||||
}
|
||||
|
|
|
@ -102,24 +102,32 @@ static int uip_readahead(struct uip_readahead_s *readahead, uint8 *buf, int len)
|
|||
* Function: uip_dataevent
|
||||
*
|
||||
* Description:
|
||||
* This is the default data_event handler that is called when there is no
|
||||
* use data handler in place
|
||||
* This is the default data event handler that is called when there is no
|
||||
* user data handler in place
|
||||
*
|
||||
* Assumptions:
|
||||
* This function is called at the interrupt level with interrupts disabled.
|
||||
* - The called has checked that UIP_NEWDATA is set in flags and that is no
|
||||
* other handler available to process the incoming data.
|
||||
* - This function is called at the interrupt level with interrupts disabled.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static inline uint8
|
||||
uip_dataevent(struct uip_driver_s *dev, struct uip_conn *conn, uint8 flags)
|
||||
static inline uint16
|
||||
uip_dataevent(struct uip_driver_s *dev, struct uip_conn *conn, uint16 flags)
|
||||
{
|
||||
uint8 ret = flags;
|
||||
uint16 ret;
|
||||
|
||||
/* Assume that we will ACK the data. The data will be ACKed if it is
|
||||
* placed in the read-ahead buffer -OR- if it zero length
|
||||
*/
|
||||
|
||||
ret = (flags & ~UIP_NEWDATA) | UIP_SNDACK;
|
||||
|
||||
/* Is there new data? With non-zero length? (Certain connection events
|
||||
* can have zero-length with UIP_NEWDATA set just to cause an ACK).
|
||||
*/
|
||||
|
||||
if ((flags & UIP_NEWDATA) != 0 && dev->d_len > 0)
|
||||
if (dev->d_len > 0)
|
||||
{
|
||||
#if CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0
|
||||
struct uip_readahead_s *readahead1;
|
||||
|
@ -127,7 +135,11 @@ uip_dataevent(struct uip_driver_s *dev, struct uip_conn *conn, uint8 flags)
|
|||
uint16 recvlen = 0;
|
||||
uint8 *buf = dev->d_appdata;
|
||||
int buflen = dev->d_len;
|
||||
#endif
|
||||
|
||||
nvdbg("No listener on connection\n");
|
||||
|
||||
#if CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0
|
||||
/* First, we need to determine if we have space to buffer the data. This
|
||||
* needs to be verified before we actually begin buffering the data. We
|
||||
* will use any remaining space in the last allocated readahead buffer
|
||||
|
@ -169,28 +181,30 @@ uip_dataevent(struct uip_driver_s *dev, struct uip_conn *conn, uint8 flags)
|
|||
sq_addlast(&readahead2->rh_node, &conn->readahead);
|
||||
}
|
||||
|
||||
/* Indicate that all of the data in the buffer has been consumed */
|
||||
|
||||
nvdbg("Buffered %d bytes\n", dev->d_len);
|
||||
dev->d_len = 0;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* There is no handler to receive new data and there are no free
|
||||
* read-ahead buffers to retain the data. In this case, clear the
|
||||
* UIP_NEWDATA bit so that no ACK will be sent and drop the packet.
|
||||
* read-ahead buffers to retain the data -- drop the packet.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_NET_STATISTICS
|
||||
nvdbg("Dropped %d bytes\n", dev->d_len);
|
||||
|
||||
#ifdef CONFIG_NET_STATISTICS
|
||||
uip_stat.tcp.syndrop++;
|
||||
uip_stat.tcp.drop++;
|
||||
#endif
|
||||
ret &= ~UIP_NEWDATA;
|
||||
dev->d_len = 0;
|
||||
/* Clear the UIP_SNDACK bit so that no ACK will be sent */
|
||||
|
||||
ret &= ~UIP_SNDACK;
|
||||
}
|
||||
}
|
||||
|
||||
/* In any event, the new data has now been handled */
|
||||
|
||||
dev->d_len = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -209,7 +223,7 @@ uip_dataevent(struct uip_driver_s *dev, struct uip_conn *conn, uint8 flags)
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
uint8 uip_tcpcallback(struct uip_driver_s *dev, struct uip_conn *conn, uint8 flags)
|
||||
uint16 uip_tcpcallback(struct uip_driver_s *dev, struct uip_conn *conn, uint16 flags)
|
||||
{
|
||||
/* Preserve the UIP_ACKDATA, UIP_CLOSE, and UIP_ABORT in the response.
|
||||
* These is needed by uIP to handle responses and buffer state. The
|
||||
|
@ -217,39 +231,42 @@ uint8 uip_tcpcallback(struct uip_driver_s *dev, struct uip_conn *conn, uint8 fla
|
|||
* explicitly set in the callback.
|
||||
*/
|
||||
|
||||
uint8 ret = flags;
|
||||
uint16 ret = flags;
|
||||
|
||||
nvdbg("flags: %02x\n", flags);
|
||||
nvdbg("flags: %04x\n", flags);
|
||||
|
||||
/* Check if there is a data callback */
|
||||
/* Perform the data callback. When a data callback is executed from 'list',
|
||||
* the input flags are normally returned, however, the implementation
|
||||
* may set one of the following:
|
||||
*
|
||||
* UIP_CLOSE - Gracefully close the current connection
|
||||
* UIP_ABORT - Abort (reset) the current connection on an error that
|
||||
* prevents UIP_CLOSE from working.
|
||||
*
|
||||
* And/Or set/clear the following:
|
||||
*
|
||||
* UIP_NEWDATA - May be cleared to indicate that the data was consumed
|
||||
* and that no further process of the new data should be
|
||||
* attempted.
|
||||
* UIP_SNDACK - If UIP_NEWDATA is cleared, then UIP_SNDACK may be set
|
||||
* to indicate that an ACK should be included in the response.
|
||||
* (In UIP_NEWDATA is cleared bu UIP_SNDACK is not set, then
|
||||
* dev->d_len should also be cleared).
|
||||
*/
|
||||
|
||||
ret = uip_callbackexecute(dev, conn, flags, conn->list);
|
||||
|
||||
if (conn->data_event)
|
||||
{
|
||||
/* Perform the callback. Callback function normally returns the input flags,
|
||||
* however, the implementation may set one of the following:
|
||||
*
|
||||
* UIP_CLOSE - Gracefully close the current connection
|
||||
* UIP_ABORT - Abort (reset) the current connection on an error that
|
||||
* prevents UIP_CLOSE from working.
|
||||
*
|
||||
* Or clear the following:
|
||||
*
|
||||
* UIP_NEWDATA - May be cleared to suppress returning the ACK response.
|
||||
* (dev->d_len should also be set to zero in this case).
|
||||
*/
|
||||
|
||||
ret = conn->data_event(dev, conn, flags);
|
||||
}
|
||||
|
||||
/* If there is no data callback -OR- if the data callback does not handle the
|
||||
* newdata event, then there is no handler in place to handle new incoming data.
|
||||
/* There may be no new data handler in place at them moment that the new
|
||||
* incoming data is received. If the new incoming data was not handled, then
|
||||
* either (1) put the unhandled incoming data in the read-ahead buffer (if
|
||||
* enabled) or (2) suppress the ACK to the data in the hope that it will
|
||||
* be re-transmitted at a better time.
|
||||
*/
|
||||
|
||||
if (!conn->data_event || (conn->data_flags & UIP_NEWDATA) == 0)
|
||||
if ((ret & UIP_NEWDATA) != 0)
|
||||
{
|
||||
/* In either case, we will take a default newdata action */
|
||||
/* Data was not handled.. dispose of it appropriately */
|
||||
|
||||
nvdbg("No listener on connection\n");
|
||||
ret = uip_dataevent(dev, conn, ret);
|
||||
}
|
||||
|
||||
|
|
|
@ -98,8 +98,8 @@ void uip_tcpinput(struct uip_driver_s *dev)
|
|||
{
|
||||
struct uip_conn *conn = NULL;
|
||||
uint16 tmp16;
|
||||
uint16 flags;
|
||||
uint8 opt;
|
||||
uint8 flags;
|
||||
uint8 result;
|
||||
int len;
|
||||
int i;
|
||||
|
|
|
@ -228,7 +228,7 @@ static void uip_tcpsendcommon(struct uip_driver_s *dev, struct uip_conn *conn)
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
void uip_tcpsend(struct uip_driver_s *dev, struct uip_conn *conn, uint8 flags, uint16 len)
|
||||
void uip_tcpsend(struct uip_driver_s *dev, struct uip_conn *conn, uint16 flags, uint16 len)
|
||||
{
|
||||
BUF->flags = flags;
|
||||
dev->d_len = len;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/****************************************************************************
|
||||
* net/uip/uip-udpcallback.c
|
||||
*
|
||||
* Copyright (C) 2007 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
*
|
||||
*
|
||||
|
@ -74,9 +74,9 @@
|
|||
****************************************************************************/
|
||||
|
||||
void uip_udpcallback(struct uip_driver_s *dev, struct uip_udp_conn *conn,
|
||||
uint8 flags)
|
||||
uint16 flags)
|
||||
{
|
||||
nvdbg("flags: %02x\n", flags);
|
||||
nvdbg("flags: %04x\n", flags);
|
||||
|
||||
/* Some sanity checking */
|
||||
|
||||
|
@ -84,7 +84,7 @@ void uip_udpcallback(struct uip_driver_s *dev, struct uip_udp_conn *conn,
|
|||
{
|
||||
/* Perform the callback */
|
||||
|
||||
conn->event(dev, conn, flags);
|
||||
flags = uip_callbackexecute(dev, conn, flags, conn->list);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue