/*
Copyright (C) 2005-2007 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
*/
/**
* @file
* Threads communicate by passing events via event queues.
*/
#ifndef _EVENTS_H
#define _EVENTS_H
#include <queue>
#include "timekeeper.h"
#include "stun/stun.h"
#include "audio/audio_codecs.h"
#include "parser/sip_message.h"
#include "sockets/socket.h"
#include "threads/mutex.h"
#include "threads/sema.h"
using namespace std;
// Forward declarations
class t_userintf;
/** Different types of events. */
enum t_event_type {
EV_QUIT, /**< Generic quit event */
EV_NETWORK, /**< Network event, eg. SIP message from/to network */
EV_USER, /**< User event, eg. SIP message from/to user */
EV_TIMEOUT, /**< Timer expiry */
EV_FAILURE, /**< Failure, eg. transport failure */
EV_START_TIMER, /**< Start timer */
EV_STOP_TIMER, /**< Stop timer */
EV_ABORT_TRANS, /**< Abort transaction */
EV_STUN_REQUEST, /**< Outgoing STUN request */
EV_STUN_RESPONSE, /**< Received STUN response */
EV_NAT_KEEPALIVE, /**< Send a NAT keep alive packet */
EV_ICMP, /**< ICMP error */
EV_UI, /**< User interface event */
EV_ASYNC_RESPONSE, /**< Response on an asynchronous question */
};
/** Abstract parent class for all events */
class t_event {
public:
virtual ~t_event() {}
/** Get the type of this event. */
virtual t_event_type get_type(void) const = 0;
};
/**
* Generic quit event.
* The quit event instructs a thread to exit gracefully.
*/
class t_event_quit : public t_event {
public:
virtual ~t_event_quit();
virtual t_event_type get_type(void) const;
};
/**
* Network events.
* A network event is a SIP message going from the transaction manager
* to the network or v.v.
*/
class t_event_network : public t_event {
private:
/** The SIP message. */
t_sip_message *msg;
public:
unsigned int src_addr; /**< Source IP address of the SIP message (host order). */
unsigned short src_port; /**< Source port of the SIP message (host order). */
unsigned int dst_addr; /**< Destination IP address of the SIP message (host order). */
unsigned short dst_port; /**< Destiantion port of the SIP message (host order). */
/**
* Constructor.
* The event will keep a copy of the SIP message.
* @param m [in] The SIP message.
*/
t_event_network(t_sip_message *m);
~t_event_network();
t_event_type get_type(void) const;
/**
* Get the SIP message.
* @return Pointer to the SIP message inside this event.
*/
t_sip_message *get_msg(void) const;
};
/**
* User events.
* A user event is a SIP message going from the user to the
* transaction manager or v.v.
*/
class t_event_user : public t_event {
private:
t_sip_message *msg; /**< The SIP message. */
unsigned short tuid; /**< Transaction user id. */
unsigned short tid; /**< Transaction id. */
/**
* Transaction id that is the target of the CANCEL message.
* Only set if tid is a CANCEL transaction and the event
* is sent towards the user.
*/
unsigned short tid_cancel_target;
/** User profile of the user sending/receiving the SIP message. */
t_user *user_config;
public:
/** Constructor.
* @param u [in] User profile.
* @param m [in] SIP message
* @param _tuid [in] Transaction user id associated with this message.
* @param _tid [in] Transaction id of the transaction for this message.
*/
t_event_user(t_user *u, t_sip_message *m, unsigned short _tuid,
unsigned short _tid);
/** Constructor for CANCEL request towards the user.
* @param u [in] User profile.
* @param m [in] SIP message.
* @param _tuid [in] Transaction user id associated with this message.
* @param _tid [in] Transaction id of the transaction for this message.
* @param _tid_cancel_target [in] Id of the target transaction of a CANCEL request.
*/
t_event_user(t_user *u, t_sip_message *m, unsigned short _tuid,
unsigned short _tid, unsigned short _tid_cancel_target);
~t_event_user();
t_event_type get_type(void) const;
/**
* Get the SIP message.
* @return Pointer to the SIP message inside this event.
*/
t_sip_message *get_msg(void) const;
/** Get transaction user id. */
unsigned short get_tuid(void) const;
/** Get transaction id. */
unsigned short get_tid(void) const;
/** Get the CANCEL target transaction id. */
unsigned short get_tid_cancel_target(void) const;
/**
* Get the user profile.
* @return Pointer to the user profile inside the event.
*/
t_user *get_user_config(void) const;
};
/**
* Time out events.
* Expiration of a timer is signalled by a time out event.
*/
class t_event_timeout : public t_event {
private:
/**
* The epxired timer.
* @note Timer pointer will be deleted upon destruction of the object.
*/
t_timer *timer;
public:
/**
* Constructor.
* @param t [in] The expired timer.
* @note The event will keep a copy of the timer.
*/
t_event_timeout(t_timer *t);
~t_event_timeout();
t_event_type get_type(void) const;
/**
* Get the timer from the event.
* @return The timer.
*/
t_timer *get_timer(void) const;
};
/** Types of failures. */
enum t_failure {
FAIL_TIMEOUT, /**< Transaction timed out */
FAIL_TRANSPORT /**< Transport failure */
};
/**
* Failure events.
*/
class t_event_failure : public t_event {
private:
t_failure failure; /**< Type of failure. */
unsigned short tid; /**< Id of transaction that failed. */
public:
/**
* Constructor.
* @param f [in] Type of failure.
* @param _tid [in] Transaction id.
*/
t_event_failure(t_failure f, unsigned short _tid);
t_event_type get_type(void) const;
/**
* Get the type of failure.
* @return Type of failure.
*/
t_failure get_failure(void) const;
/**
* Get the transaction id.
* @return Transaction id.
*/
unsigned short get_tid(void) const;
};
/**
* Start timer event.
* A start timer event instructs the time keeper to start a timer.
*/
class t_event_start_timer : public t_event {
private:
t_timer *timer; /**< The timer to start. */
public:
/**
* Constructor.
* @param t [in] The timer to start.
*/
t_event_start_timer(t_timer *t);
t_event_type get_type(void) const;
/**
* Get the timer.
* @return Timer.
*/
t_timer *get_timer(void) const;
};
/**
* Stop timer event
* A stop timer event instructs the time keeper to stop a timer.
*/
class t_event_stop_timer : public t_event {
private:
/** Id of the timer to stop. */
unsigned short timer_id;
public:
/**
* Constructor.
* @param id [in] Id of the timer to stop.
*/
t_event_stop_timer(unsigned short id);
t_event_type get_type(void) const;
/**
* Get the timer id.
* @return Timer id.
*/
unsigned short get_timer_id(void) const;
};
/**
* Abort transaction event.
* With an abort transaction event, the requester asks the transaction
* manager to abort a pending transaction.
*/
class t_event_abort_trans : public t_event {
private:
unsigned short tid; /**< Id of the transaction to abort. */
public:
/**
* Constructor.
* @param _tid [in] Transaction id.
*/
t_event_abort_trans(unsigned short _tid);
t_event_type get_type(void) const;
/**
* Get transaction id.
* @return Transaction id.
*/
unsigned short get_tid(void) const;
};
/** STUN event types. */
enum t_stun_event_type {
TYPE_STUN_SIP, /**< Request to open a port for SIP. */
TYPE_STUN_MEDIA, /**< Request to open a port for media. */
};
/**
* STUN request event.
*/
class t_event_stun_request : public t_event {
private:
StunMessage *msg; /**< STUN request to send. */
unsigned short tuid; /**< Transaction user id. */
unsigned short tid; /**< Transaction id. */
t_stun_event_type stun_event_type; /**< Type of STUN event. */
t_user *user_config; /**< User profile associated with this request. */
public:
unsigned int dst_addr; /**< Destination address of request (host order). */
unsigned short dst_port; /**< Destination port of request (host order). */
unsigned short src_port; /**< Source port for media event type (host order). */
/** Constructor. */
t_event_stun_request(t_user *u, StunMessage *m, t_stun_event_type ev_type,
unsigned short _tuid, unsigned short _tid);
~t_event_stun_request();
t_event_type get_type(void) const;
/** Get STUN message. */
StunMessage *get_msg(void) const;
/** Get transaction user id. */
unsigned short get_tuid(void) const;
/** Get transaction id. */
unsigned short get_tid(void) const;
/** Get STUN event type. */
t_stun_event_type get_stun_event_type(void) const;
/** Get user profile. */
t_user *get_user_config(void) const;
};
/**
* STUN response event.
*/
class t_event_stun_response : public t_event {
private:
StunMessage *msg; /**< STUN request to send. */
unsigned short tuid; /**< Transaction user id. */
unsigned short tid; /**< Transaction id. */
public:
/** Constructor. */
t_event_stun_response(StunMessage *m, unsigned short _tuid,
unsigned short _tid);
~t_event_stun_response();
t_event_type get_type(void) const;
/** Get STUN message. */
StunMessage *get_msg(void) const;
/** Get transaction user id. */
unsigned short get_tuid(void) const;
/** Get transaction id. */
unsigned short get_tid(void) const;
};
/**
* NAT keep alive event.
* Request to send a NAT keep alive message.
*/
class t_event_nat_keepalive : public t_event {
public:
unsigned int dst_addr; /**< Destination address for keepalive (host order) */
unsigned short dst_port; /**< Destination port (host order) */
t_event_type get_type(void) const;
};
/**
* ICMP event.
* This event signals the reception of an ICMP error.
*/
class t_event_icmp : public t_event {
private:
t_icmp_msg icmp; /**< The received ICMP message. */
public:
/**
* Constructor.
* @param m [in] ICMP message.
*/
t_event_icmp(const t_icmp_msg &m);
t_event_type get_type(void) const;
/**
* Get the ICMP message.
* @return ICMP message.
*/
t_icmp_msg get_icmp(void) const;
};
/** User interface callback types. */
enum t_ui_event_type {
TYPE_UI_CB_DTMF_DETECTED, /**< DTMF tone detected */
TYPE_UI_CB_SEND_DTMF, /**< Sending DTMF */
TYPE_UI_CB_RECV_CODEC_CHANGED, /**< Codec changed */
TYPE_UI_CB_LINE_STATE_CHANGED, /**< Line state changed */
TYPE_UI_CB_LINE_ENCRYPTED, /**< Line is now encrypted */
TYPE_UI_CB_SHOW_ZRTP_SAS, /**< Show the ZRTP SAS */
TYPE_UI_CB_ZRTP_CONFIRM_GO_CLEAR, /**< ZRTP Confirm go-clear */
TYPE_UI_CB_QUIT /**< Quit the user interface */
};
/**
* User interface event.
* Send a user interface callback to the user interface.
* Most callbacks are called directly as a function call.
* Sometimes an asynchronous callback is needed. That's where
* this event is used for.
*/
class t_event_ui : public t_event {
private:
t_ui_event_type type; /**< User interface callback type. */
/** @name Parameters for call back functions */
//@{
int line; /**< Line number. */
t_audio_codec codec; /**< Audio codec. */
char dtmf_event; /**< DTMF event. */
bool encrypted; /**< Encryption indication. */
string cipher_mode; /**< Cipher mode (algorithm name). */
string zrtp_sas; /**< ZRTP SAS/ */
//@}
public:
/**
* Constructor.
* @param _type [in] Type of callback.
*/
t_event_ui(t_ui_event_type _type);
t_event_type get_type(void) const;
/** @name Set parameters for call back functions */
//@{
void set_line(int _line);
void set_codec(t_audio_codec _codec);
void set_dtmf_event(char _dtmf_event);
void set_encrypted(bool on);
void set_cipher_mode(const string &_cipher_mode);
void set_zrtp_sas(const string &sas);
//@}
/**
* Call the callback function.
* @param user_intf [in] The user interface that receives the callback.
*/
void exec(t_userintf *user_intf);
};
/**
* Asynchronous response event.
* A user interface can open an asynchronous message box to request
* information from the user. Via this event the user interface signals
* the response from the user.
*/
class t_event_async_response : public t_event {
public:
/** Response type */
enum t_response_type {
RESP_REFER_PERMISSION /**< Response on permission to refer question */
};
private:
t_response_type response_type; /**< Response type. */
bool bool_response; /**< Boolean response. */
public:
/**
* Constructor.
* @param type [in] The response type.
*/
t_event_async_response(t_response_type type);
t_event_type get_type(void) const;
/**
* Set the boolean response.
* @param b [in] The response.
*/
void set_bool_response(bool b);
/**
* Get response type.
* @return Response type.
*/
t_response_type get_response_type(void) const;
/**
* Get boolean response.
* @return The response.
*/
bool get_bool_response(void) const;
};
/**
* Event queue.
* An event queue is the communication pipe between multiple
* threads. Multiple threads write events into the queue and
* one thread reads the events from the queue and processes them
* Access to the queue is protected by a mutex. A semaphore is
* used to synchronize the reader with the writers of the queue.
*/
class t_event_queue {
private:
queue<t_event *> ev_queue; /**< Queue of events. */
t_mutex mutex_evq; /**< Mutex to protect access to the queue. */
t_semaphore sema_evq; /**< Semephore counting the number of events. */
/**
* Semaphore to signal an interrupt.
* Will be posted when the interrupt method is called.
*/
t_semaphore sema_caught_interrupt;
public:
/** Constructor. */
t_event_queue();
~t_event_queue();
/**
* Push an event into the queue.
* @param e [in] Event
*/
void push(t_event *e);
/** Push a quit event into the queue. */
void push_quit(void);
/**
* Create a network event and push it into the queue.
* @param m [in] SIP message.
* @param ipaddr [in] Destination address of the message (host order).
* @param port [in] Port of the message (host order).
*/
void push_network(t_sip_message *m, unsigned long ipaddr,
unsigned short port);
/**
* Create a user event and push it into the queue.
* The user event must be associated with a user profile.
* @param user_config [in] The user profile.
* @param m [in] SIP message.
* @param tuid [in] Transaction user id.
* @param tid [in] Transaction id.
*/
void push_user(t_user *user_config, t_sip_message *m, unsigned short tuid,
unsigned short tid);
/**
* Create a user event and push it into the queue.
* The user event must be unrelated to a particular user profile.
* @param m [in] SIP message.
* @param tuid [in] Transaction user id.
* @param tid [in] Transaction id.
*/
void push_user(t_sip_message *m, unsigned short tuid,
unsigned short tid);
/**
* Create a cancel event for a user.
* @param user_config [in] The user profile.
* @param m [in] SIP message.
* @param tuid [in] Transaction user id.
* @param tid [in] Transaction id.
*/
void push_user_cancel(t_user *user_config, t_sip_message *m, unsigned short tuid,
unsigned short tid, unsigned short target_tid);
/**
* Create a cancel event for a user.
* @param m [in] SIP message.
* @param tuid [in] Transaction user id.
* @param tid [in] Transaction id.
*/
void push_user_cancel(t_sip_message *m, unsigned short tuid,
unsigned short tid, unsigned short target_tid);
/**
* Create a timeout event and push it into the queue.
* @param t [in] The timer that expired.
*/
void push_timeout(t_timer *t);
/**
* Create failure event and push it into the queue.
* @param f [in] Type of failure.
* @param tid [in] Transaction id of failed transaction.
*/
void push_failure(t_failure f, unsigned short tid);
/**
* Create a start timer event.
* @param t [in] Timer to start.
*/
void push_start_timer(t_timer *t);
/**
* Create a stop timer event.
* @param timer_id [in] Timer id of timer to stop.
*/
void push_stop_timer(unsigned short timer_id);
/**
* Create an abort transaction event.
* @param tid [in] Transaction id of transaction to abort.
*/
void push_abort_trans(unsigned short tid);
/**
* Create a STUN request event.
* @param user_config [in] The user profile associated with the request.
* @param m [in] STUN request.
* @param ev_type [in] Type of STUN event.
* @param tuid [in] Transaction user id.
* @param tid [in] Transaction id.
* @param ipaddr [in] Destination address (host order)
* @param port [in] Destination port (host order)
* @param src_port [in] Source port of media. This must only be passed for
* a media STUN event.
*/
void push_stun_request(t_user *user_config, StunMessage *m, t_stun_event_type ev_type,
unsigned short tuid, unsigned short tid,
unsigned long ipaddr, unsigned short port, unsigned short src_port = 0);
/**
* Create a STUN response event.
* @param m [in] STUN response.
* @param tuid [in] Transaction user id.
* @param tid [in] Transaction id.
*/
void push_stun_response(StunMessage *m,
unsigned short tuid, unsigned short tid);
/**
* Create a NAT keepalive event.
* @param ipaddr [in] Destination address (host order)
* @param port [in] Destination port (host order)
*/
void push_nat_keepalive(unsigned long ipaddr, unsigned short port);
/**
* Create ICMP event.
* @param m [in] ICMP message.
*/
void push_icmp(const t_icmp_msg &m);
/**
* Create a REFER pemission response event.
* @param permission [in] Permission allowed?.
*/
void push_refer_permission_response(bool permission);
/**
* Pop an event from the queue.
* If the queue is empty then the thread will be blocked until an
* event arrives.
* @return The popped event.
*/
t_event *pop(void);
/**
* Pop an event from the queue.
* Same method as above, but this one can be interrupted by
* calling the method interrupt.
* @param interrupted [out] When the pop operation is interrupted this
* parameter is set to true. Otherwise it is false.
* @return NULL, when interrupted.
* @return The popped event, otherwise.
*/
t_event *pop(bool &interrupted);
/**
* Send an interrupt.
* This will cause the interruptable pop to return.
* A non-interruptable pop will ignore the interrupt.
* If pop is currently not suspending the thread execution then the
* next call to pop will catch the interrupt.
*/
void interrupt(void);
};
#endif
syntax highlighted by Code2HTML, v. 0.9.1