Compare commits

..

2 Commits
1.4.5 ... 1.4.0

Author SHA1 Message Date
Kevin P. Fleming
437b249fbe importing files for 1.4.0 release
git-svn-id: https://origsvn.digium.com/svn/libpri/tags/1.4.0@384 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2006-12-23 14:35:11 +00:00
Kevin P. Fleming
d0084667a3 Creating tag for the release of libpri-1.4.0
git-svn-id: https://origsvn.digium.com/svn/libpri/tags/1.4.0@383 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2006-12-23 14:34:22 +00:00
17 changed files with 433 additions and 2123 deletions

View File

@@ -1 +1 @@
1.4.5
1.4.0

296
ChangeLog
View File

@@ -1,299 +1,3 @@
2008-07-11 Jason Parker <jparker@digium.com>
* Libpri 1.4.5 released.
2008-07-11 16:44 +0000 [r574-579] Kevin P. Fleming <kpfleming@digium.com>
* /: ignore generated files
* pri.c, pri_internal.h, q931.c, libpri.h: modify work done for
issue #10552, making the support of inband audio after RELEASE a
configurable option, since it is causing problems for a number of
users (closes issue #13042)
2008-06-04 17:02 +0000 [r562] Dwayne M. Hubbard <dhubbard@digium.com>
* q931.c: While working on issue 3450 I noticed that the
information channel selection field in the channel identification
IE was displayed incorrectly when using 'pri intense debug'. I
wanted another pair of eyes to look at the code because
everything looked correct until Shaun Ruffell noticed the missing
comma in the msg_chan_sel array.
2008-05-07 19:51 +0000 [r557] Matthew Fredrickson <creslin@digium.com>
* pri.c, pritest.c, pri_internal.h, pri_q921.h, Makefile, q921.c,
q931.c, pri_facility.c, prisched.c, testprilib.c, pri_timers.h,
pri_facility.h, libpri.h: Moving trunk changes back into 1.4
2008-05-07 Matthew Fredrickson <creslin@digium.com>
* Libpri 1.4.4 released.
2008-05-06 16:43 +0000 [r553-555] Matthew Fredrickson <creslin@digium.com>
* q921.c, pri.c: Remove some unnecessary debug messages
* q931.c: We passed TBR3 layer 2 and layer 3 testing with this
commit in for BRI-TE PTMP.
* q931.c: Final patch to pass certification
2008-04-22 15:30 +0000 [r546] Russell Bryant <russell@digium.com>
* Makefile: All versions of libpri have been installed as
libpri.so.1.0, even though the API and ABI have changed over
time. This patch changes the Makefile to install the library as
libpri.so.1.4 to indicate that this is not compatible with
previous versions. In the future, this should be changed as we
make ABI changes. (closes issue #10376) Reported by: tzafrir
Patches: libpri-soname.diff uploaded by tzafrir (license 46) --
with very minor changes by me
2008-03-15 19:57 +0000 [r541-543] Matthew Fredrickson <creslin@digium.com>
* libpri.h, pri.c: Remove some useless event items
* q921.c, pri_internal.h: Make sure if we're a bri and in PTMP mode
that we release the TEI and try to get a new one with the other
end when we lose activity in multiframe mode
* q921.c, pri.c, pri_q921.h: When we recieve a UA in any TEI
established state other than awaiting establishement make sure we
drop the TEI and get a new one. For passing tests PC37.2 - PC41.2
in Q.921
2008-03-06 23:43 +0000 [r538-539] Matthew Fredrickson <creslin@digium.com>
* q921.c: Make sure we are sending as command not as response
* q921.c: Make sure C/R bit is correct
2008-03-01 23:30 +0000 [r531-535] Matthew Fredrickson <creslin@digium.com>
* q921.c: Remove some (currently) useless code
* q921.c, pri.c, pri_internal.h: Some more updates to add code for
passing PC 27.1 in Q.921
* q921.c, pri.c: Various coding style cleanups as well as a bug fix
for TEI removal
* q921.c, q931.c, pri.c, pri_internal.h: Initial checkin of code to
pass Q.921 PC25 and PC26
* q921.c: Add support for responding to TEI requests (Q.921 PC23.x)
2008-02-18 20:31 +0000 [r525] Matthew Fredrickson <creslin@digium.com>
* q931.c, libpri.h: Improve transmission, receiving, and dumping of
bearer capability IE (#11593)
2008-01-16 18:06 +0000 [r518] Jason Parker <jparker@digium.com>
* Makefile, /: Add logging for 'make update' command (also fixes
updates in some places). Issue #11766, initial patch by jmls.
2007-12-26 17:35 +0000 [r505] Russell Bryant <russell@digium.com>
* libpri.h: Remove unnecessary usage of the extern keyword.
2007-12-06 22:16 +0000 [r494-496] Russell Bryant <russell@digium.com>
* q921.c, q931.c, pri_facility.c, pri.c: Change malloc+memset to
calloc. Also, handle allocation failures early to reduce
indentation. (closes issue #11469) Reported by: eliel Patches:
pri.c.patch uploaded by eliel (license 64) q931.c.patch uploaded
by eliel (license 64) q921.c.patch uploaded by eliel (license 64)
pri_facility.c.patch uploaded by eliel (license 64)
* pri.c: Change a use of malloc+memset to calloc. Also, reduce
indentation of a function by doing the check for memory
allocation failure at the beginning.
* pri.c: Change the table used to hold the default timers to be
global and const, instead of allocating it on the stack each time
the function is called.
2007-12-05 00:20 +0000 [r491-493] Matthew Fredrickson <creslin@digium.com>
* q931.c: Improve the parameter name to better reflect its use
* q921.c, q931.c: More PTMP fixes. Stand by, more changes to come
* q921.c, q931.c, testprilib.c: More magic to make BRI CPE PTMP
work
2007-11-21 22:30 +0000 [r486-487] Matthew Fredrickson <creslin@digium.com>
* q931.c: Make sure we loop BRI call references for one byte CREFs
instead of two
* q921.c, q931.c, libpri.h, pri.c, pritest.c, pri_internal.h: Add
BRI support to libpri
2007-10-13 16:00 +0000 [r473] Matthew Fredrickson <creslin@digium.com>
* q921.c: Make sure that we only output the message handling debug
when we're actually debugging
2007-09-25 21:56 +0000 [r469] Matthew Fredrickson <creslin@digium.com>
* q931.c: Fix user-user IE order in setup message (#10705)
2007-06-20 15:18 +0000 [r428-430] Matthew Fredrickson <creslin@digium.com>
* Makefile: Revert that back to how it was
* Makefile, q921.c, q931.c, prisched.c, testprilib.c, pri_timers.h,
libpri.h, pri.c, pri_internal.h, pri_q921.h: Patch to add PTMP
mode (BRI support)
2007-06-06 21:59 +0000 [r417-425] Matthew Fredrickson <creslin@digium.com>
* q931.c, pri_facility.c, pri_facility.h, pri.c, pri_internal.h:
Preliminary patch plus mods for Q.SIG Path Replacement (Q.SIG
version of 2BCT) #7778
2007-05-25 17:36 +0000 [r413] Matthew Fredrickson <creslin@digium.com>
* q931.c, pri_facility.c, pri_facility.h, libpri.h: Commit path for
ROSE-12 and ROSE-13 support (#9076)
2006-11-03 18:16 +0000 [r382] Matthew Fredrickson <creslin@digium.com>
* q921.c: Remove pointless recursion. (#8281)
2008-05-07 19:51 +0000 [r557] Matthew Fredrickson <creslin@digium.com>
* pri.c, pritest.c, pri_internal.h, pri_q921.h, Makefile, q921.c,
q931.c, pri_facility.c, prisched.c, testprilib.c, pri_timers.h,
pri_facility.h, libpri.h: Moving trunk changes back into 1.4
2008-05-02 20:21 +0000 [r552] Brett Bryant <bbryant@digium.com>
* Makefile, build_tools (added), build_tools/make_version (added),
build_tools/make_version_c (added), libpri.h: Add new API call
(pri_get_version) to show the current version of the branch for
support purposes.
2008-04-16 00:21 +0000 [r544] Kevin P. Fleming <kpfleming@digium.com>
* q921.c: fix the indentation in this function so that it is
actually possible to read it and understand the logic and flow
2008-02-21 16:38 +0000 [r528] Joshua Colp <jcolp@digium.com>
* q931.c: If inband audio is being provided with a disconnect
message let the audio be heard before releasing the channel.
(closes issue #10552) Reported by: paravoid Patches:
disconnect-audio.diff uploaded by paravoid (license 200)
2008-02-18 20:31 +0000 [r524] Matthew Fredrickson <creslin@digium.com>
* q931.c, libpri.h: Improve transmission, receiving, and dumping of
bearer capability IE (#11593)
2008-01-11 16:34 +0000 [r514] Matthew Fredrickson <creslin@digium.com>
* q931.c, /: Merged revisions 513 via svnmerge from
https://origsvn.digium.com/svn/libpri/branches/1.2 ........ r513
| mattf | 2008-01-11 10:33:52 -0600 (Fri, 11 Jan 2008) | 1 line
We should not be parsing further into the bearer capability IE if
the length does not confirm that there actually is data present
........
2007-12-13 Russell Bryant <russell@digium.com>
* libpri 1.4.3 released.
2007-10-22 15:10 +0000 [r479] Kevin P. Fleming <kpfleming@digium.com>
* pri_internal.h, /: Merged revisions 478 via svnmerge from
https://origsvn.digium.com/svn/libpri/branches/1.2 ........ r478
| kpfleming | 2007-10-22 10:09:27 -0500 (Mon, 22 Oct 2007) | 3
lines we need to include stddef.h for 'size_t' ........
2007-10-16 Matthew Fredrickson <creslin@digium.com>
* libpri 1.4.2 released.
2007-10-05 16:45 +0000 [r470] Jason Parker <jparker@digium.com>
* libpri.h: Fix an incorrect pri_event structure definition. Issue
10832, patch by flefoll
2007-09-25 21:37 +0000 [r468] Matthew Fredrickson <creslin@digium.com>
* q931.c: Fix user-user IE order in setup message (#10705)
2007-09-14 21:32 +0000 [r465] Matthew Fredrickson <creslin@digium.com>
* q931.c, libpri.h: Fix for #10189. Make sure we properly report
the user layer 1 for H.223 and H.245
2007-09-06 15:11 +0000 [r462] Matthew Fredrickson <creslin@digium.com>
* pri.c, pri_facility.c, /: Merged revisions 460 via svnmerge from
https://origsvn.digium.com/svn/libpri/branches/1.2 ........ r460
| mattf | 2007-09-06 10:06:42 -0500 (Thu, 06 Sep 2007) | 1 line
TBCT now works. It should work for NI2, 4E, and 5E. This code was
tested on NI2. ........
2007-08-27 19:21 +0000 [r446] Jason Parker <jparker@digium.com>
* Makefile, /: Merged revisions 445 via svnmerge from
https://origsvn.digium.com/svn/libpri/branches/1.2 ........ r445
| qwell | 2007-08-27 14:20:23 -0500 (Mon, 27 Aug 2007) | 2 lines
Make sure we build both the static and shared modules with -fPIC.
........
2007-08-06 19:58 +0000 [r441] Jason Parker <jparker@digium.com>
* Makefile: Allow setting CC to something with a space, such as
`make CC="gcc -m32"` Issue 10253.
2007-07-09 Russell Bryant <russell@digium.com>
* libpri 1.4.1 released.
2007-06-19 18:23 +0000 [r427] Matthew Fredrickson <creslin@digium.com>
* q931.c, /: Merged revisions 426 via svnmerge from
https://origsvn.digium.com/svn/libpri/branches/1.2 ........ r426
| mattf | 2007-06-19 13:22:33 -0500 (Tue, 19 Jun 2007) | 1 line
Try to send pending facility messages if we receive alerting (for
when we don't get proceeding) (#9651) ........
2007-06-06 21:58 +0000 [r416-424] Matthew Fredrickson <creslin@digium.com>
* pri_facility.c, /: Merged revisions 423 via svnmerge from
https://origsvn.digium.com/svn/libpri/branches/1.2 ........ r423
| mattf | 2007-06-06 16:57:15 -0500 (Wed, 06 Jun 2007) | 1 line
Oops, that should not be on one line ........
* pri_facility.c, /: Merged revisions 415 via svnmerge from
https://origsvn.digium.com/svn/libpri/branches/1.2 ........ r415
| mattf | 2007-06-06 08:20:05 -0500 (Wed, 06 Jun 2007) | 2 lines
Make sure we only send the NFE when we are talking QSIG ........
2007-01-22 22:29 +0000 [r390] Matthew Fredrickson <creslin@digium.com>
* q931.c, /: Merged revisions 389 via svnmerge from
https://origsvn.digium.com/svn/libpri/branches/1.2 ........ r389
| mattf | 2007-01-22 16:20:59 -0600 (Mon, 22 Jan 2007) | 2 lines
Make sure we send DISCONNECT if we reached the active state and a
call is disconnected, regardless of cause code. ........
2006-12-30 19:17 +0000 [r386] Joshua Colp <jcolp@digium.com>
* Makefile, /: Merged revisions 385 via svnmerge from
https://origsvn.digium.com/svn/libpri/branches/1.2 ........ r385
| file | 2006-12-30 14:16:17 -0500 (Sat, 30 Dec 2006) | 2 lines
Specify full path to restorecon instead of assuming it will be
available from what is in $PATH. (issue #8670 reported by djflux)
........
2006-12-23 Kevin P. Fleming <kpfleming@digium.com>
* libpri 1.4.0 released.

View File

@@ -28,25 +28,18 @@
#LIBPRI_COUNTERS=-DLIBPRI_COUNTERS
CC=gcc
GREP=grep
AWK=awk
OSARCH=$(shell uname -s)
PROC?=$(shell uname -m)
# SONAME version; should be changed on every ABI change
# please don't change it needlessly; it's perfectly fine to have a SONAME
# of 1.2 and a version of 1.4.x
SONAME:=1.4
STATIC_LIBRARY=libpri.a
DYNAMIC_LIBRARY:=libpri.so.$(SONAME)
STATIC_OBJS=copy_string.o pri.o q921.o prisched.o q931.o pri_facility.o version.o
DYNAMIC_OBJS=copy_string.lo pri.lo q921.lo prisched.lo q931.lo pri_facility.lo version.lo
CFLAGS=-Wall -Werror -Wstrict-prototypes -Wmissing-prototypes -g -fPIC $(ALERTING) $(LIBPRI_COUNTERS)
DYNAMIC_LIBRARY=libpri.so.1.0
STATIC_OBJS=copy_string.o pri.o q921.o prisched.o q931.o pri_facility.o
DYNAMIC_OBJS=copy_string.lo pri.lo q921.lo prisched.lo q931.lo pri_facility.lo
CFLAGS=-Wall -Werror -Wstrict-prototypes -Wmissing-prototypes -g $(ALERTING) $(LIBPRI_COUNTERS)
INSTALL_PREFIX=$(DESTDIR)
INSTALL_BASE=/usr
SOFLAGS:=-Wl,-h$(DYNAMIC_LIBRARY)
SOFLAGS = -Wl,-hlibpri.so.1.0
LDCONFIG = /sbin/ldconfig
ifneq (,$(findstring X$(OSARCH)X, XLinuxX XGNU/kFreeBSDX))
LDCONFIG_FLAGS=-n
@@ -61,13 +54,10 @@ ifeq (${OSARCH},SunOS)
CFLAGS += -DSOLARIS -I../zaptel-solaris
LDCONFIG =
LDCONFIG_FLAGS = \# # Trick to comment out the period in the command below
SOSLINK = ln -sf libpri.so.1.0 libpri.so.1
#INSTALL_PREFIX = /opt/asterisk # Uncomment out to install in standard Solaris location for 3rd party code
endif
export PRIVERSION
PRIVERSION:=$(shell GREP=$(GREP) AWK=$(AWK) build_tools/make_version .)
#The problem with sparc is the best stuff is in newer versions of gcc (post 3.0) only.
#This works for even old (2.96) versions of gcc and provides a small boost either way.
#A ultrasparc cpu is really v9 but the stock debian stable 3.0 gcc doesnt support it.
@@ -81,16 +71,7 @@ all: depend $(STATIC_LIBRARY) $(DYNAMIC_LIBRARY)
update:
@if [ -d .svn ]; then \
echo "Updating from Subversion..." ; \
fromrev="`svn info | $(AWK) '/Revision: / {print $$2}'`"; \
svn update | tee update.out; \
torev="`svn info | $(AWK) '/Revision: / {print $$2}'`"; \
echo "`date` Updated from revision $${fromrev} to $${torev}." >> update.log; \
rm -f .version; \
if [ `grep -c ^C update.out` -gt 0 ]; then \
echo ; echo "The following files have conflicts:" ; \
grep ^C update.out | cut -b4- ; \
fi ; \
rm -f update.out; \
svn update -q; \
else \
echo "Not under version control"; \
fi
@@ -101,20 +82,21 @@ install: $(STATIC_LIBRARY) $(DYNAMIC_LIBRARY)
ifneq (${OSARCH},SunOS)
install -m 644 libpri.h $(INSTALL_PREFIX)$(INSTALL_BASE)/include
install -m 755 $(DYNAMIC_LIBRARY) $(INSTALL_PREFIX)$(INSTALL_BASE)/lib
if [ -x /usr/sbin/sestatus ] && ( /usr/sbin/sestatus | grep "SELinux status:" | grep -q "enabled"); then /sbin/restorecon -v $(INSTALL_PREFIX)$(INSTALL_BASE)/lib/$(DYNAMIC_LIBRARY); fi
( cd $(INSTALL_PREFIX)$(INSTALL_BASE)/lib ; ln -sf libpri.so.$(SONAME) libpri.so)
if [ -x /usr/sbin/sestatus ] && ( /usr/sbin/sestatus | grep "SELinux status:" | grep -q "enabled"); then restorecon -v $(INSTALL_PREFIX)$(INSTALL_BASE)/lib/$(DYNAMIC_LIBRARY); fi
( cd $(INSTALL_PREFIX)$(INSTALL_BASE)/lib ; ln -sf libpri.so.1.0 libpri.so ; ln -sf libpri.so.1.0 libpri.so.1 )
install -m 644 $(STATIC_LIBRARY) $(INSTALL_PREFIX)$(INSTALL_BASE)/lib
if test $$(id -u) = 0; then $(LDCONFIG) $(LDCONFIG_FLAGS) $(INSTALL_PREFIX)$(INSTALL_BASE)/lib; fi
else
install -f $(INSTALL_PREFIX)$(INSTALL_BASE)/include -m 644 libpri.h
install -f $(INSTALL_PREFIX)$(INSTALL_BASE)/lib -m 755 $(DYNAMIC_LIBRARY)
( cd $(INSTALL_PREFIX)$(INSTALL_BASE)/lib ; ln -sf libpri.so.$(SONAME) libpri.so)
( cd $(INSTALL_PREFIX)$(INSTALL_BASE)/lib ; ln -sf libpri.so.1.0 libpri.so ; $(SOSLINK) )
install -f $(INSTALL_PREFIX)$(INSTALL_BASE)/lib -m 644 $(STATIC_LIBRARY)
endif
uninstall:
@echo "Removing Libpri"
rm -f $(INSTALL_PREFIX)$(INSTALL_BASE)/lib/libpri.so.$(SONAME)
rm -f $(INSTALL_PREFIX)$(INSTALL_BASE)/lib/libpri.so.1.0
rm -f $(INSTALL_PREFIX)$(INSTALL_BASE)/lib/libpri.so.1
rm -f $(INSTALL_PREFIX)$(INSTALL_BASE)/lib/libpri.so
rm -f $(INSTALL_PREFIX)$(INSTALL_BASE)/lib/libpri.a
rm -f $(INSTALL_PREFIX)$(INSTALL_BASE)/include/libpri.h
@@ -136,7 +118,7 @@ include .depend
endif
%.lo : %.c
$(CC) $(CFLAGS) -o $@ -c $<
$(CC) -fPIC $(CFLAGS) -o $@ -c $<
$(STATIC_LIBRARY): $(STATIC_OBJS)
ar rcs $(STATIC_LIBRARY) $(STATIC_OBJS)
@@ -145,15 +127,12 @@ $(STATIC_LIBRARY): $(STATIC_OBJS)
$(DYNAMIC_LIBRARY): $(DYNAMIC_OBJS)
$(CC) -shared $(SOFLAGS) -o $@ $(DYNAMIC_OBJS)
$(LDCONFIG) $(LDCONFIG_FLAGS) .
ln -sf libpri.so.$(SONAME) libpri.so
version.c:
@build_tools/make_version_c > $@.tmp
@cmp -s $@.tmp $@ || mv $@.tmp $@
@rm -f $@.tmp
ln -sf libpri.so.1.0 libpri.so
ln -sf libpri.so.1.0 libpri.so.1
$(SOSLINK)
clean:
rm -f *.o *.so *.lo *.so.$(SONAME)
rm -f *.o *.so *.lo *.so.1 *.so.1.0
rm -f testprilib $(STATIC_LIBRARY) $(DYNAMIC_LIBRARY)
rm -f pritest pridump
rm -f .depend
@@ -161,6 +140,4 @@ clean:
depend: .depend
.depend:
CC="$(CC)" ./mkdep ${CFLAGS} `ls *.c`
.PHONY: version.c
CC=$(CC) ./mkdep ${CFLAGS} `ls *.c`

View File

@@ -1,74 +0,0 @@
#!/bin/sh
if [ -f ${1}/.version ]; then
cat ${1}/.version
elif [ -d .svn ]; then
PARTS=`LANG=C svn info ${1} | ${GREP} URL | ${AWK} '{print $2;}' | sed -e 's:^.*/svn/libpri/::' | sed -e 's:/: :g'`
BRANCH=0
TEAM=0
TAG=0
REV=`svnversion -c ${1} | cut -d: -f2`
BASE=`LANG=C svn pg svnmerge-integrated ${1} | cut -d: -f1`
if [ "${PARTS}" = "trunk" ] ; then
echo SVN-trunk-r${REV}
exit 0
fi
for PART in $PARTS ; do
if [ ${TAG} != 0 ] ; then
if [ "${PART}" = "autotag_for_be" ] ; then
continue
fi
if [ "${PART}" = "autotag_for_sx00i" ] ; then
continue
fi
RESULT="${PART}"
break
fi
if [ ${BRANCH} != 0 ] ; then
if [ -z ${RESULT} ] ; then
RESULT="2${PART}"
else
RESULT="3${RESULT}-${PART}"
fi
break
fi
if [ ${TEAM} != 0 ] ; then
if [ -z ${RESULT} ] ; then
RESULT="4${PART}"
else
RESULT="5${RESULT}-${PART}"
fi
continue
fi
if [ "${PART}" = "branches" ] ; then
BRANCH=1
RESULT="branch"
continue
fi
if [ "${PART}" = "tags" ] ; then
TAG=1
continue
fi
if [ "${PART}" = "team" ] ; then
TEAM=1
continue
fi
done
RESULT="libss7"
if [ ${TAG} != 0 ] ; then
echo ${RESULT}
else
echo SVN-${RESULT}-r${REV}${BASE:+-${BASE}}
fi
fi

View File

@@ -1,24 +0,0 @@
#!/bin/sh
if [ ! -f ../.flavor ]; then
EXTRA=""
else
aadkver=`cat ../.version`
aadkflavor=`cat ../.flavor`
EXTRA=" (${aadkflavor} ${aadkver})"
fi
cat << END
/*
* version.c
* Automatically generated
*/
#include "libpri.h"
static const char pri_version[] = "${PRIVERSION}${EXTRA}";
const char *pri_get_version(void)
{
return pri_version;
}
END

175
libpri.h
View File

@@ -202,57 +202,11 @@
#define PRI_LAYER_1_ALAW 0x23
#define PRI_LAYER_1_G721 0x24
#define PRI_LAYER_1_G722_G725 0x25
#define PRI_LAYER_1_H223_H245 0x26
#define PRI_LAYER_1_G7XX_384K 0x26
#define PRI_LAYER_1_NON_ITU_ADAPT 0x27
#define PRI_LAYER_1_V120_RATE_ADAPT 0x28
#define PRI_LAYER_1_X31_RATE_ADAPT 0x29
/* Intermediate rates for V.110 */
#define PRI_INT_RATE_8K 1
#define PRI_INT_RATE_16K 2
#define PRI_INT_RATE_32K 3
/* Rate adaption for bottom 5 bits of rateadaption */
#define PRI_RATE_USER_RATE_MASK 0x1F
#define PRI_RATE_ADAPT_UNSPEC 0x00
#define PRI_RATE_ADAPT_0K6 0x01
#define PRI_RATE_ADAPT_1K2 0x02
#define PRI_RATE_ADAPT_2K4 0x03
#define PRI_RATE_ADAPT_3K6 0x04
#define PRI_RATE_ADAPT_4K8 0x05
#define PRI_RATE_ADAPT_7K2 0x06
#define PRI_RATE_ADAPT_8K 0x07
#define PRI_RATE_ADAPT_9K6 0x08
#define PRI_RATE_ADAPT_14K4 0x09
#define PRI_RATE_ADAPT_16K 0x0A
#define PRI_RATE_ADAPT_19K2 0x0B
#define PRI_RATE_ADAPT_32K 0x0C
#define PRI_RATE_ADAPT_38K4 0x0D
#define PRI_RATE_ADAPT_48K 0x0E
#define PRI_RATE_ADAPT_56K 0x0F
#define PRI_RATE_ADAPT_57K6 0x12
#define PRI_RATE_ADAPT_28K8 0x13
#define PRI_RATE_ADAPT_24K 0x14
#define PRI_RATE_ADAPT_0K1345 0x15
#define PRI_RATE_ADAPT_0K1 0x16
#define PRI_RATE_ADAPT_0K075_1K2 0x17
#define PRI_RATE_ADAPT_1K2_0K075 0x18
#define PRI_RATE_ADAPT_0K05 0x19
#define PRI_RATE_ADAPT_0K075 0x1A
#define PRI_RATE_ADAPT_0K110 0x1B
#define PRI_RATE_ADAPT_0K150 0x1C
#define PRI_RATE_ADAPT_0K200 0x1D
#define PRI_RATE_ADAPT_0K300 0x1E
#define PRI_RATE_ADAPT_12K 0x1F
/* in-band negotiation flag for rateadaption bit 5 */
#define PRI_RATE_ADAPT_NEGOTIATION_POSS 0x20
/* async flag for rateadaption bit 6 */
#define PRI_RATE_ADAPT_ASYNC 0x40
/* Notifications */
#define PRI_NOTIFY_USER_SUSPENDED 0x00 /* User suspended */
#define PRI_NOTIFY_USER_RESUMED 0x01 /* User resumed */
@@ -342,8 +296,6 @@ typedef struct pri_event_facname {
int channel;
int cref;
q931_call *call;
int callingpres; /* Presentation of Calling CallerID */
int callingplan; /* Dialing plan of Calling entity */
} pri_event_facname;
#define PRI_CALLINGPLANANI
@@ -434,7 +386,7 @@ typedef union {
pri_event_ring ring; /* Ring */
pri_event_hangup hangup; /* Hang up */
pri_event_ringing ringing; /* Ringing */
pri_event_answer answer; /* Answer */
pri_event_ringing answer; /* Answer */
pri_event_restart_ack restartack; /* Restart Acknowledge */
pri_event_proceeding proceeding; /* Call proceeding & Progress */
pri_event_setup_ack setup_ack; /* SETUP_ACKNOWLEDGE structure */
@@ -453,78 +405,77 @@ typedef int (*pri_io_cb)(struct pri *pri, void *buf, int buflen);
channel operating in HDLC mode with FCS computed by the fd's driver. Also it
must be NON-BLOCKING! Frames received on the fd should include FCS. Nodetype
must be one of PRI_NETWORK or PRI_CPE. switchtype should be PRI_SWITCH_* */
struct pri *pri_new(int fd, int nodetype, int switchtype);
struct pri *pri_new_bri(int fd, int ptpmode, int nodetype, int switchtype);
extern struct pri *pri_new(int fd, int nodetype, int switchtype);
/* Create D-channel just as above with user defined I/O callbacks and data */
struct pri *pri_new_cb(int fd, int nodetype, int switchtype, pri_io_cb io_read, pri_io_cb io_write, void *userdata);
extern struct pri *pri_new_cb(int fd, int nodetype, int switchtype, pri_io_cb io_read, pri_io_cb io_write, void *userdata);
/* Retrieve the user data associated with the D channel */
void *pri_get_userdata(struct pri *pri);
extern void *pri_get_userdata(struct pri *pri);
/* Set the user data associated with the D channel */
void pri_set_userdata(struct pri *pri, void *userdata);
extern void pri_set_userdata(struct pri *pri, void *userdata);
/* Set Network Specific Facility for PRI */
void pri_set_nsf(struct pri *pri, int nsf);
extern void pri_set_nsf(struct pri *pri, int nsf);
/* Set debug parameters on PRI -- see above debug definitions */
void pri_set_debug(struct pri *pri, int debug);
extern void pri_set_debug(struct pri *pri, int debug);
/* Get debug parameters on PRI -- see above debug definitions */
int pri_get_debug(struct pri *pri);
extern int pri_get_debug(struct pri *pri);
#define PRI_FACILITY_ENABLE
/* Enable transmission support of Facility IEs on the pri */
void pri_facility_enable(struct pri *pri);
extern void pri_facility_enable(struct pri *pri);
/* Run PRI on the given D-channel, taking care of any events that
need to be handled. If block is set, it will block until an event
occurs which needs to be handled */
pri_event *pri_dchannel_run(struct pri *pri, int block);
extern pri_event *pri_dchannel_run(struct pri *pri, int block);
/* Check for an outstanding event on the PRI */
pri_event *pri_check_event(struct pri *pri);
/* Give a name to a given event ID */
char *pri_event2str(int id);
extern char *pri_event2str(int id);
/* Give a name to a node type */
char *pri_node2str(int id);
extern char *pri_node2str(int id);
/* Give a name to a switch type */
char *pri_switch2str(int id);
extern char *pri_switch2str(int id);
/* Print an event */
void pri_dump_event(struct pri *pri, pri_event *e);
extern void pri_dump_event(struct pri *pri, pri_event *e);
/* Turn presentation into a string */
char *pri_pres2str(int pres);
extern char *pri_pres2str(int pres);
/* Turn numbering plan into a string */
char *pri_plan2str(int plan);
extern char *pri_plan2str(int plan);
/* Turn cause into a string */
char *pri_cause2str(int cause);
extern char *pri_cause2str(int cause);
/* Acknowledge a call and place it on the given channel. Set info to non-zero if there
is in-band data available on the channel */
int pri_acknowledge(struct pri *pri, q931_call *call, int channel, int info);
extern int pri_acknowledge(struct pri *pri, q931_call *call, int channel, int info);
/* Send a digit in overlap mode */
int pri_information(struct pri *pri, q931_call *call, char digit);
extern int pri_information(struct pri *pri, q931_call *call, char digit);
#define PRI_KEYPAD_FACILITY_TX
/* Send a keypad facility string of digits */
int pri_keypad_facility(struct pri *pri, q931_call *call, char *digits);
extern int pri_keypad_facility(struct pri *pri, q931_call *call, char *digits);
/* Answer the incomplete(call without called number) call on the given channel.
Set non-isdn to non-zero if you are not connecting to ISDN equipment */
int pri_need_more_info(struct pri *pri, q931_call *call, int channel, int nonisdn);
extern int pri_need_more_info(struct pri *pri, q931_call *call, int channel, int nonisdn);
/* Answer the call on the given channel (ignored if you called acknowledge already).
Set non-isdn to non-zero if you are not connecting to ISDN equipment */
int pri_answer(struct pri *pri, q931_call *call, int channel, int nonisdn);
extern int pri_answer(struct pri *pri, q931_call *call, int channel, int nonisdn);
/* Set CRV reference for GR-303 calls */
@@ -541,60 +492,59 @@ int pri_answer(struct pri *pri, q931_call *call, int channel, int nonisdn);
/* Hangup a call */
#define PRI_HANGUP
int pri_hangup(struct pri *pri, q931_call *call, int cause);
extern int pri_hangup(struct pri *pri, q931_call *call, int cause);
#define PRI_DESTROYCALL
void pri_destroycall(struct pri *pri, q931_call *call);
extern void pri_destroycall(struct pri *pri, q931_call *call);
#define PRI_RESTART
int pri_restart(struct pri *pri);
extern int pri_restart(struct pri *pri);
int pri_reset(struct pri *pri, int channel);
extern int pri_reset(struct pri *pri, int channel);
/* Create a new call */
q931_call *pri_new_call(struct pri *pri);
extern q931_call *pri_new_call(struct pri *pri);
/* Retrieve CRV reference for GR-303 calls. Returns >0 on success. */
int pri_get_crv(struct pri *pri, q931_call *call, int *callmode);
extern int pri_get_crv(struct pri *pri, q931_call *call, int *callmode);
/* Retrieve CRV reference for GR-303 calls. CRV must be >0, call mode should be 0 */
int pri_set_crv(struct pri *pri, q931_call *call, int crv, int callmode);
extern int pri_set_crv(struct pri *pri, q931_call *call, int crv, int callmode);
/* How long until you need to poll for a new event */
struct timeval *pri_schedule_next(struct pri *pri);
extern struct timeval *pri_schedule_next(struct pri *pri);
/* Run any pending schedule events */
extern pri_event *pri_schedule_run(struct pri *pri);
extern pri_event *pri_schedule_run_tv(struct pri *pri, const struct timeval *now);
int pri_call(struct pri *pri, q931_call *c, int transmode, int channel,
extern int pri_call(struct pri *pri, q931_call *c, int transmode, int channel,
int exclusive, int nonisdn, char *caller, int callerplan, char *callername, int callerpres,
char *called,int calledplan, int ulayer1);
struct pri_sr *pri_sr_new(void);
void pri_sr_free(struct pri_sr *sr);
extern struct pri_sr *pri_sr_new(void);
extern void pri_sr_free(struct pri_sr *sr);
int pri_sr_set_channel(struct pri_sr *sr, int channel, int exclusive, int nonisdn);
int pri_sr_set_bearer(struct pri_sr *sr, int transmode, int userl1);
int pri_sr_set_called(struct pri_sr *sr, char *called, int calledplan, int complete);
int pri_sr_set_caller(struct pri_sr *sr, char *caller, char *callername, int callerplan, int callerpres);
int pri_sr_set_redirecting(struct pri_sr *sr, char *num, int plan, int pres, int reason);
extern int pri_sr_set_channel(struct pri_sr *sr, int channel, int exclusive, int nonisdn);
extern int pri_sr_set_bearer(struct pri_sr *sr, int transmode, int userl1);
extern int pri_sr_set_called(struct pri_sr *sr, char *called, int calledplan, int complete);
extern int pri_sr_set_caller(struct pri_sr *sr, char *caller, char *callername, int callerplan, int callerpres);
extern int pri_sr_set_redirecting(struct pri_sr *sr, char *num, int plan, int pres, int reason);
#define PRI_USER_USER_TX
/* Set the user user field. Warning! don't send binary data accross this field */
void pri_sr_set_useruser(struct pri_sr *sr, const char *userchars);
extern void pri_sr_set_useruser(struct pri_sr *sr, const char *userchars);
void pri_call_set_useruser(q931_call *sr, const char *userchars);
extern void pri_call_set_useruser(q931_call *sr, const char *userchars);
int pri_setup(struct pri *pri, q931_call *call, struct pri_sr *req);
extern int pri_setup(struct pri *pri, q931_call *call, struct pri_sr *req);
/* Set a call has a call indpendent signalling connection (i.e. no bchan) */
int pri_sr_set_connection_call_independent(struct pri_sr *req);
extern int pri_sr_set_connection_call_independent(struct pri_sr *req);
/* Send an MWI indication to a remote location. If activate is non zero, activates, if zero, decativates */
int pri_mwi_activate(struct pri *pri, q931_call *c, char *caller, int callerplan, char *callername, int callerpres, char *called, int calledplan);
extern int pri_mwi_activate(struct pri *pri, q931_call *c, char *caller, int callerplan, char *callername, int callerpres, char *called, int calledplan);
/* Send an MWI deactivate request to a remote location */
int pri_mwi_deactivate(struct pri *pri, q931_call *c, char *caller, int callerplan, char *callername, int callerpres, char *called, int calledplan);
extern int pri_mwi_deactivate(struct pri *pri, q931_call *c, char *caller, int callerplan, char *callername, int callerpres, char *called, int calledplan);
#define PRI_2BCT
/* Attempt to pass the channels back to the NET side if compatable and
@@ -603,33 +553,30 @@ int pri_channel_bridge(q931_call *call1, q931_call *call2);
/* Override message and error stuff */
#define PRI_NEW_SET_API
void pri_set_message(void (*__pri_error)(struct pri *pri, char *));
void pri_set_error(void (*__pri_error)(struct pri *pri, char *));
extern void pri_set_message(void (*__pri_error)(struct pri *pri, char *));
extern void pri_set_error(void (*__pri_error)(struct pri *pri, char *));
/* Set overlap mode */
#define PRI_SET_OVERLAPDIAL
void pri_set_overlapdial(struct pri *pri,int state);
extern void pri_set_overlapdial(struct pri *pri,int state);
#define PRI_DUMP_INFO_STR
char *pri_dump_info_str(struct pri *pri);
extern char *pri_dump_info_str(struct pri *pri);
/* Get file descriptor */
int pri_fd(struct pri *pri);
extern int pri_fd(struct pri *pri);
#define PRI_PROGRESS
/* Send call proceeding */
int pri_progress(struct pri *pri, q931_call *c, int channel, int info);
extern int pri_progress(struct pri *pri, q931_call *c, int channel, int info);
#define PRI_PROCEEDING_FULL
/* Send call proceeding */
int pri_proceeding(struct pri *pri, q931_call *c, int channel, int info);
/* Enable inband progress when a RELEASE is received */
void pri_set_inbandrelease(struct pri *pri, unsigned int enable);
extern int pri_proceeding(struct pri *pri, q931_call *c, int channel, int info);
/* Enslave a PRI to another, so they share the same call list
(and maybe some timers) */
void pri_enslave(struct pri *master, struct pri *slave);
extern void pri_enslave(struct pri *master, struct pri *slave);
#define PRI_GR303_SUPPORT
#define PRI_ENSLAVE_SUPPORT
@@ -640,20 +587,20 @@ void pri_enslave(struct pri *master, struct pri *slave);
#define PRI_ANI
/* Send notification */
int pri_notify(struct pri *pri, q931_call *c, int channel, int info);
extern int pri_notify(struct pri *pri, q931_call *c, int channel, int info);
/* Get/Set PRI Timers */
#define PRI_GETSET_TIMERS
int pri_set_timer(struct pri *pri, int timer, int value);
int pri_get_timer(struct pri *pri, int timer);
int pri_timer2idx(char *timer);
extern int pri_set_timer(struct pri *pri, int timer, int value);
extern int pri_get_timer(struct pri *pri, int timer);
extern int pri_timer2idx(char *timer);
#define PRI_MAX_TIMERS 32
#define PRI_TIMER_N200 0 /* Maximum numer of q921 retransmissions */
#define PRI_TIMER_N201 1 /* Maximum numer of octets in an information field */
#define PRI_TIMER_N202 2 /* Maximum numer of transmissions of the TEI identity request message */
#define PRI_TIMER_K 3 /* Maximum number of outstanding I-frames */
#define PRI_TIMER_K 3 /* Maximum number of outstanding I-frames */
#define PRI_TIMER_T200 4 /* time between SABME's */
#define PRI_TIMER_T201 5 /* minimum time between retransmissions of the TEI Identity check messages */
@@ -681,10 +628,4 @@ int pri_timer2idx(char *timer);
#define PRI_TIMER_T321 26
#define PRI_TIMER_T322 27
#define PRI_TIMER_TM20 28 /* maximum time avaiting XID response */
#define PRI_TIMER_NM20 29 /* number of XID retransmits */
/* Get PRI version */
const char *pri_get_version(void);
#endif

178
pri.c
View File

@@ -81,7 +81,7 @@ char *pri_switch2str(int sw)
static void pri_default_timers(struct pri *pri, int switchtype)
{
static const int defaulttimers[20][PRI_MAX_TIMERS] = PRI_TIMERS_ALL;
int defaulttimers[20][PRI_MAX_TIMERS] = PRI_TIMERS_ALL;
int x;
for (x = 0; x<PRI_MAX_TIMERS; x++) {
@@ -187,76 +187,63 @@ static int __pri_write(struct pri *pri, void *buf, int buflen)
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)
static struct pri *__pri_new(int fd, int node, int switchtype, struct pri *master, pri_io_cb rd, pri_io_cb wr, void *userdata)
{
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);
}
p = malloc(sizeof(struct pri));
if (p) {
memset(p, 0, sizeof(struct pri));
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 = Q921_SAPI_CALL_CTRL;
p->tei = 0;
p->nsf = PRI_NSF_NONE;
p->protodisc = Q931_PROTOCOL_DISCRIMINATOR;
p->master = master;
p->callpool = &p->localpool;
pri_default_timers(p, switchtype);
#ifdef LIBPRI_COUNTERS
p->q921_rxcount = 0;
p->q921_txcount = 0;
p->q931_rxcount = 0;
p->q931_txcount = 0;
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;
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(-1, node, PRI_SWITCH_GR303_EOC_PATH, p, NULL, NULL, NULL);
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(-1, node, PRI_SWITCH_GR303_TMC_SWITCHING, p, NULL, NULL, NULL);
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;
}
} 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);
}
/* Start Q.921 layer, Wait if we're the network */
if (p)
q921_start(p, p->localtype == PRI_CPE);
return p;
}
@@ -283,15 +270,7 @@ int pri_restart(struct pri *pri)
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);
return __pri_new(fd, nodetype, switchtype, NULL, __pri_read, __pri_write, NULL);
}
struct pri *pri_new_cb(int fd, int nodetype, int switchtype, pri_io_cb io_read, pri_io_cb io_write, void *userdata)
@@ -300,7 +279,7 @@ struct pri *pri_new_cb(int fd, int nodetype, int switchtype, pri_io_cb 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);
return __pri_new(fd, nodetype, switchtype, NULL, io_read, io_write, userdata);
}
void *pri_get_userdata(struct pri *pri)
@@ -550,44 +529,22 @@ int pri_channel_bridge(q931_call *call1, q931_call *call2)
if (!call1 || !call2)
return -1;
/* Make sure we have compatible switchtypes */
if (call1->pri->switchtype != call2->pri->switchtype)
return -1;
/* Check for bearer capability */
if (call1->transcapability != call2->transcapability)
return -1;
/* Check to see if we're on the same PRI */
/* Check to see if calls are on the same PRI dchannel
* Currently only support calls on the same dchannel
*/
if (call1->pri != call2->pri)
return -1;
switch (call1->pri->switchtype) {
case PRI_SWITCH_NI2:
case PRI_SWITCH_LUCENT5E:
case PRI_SWITCH_ATT4ESS:
if (eect_initiate_transfer(call1->pri, call1, call2))
return -1;
else
return 0;
break;
case PRI_SWITCH_DMS100:
if (rlt_initiate_transfer(call1->pri, call1, call2))
return -1;
else
return 0;
break;
case PRI_SWITCH_QSIG:
call1->bridged_call = call2;
call2->bridged_call = call1;
if (anfpr_initiate_transfer(call1->pri, call1, call2))
return -1;
else
return 0;
break;
default:
return -1;
}
if (call1->pri->switchtype == PRI_SWITCH_LUCENT5E)
return eect_initiate_transfer(call1->pri, call1, call2);
if (call1->pri->switchtype == PRI_SWITCH_DMS100)
return rlt_initiate_transfer(call1->pri, call1, call2);
return -1;
}
int pri_hangup(struct pri *pri, q931_call *call, int cause)
@@ -782,11 +739,6 @@ void pri_set_overlapdial(struct pri *pri,int state)
pri->overlapdial = state;
}
void pri_set_inbandrelease(struct pri *pri, unsigned int enable)
{
pri->acceptinbandrelease = (enable != 0);
}
int pri_fd(struct pri *pri)
{
return pri->fd;
@@ -855,7 +807,7 @@ void pri_enslave(struct pri *master, struct pri *slave)
struct pri_sr *pri_sr_new(void)
{
struct pri_sr *req;
req = malloc(sizeof(*req));
req = malloc(sizeof(struct pri_sr));
if (req)
pri_sr_init(req);
return req;

View File

@@ -167,18 +167,9 @@ static unsigned char get_invokeid(struct pri *pri)
struct addressingdataelements_presentednumberunscreened {
char partyaddress[21];
char partysubaddress[21];
int npi; /* Numbering Plan Indicator */
int ton; /* Type Of Number */
int pres; /* Presentation */
};
struct addressingdataelements_presentednumberscreened {
char partyaddress[21];
char partysubaddress[21];
int npi; /* Numbering Plan Indicator */
int ton; /* Type Of Number */
int pres; /* Presentation */
int scrind; /* Screening Indicator */
int npi;
int ton;
int pres;
};
#define PRI_CHECKOVERFLOW(size) \
@@ -462,35 +453,6 @@ static int rose_public_party_number_decode(struct pri *pri, q931_call *call, uns
return -1;
}
static int rose_private_party_number_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberunscreened *value)
{
int i = 0;
struct rose_component *comp = NULL;
unsigned char *vdata = data;
int ton;
int res = 0;
if (len < 2)
return -1;
do {
GET_COMPONENT(comp, i, vdata, len);
CHECK_COMPONENT(comp, ASN1_ENUMERATED, "Don't know what to do with PrivatePartyNumber ROSE component type 0x%x\n");
ASN1_GET_INTEGER(comp, ton);
NEXT_COMPONENT(comp, i);
ton = typeofnumber_for_q931(pri, ton);
res = rose_number_digits_decode(pri, call, &vdata[i], len-i, value);
if (res < 0)
return -1;
value->ton = ton;
return res + 3;
} while(0);
return -1;
}
static int rose_address_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberunscreened *value)
{
int i = 0;
@@ -541,11 +503,9 @@ static int rose_address_decode(struct pri *pri, q931_call *call, unsigned char *
pri_message(pri, "!! telexPartyNumber isn't handled\n");
return -1;
case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_5): /* [5] priavePartyNumber */
res = rose_private_party_number_decode(pri, call, comp->data, comp->len, value);
if (res < 0)
return -1;
pri_message(pri, "!! privatePartyNumber isn't handled\n");
value->npi = PRI_NPI_PRIVATE;
break;
return -1;
case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_8): /* [8] nationalStandardPartyNumber */
res = rose_number_digits_decode(pri, call, comp->data, comp->len, value);
if (res < 0)
@@ -629,8 +589,6 @@ static int rose_diverting_leg_information2_decode(struct pri *pri, q931_call *ca
struct rose_component *comp = NULL;
unsigned char *vdata = sequence->data;
int res = 0;
memset(&divertingnr, 0, sizeof(divertingnr));
memset(&originalcallednr, 0, sizeof(originalcallednr));
/* Data checks */
if (sequence->type != (ASN1_CONSTRUCTOR | ASN1_SEQUENCE)) { /* Constructed Sequence */
@@ -712,9 +670,6 @@ static int rose_diverting_leg_information2_decode(struct pri *pri, q931_call *ca
if (pri->debug & PRI_DEBUG_APDU)
pri_message(pri, " Received Originally Called Name '%s'\n", origcalledname);
break;
case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_5):
pri_message(pri, "!! Ignoring DivertingLegInformation2 component 0x%X\n", comp->type);
break;
default:
if (comp->type == 0 && comp->len == 0) {
break; /* Found termination characters */
@@ -729,13 +684,11 @@ static int rose_diverting_leg_information2_decode(struct pri *pri, q931_call *ca
call->redirectingpres = divertingnr.pres;
call->redirectingreason = diversion_reason;
libpri_copy_string(call->redirectingnum, divertingnr.partyaddress, sizeof(call->redirectingnum));
pri_message(pri, " Received redirectingnum '%s' (%d)\n", call->redirectingnum, (int)call->redirectingnum[0]);
}
if (originalcallednr.pres >= 0) {
call->origcalledplan = originalcallednr.npi;
call->origcalledpres = originalcallednr.pres;
libpri_copy_string(call->origcallednum, originalcallednr.partyaddress, sizeof(call->origcallednum));
pri_message(pri, " Received origcallednum '%s' (%d)\n", call->origcallednum, (int)call->origcallednum[0]);
}
libpri_copy_string(call->redirectingname, redirectingname, sizeof(call->redirectingname));
libpri_copy_string(call->origcalledname, origcalledname, sizeof(call->origcalledname));
@@ -990,13 +943,11 @@ static int add_callername_facility_ies(struct pri *pri, q931_call *c, int cpe)
buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
/* Interpretation component */
if (pri->switchtype == PRI_SWITCH_QSIG) {
ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer, i);
ASN1_PUSH(compstk, compsp, comp);
ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i, 0);
ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i, 0);
ASN1_FIXUP(compstk, compsp, buffer, i);
}
ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer, i);
ASN1_PUSH(compstk, compsp, comp);
ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i, 0);
ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i, 0);
ASN1_FIXUP(compstk, compsp, buffer, i);
ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0);
@@ -1033,13 +984,11 @@ static int add_callername_facility_ies(struct pri *pri, q931_call *c, int cpe)
buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
/* Interpretation component */
if (pri->switchtype == PRI_SWITCH_QSIG) {
ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer, i);
ASN1_PUSH(compstk, compsp, comp);
ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i, 0);
ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i, 0);
ASN1_FIXUP(compstk, compsp, buffer, i);
}
ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer, i);
ASN1_PUSH(compstk, compsp, comp);
ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i, 0);
ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i, 0);
ASN1_FIXUP(compstk, compsp, buffer, i);
ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0);
@@ -1128,10 +1077,13 @@ int mwi_message_send(struct pri* pri, q931_call *call, struct pri_sr *req, int a
/* EECT functions */
int eect_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2)
{
/* Did all the tests to see if we're on the same PRI and
* are on a compatible switchtype */
/* TODO */
int i = 0;
int res = 0;
unsigned char buffer[255] = "";
short call_reference = c2->cr ^ 0x8000; /* Let's do the trickery to make sure the flag is correct */
unsigned short call_reference = c2->cr;
struct rose_component *comp = NULL, *compstk[10];
int compsp = 0;
static unsigned char op_tag[] = {
@@ -1144,7 +1096,16 @@ int eect_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2)
0x08,
};
buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_ROSE);
buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
/* Interpretation component */
ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer, i);
ASN1_PUSH(compstk, compsp, comp);
ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i, 0);
ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i, 0);
ASN1_FIXUP(compstk, compsp, buffer, i);
ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0);
ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
ASN1_PUSH(compstk, compsp, comp);
@@ -1181,162 +1142,6 @@ int eect_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2)
}
/* End EECT */
static int anfpr_pathreplacement_respond(struct pri *pri, q931_call *call, q931_ie *ie)
{
int res;
res = pri_call_apdu_queue_cleanup(call->bridged_call);
if (res) {
pri_message(pri, "Could not Clear queue ADPU\n");
return -1;
}
/* Send message */
res = pri_call_apdu_queue(call->bridged_call, Q931_FACILITY, ie->data, ie->len, NULL, NULL);
if (res) {
pri_message(pri, "Could not queue ADPU in facility message\n");
return -1;
}
/* Remember that if we queue a facility IE for a facility message we
* have to explicitly send the facility message ourselves */
res = q931_facility(call->bridged_call->pri, call->bridged_call);
if (res) {
pri_message(pri, "Could not schedule facility message for call %d\n", call->bridged_call->cr);
return -1;
}
return 0;
}
/* AFN-PR */
extern int anfpr_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2)
{
/* Did all the tests to see if we're on the same PRI and
* are on a compatible switchtype */
/* TODO */
int i = 0;
int res = 0;
unsigned char buffer[255] = "";
unsigned short call_reference = c2->cr;
struct rose_component *comp = NULL, *compstk[10];
unsigned char buffer2[255] = "";
int compsp = 0;
static unsigned char op_tag[] = {
0x0C,
};
/* Channel 1 */
buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
/* Interpretation component */
ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer, i);
ASN1_PUSH(compstk, compsp, comp);
ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i, 0);
ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i, 0);
ASN1_FIXUP(compstk, compsp, buffer, i);
ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 2); /* reject - to get feedback from QSIG switch */
ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
ASN1_PUSH(compstk, compsp, comp);
ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, get_invokeid(pri));
res = asn1_string_encode(ASN1_INTEGER, &buffer[i], sizeof(buffer)-i, sizeof(op_tag), op_tag, sizeof(op_tag));
if (res < 0)
return -1;
i += res;
ASN1_ADD_SIMPLE(comp, (ASN1_SEQUENCE | ASN1_CONSTRUCTOR), buffer, i);
ASN1_PUSH(compstk, compsp, comp);
buffer[i++] = (0x0a);
buffer[i++] = (0x01);
buffer[i++] = (0x00);
buffer[i++] = (0x81);
buffer[i++] = (0x00);
buffer[i++] = (0x0a);
buffer[i++] = (0x01);
buffer[i++] = (0x01);
ASN1_ADD_WORDCOMP(comp, ASN1_INTEGER, buffer, i, call_reference);
ASN1_FIXUP(compstk, compsp, buffer, i);
ASN1_FIXUP(compstk, compsp, buffer, i);
res = pri_call_apdu_queue(c1, Q931_FACILITY, buffer, i, NULL, NULL);
if (res) {
pri_message(pri, "Could not queue ADPU in facility message\n");
return -1;
}
/* Remember that if we queue a facility IE for a facility message we
* have to explicitly send the facility message ourselves */
res = q931_facility(c1->pri, c1);
if (res) {
pri_message(pri, "Could not schedule facility message for call %d\n", c1->cr);
return -1;
}
/* Channel 2 */
i = 0;
res = 0;
compsp = 0;
buffer2[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
/* Interpretation component */
ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer2, i);
ASN1_PUSH(compstk, compsp, comp);
ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer2, i, 0);
ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer2, i, 0);
ASN1_FIXUP(compstk, compsp, buffer2, i);
ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer2, i, 2); /* reject */
ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer2, i);
ASN1_PUSH(compstk, compsp, comp);
ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer2, i, get_invokeid(pri));
res = asn1_string_encode(ASN1_INTEGER, &buffer2[i], sizeof(buffer2)-i, sizeof(op_tag), op_tag, sizeof(op_tag));
if (res < 0)
return -1;
i += res;
ASN1_ADD_SIMPLE(comp, (ASN1_SEQUENCE | ASN1_CONSTRUCTOR), buffer2, i);
ASN1_PUSH(compstk, compsp, comp);
buffer2[i++] = (0x0a);
buffer2[i++] = (0x01);
buffer2[i++] = (0x01);
buffer2[i++] = (0x81);
buffer2[i++] = (0x00);
buffer2[i++] = (0x0a);
buffer2[i++] = (0x01);
buffer2[i++] = (0x01);
ASN1_ADD_WORDCOMP(comp, ASN1_INTEGER, buffer2, i, call_reference);
ASN1_FIXUP(compstk, compsp, buffer2, i);
ASN1_FIXUP(compstk, compsp, buffer2, i);
res = pri_call_apdu_queue(c2, Q931_FACILITY, buffer2, i, NULL, NULL);
if (res) {
pri_message(pri, "Could not queue ADPU in facility message\n");
return -1;
}
/* Remember that if we queue a facility IE for a facility message we
* have to explicitly send the facility message ourselves */
res = q931_facility(c2->pri, c2);
if (res) {
pri_message(pri, "Could not schedule facility message for call %d\n", c1->cr);
return -1;
}
return 0;
}
/* End AFN-PR */
/* AOC */
static int aoc_aoce_charging_request_decode(struct pri *pri, q931_call *call, unsigned char *data, int len)
{
@@ -1543,433 +1348,7 @@ static int aoc_aoce_charging_unit_encode(struct pri *pri, q931_call *c, long cha
}
/* End AOC */
/* ===== Call Transfer Supplementary Service (ECMA-178) ===== */
static int rose_party_number_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberunscreened *value)
{
int i = 0;
int size = 0;
struct rose_component *comp = NULL;
unsigned char *vdata = data;
do {
GET_COMPONENT(comp, i, vdata, len);
switch(comp->type) {
case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0): /* [0] IMPLICIT NumberDigits -- default: unknownPartyNumber */
if (pri->debug & PRI_DEBUG_APDU)
pri_message(pri, " PartyNumber: UnknownPartyNumber len=%d\n", len);
size = rose_number_digits_decode(pri, call, comp->data, comp->len, value);
if (size < 0)
return -1;
value->npi = PRI_NPI_UNKNOWN;
value->ton = PRI_TON_UNKNOWN;
break;
case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1): /* [1] IMPLICIT PublicPartyNumber */
if (pri->debug & PRI_DEBUG_APDU)
pri_message(pri, " PartyNumber: PublicPartyNumber len=%d\n", len);
size = rose_public_party_number_decode(pri, call, comp->data, comp->len, value);
if (size < 0)
return -1;
value->npi = PRI_NPI_E163_E164;
break;
case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_3): /* [3] IMPLICIT NumberDigits -- not used: dataPartyNumber */
pri_message(pri, "!! PartyNumber: dataPartyNumber is reserved!\n");
size = rose_number_digits_decode(pri, call, comp->data, comp->len, value);
if (size < 0)
return -1;
value->npi = PRI_NPI_X121 /* ??? */;
value->ton = PRI_TON_UNKNOWN /* ??? */;
break;
case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_4): /* [4] IMPLICIT NumberDigits -- not used: telexPartyNumber */
pri_message(pri, "!! PartyNumber: telexPartyNumber is reserved!\n");
size = rose_number_digits_decode(pri, call, comp->data, comp->len, value);
if (size < 0)
return -1;
value->npi = PRI_NPI_F69 /* ??? */;
value->ton = PRI_TON_UNKNOWN /* ??? */;
break;
case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_5): /* [5] IMPLICIT PrivatePartyNumber */
if (pri->debug & PRI_DEBUG_APDU)
pri_message(pri, " PartyNumber: PrivatePartyNumber len=%d\n", len);
size = rose_private_party_number_decode(pri, call, comp->data, comp->len, value);
if (size < 0)
return -1;
value->npi = PRI_NPI_PRIVATE;
break;
case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_8): /* [8] IMPLICIT NumberDigits -- not used: nationalStandatdPartyNumber */
pri_message(pri, "!! PartyNumber: nationalStandardPartyNumber is reserved!\n");
size = rose_number_digits_decode(pri, call, comp->data, comp->len, value);
if (size < 0)
return -1;
value->npi = PRI_NPI_NATIONAL;
value->ton = PRI_TON_NATIONAL;
break;
default:
pri_message(pri, "Invalid PartyNumber component 0x%X\n", comp->type);
return -1;
}
ASN1_FIXUP_LEN(comp, size);
if (pri->debug & PRI_DEBUG_APDU)
pri_message(pri, " PartyNumber: '%s' size=%d len=%d\n", value->partyaddress, size, len);
return size;
}
while (0);
return -1;
}
static int rose_number_screened_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberscreened *value)
{
int i = 0;
int size = 0;
struct rose_component *comp = NULL;
unsigned char *vdata = data;
int scrind = -1;
do {
/* Party Number */
GET_COMPONENT(comp, i, vdata, len);
size = rose_party_number_decode(pri, call, (u_int8_t *)comp, comp->len + 2, (struct addressingdataelements_presentednumberunscreened*) value);
if (size < 0)
return -1;
comp->len = size;
NEXT_COMPONENT(comp, i);
/* Screening Indicator */
GET_COMPONENT(comp, i, vdata, len);
CHECK_COMPONENT(comp, ASN1_ENUMERATED, "Don't know what to do with NumberScreened ROSE component type 0x%x\n");
ASN1_GET_INTEGER(comp, scrind);
// Todo: scrind = screeningindicator_for_q931(pri, scrind);
NEXT_COMPONENT(comp, i);
value->scrind = scrind;
if (pri->debug & PRI_DEBUG_APDU)
pri_message(pri, " NumberScreened: '%s' ScreeningIndicator=%d i=%d len=%d\n", value->partyaddress, scrind, i, len);
return i-2; // We do not have a sequence header here.
}
while (0);
return -1;
}
static int rose_presented_number_screened_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberscreened *value)
{
int i = 0;
int size = 0;
struct rose_component *comp = NULL;
unsigned char *vdata = data;
/* Fill in default values */
value->ton = PRI_TON_UNKNOWN;
value->npi = PRI_NPI_UNKNOWN;
value->pres = -1; /* Data is not available */
do {
GET_COMPONENT(comp, i, vdata, len);
switch(comp->type) {
case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0): /* [0] IMPLICIT presentationAllowedNumber */
if (pri->debug & PRI_DEBUG_APDU)
pri_message(pri, " PresentedNumberScreened: presentationAllowedNumber comp->len=%d\n", comp->len);
value->pres = PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN;
size = rose_number_screened_decode(pri, call, comp->data, comp->len, value);
if (size < 0)
return -1;
ASN1_FIXUP_LEN(comp, size);
return size + 2;
case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1): /* [1] IMPLICIT presentationRestricted */
if (pri->debug & PRI_DEBUG_APDU)
pri_message(pri, " PresentedNumberScreened: presentationRestricted comp->len=%d\n", comp->len);
if (comp->len != 0) { /* must be NULL */
pri_error(pri, "!! Invalid PresentationRestricted component received (len != 0)\n");
return -1;
}
value->pres = PRES_PROHIB_USER_NUMBER_PASSED_SCREEN;
return 2;
case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2): /* [2] IMPLICIT numberNotAvailableDueToInterworking */
if (pri->debug & PRI_DEBUG_APDU)
pri_message(pri, " PresentedNumberScreened: NumberNotAvailableDueToInterworking comp->len=%d\n", comp->len);
if (comp->len != 0) { /* must be NULL */
pri_error(pri, "!! Invalid NumberNotAvailableDueToInterworking component received (len != 0)\n");
return -1;
}
value->pres = PRES_NUMBER_NOT_AVAILABLE;
if (pri->debug & PRI_DEBUG_APDU)
pri_message(pri, " PresentedNumberScreened: numberNotAvailableDueToInterworking Type=0x%X i=%d len=%d size=%d\n", comp->type, i, len);
return 2;
case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_3): /* [3] IMPLICIT presentationRestrictedNumber */
if (pri->debug & PRI_DEBUG_APDU)
pri_message(pri, " PresentedNumberScreened: presentationRestrictedNumber comp->len=%d\n", comp->len);
value->pres = PRES_PROHIB_USER_NUMBER_PASSED_SCREEN;
size = rose_number_screened_decode(pri, call, comp->data, comp->len, value);
if (size < 0)
return -1;
ASN1_FIXUP_LEN(comp, size);
return size + 2;
default:
pri_message(pri, "Invalid PresentedNumberScreened component 0x%X\n", comp->type);
}
return -1;
}
while (0);
return -1;
}
static int rose_call_transfer_complete_decode(struct pri *pri, q931_call *call, struct rose_component *sequence, int len)
{
int i = 0;
struct rose_component *comp = NULL;
unsigned char *vdata = sequence->data;
int res = 0;
int end_designation = 0;
struct addressingdataelements_presentednumberscreened redirection_number;
char redirection_name[50] = "";
int call_status = 0;
redirection_number.partyaddress[0] = 0;
redirection_number.partysubaddress[0] = 0;
call->callername[0] = 0;
call->callernum[0] = 0;
/* Data checks */
if (sequence->type != (ASN1_CONSTRUCTOR | ASN1_SEQUENCE)) { /* Constructed Sequence */
pri_message(pri, "Invalid callTransferComplete argument. (Not a sequence)\n");
return -1;
}
if (sequence->len == ASN1_LEN_INDEF) {
len -= 4; /* For the 2 extra characters at the end
* and two characters of header */
} else
len -= 2;
if (pri->debug & PRI_DEBUG_APDU)
pri_message(pri, " CT-Complete: len=%d\n", len);
do {
/* End Designation */
GET_COMPONENT(comp, i, vdata, len);
CHECK_COMPONENT(comp, ASN1_ENUMERATED, "Invalid endDesignation type 0x%X of ROSE callTransferComplete component received\n");
ASN1_GET_INTEGER(comp, end_designation);
NEXT_COMPONENT(comp, i);
if (pri->debug & PRI_DEBUG_APDU)
pri_message(pri, " CT-Complete: Received endDesignation=%d\n", end_designation);
/* Redirection Number */
GET_COMPONENT(comp, i, vdata, len);
res = rose_presented_number_screened_decode(pri, call, (u_int8_t *)comp, comp->len + 2, &redirection_number);
if (res < 0)
return -1;
comp->len = res;
if (res > 2) {
if (pri->debug & PRI_DEBUG_APDU)
pri_message(pri, " CT-Complete: Received redirectionNumber=%s\n", redirection_number.partyaddress);
strncpy(call->callernum, redirection_number.partyaddress, 20);
call->callernum[20] = 0;
}
NEXT_COMPONENT(comp, i);
#if 0 /* This one is optional. How do we check if it is there? */
/* Basic Call Info Elements */
GET_COMPONENT(comp, i, vdata, len);
NEXT_COMPONENT(comp, i);
#endif
/* Redirection Name */
GET_COMPONENT(comp, i, vdata, len);
res = asn1_name_decode((u_int8_t *)comp, comp->len + 2, redirection_name, sizeof(redirection_name));
if (res < 0)
return -1;
memcpy(call->callername, comp->data, comp->len);
call->callername[comp->len] = 0;
ASN1_FIXUP_LEN(comp, res);
comp->len = res;
NEXT_COMPONENT(comp, i);
if (pri->debug & PRI_DEBUG_APDU)
pri_message(pri, " CT-Complete: Received redirectionName '%s'\n", redirection_name);
/* Call Status */
GET_COMPONENT(comp, i, vdata, len);
CHECK_COMPONENT(comp, ASN1_ENUMERATED, "Invalid callStatus type 0x%X of ROSE callTransferComplete component received\n");
ASN1_GET_INTEGER(comp, call_status);
NEXT_COMPONENT(comp, i);
if (pri->debug & PRI_DEBUG_APDU)
pri_message(pri, " CT-Complete: Received callStatus=%d\n", call_status);
/* Argument Extension */
#if 0 /* Not supported */
GET_COMPONENT(comp, i, vdata, len);
switch (comp->type) {
case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_9): /* [9] IMPLICIT Extension */
res = rose_extension_decode(pri, call, comp->data, comp->len, &redirection_number);
if (res < 0)
return -1;
ASN1_FIXUP_LEN(comp, res);
comp->len = res;
case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_10): /* [10] IMPLICIT SEQUENCE OF Extension */
res = rose_sequence_of_extension_decode(pri, call, comp->data, comp->len, &redirection_number);
if (res < 0)
return -1;
ASN1_FIXUP_LEN(comp, res);
comp->len = res;
default:
pri_message(pri, " CT-Complete: !! Unknown argumentExtension received 0x%X\n", comp->type);
return -1;
}
#else
GET_COMPONENT(comp, i, vdata, len);
ASN1_FIXUP_LEN(comp, res);
NEXT_COMPONENT(comp, i);
#endif
if(i < len)
pri_message(pri, " CT-Complete: !! not all information is handled !! i=%d / len=%d\n", i, len);
return 0;
}
while (0);
return -1;
}
static int rose_call_transfer_update_decode(struct pri *pri, q931_call *call, struct rose_component *sequence, int len)
{
int i = 0;
struct rose_component *comp = NULL;
unsigned char *vdata = sequence->data;
int res = 0;
struct addressingdataelements_presentednumberscreened redirection_number;
redirection_number.partyaddress[0] = 0;
redirection_number.partysubaddress[0] = 0;
char redirection_name[50] = "";
call->callername[0] = 0;
call->callernum[0] = 0;
/* Data checks */
if (sequence->type != (ASN1_CONSTRUCTOR | ASN1_SEQUENCE)) { /* Constructed Sequence */
pri_message(pri, "Invalid callTransferComplete argument. (Not a sequence)\n");
return -1;
}
if (sequence->len == ASN1_LEN_INDEF) {
len -= 4; /* For the 2 extra characters at the end
* and two characters of header */
} else
len -= 2;
if (pri->debug & PRI_DEBUG_APDU)
pri_message(pri, " CT-Complete: len=%d\n", len);
do {
/* Redirection Number */
GET_COMPONENT(comp, i, vdata, len);
res = rose_presented_number_screened_decode(pri, call, (u_int8_t *)comp, comp->len + 2, &redirection_number);
if (res < 0)
return -1;
comp->len = res;
if (res > 2) {
if (pri->debug & PRI_DEBUG_APDU)
pri_message(pri, " CT-Complete: Received redirectionNumber=%s\n", redirection_number.partyaddress);
strncpy(call->callernum, redirection_number.partyaddress, 20);
call->callernum[20] = 0;
}
NEXT_COMPONENT(comp, i);
/* Redirection Name */
GET_COMPONENT(comp, i, vdata, len);
res = asn1_name_decode((u_int8_t *)comp, comp->len + 2, redirection_name, sizeof(redirection_name));
if (res < 0)
return -1;
memcpy(call->callername, comp->data, comp->len);
call->callername[comp->len] = 0;
ASN1_FIXUP_LEN(comp, res);
comp->len = res;
NEXT_COMPONENT(comp, i);
if (pri->debug & PRI_DEBUG_APDU)
pri_message(pri, " CT-Complete: Received redirectionName '%s'\n", redirection_name);
#if 0 /* This one is optional. How do we check if it is there? */
/* Basic Call Info Elements */
GET_COMPONENT(comp, i, vdata, len);
NEXT_COMPONENT(comp, i);
#endif
/* Argument Extension */
#if 0 /* Not supported */
GET_COMPONENT(comp, i, vdata, len);
switch (comp->type) {
case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_9): /* [9] IMPLICIT Extension */
res = rose_extension_decode(pri, call, comp->data, comp->len, &redirection_number);
if (res < 0)
return -1;
ASN1_FIXUP_LEN(comp, res);
comp->len = res;
case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_10): /* [10] IMPLICIT SEQUENCE OF Extension */
res = rose_sequence_of_extension_decode(pri, call, comp->data, comp->len, &redirection_number);
if (res < 0)
return -1;
ASN1_FIXUP_LEN(comp, res);
comp->len = res;
default:
pri_message(pri, " CT-Complete: !! Unknown argumentExtension received 0x%X\n", comp->type);
return -1;
}
#else
GET_COMPONENT(comp, i, vdata, len);
ASN1_FIXUP_LEN(comp, res);
NEXT_COMPONENT(comp, i);
#endif
if(i < len)
pri_message(pri, " CT-Complete: !! not all information is handled !! i=%d / len=%d\n", i, len);
return 0;
}
while (0);
return -1;
}
/* ===== End Call Transfer Supplementary Service (ECMA-178) ===== */
int rose_reject_decode(struct pri *pri, q931_call *call, q931_ie *ie, unsigned char *data, int len)
int rose_reject_decode(struct pri *pri, q931_call *call, unsigned char *data, int len)
{
int i = 0;
int problemtag = -1;
@@ -2037,7 +1416,7 @@ int rose_reject_decode(struct pri *pri, q931_call *call, q931_ie *ie, unsigned c
return -1;
}
int rose_return_error_decode(struct pri *pri, q931_call *call, q931_ie *ie, unsigned char *data, int len)
int rose_return_error_decode(struct pri *pri, q931_call *call, unsigned char *data, int len)
{
int i = 0;
int errorvalue = -1;
@@ -2101,7 +1480,7 @@ int rose_return_error_decode(struct pri *pri, q931_call *call, q931_ie *ie, unsi
return -1;
}
int rose_return_result_decode(struct pri *pri, q931_call *call, q931_ie *ie, unsigned char *data, int len)
int rose_return_result_decode(struct pri *pri, q931_call *call, unsigned char *data, int len)
{
int i = 0;
int operationidvalue = -1;
@@ -2163,10 +1542,9 @@ int rose_return_result_decode(struct pri *pri, q931_call *call, q931_ie *ie, uns
return -1;
}
int rose_invoke_decode(struct pri *pri, q931_call *call, q931_ie *ie, unsigned char *data, int len)
int rose_invoke_decode(struct pri *pri, q931_call *call, unsigned char *data, int len)
{
int i = 0;
int res = 0;
int operation_tag;
unsigned char *vdata = data;
struct rose_component *comp = NULL, *invokeid = NULL, *operationid = NULL;
@@ -2217,50 +1595,6 @@ int rose_invoke_decode(struct pri *pri, q931_call *call, q931_ie *ie, unsigned c
return -1;
}
break;
case ROSE_CALL_TRANSFER_IDENTIFY:
if (pri->debug & PRI_DEBUG_APDU)
pri_message(pri, "ROSE %i: CallTransferIdentify - not handled!\n", operation_tag);
dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
return -1;
case ROSE_CALL_TRANSFER_ABANDON:
if (pri->debug & PRI_DEBUG_APDU)
pri_message(pri, "ROSE %i: CallTransferAbandon - not handled!\n", operation_tag);
dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
return -1;
case ROSE_CALL_TRANSFER_INITIATE:
if (pri->debug & PRI_DEBUG_APDU)
pri_message(pri, "ROSE %i: CallTransferInitiate - not handled!\n", operation_tag);
dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
return -1;
case ROSE_CALL_TRANSFER_SETUP:
if (pri->debug & PRI_DEBUG_APDU)
pri_message(pri, "ROSE %i: CallTransferSetup - not handled!\n", operation_tag);
dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
return -1;
case ROSE_CALL_TRANSFER_ACTIVE:
if (pri->debug & PRI_DEBUG_APDU)
pri_message(pri, "ROSE %i: CallTransferActive - not handled!\n", operation_tag);
dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
return -1;
case ROSE_CALL_TRANSFER_COMPLETE:
if (pri->debug & PRI_DEBUG_APDU)
{
pri_message(pri, "ROSE %i: Handle CallTransferComplete\n", operation_tag);
dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
}
return rose_call_transfer_complete_decode(pri, call, comp, len-i);
case ROSE_CALL_TRANSFER_UPDATE:
if (pri->debug & PRI_DEBUG_APDU)
{
pri_message(pri, "ROSE %i: Handle CallTransferUpdate\n", operation_tag);
dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
}
return rose_call_transfer_update_decode(pri, call, comp, len-i);
case ROSE_SUBADDRESS_TRANSFER:
if (pri->debug & PRI_DEBUG_APDU)
pri_message(pri, "ROSE %i: SubaddressTransfer - not handled!\n", operation_tag);
dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
return -1;
case ROSE_DIVERTING_LEG_INFORMATION2:
if (pri->debug & PRI_DEBUG_APDU)
pri_message(pri, " Handle DivertingLegInformation2\n");
@@ -2315,15 +1649,6 @@ int rose_invoke_decode(struct pri *pri, q931_call *call, q931_ie *ie, unsigned c
dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
}
return -1;
case SS_ANFPR_PATHREPLACEMENT:
/* Clear Queue */
res = pri_call_apdu_queue_cleanup(call->bridged_call);
if (res) {
pri_message(pri, "Could not Clear queue ADPU\n");
return -1;
}
anfpr_pathreplacement_respond(pri, call, ie);
break;
default:
if (pri->debug & PRI_DEBUG_APDU) {
pri_message(pri, "!! Unable to handle ROSE operation %d", operation_tag);
@@ -2344,16 +1669,19 @@ int pri_call_apdu_queue(q931_call *call, int messagetype, void *apdu, int apdu_l
if (!call || !messagetype || !apdu || (apdu_len < 1) || (apdu_len > 255))
return -1;
if (!(new_event = calloc(1, sizeof(*new_event)))) {
new_event = malloc(sizeof(struct apdu_event));
if (new_event) {
memset(new_event, 0, sizeof(struct apdu_event));
new_event->message = messagetype;
new_event->callback = function;
new_event->data = data;
memcpy(new_event->apdu, apdu, apdu_len);
new_event->apdu_len = apdu_len;
} else {
pri_error(call->pri, "!! Malloc failed!\n");
return -1;
}
new_event->message = messagetype;
new_event->callback = function;
new_event->data = data;
memcpy(new_event->apdu, apdu, apdu_len);
new_event->apdu_len = apdu_len;
if (call->apdus) {
cur = call->apdus;

View File

@@ -9,7 +9,6 @@
#ifndef _PRI_FACILITY_H
#define _PRI_FACILITY_H
#include "pri_q931.h"
/* Protocol Profile field */
#define Q932_PROTOCOL_ROSE 0x11 /* X.219 & X.229 */
@@ -33,15 +32,6 @@
#define COMP_TYPE_NFE 0xAA
/* Operation ID values */
/* Q.952.7 (ECMA-178) ROSE operations (Transfer) */
#define ROSE_CALL_TRANSFER_IDENTIFY 7
#define ROSE_CALL_TRANSFER_ABANDON 8
#define ROSE_CALL_TRANSFER_INITIATE 9
#define ROSE_CALL_TRANSFER_SETUP 10
#define ROSE_CALL_TRANSFER_ACTIVE 11
#define ROSE_CALL_TRANSFER_COMPLETE 12
#define ROSE_CALL_TRANSFER_UPDATE 13
#define ROSE_SUBADDRESS_TRANSFER 14
/* Q.952 ROSE operations (Diverting) */
#define ROSE_DIVERTING_LEG_INFORMATION1 18
#define ROSE_DIVERTING_LEG_INFORMATION2 0x15
@@ -58,7 +48,6 @@
#define ROSE_AOC_IDENTIFICATION_OF_CHARGE 37
/* Q.SIG operations */
#define SS_CNID_CALLINGNAME 0
#define SS_ANFPR_PATHREPLACEMENT 4
#define SS_DIVERTING_LEG_INFORMATION2 21
#define SS_MWI_ACTIVATE 80
#define SS_MWI_DEACTIVATE 81
@@ -157,8 +146,7 @@ struct rose_component {
u_int8_t data[0];
};
#if 1
#define GET_COMPONENT(component, idx, ptr, length) \
#define GET_COMPONENT(component, idx, ptr, length) \
if ((idx)+2 > (length)) \
break; \
(component) = (struct rose_component*)&((ptr)[idx]); \
@@ -166,24 +154,16 @@ struct rose_component {
if ((component)->len != ASN1_LEN_INDEF) \
pri_message(pri, "Length (%d) of 0x%X component is too long\n", (component)->len, (component)->type); \
}
#else /* Debugging */
#define GET_COMPONENT(component, idx, ptr, length) \
if ((idx)+2 > (length)) \
break; \
(component) = (struct rose_component*)&((ptr)[idx]); \
if ((idx)+(component)->len+2 > (length)) { \
if ((component)->len != 128) \
pri_message(pri, "Length (%d) of 0x%X component is too long\n", (component)->len, (component)->type); \
} \
pri_message(pri, "XX %s:%d Got component %d (0x%02X), length %d\n", __FUNCTION__, __LINE__, (component)->type, (component)->type, (component)->len); \
/*
pri_message("XX Got component %d (0x%02X), length %d\n", (component)->type, (component)->type, (component)->len); \
if ((component)->len > 0) { \
int zzz; \
pri_message(pri, "XX Data:"); \
pri_message("XX Data:"); \
for (zzz = 0; zzz < (component)->len; ++zzz) \
pri_message(pri, " %02X", (component)->data[zzz]); \
pri_message(pri, "\n"); \
pri_message(" %02X", (component)->data[zzz]); \
pri_message("\n"); \
}
#endif
*/
#define NEXT_COMPONENT(component, idx) \
(idx) += (component)->len + 2
@@ -256,16 +236,16 @@ struct rose_component {
} while (0)
/* Decoder for the invoke ROSE component */
int rose_invoke_decode(struct pri *pri, struct q931_call *call, q931_ie *ie, unsigned char *data, int len);
int rose_invoke_decode(struct pri *pri, struct q931_call *call, unsigned char *data, int len);
/* Decoder for the return result ROSE component */
int rose_return_result_decode(struct pri *pri, struct q931_call *call, q931_ie *ie, unsigned char *data, int len);
int rose_return_result_decode(struct pri *pri, struct q931_call *call, unsigned char *data, int len);
/* Decoder for the return error ROSE component */
int rose_return_error_decode(struct pri *pri, struct q931_call *call, q931_ie *ie, unsigned char *data, int len);
int rose_return_error_decode(struct pri *pri, struct q931_call *call, unsigned char *data, int len);
/* Decoder for the reject ROSE component */
int rose_reject_decode(struct pri *pri, struct q931_call *call, q931_ie *ie, unsigned char *data, int len);
int rose_reject_decode(struct pri *pri, struct q931_call *call, unsigned char *data, int len);
int asn1_copy_string(char * buf, int buflen, struct rose_component *comp);
@@ -286,9 +266,6 @@ int eect_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2);
int rlt_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2);
/* starts a QSIG Path Replacement */
extern int anfpr_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2);
/* Use this function to queue a facility-IE born APDU onto a call
* call is the call to use, messagetype is any one of the Q931 messages,
* apdu is the apdu data, apdu_len is the length of the apdu data */

View File

@@ -25,7 +25,6 @@
#ifndef _PRI_INTERNAL_H
#define _PRI_INTERNAL_H
#include <stddef.h>
#include <sys/time.h>
#define DBGHEAD __FILE__ ":%d %s: "
@@ -64,8 +63,6 @@ struct pri {
int sapi;
int tei;
int protodisc;
unsigned int bri:1;
unsigned int acceptinbandrelease:1; /* Should we allow inband progress after RELEASE? */
/* Q.921 State */
int q921_state;
@@ -85,11 +82,7 @@ struct pri {
/* Various timers */
int sabme_timer; /* SABME retransmit */
int sabme_count; /* SABME retransmit counter for BRI */
int t203_timer; /* Max idle time */
int t202_timer;
int n202_counter;
int ri;
int t200_timer; /* T-200 retransmission timer */
/* All ISDN Timer values */
int timers[MAX_TIMERS];
@@ -253,9 +246,6 @@ struct q931_call {
int transferable;
unsigned int rlt_call_id; /* RLT call id */
/* Bridged call info */
q931_call *bridged_call; /* Pointer to other leg of bridged call */
};
extern int pri_schedule_event(struct pri *pri, int ms, void (*function)(void *data), void *data);
@@ -272,8 +262,4 @@ extern void pri_error(struct pri *pri, char *fmt, ...);
void libpri_copy_string(char *dst, const char *src, size_t size);
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);
void __pri_free_tei(struct pri *p);
#endif

View File

@@ -46,11 +46,10 @@
#define Q921_FRAMETYPE_I 0x0
#define Q921_FRAMETYPE_S 0x1
#define Q921_TEI_GROUP 127
#define Q921_TEI_PRI 0
#define Q921_TEI_GROUP 127
#define Q921_TEI_GR303_EOC_PATH 0
#define Q921_TEI_GR303_EOC_OPS 4
#define Q921_TEI_GR303_TMC_SWITCHING 0
#define Q921_TEI_GR303_TMC_SWITCHING 0
#define Q921_TEI_GR303_TMC_CALLPROC 0
#define Q921_SAPI_CALL_CTRL 0
@@ -64,14 +63,6 @@
#define Q921_SAPI_LAYER2_MANAGEMENT 63
#define Q921_TEI_IDENTITY_REQUEST 1
#define Q921_TEI_IDENTITY_ASSIGNED 2
#define Q921_TEI_IDENTITY_DENIED 3
#define Q921_TEI_IDENTITY_CHECK_REQUEST 4
#define Q921_TEI_IDENTITY_CHECK_RESPONSE 5
#define Q921_TEI_IDENTITY_REMOVE 6
#define Q921_TEI_IDENTITY_VERIFY 7
typedef struct q921_header {
#if __BYTE_ORDER == __BIG_ENDIAN
u_int8_t sapi:6; /* Service Access Point Indentifier (always 0 for PRI) (0) */
@@ -163,12 +154,6 @@ typedef struct q921_frame {
#define Q921_INC(j) (j) = (((j) + 1) % 128)
typedef enum q921_state {
Q921_DOWN = 0,
Q921_TEI_UNASSIGNED,
Q921_TEI_AWAITING_ESTABLISH,
Q921_TEI_AWAITING_ASSIGN,
Q921_TEI_ASSIGNED,
Q921_NEGOTIATION,
Q921_LINK_CONNECTION_RELEASED, /* Also known as TEI_ASSIGNED */
Q921_LINK_CONNECTION_ESTABLISHED,
Q921_AWAITING_ESTABLISH,

View File

@@ -26,37 +26,34 @@
#define _PRI_TIMERS_H
/* -1 means we dont currently support the timer/counter */
#define PRI_TIMERS_DEFAULT { \
3, /* N200 */ \
-1, /* N201 */ \
3, /* N202 */ \
7, /* K */ \
#define PRI_TIMERS_DEFAULT { 3, /* N200 */ \
-1, /* N201 */ \
-1, /* N202 */ \
7, /* K */ \
1000, /* T200 */ \
-1, /* T201 */ \
10000, /* T202 */ \
-1, /* T201 */ \
-1, /* T202 */ \
10000, /* T203 */ \
-1, /* T300 */ \
-1, /* T301 */ \
-1, /* T302 */ \
-1, /* T303 */ \
-1, /* T304 */ \
-1, /* T300 */ \
-1, /* T301 */ \
-1, /* T302 */ \
-1, /* T303 */ \
-1, /* T304 */ \
30000, /* T305 */ \
-1, /* T306 */ \
-1, /* T307 */ \
-1, /* T306 */ \
-1, /* T307 */ \
4000, /* T308 */ \
-1, /* T309 */ \
-1, /* T310 */ \
-1, /* T309 */ \
-1, /* T310 */ \
4000, /* T313 */ \
-1, /* T314 */ \
-1, /* T316 */ \
-1, /* T317 */ \
-1, /* T318 */ \
-1, /* T319 */ \
-1, /* T320 */ \
-1, /* T321 */ \
-1, /* T322 */ \
2500, /* TM20 - Q.921 Appendix IV */ \
3, /* NM20 - Q.921 Appendix IV */ \
-1, /* T314 */ \
-1, /* T316 */ \
-1, /* T317 */ \
-1, /* T318 */ \
-1, /* T319 */ \
-1, /* T320 */ \
-1, /* T321 */ \
-1 /* T322 */ \
}
/* XXX Only our default timers are setup now XXX */

View File

@@ -35,9 +35,6 @@ int pri_schedule_event(struct pri *pri, int ms, void (*function)(void *data), vo
{
int x;
struct timeval tv;
/* Scheduling runs on master channels only */
while (pri->master)
pri = pri->master;
for (x=1;x<MAX_SCHED;x++)
if (!pri->pri_sched[x].callback)
break;
@@ -116,8 +113,6 @@ pri_event *pri_schedule_run(struct pri *pri)
void pri_schedule_del(struct pri *pri,int id)
{
while (pri->master)
pri = pri->master;
if ((id >= MAX_SCHED) || (id < 0))
pri_error(pri, "Asked to delete sched id %d???\n", id);
pri->pri_sched[id].callback = NULL;

View File

@@ -294,7 +294,7 @@ static int run_pri(int dfd, int swtype, int node)
fd_set rfds, efds;
int res,x;
pri = pri_new_bri(dfd, 1, node, swtype);
pri = pri_new(dfd, node, swtype);
if (!pri) {
fprintf(stderr, "Unable to create PRI\n");
return -1;

402
q921.c
View File

@@ -51,8 +51,6 @@
} while(0)
static void reschedule_t203(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)
{
@@ -70,10 +68,8 @@ static void q921_discard_retransmissions(struct pri *pri)
static int q921_transmit(struct pri *pri, q921_h *h, int len)
{
int res;
if (pri->master)
pri = pri->master;
return q921_transmit(pri->master, h, len);
#ifdef RANDOM_DROPS
if (!(random() % 3)) {
pri_message(pri, " === Dropping Packet ===\n");
@@ -96,49 +92,6 @@ static int q921_transmit(struct pri *pri, q921_h *h, int len)
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;
@@ -190,15 +143,6 @@ static void q921_send_sabme(void *vpri, int now)
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);
@@ -379,7 +323,6 @@ static void q921_rr(struct pri *pri, int pbit, int cmd) {
static void t200_expire(void *vpri)
{
struct pri *pri = vpri;
if (pri->txqueue) {
/* Retransmit first packet in the queue, setting the poll bit */
if (pri->debug & PRI_DEBUG_Q921_DUMP)
@@ -391,35 +334,35 @@ static void t200_expire(void *vpri)
pri->v_na = pri->v_r;
pri->solicitfbit = 1;
pri->retrans++;
/* Up to three retransmissions */
if (pri->retrans < pri->timers[PRI_TIMER_N200]) {
/* 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");
q921_transmit(pri, (q921_h *)&pri->txqueue->h, pri->txqueue->len);
}
if (pri->debug & PRI_DEBUG_Q921_DUMP)
pri_message(pri, "-- Rescheduling retransmission (%d)\n", pri->retrans);
pri->t200_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri);
} else {
if (pri->debug & PRI_DEBUG_Q921_STATE)
pri_message(pri, "-- Timeout occured, restarting PRI\n");
if (pri->debug & PRI_DEBUG_Q921_STATE && pri->q921_state != Q921_LINK_CONNECTION_RELEASED)
pri_message(pri, DBGHEAD "q921_state now is Q921_LINK_CONNECTION_RELEASED\n",DBGINFO);
pri->q921_state = Q921_LINK_CONNECTION_RELEASED;
pri->t200_timer = 0;
q921_dchannel_down(pri);
q921_start(pri, 1);
pri->schedev = 1;
/* Up to three retransmissions */
if (pri->retrans < pri->timers[PRI_TIMER_N200]) {
/* 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");
q921_transmit(pri, (q921_h *)&pri->txqueue->h, pri->txqueue->len);
}
if (pri->debug & PRI_DEBUG_Q921_DUMP)
pri_message(pri, "-- Rescheduling retransmission (%d)\n", pri->retrans);
pri->t200_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri);
} else {
if (pri->debug & PRI_DEBUG_Q921_STATE)
pri_message(pri, "-- Timeout occured, restarting PRI\n");
if (pri->debug & PRI_DEBUG_Q921_STATE && pri->q921_state != Q921_LINK_CONNECTION_RELEASED)
pri_message(pri, DBGHEAD "q921_state now is Q921_LINK_CONNECTION_RELEASED\n",DBGINFO);
pri->q921_state = Q921_LINK_CONNECTION_RELEASED;
pri->t200_timer = 0;
q921_dchannel_down(pri);
q921_start(pri, 1);
pri->schedev = 1;
}
} else if (pri->solicitfbit) {
if (pri->debug & PRI_DEBUG_Q921_DUMP)
pri_message(pri, "-- Retrying poll with f-bit\n");
if (pri->debug & PRI_DEBUG_Q921_DUMP)
pri_message(pri, "-- Retrying poll with f-bit\n");
pri->retrans++;
if (pri->retrans < pri->timers[PRI_TIMER_N200]) {
pri->solicitfbit = 1;
@@ -432,14 +375,9 @@ static void t200_expire(void *vpri)
pri_message(pri, DBGHEAD "q921_state now is Q921_LINK_CONNECTION_RELEASED\n", DBGINFO);
pri->q921_state = Q921_LINK_CONNECTION_RELEASED;
pri->t200_timer = 0;
if (pri->bri && pri->master) {
q921_tei_release_and_reacquire(pri->master);
return;
} else {
q921_dchannel_down(pri);
q921_start(pri, 1);
pri->schedev = 1;
}
q921_dchannel_down(pri);
q921_start(pri, 1);
pri->schedev = 1;
}
} else {
pri_error(pri, "T200 counter expired, nothing to send...\n");
@@ -450,10 +388,10 @@ static void t200_expire(void *vpri)
int q921_transmit_iframe(struct pri *pri, void *buf, int len, int cr)
{
q921_frame *f, *prev=NULL;
for (f=pri->txqueue; f; f = f->next) prev = f;
f = calloc(1, sizeof(q921_frame) + len + 2);
f = malloc(sizeof(q921_frame) + len + 2);
if (f) {
memset(f,0,sizeof(q921_frame) + len + 2);
Q921_INIT(pri, f->h);
switch(pri->localtype) {
case PRI_NETWORK:
@@ -715,10 +653,8 @@ static pri_event *q921_dchannel_up(struct pri *pri)
q921_reset(pri);
/* Stop any SABME retransmissions */
if (pri->sabme_timer) {
pri_schedule_del(pri, pri->sabme_timer);
pri->sabme_timer = 0;
}
pri_schedule_del(pri, pri->sabme_timer);
pri->sabme_timer = 0;
/* Reset any rejects */
pri->sentrej = 0;
@@ -761,14 +697,10 @@ void q921_reset(struct pri *pri)
pri->v_na = 0;
pri->window = pri->timers[PRI_TIMER_K];
pri->windowlen = 0;
if (pri->sabme_timer)
pri_schedule_del(pri, pri->sabme_timer);
if (pri->t203_timer)
pri_schedule_del(pri, pri->t203_timer);
if (pri->t200_timer)
pri_schedule_del(pri, pri->t200_timer);
pri_schedule_del(pri, pri->sabme_timer);
pri_schedule_del(pri, pri->t203_timer);
pri_schedule_del(pri, pri->t200_timer);
pri->sabme_timer = 0;
pri->sabme_count = 0;
pri->t203_timer = 0;
pri->t200_timer = 0;
pri->busy = 0;
@@ -783,101 +715,6 @@ void q921_reset(struct pri *pri)
q921_discard_retransmissions(pri);
}
static void q921_tei_release_and_reacquire(struct pri *master)
{
/* Make sure the master is passed into this function */
q921_dchannel_down(master->subchannel);
__pri_free_tei(master->subchannel);
master->subchannel = NULL;
master->ev.gen.e = PRI_EVENT_DCHAN_DOWN;
master->schedev = 1;
q921_start(master, master->localtype == PRI_CPE);
}
static pri_event *q921_receive_MDL(struct pri *pri, q921_u *h, int len)
{
int ri;
struct pri *sub;
int tei;
if (pri->debug & PRI_DEBUG_Q921_STATE)
pri_message(pri, "Received MDL message\n");
if (h->data[0] != 0x0f) {
pri_error(pri, "Received MDL with unsupported management entity %02x\n", h->data[0]);
return NULL;
}
if (!(h->data[4] & 0x01)) {
pri_error(pri, "Received MDL with multibyte TEI identifier\n");
return NULL;
}
ri = (h->data[1] << 8) | h->data[2];
tei = (h->data[4] >> 1);
switch(h->data[3]) {
case Q921_TEI_IDENTITY_REQUEST:
if (tei != 127) {
pri_error(pri, "Received TEI identity request with invalid TEI %d\n", tei);
q921_send_tei(pri, Q921_TEI_IDENTITY_DENIED, ri, tei, 1);
}
/* Go to master */
for (sub = pri; sub->master; sub = sub->master);
tei = 64;
while(sub->subchannel) {
if(sub->subchannel->tei == tei)
++tei;
}
sub->subchannel = __pri_new_tei(-1, pri->localtype, pri->switchtype, pri, NULL, NULL, NULL, tei, 1);
if (!sub->subchannel) {
pri_error(pri, "Unable to allocate D-channel for new TEI %d\n", tei);
return NULL;
}
q921_send_tei(pri, Q921_TEI_IDENTITY_ASSIGNED, ri, tei, 1);
break;
case Q921_TEI_IDENTITY_ASSIGNED:
if (ri != pri->ri) {
pri_message(pri, "TEI assignment received for invalid Ri %02x (our is %02x)\n", ri, pri->ri);
return NULL;
}
if (pri->t202_timer) {
pri_schedule_del(pri, pri->t202_timer);
pri->t202_timer = 0;
}
if (pri->subchannel && (pri->subchannel->tei == tei)) {
pri_error(pri, "TEI already assigned (new is %d, current is %d)\n", tei, pri->subchannel->tei);
q921_tei_release_and_reacquire(pri);
return NULL;
}
pri_message(pri, "TEI assiged to %d\n", tei);
pri->subchannel = __pri_new_tei(-1, pri->localtype, pri->switchtype, pri, NULL, NULL, NULL, tei, 1);
if (!pri->subchannel) {
pri_error(pri, "Unable to allocate D-channel for new TEI %d\n", tei);
return NULL;
}
pri->q921_state = Q921_TEI_ASSIGNED;
break;
case Q921_TEI_IDENTITY_CHECK_REQUEST:
/* We're assuming one TEI per PRI in TE PTMP mode */
/* If no subchannel (TEI) ignore */
if (!pri->subchannel)
return NULL;
/* If it's addressed to the group TEI or to our TEI specifically, we respond */
if ((tei == Q921_TEI_GROUP) || (tei == pri->subchannel->tei))
q921_send_tei(pri, Q921_TEI_IDENTITY_CHECK_RESPONSE, random() % 65535, pri->subchannel->tei, 1);
break;
case Q921_TEI_IDENTITY_REMOVE:
/* XXX: Assuming multiframe mode has been disconnected already */
if (!pri->subchannel)
return NULL;
if ((tei == Q921_TEI_GROUP) || (tei == pri->subchannel->tei)) {
q921_tei_release_and_reacquire(pri);
}
}
return NULL; /* Do we need to return something??? */
}
static pri_event *__q921_receive_qualified(struct pri *pri, q921_h *h, int len)
{
q921_frame *f;
@@ -928,59 +765,59 @@ static pri_event *__q921_receive_qualified(struct pri *pri, q921_h *h, int len)
pri->solicitfbit = 0;
}
break;
case 1:
/* Receiver not ready */
if (pri->debug & PRI_DEBUG_Q921_STATE)
pri_message(pri, "-- Got receiver not ready\n");
if(h->s.p_f) {
/* Send RR if poll bit set */
q921_rr(pri, h->s.p_f, 0);
}
pri->busy = 1;
break;
case 2:
/* Just retransmit */
if (pri->debug & PRI_DEBUG_Q921_STATE)
pri_message(pri, "-- Got reject requesting packet %d... Retransmitting.\n", h->s.n_r);
if (h->s.p_f) {
/* If it has the poll bit set, send an appropriate supervisory response */
q921_rr(pri, 1, 0);
}
sendnow = 0;
/* Resend the proper I-frame */
for(f=pri->txqueue;f;f=f->next) {
if ((sendnow || (f->h.n_s == h->s.n_r)) && f->transmitted) {
/* Matches the request, or follows in our window, and has
already been transmitted. */
sendnow = 1;
pri_error(pri, "!! Got reject for frame %d, retransmitting frame %d now, updating n_r!\n", h->s.n_r, f->h.n_s);
f->h.n_r = pri->v_r;
q921_transmit(pri, (q921_h *)(&f->h), f->len);
}
}
if (!sendnow) {
if (pri->txqueue) {
/* This should never happen */
if (!h->s.p_f || h->s.n_r) {
pri_error(pri, "!! Got reject for frame %d, but we only have others!\n", h->s.n_r);
}
} else {
/* Hrm, we have nothing to send, but have been REJ'd. Reset v_a, v_s, etc */
pri_error(pri, "!! Got reject for frame %d, but we have nothing -- resetting!\n", h->s.n_r);
pri->v_a = h->s.n_r;
pri->v_s = h->s.n_r;
/* Reset t200 timer if it was somehow going */
if (pri->t200_timer) {
pri_schedule_del(pri, pri->t200_timer);
pri->t200_timer = 0;
}
/* Reset and restart t203 timer */
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);
}
}
break;
case 1:
/* Receiver not ready */
if (pri->debug & PRI_DEBUG_Q921_DUMP)
pri_message(pri, "-- Got receiver not ready\n");
if(h->s.p_f) {
/* Send RR if poll bit set */
q921_rr(pri, h->s.p_f, 0);
}
pri->busy = 1;
break;
case 2:
/* Just retransmit */
if (pri->debug & PRI_DEBUG_Q921_DUMP)
pri_message(pri, "-- Got reject requesting packet %d... Retransmitting.\n", h->s.n_r);
if (h->s.p_f) {
/* If it has the poll bit set, send an appropriate supervisory response */
q921_rr(pri, 1, 0);
}
sendnow = 0;
/* Resend the proper I-frame */
for(f=pri->txqueue;f;f=f->next) {
if ((sendnow || (f->h.n_s == h->s.n_r)) && f->transmitted) {
/* Matches the request, or follows in our window, and has
already been transmitted. */
sendnow = 1;
pri_error(pri, "!! Got reject for frame %d, retransmitting frame %d now, updating n_r!\n", h->s.n_r, f->h.n_s);
f->h.n_r = pri->v_r;
q921_transmit(pri, (q921_h *)(&f->h), f->len);
}
}
if (!sendnow) {
if (pri->txqueue) {
/* This should never happen */
if (!h->s.p_f || h->s.n_r) {
pri_error(pri, "!! Got reject for frame %d, but we only have others!\n", h->s.n_r);
}
} else {
/* Hrm, we have nothing to send, but have been REJ'd. Reset v_a, v_s, etc */
pri_error(pri, "!! Got reject for frame %d, but we have nothing -- resetting!\n", h->s.n_r);
pri->v_a = h->s.n_r;
pri->v_s = h->s.n_r;
/* Reset t200 timer if it was somehow going */
if (pri->t200_timer) {
pri_schedule_del(pri, pri->t200_timer);
pri->t200_timer = 0;
}
/* Reset and restart t203 timer */
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);
}
}
break;
default:
pri_error(pri, "!! XXX Unknown Supervisory frame ss=0x%02x,pf=%02xnr=%02x vs=%02x, va=%02x XXX\n", h->s.ss, h->s.p_f, h->s.n_r,
pri->v_s, pri->v_a);
@@ -1001,7 +838,7 @@ static pri_event *__q921_receive_qualified(struct pri *pri, q921_h *h, int len)
pri_message(pri, "-- Got DM Mode from peer.\n");
/* Disconnected mode, try again after T200 */
ev = q921_dchannel_down(pri);
q921_restart(pri, 0);
q921_start(pri, 0);
return ev;
} else {
@@ -1009,23 +846,12 @@ static pri_event *__q921_receive_qualified(struct pri *pri, q921_h *h, int len)
pri_message(pri, "-- Ignoring unsolicited DM with p/f set to 0\n");
#if 0
/* Requesting that we start */
q921_restart(pri, 0);
q921_start(pri, 0);
#endif
}
break;
} else if (!h->u.m2) {
if ((pri->sapi == Q921_SAPI_LAYER2_MANAGEMENT) && (pri->tei == Q921_TEI_GROUP))
q921_receive_MDL(pri, (q921_u *)h, len);
else {
int res;
res = q931_receive(pri, (q931_h *) h->u.data, len - 3);
if (res == -1) {
return NULL;
}
if (res & Q931_RES_HAVEEVENT)
return &pri->ev;
}
pri_message(pri, "XXX Unnumbered Information not implemented XXX\n");
}
break;
case 2:
@@ -1034,7 +860,7 @@ static pri_event *__q921_receive_qualified(struct pri *pri, q921_h *h, int len)
/* Acknowledge */
q921_send_ua(pri, h->u.p_f);
ev = q921_dchannel_down(pri);
q921_restart(pri, 0);
q921_start(pri, 0);
return ev;
case 3:
if (h->u.m2 == 3) {
@@ -1065,17 +891,8 @@ static pri_event *__q921_receive_qualified(struct pri *pri, q921_h *h, int len)
pri_message(pri, "-- Got UA from %s peer Link up.\n", h->h.c_r ? "cpe" : "network");
}
return q921_dchannel_up(pri);
} else if ((pri->q921_state >= Q921_TEI_ASSIGNED) && pri->bri) {
/* Possible duplicate TEI assignment */
if (pri->master)
q921_tei_release_and_reacquire(pri->master);
else
pri_error(pri, "Huh!? no master found\n");
} else {
/* Since we're not in the AWAITING_ESTABLISH STATE, it's unsolicited */
} else
pri_error(pri, "!! Got a UA, but i'm in state %d\n", pri->q921_state);
}
} else
pri_error(pri, "!! Weird frame received (m3=3, m2 = %d)\n", h->u.m2);
break;
@@ -1107,24 +924,21 @@ static pri_event *__q921_receive(struct pri *pri, q921_h *h, int len)
if (h->h.ea1 || !(h->h.ea2))
return NULL;
#if 0 /* Will be rejected by subchannel analyzis */
/* Check for broadcasts - not yet handled */
if (h->h.tei == Q921_TEI_GROUP)
return NULL;
#endif
if (!((h->h.sapi == pri->sapi) && ((h->h.tei == pri->tei) || (h->h.tei == Q921_TEI_GROUP)))) {
/* Check for SAPIs we don't yet handle */
/* Check for SAPIs we don't yet handle */
if ((h->h.sapi != pri->sapi) || (h->h.tei != pri->tei)) {
#ifdef PROCESS_SUBCHANNELS
/* If it's not us, try any subchannels we have */
if (pri->subchannel)
return q921_receive(pri->subchannel, h, len + 2);
else {
else
#endif
return NULL;
}
}
if (pri->debug & PRI_DEBUG_Q921_DUMP)
pri_message(pri, "Handling message for SAPI/TEI=%d/%d\n", h->h.sapi, h->h.tei);
ev = __q921_receive_qualified(pri, h, len);
reschedule_t203(pri);
return ev;
@@ -1140,7 +954,7 @@ pri_event *q921_receive(struct pri *pri, q921_h *h, int len)
return e;
}
static void q921_restart(struct pri *pri, int now)
void q921_start(struct pri *pri, int now)
{
if (pri->q921_state != Q921_LINK_CONNECTION_RELEASED) {
pri_error(pri, "!! q921_start: Not in 'Link Connection Released' state\n");
@@ -1151,15 +965,3 @@ static void q921_restart(struct pri *pri, int now)
/* Do the SABME XXX Maybe we should implement T_WAIT? XXX */
q921_send_sabme(pri, now);
}
void q921_start(struct pri *pri, int isCPE)
{
q921_reset(pri);
if ((pri->sapi == Q921_SAPI_LAYER2_MANAGEMENT) && (pri->tei == Q921_TEI_GROUP)) {
pri->q921_state = Q921_DOWN;
if (isCPE)
q921_tei_request(pri);
} else {
q921_send_sabme(pri, isCPE);
}
}

444
q931.c
View File

@@ -255,10 +255,18 @@ static char *code2str(int code, struct msgtype *codes, int max)
static void call_init(struct q931_call *c)
{
memset(c, 0, sizeof(*c));
c->alive = 0;
c->sendhangupack = 0;
c->forceinvert = -1;
c->cr = -1;
c->slotmap = -1;
c->channelno = -1;
c->ds1no = 0;
c->ds1explicit = 0;
c->chanflags = 0;
c->next = NULL;
c->sentchannel = 0;
c->newcall = 1;
c->ourcallstate = Q931_CALL_STATE_NULL;
c->peercallstate = Q931_CALL_STATE_NULL;
@@ -286,22 +294,15 @@ static FUNC_RECV(receive_channel_id)
}
#endif
#ifndef NOAUTO_CHANNEL_SELECTION_SUPPORT
if (pri->bri) {
if (!(ie->data[0] & 3))
switch (ie->data[0] & 3) {
case 0:
call->justsignalling = 1;
else
call->channelno = ie->data[0] & 3;
} else {
switch (ie->data[0] & 3) {
case 0:
call->justsignalling = 1;
break;
case 1:
break;
default:
pri_error(pri, "!! Unexpected Channel selection %d\n", ie->data[0] & 3);
return -1;
}
break;
case 1:
break;
default:
pri_error(pri, "!! Unexpected Channel selection %d\n", ie->data[0] & 3);
return -1;
}
#endif
if (ie->data[0] & 0x08)
@@ -365,11 +366,7 @@ static FUNC_SEND(transmit_channel_id)
/* Start with standard stuff */
if (pri->switchtype == PRI_SWITCH_GR303_TMC)
ie->data[pos] = 0x69;
else if (pri->bri) {
ie->data[pos] = 0x80;
if (call->channelno > -1)
ie->data[pos] |= (call->channelno & 0x3);
} else
else
ie->data[pos] = 0xa1;
/* Add exclusive flag if necessary */
if (call->chanflags & FLAG_EXCLUSIVE)
@@ -386,10 +383,6 @@ static FUNC_SEND(transmit_channel_id)
ie->data[pos++] = 0x80 | call->ds1no;
} else
pos++;
if (pri->bri)
return pos + 2;
if ((call->channelno > -1) || (call->slotmap != -1)) {
/* We'll have the octet 8.2 and 8.3's present */
ie->data[pos++] = 0x83;
@@ -421,7 +414,7 @@ static FUNC_DUMP(dump_channel_id)
int x;
int res = 0;
static const char* msg_chan_sel[] = {
"No channel selected", "B1 channel", "B2 channel","Any channel selected",
"No channel selected", "B1 channel", "B2 channel","Any channel selected"
"No channel selected", "As indicated in following octets", "Reserved","Any channel selected"
};
@@ -550,12 +543,12 @@ static char *mode2str(int mode)
static char *l12str(int proto)
{
static struct msgtype protos[] = {
{ PRI_LAYER_1_ITU_RATE_ADAPT, "V.110 Rate Adaption" },
{ PRI_LAYER_1_ITU_RATE_ADAPT, "ITU Rate Adaption" },
{ PRI_LAYER_1_ULAW, "u-Law" },
{ PRI_LAYER_1_ALAW, "A-Law" },
{ PRI_LAYER_1_G721, "G.721 ADPCM" },
{ PRI_LAYER_1_G722_G725, "G.722/G.725 7kHz Audio" },
{ PRI_LAYER_1_H223_H245, "H.223/H.245 Multimedia" },
{ PRI_LAYER_1_G7XX_384K, "G.7xx 384k Video" },
{ PRI_LAYER_1_NON_ITU_ADAPT, "Non-ITU Rate Adaption" },
{ PRI_LAYER_1_V120_RATE_ADAPT, "V.120 Rate Adaption" },
{ PRI_LAYER_1_X31_RATE_ADAPT, "X.31 Rate Adaption" },
@@ -566,7 +559,7 @@ static char *l12str(int proto)
static char *ra2str(int proto)
{
static struct msgtype protos[] = {
{ PRI_RATE_ADAPT_9K6, "9.6 kbit/s" },
{ RATE_ADAPT_56K, "from 56kbps" },
};
return code2str(proto, protos, sizeof(protos) / sizeof(protos[0]));
}
@@ -587,143 +580,31 @@ static char *l32str(int proto)
return code2str(proto, protos, sizeof(protos) / sizeof(protos[0]));
}
static char *int_rate2str(int proto)
{
static struct msgtype protos[] = {
{ PRI_INT_RATE_8K, "8 kbit/s" },
{ PRI_INT_RATE_16K, "16 kbit/s" },
{ PRI_INT_RATE_32K, "32 kbit/s" },
};
return code2str(proto, protos, sizeof(protos) / sizeof(protos[0]));
}
static FUNC_DUMP(dump_bearer_capability)
{
int pos=2;
pri_message(pri, "%c Bearer Capability (len=%2d) [ Ext: %d Q.931 Std: %d Info transfer capability: %s (%d)\n",
prefix, len, (ie->data[0] & 0x80 ) >> 7, (ie->data[0] & 0x60) >> 5, cap2str(ie->data[0] & 0x1f), (ie->data[0] & 0x1f));
pri_message(pri, "%c Ext: %d Trans mode/rate: %s (%d)\n", prefix, (ie->data[1] & 0x80) >> 7, mode2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f);
/* octet 4.1 exists iff mode/rate is multirate */
if ((ie->data[1] & 0x7f) == 0x18) {
pri_message(pri, "%c Ext: %d Transfer rate multiplier: %d x 64\n", prefix, (ie->data[2] & 0x80) >> 7, ie->data[2] & 0x7f);
pos++;
}
/* don't count the IE num and length as part of the data */
len -= 2;
/* Look for octet 5; this is identified by bits 5,6 == 01 */
if (pos < len &&
(ie->data[pos] & 0x60) == 0x20) {
/* although the layer1 is only the bottom 5 bits of the byte,
previous versions of this library passed bits 5&6 through
too, so we have to do the same for binary compatability */
u_int8_t layer1 = ie->data[pos] & 0x7f;
pri_message(pri, "%c User information layer 1: %s (%d)\n",
prefix, l12str(layer1), layer1);
/* Stop here if no more */
if (pos >= len)
return;
if ((ie->data[1] & 0x7f) != TRANS_MODE_PACKET) {
/* Look for octets 5 and 5.a if present */
pri_message(pri, "%c Ext: %d User information layer 1: %s (%d)\n", prefix, (ie->data[pos] >> 7), l12str(ie->data[pos] & 0x7f), ie->data[pos] & 0x7f);
if ((ie->data[pos] & 0x7f) == PRI_LAYER_1_ITU_RATE_ADAPT)
pri_message(pri, "%c Ext: %d Rate adaptatation: %s (%d)\n", prefix, ie->data[pos] >> 7, ra2str(ie->data[pos] & 0x7f), ie->data[pos] & 0x7f);
pos++;
/* octet 5a? */
if (pos < len && !(ie->data[pos-1] & 0x80)) {
int ra = ie->data[pos] & 0x7f;
pri_message(pri, "%c Async: %d, Negotiation: %d, "
"User rate: %s (%#x)\n",
prefix,
ra & PRI_RATE_ADAPT_ASYNC ? 1 : 0,
ra & PRI_RATE_ADAPT_NEGOTIATION_POSS ? 1 : 0,
ra2str(ra & PRI_RATE_USER_RATE_MASK),
ra & PRI_RATE_USER_RATE_MASK);
pos++;
}
/* octet 5b? */
if (pos < len && !(ie->data[pos-1] & 0x80)) {
u_int8_t data = ie->data[pos];
if (layer1 == PRI_LAYER_1_ITU_RATE_ADAPT) {
pri_message(pri, "%c Intermediate rate: %s (%d), "
"NIC on Tx: %d, NIC on Rx: %d, "
"Flow control on Tx: %d, "
"Flow control on Rx: %d\n",
prefix, int_rate2str((data & 0x60)>>5),
(data & 0x60)>>5,
(data & 0x10)?1:0,
(data & 0x08)?1:0,
(data & 0x04)?1:0,
(data & 0x02)?1:0);
} else if (layer1 == PRI_LAYER_1_V120_RATE_ADAPT) {
pri_message(pri, "%c Hdr: %d, Multiframe: %d, Mode: %d, "
"LLI negot: %d, Assignor: %d, "
"In-band neg: %d\n", prefix,
(data & 0x40)?1:0,
(data & 0x20)?1:0,
(data & 0x10)?1:0,
(data & 0x08)?1:0,
(data & 0x04)?1:0,
(data & 0x02)?1:0);
} else {
pri_message(pri, "%c Unknown octet 5b: 0x%x\n", data );
}
pos++;
}
/* octet 5c? */
if (pos < len && !(ie->data[pos-1] & 0x80)) {
u_int8_t data = ie->data[pos];
const char *stop_bits[] = {"?","1","1.5","2"};
const char *data_bits[] = {"?","5","7","8"};
const char *parity[] = {"Odd","?","Even","None",
"zero","one","?","?"};
pri_message(pri, "%c Stop bits: %s, data bits: %s, "
"parity: %s\n", prefix,
stop_bits[(data & 0x60) >> 5],
data_bits[(data & 0x18) >> 3],
parity[(data & 0x7)]);
pos++;
}
/* octet 5d? */
if (pos < len && !(ie->data[pos-1] & 0x80)) {
u_int8_t data = ie->data[pos];
pri_message(pri, "%c Duplex mode: %d, modem type: %d\n",
prefix, (data & 0x40) ? 1 : 0,data & 0x3F);
pos++;
}
}
/* Look for octet 6; this is identified by bits 5,6 == 10 */
if (pos < len &&
(ie->data[pos] & 0x60) == 0x40) {
pri_message(pri, "%c User information layer 2: %s (%d)\n",
prefix, l22str(ie->data[pos] & 0x1f),
ie->data[pos] & 0x1f);
} else {
/* Look for octets 6 and 7 but not 5 and 5.a */
pri_message(pri, "%c Ext: %d User information layer 2: %s (%d)\n", prefix, ie->data[pos] >> 7, l22str(ie->data[pos] & 0x7f), ie->data[pos] & 0x7f);
pos++;
}
/* Look for octet 7; this is identified by bits 5,6 == 11 */
if (pos < len && (ie->data[pos] & 0x60) == 0x60) {
pri_message(pri, "%c User information layer 3: %s (%d)\n",
prefix, l32str(ie->data[pos] & 0x1f),
ie->data[pos] & 0x1f);
pri_message(pri, "%c Ext: %d User information layer 3: %s (%d)\n", prefix, ie->data[pos] >> 7, l32str(ie->data[pos] & 0x7f), ie->data[pos] & 0x7f);
pos++;
/* octets 7a and 7b? */
if (pos + 1 < len && !(ie->data[pos-1] & 0x80) &&
!(ie->data[pos] & 0x80)) {
unsigned int proto;
proto = ((ie->data[pos] & 0xF) << 4 ) |
(ie->data[pos+1] & 0xF);
pri_message(pri, "%c Network layer: 0x%x\n", prefix,
proto );
pos += 2;
}
}
}
@@ -736,44 +617,18 @@ static FUNC_RECV(receive_bearer_capability)
}
call->transcapability = ie->data[0] & 0x1f;
call->transmoderate = ie->data[1] & 0x7f;
/* octet 4.1 exists iff mode/rate is multirate */
if (call->transmoderate == TRANS_MODE_MULTIRATE) {
call->transmultiple = ie->data[pos++] & 0x7f;
}
/* Look for octet 5; this is identified by bits 5,6 == 01 */
if (pos < len &&
(ie->data[pos] & 0x60) == 0x20 ) {
/* although the layer1 is only the bottom 5 bits of the byte,
previous versions of this library passed bits 5&6 through
too, so we have to do the same for binary compatability */
if (call->transmoderate == PRI_TRANS_CAP_AUDIO_4ESS)
call->transmoderate = PRI_TRANS_CAP_3_1K_AUDIO;
if (call->transmoderate != TRANS_MODE_PACKET) {
call->userl1 = ie->data[pos] & 0x7f;
pos++;
/* octet 5a? */
if (pos < len && !(ie->data[pos-1] & 0x80)) {
call->rateadaption = ie->data[pos] & 0x7f;
pos++;
}
/* octets 5b through 5d? */
while (pos < len && !(ie->data[pos-1] & 0x80)) {
pos++;
if (call->userl1 == PRI_LAYER_1_ITU_RATE_ADAPT) {
call->rateadaption = ie->data[++pos] & 0x7f;
}
}
/* Look for octet 6; this is identified by bits 5,6 == 10 */
if (pos < len &&
(ie->data[pos] & 0x60) == 0x40) {
call->userl2 = ie->data[pos++] & 0x1f;
}
/* Look for octet 7; this is identified by bits 5,6 == 11 */
if (pos < len &&
(ie->data[pos] & 0x60) == 0x60) {
call->userl3 = ie->data[pos++] & 0x1f;
pos++;
} else {
/* Get 6 and 7 */
call->userl2 = ie->data[pos++] & 0x7f;
call->userl3 = ie->data[pos] & 0x7f;
}
return 0;
}
@@ -781,14 +636,13 @@ static FUNC_RECV(receive_bearer_capability)
static FUNC_SEND(transmit_bearer_capability)
{
int tc;
int pos;
/* We are ready to transmit single IE only */
if(order > 1)
return 0;
tc = call->transcapability;
if (pri->subchannel && !pri->bri) {
if (pri->subchannel) {
/* Bearer capability is *hard coded* in GR-303 */
ie->data[0] = 0x88;
ie->data[1] = 0x90;
@@ -801,46 +655,33 @@ static FUNC_SEND(transmit_bearer_capability)
return 4;
}
if (pri->switchtype == PRI_SWITCH_ATT4ESS) {
/* 4ESS uses a different trans capability for 3.1khz audio */
if (tc == PRI_TRANS_CAP_3_1K_AUDIO)
tc = PRI_TRANS_CAP_AUDIO_4ESS;
}
ie->data[0] = 0x80 | tc;
ie->data[1] = call->transmoderate | 0x80;
pos = 2;
/* octet 4.1 exists iff mode/rate is multirate */
if (call->transmoderate == TRANS_MODE_MULTIRATE ) {
ie->data[pos++] = call->transmultiple | 0x80;
}
if ((tc & PRI_TRANS_CAP_DIGITAL) && (pri->switchtype == PRI_SWITCH_EUROISDN_E1) &&
(call->transmoderate == TRANS_MODE_PACKET)) {
if ((tc & PRI_TRANS_CAP_DIGITAL)&&(pri->switchtype == PRI_SWITCH_EUROISDN_E1)) {
/* Apparently EuroISDN switches don't seem to like user layer 2/3 */
return 4;
}
if (call->transmoderate != TRANS_MODE_PACKET) {
/* If you have an AT&T 4ESS, you don't send any more info */
if ((pri->switchtype != PRI_SWITCH_ATT4ESS) && (call->userl1 > -1)) {
ie->data[pos++] = call->userl1 | 0x80; /* XXX Ext bit? XXX */
ie->data[2] = call->userl1 | 0x80; /* XXX Ext bit? XXX */
if (call->userl1 == PRI_LAYER_1_ITU_RATE_ADAPT) {
ie->data[pos++] = call->rateadaption | 0x80;
ie->data[3] = call->rateadaption | 0x80;
return 6;
}
return pos + 2;
}
ie->data[pos++] = 0xa0 | (call->userl1 & 0x1f);
if (call->userl1 == PRI_LAYER_1_ITU_RATE_ADAPT) {
ie->data[pos-1] &= ~0x80; /* clear EXT bit in octet 5 */
ie->data[pos++] = call->rateadaption | 0x80;
}
}
if (call->userl2 != -1)
ie->data[pos++] = 0xc0 | (call->userl2 & 0x1f);
if (call->userl3 != -1)
ie->data[pos++] = 0xe0 | (call->userl3 & 0x1f);
return pos + 2;
return 5;
} else
return 4;
} else {
ie->data[2] = 0x80 | call->userl2;
ie->data[3] = 0x80 | call->userl3;
return 6;
}
}
char *pri_plan2str(int plan)
@@ -1333,7 +1174,7 @@ static FUNC_RECV(receive_facility)
state = my_state; \
if (pri->debug) \
pri_message(pri, "Handle Q.932 %s component\n", name); \
(handler)(pri, call, ie, comp->data, comp->len); \
(handler)(pri, call, comp->data, comp->len); \
break;
#define Q932_HANDLE_NULL(component, my_state, name, handle) \
case component: \
@@ -1428,7 +1269,7 @@ static FUNC_SEND(transmit_progress_indicator)
{
int code, mask;
/* Can't send progress indicator on GR-303 -- EVER! */
if (pri->subchannel && !pri->bri)
if (pri->subchannel)
return 0;
if (call->progressmask > 0) {
if (call->progressmask & (mask = PRI_PROG_CALL_NOT_E2E_ISDN))
@@ -2320,18 +2161,10 @@ static inline void q931_dumpie(struct pri *pri, int codeset, q931_ie *ie, char p
pri_error(pri, "!! %c Unknown IE %d (cs%d, len = %d)\n", prefix, Q931_IE_IE(base_ie), Q931_IE_CODESET(base_ie), ielen(ie));
}
static q931_call *q931_getcall(struct pri *pri, int cr, int outboundnew)
static q931_call *q931_getcall(struct pri *pri, int cr)
{
q931_call *cur, *prev;
struct pri *master;
/* Find the master - He has the call pool */
if (pri->master)
master = pri->master;
else
master = pri;
cur = *master->callpool;
cur = *pri->callpool;
prev = NULL;
while(cur) {
if (cur->cr == cr)
@@ -2342,59 +2175,41 @@ static q931_call *q931_getcall(struct pri *pri, int cr, int outboundnew)
/* No call exists, make a new one */
if (pri->debug & PRI_DEBUG_Q931_STATE)
pri_message(pri, "-- Making new call for cr %d\n", cr);
if (!(cur = calloc(1, sizeof(*cur))))
return NULL;
call_init(cur);
/* Call reference */
cur->cr = cr;
/* PRI is set to whoever called us */
if (pri->bri && (pri->localtype == PRI_CPE) && pri->subchannel && outboundnew)
cur->pri = pri->subchannel;
else
cur = malloc(sizeof(struct q931_call));
if (cur) {
call_init(cur);
/* Call reference */
cur->cr = cr;
cur->pri = pri;
/* Append to end of list */
if (prev)
prev->next = cur;
else
*master->callpool = cur;
/* Append to end of list */
if (prev)
prev->next = cur;
else
*pri->callpool = cur;
}
return cur;
}
q931_call *q931_new_call(struct pri *pri)
{
q931_call *cur;
do {
cur = *pri->callpool;
pri->cref++;
if (!pri->bri) {
if (pri->cref > 32767)
pri->cref = 1;
} else {
if (pri->cref > 127)
pri->cref = 1;
}
if (pri->cref > 32767)
pri->cref = 1;
while(cur) {
if (cur->cr == (0x8000 | pri->cref))
break;
cur = cur->next;
}
} while(cur);
return q931_getcall(pri, pri->cref | 0x8000, 1);
return q931_getcall(pri, pri->cref | 0x8000);
}
static void q931_destroy(struct pri *pri, int cr, q931_call *c)
{
q931_call *cur, *prev;
/* For destroying, make sure we are using the master span, since it maintains the call pool */
for (;pri->master; pri = pri->master);
prev = NULL;
cur = *pri->callpool;
while(cur) {
@@ -2559,40 +2374,26 @@ static void init_header(struct pri *pri, q931_call *call, unsigned char *buf, q9
{
/* Returns header and message header and modifies length in place */
q931_h *h = (q931_h *)buf;
q931_mh * mh;
q931_mh * mh = (q931_mh *)(h->contents + 2);
h->pd = pri->protodisc;
h->x0 = 0; /* Reserved 0 */
if (!pri->bri) {
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 && !pri->bri) {
/* On GR-303, top bit is always 0 */
h->crv[0] &= 0x7f;
}
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 {
h->crlen = 1;
if (call->cr || call->forceinvert) {
h->crv[0] = (((call->cr ^ 0x8000) & 0x8000) >> 8) | (call->cr & 0x7f);
} else {
/* Unless of course this has no call reference */
h->crv[0] = 0;
}
/* 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 = (q931_mh *)(h->contents + h->crlen);
mh->f = 0;
*hb = h;
*mhb = mh;
if (h->crlen == 2)
*len -= 5;
else
*len -= 4;
*len -= 5;
}
@@ -2641,7 +2442,7 @@ static int send_message(struct pri *pri, q931_call *c, int msgtype, int ies[])
}
/* Invert the logic */
len = sizeof(buf) - len;
q931_xmit(c->pri, h, len, 1);
q931_xmit(pri, h, len, 1);
c->acked = 1;
return 0;
}
@@ -2824,7 +2625,6 @@ int q931_setup_ack(struct pri *pri, q931_call *c, int channel, int nonisdn)
return send_message(pri, c, Q931_SETUP_ACKNOWLEDGE, connect_ies);
}
/* T313 expiry, first time */
static void pri_connect_timeout(void *data)
{
struct q931_call *c = data;
@@ -2835,7 +2635,6 @@ static void pri_connect_timeout(void *data)
}
/* T308 expiry, first time */
static void pri_release_timeout(void *data)
{
struct q931_call *c = data;
@@ -2844,12 +2643,9 @@ static void pri_release_timeout(void *data)
pri_message(pri, "Timed out looking for release complete\n");
c->t308_timedout++;
c->alive = 1;
/* The call to q931_release will re-schedule T308 */
q931_release(pri, c, c->cause);
q931_release(pri, c, PRI_CAUSE_NORMAL_CLEARING);
}
/* T308 expiry, second time */
static void pri_release_finaltimeout(void *data)
{
struct q931_call *c = data;
@@ -2871,7 +2667,6 @@ static void pri_release_finaltimeout(void *data)
q931_hangup(pri, c, c->cause);
}
/* T305 expiry, first time */
static void pri_disconnect_timeout(void *data)
{
struct q931_call *c = data;
@@ -2908,7 +2703,7 @@ int q931_connect(struct pri *pri, q931_call *c, int channel, int nonisdn)
if (c->retranstimer)
pri_schedule_del(pri, c->retranstimer);
c->retranstimer = 0;
if ((c->ourcallstate == Q931_CALL_STATE_CONNECT_REQUEST) && (pri->bri || (!pri->subchannel)))
if ((c->ourcallstate == Q931_CALL_STATE_CONNECT_REQUEST) && (!pri->subchannel))
c->retranstimer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T313], pri_connect_timeout, c);
return send_message(pri, c, Q931_CONNECT, connect_ies);
}
@@ -2944,7 +2739,7 @@ static int restart_ies[] = { Q931_CHANNEL_IDENT, Q931_RESTART_INDICATOR, -1 };
int q931_restart(struct pri *pri, int channel)
{
struct q931_call *c;
c = q931_getcall(pri, 0 | 0x8000, 0);
c = q931_getcall(pri, 0 | 0x8000);
if (!c)
return -1;
if (!channel)
@@ -2981,9 +2776,8 @@ int q931_disconnect(struct pri *pri, q931_call *c, int cause)
return 0;
}
static int setup_ies[] = { Q931_BEARER_CAPABILITY, Q931_CHANNEL_IDENT, Q931_IE_FACILITY, Q931_PROGRESS_INDICATOR, Q931_NETWORK_SPEC_FAC, Q931_DISPLAY,
Q931_CALLING_PARTY_NUMBER, Q931_CALLED_PARTY_NUMBER, Q931_REDIRECTING_NUMBER, Q931_IE_USER_USER, Q931_SENDING_COMPLETE,
Q931_IE_ORIGINATING_LINE_INFO, Q931_IE_GENERIC_DIGITS, -1 };
static int setup_ies[] = { Q931_BEARER_CAPABILITY, Q931_CHANNEL_IDENT, Q931_IE_FACILITY, Q931_PROGRESS_INDICATOR, Q931_NETWORK_SPEC_FAC, Q931_DISPLAY, Q931_IE_USER_USER,
Q931_CALLING_PARTY_NUMBER, Q931_CALLED_PARTY_NUMBER, Q931_REDIRECTING_NUMBER, Q931_SENDING_COMPLETE, Q931_IE_ORIGINATING_LINE_INFO, Q931_IE_GENERIC_DIGITS, -1 };
static int gr303_setup_ies[] = { Q931_BEARER_CAPABILITY, Q931_CHANNEL_IDENT, -1 };
@@ -2999,12 +2793,10 @@ int q931_setup(struct pri *pri, q931_call *c, struct pri_sr *req)
if (!req->userl1)
req->userl1 = PRI_LAYER_1_ULAW;
c->userl1 = req->userl1;
c->userl2 = -1;
c->userl3 = -1;
c->ds1no = (req->channel & 0xff00) >> 8;
c->ds1explicit = (req->channel & 0x10000) >> 16;
req->channel &= 0xff;
if ((pri->localtype == PRI_CPE) && pri->subchannel && !pri->bri) {
if ((pri->localtype == PRI_CPE) && pri->subchannel) {
req->channel = 0;
req->exclusive = 0;
}
@@ -3074,7 +2866,7 @@ int q931_setup(struct pri *pri, q931_call *c, struct pri_sr *req)
pri_call_add_standard_apdus(pri, c);
if (pri->subchannel && !pri->bri)
if (pri->subchannel)
res = send_message(pri, c, Q931_SETUP, gr303_setup_ies);
else if (c->justsignalling)
res = send_message(pri, c, Q931_SETUP, cis_setup_ies);
@@ -3118,7 +2910,7 @@ static int gr303_connect_acknowledge_ies[] = { Q931_CHANNEL_IDENT, -1 };
static int q931_connect_acknowledge(struct pri *pri, q931_call *c)
{
if (pri->subchannel && !pri->bri) {
if (pri->subchannel) {
if (pri->localtype == PRI_CPE)
return send_message(pri, c, Q931_CONNECT_ACKNOWLEDGE, gr303_connect_acknowledge_ies);
} else
@@ -3171,6 +2963,8 @@ int q931_hangup(struct pri *pri, q931_call *c, int cause)
/* sent CONNECT */
case Q931_CALL_STATE_INCOMING_CALL_PROCEEDING:
/* we sent CALL_PROCEEDING */
case Q931_CALL_STATE_ACTIVE:
/* received CONNECT */
case Q931_CALL_STATE_OVERLAP_RECEIVING:
/* received SETUP_ACKNOWLEDGE */
/* send DISCONNECT in general */
@@ -3184,10 +2978,6 @@ int q931_hangup(struct pri *pri, q931_call *c, int cause)
} else
pri_error(pri, "Wierd, doing nothing but this shouldn't happen, ourstate %s, peerstate %s\n",callstate2str(c->ourcallstate),callstate2str(c->peercallstate));
break;
case Q931_CALL_STATE_ACTIVE:
/* received CONNECT */
q931_disconnect(pri,c,cause);
break;
case Q931_CALL_STATE_DISCONNECT_REQUEST:
/* sent DISCONNECT */
q931_release(pri,c,cause);
@@ -3252,7 +3042,7 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
pri_error(pri, "Warning: unknown/inappropriate protocol discriminator received (%02x/%d)\n", h->pd, h->pd);
return 0;
}
c = q931_getcall(pri, q931_cr(h), 0);
c = q931_getcall(pri, q931_cr(h));
if (!c) {
pri_error(pri, "Unable to locate call %d\n", q931_cr(h));
return -1;
@@ -3556,16 +3346,6 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
pri->ev.ringing.progressmask = c->progressmask;
libpri_copy_string(pri->ev.ringing.useruserinfo, c->useruserinfo, sizeof(pri->ev.ringing.useruserinfo));
c->useruserinfo[0] = '\0';
cur = c->apdus;
while (cur) {
if (!cur->sent && cur->message == Q931_FACILITY) {
q931_facility(pri, c);
break;
}
cur = cur->next;
}
return Q931_RES_HAVEEVENT;
case Q931_CONNECT:
if (c->newcall) {
@@ -3601,8 +3381,6 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
libpri_copy_string(pri->ev.facname.callingname, c->callername, sizeof(pri->ev.facname.callingname));
libpri_copy_string(pri->ev.facname.callingnum, c->callernum, sizeof(pri->ev.facname.callingnum));
pri->ev.facname.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
pri->ev.facname.callingpres = c->callerpres;
pri->ev.facname.callingplan = c->callerplan;
pri->ev.facname.cref = c->cr;
pri->ev.facname.call = c;
#if 0
@@ -3681,15 +3459,7 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
(c->cause != PRI_CAUSE_INTERWORKING))
pri_error(pri, "Received unsolicited status: %s\n", pri_cause2str(c->cause));
/* Workaround for S-12 ver 7.3 - it responds for invalid/non-implemented IEs at SETUP with null call state */
#if 0
if (!c->sugcallstate && (c->ourcallstate != Q931_CALL_STATE_CALL_INITIATED)) {
#else
/* Remove "workaround" since it breaks certification testing. If we receive a STATUS message of call state
* NULL and we are not in the call state NULL we must clear resources and return to the call state to pass
* testing. See section 5.8.11 of Q.931 */
if (!c->sugcallstate) {
#endif
pri->ev.hangup.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
pri->ev.hangup.cause = c->cause;
pri->ev.hangup.cref = c->cr;
@@ -3779,12 +3549,6 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_DISCONNECT_INDICATION);
c->peercallstate = Q931_CALL_STATE_DISCONNECT_REQUEST;
c->sendhangupack = 1;
/* wait for a RELEASE so that sufficient time has passed
for the inband audio to be heard */
if (pri->acceptinbandrelease && (c->progressmask & PRI_PROG_INBAND_AVAILABLE))
break;
/* Return such an event */
pri->ev.e = PRI_EVENT_HANGUP_REQ;
pri->ev.hangup.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);

View File

@@ -64,7 +64,7 @@ static struct pri *first, *cur;
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
#define TEST_CALLS 1
#define TEST_CALLS 32
static void event1(struct pri *pri, pri_event *e)
{
@@ -232,9 +232,9 @@ static void *dchan(void *data)
}
if (e) {
if (first == pri) {
event1(e->gen.pri, e);
event1(pri, e);
} else {
event2(e->gen.pri, e);
event2(pri, e);
}
}
pthread_mutex_unlock(&lock);
@@ -254,7 +254,7 @@ int main(int argc, char *argv[])
perror("socketpair");
exit(1);
}
if (!(pri = pri_new_bri(pair[0], 0, PRI_NETWORK, PRI_DEF_SWITCHTYPE))) {
if (!(pri = pri_new(pair[0], PRI_NETWORK, PRI_DEF_SWITCHTYPE))) {
perror("pri(0)");
exit(1);
}
@@ -265,7 +265,7 @@ int main(int argc, char *argv[])
perror("thread(0)");
exit(1);
}
if (!(pri = pri_new_bri(pair[1], 0, PRI_CPE, PRI_DEF_SWITCHTYPE))) {
if (!(pri = pri_new(pair[1], PRI_CPE, PRI_DEF_SWITCHTYPE))) {
perror("pri(1)");
exit(1);
}