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