KM3NeT CLB  2.0
KM3NeT CLB v2 Embedded Software
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
srp.c
1 /*
2  * srp.c
3  *
4  * Created on: 22 mrt. 2013
5  * Author: vincentb
6  */
7 
8 #include "net/srp.h"
9 
10 #include <time.h>
11 #include <assert.h>
12 #include <stdlib.h>
13 #include <stdio.h>
14 
15 #include "util/log.h"
16 
17 #include "coll/varqueue.h"
18 #include "coll/queue.h"
19 #include "util/macro.h"
20 #include "kernel/scheduler.h"
21 
22 LOG_DEF(Srp)
23 
24 #define SRP_LITE
25 
26 typedef struct SrpStats_
27 {
28  uint32_t rx;
29  uint32_t rx_dup;
30  uint32_t rx_cache_full;
31  uint32_t rx_cfm;
32  uint32_t rx_err_fmt;
33  uint32_t rx_drop_ack;
34  uint32_t tx;
35  uint32_t tx_err;
36 } SrpStats;
37 
38 static SrpStats _stats;
39 
40 // #define SRP_TRACE
41 
42 // #define SRP_VERBOSE
43 
44 // #define SRP_STRICT_RX_CACHE
45 
46 #ifdef SRP_TRACE
47 
48 #define _TCD(NAME, FMT, ...) \
49  logDebug("dbg: " STR(NAME) ": " FMT, __VA_ARGS__)
50 
51 #define _TCM(NAME, FMT, ...) \
52  logDebug("dbg: " STR(NAME), 0)
53 
54 #else
55 #define _TCD(NAME, FMT, ...)
56 #define _TCM(NAME, MSG)
57 #endif
58 
59 // general variables and structs
60 // -----------------------------
61 
62 static int _srpSchdPeriodicId;
63 
64 // though in theory the clock usually returns millis we should not assume so.
65 
66 // spread is an additional random element
67 #define _SRP_RESEND_SPREAD 64
68 
69 // first timeout, will increase by a factor of 2 each time.
70 #ifndef KM3SIM
71 #define _SRP_RESEND_TIMEOUT ( ( SRP_RESEND_TIMEOUT * CLOCKS_PER_SEC ) / 1000 )
72 #else
73 #define _SRP_RESEND_TIMEOUT SRP_RESEND_TIMEOUT
74 #endif
75 
76 // > maximum possible timeout
77 // suppose the resend timeout is 200, and the resend count is 5, this means
78 // that it will be resend after 200, 400, 600 and 800 1000 1200 ms. The total of which
79 // is 4200.
80 #define _SRP_CACHE_MAX_AGE \
81  ( ( _SRP_RESEND_TIMEOUT + ( _SRP_RESEND_TIMEOUT / 2 ) * \
82  ( SRP_RESEND_MAX - 1 ) ) * SRP_RESEND_MAX )
83 
84 #if (_SRP_CACHE_MAX_AGE > 0x7FFF)
85 #error "Timeout too big"
86 #endif
87 
88 
89 typedef struct
90 {
91  SrpHeader hdr;
92  uint8_t content[SRP_MAX_PAYLOAD];
93 } SrpMessage;
94 
95 static SrpMessage _srpSwap;
96 
97 // variables and structs for transmission
98 // --------------------------------------
99 #define _SRP_TXF_CNT_MASK 0x3F
100 #define _SRP_TXF_CNT_SHIFT 0
101 #define _SRP_TXF_CONFIRMED BIT(6)
102 
103 #define _SRP_TX_CNT_GET( F ) ( ( ( F ) & _SRP_TXF_CNT_MASK ) >> _SRP_TXF_CNT_SHIFT )
104 #define _SRP_TX_CNT_SET( C ) ( ( ( C ) << _SRP_TXF_CNT_SHIFT ) & _SRP_TXF_CNT_MASK )
105 
106 
107 #ifndef SRP_LITE
108 typedef struct
109 {
110  SockAddr addr;
111  uint16_t timeout;
112  uint8_t msgId;
113  uint8_t flags;
114 } SrpTxRec;
115 
116 VQ_INIT(_srpTxQueue, SRP_TX_QUEUE_SIZE);
117 Q_INIT(_srpTxRecQueue, sizeof(SrpTxRec), SRP_TX_MAX_QUEUE);
118 
119 #endif
120 
121 static uint8_t _srpTxId;
122 
123 // variables and struct for reception
124 // -----------------------------------
125 #define _SRP_RXF_USED BIT(0)
126 #define _SRP_RXF_SEND_CFM BIT(1)
127 #define _SRP_RXF_NEED_CFM ( _SRP_RXF_USED | _SRP_RXF_SEND_CFM )
128 
129 typedef struct
130 {
131  SockAddr addr;
132  uint16_t timeout;
133  uint8_t msgId;
134  uint8_t flags;
135 } SrpRxEntry;
136 
137 static SrpRxEntry _srpRxCache[SRP_RX_MAX_CACHE];
138 static SrpRxEntry * const _srpRxCacheLast = &_srpRxCache[SRP_RX_MAX_CACHE - 1];
139 static SrpRxEntry * const _srpRxCacheFirst = &_srpRxCache[0];
140 
141 // 16 bit cyclic time out functions
142 // --------------------------------
143 static inline uint16_t srpTimeOutNew(uint16_t to)
144 {
145  return ( clock() + to ) & 0xFFFF;
146 }
147 
148 static inline bool srpTimeOut(uint16_t to)
149 {
150  return CGE(clock() & 0xFFFF, to, 16);
151 }
152 
154 {
155  int t;
156 #ifndef SRP_LITE
157  puts("---- SRP TX Queue ----");
158 
159 
160 
161  printf("Commit content: %d of %d\n", _srpTxQueue.used, _srpTxQueue.size);
162  printf("Commit record : %d of %d\n", _srpTxRecQueue.length, _srpTxRecQueue.descr->capacity);
163 
164 
165  SrpTxRec * txRec = (SrpTxRec *) qFirst(&_srpTxRecQueue);
166  t = 0;
167  while (txRec != NULL) {
168  printf("- %d: flags=%02x id=%d timeout=%d\n", t, txRec->flags, txRec->msgId, txRec->timeout);
169  txRec = (SrpTxRec *) qNext(&_srpTxRecQueue, txRec);
170  ++t;
171  }
172 #endif
173 
174  puts("---- SRP RX Cache ----");
175 
176  SrpRxEntry * curEntry;
177 
178  t = 0;
179 
180  for (curEntry = _srpRxCacheFirst; curEntry <= _srpRxCacheLast; ++curEntry)
181  {
182  if (curEntry->flags & _SRP_RXF_USED) {
183  t++;
184  printf("- %d: flags=%02x id=%d timeout=%d\n",
185  t, curEntry->flags, curEntry->msgId, curEntry->timeout);
186  }
187 
188  }
189  printf("Commit record : %d of " STR(SRP_RX_MAX_CACHE) "\n", t);
190 
191  puts("");
192  printf("RX-msg: %d, RX-dups: %d, RX-cache-full: %d\n", _stats.rx, _stats.rx_dup, _stats.rx_cache_full);
193  printf("RX-cfm: %d, RX-err-fmt: %d, RX-drop-ack: %d\n", _stats.rx_cfm, _stats.rx_err_fmt, _stats.rx_drop_ack);
194  printf("TX: %d, TX-err: %d\n", _stats.tx, _stats.tx_err);
195 }
196 
197 // check if a received message has already been received before.
198 // if so, it will return false, and queue this for reception again.
199 // otherwise it will attempt to allocate a cache entry for the message.
200 static bool srpRxNew(SockAddr * addr, uint8_t msgId)
201 {
202 
203  // lets attempt to spread this through the cache.
204  SrpRxEntry * const firstEntry = _srpRxCacheFirst + ( msgId % SRP_RX_MAX_CACHE );
205 
206  SrpRxEntry * curEntry = firstEntry;
207 
208  // best entry is the cache entry to overwrite if the message has not been received
209  // before. By default a previous empty entry is the best entry. Otherwise, the oldest
210  // entry is removed.
211 
212  SrpRxEntry * bestEntry = NULL;
213 
214  do
215  {
216  // 1. check if it has been received, and free old cache entries.
217  if (curEntry->flags & _SRP_RXF_USED) {
218  if (sockAddrEq(&(curEntry->addr), addr) && curEntry->msgId == msgId) {
219  curEntry->flags |= _SRP_RXF_SEND_CFM;
220  // the received message was received before, we can just flag it
221  // as need to be confirmed. No new entry will need to be created.
222  // exit now.
223  _TCD(srpRxNew, "Received message wit rmsgID=%d before, ignore", msgId);
224  _stats.rx_dup += 1;
225  return false;
226  }
227  // do some administration, if the entry is timed-out, free it.
228  if (srpTimeOut(curEntry->timeout))
229  {
230  curEntry->flags = 0; // free it
231  }
232  }
233 
234 #ifdef SRP_STRICT_RX_CACHE
235  // Strict caching only frees cache if it timed-out. This lowers the throughput, but
236  // increases the reliability. Throughput is the RX cache-size divided by the retransmit
237  // timeout. E.g. if is 250ms x 16, then 4 seconds is the timeout, if the cache size
238  // is then 64, it means 64 / 4 -> 16 RX messages per second can be processed.
239 
240  if (curEntry->flags == 0) {
241 
242  bestEntry = curEntry;
243  break;
244  }
245 
246 #else
247 
248  // 2. if there is no best entry, which is always the case in the first iteration of the
249  // loop we will take anything as long as it has not confirm pending
250  if (bestEntry == NULL)
251  {
252  // 2.1. as long as its not an entry that has a confirm pending, we'll take it
253  if (!(curEntry->flags & _SRP_RXF_SEND_CFM))
254  {
255  // take this entry, even if it may be sub-optimal
256  bestEntry = curEntry;
257  }
258  // otherwise best entry will remain NULL, for the next loop
259  } else if (bestEntry->flags != 0) {
260  // 2.2. if the best entry is actually still used, i.e. its not free,
261  // we will look for another entry.
262 
263  if (curEntry->flags == 0) {
264  // 2.2.1. had not so good entry, but now we have a better one!
265  bestEntry = curEntry;
266  // unfortunately we can not break here, since the message may still have
267  // been received before, so we need to iterate through the remaining entries.
268  } else if (bestEntry->flags != 0 && CLE(curEntry->timeout, bestEntry->timeout, 16)) {
269  // 2.2.2. older, but still used, entry, take it.
270  // though we rather wait for it to be cleared from the cache.
271  bestEntry = curEntry;
272  }
273  }
274 #endif
275 
276  // move to next cache entry
277  curEntry = ( curEntry == _srpRxCacheLast ) ? _srpRxCacheFirst : curEntry + 1;
278  } while (curEntry != firstEntry);
279 
280 
281  // if no best entry is found, we give up, and just
282  // communicate like it was already received
283  if (bestEntry == NULL) // rare case this is!
284  {
285  // this will cause a retransmit. Its not to be helped.
286  logWarn("No free entries, could not accept message with rmsgID %d", msgId);
287  _stats.rx_cache_full += 1;
288  return false;
289  }
290 
291 // puts("Added new entry to Rx cache");
292  _TCD(srpRxNew, "New entry to RX cache, old rmsgID = %d, new rmsgID = %d",
293  bestEntry->msgId, msgId);
294  bestEntry->flags = _SRP_RXF_SEND_CFM | _SRP_RXF_USED;
295  bestEntry->addr = *addr;
296  bestEntry->msgId = msgId;
297  bestEntry->timeout = srpTimeOutNew(_SRP_CACHE_MAX_AGE);
298 
299  _stats.rx += 1;
300  return true;
301 }
302 
303 // Returns the first ACK for a specific IP address, or returns false if there are no ACKs for
304 // this address.
305 // A special function is that if the IP address is 0 (not the pointer), the IP address will be
306 // filled in of the first confirm.
307 static bool srpAckFor(SockAddr * addr, uint8_t * cfmPtr)
308 {
309  SrpRxEntry * entry = _srpRxCacheFirst;
310  while (entry <= _srpRxCacheLast)
311  {
312  if ( ( entry->flags & _SRP_RXF_NEED_CFM ) == _SRP_RXF_NEED_CFM &&
313  ( addr->ip == 0 || sockAddrEq(&entry->addr, addr)) )
314  {
315  // clear confirm flag and put message ID in pointer.
316  *cfmPtr = entry->msgId;
317  *addr = entry->addr;
318  _TCD(srpRxNew, "Send confirm for rmsgId=%d", entry->msgId);
319  // puts("Found entry to be confirmed");
320  entry->flags &= ~_SRP_RXF_SEND_CFM;
321  _stats.rx_cfm += 1;
322  return true;
323  }
324  entry++;
325  }
326  return false;
327 }
328 
329 
330 
331 /*
332  * Prepares the headers of the current transmission packet.
333  *
334  * If len == 0, a special confirm-only packet is generated (if anything needs to be confirmed).
335  * If no IP address is specified the first to-be-confirmed message will be used for the ip
336  * address.
337  */
338 static bool srpUdpTransmit(SockAddr * addr, int len, bool dontack)
339 {
340  int ackCnt = 0;
341 
342 
343 
344  // mark as message if the length > 0
345  if (len > 0)
346  {
347  _srpSwap.hdr.flags = SRP_FLG_MSG;
348 
349  if (dontack)
350  _srpSwap.hdr.flags |= SRP_FLG_DONTACK;
351 
352  } else
353  {
354  _srpSwap.hdr.flags = 0;
355  }
356 
357  // fill with acknowledges.
358  while (srpAckFor(addr, &(_srpSwap.hdr.ackId[ackCnt])))
359  {
360  ackCnt++;
361  if (ackCnt >= SRP_MAX_ACKS) break;
362  }
363 
364  // no ACK to create
365  if (ackCnt == 0 && len == 0) return false;
366 
367  _TCD(srpUdpTransmit, "Transmitting: addr=0x%08x len=%d", addr->ip, len);
368 
369  _srpSwap.hdr.flags |= ackCnt << SRP_FLG_ACK_SHIFT;
370 
371  _srpSwap.content[len] = '\0';
372 
373  _stats.tx += 1;
374  _srpUdpTx(addr, (uint8_t *)&_srpSwap, len + sizeof(SrpHeader));
375  return true;
376 }
377 
378 
379 
380 #ifndef SRP_LITE
381 /*
382  * Confirms a transmitted message. Will be removed from queue later on.
383  */
384 void srpTxCfm(SockAddr * sender, uint8_t msgId)
385 {
386 
387  SrpTxRec * txRec = qFirst(&_srpTxRecQueue);
388 
389  while (txRec != NULL)
390  {
391  if (txRec->msgId == msgId && sockAddrEq(sender, &(txRec->addr)))
392  {
393  _TCD(srpTxCfm, "Message lmsgID=%d confirmed!", txRec->msgId);
394  txRec->flags |= _SRP_TXF_CONFIRMED;
395  return;
396  }
397 
398  txRec = qNext(&_srpTxRecQueue, txRec);
399  }
400 }
401 
402 #endif
403 
404 
405 /*!
406  * Invoked by UDP stack for receiving an SRP packet.
407  */
408 void srpUdpRx(SockAddr * rxAddr, uint8_t * udpPayload, int len)
409 {
410  // TODO change all lengths into unsigned!
411 
412  // FIX 2019-03-21: truncated incoming SRP packets create negative length
413  if (len < sizeof( SrpHeader ))
414  {
415  _stats.rx_err_fmt++;
416  return;
417  }
418  SrpMessage * msgPtr = (SrpMessage *)udpPayload;
419 #ifndef SRP_LITE
420  int i;
421  int cfm = ( msgPtr->hdr.flags & SRP_FLG_ACK_MASK ) >> SRP_FLG_ACK_SHIFT;
422 
423  for (i = 0; i < cfm; ++i) {
424  srpTxCfm(rxAddr, msgPtr->hdr.ackId[i]);
425  }
426 #else
427  int cfm = ( msgPtr->hdr.flags & SRP_FLG_ACK_MASK ) >> SRP_FLG_ACK_SHIFT;
428  if (cfm > 0) {
429  _stats.rx_drop_ack++;
430  }
431 #endif
432 
433  if (msgPtr->hdr.flags & SRP_FLG_MSG) {
434  if (srpRxNew(rxAddr, msgPtr->hdr.msgId)) {
435  _srpRx(rxAddr, msgPtr->content, len - sizeof( SrpHeader ));
436  }
437  }
438 
439  srpProcess();
440 
441 }
442 
443 
444 
445 /*!
446  * Invoked by application for sending an SRP packet.
447  */
448 
449 
450 #ifndef SRP_LITE
451 bool srpTx(SockAddr * txAddr, uint8_t * message, int len)
452 {
453  _TCD(srpTx, "Packet size: %d", len);
454  _TCD(srpTx, "TX Free: %d, used = %d, read = %d, write = %d", vqFree(&_srpTxQueue),
455  _srpTxQueue.used, _srpTxQueue.read, _srpTxQueue.write);
456  // check if there is enough space to queue.
457  if (vqFree(&_srpTxQueue) < ( len + sizeof(SrpHeader) ) ) {
458  logWarn("TX queue full, cannot create message");
459  return false;
460  }
461  if (qFull(&_srpTxRecQueue)) {
462 #ifdef SRP_VERBOSE
463  logWarn("TX record queue full, cannot create message");
464 #endif
465  return false;
466  }
467 
468  // fill in preliminary information
469  memcpy(_srpSwap.content, message, len);
470  _srpSwap.hdr.msgId = _srpTxId ++;
471  _srpSwap.hdr.flags = SRP_FLG_MSG;
472  _TCD(srpProcessTx, "Transmitting lmsgId=%d", _srpSwap.hdr.msgId);
473  // transmit the packet
474  srpUdpTransmit(txAddr, len, false);
475 
476  // queue it for resend (if requird)
477  const SrpTxRec qRec =
478  {
479  .addr = *txAddr,
480  .timeout = srpTimeOutNew( _SRP_RESEND_TIMEOUT + ( rand() % _SRP_RESEND_SPREAD ) ),
481  .flags = _SRP_TX_CNT_SET( 0 ),
482  .msgId = _srpSwap.hdr.msgId
483  };
484 
485  qQueue(&_srpTxRecQueue, (uint8_t *)&qRec);
486 // printf("srpTx: Queuing packet of length %d\n", len + sizeof(SrpHeader));
487  vqQueue(&_srpTxQueue, len + sizeof(SrpHeader), (uint8_t *)&_srpSwap);
488  return true;
489 }
490 
491 
492 static bool srpProcessTx()
493 {
494  // First we're going to purse the retransmit queue.
495  // get first transmit record.
496  SrpTxRec * txRecPtr = qFirst(&_srpTxRecQueue);
497 
498  // if its not null.
499  while (txRecPtr != NULL)
500  {
501  // check if it is not confirmed (else we can remove it)
502  if (! ( txRecPtr->flags & _SRP_TXF_CONFIRMED ) )
503  {
504  // check if its time to resend (first message).
505  if (!srpTimeOut(txRecPtr->timeout)) {
506  // not time yet,
507  txRecPtr = NULL;
508  break;
509  }
510 
511  if ( _SRP_TX_CNT_GET(txRecPtr->flags) < SRP_RESEND_MAX) {
512  // we need to resend this one.
513  break;
514  } else {
515  _srpLost(&(txRecPtr->addr), txRecPtr->msgId);
516 #ifdef SRP_VERBOSE
517  logWarn("Lost packet: SockAddr=0x%08x msgId=%d",
518  txRecPtr->addr.ip, txRecPtr->msgId);
519 #endif
520 // printf("Packet with id %d lost\n", txRecPtr->msgId);
521  }
522  }
523 
524  qDeQueueIP(&_srpTxRecQueue); // remove tx record from queue.
525  vqRemove(&_srpTxQueue); // remove message from queue
526  txRecPtr = qFirst(&_srpTxRecQueue); // poll next record (if any)
527  }
528 
529  // nothing to transmit
530  if (txRecPtr == NULL /* && removeConfirmQueue > 0 */)
531  {
532  SockAddr addr = {0, 0};
533 
534  return srpUdpTransmit(&addr, 0, false);
535  }
536  else
537  {
538  // there is something to send.
539 
540  SrpTxRec txRec;
541  uint16_t len = sizeof(_srpSwap);
542 
543  // dequeue required information
544  qDeQueue(&_srpTxRecQueue, &txRec);
545 
546  vqDeQueue(&_srpTxQueue, &len, (uint8_t *)&_srpSwap);
547  _TCD(srpProcessTx, "Retransmitting lmsgId=%d", txRec.msgId);
548  // transmit again
549  srpUdpTransmit(&(txRec.addr), len - sizeof(SrpHeader), false);
550 
551  // reset timeout properties
552 
553  int cnt = _SRP_TX_CNT_GET( txRec.flags );
554 
555  cnt++;
556 
557  txRec.flags = ( txRec.flags & ~_SRP_TXF_CNT_MASK ) |
558  _SRP_TX_CNT_SET( cnt );
559 
560  // incremental backup:
561  // - timeouts are increased each resend + random value
562 
563 
564  txRec.timeout = srpTimeOutNew( ( _SRP_RESEND_TIMEOUT * cnt )
565  + ( rand() % _SRP_RESEND_SPREAD ) );
566 
567  // put in back of queue again.
568  // printf("srpProcess: Queuing packet of length %d\n", len);
569  qQueue(&_srpTxRecQueue, (uint8_t *)&txRec);
570  vqQueue(&_srpTxQueue, len, (uint8_t *)&_srpSwap);
571  return true;
572  }
573 
574 
575  return false;
576 
577 }
578 
579 #endif
580 
581 #ifdef SRP_LITE
582 
583 /*!
584  * Invoked by application for sending an SRP packet.
585  */
586 bool srpTx(SockAddr * txAddr, uint8_t * message, int len)
587 {
588  _TCD(srpTx, "Packet size: %d", len);
589 
590  // FIX 2019-03-21: Now check if returned value is realistic
591  if (len < 0 || len > SRP_MAX_PAYLOAD) {
592  logError("Invalid TX length! %d", len);
593  _stats.tx_err += 1;
594  return false;
595  }
596 
597  // fill in preliminary information
598  memcpy(_srpSwap.content, message, len);
599  _srpSwap.hdr.msgId = _srpTxId ++;
600  _srpSwap.hdr.flags = SRP_FLG_MSG | SRP_FLG_DONTACK;
601  _TCD(srpProcessTx, "Transmitting noack lmsgId=%d", _srpSwap.hdr.msgId);
602  // transmit the packet
603 
604  srpUdpTransmit(txAddr, len, true);
605  return true;
606 }
607 
608 static bool srpProcessTx()
609 {
610  SockAddr addr = {0, 0};
611  return srpUdpTransmit(&addr, 0, true);
612 }
613 
614 
615 #endif
616 
617 
618 static void srpProcessRx()
619 {
620  // does some administration for the RX cache.
621  SrpRxEntry * curEntry;
622  for (curEntry = _srpRxCacheFirst; curEntry <= _srpRxCacheLast; ++curEntry)
623  {
624  if (curEntry->flags & _SRP_RXF_USED)
625  {
626  if (srpTimeOut(curEntry->timeout)) {
627  _TCD(srpProcessRx, "Freeing RX cache entry for rmsgId=%d", curEntry->msgId);
628  curEntry->flags = 0; // free it
629  }
630  }
631  }
632 
633 }
634 
635 
637 {
638  bool r = srpProcessTx();
639  while (r) {
640  r = srpProcessTx();
641  }
642  srpProcessRx();
643 }
644 
645 /*!
646  * Initializes the simple retransmission protocol.
647  */
648 void srpInit()
649 {
650  // check if the max age is not too high, for safety its 16384. So if the timer runs at
651  // a 1000 Hz, the maximum age of a message is 16 seconds.
652  assert ( _SRP_CACHE_MAX_AGE < (1 << 14));
653 
654  _srpTxId = rand() & 0xFF;
655 
656  schdRegister(srpProcess, false, &_srpSchdPeriodicId);
657  schdRunPeriodic(_srpSchdPeriodicId, SRP_RESEND_TIMEOUT / 2);
658 }
#define SRP_TX_QUEUE_SIZE
Transmit queue buffer size.
Definition: srp.h:31
A variable length queue implementation.
bool vqDeQueue(VarQueue *const vq, uint16_t *length, uint8_t *buffer)
DeQueues an element from the queue.
Definition: varqueue.c:50
static bool qFull(Queue *q)
Returns whether or not the queue is full.
Definition: queue.h:249
static void * qNext(Queue *q, void *ptr)
Peek at the next element in the queue.
Definition: queue.h:236
Definition: srp.c:89
void schdRunPeriodic(int taskId, int interval)
Schedule a task to run periodically.
Definition: scheduler.c:212
bool vqQueue(VarQueue *const vq, uint16_t length, uint8_t *buffer)
Queues an element on the queue.
Definition: varqueue.c:24
bool srpTx(SockAddr *txAddr, uint8_t *message, int len)
Invoked by application for sending an SRP packet.
Definition: srp.c:586
#define SRP_RESEND_MAX
Max number of resends.
Definition: srp.h:34
void _srpUdpTx(SockAddr *txAddr, uint8_t *udpPayload, int len)
Transmit UDP packet.
Definition: network.c:393
#define SRP_RESEND_TIMEOUT
Resend time-out in ms.
Definition: srp.h:33
bool schdRegister(SchdTaskF task, bool priority, int *taskId)
Register a task with the scheduler.
Definition: scheduler.c:95
Definition: srp.c:129
void _srpLost(SockAddr *addr, uint8_t msgId)
Stub, invoked when an SRP message is lost.
Definition: network.c:657
SRP or Simple Retransmission Protocol is a protocol which retransmits packets if they have not been c...
Simple task scheduler for tasks.
void srpDumpStatus()
Outputs SRP status information.
Definition: srp.c:153
#define STR(EXPR)
Stringyfies an expression.
Definition: macro.h:37
Queue is created in statically allocated memory.
uint32_t ip
IP address.
Definition: net.h:33
#define logWarn(MSG,...)
Format a log message with warning level.
Definition: log.h:219
void srpProcess()
Should be called periodically to process any pending requests.
Definition: srp.c:636
void srpUdpRx(SockAddr *rxAddr, uint8_t *udpPayload, int len)
Invoked by UDP stack for receiving a SRP packet.
Definition: srp.c:408
static bool sockAddrEq(SockAddr *addr1, SockAddr *addr2)
Checks if two socket addresses are equal.
Definition: net.h:51
Header used by SRP protocol.
Definition: srp.h:52
Combination of IP address and port.
Definition: net.h:31
#define VQ_INIT(NAME, SIZE)
Initializes the variable length queue.
Definition: varqueue.h:66
static void * qFirst(Queue *q)
Peek at the first element in the queue.
Definition: queue.h:209
#define SRP_FLG_MSG
Contains message.
Definition: srp.h:38
static bool qDeQueue(Queue *q, void *data)
Dequeue an element from the front of the queue.
Definition: queue.h:173
#define SRP_TX_MAX_QUEUE
Allow up to 32 items on the TX queue.
Definition: srp.h:32
#define CLE(A, B, BITS)
Cyclic comparison function Less Or Equal To.
Definition: macro.h:102
#define SRP_MAX_ACKS
Maximum number of acknowledges.
Definition: srp.h:46
#define SRP_FLG_DONTACK
No ack required.
Definition: srp.h:39
static bool qQueue(Queue *q, void *data)
Queue data to the end of the queue.
Definition: queue.h:125
#define logError(MSG,...)
Format a log message with fatal level.
Definition: log.h:232
uint16_t vqFree(VarQueue *const vq)
Returns the number of bytes free for the next element.
Definition: varqueue.c:114
#define LOG_DEF(NAME,...)
Define a logger for a module.
Definition: log.h:129
#define SRP_FLG_ACK_SHIFT
Shift for the number of acks.
Definition: srp.h:40
#define Q_INIT(NAME, ENTRY_SIZE, CAPACITY)
Convenience Macro, defines and inits queue.
Definition: queue.h:84
#define SRP_FLG_ACK_MASK
Mask for the number of acks.
Definition: srp.h:41
#define CGE(A, B, BITS)
Cyclic comparison function Greater Of Equal To.
Definition: macro.h:78
Provides common macros.
#define SRP_MAX_PAYLOAD
maximum size of the payload of a SRP message.
Definition: srp.h:44
#define SRP_RX_MAX_CACHE
Max receive confirms.
Definition: srp.h:35
Implements a generic logger facility.
void _srpRx(SockAddr *rxAddr, uint8_t *message, int len)
Process a received SRP packet.
Definition: network.c:605
void * qDeQueueIP(Queue *q)
Dequeue an element from the front of the queue in place.
Definition: queue.c:33
void srpInit()
Initializes the SRP protocol engine.
Definition: srp.c:648
bool vqRemove(VarQueue *const vq)
Removes the first element from the queue (not the last).
Definition: varqueue.c:98