Bug Summary

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'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name nua_server.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib/llvm-11/lib/clang/11.0.1 -D HAVE_CONFIG_H -I . -I ../.. -I ../../libsofia-sip-ua/su/sofia-sip -I ../../libsofia-sip-ua/features -I ../../libsofia-sip-ua/features -I ../../libsofia-sip-ua/ipt -I ../../libsofia-sip-ua/ipt -I ../../libsofia-sip-ua/iptsec -I ../../libsofia-sip-ua/iptsec -I ../../libsofia-sip-ua/bnf -I ../../libsofia-sip-ua/bnf -I ../../libsofia-sip-ua/http -I ../../libsofia-sip-ua/http -I ../../libsofia-sip-ua/msg -I ../../libsofia-sip-ua/msg -I ../../libsofia-sip-ua/nth -I ../../libsofia-sip-ua/nth -I ../../libsofia-sip-ua/nta -I ../../libsofia-sip-ua/nta -I ../../libsofia-sip-ua/nea -I ../../libsofia-sip-ua/nea -I ../../libsofia-sip-ua/nua -I ../../libsofia-sip-ua/nua -I ../../libsofia-sip-ua/soa -I ../../libsofia-sip-ua/soa -I ../../libsofia-sip-ua/sdp -I ../../libsofia-sip-ua/sdp -I ../../libsofia-sip-ua/sip -I ../../libsofia-sip-ua/sip -I ../../libsofia-sip-ua/soa -I ../../libsofia-sip-ua/soa -I ../../libsofia-sip-ua/sresolv -I ../../libsofia-sip-ua/sresolv -I ../../libsofia-sip-ua/tport -I ../../libsofia-sip-ua/tport -I ../../libsofia-sip-ua/stun -I ../../libsofia-sip-ua/stun -I ../../libsofia-sip-ua/url -I ../../libsofia-sip-ua/url -I ../../libsofia-sip-ua/su -I ../../libsofia-sip-ua/su -I ../../s2check -D SU_DEBUG=0 -D PIC -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-11/lib/clang/11.0.1/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir /drone/src/libsofia-sip-ua/nua -ferror-limit 19 -fgnuc-version=4.2.1 -analyzer-output=html -faddrsig -o /drone/src/scan-build/2022-06-23-181620-12-1 -x c nua_server.c
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
64nua_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
85int 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
288int nua_base_server_init(nua_server_request_t *sr)
289{
290 return 0;
291}
292
293int nua_base_server_preprocess(nua_server_request_t *sr)
294{
295 return 0;
296}
297
298void 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
411void
412nua_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
472int 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
481int 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 */
491int 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 */
507int 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 */
646int 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
672int 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
680int 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 */
700int 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}