📄 chan_h323.c
字号:
if (!got_progress) h323_send_progress(token); res = 0; } break; case AST_CONTROL_BUSY: if (c->_state != AST_STATE_UP) { h323_answering_call(token, 1); ast_softhangup_nolock(c, AST_SOFTHANGUP_DEV); res = 0; } break; case AST_CONTROL_CONGESTION: if (c->_state != AST_STATE_UP) { h323_answering_call(token, 1); ast_softhangup_nolock(c, AST_SOFTHANGUP_DEV); res = 0; } break; case AST_CONTROL_HOLD: ast_moh_start(c, data, NULL); res = 0; break; case AST_CONTROL_UNHOLD: ast_moh_stop(c); res = 0; break; case AST_CONTROL_SRCUPDATE: ast_rtp_new_source(pvt->rtp); res = 0; break; case AST_CONTROL_PROCEEDING: case -1: break; default: ast_log(LOG_WARNING, "OH323: Don't know how to indicate condition %d on %s\n", condition, token); break; } if (h323debug) ast_log(LOG_DEBUG, "OH323: Indicated %d on %s, res=%d\n", condition, token, res); if (token) free(token); oh323_update_info(c); return res;}static int oh323_fixup(struct ast_channel *oldchan, struct ast_channel *newchan){ struct oh323_pvt *pvt = (struct oh323_pvt *) newchan->tech_pvt; ast_mutex_lock(&pvt->lock); if (pvt->owner != oldchan) { ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, pvt->owner); return -1; } pvt->owner = newchan; ast_mutex_unlock(&pvt->lock); return 0;}static int __oh323_rtp_create(struct oh323_pvt *pvt){ struct in_addr our_addr; if (pvt->rtp) return 0; if (ast_find_ourip(&our_addr, bindaddr)) { ast_mutex_unlock(&pvt->lock); ast_log(LOG_ERROR, "Unable to locate local IP address for RTP stream\n"); return -1; } pvt->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, our_addr); if (!pvt->rtp) { ast_mutex_unlock(&pvt->lock); ast_log(LOG_WARNING, "Unable to create RTP session: %s\n", strerror(errno)); return -1; } if (h323debug) ast_log(LOG_DEBUG, "Created RTP channel\n"); ast_rtp_settos(pvt->rtp, tos); if (h323debug) ast_log(LOG_DEBUG, "Setting NAT on RTP to %d\n", pvt->options.nat); ast_rtp_setnat(pvt->rtp, pvt->options.nat); if (pvt->dtmf_pt > 0) ast_rtp_set_rtpmap_type(pvt->rtp, pvt->dtmf_pt, "audio", "telephone-event", 0); if (pvt->peercapability) ast_rtp_codec_setpref(pvt->rtp, &pvt->peer_prefs); if (pvt->owner && !ast_channel_trylock(pvt->owner)) { ast_jb_configure(pvt->owner, &global_jbconf); pvt->owner->fds[0] = ast_rtp_fd(pvt->rtp); pvt->owner->fds[1] = ast_rtcp_fd(pvt->rtp); ast_queue_frame(pvt->owner, &ast_null_frame); /* Tell Asterisk to apply changes */ ast_channel_unlock(pvt->owner); } else pvt->update_rtp_info = 1; return 0;}/* Private structure should be locked on a call */static struct ast_channel *__oh323_new(struct oh323_pvt *pvt, int state, const char *host){ struct ast_channel *ch; char *cid_num, *cid_name; int fmt; if (!ast_strlen_zero(pvt->options.cid_num)) cid_num = pvt->options.cid_num; else cid_num = pvt->cd.call_source_e164; if (!ast_strlen_zero(pvt->options.cid_name)) cid_name = pvt->options.cid_name; else cid_name = pvt->cd.call_source_name; /* Don't hold a oh323_pvt lock while we allocate a chanel */ ast_mutex_unlock(&pvt->lock); ch = ast_channel_alloc(1, state, cid_num, cid_name, pvt->accountcode, pvt->exten, pvt->context, pvt->amaflags, "H323/%s", host); /* Update usage counter */ ast_module_ref(ast_module_info->self); ast_mutex_lock(&pvt->lock); if (ch) { ch->tech = &oh323_tech; if (!(fmt = pvt->jointcapability) && !(fmt = pvt->options.capability)) fmt = global_options.capability; ch->nativeformats = ast_codec_choose(&pvt->options.prefs, fmt, 1)/* | (pvt->jointcapability & AST_FORMAT_VIDEO_MASK)*/; pvt->nativeformats = ch->nativeformats; fmt = ast_best_codec(ch->nativeformats); ch->writeformat = fmt; ch->rawwriteformat = fmt; ch->readformat = fmt; ch->rawreadformat = fmt;#if 0 ch->fds[0] = ast_rtp_fd(pvt->rtp); ch->fds[1] = ast_rtcp_fd(pvt->rtp);#endif#ifdef VIDEO_SUPPORT if (pvt->vrtp) { ch->fds[2] = ast_rtp_fd(pvt->vrtp); ch->fds[3] = ast_rtcp_fd(pvt->vrtp); }#endif#ifdef T38_SUPPORT if (pvt->udptl) { ch->fds[4] = ast_udptl_fd(pvt->udptl); }#endif if (state == AST_STATE_RING) { ch->rings = 1; } /* Allocate dsp for in-band DTMF support */ if (pvt->options.dtmfmode & H323_DTMF_INBAND) { pvt->vad = ast_dsp_new(); ast_dsp_set_features(pvt->vad, DSP_FEATURE_DTMF_DETECT); } /* Register channel functions. */ ch->tech_pvt = pvt; /* Set the owner of this channel */ pvt->owner = ch; ast_copy_string(ch->context, pvt->context, sizeof(ch->context)); ast_copy_string(ch->exten, pvt->exten, sizeof(ch->exten)); ch->priority = 1; if (!ast_strlen_zero(pvt->accountcode)) { ast_string_field_set(ch, accountcode, pvt->accountcode); } if (pvt->amaflags) { ch->amaflags = pvt->amaflags; } /* Don't use ast_set_callerid() here because it will * generate a needless NewCallerID event */ ch->cid.cid_ani = ast_strdup(cid_num); if (pvt->cd.redirect_reason >= 0) { ch->cid.cid_rdnis = ast_strdup(pvt->cd.redirect_number); pbx_builtin_setvar_helper(ch, "PRIREDIRECTREASON", redirectingreason2str(pvt->cd.redirect_reason)); } ch->cid.cid_pres = pvt->cd.presentation; ch->cid.cid_ton = pvt->cd.type_of_number; if (!ast_strlen_zero(pvt->exten) && strcmp(pvt->exten, "s")) { ch->cid.cid_dnid = strdup(pvt->exten); } if (pvt->cd.transfer_capability >= 0) ch->transfercapability = pvt->cd.transfer_capability; if (state != AST_STATE_DOWN) { if (ast_pbx_start(ch)) { ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ch->name); ast_hangup(ch); ch = NULL; } } } else { ast_log(LOG_WARNING, "Unable to allocate channel structure\n"); } return ch;}static struct oh323_pvt *oh323_alloc(int callid){ struct oh323_pvt *pvt; pvt = (struct oh323_pvt *) malloc(sizeof(struct oh323_pvt)); if (!pvt) { ast_log(LOG_ERROR, "Couldn't allocate private structure. This is bad\n"); return NULL; } memset(pvt, 0, sizeof(struct oh323_pvt)); pvt->cd.redirect_reason = -1; pvt->cd.transfer_capability = -1; /* Ensure the call token is allocated for outgoing call */ if (!callid) { if ((pvt->cd).call_token == NULL) { (pvt->cd).call_token = (char *)malloc(128); } if (!pvt->cd.call_token) { ast_log(LOG_ERROR, "Not enough memory to alocate call token\n"); ast_rtp_destroy(pvt->rtp); free(pvt); return NULL; } memset((char *)(pvt->cd).call_token, 0, 128); pvt->cd.call_reference = callid; } memcpy(&pvt->options, &global_options, sizeof(pvt->options)); pvt->jointcapability = pvt->options.capability; if (pvt->options.dtmfmode & H323_DTMF_RFC2833) { pvt->nonCodecCapability |= AST_RTP_DTMF; } else { pvt->nonCodecCapability &= ~AST_RTP_DTMF; } ast_copy_string(pvt->context, default_context, sizeof(pvt->context)); pvt->newstate = pvt->newcontrol = pvt->newdigit = pvt->update_rtp_info = pvt->DTMFsched = -1; ast_mutex_init(&pvt->lock); /* Add to interface list */ ast_mutex_lock(&iflock); pvt->next = iflist; iflist = pvt; ast_mutex_unlock(&iflock); return pvt;}static struct oh323_pvt *find_call_locked(int call_reference, const char *token){ struct oh323_pvt *pvt; ast_mutex_lock(&iflock); pvt = iflist; while(pvt) { if (!pvt->needdestroy && ((signed int)pvt->cd.call_reference == call_reference)) { /* Found the call */ if ((token != NULL) && (pvt->cd.call_token != NULL) && (!strcmp(pvt->cd.call_token, token))) { ast_mutex_lock(&pvt->lock); ast_mutex_unlock(&iflock); return pvt; } else if (token == NULL) { ast_log(LOG_WARNING, "Call Token is NULL\n"); ast_mutex_lock(&pvt->lock); ast_mutex_unlock(&iflock); return pvt; } } pvt = pvt->next; } ast_mutex_unlock(&iflock); return NULL;}static int update_state(struct oh323_pvt *pvt, int state, int signal){ if (!pvt) return 0; if (pvt->owner && !ast_channel_trylock(pvt->owner)) { if (state >= 0) ast_setstate(pvt->owner, state); if (signal >= 0) ast_queue_control(pvt->owner, signal); ast_channel_unlock(pvt->owner); return 1; } else { if (state >= 0) pvt->newstate = state; if (signal >= 0) pvt->newcontrol = signal; return 0; }}static struct oh323_alias *build_alias(const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime){ struct oh323_alias *alias; int found = 0; alias = ASTOBJ_CONTAINER_FIND_UNLINK_FULL(&aliasl, name, name, 0, 0, strcasecmp); if (alias) found++; else { if (!(alias = (struct oh323_alias *)calloc(1, sizeof(*alias)))) return NULL; ASTOBJ_INIT(alias); } if (!found && name) ast_copy_string(alias->name, name, sizeof(alias->name)); for (; v || ((v = alt) && !(alt = NULL)); v = v->next) { if (!strcasecmp(v->name, "e164")) { ast_copy_string(alias->e164, v->value, sizeof(alias->e164)); } else if (!strcasecmp(v->name, "prefix")) { ast_copy_string(alias->prefix, v->value, sizeof(alias->prefix)); } else if (!strcasecmp(v->name, "context")) { ast_copy_string(alias->context, v->value, sizeof(alias->context)); } else if (!strcasecmp(v->name, "secret")) { ast_copy_string(alias->secret, v->value, sizeof(alias->secret)); } else { if (strcasecmp(v->value, "h323")) { ast_log(LOG_WARNING, "Keyword %s does not make sense in type=h323\n", v->name); } } } ASTOBJ_UNMARK(alias); return alias;}static struct oh323_alias *realtime_alias(const char *alias){ struct ast_variable *var, *tmp; struct oh323_alias *a; var = ast_load_realtime("h323", "name", alias, NULL); if (!var) return NULL; for (tmp = var; tmp; tmp = tmp->next) { if (!strcasecmp(tmp->name, "type") && !(!strcasecmp(tmp->value, "alias") || !strcasecmp(tmp->value, "h323"))) { ast_variables_destroy(var); return NULL; } } a = build_alias(alias, var, NULL, 1); ast_variables_destroy(var); return a;}#define DEPRECATED(_v, _new_opt) \ ast_log(LOG_WARNING, "Option %s found at line %d has beed deprecated. Use %s instead.\n", (_v)->name, (_v)->lineno, (_new_opt))static int update_common_options(struct ast_variable *v, struct call_options *options){ int tmp; if (!strcasecmp(v->name, "allow")) { ast_parse_allow_disallow(&options->prefs, &options->capability, v->value, 1); } else if (!strcasecmp(v->name, "disallow")) { ast_parse_allow_disallow(&options->prefs, &options->capability, v->value, 0); } else if (!strcasecmp(v->name, "dtmfmode")) { if (!strcasecmp(v->value, "inband")) { options->dtmfmode = H323_DTMF_INBAND; } else if (!strcasecmp(v->value, "rfc2833")) { options->dtmfmode = H323_DTMF_RFC2833; } else { ast_log(LOG_WARNING, "Unknown dtmf mode '%s', using rfc2833\n", v->value); options->dtmfmode = H323_DTMF_RFC2833; } } else if (!strcasecmp(v->name, "dtmfcodec")) { tmp = atoi(v->value); if (tmp < 96) ast_log(LOG_WARNING, "Invalid %s value %s at line %d\n", v->name, v->value, v->lineno); else options->dtmfcodec = tmp; } else if (!strcasecmp(v->name, "bridge")) { options->bridge = ast_true(v->value); } else if (!strcasecmp(v->name, "nat")) { options->nat = ast_true(v->value); } else if (!strcasecmp(v->name, "noFastStart")) { DEPRECATED(v, "fastStart"); options->fastStart = !ast_true(v->value); } else if (!strcasecmp(v->name, "fastStart")) { options->fastStart = ast_true(v->value); } else if (!strcasecmp(v->name, "noH245Tunneling")) { DEPRECATED(v, "h245Tunneling"); options->h245Tunneling = !ast_true(v->value); } else if (!strcasecmp(v->name, "h245Tunneling")) { options->h245Tunneling = ast_true(v->value); } else if (!strcasecmp(v->name, "noSilenceSuppression")) { DEPRECATED(v, "silenceSuppression"); options->silenceSuppression = !ast_true(v->value); } else if (!strcasecmp(v->name, "silenceSuppression")) { options->silenceSuppression = ast_true(v->value); } else if (!strcasecmp(v->name, "progress_setup")) { tmp = atoi(v->value); if ((tmp != 0) && (tmp != 1) && (tmp != 3) && (tmp != 8)) { ast_log(LOG_WARNING, "Invalid value %s for %s at line %d, assuming 0\n", v->value, v->name, v->lineno); tmp = 0; } options->progress_setup = tmp; } else if (!strcasecmp(v->name, "progress_alert")) { tmp = atoi(v->value); if ((tmp != 0) && (tmp != 1) && (tmp != 8)) { ast_log(LOG_WARNING, "Invalid value %s for %s at line %d, assuming 0\n", v->value, v->name, v->lineno); tmp = 0; } options->progress_alert = tmp; } else if (!strcasecmp(v->name, "progress_audio")) { options->progress_audio = ast_true(v->value); } else if (!strcasecmp(v->name, "callerid")) { ast_callerid_split(v->value, options->cid_name, sizeof(options->cid_name), options->cid_num, sizeof(options->cid_num)); } else if (!strcasecmp(v->name, "fullname")) { ast_copy_string(options->cid_name, v->value, sizeof(options->cid_name)); } else if (!strcasecmp(v->name, "cid_number")) { ast_copy_string(options->cid_num, v->value, sizeof(options->cid_num)); } else if (!strcasecmp(v->name, "tunneling")) { if (!strcasecmp(v->value, "none")) options->tunnelOptions = 0; else if (!strcasecmp(v->value, "cisco")) options->tunnelOptions |= H323_TUNNEL_CISCO; else if (!strcasecmp(v->value, "qsig")) options->tunnelOptions |= H323_TUNNEL_QSIG; else ast_log(LOG_WARNING, "Invalid value %s for %s at line %d\n", v->value, v->name, v->lineno); } else return 1; return 0;}#undef DEPRECATEDstatic struct oh323_user *build_user(char *name, struct ast_variable *v, struct ast_variable *alt, int realtime){ struct oh323_user *user;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -