9
0
Fork 0

Verified recvfrom()

git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@402 7fd9a85b-ad96-42d3-883c-3090e2eb8679
This commit is contained in:
patacongo 2007-11-23 19:25:39 +00:00
parent fefb295d62
commit 6dad5fb314
10 changed files with 288 additions and 89 deletions

View File

@ -215,7 +215,7 @@
* Added listen() and accept() * Added listen() and accept()
* Added DM90x0 ethernet driver * Added DM90x0 ethernet driver
* ARP timer is now built into the network layer * ARP timer is now built into the network layer
* Basic client functionality verified: socket(), bind(), connect(), recv(), send(). * Basic client functionality verified: TCP socket(), bind(), connect(), recv(), send().
0.3.1 2007-11-19 Gregory Nutt <spudmonkey@racsa.co.cr> 0.3.1 2007-11-19 Gregory Nutt <spudmonkey@racsa.co.cr>
@ -223,12 +223,12 @@
* Corrected a TCP problem where packets were dropped because there was no * Corrected a TCP problem where packets were dropped because there was no
recv() in place but the packet was being ACKed. There are still TCP recv() in place but the packet was being ACKed. There are still TCP
recv buffering issues, but this is part of a larger buffering issue. recv buffering issues, but this is part of a larger buffering issue.
* Basic server functionality verified: listen(), accept() * Basic server functionality verified: TCP listen(), accept()
* Fix DM90x0 driver problem that caused TX overruns * Fix DM90x0 driver problem that caused TX overruns
* Add strncmp() * Add strncmp()
* Added TCP/IP read-ahead buffer to minimize failed ACKs and packet loss. * Added TCP/IP read-ahead buffer to minimize failed ACKs and packet loss.
0.3.2 2007-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr> 0.3.2 2007-11-23 Gregory Nutt <spudmonkey@racsa.co.cr>
* Add strcat() and strncat() * Add strcat() and strncat()
* Integrated uIP micro webserver * Integrated uIP micro webserver
@ -239,4 +239,10 @@
* Moved urgent data info into device structure. * Moved urgent data info into device structure.
* TCP and ICMP protocols can now be disabled. * TCP and ICMP protocols can now be disabled.
* Added UDP test in examples/udp * Added UDP test in examples/udp
* Verified/debugged UDP send logic using examples/udp * Verified/debugged UDP socket(), bind(), sendto() and recvfrom() logic
using examples/udp
* recvfrom() and accept() now correctly return the remote address.
* Fixed computation error in ntohl().
0.3.3 2007-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr>

View File

