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

📄 q931.c

📁 This a software PBX driver
💻 C
📖 第 1 页 / 共 5 页
字号:
	q931_call *cur, *prev;	prev = NULL;	cur = *pri->callpool;	while(cur) {		if ((c && (cur == c)) || (!c && (cur->cr == cr))) {			if (prev)				prev->next = cur->next;			else				*pri->callpool = cur->next;			if (pri->debug & PRI_DEBUG_Q931_STATE)				pri_message("NEW_HANGUP DEBUG: Destroying the call, ourstate %s, peerstate %s\n",callstate2str(cur->ourcallstate),callstate2str(cur->peercallstate));			if (cur->retranstimer)				pri_schedule_del(pri, cur->retranstimer);			free(cur);			return;		}		prev = cur;		cur = cur->next;	}	pri_error("Can't destroy call %d!\n", cr);}static void q931_destroycall(struct pri *pri, int cr){	return q931_destroy(pri, cr, NULL);}void __q931_destroycall(struct pri *pri, q931_call *c) {	if (pri && c)		q931_destroy(pri,0, c);	return;}static int add_ie(struct pri *pri, q931_call *call, int msgtype, int ie, q931_ie *iet, int maxlen, int *codeset){	unsigned int x;	int res;	int have_shift;	for (x=0;x<sizeof(ies) / sizeof(ies[0]);x++) {		if (ies[x].ie == ie) {			/* This is our baby */			if (ies[x].transmit) {				/* Prepend with CODE SHIFT IE if required */				if (*codeset != Q931_IE_CODESET(ies[x].ie)) {					/* Locking shift to codeset 0 isn't possible */					iet->ie = Q931_IE_CODESET(ies[x].ie) | (Q931_IE_CODESET(ies[x].ie) ? Q931_LOCKING_SHIFT : Q931_NON_LOCKING_SHIFT);					have_shift = 1;					iet = (q931_ie *)((char *)iet + 1);					maxlen--;				}				else					have_shift = 0;				iet->ie = ie;				res = ies[x].transmit(ie, pri, call, msgtype, iet, maxlen);				/* Error if res < 0 or ignored if res == 0 */				if (res <= 0)					return res;				if ((iet->ie & 0x80) == 0) /* Multibyte IE */					iet->len = res - 2;				if (have_shift) {					if (Q931_IE_CODESET(ies[x].ie))						*codeset = Q931_IE_CODESET(ies[x].ie);					return res + 1; /* Shift is single-byte IE */				}				return res;			} else {				pri_error("!! Don't know how to add an IE %s (%d)\n", ie2str(ie), ie);				return -1;			}		}	}	pri_error("!! Unknown IE %d (%s)\n", ie, ie2str(ie));	return -1;}static char *disc2str(int disc){	static struct msgtype discs[] = {		{ Q931_PROTOCOL_DISCRIMINATOR, "Q.931" },		{ GR303_PROTOCOL_DISCRIMINATOR, "GR-303" },		{ 0x3, "AT&T Maintenance" },		{ 0x43, "New AT&T Maintenance" },	};	return code2str(disc, discs, sizeof(discs) / sizeof(discs[0]));}void q931_dump(q931_h *h, int len, int txrx){	q931_mh *mh;	char c;	int x=0, r;	int cur_codeset;	int codeset;	c = txrx ? '>' : '<';	pri_message("%c Protocol Discriminator: %s (%d)  len=%d\n", c, disc2str(h->pd), h->pd, len);	pri_message("%c Call Ref: len=%2d (reference %d/0x%X) (%s)\n", c, h->crlen, q931_cr(h), q931_cr(h), (h->crv[0] & 0x80) ? "Terminator" : "Originator");	/* Message header begins at the end of the call reference number */	mh = (q931_mh *)(h->contents + h->crlen);	pri_message("%c Message type: %s (%d)\n", c, msg2str(mh->msg), mh->msg);	/* Drop length of header, including call reference */	len -= (h->crlen + 3);	codeset = cur_codeset = 0;	while(x < len) {		r = ielen((q931_ie *)(mh->data + x));		q931_dumpie(cur_codeset, (q931_ie *)(mh->data + x), c);		switch (mh->data[x] & 0xf8) {		case Q931_LOCKING_SHIFT:			if ((mh->data[x] & 7) > 0)				codeset = cur_codeset = mh->data[x] & 7;			break;		case Q931_NON_LOCKING_SHIFT:			cur_codeset = mh->data[x] & 7;			break;		default:			/* Reset temporary codeset change */			cur_codeset = codeset;		}		x += r;	}	if (x > len) 		pri_error("XXX Message longer than it should be?? XXX\n");}static int q931_handle_ie(int codeset, struct pri *pri, q931_call *c, int msg, q931_ie *ie){	unsigned int x;	int full_ie = Q931_FULL_IE(codeset, ie->ie);	if (pri->debug & PRI_DEBUG_Q931_STATE)		pri_message("-- Processing IE %d (cs%d, %s)\n", ie->ie, codeset, ie2str(full_ie));	for (x=0;x<sizeof(ies) / sizeof(ies[0]);x++) {		if (full_ie == ies[x].ie) {			if (ies[x].receive)				return ies[x].receive(full_ie, pri, c, msg, ie, ielen(ie));			else {				if (pri->debug & PRI_DEBUG_Q931_ANOMALY)					pri_error("!! No handler for IE %d (cs%d, %s)\n", ie->ie, codeset, ie2str(full_ie));				return -1;			}		}	}	pri_message("!! Unknown IE %d (cs%d, %s)\n", ie->ie, codeset, ie2str(full_ie));	return -1;}static void init_header(struct pri *pri, q931_call *call, char *buf, q931_h **hb, q931_mh **mhb, int *len){	/* Returns header and message header and modifies length in place */	q931_h *h = (q931_h *)buf;	q931_mh * mh = (q931_mh *)(h->contents + 2);	h->pd = pri->protodisc;	h->x0 = 0;		/* Reserved 0 */	h->crlen = 2;	/* Two bytes of Call Reference.  Invert the top bit to make it from our sense */	if (call->cr || call->forceinvert) {		h->crv[0] = ((call->cr ^ 0x8000) & 0xff00) >> 8;		h->crv[1] = (call->cr & 0xff);	} else {		/* Unless of course this has no call reference */		h->crv[0] = 0;		h->crv[1] = 0;	}	if (pri->subchannel) {		/* On GR-303, top bit is always 0 */		h->crv[0] &= 0x7f;	}	mh->f = 0;	*hb = h;	*mhb = mh;	*len -= 5;	}static int q931_xmit(struct pri *pri, q931_h *h, int len, int cr){	q921_transmit_iframe(pri, h, len, cr);	/* The transmit operation might dump the q921 header, so logging the q931	   message body after the transmit puts the sections of the message in the	   right order in the log */	if (pri->debug & PRI_DEBUG_Q931_DUMP)		q931_dump(h, len, 1);#ifdef LIBPRI_COUNTERS	pri->q931_txcount++;#endif	return 0;}static int send_message(struct pri *pri, q931_call *c, int msgtype, int ies[]){	unsigned char buf[1024];	q931_h *h;	q931_mh *mh;	int len;	int res;	int offset=0;	int x;	int codeset;	memset(buf, 0, sizeof(buf));	len = sizeof(buf);	init_header(pri, c, buf, &h, &mh, &len);	mh->msg = msgtype;	x=0;	codeset = 0;	while(ies[x] > -1) {		res = add_ie(pri, c, mh->msg, ies[x], (q931_ie *)(mh->data + offset), len, &codeset);		if (res < 0) {			pri_error("!! Unable to add IE '%s'\n", ie2str(ies[x]));			return -1;		}		offset += res;		len -= res;		x++;	}	/* Invert the logic */	len = sizeof(buf) - len;	q931_xmit(pri, h, len, 1);	c->acked = 1;	return 0;}static int status_ies[] = { Q931_CAUSE, Q931_CALL_STATE, -1 };static int q931_status(struct pri *pri, q931_call *c, int cause){	q931_call *cur = NULL;	if (!cause)		cause = PRI_CAUSE_RESPONSE_TO_STATUS_ENQUIRY;	if (c->cr > -1)		cur = *pri->callpool;	while(cur) {		if (cur->cr == c->cr) {			cur->cause=cause;			cur->causecode = CODE_CCITT;			cur->causeloc = LOC_USER;			break;		}		cur = cur->next;	}	if (!cur) {		pri_message("YYY Here we get reset YYY\n");		/* something went wrong, respond with "no such call" */		c->ourcallstate = Q931_CALL_STATE_NULL;		c->peercallstate = Q931_CALL_STATE_NULL;		cur=c;	}	return send_message(pri, cur, Q931_STATUS, status_ies);}static int information_ies[] = { Q931_CALLED_PARTY_NUMBER, -1 };int q931_information(struct pri *pri, q931_call *c, char digit){	c->callednum[0]=digit;	c->callednum[1]='\0';	return send_message(pri, c, Q931_INFORMATION, information_ies);}static int restart_ack_ies[] = { Q931_CHANNEL_IDENT, Q931_RESTART_INDICATOR, -1 };static int restart_ack(struct pri *pri, q931_call *c){	c->ourcallstate = Q931_CALL_STATE_NULL;	c->peercallstate = Q931_CALL_STATE_NULL;	return send_message(pri, c, Q931_RESTART_ACKNOWLEDGE, restart_ack_ies);}static int notify_ies[] = { Q931_IE_NOTIFY_IND, -1 };int q931_notify(struct pri *pri, q931_call *c, int channel, int info){	if (info >= 0)		c->notify = info & 0x7F;	else		c->notify = -1;	return send_message(pri, c, Q931_NOTIFY, notify_ies);}#ifdef ALERTING_NO_PROGRESSstatic int call_progress_ies[] = { -1 };#elsestatic int call_progress_ies[] = { Q931_PROGRESS_INDICATOR, -1 };#endifint q931_call_progress(struct pri *pri, q931_call *c, int channel, int info){	if (channel) { 		c->ds1no = (channel & 0xff00) >> 8;		channel &= 0xff;		c->channelno = channel;			}	if (info) {		c->progloc = LOC_PRIV_NET_LOCAL_USER;		c->progcode = CODE_CCITT;		c->progress = Q931_PROG_INBAND_AVAILABLE;	} else		c->progress = -1;	c->alive = 1;	return send_message(pri, c, Q931_PROGRESS, call_progress_ies);}#ifdef ALERTING_NO_PROGRESSstatic int call_proceeding_ies[] = { Q931_CHANNEL_IDENT, -1 };#elsestatic int call_proceeding_ies[] = { Q931_CHANNEL_IDENT, Q931_PROGRESS_INDICATOR, -1 };#endifint q931_call_proceeding(struct pri *pri, q931_call *c, int channel, int info){	if (channel) { 		c->ds1no = (channel & 0xff00) >> 8;		channel &= 0xff;		c->channelno = channel;			}	c->chanflags &= ~FLAG_PREFERRED;	c->chanflags |= FLAG_EXCLUSIVE;	c->ourcallstate = Q931_CALL_STATE_INCOMING_CALL_PROCEEDING;	c->peercallstate = Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING;	if (info) {		c->progloc = LOC_PRIV_NET_LOCAL_USER;		c->progcode = CODE_CCITT;		c->progress = Q931_PROG_INBAND_AVAILABLE;	} else		c->progress = -1;	c->proc = 1;	c->alive = 1;	return send_message(pri, c, Q931_CALL_PROCEEDING, call_proceeding_ies);}#ifndef ALERTING_NO_PROGRESSstatic int alerting_ies[] = { Q931_PROGRESS_INDICATOR, -1 };#elsestatic int alerting_ies[] = { -1 };#endifint q931_alerting(struct pri *pri, q931_call *c, int channel, int info){	if (!c->proc) 		q931_call_proceeding(pri, c, channel, 0);	if (info) {		c->progloc = LOC_PRIV_NET_LOCAL_USER;		c->progcode = CODE_CCITT;		c->progress = Q931_PROG_INBAND_AVAILABLE;	} else		c->progress = -1;	c->ourcallstate = Q931_CALL_STATE_CALL_RECEIVED;	c->peercallstate = Q931_CALL_STATE_CALL_DELIVERED;	c->alive = 1;	return send_message(pri, c, Q931_ALERTING, alerting_ies);}static int connect_ies[] = {  Q931_CHANNEL_IDENT, Q931_PROGRESS_INDICATOR, -1 }; int q931_setup_ack(struct pri *pri, q931_call *c, int channel, int nonisdn){	if (channel) { 		c->ds1no = (channel & 0xff00) >> 8;		channel &= 0xff;		c->channelno = channel;			}	c->chanflags &= ~FLAG_PREFERRED;	c->chanflags |= FLAG_EXCLUSIVE;	if (nonisdn && (pri->switchtype != PRI_SWITCH_DMS100)) {		c->progloc  = LOC_PRIV_NET_LOCAL_USER;		c->progcode = CODE_CCITT;		c->progress = Q931_PROG_CALLED_NOT_ISDN;	} else		c->progress = -1;	c->ourcallstate = Q931_CALL_STATE_OVERLAP_RECEIVING;	c->peercallstate = Q931_CALL_STATE_OVERLAP_SENDING;	c->alive = 1;	return send_message(pri, c, Q931_SETUP_ACKNOWLEDGE, connect_ies);}static void pri_connect_timeout(void *data){	struct q931_call *c = data;	struct pri *pri = c->pri;	if (pri->debug & PRI_DEBUG_Q931_STATE)		pri_message("Timed out looking for connect acknowledge\n");	q931_disconnect(pri, c, PRI_CAUSE_NORMAL_CLEARING);	}static void pri_release_timeout(void *data){	struct q931_call *c = data;	struct pri *pri = c->pri;	if (pri->debug & PRI_DEBUG_Q931_STATE)		pri_message("Timed out looking for release complete\n");	c->t308_timedout++;	c->alive = 1;	q931_release(pri, c, PRI_CAUSE_NORMAL_CLEARING);}static void pri_release_finaltimeout(void *data){	struct q931_call *c = data;	struct pri *pri = c->pri;	c->alive = 1;	if (pri->debug & PRI_DEBUG_Q931_STATE)		pri_message("Final time-out looking for release complete\n");	c->t308_timedout++;	c->ourcallstate = Q931_CALL_STATE_NULL;	c->peercallstate = Q931_CALL_STATE_NULL;	pri->schedev = 1;	pri->ev.e = PRI_EVENT_HANGUP_ACK;	pri->ev.hangup.channel = c->channelno;	pri->ev.hangup.cref = c->cr;	pri->ev.hangup.cause = c->cause;	pri->ev.hangup.call = c;	q931_hangup(pri, c, c->cause);}static void pri_disconnect_timeout(void *data){	struct q931_call *c = data;	struct pri *pri = c->pri;	if (pri->debug & PRI_DEBUG_Q931_STATE)		p

⌨️ 快捷键说明

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