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
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).

View File

@ -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%">

View File

@ -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__ */

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);
#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

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 */
#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.

View File

@ -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

View File

@ -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 */
};
/****************************************************************************

View File

@ -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;

View File

@ -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);
}

View File

@ -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;
}