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 etimer_expired(struct etimer *et)
Check if an event timer has expired.
void process_poll(struct process *p)
Request a process to be polled.
void elfloader_init(void)
elfloader initialization function.
int cfs_open(const char *name, int flags)
Open a file.
cfs_offset_t cfs_seek(int fd, cfs_offset_t offset, int whence)
Seek to a specified position in an open file.
#define PROCESS_BEGIN()
Define the beginning of a process.
#define CFS_WRITE
Specify that cfs_open() should open a file for writing.
Representation of a uIP TCP connection.
#define PT_YIELD(pt)
Yield from the current protothread.
#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.
#define CFS_READ
Specify that cfs_open() should open a file for reading.
#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.
CCIF void tcpip_poll_udp(struct uip_udp_conn *conn)
Cause a specified UDP connection to be polled.
#define PT_THREAD(name_args)
Declaration of a protothread.
#define uip_acked()
Has previously sent data been acknowledged?
#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.
Header file for the Contiki ELF loader.
#define uip_close()
Close the current connection.
struct process *const * elfloader_autostart_processes
A pointer to the processes loaded with elfloader_load().
#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 ELFLOADER_OK
Return value from elfloader_load() indicating that loading worked.
#define CFS_SEEK_SET
Specify that cfs_seek() should compute the offset from the beginning of the file. ...
#define uip_closed()
Has the connection been closed by the other end?
Representation of a uIP UDP connection.
int timer_expired(struct timer *t)
Check if a timer has expired.
#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?