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-simple/evsub.h>
21 #include <pjsip-simple/evsub_msg.h>
22 #include <pjsip-simple/errno.h>
23 #include <pjsip/sip_errno.h>
24 #include <pjsip/sip_module.h>
25 #include <pjsip/sip_endpoint.h>
26 #include <pjsip/sip_dialog.h>
27 #include <pjsip/sip_auth.h>
28 #include <pjsip/sip_transaction.h>
29 #include <pjsip/sip_event.h>
30 #include <pj/assert.h>
31 #include <pj/guid.h>
32 #include <pj/log.h>
33 #include <pj/os.h>
34 #include <pj/pool.h>
35 #include <pj/rand.h>
36 #include <pj/string.h>
37 
38 
39 #define THIS_FILE	"evsub.c"
40 
41 /*
42  * Global constant
43  */
44 
45 /* Let's define this enum, so that it'll trigger compilation error
46  * when somebody define the same enum in sip_msg.h
47  */
48 enum
49 {
50     PJSIP_SUBSCRIBE_METHOD = PJSIP_OTHER_METHOD,
51     PJSIP_NOTIFY_METHOD = PJSIP_OTHER_METHOD
52 };
53 
54 PJ_DEF_DATA(const pjsip_method) pjsip_subscribe_method =
55 {
56     (pjsip_method_e) PJSIP_SUBSCRIBE_METHOD,
57     { "SUBSCRIBE", 9 }
58 };
59 
60 PJ_DEF_DATA(const pjsip_method) pjsip_notify_method =
61 {
62     (pjsip_method_e) PJSIP_NOTIFY_METHOD,
63     { "NOTIFY", 6 }
64 };
65 
66 /**
67  * SUBSCRIBE method constant.
68  */
pjsip_get_subscribe_method()69 PJ_DEF(const pjsip_method*) pjsip_get_subscribe_method()
70 {
71     return &pjsip_subscribe_method;
72 }
73 
74 /**
75  * NOTIFY method constant.
76  */
pjsip_get_notify_method()77 PJ_DEF(const pjsip_method*) pjsip_get_notify_method()
78 {
79     return &pjsip_notify_method;
80 }
81 
82 
83 /*
84  * Static prototypes.
85  */
86 static void	   mod_evsub_on_tsx_state(pjsip_transaction*, pjsip_event*);
87 static pj_status_t mod_evsub_unload(void);
88 
89 
90 /*
91  * State names.
92  */
93 static pj_str_t evsub_state_names[] =
94 {
95     { "NULL",	    4},
96     { "SENT",	    4},
97     { "ACCEPTED",   8},
98     { "PENDING",    7},
99     { "ACTIVE",	    6},
100     { "TERMINATED", 10},
101     { "UNKNOWN",    7}
102 };
103 
104 /*
105  * Timer constants.
106  */
107 
108 /* Number of seconds to send SUBSCRIBE before the actual expiration */
109 #define TIME_UAC_REFRESH	PJSIP_EVSUB_TIME_UAC_REFRESH
110 
111 /* Time to wait for the final NOTIFY after sending unsubscription */
112 #define TIME_UAC_TERMINATE	PJSIP_EVSUB_TIME_UAC_TERMINATE
113 
114 /* If client responds NOTIFY with non-2xx final response (such as 401),
115  * wait for this seconds for further NOTIFY, otherwise client will
116  * unsubscribe
117  */
118 #define TIME_UAC_WAIT_NOTIFY	PJSIP_EVSUB_TIME_UAC_WAIT_NOTIFY
119 
120 
121 /*
122  * Timer id
123  */
124 enum timer_id
125 {
126     /* No timer. */
127     TIMER_TYPE_NONE,
128 
129     /* Time to refresh client subscription.
130      * The action is to call on_client_refresh() callback.
131      */
132     TIMER_TYPE_UAC_REFRESH,
133 
134     /* UAS timeout after to subscription refresh.
135      * The action is to call on_server_timeout() callback.
136      */
137     TIMER_TYPE_UAS_TIMEOUT,
138 
139     /* UAC waiting for final NOTIFY after unsubscribing
140      * The action is to terminate.
141      */
142     TIMER_TYPE_UAC_TERMINATE,
143 
144     /* UAC waiting for further NOTIFY after sending non-2xx response to
145      * NOTIFY. The action is to unsubscribe.
146      */
147     TIMER_TYPE_UAC_WAIT_NOTIFY,
148 
149     /* Max nb of timer types. */
150     TIMER_TYPE_MAX
151 };
152 
153 static const char *timer_names[] =
154 {
155     "None",
156     "UAC_REFRESH",
157     "UAS_TIMEOUT",
158     "UAC_TERMINATE",
159     "UAC_WAIT_NOTIFY",
160     "INVALID_TIMER"
161 };
162 
163 /*
164  * Definition of event package.
165  */
166 struct evpkg
167 {
168     PJ_DECL_LIST_MEMBER(struct evpkg);
169 
170     pj_str_t		 pkg_name;
171     pjsip_module	*pkg_mod;
172     unsigned		 pkg_expires;
173     pjsip_accept_hdr	*pkg_accept;
174 };
175 
176 
177 /*
178  * Event subscription module (mod-evsub).
179  */
180 static struct mod_evsub
181 {
182     pjsip_module	     mod;
183     pj_pool_t		    *pool;
184     pjsip_endpoint	    *endpt;
185     struct evpkg	     pkg_list;
186     pjsip_allow_events_hdr  *allow_events_hdr;
187 
188 } mod_evsub =
189 {
190     {
191 	NULL, NULL,			    /* prev, next.		*/
192 	{ "mod-evsub", 9 },		    /* Name.			*/
193 	-1,				    /* Id			*/
194 	PJSIP_MOD_PRIORITY_DIALOG_USAGE,    /* Priority			*/
195 	NULL,				    /* load()			*/
196 	NULL,				    /* start()			*/
197 	NULL,				    /* stop()			*/
198 	&mod_evsub_unload,		    /* unload()			*/
199 	NULL,				    /* on_rx_request()		*/
200 	NULL,				    /* on_rx_response()		*/
201 	NULL,				    /* on_tx_request.		*/
202 	NULL,				    /* on_tx_response()		*/
203 	&mod_evsub_on_tsx_state,	    /* on_tsx_state()		*/
204     }
205 };
206 
207 
208 /*
209  * Event subscription session.
210  */
211 struct pjsip_evsub
212 {
213     char		  obj_name[PJ_MAX_OBJ_NAME]; /**< Name.		    */
214     pj_pool_t		 *pool;		/**< Pool.			    */
215     pjsip_endpoint	 *endpt;	/**< Endpoint instance.		    */
216     pjsip_dialog	 *dlg;		/**< Underlying dialog.		    */
217     struct evpkg	 *pkg;		/**< The event package.		    */
218     unsigned		  option;	/**< Options.			    */
219     pjsip_evsub_user	  user;		/**< Callback.			    */
220     pj_bool_t		  call_cb;	/**< Notify callback?		    */
221     pjsip_role_e	  role;		/**< UAC=subscriber, UAS=notifier   */
222     pjsip_evsub_state	  state;	/**< Subscription state.	    */
223     pj_str_t		  state_str;	/**< String describing the state.   */
224     pjsip_evsub_state	  dst_state;	/**< Pending state to be set.	    */
225     pj_str_t		  dst_state_str;/**< Pending state to be set.	    */
226     pj_str_t		  term_reason;	/**< Termination reason.	    */
227     pjsip_method	  method;	/**< Method that established subscr.*/
228     pjsip_event_hdr	 *event;	/**< Event description.		    */
229     pjsip_expires_hdr	 *expires;	/**< Expires header		    */
230     pjsip_accept_hdr	 *accept;	/**< Local Accept header.	    */
231     pjsip_hdr             sub_hdr_list; /**< User-defined header.           */
232 
233     pj_time_val		  refresh_time;	/**< Time to refresh.		    */
234     pj_timer_entry	  timer;	/**< Internal timer.		    */
235     int			  pending_tsx;	/**< Number of pending transactions.*/
236     pjsip_transaction	 *pending_sub;	/**< Pending UAC SUBSCRIBE tsx.	    */
237     pj_timer_entry	 *pending_sub_timer; /**< Stop pending sub timer.   */
238     pj_grp_lock_t	 *grp_lock;	/* Session group lock	    */
239 
240     void		 *mod_data[PJSIP_MAX_MODULE];	/**< Module data.   */
241 };
242 
243 
244 /*
245  * This is the structure that will be "attached" to dialog.
246  * The purpose is to allow multiple subscriptions inside a dialog.
247  */
248 struct dlgsub
249 {
250     PJ_DECL_LIST_MEMBER(struct dlgsub);
251     pjsip_evsub *sub;
252 };
253 
254 
255 /* Static vars. */
256 static const pj_str_t STR_EVENT	       = { "Event", 5 };
257 static const pj_str_t STR_EVENT_S      = { "o", 1 };
258 static const pj_str_t STR_SUB_STATE    = { "Subscription-State", 18 };
259 static const pj_str_t STR_TERMINATED   = { "terminated", 10 };
260 static const pj_str_t STR_ACTIVE       = { "active", 6 };
261 static const pj_str_t STR_PENDING      = { "pending", 7 };
262 static const pj_str_t STR_TIMEOUT      = { "timeout", 7};
263 static const pj_str_t STR_RETRY_AFTER  = { "Retry-After", 11 };
264 
265 
266 /*
267  * On unload module.
268  */
mod_evsub_unload(void)269 static pj_status_t mod_evsub_unload(void)
270 {
271     pjsip_endpt_release_pool(mod_evsub.endpt, mod_evsub.pool);
272     mod_evsub.pool = NULL;
273 
274     return PJ_SUCCESS;
275 }
276 
277 /* Proto for pjsipsimple_strerror().
278  * Defined in errno.c
279  */
280 PJ_DECL(pj_str_t) pjsipsimple_strerror( pj_status_t statcode,
281 				        char *buf, pj_size_t bufsize );
282 
283 /*
284  * Init and register module.
285  */
pjsip_evsub_init_module(pjsip_endpoint * endpt)286 PJ_DEF(pj_status_t) pjsip_evsub_init_module(pjsip_endpoint *endpt)
287 {
288     pj_status_t status;
289     pj_str_t method_tags[] = {
290 	{ "SUBSCRIBE", 9},
291 	{ "NOTIFY", 6}
292     };
293 
294     status = pj_register_strerror(PJSIP_SIMPLE_ERRNO_START,
295 				  PJ_ERRNO_SPACE_SIZE,
296 				  &pjsipsimple_strerror);
297     pj_assert(status == PJ_SUCCESS);
298 
299     PJ_ASSERT_RETURN(endpt != NULL, PJ_EINVAL);
300     PJ_ASSERT_RETURN(mod_evsub.mod.id == -1, PJ_EINVALIDOP);
301 
302     /* Keep endpoint for future reference: */
303     mod_evsub.endpt = endpt;
304 
305     /* Init event package list: */
306     pj_list_init(&mod_evsub.pkg_list);
307 
308     /* Create pool: */
309     mod_evsub.pool = pjsip_endpt_create_pool(endpt, "evsub",
310                                         PJSIP_POOL_EVSUB_LEN,
311                                         PJSIP_POOL_EVSUB_INC);
312     if (!mod_evsub.pool)
313 	return PJ_ENOMEM;
314 
315     /* Register module: */
316     status = pjsip_endpt_register_module(endpt, &mod_evsub.mod);
317     if (status  != PJ_SUCCESS)
318 	goto on_error;
319 
320     /* Create Allow-Events header: */
321     mod_evsub.allow_events_hdr = pjsip_allow_events_hdr_create(mod_evsub.pool);
322 
323     /* Register SIP-event specific headers parser: */
324     pjsip_evsub_init_parser();
325 
326     /* Register new methods SUBSCRIBE and NOTIFY in Allow-ed header */
327     pjsip_endpt_add_capability(endpt, &mod_evsub.mod, PJSIP_H_ALLOW, NULL,
328 			       2, method_tags);
329 
330     /* Done. */
331     return PJ_SUCCESS;
332 
333 on_error:
334     if (mod_evsub.pool) {
335 	pjsip_endpt_release_pool(endpt, mod_evsub.pool);
336 	mod_evsub.pool = NULL;
337     }
338     mod_evsub.endpt = NULL;
339     return status;
340 }
341 
342 
343 /*
344  * Get the instance of the module.
345  */
pjsip_evsub_instance(void)346 PJ_DEF(pjsip_module*) pjsip_evsub_instance(void)
347 {
348     PJ_ASSERT_RETURN(mod_evsub.mod.id != -1, NULL);
349 
350     return &mod_evsub.mod;
351 }
352 
353 
354 /*
355  * Get the event subscription instance in the transaction.
356  */
pjsip_tsx_get_evsub(pjsip_transaction * tsx)357 PJ_DEF(pjsip_evsub*) pjsip_tsx_get_evsub(pjsip_transaction *tsx)
358 {
359     return (pjsip_evsub*) tsx->mod_data[mod_evsub.mod.id];
360 }
361 
362 
363 /*
364  * Set event subscription's module data.
365  */
pjsip_evsub_set_mod_data(pjsip_evsub * sub,unsigned mod_id,void * data)366 PJ_DEF(void) pjsip_evsub_set_mod_data( pjsip_evsub *sub, unsigned mod_id,
367 				       void *data )
368 {
369     PJ_ASSERT_ON_FAIL(mod_id < PJSIP_MAX_MODULE, return);
370     sub->mod_data[mod_id] = data;
371 }
372 
373 
374 /*
375  * Get event subscription's module data.
376  */
pjsip_evsub_get_mod_data(pjsip_evsub * sub,unsigned mod_id)377 PJ_DEF(void*) pjsip_evsub_get_mod_data( pjsip_evsub *sub, unsigned mod_id )
378 {
379     PJ_ASSERT_RETURN(mod_id < PJSIP_MAX_MODULE, NULL);
380     return sub->mod_data[mod_id];
381 }
382 
383 
384 /*
385  * Find registered event package with matching name.
386  */
find_pkg(const pj_str_t * event_name)387 static struct evpkg* find_pkg(const pj_str_t *event_name)
388 {
389     struct evpkg *pkg;
390 
391     pkg = mod_evsub.pkg_list.next;
392     while (pkg != &mod_evsub.pkg_list) {
393 
394 	if (pj_stricmp(&pkg->pkg_name, event_name) == 0) {
395 	    return pkg;
396 	}
397 
398 	pkg = pkg->next;
399     }
400 
401     return NULL;
402 }
403 
404 /*
405  * Register an event package
406  */
pjsip_evsub_register_pkg(pjsip_module * pkg_mod,const pj_str_t * event_name,unsigned expires,unsigned accept_cnt,const pj_str_t accept[])407 PJ_DEF(pj_status_t) pjsip_evsub_register_pkg( pjsip_module *pkg_mod,
408 					      const pj_str_t *event_name,
409 					      unsigned expires,
410 					      unsigned accept_cnt,
411 					      const pj_str_t accept[])
412 {
413     struct evpkg *pkg;
414     unsigned i;
415 
416     PJ_ASSERT_RETURN(pkg_mod && event_name, PJ_EINVAL);
417 
418     /* Make sure accept_cnt < PJ_ARRAY_SIZE(pkg->pkg_accept->values) */
419     PJ_ASSERT_RETURN(accept_cnt <= PJSIP_GENERIC_ARRAY_MAX_COUNT,
420 		     PJ_ETOOMANY);
421 
422     /* Make sure evsub module has been initialized */
423     PJ_ASSERT_RETURN(mod_evsub.mod.id != -1, PJ_EINVALIDOP);
424 
425     /* Make sure no module with the specified name already registered: */
426 
427     PJ_ASSERT_RETURN(find_pkg(event_name) == NULL, PJSIP_SIMPLE_EPKGEXISTS);
428 
429 
430     /* Create new event package: */
431 
432     pkg = PJ_POOL_ALLOC_T(mod_evsub.pool, struct evpkg);
433     pkg->pkg_mod = pkg_mod;
434     pkg->pkg_expires = expires;
435     pj_strdup(mod_evsub.pool, &pkg->pkg_name, event_name);
436 
437     pkg->pkg_accept = pjsip_accept_hdr_create(mod_evsub.pool);
438     pkg->pkg_accept->count = accept_cnt;
439     for (i=0; i<accept_cnt; ++i) {
440 	pj_strdup(mod_evsub.pool, &pkg->pkg_accept->values[i], &accept[i]);
441     }
442 
443     /* Add to package list: */
444 
445     pj_list_push_back(&mod_evsub.pkg_list, pkg);
446 
447     /* Add to Allow-Events header: */
448 
449     if (mod_evsub.allow_events_hdr->count !=
450 	PJ_ARRAY_SIZE(mod_evsub.allow_events_hdr->values))
451     {
452 	mod_evsub.allow_events_hdr->values[mod_evsub.allow_events_hdr->count] =
453 	    pkg->pkg_name;
454 	++mod_evsub.allow_events_hdr->count;
455     }
456 
457     /* Add to endpoint's Accept header */
458     pjsip_endpt_add_capability(mod_evsub.endpt, &mod_evsub.mod,
459 			       PJSIP_H_ACCEPT, NULL,
460 			       pkg->pkg_accept->count,
461 			       pkg->pkg_accept->values);
462 
463 
464     /* Done */
465 
466     PJ_LOG(5,(THIS_FILE, "Event pkg \"%.*s\" registered by %.*s",
467 	      (int)event_name->slen, event_name->ptr,
468 	      (int)pkg_mod->name.slen, pkg_mod->name.ptr));
469 
470     return PJ_SUCCESS;
471 }
472 
473 
474 /*
475  * Retrieve Allow-Events header
476  */
pjsip_evsub_get_allow_events_hdr(pjsip_module * m)477 PJ_DEF(const pjsip_hdr*) pjsip_evsub_get_allow_events_hdr(pjsip_module *m)
478 {
479     struct mod_evsub *mod;
480 
481     if (m == NULL)
482 	m = pjsip_evsub_instance();
483 
484     mod = (struct mod_evsub*)m;
485 
486     return (pjsip_hdr*) mod->allow_events_hdr;
487 }
488 
489 
490 /*
491  * Update expiration time.
492  */
update_expires(pjsip_evsub * sub,pj_uint32_t interval)493 static void update_expires( pjsip_evsub *sub, pj_uint32_t interval )
494 {
495     pj_gettimeofday(&sub->refresh_time);
496     sub->refresh_time.sec += interval;
497 }
498 
499 
500 /*
501  * Schedule timer.
502  */
set_timer(pjsip_evsub * sub,int timer_id,pj_uint32_t seconds)503 static void set_timer( pjsip_evsub *sub, int timer_id,
504 		       pj_uint32_t seconds)
505 {
506     if (sub->timer.id != TIMER_TYPE_NONE) {
507 	PJ_LOG(5,(sub->obj_name, "%s %s timer",
508 		  (timer_id==sub->timer.id ? "Updating" : "Cancelling"),
509 		  timer_names[sub->timer.id]));
510 	pjsip_endpt_cancel_timer(sub->endpt, &sub->timer);
511 	sub->timer.id = TIMER_TYPE_NONE;
512     }
513 
514     if (timer_id != TIMER_TYPE_NONE && seconds != PJSIP_EXPIRES_NOT_SPECIFIED)
515     {
516 	pj_time_val timeout;
517 
518 	PJ_ASSERT_ON_FAIL(timer_id>TIMER_TYPE_NONE && timer_id<TIMER_TYPE_MAX,
519 			  return);
520 
521 	timeout.sec = seconds;
522 	timeout.msec = 0;
523 
524 	pj_timer_heap_schedule_w_grp_lock(
525 			    pjsip_endpt_get_timer_heap(sub->endpt),
526 			    &sub->timer, &timeout, timer_id, sub->grp_lock);
527 
528 	PJ_LOG(5,(sub->obj_name, "Timer %s scheduled in %d seconds",
529 		  timer_names[sub->timer.id], timeout.sec));
530     }
531 }
532 
533 
534 /*
535  * Set event subscription UAS timout.
536  */
pjsip_evsub_uas_set_timeout(pjsip_evsub * sub,pj_uint32_t seconds)537 PJ_DEF(void) pjsip_evsub_uas_set_timeout(pjsip_evsub *sub, pj_uint32_t seconds)
538 {
539     set_timer(sub, TIMER_TYPE_UAS_TIMEOUT, (pj_int32_t)seconds);
540 }
541 
542 
543 /*
544  * Destructor.
545  */
evsub_on_destroy(void * obj)546 static void evsub_on_destroy(void *obj)
547 {
548     pjsip_evsub *sub = (pjsip_evsub*)obj;
549 
550     /* Decrement dialog's session */
551     pjsip_dlg_dec_session(sub->dlg, &mod_evsub.mod);
552 }
553 
554 
555 /*
556  * Destroy session.
557  */
evsub_destroy(pjsip_evsub * sub)558 static void evsub_destroy( pjsip_evsub *sub )
559 {
560     struct dlgsub *dlgsub_head, *dlgsub;
561 
562     PJ_LOG(4,(sub->obj_name, "Subscription destroyed"));
563 
564     /* Kill timer */
565     set_timer(sub, TIMER_TYPE_NONE, 0);
566 
567     /* Kill timer for stopping pending sub (see ticket #1807) */
568     if (sub->pending_sub_timer && sub->pending_sub_timer->id == 1) {
569 	pjsip_endpt_cancel_timer(sub->endpt, sub->pending_sub_timer);
570 	sub->pending_sub_timer->id = 0;
571 	sub->pending_sub_timer = NULL;
572     }
573 
574     /* Remove this session from dialog's list of subscription */
575     dlgsub_head = (struct dlgsub *) sub->dlg->mod_data[mod_evsub.mod.id];
576     dlgsub = dlgsub_head->next;
577     while (dlgsub != dlgsub_head) {
578 
579 	if (dlgsub->sub == sub) {
580 	    pj_list_erase(dlgsub);
581 	    break;
582 	}
583 
584 	dlgsub = dlgsub->next;
585     }
586 
587     pj_grp_lock_dec_ref(sub->grp_lock);
588 }
589 
590 /*
591  * Set subscription session state.
592  */
set_state(pjsip_evsub * sub,pjsip_evsub_state state,const pj_str_t * state_str,pjsip_event * event,const pj_str_t * reason)593 static void set_state( pjsip_evsub *sub, pjsip_evsub_state state,
594 		       const pj_str_t *state_str, pjsip_event *event,
595 		       const pj_str_t *reason)
596 {
597     pjsip_evsub_state prev_state = sub->state;
598     pj_str_t old_state_str = sub->state_str;
599     pjsip_event dummy_event;
600 
601     sub->state = state;
602 
603     if (state_str && state_str->slen)
604 	pj_strdup_with_null(sub->pool, &sub->state_str, state_str);
605     else
606 	sub->state_str = evsub_state_names[state];
607 
608     if (reason && sub->term_reason.slen==0)
609 	pj_strdup(sub->pool, &sub->term_reason, reason);
610 
611     PJ_LOG(4,(sub->obj_name,
612 	      "Subscription state changed %.*s --> %.*s",
613 	      (int)old_state_str.slen,
614 	      old_state_str.ptr,
615 	      (int)sub->state_str.slen,
616 	      sub->state_str.ptr));
617     pj_log_push_indent();
618 
619     /* don't call the callback with NULL event, it may crash the app! */
620     if (!event) {
621 	PJSIP_EVENT_INIT_USER(dummy_event, 0, 0, 0, 0);
622 	event = &dummy_event;
623     }
624 
625     if (sub->user.on_evsub_state && sub->call_cb)
626 	(*sub->user.on_evsub_state)(sub, event);
627 
628     if (state == PJSIP_EVSUB_STATE_TERMINATED &&
629 	prev_state != PJSIP_EVSUB_STATE_TERMINATED)
630     {
631 	/* Kill any timer. */
632 	set_timer(sub, TIMER_TYPE_NONE, 0);
633 
634 	if (sub->pending_tsx == 0) {
635 	    evsub_destroy(sub);
636 	}
637     }
638 
639     pj_log_pop_indent();
640 }
641 
642 
643 /*
644  * Timer callback.
645  */
on_timer(pj_timer_heap_t * timer_heap,struct pj_timer_entry * entry)646 static void on_timer( pj_timer_heap_t *timer_heap,
647 		      struct pj_timer_entry *entry)
648 {
649     pjsip_evsub *sub;
650     int timer_id;
651 
652     PJ_UNUSED_ARG(timer_heap);
653 
654     sub = (pjsip_evsub*) entry->user_data;
655 
656     pjsip_dlg_inc_lock(sub->dlg);
657 
658     /* If this timer entry has just been rescheduled or cancelled
659      * while waiting for dialog mutex, just return (see #1885 scenario 1).
660      */
661     if (pj_timer_entry_running(entry) || entry->id == TIMER_TYPE_NONE) {
662 	pjsip_dlg_dec_lock(sub->dlg);
663 	return;
664     }
665 
666     timer_id = entry->id;
667     entry->id = TIMER_TYPE_NONE;
668 
669     switch (timer_id) {
670 
671     case TIMER_TYPE_UAC_REFRESH:
672 	/* Time for UAC to refresh subscription */
673 	if (sub->user.on_client_refresh && sub->call_cb) {
674 	    (*sub->user.on_client_refresh)(sub);
675 	} else {
676 	    pjsip_tx_data *tdata;
677 	    pj_status_t status;
678 
679 	    PJ_LOG(5,(sub->obj_name, "Refreshing subscription."));
680 	    pj_log_push_indent();
681 	    status = pjsip_evsub_initiate(sub, NULL,
682 					  sub->expires->ivalue,
683 					  &tdata);
684 	    if (status == PJ_SUCCESS)
685 		pjsip_evsub_send_request(sub, tdata);
686 
687 	    pj_log_pop_indent();
688 	}
689 	break;
690 
691     case TIMER_TYPE_UAS_TIMEOUT:
692 	/* Refresh from UAC has not been received */
693 	if (sub->user.on_server_timeout && sub->call_cb) {
694 	    (*sub->user.on_server_timeout)(sub);
695 	} else {
696 	    pjsip_tx_data *tdata;
697 	    pj_status_t status;
698 
699 	    PJ_LOG(5,(sub->obj_name, "Timeout waiting for refresh. "
700 				     "Sending NOTIFY to terminate."));
701 	    pj_log_push_indent();
702 	    status = pjsip_evsub_notify( sub, PJSIP_EVSUB_STATE_TERMINATED,
703 					 NULL, &STR_TIMEOUT, &tdata);
704 	    if (status == PJ_SUCCESS)
705 		pjsip_evsub_send_request(sub, tdata);
706 
707 	    pj_log_pop_indent();
708 	}
709 	break;
710 
711     case TIMER_TYPE_UAC_TERMINATE:
712 	{
713 	    pj_str_t timeout = {"timeout", 7};
714 
715 	    PJ_LOG(5,(sub->obj_name, "Timeout waiting for final NOTIFY. "
716 				     "Terminating.."));
717 	    pj_log_push_indent();
718 	    set_state(sub, PJSIP_EVSUB_STATE_TERMINATED, NULL, NULL,
719 		      &timeout);
720 	    pj_log_pop_indent();
721 	}
722 	break;
723 
724     case TIMER_TYPE_UAC_WAIT_NOTIFY:
725 	{
726 	    pjsip_tx_data *tdata;
727 	    pj_status_t status;
728 
729 	    PJ_LOG(5,(sub->obj_name,
730 		     "Timeout waiting for subsequent NOTIFY (we did "
731 		     "send non-2xx response for previous NOTIFY). "
732 		     "Unsubscribing.."));
733 	    pj_log_push_indent();
734 	    status = pjsip_evsub_initiate( sub, NULL, 0, &tdata);
735 	    if (status == PJ_SUCCESS)
736 		pjsip_evsub_send_request(sub, tdata);
737 
738 	    pj_log_pop_indent();
739 	}
740 	break;
741 
742     default:
743 	pj_assert(!"Invalid timer id");
744     }
745 
746     pjsip_dlg_dec_lock(sub->dlg);
747 }
748 
749 
750 /*
751  * Create subscription session, used for both client and notifier.
752  */
evsub_create(pjsip_dialog * dlg,pjsip_role_e role,const pjsip_evsub_user * user_cb,const pj_str_t * event,unsigned option,pjsip_evsub ** p_evsub)753 static pj_status_t evsub_create( pjsip_dialog *dlg,
754 				 pjsip_role_e role,
755 				 const pjsip_evsub_user *user_cb,
756 				 const pj_str_t *event,
757 				 unsigned option,
758 				 pjsip_evsub **p_evsub )
759 {
760     pjsip_evsub *sub;
761     struct evpkg *pkg;
762     struct dlgsub *dlgsub_head, *dlgsub;
763     pj_status_t status;
764 
765     /* Make sure there's package register for the event name: */
766 
767     pkg = find_pkg(event);
768     if (pkg == NULL)
769 	return PJSIP_SIMPLE_ENOPKG;
770 
771 
772     /* Must lock dialog before using pool etc. */
773     pjsip_dlg_inc_lock(dlg);
774 
775     /* Init attributes: */
776 
777     sub = PJ_POOL_ZALLOC_T(dlg->pool, struct pjsip_evsub);
778     sub->pool = dlg->pool;
779     sub->endpt = dlg->endpt;
780     sub->dlg = dlg;
781     sub->pkg = pkg;
782     sub->role = role;
783     sub->call_cb = PJ_TRUE;
784     sub->option = option;
785     sub->state = PJSIP_EVSUB_STATE_NULL;
786     sub->state_str = evsub_state_names[sub->state];
787     sub->expires = pjsip_expires_hdr_create(sub->pool, pkg->pkg_expires);
788     sub->accept = (pjsip_accept_hdr*)
789     		  pjsip_hdr_clone(sub->pool, pkg->pkg_accept);
790     pj_list_init(&sub->sub_hdr_list);
791 
792     sub->timer.user_data = sub;
793     sub->timer.cb = &on_timer;
794 
795     /* Set name. */
796     pj_ansi_snprintf(sub->obj_name, PJ_ARRAY_SIZE(sub->obj_name),
797 		     "evsub%p", sub);
798 
799 
800     /* Copy callback, if any: */
801     if (user_cb)
802 	pj_memcpy(&sub->user, user_cb, sizeof(pjsip_evsub_user));
803 
804 
805     /* Create Event header: */
806     sub->event = pjsip_event_hdr_create(sub->pool);
807     pj_strdup(sub->pool, &sub->event->event_type, event);
808 
809 
810     /* Check if another subscription has been registered to the dialog. In
811      * that case, just add ourselves to the subscription list, otherwise
812      * create and register a new subscription list.
813      */
814     if (pjsip_dlg_has_usage(dlg, &mod_evsub.mod)) {
815 	dlgsub_head = (struct dlgsub*) dlg->mod_data[mod_evsub.mod.id];
816 	dlgsub = PJ_POOL_ALLOC_T(sub->pool, struct dlgsub);
817 	dlgsub->sub = sub;
818 	pj_list_push_back(dlgsub_head, dlgsub);
819     } else {
820 	dlgsub_head = PJ_POOL_ALLOC_T(sub->pool, struct dlgsub);
821 	dlgsub = PJ_POOL_ALLOC_T(sub->pool, struct dlgsub);
822 	dlgsub->sub = sub;
823 
824 	pj_list_init(dlgsub_head);
825 	pj_list_push_back(dlgsub_head, dlgsub);
826 
827 
828 	/* Register as dialog usage: */
829 
830 	status = pjsip_dlg_add_usage(dlg, &mod_evsub.mod, dlgsub_head);
831 	if (status != PJ_SUCCESS) {
832 	    pjsip_dlg_dec_lock(dlg);
833 	    return status;
834 	}
835     }
836 
837     PJ_LOG(5,(sub->obj_name, "%s subscription created, using dialog %s",
838 	      (role==PJSIP_ROLE_UAC ? "UAC" : "UAS"),
839 	      dlg->obj_name));
840 
841     *p_evsub = sub;
842     pjsip_dlg_dec_lock(dlg);
843 
844     return PJ_SUCCESS;
845 }
846 
847 /*
848  * Increment the event subscription's group lock.
849  */
pjsip_evsub_add_ref(pjsip_evsub * sub)850 PJ_DEF(pj_status_t) pjsip_evsub_add_ref(pjsip_evsub *sub)
851 {
852     return pj_grp_lock_add_ref(sub->grp_lock);
853 }
854 
855 /*
856  * Decrement the event subscription's group lock.
857  */
pjsip_evsub_dec_ref(pjsip_evsub * sub)858 PJ_DEF(pj_status_t) pjsip_evsub_dec_ref(pjsip_evsub *sub)
859 {
860     return pj_grp_lock_dec_ref(sub->grp_lock);
861 }
862 
863 /*
864  * Create client subscription session.
865  */
pjsip_evsub_create_uac(pjsip_dialog * dlg,const pjsip_evsub_user * user_cb,const pj_str_t * event,unsigned option,pjsip_evsub ** p_evsub)866 PJ_DEF(pj_status_t) pjsip_evsub_create_uac( pjsip_dialog *dlg,
867 					    const pjsip_evsub_user *user_cb,
868 					    const pj_str_t *event,
869 					    unsigned option,
870 					    pjsip_evsub **p_evsub)
871 {
872     pjsip_evsub *sub;
873     pj_status_t status;
874 
875     PJ_ASSERT_RETURN(dlg && event && p_evsub, PJ_EINVAL);
876 
877     pjsip_dlg_inc_lock(dlg);
878     status = evsub_create(dlg, PJSIP_UAC_ROLE, user_cb, event, option, &sub);
879     if (status != PJ_SUCCESS)
880 	goto on_return;
881 
882     /* Add unique Id to Event header, only when PJSIP_EVSUB_NO_EVENT_ID
883      * is not specified.
884      */
885     if ((option & PJSIP_EVSUB_NO_EVENT_ID) == 0) {
886 	pj_create_unique_string(sub->pool, &sub->event->id_param);
887     }
888 
889     /* Increment dlg session. */
890     pjsip_dlg_inc_session(sub->dlg, &mod_evsub.mod);
891 
892     /* Init group lock */
893     status = pj_grp_lock_create(dlg->pool, NULL, &sub->grp_lock);
894     if (status != PJ_SUCCESS) {
895 	pjsip_dlg_dec_session(sub->dlg, &mod_evsub.mod);
896 	goto on_return;
897     }
898 
899     pj_grp_lock_add_ref(sub->grp_lock);
900     pj_grp_lock_add_handler(sub->grp_lock, dlg->pool, sub, &evsub_on_destroy);
901 
902     /* Done */
903     *p_evsub = sub;
904 
905 on_return:
906     pjsip_dlg_dec_lock(dlg);
907     return status;
908 }
909 
910 
911 /*
912  * Create server subscription session from incoming request.
913  */
pjsip_evsub_create_uas(pjsip_dialog * dlg,const pjsip_evsub_user * user_cb,pjsip_rx_data * rdata,unsigned option,pjsip_evsub ** p_evsub)914 PJ_DEF(pj_status_t) pjsip_evsub_create_uas( pjsip_dialog *dlg,
915 					    const pjsip_evsub_user *user_cb,
916 					    pjsip_rx_data *rdata,
917 					    unsigned option,
918 					    pjsip_evsub **p_evsub)
919 {
920     pjsip_evsub *sub;
921     pjsip_transaction *tsx;
922     pjsip_accept_hdr *accept_hdr;
923     pjsip_event_hdr *event_hdr;
924     pjsip_expires_hdr *expires_hdr;
925     pj_status_t status;
926 
927     /* Check arguments: */
928     PJ_ASSERT_RETURN(dlg && rdata && p_evsub, PJ_EINVAL);
929 
930     /* MUST be request message: */
931     PJ_ASSERT_RETURN(rdata->msg_info.msg->type == PJSIP_REQUEST_MSG,
932 		     PJSIP_ENOTREQUESTMSG);
933 
934     /* Transaction MUST have been created (in the dialog) */
935     tsx = pjsip_rdata_get_tsx(rdata);
936     PJ_ASSERT_RETURN(tsx != NULL, PJSIP_ENOTSX);
937 
938     /* No subscription must have been attached to transaction */
939     PJ_ASSERT_RETURN(tsx->mod_data[mod_evsub.mod.id] == NULL,
940 		     PJSIP_ETYPEEXISTS);
941 
942     /* Package MUST implement on_rx_refresh */
943     PJ_ASSERT_RETURN(user_cb->on_rx_refresh, PJ_EINVALIDOP);
944 
945     /* Request MUST have "Event" header. We need the Event header to get
946      * the package name (don't want to add more arguments in the function).
947      */
948     event_hdr = (pjsip_event_hdr*)
949 		 pjsip_msg_find_hdr_by_names(rdata->msg_info.msg, &STR_EVENT,
950 					     &STR_EVENT_S, NULL);
951     if (event_hdr == NULL) {
952 	return PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_BAD_REQUEST);
953     }
954 
955     /* Start locking the mutex: */
956 
957     pjsip_dlg_inc_lock(dlg);
958 
959     /* Create the session: */
960 
961     status = evsub_create(dlg, PJSIP_UAS_ROLE, user_cb,
962 			  &event_hdr->event_type, option, &sub);
963     if (status != PJ_SUCCESS)
964 	goto on_return;
965 
966     /* Just duplicate Event header from the request */
967     sub->event = (pjsip_event_hdr*) pjsip_hdr_clone(sub->pool, event_hdr);
968 
969     /* Set the method: */
970     pjsip_method_copy(sub->pool, &sub->method,
971 		      &rdata->msg_info.msg->line.req.method);
972 
973     /* Update expiration time according to client request: */
974 
975     expires_hdr = (pjsip_expires_hdr*)
976 	pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_EXPIRES, NULL);
977     if (expires_hdr) {
978 	sub->expires->ivalue = expires_hdr->ivalue;
979     }
980 
981     /* Update time. */
982     update_expires(sub, sub->expires->ivalue);
983 
984     /* Update Accept header: */
985 
986     accept_hdr = (pjsip_accept_hdr*)
987 	pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_ACCEPT, NULL);
988     if (accept_hdr)
989 	sub->accept = (pjsip_accept_hdr*)pjsip_hdr_clone(sub->pool,accept_hdr);
990 
991     /* Increment dlg session. */
992     pjsip_dlg_inc_session(dlg, &mod_evsub.mod);
993 
994     /* Init group lock */
995     status = pj_grp_lock_create(dlg->pool, NULL, &sub->grp_lock);
996     if (status != PJ_SUCCESS) {
997 	pjsip_dlg_dec_session(sub->dlg, &mod_evsub.mod);
998 	goto on_return;
999     }
1000 
1001     pj_grp_lock_add_ref(sub->grp_lock);
1002     pj_grp_lock_add_handler(sub->grp_lock, dlg->pool, sub, &evsub_on_destroy);
1003 
1004     /* We can start the session: */
1005 
1006     sub->pending_tsx++;
1007     tsx->mod_data[mod_evsub.mod.id] = sub;
1008 
1009     /* Done. */
1010     *p_evsub = sub;
1011 
1012 
1013 on_return:
1014     pjsip_dlg_dec_lock(dlg);
1015     return status;
1016 }
1017 
1018 
1019 /*
1020  * Forcefully destroy subscription.
1021  */
pjsip_evsub_terminate(pjsip_evsub * sub,pj_bool_t notify)1022 PJ_DEF(pj_status_t) pjsip_evsub_terminate( pjsip_evsub *sub,
1023 					   pj_bool_t notify )
1024 {
1025     PJ_ASSERT_RETURN(sub, PJ_EINVAL);
1026 
1027     pjsip_dlg_inc_lock(sub->dlg);
1028 
1029     /* I think it's pretty safe to disable this check.
1030 
1031     if (sub->pending_tsx) {
1032 	pj_assert(!"Unable to terminate when there's pending tsx");
1033 	pjsip_dlg_dec_lock(sub->dlg);
1034 	return PJ_EINVALIDOP;
1035     }
1036     */
1037 
1038     sub->call_cb = notify;
1039     set_state(sub, PJSIP_EVSUB_STATE_TERMINATED, NULL, NULL, NULL);
1040 
1041     pjsip_dlg_dec_lock(sub->dlg);
1042     return PJ_SUCCESS;
1043 }
1044 
1045 /*
1046  * Get subscription state.
1047  */
pjsip_evsub_get_state(pjsip_evsub * sub)1048 PJ_DEF(pjsip_evsub_state) pjsip_evsub_get_state(pjsip_evsub *sub)
1049 {
1050     return sub->state;
1051 }
1052 
1053 /*
1054  * Get state name.
1055  */
pjsip_evsub_get_state_name(pjsip_evsub * sub)1056 PJ_DEF(const char*) pjsip_evsub_get_state_name(pjsip_evsub *sub)
1057 {
1058     return sub->state_str.ptr;
1059 }
1060 
1061 /*
1062  * Get termination reason.
1063  */
pjsip_evsub_get_termination_reason(pjsip_evsub * sub)1064 PJ_DEF(const pj_str_t*) pjsip_evsub_get_termination_reason(pjsip_evsub *sub)
1065 {
1066     return &sub->term_reason;
1067 }
1068 
1069 /*
1070  * Initiate client subscription
1071  */
pjsip_evsub_initiate(pjsip_evsub * sub,const pjsip_method * method,pj_uint32_t expires,pjsip_tx_data ** p_tdata)1072 PJ_DEF(pj_status_t) pjsip_evsub_initiate( pjsip_evsub *sub,
1073 					  const pjsip_method *method,
1074 					  pj_uint32_t expires,
1075 					  pjsip_tx_data **p_tdata)
1076 {
1077     pjsip_tx_data *tdata;
1078     pj_status_t status;
1079 
1080     PJ_ASSERT_RETURN(sub!=NULL && p_tdata!=NULL, PJ_EINVAL);
1081 
1082     /* Use SUBSCRIBE if method is not specified */
1083     if (method == NULL)
1084 	method = &pjsip_subscribe_method;
1085 
1086     pjsip_dlg_inc_lock(sub->dlg);
1087 
1088     /* Update method: */
1089     if (sub->state == PJSIP_EVSUB_STATE_NULL)
1090 	pjsip_method_copy(sub->pool, &sub->method, method);
1091 
1092     status = pjsip_dlg_create_request( sub->dlg, method, -1, &tdata);
1093     if (status != PJ_SUCCESS)
1094 	goto on_return;
1095 
1096 
1097     /* Add Event header: */
1098     pjsip_msg_add_hdr( tdata->msg, (pjsip_hdr*)
1099 		       pjsip_hdr_shallow_clone(tdata->pool, sub->event));
1100 
1101     /* Update and add expires header: */
1102     if (expires != PJSIP_EXPIRES_NOT_SPECIFIED)
1103 	sub->expires->ivalue = expires;
1104     pjsip_msg_add_hdr( tdata->msg, (pjsip_hdr*)
1105 		       pjsip_hdr_shallow_clone(tdata->pool, sub->expires));
1106 
1107     /* Add Supported header (it's optional in RFC 3265, but some event package
1108      * RFC may bring this requirement to SHOULD strength - e.g. RFC 5373)
1109      */
1110     {
1111        const pjsip_hdr *hdr = pjsip_endpt_get_capability(sub->endpt,
1112 						         PJSIP_H_SUPPORTED,
1113 						         NULL);
1114        if (hdr) {
1115 	   pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)
1116 			     pjsip_hdr_shallow_clone(tdata->pool, hdr));
1117        }
1118     }
1119 
1120     /* Add Accept header: */
1121     pjsip_msg_add_hdr( tdata->msg, (pjsip_hdr*)
1122 		       pjsip_hdr_shallow_clone(tdata->pool, sub->accept));
1123 
1124 
1125     /* Add Allow-Events header: */
1126     pjsip_msg_add_hdr( tdata->msg, (pjsip_hdr*)
1127 		       pjsip_hdr_shallow_clone(tdata->pool,
1128 					       mod_evsub.allow_events_hdr));
1129 
1130 
1131     /* Add custom headers */
1132     {
1133 	const pjsip_hdr *hdr = sub->sub_hdr_list.next;
1134 	while (hdr != &sub->sub_hdr_list) {
1135 	    pjsip_msg_add_hdr( tdata->msg, (pjsip_hdr*)
1136 			       pjsip_hdr_shallow_clone(tdata->pool, hdr));
1137 	    hdr = hdr->next;
1138 	}
1139     }
1140 
1141 
1142     *p_tdata = tdata;
1143 
1144 
1145 on_return:
1146 
1147     pjsip_dlg_dec_lock(sub->dlg);
1148     return status;
1149 }
1150 
1151 
1152 /*
1153  * Add custom headers.
1154  */
pjsip_evsub_add_header(pjsip_evsub * sub,const pjsip_hdr * hdr_list)1155 PJ_DEF(pj_status_t) pjsip_evsub_add_header( pjsip_evsub *sub,
1156 					    const pjsip_hdr *hdr_list )
1157 {
1158     const pjsip_hdr *hdr;
1159 
1160     PJ_ASSERT_RETURN(sub && hdr_list, PJ_EINVAL);
1161 
1162     hdr = hdr_list->next;
1163     while (hdr != hdr_list) {
1164         pj_list_push_back(&sub->sub_hdr_list, (pjsip_hdr*)
1165 		          pjsip_hdr_clone(sub->pool, hdr));
1166 	hdr = hdr->next;
1167     }
1168 
1169     return PJ_SUCCESS;
1170 }
1171 
1172 
1173 /*
1174  * Accept incoming subscription request.
1175  */
pjsip_evsub_accept(pjsip_evsub * sub,pjsip_rx_data * rdata,int st_code,const pjsip_hdr * hdr_list)1176 PJ_DEF(pj_status_t) pjsip_evsub_accept( pjsip_evsub *sub,
1177 					pjsip_rx_data *rdata,
1178 				        int st_code,
1179 					const pjsip_hdr *hdr_list )
1180 {
1181     pjsip_tx_data *tdata;
1182     pjsip_transaction *tsx;
1183     pj_status_t status;
1184 
1185     /* Check arguments */
1186     PJ_ASSERT_RETURN(sub && rdata, PJ_EINVAL);
1187 
1188     /* Can only be for server subscription: */
1189     PJ_ASSERT_RETURN(sub->role == PJSIP_ROLE_UAS, PJ_EINVALIDOP);
1190 
1191     /* Only expect 2xx status code (for now) */
1192     PJ_ASSERT_RETURN(st_code/100 == 2, PJ_EINVALIDOP);
1193 
1194     /* Subscription MUST have been attached to the transaction.
1195      * Initial subscription request will be attached on evsub_create_uas(),
1196      * while subsequent requests will be attached in tsx_state()
1197      */
1198     tsx = pjsip_rdata_get_tsx(rdata);
1199     PJ_ASSERT_RETURN(tsx->mod_data[mod_evsub.mod.id] != NULL,
1200 		     PJ_EINVALIDOP);
1201 
1202     /* Lock dialog */
1203     pjsip_dlg_inc_lock(sub->dlg);
1204 
1205     /* Create response: */
1206     status = pjsip_dlg_create_response( sub->dlg, rdata, st_code, NULL,
1207 					&tdata);
1208     if (status != PJ_SUCCESS)
1209 	goto on_return;
1210 
1211 
1212     /* Add expires header: */
1213     pjsip_msg_add_hdr( tdata->msg, (pjsip_hdr*)
1214 		       pjsip_hdr_shallow_clone(tdata->pool, sub->expires));
1215 
1216     /* Add additional header, if any. */
1217     if (hdr_list) {
1218 	const pjsip_hdr *hdr = hdr_list->next;
1219 	while (hdr != hdr_list) {
1220 	    pjsip_msg_add_hdr( tdata->msg, (pjsip_hdr*)
1221 			       pjsip_hdr_clone(tdata->pool, hdr));
1222 	    hdr = hdr->next;
1223 	}
1224     }
1225 
1226     /* Send the response: */
1227     status = pjsip_dlg_send_response( sub->dlg, tsx, tdata );
1228     if (status != PJ_SUCCESS)
1229 	goto on_return;
1230 
1231     /* Set UAS timeout timer, when status code is 2xx and state is not
1232      * terminated.
1233      */
1234     if (st_code/100 == 2 && sub->state != PJSIP_EVSUB_STATE_TERMINATED) {
1235 	PJ_LOG(5,(sub->obj_name, "UAS timeout in %d seconds",
1236 		  sub->expires->ivalue));
1237 	set_timer(sub, TIMER_TYPE_UAS_TIMEOUT, sub->expires->ivalue);
1238     }
1239 
1240 on_return:
1241 
1242     pjsip_dlg_dec_lock(sub->dlg);
1243     return status;
1244 }
1245 
1246 
1247 /*
1248  * Create Subscription-State header based on current server subscription
1249  * state.
1250  */
sub_state_create(pj_pool_t * pool,pjsip_evsub * sub,pjsip_evsub_state state,const pj_str_t * state_str,const pj_str_t * reason)1251 static pjsip_sub_state_hdr* sub_state_create( pj_pool_t *pool,
1252 					      pjsip_evsub *sub,
1253 					      pjsip_evsub_state state,
1254 					      const pj_str_t *state_str,
1255 					      const pj_str_t *reason )
1256 {
1257     pjsip_sub_state_hdr *sub_state;
1258     pj_time_val now, delay;
1259 
1260     /* Get the remaining time before refresh is required */
1261     pj_gettimeofday(&now);
1262     delay = sub->refresh_time;
1263     PJ_TIME_VAL_SUB(delay, now);
1264 
1265     /* Create the Subscription-State header */
1266     sub_state = pjsip_sub_state_hdr_create(pool);
1267 
1268     /* Fill up the header */
1269     switch (state) {
1270     case PJSIP_EVSUB_STATE_NULL:
1271     case PJSIP_EVSUB_STATE_SENT:
1272 	pj_assert(!"Invalid state!");
1273 	/* Treat as pending */
1274 
1275     case PJSIP_EVSUB_STATE_ACCEPTED:
1276     case PJSIP_EVSUB_STATE_PENDING:
1277 	sub_state->sub_state = STR_PENDING;
1278 	sub_state->expires_param = delay.sec;
1279 	break;
1280 
1281     case PJSIP_EVSUB_STATE_ACTIVE:
1282 	sub_state->sub_state = STR_ACTIVE;
1283 	sub_state->expires_param = delay.sec;
1284 	break;
1285 
1286     case PJSIP_EVSUB_STATE_TERMINATED:
1287 	sub_state->sub_state = STR_TERMINATED;
1288 	if (reason != NULL)
1289 	    pj_strdup(pool, &sub_state->reason_param, reason);
1290 	break;
1291 
1292     case PJSIP_EVSUB_STATE_UNKNOWN:
1293 	pj_assert(state_str != NULL);
1294 	pj_strdup(pool, &sub_state->sub_state, state_str);
1295 	break;
1296     }
1297 
1298     return sub_state;
1299 }
1300 
1301 /*
1302  * Create and send NOTIFY request.
1303  */
pjsip_evsub_notify(pjsip_evsub * sub,pjsip_evsub_state state,const pj_str_t * state_str,const pj_str_t * reason,pjsip_tx_data ** p_tdata)1304 PJ_DEF(pj_status_t) pjsip_evsub_notify( pjsip_evsub *sub,
1305 					pjsip_evsub_state state,
1306 					const pj_str_t *state_str,
1307 					const pj_str_t *reason,
1308 					pjsip_tx_data **p_tdata)
1309 {
1310     pjsip_tx_data *tdata;
1311     pjsip_sub_state_hdr *sub_state;
1312     pj_status_t status;
1313 
1314     /* Check arguments. */
1315     PJ_ASSERT_RETURN(sub!=NULL && p_tdata!=NULL, PJ_EINVAL);
1316 
1317     /* Lock dialog. */
1318     pjsip_dlg_inc_lock(sub->dlg);
1319 
1320     /* Create NOTIFY request */
1321     status = pjsip_dlg_create_request( sub->dlg, pjsip_get_notify_method(),
1322 				       -1, &tdata);
1323     if (status != PJ_SUCCESS)
1324 	goto on_return;
1325 
1326     /* Add Event header */
1327     pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)
1328 		      pjsip_hdr_shallow_clone(tdata->pool, sub->event));
1329 
1330     /* Add Subscription-State header */
1331     sub_state = sub_state_create(tdata->pool, sub, state, state_str,
1332 				 reason);
1333     pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)sub_state);
1334 
1335     /* Add Allow-Events header */
1336     pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)
1337 		      pjsip_hdr_shallow_clone(tdata->pool, mod_evsub.allow_events_hdr));
1338 
1339     /* Add Authentication headers. */
1340     pjsip_auth_clt_init_req( &sub->dlg->auth_sess, tdata );
1341 
1342     /* Update reason */
1343     if (reason)
1344 	pj_strdup(sub->dlg->pool, &sub->term_reason, reason);
1345 
1346     /* Save destination state. */
1347     sub->dst_state = state;
1348     if (state_str)
1349 	pj_strdup(sub->pool, &sub->dst_state_str, state_str);
1350     else
1351 	sub->dst_state_str.slen = 0;
1352 
1353 
1354     *p_tdata = tdata;
1355 
1356 on_return:
1357     /* Unlock dialog */
1358     pjsip_dlg_dec_lock(sub->dlg);
1359     return status;
1360 }
1361 
1362 
1363 /*
1364  * Create NOTIFY to reflect current status.
1365  */
pjsip_evsub_current_notify(pjsip_evsub * sub,pjsip_tx_data ** p_tdata)1366 PJ_DEF(pj_status_t) pjsip_evsub_current_notify( pjsip_evsub *sub,
1367 						pjsip_tx_data **p_tdata )
1368 {
1369     return pjsip_evsub_notify( sub, sub->state, &sub->state_str,
1370 			       NULL, p_tdata );
1371 }
1372 
1373 
1374 /*
1375  * Send request.
1376  */
pjsip_evsub_send_request(pjsip_evsub * sub,pjsip_tx_data * tdata)1377 PJ_DEF(pj_status_t) pjsip_evsub_send_request( pjsip_evsub *sub,
1378 					      pjsip_tx_data *tdata)
1379 {
1380     pj_status_t status;
1381 
1382     /* Must be request message. */
1383     PJ_ASSERT_RETURN(tdata->msg->type == PJSIP_REQUEST_MSG,
1384 		     PJSIP_ENOTREQUESTMSG);
1385 
1386     /* Lock */
1387     pjsip_dlg_inc_lock(sub->dlg);
1388 
1389     /* Send the request. */
1390     status = pjsip_dlg_send_request(sub->dlg, tdata, -1, NULL);
1391     if (status != PJ_SUCCESS)
1392 	goto on_return;
1393 
1394 
1395     /* Special case for NOTIFY:
1396      * The new state was set in pjsip_evsub_notify(), but we apply the
1397      * new state now, when the request was actually sent.
1398      */
1399     if (pjsip_method_cmp(&tdata->msg->line.req.method,
1400 			 &pjsip_notify_method)==0)
1401     {
1402 	PJ_ASSERT_ON_FAIL(  sub->dst_state!=PJSIP_EVSUB_STATE_NULL,
1403 			    {goto on_return;});
1404 
1405 	set_state(sub, sub->dst_state,
1406 		  (sub->dst_state_str.slen ? &sub->dst_state_str : NULL),
1407 		  NULL, NULL);
1408 
1409 	sub->dst_state = PJSIP_EVSUB_STATE_NULL;
1410 	sub->dst_state_str.slen = 0;
1411 
1412     }
1413 
1414 
1415 on_return:
1416     pjsip_dlg_dec_lock(sub->dlg);
1417     return status;
1418 }
1419 
1420 
1421 /* Callback to be called to terminate transaction. */
terminate_timer_cb(pj_timer_heap_t * timer_heap,struct pj_timer_entry * entry)1422 static void terminate_timer_cb(pj_timer_heap_t *timer_heap,
1423 			       struct pj_timer_entry *entry)
1424 {
1425     pj_str_t *key;
1426     pjsip_transaction *tsx;
1427 
1428     PJ_UNUSED_ARG(timer_heap);
1429 
1430     /* Clear timer ID */
1431     entry->id = 0;
1432 
1433     key = (pj_str_t*)entry->user_data;
1434     tsx = pjsip_tsx_layer_find_tsx(key, PJ_FALSE);
1435     /* Chance of race condition here */
1436     if (tsx) {
1437 	pjsip_tsx_terminate(tsx, PJSIP_SC_REQUEST_UPDATED);
1438     }
1439 }
1440 
1441 
1442 /*
1443  * Attach subscription session to newly created transaction, if appropriate.
1444  */
on_new_transaction(pjsip_transaction * tsx,pjsip_event * event)1445 static pjsip_evsub *on_new_transaction( pjsip_transaction *tsx,
1446 				        pjsip_event *event)
1447 {
1448     /*
1449      * Newly created transaction will not have subscription session
1450      * attached to it. Find the subscription session from the dialog,
1451      * by matching the Event header.
1452      */
1453     pjsip_dialog *dlg;
1454     pjsip_event_hdr *event_hdr;
1455     pjsip_msg *msg;
1456     struct dlgsub *dlgsub_head, *dlgsub;
1457     pjsip_evsub *sub;
1458 
1459     dlg = pjsip_tsx_get_dlg(tsx);
1460     if (!dlg) {
1461 	pj_assert(!"Transaction should have a dialog instance!");
1462 	return NULL;
1463     }
1464 
1465 
1466     switch (event->body.tsx_state.type) {
1467     case PJSIP_EVENT_RX_MSG:
1468 	msg = event->body.tsx_state.src.rdata->msg_info.msg;
1469 	break;
1470     case PJSIP_EVENT_TX_MSG:
1471 	msg = event->body.tsx_state.src.tdata->msg;
1472 	break;
1473     default:
1474 	if (tsx->role == PJSIP_ROLE_UAC)
1475 	    msg = tsx->last_tx->msg;
1476 	else
1477 	    msg = NULL;
1478 	break;
1479     }
1480 
1481     if (!msg) {
1482 	//Note:
1483 	// this transaction can be other transaction in the dialog.
1484 	// The assertion below probably only valid for dialog that
1485 	// only has one event subscription usage.
1486 	//pj_assert(!"First transaction event is not TX or RX!");
1487 	return NULL;
1488     }
1489 
1490     event_hdr = (pjsip_event_hdr*)
1491     		pjsip_msg_find_hdr_by_names(msg, &STR_EVENT,
1492 					    &STR_EVENT_S, NULL);
1493     if (!event_hdr) {
1494 	/* Not subscription related message */
1495 	return NULL;
1496     }
1497 
1498     /* Find the subscription in the dialog, based on the content
1499      * of Event header:
1500      */
1501 
1502     dlgsub_head = (struct dlgsub*) dlg->mod_data[mod_evsub.mod.id];
1503     if (dlgsub_head == NULL) {
1504 	dlgsub_head = PJ_POOL_ALLOC_T(dlg->pool, struct dlgsub);
1505 	pj_list_init(dlgsub_head);
1506 	dlg->mod_data[mod_evsub.mod.id] = dlgsub_head;
1507     }
1508     dlgsub = dlgsub_head->next;
1509 
1510     while (dlgsub != dlgsub_head) {
1511 
1512 	if (pj_stricmp(&dlgsub->sub->event->event_type,
1513 		       &event_hdr->event_type)==0)
1514 	{
1515 	    /* Event type matched.
1516 	     * Check if event ID matched too.
1517 	     */
1518 	    if (pj_strcmp(&dlgsub->sub->event->id_param,
1519 			  &event_hdr->id_param)==0)
1520 	    {
1521 		/* Skip this subscription if it has no event ID and has been
1522 		 * terminated (see ticket #1647).
1523 		 */
1524 		if ((dlgsub->sub->option & PJSIP_EVSUB_NO_EVENT_ID) &&
1525 		    (pjsip_evsub_get_state(dlgsub->sub)==
1526 					PJSIP_EVSUB_STATE_TERMINATED))
1527 		{
1528 		    dlgsub = dlgsub->next;
1529     		    continue;
1530 		} else {
1531 		    break;
1532 		}
1533 
1534 	    }
1535 	    /*
1536 	     * Otherwise if it is an UAC subscription, AND
1537 	     * PJSIP_EVSUB_NO_EVENT_ID flag is set, AND
1538 	     * the session's event id is NULL, AND
1539 	     * the incoming request is NOTIFY with event ID, then
1540 	     * we consider it as a match, and update the
1541 	     * session's event id.
1542 	     */
1543 	    else if (dlgsub->sub->role == PJSIP_ROLE_UAC &&
1544 		     (dlgsub->sub->option & PJSIP_EVSUB_NO_EVENT_ID)!=0 &&
1545 		     dlgsub->sub->event->id_param.slen==0 &&
1546 		     !pjsip_method_cmp(&tsx->method, &pjsip_notify_method))
1547 	    {
1548 		/* Update session's event id. */
1549 		pj_strdup(dlgsub->sub->pool,
1550 			  &dlgsub->sub->event->id_param,
1551 			  &event_hdr->id_param);
1552 
1553 		break;
1554 	    }
1555 	}
1556 
1557 
1558 
1559 	dlgsub = dlgsub->next;
1560     }
1561 
1562     /* Note:
1563      *  the second condition is for http://trac.pjsip.org/repos/ticket/911
1564      */
1565     if (dlgsub == dlgsub_head ||
1566 	(dlgsub->sub &&
1567 	    pjsip_evsub_get_state(dlgsub->sub)==PJSIP_EVSUB_STATE_TERMINATED))
1568     {
1569 	const char *reason_msg =
1570 	    (dlgsub == dlgsub_head ? "Subscription Does Not Exist" :
1571 	     "Subscription already terminated");
1572 
1573 	/* This could be incoming request to create new subscription */
1574 	PJ_LOG(4,(THIS_FILE,
1575 		  "%s for %.*s, event=%.*s;id=%.*s",
1576 		  reason_msg,
1577 		  (int)tsx->method.name.slen,
1578 		  tsx->method.name.ptr,
1579 		  (int)event_hdr->event_type.slen,
1580 		  event_hdr->event_type.ptr,
1581 		  (int)event_hdr->id_param.slen,
1582 		  event_hdr->id_param.ptr));
1583 
1584 	/* If this is an incoming NOTIFY, reject with 481 */
1585 	if (tsx->state == PJSIP_TSX_STATE_TRYING &&
1586 	    pjsip_method_cmp(&tsx->method, &pjsip_notify_method)==0)
1587 	{
1588 	    pj_str_t reason;
1589 	    pjsip_tx_data *tdata;
1590 	    pj_status_t status;
1591 
1592 	    pj_cstr(&reason, reason_msg);
1593 	    status = pjsip_dlg_create_response(dlg,
1594 					       event->body.tsx_state.src.rdata,
1595 					       481, &reason,
1596 					       &tdata);
1597 	    if (status == PJ_SUCCESS) {
1598 		status = pjsip_dlg_send_response(dlg, tsx, tdata);
1599 	    }
1600 	}
1601 	return NULL;
1602     }
1603 
1604     /* Found! */
1605     sub = dlgsub->sub;
1606 
1607     /* Attach session to the transaction */
1608     tsx->mod_data[mod_evsub.mod.id] = sub;
1609     sub->pending_tsx++;
1610 
1611     /* Special case for outgoing/UAC SUBSCRIBE/REFER transaction.
1612      * We can only have one pending UAC SUBSCRIBE/REFER, so if another
1613      * transaction is started while previous one still alive, terminate
1614      * the older one.
1615      *
1616      * Sample scenario:
1617      *	- subscribe sent to destination that doesn't exist, transaction
1618      *	  is still retransmitting request, then unsubscribe is sent.
1619      */
1620     if (tsx->role == PJSIP_ROLE_UAC &&
1621 	tsx->state == PJSIP_TSX_STATE_CALLING &&
1622 	(pjsip_method_cmp(&tsx->method, &sub->method) == 0  ||
1623 	 pjsip_method_cmp(&tsx->method, &pjsip_subscribe_method) == 0))
1624     {
1625 
1626 	if (sub->pending_sub &&
1627 	    sub->pending_sub->state < PJSIP_TSX_STATE_COMPLETED)
1628 	{
1629 	    pj_timer_entry *timer;
1630 	    pj_str_t *key;
1631 	    pj_time_val timeout = {0, 0};
1632 
1633 	    PJ_LOG(4,(sub->obj_name,
1634 		      "Cancelling pending subscription request"));
1635 
1636 	    /* By convention, we use 490 (Request Updated) status code.
1637 	     * When transaction handler (below) see this status code, it
1638 	     * will ignore the transaction.
1639 	     */
1640 	    /* This unfortunately may cause deadlock, because at the moment
1641 	     * we are holding dialog's mutex. If a response to this
1642 	     * transaction is in progress in another thread, that thread
1643 	     * will deadlock when trying to acquire dialog mutex, because
1644 	     * it is holding the transaction mutex.
1645 	     *
1646 	     * So the solution is to register timer to kill this transaction.
1647 	     */
1648 	    //pjsip_tsx_terminate(sub->pending_sub, PJSIP_SC_REQUEST_UPDATED);
1649 	    timer = PJ_POOL_ZALLOC_T(dlg->pool, pj_timer_entry);
1650 	    key = PJ_POOL_ALLOC_T(dlg->pool, pj_str_t);
1651 	    pj_strdup(dlg->pool, key, &sub->pending_sub->transaction_key);
1652 	    timer->cb = &terminate_timer_cb;
1653 	    timer->user_data = key;
1654 	    timer->id = 1;
1655 	    sub->pending_sub_timer = timer;
1656 
1657 	    pjsip_endpt_schedule_timer(dlg->endpt, timer, &timeout);
1658 	}
1659 
1660 	sub->pending_sub = tsx;
1661 
1662     }
1663 
1664     return sub;
1665 }
1666 
1667 
1668 /*
1669  * Create response, adding custome headers and msg body.
1670  */
create_response(pjsip_evsub * sub,pjsip_rx_data * rdata,int st_code,const pj_str_t * st_text,const pjsip_hdr * res_hdr,const pjsip_msg_body * body,pjsip_tx_data ** p_tdata)1671 static pj_status_t create_response( pjsip_evsub *sub,
1672 				    pjsip_rx_data *rdata,
1673 				    int st_code,
1674 				    const pj_str_t *st_text,
1675 				    const pjsip_hdr *res_hdr,
1676 				    const pjsip_msg_body *body,
1677 				    pjsip_tx_data **p_tdata)
1678 {
1679     pjsip_tx_data *tdata;
1680     pjsip_hdr *hdr;
1681     pj_status_t status;
1682 
1683     status = pjsip_dlg_create_response(sub->dlg, rdata,
1684 				       st_code, st_text, &tdata);
1685     if (status != PJ_SUCCESS)
1686 	return status;
1687 
1688     *p_tdata = tdata;
1689 
1690     /* Add response headers. */
1691     hdr = res_hdr->next;
1692     while (hdr != res_hdr) {
1693 	pjsip_msg_add_hdr( tdata->msg, (pjsip_hdr*)
1694 			   pjsip_hdr_clone(tdata->pool, hdr));
1695 	hdr = hdr->next;
1696     }
1697 
1698     /* Add msg body, if any */
1699     if (body) {
1700 	tdata->msg->body = pjsip_msg_body_clone(tdata->pool, body);
1701 	if (tdata->msg->body == NULL) {
1702 
1703 	    PJ_LOG(4,(THIS_FILE, "Error: unable to clone msg body"));
1704 
1705 	    /* Ignore */
1706 	    return PJ_SUCCESS;
1707 	}
1708     }
1709 
1710     return PJ_SUCCESS;
1711 }
1712 
1713 /*
1714  * Get subscription state from the value of Subscription-State header.
1715  */
get_hdr_state(pjsip_sub_state_hdr * sub_state,pjsip_evsub_state * state,pj_str_t ** state_str)1716 static void get_hdr_state( pjsip_sub_state_hdr *sub_state,
1717 			   pjsip_evsub_state *state,
1718 			   pj_str_t **state_str )
1719 {
1720     if (pj_stricmp(&sub_state->sub_state, &STR_TERMINATED)==0) {
1721 
1722 	*state = PJSIP_EVSUB_STATE_TERMINATED;
1723 	*state_str = NULL;
1724 
1725     } else if (pj_stricmp(&sub_state->sub_state, &STR_ACTIVE)==0) {
1726 
1727 	*state = PJSIP_EVSUB_STATE_ACTIVE;
1728 	*state_str = NULL;
1729 
1730     } else if (pj_stricmp(&sub_state->sub_state, &STR_PENDING)==0) {
1731 
1732 	*state = PJSIP_EVSUB_STATE_PENDING;
1733 	*state_str = NULL;
1734 
1735     } else {
1736 
1737 	*state = PJSIP_EVSUB_STATE_UNKNOWN;
1738 	*state_str = &sub_state->sub_state;
1739 
1740     }
1741 }
1742 
1743 /*
1744  * Transaction event processing by UAC, after subscription is sent.
1745  */
on_tsx_state_uac(pjsip_evsub * sub,pjsip_transaction * tsx,pjsip_event * event)1746 static void on_tsx_state_uac( pjsip_evsub *sub, pjsip_transaction *tsx,
1747 			      pjsip_event *event )
1748 {
1749 
1750     if (pjsip_method_cmp(&tsx->method, &sub->method)==0 ||
1751 	pjsip_method_cmp(&tsx->method, &pjsip_subscribe_method)==0)
1752     {
1753 
1754 	/* Received response to outgoing request that establishes/refresh
1755 	 * subscription.
1756 	 */
1757 
1758 	/* First time initial request is sent. */
1759 	if (sub->state == PJSIP_EVSUB_STATE_NULL &&
1760 	    tsx->state == PJSIP_TSX_STATE_CALLING)
1761 	{
1762 	    set_state(sub, PJSIP_EVSUB_STATE_SENT, NULL, event, NULL);
1763 	    return;
1764 	}
1765 
1766 	/* Only interested in final response */
1767 	if (tsx->state != PJSIP_TSX_STATE_COMPLETED &&
1768 	    tsx->state != PJSIP_TSX_STATE_TERMINATED)
1769 	{
1770 	    return;
1771 	}
1772 
1773 	/* Clear pending subscription */
1774 	if (tsx == sub->pending_sub) {
1775 	    sub->pending_sub = NULL;
1776 	} else if (sub->pending_sub != NULL) {
1777 	    /* This SUBSCRIBE transaction has been "renewed" with another
1778 	     * SUBSCRIBE, so we can just ignore this. For example, user
1779 	     * sent SUBSCRIBE followed immediately with UN-SUBSCRIBE.
1780 	     */
1781 	    return;
1782 	}
1783 
1784 	/* Handle authentication. */
1785 	if (tsx->status_code==401 || tsx->status_code==407) {
1786 	    pjsip_tx_data *tdata;
1787 	    pj_status_t status;
1788 
1789 	    if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {
1790 		/* Previously failed transaction has terminated */
1791 		return;
1792 	    }
1793 
1794 	    status = pjsip_auth_clt_reinit_req(&sub->dlg->auth_sess,
1795 					       event->body.tsx_state.src.rdata,
1796 					       tsx->last_tx, &tdata);
1797 	    if (status == PJ_SUCCESS)
1798 		status = pjsip_dlg_send_request(sub->dlg, tdata, -1, NULL);
1799 
1800 	    if (status != PJ_SUCCESS) {
1801 		/* Authentication failed! */
1802 		set_state(sub, PJSIP_EVSUB_STATE_TERMINATED,
1803 			  NULL, event, &tsx->status_text);
1804 		return;
1805 	    }
1806 
1807 	    return;
1808 	}
1809 
1810 	if (tsx->status_code/100 == 2) {
1811 
1812 	    /* Successfull SUBSCRIBE request!
1813 	     * This could be:
1814 	     *	- response to initial SUBSCRIBE request
1815 	     *	- response to subsequent refresh
1816 	     *	- response to unsubscription
1817 	     */
1818 
1819 	    if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {
1820 		/* Ignore; this transaction has been processed before */
1821 		return;
1822 	    }
1823 
1824 	    /* Update UAC refresh time, if response contains Expires header,
1825 	     * only when we're not unsubscribing.
1826 	     */
1827 	    if (sub->expires->ivalue != 0) {
1828 		pjsip_msg *msg;
1829 		pjsip_expires_hdr *expires;
1830 
1831 		msg = event->body.tsx_state.src.rdata->msg_info.msg;
1832 		expires = (pjsip_expires_hdr*)
1833 			  pjsip_msg_find_hdr(msg, PJSIP_H_EXPIRES, NULL);
1834 		if (expires) {
1835 		    sub->expires->ivalue = expires->ivalue;
1836 		}
1837 	    }
1838 
1839 	    /* Update time */
1840 	    update_expires(sub, sub->expires->ivalue);
1841 
1842 	    /* Start UAC refresh timer, only when we're not unsubscribing */
1843 	    if (sub->expires->ivalue != 0) {
1844 		unsigned timeout = (sub->expires->ivalue > TIME_UAC_REFRESH) ?
1845 		    sub->expires->ivalue - TIME_UAC_REFRESH : sub->expires->ivalue;
1846 
1847 		/* Reduce timeout by about 1 - 10 secs (randomized) */
1848 		if (timeout > 10)
1849 		    timeout += -10 + (pj_rand() % 10);
1850 
1851 		PJ_LOG(5,(sub->obj_name, "Will refresh in %d seconds",
1852 			  timeout));
1853 		set_timer(sub, TIMER_TYPE_UAC_REFRESH, timeout);
1854 
1855 	    } else {
1856 		/* Otherwise set timer to terminate client subscription when
1857 		 * NOTIFY to end subscription is not received.
1858 		 */
1859 		set_timer(sub, TIMER_TYPE_UAC_TERMINATE, TIME_UAC_TERMINATE);
1860 	    }
1861 
1862 	    /* Set state, if necessary */
1863 	    pj_assert(sub->state != PJSIP_EVSUB_STATE_NULL);
1864 	    if (sub->state == PJSIP_EVSUB_STATE_SENT) {
1865 		set_state(sub, PJSIP_EVSUB_STATE_ACCEPTED, NULL, event, NULL);
1866 	    }
1867 
1868 	} else {
1869 
1870 	    /* Failed SUBSCRIBE request!
1871 	     *
1872 	     * The RFC 3265 says that if outgoing SUBSCRIBE fails with status
1873 	     * other than 481, the subscription is still considered valid for
1874 	     * the duration of the last Expires.
1875 	     *
1876 	     * Since we send refresh about 5 seconds (TIME_UAC_REFRESH) before
1877 	     * expiration, theoritically the expiration is still valid for the
1878 	     * next 5 seconds even when we receive non-481 failed response.
1879 	     *
1880 	     * Ah, what the heck!
1881 	     *
1882 	     * Just terminate now!
1883 	     *
1884 	     */
1885 
1886 	    if (sub->state == PJSIP_EVSUB_STATE_TERMINATED) {
1887 		/* Ignore, has been handled before */
1888 		return;
1889 	    }
1890 
1891 	    /* Ignore 490 (Request Updated) status.
1892 	     * This happens when application sends SUBSCRIBE/REFER while
1893 	     * another one is still in progress.
1894 	     */
1895 	    if (tsx->status_code == PJSIP_SC_REQUEST_UPDATED) {
1896 		return;
1897 	    }
1898 
1899 	    /* Set state to TERMINATED */
1900 	    set_state(sub, PJSIP_EVSUB_STATE_TERMINATED,
1901 		      NULL, event, &tsx->status_text);
1902 
1903 	}
1904 
1905     } else if (pjsip_method_cmp(&tsx->method, &pjsip_notify_method) == 0) {
1906 
1907 	/* Incoming NOTIFY.
1908 	 * This can be the result of:
1909 	 *  - Initial subscription response
1910 	 *  - UAS updating the resource info.
1911 	 *  - Unsubscription response.
1912 	 */
1913 	int st_code = 200;
1914 	pj_str_t *st_text = NULL;
1915 	pjsip_hdr res_hdr;
1916 	pjsip_msg_body *body = NULL;
1917 
1918 	pjsip_rx_data *rdata;
1919 	pjsip_msg *msg;
1920 	pjsip_sub_state_hdr *sub_state;
1921 
1922 	pjsip_evsub_state new_state;
1923 	pj_str_t *new_state_str;
1924 
1925 	pjsip_tx_data *tdata;
1926 	pj_status_t status;
1927 
1928 	/* Only want to handle initial NOTIFY receive event. */
1929 	if (tsx->state != PJSIP_TSX_STATE_TRYING)
1930 	    return;
1931 
1932 
1933 	rdata = event->body.tsx_state.src.rdata;
1934 	msg = rdata->msg_info.msg;
1935 
1936 	pj_list_init(&res_hdr);
1937 
1938 	/* Get subscription state header. */
1939 	sub_state = (pjsip_sub_state_hdr*)
1940 		    pjsip_msg_find_hdr_by_name(msg, &STR_SUB_STATE, NULL);
1941 	if (sub_state == NULL) {
1942 
1943 	    pjsip_warning_hdr *warn_hdr;
1944 	    pj_str_t warn_text = { "Missing Subscription-State header", 33};
1945 
1946 	    /* Bad request! Add warning header. */
1947 	    st_code = PJSIP_SC_BAD_REQUEST;
1948 	    warn_hdr = pjsip_warning_hdr_create(rdata->tp_info.pool, 399,
1949 					        pjsip_endpt_name(sub->endpt),
1950 						&warn_text);
1951 	    pj_list_push_back(&res_hdr, warn_hdr);
1952 	}
1953 
1954 	/* Call application registered callback to handle incoming NOTIFY,
1955 	 * if any.
1956 	 */
1957 	if (st_code==200 && sub->user.on_rx_notify && sub->call_cb) {
1958 	    (*sub->user.on_rx_notify)(sub, rdata, &st_code, &st_text,
1959 				      &res_hdr, &body);
1960 
1961 	    /* Application MUST specify final response! */
1962 	    PJ_ASSERT_ON_FAIL(st_code >= 200, {st_code=200; });
1963 
1964 	    /* Must be a valid status code */
1965 	    PJ_ASSERT_ON_FAIL(st_code <= 699, {st_code=500; });
1966 	}
1967 
1968 
1969 	/* If non-2xx should be returned, then send the response.
1970 	 * No need to update server subscription state.
1971 	 */
1972 	if (st_code >= 300) {
1973 	    status = create_response(sub, rdata, st_code, st_text, &res_hdr,
1974 				     body, &tdata);
1975 	    if (status == PJ_SUCCESS) {
1976 		status = pjsip_dlg_send_response(sub->dlg, tsx, tdata);
1977 	    }
1978 
1979 	    /* Start timer to terminate subscription, just in case server
1980 	     * is not able to generate NOTIFY to our response.
1981 	     */
1982 	    if (status == PJ_SUCCESS) {
1983 		unsigned timeout = TIME_UAC_WAIT_NOTIFY;
1984 		set_timer(sub, TIMER_TYPE_UAC_WAIT_NOTIFY, timeout);
1985 	    } else {
1986 		char errmsg[PJ_ERR_MSG_SIZE];
1987 		pj_str_t reason;
1988 
1989 		reason = pj_strerror(status, errmsg, sizeof(errmsg));
1990 		set_state(sub, PJSIP_EVSUB_STATE_TERMINATED, NULL, NULL,
1991 			  &reason);
1992 	    }
1993 
1994 	    return;
1995 	}
1996 
1997 	/* Update expiration from the value of expires param in
1998 	 * Subscription-State header, but ONLY when subscription state
1999 	 * is "active" or "pending", AND the header contains expires param.
2000 	 */
2001 	if (sub->expires->ivalue != 0 &&
2002 	    sub_state->expires_param != PJSIP_EXPIRES_NOT_SPECIFIED &&
2003 	    (pj_stricmp(&sub_state->sub_state, &STR_ACTIVE)==0 ||
2004 	     pj_stricmp(&sub_state->sub_state, &STR_PENDING)==0))
2005 	{
2006 	    unsigned next_refresh = sub_state->expires_param;
2007 	    unsigned timeout;
2008 
2009 	    update_expires(sub, next_refresh);
2010 
2011 	    /* Start UAC refresh timer, only when we're not unsubscribing */
2012 	    timeout = (next_refresh > TIME_UAC_REFRESH) ?
2013 			next_refresh - TIME_UAC_REFRESH : next_refresh;
2014 
2015 	    PJ_LOG(5,(sub->obj_name, "Will refresh in %d seconds", timeout));
2016 	    set_timer(sub, TIMER_TYPE_UAC_REFRESH, timeout);
2017 	}
2018 
2019 	/* Find out the state */
2020 	get_hdr_state(sub_state, &new_state, &new_state_str);
2021 
2022 	/* Send response. */
2023 	status = create_response(sub, rdata, st_code, st_text, &res_hdr,
2024 				 body, &tdata);
2025 	if (status == PJ_SUCCESS)
2026 	    status = pjsip_dlg_send_response(sub->dlg, tsx, tdata);
2027 
2028 	/* Set the state */
2029 	if (status == PJ_SUCCESS) {
2030 	    set_state(sub, new_state, new_state_str, event,
2031 		      &sub_state->reason_param);
2032 	} else {
2033 	    char errmsg[PJ_ERR_MSG_SIZE];
2034 	    pj_str_t reason;
2035 
2036 	    reason = pj_strerror(status, errmsg, sizeof(errmsg));
2037 	    set_state(sub, PJSIP_EVSUB_STATE_TERMINATED, NULL, event,
2038 		      &reason);
2039 	}
2040 
2041 
2042     } else {
2043 
2044 	/*
2045 	 * Unexpected method!
2046 	 */
2047 	PJ_LOG(4,(sub->obj_name, "Unexpected transaction method %.*s",
2048 		 (int)tsx->method.name.slen, tsx->method.name.ptr));
2049     }
2050 }
2051 
2052 
2053 /*
2054  * Transaction event processing by UAS, after subscription is accepted.
2055  */
on_tsx_state_uas(pjsip_evsub * sub,pjsip_transaction * tsx,pjsip_event * event)2056 static void on_tsx_state_uas( pjsip_evsub *sub, pjsip_transaction *tsx,
2057 			      pjsip_event *event)
2058 {
2059 
2060     if (pjsip_method_cmp(&tsx->method, &sub->method) == 0 ||
2061 	pjsip_method_cmp(&tsx->method, &pjsip_subscribe_method) == 0)
2062     {
2063 
2064 	/*
2065 	 * Incoming request (e.g. SUBSCRIBE or REFER) to refresh subsciption.
2066 	 *
2067 	 */
2068 	pjsip_rx_data *rdata;
2069 	pjsip_event_hdr *event_hdr;
2070 	pjsip_expires_hdr *expires;
2071 	pjsip_msg *msg;
2072 	pjsip_tx_data *tdata;
2073 	int st_code = 200;
2074 	pj_str_t *st_text = NULL;
2075 	pjsip_hdr res_hdr;
2076 	pjsip_msg_body *body = NULL;
2077 	pjsip_evsub_state old_state;
2078 	pj_str_t old_state_str;
2079 	pj_str_t reason = { NULL, 0 };
2080 	pj_status_t status;
2081 
2082 
2083 	/* Only wants to handle the first event when the request is
2084 	 * received.
2085 	 */
2086 	if (tsx->state != PJSIP_TSX_STATE_TRYING)
2087 	    return;
2088 
2089 	rdata = event->body.tsx_state.src.rdata;
2090 	msg = rdata->msg_info.msg;
2091 
2092 	/* Set expiration time based on client request (in Expires header),
2093 	 * or package default expiration time.
2094 	 */
2095 	event_hdr = (pjsip_event_hdr*)
2096 		    pjsip_msg_find_hdr_by_names(msg, &STR_EVENT,
2097 					        &STR_EVENT, NULL);
2098 	expires = (pjsip_expires_hdr*)
2099 		  pjsip_msg_find_hdr(msg, PJSIP_H_EXPIRES, NULL);
2100 	if (event_hdr && expires) {
2101 	    struct evpkg *evpkg;
2102 
2103 	    evpkg = find_pkg(&event_hdr->event_type);
2104 	    if (evpkg) {
2105 		if (expires->ivalue < evpkg->pkg_expires)
2106 		    sub->expires->ivalue = expires->ivalue;
2107 		else
2108 		    sub->expires->ivalue = evpkg->pkg_expires;
2109 	    }
2110 	}
2111 
2112 	/* Update time (before calling on_rx_refresh, since application
2113 	 * will send NOTIFY.
2114 	 */
2115 	update_expires(sub, sub->expires->ivalue);
2116 
2117 
2118 	/* Save old state.
2119 	 * If application respond with non-2xx, revert to old state.
2120 	 */
2121 	old_state = sub->state;
2122 	old_state_str = sub->state_str;
2123 
2124 	if (sub->expires->ivalue == 0) {
2125 	    sub->state = PJSIP_EVSUB_STATE_TERMINATED;
2126 	    sub->state_str = evsub_state_names[sub->state];
2127 	} else  if (sub->state == PJSIP_EVSUB_STATE_NULL) {
2128 	    sub->state = PJSIP_EVSUB_STATE_ACCEPTED;
2129 	    sub->state_str = evsub_state_names[sub->state];
2130 	}
2131 
2132 	/* Call application's on_rx_refresh, just in case it wants to send
2133 	 * response other than 200 (OK)
2134 	 */
2135 	pj_list_init(&res_hdr);
2136 
2137 	if (sub->user.on_rx_refresh && sub->call_cb) {
2138 	    (*sub->user.on_rx_refresh)(sub, rdata, &st_code, &st_text,
2139 				       &res_hdr, &body);
2140 	}
2141 
2142 	/* Application MUST specify final response! */
2143 	PJ_ASSERT_ON_FAIL(st_code >= 200, {st_code=200; });
2144 
2145 	/* Must be a valid status code */
2146 	PJ_ASSERT_ON_FAIL(st_code <= 699, {st_code=500; });
2147 
2148 
2149 	/* Create and send response */
2150 	status = create_response(sub, rdata, st_code, st_text, &res_hdr,
2151 				 body, &tdata);
2152 	if (status == PJ_SUCCESS) {
2153 	    /* Add expires header: */
2154 	    pjsip_msg_add_hdr( tdata->msg, (pjsip_hdr*)
2155 			       pjsip_hdr_shallow_clone(tdata->pool,
2156 						       sub->expires));
2157 
2158 	    /* Send */
2159 	    status = pjsip_dlg_send_response(sub->dlg, tsx, tdata);
2160 	}
2161 
2162 	/* Update state or revert state */
2163 	if (st_code/100==2) {
2164 
2165 	    if (sub->expires->ivalue == 0) {
2166 		set_state(sub, sub->state, NULL, event, &reason);
2167 	    } else  if (sub->state == PJSIP_EVSUB_STATE_NULL) {
2168 		set_state(sub, sub->state, NULL, event, &reason);
2169 	    }
2170 
2171 	    /* Set UAS timeout timer, when state is not terminated. */
2172 	    if (sub->state != PJSIP_EVSUB_STATE_TERMINATED) {
2173 		PJ_LOG(5,(sub->obj_name, "UAS timeout in %d seconds",
2174 			  sub->expires->ivalue));
2175 		set_timer(sub, TIMER_TYPE_UAS_TIMEOUT,
2176 			  sub->expires->ivalue);
2177 	    }
2178 
2179 	}  else {
2180 	    sub->state = old_state;
2181 	    sub->state_str = old_state_str;
2182 	}
2183 
2184 
2185     } else if (pjsip_method_cmp(&tsx->method, &pjsip_notify_method)==0) {
2186 
2187 	/* Handle authentication */
2188 	if (tsx->state == PJSIP_TSX_STATE_COMPLETED &&
2189 	    (tsx->status_code==401 || tsx->status_code==407))
2190 	{
2191 	    pjsip_tx_data *tdata;
2192 	    pj_status_t status;
2193 	    pjsip_rx_data *rdata = event->body.tsx_state.src.rdata;
2194 
2195 	    /* Handled by other module already (e.g: invite module) */
2196 	    if (tsx->last_tx->auth_retry)
2197 		return;
2198 
2199 	    status = pjsip_auth_clt_reinit_req(&sub->dlg->auth_sess, rdata,
2200 					       tsx->last_tx, &tdata);
2201 	    if (status == PJ_SUCCESS)
2202 		status = pjsip_dlg_send_request(sub->dlg, tdata, -1, NULL);
2203 
2204 	    if (status != PJ_SUCCESS) {
2205 		/* Can't authenticate. Terminate session (?) */
2206 		set_state(sub, PJSIP_EVSUB_STATE_TERMINATED, NULL, NULL,
2207 			  &tsx->status_text);
2208 	    }
2209 	    return;
2210 
2211 	}
2212 
2213 	if (sub->state == PJSIP_EVSUB_STATE_TERMINATED)
2214 	    return;
2215 
2216 	/* NOTIFY failure check */
2217 	if (tsx->status_code/100 != 2) {
2218 	    pj_bool_t should_terminate_sub = PJ_FALSE;
2219 
2220 	    if (event->body.tsx_state.type == PJSIP_EVENT_RX_MSG) {
2221 		if (tsx->status_code == 481) {
2222 		    should_terminate_sub = PJ_TRUE;
2223 		} else {
2224 		    pjsip_retry_after_hdr *retry_after;
2225 		    pjsip_rx_data *rdata = event->body.tsx_state.src.rdata;
2226 		    pjsip_msg *msg = rdata->msg_info.msg;
2227 
2228 		    retry_after = (pjsip_retry_after_hdr*)
2229 		       pjsip_msg_find_hdr_by_name(msg, &STR_RETRY_AFTER, NULL);
2230 
2231 		    if (!retry_after) {
2232 			should_terminate_sub = PJ_TRUE;
2233 		    }
2234 		}
2235 	    } else if (event->body.tsx_state.type == PJSIP_EVENT_TIMER) {
2236 		if (tsx->status_code == 408) {
2237 		    should_terminate_sub = PJ_TRUE;
2238 		}
2239 	    }
2240 
2241 	    /*
2242 	     * Terminate event usage if we receive non 2xx without retry_after
2243 	     * parameter, 481, 408 responses.
2244 	     */
2245 	    if (should_terminate_sub) {
2246 		set_state(sub, PJSIP_EVSUB_STATE_TERMINATED, NULL, event,
2247 			  &tsx->status_text);
2248 		return;
2249 	    }
2250 	}
2251     } else {
2252 
2253 	/*
2254 	 * Unexpected method!
2255 	 */
2256 	PJ_LOG(4,(sub->obj_name, "Unexpected transaction method %.*s",
2257 		 (int)tsx->method.name.slen, tsx->method.name.ptr));
2258 
2259     }
2260 }
2261 
2262 
2263 /*
2264  * Notification when transaction state has changed!
2265  */
mod_evsub_on_tsx_state(pjsip_transaction * tsx,pjsip_event * event)2266 static void mod_evsub_on_tsx_state(pjsip_transaction *tsx, pjsip_event *event)
2267 {
2268     pjsip_evsub *sub = pjsip_tsx_get_evsub(tsx);
2269 
2270     if (sub == NULL) {
2271 	sub = on_new_transaction(tsx, event);
2272 	if (sub == NULL)
2273 	    return;
2274     }
2275 
2276 
2277     /* Call on_tsx_state callback, if any. */
2278     if (sub->user.on_tsx_state && sub->call_cb)
2279 	(*sub->user.on_tsx_state)(sub, tsx, event);
2280 
2281 
2282     /* Process the event: */
2283 
2284     if (sub->role == PJSIP_ROLE_UAC) {
2285 	on_tsx_state_uac(sub, tsx, event);
2286     } else {
2287 	on_tsx_state_uas(sub, tsx, event);
2288     }
2289 
2290 
2291     /* Check transaction TERMINATE event */
2292     if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {
2293 
2294 	--sub->pending_tsx;
2295 
2296 	if (sub->state == PJSIP_EVSUB_STATE_TERMINATED &&
2297 	    sub->pending_tsx == 0)
2298 	{
2299 	    evsub_destroy(sub);
2300 	}
2301 
2302     }
2303 }
2304 
2305 
2306