diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h index 0db9a1917b889b901602e318641403b0244f8108..02ac1ed7f94aa68fed255dc336c0bfbdcf806021 100644 --- a/include/asterisk/res_pjsip.h +++ b/include/asterisk/res_pjsip.h @@ -1103,6 +1103,7 @@ struct ast_sip_endpoint { unsigned int failover_reg_addr; /* the transport name of latest registration */ char *register_transport; + unsigned int max_sessions; }; struct pjsip_register_dest { diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c index 8a3cf2a05357c2bebb43fd0c670fe2d4ddedf5f8..e9bba44565f789d6c8398e142473b28fd9ee3440 100644 --- a/res/res_pjsip/pjsip_configuration.c +++ b/res/res_pjsip/pjsip_configuration.c @@ -47,6 +47,8 @@ struct sip_persistent_endpoint { struct ast_endpoint *endpoint; }; +#define DEFAULT_MAX_SESSIONS_PER_CLIENT 0 + /*! \brief Container for persistent endpoint information */ static struct ao2_container *persistent_endpoints; @@ -2354,6 +2356,7 @@ int ast_res_pjsip_initialize_configuration(void) ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "security_negotiation", "no", security_negotiation_handler, security_negotiation_to_str, NULL, 0, 0); ast_sorcery_object_field_register(sip_sorcery, "endpoint", "send_aoc", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, send_aoc)); ast_sorcery_object_field_register(sip_sorcery, "endpoint", "Emergency", "false", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, Emergency)); + ast_sorcery_object_field_register(sip_sorcery, "endpoint", "max_sessions", __stringify(DEFAULT_MAX_SESSIONS_PER_CLIENT), OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, max_sessions)); if (ast_sip_initialize_sorcery_transport()) { ast_log(LOG_ERROR, "Failed to register SIP transport support with sorcery\n"); diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c index 11edcd9c07223913284478c96bf91b8edbc34dbe..a643ff6ba15e731963f2d8084a45347176945d5a 100644 --- a/res/res_pjsip_session.c +++ b/res/res_pjsip_session.c @@ -3485,6 +3485,9 @@ struct ast_sip_session *ast_sip_session_create_outgoing(struct ast_sip_endpoint if (line_calls >= ast_sip_get_max_sessions_per_line()) { ast_log(LOG_WARNING, "Max call per line limit exceeded [%d/%d]\n", line_calls, ast_sip_get_max_sessions_per_line()); SCOPE_EXIT_RTN_VALUE(NULL, "Max call per line limit exceeded\n"); + } else if (endpoint->max_sessions && line_calls >= endpoint->max_sessions) { + ast_log(LOG_WARNING, "Max call per client limit exceeded [%d/%d]\n", line_calls, endpoint->max_sessions); + SCOPE_EXIT_RTN_VALUE(NULL, "Max call per client limit exceeded\n"); } else if (((current_session_count >= ast_sip_get_max_sessions_total()) && (ast_active_calls() != 3)) || ((current_session_count >= ast_sip_get_max_sessions_total()) && (ast_active_channels() >= 7))) { ast_log(LOG_WARNING, "Max call limit exceeded [%d/%d]\n", current_session_count, ast_sip_get_max_sessions_total()); @@ -4379,6 +4382,14 @@ static void handle_new_invite_request(pjsip_rx_data *rdata) pjsip_inv_terminate(inv_session, 486, PJ_FALSE); } SCOPE_EXIT_RTN("Max call per line limit exceeded\n"); + } else if (endpoint->max_sessions && line_calls >= endpoint->max_sessions) { + ast_log(LOG_WARNING, "Max call per client limit exceeded [%d/%d]\n", line_calls, endpoint->max_sessions); + /* Dialog's lock and reference are removed in new_invite_initial_answer */ + if (!new_invite_initial_answer(inv_session, rdata, 486, 486, PJ_FALSE)) { + /* Terminate the session if it wasn't done in the answer */ + pjsip_inv_terminate(inv_session, 486, PJ_FALSE); + } + SCOPE_EXIT_RTN("Max call per client limit exceeded\n"); } else if ((current_session_count == ast_sip_get_max_sessions_total()) || (ast_active_calls() >= ast_sip_get_max_sessions_total())) { ast_log(LOG_WARNING, "Max call limit exceeded [%d/%d]\n", current_session_count, ast_sip_get_max_sessions_total()); /* Dialog's lock and reference are removed in new_invite_initial_answer */