File: | libsofia-sip-ua/nua/nua_server.c |
Warning: | line 179, column 4 Although the value stored to 'status' is used in the enclosing expression, the value is never actually read from 'status' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | /**@CFILE nua_server.c |
26 | * @brief Server transaction handling |
27 | * |
28 | * @author Pekka Pessi <Pekka.Pessi@nokia.com> |
29 | * |
30 | * @date Created: Tue Feb 3 16:10:45 EET 2009 |
31 | */ |
32 | |
33 | #include "config.h" |
34 | |
35 | #include <stddef.h> |
36 | #include <stdlib.h> |
37 | #include <string.h> |
38 | #include <limits.h> |
39 | |
40 | #include <assert.h> |
41 | |
42 | #include <sofia-sip/su_string.h> |
43 | #include <sofia-sip/su_tagarg.h> |
44 | |
45 | #include <sofia-sip/sip_protos.h> |
46 | #include <sofia-sip/sip_status.h> |
47 | #include <sofia-sip/sip_util.h> |
48 | |
49 | #define NUA_SAVED_EVENT_Tsu_msg_t * su_msg_t * |
50 | #define NUA_SAVED_SIGNAL_Tsu_msg_t * su_msg_t * |
51 | |
52 | #include <sofia-sip/su_wait.h> |
53 | |
54 | #include "nua_stack.h" |
55 | #include "nua_dialog.h" |
56 | #include "nua_server.h" |
57 | #include "nua_params.h" |
58 | |
59 | /* ======================================================================== */ |
60 | /* |
61 | * Process incoming requests |
62 | */ |
63 | |
64 | nua_server_methods_t const *nua_server_methods[] = { |
65 | /* These must be in same order as in sip_method_t */ |
66 | &nua_extension_server_methods, |
67 | &nua_invite_server_methods, /**< INVITE */ |
68 | NULL((void*)0), /**< ACK */ |
69 | NULL((void*)0), /**< CANCEL */ |
70 | &nua_bye_server_methods, /**< BYE */ |
71 | &nua_options_server_methods, /**< OPTIONS */ |
72 | &nua_register_server_methods, /**< REGISTER */ |
73 | &nua_info_server_methods, /**< INFO */ |
74 | &nua_prack_server_methods, /**< PRACK */ |
75 | &nua_update_server_methods, /**< UPDATE */ |
76 | &nua_message_server_methods, /**< MESSAGE */ |
77 | &nua_subscribe_server_methods,/**< SUBSCRIBE */ |
78 | &nua_notify_server_methods, /**< NOTIFY */ |
79 | &nua_refer_server_methods, /**< REFER */ |
80 | &nua_publish_server_methods, /**< PUBLISH */ |
81 | NULL((void*)0) |
82 | }; |
83 | |
84 | |
85 | int nua_stack_process_request(nua_handle_t *nh, |
86 | nta_leg_t *leg, |
87 | nta_incoming_t *irq, |
88 | sip_t const *sip) |
89 | { |
90 | nua_t *nua = nh->nh_nua; |
91 | sip_method_t method = sip->sip_request->rq_method; |
92 | char const *name = sip->sip_request->rq_method_name; |
93 | nua_server_methods_t const *sm; |
94 | nua_server_request_t *sr, sr0[1]; |
95 | int status, initial = 1; |
96 | int create_dialog; |
97 | |
98 | char const *user_agent = NH_PGET(nh, user_agent)(((nh)->nh_prefs)->nhp_set_.set_bits.nhb_user_agent ? ( (nh)->nh_prefs)->nhp_user_agent : ((nh)->nh_nua-> nua_handles->nh_prefs)->nhp_user_agent); |
99 | sip_supported_t const *supported = NH_PGET(nh, supported)(((nh)->nh_prefs)->nhp_set_.set_bits.nhb_supported ? (( nh)->nh_prefs)->nhp_supported : ((nh)->nh_nua->nua_handles ->nh_prefs)->nhp_supported); |
100 | sip_allow_t const *allow = NH_PGET(nh, allow)(((nh)->nh_prefs)->nhp_set_.set_bits.nhb_allow ? ((nh)-> nh_prefs)->nhp_allow : ((nh)->nh_nua->nua_handles-> nh_prefs)->nhp_allow); |
101 | |
102 | enter(void)((((nua_log) != ((void*)0) && (nua_log)->log_init ) == 0 ? 9 : (((nua_log) != ((void*)0) && (nua_log)-> log_init > 1) ? (nua_log)->log_level : su_log_default-> log_level)) >= 9 ? (_su_llog((nua_log), 9, "nua_server.c", (const char *)__func__, 102, "nua: %s: entering\n", __func__ )) : (void)0); |
103 | |
104 | nta_incoming_tag(irq, NULL((void*)0)); |
105 | |
106 | if (method == sip_method_cancel) |
107 | return 481; |
108 | |
109 | /* Hook to outbound */ |
110 | if (method == sip_method_options) { |
111 | status = nua_registration_process_request(nua->nua_registrations, |
112 | irq, sip); |
113 | if (status) |
114 | return status; |
115 | } |
116 | |
117 | if (nta_check_method(irq, sip, allow, |
118 | SIPTAG_SUPPORTED(supported)siptag_supported, siptag_supported_v(supported), |
119 | SIPTAG_USER_AGENT_STR(user_agent)siptag_user_agent_str, tag_str_v(user_agent), |
120 | TAG_END()(tag_type_t)0, (tag_value_t)0)) |
121 | return 405; |
122 | |
123 | switch (sip->sip_request->rq_url->url_type) { |
124 | case url_sip: |
125 | case url_urn: |
126 | case url_sips: |
127 | case url_im: |
128 | case url_pres: |
129 | case url_tel: |
130 | break; |
131 | default: |
132 | nta_incoming_treply(irq, status = SIP_416_UNSUPPORTED_URI416, sip_416_Unsupported_uri, |
133 | SIPTAG_ALLOW(allow)siptag_allow, siptag_allow_v(allow), |
134 | SIPTAG_SUPPORTED(supported)siptag_supported, siptag_supported_v(supported), |
135 | SIPTAG_USER_AGENT_STR(user_agent)siptag_user_agent_str, tag_str_v(user_agent), |
136 | TAG_END()(tag_type_t)0, (tag_value_t)0); |
137 | return status; |
138 | } |
139 | |
140 | if (nta_check_required(irq, sip, supported, |
141 | SIPTAG_ALLOW(allow)siptag_allow, siptag_allow_v(allow), |
142 | SIPTAG_USER_AGENT_STR(user_agent)siptag_user_agent_str, tag_str_v(user_agent), |
143 | TAG_END()(tag_type_t)0, (tag_value_t)0)) |
144 | return 420; |
145 | |
146 | if (method > sip_method_unknown && method <= sip_method_publish) |
147 | sm = nua_server_methods[method]; |
148 | else |
149 | sm = nua_server_methods[0]; |
150 | |
151 | initial = nh == nua->nua_dhandlenua_handles; |
152 | |
153 | if (sm == NULL((void*)0)) { |
154 | SU_DEBUG_1(("nua(%p): strange %s from <" URL_PRINT_FORMAT ">\n",((((nua_log) != ((void*)0) && (nua_log)->log_init) == 0 ? 9 : (((nua_log) != ((void*)0) && (nua_log)-> log_init > 1) ? (nua_log)->log_level : su_log_default-> log_level)) >= 1 ? (_su_llog((nua_log), 1, "nua_server.c", (const char *)__func__, 156, "nua(%p): strange %s from <" "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s" ">\n", (void *)nh, sip->sip_request->rq_method_name, (sip->sip_from-> a_url)->url_scheme ? (sip->sip_from->a_url)->url_scheme : "", (sip->sip_from->a_url)->url_type != url_any && (sip->sip_from->a_url)->url_scheme && (sip-> sip_from->a_url)->url_scheme[0] ? ":" : "", (sip->sip_from ->a_url)->url_root && ((sip->sip_from->a_url )->url_host || (sip->sip_from->a_url)->url_user) ? "//" : "", (sip->sip_from->a_url)->url_user ? (sip-> sip_from->a_url)->url_user : "", (sip->sip_from-> a_url)->url_user && (sip->sip_from->a_url)-> url_password ? ":" : "", (sip->sip_from->a_url)->url_user && (sip->sip_from->a_url)->url_password ? ( sip->sip_from->a_url)->url_password : "", (sip->sip_from ->a_url)->url_user && (sip->sip_from->a_url )->url_host ? "@" : "", (sip->sip_from->a_url)->url_host ? (sip->sip_from->a_url)->url_host : "", (sip->sip_from ->a_url)->url_host && (sip->sip_from->a_url )->url_port ? ":" : "", (sip->sip_from->a_url)->url_host && (sip->sip_from->a_url)->url_port ? (sip-> sip_from->a_url)->url_port : "", (sip->sip_from-> a_url)->url_root && (sip->sip_from->a_url)-> url_path ? "/" : "", (sip->sip_from->a_url)->url_path ? (sip->sip_from->a_url)->url_path : "", (sip->sip_from ->a_url)->url_params ? ";" : "", (sip->sip_from-> a_url)->url_params ? (sip->sip_from->a_url)->url_params : "", (sip->sip_from->a_url)->url_headers ? "?" : "" , (sip->sip_from->a_url)->url_headers ? (sip->sip_from ->a_url)->url_headers : "", (sip->sip_from->a_url )->url_fragment ? "#" : "", (sip->sip_from->a_url)-> url_fragment ? (sip->sip_from->a_url)->url_fragment : "")) : (void)0) |
155 | (void *)nh, sip->sip_request->rq_method_name,((((nua_log) != ((void*)0) && (nua_log)->log_init) == 0 ? 9 : (((nua_log) != ((void*)0) && (nua_log)-> log_init > 1) ? (nua_log)->log_level : su_log_default-> log_level)) >= 1 ? (_su_llog((nua_log), 1, "nua_server.c", (const char *)__func__, 156, "nua(%p): strange %s from <" "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s" ">\n", (void *)nh, sip->sip_request->rq_method_name, (sip->sip_from-> a_url)->url_scheme ? (sip->sip_from->a_url)->url_scheme : "", (sip->sip_from->a_url)->url_type != url_any && (sip->sip_from->a_url)->url_scheme && (sip-> sip_from->a_url)->url_scheme[0] ? ":" : "", (sip->sip_from ->a_url)->url_root && ((sip->sip_from->a_url )->url_host || (sip->sip_from->a_url)->url_user) ? "//" : "", (sip->sip_from->a_url)->url_user ? (sip-> sip_from->a_url)->url_user : "", (sip->sip_from-> a_url)->url_user && (sip->sip_from->a_url)-> url_password ? ":" : "", (sip->sip_from->a_url)->url_user && (sip->sip_from->a_url)->url_password ? ( sip->sip_from->a_url)->url_password : "", (sip->sip_from ->a_url)->url_user && (sip->sip_from->a_url )->url_host ? "@" : "", (sip->sip_from->a_url)->url_host ? (sip->sip_from->a_url)->url_host : "", (sip->sip_from ->a_url)->url_host && (sip->sip_from->a_url )->url_port ? ":" : "", (sip->sip_from->a_url)->url_host && (sip->sip_from->a_url)->url_port ? (sip-> sip_from->a_url)->url_port : "", (sip->sip_from-> a_url)->url_root && (sip->sip_from->a_url)-> url_path ? "/" : "", (sip->sip_from->a_url)->url_path ? (sip->sip_from->a_url)->url_path : "", (sip->sip_from ->a_url)->url_params ? ";" : "", (sip->sip_from-> a_url)->url_params ? (sip->sip_from->a_url)->url_params : "", (sip->sip_from->a_url)->url_headers ? "?" : "" , (sip->sip_from->a_url)->url_headers ? (sip->sip_from ->a_url)->url_headers : "", (sip->sip_from->a_url )->url_fragment ? "#" : "", (sip->sip_from->a_url)-> url_fragment ? (sip->sip_from->a_url)->url_fragment : "")) : (void)0) |
156 | URL_PRINT_ARGS(sip->sip_from->a_url)))((((nua_log) != ((void*)0) && (nua_log)->log_init) == 0 ? 9 : (((nua_log) != ((void*)0) && (nua_log)-> log_init > 1) ? (nua_log)->log_level : su_log_default-> log_level)) >= 1 ? (_su_llog((nua_log), 1, "nua_server.c", (const char *)__func__, 156, "nua(%p): strange %s from <" "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s" ">\n", (void *)nh, sip->sip_request->rq_method_name, (sip->sip_from-> a_url)->url_scheme ? (sip->sip_from->a_url)->url_scheme : "", (sip->sip_from->a_url)->url_type != url_any && (sip->sip_from->a_url)->url_scheme && (sip-> sip_from->a_url)->url_scheme[0] ? ":" : "", (sip->sip_from ->a_url)->url_root && ((sip->sip_from->a_url )->url_host || (sip->sip_from->a_url)->url_user) ? "//" : "", (sip->sip_from->a_url)->url_user ? (sip-> sip_from->a_url)->url_user : "", (sip->sip_from-> a_url)->url_user && (sip->sip_from->a_url)-> url_password ? ":" : "", (sip->sip_from->a_url)->url_user && (sip->sip_from->a_url)->url_password ? ( sip->sip_from->a_url)->url_password : "", (sip->sip_from ->a_url)->url_user && (sip->sip_from->a_url )->url_host ? "@" : "", (sip->sip_from->a_url)->url_host ? (sip->sip_from->a_url)->url_host : "", (sip->sip_from ->a_url)->url_host && (sip->sip_from->a_url )->url_port ? ":" : "", (sip->sip_from->a_url)->url_host && (sip->sip_from->a_url)->url_port ? (sip-> sip_from->a_url)->url_port : "", (sip->sip_from-> a_url)->url_root && (sip->sip_from->a_url)-> url_path ? "/" : "", (sip->sip_from->a_url)->url_path ? (sip->sip_from->a_url)->url_path : "", (sip->sip_from ->a_url)->url_params ? ";" : "", (sip->sip_from-> a_url)->url_params ? (sip->sip_from->a_url)->url_params : "", (sip->sip_from->a_url)->url_headers ? "?" : "" , (sip->sip_from->a_url)->url_headers ? (sip->sip_from ->a_url)->url_headers : "", (sip->sip_from->a_url )->url_fragment ? "#" : "", (sip->sip_from->a_url)-> url_fragment ? (sip->sip_from->a_url)->url_fragment : "")) : (void)0); |
157 | } |
158 | else if (initial && sm->sm_flags.in_dialog) { |
159 | /* These must be in-dialog */ |
160 | sm = NULL((void*)0); |
161 | } |
162 | else if (initial && sip->sip_to->a_tag && method != sip_method_subscribe) { |
163 | /* RFC 3261 section 12.2.2: |
164 | |
165 | If the UAS wishes to reject the request because it does not wish to |
166 | recreate the dialog, it MUST respond to the request with a 481 |
167 | (Call/Transaction Does Not Exist) status code and pass that to the |
168 | server transaction. |
169 | */ /* we allow this on subscribes because we have disabled the built-in notify server and we need those messages in the application layer */ |
170 | |
171 | if (method == sip_method_info) |
172 | /* accept out-of-dialog info */; else |
173 | if (method != sip_method_message || !NH_PGET(nh, win_messenger_enable)(((nh)->nh_prefs)->nhp_set_.set_bits.nhb_win_messenger_enable ? ((nh)->nh_prefs)->nhp_win_messenger_enable : ((nh)-> nh_nua->nua_handles->nh_prefs)->nhp_win_messenger_enable )) |
174 | sm = NULL((void*)0); |
175 | } |
176 | |
177 | if (!sm) { |
178 | nta_incoming_treply(irq, |
179 | status = 481, "Call Does Not Exist", |
Although the value stored to 'status' is used in the enclosing expression, the value is never actually read from 'status' | |
180 | SIPTAG_ALLOW(allow)siptag_allow, siptag_allow_v(allow), |
181 | SIPTAG_SUPPORTED(supported)siptag_supported, siptag_supported_v(supported), |
182 | SIPTAG_USER_AGENT_STR(user_agent)siptag_user_agent_str, tag_str_v(user_agent), |
183 | TAG_END()(tag_type_t)0, (tag_value_t)0); |
184 | return 481; |
185 | } |
186 | |
187 | create_dialog = sm->sm_flags.create_dialog; |
188 | if (method == sip_method_message && NH_PGET(nh, win_messenger_enable)(((nh)->nh_prefs)->nhp_set_.set_bits.nhb_win_messenger_enable ? ((nh)->nh_prefs)->nhp_win_messenger_enable : ((nh)-> nh_nua->nua_handles->nh_prefs)->nhp_win_messenger_enable )) |
189 | create_dialog = 1; |
190 | sr = memset(sr0, 0, (sizeof sr0)); |
191 | |
192 | sr->sr_methods = sm; |
193 | sr->sr_method = method = sip->sip_request->rq_method; |
194 | sr->sr_add_contact = sm->sm_flags.add_contact; |
195 | sr->sr_target_refresh = sm->sm_flags.target_refresh; |
196 | |
197 | sr->sr_owner = nh; |
198 | sr->sr_initial = initial; |
199 | |
200 | sr->sr_irq = irq; |
201 | |
202 | SR_STATUS1(sr, SIP_100_TRYING)sr_status(sr, 100, sip_100_Trying); |
203 | |
204 | sr->sr_request.msg = nta_incoming_getrequest(irq); |
205 | sr->sr_request.sip = sip; |
206 | assert(sr->sr_request.msg)((void) sizeof ((sr->sr_request.msg) ? 1 : 0), __extension__ ({ if (sr->sr_request.msg) ; else __assert_fail ("sr->sr_request.msg" , "nua_server.c", 206, __extension__ __PRETTY_FUNCTION__); }) ); |
207 | |
208 | sr->sr_response.msg = nta_incoming_create_response(irq, 0, NULL((void*)0)); |
209 | sr->sr_response.sip = sip_object(sr->sr_response.msg); |
210 | |
211 | if (sr->sr_response.msg == NULL((void*)0)) { |
212 | SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR)sr_status(sr, 500, sip_500_Internal_server_error); |
213 | } |
214 | else if (sm->sm_init && sm->sm_init(sr)) { |
215 | if (sr->sr_status < 200) /* Init may have set response status */ |
216 | SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR)sr_status(sr, 500, sip_500_Internal_server_error); |
217 | } |
218 | /* Create handle if request does not fail */ |
219 | else if (initial && sr->sr_status < 300) { |
220 | if ((nh = nua_stack_incoming_handle(nua, irq, sip, create_dialog))) |
221 | sr->sr_owner = nh; |
222 | else |
223 | SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR)sr_status(sr, 500, sip_500_Internal_server_error); |
224 | } |
225 | |
226 | if (sr->sr_status < 300 && sm->sm_preprocess && sm->sm_preprocess(sr)) { |
227 | if (sr->sr_status < 200) /* Set response status if preprocess did not */ |
228 | SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR)sr_status(sr, 500, sip_500_Internal_server_error); |
229 | } |
230 | |
231 | if (sr->sr_status < 300) { |
232 | if (sr->sr_target_refresh) |
233 | nua_dialog_uas_route(nh, nh->nh_ds, sip, 1); /* Set route and tags */ |
234 | nua_dialog_store_peer_info(nh, nh->nh_ds, sip); |
235 | } |
236 | |
237 | if (sr->sr_status == 100 && method != sip_method_unknown && |
238 | !sip_is_allowed(NH_PGET(sr->sr_owner, appl_method)(((sr->sr_owner)->nh_prefs)->nhp_set_.set_bits.nhb_appl_method ? ((sr->sr_owner)->nh_prefs)->nhp_appl_method : ((sr ->sr_owner)->nh_nua->nua_handles->nh_prefs)->nhp_appl_method ), method, name)) { |
239 | if (method == sip_method_refer || method == sip_method_subscribe) |
240 | SR_STATUS1(sr, SIP_202_ACCEPTED)sr_status(sr, 202, sip_202_Accepted); |
241 | else |
242 | SR_STATUS1(sr, SIP_200_OK)sr_status(sr, 200, sip_200_OK); |
243 | } |
244 | |
245 | /* INVITE server request is not finalized after 2XX response */ |
246 | if (sr->sr_status < (method == sip_method_invite ? 300 : 200)) { |
247 | sr = su_alloc(nh->nh_home, (sizeof *sr)); |
248 | |
249 | if (sr) { |
250 | *sr = *sr0; |
251 | |
252 | if ((sr->sr_next = nh->nh_ds->ds_sr)) |
253 | *(sr->sr_prev = sr->sr_next->sr_prev) = sr, |
254 | sr->sr_next->sr_prev = &sr->sr_next; |
255 | else |
256 | *(sr->sr_prev = &nh->nh_ds->ds_sr) = sr; |
257 | } |
258 | else { |
259 | sr = sr0; |
260 | SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR)sr_status(sr, 500, sip_500_Internal_server_error); |
261 | } |
262 | } |
263 | |
264 | if (sr->sr_status <= 100) { |
265 | SR_STATUS1(sr, SIP_100_TRYING)sr_status(sr, 100, sip_100_Trying); |
266 | if ((method == sip_method_invite && nh->nh_prefs->nhp_auto_invite_100) || |
267 | sip->sip_timestamp) { |
268 | nta_incoming_treply(irq, SIP_100_TRYING100, sip_100_Trying, |
269 | SIPTAG_USER_AGENT_STR(user_agent)siptag_user_agent_str, tag_str_v(user_agent), |
270 | TAG_END()(tag_type_t)0, (tag_value_t)0); |
271 | |
272 | } |
273 | } |
274 | else { |
275 | /* Note that this may change the sr->sr_status */ |
276 | nua_server_respond(sr, NULL((void*)0)); |
277 | } |
278 | |
279 | if (nua_server_report(sr) == 0) |
280 | return 0; |
281 | |
282 | return 501; |
283 | } |
284 | |
285 | #undef nua_base_server_init |
286 | #undef nua_base_server_preprocess |
287 | |
288 | int nua_base_server_init(nua_server_request_t *sr) |
289 | { |
290 | return 0; |
291 | } |
292 | |
293 | int nua_base_server_preprocess(nua_server_request_t *sr) |
294 | { |
295 | return 0; |
296 | } |
297 | |
298 | void nua_server_request_destroy(nua_server_request_t *sr) |
299 | { |
300 | nua_server_request_t *sr0 = NULL((void*)0); |
301 | |
302 | if (sr == NULL((void*)0)) |
303 | return; |
304 | |
305 | if (SR_HAS_SAVED_SIGNAL(sr)((sr)->sr_signal[0] != ((void*)0))) |
306 | nua_destroy_signal(sr->sr_signal); |
307 | |
308 | if (sr->sr_prev) { |
309 | /* Allocated from heap */ |
310 | if ((*sr->sr_prev = sr->sr_next)) |
311 | sr->sr_next->sr_prev = sr->sr_prev; |
312 | sr0 = sr; |
313 | } |
314 | |
315 | if (sr->sr_irq) { |
316 | nta_incoming_t *irq = sr->sr_irq; |
317 | if (sr->sr_method == sip_method_bye && sr->sr_status < 200) { |
318 | nta_incoming_treply(sr->sr_irq, SIP_200_OK200, sip_200_OK, TAG_END()(tag_type_t)0, (tag_value_t)0); |
319 | } |
320 | sr->sr_irq = NULL((void*)0); |
321 | nta_incoming_destroy(irq); |
322 | } |
323 | |
324 | if (sr->sr_request.msg) { |
325 | msg_t *msg = sr->sr_request.msg; |
326 | sr->sr_request.msg = NULL((void*)0); |
327 | msg_destroy(msg); |
328 | } |
329 | |
330 | if (sr->sr_response.msg) { |
331 | msg_t *msg = sr->sr_response.msg; |
332 | sr->sr_response.msg = NULL((void*)0); |
333 | msg_destroy(msg); |
334 | } |
335 | |
336 | if (sr0) su_free(sr->sr_owner->nh_home, sr0); |
337 | } |
338 | |
339 | /**@fn void nua_respond(nua_handle_t *nh, int status, char const *phrase, tag_type_t tag, tag_value_t value, ...); |
340 | * |
341 | * Respond to a request with given status code and phrase. |
342 | * |
343 | * The stack returns a SIP response message with given status code and |
344 | * phrase to the client. The tagged parameter list can specify extra headers |
345 | * to include with the response message and other stack parameters. The SIP |
346 | * session or other protocol state associated with the handle is updated |
347 | * accordingly (for instance, if an initial INVITE is responded with 200, a |
348 | * SIP session is established.) |
349 | * |
350 | * When responding to an incoming INVITE request, the nua_respond() can be |
351 | * called without NUTAG_WITH() (or NUTAG_WITH_CURRENT() or |
352 | * NUTAG_WITH_SAVED()). Otherwise, NUTAG_WITH() will contain an indication |
353 | * of the request being responded. |
354 | * |
355 | * @param nh Pointer to operation handle |
356 | * @param status SIP response status code (see RFCs of SIP) |
357 | * @param phrase free text (default response phrase is used if NULL) |
358 | * @param tag, value, ... List of tagged parameters |
359 | * |
360 | * @return |
361 | * nothing |
362 | * |
363 | * @par Responses by Protocol Engine |
364 | * |
365 | * When nua protocol engine receives an incoming SIP request, it can either |
366 | * respond to the request automatically or let application to respond to the |
367 | * request. The automatic response is returned to the client if the request |
368 | * fails syntax check, or the method, SIP extension or content negotiation |
369 | * fails. |
370 | * |
371 | * When the @ref nua_handlingevents "request event" is delivered to the |
372 | * application, the application should examine the @a status parameter. The |
373 | * @a status parameter is 200 or greater if the request has been already |
374 | * responded automatically by the stack. |
375 | * |
376 | * The application can add methods that it likes to handle by itself with |
377 | * NUTAG_APPL_METHOD(). The default set of NUTAG_APPL_METHOD() includes |
378 | * INVITE, PUBLISH, REGISTER and SUBSCRIBE. Note that unless the method is |
379 | * also included in the set of allowed methods with NUTAG_ALLOW(), the stack |
380 | * will respond to the incoming methods with <i>405 Not Allowed</i>. |
381 | * |
382 | * In order to simplify the simple applications, most requests are responded |
383 | * automatically. The BYE and CANCEL requests are always responded by the |
384 | * stack. Likewise, the NOTIFY requests associated with an event |
385 | * subscription are responded by the stack. |
386 | * |
387 | * Note that certain methods are rejected outside a SIP session (created |
388 | * with INVITE transaction). They include BYE, UPDATE, PRACK and INFO. Also |
389 | * the auxiliary methods ACK and CANCEL are rejected by the stack if there |
390 | * is no ongoing INVITE transaction corresponding to them. |
391 | * |
392 | * @par Related Tags: |
393 | * NUTAG_WITH(), NUTAG_WITH_THIS(), NUTAG_WITH_SAVED() \n |
394 | * NUTAG_EARLY_ANSWER() \n |
395 | * SOATAG_ADDRESS() \n |
396 | * SOATAG_AF() \n |
397 | * SOATAG_HOLD() \n |
398 | * Tags used with nua_set_hparams() \n |
399 | * Header tags defined in <sofia-sip/sip_tag.h>. |
400 | * |
401 | * @par Events: |
402 | * #nua_i_state \n |
403 | * #nua_i_media_error \n |
404 | * #nua_i_error \n |
405 | * #nua_i_active \n |
406 | * #nua_i_terminated \n |
407 | * |
408 | * @sa #nua_i_invite, #nua_i_register, #nua_i_subscribe, #nua_i_publish |
409 | */ |
410 | |
411 | void |
412 | nua_stack_respond(nua_t *nua, nua_handle_t *nh, |
413 | int status, char const *phrase, tagi_t const *tags) |
414 | { |
415 | nua_server_request_t *sr; |
416 | tagi_t const *t; |
417 | msg_t const *request = NULL((void*)0); |
418 | |
419 | t = tl_find_last(tags, nutag_with); |
420 | |
421 | if (t) |
422 | request = (msg_t const *)t->t_value; |
423 | |
424 | for (sr = nh->nh_ds->ds_sr; sr; sr = sr->sr_next) { |
425 | if (request && sr->sr_request.msg == request) |
426 | break; |
427 | /* nua_respond() to INVITE can be used without NUTAG_WITH() */ |
428 | if (!t && sr->sr_method == sip_method_invite) |
429 | break; |
430 | } |
431 | |
432 | if (sr == NULL((void*)0)) { |
433 | nua_stack_event(nua, nh, NULL((void*)0), nua_i_error, |
434 | 500, "Responding to a Non-Existing Request", NULL((void*)0)); |
435 | return; |
436 | } |
437 | else if (!nua_server_request_is_pending(sr)) { |
438 | nua_stack_event(nua, nh, NULL((void*)0), nua_i_error, |
439 | 500, "Already Sent Final Response", NULL((void*)0)); |
440 | return; |
441 | } |
442 | else if (sr->sr_100rel && !sr->sr_pracked && 200 <= status && status < 300) { |
443 | /* Save signal until we have received PRACK */ |
444 | if (tags && nua_stack_set_params(nua, nh, nua_i_none, tags) < 0) { |
445 | sr->sr_application = status; |
446 | SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR)sr_status(sr, 500, sip_500_Internal_server_error); |
447 | } |
448 | else { |
449 | su_msg_save(sr->sr_signal, nh->nh_nua->nua_signal); |
450 | return; |
451 | } |
452 | } |
453 | else { |
454 | sr->sr_application = status; |
455 | if (tags && nua_stack_set_params(nua, nh, nua_i_none, tags) < 0) |
456 | SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR)sr_status(sr, 500, sip_500_Internal_server_error); |
457 | else { |
458 | sr->sr_status = status, sr->sr_phrase = phrase; |
459 | } |
460 | } |
461 | |
462 | nua_server_params(sr, tags); |
463 | nua_server_respond(sr, tags); |
464 | |
465 | if (!(sr->sr_method == sip_method_invite && status == 100)) { |
466 | /* Since we don't change state, do not notify application when |
467 | we send 100 Trying for INVITE */ |
468 | nua_server_report(sr); |
469 | } |
470 | } |
471 | |
472 | int nua_server_params(nua_server_request_t *sr, tagi_t const *tags) |
473 | { |
474 | if (sr->sr_methods->sm_params) |
475 | return sr->sr_methods->sm_params(sr, tags); |
476 | return 0; |
477 | } |
478 | |
479 | #undef nua_base_server_params |
480 | |
481 | int nua_base_server_params(nua_server_request_t *sr, tagi_t const *tags) |
482 | { |
483 | return 0; |
484 | } |
485 | |
486 | /** Return the response to the client. |
487 | * |
488 | * @retval 0 when successfully sent |
489 | * @retval -1 upon an error |
490 | */ |
491 | int nua_server_trespond(nua_server_request_t *sr, |
492 | tag_type_t tag, tag_value_t value, ...) |
493 | { |
494 | int retval; |
495 | ta_list ta; |
496 | ta_start(ta, tag, value)do { tag_type_t ta_start__tag = (tag); tag_value_t ta_start__value = (value); __builtin_va_start((ta).ap, (value)); while ((ta_start__tag ) == tag_next && (ta_start__value) != 0) { ta_start__tag = ((tagi_t *)ta_start__value)->t_tag; if (ta_start__tag == tag_null || ta_start__tag == ((void*)0)) break; if (ta_start__tag == tag_next) { ta_start__value = ((tagi_t *)ta_start__value) ->t_value; } else { ta_start__tag = tag_next; break; } } ( ta).tl->t_tag = ta_start__tag; (ta).tl->t_value = ta_start__value ; if (ta_start__tag != ((void*)0) && ta_start__tag != tag_null && ta_start__tag != tag_next) { va_list ta_start__ap ; __builtin_va_copy((ta_start__ap), ((ta).ap)); (ta).tl[1].t_tag = tag_next; (ta).tl[1].t_value = (tag_value_t)tl_vlist(ta_start__ap ); __builtin_va_end(ta_start__ap); } else { (ta).tl[1].t_value = 0; (ta).tl[1].t_value = (tag_value_t)0; } } while(0); |
497 | retval = nua_server_respond(sr, ta_args(ta)(ta).tl); |
498 | ta_end(ta)((((ta).tl[1].t_value) ? (tl_vfree((tagi_t *)((ta).tl[1].t_value ))) : (void)0), (ta).tl[1].t_value = 0, __builtin_va_end((ta) .ap)); |
499 | return retval; |
500 | } |
501 | |
502 | /** Return the response to the client. |
503 | * |
504 | * @retval 0 when successfully sent |
505 | * @retval -1 upon an error |
506 | */ |
507 | int nua_server_respond(nua_server_request_t *sr, tagi_t const *tags) |
508 | { |
509 | nua_handle_t *nh = sr->sr_owner; |
510 | nua_dialog_state_t *ds = nh->nh_ds; |
511 | sip_method_t method = sr->sr_method; |
512 | struct { msg_t *msg; sip_t *sip; } next = { NULL((void*)0), NULL((void*)0) }; |
513 | int retval, user_contact = 1; |
514 | #if HAVE_OPEN_C |
515 | /* Nice. And old arm symbian compiler; see below. */ |
516 | tagi_t next_tags[2]; |
517 | #else |
518 | tagi_t next_tags[2] = {{ SIPTAG_END()siptag_end, (tag_value_t)0 }, { TAG_NEXT(tags)tag_next, (tag_value_t)(tags) }}; |
519 | #endif |
520 | |
521 | msg_t *msg = sr->sr_response.msg; |
522 | sip_t *sip = sr->sr_response.sip; |
523 | sip_contact_t *m = sr->sr_request.sip->sip_contact; |
524 | |
525 | #if HAVE_OPEN_C |
526 | next_tags[0].t_tag = siptag_end; |
527 | next_tags[0].t_value = (tag_value_t)0; |
528 | next_tags[1].t_tag = tag_next; |
529 | next_tags[1].t_value = (tag_value_t)(tags); |
530 | #endif |
531 | |
532 | if (sr->sr_response.msg == NULL((void*)0)) { |
533 | //assert(sr->sr_status == 500); |
534 | SU_DEBUG_0(("sr without msg, sr_status=%u", sr->sr_status))((((nua_log) != ((void*)0) && (nua_log)->log_init) == 0 ? 9 : (((nua_log) != ((void*)0) && (nua_log)-> log_init > 1) ? (nua_log)->log_level : su_log_default-> log_level)) >= 0 ? (_su_llog((nua_log), 0, "nua_server.c", (const char *)__func__, 534, "sr without msg, sr_status=%u", sr->sr_status)) : (void)0); |
535 | goto internal_error; |
536 | } |
537 | |
538 | if (sr->sr_status == 100) { |
539 | return nta_incoming_treply(sr->sr_irq, SIP_100_TRYING100, sip_100_Trying, |
540 | SIPTAG_USER_AGENT_STR(NH_PGET(nh, user_agent))siptag_user_agent_str, tag_str_v((((nh)->nh_prefs)->nhp_set_ .set_bits.nhb_user_agent ? ((nh)->nh_prefs)->nhp_user_agent : ((nh)->nh_nua->nua_handles->nh_prefs)->nhp_user_agent )), |
541 | TAG_END()(tag_type_t)0, (tag_value_t)0); |
542 | return 0; |
543 | } |
544 | |
545 | if (sr->sr_status < 200) { |
546 | next.msg = nta_incoming_create_response(sr->sr_irq, 0, NULL((void*)0)); |
547 | next.sip = sip_object(next.msg); |
548 | if (next.sip == NULL((void*)0)) |
549 | SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR)sr_status(sr, 500, sip_500_Internal_server_error); |
550 | } |
551 | |
552 | if (nta_incoming_complete_response(sr->sr_irq, msg, |
553 | sr->sr_status, |
554 | sr->sr_phrase, |
555 | TAG_NEXT(tags)tag_next, (tag_value_t)(tags)) < 0) |
556 | ; |
557 | else if (!sip->sip_supported && NH_PGET(nh, supported)(((nh)->nh_prefs)->nhp_set_.set_bits.nhb_supported ? (( nh)->nh_prefs)->nhp_supported : ((nh)->nh_nua->nua_handles ->nh_prefs)->nhp_supported) && |
558 | sip_add_dup(msg, sip, (sip_header_t *)NH_PGET(nh, supported)(((nh)->nh_prefs)->nhp_set_.set_bits.nhb_supported ? (( nh)->nh_prefs)->nhp_supported : ((nh)->nh_nua->nua_handles ->nh_prefs)->nhp_supported)) < 0) |
559 | ; |
560 | else if (!sip->sip_user_agent && NH_PGET(nh, user_agent)(((nh)->nh_prefs)->nhp_set_.set_bits.nhb_user_agent ? ( (nh)->nh_prefs)->nhp_user_agent : ((nh)->nh_nua-> nua_handles->nh_prefs)->nhp_user_agent) && |
561 | sip_add_make(msg, sip, sip_user_agent_class, |
562 | NH_PGET(nh, user_agent)(((nh)->nh_prefs)->nhp_set_.set_bits.nhb_user_agent ? ( (nh)->nh_prefs)->nhp_user_agent : ((nh)->nh_nua-> nua_handles->nh_prefs)->nhp_user_agent)) < 0) |
563 | ; |
564 | else if (!sip->sip_organization && NH_PGET(nh, organization)(((nh)->nh_prefs)->nhp_set_.set_bits.nhb_organization ? ((nh)->nh_prefs)->nhp_organization : ((nh)->nh_nua-> nua_handles->nh_prefs)->nhp_organization) && |
565 | sip_add_make(msg, sip, sip_organization_class, |
566 | NH_PGET(nh, organization)(((nh)->nh_prefs)->nhp_set_.set_bits.nhb_organization ? ((nh)->nh_prefs)->nhp_organization : ((nh)->nh_nua-> nua_handles->nh_prefs)->nhp_organization)) < 0) |
567 | ; |
568 | else if (!sip->sip_via && NH_PGET(nh, via)(((nh)->nh_prefs)->nhp_set_.set_bits.nhb_via ? ((nh)-> nh_prefs)->nhp_via : ((nh)->nh_nua->nua_handles-> nh_prefs)->nhp_via) && |
569 | sip_add_make(msg, sip, sip_via_class, |
570 | NH_PGET(nh, via)(((nh)->nh_prefs)->nhp_set_.set_bits.nhb_via ? ((nh)-> nh_prefs)->nhp_via : ((nh)->nh_nua->nua_handles-> nh_prefs)->nhp_via)) < 0) |
571 | ; |
572 | else if (!sip->sip_allow && NH_PGET(nh, allow)(((nh)->nh_prefs)->nhp_set_.set_bits.nhb_allow ? ((nh)-> nh_prefs)->nhp_allow : ((nh)->nh_nua->nua_handles-> nh_prefs)->nhp_allow) && |
573 | sip_add_dup(msg, sip, (void *)NH_PGET(nh, allow)(((nh)->nh_prefs)->nhp_set_.set_bits.nhb_allow ? ((nh)-> nh_prefs)->nhp_allow : ((nh)->nh_nua->nua_handles-> nh_prefs)->nhp_allow)) < 0) |
574 | ; |
575 | else if (!sip->sip_allow_events && |
576 | NH_PGET(nh, allow_events)(((nh)->nh_prefs)->nhp_set_.set_bits.nhb_allow_events ? ((nh)->nh_prefs)->nhp_allow_events : ((nh)->nh_nua-> nua_handles->nh_prefs)->nhp_allow_events) && |
577 | (method == sip_method_publish || method == sip_method_subscribe || |
578 | method == sip_method_options || method == sip_method_refer || |
579 | (sr->sr_initial && |
580 | (method == sip_method_invite || |
581 | method == sip_method_notify))) && |
582 | sip_add_dup(msg, sip, (void *)NH_PGET(nh, allow_events)(((nh)->nh_prefs)->nhp_set_.set_bits.nhb_allow_events ? ((nh)->nh_prefs)->nhp_allow_events : ((nh)->nh_nua-> nua_handles->nh_prefs)->nhp_allow_events)) < 0) |
583 | ; |
584 | else if (!sip->sip_contact && sr->sr_status < 300 && sr->sr_add_contact && |
585 | (user_contact = 0, |
586 | ds->ds_ltarget |
587 | ? sip_add_dup(msg, sip, (sip_header_t *)ds->ds_ltarget) |
588 | : nua_registration_add_contact_to_response(nh, msg, sip, NULL((void*)0), m)) |
589 | < 0) |
590 | ; |
591 | else { |
592 | int term; |
593 | sip_contact_t *ltarget = NULL((void*)0); |
594 | |
595 | term = sip_response_terminates_dialog(sr->sr_status, sr->sr_method, NULL((void*)0)); |
596 | |
597 | sr->sr_terminating = (term < 0) ? -1 : (term > 0 || sr->sr_terminating); |
598 | |
599 | if (sr->sr_target_refresh && sr->sr_status < 300 && !sr->sr_terminating && |
600 | user_contact && sip->sip_contact) { |
601 | /* Save Contact given by application */ |
602 | ltarget = sip_contact_dup(nh->nh_home, sip->sip_contact); |
603 | } |
604 | |
605 | retval = sr->sr_methods->sm_respond(sr, next_tags); |
606 | |
607 | if (sr->sr_status < 200) |
608 | sr->sr_response.msg = next.msg, sr->sr_response.sip = next.sip; |
609 | else if (next.msg) |
610 | msg_destroy(next.msg); |
611 | |
612 | assert(sr->sr_status >= 200 || sr->sr_response.msg)((void) sizeof ((sr->sr_status >= 200 || sr->sr_response .msg) ? 1 : 0), __extension__ ({ if (sr->sr_status >= 200 || sr->sr_response.msg) ; else __assert_fail ("sr->sr_status >= 200 || sr->sr_response.msg" , "nua_server.c", 612, __extension__ __PRETTY_FUNCTION__); }) ); |
613 | |
614 | if (ltarget) { |
615 | if (sr->sr_status < 300) { |
616 | nua_dialog_state_t *ds = nh->nh_ds; |
617 | msg_header_free(nh->nh_home, (msg_header_t *)ds->ds_ltarget); |
618 | ds->ds_ltarget = ltarget; |
619 | } |
620 | else |
621 | msg_header_free(nh->nh_home, (msg_header_t *)ltarget); |
622 | } |
623 | |
624 | return retval; |
625 | } |
626 | |
627 | if (next.msg) |
628 | msg_destroy(next.msg); |
629 | |
630 | SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR)sr_status(sr, 500, sip_500_Internal_server_error); |
631 | |
632 | msg_destroy(msg); |
633 | |
634 | internal_error: |
635 | sr->sr_response.msg = NULL((void*)0), sr->sr_response.sip = NULL((void*)0); |
636 | nta_incoming_treply(sr->sr_irq, sr->sr_status, sr->sr_phrase, TAG_END()(tag_type_t)0, (tag_value_t)0); |
637 | |
638 | return 0; |
639 | } |
640 | |
641 | /** Return the response to the client. |
642 | * |
643 | * @retval 0 when successfully sent |
644 | * @retval -1 upon an error |
645 | */ |
646 | int nua_base_server_respond(nua_server_request_t *sr, tagi_t const *tags) |
647 | { |
648 | msg_t *response = sr->sr_response.msg; |
649 | sip_t *sip = sr->sr_response.sip; |
650 | |
651 | sr->sr_response.msg = NULL((void*)0), sr->sr_response.sip = NULL((void*)0); |
652 | |
653 | if (sr->sr_status != sip->sip_status->st_status) { |
654 | msg_header_remove(response, (msg_pub_t *)sip, |
655 | (msg_header_t *)sip->sip_status); |
656 | nta_incoming_complete_response(sr->sr_irq, response, |
657 | sr->sr_status, |
658 | sr->sr_phrase, |
659 | TAG_END()(tag_type_t)0, (tag_value_t)0); |
660 | } |
661 | |
662 | if (sr->sr_status != sip->sip_status->st_status) { |
663 | msg_destroy(response); |
664 | SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR)sr_status(sr, 500, sip_500_Internal_server_error); |
665 | nta_incoming_treply(sr->sr_irq, sr->sr_status, sr->sr_phrase, TAG_END()(tag_type_t)0, (tag_value_t)0); |
666 | return 0; |
667 | } |
668 | |
669 | return nta_incoming_mreply(sr->sr_irq, response); |
670 | } |
671 | |
672 | int nua_server_report(nua_server_request_t *sr) |
673 | { |
674 | if (sr) |
675 | return sr->sr_methods->sm_report(sr, NULL((void*)0)); |
676 | else |
677 | return 1; |
678 | } |
679 | |
680 | int nua_base_server_treport(nua_server_request_t *sr, |
681 | tag_type_t tag, tag_value_t value, |
682 | ...) |
683 | { |
684 | int retval; |
685 | ta_list ta; |
686 | ta_start(ta, tag, value)do { tag_type_t ta_start__tag = (tag); tag_value_t ta_start__value = (value); __builtin_va_start((ta).ap, (value)); while ((ta_start__tag ) == tag_next && (ta_start__value) != 0) { ta_start__tag = ((tagi_t *)ta_start__value)->t_tag; if (ta_start__tag == tag_null || ta_start__tag == ((void*)0)) break; if (ta_start__tag == tag_next) { ta_start__value = ((tagi_t *)ta_start__value) ->t_value; } else { ta_start__tag = tag_next; break; } } ( ta).tl->t_tag = ta_start__tag; (ta).tl->t_value = ta_start__value ; if (ta_start__tag != ((void*)0) && ta_start__tag != tag_null && ta_start__tag != tag_next) { va_list ta_start__ap ; __builtin_va_copy((ta_start__ap), ((ta).ap)); (ta).tl[1].t_tag = tag_next; (ta).tl[1].t_value = (tag_value_t)tl_vlist(ta_start__ap ); __builtin_va_end(ta_start__ap); } else { (ta).tl[1].t_value = 0; (ta).tl[1].t_value = (tag_value_t)0; } } while(0); |
687 | retval = nua_base_server_report(sr, ta_args(ta)(ta).tl); |
688 | ta_end(ta)((((ta).tl[1].t_value) ? (tl_vfree((tagi_t *)((ta).tl[1].t_value ))) : (void)0), (ta).tl[1].t_value = 0, __builtin_va_end((ta) .ap)); |
689 | return retval; |
690 | } |
691 | |
692 | /**Report request event to the application. |
693 | * |
694 | * @retval 0 request lives |
695 | * @retval 1 request was destroyed |
696 | * @retval 2 request and its usage was destroyed |
697 | * @retval 3 request, all usages and dialog was destroyed |
698 | * @retval 4 request, all usages, dialog, and handle was destroyed |
699 | */ |
700 | int nua_base_server_report(nua_server_request_t *sr, tagi_t const *tags) |
701 | { |
702 | nua_handle_t *nh = sr->sr_owner; |
703 | nua_t *nua = nh->nh_nua; |
704 | nua_dialog_usage_t *usage = sr->sr_usage; |
705 | int initial = sr->sr_initial; |
706 | int status = sr->sr_status; |
707 | char const *phrase = sr->sr_phrase; |
708 | |
709 | int terminated; |
710 | int handle_can_be_terminated = initial && !sr->sr_event; |
711 | |
712 | if (sr->sr_application) { |
713 | /* There was an error sending response */ |
714 | if (sr->sr_application != sr->sr_status) |
715 | nua_stack_event(nua, nh, NULL((void*)0), nua_i_error, status, phrase, tags); |
716 | sr->sr_application = 0; |
717 | } |
718 | else if (status < 300 && !sr->sr_event) { |
719 | msg_t *msg = msg_ref_create(sr->sr_request.msg); |
720 | nua_event_t e = (enum nua_event_e)sr->sr_methods->sm_event; |
721 | sr->sr_event = 1; |
722 | nua_stack_event(nua, nh, msg, e, status, phrase, tags); |
723 | } |
724 | |
725 | if (status < 200) |
726 | return 0; /* sr lives on until final response is sent */ |
727 | |
728 | if (sr->sr_method == sip_method_invite && status < 300) |
729 | return 0; /* INVITE lives on until ACK is received */ |
730 | |
731 | if (initial && 300 <= status) |
732 | terminated = 1; |
733 | else if (sr->sr_terminating && status < 300) |
734 | terminated = 1; |
735 | else |
736 | terminated = sip_response_terminates_dialog(status, sr->sr_method, NULL((void*)0)); |
737 | |
738 | if (usage && terminated) |
739 | nua_dialog_usage_remove(nh, nh->nh_ds, usage, NULL((void*)0), sr); |
740 | |
741 | nua_server_request_destroy(sr); |
742 | |
743 | if (!terminated) |
744 | return 1; |
745 | |
746 | if (!initial) { |
747 | if (terminated > 0) |
748 | return 2; |
749 | |
750 | /* Remove all usages of the dialog */ |
751 | nua_dialog_deinit(nh, nh->nh_ds); |
752 | |
753 | return 3; |
754 | } |
755 | else if (!handle_can_be_terminated) { |
756 | return 3; |
757 | } |
758 | else { |
759 | if (nh != nh->nh_nua->nua_dhandlenua_handles) |
760 | nh_destroy(nh->nh_nua, nh); |
761 | |
762 | return 4; |
763 | } |
764 | } |