diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c index 1319094cfff0b5377c9c39fbcac5f8c52f15367e..0a8d1bcb520885a65eee46b3944b578d6cc8202d 100644 --- a/channels/chan_pjsip.c +++ b/channels/chan_pjsip.c @@ -162,11 +162,18 @@ static enum ast_rtp_glue_result chan_pjsip_get_rtp_peer(struct ast_channel *chan struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(chan); struct chan_pjsip_pvt *pvt; struct ast_sip_endpoint *endpoint; + struct ast_datastore *datastore; if (!channel || !channel->session || !(pvt = channel->pvt) || !pvt->media[SIP_MEDIA_AUDIO]->rtp) { return AST_RTP_GLUE_RESULT_FORBID; } + datastore = ast_sip_session_get_datastore(channel->session, "t38"); + if (datastore) { + ao2_ref(datastore, -1); + return AST_RTP_GLUE_RESULT_FORBID; + } + endpoint = channel->session->endpoint; *instance = pvt->media[SIP_MEDIA_AUDIO]->rtp; diff --git a/res/res_pjsip_t38.c b/res/res_pjsip_t38.c index 0db2e5c3716b961ff7969dad8f5dfcadd0d7d197..2c544bb70e8b1d4cde2a49325910def8b18b4077 100644 --- a/res/res_pjsip_t38.c +++ b/res/res_pjsip_t38.c @@ -161,6 +161,9 @@ static void t38_change_state(struct ast_sip_session *session, struct ast_sip_ses parameters.max_ifp = ast_udptl_get_far_max_ifp(session_media->udptl); parameters.request_response = AST_T38_REQUEST_NEGOTIATE; ast_udptl_set_tag(session_media->udptl, "%s", ast_channel_name(session->channel)); + + /* Inform the bridge the channel is in that it needs to be reconfigured */ + ast_channel_set_unbridged(session->channel, 1); break; case T38_ENABLED: parameters = state->their_parms; @@ -177,7 +180,8 @@ static void t38_change_state(struct ast_sip_session *session, struct ast_sip_ses } break; case T38_LOCAL_REINVITE: - /* wait until we get a peer response before responding to local reinvite */ + /* Inform the bridge the channel is in that it needs to be reconfigured */ + ast_channel_set_unbridged(session->channel, 1); break; case T38_MAX_ENUM: /* Well, that shouldn't happen */ @@ -463,6 +467,11 @@ static void t38_masq(void *data, int framehook_id, ast_framehook_detach(new_chan, framehook_id); } +static int t38_consume(void *data, enum ast_frame_type type) +{ + return 0; +} + static const struct ast_datastore_info t38_framehook_datastore = { .type = "T38 framehook", }; @@ -475,6 +484,7 @@ static void t38_attach_framehook(struct ast_sip_session *session) static struct ast_framehook_interface hook = { .version = AST_FRAMEHOOK_INTERFACE_VERSION, .event_cb = t38_framehook, + .consume_cb = t38_consume, .chan_fixup_cb = t38_masq, .chan_breakdown_cb = t38_masq, }; @@ -560,6 +570,41 @@ static struct ast_sip_session_supplement t38_supplement = { .outgoing_request = t38_outgoing_invite_request, }; +static int t38_incoming_bye_request(struct ast_sip_session *session, struct pjsip_rx_data *rdata) +{ + struct ast_datastore *datastore; + struct ast_sip_session_media *session_media; + + if (!session->channel) { + return 0; + } + + datastore = ast_sip_session_get_datastore(session, "t38"); + if (!datastore) { + return 0; + } + + session_media = ao2_find(session->media, "image", OBJ_KEY); + if (!session_media) { + ao2_ref(datastore, -1); + return 0; + } + + t38_change_state(session, session_media, datastore->data, T38_REJECTED); + + ao2_ref(datastore, -1); + ao2_ref(session_media, -1); + + return 0; +} + +/*! \brief Supplement for handling a remote termination of T.38 state */ +static struct ast_sip_session_supplement t38_bye_supplement = { + .method = "BYE", + .priority = AST_SIP_SUPPLEMENT_PRIORITY_CHANNEL + 1, + .incoming_request = t38_incoming_bye_request, +}; + /*! \brief Parse a T.38 image stream and store the attribute information */ static void t38_interpret_sdp(struct t38_state *state, struct ast_sip_session *session, struct ast_sip_session_media *session_media, const struct pjmedia_sdp_media *stream) @@ -889,6 +934,7 @@ static int unload_module(void) { ast_sip_session_unregister_sdp_handler(&image_sdp_handler, "image"); ast_sip_session_unregister_supplement(&t38_supplement); + ast_sip_session_unregister_supplement(&t38_bye_supplement); return 0; } @@ -915,6 +961,11 @@ static int load_module(void) goto end; } + if (ast_sip_session_register_supplement(&t38_bye_supplement)) { + ast_log(LOG_ERROR, "Unable to register T.38 BYE session supplement\n"); + goto end; + } + if (ast_sip_session_register_sdp_handler(&image_sdp_handler, "image")) { ast_log(LOG_ERROR, "Unable to register SDP handler for image stream type\n"); goto end;