diff --git a/src/mod/event_handlers/mod_rayo/mod_rayo.c b/src/mod/event_handlers/mod_rayo/mod_rayo.c index c055dc990f..45fbed6597 100644 --- a/src/mod/event_handlers/mod_rayo/mod_rayo.c +++ b/src/mod/event_handlers/mod_rayo/mod_rayo.c @@ -230,14 +230,22 @@ static void rayo_console_client_send(struct rayo_actor *client, struct rayo_mess 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); } /** @@ -580,6 +588,8 @@ iks *rayo_message_remove_payload(struct rayo_message *msg) { iks *payload = msg->payload; msg->payload = NULL; + msg->from = NULL; + msg->to = NULL; return payload; } @@ -600,6 +610,7 @@ static void *SWITCH_THREAD_FUNC deliver_message_thread(switch_thread_t *thread, 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); @@ -665,7 +676,13 @@ void rayo_message_send(struct rayo_actor *from, const char *to, iks *payload, in } 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); @@ -1239,39 +1256,32 @@ static struct rayo_peer_server *rayo_peer_server_create(const char *jid) } /** - * 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; @@ -1311,7 +1321,7 @@ static iks *rayo_call_command_ok(struct rayo_call *call, switch_core_session_t * 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)); } @@ -1335,7 +1345,7 @@ static iks *rayo_component_command_ok(struct rayo_component *component, struct r 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)); @@ -1369,7 +1379,9 @@ void rayo_server_send(struct rayo_actor *server, struct rayo_message *msg) 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; } @@ -1379,7 +1391,11 @@ void rayo_server_send(struct rayo_actor *server, struct rayo_message *msg) } 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); + } } } @@ -1397,7 +1413,9 @@ void rayo_call_send(struct rayo_actor *call, struct rayo_message *msg) 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; } @@ -1405,7 +1423,9 @@ void rayo_call_send(struct rayo_actor *call, struct rayo_message *msg) 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; } @@ -1419,7 +1439,11 @@ void rayo_call_send(struct rayo_actor *call, struct rayo_message *msg) 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); + } } } @@ -1436,14 +1460,20 @@ void rayo_mixer_send(struct rayo_actor *mixer, struct rayo_message *msg) 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); + } } } @@ -1461,7 +1491,9 @@ void rayo_component_send(struct rayo_actor *component, struct rayo_message *msg) 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; } @@ -1473,7 +1505,11 @@ void rayo_component_send(struct rayo_actor *component, struct rayo_message *msg) } 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))) { @@ -1488,7 +1524,11 @@ void rayo_component_send(struct rayo_actor *component, struct rayo_message *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); + } } } } @@ -2245,7 +2285,10 @@ static void rayo_client_command_recv(struct rayo_client *rclient, iks *iq) 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")); + } } } diff --git a/src/mod/event_handlers/mod_rayo/mod_rayo.h b/src/mod/event_handlers/mod_rayo/mod_rayo.h index d9174b9fc9..29bc7fa033 100644 --- a/src/mod/event_handlers/mod_rayo/mod_rayo.h +++ b/src/mod/event_handlers/mod_rayo/mod_rayo.h @@ -65,7 +65,9 @@ struct rayo_component; struct rayo_message { iks *payload; char *to_jid; + iksid *to; char *from_jid; + iksid *from; char *from_type; char *from_subtype; int is_reply; @@ -104,8 +106,6 @@ struct rayo_actor { rayo_actor_send_fn send_fn; /** optional cleanup */ rayo_actor_cleanup_fn cleanup_fn; - /** incoming message queue */ - switch_queue_t *msg_queue; }; /** diff --git a/src/mod/event_handlers/mod_rayo/rayo_prompt_component.c b/src/mod/event_handlers/mod_rayo/rayo_prompt_component.c index 474251788e..0666b9c982 100644 --- a/src/mod/event_handlers/mod_rayo/rayo_prompt_component.c +++ b/src/mod/event_handlers/mod_rayo/rayo_prompt_component.c @@ -96,7 +96,7 @@ static void rayo_component_send_stop(struct rayo_actor *from, const char *to) 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); @@ -112,7 +112,7 @@ static void start_input(struct prompt_component *prompt, int start_timers, int b 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"); @@ -131,7 +131,7 @@ static void start_input_timers(struct prompt_component *prompt) 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); @@ -422,6 +422,22 @@ static iks *prompt_component_handle_input_complete(struct rayo_actor *prompt, st 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 */ @@ -582,7 +598,7 @@ static iks *forward_output_component_request(struct rayo_actor *prompt, struct r 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; } @@ -590,7 +606,7 @@ static iks *forward_output_component_request(struct rayo_actor *prompt, struct r 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: @@ -612,6 +628,7 @@ switch_status_t rayo_prompt_component_load(void) 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);