static int end_session(struct respoke_session *session, enum respoke_status status, const struct respoke_message *message)
{
	const char *endpoint, *type, *app;

	if (!session->channel) {
		return 0;
	}

	endpoint = respoke_message_redirected_endpoint_get(message);
	type = respoke_message_redirected_type_get(message);
	app = respoke_message_redirected_app_get(message);

	if (!ast_strlen_zero(endpoint) && !ast_strlen_zero(app)) {
		if (session->endpoint->redirect == RESPOKE_REDIRECT_INTERNAL) {
			char id[AST_UUID_STR_LEN];

			/* Since we are changing the session-id and because offer adds this session
			 * to the sessions container we need to unlink it now, which bye does
			 */
			respoke_session_bye(session, RESPOKE_STATUS_REDIRECTING);
			session->terminated = 0;

			ast_string_field_set(session, remote, endpoint);
			ast_string_field_set(session, remote_type, S_OR(type, "web"));
			ast_string_field_set(session, remote_appid, app);
			ast_string_field_set(session, remote_connection, "");
			ast_string_field_set(session, session_id, ast_uuid_generate_str(id, sizeof(id)));

			/* Send a new offer out to the new target, without the caller being any the wiser */
			if (!respoke_session_offer(session)) {
				return 0;
			}

			session->terminated = 1;
		} else if (session->endpoint->redirect == RESPOKE_REDIRECT_CORE) {
			ast_channel_call_forward_build(session->channel, "Respoke/%s/%s@%s", ast_sorcery_object_get_id(session->endpoint),
				endpoint, app);
		}
	}

	ast_set_hangupsource(session->channel, ast_channel_name(session->channel), 0);
	if (!ast_channel_hangupcause(session->channel)) {
		int cause = hangup_reason_to_cause(status);
		ast_queue_hangup_with_cause(session->channel, cause);
	} else {
		ast_queue_hangup(session->channel);
	}
	return 0;
}
Exemple #2
0
static int func_channel_write_real(struct ast_channel *chan, const char *function,
			      char *data, const char *value)
{
	int ret = 0;
	signed char gainset;

	if (!strcasecmp(data, "language"))
		locked_string_field_set(chan, language, value);
	else if (!strcasecmp(data, "parkinglot"))
		locked_string_field_set(chan, parkinglot, value);
	else if (!strcasecmp(data, "musicclass"))
		locked_string_field_set(chan, musicclass, value);
	else if (!strcasecmp(data, "accountcode"))
		locked_string_field_set(chan, accountcode, value);
	else if (!strcasecmp(data, "userfield"))
		locked_string_field_set(chan, userfield, value);
	else if (!strcasecmp(data, "after_bridge_goto")) {
		if (ast_strlen_zero(value)) {
			ast_bridge_discard_after_goto(chan);
		} else {
			ast_bridge_set_after_go_on(chan, ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan), value);
		}
	} else if (!strcasecmp(data, "amaflags")) {
		ast_channel_lock(chan);
		if (isdigit(*value)) {
			int amaflags;
			sscanf(value, "%30d", &amaflags);
			ast_channel_amaflags_set(chan, amaflags);
		} else if (!strcasecmp(value,"OMIT")){
			ast_channel_amaflags_set(chan, 1);
		} else if (!strcasecmp(value,"BILLING")){
			ast_channel_amaflags_set(chan, 2);
		} else if (!strcasecmp(value,"DOCUMENTATION")){
			ast_channel_amaflags_set(chan, 3);
		}
		ast_channel_unlock(chan);
	} else if (!strcasecmp(data, "peeraccount"))
		locked_string_field_set(chan, peeraccount, value);
	else if (!strcasecmp(data, "hangupsource"))
		/* XXX - should we be forcing this here? */
		ast_set_hangupsource(chan, value, 0);
#ifdef CHANNEL_TRACE
	else if (!strcasecmp(data, "trace")) {
		ast_channel_lock(chan);
		if (ast_true(value))
			ret = ast_channel_trace_enable(chan);
		else if (ast_false(value))
			ret = ast_channel_trace_disable(chan);
		else {
			ret = -1;
			ast_log(LOG_WARNING, "Invalid value for CHANNEL(trace).\n");
		}
		ast_channel_unlock(chan);
	}
