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

(cherry picked from commit 0fdaf7fc80)
This commit is contained in:
Sean Bright 2024-01-27 09:46:27 -05:00 committed by Asterisk Development Team
parent 347494a130
commit 4d09fb191c
3 changed files with 28 additions and 5 deletions

View File

@ -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));

View File

@ -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);
}
}

View File

@ -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 */