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

📄 chan_mgcp.c

📁 Asterisk中信道部分的源码 。。。。
💻 C
📖 第 1 页 / 共 5 页
字号:
		transmit_notify_request(sub, "G/rt");#endif				break;	case AST_CONTROL_BUSY:		transmit_notify_request(sub, "L/bz");		break;	case AST_CONTROL_CONGESTION:		transmit_notify_request(sub, "G/cg");		break;	case AST_CONTROL_HOLD:		ast_moh_start(ast, data, NULL);		break;	case AST_CONTROL_UNHOLD:		ast_moh_stop(ast);		break;	case AST_CONTROL_SRCUPDATE:		ast_rtp_new_source(sub->rtp);		break;	case -1:		transmit_notify_request(sub, "");		break;	default:		ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind);		res = -1;	}	ast_mutex_unlock(&sub->lock);	return res;}static struct ast_channel *mgcp_new(struct mgcp_subchannel *sub, int state){	struct ast_channel *tmp;	struct mgcp_endpoint *i = sub->parent;	int fmt;	tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, "MGCP/%s@%s-%d", i->name, i->parent->name, sub->id);	if (tmp) {		tmp->tech = &mgcp_tech;		tmp->nativeformats = i->capability;		if (!tmp->nativeformats)			tmp->nativeformats = capability;		fmt = ast_best_codec(tmp->nativeformats);		ast_string_field_build(tmp, name, "MGCP/%s@%s-%d", i->name, i->parent->name, sub->id);		if (sub->rtp)			tmp->fds[0] = ast_rtp_fd(sub->rtp);		if (i->dtmfmode & (MGCP_DTMF_INBAND | MGCP_DTMF_HYBRID)) {			i->dsp = ast_dsp_new();			ast_dsp_set_features(i->dsp,DSP_FEATURE_DTMF_DETECT);			/* this is to prevent clipping of dtmf tones during dsp processing */			ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_NOQUELCH);		} else {			i->dsp = NULL;		}		if (state == AST_STATE_RING)			tmp->rings = 1;		tmp->writeformat = fmt;		tmp->rawwriteformat = fmt;		tmp->readformat = fmt;		tmp->rawreadformat = fmt;		tmp->tech_pvt = sub;		if (!ast_strlen_zero(i->language))			ast_string_field_set(tmp, language, i->language);		if (!ast_strlen_zero(i->accountcode))			ast_string_field_set(tmp, accountcode, i->accountcode);		if (i->amaflags)			tmp->amaflags = i->amaflags;		sub->owner = tmp;		ast_module_ref(ast_module_info->self);		tmp->callgroup = i->callgroup;		tmp->pickupgroup = i->pickupgroup;		ast_string_field_set(tmp, call_forward, i->call_forward);		ast_copy_string(tmp->context, i->context, sizeof(tmp->context));		ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));		/* Don't use ast_set_callerid() here because it will		 * generate a needless NewCallerID event */		tmp->cid.cid_ani = ast_strdup(i->cid_num);				if (!i->adsi)			tmp->adsicpe = AST_ADSI_UNAVAILABLE;		tmp->priority = 1;		if (sub->rtp)			ast_jb_configure(tmp, &global_jbconf);		if (state != AST_STATE_DOWN) {			if (ast_pbx_start(tmp)) {				ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);				ast_hangup(tmp);				tmp = NULL;			}		}		/* verbose level check */		if (option_verbose > 2) {			ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_new(%s) created in state: %s\n",				tmp->name, ast_state2str(state));		}	} else {		ast_log(LOG_WARNING, "Unable to allocate channel structure\n");	}	return tmp;}static char* get_sdp_by_line(char* line, char *name, int nameLen){	if (strncasecmp(line, name, nameLen) == 0 && line[nameLen] == '=') {		char* r = line + nameLen + 1;		while (*r && (*r < 33)) ++r;		return r;	}	return "";}static char *get_sdp(struct mgcp_request *req, char *name){	int x;	int len = strlen(name);	char *r;	for (x=0; x<req->lines; x++) {		r = get_sdp_by_line(req->line[x], name, len);		if (r[0] != '\0') return r;	}	return "";}static void sdpLineNum_iterator_init(int* iterator){	*iterator = 0;}static char* get_sdp_iterate(int* iterator, struct mgcp_request *req, char *name){	int len = strlen(name);	char *r;	while (*iterator < req->lines) {		r = get_sdp_by_line(req->line[(*iterator)++], name, len);		if (r[0] != '\0') return r;	}	return "";}static char *__get_header(struct mgcp_request *req, char *name, int *start){	int x;	int len = strlen(name);	char *r;	for (x=*start;x<req->headers;x++) {		if (!strncasecmp(req->header[x], name, len) && 		    (req->header[x][len] == ':')) {			r = req->header[x] + len + 1;			while(*r && (*r < 33))				r++;			*start = x+1;			return r;		}	}	/* Don't return NULL, so get_header is always a valid pointer */	return "";}static char *get_header(struct mgcp_request *req, char *name){	int start = 0;	return __get_header(req, name, &start);}/*! \brief get_csv: (SC:) get comma separated value */static char *get_csv(char *c, int *len, char **next) {	char *s;	*next = NULL, *len = 0;	if (!c) return NULL;	while (*c && (*c < 33 || *c == ','))		c++;	s = c;	while (*c && (*c >= 33 && *c != ','))		c++, (*len)++;	*next = c;	if (*len == 0)		s = NULL, *next = NULL;	return s;}static struct mgcp_subchannel *find_subchannel_and_lock(char *name, int msgid, struct sockaddr_in *sin){	struct mgcp_endpoint *p = NULL;	struct mgcp_subchannel *sub = NULL;	struct mgcp_gateway *g;	char tmp[256] = "";	char *at = NULL, *c;	int found = 0;	if (name) {		ast_copy_string(tmp, name, sizeof(tmp));		at = strchr(tmp, '@');		if (!at) {			ast_log(LOG_NOTICE, "Endpoint '%s' has no at sign!\n", name);			return NULL;		}		*at++ = '\0';	}	ast_mutex_lock(&gatelock);	if (at && (at[0] == '[')) {		at++;		c = strrchr(at, ']');		if (c)			*c = '\0';	}	g = gateways;	while(g) {		if ((!name || !strcasecmp(g->name, at)) && 		    (sin || g->addr.sin_addr.s_addr || g->defaddr.sin_addr.s_addr)) {			/* Found the gateway.  If it's dynamic, save it's address -- now for the endpoint */			if (sin && g->dynamic && name) {				if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) ||					(g->addr.sin_port != sin->sin_port)) {					memcpy(&g->addr, sin, sizeof(g->addr));					if (ast_ouraddrfor(&g->addr.sin_addr, &g->ourip))						memcpy(&g->ourip, &__ourip, sizeof(g->ourip));					if (option_verbose > 2)						ast_verbose(VERBOSE_PREFIX_3 "Registered MGCP gateway '%s' at %s port %d\n", g->name, ast_inet_ntoa(g->addr.sin_addr), ntohs(g->addr.sin_port));				}			}			/* not dynamic, check if the name matches */			else if (name) {				if (strcasecmp(g->name, at)) {					g = g->next;					continue;				}			}			/* not dynamic, no name, check if the addr matches */			else if (!name && sin) { 				if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) ||				    (g->addr.sin_port != sin->sin_port)) {					g = g->next;					continue;				}			} else {				g = g->next;				continue;			}			/* SC */			p = g->endpoints;			while(p) {				if (option_debug)					ast_log(LOG_DEBUG, "Searching on %s@%s for subchannel\n",						p->name, g->name);				if (msgid) {#if 0 /* new transport mech */					sub = p->sub;					do {						if (option_debug)							ast_log(LOG_DEBUG, "Searching on %s@%s-%d for subchannel with lastout: %d\n",								p->name, g->name, sub->id, msgid);						if (sub->lastout == msgid) {							if (option_debug)								ast_log(LOG_DEBUG, "Found subchannel sub%d to handle request %d sub->lastout: %d\n",									sub->id, msgid, sub->lastout);							found = 1;							break;						}						sub = sub->next;					} while (sub != p->sub);					if (found) {						break;					}#endif					/* SC */					sub = p->sub;					found = 1;					/* SC */					break;				} else if (name && !strcasecmp(p->name, tmp)) {					ast_log(LOG_DEBUG, "Coundn't determine subchannel, assuming current master %s@%s-%d\n", 						p->name, g->name, p->sub->id);					sub = p->sub;					found = 1;					break;				}				p = p->next;			}			if (sub && found) {				ast_mutex_lock(&sub->lock);				break;			}		}		g = g->next;	}	ast_mutex_unlock(&gatelock);	if (!sub) {		if (name) {			if (g)				ast_log(LOG_NOTICE, "Endpoint '%s' not found on gateway '%s'\n", tmp, at);			else				ast_log(LOG_NOTICE, "Gateway '%s' (and thus its endpoint '%s') does not exist\n", at, tmp);		} 	}	return sub;}static void parse(struct mgcp_request *req){	/* Divide fields by NULL's */	char *c;	int f = 0;	c = req->data;	/* First header starts immediately */	req->header[f] = c;	while(*c) {		if (*c == '\n') {			/* We've got a new header */			*c = 0;#if 0			printf("Header: %s (%d)\n", req->header[f], strlen(req->header[f]));#endif						if (ast_strlen_zero(req->header[f])) {				/* Line by itself means we're now in content */				c++;				break;			}			if (f >= MGCP_MAX_HEADERS - 1) {				ast_log(LOG_WARNING, "Too many MGCP headers...\n");			} else				f++;			req->header[f] = c + 1;		} else if (*c == '\r') {			/* Ignore but eliminate \r's */			*c = 0;		}		c++;	}	/* Check for last header */	if (!ast_strlen_zero(req->header[f])) 		f++;	req->headers = f;	/* Now we process any mime content */	f = 0;	req->line[f] = c;	while(*c) {		if (*c == '\n') {			/* We've got a new line */			*c = 0;#if 0			printf("Line: %s (%d)\n", req->line[f], strlen(req->line[f]));#endif						if (f >= MGCP_MAX_LINES - 1) {				ast_log(LOG_WARNING, "Too many SDP lines...\n");			} else				f++;			req->line[f] = c + 1;		} else if (*c == '\r') {			/* Ignore and eliminate \r's */			*c = 0;		}		c++;	}	/* Check for last line */	if (!ast_strlen_zero(req->line[f])) 		f++;	req->lines = f;	/* Parse up the initial header */	c = req->header[0];	while(*c && *c < 33) c++;	/* First the verb */	req->verb = c;	while(*c && (*c > 32)) c++;	if (*c) {		*c = '\0';		c++;		while(*c && (*c < 33)) c++;		req->identifier = c;		while(*c && (*c > 32)) c++;		if (*c) {			*c = '\0';			c++;			while(*c && (*c < 33)) c++;			req->endpoint = c;			while(*c && (*c > 32)) c++;			if (*c) {				*c = '\0';				c++;				while(*c && (*c < 33)) c++;				req->version = c;				while(*c && (*c > 32)) c++;				while(*c && (*c < 33)) c++;				while(*c && (*c > 32)) c++;				*c = '\0';			}		}	}			if (mgcpdebug) {		ast_verbose("Verb: '%s', Identifier: '%s', Endpoint: '%s', Version: '%s'\n",			req->verb, req->identifier, req->endpoint, req->version);		ast_verbose("%d headers, %d lines\n", req->headers, req->lines);	}	if (*c) 		ast_log(LOG_WARNING, "Odd content, extra stuff left over ('%s')\n", c);}static int process_sdp(struct mgcp_subchannel *sub, struct mgcp_request *req){	char *m;	char *c;	char *a;	char host[258];	int len;	int portno;	int peercapability, peerNonCodecCapability;	struct sockaddr_in sin;	char *codecs;	struct ast_hostent ahp; struct hostent *hp;	int codec, codec_count=0;	int iterator;	struct mgcp_endpoint *p = sub->parent;	/* Get codec and RTP info from SDP */	m = get_sdp(req, "m");	c = get_sdp(req, "c");	if (ast_strlen_zero(m) || ast_strlen_zero(c)) {		ast_log(LOG_WARNING, "Insufficient information for SDP (m = '%s', c = '%s')\n", m, c);		return -1;	}	if (sscanf(c, "IN IP4 %256s", host) != 1) {		ast_log(LOG_WARNING, "Invalid host in c= line, '%s'\n", c);		return -1;	}	/* XXX This could block for a long time, and block the main thread! XXX */	hp = ast_gethostbyname(host, &ahp);	if (!hp) {		ast_log(LOG_WARNING, "Unable to lookup host in c= line, '%s'\n", c);		return -1;	}	if (sscanf(m, "audio %d RTP/AVP %n", &portno, &len) != 1) {		ast_log(LOG_WARNING, "Unable to determine port number for RTP in '%s'\n", m); 		return -1;	}	sin.sin_family = AF_INET;	memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));	sin.sin_port = htons(portno);	ast_rtp_set_peer(sub->rtp, &sin);#if 0	printf("Peer RTP is at port %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));#endif		/* Scan through the RTP payload types specified in a "m=" line: */	ast_rtp_pt_clear(sub->rtp);	codecs = ast_strdupa(m + len);	while (!ast_strlen_zero(codecs)) {		if (sscanf(codecs, "%d%n", &codec, &len) != 1) {			if (codec_count)				break;			ast_log(LOG_WARNING, "Error in codec string '%s' at '%s'\n", m, codecs);			return -1;		}		ast_rtp_set_m_type(sub->rtp, codec);		codec_count++;		codecs += len;	}	/* Next, scan through each "a=rtpmap:" line, noting each */	/* specified RTP payload type (with corresponding MIME subtype): */	sdpLineNum_iterator_init(&iterator);	while ((a = get_sdp_iterate(&iterator, req, "a"))[0] != '\0') {		char* mimeSubtype = ast_strdupa(a); /* ensures we have enough space */		if (sscanf(a, "rtpmap: %u %[^/]/", &codec, mimeSubtype) != 2)			continue;		/* Note: should really look at the 'freq' and '#chans' params too */		ast_rtp_set_rtpmap_type(sub->rtp, codec, "audio", mimeSubtype, 0);	}	/* Now gather all of the codecs that were asked for: */	ast_rtp_get_current_formats(sub->rtp, &peercapability, &peerNonCodecCapability);

⌨️ 快捷键说明

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