/**
 * Pass output component command
 */
static iks *forward_output_component_request(struct rayo_actor *prompt, struct rayo_message *msg, void *data)
{
	iks *iq = msg->payload;
	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s (%s) %s prompt\n",
		RAYO_JID(prompt), prompt_component_state_to_string(PROMPT_COMPONENT(prompt)->state), iks_name(iks_first_tag(iq)));

	switch (PROMPT_COMPONENT(prompt)->state) {
		case PCS_OUTPUT:
		case PCS_START_INPUT_OUTPUT:
		case PCS_INPUT_OUTPUT: {
			/* forward request to output component */
			iks_insert_attrib(iq, "from", RAYO_JID(prompt));
			iks_insert_attrib(iq, "to", PROMPT_COMPONENT(prompt)->output_jid);
			RAYO_SEND_MESSAGE_DUP(prompt, PROMPT_COMPONENT(prompt)->output_jid, iq);
			return NULL;
		}
		case PCS_START_INPUT_TIMERS:
		case PCS_START_OUTPUT:
		case PCS_START_OUTPUT_BARGE:
			/* ref hasn't been sent yet */
			return iks_new_error_detailed(iq, STANZA_ERROR_UNEXPECTED_REQUEST, "too soon");
			break;
		case PCS_START_INPUT:
		case PCS_STOP_OUTPUT:
		case PCS_DONE_STOP_OUTPUT:
		case PCS_INPUT:
		case PCS_DONE:
			return iks_new_error_detailed(iq, STANZA_ERROR_UNEXPECTED_REQUEST, "output is finished");
	}
	return NULL;
}
/**
 * Handle barge event
 */
static iks *prompt_component_handle_input_barge(struct rayo_actor *prompt, struct rayo_message *msg, void *data)
{
	iks *presence = msg->payload;
	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s (%s) input barge\n",
		RAYO_JID(prompt), prompt_component_state_to_string(PROMPT_COMPONENT(prompt)->state));

	switch (PROMPT_COMPONENT(prompt)->state) {
		case PCS_INPUT_OUTPUT:
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s, got <start-of-input> from %s: %s\n",
				RAYO_JID(prompt), msg->from_jid, iks_string(iks_stack(presence), presence));
			PROMPT_COMPONENT(prompt)->state = PCS_STOP_OUTPUT;
			rayo_component_send_stop(prompt, PROMPT_COMPONENT(prompt)->output_jid);
			break;
		case PCS_STOP_OUTPUT:
		case PCS_INPUT:
			/* don't care */
			break;
		case PCS_OUTPUT:
		case PCS_START_OUTPUT:
		case PCS_START_OUTPUT_BARGE:
		case PCS_START_INPUT:
		case PCS_START_INPUT_OUTPUT:
		case PCS_START_INPUT_TIMERS:
		case PCS_DONE_STOP_OUTPUT:
		case PCS_DONE:
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s, unexpected start output error event\n", RAYO_JID(prompt));
			break;
	}
	return NULL;
}
/**
 * Handle input failure.
 */
