summaryrefslogtreecommitdiff
path: root/nuttx/netutils
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2007-09-08 21:54:43 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2007-09-08 21:54:43 +0000
commit255e1fe83691a2c5a3328bcec13e2bce0a140696 (patch)
tree9868873a70e46df85e9ec0cf7c599239808b8808 /nuttx/netutils
parentb084f0f30622b823a1cb99324505aaca673ccef1 (diff)
downloadpx4-nuttx-255e1fe83691a2c5a3328bcec13e2bce0a140696.tar.gz
px4-nuttx-255e1fe83691a2c5a3328bcec13e2bce0a140696.tar.bz2
px4-nuttx-255e1fe83691a2c5a3328bcec13e2bce0a140696.zip
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
Diffstat (limited to 'nuttx/netutils')
-rw-r--r--nuttx/netutils/dhcpc/dhcpc.c279
-rw-r--r--nuttx/netutils/resolv/resolv.c43
2 files changed, 176 insertions, 146 deletions
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;
}