summaryrefslogtreecommitdiffstats
path: root/src/timekeeper.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/timekeeper.h')
-rw-r--r--src/timekeeper.h267
1 files changed, 267 insertions, 0 deletions
diff --git a/src/timekeeper.h b/src/timekeeper.h
new file mode 100644
index 0000000..4ed2565
--- /dev/null
+++ b/src/timekeeper.h
@@ -0,0 +1,267 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifndef _TIMEKEEPER_H
+#define _TIMEKEEPER_H
+
+#include <list>
+#include "id_object.h"
+#include "protocol.h"
+#include "transaction.h"
+#include "threads/mutex.h"
+#include "threads/sema.h"
+
+using namespace std;
+
+// Forward declarations
+class t_phone;
+class t_line;
+class t_subscription;
+
+/** Timer type */
+enum t_timer_type {
+ TMR_TRANSACTION, /**< Transaction timer */
+ TMR_PHONE, /**< Timer associated with the phone */
+ TMR_LINE, /**< Timer associated with a line */
+ TMR_SUBSCRIBE, /**< Subscription timer */
+ TMR_PUBLISH, /**< Publication timer */
+ TMR_STUN_TRANSACTION /**< STUN timer */
+};
+////////////////////////////////////////////////////////////////
+// General timer.
+////////////////////////////////////////////////////////////////
+// Instances should be created from subclasses.
+class t_timer : public t_id_object {
+private:
+ long duration; // milliseconds
+ long relative_duration; // milliseconds
+
+public:
+ t_timer(long dur);
+ virtual ~t_timer() {}
+
+ // This method is invoked on expiry
+ // Subclasses should implent the action to be taken.
+ virtual void expired(void) = 0;
+
+ long get_duration(void) const;
+ long get_relative_duration(void) const;
+ void set_relative_duration(long d);
+ virtual t_timer *copy(void) const = 0;
+ virtual t_timer_type get_type(void) const = 0;
+
+ // Get the name of the timer (for debugging purposes)
+ virtual string get_name(void) const = 0;
+};
+
+////////////////////////////////////////////////////////////////
+// Transaction timer
+////////////////////////////////////////////////////////////////
+class t_tmr_transaction : public t_timer {
+private:
+ unsigned short transaction_id;
+ t_sip_timer sip_timer;
+
+public:
+ t_tmr_transaction(long dur, t_sip_timer tmr, unsigned short tid);
+
+ void expired(void);
+ t_timer *copy(void) const;
+ t_timer_type get_type(void) const;
+ unsigned short get_tid(void) const;
+ t_sip_timer get_sip_timer(void) const;
+ string get_name(void) const;
+};
+
+////////////////////////////////////////////////////////////////
+// Phone timer
+////////////////////////////////////////////////////////////////
+class t_tmr_phone : public t_timer {
+private:
+ t_phone *the_phone;
+ t_phone_timer phone_timer;
+
+public:
+ t_tmr_phone(long dur, t_phone_timer ptmr, t_phone *p);
+
+ void expired(void);
+ t_timer *copy(void) const;
+ t_timer_type get_type(void) const;
+ t_phone_timer get_phone_timer(void) const;
+ t_phone *get_phone(void) const;
+ string get_name(void) const;
+};
+
+////////////////////////////////////////////////////////////////
+// Line timer
+////////////////////////////////////////////////////////////////
+class t_tmr_line : public t_timer {
+private:
+ t_object_id line_id;
+ t_line_timer line_timer;
+ t_object_id dialog_id;
+
+public:
+ t_tmr_line(long dur, t_line_timer ltmr, t_object_id lid,
+ t_object_id d);
+
+ void expired(void);
+ t_timer *copy(void) const;
+ t_timer_type get_type(void) const;
+ t_line_timer get_line_timer(void) const;
+ t_object_id get_line_id(void) const;
+ t_object_id get_dialog_id(void) const;
+ string get_name(void) const;
+};
+
+////////////////////////////////////////////////////////////////
+// Subscribe timer
+////////////////////////////////////////////////////////////////
+class t_tmr_subscribe : public t_timer {
+private:
+ t_subscribe_timer subscribe_timer;
+ t_object_id line_id;
+ t_object_id dialog_id;
+ string sub_event_type;
+ string sub_event_id;
+
+
+public:
+ t_tmr_subscribe(long dur, t_subscribe_timer stmr, t_object_id lid, t_object_id d,
+ const string &event_type, const string &event_id);
+
+ void expired(void);
+ t_timer *copy(void) const;
+ t_timer_type get_type(void) const;
+ t_subscribe_timer get_subscribe_timer(void) const;
+ t_object_id get_line_id(void) const;
+ t_object_id get_dialog_id(void) const;
+ string get_sub_event_type(void) const;
+ string get_sub_event_id(void) const;
+ string get_name(void) const;
+};
+
+/** Publication timer */
+class t_tmr_publish : public t_timer {
+private:
+ t_publish_timer publish_timer; /**< Type of timer */
+ string event_type; /**< Event type of publication */
+
+
+public:
+ t_tmr_publish(long dur, t_publish_timer ptmr, const string &_event_type);
+
+ void expired(void);
+ t_timer *copy(void) const;
+ t_timer_type get_type(void) const;
+ t_publish_timer get_publish_timer(void) const;
+ string get_name(void) const;
+};
+
+////////////////////////////////////////////////////////////////
+// STUN transaction timer
+////////////////////////////////////////////////////////////////
+class t_tmr_stun_trans : public t_timer {
+private:
+ unsigned short transaction_id;
+ t_stun_timer stun_timer;
+
+public:
+ t_tmr_stun_trans(long dur, t_stun_timer tmr, unsigned short tid);
+
+ void expired(void);
+ t_timer *copy(void) const;
+ t_timer_type get_type(void) const;
+ unsigned short get_tid(void) const;
+ t_stun_timer get_stun_timer(void) const;
+ string get_name(void) const;
+};
+
+
+////////////////////////////////////////////////////////////////
+// Timekeeper
+////////////////////////////////////////////////////////////////
+// A timekeeper keeps track of multiple timers per thread.
+// Only one single thread should call the methods of a single
+// timekeeper. Multiple threads using the same timekeeper will
+// cause havoc.
+
+class t_timekeeper {
+private:
+ // List of running timers in order of timeout. As there
+ // is only 1 real timer running on the OS. Each timer gets
+ // a duration relative to its predecessor in the list.
+ list<t_timer *> timer_list;
+
+ // Mutex to synchronize timekeeper actions.
+ t_mutex mutex;
+
+ // Indicate if current timer was stopped, but not removed
+ // to prevent race conditions. Expiry of a stopped timer
+ // will not trigger any actions.
+ bool stopped;
+
+ // Indicate if the current timer expired while the
+ // mutex was locked.
+ bool timer_expired;
+
+ // Every method should start with locking the timekeeper
+ // and end with unlocking. The unlocking method will check
+ // if a timer expired during the locked state. If so, then
+ // the expiry will be processed.
+ void lock(void);
+ void unlock(void);
+
+ // Start the timekeeper from the thread that will handle
+ // the SIGALRM signal. Start must be called before the
+ // timekeeper can be used.
+ void start(void (*timeout_handler)(int));
+
+ // Start a timer. The timer id is returned. This id is
+ // needed to stop a timer. Pointer t should not be used
+ // or deleted after starting. When the timer expires or
+ // is stopped it will be deleted.
+ void start_timer(t_timer *t);
+
+ void stop_timer(t_object_id id);
+
+public:
+ // The timeout_handler must be a signal handler for SIGALRM
+ t_timekeeper();
+ ~t_timekeeper();
+
+ // Report that the current timer has expired.
+ void report_expiry(void);
+
+ // Get remaining time of a running timer.
+ // Returns 0 if the timer is not running anymore.
+ unsigned long get_remaining_time(t_object_id timer_id);
+
+ // Main loop to be run in a separate thread
+ void run(void);
+};
+
+// Entry function for timekeeper thread
+void *timekeeper_main(void *arg);
+
+// Entry function of the thread waiting for SIGALRM
+// A dedicated thread is started to catch the SIGALRM signal and take
+// the appropriate action. All threads must block the SIGALRM signal.
+void *timekeeper_sigwait(void *arg);
+
+#endif