timer.h 7.32 KB
Newer Older
1 2 3
/*
 * This file is part of the Nice GLib ICE library.
 *
4 5 6
 * (C) 2008-2009 Collabora Ltd.
 *  Contact: Youness Alaoui
 * (C) 2007-2009 Nokia Corporation. All rights reserved.
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
 *  Contact: Rémi Denis-Courmont
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is the Nice GLib ICE library.
 *
 * The Initial Developers of the Original Code are Collabora Ltd and Nokia
 * Corporation. All Rights Reserved.
 *
 * Contributors:
25
 *   Youness Alaoui, Collabora Ltd.
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
 *   Rémi Denis-Courmont, Nokia
 *
 * Alternatively, the contents of this file may be used under the terms of the
 * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
 * case the provisions of LGPL are applicable instead of those above. If you
 * wish to allow use of your version of this file only under the terms of the
 * LGPL and not to allow others to use your version of this file under the
 * MPL, indicate your decision by deleting the provisions above and replace
 * them with the notice and other provisions required by the LGPL. If you do
 * not delete the provisions above, a recipient may use your version of this
 * file under either the MPL or the LGPL.
 */

#ifndef STUN_TIMER_H
# define STUN_TIMER_H 1

42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
/**
 * SECTION:timer
 * @short_description: STUN timer Usage
 * @include: stun/usages/timer.h
 * @stability: Stable
 *
 * 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>
   <title>Simple example on how to use the timer usage</title>
   <programlisting>
   StunTimer timer;
   unsigned remainder;
   StunUsageTimerReturn ret;

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

   // Send the message and start the timer
   send(socket, request, sizeof(request));
65 66
   stun_timer_start(&timer, STUN_TIMER_DEFAULT_TIMEOUT,
                    STUN_TIMER_DEFAULT_MAX_RETRANSMISSIONS);
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102

   // 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
   }

   </programlisting>
 </example>
103 104
 */

105 106 107
#ifdef _WIN32
#include <winsock2.h>
#else
108
# include <sys/types.h>
109
# include <sys/time.h>
110
# include <time.h>
111
#endif
112

113

114 115 116 117 118 119 120 121
/**
 * StunTimer:
 *
 * An opaque structure representing a STUN transaction retransmission timer
 */
typedef struct stun_timer_s StunTimer;

struct stun_timer_s {
122
  struct timeval deadline;
123
  unsigned delay;
124 125
  unsigned retransmissions;
  unsigned max_retransmissions;
126 127
};

128

129 130 131 132
/**
 * STUN_TIMER_DEFAULT_TIMEOUT:
 *
 * The default intial timeout to use for the timer
133 134
 * 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
135 136 137 138 139
 * mu-Law audio, so 200ms should be hyper safe. With an initial timeout
 * of 200ms, a default of 7 transmissions, the last timeout will be
 * 16 * 200ms, and we expect to receive a response from the stun server
 * before (1 + 2 + 4 + 8 + 16 + 32 + 16) * 200ms = 15200 ms after the initial
 * stun request has been sent.
140
 */
141
#define STUN_TIMER_DEFAULT_TIMEOUT 200
142 143 144 145 146 147

/**
 * STUN_TIMER_DEFAULT_MAX_RETRANSMISSIONS:
 *
 * The default maximum retransmissions allowed before a timer decides to timeout
 */
148
#define STUN_TIMER_DEFAULT_MAX_RETRANSMISSIONS 7
149 150 151 152 153 154 155 156

/**
 * STUN_TIMER_DEFAULT_RELIABLE_TIMEOUT:
 *
 * The default intial timeout to use for a reliable timer
 */
#define STUN_TIMER_DEFAULT_RELIABLE_TIMEOUT 7900

157 158 159 160 161 162 163 164 165 166 167 168
/**
 * StunUsageTimerReturn:
 * @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
 *
 * Return value of stun_usage_timer_refresh() which provides you with status
 * information on the timer.
 */
169 170 171 172 173
typedef enum {
  STUN_USAGE_TIMER_RETURN_SUCCESS,
  STUN_USAGE_TIMER_RETURN_RETRANSMIT,
  STUN_USAGE_TIMER_RETURN_TIMEOUT
} StunUsageTimerReturn;
174 175 176 177 178

# ifdef __cplusplus
extern "C" {
# endif

179

180
/**
181 182
 * stun_timer_start:
 * @timer: The #StunTimer to start
183 184 185
 * @initial_timeout: The initial timeout to use before the first retransmission
 * @max_retransmissions: The maximum number of transmissions before the
 * #StunTimer times out
186
 *
187
 * Starts a STUN transaction retransmission timer.
188
 * This should be called as soon as you send the message for the first time on
189 190 191 192 193 194 195 196 197 198 199 200 201 202
 * 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.
 * <para>
 * To determine the total timeout value, one can use the following equation :
 <programlisting>
 total_timeout =  initial_timeout * (2^(max_retransmissions + 1) - 1);
 </programlisting>
 * </para>
 *
 * See also: #STUN_TIMER_DEFAULT_TIMEOUT
 *
 * See also: #STUN_TIMER_DEFAULT_MAX_RETRANSMISSIONS
203
 */
204 205
void stun_timer_start (StunTimer *timer, unsigned int initial_timeout,
      unsigned int max_retransmissions);
206 207 208 209

/**
 * stun_timer_start_reliable:
 * @timer: The #StunTimer to start
210
 * @initial_timeout: The initial timeout to use before the first retransmission
211 212 213 214 215
 *
 * 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
 */
216
void stun_timer_start_reliable (StunTimer *timer, unsigned int initial_timeout);
217 218

/**
219 220 221
 * stun_timer_refresh:
 * @timer: The #StunTimer to refresh
 *
222
 * Updates a STUN transaction retransmission timer.
223
 * Returns: A #StunUsageTimerReturn telling you what to do next
224
 */
225
StunUsageTimerReturn stun_timer_refresh (StunTimer *timer);
226 227 228 229 230 231 232 233

/**
 * stun_timer_remainder:
 * @timer: The #StunTimer to query
 *
 * Query the timer on the time left before the next refresh should be done
 * Returns: The time remaining for the timer to expire in milliseconds
 */
234
unsigned stun_timer_remainder (const StunTimer *timer);
235 236 237 238 239 240

# ifdef __cplusplus
}
# endif

#endif /* !STUN_TIMER_H */