コード例 #1
0
ファイル: config_auth.c プロジェクト: huangjingpei/asterisk
int ast_sip_for_each_auth(const struct ast_sip_auth_array *array,
			  ao2_callback_fn on_auth, void *arg)
{
	int i;

	if (!array || !array->num) {
		return 0;
	}

	for (i = 0; i < array->num; ++i) {
		RAII_VAR(struct ast_sip_auth *, auth, ast_sorcery_retrieve_by_id(
				 ast_sip_get_sorcery(), SIP_SORCERY_AUTH_TYPE,
				 array->names[i]), ao2_cleanup);

		if (!auth) {
			continue;
		}

		if (on_auth(auth, arg, 0)) {
			return -1;
		}
	}

	return 0;
}
コード例 #2
0
ファイル: pjsip_options.c プロジェクト: mikefaille/asterisk
int ast_sip_initialize_sorcery_qualify(void)
{
    struct ast_sorcery *sorcery = ast_sip_get_sorcery();

    /* initialize sorcery ast_sip_contact_status resource */
    ast_sorcery_apply_default(sorcery, CONTACT_STATUS, "memory", NULL);

    if (ast_sorcery_internal_object_register(sorcery, CONTACT_STATUS,
            contact_status_alloc, NULL, NULL)) {
        ast_log(LOG_ERROR, "Unable to register ast_sip_contact_status in sorcery\n");
        return -1;
    }

    snprintf(status_value_unknown, sizeof(status_value_unknown), "%u", UNKNOWN);
    ast_sorcery_object_field_register_nodoc(sorcery, CONTACT_STATUS, "last_status",
                                            status_value_unknown, OPT_UINT_T, 1, FLDSET(struct ast_sip_contact_status, last_status));
    snprintf(status_value_created, sizeof(status_value_created), "%u", CREATED);
    ast_sorcery_object_field_register_nodoc(sorcery, CONTACT_STATUS, "status",
                                            status_value_created, OPT_UINT_T, 1, FLDSET(struct ast_sip_contact_status, status));
    ast_sorcery_object_field_register_custom_nodoc(sorcery, CONTACT_STATUS, "rtt_start",
            "0.0", rtt_start_handler, rtt_start_to_str, NULL, 0, 0);
    ast_sorcery_object_field_register_nodoc(sorcery, CONTACT_STATUS, "rtt",
                                            "0", OPT_UINT_T, 1, FLDSET(struct ast_sip_contact_status, rtt));

    return 0;
}
コード例 #3
0
/*! \brief Helper function which returns a UDP transport bound to the given address and port */
static pjsip_transport *multihomed_get_udp_transport(pj_str_t *address, int port)
{
	struct ao2_container *transports = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "transport",
		AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
	struct ast_sip_transport *transport;
	struct ao2_iterator iter;
	pjsip_transport *sip_transport = NULL;

	if (!transports) {
		return NULL;
	}

	for (iter = ao2_iterator_init(transports, 0); (transport = ao2_iterator_next(&iter)); ao2_ref(transport, -1)) {
		if ((transport->type != AST_TRANSPORT_UDP) ||
			(pj_strcmp(&transport->state->transport->local_name.host, address)) ||
			(transport->state->transport->local_name.port != port)) {
			continue;
		}

		sip_transport = transport->state->transport;
		ao2_ref(transport, -1);
		break;
	}
	ao2_iterator_destroy(&iter);

	ao2_ref(transports, -1);

	return sip_transport;
}
コード例 #4
0
ファイル: res_pjsip_mwi.c プロジェクト: pruiz/asterisk
static void create_mwi_subscriptions(void)
{
	struct ao2_container *mwi_subscriptions = ao2_container_alloc(MWI_BUCKETS, mwi_sub_hash, mwi_sub_cmp);
	RAII_VAR(struct ao2_container *, old_mwi_subscriptions, ao2_global_obj_ref(unsolicited_mwi), ao2_cleanup);
	RAII_VAR(struct ao2_container *, endpoints, ast_sorcery_retrieve_by_fields(
				ast_sip_get_sorcery(), "endpoint", AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL),
			ao2_cleanup);

	if (!mwi_subscriptions) {
		return;
	}

	/* We remove all the old stasis subscriptions first before applying the new configuration. This
	 * prevents a situation where there might be multiple overlapping stasis subscriptions for an
	 * endpoint for mailboxes. Though there may be mailbox changes during the gap between unsubscribing
	 * and resubscribing, up-to-date mailbox state will be sent out to the endpoint when the
	 * new stasis subscription is established
	 */
	if (old_mwi_subscriptions) {
		ao2_callback(old_mwi_subscriptions, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, unsubscribe, NULL);
	}
	ao2_callback(endpoints, OBJ_NODATA, create_mwi_subscriptions_for_endpoint, mwi_subscriptions);
	ao2_global_obj_replace_unref(unsolicited_mwi, mwi_subscriptions);
	ao2_ref(mwi_subscriptions, -1);
}
コード例 #5
0
ファイル: pjsip_options.c プロジェクト: litnimax/asterisk
static int on_aor_update_endpoint_state(void *obj, void *arg, int flags)
{
	struct ast_sip_aor *aor = obj;
	struct ao2_container *endpoints;
	RAII_VAR(struct ast_variable *, var, NULL, ast_variables_destroy);
	const char *aor_name = ast_sorcery_object_get_id(aor);
	char *aor_like;

	if (ast_strlen_zero(aor_name)) {
		return -1;
	}

	if (aor->permanent_contacts && ((int)(aor->qualify_frequency * 1000)) <= 0) {
		aor_like = ast_alloca(strlen(aor_name) + 3);
		sprintf(aor_like, "%%%s%%", aor_name);
		var = ast_variable_new("aors LIKE", aor_like, "");
		if (!var) {
			return -1;
		}
		endpoints = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(),
			"endpoint", AST_RETRIEVE_FLAG_MULTIPLE, var);

		if (endpoints) {
		    /*
		     * Because aors are a string list, we have to use a pattern match but since a simple
		     * pattern match could return an endpoint that has an aor of "aaabccc" when searching
		     * for "abc", we still have to iterate over them to find an exact aor match.
		     */
		    ao2_callback(endpoints, 0, aor_update_endpoint_state, (char *)aor_name);
		    ao2_ref(endpoints, -1);
		}
	}

	return 0;
}
コード例 #6
0
ファイル: res_pjsip_mwi.c プロジェクト: juned/asterisk
static int load_module(void)
{
	CHECK_PJSIP_MODULE_LOADED();

	if (ast_sip_register_subscription_handler(&mwi_handler)) {
		return AST_MODULE_LOAD_DECLINE;
	}

	unsolicited_mwi = ao2_container_alloc(MWI_BUCKETS, mwi_sub_hash, mwi_sub_cmp);
	if (!unsolicited_mwi) {
		ast_sip_unregister_subscription_handler(&mwi_handler);
		return AST_MODULE_LOAD_DECLINE;
	}

	create_mwi_subscriptions();
	ast_sorcery_observer_add(ast_sip_get_sorcery(), "contact", &mwi_contact_observer);

	if (ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) {
		ast_sip_push_task(NULL, send_initial_notify_all, NULL);
	} else {
		stasis_subscribe_pool(ast_manager_get_topic(), mwi_startup_event_cb, NULL);
	}

	return AST_MODULE_LOAD_SUCCESS;
}
コード例 #7
0
static int load_module(void)
{
	CHECK_PJSIP_MODULE_LOADED();

	contact_autoexpire = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK,
		CONTACT_AUTOEXPIRE_BUCKETS, contact_expiration_hash, contact_expiration_cmp);
	if (!contact_autoexpire) {
		ast_log(LOG_ERROR, "Could not create container for contact auto-expiration\n");
		return AST_MODULE_LOAD_FAILURE;
	}

	if (!(sched = ast_sched_context_create())) {
		ast_log(LOG_ERROR, "Could not create scheduler for contact auto-expiration\n");
		unload_module();
		return AST_MODULE_LOAD_FAILURE;
	}

	if (ast_sched_start_thread(sched)) {
		ast_log(LOG_ERROR, "Could not start scheduler thread for contact auto-expiration\n");
		unload_module();
		return AST_MODULE_LOAD_FAILURE;
	}

	contact_expiration_initialize_existing();

	if (ast_sorcery_observer_add(ast_sip_get_sorcery(), "contact", &contact_expiration_observer)) {
		ast_log(LOG_ERROR, "Could not add observer for notifications about contacts for contact auto-expiration\n");
		unload_module();
		return AST_MODULE_LOAD_FAILURE;
	}

	return AST_MODULE_LOAD_SUCCESS;
}
コード例 #8
0
ファイル: pjsip_options.c プロジェクト: semidy/asterisk
static int format_contact_status(void *obj, void *arg, int flags)
{
	struct ast_sip_contact_wrapper *wrapper = obj;
	struct ast_sip_contact *contact = wrapper->contact;
	struct ast_sip_ami *ami = arg;
	struct ast_sip_contact_status *status;
	struct ast_str *buf;
	const struct ast_sip_endpoint *endpoint = ami->arg;

	buf = ast_sip_create_ami_event("ContactStatusDetail", ami);
	if (!buf) {
		return -1;
	}

	status = ast_sorcery_retrieve_by_id(
		ast_sip_get_sorcery(), CONTACT_STATUS,
		ast_sorcery_object_get_id(contact));

	ast_str_append(&buf, 0, "AOR: %s\r\n", wrapper->aor_id);
	ast_str_append(&buf, 0, "URI: %s\r\n", contact->uri);
	ast_str_append(&buf, 0, "Status: %s\r\n", ast_sip_get_contact_status_label(status->status));
	if (status->status == UNKNOWN) {
		ast_str_append(&buf, 0, "RoundtripUsec: N/A\r\n");
	} else {
		ast_str_append(&buf, 0, "RoundtripUsec: %" PRId64 "\r\n", status->rtt);
	}
	ast_str_append(&buf, 0, "EndpointName: %s\r\n",
			ast_sorcery_object_get_id(endpoint));
	astman_append(ami->s, "%s\r\n", ast_str_buffer(buf));
	ami->count++;
	
	ast_free(buf);
	ao2_cleanup(status);
	return 0;
}
コード例 #9
0
ファイル: pjsip_options.c プロジェクト: litnimax/asterisk
/*!
 * \brief Retrieve a ast_sip_contact_status object from sorcery creating
 *        one if not found.
 */
struct ast_sip_contact_status *ast_res_pjsip_find_or_create_contact_status(const struct ast_sip_contact *contact)
{
	struct ast_sip_contact_status *status;
	SCOPED_MUTEX(lock, &creation_lock);

	status = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), CONTACT_STATUS,
		ast_sorcery_object_get_id(contact));
	if (status) {
		return status;
	}

	status = ast_sorcery_alloc(ast_sip_get_sorcery(), CONTACT_STATUS,
		ast_sorcery_object_get_id(contact));
	if (!status) {
		ast_log(LOG_ERROR, "Unable to create ast_sip_contact_status for contact %s/%s\n",
			contact->aor, contact->uri);
		return NULL;
	}

	ast_string_field_set(status, uri, contact->uri);
	status->rtt_start = ast_tv(0, 0);
	status->rtt = 0;

	if (ast_sorcery_create(ast_sip_get_sorcery(), status)) {
		ast_log(LOG_ERROR, "Unable to persist ast_sip_contact_status for contact %s\n",
			contact->uri);
		ao2_ref(status, -1);
		return NULL;
	}

	/* The permanent contact added after asterisk start should be qualified. */
	if (ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED) && ast_tvzero(contact->expiration_time)) {
		/*
		 * The FULLY_BOOTED to filter out contacts that already existed when asterisk started.
		 * The zero expiration_time to select only permanent contacts.
		 */
		ao2_ref((struct ast_sip_contact *) contact, +1);
		if (ast_sip_push_task(NULL, qualify_and_schedule_aor_contact, (struct ast_sip_contact *) contact)) {
			ao2_ref((struct ast_sip_contact *) contact, -1);
		}
	}

	ast_statsd_log_string_va("PJSIP.contacts.states.%s", AST_STATSD_GAUGE,
		"+1", 1.0, ast_sip_get_contact_status_label(status->status));

	return status;
}
コード例 #10
0
ファイル: pjsip_options.c プロジェクト: cfhb/vlink-cti
/*!
 * \internal
 * \brief Update an ast_sip_contact_status's elements.
 */
static void update_contact_status(const struct ast_sip_contact *contact,
	enum ast_sip_contact_status_type value)
{
	struct ast_sip_contact_status *status;
	struct ast_sip_contact_status *update;

	status = ast_res_pjsip_find_or_create_contact_status(contact);
	if (!status) {
		ast_log(LOG_ERROR, "Unable to find ast_sip_contact_status for contact %s\n",
			contact->uri);
		return;
	}

	update = ast_sorcery_alloc(ast_sip_get_sorcery(), CONTACT_STATUS,
		ast_sorcery_object_get_id(status));
	if (!update) {
		ast_log(LOG_ERROR, "Unable to allocate ast_sip_contact_status for contact %s\n",
			contact->uri);
		return;
	}

	update->last_status = status->status;
	update->status = value;

	/* if the contact is available calculate the rtt as
	   the diff between the last start time and "now" */
	update->rtt = update->status == AVAILABLE && status->rtt_start.tv_sec > 0 ?
		ast_tvdiff_us(ast_tvnow(), status->rtt_start) : 0;

	update->rtt_start = ast_tv(0, 0);

	ast_test_suite_event_notify("AOR_CONTACT_QUALIFY_RESULT",
		"Contact: %s\r\n"
			"Status: %s\r\n"
			"RTT: %" PRId64,
		ast_sorcery_object_get_id(update),
		ast_sip_get_contact_status_label(update->status),
		update->rtt);

