summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--nuttx/ChangeLog3
-rw-r--r--nuttx/Documentation/NuttX.html3
-rw-r--r--nuttx/include/net/uip/dhcpc.h2
-rw-r--r--nuttx/include/net/uip/resolv.h2
-rw-r--r--nuttx/include/net/uip/uip.h3
-rw-r--r--nuttx/net/recvfrom.c102
-rw-r--r--nuttx/net/sendto.c6
-rw-r--r--nuttx/net/uip/uip-wait.c55
-rw-r--r--nuttx/netutils/dhcpc/dhcpc.c279
-rw-r--r--nuttx/netutils/resolv/resolv.c43
10 files changed, 265 insertions, 233 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog
index 41cdae757..6f7555625 100644
--- a/nuttx/ChangeLog
+++ b/nuttx/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 <spudmonkey@racsa.co.cr>
+0.3.0 2007-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr>
* 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/nuttx/Documentation/NuttX.html b/nuttx/Documentation/NuttX.html
index bd511e940..5e997c711 100644
--- a/nuttx/Documentation/NuttX.html
+++ b/nuttx/Documentation/NuttX.html
@@ -632,7 +632,7 @@ Other memory:
</table>
<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
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).
</pre></ul>
<table width ="100%">
diff --git a/nuttx/include/net/uip/dhcpc.h b/nuttx/include/net/uip/dhcpc.h
index d1950c9b8..13b717e43 100644
--- a/nuttx/include/net/uip/dhcpc.h
+++ b/nuttx/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/nuttx/include/net/uip/resolv.h b/nuttx/include/net/uip/resolv.h
index 1f22012b5..c9547f13e 100644
--- a/nuttx/include/net/uip/resolv.h
+++ b/nuttx/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/nuttx/include/net/uip/uip.h b/nuttx/include/net/uip/uip.h
index 004c0ec6e..fe2088b2c 100644
--- a/nuttx/include/net/uip/uip.h
+++ b/nuttx/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/nuttx/net/recvfrom.c b/nuttx/net/recvfrom.c
index d6d8b4aca..d008262bf 100644
--- a/nuttx/net/recvfrom.c
+++ b/nuttx/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)
- {
- recvlen = pstate-> rf_buflen;
- }
- else
+ /* If new data is available, then complete the read action. */
+
+ if (uip_newdata())
{
- 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 */
- /* Copy the appdate into the user data and send it */
+ memcpy(pstate->rf_buffer, uip_appdata, recvlen);
- memcpy(pstate->rf_buffer, uip_appdata, recvlen);
+ /* Don't allow any further call backs. */
- /* Don't allow any further call backs. */
+ uip_conn->private = NULL;
+ uip_conn->callback = NULL;
- uip_conn->private = NULL;
- uip_conn->callback = NULL;
+ /* Wake up the waiting thread, returning the number of bytes
+ * actually read.
+ */
- /* Wake up the waiting thread, returning the number of bytes
- * actually read.
+ pstate->rf_buflen = recvlen;
+ sem_post(&pstate-> rf_sem);
+ }
+
+ /* 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/nuttx/net/sendto.c b/nuttx/net/sendto.c
index 1917ebf58..eef1a31b4 100644
--- a/nuttx/net/sendto.c
+++ b/nuttx/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/nuttx/net/uip/uip-wait.c b/nuttx/net/uip/uip-wait.c
index c7bf0a1bb..14775f54e 100644
--- a/nuttx/net/uip/uip-wait.c
+++ b/nuttx/net/uip/uip-wait.c
@@ -39,7 +39,6 @@
#include <nuttx/config.h>
#include <semaphore.h>
-#include <wdog.h>
#include <arch/irq.h>
#include <net/uip/uip.h>
@@ -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/nuttx/netutils/dhcpc/dhcpc.c b/nuttx/netutils/dhcpc/dhcpc.c
index 1e11ae079..9c90fb8a8 100644
--- a/nuttx/netutils/dhcpc/dhcpc.c
+++ b/nuttx/netutils/dhcpc/dhcpc.c
@@ -43,13 +43,14 @@
****************************************************************************/
#include <sys/types.h>
+#include <sys/socket.h>
+
#include <stdlib.h>
#include <string.h>
-#include <pthread.h>
-#include <semaphore.h>
+#include <unistd.h>
#include <time.h>
+#include <errno.h>
#include <debug.h>
-#include <sys/socket.h>
#include <net/uip/uip.h>
#include <net/uip/dhcpc.h>
@@ -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,105 +283,20 @@ 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)
-{
- struct dhcpc_state *presult = pdhcpc->result;
-
-restart:
- pdhcpc->state = STATE_SENDING;
- pdhcpc->ticks = CLOCK_SECOND;
-
- do
- {
- /* Send the command */
-
- 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)
- {
- pdhcpc->state = STATE_OFFER_RECEIVED;
- break;
- }
-
- if (pdhcpc->ticks < CLOCK_SECOND * 60)
- {
- pdhcpc->ticks *= 2;
- }
- }
- 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);
-
- dbg("Got IP address %d.%d.%d.%d\n",
- uip_ipaddr1(presult->ipaddr), uip_ipaddr2(presult->ipaddr),
- uip_ipaddr3(presult->ipaddr), uip_ipaddr4(presult->ipaddr));
- dbg("Got netmask %d.%d.%d.%d\n",
- uip_ipaddr1(presult->netmask), uip_ipaddr2(presult->netmask),
- uip_ipaddr3(presult->netmask), uip_ipaddr4(presult->netmask));
- dbg("Got DNS server %d.%d.%d.%d\n",
- uip_ipaddr1(presult->dnsaddr), uip_ipaddr2(presult->dnsaddr),
- uip_ipaddr3(presult->dnsaddr), uip_ipaddr4(presult->dnsaddr));
- dbg("Got default router %d.%d.%d.%d\n",
- uip_ipaddr1(presult->default_router), uip_ipaddr2(presult->default_router),
- uip_ipaddr3(presult->default_router), uip_ipaddr4(presult->default_router));
- dbg("Lease expires in %ld seconds\n",
- ntohs(presult->lease_time[0])*65536ul + ntohs(presult->lease_time[1]));
- return OK;
-}
-
/****************************************************************************
* Global Functions
****************************************************************************/
@@ -393,6 +305,7 @@ void *dhcpc_open(const void *mac_addr, int mac_len)
{
struct dhcpc_state_internal *pdhcpc;
struct sockaddr_in addr;
+ struct timeval tv;
/* Allocate an internal DHCP structure */
@@ -404,7 +317,6 @@ void *dhcpc_open(const void *mac_addr, int mac_len)
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 */
@@ -412,23 +324,34 @@ void *dhcpc_open(const void *mac_addr, int mac_len)
if (pdhcpc->sockfd < 0)
{
free(pdhcpc);
- pdhcpc = NULL;
+ return 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, (struct sockaddr*)&addr, sizeof(struct sockaddr_in)) < 0)
{
- /* bind the socket */
+ close(pdhcpc->sockfd);
+ free(pdhcpc);
+ return NULL;
+ }
- addr.sin_family = AF_INET;
- addr.sin_port = HTONS(DHCPC_CLIENT_PORT);
- addr.sin_addr.s_addr = INADDR_ANY;
+ /* Configure for read timeouts */
- if (bind(pdhcpc->sockfd, &addr, sizeof(struct sockaddr_in)) < 0)
- {
- free(pdhcpc);
- pdhcpc = NULL;
- }
+ 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;
}
@@ -441,17 +364,89 @@ void dhcpc_close(void *handle)
}
}
-int dhcpc_request(void *handle, struct dhcpc_state *ds)
+int dhcpc_request(void *handle, struct dhcpc_state *presult)
{
struct dhcpc_state_internal *pdhcpc = (struct dhcpc_state_internal *)handle;
- uint16 ipaddr[2];
+ ssize_t result;
+ int state;
- if (pdhcpc->state == STATE_INITIAL)
+ /* Loop until we receive the offer */
+
+ do
{
- uip_ipaddr(ipaddr, 0,0,0,0);
- uip_sethostaddr(ipaddr);
+ state = STATE_SENDING;
+
+ do
+ {
+ /* Send the command */
+
+ 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(state != STATE_CONFIG_RECEIVED);
- pdhcpc->result = ds;
- return handle_dhcp(pdhcpc);
+ dbg("Got IP address %d.%d.%d.%d\n",
+ uip_ipaddr1(presult->ipaddr), uip_ipaddr2(presult->ipaddr),
+ uip_ipaddr3(presult->ipaddr), uip_ipaddr4(presult->ipaddr));
+ dbg("Got netmask %d.%d.%d.%d\n",
+ uip_ipaddr1(presult->netmask), uip_ipaddr2(presult->netmask),
+ uip_ipaddr3(presult->netmask), uip_ipaddr4(presult->netmask));
+ dbg("Got DNS server %d.%d.%d.%d\n",
+ uip_ipaddr1(presult->dnsaddr), uip_ipaddr2(presult->dnsaddr),
+ uip_ipaddr3(presult->dnsaddr), uip_ipaddr4(presult->dnsaddr));
+ dbg("Got default router %d.%d.%d.%d\n",
+ uip_ipaddr1(presult->default_router), uip_ipaddr2(presult->default_router),
+ uip_ipaddr3(presult->default_router), uip_ipaddr4(presult->default_router));
+ dbg("Lease expires in %ld seconds\n",
+ ntohs(presult->lease_time[0])*65536ul + ntohs(presult->lease_time[1]));
+ return OK;
}
diff --git a/nuttx/netutils/resolv/resolv.c b/nuttx/netutils/resolv/resolv.c
index b6c861e51..b318e551e 100644
--- a/nuttx/netutils/resolv/resolv.c
+++ b/nuttx/netutils/resolv/resolv.c
@@ -52,6 +52,9 @@
#include <sys/types.h>
#include <string.h>
+#include <unistd.h>
+#include <time.h>
+#include <errno.h>
#include <debug.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)
#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;
}