Added receive timeout via setsockopt(SO_RCVTIMEO)

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@336 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo 2007-09-08 21:54:43 +00:00
parent 09d6450ab3
commit 952db3328f
10 changed files with 292 additions and 260 deletions

View File

@ -199,7 +199,7 @@
* examples/nsh/: Add cp, rm, rmdir, set, unset commands. echo will now print * examples/nsh/: Add cp, rm, rmdir, set, unset commands. echo will now print
environment variables. environment variables.
0.2.9 2007-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr> 0.3.0 2007-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr>
* Imported uIP into the tree (see * Imported uIP into the tree (see
http://www.sics.se/~adam/uip/index.php/Main_Page) http://www.sics.se/~adam/uip/index.php/Main_Page)
@ -209,4 +209,5 @@
* Added recv() and recvfrom(). * Added recv() and recvfrom().
* Added getsockopt() and setsockopt() * Added getsockopt() and setsockopt()
* Documentation updated to address socket interfaces. * Documentation updated to address socket interfaces.
* Implemented receive timeouts via setsockopt(SO_RCVTIMEO).

View File

@ -632,7 +632,7 @@ Other memory:
</table> </table>
<pre><ul> <pre><ul>
0.2.9 2007-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr> 0.3.0 2007-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr>
* Imported uIP into the tree (see * Imported uIP into the tree (see
http://www.sics.se/~adam/uip/index.php/Main_Page) http://www.sics.se/~adam/uip/index.php/Main_Page)
@ -642,6 +642,7 @@ Other memory:
* Added recv() and recvfrom(). * Added recv() and recvfrom().
* Added getsockopt() and setsockopt() * Added getsockopt() and setsockopt()
* Documentation updated to address socket interfaces. * Documentation updated to address socket interfaces.
* Implemented receive timeouts via setsockopt(SO_RCVTIMEO).
</pre></ul> </pre></ul>
<table width ="100%"> <table width ="100%">

View File

@ -67,7 +67,7 @@ struct dhcpc_state
****************************************************************************/ ****************************************************************************/
void *dhcpc_open(const void *mac_addr, int mac_len); void *dhcpc_open(const void *mac_addr, int mac_len);
int dhcpc_request(void *handle, struct dhcpc_state *ds); int dhcpc_request(void *handle, struct dhcpc_state *presult);
void dhcpc_close(void *handle); void dhcpc_close(void *handle);
#endif /* NET_UIP_DHCP_H__ */ #endif /* NET_UIP_DHCP_H__ */

View File

@ -54,7 +54,7 @@ EXTERN void resolv_getserver(const struct sockaddr_in6 *dnsserver);
EXTERN int resolv_query(const char *name, struct sockaddr_in6 *addr); EXTERN int resolv_query(const char *name, struct sockaddr_in6 *addr);
#else #else
EXTERN void resolv_conf(const struct sockaddr_in *dnsserver); EXTERN void resolv_conf(const struct sockaddr_in *dnsserver);
EXTERN void resolv_getserver(const struct sockaddr_in *dnsserver); EXTERN void resolv_getserver(struct sockaddr_in *dnsserver);
EXTERN int resolv_query(const char *name, struct sockaddr_in *addr); EXTERN int resolv_query(const char *name, struct sockaddr_in *addr);
#endif #endif

View File

@ -1126,8 +1126,7 @@ extern int uip_udpconnect(struct uip_udp_conn *conn, const struct sockaddr_in *a
/* This function is called user code to set up the wait */ /* This function is called user code to set up the wait */
#define uip_event_wait(waitflags) uip_event_timedwait(waitflags,0) extern int uip_event_wait(uint16 waitflags);
extern int uip_event_timedwait(uint16 waitflags, int timeout);
/* This function is called from uip_interrupt() to wake up any /* This function is called from uip_interrupt() to wake up any
* waiting threads/tasks. * waiting threads/tasks.

View File

@ -58,9 +58,15 @@
struct recvfrom_s struct recvfrom_s
{ {
sem_t rf_sem; #if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK)
uint16 rf_buflen; FAR struct socket *rf_sock /* The parent socket structure */
char * rf_buffer; #endif
sem_t rf_sem; /* Semaphore signals recv completion */
sint16 rf_buflen; /* Length of receive buffer (error if <0) */
char *rf_buffer; /* Pointer to receive buffer */
#if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK)
uint32 rf_starttime; /* rcv start time for determining timeout */
#endif
}; };
/**************************************************************************** /****************************************************************************
@ -72,12 +78,13 @@ void recvfrom_interrupt(void *private)
struct recvfrom_s *pstate = (struct recvfrom_s *)private; struct recvfrom_s *pstate = (struct recvfrom_s *)private;
size_t recvlen; size_t recvlen;
/* If new data is available and we are correctly intialized, then complete /* 'private' might be null in some race conditions (?) */
* the read action. We could also check for POLL events here in order to
* implement SO_RECVTIMEO.
*/
if (uip_newdata() && private) if (pstate)
{
/* If new data is available, then complete the read action. */
if (uip_newdata())
{ {
/* Get the length of the data to return */ /* Get the length of the data to return */
if (uip_len > pstate-> rf_buflen) if (uip_len > pstate-> rf_buflen)
@ -105,6 +112,28 @@ void recvfrom_interrupt(void *private)
pstate->rf_buflen = recvlen; pstate->rf_buflen = recvlen;
sem_post(&pstate-> rf_sem); sem_post(&pstate-> rf_sem);
} }
/* No data has been received. If this is a poll event, then check
* for a timeout.
*/
#if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK)
else if (uip_newdata() && pstate->rf_sock)
{
/* Check if SO_RCVTIMEO has been selected for this socket */
uint rcvtimeo = ;
if (pstate->rf_sock->s_rcvtimeo)
{
/* Yes.. Check if the timeout has elapsed */
if (net_timeo(pstate->rf_starttime, pstate->rf_sock->s_rcvtimeo))
{
}
}
}
#endif
}
} }
/**************************************************************************** /****************************************************************************
@ -213,6 +242,12 @@ ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *
state. rf_buflen = len; state. rf_buflen = len;
state. rf_buffer = buf; state. rf_buffer = buf;
#if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK)
/* Set up the start time for the timeout */
state.rf_starttime = g_system_timer;
#endif
/* Setup the UDP socket */ /* Setup the UDP socket */
ret = uip_udpconnect(psock->s_conn, NULL); ret = uip_udpconnect(psock->s_conn, NULL);
@ -244,6 +279,20 @@ ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *
sem_destroy(&state. rf_sem); sem_destroy(&state. rf_sem);
irqrestore(save); irqrestore(save);
/* Check for a timeout. Errors are signaled by negative errno values
* for the rcv length
*/
#if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK)
if (state.rf_buflen < 0)
{
/* Return EGAIN on a timeout */
err = -state.rf_buflen;
goto errout;
}
#endif
/* If sem_wait failed, then we were probably reawakened by a signal. In /* If sem_wait failed, then we were probably reawakened by a signal. In
* this case, sem_wait will have set errno appropriately. * this case, sem_wait will have set errno appropriately.
*/ */
@ -253,8 +302,9 @@ ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *
return ERROR; return ERROR;
} }
return state.rf_buflen;
#warning "Needs to return server address" #warning "Needs to return server address"
return state.rf_buflen;
#else #else
err = ENOSYS; err = ENOSYS;
#endif #endif