	if (ast_sorcery_update(ast_sip_get_sorcery(), update)) {
		ast_log(LOG_ERROR, "Unable to update ast_sip_contact_status for contact %s\n",
			contact->uri);
	}

	ao2_ref(status, -1);
	ao2_ref(update, -1);
}
コード例 #11
0
ファイル: res_pjsip_mwi.c プロジェクト: juned/asterisk
static int unload_module(void)
{
	ao2_callback(unsolicited_mwi, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, unsubscribe, NULL);
	ao2_ref(unsolicited_mwi, -1);
	ast_sorcery_observer_remove(ast_sip_get_sorcery(), "contact", &mwi_contact_observer);
	ast_sip_unregister_subscription_handler(&mwi_handler);
	return 0;
}
コード例 #12
0
ファイル: config_auth.c プロジェクト: scudella/asterisk
static struct ao2_container *cli_get_auths(void)
{
	struct ao2_container *auths;

	auths = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "auth",
			AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);

	return auths;
}
コード例 #13
0
ファイル: location.c プロジェクト: litnimax/asterisk
/*! \brief Custom handler for permanent URIs */
static int permanent_uri_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
{
	struct ast_sip_aor *aor = obj;
	const char *aor_id = ast_sorcery_object_get_id(aor);
	char *contacts;
	char *contact_uri;

	if (ast_strlen_zero(var->value)) {
		return 0;
	}

	contacts = ast_strdupa(var->value);
	while ((contact_uri = ast_strip(strsep(&contacts, ",")))) {
		struct ast_sip_contact *contact;
		struct ast_sip_contact_status *status;
		char hash[33];
		char contact_id[strlen(aor_id) + sizeof(hash) + 2];

		if (ast_strlen_zero(contact_uri)) {
			continue;
		}

		if (ast_sip_validate_uri_length(contact_uri)) {
			ast_log(LOG_ERROR, "Contact uri or hostname length exceeds pjproject limit: %s\n", contact_uri);
			return -1;
		}

		if (!aor->permanent_contacts) {
			aor->permanent_contacts = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK,
				AO2_CONTAINER_ALLOC_OPT_DUPS_REJECT, permanent_uri_sort_fn, NULL);
			if (!aor->permanent_contacts) {
				return -1;
			}
		}

		ast_md5_hash(hash, contact_uri);
		snprintf(contact_id, sizeof(contact_id), "%s@@%s", aor_id, hash);
		contact = ast_sorcery_alloc(ast_sip_get_sorcery(), "contact", contact_id);
		if (!contact) {
			return -1;
		}

		ast_string_field_set(contact, uri, contact_uri);

		status = ast_res_pjsip_find_or_create_contact_status(contact);
		if (!status) {
			ao2_ref(contact, -1);
			return -1;
		}
		ao2_ref(status, -1);

		ao2_link(aor->permanent_contacts, contact);
		ao2_ref(contact, -1);
	}

	return 0;
}
コード例 #14
0
/*!
 * \internal
 * \brief A contact has been deleted remove status tracking.
 */
