1 /*
2  * This file is part of the Sofia-SIP package
3  *
4  * Copyright (C) 2006 Nokia Corporation.
5  *
6  * Contact: Pekka Pessi <pekka.pessi@nokia.com>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public License
10  * as published by the Free Software Foundation; either version 2.1 of
11  * the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21  * 02110-1301 USA
22  *
23  */
24 
25 /**@internal @file nua.c High-Level User Agent Library - "nua" Implementation.
26  *
27  * @author Pekka Pessi <Pekka.Pessi@nokia.com>
28  * @author Kai Vehmanen <Kai.Vehmanen@nokia.com>
29  * @author Pasi Rinne-Rahkola
30  *
31  * @date Created: Wed Feb 14 18:32:58 2001 ppessi
32  */
33 
34 #include "config.h"
35 
36 #include <sofia-sip/su_tag.h>
37 #include <sofia-sip/su_tag_class.h>
38 #include <sofia-sip/su_tagarg.h>
39 
40 #include <sofia-sip/su_tag_io.h>
41 
42 #define SU_LOG (nua_log)
43 #include <sofia-sip/su_debug.h>
44 
45 #define SU_ROOT_MAGIC_T   struct nua_s
46 
47 #include <sofia-sip/sip_status.h>
48 #include <sofia-sip/sip_header.h>
49 #include <sofia-sip/nta.h>
50 
51 #include "sofia-sip/nua.h"
52 #include "sofia-sip/nua_tag.h"
53 #include "nua_stack.h"
54 
55 #include <stddef.h>
56 #include <stdlib.h>
57 #include <string.h>
58 #include <stdio.h>
59 #include <assert.h>
60 
61 /* From AM_INIT/AC_INIT in our "config.h" */
62 char const nua_version[] = VERSION;
63 
64 /**Environment variable determining the debug log level for @nua module.
65  *
66  * The NUA_DEBUG environment variable is used to determine the debug logging
67  * level for @nua module. The default level is 3.
68  *
69  * @sa <sofia-sip/su_debug.h>, nua_log, SOFIA_DEBUG
70  */
71 extern char const NUA_DEBUG[];
72 
73 #ifndef SU_DEBUG
74 #define SU_DEBUG 3
75 #endif
76 
77 /**Debug log for @nua module.
78  *
79  * The nua_log is the log object used by @nua module. The level of
80  * #nua_log is set using #NUA_DEBUG environment variable.
81  */
82 su_log_t nua_log[] = { SU_LOG_INIT("nua", "NUA_DEBUG", SU_DEBUG) };
83 
84 /**Create a @nua agent.
85  *
86  * This function creates a Sofia-SIP User Agent stack object (@nua) and
87  * initializes its parameters by given tagged values.
88  *
89  * @param root            Pointer to a root object
90  * @param callback        Pointer to event callback function
91  * @param magic           Pointer to callback context
92  * @param tag,�value, ... List of tagged parameters
93  *
94  * @retval !=NULL a pointer to a @nua stack object
95  * @retval NULL upon an error
96  *
97  * @par Related tags:
98  * - NUTAG_PROXY(), giving the URI of the outbound proxy
99  *   (but see also NUTAG_INITIAL_ROUTE()).
100  * - NUTAG_URL() (and NUTAG_SIPS_URL(), listing URIs describing
101  *   transports)
102  * - NUTAG_CERTIFICATE_DIR(), specifying the location of the
103  *   root and client/server certificate files
104  * - NUTAG_SIP_PARSER(), providing customized parser used to
105  *   parse received SIP messages
106  * - All parameter tags, listed with nua_set_params()
107  * - All NTATAG_* are passed to NTA documented in <sofia-sip/nta_tag.h>:
108  *   see NTATAG_EXTRA_100(),
109  * - All tport tags are passed to tport.
110  *   They are documented in <sofia-sip/tport_tag.h>
111  * - All SOATAG_* are passed to the default SOA (media session) object which
112  *   is created by nua_create() unless NUTAG_MEDIA_ENABLE(0) is included in
113  *   the tag list
114  * - STUN tags STUNTAG_DOMAIN(), STUNTAG_SERVER().
115  *   STUN is deprecated, however.
116  *
117  * @note
118  * From the @VERSION_1_12_2 all the nua_set_params() tags are processed.
119  * Previously all nutags except NUTAG_SOA_NAME() and NUTAG_MEDIA_ENABLE()
120  * were ignored.
121  *
122  * @note
123  * Both the NUTAG_URL() and NUTAG_SIPS_URL() are used to pass arguments to
124  * nta_agent_add_tport().
125  *
126  * @par Events:
127  *     none
128  *
129  * @sa nua_shutdown(), nua_destroy(), nua_handle(), nta_agent_create().
130  */
nua_create(su_root_t * root,nua_callback_f callback,nua_magic_t * magic,tag_type_t tag,tag_value_t value,...)131 nua_t *nua_create(su_root_t *root,
132 		  nua_callback_f callback,
133 		  nua_magic_t *magic,
134 		  tag_type_t tag, tag_value_t value, ...)
135 {
136   nua_t *nua = NULL;
137 
138   enter;
139 
140   if (callback == NULL)
141     return (void)(errno = EFAULT), NULL;
142 
143   if (root == NULL)
144     return (void)(errno = EFAULT), NULL;
145 
146   if ((nua = su_home_new(sizeof(*nua)))) {
147     ta_list ta;
148 
149     su_home_threadsafe(nua->nua_home);
150     nua->nua_api_root = root;
151 
152     ta_start(ta, tag, value);
153 
154     nua->nua_args = tl_adup(nua->nua_home, ta_args(ta));
155 
156     su_task_copy(nua->nua_client, su_root_task(root));
157 
158     /* XXX: where to put this in the nua_server case? */
159 #if HAVE_SMIME		/* Start NRC Boston */
160       nua->sm = sm_create();
161 #endif                  /* End NRC Boston */
162 
163 #ifndef NUA_SERVER
164     if (su_clone_start(root,
165 		       nua->nua_clone,
166 		       nua,
167 		       nua_stack_init,
168 		       nua_stack_deinit) == SU_SUCCESS) {
169       su_task_copy(nua->nua_server, su_clone_task(nua->nua_clone));
170       nua->nua_callback = callback;
171       nua->nua_magic = magic;
172     }
173     else {
174       su_home_unref(nua->nua_home);
175       nua = NULL;
176     }
177 #endif
178 
179     ta_end(ta);
180   }
181 
182   return nua;
183 }
184 
185 /* nua_shutdown() is documented with nua_stack_shutdown() */
186 
nua_shutdown(nua_t * nua)187 void nua_shutdown(nua_t *nua)
188 {
189   enter;
190 
191   if (nua)
192     nua->nua_shutdown_started = 1;
193   nua_signal(nua, NULL, NULL, nua_r_shutdown, 0, NULL, TAG_END());
194 }
195 
196 /** Destroy the @nua stack.
197  *
198  * Before calling nua_destroy() the application
199  * should call nua_shutdown and wait for successful #nua_r_shutdown event.
200  * Shuts down and destroys the @nua stack. Ongoing calls, registrations,
201  * and subscriptions are left as they are.
202  *
203  * @param nua         Pointer to @nua stack object
204  *
205  * @return
206  *     nothing
207  *
208  * @par Related tags:
209  *     none
210  *
211  * @par Events:
212  *     none
213  *
214  * @sa nua_shutdown(), nua_create(), nua_handle_destroy(), nua_handle_unref()
215  */
nua_destroy(nua_t * nua)216 void nua_destroy(nua_t *nua)
217 {
218   enter;
219 
220   if (nua) {
221     if (!nua->nua_shutdown_final) {
222       SU_DEBUG_0(("nua_destroy(%p): FATAL: nua_shutdown not completed\n",
223 		  (void *)nua));
224       assert(nua->nua_shutdown);
225       return;
226     }
227 
228     nua->nua_callback = NULL;
229 
230     su_task_deinit(nua->nua_server);
231     su_task_deinit(nua->nua_client);
232 
233     su_clone_wait(nua->nua_api_root, nua->nua_clone);
234 #if HAVE_SMIME		/* Start NRC Boston */
235     sm_destroy(nua->sm);
236 #endif			/* End NRC Boston */
237     su_home_unref(nua->nua_home);
238   }
239 }
240 
241 /** Fetch callback context from nua.
242  *
243  * @param nua         Pointer to @nua stack object
244  *
245  * @return Callback context pointer.
246  *
247  * @NEW_1_12_4.
248  */
nua_magic(nua_t * nua)249 nua_magic_t *nua_magic(nua_t *nua)
250 {
251   return nua ? nua->nua_magic : NULL;
252 }
253 
254 /** Obtain default operation handle of the @nua stack object.
255  *
256  * A default operation can be used for operations where the
257  * ultimate result is not important or can be discarded.
258  *
259  * @param nua         Pointer to @nua stack object
260  *
261  * @retval !=NULL Pointer to @nua operation handle
262  * @retval NULL   No default operation exists
263  *
264  * @par Related tags:
265  *    none
266  *
267  * @par Events:
268  *    none
269  *
270  */
nua_default(nua_t * nua)271 nua_handle_t *nua_default(nua_t *nua)
272 {
273   return nua ? nua->nua_handles : NULL;
274 }
275 
276 /** Create an operation handle
277  *
278  * Allocates a new operation handle and associated storage.
279  *
280  * @param nua         Pointer to @nua stack object
281  * @param hmagic      Pointer to callback context
282  * @param tag, value, ... List of tagged parameters
283  *
284  * @retval !=NULL  Pointer to operation handle
285  * @retval NULL    Creation failed
286  *
287  * @par Related tags:
288  *     Duplicates the provided tags for use with every operation. Note that
289  *     NUTAG_URL() is converted to SIPTAG_TO() if there is no SIPTAG_TO().
290  *     And also vice versa, request-URI is taken from SIPTAG_TO() if there
291  *     is no NUTAG_URL(). Note that certain SIP headers cannot be saved with
292  *     the handle. They include @ContentLength, @CSeq, @RSeq, @RAck, and
293  *     @Timestamp.
294  *
295  * @par
296  *     nua_handle() accepts all the tags accepted by nua_set_hparams(), too.
297  *
298  *
299  * @par Events:
300  *     none
301  *
302  * @sa nua_handle_bind(), nua_handle_destroy(), nua_handle_ref(),
303  * nua_handle_unref().
304  */
nua_handle(nua_t * nua,nua_hmagic_t * hmagic,tag_type_t tag,tag_value_t value,...)305 nua_handle_t *nua_handle(nua_t *nua, nua_hmagic_t *hmagic,
306 			 tag_type_t tag, tag_value_t value, ...)
307 {
308   nua_handle_t *nh = NULL;
309 
310   if (nua) {
311     ta_list ta;
312 
313     ta_start(ta, tag, value);
314 
315     nh = nh_create_handle(nua, hmagic, ta_args(ta));
316 
317     if (nh)
318       nh->nh_ref_by_user = 1;
319 
320     ta_end(ta);
321   }
322 
323   return nh;
324 }
325 
326 /** Bind a callback context to an operation handle.
327  *
328  * @param nh          Pointer to operation handle
329  * @param hmagic      Pointer to callback context
330  *
331  * @return
332  *     nothing
333  *
334  * @par Related tags:
335  *     none
336  *
337  * @par Events:
338  *     none
339  */
nua_handle_bind(nua_handle_t * nh,nua_hmagic_t * hmagic)340 void nua_handle_bind(nua_handle_t *nh, nua_hmagic_t *hmagic)
341 {
342   enter;
343 
344   if (NH_IS_VALID(nh))
345     nh->nh_magic = hmagic;
346 }
347 
348 /** Fetch a callback context from an operation handle.
349  *
350  * @param nh          Pointer to operation handle
351  *
352  * @return
353  *     Pointer to callback context
354  *
355  * @par Related tags:
356  *     none
357  *
358  * @par Events:
359  *     none
360  *
361  * @NEW_1_12_4.
362  */
nua_handle_magic(nua_handle_t * nh)363 nua_hmagic_t *nua_handle_magic(nua_handle_t *nh)
364 {
365   nua_hmagic_t *magic = NULL;
366   enter;
367 
368   if (NH_IS_VALID(nh))
369     magic = nh->nh_magic;
370 
371   return magic;
372 }
373 
374 /* ---------------------------------------------------------------------- */
375 
376 /** Check if operation handle is used for INVITE
377  *
378  * Check if operation handle has been used with either outgoing or incoming
379  * INVITE request.
380  *
381  * @param nh          Pointer to operation handle
382  *
383  * @retval 0 no invite in operation or operation handle is invalid
384  * @retval 1 operation has invite
385  *
386  * @par Related tags:
387  *     none
388  *
389  * @par Events:
390  *     none
391  */
nua_handle_has_invite(nua_handle_t const * nh)392 int nua_handle_has_invite(nua_handle_t const *nh)
393 {
394   return nh ? nh->nh_has_invite : 0;
395 }
396 
397 /**Check if operation handle has active event subscriptions.
398  *
399  * Active subscription can be established either by nua_subscribe() or
400  * nua_refer() calls.
401  *
402  * @param nh          Pointer to operation handle
403  *
404  * @retval 0    no event subscriptions in operation or
405  *              operation handle is invalid
406  * @retval !=0  operation has event subscriptions
407  *
408  * @par Related tags:
409  *     none
410  *
411  * @par Events:
412  *     none
413  */
nua_handle_has_events(nua_handle_t const * nh)414 int nua_handle_has_events(nua_handle_t const *nh)
415 {
416   return nh ? nh->nh_ds->ds_has_events : 0;
417 }
418 
419 /** Check if operation handle has active registrations
420  *
421  * A registration is active when either when a REGISTER operation is going
422  * on or when it has successfully completed so that @nua stack is expected to
423  * refresh the registration in the future. Normally, a handle has active
424  * registration after nua_register() until nua_unregister() completes,
425  * unless the initial nua_register() had either expiration time of 0 or it
426  * had SIPTAG_CONTACT(NULL) as an argument.
427  *
428  * @param nh          Pointer to operation handle
429  *
430  * @retval 0 no active registration in operation or
431  *           operation handle is invalid
432  * @retval 1 operation has registration
433  *
434  * @par Related tags:
435  *     none
436  *
437  * @par Events:
438  *     none
439  *
440  * @sa nua_register(), nua_unregister(), #nua_r_register, #nua_r_unregister
441  */
nua_handle_has_registrations(nua_handle_t const * nh)442 int nua_handle_has_registrations(nua_handle_t const *nh)
443 {
444   return nh && nh->nh_ds->ds_has_register;
445 }
446 
447 /** Check if operation handle has been used with outgoing SUBSCRIBE of REFER request.
448  *
449  * @param nh          Pointer to operation handle
450  *
451  * @retval 0 no active subscription in operation or
452  *           operation handle is invalid
453  * @retval 1 operation has subscription.
454  *
455  * @par Related tags:
456  *     none
457  *
458  * @par Events:
459  *     none
460  */
nua_handle_has_subscribe(nua_handle_t const * nh)461 int nua_handle_has_subscribe(nua_handle_t const *nh)
462 {
463   return nh ? nh->nh_has_subscribe : 0;
464 }
465 
466 /** Check if operation handle has been used with nua_register() or nua_unregister().
467  *
468  * @param nh          Pointer to operation handle
469  *
470  * @retval 0 no active register in operation or operation handle is invalid
471  * @retval 1 operation has been used with nua_register() or nua-unregister()
472  *
473  * @par Related tags:
474  *     none
475  *
476  * @par Events:
477  *     none
478  */
nua_handle_has_register(nua_handle_t const * nh)479 int nua_handle_has_register(nua_handle_t const *nh)
480 {
481   return nh ? nh->nh_has_register : 0;
482 }
483 
484 /** Check if operation handle has an active call
485  *
486  * @param nh          Pointer to operation handle
487  *
488  * @retval 0 no active call in operation or operation handle is invalid
489  * @retval 1 operation has established call or pending call request.
490  *
491  * @par Related tags:
492  *     none
493  *
494  * @par Events:
495  *     none
496  */
nua_handle_has_active_call(nua_handle_t const * nh)497 int nua_handle_has_active_call(nua_handle_t const *nh)
498 {
499   return nh ? nh->nh_active_call : 0;
500 }
501 
502 /** Check if operation handle has a call on hold
503  *
504  * Please note that this status is not affected by remote end putting
505  * this end on hold. Remote end can put each media separately on hold
506  * and status is reflected on SOATAG_ACTIVE_AUDIO(), SOATAG_ACTIVE_VIDEO()
507  * and SOATAG_ACTIVE_CHAT() tag values in #nua_i_state event.
508  *
509  * @param nh          Pointer to operation handle
510  *
511  * @retval 0  if no call on hold in operation or operation handle is invalid
512  * @retval 1  if operation has call on hold, for example nua_invite() or
513  *            nua_update() has been called with SOATAG_HOLD() with non-NULL
514  *            argument.
515  *
516  * @par Related tags:
517  *     none
518  *
519  * @par Events:
520  *     none
521  */
nua_handle_has_call_on_hold(nua_handle_t const * nh)522 int nua_handle_has_call_on_hold(nua_handle_t const *nh)
523 {
524   return nh ? nh->nh_hold_remote : 0;
525 }
526 
527 /** Get the remote address (From/To header) of operation handle
528  *
529  * Remote address is used as To header in outgoing operations and
530  * derived from From: header in incoming operations.
531  *
532  * @param nh          Pointer to operation handle
533  *
534  * @retval NULL   no remote address for operation or operation handle invalid
535  * @retval !=NULL pointer to remote address for operation
536  *
537  * @par Related tags:
538  *     none
539  *
540  * @par Events:
541  *     none
542  */
nua_handle_remote(nua_handle_t const * nh)543 sip_to_t const *nua_handle_remote(nua_handle_t const *nh)
544 {
545   return nh ? nh->nh_ds->ds_remote : NULL;
546 }
547 
548 /** Get the local address (From/To header) of operation handle
549  *
550  * Local address is used as From header in outgoing operations and
551  * derived from To: header in incoming operations.
552  *
553  * @param nh          Pointer to operation handle
554  *
555  * @retval NULL   no local address for operation or operation handle invalid
556  * @retval !=NULL pointer to local address for operation
557  *
558  * @par Related tags:
559  *     none
560  *
561  * @par Events:
562  *     none
563  */
nua_handle_local(nua_handle_t const * nh)564 sip_to_t const *nua_handle_local(nua_handle_t const *nh)
565 {
566   return nh ? nh->nh_ds->ds_local : NULL;
567 }
568 
569 /* Documented with nua_stack_set_params() */
nua_set_params(nua_t * nua,tag_type_t tag,tag_value_t value,...)570 void nua_set_params(nua_t *nua, tag_type_t tag, tag_value_t value, ...)
571 {
572   ta_list ta;
573   ta_start(ta, tag, value);
574 
575   enter;
576 
577   nua_signal(nua, NULL, NULL, nua_r_set_params, 0, NULL, ta_tags(ta));
578 
579   ta_end(ta);
580 }
581 
582 /* Documented with nua_stack_get_params() */
nua_get_params(nua_t * nua,tag_type_t tag,tag_value_t value,...)583 void nua_get_params(nua_t *nua, tag_type_t tag, tag_value_t value, ...)
584 {
585   ta_list ta;
586   ta_start(ta, tag, value);
587 
588   enter;
589 
590   nua_signal(nua, NULL, NULL, nua_r_get_params, 0, NULL, ta_tags(ta));
591 
592   ta_end(ta);
593 }
594 
595 #define NUA_SIGNAL(nh, event, tag, value) \
596   enter; \
597   if (NH_IS_VALID((nh))) { \
598     ta_list ta; \
599     ta_start(ta, tag, value); \
600     nua_signal((nh)->nh_nua, nh, NULL, event, 0, NULL, ta_tags(ta));	\
601     ta_end(ta); \
602   } \
603   else { \
604     SU_DEBUG_1(("nua: " #event " with invalid handle %p\n", (void *)nh)); \
605   }
606 
607 /* Documented with nua_stack_set_params() */
nua_set_hparams(nua_handle_t * nh,tag_type_t tag,tag_value_t value,...)608 void nua_set_hparams(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...)
609 {
610   NUA_SIGNAL(nh, nua_r_set_params, tag, value);
611 }
612 
613 /* Documented with nua_stack_get_params() */
nua_get_hparams(nua_handle_t * nh,tag_type_t tag,tag_value_t value,...)614 void nua_get_hparams(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...)
615 {
616   NUA_SIGNAL(nh, nua_r_get_params, tag, value);
617 }
618 
619 /* Documented with nua_stack_register() */
nua_register(nua_handle_t * nh,tag_type_t tag,tag_value_t value,...)620 void nua_register(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...)
621 {
622   NUA_SIGNAL(nh, nua_r_register, tag, value);
623 }
624 
nua_unregister(nua_handle_t * nh,tag_type_t tag,tag_value_t value,...)625 void nua_unregister(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...)
626 {
627   NUA_SIGNAL(nh, nua_r_unregister, tag, value);
628 }
629 
630 /* Documented with nua_stack_invite() */
nua_invite(nua_handle_t * nh,tag_type_t tag,tag_value_t value,...)631 void nua_invite(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...)
632 {
633   NUA_SIGNAL(nh, nua_r_invite, tag, value);
634 }
635 
636 /* Documented with nua_stack_ack() */
nua_ack(nua_handle_t * nh,tag_type_t tag,tag_value_t value,...)637 void nua_ack(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...)
638 {
639   NUA_SIGNAL(nh, nua_r_ack, tag, value);
640 }
641 
642 /* Documented with nua_stack_bye() */
nua_bye(nua_handle_t * nh,tag_type_t tag,tag_value_t value,...)643 void nua_bye(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...)
644 {
645   NUA_SIGNAL(nh, nua_r_bye, tag, value);
646 }
647 
648 /* Documented with nua_stack_cancel() */
nua_cancel(nua_handle_t * nh,tag_type_t tag,tag_value_t value,...)649 void nua_cancel(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...)
650 {
651   NUA_SIGNAL(nh, nua_r_cancel, tag, value);
652 }
653 
654 /* Documented with nua_stack_options() */
nua_options(nua_handle_t * nh,tag_type_t tag,tag_value_t value,...)655 void nua_options(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...)
656 {
657   NUA_SIGNAL(nh, nua_r_options, tag, value);
658 }
659 
660 /* Documented with nua_stack_message() */
nua_message(nua_handle_t * nh,tag_type_t tag,tag_value_t value,...)661 void nua_message(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...)
662 {
663   NUA_SIGNAL(nh, nua_r_message, tag, value);
664 }
665 
666 /* Documented with nua_stack_method() */
nua_method(nua_handle_t * nh,tag_type_t tag,tag_value_t value,...)667 void nua_method(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...)
668 {
669   NUA_SIGNAL(nh, nua_r_method, tag, value);
670 }
671 
672 /** Send a chat message.
673  *
674  * A chat channel can be established during call setup using "message" media.
675  * An active chat channel is indicated using #nua_i_state event containing
676  * SOATAG_ACTIVE_CHAT() tag. Chat messages can be sent using this channel with
677  * nua_chat() function. Currently this is implemented using SIP MESSAGE
678  * requests but in future MSRP (message session protocol) will replace it.
679 *
680  * @param nh              Pointer to operation handle
681  * @param tag, value, ... List of tagged parameters
682  *
683  * @return
684  *    nothing
685  *
686  * @par Related Tags:
687  *    SIPTAG_CONTENT_TYPE() \n
688  *    SIPTAG_PAYLOAD()      \n
689  *    SIPTAG_FROM()         \n
690  *    SIPTAG_TO()           \n
691  *    Use of other SIP tags is deprecated
692  *
693  * @par Events:
694  *    #nua_r_chat
695  */
nua_chat(nua_handle_t * nh,tag_type_t tag,tag_value_t value,...)696 void nua_chat(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...)
697 {
698   NUA_SIGNAL(nh, nua_r_chat, tag, value);
699 }
700 
701 /* Documented with nua_stack_subscribe() */
nua_subscribe(nua_handle_t * nh,tag_type_t tag,tag_value_t value,...)702 void nua_subscribe(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...)
703 {
704   NUA_SIGNAL(nh, nua_r_subscribe, tag, value);
705 }
706 
707 /* Documented with nua_stack_subscribe() */
nua_unsubscribe(nua_handle_t * nh,tag_type_t tag,tag_value_t value,...)708 void nua_unsubscribe(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...)
709 {
710   NUA_SIGNAL(nh, nua_r_unsubscribe, tag, value);
711 }
712 
713 /* Documented with nua_stack_notify() */
nua_notify(nua_handle_t * nh,tag_type_t tag,tag_value_t value,...)714 void nua_notify(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...)
715 {
716   NUA_SIGNAL(nh, nua_r_notify, tag, value);
717 }
718 
719 /* nua_r_notify is documented with process_response_to_notify() */
720 
721 /** Create an event server.
722  *
723  * This function create an event server taking care of sending NOTIFY
724  * requests and responding to further SUBSCRIBE requests. The event
725  * server can accept multiple subscriptions from several sources and
726  * takes care for distributing the notifications. Unlike other functions
727  * this call only accepts the SIP tags listed below.
728  *
729  * @param nh              Pointer to operation handle
730  * @param tag, value, ... List of tagged parameters
731  *
732  * @return
733  *    nothing
734  *
735  * @par Related Tags:
736  *    NUTAG_URL() \n
737  *    SIPTAG_EVENT() or SIPTAG_EVENT_STR() \n
738  *    SIPTAG_CONTENT_TYPE() or SIPTAG_CONTENT_TYPE_STR() \n
739  *    SIPTAG_PAYLOAD() or SIPTAG_PAYLOAD_STR() \n
740  *    SIPTAG_ACCEPT() or SIPTAG_ACCEPT_STR() \n
741  *
742  * @par Events:
743  *    #nua_r_notify
744  */
nua_notifier(nua_handle_t * nh,tag_type_t tag,tag_value_t value,...)745 void nua_notifier(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...)
746 {
747   NUA_SIGNAL(nh, nua_r_notifier, tag, value);
748 }
749 
750 /** Terminate an event server.
751  *
752  * Terminate an event server with matching event and content type. The event
753  * server was created earlier with nua_notifier() function.
754  *
755  * @param nh              Pointer to operation handle
756  * @param tag, value, ... List of tagged parameters
757  *
758  * @return
759  *    nothing
760  *
761  * @par Related Tags:
762  *    SIPTAG_EVENT() \n
763  *    SIPTAG_CONTENT_TYPE() \n
764  *    SIPTAG_PAYLOAD() \n
765  *    NEATAG_REASON()
766  *
767  * @par Events:
768  *    #nua_r_terminate
769  *
770  * @sa nua_notifier(), nua_authorize().
771  */
nua_terminate(nua_handle_t * nh,tag_type_t tag,tag_value_t value,...)772 void nua_terminate(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...)
773 {
774   NUA_SIGNAL(nh, nua_r_terminate, tag, value);
775 }
776 
777 /* Documented with nua_stack_refer() */
nua_refer(nua_handle_t * nh,tag_type_t tag,tag_value_t value,...)778 void nua_refer(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...)
779 {
780   NUA_SIGNAL(nh, nua_r_refer, tag, value);
781 }
782 
783 /* Documented with nua_stack_publish() */
nua_publish(nua_handle_t * nh,tag_type_t tag,tag_value_t value,...)784 void nua_publish(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...)
785 {
786   NUA_SIGNAL(nh, nua_r_publish, tag, value);
787 }
788 
789 /* Documented with nua_stack_publish() */
nua_unpublish(nua_handle_t * nh,tag_type_t tag,tag_value_t value,...)790 void nua_unpublish(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...)
791 {
792   NUA_SIGNAL(nh, nua_r_unpublish, tag, value);
793 }
794 
795 /* Documented with nua_stack_info() */
nua_info(nua_handle_t * nh,tag_type_t tag,tag_value_t value,...)796 void nua_info(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...)
797 {
798   NUA_SIGNAL(nh, nua_r_info, tag, value);
799 }
800 
801 /* Documented with nua_stack_prack() */
nua_prack(nua_handle_t * nh,tag_type_t tag,tag_value_t value,...)802 void nua_prack(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...)
803 {
804   NUA_SIGNAL(nh, nua_r_prack, tag, value);
805 }
806 
807 /* Documented with nua_stack_update() */
nua_update(nua_handle_t * nh,tag_type_t tag,tag_value_t value,...)808 void nua_update(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...)
809 {
810   NUA_SIGNAL(nh, nua_r_update, tag, value);
811 }
812 
813 /** Authenticate an operation.
814  *
815  * - 401 / 407 response with www-authenticate header/ proxy-authenticate header
816  * - application should provide stack with username&password for each realm
817  *   with NUTAG_AUTH() tag
818  * - restarts operation
819  *
820  * @param nh              Pointer to operation handle
821  * @param tag, value, ... List of tagged parameters
822  *
823  * @return
824  *    nothing
825  *
826  * @par Related Tags:
827  *    NUTAG_AUTH()
828  *
829  * @par Events:
830  *    (any operation events)
831  */
nua_authenticate(nua_handle_t * nh,tag_type_t tag,tag_value_t value,...)832 void nua_authenticate(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...)
833 {
834   NUA_SIGNAL(nh, nua_r_authenticate, tag, value);
835 }
836 
837 /** Authorize a subscriber.
838  *
839  * After creating a local presence server by nua_notifier(), an incoming
840  * SUBSCRIBE request causes #nua_i_subscription event. Each subscriber is
841  * identified with NEATAG_SUB() tag in the #nua_i_subscription event.
842  * Application can either authorize the subscriber with
843  * NUTAG_SUBSTATE(#nua_substate_active) or terminate the subscription with
844  * NUTAG_SUBSTATE(#nua_substate_terminated).
845  *
846  * @param nh              Pointer to operation handle
847  * @param tag, value, ... List of tagged parameters
848  *
849  * @return
850  *    nothing
851  *
852  * @par Related Tags:
853  *    NEATAG_SUB() \n
854  *    NUTAG_SUBSTATE()
855  *
856  * @par Events:
857  *    #nua_i_subscription
858  *
859  * @sa nua_notifier(), nua_terminate()
860  */
nua_authorize(nua_handle_t * nh,tag_type_t tag,tag_value_t value,...)861 void nua_authorize(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...)
862 {
863   NUA_SIGNAL(nh, nua_r_authorize, tag, value);
864 }
865 
866 /*# Redirect an operation. */
nua_redirect(nua_handle_t * nh,tag_type_t tag,tag_value_t value,...)867 void nua_redirect(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...)
868 {
869   NUA_SIGNAL(nh, nua_r_redirect, tag, value);
870 }
871 
872 /* Documented with nua_stack_respond() */
873 
nua_respond(nua_handle_t * nh,int status,char const * phrase,tag_type_t tag,tag_value_t value,...)874 void nua_respond(nua_handle_t *nh,
875 		 int status, char const *phrase,
876 		 tag_type_t tag, tag_value_t value,
877 		 ...)
878 {
879   enter;
880 
881   if (NH_IS_VALID(nh)) {
882     ta_list ta;
883     ta_start(ta, tag, value);
884     nua_signal(nh->nh_nua, nh, NULL, nua_r_respond,
885 	       status, phrase, ta_tags(ta));
886     ta_end(ta);
887   }
888   else {
889     SU_DEBUG_1(("nua: respond with invalid handle %p\n", (void *)nh));
890   }
891 }
892 
893 /** Destroy a handle
894  *
895  * Terminate the protocol state associated with an operation handle. The
896  * stack discards resources and terminates the ongoing dialog usage,
897  * sessions and transactions associated with this handle. For example, calls
898  * are terminated with BYE request. Also, the reference count for the handle
899  * is also decremented.
900  *
901  * The handles use reference counting for memory management. In order to
902  * make it more convenient for programmer, nua_handle_destroy() decreases
903  * the reference count, too.
904  *
905  * @param nh              Pointer to operation handle
906  *
907  * @return
908  *    nothing
909  *
910  * @par Related Tags:
911  *    none
912  *
913  * @par Events:
914  *    none
915  *
916  * @sa nua_handle(), nua_handle_bind(), nua_handle_ref(), nua_handle_unref(),
917  * nua_unregister(), nua_unpublish(), nua_unsubscribe(), nua_bye().
918  */
nua_handle_destroy(nua_handle_t * nh)919 void nua_handle_destroy(nua_handle_t *nh)
920 {
921   enter;
922 
923   if (NH_IS_VALID(nh) && !NH_IS_DEFAULT(nh)) {
924     nh->nh_valid = NULL;	/* Events are no more delivered to appl. */
925     nua_signal(nh->nh_nua, nh, NULL, nua_r_destroy, 0, NULL, TAG_END());
926   }
927 }
928 
929 /* ---------------------------------------------------------------------- */
930 
931 struct nua_stack_handle_make_replaces_args {
932   sip_replaces_t *retval;
933   nua_handle_t *nh;
934   su_home_t *home;
935   int early_only;
936 };
937 
nua_stack_handle_make_replaces_call(void * arg)938 static int nua_stack_handle_make_replaces_call(void *arg)
939 {
940   struct nua_stack_handle_make_replaces_args *a = arg;
941 
942   a->retval = nua_stack_handle_make_replaces(a->nh, a->home, a->early_only);
943 
944   return 0;
945 }
946 
947 
948 /**Generate a @Replaces header for handle.
949  *
950  * A @Replaces header contains the @CallID value, @From and @To tags
951  * corresponding to SIP dialog associated with handle @a nh. Note that the
952  * @Replaces matches with dialog of the remote peer,
953  * nua_handle_by_replaces() does not return same handle (unless you swap
954  * rp_from_tag and rp_to_tag in @Replaces header).
955  *
956  * A @Replaces header is used in attended transfer, among other things.
957  *
958  * @param nh pointer to operation handle
959  * @param home memory home used to allocate the header
960  * @param early_only if true, include "early-only" parameter in @Replaces, too
961  *
962  * @return A newly created @Replaces header.
963  *
964  * @since New in @VERSION_1_12_4.
965  *
966  * @sa nua_handle_by_replaces(), @Replaces, @RFC3891, @RFC3515, nua_refer(),
967  * #nua_i_refer(), @ReferTo, nta_leg_make_replaces(),
968  * sip_headers_as_url_query()
969  */
nua_handle_make_replaces(nua_handle_t * nh,su_home_t * home,int early_only)970 sip_replaces_t *nua_handle_make_replaces(nua_handle_t *nh,
971 					 su_home_t *home,
972 					 int early_only)
973 {
974   if (nh && nh->nh_valid && nh->nh_nua) {
975 #if HAVE_OPEN_C
976     struct nua_stack_handle_make_replaces_args a = { NULL, NULL, NULL, 0 };
977     a.nh = nh;
978     a.home = home;
979     a.early_only = early_only;
980 #else
981     struct nua_stack_handle_make_replaces_args a = { NULL, nh, home, early_only };
982 #endif
983 
984     if (su_task_execute(nh->nh_nua->nua_server,
985 			nua_stack_handle_make_replaces_call, (void *)&a,
986 			NULL) == 0) {
987       return a.retval;
988     }
989   }
990   return NULL;
991 }
992 
993 struct nua_stack_handle_by_replaces_args {
994   nua_handle_t *retval;
995   nua_t *nua;
996   sip_replaces_t const *r;
997 };
998 
nua_stack_handle_by_replaces_call(void * arg)999 static int nua_stack_handle_by_replaces_call(void *arg)
1000 {
1001   struct nua_stack_handle_by_replaces_args *a = arg;
1002 
1003   a->retval = nua_stack_handle_by_replaces(a->nua, a->r);
1004 
1005   return 0;
1006 }
1007 
1008 struct nua_stack_handle_by_call_id_args {
1009   nua_handle_t *retval;
1010   nua_t *nua;
1011   const char *call_id;
1012 };
1013 
nua_stack_handle_by_call_id_call(void * arg)1014 static int nua_stack_handle_by_call_id_call(void *arg)
1015 {
1016   struct nua_stack_handle_by_call_id_args *a = arg;
1017 
1018   a->retval = nua_stack_handle_by_call_id(a->nua, a->call_id);
1019 
1020   return 0;
1021 }
1022 
1023 /** Obtain a new reference to an existing handle based on @Replaces header.
1024  *
1025  * @since New in @VERSION_1_12_4.
1026  *
1027  * @note
1028  * You should release the reference with nua_handle_unref() when you are
1029  * done with the handle.
1030  *
1031  * @sa nua_handle_make_replaces(), @Replaces, @RFC3891, nua_refer(),
1032  * #nua_i_refer, @ReferTo, nta_leg_by_replaces()
1033  */
nua_handle_by_replaces(nua_t * nua,sip_replaces_t const * r)1034 nua_handle_t *nua_handle_by_replaces(nua_t *nua, sip_replaces_t const *r)
1035 {
1036   if (nua) {
1037 #if HAVE_OPEN_C
1038     struct nua_stack_handle_by_replaces_args a;
1039     a.retval = NULL;
1040     a.nua = nua;
1041     a.r = r;
1042 #else
1043     struct nua_stack_handle_by_replaces_args a = { NULL, nua, r };
1044 #endif
1045 
1046     if (su_task_execute(nua->nua_server,
1047 			nua_stack_handle_by_replaces_call, (void *)&a,
1048 			NULL) == 0) {
1049       nua_handle_t *nh = a.retval;
1050 
1051       if (nh && !NH_IS_DEFAULT(nh) && nh->nh_valid)
1052 	return nua_handle_ref(nh);
1053     }
1054   }
1055   return NULL;
1056 }
1057 
1058 /** Obtain a new reference to an existing handle based on @CallID.
1059  *
1060  * @since New in @VERSION_1_12_9.
1061  *
1062  * @note
1063  * You should release the reference with nua_handle_unref() when you are
1064  * done with the handle.
1065  *
1066  * @sa nua_handle_make_replaces(), @Replaces, @RFC3891, nua_refer(),
1067  * #nua_i_refer, @ReferTo, nta_leg_by_replaces()
1068  */
nua_handle_by_call_id(nua_t * nua,const char * call_id)1069 nua_handle_t *nua_handle_by_call_id(nua_t *nua, const char *call_id)
1070 {
1071   if (nua) {
1072 #if HAVE_OPEN_C
1073     struct nua_stack_handle_by_call_id_args a;
1074 	a.retval = NULL;
1075     a.nua = nua;
1076     a.call_id = call_id;
1077 #else
1078     struct nua_stack_handle_by_call_id_args a = { NULL, nua, call_id };
1079 #endif
1080 
1081     if (su_task_execute(nua->nua_server,
1082 			nua_stack_handle_by_call_id_call, (void *)&a,
1083 			NULL) == 0) {
1084       nua_handle_t *nh = a.retval;
1085 
1086       if (nh && !NH_IS_DEFAULT(nh) && nh->nh_valid)
1087 	return nua_handle_ref(nh);
1088     }
1089   }
1090   return NULL;
1091 }
1092