diff --git a/libs/sofia-sip/libsofia-sip-ua/nta/nta.c b/libs/sofia-sip/libsofia-sip-ua/nta/nta.c index 686ac8e4bd..5e5fa2ca9e 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nta/nta.c +++ b/libs/sofia-sip/libsofia-sip-ua/nta/nta.c @@ -346,7 +346,7 @@ su_log_t nta_log[] = { SU_LOG_INIT("nta", "NTA_DEBUG", SU_DEBUG) }; * NTATAG_SIP_T1X64(), NTATAG_SIP_T1(), NTATAG_SIP_T2(), NTATAG_SIP_T4(), * NTATAG_STATELESS(), * NTATAG_TAG_3261(), NTATAG_TCP_RPORT(), NTATAG_TIMEOUT_408(), - * NTATAG_TIMER_C(), + * NTATAG_TIMER_C(), NTATAG_MAX_PROCEEDING(), * NTATAG_UA(), NTATAG_UDP_MTU(), NTATAG_USER_VIA(), * NTATAG_USE_NAPTR(), NTATAG_USE_SRV() and NTATAG_USE_TIMESTAMP(). * @@ -864,7 +864,7 @@ void agent_kill_terminator(nta_agent_t *agent) * INVITE transactions, or how the @Via headers are generated. * * @note - * Setting the parameters NTATAG_MAXSIZE(), NTATAG_UDP_MTU(), + * Setting the parameters NTATAG_MAXSIZE(), NTATAG_UDP_MTU(), NTATAG_MAX_PROCEEDING(), * NTATAG_SIP_T1X64(), NTATAG_SIP_T1(), NTATAG_SIP_T2(), NTATAG_SIP_T4() to * 0 selects the default value. * @@ -882,7 +882,7 @@ void agent_kill_terminator(nta_agent_t *agent) * NTATAG_SIP_T1X64(), NTATAG_SIP_T1(), NTATAG_SIP_T2(), NTATAG_SIP_T4(), * NTATAG_STATELESS(), * NTATAG_TAG_3261(), NTATAG_TCP_RPORT(), NTATAG_TIMEOUT_408(), - * NTATAG_TIMER_C(), + * NTATAG_TIMER_C(), NTATAG_MAX_PROCEEDING(), * NTATAG_UA(), NTATAG_UDP_MTU(), NTATAG_USER_VIA(), * NTATAG_USE_NAPTR(), NTATAG_USE_SRV() and NTATAG_USE_TIMESTAMP(). * @@ -915,6 +915,7 @@ int agent_set_params(nta_agent_t *agent, tagi_t *tags) unsigned bad_req_mask = agent->sa_bad_req_mask; unsigned bad_resp_mask = agent->sa_bad_resp_mask; usize_t maxsize = agent->sa_maxsize; + usize_t max_proceeding = agent->sa_max_proceeding; unsigned max_forwards = agent->sa_max_forwards->mf_count; unsigned udp_mtu = agent->sa_udp_mtu; unsigned sip_t1 = agent->sa_t1; @@ -966,6 +967,7 @@ int agent_set_params(nta_agent_t *agent, tagi_t *tags) NTATAG_DEFAULT_PROXY_REF(proxy), NTATAG_EXTRA_100_REF(extra_100), NTATAG_MAXSIZE_REF(maxsize), + NTATAG_MAX_PROCEEDING_REF(max_proceeding), NTATAG_MAX_FORWARDS_REF(max_forwards), NTATAG_MCLASS_REF(mclass), NTATAG_MERGE_482_REF(merge_482), @@ -1070,6 +1072,9 @@ int agent_set_params(nta_agent_t *agent, tagi_t *tags) if (maxsize > NTA_TIME_MAX) maxsize = NTA_TIME_MAX; agent->sa_maxsize = maxsize; + if (max_proceeding == 0) max_proceeding = SIZE_MAX; + agent->sa_max_proceeding = max_proceeding; + if (max_forwards == 0) max_forwards = 70; /* Default value */ agent->sa_max_forwards->mf_count = max_forwards; @@ -1178,7 +1183,7 @@ void agent_set_udp_params(nta_agent_t *self, usize_t udp_mtu) * NTATAG_DEBUG_DROP_PROB_REF(), NTATAG_DEFAULT_PROXY_REF(), * NTATAG_EXTRA_100_REF(), * NTATAG_MAXSIZE_REF(), NTATAG_MAX_FORWARDS_REF(), NTATAG_MCLASS_REF(), - * NTATAG_MERGE_482_REF(), + * NTATAG_MERGE_482_REF(), NTATAG_MAX_PROCEEDING_REF(), * NTATAG_PASS_100_REF(), NTATAG_PASS_408_REF(), NTATAG_PRELOAD_REF(), * NTATAG_PROGRESS_REF(), * NTATAG_REL100_REF(), @@ -1226,6 +1231,7 @@ int agent_get_params(nta_agent_t *agent, tagi_t *tags) NTATAG_DEFAULT_PROXY(agent->sa_default_proxy), NTATAG_EXTRA_100(agent->sa_extra_100), NTATAG_MAXSIZE(agent->sa_maxsize), + NTATAG_MAX_PROCEEDING(agent->sa_max_proceeding), NTATAG_MAX_FORWARDS(agent->sa_max_forwards->mf_count), NTATAG_MCLASS(agent->sa_mclass), NTATAG_MERGE_482(agent->sa_merge_482), @@ -2390,9 +2396,16 @@ void agent_recv_request(nta_agent_t *agent, leg_recv(leg, msg, sip, tport); } else if (!agent->sa_is_stateless && (leg = agent->sa_default_leg)) { - SU_DEBUG_5(("nta: %s (%u) %s\n", - method_name, cseq, "going to a default leg")); - leg_recv(leg, msg, sip, tport); + if (method == sip_method_invite && agent->sa_in.proceeding->q_length >= agent->sa_max_proceeding) { + SU_DEBUG_5(("nta: proceeding queue full for %s (%u)\n", method_name, cseq)); + nta_msg_treply(agent, msg, SIP_486_BUSY_HERE, + NTATAG_TPORT(tport), + TAG_END()); + return; + } else { + SU_DEBUG_5(("nta: %s (%u) %s\n", method_name, cseq, "going to a default leg")); + leg_recv(leg, msg, sip, tport); + } } else if (agent->sa_callback) { /* Stateless processing for request */ diff --git a/libs/sofia-sip/libsofia-sip-ua/nta/nta_internal.h b/libs/sofia-sip/libsofia-sip-ua/nta/nta_internal.h index 69b8c46a56..613c5313fc 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nta/nta_internal.h +++ b/libs/sofia-sip/libsofia-sip-ua/nta/nta_internal.h @@ -145,6 +145,9 @@ struct nta_agent_s /** Maximum size of incoming messages */ size_t sa_maxsize; + /** Maximum size of proceeding queue */ + size_t sa_max_proceeding; + /** Maximum size of outgoing UDP requests */ unsigned sa_udp_mtu; diff --git a/libs/sofia-sip/libsofia-sip-ua/nta/nta_tag.c b/libs/sofia-sip/libsofia-sip-ua/nta/nta_tag.c index 7da5f74600..91ee4b9455 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nta/nta_tag.c +++ b/libs/sofia-sip/libsofia-sip-ua/nta/nta_tag.c @@ -400,6 +400,27 @@ tag_typedef_t ntatag_remote_cseq = UINTTAG_TYPEDEF(remote_cseq); */ tag_typedef_t ntatag_maxsize = USIZETAG_TYPEDEF(maxsize); +/**@def NTATAG_MAX_PROCEEDING(x) + * + * Maximum size of proceeding queue. + * + * If the size of the proceedng message queue would exceed the + * given limit, the stack will automatically respond with 486 + * Server Busy. + * + * @par Used with + * nua_create(), nua_set_params(), + * nta_agent_create(), nta_agent_set_params() + * + * @par Parameter type + * - #usize_t + * + * @par Values + * - Maximum acceptable size of a queue (size_t). + * + */ +tag_typedef_t ntatag_max_proceeding = USIZETAG_TYPEDEF(max_proceeding); + /**@def NTATAG_UDP_MTU(x) * * Maximum size of outgoing UDP request. diff --git a/libs/sofia-sip/libsofia-sip-ua/nta/sofia-sip/nta_tag.h b/libs/sofia-sip/libsofia-sip-ua/nta/sofia-sip/nta_tag.h index 4b2ae32854..82e4b1c969 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nta/sofia-sip/nta_tag.h +++ b/libs/sofia-sip/libsofia-sip-ua/nta/sofia-sip/nta_tag.h @@ -155,6 +155,12 @@ NTA_DLL extern tag_typedef_t ntatag_udp_mtu; NTA_DLL extern tag_typedef_t ntatag_udp_mtu_ref; #define NTATAG_UDP_MTU_REF(x) ntatag_udp_mtu_ref, tag_uint_vr(&(x)) +NTA_DLL extern tag_typedef_t ntatag_max_proceeding; +#define NTATAG_MAX_PROCEEDING(x) ntatag_max_proceeding, tag_usize_v((x)) + +NTA_DLL extern tag_typedef_t ntatag_max_proceeding_ref; +#define NTATAG_MAX_PROCEEDING_REF(x) ntatag_max_proceeding_ref, tag_usize_vr(&(x)) + NTA_DLL extern tag_typedef_t ntatag_max_forwards; #define NTATAG_MAX_FORWARDS(x) ntatag_max_forwards, tag_uint_v((x)) diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/nua_params.c b/libs/sofia-sip/libsofia-sip-ua/nua/nua_params.c index beec60976a..34dd314488 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_params.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_params.c @@ -1526,6 +1526,7 @@ int nua_stack_get_params(nua_t *nua, nua_handle_t *nh, nua_event_t e, /* nta */ usize_t udp_mtu = 0; + usize_t max_proceeding = 0; unsigned sip_t1 = 0, sip_t2 = 0, sip_t4 = 0, sip_t1x64 = 0; unsigned debug_drop_prob = 0; url_string_t const *proxy = NULL; @@ -1543,6 +1544,7 @@ int nua_stack_get_params(nua_t *nua, nua_handle_t *nh, nua_event_t e, nta_agent_get_params(nua->nua_nta, NTATAG_UDP_MTU_REF(udp_mtu), + NTATAG_MAX_PROCEEDING_REF(max_proceeding), NTATAG_SIP_T1_REF(sip_t1), NTATAG_SIP_T2_REF(sip_t2), NTATAG_SIP_T4_REF(sip_t4), @@ -1674,6 +1676,7 @@ int nua_stack_get_params(nua_t *nua, nua_handle_t *nh, nua_event_t e, #endif NTATAG_UDP_MTU(udp_mtu), + NTATAG_MAX_PROCEEDING(max_proceeding), NTATAG_SIP_T1(sip_t1), NTATAG_SIP_T2(sip_t2), NTATAG_SIP_T4(sip_t4), diff --git a/libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_tag.h b/libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_tag.h index dd47eacb11..c95748bd19 100644 --- a/libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_tag.h +++ b/libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_tag.h @@ -216,6 +216,8 @@ su_inline tag_value_t tag_filter_v(tag_filter_f *v) {return(tag_value_t)v;} #define tag_uint_vr(v) (tag_value_t)(v) #define tag_usize_v(v) (tag_value_t)(v) #define tag_usize_vr(v) (tag_value_t)(v) +#define tag_size_v(v) (tag_value_t)(v) +#define tag_size_vr(v) (tag_value_t)(v) #define tag_bool_v(v) (tag_value_t)(v != 0) #define tag_bool_vr(v) (tag_value_t)(v) #define tag_ptr_v(v) (tag_value_t)(v)