static iks *prompt_component_handle_input_error(struct rayo_actor *prompt, struct rayo_message *msg, void *data)
{
	iks *iq = msg->payload;
	iks *error = iks_find(iq, "error");

	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s (%s) input error\n",
		RAYO_JID(prompt), prompt_component_state_to_string(PROMPT_COMPONENT(prompt)->state));

	switch (PROMPT_COMPONENT(prompt)->state) {
		case PCS_START_INPUT_TIMERS:
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s, <input> error: %s\n", RAYO_JID(prompt), iks_string(iks_stack(iq), iq));
			PROMPT_COMPONENT(prompt)->state = PCS_DONE;

			/* forward IQ error to client */
			iq = PROMPT_COMPONENT(prompt)->iq;
			iks_insert_attrib(iq, "from", RAYO_JID(RAYO_COMPONENT(prompt)->parent));
			iks_insert_attrib(iq, "to", RAYO_COMPONENT(prompt)->client_jid);
			iks_insert_node(iq, iks_copy_within(error, iks_stack(iq)));
			RAYO_SEND_REPLY(prompt, RAYO_COMPONENT(prompt)->client_jid, iq);

			/* done */
			RAYO_UNLOCK(prompt);
			RAYO_DESTROY(prompt);

			break;

		case PCS_START_INPUT:
			/* send presence error to client */
			PROMPT_COMPONENT(prompt)->state = PCS_DONE;
			iks_delete(PROMPT_COMPONENT(prompt)->iq);
			rayo_component_send_complete(RAYO_COMPONENT(prompt), COMPONENT_COMPLETE_ERROR);
			break;
		case PCS_START_INPUT_OUTPUT:
			PROMPT_COMPONENT(prompt)->state = PCS_DONE_STOP_OUTPUT;

			/* forward IQ error to client */
			iq = PROMPT_COMPONENT(prompt)->iq;
			iks_insert_attrib(iq, "from", RAYO_JID(RAYO_COMPONENT(prompt)->parent));
			iks_insert_attrib(iq, "to", RAYO_COMPONENT(prompt)->client_jid);
			iks_insert_node(iq, iks_copy_within(error, iks_stack(iq)));
			PROMPT_COMPONENT(prompt)->complete = iq;

			rayo_component_send_stop(prompt, PROMPT_COMPONENT(prompt)->output_jid);
			break;
		case PCS_START_OUTPUT:
		case PCS_START_OUTPUT_BARGE:
		case PCS_INPUT_OUTPUT:
		case PCS_STOP_OUTPUT:
		case PCS_INPUT:
		case PCS_OUTPUT:
		case PCS_DONE_STOP_OUTPUT:
		case PCS_DONE:
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s, unexpected start input error event\n", RAYO_JID(prompt));
			break;
	}

	return NULL;
}
/**
 * Handle start of output.
 */
static iks *prompt_component_handle_output_start(struct rayo_actor *prompt, struct rayo_message *msg, void *data)
{
	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s (%s) output start\n",
		RAYO_JID(prompt), prompt_component_state_to_string(PROMPT_COMPONENT(prompt)->state));

	switch (PROMPT_COMPONENT(prompt)->state) {
		case PCS_START_OUTPUT:
			PROMPT_COMPONENT(prompt)->output_jid = switch_core_strdup(RAYO_POOL(prompt), msg->from_jid);
			PROMPT_COMPONENT(prompt)->state = PCS_OUTPUT;
			/* send ref to client */
			rayo_component_send_start(RAYO_COMPONENT(prompt), PROMPT_COMPONENT(prompt)->iq);
			break;
		case PCS_START_OUTPUT_BARGE:
			PROMPT_COMPONENT(prompt)->output_jid = switch_core_strdup(RAYO_POOL(prompt), msg->from_jid);
			PROMPT_COMPONENT(prompt)->state = PCS_START_INPUT_OUTPUT;
			/* start input without timers and with barge events */
			start_input(PROMPT_COMPONENT(prompt), 0, 1);
			break;
		case PCS_OUTPUT:
		case PCS_START_INPUT_OUTPUT:
		case PCS_START_INPUT:
		case PCS_START_INPUT_TIMERS:
		case PCS_INPUT_OUTPUT:
		case PCS_STOP_OUTPUT:
		case PCS_INPUT:
		case PCS_DONE_STOP_OUTPUT:
		case PCS_DONE:
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s, unexpected start output event\n", RAYO_JID(prompt));
			break;
	}

	return NULL;
}
Exemple #5
0
/**
 * Forward result
 */
static iks *prompt_component_handle_result(struct rayo_actor *prompt, struct rayo_message *msg, void *data)
{
	iks *iq = msg->payload;

	/* forward all results, except for internal ones... */
	const char *id = iks_find_attrib_soft(iq, "id");
	if (strncmp("mod_rayo-prompt", id, 15)) {
		iks_insert_attrib(iq, "from", RAYO_JID(prompt));
		iks_insert_attrib(iq, "to", RAYO_COMPONENT(prompt)->client_jid);
		RAYO_SEND_REPLY_DUP(prompt, RAYO_COMPONENT(prompt)->client_jid, iq);
	} else if (!zstr(PROMPT_COMPONENT(prompt)->start_timers_request_id) && !strcmp(PROMPT_COMPONENT(prompt)->start_timers_request_id, id)) {
		rayo_component_send_input_timers_started_event(RAYO_COMPONENT(prompt));
	}

	return NULL;
}
/**
 * Handle barge event
 */
static iks *prompt_component_handle_input_start_timers_error(struct rayo_actor *prompt, struct rayo_message *msg, void *data)
{
	/* this is only expected if input component is gone */
	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s (%s) start timers error\n",
		RAYO_JID(prompt), prompt_component_state_to_string(PROMPT_COMPONENT(prompt)->state));

	return NULL;
}
Exemple #7
0
/**
 * Handle completion event
 */
static iks *prompt_component_handle_input_complete(struct rayo_actor *prompt, struct rayo_message *msg, void *data)
{
	iks *presence = msg->payload;
	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s (%s) input complete\n",
		RAYO_JID(prompt), prompt_component_state_to_string(PROMPT_COMPONENT(prompt)->state));

	switch (PROMPT_COMPONENT(prompt)->state) {
		case PCS_INPUT_OUTPUT:
			PROMPT_COMPONENT(prompt)->state = PCS_DONE_STOP_OUTPUT;
			presence = iks_copy(presence);
			iks_insert_attrib(presence, "from", RAYO_JID(prompt));
			iks_insert_attrib(presence, "to", RAYO_COMPONENT(prompt)->client_jid);
			PROMPT_COMPONENT(prompt)->complete = presence;
			rayo_component_send_stop(prompt, PROMPT_COMPONENT(prompt)->output_jid);
			break;
		case PCS_STOP_OUTPUT:
			PROMPT_COMPONENT(prompt)->state = PCS_DONE_STOP_OUTPUT;
			presence = iks_copy(presence);
			iks_insert_attrib(presence, "from", RAYO_JID(prompt));
			iks_insert_attrib(presence, "to", RAYO_COMPONENT(prompt)->client_jid);
			PROMPT_COMPONENT(prompt)->complete = presence;
			break;
		case PCS_INPUT:
			PROMPT_COMPONENT(prompt)->state = PCS_DONE;
			/* pass through */
		case PCS_DONE:
			presence = iks_copy(presence);
			iks_insert_attrib(presence, "from", RAYO_JID(prompt));
			iks_insert_attrib(presence, "to", RAYO_COMPONENT(prompt)->client_jid);
			iks_delete(PROMPT_COMPONENT(prompt)->iq);
			rayo_component_send_complete_event(RAYO_COMPONENT(prompt), presence);
			break;
		case PCS_OUTPUT:
		case PCS_START_OUTPUT:
		case PCS_START_OUTPUT_BARGE:
		case PCS_START_INPUT:
		case PCS_START_INPUT_OUTPUT:
		case PCS_START_INPUT_TIMERS:
		case PCS_DONE_STOP_OUTPUT:
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s, unexpected start output error event\n", RAYO_JID(prompt));
			break;
	}

	return NULL;
}
/**
 * Start input component
 */
static void start_input(struct prompt_component *prompt, int start_timers, int barge_event)
{
	iks *iq = iks_new("iq");
	iks *input = iks_find(PROMPT_COMPONENT(prompt)->iq, "prompt");
	input = iks_find(input, "input");
	iks_insert_attrib(iq, "from", RAYO_JID(prompt));
	iks_insert_attrib(iq, "to", RAYO_JID(RAYO_COMPONENT(prompt)->parent));
	iks_insert_attrib_printf(iq, "id", "mod_rayo-prompt-%d", RAYO_SEQ_NEXT(prompt));
	iks_insert_attrib(iq, "type", "set");
	input = iks_copy_within(input, iks_stack(iq));
	iks_insert_attrib(input, "start-timers", start_timers ? "true" : "false");
	iks_insert_attrib(input, "barge-event", barge_event ? "true" : "false");
	iks_insert_node(iq, input);
	RAYO_SEND_MESSAGE(prompt, RAYO_JID(RAYO_COMPONENT(prompt)->parent), iq);
}
/**
 * Stop execution of prompt component
 */
static iks *stop_call_prompt_component(struct rayo_actor *prompt, struct rayo_message *msg, void *data)
{
	iks *iq = msg->payload;
	iks *reply = NULL;
	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s (%s) stop prompt\n",
		RAYO_JID(prompt), prompt_component_state_to_string(PROMPT_COMPONENT(prompt)->state));

	switch (PROMPT_COMPONENT(prompt)->state) {
		case PCS_OUTPUT:
			/* input hasn't started yet */
			PROMPT_COMPONENT(prompt)->state = PCS_DONE_STOP_OUTPUT;
			PROMPT_COMPONENT(prompt)->complete = rayo_component_create_complete_event(RAYO_COMPONENT(prompt), COMPONENT_COMPLETE_STOP);
			rayo_component_send_stop(prompt, PROMPT_COMPONENT(prompt)->output_jid);
			break;
		case PCS_INPUT_OUTPUT:
		case PCS_INPUT:
		case PCS_STOP_OUTPUT:
			/* stopping input will trigger completion */
			rayo_component_send_stop(prompt, PROMPT_COMPONENT(prompt)->input_jid);
			break;
		case PCS_START_INPUT:
			/* stop input as soon as it starts */
			PROMPT_COMPONENT(prompt)->state = PCS_DONE;
			break;
		case PCS_DONE_STOP_OUTPUT:
		case PCS_DONE:
			/* already done */
			break;
		case PCS_START_OUTPUT:
		case PCS_START_OUTPUT_BARGE:
		case PCS_START_INPUT_OUTPUT:
		case PCS_START_INPUT_TIMERS:
			/* ref hasn't been sent yet */
			reply = iks_new_error(iq, STANZA_ERROR_UNEXPECTED_REQUEST);
			break;
	}

	if (!reply) {
		reply = iks_new_iq_result(iq);
	}
	return reply;
}
/**
 * Handle completion event
 */
static iks *prompt_component_handle_output_complete(struct rayo_actor *prompt, struct rayo_message *msg, void *data)
{
	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s (%s) output complete\n",
		RAYO_JID(prompt), prompt_component_state_to_string(PROMPT_COMPONENT(prompt)->state));

	switch (PROMPT_COMPONENT(prompt)->state) {
		case PCS_OUTPUT:
			PROMPT_COMPONENT(prompt)->state = PCS_START_INPUT;
			/* start input with timers enabled and barge events disabled */
			start_input(PROMPT_COMPONENT(prompt), 1, 0);
			iks_delete(PROMPT_COMPONENT(prompt)->iq);
			break;
		case PCS_START_INPUT_OUTPUT:
			/* output finished before input started */
			PROMPT_COMPONENT(prompt)->state = PCS_START_INPUT_TIMERS;
			break;
		case PCS_INPUT_OUTPUT:
			PROMPT_COMPONENT(prompt)->state = PCS_INPUT;
			start_input_timers(PROMPT_COMPONENT(prompt));
			break;
		case PCS_STOP_OUTPUT:
			PROMPT_COMPONENT(prompt)->state = PCS_INPUT;
			start_input_timers(PROMPT_COMPONENT(prompt));
			break;
		case PCS_DONE_STOP_OUTPUT:
			if (PROMPT_COMPONENT(prompt)->complete) {
				rayo_component_send_complete_event(RAYO_COMPONENT(prompt), PROMPT_COMPONENT(prompt)->complete);
			}
			break;
		case PCS_INPUT:
		case PCS_START_OUTPUT:
		case PCS_START_OUTPUT_BARGE:
		case PCS_START_INPUT:
		case PCS_START_INPUT_TIMERS:
		case PCS_DONE:
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s, unexpected start output error event\n", RAYO_JID(prompt));
			break;
	}

	return NULL;
}