static void contact_deleted(const void *obj)
{
	struct ast_sip_contact *contact = (struct ast_sip_contact *) obj;
	struct ast_sip_contact_status *status;

	unschedule_qualify(contact);

	status = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), CONTACT_STATUS,
		ast_sorcery_object_get_id(contact));
	if (!status) {
		return;
	}

	if (ast_sorcery_delete(ast_sip_get_sorcery(), status)) {
		ast_log(LOG_ERROR, "Unable to delete ast_sip_contact_status for contact %s\n",
			contact->uri);
	}
	ao2_ref(status, -1);
}
コード例 #15
0
ファイル: res_pjsip_logger.c プロジェクト: GGGO/asterisk
static int unload_module(void)
{
	ast_cli_unregister_multiple(cli_pjsip, ARRAY_LEN(cli_pjsip));
	ast_sip_unregister_service(&logging_module);

	ast_sorcery_observer_remove(
		ast_sip_get_sorcery(), "global", &global_observer);

	return 0;
}
コード例 #16
0
ファイル: pjsip_options.c プロジェクト: litnimax/asterisk
int ast_sip_format_contact_ami(void *obj, void *arg, int flags)
{
	struct ast_sip_contact_wrapper *wrapper = obj;
	struct ast_sip_contact *contact = wrapper->contact;
	struct ast_sip_ami *ami = arg;
	struct ast_sip_contact_status *status;
	struct ast_str *buf;
	const struct ast_sip_endpoint *endpoint = ami->arg;

	buf = ast_sip_create_ami_event("ContactStatusDetail", ami);
	if (!buf) {
		return -1;
	}

	status = ast_sorcery_retrieve_by_id(
		ast_sip_get_sorcery(), CONTACT_STATUS,
		ast_sorcery_object_get_id(contact));

	ast_str_append(&buf, 0, "AOR: %s\r\n", wrapper->aor_id);
	ast_str_append(&buf, 0, "URI: %s\r\n", contact->uri);
	ast_str_append(&buf, 0, "UserAgent: %s\r\n", contact->user_agent);
	ast_str_append(&buf, 0, "RegExpire: %ld\r\n", contact->expiration_time.tv_sec);
	if (!ast_strlen_zero(contact->via_addr)) {
		ast_str_append(&buf, 0, "ViaAddress: %s", contact->via_addr);
		if (contact->via_port) {
			ast_str_append(&buf, 0, ":%d", contact->via_port);
		}
		ast_str_append(&buf, 0, "\r\n");
	}
	if (!ast_strlen_zero(contact->call_id)) {
		ast_str_append(&buf, 0, "CallID: %s\r\n", contact->call_id);
	}
	ast_str_append(&buf, 0, "Status: %s\r\n", ast_sip_get_contact_status_label(status->status));
	if (status->status == UNKNOWN) {
		ast_str_append(&buf, 0, "RoundtripUsec: N/A\r\n");
	} else {
		ast_str_append(&buf, 0, "RoundtripUsec: %" PRId64 "\r\n", status->rtt);
	}
	ast_str_append(&buf, 0, "EndpointName: %s\r\n",
			endpoint ? ast_sorcery_object_get_id(endpoint) : S_OR(contact->endpoint_name, ""));

	ast_str_append(&buf, 0, "ID: %s\r\n", ast_sorcery_object_get_id(contact));
	ast_str_append(&buf, 0, "AuthenticateQualify: %d\r\n", contact->authenticate_qualify);
	ast_str_append(&buf, 0, "OutboundProxy: %s\r\n", contact->outbound_proxy);
	ast_str_append(&buf, 0, "Path: %s\r\n", contact->path);
	ast_str_append(&buf, 0, "QualifyFrequency: %u\r\n", contact->qualify_frequency);
	ast_str_append(&buf, 0, "QualifyTimeout: %.3f\r\n", contact->qualify_timeout);

	astman_append(ami->s, "%s\r\n", ast_str_buffer(buf));
	ami->count++;
	
	ast_free(buf);
	ao2_cleanup(status);
	return 0;
}
コード例 #17
0
/*! \brief Scheduler function which deletes a contact */
static int contact_expiration_expire(const void *data)
{
	struct contact_expiration *expiration = (void *) data;

	expiration->sched = -1;

	/* This will end up invoking the deleted observer callback, which will perform the unlinking and such */
	ast_sorcery_delete(ast_sip_get_sorcery(), expiration->contact);
	ao2_ref(expiration, -1);
	return 0;
}
コード例 #18
0
ファイル: location.c プロジェクト: MakerHe/asterisk
int ast_sip_destroy_sorcery_location(void)
{
	ast_sorcery_observer_remove(ast_sip_get_sorcery(), "aor", &aor_observer);
	ast_cli_unregister_multiple(cli_commands, ARRAY_LEN(cli_commands));
	ast_sip_unregister_cli_formatter(contact_formatter);
	ast_sip_unregister_cli_formatter(aor_formatter);

	internal_sip_unregister_endpoint_formatter(&endpoint_aor_formatter);

	return 0;
}
コード例 #19
0
void ast_res_pjsip_cleanup_options_handling(void)
{
	ast_cli_unregister_multiple(cli_options, ARRAY_LEN(cli_options));
	ast_manager_unregister("PJSIPQualify");
	internal_sip_unregister_endpoint_formatter(&contact_status_formatter);

	ast_sorcery_observer_remove(ast_sip_get_sorcery(), "aor", &observer_callbacks_options);
	pjsip_endpt_unregister_module(ast_sip_get_pjsip_endpoint(), &options_module);
	ao2_cleanup(sched_qualifies);
	sched_qualifies = NULL;
}
コード例 #20
0
ファイル: res_pjsip_mwi.c プロジェクト: adaptiman/asterisk
static int unload_module(void)
{
	RAII_VAR(struct ao2_container *, mwi_subscriptions, ao2_global_obj_ref(unsolicited_mwi), ao2_cleanup);
	if (mwi_subscriptions) {
		ao2_callback(mwi_subscriptions, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, unsubscribe, NULL);
		ao2_global_obj_release(unsolicited_mwi);
		ast_sorcery_observer_remove(ast_sip_get_sorcery(), "contact", &mwi_contact_observer);
	}
	ast_sip_unregister_subscription_handler(&mwi_handler);
	return 0;
}
コード例 #21
0
ファイル: config_auth.c プロジェクト: scudella/asterisk
static int ami_show_auths(struct mansession *s, const struct message *m)
{
	struct ast_sip_ami ami = { .s = s, .m = m, .action_id = astman_get_header(m, "ActionID"), };
	struct ao2_container *auths;

	auths = cli_get_auths();
	if (!auths) {
		astman_send_error(s, m, "Could not get Auths\n");
		return 0;
	}

	if (!ao2_container_count(auths)) {
		astman_send_error(s, m, "No Auths found\n");
		ao2_ref(auths, -1);
		return 0;
	}

	astman_send_listack(s, m, "A listing of Auths follows, presented as AuthList events",
			"start");

	ao2_callback(auths, OBJ_NODATA, format_ami_authlist_handler, &ami);

	astman_send_list_complete_start(s, m, "AuthListComplete", ami.count);
	astman_send_list_complete_end(s);

	ao2_ref(auths, -1);

	return 0;
}

