📄 readme.txt
字号:
+-----------------------------------------------------------------------------+
| ISDN and ISDNEXT sample documentation |
| Copyright (c) 2002-2006 by TelcoBridges inc. |
+-----------------------------------------------------------------------------+
-------------------------------------------------------------------------------
- 1 - TABLE OF CONTENT
-------------------------------------------------------------------------------
1 TABLE OF CONTENT
2 Introduction and overview of the sample
3 Design overview
3.1 Files organization
3.2 Memory structures organization
3.3 Threads usage
3.4 First configuration and HA resynchronization
3.5 Events, responses and call handling
4 Configuration file
-------------------------------------------------------------------------------
- 2 - Introduction and overview of the sample
-------------------------------------------------------------------------------
The ISDN and ISDNEXT applications are used to allocate and control ISDN
protocol stacks onto TB640 blade(s). As this application implements the
full functionnalities required to handle ISDN incoming and outgoing calls, it
is more considered a tool than a plain didactic sample. In a typical sample,
APIs messages to handle ISDN stack sand calls would be shown in a sequential
manner in order to really show the proper sequence. In this case, this
application is designed to achieve the full performance of the TB640 and,
thus, is required to follow an asynchronous call handling architecture rather
than sequential and may not be as 'simple' to follow as a regular 'sample'.
This application is instructed to take control of up to two blades'
resources (ISDN, trunks and optionally CT-Bus) specified by a configuration file.
It is possible for multiple instance of this application to act onto the same
blade as long as ISDN and trunk configurations are not conflicting and that the
Ct-bus resources are not used. Otherwise, strange behavior might occurs (such
as dropped calls, notifications received twice, etc.).
This application is divided in 4 major sections: configuration, HA
handling, calls handling and CLI (or user-interface). Each of these individual
application parts is described in more detail in the following section.
-------------------------------------------------------------------------------
- 3 - Design overview
-------------------------------------------------------------------------------
+-------------------------+
- 3.1 - Files organization
+-------------------------+
This sample functionnalities are divided amongst differents files according
to their categories.
isdn.c
It is the main entry point of the application. Within this file are
the calls to parse the configuration file, initiate the
resynchronization of resources and start the CLI interface.
cli.c
This file contains the necessary code to handle the user-interface and
the different user commands to act upon the ISDN stacks (i.e. make
calls, drop calls, start stress-tests). It is also responsible to
the timeslots/calls monitoring screen that displays the state of every
ISDN calls in real-time.
parse.c
This file contains the functions to parse the configuration file,
validate the syntax of each section and to populated local memory
strutures with the expected configuration parameters.
config.c
This file contains the functions responsible to allocate resources onto
blade(s) [trunks, trunk resources, Ctbus resources and stacks]. Note
that these functions don't handle HA (or re-sync). They are designed
to allocate resources that are non-existing on a blade. The resource
configuration is taken from local memory structure that were filled
from the configuration file (from the file parse.c).
ha.c
This file contains the functions responsible to query blades' current
allocated resources, compared them with the expected configured
resources (i.e. from local memory structures), notify the user from
configuration conflict and, finally, to invoke resource allocation
functions (from config.c) for missing resources.
tbxasync.c (from the ../../common/src directory)
This file contains helper functions to create 'call contexts' and
match any incoming notifications and responses to the appropriate call
context. This allows the rest of the application's state machines
to be implemented on a 'per-call' basis. This basically means that
every active or pending calls is assigned a contexts which keeps track
of the current call state and variables (i.e. called number, calling
numbers, state flags, etc). The call state machine can be invoked
multiple time in parallel each time acting on different call contexts.
states.c
This file contains the implementation of the ISDN call state machine.
This state machine can be applied to different call contexts in
parallel, thus allowing the best performance in overall system call
handling.
isdn.h
This header file contains the complete memory structure definitions.
macros.h
This header file contains different macro implementations to ease
the general code reading.
prototypes.h
This header file contains the different function prototype definitions.
+--------------------------------------+
- 3.2 - Memory structures organization
+--------------------------------------+
This section describes the local memory structures that are populated
from the configuration file and then updated with run-time information (such
as the resource handles, states, etc).
+ TB640_ISDN_CONTEXT
|
| . Tbx library handle
| . Different application global configuration and flags
|
+---+ TB640_ISDN_ADAPTER_INFO [2]
|
| . Adapter global information (name, handles, etc)
| . Hash tables for resource (stacks, trunks and Ct-bus) handles
| matching with memory structures
| . Async library information (one lib can control from 1-64 trunks.
| Usually 1 library controls 64 trunks -> 1 thread/filter per
| 64 trunks).
|
+---+ TB640_ISDN_TRUNK_INFO [64]
|
| . Assiged stack handle information
| . Configuration options global to the stack/trunk
|
+---+ TB640_ISDN_CFG
| + . stack configuration parameters
|
+---+ TB640_ISDN_TRUNK_RESOURCE_INFO [32]
|
| . Trunk resource handle
| . State informations of the timeslot
| . Call handle currently pending/active on the timeslot
|
+---+ TB640_ISDN_TRUNK_RESOURCE_STATS
| . Statistics of a trunk resource/timeslot
|
+---+ TB640_ISDN_CTBUS_INFO
| . Information about a linked Ctbus resource (if any)
|
+---+ TB640_ISDN_HISTORY_ENTRY [up to 256]
. Call state history for the trunk resource/timeslot
+---------------------+
- 3.3 - Threads usage
+---------------------+
Within the application, a certain number of threads are used to accomplish the
overall processing. Basically, they fall into two different categories: main/CLI
and calls handling.
Entry point
|
+-----------------------+ +--------------------------+ +--------+
| Main/CLI | | Async. lib #1 | | Async. |
| | | | | lib |
| - Parse cfg files | | - controls from 1 to 64 | | #x |
| - Open TBX library | | trunks of 1 adapter | | |
| - Spawn other threads |-- spawns --> | - Receives events for | | |
| with async. library | 1 to x | controlled stks/trunks | ... | |
| - Enter the CLI loop | async lib. | only | | idem |
| for display and user| | - Invoke call state | | |
| commands | | machine for every rsp/ | | |
| - Frees up resources | | notif received for | | |
| upon app. exit | | every call context | | |
+-----------------------+ | - May call the HA resync | +--------+
| process (res. query, |
| res. alloc) if adapter |
| goes down or up. |
+--------------------------+
Except for the main/CLI thread, all others are event driven and contain no
synchronous calls that could lock them for an extended period of time. Thus,
only a global mutex is required for the overall threads within the application
to access (read or write) the local memory structures described in an earlier
section of this document.
Although the number of threads (a.k.a async. libs per adapter) is
configurable through the #define TB640_ISDN_MAX_TRUNK_PER_OPERATION_LIBRARY,
it is currently set as a single async. lib thread/filter will control the
whole 64 trunks of a blade. As mentioned before, since every processing is
event driven and non-blocking, no gain would be added by using multiple threads
in the call handling. On the other hand, it would have been possible to
control all adapters/blades using a single async lib/filter but this approach
would be limitative since a single filter can only contain a certain number
of filter conditions (i.e. the number of adapter/blade would be limited by
this anyway). Because of this reason, a minimum of one async. lib/filter is
used per adaper/blade.
+----------------------------------------------------+
- 3.4 - First configuration and HA resynchronization
+----------------------------------------------------+
The first resource configuration and HA resynchronization is actually the
same processing done in different conditions. When the main thread starts,
the state of controlled adapter is unknown (i.e. no clue about what is
allocated vs what is not). Before starting the resynchronization process, we
need to wait until we see the event TBX_MSG_ID_API_NOTIF_ADAPTER_ADDED (in file
states.c). Once this event is received, the application needs to go query
the targeted adapter to see what resources are already allocated (because it
cannot distinguish between a 'link failure recovery' and a 'fresh blade
reboot'. Since this event is received by all 'async lib' thread connected
to the adapter, the application actually stops (through the use of a mutex)
all async lib. threads linked to that adapter until only one active remains.
That last active threads will call the resource query functions (in file ha.c),
compare with the expected configuration (from the local memory structures) and
allocated missing resources (trunks, trunk res., stacks). Once the allocation
process is done, all async. libs are restarted (mutex is freed) and event
processing can continuer.
In summary, the only difference between a live HA resynchronization and the
very first resource allocation is that the original configuration is done upon
the reception of a 'simulated' TBX_MSG_ID_API_NOTIF_ADAPTER_ADDED. Indeed, since
upon startup, the application makes sure that the adapter(s) is/are available
to control, no 'real' TBX_MSG_ID_API_NOTIF_ADAPTER_ADDED is received (the
adapter is already up after the TBX library is opened). Thus, the main thread
(in function TB640IsdnConfigureSystem() from file config.c) sends a simulated
event to the async lib. threads to trigger the re-sync process.
On the other hand, the adapter uninitialization (i.e. when the adapter dies
or when the link is broken) is done using the same processing as described
above. The uninitialization processing consists in cleaning the local
memory structures of all dynamic resource information (mostly resource handles).
+-------------------------------------------+
- 3.5 - Events, responses and call handling
+-------------------------------------------+
In order to be able to process multiple calls in parallel, the application
needs to keep track of the current state of each individual call into a
memory structure called a 'call context' (i.e. structure named
TB640_ISDN_CALL_CONTEXT located in isdn.h). Every call context will evoluate
from one state to the other (e.g. from 'waiting for ISDN CONN_ACK' state to
'ACTIVE' state) when receiving notifications. Timeouts and CLi user commands
(such as 'MakeCall') are also under the form of notifications.
Asynchronous event processing is the base of ISDN call handling. Typically
all notifications are captured by the TBX filter owned by the async. lib
process. Once an event is received, the async. lib tries to find if it
relates to an already existing call. If so, the call context pointer is
retrieved and passed to a user-function (i.e. TB640IsdnEventMessageHandler(),
TB640IsdnResponseMessageHandler() from file states.c) depending on the type
of notification received (notif. or response).
Events and responses that are linked to a call context (i.e. relates to
a calls) are forwared to the function TB640IsdnProcessStateChange() (from file
states.c). This function is actually a big switch-case that calls the
appropriate state function based on the current state of the call context.
As specified in the file isdnstates.pdf, the ISDN call processing is divided
in a series of states which are responsible to do actions based on input
notifications and responses. These state functions (TB640IsdnProcessStateIdle,
TB640IsdnProcessState1, TB640IsdnProcessState2, etc) corresponds to the
implementation of each of those states. They are called with the call context
and the received notification/response as arguments and can trigger some
actions for the targeted calls (i.e. send request(s) to the blade, change
call state, etc).
To ease the reading of a state handling, nested switch-cases have been
hidden using macros. Those macros actually only hide the repeating code of
having to do a first switch-case onto the current state of the call and then
another switch-case onto the received event message ID. The macros also
hides the initialization of pointers toward contexts such as the current
concerned trunk structure, trunk res. structure, call context, etc.
Example of such state processing function:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -