Contiki 3.x
deluge.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2007, Swedish Institute of Computer Science
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * This file is part of the Contiki operating system.
30  *
31  */
32 
33 /**
34  * \file
35  * An implementation of the Deluge protocol.
36  * (Hui and Culler: The dynamic behavior of a data
37  * dissemination protocol for network programming at scale,
38  * ACM SenSys 2004)
39  * \author
40  * Nicolas Tsiftes <nvt@sics.se>
41  */
42 
43 #include "contiki.h"
44 #include "net/rime/rime.h"
45 #include "cfs/cfs.h"
46 #include "loader/elfloader.h"
47 #include "lib/crc16.h"
48 #include "lib/random.h"
49 #include "sys/node-id.h"
50 #include "deluge.h"
51 
52 #if NETSIM
53 #include "ether.h"
54 #include <stdio.h>
55 #endif
56 
57 #include "dev/leds.h"
58 #include <stdlib.h>
59 #include <string.h>
60 
61 #define DEBUG 0
62 #if DEBUG
63 #include <stdio.h>
64 #define PRINTF(...) printf(__VA_ARGS__)
65 #else
66 #define PRINTF(...)
67 #endif
68 
69 /* Implementation-specific variables. */
70 static struct broadcast_conn deluge_broadcast;
71 static struct unicast_conn deluge_uc;
72 static struct deluge_object current_object;
73 static process_event_t deluge_event;
74 
75 /* Deluge variables. */
76 static int deluge_state;
77 static int old_summary;
78 static int neighbor_inconsistency;
79 static unsigned r_interval;
80 static unsigned recv_adv;
81 static int broadcast_profile;
82 
83 /* Deluge timers. */
84 static struct ctimer rx_timer;
85 static struct ctimer tx_timer;
86 static struct ctimer summary_timer;
87 static struct ctimer profile_timer;
88 
89 /* Deluge objects will get an ID that defaults to the current value of
90  the next_object_id parameter. */
91 static deluge_object_id_t next_object_id;
92 
93 /* Rime callbacks. */
94 static void broadcast_recv(struct broadcast_conn *, const linkaddr_t *);
95 static void unicast_recv(struct unicast_conn *, const linkaddr_t *);
96 
97 static const struct broadcast_callbacks broadcast_call = {broadcast_recv, NULL};
98 static const struct unicast_callbacks unicast_call = {unicast_recv, NULL};
99 
100 /* The Deluge process manages the main Deluge timer. */
101 PROCESS(deluge_process, "Deluge");
102 
103 static void
104 transition(int state)
105 {
106  if(state != deluge_state) {
107  switch(deluge_state) {
108  case DELUGE_STATE_MAINTAIN:
109  ctimer_stop(&summary_timer);
110  ctimer_stop(&profile_timer);
111  break;
112  case DELUGE_STATE_RX:
113  ctimer_stop(&rx_timer);
114  break;
115  case DELUGE_STATE_TX:
116  ctimer_stop(&tx_timer);
117  break;
118  }
119  deluge_state = state;
120  }
121 }
122 
123 static int
124 write_page(struct deluge_object *obj, unsigned pagenum, unsigned char *data)
125 {
126  cfs_offset_t offset;
127 
128  offset = pagenum * S_PAGE;
129 
130  if(cfs_seek(obj->cfs_fd, offset, CFS_SEEK_SET) != offset) {
131  return -1;
132  }
133  return cfs_write(obj->cfs_fd, (char *)data, S_PAGE);
134 }
135 
136 static int
137 read_page(struct deluge_object *obj, unsigned pagenum, unsigned char *buf)
138 {
139  cfs_offset_t offset;
140 
141  offset = pagenum * S_PAGE;
142 
143  if(cfs_seek(obj->cfs_fd, offset, CFS_SEEK_SET) != offset) {
144  return -1;
145  }
146  return cfs_read(obj->cfs_fd, (char *)buf, S_PAGE);
147 }
148 
149 static void
150 init_page(struct deluge_object *obj, int pagenum, int have)
151 {
152  struct deluge_page *page;
153  unsigned char buf[S_PAGE];
154 
155  page = &obj->pages[pagenum];
156 
157  page->flags = 0;
158  page->last_request = 0;
159  page->last_data = 0;
160 
161  if(have) {
162  page->version = obj->version;
163  page->packet_set = ALL_PACKETS;
164  page->flags |= PAGE_COMPLETE;
165  read_page(obj, pagenum, buf);
166  page->crc = crc16_data(buf, S_PAGE, 0);
167  } else {
168  page->version = 0;
169  page->packet_set = 0;
170  }
171 }
172 
173 static cfs_offset_t
174 file_size(const char *file)
175 {
176  int fd;
177  cfs_offset_t size;
178 
179  fd = cfs_open(file, CFS_READ);
180  if(fd < 0) {
181  return (cfs_offset_t)-1;
182  }
183 
184  size = cfs_seek(fd, 0, CFS_SEEK_END);
185  cfs_close(fd);
186 
187  return size;
188 }
189 
190 static int
191 init_object(struct deluge_object *obj, char *filename, unsigned version)
192 {
193  static struct deluge_page *page;
194  int i;
195 
196  obj->cfs_fd = cfs_open(filename, CFS_READ | CFS_WRITE);
197  if(obj->cfs_fd < 0) {
198  return -1;
199  }
200 
201  obj->filename = filename;
202  obj->object_id = next_object_id++;
203  obj->size = file_size(filename);
204  obj->version = obj->update_version = version;
205  obj->current_rx_page = 0;
206  obj->nrequests = 0;
207  obj->tx_set = 0;
208 
209  obj->pages = malloc(OBJECT_PAGE_COUNT(*obj) * sizeof(*obj->pages));
210  if(obj->pages == NULL) {
211  cfs_close(obj->cfs_fd);
212  return -1;
213  }
214 
215  for(i = 0; i < OBJECT_PAGE_COUNT(current_object); i++) {
216  page = &current_object.pages[i];
217  init_page(&current_object, i, 1);
218  }
219 
220  memset(obj->current_page, 0, sizeof(obj->current_page));
221 
222  return 0;
223 }
224 
225 static int
226 highest_available_page(struct deluge_object *obj)
227 {
228  int i;
229 
230  for(i = 0; i < OBJECT_PAGE_COUNT(*obj); i++) {
231  if(!(obj->pages[i].flags & PAGE_COMPLETE)) {
232  break;
233  }
234  }
235 
236  return i;
237 }
238 
239 static void
240 send_request(void *arg)
241 {
242  struct deluge_object *obj;
243  struct deluge_msg_request request;
244 
245  obj = (struct deluge_object *)arg;
246 
247  request.cmd = DELUGE_CMD_REQUEST;
248  request.pagenum = obj->current_rx_page;
249  request.version = obj->pages[request.pagenum].version;
250  request.request_set = ~obj->pages[obj->current_rx_page].packet_set;
251  request.object_id = obj->object_id;
252 
253  PRINTF("Sending request for page %d, version %u, request_set %u\n",
254  request.pagenum, request.version, request.request_set);
255  packetbuf_copyfrom(&request, sizeof(request));
256  unicast_send(&deluge_uc, &obj->summary_from);
257 
258  /* Deluge R.2 */
259  if(++obj->nrequests == CONST_LAMBDA) {
260  /* XXX check rate here too. */
261  obj->nrequests = 0;
262  transition(DELUGE_STATE_MAINTAIN);
263  } else {
264  ctimer_reset(&rx_timer);
265  }
266 }
267 
268 static void
269 advertise_summary(struct deluge_object *obj)
270 {
271  struct deluge_msg_summary summary;
272 
273  if(recv_adv >= CONST_K) {
274  ctimer_stop(&summary_timer);
275  return;
276  }
277 
278  summary.cmd = DELUGE_CMD_SUMMARY;
279  summary.version = obj->update_version;
280  summary.highest_available = highest_available_page(obj);
281  summary.object_id = obj->object_id;
282 
283  PRINTF("Advertising summary for object id %u: version=%u, available=%u\n",
284  (unsigned)obj->object_id, summary.version, summary.highest_available);
285 
286  packetbuf_copyfrom(&summary, sizeof(summary));
287  broadcast_send(&deluge_broadcast);
288 }
289 
290 static void
291 handle_summary(struct deluge_msg_summary *msg, const linkaddr_t *sender)
292 {
293  int highest_available, i;
294  clock_time_t oldest_request, oldest_data, now;
295  struct deluge_page *page;
296 
297  highest_available = highest_available_page(&current_object);
298 
299  if(msg->version != current_object.version ||
300  msg->highest_available != highest_available) {
301  neighbor_inconsistency = 1;
302  } else {
303  recv_adv++;
304  }
305 
306  if(msg->version < current_object.version) {
307  old_summary = 1;
308  broadcast_profile = 1;
309  }
310 
311  /* Deluge M.5 */
312  if(msg->version == current_object.update_version &&
313  msg->highest_available > highest_available) {
314  if(msg->highest_available > OBJECT_PAGE_COUNT(current_object)) {
315  PRINTF("Error: highest available is above object page count!\n");
316  return;
317  }
318 
319  oldest_request = oldest_data = now = clock_time();
320  for(i = 0; i < msg->highest_available; i++) {
321  page = &current_object.pages[i];
322  if(page->last_request < oldest_request) {
323  oldest_request = page->last_request;
324  }
325  if(page->last_request < oldest_data) {
326  oldest_data = page->last_data;
327  }
328  }
329 
330  if(((now - oldest_request) / CLOCK_SECOND) <= 2 * r_interval ||
331  ((now - oldest_data) / CLOCK_SECOND) <= r_interval) {
332  return;
333  }
334 
335  linkaddr_copy(&current_object.summary_from, sender);
336  transition(DELUGE_STATE_RX);
337 
338  if(ctimer_expired(&rx_timer)) {
339  ctimer_set(&rx_timer,
340  CONST_OMEGA * ESTIMATED_TX_TIME + ((unsigned)random_rand() % T_R),
341  send_request, &current_object);
342  }
343  }
344 }
345 
346 static void
347 send_page(struct deluge_object *obj, unsigned pagenum)
348 {
349  unsigned char buf[S_PAGE];
350  struct deluge_msg_packet pkt;
351  unsigned char *cp;
352 
353  pkt.cmd = DELUGE_CMD_PACKET;
354  pkt.pagenum = pagenum;
355  pkt.version = obj->pages[pagenum].version;
356  pkt.packetnum = 0;
357  pkt.object_id = obj->object_id;
358  pkt.crc = 0;
359 
360  read_page(obj, pagenum, buf);
361 
362  /* Divide the page into packets and send them one at a time. */
363  for(cp = buf; cp + S_PKT <= (unsigned char *)&buf[S_PAGE]; cp += S_PKT) {
364  if(obj->tx_set & (1 << pkt.packetnum)) {
365  pkt.crc = crc16_data(cp, S_PKT, 0);
366  memcpy(pkt.payload, cp, S_PKT);
367  packetbuf_copyfrom(&pkt, sizeof(pkt));
368  broadcast_send(&deluge_broadcast);
369  }
370  pkt.packetnum++;
371  }
372  obj->tx_set = 0;
373 }
374 
375 static void
376 tx_callback(void *arg)
377 {
378  struct deluge_object *obj;
379 
380  obj = (struct deluge_object *)arg;
381  if(obj->current_tx_page >= 0 && obj->tx_set) {
382  send_page(obj, obj->current_tx_page);
383  /* Deluge T.2. */
384  if(obj->tx_set) {
385  packetbuf_set_attr(PACKETBUF_ATTR_PACKET_TYPE,
386  PACKETBUF_ATTR_PACKET_TYPE_STREAM);
387  ctimer_reset(&tx_timer);
388  } else {
389  packetbuf_set_attr(PACKETBUF_ATTR_PACKET_TYPE,
390  PACKETBUF_ATTR_PACKET_TYPE_STREAM_END);
391  obj->current_tx_page = -1;
392  transition(DELUGE_STATE_MAINTAIN);
393  }
394  }
395 }
396 
397 static void
398 handle_request(struct deluge_msg_request *msg)
399 {
400  int highest_available;
401 
402  if(msg->pagenum >= OBJECT_PAGE_COUNT(current_object)) {
403  return;
404  }
405 
406  if(msg->version != current_object.version) {
407  neighbor_inconsistency = 1;
408  }
409 
410  highest_available = highest_available_page(&current_object);
411 
412  /* Deluge M.6 */
413  if(msg->version == current_object.version &&
414  msg->pagenum <= highest_available) {
415  current_object.pages[msg->pagenum].last_request = clock_time();
416 
417  /* Deluge T.1 */
418  if(msg->pagenum == current_object.current_tx_page) {
419  current_object.tx_set |= msg->request_set;
420  } else {
421  current_object.current_tx_page = msg->pagenum;
422  current_object.tx_set = msg->request_set;
423  }
424 
425  transition(DELUGE_STATE_TX);
426  ctimer_set(&tx_timer, CLOCK_SECOND, tx_callback, &current_object);
427  }
428 }
429 
430 static void
431 handle_packet(struct deluge_msg_packet *msg)
432 {
433  struct deluge_page *page;
434  uint16_t crc;
435  struct deluge_msg_packet packet;
436 
437  memcpy(&packet, msg, sizeof(packet));
438 
439  PRINTF("Incoming packet for object id %u, version %u, page %u, packet num %u!\n",
440  (unsigned)packet.object_id, (unsigned)packet.version,
441  (unsigned)packet.pagenum, (unsigned)packet.packetnum);
442 
443  if(packet.pagenum != current_object.current_rx_page) {
444  return;
445  }
446 
447  if(packet.version != current_object.version) {
448  neighbor_inconsistency = 1;
449  }
450 
451  page = &current_object.pages[packet.pagenum];
452  if(packet.version == page->version && !(page->flags & PAGE_COMPLETE)) {
453  memcpy(&current_object.current_page[S_PKT * packet.packetnum],
454  packet.payload, S_PKT);
455 
456  crc = crc16_data(packet.payload, S_PKT, 0);
457  if(packet.crc != crc) {
458  PRINTF("packet crc: %hu, calculated crc: %hu\n", packet.crc, crc);
459  return;
460  }
461 
462  page->last_data = clock_time();
463  page->packet_set |= (1 << packet.packetnum);
464 
465  if(page->packet_set == ALL_PACKETS) {
466  /* This is the last packet of the requested page; stop streaming. */
467  packetbuf_set_attr(PACKETBUF_ATTR_PACKET_TYPE,
468  PACKETBUF_ATTR_PACKET_TYPE_STREAM_END);
469 
470  write_page(&current_object, packet.pagenum, current_object.current_page);
471  page->version = packet.version;
472  page->flags = PAGE_COMPLETE;
473  PRINTF("Page %u completed\n", packet.pagenum);
474 
475  current_object.current_rx_page++;
476 
477  if(packet.pagenum == OBJECT_PAGE_COUNT(current_object) - 1) {
478  current_object.version = current_object.update_version;
479  leds_on(LEDS_RED);
480  PRINTF("Update completed for object %u, version %u\n",
481  (unsigned)current_object.object_id, packet.version);
482  } else if(current_object.current_rx_page < OBJECT_PAGE_COUNT(current_object)) {
483  if(ctimer_expired(&rx_timer)) {
484  ctimer_set(&rx_timer,
485  CONST_OMEGA * ESTIMATED_TX_TIME + (random_rand() % T_R),
486  send_request, &current_object);
487  }
488  }
489  /* Deluge R.3 */
490  transition(DELUGE_STATE_MAINTAIN);
491  } else {
492  /* More packets to come. Put lower layers in streaming mode. */
493  packetbuf_set_attr(PACKETBUF_ATTR_PACKET_TYPE,
494  PACKETBUF_ATTR_PACKET_TYPE_STREAM);
495  }
496  }
497 }
498 
499 static void
500 send_profile(struct deluge_object *obj)
501 {
502  struct deluge_msg_profile *msg;
503  unsigned char buf[sizeof(*msg) + OBJECT_PAGE_COUNT(*obj)];
504  int i;
505 
506  if(broadcast_profile && recv_adv < CONST_K) {
507  broadcast_profile = 0;
508 
509  msg = (struct deluge_msg_profile *)buf;
510  msg->cmd = DELUGE_CMD_PROFILE;
511  msg->version = obj->version;
512  msg->npages = OBJECT_PAGE_COUNT(*obj);
513  msg->object_id = obj->object_id;
514  for(i = 0; i < msg->npages; i++) {
515  msg->version_vector[i] = obj->pages[i].version;
516  }
517 
518  packetbuf_copyfrom(buf, sizeof(buf));
519  broadcast_send(&deluge_broadcast);
520  }
521 }
522 
523 static void
524 handle_profile(struct deluge_msg_profile *msg)
525 {
526  int i;
527  int npages;
528  struct deluge_object *obj;
529  char *p;
530 
531  obj = &current_object;
532  if(msg->version <= current_object.update_version) {
533  return;
534  }
535 
536  PRINTF("Received profile of version %u with a vector of %u pages.\n",
537  msg->version, msg->npages);
538 
539  leds_off(LEDS_RED);
540  current_object.tx_set = 0;
541 
542  npages = OBJECT_PAGE_COUNT(*obj);
543  obj->size = msg->npages * S_PAGE;
544 
545  p = malloc(OBJECT_PAGE_COUNT(*obj) * sizeof(*obj->pages));
546  if(p == NULL) {
547  PRINTF("Failed to reallocate memory for pages!\n");
548  return;
549  }
550 
551  memcpy(p, obj->pages, npages * sizeof(*obj->pages));
552  free(obj->pages);
553  obj->pages = (struct deluge_page *)p;
554 
555  if(msg->npages < npages) {
556  npages = msg->npages;
557  }
558 
559  for(i = 0; i < npages; i++) {
560  if(msg->version_vector[i] > obj->pages[i].version) {
561  obj->pages[i].packet_set = 0;
562  obj->pages[i].flags &= ~PAGE_COMPLETE;
563  obj->pages[i].version = msg->version_vector[i];
564  }
565  }
566 
567  for(; i < msg->npages; i++) {
568  init_page(obj, i, 0);
569  }
570 
571  obj->current_rx_page = highest_available_page(obj);
572  obj->update_version = msg->version;
573 
574  transition(DELUGE_STATE_RX);
575 
576  ctimer_set(&rx_timer,
577  CONST_OMEGA * ESTIMATED_TX_TIME + ((unsigned)random_rand() % T_R),
578  send_request, obj);
579 }
580 
581 static void
582 command_dispatcher(const linkaddr_t *sender)
583 {
584  char *msg;
585  int len;
586  struct deluge_msg_profile *profile;
587 
588  msg = packetbuf_dataptr();
589  len = packetbuf_datalen();
590  if(len < 1)
591  return;
592 
593  switch(msg[0]) {
594  case DELUGE_CMD_SUMMARY:
595  if(len >= sizeof(struct deluge_msg_summary))
596  handle_summary((struct deluge_msg_summary *)msg, sender);
597  break;
598  case DELUGE_CMD_REQUEST:
599  if(len >= sizeof(struct deluge_msg_request))
600  handle_request((struct deluge_msg_request *)msg);
601  break;
602  case DELUGE_CMD_PACKET:
603  if(len >= sizeof(struct deluge_msg_packet))
604  handle_packet((struct deluge_msg_packet *)msg);
605  break;
606  case DELUGE_CMD_PROFILE:
607  profile = (struct deluge_msg_profile *)msg;
608  if(len >= sizeof(*profile) &&
609  len >= sizeof(*profile) + profile->npages * profile->version_vector[0])
610  handle_profile((struct deluge_msg_profile *)msg);
611  break;
612  default:
613  PRINTF("Incoming packet with unknown command: %d\n", msg[0]);
614  }
615 }
616 
617 static void
618 unicast_recv(struct unicast_conn *c, const linkaddr_t *sender)
619 {
620  command_dispatcher(sender);
621 }
622 
623 static void
624 broadcast_recv(struct broadcast_conn *c, const linkaddr_t *sender)
625 {
626  command_dispatcher(sender);
627 }
628 
629 int
630 deluge_disseminate(char *file, unsigned version)
631 {
632  /* This implementation disseminates at most one object. */
633  if(next_object_id > 0 || init_object(&current_object, file, version) < 0) {
634  return -1;
635  }
636  process_start(&deluge_process, (void *)file);
637 
638  return 0;
639 }
640 
641 PROCESS_THREAD(deluge_process, ev, data)
642 {
643  static struct etimer et;
644  static unsigned time_counter;
645  static unsigned r_rand;
646 
647  PROCESS_EXITHANDLER(goto exit);
648 
649  PROCESS_BEGIN();
650 
651  deluge_event = process_alloc_event();
652 
653  broadcast_open(&deluge_broadcast, DELUGE_BROADCAST_CHANNEL, &broadcast_call);
654  unicast_open(&deluge_uc, DELUGE_UNICAST_CHANNEL, &unicast_call);
655  r_interval = T_LOW;
656 
657  PRINTF("Maintaining state for object %s of %d pages\n",
658  current_object.filename, OBJECT_PAGE_COUNT(current_object));
659 
660  deluge_state = DELUGE_STATE_MAINTAIN;
661 
662  for(r_interval = T_LOW;;) {
663  if(neighbor_inconsistency) {
664  /* Deluge M.2 */
665  r_interval = T_LOW;
666  neighbor_inconsistency = 0;
667  } else {
668  /* Deluge M.3 */
669  r_interval = (2 * r_interval >= T_HIGH) ? T_HIGH : 2 * r_interval;
670  }
671 
672  r_rand = r_interval / 2 + ((unsigned)random_rand() % (r_interval / 2));
673  recv_adv = 0;
674  old_summary = 0;
675 
676  /* Deluge M.1 */
677  ctimer_set(&summary_timer, r_rand * CLOCK_SECOND,
678  (void *)(void *)advertise_summary, &current_object);
679 
680  /* Deluge M.4 */
681  ctimer_set(&profile_timer, r_rand * CLOCK_SECOND,
682  (void *)(void *)send_profile, &current_object);
683 
684  LONG_TIMER(et, time_counter, r_interval);
685  }
686 
687 exit:
688  unicast_close(&deluge_uc);
689  broadcast_close(&deluge_broadcast);
690  if(current_object.cfs_fd >= 0) {
691  cfs_close(current_object.cfs_fd);
692  }
693  if(current_object.pages != NULL) {
694  free(current_object.pages);
695  }
696 
697  PROCESS_END();
698 }
int packetbuf_copyfrom(const void *from, uint16_t len)
Copy from external data into the packetbuf.
Definition: packetbuf.c:93
void broadcast_close(struct broadcast_conn *c)
Close a broadcast connection.
Definition: broadcast.c:105
int cfs_open(const char *name, int flags)
Open a file.
Definition: cfs-coffee.c:996
#define LEDS_RED
LED1 (Red) -&gt; PC0.
Definition: board.h:89
cfs_offset_t cfs_seek(int fd, cfs_offset_t offset, int whence)
Seek to a specified position in an open file.
Definition: cfs-coffee.c:1042
#define PROCESS_BEGIN()
Define the beginning of a process.
Definition: process.h:120
#define CFS_WRITE
Specify that cfs_open() should open a file for writing.
Definition: cfs.h:104
int ctimer_expired(struct ctimer *c)
Check if a callback timer has expired.
Definition: ctimer.c:154
Header for Deluge.
#define NULL
The null pointer.
#define CFS_SEEK_END
Specify that cfs_seek() should compute the offset from the end of the file.
Definition: cfs.h:145
process_event_t process_alloc_event(void)
Allocate a global event number.
Definition: process.c:93
#define CFS_READ
Specify that cfs_open() should open a file for reading.
Definition: cfs.h:90
Header file for the Rime stack
uint16_t packetbuf_datalen(void)
Get the length of the data in the packetbuf.
Definition: packetbuf.c:239
void linkaddr_copy(linkaddr_t *dest, const linkaddr_t *src)
Copy a Rime address.
Definition: linkaddr.c:60
#define PROCESS_THREAD(name, ev, data)
Define the body of a process.
Definition: process.h:273
#define PROCESS_END()
Define the end of a process.
Definition: process.h:131
CCIF clock_time_t clock_time(void)
Get the current clock time.
Definition: clock.c:41
void ctimer_set(struct ctimer *c, clock_time_t t, void(*f)(void *), void *ptr)
Set a callback timer.
Definition: ctimer.c:99
#define PROCESS_EXITHANDLER(handler)
Specify an action when a process exits.
Definition: process.h:254
Callback structure for broadcast.
Definition: broadcast.h:80
void ctimer_reset(struct ctimer *c)
Reset a callback timer with the same interval as was previously set.
Definition: ctimer.c:118
#define PROCESS(name, strname)
Declare a process.
Definition: process.h:307
int broadcast_send(struct broadcast_conn *c)
Send an identified best-effort broadcast packet.
Definition: broadcast.c:111
void process_start(struct process *p, process_data_t data)
Start a process.
Definition: process.c:99
#define CFS_SEEK_SET
Specify that cfs_seek() should compute the offset from the beginning of the file. ...
Definition: cfs.h:127
Header file for the Contiki ELF loader.
void * packetbuf_dataptr(void)
Get a pointer to the data in the packetbuf.
Definition: packetbuf.c:207
void broadcast_open(struct broadcast_conn *c, uint16_t channel, const struct broadcast_callbacks *u)
Set up an identified best-effort broadcast connection.
Definition: broadcast.c:96
Header file for the CRC16 calculcation
A timer.
Definition: etimer.h:76
void ctimer_stop(struct ctimer *c)
Stop a pending callback timer.
Definition: ctimer.c:142
unsigned short random_rand(void)
Generate the next state and return the upper part of it.
Definition: random.c:47
unsigned short crc16_data(const unsigned char *data, int len, unsigned short acc)
Calculate the CRC16 over a data area.
Definition: crc16.c:66
void cfs_close(int fd)
Close an open file.
Definition: cfs-coffee.c:1032
#define CLOCK_SECOND
A second, measured in system clock time.
Definition: clock.h:82
CFS header file.