diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c index 2613a74bc2b2da339eaad7ec28afdea6347b3b9c..add7168c28ecce5a900d00f640ec88520076388c 100644 --- a/res/res_pjsip_session.c +++ b/res/res_pjsip_session.c @@ -2096,39 +2096,8 @@ struct new_invite { pjsip_rx_data *rdata; }; -static void new_invite_destroy(void *obj) +static int new_invite(struct new_invite *invite) { - struct new_invite *invite = obj; - - ao2_cleanup(invite->session); - - if (invite->rdata) { - pjsip_rx_data_free_cloned(invite->rdata); - } -} - -static struct new_invite *new_invite_alloc(struct ast_sip_session *session, pjsip_rx_data *rdata) -{ - struct new_invite *invite = ao2_alloc(sizeof(*invite), new_invite_destroy); - - if (!invite) { - return NULL; - } - - ao2_ref(session, +1); - invite->session = session; - - if (pjsip_rx_data_clone(rdata, 0, &invite->rdata) != PJ_SUCCESS) { - ao2_ref(invite, -1); - return NULL; - } - - return invite; -} - -static int new_invite(void *data) -{ - RAII_VAR(struct new_invite *, invite, data, ao2_cleanup); pjsip_tx_data *tdata = NULL; pjsip_timer_setting timer; pjsip_rdata_sdp_info *sdp_info; @@ -2250,7 +2219,7 @@ static void handle_new_invite_request(pjsip_rx_data *rdata) pjsip_tx_data *tdata = NULL; pjsip_inv_session *inv_session = NULL; struct ast_sip_session *session; - struct new_invite *invite; + struct new_invite invite; ast_assert(endpoint != NULL); @@ -2287,18 +2256,17 @@ static void handle_new_invite_request(pjsip_rx_data *rdata) return; } - invite = new_invite_alloc(session, rdata); - if (!invite || ast_sip_push_task(session->serializer, new_invite, invite)) { - if (pjsip_inv_initial_answer(inv_session, rdata, 500, NULL, NULL, &tdata) == PJ_SUCCESS) { - pjsip_inv_terminate(inv_session, 500, PJ_FALSE); - } else { - pjsip_inv_send_msg(inv_session, tdata); - } -#ifdef HAVE_PJSIP_INV_SESSION_REF - pjsip_inv_dec_ref(inv_session); -#endif - ao2_cleanup(invite); - } + /* + * The current thread is supposed be the session serializer to prevent + * any initial INVITE retransmissions from trying to setup the same + * call again. + */ + ast_assert(ast_taskprocessor_is_task(session->serializer)); + + invite.session = session; + invite.rdata = rdata; + new_invite(&invite); + ao2_ref(session, -1); } @@ -2339,13 +2307,14 @@ static pj_bool_t has_supplement(const struct ast_sip_session *session, const pjs * 2) An in-dialog request that the inv_session layer does not * handle is received (such as an in-dialog INFO) * - * In all cases, there is very little we actually do in this function + * Except for INVITEs, there is very little we actually do in this function * 1) For requests we don't handle, we return PJ_FALSE - * 2) For new INVITEs, throw the work into the SIP threadpool to be done - * there to free up the thread(s) handling incoming requests - * 3) For in-dialog requests we handle, we defer handling them until the - * on_inv_state_change() callback instead (where we will end up putting - * them into the threadpool). + * 2) For new INVITEs, handle them now to prevent retransmissions from + * trying to setup the same call again. + * 3) For in-dialog requests we handle, we process them in the + * .on_state_changed = session_inv_on_state_changed or + * .on_tsx_state_changed = session_inv_on_tsx_state_changed + * callbacks instead. */ static pj_bool_t session_on_rx_request(pjsip_rx_data *rdata) {