|
|
@ -53,7 +53,92 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
|
|
|
|
|
|
|
|
|
|
|
#define MAX_VALS 128
|
|
|
|
#define MAX_VALS 128
|
|
|
|
|
|
|
|
|
|
|
|
static void ast_ari_events_event_websocket_ws_cb(struct ast_websocket *ws_session,
|
|
|
|
static int ast_ari_events_event_websocket_ws_attempted_cb(struct ast_tcptls_session_instance *ser, struct ast_variable *get_params, struct ast_variable *headers)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
struct ast_ari_events_event_websocket_args args = {};
|
|
|
|
|
|
|
|
int res = 0;
|
|
|
|
|
|
|
|
RAII_VAR(struct ast_ari_response *, response, NULL, ast_free);
|
|
|
|
|
|
|
|
struct ast_variable *i;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
response = ast_calloc(1, sizeof(*response));
|
|
|
|
|
|
|
|
if (!response) {
|
|
|
|
|
|
|
|
ast_log(LOG_ERROR, "Failed to create response.\n");
|
|
|
|
|
|
|
|
goto fin;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (i = get_params; i; i = i->next) {
|
|
|
|
|
|
|
|
if (strcmp(i->name, "app") == 0) {
|
|
|
|
|
|
|
|
/* Parse comma separated list */
|
|
|
|
|
|
|
|
char *vals[MAX_VALS];
|
|
|
|
|
|
|
|
size_t j;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
args.app_parse = ast_strdup(i->value);
|
|
|
|
|
|
|
|
if (!args.app_parse) {
|
|
|
|
|
|
|
|
ast_ari_response_alloc_failed(response);
|
|
|
|
|
|
|
|
goto fin;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (strlen(args.app_parse) == 0) {
|
|
|
|
|
|
|
|
/* ast_app_separate_args can't handle "" */
|
|
|
|
|
|
|
|
args.app_count = 1;
|
|
|
|
|
|
|
|
vals[0] = args.app_parse;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
args.app_count = ast_app_separate_args(
|
|
|
|
|
|
|
|
args.app_parse, ',', vals,
|
|
|
|
|
|
|
|
ARRAY_LEN(vals));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (args.app_count == 0) {
|
|
|
|
|
|
|
|
ast_ari_response_alloc_failed(response);
|
|
|
|
|
|
|
|
goto fin;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (args.app_count >= MAX_VALS) {
|
|
|
|
|
|
|
|
ast_ari_response_error(response, 400,
|
|
|
|
|
|
|
|
"Bad Request",
|
|
|
|
|
|
|
|
"Too many values for app");
|
|
|
|
|
|
|
|
goto fin;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
args.app = ast_malloc(sizeof(*args.app) * args.app_count);
|
|
|
|
|
|
|
|
if (!args.app) {
|
|
|
|
|
|
|
|
ast_ari_response_alloc_failed(response);
|
|
|
|
|
|
|
|
goto fin;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (j = 0; j < args.app_count; ++j) {
|
|
|
|
|
|
|
|
args.app[j] = (vals[j]);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} else
|
|
|
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
res = ast_ari_websocket_events_event_websocket_attempted(ser, headers, &args);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fin: __attribute__((unused))
|
|
|
|
|
|
|
|
if (!response) {
|
|
|
|
|
|
|
|
ast_http_error(ser, 500, "Server Error", "Memory allocation error");
|
|
|
|
|
|
|
|
res = -1;
|
|
|
|
|
|
|
|
} else if (response->response_code != 0) {
|
|
|
|
|
|
|
|
/* Param parsing failure */
|
|
|
|
|
|
|
|
RAII_VAR(char *, msg, NULL, ast_json_free);
|
|
|
|
|
|
|
|
if (response->message) {
|
|
|
|
|
|
|
|
msg = ast_json_dump_string(response->message);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
ast_log(LOG_ERROR, "Missing response message\n");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (msg) {
|
|
|
|
|
|
|
|
ast_http_error(ser, response->response_code, response->response_text, msg);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
res = -1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
ast_free(args.app_parse);
|
|
|
|
|
|
|
|
ast_free(args.app);
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void ast_ari_events_event_websocket_ws_established_cb(struct ast_websocket *ws_session,
|
|
|
|
struct ast_variable *get_params, struct ast_variable *headers)
|
|
|
|
struct ast_variable *get_params, struct ast_variable *headers)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
struct ast_ari_events_event_websocket_args args = {};
|
|
|
|
struct ast_ari_events_event_websocket_args args = {};
|
|
|
@ -126,16 +211,11 @@ static void ast_ari_events_event_websocket_ws_cb(struct ast_websocket *ws_sessio
|
|
|
|
{}
|
|
|
|
{}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ast_ari_websocket_events_event_websocket(session, headers, &args);
|
|
|
|
ast_ari_websocket_events_event_websocket_established(session, headers, &args);
|
|
|
|
|
|
|
|
|
|
|
|
fin: __attribute__((unused))
|
|
|
|
fin: __attribute__((unused))
|
|
|
|
if (response && response->response_code != 0) {
|
|
|
|
if (response && response->response_code != 0) {
|
|
|
|
/* Param parsing failure */
|
|
|
|
/* Param parsing failure */
|
|
|
|
/* TODO - ideally, this would return the error code to the
|
|
|
|
|
|
|
|
* HTTP client; but we've already done the WebSocket
|
|
|
|
|
|
|
|
* negotiation. Param parsing should happen earlier, but we
|
|
|
|
|
|
|
|
* need a way to pass it through the WebSocket code to the
|
|
|
|
|
|
|
|
* callback */
|
|
|
|
|
|
|
|
RAII_VAR(char *, msg, NULL, ast_json_free);
|
|
|
|
RAII_VAR(char *, msg, NULL, ast_json_free);
|
|
|
|
if (response->message) {
|
|
|
|
if (response->message) {
|
|
|
|
msg = ast_json_dump_string(response->message);
|
|
|
|
msg = ast_json_dump_string(response->message);
|
|
|
@ -351,12 +431,22 @@ static struct stasis_rest_handlers events = {
|
|
|
|
static int load_module(void)
|
|
|
|
static int load_module(void)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int res = 0;
|
|
|
|
int res = 0;
|
|
|
|
|
|
|
|
struct ast_websocket_protocol *protocol;
|
|
|
|
|
|
|
|
|
|
|
|
events.ws_server = ast_websocket_server_create();
|
|
|
|
events.ws_server = ast_websocket_server_create();
|
|
|
|
if (!events.ws_server) {
|
|
|
|
if (!events.ws_server) {
|
|
|
|
return AST_MODULE_LOAD_FAILURE;
|
|
|
|
return AST_MODULE_LOAD_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
res |= ast_websocket_server_add_protocol(events.ws_server,
|
|
|
|
|
|
|
|
"ari", ast_ari_events_event_websocket_ws_cb);
|
|
|
|
protocol = ast_websocket_sub_protocol_alloc("ari");
|
|
|
|
|
|
|
|
if (!protocol) {
|
|
|
|
|
|
|
|
ao2_ref(events.ws_server, -1);
|
|
|
|
|
|
|
|
events.ws_server = NULL;
|
|
|
|
|
|
|
|
return AST_MODULE_LOAD_FAILURE;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
protocol->session_attempted = ast_ari_events_event_websocket_ws_attempted_cb;
|
|
|
|
|
|
|
|
protocol->session_established = ast_ari_events_event_websocket_ws_established_cb;
|
|
|
|
|
|
|
|
res |= ast_websocket_server_add_protocol2(events.ws_server, protocol);
|
|
|
|
stasis_app_ref();
|
|
|
|
stasis_app_ref();
|
|
|
|
res |= ast_ari_add_handler(&events);
|
|
|
|
res |= ast_ari_add_handler(&events);
|
|
|
|
return res;
|
|
|
|
return res;
|
|
|
|