Add support for ICE/STUN/TURN in res_rtp_asterisk and chan_sip.
[asterisk/asterisk.git] / res / pjproject / pjsip / src / pjsip-ua / sip_xfer.c
1 /* $Id$ */
2 /* 
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 #include <pjsip-ua/sip_xfer.h>
21 #include <pjsip-simple/evsub_msg.h>
22 #include <pjsip/sip_dialog.h>
23 #include <pjsip/sip_errno.h>
24 #include <pjsip/sip_endpoint.h>
25 #include <pjsip/sip_module.h>
26 #include <pjsip/sip_transport.h>
27 #include <pj/assert.h>
28 #include <pj/pool.h>
29 #include <pj/string.h>
30
31 /* Subscription expiration */
32 #ifndef PJSIP_XFER_EXPIRES
33 #   define PJSIP_XFER_EXPIRES       600
34 #endif
35
36
37 /*
38  * Refer module (mod-refer)
39  */
40 static struct pjsip_module mod_xfer = 
41 {
42     NULL, NULL,                         /* prev, next.                  */
43     { "mod-refer", 9 },                 /* Name.                        */
44     -1,                                 /* Id                           */
45     PJSIP_MOD_PRIORITY_DIALOG_USAGE,    /* Priority                     */
46     NULL,                               /* load()                       */
47     NULL,                               /* start()                      */
48     NULL,                               /* stop()                       */
49     NULL,                               /* unload()                     */
50     NULL,                               /* on_rx_request()              */
51     NULL,                               /* on_rx_response()             */
52     NULL,                               /* on_tx_request.               */
53     NULL,                               /* on_tx_response()             */
54     NULL,                               /* on_tsx_state()               */
55 };
56
57
58 /* Declare PJSIP_REFER_METHOD, so that if somebody declares this in
59  * sip_msg.h we can catch the error here.
60  */
61 enum
62 {
63     PJSIP_REFER_METHOD = PJSIP_OTHER_METHOD
64 };
65
66 PJ_DEF_DATA(const pjsip_method) pjsip_refer_method = {
67     (pjsip_method_e) PJSIP_REFER_METHOD,
68     { "REFER", 5}
69 };
70
71 PJ_DEF(const pjsip_method*) pjsip_get_refer_method()
72 {
73     return &pjsip_refer_method;
74 }
75
76 /*
77  * String constants
78  */
79 const pj_str_t STR_REFER = { "refer", 5 };
80 const pj_str_t STR_MESSAGE = { "message", 7 };
81 const pj_str_t STR_SIPFRAG = { "sipfrag", 7 };
82 const pj_str_t STR_SIPFRAG_VERSION = {";version=2.0", 12 };
83
84
85 /*
86  * Transfer struct.
87  */
88 struct pjsip_xfer
89 {
90     pjsip_evsub         *sub;           /**< Event subscribtion record.     */
91     pjsip_dialog        *dlg;           /**< The dialog.                    */
92     pjsip_evsub_user     user_cb;       /**< The user callback.             */
93     pj_str_t             refer_to_uri;  /**< The full Refer-To URI.         */
94     int                  last_st_code;  /**< st_code sent in last NOTIFY    */
95     pj_str_t             last_st_text;  /**< st_text sent in last NOTIFY    */
96 };
97
98
99 typedef struct pjsip_xfer pjsip_xfer;
100
101
102
103 /*
104  * Forward decl for evsub callback.
105  */
106 static void xfer_on_evsub_state( pjsip_evsub *sub, pjsip_event *event);
107 static void xfer_on_evsub_tsx_state( pjsip_evsub *sub, pjsip_transaction *tsx,
108                                      pjsip_event *event);
109 static void xfer_on_evsub_rx_refresh( pjsip_evsub *sub, 
110                                       pjsip_rx_data *rdata,
111                                       int *p_st_code,
112                                       pj_str_t **p_st_text,
113                                       pjsip_hdr *res_hdr,
114                                       pjsip_msg_body **p_body);
115 static void xfer_on_evsub_rx_notify( pjsip_evsub *sub, 
116                                      pjsip_rx_data *rdata,
117                                      int *p_st_code,
118                                      pj_str_t **p_st_text,
119                                      pjsip_hdr *res_hdr,
120                                      pjsip_msg_body **p_body);
121 static void xfer_on_evsub_client_refresh(pjsip_evsub *sub);
122 static void xfer_on_evsub_server_timeout(pjsip_evsub *sub);
123
124
125 /*
126  * Event subscription callback for xference.
127  */
128 static pjsip_evsub_user xfer_user = 
129 {
130     &xfer_on_evsub_state,
131     &xfer_on_evsub_tsx_state,
132     &xfer_on_evsub_rx_refresh,
133     &xfer_on_evsub_rx_notify,
134     &xfer_on_evsub_client_refresh,
135     &xfer_on_evsub_server_timeout,
136 };
137
138
139
140
141 /*
142  * Initialize the REFER subsystem.
143  */
144 PJ_DEF(pj_status_t) pjsip_xfer_init_module(pjsip_endpoint *endpt)
145 {
146     const pj_str_t accept = { "message/sipfrag;version=2.0", 27 };
147     pj_status_t status;
148
149     PJ_ASSERT_RETURN(endpt != NULL, PJ_EINVAL);
150     PJ_ASSERT_RETURN(mod_xfer.id == -1, PJ_EINVALIDOP);
151
152     status = pjsip_endpt_register_module(endpt, &mod_xfer);
153     if (status != PJ_SUCCESS)
154         return status;
155
156     status = pjsip_endpt_add_capability( endpt, &mod_xfer, PJSIP_H_ALLOW, 
157                                          NULL, 1, 
158                                          &pjsip_get_refer_method()->name);
159     if (status != PJ_SUCCESS)
160         return status;
161
162     status = pjsip_evsub_register_pkg(&mod_xfer, &STR_REFER, 
163                                       PJSIP_XFER_EXPIRES, 1, &accept);
164     if (status != PJ_SUCCESS)
165         return status;
166
167     return PJ_SUCCESS;
168 }
169
170
171 /*
172  * Create transferer (sender of REFER request).
173  *
174  */
175 PJ_DEF(pj_status_t) pjsip_xfer_create_uac( pjsip_dialog *dlg,
176                                            const pjsip_evsub_user *user_cb,
177                                            pjsip_evsub **p_evsub )
178 {
179     pj_status_t status;
180     pjsip_xfer *xfer;
181     pjsip_evsub *sub;
182
183     PJ_ASSERT_RETURN(dlg && p_evsub, PJ_EINVAL);
184
185     pjsip_dlg_inc_lock(dlg);
186
187     /* Create event subscription */
188     status = pjsip_evsub_create_uac( dlg,  &xfer_user, &STR_REFER, 
189                                      PJSIP_EVSUB_NO_EVENT_ID, &sub);
190     if (status != PJ_SUCCESS)
191         goto on_return;
192
193     /* Create xfer session */
194     xfer = PJ_POOL_ZALLOC_T(dlg->pool, pjsip_xfer);
195     xfer->dlg = dlg;
196     xfer->sub = sub;
197     if (user_cb)
198         pj_memcpy(&xfer->user_cb, user_cb, sizeof(pjsip_evsub_user));
199
200     /* Attach to evsub */
201     pjsip_evsub_set_mod_data(sub, mod_xfer.id, xfer);
202
203     *p_evsub = sub;
204
205 on_return:
206     pjsip_dlg_dec_lock(dlg);
207     return status;
208
209 }
210
211
212
213
214 /*
215  * Create transferee (receiver of REFER request).
216  *
217  */
218 PJ_DEF(pj_status_t) pjsip_xfer_create_uas( pjsip_dialog *dlg,
219                                            const pjsip_evsub_user *user_cb,
220                                            pjsip_rx_data *rdata,
221                                            pjsip_evsub **p_evsub )
222 {
223     pjsip_evsub *sub;
224     pjsip_xfer *xfer;
225     const pj_str_t STR_EVENT = {"Event", 5 };
226     pjsip_event_hdr *event_hdr;
227     pj_status_t status;
228
229     /* Check arguments */
230     PJ_ASSERT_RETURN(dlg && rdata && p_evsub, PJ_EINVAL);
231
232     /* Must be request message */
233     PJ_ASSERT_RETURN(rdata->msg_info.msg->type == PJSIP_REQUEST_MSG,
234                      PJSIP_ENOTREQUESTMSG);
235
236     /* Check that request is REFER */
237     PJ_ASSERT_RETURN(pjsip_method_cmp(&rdata->msg_info.msg->line.req.method,
238                                       pjsip_get_refer_method())==0,
239                      PJSIP_ENOTREFER);
240
241     /* Lock dialog */
242     pjsip_dlg_inc_lock(dlg);
243
244     /* The evsub framework expects an Event header in the request,
245      * while a REFER request conveniently doesn't have one (pun intended!).
246      * So create a dummy Event header.
247      */
248     if (pjsip_msg_find_hdr_by_name(rdata->msg_info.msg,
249                                    &STR_EVENT, NULL)==NULL)
250     {
251         event_hdr = pjsip_event_hdr_create(rdata->tp_info.pool);
252         event_hdr->event_type = STR_REFER;
253         pjsip_msg_add_hdr(rdata->msg_info.msg, (pjsip_hdr*)event_hdr);
254     }
255
256     /* Create server subscription */
257     status = pjsip_evsub_create_uas( dlg, &xfer_user, rdata, 
258                                      PJSIP_EVSUB_NO_EVENT_ID, &sub);
259     if (status != PJ_SUCCESS)
260         goto on_return;
261
262     /* Create server xfer subscription */
263     xfer = PJ_POOL_ZALLOC_T(dlg->pool, pjsip_xfer);
264     xfer->dlg = dlg;
265     xfer->sub = sub;
266     if (user_cb)
267         pj_memcpy(&xfer->user_cb, user_cb, sizeof(pjsip_evsub_user));
268
269     /* Attach to evsub */
270     pjsip_evsub_set_mod_data(sub, mod_xfer.id, xfer);
271
272     /* Done: */
273     *p_evsub = sub;
274
275 on_return:
276     pjsip_dlg_dec_lock(dlg);
277     return status;
278 }
279
280
281
282 /*
283  * Call this function to create request to initiate REFER subscription.
284  *
285  */
286 PJ_DEF(pj_status_t) pjsip_xfer_initiate( pjsip_evsub *sub,
287                                          const pj_str_t *refer_to_uri,
288                                          pjsip_tx_data **p_tdata)
289 {
290     pjsip_xfer *xfer;
291     const pj_str_t refer_to = { "Refer-To", 8};
292     pjsip_tx_data *tdata;
293     pjsip_generic_string_hdr *hdr;
294     pj_status_t status;
295
296     /* sub and p_tdata argument must be valid.  */
297     PJ_ASSERT_RETURN(sub && p_tdata, PJ_EINVAL);
298
299
300     /* Get the xfer object. */
301     xfer = (pjsip_xfer*) pjsip_evsub_get_mod_data(sub, mod_xfer.id);
302     PJ_ASSERT_RETURN(xfer != NULL, PJSIP_ENOREFERSESSION);
303
304     /* refer_to_uri argument MAY be NULL for subsequent REFER requests,
305      * but it MUST be specified in the first REFER.
306      */
307     PJ_ASSERT_RETURN((refer_to_uri || xfer->refer_to_uri.slen), PJ_EINVAL);
308
309     /* Lock dialog. */
310     pjsip_dlg_inc_lock(xfer->dlg);
311
312     /* Create basic REFER request */
313     status = pjsip_evsub_initiate(sub, pjsip_get_refer_method(), -1, 
314                                   &tdata);
315     if (status != PJ_SUCCESS)
316         goto on_return;
317
318     /* Save Refer-To URI. */
319     if (refer_to_uri == NULL) {
320         refer_to_uri = &xfer->refer_to_uri;
321     } else {
322         pj_strdup(xfer->dlg->pool, &xfer->refer_to_uri, refer_to_uri);
323     }
324
325     /* Create and add Refer-To header. */
326     hdr = pjsip_generic_string_hdr_create(tdata->pool, &refer_to,
327                                           refer_to_uri);
328     if (!hdr) {
329         pjsip_tx_data_dec_ref(tdata);
330         status = PJ_ENOMEM;
331         goto on_return;
332     }
333
334     pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)hdr);
335
336
337     /* Done. */
338     *p_tdata = tdata;
339
340     status = PJ_SUCCESS;
341
342 on_return:
343     pjsip_dlg_dec_lock(xfer->dlg);
344     return status;
345 }
346
347
348 /*
349  * Accept the incoming REFER request by sending 2xx response.
350  *
351  */
352 PJ_DEF(pj_status_t) pjsip_xfer_accept( pjsip_evsub *sub,
353                                        pjsip_rx_data *rdata,
354                                        int st_code,
355                                        const pjsip_hdr *hdr_list )
356 {
357     /*
358      * Don't need to add custom headers, so just call basic
359      * evsub response.
360      */
361     return pjsip_evsub_accept( sub, rdata, st_code, hdr_list );
362 }
363
364
365 /*
366  * For notifier, create NOTIFY request to subscriber, and set the state 
367  * of the subscription. 
368  */
369 PJ_DEF(pj_status_t) pjsip_xfer_notify( pjsip_evsub *sub,
370                                        pjsip_evsub_state state,
371                                        int xfer_st_code,
372                                        const pj_str_t *xfer_st_text,
373                                        pjsip_tx_data **p_tdata)
374 {
375     pjsip_tx_data *tdata;
376     pjsip_xfer *xfer;
377     pjsip_param *param;
378     const pj_str_t reason = { "noresource", 10 };
379     char *body;
380     int bodylen;
381     pjsip_msg_body *msg_body;
382     pj_status_t status;
383     
384
385     /* Check arguments. */
386     PJ_ASSERT_RETURN(sub, PJ_EINVAL);
387
388     /* Get the xfer object. */
389     xfer = (pjsip_xfer*) pjsip_evsub_get_mod_data(sub, mod_xfer.id);
390     PJ_ASSERT_RETURN(xfer != NULL, PJSIP_ENOREFERSESSION);
391
392
393     /* Lock object. */
394     pjsip_dlg_inc_lock(xfer->dlg);
395
396     /* Create the NOTIFY request. 
397      * Note that reason is only used when state is TERMINATED, and
398      * the defined termination reason for REFER is "noresource".
399      */
400     status = pjsip_evsub_notify( sub, state, NULL, &reason, &tdata);
401     if (status != PJ_SUCCESS)
402         goto on_return;
403
404
405     /* Check status text */
406     if (xfer_st_text==NULL || xfer_st_text->slen==0)
407         xfer_st_text = pjsip_get_status_text(xfer_st_code);
408
409     /* Save st_code and st_text, for current_notify() */
410     xfer->last_st_code = xfer_st_code;
411     pj_strdup(xfer->dlg->pool, &xfer->last_st_text, xfer_st_text);
412
413     /* Create sipfrag content. */
414     body = (char*) pj_pool_alloc(tdata->pool, 128);
415     bodylen = pj_ansi_snprintf(body, 128, "SIP/2.0 %u %.*s\r\n",
416                                xfer_st_code,
417                                (int)xfer_st_text->slen,
418                                xfer_st_text->ptr);
419     PJ_ASSERT_ON_FAIL(bodylen > 0 && bodylen < 128, 
420                         {status=PJ_EBUG; pjsip_tx_data_dec_ref(tdata); 
421                          goto on_return; });
422
423
424     /* Create SIP message body. */
425     msg_body = PJ_POOL_ZALLOC_T(tdata->pool, pjsip_msg_body);
426     pjsip_media_type_init(&msg_body->content_type, (pj_str_t*)&STR_MESSAGE,
427                           (pj_str_t*)&STR_SIPFRAG);
428     msg_body->data = body;
429     msg_body->len = bodylen;
430     msg_body->print_body = &pjsip_print_text_body;
431     msg_body->clone_data = &pjsip_clone_text_data;
432
433     param = PJ_POOL_ALLOC_T(tdata->pool, pjsip_param);
434     param->name = pj_str("version");
435     param->value = pj_str("2.0");
436     pj_list_push_back(&msg_body->content_type.param, param);
437
438     /* Attach sipfrag body. */
439     tdata->msg->body = msg_body;
440
441
442     /* Done. */
443     *p_tdata = tdata;
444
445
446 on_return:
447     pjsip_dlg_dec_lock(xfer->dlg);
448     return status;
449
450 }
451
452
453 /*
454  * Send current state and the last sipfrag body.
455  */
456 PJ_DEF(pj_status_t) pjsip_xfer_current_notify( pjsip_evsub *sub,
457                                                pjsip_tx_data **p_tdata )
458 {
459     pjsip_xfer *xfer;
460     pj_status_t status;
461     
462
463     /* Check arguments. */
464     PJ_ASSERT_RETURN(sub, PJ_EINVAL);
465
466     /* Get the xfer object. */
467     xfer = (pjsip_xfer*) pjsip_evsub_get_mod_data(sub, mod_xfer.id);
468     PJ_ASSERT_RETURN(xfer != NULL, PJSIP_ENOREFERSESSION);
469
470     pjsip_dlg_inc_lock(xfer->dlg);
471
472     status = pjsip_xfer_notify(sub, pjsip_evsub_get_state(sub),
473                                xfer->last_st_code, &xfer->last_st_text,
474                                p_tdata);
475
476     pjsip_dlg_dec_lock(xfer->dlg);
477
478     return status;
479 }
480
481
482 /*
483  * Send request message. 
484  */
485 PJ_DEF(pj_status_t) pjsip_xfer_send_request( pjsip_evsub *sub,
486                                              pjsip_tx_data *tdata)
487 {
488     return pjsip_evsub_send_request(sub, tdata);
489 }
490
491
492 /*
493  * This callback is called by event subscription when subscription
494  * state has changed.
495  */
496 static void xfer_on_evsub_state( pjsip_evsub *sub, pjsip_event *event)
497 {
498     pjsip_xfer *xfer;
499
500     xfer = (pjsip_xfer*) pjsip_evsub_get_mod_data(sub, mod_xfer.id);
501     PJ_ASSERT_ON_FAIL(xfer!=NULL, {return;});
502
503     if (xfer->user_cb.on_evsub_state)
504         (*xfer->user_cb.on_evsub_state)(sub, event);
505
506 }
507
508 /*
509  * Called when transaction state has changed.
510  */
511 static void xfer_on_evsub_tsx_state( pjsip_evsub *sub, pjsip_transaction *tsx,
512                                      pjsip_event *event)
513 {
514     pjsip_xfer *xfer;
515
516     xfer = (pjsip_xfer*) pjsip_evsub_get_mod_data(sub, mod_xfer.id);
517     PJ_ASSERT_ON_FAIL(xfer!=NULL, {return;});
518
519     if (xfer->user_cb.on_tsx_state)
520         (*xfer->user_cb.on_tsx_state)(sub, tsx, event);
521 }
522
523 /*
524  * Called when REFER is received to refresh subscription.
525  */
526 static void xfer_on_evsub_rx_refresh( pjsip_evsub *sub, 
527                                       pjsip_rx_data *rdata,
528                                       int *p_st_code,
529                                       pj_str_t **p_st_text,
530                                       pjsip_hdr *res_hdr,
531                                       pjsip_msg_body **p_body)
532 {
533     pjsip_xfer *xfer;
534
535     xfer = (pjsip_xfer*) pjsip_evsub_get_mod_data(sub, mod_xfer.id);
536     PJ_ASSERT_ON_FAIL(xfer!=NULL, {return;});
537
538     if (xfer->user_cb.on_rx_refresh) {
539         (*xfer->user_cb.on_rx_refresh)(sub, rdata, p_st_code, p_st_text,
540                                        res_hdr, p_body);
541
542     } else {
543         /* Implementors MUST send NOTIFY if it implements on_rx_refresh
544          * (implementor == "us" from evsub point of view.
545          */
546         pjsip_tx_data *tdata;
547         pj_status_t status;
548
549         if (pjsip_evsub_get_state(sub)==PJSIP_EVSUB_STATE_TERMINATED) {
550             status = pjsip_xfer_notify( sub, PJSIP_EVSUB_STATE_TERMINATED,
551                                         xfer->last_st_code,
552                                         &xfer->last_st_text, 
553                                         &tdata);
554         } else {
555             status = pjsip_xfer_current_notify(sub, &tdata);
556         }
557
558         if (status == PJ_SUCCESS)
559             pjsip_xfer_send_request(sub, tdata);
560     }
561 }
562
563
564 /*
565  * Called when NOTIFY is received.
566  */
567 static void xfer_on_evsub_rx_notify( pjsip_evsub *sub, 
568                                      pjsip_rx_data *rdata,
569                                      int *p_st_code,
570                                      pj_str_t **p_st_text,
571                                      pjsip_hdr *res_hdr,
572                                      pjsip_msg_body **p_body)
573 {
574     pjsip_xfer *xfer;
575
576     xfer = (pjsip_xfer*) pjsip_evsub_get_mod_data(sub, mod_xfer.id);
577     PJ_ASSERT_ON_FAIL(xfer!=NULL, {return;});
578
579     if (xfer->user_cb.on_rx_notify)
580         (*xfer->user_cb.on_rx_notify)(sub, rdata, p_st_code, p_st_text,
581                                       res_hdr, p_body);
582 }
583
584 /*
585  * Called when it's time to send SUBSCRIBE.
586  */
587 static void xfer_on_evsub_client_refresh(pjsip_evsub *sub)
588 {
589     pjsip_xfer *xfer;
590
591     xfer = (pjsip_xfer*) pjsip_evsub_get_mod_data(sub, mod_xfer.id);
592     PJ_ASSERT_ON_FAIL(xfer!=NULL, {return;});
593
594     if (xfer->user_cb.on_client_refresh) {
595         (*xfer->user_cb.on_client_refresh)(sub);
596     } else {
597         pj_status_t status;
598         pjsip_tx_data *tdata;
599
600         status = pjsip_evsub_initiate(sub, NULL, PJSIP_XFER_EXPIRES, &tdata);
601         if (status == PJ_SUCCESS)
602             pjsip_xfer_send_request(sub, tdata);
603     }
604 }
605
606
607 /*
608  * Called when no refresh is received after the interval.
609  */
610 static void xfer_on_evsub_server_timeout(pjsip_evsub *sub)
611 {
612     pjsip_xfer *xfer;
613
614     xfer = (pjsip_xfer*) pjsip_evsub_get_mod_data(sub, mod_xfer.id);
615     PJ_ASSERT_ON_FAIL(xfer!=NULL, {return;});
616
617     if (xfer->user_cb.on_server_timeout) {
618         (*xfer->user_cb.on_server_timeout)(sub);
619     } else {
620         pj_status_t status;
621         pjsip_tx_data *tdata;
622
623         status = pjsip_xfer_notify(sub, PJSIP_EVSUB_STATE_TERMINATED,
624                                    xfer->last_st_code, 
625                                    &xfer->last_st_text, &tdata);
626         if (status == PJ_SUCCESS)
627             pjsip_xfer_send_request(sub, tdata);
628     }
629 }
630