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
+3 -2
View File
@@ -12,6 +12,7 @@
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
* are met: * are met:
*
* 1. Redistributions of source code must retain the above copyright * 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright * 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); 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 *ds);
void dhcpc_close(void *handle); void dhcpc_close(void *handle);
#endif /* NET_UIP_DHCP_H__ */ #endif /* NET_UIP_DHCP_H__ */
+5 -4
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. * addr3 The forth octet of the IP address.
*/ */
#define uip_ipaddr(addr, addr0,addr1,addr2,addr3) do { \ #define uip_ipaddr(addr, addr0, addr1, addr2, addr3) \
((uint16 *)(addr))[0] = HTONS(((addr0) << 8) | (addr1)); \ do { \
((uint16 *)(addr))[1] = HTONS(((addr2) << 8) | (addr3)); \ ((uint16 *)(addr))[0] = HTONS(((addr0) << 8) | (addr1)); \
} while(0) ((uint16 *)(addr))[1] = HTONS(((addr2) << 8) | (addr3)); \
} while(0)
/* Construct an IPv6 address from eight 16-bit words. /* Construct an IPv6 address from eight 16-bit words.
* *
+33 -5
View File
@@ -72,6 +72,11 @@ void recvfrom_interrupt(void *private)
struct recvfrom_s *pstate = (struct recvfrom_s *)private; struct recvfrom_s *pstate = (struct recvfrom_s *)private;
size_t recvlen; 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) if (uip_newdata() && private)
{ {
/* Get the length of the data to return */ /* Get the length of the data to return */
@@ -88,12 +93,14 @@ void recvfrom_interrupt(void *private)
memcpy(pstate->rf_buffer, uip_appdata, recvlen); 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->private = NULL;
uip_conn->callback = 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; pstate->rf_buflen = recvlen;
sem_post(&pstate-> rf_sem); 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(); save = irqsave();
memset(&state, 0, sizeof(struct recvfrom_s)); 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_buflen = len;
state. rf_buffer = buf; 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 = (struct uip_udp_conn *)psock->s_conn;
udp_conn->private = (void*)&state; udp_conn->private = (void*)&state;
udp_conn->callback = recvfrom_interrupt; 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); irqrestore(save);
sem_wait(&state. rf_sem); /* If sem_wait failed, then we were probably reawakened by a signal. In
sem_destroy(&state. rf_sem); * this case, sem_wait will have set errno appropriately.
*/
if (ret < 0)
{
return ERROR;
}
return state.rf_buflen; return state.rf_buflen;
#warning "Needs to return server address" #warning "Needs to return server address"
#else #else
+19 -7
View File
@@ -154,7 +154,9 @@ const uip_ipaddr_t uip_netmask =
{HTONS((UIP_NETMASK0 << 8) | UIP_NETMASK1), {HTONS((UIP_NETMASK0 << 8) | UIP_NETMASK1),
HTONS((UIP_NETMASK2 << 8) | UIP_NETMASK3)}; HTONS((UIP_NETMASK2 << 8) | UIP_NETMASK3)};
#else #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 */ #endif /* UIP_FIXEDADDR */
#ifndef CONFIG_NET_EXTERNAL_BUFFER #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. */ struct uip_conn *uip_conn; /* uip_conn always points to the current connection. */
uint16 uip_listenports[UIP_LISTENPORTS]; 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 #ifdef CONFIG_NET_UDP
struct uip_udp_conn *uip_udp_conn; struct uip_udp_conn *uip_udp_conn;
#endif /* CONFIG_NET_UDP */ #endif /* CONFIG_NET_UDP */
/* Temporary variables. */ /* Temporary variables. */
uint8 uip_acc32[4]; uint8 uip_acc32[4];
#if UIP_STATISTICS == 1 #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. */ * used for the IP ID field. */
/* Temporary variables. */ /* Temporary variables. */
static uint8 c, opt;
static uint8 c;
static uint8 opt;
static uint16 tmp16; static uint16 tmp16;
/**************************************************************************** /****************************************************************************
@@ -1472,14 +1477,16 @@ tcp_send_synack:
if (uip_flags & UIP_ACKDATA) if (uip_flags & UIP_ACKDATA)
{ {
uip_connr->tcpstateflags = UIP_ESTABLISHED; uip_connr->tcpstateflags = UIP_ESTABLISHED;
uip_flags = UIP_CONNECTED; uip_flags = UIP_CONNECTED;
uip_connr->len = 0; uip_connr->len = 0;
if (uip_len > 0) if (uip_len > 0)
{ {
uip_flags |= UIP_NEWDATA; uip_flags |= UIP_NEWDATA;
uip_add_rcv_nxt(uip_len); uip_add_rcv_nxt(uip_len);
} }
uip_slen = 0;
uip_slen = 0;
uip_tcp_callback(); uip_tcp_callback();
goto appsend; goto appsend;
} }
@@ -1535,6 +1542,7 @@ tcp_send_synack:
} }
} }
} }
uip_connr->tcpstateflags = UIP_ESTABLISHED; uip_connr->tcpstateflags = UIP_ESTABLISHED;
uip_connr->rcv_nxt[0] = BUF->seqno[0]; uip_connr->rcv_nxt[0] = BUF->seqno[0];
uip_connr->rcv_nxt[1] = BUF->seqno[1]; uip_connr->rcv_nxt[1] = BUF->seqno[1];
@@ -1575,12 +1583,15 @@ tcp_send_synack:
{ {
goto drop; goto drop;
} }
uip_add_rcv_nxt(1 + uip_len); uip_add_rcv_nxt(1 + uip_len);
uip_flags |= UIP_CLOSE; uip_flags |= UIP_CLOSE;
if (uip_len > 0) if (uip_len > 0)
{ {
uip_flags |= UIP_NEWDATA; uip_flags |= UIP_NEWDATA;
} }
uip_tcp_callback(); uip_tcp_callback();
uip_connr->len = 1; uip_connr->len = 1;
uip_connr->tcpstateflags = UIP_LAST_ACK; uip_connr->tcpstateflags = UIP_LAST_ACK;
@@ -1781,6 +1792,7 @@ tcp_send_synack:
{ {
uip_connr->tcpstateflags = UIP_CLOSING; uip_connr->tcpstateflags = UIP_CLOSING;
} }
uip_add_rcv_nxt(1); uip_add_rcv_nxt(1);
uip_flags = UIP_CLOSE; uip_flags = UIP_CLOSE;
uip_tcp_callback(); uip_tcp_callback();
+94 -66
View File
@@ -49,6 +49,7 @@
#include <semaphore.h> #include <semaphore.h>
#include <time.h> #include <time.h>
#include <debug.h> #include <debug.h>
#include <sys/socket.h>
#include <net/uip/uip.h> #include <net/uip/uip.h>
#include <net/uip/dhcpc.h> #include <net/uip/dhcpc.h>
@@ -101,39 +102,42 @@
struct dhcpc_state_internal struct dhcpc_state_internal
{ {
char state;
sem_t sem;
struct uip_udp_conn *conn; struct uip_udp_conn *conn;
uint16 ticks; struct dhcpc_state *result;
const void *mac_addr; const void *mac_addr;
int mac_len; int mac_len;
struct dhcpc_state *result; int sockfd;
uint16 ticks;
char state;
}; };
struct dhcp_msg struct dhcp_msg
{ {
uint8 op, htype, hlen, hops; uint8 op;
uint8 xid[4]; uint8 htype;
uint16 secs, flags; uint8 hlen;
uint8 ciaddr[4]; uint8 hops;
uint8 yiaddr[4]; uint8 xid[4];
uint8 siaddr[4]; uint16 secs;
uint8 giaddr[4]; uint16 flags;
uint8 chaddr[16]; uint8 ciaddr[4];
uint8 yiaddr[4];
uint8 siaddr[4];
uint8 giaddr[4];
uint8 chaddr[16];
#ifndef CONFIG_NET_DHCP_LIGHT #ifndef CONFIG_NET_DHCP_LIGHT
uint8 sname[64]; uint8 sname[64];
uint8 file[128]; uint8 file[128];
#endif #endif
uint8 options[312]; uint8 options[312];
}; };
/**************************************************************************** /****************************************************************************
* Private Data * 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 const uint8 magic_cookie[4] = {99, 130, 83, 99};
static volatile struct dhcpc_state_internal *gpdhcpc;
/**************************************************************************** /****************************************************************************
* Private Functions * 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) 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->htype = DHCP_HTYPE_ETHERNET;
m->hlen = pdhcpc->mac_len; m->hlen = pdhcpc->mac_len;
m->hops = 0; m->hops = 0;
memcpy(m->xid, xid, sizeof(m->xid)); memcpy(m->xid, xid, sizeof(m->xid));
m->secs = 0; m->secs = 0;
m->flags = HTONS(BOOTP_BROADCAST); /* Broadcast bit. */ m->flags = HTONS(BOOTP_BROADCAST); /* Broadcast bit. */
/* uip_ipaddr_copy(m->ciaddr, uip_hostaddr);*/ /* uip_ipaddr_copy(m->ciaddr, uip_hostaddr);*/
memcpy(m->ciaddr, uip_hostaddr, sizeof(m->ciaddr)); 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)); 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 msg;
struct dhcp_msg *m = (struct dhcp_msg *)uip_appdata; 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); addr.sin_family = AF_INET;
end = add_req_options(end); addr.sin_port = HTONS(DHCPC_SERVER_PORT);
end = add_end(end); 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 msg;
struct dhcp_msg *m = (struct dhcp_msg *)uip_appdata; 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); addr.sin_family = AF_INET;
end = add_server_id(pdhcpc->result, end); addr.sin_port = HTONS(DHCPC_SERVER_PORT);
end = add_req_ipaddr(pdhcpc->result, end); addr.sin_addr.s_addr = INADDR_BROADCAST;
end = add_end(end);
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) 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; 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; struct dhcpc_state *presult = pdhcpc->result;
@@ -297,8 +315,11 @@ restart:
send_discover(pdhcpc); 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); uip_event_timedwait(UIP_NEWDATA, CLOCK_SECOND);
if (uip_newdata() && parse_msg(pdhcpc) == DHCPOFFER) if (uip_newdata() && parse_msg(pdhcpc) == DHCPOFFER)
@@ -322,7 +343,11 @@ restart:
send_request(pdhcpc); send_request(pdhcpc);
/* Set up a watchdog to timeout the recvfrom */
#warning need to implement timeout;
/* Then wait to received the response */ /* Then wait to received the response */
#warning need to use recvfrom
uip_event_timedwait(UIP_NEWDATA, CLOCK_SECOND); uip_event_timedwait(UIP_NEWDATA, CLOCK_SECOND);
@@ -357,6 +382,7 @@ restart:
uip_ipaddr3(presult->default_router), uip_ipaddr4(presult->default_router)); uip_ipaddr3(presult->default_router), uip_ipaddr4(presult->default_router));
dbg("Lease expires in %ld seconds\n", dbg("Lease expires in %ld seconds\n",
ntohs(presult->lease_time[0])*65536ul + ntohs(presult->lease_time[1])); 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) void *dhcpc_open(const void *mac_addr, int mac_len)
{ {
uip_ipaddr_t addr;
struct dhcpc_state_internal *pdhcpc; 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)); pdhcpc = (struct dhcpc_state_internal *)malloc(sizeof(struct dhcpc_state_internal));
if (pdhcpc) if (pdhcpc)
{ {
/* Initialize the allocated structure */
memset(pdhcpc, 0, sizeof(struct dhcpc_state_internal)); memset(pdhcpc, 0, sizeof(struct dhcpc_state_internal));
pdhcpc->mac_addr = mac_addr; pdhcpc->mac_addr = mac_addr;
pdhcpc->mac_len = mac_len; pdhcpc->mac_len = mac_len;
pdhcpc->state = STATE_INITIAL; pdhcpc->state = STATE_INITIAL;
sem_init(&pdhcpc->sem, 0, 0);
uip_ipaddr(addr, 255,255,255,255); /* Create a UDP socket */
pdhcpc->conn = uip_udp_new(&addr, HTONS(DHCPC_SERVER_PORT));
if (pdhcpc->conn != NULL) 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; 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) int dhcpc_request(void *handle, struct dhcpc_state *ds)
{ {
struct dhcpc_state_internal *pdhcpc = (struct dhcpc_state_internal *)handle; 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; pdhcpc->result = ds;
gpdhcpc = pdhcpc; return handle_dhcp(pdhcpc);
sem_wait(&pdhcpc->sem);
gpdhcpc = NULL;
handle_dhcp(pdhcpc);
return OK;
} }