From 952db3328ff27679804d6fef75b06b3aa7781c86 Mon Sep 17 00:00:00 2001 From: patacongo Date: Sat, 8 Sep 2007 21:54:43 +0000 Subject: [PATCH] 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 --- ChangeLog | 3 +- Documentation/NuttX.html | 3 +- include/net/uip/dhcpc.h | 2 +- include/net/uip/resolv.h | 2 +- include/net/uip/uip.h | 3 +- net/recvfrom.c | 108 +++++++++---- net/sendto.c | 6 +- net/uip/uip-wait.c | 55 +------ netutils/dhcpc/dhcpc.c | 327 +++++++++++++++++++-------------------- netutils/resolv/resolv.c | 43 ++++- 10 files changed, 292 insertions(+), 260 deletions(-) diff --git a/ChangeLog b/ChangeLog index 41cdae7574..6f7555625a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -199,7 +199,7 @@ * examples/nsh/: Add cp, rm, rmdir, set, unset commands. echo will now print environment variables. -0.2.9 2007-xx-xx Gregory Nutt +0.3.0 2007-xx-xx Gregory Nutt * Imported uIP into the tree (see http://www.sics.se/~adam/uip/index.php/Main_Page) @@ -209,4 +209,5 @@ * Added recv() and recvfrom(). * Added getsockopt() and setsockopt() * Documentation updated to address socket interfaces. + * Implemented receive timeouts via setsockopt(SO_RCVTIMEO). diff --git a/Documentation/NuttX.html b/Documentation/NuttX.html index bd511e9407..5e997c711b 100644 --- a/Documentation/NuttX.html +++ b/Documentation/NuttX.html @@ -632,7 +632,7 @@ Other memory:
    -0.2.9 2007-xx-xx Gregory Nutt +0.3.0 2007-xx-xx Gregory Nutt * Imported uIP into the tree (see http://www.sics.se/~adam/uip/index.php/Main_Page) @@ -642,6 +642,7 @@ Other memory: * Added recv() and recvfrom(). * Added getsockopt() and setsockopt() * Documentation updated to address socket interfaces. + * Implemented receive timeouts via setsockopt(SO_RCVTIMEO).
diff --git a/include/net/uip/dhcpc.h b/include/net/uip/dhcpc.h index d1950c9b80..13b717e439 100644 --- a/include/net/uip/dhcpc.h +++ b/include/net/uip/dhcpc.h @@ -67,7 +67,7 @@ struct dhcpc_state ****************************************************************************/ 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); #endif /* NET_UIP_DHCP_H__ */ diff --git a/include/net/uip/resolv.h b/include/net/uip/resolv.h index 1f22012b55..c9547f13ed 100644 --- a/include/net/uip/resolv.h +++ b/include/net/uip/resolv.h @@ -54,7 +54,7 @@ EXTERN void resolv_getserver(const struct sockaddr_in6 *dnsserver); EXTERN int resolv_query(const char *name, struct sockaddr_in6 *addr); #else 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); #endif diff --git a/include/net/uip/uip.h b/include/net/uip/uip.h index 004c0ec6e5..fe2088b2ca 100644 --- a/include/net/uip/uip.h +++ b/include/net/uip/uip.h @@ -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 */ -#define uip_event_wait(waitflags) uip_event_timedwait(waitflags,0) -extern int uip_event_timedwait(uint16 waitflags, int timeout); +extern int uip_event_wait(uint16 waitflags); /* This function is called from uip_interrupt() to wake up any * waiting threads/tasks. diff --git a/net/recvfrom.c b/net/recvfrom.c index d6d8b4aca3..d008262bf8 100644 --- a/net/recvfrom.c +++ b/net/recvfrom.c @@ -58,9 +58,15 @@ struct recvfrom_s { - sem_t rf_sem; - uint16 rf_buflen; - char * rf_buffer; +#if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK) + FAR struct socket *rf_sock /* The parent socket structure */ +#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,38 +78,61 @@ void recvfrom_interrupt(void *private) struct recvfrom_s *pstate = (struct recvfrom_s *)private; size_t recvlen; - /* If new data is available and we are correctly intialized, then complete - * the read action. We could also check for POLL events here in order to - * implement SO_RECVTIMEO. - */ + /* 'private' might be null in some race conditions (?) */ - if (uip_newdata() && private) + if (pstate) { - /* Get the length of the data to return */ - if (uip_len > pstate-> rf_buflen) + /* If new data is available, then complete the read action. */ + + if (uip_newdata()) { - recvlen = pstate-> rf_buflen; - } - else - { - recvlen = uip_len; + /* Get the length of the data to return */ + if (uip_len > pstate-> rf_buflen) + { + recvlen = pstate-> rf_buflen; + } + else + { + recvlen = uip_len; + } + + /* Copy the appdate into the user data and send it */ + + memcpy(pstate->rf_buffer, uip_appdata, recvlen); + + /* Don't allow any further call backs. */ + + uip_conn->private = NULL; + uip_conn->callback = NULL; + + /* Wake up the waiting thread, returning the number of bytes + * actually read. + */ + + pstate->rf_buflen = recvlen; + sem_post(&pstate-> rf_sem); } - /* Copy the appdate into the user data and send it */ - - memcpy(pstate->rf_buffer, uip_appdata, recvlen); - - /* Don't allow any further call backs. */ - - uip_conn->private = NULL; - uip_conn->callback = NULL; - - /* Wake up the waiting thread, returning the number of bytes - * actually read. + /* No data has been received. If this is a poll event, then check + * for a timeout. */ - pstate->rf_buflen = recvlen; - sem_post(&pstate-> rf_sem); +#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_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 */ 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); 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 * 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 state.rf_buflen; #warning "Needs to return server address" + return state.rf_buflen; + #else err = ENOSYS; #endif diff --git a/net/sendto.c b/net/sendto.c index 1917ebf58d..eef1a31b4e 100644 --- a/net/sendto.c +++ b/net/sendto.c @@ -58,9 +58,9 @@ struct sendto_s { - sem_t st_sem; - uint16 st_buflen; - const char *st_buffer; + 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 */ }; /**************************************************************************** diff --git a/net/uip/uip-wait.c b/net/uip/uip-wait.c index c7bf0a1bb2..14775f54e3 100644 --- a/net/uip/uip-wait.c +++ b/net/uip/uip-wait.c @@ -39,7 +39,6 @@ #include #include -#include #include #include @@ -63,31 +62,18 @@ static uint16 uip_waitflags = 0; /* UIP flags to wait for */ * 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 ************************************************************/ /* 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 * uip_event_signal(). */ irqstate_t save = irqsave(); - WDOG_ID wdog; /* At present, we support only a single waiter. If uip_waitflags * 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; - /* Was a timeut requested as well? */ - - 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 */ + /* Wait for the event to occur */ if (sem_wait(&uip_waitsem) != 0) { - goto errout_with_watchdog; - } - - /* We no longer need the watchdog */ - - if (wdog) - { - wd_delete(wdog); - wdog = NULL; + goto errout_with_irqdisabled; } } irqrestore(save); return OK; -errout_with_watchdog: - if (wdog) - { - wd_delete(wdog); - } - errout_with_irqdisabled: irqrestore(save); return ERROR; diff --git a/netutils/dhcpc/dhcpc.c b/netutils/dhcpc/dhcpc.c index 1e11ae079c..9c90fb8a8c 100644 --- a/netutils/dhcpc/dhcpc.c +++ b/netutils/dhcpc/dhcpc.c @@ -43,13 +43,14 @@ ****************************************************************************/ #include +#include + #include #include -#include -#include +#include #include +#include #include -#include #include #include @@ -58,10 +59,6 @@ * Definitions ****************************************************************************/ -/* CLK_TCK is the frequency of the system clock (typically 100Hz) */ - -#define CLOCK_SECOND CLK_TCK - #define STATE_INITIAL 0 #define STATE_SENDING 1 #define STATE_OFFER_RECEIVED 2 @@ -96,6 +93,8 @@ #define DHCP_OPTION_REQ_LIST 55 #define DHCP_OPTION_END 255 +#define BUFFER_SIZE 256 + /**************************************************************************** * Private Types ****************************************************************************/ @@ -103,12 +102,10 @@ struct dhcpc_state_internal { struct uip_udp_conn *conn; - struct dhcpc_state *result; const void *mac_addr; int mac_len; int sockfd; - uint16 ticks; - char state; + char buffer[256]; }; struct dhcp_msg @@ -183,28 +180,28 @@ static uint8 *add_end(uint8 *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; - m->htype = DHCP_HTYPE_ETHERNET; - m->hlen = pdhcpc->mac_len; - m->hops = 0; - memcpy(m->xid, xid, sizeof(m->xid)); - m->secs = 0; - m->flags = HTONS(BOOTP_BROADCAST); /* Broadcast bit. */ - /* uip_ipaddr_copy(m->ciaddr, uip_hostaddr);*/ - memcpy(m->ciaddr, uip_hostaddr, sizeof(m->ciaddr)); - memset(m->yiaddr, 0, sizeof(m->yiaddr)); - memset(m->siaddr, 0, sizeof(m->siaddr)); - memset(m->giaddr, 0, sizeof(m->giaddr)); - memcpy(m->chaddr, pdhcpc->mac_addr, pdhcpc->mac_len); - memset(&m->chaddr[pdhcpc->mac_len], 0, sizeof(m->chaddr) - pdhcpc->mac_len); + pmsg->op = DHCP_REQUEST; + pmsg->htype = DHCP_HTYPE_ETHERNET; + pmsg->hlen = pdhcpc->mac_len; + pmsg->hops = 0; + memcpy(pmsg->xid, xid, sizeof(pmsg->xid)); + pmsg->secs = 0; + pmsg->flags = HTONS(BOOTP_BROADCAST); /* Broadcast bit. */ + /* uip_ipaddr_copy(pmsg->ciaddr, uip_hostaddr);*/ + memcpy(pmsg->ciaddr, uip_hostaddr, sizeof(pmsg->ciaddr)); + memset(pmsg->yiaddr, 0, sizeof(pmsg->yiaddr)); + memset(pmsg->siaddr, 0, sizeof(pmsg->siaddr)); + memset(pmsg->giaddr, 0, sizeof(pmsg->giaddr)); + memcpy(pmsg->chaddr, pdhcpc->mac_addr, pdhcpc->mac_len); + memset(&pmsg->chaddr[pdhcpc->mac_len], 0, sizeof(pmsg->chaddr) - pdhcpc->mac_len); #ifndef CONFIG_NET_DHCP_LIGHT - memset(m->sname, 0, sizeof(m->sname)); - memset(m->file, 0, sizeof(m->file)); + memset(pmsg->sname, 0, sizeof(pmsg->sname)); + memset(pmsg->file, 0, sizeof(pmsg->file)); #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) @@ -228,7 +225,7 @@ static int send_discover(struct dhcpc_state_internal *pdhcpc) (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 sockaddr_in addr; @@ -237,8 +234,8 @@ static int send_request(struct dhcpc_state_internal *pdhcpc) create_msg(pdhcpc, &msg); pend = add_msg_type(&msg.options[4], DHCPREQUEST); - pend = add_server_id(pdhcpc->result, pend); - pend = add_req_ipaddr(pdhcpc->result, pend); + pend = add_server_id(presult, pend); + pend = add_req_ipaddr(presult, pend); pend = add_end(pend); len = pend - (uint8*)&msg; @@ -286,87 +283,156 @@ static uint8 parse_options(struct dhcpc_state *presult, uint8 *optptr, int len) 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 *m = (struct dhcp_msg *)uip_appdata; + struct dhcp_msg *pbuffer = (struct dhcp_msg *)pdhcpc->buffer; - if (m->op == DHCP_REPLY && - memcmp(m->xid, xid, sizeof(xid)) == 0 && - memcmp(m->chaddr, pdhcpc->mac_addr, pdhcpc->mac_len) == 0) + if (pbuffer->op == DHCP_REPLY && + memcmp(pbuffer->xid, xid, sizeof(xid)) == 0 && + memcmp(pbuffer->chaddr, pdhcpc->mac_addr, pdhcpc->mac_len) == 0) { - memcpy(presult->ipaddr, m->yiaddr, 4); - return parse_options(presult, &m->options[4], uip_datalen()); + memcpy(presult->ipaddr, pbuffer->yiaddr, 4); + return parse_options(presult, &pbuffer->options[4], buflen); } return 0; } -static int handle_dhcp(struct dhcpc_state_internal *pdhcpc) +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +void *dhcpc_open(const void *mac_addr, int mac_len) { - struct dhcpc_state *presult = pdhcpc->result; + struct dhcpc_state_internal *pdhcpc; + struct sockaddr_in addr; + struct timeval tv; -restart: - pdhcpc->state = STATE_SENDING; - pdhcpc->ticks = CLOCK_SECOND; + /* 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 { - /* Send the command */ + state = STATE_SENDING; - send_discover(pdhcpc); - - /* 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) + do { - pdhcpc->state = STATE_OFFER_RECEIVED; - break; - } + /* Send the command */ - if (pdhcpc->ticks < CLOCK_SECOND * 60) - { - pdhcpc->ticks *= 2; + if (send_discover(pdhcpc) < 0) + { + return ERROR; + } + + /* Get the response */ + + result = recv(pdhcpc->sockfd, pdhcpc->buffer, BUFFER_SIZE, 0); + if (result >= 0) + { + if (parse_msg(pdhcpc, result, presult) == DHCPOFFER) + { + state = STATE_OFFER_RECEIVED; + } + } + else if (*get_errno_ptr() != EAGAIN) + { + /* An error other than a timeout was received */ + + return ERROR; + } } + while (state != STATE_OFFER_RECEIVED); + + do + { + /* Send the request */ + + if (send_request(pdhcpc, presult) < 0) + { + return ERROR; + } + + /* Get the response */ + + result = recv(pdhcpc->sockfd, pdhcpc->buffer, BUFFER_SIZE, 0); + if (result >= 0) + { + if (parse_msg(pdhcpc, result, presult) == DHCPACK) + { + 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(pdhcpc->state != STATE_OFFER_RECEIVED); - - pdhcpc->ticks = CLOCK_SECOND; - - do - { - /* Send the request */ - - send_request(pdhcpc); - - /* 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; - break; - } - - if (pdhcpc->ticks <= CLOCK_SECOND * 10) - { - pdhcpc->ticks += CLOCK_SECOND; - } - else - { - goto restart; - } - } - while(pdhcpc->state != STATE_CONFIG_RECEIVED); + while(state != STATE_CONFIG_RECEIVED); dbg("Got IP address %d.%d.%d.%d\n", uip_ipaddr1(presult->ipaddr), uip_ipaddr2(presult->ipaddr), @@ -384,74 +450,3 @@ restart: ntohs(presult->lease_time[0])*65536ul + ntohs(presult->lease_time[1])); 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); -} diff --git a/netutils/resolv/resolv.c b/netutils/resolv/resolv.c index b6c861e517..b318e551ee 100644 --- a/netutils/resolv/resolv.c +++ b/netutils/resolv/resolv.c @@ -52,6 +52,9 @@ #include #include +#include +#include +#include #include #include @@ -341,10 +344,29 @@ int resolv_query(const char *name, struct sockaddr_in6 *addr) int resolv_query(const char *name, struct sockaddr_in *addr) #endif { - int ret = send_query(name, addr); - if (ret == 0) + int retries; + 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); + 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; } @@ -352,9 +374,9 @@ int resolv_query(const char *name, struct sockaddr_in *addr) /* Obtain the currently configured DNS server. */ #ifdef CONFIG_NET_IPv6 -void resolv_getserver(const struct sockaddr_in6 *dnsserver) +void resolv_getserver(struct sockaddr_in6 *dnsserver) #else -void resolv_getserver(const struct sockaddr_in *dnsserver) +void resolv_getserver(struct sockaddr_in *dnsserver) #endif { memcpy(dnsserver, &g_dnsserver, ADDRLEN); @@ -375,10 +397,23 @@ void resolv_conf(const struct sockaddr_in *dnsserver) int resolv_init(void) { + struct timeval tv; g_sockfd = socket(PF_INET, SOCK_DGRAM, 0); if (g_sockfd < 0) { 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; }