View File

@ -58,9 +58,9 @@
struct sendto_s struct sendto_s
{ {
sem_t st_sem; sem_t st_sem; /* Semaphore signals sendto completion */
uint16 st_buflen; uint16 st_buflen; /* Length of send buffer (error if <0) */
const char *st_buffer; const char *st_buffer; /* Pointer to send buffer */
}; };
/**************************************************************************** /****************************************************************************

View File

@ -39,7 +39,6 @@
#include <nuttx/config.h> #include <nuttx/config.h>
#include <semaphore.h> #include <semaphore.h>
#include <wdog.h>
#include <arch/irq.h> #include <arch/irq.h>
#include <net/uip/uip.h> #include <net/uip/uip.h>
@ -63,31 +62,18 @@ static uint16 uip_waitflags = 0; /* UIP flags to wait for */
* Private Functions * Private Functions
************************************************************/ ************************************************************/
/* Called from the timer interrupt handler when a event wait
* watchdog expires.
*/
static void uip_event_timeout(int argc, uint32 itcb, ...)
{
irqstate_t save = irqsave(); /* Should not be necessary */
uip_flags |= UIP_APPTIMEOUT; /* Set software timeout event */
uip_event_signal(); /* Signal the waiting thread/task */
irqrestore(save); /* Restore interrupts */
}
/************************************************************ /************************************************************
* Global Functions * Global Functions
************************************************************/ ************************************************************/
/* This function is called user code to set up the wait */ /* This function is called user code to set up the wait */
int uip_event_timedwait(uint16 waitflags, int timeout) int uip_event_wait(uint16 waitflags)
{ {
/* Prevent conflicts with the interrupt level operation of /* Prevent conflicts with the interrupt level operation of
* uip_event_signal(). * uip_event_signal().
*/ */
irqstate_t save = irqsave(); irqstate_t save = irqsave();
WDOG_ID wdog;
/* At present, we support only a single waiter. If uip_waitflags /* At present, we support only a single waiter. If uip_waitflags
* is non-zero on entry, then there is a problem. * is non-zero on entry, then there is a problem.
@ -111,52 +97,17 @@ int uip_event_timedwait(uint16 waitflags, int timeout)
uip_waitflags = waitflags; uip_waitflags = waitflags;
/* Was a timeut requested as well? */ /* Wait for the event to occur */
if (timeout)
{
/* Yes, then set the application timeout event as well */
uip_waitflags |= UIP_APPTIMEOUT;
/* Create a watchdog */
wdog = wd_create();
if (!wdog)
{
goto errout_with_irqdisabled;
}
/* Start the watchdog */
wd_start(wdog, timeout, (wdentry_t)uip_event_timeout, 0);
}
/* Wait for the event (or timeout) to occur */
if (sem_wait(&uip_waitsem) != 0) if (sem_wait(&uip_waitsem) != 0)
{ {
goto errout_with_watchdog; goto errout_with_irqdisabled;
}
/* We no longer need the watchdog */
if (wdog)
{
wd_delete(wdog);
wdog = NULL;
} }
} }
irqrestore(save); irqrestore(save);
return OK; return OK;
errout_with_watchdog:
if (wdog)
{
wd_delete(wdog);
}
errout_with_irqdisabled: errout_with_irqdisabled:
irqrestore(save); irqrestore(save);
return ERROR; return ERROR;

