static void on_client_presence(struct rayo_client *rclient, iks *node);
+/**
+ * @param msg to check
+ * @return true if message was sent by admin client (console)
+ */
+static int is_admin_client_message(struct rayo_message *msg)
+{
+ return !zstr(msg->from_jid) && !strcmp(RAYO_JID(globals.console), msg->from_jid);
+}
/**
- * @param jid to check
- * @return true if jid is admin client (console)
+ * @param msg to check
+ * @return true if from/to bare JIDs match
*/
-static int is_admin_client(const char *jid)
+static int is_internal_message(struct rayo_message *msg)
{
- return !zstr(jid) && !strcmp(RAYO_JID(globals.console), jid);
+ return msg->from && msg->to && (iks_id_cmp(msg->from, msg->to, IKS_ID_PARTIAL) == 0);
}
/**
{
iks *payload = msg->payload;
msg->payload = NULL;
+ msg->from = NULL;
+ msg->to = NULL;
return payload;
}
if (actor) {
/* deliver to actor */
switch_mutex_lock(actor->mutex);
+ switch_log_printf(SWITCH_CHANNEL_ID_LOG, msg->file, "", msg->line, "", SWITCH_LOG_DEBUG, "Deliver %s => %s %s\n", msg->from_jid, msg->to_jid, iks_string(iks_stack(msg->payload), msg->payload));
actor->send_fn(actor, msg);
switch_mutex_unlock(actor->mutex);
RAYO_UNLOCK(actor);
}
msg->is_reply = reply;
msg->to_jid = strdup(zstr(to) ? "" : to);
+ if (!zstr(msg->to_jid)) {
+ msg->to = iks_id_new(iks_stack(payload), msg->to_jid);
+ }
msg->from_jid = strdup(RAYO_JID(from));
+ if (!zstr(msg->from_jid)) {
+ msg->from = iks_id_new(iks_stack(payload), msg->from_jid);
+ }
msg->from_type = strdup(zstr(from->type) ? "" : from->type);
msg->from_subtype = strdup(zstr(from->subtype) ? "" : from->subtype);
msg->file = strdup(file);
}
/**
- * Check if client has control of offered call. Take control if nobody else does.
- * @param rclient the Rayo client
+ * Check if message sender has control of offered call. Take control if nobody else does.
* @param call the Rayo call
* @param session the session
- * @param call_jid the call JID
- * @param call_uuid the internal call UUID
- * @return 1 if session has call control
+ * @param msg the message
+ * @return 1 if sender has call control
*/
-static int rayo_client_has_call_control(const char *rclient, struct rayo_call *call, switch_core_session_t *session)
+static int has_call_control(struct rayo_call *call, switch_core_session_t *session, struct rayo_message *msg)
{
int control = 0;
- if (zstr(rclient)) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Null client JID!!\n");
- return 0;
- }
-
/* nobody in charge */
if (zstr(call->dcp_jid)) {
/* was offered to this session? */
- if (switch_core_hash_find(call->pcps, rclient)) {
+ if (!zstr(msg->from_jid) && switch_core_hash_find(call->pcps, msg->from_jid)) {
/* take charge */
- call->dcp_jid = switch_core_strdup(RAYO_POOL(call), rclient);
+ call->dcp_jid = switch_core_strdup(RAYO_POOL(call), msg->from_jid);
switch_channel_set_variable(switch_core_session_get_channel(session), "rayo_dcp_jid", rayo_call_get_dcp_jid(call));
control = 1;
switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rayo_call_get_uuid(call)), SWITCH_LOG_INFO, "%s has control of call\n", rayo_call_get_dcp_jid(call));
}
- } else if (is_admin_client(rclient) || !strcmp(rayo_call_get_dcp_jid(call), rclient)) {
+ } else if (!strcmp(rayo_call_get_dcp_jid(call), msg->from_jid) || is_internal_message(msg) || is_admin_client_message(msg)) {
control = 1;
}
if (!control) {
- switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rayo_call_get_uuid(call)), SWITCH_LOG_INFO, "%s does not have control of call\n", rclient);
+ switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rayo_call_get_uuid(call)), SWITCH_LOG_INFO, "%s does not have control of call\n", msg->from_jid);
}
return control;
if (bad) {
response = iks_new_error(node, STANZA_ERROR_BAD_REQUEST);
- } else if (!rayo_client_has_call_control(msg->from_jid, call, session)) {
+ } else if (!has_call_control(call, session, msg)) {
response = iks_new_error(node, STANZA_ERROR_CONFLICT);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s, %s conflict\n", msg->from_jid, RAYO_JID(call));
}
if (bad) {
response = iks_new_error(node, STANZA_ERROR_BAD_REQUEST);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s, %s bad request\n", msg->from_jid, RAYO_JID(component));
- } else if (!is_admin_client(msg->from_jid) && strcmp(component->client_jid, from)) {
+ } else if (strcmp(component->client_jid, from) && !is_admin_client_message(msg) && !is_internal_message(msg)) {
/* does not have control of this component */
response = iks_new_error(node, STANZA_ERROR_CONFLICT);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s, %s conflict\n", msg->from_jid, RAYO_JID(component));
handler = rayo_actor_command_handler_find(server, msg);
if (!handler) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s, no handler function for command to %s\n", msg->from_jid, RAYO_JID(server));
- RAYO_SEND_REPLY(server, msg->from_jid, iks_new_error(iq, STANZA_ERROR_FEATURE_NOT_IMPLEMENTED));
+ if (!msg->is_reply) {
+ RAYO_SEND_REPLY(server, msg->from_jid, iks_new_error(iq, STANZA_ERROR_FEATURE_NOT_IMPLEMENTED));
+ }
return;
}
}
if (response) {
- RAYO_SEND_REPLY(server, msg->from_jid, response);
+ if (!msg->is_reply) {
+ RAYO_SEND_REPLY(server, msg->from_jid, response);
+ } else {
+ iks_delete(response);
+ }
}
}
handler = rayo_actor_command_handler_find(call, msg);
if (!handler) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s, no handler function for command\n", RAYO_JID(call));
- RAYO_SEND_REPLY(call, msg->from_jid, iks_new_error(iq, STANZA_ERROR_FEATURE_NOT_IMPLEMENTED));
+ if (!msg->is_reply) {
+ RAYO_SEND_REPLY(call, msg->from_jid, iks_new_error(iq, STANZA_ERROR_FEATURE_NOT_IMPLEMENTED));
+ }
return;
}
session = switch_core_session_locate(rayo_call_get_uuid(RAYO_CALL(call)));
if (!session) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s, session not found\n", RAYO_JID(call));
- RAYO_SEND_REPLY(call, msg->from_jid, iks_new_error(iq, STANZA_ERROR_SERVICE_UNAVAILABLE));
+ if (!msg->is_reply) {
+ RAYO_SEND_REPLY(call, msg->from_jid, iks_new_error(iq, STANZA_ERROR_SERVICE_UNAVAILABLE));
+ }
return;
}
switch_core_session_rwunlock(session);
if (response) {
- RAYO_SEND_REPLY(call, msg->from_jid, response);
+ if (!msg->is_reply) {
+ RAYO_SEND_REPLY(call, msg->from_jid, response);
+ } else {
+ iks_delete(response);
+ }
}
}
handler = rayo_actor_command_handler_find(mixer, msg);
if (!handler) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s, no handler function for command\n", RAYO_JID(mixer));
- RAYO_SEND_REPLY(mixer, msg->from_jid, iks_new_error(iq, STANZA_ERROR_FEATURE_NOT_IMPLEMENTED));
+ if (!msg->is_reply) {
+ RAYO_SEND_REPLY(mixer, msg->from_jid, iks_new_error(iq, STANZA_ERROR_FEATURE_NOT_IMPLEMENTED));
+ }
return;
}
/* execute the command */
response = handler(mixer, msg, NULL);
if (response) {
- RAYO_SEND_REPLY(mixer, msg->from_jid, response);
+ if (!msg->is_reply) {
+ RAYO_SEND_REPLY(mixer, msg->from_jid, response);
+ } else {
+ iks_delete(response);
+ }
}
}
handler = rayo_actor_command_handler_find(component, msg);
if (!handler) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s, no component handler function for command\n", RAYO_JID(component));
- RAYO_SEND_REPLY(component, msg->from_jid, iks_new_error(xml_msg, STANZA_ERROR_FEATURE_NOT_IMPLEMENTED));
+ if (!msg->is_reply) {
+ RAYO_SEND_REPLY(component, msg->from_jid, iks_new_error(xml_msg, STANZA_ERROR_FEATURE_NOT_IMPLEMENTED));
+ }
return;
}
}
if (response) {
- RAYO_SEND_REPLY(component, msg->from_jid, response);
+ if (!msg->is_reply) {
+ RAYO_SEND_REPLY(component, msg->from_jid, response);
+ } else {
+ iks_delete(response);
+ }
return;
}
} else if (!strcmp("presence", iks_name(xml_msg))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s, forwarding event\n", RAYO_JID(component));
response = handler(component, msg, NULL);
if (response) {
- RAYO_SEND_REPLY(component, msg->from_jid, response);
+ if (!msg->is_reply) {
+ RAYO_SEND_REPLY(component, msg->from_jid, response);
+ } else {
+ iks_delete(response);
+ }
}
}
}
if (command) {
RAYO_SEND_MESSAGE_DUP(rclient, to, iq);
} else {
- RAYO_SEND_REPLY(globals.server, RAYO_JID(rclient), iks_new_error_detailed(iq, STANZA_ERROR_BAD_REQUEST, "empty IQ request"));
+ const char *type = iks_find_attrib_soft(iq, "type");
+ if (strcmp("error", type) && strcmp("result", type)) {
+ RAYO_SEND_REPLY(globals.server, RAYO_JID(rclient), iks_new_error_detailed(iq, STANZA_ERROR_BAD_REQUEST, "empty IQ request"));
+ }
}
}
iks_insert_attrib(stop, "from", RAYO_JID(from));
iks_insert_attrib(stop, "to", to);
iks_insert_attrib(stop, "type", "set");
- iks_insert_attrib_printf(stop, "id", "mod_rayo-%d", RAYO_SEQ_NEXT(from));
+ iks_insert_attrib_printf(stop, "id", "mod_rayo-prompt-%d", RAYO_SEQ_NEXT(from));
x = iks_insert(stop, "stop");
iks_insert_attrib(x, "xmlns", RAYO_EXT_NS);
RAYO_SEND_MESSAGE(from, to, stop);
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-%d", RAYO_SEQ_NEXT(prompt));
+ 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(iq, "from", RAYO_JID(prompt));
iks_insert_attrib(iq, "to", prompt->input_jid);
iks_insert_attrib(iq, "type", "set");
- iks_insert_attrib_printf(iq, "id", "mod_rayo-%d", RAYO_SEQ_NEXT(prompt));
+ iks_insert_attrib_printf(iq, "id", "mod_rayo-prompt-%d", RAYO_SEQ_NEXT(prompt));
x = iks_insert(iq, "start-timers");
iks_insert_attrib(x, "xmlns", RAYO_INPUT_NS);
RAYO_SEND_MESSAGE(prompt, prompt->input_jid, iq);
return NULL;
}
+/**
+ * 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... */
+ if (strncmp("mod_rayo-prompt", iks_find_attrib_soft(iq, "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);
+ }
+ return NULL;
+}
+
/**
* Handle completion event
*/
case PCS_INPUT_OUTPUT: {
/* forward request to output component */
iks_insert_attrib(iq, "from", RAYO_JID(prompt));
- iks_insert_attrib(iq, "to", RAYO_JID(PROMPT_COMPONENT(prompt)->output_jid));
+ 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_OUTPUT:
case PCS_START_OUTPUT_BARGE:
/* ref hasn't been sent yet */
- return iks_new_error(iq, STANZA_ERROR_UNEXPECTED_REQUEST);
+ return iks_new_error_detailed(iq, STANZA_ERROR_UNEXPECTED_REQUEST, "too soon");
break;
case PCS_START_INPUT:
case PCS_STOP_OUTPUT:
rayo_actor_command_handler_add(RAT_CALL, "", "set:"RAYO_PROMPT_NS":prompt", start_call_prompt_component);
rayo_actor_command_handler_add(RAT_CALL_COMPONENT, "prompt", "set:"RAYO_EXT_NS":stop", stop_call_prompt_component);
rayo_actor_command_handler_add(RAT_CALL_COMPONENT, "prompt", "result:"RAYO_NS":ref", prompt_component_handle_io_start);
+ rayo_actor_command_handler_add(RAT_CALL_COMPONENT, "prompt", "result::", prompt_component_handle_result);
rayo_actor_command_handler_add(RAT_CALL_COMPONENT, "prompt", "error:"RAYO_OUTPUT_NS":output", prompt_component_handle_output_error);
rayo_actor_command_handler_add(RAT_CALL_COMPONENT, "prompt", "error:"RAYO_INPUT_NS":input", prompt_component_handle_input_error);
rayo_actor_command_handler_add(RAT_CALL_COMPONENT, "prompt", "error:"RAYO_INPUT_NS":start-timers", prompt_component_handle_input_start_timers_error);