timer.h 7.38 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
140
141
 * mu-Law audio, so 200ms should be hyper safe. With an initial timeout
 * of 200ms, a default of 5 transmissions, the last timeout will be
 * 4 * 200ms, and we expect to receive a response from the stun server
 * before (1 + 2 + 4 + 8 + 4) * 200ms = 3800 ms after the initial
 * stun request t1 has been sent:
 *
 * t1 ..200ms.. t2 ..400ms.. t3 ..800ms.. t4 ..1600ms.. t5 ..800ms.. X
142
 */
143
#define STUN_TIMER_DEFAULT_TIMEOUT 200
144
145
146
147
148
149

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

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

159
160
161
162
163
164
165
166
167
168
169
170
/**
 * 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.
 */
171
172
173
174
175
typedef enum {
  STUN_USAGE_TIMER_RETURN_SUCCESS,
  STUN_USAGE_TIMER_RETURN_RETRANSMIT,
  STUN_USAGE_TIMER_RETURN_TIMEOUT
} StunUsageTimerReturn;
176
177
178
179
180

# ifdef __cplusplus
extern "C" {
# endif

181

182
/**
183
184
 * stun_timer_start:
 * @timer: The #StunTimer to start
185
186
187
 * @initial_timeout: The initial timeout to use before the first retransmission
 * @max_retransmissions: The maximum number of transmissions before the
 * #StunTimer times out
188
 *
189
 * Starts a STUN transaction retransmission timer.
190
 * This should be called as soon as you send the message for the first time on
191
192
193
194
195
196
197
198
199
200
201
202
203
204
 * 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
205
 */
206
207
void stun_timer_start (StunTimer *timer, unsigned int initial_timeout,
      unsigned int max_retransmissions);
208
209
210
211

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

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

/**
 * 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
 */
236
unsigned stun_timer_remainder (const StunTimer *timer);
237
238
239
240
241
242

# ifdef __cplusplus
}
# endif

#endif /* !STUN_TIMER_H */