241 lines
7.3 KiB
C
241 lines
7.3 KiB
C
/*
|
|
* This file is part of the Nice GLib ICE library.
|
|
*
|
|
* (C) 2008-2009 Collabora Ltd.
|
|
* Contact: Youness Alaoui
|
|
* (C) 2007-2009 Nokia Corporation. All rights reserved.
|
|
* 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:
|
|
* Youness Alaoui, Collabora Ltd.
|
|
* 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
|
|
|
|
/**
|
|
* 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));
|
|
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
|
|
}
|
|
|
|
</programlisting>
|
|
</example>
|
|
*/
|
|
|
|
#ifdef _WIN32
|
|
#include <winsock2.h>
|
|
#else
|
|
# include <sys/types.h>
|
|
# include <sys/time.h>
|
|
# include <time.h>
|
|
#endif
|
|
|
|
|
|
/**
|
|
* StunTimer:
|
|
*
|
|
* An opaque structure representing a STUN transaction retransmission timer
|
|
*/
|
|
typedef struct stun_timer_s StunTimer;
|
|
|
|
struct stun_timer_s {
|
|
struct timeval deadline;
|
|
unsigned delay;
|
|
unsigned retransmissions;
|
|
unsigned max_retransmissions;
|
|
};
|
|
|
|
|
|
/**
|
|
* STUN_TIMER_DEFAULT_TIMEOUT:
|
|
*
|
|
* 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. 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.
|
|
*/
|
|
#define STUN_TIMER_DEFAULT_TIMEOUT 200
|
|
|
|
/**
|
|
* STUN_TIMER_DEFAULT_MAX_RETRANSMISSIONS:
|
|
*
|
|
* The default maximum retransmissions allowed before a timer decides to timeout
|
|
*/
|
|
#define STUN_TIMER_DEFAULT_MAX_RETRANSMISSIONS 7
|
|
|
|
/**
|
|
* STUN_TIMER_DEFAULT_RELIABLE_TIMEOUT:
|
|
*
|
|
* The default intial timeout to use for a reliable timer
|
|
*/
|
|
#define STUN_TIMER_DEFAULT_RELIABLE_TIMEOUT 7900
|
|
|
|
/**
|
|
* 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.
|
|
*/
|
|
typedef enum {
|
|
STUN_USAGE_TIMER_RETURN_SUCCESS,
|
|
STUN_USAGE_TIMER_RETURN_RETRANSMIT,
|
|
STUN_USAGE_TIMER_RETURN_TIMEOUT
|
|
} StunUsageTimerReturn;
|
|
|
|
# ifdef __cplusplus
|
|
extern "C" {
|
|
# endif
|
|
|
|
|
|
/**
|
|
* stun_timer_start:
|
|
* @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
|
|
*
|
|
* 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.
|
|
* <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
|
|
*/
|
|
void stun_timer_start (StunTimer *timer, unsigned int initial_timeout,
|
|
unsigned int max_retransmissions);
|
|
|
|
/**
|
|
* stun_timer_start_reliable:
|
|
* @timer: The #StunTimer to start
|
|
* @initial_timeout: The initial timeout to use before the first retransmission
|
|
*
|
|
* 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
|
|
*/
|
|
void stun_timer_start_reliable (StunTimer *timer, unsigned int initial_timeout);
|
|
|
|
/**
|
|
* stun_timer_refresh:
|
|
* @timer: The #StunTimer to refresh
|
|
*
|
|
* Updates a STUN transaction retransmission timer.
|
|
* Returns: A #StunUsageTimerReturn telling you what to do next
|
|
*/
|
|
StunUsageTimerReturn stun_timer_refresh (StunTimer *timer);
|
|
|
|
/**
|
|
* 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
|
|
*/
|
|
unsigned stun_timer_remainder (const StunTimer *timer);
|
|
|
|
# ifdef __cplusplus
|
|
}
|
|
# endif
|
|
|
|
#endif /* !STUN_TIMER_H */
|