diff --git a/res/ari/resource_channels.c b/res/ari/resource_channels.c index c195eef87e3452e35696b5c2427b19b1b8adeb08..1164ab10ed7124a44830b4e4b2ea8930fbc80ab6 100644 --- a/res/ari/resource_channels.c +++ b/res/ari/resource_channels.c @@ -49,6 +49,40 @@ #include <limits.h> +/*! \brief Return the corresponded hangup code of the given reason */ +static int convert_reason_to_hangup_code(const char* reason) +{ + if (!strcmp(reason, "normal")) { + return AST_CAUSE_NORMAL; + } else if (!strcmp(reason, "busy")) { + return AST_CAUSE_BUSY; + } else if (!strcmp(reason, "congestion")) { + return AST_CAUSE_CONGESTION; + } else if (!strcmp(reason, "no_answer")) { + return AST_CAUSE_NOANSWER; + } else if (!strcmp(reason, "timeout")) { + return AST_CAUSE_NO_USER_RESPONSE; + } else if (!strcmp(reason, "rejected")) { + return AST_CAUSE_CALL_REJECTED; + } else if (!strcmp(reason, "unallocated")) { + return AST_CAUSE_UNALLOCATED; + } else if (!strcmp(reason, "normal_unspecified")) { + return AST_CAUSE_NORMAL_UNSPECIFIED; + } else if (!strcmp(reason, "number_incomplete")) { + return AST_CAUSE_INVALID_NUMBER_FORMAT; + } else if (!strcmp(reason, "codec_mismatch")) { + return AST_CAUSE_BEARERCAPABILITY_NOTAVAIL; + } else if (!strcmp(reason, "interworking")) { + return AST_CAUSE_INTERWORKING; + } else if (!strcmp(reason, "failure")) { + return AST_CAUSE_FAILURE; + } else if(!strcmp(reason, "answered_elsewhere")) { + return AST_CAUSE_ANSWERED_ELSEWHERE; + } + + return -1; +} + /*! * \brief Ensure channel is in a state that allows operation to be performed. * @@ -885,39 +919,34 @@ void ast_ari_channels_hangup(struct ast_variable *headers, return; } - if (ast_strlen_zero(args->reason) || !strcmp(args->reason, "normal")) { - cause = AST_CAUSE_NORMAL; - } else if (!strcmp(args->reason, "busy")) { - cause = AST_CAUSE_BUSY; - } else if (!strcmp(args->reason, "congestion")) { - cause = AST_CAUSE_CONGESTION; - } else if (!strcmp(args->reason, "no_answer")) { - cause = AST_CAUSE_NOANSWER; - } else if (!strcmp(args->reason, "timeout")) { - cause = AST_CAUSE_NO_USER_RESPONSE; - } else if (!strcmp(args->reason, "rejected")) { - cause = AST_CAUSE_CALL_REJECTED; - } else if (!strcmp(args->reason, "unallocated")) { - cause = AST_CAUSE_UNALLOCATED; - } else if (!strcmp(args->reason, "normal_unspecified")) { - cause = AST_CAUSE_NORMAL_UNSPECIFIED; - } else if (!strcmp(args->reason, "number_incomplete")) { - cause = AST_CAUSE_INVALID_NUMBER_FORMAT; - } else if (!strcmp(args->reason, "codec_mismatch")) { - cause = AST_CAUSE_BEARERCAPABILITY_NOTAVAIL; - } else if (!strcmp(args->reason, "interworking")) { - cause = AST_CAUSE_INTERWORKING; - } else if (!strcmp(args->reason, "failure")) { - cause = AST_CAUSE_FAILURE; - } else if(!strcmp(args->reason, "answered_elsewhere")) { - cause = AST_CAUSE_ANSWERED_ELSEWHERE; - } else { - ast_ari_response_error( - response, 400, "Invalid Reason", - "Invalid reason for hangup provided"); + if (!ast_strlen_zero(args->reason) && !ast_strlen_zero(args->reason_code)) { + ast_ari_response_error(response, 400, "Bad Request", + "The reason and reason_code can't both be specified"); return; } + if (!ast_strlen_zero(args->reason_code)) { + /* reason_code allows any hangup code */ + if (sscanf(args->reason_code, "%30d", &cause) != 1) { + ast_ari_response_error( + response, 400, "Invalid Reason Code", + "Invalid reason for hangup reason code provided"); + return; + } + } else if (!ast_strlen_zero(args->reason)) { + /* reason allows only listed hangup reason */ + cause = convert_reason_to_hangup_code(args->reason); + if (cause == -1) { + ast_ari_response_error( + response, 400, "Invalid Reason", + "Invalid reason for hangup reason provided"); + return; + } + } else { + /* not specified. set default hangup */ + cause = AST_CAUSE_NORMAL; + } + ast_channel_hangupcause_set(chan, cause); ast_softhangup(chan, AST_SOFTHANGUP_EXPLICIT); diff --git a/res/ari/resource_channels.h b/res/ari/resource_channels.h index 401c8a5651a1933b1e129ded841621b38dde9ba4..8aefb40479e6f2fc57afc0809052c7e2e37e638d 100644 --- a/res/ari/resource_channels.h +++ b/res/ari/resource_channels.h @@ -207,7 +207,9 @@ void ast_ari_channels_originate_with_id(struct ast_variable *headers, struct ast struct ast_ari_channels_hangup_args { /*! Channel's id */ const char *channel_id; - /*! Reason for hanging up the channel */ + /*! The reason code for hanging up the channel for detail use. Mutually exclusive with 'reason'. See detail hangup codes at here. https://wiki.asterisk.org/wiki/display/AST/Hangup+Cause+Mappings */ + const char *reason_code; + /*! Reason for hanging up the channel for simple use. Mutually exclusive with 'reason_code'. */ const char *reason; }; /*! diff --git a/res/res_ari_channels.c b/res/res_ari_channels.c index 73d1e4b2df25841694ba5f77bf098d6b90afd6c6..825d4c2704014bd12ea69382f153ab4c3985fb4f 100644 --- a/res/res_ari_channels.c +++ b/res/res_ari_channels.c @@ -598,6 +598,10 @@ int ast_ari_channels_hangup_parse_body( { struct ast_json *field; /* Parse query parameters out of it */ + field = ast_json_object_get(body, "reason_code"); + if (field) { + args->reason_code = ast_json_string_get(field); + } field = ast_json_object_get(body, "reason"); if (field) { args->reason = ast_json_string_get(field); @@ -625,6 +629,9 @@ static void ast_ari_channels_hangup_cb( #endif /* AST_DEVMODE */ for (i = get_params; i; i = i->next) { + if (strcmp(i->name, "reason_code") == 0) { + args.reason_code = (i->value); + } else if (strcmp(i->name, "reason") == 0) { args.reason = (i->value); } else diff --git a/rest-api/api-docs/channels.json b/rest-api/api-docs/channels.json index 4ea5f5647cce6819e46fec995b7b3c26ad32f963..77412695bd9e816b24c35224efa12d4503e19200 100644 --- a/rest-api/api-docs/channels.json +++ b/rest-api/api-docs/channels.json @@ -406,14 +406,21 @@ "allowMultiple": false, "dataType": "string" }, + { + "name": "reason_code", + "description": "The reason code for hanging up the channel for detail use. Mutually exclusive with 'reason'. See detail hangup codes at here. https://wiki.asterisk.org/wiki/display/AST/Hangup+Cause+Mappings", + "paramType": "query", + "required": false, + "allowMultiple": false, + "dataType": "string" + }, { "name": "reason", - "description": "Reason for hanging up the channel", + "description": "Reason for hanging up the channel for simple use. Mutually exclusive with 'reason_code'.", "paramType": "query", "required": false, "allowMultiple": false, "dataType": "string", - "defalutValue": "normal", "allowableValues": { "valueType": "LIST", "values": [