⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chan_local.c

📁 Asterisk中信道部分的源码 。。。。
💻 C
📖 第 1 页 / 共 2 页
字号:
		ast_mutex_unlock(&p->lock);	return res;}static int local_digit_end(struct ast_channel *ast, char digit, unsigned int duration){	struct local_pvt *p = ast->tech_pvt;	int res = -1;	struct ast_frame f = { AST_FRAME_DTMF_END, };	int isoutbound;	if (!p)		return -1;	ast_mutex_lock(&p->lock);	isoutbound = IS_OUTBOUND(ast, p);	f.subclass = digit;	f.len = duration;	if (!(res = local_queue_frame(p, isoutbound, &f, ast, 0)))		ast_mutex_unlock(&p->lock);	return res;}static int local_sendtext(struct ast_channel *ast, const char *text){	struct local_pvt *p = ast->tech_pvt;	int res = -1;	struct ast_frame f = { AST_FRAME_TEXT, };	int isoutbound;	if (!p)		return -1;	ast_mutex_lock(&p->lock);	isoutbound = IS_OUTBOUND(ast, p);	f.data = (char *) text;	f.datalen = strlen(text) + 1;	if (!(res = local_queue_frame(p, isoutbound, &f, ast, 0)))		ast_mutex_unlock(&p->lock);	return res;}static int local_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen){	struct local_pvt *p = ast->tech_pvt;	int res = -1;	struct ast_frame f = { AST_FRAME_HTML, };	int isoutbound;	if (!p)		return -1;		ast_mutex_lock(&p->lock);	isoutbound = IS_OUTBOUND(ast, p);	f.subclass = subclass;	f.data = (char *)data;	f.datalen = datalen;	if (!(res = local_queue_frame(p, isoutbound, &f, ast, 0)))		ast_mutex_unlock(&p->lock);	return res;}/*! \brief Initiate new call, part of PBX interface  * 	dest is the dial string */static int local_call(struct ast_channel *ast, char *dest, int timeout){	struct local_pvt *p = ast->tech_pvt;	int res;	struct ast_var_t *varptr = NULL, *new;	size_t len, namelen;	if (!p)		return -1;		ast_mutex_lock(&p->lock);	/*	 * Note that cid_num and cid_name aren't passed in the ast_channel_alloc	 * call, so it's done here instead.	 */	p->chan->cid.cid_num = ast_strdup(p->owner->cid.cid_num);	p->chan->cid.cid_name = ast_strdup(p->owner->cid.cid_name);	p->chan->cid.cid_rdnis = ast_strdup(p->owner->cid.cid_rdnis);	p->chan->cid.cid_ani = ast_strdup(p->owner->cid.cid_ani);	p->chan->cid.cid_pres = p->owner->cid.cid_pres;	ast_string_field_set(p->chan, language, p->owner->language);	ast_string_field_set(p->chan, accountcode, p->owner->accountcode);	ast_cdr_update(p->chan);	p->chan->cdrflags = p->owner->cdrflags;	/* copy the channel variables from the incoming channel to the outgoing channel */	/* Note that due to certain assumptions, they MUST be in the same order */	AST_LIST_TRAVERSE(&p->owner->varshead, varptr, entries) {		namelen = strlen(varptr->name);		len = sizeof(struct ast_var_t) + namelen + strlen(varptr->value) + 2;		if ((new = ast_calloc(1, len))) {			memcpy(new, varptr, len);			new->value = &(new->name[0]) + namelen + 1;			AST_LIST_INSERT_TAIL(&p->chan->varshead, new, entries);		}	}	ast_channel_datastore_inherit(p->owner, p->chan);	/* Start switch on sub channel */	if (!(res = ast_pbx_start(p->chan)))		ast_set_flag(p, LOCAL_LAUNCHED_PBX);	ast_mutex_unlock(&p->lock);	return res;}/*! \brief Hangup a call through the local proxy channel */static int local_hangup(struct ast_channel *ast){	struct local_pvt *p = ast->tech_pvt;	int isoutbound;	struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_HANGUP };	struct ast_channel *ochan = NULL;	int glaredetect = 0, res = 0;	if (!p)		return -1;	while (ast_mutex_trylock(&p->lock)) {		ast_channel_unlock(ast);		usleep(1);		ast_channel_lock(ast);	}	isoutbound = IS_OUTBOUND(ast, p);	if (isoutbound) {		const char *status = pbx_builtin_getvar_helper(p->chan, "DIALSTATUS");		if ((status) && (p->owner)) {			/* Deadlock avoidance */			while (p->owner && ast_channel_trylock(p->owner)) {				ast_mutex_unlock(&p->lock);				if (ast) {					ast_channel_unlock(ast);				}				usleep(1);				if (ast) {					ast_channel_lock(ast);				}				ast_mutex_lock(&p->lock);			}			if (p->owner) {				pbx_builtin_setvar_helper(p->owner, "CHANLOCALSTATUS", status);				ast_channel_unlock(p->owner);			}		}		p->chan = NULL;		ast_clear_flag(p, LOCAL_LAUNCHED_PBX);		ast_module_user_remove(p->u_chan);	} else {		p->owner = NULL;		ast_module_user_remove(p->u_owner);		if (p->chan) {			ast_queue_hangup(p->chan);		}	}		ast->tech_pvt = NULL;		if (!p->owner && !p->chan) {		/* Okay, done with the private part now, too. */		glaredetect = ast_test_flag(p, LOCAL_GLARE_DETECT);		/* If we have a queue holding, don't actually destroy p yet, but		   let local_queue do it. */		if (glaredetect)			ast_set_flag(p, LOCAL_CANCEL_QUEUE);		ast_mutex_unlock(&p->lock);		/* Remove from list */		AST_LIST_LOCK(&locals);		AST_LIST_REMOVE(&locals, p, list);		AST_LIST_UNLOCK(&locals);		/* Grab / release lock just in case */		ast_mutex_lock(&p->lock);		ast_mutex_unlock(&p->lock);		/* And destroy */		if (!glaredetect) {			p = local_pvt_destroy(p);		}		return 0;	}	if (p->chan && !ast_test_flag(p, LOCAL_LAUNCHED_PBX))		/* Need to actually hangup since there is no PBX */		ochan = p->chan;	else		res = local_queue_frame(p, isoutbound, &f, NULL, 1);	if (!res)		ast_mutex_unlock(&p->lock);	if (ochan)		ast_hangup(ochan);	return 0;}/*! \brief Create a call structure */static struct local_pvt *local_alloc(const char *data, int format){	struct local_pvt *tmp = NULL;	char *c = NULL, *opts = NULL;	if (!(tmp = ast_calloc(1, sizeof(*tmp))))		return NULL;	/* Initialize private structure information */	ast_mutex_init(&tmp->lock);	ast_copy_string(tmp->exten, data, sizeof(tmp->exten));	/* Look for options */	if ((opts = strchr(tmp->exten, '/'))) {		*opts++ = '\0';		if (strchr(opts, 'n'))			ast_set_flag(tmp, LOCAL_NO_OPTIMIZATION);	}	/* Look for a context */	if ((c = strchr(tmp->exten, '@')))		*c++ = '\0';	ast_copy_string(tmp->context, c ? c : "default", sizeof(tmp->context));	tmp->reqformat = format;	if (!ast_exists_extension(NULL, tmp->context, tmp->exten, 1, NULL)) {		ast_log(LOG_NOTICE, "No such extension/context %s@%s creating local channel\n", tmp->exten, tmp->context);		tmp = local_pvt_destroy(tmp);	} else {		/* Add to list */		AST_LIST_LOCK(&locals);		AST_LIST_INSERT_HEAD(&locals, tmp, list);		AST_LIST_UNLOCK(&locals);	}		return tmp;}/*! \brief Start new local channel */static struct ast_channel *local_new(struct local_pvt *p, int state){	struct ast_channel *tmp = NULL, *tmp2 = NULL;	int randnum = ast_random() & 0xffff, fmt = 0;	const char *t;	int ama;	/* Allocate two new Asterisk channels */	/* safe accountcode */	if (p->owner && p->owner->accountcode)		t = p->owner->accountcode;	else		t = "";	if (p->owner)		ama = p->owner->amaflags;	else		ama = 0;	if (!(tmp = ast_channel_alloc(1, state, 0, 0, t, p->exten, p->context, ama, "Local/%s@%s-%04x,1", p->exten, p->context, randnum)) 			|| !(tmp2 = ast_channel_alloc(1, AST_STATE_RING, 0, 0, t, p->exten, p->context, ama, "Local/%s@%s-%04x,2", p->exten, p->context, randnum))) {		if (tmp)			ast_channel_free(tmp);		if (tmp2)			ast_channel_free(tmp2);		ast_log(LOG_WARNING, "Unable to allocate channel structure(s)\n");		return NULL;	} 	tmp2->tech = tmp->tech = &local_tech;	tmp->nativeformats = p->reqformat;	tmp2->nativeformats = p->reqformat;	/* Determine our read/write format and set it on each channel */	fmt = ast_best_codec(p->reqformat);	tmp->writeformat = fmt;	tmp2->writeformat = fmt;	tmp->rawwriteformat = fmt;	tmp2->rawwriteformat = fmt;	tmp->readformat = fmt;	tmp2->readformat = fmt;	tmp->rawreadformat = fmt;	tmp2->rawreadformat = fmt;	tmp->tech_pvt = p;	tmp2->tech_pvt = p;	p->owner = tmp;	p->chan = tmp2;	p->u_owner = ast_module_user_add(p->owner);	p->u_chan = ast_module_user_add(p->chan);	ast_copy_string(tmp->context, p->context, sizeof(tmp->context));	ast_copy_string(tmp2->context, p->context, sizeof(tmp2->context));	ast_copy_string(tmp2->exten, p->exten, sizeof(tmp->exten));	tmp->priority = 1;	tmp2->priority = 1;	return tmp;}/*! \brief Part of PBX interface */static struct ast_channel *local_request(const char *type, int format, void *data, int *cause){	struct local_pvt *p = NULL;	struct ast_channel *chan = NULL;	/* Allocate a new private structure and then Asterisk channel */	if ((p = local_alloc(data, format))) {		if (!(chan = local_new(p, AST_STATE_DOWN))) {			AST_LIST_LOCK(&locals);			AST_LIST_REMOVE(&locals, p, list);			AST_LIST_UNLOCK(&locals);			p = local_pvt_destroy(p);		}	}	return chan;}/*! \brief CLI command "local show channels" */static int locals_show(int fd, int argc, char **argv){	struct local_pvt *p = NULL;	if (argc != 3)		return RESULT_SHOWUSAGE;	AST_LIST_LOCK(&locals);	if (!AST_LIST_EMPTY(&locals)) {		AST_LIST_TRAVERSE(&locals, p, list) {			ast_mutex_lock(&p->lock);			ast_cli(fd, "%s -- %s@%s\n", p->owner ? p->owner->name : "<unowned>", p->exten, p->context);			ast_mutex_unlock(&p->lock);		}	} else		ast_cli(fd, "No local channels in use\n");	AST_LIST_UNLOCK(&locals);	return RESULT_SUCCESS;}static char show_locals_usage[] = "Usage: local show channels\n""       Provides summary information on active local proxy channels.\n";static struct ast_cli_entry cli_local[] = {	{ { "local", "show", "channels", NULL },	locals_show, "List status of local channels",	show_locals_usage },};/*! \brief Load module into PBX, register channel */static int load_module(void){	/* Make sure we can register our channel type */	if (ast_channel_register(&local_tech)) {		ast_log(LOG_ERROR, "Unable to register channel class 'Local'\n");		return -1;	}	ast_cli_register_multiple(cli_local, sizeof(cli_local) / sizeof(struct ast_cli_entry));	return 0;}/*! \brief Unload the local proxy channel from Asterisk */static int unload_module(void){	struct local_pvt *p = NULL;	/* First, take us out of the channel loop */	ast_cli_unregister_multiple(cli_local, sizeof(cli_local) / sizeof(struct ast_cli_entry));	ast_channel_unregister(&local_tech);	if (!AST_LIST_LOCK(&locals)) {		/* Hangup all interfaces if they have an owner */		AST_LIST_TRAVERSE(&locals, p, list) {			if (p->owner)				ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);		}		AST_LIST_UNLOCK(&locals);	} else {		ast_log(LOG_WARNING, "Unable to lock the monitor\n");		return -1;	}			return 0;}AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Local Proxy Channel (Note: used internally by other modules)");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -