Exemplo n.º 1
0
int __ast_codec_register(struct ast_codec *codec, struct ast_module *mod)
{
	SCOPED_AO2WRLOCK(lock, codecs);
	struct ast_codec *codec_new;

	/* Some types have specific requirements */
	if (codec->type == AST_MEDIA_TYPE_UNKNOWN) {
		ast_log(LOG_ERROR, "A media type must be specified for codec '%s'\n", codec->name);
		return -1;
	} else if (codec->type == AST_MEDIA_TYPE_AUDIO) {
		if (!codec->sample_rate) {
			ast_log(LOG_ERROR, "A sample rate must be specified for codec '%s' of type '%s'\n",
				codec->name, ast_codec_media_type2str(codec->type));
			return -1;
		}
	}

	codec_new = ao2_find(codecs, codec, OBJ_SEARCH_OBJECT | OBJ_NOLOCK);
	if (codec_new) {
		ast_log(LOG_ERROR, "A codec with name '%s' of type '%s' and sample rate '%u' is already registered\n",
			codec->name, ast_codec_media_type2str(codec->type), codec->sample_rate);
		ao2_ref(codec_new, -1);
		return -1;
	}

	codec_new = ao2_t_alloc_options(sizeof(*codec_new), codec_dtor,
		AO2_ALLOC_OPT_LOCK_NOLOCK, S_OR(codec->description, ""));
	if (!codec_new) {
		ast_log(LOG_ERROR, "Could not allocate a codec with name '%s' of type '%s' and sample rate '%u'\n",
			codec->name, ast_codec_media_type2str(codec->type), codec->sample_rate);
		return -1;
	}
	*codec_new = *codec;
	codec_new->id = codec_id++;

	ao2_link_flags(codecs, codec_new, OBJ_NOLOCK);

	/* Once registered a codec can not be unregistered, and the module must persist until shutdown */
	ast_module_shutdown_ref(mod);

	ast_verb(2, "Registered '%s' codec '%s' at sample rate '%u' with id '%u'\n",
		ast_codec_media_type2str(codec->type), codec->name, codec->sample_rate, codec_new->id);

	ao2_ref(codec_new, -1);

	return 0;
}
Exemplo n.º 2
0
struct ast_format *ast_format_create_named(const char *format_name, struct ast_codec *codec)
{
	struct ast_format *format;
	struct format_interface *format_interface;

	format = ao2_t_alloc_options(sizeof(*format), format_destroy,
		AO2_ALLOC_OPT_LOCK_NOLOCK, S_OR(codec->description, ""));
	if (!format) {
		return NULL;
	}
	format->name = format_name;
	format->codec = ao2_bump(codec);
	format->channel_count = 1;

	format_interface = ao2_find(interfaces, codec->name, OBJ_SEARCH_KEY);
	if (format_interface) {
		format->interface = format_interface->interface;
		ao2_ref(format_interface, -1);
	}

	return format;
}
Exemplo n.º 3
0
/*!
 * \brief Create a pjsip transport.
 */
static int transport_create(void *data)
{
	struct transport_create_data *create_data = data;
	struct ws_transport *newtransport = NULL;

	pjsip_endpoint *endpt = ast_sip_get_pjsip_endpoint();
	struct pjsip_tpmgr *tpmgr = pjsip_endpt_get_tpmgr(endpt);

	pj_pool_t *pool;
	pj_str_t buf;
	pj_status_t status;

	newtransport = ao2_t_alloc_options(sizeof(*newtransport), transport_dtor,
			AO2_ALLOC_OPT_LOCK_NOLOCK, "pjsip websocket transport");
	if (!newtransport) {
		ast_log(LOG_ERROR, "Failed to allocate WebSocket transport.\n");
		goto on_error;
	}

	newtransport->transport.endpt = endpt;

	if (!(pool = pjsip_endpt_create_pool(endpt, "ws", 512, 512))) {
		ast_log(LOG_ERROR, "Failed to allocate WebSocket endpoint pool.\n");
		goto on_error;
	}

	newtransport->transport.pool = pool;
	newtransport->ws_session = create_data->ws_session;

	/* Keep the session until transport dies */
	ast_websocket_ref(newtransport->ws_session);

	status = pj_atomic_create(pool, 0, &newtransport->transport.ref_cnt);
	if (status != PJ_SUCCESS) {
		goto on_error;
	}

	status = pj_lock_create_recursive_mutex(pool, pool->obj_name, &newtransport->transport.lock);
	if (status != PJ_SUCCESS) {
		goto on_error;
	}

	pj_sockaddr_parse(pj_AF_UNSPEC(), 0, pj_cstr(&buf, ast_sockaddr_stringify(ast_websocket_remote_address(newtransport->ws_session))), &newtransport->transport.key.rem_addr);
	newtransport->transport.key.rem_addr.addr.sa_family = pj_AF_INET();
	newtransport->transport.key.type = ast_websocket_is_secure(newtransport->ws_session) ? transport_type_wss : transport_type_ws;

	newtransport->transport.addr_len = pj_sockaddr_get_len(&newtransport->transport.key.rem_addr);

	pj_sockaddr_cp(&newtransport->transport.local_addr, &newtransport->transport.key.rem_addr);

	newtransport->transport.local_name.host.ptr = (char *)pj_pool_alloc(pool, newtransport->transport.addr_len+4);
	pj_sockaddr_print(&newtransport->transport.key.rem_addr, newtransport->transport.local_name.host.ptr, newtransport->transport.addr_len+4, 0);
	newtransport->transport.local_name.host.slen = pj_ansi_strlen(newtransport->transport.local_name.host.ptr);
	newtransport->transport.local_name.port = pj_sockaddr_get_port(&newtransport->transport.key.rem_addr);

	newtransport->transport.type_name = (char *)pjsip_transport_get_type_name(newtransport->transport.key.type);
	newtransport->transport.flag = pjsip_transport_get_flag_from_type((pjsip_transport_type_e)newtransport->transport.key.type);
	newtransport->transport.info = (char *)pj_pool_alloc(newtransport->transport.pool, 64);

	newtransport->transport.tpmgr = tpmgr;
	newtransport->transport.send_msg = &ws_send_msg;
	newtransport->transport.destroy = &ws_destroy;

	status = pjsip_transport_register(newtransport->transport.tpmgr,
			(pjsip_transport *)newtransport);
	if (status != PJ_SUCCESS) {
		goto on_error;
	}

	/* Add a reference for pjsip transport manager */
	ao2_ref(newtransport, +1);

	newtransport->rdata.tp_info.transport = &newtransport->transport;
	newtransport->rdata.tp_info.pool = pjsip_endpt_create_pool(endpt, "rtd%p",
		PJSIP_POOL_RDATA_LEN, PJSIP_POOL_RDATA_INC);
	if (!newtransport->rdata.tp_info.pool) {
		ast_log(LOG_ERROR, "Failed to allocate WebSocket rdata.\n");
		pjsip_transport_destroy((pjsip_transport *)newtransport);
		goto on_error;
	}

	create_data->transport = newtransport;
	return 0;

on_error:
	ao2_cleanup(newtransport);
	return -1;
}