blob: 6293b0f4945ae28a4afec6568e7a7b3f64fe9475 [file] [log] [blame]
Alexandre Lision8af73cb2013-12-10 14:11:20 -05001/* $Id: sip_replaces.h 3553 2011-05-05 06:14:19Z nanang $ */
Tristan Matthews0a329cc2013-07-17 13:20:14 -04002/*
3 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20#ifndef __PJSIP_REPLACES_H__
21#define __PJSIP_REPLACES_H__
22
23
24/**
25 * @file sip_replaces.h
26 * @brief SIP Replaces support (RFC 3891 - SIP "Replaces" Header)
27 */
28#include <pjsip/sip_msg.h>
29
30/**
31 * @defgroup PJSIP_REPLACES SIP Replaces support (RFC 3891 - "Replaces" Header)
32 * @ingroup PJSIP_HIGH_UA
33 * @brief SIP Replaces support (RFC 3891 - "Replaces" Header)
34 * @{
35 *
36 * This module implements support for Replaces header in PJSIP. The Replaces
37 * specification is written in RFC 3891 - The Session Initiation Protocol (SIP)
38 * "Replaces" Header, and can be used to enable a variety of features,
39 * for example: "Attended Transfer" and "Call Pickup".
40 *
41 *
42 *
43 * \section PJSIP_REPLACES_USING_SEC Using PJSIP Replaces Support
44 *
45 * \subsection PJSIP_REPLACES_INIT_SUBSEC Initialization
46 *
47 * Application needs to call #pjsip_replaces_init_module() during application
48 * initialization stage to register "replaces" support in PJSIP.
49 *
50 *
51 *
52 * \subsection PJSIP_REPLACES_UAC_SUBSEC UAC Behavior: Sending a Replaces Header
53 *
54 * A User Agent that wishes to replace a single existing early or
55 * confirmed dialog with a new dialog of its own, MAY send the target
56 * User Agent an INVITE request containing a Replaces header field. The
57 * User Agent Client (UAC) places the Call-ID, to-tag, and from-tag
58 * information for the target dialog in a single Replaces header field
59 * and sends the new INVITE to the target.
60 *
61 * To initiate outgoing INVITE request with Replaces header, application
62 * would create the INVITE request with #pjsip_inv_invite(), then adds
63 * #pjsip_replaces_hdr instance into the request, filling up the Call-ID,
64 * To-tag, and From-tag properties of the header with the identification
65 * of the dialog to be replaced. Application may also optionally
66 * set the \a early_only property of the header to indicate that it only
67 * wants to replace early dialog.
68 *
69 * Note that when the outgoing INVITE request (with Replaces) is initiated
70 * from an incoming REFER request (as in Attended Call Transfer case),
71 * this process should be done rather more automatically by PJSIP. Upon
72 * receiving incoming incoming REFER request, normally these processes
73 * will be performed:
74 * - Application finds \a Refer-To header,
75 * - Application creates outgoing dialog/invite session, specifying
76 * the URI in the \a Refer-To header as the initial remote target,
77 * - The URI in the \a Refer-To header may contain header parameters such
78 * as \a Replaces and \a Require headers.
79 * - The dialog keeps the header fields in the header parameters
80 * of the URI, and the invite session would add these headers into
81 * the outgoing INVITE request. Because of this, the outgoing
82 * INVITE request will contain the \a Replaces and \a Require headers.
83 *
84 *
85 * For more information, please see the implementation of
86 * #pjsua_call_xfer_replaces() in \ref PJSUA_LIB source code.
87 *
88 *
89 * \subsection PJSIP_REPLACES_UAS_SUBSEC UAS Behavior: Receiving a Replaces Header
90 *
91 * The Replaces header contains information used to match an existing
92 * SIP dialog (call-id, to-tag, and from-tag). Upon receiving an INVITE
93 * with a Replaces header, the User Agent (UA) attempts to match this
94 * information with a confirmed or early dialog.
95 *
96 * In PJSIP, if application wants to process the Replaces header in the
97 * incoming INVITE request, it should call #pjsip_replaces_verify_request()
98 * before creating the INVITE session. The #pjsip_replaces_verify_request()
99 * function checks and verifies the request to see if Replaces request
100 * can be processed. To be more specific, it performs the following
101 * verification:
102 * - checks that Replaces header is present. If not, the function will
103 * return PJ_SUCCESS without doing anything.
104 * - checks that no duplicate Replaces headers are present, or otherwise
105 * it will return 400 "Bad Request" response.
106 * - checks for matching dialog and verifies that the invite session has
107 * the correct state, and may return 481 "Call/Transaction Does Not Exist",
108 * 603 "Declined", or 486 "Busy Here" according to the processing rules
109 * specified in RFC 3891.
110 * - if matching dialog with correct state is found, it will give PJ_SUCCESS
111 * status and return the matching dialog back to the application.
112 *
113 * The following pseudocode illustrates how application can process the
114 * incoming INVITE if it wants to support Replaces extension:
115 *
116 \code
117 // Incoming INVITE request handler
118 pj_bool_t on_rx_invite(pjsip_rx_data *rdata)
119 {
120 pjsip_dialog *dlg, *replaced_dlg;
121 pjsip_inv_session *inv;
122 pjsip_tx_data *response;
123 pj_status_t status;
124
125 // Check whether Replaces header is present in the request and process accordingly.
126 //
127 status = pjsip_replaces_verify_request(rdata, &replaced_dlg, PJ_FALSE, &response);
128 if (status != PJ_SUCCESS) {
129 // Something wrong with Replaces request.
130 //
131 if (response) {
132 pjsip_endpt_send_response(endpt, rdata, response, NULL, NULL);
133 } else {
134 // Respond with 500 (Internal Server Error)
135 pjsip_endpt_respond_stateless(endpt, rdata, 500, NULL, NULL, NULL);
136 }
137 }
138
139 // Create UAS Invite session as usual.
140 //
141 status = pjsip_dlg_create_uas(.., rdata, .., &dlg);
142 ..
143 status = pjsip_inv_create_uas(dlg, .., &inv);
144
145 // Send initial 100 "Trying" to the INVITE request
146 //
147 status = pjsip_inv_initial_answer(inv, rdata, 100, ..., &response);
148 if (status == PJ_SUCCESS)
149 pjsip_inv_send_msg(inv, response);
150
151
152 // This is where processing is different between normal call
153 // (without Replaces) and call with Replaces.
154 //
155 if (replaced_dlg) {
156 pjsip_inv_session *replaced_inv;
157
158 // Always answer the new INVITE with 200, regardless whether
159 // the replaced call is in early or confirmed state.
160 //
161 status = pjsip_inv_answer(inv, 200, NULL, NULL, &response);
162 if (status == PJ_SUCCESS)
163 pjsip_inv_send_msg(inv, response);
164
165
166 // Get the INVITE session associated with the replaced dialog.
167 //
168 replaced_inv = pjsip_dlg_get_inv_session(replaced_dlg);
169
170
171 // Disconnect the "replaced" INVITE session.
172 //
173 status = pjsip_inv_end_session(replaced_inv, PJSIP_SC_GONE, NULL, &tdata);
174 if (status == PJ_SUCCESS && tdata)
175 status = pjsip_inv_send_msg(replaced_inv, tdata);
176
177
178 // It's up to application to associate the new INVITE session
179 // with the old (now terminated) session. For example, application
180 // may assign the same User Interface object for the new INVITE
181 // session.
182
183 } else {
184 // Process normal INVITE without Replaces.
185 ...
186 }
187 }
188
189 \endcode
190 *
191 *
192 * For a complete sample implementation, please see \a pjsua_call_on_incoming()
193 * function of \ref PJSUA_LIB in \a pjsua_call.c file.
194 *
195 *
196 * \section PJSIP_REPLACES_REFERENCE References
197 *
198 * References:
199 * - <A HREF="http://www.ietf.org/rfc/rfc3891.txt">RFC 3891: The Session
200 * Initiation Protocol (SIP) "Replaces" Header</A>
201 * - \ref PJSUA_XFER
202 */
203
204PJ_BEGIN_DECL
205
206
207/**
208 * Declaration of SIP Replaces header (RFC 3891).
209 */
210typedef struct pjsip_replaces_hdr
211{
212 /** Standard header field. */
213 PJSIP_DECL_HDR_MEMBER(struct pjsip_replaces_hdr);
214
215 /** Call-Id */
216 pj_str_t call_id;
217
218 /** to-tag */
219 pj_str_t to_tag;
220
221 /** from-tag */
222 pj_str_t from_tag;
223
224 /** early-only? */
225 pj_bool_t early_only;
226
227 /** Other parameters */
228 pjsip_param other_param;
229
230} pjsip_replaces_hdr;
231
232
233
234/**
235 * Initialize Replaces support in PJSIP. This would, among other things,
236 * register the header parser for Replaces header.
237 *
238 * @param endpt The endpoint instance.
239 *
240 * @return PJ_SUCCESS on success.
241 */
242PJ_DECL(pj_status_t) pjsip_replaces_init_module(pjsip_endpoint *endpt);
243
244
245/**
246 * Create Replaces header.
247 *
248 * @param pool Pool to allocate the header instance from.
249 *
250 * @return An empty Replaces header instance.
251 */
252PJ_DECL(pjsip_replaces_hdr*) pjsip_replaces_hdr_create(pj_pool_t *pool);
253
254
255/**
256 * Verify that incoming request with Replaces header can be processed.
257 * This function will perform all necessary checks according to RFC 3891
258 * Section 3 "User Agent Server Behavior: Receiving a Replaces Header".
259 *
260 * @param rdata The incoming request to be verified.
261 * @param p_dlg On return, it will be filled with the matching
262 * dialog.
263 * @param lock_dlg Specifies whether this function should acquire lock
264 * to the matching dialog. If yes (and should be yes!),
265 * then application will need to release the dialog's
266 * lock with #pjsip_dlg_dec_lock() when the function
267 * returns PJ_SUCCESS and the \a p_dlg parameter is filled
268 * with the dialog instance.
269 * @param p_tdata Upon error, it will be filled with the final response
270 * to be sent to the request sender.
271 *
272 * @return The function returns the following:
273 * - If the request doesn't contain Replaces header, the
274 * function returns PJ_SUCCESS and \a p_dlg parameter
275 * will be set to NULL.
276 * - If the request contains Replaces header and a valid,
277 * matching dialog is found, the function returns
278 * PJ_SUCCESS and \a p_dlg parameter will be set to the
279 * matching dialog instance.
280 * - Upon error condition (as described by RFC 3891), the
281 * function returns non-PJ_SUCCESS, and \a p_tdata
282 * parameter SHOULD be set with a final response message
283 * to be sent to the sender of the request.
284 */
285PJ_DECL(pj_status_t) pjsip_replaces_verify_request(pjsip_rx_data *rdata,
286 pjsip_dialog **p_dlg,
287 pj_bool_t lock_dlg,
288 pjsip_tx_data **p_tdata);
289
290
291
292PJ_END_DECL
293
294
295/**
296 * @}
297 */
298
299
300#endif /* __PJSIP_REPLACES_H__ */
301