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