Merge "ARI: Ensure proper channel state on operations."

This commit is contained in:
zuul 2016-06-09 21:50:07 -05:00 committed by Gerrit Code Review
commit 39e6d80937
3 changed files with 195 additions and 0 deletions

View File

@ -53,6 +53,60 @@ ASTERISK_REGISTER_FILE()
#include <limits.h>
/*!
* \brief Ensure channel is in a state that allows operation to be performed.
*
* Since Asterisk 14, it has been possible for down channels, as well as unanswered
* outbound channels to enter Stasis. While some operations are fine to perform on
* such channels, operations that
*
* - Attempt to manipulate channel state
* - Attempt to play media
* - Attempt to control the channel's location in the dialplan
*
* are invalid. This function can be used to determine if the channel is in an
* appropriate state.
*
* \note When this function returns an error, the HTTP response is taken care of.
*
* \param control The app control
* \param response Response to fill in if there is an error
*
* \retval 0 Channel is in a valid state. Continue on!
* \retval non-zero Channel is in an invalid state. Bail!
*/
static int channel_state_invalid(struct stasis_app_control *control,
struct ast_ari_response *response)
{
struct ast_channel_snapshot *snapshot;
snapshot = stasis_app_control_get_snapshot(control);
if (!snapshot) {
ast_ari_response_error(response, 404, "Not Found", "Channel not found");
return -1;
}
/* These channel states apply only to outbound channels:
* - Down: Channel has been created, and nothing else has been done
* - Reserved: For a PRI, an underlying B-channel is reserved,
* but the channel is not yet dialed
* - Ringing: The channel has been dialed.
*
* This does not affect inbound channels. Inbound channels, when they
* enter the dialplan, are in the "Ring" state. If they have already
* been answered, then they are in the "Up" state.
*/
if (snapshot->state == AST_STATE_DOWN
|| snapshot->state == AST_STATE_RESERVED
|| snapshot->state == AST_STATE_RINGING) {
ast_ari_response_error(response, 412, "Precondition Failed",
"Channel in invalid state");
return -1;
}
return 0;
}
/*!
* \brief Finds the control object for a channel, filling the response with an
* error, if appropriate.
@ -107,8 +161,13 @@ void ast_ari_channels_continue_in_dialplan(
return;
}
if (channel_state_invalid(control, response)) {
return;
}
snapshot = stasis_app_control_get_snapshot(control);
if (!snapshot) {
ast_ari_response_error(response, 404, "Not Found", "Channel not found");
return;
}
@ -175,6 +234,10 @@ void ast_ari_channels_redirect(struct ast_variable *headers,
return;
}
if (channel_state_invalid(control, response)) {
return;
}
if (ast_strlen_zero(args->endpoint)) {
ast_ari_response_error(response, 400, "Not Found",
"Required parameter 'endpoint' not provided.");
@ -229,6 +292,10 @@ void ast_ari_channels_answer(struct ast_variable *headers,
return;
}
if (channel_state_invalid(control, response)) {
return;
}
if (stasis_app_control_answer(control) != 0) {
ast_ari_response_error(
response, 500, "Internal Server Error",
@ -250,6 +317,10 @@ void ast_ari_channels_ring(struct ast_variable *headers,
return;
}
if (channel_state_invalid(control, response)) {
return;
}
stasis_app_control_ring(control);
ast_ari_response_no_content(response);
@ -266,6 +337,10 @@ void ast_ari_channels_ring_stop(struct ast_variable *headers,
return;
}
if (channel_state_invalid(control, response)) {
return;
}
stasis_app_control_ring_stop(control);
ast_ari_response_no_content(response);
@ -284,6 +359,10 @@ void ast_ari_channels_mute(struct ast_variable *headers,
return;
}
if (channel_state_invalid(control, response)) {
return;
}
if (ast_strlen_zero(args->direction)) {
ast_ari_response_error(
response, 400, "Bad Request",
@ -322,6 +401,10 @@ void ast_ari_channels_unmute(struct ast_variable *headers,
return;
}
if (channel_state_invalid(control, response)) {
return;
}
if (ast_strlen_zero(args->direction)) {
ast_ari_response_error(
response, 400, "Bad Request",
@ -358,6 +441,10 @@ void ast_ari_channels_send_dtmf(struct ast_variable *headers,
return;
}
if (channel_state_invalid(control, response)) {
return;
}
if (ast_strlen_zero(args->dtmf)) {
ast_ari_response_error(
response, 400, "Bad Request",
@ -382,6 +469,10 @@ void ast_ari_channels_hold(struct ast_variable *headers,
return;
}
if (channel_state_invalid(control, response)) {
return;
}
stasis_app_control_hold(control);
ast_ari_response_no_content(response);
@ -399,6 +490,10 @@ void ast_ari_channels_unhold(struct ast_variable *headers,
return;
}
if (channel_state_invalid(control, response)) {
return;
}
stasis_app_control_unhold(control);
ast_ari_response_no_content(response);
@ -416,6 +511,10 @@ void ast_ari_channels_start_moh(struct ast_variable *headers,
return;
}
if (channel_state_invalid(control, response)) {
return;
}
stasis_app_control_moh_start(control, args->moh_class);
ast_ari_response_no_content(response);
}
@ -432,6 +531,10 @@ void ast_ari_channels_stop_moh(struct ast_variable *headers,
return;
}
if (channel_state_invalid(control, response)) {
return;
}
stasis_app_control_moh_stop(control);
ast_ari_response_no_content(response);
}
@ -448,6 +551,10 @@ void ast_ari_channels_start_silence(struct ast_variable *headers,
return;
}
if (channel_state_invalid(control, response)) {
return;
}
stasis_app_control_silence_start(control);
ast_ari_response_no_content(response);
}
@ -464,6 +571,10 @@ void ast_ari_channels_stop_silence(struct ast_variable *headers,
return;
}
if (channel_state_invalid(control, response)) {
return;
}
stasis_app_control_silence_stop(control);
ast_ari_response_no_content(response);
}
@ -493,6 +604,10 @@ static void ari_channels_handle_play(
return;
}
if (channel_state_invalid(control, response)) {
return;
}
snapshot = stasis_app_control_get_snapshot(control);
if (!snapshot) {
ast_ari_response_error(

View File

@ -832,6 +832,7 @@ static void ast_ari_channels_continue_in_dialplan_cb(
case 501: /* Not Implemented */
case 404: /* Channel not found */
case 409: /* Channel not in a Stasis application */
case 412: /* Channel in invalid state */
is_valid = 1;
break;
default:
@ -932,6 +933,7 @@ static void ast_ari_channels_redirect_cb(
case 404: /* Channel or endpoint not found */
case 409: /* Channel not in a Stasis application */
case 422: /* Endpoint is not the same type as the channel */
case 412: /* Channel in invalid state */
is_valid = 1;
break;
default:
@ -992,6 +994,7 @@ static void ast_ari_channels_answer_cb(
case 501: /* Not Implemented */
case 404: /* Channel not found */
case 409: /* Channel not in a Stasis application */
case 412: /* Channel in invalid state */
is_valid = 1;
break;
default:
@ -1052,6 +1055,7 @@ static void ast_ari_channels_ring_cb(
case 501: /* Not Implemented */
case 404: /* Channel not found */
case 409: /* Channel not in a Stasis application */
case 412: /* Channel in invalid state */
is_valid = 1;
break;
default:
@ -1112,6 +1116,7 @@ static void ast_ari_channels_ring_stop_cb(
case 501: /* Not Implemented */
case 404: /* Channel not found */
case 409: /* Channel not in a Stasis application */
case 412: /* Channel in invalid state */
is_valid = 1;
break;
default:
@ -1239,6 +1244,7 @@ static void ast_ari_channels_send_dtmf_cb(
case 400: /* DTMF is required */
case 404: /* Channel not found */
case 409: /* Channel not in a Stasis application */
case 412: /* Channel in invalid state */
is_valid = 1;
break;
default:
@ -1337,6 +1343,7 @@ static void ast_ari_channels_mute_cb(
case 501: /* Not Implemented */
case 404: /* Channel not found */
case 409: /* Channel not in a Stasis application */
case 412: /* Channel in invalid state */
is_valid = 1;
break;
default:
@ -1435,6 +1442,7 @@ static void ast_ari_channels_unmute_cb(
case 501: /* Not Implemented */
case 404: /* Channel not found */
case 409: /* Channel not in a Stasis application */
case 412: /* Channel in invalid state */
is_valid = 1;
break;
default:
@ -1495,6 +1503,7 @@ static void ast_ari_channels_hold_cb(
case 501: /* Not Implemented */
case 404: /* Channel not found */
case 409: /* Channel not in a Stasis application */
case 412: /* Channel in invalid state */
is_valid = 1;
break;
default:
@ -1555,6 +1564,7 @@ static void ast_ari_channels_unhold_cb(
case 501: /* Not Implemented */
case 404: /* Channel not found */
case 409: /* Channel not in a Stasis application */
case 412: /* Channel in invalid state */
is_valid = 1;
break;
default:
@ -1653,6 +1663,7 @@ static void ast_ari_channels_start_moh_cb(
case 501: /* Not Implemented */
case 404: /* Channel not found */
case 409: /* Channel not in a Stasis application */
case 412: /* Channel in invalid state */
is_valid = 1;
break;
default:
@ -1713,6 +1724,7 @@ static void ast_ari_channels_stop_moh_cb(
case 501: /* Not Implemented */
case 404: /* Channel not found */
case 409: /* Channel not in a Stasis application */
case 412: /* Channel in invalid state */
is_valid = 1;
break;
default:
@ -1773,6 +1785,7 @@ static void ast_ari_channels_start_silence_cb(
case 501: /* Not Implemented */
case 404: /* Channel not found */
case 409: /* Channel not in a Stasis application */
case 412: /* Channel in invalid state */
is_valid = 1;
break;
default:
@ -1833,6 +1846,7 @@ static void ast_ari_channels_stop_silence_cb(
case 501: /* Not Implemented */
case 404: /* Channel not found */
case 409: /* Channel not in a Stasis application */
case 412: /* Channel in invalid state */
is_valid = 1;
break;
default:
@ -2024,6 +2038,7 @@ static void ast_ari_channels_play_cb(
case 501: /* Not Implemented */
case 404: /* Channel not found */
case 409: /* Channel not in a Stasis application */
case 412: /* Channel in invalid state */
is_valid = 1;
break;
default:
@ -2213,6 +2228,7 @@ static void ast_ari_channels_play_with_id_cb(
case 501: /* Not Implemented */
case 404: /* Channel not found */
case 409: /* Channel not in a Stasis application */
case 412: /* Channel in invalid state */
is_valid = 1;
break;
default:

View File

@ -477,6 +477,10 @@
{
"code": 409,
"reason": "Channel not in a Stasis application"
},
{
"code": 412,
"reason": "Channel in invalid state"
}
]
}
@ -525,6 +529,10 @@
{
"code": 422,
"reason": "Endpoint is not the same type as the channel"
},
{
"code": 412,
"reason": "Channel in invalid state"
}
]
}
@ -557,6 +565,10 @@
{
"code": 409,
"reason": "Channel not in a Stasis application"
},
{
"code": 412,
"reason": "Channel in invalid state"
}
]
}
@ -589,6 +601,10 @@
{
"code": 409,
"reason": "Channel not in a Stasis application"
},
{
"code": 412,
"reason": "Channel in invalid state"
}
]
},
@ -615,6 +631,10 @@
{
"code": 409,
"reason": "Channel not in a Stasis application"
},
{
"code": 412,
"reason": "Channel in invalid state"
}
]
}
@ -695,6 +715,10 @@
{
"code": 409,
"reason": "Channel not in a Stasis application"
},
{
"code": 412,
"reason": "Channel in invalid state"
}
]
}
@ -744,6 +768,10 @@
{
"code": 409,
"reason": "Channel not in a Stasis application"
},
{
"code": 412,
"reason": "Channel in invalid state"
}
]
},
@ -787,6 +815,10 @@
{
"code": 409,
"reason": "Channel not in a Stasis application"
},
{
"code": 412,
"reason": "Channel in invalid state"
}
]
}
@ -819,6 +851,10 @@
{
"code": 409,
"reason": "Channel not in a Stasis application"
},
{
"code": 412,
"reason": "Channel in invalid state"
}
]
},
@ -845,6 +881,10 @@
{
"code": 409,
"reason": "Channel not in a Stasis application"
},
{
"code": 412,
"reason": "Channel in invalid state"
}
]
}
@ -886,6 +926,10 @@
{
"code": 409,
"reason": "Channel not in a Stasis application"
},
{
"code": 412,
"reason": "Channel in invalid state"
}
]
},
@ -912,6 +956,10 @@
{
"code": 409,
"reason": "Channel not in a Stasis application"
},
{
"code": 412,
"reason": "Channel in invalid state"
}
]
}
@ -945,6 +993,10 @@
{
"code": 409,
"reason": "Channel not in a Stasis application"
},
{
"code": 412,
"reason": "Channel in invalid state"
}
]
},
@ -971,6 +1023,10 @@
{
"code": 409,
"reason": "Channel not in a Stasis application"
},
{
"code": 412,
"reason": "Channel in invalid state"
}
]
}
@ -1045,6 +1101,10 @@
{
"code": 409,
"reason": "Channel not in a Stasis application"
},
{
"code": 412,
"reason": "Channel in invalid state"
}
]
}
@ -1119,6 +1179,10 @@
{
"code": 409,
"reason": "Channel not in a Stasis application"
},
{
"code": 412,
"reason": "Channel in invalid state"
}
]
}