static struct ao2_container *cli_get_container(const char *regex)
{
	RAII_VAR(struct ao2_container *, container, NULL, ao2_cleanup);
	struct ao2_container *s_container;

	container = ast_sorcery_retrieve_by_regex(ast_sip_get_sorcery(), "auth", regex);
	if (!container) {
		return NULL;
	}

	s_container = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, 0,
		ast_sorcery_object_id_sort, ast_sorcery_object_id_compare);
	if (!s_container) {
		return NULL;
	}

	if (ao2_container_dup(s_container, container, 0)) {
		ao2_ref(s_container, -1);
		return NULL;
	}

	return s_container;
}
コード例 #22
0
static struct ast_sip_endpoint *anonymous_identify(pjsip_rx_data *rdata)
{
	char domain_name[DOMAIN_NAME_LEN + 1];
	struct ast_sip_endpoint *endpoint;

	if (get_endpoint_details(rdata, domain_name, sizeof(domain_name))) {
		return NULL;
	}

	if (!ast_sip_get_disable_multi_domain()) {
		struct ast_sip_domain_alias *alias;
		struct ao2_container *transport_states;
		struct ast_sip_transport_state *transport_state = NULL;
		struct ast_sip_transport *transport = NULL;
		char id[sizeof("anonymous@") + DOMAIN_NAME_LEN];

		/* Attempt to find the endpoint given the name and domain provided */
		snprintf(id, sizeof(id), "anonymous@%s", domain_name);
		endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", id);
		if (endpoint) {
			goto done;
		}

		/* See if an alias exists for the domain provided */
		alias = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "domain_alias",
			domain_name);
		if (alias) {
			snprintf(id, sizeof(id), "anonymous@%s", alias->domain);
			ao2_ref(alias, -1);
			endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", id);
			if (endpoint) {
				goto done;
			}
		}

		/* See if the transport this came in on has a provided domain */
		if ((transport_states = ast_sip_get_transport_states())
			&& (transport_state = ao2_callback(transport_states, 0, find_transport_state_in_use, rdata))
			&& (transport = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "transport", transport_state->id))
			&& !ast_strlen_zero(transport->domain)) {
			snprintf(id, sizeof(id), "anonymous@%s", transport->domain);
			endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", id);
		}
		ao2_cleanup(transport);
		ao2_cleanup(transport_state);
		ao2_cleanup(transport_states);
		if (endpoint) {
			goto done;
		}
	}

	/* Fall back to no domain */
	endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", "anonymous");

done:
	if (endpoint) {
		ast_debug(3, "Retrieved anonymous endpoint '%s'\n", ast_sorcery_object_get_id(endpoint));
	}
	return endpoint;
}
コード例 #23
0
ファイル: pjsip_options.c プロジェクト: litnimax/asterisk
static void update_all_unqualified_endpoints(void)
{
	struct ao2_container *aors;
	struct ao2_container *contacts;
	RAII_VAR(struct ast_variable *, var_aor, NULL, ast_variables_destroy);
	RAII_VAR(struct ast_variable *, var_contact, NULL, ast_variables_destroy);
	RAII_VAR(char *, time_now, NULL, ast_free);
	struct timeval tv = ast_tvnow();

	if (!(var_aor = ast_variable_new("contact !=", "", ""))) {
		return;
	}
	if (!(var_aor->next = ast_variable_new("qualify_frequency <=", "0", ""))) {
		return;
	}

	if (ast_asprintf(&time_now, "%ld", tv.tv_sec) == -1) {
		return;
	}
	if (!(var_contact = ast_variable_new("expiration_time >", time_now, ""))) {
		return;
	}
	if (!(var_contact->next = ast_variable_new("qualify_frequency <=", "0", ""))) {
		return;
	}

	aors = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(),
		"aor", AST_RETRIEVE_FLAG_MULTIPLE, var_aor);
	if (aors) {
		ao2_callback(aors, OBJ_NODATA, on_aor_update_endpoint_state, NULL);
		ao2_ref(aors, -1);
	}

	contacts = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(),
		"contact", AST_RETRIEVE_FLAG_MULTIPLE, var_contact);
	if (contacts) {
		ao2_callback(contacts, OBJ_NODATA, contact_update_endpoint_state, NULL);
		ao2_ref(contacts, -1);
	}
}
コード例 #24
0
static char *find_aor_name(const char *username, const char *domain, const char *aors)
{
	char *configured_aors;
	char *aors_buf;
	char *aor_name;
	char *id_domain;
	struct ast_sip_domain_alias *alias;

	id_domain = ast_alloca(strlen(username) + strlen(domain) + 2);
	sprintf(id_domain, "%s@%s", username, domain);

	aors_buf = ast_strdupa(aors);

	/* Look for exact match on username@domain */
	configured_aors = aors_buf;
	while ((aor_name = ast_strip(strsep(&configured_aors, ",")))) {
		if (match_aor(aor_name, id_domain)) {
			return ast_strdup(aor_name);
		}
	}

	/* If there's a domain alias, look for exact match on username@domain_alias */
	alias = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "domain_alias", domain);
	if (alias) {
		char *id_domain_alias = ast_alloca(strlen(username) + strlen(alias->domain) + 2);

		sprintf(id_domain, "%s@%s", username, alias->domain);
		ao2_cleanup(alias);

		configured_aors = strcpy(aors_buf, aors);/* Safe */
		while ((aor_name = ast_strip(strsep(&configured_aors, ",")))) {
			if (match_aor(aor_name, id_domain_alias)) {
				return ast_strdup(aor_name);
			}
		}
	}

	if (ast_strlen_zero(username)) {
		/* No username, no match */
		return NULL;
	}

	/* Look for exact match on username only */
	configured_aors = strcpy(aors_buf, aors);/* Safe */
	while ((aor_name = ast_strip(strsep(&configured_aors, ",")))) {
		if (match_aor(aor_name, username)) {
			return ast_strdup(aor_name);
		}
	}

	return NULL;
}
コード例 #25
0
/*! \brief Callback function which deletes a contact if it has expired or sets up auto-expiry */
static int contact_expiration_setup(void *obj, void *arg, int flags)
{
	struct ast_sip_contact *contact = obj;
	int expires = MAX(0, ast_tvdiff_ms(contact->expiration_time, ast_tvnow()));

	if (!expires) {
		ast_sorcery_delete(ast_sip_get_sorcery(), contact);
	} else {
		contact_expiration_observer_created(contact);
	}

	return 0;
}
コード例 #26
0
/*! \brief Initialize auto-expiration of any existing contacts */
static void contact_expiration_initialize_existing(void)
{
	struct ao2_container *contacts;

	contacts = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "contact",
		AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
	if (!contacts) {
		return;
	}

	ao2_callback(contacts, OBJ_NODATA, contact_expiration_setup, NULL);
	ao2_ref(contacts, -1);
}
コード例 #27
0
ファイル: pjsip_options.c プロジェクト: litnimax/asterisk
/*!
 * \internal
 * \brief Attempt to qualify the contact
 *
 * \details Sends a SIP OPTIONS request to the given contact in order to make
 *         sure that contact is available.
 */