@ -8,7 +8,7 @@
<tr align="center" bgcolor="#e4e4e4"> <tr align="center" bgcolor="#e4e4e4">
<td> <td>
<h1><big><font color="#3c34ec"><i>NuttX RTOS</i></font></big></h1> <h1><big><font color="#3c34ec"><i>NuttX RTOS</i></font></big></h1>
<p>Last Updated: November 20, 2007</p> <p>Last Updated: November 23, 2007</p>
</td> </td>
</tr> </tr>
</table> </table>
@ -183,27 +183,36 @@
</table> </table>
<p> <p>
The 13th release of NuttX (nuttx-0.3.0) is available for download The 14th release of NuttX (nuttx-0.3.2) is available for download
from the <a href="http://sourceforge.net/project/showfiles.php?group_id=189573">SourceForge</a> from the <a href="http://sourceforge.net/project/showfiles.php?group_id=189573">SourceForge</a>
website. website.
The change log associated with the release is available <a href="#currentrelease">here</a>. The change log associated with the release is available <a href="#currentrelease">here</a>.
Unreleased changes after this release are avalable in CVS. Unreleased changes after this release are avalable in CVS.
These unreleased changes are listed <a href="#pendingchanges">here</a>. These unreleased changes are listed <a href="#pendingchanges">here</a>.
</p> </p>
<p> <p>
NuttX 0.3.1 is the second release containing the integration of a network NuttX 0.3.2 is the 3rd release containing the integration of a network
subsystem and the uIP TCP/IP, UDP, and ICMP stacks based on subsystem and the uIP TCP/IP, UDP, and ICMP stacks based on
<a href="http://www.sics.se/~adam/uip/index.php/Main_Page">uIP</a> <a href="http://www.sics.se/~adam/uip/index.php/Main_Page">uIP</a>
into NuttX. into NuttX.
</p> </p>
<p> <p>
Many network-related problems have been fixed from version 0.3.0 Many network-related problems have been fixed from version 0.3.1
and the implementation has matured significantly. and the implementation has matured significantly.
However, the level of network reliability is probably still at the Changes in this release include:
pre-alpha or early level. </p>
It is sufficiently complete that you may begin to perform some network <ul>
integration and is exepcted to achieve beta level of reliability over <li>TCP-related bug-fixes,</li>
the next few releases. <li>TCP performance improvements,</li>
<li>Initial UDP integration, and</li>
<li>Initial uIP micro webserver integration
</ul>
</p>
See the ChangeLog for a complete list of changes.
</p>
<p>
The level of network reliability is a a strong alpha level is expected to
achieve beta level of reliability over the next few releases.
</p> </p>
<p> <p>
The baseline functionality of NuttX continues to mature and remains at The baseline functionality of NuttX continues to mature and remains at
@ -667,17 +676,7 @@ Other memory:
* Added DM90x0 ethernet driver * Added DM90x0 ethernet driver
* ARP timer is now built into the network layer * ARP timer is now built into the network layer
* Basic client functionality verified: socket(), bind(), connect(), recv(), send(). * Basic client functionality verified: socket(), bind(), connect(), recv(), send().
</pre></ul>
<table width ="100%">
<tr bgcolor="#e4e4e4">
<td>
<a name="currentrelease">ChangeLog for Current Release</a>
</td>
</tr>
</table>
<pre><ul>
0.3.1 2007-11-19 Gregory Nutt &lt;spudmonkey@racsa.co.cr&gt; 0.3.1 2007-11-19 Gregory Nutt &lt;spudmonkey@racsa.co.cr&gt;
* Separated net/uip/uip.c into several functions in several files. * Separated net/uip/uip.c into several functions in several files.
@ -693,7 +692,7 @@ Other memory:
<table width ="100%"> <table width ="100%">
<tr bgcolor="#e4e4e4"> <tr bgcolor="#e4e4e4">
<td> <td>
<a name="pendingchanges">Unreleased Changes</a> <a name="currentrelease">ChangeLog for Current Release</a>
</td> </td>
</tr> </tr>
</table> </table>
@ -710,7 +709,22 @@ Other memory:
* Moved urgent data info into device structure. * Moved urgent data info into device structure.
* TCP and ICMP protocols can now be disabled. * TCP and ICMP protocols can now be disabled.
* Added UDP test in examples/udp * Added UDP test in examples/udp
* Verified/debugged UDP send logic using examples/udp * Verified/debugged UDP socket(), bind(), sendto() and recvfrom() logic
using examples/udp
* recvfrom() and accept() now correctly return the remote address.
* Fixed computation error in ntohl().
</pre></ul>
<table width ="100%">
<tr bgcolor="#e4e4e4">
<td>
<a name="pendingchanges">Unreleased Changes</a>
</td>
</tr>
</table>
<pre><ul>
0.3.3 2007-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr>
</pre></ul> </pre></ul>
<table width ="100%"> <table width ="100%">

View File

