ari/pjsip: Make it possible to control transfers through ARI

Introduce a ChannelTransfer event and the ability to notify progress to
ARI. Implement emitting this event from the PJSIP channel instead of
handling the transfer in Asterisk when configured.

Introduce a dialplan function to the PJSIP channel to switch between the
"core" and "ari-only" behavior.

UserNote: Call transfers on the PJSIP channel can now be controlled by
ARI. This can be enabled by using the PJSIP_TRANSFER_HANDLING(ari-only)
dialplan function.

(cherry picked from commit 5e4fca062c)
This commit is contained in:
Holger Hans Peter Freyther
2024-06-15 16:01:58 +08:00
committed by Asterisk Development Team
parent af966a98a1
commit 6f17f61394
18 changed files with 1462 additions and 6 deletions

View File

@@ -1851,6 +1851,8 @@ static int chan_pjsip_indicate(struct ast_channel *ast, int condition, const voi
break;
case AST_CONTROL_STREAM_TOPOLOGY_SOURCE_CHANGED:
break;
case AST_CONTROL_TRANSFER:
break;
case -1:
res = -1;
break;
@@ -3274,6 +3276,11 @@ static struct ast_custom_function session_refresh_function = {
.write = pjsip_acf_session_refresh_write,
};
static struct ast_custom_function transfer_handling_function = {
.name = "PJSIP_TRANSFER_HANDLING",
.write = pjsip_transfer_handling_write,
};
static char *app_pjsip_hangup = "PJSIPHangup";
/*!
@@ -3338,6 +3345,11 @@ static int load_module(void)
goto end;
}
if (ast_custom_function_register(&transfer_handling_function)) {
ast_log(LOG_WARNING, "Unable to register PJSIP_TRANSFER_HANDLING dialplan function\n");
goto end;
}
if (ast_register_application_xml(app_pjsip_hangup, pjsip_app_hangup)) {
ast_log(LOG_WARNING, "Unable to register PJSIPHangup dialplan application\n");
goto end;
@@ -3393,6 +3405,7 @@ end:
ast_custom_function_unregister(&chan_pjsip_parse_uri_function);
ast_custom_function_unregister(&chan_pjsip_parse_uri_from_function);
ast_custom_function_unregister(&session_refresh_function);
ast_custom_function_unregister(&transfer_handling_function);
ast_unregister_application(app_pjsip_hangup);
ast_manager_unregister(app_pjsip_hangup);
@@ -3426,6 +3439,7 @@ static int unload_module(void)
ast_custom_function_unregister(&chan_pjsip_parse_uri_function);
ast_custom_function_unregister(&chan_pjsip_parse_uri_from_function);
ast_custom_function_unregister(&session_refresh_function);
ast_custom_function_unregister(&transfer_handling_function);
ast_unregister_application(app_pjsip_hangup);
ast_manager_unregister(app_pjsip_hangup);

View File

@@ -1368,3 +1368,36 @@ int pjsip_action_hangup(struct mansession *s, const struct message *m)
return ast_manager_hangup_helper(s, m,
pjsip_app_hangup_handler, response_code_validator);
}
int pjsip_transfer_handling_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
{
struct ast_sip_channel_pvt *channel;
int ret = 0;
if (!chan) {
ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
return -1;
}
ast_channel_lock(chan);
if (strcmp(ast_channel_tech(chan)->type, "PJSIP")) {
ast_log(LOG_WARNING, "Cannot call %s on a non-PJSIP channel %s\n", cmd, ast_channel_name(chan));
ast_channel_unlock(chan);
return -1;
}
channel = ast_channel_tech_pvt(chan);
if (ast_strlen_zero(value) || !strcmp(value, "core")) {
channel->session->transferhandling_ari = 0;
} else if (!strcmp(value, "ari-only")) {
channel->session->transferhandling_ari = 1;
} else {
ast_log(AST_LOG_WARNING, "Cannot set unknown transfer handling '%s' on channel '%s', transfer handling will remain unchanged.",
value, ast_channel_name(chan));
ret = -1;
}
ast_channel_unlock(chan);
return ret;
}

View File

@@ -405,6 +405,32 @@
<para>Parse the contents of the provided variable as a URI and return a specified part of the URI.</para>
</description>
</function>
<function name="PJSIP_TRANSFER_HANDLING" language="en_US">
<since>
<version>22.3.0</version>
<version>21.8.0</version>
<version>20.13.0</version>
</since>
<synopsis>
Set how transfers are handled for a PJSIP channel.
</synopsis>
<syntax>
<parameter name="mode" required="false">
<para>How transfers are handled for a PJSIP channel. Default is <literal>core</literal>.</para>
<enumlist>
<enum name="core">
<para>Asterisk will handle attended and blind transfers.</para>
</enum>
<enum name="ari-only">
<para>Asterisk will generate ARI events on incoming SIP REFER.</para>
</enum>
</enumlist>
</parameter>
</syntax>
<description>
<para>When written, sets the transferhandling behavior</para>
</description>
</function>
<info name="CHANNEL" language="en_US" tech="PJSIP">
<enumlist>

View File

@@ -168,4 +168,16 @@ int pjsip_app_hangup(struct ast_channel *chan, const char *data);
*/
int pjsip_action_hangup(struct mansession *s, const struct message *m);
/*!
* \brief PJSIP_TRANSFER_HANDLING function write callback
* \param chan The channel the function is called on
* \param cmd the Name of the function
* \param data Arguments passed to the function
* \param value Value to be set by the function
*
* \retval 0 on success
* \retval -1 on failure
*/
int pjsip_transfer_handling_write(struct ast_channel *chan, const char *cmd, char *data, const char *value);
#endif /* _PJSIP_DIALPLAN_FUNCTIONS */