#endif
	else if (!strcasecmp(data, "tonezone")) {
		struct ast_tone_zone *new_zone;
		if (!(new_zone = ast_get_indication_zone(value))) {
			ast_log(LOG_ERROR, "Unknown country code '%s' for tonezone. Check indications.conf for available country codes.\n", value);
			ret = -1;
		} else {
			ast_channel_lock(chan);
			if (ast_channel_zone(chan)) {
				ast_channel_zone_set(chan, ast_tone_zone_unref(ast_channel_zone(chan)));
			}
			ast_channel_zone_set(chan, ast_tone_zone_ref(new_zone));
			ast_channel_unlock(chan);
			new_zone = ast_tone_zone_unref(new_zone);
		}
	} else if (!strcasecmp(data, "dtmf_features")) {
		ret = ast_bridge_features_ds_set_string(chan, value);
	} else if (!strcasecmp(data, "callgroup")) {
		ast_channel_lock(chan);
		ast_channel_callgroup_set(chan, ast_get_group(value));
		ast_channel_unlock(chan);
	} else if (!strcasecmp(data, "pickupgroup")) {
		ast_channel_lock(chan);
		ast_channel_pickupgroup_set(chan, ast_get_group(value));
		ast_channel_unlock(chan);
	} else if (!strcasecmp(data, "namedcallgroup")) {
		struct ast_namedgroups *groups = ast_get_namedgroups(value);

		ast_channel_lock(chan);
		ast_channel_named_callgroups_set(chan, groups);
		ast_channel_unlock(chan);
		ast_unref_namedgroups(groups);
	} else if (!strcasecmp(data, "namedpickupgroup")) {
		struct ast_namedgroups *groups = ast_get_namedgroups(value);

		ast_channel_lock(chan);
		ast_channel_named_pickupgroups_set(chan, groups);
		ast_channel_unlock(chan);
		ast_unref_namedgroups(groups);
	} else if (!strcasecmp(data, "txgain")) {
		sscanf(value, "%4hhd", &gainset);
		ast_channel_setoption(chan, AST_OPTION_TXGAIN, &gainset, sizeof(gainset), 0);
	} else if (!strcasecmp(data, "rxgain")) {
		sscanf(value, "%4hhd", &gainset);
		ast_channel_setoption(chan, AST_OPTION_RXGAIN, &gainset, sizeof(gainset), 0);
	} else if (!strcasecmp(data, "transfercapability")) {
		unsigned short i;

		ast_channel_lock(chan);
		for (i = 0; i < 0x20; i++) {
			if (!strcasecmp(transfercapability_table[i], value) && strcmp(value, "UNK")) {
				ast_channel_transfercapability_set(chan, i);
				break;
			}
		}
		ast_channel_unlock(chan);
	} else if (!strcasecmp(data, "hangup_handler_pop")) {
		/* Pop one hangup handler before pushing the new handler. */
		ast_pbx_hangup_handler_pop(chan);
		ast_pbx_hangup_handler_push(chan, value);
	} else if (!strcasecmp(data, "hangup_handler_push")) {
		ast_pbx_hangup_handler_push(chan, value);
	} else if (!strcasecmp(data, "hangup_handler_wipe")) {
		/* Pop all hangup handlers before pushing the new handler. */
		while (ast_pbx_hangup_handler_pop(chan)) {
		}
		ast_pbx_hangup_handler_push(chan, value);
	} else if (!strncasecmp(data, "secure_bridge_", 14)) {
		struct ast_datastore *ds;
		struct ast_secure_call_store *store;

		if (!chan || !value) {
			return -1;
		}

		ast_channel_lock(chan);
		if (!(ds = ast_channel_datastore_find(chan, &secure_call_info, NULL))) {
			if (!(ds = ast_datastore_alloc(&secure_call_info, NULL))) {
				ast_channel_unlock(chan);
				return -1;
			}
			if (!(store = ast_calloc(1, sizeof(*store)))) {
				ast_channel_unlock(chan);
				ast_free(ds);
				return -1;
			}
			ds->data = store;
			ast_channel_datastore_add(chan, ds);
		} else {
			store = ds->data;
		}

		if (!strcasecmp(data, "secure_bridge_signaling")) {
			store->signaling = ast_true(value) ? 1 : 0;
		} else if (!strcasecmp(data, "secure_bridge_media")) {
			store->media = ast_true(value) ? 1 : 0;
		}
		ast_channel_unlock(chan);
	} else if (!strcasecmp(data, "max_forwards")) {
		int max_forwards;
		if (sscanf(value, "%d", &max_forwards) != 1) {
			ast_log(LOG_WARNING, "Unable to set max forwards to '%s'\n", value);
			ret = -1;
		} else {
			ast_channel_lock(chan);
			ret = ast_max_forwards_set(chan, max_forwards);
			ast_channel_unlock(chan);
		}
	} else if (!ast_channel_tech(chan)->func_channel_write
		 || ast_channel_tech(chan)->func_channel_write(chan, function, data, value)) {
		ast_log(LOG_WARNING, "Unknown or unavailable item requested: '%s'\n",
				data);
		ret = -1;
	}

	return ret;
}
Exemple #3
0
static int func_channel_write_real(struct ast_channel *chan, const char *function,
                                   char *data, const char *value)
{
    int ret = 0;
    signed char gainset;

    if (!strcasecmp(data, "language"))
        locked_string_field_set(chan, language, value);
    else if (!strcasecmp(data, "parkinglot"))
        locked_string_field_set(chan, parkinglot, value);
    else if (!strcasecmp(data, "musicclass"))
        locked_string_field_set(chan, musicclass, value);
    else if (!strcasecmp(data, "accountcode"))
        locked_string_field_set(chan, accountcode, value);
    else if (!strcasecmp(data, "userfield"))
        locked_string_field_set(chan, userfield, value);
    else if (!strcasecmp(data, "amaflags")) {
        ast_channel_lock(chan);
        if(isdigit(*value)) {
            sscanf(value, "%30d", &chan->amaflags);
        } else if (!strcasecmp(value,"OMIT")) {
            chan->amaflags = 1;
        } else if (!strcasecmp(value,"BILLING")) {
            chan->amaflags = 2;
        } else if (!strcasecmp(value,"DOCUMENTATION")) {
            chan->amaflags = 3;
        }
        ast_channel_unlock(chan);
    } else if (!strcasecmp(data, "peeraccount"))
        locked_string_field_set(chan, peeraccount, value);
    else if (!strcasecmp(data, "hangupsource"))
        /* XXX - should we be forcing this here? */
        ast_set_hangupsource(chan, value, 0);
#ifdef CHANNEL_TRACE
    else if (!strcasecmp(data, "trace")) {
        ast_channel_lock(chan);
        if (ast_true(value))
            ret = ast_channel_trace_enable(chan);
        else if (ast_false(value))
            ret = ast_channel_trace_disable(chan);
        else {
            ret = -1;
            ast_log(LOG_WARNING, "Invalid value for CHANNEL(trace).");
        }
        ast_channel_unlock(chan);
    }
#endif
    else if (!strcasecmp(data, "tonezone")) {
        struct ast_tone_zone *new_zone;
        if (!(new_zone = ast_get_indication_zone(value))) {
            ast_log(LOG_ERROR, "Unknown country code '%s' for tonezone. Check indications.conf for available country codes.\n", value);
            ret = -1;
        } else {
            ast_channel_lock(chan);
            if (chan->zone) {
                chan->zone = ast_tone_zone_unref(chan->zone);
            }
            chan->zone = ast_tone_zone_ref(new_zone);
            ast_channel_unlock(chan);
            new_zone = ast_tone_zone_unref(new_zone);
        }
    } else if (!strcasecmp(data, "callgroup")) {
        chan->callgroup = ast_get_group(value);
    } else if (!strcasecmp(data, "pickupgroup")) {
        chan->pickupgroup = ast_get_group(value);
    } else if (!strcasecmp(data, "txgain")) {
        sscanf(value, "%4hhd", &gainset);
        ast_channel_setoption(chan, AST_OPTION_TXGAIN, &gainset, sizeof(gainset), 0);
    } else if (!strcasecmp(data, "rxgain")) {
        sscanf(value, "%4hhd", &gainset);
        ast_channel_setoption(chan, AST_OPTION_RXGAIN, &gainset, sizeof(gainset), 0);
    } else if (!strcasecmp(data, "transfercapability")) {
        unsigned short i;
        for (i = 0; i < 0x20; i++) {
            if (!strcasecmp(transfercapability_table[i], value) && strcmp(value, "UNK")) {
                chan->transfercapability = i;
                break;
            }
        }
    } else if (!strncasecmp(data, "secure_bridge_", 14)) {
        struct ast_datastore *ds;
        struct ast_secure_call_store *store;

        if (!chan || !value) {
            return -1;
        }

        ast_channel_lock(chan);
        if (!(ds = ast_channel_datastore_find(chan, &secure_call_info, NULL))) {
            if (!(ds = ast_datastore_alloc(&secure_call_info, NULL))) {
                ast_channel_unlock(chan);
                return -1;
            }
            if (!(store = ast_calloc(1, sizeof(*store)))) {
                ast_channel_unlock(chan);
                ast_free(ds);
                return -1;
            }
            ds->data = store;
            ast_channel_datastore_add(chan, ds);
        } else {
            store = ds->data;
        }
        ast_channel_unlock(chan);

        if (!strcasecmp(data, "secure_bridge_signaling")) {
            store->signaling = ast_true(value) ? 1 : 0;
        } else if (!strcasecmp(data, "secure_bridge_media")) {
            store->media = ast_true(value) ? 1 : 0;
        }
    } else if (!chan->tech->func_channel_write
               || chan->tech->func_channel_write(chan, function, data, value)) {
        ast_log(LOG_WARNING, "Unknown or unavailable item requested: '%s'\n",
                data);
        ret = -1;
    }

    return ret;
}