FS-5865 --resolve mod_rayo: fix join/unjoin IQ result for mixers

This commit is contained in:
Chris Rienzo 2013-10-15 14:17:33 -04:00
parent 348e9ba1d1
commit ca32b7e357
1 changed files with 142 additions and 31 deletions

View File

@ -941,10 +941,11 @@ static void rayo_call_cleanup(struct rayo_actor *actor)
/* lost the race: pending join failed... send IQ result to client now. */
if (call->pending_join_request) {
iks *result = iks_new_error_detailed(call->pending_join_request, STANZA_ERROR_ITEM_NOT_FOUND, "call ended");
RAYO_SEND_REPLY(call, iks_find_attrib_soft(call->pending_join_request, "from"), result);
iks_delete(call->pending_join_request);
iks *request = call->pending_join_request;
iks *result = iks_new_error_detailed(request, STANZA_ERROR_ITEM_NOT_FOUND, "call ended");
call->pending_join_request = NULL;
RAYO_SEND_REPLY(call, iks_find_attrib_soft(request, "from"), result);
iks_delete(call->pending_join_request);
}
iks_delete(revent);
@ -1765,9 +1766,11 @@ static iks *join_call(struct rayo_call *call, switch_core_session_t *session, st
}
call->pending_join_request = iks_copy(node);
if (switch_ivr_uuid_bridge(rayo_call_get_uuid(call), rayo_call_get_uuid(b_call)) != SWITCH_STATUS_SUCCESS) {
response = iks_new_error_detailed(node, STANZA_ERROR_INTERNAL_SERVER_ERROR, "failed to bridge call");
iks_delete(call->pending_join_request);
iks *request = call->pending_join_request;
iks *result = iks_new_error_detailed(request, STANZA_ERROR_ITEM_NOT_FOUND, "failed to bridge call");
call->pending_join_request = NULL;
RAYO_SEND_REPLY(call, iks_find_attrib_soft(request, "from"), result);
iks_delete(call->pending_join_request);
}
RAYO_UNLOCK(b_call);
}
@ -1776,14 +1779,66 @@ static iks *join_call(struct rayo_call *call, switch_core_session_t *session, st
/**
* Execute command on session's conference
* @param session to execute conference API on
* @param conf_name of conference
* @param command to send to conference
* @param node IQ request
* @return response on failure
*/
static void exec_conference_api(switch_core_session_t *session, const char *conf_name, const char *command)
static iks *exec_conference_api(switch_core_session_t *session, const char *conf_name, const char *command, iks *node)
{
iks *response = NULL;
switch_stream_handle_t stream = { 0 };
const char *conf_member_id = switch_channel_get_variable(switch_core_session_get_channel(session), "conference_member_id");
SWITCH_STANDARD_STREAM(stream);
switch_api_execute("conference", switch_core_session_sprintf(session, "%s %s %s", conf_name, command, conf_member_id), NULL, &stream);
if (!zstr(stream.data) && strncmp("OK", stream.data, 2)) {
response = iks_new_error_detailed_printf(node, STANZA_ERROR_INTERNAL_SERVER_ERROR, "%s", stream.data);
}
switch_safe_free(stream.data);
return response;
}
/**
* Execute conference app on session
* @param session to execute conference API on
* @param command to send to conference (conference name, member flags, etc)
* @param node IQ request
* @return response on failure
*/
static iks *exec_conference_app(switch_core_session_t *session, const char *command, iks *node)
{
iks *response = NULL;
switch_event_t *execute_event = NULL;
switch_channel_t *channel = switch_core_session_get_channel(session);
/* conference requires local media on channel */
if (!switch_channel_media_ready(channel) && switch_channel_pre_answer(channel) != SWITCH_STATUS_SUCCESS) {
/* shit */
response = iks_new_error_detailed(node, STANZA_ERROR_INTERNAL_SERVER_ERROR, "failed to start media");
return response;
}
/* send execute conference event to session */
if (switch_event_create(&execute_event, SWITCH_EVENT_COMMAND) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "call-command", "execute");
switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "execute-app-name", "conference");
switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "execute-app-arg", command);
//switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "event_uuid", uuid);
switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "event-lock", "true");
if (!switch_channel_test_flag(channel, CF_PROXY_MODE)) {
switch_channel_set_flag(channel, CF_BLOCK_BROADCAST_UNTIL_MEDIA);
}
if (switch_core_session_queue_private_event(session, &execute_event, SWITCH_FALSE) != SWITCH_STATUS_SUCCESS) {
response = iks_new_error_detailed(node, STANZA_ERROR_INTERNAL_SERVER_ERROR, "failed to join mixer (queue event failed)");
if (execute_event) {
switch_event_destroy(&execute_event);
}
return response;
}
}
return response;
}
/**
@ -1803,14 +1858,20 @@ static iks *join_mixer(struct rayo_call *call, switch_core_session_t *session, s
if (call->joined_id) {
/* adjust join conference params */
if (!strcmp("duplex", direction)) {
exec_conference_api(session, mixer_name, "unmute");
exec_conference_api(session, mixer_name, "undeaf");
if ((response = exec_conference_api(session, mixer_name, "unmute", node)) ||
(response = exec_conference_api(session, mixer_name, "undeaf", node))) {
return response;
}
} else if (!strcmp("recv", direction)) {
exec_conference_api(session, mixer_name, "mute");
exec_conference_api(session, mixer_name, "undeaf");
if ((response = exec_conference_api(session, mixer_name, "mute", node)) ||
(response = exec_conference_api(session, mixer_name, "undeaf", node))) {
return response;
}
} else {
exec_conference_api(session, mixer_name, "unmute");
exec_conference_api(session, mixer_name, "deaf");
if ((response = exec_conference_api(session, mixer_name, "unmute", node)) ||
(response = exec_conference_api(session, mixer_name, "deaf", node))) {
return response;
}
}
response = iks_new_iq_result(node);
} else {
@ -1821,10 +1882,12 @@ static iks *join_mixer(struct rayo_call *call, switch_core_session_t *session, s
} else if (!strcmp("recv", direction)) {
conf_args = switch_core_session_sprintf(session, "%s+flags{mute}", conf_args);
}
if (switch_core_session_execute_application_async(session, "conference", conf_args) == SWITCH_STATUS_SUCCESS) {
response = iks_new_iq_result(node);
} else {
response = iks_new_error_detailed(node, STANZA_ERROR_INTERNAL_SERVER_ERROR, "failed execute conference app");
call->pending_join_request = iks_copy(node);
response = exec_conference_app(session, conf_args, node);
if (response) {
iks_delete(call->pending_join_request);
call->pending_join_request = NULL;
}
}
return response;
@ -1951,11 +2014,12 @@ static iks *unjoin_mixer(struct rayo_call *call, switch_core_session_t *session,
goto done;
}
/* ack command */
response = iks_new_iq_result(node);
/* kick the member */
exec_conference_api(session, mixer_name, "hup");
response = exec_conference_api(session, mixer_name, "hup", node);
if (!response) {
/* ack command */
response = iks_new_iq_result(node);
}
done:
@ -2538,6 +2602,15 @@ static void on_mixer_add_member_event(struct rayo_mixer *mixer, switch_event_t *
call->joined = JOINED_MIXER;
call->joined_id = switch_core_strdup(RAYO_POOL(call), rayo_mixer_get_name(mixer));
/* send IQ result to client now. */
if (call->pending_join_request) {
iks *request = call->pending_join_request;
iks *result = iks_new_iq_result(request);
call->pending_join_request = NULL;
RAYO_SEND_REPLY(call, iks_find_attrib_soft(request, "from"), result);
iks_delete(request);
}
/* send mixer joined event to member DCP */
add_member_event = iks_new_presence("joined", RAYO_NS, RAYO_JID(call), call->dcp_jid);
x = iks_find(add_member_event, "joined");
@ -2705,14 +2778,13 @@ static void on_call_bridge_event(struct rayo_client *rclient, switch_event_t *ev
call->joined_id = switch_core_strdup(RAYO_POOL(call), b_uuid);
/* send IQ result to client now. */
switch_mutex_lock(RAYO_ACTOR(call)->mutex);
if (call->pending_join_request) {
iks *result = iks_new_iq_result(call->pending_join_request);
RAYO_SEND_REPLY(call, iks_find_attrib_soft(call->pending_join_request, "from"), result);
iks_delete(call->pending_join_request);
iks *request = call->pending_join_request;
iks *result = iks_new_iq_result(request);
call->pending_join_request = NULL;
RAYO_SEND_REPLY(call, iks_find_attrib_soft(request, "from"), result);
iks_delete(request);
}
switch_mutex_unlock(RAYO_ACTOR(call)->mutex);
/* send A-leg event */
revent = iks_new_presence("joined", RAYO_NS,
@ -2760,14 +2832,13 @@ static void on_call_unbridge_event(struct rayo_client *rclient, switch_event_t *
call->joined_id = NULL;
/* send IQ result to client now. */
switch_mutex_lock(RAYO_ACTOR(call)->mutex);
if (call->pending_join_request) {
iks *result = iks_new_iq_result(call->pending_join_request);
RAYO_SEND_REPLY(call, iks_find_attrib_soft(call->pending_join_request, "from"), result);
iks_delete(call->pending_join_request);
iks *request = call->pending_join_request;
iks *result = iks_new_iq_result(request);
call->pending_join_request = NULL;
RAYO_SEND_REPLY(call, iks_find_attrib_soft(request, "from"), result);
iks_delete(request);
}
switch_mutex_unlock(RAYO_ACTOR(call)->mutex);
/* send A-leg event */
revent = iks_new_presence("unjoined", RAYO_NS,
@ -2793,6 +2864,36 @@ static void on_call_unbridge_event(struct rayo_client *rclient, switch_event_t *
}
}
/**
* Handle call execute application event
* @param rclient the Rayo client
* @param event the execute event
*/
static void on_call_execute_event(struct rayo_client *rclient, switch_event_t *event)
{
struct rayo_call *call = RAYO_CALL_LOCATE_BY_ID(switch_event_get_header(event, "Unique-ID"));
if (call) {
switch_log_printf(SWITCH_CHANNEL_UUID_LOG(RAYO_ID(call)), SWITCH_LOG_DEBUG, "Application %s execute\n", switch_event_get_header(event, "Application"));
RAYO_UNLOCK(call);
}
}
/**
* Handle call execute application complete event
* @param rclient the Rayo client
* @param event the execute complete event
*/
static void on_call_execute_complete_event(struct rayo_client *rclient, switch_event_t *event)
{
struct rayo_call *call = RAYO_CALL_LOCATE_BY_ID(switch_event_get_header(event, "Unique-ID"));
if (call) {
const char *app = switch_event_get_header(event, "Application");
switch_log_printf(SWITCH_CHANNEL_UUID_LOG(RAYO_ID(call)), SWITCH_LOG_DEBUG, "Application %s execute complete: %s \n",
app,
switch_event_get_header(event, "Application-Response"));
RAYO_UNLOCK(call);
}
}
/**
* Handle events to deliver to client connection
@ -2819,6 +2920,12 @@ static void rayo_client_handle_event(struct rayo_client *rclient, switch_event_t
case SWITCH_EVENT_CHANNEL_UNBRIDGE:
on_call_unbridge_event(rclient, event);
break;
case SWITCH_EVENT_CHANNEL_EXECUTE:
on_call_execute_event(rclient, event);
break;
case SWITCH_EVENT_CHANNEL_EXECUTE_COMPLETE:
on_call_execute_complete_event(rclient, event);
break;
default:
/* don't care */
break;
@ -2944,7 +3051,9 @@ static switch_status_t rayo_call_on_read_frame(switch_core_session_t *session, s
switch_time_t idle_start = call->idle_start_time;
int idle_duration_ms = (now - idle_start) / 1000;
/* detect idle session (rayo-client has stopped controlling call) and terminate call */
if (!rayo_call_is_joined(call) && idle_duration_ms > globals.max_idle_ms) {
if (rayo_call_is_joined(call)) {
call->idle_start_time = now;
} else if (idle_duration_ms > globals.max_idle_ms) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Ending abandoned call. idle_duration_ms = %i ms\n", idle_duration_ms);
switch_channel_hangup(channel, RAYO_CAUSE_HANGUP);
}
@ -3891,6 +4000,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_rayo_load)
switch_event_bind(modname, SWITCH_EVENT_CHANNEL_ANSWER, NULL, route_call_event, NULL);
switch_event_bind(modname, SWITCH_EVENT_CHANNEL_BRIDGE, NULL, route_call_event, NULL);
switch_event_bind(modname, SWITCH_EVENT_CHANNEL_UNBRIDGE, NULL, route_call_event, NULL);
switch_event_bind(modname, SWITCH_EVENT_CHANNEL_EXECUTE, NULL, route_call_event, NULL);
switch_event_bind(modname, SWITCH_EVENT_CHANNEL_EXECUTE_COMPLETE, NULL, route_call_event, NULL);
switch_event_bind(modname, SWITCH_EVENT_CHANNEL_DESTROY, NULL, on_call_end_event, NULL);