View File

@ -43,13 +43,14 @@
****************************************************************************/ ****************************************************************************/
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <pthread.h> #include <unistd.h>
#include <semaphore.h>
#include <time.h> #include <time.h>
#include <errno.h>
#include <debug.h> #include <debug.h>
#include <sys/socket.h>
#include <net/uip/uip.h> #include <net/uip/uip.h>
#include <net/uip/dhcpc.h> #include <net/uip/dhcpc.h>
@ -58,10 +59,6 @@
* Definitions * Definitions
****************************************************************************/ ****************************************************************************/
/* CLK_TCK is the frequency of the system clock (typically 100Hz) */
#define CLOCK_SECOND CLK_TCK
#define STATE_INITIAL 0 #define STATE_INITIAL 0
#define STATE_SENDING 1 #define STATE_SENDING 1
#define STATE_OFFER_RECEIVED 2 #define STATE_OFFER_RECEIVED 2
@ -96,6 +93,8 @@
#define DHCP_OPTION_REQ_LIST 55 #define DHCP_OPTION_REQ_LIST 55
#define DHCP_OPTION_END 255 #define DHCP_OPTION_END 255
#define BUFFER_SIZE 256
/**************************************************************************** /****************************************************************************
* Private Types * Private Types
****************************************************************************/ ****************************************************************************/
@ -103,12 +102,10 @@
struct dhcpc_state_internal struct dhcpc_state_internal
{ {
struct uip_udp_conn *conn; struct uip_udp_conn *conn;
struct dhcpc_state *result;
const void *mac_addr; const void *mac_addr;
int mac_len; int mac_len;
int sockfd; int sockfd;
uint16 ticks; char buffer[256];
char state;
}; };
struct dhcp_msg struct dhcp_msg
@ -183,28 +180,28 @@ static uint8 *add_end(uint8 *optptr)
return optptr; return optptr;
} }
static void create_msg(struct dhcpc_state_internal *pdhcpc, struct dhcp_msg *m) static void create_msg(struct dhcpc_state_internal *pdhcpc, struct dhcp_msg *pmsg)
{ {
m->op = DHCP_REQUEST; pmsg->op = DHCP_REQUEST;
m->htype = DHCP_HTYPE_ETHERNET; pmsg->htype = DHCP_HTYPE_ETHERNET;
m->hlen = pdhcpc->mac_len; pmsg->hlen = pdhcpc->mac_len;
m->hops = 0; pmsg->hops = 0;
memcpy(m->xid, xid, sizeof(m->xid)); memcpy(pmsg->xid, xid, sizeof(pmsg->xid));
m->secs = 0; pmsg->secs = 0;
m->flags = HTONS(BOOTP_BROADCAST); /* Broadcast bit. */ pmsg->flags = HTONS(BOOTP_BROADCAST); /* Broadcast bit. */
/* uip_ipaddr_copy(m->ciaddr, uip_hostaddr);*/ /* uip_ipaddr_copy(pmsg->ciaddr, uip_hostaddr);*/
memcpy(m->ciaddr, uip_hostaddr, sizeof(m->ciaddr)); memcpy(pmsg->ciaddr, uip_hostaddr, sizeof(pmsg->ciaddr));
memset(m->yiaddr, 0, sizeof(m->yiaddr)); memset(pmsg->yiaddr, 0, sizeof(pmsg->yiaddr));
memset(m->siaddr, 0, sizeof(m->siaddr)); memset(pmsg->siaddr, 0, sizeof(pmsg->siaddr));
memset(m->giaddr, 0, sizeof(m->giaddr)); memset(pmsg->giaddr, 0, sizeof(pmsg->giaddr));
memcpy(m->chaddr, pdhcpc->mac_addr, pdhcpc->mac_len); memcpy(pmsg->chaddr, pdhcpc->mac_addr, pdhcpc->mac_len);
memset(&m->chaddr[pdhcpc->mac_len], 0, sizeof(m->chaddr) - pdhcpc->mac_len); memset(&pmsg->chaddr[pdhcpc->mac_len], 0, sizeof(pmsg->chaddr) - pdhcpc->mac_len);
#ifndef CONFIG_NET_DHCP_LIGHT #ifndef CONFIG_NET_DHCP_LIGHT
memset(m->sname, 0, sizeof(m->sname)); memset(pmsg->sname, 0, sizeof(pmsg->sname));
memset(m->file, 0, sizeof(m->file)); memset(pmsg->file, 0, sizeof(pmsg->file));
#endif #endif
memcpy(m->options, magic_cookie, sizeof(magic_cookie)); memcpy(pmsg->options, magic_cookie, sizeof(magic_cookie));
} }
static int send_discover(struct dhcpc_state_internal *pdhcpc) static int send_discover(struct dhcpc_state_internal *pdhcpc)
@ -228,7 +225,7 @@ static int send_discover(struct dhcpc_state_internal *pdhcpc)
(struct sockaddr*)&addr, sizeof(struct sockaddr_in)); (struct sockaddr*)&addr, sizeof(struct sockaddr_in));
} }
static int send_request(struct dhcpc_state_internal *pdhcpc) static int send_request(struct dhcpc_state_internal *pdhcpc, struct dhcpc_state *presult)
{ {
struct dhcp_msg msg; struct dhcp_msg msg;
struct sockaddr_in addr; struct sockaddr_in addr;
@ -237,8 +234,8 @@ static int send_request(struct dhcpc_state_internal *pdhcpc)
create_msg(pdhcpc, &msg); create_msg(pdhcpc, &msg);
pend = add_msg_type(&msg.options[4], DHCPREQUEST); pend = add_msg_type(&msg.options[4], DHCPREQUEST);
pend = add_server_id(pdhcpc->result, pend); pend = add_server_id(presult, pend);
pend = add_req_ipaddr(pdhcpc->result, pend); pend = add_req_ipaddr(presult, pend);
pend = add_end(pend); pend = add_end(pend);
len = pend - (uint8*)&msg; len = pend - (uint8*)&msg;
@ -286,87 +283,156 @@ static uint8 parse_options(struct dhcpc_state *presult, uint8 *optptr, int len)
return type; return type;
} }
static uint8 parse_msg(struct dhcpc_state_internal *pdhcpc) static uint8 parse_msg(struct dhcpc_state_internal *pdhcpc, int buflen, struct dhcpc_state *presult)
{ {
struct dhcpc_state *presult = pdhcpc->result; struct dhcp_msg *pbuffer = (struct dhcp_msg *)pdhcpc->buffer;
struct dhcp_msg *m = (struct dhcp_msg *)uip_appdata;
if (m->op == DHCP_REPLY && if (pbuffer->op == DHCP_REPLY &&
memcmp(m->xid, xid, sizeof(xid)) == 0 && memcmp(pbuffer->xid, xid, sizeof(xid)) == 0 &&
memcmp(m->chaddr, pdhcpc->mac_addr, pdhcpc->mac_len) == 0) memcmp(pbuffer->chaddr, pdhcpc->mac_addr, pdhcpc->mac_len) == 0)
{ {
memcpy(presult->ipaddr, m->yiaddr, 4); memcpy(presult->ipaddr, pbuffer->yiaddr, 4);
return parse_options(presult, &m->options[4], uip_datalen()); return parse_options(presult, &pbuffer->options[4], buflen);
} }
return 0; return 0;
} }
static int handle_dhcp(struct dhcpc_state_internal *pdhcpc) /****************************************************************************
{ * Global Functions
struct dhcpc_state *presult = pdhcpc->result; ****************************************************************************/
restart: void *dhcpc_open(const void *mac_addr, int mac_len)
pdhcpc->state = STATE_SENDING; {
pdhcpc->ticks = CLOCK_SECOND; struct dhcpc_state_internal *pdhcpc;
struct sockaddr_in addr;
struct timeval tv;
/* Allocate an internal DHCP structure */
pdhcpc = (struct dhcpc_state_internal *)malloc(sizeof(struct dhcpc_state_internal));
if (pdhcpc)
{
/* Initialize the allocated structure */
memset(pdhcpc, 0, sizeof(struct dhcpc_state_internal));
pdhcpc->mac_addr = mac_addr;
pdhcpc->mac_len = mac_len;
/* Create a UDP socket */
pdhcpc->sockfd = socket(PF_INET, SOCK_DGRAM, 0);
if (pdhcpc->sockfd < 0)
{
free(pdhcpc);
return NULL;
}
/* bind the socket */
addr.sin_family = AF_INET;
addr.sin_port = HTONS(DHCPC_CLIENT_PORT);
addr.sin_addr.s_addr = INADDR_ANY;
if (bind(pdhcpc->sockfd, (struct sockaddr*)&addr, sizeof(struct sockaddr_in)) < 0)
{
close(pdhcpc->sockfd);
free(pdhcpc);
return NULL;
}
/* Configure for read timeouts */
tv.tv_sec = 30;
tv.tv_usec = 0;
if (setsockopt(pdhcpc->sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(struct timeval)) < 0)
{
close(pdhcpc->sockfd);
free(pdhcpc);
return NULL;
}
}
return (void*)pdhcpc;
}
void dhcpc_close(void *handle)
{
struct dchcpc_state_internal *pdhcpc = (struct dchcpc_state_internal *)handle;
if (pdhcpc)
{
free(pdhcpc);
}
}
int dhcpc_request(void *handle, struct dhcpc_state *presult)
{
struct dhcpc_state_internal *pdhcpc = (struct dhcpc_state_internal *)handle;
ssize_t result;
int state;
/* Loop until we receive the offer */
do
{
state = STATE_SENDING;
do do
{ {
/* Send the command */ /* Send the command */
send_discover(pdhcpc); if (send_discover(pdhcpc) < 0)
/* Set up a watchdog to timeout the recvfrom */
#warning need to implement timeout;
/* Wait for the response */
#warning need to use recvfrom
uip_event_timedwait(UIP_NEWDATA, CLOCK_SECOND);
if (uip_newdata() && parse_msg(pdhcpc) == DHCPOFFER)
{ {
pdhcpc->state = STATE_OFFER_RECEIVED; return ERROR;
break;
} }
if (pdhcpc->ticks < CLOCK_SECOND * 60) /* Get the response */
result = recv(pdhcpc->sockfd, pdhcpc->buffer, BUFFER_SIZE, 0);
if (result >= 0)
{ {
pdhcpc->ticks *= 2; if (parse_msg(pdhcpc, result, presult) == DHCPOFFER)
{
state = STATE_OFFER_RECEIVED;
} }
} }
while(pdhcpc->state != STATE_OFFER_RECEIVED); else if (*get_errno_ptr() != EAGAIN)
{
/* An error other than a timeout was received */
pdhcpc->ticks = CLOCK_SECOND; return ERROR;
}
}
while (state != STATE_OFFER_RECEIVED);
do do
{ {
/* Send the request */ /* Send the request */
send_request(pdhcpc); if (send_request(pdhcpc, presult) < 0)
/* Set up a watchdog to timeout the recvfrom */
#warning need to implement timeout;
/* Then wait to received the response */
#warning need to use recvfrom
uip_event_timedwait(UIP_NEWDATA, CLOCK_SECOND);
if (uip_newdata() && parse_msg(pdhcpc) == DHCPACK)
{ {
pdhcpc->state = STATE_CONFIG_RECEIVED; return ERROR;
break;
} }
if (pdhcpc->ticks <= CLOCK_SECOND * 10) /* Get the response */
result = recv(pdhcpc->sockfd, pdhcpc->buffer, BUFFER_SIZE, 0);
if (result >= 0)
{ {
pdhcpc->ticks += CLOCK_SECOND; if (parse_msg(pdhcpc, result, presult) == DHCPACK)
}
else
{ {
goto restart; state = STATE_CONFIG_RECEIVED;
} }
} }
while(pdhcpc->state != STATE_CONFIG_RECEIVED); else if (*get_errno_ptr() != EAGAIN)
{
/* An error other than a timeout was received */
return ERROR;
}
}
while (state != STATE_CONFIG_RECEIVED);
}
while(state != STATE_CONFIG_RECEIVED);
dbg("Got IP address %d.%d.%d.%d\n", dbg("Got IP address %d.%d.%d.%d\n",
uip_ipaddr1(presult->ipaddr), uip_ipaddr2(presult->ipaddr), uip_ipaddr1(presult->ipaddr), uip_ipaddr2(presult->ipaddr),
@ -384,74 +450,3 @@ restart:
ntohs(presult->lease_time[0])*65536ul + ntohs(presult->lease_time[1])); ntohs(presult->lease_time[0])*65536ul + ntohs(presult->lease_time[1]));
return OK; return OK;
} }
/****************************************************************************
* Global Functions
****************************************************************************/
void *dhcpc_open(const void *mac_addr, int mac_len)
{
struct dhcpc_state_internal *pdhcpc;
struct sockaddr_in addr;
/* Allocate an internal DHCP structure */
pdhcpc = (struct dhcpc_state_internal *)malloc(sizeof(struct dhcpc_state_internal));
if (pdhcpc)
{
/* Initialize the allocated structure */
memset(pdhcpc, 0, sizeof(struct dhcpc_state_internal));
pdhcpc->mac_addr = mac_addr;
pdhcpc->mac_len = mac_len;
pdhcpc->state = STATE_INITIAL;
/* Create a UDP socket */
pdhcpc->sockfd = socket(PF_INET, SOCK_DGRAM, 0);
if (pdhcpc->sockfd < 0)
{
free(pdhcpc);
pdhcpc = NULL;
}
else
{
/* bind the socket */
addr.sin_family = AF_INET;
addr.sin_port = HTONS(DHCPC_CLIENT_PORT);
addr.sin_addr.s_addr = INADDR_ANY;
if (bind(pdhcpc->sockfd, &addr, sizeof(struct sockaddr_in)) < 0)
{
free(pdhcpc);
pdhcpc = NULL;
}
}
}
return (void*)pdhcpc;
}
void dhcpc_close(void *handle)
{
struct dchcpc_state_internal *pdhcpc = (struct dchcpc_state_internal *)handle;
if (pdhcpc)
{
free(pdhcpc);
}
}
int dhcpc_request(void *handle, struct dhcpc_state *ds)
{
struct dhcpc_state_internal *pdhcpc = (struct dhcpc_state_internal *)handle;
uint16 ipaddr[2];
if (pdhcpc->state == STATE_INITIAL)
{
uip_ipaddr(ipaddr, 0,0,0,0);
uip_sethostaddr(ipaddr);
}
pdhcpc->result = ds;
return handle_dhcp(pdhcpc);
}

