1 /*
2  * This file is part of the Sofia-SIP package
3  *
4  * Copyright (C) 2005 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 #ifndef NUA_STACK_H
26 /** Defined when <nua_stack.h> has been included. */
27 #define NUA_STACK_H
28 /**@IFILE nua_stack.h
29  * @brief Sofia-SIP User Agent Engine - internal stack interface
30  *
31  * @author Pekka Pessi <Pekka.Pessi@nokia.com>
32  * @author Kai Vehmanen <Kai.Vehmanen@nokia.com>
33  *
34  * @date Created: Wed Feb 14 17:09:44 2001 ppessi
35  */
36 
37 #ifndef SU_CONFIG_H
38 #include <su_config.h>
39 #endif
40 
41 #ifndef SU_OS_NW_H
42 #include <sofia-sip/su_os_nw.h>
43 #endif
44 #ifndef SOA_H
45 #include "sofia-sip/soa.h"
46 #endif
47 #ifndef NTA_H
48 #include <sofia-sip/nta.h>
49 #endif
50 #ifndef AUTH_CLIENT_H
51 #include <sofia-sip/auth_client.h>
52 #endif
53 #ifndef NEA_H
54 #include <sofia-sip/nea.h>
55 #endif
56 #ifndef NUA_H
57 #include <sofia-sip/nua.h>
58 #endif
59 
60 #define SU_LOG (nua_log)
61 #include <sofia-sip/su_debug.h>
62 
63 #ifndef NUA_DIALOG_H
64 #define NUA_OWNER_T struct nua_handle_s
65 #include "nua_dialog.h"
66 #endif
67 
68 SOFIA_BEGIN_DECLS
69 
70 #if HAVE_SIGCOMP
71 #include <sigcomp.h>
72 #endif
73 
74 #ifndef NUA_PARAMS_H
75 #include "nua_params.h"
76 #endif
77 
78 typedef struct event_s event_t, nua_signal_data_t;
79 
80 /** Extended event data. */
81 typedef struct nua_ee_data {
82   nua_t *ee_nua;
83   nua_event_data_t ee_data[1];
84 } nua_ee_data_t;
85 
86 #ifndef _MSC_VER
87 #define       NONE ((void *)-1)
88 #else
89 #define       NONE ((void *)(INT_PTR)-1)
90 #endif
91 
92 typedef struct register_usage nua_registration_t;
93 
94 #define \
95   NH_ACTIVE_MEDIA_TAGS(include, soa)					\
96   TAG_IF((include) && (soa) && soa_is_audio_active(soa) >= 0,		\
97 	 SOATAG_ACTIVE_AUDIO(soa_is_audio_active(soa))),		\
98   TAG_IF((include) && (soa) && soa_is_video_active(soa) >= 0,		\
99 	 SOATAG_ACTIVE_VIDEO(soa_is_video_active(soa))),		\
100   TAG_IF((include) && (soa) && soa_is_image_active(soa) >= 0,		\
101 	 SOATAG_ACTIVE_IMAGE(soa_is_image_active(soa))),		\
102   TAG_IF((include) && (soa) && soa_is_chat_active(soa) >= 0,		\
103 	 SOATAG_ACTIVE_CHAT(soa_is_chat_active(soa)))
104 
105 #define \
106   NH_REMOTE_MEDIA_TAGS(include, soa)					\
107   TAG_IF((include) && (soa) && soa_is_remote_audio_active(soa) >= 0,	\
108 	 SOATAG_ACTIVE_AUDIO(soa_is_remote_audio_active(soa))),		\
109   TAG_IF((include) && (soa) && soa_is_remote_video_active(soa) >= 0,	\
110 	 SOATAG_ACTIVE_VIDEO(soa_is_remote_video_active(soa))),		\
111   TAG_IF((include) && (soa) && soa_is_remote_image_active(soa) >= 0,	\
112 	 SOATAG_ACTIVE_IMAGE(soa_is_remote_image_active(soa))),		\
113   TAG_IF((include) && (soa) && soa_is_remote_chat_active(soa) >= 0,	\
114 	 SOATAG_ACTIVE_CHAT(soa_is_remote_chat_active(soa)))
115 
116 /** @internal @brief NUA handle.
117  *
118  */
119 struct nua_handle_s
120 {
121   su_home_t       nh_home[1];	/**< Memory home  */
122   nua_handle_t   *nh_next;
123   nua_handle_t  **nh_prev;
124 
125   nua_t        	 *nh_nua;	/**< Pointer to NUA object  */
126   void           *nh_valid;	/**< Cookie */
127 #define nua_valid_handle_cookie ((void *)(intptr_t)nua_handle)
128   nua_hmagic_t 	 *nh_magic;	/**< Application context */
129 
130   tagi_t         *nh_tags;	/**< Initial tags */
131   tagi_t         *nh_ptags;	/**< Initial parameters */
132 
133   nua_handle_t   *nh_identity;	/**< Identity */
134 
135   nua_handle_preferences_t *nh_prefs; /**< Preferences */
136 #define nh_dprefs nh_nua->nua_dhandle->nh_prefs
137 
138   /* Handle type is determined by special event and flags. */
139   nua_event_t     nh_special;	/**< Special event */
140   unsigned        nh_has_invite:1;     /**< Has call */
141   unsigned        nh_has_subscribe:1;  /**< Has watcher */
142   unsigned        nh_has_notify:1;     /**< Has notifier */
143   unsigned        nh_has_register:1;   /**< Has registration */
144 
145   /* Call status */
146   unsigned        nh_active_call:1;
147   unsigned        nh_hold_remote:1;
148 
149   unsigned        nh_ref_by_stack:1;	/**< Has stack used the handle? */
150   unsigned        nh_ref_by_user:1;	/**< Has user used the handle? */
151   unsigned        nh_init:1;	        /**< Handle has been initialized */
152   unsigned        nh_used_ptags:1;	/**< Ptags has been used */
153   unsigned        nh_destroyed:1;	/**< nh_destroy already called */
154   unsigned :0;
155 
156   nua_dialog_state_t nh_ds[1];
157 
158   auth_client_t  *nh_auth;	/**< Authorization objects */
159 
160   soa_session_t  *nh_soa;	/**< Media session */
161 
162   struct nua_referral {
163     nua_handle_t  *ref_handle;	/**< Referring handle */
164     sip_event_t   *ref_event;	/**< Event used with NOTIFY */
165   } nh_referral[1];
166 
167   nea_server_t   *nh_notifier;	/**< SIP notifier */
168 };
169 
170 #define NH_IS_VALID(nh) \
171   ((nh) && (nh)->nh_valid == nua_valid_handle_cookie)
172 
173 #define NH_STATUS(nh) \
174   (nh)->nh_status, \
175   (nh)->nh_phrase, \
176   SIPTAG_WARNING_STR(nh->nh_warning)
177 
178 #define NH_IS_DEFAULT(nh) ((nh) == (nh)->nh_nua->nua_handles)
179 
180 su_inline
nh_is_special(nua_handle_t * nh)181 int nh_is_special(nua_handle_t *nh)
182 {
183   return nh == NULL || nh->nh_special;
184 }
185 
186 typedef struct nua_event_frame_s nua_event_frame_t;
187 
188 extern char const nua_internal_error[];
189 
190 #define NUA_INTERNAL_ERROR 900, nua_internal_error
191 #define _NUA_INTERNAL_ERROR_AT(file, line) "Internal error at " file ":" #line
192 #define NUA_ERROR_AT(file, line) 900, _NUA_INTERNAL_ERROR_AT(file, line)
193 
194 struct nua_s {
195   su_home_t            nua_home[1];
196 
197   /* API (client) side */
198   su_root_t    	      *nua_api_root;
199   su_clone_r   	       nua_clone;
200   su_task_r            nua_client;
201 
202   nua_callback_f       nua_callback;
203   nua_magic_t         *nua_magic;
204 
205   nua_event_frame_t   *nua_current;
206   nua_saved_event_t    nua_signal[1];
207 
208   /**< Used by stop-and-wait args calls */
209   tagi_t const        *nua_args;
210 
211   /* Engine state flags */
212   sip_time_t           nua_shutdown;
213 
214   unsigned             nua_shutdown_started:1; /**< Shutdown initiated */
215   unsigned             nua_shutdown_final:1; /**< Shutdown is complete */
216 
217   unsigned             nua_from_is_set;
218   unsigned :0;
219 
220   /**< Local SIP address. Contents are kept around for ever. */
221   sip_from_t           nua_from[1];
222 
223   /* ---------------------------------------------------------------------- */
224 
225   /* Protocol (server) side */
226   su_network_changed_t *nua_nw_changed;
227 
228   nua_registration_t *nua_registrations; /**< Active registrations */
229 
230   /* Constants */
231   sip_accept_t       *nua_invite_accept; /* What we accept for invite */
232 
233   su_root_t          *nua_root;
234   su_task_r           nua_server;
235   nta_agent_t        *nua_nta;
236   su_timer_t         *nua_timer;
237 
238   /* User-agent parameters */
239   nua_global_preferences_t nua_prefs[1];
240 
241   nua_handle_t        *nua_handles;
242   nua_handle_t       **nua_handles_tail;
243 };
244 
245 #define nua_dhandle    nua_handles
246 
247 #if HAVE_FUNC
248 #define enter (void)SU_DEBUG_9(("nua: %s: entering\n", __func__))
249 #define nh_enter (void)SU_DEBUG_9(("nua %s(%p): entering\n", __func__, nh))
250 #elif HAVE_FUNCTION
251 #define enter (void)SU_DEBUG_9(("nua: %s: entering\n", __FUNCTION__))
252 #define nh_enter (void)SU_DEBUG_9(("nua %s(%p): entering\n", __FUNCTION__, nh))
253 #define __func__ __FUNCTION__
254 #else
255 #define enter ((void)0)
256 #define nh_enter ((void)0)
257 #define __func__ "nua"
258 #endif
259 
260 #if HAVE_MEMLEAK_LOG
261 
262 #define nua_handle_ref(nh) \
263   _nua_handle_ref_by((nh), __FILE__, __LINE__, __func__)
264 #define nua_handle_unref(nh) \
265   _nua_handle_unref_by((nh), __FILE__, __LINE__, __func__)
266 
267 nua_handle_t *_nua_handle_ref_by(
268   nua_handle_t *nh, char const *file, unsigned line, char const *by);
269 int _nua_handle_unref_by(
270   nua_handle_t *nh, char const *file, unsigned line, char const *by);
271 
272 #endif
273 
nua_stack_ref(nua_t * nua)274 su_inline nua_t *nua_stack_ref(nua_t *nua)
275 {
276   return (nua_t *)su_home_ref(nua->nua_home);
277 }
278 
nua_stack_unref(nua_t * nua)279 su_inline void nua_stack_unref(nua_t *nua)
280 {
281   su_home_unref(nua->nua_home);
282 }
283 
284 /* Internal prototypes */
285 int  nua_stack_init(su_root_t *root, nua_t *nua);
286 void nua_stack_deinit(su_root_t *root, nua_t *nua);
287 
288 int nua_stack_init_transport(nua_t *nua, tagi_t const *tags);
289 
290 int nua_stack_init_registrations(nua_t *nua);
291 
292 nua_registration_t *nua_registration_by_aor(nua_registration_t const *list,
293 					    sip_from_t const *aor,
294 					    url_t const *remote_uri,
295 					    int only_default);
296 
297 sip_contact_t const *nua_registration_contact(nua_registration_t const *nr);
298 
299 int nua_registration_process_request(nua_registration_t *nr,
300 				     nta_incoming_t *irq,
301 				     sip_t const *sip);
302 
303 void nua_stack_post_signal(nua_handle_t *nh, nua_event_t event,
304 			   tag_type_t tag, tag_value_t value, ...);
305 
306 typedef int nua_stack_signal_handler(nua_t *,
307 				     nua_handle_t *,
308 				     nua_event_t,
309 				     tagi_t const *);
310 
311 void nua_move_signal(nua_saved_signal_t a[1], nua_saved_signal_t b[1]);
312 nua_signal_data_t const *nua_signal_data(nua_saved_signal_t const saved[1]);
313 void nua_destroy_signal(nua_saved_signal_t saved[1]);
314 
315 nua_stack_signal_handler
316   nua_stack_set_params, nua_stack_get_params,
317   nua_stack_register,
318   nua_stack_invite, nua_stack_ack, nua_stack_cancel,
319   nua_stack_bye, nua_stack_info, nua_stack_update,
320   nua_stack_prack,
321   nua_stack_options, nua_stack_publish, nua_stack_message,
322   nua_stack_subscribe, nua_stack_notify, nua_stack_refer,
323   nua_stack_method;
324 
325 #define UA_EVENT1(e, statusphrase) \
326   nua_stack_event(nua, nh, NULL, e, statusphrase, NULL)
327 
328 #define UA_EVENT2(e, status, phrase)			\
329   nua_stack_event(nua, nh, NULL, e, status, phrase, NULL)
330 
331 #define UA_EVENT3(e, status, phrase, tag)			\
332   nua_stack_event(nua, nh, NULL, e, status, phrase, tag, NULL)
333 
334 int nua_stack_tevent(nua_t *nua, nua_handle_t *nh, msg_t *msg,
335 		     nua_event_t event, int status, char const *phrase,
336 		     tag_type_t tag, tag_value_t value, ...);
337 
338 int nua_stack_event(nua_t *nua, nua_handle_t *nh, msg_t *msg,
339 		    nua_event_t event, int status, char const *phrase,
340 		    tagi_t const *tags);
341 
342 su_msg_t *nua_current_msg(nua_t const *nua, int clear);
343 
344 void nua_move_event(nua_saved_event_t a[1], nua_saved_event_t b[1]);
345 
346 nua_handle_t *nh_create_handle(nua_t *nua, nua_hmagic_t *hmagic, tagi_t *tags);
347 
348 nua_handle_t *nua_stack_incoming_handle(nua_t *nua,
349 					nta_incoming_t *irq,
350 					sip_t const *sip,
351 					int create_dialog);
352 
353 int nua_stack_init_handle(nua_t *nua, nua_handle_t *nh, tagi_t const *tags);
354 
355 enum nh_kind {
356   nh_has_nothing,
357   nh_has_invite,
358   nh_has_subscribe,
359   nh_has_notify,
360   nh_has_register,
361   nh_has_streaming
362 };
363 
364 int nua_stack_set_handle_special(nua_handle_t *nh,
365 				 enum nh_kind kind,
366 				 nua_event_t special);
367 
368 int nua_handle_save_tags(nua_handle_t *h, tagi_t *tags);
369 
370 void nh_destroy(nua_t *nua, nua_handle_t *nh);
371 
372 nua_handle_t *nh_validate(nua_t *nua, nua_handle_t *maybe);
373 
374 sip_replaces_t *nua_stack_handle_make_replaces(nua_handle_t *handle,
375 					       su_home_t *home,
376 					       int early_only);
377 
378 nua_handle_t *nua_stack_handle_by_replaces(nua_t *nua,
379 					   sip_replaces_t const *r);
380 
381 nua_handle_t *nua_stack_handle_by_call_id(nua_t *nua, const char *call_id);
382 
383 
384 /* ---------------------------------------------------------------------- */
385 
386 int nua_stack_set_defaults(nua_handle_t *nh, nua_handle_preferences_t *nhp);
387 
388 int nua_stack_set_from(nua_t *, int initial, tagi_t const *tags);
389 
390 int nua_stack_init_instance(nua_handle_t *nh, tagi_t const *tags);
391 
392 int nua_stack_process_request(nua_handle_t *nh,
393 			      nta_leg_t *leg,
394 			      nta_incoming_t *irq,
395 			      sip_t const *sip);
396 
397 int nua_stack_launch_network_change_detector(nua_t *nua);
398 
399 sip_contact_t const *nua_stack_get_contact(nua_registration_t const *nr);
400 
401 int nua_registration_add_contact_to_request(nua_handle_t *nh,
402 					    msg_t *msg,
403 					    sip_t *sip,
404 					    int add_contact,
405 					    int add_service_route);
406 
407 int nua_registration_add_contact_to_response(nua_handle_t *nh,
408 					     msg_t *msg,
409 					     sip_t *sip,
410 					     sip_record_route_t const *,
411 					     sip_contact_t const *remote);
412 
413 /* ---------------------------------------------------------------------- */
414 
415 #ifndef SDP_MIME_TYPE
416 #define SDP_MIME_TYPE nua_application_sdp
417 #endif
418 
419 extern char const nua_application_sdp[];
420 
421 /* ---------------------------------------------------------------------- */
422 
423 #define SIP_METHOD_UNKNOWN sip_method_unknown, NULL
424 
425 /* Private tags */
426 #define NUTAG_ADD_CONTACT(v) _nutag_add_contact, tag_bool_v(v)
427 extern tag_typedef_t _nutag_add_contact;
428 
429 /* ---------------------------------------------------------------------- */
430 
431 #define SET_STATUS(_status, _phrase) status = _status, phrase = _phrase
432 
433 #define SET_STATUS2(_status, _phrase) status = _status, phrase = _phrase
434 
435 /* This is an "interesting" macro:
436  * x is a define expanding to <i>num, str</i>.
437  * @a num is assigned to variable status, @a str to variable phrase.
438  * Macro SET_STATUS1 expands to two comma-separated expressions that are
439  * also usable as function arguments.
440  */
441 #define SET_STATUS1(x) ((status = x), status), (phrase = ((void)x))
442 
443 /* ---------------------------------------------------------------------- */
444 /* Application side prototypes */
445 
446 int nua_signal(nua_t *nua, nua_handle_t *nh, msg_t *msg,
447 	       nua_event_t event, int status, char const *phrase,
448 	       tag_type_t tag, tag_value_t value, ...);
449 
450 SOFIA_END_DECLS
451 
452 #endif /* NUA_STACK_H */
453