diff options
author | Mark Michelson <mmichelson@digium.com> | 2015-03-27 20:30:18 +0000 |
---|---|---|
committer | Mark Michelson <mmichelson@digium.com> | 2015-03-27 20:30:18 +0000 |
commit | 85feac857c659c8ddff3af67099f0b0bd34fb2b2 (patch) | |
tree | b825a9916fe72408833484ed5ceb305e1772c2a7 /res/res_pjsip.c | |
parent | dc2cf21144b81800329bad4596ded07ed0882ed7 (diff) |
Add stateful PJSIP response API call, and use it for out-of-dialog responses.
Asterisk had an issue where retransmissions of MESSAGE requests resulted in
Asterisk processing the retransmission as if it were a new MESSAGE request.
This patch fixes the issue by creating a transaction in PJSIP on the incoming
request. This way, if a retransmission arrives, the PJSIP transaction layer
will resend the response and Asterisk will not ever see the retransmission.
ASTERISK-24920 #close
Reported by Mark Michelson
Review: https://reviewboard.asterisk.org/r/4532/
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/13@433619 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'res/res_pjsip.c')
-rw-r--r-- | res/res_pjsip.c | 30 |
1 files changed, 27 insertions, 3 deletions
diff --git a/res/res_pjsip.c b/res/res_pjsip.c index c0e00d731..e632817d5 100644 --- a/res/res_pjsip.c +++ b/res/res_pjsip.c @@ -3292,7 +3292,7 @@ static pj_bool_t supplement_on_rx_request(pjsip_rx_data *rdata) return PJ_FALSE; } -int ast_sip_send_response(pjsip_response_addr *res_addr, pjsip_tx_data *tdata, struct ast_sip_endpoint *sip_endpoint) +static void supplement_outgoing_response(pjsip_tx_data *tdata, struct ast_sip_endpoint *sip_endpoint) { struct ast_sip_supplement *supplement; pjsip_cseq_hdr *cseq = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CSEQ, NULL); @@ -3300,8 +3300,7 @@ int ast_sip_send_response(pjsip_response_addr *res_addr, pjsip_tx_data *tdata, s AST_RWLIST_RDLOCK(&supplements); AST_LIST_TRAVERSE(&supplements, supplement, next) { - if (supplement->outgoing_response - && does_method_match(&cseq->method.name, supplement->method)) { + if (supplement->outgoing_response && does_method_match(&cseq->method.name, supplement->method)) { supplement->outgoing_response(sip_endpoint, contact, tdata); } } @@ -3309,10 +3308,35 @@ int ast_sip_send_response(pjsip_response_addr *res_addr, pjsip_tx_data *tdata, s ast_sip_mod_data_set(tdata->pool, tdata->mod_data, supplement_module.id, MOD_DATA_CONTACT, NULL); ao2_cleanup(contact); +} + +int ast_sip_send_response(pjsip_response_addr *res_addr, pjsip_tx_data *tdata, struct ast_sip_endpoint *sip_endpoint) +{ + supplement_outgoing_response(tdata, sip_endpoint); return pjsip_endpt_send_response(ast_sip_get_pjsip_endpoint(), res_addr, tdata, NULL, NULL); } +int ast_sip_send_stateful_response(pjsip_rx_data *rdata, pjsip_tx_data *tdata, struct ast_sip_endpoint *sip_endpoint) +{ + pjsip_transaction *tsx; + + if (pjsip_tsx_create_uas(NULL, rdata, &tsx) != PJ_SUCCESS) { + pjsip_tx_data_dec_ref(tdata); + return -1; + } + pjsip_tsx_recv_msg(tsx, rdata); + + supplement_outgoing_response(tdata, sip_endpoint); + + if (pjsip_tsx_send_msg(tsx, tdata) != PJ_SUCCESS) { + pjsip_tx_data_dec_ref(tdata); + return -1; + } + + return 0; +} + int ast_sip_create_response(const pjsip_rx_data *rdata, int st_code, struct ast_sip_contact *contact, pjsip_tx_data **tdata) { |