83 lines
2.4 KiB
C
83 lines
2.4 KiB
C
|
#include "node.h"
|
||
|
#include "coap_timer.h"
|
||
|
#include "os_type.h"
|
||
|
#include "osapi.h"
|
||
|
#include "pm/swtimer.h"
|
||
|
|
||
|
static os_timer_t coap_timer;
|
||
|
static coap_tick_t basetime = 0;
|
||
|
|
||
|
void coap_timer_elapsed(coap_tick_t *diff){
|
||
|
coap_tick_t now = system_get_time() / 1000; // coap_tick_t is in ms. also sys_timer
|
||
|
if(now>=basetime){
|
||
|
*diff = now-basetime;
|
||
|
} else {
|
||
|
*diff = now + SYS_TIME_MAX -basetime;
|
||
|
}
|
||
|
basetime = now;
|
||
|
}
|
||
|
|
||
|
void coap_timer_tick(void *arg){
|
||
|
if( !arg )
|
||
|
return;
|
||
|
coap_queue_t **queue = (coap_queue_t **)arg;
|
||
|
if( !(*queue) )
|
||
|
return;
|
||
|
|
||
|
coap_queue_t *node = coap_pop_next( queue );
|
||
|
/* re-initialize timeout when maximum number of retransmissions are not reached yet */
|
||
|
if (node->retransmit_cnt < COAP_DEFAULT_MAX_RETRANSMIT) {
|
||
|
node->retransmit_cnt++;
|
||
|
node->t = node->timeout << node->retransmit_cnt;
|
||
|
|
||
|
NODE_DBG("** retransmission #%d of transaction %d\n",
|
||
|
node->retransmit_cnt, (((uint16_t)(node->pdu->pkt->hdr.id[0]))<<8)+node->pdu->pkt->hdr.id[1]);
|
||
|
node->id = coap_send(node->pconn, node->pdu);
|
||
|
if (COAP_INVALID_TID == node->id) {
|
||
|
NODE_DBG("retransmission: error sending pdu\n");
|
||
|
coap_delete_node(node);
|
||
|
} else {
|
||
|
coap_insert_node(queue, node);
|
||
|
}
|
||
|
} else {
|
||
|
/* And finally delete the node */
|
||
|
coap_delete_node( node );
|
||
|
}
|
||
|
|
||
|
coap_timer_start(queue);
|
||
|
}
|
||
|
|
||
|
void coap_timer_setup(coap_queue_t ** queue, coap_tick_t t){
|
||
|
os_timer_disarm(&coap_timer);
|
||
|
os_timer_setfn(&coap_timer, (os_timer_func_t *)coap_timer_tick, queue);
|
||
|
SWTIMER_REG_CB(coap_timer_tick, SWTIMER_RESUME);
|
||
|
//coap_timer_tick processes a queue, my guess is that it is ok to resume the timer from where it left off
|
||
|
os_timer_arm(&coap_timer, t, 0); // no repeat
|
||
|
}
|
||
|
|
||
|
void coap_timer_stop(void){
|
||
|
os_timer_disarm(&coap_timer);
|
||
|
}
|
||
|
|
||
|
void coap_timer_update(coap_queue_t ** queue){
|
||
|
if (!queue)
|
||
|
return;
|
||
|
coap_tick_t diff = 0;
|
||
|
coap_queue_t *first = *queue;
|
||
|
coap_timer_elapsed(&diff); // update: basetime = now, diff = now - oldbase, means time elapsed
|
||
|
if (first) {
|
||
|
// diff ms time is elapsed, re-calculate the first node->t
|
||
|
if (first->t >= diff){
|
||
|
first->t -= diff;
|
||
|
} else {
|
||
|
first->t = 0; // when timer enabled, time out almost immediately
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void coap_timer_start(coap_queue_t ** queue){
|
||
|
if(*queue){ // if there is node in the queue, set timeout to its ->t.
|
||
|
coap_timer_setup(queue, (*queue)->t);
|
||
|
}
|
||
|
}
|