@ -1,23 +1,27 @@
nuttx-0.3.1 nuttx-0.3.2
^^^^^^^^^^^ ^^^^^^^^^^^
This is the 13th release of NuttX and the second release containing This is the 14th release of NuttX and the 3rd release containing
the integration of a network subsystem and the uIP TCP/IP, UDP, and the integration of a network subsystem and the uIP TCP/IP, UDP, and
ICMP stacks into NuttX (see http://www.sics.se/~adam/uip/index.php/Main_Page). ICMP stacks into NuttX (see http://www.sics.se/~adam/uip/index.php/Main_Page).
Many network-related problems have been fixed and the implementation Many network-related problems have been fixed and the implementation
has matured significantly. However, the level of network reliability has matured significantly. This release consists of:
is probably still at the pre-alpha or early level. It is sufficiently
complete that you may begin to perform some network integration and
is exepcted to achieve beta level of reliability over the next few
releases.
The baseline functionality of NuttX continues to mature and remains at o TCP-related bug-fixes
post-beta (as long as the network is not used). o TCP performance improvements
o Initial UDP integration
o Initial uIP micro webserver integration
See the ChangeLog for a complete list of changes. See the ChangeLog for a complete list of changes.
The level of network reliability is at alpha level is expected to
achieve beta level of reliability over the next few releases.
The baseline functionality of NuttX continues to mature and remains at
post-beta.
This release has been verified only on the Neuros OSD (DM320 ARM9) This release has been verified only on the Neuros OSD (DM320 ARM9)
platform using the DM90x0 driver. platform using the DM90x0 driver.
This tarball contains a complete CVS snapshot from November 19, 2007. This tarball contains a complete CVS snapshot from November 23, 2007.

View File

@ -29,7 +29,6 @@ o C++ Support
- Need to call static constructors - Need to call static constructors
o Network o Network
- UDP is untested.
- Did not implement send() and sendto() timeouts. Option is setable via setsockopt, - Did not implement send() and sendto() timeouts. Option is setable via setsockopt,
but is not implemented. but is not implemented.
- uIP's netutils/telnetd (and maybe others) are seriously broken. - uIP's netutils/telnetd (and maybe others) are seriously broken.
@ -37,7 +36,6 @@ o Network
- uIP's netutils/webserver hangs - uIP's netutils/webserver hangs
- uIP's netutils/smtp, dpcpc, resolv, webclient -- untested - uIP's netutils/smtp, dpcpc, resolv, webclient -- untested
- Should implement SOCK_RAW - Should implement SOCK_RAW
- accept() and recvfrom() need to return connection address
- Performance Improvements (uIP is not very fast): - Performance Improvements (uIP is not very fast):
Need to extend logic so that uIP can have more than on packet in flight and to Need to extend logic so that uIP can have more than on packet in flight and to
handle deferred acknowledgements. handle deferred acknowledgements.

View File

@ -83,6 +83,7 @@ void recv_server(void)
{ {
struct sockaddr_in server; struct sockaddr_in server;
struct sockaddr_in client; struct sockaddr_in client;
uint32 tmpaddr;
unsigned char inbuf[1024]; unsigned char inbuf[1024];
int sockfd; int sockfd;
int nbytes; int nbytes;
@ -128,7 +129,13 @@ void recv_server(void)
addrlen = sizeof(struct sockaddr_in); addrlen = sizeof(struct sockaddr_in);
nbytes = recvfrom(sockfd, inbuf, 1024, 0, nbytes = recvfrom(sockfd, inbuf, 1024, 0,
(struct sockaddr*)&client, &addrlen); (struct sockaddr*)&client, &addrlen);
message("server: %d. Recieved %d bytes\n", offset, nbytes);
tmpaddr = ntohl(client.sin_addr.s_addr);
message("server: %d. Received %d bytes from %d.%d.%d.%d:%d\n",
offset, nbytes,
tmpaddr >> 24, (tmpaddr >> 16) & 0xff,
(tmpaddr >> 8) & 0xff, tmpaddr & 0xff,
ntohs(client.sin_port));
if (nbytes < 0) if (nbytes < 0)
{ {

View File

@ -74,7 +74,7 @@ int open(const char *path, int oflags, ...)
struct filelist *list; struct filelist *list;
FAR struct inode *inode; FAR struct inode *inode;
const char *relpath = NULL; const char *relpath = NULL;
#ifdef CONFIG_FILE_MODE #if defined(CONFIG_FILE_MODE) || !defined(CONFIG_DISABLE_MOUNTPOINT)
mode_t mode = 0666; mode_t mode = 0666;
#endif #endif
int ret; int ret;

View File

@ -53,7 +53,10 @@ uint32 htonl(uint32 hl)
#ifdef CONFIG_ENDIAN_BIG #ifdef CONFIG_ENDIAN_BIG
return hl; return hl;
#else #else
return (uint32)htons((uint16)((hl) << 16)) | (uint32)htons((uint16)((hl) & 0xffff)); return (( (hl) >> 24) |
(((hl) >> 8) & 0x0000ff00) |
(((hl) << 8) & 0x00ff0000) |
( (hl) << 24));
#endif #endif
} }

View File

@ -52,6 +52,10 @@
#include "net-internal.h" #include "net-internal.h"
/****************************************************************************
* Definitions
****************************************************************************/
/**************************************************************************** /****************************************************************************
* Private Types * Private Types
****************************************************************************/ ****************************************************************************/
@ -76,6 +80,47 @@ struct accept_s
* Private Functions * Private Functions
****************************************************************************/ ****************************************************************************/
/****************************************************************************
* Function: accept_tcpsender
*
* Description:
* Getting the sender's address from the UDP packet
*
* Parameters:
* conn - The newly accepted TCP connection
* pstate - the recvfrom state structure
*
* Returned Value:
* None
*
* Assumptions:
* Running at the interrupt level
*
****************************************************************************/
#ifdef CONFIG_NET_TCP
static inline void accept_tcpsender(struct uip_conn *conn, struct accept_s *pstate)
{
#ifdef CONFIG_NET_IPv6
FAR struct sockaddr_in6 *addr = pstate->acpt_addr;
#else
FAR struct sockaddr_in *addr = pstate->acpt_addr;
#endif
if (addr)
{
addr->sin_family = AF_INET;
addr->sin_port = conn->rport;
#ifdef CONFIG_NET_IPv6
uip_ipaddr_copy(addr->sin_addr.s_addr, conn->ripaddr);
#else
uip_ipaddr_copy(addr->sin_addr.s_addr, conn->ripaddr);
#endif
}
}
#endif
/**************************************************************************** /****************************************************************************
* Function: accept_interrupt * Function: accept_interrupt
* *
@ -102,7 +147,8 @@ static int accept_interrupt(struct uip_conn *listener, struct uip_conn *conn)
if (pstate) if (pstate)
{ {
/* Get the connection address */ /* Get the connection address */
#warning "need to return the address of the connection"
accept_tcpsender(conn, pstate);
/* Save the connection structure */ /* Save the connection structure */

View File

@ -59,6 +59,9 @@
#define TCP_TIMEO 10 /* Deciseconds after data received before recv() returns */ #define TCP_TIMEO 10 /* Deciseconds after data received before recv() returns */
#define UDPBUF ((struct uip_udpip_hdr *)&dev->d_buf[UIP_LLH_LEN])
#define TCPBUF ((struct uip_tcpip_hdr *)&dev->d_buf[UIP_LLH_LEN])
/**************************************************************************** /****************************************************************************
* Private Types * Private Types
****************************************************************************/ ****************************************************************************/
@ -67,14 +70,19 @@
struct recvfrom_s struct recvfrom_s
{ {
#if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK) #if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK)
FAR struct socket *rf_sock; /* The parent socket structure */ FAR struct socket *rf_sock; /* The parent socket structure */
uint32 rf_starttime; /* rcv start time for determining timeout */ uint32 rf_starttime; /* rcv start time for determining timeout */
#endif #endif
sem_t rf_sem; /* Semaphore signals recv completion */ sem_t rf_sem; /* Semaphore signals recv completion */
size_t rf_buflen; /* Length of receive buffer */ size_t rf_buflen; /* Length of receive buffer */
char *rf_buffer; /* Pointer to receive buffer */ char *rf_buffer; /* Pointer to receive buffer */
size_t rf_recvlen; /* The received length */ #ifdef CONFIG_NET_IPv6
int rf_result; /* OK on success, otherwise a negated errno. */ FAR struct sockaddr_in6 *rf_from; /* Address of sender */
#else
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 */
}; };
#endif /* CONFIG_NET_UDP || CONFIG_NET_TCP */ #endif /* CONFIG_NET_UDP || CONFIG_NET_TCP */
@ -286,6 +294,47 @@ static int recvfrom_timeout(struct recvfrom_s *pstate)
#endif /* CONFIG_NET_SOCKOPTS && !CONFIG_DISABLE_CLOCK */ #endif /* CONFIG_NET_SOCKOPTS && !CONFIG_DISABLE_CLOCK */
#endif /* CONFIG_NET_UDP || CONFIG_NET_TCP */ #endif /* CONFIG_NET_UDP || CONFIG_NET_TCP */
/****************************************************************************
* Function: recvfrom_tcpsender
*
* Description:
* Getting the sender's address from the UDP packet
*
* Parameters:
* dev - The device driver data structure
* pstate - the recvfrom state structure
*
* Returned Value:
* None
*
* Assumptions:
* Running at the interrupt level
*
****************************************************************************/
#ifdef CONFIG_NET_TCP
static inline void recvfrom_tcpsender(struct uip_driver_s *dev, struct recvfrom_s *pstate)
{
#ifdef CONFIG_NET_IPv6
FAR struct sockaddr_in6 *infrom = pstate->rf_from;
#else
FAR struct sockaddr_in *infrom = pstate->rf_from;
#endif
if (infrom)
{
infrom->sin_family = AF_INET;
infrom->sin_port = TCPBUF->srcport;
#ifdef CONFIG_NET_IPv6
uip_ipaddr_copy(infrom->sin_addr.s_addr, TCPBUF->srcipaddr);
#else
uip_ipaddr_copy(infrom->sin_addr.s_addr, uip_ip4addr_conv(TCPBUF->srcipaddr));
#endif
}
}
#endif
/**************************************************************************** /****************************************************************************
* Function: recvfrom_tcpinterrupt * Function: recvfrom_tcpinterrupt
* *
@ -326,6 +375,10 @@ static uint8 recvfrom_tcpinterrupt(struct uip_driver_s *dev,
recvfrom_newdata(dev, pstate); recvfrom_newdata(dev, pstate);
/* Save the sender's address in the caller's 'from' location */
recvfrom_tcpsender(dev, pstate);
/* If the user buffer has been filled, then we are finished. */ /* If the user buffer has been filled, then we are finished. */
if (pstate->rf_buflen == 0) if (pstate->rf_buflen == 0)
@ -415,6 +468,47 @@ static uint8 recvfrom_tcpinterrupt(struct uip_driver_s *dev,
} }
#endif /* CONFIG_NET_TCP */ #endif /* CONFIG_NET_TCP */
/****************************************************************************
* Function: recvfrom_udpsender
*
* Description:
* Getting the sender's address from the UDP packet
*
* Parameters:
* dev - The device driver data structure
* pstate - the recvfrom state structure
*
* Returned Value:
* None
*
* Assumptions:
* Running at the interrupt level
*
****************************************************************************/
#ifdef CONFIG_NET_UDP
static inline void recvfrom_udpsender(struct uip_driver_s *dev, struct recvfrom_s *pstate)
{
#ifdef CONFIG_NET_IPv6
FAR struct sockaddr_in6 *infrom = pstate->rf_from;
#else
FAR struct sockaddr_in *infrom = pstate->rf_from;
#endif
if (infrom)
{
infrom->sin_family = AF_INET;
infrom->sin_port = UDPBUF->srcport;
#ifdef CONFIG_NET_IPv6
uip_ipaddr_copy(infrom->sin_addr.s_addr, UDPBUF->srcipaddr);
#else
uip_ipaddr_copy(infrom->sin_addr.s_addr, uip_ip4addr_conv(UDPBUF->srcipaddr));
#endif
}
}
#endif
/**************************************************************************** /****************************************************************************
* Function: recvfrom_udpinterrupt * Function: recvfrom_udpinterrupt
* *
@ -457,13 +551,17 @@ static void recvfrom_udpinterrupt(struct uip_driver_s *dev,
/* We are finished. */ /* We are finished. */
vdbg("UDP resume\n"); vdbg("UDP done\n");
/* Don't allow any further UDP call backs. */ /* Don't allow any further UDP call backs. */
conn->private = NULL; conn->private = NULL;
conn->event = NULL; conn->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 /* Wake up the waiting thread, returning the number of bytes
* actually read. * actually read.
*/ */
@ -539,6 +637,11 @@ static void recvfrom_udpinterrupt(struct uip_driver_s *dev,
#if defined(CONFIG_NET_UDP) || defined(CONFIG_NET_TCP) #if defined(CONFIG_NET_UDP) || defined(CONFIG_NET_TCP)
static void recvfrom_init(FAR struct socket *psock, FAR void *buf, size_t len, static void recvfrom_init(FAR struct socket *psock, FAR void *buf, size_t len,
#ifdef CONFIG_NET_IPv6
FAR struct sockaddr_in6 *infrom,
#else
FAR struct sockaddr_in *infrom,
#endif
struct recvfrom_s *pstate) struct recvfrom_s *pstate)
{ {
/* Initialize the state structure. */ /* Initialize the state structure. */
@ -547,6 +650,7 @@ static void recvfrom_init(FAR struct socket *psock, FAR void *buf, size_t len,
(void)sem_init(&pstate->rf_sem, 0, 0); /* Doesn't really fail */ (void)sem_init(&pstate->rf_sem, 0, 0); /* Doesn't really fail */
pstate->rf_buflen = len; pstate->rf_buflen = len;
pstate->rf_buffer = buf; pstate->rf_buffer = buf;
pstate->rf_from = infrom;
#if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK) #if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK)
/* Set up the start time for the timeout */ /* Set up the start time for the timeout */
@ -630,13 +734,13 @@ static ssize_t recvfrom_result(int result, struct recvfrom_s *pstate)
#ifdef CONFIG_NET_UDP #ifdef CONFIG_NET_UDP
#ifdef CONFIG_NET_IPv6 #ifdef CONFIG_NET_IPv6
static ssize_t udp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len, static ssize_t udp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
FAR const struct sockaddr_in6 *infrom ) FAR struct sockaddr_in6 *infrom )
#else #else
static ssize_t udp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len, static ssize_t udp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
FAR const struct sockaddr_in *infrom ) FAR struct sockaddr_in *infrom )
#endif #endif
{ {
struct uip_udp_conn *udp_conn; struct uip_udp_conn *udp_conn = (struct uip_udp_conn *)psock->s_conn;
struct recvfrom_s state; struct recvfrom_s state;
irqstate_t save; irqstate_t save;
int ret; int ret;
@ -649,11 +753,11 @@ static ssize_t udp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
*/ */
save = irqsave(); save = irqsave();
recvfrom_init(psock, buf, len, &state); recvfrom_init(psock, buf, len, infrom, &state);
/* Setup the UDP socket */ /* Setup the UDP remote connection */
ret = uip_udpconnect(psock->s_conn, NULL); ret = uip_udpconnect(udp_conn, infrom);
if (ret < 0) if (ret < 0)
{ {
irqrestore(save); irqrestore(save);
@ -662,13 +766,12 @@ static ssize_t udp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
/* Set up the callback in the connection */ /* Set up the callback in the connection */
udp_conn = (struct uip_udp_conn *)psock->s_conn;
udp_conn->private = (void*)&state; udp_conn->private = (void*)&state;
udp_conn->event = recvfrom_udpinterrupt; udp_conn->event = recvfrom_udpinterrupt;
/* Enable the UDP socket */ /* Enable the UDP socket */
uip_udpenable(psock->s_conn); uip_udpenable(udp_conn);
/* Wait for either the receive to complete or for an error/timeout to occur. /* 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) * NOTES: (1) sem_wait will also terminate if a signal is received, (2)
@ -680,12 +783,11 @@ static ssize_t udp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
/* Make sure that no further interrupts are processed */ /* Make sure that no further interrupts are processed */
uip_udpdisable(psock->s_conn); uip_udpdisable(udp_conn);
udp_conn->private = NULL; udp_conn->private = NULL;
udp_conn->event = NULL; udp_conn->event = NULL;
irqrestore(save); irqrestore(save);
#warning "Needs to return server address"
return recvfrom_result(ret, &state); return recvfrom_result(ret, &state);
} }
#endif /* CONFIG_NET_UDP */ #endif /* CONFIG_NET_UDP */
@ -713,10 +815,10 @@ static ssize_t udp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
#ifdef CONFIG_NET_TCP #ifdef CONFIG_NET_TCP
#ifdef CONFIG_NET_IPv6 #ifdef CONFIG_NET_IPv6
static ssize_t tcp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len, static ssize_t tcp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
FAR const struct sockaddr_in6 *infrom ) FAR struct sockaddr_in6 *infrom )
#else #else
static ssize_t tcp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len, static ssize_t tcp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
FAR const struct sockaddr_in *infrom ) FAR struct sockaddr_in *infrom )
#endif #endif
{ {
struct uip_conn *conn; struct uip_conn *conn;
@ -740,7 +842,7 @@ static ssize_t tcp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
*/ */
save = irqsave(); save = irqsave();
recvfrom_init(psock, buf, len, &state); recvfrom_init(psock, buf, len, infrom, &state);
#if CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0 #if CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0
@ -776,7 +878,6 @@ static ssize_t tcp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
} }
irqrestore(save); irqrestore(save);
#warning "Needs to return server address"
return recvfrom_result(ret, &state); return recvfrom_result(ret, &state);
} }
#endif /* CONFIG_NET_TCP */ #endif /* CONFIG_NET_TCP */
@ -837,16 +938,16 @@ static ssize_t tcp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
* *
****************************************************************************/ ****************************************************************************/
ssize_t recvfrom(int sockfd, FAR void *buf, size_t len, int flags, FAR struct sockaddr *from, ssize_t recvfrom(int sockfd, FAR void *buf, size_t len, int flags,
FAR socklen_t *fromlen) FAR struct sockaddr *from, FAR socklen_t *fromlen)
{ {
FAR struct socket *psock; FAR struct socket *psock;
#if defined(CONFIG_NET_UDP) || defined(CONFIG_NET_TCP) #if defined(CONFIG_NET_UDP) || defined(CONFIG_NET_TCP)
#ifdef CONFIG_NET_IPv6 #ifdef CONFIG_NET_IPv6
FAR const struct sockaddr_in6 *infrom = (const struct sockaddr_in6 *)from; FAR struct sockaddr_in6 *infrom = (struct sockaddr_in6 *)from;
#else #else
FAR const struct sockaddr_in *infrom = (const struct sockaddr_in *)from; FAR struct sockaddr_in *infrom = (struct sockaddr_in *)from;
#endif #endif
#endif #endif
@ -871,17 +972,19 @@ ssize_t recvfrom(int sockfd, FAR void *buf, size_t len, int flags, FAR struct so
goto errout; goto errout;
} }
/* If a 'from' address has been provided, verify that it is valid */ /* If a 'from' address has been provided, verify that it is large
* enough to hold this address family.
*/
if (from) if (from)
{ {
#ifdef CONFIG_NET_IPv6 #ifdef CONFIG_NET_IPv6
if (from->sa_family != AF_INET6 || *fromlen < sizeof(struct sockaddr_in6)) if (*fromlen < sizeof(struct sockaddr_in6))
#else #else
if (from->sa_family != AF_INET || *fromlen < sizeof(struct sockaddr_in)) if (*fromlen < sizeof(struct sockaddr_in))
#endif #endif
{ {
err = EBADF; err = EINVAL;
goto errout; goto errout;
} }
} }

View File

@ -1,5 +1,5 @@
/**************************************************************************** /****************************************************************************
* uip-udpconn.c * net/uip/uip-udpconn.c
* *
* Copyright (C) 2007 Gregory Nutt. All rights reserved. * Copyright (C) 2007 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr> * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
@ -52,6 +52,8 @@
#include <semaphore.h> #include <semaphore.h>
#include <assert.h> #include <assert.h>
#include <errno.h> #include <errno.h>
#include <debug.h>
#include <arch/irq.h> #include <arch/irq.h>
#include <net/uip/uipopt.h> #include <net/uip/uipopt.h>
@ -118,7 +120,7 @@ static inline void _uip_semtake(sem_t *sem)
* *
****************************************************************************/ ****************************************************************************/
static struct uip_udp_conn *uip_find_conn( uint16 portno ) static struct uip_udp_conn *uip_find_conn(uint16 portno)
{ {
int i; int i;
@ -234,6 +236,7 @@ void uip_udpfree(struct uip_udp_conn *conn)
struct uip_udp_conn *uip_udpactive(struct uip_udpip_hdr *buf) struct uip_udp_conn *uip_udpactive(struct uip_udpip_hdr *buf)
{ {
struct uip_udp_conn *conn = (struct uip_udp_conn *)g_active_udp_connections.head; struct uip_udp_conn *conn = (struct uip_udp_conn *)g_active_udp_connections.head;
while (conn) while (conn)
{ {
/* If the local UDP port is non-zero, the connection is considered /* If the local UDP port is non-zero, the connection is considered
@ -252,7 +255,6 @@ struct uip_udp_conn *uip_udpactive(struct uip_udpip_hdr *buf)
uiphdr_ipaddr_cmp(buf->srcipaddr, &conn->ripaddr))) uiphdr_ipaddr_cmp(buf->srcipaddr, &conn->ripaddr)))
{ {
/* Matching connection found.. return a reference to it */ /* Matching connection found.. return a reference to it */
break; break;
} }
@ -261,7 +263,7 @@ struct uip_udp_conn *uip_udpactive(struct uip_udpip_hdr *buf)
conn = (struct uip_udp_conn *)conn->node.flink; conn = (struct uip_udp_conn *)conn->node.flink;
} }
return NULL; return conn;
} }
/**************************************************************************** /****************************************************************************
@ -307,13 +309,29 @@ int uip_udpbind(struct uip_udp_conn *conn, const struct sockaddr_in *addr)
#endif #endif
{ {
int ret = -EADDRINUSE; int ret = -EADDRINUSE;
irqstate_t flags = irqsave(); irqstate_t flags;
if (!uip_find_conn(g_last_udp_port))
/* Never set lport to zero! */
if (addr->sin_port)
{ {
conn->lport = HTONS(g_last_udp_port); /* Interrupts must be disabled while access the UDP connection list */
ret = OK;
flags = irqsave();
/* Is any other UDP connection bound to this port? */
if (!uip_find_conn(addr->sin_port))
{
/* No.. then bind the socket to the port */
conn->lport = addr->sin_port;
ret = OK;
}
irqrestore(flags);
} }
irqrestore(flags);
return ret; return ret;
} }
@ -367,7 +385,7 @@ int uip_udpconnect(struct uip_udp_conn *conn, const struct sockaddr_in *addr)
g_last_udp_port = 4096; g_last_udp_port = 4096;
} }
} }
while (uip_find_conn(g_last_udp_port)); while (uip_find_conn(htons(g_last_udp_port)));
/* Initialize and return the connection structure, bind it to the /* Initialize and return the connection structure, bind it to the
* port number * port number
@ -406,7 +424,7 @@ int uip_udpconnect(struct uip_udp_conn *conn, const struct sockaddr_in *addr)
void uip_udpenable(struct uip_udp_conn *conn) void uip_udpenable(struct uip_udp_conn *conn)
{ {
/* Add the connection structure to the active connectionlist. This list /* Add the connection structure to the active connectionlist. This list
* is modifiable from interrupt level, we we must diable interrupts to * is modifiable from interrupt level, we we must disable interrupts to
* access it safely. * access it safely.
*/ */
@ -417,8 +435,8 @@ void uip_udpenable(struct uip_udp_conn *conn)
void uip_udpdisable(struct uip_udp_conn *conn) void uip_udpdisable(struct uip_udp_conn *conn)
{ {
/* Remove the connection structure to the active connectionlist. This list /* Remove the connection structure from the active connectionlist. This list
* is modifiable from interrupt level, we we must diable interrupts to * is modifiable from interrupt level, we we must disable interrupts to
* access it safely. * access it safely.
*/ */