From 0fdaf7fc80aced62150a4a898ba21d400d7f4dab Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Sat, 27 Jan 2024 09:46:27 -0500 Subject: [PATCH] res_pjsip_session.c: Correctly format SDP connection addresses. Resolves a regression identified by @justinludwig involving the rendering of IPv6 addresses in outgoing SDP. Also updates `media_address` on PJSIP endpoints so that if we are able to parse the configured value as an IP we store it in a format that we can directly use later. Based on my reading of the code it appeared that one could configure `media_address` as: ``` [foo] type = endpoint ... media_address = [2001:db8::] ``` And that value would be blindly copied into the outgoing SDP without regard to its format. Fixes #541 --- res/res_pjsip/pjsip_configuration.c | 25 ++++++++++++++++++++++++- res/res_pjsip_session.c | 4 ++-- res/res_pjsip_t38.c | 4 ++-- 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c index 613d06fa52..698ff20f28 100644 --- a/res/res_pjsip/pjsip_configuration.c +++ b/res/res_pjsip/pjsip_configuration.c @@ -538,6 +538,29 @@ static int ident_to_str(const void *obj, const intptr_t *args, char **buf) return 0; } +static int media_address_handler(const struct aco_option *opt, struct ast_variable *var, void *obj) +{ + struct ast_sip_endpoint *endpoint = obj; + struct ast_sockaddr addr; + + if (ast_sockaddr_parse(&addr, var->value, 0)) { + /* If we're able to parse as an IP, ensure it's formatted correctly for later */ + ast_string_field_set(endpoint, media.address, ast_sockaddr_stringify_addr_remote(&addr)); + } else { + /* If we weren't able to parse it as an IP, just assume it's a hostname */ + ast_string_field_set(endpoint, media.address, var->value); + } + + return 0; +} + +static int media_address_to_str(const void *obj, const intptr_t *args, char **buf) +{ + const struct ast_sip_endpoint *endpoint = obj; + *buf = ast_strdup(endpoint->media.address); + return 0; +} + static int redirect_handler(const struct aco_option *opt, struct ast_variable *var, void *obj) { struct ast_sip_endpoint *endpoint = obj; @@ -2163,7 +2186,7 @@ int ast_res_pjsip_initialize_configuration(void) ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "auth", "", inbound_auth_handler, inbound_auths_to_str, NULL, 0, 0); ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "outbound_auth", "", outbound_auth_handler, outbound_auths_to_str, NULL, 0, 0); ast_sorcery_object_field_register(sip_sorcery, "endpoint", "aors", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, aors)); - ast_sorcery_object_field_register(sip_sorcery, "endpoint", "media_address", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, media.address)); + ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "media_address", "", media_address_handler, media_address_to_str, NULL, 0, 0); ast_sorcery_object_field_register(sip_sorcery, "endpoint", "bind_rtp_to_media_address", "no", OPT_BOOL_T, 1, STRFLDSET(struct ast_sip_endpoint, media.bind_rtp_to_media_address)); ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "identify_by", "username,ip", ident_handler, ident_to_str, NULL, 0, 0); ast_sorcery_object_field_register(sip_sorcery, "endpoint", "direct_media", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.direct_media.enabled)); diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c index b1d2dbdf17..0ff35736c1 100644 --- a/res/res_pjsip_session.c +++ b/res/res_pjsip_session.c @@ -5631,8 +5631,8 @@ static void session_outgoing_nat_hook(pjsip_tx_data *tdata, struct ast_sip_trans * rewriting. No localnet configured? Always rewrite. */ if (ast_sip_transport_is_local(transport_state, &our_sdp_addr) || !transport_state->localnet) { ast_debug(5, "%s: Setting external media address to %s\n", ast_sip_session_get_name(session), - ast_sockaddr_stringify_host(&transport_state->external_media_address)); - pj_strdup2(tdata->pool, &sdp->conn->addr, ast_sockaddr_stringify_host(&transport_state->external_media_address)); + ast_sockaddr_stringify_addr_remote(&transport_state->external_media_address)); + pj_strdup2(tdata->pool, &sdp->conn->addr, ast_sockaddr_stringify_addr_remote(&transport_state->external_media_address)); pj_strassign(&sdp->origin.addr, &sdp->conn->addr); } } diff --git a/res/res_pjsip_t38.c b/res/res_pjsip_t38.c index 7df35d9b2a..681fabbf73 100644 --- a/res/res_pjsip_t38.c +++ b/res/res_pjsip_t38.c @@ -1097,8 +1097,8 @@ static void change_outgoing_sdp_stream_media_address(pjsip_tx_data *tdata, struc if (ast_sip_transport_is_nonlocal(transport_state, &our_sdp_addr) && transport_state->localnet) { return; } - ast_debug(5, "Setting media address to %s\n", ast_sockaddr_stringify_host(&transport_state->external_media_address)); - pj_strdup2(tdata->pool, &stream->conn->addr, ast_sockaddr_stringify_host(&transport_state->external_media_address)); + ast_debug(5, "Setting media address to %s\n", ast_sockaddr_stringify_addr_remote(&transport_state->external_media_address)); + pj_strdup2(tdata->pool, &stream->conn->addr, ast_sockaddr_stringify_addr_remote(&transport_state->external_media_address)); } /*! \brief Function which destroys the UDPTL instance when session ends */