If port=0, UDP should select a port number

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@1625 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo 2009-03-19 00:18:21 +00:00
parent 8f2bf0bf97
commit 8a850fb963

View File

@ -1,7 +1,7 @@
/**************************************************************************** /****************************************************************************
* net/uip/uip_udpconn.c * net/uip/uip_udpconn.c
* *
* Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr> * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
* *
* Large parts of this file were leveraged from uIP logic: * Large parts of this file were leveraged from uIP logic:
@ -137,6 +137,62 @@ static struct uip_udp_conn *uip_find_conn(uint16 portno)
return NULL; return NULL;
} }
/****************************************************************************
* Name: uip_selectport()
*
* Description:
* Select an unused port number.
*
* NOTE that in prinicple this function could fail if there is no available
* port number. There is no check for that case and it would actually
* in an infinite loop if that were the case. In this simple, small UDP
* implementation, it is reasonable to assume that that error cannot happen
* and that a port number will always be available.
*
* Input Parameters:
* None
*
* Return:
* Next available port number
*
****************************************************************************/
static uint16 uip_selectport(void)
{
uint16 portno;
/* Find an unused local port number. Loop until we find a valid
* listen port number that is not being used by any other connection.
*/
irqstate_t flags = irqsave();
do
{
/* Guess that the next available port number will be the one after
* the last port number assigned.
*/
++g_last_udp_port;
/* Make sure that the port number is within range */
if (g_last_udp_port >= 32000)
{
g_last_udp_port = 4096;
}
}
while (uip_find_conn(htons(g_last_udp_port)));
/* Initialize and return the connection structure, bind it to the
* port number
*/
portno = g_last_udp_port;
irqrestore(flags);
return portno;
}
/**************************************************************************** /****************************************************************************
* Public Functions * Public Functions
****************************************************************************/ ****************************************************************************/
@ -311,9 +367,16 @@ int uip_udpbind(struct uip_udp_conn *conn, const struct sockaddr_in *addr)
int ret = -EADDRINUSE; int ret = -EADDRINUSE;
irqstate_t flags; irqstate_t flags;
/* Never set lport to zero! */ /* Is the user requesting to bind to any port? */
if (addr->sin_port) if (!addr->sin_port)
{
/* Yes.. Find an unused local port number */
conn->lport = htons(uip_selectport());
ret = OK;
}
else
{ {
/* Interrupts must be disabled while access the UDP connection list */ /* Interrupts must be disabled while access the UDP connection list */
@ -326,12 +389,11 @@ int uip_udpbind(struct uip_udp_conn *conn, const struct sockaddr_in *addr)
/* No.. then bind the socket to the port */ /* No.. then bind the socket to the port */
conn->lport = addr->sin_port; conn->lport = addr->sin_port;
ret = OK; ret = OK;
} }
irqrestore(flags); irqrestore(flags);
} }
return ret; return ret;
} }
@ -361,40 +423,19 @@ int uip_udpconnect(struct uip_udp_conn *conn, const struct sockaddr_in6 *addr)
int uip_udpconnect(struct uip_udp_conn *conn, const struct sockaddr_in *addr) int uip_udpconnect(struct uip_udp_conn *conn, const struct sockaddr_in *addr)
#endif #endif
{ {
/* Has this structure already been bound to a local port? */ /* Has this address already been bound to a local port (lport)? */
if (!conn->lport) if (!conn->lport)
{ {
/* No..Find an unused local port number. Loop until we find a valid /* No.. Find an unused local port number and bind it to the
* listen port number that is not being used by any other connection. * connection structure.
*/ */
irqstate_t flags = irqsave(); conn->lport = htons(uip_selectport());
do
{
/* Guess that the next available port number will be the one after
* the last port number assigned.
*/
++g_last_udp_port;
/* Make sure that the port number is within range */
if (g_last_udp_port >= 32000)
{
g_last_udp_port = 4096;
}
}
while (uip_find_conn(htons(g_last_udp_port)));
/* Initialize and return the connection structure, bind it to the
* port number
*/
conn->lport = HTONS(g_last_udp_port);
irqrestore(flags);
} }
/* Is there a remote port (rport) */
if (addr) if (addr)
{ {
conn->rport = addr->sin_port; conn->rport = addr->sin_port;