## Timer Timer — STUN timer Usage |

## Stability Level

Stable, unless otherwise indicated

## Functions

void | stun_timer_start ()
void | stun_timer_start_reliable ()
StunUsageTimerReturn | stun_timer_refresh ()
unsigned | stun_timer_remainder ()

## Types and Values

typedef | StunTimer
enum | StunUsageTimerReturn
#define | STUN_TIMER_DEFAULT_MAX_RETRANSMISSIONS
#define | STUN_TIMER_DEFAULT_RELIABLE_TIMEOUT
#define | STUN_TIMER_DEFAULT_TIMEOUT

## Includes

    #include <stun/usages/timer.h>

## Description

The STUN timer usage is a set of helpful utility functions that allows you to easily track when a STUN message should be retransmitted or considered as timed out.

Example 3. Simple example on how to use the timer usage

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    StunTimer timer;
    unsigned remainder;
    StunUsageTimerReturn ret;

    // Build the message, etc..
    ...

    // Send the message and start the timer
    send(socket, request, sizeof(request));
    stun_timer_start(&timer, STUN_TIMER_DEFAULT_TIMEOUT,
                     STUN_TIMER_DEFAULT_MAX_RETRANSMISSIONS);

    // Loop until we get the response
    for (;;) {
      remainder = stun_timer_remainder(&timer);

      // Poll the socket until data is received or the timer expires
      if (poll (&pollfd, 1, delay) <= 0) {
        // Time out and no response was received
        ret = stun_timer_refresh (&timer);
        if (ret == STUN_USAGE_TIMER_RETURN_TIMEOUT) {
          // Transaction timed out
          break;
        } else if (ret == STUN_USAGE_TIMER_RETURN_RETRANSMIT) {
          // A retransmission is necessary
          send(socket, request, sizeof(request));
          continue;
        } else if (ret == STUN_USAGE_TIMER_RETURN_SUCCESS) {
          // The refresh succeeded and nothing has to be done, continue polling
          continue;
        }
      } else {
        // We received a response, read it
        recv(socket, response, sizeof(response));
        break;
      }
    }

    // Check if the transaction timed out or not
    if (ret == STUN_USAGE_TIMER_RETURN_TIMEOUT) {
      // do whatever needs to be done in that case
    } else {
      // Parse the response
    }

## Functions

### stun_timer_start ()

    void
    stun_timer_start (StunTimer *timer,
                      unsigned int initial_timeout,
                      unsigned int max_retransmissions);

Starts a STUN transaction retransmission timer. This should be called as soon as you send the message for the first time on a UDP socket. The timeout before the next retransmission is set to `initial_timeout` , then each time a packet is retransmited, that timeout will be doubled, until the `max_retransmissions` retransmissions limit is reached.

To determine the total timeout value, one can use the following equation :

     total_timeout =  initial_timeout * (2^(max_retransmissions + 1) - 1);

See also: STUN_TIMER_DEFAULT_TIMEOUT

See also: STUN_TIMER_DEFAULT_MAX_RETRANSMISSIONS

#### Parameters

timer | The StunTimer to start |
initial_timeout | The initial timeout to use before the first retransmission |
max_retransmissions | The maximum number of transmissions before the StunTimer times out |

### stun_timer_start_reliable ()

    void
    stun_timer_start_reliable (StunTimer *timer,
                               unsigned int initial_timeout);

Starts a STUN transaction retransmission timer for a reliable transport. This should be called as soon as you send the message for the first time on a TCP socket

#### Parameters

timer | The StunTimer to start |
initial_timeout | The initial timeout to use before the first retransmission |

### stun_timer_refresh ()

    StunUsageTimerReturn
    stun_timer_refresh (StunTimer *timer);

Updates a STUN transaction retransmission timer.

#### Parameters

timer | The StunTimer to refresh |

#### Returns

A StunUsageTimerReturn telling you what to do next

### stun_timer_remainder ()

    unsigned
    stun_timer_remainder (const StunTimer *timer);

Query the timer on the time left before the next refresh should be done

#### Parameters

timer | The StunTimer to query |

#### Returns

The time remaining for the timer to expire in milliseconds

## Types and Values

### StunTimer

    typedef struct stun_timer_s StunTimer;

An opaque structure representing a STUN transaction retransmission timer

### enum StunUsageTimerReturn

Return value of `stun_usage_timer_refresh()` which provides you with status information on the timer.

#### Members

STUN_USAGE_TIMER_RETURN_SUCCESS | The timer was refreshed successfully and there is nothing to be done |
STUN_USAGE_TIMER_RETURN_RETRANSMIT | The timer expired and the message should be retransmitted now. |
STUN_USAGE_TIMER_RETURN_TIMEOUT | The timer expired as well as all the retransmissions, the transaction timed out |

### STUN_TIMER_DEFAULT_MAX_RETRANSMISSIONS

    #define STUN_TIMER_DEFAULT_MAX_RETRANSMISSIONS 7

The default maximum retransmissions allowed before a timer decides to timeout

### STUN_TIMER_DEFAULT_RELIABLE_TIMEOUT

    #define STUN_TIMER_DEFAULT_RELIABLE_TIMEOUT 7900

The default intial timeout to use for a reliable timer

### STUN_TIMER_DEFAULT_TIMEOUT

    #define STUN_TIMER_DEFAULT_TIMEOUT 200

The default intial timeout to use for the timer RFC recommendds 500, but it's ridiculous, 50ms is known to work in most cases as it is also what is used by SIP style VoIP when sending A-Law and mu-Law audio, so 200ms should be hyper safe.