60 #define SEND_INTERVAL CLOCK_SECOND / 2
61 #define STEADY_INTERVAL CLOCK_SECOND * 16
62 #define RESEND_INTERVAL SEND_INTERVAL * 4
63 #define NACK_TIMEOUT CLOCK_SECOND / 4
67 uint8_t hops_from_base;
72 #define POLITE_HEADER 1
81 #define FLAG_LAST_SENT 0x01
82 #define FLAG_LAST_RECEIVED 0x02
83 #define FLAG_IS_STOPPED 0x04
88 #define PRINTF(...) printf(__VA_ARGS__)
93 #define LT(a, b) ((signed short)((a) - (b)) < 0)
97 read_data(
struct rudolph2_conn *c, uint8_t *dataptr,
int chunk)
101 if(c->cb->read_chunk) {
102 len = c->cb->read_chunk(c, chunk * RUDOLPH2_DATASIZE,
103 dataptr, RUDOLPH2_DATASIZE);
109 format_data(
struct rudolph2_conn *c,
int chunk)
111 struct rudolph2_hdr *hdr;
116 hdr->type = TYPE_DATA;
117 hdr->hops_from_base = c->hops_from_base;
118 hdr->version = c->version;
120 len = read_data(c, (uint8_t *)hdr +
sizeof(
struct rudolph2_hdr), chunk);
127 write_data(
struct rudolph2_conn *c,
int chunk, uint8_t *data,
int datalen)
130 if(c->flags & FLAG_IS_STOPPED) {
135 c->cb->write_chunk(c, 0, RUDOLPH2_FLAG_NEWFILE, data, 0);
138 PRINTF(
"%d.%d: get %d bytes\n",
143 if(datalen < RUDOLPH2_DATASIZE) {
144 PRINTF(
"%d.%d: get %d bytes, file complete\n",
147 c->cb->write_chunk(c, chunk * RUDOLPH2_DATASIZE,
148 RUDOLPH2_FLAG_LASTCHUNK, data, datalen);
150 c->cb->write_chunk(c, chunk * RUDOLPH2_DATASIZE,
151 RUDOLPH2_FLAG_NONE, data, datalen);
156 send_data(
struct rudolph2_conn *c, clock_time_t interval)
160 len = format_data(c, c->snd_nxt);
162 PRINTF(
"%d.%d: send_data chunk %d, rcv_nxt %d\n",
164 c->snd_nxt, c->rcv_nxt);
170 send_nack(
struct rudolph2_conn *c)
172 struct rudolph2_hdr *hdr;
177 hdr->hops_from_base = c->hops_from_base;
178 hdr->type = TYPE_NACK;
179 hdr->version = c->version;
180 hdr->chunk = c->rcv_nxt;
182 PRINTF(
"%d.%d: Sending nack for %d\n",
190 send_next(
struct rudolph2_conn *c)
193 clock_time_t interval;
195 if(c->flags & FLAG_LAST_SENT) {
196 interval = STEADY_INTERVAL;
198 interval = SEND_INTERVAL;
201 len = send_data(c, interval);
203 if(len < RUDOLPH2_DATASIZE) {
204 c->flags |= FLAG_LAST_SENT;
206 c->flags &= ~FLAG_LAST_SENT;
210 len == RUDOLPH2_DATASIZE &&
211 c->snd_nxt + 1 < c->rcv_nxt) {
249 timed_send(
void *ptr)
251 struct rudolph2_conn *c = (
struct rudolph2_conn *)ptr;
252 clock_time_t interval;
255 if((c->flags & FLAG_IS_STOPPED) == 0 &&
256 (c->flags & FLAG_LAST_RECEIVED)) {
264 if(c->flags & FLAG_LAST_SENT) {
265 interval = STEADY_INTERVAL;
267 interval = SEND_INTERVAL;
271 len = send_data(c, interval);
273 if(len < RUDOLPH2_DATASIZE) {
274 c->flags |= FLAG_LAST_SENT;
276 c->flags &= ~FLAG_LAST_SENT;
280 len == RUDOLPH2_DATASIZE &&
281 c->snd_nxt + 1 < c->rcv_nxt) {
292 struct rudolph2_conn *c = (
struct rudolph2_conn *)polite;
298 if(hdr->type == TYPE_NACK && hdr->hops_from_base > c->hops_from_base) {
300 PRINTF(
"%d.%d: Got NACK for %d:%d (%d:%d)\n",
302 hdr->version, hdr->chunk,
303 c->version, c->rcv_nxt);
304 if(hdr->version == c->version) {
305 if(hdr->chunk < c->rcv_nxt) {
306 c->snd_nxt = hdr->chunk;
307 send_data(c, SEND_INTERVAL);
309 }
else if(LT(hdr->version, c->version)) {
311 send_data(c, SEND_INTERVAL);
313 }
else if(hdr->type == TYPE_DATA) {
314 if(hdr->hops_from_base < c->hops_from_base) {
317 c->hops_from_base = hdr->hops_from_base + 1;
318 if(LT(c->version, hdr->version)) {
319 PRINTF(
"%d.%d: rudolph2 new version %d, chunk %d\n",
321 hdr->version, hdr->chunk);
322 c->version = hdr->version;
323 c->snd_nxt = c->rcv_nxt = 0;
324 c->flags &= ~FLAG_LAST_RECEIVED;
325 c->flags &= ~FLAG_LAST_SENT;
326 if(hdr->chunk != 0) {
332 }
else if(hdr->version == c->version) {
333 PRINTF(
"%d.%d: got chunk %d snd_nxt %d rcv_nxt %d\n",
335 hdr->chunk, c->snd_nxt, c->rcv_nxt);
337 if(hdr->chunk == c->rcv_nxt) {
340 PRINTF(
"%d.%d: received chunk %d len %d\n",
346 if(len < RUDOLPH2_DATASIZE) {
347 c->flags |= FLAG_LAST_RECEIVED;
348 send_data(c, RESEND_INTERVAL);
349 ctimer_set(&c->t, RESEND_INTERVAL, timed_send, c);
351 }
else if(hdr->chunk > c->rcv_nxt) {
352 PRINTF(
"%d.%d: received chunk %d > %d, sending NACK\n",
354 hdr->chunk, c->rcv_nxt);
356 }
else if(hdr->chunk < c->rcv_nxt) {
367 rudolph2_open(
struct rudolph2_conn *c, uint16_t channel,
368 const struct rudolph2_callbacks *cb)
373 c->hops_from_base = HOPS_MAX;
377 rudolph2_close(
struct rudolph2_conn *c)
383 rudolph2_send(
struct rudolph2_conn *c, clock_time_t send_interval)
387 c->hops_from_base = 0;
390 len = RUDOLPH2_DATASIZE;
392 for(c->rcv_nxt = 0; len == RUDOLPH2_DATASIZE; c->rcv_nxt++) {
395 c->flags = FLAG_LAST_RECEIVED;
397 send_data(c, SEND_INTERVAL);
398 ctimer_set(&c->t, SEND_INTERVAL, timed_send, c);
402 rudolph2_stop(
struct rudolph2_conn *c)
405 c->flags |= FLAG_IS_STOPPED;