static int chanavail_exec(struct ast_channel *chan, const char *data) { int inuse=-1, option_state=0, string_compare=0, option_all_avail=0; int status; char *info, tmp[512], trychan[512], *peers, *tech, *number, *rest, *cur; struct ast_str *tmp_availchan = ast_str_alloca(2048); struct ast_str *tmp_availorig = ast_str_alloca(2048); struct ast_str *tmp_availstat = ast_str_alloca(2048); struct ast_str *tmp_availcause = ast_str_alloca(2048); struct ast_channel *tempchan; AST_DECLARE_APP_ARGS(args, AST_APP_ARG(reqchans); AST_APP_ARG(options); );
static int add_ipv4_ie(struct ast_event **event, enum ast_event_ie_type ie_type, const struct ast_security_event_ipv4_addr *addr) { struct ast_str *str = ast_str_alloca(64); ast_str_set(&str, 0, "IPV4/"); switch (addr->transport) { case AST_SECURITY_EVENT_TRANSPORT_UDP: ast_str_append(&str, 0, "UDP/"); break; case AST_SECURITY_EVENT_TRANSPORT_TCP: ast_str_append(&str, 0, "TCP/"); break; case AST_SECURITY_EVENT_TRANSPORT_TLS: ast_str_append(&str, 0, "TLS/"); break; } ast_str_append(&str, 0, "%s/%hu", ast_inet_ntoa(addr->sin->sin_addr), ntohs(addr->sin->sin_port)); return ast_event_append_ie_str(event, ie_type, ast_str_buffer(str)); }
static struct ast_event *alloc_event(const struct ast_security_event_common *sec) { struct ast_str *str = ast_str_alloca(TIMESTAMP_STR_LEN); struct timeval tv = ast_tvnow(); const char *severity_str; if (check_event_type(sec->event_type)) { return NULL; } encode_timestamp(&str, &tv); severity_str = S_OR( ast_security_event_severity_get_name(sec_events[sec->event_type].severity), "Unknown" ); return ast_event_new(AST_EVENT_SECURITY, AST_EVENT_IE_SECURITY_EVENT, AST_EVENT_IE_PLTYPE_UINT, sec->event_type, AST_EVENT_IE_EVENT_VERSION, AST_EVENT_IE_PLTYPE_UINT, sec->version, AST_EVENT_IE_EVENT_TV, AST_EVENT_IE_PLTYPE_STR, ast_str_buffer(str), AST_EVENT_IE_SERVICE, AST_EVENT_IE_PLTYPE_STR, sec->service, AST_EVENT_IE_SEVERITY, AST_EVENT_IE_PLTYPE_STR, severity_str, AST_EVENT_IE_END); }
static int sendtext_exec(struct ast_channel *chan, const char *data) { char *status = "UNSUPPORTED"; struct ast_str *str; /* NOT ast_strlen_zero, because some protocols (e.g. SIP) MUST be able to * send a zero-length message. */ if (!data) { ast_log(LOG_WARNING, "SendText requires an argument (text)\n"); return -1; } if (!(str = ast_str_alloca(strlen(data) + 1))) { return -1; } ast_str_get_encoded_str(&str, -1, data); ast_channel_lock(chan); if (!chan->tech->send_text) { ast_channel_unlock(chan); /* Does not support transport */ pbx_builtin_setvar_helper(chan, "SENDTEXTSTATUS", status); return 0; } status = "FAILURE"; if (!ast_sendtext(chan, ast_str_buffer(str))) { status = "SUCCESS"; } ast_channel_unlock(chan); pbx_builtin_setvar_helper(chan, "SENDTEXTSTATUS", status); return 0; }
/*! * \brief Ensure that a nonce on an incoming request is sane. * * The nonce in an incoming Authorization header needs to pass some scrutiny in order * for us to consider accepting it. What we do is re-build a nonce based on request * data and a realm and see if it matches the nonce they sent us. * \param candidate The nonce on an incoming request * \param rdata The incoming request * \param auth The auth credentials we are trying to match against. * \retval 0 Nonce does not pass validity checks * \retval 1 Nonce passes validity check */ static int check_nonce(const char *candidate, const pjsip_rx_data *rdata, const struct ast_sip_auth *auth) { char *copy = ast_strdupa(candidate); char *timestamp = strsep(©, "/"); int timestamp_int; time_t now = time(NULL); struct ast_str *calculated = ast_str_alloca(64); if (!copy) { /* Clearly a bad nonce! */ return 0; } if (sscanf(timestamp, "%30d", ×tamp_int) != 1) { return 0; } if ((int) now - timestamp_int > auth->nonce_lifetime) { return 0; } build_nonce(&calculated, timestamp, rdata, auth->realm); ast_debug(3, "Calculated nonce %s. Actual nonce is %s\n", ast_str_buffer(calculated), candidate); if (strcmp(ast_str_buffer(calculated), candidate)) { return 0; } return 1; }
static enum ast_test_result_state test_2way_function(struct ast_test *test, struct ast_channel *c, const char *encode1, const char *encode2, const char *decode1, const char *decode2) { struct ast_str *str = ast_str_create(16), *expression = ast_str_alloca(120); int okay; ast_str_set(&expression, 0, "%s%s%s", encode1, "foobarbaz", encode2); ast_str_substitute_variables(&str, 0, c, ast_str_buffer(expression)); ast_str_set(&expression, 0, "%s%s%s", decode1, ast_str_buffer(str), decode2); ast_str_substitute_variables(&str, 0, c, ast_str_buffer(expression)); okay = !strcmp(ast_str_buffer(str), "foobarbaz"); ast_test_status_update(test, "Testing '%s%s' and '%s%s' . . . . . %s\n", encode1, encode2, decode1, decode2, okay ? "passed" : "FAILED"); if (!okay) { ast_test_status_update(test, " '%s' != 'foobarbaz'\n", ast_str_buffer(str)); } ast_free(str); return okay ? AST_TEST_PASS : AST_TEST_FAIL; }
static void ast_eivr_getvariable(struct ast_channel *chan, char *data, char *outbuf, int outbuflen) { /* original input data: "G,var1,var2," */ /* data passed as "data": "var1,var2" */ char *inbuf, *variable; const char *value; int j; struct ast_str *newstring = ast_str_alloca(outbuflen); outbuf[0] = '\0'; for (j = 1, inbuf = data; ; j++) { variable = strsep(&inbuf, ","); if (variable == NULL) { int outstrlen = strlen(outbuf); if (outstrlen && outbuf[outstrlen - 1] == ',') { outbuf[outstrlen - 1] = 0; } break; } ast_channel_lock(chan); if (!(value = pbx_builtin_getvar_helper(chan, variable))) { value = ""; } ast_str_append(&newstring, 0, "%s=%s,", variable, value); ast_channel_unlock(chan); ast_copy_string(outbuf, ast_str_buffer(newstring), outbuflen); } }
static int add_timeval_ie(struct ast_event **event, enum ast_event_ie_type ie_type, const struct timeval *tv) { struct ast_str *str = ast_str_alloca(TIMESTAMP_STR_LEN); encode_timestamp(&str, tv); return ast_event_append_ie_str(event, ie_type, ast_str_buffer(str)); }
/*! * \brief Calculate a nonce * * We use this in order to create authentication challenges. We also use this in order * to verify that an incoming request with credentials could be in response to one * of our challenges. * * The nonce is calculated from a timestamp, the source IP address, the source port, a * unique ID for us, and the realm. This helps to ensure that the incoming request * is from the same source that the nonce was calculated for. Including the realm * ensures that multiple challenges to the same request have different nonces. * * \param A UNIX timestamp expressed as a string * \param rdata The incoming request * \param realm The realm for which authentication should occur */ static int build_nonce(struct ast_str **nonce, const char *timestamp, const pjsip_rx_data *rdata, const char *realm) { struct ast_str *str = ast_str_alloca(256); RAII_VAR(char *, eid, ao2_global_obj_ref(entity_id), ao2_cleanup); char hash[32]; ast_str_append(&str, 0, "%s", timestamp); ast_str_append(&str, 0, ":%s", rdata->pkt_info.src_name); ast_str_append(&str, 0, ":%d", rdata->pkt_info.src_port); ast_str_append(&str, 0, ":%s", eid); ast_str_append(&str, 0, ":%s", realm); ast_md5_hash(hash, ast_str_buffer(str)); ast_str_append(nonce, 0, "%s/%s", timestamp, hash); return 0; }
/*! * \brief astobj2 callback for adding digest challenges to responses * * \param realm An auth's realm to build a challenge from * \param tdata The response to add the challenge to * \param rdata The request the challenge is in response to * \param is_stale Indicates whether nonce on incoming request was stale */ static void challenge(const char *realm, pjsip_tx_data *tdata, const pjsip_rx_data *rdata, int is_stale) { pj_str_t qop; pj_str_t pj_nonce; pjsip_auth_srv auth_server; struct ast_str *nonce = ast_str_alloca(256); char time_buf[32]; time_t timestamp = time(NULL); snprintf(time_buf, sizeof(time_buf), "%d", (int) timestamp); build_nonce(&nonce, time_buf, rdata, realm); setup_auth_srv(tdata->pool, &auth_server, realm); pj_cstr(&pj_nonce, ast_str_buffer(nonce)); pj_cstr(&qop, "auth"); pjsip_auth_srv_challenge(&auth_server, &qop, &pj_nonce, NULL, is_stale ? PJ_TRUE : PJ_FALSE, tdata); }
struct ast_json *ast_json_ipaddr(const struct ast_sockaddr *addr, enum ast_transport transport_type) { struct ast_str *string = ast_str_alloca(64); if (!string) { return NULL; } ast_str_set(&string, 0, (ast_sockaddr_is_ipv4(addr) || ast_sockaddr_is_ipv4_mapped(addr)) ? "IPV4/" : "IPV6/"); if (transport_type) { char *transport_string = NULL; /* NOTE: None will be applied if multiple transport types are specified in transport_type */ switch(transport_type) { case AST_TRANSPORT_UDP: transport_string = "UDP"; break; case AST_TRANSPORT_TCP: transport_string = "TCP"; break; case AST_TRANSPORT_TLS: transport_string = "TLS"; break; case AST_TRANSPORT_WS: transport_string = "WS"; break; case AST_TRANSPORT_WSS: transport_string = "WSS"; break; } if (transport_string) { ast_str_append(&string, 0, "%s/", transport_string); } } ast_str_append(&string, 0, "%s", ast_sockaddr_stringify_addr(addr)); ast_str_append(&string, 0, "/%s", ast_sockaddr_stringify_port(addr)); return ast_json_string_create(ast_str_buffer(string)); }
static pjmedia_sdp_attr* generate_fmtp_attr(pj_pool_t *pool, struct ast_format *format, int rtp_code) { struct ast_str *fmtp0 = ast_str_alloca(256); pj_str_t fmtp1; pjmedia_sdp_attr *attr = NULL; char *tmp; ast_format_generate_sdp_fmtp(format, rtp_code, &fmtp0); if (ast_str_strlen(fmtp0)) { tmp = ast_str_buffer(fmtp0) + ast_str_strlen(fmtp0) - 1; /* remove any carriage return line feeds */ while (*tmp == '\r' || *tmp == '\n') --tmp; *++tmp = '\0'; /* ast...generate gives us everything, just need value */ tmp = strchr(ast_str_buffer(fmtp0), ':'); if (tmp && tmp + 1) { fmtp1 = pj_str(tmp + 1); } else { fmtp1 = pj_str(ast_str_buffer(fmtp0)); } attr = pjmedia_sdp_attr_create(pool, "fmtp", &fmtp1); } return attr; }
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 u_char *ast_var_channels_table(struct variable *vp, oid *name, size_t *length, int exact, size_t *var_len, WriteMethod **write_method) { static unsigned long long_ret; static u_char bits_ret[2]; static char string_ret[256]; struct ast_channel *chan, *bridge; struct timeval tval; u_char *ret = NULL; int i, bit; struct ast_str *out = ast_str_alloca(2048); struct ast_channel_iterator *iter; if (header_simple_table(vp, name, length, exact, var_len, write_method, ast_active_channels())) return NULL; i = name[*length - 1] - 1; if (!(iter = ast_channel_iterator_all_new())) { return NULL; } while ((chan = ast_channel_iterator_next(iter)) && i) { ast_channel_unref(chan); i--; } iter = ast_channel_iterator_destroy(iter); if (chan == NULL) { return NULL; } *var_len = sizeof(long_ret); ast_channel_lock(chan); switch (vp->magic) { case ASTCHANINDEX: long_ret = name[*length - 1]; ret = (u_char *)&long_ret; break; case ASTCHANNAME: if (!ast_strlen_zero(ast_channel_name(chan))) { ast_copy_string(string_ret, ast_channel_name(chan), sizeof(string_ret)); *var_len = strlen(string_ret); ret = (u_char *)string_ret; } break; case ASTCHANLANGUAGE: if (!ast_strlen_zero(ast_channel_language(chan))) { ast_copy_string(string_ret, ast_channel_language(chan), sizeof(string_ret)); *var_len = strlen(string_ret); ret = (u_char *)string_ret; } break; case ASTCHANTYPE: ast_copy_string(string_ret, ast_channel_tech(chan)->type, sizeof(string_ret)); *var_len = strlen(string_ret); ret = (u_char *)string_ret; break; case ASTCHANMUSICCLASS: if (!ast_strlen_zero(ast_channel_musicclass(chan))) { ast_copy_string(string_ret, ast_channel_musicclass(chan), sizeof(string_ret)); *var_len = strlen(string_ret); ret = (u_char *)string_ret; } break; case ASTCHANBRIDGE: if ((bridge = ast_bridged_channel(chan)) != NULL) { ast_copy_string(string_ret, ast_channel_name(bridge), sizeof(string_ret)); *var_len = strlen(string_ret); ret = (u_char *)string_ret; } break; case ASTCHANMASQ: if (ast_channel_masq(chan) && !ast_strlen_zero(ast_channel_name(ast_channel_masq(chan)))) { ast_copy_string(string_ret, ast_channel_name(ast_channel_masq(chan)), sizeof(string_ret)); *var_len = strlen(string_ret); ret = (u_char *)string_ret; } break; case ASTCHANMASQR: if (ast_channel_masqr(chan) && !ast_strlen_zero(ast_channel_name(ast_channel_masqr(chan)))) { ast_copy_string(string_ret, ast_channel_name(ast_channel_masqr(chan)), sizeof(string_ret)); *var_len = strlen(string_ret); ret = (u_char *)string_ret; } break; case ASTCHANWHENHANGUP: if (!ast_tvzero(*ast_channel_whentohangup(chan))) { gettimeofday(&tval, NULL); long_ret = difftime(ast_channel_whentohangup(chan)->tv_sec, tval.tv_sec) * 100 - tval.tv_usec / 10000; ret= (u_char *)&long_ret; } break; case ASTCHANAPP: if (ast_channel_appl(chan)) { ast_copy_string(string_ret, ast_channel_appl(chan), sizeof(string_ret)); *var_len = strlen(string_ret); ret = (u_char *)string_ret; } break; case ASTCHANDATA: if (ast_channel_data(chan)) { ast_copy_string(string_ret, ast_channel_data(chan), sizeof(string_ret)); *var_len = strlen(string_ret); ret = (u_char *)string_ret; } break; case ASTCHANCONTEXT: ast_copy_string(string_ret, ast_channel_context(chan), sizeof(string_ret)); *var_len = strlen(string_ret); ret = (u_char *)string_ret; break; case ASTCHANMACROCONTEXT: ast_copy_string(string_ret, ast_channel_macrocontext(chan), sizeof(string_ret)); *var_len = strlen(string_ret); ret = (u_char *)string_ret; break; case ASTCHANMACROEXTEN: ast_copy_string(string_ret, ast_channel_macroexten(chan), sizeof(string_ret)); *var_len = strlen(string_ret); ret = (u_char *)string_ret; break; case ASTCHANMACROPRI: long_ret = ast_channel_macropriority(chan); ret = (u_char *)&long_ret; break; case ASTCHANEXTEN: ast_copy_string(string_ret, ast_channel_exten(chan), sizeof(string_ret)); *var_len = strlen(string_ret); ret = (u_char *)string_ret; break; case ASTCHANPRI: long_ret = ast_channel_priority(chan); ret = (u_char *)&long_ret; break; case ASTCHANACCOUNTCODE: if (!ast_strlen_zero(ast_channel_accountcode(chan))) { ast_copy_string(string_ret, ast_channel_accountcode(chan), sizeof(string_ret)); *var_len = strlen(string_ret); ret = (u_char *)string_ret; } break; case ASTCHANFORWARDTO: if (!ast_strlen_zero(ast_channel_call_forward(chan))) { ast_copy_string(string_ret, ast_channel_call_forward(chan), sizeof(string_ret)); *var_len = strlen(string_ret); ret = (u_char *)string_ret; } break; case ASTCHANUNIQUEID: ast_copy_string(string_ret, ast_channel_uniqueid(chan), sizeof(string_ret)); *var_len = strlen(string_ret); ret = (u_char *)string_ret; break; case ASTCHANCALLGROUP: long_ret = ast_channel_callgroup(chan); ret = (u_char *)&long_ret; break; case ASTCHANPICKUPGROUP: long_ret = ast_channel_pickupgroup(chan); ret = (u_char *)&long_ret; break; case ASTCHANSTATE: long_ret = ast_channel_state(chan) & 0xffff; ret = (u_char *)&long_ret; break; case ASTCHANMUTED: long_ret = ast_channel_state(chan) & AST_STATE_MUTE ? 1 : 2; ret = (u_char *)&long_ret; break; case ASTCHANRINGS: long_ret = ast_channel_rings(chan); ret = (u_char *)&long_ret; break; case ASTCHANCIDDNID: if (ast_channel_dialed(chan)->number.str) { ast_copy_string(string_ret, ast_channel_dialed(chan)->number.str, sizeof(string_ret)); *var_len = strlen(string_ret); ret = (u_char *)string_ret; } break; case ASTCHANCIDNUM: if (ast_channel_caller(chan)->id.number.valid && ast_channel_caller(chan)->id.number.str) { ast_copy_string(string_ret, ast_channel_caller(chan)->id.number.str, sizeof(string_ret)); *var_len = strlen(string_ret); ret = (u_char *)string_ret; } break; case ASTCHANCIDNAME: if (ast_channel_caller(chan)->id.name.valid && ast_channel_caller(chan)->id.name.str) { ast_copy_string(string_ret, ast_channel_caller(chan)->id.name.str, sizeof(string_ret)); *var_len = strlen(string_ret); ret = (u_char *)string_ret; } break; case ASTCHANCIDANI: if (ast_channel_caller(chan)->ani.number.valid && ast_channel_caller(chan)->ani.number.str) { ast_copy_string(string_ret, ast_channel_caller(chan)->ani.number.str, sizeof(string_ret)); *var_len = strlen(string_ret); ret = (u_char *)string_ret; } break; case ASTCHANCIDRDNIS: if (ast_channel_redirecting(chan)->from.number.valid && ast_channel_redirecting(chan)->from.number.str) { ast_copy_string(string_ret, ast_channel_redirecting(chan)->from.number.str, sizeof(string_ret)); *var_len = strlen(string_ret); ret = (u_char *)string_ret; } break; case ASTCHANCIDPRES: long_ret = ast_party_id_presentation(&ast_channel_caller(chan)->id); ret = (u_char *)&long_ret; break; case ASTCHANCIDANI2: long_ret = ast_channel_caller(chan)->ani2; ret = (u_char *)&long_ret; break; case ASTCHANCIDTON: long_ret = ast_channel_caller(chan)->id.number.plan; ret = (u_char *)&long_ret; break; case ASTCHANCIDTNS: long_ret = ast_channel_dialed(chan)->transit_network_select; ret = (u_char *)&long_ret; break; case ASTCHANAMAFLAGS: long_ret = ast_channel_amaflags(chan); ret = (u_char *)&long_ret; break; case ASTCHANADSI: long_ret = ast_channel_adsicpe(chan); ret = (u_char *)&long_ret; break; case ASTCHANTONEZONE: if (ast_channel_zone(chan)) { ast_copy_string(string_ret, ast_channel_zone(chan)->country, sizeof(string_ret)); *var_len = strlen(string_ret); ret = (u_char *)string_ret; } break; case ASTCHANHANGUPCAUSE: long_ret = ast_channel_hangupcause(chan); ret = (u_char *)&long_ret; break; case ASTCHANVARIABLES: if (pbx_builtin_serialize_variables(chan, &out)) { *var_len = ast_str_strlen(out); ret = (u_char *)ast_str_buffer(out); } break; case ASTCHANFLAGS: bits_ret[0] = 0; for (bit = 0; bit < 8; bit++) bits_ret[0] |= ((ast_channel_flags(chan)->flags & (1 << bit)) >> bit) << (7 - bit); bits_ret[1] = 0; for (bit = 0; bit < 8; bit++) bits_ret[1] |= (((ast_channel_flags(chan)->flags >> 8) & (1 << bit)) >> bit) << (7 - bit); *var_len = 2; ret = bits_ret; break; case ASTCHANTRANSFERCAP: long_ret = ast_channel_transfercapability(chan); ret = (u_char *)&long_ret; default: break; } ast_channel_unlock(chan); chan = ast_channel_unref(chan); return ret; }
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; }
static int serialize_showchan(struct ast_channel *c, char *buf, size_t size) { long elapsed_seconds = 0; int hour = 0, min = 0, sec = 0; struct ast_str *format_buf = ast_str_alloca(64); char cgrp[256]; char pgrp[256]; struct ast_str *write_transpath = ast_str_alloca(256); struct ast_str *read_transpath = ast_str_alloca(256); struct ast_bridge *bridge; memset(buf, 0, size); if (!c) return 0; elapsed_seconds = ast_channel_get_duration(c); hour = elapsed_seconds / 3600; min = (elapsed_seconds % 3600) / 60; sec = elapsed_seconds % 60; ast_channel_lock(c); bridge = ast_channel_get_bridge(c); ast_channel_unlock(c); snprintf(buf,size, "Name= %s\n" "Type= %s\n" "UniqueID= %s\n" "LinkedID= %s\n" "CallerIDNum= %s\n" "CallerIDName= %s\n" "ConnectedLineIDNum= %s\n" "ConnectedLineIDName=%s\n" "DNIDDigits= %s\n" "RDNIS= %s\n" "Parkinglot= %s\n" "Language= %s\n" "State= %s (%u)\n" "Rings= %d\n" "NativeFormat= %s\n" "WriteFormat= %s\n" "ReadFormat= %s\n" "RawWriteFormat= %s\n" "RawReadFormat= %s\n" "WriteTranscode= %s %s\n" "ReadTranscode= %s %s\n" "1stFileDescriptor= %d\n" "Framesin= %u %s\n" "Framesout= %u %s\n" "TimetoHangup= %ld\n" "ElapsedTime= %dh%dm%ds\n" "BridgeID= %s\n" "Context= %s\n" "Extension= %s\n" "Priority= %d\n" "CallGroup= %s\n" "PickupGroup= %s\n" "Application= %s\n" "Data= %s\n" "Blocking_in= %s\n", ast_channel_name(c), ast_channel_tech(c)->type, ast_channel_uniqueid(c), ast_channel_linkedid(c), S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, "(N/A)"), S_COR(ast_channel_caller(c)->id.name.valid, ast_channel_caller(c)->id.name.str, "(N/A)"), S_COR(ast_channel_connected(c)->id.number.valid, ast_channel_connected(c)->id.number.str, "(N/A)"), S_COR(ast_channel_connected(c)->id.name.valid, ast_channel_connected(c)->id.name.str, "(N/A)"), S_OR(ast_channel_dialed(c)->number.str, "(N/A)"), S_COR(ast_channel_redirecting(c)->from.number.valid, ast_channel_redirecting(c)->from.number.str, "(N/A)"), ast_channel_parkinglot(c), ast_channel_language(c), ast_state2str(ast_channel_state(c)), ast_channel_state(c), ast_channel_rings(c), ast_format_cap_get_names(ast_channel_nativeformats(c), &format_buf), ast_format_get_name(ast_channel_writeformat(c)), ast_format_get_name(ast_channel_readformat(c)), ast_format_get_name(ast_channel_rawwriteformat(c)), ast_format_get_name(ast_channel_rawreadformat(c)), ast_channel_writetrans(c) ? "Yes" : "No", ast_translate_path_to_str(ast_channel_writetrans(c), &write_transpath), ast_channel_readtrans(c) ? "Yes" : "No", ast_translate_path_to_str(ast_channel_readtrans(c), &read_transpath), ast_channel_fd(c, 0), ast_channel_fin(c) & ~DEBUGCHAN_FLAG, (ast_channel_fin(c) & DEBUGCHAN_FLAG) ? " (DEBUGGED)" : "", ast_channel_fout(c) & ~DEBUGCHAN_FLAG, (ast_channel_fout(c) & DEBUGCHAN_FLAG) ? " (DEBUGGED)" : "", (long)ast_channel_whentohangup(c)->tv_sec, hour, min, sec, bridge ? bridge->uniqueid : "(Not bridged)", ast_channel_context(c), ast_channel_exten(c), ast_channel_priority(c), ast_print_group(cgrp, sizeof(cgrp), ast_channel_callgroup(c)), ast_print_group(pgrp, sizeof(pgrp), ast_channel_pickupgroup(c)), ast_channel_appl(c) ? ast_channel_appl(c) : "(N/A)", ast_channel_data(c) ? S_OR(ast_channel_data(c), "(Empty)") : "(None)", (ast_test_flag(ast_channel_flags(c), AST_FLAG_BLOCKING) ? ast_channel_blockproc(c) : "(Not Blocking)")); ao2_cleanup(bridge); 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; }
static int serialize_showchan(struct ast_channel *c, char *buf, size_t size) { struct timeval now; long elapsed_seconds = 0; int hour = 0, min = 0, sec = 0; char nf[256]; char cgrp[256]; char pgrp[256]; struct ast_str *write_transpath = ast_str_alloca(256); struct ast_str *read_transpath = ast_str_alloca(256); now = ast_tvnow(); memset(buf, 0, size); if (!c) return 0; if (c->cdr) { elapsed_seconds = now.tv_sec - c->cdr->start.tv_sec; hour = elapsed_seconds / 3600; min = (elapsed_seconds % 3600) / 60; sec = elapsed_seconds % 60; } snprintf(buf,size, "Name= %s\n" "Type= %s\n" "UniqueID= %s\n" "LinkedID= %s\n" "CallerIDNum= %s\n" "CallerIDName= %s\n" "ConnectedLineIDNum= %s\n" "ConnectedLineIDName=%s\n" "DNIDDigits= %s\n" "RDNIS= %s\n" "Parkinglot= %s\n" "Language= %s\n" "State= %s (%d)\n" "Rings= %d\n" "NativeFormat= %s\n" "WriteFormat= %s\n" "ReadFormat= %s\n" "RawWriteFormat= %s\n" "RawReadFormat= %s\n" "WriteTranscode= %s %s\n" "ReadTranscode= %s %s\n" "1stFileDescriptor= %d\n" "Framesin= %d %s\n" "Framesout= %d %s\n" "TimetoHangup= %ld\n" "ElapsedTime= %dh%dm%ds\n" "DirectBridge= %s\n" "IndirectBridge= %s\n" "Context= %s\n" "Extension= %s\n" "Priority= %d\n" "CallGroup= %s\n" "PickupGroup= %s\n" "Application= %s\n" "Data= %s\n" "Blocking_in= %s\n", c->name, c->tech->type, c->uniqueid, c->linkedid, S_COR(c->caller.id.number.valid, c->caller.id.number.str, "(N/A)"), S_COR(c->caller.id.name.valid, c->caller.id.name.str, "(N/A)"), S_COR(c->connected.id.number.valid, c->connected.id.number.str, "(N/A)"), S_COR(c->connected.id.name.valid, c->connected.id.name.str, "(N/A)"), S_OR(c->dialed.number.str, "(N/A)"), S_COR(c->redirecting.from.number.valid, c->redirecting.from.number.str, "(N/A)"), c->parkinglot, c->language, ast_state2str(c->_state), c->_state, c->rings, ast_getformatname_multiple(nf, sizeof(nf), c->nativeformats), ast_getformatname(&c->writeformat), ast_getformatname(&c->readformat), ast_getformatname(&c->rawwriteformat), ast_getformatname(&c->rawreadformat), c->writetrans ? "Yes" : "No", ast_translate_path_to_str(c->writetrans, &write_transpath), c->readtrans ? "Yes" : "No", ast_translate_path_to_str(c->readtrans, &read_transpath), c->fds[0], c->fin & ~DEBUGCHAN_FLAG, (c->fin & DEBUGCHAN_FLAG) ? " (DEBUGGED)" : "", c->fout & ~DEBUGCHAN_FLAG, (c->fout & DEBUGCHAN_FLAG) ? " (DEBUGGED)" : "", (long)c->whentohangup.tv_sec, hour, min, sec, c->_bridge ? c->_bridge->name : "<none>", ast_bridged_channel(c) ? ast_bridged_channel(c)->name : "<none>", c->context, c->exten, c->priority, ast_print_group(cgrp, sizeof(cgrp), c->callgroup), ast_print_group(pgrp, sizeof(pgrp), c->pickupgroup), c->appl ? c->appl : "(N/A)", c->data ? S_OR(c->data, "(Empty)") : "(None)", (ast_test_flag(c, AST_FLAG_BLOCKING) ? c->blockproc : "(Not Blocking)")); return 0; }
static u_char *ast_var_channels_table(struct variable *vp, oid *name, size_t *length, int exact, size_t *var_len, WriteMethod **write_method) { static unsigned long long_ret; static u_char bits_ret[2]; static char string_ret[256]; struct ast_channel *chan, *bridge; struct timeval tval; u_char *ret = NULL; int i, bit; struct ast_str *out = ast_str_alloca(2048); if (header_simple_table(vp, name, length, exact, var_len, write_method, ast_active_channels())) return NULL; i = name[*length - 1] - 1; for (chan = ast_channel_walk_locked(NULL); chan && i; chan = ast_channel_walk_locked(chan), i--) ast_channel_unlock(chan); if (chan == NULL) return NULL; *var_len = sizeof(long_ret); switch (vp->magic) { case ASTCHANINDEX: long_ret = name[*length - 1]; ret = (u_char *)&long_ret; break; case ASTCHANNAME: if (!ast_strlen_zero(chan->name)) { strncpy(string_ret, chan->name, sizeof(string_ret)); string_ret[sizeof(string_ret) - 1] = '\0'; *var_len = strlen(string_ret); ret = (u_char *)string_ret; } break; case ASTCHANLANGUAGE: if (!ast_strlen_zero(chan->language)) { strncpy(string_ret, chan->language, sizeof(string_ret)); string_ret[sizeof(string_ret) - 1] = '\0'; *var_len = strlen(string_ret); ret = (u_char *)string_ret; } break; case ASTCHANTYPE: strncpy(string_ret, chan->tech->type, sizeof(string_ret)); string_ret[sizeof(string_ret) - 1] = '\0'; *var_len = strlen(string_ret); ret = (u_char *)string_ret; break; case ASTCHANMUSICCLASS: if (!ast_strlen_zero(chan->musicclass)) { strncpy(string_ret, chan->musicclass, sizeof(string_ret)); string_ret[sizeof(string_ret) - 1] = '\0'; *var_len = strlen(string_ret); ret = (u_char *)string_ret; } break; case ASTCHANBRIDGE: if ((bridge = ast_bridged_channel(chan)) != NULL) { strncpy(string_ret, bridge->name, sizeof(string_ret)); string_ret[sizeof(string_ret) - 1] = '\0'; *var_len = strlen(string_ret); ret = (u_char *)string_ret; } break; case ASTCHANMASQ: if (chan->masq && !ast_strlen_zero(chan->masq->name)) { strncpy(string_ret, chan->masq->name, sizeof(string_ret)); string_ret[sizeof(string_ret) - 1] = '\0'; *var_len = strlen(string_ret); ret = (u_char *)string_ret; } break; case ASTCHANMASQR: if (chan->masqr && !ast_strlen_zero(chan->masqr->name)) { strncpy(string_ret, chan->masqr->name, sizeof(string_ret)); string_ret[sizeof(string_ret) - 1] = '\0'; *var_len = strlen(string_ret); ret = (u_char *)string_ret; } break; case ASTCHANWHENHANGUP: if (!ast_tvzero(chan->whentohangup)) { gettimeofday(&tval, NULL); long_ret = difftime(chan->whentohangup.tv_sec, tval.tv_sec) * 100 - tval.tv_usec / 10000; ret= (u_char *)&long_ret; } break; case ASTCHANAPP: if (chan->appl) { strncpy(string_ret, chan->appl, sizeof(string_ret)); string_ret[sizeof(string_ret) - 1] = '\0'; *var_len = strlen(string_ret); ret = (u_char *)string_ret; } break; case ASTCHANDATA: if (chan->data) { strncpy(string_ret, chan->data, sizeof(string_ret)); string_ret[sizeof(string_ret) - 1] = '\0'; *var_len = strlen(string_ret); ret = (u_char *)string_ret; } break; case ASTCHANCONTEXT: strncpy(string_ret, chan->context, sizeof(string_ret)); string_ret[sizeof(string_ret) - 1] = '\0'; *var_len = strlen(string_ret); ret = (u_char *)string_ret; break; case ASTCHANMACROCONTEXT: strncpy(string_ret, chan->macrocontext, sizeof(string_ret)); string_ret[sizeof(string_ret) - 1] = '\0'; *var_len = strlen(string_ret); ret = (u_char *)string_ret; break; case ASTCHANMACROEXTEN: strncpy(string_ret, chan->macroexten, sizeof(string_ret)); string_ret[sizeof(string_ret) - 1] = '\0'; *var_len = strlen(string_ret); ret = (u_char *)string_ret; break; case ASTCHANMACROPRI: long_ret = chan->macropriority; ret = (u_char *)&long_ret; break; case ASTCHANEXTEN: strncpy(string_ret, chan->exten, sizeof(string_ret)); string_ret[sizeof(string_ret) - 1] = '\0'; *var_len = strlen(string_ret); ret = (u_char *)string_ret; break; case ASTCHANPRI: long_ret = chan->priority; ret = (u_char *)&long_ret; break; case ASTCHANACCOUNTCODE: if (!ast_strlen_zero(chan->accountcode)) { strncpy(string_ret, chan->accountcode, sizeof(string_ret)); string_ret[sizeof(string_ret) - 1] = '\0'; *var_len = strlen(string_ret); ret = (u_char *)string_ret; } break; case ASTCHANFORWARDTO: if (!ast_strlen_zero(chan->call_forward)) { strncpy(string_ret, chan->call_forward, sizeof(string_ret)); string_ret[sizeof(string_ret) - 1] = '\0'; *var_len = strlen(string_ret); ret = (u_char *)string_ret; } break; case ASTCHANUNIQUEID: strncpy(string_ret, chan->uniqueid, sizeof(string_ret)); string_ret[sizeof(string_ret) - 1] = '\0'; *var_len = strlen(string_ret); ret = (u_char *)string_ret; break; case ASTCHANCALLGROUP: long_ret = chan->callgroup; ret = (u_char *)&long_ret; break; case ASTCHANPICKUPGROUP: long_ret = chan->pickupgroup; ret = (u_char *)&long_ret; break; case ASTCHANSTATE: long_ret = chan->_state & 0xffff; ret = (u_char *)&long_ret; break; case ASTCHANMUTED: long_ret = chan->_state & AST_STATE_MUTE ? 1 : 2; ret = (u_char *)&long_ret; break; case ASTCHANRINGS: long_ret = chan->rings; ret = (u_char *)&long_ret; break; case ASTCHANCIDDNID: if (chan->cid.cid_dnid) { strncpy(string_ret, chan->cid.cid_dnid, sizeof(string_ret)); string_ret[sizeof(string_ret) - 1] = '\0'; *var_len = strlen(string_ret); ret = (u_char *)string_ret; } break; case ASTCHANCIDNUM: if (chan->cid.cid_num) { strncpy(string_ret, chan->cid.cid_num, sizeof(string_ret)); string_ret[sizeof(string_ret) - 1] = '\0'; *var_len = strlen(string_ret); ret = (u_char *)string_ret; } break; case ASTCHANCIDNAME: if (chan->cid.cid_name) { strncpy(string_ret, chan->cid.cid_name, sizeof(string_ret)); string_ret[sizeof(string_ret) - 1] = '\0'; *var_len = strlen(string_ret); ret = (u_char *)string_ret; } break; case ASTCHANCIDANI: if (chan->cid.cid_ani) { strncpy(string_ret, chan->cid.cid_ani, sizeof(string_ret)); string_ret[sizeof(string_ret) - 1] = '\0'; *var_len = strlen(string_ret); ret = (u_char *)string_ret; } break; case ASTCHANCIDRDNIS: if (chan->cid.cid_rdnis) { strncpy(string_ret, chan->cid.cid_rdnis, sizeof(string_ret)); string_ret[sizeof(string_ret) - 1] = '\0'; *var_len = strlen(string_ret); ret = (u_char *)string_ret; } break; case ASTCHANCIDPRES: long_ret = chan->cid.cid_pres; ret = (u_char *)&long_ret; break; case ASTCHANCIDANI2: long_ret = chan->cid.cid_ani2; ret = (u_char *)&long_ret; break; case ASTCHANCIDTON: long_ret = chan->cid.cid_ton; ret = (u_char *)&long_ret; break; case ASTCHANCIDTNS: long_ret = chan->cid.cid_tns; ret = (u_char *)&long_ret; break; case ASTCHANAMAFLAGS: long_ret = chan->amaflags; ret = (u_char *)&long_ret; break; case ASTCHANADSI: long_ret = chan->adsicpe; ret = (u_char *)&long_ret; break; case ASTCHANTONEZONE: if (chan->zone) { strncpy(string_ret, chan->zone->country, sizeof(string_ret)); string_ret[sizeof(string_ret) - 1] = '\0'; *var_len = strlen(string_ret); ret = (u_char *)string_ret; } break; case ASTCHANHANGUPCAUSE: long_ret = chan->hangupcause; ret = (u_char *)&long_ret; break; case ASTCHANVARIABLES: if (pbx_builtin_serialize_variables(chan, &out)) { *var_len = ast_str_strlen(out); ret = (u_char *)ast_str_buffer(out); } break; case ASTCHANFLAGS: bits_ret[0] = 0; for (bit = 0; bit < 8; bit++) bits_ret[0] |= ((chan->flags & (1 << bit)) >> bit) << (7 - bit); bits_ret[1] = 0; for (bit = 0; bit < 8; bit++) bits_ret[1] |= (((chan->flags >> 8) & (1 << bit)) >> bit) << (7 - bit); *var_len = 2; ret = bits_ret; break; case ASTCHANTRANSFERCAP: long_ret = chan->transfercapability; ret = (u_char *)&long_ret; default: break; } ast_channel_unlock(chan); return ret; }
int ast_strings_match(const char *left, const char *op, const char *right) { char *internal_op = (char *)op; char *internal_right = (char *)right; double left_num; double right_num; int scan_numeric = 0; if (!(left && right)) { return 0; } if (ast_strlen_zero(op)) { if (ast_strlen_zero(left) && ast_strlen_zero(right)) { return 1; } if (strlen(right) >= 2 && right[0] == '/' && right[strlen(right) - 1] == '/') { internal_op = "regex"; internal_right = ast_strdupa(right); /* strip the leading and trailing '/' */ internal_right++; internal_right[strlen(internal_right) - 1] = '\0'; goto regex; } else { internal_op = "="; goto equals; } } if (!strcasecmp(op, "like")) { char *tok; struct ast_str *buffer = ast_str_alloca(128); if (!strchr(right, '%')) { return !strcmp(left, right); } else { internal_op = "regex"; internal_right = ast_strdupa(right); tok = strsep(&internal_right, "%"); ast_str_set(&buffer, 0, "^%s", tok); while ((tok = strsep(&internal_right, "%"))) { ast_str_append(&buffer, 0, ".*%s", tok); } ast_str_append(&buffer, 0, "%s", "$"); internal_right = ast_str_buffer(buffer); /* fall through to regex */ } } regex: if (!strcasecmp(internal_op, "regex")) { regex_t expression; int rc; if (regcomp(&expression, internal_right, REG_EXTENDED | REG_NOSUB)) { return 0; } rc = regexec(&expression, left, 0, NULL, 0); regfree(&expression); return !rc; } equals: scan_numeric = (sscanf(left, "%lf", &left_num) && sscanf(internal_right, "%lf", &right_num)); if (internal_op[0] == '=') { if (ast_strlen_zero(left) && ast_strlen_zero(internal_right)) { return 1; } if (scan_numeric) { return (left_num == right_num); } else { return (!strcmp(left, internal_right)); } } if (internal_op[0] == '!' && internal_op[1] == '=') { if (scan_numeric) { return (left_num != right_num); } else { return !!strcmp(left, internal_right); } } if (internal_op[0] == '<') { if (scan_numeric) { if (internal_op[1] == '=') { return (left_num <= right_num); } else { return (left_num < right_num); } } else { if (internal_op[1] == '=') { return strcmp(left, internal_right) <= 0; } else { return strcmp(left, internal_right) < 0; } } } if (internal_op[0] == '>') { if (scan_numeric) { if (internal_op[1] == '=') { return (left_num >= right_num); } else { return (left_num > right_num); } } else { if (internal_op[1] == '=') { return strcmp(left, internal_right) >= 0; } else { return strcmp(left, internal_right) > 0; } } } return 0; }
struct ast_channel_snapshot *ast_channel_snapshot_create(struct ast_channel *chan) { struct ast_channel_snapshot *snapshot; struct ast_bridge *bridge; char nativeformats[256]; struct ast_str *write_transpath = ast_str_alloca(256); struct ast_str *read_transpath = ast_str_alloca(256); struct ast_party_id effective_connected_id; struct ast_callid *callid; /* no snapshots for dummy channels */ if (!ast_channel_tech(chan)) { return NULL; } snapshot = ao2_alloc(sizeof(*snapshot), channel_snapshot_dtor); if (!snapshot || ast_string_field_init(snapshot, 1024)) { ao2_cleanup(snapshot); return NULL; } ast_string_field_set(snapshot, name, ast_channel_name(chan)); ast_string_field_set(snapshot, type, ast_channel_tech(chan)->type); ast_string_field_set(snapshot, accountcode, ast_channel_accountcode(chan)); ast_string_field_set(snapshot, peeraccount, ast_channel_peeraccount(chan)); ast_string_field_set(snapshot, userfield, ast_channel_userfield(chan)); ast_string_field_set(snapshot, uniqueid, ast_channel_uniqueid(chan)); ast_string_field_set(snapshot, linkedid, ast_channel_linkedid(chan)); ast_string_field_set(snapshot, hangupsource, ast_channel_hangupsource(chan)); if (ast_channel_appl(chan)) { ast_string_field_set(snapshot, appl, ast_channel_appl(chan)); } if (ast_channel_data(chan)) { ast_string_field_set(snapshot, data, ast_channel_data(chan)); } ast_string_field_set(snapshot, context, ast_channel_context(chan)); ast_string_field_set(snapshot, exten, ast_channel_exten(chan)); ast_string_field_set(snapshot, caller_name, S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, "")); ast_string_field_set(snapshot, caller_number, S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, "")); ast_string_field_set(snapshot, caller_dnid, S_OR(ast_channel_dialed(chan)->number.str, "")); ast_string_field_set(snapshot, caller_subaddr, S_COR(ast_channel_caller(chan)->id.subaddress.valid, ast_channel_caller(chan)->id.subaddress.str, "")); ast_string_field_set(snapshot, dialed_subaddr, S_COR(ast_channel_dialed(chan)->subaddress.valid, ast_channel_dialed(chan)->subaddress.str, "")); ast_string_field_set(snapshot, caller_ani, S_COR(ast_channel_caller(chan)->ani.number.valid, ast_channel_caller(chan)->ani.number.str, "")); ast_string_field_set(snapshot, caller_rdnis, S_COR(ast_channel_redirecting(chan)->from.number.valid, ast_channel_redirecting(chan)->from.number.str, "")); ast_string_field_set(snapshot, caller_dnid, S_OR(ast_channel_dialed(chan)->number.str, "")); ast_string_field_set(snapshot, connected_name, S_COR(ast_channel_connected(chan)->id.name.valid, ast_channel_connected(chan)->id.name.str, "")); ast_string_field_set(snapshot, connected_number, S_COR(ast_channel_connected(chan)->id.number.valid, ast_channel_connected(chan)->id.number.str, "")); ast_string_field_set(snapshot, language, ast_channel_language(chan)); if ((bridge = ast_channel_get_bridge(chan))) { ast_string_field_set(snapshot, bridgeid, bridge->uniqueid); ao2_cleanup(bridge); } ast_string_field_set(snapshot, nativeformats, ast_getformatname_multiple(nativeformats, sizeof(nativeformats), ast_channel_nativeformats(chan))); ast_string_field_set(snapshot, readformat, ast_getformatname(ast_channel_readformat(chan))); ast_string_field_set(snapshot, writeformat, ast_getformatname(ast_channel_writeformat(chan))); ast_string_field_set(snapshot, writetrans, ast_translate_path_to_str(ast_channel_writetrans(chan), &write_transpath)); ast_string_field_set(snapshot, readtrans, ast_translate_path_to_str(ast_channel_readtrans(chan), &read_transpath)); effective_connected_id = ast_channel_connected_effective_id(chan); ast_string_field_set(snapshot, effective_name, S_COR(effective_connected_id.name.valid, effective_connected_id.name.str, "")); ast_string_field_set(snapshot, effective_number, S_COR(effective_connected_id.number.valid, effective_connected_id.number.str, "")); if ((callid = ast_channel_callid(chan))) { ast_callid_strnprint(snapshot->callid, sizeof(snapshot->callid), callid); ast_callid_unref(callid); } snapshot->creationtime = ast_channel_creationtime(chan); snapshot->hanguptime = *(ast_channel_whentohangup(chan)); snapshot->state = ast_channel_state(chan); snapshot->priority = ast_channel_priority(chan); snapshot->amaflags = ast_channel_amaflags(chan); snapshot->hangupcause = ast_channel_hangupcause(chan); ast_copy_flags(&snapshot->flags, ast_channel_flags(chan), 0xFFFFFFFF); snapshot->caller_pres = ast_party_id_presentation(&ast_channel_caller(chan)->id); snapshot->callgroup = ast_channel_callgroup(chan); snapshot->pickupgroup = ast_channel_pickupgroup(chan); ast_set_flag(&snapshot->softhangup_flags, ast_channel_softhangup_internal_flag(chan)); snapshot->manager_vars = ast_channel_get_manager_vars(chan); snapshot->channel_vars = ast_channel_get_vars(chan); snapshot->tech_properties = ast_channel_tech(chan)->properties; return snapshot; }
/*! \brief Function which passes through an aliased CLI command to the real one */ static char *cli_alias_passthrough(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { struct cli_alias *alias; struct cli_alias tmp = { .cli_entry.command = e->command, }; char *generator; const char *line; /* Try to find the alias based on the CLI entry */ if (!(alias = ao2_find(cli_aliases, &tmp, OBJ_POINTER))) { return 0; } switch (cmd) { case CLI_INIT: ao2_ref(alias, -1); return NULL; case CLI_GENERATE: line = a->line; line += (strlen(alias->alias)); if (!strncasecmp(alias->alias, alias->real_cmd, strlen(alias->alias))) { generator = NULL; } else if (!ast_strlen_zero(a->word)) { struct ast_str *real_cmd = ast_str_alloca(strlen(alias->real_cmd) + strlen(line) + 1); ast_str_append(&real_cmd, 0, "%s%s", alias->real_cmd, line); generator = ast_cli_generator(ast_str_buffer(real_cmd), a->word, a->n); } else { generator = ast_cli_generator(alias->real_cmd, a->word, a->n); } ao2_ref(alias, -1); return generator; } /* If they gave us extra arguments we need to construct a string to pass in */ if (a->argc != e->args) { struct ast_str *real_cmd = ast_str_alloca(2048); int i; ast_str_append(&real_cmd, 0, "%s", alias->real_cmd); /* Add the additional arguments that have been passed in */ for (i = e->args + 1; i <= a->argc; i++) { ast_str_append(&real_cmd, 0, " %s", a->argv[i - 1]); } ast_cli_command(a->fd, ast_str_buffer(real_cmd)); } else { ast_cli_command(a->fd, alias->real_cmd); } ao2_ref(alias, -1); return CLI_SUCCESS; } /*! \brief CLI Command to display CLI Aliases */ static char *alias_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { #define FORMAT "%-50.50s %-50.50s\n" struct cli_alias *alias; struct ao2_iterator i; switch (cmd) { case CLI_INIT: e->command = "cli show aliases"; e->usage = "Usage: cli show aliases\n" " Displays a list of aliased CLI commands.\n"; return NULL; case CLI_GENERATE: return NULL; } ast_cli(a->fd, FORMAT, "Alias Command", "Real Command"); i = ao2_iterator_init(cli_aliases, 0); for (; (alias = ao2_iterator_next(&i)); ao2_ref(alias, -1)) { ast_cli(a->fd, FORMAT, alias->alias, alias->real_cmd); } ao2_iterator_destroy(&i); return CLI_SUCCESS; #undef FORMAT } /*! \brief CLI commands to interact with things */ static struct ast_cli_entry cli_alias[] = { AST_CLI_DEFINE(alias_show, "Show CLI command aliases"), }; /*! \brief Function called to load or reload the configuration file */ static void load_config(int reload) { struct ast_config *cfg = NULL; struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; struct cli_alias *alias; struct ast_variable *v, *v1; if (!(cfg = ast_config_load(config_file, config_flags)) || cfg == CONFIG_STATUS_FILEINVALID) { ast_log(LOG_ERROR, "res_clialiases configuration file '%s' not found\n", config_file); return; } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) { return; } /* Destroy any existing CLI aliases */ if (reload) { ao2_callback(cli_aliases, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL); } for (v = ast_variable_browse(cfg, "general"); v; v = v->next) { if (strcmp(v->name, "template")) { ast_log(LOG_WARNING, "%s is not a correct option in [%s]\n", v->name, "general"); continue; } /* Read in those there CLI aliases */ for (v1 = ast_variable_browse(cfg, v->value); v1; v1 = v1->next) { if (!(alias = ao2_alloc((sizeof(*alias) + strlen(v1->name) + strlen(v1->value) + 2), alias_destroy))) { continue; } alias->alias = ((char *) alias) + sizeof(*alias); alias->real_cmd = ((char *) alias->alias) + strlen(v1->name) + 1; strcpy(alias->alias, v1->name); strcpy(alias->real_cmd, v1->value); alias->cli_entry.handler = cli_alias_passthrough; alias->cli_entry.command = alias->alias; alias->cli_entry.usage = "Aliased CLI Command\n"; ast_cli_register(&alias->cli_entry); ao2_link(cli_aliases, alias); ast_verbose(VERBOSE_PREFIX_2 "Aliased CLI command '%s' to '%s'\n", v1->name, v1->value); ao2_ref(alias, -1); } } ast_config_destroy(cfg); return; } /*! \brief Function called to reload the module */ static int reload_module(void) { load_config(1); 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")) { 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; }