53 #define DEFAULT_SEND_INTERVAL CLOCK_SECOND * 2
54 #define TRICKLE_INTERVAL CLOCK_SECOND / 2
55 #define NACK_TIMEOUT CLOCK_SECOND / 4
56 #define REPAIR_TIMEOUT CLOCK_SECOND / 4
64 #define RUDOLPH1_DATASIZE 64
66 struct rudolph1_datapacket {
67 struct rudolph1_hdr h;
69 uint8_t data[RUDOLPH1_DATASIZE];
80 #define PRINTF(...) printf(__VA_ARGS__)
85 #define LT(a, b) ((signed char)((a) - (b)) < 0)
89 read_data(
struct rudolph1_conn *c, uint8_t *dataptr,
int chunk)
93 if(c->cb->read_chunk) {
94 len = c->cb->read_chunk(c, chunk * RUDOLPH1_DATASIZE,
95 dataptr, RUDOLPH1_DATASIZE);
101 format_data(
struct rudolph1_conn *c,
int chunk)
103 struct rudolph1_datapacket *p;
107 p->h.type = TYPE_DATA;
108 p->h.version = c->version;
110 p->datalen = read_data(c, p->data, chunk);
112 (RUDOLPH1_DATASIZE - p->datalen));
118 write_data(
struct rudolph1_conn *c,
int chunk, uint8_t *data,
int datalen)
121 c->cb->write_chunk(c, 0, RUDOLPH1_FLAG_NEWFILE, data, 0);
124 if(datalen < RUDOLPH1_DATASIZE) {
125 PRINTF(
"%d.%d: get %d bytes, file complete\n",
128 c->cb->write_chunk(c, chunk * RUDOLPH1_DATASIZE,
129 RUDOLPH1_FLAG_LASTCHUNK, data, datalen);
131 c->cb->write_chunk(c, chunk * RUDOLPH1_DATASIZE,
132 RUDOLPH1_FLAG_NONE, data, datalen);
137 send_nack(
struct rudolph1_conn *c)
139 struct rudolph1_hdr *hdr;
144 hdr->type = TYPE_NACK;
145 hdr->version = c->version;
146 hdr->chunk = c->chunk;
148 PRINTF(
"%d.%d: Sending nack for %d:%d\n",
150 hdr->version, hdr->chunk);
151 ipolite_send(&c->ipolite, NACK_TIMEOUT,
sizeof(
struct rudolph1_hdr));
155 handle_data(
struct rudolph1_conn *c,
struct rudolph1_datapacket *p)
157 if(LT(c->version, p->h.version)) {
158 PRINTF(
"%d.%d: rudolph1 new version %d, chunk %d\n",
160 p->h.version, p->h.chunk);
161 c->version = p->h.version;
162 c->highest_chunk_heard = c->chunk = 0;
163 if(p->h.chunk != 0) {
166 write_data(c, 0, p->data, p->datalen);
170 }
else if(p->h.version == c->version) {
171 PRINTF(
"%d.%d: got chunk %d (%d) highest heard %d\n",
173 p->h.chunk, c->chunk, c->highest_chunk_heard);
175 if(p->h.chunk == c->chunk) {
176 PRINTF(
"%d.%d: received chunk %d\n",
179 write_data(c, p->h.chunk, p->data, p->datalen);
180 if(c->highest_chunk_heard < c->chunk) {
181 c->highest_chunk_heard = c->chunk;
184 }
else if(p->h.chunk > c->chunk) {
185 PRINTF(
"%d.%d: received chunk %d > %d, sending NACK\n",
187 p->h.chunk, c->chunk);
189 c->highest_chunk_heard = p->h.chunk;
190 }
else if(p->h.chunk < c->chunk) {
197 if(c->highest_chunk_heard > p->h.chunk) {
207 recv_trickle(
struct trickle_conn *trickle)
209 struct rudolph1_conn *c = (
struct rudolph1_conn *)trickle;
212 if(p->h.type == TYPE_DATA) {
213 PRINTF(
"%d.%d: received trickle with chunk %d\n",
223 PRINTF(
"%d.%d: Sent ipolite\n",
230 PRINTF(
"%d.%d: dropped ipolite\n",
235 recv_ipolite(
struct ipolite_conn *ipolite,
const rimeaddr_t *from)
237 struct rudolph1_conn *c = (
struct rudolph1_conn *)
238 ((
char *)ipolite - offsetof(
struct rudolph1_conn, ipolite));
241 PRINTF(
"%d.%d: Got ipolite type %d\n",
247 if(p->h.type == TYPE_NACK) {
248 PRINTF(
"%d.%d: Got NACK for %d:%d (%d:%d)\n",
250 p->h.version, p->h.chunk,
251 c->version, c->chunk);
252 if(p->h.version == c->version) {
253 if(p->h.chunk < c->chunk) {
255 PRINTF(
"%d.%d: sending repair for chunk %d\n",
258 format_data(c, p->h.chunk);
259 ipolite_send(&c->ipolite, REPAIR_TIMEOUT,
sizeof(
struct rudolph1_hdr));
261 }
else if(LT(p->h.version, c->version)) {
263 ipolite_send(&c->ipolite, c->send_interval / 2,
sizeof(
struct rudolph1_hdr));
265 }
else if(p->h.type == TYPE_DATA) {
267 PRINTF(
"%d.%d: got repair for chunk %d\n",
275 send_next_packet(
void *ptr)
277 struct rudolph1_conn *c = ptr;
280 len = format_data(c, c->chunk);
281 trickle_send(&c->trickle);
282 if(len == RUDOLPH1_DATASIZE) {
283 ctimer_set(&c->t, c->send_interval, send_next_packet, c);
285 PRINTF(
"%d.%d: send_next_packet chunk %d, next %d\n",
287 c->chunk, c->chunk + 1);
289 c->highest_chunk_heard = c->chunk;
293 ctimer_set(&c->t, c->send_interval, send_next_packet, c);
300 static const struct trickle_callbacks trickle = { recv_trickle };
303 rudolph1_open(
struct rudolph1_conn *c, uint16_t channel,
304 const struct rudolph1_callbacks *cb)
306 trickle_open(&c->trickle, TRICKLE_INTERVAL, channel, &trickle);
310 c->send_interval = DEFAULT_SEND_INTERVAL;
314 rudolph1_close(
struct rudolph1_conn *c)
316 trickle_close(&c->trickle);
321 rudolph1_send(
struct rudolph1_conn *c, clock_time_t send_interval)
324 c->chunk = c->highest_chunk_heard = 0;
327 trickle_send(&c->trickle);
329 c->send_interval = send_interval;
330 ctimer_set(&c->t, send_interval, send_next_packet, c);
334 rudolph1_stop(
struct rudolph1_conn *c)