static int qualify_contact(struct ast_sip_endpoint *endpoint, struct ast_sip_contact *contact)
{
	pjsip_tx_data *tdata;
	RAII_VAR(struct ast_sip_endpoint *, endpoint_local, NULL, ao2_cleanup);

	if (endpoint) {
		endpoint_local = ao2_bump(endpoint);
	} else {
		if (!ast_strlen_zero(contact->endpoint_name)) {
			endpoint_local = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", contact->endpoint_name);
		}
		if (!endpoint_local) {
			endpoint_local = find_an_endpoint(contact);
		}
		if (!endpoint_local) {
			ast_log(LOG_WARNING, "Unable to find an endpoint to qualify contact %s. Deleting this contact\n",
				contact->uri);
			contact_deleted(contact);
			return -1;
		}
	}

	if (ast_sip_create_request("OPTIONS", NULL, endpoint_local, NULL, contact, &tdata)) {
		ast_log(LOG_ERROR, "Unable to create request to qualify contact %s\n",
			contact->uri);
		return -1;
	}

	/* If an outbound proxy is specified set it on this request */
	if (!ast_strlen_zero(contact->outbound_proxy) &&
		ast_sip_set_outbound_proxy(tdata, contact->outbound_proxy)) {
		pjsip_tx_data_dec_ref(tdata);
		ast_log(LOG_ERROR, "Unable to apply outbound proxy on request to qualify contact %s\n",
			contact->uri);
		return -1;
	}

	init_start_time(contact);

	ao2_ref(contact, +1);
	if (ast_sip_send_out_of_dialog_request(tdata, endpoint_local, (int)(contact->qualify_timeout * 1000), contact, qualify_contact_cb)
		!= PJ_SUCCESS) {
		ast_log(LOG_ERROR, "Unable to send request to qualify contact %s\n",
			contact->uri);
		update_contact_status(contact, UNAVAILABLE, 0);
		ao2_ref(contact, -1);
		return -1;
	}

	return 0;
}
コード例 #28
0
static int unload_module(void)
{
	ast_sorcery_observer_remove(ast_sip_get_sorcery(), "contact", &contact_expiration_observer);
	if (sched) {
		ao2_callback(contact_autoexpire, OBJ_MULTIPLE | OBJ_NODATA | OBJ_UNLINK,
			unload_observer_delete, NULL);
		ast_sched_context_destroy(sched);
		sched = NULL;
	}
	ao2_cleanup(contact_autoexpire);
	contact_autoexpire = NULL;

	return 0;
}
コード例 #29
0
ファイル: res_pjsip_logger.c プロジェクト: asterisk/asterisk
static int load_module(void)
{
	if (ast_sorcery_observer_add(ast_sip_get_sorcery(), "global", &global_observer)) {
		ast_log(LOG_WARNING, "Unable to add global observer\n");
		return AST_MODULE_LOAD_DECLINE;
	}

	check_debug();

	ast_sip_register_service(&logging_module);
	ast_cli_register_multiple(cli_pjsip, ARRAY_LEN(cli_pjsip));

	return AST_MODULE_LOAD_SUCCESS;
}
コード例 #30
0
ファイル: pjsip_options.c プロジェクト: lyx2014/Asterisk
/*!
 * \internal
 * \brief Update an ast_sip_contact_status's elements.
 */
static void update_contact_status(const struct ast_sip_contact *contact,
	enum ast_sip_contact_status_type value)
{
	struct ast_sip_contact_status *status;
	struct ast_sip_contact_status *update;

	status = find_or_create_contact_status(contact);
	if (!status) {
		return;
	}

	update = ast_sorcery_alloc(ast_sip_get_sorcery(), CONTACT_STATUS,
		ast_sorcery_object_get_id(status));
	if (!update) {
		ast_log(LOG_ERROR, "Unable to create update ast_sip_contact_status for contact %s\n",
			contact->uri);
		ao2_ref(status, -1);
		return;
	}

	update->status = value;

	/* if the contact is available calculate the rtt as
	   the diff between the last start time and "now" */
	update->rtt = update->status == AVAILABLE ?
		ast_tvdiff_us(ast_tvnow(), status->rtt_start) : 0;

	update->rtt_start = ast_tv(0, 0);

	if (ast_sorcery_update(ast_sip_get_sorcery(), update)) {
		ast_log(LOG_ERROR, "Unable to update ast_sip_contact_status for contact %s\n",
			contact->uri);
	}

	ao2_ref(update, -1);
	ao2_ref(status, -1);
}