Compare commits

...

34 Commits

Author SHA1 Message Date
Russell Bryant
92fc823114 Importing files for 1.6.0-beta1 release
git-svn-id: https://origsvn.digium.com/svn/libpri/tags/1.6.0-beta1@520 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2008-01-19 00:45:19 +00:00
Russell Bryant
0671ab6798 Creating tag for the release of libpri-1.6.0-beta1
git-svn-id: https://origsvn.digium.com/svn/libpri/tags/1.6.0-beta1@519 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2008-01-19 00:43:47 +00:00
Jason Parker
682b914cd7 Add logging for 'make update' command (also fixes updates in some places). Issue #11766, initial patch by jmls.
git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@518 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2008-01-16 18:06:29 +00:00
Matthew Fredrickson
1de0fae287 Merged revisions 514 via svnmerge from
https://origsvn.digium.com/svn/libpri/branches/1.4

................
r514 | mattf | 2008-01-11 10:34:44 -0600 (Fri, 11 Jan 2008) | 9 lines

Merged revisions 513 via svnmerge from 
https://origsvn.digium.com/svn/libpri/branches/1.2

........
r513 | mattf | 2008-01-11 10:33:52 -0600 (Fri, 11 Jan 2008) | 1 line

We should not be parsing further into the bearer capability IE if the length does not confirm that there actually is data present
........

................


