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

📄 q921.c

📁 Q.931/Q.921 source code compiles
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * 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 <stdio.h>#include <string.h>#include <stdlib.h>#include <unistd.h>#include <errno.h>#include "compat.h"#include "libpri.h"#include "pri_internal.h"#include "pri_q921.h" #include "pri_q931.h"/* * Define RANDOM_DROPS To randomly drop packets in order to simulate loss for testing * retransmission functionality *//*#define RANDOM_DROPS*/#define Q921_INIT(pri, hf) do { \	memset(&(hf),0,sizeof(hf)); \	(hf).h.sapi = (pri)->sapi; \	(hf).h.ea1 = 0; \	(hf).h.ea2 = 1; \	(hf).h.tei = (pri)->tei; \} while(0)static void reschedule_t203(struct pri *pri);static void reschedule_t200(struct pri *pri);static void q921_restart(struct pri *pri, int now);static void q921_tei_release_and_reacquire(struct pri *master);static void q921_discard_retransmissions(struct pri *pri){	struct q921_frame *f, *p;	f = pri->txqueue;	while(f) {		p = f;		f = f->next;		/* Free frame */		free(p);	}	pri->txqueue = NULL;}static int q921_transmit(struct pri *pri, q921_h *h, int len) {	int res;	if (pri->master)		pri = pri->master;#ifdef RANDOM_DROPS   if (!(random() % 3)) {         pri_message(pri, " === Dropping Packet ===\n");         return 0;   }#endif   #ifdef LIBPRI_COUNTERS	pri->q921_txcount++;      #endif	/* Just send it raw */	if (pri->debug & (PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW))		q921_dump(pri, h, len, pri->debug & PRI_DEBUG_Q921_RAW, 1);	/* Write an extra two bytes for the FCS */	res = pri->write_func ? pri->write_func(pri, h, len + 2) : 0;	if (res != (len + 2)) {		pri_error(pri, "Short write: %d/%d (%s)\n", res, len + 2, strerror(errno));		return -1;	}	return 0;}static void q921_send_tei(struct pri *pri, int message, int ri, int ai, int iscommand){	q921_u *f;	if (!(f = calloc(1, sizeof(*f) + 5)))		return;	Q921_INIT(pri, *f);	f->h.c_r = (pri->localtype == PRI_NETWORK) ? iscommand : !iscommand;	f->ft = Q921_FRAMETYPE_U;	f->data[0] = 0x0f;	/* Management entity */	f->data[1] = (ri >> 8) & 0xff;	f->data[2] = ri & 0xff;	f->data[3] = message;	f->data[4] = (ai << 1) | 1;	if (pri->debug & PRI_DEBUG_Q921_STATE)		pri_message(pri, "Sending TEI management message %d, TEI=%d\n", message, ai);	q921_transmit(pri, (q921_h *)f, 8);	free(f);}static void q921_tei_request(void *vpri){	struct pri *pri = (struct pri *)vpri;	if (pri->subchannel) {		pri_error(pri, "Cannot request TEI while its already assigned\n");		return;	}	pri->n202_counter++;#if 0	if (pri->n202_counter > pri->timers[PRI_TIMER_N202]) {		pri_error(pri, "Unable to assign TEI from network\n");		return;	}#endif	pri->ri = random() % 65535;	q921_send_tei(pri, Q921_TEI_IDENTITY_REQUEST, pri->ri, Q921_TEI_GROUP, 1);	if (pri->t202_timer)		pri_schedule_del(pri, pri->t202_timer);	pri->t202_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T202], q921_tei_request, pri);}static void q921_send_ua(struct pri *pri, int pfbit){	q921_h h;	Q921_INIT(pri, h);	h.u.m3 = 3;		/* M3 = 3 */	h.u.m2 = 0;		/* M2 = 0 */	h.u.p_f = pfbit;	/* Final bit on */	h.u.ft = Q921_FRAMETYPE_U;	switch(pri->localtype) {	case PRI_NETWORK:		h.h.c_r = 0;		break;	case PRI_CPE:		h.h.c_r = 1;		break;	default:		pri_error(pri, "Don't know how to U/A on a type %d node\n", pri->localtype);		return;	}	if (pri->debug & (PRI_DEBUG_Q921_STATE | PRI_DEBUG_Q921_DUMP))		pri_message(pri, "Sending Unnumbered Acknowledgement\n");	q921_transmit(pri, &h, 3);}static void q921_send_sabme_now(void *vpri);static void q921_send_sabme(void *vpri, int now){	struct pri *pri = vpri;	q921_h h;	pri_schedule_del(pri, pri->sabme_timer);	pri->sabme_timer = 0;	pri->sabme_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T200], q921_send_sabme_now, pri);	if (!now)		return;	Q921_INIT(pri, h);	h.u.m3 = 3;	/* M3 = 3 */	h.u.m2 = 3;	/* M2 = 3 */	h.u.p_f = 1;	/* Poll bit set */	h.u.ft = Q921_FRAMETYPE_U;	switch(pri->localtype) {	case PRI_NETWORK:		h.h.c_r = 1;		break;	case PRI_CPE:		h.h.c_r = 0;		break;	default:		pri_error(pri, "Don't know how to U/A on a type %d node\n", pri->localtype);		return;	}	if (pri->bri && (pri->state == Q921_AWAITING_ESTABLISH)) {		if (pri->sabme_count >= pri->timers[PRI_TIMER_N200]) {			pri_schedule_del(pri, pri->sabme_timer);			pri->sabme_timer = 0;			q921_tei_release_and_reacquire(pri->master);		} else {			pri->sabme_count++;		}	}	if (pri->debug & (PRI_DEBUG_Q921_STATE | PRI_DEBUG_Q921_DUMP))		pri_message(pri, "Sending Set Asynchronous Balanced Mode Extended\n");	q921_transmit(pri, &h, 3);	if (pri->debug & PRI_DEBUG_Q921_STATE && pri->q921_state != Q921_AWAITING_ESTABLISH)		pri_message(pri, DBGHEAD "q921_state now is Q921_AWAITING_ESTABLISH\n", DBGINFO);	pri->q921_state = Q921_AWAITING_ESTABLISH;}static void q921_send_sabme_now(void *vpri){	q921_send_sabme(vpri, 1);}static int q921_ack_packet(struct pri *pri, int num){	struct q921_frame *f, *prev = NULL;	f = pri->txqueue;	while(f) {		if (f->h.n_s == num) {			/* Cancel each packet as necessary */			/* That's our packet */			if (prev)				prev->next = f->next;			else				pri->txqueue = f->next;			if (pri->debug & PRI_DEBUG_Q921_DUMP)				pri_message(pri, "-- ACKing packet %d, new txqueue is %d (-1 means empty)\n", f->h.n_s, pri->txqueue ? pri->txqueue->h.n_s : -1);			/* Update v_a */			pri->v_a = num;			free(f);			/* Reset retransmission counter if we actually acked something */			pri->retrans = 0;			/* Decrement window size */			pri->windowlen--;			return 1;		}		prev = f;		f = f->next;	}	return 0;}static void t203_expire(void *);static void t200_expire(void *);static pri_event *q921_dchannel_down(struct pri *pri);static void reschedule_t200(struct pri *pri){	if (pri->debug & PRI_DEBUG_Q921_DUMP)		pri_message(pri, "-- Restarting T200 timer\n");	if (pri->t200_timer)		pri_schedule_del(pri, pri->t200_timer);	pri->t200_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri);}static void reschedule_t203(struct pri *pri){	if (pri->debug & PRI_DEBUG_Q921_DUMP)		pri_message(pri, "-- Restarting T203 timer\n");	if (pri->t203_timer) 		pri_schedule_del(pri, pri->t203_timer);	pri->t203_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T203], t203_expire, pri);}static pri_event *q921_ack_rx(struct pri *pri, int ack, int send_untransmitted_frames){	int x;	int cnt=0;	pri_event *ev;	struct q921_frame *f;	/* Make sure the ACK was within our window */	for (x=pri->v_a; (x != pri->v_s) && (x != ack); Q921_INC(x));	if (x != ack) {		/* ACK was outside of our window --- ignore */		pri_error(pri, "ACK received for '%d' outside of window of '%d' to '%d', restarting\n", ack, pri->v_a, pri->v_s);		ev = q921_dchannel_down(pri);		q921_start(pri, 1);		pri->schedev = 1;		return ev;	}	/* Cancel each packet as necessary */	if (pri->debug & PRI_DEBUG_Q921_DUMP)		pri_message(pri, "-- ACKing all packets from %d to (but not including) %d\n", pri->v_a, ack);	for (x=pri->v_a; x != ack; Q921_INC(x)) 		cnt += q921_ack_packet(pri, x);		if (!pri->txqueue) {		if (pri->debug & PRI_DEBUG_Q921_DUMP)			pri_message(pri, "-- Since there was nothing left, stopping T200 counter\n");		/* Something was ACK'd.  Stop T200 counter */		if (pri->t200_timer) {			pri_schedule_del(pri, pri->t200_timer);			pri->t200_timer = 0;		}	}	if (pri->t203_timer) {		if (pri->debug & PRI_DEBUG_Q921_DUMP)			pri_message(pri, "-- Stopping T203 counter since we got an ACK\n");		pri_schedule_del(pri, pri->t203_timer);		pri->t203_timer = 0;	}	if (pri->txqueue) {		/* Something left to transmit, Start the T200 counter again if we stopped it */		if (!pri->busy && send_untransmitted_frames) {			pri->retrans = 0;			/* Search for something to send */			f = pri->txqueue;			while(f && (pri->windowlen < pri->window)) {				if (!f->transmitted) {					/* Send it now... */					if (pri->debug & PRI_DEBUG_Q921_DUMP)						pri_message(pri, "-- Finally transmitting %d, since window opened up (%d)\n", f->h.n_s, pri->windowlen);					f->transmitted++;					pri->windowlen++;					f->h.n_r = pri->v_r;					f->h.p_f = 0;					q921_transmit(pri, (q921_h *)(&f->h), f->len);				}				f = f->next;			}		}		if (pri->debug & PRI_DEBUG_Q921_DUMP)			pri_message(pri, "-- Waiting for acknowledge, restarting T200 counter\n");				reschedule_t200(pri);	} else {		if (pri->debug & PRI_DEBUG_Q921_DUMP)			pri_message(pri, "-- Nothing left, starting T203 counter\n");		/* Nothing to transmit, start the T203 counter instead */		pri->t203_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T203], t203_expire, pri);	}	return NULL;}static void q921_reject(struct pri *pri, int pf){	q921_h h;	Q921_INIT(pri, h);	h.s.x0 = 0;	/* Always 0 */	h.s.ss = 2;	/* Reject */	h.s.ft = 1;	/* Frametype (01) */	h.s.n_r = pri->v_r;	/* Where to start retransmission */	h.s.p_f = pf;		switch(pri->localtype) {	case PRI_NETWORK:		h.h.c_r = 0;		break;	case PRI_CPE:		h.h.c_r = 1;		break;	default:		pri_error(pri, "Don't know how to U/A on a type %d node\n", pri->localtype);		return;	}	if (pri->debug & PRI_DEBUG_Q921_DUMP)		pri_message(pri, "Sending Reject (%d)\n", pri->v_r);	pri->sentrej = 1;	q921_transmit(pri, &h, 4);}static void q921_rr(struct pri *pri, int pbit, int cmd) {	q921_h h;	Q921_INIT(pri, h);	h.s.x0 = 0;	/* Always 0 */	h.s.ss = 0; /* Receive Ready */	h.s.ft = 1;	/* Frametype (01) */	h.s.n_r = pri->v_r;	/* N/R */	h.s.p_f = pbit;		/* Poll/Final set appropriately */	switch(pri->localtype) {	case PRI_NETWORK:		if (cmd)			h.h.c_r = 1;		else			h.h.c_r = 0;		break;	case PRI_CPE:		if (cmd)			h.h.c_r = 0;		else			h.h.c_r = 1;		break;	default:		pri_error(pri, "Don't know how to U/A on a type %d node\n", pri->localtype);		return;	}	pri->v_na = pri->v_r;	/* Make a note that we've already acked this */	if (pri->debug & PRI_DEBUG_Q921_DUMP)		pri_message(pri, "Sending Receiver Ready (%d)\n", pri->v_r);	q921_transmit(pri, &h, 4);}static void t200_expire(void *vpri){	struct pri *pri = vpri;	q921_frame *f, *lastframe=NULL;	if (pri->txqueue) {		/* Retransmit first packet in the queue, setting the poll bit */		if (pri->debug & PRI_DEBUG_Q921_DUMP)			pri_message(pri, "-- T200 counter expired, What to do...\n");		pri->solicitfbit = 1;		/* Up to three retransmissions */		if (pri->retrans < pri->timers[PRI_TIMER_N200]) {			pri->retrans++;			/* Reschedule t200_timer */			if (pri->debug & PRI_DEBUG_Q921_DUMP)				pri_message(pri, "-- Retransmitting %d bytes\n", pri->txqueue->len);			if (pri->busy) 				q921_rr(pri, 1, 1);			else {				if (!pri->txqueue->transmitted) 					pri_error(pri, "!! Not good - head of queue has not been transmitted yet\n");				/*Actually we need to retransmit the last transmitted packet, setting the poll bit */				for (f=pri->txqueue; f; f = f->next) {					if (f->transmitted)						lastframe = f;				}				if (lastframe) {					/* Force Poll bit */

⌨️ 快捷键说明

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