69 #include "contiki-net.h"
71 #include "codeprop-otf.h"
75 static const char *err_msgs[] =
76 {
"OK\r\n",
"Bad ELF header\r\n",
"No symtab\r\n",
"No strtab\r\n",
77 "No text\r\n",
"Symbol not found\r\n",
"Segment not found\r\n",
78 "No startpoint\r\n",
"Unhandled relocation\r\n",
79 "Relocation out of range\r\n",
"Relocations not sorted\r\n",
80 "Input error\r\n" ,
"Ouput error\r\n" };
82 #define CODEPROP_DATA_PORT 6510
87 #define PRINTF(x) printf x
92 #define START_TIMEOUT 12 * CLOCK_SECOND
93 #define MISS_NACK_TIMEOUT (CLOCK_SECOND / 8) * (random_rand() % 8)
94 #define HIT_NACK_TIMEOUT (CLOCK_SECOND / 8) * (8 + random_rand() % 16)
95 #define NACK_REXMIT_TIMEOUT CLOCK_SECOND * (4 + random_rand() % 4)
97 #define WAITING_TIME CLOCK_SECOND * 10
99 #define NUM_SEND_DUPLICATES 2
101 #define UDPHEADERSIZE 8
102 #define UDPDATASIZE 32
104 struct codeprop_udphdr {
107 #define TYPE_DATA 0x0001
108 #define TYPE_NACK 0x0002
111 uint8_t data[UDPDATASIZE];
114 struct codeprop_tcphdr {
119 static void uipcall(
void *state);
121 PROCESS(codeprop_process,
"Code propagator");
123 struct codeprop_state {
126 #define STATE_RECEIVING_TCPDATA 1
127 #define STATE_RECEIVING_UDPDATA 2
128 #define STATE_SENDING_UDPDATA 3
136 uint8_t send_counter;
137 struct pt tcpthread_pt;
138 struct pt udpthread_pt;
139 struct pt recv_udpthread_pt;
146 static struct codeprop_state s;
148 void system_log(
char *msg);
150 static clock_time_t send_time;
152 #define CONNECTION_TIMEOUT (30 * CLOCK_SECOND)
156 codeprop_set_rate(clock_time_t time)
178 s.state = STATE_NONE;
191 }
else if(ev == PROCESS_EVENT_TIMER) {
200 send_udpdata(
struct codeprop_udphdr *uh)
208 if(s.len - s.addr > UDPDATASIZE) {
211 len = s.len - s.addr;
215 cfs_read(fd, (
char*)&uh->data[0], len);
221 PRINTF((
"codeprop: sending packet from address 0x%04x\n", s.addr));
231 struct codeprop_udphdr *uh = (
struct codeprop_udphdr *)
uip_appdata;
239 for(s.addr = 0; s.addr < s.len; ) {
240 len = send_udpdata(uh);
249 PRINTF((
"send_udpthread: got NACK for address 0x%x (now 0x%x)\n",
262 s.state = STATE_NONE;
270 send_nack(
struct codeprop_udphdr *uh,
unsigned short addr)
281 struct codeprop_udphdr *uh = (
struct codeprop_udphdr *)
uip_appdata;
313 while(s.addr < s.len) {
322 cfs_write(fd, (
char*)&uh->data[0], len);
325 PRINTF((
"Saved %d bytes at address %d, %d bytes left\n",
332 }
else if(
uip_htons(uh->addr) > s.addr) {
333 PRINTF((
"sending nack since 0x%x != 0x%x\n",
uip_htons(uh->addr), s.addr));
334 send_nack(uh, s.addr);
342 timer_set(&s.nacktimer, HIT_NACK_TIMEOUT);
348 send_nack(uh, s.addr);
358 codeprop_start_program();
366 #define CODEPROP_TCPHDR_SIZE sizeof(struct codeprop_tcphdr)
371 struct codeprop_tcphdr *th;
379 codeprop_exit_program();
381 s.state = STATE_RECEIVING_TCPDATA;
390 PRINTF((
"codeprop: header not found in first tcp segment\n"));
397 datalen -= CODEPROP_TCPHDR_SIZE;
405 PRINTF((
"codeprop: seek in buffer file failed\n"));
409 if (cfs_write(fd,
uip_appdata, datalen) != datalen) {
410 PRINTF((
"codeprop: write to buffer file failed\n"));
418 }
while(s.addr < s.len);
424 err = codeprop_start_program();
428 if (err >= 0 && err <
sizeof(err_msgs)/
sizeof(
char*)) {
429 uip_send(err_msgs[err], strlen(err_msgs[err]));
441 s.state = STATE_SENDING_UDPDATA;
452 codeprop_start_broadcast(
unsigned int len)
457 s.state = STATE_SENDING_UDPDATA;
462 codeprop_exit_program(
void)
470 codeprop_start_program(
void)
474 codeprop_exit_program();
478 PRINTF((
"codeprop: starting %s\n",
489 recv_udpthread(&s.recv_udpthread_pt);
490 send_udpthread(&s.udpthread_pt);
504 PRINTF((
"codeprop: uip_connected() and state != NULL\n"));
508 recv_tcpthread(&s.tcpthread_pt);
512 PRINTF((
"codeprop: connection down\n"));
int cfs_open(const char *name, int flags)
Open a file.
void process_poll(struct process *p)
Request a process to be polled.
#define uip_acked()
Has previously sent data been acknowledged?
#define CFS_WRITE
Specify that cfs_open() should open a file for writing.
Representation of a uIP TCP connection.
#define PT_INIT(pt)
Initialize a protothread.
#define uip_abort()
Abort the current connection.
static uip_ds6_addr_t * addr
Pointer to a router list entry.
process_event_t tcpip_event
The uIP event.
#define UIP_HTONS(n)
Convert 16-bit quantity from host byte order to network byte order.
#define CFS_SEEK_SET
Specify that cfs_seek() should compute the offset from the beginning of the file. ...
void timer_set(struct timer *t, clock_time_t interval)
Set a timer.
Header file for the Contiki ELF loader.
struct uip_udp_conn * udp_broadcast_new(uint16_t port, void *appstate)
Create a new UDP broadcast connection.
void etimer_set(struct etimer *et, clock_time_t interval)
Set an event timer.
#define uip_closed()
Has the connection been closed by the other end?
#define PROCESS_END()
Define the end of a process.
Representation of a uIP UDP connection.
#define PROCESS(name, strname)
Declare a process.
void tcp_listen(uint16_t port)
Open a TCP port.
#define PT_YIELD(pt)
Yield from the current protothread.
#define CFS_READ
Specify that cfs_open() should open a file for reading.
#define PROCESS_THREAD(name, ev, data)
Define the body of a process.
#define uip_udpconnection()
Is the current connection a UDP connection?
uip_appdata
Pointer to the application data in the packet buffer.
#define PT_WAIT_UNTIL(pt, condition)
Block and wait until condition is true.
#define uip_aborted()
Has the connection been aborted by the other end?
#define PT_EXIT(pt)
Exit the protothread.
#define uip_udp_send(len)
Send a UDP datagram of length len on the current connection.
#define uip_datalen()
The length of any incoming data that is currently available (if available) in the uip_appdata buffer...
void elfloader_init(void)
elfloader initialization function.
#define ELFLOADER_OK
Return value from elfloader_load() indicating that loading worked.
struct process *const * elfloader_autostart_processes
A pointer to the processes loaded with elfloader_load().
#define NULL
The null pointer.
#define PT_YIELD_UNTIL(pt, cond)
Yield from the protothread until a condition occurs.
CCIF void uip_send(const void *data, int len)
Send data on the current connection.
#define PROCESS_YIELD()
Yield the currently running process.
#define PT_THREAD(name_args)
Declaration of a protothread.
int etimer_expired(struct etimer *et)
Check if an event timer has expired.
uint16_t lport
The local TCP port, in network byte order.
#define PT_BEGIN(pt)
Declare the start of a protothread inside the C function implementing the protothread.
#define uip_connected()
Has the connection just been connected?
#define CLOCK_SECOND
A second, measured in system clock time.
static volatile clock_time_t count
These routines define the AVR-specific calls declared in /core/sys/clock.h CLOCK_SECOND is the number...
#define uip_rexmit()
Do we need to retransmit previously data?
#define PT_END(pt)
Declare the end of a protothread.
void tcpip_poll_udp(struct uip_udp_conn *conn)
Cause a specified UDP connection to be polled.
int elfloader_load(int fd)
Load and relocate an ELF file.
cfs_offset_t cfs_seek(int fd, cfs_offset_t offset, int whence)
Seek to a specified position in an open file.
#define uip_close()
Close the current connection.
#define uip_timedout()
Has the connection timed out?
#define uip_newdata()
Is new incoming data available?
CCIF uint16_t uip_htons(uint16_t val)
Convert a 16-bit quantity from host byte order to network byte order.
int timer_expired(struct timer *t)
Check if a timer has expired.
#define PROCESS_BEGIN()
Define the beginning of a process.