View File

@ -52,6 +52,9 @@
#include <sys/types.h> #include <sys/types.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#include <time.h>
#include <errno.h>
#include <debug.h> #include <debug.h>
#include <sys/socket.h> #include <sys/socket.h>
@ -341,10 +344,29 @@ int resolv_query(const char *name, struct sockaddr_in6 *addr)
int resolv_query(const char *name, struct sockaddr_in *addr) int resolv_query(const char *name, struct sockaddr_in *addr)
#endif #endif
{ {
int ret = send_query(name, addr); int retries;
if (ret == 0) int ret;
// Loop while receive timeout errors occur and there are remaining retries
for (retries = 0; retries < 3; retries++)
{ {
if (send_query(name, addr) < 0)
{
return ERROR;
}
ret = recv_response(addr); ret = recv_response(addr);
if (ret >= 0)
{
/* Response received successfully */
return OK;
}
else if (*get_errno_ptr() != EAGAIN)
{
/* Some failure other than receive timeout occurred */
return ERROR;
}
} }
return ret; return ret;
} }
@ -352,9 +374,9 @@ int resolv_query(const char *name, struct sockaddr_in *addr)
/* Obtain the currently configured DNS server. */ /* Obtain the currently configured DNS server. */
#ifdef CONFIG_NET_IPv6 #ifdef CONFIG_NET_IPv6
void resolv_getserver(const struct sockaddr_in6 *dnsserver) void resolv_getserver(struct sockaddr_in6 *dnsserver)
#else #else
void resolv_getserver(const struct sockaddr_in *dnsserver) void resolv_getserver(struct sockaddr_in *dnsserver)
#endif #endif
{ {
memcpy(dnsserver, &g_dnsserver, ADDRLEN); memcpy(dnsserver, &g_dnsserver, ADDRLEN);
@ -375,10 +397,23 @@ void resolv_conf(const struct sockaddr_in *dnsserver)
int resolv_init(void) int resolv_init(void)
{ {
struct timeval tv;
g_sockfd = socket(PF_INET, SOCK_DGRAM, 0); g_sockfd = socket(PF_INET, SOCK_DGRAM, 0);
if (g_sockfd < 0) if (g_sockfd < 0)
{ {
return ERROR; return ERROR;
} }
/* Set up a receive timeout */
tv.tv_sec = 30;
tv.tv_usec = 0;
if (setsockopt(g_sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(struct timeval)) < 0)
{
close(g_sockfd);
g_sockfd = -1;
return ERROR;
}
return OK; return OK;
} }