git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@515 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2008-01-11 16:36:10 +00:00
Russell Bryant
a80635e804 Remove unnecessary usage of the extern keyword.
git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@505 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2007-12-26 17:35:41 +00:00
Russell Bryant
b288766b85 Change malloc+memset to calloc. Also, handle allocation failures early to reduce indentation.
(closes issue #11469)
Reported by: eliel
Patches:
      pri.c.patch uploaded by eliel (license 64)
      q931.c.patch uploaded by eliel (license 64)
      q921.c.patch uploaded by eliel (license 64)
      pri_facility.c.patch uploaded by eliel (license 64)


git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@496 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2007-12-06 22:16:32 +00:00
Russell Bryant
1ee4f8aa3f Change a use of malloc+memset to calloc. Also, reduce indentation of a function
by doing the check for memory allocation failure at the beginning.


git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@495 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2007-12-06 03:48:07 +00:00
Russell Bryant
414fe8f956 Change the table used to hold the default timers to be global and const,
instead of allocating it on the stack each time the function is called.


git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@494 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2007-12-06 03:44:59 +00:00
Matthew Fredrickson
79bb2373f9 Improve the parameter name to better reflect its use
git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@493 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2007-12-05 00:20:13 +00:00
Matthew Fredrickson
dd553ed543 More PTMP fixes. Stand by, more changes to come
git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@492 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2007-12-05 00:12:54 +00:00
Matthew Fredrickson
813b2d1176 More magic to make BRI CPE PTMP work
git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@491 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2007-12-04 18:01:51 +00:00
Matthew Fredrickson
581287c8dc Make sure we loop BRI call references for one byte CREFs instead of two
git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@487 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2007-11-21 22:30:09 +00:00
Matthew Fredrickson
3071a4da29 Add BRI support to libpri
git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@486 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2007-11-21 21:49:30 +00:00
Kevin P. Fleming
9857425714 Merged revisions 479 via svnmerge from
https://origsvn.digium.com/svn/libpri/branches/1.4

................
r479 | kpfleming | 2007-10-22 10:10:06 -0500 (Mon, 22 Oct 2007) | 11 lines

Merged revisions 478 via svnmerge from 
https://origsvn.digium.com/svn/libpri/branches/1.2

........
r478 | kpfleming | 2007-10-22 10:09:27 -0500 (Mon, 22 Oct 2007) | 3 lines

we need to include stddef.h for 'size_t'


........

................


git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@480 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2007-10-22 15:15:31 +00:00
Matthew Fredrickson
ad076ee67b Make sure that we only output the message handling debug when we're actually debugging
git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@473 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2007-10-13 16:00:09 +00:00
Jason Parker
8bb0942f1a Merged revisions 470 via svnmerge from
https://origsvn.digium.com/svn/libpri/branches/1.4

(closes issue #10832)
........
r470 | qwell | 2007-10-05 11:45:39 -0500 (Fri, 05 Oct 2007) | 4 lines

Fix an incorrect pri_event structure definition.

Issue 10832, patch by flefoll

........


git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@471 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2007-10-05 16:46:18 +00:00
Matthew Fredrickson
9e05c336b1 Fix user-user IE order in setup message (#10705)
git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@469 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2007-09-25 21:56:47 +00:00
Matthew Fredrickson
b4970d79e9 Merged revisions 465 via svnmerge from
https://origsvn.digium.com/svn/libpri/branches/1.4

........
r465 | mattf | 2007-09-14 16:32:54 -0500 (Fri, 14 Sep 2007) | 1 line

Fix for #10189.  Make sure we properly report the user layer 1 for H.223 and H.245
........


git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@466 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2007-09-14 21:34:11 +00:00
Matthew Fredrickson
dc7a314fb3 Merged revisions 462 via svnmerge from
https://origsvn.digium.com/svn/libpri/branches/1.4

................
r462 | mattf | 2007-09-06 10:11:29 -0500 (Thu, 06 Sep 2007) | 9 lines

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.
........

................


git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@463 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2007-09-06 15:15:50 +00:00
Jason Parker
68b9ad1084 Merged revisions 446 via svnmerge from
https://origsvn.digium.com/svn/libpri/branches/1.4

................
r446 | qwell | 2007-08-27 14:21:08 -0500 (Mon, 27 Aug 2007) | 10 lines

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.

........

................


git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@447 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2007-08-27 19:22:03 +00:00
Jason Parker
f611084923 Merged revisions 441 via svnmerge from
https://origsvn.digium.com/svn/libpri/branches/1.4

(closes issue #10253)
........
r441 | qwell | 2007-08-06 14:58:19 -0500 (Mon, 06 Aug 2007) | 4 lines

Allow setting CC to something with a space, such as `make CC="gcc -m32"`

Issue 10253.

........


git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@442 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2007-08-06 19:58:56 +00:00
Matthew Fredrickson
a19cc73b41 Revert that back to how it was
git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@430 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2007-06-20 15:18:34 +00:00
Matthew Fredrickson
cbda0d7376 Patch to add PTMP mode (BRI support)
git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@429 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2007-06-19 20:31:54 +00:00
Matthew Fredrickson
453e006faa Merged revisions 427 via svnmerge from
https://origsvn.digium.com/svn/libpri/branches/1.4

................
r427 | mattf | 2007-06-19 13:23:36 -0500 (Tue, 19 Jun 2007) | 9 lines

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)
........

................


git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@428 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2007-06-19 18:24:20 +00:00
Matthew Fredrickson
3fba8aa932 Merged revisions 424 via svnmerge from
https://origsvn.digium.com/svn/libpri/branches/1.4

................
r424 | mattf | 2007-06-06 16:58:22 -0500 (Wed, 06 Jun 2007) | 9 lines

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
........

................


git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@425 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2007-06-06 21:59:19 +00:00
Matthew Fredrickson
bcd84a9d79 Preliminary patch plus mods for Q.SIG Path Replacement (Q.SIG version of 2BCT) #7778
git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@422 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2007-06-06 21:47:36 +00:00
Matthew Fredrickson
f5d76bd5d2 Merged revisions 416 via svnmerge from
https://origsvn.digium.com/svn/libpri/branches/1.4

................
r416 | mattf | 2007-06-06 08:22:15 -0500 (Wed, 06 Jun 2007) | 10 lines

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

........

................


git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@417 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2007-06-06 13:23:29 +00:00
Matthew Fredrickson
0a62b72633 Commit path for ROSE-12 and ROSE-13 support (#9076)
git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@413 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2007-05-25 17:36:28 +00:00
Matthew Fredrickson
ec3b7c156e Merged revisions 390 via svnmerge from
https://origsvn.digium.com/svn/libpri/branches/1.4

................
r390 | mattf | 2007-01-22 16:29:24 -0600 (Mon, 22 Jan 2007) | 10 lines

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.

........

................


git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@393 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2007-01-23 22:02:44 +00:00
Matthew Fredrickson
bcee9e2fd6 Fix mess up in up-port
git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@392 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2007-01-23 22:01:28 +00:00
Matthew Fredrickson
054a30cd94 Merged revisions 389 via svnmerge from
https://origsvn.digium.com/svn/libpri/branches/1.4

........
........


git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@391 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2007-01-22 22:31:13 +00:00
Joshua Colp
fd22b45abb Merged revisions 386 via svnmerge from
https://origsvn.digium.com/svn/libpri/branches/1.4

................
r386 | file | 2006-12-30 14:17:34 -0500 (Sat, 30 Dec 2006) | 10 lines

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)

........

................


git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@387 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2006-12-30 19:18:43 +00:00
Matthew Fredrickson
9a0d8c4df9 Remove pointless recursion. (#8281)
git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@382 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2006-11-03 18:16:49 +00:00
Kevin P. Fleming
c7f3a4b899 set up merge tracking from 1.4 branch
git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@374 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2006-09-20 21:00:58 +00:00
15 changed files with 1572 additions and 354 deletions

1
.version Normal file
View File

@@ -0,0 +1 @@
1.6.0-beta1

211
ChangeLog Normal file
View File

@@ -0,0 +1,211 @@
2008-01-18 Russell Bryant <russell@digium.com>
* libpri 1.6.0-beta1 released.
2008-01-16 18:06 +0000 [r518] Jason Parker <jparker@digium.com>
* Makefile, /: Add logging for 'make update' command (also fixes
updates in some places). Issue #11766, initial patch by jmls.
2008-01-11 16:36 +0000 [r515] Matthew Fredrickson <creslin@digium.com>
* q931.c, /: Merged revisions 514 via svnmerge from
https://origsvn.digium.com/svn/libpri/branches/1.4
................ r514 | mattf | 2008-01-11 10:34:44 -0600 (Fri,
11 Jan 2008) | 9 lines Merged revisions 513 via svnmerge from
https://origsvn.digium.com/svn/libpri/branches/1.2 ........ r513
| mattf | 2008-01-11 10:33:52 -0600 (Fri, 11 Jan 2008) | 1 line
We should not be parsing further into the bearer capability IE if
the length does not confirm that there actually is data present
........ ................
2007-12-26 17:35 +0000 [r505] Russell Bryant <russell@digium.com>
* libpri.h: Remove unnecessary usage of the extern keyword.
2007-12-06 22:16 +0000 [r494-496] Russell Bryant <russell@digium.com>
* q921.c, q931.c, pri_facility.c, pri.c: Change malloc+memset to
calloc. Also, handle allocation failures early to reduce
indentation. (closes issue #11469) Reported by: eliel Patches:
pri.c.patch uploaded by eliel (license 64) q931.c.patch uploaded
by eliel (license 64) q921.c.patch uploaded by eliel (license 64)
pri_facility.c.patch uploaded by eliel (license 64)
* pri.c: Change a use of malloc+memset to calloc. Also, reduce
indentation of a function by doing the check for memory
allocation failure at the beginning.
* pri.c: Change the table used to hold the default timers to be
global and const, instead of allocating it on the stack each time
the function is called.
2007-12-05 00:20 +0000 [r491-493] Matthew Fredrickson <creslin@digium.com>
* q931.c: Improve the parameter name to better reflect its use
* q921.c, q931.c: More PTMP fixes. Stand by, more changes to come
* q921.c, q931.c, testprilib.c: More magic to make BRI CPE PTMP
work
2007-11-21 22:30 +0000 [r486-487] Matthew Fredrickson <creslin@digium.com>
* q931.c: Make sure we loop BRI call references for one byte CREFs
instead of two
* q921.c, q931.c, libpri.h, pri.c, pritest.c, pri_internal.h: Add
BRI support to libpri
2007-10-22 15:15 +0000 [r480] Kevin P. Fleming <kpfleming@digium.com>
* /, pri_internal.h: Merged revisions 479 via svnmerge from
https://origsvn.digium.com/svn/libpri/branches/1.4
................ r479 | kpfleming | 2007-10-22 10:10:06 -0500
(Mon, 22 Oct 2007) | 11 lines Merged revisions 478 via svnmerge
from https://origsvn.digium.com/svn/libpri/branches/1.2 ........
r478 | kpfleming | 2007-10-22 10:09:27 -0500 (Mon, 22 Oct 2007) |
3 lines we need to include stddef.h for 'size_t' ........
................
2007-10-13 16:00 +0000 [r473] Matthew Fredrickson <creslin@digium.com>
* q921.c: Make sure that we only output the message handling debug
when we're actually debugging
2007-10-05 16:46 +0000 [r471] Jason Parker <jparker@digium.com>
* /, libpri.h: Merged revisions 470 via svnmerge from
https://origsvn.digium.com/svn/libpri/branches/1.4 (closes issue
#10832) ........ r470 | qwell | 2007-10-05 11:45:39 -0500 (Fri,
05 Oct 2007) | 4 lines Fix an incorrect pri_event structure
definition. Issue 10832, patch by flefoll ........
2007-09-25 21:56 +0000 [r469] Matthew Fredrickson <creslin@digium.com>
* q931.c: Fix user-user IE order in setup message (#10705)
2007-09-14 21:34 +0000 [r466] Matthew Fredrickson <creslin@digium.com>
* q931.c, /, libpri.h: Merged revisions 465 via svnmerge from
https://origsvn.digium.com/svn/libpri/branches/1.4 ........ r465
| mattf | 2007-09-14 16:32:54 -0500 (Fri, 14 Sep 2007) | 1 line
Fix for #10189. Make sure we properly report the user layer 1 for
H.223 and H.245 ........
2007-09-06 15:15 +0000 [r463] Matthew Fredrickson <creslin@digium.com>
* pri_facility.c, /, pri.c: Merged revisions 462 via svnmerge from
https://origsvn.digium.com/svn/libpri/branches/1.4
................ r462 | mattf | 2007-09-06 10:11:29 -0500 (Thu,
06 Sep 2007) | 9 lines Merged revisions 460 via svnmerge from
https://origsvn.digium.com/svn/libpri/branches/1.2 ........ r460
| mattf | 2007-09-06 10:06:42 -0500 (Thu, 06 Sep 2007) | 1 line
TBCT now works. It should work for NI2, 4E, and 5E. This code was
tested on NI2. ........ ................
2007-08-27 19:22 +0000 [r447] Jason Parker <jparker@digium.com>
* Makefile, /: Merged revisions 446 via svnmerge from
https://origsvn.digium.com/svn/libpri/branches/1.4
................ r446 | qwell | 2007-08-27 14:21:08 -0500 (Mon,
27 Aug 2007) | 10 lines Merged revisions 445 via svnmerge from
https://origsvn.digium.com/svn/libpri/branches/1.2 ........ r445
| qwell | 2007-08-27 14:20:23 -0500 (Mon, 27 Aug 2007) | 2 lines
Make sure we build both the static and shared modules with -fPIC.
........ ................
2007-08-06 19:58 +0000 [r442] Jason Parker <jparker@digium.com>
* Makefile, /: Merged revisions 441 via svnmerge from
https://origsvn.digium.com/svn/libpri/branches/1.4 (closes issue
#10253) ........ r441 | qwell | 2007-08-06 14:58:19 -0500 (Mon,
06 Aug 2007) | 4 lines Allow setting CC to something with a
space, such as `make CC="gcc -m32"` Issue 10253. ........
2007-06-20 15:18 +0000 [r428-430] Matthew Fredrickson <creslin@digium.com>
* Makefile: Revert that back to how it was
* Makefile, q921.c, q931.c, prisched.c, testprilib.c, pri_timers.h,
libpri.h, pri.c, pri_internal.h, pri_q921.h: Patch to add PTMP
mode (BRI support)
* q931.c, /: Merged revisions 427 via svnmerge from
https://origsvn.digium.com/svn/libpri/branches/1.4
................ r427 | mattf | 2007-06-19 13:23:36 -0500 (Tue,
19 Jun 2007) | 9 lines Merged revisions 426 via svnmerge from
https://origsvn.digium.com/svn/libpri/branches/1.2 ........ r426
| mattf | 2007-06-19 13:22:33 -0500 (Tue, 19 Jun 2007) | 1 line
Try to send pending facility messages if we receive alerting (for
when we don't get proceeding) (#9651) ........ ................
2007-06-06 21:59 +0000 [r417-425] Matthew Fredrickson <creslin@digium.com>
* pri_facility.c, /: Merged revisions 424 via svnmerge from
https://origsvn.digium.com/svn/libpri/branches/1.4
................ r424 | mattf | 2007-06-06 16:58:22 -0500 (Wed,
06 Jun 2007) | 9 lines 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 ........ ................
* q931.c, pri_facility.c, pri_facility.h, pri.c, pri_internal.h:
Preliminary patch plus mods for Q.SIG Path Replacement (Q.SIG
version of 2BCT) #7778
* pri_facility.c, /: Merged revisions 416 via svnmerge from
https://origsvn.digium.com/svn/libpri/branches/1.4
................ r416 | mattf | 2007-06-06 08:22:15 -0500 (Wed,
06 Jun 2007) | 10 lines Merged revisions 415 via svnmerge from
https://origsvn.digium.com/svn/libpri/branches/1.2 ........ r415
| mattf | 2007-06-06 08:20:05 -0500 (Wed, 06 Jun 2007) | 2 lines
Make sure we only send the NFE when we are talking QSIG ........
................
2007-05-25 17:36 +0000 [r413] Matthew Fredrickson <creslin@digium.com>
* q931.c, pri_facility.c, pri_facility.h, libpri.h: Commit path for
ROSE-12 and ROSE-13 support (#9076)
2007-01-23 22:02 +0000 [r391-393] Matthew Fredrickson <creslin@digium.com>
* q931.c, /: Merged revisions 390 via svnmerge from
https://origsvn.digium.com/svn/libpri/branches/1.4
................ r390 | mattf | 2007-01-22 16:29:24 -0600 (Mon,
22 Jan 2007) | 10 lines 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. ........
................
* /: Fix mess up in up-port
* /: Merged revisions 389 via svnmerge from
https://origsvn.digium.com/svn/libpri/branches/1.4 ........
........
2006-12-30 19:18 +0000 [r387] Joshua Colp <jcolp@digium.com>
* Makefile, /: Merged revisions 386 via svnmerge from
https://origsvn.digium.com/svn/libpri/branches/1.4
................ r386 | file | 2006-12-30 14:17:34 -0500 (Sat, 30
Dec 2006) | 10 lines Merged revisions 385 via svnmerge from
https://origsvn.digium.com/svn/libpri/branches/1.2 ........ r385
| file | 2006-12-30 14:16:17 -0500 (Sat, 30 Dec 2006) | 2 lines
Specify full path to restorecon instead of assuming it will be
available from what is in $PATH. (issue #8670 reported by djflux)
........ ................
2006-11-03 18:16 +0000 [r382] Matthew Fredrickson <creslin@digium.com>
* q921.c: Remove pointless recursion. (#8281)
2006-09-20 21:00 +0000 [r374] Kevin P. Fleming <kpfleming@digium.com>
* /: set up merge tracking from 1.4 branch
2006-09-20 Kevin P. Fleming <kpfleming@digium.com>
* libpri 1.4.0-beta1 released.

View File

@@ -36,7 +36,7 @@ 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
@@ -71,7 +71,16 @@ all: depend $(STATIC_LIBRARY) $(DYNAMIC_LIBRARY)
update:
@if [ -d .svn ]; then \
echo "Updating from Subversion..." ; \
svn update -q; \
fromrev="`svn info | $(AWK) '/Revision: / {print $$2}'`"; \
svn update | tee update.out; \
torev="`svn info | $(AWK) '/Revision: / {print $$2}'`"; \
echo "`date` Updated from revision $${fromrev} to $${torev}." >> update.log; \
rm -f .version; \
if [ `grep -c ^C update.out` -gt 0 ]; then \
echo ; echo "The following files have conflicts:" ; \
grep ^C update.out | cut -b4- ; \
fi ; \
rm -f update.out; \
else \
echo "Not under version control"; \
fi
@@ -82,7 +91,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
@@ -118,7 +127,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)
@@ -140,4 +149,4 @@ clean:
depend: .depend
.depend:
CC=$(CC) ./mkdep ${CFLAGS} `ls *.c`
CC="$(CC)" ./mkdep ${CFLAGS} `ls *.c`

141
libpri.h
View File

@@ -202,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
@@ -257,20 +257,24 @@ typedef struct q931_call q931_call;
typedef struct pri_event_generic {
/* Events with no additional information fall in this category */
int e;
struct pri *pri;
} pri_event_generic;
typedef struct pri_event_error {
int e;
struct pri *pri;
char err[256];
} pri_event_error;
typedef struct pri_event_restart {
int e;
struct pri *pri;
int channel;
} pri_event_restart;
typedef struct pri_event_ringing {
int e;
struct pri *pri;
int channel;
int cref;
int progress;
@@ -281,6 +285,7 @@ typedef struct pri_event_ringing {
typedef struct pri_event_answer {
int e;
struct pri *pri;
int channel;
int cref;
int progress;
@@ -291,6 +296,9 @@ typedef struct pri_event_answer {
typedef struct pri_event_facname {
int e;
struct pri *pri;
int callingpres; /* Presentation of Calling CallerID */
int callingplan; /* Dialing plan of Calling entity */
char callingname[256];
char callingnum[256];
int channel;
@@ -302,7 +310,9 @@ typedef struct pri_event_facname {
#define PRI_CALLINGPLANRDNIS
typedef struct pri_event_ring {
int e;
struct pri *pri;
int channel; /* Channel requested */
int cref; /* Call Reference Number */
int callingpres; /* Presentation of Calling CallerID */
int callingplanani; /* Dialing plan of Calling entity ANI */
int callingplan; /* Dialing plan of Calling entity */
@@ -318,7 +328,6 @@ typedef struct pri_event_ring {
int callingplanrdnis; /* Dialing plan of Redirecting Number */
char useruserinfo[260]; /* User->User info */
int flexible; /* Are we flexible with our channel selection? */
int cref; /* Call Reference Number */
int ctype; /* Call type (see PRI_TRANS_CAP_* */
int layer1; /* User layer 1 */
int complete; /* Have we seen "Complete" i.e. no more number? */
@@ -334,9 +343,10 @@ typedef struct pri_event_ring {
typedef struct pri_event_hangup {
int e;
struct pri *pri;
int channel; /* Channel requested */
int cause;
int cref;
int cause;
q931_call *call; /* Opaque call pointer */
long aoc_units; /* Advise of Charge number of charged units */
char useruserinfo[260]; /* User->User info */
@@ -344,12 +354,14 @@ typedef struct pri_event_hangup {
typedef struct pri_event_restart_ack {
int e;
struct pri *pri;
int channel;
} pri_event_restart_ack;
#define PRI_PROGRESS_CAUSE
typedef struct pri_event_proceeding {
int e;
struct pri *pri;
int channel;
int cref;
int progress;
@@ -360,18 +372,21 @@ typedef struct pri_event_proceeding {
typedef struct pri_event_setup_ack {
int e;
struct pri *pri;
int channel;
q931_call *call;
} pri_event_setup_ack;
typedef struct pri_event_notify {
int e;
struct pri *pri;
int channel;
int info;
} pri_event_notify;
typedef struct pri_event_keypad_digit {
int e;
struct pri *pri;
int channel;
q931_call *call;
char digits[64];
@@ -386,7 +401,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 */
@@ -405,77 +420,78 @@ typedef int (*pri_io_cb)(struct pri *pri, void *buf, int buflen);
channel operating in HDLC mode with FCS computed by the fd's driver. Also it
must be NON-BLOCKING! Frames received on the fd should include FCS. Nodetype
must be one of PRI_NETWORK or PRI_CPE. switchtype should be PRI_SWITCH_* */
extern struct pri *pri_new(int fd, int nodetype, int switchtype);
struct pri *pri_new(int fd, int nodetype, int switchtype);
struct pri *pri_new_bri(int fd, int ptpmode, int nodetype, int switchtype);
/* Create D-channel just as above with user defined I/O callbacks and data */
extern struct pri *pri_new_cb(int fd, int nodetype, int switchtype, pri_io_cb io_read, pri_io_cb io_write, void *userdata);
struct pri *pri_new_cb(int fd, int nodetype, int switchtype, pri_io_cb io_read, pri_io_cb io_write, void *userdata);
/* Retrieve the user data associated with the D channel */
extern void *pri_get_userdata(struct pri *pri);
void *pri_get_userdata(struct pri *pri);
/* Set the user data associated with the D channel */
extern void pri_set_userdata(struct pri *pri, void *userdata);
void pri_set_userdata(struct pri *pri, void *userdata);
/* Set Network Specific Facility for PRI */
extern void pri_set_nsf(struct pri *pri, int nsf);
void pri_set_nsf(struct pri *pri, int nsf);
/* Set debug parameters on PRI -- see above debug definitions */
extern void pri_set_debug(struct pri *pri, int debug);
void pri_set_debug(struct pri *pri, int debug);
/* Get debug parameters on PRI -- see above debug definitions */
extern int pri_get_debug(struct pri *pri);
int pri_get_debug(struct pri *pri);
#define PRI_FACILITY_ENABLE
/* Enable transmission support of Facility IEs on the pri */
extern void pri_facility_enable(struct pri *pri);
void pri_facility_enable(struct pri *pri);
/* Run PRI on the given D-channel, taking care of any events that
need to be handled. If block is set, it will block until an event
occurs which needs to be handled */
extern pri_event *pri_dchannel_run(struct pri *pri, int block);
pri_event *pri_dchannel_run(struct pri *pri, int block);
/* Check for an outstanding event on the PRI */
pri_event *pri_check_event(struct pri *pri);
/* Give a name to a given event ID */
extern char *pri_event2str(int id);
char *pri_event2str(int id);
/* Give a name to a node type */
extern char *pri_node2str(int id);
char *pri_node2str(int id);
/* Give a name to a switch type */
extern char *pri_switch2str(int id);
char *pri_switch2str(int id);
/* Print an event */
extern void pri_dump_event(struct pri *pri, pri_event *e);
void pri_dump_event(struct pri *pri, pri_event *e);
/* Turn presentation into a string */
extern char *pri_pres2str(int pres);
char *pri_pres2str(int pres);
/* Turn numbering plan into a string */
extern char *pri_plan2str(int plan);
char *pri_plan2str(int plan);
/* Turn cause into a string */
extern char *pri_cause2str(int cause);
char *pri_cause2str(int cause);
/* Acknowledge a call and place it on the given channel. Set info to non-zero if there
is in-band data available on the channel */
extern int pri_acknowledge(struct pri *pri, q931_call *call, int channel, int info);
int pri_acknowledge(struct pri *pri, q931_call *call, int channel, int info);
/* Send a digit in overlap mode */
extern int pri_information(struct pri *pri, q931_call *call, char digit);
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);
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);
int pri_need_more_info(struct pri *pri, q931_call *call, int channel, int nonisdn);
/* Answer the call on the given channel (ignored if you called acknowledge already).
Set non-isdn to non-zero if you are not connecting to ISDN equipment */
extern int pri_answer(struct pri *pri, q931_call *call, int channel, int nonisdn);
int pri_answer(struct pri *pri, q931_call *call, int channel, int nonisdn);
/* Set CRV reference for GR-303 calls */
@@ -492,59 +508,59 @@ extern int pri_answer(struct pri *pri, q931_call *call, int channel, int nonisdn
/* Hangup a call */
#define PRI_HANGUP
extern int pri_hangup(struct pri *pri, q931_call *call, int cause);
int pri_hangup(struct pri *pri, q931_call *call, int cause);
#define PRI_DESTROYCALL
extern void pri_destroycall(struct pri *pri, q931_call *call);
void pri_destroycall(struct pri *pri, q931_call *call);
#define PRI_RESTART
extern int pri_restart(struct pri *pri);
int pri_restart(struct pri *pri);
extern int pri_reset(struct pri *pri, int channel);
int pri_reset(struct pri *pri, int channel);
/* Create a new call */
extern q931_call *pri_new_call(struct pri *pri);
q931_call *pri_new_call(struct pri *pri);
/* Retrieve CRV reference for GR-303 calls. Returns >0 on success. */
extern int pri_get_crv(struct pri *pri, q931_call *call, int *callmode);
int pri_get_crv(struct pri *pri, q931_call *call, int *callmode);
/* Retrieve CRV reference for GR-303 calls. CRV must be >0, call mode should be 0 */
extern int pri_set_crv(struct pri *pri, q931_call *call, int crv, int callmode);
int pri_set_crv(struct pri *pri, q931_call *call, int crv, int callmode);
/* How long until you need to poll for a new event */
extern struct timeval *pri_schedule_next(struct pri *pri);
struct timeval *pri_schedule_next(struct pri *pri);
/* Run any pending schedule events */
extern pri_event *pri_schedule_run(struct pri *pri);
pri_event *pri_schedule_run(struct pri *pri);
extern int pri_call(struct pri *pri, q931_call *c, int transmode, int channel,
int pri_call(struct pri *pri, q931_call *c, int transmode, int channel,
int exclusive, int nonisdn, char *caller, int callerplan, char *callername, int callerpres,
char *called,int calledplan, int ulayer1);
extern struct pri_sr *pri_sr_new(void);
extern void pri_sr_free(struct pri_sr *sr);
struct pri_sr *pri_sr_new(void);
void pri_sr_free(struct pri_sr *sr);
extern int pri_sr_set_channel(struct pri_sr *sr, int channel, int exclusive, int nonisdn);
extern int pri_sr_set_bearer(struct pri_sr *sr, int transmode, int userl1);
extern int pri_sr_set_called(struct pri_sr *sr, char *called, int calledplan, int complete);
extern int pri_sr_set_caller(struct pri_sr *sr, char *caller, char *callername, int callerplan, int callerpres);
extern int pri_sr_set_redirecting(struct pri_sr *sr, char *num, int plan, int pres, int reason);
int pri_sr_set_channel(struct pri_sr *sr, int channel, int exclusive, int nonisdn);
int pri_sr_set_bearer(struct pri_sr *sr, int transmode, int userl1);
int pri_sr_set_called(struct pri_sr *sr, char *called, int calledplan, int complete);
int pri_sr_set_caller(struct pri_sr *sr, char *caller, char *callername, int callerplan, int callerpres);
int pri_sr_set_redirecting(struct pri_sr *sr, char *num, int plan, int pres, int reason);
#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, const char *userchars);
void pri_sr_set_useruser(struct pri_sr *sr, const char *userchars);
extern void pri_call_set_useruser(q931_call *sr, const char *userchars);
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);
int pri_setup(struct pri *pri, q931_call *call, struct pri_sr *req);
/* Set a call has a call indpendent signalling connection (i.e. no bchan) */
extern int pri_sr_set_connection_call_independent(struct pri_sr *req);
int pri_sr_set_connection_call_independent(struct pri_sr *req);
/* Send an MWI indication to a remote location. If activate is non zero, activates, if zero, decativates */
extern int pri_mwi_activate(struct pri *pri, q931_call *c, char *caller, int callerplan, char *callername, int callerpres, char *called, int calledplan);
int pri_mwi_activate(struct pri *pri, q931_call *c, char *caller, int callerplan, char *callername, int callerpres, char *called, int calledplan);
/* Send an MWI deactivate request to a remote location */
extern int pri_mwi_deactivate(struct pri *pri, q931_call *c, char *caller, int callerplan, char *callername, int callerpres, char *called, int calledplan);
int pri_mwi_deactivate(struct pri *pri, q931_call *c, char *caller, int callerplan, char *callername, int callerpres, char *called, int calledplan);
#define PRI_2BCT
/* Attempt to pass the channels back to the NET side if compatable and
@@ -553,30 +569,30 @@ int pri_channel_bridge(q931_call *call1, q931_call *call2);
/* Override message and error stuff */
#define PRI_NEW_SET_API
extern void pri_set_message(void (*__pri_error)(struct pri *pri, char *));
extern void pri_set_error(void (*__pri_error)(struct pri *pri, char *));
void pri_set_message(void (*__pri_error)(struct pri *pri, char *));
void pri_set_error(void (*__pri_error)(struct pri *pri, char *));
/* Set overlap mode */
#define PRI_SET_OVERLAPDIAL
extern void pri_set_overlapdial(struct pri *pri,int state);
void pri_set_overlapdial(struct pri *pri,int state);
#define PRI_DUMP_INFO_STR
extern char *pri_dump_info_str(struct pri *pri);
char *pri_dump_info_str(struct pri *pri);
/* Get file descriptor */
extern int pri_fd(struct pri *pri);
int pri_fd(struct pri *pri);
#define PRI_PROGRESS
/* Send call proceeding */
extern int pri_progress(struct pri *pri, q931_call *c, int channel, int info);
int pri_progress(struct pri *pri, q931_call *c, int channel, int info);
#define PRI_PROCEEDING_FULL
/* Send call proceeding */
extern int pri_proceeding(struct pri *pri, q931_call *c, int channel, int info);
int pri_proceeding(struct pri *pri, q931_call *c, int channel, int info);
/* Enslave a PRI to another, so they share the same call list
(and maybe some timers) */
extern void pri_enslave(struct pri *master, struct pri *slave);
void pri_enslave(struct pri *master, struct pri *slave);
#define PRI_GR303_SUPPORT
#define PRI_ENSLAVE_SUPPORT
@@ -587,20 +603,20 @@ extern void pri_enslave(struct pri *master, struct pri *slave);
#define PRI_ANI
/* Send notification */
extern int pri_notify(struct pri *pri, q931_call *c, int channel, int info);
int pri_notify(struct pri *pri, q931_call *c, int channel, int info);
/* Get/Set PRI Timers */
#define PRI_GETSET_TIMERS
extern int pri_set_timer(struct pri *pri, int timer, int value);
extern int pri_get_timer(struct pri *pri, int timer);
extern int pri_timer2idx(char *timer);
int pri_set_timer(struct pri *pri, int timer, int value);
int pri_get_timer(struct pri *pri, int timer);
int pri_timer2idx(char *timer);
#define PRI_MAX_TIMERS 32
#define PRI_TIMER_N200 0 /* Maximum numer of q921 retransmissions */
#define PRI_TIMER_N201 1 /* Maximum numer of octets in an information field */
#define PRI_TIMER_N202 2 /* Maximum numer of transmissions of the TEI identity request message */
#define PRI_TIMER_K 3 /* Maximum number of outstanding I-frames */
#define PRI_TIMER_K 3 /* Maximum number of outstanding I-frames */
#define PRI_TIMER_T200 4 /* time between SABME's */
#define PRI_TIMER_T201 5 /* minimum time between retransmissions of the TEI Identity check messages */
@@ -628,4 +644,7 @@ extern int pri_timer2idx(char *timer);
#define PRI_TIMER_T321 26
#define PRI_TIMER_T322 27
#define PRI_TIMER_TM20 28 /* maximum time avaiting XID response */
#define PRI_TIMER_NM20 29 /* number of XID retransmits */
#endif

174
pri.c
View File

@@ -81,7 +81,7 @@ char *pri_switch2str(int sw)
static void pri_default_timers(struct pri *pri, int switchtype)
{
int defaulttimers[20][PRI_MAX_TIMERS] = PRI_TIMERS_ALL;
static const int defaulttimers[20][PRI_MAX_TIMERS] = PRI_TIMERS_ALL;
int x;
for (x = 0; x<PRI_MAX_TIMERS; x++) {
@@ -187,63 +187,71 @@ static int __pri_write(struct pri *pri, void *buf, int buflen)
return res;
}
static struct pri *__pri_new(int fd, int node, int switchtype, struct pri *master, pri_io_cb rd, pri_io_cb wr, void *userdata)
struct pri *__pri_new_tei(int fd, int node, int switchtype, struct pri *master, pri_io_cb rd, pri_io_cb wr, void *userdata, int tei, int bri)
{
struct pri *p;
p = malloc(sizeof(struct pri));
if (p) {
memset(p, 0, sizeof(struct pri));
p->fd = fd;
p->read_func = rd;
p->write_func = wr;
p->userdata = userdata;
p->localtype = node;
p->switchtype = switchtype;
p->cref = 1;
p->sapi = Q921_SAPI_CALL_CTRL;
p->tei = 0;
p->nsf = PRI_NSF_NONE;
p->protodisc = Q931_PROTOCOL_DISCRIMINATOR;
p->master = master;
p->callpool = &p->localpool;
pri_default_timers(p, switchtype);
#ifdef LIBPRI_COUNTERS
p->q921_rxcount = 0;
p->q921_txcount = 0;
p->q931_rxcount = 0;
p->q931_txcount = 0;
#endif
if (switchtype == PRI_SWITCH_GR303_EOC) {
p->protodisc = GR303_PROTOCOL_DISCRIMINATOR;
p->sapi = Q921_SAPI_GR303_EOC;
p->tei = Q921_TEI_GR303_EOC_OPS;
p->subchannel = __pri_new(-1, node, PRI_SWITCH_GR303_EOC_PATH, p, NULL, NULL, NULL);
if (!p->subchannel) {
free(p);
p = NULL;
}
} else if (switchtype == PRI_SWITCH_GR303_TMC) {
p->protodisc = GR303_PROTOCOL_DISCRIMINATOR;
p->sapi = Q921_SAPI_GR303_TMC_CALLPROC;
p->tei = Q921_TEI_GR303_TMC_CALLPROC;
p->subchannel = __pri_new(-1, node, PRI_SWITCH_GR303_TMC_SWITCHING, p, NULL, NULL, NULL);
if (!p->subchannel) {
free(p);
p = NULL;
}
} else if (switchtype == PRI_SWITCH_GR303_TMC_SWITCHING) {
p->protodisc = GR303_PROTOCOL_DISCRIMINATOR;
p->sapi = Q921_SAPI_GR303_TMC_SWITCHING;
p->tei = Q921_TEI_GR303_TMC_SWITCHING;
} else if (switchtype == PRI_SWITCH_GR303_EOC_PATH) {
p->protodisc = GR303_PROTOCOL_DISCRIMINATOR;
p->sapi = Q921_SAPI_GR303_EOC;
p->tei = Q921_TEI_GR303_EOC_PATH;
}
/* Start Q.921 layer, Wait if we're the network */
if (p)
q921_start(p, p->localtype == PRI_CPE);
if (!(p = calloc(1, sizeof(*p))))
return NULL;
p->bri = bri;
p->fd = fd;
p->read_func = rd;
p->write_func = wr;
p->userdata = userdata;
p->localtype = node;
p->switchtype = switchtype;
p->cref = 1;
p->sapi = (tei == Q921_TEI_GROUP) ? Q921_SAPI_LAYER2_MANAGEMENT : Q921_SAPI_CALL_CTRL;
p->tei = tei;
p->nsf = PRI_NSF_NONE;
p->protodisc = Q931_PROTOCOL_DISCRIMINATOR;
p->master = master;
p->callpool = &p->localpool;
p->ev.gen.pri = p;
pri_default_timers(p, switchtype);
if (master) {
pri_set_debug(p, master->debug);
if (master->sendfacility)
pri_facility_enable(p);
}
#ifdef LIBPRI_COUNTERS
p->q921_rxcount = 0;
p->q921_txcount = 0;
p->q931_rxcount = 0;
p->q931_txcount = 0;
#endif
if (switchtype == PRI_SWITCH_GR303_EOC) {
p->protodisc = GR303_PROTOCOL_DISCRIMINATOR;
p->sapi = Q921_SAPI_GR303_EOC;
p->tei = Q921_TEI_GR303_EOC_OPS;
p->subchannel = __pri_new_tei(-1, node, PRI_SWITCH_GR303_EOC_PATH, p, NULL, NULL, NULL, Q921_TEI_GR303_EOC_PATH, 0);
if (!p->subchannel) {
free(p);
p = NULL;
}
} else if (switchtype == PRI_SWITCH_GR303_TMC) {
p->protodisc = GR303_PROTOCOL_DISCRIMINATOR;
p->sapi = Q921_SAPI_GR303_TMC_CALLPROC;
p->tei = Q921_TEI_GR303_TMC_CALLPROC;
p->subchannel = __pri_new_tei(-1, node, PRI_SWITCH_GR303_TMC_SWITCHING, p, NULL, NULL, NULL, Q921_TEI_GR303_TMC_SWITCHING, 0);
if (!p->subchannel) {
free(p);
p = NULL;
}
} else if (switchtype == PRI_SWITCH_GR303_TMC_SWITCHING) {
p->protodisc = GR303_PROTOCOL_DISCRIMINATOR;
p->sapi = Q921_SAPI_GR303_TMC_SWITCHING;
p->tei = Q921_TEI_GR303_TMC_SWITCHING;
} else if (switchtype == PRI_SWITCH_GR303_EOC_PATH) {
p->protodisc = GR303_PROTOCOL_DISCRIMINATOR;
p->sapi = Q921_SAPI_GR303_EOC;
p->tei = Q921_TEI_GR303_EOC_PATH;
}
/* Start Q.921 layer, Wait if we're the network */
if (p)
q921_start(p, p->localtype == PRI_CPE);
return p;
}
@@ -270,7 +278,15 @@ int pri_restart(struct pri *pri)
struct pri *pri_new(int fd, int nodetype, int switchtype)
{
return __pri_new(fd, nodetype, switchtype, NULL, __pri_read, __pri_write, NULL);
return __pri_new_tei(fd, nodetype, switchtype, NULL, __pri_read, __pri_write, NULL, Q921_TEI_PRI, 0);
}
struct pri *pri_new_bri(int fd, int ptpmode, int nodetype, int switchtype)
{
if (ptpmode)
return __pri_new_tei(fd, nodetype, switchtype, NULL, __pri_read, __pri_write, NULL, Q921_TEI_PRI, 1);
else
return __pri_new_tei(fd, nodetype, switchtype, NULL, __pri_read, __pri_write, NULL, Q921_TEI_GROUP, 1);
}
struct pri *pri_new_cb(int fd, int nodetype, int switchtype, pri_io_cb io_read, pri_io_cb io_write, void *userdata)
@@ -279,7 +295,7 @@ struct pri *pri_new_cb(int fd, int nodetype, int switchtype, pri_io_cb io_read,
io_read = __pri_read;
if (!io_write)
io_write = __pri_write;
return __pri_new(fd, nodetype, switchtype, NULL, io_read, io_write, userdata);
return __pri_new_tei(fd, nodetype, switchtype, NULL, io_read, io_write, userdata, Q921_TEI_PRI, 0);
}
void *pri_get_userdata(struct pri *pri)
@@ -529,22 +545,44 @@ int pri_channel_bridge(q931_call *call1, q931_call *call2)
if (!call1 || !call2)
return -1;
/* Make sure we have compatible switchtypes */
if (call1->pri->switchtype != call2->pri->switchtype)
return -1;
/* Check for bearer capability */
if (call1->transcapability != call2->transcapability)
return -1;
/* Check to see if 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 (call1->pri->switchtype == PRI_SWITCH_LUCENT5E)
return eect_initiate_transfer(call1->pri, call1, call2);
if (call1->pri->switchtype == PRI_SWITCH_DMS100)
return rlt_initiate_transfer(call1->pri, call1, call2);
return -1;
switch (call1->pri->switchtype) {
case PRI_SWITCH_NI2:
case PRI_SWITCH_LUCENT5E:
case PRI_SWITCH_ATT4ESS:
if (eect_initiate_transfer(call1->pri, call1, call2))
return -1;
else
return 0;
break;
case PRI_SWITCH_DMS100:
if (rlt_initiate_transfer(call1->pri, call1, call2))
return -1;
else
return 0;
break;
case PRI_SWITCH_QSIG:
call1->bridged_call = call2;
call2->bridged_call = call1;
if (anfpr_initiate_transfer(call1->pri, call1, call2))
return -1;
else
return 0;
break;
default:
return -1;
}
}
int pri_hangup(struct pri *pri, q931_call *call, int cause)
@@ -807,7 +845,7 @@ void pri_enslave(struct pri *master, struct pri *slave)
struct pri_sr *pri_sr_new(void)
{
struct pri_sr *req;
req = malloc(sizeof(struct pri_sr));
req = malloc(sizeof(*req));
if (req)
pri_sr_init(req);
return req;

View File

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

View File

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

View File

@@ -25,6 +25,7 @@
#ifndef _PRI_INTERNAL_H
#define _PRI_INTERNAL_H
#include <stddef.h>
#include <sys/time.h>
#define DBGHEAD __FILE__ ":%d %s: "
@@ -60,6 +61,7 @@ struct pri {
int localtype; /* Local network type (unknown, network, cpe) */
int remotetype; /* Remote network type (unknown, network, cpe) */
int bri;
int sapi;
int tei;
int protodisc;
@@ -83,6 +85,9 @@ struct pri {
/* Various timers */
int sabme_timer; /* SABME retransmit */
int t203_timer; /* Max idle time */
int t202_timer;
int n202_counter;
int ri;
int t200_timer; /* T-200 retransmission timer */
/* All ISDN Timer values */
int timers[MAX_TIMERS];
@@ -246,6 +251,9 @@ struct q931_call {
int transferable;
unsigned int rlt_call_id; /* RLT call id */
/* Bridged call info */
q931_call *bridged_call; /* Pointer to other leg of bridged call */
};
extern int pri_schedule_event(struct pri *pri, int ms, void (*function)(void *data), void *data);
@@ -262,4 +270,6 @@ extern void pri_error(struct pri *pri, char *fmt, ...);
void libpri_copy_string(char *dst, const char *src, size_t size);
struct pri *__pri_new_tei(int fd, int node, int switchtype, struct pri *master, pri_io_cb rd, pri_io_cb wr, void *userdata, int tei, int bri);
#endif

View File

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

View File

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

View File

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

View File

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

283
q921.c
View File

@@ -51,6 +51,7 @@
} while(0)
static void reschedule_t203(struct pri *pri);
static void q921_restart(struct pri *pri, int now);
static void q921_discard_retransmissions(struct pri *pri)
{
@@ -68,8 +69,10 @@ static void q921_discard_retransmissions(struct pri *pri)
static int q921_transmit(struct pri *pri, q921_h *h, int len)
{
int res;
if (pri->master)
return q921_transmit(pri->master, h, len);
while (pri->master)
pri = pri->master;
#ifdef RANDOM_DROPS
if (!(random() % 3)) {
pri_message(pri, " === Dropping Packet ===\n");
@@ -92,6 +95,49 @@ static int q921_transmit(struct pri *pri, q921_h *h, int len)
return 0;
}
static void q921_send_tei(struct pri *pri, int message, int ri, int ai, int isreq)
{
q921_u *f;
if (!(f = calloc(1, sizeof(*f) + 5)))
return;
Q921_INIT(pri, *f);
f->h.c_r = isreq;
f->ft = Q921_FRAMETYPE_U;
f->data[0] = 0x0f; /* Management entity */
f->data[1] = (ri >> 8) & 0xff;
f->data[2] = ri & 0xff;
f->data[3] = message;
f->data[4] = (ai << 1) | 1;
// if (pri->debug & PRI_DEBUG_Q921_STATE)
pri_message(pri, "Sending TEI management message %d, TEI=%d\n", message, ai);
q921_transmit(pri, (q921_h *)f, 8);
free(f);
}
static void q921_tei_request(void *vpri)
{
struct pri *pri = (struct pri *)vpri;
if (pri->subchannel) {
pri_error(pri, "Cannot request TEI while its already assigned\n");
return;
}
pri->n202_counter++;
#if 0
if (pri->n202_counter > pri->timers[PRI_TIMER_N202]) {
pri_error(pri, "Unable to assign TEI from network\n");
return;
}
#endif
pri->ri = random() % 65535;
q921_send_tei(pri, Q921_TEI_IDENTITY_REQUEST, pri->ri, Q921_TEI_GROUP, 1);
if (pri->t202_timer)
pri_schedule_del(pri, pri->t202_timer);
pri->t202_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T202], q921_tei_request, pri);
}
static void q921_send_ua(struct pri *pri, int pfbit)
{
q921_h h;
@@ -388,10 +434,10 @@ static void t200_expire(void *vpri)
int q921_transmit_iframe(struct pri *pri, void *buf, int len, int cr)
{
q921_frame *f, *prev=NULL;
for (f=pri->txqueue; f; f = f->next) prev = f;
f = malloc(sizeof(q921_frame) + len + 2);
f = calloc(1, sizeof(q921_frame) + len + 2);
if (f) {
memset(f,0,sizeof(q921_frame) + len + 2);
Q921_INIT(pri, f->h);
switch(pri->localtype) {
case PRI_NETWORK:
@@ -653,8 +699,10 @@ static pri_event *q921_dchannel_up(struct pri *pri)
q921_reset(pri);
/* Stop any SABME retransmissions */
pri_schedule_del(pri, pri->sabme_timer);
pri->sabme_timer = 0;
if (pri->sabme_timer) {
pri_schedule_del(pri, pri->sabme_timer);
pri->sabme_timer = 0;
}
/* Reset any rejects */
pri->sentrej = 0;
@@ -697,9 +745,12 @@ void q921_reset(struct pri *pri)
pri->v_na = 0;
pri->window = pri->timers[PRI_TIMER_K];
pri->windowlen = 0;
pri_schedule_del(pri, pri->sabme_timer);
pri_schedule_del(pri, pri->t203_timer);
pri_schedule_del(pri, pri->t200_timer);
if (pri->sabme_timer)
pri_schedule_del(pri, pri->sabme_timer);
if (pri->t203_timer)
pri_schedule_del(pri, pri->t203_timer);
if (pri->t200_timer)
pri_schedule_del(pri, pri->t200_timer);
pri->sabme_timer = 0;
pri->t203_timer = 0;
pri->t200_timer = 0;
@@ -715,6 +766,66 @@ void q921_reset(struct pri *pri)
q921_discard_retransmissions(pri);
}
static pri_event *q921_receive_MDL(struct pri *pri, q921_u *h, int len)
{
int ri;
struct pri *sub;
int tei;
pri_message(pri, "Received MDL message\n");
if (h->data[0] != 0x0f) {
pri_error(pri, "Received MDL with unsupported management entity %02x\n", h->data[0]);
return NULL;
}
if (!(h->data[4] & 0x01)) {
pri_error(pri, "Received MDL with multibyte TEI identifier\n");
return NULL;
}
ri = (h->data[1] << 8) | h->data[2];
tei = (h->data[4] >> 1);
switch(h->data[3]) {
case Q921_TEI_IDENTITY_REQUEST:
if (tei != 127) {
pri_error(pri, "Received TEI identity request with invalid TEI %d\n", tei);
q921_send_tei(pri, Q921_TEI_IDENTITY_DENIED, ri, tei, 0);
}
/* Go to master */
for (sub = pri; sub->master; sub = sub->master);
tei = 64;
while(sub->subchannel) {
if(sub->subchannel->tei == tei)
++tei;
}
sub->subchannel = __pri_new_tei(-1, pri->localtype, pri->switchtype, pri, NULL, NULL, NULL, tei, 1);
if (!sub->subchannel) {
pri_error(pri, "Unable to allocate D-channel for new TEI %d\n", tei);
return NULL;
}
q921_send_tei(pri, Q921_TEI_IDENTITY_ASSIGNED, ri, tei, 0);
break;
case Q921_TEI_IDENTITY_ASSIGNED:
if (ri != pri->ri) {
pri_message(pri, "TEI assignment received for invalid Ri %02x (our is %02x)\n", ri, pri->ri);
return NULL;
}
if (pri->t202_timer) {
pri_schedule_del(pri, pri->t202_timer);
pri->t202_timer = 0;
}
if (pri->subchannel) {
pri_error(pri, "TEI already assigned (new is %d, current is %d)\n", tei, pri->subchannel->tei);
}
pri_message(pri, "TEI assiged to %d\n", tei);
pri->subchannel = __pri_new_tei(-1, pri->localtype, pri->switchtype, pri, NULL, NULL, NULL, tei, 1);
if (!pri->subchannel) {
pri_error(pri, "Unable to allocate D-channel for new TEI %d\n", tei);
return NULL;
}
pri->q921_state = Q921_TEI_ASSIGNED;
break;
}
return NULL; /* Do we need to return something??? */
}
static pri_event *__q921_receive_qualified(struct pri *pri, q921_h *h, int len)
{
q921_frame *f;
@@ -765,59 +876,59 @@ static pri_event *__q921_receive_qualified(struct pri *pri, q921_h *h, int len)
pri->solicitfbit = 0;
}
break;
case 1:
/* Receiver not ready */
if (pri->debug & PRI_DEBUG_Q921_DUMP)
pri_message(pri, "-- Got receiver not ready\n");
if(h->s.p_f) {
/* Send RR if poll bit set */
q921_rr(pri, h->s.p_f, 0);
}
pri->busy = 1;
break;
case 2:
/* Just retransmit */
if (pri->debug & PRI_DEBUG_Q921_DUMP)
pri_message(pri, "-- Got reject requesting packet %d... Retransmitting.\n", h->s.n_r);
if (h->s.p_f) {
/* If it has the poll bit set, send an appropriate supervisory response */
q921_rr(pri, 1, 0);
}
sendnow = 0;
/* Resend the proper I-frame */
for(f=pri->txqueue;f;f=f->next) {
if ((sendnow || (f->h.n_s == h->s.n_r)) && f->transmitted) {
/* Matches the request, or follows in our window, and has
already been transmitted. */
sendnow = 1;
pri_error(pri, "!! Got reject for frame %d, retransmitting frame %d now, updating n_r!\n", h->s.n_r, f->h.n_s);
f->h.n_r = pri->v_r;
q921_transmit(pri, (q921_h *)(&f->h), f->len);
}
}
if (!sendnow) {
if (pri->txqueue) {
/* This should never happen */
if (!h->s.p_f || h->s.n_r) {
pri_error(pri, "!! Got reject for frame %d, but we only have others!\n", h->s.n_r);
}
} else {
/* Hrm, we have nothing to send, but have been REJ'd. Reset v_a, v_s, etc */
pri_error(pri, "!! Got reject for frame %d, but we have nothing -- resetting!\n", h->s.n_r);
pri->v_a = h->s.n_r;
pri->v_s = h->s.n_r;
/* Reset t200 timer if it was somehow going */
if (pri->t200_timer) {
pri_schedule_del(pri, pri->t200_timer);
pri->t200_timer = 0;
}
/* Reset and restart t203 timer */
if (pri->t203_timer)
pri_schedule_del(pri, pri->t203_timer);
pri->t203_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T203], t203_expire, pri);
}
}
break;
case 1:
/* Receiver not ready */
if (pri->debug & PRI_DEBUG_Q921_STATE)
pri_message(pri, "-- Got receiver not ready\n");
if(h->s.p_f) {
/* Send RR if poll bit set */
q921_rr(pri, h->s.p_f, 0);
}
pri->busy = 1;
break;
case 2:
/* Just retransmit */
if (pri->debug & PRI_DEBUG_Q921_STATE)
pri_message(pri, "-- Got reject requesting packet %d... Retransmitting.\n", h->s.n_r);
if (h->s.p_f) {
/* If it has the poll bit set, send an appropriate supervisory response */
q921_rr(pri, 1, 0);
}
sendnow = 0;
/* Resend the proper I-frame */
for(f=pri->txqueue;f;f=f->next) {
if ((sendnow || (f->h.n_s == h->s.n_r)) && f->transmitted) {
/* Matches the request, or follows in our window, and has
already been transmitted. */
sendnow = 1;
pri_error(pri, "!! Got reject for frame %d, retransmitting frame %d now, updating n_r!\n", h->s.n_r, f->h.n_s);
f->h.n_r = pri->v_r;
q921_transmit(pri, (q921_h *)(&f->h), f->len);
}
}
if (!sendnow) {
if (pri->txqueue) {
/* This should never happen */
if (!h->s.p_f || h->s.n_r) {
pri_error(pri, "!! Got reject for frame %d, but we only have others!\n", h->s.n_r);
}
} else {
/* Hrm, we have nothing to send, but have been REJ'd. Reset v_a, v_s, etc */
pri_error(pri, "!! Got reject for frame %d, but we have nothing -- resetting!\n", h->s.n_r);
pri->v_a = h->s.n_r;
pri->v_s = h->s.n_r;
/* Reset t200 timer if it was somehow going */
if (pri->t200_timer) {
pri_schedule_del(pri, pri->t200_timer);
pri->t200_timer = 0;
}
/* Reset and restart t203 timer */
if (pri->t203_timer)
pri_schedule_del(pri, pri->t203_timer);
pri->t203_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T203], t203_expire, pri);
}
}
break;
default:
pri_error(pri, "!! XXX Unknown Supervisory frame ss=0x%02x,pf=%02xnr=%02x vs=%02x, va=%02x XXX\n", h->s.ss, h->s.p_f, h->s.n_r,
pri->v_s, pri->v_a);
@@ -838,7 +949,7 @@ static pri_event *__q921_receive_qualified(struct pri *pri, q921_h *h, int len)
pri_message(pri, "-- Got DM Mode from peer.\n");
/* Disconnected mode, try again after T200 */
ev = q921_dchannel_down(pri);
q921_start(pri, 0);
q921_restart(pri, 0);
return ev;
} else {
@@ -846,12 +957,23 @@ static pri_event *__q921_receive_qualified(struct pri *pri, q921_h *h, int len)
pri_message(pri, "-- Ignoring unsolicited DM with p/f set to 0\n");
#if 0
/* Requesting that we start */
q921_start(pri, 0);
q921_restart(pri, 0);
#endif
}
break;
} else if (!h->u.m2) {
pri_message(pri, "XXX Unnumbered Information not implemented XXX\n");
if ((pri->sapi == Q921_SAPI_LAYER2_MANAGEMENT) && (pri->tei == Q921_TEI_GROUP))
q921_receive_MDL(pri, (q921_u *)h, len);
else {
int res;
res = q931_receive(pri, (q931_h *) h->u.data, len - 3);
if (res == -1) {
return NULL;
}
if (res & Q931_RES_HAVEEVENT)
return &pri->ev;
}
}
break;
case 2:
@@ -860,7 +982,7 @@ static pri_event *__q921_receive_qualified(struct pri *pri, q921_h *h, int len)
/* Acknowledge */
q921_send_ua(pri, h->u.p_f);
ev = q921_dchannel_down(pri);
q921_start(pri, 0);
q921_restart(pri, 0);
return ev;
case 3:
if (h->u.m2 == 3) {
@@ -924,21 +1046,26 @@ static pri_event *__q921_receive(struct pri *pri, q921_h *h, int len)
if (h->h.ea1 || !(h->h.ea2))
return NULL;
#if 0 /* Will be rejected by subchannel analyzis */
/* Check for broadcasts - not yet handled */
if (h->h.tei == Q921_TEI_GROUP)
return NULL;
#endif
/* Check for SAPIs we don't yet handle */
if ((h->h.sapi != pri->sapi) || (h->h.tei != pri->tei)) {
#ifdef PROCESS_SUBCHANNELS
if (!((h->h.sapi == pri->sapi) && ((h->h.tei == pri->tei) || (h->h.tei == Q921_TEI_GROUP)))) {
/* Check for SAPIs we don't yet handle */
/* If it's not us, try any subchannels we have */
if (pri->subchannel)
return q921_receive(pri->subchannel, h, len + 2);
else
#endif
{
pri_error(pri, "Message for SAPI/TEI=%d/%d IS NOT HANDLED\n", h->h.sapi, h->h.tei);
return NULL;
}
}
if (pri->debug & PRI_DEBUG_Q921_DUMP)
pri_message(pri, "Handling message for SAPI/TEI=%d/%d\n", h->h.sapi, h->h.tei);
ev = __q921_receive_qualified(pri, h, len);
reschedule_t203(pri);
return ev;
@@ -954,7 +1081,7 @@ pri_event *q921_receive(struct pri *pri, q921_h *h, int len)
return e;
}
void q921_start(struct pri *pri, int now)
static void q921_restart(struct pri *pri, int now)
{
if (pri->q921_state != Q921_LINK_CONNECTION_RELEASED) {
pri_error(pri, "!! q921_start: Not in 'Link Connection Released' state\n");
@@ -965,3 +1092,17 @@ void q921_start(struct pri *pri, int now)
/* Do the SABME XXX Maybe we should implement T_WAIT? XXX */
q921_send_sabme(pri, now);
}
void q921_start(struct pri *pri, int isCPE)
{
q921_reset(pri);
if ((pri->sapi == Q921_SAPI_LAYER2_MANAGEMENT) && (pri->tei == Q921_TEI_GROUP)) {
pri_message(pri, "Starting in BRI mode\n");
pri->q921_state = Q921_DOWN;
if (isCPE)
q921_tei_request(pri);
} else {
pri_message(pri, "Starting in PRI mode, isCPE=%d, SAPI/TEI=%d/%d\n", isCPE, pri->sapi, pri->tei);
q921_send_sabme(pri, isCPE);
}
}

199
q931.c
View File

@@ -255,18 +255,10 @@ static char *code2str(int code, struct msgtype *codes, int max)
static void call_init(struct q931_call *c)
{
memset(c, 0, sizeof(*c));
c->alive = 0;
c->sendhangupack = 0;
c->forceinvert = -1;
c->cr = -1;
c->slotmap = -1;
c->channelno = -1;
c->ds1no = 0;
c->ds1explicit = 0;
c->chanflags = 0;
c->next = NULL;
c->sentchannel = 0;
c->newcall = 1;
c->ourcallstate = Q931_CALL_STATE_NULL;
c->peercallstate = Q931_CALL_STATE_NULL;
@@ -294,15 +286,22 @@ static FUNC_RECV(receive_channel_id)
}
#endif
#ifndef NOAUTO_CHANNEL_SELECTION_SUPPORT
switch (ie->data[0] & 3) {
case 0:
if (pri->bri) {
if (!(ie->data[0] & 3))
call->justsignalling = 1;
break;
case 1:
break;
default:
pri_error(pri, "!! Unexpected Channel selection %d\n", ie->data[0] & 3);
return -1;
else
call->channelno = ie->data[0] & 3;
} else {
switch (ie->data[0] & 3) {
case 0:
call->justsignalling = 1;
break;
case 1:
break;
default:
pri_error(pri, "!! Unexpected Channel selection %d\n", ie->data[0] & 3);
return -1;
}
}
#endif
if (ie->data[0] & 0x08)
@@ -366,7 +365,11 @@ static FUNC_SEND(transmit_channel_id)
/* Start with standard stuff */
if (pri->switchtype == PRI_SWITCH_GR303_TMC)
ie->data[pos] = 0x69;
else
else if (pri->bri) {
ie->data[pos] = 0x80;
if (call->channelno > -1)
ie->data[pos] |= (call->channelno & 0x3);
} else
ie->data[pos] = 0xa1;
/* Add exclusive flag if necessary */
if (call->chanflags & FLAG_EXCLUSIVE)
@@ -383,6 +386,10 @@ static FUNC_SEND(transmit_channel_id)
ie->data[pos++] = 0x80 | call->ds1no;
} else
pos++;
if (pri->bri)
return pos + 2;
if ((call->channelno > -1) || (call->slotmap != -1)) {
/* We'll have the octet 8.2 and 8.3's present */
ie->data[pos++] = 0x83;
@@ -548,7 +555,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" },
@@ -591,8 +598,9 @@ static FUNC_DUMP(dump_bearer_capability)
pos++;
}
/* Stop here if no more */
if (pos >= len)
if (pos >= len - 2)
return;
if ((ie->data[1] & 0x7f) != TRANS_MODE_PACKET) {
/* Look for octets 5 and 5.a if present */
pri_message(pri, "%c Ext: %d User information layer 1: %s (%d)\n", prefix, (ie->data[pos] >> 7), l12str(ie->data[pos] & 0x7f), ie->data[pos] & 0x7f);
@@ -619,6 +627,10 @@ static FUNC_RECV(receive_bearer_capability)
call->transmoderate = ie->data[1] & 0x7f;
if (call->transmoderate == PRI_TRANS_CAP_AUDIO_4ESS)
call->transmoderate = PRI_TRANS_CAP_3_1K_AUDIO;
if (pos >= len - 2)
return 0;
if (call->transmoderate != TRANS_MODE_PACKET) {
call->userl1 = ie->data[pos] & 0x7f;
if (call->userl1 == PRI_LAYER_1_ITU_RATE_ADAPT) {
@@ -642,7 +654,7 @@ static FUNC_SEND(transmit_bearer_capability)
return 0;
tc = call->transcapability;
if (pri->subchannel) {
if (pri->subchannel && !pri->bri) {
/* Bearer capability is *hard coded* in GR-303 */
ie->data[0] = 0x88;
ie->data[1] = 0x90;
@@ -662,7 +674,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;
}
@@ -1174,7 +1187,7 @@ static FUNC_RECV(receive_facility)
state = my_state; \
if (pri->debug) \
pri_message(pri, "Handle Q.932 %s component\n", name); \
(handler)(pri, call, comp->data, comp->len); \
(handler)(pri, call, ie, comp->data, comp->len); \
break;
#define Q932_HANDLE_NULL(component, my_state, name, handle) \
case component: \
@@ -1269,7 +1282,7 @@ static FUNC_SEND(transmit_progress_indicator)
{
int code, mask;
/* Can't send progress indicator on GR-303 -- EVER! */
if (pri->subchannel)
if (pri->subchannel && !pri->bri)
return 0;
if (call->progressmask > 0) {
if (call->progressmask & (mask = PRI_PROG_CALL_NOT_E2E_ISDN))
@@ -2161,10 +2174,15 @@ static inline void q931_dumpie(struct pri *pri, int codeset, q931_ie *ie, char p
pri_error(pri, "!! %c Unknown IE %d (cs%d, len = %d)\n", prefix, Q931_IE_IE(base_ie), Q931_IE_CODESET(base_ie), ielen(ie));
}
static q931_call *q931_getcall(struct pri *pri, int cr)
static q931_call *q931_getcall(struct pri *pri, int cr, int outboundnew)
{
q931_call *cur, *prev;
cur = *pri->callpool;
struct pri *master;
/* Find the master - He has the call pool */
for (master = pri; master->master; master = master->master);
cur = *master->callpool;
prev = NULL;
while(cur) {
if (cur->cr == cr)
@@ -2175,41 +2193,59 @@ static q931_call *q931_getcall(struct pri *pri, int cr)
/* No call exists, make a new one */
if (pri->debug & PRI_DEBUG_Q931_STATE)
pri_message(pri, "-- Making new call for cr %d\n", cr);
cur = malloc(sizeof(struct q931_call));
if (cur) {
call_init(cur);
/* Call reference */
cur->cr = cr;
if (!(cur = calloc(1, sizeof(*cur))))
return NULL;
call_init(cur);
/* Call reference */
cur->cr = cr;
/* PRI is set to whoever called us */
if (pri->bri && (pri->localtype == PRI_CPE) && pri->subchannel && outboundnew)
cur->pri = pri->subchannel;
else
cur->pri = pri;
/* Append to end of list */
if (prev)
prev->next = cur;
else
*pri->callpool = cur;
}
/* Append to end of list */
if (prev)
prev->next = cur;
else
*master->callpool = cur;
return cur;
}
q931_call *q931_new_call(struct pri *pri)
{
q931_call *cur;
do {
cur = *pri->callpool;
pri->cref++;
if (pri->cref > 32767)
pri->cref = 1;
if (!pri->bri) {
if (pri->cref > 32767)
pri->cref = 1;
} else {
if (pri->cref > 127)
pri->cref = 1;
}
while(cur) {
if (cur->cr == (0x8000 | pri->cref))
break;
cur = cur->next;
}
} while(cur);
return q931_getcall(pri, pri->cref | 0x8000);
return q931_getcall(pri, pri->cref | 0x8000, 1);
}
static void q931_destroy(struct pri *pri, int cr, q931_call *c)
{
q931_call *cur, *prev;
/* For destroying, make sure we are using the master span, since it maintains the call pool */
for (;pri->master; pri = pri->master);
prev = NULL;
cur = *pri->callpool;
while(cur) {
@@ -2374,26 +2410,40 @@ static void init_header(struct pri *pri, q931_call *call, unsigned char *buf, q9
{
/* Returns header and message header and modifies length in place */
q931_h *h = (q931_h *)buf;
q931_mh * mh = (q931_mh *)(h->contents + 2);
q931_mh * mh;
h->pd = pri->protodisc;
h->x0 = 0; /* Reserved 0 */
h->crlen = 2; /* Two bytes of Call Reference. Invert the top bit to make it from our sense */
if (call->cr || call->forceinvert) {
h->crv[0] = ((call->cr ^ 0x8000) & 0xff00) >> 8;
h->crv[1] = (call->cr & 0xff);
if (!pri->bri) {
h->crlen = 2; /* Two bytes of Call Reference. Invert the top bit to make it from our sense */
if (call->cr || call->forceinvert) {
h->crv[0] = ((call->cr ^ 0x8000) & 0xff00) >> 8;
h->crv[1] = (call->cr & 0xff);
} else {
/* Unless of course this has no call reference */
h->crv[0] = 0;
h->crv[1] = 0;
}
if (pri->subchannel && !pri->bri) {
/* On GR-303, top bit is always 0 */
h->crv[0] &= 0x7f;
}
} else {
/* Unless of course this has no call reference */
h->crv[0] = 0;
h->crv[1] = 0;
}
if (pri->subchannel) {
/* On GR-303, top bit is always 0 */
h->crv[0] &= 0x7f;
h->crlen = 1;
if (call->cr || call->forceinvert) {
h->crv[0] = (((call->cr ^ 0x8000) & 0x8000) >> 8) | (call->cr & 0x7f);
} else {
/* Unless of course this has no call reference */
h->crv[0] = 0;
}
}
mh = (q931_mh *)(h->contents + h->crlen);
mh->f = 0;
*hb = h;
*mhb = mh;
*len -= 5;
if (h->crlen == 2)
*len -= 5;
else
*len -= 4;
}
@@ -2442,7 +2492,7 @@ static int send_message(struct pri *pri, q931_call *c, int msgtype, int ies[])
}
/* Invert the logic */
len = sizeof(buf) - len;
q931_xmit(pri, h, len, 1);
q931_xmit(c->pri, h, len, 1);
c->acked = 1;
return 0;
}
@@ -2625,6 +2675,7 @@ int q931_setup_ack(struct pri *pri, q931_call *c, int channel, int nonisdn)
return send_message(pri, c, Q931_SETUP_ACKNOWLEDGE, connect_ies);
}
/* T313 expiry, first time */
static void pri_connect_timeout(void *data)
{
struct q931_call *c = data;
@@ -2635,6 +2686,7 @@ static void pri_connect_timeout(void *data)
}
/* T308 expiry, first time */
static void pri_release_timeout(void *data)
{
struct q931_call *c = data;
@@ -2643,9 +2695,12 @@ static void pri_release_timeout(void *data)
pri_message(pri, "Timed out looking for release complete\n");
c->t308_timedout++;
c->alive = 1;
q931_release(pri, c, PRI_CAUSE_NORMAL_CLEARING);
/* The call to q931_release will re-schedule T308 */
q931_release(pri, c, c->cause);
}
/* T308 expiry, second time */
static void pri_release_finaltimeout(void *data)
{
struct q931_call *c = data;
@@ -2667,6 +2722,7 @@ static void pri_release_finaltimeout(void *data)
q931_hangup(pri, c, c->cause);
}
/* T305 expiry, first time */
static void pri_disconnect_timeout(void *data)
{
struct q931_call *c = data;
@@ -2703,7 +2759,7 @@ int q931_connect(struct pri *pri, q931_call *c, int channel, int nonisdn)
if (c->retranstimer)
pri_schedule_del(pri, c->retranstimer);
c->retranstimer = 0;
if ((c->ourcallstate == Q931_CALL_STATE_CONNECT_REQUEST) && (!pri->subchannel))
if ((c->ourcallstate == Q931_CALL_STATE_CONNECT_REQUEST) && (pri->bri || (!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);
}
@@ -2739,7 +2795,7 @@ static int restart_ies[] = { Q931_CHANNEL_IDENT, Q931_RESTART_INDICATOR, -1 };
int q931_restart(struct pri *pri, int channel)
{
struct q931_call *c;
c = q931_getcall(pri, 0 | 0x8000);
c = q931_getcall(pri, 0 | 0x8000, 0);
if (!c)
return -1;
if (!channel)
@@ -2776,8 +2832,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 };
@@ -2796,7 +2853,7 @@ int q931_setup(struct pri *pri, q931_call *c, struct pri_sr *req)
c->ds1no = (req->channel & 0xff00) >> 8;
c->ds1explicit = (req->channel & 0x10000) >> 16;
req->channel &= 0xff;
if ((pri->localtype == PRI_CPE) && pri->subchannel) {
if ((pri->localtype == PRI_CPE) && pri->subchannel && !pri->bri) {
req->channel = 0;
req->exclusive = 0;
}
@@ -2866,7 +2923,7 @@ int q931_setup(struct pri *pri, q931_call *c, struct pri_sr *req)
pri_call_add_standard_apdus(pri, c);
if (pri->subchannel)
if (pri->subchannel && !pri->bri)
res = send_message(pri, c, Q931_SETUP, gr303_setup_ies);
else if (c->justsignalling)
res = send_message(pri, c, Q931_SETUP, cis_setup_ies);
@@ -2910,7 +2967,7 @@ static int gr303_connect_acknowledge_ies[] = { Q931_CHANNEL_IDENT, -1 };
static int q931_connect_acknowledge(struct pri *pri, q931_call *c)
{
if (pri->subchannel) {
if (pri->subchannel && !pri->bri) {
if (pri->localtype == PRI_CPE)
return send_message(pri, c, Q931_CONNECT_ACKNOWLEDGE, gr303_connect_acknowledge_ies);
} else
@@ -2963,8 +3020,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 */
@@ -2978,6 +3033,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);
@@ -3042,7 +3101,7 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
pri_error(pri, "Warning: unknown/inappropriate protocol discriminator received (%02x/%d)\n", h->pd, h->pd);
return 0;
}
c = q931_getcall(pri, q931_cr(h));
c = q931_getcall(pri, q931_cr(h), 0);
if (!c) {
pri_error(pri, "Unable to locate call %d\n", q931_cr(h));
return -1;
@@ -3346,6 +3405,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) {
@@ -3381,6 +3450,8 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
libpri_copy_string(pri->ev.facname.callingname, c->callername, sizeof(pri->ev.facname.callingname));
libpri_copy_string(pri->ev.facname.callingnum, c->callernum, sizeof(pri->ev.facname.callingnum));
pri->ev.facname.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
pri->ev.facname.callingpres = c->callerpres;
pri->ev.facname.callingplan = c->callerplan;
pri->ev.facname.cref = c->cr;
pri->ev.facname.call = c;
#if 0

View File

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