mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-30 02:26:23 +00:00
Merge "chan_pjsip: Handle T.38 faxes with direct media bridges"
This commit is contained in:
@@ -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 ast_sip_channel_pvt *channel = ast_channel_tech_pvt(chan);
|
||||||
struct chan_pjsip_pvt *pvt;
|
struct chan_pjsip_pvt *pvt;
|
||||||
struct ast_sip_endpoint *endpoint;
|
struct ast_sip_endpoint *endpoint;
|
||||||
|
struct ast_datastore *datastore;
|
||||||
|
|
||||||
if (!channel || !channel->session || !(pvt = channel->pvt) || !pvt->media[SIP_MEDIA_AUDIO]->rtp) {
|
if (!channel || !channel->session || !(pvt = channel->pvt) || !pvt->media[SIP_MEDIA_AUDIO]->rtp) {
|
||||||
return AST_RTP_GLUE_RESULT_FORBID;
|
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;
|
endpoint = channel->session->endpoint;
|
||||||
|
|
||||||
*instance = pvt->media[SIP_MEDIA_AUDIO]->rtp;
|
*instance = pvt->media[SIP_MEDIA_AUDIO]->rtp;
|
||||||
|
@@ -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.max_ifp = ast_udptl_get_far_max_ifp(session_media->udptl);
|
||||||
parameters.request_response = AST_T38_REQUEST_NEGOTIATE;
|
parameters.request_response = AST_T38_REQUEST_NEGOTIATE;
|
||||||
ast_udptl_set_tag(session_media->udptl, "%s", ast_channel_name(session->channel));
|
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;
|
break;
|
||||||
case T38_ENABLED:
|
case T38_ENABLED:
|
||||||
parameters = state->their_parms;
|
parameters = state->their_parms;
|
||||||
@@ -177,7 +180,8 @@ static void t38_change_state(struct ast_sip_session *session, struct ast_sip_ses
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case T38_LOCAL_REINVITE:
|
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;
|
break;
|
||||||
case T38_MAX_ENUM:
|
case T38_MAX_ENUM:
|
||||||
/* Well, that shouldn't happen */
|
/* 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);
|
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 = {
|
static const struct ast_datastore_info t38_framehook_datastore = {
|
||||||
.type = "T38 framehook",
|
.type = "T38 framehook",
|
||||||
};
|
};
|
||||||
@@ -475,6 +484,7 @@ static void t38_attach_framehook(struct ast_sip_session *session)
|
|||||||
static struct ast_framehook_interface hook = {
|
static struct ast_framehook_interface hook = {
|
||||||
.version = AST_FRAMEHOOK_INTERFACE_VERSION,
|
.version = AST_FRAMEHOOK_INTERFACE_VERSION,
|
||||||
.event_cb = t38_framehook,
|
.event_cb = t38_framehook,
|
||||||
|
.consume_cb = t38_consume,
|
||||||
.chan_fixup_cb = t38_masq,
|
.chan_fixup_cb = t38_masq,
|
||||||
.chan_breakdown_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,
|
.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 */
|
/*! \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,
|
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)
|
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_sdp_handler(&image_sdp_handler, "image");
|
||||||
ast_sip_session_unregister_supplement(&t38_supplement);
|
ast_sip_session_unregister_supplement(&t38_supplement);
|
||||||
|
ast_sip_session_unregister_supplement(&t38_bye_supplement);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -915,6 +961,11 @@ static int load_module(void)
|
|||||||
goto end;
|
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")) {
|
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");
|
ast_log(LOG_ERROR, "Unable to register SDP handler for image stream type\n");
|
||||||
goto end;
|
goto end;
|
||||||
|
Reference in New Issue
Block a user