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:
patacongo 2007-09-05 00:13:18 +00:00
parent 4f3ecdd85a
commit 8c0ce78863
5 changed files with 154 additions and 84 deletions

View File

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

View File

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

View File

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

View File

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

View File

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