68 #include "sys/clock.h"
76 #include "lib/random.h"
80 void codeprop_set_rate(clock_time_t time);
85 #define PRINTF(x) printf x
90 #define START_TIMEOUT 12 * CLOCK_SECOND
91 #define MISS_NACK_TIMEOUT (CLOCK_SECOND / 8) * (random_rand() % 8)
92 #define HIT_NACK_TIMEOUT (CLOCK_SECOND / 8) * (8 + random_rand() % 16)
93 #define NACK_REXMIT_TIMEOUT CLOCK_SECOND * (4 + random_rand() % 4)
95 #define WAITING_TIME CLOCK_SECOND * 10
97 #define NUM_SEND_DUPLICATES 2
99 #define UDPHEADERSIZE 8
100 #define UDPDATASIZE 32
102 struct codeprop_udphdr {
105 #define TYPE_DATA 0x0001
106 #define TYPE_NACK 0x0002
109 uint8_t data[UDPDATASIZE];
112 static void uipcall(
void *state);
114 PROCESS(codeprop_process,
"Code propagator");
116 struct codeprop_state {
119 #define STATE_RECEIVING_TCPDATA 1
120 #define STATE_RECEIVING_UDPDATA 2
121 #define STATE_SENDING_UDPDATA 3
129 uint8_t send_counter;
130 struct pt tcpthread_pt;
131 struct pt udpthread_pt;
132 struct pt recv_udpthread_pt;
137 static struct codeprop_state s;
139 process_event_t codeprop_event_quit;
141 void system_log(
char *msg);
143 static clock_time_t send_time;
145 #define CONNECTION_TIMEOUT (30 * CLOCK_SECOND)
153 codeprop_set_rate(clock_time_t time)
175 s.state = STATE_NONE;
184 if(ev == EVENT_START_PROGRAM) {
190 }
else if(ev == PROCESS_EVENT_TIMER) {
199 send_udpdata(
struct codeprop_udphdr *uh)
207 if(s.len - s.addr > UDPDATASIZE) {
210 len = s.len - s.addr;
218 PRINTF((
"codeprop: sending packet from address 0x%04x\n", s.addr));
228 struct codeprop_udphdr *uh = (
struct codeprop_udphdr *)
uip_appdata;
236 for(s.addr = 0; s.addr < s.len; ) {
237 len = send_udpdata(uh);
246 PRINTF((
"send_udpthread: got NACK for address 0x%x (now 0x%x)\n",
258 s.state = STATE_NONE;
266 send_nack(
struct codeprop_udphdr *uh,
unsigned short addr)
277 struct codeprop_udphdr *uh = (
struct codeprop_udphdr *)
uip_appdata;
308 while(s.addr < s.len) {
316 PRINTF((
"Saved %d bytes at address %d, %d bytes left\n",
323 }
else if(
uip_htons(uh->addr) > s.addr) {
324 PRINTF((
"sending nack since 0x%x != 0x%x\n",
uip_htons(uh->addr), s.addr));
325 send_nack(uh, s.addr);
333 timer_set(&s.nacktimer, HIT_NACK_TIMEOUT);
339 send_nack(uh, s.addr);
360 struct codeprop_tcphdr *th;
369 s.state = STATE_RECEIVING_TCPDATA;
380 if(
uip_datalen() <
sizeof(
struct codeprop_tcphdr)) {
381 PRINTF((
"codeprop: header not found in first tcp segment\n"));
388 datalen =
uip_datalen() -
sizeof(
struct codeprop_tcphdr);
402 }
while(s.addr < s.len);
414 s.state = STATE_SENDING_UDPDATA;
417 codeprop_start_program();
427 codeprop_start_broadcast(
unsigned int len)
432 s.state = STATE_SENDING_UDPDATA;
437 codeprop_start_program(
void)
447 recv_udpthread(&s.recv_udpthread_pt);
448 send_udpthread(&s.udpthread_pt);
460 (process_data_t)
NULL);
462 PRINTF((
"codeprop: uip_connected() and state != NULL\n"));
466 recv_tcpthread(&s.tcpthread_pt);
470 PRINTF((
"codeprop: connection down\n"));
void eeprom_read(eeprom_addr_t addr, unsigned char *buf, int size)
Read data from the EEPROM.
int etimer_expired(struct etimer *et)
Check if an event timer has expired.
void process_poll(struct process *p)
Request a process to be polled.
#define PROCESS_BEGIN()
Define the beginning of a process.
Representation of a uIP TCP connection.
#define PT_YIELD(pt)
Yield from the current protothread.
Header for the Contiki/uIP interface.
#define uip_aborted()
Has the connection been aborted by the other end?
CCIF void uip_send(const void *data, int len)
Send data on the current connection.
#define uip_newdata()
Is new incoming data available?
void timer_set(struct timer *t, clock_time_t interval)
Set a timer.
uint16_t lport
The local TCP port, in network byte order.
int elfloader_load(int fd)
Load and relocate an ELF file.
#define NULL
The null pointer.
#define PT_INIT(pt)
Initialize a protothread.
process_event_t process_alloc_event(void)
Allocate a global event number.
#define uip_udp_send(len)
Send a UDP datagram of length len on the current connection.
#define UIP_HTONS(n)
Convert 16-bit quantity from host byte order to network byte order.
int process_post(struct process *p, process_event_t ev, process_data_t data)
Post an asynchronous event.
CCIF void tcpip_poll_udp(struct uip_udp_conn *conn)
Cause a specified UDP connection to be polled.
void eeprom_write(eeprom_addr_t addr, unsigned char *buf, int size)
Write a buffer into EEPROM.
#define PT_THREAD(name_args)
Declaration of a protothread.
#define uip_acked()
Has previously sent data been acknowledged?
#define LEDS_YELLOW
LED2 (Yellow) -> PC1.
#define uip_connected()
Has the connection just been connected?
#define PT_WAIT_UNTIL(pt, condition)
Block and wait until condition is true.
#define PROCESS_THREAD(name, ev, data)
Define the body of a process.
#define PROCESS_END()
Define the end of a process.
struct uip_udp_conn * udp_broadcast_new(uint16_t port, void *appstate)
Create a new UDP broadcast connection.
#define uip_abort()
Abort the current connection.
CCIF uint16_t uip_htons(uint16_t val)
Convert a 16-bit quantity from host byte order to network byte order.
#define PT_BEGIN(pt)
Declare the start of a protothread inside the C function implementing the protothread.
#define uip_udpconnection()
Is the current connection a UDP connection?
#define PROCESS(name, strname)
Declare a process.
#define uip_close()
Close the current connection.
#define uip_datalen()
The length of any incoming data that is currently available (if available) in the uip_appdata buffer...
#define PT_YIELD_UNTIL(pt, cond)
Yield from the protothread until a condition occurs.
process_event_t tcpip_event
The uIP event.
#define uip_timedout()
Has the connection timed out?
#define PT_END(pt)
Declare the end of a protothread.
#define PROCESS_YIELD()
Yield the currently running process.
void etimer_set(struct etimer *et, clock_time_t interval)
Set an event timer.
CCIF void tcp_listen(uint16_t port)
Open a TCP port.
#define uip_closed()
Has the connection been closed by the other end?
Header file for the Contiki ELF loader.
Representation of a uIP UDP connection.
int timer_expired(struct timer *t)
Check if a timer has expired.
void leds_blink(void)
Blink all LEDs.
#define PT_EXIT(pt)
Exit the protothread.
uip_appdata
Pointer to the application data in the packet buffer.
#define CLOCK_SECOND
A second, measured in system clock time.
#define uip_rexmit()
Do we need to retransmit previously data?