static void cleanup_capabilities(void) { if (announce_tech.capabilities) { announce_tech.capabilities = ast_format_cap_destroy(announce_tech.capabilities); } if (record_tech.capabilities) { record_tech.capabilities = ast_format_cap_destroy(record_tech.capabilities); } }
/*! \brief Function called when our module is unloaded */ static int unload_module(void) { ast_channel_unregister(&multicast_rtp_tech); multicast_rtp_tech.capabilities = ast_format_cap_destroy(multicast_rtp_tech.capabilities); return 0; }
static int container_test2_no_locking_helper(struct ast_format_cap *cap, struct ast_test *test) { int num = 0; struct ast_format tmpformat = { 0, }; ast_format_cap_add(cap, ast_format_set(&tmpformat, AST_FORMAT_GSM, 0)); ast_format_cap_add(cap, ast_format_set(&tmpformat, AST_FORMAT_ULAW, 0)); ast_format_cap_add(cap, ast_format_set(&tmpformat, AST_FORMAT_G722, 0)); ast_format_cap_iter_start(cap); while (!ast_format_cap_iter_next(cap, &tmpformat)) { num++; } ast_format_cap_iter_end(cap); ast_format_cap_iter_start(cap); while (!ast_format_cap_iter_next(cap, &tmpformat)) { num++; } ast_format_cap_iter_end(cap); ast_format_cap_destroy(cap); ast_test_status_update(test, "%d items iterated over\n", num); return (num == 6) ? AST_TEST_PASS : AST_TEST_FAIL; }
static int unload_module(void) { int res = ast_bridge_technology_unregister(&multiplexed_bridge); ao2_ref(multiplexed_threads, -1); multiplexed_bridge.format_capabilities = ast_format_cap_destroy(multiplexed_bridge.format_capabilities); return res; }
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; }
static int nv_detectfax_exec(struct ast_channel *chan, const char *data) { int res = 0; char tmp[256] = "\0"; char *p = NULL; char *waitstr = NULL; char *options = NULL; char *silstr = NULL; char *minstr = NULL; char *maxstr = NULL; struct ast_frame *fr = NULL; struct ast_frame *fr2 = NULL; int notsilent = 0; struct timeval start = {0, 0}, end = {0, 0}; int waitdur = 4; int sildur = 1000; int mindur = 100; int maxdur = -1; int skipanswer = 0; int noextneeded = 0; int ignoredtmf = 0; int ignorefax = 0; int ignoretalk = 0; int x = 0; struct ast_format* origrformat = NULL; int features = 0; time_t timeout = 0; struct ast_dsp *dsp = NULL; struct ast_format_cap *cap; struct ast_format linearFormat; /* linear format capabilities */ ast_format_set(&linearFormat, AST_FORMAT_SLINEAR, 0); cap = ast_format_cap_alloc_nolock(); ast_format_cap_add(cap, &linearFormat); /* done */ pbx_builtin_setvar_helper(chan, "FAX_DETECTED", ""); pbx_builtin_setvar_helper(chan, "FAXEXTEN", ""); pbx_builtin_setvar_helper(chan, "DTMF_DETECTED", ""); pbx_builtin_setvar_helper(chan, "TALK_DETECTED", ""); if (data || !ast_strlen_zero(data)) { strncpy(tmp, data, sizeof(tmp)-1); } p = tmp; waitstr = strsep(&p, ","); options = strsep(&p, ","); silstr = strsep(&p, ","); minstr = strsep(&p, ","); maxstr = strsep(&p, ","); if (waitstr) { if ((sscanf(waitstr, "%d", &x) == 1) && (x > 0)) waitdur = x; } if (options) { if (strchr(options, 'n')) skipanswer = 1; if (strchr(options, 'x')) noextneeded = 1; if (strchr(options, 'd')) ignoredtmf = 1; if (strchr(options, 'f')) ignorefax = 1; if (strchr(options, 't')) ignoretalk = 1; } if (silstr) { if ((sscanf(silstr, "%d", &x) == 1) && (x > 0)) sildur = x; } if (minstr) { if ((sscanf(minstr, "%d", &x) == 1) && (x > 0)) mindur = x; } if (maxstr) { if ((sscanf(maxstr, "%d", &x) == 1) && (x > 0)) maxdur = x; } ast_log(LOG_DEBUG, "Preparing detect of fax (waitdur=%dms, sildur=%dms, mindur=%dms, maxdur=%dms)\n", waitdur, sildur, mindur, maxdur); // LOCAL_USER_ADD(u); // if (chan->_state != AST_STATE_UP && !skipanswer) { if (ast_channel_state(chan) != AST_STATE_UP && !skipanswer) { /* Otherwise answer unless we're supposed to send this while on-hook */ res = ast_answer(chan); } if (!res) { // origrformat = chan->readformat; origrformat = ast_channel_readformat(chan); // if ((res = ast_set_read_format(chan, AST_FORMAT_SLINEAR))) if ((res = ast_set_read_format_from_cap(chan, cap)) ){ ast_log(LOG_WARNING, "Unable to set read format to linear!\n"); } } if (!(dsp = ast_dsp_new())) { ast_log(LOG_WARNING, "Unable to allocate DSP!\n"); res = -1; } if (dsp) { if (!ignoretalk) ; /* features |= DSP_FEATURE_SILENCE_SUPPRESS; */ if (!ignorefax) features |= DSP_FEATURE_FAX_DETECT; //if (!ignoredtmf) features |= DSP_FEATURE_DIGIT_DETECT; ast_dsp_set_threshold(dsp, 256); ast_dsp_set_features(dsp, features | DSP_DIGITMODE_RELAXDTMF); ast_dsp_set_digitmode(dsp, DSP_DIGITMODE_DTMF); } if (!res) { if (waitdur > 0) timeout = time(NULL) + (time_t)waitdur; while(ast_waitfor(chan, -1) > -1) { if (waitdur > 0 && time(NULL) > timeout) { res = 0; break; } fr = ast_read(chan); if (!fr) { ast_log(LOG_DEBUG, "Got hangup\n"); res = -1; break; } fr2 = ast_dsp_process(chan, dsp, fr); if (!fr2) { ast_log(LOG_WARNING, "Bad DSP received (what happened?)\n"); fr2 = fr; } if (fr2->frametype == AST_FRAME_DTMF) { if (fr2->subclass.integer == 'f' && !ignorefax) { /* Fax tone -- Handle and return NULL */ ast_log(LOG_DEBUG, "Fax detected on %s\n", ast_channel_name(chan)); ast_log(LOG_DEBUG, "Fax detected on %s\n", ast_channel_name(chan)); if (strcmp(ast_channel_exten(chan), "fax")) { ast_log(LOG_NOTICE, "Redirecting %s to fax extension\n", ast_channel_name(chan)); pbx_builtin_setvar_helper(chan, "FAX_DETECTED", "1"); pbx_builtin_setvar_helper(chan,"FAXEXTEN",ast_channel_exten(chan)); if (ast_exists_extension(chan, ast_channel_context(chan), "fax", 1, ast_channel_caller(chan)->id.number.str)) { /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */ // strncpy(ast_channel_exten(chan), "fax", sizeof(ast_channel_exten(chan))-1); // chan->priority = 0; ast_channel_exten_set(chan, "fax"); ast_channel_priority_set(chan, 0); } else ast_log(LOG_WARNING, "Fax detected, but no fax extension\n"); } else ast_log(LOG_WARNING, "Already in a fax extension, not redirecting\n"); res = 0; ast_frfree(fr); break; } else if (!ignoredtmf) { ast_log(LOG_DEBUG, "DTMF detected on %s\n", ast_channel_name(chan)); char t[2]; t[0] = fr2->subclass.integer; t[1] = '\0'; if (noextneeded || ast_canmatch_extension(chan, ast_channel_context(chan), t, 1, ast_channel_caller(chan)->id.number.str)) { pbx_builtin_setvar_helper(chan, "DTMF_DETECTED", "1"); /* They entered a valid extension, or might be anyhow */ if (noextneeded) { ast_log(LOG_NOTICE, "DTMF received (not matching to exten)\n"); res = 0; } else { ast_log(LOG_NOTICE, "DTMF received (matching to exten)\n"); res = fr2->subclass.integer; } ast_frfree(fr); break; } else ast_log(LOG_DEBUG, "Valid extension requested and DTMF did not match\n"); } // } else if ((fr->frametype == AST_FRAME_VOICE) && (fr->subclass == AST_FORMAT_SLINEAR) && !ignoretalk) { } else if ((fr->frametype == AST_FRAME_VOICE) && ( ast_format_cap_iscompatible(cap, &fr->subclass.format)) && !ignoretalk) { int totalsilence; int ms; res = ast_dsp_silence(dsp, fr, &totalsilence); if (res && (totalsilence > sildur)) { /* We've been quiet a little while */ if (notsilent) { /* We had heard some talking */ gettimeofday(&end, NULL); ms = (end.tv_sec - start.tv_sec) * 1000; ms += (end.tv_usec - start.tv_usec) / 1000; ms -= sildur; if (ms < 0) ms = 0; if ((ms > mindur) && ((maxdur < 0) || (ms < maxdur))) { char ms_str[10]; ast_log(LOG_DEBUG, "Found qualified token of %d ms\n", ms); ast_log(LOG_NOTICE, "Redirecting %s to talk extension\n", ast_channel_name(chan)); /* Save detected talk time (in milliseconds) */ sprintf(ms_str, "%d", ms); pbx_builtin_setvar_helper(chan, "TALK_DETECTED", ms_str); if (ast_exists_extension(chan, ast_channel_context(chan), "talk", 1, ast_channel_caller(chan)->id.number.str)) { // strncpy(ast_channel_exten(chan), "talk", sizeof(ast_channel_exten(chan)) - 1); // chan->priority = 0; ast_channel_exten_set(chan, "talk"); ast_channel_priority_set(chan, 0); } else ast_log(LOG_WARNING, "Talk detected, but no talk extension\n"); res = 0; ast_frfree(fr); break; } else ast_log(LOG_DEBUG, "Found unqualified token of %d ms\n", ms); notsilent = 0; } } else { if (!notsilent) { /* Heard some audio, mark the begining of the token */ gettimeofday(&start, NULL); ast_log(LOG_DEBUG, "Start of voice token!\n"); notsilent = 1; } } } ast_frfree(fr); } } else ast_log(LOG_WARNING, "Could not answer channel '%s'\n", ast_channel_name(chan)); if (res > -1) { if (origrformat && ast_set_read_format(chan, origrformat)) { ast_log(LOG_WARNING, "Failed to restore read format for %s to %s\n", ast_channel_name(chan), ast_getformatname(origrformat)); } } if (dsp) ast_dsp_free(dsp); // LOCAL_USER_REMOVE(u); ast_format_cap_destroy(cap); return res; }
/*! \brief Unload the bridge interaction channel from Asterisk */ static int unload_module(void) { ast_channel_unregister(&bridge_tech); bridge_tech.capabilities = ast_format_cap_destroy(bridge_tech.capabilities); return 0; }
int ast_format_cap_has_joint(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2) { struct ao2_iterator it; struct ast_format *tmp; struct find_joint_data data = { .joint_found = 0, .joint_cap = NULL, }; it = ao2_iterator_init(cap1->formats, cap1->nolock ? AO2_ITERATOR_DONTLOCK : 0); while ((tmp = ao2_iterator_next(&it))) { data.format = tmp; ao2_callback(cap2->formats, OBJ_MULTIPLE | OBJ_NODATA | cap2->nolock, find_joint_cb, &data); ao2_ref(tmp, -1); } ao2_iterator_destroy(&it); return data.joint_found ? 1 : 0; } int ast_format_cap_identical(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2) { struct ao2_iterator it; struct ast_format *tmp; if (ao2_container_count(cap1->formats) != ao2_container_count(cap2->formats)) { return 0; /* if they are not the same size, they are not identical */ } it = ao2_iterator_init(cap1->formats, cap1->nolock ? AO2_ITERATOR_DONTLOCK : 0); while ((tmp = ao2_iterator_next(&it))) { if (!ast_format_cap_iscompatible(cap2, tmp)) { ao2_ref(tmp, -1); ao2_iterator_destroy(&it); return 0; } ao2_ref(tmp, -1); } ao2_iterator_destroy(&it); return 1; } struct ast_format_cap *ast_format_cap_joint(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2) { struct ao2_iterator it; struct ast_format_cap *result = ast_format_cap_alloc_nolock(); struct ast_format *tmp; struct find_joint_data data = { .joint_found = 0, .joint_cap = result, }; if (!result) { return NULL; } it = ao2_iterator_init(cap1->formats, cap1->nolock ? AO2_ITERATOR_DONTLOCK : 0); while ((tmp = ao2_iterator_next(&it))) { data.format = tmp; ao2_callback(cap2->formats, OBJ_MULTIPLE | OBJ_NODATA | cap2->nolock, find_joint_cb, &data); ao2_ref(tmp, -1); } ao2_iterator_destroy(&it); if (ao2_container_count(result->formats)) { return result; } result = ast_format_cap_destroy(result); return NULL; } static int joint_copy_helper(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2, struct ast_format_cap *result, int append) { struct ao2_iterator it; struct ast_format *tmp; struct find_joint_data data = { .joint_cap = result, .joint_found = 0, }; if (!append) { ast_format_cap_remove_all(result); } it = ao2_iterator_init(cap1->formats, cap1->nolock ? AO2_ITERATOR_DONTLOCK : 0); while ((tmp = ao2_iterator_next(&it))) { data.format = tmp; ao2_callback(cap2->formats, OBJ_MULTIPLE | OBJ_NODATA | cap2->nolock, find_joint_cb, &data); ao2_ref(tmp, -1); } ao2_iterator_destroy(&it); return ao2_container_count(result->formats) ? 1 : 0; } int ast_format_cap_joint_append(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2, struct ast_format_cap *result) { return joint_copy_helper(cap1, cap2, result, 1); } int ast_format_cap_joint_copy(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2, struct ast_format_cap *result) { return joint_copy_helper(cap1, cap2, result, 0); } struct ast_format_cap *ast_format_cap_get_type(const struct ast_format_cap *cap, enum ast_format_type ftype) { struct ao2_iterator it; struct ast_format_cap *result = ast_format_cap_alloc_nolock(); struct ast_format *tmp; if (!result) { return NULL; } /* for each format in cap1, see if that format is * compatible with cap2. If so copy it to the result */ it = ao2_iterator_init(cap->formats, cap->nolock ? AO2_ITERATOR_DONTLOCK : 0); while ((tmp = ao2_iterator_next(&it))) { if (AST_FORMAT_GET_TYPE(tmp->id) == ftype) { /* copy format */ ast_format_cap_add(result, tmp); } ao2_ref(tmp, -1); } ao2_iterator_destroy(&it); if (ao2_container_count(result->formats)) { return result; } result = ast_format_cap_destroy(result); return NULL; } int ast_format_cap_has_type(const struct ast_format_cap *cap, enum ast_format_type type) { struct ao2_iterator it; struct ast_format *tmp; it = ao2_iterator_init(cap->formats, cap->nolock ? AO2_ITERATOR_DONTLOCK : 0); while ((tmp = ao2_iterator_next(&it))) { if (AST_FORMAT_GET_TYPE(tmp->id) == type) { ao2_ref(tmp, -1); ao2_iterator_destroy(&it); return 1; } ao2_ref(tmp, -1); } ao2_iterator_destroy(&it); return 0; } void ast_format_cap_iter_start(struct ast_format_cap *cap) { if (!cap->nolock) { ao2_lock(cap->formats); } cap->it = ao2_iterator_init(cap->formats, cap->nolock ? AO2_ITERATOR_DONTLOCK : 0); } void ast_format_cap_iter_end(struct ast_format_cap *cap) { ao2_iterator_destroy(&cap->it); if (!cap->nolock) { ao2_unlock(cap->formats); } } int ast_format_cap_iter_next(struct ast_format_cap *cap, struct ast_format *format) { struct ast_format *tmp = ao2_iterator_next(&cap->it); if (!tmp) { return -1; } ast_format_copy(format, tmp); ao2_ref(tmp, -1); return 0; } char *ast_getformatname_multiple(char *buf, size_t size, struct ast_format_cap *cap) { int x; unsigned len; char *start, *end = buf; struct ast_format tmp_fmt; size_t f_len; const struct ast_format_list *f_list = ast_format_list_get(&f_len); if (!size) { f_list = ast_format_list_destroy(f_list); return buf; } snprintf(end, size, "("); len = strlen(end); end += len; size -= len; start = end; for (x = 0; x < f_len; x++) { ast_format_copy(&tmp_fmt, &f_list[x].format); if (ast_format_cap_iscompatible(cap, &tmp_fmt)) { snprintf(end, size, "%s|", f_list[x].name); len = strlen(end); end += len; size -= len; } } if (start == end) { ast_copy_string(start, "nothing)", size); } else if (size > 1) { *(end - 1) = ')'; } f_list = ast_format_list_destroy(f_list); return buf; } uint64_t ast_format_cap_to_old_bitfield(const struct ast_format_cap *cap) { uint64_t res = 0; struct ao2_iterator it; struct ast_format *tmp; it = ao2_iterator_init(cap->formats, cap->nolock ? AO2_ITERATOR_DONTLOCK : 0); while ((tmp = ao2_iterator_next(&it))) { res |= ast_format_to_old_bitfield(tmp); ao2_ref(tmp, -1); } ao2_iterator_destroy(&it); return res; }
static int func_channel_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len) { int ret = 0; char tmp[512]; struct ast_format_cap *tmpcap; if (!strcasecmp(data, "audionativeformat")) { if ((tmpcap = ast_format_cap_get_type(chan->nativeformats, AST_FORMAT_TYPE_AUDIO))) { ast_copy_string(buf, ast_getformatname_multiple(tmp, sizeof(tmp), tmpcap), len); tmpcap = ast_format_cap_destroy(tmpcap); } } else if (!strcasecmp(data, "videonativeformat")) { if ((tmpcap = ast_format_cap_get_type(chan->nativeformats, AST_FORMAT_TYPE_VIDEO))) { ast_copy_string(buf, ast_getformatname_multiple(tmp, sizeof(tmp), tmpcap), len); tmpcap = ast_format_cap_destroy(tmpcap); } } else if (!strcasecmp(data, "audioreadformat")) { ast_copy_string(buf, ast_getformatname(&chan->readformat), len); } else if (!strcasecmp(data, "audiowriteformat")) { ast_copy_string(buf, ast_getformatname(&chan->writeformat), len); #ifdef CHANNEL_TRACE } else if (!strcasecmp(data, "trace")) { ast_channel_lock(chan); ast_copy_string(buf, ast_channel_trace_is_enabled(chan) ? "1" : "0", len); ast_channel_unlock(chan); #endif } else if (!strcasecmp(data, "tonezone") && chan->zone) locked_copy_string(chan, buf, chan->zone->country, len); else if (!strcasecmp(data, "language")) locked_copy_string(chan, buf, chan->language, len); else if (!strcasecmp(data, "musicclass")) locked_copy_string(chan, buf, chan->musicclass, len); else if (!strcasecmp(data, "name")) { locked_copy_string(chan, buf, chan->name, len); } else if (!strcasecmp(data, "parkinglot")) locked_copy_string(chan, buf, chan->parkinglot, len); else if (!strcasecmp(data, "state")) locked_copy_string(chan, buf, ast_state2str(chan->_state), len); else if (!strcasecmp(data, "channeltype")) locked_copy_string(chan, buf, chan->tech->type, len); else if (!strcasecmp(data, "accountcode")) locked_copy_string(chan, buf, chan->accountcode, len); else if (!strcasecmp(data, "checkhangup")) { ast_channel_lock(chan); ast_copy_string(buf, ast_check_hangup(chan) ? "1" : "0", len); ast_channel_unlock(chan); } else if (!strcasecmp(data, "peeraccount")) locked_copy_string(chan, buf, chan->peeraccount, len); else if (!strcasecmp(data, "hangupsource")) locked_copy_string(chan, buf, chan->hangupsource, len); else if (!strcasecmp(data, "appname") && chan->appl) locked_copy_string(chan, buf, chan->appl, len); else if (!strcasecmp(data, "appdata") && chan->data) locked_copy_string(chan, buf, chan->data, len); else if (!strcasecmp(data, "exten") && chan->data) locked_copy_string(chan, buf, chan->exten, len); else if (!strcasecmp(data, "context") && chan->data) locked_copy_string(chan, buf, chan->context, len); else if (!strcasecmp(data, "userfield") && chan->data) locked_copy_string(chan, buf, chan->userfield, len); else if (!strcasecmp(data, "channame") && chan->data) locked_copy_string(chan, buf, chan->name, len); else if (!strcasecmp(data, "linkedid")) { ast_channel_lock(chan); if (ast_strlen_zero(chan->linkedid)) { /* fall back on the channel's uniqueid if linkedid is unset */ ast_copy_string(buf, chan->uniqueid, len); } else { ast_copy_string(buf, chan->linkedid, len); } ast_channel_unlock(chan); } else if (!strcasecmp(data, "peer")) { struct ast_channel *p; ast_channel_lock(chan); p = ast_bridged_channel(chan); if (p || chan->tech || chan->cdr) /* dummy channel? if so, we hid the peer name in the language */ ast_copy_string(buf, (p ? p->name : ""), len); else { /* a dummy channel can still pass along bridged peer info via the BRIDGEPEER variable */ const char *pname = pbx_builtin_getvar_helper(chan, "BRIDGEPEER"); if (!ast_strlen_zero(pname)) ast_copy_string(buf, pname, len); /* a horrible kludge, but... how else? */ else buf[0] = 0; } ast_channel_unlock(chan); } else if (!strcasecmp(data, "uniqueid")) { locked_copy_string(chan, buf, chan->uniqueid, len); } else if (!strcasecmp(data, "transfercapability")) { locked_copy_string(chan, buf, transfercapability_table[chan->transfercapability & 0x1f], len); } else if (!strcasecmp(data, "callgroup")) { char groupbuf[256]; locked_copy_string(chan, buf, ast_print_group(groupbuf, sizeof(groupbuf), chan->callgroup), len); } else if (!strcasecmp(data, "pickupgroup")) { char groupbuf[256]; locked_copy_string(chan, buf, ast_print_group(groupbuf, sizeof(groupbuf), chan->pickupgroup), len); } else if (!strcasecmp(data, "amaflags")) { char amabuf[256]; snprintf(amabuf,sizeof(amabuf), "%d", chan->amaflags); locked_copy_string(chan, buf, amabuf, len); } else if (!strncasecmp(data, "secure_bridge_", 14)) { struct ast_datastore *ds; 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 (!chan->tech || !chan->tech->func_channel_read || chan->tech->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 container_test1_helper(struct ast_format_cap *cap1, struct ast_format_cap *cap2, struct ast_test *test) { int res = AST_TEST_PASS; struct ast_format_cap *cap_joint = NULL; struct ast_format tmpformat; if (ast_format_attr_reg_interface(&test_interface)) { ast_test_status_update(test, "test_interface failed to register.\n"); ast_format_cap_destroy(cap1); ast_format_cap_destroy(cap2); return AST_TEST_FAIL; } ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_GSM, 0)); ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_ULAW, 0)); ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_G722, 0)); ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_ALAW, 0)); ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_H264, 0)); ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_H263, 0)); ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_T140, 0)); ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_JPEG, 0)); ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_TESTLAW, 1, TEST_ATTR_KEY_STRING, "testing caps hooray", TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ, TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_16KHZ, TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_32KHZ, AST_FORMAT_ATTR_END)); /* Test is compatible */ if (!ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_ALAW, 0)) || !ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_ULAW, 0)) || !ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_GSM, 0)) || !ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_H264, 0)) || !ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_JPEG, 0)) || !ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_T140, 0))) { ast_test_status_update(test, "ast cap1 failed to properly detect compatibility test 1.\n"); res = AST_TEST_FAIL; goto test3_cleanup; } /* Test things that are not compatible */ if (ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_SPEEX, 0)) || ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_SPEEX16, 0)) || ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_H261, 0))) { ast_test_status_update(test, "ast cap1 failed to properly detect compatibility test 2.\n"); res = AST_TEST_FAIL; goto test3_cleanup; } /* Test compatiblity with format with attributes. */ if (!ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_TESTLAW, 1, TEST_ATTR_KEY_STRING, "testing caps hooray", TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ, TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_16KHZ, AST_FORMAT_ATTR_END))) { ast_test_status_update(test, "ast cap1 failed to properly detect compatibility test 3.\n"); res = AST_TEST_FAIL; goto test3_cleanup; } if (!ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_TESTLAW, 1, TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ, AST_FORMAT_ATTR_END))) { ast_test_status_update(test, "ast cap1 failed to properly detect compatibility test 4.\n"); res = AST_TEST_FAIL; goto test3_cleanup; } if (ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_TESTLAW, 1, TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ, TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_48KHZ, /* 48khz was not compatible, so this should fail iscompatible check */ AST_FORMAT_ATTR_END))) { ast_test_status_update(test, "ast cap1 failed to properly detect compatibility test 5.\n"); res = AST_TEST_FAIL; goto test3_cleanup; } /* Lets start testing the functions that compare ast_format_cap objects. * Genreate the cap2 object to contain some similar formats as cap1 * and some different formats as well. */ ast_format_cap_add(cap2, ast_format_set(&tmpformat, AST_FORMAT_GSM, 0)); ast_format_cap_add(cap2, ast_format_set(&tmpformat, AST_FORMAT_ULAW, 0)); ast_format_cap_add(cap2, ast_format_set(&tmpformat, AST_FORMAT_SIREN7, 0)); ast_format_cap_add(cap2, ast_format_set(&tmpformat, AST_FORMAT_H261, 0)); ast_format_cap_add(cap2, ast_format_set(&tmpformat, AST_FORMAT_T140, 0)); ast_format_cap_add(cap2, ast_format_set(&tmpformat, AST_FORMAT_TESTLAW, 1, TEST_ATTR_KEY_STRING, "testing caps hooray", TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ, TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_12KHZ, TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_16KHZ, TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_32KHZ, TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_48KHZ, AST_FORMAT_ATTR_END)); /* find joint formats between cap1 and cap2 */ cap_joint = ast_format_cap_joint(cap1, cap2); if (!cap_joint) { ast_test_status_update(test, "failed to create joint capabilities correctly.\n"); res = AST_TEST_FAIL; goto test3_cleanup; } /* determine if cap_joint is what we think it should be */ if (!ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_GSM, 0)) || !ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_ULAW, 0)) || !ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_T140, 0)) || !ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_TESTLAW, 1, TEST_ATTR_KEY_STRING, "testing caps hooray", TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ, TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_16KHZ, AST_FORMAT_ATTR_END))) { ast_test_status_update(test, "ast cap_joint failed to properly detect compatibility test 1.\n"); res = AST_TEST_FAIL; goto test3_cleanup; } /* make sure joint cap does not have formats that should not be there */ if (ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_SIREN7, 0)) || ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_TESTLAW, 1, TEST_ATTR_KEY_STRING, "testing caps hooray", TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ, TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_16KHZ, TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_48KHZ, AST_FORMAT_ATTR_END))) { ast_test_status_update(test, "ast cap_joint failed to properly detect compatibility test 1.\n"); res = AST_TEST_FAIL; goto test3_cleanup; } /* Lets test removing a capability */ if (ast_format_cap_remove(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_T140, 0))) { ast_test_status_update(test, "ast_format_cap_remove failed. \n"); res = AST_TEST_FAIL; goto test3_cleanup; } /* Lets make sure what we just removed does not still exist */ if (ast_format_cap_iscompatible(cap_joint, &tmpformat)) { ast_test_status_update(test, "ast_format_cap_remove failed 2. \n"); res = AST_TEST_FAIL; goto test3_cleanup; } /* Lets test removing a capability by id.*/ if (ast_format_cap_remove_byid(cap_joint, AST_FORMAT_GSM)) { ast_test_status_update(test, "ast_format_cap_remove failed 3. \n"); res = AST_TEST_FAIL; goto test3_cleanup; } /* Lets make sure what we just removed does not still exist */ if (ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_GSM, 0))) { ast_test_status_update(test, "ast_format_cap_remove failed 4. \n"); res = AST_TEST_FAIL; goto test3_cleanup; } /* lets test getting joint formats by type */ ast_format_cap_destroy(cap_joint); if (!(cap_joint = ast_format_cap_get_type(cap1, AST_FORMAT_TYPE_VIDEO))) { ast_test_status_update(test, "ast_format_cap_get_type failed.\n"); res = AST_TEST_FAIL; goto test3_cleanup; } /* lets make sure our joint capability structure has what we expect */ if (!ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_H264, 0)) || !ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_H263, 0))) { ast_test_status_update(test, "get_type failed 2.\n"); res = AST_TEST_FAIL; goto test3_cleanup; } /* now make sure joint does not have anything but video */ if (ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_ALAW, 0)) || ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_ULAW, 0)) || ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_GSM, 0)) || ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_JPEG, 0)) || ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_T140, 0))) { ast_test_status_update(test, "get_type failed 3.\n"); res = AST_TEST_FAIL; goto test3_cleanup; } /* now lets remove everythign from cap_joint */ ast_format_cap_remove_all(cap_joint); if (!ast_format_cap_is_empty(cap_joint)) { ast_test_status_update(test, "failed to remove all\n"); res = AST_TEST_FAIL; goto test3_cleanup; } /* now lets add all by type */ ast_format_cap_add_all_by_type(cap_joint, AST_FORMAT_TYPE_AUDIO); if (ast_format_cap_is_empty(cap_joint)) { ast_test_status_update(test, "failed to add all by type AUDIO\n"); res = AST_TEST_FAIL; } ast_format_cap_iter_start(cap_joint); while (!(ast_format_cap_iter_next(cap_joint, &tmpformat))) { if (AST_FORMAT_GET_TYPE(tmpformat.id) != AST_FORMAT_TYPE_AUDIO) { ast_test_status_update(test, "failed to add all by type AUDIO\n"); res = AST_TEST_FAIL; ast_format_cap_iter_end(cap_joint); goto test3_cleanup; } } ast_format_cap_iter_end(cap_joint); /* test append */ ast_format_cap_append(cap_joint, cap1); ast_format_cap_iter_start(cap1); while (!(ast_format_cap_iter_next(cap1, &tmpformat))) { if (!ast_format_cap_iscompatible(cap_joint, &tmpformat)) { ast_test_status_update(test, "failed to append format capabilities.\n"); res = AST_TEST_FAIL; ast_format_cap_iter_end(cap1); goto test3_cleanup; } } ast_format_cap_iter_end(cap1); /* test copy */ cap1 = ast_format_cap_destroy(cap1); cap1 = ast_format_cap_dup(cap_joint); if (!ast_format_cap_identical(cap_joint, cap1)) { ast_test_status_update(test, "failed to copy capabilities\n"); res = AST_TEST_FAIL; goto test3_cleanup; } /* test remove by type */ ast_format_cap_remove_bytype(cap_joint, AST_FORMAT_TYPE_AUDIO); if (ast_format_cap_has_type(cap_joint, AST_FORMAT_TYPE_AUDIO)) { ast_test_status_update(test, "failed to remove all by type audio\n"); res = AST_TEST_FAIL; goto test3_cleanup; } if (!ast_format_cap_has_type(cap_joint, AST_FORMAT_TYPE_TEXT)) { /* it should still have text */ ast_test_status_update(test, "failed to remove all by type audio\n"); res = AST_TEST_FAIL; goto test3_cleanup; } ast_format_cap_iter_start(cap_joint); while (!(ast_format_cap_iter_next(cap_joint, &tmpformat))) { if (AST_FORMAT_GET_TYPE(tmpformat.id) == AST_FORMAT_TYPE_AUDIO) { ast_test_status_update(test, "failed to remove all by type audio\n"); res = AST_TEST_FAIL; ast_format_cap_iter_end(cap_joint); goto test3_cleanup; } } ast_format_cap_iter_end(cap_joint); /* test add all */ ast_format_cap_remove_all(cap_joint); ast_format_cap_add_all(cap_joint); { int video = 0, audio = 0, text = 0, image = 0; ast_format_cap_iter_start(cap_joint); while (!(ast_format_cap_iter_next(cap_joint, &tmpformat))) { switch (AST_FORMAT_GET_TYPE(tmpformat.id)) { case AST_FORMAT_TYPE_AUDIO: audio++; break; case AST_FORMAT_TYPE_VIDEO: video++; break; case AST_FORMAT_TYPE_TEXT: text++; break; case AST_FORMAT_TYPE_IMAGE: image++; break; } } ast_format_cap_iter_end(cap_joint); if (!video || !audio || !text || !image) { ast_test_status_update(test, "failed to add all\n"); res = AST_TEST_FAIL; goto test3_cleanup; } } /* test copy2 */ ast_format_cap_copy(cap2, cap_joint); if (!ast_format_cap_identical(cap2, cap_joint)) { ast_test_status_update(test, "ast_format_cap_copy failed\n"); res = AST_TEST_FAIL; goto test3_cleanup; } test3_cleanup: ast_format_cap_destroy(cap1); ast_format_cap_destroy(cap2); ast_format_cap_destroy(cap_joint); /* unregister interface */ if (ast_format_attr_unreg_interface(&test_interface)) { ast_test_status_update(test, "test_interface failed to unregister.\n"); res = AST_TEST_FAIL; } return res; }
static int unload_module(void) { ast_format_cap_destroy(simple_bridge.format_capabilities); return ast_bridge_technology_unregister(&simple_bridge); }
void ast_unreal_destructor(void *vdoomed) { struct ast_unreal_pvt *doomed = vdoomed; doomed->reqcap = ast_format_cap_destroy(doomed->reqcap); }
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")) { char tmp[512]; if ((tmpcap = ast_format_cap_get_type(ast_channel_nativeformats(chan), AST_FORMAT_TYPE_AUDIO))) { ast_copy_string(buf, ast_getformatname_multiple(tmp, sizeof(tmp), tmpcap), len); tmpcap = ast_format_cap_destroy(tmpcap); } } else if (!strcasecmp(data, "videonativeformat")) { char tmp[512]; if ((tmpcap = ast_format_cap_get_type(ast_channel_nativeformats(chan), AST_FORMAT_TYPE_VIDEO))) { ast_copy_string(buf, ast_getformatname_multiple(tmp, sizeof(tmp), tmpcap), len); tmpcap = ast_format_cap_destroy(tmpcap); } } else if (!strcasecmp(data, "audioreadformat")) { ast_copy_string(buf, ast_getformatname(ast_channel_readformat(chan)), len); } else if (!strcasecmp(data, "audiowriteformat")) { ast_copy_string(buf, ast_getformatname(ast_channel_writeformat(chan)), len); #ifdef CHANNEL_TRACE } else if (!strcasecmp(data, "trace")) { ast_channel_lock(chan); ast_copy_string(buf, ast_channel_trace_is_enabled(chan) ? "1" : "0", len); ast_channel_unlock(chan); #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, "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")) { ast_channel_lock(chan); ast_copy_string(buf, ast_check_hangup(chan) ? "1" : "0", len); ast_channel_unlock(chan); } 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")) { RAII_VAR(struct ast_channel *, p, NULL, ast_channel_cleanup); ast_channel_lock(chan); p = ast_channel_bridge_peer(chan); if (p || ast_channel_tech(chan)) /* dummy channel? if so, we hid the peer name in the language */ ast_copy_string(buf, (p ? ast_channel_name(p) : ""), len); else { /* a dummy channel can still pass along bridged peer info via the BRIDGEPEER variable */ const char *pname = pbx_builtin_getvar_helper(chan, "BRIDGEPEER"); if (!ast_strlen_zero(pname)) ast_copy_string(buf, pname, len); /* a horrible kludge, but... how else? */ else buf[0] = 0; } 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, "%d", ast_channel_amaflags(chan)); ast_channel_unlock(chan); } else if (!strncasecmp(data, "secure_bridge_", 14)) { struct ast_datastore *ds; 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 (!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; }