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:
parent
09d6450ab3
commit
952db3328f
@ -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).
|
||||
|
||||
|
@ -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%">
|
||||
|
@ -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__ */
|
||||
|
@ -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
|
||||
|
||||
|
@ -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.
|
||||
|
108
net/recvfrom.c
108
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
|
||||
|
@ -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 */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -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;
|
||||
|
@ -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,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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user