| 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 | } |