coap_timer.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. #include "node.h"
  2. #include "coap_timer.h"
  3. #include "os_type.h"
  4. #include "pm/swtimer.h"
  5. static os_timer_t coap_timer;
  6. static coap_tick_t basetime = 0;
  7. void coap_timer_elapsed(coap_tick_t *diff){
  8. coap_tick_t now = system_get_time() / 1000; // coap_tick_t is in ms. also sys_timer
  9. if(now>=basetime){
  10. *diff = now-basetime;
  11. } else {
  12. *diff = now + SYS_TIME_MAX -basetime;
  13. }
  14. basetime = now;
  15. }
  16. void coap_timer_tick(void *arg){
  17. if( !arg )
  18. return;
  19. coap_queue_t **queue = (coap_queue_t **)arg;
  20. if( !(*queue) )
  21. return;
  22. coap_queue_t *node = coap_pop_next( queue );
  23. /* re-initialize timeout when maximum number of retransmissions are not reached yet */
  24. if (node->retransmit_cnt < COAP_DEFAULT_MAX_RETRANSMIT) {
  25. node->retransmit_cnt++;
  26. node->t = node->timeout << node->retransmit_cnt;
  27. NODE_DBG("** retransmission #%d of transaction %d\n",
  28. node->retransmit_cnt, (((uint16_t)(node->pdu->pkt->hdr.id[0]))<<8)+node->pdu->pkt->hdr.id[1]);
  29. node->id = coap_send(node->pconn, node->pdu);
  30. if (COAP_INVALID_TID == node->id) {
  31. NODE_DBG("retransmission: error sending pdu\n");
  32. coap_delete_node(node);
  33. } else {
  34. coap_insert_node(queue, node);
  35. }
  36. } else {
  37. /* And finally delete the node */
  38. coap_delete_node( node );
  39. }
  40. coap_timer_start(queue);
  41. }
  42. void coap_timer_setup(coap_queue_t ** queue, coap_tick_t t){
  43. os_timer_disarm(&coap_timer);
  44. os_timer_setfn(&coap_timer, (os_timer_func_t *)coap_timer_tick, queue);
  45. SWTIMER_REG_CB(coap_timer_tick, SWTIMER_RESUME);
  46. //coap_timer_tick processes a queue, my guess is that it is ok to resume the timer from where it left off
  47. os_timer_arm(&coap_timer, t, 0); // no repeat
  48. }
  49. void coap_timer_stop(void){
  50. os_timer_disarm(&coap_timer);
  51. }
  52. void coap_timer_update(coap_queue_t ** queue){
  53. if (!queue)
  54. return;
  55. coap_tick_t diff = 0;
  56. coap_queue_t *first = *queue;
  57. coap_timer_elapsed(&diff); // update: basetime = now, diff = now - oldbase, means time elapsed
  58. if (first) {
  59. // diff ms time is elapsed, re-calculate the first node->t
  60. if (first->t >= diff){
  61. first->t -= diff;
  62. } else {
  63. first->t = 0; // when timer enabled, time out almost immediately
  64. }
  65. }
  66. }
  67. void coap_timer_start(coap_queue_t ** queue){
  68. if(*queue){ // if there is node in the queue, set timeout to its ->t.
  69. coap_timer_setup(queue, (*queue)->t);
  70. }
  71. }