/* * 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. * * Simple example on how to use the timer usage 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 } */ #ifdef _WIN32 #include #else # include # include # include #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. * * 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 */ 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 */