69 #include "contiki-net.h"
71 #include "codeprop-tmp.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" };
80 #define CODEPROP_DATA_PORT 6510
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 struct codeprop_tcphdr {
117 static void uipcall(
void *state);
119 PROCESS(codeprop_process,
"Code propagator");
121 struct codeprop_state {
124 #define STATE_RECEIVING_TCPDATA 1
125 #define STATE_RECEIVING_UDPDATA 2
126 #define STATE_SENDING_UDPDATA 3
134 uint8_t send_counter;
135 struct pt tcpthread_pt;
136 struct pt udpthread_pt;
137 struct pt recv_udpthread_pt;
144 static struct codeprop_state s;
146 void system_log(
char *msg);
148 static clock_time_t send_time;
150 #define CONNECTION_TIMEOUT (30 * CLOCK_SECOND)
154 codeprop_set_rate(clock_time_t time)
176 s.state = STATE_NONE;
189 }
else if(ev == PROCESS_EVENT_TIMER) {
198 send_udpdata(
struct codeprop_udphdr *uh)
206 if(s.len - s.addr > UDPDATASIZE) {
209 len = s.len - s.addr;
213 cfs_read(fd, &uh->data[0], len);
219 PRINTF((
"codeprop: sending packet from address 0x%04x\n", s.addr));
229 struct codeprop_udphdr *uh = (
struct codeprop_udphdr *)
uip_appdata;
237 for(s.addr = 0; s.addr < s.len; ) {
238 len = send_udpdata(uh);
247 PRINTF((
"send_udpthread: got NACK for address 0x%x (now 0x%x)\n",
260 s.state = STATE_NONE;
268 send_nack(
struct codeprop_udphdr *uh,
unsigned short addr)
279 struct codeprop_udphdr *uh = (
struct codeprop_udphdr *)
uip_appdata;
311 while(s.addr < s.len) {
320 cfs_write(fd, &uh->data[0], len);
323 PRINTF((
"Saved %d bytes at address %d, %d bytes left\n",
330 }
else if(
uip_htons(uh->addr) > s.addr) {
331 PRINTF((
"sending nack since 0x%x != 0x%x\n",
uip_htons(uh->addr), s.addr));
332 send_nack(uh, s.addr);
340 timer_set(&s.nacktimer, HIT_NACK_TIMEOUT);
346 send_nack(uh, s.addr);
356 codeprop_start_program();
367 struct codeprop_tcphdr *th;
375 codeprop_exit_program();
377 s.state = STATE_RECEIVING_TCPDATA;
388 if(
uip_datalen() <
sizeof(
struct codeprop_tcphdr)) {
389 PRINTF((
"codeprop: header not found in first tcp segment\n"));
396 datalen -=
sizeof(
struct codeprop_tcphdr);
412 }
while(s.addr < s.len);
419 err = codeprop_start_program();
423 uip_send(err_msgs[err], strlen(err_msgs[err]));
432 s.state = STATE_SENDING_UDPDATA;
443 codeprop_start_broadcast(
unsigned int len)
448 s.state = STATE_SENDING_UDPDATA;
453 codeprop_exit_program(
void)
461 codeprop_start_program(
void)
465 codeprop_exit_program();
469 PRINTF((
"codeprop: starting %s\n",
480 recv_udpthread(&s.recv_udpthread_pt);
481 send_udpthread(&s.udpthread_pt);
495 PRINTF((
"codeprop: uip_connected() and state != NULL\n"));
499 recv_tcpthread(&s.tcpthread_pt);
503 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.
#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?
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.
#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?