static switch_bool_t is_call_actor(struct rayo_actor *actor);
+static void rayo_call_send_end(struct rayo_call *call, switch_event_t *event, int local_hangup, const char *cause_str, const char *cause_q850_str);
+
/**
* Entity features returned by service discovery
}
/**
- * Fire <end> event when call is cleaned up completely
+ * Send <end> event to DCP and PCPs
*/
-static void rayo_call_cleanup(struct rayo_actor *actor)
+static void rayo_call_send_end(struct rayo_call *call, switch_event_t *event, int local_hangup, const char *cause_str, const char *cause_q850_str)
{
- struct rayo_call *call = RAYO_CALL(actor);
- switch_event_t *event = call->end_event;
int no_offered_clients = 1;
switch_hash_index_t *hi = NULL;
iks *revent;
iks *end;
const char *dcp_jid = rayo_call_get_dcp_jid(call);
- if (!event || call->dial_request_failed) {
- /* destroyed before FS session was created (in originate, for example) */
- goto done;
- }
-
- /* send call unjoined event, if not already sent */
- if (call->joined && call->joined_id) {
- if (!zstr(dcp_jid)) {
- iks *unjoined;
- iks *uevent = iks_new_presence("unjoined", RAYO_NS, RAYO_JID(call), dcp_jid);
- unjoined = iks_find(uevent, "unjoined");
- iks_insert_attrib_printf(unjoined, "call-uri", "%s", call->joined_id);
- RAYO_SEND_MESSAGE(call, dcp_jid, uevent);
- }
- }
-
/* build call end event */
- revent = iks_new_presence("end", RAYO_NS,
- RAYO_JID(call),
- "foo");
+ revent = iks_new_presence("end", RAYO_NS, RAYO_JID(call), "foo");
iks_insert_attrib(revent, "type", "unavailable");
end = iks_find(revent, "end");
- if (switch_true(switch_event_get_header(event, "variable_rayo_local_hangup"))) {
+ if (local_hangup) {
iks_insert(end, RAYO_END_REASON_HANGUP_LOCAL);
} else {
/* remote hangup... translate to specific rayo reason */
iks *reason;
switch_call_cause_t cause = SWITCH_CAUSE_NONE;
- char *cause_str = switch_event_get_header(event, "variable_hangup_cause");
- char *cause_q850_str = switch_event_get_header(event, "variable_hangup_cause_q850");
- if (cause_str) {
+ if (!zstr(cause_str)) {
cause = switch_channel_str2cause(cause_str);
}
reason = iks_insert(end, switch_cause_to_rayo_cause(cause));
}
#if 0
- {
+ if (event) {
char *event_str;
if (switch_event_serialize(event, &event_str, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rayo_call_get_uuid(call)), SWITCH_LOG_DEBUG, "%s\n", event_str);
#endif
/* add signaling headers */
- {
+ if (event) {
switch_event_header_t *header;
/* get all variables prefixed with sip_h_ */
for (header = event->headers; header; header = header->next) {
switch_assert(client_jid);
iks_insert_attrib(revent, "to", client_jid);
switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rayo_call_get_uuid(call)), SWITCH_LOG_DEBUG, "Sending <end> to offered client %s\n", client_jid);
- RAYO_SEND_MESSAGE_DUP(actor, client_jid, revent);
+ RAYO_SEND_MESSAGE_DUP(call, client_jid, revent);
no_offered_clients = 0;
}
/* send to DCP only */
switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rayo_call_get_uuid(call)), SWITCH_LOG_DEBUG, "Sending <end> to DCP %s\n", dcp_jid);
iks_insert_attrib(revent, "to", dcp_jid);
- RAYO_SEND_MESSAGE_DUP(actor, dcp_jid, revent);
+ RAYO_SEND_MESSAGE_DUP(call, dcp_jid, revent);
}
iks_delete(revent);
+}
+
+/**
+ * Fire <end> event when call is cleaned up completely
+ */
+static void rayo_call_cleanup(struct rayo_actor *actor)
+{
+ struct rayo_call *call = RAYO_CALL(actor);
+ switch_event_t *event = call->end_event;
+ const char *dcp_jid = rayo_call_get_dcp_jid(call);
+
+ if (!event || call->dial_request_failed) {
+ /* destroyed before FS session was created (in originate, for example) */
+ goto done;
+ }
+
+ /* send call unjoined event, if not already sent */
+ if (call->joined && call->joined_id) {
+ if (!zstr(dcp_jid)) {
+ iks *unjoined;
+ iks *uevent = iks_new_presence("unjoined", RAYO_NS, RAYO_JID(call), dcp_jid);
+ unjoined = iks_find(uevent, "unjoined");
+ iks_insert_attrib_printf(unjoined, "call-uri", "%s", call->joined_id);
+ RAYO_SEND_MESSAGE(call, dcp_jid, uevent);
+ }
+ }
+
+ rayo_call_send_end(call,
+ event,
+ switch_true(switch_event_get_header(event, "variable_rayo_local_hangup")),
+ switch_event_get_header(event, "variable_hangup_cause"),
+ switch_event_get_header(event, "variable_hangup_cause_q850"));
done:
/* out of sessions, typically */
response = iks_new_error_detailed(iq, STANZA_ERROR_RESOURCE_CONSTRAINT, (char *)api_stream.data);
} else if (!strncmp("-ERR USER_NOT_REGISTERED", api_stream.data, strlen("-ERR USER_NOT_REGISTERED"))) {
- response = iks_new_error_detailed(iq, STANZA_ERROR_UNEXPECTED_REQUEST, (char *)api_stream.data);
+ /* call session was never created, so we must fake it so that a call error is sent and
+ not a dial error */
+ /* send ref response to DCP immediately followed with failure */
+ iks *ref;
+ iks *ref_response = iks_new("iq");
+ iks_insert_attrib(ref_response, "from", RAYO_JID(globals.server));
+ iks_insert_attrib(ref_response, "to", dcp_jid);
+ iks_insert_attrib(ref_response, "id", iks_find_attrib_soft(iq, "id"));
+ iks_insert_attrib(ref_response, "type", "result");
+ ref = iks_insert(ref_response, "ref");
+ iks_insert_attrib(ref, "xmlns", RAYO_NS);
+ iks_insert_attrib_printf(ref, "uri", "xmpp:%s", RAYO_JID(call));
+ RAYO_SEND_MESSAGE(globals.server, dcp_jid, ref_response);
+
+ /* send subscriber-absent call hangup reason */
+ rayo_call_send_end(call, NULL, 0, "SUBSCRIBER_ABSENT", "20");
+
+ /* destroy call */
+ RAYO_DESTROY(call);
+ RAYO_UNLOCK(call);
} else if (!strncmp("-ERR EXCHANGE_ROUTING_ERROR", api_stream.data, strlen("-ERR EXCHANGE_ROUTING_ERROR"))) {
/* max forwards */
response = iks_new_error_detailed(iq, STANZA_ERROR_RESOURCE_CONSTRAINT, (char *)api_stream.data);