summaryrefslogtreecommitdiff
path: root/res/res_pjsip
diff options
context:
space:
mode:
Diffstat (limited to 'res/res_pjsip')
-rw-r--r--res/res_pjsip/config_transport.c22
-rw-r--r--res/res_pjsip/pjsip_message_ip_updater.c83
2 files changed, 98 insertions, 7 deletions
diff --git a/res/res_pjsip/config_transport.c b/res/res_pjsip/config_transport.c
index 60b4507cd..3c41f175a 100644
--- a/res/res_pjsip/config_transport.c
+++ b/res/res_pjsip/config_transport.c
@@ -552,13 +552,20 @@ static int transport_apply(const struct ast_sorcery *sorcery, void *obj)
}
}
- if (res == PJ_SUCCESS && (transport->tos || transport->cos)) {
- pj_sock_t sock;
- pj_qos_params qos_params;
- sock = pjsip_udp_transport_get_socket(temp_state->state->transport);
- pj_sock_get_qos_params(sock, &qos_params);
- set_qos(transport, &qos_params);
- pj_sock_set_qos_params(sock, &qos_params);
+ if (res == PJ_SUCCESS) {
+ temp_state->state->transport->info = pj_pool_alloc(temp_state->state->transport->pool,
+ (AST_SIP_X_AST_TXP_LEN + strlen(transport_id) + 2));
+
+ sprintf(temp_state->state->transport->info, "%s:%s", AST_SIP_X_AST_TXP, transport_id);
+
+ if (transport->tos || transport->cos) {
+ pj_sock_t sock;
+ pj_qos_params qos_params;
+ sock = pjsip_udp_transport_get_socket(temp_state->state->transport);
+ pj_sock_get_qos_params(sock, &qos_params);
+ set_qos(transport, &qos_params);
+ pj_sock_set_qos_params(sock, &qos_params);
+ }
}
} else if (transport->type == AST_TRANSPORT_TCP) {
pjsip_tcp_transport_cfg cfg;
@@ -1375,6 +1382,7 @@ int ast_sip_initialize_sorcery_transport(void)
ast_sorcery_object_field_register(sorcery, "transport", "cos", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_transport, cos));
ast_sorcery_object_field_register(sorcery, "transport", "websocket_write_timeout", AST_DEFAULT_WEBSOCKET_WRITE_TIMEOUT_STR, OPT_INT_T, PARSE_IN_RANGE, FLDSET(struct ast_sip_transport, write_timeout), 1, INT_MAX);
ast_sorcery_object_field_register(sorcery, "transport", "allow_reload", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_transport, allow_reload));
+ ast_sorcery_object_field_register(sorcery, "transport", "symmetric_transport", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_transport, symmetric_transport));
internal_sip_register_endpoint_formatter(&endpoint_transport_formatter);
diff --git a/res/res_pjsip/pjsip_message_ip_updater.c b/res/res_pjsip/pjsip_message_ip_updater.c
index 7671ad0a7..864d898b3 100644
--- a/res/res_pjsip/pjsip_message_ip_updater.c
+++ b/res/res_pjsip/pjsip_message_ip_updater.c
@@ -28,6 +28,7 @@
#define MOD_DATA_RESTRICTIONS "restrictions"
static pj_status_t multihomed_on_tx_message(pjsip_tx_data *tdata);
+static pj_bool_t multihomed_on_rx_message(pjsip_rx_data *rdata);
/*! \brief Outgoing message modification restrictions */
struct multihomed_message_restrictions {
@@ -41,6 +42,7 @@ static pjsip_module multihomed_module = {
.priority = PJSIP_MOD_PRIORITY_TSX_LAYER - 1,
.on_tx_request = multihomed_on_tx_message,
.on_tx_response = multihomed_on_tx_message,
+ .on_rx_request = multihomed_on_rx_message,
};
/*! \brief Helper function to get (or allocate if not already present) restrictions on a message */
@@ -151,6 +153,44 @@ static int multihomed_rewrite_sdp(struct pjmedia_sdp_session *sdp)
return 0;
}
+static void sanitize_tdata(pjsip_tx_data *tdata)
+{
+ static const pj_str_t x_name = { AST_SIP_X_AST_TXP, AST_SIP_X_AST_TXP_LEN };
+ pjsip_param *x_transport;
+ pjsip_sip_uri *uri;
+ pjsip_fromto_hdr *fromto;
+ pjsip_contact_hdr *contact;
+ pjsip_hdr *hdr;
+
+ if (tdata->msg->type == PJSIP_REQUEST_MSG) {
+ uri = pjsip_uri_get_uri(tdata->msg->line.req.uri);
+ x_transport = pjsip_param_find(&uri->other_param, &x_name);
+ if (x_transport) {
+ pj_list_erase(x_transport);
+ }
+ }
+
+ for (hdr = tdata->msg->hdr.next; hdr != &tdata->msg->hdr; hdr = hdr->next) {
+ if (hdr->type == PJSIP_H_TO || hdr->type == PJSIP_H_FROM) {
+ fromto = (pjsip_fromto_hdr *) hdr;
+ uri = pjsip_uri_get_uri(fromto->uri);
+ x_transport = pjsip_param_find(&uri->other_param, &x_name);
+ if (x_transport) {
+ pj_list_erase(x_transport);
+ }
+ } else if (hdr->type == PJSIP_H_CONTACT) {
+ contact = (pjsip_contact_hdr *) hdr;
+ uri = pjsip_uri_get_uri(contact->uri);
+ x_transport = pjsip_param_find(&uri->other_param, &x_name);
+ if (x_transport) {
+ pj_list_erase(x_transport);
+ }
+ }
+ }
+
+ pjsip_tx_data_invalidate_msg(tdata);
+}
+
static pj_status_t multihomed_on_tx_message(pjsip_tx_data *tdata)
{
struct multihomed_message_restrictions *restrictions = ast_sip_mod_data_get(tdata->mod_data, multihomed_module.id, MOD_DATA_RESTRICTIONS);
@@ -159,6 +199,8 @@ static pj_status_t multihomed_on_tx_message(pjsip_tx_data *tdata)
pjsip_via_hdr *via;
pjsip_fromto_hdr *from;
+ sanitize_tdata(tdata);
+
/* Use the destination information to determine what local interface this message will go out on */
pjsip_tpmgr_fla2_param_default(&prm);
prm.tp_type = tdata->tp_info.transport->key.type;
@@ -273,6 +315,47 @@ static pj_status_t multihomed_on_tx_message(pjsip_tx_data *tdata)
return PJ_SUCCESS;
}
+static pj_bool_t multihomed_on_rx_message(pjsip_rx_data *rdata)
+{
+ pjsip_contact_hdr *contact;
+ pjsip_sip_uri *uri;
+ const char *transport_id;
+ struct ast_sip_transport *transport;
+ pjsip_param *x_transport;
+
+ if (rdata->msg_info.msg->type != PJSIP_REQUEST_MSG) {
+ return PJ_FALSE;
+ }
+
+ contact = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT, NULL);
+ if (!(contact && contact->uri
+ && ast_begins_with(rdata->tp_info.transport->info, AST_SIP_X_AST_TXP ":"))) {
+ return PJ_FALSE;
+ }
+
+ uri = pjsip_uri_get_uri(contact->uri);
+
+ transport_id = rdata->tp_info.transport->info + AST_SIP_X_AST_TXP_LEN + 1;
+ transport = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "transport", transport_id);
+
+ if (!(transport && transport->symmetric_transport)) {
+ return PJ_FALSE;
+ }
+
+ x_transport = PJ_POOL_ALLOC_T(rdata->tp_info.pool, pjsip_param);
+ x_transport->name = pj_strdup3(rdata->tp_info.pool, AST_SIP_X_AST_TXP);
+ x_transport->value = pj_strdup3(rdata->tp_info.pool, transport_id);
+
+ pj_list_insert_before(&uri->other_param, x_transport);
+
+ ast_debug(1, "Set transport '%s' on %.*s from %.*s:%d\n", transport_id,
+ (int)rdata->msg_info.msg->line.req.method.name.slen,
+ rdata->msg_info.msg->line.req.method.name.ptr,
+ (int)uri->host.slen, uri->host.ptr, uri->port);
+
+ return PJ_FALSE;
+}
+
void ast_res_pjsip_cleanup_message_ip_updater(void)
{
ast_sip_unregister_service(&multihomed_module);