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

📄 pri.c

📁 Q.931/Q.921 source code compiles
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * libpri: An implementation of Primary Rate ISDN * * Written by Mark Spencer <markster@digium.com> * * Copyright (C) 2001-2005, Digium, Inc. * All Rights Reserved. *//* * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2 as published by the * Free Software Foundation. See the LICENSE file included with * this program for more details. * * In addition, when this program is distributed with Asterisk in * any form that would qualify as a 'combined work' or as a * 'derivative work' (but not mere aggregation), you can redistribute * and/or modify the combination under the terms of the license * provided with that copy of Asterisk, instead of the license * terms granted here. */#include <unistd.h>#include <stdlib.h>#include <string.h>#include <errno.h>#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <sys/select.h>#include <stdarg.h>#include "compat.h"#include "libpri.h"#include "pri_internal.h"#include "pri_facility.h"#include "pri_q921.h"#include "pri_q931.h"#include "pri_timers.h"char *pri_node2str(int node){	switch(node) {	case PRI_UNKNOWN:		return "Unknown node type";	case PRI_NETWORK:		return "Network";	case PRI_CPE:		return "CPE";	default:		return "Invalid value";	}}char *pri_switch2str(int sw){	switch(sw) {	case PRI_SWITCH_NI2:		return "National ISDN";	case PRI_SWITCH_DMS100:		return "Nortel DMS100";	case PRI_SWITCH_LUCENT5E:		return "Lucent 5E";	case PRI_SWITCH_ATT4ESS:		return "AT&T 4ESS";	case PRI_SWITCH_NI1:		return "National ISDN 1";	case PRI_SWITCH_EUROISDN_E1:		return "EuroISDN";	case PRI_SWITCH_GR303_EOC:		return "GR303 EOC";	case PRI_SWITCH_GR303_TMC:		return "GR303 TMC";	case PRI_SWITCH_QSIG:		return "Q.SIG switch";	default:		return "Unknown switchtype";	}}static void pri_default_timers(struct pri *pri, int switchtype){	static const int defaulttimers[20][PRI_MAX_TIMERS] = PRI_TIMERS_ALL;	int x;	for (x = 0; x<PRI_MAX_TIMERS; x++) {		pri->timers[x] = defaulttimers[switchtype][x];	}}int pri_set_timer(struct pri *pri, int timer, int value){	if (timer < 0 || timer > PRI_MAX_TIMERS || value < 0)		return -1;	pri->timers[timer] = value;	return 0;}int pri_get_timer(struct pri *pri, int timer){	if (timer < 0 || timer > PRI_MAX_TIMERS)		return -1;	return pri->timers[timer];}int pri_timer2idx(char *timer){	if (!strcasecmp(timer, "N200"))		return PRI_TIMER_N200;	else if (!strcasecmp(timer, "N201"))		return PRI_TIMER_N201;	else if (!strcasecmp(timer, "N202"))		return PRI_TIMER_N202;	else if (!strcasecmp(timer, "K"))		return PRI_TIMER_K;	else if (!strcasecmp(timer, "T200"))		return PRI_TIMER_T200;	else if (!strcasecmp(timer, "T202"))		return PRI_TIMER_T202;	else if (!strcasecmp(timer, "T203"))		return PRI_TIMER_T203;	else if (!strcasecmp(timer, "T300"))		return PRI_TIMER_T300;	else if (!strcasecmp(timer, "T301"))		return PRI_TIMER_T301;	else if (!strcasecmp(timer, "T302"))		return PRI_TIMER_T302;	else if (!strcasecmp(timer, "T303"))		return PRI_TIMER_T303;	else if (!strcasecmp(timer, "T304"))		return PRI_TIMER_T304;	else if (!strcasecmp(timer, "T305"))		return PRI_TIMER_T305;	else if (!strcasecmp(timer, "T306"))		return PRI_TIMER_T306;	else if (!strcasecmp(timer, "T307"))		return PRI_TIMER_T307;	else if (!strcasecmp(timer, "T308"))		return PRI_TIMER_T308;	else if (!strcasecmp(timer, "T309"))		return PRI_TIMER_T309;	else if (!strcasecmp(timer, "T310"))		return PRI_TIMER_T310;	else if (!strcasecmp(timer, "T313"))		return PRI_TIMER_T313;	else if (!strcasecmp(timer, "T314"))		return PRI_TIMER_T314;	else if (!strcasecmp(timer, "T316"))		return PRI_TIMER_T316;	else if (!strcasecmp(timer, "T317"))		return PRI_TIMER_T317;	else if (!strcasecmp(timer, "T318"))		return PRI_TIMER_T318;	else if (!strcasecmp(timer, "T319"))		return PRI_TIMER_T319;	else if (!strcasecmp(timer, "T320"))		return PRI_TIMER_T320;	else if (!strcasecmp(timer, "T321"))		return PRI_TIMER_T321;	else if (!strcasecmp(timer, "T322"))		return PRI_TIMER_T322;	else		return -1;}static int __pri_read(struct pri *pri, void *buf, int buflen){	int res = read(pri->fd, buf, buflen);	if (res < 0) {		if (errno != EAGAIN)			pri_error(pri, "Read on %d failed: %s\n", pri->fd, strerror(errno));		return 0;	}	return res;}static int __pri_write(struct pri *pri, void *buf, int buflen){	int res = write(pri->fd, buf, buflen);	if (res < 0) {		if (errno != EAGAIN)			pri_error(pri, "Write to %d failed: %s\n", pri->fd, strerror(errno));		return 0;	}	return res;}/* Pass in the master for this function */void __pri_free_tei(struct pri * p){	free (p);}struct pri *__pri_new_tei(int fd, int node, int switchtype, struct pri *master, pri_io_cb rd, pri_io_cb wr, void *userdata, int tei, int bri){	struct pri *p;	if (!(p = calloc(1, sizeof(*p))))		return NULL;	p->bri = bri;	p->fd = fd;	p->read_func = rd;	p->write_func = wr;	p->userdata = userdata;	p->localtype = node;	p->switchtype = switchtype;	p->cref = 1;	p->sapi = (tei == Q921_TEI_GROUP) ? Q921_SAPI_LAYER2_MANAGEMENT : Q921_SAPI_CALL_CTRL;	p->tei = tei;	p->nsf = PRI_NSF_NONE;	p->protodisc = Q931_PROTOCOL_DISCRIMINATOR;	p->master = master;	p->callpool = &p->localpool;	pri_default_timers(p, switchtype);	if (master) {		pri_set_debug(p, master->debug);		if (master->sendfacility)			pri_facility_enable(p);	}#ifdef LIBPRI_COUNTERS	p->q921_rxcount = 0;	p->q921_txcount = 0;	p->q931_rxcount = 0;	p->q931_txcount = 0;#endif	if (switchtype == PRI_SWITCH_GR303_EOC) {		p->protodisc = GR303_PROTOCOL_DISCRIMINATOR;		p->sapi = Q921_SAPI_GR303_EOC;		p->tei = Q921_TEI_GR303_EOC_OPS;		p->subchannel = __pri_new_tei(-1, node, PRI_SWITCH_GR303_EOC_PATH, p, NULL, NULL, NULL, Q921_TEI_GR303_EOC_PATH, 0);		if (!p->subchannel) {			free(p);			p = NULL;		}	} else if (switchtype == PRI_SWITCH_GR303_TMC) {		p->protodisc = GR303_PROTOCOL_DISCRIMINATOR;		p->sapi = Q921_SAPI_GR303_TMC_CALLPROC;		p->tei = Q921_TEI_GR303_TMC_CALLPROC;		p->subchannel = __pri_new_tei(-1, node, PRI_SWITCH_GR303_TMC_SWITCHING, p, NULL, NULL, NULL, Q921_TEI_GR303_TMC_SWITCHING, 0);		if (!p->subchannel) {			free(p);			p = NULL;		}	} else if (switchtype == PRI_SWITCH_GR303_TMC_SWITCHING) {		p->protodisc = GR303_PROTOCOL_DISCRIMINATOR;		p->sapi = Q921_SAPI_GR303_TMC_SWITCHING;		p->tei = Q921_TEI_GR303_TMC_SWITCHING;	} else if (switchtype == PRI_SWITCH_GR303_EOC_PATH) {		p->protodisc = GR303_PROTOCOL_DISCRIMINATOR;		p->sapi = Q921_SAPI_GR303_EOC;		p->tei = Q921_TEI_GR303_EOC_PATH;	}	/* Start Q.921 layer, Wait if we're the network */	if (p)		q921_start(p, p->localtype == PRI_CPE);		return p;}void pri_call_set_useruser(q931_call *c, const char *userchars){	if (userchars)		libpri_copy_string(c->useruserinfo, userchars, sizeof(c->useruserinfo));}void pri_sr_set_useruser(struct pri_sr *sr, const char *userchars){	sr->useruserinfo = userchars;}int pri_restart(struct pri *pri){	/* Restart Q.921 layer */	if (pri) {		q921_reset(pri);		q921_start(pri, pri->localtype == PRI_CPE);		}	return 0;}struct pri *pri_new(int fd, int nodetype, int switchtype){	return __pri_new_tei(fd, nodetype, switchtype, NULL, __pri_read, __pri_write, NULL, Q921_TEI_PRI, 0);}struct pri *pri_new_bri(int fd, int ptpmode, int nodetype, int switchtype){	if (ptpmode)		return __pri_new_tei(fd, nodetype, switchtype, NULL, __pri_read, __pri_write, NULL, Q921_TEI_PRI, 1);	else		return __pri_new_tei(fd, nodetype, switchtype, NULL, __pri_read, __pri_write, NULL, Q921_TEI_GROUP, 1);}struct pri *pri_new_cb(int fd, int nodetype, int switchtype, pri_io_cb io_read, pri_io_cb io_write, void *userdata){	if (!io_read)		io_read = __pri_read;	if (!io_write)		io_write = __pri_write;	return __pri_new_tei(fd, nodetype, switchtype, NULL, io_read, io_write, userdata, Q921_TEI_PRI, 0);}void *pri_get_userdata(struct pri *pri){	return pri ? pri->userdata : NULL;}void pri_set_userdata(struct pri *pri, void *userdata){	if (pri)		pri->userdata = userdata;}void pri_set_nsf(struct pri *pri, int nsf){	if (pri)		pri->nsf = nsf;}char *pri_event2str(int id){	switch(id) {	case PRI_EVENT_DCHAN_UP:		return "D-Channel Up";	case PRI_EVENT_DCHAN_DOWN:		return "D-channel Down";	case PRI_EVENT_RESTART:		return "Restart channel";	case PRI_EVENT_RING:		return "Ring";	case PRI_EVENT_HANGUP:		return "Hangup";	case PRI_EVENT_RINGING:		return "Ringing";	case PRI_EVENT_ANSWER:		return "Answer";	case PRI_EVENT_HANGUP_ACK:		return "Hangup ACK";	case PRI_EVENT_RESTART_ACK:		return "Restart ACK";	case PRI_EVENT_FACNAME:		return "FacName";	case PRI_EVENT_INFO_RECEIVED:		return "Info Received";	case PRI_EVENT_PROCEEDING:		return "Proceeding";	case PRI_EVENT_SETUP_ACK:		return "Setup ACK";	case PRI_EVENT_HANGUP_REQ:		return "Hangup Req";	case PRI_EVENT_NOTIFY:		return "Notify";	case PRI_EVENT_PROGRESS:		return "Progress";	case PRI_EVENT_CONFIG_ERR:		return "Configuration Error";	default:		return "Unknown Event";	}}pri_event *pri_check_event(struct pri *pri){	char buf[1024];	int res;	pri_event *e;	res = pri->read_func ? pri->read_func(pri, buf, sizeof(buf)) : 0;	if (!res)		return NULL;	/* Receive the q921 packet */	e = q921_receive(pri, (q921_h *)buf, res);	return e;}static int wait_pri(struct pri *pri){		struct timeval *tv, real;	fd_set fds;	int res;	FD_ZERO(&fds);	FD_SET(pri->fd, &fds);	tv = pri_schedule_next(pri);	if (tv) {		gettimeofday(&real, NULL);		real.tv_sec = tv->tv_sec - real.tv_sec;		real.tv_usec = tv->tv_usec - real.tv_usec;		if (real.tv_usec < 0) {			real.tv_usec += 1000000;			real.tv_sec -= 1;		}		if (real.tv_sec < 0) {			real.tv_sec = 0;			real.tv_usec = 0;		}	}	res = select(pri->fd + 1, &fds, NULL, NULL, tv ? &real : tv);	if (res < 0) 		return -1;	return res;}pri_event *pri_mkerror(struct pri *pri, char *errstr){	/* Return a configuration error */	pri->ev.err.e = PRI_EVENT_CONFIG_ERR;	libpri_copy_string(pri->ev.err.err, errstr, sizeof(pri->ev.err.err));	return &pri->ev;}pri_event *pri_dchannel_run(struct pri *pri, int block){	pri_event *e;	int res;	if (!pri)		return NULL;	if (block) {		do {			e =  NULL;			res = wait_pri(pri);			/* Check for error / interruption */			if (res < 0)				return NULL;			if (!res)				e = pri_schedule_run(pri);			else				e = pri_check_event(pri);		} while(!e);	} else {		e = pri_check_event(pri);		return e;	}	return e;}void pri_set_debug(struct pri *pri, int debug){	if (!pri)		return;	pri->debug = debug;	if (pri->subchannel)		pri_set_debug(pri->subchannel, debug);}int pri_get_debug(struct pri *pri){	if (!pri)		return -1;	if (pri->subchannel)		return pri_get_debug(pri->subchannel);	return pri->debug;}void pri_facility_enable(struct pri *pri){	if (!pri)		return;	pri->sendfacility = 1;	if (pri->subchannel)		pri_facility_enable(pri->subchannel);	return;}

⌨️ 快捷键说明

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