mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-31 02:37:10 +00:00 
			
		
		
		
	Merge "res_pjsip_exten_state: Create PUBLISH messages."
This commit is contained in:
		| @@ -92,6 +92,28 @@ void ast_sip_unregister_event_publisher_handler(struct ast_sip_event_publisher_h | ||||
|  */ | ||||
| struct ast_sip_outbound_publish_client *ast_sip_publish_client_get(const char *name); | ||||
|  | ||||
| /*! | ||||
|  * \brief Get the From URI the client will use. | ||||
|  * \since 14.0.0 | ||||
|  * | ||||
|  * \param client The publication client to get the From URI | ||||
|  * | ||||
|  * \retval From-uri on success | ||||
|  * \retval Empty-string on failure | ||||
|  */ | ||||
| const char *ast_sip_publish_client_get_from_uri(struct ast_sip_outbound_publish_client *client); | ||||
|  | ||||
| /*! | ||||
|  * \brief Get the To URI the client will use. | ||||
|  * \since 14.0.0 | ||||
|  * | ||||
|  * \param client The publication client to get the To URI | ||||
|  * | ||||
|  * \retval From-uri on success | ||||
|  * \retval Empty-string on failure | ||||
|  */ | ||||
| const char *ast_sip_publish_client_get_to_uri(struct ast_sip_outbound_publish_client *client); | ||||
|  | ||||
| /*! | ||||
|  * \brief Alternative for ast_datastore_alloc() | ||||
|  * | ||||
|   | ||||
| @@ -56,6 +56,9 @@ | ||||
|  */ | ||||
| static struct ao2_container *publishers; | ||||
|  | ||||
| /*! Serializer for outbound extension state publishing. */ | ||||
| static struct ast_taskprocessor *publish_exten_state_serializer; | ||||
|  | ||||
| /*! | ||||
|  * \brief A subscription for extension state | ||||
|  * | ||||
| @@ -542,6 +545,142 @@ static void to_ami(struct ast_sip_subscription *sub, | ||||
| 			       exten_state_sub->last_exten_state)); | ||||
| } | ||||
|  | ||||
| struct exten_state_pub_data { | ||||
| 	/*! Publishers needing state update */ | ||||
| 	AST_VECTOR(name, struct exten_state_publisher *) pubs; | ||||
| 	/*! Body generator state data */ | ||||
| 	struct ast_sip_exten_state_data exten_state_data; | ||||
| }; | ||||
|  | ||||
| static void exten_state_pub_data_destroy(struct exten_state_pub_data *doomed) | ||||
| { | ||||
| 	if (!doomed) { | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	ast_free((void *) doomed->exten_state_data.exten); | ||||
| 	ast_free(doomed->exten_state_data.presence_subtype); | ||||
| 	ast_free(doomed->exten_state_data.presence_message); | ||||
| 	ao2_cleanup(doomed->exten_state_data.device_state_info); | ||||
|  | ||||
| 	AST_VECTOR_CALLBACK_VOID(&doomed->pubs, ao2_ref, -1); | ||||
| 	AST_VECTOR_FREE(&doomed->pubs); | ||||
|  | ||||
| 	ast_free(doomed); | ||||
| } | ||||
|  | ||||
| static struct exten_state_pub_data *exten_state_pub_data_alloc(const char *exten, struct ast_state_cb_info *info) | ||||
| { | ||||
| 	struct exten_state_pub_data *pub_data; | ||||
|  | ||||
| 	pub_data = ast_calloc(1, sizeof(*pub_data)); | ||||
| 	if (!pub_data) { | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	if (AST_VECTOR_INIT(&pub_data->pubs, ao2_container_count(publishers))) { | ||||
| 		exten_state_pub_data_destroy(pub_data); | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	/* Save off currently known information for the body generators. */ | ||||
| 	pub_data->exten_state_data.exten = ast_strdup(exten); | ||||
| 	pub_data->exten_state_data.exten_state = info->exten_state; | ||||
| 	pub_data->exten_state_data.presence_state = info->presence_state; | ||||
| 	pub_data->exten_state_data.presence_subtype = ast_strdup(info->presence_subtype); | ||||
| 	pub_data->exten_state_data.presence_message = ast_strdup(info->presence_message); | ||||
| 	pub_data->exten_state_data.device_state_info = ao2_bump(info->device_state_info); | ||||
| 	if (!pub_data->exten_state_data.exten | ||||
| 		|| !pub_data->exten_state_data.presence_subtype | ||||
| 		|| !pub_data->exten_state_data.presence_message) { | ||||
| 		exten_state_pub_data_destroy(pub_data); | ||||
| 		return NULL; | ||||
| 	} | ||||
| 	return pub_data; | ||||
| } | ||||
|  | ||||
| /*! | ||||
|  * \internal | ||||
|  * \brief Create exten state PUBLISH messages under PJSIP thread. | ||||
|  * \since 14.0.0 | ||||
|  * | ||||
|  * \return 0 | ||||
|  */ | ||||
| static int exten_state_publisher_cb(void *data) | ||||
| { | ||||
| 	struct exten_state_pub_data *pub_data = data; | ||||
| 	struct exten_state_publisher *publisher; | ||||
| 	size_t idx; | ||||
| 	struct ast_str *body_text; | ||||
| 	pj_pool_t *pool; | ||||
| 	struct ast_sip_body_data gen_data = { | ||||
| 		.body_type = AST_SIP_EXTEN_STATE_DATA, | ||||
| 		.body_data = &pub_data->exten_state_data, | ||||
| 	}; | ||||
| 	struct ast_sip_body body; | ||||
|  | ||||
| 	body_text = ast_str_create(64); | ||||
| 	if (!body_text) { | ||||
| 		exten_state_pub_data_destroy(pub_data); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	/* Need a PJSIP memory pool to generate the bodies. */ | ||||
| 	pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(), "pub_state_body", | ||||
| 		1024, 1024); | ||||
| 	if (!pool) { | ||||
| 		ast_log(LOG_WARNING, "Exten state publishing unable to create memory pool\n"); | ||||
| 		exten_state_pub_data_destroy(pub_data); | ||||
| 		ast_free(body_text); | ||||
| 		return 0; | ||||
| 	} | ||||
| 	pub_data->exten_state_data.pool = pool; | ||||
|  | ||||
| 	for (idx = 0; idx < AST_VECTOR_SIZE(&pub_data->pubs); ++idx) { | ||||
| 		const char *uri; | ||||
| 		int res; | ||||
|  | ||||
| 		publisher = AST_VECTOR_GET(&pub_data->pubs, idx); | ||||
|  | ||||
| 		uri = ast_sip_publish_client_get_from_uri(publisher->client); | ||||
| 		if (ast_strlen_zero(uri)) { | ||||
| 			ast_log(LOG_WARNING, "PUBLISH client '%s' has no from_uri or server_uri defined.\n", | ||||
| 				publisher->name); | ||||
| 			continue; | ||||
| 		} | ||||
| 		ast_copy_string(pub_data->exten_state_data.local, uri, sizeof(pub_data->exten_state_data.local)); | ||||
|  | ||||
| 		uri = ast_sip_publish_client_get_to_uri(publisher->client); | ||||
| 		if (ast_strlen_zero(uri)) { | ||||
| 			ast_log(LOG_WARNING, "PUBLISH client '%s' has no to_uri or server_uri defined.\n", | ||||
| 				publisher->name); | ||||
| 			continue; | ||||
| 		} | ||||
| 		ast_copy_string(pub_data->exten_state_data.remote, uri, sizeof(pub_data->exten_state_data.remote)); | ||||
|  | ||||
| 		res = ast_sip_pubsub_generate_body_content(publisher->body_type, | ||||
| 			publisher->body_subtype, &gen_data, &body_text); | ||||
| 		pj_pool_reset(pool); | ||||
| 		if (res) { | ||||
| 			ast_log(LOG_WARNING, | ||||
| 				"PUBLISH client '%s' unable to generate %s/%s PUBLISH body.\n", | ||||
| 				publisher->name, publisher->body_type, publisher->body_subtype); | ||||
| 			continue; | ||||
| 		} | ||||
|  | ||||
| 		body.type = publisher->body_type; | ||||
| 		body.subtype = publisher->body_subtype; | ||||
| 		body.body_text = ast_str_buffer(body_text); | ||||
| 		ast_sip_publish_client_send(publisher->client, &body); | ||||
| 	} | ||||
|  | ||||
| 	pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool); | ||||
|  | ||||
| 	ast_free(body_text); | ||||
| 	exten_state_pub_data_destroy(pub_data); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| /*! | ||||
|  * \brief Global extension state callback function | ||||
|  */ | ||||
| @@ -549,17 +688,46 @@ static int exten_state_publisher_state_cb(const char *context, const char *exten | ||||
| { | ||||
| 	struct ao2_iterator publisher_iter; | ||||
| 	struct exten_state_publisher *publisher; | ||||
| 	struct exten_state_pub_data *pub_data = NULL; | ||||
|  | ||||
| 	ast_debug(5, "Exten state publisher: %s@%s Reason:%s State:%s Presence:%s Subtype:'%s' Message:'%s'\n", | ||||
| 		exten, context, | ||||
| 		info->reason == AST_HINT_UPDATE_DEVICE | ||||
| 			? "Device" | ||||
| 			: info->reason == AST_HINT_UPDATE_PRESENCE | ||||
| 				? "Presence" | ||||
| 				: "Unknown", | ||||
| 		ast_extension_state2str(info->exten_state), | ||||
| 		ast_presence_state2str(info->presence_state), | ||||
| 		S_OR(info->presence_subtype, ""), | ||||
| 		S_OR(info->presence_message, "")); | ||||
| 	publisher_iter = ao2_iterator_init(publishers, 0); | ||||
| 	for (; (publisher = ao2_iterator_next(&publisher_iter)); ao2_ref(publisher, -1)) { | ||||
| 		if ((publisher->context_filter && regexec(&publisher->context_regex, context, 0, NULL, 0)) || | ||||
| 		    (publisher->exten_filter && regexec(&publisher->exten_regex, exten, 0, NULL, 0))) { | ||||
| 			continue; | ||||
| 		} | ||||
| 		/* This is a placeholder for additional code to come */ | ||||
|  | ||||
| 		if (!pub_data) { | ||||
| 			pub_data = exten_state_pub_data_alloc(exten, info); | ||||
| 			if (!pub_data) { | ||||
| 				ao2_ref(publisher, -1); | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		ao2_ref(publisher, +1); | ||||
| 		AST_VECTOR_APPEND(&pub_data->pubs, publisher); | ||||
| 		ast_debug(5, "'%s' will publish exten state\n", publisher->name); | ||||
| 	} | ||||
| 	ao2_iterator_destroy(&publisher_iter); | ||||
|  | ||||
| 	if (pub_data | ||||
| 		&& ast_sip_push_task(publish_exten_state_serializer, exten_state_publisher_cb, | ||||
| 			pub_data)) { | ||||
| 		exten_state_pub_data_destroy(pub_data); | ||||
| 	} | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| @@ -755,6 +923,10 @@ static int unload_module(void) | ||||
| 	ast_sip_unregister_subscription_handler(&presence_handler); | ||||
|  | ||||
| 	ast_extension_state_del(0, exten_state_publisher_state_cb); | ||||
|  | ||||
| 	ast_taskprocessor_unreference(publish_exten_state_serializer); | ||||
| 	publish_exten_state_serializer = NULL; | ||||
|  | ||||
| 	ao2_cleanup(publishers); | ||||
| 	publishers = NULL; | ||||
|  | ||||
| @@ -777,6 +949,12 @@ static int load_module(void) | ||||
| 		return AST_MODULE_LOAD_DECLINE; | ||||
| 	} | ||||
|  | ||||
| 	publish_exten_state_serializer = ast_sip_create_serializer("pjsip/exten_state"); | ||||
| 	if (!publish_exten_state_serializer) { | ||||
| 		unload_module(); | ||||
| 		return AST_MODULE_LOAD_DECLINE; | ||||
| 	} | ||||
|  | ||||
| 	if (ast_sip_register_subscription_handler(&presence_handler)) { | ||||
| 		ast_log(LOG_WARNING, "Unable to register subscription handler %s\n", | ||||
| 			presence_handler.event_name); | ||||
|   | ||||
| @@ -425,6 +425,20 @@ struct ast_sip_outbound_publish_client *ast_sip_publish_client_get(const char *n | ||||
| 	return state->client; | ||||
| } | ||||
|  | ||||
| const char *ast_sip_publish_client_get_from_uri(struct ast_sip_outbound_publish_client *client) | ||||
| { | ||||
| 	struct ast_sip_outbound_publish *publish = client->publish; | ||||
|  | ||||
| 	return S_OR(publish->from_uri, S_OR(publish->server_uri, "")); | ||||
| } | ||||
|  | ||||
| const char *ast_sip_publish_client_get_to_uri(struct ast_sip_outbound_publish_client *client) | ||||
| { | ||||
| 	struct ast_sip_outbound_publish *publish = client->publish; | ||||
|  | ||||
| 	return S_OR(publish->to_uri, S_OR(publish->server_uri, "")); | ||||
| } | ||||
|  | ||||
| int ast_sip_register_event_publisher_handler(struct ast_sip_event_publisher_handler *handler) | ||||
| { | ||||
| 	struct ast_sip_event_publisher_handler *existing; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user