static int load_module(void) { announce_tech.capabilities = ast_format_cap_alloc(0); if (!announce_tech.capabilities) { return AST_MODULE_LOAD_DECLINE; } record_tech.capabilities = ast_format_cap_alloc(0); if (!record_tech.capabilities) { return AST_MODULE_LOAD_DECLINE; } ast_format_cap_add_all(announce_tech.capabilities); ast_format_cap_add_all(record_tech.capabilities); if (ast_channel_register(&announce_tech)) { ast_log(LOG_ERROR, "Unable to register channel technology %s(%s).\n", announce_tech.type, announce_tech.description); cleanup_capabilities(); return AST_MODULE_LOAD_DECLINE; } if (ast_channel_register(&record_tech)) { ast_log(LOG_ERROR, "Unable to register channel technology %s(%s).\n", record_tech.type, record_tech.description); cleanup_capabilities(); return AST_MODULE_LOAD_DECLINE; } return AST_MODULE_LOAD_SUCCESS; }
static int load_module(void) { announce_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); if (!announce_tech.capabilities) { return AST_MODULE_LOAD_DECLINE; } record_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); if (!record_tech.capabilities) { return AST_MODULE_LOAD_DECLINE; } ast_format_cap_append_by_type(announce_tech.capabilities, AST_MEDIA_TYPE_UNKNOWN); ast_format_cap_append_by_type(record_tech.capabilities, AST_MEDIA_TYPE_UNKNOWN); if (ast_channel_register(&announce_tech)) { ast_log(LOG_ERROR, "Unable to register channel technology %s(%s).\n", announce_tech.type, announce_tech.description); cleanup_capabilities(); return AST_MODULE_LOAD_DECLINE; } if (ast_channel_register(&record_tech)) { ast_log(LOG_ERROR, "Unable to register channel technology %s(%s).\n", record_tech.type, record_tech.description); cleanup_capabilities(); return AST_MODULE_LOAD_DECLINE; } return AST_MODULE_LOAD_SUCCESS; }
/** \brief Load module */ static int load_module(void) { ast_log(LOG_NOTICE, "Load Res-Speech-UniMRCP module\n"); if(uni_engine_load() == FALSE) { return AST_MODULE_LOAD_FAILURE; } if(mrcp_client_start(uni_engine.client) != TRUE) { ast_log(LOG_ERROR, "Failed to start MRCP client\n"); uni_engine_unload(); return AST_MODULE_LOAD_FAILURE; } #if AST_VERSION_AT_LEAST(10,0,0) #if AST_VERSION_AT_LEAST(13,0,0) ast_engine.formats = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); #elif AST_VERSION_AT_LEAST(12,0,0) ast_engine.formats = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK); #else /* <= 11 */ ast_engine.formats = ast_format_cap_alloc_nolock(); #endif if(!ast_engine.formats) { ast_log(LOG_ERROR, "Failed to alloc media format capabilities\n"); uni_engine_unload(); return AST_MODULE_LOAD_FAILURE; } #if AST_VERSION_AT_LEAST(13,0,0) ast_format_cap_append(ast_engine.formats, ast_format_slin, 0); #else struct ast_format format; ast_format_set(&format, AST_FORMAT_SLINEAR, 0); ast_format_cap_add(ast_engine.formats, &format); #endif #else /* <= 1.8 */ ast_engine.formats = AST_FORMAT_SLINEAR; #endif if(ast_speech_register(&ast_engine)) { ast_log(LOG_ERROR, "Failed to register module\n"); mrcp_client_shutdown(uni_engine.client); uni_engine_unload(); return AST_MODULE_LOAD_FAILURE; } return AST_MODULE_LOAD_SUCCESS; }
/*! * \brief orginate a call from the CLI * \param fd file descriptor for cli * \param chan channel to create type/data * \param app application you want to run * \param appdata data for application * \retval CLI_SUCCESS on success. * \retval CLI_SHOWUSAGE on failure. */ static char *orig_app(int fd, const char *chan, const char *app, const char *appdata) { char *chantech; char *chandata; int reason = 0; struct ast_format_cap *cap; if (ast_strlen_zero(app)) return CLI_SHOWUSAGE; chandata = ast_strdupa(chan); chantech = strsep(&chandata, "/"); if (!chandata) { ast_cli(fd, "*** No data provided after channel type! ***\n"); return CLI_SHOWUSAGE; } if (!(cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) { return CLI_FAILURE; } ast_format_cap_append(cap, ast_format_slin, 0); ast_pbx_outgoing_app(chantech, cap, chandata, TIMEOUT * 1000, app, appdata, &reason, AST_OUTGOING_NO_WAIT, NULL, NULL, NULL, NULL, NULL, NULL); ao2_ref(cap, -1); return CLI_SUCCESS; }
/*! * \brief orginate from extension * \param fd file descriptor for cli * \param chan channel to create type/data * \param data contains exten\@context * \retval CLI_SUCCESS on success. * \retval CLI_SHOWUSAGE on failure. */ static char *orig_exten(int fd, const char *chan, const char *data) { char *chantech; char *chandata; char *exten = NULL; char *context = NULL; int reason = 0; struct ast_format_cap *cap; chandata = ast_strdupa(chan); chantech = strsep(&chandata, "/"); if (!chandata) { ast_cli(fd, "*** No data provided after channel type! ***\n"); return CLI_SHOWUSAGE; } if (!ast_strlen_zero(data)) { context = ast_strdupa(data); exten = strsep(&context, "@"); } if (ast_strlen_zero(exten)) exten = "s"; if (ast_strlen_zero(context)) context = "default"; if (!(cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) { return CLI_FAILURE; } ast_format_cap_append(cap, ast_format_slin, 0); ast_pbx_outgoing_exten(chantech, cap, chandata, TIMEOUT * 1000, context, exten, 1, &reason, 0, NULL, NULL, NULL, NULL, NULL, 0, NULL); ao2_ref(cap, -1); return CLI_SUCCESS; }
static int load_module(void) { if (!(native_rtp_bridge.format_capabilities = ast_format_cap_alloc(0))) { return AST_MODULE_LOAD_DECLINE; } ast_format_cap_append_by_type(native_rtp_bridge.format_capabilities, AST_MEDIA_TYPE_AUDIO); ast_format_cap_append_by_type(native_rtp_bridge.format_capabilities, AST_MEDIA_TYPE_VIDEO); ast_format_cap_append_by_type(native_rtp_bridge.format_capabilities, AST_MEDIA_TYPE_TEXT); return ast_bridge_technology_register(&native_rtp_bridge); }
static int load_module(void) { if (!(simple_bridge.format_capabilities = ast_format_cap_alloc())) { return AST_MODULE_LOAD_DECLINE; } ast_format_cap_add_all_by_type(simple_bridge.format_capabilities, AST_FORMAT_TYPE_AUDIO); ast_format_cap_add_all_by_type(simple_bridge.format_capabilities, AST_FORMAT_TYPE_VIDEO); ast_format_cap_add_all_by_type(simple_bridge.format_capabilities, AST_FORMAT_TYPE_TEXT); return ast_bridge_technology_register(&simple_bridge); }
static int load_module(void) { if (!(multiplexed_threads = ao2_container_alloc(MULTIPLEXED_BUCKETS, NULL, NULL))) { return AST_MODULE_LOAD_DECLINE; } if (!(multiplexed_bridge.format_capabilities = ast_format_cap_alloc())) { return AST_MODULE_LOAD_DECLINE; } ast_format_cap_add_all_by_type(multiplexed_bridge.format_capabilities, AST_FORMAT_TYPE_AUDIO); ast_format_cap_add_all_by_type(multiplexed_bridge.format_capabilities, AST_FORMAT_TYPE_VIDEO); ast_format_cap_add_all_by_type(multiplexed_bridge.format_capabilities, AST_FORMAT_TYPE_TEXT); return ast_bridge_technology_register(&multiplexed_bridge); }
/*! \brief Function called when our module is loaded */ static int load_module(void) { if (!(multicast_rtp_tech.capabilities = ast_format_cap_alloc(0))) { return AST_MODULE_LOAD_DECLINE; } ast_format_cap_add_all(multicast_rtp_tech.capabilities); if (ast_channel_register(&multicast_rtp_tech)) { ast_log(LOG_ERROR, "Unable to register channel class 'MulticastRTP'\n"); return AST_MODULE_LOAD_DECLINE; } return AST_MODULE_LOAD_SUCCESS; }
static int container_test3_helper(int nolocking, struct ast_test *test) { int x; int res = AST_TEST_PASS; struct ast_format_cap *cap1; struct ast_format_cap *cap2; struct ast_format_cap *joint; for (x = 0; x < 2000; x++) { if (nolocking) { cap1 = ast_format_cap_alloc_nolock(); cap2 = ast_format_cap_alloc_nolock(); joint = ast_format_cap_alloc_nolock(); } else { cap1 = ast_format_cap_alloc(); cap2 = ast_format_cap_alloc(); joint = ast_format_cap_alloc(); } if (!cap1 || !cap2 || !joint) { ast_test_status_update(test, "cap alloc fail\n"); return AST_TEST_FAIL; } ast_format_cap_add_all(cap1); ast_format_cap_add_all_by_type(cap2, AST_FORMAT_TYPE_AUDIO); ast_format_cap_joint_copy(cap1, cap2, joint); if (!(ast_format_cap_identical(cap2, joint))) { ast_test_status_update(test, "failed identical test\n"); res = AST_TEST_FAIL; cap1 = ast_format_cap_destroy(cap1); cap2 = ast_format_cap_destroy(cap2); joint = ast_format_cap_destroy(joint); break; } cap1 = ast_format_cap_destroy(cap1); cap2 = ast_format_cap_destroy(cap2); joint = ast_format_cap_destroy(joint); } return res; }
/*! \brief Load module into PBX, register channel */ static int load_module(void) { if (!(bridge_tech.capabilities = ast_format_cap_alloc())) { return AST_MODULE_LOAD_FAILURE; } ast_format_cap_add_all(bridge_tech.capabilities); /* Make sure we can register our channel type */ if (ast_channel_register(&bridge_tech)) { ast_log(LOG_ERROR, "Unable to register channel class 'Bridge'\n"); return AST_MODULE_LOAD_FAILURE; } return AST_MODULE_LOAD_SUCCESS; }
struct ast_format_cap *ast_format_cap_dup(const struct ast_format_cap *cap) { struct ast_format_cap *dst; if (cap->nolock) { dst = ast_format_cap_alloc_nolock(); } else { dst = ast_format_cap_alloc(); } if (!dst) { return NULL; } ao2_callback(cap->formats, OBJ_NODATA | cap->nolock, copy_cb, dst); return dst; }
int ast_local_init(void) { if (STASIS_MESSAGE_TYPE_INIT(ast_local_optimization_begin_type)) { return -1; } if (STASIS_MESSAGE_TYPE_INIT(ast_local_optimization_end_type)) { return -1; } if (STASIS_MESSAGE_TYPE_INIT(ast_local_bridge_type)) { return -1; } if (!(local_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) { return -1; } ast_format_cap_append_by_type(local_tech.capabilities, AST_MEDIA_TYPE_UNKNOWN); locals = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_MUTEX, 0, NULL, locals_cmp_cb); if (!locals) { ao2_cleanup(local_tech.capabilities); local_tech.capabilities = NULL; return -1; } /* Make sure we can register our channel type */ if (ast_channel_register(&local_tech)) { ast_log(LOG_ERROR, "Unable to register channel class 'Local'\n"); ao2_ref(locals, -1); ao2_cleanup(local_tech.capabilities); local_tech.capabilities = NULL; return -1; } ast_cli_register_multiple(cli_local, ARRAY_LEN(cli_local)); ast_manager_register_xml_core("LocalOptimizeAway", EVENT_FLAG_SYSTEM|EVENT_FLAG_CALL, manager_optimize_away); ast_register_cleanup(local_shutdown); return 0; }
static struct ast_channel *prepare_bridge_media_channel(const char *type) { RAII_VAR(struct ast_format_cap *, cap, NULL, ao2_cleanup); struct ast_channel *chan; cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); if (!cap) { return NULL; } ast_format_cap_append(cap, ast_format_slin, 0); chan = ast_request(type, cap, NULL, NULL, "ARI", NULL); if (!chan) { return NULL; } if (stasis_app_channel_unreal_set_internal(chan)) { ast_channel_cleanup(chan); return NULL; } return chan; }
static int set_caps(struct ast_sip_session *session, struct ast_sip_session_media *session_media, const struct pjmedia_sdp_media *stream) { RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup); RAII_VAR(struct ast_format_cap *, peer, NULL, ao2_cleanup); RAII_VAR(struct ast_format_cap *, joint, NULL, ao2_cleanup); enum ast_media_type media_type = stream_to_media_type(session_media->stream_type); struct ast_rtp_codecs codecs = AST_RTP_CODECS_NULL_INIT; int fmts = 0; int direct_media_enabled = !ast_sockaddr_isnull(&session_media->direct_media_addr) && ast_format_cap_count(session->direct_media_cap); int dsp_features = 0; if (!(caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT)) || !(peer = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT)) || !(joint = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) { ast_log(LOG_ERROR, "Failed to allocate %s capabilities\n", session_media->stream_type); return -1; } /* get the endpoint capabilities */ if (direct_media_enabled) { ast_format_cap_get_compatible(session->endpoint->media.codecs, session->direct_media_cap, caps); format_cap_only_type(caps, media_type); } else { ast_format_cap_append_from_cap(caps, session->endpoint->media.codecs, media_type); } /* get the capabilities on the peer */ get_codecs(session, stream, &codecs, session_media); ast_rtp_codecs_payload_formats(&codecs, peer, &fmts); /* get the joint capabilities between peer and endpoint */ ast_format_cap_get_compatible(caps, peer, joint); if (!ast_format_cap_count(joint)) { struct ast_str *usbuf = ast_str_alloca(256); struct ast_str *thembuf = ast_str_alloca(256); ast_rtp_codecs_payloads_destroy(&codecs); ast_log(LOG_NOTICE, "No joint capabilities for '%s' media stream between our configuration(%s) and incoming SDP(%s)\n", session_media->stream_type, ast_format_cap_get_names(caps, &usbuf), ast_format_cap_get_names(peer, &thembuf)); return -1; } ast_rtp_codecs_payloads_copy(&codecs, ast_rtp_instance_get_codecs(session_media->rtp), session_media->rtp); ast_format_cap_append_from_cap(session->req_caps, joint, AST_MEDIA_TYPE_UNKNOWN); if (session->channel) { ast_channel_lock(session->channel); ast_format_cap_remove_by_type(caps, AST_MEDIA_TYPE_UNKNOWN); ast_format_cap_append_from_cap(caps, ast_channel_nativeformats(session->channel), AST_MEDIA_TYPE_UNKNOWN); ast_format_cap_remove_by_type(caps, media_type); ast_format_cap_append_from_cap(caps, joint, media_type); /* * Apply the new formats to the channel, potentially changing * raw read/write formats and translation path while doing so. */ ast_channel_nativeformats_set(session->channel, caps); if (media_type == AST_MEDIA_TYPE_AUDIO) { ast_set_read_format(session->channel, ast_channel_readformat(session->channel)); ast_set_write_format(session->channel, ast_channel_writeformat(session->channel)); } if ((session->endpoint->dtmf == AST_SIP_DTMF_AUTO) && (ast_rtp_instance_dtmf_mode_get(session_media->rtp) == AST_RTP_DTMF_MODE_RFC2833) && (session->dsp)) { dsp_features = ast_dsp_get_features(session->dsp); dsp_features &= ~DSP_FEATURE_DIGIT_DETECT; if (dsp_features) { ast_dsp_set_features(session->dsp, dsp_features); } else { ast_dsp_free(session->dsp); session->dsp = NULL; } } ast_channel_unlock(session->channel); } ast_rtp_codecs_payloads_destroy(&codecs); return 0; }
static int func_channel_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len) { int ret = 0; struct ast_format_cap *tmpcap; if (!chan) { ast_log(LOG_WARNING, "No channel was provided to %s function.\n", function); return -1; } if (!strcasecmp(data, "audionativeformat")) { tmpcap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); if (tmpcap) { struct ast_str *codec_buf = ast_str_alloca(128); ast_channel_lock(chan); ast_format_cap_append_from_cap(tmpcap, ast_channel_nativeformats(chan), AST_MEDIA_TYPE_AUDIO); ast_channel_unlock(chan); ast_copy_string(buf, ast_format_cap_get_names(tmpcap, &codec_buf), len); ao2_ref(tmpcap, -1); } } else if (!strcasecmp(data, "videonativeformat")) { tmpcap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); if (tmpcap) { struct ast_str *codec_buf = ast_str_alloca(128); ast_channel_lock(chan); ast_format_cap_append_from_cap(tmpcap, ast_channel_nativeformats(chan), AST_MEDIA_TYPE_VIDEO); ast_channel_unlock(chan); ast_copy_string(buf, ast_format_cap_get_names(tmpcap, &codec_buf), len); ao2_ref(tmpcap, -1); } } else if (!strcasecmp(data, "audioreadformat")) { locked_copy_string(chan, buf, ast_format_get_name(ast_channel_readformat(chan)), len); } else if (!strcasecmp(data, "audiowriteformat")) { locked_copy_string(chan, buf, ast_format_get_name(ast_channel_writeformat(chan)), len); #ifdef CHANNEL_TRACE } else if (!strcasecmp(data, "trace")) { locked_copy_string(chan, buf, ast_channel_trace_is_enabled(chan) ? "1" : "0", len); #endif } else if (!strcasecmp(data, "tonezone") && ast_channel_zone(chan)) { locked_copy_string(chan, buf, ast_channel_zone(chan)->country, len); } else if (!strcasecmp(data, "dtmf_features")) { if (ast_bridge_features_ds_get_string(chan, buf, len)) { buf[0] = '\0'; } } else if (!strcasecmp(data, "language")) locked_copy_string(chan, buf, ast_channel_language(chan), len); else if (!strcasecmp(data, "musicclass")) locked_copy_string(chan, buf, ast_channel_musicclass(chan), len); else if (!strcasecmp(data, "name")) { locked_copy_string(chan, buf, ast_channel_name(chan), len); } else if (!strcasecmp(data, "parkinglot")) locked_copy_string(chan, buf, ast_channel_parkinglot(chan), len); else if (!strcasecmp(data, "state")) locked_copy_string(chan, buf, ast_state2str(ast_channel_state(chan)), len); else if (!strcasecmp(data, "onhold")) { locked_copy_string(chan, buf, ast_channel_hold_state(chan) == AST_CONTROL_HOLD ? "1" : "0", len); } else if (!strcasecmp(data, "channeltype")) locked_copy_string(chan, buf, ast_channel_tech(chan)->type, len); else if (!strcasecmp(data, "accountcode")) locked_copy_string(chan, buf, ast_channel_accountcode(chan), len); else if (!strcasecmp(data, "checkhangup")) { locked_copy_string(chan, buf, ast_check_hangup(chan) ? "1" : "0", len); } else if (!strcasecmp(data, "peeraccount")) locked_copy_string(chan, buf, ast_channel_peeraccount(chan), len); else if (!strcasecmp(data, "hangupsource")) locked_copy_string(chan, buf, ast_channel_hangupsource(chan), len); else if (!strcasecmp(data, "appname") && ast_channel_appl(chan)) locked_copy_string(chan, buf, ast_channel_appl(chan), len); else if (!strcasecmp(data, "appdata") && ast_channel_data(chan)) locked_copy_string(chan, buf, ast_channel_data(chan), len); else if (!strcasecmp(data, "exten") && ast_channel_data(chan)) locked_copy_string(chan, buf, ast_channel_exten(chan), len); else if (!strcasecmp(data, "context") && ast_channel_data(chan)) locked_copy_string(chan, buf, ast_channel_context(chan), len); else if (!strcasecmp(data, "userfield") && ast_channel_data(chan)) locked_copy_string(chan, buf, ast_channel_userfield(chan), len); else if (!strcasecmp(data, "channame") && ast_channel_data(chan)) locked_copy_string(chan, buf, ast_channel_name(chan), len); else if (!strcasecmp(data, "linkedid")) { ast_channel_lock(chan); if (ast_strlen_zero(ast_channel_linkedid(chan))) { /* fall back on the channel's uniqueid if linkedid is unset */ ast_copy_string(buf, ast_channel_uniqueid(chan), len); } else { ast_copy_string(buf, ast_channel_linkedid(chan), len); } ast_channel_unlock(chan); } else if (!strcasecmp(data, "peer")) { struct ast_channel *peer; peer = ast_channel_bridge_peer(chan); if (peer) { /* Only real channels could have a bridge peer this way. */ ast_channel_lock(peer); ast_copy_string(buf, ast_channel_name(peer), len); ast_channel_unlock(peer); ast_channel_unref(peer); } else { buf[0] = '\0'; ast_channel_lock(chan); if (!ast_channel_tech(chan)) { const char *pname; /* * A dummy channel can still pass along bridged peer info * via the BRIDGEPEER variable. * * A horrible kludge, but... how else? */ pname = pbx_builtin_getvar_helper(chan, "BRIDGEPEER"); if (!ast_strlen_zero(pname)) { ast_copy_string(buf, pname, len); } } ast_channel_unlock(chan); } } else if (!strcasecmp(data, "uniqueid")) { locked_copy_string(chan, buf, ast_channel_uniqueid(chan), len); } else if (!strcasecmp(data, "transfercapability")) { locked_copy_string(chan, buf, transfercapability_table[ast_channel_transfercapability(chan) & 0x1f], len); } else if (!strcasecmp(data, "callgroup")) { char groupbuf[256]; locked_copy_string(chan, buf, ast_print_group(groupbuf, sizeof(groupbuf), ast_channel_callgroup(chan)), len); } else if (!strcasecmp(data, "pickupgroup")) { char groupbuf[256]; locked_copy_string(chan, buf, ast_print_group(groupbuf, sizeof(groupbuf), ast_channel_pickupgroup(chan)), len); } else if (!strcasecmp(data, "namedcallgroup")) { struct ast_str *tmp_str = ast_str_alloca(1024); locked_copy_string(chan, buf, ast_print_namedgroups(&tmp_str, ast_channel_named_callgroups(chan)), len); } else if (!strcasecmp(data, "namedpickupgroup")) { struct ast_str *tmp_str = ast_str_alloca(1024); locked_copy_string(chan, buf, ast_print_namedgroups(&tmp_str, ast_channel_named_pickupgroups(chan)), len); } else if (!strcasecmp(data, "after_bridge_goto")) { ast_bridge_read_after_goto(chan, buf, len); } else if (!strcasecmp(data, "amaflags")) { ast_channel_lock(chan); snprintf(buf, len, "%u", ast_channel_amaflags(chan)); ast_channel_unlock(chan); } else if (!strncasecmp(data, "secure_bridge_", 14)) { struct ast_datastore *ds; buf[0] = '\0'; ast_channel_lock(chan); if ((ds = ast_channel_datastore_find(chan, &secure_call_info, NULL))) { struct ast_secure_call_store *encrypt = ds->data; if (!strcasecmp(data, "secure_bridge_signaling")) { snprintf(buf, len, "%s", encrypt->signaling ? "1" : ""); } else if (!strcasecmp(data, "secure_bridge_media")) { snprintf(buf, len, "%s", encrypt->media ? "1" : ""); } } ast_channel_unlock(chan); } else if (!strcasecmp(data, "max_forwards")) { ast_channel_lock(chan); snprintf(buf, len, "%d", ast_max_forwards_get(chan)); ast_channel_unlock(chan); } else if (!ast_channel_tech(chan) || !ast_channel_tech(chan)->func_channel_read || ast_channel_tech(chan)->func_channel_read(chan, function, data, buf, len)) { ast_log(LOG_WARNING, "Unknown or unavailable item requested: '%s'\n", data); ret = -1; } return ret; }
static int set_caps(struct ast_sip_session *session, struct ast_sip_session_media *session_media, const struct pjmedia_sdp_media *stream) { RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup); RAII_VAR(struct ast_format_cap *, peer, NULL, ao2_cleanup); RAII_VAR(struct ast_format_cap *, joint, NULL, ao2_cleanup); enum ast_media_type media_type = stream_to_media_type(session_media->stream_type); struct ast_rtp_codecs codecs = AST_RTP_CODECS_NULL_INIT; int fmts = 0; int direct_media_enabled = !ast_sockaddr_isnull(&session_media->direct_media_addr) && ast_format_cap_count(session->direct_media_cap); if (!(caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT)) || !(peer = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT)) || !(joint = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) { ast_log(LOG_ERROR, "Failed to allocate %s capabilities\n", session_media->stream_type); return -1; } /* get the endpoint capabilities */ if (direct_media_enabled) { ast_format_cap_get_compatible(session->endpoint->media.codecs, session->direct_media_cap, caps); format_cap_only_type(caps, media_type); } else { ast_format_cap_append_from_cap(caps, session->endpoint->media.codecs, media_type); } /* get the capabilities on the peer */ get_codecs(session, stream, &codecs); ast_rtp_codecs_payload_formats(&codecs, peer, &fmts); /* get the joint capabilities between peer and endpoint */ ast_format_cap_get_compatible(caps, peer, joint); if (!ast_format_cap_count(joint)) { struct ast_str *usbuf = ast_str_alloca(64); struct ast_str *thembuf = ast_str_alloca(64); ast_rtp_codecs_payloads_destroy(&codecs); ast_log(LOG_NOTICE, "No joint capabilities for '%s' media stream between our configuration(%s) and incoming SDP(%s)\n", session_media->stream_type, ast_format_cap_get_names(caps, &usbuf), ast_format_cap_get_names(peer, &thembuf)); return -1; } ast_rtp_codecs_payloads_copy(&codecs, ast_rtp_instance_get_codecs(session_media->rtp), session_media->rtp); ast_format_cap_append_from_cap(session->req_caps, joint, AST_MEDIA_TYPE_UNKNOWN); if (session->channel) { struct ast_format *fmt; ast_channel_lock(session->channel); ast_format_cap_remove_by_type(caps, AST_MEDIA_TYPE_UNKNOWN); ast_format_cap_append_from_cap(caps, ast_channel_nativeformats(session->channel), AST_MEDIA_TYPE_UNKNOWN); ast_format_cap_remove_by_type(caps, media_type); /* * XXX Historically we picked the "best" joint format to use * and stuck with it. It would be nice to just append the * determined joint media capabilities to give translation * more formats to choose from when necessary. Unfortunately, * there are some areas of the system where this doesn't work * very well. (The softmix bridge in particular is reluctant * to pick higher fidelity formats and has a problem with * asymmetric sample rates.) */ fmt = ast_format_cap_get_format(joint, 0); ast_format_cap_append(caps, fmt, 0); /* * Apply the new formats to the channel, potentially changing * raw read/write formats and translation path while doing so. */ ast_channel_nativeformats_set(session->channel, caps); ast_set_read_format(session->channel, ast_channel_readformat(session->channel)); ast_set_write_format(session->channel, ast_channel_writeformat(session->channel)); ast_channel_unlock(session->channel); ao2_ref(fmt, -1); } ast_rtp_codecs_payloads_destroy(&codecs); return 0; }
struct ast_unreal_pvt *ast_unreal_alloc(size_t size, ao2_destructor_fn destructor, struct ast_format_cap *cap) { struct ast_unreal_pvt *unreal; static const struct ast_jb_conf jb_conf = { .flags = 0, .max_size = -1, .resync_threshold = -1, .impl = "", .target_extra = -1, }; unreal = ao2_alloc(size, destructor); if (!unreal) { return NULL; } unreal->reqcap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); if (!unreal->reqcap) { ao2_ref(unreal, -1); return NULL; } ast_format_cap_append_from_cap(unreal->reqcap, cap, AST_MEDIA_TYPE_UNKNOWN); memcpy(&unreal->jb_conf, &jb_conf, sizeof(unreal->jb_conf)); return unreal; } struct ast_channel *ast_unreal_new_channels(struct ast_unreal_pvt *p, const struct ast_channel_tech *tech, int semi1_state, int semi2_state, const char *exten, const char *context, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, struct ast_callid *callid) { struct ast_channel *owner; struct ast_channel *chan; RAII_VAR(struct ast_format *, fmt, NULL, ao2_cleanup); struct ast_assigned_ids id1 = {NULL, NULL}; struct ast_assigned_ids id2 = {NULL, NULL}; int generated_seqno = ast_atomic_fetchadd_int((int *) &name_sequence, +1); /* set unique ids for the two channels */ if (assignedids && !ast_strlen_zero(assignedids->uniqueid)) { id1.uniqueid = assignedids->uniqueid; id2.uniqueid = assignedids->uniqueid2; } /* if id1 given but not id2, use default of id1;2 */ if (id1.uniqueid && ast_strlen_zero(id2.uniqueid)) { char *uniqueid2; uniqueid2 = ast_alloca(strlen(id1.uniqueid) + 3); strcpy(uniqueid2, id1.uniqueid);/* Safe */ strcat(uniqueid2, ";2");/* Safe */ id2.uniqueid = uniqueid2; } /* * Allocate two new Asterisk channels * * Make sure that the ;2 channel gets the same linkedid as ;1. * You can't pass linkedid to both allocations since if linkedid * isn't set, then each channel will generate its own linkedid. */ owner = ast_channel_alloc(1, semi1_state, NULL, NULL, NULL, exten, context, &id1, requestor, 0, "%s/%s-%08x;1", tech->type, p->name, (unsigned)generated_seqno); if (!owner) { ast_log(LOG_WARNING, "Unable to allocate owner channel structure\n"); return NULL; } if (callid) { ast_channel_callid_set(owner, callid); } ast_channel_tech_set(owner, tech); ao2_ref(p, +1); ast_channel_tech_pvt_set(owner, p); ast_channel_nativeformats_set(owner, p->reqcap); /* Determine our read/write format and set it on each channel */ fmt = ast_format_cap_get_format(p->reqcap, 0); if (!fmt) { ast_channel_tech_pvt_set(owner, NULL); ao2_ref(p, -1); ast_channel_unlock(owner); ast_channel_release(owner); return NULL; } ast_channel_set_writeformat(owner, fmt); ast_channel_set_rawwriteformat(owner, fmt); ast_channel_set_readformat(owner, fmt); ast_channel_set_rawreadformat(owner, fmt); ast_set_flag(ast_channel_flags(owner), AST_FLAG_DISABLE_DEVSTATE_CACHE); ast_jb_configure(owner, &p->jb_conf); if (ast_channel_cc_params_init(owner, requestor ? ast_channel_get_cc_config_params((struct ast_channel *) requestor) : NULL)) { ast_channel_tech_pvt_set(owner, NULL); ao2_ref(p, -1); ast_channel_tech_pvt_set(owner, NULL); ast_channel_unlock(owner); ast_channel_release(owner); return NULL; } p->owner = owner; ast_channel_unlock(owner); chan = ast_channel_alloc(1, semi2_state, NULL, NULL, NULL, exten, context, &id2, owner, 0, "%s/%s-%08x;2", tech->type, p->name, (unsigned)generated_seqno); if (!chan) { ast_log(LOG_WARNING, "Unable to allocate chan channel structure\n"); ast_channel_tech_pvt_set(owner, NULL); ao2_ref(p, -1); ast_channel_tech_pvt_set(owner, NULL); ast_channel_release(owner); return NULL; } if (callid) { ast_channel_callid_set(chan, callid); } ast_channel_tech_set(chan, tech); ao2_ref(p, +1); ast_channel_tech_pvt_set(chan, p); ast_channel_nativeformats_set(chan, p->reqcap); /* Format was already determined when setting up owner */ ast_channel_set_writeformat(chan, fmt); ast_channel_set_rawwriteformat(chan, fmt); ast_channel_set_readformat(chan, fmt); ast_channel_set_rawreadformat(chan, fmt); ast_set_flag(ast_channel_flags(chan), AST_FLAG_DISABLE_DEVSTATE_CACHE); p->chan = chan; ast_channel_unlock(chan); return owner; }
static int set_caps(struct ast_sip_session *session, struct ast_sip_session_media *session_media, const struct pjmedia_sdp_media *stream) { RAII_VAR(struct ast_format_cap *, caps, NULL, ast_format_cap_destroy); RAII_VAR(struct ast_format_cap *, peer, NULL, ast_format_cap_destroy); RAII_VAR(struct ast_format_cap *, joint, NULL, ast_format_cap_destroy); enum ast_format_type media_type = stream_to_media_type(session_media->stream_type); struct ast_rtp_codecs codecs; struct ast_format fmt; int fmts = 0; int direct_media_enabled = !ast_sockaddr_isnull(&session_media->direct_media_addr) && !ast_format_cap_is_empty(session->direct_media_cap); if (!(caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK)) || !(peer = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK))) { ast_log(LOG_ERROR, "Failed to allocate %s capabilities\n", session_media->stream_type); return -1; } /* get the endpoint capabilities */ if (direct_media_enabled) { ast_format_cap_joint_copy(session->endpoint->media.codecs, session->direct_media_cap, caps); } else { ast_format_cap_copy(caps, session->endpoint->media.codecs); } format_cap_only_type(caps, media_type); /* get the capabilities on the peer */ get_codecs(session, stream, &codecs); ast_rtp_codecs_payload_formats(&codecs, peer, &fmts); /* get the joint capabilities between peer and endpoint */ if (!(joint = ast_format_cap_joint(caps, peer))) { char usbuf[64], thembuf[64]; ast_rtp_codecs_payloads_destroy(&codecs); ast_getformatname_multiple(usbuf, sizeof(usbuf), caps); ast_getformatname_multiple(thembuf, sizeof(thembuf), peer); ast_log(LOG_WARNING, "No joint capabilities between our configuration(%s) and incoming SDP(%s)\n", usbuf, thembuf); return -1; } ast_rtp_codecs_payloads_copy(&codecs, ast_rtp_instance_get_codecs(session_media->rtp), session_media->rtp); ast_format_cap_copy(caps, session->req_caps); ast_format_cap_remove_bytype(caps, media_type); ast_format_cap_append(caps, joint); ast_format_cap_append(session->req_caps, caps); if (session->channel) { ast_format_cap_copy(caps, ast_channel_nativeformats(session->channel)); ast_format_cap_remove_bytype(caps, media_type); ast_codec_choose(&session->endpoint->media.prefs, joint, 1, &fmt); ast_format_cap_add(caps, &fmt); /* Apply the new formats to the channel, potentially changing read/write formats while doing so */ ast_format_cap_copy(ast_channel_nativeformats(session->channel), caps); ast_set_read_format(session->channel, ast_channel_readformat(session->channel)); ast_set_write_format(session->channel, ast_channel_writeformat(session->channel)); } ast_rtp_codecs_payloads_destroy(&codecs); return 0; }
struct ast_channel *stasis_app_control_snoop(struct ast_channel *chan, enum stasis_app_snoop_direction spy, enum stasis_app_snoop_direction whisper, const char *app, const char *app_args, const char *snoop_id) { RAII_VAR(struct stasis_app_snoop *, snoop, NULL, ao2_cleanup); struct ast_format_cap *caps; pthread_t thread; struct ast_assigned_ids assignedids = { .uniqueid = snoop_id, }; if (spy == STASIS_SNOOP_DIRECTION_NONE && whisper == STASIS_SNOOP_DIRECTION_NONE) { return NULL; } snoop = ao2_alloc_options(sizeof(*snoop), snoop_destroy, AO2_ALLOC_OPT_LOCK_NOLOCK); if (!snoop) { return NULL; } /* Allocate a buffer to store the Stasis application and arguments in */ snoop->app = ast_str_create(64); if (!snoop->app) { return NULL; } ast_str_set(&snoop->app, 0, "%s", app); if (!ast_strlen_zero(app_args)) { ast_str_append(&snoop->app, 0, ",%s", app_args); } /* Set up a timer for the Snoop channel so it wakes up at a specific interval */ snoop->timer = ast_timer_open(); if (!snoop->timer) { return NULL; } ast_timer_set_rate(snoop->timer, 1000 / SNOOP_INTERVAL); /* Determine which signed linear format should be used */ snoop_determine_format(chan, snoop); /* Allocate a Snoop channel and set up various parameters */ snoop->chan = ast_channel_alloc(1, AST_STATE_UP, "", "", "", "", "", &assignedids, NULL, 0, "Snoop/%s-%08x", ast_channel_uniqueid(chan), (unsigned)ast_atomic_fetchadd_int((int *)&chan_idx, +1)); if (!snoop->chan) { return NULL; } ast_copy_string(snoop->uniqueid, ast_channel_uniqueid(chan), sizeof(snoop->uniqueid)); /* To keep the channel valid on the Snoop structure until it is destroyed we bump the ref up here */ ast_channel_ref(snoop->chan); ast_channel_tech_set(snoop->chan, &snoop_tech); ao2_ref(snoop, +1); ast_channel_tech_pvt_set(snoop->chan, snoop); ast_channel_set_fd(snoop->chan, 0, ast_timer_fd(snoop->timer)); /* The format on the Snoop channel will be this signed linear format, and it will never change */ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); if (!caps) { ast_channel_unlock(snoop->chan); ast_hangup(snoop->chan); return NULL; } ast_format_cap_append(caps, snoop->spy_format, 0); ast_channel_nativeformats_set(snoop->chan, caps); ao2_ref(caps, -1); ast_channel_set_writeformat(snoop->chan, snoop->spy_format); ast_channel_set_rawwriteformat(snoop->chan, snoop->spy_format); ast_channel_set_readformat(snoop->chan, snoop->spy_format); ast_channel_set_rawreadformat(snoop->chan, snoop->spy_format); ast_channel_unlock(snoop->chan); if (spy != STASIS_SNOOP_DIRECTION_NONE) { if (snoop_setup_audiohook(chan, AST_AUDIOHOOK_TYPE_SPY, spy, &snoop->spy_direction, &snoop->spy)) { ast_hangup(snoop->chan); return NULL; } snoop->spy_samples = ast_format_get_sample_rate(snoop->spy_format) / (1000 / SNOOP_INTERVAL); snoop->spy_active = 1; } /* If whispering is enabled set up the audiohook */ if (whisper != STASIS_SNOOP_DIRECTION_NONE) { if (snoop_setup_audiohook(chan, AST_AUDIOHOOK_TYPE_WHISPER, whisper, &snoop->whisper_direction, &snoop->whisper)) { ast_hangup(snoop->chan); return NULL; } snoop->whisper_active = 1; } /* Create the thread which services the Snoop channel */ ao2_ref(snoop, +1); if (ast_pthread_create_detached_background(&thread, NULL, snoop_stasis_thread, snoop)) { ao2_cleanup(snoop); /* No other thread is servicing this channel so we can immediately hang it up */ ast_hangup(snoop->chan); return NULL; } publish_chanspy_message(snoop, 1); /* The caller of this has a reference as well */ return ast_channel_ref(snoop->chan); }
static int native_rtp_bridge_compatible_check(struct ast_bridge *bridge, struct ast_bridge_channel *bc0, struct ast_bridge_channel *bc1) { enum ast_rtp_glue_result native_type; struct ast_rtp_glue *glue0; struct ast_rtp_glue *glue1; RAII_VAR(struct ast_rtp_instance *, instance0, NULL, ao2_cleanup); RAII_VAR(struct ast_rtp_instance *, instance1, NULL, ao2_cleanup); RAII_VAR(struct ast_rtp_instance *, vinstance0, NULL, ao2_cleanup); RAII_VAR(struct ast_rtp_instance *, vinstance1, NULL, ao2_cleanup); RAII_VAR(struct ast_format_cap *, cap0, NULL, ao2_cleanup); RAII_VAR(struct ast_format_cap *, cap1, NULL, ao2_cleanup); int read_ptime0; int read_ptime1; int write_ptime0; int write_ptime1; if (!native_rtp_bridge_capable(bc0->chan)) { ast_debug(1, "Bridge '%s' can not use native RTP bridge as channel '%s' has features which prevent it\n", bridge->uniqueid, ast_channel_name(bc0->chan)); return 0; } if (!native_rtp_bridge_capable(bc1->chan)) { ast_debug(1, "Bridge '%s' can not use native RTP bridge as channel '%s' has features which prevent it\n", bridge->uniqueid, ast_channel_name(bc1->chan)); return 0; } native_type = native_rtp_bridge_get(bc0->chan, bc1->chan, &glue0, &glue1, &instance0, &instance1, &vinstance0, &vinstance1); if (native_type == AST_RTP_GLUE_RESULT_FORBID) { ast_debug(1, "Bridge '%s' can not use native RTP bridge as it was forbidden while getting details\n", bridge->uniqueid); return 0; } if (ao2_container_count(bc0->features->dtmf_hooks) && ast_rtp_instance_dtmf_mode_get(instance0)) { ast_debug(1, "Bridge '%s' can not use native RTP bridge as channel '%s' has DTMF hooks\n", bridge->uniqueid, ast_channel_name(bc0->chan)); return 0; } if (ao2_container_count(bc1->features->dtmf_hooks) && ast_rtp_instance_dtmf_mode_get(instance1)) { ast_debug(1, "Bridge '%s' can not use native RTP bridge as channel '%s' has DTMF hooks\n", bridge->uniqueid, ast_channel_name(bc1->chan)); return 0; } if (native_type == AST_RTP_GLUE_RESULT_LOCAL && (ast_rtp_instance_get_engine(instance0)->local_bridge != ast_rtp_instance_get_engine(instance1)->local_bridge || (ast_rtp_instance_get_engine(instance0)->dtmf_compatible && !ast_rtp_instance_get_engine(instance0)->dtmf_compatible(bc0->chan, instance0, bc1->chan, instance1)))) { ast_debug(1, "Bridge '%s' can not use local native RTP bridge as local bridge or DTMF is not compatible\n", bridge->uniqueid); return 0; } cap0 = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); cap1 = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); if (!cap0 || !cap1) { return 0; } /* Make sure that codecs match */ if (glue0->get_codec) { glue0->get_codec(bc0->chan, cap0); } if (glue1->get_codec) { glue1->get_codec(bc1->chan, cap1); } if (ast_format_cap_count(cap0) != 0 && ast_format_cap_count(cap1) != 0 && !ast_format_cap_iscompatible(cap0, cap1)) { struct ast_str *codec_buf0 = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN); struct ast_str *codec_buf1 = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN); ast_debug(1, "Bridge '%s': Channel codec0 = %s is not codec1 = %s, cannot native bridge in RTP.\n", bridge->uniqueid, ast_format_cap_get_names(cap0, &codec_buf0), ast_format_cap_get_names(cap1, &codec_buf1)); return 0; } read_ptime0 = ast_format_cap_get_format_framing(cap0, ast_channel_rawreadformat(bc0->chan)); read_ptime1 = ast_format_cap_get_format_framing(cap1, ast_channel_rawreadformat(bc1->chan)); write_ptime0 = ast_format_cap_get_format_framing(cap0, ast_channel_rawwriteformat(bc0->chan)); write_ptime1 = ast_format_cap_get_format_framing(cap1, ast_channel_rawwriteformat(bc1->chan)); if (read_ptime0 != write_ptime1 || read_ptime1 != write_ptime0) { ast_debug(1, "Bridge '%s': Packetization differs between RTP streams (%d != %d or %d != %d). Cannot native bridge in RTP\n", bridge->uniqueid, read_ptime0, write_ptime1, read_ptime1, write_ptime0); return 0; } return 1; }