summaryrefslogtreecommitdiffstats
path: root/src/dialog.h
diff options
context:
space:
mode:
authorMichal Kubecek <mkubecek@suse.cz>2015-04-13 09:21:39 +0200
committerMichal Kubecek <mkubecek@suse.cz>2015-04-13 09:21:39 +0200
commite2bc6f4153813cc570ae814c8ddb74628009b488 (patch)
treea40b171be1d859c2232ccc94f758010f9ae54d3c /src/dialog.h
downloadtwinkle-e2bc6f4153813cc570ae814c8ddb74628009b488.tar
twinkle-e2bc6f4153813cc570ae814c8ddb74628009b488.tar.gz
twinkle-e2bc6f4153813cc570ae814c8ddb74628009b488.tar.lz
twinkle-e2bc6f4153813cc570ae814c8ddb74628009b488.tar.xz
twinkle-e2bc6f4153813cc570ae814c8ddb74628009b488.zip
initial checkin
Check in contents of upstream 1.4.2 tarball, exclude generated files.
Diffstat (limited to 'src/dialog.h')
-rw-r--r--src/dialog.h845
1 files changed, 845 insertions, 0 deletions
diff --git a/src/dialog.h b/src/dialog.h
new file mode 100644
index 0000000..7466d22
--- /dev/null
+++ b/src/dialog.h
@@ -0,0 +1,845 @@
+/*
+ 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
+*/
+
+/**
+ * @file
+ * SIP dialog established by an INVITE transaction.
+ */
+
+#ifndef _DIALOG_H
+#define _DIALOG_H
+
+#include <string>
+#include <list>
+#include <set>
+#include <queue>
+#include "abstract_dialog.h"
+#include "client_request.h"
+#include "phone.h"
+#include "transaction_layer.h"
+#include "protocol.h"
+#include "redirect.h"
+#include "session.h"
+#include "user.h"
+#include "sockets/url.h"
+#include "threads/mutex.h"
+#include "parser/request.h"
+#include "sdp/sdp.h"
+#include "stun/stun.h"
+
+using namespace std;
+
+// Forward declarations
+class t_phone;
+class t_line;
+class t_session;
+class t_sub_refer;
+
+/** Dialog state */
+enum t_dialog_state {
+ DS_NULL, /**< Initial state */
+
+ // UAC states
+ DS_W4INVITE_RESP, /**< INVITE sent, waiting for response */
+ DS_W4INVITE_RESP2, /**< Provisional response received */
+ DS_EARLY, /**< Provisional response with to-tag received */
+ DS_W4BYE_RESP, /**< BYE sent, waiting for response */
+
+ // UAS states
+ DS_W4ACK, /**< Waiting for ACK on 2XX INVITE */
+ DS_W4ANSWER, /**< INVITE received, waiting for user to answer */
+
+ // UAS and UAC states
+ DS_CONFIRMED, /**< Success received/sent */
+ DS_W4ACK_RE_INVITE, /**< Waiting for ACK on re-INVITE */
+ DS_W4RE_INVITE_RESP, /**< re-INVITE sent, waiting for response */
+ DS_W4RE_INVITE_RESP2, /**< re-INVITE sent, provisional response recvd */
+ DS_TERMINATED, /**< Dialog terminated */
+
+ // Subscription states
+ DS_CONFIRMED_SUB, /**< Confirmed refer-subscription dialog */
+};
+
+/** Purpose for sending a re-INVITE request */
+enum t_reinvite_purpose {
+ REINVITE_HOLD, /**< Re-invite for call hold */
+ REINVITE_RETRIEVE, /**< Re-invite for call retrieve */
+};
+
+/**
+ * SIP dialog established by an INVITE transaction.
+ *
+ * Dialog state diagrams:
+ * @dot
+ * digraph call {
+ * label="Call setup and tear down state transitions"
+ * node [shape=ellipse, fontname=Helvetica, fontsize=10, style=filled, fillcolor=yellow];
+ * edge [fontname=Helvetica, fontsize=9];
+ *
+ * null [label="DS_NULL" URL="\ref DS_NULL"];
+ * w4invite_resp [label="DS_W4INVITE_RESP" URL="\ref DS_W4INVITE_RESP"]
+ * w4invite_resp2 [label="DS_W4INVITE_RESP2" URL="\ref DS_W4INVITE_RESP2"]
+ * early [label="DS_EARLY" URL="\ref DS_EARLY"]
+ * w4bye_resp [label="DS_W4BYE_RESP" URL="\ref DS_W4BYE_RESP"]
+ * w4ack [label="DS_W4ACK" URL="\ref DS_W4ACK"]
+ * w4answer [label="DS_W4ANSWER" URL="\ref DS_W4ANSWER"]
+ * confirmed [label="DS_CONFIRMED" URL="\ref DS_CONFIRMED"]
+ * terminated [label="DS_TERMINATED" URL="\ref DS_TERMINATED"]
+ *
+ * null -> w4invite_resp [label="send INVITE"]
+ * null -> w4answer [label="receive INVITE"]
+ * null -> terminated [label="receive INVITE\nSTUN media\nbind fails"]
+ * null -> terminated [label="receive INVITE\nunsupported\nmedia or body"]
+ * w4invite_resp -> w4invite_resp2 [label="receive 1XX without to-tag"]
+ * w4invite_resp -> early [label="receive 1XX with to-tag"]
+ * w4invite_resp -> confirmed [label="receive 2XX"]
+ * w4invite_resp -> terminated [label="receive failure\nresponse"]
+ * w4invite_resp2 -> confirmed [label="receive 2XX"]
+ * w4invite_resp2 -> early [label="receive 1XX with to-tag"]
+ * w4invite_resp2 -> terminated [label="receive failure\nresponse"]
+ * early -> confirmed [label="receive 2XX"]
+ * early -> terminated [label="receive failure\nresponse"]
+ * w4answer -> w4ack [label="user answered, send 2XX"]
+ * w4answer -> terminated [label="user rejected\nsend 4XX/6XX"]
+ * w4answer -> terminated [label="receive CANCEL/BYE\nsend 487"]
+ * w4ack -> confirmed [label="receive ACK"]
+ * confirmed -> w4bye_resp [label="send BYE"]
+ * confirmed -> terminated [label="receive BYE"]
+ * w4bye_resp -> terminated [label="receive BYE response"]
+ * }
+ * @enddot
+ *
+ * @dot
+ * digraph reinvite {
+ * label="re-INVITE state transitions"
+ * node [shape=ellipse, fontname=Helvetica, fontsize=10, style=filled, fillcolor=yellow];
+ * edge [fontname=Helvetica, fontsize=9];
+ *
+ * confirmed [label="DS_CONFIRMED" URL="\ref DS_CONFIRMED"]
+ * w4ack_re_invite [label="DS_W4ACK_RE_INVITE" URL="\ref DS_W4ACK_RE_INVITE"]
+ * w4re_invite_resp [label="DS_W4RE_INVITE_RESP" URL="\ref DS_W4RE_INVITE_RESP"]
+ * w4re_invite_resp2 [label="DS_W4RE_INVITE_RESP2" URL="\ref DS_W4RE_INVITE_RESP2"]
+ * terminated [label="DS_TERMINATED" URL="\ref DS_TERMINATED"]
+ *
+ * confirmed -> w4ack_re_invite [label="receive re-INVITE, send 2XX"]
+ * confirmed -> terminated [label="receive re-INVITE\nSTUN fails"]
+ * confirmed -> confirmed [label="receive re-INVITE, send failure response"]
+ * confirmed -> w4re_invite_resp [label="send re-INVITE"]
+ * w4ack_re_invite -> confirmed [label="reveive ACK"]
+ * w4re_invite_resp -> w4re_invite_resp2 [label="receive 1XX"]
+ * w4re_invite_resp -> confirmed [label="receive final response"]
+ * w4re_invite_resp2 -> confirmed [label="receive final response"]
+ * w4re_invite_resp -> terminated [label="receive BYE"]
+ * w4re_invite_resp2 -> terminated [label="receive BYE"]
+ * }
+ * @enddot
+ *
+ * @dot
+ * digraph refer {
+ * label="State transitions when REFER subscription is active"
+ * node [shape=ellipse, fontname=Helvetica, fontsize=10, style=filled, fillcolor=yellow];
+ * edge [fontname=Helvetica, fontsize=9];
+ *
+ * confirmed [label="DS_CONFIRMED" URL="\ref DS_CONFIRMED"]
+ * w4bye_resp [label="DS_W4BYE_RESP" URL="\ref DS_W4BYE_RESP"]
+ * w4re_invite_resp [label="DS_W4RE_INVITE_RESP" URL="\ref DS_W4RE_INVITE_RESP"]
+ * w4re_invite_resp2 [label="DS_W4RE_INVITE_RESP2" URL="\ref DS_W4RE_INVITE_RESP2"]
+ * terminated [label="DS_TERMINATED" URL="\ref DS_TERMINATED"]
+ * confirmed_sub [label="DS_CONFIRMED_SUB" URL="DS_CONFIRMED_SUB"]
+ *
+ * confirmed -> confirmed_sub [label="receive BYE"]
+ * w4re_invite_resp -> confirmed_sub [label="receive BYE"]
+ * w4re_invite_resp2 -> confirmed_sub [label="receive BYE"]
+ * w4bye_resp -> confirmed_sub [label="receive BYE response"]
+ * confirmed_sub -> terminated [label="terminate subscription"]
+ * }
+ * @enddot
+ *
+ * @dot
+ * digraph timeout {
+ * label="State transitions due to timeouts"
+ * node [shape=ellipse, fontname=Helvetica, fontsize=10, style=filled, fillcolor=yellow];
+ * edge [fontname=Helvetica, fontsize=9];
+ *
+ * w4answer [label="DS_W4ANSWER" URL="\ref DS_W4ANSWER"]
+ * w4ack [label="DS_W4ACK" URL="\ref DS_W4ACK"]
+ * confirmed [label="DS_CONFIRMED" URL="\ref DS_CONFIRMED"]
+ * terminated [label="DS_TERMINATED" URL="\ref DS_TERMINATED"]
+ * confirmed_sub [label="DS_CONFIRMED_SUB" URL="DS_CONFIRMED_SUB"]
+ *
+ * w4answer -> w4answer [label="LTMR_100REL_TIMEOUT\nretransmit 1XX" URL="LTMR_100REL_TIMEOUT"]
+ * w4answer -> terminated [label="LTMR_100REL_GUARD\nsend 500" URL="LTMR_100REL_GUARD"]
+ * w4ack -> w4ack [label="LTMR_ACK_TIMEOUT\nretransmit 2XX" URL="LTMR_ACK_TIMEOUT"]
+ * w4ack -> confirmed [label="LTMR_ACK_GUARD\ntear down call" URL="LTMR_ACK_GUARD"]
+ * confirmed_sub -> terminated [label="REFER subscription\ntimeout"]
+ * }
+ * @enddot
+ */
+class t_dialog : public t_abstract_dialog {
+ friend class t_phone;
+
+protected:
+ t_line *line; /**< Phone line owning this dialog. */
+ t_dialog_state state; /**< Dialog state. */
+
+ /** Session established by this dialog. */
+ t_session *session;
+
+ /**
+ * New session being established during re-invite.
+ * When the re-INVITE transaction finishes successfully, then
+ * this session information will override the general session.
+ */
+ t_session *session_re_invite;
+
+ /** The purpose of an outgoing re-INVITE request */
+ t_reinvite_purpose reinvite_purpose;
+
+ /** Indicates if the last call hold action failed. */
+ bool hold_failed;
+
+ t_client_request *req_out; /**< Pending outgoing non-INVITE request */
+ t_client_request *req_out_invite; /**< Pending outgoing INVITE */
+ t_client_request *req_in_invite; /**< Pending incoming INVITE */
+ t_client_request *req_cancel; /**< Pending outgoing CANCEL */
+ t_client_request *req_refer; /**< Pending outgoing REFER */
+ t_client_request *req_info; /**< Pending outgoing INFO */
+
+ /**
+ * Last outgoing PRACK. While a PRACK is still pending a new 1xx
+ * response might come in. A PRACK will be sent for this 1xx without
+ * waiting for the response for the previous PRACK.
+ */
+ t_client_request *req_prack;
+
+ /** Pending STUN request */
+ t_client_request *req_stun;
+
+ /**
+ * Incoming request queue. A request may come in when it cannot be
+ * served yet. Such a request is stored in the queue to be served
+ * later.
+ */
+ list<t_client_request *> inc_req_queue;
+
+ /** Indication if request must be cancelled */
+ bool request_cancelled;
+
+ /**
+ * Indication that the dialog must be terminated after a 2XX
+ * on an INVITE is received (e.g. when 2XX glares with CANCEL).
+ */
+ bool end_after_2xx_invite;
+
+ /** Indication that the dialog must be terminated after ACK. */
+ bool end_after_ack;
+
+ /**
+ * Indication that the user wants to answer the call.
+ * Sending the answer must be delayed as we are still waiting for
+ * a PRACK to acknowledge a 1xx containing SDP from the
+ * far end (RFC 3262 3).
+ */
+ bool answer_after_prack;
+
+ /** Indication if 180 ringing has already been received */
+ bool ringing_received;
+
+ /** Cached success response to INVITE needed for retransmission */
+ t_response *resp_invite;
+
+ /**
+ * Cached provisional response to INVITE needed for retransmission
+ * when provisional responses are sent reliable (100rel)
+ */
+ t_response *resp_1xx_invite;
+
+ /** Cached ack needed for retransmission */
+ t_request *ack;
+
+ /** Subscription created by REFER (RFC 3515) */
+ t_sub_refer *sub_refer;
+
+ /** Queue of DTMF digits to be sent via INFO requests */
+ queue<char> dtmf_queue;
+
+ /** @name Process incoming responses */
+ //@{
+ /**
+ * Process an incoming response in the @ref DS_W4INVITE_RESP state.
+ * @param r The response
+ * @param tuid Transaction user id
+ * @param tid Transaction id
+ */
+ void state_w4invite_resp(t_response *r, t_tuid tuid, t_tid tid);
+
+ /**
+ * Process an incoming response in the @ref DS_EARLY state.
+ * @param r The response
+ * @param tuid Transaction user id
+ * @param tid Transaction id
+ */
+ void state_early(t_response *r, t_tuid tuid, t_tid tid);
+
+ /**
+ * Process an incoming response in the @ref DS_W4BYE_RESP state.
+ * @param r The response
+ * @param tuid Transaction user id
+ * @param tid Transaction id
+ */
+ void state_w4bye_resp(t_response *r, t_tuid tuid, t_tid tid);
+
+ /**
+ * Process an incoming response in the @ref DS_CONFIRMED state.
+ * @param r The response
+ * @param tuid Transaction user id
+ * @param tid Transaction id
+ */
+ void state_confirmed_resp(t_response *r, t_tuid tuid, t_tid tid);
+
+ /**
+ * Process an incoming response in the @ref DS_W4RE_INVITE_RESP state.
+ * @param r The response
+ * @param tuid Transaction user id
+ * @param tid Transaction id
+ */
+ void state_w4re_invite_resp(t_response *r, t_tuid tuid, t_tid tid);
+ //@}
+
+ /** @name Process incoming requests */
+ //@{
+ /**
+ * Process an incoming request in the @ref DS_NULL state.
+ * @param r The request
+ * @param tuid Transaction user id
+ * @param tid Transaction id
+ */
+ void state_null(t_request *r, t_tuid tuid, t_tid tid);
+
+ /**
+ * Process an incoming request in the @ref DS_W4ANSWER state.
+ * @param r The request
+ * @param tuid Transaction user id
+ * @param tid Transaction id
+ */
+ void state_w4answer(t_request *r, t_tuid tuid, t_tid tid);
+
+ /**
+ * Process an incoming request in the @ref DS_W4ACK state.
+ * @param r The request
+ * @param tuid Transaction user id
+ * @param tid Transaction id
+ */
+ void state_w4ack(t_request *r, t_tuid tuid, t_tid tid);
+
+ /**
+ * Process an incoming request in the @ref DS_W4ACK_RE_INVITE state.
+ * @param r The request
+ * @param tuid Transaction user id
+ * @param tid Transaction id
+ */
+ void state_w4ack_re_invite(t_request *r, t_tuid tuid, t_tid tid);
+
+ /**
+ * Process an incoming request in the @ref DS_W4RE_INVITE_RESP state.
+ * @param r The request
+ * @param tuid Transaction user id
+ * @param tid Transaction id
+ */
+ void state_w4re_invite_resp(t_request *r, t_tuid tuid, t_tid tid);
+
+ /**
+ * Process an incoming request in the @ref DS_W4BYE_RESP state.
+ * @param r The request
+ * @param tuid Transaction user id
+ * @param tid Transaction id
+ */
+ void state_w4bye_resp(t_request *r, t_tuid tuid, t_tid tid);
+
+ /**
+ * Process an incoming request in the @ref DS_CONFIRMED state.
+ * @param r The request
+ * @param tuid Transaction user id
+ * @param tid Transaction id
+ */
+ void state_confirmed(t_request *r, t_tuid tuid, t_tid tid);
+
+ /**
+ * Process an incoming request in the @ref DS_CONFIRMED_SUB state.
+ * @param r The request
+ * @param tuid Transaction user id
+ * @param tid Transaction id
+ */
+ void state_confirmed_sub(t_request *r, t_tuid tuid, t_tid tid);
+ //@}
+
+ /** @name Process requests in the confirmed state */
+ //@{
+ /** Proces incoming re-INVITE. */
+ void process_re_invite(t_request *r, t_tuid tuid, t_tid tid);
+
+ /** Proces incoming REFER. */
+ void process_refer(t_request *r, t_tuid tuid, t_tid tid);
+
+ /** Process incoming SUBSCRIBE (refer subscription). */
+ void process_subscribe(t_request *r, t_tuid tuid, t_tid tid);
+
+ /** Process incoming NOTIFY (refer subscription). */
+ void process_notify(t_request *r, t_tuid tuid, t_tid tid);
+
+ /** Process incoming INFO. */
+ void process_info(t_request *r, t_tuid tuid, t_tid tid);
+
+ /** Process incoming MESSAGE. */
+ void process_message(t_request *r, t_tuid tuid, t_tid tid);
+ //@}
+
+ /** @name Process timeouts */
+ //@{
+ /**
+ * Process timeout in @ref DS_W4INVITE_RESP state.
+ * @param timer The expired timer.
+ */
+ void state_w4invite_resp(t_line_timer timer);
+
+ /**
+ * Process timeout in @ref DS_EARLY state.
+ * @param timer The expired timer.
+ */
+ void state_early(t_line_timer timer);
+
+ /**
+ * Process timeout in @ref DS_W4ACK state.
+ * @param timer The expired timer.
+ */
+ void state_w4ack(t_line_timer timer);
+
+ /**
+ * Process timeout in @ref DS_W4ACK_RE_INVITE state.
+ * @param timer The expired timer.
+ */
+ void state_w4ack_re_invite(t_line_timer timer);
+
+ /**
+ * Process timeout in @ref DS_W4RE_INVITE_RESP state.
+ * @param timer The expired timer.
+ */
+ void state_w4re_invite_resp(t_line_timer timer);
+
+ /**
+ * Process timeout in @ref DS_W4ANSWER state.
+ * @param timer The expired timer.
+ */
+ void state_w4answer(t_line_timer timer);
+
+ /**
+ * Process timeout in @ref DS_CONFIRMED state.
+ * @param timer The expired timer.
+ */
+ void state_confirmed(t_line_timer timer);
+ //@}
+
+ /** Make the re-INVITE session the current session. */
+ void activate_new_session(void);
+
+ /**
+ * Process SDP answer in 1xx and 2xx responses if present.
+ * Apply ringing tone for a 180 response.
+ * Determine if call should be canceled due to unsupported
+ * or missing SDP.
+ * @param r The 1XX/2XX response.
+ */
+ void process_1xx_2xx_invite_resp(t_response *r);
+
+ /**
+ * Acknowledge a reveived 2xx response on an INVITE.
+ * @param r The 2XX response.
+ */
+ void ack_2xx_invite(t_response *r);
+
+ /**
+ * Send PRACK if the response requires it.
+ * @param r The response.
+ */
+ void send_prack_if_required(t_response *r);
+
+ /**
+ * Determine if a reliable provisional repsonse must be discarded.
+ * A provisional response must be discarded because it is a retransmission
+ * or received out of order.
+ * Initializes the remote response nr if the response is the
+ * first response.
+ * @param r The provisional response.
+ * @return true, discard response.
+ * @return false, otherwise
+ */
+ bool must_discard_100rel(t_response *r);
+
+ /**
+ * Respond to an incoming PRACK.
+ * @param r The incoming PRACK.
+ * @param tuid Transaction user id
+ * @param tid Transaction id
+ * @return true, if a success response was given.
+ * @return false if an error response was given.
+ */
+ bool respond_prack(t_request *r, t_tuid tuid, t_tid tid);
+
+ virtual void send_request(t_request *r, t_tuid tuid);
+public:
+ /** @name Timer durations and timer id's */
+ //@{
+ unsigned long dur_ack_timeout; /**< @ref LTMR_ACK_TIMEOUT duration (ms) */
+ t_object_id id_ack_timeout; /**< @ref LTMR_ACK_TIMEOUT timer id */
+ t_object_id id_ack_guard; /**< @ref LTMR_ACK_GUARD timer id */
+ t_object_id id_re_invite_guard; /**< @ref LTMR_RE_INVITE_GUARD timer id */
+ t_object_id id_glare_retry; /**< @ref LTMR_GLARE_RETRY timer id */
+ t_object_id id_cancel_guard; /**< @ref LTMR_CANCEL_GUARD timer id */
+ //@}
+
+ /** @name RFC 3262 100rel timers */
+ //@{
+ unsigned long dur_100rel_timeout; /**< @ref LTMR_100REL_TIMEOUT duration (ms) */
+ t_object_id id_100rel_timeout; /**< @ref LTMR_100REL_TIMEOUT timer id */
+ t_object_id id_100rel_guard; /**< @ref LTMR_100REL_GUARD timer id */
+ //@}
+
+ /** Indicates if last incoming REFER was accepted. */
+ bool refer_accepted;
+
+ /** Indicates if the call transfer triggered by the last outgoing REFER succeeded. */
+ bool refer_succeeded;
+
+ /** Indicates if the last outgoing REFER request failed. */
+ bool out_refer_req_failed;
+
+ /**
+ * Indicates if this dialog is setup because the user told to do
+ * so by a REFER.
+ */
+ bool is_referred_call;
+
+ /** State of an outgoing REFER. */
+ t_refer_state refer_state;
+
+ /**
+ * Constructor.
+ * @param _line The line owning this dialog.
+ */
+ t_dialog(t_line *_line);
+
+ /** Destructor. */
+ virtual ~t_dialog();
+
+ virtual t_request *create_request(t_method m);
+
+ virtual t_dialog *copy(void);
+
+ /**
+ * Send INIVTE request.
+ * @param to_uri The URI to be used a request-URI and To header URI
+ * @param to_display Display name for To header.
+ * @param subject If not empty, this string will go into the Subject header.
+ * @param hdr_referred_by The Reffered-By header to be put in the INVITE.
+ * @param hdr_replaces The Replaces header to be put in the INVITE.
+ * @param hdr_require Required extensions to be put in the Require header.
+ * @param hdr_request_disposition Request-Disposition header to be put in the INVITE.
+ * @param anonymous Inidicates if the INVITE should be sent anonymous.
+ *
+ * @pre Dialog is in @ref DS_NULL state.
+ */
+ void send_invite(const t_url &to_uri, const string &to_display,
+ const string &subject, const t_hdr_referred_by &hdr_referred_by,
+ const t_hdr_replaces &hdr_replaces,
+ const t_hdr_require &hdr_require,
+ const t_hdr_request_disposition &hdr_request_disposition,
+ bool anonymous);
+
+ /**
+ * Resend the INVITE with an authorization header containing credentials
+ * for the challenge in the response.
+ * @param resp, the response on the INVITE.
+ * @return true, if resending succeeded.
+ * @return false, if credentials could not be determined.
+ *
+ * @pre The response must be a 401 or 407.
+ */
+ bool resend_invite_auth(t_response *resp);
+
+ /**
+ * Resend the INVITE because the far-end did not support all required
+ * extensions. Extensions that could not be supported will not be
+ * required this time.
+ * @param resp The response in the INVITE.
+ * @return true, if resending succeeded.
+ * @return false, if far-end did not indicate which extensions are
+ * unsupported. Or if a required extension could not be disabled.
+ *
+ * @pre The response must be a 420.
+ */
+ bool resend_invite_unsupported(t_response *resp);
+
+ /**
+ * Redirect INVITE to the next destination.
+ * @param resp The response on the INVITE.
+ * @return true, if INIVTE was redirected succesfully.
+ * @return false, if there is no next destination.
+ *
+ * @pre The response must be a 3XX.
+ */
+ bool redirect_invite(t_response *resp);
+
+ /**
+ * Failover INVITE to the next destination from DNS lookup.
+ * @return true, if INIVTE was succesfully sent.
+ * @return false, if there is no next destination.
+ */
+ bool failover_invite(void);
+
+ /** Send BYE request. */
+ void send_bye(void);
+
+ /** Send OPTIONS request. */
+ void send_options(void);
+
+ /**
+ * Send CANCEL request.
+ * If an early dialog exists, then the CANCEL can be sent
+ * right away as a response has been received for the INVITE.
+ * Otherwise, the CANCEL will be sent as soon as an early dialog
+ * is created.
+ * @param early_dialog_exists Indicates if an early dialog exists.
+ */
+ void send_cancel(bool early_dialog_exists);
+
+ /**
+ * Indicate that the dialog must be ended if a 2XX is received
+ * on an INVITE.
+ * @param on Set/clear indication.
+ */
+ void set_end_after_2xx_invite(bool on);
+
+ /**
+ * Send re-INVITE.
+ * @pre session_re_invite attribute contains the session
+ * information for the re-INVITE.
+ */
+ void send_re_invite(void);
+
+ virtual bool resend_request_auth(t_response *resp);
+
+ virtual bool redirect_request(t_response *resp);
+
+ virtual bool failover_request(t_response *resp);
+
+ /**
+ * Hold call.
+ * If rtp_only is false, then a re-INVITE will be sent.
+ * @param rtponly Indicates if only the RTP streams should be stopped and
+ * the soundcard freed without any SIP signaling.
+ */
+ void hold(bool rtponly = false);
+
+ /** Retrieve call (send re-INVITE if needed). */
+ void retrieve(void);
+
+ /** Kill all RTP stream associated with this dialog. */
+ void kill_rtp(void);
+
+ /**
+ * Refer a call (send REFER).
+ * @param uri URI of the refer target.
+ * @param display Display name of the refer target.
+ */
+ void send_refer(const t_url &uri, const string &display);
+
+ /**
+ * Send DTMF digit.
+ * @param digit The digit.
+ * @param inband Indicates if digit must be sent inband.
+ * @param info Indicates if digit must be sent in a SIP INFO.
+ *
+ * @pre Either inband or info or none of the indicators is true.
+ * @post If none of the indicators is true, then RFC 2833 is used.
+ */
+ void send_dtmf(char digit, bool inband, bool info);
+
+ /**
+ * Create a binding for the media port via STUN.
+ * @return true, if binding is created.
+ * @return false, if binding cannot be created.
+ */
+ bool stun_bind_media(void);
+
+ /** @name Handle received events */
+ //@{
+ void recvd_response(t_response *r, t_tuid tuid, t_tid tid);
+
+ void recvd_request(t_request *r, t_tuid tuid, t_tid tid);
+
+ /**
+ * Handle incoming CANCEL request.
+ * @param r The CANCEL request.
+ * @param cancel_tid Transaction id of the CANCEL transaction.
+ * @param target_tid Transaction id of the transaction to be cancellerd.
+ */
+ void recvd_cancel(t_request *r, t_tid cancel_tid, t_tid target_tid);
+
+ /**
+ * Handle incoming STUN response.
+ * @param r The STUN response.
+ * @param tuid Transaction user id
+ * @param tid Transaction id
+ */
+ void recvd_stun_resp(StunMessage *r, t_tuid tuid, t_tid tid);
+
+ /**
+ * Handle the response from the user on the question for refer
+ * permission. This response is received on the dialog that received
+ * the REFER before.
+ * @param permission Permission response from the user.
+ * @param r The REFER request that was received.
+ */
+ void recvd_refer_permission(bool permission, t_request *r);
+ //@}
+
+ /** Answer a call (send 200 OK). */
+ void answer(void);
+
+ /**
+ * Reject a call.
+ * @param code The response code to reject the call with.
+ * @param reason A specific reason may be given to the error code. If no
+ * reason is specified the default reason is used.
+ *
+ * @pre code >= 400
+ */
+ void reject(int code, string reason = "");
+
+ /**
+ * Redirect a call.
+ * @param code The response code to redirect the call with.
+ * @param A specific reason may be give to the error code. If no
+ * reason is specified the default reason is used.
+ * @param destinations The list of redirect destinations in order of
+ * preference.
+ *
+ * @pre code is 3XX.
+ */
+ void redirect(const list<t_display_url> &destinations, int code, string reason = "");
+
+ virtual bool match_response(t_response *r, t_tuid tuid);
+
+ /**
+ * Match STUN response with dialog.
+ * @param r STUN response.
+ * @param tuid Transaction user id
+ * @return true, if response matches.
+ * @return false, otherwise.
+ */
+ bool match_response(StunMessage *r, t_tuid tuid);
+
+ /**
+ * Match CANCEL request with dialog.
+ * @param r CANCEL request.
+ * @param target_tid Transaction id of transaction to be cancelled.
+ * @return true, if request matches.
+ * @return false, otherwise.
+ */
+ bool match_cancel(t_request *r, t_tid target_tid);
+
+ /**
+ * Check if an incoming INVITE is a retransmission.
+ * @param r The INVITE request.
+ * @return true, if INVITE is a retransmission.
+ * @return false, otherwise.
+ */
+ bool is_invite_retrans(t_request *r);
+
+ /** Process a retransmission of an incoming INVITE. */
+ void process_invite_retrans(void);
+
+ /**
+ * Get the state of the dialog.
+ * @return The dialog state.
+ */
+ t_dialog_state get_state(void) const;
+
+ /**
+ * Process dialog timer timeout.
+ * @param timer The timer that expired.
+ */
+ void timeout(t_line_timer timer);
+
+ /**
+ * Process subcribe timer timeout (REFER subscription).
+ * @param timer The timer that expired.
+ * @param event_type Event type of the subscription.
+ * @param event_id Event id of the subscription.
+ */
+ void timeout_sub(t_subscribe_timer timer, const string &event_type,
+ const string &event_id);
+
+ /**
+ * Get the phone that belongs to this dialog.
+ * @return The phone object.
+ */
+ t_phone *get_phone(void) const;
+
+ /**
+ * Get the line that belongs to this dialog.
+ * @return The line object.
+ */
+ t_line *get_line(void) const;
+
+ /**
+ * Get the session belonging to this dialog.
+ * @return The session belonging to this dialog.
+ * @return NULL if there is no session.
+ */
+ t_session * get_session(void) const;
+
+ /**
+ * Get the audio session belonging to this dialog.
+ * @return The audio session belonging to this dialog.
+ * @return NULL if there is no audio session.
+ */
+ t_audio_session *get_audio_session(void) const;
+
+ /**
+ * Check if the dialog has an acitve session.
+ * @return true, if the dialog has an active session.
+ * @return false, otherwise.
+ */
+ bool has_active_session(void) const;
+
+ /**
+ * Notify the dialog of the progress of a reference.
+ * @param r The response sent by the refer target.
+ */
+ void notify_refer_progress(t_response *r);
+
+ /**
+ * Check if a dialog will be released.
+ * @return true, if the dialog will be released.
+ * @return false, otherwise.
+ */
+ bool will_release(void) const;
+};
+
+#endif