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