Compare commits
71 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
21e58c2f33 | ||
|
|
d1e0d1f6d4 | ||
|
|
595154da5a | ||
|
|
cdb9c294c1 | ||
|
|
2a27c0f173 | ||
|
|
e498bef21f | ||
|
|
ac51a8e058 | ||
|
|
11f13f9b2d | ||
|
|
cd56dc1b1c | ||
|
|
a17ce5bdea | ||
|
|
fcd5775b8b | ||
|
|
199d4c7fc5 | ||
|
|
a22bd0df05 | ||
|
|
a898653315 | ||
|
|
16ae0df732 | ||
|
|
342c1f81ca | ||
|
|
9969553056 | ||
|
|
9037525b7b | ||
|
|
f245f64a2e | ||
|
|
cd91dba660 | ||
|
|
a24748c0f8 | ||
|
|
8c69834e21 | ||
|
|
8192b42674 | ||
|
|
de00a26f71 | ||
|
|
fe9fff6dcb | ||
|
|
2ce7890fdd | ||
|
|
de008c4d60 | ||
|
|
7db8af4b80 | ||
|
|
a33fd59dc6 | ||
|
|
a3ee176154 | ||
|
|
f316eed834 | ||
|
|
c6ccbf69ca | ||
|
|
f10e2174b4 | ||
|
|
fd75f5ade1 | ||
|
|
ed9c90a985 | ||
|
|
f57f033aac | ||
|
|
11984069b6 | ||
|
|
533412e361 | ||
|
|
e2091c29ef | ||
|
|
b92b08dad7 | ||
|
|
e225476864 | ||
|
|
e17aebfc82 | ||
|
|
d8f64e6c98 | ||
|
|
3c061000b5 | ||
|
|
a98061f019 | ||
|
|
3ea2ea8cf1 | ||
|
|
6f831daaed | ||
|
|
681a5f582e | ||
|
|
0a326a9744 | ||
|
|
30188c642d | ||
|
|
3f78370c92 | ||
|
|
4c20e50a5d | ||
|
|
6b5781bb3a | ||
|
|
333a5eb67a | ||
|
|
0e2e37b537 | ||
|
|
cb7b843e10 | ||
|
|
d97a630a81 | ||
|
|
9447f39f3f | ||
|
|
8fa183a4bc | ||
|
|
9e03b9b8c7 | ||
|
|
274f535654 | ||
|
|
424fa816e3 | ||
|
|
9c8628715f | ||
|
|
bb1f882f8a | ||
|
|
8738891752 | ||
|
|
b1db8aaae6 | ||
|
|
dd611af000 | ||
|
|
8d6d58ab09 | ||
|
|
d6cab1d527 | ||
|
|
a634c4253b | ||
|
|
cf8c723f8b |
124
ChangeLog
124
ChangeLog
@@ -1,91 +1,87 @@
|
||||
2006-10-17 Kevin P. Fleming <kpfleming@digium.com>
|
||||
2007-10-16 Matthew Fredrickson <creslin@digium.com>
|
||||
|
||||
* libpri 1.2.4 Released
|
||||
* libpri 1.4.2 released.
|
||||
|
||||
2006-07-28 14:44 +0000 [r368] Matt Frederickson <creslin@digium.com>
|
||||
2007-10-05 16:45 +0000 [r470] Jason Parker <jparker@digium.com>
|
||||
|
||||
* q931.c: Make sure we send any pending facilty APDUs after we get
|
||||
proceeding. (#7551)
|
||||
* libpri.h: Fix an incorrect pri_event structure definition. Issue
|
||||
10832, patch by flefoll
|
||||
|
||||
2006-07-12 19:08 +0000 [r360] Russell Bryant <russell@digium.com>
|
||||
2007-09-25 21:37 +0000 [r468] Matthew Fredrickson <creslin@digium.com>
|
||||
|
||||
* q931.c: ensure buffer is initialized (issue #7512, klaus3000)
|
||||
* q931.c: Fix user-user IE order in setup message (#10705)
|
||||
|
||||
2006-07-07 15:36 +0000 [r358] Matt Frederickson <creslin@digium.com>
|
||||
2007-09-14 21:32 +0000 [r465] Matthew Fredrickson <creslin@digium.com>
|
||||
|
||||
* q931.c: Fix for #7378 (namespace collision)
|
||||
* q931.c, libpri.h: Fix for #10189. Make sure we properly report
|
||||
the user layer 1 for H.223 and H.245
|
||||
|
||||
2006-06-02 16:05 +0000 [r342-347] Matt Frederickson <creslin@digium.com>
|
||||
2007-09-06 15:11 +0000 [r462] Matthew Fredrickson <creslin@digium.com>
|
||||
|
||||
* q931.c: Minor state fix. (#7269)
|
||||
* 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. ........
|
||||
|
||||
* q931.c: Fix for 7115 (Don't call pri_message multiple times per
|
||||
line)
|
||||
2007-08-27 19:21 +0000 [r446] Jason Parker <jparker@digium.com>
|
||||
|
||||
* q931.c: Fixes to fill in non-filled fields in libpri. (Issue
|
||||
#7241) Thanks flefoll!
|
||||
* 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.
|
||||
........
|
||||
|
||||
2006-05-30 Kevin P. Fleming <kpfleming@digium.com>
|
||||
2007-08-06 19:58 +0000 [r441] Jason Parker <jparker@digium.com>
|
||||
|
||||
* libpri 1.2.3 Released
|
||||
* Makefile: Allow setting CC to something with a space, such as
|
||||
`make CC="gcc -m32"` Issue 10253.
|
||||
|
||||
2006-04-30 15:17 +0000 [r332] Kevin P. Fleming <kpfleming@digium.com>
|
||||
2007-07-09 Russell Bryant <russell@digium.com>
|
||||
|
||||
* Makefile: set LDCONFIG_FLAGS for GNU/kFreeBSD as well use the
|
||||
flags during installation
|
||||
* libpri 1.4.1 released.
|
||||
|
||||
2006-04-27 16:08 +0000 [r327] Matt Frederickson <creslin@digium.com>
|
||||
2007-06-19 18:23 +0000 [r427] Matthew Fredrickson <creslin@digium.com>
|
||||
|
||||
* q931.c, libpri.h: Make sure we pass the call back in the
|
||||
setup_ack
|
||||
* 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) ........
|
||||
|
||||
2006-04-04 15:36 +0000 [r323] Matt Frederickson <creslin@digium.com>
|
||||
2007-06-06 21:58 +0000 [r416-424] Matthew Fredrickson <creslin@digium.com>
|
||||
|
||||
* Makefile: Fix for #6566 (Makefile does not honor DESTDIR)
|
||||
* 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 ........
|
||||
|
||||
2006-02-17 18:55 +0000 [r316] Matt Frederickson <creslin@digium.com>
|
||||
* 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 ........
|
||||
|
||||
* q931.c: Backport of 6480
|
||||
2007-01-22 22:29 +0000 [r390] Matthew Fredrickson <creslin@digium.com>
|
||||
|
||||
2006-02-15 17:59 +0000 [r311] Matt O'Gorman <mogorman@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. ........
|
||||
|
||||
* README: bug 6500 typo in README.
|
||||
2006-12-30 19:17 +0000 [r386] Joshua Colp <jcolp@digium.com>
|
||||
|
||||
2006-02-13 23:06 +0000 [r306] Kevin P. Fleming <kpfleming@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)
|
||||
........
|
||||
|
||||
* pri_facility.c: suppress annoying message about unsupported
|
||||
components in facility messages
|
||||
|
||||
2006-01-18 Russell Bryant <russell@digium.com>
|
||||
|
||||
* Libpri 1.2.2 Released
|
||||
|
||||
2006-01-17 13:43 +0000 [r291] Kevin P. Fleming <kpfleming@digium.com>
|
||||
|
||||
* q931.c: ensure that user-user info field in call is properly
|
||||
reset when not needed
|
||||
|
||||
2006-01-10 20:19 +0000 [r290] Matt Frederickson <creslin@digium.com>
|
||||
|
||||
* Makefile: Backport of doing correct minor numbers to 1.2 (#6188)
|
||||
|
||||
2005-12-27 14:01 +0000 [r284] Matt Frederickson <creslin@digium.com>
|
||||
|
||||
* q931.c: Fix for issue #6039 backported to 1.2
|
||||
|
||||
2005-12-06 21:35 +0000 [r280] Matt Frederickson <creslin@digium.com>
|
||||
|
||||
* q921.c: Send RR as command instead of response when T200 expires
|
||||
after receiving RNR.
|
||||
|
||||
2005-12-01 23:13 +0000 [r274] Kevin P. Fleming <kpfleming@digium.com>
|
||||
|
||||
* Makefile: Makefile 'update' target now supports Subversion
|
||||
repositories (issue #5875)
|
||||
|
||||
2005-12-01 02:34 +0000 [r270] Matt Frederickson <creslin@digium.com>
|
||||
|
||||
* q931.c: Backport of fix from trunk. Fix broken single digit
|
||||
keypad facility code.
|
||||
2006-12-23 Kevin P. Fleming <kpfleming@digium.com>
|
||||
|
||||
* libpri 1.4.0 released.
|
||||
|
||||
2006-09-20 Kevin P. Fleming <kpfleming@digium.com>
|
||||
|
||||
* libpri 1.4.0-beta1 released.
|
||||
|
||||
18
Makefile
18
Makefile
@@ -32,23 +32,22 @@ CC=gcc
|
||||
OSARCH=$(shell uname -s)
|
||||
PROC?=$(shell uname -m)
|
||||
|
||||
TOBJS=testpri.o
|
||||
T2OBJS=testprilib.o
|
||||
STATIC_LIBRARY=libpri.a
|
||||
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)
|
||||
CFLAGS=-Wall -Werror -Wstrict-prototypes -Wmissing-prototypes -g -fPIC $(ALERTING) $(LIBPRI_COUNTERS)
|
||||
INSTALL_PREFIX=$(DESTDIR)
|
||||
INSTALL_BASE=/usr
|
||||
SOFLAGS = -Wl,-hlibpri.so.1.0
|
||||
LDCONFIG = /sbin/ldconfig
|
||||
ifneq (,$(findstring $(OSARCH), Linux GNU/kFreeBSD))
|
||||
ifneq (,$(findstring X$(OSARCH)X, XLinuxX XGNU/kFreeBSDX))
|
||||
LDCONFIG_FLAGS=-n
|
||||
else
|
||||
ifeq (${OSARCH},FreeBSD)
|
||||
LDCONFIG_FLAGS=-m
|
||||
CFLAGS += -I../zaptel -I../zapata
|
||||
INSTALL_BASE=/usr/local
|
||||
endif
|
||||
endif
|
||||
ifeq (${OSARCH},SunOS)
|
||||
@@ -73,9 +72,6 @@ update:
|
||||
@if [ -d .svn ]; then \
|
||||
echo "Updating from Subversion..." ; \
|
||||
svn update -q; \
|
||||
elif [ -d CVS ]; then \
|
||||
echo "Updating from CVS..." ; \
|
||||
cvs -q -z3 update -Pd; \
|
||||
else \
|
||||
echo "Not under version control"; \
|
||||
fi
|
||||
@@ -86,7 +82,7 @@ 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 restorecon -v $(INSTALL_PREFIX)$(INSTALL_BASE)/lib/$(DYNAMIC_LIBRARY); fi
|
||||
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.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
|
||||
@@ -122,7 +118,7 @@ include .depend
|
||||
endif
|
||||
|
||||
%.lo : %.c
|
||||
$(CC) -fPIC $(CFLAGS) -o $@ -c $<
|
||||
$(CC) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
$(STATIC_LIBRARY): $(STATIC_OBJS)
|
||||
ar rcs $(STATIC_LIBRARY) $(STATIC_OBJS)
|
||||
@@ -137,11 +133,11 @@ $(DYNAMIC_LIBRARY): $(DYNAMIC_OBJS)
|
||||
|
||||
clean:
|
||||
rm -f *.o *.so *.lo *.so.1 *.so.1.0
|
||||
rm -f testpri testprilib $(STATIC_LIBRARY) $(DYNAMIC_LIBRARY)
|
||||
rm -f testprilib $(STATIC_LIBRARY) $(DYNAMIC_LIBRARY)
|
||||
rm -f pritest pridump
|
||||
rm -f .depend
|
||||
|
||||
depend: .depend
|
||||
|
||||
.depend:
|
||||
CC=$(CC) ./mkdep ${CFLAGS} `ls *.c`
|
||||
CC="$(CC)" ./mkdep ${CFLAGS} `ls *.c`
|
||||
|
||||
4
TODO
4
TODO
@@ -1,10 +1,8 @@
|
||||
General:
|
||||
-- D-Channel Backup
|
||||
-- Test against 4e
|
||||
|
||||
Q.921:
|
||||
-- Support unnumbered information frames
|
||||
-- Get TEI codes working for BRI interfaces
|
||||
|
||||
Q.931:
|
||||
-- Locking Shift IE
|
||||
-- Implement the 11 missing Q.931 timers
|
||||
|
||||
44
libpri.h
44
libpri.h
@@ -142,10 +142,10 @@
|
||||
|
||||
/* Causes for disconnection */
|
||||
#define PRI_CAUSE_UNALLOCATED 1
|
||||
#define PRI_CAUSE_NO_ROUTE_TRANSIT_NET 2
|
||||
#define PRI_CAUSE_NO_ROUTE_TRANSIT_NET 2 /* !Q.SIG */
|
||||
#define PRI_CAUSE_NO_ROUTE_DESTINATION 3
|
||||
#define PRI_CAUSE_CHANNEL_UNACCEPTABLE 6
|
||||
#define PRI_CAUSE_CALL_AWARDED_DELIVERED 7
|
||||
#define PRI_CAUSE_CALL_AWARDED_DELIVERED 7 /* !Q.SIG */
|
||||
#define PRI_CAUSE_NORMAL_CLEARING 16
|
||||
#define PRI_CAUSE_USER_BUSY 17
|
||||
#define PRI_CAUSE_NO_USER_RESPONSE 18
|
||||
@@ -154,27 +154,29 @@
|
||||
#define PRI_CAUSE_NUMBER_CHANGED 22
|
||||
#define PRI_CAUSE_DESTINATION_OUT_OF_ORDER 27
|
||||
#define PRI_CAUSE_INVALID_NUMBER_FORMAT 28
|
||||
#define PRI_CAUSE_FACILITY_REJECTED 29
|
||||
#define PRI_CAUSE_FACILITY_REJECTED 29 /* !Q.SIG */
|
||||
#define PRI_CAUSE_RESPONSE_TO_STATUS_ENQUIRY 30
|
||||
#define PRI_CAUSE_NORMAL_UNSPECIFIED 31
|
||||
#define PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION 34
|
||||
#define PRI_CAUSE_NETWORK_OUT_OF_ORDER 38
|
||||
#define PRI_CAUSE_NETWORK_OUT_OF_ORDER 38 /* !Q.SIG */
|
||||
#define PRI_CAUSE_NORMAL_TEMPORARY_FAILURE 41
|
||||
#define PRI_CAUSE_SWITCH_CONGESTION 42
|
||||
#define PRI_CAUSE_ACCESS_INFO_DISCARDED 43
|
||||
#define PRI_CAUSE_SWITCH_CONGESTION 42 /* !Q.SIG */
|
||||
#define PRI_CAUSE_ACCESS_INFO_DISCARDED 43 /* !Q.SIG */
|
||||
#define PRI_CAUSE_REQUESTED_CHAN_UNAVAIL 44
|
||||
#define PRI_CAUSE_PRE_EMPTED 45
|
||||
#define PRI_CAUSE_FACILITY_NOT_SUBSCRIBED 50
|
||||
#define PRI_CAUSE_OUTGOING_CALL_BARRED 52
|
||||
#define PRI_CAUSE_INCOMING_CALL_BARRED 54
|
||||
#define PRI_CAUSE_PRE_EMPTED 45 /* !Q.SIG */
|
||||
#define PRI_CAUSE_FACILITY_NOT_SUBSCRIBED 50 /* !Q.SIG */
|
||||
#define PRI_CAUSE_OUTGOING_CALL_BARRED 52 /* !Q.SIG */
|
||||
#define PRI_CAUSE_INCOMING_CALL_BARRED 54 /* !Q.SIG */
|
||||
#define PRI_CAUSE_BEARERCAPABILITY_NOTAUTH 57
|
||||
#define PRI_CAUSE_BEARERCAPABILITY_NOTAVAIL 58
|
||||
#define PRI_CAUSE_SERVICEOROPTION_NOTAVAIL 63 /* Q.SIG */
|
||||
#define PRI_CAUSE_BEARERCAPABILITY_NOTIMPL 65
|
||||
#define PRI_CAUSE_CHAN_NOT_IMPLEMENTED 66
|
||||
#define PRI_CAUSE_FACILITY_NOT_IMPLEMENTED 69
|
||||
#define PRI_CAUSE_CHAN_NOT_IMPLEMENTED 66 /* !Q.SIG */
|
||||
#define PRI_CAUSE_FACILITY_NOT_IMPLEMENTED 69 /* !Q.SIG */
|
||||
#define PRI_CAUSE_INVALID_CALL_REFERENCE 81
|
||||
#define PRI_CAUSE_IDENTIFIED_CHANNEL_NOTEXIST 82 /* Q.SIG */
|
||||
#define PRI_CAUSE_INCOMPATIBLE_DESTINATION 88
|
||||
#define PRI_CAUSE_INVALID_MSG_UNSPECIFIED 95
|
||||
#define PRI_CAUSE_INVALID_MSG_UNSPECIFIED 95 /* !Q.SIG */
|
||||
#define PRI_CAUSE_MANDATORY_IE_MISSING 96
|
||||
#define PRI_CAUSE_MESSAGE_TYPE_NONEXIST 97
|
||||
#define PRI_CAUSE_WRONG_MESSAGE 98
|
||||
@@ -182,9 +184,9 @@
|
||||
#define PRI_CAUSE_INVALID_IE_CONTENTS 100
|
||||
#define PRI_CAUSE_WRONG_CALL_STATE 101
|
||||
#define PRI_CAUSE_RECOVERY_ON_TIMER_EXPIRE 102
|
||||
#define PRI_CAUSE_MANDATORY_IE_LENGTH_ERROR 103
|
||||
#define PRI_CAUSE_MANDATORY_IE_LENGTH_ERROR 103 /* !Q.SIG */
|
||||
#define PRI_CAUSE_PROTOCOL_ERROR 111
|
||||
#define PRI_CAUSE_INTERWORKING 127
|
||||
#define PRI_CAUSE_INTERWORKING 127 /* !Q.SIG */
|
||||
|
||||
/* Transmit capabilities */
|
||||
#define PRI_TRANS_CAP_SPEECH 0x0
|
||||
@@ -200,7 +202,7 @@
|
||||
#define PRI_LAYER_1_ALAW 0x23
|
||||
#define PRI_LAYER_1_G721 0x24
|
||||
#define PRI_LAYER_1_G722_G725 0x25
|
||||
#define PRI_LAYER_1_G7XX_384K 0x26
|
||||
#define PRI_LAYER_1_H223_H245 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
|
||||
@@ -384,7 +386,7 @@ typedef union {
|
||||
pri_event_ring ring; /* Ring */
|
||||
pri_event_hangup hangup; /* Hang up */
|
||||
pri_event_ringing ringing; /* Ringing */
|
||||
pri_event_ringing answer; /* Answer */
|
||||
pri_event_answer 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 */
|
||||
@@ -463,6 +465,10 @@ extern int pri_acknowledge(struct pri *pri, q931_call *call, int channel, int in
|
||||
/* Send a digit in overlap mode */
|
||||
extern int pri_information(struct pri *pri, q931_call *call, char digit);
|
||||
|
||||
#define PRI_KEYPAD_FACILITY_TX
|
||||
/* Send a keypad facility string of 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 */
|
||||
extern int pri_need_more_info(struct pri *pri, q931_call *call, int channel, int nonisdn);
|
||||
@@ -525,9 +531,9 @@ extern int pri_sr_set_caller(struct pri_sr *sr, char *caller, char *callername,
|
||||
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 */
|
||||
extern void pri_sr_set_useruser(struct pri_sr *sr, char *userchars);
|
||||
extern void pri_sr_set_useruser(struct pri_sr *sr, const char *userchars);
|
||||
|
||||
extern void pri_call_set_useruser(q931_call *sr, char *userchars);
|
||||
extern void pri_call_set_useruser(q931_call *sr, const char *userchars);
|
||||
|
||||
extern int pri_setup(struct pri *pri, q931_call *call, struct pri_sr *req);
|
||||
|
||||
|
||||
2
mkdep
2
mkdep
@@ -1,4 +1,4 @@
|
||||
#!/bin/bash -
|
||||
#!/bin/sh -
|
||||
#
|
||||
# $OpenBSD: mkdep.gcc.sh,v 1.8 1998/09/02 06:40:07 deraadt Exp $
|
||||
# $NetBSD: mkdep.gcc.sh,v 1.9 1994/12/23 07:34:59 jtc Exp $
|
||||
|
||||
45
pri.c
45
pri.c
@@ -247,13 +247,13 @@ static struct pri *__pri_new(int fd, int node, int switchtype, struct pri *maste
|
||||
return p;
|
||||
}
|
||||
|
||||
void pri_call_set_useruser(q931_call *c, char *userchars)
|
||||
void pri_call_set_useruser(q931_call *c, const char *userchars)
|
||||
{
|
||||
if (userchars)
|
||||
libpri_copy_string(c->useruserinfo, userchars, sizeof(c->useruserinfo));
|
||||
}
|
||||
|
||||
void pri_sr_set_useruser(struct pri_sr *sr, char *userchars)
|
||||
void pri_sr_set_useruser(struct pri_sr *sr, const char *userchars)
|
||||
{
|
||||
sr->useruserinfo = userchars;
|
||||
}
|
||||
@@ -471,6 +471,14 @@ int pri_information(struct pri *pri, q931_call *call, char digit)
|
||||
return q931_information(pri, call, digit);
|
||||
}
|
||||
|
||||
int pri_keypad_facility(struct pri *pri, q931_call *call, char *digits)
|
||||
{
|
||||
if (!pri || !call || !digits || !digits[0])
|
||||
return -1;
|
||||
|
||||
return q931_keypad_facility(pri, call, digits);
|
||||
}
|
||||
|
||||
int pri_notify(struct pri *pri, q931_call *call, int channel, int info)
|
||||
{
|
||||
if (!pri || !call)
|
||||
@@ -521,24 +529,36 @@ int pri_channel_bridge(q931_call *call1, q931_call *call2)
|
||||
if (!call1 || !call2)
|
||||
return -1;
|
||||
|
||||
/* Check switchtype compatibility */
|
||||
if (call1->pri->switchtype != PRI_SWITCH_LUCENT5E ||
|
||||
call2->pri->switchtype != PRI_SWITCH_LUCENT5E)
|
||||
/* 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 calls are on the same PRI dchannel
|
||||
* Currently only support calls on the same dchannel
|
||||
*/
|
||||
|
||||
/* Check to see if we're on the same PRI */
|
||||
if (call1->pri != call2->pri)
|
||||
return -1;
|
||||
|
||||
if (eect_initiate_transfer(call1->pri, call1, call2))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
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;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int pri_hangup(struct pri *pri, q931_call *call, int cause)
|
||||
@@ -775,6 +795,7 @@ char *pri_dump_info_str(struct pri *pri)
|
||||
len += sprintf(buf + len, "T203 Timer: %d\n", pri->timers[PRI_TIMER_T203]);
|
||||
len += sprintf(buf + len, "T305 Timer: %d\n", pri->timers[PRI_TIMER_T305]);
|
||||
len += sprintf(buf + len, "T308 Timer: %d\n", pri->timers[PRI_TIMER_T308]);
|
||||
len += sprintf(buf + len, "T309 Timer: %d\n", pri->timers[PRI_TIMER_T309]);
|
||||
len += sprintf(buf + len, "T313 Timer: %d\n", pri->timers[PRI_TIMER_T313]);
|
||||
len += sprintf(buf + len, "N200 Counter: %d\n", pri->timers[PRI_TIMER_N200]);
|
||||
|
||||
|
||||
511
pri_facility.c
511
pri_facility.c
@@ -32,6 +32,132 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
||||
static char *asn1id2text(int id)
|
||||
{
|
||||
static char data[32];
|
||||
static char *strings[] = {
|
||||
"none",
|
||||
"Boolean",
|
||||
"Integer",
|
||||
"Bit String",
|
||||
"Octet String",
|
||||
"NULL",
|
||||
"Object Identifier",
|
||||
"Object Descriptor",
|
||||
"External Reference",
|
||||
"Real Number",
|
||||
"Enumerated",
|
||||
"Embedded PDV",
|
||||
"UTF-8 String",
|
||||
"Relative Object ID",
|
||||
"Reserved (0e)",
|
||||
"Reserved (0f)",
|
||||
"Sequence",
|
||||
"Set",
|
||||
"Numeric String",
|
||||
"Printable String",
|
||||
"Tele-Text String",
|
||||
"IA-5 String",
|
||||
"UTC Time",
|
||||
"Generalized Time",
|
||||
};
|
||||
if (id > 0 && id <= 0x18) {
|
||||
return strings[id];
|
||||
} else {
|
||||
sprintf(data, "Unknown (%02x)", id);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
static int asn1_dumprecursive(struct pri *pri, void *comp_ptr, int len, int level)
|
||||
{
|
||||
unsigned char *vdata = (unsigned char *)comp_ptr;
|
||||
struct rose_component *comp;
|
||||
int i = 0;
|
||||
int j, k, l;
|
||||
int clen = 0;
|
||||
|
||||
while (len > 0) {
|
||||
GET_COMPONENT(comp, i, vdata, len);
|
||||
pri_message(pri, "%*s%02X %04X", 2 * level, "", comp->type, comp->len);
|
||||
if ((comp->type == 0) && (comp->len == 0))
|
||||
return clen + 2;
|
||||
if ((comp->type & ASN1_PC_MASK) == ASN1_PRIMITIVE) {
|
||||
for (j = 0; j < comp->len; ++j)
|
||||
pri_message(pri, " %02X", comp->data[j]);
|
||||
}
|
||||
if ((comp->type & ASN1_CLAN_MASK) == ASN1_UNIVERSAL) {
|
||||
switch (comp->type & ASN1_TYPE_MASK) {
|
||||
case 0:
|
||||
pri_message(pri, " (none)");
|
||||
break;
|
||||
case ASN1_BOOLEAN:
|
||||
pri_message(pri, " (BOOLEAN: %d)", comp->data[0]);
|
||||
break;
|
||||
case ASN1_INTEGER:
|
||||
for (k = l = 0; k < comp->len; ++k)
|
||||
l = (l << 8) | comp->data[k];
|
||||
pri_message(pri, " (INTEGER: %d)", l);
|
||||
break;
|
||||
case ASN1_BITSTRING:
|
||||
pri_message(pri, " (BITSTRING:");
|
||||
for (k = 0; k < comp->len; ++k)
|
||||
pri_message(pri, " %02x", comp->data[k]);
|
||||
pri_message(pri, ")");
|
||||
break;
|
||||
case ASN1_OCTETSTRING:
|
||||
pri_message(pri, " (OCTETSTRING:");
|
||||
for (k = 0; k < comp->len; ++k)
|
||||
pri_message(pri, " %02x", comp->data[k]);
|
||||
pri_message(pri, ")");
|
||||
break;
|
||||
case ASN1_NULL:
|
||||
pri_message(pri, " (NULL)");
|
||||
break;
|
||||
case ASN1_OBJECTIDENTIFIER:
|
||||
pri_message(pri, " (OBJECTIDENTIFIER:");
|
||||
for (k = 0; k < comp->len; ++k)
|
||||
pri_message(pri, " %02x", comp->data[k]);
|
||||
pri_message(pri, ")");
|
||||
break;
|
||||
case ASN1_ENUMERATED:
|
||||
for (k = l = 0; k < comp->len; ++k)
|
||||
l = (l << 8) | comp->data[k];
|
||||
pri_message(pri, " (ENUMERATED: %d)", l);
|
||||
break;
|
||||
case ASN1_SEQUENCE:
|
||||
pri_message(pri, " (SEQUENCE)");
|
||||
break;
|
||||
default:
|
||||
pri_message(pri, " (component %02x - %s)", comp->type, asn1id2text(comp->type & ASN1_TYPE_MASK));
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if ((comp->type & ASN1_CLAN_MASK) == ASN1_CONTEXT_SPECIFIC) {
|
||||
pri_message(pri, " (CONTEXT SPECIFIC [%d])", comp->type & ASN1_TYPE_MASK);
|
||||
}
|
||||
else {
|
||||
pri_message(pri, " (component %02x)", comp->type);
|
||||
}
|
||||
pri_message(pri, "\n");
|
||||
if ((comp->type & ASN1_PC_MASK) == ASN1_CONSTRUCTOR)
|
||||
j = asn1_dumprecursive(pri, comp->data, (comp->len ? comp->len : INT_MAX), level+1);
|
||||
else
|
||||
j = comp->len;
|
||||
j += 2;
|
||||
len -= j;
|
||||
vdata += j;
|
||||
clen += j;
|
||||
}
|
||||
return clen;
|
||||
}
|
||||
|
||||
int asn1_dump(struct pri *pri, void *comp, int len)
|
||||
{
|
||||
return asn1_dumprecursive(pri, comp, len, 0);
|
||||
}
|
||||
|
||||
static unsigned char get_invokeid(struct pri *pri)
|
||||
{
|
||||
@@ -46,28 +172,44 @@ struct addressingdataelements_presentednumberunscreened {
|
||||
int pres;
|
||||
};
|
||||
|
||||
#define PRI_CHECKOVERFLOW(size) \
|
||||
if (msgptr - message + (size) >= sizeof(message)) { \
|
||||
*msgptr = '\0'; \
|
||||
pri_message(pri, "%s", message); \
|
||||
msgptr = message; \
|
||||
}
|
||||
|
||||
static void dump_apdu(struct pri *pri, unsigned char *c, int len)
|
||||
{
|
||||
#define MAX_APDU_LENGTH 255
|
||||
static char hexs[16] = "0123456789ABCDEF";
|
||||
int i;
|
||||
char message[(2 + MAX_APDU_LENGTH * 3 + 6 + MAX_APDU_LENGTH + 3)] = ""; /* please adjust here, if you make changes below! */
|
||||
char *msgptr;
|
||||
|
||||
if (len > MAX_APDU_LENGTH)
|
||||
return;
|
||||
|
||||
snprintf(message, sizeof(message)-1, " [");
|
||||
for (i=0; i<len; i++)
|
||||
snprintf((char *)(message+strlen(message)), sizeof(message)-strlen(message)-1, " %02x", c[i]);
|
||||
snprintf((char *)(message+strlen(message)), sizeof(message)-strlen(message)-1, " ] - [");
|
||||
msgptr = message;
|
||||
*msgptr++ = ' ';
|
||||
*msgptr++ = '[';
|
||||
for (i=0; i<len; i++) {
|
||||
if (c[i] < 20 || c[i] >= 128)
|
||||
snprintf((char *)(message+strlen(message)), sizeof(message)-strlen(message)-1, "<EFBFBD>");
|
||||
else
|
||||
snprintf((char *)(message+strlen(message)), sizeof(message)-strlen(message)-1, "%c", c[i]);
|
||||
PRI_CHECKOVERFLOW(3);
|
||||
*msgptr++ = ' ';
|
||||
*msgptr++ = hexs[(c[i] >> 4) & 0x0f];
|
||||
*msgptr++ = hexs[(c[i]) & 0x0f];
|
||||
}
|
||||
snprintf((char *)(message+strlen(message)), sizeof(message)-strlen(message)-1, "]\n");
|
||||
pri_message(pri, message);
|
||||
PRI_CHECKOVERFLOW(6);
|
||||
strcpy(msgptr, " ] - [");
|
||||
msgptr += strlen(msgptr);
|
||||
for (i=0; i<len; i++) {
|
||||
PRI_CHECKOVERFLOW(1);
|
||||
*msgptr++ = ((c[i] < ' ') || (c[i] > '~')) ? '.' : c[i];
|
||||
}
|
||||
PRI_CHECKOVERFLOW(2);
|
||||
*msgptr++ = ']';
|
||||
*msgptr++ = '\n';
|
||||
*msgptr = '\0';
|
||||
pri_message(pri, "%s", message);
|
||||
}
|
||||
#undef PRI_CHECKOVERFLOW
|
||||
|
||||
int redirectingreason_from_q931(struct pri *pri, int redirectingreason)
|
||||
{
|
||||
@@ -564,9 +706,11 @@ static int rose_diverting_leg_information2_encode(struct pri *pri, q931_call *ca
|
||||
unsigned char buffer[256];
|
||||
int len = 253;
|
||||
|
||||
#if 0 /* This is not required by specifications */
|
||||
if (!strlen(call->callername)) {
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
buffer[i] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
|
||||
i++;
|
||||
@@ -694,6 +838,84 @@ static int rose_diverting_leg_information2_encode(struct pri *pri, q931_call *ca
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Send the rltThirdParty: Invoke */
|
||||
int rlt_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2)
|
||||
{
|
||||
int i = 0;
|
||||
unsigned char buffer[256];
|
||||
struct rose_component *comp = NULL, *compstk[10];
|
||||
const unsigned char rlt_3rd_pty = RLT_THIRD_PARTY;
|
||||
q931_call *callwithid = NULL, *apdubearer = NULL;
|
||||
int compsp = 0;
|
||||
|
||||
if (c2->transferable) {
|
||||
apdubearer = c1;
|
||||
callwithid = c2;
|
||||
} else if (c1->transferable) {
|
||||
apdubearer = c2;
|
||||
callwithid = c1;
|
||||
} else
|
||||
return -1;
|
||||
|
||||
buffer[i++] = (Q932_PROTOCOL_ROSE);
|
||||
buffer[i++] = (0x80 | RLT_SERVICE_ID); /* Service Identifier octet */
|
||||
|
||||
ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
|
||||
ASN1_PUSH(compstk, compsp, comp);
|
||||
|
||||
/* Invoke ID is set to the operation ID */
|
||||
ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, rlt_3rd_pty);
|
||||
|
||||
/* Operation Tag */
|
||||
ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, rlt_3rd_pty);
|
||||
|
||||
/* Additional RLT invoke info - Octet 12 */
|
||||
ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), buffer, i);
|
||||
ASN1_PUSH(compstk, compsp, comp);
|
||||
|
||||
ASN1_ADD_WORDCOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i, callwithid->rlt_call_id & 0xFFFFFF); /* Length is 3 octets */
|
||||
/* Reason for redirect - unused, set to 129 */
|
||||
ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1), buffer, i, 0);
|
||||
ASN1_FIXUP(compstk, compsp, buffer, i);
|
||||
ASN1_FIXUP(compstk, compsp, buffer, i);
|
||||
|
||||
if (pri_call_apdu_queue(apdubearer, Q931_FACILITY, buffer, i, NULL, NULL))
|
||||
return -1;
|
||||
|
||||
if (q931_facility(apdubearer->pri, apdubearer)) {
|
||||
pri_message(pri, "Could not schedule facility message for call %d\n", apdubearer->cr);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int add_dms100_transfer_ability_apdu(struct pri *pri, q931_call *c)
|
||||
{
|
||||
int i = 0;
|
||||
unsigned char buffer[256];
|
||||
struct rose_component *comp = NULL, *compstk[10];
|
||||
const unsigned char rlt_op_ind = RLT_OPERATION_IND;
|
||||
int compsp = 0;
|
||||
|
||||
buffer[i++] = (Q932_PROTOCOL_ROSE); /* Note to self: DON'T set the EXT bit */
|
||||
buffer[i++] = (0x80 | RLT_SERVICE_ID); /* Service Identifier octet */
|
||||
|
||||
ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
|
||||
ASN1_PUSH(compstk, compsp, comp);
|
||||
|
||||
/* Invoke ID is set to the operation ID */
|
||||
ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, rlt_op_ind);
|
||||
|
||||
/* Operation Tag - basically the same as the invoke ID tag */
|
||||
ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, rlt_op_ind);
|
||||
ASN1_FIXUP(compstk, compsp, buffer, i);
|
||||
|
||||
if (pri_call_apdu_queue(c, Q931_SETUP, buffer, i, NULL, NULL))
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Sending callername information functions */
|
||||
static int add_callername_facility_ies(struct pri *pri, q931_call *c, int cpe)
|
||||
{
|
||||
@@ -721,11 +943,13 @@ static int add_callername_facility_ies(struct pri *pri, q931_call *c, int cpe)
|
||||
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);
|
||||
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_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0);
|
||||
|
||||
@@ -749,7 +973,7 @@ static int add_callername_facility_ies(struct pri *pri, q931_call *c, int cpe)
|
||||
}
|
||||
|
||||
|
||||
/* Now the ADPu that contains the information that needs sent.
|
||||
/* Now the APDU that contains the information that needs sent.
|
||||
* We can reuse the buffer since the queue function doesn't
|
||||
* need it. */
|
||||
|
||||
@@ -762,11 +986,13 @@ static int add_callername_facility_ies(struct pri *pri, q931_call *c, int cpe)
|
||||
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);
|
||||
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_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0);
|
||||
|
||||
@@ -803,7 +1029,7 @@ static void mwi_activate_encode_cb(void *data)
|
||||
return;
|
||||
}
|
||||
|
||||
extern int mwi_message_send(struct pri* pri, q931_call *call, struct pri_sr *req, int activate)
|
||||
int mwi_message_send(struct pri* pri, q931_call *call, struct pri_sr *req, int activate)
|
||||
{
|
||||
int i = 0;
|
||||
unsigned char buffer[255] = "";
|
||||
@@ -853,15 +1079,12 @@ extern int mwi_message_send(struct pri* pri, q931_call *call, struct pri_sr *req
|
||||
/* End MWI */
|
||||
|
||||
/* EECT functions */
|
||||
extern int eect_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2)
|
||||
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] = "";
|
||||
unsigned short call_reference = c2->cr;
|
||||
short call_reference = c2->cr ^ 0x8000; /* Let's do the trickery to make sure the flag is correct */
|
||||
struct rose_component *comp = NULL, *compstk[10];
|
||||
int compsp = 0;
|
||||
static unsigned char op_tag[] = {
|
||||
@@ -874,16 +1097,7 @@ extern int eect_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2)
|
||||
0x08,
|
||||
};
|
||||
|
||||
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);
|
||||
buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_ROSE);
|
||||
|
||||
ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
|
||||
ASN1_PUSH(compstk, compsp, comp);
|
||||
@@ -903,7 +1117,7 @@ extern int eect_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2)
|
||||
|
||||
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");
|
||||
pri_message(pri, "Could not queue APDU in facility message\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1110,7 +1324,7 @@ static int aoc_aoce_charging_unit_encode(struct pri *pri, q931_call *c, long cha
|
||||
/* code below is untested */
|
||||
res = pri_call_apdu_queue(c, Q931_FACILITY, buffer, i, NULL, NULL);
|
||||
if (res) {
|
||||
pri_message(pri, "Could not queue ADPU in facility message\n");
|
||||
pri_message(pri, "Could not queue APDU in facility message\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1126,7 +1340,201 @@ static int aoc_aoce_charging_unit_encode(struct pri *pri, q931_call *c, long cha
|
||||
}
|
||||
/* End AOC */
|
||||
|
||||
extern int rose_invoke_decode(struct pri *pri, q931_call *call, 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;
|
||||
int problem = -1;
|
||||
int invokeidvalue = -1;
|
||||
unsigned char *vdata = data;
|
||||
struct rose_component *comp = NULL;
|
||||
char *problemtagstr, *problemstr;
|
||||
|
||||
do {
|
||||
/* Invoke ID stuff */
|
||||
GET_COMPONENT(comp, i, vdata, len);
|
||||
CHECK_COMPONENT(comp, INVOKE_IDENTIFIER, "Don't know what to do if first ROSE component is of type 0x%x\n");
|
||||
ASN1_GET_INTEGER(comp, invokeidvalue);
|
||||
NEXT_COMPONENT(comp, i);
|
||||
|
||||
GET_COMPONENT(comp, i, vdata, len);
|
||||
problemtag = comp->type;
|
||||
problem = comp->data[0];
|
||||
|
||||
if (pri->switchtype == PRI_SWITCH_DMS100) {
|
||||
switch (problemtag) {
|
||||
case 0x80:
|
||||
problemtagstr = "General problem";
|
||||
break;
|
||||
case 0x81:
|
||||
problemtagstr = "Invoke problem";
|
||||
break;
|
||||
case 0x82:
|
||||
problemtagstr = "Return result problem";
|
||||
break;
|
||||
case 0x83:
|
||||
problemtagstr = "Return error problem";
|
||||
break;
|
||||
default:
|
||||
problemtagstr = "Unknown";
|
||||
}
|
||||
|
||||
switch (problem) {
|
||||
case 0x00:
|
||||
problemstr = "Unrecognized component";
|
||||
break;
|
||||
case 0x01:
|
||||
problemstr = "Mistyped component";
|
||||
break;
|
||||
case 0x02:
|
||||
problemstr = "Badly structured component";
|
||||
break;
|
||||
default:
|
||||
problemstr = "Unknown";
|
||||
}
|
||||
|
||||
pri_error(pri, "ROSE REJECT:\n");
|
||||
pri_error(pri, "\tINVOKE ID: 0x%X\n", invokeidvalue);
|
||||
pri_error(pri, "\tPROBLEM TYPE: %s (0x%x)\n", problemtagstr, problemtag);
|
||||
pri_error(pri, "\tPROBLEM: %s (0x%x)\n", problemstr, problem);
|
||||
|
||||
return 0;
|
||||
} else {
|
||||
pri_message(pri, "Unable to handle return result on switchtype %d!\n", pri->switchtype);
|
||||
return -1;
|
||||
}
|
||||
|
||||
} while(0);
|
||||
|
||||
return -1;
|
||||
}
|
||||
int rose_return_error_decode(struct pri *pri, q931_call *call, unsigned char *data, int len)
|
||||
{
|
||||
int i = 0;
|
||||
int errorvalue = -1;
|
||||
int invokeidvalue = -1;
|
||||
unsigned char *vdata = data;
|
||||
struct rose_component *comp = NULL;
|
||||
char *invokeidstr, *errorstr;
|
||||
|
||||
do {
|
||||
/* Invoke ID stuff */
|
||||
GET_COMPONENT(comp, i, vdata, len);
|
||||
CHECK_COMPONENT(comp, INVOKE_IDENTIFIER, "Don't know what to do if first ROSE component is of type 0x%x\n");
|
||||
ASN1_GET_INTEGER(comp, invokeidvalue);
|
||||
NEXT_COMPONENT(comp, i);
|
||||
|
||||
GET_COMPONENT(comp, i, vdata, len);
|
||||
CHECK_COMPONENT(comp, ASN1_INTEGER, "Don't know what to do if second component in return error is 0x%x\n");
|
||||
ASN1_GET_INTEGER(comp, errorvalue);
|
||||
|
||||
if (pri->switchtype == PRI_SWITCH_DMS100) {
|
||||
switch (invokeidvalue) {
|
||||
case RLT_OPERATION_IND:
|
||||
invokeidstr = "RLT_OPERATION_IND";
|
||||
break;
|
||||
case RLT_THIRD_PARTY:
|
||||
invokeidstr = "RLT_THIRD_PARTY";
|
||||
break;
|
||||
default:
|
||||
invokeidstr = "Unknown";
|
||||
}
|
||||
|
||||
switch (errorvalue) {
|
||||
case 0x10:
|
||||
errorstr = "RLT Bridge Fail";
|
||||
break;
|
||||
case 0x11:
|
||||
errorstr = "RLT Call ID Not Found";
|
||||
break;
|
||||
case 0x12:
|
||||
errorstr = "RLT Not Allowed";
|
||||
break;
|
||||
case 0x13:
|
||||
errorstr = "RLT Switch Equip Congs";
|
||||
break;
|
||||
default:
|
||||
errorstr = "Unknown";
|
||||
}
|
||||
|
||||
pri_error(pri, "ROSE RETURN ERROR:\n");
|
||||
pri_error(pri, "\tOPERATION: %s\n", invokeidstr);
|
||||
pri_error(pri, "\tERROR: %s\n", errorstr);
|
||||
|
||||
return 0;
|
||||
} else {
|
||||
pri_message(pri, "Unable to handle return result on switchtype %d!\n", pri->switchtype);
|
||||
return -1;
|
||||
}
|
||||
|
||||
} while(0);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int rose_return_result_decode(struct pri *pri, q931_call *call, unsigned char *data, int len)
|
||||
{
|
||||
int i = 0;
|
||||
int operationidvalue = -1;
|
||||
int invokeidvalue = -1;
|
||||
unsigned char *vdata = data;
|
||||
struct rose_component *comp = NULL;
|
||||
|
||||
do {
|
||||
/* Invoke ID stuff */
|
||||
GET_COMPONENT(comp, i, vdata, len);
|
||||
CHECK_COMPONENT(comp, INVOKE_IDENTIFIER, "Don't know what to do if first ROSE component is of type 0x%x\n");
|
||||
ASN1_GET_INTEGER(comp, invokeidvalue);
|
||||
NEXT_COMPONENT(comp, i);
|
||||
|
||||
if (pri->switchtype == PRI_SWITCH_DMS100) {
|
||||
switch (invokeidvalue) {
|
||||
case RLT_THIRD_PARTY:
|
||||
if (pri->debug & PRI_DEBUG_APDU) pri_message(pri, "Successfully completed RLT transfer!\n");
|
||||
return 0;
|
||||
case RLT_OPERATION_IND:
|
||||
if (pri->debug & PRI_DEBUG_APDU) pri_message(pri, "Received RLT_OPERATION_IND\n");
|
||||
/* Have to take out the rlt_call_id */
|
||||
GET_COMPONENT(comp, i, vdata, len);
|
||||
CHECK_COMPONENT(comp, ASN1_SEQUENCE, "Protocol error detected in parsing RLT_OPERATION_IND return result!\n");
|
||||
|
||||
/* Traverse the contents of this sequence */
|
||||
/* First is the Operation Value */
|
||||
SUB_COMPONENT(comp, i);
|
||||
GET_COMPONENT(comp, i, vdata, len);
|
||||
CHECK_COMPONENT(comp, ASN1_INTEGER, "RLT_OPERATION_IND should be of type ASN1_INTEGER!\n");
|
||||
ASN1_GET_INTEGER(comp, operationidvalue);
|
||||
|
||||
if (operationidvalue != RLT_OPERATION_IND) {
|
||||
pri_message(pri, "Invalid Operation ID value (0x%x) in return result!\n", operationidvalue);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Next is the Call ID */
|
||||
NEXT_COMPONENT(comp, i);
|
||||
GET_COMPONENT(comp, i, vdata, len);
|
||||
CHECK_COMPONENT(comp, ASN1_TAG_0, "Error check failed on Call ID!\n");
|
||||
ASN1_GET_INTEGER(comp, call->rlt_call_id);
|
||||
/* We have enough data to transfer the call */
|
||||
call->transferable = 1;
|
||||
|
||||
return 0;
|
||||
|
||||
default:
|
||||
pri_message(pri, "Could not parse invoke of type 0x%x!\n", invokeidvalue);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
pri_message(pri, "Unable to handle return result on switchtype %d!\n", pri->switchtype);
|
||||
return -1;
|
||||
}
|
||||
|
||||
} while(0);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int rose_invoke_decode(struct pri *pri, q931_call *call, unsigned char *data, int len)
|
||||
{
|
||||
int i = 0;
|
||||
int operation_tag;
|
||||
@@ -1245,7 +1653,7 @@ extern int rose_invoke_decode(struct pri *pri, q931_call *call, unsigned char *d
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern int pri_call_apdu_queue(q931_call *call, int messagetype, void *apdu, int apdu_len, void (*function)(void *data), void *data)
|
||||
int pri_call_apdu_queue(q931_call *call, int messagetype, void *apdu, int apdu_len, void (*function)(void *data), void *data)
|
||||
{
|
||||
struct apdu_event *cur = NULL;
|
||||
struct apdu_event *new_event = NULL;
|
||||
@@ -1279,7 +1687,7 @@ extern int pri_call_apdu_queue(q931_call *call, int messagetype, void *apdu, int
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern int pri_call_apdu_queue_cleanup(q931_call *call)
|
||||
int pri_call_apdu_queue_cleanup(q931_call *call)
|
||||
{
|
||||
struct apdu_event *cur_event = NULL, *free_event = NULL;
|
||||
|
||||
@@ -1297,7 +1705,7 @@ extern int pri_call_apdu_queue_cleanup(q931_call *call)
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern int pri_call_add_standard_apdus(struct pri *pri, q931_call *call)
|
||||
int pri_call_add_standard_apdus(struct pri *pri, q931_call *call)
|
||||
{
|
||||
if (!pri->sendfacility)
|
||||
return 0;
|
||||
@@ -1309,6 +1717,7 @@ extern int pri_call_add_standard_apdus(struct pri *pri, q931_call *call)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (pri->localtype == PRI_NETWORK) {
|
||||
switch (pri->switchtype) {
|
||||
case PRI_SWITCH_NI2:
|
||||
@@ -1328,6 +1737,16 @@ extern int pri_call_add_standard_apdus(struct pri *pri, q931_call *call)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
if (pri->switchtype == PRI_SWITCH_NI2)
|
||||
add_callername_facility_ies(pri, call, (pri->localtype == PRI_CPE));
|
||||
#endif
|
||||
|
||||
if ((pri->switchtype == PRI_SWITCH_DMS100) && (pri->localtype == PRI_CPE)) {
|
||||
add_dms100_transfer_ability_apdu(pri, call);
|
||||
}
|
||||
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -104,7 +104,7 @@
|
||||
#define ASN1_CLAN_MASK 0xc0
|
||||
#define ASN1_UNIVERSAL 0x00
|
||||
#define ASN1_APPLICATION 0x40
|
||||
#define ASN1_CONTEXT_SPECIFIC 0x80
|
||||
#define ASN1_CONTEXT_SPECIFIC 0x80
|
||||
#define ASN1_PRIVATE 0xc0
|
||||
|
||||
/* ASN.1 Length masks */
|
||||
@@ -135,6 +135,11 @@
|
||||
#define Q932_TON_SUBSCRIBER 0x04
|
||||
#define Q932_TON_ABBREVIATED 0x06
|
||||
|
||||
/* RLT related Operations */
|
||||
#define RLT_SERVICE_ID 0x3e
|
||||
#define RLT_OPERATION_IND 0x01
|
||||
#define RLT_THIRD_PARTY 0x02
|
||||
|
||||
struct rose_component {
|
||||
u_int8_t type;
|
||||
u_int8_t len;
|
||||
@@ -146,7 +151,7 @@ struct rose_component {
|
||||
break; \
|
||||
(component) = (struct rose_component*)&((ptr)[idx]); \
|
||||
if ((idx)+(component)->len+2 > (length)) { \
|
||||
if ((component)->len != 128) \
|
||||
if ((component)->len != ASN1_LEN_INDEF) \
|
||||
pri_message(pri, "Length (%d) of 0x%X component is too long\n", (component)->len, (component)->type); \
|
||||
}
|
||||
/*
|
||||
@@ -169,6 +174,7 @@ struct rose_component {
|
||||
#define CHECK_COMPONENT(component, comptype, message) \
|
||||
if ((component)->type && ((component)->type & ASN1_TYPE_MASK) != (comptype)) { \
|
||||
pri_message(pri, (message), (component)->type); \
|
||||
asn1_dump(pri, (component), (component)->len+2); \
|
||||
break; \
|
||||
}
|
||||
|
||||
@@ -229,35 +235,48 @@ struct rose_component {
|
||||
(stack)[(stackpointer)]->len = (unsigned char *)&((data)[(idx)]) - (unsigned char *)(stack)[(stackpointer)] - 2; \
|
||||
} while (0)
|
||||
|
||||
/* Decoder for the invoke part of a ROSE request */
|
||||
extern int rose_invoke_decode(struct pri *pri, struct q931_call *call, unsigned char *data, int len);
|
||||
/* Decoder for the invoke ROSE component */
|
||||
int rose_invoke_decode(struct pri *pri, struct q931_call *call, unsigned char *data, int len);
|
||||
|
||||
extern int asn1_copy_string(char * buf, int buflen, struct rose_component *comp);
|
||||
/* Decoder for the return result ROSE component */
|
||||
int rose_return_result_decode(struct pri *pri, struct q931_call *call, unsigned char *data, int len);
|
||||
|
||||
extern int asn1_string_encode(unsigned char asn1_type, void *data, int len, int max_len, void *src, int src_len);
|
||||
/* Decoder for the return error ROSE component */
|
||||
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, unsigned char *data, int len);
|
||||
|
||||
int asn1_copy_string(char * buf, int buflen, struct rose_component *comp);
|
||||
|
||||
int asn1_string_encode(unsigned char asn1_type, void *data, int len, int max_len, void *src, int src_len);
|
||||
|
||||
/* Get Name types from ASN.1 */
|
||||
extern int asn1_name_decode(void * data, int len, char *namebuf, int buflen);
|
||||
int asn1_name_decode(void * data, int len, char *namebuf, int buflen);
|
||||
|
||||
extern int typeofnumber_from_q931(struct pri *pri, int ton);
|
||||
int typeofnumber_from_q931(struct pri *pri, int ton);
|
||||
|
||||
extern int redirectingreason_from_q931(struct pri *pri, int redirectingreason);
|
||||
int redirectingreason_from_q931(struct pri *pri, int redirectingreason);
|
||||
|
||||
/* Queues an MWI apdu on a the given call */
|
||||
extern int mwi_message_send(struct pri *pri, q931_call *call, struct pri_sr *req, int activate);
|
||||
int mwi_message_send(struct pri *pri, q931_call *call, struct pri_sr *req, int activate);
|
||||
|
||||
/* starts a 2BCT */
|
||||
extern int eect_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2);
|
||||
int eect_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2);
|
||||
|
||||
/* Use this function to queue a facility-IE born ADPU onto a call
|
||||
int rlt_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 */
|
||||
extern int pri_call_apdu_queue(q931_call *call, int messagetype, void *apdu, int apdu_len, void (*function)(void *data), void *data);
|
||||
int pri_call_apdu_queue(q931_call *call, int messagetype, void *apdu, int apdu_len, void (*function)(void *data), void *data);
|
||||
|
||||
/* Used by q931.c to cleanup the apdu queue upon destruction of a call */
|
||||
extern int pri_call_apdu_queue_cleanup(q931_call *call);
|
||||
int pri_call_apdu_queue_cleanup(q931_call *call);
|
||||
|
||||
/* Adds the "standard" ADPUs to a call */
|
||||
extern int pri_call_add_standard_apdus(struct pri *pri, q931_call *call);
|
||||
/* Adds the "standard" APDUs to a call */
|
||||
int pri_call_add_standard_apdus(struct pri *pri, q931_call *call);
|
||||
|
||||
int asn1_dump(struct pri *pri, void *comp, int len);
|
||||
|
||||
#endif /* _PRI_FACILITY_H */
|
||||
|
||||
@@ -27,6 +27,9 @@
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
#define DBGHEAD __FILE__ ":%d %s: "
|
||||
#define DBGINFO __LINE__,__PRETTY_FUNCTION__
|
||||
|
||||
struct pri_sched {
|
||||
struct timeval when;
|
||||
void (*callback)(void *data);
|
||||
@@ -129,7 +132,8 @@ struct pri_sr {
|
||||
int redirectingpres;
|
||||
int redirectingreason;
|
||||
int justsignalling;
|
||||
char *useruserinfo;
|
||||
const char *useruserinfo;
|
||||
int transferable;
|
||||
};
|
||||
|
||||
/* Internal switch types */
|
||||
@@ -206,7 +210,7 @@ struct q931_call {
|
||||
char callernum[256];
|
||||
char callername[256];
|
||||
|
||||
char digitbuf[64]; /* Buffer for digits that come in KEYPAD_FACILITY */
|
||||
char keypad_digits[64]; /* Buffer for digits that come in KEYPAD_FACILITY */
|
||||
|
||||
int ani2; /* ANI II */
|
||||
|
||||
@@ -239,6 +243,9 @@ struct q931_call {
|
||||
long aoc_units; /* Advice of Charge Units */
|
||||
|
||||
struct apdu_event *apdus; /* APDU queue for call */
|
||||
|
||||
int transferable;
|
||||
unsigned int rlt_call_id; /* RLT call id */
|
||||
};
|
||||
|
||||
extern int pri_schedule_event(struct pri *pri, int ms, void (*function)(void *data), void *data);
|
||||
|
||||
10
pri_q931.h
10
pri_q931.h
@@ -243,6 +243,10 @@ typedef struct q931_ie {
|
||||
/* EuroISDN */
|
||||
#define Q931_SENDING_COMPLETE 0xa1
|
||||
|
||||
|
||||
/* Q.SIG specific */
|
||||
#define QSIG_IE_TRANSIT_COUNT 0x31
|
||||
|
||||
extern int q931_receive(struct pri *pri, q931_h *h, int len);
|
||||
|
||||
extern int q931_alerting(struct pri *pri, q931_call *call, int channel, int info);
|
||||
@@ -257,6 +261,8 @@ extern int q931_setup_ack(struct pri *pri, q931_call *call, int channel, int non
|
||||
|
||||
extern int q931_information(struct pri *pri, q931_call *call, char digit);
|
||||
|
||||
extern int q931_keypad_facility(struct pri *pri, q931_call *call, char *digits);
|
||||
|
||||
extern int q931_connect(struct pri *pri, q931_call *call, int channel, int nonisdn);
|
||||
|
||||
extern int q931_release(struct pri *pri, q931_call *call, int cause);
|
||||
@@ -279,5 +285,7 @@ extern int q931_setup(struct pri *pri, q931_call *c, struct pri_sr *req);
|
||||
extern void q931_dump(struct pri *pri, q931_h *h, int len, int txrx);
|
||||
|
||||
extern void __q931_destroycall(struct pri *pri, q931_call *c);
|
||||
|
||||
|
||||
extern void q931_dl_indication(struct pri *pri, int event);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -37,11 +37,7 @@
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/types.h>
|
||||
#if defined(__linux__)
|
||||
#include <linux/zaptel.h>
|
||||
#elif defined(__FreeBSD__)
|
||||
#include <zaptel.h>
|
||||
#endif
|
||||
#include <zaptel/zaptel.h>
|
||||
#include "libpri.h"
|
||||
#include "pri_q921.h"
|
||||
#include "pri_q931.h"
|
||||
|
||||
@@ -40,11 +40,7 @@
|
||||
#include <sys/wait.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/time.h>
|
||||
#if defined(__linux__)
|
||||
#include <linux/zaptel.h>
|
||||
#elif defined(__FreeBSD__)
|
||||
#include <zaptel.h>
|
||||
#endif
|
||||
#include <zaptel/zaptel.h>
|
||||
#include <zap.h>
|
||||
#include "libpri.h"
|
||||
|
||||
|
||||
86
q921.c
86
q921.c
@@ -80,7 +80,7 @@ static int q921_transmit(struct pri *pri, q921_h *h, int len)
|
||||
pri->q921_txcount++;
|
||||
#endif
|
||||
/* Just send it raw */
|
||||
if (pri->debug & PRI_DEBUG_Q921_DUMP)
|
||||
if (pri->debug & (PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW))
|
||||
q921_dump(pri, h, len, pri->debug & PRI_DEBUG_Q921_RAW, 1);
|
||||
/* Write an extra two bytes for the FCS */
|
||||
res = pri->write_func ? pri->write_func(pri, h, len + 2) : 0;
|
||||
@@ -111,7 +111,7 @@ static void q921_send_ua(struct pri *pri, int pfbit)
|
||||
pri_error(pri, "Don't know how to U/A on a type %d node\n", pri->localtype);
|
||||
return;
|
||||
}
|
||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||
if (pri->debug & (PRI_DEBUG_Q921_STATE | PRI_DEBUG_Q921_DUMP))
|
||||
pri_message(pri, "Sending Unnumbered Acknowledgement\n");
|
||||
q921_transmit(pri, &h, 3);
|
||||
}
|
||||
@@ -143,9 +143,11 @@ 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->debug & PRI_DEBUG_Q921_STATE)
|
||||
if (pri->debug & (PRI_DEBUG_Q921_STATE | PRI_DEBUG_Q921_DUMP))
|
||||
pri_message(pri, "Sending Set Asynchronous Balanced Mode Extended\n");
|
||||
q921_transmit(pri, &h, 3);
|
||||
if (pri->debug & PRI_DEBUG_Q921_STATE && pri->q921_state != Q921_AWAITING_ESTABLISH)
|
||||
pri_message(pri, DBGHEAD "q921_state now is Q921_AWAITING_ESTABLISH\n", DBGINFO);
|
||||
pri->q921_state = Q921_AWAITING_ESTABLISH;
|
||||
}
|
||||
|
||||
@@ -166,7 +168,7 @@ static int q921_ack_packet(struct pri *pri, int num)
|
||||
prev->next = f->next;
|
||||
else
|
||||
pri->txqueue = f->next;
|
||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||
if (pri->debug & PRI_DEBUG_Q921_DUMP)
|
||||
pri_message(pri, "-- ACKing packet %d, new txqueue is %d (-1 means empty)\n", f->h.n_s, pri->txqueue ? pri->txqueue->h.n_s : -1);
|
||||
/* Update v_a */
|
||||
pri->v_a = num;
|
||||
@@ -180,7 +182,7 @@ static int q921_ack_packet(struct pri *pri, int num)
|
||||
while(f) {
|
||||
if (!f->transmitted) {
|
||||
/* Send it now... */
|
||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||
if (pri->debug & PRI_DEBUG_Q921_DUMP)
|
||||
pri_message(pri, "-- Finally transmitting %d, since window opened up\n", f->h.n_s);
|
||||
f->transmitted++;
|
||||
pri->windowlen++;
|
||||
@@ -206,7 +208,7 @@ static void reschedule_t203(struct pri *pri)
|
||||
{
|
||||
if (pri->t203_timer) {
|
||||
pri_schedule_del(pri, pri->t203_timer);
|
||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||
if (pri->debug & PRI_DEBUG_Q921_DUMP)
|
||||
pri_message(pri, "-- Restarting T203 counter\n");
|
||||
/* Nothing to transmit, start the T203 counter instead */
|
||||
pri->t203_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T203], t203_expire, pri);
|
||||
@@ -229,31 +231,31 @@ static pri_event *q921_ack_rx(struct pri *pri, int ack)
|
||||
return ev;
|
||||
}
|
||||
/* Cancel each packet as necessary */
|
||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||
if (pri->debug & PRI_DEBUG_Q921_DUMP)
|
||||
pri_message(pri, "-- ACKing all packets from %d to (but not including) %d\n", pri->v_a, ack);
|
||||
for (x=pri->v_a; x != ack; Q921_INC(x))
|
||||
cnt += q921_ack_packet(pri, x);
|
||||
if (!pri->txqueue) {
|
||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||
if (pri->debug & PRI_DEBUG_Q921_DUMP)
|
||||
pri_message(pri, "-- Since there was nothing left, stopping T200 counter\n");
|
||||
/* Something was ACK'd. Stop T200 counter */
|
||||
pri_schedule_del(pri, pri->t200_timer);
|
||||
pri->t200_timer = 0;
|
||||
}
|
||||
if (pri->t203_timer) {
|
||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||
if (pri->debug & PRI_DEBUG_Q921_DUMP)
|
||||
pri_message(pri, "-- Stopping T203 counter since we got an ACK\n");
|
||||
pri_schedule_del(pri, pri->t203_timer);
|
||||
pri->t203_timer = 0;
|
||||
}
|
||||
if (pri->txqueue) {
|
||||
/* Something left to transmit, Start the T200 counter again if we stopped it */
|
||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||
if (pri->debug & PRI_DEBUG_Q921_DUMP)
|
||||
pri_message(pri, "-- Something left to transmit (%d), restarting T200 counter\n", pri->txqueue->h.n_s);
|
||||
if (!pri->t200_timer)
|
||||
pri->t200_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri);
|
||||
} else {
|
||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||
if (pri->debug & PRI_DEBUG_Q921_DUMP)
|
||||
pri_message(pri, "-- Nothing left, starting T203 counter\n");
|
||||
/* Nothing to transmit, start the T203 counter instead */
|
||||
pri->t203_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T203], t203_expire, pri);
|
||||
@@ -281,7 +283,7 @@ static void q921_reject(struct pri *pri, int pf)
|
||||
pri_error(pri, "Don't know how to U/A on a type %d node\n", pri->localtype);
|
||||
return;
|
||||
}
|
||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||
if (pri->debug & PRI_DEBUG_Q921_DUMP)
|
||||
pri_message(pri, "Sending Reject (%d)\n", pri->v_r);
|
||||
pri->sentrej = 1;
|
||||
q921_transmit(pri, &h, 4);
|
||||
@@ -313,7 +315,7 @@ static void q921_rr(struct pri *pri, int pbit, int cmd) {
|
||||
return;
|
||||
}
|
||||
pri->v_na = pri->v_r; /* Make a note that we've already acked this */
|
||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||
if (pri->debug & PRI_DEBUG_Q921_DUMP)
|
||||
pri_message(pri, "Sending Receiver Ready (%d)\n", pri->v_r);
|
||||
q921_transmit(pri, &h, 4);
|
||||
}
|
||||
@@ -323,7 +325,7 @@ 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_STATE)
|
||||
if (pri->debug & PRI_DEBUG_Q921_DUMP)
|
||||
pri_message(pri, "-- T200 counter expired, What to do...\n");
|
||||
/* Force Poll bit */
|
||||
pri->txqueue->h.p_f = 1;
|
||||
@@ -335,7 +337,7 @@ static void t200_expire(void *vpri)
|
||||
/* Up to three retransmissions */
|
||||
if (pri->retrans < pri->timers[PRI_TIMER_N200]) {
|
||||
/* Reschedule t200_timer */
|
||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||
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);
|
||||
@@ -344,12 +346,14 @@ static void t200_expire(void *vpri)
|
||||
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_STATE)
|
||||
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)
|
||||
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);
|
||||
@@ -357,7 +361,7 @@ static void t200_expire(void *vpri)
|
||||
pri->schedev = 1;
|
||||
}
|
||||
} else if (pri->solicitfbit) {
|
||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||
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]) {
|
||||
@@ -365,8 +369,10 @@ static void t200_expire(void *vpri)
|
||||
q921_rr(pri, 1, 1);
|
||||
pri->t200_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri);
|
||||
} else {
|
||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||
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);
|
||||
@@ -423,23 +429,23 @@ int q921_transmit_iframe(struct pri *pri, void *buf, int len, int cr)
|
||||
q921_transmit(pri, (q921_h *)(&f->h), f->len);
|
||||
f->transmitted++;
|
||||
} else {
|
||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||
if (pri->debug & PRI_DEBUG_Q921_DUMP)
|
||||
pri_message(pri, "Delaying transmission of %d, window is %d/%d long\n",
|
||||
f->h.n_s, pri->windowlen, pri->window);
|
||||
}
|
||||
}
|
||||
if (pri->t203_timer) {
|
||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||
if (pri->debug & PRI_DEBUG_Q921_DUMP)
|
||||
pri_message(pri, "Stopping T_203 timer\n");
|
||||
pri_schedule_del(pri, pri->t203_timer);
|
||||
pri->t203_timer = 0;
|
||||
}
|
||||
if (!pri->t200_timer) {
|
||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||
if (pri->debug & PRI_DEBUG_Q921_DUMP)
|
||||
pri_message(pri, "Starting T_200 timer\n");
|
||||
pri->t200_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri);
|
||||
} else
|
||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||
if (pri->debug & PRI_DEBUG_Q921_DUMP)
|
||||
pri_message(pri, "T_200 timer already going (%d)\n", pri->t200_timer);
|
||||
|
||||
} else {
|
||||
@@ -453,7 +459,7 @@ static void t203_expire(void *vpri)
|
||||
{
|
||||
struct pri *pri = vpri;
|
||||
if (pri->q921_state == Q921_LINK_CONNECTION_ESTABLISHED) {
|
||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||
if (pri->debug & PRI_DEBUG_Q921_DUMP)
|
||||
pri_message(pri, "T203 counter expired, sending RR and scheduling T203 again\n");
|
||||
/* Solicit an F-bit in the other's RR */
|
||||
pri->solicitfbit = 1;
|
||||
@@ -462,7 +468,7 @@ static void t203_expire(void *vpri)
|
||||
/* Start timer T200 to resend our RR if we don't get it */
|
||||
pri->t203_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri);
|
||||
} else {
|
||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||
if (pri->debug & PRI_DEBUG_Q921_DUMP)
|
||||
pri_message(pri, "T203 counter expired in weird state %d\n", pri->q921_state);
|
||||
pri->t203_timer = 0;
|
||||
}
|
||||
@@ -654,11 +660,16 @@ static pri_event *q921_dchannel_up(struct pri *pri)
|
||||
pri->sentrej = 0;
|
||||
|
||||
/* Go into connection established state */
|
||||
if (pri->debug & PRI_DEBUG_Q921_STATE && pri->q921_state != Q921_LINK_CONNECTION_ESTABLISHED)
|
||||
pri_message(pri, DBGHEAD "q921_state now is Q921_LINK_CONNECTION_ESTABLISHED\n", DBGINFO);
|
||||
pri->q921_state = Q921_LINK_CONNECTION_ESTABLISHED;
|
||||
|
||||
/* Start the T203 timer */
|
||||
pri->t203_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T203], t203_expire, pri);
|
||||
|
||||
/* Notify Layer 3 */
|
||||
q931_dl_indication(pri, PRI_EVENT_DCHAN_UP);
|
||||
|
||||
/* Report event that D-Channel is now up */
|
||||
pri->ev.gen.e = PRI_EVENT_DCHAN_UP;
|
||||
return &pri->ev;
|
||||
@@ -669,6 +680,9 @@ static pri_event *q921_dchannel_down(struct pri *pri)
|
||||
/* Reset counters, reset sabme timer etc */
|
||||
q921_reset(pri);
|
||||
|
||||
/* Notify Layer 3 */
|
||||
q931_dl_indication(pri, PRI_EVENT_DCHAN_DOWN);
|
||||
|
||||
/* Report event that D-Channel is now up */
|
||||
pri->ev.gen.e = PRI_EVENT_DCHAN_DOWN;
|
||||
return &pri->ev;
|
||||
@@ -691,6 +705,8 @@ void q921_reset(struct pri *pri)
|
||||
pri->t200_timer = 0;
|
||||
pri->busy = 0;
|
||||
pri->solicitfbit = 0;
|
||||
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->retrans = 0;
|
||||
pri->sentrej = 0;
|
||||
@@ -739,10 +755,10 @@ static pri_event *__q921_receive_qualified(struct pri *pri, q921_h *h, int len)
|
||||
if (h->s.p_f) {
|
||||
/* If it's a p/f one then send back a RR in return with the p/f bit set */
|
||||
if (pri->solicitfbit) {
|
||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||
if (pri->debug & PRI_DEBUG_Q921_DUMP)
|
||||
pri_message(pri, "-- Got RR response to our frame\n");
|
||||
} else {
|
||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||
if (pri->debug & PRI_DEBUG_Q921_DUMP)
|
||||
pri_message(pri, "-- Unsolicited RR with P/F bit, responding\n");
|
||||
q921_rr(pri, 1, 0);
|
||||
}
|
||||
@@ -751,7 +767,7 @@ static pri_event *__q921_receive_qualified(struct pri *pri, q921_h *h, int len)
|
||||
break;
|
||||
case 1:
|
||||
/* Receiver not ready */
|
||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||
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 */
|
||||
@@ -761,7 +777,7 @@ static pri_event *__q921_receive_qualified(struct pri *pri, q921_h *h, int len)
|
||||
break;
|
||||
case 2:
|
||||
/* Just retransmit */
|
||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||
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 */
|
||||
@@ -818,7 +834,7 @@ static pri_event *__q921_receive_qualified(struct pri *pri, q921_h *h, int len)
|
||||
if (h->u.p_f) {
|
||||
/* Section 5.7.1 says we should restart on receiving a DM response with the f-bit set to
|
||||
one, but we wait T200 first */
|
||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||
if (pri->debug & (PRI_DEBUG_Q921_STATE | PRI_DEBUG_Q921_DUMP))
|
||||
pri_message(pri, "-- Got DM Mode from peer.\n");
|
||||
/* Disconnected mode, try again after T200 */
|
||||
ev = q921_dchannel_down(pri);
|
||||
@@ -826,7 +842,7 @@ static pri_event *__q921_receive_qualified(struct pri *pri, q921_h *h, int len)
|
||||
return ev;
|
||||
|
||||
} else {
|
||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||
if (pri->debug & PRI_DEBUG_Q921_DUMP)
|
||||
pri_message(pri, "-- Ignoring unsolicited DM with p/f set to 0\n");
|
||||
#if 0
|
||||
/* Requesting that we start */
|
||||
@@ -839,7 +855,7 @@ static pri_event *__q921_receive_qualified(struct pri *pri, q921_h *h, int len)
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||
if (pri->debug & (PRI_DEBUG_Q921_STATE | PRI_DEBUG_Q921_DUMP))
|
||||
pri_message(pri, "-- Got Disconnect from peer.\n");
|
||||
/* Acknowledge */
|
||||
q921_send_ua(pri, h->u.p_f);
|
||||
@@ -849,7 +865,7 @@ static pri_event *__q921_receive_qualified(struct pri *pri, q921_h *h, int len)
|
||||
case 3:
|
||||
if (h->u.m2 == 3) {
|
||||
/* SABME */
|
||||
if (pri->debug & PRI_DEBUG_Q921_STATE) {
|
||||
if (pri->debug & (PRI_DEBUG_Q921_STATE | PRI_DEBUG_Q921_DUMP)) {
|
||||
pri_message(pri, "-- Got SABME from %s peer.\n", h->h.c_r ? "network" : "cpe");
|
||||
}
|
||||
if (h->h.c_r) {
|
||||
@@ -871,7 +887,7 @@ static pri_event *__q921_receive_qualified(struct pri *pri, q921_h *h, int len)
|
||||
} else if (h->u.m2 == 0) {
|
||||
/* It's a UA */
|
||||
if (pri->q921_state == Q921_AWAITING_ESTABLISH) {
|
||||
if (pri->debug & PRI_DEBUG_Q921_STATE) {
|
||||
if (pri->debug & (PRI_DEBUG_Q921_STATE | PRI_DEBUG_Q921_DUMP)) {
|
||||
pri_message(pri, "-- Got UA from %s peer Link up.\n", h->h.c_r ? "cpe" : "network");
|
||||
}
|
||||
return q921_dchannel_up(pri);
|
||||
@@ -901,7 +917,7 @@ static pri_event *__q921_receive(struct pri *pri, q921_h *h, int len)
|
||||
/* Discard FCS */
|
||||
len -= 2;
|
||||
|
||||
if (!pri->master && pri->debug & PRI_DEBUG_Q921_DUMP)
|
||||
if (!pri->master && pri->debug & (PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW))
|
||||
q921_dump(pri, h, len, pri->debug & PRI_DEBUG_Q921_RAW, 0);
|
||||
|
||||
/* Check some reject conditions -- Start by rejecting improper ea's */
|
||||
|
||||
470
q931.c
470
q931.c
@@ -32,6 +32,7 @@
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
|
||||
@@ -119,9 +120,11 @@ static struct msgtype causes[] = {
|
||||
{ PRI_CAUSE_BEARERCAPABILITY_NOTAUTH, "Bearer capability not authorized" },
|
||||
{ PRI_CAUSE_BEARERCAPABILITY_NOTAVAIL, "Bearer capability not available" },
|
||||
{ PRI_CAUSE_BEARERCAPABILITY_NOTIMPL, "Bearer capability not implemented" },
|
||||
{ PRI_CAUSE_SERVICEOROPTION_NOTAVAIL, "Service or option not available, unspecified" },
|
||||
{ PRI_CAUSE_CHAN_NOT_IMPLEMENTED, "Channel not implemented" },
|
||||
{ PRI_CAUSE_FACILITY_NOT_IMPLEMENTED, "Facility not implemented" },
|
||||
{ PRI_CAUSE_INVALID_CALL_REFERENCE, "Invalid call reference value" },
|
||||
{ PRI_CAUSE_IDENTIFIED_CHANNEL_NOTEXIST, "Identified channel does not exist" },
|
||||
{ PRI_CAUSE_INCOMPATIBLE_DESTINATION, "Incompatible destination" },
|
||||
{ PRI_CAUSE_INVALID_MSG_UNSPECIFIED, "Invalid message unspecified" },
|
||||
{ PRI_CAUSE_MANDATORY_IE_MISSING, "Mandatory information element is missing" },
|
||||
@@ -213,6 +216,18 @@ static char *msg2str(int msg);
|
||||
#define FUNC_RECV(name) int ((name))(int full_ie, struct pri *pri, q931_call *call, int msgtype, q931_ie *ie, int len)
|
||||
#define FUNC_SEND(name) int ((name))(int full_ie, struct pri *pri, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
|
||||
|
||||
#if 1
|
||||
/* Update call state with transition trace. */
|
||||
#define UPDATE_OURCALLSTATE(pri,c,newstate) do {\
|
||||
if (pri->debug & (PRI_DEBUG_Q931_STATE) && c->ourcallstate != newstate) \
|
||||
pri_message(pri, DBGHEAD "call %d on channel %d enters state %d (%s)\n", DBGINFO, \
|
||||
c->cr, c->channelno, newstate, callstate2str(newstate)); \
|
||||
c->ourcallstate = newstate; \
|
||||
} while (0)
|
||||
#else
|
||||
/* Update call state with no trace. */
|
||||
#define UPDATE_OURCALLSTATE(pri,c,newstate) c->ourcallstate = newstate
|
||||
#endif
|
||||
|
||||
struct ie {
|
||||
/* Maximal count of same IEs at the message (0 - any, 1..n - limited) */
|
||||
@@ -403,7 +418,7 @@ static FUNC_DUMP(dump_channel_id)
|
||||
"No channel selected", "As indicated in following octets", "Reserved","Any channel selected"
|
||||
};
|
||||
|
||||
pri_message(pri, "%c Channel ID (len=%2d) [ Ext: %d IntID: %s, %s Spare: %d, %s Dchan: %d\n",
|
||||
pri_message(pri, "%c Channel ID (len=%2d) [ Ext: %d IntID: %s %s Spare: %d %s Dchan: %d\n",
|
||||
prefix, len, (ie->data[0] & 0x80) ? 1 : 0, (ie->data[0] & 0x40) ? "Explicit" : "Implicit",
|
||||
(ie->data[0] & 0x20) ? "PRI" : "Other", (ie->data[0] & 0x10) ? 1 : 0,
|
||||
(ie->data[0] & 0x08) ? "Exclusive" : "Preferred", (ie->data[0] & 0x04) ? 1 : 0);
|
||||
@@ -420,7 +435,7 @@ static FUNC_DUMP(dump_channel_id)
|
||||
}
|
||||
if (pos+2 < len) {
|
||||
/* Still more information here */
|
||||
pri_message(pri, "%c Ext: %d Coding: %d %s Specified Channel Type: %d\n",
|
||||
pri_message(pri, "%c Ext: %d Coding: %d %s Specified Channel Type: %d\n",
|
||||
prefix, (ie->data[pos] & 0x80) >> 7, (ie->data[pos] & 60) >> 5,
|
||||
(ie->data[pos] & 0x10) ? "Slot Map" : "Number", ie->data[pos] & 0x0f);
|
||||
if (!(ie->data[pos] & 0x10)) {
|
||||
@@ -533,7 +548,7 @@ static char *l12str(int proto)
|
||||
{ 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_G7XX_384K, "G.7xx 384k Video" },
|
||||
{ PRI_LAYER_1_H223_H245, "H.223 and H.245" }, /* Recommendation Q.931(05/98) page 60) */
|
||||
{ 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" },
|
||||
@@ -647,7 +662,8 @@ static FUNC_SEND(transmit_bearer_capability)
|
||||
}
|
||||
ie->data[0] = 0x80 | tc;
|
||||
ie->data[1] = call->transmoderate | 0x80;
|
||||
if ((tc & PRI_TRANS_CAP_DIGITAL)&&(pri->switchtype == PRI_SWITCH_EUROISDN_E1)) {
|
||||
if ( (tc & PRI_TRANS_CAP_DIGITAL) && (pri->switchtype == PRI_SWITCH_EUROISDN_E1) &&
|
||||
(call->transmoderate == TRANS_MODE_PACKET) ) {
|
||||
/* Apparently EuroISDN switches don't seem to like user layer 2/3 */
|
||||
return 4;
|
||||
}
|
||||
@@ -749,7 +765,7 @@ static FUNC_DUMP(dump_called_party_number)
|
||||
unsigned char cnum[256];
|
||||
|
||||
q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3);
|
||||
pri_message(pri, "%c Called Number (len=%2d) [ Ext: %d TON: %s (%d) NPI: %s (%d) '%s' ]\n",
|
||||
pri_message(pri, "%c Called Number (len=%2d) [ Ext: %d TON: %s (%d) NPI: %s (%d) '%s' ]\n",
|
||||
prefix, len, ie->data[0] >> 7, ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07, npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f, cnum);
|
||||
}
|
||||
|
||||
@@ -757,7 +773,7 @@ static FUNC_DUMP(dump_called_party_subaddr)
|
||||
{
|
||||
unsigned char cnum[256];
|
||||
q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3);
|
||||
pri_message(pri, "%c Called Sub-Address (len=%2d) [ Ext: %d Type: %s (%d) O: %d '%s' ]\n",
|
||||
pri_message(pri, "%c Called Sub-Address (len=%2d) [ Ext: %d Type: %s (%d) O: %d '%s' ]\n",
|
||||
prefix, len, ie->data[0] >> 7,
|
||||
subaddrtype2str((ie->data[0] & 0x70) >> 4), (ie->data[0] & 0x70) >> 4,
|
||||
(ie->data[0] & 0x08) >> 3, cnum);
|
||||
@@ -772,16 +788,16 @@ static FUNC_DUMP(dump_calling_party_number)
|
||||
q931_get_number(cnum, sizeof(cnum), ie->data + 2, len - 4);
|
||||
pri_message(pri, "%c Calling Number (len=%2d) [ Ext: %d TON: %s (%d) NPI: %s (%d)\n", prefix, len, ie->data[0] >> 7, ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07, npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f);
|
||||
if (ie->data[0] & 0x80)
|
||||
pri_message(pri, "%c Presentation: %s (%d) '%s' ]\n", prefix, pri_pres2str(0), 0, cnum);
|
||||
pri_message(pri, "%c Presentation: %s (%d) '%s' ]\n", prefix, pri_pres2str(0), 0, cnum);
|
||||
else
|
||||
pri_message(pri, "%c Presentation: %s (%d) '%s' ]\n", prefix, pri_pres2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f, cnum);
|
||||
pri_message(pri, "%c Presentation: %s (%d) '%s' ]\n", prefix, pri_pres2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f, cnum);
|
||||
}
|
||||
|
||||
static FUNC_DUMP(dump_calling_party_subaddr)
|
||||
{
|
||||
unsigned char cnum[256];
|
||||
q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3);
|
||||
pri_message(pri, "%c Calling Sub-Address (len=%2d) [ Ext: %d Type: %s (%d) O: %d '%s' ]\n",
|
||||
pri_message(pri, "%c Calling Sub-Address (len=%2d) [ Ext: %d Type: %s (%d) O: %d '%s' ]\n",
|
||||
prefix, len, ie->data[0] >> 7,
|
||||
subaddrtype2str((ie->data[0] & 0x70) >> 4), (ie->data[0] & 0x70) >> 4,
|
||||
(ie->data[0] & 0x08) >> 3, cnum);
|
||||
@@ -800,18 +816,18 @@ static FUNC_DUMP(dump_redirecting_number)
|
||||
prefix, len, ie->data[0] >> 7, ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07, npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f);
|
||||
break;
|
||||
case 1: /* Octet 3a */
|
||||
pri_message(pri, "\n%c Ext: %d Presentation: %s (%d)",
|
||||
pri_message(pri, "\n%c Ext: %d Presentation: %s (%d)",
|
||||
prefix, ie->data[1] >> 7, pri_pres2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f);
|
||||
break;
|
||||
case 2: /* Octet 3b */
|
||||
pri_message(pri, "\n%c Ext: %d Reason: %s (%d)",
|
||||
pri_message(pri, "\n%c Ext: %d Reason: %s (%d)",
|
||||
prefix, ie->data[2] >> 7, redirection_reason2str(ie->data[2] & 0x7f), ie->data[2] & 0x7f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
while(!(ie->data[i++]& 0x80));
|
||||
q931_get_number(cnum, sizeof(cnum), ie->data + i, ie->len - i);
|
||||
pri_message(pri, " '%s' ]\n", cnum);
|
||||
pri_message(pri, " '%s' ]\n", cnum);
|
||||
}
|
||||
|
||||
static FUNC_DUMP(dump_connected_number)
|
||||
@@ -827,14 +843,14 @@ static FUNC_DUMP(dump_connected_number)
|
||||
prefix, len, ie->data[0] >> 7, ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07, npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f);
|
||||
break;
|
||||
case 1: /* Octet 3a */
|
||||
pri_message(pri, "\n%c Ext: %d Presentation: %s (%d)",
|
||||
pri_message(pri, "\n%c Ext: %d Presentation: %s (%d)",
|
||||
prefix, ie->data[1] >> 7, pri_pres2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
while(!(ie->data[i++]& 0x80));
|
||||
q931_get_number(cnum, sizeof(cnum), ie->data + i, ie->len - i);
|
||||
pri_message(pri, " '%s' ]\n", cnum);
|
||||
pri_message(pri, " '%s' ]\n", cnum);
|
||||
}
|
||||
|
||||
|
||||
@@ -880,7 +896,7 @@ static FUNC_DUMP(dump_redirecting_subaddr)
|
||||
{
|
||||
unsigned char cnum[256];
|
||||
q931_get_number(cnum, sizeof(cnum), ie->data + 2, len - 4);
|
||||
pri_message(pri, "%c Redirecting Sub-Address (len=%2d) [ Ext: %d Type: %s (%d) O: %d '%s' ]\n",
|
||||
pri_message(pri, "%c Redirecting Sub-Address (len=%2d) [ Ext: %d Type: %s (%d) O: %d '%s' ]\n",
|
||||
prefix, len, ie->data[0] >> 7,
|
||||
subaddrtype2str((ie->data[0] & 0x70) >> 4), (ie->data[0] & 0x70) >> 4,
|
||||
(ie->data[0] & 0x08) >> 3, cnum);
|
||||
@@ -1034,7 +1050,7 @@ static char *loc2str(int loc)
|
||||
|
||||
static FUNC_DUMP(dump_progress_indicator)
|
||||
{
|
||||
pri_message(pri, "%c Progress Indicator (len=%2d) [ Ext: %d Coding: %s (%d) 0: %d Location: %s (%d)\n",
|
||||
pri_message(pri, "%c Progress Indicator (len=%2d) [ Ext: %d Coding: %s (%d) 0: %d Location: %s (%d)\n",
|
||||
prefix, len, ie->data[0] >> 7, coding2str((ie->data[0] & 0x60) >> 5), (ie->data[0] & 0x60) >> 5,
|
||||
(ie->data[0] & 0x10) >> 4, loc2str(ie->data[0] & 0xf), ie->data[0] & 0xf);
|
||||
pri_message(pri, "%c Ext: %d Progress Description: %s (%d) ]\n",
|
||||
@@ -1057,17 +1073,19 @@ static FUNC_RECV(receive_display)
|
||||
static FUNC_SEND(transmit_display)
|
||||
{
|
||||
int i;
|
||||
if ((pri->switchtype != PRI_SWITCH_NI1) && (pri->switchtype != PRI_SWITCH_QSIG)
|
||||
&& *call->callername) {
|
||||
i = 0;
|
||||
if(pri->switchtype != PRI_SWITCH_EUROISDN_E1) {
|
||||
ie->data[0] = 0xb1;
|
||||
++i;
|
||||
}
|
||||
memcpy(ie->data + i, call->callername, strlen(call->callername));
|
||||
return 2 + i + strlen(call->callername);
|
||||
|
||||
if ((pri->switchtype == PRI_SWITCH_QSIG) ||
|
||||
((pri->switchtype == PRI_SWITCH_EUROISDN_E1) && (pri->localtype == PRI_CPE)) ||
|
||||
!call->callername[0])
|
||||
return 0;
|
||||
|
||||
i = 0;
|
||||
if(pri->switchtype != PRI_SWITCH_EUROISDN_E1) {
|
||||
ie->data[0] = 0xb1;
|
||||
++i;
|
||||
}
|
||||
return 0;
|
||||
memcpy(ie->data + i, call->callername, strlen(call->callername));
|
||||
return 2 + i + strlen(call->callername);
|
||||
}
|
||||
|
||||
static FUNC_RECV(receive_progress_indicator)
|
||||
@@ -1118,22 +1136,21 @@ static FUNC_SEND(transmit_facility)
|
||||
int i = 0;
|
||||
|
||||
for (tmp = call->apdus; tmp; tmp = tmp->next) {
|
||||
if (tmp->message == msgtype)
|
||||
if ((tmp->message == msgtype) && !tmp->sent)
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (!tmp) /* No APDU found */
|
||||
return 0;
|
||||
|
||||
if (tmp->apdu_len > 235) { /* TODO: find out how much sapce we can use */
|
||||
pri_message(pri, "Requested ADPU (%d bytes) is too long\n", tmp->apdu_len);
|
||||
|
||||
|
||||
if (tmp->apdu_len > 235) { /* TODO: find out how much space we can use */
|
||||
pri_message(pri, "Requested APDU (%d bytes) is too long\n", tmp->apdu_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(ie->data, tmp->apdu, tmp->apdu_len);
|
||||
memcpy(&ie->data[i], tmp->apdu, tmp->apdu_len);
|
||||
i += tmp->apdu_len;
|
||||
tmp->sent = 1;
|
||||
|
||||
return i + 2;
|
||||
}
|
||||
@@ -1174,10 +1191,6 @@ static FUNC_RECV(receive_facility)
|
||||
if (ie->len < 1)
|
||||
return -1;
|
||||
|
||||
if ((ie->data[i] & 0xe0) != 0x80) {
|
||||
pri_error(pri, "!! Invalid Protocol Profile field 0x%X\n", ie->data[i]);
|
||||
return -1;
|
||||
}
|
||||
switch(next_protocol = protocol = (ie->data[i] & 0x1f)) {
|
||||
case Q932_PROTOCOL_CMIP:
|
||||
case Q932_PROTOCOL_ACSE:
|
||||
@@ -1194,6 +1207,9 @@ static FUNC_RECV(receive_facility)
|
||||
pri_error(pri, "!! Invalid Q.932 Protocol Profile of type 0x%X received\n", protocol);
|
||||
return -1;
|
||||
}
|
||||
/* Service indicator octet - Just ignore for now */
|
||||
if (!(ie->data[i] & 0x80))
|
||||
i++;
|
||||
i++;
|
||||
|
||||
if (ie->len < 3)
|
||||
@@ -1216,9 +1232,9 @@ static FUNC_RECV(receive_facility)
|
||||
case Q932_PROTOCOL_ROSE:
|
||||
switch (comp->type) {
|
||||
Q932_HANDLE_PROC(COMP_TYPE_INVOKE, Q932_STATE_SERVICE, "ROSE Invoke", rose_invoke_decode);
|
||||
Q932_HANDLE_NULL(COMP_TYPE_RETURN_RESULT, Q932_STATE_SERVICE, "ROSE return result", NULL);
|
||||
Q932_HANDLE_NULL(COMP_TYPE_RETURN_ERROR, Q932_STATE_SERVICE, "ROSE return error", NULL);
|
||||
Q932_HANDLE_NULL(COMP_TYPE_REJECT, Q932_STATE_SERVICE, "ROSE reject", NULL);
|
||||
Q932_HANDLE_PROC(COMP_TYPE_RETURN_RESULT, Q932_STATE_SERVICE, "ROSE return result", rose_return_result_decode);
|
||||
Q932_HANDLE_PROC(COMP_TYPE_RETURN_ERROR, Q932_STATE_SERVICE, "ROSE return error", rose_return_error_decode);
|
||||
Q932_HANDLE_PROC(COMP_TYPE_REJECT, Q932_STATE_SERVICE, "ROSE reject", rose_reject_decode);
|
||||
default:
|
||||
if (pri->debug & PRI_DEBUG_APDU)
|
||||
pri_message(pri, "Don't know how to handle ROSE component of type 0x%X\n", comp->type);
|
||||
@@ -1332,7 +1348,7 @@ static char *callstate2str(int callstate)
|
||||
|
||||
static FUNC_DUMP(dump_call_state)
|
||||
{
|
||||
pri_message(pri, "%c Call State (len=%2d) [ Ext: %d Coding: %s (%d) Call state: %s (%d)\n",
|
||||
pri_message(pri, "%c Call State (len=%2d) [ Ext: %d Coding: %s (%d) Call state: %s (%d)\n",
|
||||
prefix, len, ie->data[0] >> 7, coding2str((ie->data[0] & 0xC0) >> 6), (ie->data[0] & 0xC0) >> 6,
|
||||
callstate2str(ie->data[0] & 0x3f), ie->data[0] & 0x3f);
|
||||
}
|
||||
@@ -1371,7 +1387,8 @@ static FUNC_DUMP(dump_keypad_facility)
|
||||
if (ie->len == 0 || ie->len > sizeof(tmp))
|
||||
return;
|
||||
|
||||
libpri_copy_string(tmp, (char *) ie->data, sizeof(tmp));
|
||||
memcpy(tmp, ie->data, ie->len);
|
||||
tmp[ie->len] = '\0';
|
||||
pri_message(pri, "%c Keypad Facility (len=%2d) [ %s ]\n", prefix, ie->len, tmp );
|
||||
}
|
||||
|
||||
@@ -1382,18 +1399,37 @@ static FUNC_RECV(receive_keypad_facility)
|
||||
if (ie->len == 0)
|
||||
return -1;
|
||||
|
||||
if (ie->len > (sizeof(call->digitbuf) - 1))
|
||||
mylen = (sizeof(call->digitbuf) - 1);
|
||||
if (ie->len > (sizeof(call->keypad_digits) - 1))
|
||||
mylen = (sizeof(call->keypad_digits) - 1);
|
||||
else
|
||||
mylen = ie->len;
|
||||
|
||||
memcpy(call->digitbuf, ie->data, mylen);
|
||||
|
||||
call->digitbuf[mylen] = 0;
|
||||
memcpy(call->keypad_digits, ie->data, mylen);
|
||||
call->keypad_digits[mylen] = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static FUNC_SEND(transmit_keypad_facility)
|
||||
{
|
||||
int sublen;
|
||||
|
||||
sublen = strlen(call->keypad_digits);
|
||||
|
||||
if (sublen > 32) {
|
||||
sublen = 32;
|
||||
call->keypad_digits[32] = '\0';
|
||||
}
|
||||
|
||||
if (sublen) {
|
||||
libpri_copy_string((char *)ie->data, (char *)call->keypad_digits, sizeof(call->keypad_digits));
|
||||
/* Make sure we clear the field */
|
||||
call->keypad_digits[0] = '\0';
|
||||
return sublen + 2;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static FUNC_DUMP(dump_display)
|
||||
{
|
||||
int x, y;
|
||||
@@ -1413,59 +1449,72 @@ static FUNC_DUMP(dump_display)
|
||||
}
|
||||
}
|
||||
|
||||
static void dump_ie_data(unsigned char *c, int len)
|
||||
#define CHECK_OVERFLOW(limit) \
|
||||
if (tmpptr - tmp + limit >= sizeof(tmp)) { \
|
||||
*tmpptr = '\0'; \
|
||||
pri_message(pri, "%s", tmpptr = tmp); \
|
||||
}
|
||||
|
||||
static void dump_ie_data(struct pri *pri, unsigned char *c, int len)
|
||||
{
|
||||
char tmp[1024] = "";
|
||||
int x=0;
|
||||
static char hexs[16] = "0123456789ABCDEF";
|
||||
char tmp[1024], *tmpptr;
|
||||
int lastascii = 0;
|
||||
while(len) {
|
||||
if (((*c >= 'A') && (*c <= 'Z')) ||
|
||||
((*c >= 'a') && (*c <= 'z')) ||
|
||||
((*c >= '0') && (*c <= '9'))) {
|
||||
tmpptr = tmp;
|
||||
for (; len; --len, ++c) {
|
||||
CHECK_OVERFLOW(7);
|
||||
if (isprint(*c)) {
|
||||
if (!lastascii) {
|
||||
if (*tmp) {
|
||||
tmp[x++] = ',';
|
||||
tmp[x++] = ' ';
|
||||
if (tmpptr != tmp) {
|
||||
*tmpptr++ = ',';
|
||||
*tmpptr++ = ' ';
|
||||
}
|
||||
tmp[x++] = '\'';
|
||||
*tmpptr++ = '\'';
|
||||
lastascii = 1;
|
||||
}
|
||||
tmp[x++] = *c;
|
||||
lastascii = 1;
|
||||
*tmpptr++ = *c;
|
||||
} else {
|
||||
if (lastascii) {
|
||||
tmp[x++] = '\'';
|
||||
*tmpptr++ = '\'';
|
||||
lastascii = 0;
|
||||
}
|
||||
if (*tmp) {
|
||||
tmp[x++] = ',';
|
||||
tmp[x++] = ' ';
|
||||
if (tmpptr != tmp) {
|
||||
*tmpptr++ = ',';
|
||||
*tmpptr++ = ' ';
|
||||
}
|
||||
sprintf (tmp + x, "0x%02x", *c);
|
||||
x += 4;
|
||||
lastascii = 0;
|
||||
*tmpptr++ = '0';
|
||||
*tmpptr++ = 'x';
|
||||
*tmpptr++ = hexs[(*c >> 4) & 0x0f];
|
||||
*tmpptr++ = hexs[(*c) & 0x0f];
|
||||
}
|
||||
c++;
|
||||
len--;
|
||||
}
|
||||
if (lastascii)
|
||||
tmp[x++] = '\'';
|
||||
pri_message(NULL, tmp);
|
||||
*tmpptr++ = '\'';
|
||||
*tmpptr = '\0';
|
||||
pri_message(pri, "%s", tmp);
|
||||
}
|
||||
|
||||
static FUNC_DUMP(dump_facility)
|
||||
{
|
||||
int dataat = (ie->data[0] & 0x80) ? 1 : 2;
|
||||
pri_message(pri, "%c Facility (len=%2d, codeset=%d) [ ", prefix, len, Q931_IE_CODESET(full_ie));
|
||||
dump_ie_data(ie->data, ie->len);
|
||||
dump_ie_data(pri, ie->data, ie->len);
|
||||
pri_message(NULL, " ]\n");
|
||||
if (ie->len > 1) {
|
||||
pri_message(pri, "PROTOCOL %02X\n", ie->data[0] & ASN1_TYPE_MASK);
|
||||
asn1_dump(pri, &ie->data[dataat], ie->len - dataat);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static FUNC_DUMP(dump_network_spec_fac)
|
||||
{
|
||||
pri_message(pri, "%c Network-Specific Facilities (len=%2d) [ ", prefix, ie->len);
|
||||
if (ie->data[0] == 0x00) {
|
||||
pri_message(pri, code2str(ie->data[1], facilities, sizeof(facilities) / sizeof(facilities[0])));
|
||||
pri_message(pri, "%s", code2str(ie->data[1], facilities, sizeof(facilities) / sizeof(facilities[0])));
|
||||
}
|
||||
else
|
||||
dump_ie_data(ie->data, ie->len);
|
||||
dump_ie_data(pri, ie->data, ie->len);
|
||||
pri_message(pri, " ]\n");
|
||||
}
|
||||
|
||||
@@ -1499,11 +1548,11 @@ static char *pri_causeclass2str(int cause)
|
||||
static struct msgtype causeclasses[] = {
|
||||
{ 0, "Normal Event" },
|
||||
{ 1, "Normal Event" },
|
||||
{ 2, "Network Congestion" },
|
||||
{ 2, "Network Congestion (resource unavailable)" },
|
||||
{ 3, "Service or Option not Available" },
|
||||
{ 4, "Service or Option not Implemented" },
|
||||
{ 5, "Invalid message" },
|
||||
{ 6, "Protocol Error" },
|
||||
{ 5, "Invalid message (e.g. parameter out of range)" },
|
||||
{ 6, "Protocol Error (e.g. unknown message)" },
|
||||
{ 7, "Interworking" },
|
||||
};
|
||||
return code2str(cause, causeclasses, sizeof(causeclasses) / sizeof(causeclasses[0]));
|
||||
@@ -1512,7 +1561,7 @@ static char *pri_causeclass2str(int cause)
|
||||
static FUNC_DUMP(dump_cause)
|
||||
{
|
||||
int x;
|
||||
pri_message(pri, "%c Cause (len=%2d) [ Ext: %d Coding: %s (%d) 0: %d Location: %s (%d)\n",
|
||||
pri_message(pri, "%c Cause (len=%2d) [ Ext: %d Coding: %s (%d) Spare: %d Location: %s (%d)\n",
|
||||
prefix, len, ie->data[0] >> 7, coding2str((ie->data[0] & 0x60) >> 5), (ie->data[0] & 0x60) >> 5,
|
||||
(ie->data[0] & 0x10) >> 4, loc2str(ie->data[0] & 0xf), ie->data[0] & 0xf);
|
||||
pri_message(pri, "%c Ext: %d Cause: %s (%d), class = %s (%d) ]\n",
|
||||
@@ -1906,6 +1955,17 @@ static FUNC_DUMP(dump_signal)
|
||||
pri_message(pri, "Signal %s (%d)\n", signal2str(ie->data[0]), ie->data[0]);
|
||||
}
|
||||
|
||||
static FUNC_DUMP(dump_transit_count)
|
||||
{
|
||||
/* Defined in ECMA-225 */
|
||||
pri_message(pri, "%c Transit Count (len=%02d): ", prefix, len);
|
||||
if (len < 3) {
|
||||
pri_message(pri, "Invalid length\n");
|
||||
return;
|
||||
}
|
||||
pri_message(pri, "Count=%d (0x%02x)\n", ie->data[0] & 0x1f, ie->data[0] & 0x1f);
|
||||
}
|
||||
|
||||
|
||||
static struct ie ies[] = {
|
||||
/* Codeset 0 - Common */
|
||||
@@ -1935,7 +1995,7 @@ static struct ie ies[] = {
|
||||
{ 0, Q931_LOW_LAYER_COMPAT, "Low-layer Compatibility" },
|
||||
{ 0, Q931_HIGH_LAYER_COMPAT, "High-layer Compatibility" },
|
||||
{ 1, Q931_PACKET_SIZE, "Packet Size" },
|
||||
{ 1, Q931_IE_FACILITY, "Facility" , dump_facility, receive_facility, transmit_facility },
|
||||
{ 0, Q931_IE_FACILITY, "Facility" , dump_facility, receive_facility, transmit_facility },
|
||||
{ 1, Q931_IE_REDIRECTION_NUMBER, "Redirection Number" },
|
||||
{ 1, Q931_IE_REDIRECTION_SUBADDR, "Redirection Subaddress" },
|
||||
{ 1, Q931_IE_FEATURE_ACTIVATE, "Feature Activation" },
|
||||
@@ -1947,7 +2007,7 @@ static struct ie ies[] = {
|
||||
{ 1, Q931_IE_NOTIFY_IND, "Notification Indicator", dump_notify, receive_notify, transmit_notify },
|
||||
{ 1, Q931_DISPLAY, "Display", dump_display, receive_display, transmit_display },
|
||||
{ 1, Q931_IE_TIME_DATE, "Date/Time", dump_time_date },
|
||||
{ 1, Q931_IE_KEYPAD_FACILITY, "Keypad Facility", dump_keypad_facility, receive_keypad_facility },
|
||||
{ 1, Q931_IE_KEYPAD_FACILITY, "Keypad Facility", dump_keypad_facility, receive_keypad_facility, transmit_keypad_facility },
|
||||
{ 0, Q931_IE_SIGNAL, "Signal", dump_signal },
|
||||
{ 1, Q931_IE_SWITCHHOOK, "Switch-hook" },
|
||||
{ 1, Q931_IE_USER_USER, "User-User", dump_user_user, receive_user_user, transmit_user_user },
|
||||
@@ -1960,6 +2020,8 @@ static struct ie ies[] = {
|
||||
{ 1, Q931_IE_USER_USER_FACILITY, "User-User Facility" },
|
||||
{ 1, Q931_IE_UPDATE, "Update" },
|
||||
{ 1, Q931_SENDING_COMPLETE, "Sending Complete", dump_sending_complete, receive_sending_complete, transmit_sending_complete },
|
||||
/* Codeset 4 - Q.SIG specific */
|
||||
{ 1, QSIG_IE_TRANSIT_COUNT | Q931_CODESET(4), "Transit Count", dump_transit_count },
|
||||
/* Codeset 6 - Network specific */
|
||||
{ 1, Q931_IE_ORIGINATING_LINE_INFO, "Originating Line Information", dump_line_information, receive_line_information, transmit_line_information },
|
||||
{ 1, Q931_IE_FACILITY | Q931_CODESET(6), "Facility", dump_facility, receive_facility, transmit_facility },
|
||||
@@ -2097,7 +2159,7 @@ static inline void q931_dumpie(struct pri *pri, int codeset, q931_ie *ie, char p
|
||||
return;
|
||||
}
|
||||
|
||||
pri_error(pri, "!! %c Unknown IE %d (len = %d)\n", prefix, base_ie, ielen(ie));
|
||||
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)
|
||||
@@ -2360,7 +2422,6 @@ static int send_message(struct pri *pri, q931_call *c, int msgtype, int ies[])
|
||||
int offset=0;
|
||||
int x;
|
||||
int codeset;
|
||||
struct apdu_event *facevent = c->apdus;
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
len = sizeof(buf);
|
||||
@@ -2369,24 +2430,7 @@ static int send_message(struct pri *pri, q931_call *c, int msgtype, int ies[])
|
||||
x=0;
|
||||
codeset = 0;
|
||||
while(ies[x] > -1) {
|
||||
if (ies[x] == Q931_IE_FACILITY) {
|
||||
res = 0;
|
||||
while (facevent) {
|
||||
if (!facevent->sent && (facevent->message == msgtype)) {
|
||||
int tmpres;
|
||||
tmpres = add_ie(pri, c, mh->msg, ies[x], (q931_ie *)(mh->data + offset), len, &codeset);
|
||||
if (tmpres < 0) {
|
||||
pri_error(pri, "!! Unable to add IE '%s'\n", ie2str(ies[x]));
|
||||
return -1;
|
||||
}
|
||||
res += tmpres;
|
||||
facevent->sent = 1;
|
||||
}
|
||||
facevent = facevent->next;
|
||||
}
|
||||
} else {
|
||||
res = add_ie(pri, c, mh->msg, ies[x], (q931_ie *)(mh->data + offset), len, &codeset);
|
||||
}
|
||||
res = add_ie(pri, c, mh->msg, ies[x], (q931_ie *)(mh->data + offset), len, &codeset);
|
||||
|
||||
if (res < 0) {
|
||||
pri_error(pri, "!! Unable to add IE '%s'\n", ie2str(ies[x]));
|
||||
@@ -2432,20 +2476,28 @@ static int q931_status(struct pri *pri, q931_call *c, int cause)
|
||||
return send_message(pri, cur, Q931_STATUS, status_ies);
|
||||
}
|
||||
|
||||
static int information_ies[] = { Q931_CALLED_PARTY_NUMBER, -1 };
|
||||
static int information_ies[] = { Q931_IE_KEYPAD_FACILITY, Q931_CALLED_PARTY_NUMBER, -1 };
|
||||
|
||||
int q931_information(struct pri *pri, q931_call *c, char digit)
|
||||
{
|
||||
c->callednum[0]=digit;
|
||||
c->callednum[1]='\0';
|
||||
c->callednum[0] = digit;
|
||||
c->callednum[1] = '\0';
|
||||
return send_message(pri, c, Q931_INFORMATION, information_ies);
|
||||
}
|
||||
|
||||
static int keypad_facility_ies[] = { Q931_IE_KEYPAD_FACILITY, -1 };
|
||||
|
||||
int q931_keypad_facility(struct pri *pri, q931_call *call, char *digits)
|
||||
{
|
||||
libpri_copy_string(call->keypad_digits, digits, sizeof(call->keypad_digits));
|
||||
return send_message(pri, call, Q931_INFORMATION, keypad_facility_ies);
|
||||
}
|
||||
|
||||
static int restart_ack_ies[] = { Q931_CHANNEL_IDENT, Q931_RESTART_INDICATOR, -1 };
|
||||
|
||||
static int restart_ack(struct pri *pri, q931_call *c)
|
||||
{
|
||||
c->ourcallstate = Q931_CALL_STATE_NULL;
|
||||
UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_NULL);
|
||||
c->peercallstate = Q931_CALL_STATE_NULL;
|
||||
return send_message(pri, c, Q931_RESTART_ACKNOWLEDGE, restart_ack_ies);
|
||||
}
|
||||
@@ -2516,7 +2568,7 @@ int q931_call_proceeding(struct pri *pri, q931_call *c, int channel, int info)
|
||||
}
|
||||
c->chanflags &= ~FLAG_PREFERRED;
|
||||
c->chanflags |= FLAG_EXCLUSIVE;
|
||||
c->ourcallstate = Q931_CALL_STATE_INCOMING_CALL_PROCEEDING;
|
||||
UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_INCOMING_CALL_PROCEEDING);
|
||||
c->peercallstate = Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING;
|
||||
if (info) {
|
||||
c->progloc = LOC_PRIV_NET_LOCAL_USER;
|
||||
@@ -2544,7 +2596,7 @@ int q931_alerting(struct pri *pri, q931_call *c, int channel, int info)
|
||||
c->progressmask = PRI_PROG_INBAND_AVAILABLE;
|
||||
} else
|
||||
c->progressmask = 0;
|
||||
c->ourcallstate = Q931_CALL_STATE_CALL_RECEIVED;
|
||||
UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_CALL_RECEIVED);
|
||||
c->peercallstate = Q931_CALL_STATE_CALL_DELIVERED;
|
||||
c->alive = 1;
|
||||
return send_message(pri, c, Q931_ALERTING, alerting_ies);
|
||||
@@ -2568,7 +2620,7 @@ int q931_setup_ack(struct pri *pri, q931_call *c, int channel, int nonisdn)
|
||||
c->progressmask = PRI_PROG_CALLED_NOT_ISDN;
|
||||
} else
|
||||
c->progressmask = 0;
|
||||
c->ourcallstate = Q931_CALL_STATE_OVERLAP_RECEIVING;
|
||||
UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_OVERLAP_RECEIVING);
|
||||
c->peercallstate = Q931_CALL_STATE_OVERLAP_SENDING;
|
||||
c->alive = 1;
|
||||
return send_message(pri, c, Q931_SETUP_ACKNOWLEDGE, connect_ies);
|
||||
@@ -2642,17 +2694,17 @@ int q931_connect(struct pri *pri, q931_call *c, int channel, int nonisdn)
|
||||
c->progressmask = PRI_PROG_CALLED_NOT_ISDN;
|
||||
} else
|
||||
c->progressmask = 0;
|
||||
if (pri->localtype == PRI_CPE)
|
||||
c->ourcallstate = Q931_CALL_STATE_CONNECT_REQUEST;
|
||||
if(pri->localtype == PRI_NETWORK || pri->switchtype == PRI_SWITCH_QSIG)
|
||||
UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_ACTIVE);
|
||||
else
|
||||
c->ourcallstate = Q931_CALL_STATE_ACTIVE;
|
||||
UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_CONNECT_REQUEST);
|
||||
c->peercallstate = Q931_CALL_STATE_ACTIVE;
|
||||
c->alive = 1;
|
||||
/* Setup timer */
|
||||
/* Connect request timer */
|
||||
if (c->retranstimer)
|
||||
pri_schedule_del(pri, c->retranstimer);
|
||||
c->retranstimer = 0;
|
||||
if ((pri->localtype == PRI_CPE) && (!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);
|
||||
}
|
||||
@@ -2661,7 +2713,7 @@ static int release_ies[] = { Q931_CAUSE, Q931_IE_USER_USER, -1 };
|
||||
|
||||
int q931_release(struct pri *pri, q931_call *c, int cause)
|
||||
{
|
||||
c->ourcallstate = Q931_CALL_STATE_RELEASE_REQUEST;
|
||||
UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_RELEASE_REQUEST);
|
||||
/* c->peercallstate stays the same */
|
||||
if (c->alive) {
|
||||
c->alive = 0;
|
||||
@@ -2700,7 +2752,7 @@ int q931_restart(struct pri *pri, int channel)
|
||||
c->channelno = channel;
|
||||
c->chanflags &= ~FLAG_PREFERRED;
|
||||
c->chanflags |= FLAG_EXCLUSIVE;
|
||||
c->ourcallstate = Q931_CALL_STATE_RESTART;
|
||||
UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_RESTART);
|
||||
c->peercallstate = Q931_CALL_STATE_RESTART_REQUEST;
|
||||
return send_message(pri, c, Q931_RESTART, restart_ies);
|
||||
}
|
||||
@@ -2709,7 +2761,7 @@ static int disconnect_ies[] = { Q931_CAUSE, Q931_IE_USER_USER, -1 };
|
||||
|
||||
int q931_disconnect(struct pri *pri, q931_call *c, int cause)
|
||||
{
|
||||
c->ourcallstate = Q931_CALL_STATE_DISCONNECT_REQUEST;
|
||||
UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_DISCONNECT_REQUEST);
|
||||
c->peercallstate = Q931_CALL_STATE_DISCONNECT_INDICATION;
|
||||
if (c->alive) {
|
||||
c->alive = 0;
|
||||
@@ -2725,8 +2777,9 @@ 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_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 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 gr303_setup_ies[] = { Q931_BEARER_CAPABILITY, Q931_CHANNEL_IDENT, -1 };
|
||||
|
||||
@@ -2825,7 +2878,7 @@ int q931_setup(struct pri *pri, q931_call *c, struct pri_sr *req)
|
||||
c->alive = 1;
|
||||
/* make sure we call PRI_EVENT_HANGUP_ACK once we send/receive RELEASE_COMPLETE */
|
||||
c->sendhangupack = 1;
|
||||
c->ourcallstate = Q931_CALL_STATE_CALL_INITIATED;
|
||||
UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_CALL_INITIATED);
|
||||
c->peercallstate = Q931_CALL_STATE_OVERLAP_SENDING;
|
||||
}
|
||||
return res;
|
||||
@@ -2837,7 +2890,7 @@ static int release_complete_ies[] = { Q931_IE_USER_USER, -1 };
|
||||
static int q931_release_complete(struct pri *pri, q931_call *c, int cause)
|
||||
{
|
||||
int res = 0;
|
||||
c->ourcallstate = Q931_CALL_STATE_NULL;
|
||||
UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_NULL);
|
||||
c->peercallstate = Q931_CALL_STATE_NULL;
|
||||
if (cause > -1) {
|
||||
c->cause = cause;
|
||||
@@ -2912,8 +2965,6 @@ 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 */
|
||||
@@ -2927,6 +2978,10 @@ 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);
|
||||
@@ -3055,6 +3110,7 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
|
||||
case Q931_PROGRESS:
|
||||
c->useruserinfo[0] = '\0';
|
||||
c->cause = -1;
|
||||
/* Fall through */
|
||||
case Q931_CALL_PROCEEDING:
|
||||
c->progress = -1;
|
||||
c->progressmask = 0;
|
||||
@@ -3080,6 +3136,7 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
|
||||
pri_schedule_del(pri, c->retranstimer);
|
||||
c->retranstimer = 0;
|
||||
c->useruserinfo[0] = '\0';
|
||||
/* Fall through */
|
||||
case Q931_STATUS:
|
||||
c->cause = -1;
|
||||
c->causecode = -1;
|
||||
@@ -3117,12 +3174,13 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
|
||||
pri_error(pri, "!! Not yet handling pre-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg);
|
||||
/* Fall through */
|
||||
default:
|
||||
pri_error(pri, "!! Don't know how to post-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg);
|
||||
pri_error(pri, "!! Don't know how to pre-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg);
|
||||
q931_status(pri,c, PRI_CAUSE_MESSAGE_TYPE_NONEXIST);
|
||||
if (c->newcall)
|
||||
q931_destroycall(pri,c->cr);
|
||||
return -1;
|
||||
}
|
||||
/* Handle IEs */
|
||||
memset(mandies, 0, sizeof(mandies));
|
||||
missingmand = 0;
|
||||
for (x=0;x<sizeof(msgs) / sizeof(msgs[0]); x++) {
|
||||
@@ -3217,7 +3275,7 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
|
||||
q931_destroycall(pri, c->cr);
|
||||
break;
|
||||
}
|
||||
c->ourcallstate = Q931_CALL_STATE_RESTART;
|
||||
UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_RESTART);
|
||||
c->peercallstate = Q931_CALL_STATE_RESTART_REQUEST;
|
||||
/* Send back the Restart Acknowledge */
|
||||
restart_ack(pri, c);
|
||||
@@ -3237,7 +3295,7 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
|
||||
if (c->progressmask & PRI_PROG_CALLER_NOT_ISDN)
|
||||
c->nonisdn = 1;
|
||||
c->newcall = 0;
|
||||
c->ourcallstate = Q931_CALL_STATE_CALL_PRESENT;
|
||||
UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_CALL_PRESENT);
|
||||
c->peercallstate = Q931_CALL_STATE_CALL_INITIATED;
|
||||
/* it's not yet a call since higher level can respond with RELEASE or RELEASE_COMPLETE */
|
||||
c->alive = 0;
|
||||
@@ -3282,7 +3340,7 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
|
||||
q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
|
||||
break;
|
||||
}
|
||||
c->ourcallstate = Q931_CALL_STATE_CALL_DELIVERED;
|
||||
UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_CALL_DELIVERED);
|
||||
c->peercallstate = Q931_CALL_STATE_CALL_RECEIVED;
|
||||
pri->ev.e = PRI_EVENT_RINGING;
|
||||
pri->ev.ringing.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
|
||||
@@ -3292,6 +3350,16 @@ 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) {
|
||||
@@ -3302,7 +3370,7 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
|
||||
q931_status(pri, c, PRI_CAUSE_WRONG_MESSAGE);
|
||||
break;
|
||||
}
|
||||
c->ourcallstate = Q931_CALL_STATE_ACTIVE;
|
||||
UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_ACTIVE);
|
||||
c->peercallstate = Q931_CALL_STATE_CONNECT_REQUEST;
|
||||
pri->ev.e = PRI_EVENT_ANSWER;
|
||||
pri->ev.answer.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
|
||||
@@ -3357,7 +3425,7 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
|
||||
pri->ev.proceeding.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
|
||||
if (mh->msg == Q931_CALL_PROCEEDING) {
|
||||
pri->ev.e = PRI_EVENT_PROCEEDING;
|
||||
c->ourcallstate = Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING;
|
||||
UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING);
|
||||
c->peercallstate = Q931_CALL_STATE_INCOMING_CALL_PROCEEDING;
|
||||
}
|
||||
pri->ev.proceeding.progress = c->progress;
|
||||
@@ -3373,18 +3441,19 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
|
||||
}
|
||||
cur = cur->next;
|
||||
}
|
||||
|
||||
return Q931_RES_HAVEEVENT;
|
||||
case Q931_CONNECT_ACKNOWLEDGE:
|
||||
if (c->newcall) {
|
||||
q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
|
||||
break;
|
||||
}
|
||||
if (c->ourcallstate != Q931_CALL_STATE_CONNECT_REQUEST) {
|
||||
if (!(c->ourcallstate == Q931_CALL_STATE_CONNECT_REQUEST) &&
|
||||
!(c->ourcallstate == Q931_CALL_STATE_ACTIVE &&
|
||||
(pri->localtype == PRI_NETWORK || pri->switchtype == PRI_SWITCH_QSIG))) {
|
||||
q931_status(pri,c,PRI_CAUSE_WRONG_MESSAGE);
|
||||
break;
|
||||
}
|
||||
c->ourcallstate = Q931_CALL_STATE_ACTIVE;
|
||||
UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_ACTIVE);
|
||||
c->peercallstate = Q931_CALL_STATE_ACTIVE;
|
||||
break;
|
||||
case Q931_STATUS:
|
||||
@@ -3412,7 +3481,7 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
|
||||
pri->ev.hangup.aoc_units = c->aoc_units;
|
||||
libpri_copy_string(pri->ev.hangup.useruserinfo, c->useruserinfo, sizeof(pri->ev.hangup.useruserinfo));
|
||||
/* Free resources */
|
||||
c->ourcallstate = Q931_CALL_STATE_NULL;
|
||||
UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_NULL);
|
||||
c->peercallstate = Q931_CALL_STATE_NULL;
|
||||
if (c->alive) {
|
||||
pri->ev.e = PRI_EVENT_HANGUP;
|
||||
@@ -3431,7 +3500,7 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
|
||||
}
|
||||
break;
|
||||
case Q931_RELEASE_COMPLETE:
|
||||
c->ourcallstate = Q931_CALL_STATE_NULL;
|
||||
UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_NULL);
|
||||
c->peercallstate = Q931_CALL_STATE_NULL;
|
||||
pri->ev.hangup.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
|
||||
pri->ev.hangup.cause = c->cause;
|
||||
@@ -3466,7 +3535,7 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
|
||||
else {
|
||||
c->peercallstate = Q931_CALL_STATE_RELEASE_REQUEST;
|
||||
}
|
||||
c->ourcallstate = Q931_CALL_STATE_NULL;
|
||||
UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_NULL);
|
||||
pri->ev.e = PRI_EVENT_HANGUP;
|
||||
pri->ev.hangup.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
|
||||
pri->ev.hangup.cause = c->cause;
|
||||
@@ -3491,7 +3560,7 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
|
||||
q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
|
||||
break;
|
||||
}
|
||||
c->ourcallstate = Q931_CALL_STATE_DISCONNECT_INDICATION;
|
||||
UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_DISCONNECT_INDICATION);
|
||||
c->peercallstate = Q931_CALL_STATE_DISCONNECT_REQUEST;
|
||||
c->sendhangupack = 1;
|
||||
/* Return such an event */
|
||||
@@ -3509,7 +3578,7 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
|
||||
q931_hangup(pri,c,c->cause);
|
||||
break;
|
||||
case Q931_RESTART_ACKNOWLEDGE:
|
||||
c->ourcallstate = Q931_CALL_STATE_NULL;
|
||||
UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_NULL);
|
||||
c->peercallstate = Q931_CALL_STATE_NULL;
|
||||
pri->ev.e = PRI_EVENT_RESTART_ACK;
|
||||
pri->ev.restartack.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
|
||||
@@ -3527,7 +3596,9 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
|
||||
pri->ev.e = PRI_EVENT_KEYPAD_DIGIT;
|
||||
pri->ev.digit.call = c;
|
||||
pri->ev.digit.channel = c->channelno | (c->ds1no << 8);
|
||||
libpri_copy_string(pri->ev.digit.digits, c->digitbuf, sizeof(pri->ev.digit.digits));
|
||||
libpri_copy_string(pri->ev.digit.digits, c->keypad_digits, sizeof(pri->ev.digit.digits));
|
||||
/* Make sure we clear it out before we return */
|
||||
c->keypad_digits[0] = '\0';
|
||||
return Q931_RES_HAVEEVENT;
|
||||
}
|
||||
pri->ev.e = PRI_EVENT_INFO_RECEIVED;
|
||||
@@ -3548,7 +3619,7 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
|
||||
q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
|
||||
break;
|
||||
}
|
||||
c->ourcallstate = Q931_CALL_STATE_OVERLAP_SENDING;
|
||||
UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_OVERLAP_SENDING);
|
||||
c->peercallstate = Q931_CALL_STATE_OVERLAP_RECEIVING;
|
||||
pri->ev.e = PRI_EVENT_SETUP_ACK;
|
||||
pri->ev.setup_ack.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
|
||||
@@ -3597,6 +3668,131 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Clear a call, although we did not receive any hangup notification. */
|
||||
static int pri_internal_clear(void *data)
|
||||
{
|
||||
struct q931_call *c = data;
|
||||
struct pri *pri = c->pri;
|
||||
int res;
|
||||
|
||||
if (c->retranstimer)
|
||||
pri_schedule_del(pri, c->retranstimer);
|
||||
c->retranstimer = 0;
|
||||
c->useruserinfo[0] = '\0';
|
||||
c->cause = -1;
|
||||
c->causecode = -1;
|
||||
c->causeloc = -1;
|
||||
c->sugcallstate = -1;
|
||||
c->aoc_units = -1;
|
||||
|
||||
UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_NULL);
|
||||
c->peercallstate = Q931_CALL_STATE_NULL;
|
||||
pri->ev.hangup.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
|
||||
pri->ev.hangup.cause = c->cause;
|
||||
pri->ev.hangup.cref = c->cr;
|
||||
pri->ev.hangup.call = c;
|
||||
pri->ev.hangup.aoc_units = c->aoc_units;
|
||||
libpri_copy_string(pri->ev.hangup.useruserinfo, c->useruserinfo, sizeof(pri->ev.hangup.useruserinfo));
|
||||
|
||||
/* Free resources */
|
||||
if (c->alive) {
|
||||
pri->ev.e = PRI_EVENT_HANGUP;
|
||||
res = Q931_RES_HAVEEVENT;
|
||||
c->alive = 0;
|
||||
} else if (c->sendhangupack) {
|
||||
res = Q931_RES_HAVEEVENT;
|
||||
pri->ev.e = PRI_EVENT_HANGUP_ACK;
|
||||
q931_hangup(pri, c, c->cause);
|
||||
} else {
|
||||
res = 0;
|
||||
q931_hangup(pri, c, c->cause);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Handle T309 timeout for an active call. */
|
||||
static void pri_dl_down_timeout(void *data)
|
||||
{
|
||||
struct q931_call *c = data;
|
||||
struct pri *pri = c->pri;
|
||||
if (pri->debug & PRI_DEBUG_Q931_STATE)
|
||||
pri_message(pri, DBGHEAD "Timed out waiting for data link re-establishment\n", DBGINFO);
|
||||
|
||||
c->cause = PRI_CAUSE_DESTINATION_OUT_OF_ORDER;
|
||||
if (pri_internal_clear(c) == Q931_RES_HAVEEVENT)
|
||||
pri->schedev = 1;
|
||||
}
|
||||
|
||||
/* Handle Layer 2 down event for a non active call. */
|
||||
static void pri_dl_down_cancelcall(void *data)
|
||||
{
|
||||
struct q931_call *c = data;
|
||||
struct pri *pri = c->pri;
|
||||
if (pri->debug & PRI_DEBUG_Q931_STATE)
|
||||
pri_message(pri, DBGHEAD "Cancel non active call after data link failure\n", DBGINFO);
|
||||
|
||||
c->cause = PRI_CAUSE_DESTINATION_OUT_OF_ORDER;
|
||||
if (pri_internal_clear(c) == Q931_RES_HAVEEVENT)
|
||||
pri->schedev = 1;
|
||||
}
|
||||
|
||||
/* Receive an indication from Layer 2 */
|
||||
void q931_dl_indication(struct pri *pri, int event)
|
||||
{
|
||||
q931_call *cur = NULL;
|
||||
|
||||
/* Just return if T309 is not enabled. */
|
||||
if (!pri || pri->timers[PRI_TIMER_T309] < 0)
|
||||
return;
|
||||
|
||||
switch (event) {
|
||||
case PRI_EVENT_DCHAN_DOWN:
|
||||
pri_message(pri, DBGHEAD "link is DOWN\n", DBGINFO);
|
||||
cur = *pri->callpool;
|
||||
while(cur) {
|
||||
if (cur->ourcallstate == Q931_CALL_STATE_ACTIVE) {
|
||||
/* For a call in Active state, activate T309 only if there is no timer already running. */
|
||||
if (!cur->retranstimer) {
|
||||
pri_message(pri, DBGHEAD "activate T309 for call %d on channel %d\n", DBGINFO, cur->cr, cur->channelno);
|
||||
cur->retranstimer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T309], pri_dl_down_timeout, cur);
|
||||
}
|
||||
} else if (cur->ourcallstate != Q931_CALL_STATE_NULL) {
|
||||
/* For a call that is not in Active state, schedule internal clearing of the call 'ASAP' (delay 0). */
|
||||
pri_message(pri, DBGHEAD "cancel call %d on channel %d in state %d (%s)\n", DBGINFO,
|
||||
cur->cr, cur->channelno, cur->ourcallstate, callstate2str(cur->ourcallstate));
|
||||
if (cur->retranstimer)
|
||||
pri_schedule_del(pri, cur->retranstimer);
|
||||
cur->retranstimer = pri_schedule_event(pri, 0, pri_dl_down_cancelcall, cur);
|
||||
}
|
||||
cur = cur->next;
|
||||
}
|
||||
break;
|
||||
case PRI_EVENT_DCHAN_UP:
|
||||
pri_message(pri, DBGHEAD "link is UP\n", DBGINFO);
|
||||
cur = *pri->callpool;
|
||||
while(cur) {
|
||||
if (cur->ourcallstate == Q931_CALL_STATE_ACTIVE && cur->retranstimer) {
|
||||
pri_message(pri, DBGHEAD "cancel T309 for call %d on channel %d\n", DBGINFO, cur->cr, cur->channelno);
|
||||
pri_schedule_del(pri, cur->retranstimer);
|
||||
cur->retranstimer = 0;
|
||||
q931_status(pri, cur, PRI_CAUSE_NORMAL_UNSPECIFIED);
|
||||
} else if (cur->ourcallstate != Q931_CALL_STATE_NULL &&
|
||||
cur->ourcallstate != Q931_CALL_STATE_DISCONNECT_REQUEST &&
|
||||
cur->ourcallstate != Q931_CALL_STATE_DISCONNECT_INDICATION &&
|
||||
cur->ourcallstate != Q931_CALL_STATE_RELEASE_REQUEST) {
|
||||
|
||||
/* The STATUS message sent here is not required by Q.931, but it may help anyway. */
|
||||
q931_status(pri, cur, PRI_CAUSE_NORMAL_UNSPECIFIED);
|
||||
}
|
||||
cur = cur->next;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
pri_message(pri, DBGHEAD "unexpected event %d.\n", DBGINFO, event);
|
||||
}
|
||||
}
|
||||
|
||||
int q931_call_getcrv(struct pri *pri, q931_call *call, int *callmode)
|
||||
{
|
||||
if (callmode)
|
||||
|
||||
12
testprilib.c
12
testprilib.c
@@ -42,11 +42,7 @@
|
||||
#include <sys/time.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#if defined(__linux__)
|
||||
#include <linux/zaptel.h>
|
||||
#elif defined(__FreeBSD__) || defined(SOLARIS)
|
||||
#include <zaptel.h>
|
||||
#endif
|
||||
#include <zaptel/zaptel.h>
|
||||
#ifndef SOLARIS
|
||||
#include <zap.h>
|
||||
#endif
|
||||
@@ -147,7 +143,7 @@ static void event2(struct pri *pri, pri_event *e)
|
||||
}
|
||||
}
|
||||
|
||||
static void testmsg(char *s)
|
||||
static void testmsg(struct pri *pri, char *s)
|
||||
{
|
||||
char *c;
|
||||
static int keeplast = 0;
|
||||
@@ -173,7 +169,7 @@ static void testmsg(char *s)
|
||||
keeplast = 0;
|
||||
}
|
||||
|
||||
static void testerr(char *s)
|
||||
static void testerr(struct pri *pri, char *s)
|
||||
{
|
||||
char *c;
|
||||
static int keeplast = 0;
|
||||
@@ -264,6 +260,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
first = pri;
|
||||
pri_set_debug(pri, DEBUG_LEVEL);
|
||||
pri_facility_enable(pri);
|
||||
if (pthread_create(&tmp, NULL, dchan, pri)) {
|
||||
perror("thread(0)");
|
||||
exit(1);
|
||||
@@ -273,6 +270,7 @@ int main(int argc, char *argv[])
|
||||
exit(1);
|
||||
}
|
||||
pri_set_debug(pri, DEBUG_LEVEL);
|
||||
pri_facility_enable(pri);
|
||||
if (pthread_create(&tmp, NULL, dchan, pri)) {
|
||||
perror("thread(1)");
|
||||
exit(1);
|
||||
|
||||
Reference in New Issue
Block a user