sendto needs to return EINTR error; dccpc uses sendto
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@330 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
parent
4f3ecdd85a
commit
8c0ce78863
|
@ -12,6 +12,7 @@
|
|||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
|
@ -66,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);
|
||||
void dhcpc_close(void *handle);
|
||||
int dhcpc_request(void *handle, struct dhcpc_state *ds);
|
||||
void dhcpc_close(void *handle);
|
||||
|
||||
#endif /* NET_UIP_DHCP_H__ */
|
||||
|
|
|
@ -932,10 +932,11 @@ extern int uip_udpconnect(struct uip_udp_conn *conn, const struct sockaddr_in *a
|
|||
* addr3 The forth octet of the IP address.
|
||||
*/
|
||||
|
||||
#define uip_ipaddr(addr, addr0,addr1,addr2,addr3) do { \
|
||||
((uint16 *)(addr))[0] = HTONS(((addr0) << 8) | (addr1)); \
|
||||
((uint16 *)(addr))[1] = HTONS(((addr2) << 8) | (addr3)); \
|
||||
} while(0)
|
||||
#define uip_ipaddr(addr, addr0, addr1, addr2, addr3) \
|
||||
do { \
|
||||
((uint16 *)(addr))[0] = HTONS(((addr0) << 8) | (addr1)); \
|
||||
((uint16 *)(addr))[1] = HTONS(((addr2) << 8) | (addr3)); \
|
||||
} while(0)
|
||||
|
||||
/* Construct an IPv6 address from eight 16-bit words.
|
||||
*
|
||||
|
|
|
@ -72,6 +72,11 @@ 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.
|
||||
*/
|
||||
|
||||
if (uip_newdata() && private)
|
||||
{
|
||||
/* Get the length of the data to return */
|
||||
|
@ -88,12 +93,14 @@ void recvfrom_interrupt(void *private)
|
|||
|
||||
memcpy(pstate->rf_buffer, uip_appdata, recvlen);
|
||||
|
||||
/* Don't allow any furhter call backs. */
|
||||
/* Don't allow any further call backs. */
|
||||
|
||||
uip_conn->private = NULL;
|
||||
uip_conn->callback = NULL;
|
||||
|
||||
/* Wake up the waiting thread */
|
||||
/* Wake up the waiting thread, returning the number of bytes
|
||||
* actually read.
|
||||
*/
|
||||
|
||||
pstate->rf_buflen = recvlen;
|
||||
sem_post(&pstate-> rf_sem);
|
||||
|
@ -202,7 +209,7 @@ ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *
|
|||
|
||||
save = irqsave();
|
||||
memset(&state, 0, sizeof(struct recvfrom_s));
|
||||
sem_init(&state. rf_sem, 0, 0);
|
||||
(void)sem_init(&state. rf_sem, 0, 0); /* Doesn't really fail */
|
||||
state. rf_buflen = len;
|
||||
state. rf_buffer = buf;
|
||||
|
||||
|
@ -221,10 +228,31 @@ ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *
|
|||
udp_conn = (struct uip_udp_conn *)psock->s_conn;
|
||||
udp_conn->private = (void*)&state;
|
||||
udp_conn->callback = recvfrom_interrupt;
|
||||
|
||||
/* Wait for either the read to complete: NOTES: (1) sem_wait will also
|
||||
* terminate if a signal is received, (2) interrupts are disabled! They
|
||||
* will be re-enabled while the task sleeps and automatically re-enabled
|
||||
* when the task restarts.
|
||||
*/
|
||||
|
||||
ret = sem_wait(&state. rf_sem);
|
||||
|
||||
/* Make sure that no further interrupts are processed */
|
||||
|
||||
uip_conn->private = NULL;
|
||||
uip_conn->callback = NULL;
|
||||
sem_destroy(&state. rf_sem);
|
||||
irqrestore(save);
|
||||
|
||||
sem_wait(&state. rf_sem);
|
||||
sem_destroy(&state. rf_sem);
|
||||
/* If sem_wait failed, then we were probably reawakened by a signal. In
|
||||
* this case, sem_wait will have set errno appropriately.
|
||||
*/
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
return state.rf_buflen;
|
||||
#warning "Needs to return server address"
|
||||
#else
|
||||
|
|
|
@ -154,7 +154,9 @@ const uip_ipaddr_t uip_netmask =
|
|||
{HTONS((UIP_NETMASK0 << 8) | UIP_NETMASK1),
|
||||
HTONS((UIP_NETMASK2 << 8) | UIP_NETMASK3)};
|
||||
#else
|
||||
uip_ipaddr_t uip_hostaddr, uip_draddr, uip_netmask;
|
||||
uip_ipaddr_t uip_hostaddr;
|
||||
uip_ipaddr_t uip_draddr;
|
||||
uip_ipaddr_t uip_netmask;
|
||||
#endif /* UIP_FIXEDADDR */
|
||||
|
||||
#ifndef CONFIG_NET_EXTERNAL_BUFFER
|
||||
|
@ -179,12 +181,13 @@ uint16 uip_flags; /* The uip_flags variable is used for communica
|
|||
struct uip_conn *uip_conn; /* uip_conn always points to the current connection. */
|
||||
|
||||
uint16 uip_listenports[UIP_LISTENPORTS];
|
||||
/* The uip_listenports list all currently listning ports. */
|
||||
/* The uip_listenports list all currently listening ports. */
|
||||
#ifdef CONFIG_NET_UDP
|
||||
struct uip_udp_conn *uip_udp_conn;
|
||||
#endif /* CONFIG_NET_UDP */
|
||||
|
||||
/* Temporary variables. */
|
||||
|
||||
uint8 uip_acc32[4];
|
||||
|
||||
#if UIP_STATISTICS == 1
|
||||
|
@ -223,7 +226,9 @@ static uint16 ipid; /* Ths ipid variable is an increasing number th
|
|||
* used for the IP ID field. */
|
||||
|
||||
/* Temporary variables. */
|
||||
static uint8 c, opt;
|
||||
|
||||
static uint8 c;
|
||||
static uint8 opt;
|
||||
static uint16 tmp16;
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -1472,14 +1477,16 @@ tcp_send_synack:
|
|||
if (uip_flags & UIP_ACKDATA)
|
||||
{
|
||||
uip_connr->tcpstateflags = UIP_ESTABLISHED;
|
||||
uip_flags = UIP_CONNECTED;
|
||||
uip_connr->len = 0;
|
||||
uip_flags = UIP_CONNECTED;
|
||||
uip_connr->len = 0;
|
||||
|
||||
if (uip_len > 0)
|
||||
{
|
||||
uip_flags |= UIP_NEWDATA;
|
||||
uip_flags |= UIP_NEWDATA;
|
||||
uip_add_rcv_nxt(uip_len);
|
||||
}
|
||||
uip_slen = 0;
|
||||
|
||||
uip_slen = 0;
|
||||
uip_tcp_callback();
|
||||
goto appsend;
|
||||
}
|
||||
|
@ -1535,6 +1542,7 @@ tcp_send_synack:
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
uip_connr->tcpstateflags = UIP_ESTABLISHED;
|
||||
uip_connr->rcv_nxt[0] = BUF->seqno[0];
|
||||
uip_connr->rcv_nxt[1] = BUF->seqno[1];
|
||||
|
@ -1575,12 +1583,15 @@ tcp_send_synack:
|
|||
{
|
||||
goto drop;
|
||||
}
|
||||
|
||||
uip_add_rcv_nxt(1 + uip_len);
|
||||
uip_flags |= UIP_CLOSE;
|
||||
|
||||
if (uip_len > 0)
|
||||
{
|
||||
uip_flags |= UIP_NEWDATA;
|
||||
}
|
||||
|
||||
uip_tcp_callback();
|
||||
uip_connr->len = 1;
|
||||
uip_connr->tcpstateflags = UIP_LAST_ACK;
|
||||
|
@ -1781,6 +1792,7 @@ tcp_send_synack:
|
|||
{
|
||||
uip_connr->tcpstateflags = UIP_CLOSING;
|
||||
}
|
||||
|
||||
uip_add_rcv_nxt(1);
|
||||
uip_flags = UIP_CLOSE;
|
||||
uip_tcp_callback();
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include <semaphore.h>
|
||||
#include <time.h>
|
||||
#include <debug.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <net/uip/uip.h>
|
||||
#include <net/uip/dhcpc.h>
|
||||
|
@ -101,39 +102,42 @@
|
|||
|
||||
struct dhcpc_state_internal
|
||||
{
|
||||
char state;
|
||||
sem_t sem;
|
||||
struct uip_udp_conn *conn;
|
||||
uint16 ticks;
|
||||
const void *mac_addr;
|
||||
int mac_len;
|
||||
struct dhcpc_state *result;
|
||||
struct dhcpc_state *result;
|
||||
const void *mac_addr;
|
||||
int mac_len;
|
||||
int sockfd;
|
||||
uint16 ticks;
|
||||
char state;
|
||||
};
|
||||
|
||||
struct dhcp_msg
|
||||
{
|
||||
uint8 op, htype, hlen, hops;
|
||||
uint8 xid[4];
|
||||
uint16 secs, flags;
|
||||
uint8 ciaddr[4];
|
||||
uint8 yiaddr[4];
|
||||
uint8 siaddr[4];
|
||||
uint8 giaddr[4];
|
||||
uint8 chaddr[16];
|
||||
uint8 op;
|
||||
uint8 htype;
|
||||
uint8 hlen;
|
||||
uint8 hops;
|
||||
uint8 xid[4];
|
||||
uint16 secs;
|
||||
uint16 flags;
|
||||
uint8 ciaddr[4];
|
||||
uint8 yiaddr[4];
|
||||
uint8 siaddr[4];
|
||||
uint8 giaddr[4];
|
||||
uint8 chaddr[16];
|
||||
#ifndef CONFIG_NET_DHCP_LIGHT
|
||||
uint8 sname[64];
|
||||
uint8 file[128];
|
||||
uint8 sname[64];
|
||||
uint8 file[128];
|
||||
#endif
|
||||
uint8 options[312];
|
||||
uint8 options[312];
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static const uint8 xid[4] = {0xad, 0xde, 0x12, 0x23};
|
||||
static const uint8 xid[4] = {0xad, 0xde, 0x12, 0x23};
|
||||
static const uint8 magic_cookie[4] = {99, 130, 83, 99};
|
||||
static volatile struct dhcpc_state_internal *gpdhcpc;
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
|
@ -181,12 +185,12 @@ static uint8 *add_end(uint8 *optptr)
|
|||
|
||||
static void create_msg(struct dhcpc_state_internal *pdhcpc, struct dhcp_msg *m)
|
||||
{
|
||||
m->op = DHCP_REQUEST;
|
||||
m->op = DHCP_REQUEST;
|
||||
m->htype = DHCP_HTYPE_ETHERNET;
|
||||
m->hlen = pdhcpc->mac_len;
|
||||
m->hops = 0;
|
||||
m->hlen = pdhcpc->mac_len;
|
||||
m->hops = 0;
|
||||
memcpy(m->xid, xid, sizeof(m->xid));
|
||||
m->secs = 0;
|
||||
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));
|
||||
|
@ -203,33 +207,47 @@ static void create_msg(struct dhcpc_state_internal *pdhcpc, struct dhcp_msg *m)
|
|||
memcpy(m->options, magic_cookie, sizeof(magic_cookie));
|
||||
}
|
||||
|
||||
static void send_discover(struct dhcpc_state_internal *pdhcpc)
|
||||
static int send_discover(struct dhcpc_state_internal *pdhcpc)
|
||||
{
|
||||
uint8 *end;
|
||||
struct dhcp_msg *m = (struct dhcp_msg *)uip_appdata;
|
||||
struct dhcp_msg msg;
|
||||
struct sockaddr_in addr;
|
||||
uint8 *pend;
|
||||
int len;
|
||||
|
||||
create_msg(pdhcpc, m);
|
||||
create_msg(pdhcpc, &msg);
|
||||
pend = add_msg_type(&msg.options[4], DHCPDISCOVER);
|
||||
pend = add_req_options(pend);
|
||||
pend = add_end(pend);
|
||||
len = pend - (uint8*)&msg;
|
||||
|
||||
end = add_msg_type(&m->options[4], DHCPDISCOVER);
|
||||
end = add_req_options(end);
|
||||
end = add_end(end);
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = HTONS(DHCPC_SERVER_PORT);
|
||||
addr.sin_addr.s_addr = INADDR_BROADCAST;
|
||||
|
||||
uip_send(uip_appdata, end - (uint8 *)uip_appdata);
|
||||
return sendto(pdhcpc->sockfd, &msg, len, 0,
|
||||
(struct sockaddr*)&addr, sizeof(struct sockaddr_in));
|
||||
}
|
||||
|
||||
static void send_request(struct dhcpc_state_internal *pdhcpc)
|
||||
static int send_request(struct dhcpc_state_internal *pdhcpc)
|
||||
{
|
||||
uint8 *end;
|
||||
struct dhcp_msg *m = (struct dhcp_msg *)uip_appdata;
|
||||
struct dhcp_msg msg;
|
||||
struct sockaddr_in addr;
|
||||
uint8 *pend;
|
||||
int len;
|
||||
|
||||
create_msg(pdhcpc, m);
|
||||
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_end(pend);
|
||||
len = pend - (uint8*)&msg;
|
||||
|
||||
end = add_msg_type(&m->options[4], DHCPREQUEST);
|
||||
end = add_server_id(pdhcpc->result, end);
|
||||
end = add_req_ipaddr(pdhcpc->result, end);
|
||||
end = add_end(end);
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = HTONS(DHCPC_SERVER_PORT);
|
||||
addr.sin_addr.s_addr = INADDR_BROADCAST;
|
||||
|
||||
uip_send(uip_appdata, end - (uint8 *)uip_appdata);
|
||||
return sendto(pdhcpc->sockfd, &msg, len, 0,
|
||||
(struct sockaddr*)&addr, sizeof(struct sockaddr_in));
|
||||
}
|
||||
|
||||
static uint8 parse_options(struct dhcpc_state *presult, uint8 *optptr, int len)
|
||||
|
@ -283,7 +301,7 @@ static uint8 parse_msg(struct dhcpc_state_internal *pdhcpc)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void handle_dhcp(struct dhcpc_state_internal *pdhcpc)
|
||||
static int handle_dhcp(struct dhcpc_state_internal *pdhcpc)
|
||||
{
|
||||
struct dhcpc_state *presult = pdhcpc->result;
|
||||
|
||||
|
@ -297,8 +315,11 @@ restart:
|
|||
|
||||
send_discover(pdhcpc);
|
||||
|
||||
/* Wait for the response */
|
||||
/* 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)
|
||||
|
@ -322,7 +343,11 @@ restart:
|
|||
|
||||
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);
|
||||
|
||||
|
@ -357,6 +382,7 @@ restart:
|
|||
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;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -365,23 +391,42 @@ restart:
|
|||
|
||||
void *dhcpc_open(const void *mac_addr, int mac_len)
|
||||
{
|
||||
uip_ipaddr_t addr;
|
||||
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;
|
||||
sem_init(&pdhcpc->sem, 0, 0);
|
||||
|
||||
uip_ipaddr(addr, 255,255,255,255);
|
||||
pdhcpc->conn = uip_udp_new(&addr, HTONS(DHCPC_SERVER_PORT));
|
||||
if (pdhcpc->conn != NULL)
|
||||
/* Create a UDP socket */
|
||||
|
||||
pdhcpc->sockfd = socket(PF_INET, SOCK_DGRAM, 0);
|
||||
if (pdhcpc->sockfd < 0)
|
||||
{
|
||||
uip_udp_bind(pdhcpc->conn, HTONS(DHCPC_CLIENT_PORT));
|
||||
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;
|
||||
|
@ -396,19 +441,6 @@ void dhcpc_close(void *handle)
|
|||
}
|
||||
}
|
||||
|
||||
/* This function is called by the UIP interrupt handling logic whenevent an
|
||||
* event of interest occurs.
|
||||
*/
|
||||
|
||||
void uip_interrupt_udp_event(void)
|
||||
{
|
||||
#warning OBSOLETE
|
||||
if (gpdhcpc)
|
||||
{
|
||||
sem_post(&gpdhcpc->sem);
|
||||
}
|
||||
}
|
||||
|
||||
int dhcpc_request(void *handle, struct dhcpc_state *ds)
|
||||
{
|
||||
struct dhcpc_state_internal *pdhcpc = (struct dhcpc_state_internal *)handle;
|
||||
|
@ -421,9 +453,5 @@ int dhcpc_request(void *handle, struct dhcpc_state *ds)
|
|||
}
|
||||
|
||||
pdhcpc->result = ds;
|
||||
gpdhcpc = pdhcpc;
|
||||
sem_wait(&pdhcpc->sem);
|
||||
gpdhcpc = NULL;
|
||||
handle_dhcp(pdhcpc);
|
||||
return OK;
|
||||
return handle_dhcp(pdhcpc);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue