/** * Start execution of call output component * @param component to start * @param session the session to output to * @param output the output request * @param iq the original request */ static iks *start_call_output(struct rayo_component *component, switch_core_session_t *session, iks *output, iks *iq) { switch_stream_handle_t stream = { 0 }; /* acknowledge command */ rayo_component_send_start(component, iq); /* build playback command */ SWITCH_STANDARD_STREAM(stream); stream.write_function(&stream, "{id=%s,session=%s,pause=%s", RAYO_JID(component), switch_core_session_get_uuid(session), OUTPUT_COMPONENT(component)->start_paused ? "true" : "false"); if (OUTPUT_COMPONENT(component)->max_time > 0) { stream.write_function(&stream, ",timeout=%i", OUTPUT_COMPONENT(component)->max_time * 1000); } stream.write_function(&stream, "}fileman://rayo://%s", RAYO_JID(component)); if (switch_ivr_displace_session(session, stream.data, 0, "m") == SWITCH_STATUS_SUCCESS) { RAYO_UNLOCK(component); } else { if (OUTPUT_COMPONENT(component)->document) { iks_delete(OUTPUT_COMPONENT(component)->document); } if (switch_channel_get_state(switch_core_session_get_channel(session)) >= CS_HANGUP) { rayo_component_send_complete(component, COMPONENT_COMPLETE_HANGUP); component = NULL; } else { rayo_component_send_complete(component, COMPONENT_COMPLETE_ERROR); component = NULL; } } switch_safe_free(stream.data); return NULL; }
/** * Close SSML document. * @param handle * @return SWITCH_STATUS_SUCCESS */ static switch_status_t rayo_file_close(switch_file_handle_t *handle) { struct rayo_file_context *context = (struct rayo_file_context *)handle->private_info; if (context && context->component) { struct output_component *output = OUTPUT_COMPONENT(context->component); /* send completion and destroy */ if (output->stop) { rayo_component_send_complete(context->component, COMPONENT_COMPLETE_STOP); } else { rayo_component_send_complete(context->component, OUTPUT_FINISH); } /* TODO hangup / timed out */ /* cleanup internals */ switch_safe_free(context->ssml); context->ssml = NULL; if (output->document) { iks_delete(output->document); output->document = NULL; } /* close SSML file */ if (switch_test_flag((&context->fh), SWITCH_FILE_OPEN)) { return switch_core_file_close(&context->fh); } } return SWITCH_STATUS_SUCCESS; }
/** * Close SSML document. * @param handle * @return SWITCH_STATUS_SUCCESS */ static switch_status_t rayo_file_close(switch_file_handle_t *handle) { struct rayo_file_context *context = (struct rayo_file_context *)handle->private_info; if (context && context->component) { struct output_component *output = OUTPUT_COMPONENT(context->component); /* send completion and destroy */ if (output->stop) { rayo_component_send_complete(context->component, COMPONENT_COMPLETE_STOP); } else { if (!strcmp(RAYO_ACTOR(context->component)->type, RAT_CALL_COMPONENT)) { /* call output... check for hangup */ switch_core_session_t *session = switch_core_session_locate(RAYO_ACTOR(context->component)->parent->id); if (session) { if (switch_channel_get_state(switch_core_session_get_channel(session)) >= CS_HANGUP) { rayo_component_send_complete(context->component, COMPONENT_COMPLETE_HANGUP); } else { rayo_component_send_complete(context->component, OUTPUT_FINISH); } switch_core_session_rwunlock(session); } else { /* session is gone */ rayo_component_send_complete(context->component, COMPONENT_COMPLETE_HANGUP); } } else { /* mixer output... finished */ rayo_component_send_complete(context->component, OUTPUT_FINISH); } } /* TODO timed out */ /* cleanup internals */ switch_safe_free(context->ssml); context->ssml = NULL; if (output->document) { iks_delete(output->document); output->document = NULL; } /* close SSML file */ if (switch_test_flag((&context->fh), SWITCH_FILE_OPEN)) { return switch_core_file_close(&context->fh); } } return SWITCH_STATUS_SUCCESS; }
/** * 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 CPA completion because of hangup */ static void rayo_cpa_component_hangup(const char *jid, void *user_data) { struct rayo_actor *component = RAYO_LOCATE(jid); if (component) { stop_cpa_detectors(CPA_COMPONENT(component)); rayo_component_send_complete(RAYO_COMPONENT(component), COMPONENT_COMPLETE_HANGUP); RAYO_UNLOCK(component); } }
/** * Send rayo complete */ void rayo_component_send_complete_with_metadata_string(struct rayo_component *component, const char *reason, const char *reason_namespace, const char *meta, int child_of_complete) { iks *meta_xml = NULL; iksparser *p = iks_dom_new(&meta_xml); if (iks_parse(p, meta, 0, 1) != IKS_OK) { /* unexpected ... */ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "%s Failed to parse metadata for complete event: %s\n", RAYO_JID(component), meta); /* send without... */ rayo_component_send_complete(component, reason, reason_namespace); } else { rayo_component_send_complete_with_metadata(component, reason, reason_namespace, meta_xml, child_of_complete); } if (meta_xml) { iks_delete(meta_xml); } iks_parser_delete(p); }
/** * Stop execution of CPA component */ static iks *stop_cpa_component(struct rayo_actor *component, struct rayo_message *msg, void *data) { stop_cpa_detectors(CPA_COMPONENT(component)); rayo_component_send_complete(RAYO_COMPONENT(component), COMPONENT_COMPLETE_STOP); return iks_new_iq_result(msg->payload); }