dect
/
asterisk
Archived
13
0
Fork 0

Merged revisions 294740 via svnmerge from

https://origsvn.digium.com/svn/asterisk/branches/1.8

........
  r294740 | russell | 2010-11-11 16:13:38 -0600 (Thu, 11 Nov 2010) | 11 lines
  
  Remove most of the contents of the doc dir in favor of the wiki content.
  
  This merge does the following things:
  
   * Removes most of the contents from the doc/ directory in favor
     of the wiki - http://wiki.asterisk.org/
  
   * Updates the build_tools/prep_tarball script to know how to export
     the contents of the wiki in both PDF and plain text formats so that
     the documentation is still included in Asterisk release tarballs.
........


git-svn-id: http://svn.digium.com/svn/asterisk/trunk@294741 f38db490-d61c-443f-a65b-d21fe96a405b
This commit is contained in:
russell 2010-11-11 22:14:25 +00:00
parent caf86b83a5
commit 01242060d2
94 changed files with 15 additions and 20765 deletions

View File

@ -922,14 +922,6 @@ menuselect-tree: $(foreach dir,$(filter-out main,$(MOD_SUBDIRS)),$(wildcard $(di
@cat sounds/sounds.xml >> $@
@echo "</menu>" >> $@
pdf: asterisk.pdf
asterisk.pdf:
$(MAKE) -C doc/tex asterisk.pdf
txt: asterisk.txt
asterisk.txt:
$(MAKE) -C doc/tex asterisk.txt
.PHONY: menuselect
.PHONY: main
.PHONY: sounds
@ -942,7 +934,6 @@ asterisk.txt:
.PHONY: uninstall
.PHONY: _uninstall
.PHONY: uninstall-all
.PHONY: pdf
.PHONY: dont-optimize
.PHONY: badshell
.PHONY: installdirs

View File

@ -8,18 +8,8 @@
make -C sounds MENUSELECT_CORE_SOUNDS=CORE-SOUNDS-EN-GSM MENUSELECT_MOH=MOH-OPSOUND-WAV WGET=wget DOWNLOAD=wget all
make AWK=awk GREP=grep menuselect-tree
make_tex_docs() {
# make backup of asterisk.tex because we are going to alter it
cp asterisk.tex asterisk.tex.orig
sed -e "s/ASTERISKVERSION/${VERSION}/" asterisk.tex > asterisk_local.tex
mv asterisk_local.tex asterisk.tex
rubber --pdf asterisk.tex
latex2html asterisk.tex
latex asterisk.tex
catdvi -e 1 -U asterisk.dvi | sed -re "s/\[U\+2022\]/*/g" | sed -re "s/\[U\+02C6\]/^/g" | sed -re "s/([^^[:space:]])\s+/\1 /g" > asterisk.txt
# restore backup of asterisk.tex
mv asterisk.tex.orig asterisk.tex
}
VERSION=`cat .version`
cd doc/tex && make_tex_docs
cd doc
echo "Exporting Asterisk wiki to a PDF (this will take a minute) ..."
wikiexport.py
echo "Converting wiki export PDF to plain text ..."
pdftotext AST.pdf

View File

@ -1,982 +0,0 @@
--------------------------------------
== Asterisk Coding Guidelines ==
--------------------------------------
This document gives some basic indication on how the asterisk code
is structured. The first part covers the structure and style of
individual files. The second part (TO BE COMPLETED) covers the
overall code structure and the build architecture.
Please read it to the end to understand in detail how the asterisk
code is organized, and to know how to extend asterisk or contribute
new code.
We are looking forward to your contributions to Asterisk - the
Open Source PBX! As Asterisk is a large and in some parts very
time-sensitive application, the code base needs to conform to
a common set of coding rules so that many developers can enhance
and maintain the code. Code also needs to be reviewed and tested
so that it works and follows the general architecture and guide-
lines, and is well documented.
Asterisk is published under a dual-licensing scheme by Digium.
To be accepted into the codebase, all non-trivial changes must be
licensed to Digium. For more information, see the electronic license
agreement on https://issues.asterisk.org/.
Patches should be in the form of a unified (-u) diff, made from a checkout
from subversion.
/usr/src/asterisk$ svn diff > mypatch
If you would like to only include changes to certain files in the patch, you
can list them in the "svn diff" command:
/usr/src/asterisk$ svn diff somefile.c someotherfile.c > mypatch
-----------------------------------
== PART ONE: CODING GUIDELINES ==
-----------------------------------
* General rules
---------------
- Indent code using tabs, not spaces.
- All code, filenames, function names and comments must be in ENGLISH.
- Don't annotate your changes with comments like "/* JMG 4/20/04 */";
Comments should explain what the code does, not when something was changed
or who changed it. If you have done a larger contribution, make sure
that you are added to the CREDITS file.
- Don't make unnecessary whitespace changes throughout the code.
If you make changes, submit them to the tracker as separate patches
that only include whitespace and formatting changes.
- Don't use C++ type (//) comments.
- Try to match the existing formatting of the file you are working on.
- Use spaces instead of tabs when aligning in-line comments or #defines (this makes
your comments aligned even if the code is viewed with another tabsize)
* File structure and header inclusion
-------------------------------------
Every C source file should start with a proper copyright
and a brief description of the content of the file.
Following that, you should immediately put the following lines:
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
"asterisk.h" resolves OS and compiler dependencies for the basic
set of unix functions (data types, system calls, basic I/O
libraries) and the basic Asterisk APIs.
ASTERISK_FILE_VERSION() stores in the executable information
about the file.
Next, you should #include extra headers according to the functionality
that your file uses or implements. For each group of functions that
you use there is a common header, which covers OS header dependencies
and defines the 'external' API of those functions (the equivalent
of 'public' members of a class). As an example:
asterisk/module.h
if you are implementing a module, this should be included in one
of the files that are linked with the module.
asterisk/io.h
access to extra file I/O functions (stat, fstat, playing with
directories etc)
asterisk/network.h
basic network I/O - all of the socket library, select/poll,
and asterisk-specific (usually either thread-safe or reentrant
or both) functions to play with socket addresses.
asterisk/app.h
parsing of application arguments
asterisk/channel.h
struct ast_channel and functions to manipulate it
For more information look at the headers in include/asterisk/ .
These files are usually self-sufficient, i.e. they recursively #include
all the extra headers they need.
The equivalent of 'private' members of a class are either directly in
the C source file, or in files named asterisk/mod_*.h to make it clear
that they are not for inclusion by generic code.
Keep the number of header files small by not including them unnecessarily.
Don't cut&paste list of header files from other sources, but only include
those you really need. Apart from obvious cases (e.g. module.h which
is almost always necessary) write a short comment next to each #include to
explain why you need it.
* Declaration of functions and variables
----------------------------------------
- Do not declare variables mid-block (e.g. like recent GNU compilers support)
since it is harder to read and not portable to GCC 2.95 and others.
- Functions and variables that are not intended to be used outside the module
must be declared static. If you are compiling on a Linux platform that has the
'dwarves' package available, you can use the 'pglobal' tool from that package
to check for unintended global variables or functions being exposed in your
object files. Usage is very simple:
$ pglobal -vf <path to .o file>
- When reading integer numeric input with scanf (or variants), do _NOT_ use '%i'
unless you specifically want to allow non-base-10 input; '%d' is always a better
choice, since it will not silently turn numbers with leading zeros into base-8.
- Strings that are coming from input should not be used as the format argument to
any printf-style function.
* Structure alignment and padding
---------------------------------
On many platforms, structure fields (in structures that are not marked 'packed')
will be laid out by the compiler with gaps (padding) between them, in order to
satisfy alignment requirements. As a simple example:
struct foo {
int bar;
void *xyz;
}
On nearly every 64-bit platform, this will result in 4 bytes of dead space between
'bar' and 'xyz', because pointers on 64-bit platforms must be aligned on 8-byte
boundaries. Once you have your code written and tested, it may be worthwhile to review
your structure definitions to look for problems of this nature. If you are on a Linux
platform with the 'dwarves' package available, the 'pahole' tool from that package
can be used to both check for padding issues of this type and also propose reorganized
structure definitions to eliminate it. Usage is quite simple; for a structure named 'foo',
the command would look something like this:
$ pahole --reorganize --show_reorg_steps -C foo <path to module>
The 'pahole' tool has many other modes available, including some that will list all the
structures declared in the module and the amount of padding in each one that could possibly
be recovered.
* Use the internal API
----------------------
- Make sure you are aware of the string and data handling functions that exist
within Asterisk to enhance portability and in some cases to produce more
secure and thread-safe code. Check utils.c/utils.h for these.
- If you need to create a detached thread, use the ast_pthread_create_detached()
normally or ast_pthread_create_detached_background() for a thread with a smaller
stack size. This reduces the replication of the code to handle the pthread_attr_t
structure.
* Code formatting
-----------------
Roughly, Asterisk code formatting guidelines are generally equivalent to the
following:
# indent -i4 -ts4 -br -brs -cdw -lp -ce -nbfda -npcs -nprs -npsl -nbbo -saf -sai -saw -cs -l90 foo.c
this means in verbose:
-i4: indent level 4
-ts4: tab size 4
-br: braces on if line
-brs: braces on struct decl line
-cdw: cuddle do while
-lp: line up continuation below parenthesis
-ce: cuddle else
-nbfda: dont break function decl args
-npcs: no space after function call names
-nprs: no space after parentheses
-npsl: dont break procedure type
-saf: space after for
-sai: space after if
-saw: space after while
-cs: space after cast
-l90: line length 90 columns
Function calls and arguments should be spaced in a consistent way across
the codebase.
GOOD: foo(arg1, arg2);
BAD: foo(arg1,arg2);
BAD: foo (arg1, arg2);
BAD: foo( arg1, arg2 );
BAD: foo(arg1, arg2,arg3);
Don't treat keywords (if, while, do, return) as if they were functions;
leave space between the keyword and the expression used (if any). For 'return',
don't even put parentheses around the expression, since they are not
required.
There is no shortage of whitespace characters :-) Use them when they make
the code easier to read. For example:
for (str=foo;str;str=str->next)
is harder to read than
for (str = foo; str; str = str->next)
Following are examples of how code should be formatted.
- Functions:
int foo(int a, char *s)
{
return 0;
}
- If statements:
if (foo) {
bar();
} else {
blah();
}
- Case statements:
switch (foo) {
case BAR:
blah();
break;
case OTHER:
other();
break;
}
- No nested statements without braces, e.g.:
for (x = 0; x < 5; x++)
if (foo)
if (bar)
baz();
instead do:
for (x = 0; x < 5; x++) {
if (foo) {
if (bar) {
baz();
}
}
}
- Always use braces around the statements following an if/for/while construct,
even if not strictly necessary, as it reduces future possible problems.
- Don't build code like this:
if (foo) {
/* .... 50 lines of code ... */
} else {
result = 0;
return;
}
Instead, try to minimize the number of lines of code that need to be
indented, by only indenting the shortest case of the 'if'
statement, like so:
if (!foo) {
result = 0;
return;
}
.... 50 lines of code ....
When this technique is used properly, it makes functions much easier to read
and follow, especially those with more than one or two 'setup' operations
that must succeed for the rest of the function to be able to execute.
- Labels/goto are acceptable
Proper use of this technique may occasionally result in the need for a
label/goto combination so that error/failure conditions can exit the
function while still performing proper cleanup. This is not a bad thing!
Use of goto in this situation is encouraged, since it removes the need
for excess code indenting without requiring duplication of cleanup code.
- Never use an uninitialized variable
Make sure you never use an uninitialized variable. The compiler will
usually warn you if you do so. However, do not go too far the other way,
and needlessly initialize variables that do not require it. If the first
time you use a variable in a function is to store a value there, then
initializing it at declaration is pointless, and will generate extra
object code and data in the resulting binary with no purpose. When in doubt,
trust the compiler to tell you when you need to initialize a variable;
if it does not warn you, initialization is not needed.
- Do not cast 'void *'
Do not explicitly cast 'void *' into any other type, nor should you cast any
other type into 'void *'. Implicit casts to/from 'void *' are explicitly
allowed by the C specification. This means the results of malloc(), calloc(),
alloca(), and similar functions do not _ever_ need to be cast to a specific
type, and when you are passing a pointer to (for example) a callback function
that accepts a 'void *' you do not need to cast into that type.
* Function naming
-----------------
All public functions (those not marked 'static'), must be named "ast_<something>"
and have a descriptive name.
As an example, suppose you wanted to take a local function "find_feature", defined
as static in a file, and used only in that file, and make it public, and use it
in other files. You will have to remove the "static" declaration and define a
prototype in an appropriate header file (usually in include/asterisk). A more
specific name should be given, such as "ast_find_call_feature".
* Variable function argument parsing
------------------------------------
Functions with a variable amount of arguments need a 'sentinel' when called.
Newer GNU C compilers are fine if you use NULL for this. Older versions (pre 4)
don't like this.
You should use the constant SENTINEL.
This one is defined in include/asterisk/compiler.h
* Variable naming
-----------------
- Global variables
Name global variables (or local variables when you have a lot of them or
are in a long function) something that will make sense to aliens who
find your code in 100 years. All variable names should be in lower
case, except when following external APIs or specifications that normally
use upper- or mixed-case variable names; in that situation, it is
preferable to follow the external API/specification for ease of
understanding.
Make some indication in the name of global variables which represent
options that they are in fact intended to be global.
e.g.: static char global_something[80]
- Don't use unnecessary typedef's
Don't use 'typedef' just to shorten the amount of typing; there is no substantial
benefit in this:
struct foo { int bar; }; typedef struct foo foo_t;
In fact, don't use 'variable type' suffixes at all; it's much preferable to
just type 'struct foo' rather than 'foo_s'.
- Use enums instead of #define where possible
Use enums rather than long lists of #define-d numeric constants when possible;
this allows structure members, local variables and function arguments to
be declared as using the enum's type. For example:
enum option {
OPT_FOO = 1,
OPT_BAR = 2,
OPT_BAZ = 4,
};
static enum option global_option;
static handle_option(const enum option opt)
{
...
}
Note: The compiler will _not_ force you to pass an entry from the enum
as an argument to this function; this recommendation serves only to make
the code clearer and somewhat self-documenting. In addition, when using
switch/case blocks that switch on enum values, the compiler will warn
you if you forget to handle one or more of the enum values, which can be
handy.
* String handling
-----------------
Don't use strncpy for copying whole strings; it does not guarantee that the
output buffer will be null-terminated. Use ast_copy_string instead, which
is also slightly more efficient (and allows passing the actual buffer
size, which makes the code clearer).
Don't use ast_copy_string (or any length-limited copy function) for copying
fixed (known at compile time) strings into buffers, if the buffer is something
that has been allocated in the function doing the copying. In that case, you
know at the time you are writing the code whether the buffer is large enough
for the fixed string or not, and if it's not, your code won't work anyway!
Use strcpy() for this operation, or directly set the first two characters
of the buffer if you are just trying to store a one character string in the
buffer. If you are trying to 'empty' the buffer, just store a single
NULL character ('\0') in the first byte of the buffer; nothing else is
needed, and any other method is wasteful.
In addition, if the previous operations in the function have already
determined that the buffer in use is adequately sized to hold the string
you wish to put into it (even if you did not allocate the buffer yourself),
use a direct strcpy(), as it can be inlined and optimized to simple
processor operations, unlike ast_copy_string().
* String conversions
--------------------
When converting from strings to integers or floats, use the sscanf function
in preference to the atoi and atof family of functions, as sscanf detects
errors. Always check the return value of sscanf to verify that your numeric
variables successfully scanned before using them. Also, to avoid a potential
libc bug, always specify a maximum width for each conversion specifier,
including integers and floats. A good length for both integers and floats is
30, as this is more than generous, even if you're using doubles or long
integers.
* Use of functions
------------------
For the sake of uclibc, do not use index, bcopy or bzero; use strchr(), memset(),
and memmove() instead. uclibc can be configured to supply these functions, but
we can save these users time and consternation if we abstain from using these
functions.
When making applications, always ast_strdupa(data) to a local pointer if you
intend to parse the incoming data string.
if (data) {
mydata = ast_strdupa(data);
}
- Use the argument parsing macros to declare arguments and parse them, i.e.:
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(arg1);
AST_APP_ARG(arg2);
AST_APP_ARG(arg3);
);
parse = ast_strdupa(data);
AST_STANDARD_APP_ARGS(args, parse);
- Create generic code!
If you do the same or a similar operation more than one time, make it a
function or macro.
Make sure you are not duplicating any functionality already found in an
API call somewhere. If you are duplicating functionality found in
another static function, consider the value of creating a new API call
which can be shared.
* Handling of pointers and allocations
--------------------------------------
- Dereference or localize pointers
Always dereference or localize pointers to things that are not yours like
channel members in a channel that is not associated with the current
thread and for which you do not have a lock.
channame = ast_strdupa(otherchan->name);
- Use const on pointer arguments if possible
Use const on pointer arguments which your function will not be modifying, as this
allows the compiler to make certain optimizations. In general, use 'const'
on any argument that you have no direct intention of modifying, as it can
catch logic/typing errors in your code when you use the argument variable
in a way that you did not intend.
- Do not create your own linked list code - reuse!
As a common example of this point, make an effort to use the lockable
linked-list macros found in include/asterisk/linkedlists.h. They are
efficient, easy to use and provide every operation that should be
necessary for managing a singly-linked list (if something is missing,
let us know!). Just because you see other open-coded list implementations
in the source tree is no reason to continue making new copies of
that code... There are also a number of common string manipulation
and timeval manipulation functions in asterisk/strings.h and asterisk/time.h;
use them when possible.
- Avoid needless allocations!
Avoid needless malloc(), strdup() calls. If you only need the value in
the scope of your function try ast_strdupa() or declare structs on the
stack and pass a pointer to them. However, be careful to _never_ call
alloca(), ast_strdupa() or similar functions in the argument list
of a function you are calling; this can cause very strange stack
arrangements and produce unexpected behavior.
- Allocations for structures
When allocating/zeroing memory for a structure, use code like this:
struct foo *tmp;
...
tmp = ast_calloc(1, sizeof(*tmp));
Avoid the combination of ast_malloc() and memset(). Instead, always use
ast_calloc(). This will allocate and zero the memory in a single operation.
In the case that uninitialized memory is acceptable, there should be a comment
in the code that states why this is the case.
Using sizeof(*tmp) instead of sizeof(struct foo) eliminates duplication of the
'struct foo' identifier, which makes the code easier to read and also ensures
that if it is copy-and-pasted it won't require as much editing.
The ast_* family of functions for memory allocation are functionally the same.
They just add an Asterisk log error message in the case that the allocation
fails for some reason. This eliminates the need to generate custom messages
throughout the code to log that this has occurred.
- String Duplications
The functions strdup and strndup can *not* accept a NULL argument. This results
in having code like this:
if (str) {
newstr = strdup(str);
} else {
newstr = NULL;
}
However, the ast_strdup and ast_strdupa functions will happily accept a NULL
argument without generating an error. The same code can be written as:
newstr = ast_strdup(str);
Furthermore, it is unnecessary to have code that malloc/calloc's for the length
of a string (+1 for the terminating '\0') and then using strncpy to copy the
copy the string into the resulting buffer. This is the exact same thing as
using ast_strdup.
* CLI Commands
--------------
New CLI commands should be named using the module's name, followed by a verb
and then any parameters that the command needs. For example:
*CLI> iax2 show peer <peername>
not
*CLI> show iax2 peer <peername>
* New dialplan applications/functions
-------------------------------------
There are two methods of adding functionality to the Asterisk
dialplan: applications and functions. Applications (found generally in
the apps/ directory) should be collections of code that interact with
a channel and/or user in some significant way. Functions (which can be
provided by any type of module) are used when the provided
functionality is simple... getting/retrieving a value, for
example. Functions should also be used when the operation is in no way
related to a channel (a computation or string operation, for example).
Applications are registered and invoked using the
ast_register_application function; see the apps/app_skel.c file for an
example.
Functions are registered using 'struct ast_custom_function'
structures and the ast_custom_function_register function.
* Doxygen API Documentation Guidelines
--------------------------------------
When writing Asterisk API documentation the following format should be
followed. Do not use the javadoc style.
/*!
* \brief Do interesting stuff.
*
* \param thing1 interesting parameter 1.
* \param thing2 interesting parameter 2.
*
* This function does some interesting stuff.
*
* \retval zero on success
* \retval -1 on error.
*/
int ast_interesting_stuff(int thing1, int thing2)
{
return 0;
}
Notice the use of the \param, \brief, and \return constructs. These should be
used to describe the corresponding pieces of the function being documented.
Also notice the blank line after the last \param directive. All doxygen
comments must be in one /*! */ block. If the function or struct does not need
an extended description it can be left out.
Please make sure to review the doxygen manual and make liberal use of the \a,
\code, \c, \b, \note, \li and \e modifiers as appropriate.
When documenting a 'static' function or an internal structure in a module,
use the \internal modifier to ensure that the resulting documentation
explicitly says 'for internal use only'.
When adding new API you should also attach a \since note because this will
indicate to developers that this API did not exist before this version. It
also has the benefit of making the resulting HTML documentation to group
the changes for a single version.
Structures should be documented as follows.
/*!
* \brief A very interesting structure.
*/
struct interesting_struct
{
/*! \brief A data member. */
int member1;
int member2; /*!< \brief Another data member. */
}
Note that /*! */ blocks document the construct immediately following them
unless they are written, /*!< */, in which case they document the construct
preceding them.
It is very much preferred that documentation is not done inline, as done in
the previous example for member2. The first reason for this is that it tends
to encourage extremely brief, and often pointless, documentation since people
try to keep the comment from making the line extremely long. However, if you
insist on using inline comments, please indent the documentation with spaces!
That way, all of the comments are properly aligned, regardless of what tab
size is being used for viewing the code.
* Finishing up before you submit your code
------------------------------------------
- Look at the code once more
When you achieve your desired functionality, make another few refactor
passes over the code to optimize it.
- Read the patch
Before submitting a patch, *read* the actual patch file to be sure that
all the changes you expect to be there are, and that there are no
surprising changes you did not expect. During your development, that
part of Asterisk may have changed, so make sure you compare with the
latest SVN.
- Listen to advice
If you are asked to make changes to your patch, there is a good chance
the changes will introduce bugs, check it even more at this stage.
Also remember that the bug marshal or co-developer that adds comments
is only human, they may be in error :-)
- Optimize, optimize, optimize
If you are going to reuse a computed value, save it in a variable
instead of recomputing it over and over. This can prevent you from
making a mistake in subsequent computations, making it easier to correct
if the formula has an error and may or may not help optimization but
will at least help readability.
Just an example (so don't over analyze it, that'd be a shame):
const char *prefix = "pre";
const char *postfix = "post";
char *newname;
char *name = "data";
if (name && (newname = alloca(strlen(name) + strlen(prefix) + strlen(postfix) + 3))) {
snprintf(newname, strlen(name) + strlen(prefix) + strlen(postfix) + 3, "%s/%s/%s", prefix, name, postfix);
|
...vs this alternative:
const char *prefix = "pre";
const char *postfix = "post";
char *newname;
char *name = "data";
int len = 0;
if (name && (len = strlen(name) + strlen(prefix) + strlen(postfix) + 3) && (newname = alloca(len))) {
snprintf(newname, len, "%s/%s/%s", prefix, name, postfix);
}
* Creating new manager events?
------------------------------
If you create new AMI events, please read manager.txt. Do not re-use
existing headers for new purposes, but please re-use existing headers
for the same type of data.
Manager events that signal a status are required to have one
event name, with a status header that shows the status.
The old style, with one event named "ThisEventOn" and another named
"ThisEventOff", is no longer approved.
Check manager.txt for more information on manager and existing
headers. Please update this file if you add new headers.
* Locking in Asterisk
-----------------------------
A) Locking Fundamentals
Asterisk is a heavily multithreaded application. It makes extensive
use of locking to ensure safe access to shared resources between
different threads.
When more that one lock is involved in a given code path, there is the
potential for deadlocks. A deadlock occurs when a thread is stuck
waiting for a resource that it will never acquire. Here is a classic
example of a deadlock:
Thread 1 Thread 2
------------ ------------
Holds Lock A Holds Lock B
Waiting for Lock B Waiting for Lock A
In this case, there is a deadlock between threads 1 and 2.
This deadlock would have been avoided if both threads had
agreed that one must acquire Lock A before Lock B.
In general, the fundamental rule for dealing with multiple locks is
an order _must_ be established to acquire locks, and then all threads
must respect that order when acquiring locks.
A.1) Establishing a locking order
Because any ordering for acquiring locks is ok, one could establish
the rule arbitrarily, e.g. ordering by address, or by some other criterion.
The main issue, though, is defining an order that
i) is easy to check at runtime;
ii) reflects the order in which the code executes.
As an example, if a data structure B is only accessible through a
data structure A, and both require locking, then the natural order
is locking first A and then B.
As another example, if we have some unrelated data structures to
be locked in pairs, then a possible order can be based on the address
of the data structures themselves.
B) Minding the boundary between channel drivers and the Asterisk core
The #1 cause of deadlocks in Asterisk is by not properly following the
locking rules that exist at the boundary between Channel Drivers and
the Asterisk core. The Asterisk core allocates an ast_channel, and
Channel Drivers allocate "technology specific private data" (PVT) that is
associated with an ast_channel. Typically, both the ast_channel and
PVT have their own lock. There are _many_
code paths that require both objects to be locked.
The locking order in this situation is the following:
1) ast_channel
2) PVT
Channel Drivers implement the ast_channel_tech interface to provide a
channel implementation for Asterisk. Most of the channel_tech
interface callbacks are called with the associated ast_channel
locked. When accessing technology specific data, the PVT can be locked
directly because the locking order is respected.
C) Preventing lock ordering reversals.
There are some code paths which make it extremely difficult to
respect the locking order.
Consider for example the following situation:
1) A message comes in over the "network"
2) The Channel Driver (CD) monitor thread receives the message
3) The CD associates the message with a PVT and locks the PVT
4) While processing the message, the CD must do something that requires
locking the ast_channel associated to the PVT
This is the point that must be handled carefully.
The following psuedo-code
unlock(pvt);
lock(ast_channel);
lock(pvt);
is _not_ correct for two reasons:
i) first and foremost, unlocking the PVT means that other threads
can acquire the lock and believe it is safe to modify the
associated data. When reacquiring the lock, the original thread
might find unexpected changes in the protected data structures.
This essentially means that the original thread must behave as if
the lock on the pvt was not held, in which case it could have
released it itself altogether;
ii) Asterisk uses the so called "recursive" locks, which allow a thread
to issue a lock() call multiple times on the same lock. Recursive
locks count the number of calls, and they require an equivalent
number of unlock() to be actually released.
For this reason, just calling unlock() once does not guarantee that the
lock is actually released -- it all depends on how many times lock()
was called before.
An alternative, but still incorrect, construct is widely used in
the asterisk code to try and improve the situation:
while (trylock(ast_channel) == FAILURE) {
unlock(pvt);
usleep(1); /* yield to other threads */
lock(pvt);
}
Here the trylock() is non blocking, so we do not deadlock if the ast_channel
is already locked by someone else: in this case, we try to unlock the PVT
(which happens only if the PVT lock counter is 1), yield the CPU to
give other threads a chance to run, and then acquire the lock again.
This code is not correct for two reasons:
i) same as in the previous example, it releases the lock when the thread
probably did not expect it;
ii) if the PVT lock counter is greater than 1 we will not
really release the lock on the PVT. We might be lucky and have the
other contender actually release the lock itself, and so we will "win"
the race, but if both contenders have their lock counts > 1 then
they will loop forever (basically replacing deadlock with livelock).
Another variant of this code is the following:
if (trylock(ast_channel) == FAILURE) {
unlock(pvt);
lock(ast_channel);
lock(pvt);
}
which has the same issues as the while(trylock...) code, but just
deadlocks instead of looping forever in case of lock counts > 1.
The deadlock/livelock could be in principle spared if one had an
unlock_all() function that calls unlock as many times as needed to
actually release the lock, and reports the count. Then we could do:
if (trylock(ast_channel) == FAILURE) {
n = unlock_all(pvt);
lock(ast_channel)
while (n-- > 0) lock(pvt);
}
The issue with unexpected unlocks remains, though.
C) Locking multiple channels.
The next situation to consider is what to do when you need a lock on
multiple ast_channels (or multiple unrelated data structures).
If we are sure that we do not hold any of these locks, then the
following construct is sufficient:
lock(MIN(chan1, chan2));
lock(MAX(chan1, chan2));
That type of code would follow an established locking order of always
locking the channel that has a lower address first. Also keep in mind
that to use this construct for channel locking, one would have to go
through the entire codebase to ensure that when two channels are locked,
this locking order is used.
However, if we enter the above section of code with some lock held
(which would be incorrect using non-recursive locks, but is completely
legal using recursive mutexes) then the locking order is not guaranteed
anymore because it depends on which locks we already hold. So we have
to go through the same tricks used for the channel+PVT case.
D) Recommendations
As you can see from the above discussion, getting locking right is all
but easy. So please follow these recommendations when using locks:
*) Use locks only when really necessary
Please try to use locks only when strictly necessary, and only for
the minimum amount of time required to run critical sections of code.
A common use of locks in the current code is to protect a data structure
from being released while you use it.
With the use of reference-counted objects (astobj2) this should not be
necessary anymore.
*) Do not sleep while holding a lock
If possible, do not run any blocking code while holding a lock,
because you will also block other threads trying to access the same
lock. In many cases, you can hold a reference to the object to avoid
that it is deleted while you sleep, perhaps set a flag in the object
itself to report other threads that you have some pending work to
complete, then release and acquire the lock around the blocking path,
checking the status of the object after you acquire the lock to make
sure that you can still perform the operation you wanted to.
*) Try not to exploit the 'recursive' feature of locks.
Recursive locks are very convenient when coding, as you don't have to
worry, when entering a section of code, whether or not you already
hold the lock -- you can just protect the section with a lock/unlock
pair and let the lock counter track things for you.
But as you have seen, exploiting the features of recursive locks
make it a lot harder to implement proper deadlock avoidance strategies.
So please try to analyse your code and determine statically whether you
already hold a lock when entering a section of code.
If you need to call some function foo() with and without a lock held,
you could define two function as below:
foo_locked(...) {
... do something, assume lock held
}
foo(...) {
lock(xyz)
ret = foo_locked(...)
unlock(xyz)
return ret;
}
and call them according to the needs.
*) Document locking rules.
Please document the locking order rules are documented for every
lock introduced into Asterisk. This is done almost nowhere in the
existing code. However, it will be expected to be there for newly
introduced code. Over time, this information should be added for
all of the existing lock usage.
-----------------------------------------------------------------------
------------------------------------
== PART TWO: BUILD ARCHITECTURE ==
------------------------------------
The asterisk build architecture relies on autoconf to detect the
system configuration, and on a locally developed tool (menuselect) to
select build options and modules list, and on gmake to do the build.
The first step, usually to be done soon after a checkout, is running
"./configure", which will store its findings in two files:
+ include/asterisk/autoconfig.h
contains C macros, normally #define HAVE_FOO or HAVE_FOO_H ,
for all functions and headers that have been detected at build time.
These are meant to be used by C or C++ source files.
+ makeopts
contains variables that can be used by Makefiles.
In addition to the usual CC, LD, ... variables pointing to
the various build tools, and prefix, includedir ... which are
useful for generic compiler flags, there are variables
for each package detected.
These are normally of the form FOO_INCLUDE=... FOO_LIB=...
FOO_DIR=... indicating, for each package, the useful libraries
and header files.
The next step is to run "make menuselect", to extract the dependencies existing
between files and modules, and to store build options.
menuselect produces two files, both to be read by the Makefile:
+ menuselect.makeopts
Contains for each subdirectory a list of modules that must be
excluded from the build, plus some additional informatiom.
+ menuselect.makedeps
Contains, for each module, a list of packages it depends on.
For each of these packages, we can collect the relevant INCLUDE
and LIB files from makeopts. This file is based on information
in the .c source code files for each module.
The top level Makefile is in charge of setting up the build environment,
creating header files with build options, and recursively invoking the
subdir Makefiles to produce modules and the main executable.
The sources are split in multiple directories, more or less divided by
module type (apps/ channels/ funcs/ res/ ...) or by function, for the main
binary (main/ pbx/).
TO BE COMPLETED
-----------------------------------------------
Welcome to the Asterisk development community!
Meet you on the asterisk-dev mailing list.
Subscribe at http://lists.digium.com!
-- The Asterisk.org Development Team

View File

@ -1,89 +0,0 @@
===============================================================================
===
=== HowTo: Collect Debug Information for the Asterisk Issue Tracker
===
=== Written by: Paul Belanger
=== Last updated: 2010-04-12
===============================================================================
This document will provide instructions on how to collect debugging logs from an
Asterisk machine, for the purpose of helping bug marshals troubleshoot an issue
on https://issues.asterisk.org
-------------------------------------------------------------------------------
--- PREREQUISITES
-------------------------------------------------------------------------------
- Asterisk 1.4.30 or greater.
-------------------------------------------------------------------------------
--- STEPS
-------------------------------------------------------------------------------
1. Edit the logger.conf file to enable debug output to your filesystem.
Add the following line. The word "myDebugLog" can be changed to anything you
want, as that is the filename the logging will be written to. A good example
might be something like: issue_12345_full_log
myDebugLog => notice,warning,error,debug,verbose,dtmf
2. From the Asterisk CLI, restart the logger module:
*CLI> core set verbose 15
*CLI> core set debug 15
*CLI> module reload logger
Optionally, if you've used this file to record data previously, then rotate
the logs:
*CLI> logger rotate
2.1. Depending on your issue, be sure to enable the channel driver logging.
SIP (1.6.0 or higher)
*CLI> sip set debug on
SIP (1.4)
*CLI> sip set debug
IAX2 (1.6.0 or higher)
*CLI> iax2 set debug on
IAX2 (1.4)
*CLI> iax2 set debug
3. Reproduce your issue.
4. Once finished, be sure to disable the extra debbuging:
*CLI> core set verbose 0
*CLI> core set debug 0
4.1. Again, remember to disable any extra logging if you enabled it in the
channel driver.
SIP (1.4 or higher)
*CLI> sip set debug off
IAX2 (1.4 or higher)
*CLI> iax2 set debug off
5. Upload the file located in /var/log/asterisk/myDebugLog to the issue tracker.
*** IMPORTANT ***
Do NOT post the output of your file as a comment. This clutters the issue
and will only result in your comment being deleted.
6. Disable logging to the filesystem. Edit the logger.conf file and comment out
or delete the line you added in step 1. Using a semi-colon as the first
character on the line will comment out the line.
Then reload the logger module like in step 2:
*CLI> module reload logger

View File

@ -1,75 +0,0 @@
India finds itself in a unique situation (hopefully). It has several
telephone line providers, and they are not all using the same CID
signalling; and the CID signalling is not like other countries.
In order to help those in India quickly find to the CID signalling
system that their carrier uses (or range of them), and get the
configs right with a minimal amount of experimentation, this file
is provided. Not all carriers are covered, and not all mentioned
below are complete. Those with updates to this table should post
the new information on bug 6683 of the asterisk bug tracker.
---------------------------------------------------------
Provider: Bharti (is this BSNL?)
Config: cidstart=polarity_in
cidsignalling=dtmf
Results: ? (this should work), but needs to be tested?
tested by:
--------------------------------------------------------
Provider: VSNL
Config:
Results: ?
tested by:
--------------------------------------------------------
Provider: BSNL
Config: cid_start=ring
cid_signalling=dtmf
Results: ?
tested by: (abhi)
--------------------------------------------------------
Provider: MTNL, old BSNL
Config: cidsignalling = v23
cidstart=ring
Results: works
tested by: (enterux)
--------------------------------------------------------
Provider: MTNL (Delhi)
Config: cidsignalling = v23
cidstart = ring
cidsignalling = dtmf
cidstart = polarity_IN
cidsignalling = dtmf
cidstart = polarity
Results: fails
tested by: brealer
--------------------------------------------------------
Provider: TATA
Config: cidsignalling = dtmf
cidstart=polarity_IN
Results: works
tested by: brealer
---------------------------------------------------------
Asterisk still doesn't work with some of the CID scenarios in India.
If you are in India, and not able to make CID work with any of the
permutations of cidsignalling and cidstart, it could be that this
particular situation is not covered by Asterisk. A good course of
action would be to get in touch with the provider, and find out from
them exactly how their CID signalling works. Describe this to us,
and perhaps someone will be able to extend the code to cover their
signalling.

View File

@ -1,503 +0,0 @@
\begin{verbatim}
DIGIUM GENERAL PEERING AGREEMENT (TM)
Version 1.0.0, September 2004
Copyright (C) 2004 Digium, Inc.
445 Jan Davis Drive, Huntsville, AL 35806 USA
Everyone is permitted to copy and distribute complete verbatim copies
of this General Peering Agreement provided it is not modified in any
manner.
------------------------------------------------------
DIGIUM GENERAL PEERING AGREEMENT
PREAMBLE
For most of the history of telecommunications, the power of being able
to locate and communicate with another person in a system, be it across
a hall or around the world, has always centered around a centralized
authority -- from a local PBX administrator to regional and national
RBOCs, generally requiring fees, taxes or regulation. By contrast,
DUNDi is a technology developed to provide users the freedom to
communicate with each other without the necessity of any centralized
authority. This General Peering Agreement ("GPA") is used by individual
parties (each, a "Participant") to allow them to build the E164 trust
group for the DUNDi protocol.
To protect the usefulness of the E164 trust group for those who use
it, while keeping the system wholly decentralized, it is necessary to
replace many of the responsibilities generally afforded to a company or
government agency, with a set of responsibilities implemented by the
parties who use the system, themselves. It is the goal of this document
to provide all the protections necessary to keep the DUNDi E164 trust
group useful and reliable.
The Participants wish to protect competition, promote innovation and
value added services and make this service valuable both commercially
and non-commercially. To that end, this GPA provides special terms and
conditions outlining some permissible and non-permissible revenue
sources.
This GPA is independent of any software license or other license
agreement for a program or technology employing the DUNDi protocol. For
example, the implementation of DUNDi used by Asterisk is covered under a
separate license. Each Participant is responsible for compliance with
any licenses or other agreements governing use of such program or
technology that they use to peer.
You do not have to execute this GPA to use a program or technology
employing the DUNDi protocol, however if you do not execute this GPA,
you will not be able to peer using DUNDi and the E164 context with
anyone who is a member of the trust group by virtue of their having
executed this GPA with another member.
The parties to this GPA agree as follows:
0. DEFINITIONS. As used herein, certain terms shall be defined as
follows:
(a) The term "DUNDi" means the DUNDi protocol as published by
Digium, Inc. or its successor in interest with respect to the
DUNDi protocol specification.
(b) The terms "E.164" and "E164" mean ITU-T specification E.164 as
published by the International Telecommunications Union (ITU) in
May, 1997.
(c) The term "Service" refers to any communication facility (e.g.,
telephone, fax, modem, etc.), identified by an E.164-compatible
number, and assigned by the appropriate authority in that
jurisdiction.
(d) The term "Egress Gateway" refers an Internet facility that
provides a communications path to a Service or Services that may
not be directly addressable via the Internet.
(e) The term "Route" refers to an Internet address, policies, and
other characteristics defined by the DUNDi protocol and
associated with the Service, or the Egress Gateway which
provides access to the specified Service.
(f) The term "Propagate" means to accept or transmit Service and/or
Egress Gateway Routes only using the DUNDi protocol and the
DUNDi context "e164" without regard to case, and does not apply
to the exchange of information using any other protocol or
context.
(g) The term "Peering System" means the network of systems that
Propagate Routes.
(h) The term "Subscriber" means the owner of, or someone who
contracts to receive, the services identified by an E.164
number.
(i) The term "Authorizing Individual" means the Subscriber to a
number who has authorized a Participant to provide Routes
regarding their services via this Peering System.
(j) The term "Route Authority" refers to a Participant that provides
an original source of said Route within the Peering System.
Routes are propagated from the Route Authorities through the
Peering System and may be cached at intermediate points. There
may be multiple Route Authorities for any Service.
(k) The term "Participant" (introduced above) refers to any member
of the Peering System.
(l) The term "Service Provider" refers to the carrier (e.g.,
exchange carrier, Internet Telephony Service Provider, or other
reseller) that provides communication facilities for a
particular Service to a Subscriber, Customer or other End User.
(m) The term "Weight" refers to a numeric quality assigned to a
Route as per the DUNDi protocol specification. The current
Weight definitions are shown in Exhibit A.
1. PEERING. The undersigned Participants agree to Propagate Routes
with each other and any other member of the Peering System and further
agree not to Propagate DUNDi Routes with a third party unless they have
first have executed this GPA (in its unmodified form) with such third
party. The Participants further agree only to Propagate Routes with
Participants whom they reasonably believe to be honoring the terms of
the GPA. Participants may not insert, remove, amend, or otherwise
modify any of the terms of the GPA.
2. ACCEPTABLE USE POLICY. The DUNDi protocol contains information
that reflect a Subscriber's or Egress Gateway's decisions to receive
calls. In addition to the terms and conditions set forth in this GPA,
the Participants agree to honor the intent of restrictions encoded in
the DUNDi protocol. To that end, Participants agree to the following:
(a) A Participant may not utilize or permit the utilization of
Routes for which the Subscriber or Egress Gateway provider has
indicated that they do not wish to receive "Unsolicited Calls"
for the purpose of making an unsolicited phone call on behalf of
any party or organization.
(b) A Participant may not utilize or permit the utilization of
Routes which have indicated that they do not wish to receive
"Unsolicited Commercial Calls" for the purpose of making an
unsolicited phone call on behalf of a commercial organization.
(c) A Participant may never utilize or permit the utilization of any
DUNDi route for the purpose of making harassing phone calls.
(d) A Party may not utilize or permit the utilization of DUNDi
provided Routes for any systematic or random calling of numbers
(e.g., for the purpose of locating facsimile, modem services, or
systematic telemarketing).
(e) Initial control signaling for all communication sessions that
utilize Routes obtained from the Peering System must be sent
from a member of the Peering System to the Service or Egress
Gateway identified in the selected Route. For example, 'SIP
INVITES' and IAX2 "NEW" commands must be sent from the
requesting DUNDi node to the terminating Service.
(f) A Participant may not disclose any specific Route, Service or
Participant contact information obtained from the Peering System
to any party outside of the Peering System except as a
by-product of facilitating communication in accordance with
section 2e (e.g., phone books or other databases may not be
published, but the Internet addresses of the Egress Gateway or
Service does not need to be obfuscated.)
(g) The DUNDi Protocol requires that each Participant include valid
contact information about itself (including information about
nodes connected to each Participant). Participants may use or
disclose the contact information only to ensure enforcement of
legal furtherance of this Agreement.
3. ROUTES. The Participants shall only propagate valid Routes, as
defined herein, through the Peering System, regardless of the original
source. The Participants may only provide Routes as set forth below,
and then only if such Participant has no good faith reason to believe
such Route to be invalid or unauthorized.
(a) A Participant may provide Routes if each Route has as its
original source another member of the Peering System who has
duly executed the GPA and such Routes are provided in accordance
with this Agreement; provided that the Routes are not modified
(e.g., with regards to existence, destination, technology or
Weight); or
(b) A Participant may provide Routes for Services with any Weight
for which it is the Subscriber; or
(c) A Participant may provide Routes for those Services whose
Subscriber has authorized the Participant to do so, provided
that the Participant is able to confirm that the Authorizing
Individual is the Subscriber through:
i. a written statement of ownership from the Authorizing
Individual, which the Participant believes in good faith
to be accurate (e.g., a phone bill with the name of the
Authorizing Individual and the number in question); or
ii. the Participant's own direct personal knowledge that the
Authorizing Individual is the Subscriber.
(d) A Participant may provide Routes for Services, with Weight in
accordance with the Current DUNDi Specification, if it can in
good faith provide an Egress Gateway to that Service on the
traditional telephone network without cost to the calling party.
4. REVOCATION. A Participant must provide a free, easily accessible
mechanism by which a Subscriber may revoke permission to act as a Route
Authority for his Service. A Participant must stop acting as a Route
Authority for that Service within 7 days after:
(a) receipt of a revocation request;
(b) receiving other notice that the Service is no longer valid; or
(c) determination that the Subscriber's information is no longer
accurate (including that the Subscriber is no longer the service
owner or the service owner's authorized delegate).
5. SERVICE FEES. A Participant may charge a fee to act as a Route
Authority for a Service, with any Weight, provided that no Participant
may charge a fee to propagate the Route received through the Peering
System.
6. TOLL SERVICES. No Participant may provide Routes for any Services
that require payment from the calling party or their customer for
communication with the Service. Nothing in this section shall prohibit
a Participant from providing routes for Services where the calling party
may later enter into a financial transaction with the called party
(e.g., a Participant may provide Routes for calling cards services).
7. QUALITY. A Participant may not intentionally impair communication
using a Route provided to the Peering System (e.g. by adding delay,
advertisements, reduced quality). If for any reason a Participant is
unable to deliver a call via a Route provided to the Peering System,
that Participant shall return out-of-band Network Congestion
notification (e.g. "503 Service Unavailable" with SIP protocol or
"CONGESTION" with IAX protocol).
8. PROTOCOL COMPLIANCE. Participants agree to Propagate Routes in
strict compliance with current DUNDi protocol specifications.
9. ADMINISTRATIVE FEES. A Participant may charge (but is not required
to charge) another Participant a reasonable fee to cover administrative
expenses incurred in the execution of this Agreement. A Participant may
not charge any fee to continue the relationship or to provide Routes to
another Participant in the Peering System.
10. CALLER IDENTIFICATION. A Participant will make a good faith effort
to ensure the accuracy and appropriate nature of any caller
identification that it transmits via any Route obtained from the Peering
System. Caller identification shall at least be provided as a valid
E.164 number.
11. COMPLIANCE WITH LAWS. The Participants are solely responsible for
determining to what extent, if any, the obligations set forth in this
GPA conflict with any laws or regulations their region. A Participant
may not provide any service or otherwise use DUNDi under this GPA if
doing so is prohibited by law or regulation, or if any law or regulation
imposes requirements on the Participant that are inconsistent with the
terms of this GPA or the Acceptable Use Policy.
12. WARRANTY. EACH PARTICIPANT WARRANTS TO THE OTHER PARTICIPANTS THAT
IT MADE, AND WILL CONTINUE TO MAKE, A GOOD FAITH EFFORT TO AUTHENTICATE
OTHERS IN THE PEERING SYSTEM AND TO PROVIDE ACCURATE INFORMATION IN
ACCORDANCE WITH THE TERMS OF THIS GPA. THIS WARRANTY IS MADE BETWEEN
THE PARTICIPANTS, AND THE PARTICIPANTS MAY NOT EXTEND THIS WARRANTY TO
ANY NON-PARTICIPANT INCLUDING END-USERS.
13. DISCLAIMER OF WARRANTIES. THE PARTICIPANTS UNDERSTAND AND AGREE
THAT ANY SERVICE PROVIDED AS A RESULT OF THIS GPA IS "AS IS." EXCEPT FOR
THOSE WARRANTIES OTHERWISE EXPRESSLY SET FORTH HEREIN, THE PARTICIPANTS
DISCLAIM ANY REPRESENTATIONS OR WARRANTIES OF ANY KIND OR NATURE,
EXPRESS OR IMPLIED, AS TO THE CONDITION, VALUE OR QUALITIES OF THE
SERVICES PROVIDED HEREUNDER, AND SPECIFICALLY DISCLAIM ANY
REPRESENTATION OR WARRANTY OF MERCHANTABILITY, SUITABILITY OR FITNESS
FOR A PARTICULAR PURPOSE OR AS TO THE CONDITION OR WORKMANSHIP THEREOF,
OR THE ABSENCE OF ANY DEFECTS THEREIN, WHETHER LATENT OR PATENT,
INCLUDING ANY WARRANTIES ARISING FROM A COURSE OF DEALING, USAGE OR
TRADE PRACTICE. EXCEPT AS EXPRESSLY PROVIDED HEREIN, THE PARTICIPANTS
EXPRESSLY DISCLAIM ANY REPRESENTATIONS OR WARRANTIES THAT THE PEERING
SERVICE WILL BE CONTINUOUS, UNINTERRUPTED OR ERROR-FREE, THAT ANY DATA
SHARED OR OTHERWISE MADE AVAILABLE WILL BE ACCURATE OR COMPLETE OR
OTHERWISE COMPLETELY SECURE FROM UNAUTHORIZED ACCESS.
14. LIMITATION OF LIABILITIES. NO PARTICIPANT SHALL BE LIABLE TO ANY
OTHER PARTICIPANT FOR INCIDENTAL, INDIRECT, CONSEQUENTIAL, SPECIAL,
PUNITIVE OR EXEMPLARY DAMAGES OF ANY KIND (INCLUDING LOST REVENUES OR
PROFITS, LOSS OF BUSINESS OR LOSS OF DATA) IN ANY WAY RELATED TO THIS
GPA, WHETHER IN CONTRACT OR IN TORT, REGARDLESS OF WHETHER SUCH
PARTICIPANT WAS ADVISED OF THE POSSIBILITY THEREOF.
15. END-USER AGREEMENTS. The Participants may independently enter
into agreements with end-users to provide certain services (e.g., fees
to a Subscriber to originate Routes for that Service). To the extent
that provision of these services employs the Peering System, the Parties
will include in their agreements with their end-users terms and
conditions consistent with the terms of this GPA with respect to the
exclusion of warranties, limitation of liability and Acceptable Use
Policy. In no event may a Participant extend the warranty described in
Section 12 in this GPA to any end-users.
16. INDEMNIFICATION. Each Participant agrees to defend, indemnify and
hold harmless the other Participant or third-party beneficiaries to this
GPA (including their affiliates, successors, assigns, agents and
representatives and their respective officers, directors and employees)
from and against any and all actions, suits, proceedings,
investigations, demands, claims, judgments, liabilities, obligations,
liens, losses, damages, expenses (including, without limitation,
attorneys' fees) and any other fees arising out of or relating to (i)
personal injury or property damage caused by that Participant, its
employees, agents, servants, or other representatives; (ii) any act or
omission by the Participant, its employees, agents, servants or other
representatives, including, but not limited to, unauthorized
representations or warranties made by the Participant; or (iii) any
breach by the Participant of any of the terms or conditions of this GPA.
17. THIRD PARTY BENEFICIARIES. This GPA is intended to benefit those
Participants who have executed the GPA and who are in the Peering
System. It is the intent of the Parties to this GPA to give to those
Participants who are in the Peering System standing to bring any
necessary legal action to enforce the terms of this GPA.
18. TERMINATION. Any Participant may terminate this GPA at any time,
with or without cause. A Participant that terminates must immediately
cease to Propagate.
19. CHOICE OF LAW. This GPA and the rights and duties of the Parties
hereto shall be construed and determined in accordance with the internal
laws of the State of New York, United States of America, without regard
to its conflict of laws principles and without application of the United
Nations Convention on Contracts for the International Sale of Goods.
20. DISPUTE RESOLUTION. Unless otherwise agreed in writing, the
exclusive procedure for handling disputes shall be as set forth herein.
Notwithstanding such procedures, any Participant may, at any time, seek
injunctive relief in addition to the process described below.
(a) Prior to mediation or arbitration the disputing Participants
shall seek informal resolution of disputes. The process shall be
initiated with written notice of one Participant to the other
describing the dispute with reasonable particularity followed
with a written response within ten (10) days of receipt of
notice. Each Participant shall promptly designate an executive
with requisite authority to resolve the dispute. The informal
procedure shall commence within ten (10) days of the date of
response. All reasonable requests for non-privileged information
reasonably related to the dispute shall be honored. If the
dispute is not resolved within thirty (30) days of commencement
of the procedure either Participant may proceed to mediation or
arbitration pursuant to the rules set forth in (b) or (c) below.
(b) If the dispute has not been resolved pursuant to (a) above or,
if the disputing Participants fail to commence informal dispute
resolution pursuant to (a) above, either Participant may, in
writing and within twenty (20) days of the response date noted
in (a) above, ask the other Participant to participate in a one
(1) day mediation with an impartial mediator, and the other
Participant shall do so. Each Participant will bear its own
expenses and an equal share of the fees of the mediator. If the
mediation is not successful the Participants may proceed with
arbitration pursuant to (c) below.
(c) If the dispute has not been resolved pursuant to (a) or (b)
above, the dispute shall be promptly referred, no later than one
(1) year from the date of original notice and subject to
applicable statute of limitations, to binding arbitration in
accordance with the UNCITRAL Arbitration Rules in effect on the
date of this contract. The appointing authority shall be the
International Centre for Dispute Resolution. The case shall be
administered by the International Centre for Dispute Resolution
under its Procedures for Cases under the UNCITRAL Arbitration
Rules. Each Participant shall bear its own expenses and shall
share equally in fees of the arbitrator. All arbitrators shall
have substantial experience in information technology and/or in
the telecommunications business and shall be selected by the
disputing participants in accordance with UNCITRAL Arbitration
Rules. If any arbitrator, once selected is unable or unwilling
to continue for any reason, replacement shall be filled via the
process described above and a re-hearing shall be conducted. The
disputing Participants will provide each other with all
requested documents and records reasonably related to the
dispute in a manner that will minimize the expense and
inconvenience of both parties. Discovery will not include
depositions or interrogatories except as the arbitrators
expressly allow upon a showing of need. If disputes arise
concerning discovery requests, the arbitrators shall have sole
and complete discretion to resolve the disputes. The parties and
arbitrator shall be guided in resolving discovery disputes by
the Federal Rules of Civil Procedure. The Participants agree
that time of the essence principles shall guide the hearing and
that the arbitrator shall have the right and authority to issue
monetary sanctions in the event of unreasonable delay. The
arbitrator shall deliver a written opinion setting forth
findings of fact and the rationale for the award within thirty
(30) days following conclusion of the hearing. The award of the
arbitrator, which may include legal and equitable relief, but
which may not include punitive damages, will be final and
binding upon the disputing Participants, and judgment may be
entered upon it in accordance with applicable law in any court
having jurisdiction thereof. In addition to award the
arbitrator shall have the discretion to award the prevailing
Participant all or part of its attorneys' fees and costs,
including fees associated with arbitrator, if the arbitrator
determines that the positions taken by the other Participant on
material issues of the dispute were without substantial
foundation. Any conflict between the UNCITRAL Arbitration Rules
and the provisions of this GPA shall be controlled by this GPA.
21. INTEGRATED AGREEMENT. This GPA, constitutes the complete
integrated agreement between the parties concerning the subject matter
hereof. All prior and contemporaneous agreements, understandings,
negotiations or representations, whether oral or in writing, relating to
the subject matter of this GPA are superseded and canceled in their
entirety.
22. WAIVER. No waiver of any of the provisions of this GPA shall be
deemed or shall constitute a waiver of any other provision of this GPA,
whether or not similar, nor shall such waiver constitute a continuing
waiver unless otherwise expressly so provided in writing. The failure
of either party to enforce at any time any of the provisions of this
GPA, or the failure to require at any time performance by either party
of any of the provisions of this GPA, shall in no way be construed to be
a present or future waiver of such provisions, nor in any way affect the
ability of a Participant to enforce each and every such provision
thereafter.
23. INDEPENDENT CONTRACTORS. Nothing in this GPA shall make the
Parties partners, joint venturers, or otherwise associated in or with
the business of the other. Parties are, and shall always remain,
independent contractors. No Participant shall be liable for any debts,
accounts, obligations, or other liabilities of the other Participant,
its agents or employees. No party is authorized to incur debts or other
obligations of any kind on the part of or as agent for the other. This
GPA is not a franchise agreement and does not create a franchise
relationship between the parties, and if any provision of this GPA is
deemed to create a franchise between the parties, then this GPA shall
automatically terminate.
24. CAPTIONS AND HEADINGS. The captions and headings used in this GPA
are used for convenience only and are not to be given any legal effect.
25. EXECUTION. This GPA may be executed in counterparts, each of which
so executed will be deemed to be an original and such counterparts
together will constitute one and the same Agreement. The Parties shall
transmit to each other a signed copy of the GPA by any means that
faithfully reproduces the GPA along with the Signature. For purposes of
this GPA, the term "signature" shall include digital signatures as
defined by the jurisdiction of the Participant signing the GPA.
Exhibit A
Weight Range Requirements
0-99 May only be used under authorization of Owner
100-199 May only be used by the Owner's service
provider, regardless of authorization.
200-299 Reserved -- do not use for e164 context.
300-399 May only be used by the owner of the code under
which the Owner's number is a part of.
400-499 May be used by any entity providing access via
direct connectivity to the Public Switched
Telephone Network.
500-599 May be used by any entity providing access via
indirect connectivity to the Public Switched
Telephone Network (e.g. Via another VoIP
provider)
600- Reserved-- do not use for e164 context.
Participant Participant
Company:
Address:
Email:
_________________________ _________________________
Authorized Signature Authorized Signature
Name:
END OF GENERAL PEERING AGREEMENT
------------------------------------------------
How to Peer using this GPA If you wish to exchange routing information
with parties using the e164 DUNDi context, all you must do is execute
this GPA with any member of the Peering System and you will become a
member of the Peering System and be able to make Routes available in
accordance with this GPA.
DUNDi, IAX, Asterisk and GPA are trademarks of Digium, Inc.
\end{verbatim}

10
doc/README.txt Normal file
View File

@ -0,0 +1,10 @@
The vast majority of the Asterisk project documentation has been moved to the
project wiki:
http://wiki.asterisk.org/
Asterisk release tarballs contain an export of the wiki in PDF and plain text
form, which you can find in:
doc/AST.pdf
doc/AST.txt

View File

@ -1,189 +0,0 @@
================
Advice of Charge
================
Written by: David Vossel
Initial version: 04-19-2010
Email: dvossel@digium.com
This document is designed to give an overview of how to configure and
generate Advice of Charge along with a detailed explanation of how each
option works.
--------------------------------------
| READ THIS FIRST |
--------------------------------------
PLEASE REPORT ANY ISSUES ENCOUNTERED WHILE USING AOC. This feature
has had very little community feedback so far. If you are using this
feature please share with us any problems you are having and any
improvements that could make this feature more useful. Thank you!
--------------------------------------
| Terminology |
--------------------------------------
AOC: Advice of Charge
AOC-S: Advice of Charge message sent at the beginning of a call during
call setup. This message contains a list of rates associated with the
call.
AOC-D: Advice of Charge message sent during the call. This message
is typically used to update the endpoint with the current call charge.
AOC-E: Advice of Charge message sent at the end of a call. This
message is used to indicate to the endpoint the final call charge.
AMI: Asterisk Manager Interface. This interface is used to generate
AOC messages and listen for AOC events.
--------------------------------------
| AOC in chan_dahdi |
--------------------------------------
----- LibPRI Support:
ETSI, or euroisdn, is the only switchtype that LibPRI currently supports
for AOC.
----- Enable AOC Pass-through in chan_dahdi
To enable AOC pass-through between the ISDN and Asterisk use the
'aoc_enable' config option. This option allows for any combination
of AOC-S, AOC-D, and AOC-E to be enabled or disabled.
For example:
aoc_enable=s,d,e ; enables pass-through of AOC-S, AOC-D, and AOC-E
aoc_enable=s,d ; enables pass-through of AOC-S and AOC-D. Rejects
; AOC-E and AOC-E request messages
Since AOC messages are often transported on facility messages, the
'facilityenable' option must be enabled as well to fully support AOC
pass-through.
----- Handling AOC-E in chan_dahdi
Whenever a dahdi channel receives an AOC-E message from Asterisk, it
stores that message to deliver it at the appropriate time during call
termination. This means that if two AOC-E messages are received on the
same call, the last one will override the first one and only one AOC-E
message will be sent during call termination.
There are some tricky situations involving the final AOC-E message. During
a bridged call, if the endpoint receiving the AOC messages terminates
the call before the endpoint delivering the AOC does, the final AOC-E
message sent by the sending side during termination will never make it to
the receiving end because Asterisk will have already torn down that channel.
This is where the chan_dahdi.conf 'aoce_delayhangup' option comes into play.
By enabling 'aoce_delayhangup', anytime a hangup is initiated by the
ISDN side of an Asterisk channel, instead of hanging up the channel,
the channel sends a unique internal AOC-E termination request to its bridge
channel. This indicates it is about to hangup and wishes to receive the
final AOC-E message from the bridged channel before completely tearing
down. If the bridged channel knows what to do with this AOC-E termination
request, it will do whatever is necessary to indicate to its endpoint that
the call is being terminated without actually hanging up the Asterisk channel.
This allows the final AOC-E message to come in and be sent across the bridge
while both channels are still up. If the channel delaying its hangup for
the final AOC-E message times out, the call will be torn down just as it
normally would. In chan_dahdi the timeout period is 1/2 the T305 timer
which by default is 15 seconds.
'aoce_delayhangup' currently only works when both bridged channels are
dahdi_channels. If a SIP channel receives an AOC-E termination request, it
just responds by immediately hanging up the channel. Using this option when
bridged to any channel technology besides SIP or DAHDI will result in the
15 second timeout period before tearing down the call completely.
----- Requesting AOC services
AOC can be requested on a call by call basis using the DAHDI dialstring
option, A(). The A() option takes in 's', 'd', and 'e' parameters which
represent the three types of AOC messages, AOC-S, AOC-D, and AOC-E. By using
this option Asterisk will indicate to the endpoint during call setup that it
wishes to receive the specified forms of AOC during the call.
Example Usage in extensions.conf
exten => 1111,1,Dial(DAHDI/g1/1112/A(s,d,e) ; requests AOC-S, AOC-D, and AOC-E on
; call setup
exten => 1111,1,Dial(DAHDI/g1/1112/A(d,e) ; requests only AOC-D, and AOC-E on
; call setup
--------------------------------------
| AOC in chan_sip |
--------------------------------------
Asterisk supports a very basic way of sending AOC on a SIP channel to Snom
phones using an AOC specification designed by Snom. This support is limited
to the sending of AOC-D and AOC-E pass-through messages. No support for
AOC-E on call termination is present, so if the Snom endpoint receiving the
AOC messages from Asterisk terminates the call, the channel will be torn
down before the phone can receive the final AOC-E message.
To enable passthrough of AOC messages via the snom specification, use
the 'snom_aoc_enabled' option in sip.conf.
--------------------------------------
| Generate AOC Messages via AMI |
--------------------------------------
Asterisk supports a way to generate AOC messages on a channel via
the AMI action AOCMessage. At the moment the AOCMessage action is limited
to AOC-D and AOC-E message generation. There are some limitations
involved with delivering the final AOC-E message as well. The AOCMessage
action has its own detailed parameter documentation so this discussion will
focus on higher level use. When generating AOC messages on a Dahdi channel
first make sure the appropriate chan_dahdi.conf options are enabled. Without
enabling 'aoc_enable' correctly for pass-through the AOC messages will never
make it out the pri. The same goes with SIP, the 'snom_aoc_enabled' option
must be configured before messages can successfully be set to the endpoint.
----- AOC-D Message Generation
AOC-D message generation can happen anytime throughout the call. This
message type is very straight forward.
Example: AOCMessage action generating AOC-D currency message with Success
response.
Action: AOCMessage
Channel: DAHDI/i1/1111-1
MsgType: d
ChargeType: Currency
CurrencyAmount: 16
CurrencyName: USD
CurrencyMultiplier: OneThousandth
AOCBillingId: Normal
ActionID: 1234
Response: Success
ActionID: 1234
Message: AOC Message successfully queued on channel
----- AOC-E Message Generation
AOC-E messages are sent during call termination and represent the final charge
total for the call. Since Asterisk call termination results in the channel
being destroyed, it is currently not possible for the AOCMessage AMI action to
be used to send the final AOC-E message on call hangup. There is however a
work around for this issue that can be used for Dahdi channels. By default
chan_dahdi saves any AOC-E message it receives from Asterisk during a call and
waits to deliver that message during call termination. If multiple AOC-E messages
are received from Asterisk on the same Dahdi channel, only the last message received
is stored for delivery. This means that each new AOC-E message received on the
channel overrides the previous one. Knowing this the final AOC-E message can be
continually updated on a Dahdi channel until call termination occurs allowing
the last update to be sent on hangup. This method is only as accurate as the
intervals in which it is updated, but allows some form of AOC-E to be generated.
Example: AOCMessage action generating AOC-E unit message with Success response.
Action: AOCMessage
Channel: DAHDI/i1/1111-1
MsgType: e
ChargeType: Unit
UnitAmount(0): 111
UnitType(0): 6
UnitAmount(1): 222
UnitType(1): 5
UnitAmount(2): 333
UnitType(3): 4
UnitAmount(4): 444
AOCBillingId: Normal
ActionID: 1234
Response: Success
ActionID: 1234
Message: AOC Message successfully queued on channel

View File

@ -1,778 +0,0 @@
ASTERISK-MIB DEFINITIONS ::= BEGIN
IMPORTS
OBJECT-TYPE, MODULE-IDENTITY, Integer32, Counter32, TimeTicks,
Unsigned32, Gauge32
FROM SNMPv2-SMI
TEXTUAL-CONVENTION, DisplayString, TruthValue
FROM SNMPv2-TC
digium
FROM DIGIUM-MIB;
asterisk MODULE-IDENTITY
LAST-UPDATED "200806202025Z"
ORGANIZATION "Digium, Inc."
CONTACT-INFO
"Mark A. Spencer
Postal: Digium, Inc.
445 Jan Davis Drive
Huntsville, AL 35806
USA
Tel: +1 256 428 6000
Email: markster@digium.com
Thorsten Lockert
Postal: Voop AS
Boehmergaten 42
NO-5057 Bergen
Norway
Tel: +47 5598 7200
Email: tholo@voop.no"
DESCRIPTION
"Asterisk is an Open Source PBX. This MIB defined
objects for managing Asterisk instances."
REVISION "200806202025Z"
DESCRIPTION
"smilint police --
Add missing imports; fix initial capitalization
of enumeration elements; add missing range
restrictions for Integer32 indices, correct
spelling of astChanCidANI in its definition.
Addresses bug 12905. - jeffg@opennms.org"
REVISION "200708211450Z"
DESCRIPTION
"Add total and current call counter statistics."
REVISION "200603061840Z"
DESCRIPTION
"Change audio codec identification from 3kAudio to
Audio3k to conform better with specification.
Expand on contact information."
REVISION "200602041900Z"
DESCRIPTION
"Initial published revision."
::= { digium 1 }
asteriskVersion OBJECT IDENTIFIER ::= { asterisk 1 }
asteriskConfiguration OBJECT IDENTIFIER ::= { asterisk 2 }
asteriskModules OBJECT IDENTIFIER ::= { asterisk 3 }
asteriskIndications OBJECT IDENTIFIER ::= { asterisk 4 }
asteriskChannels OBJECT IDENTIFIER ::= { asterisk 5 }
-- asteriskVersion
astVersionString OBJECT-TYPE
SYNTAX DisplayString
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Text version string of the version of Asterisk that
the SNMP Agent was compiled to run against."
::= { asteriskVersion 1 }
astVersionTag OBJECT-TYPE
SYNTAX Unsigned32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"SubVersion revision of the version of Asterisk that
the SNMP Agent was compiled to run against -- this is
typically 0 for release-versions of Asterisk."
::= { asteriskVersion 2 }
-- asteriskConfiguration
astConfigUpTime OBJECT-TYPE
SYNTAX TimeTicks
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Time ticks since Asterisk was started."
::= { asteriskConfiguration 1 }
astConfigReloadTime OBJECT-TYPE
SYNTAX TimeTicks
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Time ticks since Asterisk was last reloaded."
::= { asteriskConfiguration 2 }
astConfigPid OBJECT-TYPE
SYNTAX Integer32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"The process id of the running Asterisk process."
::= { asteriskConfiguration 3 }
astConfigSocket OBJECT-TYPE
SYNTAX DisplayString
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"The control socket for giving Asterisk commands."
::= { asteriskConfiguration 4 }
astConfigCallsActive OBJECT-TYPE
SYNTAX Gauge32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"The number of calls currently active on the Asterisk PBX."
::= { asteriskConfiguration 5 }
astConfigCallsProcessed OBJECT-TYPE
SYNTAX Counter32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"The total number of calls processed through the Asterisk PBX since last
restart."
::= { asteriskConfiguration 6 }
-- asteriskModules
astNumModules OBJECT-TYPE
SYNTAX Integer32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of modules currently loaded into Asterisk."
::= { asteriskModules 1 }
-- asteriskIndications
astNumIndications OBJECT-TYPE
SYNTAX Integer32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of indications currently defined in Asterisk."
::= { asteriskIndications 1 }
astCurrentIndication OBJECT-TYPE
SYNTAX DisplayString
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Default indication zone to use."
::= { asteriskIndications 2 }
astIndicationsTable OBJECT-TYPE
SYNTAX SEQUENCE OF AstIndicationsEntry
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION
"Table with all the indication zones currently know to
the running Asterisk instance."
::= { asteriskIndications 3 }
astIndicationsEntry OBJECT-TYPE
SYNTAX AstIndicationsEntry
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION
"Information about a single indication zone."
INDEX { astIndIndex }
::= { astIndicationsTable 1 }
AstIndicationsEntry ::= SEQUENCE {
astIndIndex Integer32,
astIndCountry DisplayString,
astIndAlias DisplayString,
astIndDescription DisplayString
}
astIndIndex OBJECT-TYPE
SYNTAX Integer32 (1 .. 2147483647)
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Numerical index into the table of indication zones."
::= { astIndicationsEntry 1 }
astIndCountry OBJECT-TYPE
SYNTAX DisplayString
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Country for which the indication zone is valid,
typically this is the ISO 2-letter code of the country."
::= { astIndicationsEntry 2 }
astIndAlias OBJECT-TYPE
SYNTAX DisplayString
MAX-ACCESS read-only
STATUS current
DESCRIPTION
""
::= { astIndicationsEntry 3 }
astIndDescription OBJECT-TYPE
SYNTAX DisplayString
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Description of the indication zone, usually the full
name of the country it is valid for."
::= { astIndicationsEntry 4 }
-- asteriskChannels
astNumChannels OBJECT-TYPE
SYNTAX Gauge32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Current number of active channels."
::= { asteriskChannels 1 }
astChanTable OBJECT-TYPE
SYNTAX SEQUENCE OF AstChanEntry
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION
"Table with details of the currently active channels
in the Asterisk instance."
::= { asteriskChannels 2 }
astChanEntry OBJECT-TYPE
SYNTAX AstChanEntry
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION
"Details of a single channel."
INDEX { astChanIndex }
::= { astChanTable 1 }
AstChanEntry ::= SEQUENCE {
astChanIndex Integer32,
astChanName DisplayString,
astChanLanguage DisplayString,
astChanType DisplayString,
astChanMusicClass DisplayString,
astChanBridge DisplayString,
astChanMasq DisplayString,
astChanMasqr DisplayString,
astChanWhenHangup TimeTicks,
astChanApp DisplayString,
astChanData DisplayString,
astChanContext DisplayString,
astChanMacroContext DisplayString,
astChanMacroExten DisplayString,
astChanMacroPri Integer32,
astChanExten DisplayString,
astChanPri Integer32,
astChanAccountCode DisplayString,
astChanForwardTo DisplayString,
astChanUniqueId DisplayString,
astChanCallGroup Unsigned32,
astChanPickupGroup Unsigned32,
astChanState INTEGER,
astChanMuted TruthValue,
astChanRings Integer32,
astChanCidDNID DisplayString,
astChanCidNum DisplayString,
astChanCidName DisplayString,
astChanCidANI DisplayString,
astChanCidRDNIS DisplayString,
astChanCidPresentation DisplayString,
astChanCidANI2 Integer32,
astChanCidTON Integer32,
astChanCidTNS Integer32,
astChanAMAFlags INTEGER,
astChanADSI INTEGER,
astChanToneZone DisplayString,
astChanHangupCause INTEGER,
astChanVariables DisplayString,
astChanFlags BITS,
astChanTransferCap INTEGER
}
astChanIndex OBJECT-TYPE
SYNTAX Integer32 (1 .. 2147483647)
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Index into the channel table."
::= { astChanEntry 1 }
astChanName OBJECT-TYPE
SYNTAX DisplayString
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Name of the current channel."
::= { astChanEntry 2 }
astChanLanguage OBJECT-TYPE
SYNTAX DisplayString
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Which language the current channel is configured to
use -- used mainly for prompts."
::= { astChanEntry 3 }
astChanType OBJECT-TYPE
SYNTAX DisplayString
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Underlying technology for the current channel."
::= { astChanEntry 4 }
astChanMusicClass OBJECT-TYPE
SYNTAX DisplayString
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Music class to be used for Music on Hold for this
channel."
::= { astChanEntry 5 }
astChanBridge OBJECT-TYPE
SYNTAX DisplayString
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Which channel this channel is currently bridged (in a
conversation) with."
::= { astChanEntry 6 }
astChanMasq OBJECT-TYPE
SYNTAX DisplayString
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Channel masquerading for us."
::= { astChanEntry 7 }
astChanMasqr OBJECT-TYPE
SYNTAX DisplayString
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Channel we are masquerading for."
::= { astChanEntry 8 }
astChanWhenHangup OBJECT-TYPE
SYNTAX TimeTicks
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"How long until this channel will be hung up."
::= { astChanEntry 9 }
astChanApp OBJECT-TYPE
SYNTAX DisplayString
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Current application for the channel."
::= { astChanEntry 10 }
astChanData OBJECT-TYPE
SYNTAX DisplayString
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Arguments passed to the current application."
::= { astChanEntry 11 }
astChanContext OBJECT-TYPE
SYNTAX DisplayString
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Current extension context."
::= { astChanEntry 12 }
astChanMacroContext OBJECT-TYPE
SYNTAX DisplayString
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Current macro context."
::= { astChanEntry 13 }
astChanMacroExten OBJECT-TYPE
SYNTAX DisplayString
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Current macro extension."
::= { astChanEntry 14 }
astChanMacroPri OBJECT-TYPE
SYNTAX Integer32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Current macro priority."
::= { astChanEntry 15 }
astChanExten OBJECT-TYPE
SYNTAX DisplayString
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Current extension."
::= { astChanEntry 16 }
astChanPri OBJECT-TYPE
SYNTAX Integer32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Current priority."
::= { astChanEntry 17 }
astChanAccountCode OBJECT-TYPE
SYNTAX DisplayString
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Account Code for billing."
::= { astChanEntry 18 }
astChanForwardTo OBJECT-TYPE
SYNTAX DisplayString
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Where to forward to if asked to dial on this
interface."
::= { astChanEntry 19 }
astChanUniqueId OBJECT-TYPE
SYNTAX DisplayString
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Unique Channel Identifier."
::= { astChanEntry 20 }
astChanCallGroup OBJECT-TYPE
SYNTAX Unsigned32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Call Group."
::= { astChanEntry 21 }
astChanPickupGroup OBJECT-TYPE
SYNTAX Unsigned32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Pickup Group."
::= { astChanEntry 22 }
astChanState OBJECT-TYPE
SYNTAX INTEGER {
stateDown(0),
stateReserved(1),
stateOffHook(2),
stateDialing(3),
stateRing(4),
stateRinging(5),
stateUp(6),
stateBusy(7),
stateDialingOffHook(8),
statePreRing(9)
}
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Channel state."
::= { astChanEntry 23 }
astChanMuted OBJECT-TYPE
SYNTAX TruthValue
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Transmission of voice data has been muted."
::= { astChanEntry 24 }
astChanRings OBJECT-TYPE
SYNTAX Integer32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of rings so far."
::= { astChanEntry 25 }
astChanCidDNID OBJECT-TYPE
SYNTAX DisplayString
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Dialled Number ID."
::= { astChanEntry 26 }
astChanCidNum OBJECT-TYPE
SYNTAX DisplayString
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Caller Number."
::= { astChanEntry 27 }
astChanCidName OBJECT-TYPE
SYNTAX DisplayString
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Caller Name."
::= { astChanEntry 28 }
astChanCidANI OBJECT-TYPE
SYNTAX DisplayString
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"ANI"
::= { astChanEntry 29 }
astChanCidRDNIS OBJECT-TYPE
SYNTAX DisplayString
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Redirected Dialled Number Service."
::= { astChanEntry 30 }
astChanCidPresentation OBJECT-TYPE
SYNTAX DisplayString
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number Presentation/Screening."
::= { astChanEntry 31 }
astChanCidANI2 OBJECT-TYPE
SYNTAX Integer32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"ANI 2 (info digit)."
::= { astChanEntry 32 }
astChanCidTON OBJECT-TYPE
SYNTAX Integer32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Type of Number."
::= { astChanEntry 33 }
astChanCidTNS OBJECT-TYPE
SYNTAX Integer32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Transit Network Select."
::= { astChanEntry 34 }
astChanAMAFlags OBJECT-TYPE
SYNTAX INTEGER {
default(0),
omit(1),
billing(2),
documentation(3)
}
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"AMA Flags."
::= { astChanEntry 35 }
astChanADSI OBJECT-TYPE
SYNTAX INTEGER {
unknown(0),
available(1),
unavailable(2),
offHookOnly(3)
}
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Whether or not ADSI is detected on CPE."
::= { astChanEntry 36 }
astChanToneZone OBJECT-TYPE
SYNTAX DisplayString
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Indication zone to use for channel."
::= { astChanEntry 37 }
astChanHangupCause OBJECT-TYPE
SYNTAX INTEGER {
notDefined(0),
unregistered(3),
normal(16),
busy(17),
noAnswer(19),
congestion(34),
failure(38),
noSuchDriver(66)
}
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Why is the channel hung up."
::= { astChanEntry 38 }
astChanVariables OBJECT-TYPE
SYNTAX DisplayString
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Channel Variables defined for this channel."
::= { astChanEntry 39 }
astChanFlags OBJECT-TYPE
SYNTAX BITS {
wantsJitter(0),
deferDTMF(1),
writeInterrupt(2),
blocking(3),
zombie(4),
exception(5),
musicOnHold(6),
spying(7),
nativeBridge(8),
autoIncrementingLoop(9)
}
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Flags set on this channel."
::= { astChanEntry 40 }
astChanTransferCap OBJECT-TYPE
SYNTAX INTEGER {
speech(0),
digital(8),
restrictedDigital(9),
audio3k(16),
digitalWithTones(17),
video(24)
}
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Transfer Capabilities for this channel."
::= { astChanEntry 41 }
astNumChanTypes OBJECT-TYPE
SYNTAX Integer32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of channel types (technologies) supported."
::= { asteriskChannels 3 }
astChanTypeTable OBJECT-TYPE
SYNTAX SEQUENCE OF AstChanTypeEntry
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION
"Table with details of the supported channel types."
::= { asteriskChannels 4 }
astChanTypeEntry OBJECT-TYPE
SYNTAX AstChanTypeEntry
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION
"Information about a technology we support, including
how many channels are currently using this technology."
INDEX { astChanTypeIndex }
::= { astChanTypeTable 1 }
AstChanTypeEntry ::= SEQUENCE {
astChanTypeIndex Integer32,
astChanTypeName DisplayString,
astChanTypeDesc DisplayString,
astChanTypeDeviceState Integer32,
astChanTypeIndications Integer32,
astChanTypeTransfer Integer32,
astChanTypeChannels Gauge32
}
astChanTypeIndex OBJECT-TYPE
SYNTAX Integer32 (1 .. 2147483647)
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Index into the table of channel types."
::= { astChanTypeEntry 1 }
astChanTypeName OBJECT-TYPE
SYNTAX DisplayString
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Unique name of the technology we are describing."
::= { astChanTypeEntry 2 }
astChanTypeDesc OBJECT-TYPE
SYNTAX DisplayString
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Description of the channel type (technology)."
::= { astChanTypeEntry 3 }
astChanTypeDeviceState OBJECT-TYPE
SYNTAX TruthValue
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Whether the current technology can hold device states."
::= { astChanTypeEntry 4 }
astChanTypeIndications OBJECT-TYPE
SYNTAX TruthValue
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Whether the current technology supports progress indication."
::= { astChanTypeEntry 5 }
astChanTypeTransfer OBJECT-TYPE
SYNTAX TruthValue
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Whether the current technology supports transfers, where
Asterisk can get out from inbetween two bridged channels."
::= { astChanTypeEntry 6 }
astChanTypeChannels OBJECT-TYPE
SYNTAX Gauge32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of active channels using the current technology."
::= { astChanTypeEntry 7 }
astChanScalars OBJECT IDENTIFIER ::= { asteriskChannels 5 }
astNumChanBridge OBJECT-TYPE
SYNTAX Gauge32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of channels currently in a bridged state."
::= { astChanScalars 1 }
END

View File

@ -1,277 +0,0 @@
===============================================================================
===
=== Collecting Backtrace Information
===
=== Last updated: 2010-04-12
===============================================================================
This document is intended to provide information on how to obtain the
backtraces required on the asterisk bug tracker, available at
https://issues.asterisk.org.
-------------------------------------------------------------------------------
--- Overview
-------------------------------------------------------------------------------
The backtrace information is required by developers to help fix problem with
bugs of any kind. Backtraces provide information about what was wrong when a
program crashed; in our case, Asterisk.
-------------------------------------------------------------------------------
--- Preparing Asterisk To Produce Core Files On Crash
-------------------------------------------------------------------------------
First of all, when you start Asterisk, you MUST start it with option
-g. This tells Asterisk to produce a core file if it crashes.
If you start Asterisk with the safe_asterisk script, it automatically
starts using the option -g.
If you're not sure if Asterisk is running with the -g option, type the
following command in your shell:
debian:/tmp# ps aux | grep asterisk
root 17832 0.0 1.2 2348 788 pts/1 S Aug12 0:00 /bin/sh /usr/sbin/safe_asterisk
root 26686 0.0 2.8 15544 1744 pts/1 S Aug13 0:02 asterisk -vvvg -c
[...]
The interesting information is located in the last column.
Second, your copy of Asterisk must have been built without
optimization or the backtrace will be (nearly) unusable. This can be
done by selecting the 'DONT_OPTIMIZE' option in the Compiler Flags
submenu in the 'make menuselect' tree before building Asterisk.
Running a production server with DONT_OPTIMIZE is generally safe.
You'll notice the binary files may be a bit larger, but in terms of
Asterisk performance, and impact should be negligible.
After Asterisk crashes, a core file will be "dumped" in your /tmp/
directory. To make sure it's really there, you can just type the
following command in your shell:
debian:/tmp# ls -l /tmp/core.*
-rw------- 1 root root 10592256 Aug 12 19:40 /tmp/core.26252
-rw------- 1 root root 9924608 Aug 12 20:12 /tmp/core.26340
-rw------- 1 root root 10862592 Aug 12 20:14 /tmp/core.26374
-rw------- 1 root root 9105408 Aug 12 20:19 /tmp/core.26426
-rw------- 1 root root 9441280 Aug 12 20:20 /tmp/core.26462
-rw------- 1 root root 8331264 Aug 13 00:32 /tmp/core.26647
debian:/tmp#
In the event that there are multiple core files present (as in the
above example), it is important to look at the file timestamps in
order to determine which one you really intend to look at.
-------------------------------------------------------------------------------
--- Getting Information After A Crash
-------------------------------------------------------------------------------
There are two kind of backtraces (aka 'bt') which are useful: bt and bt full.
Now that we've verified the core file has been written to disk, the final part
is to extract 'bt' from the core file. Core files are pretty big, don't be
scared, it's normal.
******************************************************************************
*** NOTE: Don't attach core files on the bug tracker as they are only useful *
*** on the machine they were generated on. We only need the output of *
*** the 'bt' and 'bt full.' *
******************************************************************************
For extraction, we use a really nice tool, called gdb. To verify that
you have gdb installed on your system:
debian:/tmp# gdb -v
GNU gdb 6.3-debian
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-linux".
debian:/tmp#
If you don't have gdb installed, go install gdb. You should be able to install
using something like: apt-get install gdb --or-- yum install gdb
Now load the core file in gdb with the following command. This will also save
the output of gdb to the /tmp/backtract.txt file.
# gdb -se "asterisk" -c /tmp/core.26252 | tee /tmp/backtrace.txt
******************************************************************************
*** TIP!
*** Just run the following command to get the output into the
*** backtrace.txt file, ready for uploading to the issue tracker. Be sure
*** to change the name of the core file to your actual core dump file:
***
*** gdb -se "asterisk" -ex "bt full" -ex "thread apply all bt" --batch -c /tmp/core.26252 > /tmp/backtrace.txt
***
******************************************************************************
[...]
(You would see a lot of output here.)
[...]
Reading symbols from /usr/lib/asterisk/modules/app_externalivr.so...done.
Loaded symbols for /usr/lib/asterisk/modules/app_externalivr.so
#0 0x29b45d7e in ?? ()
(gdb)
In order to make extracting the gdb output easier, you may wish to
turn on logging using "set logging on". This command will save all
output to the default file of gdb.txt, which in the end can be
uploaded as an attachment to the bug tracker.
Now at the gdb prompt, type: bt
You would see output similar to:
(gdb) bt
#0 0x29b45d7e in ?? ()
#1 0x08180bf8 in ?? ()
#2 0xbcdffa58 in ?? ()
#3 0x08180bf8 in ?? ()
#4 0xbcdffa60 in ?? ()
#5 0x08180bf8 in ?? ()
#6 0x180bf894 in ?? ()
#7 0x0bf80008 in ?? ()
#8 0x180b0818 in ?? ()
#9 0x08068008 in ast_stopstream (tmp=0x40758d38) at file.c:180
#10 0x000000a0 in ?? ()
#11 0x000000a0 in ?? ()
#12 0x00000000 in ?? ()
#13 0x407513c3 in confcall_careful_stream (conf=0x8180bf8, filename=0x8181de8 "DAHDI/pseudo-1324221520") at app_meetme.c:262
#14 0x40751332 in streamconfthread (args=0x8180bf8) at app_meetme.c:1965
#15 0xbcdffbe0 in ?? ()
#16 0x40028e51 in pthread_start_thread () from /lib/libpthread.so.0
#17 0x401ec92a in clone () from /lib/libc.so.6
(gdb)
The bt's output is the information that we need on the bug tracker.
Now do a bt full as follows:
(gdb) bt full
#0 0x29b45d7e in ?? ()
No symbol table info available.
#1 0x08180bf8 in ?? ()
No symbol table info available.
#2 0xbcdffa58 in ?? ()
No symbol table info available.
#3 0x08180bf8 in ?? ()
No symbol table info available.
#4 0xbcdffa60 in ?? ()
No symbol table info available.
#5 0x08180bf8 in ?? ()
No symbol table info available.
#6 0x180bf894 in ?? ()
No symbol table info available.
#7 0x0bf80008 in ?? ()
No symbol table info available.
#8 0x180b0818 in ?? ()
No symbol table info available.
#9 0x08068008 in ast_stopstream (tmp=0x40758d38) at file.c:180
No locals.
#10 0x000000a0 in ?? ()
No symbol table info available.
#11 0x000000a0 in ?? ()
No symbol table info available.
#12 0x00000000 in ?? ()
No symbol table info available.
#13 0x407513c3 in confcall_careful_stream (conf=0x8180bf8, filename=0x8181de8 "DAHDI/pseudo-1324221520") at app_meetme.c:262
f = (struct ast_frame *) 0x8180bf8
trans = (struct ast_trans_pvt *) 0x0
#14 0x40751332 in streamconfthread (args=0x8180bf8) at app_meetme.c:1965
No locals.
#15 0xbcdffbe0 in ?? ()
No symbol table info available.
#16 0x40028e51 in pthread_start_thread () from /lib/libpthread.so.0
No symbol table info available.
#17 0x401ec92a in clone () from /lib/libc.so.6
No symbol table info available.
(gdb)
The final "extraction" would be to know all traces by all threads. Even if
Asterisk runs on the same thread for each call, it could have created some new
threads.
To make sure we have the correct information, just do:
(gdb) thread apply all bt
Thread 1 (process 26252):
#0 0x29b45d7e in ?? ()
#1 0x08180bf8 in ?? ()
#2 0xbcdffa58 in ?? ()
#3 0x08180bf8 in ?? ()
#4 0xbcdffa60 in ?? ()
#5 0x08180bf8 in ?? ()
#6 0x180bf894 in ?? ()
#7 0x0bf80008 in ?? ()
#8 0x180b0818 in ?? ()
#9 0x08068008 in ast_stopstream (tmp=0x40758d38) at file.c:180
#10 0x000000a0 in ?? ()
#11 0x000000a0 in ?? ()
#12 0x00000000 in ?? ()
#13 0x407513c3 in confcall_careful_stream (conf=0x8180bf8, filename=0x8181de8 "DAHDI/pseudo-1324221520") at app_meetme.c:262
#14 0x40751332 in streamconfthread (args=0x8180bf8) at app_meetme.c:1965
#15 0xbcdffbe0 in ?? ()
#16 0x40028e51 in pthread_start_thread () from /lib/libpthread.so.0
#17 0x401ec92a in clone () from /lib/libc.so.6
(gdb)
That output tells us crucial information about each thread.
-------------------------------------------------------------------------------
--- Getting Information For A Deadlock
-------------------------------------------------------------------------------
Whenever supplying information about a deadlock (i.e. when you run the
'core show locks' command on the Asterisk console), it is useful to also have
additional information about the threads. We can generate this information by
attaching to a running Asterisk process and gathering that information.
You can easily attach to a running Asterisk process, gather the output required
and then detach from the process all in a single step. Execute the following
command and upload the resulting backtrace-threads.txt file to the Asterisk
issue tracker:
gdb -ex "thread apply all bt" --batch /usr/sbin/asterisk `pidof asterisk` > /tmp/backtrace-threads.txt
Note that this gathers information from the running Asterisk process, so you
want to make sure you run this command immediately before or after gathering
the output of 'core show locks'. You can gather that information by running the
following command:
asterisk -rx "core show locks" > /tmp/core-show-locks.txt
-------------------------------------------------------------------------------
--- Verify Your Backtraces
-------------------------------------------------------------------------------
Before uploading your backtraces to the issue tracker, you should double check
to make sure the data you have is of use to the developers. Check your
backtrace files to make sure you're not seeing several of the following:
<value optimized out>
If you are, then you likely haven't compiled with DONT_OPTIMIZE. The impact of
DONT_OPTIMIZE is negligible on most systems. Be sure you've enabled the
DONT_OPTIMIZE flag within the Compiler Flags section of menuselect. After
doing so, be sure to run 'make install' and restart Asterisk.
-------------------------------------------------------------------------------
--- Uploading Your Information To The Issue Tracker
-------------------------------------------------------------------------------
You're now ready to upload your files to the Asterisk issue tracker (located at
https://issues.asterisk.org).
******************************************************************************
*** NOTE: Please ATTACH your output! DO NOT paste it as a note! *
******************************************************************************
If you have questions or comments regarding this documentation, feel free to
pass by the #asterisk-bugs channel on irc.freenode.net.

View File

@ -1,823 +0,0 @@
=================
Building Queues
=================
Written by: Leif Madsen
Initial version: 2010-01-14
In this article, we'll look at setting up a pair of queues in Asterisk called
'sales' and 'support'. These queues can be logged into by queue members, and
those members will also have the ability to pause and unpause themselves.
All configuration will be done in flat files on the system in order to maintain
simplicity in configuration.
Note that this documentation is based on Asterisk 1.6.2, and this is just one
approach to creating queues and the dialplan logic. You may create a better way,
and in that case, I would encourage you to submit it to the Asterisk issue
tracker at http://issues.asterisk.org for inclusion in Asterisk.
-------------------------------------
| Adding SIP Devices to Your Server |
-------------------------------------
The first thing we want to do is register a couple of SIP devices to our server.
These devices will be our agents that can login and out of the queues we'll
create later. Our naming convention will be to use MAC addresses as we want to
abstract the concepts of user (agent), device, and extension from each other.
In sip.conf, we add the following to the bottom of our file:
sip.conf
--------
[std-device](!)
type=peer
context=devices
host=dynamic
secret=s3CuR#p@s5
dtmfmode=rfc2833
disallow=all
allow=ulaw
[0004f2040001](std-device)
[0004f2040002](std-device)
What we're doing here is creating a [std-device] template and applying it to
a pair of peers that we'll register as 0004f2040001 and 0004f2040002; our
devices.
Then our devices can register to Asterisk. In my case I have a hard phone and
a soft phone registered. I can verify their connectivity by running 'sip show
peers'.
*CLI> sip show peers
Name/username Host Dyn Nat ACL Port Status
0004f2040001/0004f2040001 192.168.128.145 D 5060 Unmonitored
0004f2040002/0004f2040002 192.168.128.126 D 5060 Unmonitored
2 sip peers [Monitored: 0 online, 0 offline Unmonitored: 2 online, 0 offline]
----------------------------
| Configuring Device State |
----------------------------
Next, we need to configure our system to track the state of the devices. We do
this by defining a 'hint' in the dialplan which creates the ability for a device
subscription to be retained in memory. By default we can see there are no hints
registered in our system by running the 'core show hints' command.
*CLI> core show hints
There are no registered dialplan hint
We need to add the devices we're going to track to the extensions.conf file
under the [default] context which is the default configuration in sip.conf,
however we can change this to any context we want with the 'subscribecontext'
option.
Add the following lines to extensions.conf:
[default]
exten => 0004f2040001,hint,SIP/0004f2040001
exten => 0004f2040002,hint,SIP/0004f2040002
Then perform a 'dialplan reload' in order to reload the dialplan.
After reloading our dialplan, you can see the status of the devices with 'core
show hints' again.
*CLI> core show hints
-= Registered Asterisk Dial Plan Hints =-
0004f2040002@default : SIP/0004f2040002 State:Idle Watchers 0
0004f2040001@default : SIP/0004f2040001 State:Idle Watchers 0
----------------
- 2 hints registered
At this point, create an extension that you can dial that will play a prompt
that is long enough for you to go back to the Asterisk console to check the
state of your device while it is in use.
To do this, add the 555 extension to the [devices] context and make it playback
the tt-monkeys file.
extensions.conf
---------------
[devices]
exten => 555,1,Playback(tt-monkeys)
Dial that extension and then check the state of your device on the console.
*CLI> == Using SIP RTP CoS mark 5
-- Executing [555@devices:1] Playback("SIP/0004f2040001-00000001", "tt-monkeys") in new stack
-- <SIP/0004f2040001-00000001> Playing 'tt-monkeys.slin' (language 'en')
*CLI> core show hints
-= Registered Asterisk Dial Plan Hints =-
0004f2040002@default : SIP/0004f2040002 State:Idle Watchers 0
0004f2040001@default : SIP/0004f2040001 State:Idle Watchers 0
----------------
- 2 hints registered
Aha, we're not getting the device state correctly. There must be something else
we need to configure.
In sip.conf, we need to enable 'callcounter' in order to activate the ability
for Asterisk to monitor whether the device is in use or not. In versions prior
to 1.6.0 we needed to use 'call-limit' for this functionality, but call-limit
is now deprecated and is no longer necessary.
So, in sip.conf, in our [std-device] template, we need to add the callcounter
option.
sip.conf
--------
[std-device](!)
type=peer
context=devices
host=dynamic
secret=s3CuR#p@s5
dtmfmode=rfc2833
disallow=all
allow=ulaw
callcounter=yes ; <-- add this
Then reload chan_sip with 'sip reload' and perform our 555 test again. Dial 555
and then check the device state with 'core show hints'.
*CLI> == Using SIP RTP CoS mark 5
-- Executing [555@devices:1] Playback("SIP/0004f2040001-00000002", "tt-monkeys") in new stack
-- <SIP/0004f2040001-00000002> Playing 'tt-monkeys.slin' (language 'en')
*CLI> core show hints
-= Registered Asterisk Dial Plan Hints =-
0004f2040002@default : SIP/0004f2040002 State:Idle Watchers 0
0004f2040001@default : SIP/0004f2040001 State:InUse Watchers 0
----------------
- 2 hints registered
Note that now we have the correct device state when extension 555 is dialed,
showing that our device is InUse after dialing extension 555. This is important
when creating queues, otherwise our queue members would get multiple calls from
the queues.
-----------------------------
| Adding Queues to Asterisk |
-----------------------------
The next step is to add a couple of queues to Asterisk that we can assign queue
members into. For now we'll work with two queues; sales and support. Lets create
those queues now in queues.conf.
We'll leave the default settings that are shipped with queues.conf.sample in the
[general] section of queues.conf. See the queues.conf.sample file for more
information about each of the available options.
queues.conf
-----------
[general]
persistantmembers=yes
autofill=yes
monitor-type=MixMonitor
shared_lastcall=no
We can then define a [queue_template] that we'll assign to each of the queues
we create. These definitions can be overridden by each queue individually if you
reassign them under the [sales] or [support] headers. So under the [general]
section of your queues.conf file, add the following.
queues.conf
----------
[queue_template](!)
musicclass=default ; play [default] music
strategy=rrmemory ; use the Round Robin Memory strategy
joinempty=yes ; join the queue when no members available
leavewhenempty=no ; don't leave the queue no members available
ringinuse=no ; don't ring members when already InUse
[sales](queue_template)
; Sales queue
[support](queue_template)
; Support queue
After defining our queues, lets reload our app_queue.so module.
*CLI> module reload app_queue.so
-- Reloading module 'app_queue.so' (True Call Queueing)
== Parsing '/etc/asterisk/queues.conf': == Found
Then verify our queues loaded with 'queue show'.
*CLI> queue show
support has 0 calls (max unlimited) in 'rrmemory' strategy (0s holdtime, 0s talktime), W:0, C:0, A:0, SL:0.0% within 0s
No Members
No Callers
sales has 0 calls (max unlimited) in 'rrmemory' strategy (0s holdtime, 0s talktime), W:0, C:0, A:0, SL:0.0% within 0s
No Members
No Callers
------------------------
| Adding Queue Members |
------------------------
You'll notice that we have no queue members available to take calls from the
queues. We can add queue members from the Asterisk CLI with the 'queue add
member' command.
This is the format of the 'queue add member' command:
Usage: queue add member <channel> to <queue> [[[penalty <penalty>] as <membername>] state_interface <interface>]
Add a channel to a queue with optionally: a penalty, membername and a state_interface
The penalty, membername, and state_interface are all optional values. Special
attention should be brought to the 'state_interface' option for a member though.
The reason for state_interface is that if you're using a channel that does not
have device state itself (for example, if you were using the Local channel to
deliver a call to an end point) then you could assign the device state of a SIP
device to the pseudo channel. This allows the state of a SIP device to be
applied to the Local channel for correct device state information.
Lets add our device located at SIP/0004f2040001
*CLI> queue add member SIP/0004f2040001 to sales
Added interface 'SIP/0004f2040001' to queue 'sales'
Then lets verify our member was indeed added.
*CLI> queue show sales
sales has 0 calls (max unlimited) in 'rrmemory' strategy (0s holdtime, 0s talktime), W:0, C:0, A:0, SL:0.0% within 0s
Members:
SIP/0004f2040001 (dynamic) (Not in use) has taken no calls yet
No Callers
Now, if we dial our 555 extension, we should see that our member becomes InUse
within the queue.
*CLI> == Using SIP RTP CoS mark 5
-- Executing [555@devices:1] Playback("SIP/0004f2040001-00000001", "tt-monkeys") in new stack
-- <SIP/0004f2040001-00000001> Playing 'tt-monkeys.slin' (language 'en')
*CLI> queue show sales
sales has 0 calls (max unlimited) in 'rrmemory' strategy (0s holdtime, 0s talktime), W:0, C:0, A:0, SL:0.0% within 0s
Members:
SIP/0004f2040001 (dynamic) (In use) has taken no calls yet
No Callers
We can also remove our members from the queue using the 'queue remove' CLI
command.
*CLI> queue remove member SIP/0004f2040001 from sales
Removed interface 'SIP/0004f2040001' from queue 'sales'
Because we don't want to have to add queue members manually from the CLI, we
should create a method that allows queue members to login and out from their
devices. We'll do that in the next section.
But first, lets add an extension to our dialplan in order to permit people to
dial into our queues so calls can be delivered to our queue members.
extensions.conf
---------------
[devices]
exten => 555,1,Playback(tt-monkeys)
exten => 100,1,Queue(sales)
exten => 101,1,Queue(support)
Then reload the dialplan, and try calling extension 100 from SIP/0004f2040002,
which is the device we have not logged into the queue.
*CLI> dialplan reload
And now we call the queue at extension 100 which will ring our device at
SIP/0004f2040001.
*CLI> == Using SIP RTP CoS mark 5
-- Executing [100@devices:1] Queue("SIP/0004f2040002-00000005", "sales") in new stack
-- Started music on hold, class 'default', on SIP/0004f2040002-00000005
== Using SIP RTP CoS mark 5
-- SIP/0004f2040001-00000006 is ringing
We can see the device state has changed to Ringing while the device is ringing.
*CLI> queue show sales
sales has 1 calls (max unlimited) in 'rrmemory' strategy (2s holdtime, 3s talktime), W:0, C:1, A:1, SL:0.0% within 0s
Members:
SIP/0004f2040001 (dynamic) (Ringing) has taken 1 calls (last was 14 secs ago)
Callers:
1. SIP/0004f2040002-00000005 (wait: 0:03, prio: 0)
Our queue member then answers the phone.
*CLI> -- SIP/0004f2040001-00000006 answered SIP/0004f2040002-00000005
-- Stopped music on hold on SIP/0004f2040002-00000005
-- Native bridging SIP/0004f2040002-00000005 and SIP/0004f2040001-00000006
And we can see the queue member is now in use.
*CLI> queue show sales
sales has 0 calls (max unlimited) in 'rrmemory' strategy (3s holdtime, 3s talktime), W:0, C:1, A:1, SL:0.0% within 0s
Members:
SIP/0004f2040001 (dynamic) (In use) has taken 1 calls (last was 22 secs ago)
No Callers
Then the call is hung up.
*CLI> == Spawn extension (devices, 100, 1) exited non-zero on 'SIP/0004f2040002-00000005'
And we see that our queue member is available to take another call.
*CLI> queue show sales
sales has 0 calls (max unlimited) in 'rrmemory' strategy (3s holdtime, 4s talktime), W:0, C:2, A:1, SL:0.0% within 0s
Members:
SIP/0004f2040001 (dynamic) (Not in use) has taken 2 calls (last was 6 secs ago)
No Callers
--------------------------------
| Logging In and Out of Queues |
--------------------------------
In this section we'll show how to use the AddQueueMember() and
RemoveQueueMember() dialplan applications to login and out of queues. For more
information about the available options to AddQueueMember() and
RemoveQueueMember() use the 'core show application <app>' command from the CLI.
The following bit of dialplan is a bit long, but stick with it, and you'll see
that it isn't really all that bad. The gist of the dialplan is that it will
check to see if the active user (the device that is dialing the extension) is
currently logged into the queue extension that has been requested, and if logged
in, then will log them out; if not logged in, then they will be logged into the
queue.
We've updated the two lines we added in the previous section that allowed us to
dial the sales and support queues. We've abstracted this out a bit in order to
make it easier to add new queues in the future. This is done by adding the queue
names to a global variable, then utilizing the extension number dialed to look
up the queue name.
So we replace extension 100 and 101 with the following dialplan.
; Call any of the queues we've defined in the [globals] section.
exten => _1XX,1,Verbose(2,Call queue as configured in the QUEUE_${EXTEN} global variable)
exten => _1XX,n,Set(thisQueue=${GLOBAL(QUEUE_${EXTEN})})
exten => _1XX,n,GotoIf($["${thisQueue}" = ""]?invalid_queue,1)
exten => _1XX,n,Verbose(2, --> Entering the ${thisQueue} queue)
exten => _1XX,n,Queue(${thisQueue})
exten => _1XX,n,Hangup()
exten => invalid_queue,1,Verbose(2,Attempted to enter invalid queue)
exten => invalid_queue,n,Playback(silence/1&invalid)
exten => invalid_queue,n,Hangup()
The [globals] section contains the following two global variables.
[globals]
QUEUE_100=sales
QUEUE_101=support
So when we dial extension 100, it matches our pattern _1XX. The number we dialed
(100) is then retrievable via ${EXTEN} and we can get the name of queue 100
(sales) from the global variable QUEUE_100. We then assign it to the channel
variable thisQueue so it is easier to work with in our dialplan.
exten => _1XX,n,Set(thisQueue=${GLOBAL(QUEUE_${EXTEN})})
We then check to see if we've gotten a value back from the global variable which
would indicate whether the queue was valid or not.
exten => _1XX,n,GotoIf($["${thisQueue}" = ""]?invalid_queue,1)
If ${thisQueue} returns nothing, then we Goto the invalid_queue extension and
playback the 'invalid' file.
We could alternatively limit our pattern match to only extension 100 and 101
with the _10[0-1] pattern instead.
Lets move into the nitty-gritty section and show how we can login and logout our
devices to the pair of queues we've created.
First, we create a pattern match that takes star (*) plus the queue number
that we want to login or logout of. So to login/out of the sales queue (100) we
would dial *100. We use the same extension for logging in and out.
; Extension *100 or *101 will login/logout a queue member from sales or support queues respectively.
exten => _*10[0-1],1,Set(xtn=${EXTEN:1}) ; save ${EXTEN} with * chopped off to ${xtn}
exten => _*10[0-1],n,Goto(queueLoginLogout,member_check,1) ; check if already logged into a queue
We save the value of ${EXTEN:1} to the 'xtn' channel variable so we don't need
to keep typing the complicated pattern match.
Now we move into the meat of our login/out dialplan inside the
[queueLoginLogout] context.
The first section is initializing some variables that we need throughout the
member_check extension such as the name of the queue, the members currently
logged into the queue, and the current device peer name (i.e. SIP/0004f2040001).
; ### Login or Logout a Queue Member
[queueLoginLogout]
exten => member_check,1,Verbose(2,Logging queue member in or out of the request queue)
exten => member_check,n,Set(thisQueue=${GLOBAL(QUEUE_${xtn})}) ; assign queue name to a variable
exten => member_check,n,Set(queueMembers=${QUEUE_MEMBER_LIST(${thisQueue})}) ; assign list of logged in members of thisQueue to
; a variable (comma separated)
exten => member_check,n,Set(thisActiveMember=SIP/${CHANNEL(peername)}) ; initialize 'thisActiveMember' as current device
exten => member_check,n,GotoIf($["${queueMembers}" = ""]?q_login,1) ; short circuit to logging in if we don't have
; any members logged into this queue
At this point if there are no members currently logged into our sales queue,
we then short-circuit our dialplan to go to the 'q_login' extension since there
is no point in wasting cycles searching to see if we're already logged in.
The next step is to finish initializing some values we need within the While()
loop that we'll use to check if we're already logged into the queue. We set
our ${field} variable to 1, which will be used as the field number offset in
the CUT() function.
; Initialize some values we'll use in the While() loop
exten => member_check,n,Set(field=1) ; start our field counter at one
exten => member_check,n,Set(logged_in=0) ; initialize 'logged_in' to "not logged in"
exten => member_check,n,Set(thisQueueMember=${CUT(queueMembers,\,,${field})}) ; initialize 'thisQueueMember' with the value in the
; first field of the comma-separated list
Now we get to enter our While() loop to determine if we're already logged in.
; Enter our loop to check if our member is already logged into this queue
exten => member_check,n,While($[${EXISTS(${thisQueueMember})}]) ; while we have a queue member...
This is where we check to see if the member at this position of the list is the
same as the device we're calling from. If it doesn't match, then we go to the
'check_next' priority label (where we increase our ${field} counter variable).
If it does match, then we continue on in the dialplan.
exten => member_check,n,GotoIf($["${thisQueueMember}" != "${thisActiveMember}"]?check_next) ; if 'thisQueueMember' is not the
; same as our active peer, then
; check the next in the list of
; logged in queue members
If we continued on in the dialplan, then we set the ${logged_in} channel
variable to '1' which represents we're already logged into this queue. We then
exit the While() loop with the ExitWhile() dialplan application.
exten => member_check,n,Set(logged_in=1) ; if we got here, set as logged in
exten => member_check,n,ExitWhile() ; then exit our loop
If we didn't match this peer name in the list, then we increase our ${field}
counter variable by one, update the ${thisQueueMember} channel variable and then
move back to the top of the loop for another round of checks.
exten => member_check,n(check_next),Set(field=$[${field} + 1]) ; if we got here, increase counter
exten => member_check,n,Set(thisQueueMember=${CUT(queueMembers,\,,${field})}) ; get next member in the list
exten => member_check,n,EndWhile() ; ...end of our loop
And once we exit our loop, we determine whether we need to log our device in
or out of the queue.
; if not logged in, then login to this queue, otherwise, logout
exten => member_check,n,GotoIf($[${logged_in} = 0]?q_login,1:q_logout,1) ; if not logged in, then login, otherwise, logout
The following two extensions are used to either log the device in or out of the
queue. We use the AddQueueMember() and RemovQueueMember() applications to login
or logout the device from the queue.
The first two arguments for AddQueueMember() and RemoveQueueMember() are 'queue'
and 'device'. There are additional arguments we can pass, and you can check
those out with 'core show application AddQueueMember' and 'core show
application RemoveQueueMember()'.
; ### Login queue member ###
exten => q_login,1,Verbose(2,Logging ${thisActiveMember} into the ${thisQueue} queue)
exten => q_login,n,AddQueueMember(${thisQueue},${thisActiveMember}) ; login our active device to the queue
; requested
exten => q_login,n,Playback(silence/1) ; answer the channel by playing one second of silence
; If the member was added to the queue successfully, then playback "Agent logged in", otherwise, state an error occurred
exten => q_login,n,ExecIf($["${AQMSTATUS}" = "ADDED"]?Playback(agent-loginok):Playback(an-error-has-occurred))
exten => q_login,n,Hangup()
; ### Logout queue member ###
exten => q_logout,1,Verbose(2,Logging ${thisActiveMember} out of ${thisQueue} queue)
exten => q_logout,n,RemoveQueueMember(${thisQueue},${thisActiveMember})
exten => q_logout,n,Playback(silence/1)
exten => q_logout,n,ExecIf($["${RQMSTATUS}" = "REMOVED"]?Playback(agent-loggedoff):Playback(an-error-has-occurred))
exten => q_logout,n,Hangup()
And that's it! Give it a shot and you should see console output similar to the
following which will login and logout your queue members to the queues you've
configured.
You can see there are already a couple of queue members logged into the sales
queue.
*CLI> queue show sales
sales has 0 calls (max unlimited) in 'rrmemory' strategy (3s holdtime, 4s talktime), W:0, C:2, A:1, SL:0.0% within 0s
Members:
SIP/0004f2040001 (dynamic) (Not in use) has taken no calls yet
SIP/0004f2040002 (dynamic) (Not in use) has taken no calls yet
No Callers
Then we dial *100 to logout the active device from the sales queue.
*CLI> == Using SIP RTP CoS mark 5
-- Executing [*100@devices:1] Set("SIP/0004f2040001-00000012", "xtn=100") in new stack
-- Executing [*100@devices:2] Goto("SIP/0004f2040001-00000012", "queueLoginLogout,member_check,1") in new stack
-- Goto (queueLoginLogout,member_check,1)
-- Executing [member_check@queueLoginLogout:1] Verbose("SIP/0004f2040001-00000012", "2,Logging queue member in or out of the request queue") in new stack
== Logging queue member in or out of the request queue
-- Executing [member_check@queueLoginLogout:2] Set("SIP/0004f2040001-00000012", "thisQueue=sales") in new stack
-- Executing [member_check@queueLoginLogout:3] Set("SIP/0004f2040001-00000012", "queueMembers=SIP/0004f2040001,SIP/0004f2040002") in new stack
-- Executing [member_check@queueLoginLogout:4] Set("SIP/0004f2040001-00000012", "thisActiveMember=SIP/0004f2040001") in new stack
-- Executing [member_check@queueLoginLogout:5] GotoIf("SIP/0004f2040001-00000012", "0?q_login,1") in new stack
-- Executing [member_check@queueLoginLogout:6] Set("SIP/0004f2040001-00000012", "field=1") in new stack
-- Executing [member_check@queueLoginLogout:7] Set("SIP/0004f2040001-00000012", "logged_in=0") in new stack
-- Executing [member_check@queueLoginLogout:8] Set("SIP/0004f2040001-00000012", "thisQueueMember=SIP/0004f2040001") in new stack
-- Executing [member_check@queueLoginLogout:9] While("SIP/0004f2040001-00000012", "1") in new stack
-- Executing [member_check@queueLoginLogout:10] GotoIf("SIP/0004f2040001-00000012", "0?check_next") in new stack
-- Executing [member_check@queueLoginLogout:11] Set("SIP/0004f2040001-00000012", "logged_in=1") in new stack
-- Executing [member_check@queueLoginLogout:12] ExitWhile("SIP/0004f2040001-00000012", "") in new stack
-- Jumping to priority 15
-- Executing [member_check@queueLoginLogout:16] GotoIf("SIP/0004f2040001-00000012", "0?q_login,1:q_logout,1") in new stack
-- Goto (queueLoginLogout,q_logout,1)
-- Executing [q_logout@queueLoginLogout:1] Verbose("SIP/0004f2040001-00000012", "2,Logging SIP/0004f2040001 out of sales queue") in new stack
== Logging SIP/0004f2040001 out of sales queue
-- Executing [q_logout@queueLoginLogout:2] RemoveQueueMember("SIP/0004f2040001-00000012", "sales,SIP/0004f2040001") in new stack
[Nov 12 12:08:51] NOTICE[11582]: app_queue.c:4842 rqm_exec: Removed interface 'SIP/0004f2040001' from queue 'sales'
-- Executing [q_logout@queueLoginLogout:3] Playback("SIP/0004f2040001-00000012", "silence/1") in new stack
-- <SIP/0004f2040001-00000012> Playing 'silence/1.slin' (language 'en')
-- Executing [q_logout@queueLoginLogout:4] ExecIf("SIP/0004f2040001-00000012", "1?Playback(agent-loggedoff):Playback(an-error-has-occurred)") in new stack
-- <SIP/0004f2040001-00000012> Playing 'agent-loggedoff.slin' (language 'en')
-- Executing [q_logout@queueLoginLogout:5] Hangup("SIP/0004f2040001-00000012", "") in new stack
== Spawn extension (queueLoginLogout, q_logout, 5) exited non-zero on 'SIP/0004f2040001-00000012'
And we can see that the device we loggd out by running 'queue show sales'.
*CLI> queue show sales
sales has 0 calls (max unlimited) in 'rrmemory' strategy (3s holdtime, 4s talktime), W:0, C:2, A:1, SL:0.0% within 0s
Members:
SIP/0004f2040002 (dynamic) (Not in use) has taken no calls yet
No Callers
-------------------------------------------
| Pausing and Unpausing Members of Queues |
-------------------------------------------
Once we have our queue members logged in, it is inevitable that they will want
to pause themselves during breaks, and other short periods of inactivity. To do
this we can utilize the 'queue pause' and 'queue unpause' CLI commands.
We have two devices logged into the sales queue as we can see with the 'queue
show sales' CLI command.
*CLI> queue show sales
sales has 0 calls (max unlimited) in 'rrmemory' strategy (0s holdtime, 0s talktime), W:0, C:0, A:0, SL:0.0% within 0s
Members:
SIP/0004f2040002 (dynamic) (Not in use) has taken no calls yet
SIP/0004f2040001 (dynamic) (Not in use) has taken no calls yet
No Callers
We can then pause our devices with 'queue pause' which has the following format.
Usage: queue {pause|unpause} member <member> [queue <queue> [reason <reason>]]
Pause or unpause a queue member. Not specifying a particular queue
will pause or unpause a member across all queues to which the member
belongs.
Lets pause device 0004f2040001 in the sales queue by executing the following.
*CLI> queue pause member SIP/0004f2040001 queue sales
paused interface 'SIP/0004f2040001' in queue 'sales' for reason 'lunch'
And we can see they are paused with 'queue show sales'.
*CLI> queue show sales
sales has 0 calls (max unlimited) in 'rrmemory' strategy (0s holdtime, 0s talktime), W:0, C:0, A:0, SL:0.0% within 0s
Members:
SIP/0004f2040002 (dynamic) (Not in use) has taken no calls yet
SIP/0004f2040001 (dynamic) (paused) (Not in use) has taken no calls yet
No Callers
At this point the queue member will no longer receive calls from the system. We
can unpause them with the CLI command 'queue unpause member'.
*CLI> queue unpause member SIP/0004f2040001 queue sales
unpaused interface 'SIP/0004f2040001' in queue 'sales'
And if you don't specify a queue, it will pause or unpause from all queues.
*CLI> queue pause member SIP/0004f2040001
paused interface 'SIP/0004f2040001'
Of course we want to allow the agents to pause and unpause themselves from their
devices, so we need to create an extension and some dialplan logic for that to
happen.
Below we've created the pattern patch _*0[01]! which will match on *00 and *01,
and will *also* match with zero or more digits following it, such as the queue
extension number.
So if we want to pause ourselves in all queues, we can dial *00; unpausing can
be done with *01. But if our agents just need to pause or unpause themselves
from a single queue, then we will also accept *00100 to pause in queue 100
(sales), or we can unpause ourselves from sales with *01100.
extensions.conf
---------------
; Allow queue members to pause and unpause themselves from all queues, or an individual queue.
;
; _*0[01]! pattern match will match on *00 and *01 plus 0 or more digits.
exten => _*0[01]!,1,Verbose(2,Pausing or unpausing queue member from one or more queues)
exten => _*0[01]!,n,Set(xtn=${EXTEN:3}) ; save the queue extension to 'xtn'
exten => _*0[01]!,n,Set(thisQueue=${GLOBAL(QUEUE_${xtn})}) ; get the queue name if available
exten => _*0[01]!,n,GotoIf($[${ISNULL(${thisQueue})} & ${EXISTS(${xtn})}]?invalid_queue,1) ; if 'thisQueue' is blank and the
; the agent dialed a queue exten,
; we will tell them it's invalid
The following line will determine if we're trying to pause or unpause. This is
done by taking the value dialed (e.g. *00100) and chopping off the first 2
digits which leaves us with 0100, and then the :1 will return the next digit,
which in this case is '0' that we're using to signify that the queue member
wants to be paused (in queue 100).
So we're doing the following with our EXTEN variable.
${EXTEN:2:1}
offset ^ ^ length
Which causes the following.
*00100
^^ offset these characters
*00100
^ then return a digit length of one, which is digit 0
exten => _*0[01]!,n,GotoIf($[${EXTEN:2:1} = 0]?pause,1:unpause,1) ; determine if they wanted to pause
; or to unpause.
The following two extensions, pause & unpause, are used for pausing and
unpausing our extension from the queue(s). We use the PauseQueueMember() and
UnpauseQueueMember() dialplan applications which accept the queue name
(optional) and the queue member name. If the queue name is not provided, then it
is assumed we want to pause or unpause from all logged in queues.
; Unpause ourselves from one or more queues
exten => unpause,1,NoOp()
exten => unpause,n,UnpauseQueueMember(${thisQueue},SIP/${CHANNEL(peername)}) ; if 'thisQueue' is populated we'll pause in
; that queue, otherwise, we'll unpause in
; in all queues
Once we've unpaused ourselves, we use GoSub() to perform some common dialplan
logic that is used for pausing and unpausing. We pass three arguments to the
subroutine:
* variable name that contains the result of our operation
* the value we're expecting to get back if successful
* the filename to play
exten => unpause,n,GoSub(changePauseStatus,start,1(UPQMSTATUS,UNPAUSED,available)) ; use the changePauseStatus subroutine and
; pass the values for: variable to check,
; value to check for, and file to play
exten => unpause,n,Hangup()
And the same method is done for pausing.
; Pause ourselves in one or more queues
exten => pause,1,NoOp()
exten => pause,n,PauseQueueMember(${thisQueue},SIP/${CHANNEL(peername)})
exten => pause,n,GoSub(changePauseStatus,start,1(PQMSTATUS,PAUSED,unavailable))
exten => pause,n,Hangup()
Lets explore what happens in the subroutine we're using for pausing and
unpausing.
; ### Subroutine we use to check pausing and unpausing status ###
[changePauseStatus]
; ARG1: variable name to check, such as PQMSTATUS and UPQMSTATUS (PauseQueueMemberStatus / UnpauseQueueMemberStatus)
; ARG2: value to check for, such as PAUSED or UNPAUSED
; ARG3: file to play back if our variable value matched the value to check for
;
exten => start,1,NoOp()
exten => start,n,Playback(silence/1) ; answer line with silence
The following line is probably the most complex. We're using the IF() function
inside the Playback() application which determines which file to playback
to the user.
Those three values we passed in from the pause and unpause extensions could have
been something like:
* ARG1 -- PQMSTATUS
* ARG2 -- PAUSED
* ARG3 -- unavailable
So when expanded, we'd end up with the following inside the IF() function.
$["${PQMSTATUS}" = "PAUSED"]?unavailable:not-yet-connected
${PQMSTATUS} would then be expanded further to contain the status of our
PauseQueueMember() dialplan application, which could either be PAUSED or
NOTFOUND. So if ${PQMSTATUS} returned PAUSED, then it would match what we're
looking to match on, and we'd then return 'unavailable' to Playback() that would
tell the user they are now unavailable.
Otherwise, we'd get back a message saying "not yet connected" to indicate they
are likely not logged into the queue they are attempting to change status in.
; Please note that ${ARG1} is wrapped in ${ } in order to expand the value of ${ARG1} into
; the variable we want to retrieve the value from, i.e. ${${ARG1}} turns into ${PQMSTATUS}
exten => start,n,Playback(${IF($["${${ARG1}}" = "${ARG2}"]?${ARG3}:not-yet-connected)}) ; check if value of variable
; matches the value we're looking
; for and playback the file we want
; to play if it does
If ${xtn} is null, then we just go to the end of the subroutine, but if it isn't
then we will play back "in the queue" followed by the queue extension number
indicating which queue they were (un)paused from.
exten => start,n,GotoIf($[${ISNULL(${xtn})}]?end) ; if ${xtn} is null, then just Return()
exten => start,n,Playback(in-the-queue) ; if not null, then playback "in the queue"
exten => start,n,SayNumber(${xtn}) ; and the queue number that we (un)paused from
exten => start,n(end),Return() ; return from were we came
--------------
| Conclusion |
--------------
You should now have a simple system that permits you to login and out of queues
you create in queues.conf, and to allow queue members to pause themselves within
one or more queues. There are a lot of dialplan concepts utilized in this
article, so you are encouraged to seek out additional documentation if any of
these concepts are a bit fuzzy for you.
A good start is the doc/ subdirectory of the Asterisk sources, or the various
configuration samples files located in the configs/ subdirectory of your
Asterisk source code.

View File

@ -1,139 +0,0 @@
Asterisk call files
===================
Asterisk has the ability to initiate a call from outside of the normal
methods such as the dialplan, manager interface, or spooling interface.
Using the call file method, you must give Asterisk the following information:
* How to perform the call, similar to the Dial() application
* What to do when the call is answered
With call files you submit this information simply by creating a file with
the required syntax and placing it in the outgoing spooling directory, located
by default in /var/spool/asterisk/outgoing/ (configurable in asterisk.conf).
The pbx_spool module aggressively examines the directory contents every second,
creating a new call for every call file it finds. Do NOT write or create
the call file directly in the outgoing directory, but always create the file
in another directory of the same filesystem and then move the file to the
/var/spool/asterisk/outgoing directory, or Asterisk may read just a partial
file.
The call file syntax
====================
The call file consists of <Key>: <value> pairs; one per line.
Comments are indicated by a '#' character that begins a line, or follows a space
or tab character. To be consistent with the configuration files in Asterisk,
comments can also be indicated by a semicolon. However, the multiline comments
(;-- --;) used in Asterisk configuration files are not supported. Semicolons can
be escaped by a backslash.
The following keys-value pairs are used to specify how setup a call:
Channel: <channel> the channel to use for the new call, in the form
technology/resource as in the Dial application. This
value is required.
Callerid: <callerid> the caller id to use.
WaitTime: <number> how many seconds to wait for an answer before the call
fails (ring cycle). Default 45 seconds.
Maxretries: <number> number of retries before failing, not including the
initial attempt. Default = 0 e.g. don't retry if fails.
RetryTime: <number> how many seconds to wait before retry. The default is
300 (5 minutes).
Account: <account> the account code for the call. This value will be
assigned to CDR(accountcode)
When the call answers there are two choices:
* Execute a single application, or
* Execute the dialplan at the specified context/extension/priority.
To execute an application:
--------------------------
Application: <appname> the application to execute
Data: <args> the application arguments
To start executing applications in the dialplan:
------------------------------------------------
Context: <context> the context in the dialplan
Extension: <exten> the extension in the specified context
Priority: <priority> the priority of the specified extension
(numeric or label)
Setvar: <var=value> you may also assign values to variables that will be
available to the channel, as if you had performed a
Set(var=value) in the dialplan. More than one Setvar:
maybe specified.
The processing of the call file ends when the call is answered and terminated; when
the call was not answered in the initial attempt and subsequent retries; or if
the call file can't be successfully read and parsed.
To specify what to do with the call file at the end of processing:
Archive: <yes|no> if "no" the call file is deleted. If set to "yes" the
call file is moved to the "outgoing_done" subdirectory
of the Asterisk spool directory. The default is to
delete the call file.
If the call file is archived, Asterisk will append to the call file:
Status: <exitstatus> can be "Expired", "Completed" or "Failed"
Other lines generated by Asterisk:
Asterisk keep track of how many retries the call has already attempted,
appending to the call file the following key-pairs in the form:
StartRetry: <pid> <retrycount> (<time>)
EndRetry: <pid> <retrycount> (<time>)
With the main process ID (pid) of the Asterisk process, the retry number, and
the attempts start and end times in time_t format.
Directory locations
===================
<astspooldir>/outgoing the outgoing dir, where call files are put
for processing
<astspooldir>/outgoing_done the archive dir
<astspooldir> is specified in asterisk.conf, usually /var/spool/asterisk
How to schedule a call
======================
Call files that have the time of the last modification in the future are ignored
by Asterisk. This makes it possible to modify the time of a call file to the
wanted time, move to the outgoing directory, and Asterisk will attempt to
create the call at that time.

View File

@ -1,110 +0,0 @@
Measuring the SIP channel driver's Performance
==============================================
This file documents the methods I used to measure
the performance of the SIP channel driver, in
terms of maximum simultaneous calls and how quickly
it could handle incoming calls.
Knowing these limitations can be valuable to those
implementing PBX's in 'large' environments. Will your
installation handle expected call volume?
Quoting these numbers can be totally useless for other
installations. Minor changes like the amount of RAM
in a system, the speed of the ethernet, the amount of
cache in the CPU, the CPU clock speed, whether or not
you log CDR's, etc. can affect the numbers greatly.
In my set up, I had a dedicated test machine running Asterisk,
and another machine which ran sipp, connected together with
ethernet.
The version of sipp that I used was sipp-2.0.1; however,
I have reason to believe that other versions would work
just as well.
On the asterisk machine, I included the following in my
extensions.ael file:
context test11
{
s => {
Answer();
while (1) {
Background(demo-instruct);
}
Hangup();
}
_X. => {
Answer();
while (1) {
Background(demo-instruct);
}
Hangup();
}
}
Basically, incoming SIP calls are answered, and
the demo-instruct sound file is played endlessly
to the caller. This test depends on the calling
party to hang up, thus allowing sipp to determine
the length of a call.
The sip.conf file has this entry:
[asterisk02]
type=friend
context=test11
host=192.168.134.240 ;; the address of the host you will be running sipp on
user=sipp
directmedia=no
disallow=all
allow=ulaw
Note that it's pretty simplistic; no authentication beyond the host ip,
and it uses ulaw, which is pretty efficient, low-cpu-intensive codec.
To measure the impact of incoming call traffic on the Asterisk
machine, I run vmstat. It gives me an idea of the cpu usage by
Asterisk. The most common failure mode of Asterisk at high call volumes,
is that the CPU reaches 100% utilization, and then cannot keep up with
the workload, resulting in timeouts and other failures, which swiftly
compound and cascade, until gross failure ensues. Watch the CPU Idle %
numbers.
I learned to split the testing into two modes: one for just call call processing
power, in the which we had relatively few simultaneous calls in place,
and another where we allow the the number of simultaneous calls to quickly
reach a set maximum, and then rerun sipp, looking for the maximum.
Call processing power is measured with extremely short duration calls:
./sipp -sn uac 192.168.134.252 -s 12 -d 100 -l 256
The above tells sipp to call your asterisk test machine (192.168.134.252)
at extension 12, each call lasts just .1 second, with a limit of 256 simultaneous
calls. The simultaneous calls will be the rate/sec of incoming calls times the call length,
so 1 simultaneous call at 10 calls/sec, and 45 at 450 calls/sec. Setting the limit
to 256 implies you do not intend to test above 2560 calls/sec.
Sipp starts at 10 calls/sec, and you can slowly increase the speed by hitting '*' or '+'.
Watch your cpu utilization on the asterisk server. When you approach 100%, you have found
your limit.
Simultaneous calls can be measured with very long duration calls:
./sipp -sn uac 192.168.134.252 -s 12 -d 100000 -l 270
This will place 100 sec duration calls to Asterisk. The number of simultaneous
calls will increase until the maximum of 270 is reached. If Asterisk survives
this number and is not at 100% cpu utilization, you can stop sipp and run it again
with a higher -l argument.
By changing one Asterisk parameter at a time, you can get a feel for how much that change
will affect performance.

View File

@ -1,33 +0,0 @@
In addition to being the console for Asterisk, the CLI also sports several
features that make it very helpful to use for obtaining information and
affecting system configuration. The console can also be seen by starting
a remote console, which connects to the running daemon and shows much of
the same information as if using the daemon in foreground mode.
Connecting a remote console is as easy as using the -r or -R flags. The only
difference between these flags is that the uppercase variation (-R) will
automatically reconnect to the daemon (or at least retry) if the daemon
restarts. To exit a remote console, simply type 'quit' or 'exit'. Please note
that you can differentiate between a remote console and the Asterisk console,
as 'quit' or 'exit' will not function on the main console, which prevents an
accidental shutdown of the daemon. If you would like to shutdown the Asterisk
daemon, you can use the 'stop' set of commands, such as 'stop now',
'stop gracefully', or 'stop when convenient'.
Once on the console, the 'help' command may be used to see a list of commands
available for use. Note that in addition to the 'help' command, the Asterisk
CLI sports tab command line completion on all commands, including many
arguments. To use tab command line completion, simply press the <Tab> key at
any time while entering the beginning of any command. If the command can be
completed unambiguously, it will do so, otherwise it will complete as much of
the command as possible. Additionally, Asterisk will print a list of all
possible matches, if possible.
The 'help' command may also be used to obtain more detailed information on
how to use a particular command. For example, if you type 'help core show',
Asterisk will respond with a list of all commands that start with that string.
If you type 'help core show version', specifying a complete command, Asterisk
will respond with a usage message which describes how to use that command. As
with other commands on the Asterisk console, the help command also responds to
tab command line completion.

View File

@ -1,47 +0,0 @@
CODEC BIT EXPANSION
-------------------
The code base up to and including Asterisk 1.6.2 has a basic limit of 32 codecs
recognizable, due to the use of a 32-bit integer for the codec bitmask. We
have expanded the number of available codecs from 32 to 64, through the use of
an immutable type, called format_t. This should make future expansion to even
more bits more easily done.
The design of this expansion has made some changes to the architecture of codecs
in order to accomplish this task. I will attempt to enumerate them here.
The initial set of 32-bits were allocated as the first 16 to audio codecs, the
next 8 to video codecs, and the remaining to text codecs (which are used for
fax capabilities). Initially, there is an assumption in the code that all
audio codecs are contiguous, followed by a contiguous set of video codecs.
After the conversion, this assumption will no longer be true. The codec bits
for the existing codecs will continue to be allocated as-is, and the additional
codec bits should be allocated on an as-needed basis, with audio codecs
occupying slots 32-47 and video codecs occupying slots 48-62 (with a 0-based
offset). Slot 63 is reserved and should not be allocated; it is used in code
as an end condition for iterating through the entire set of codecs.
The frame structure has been altered. Initially, the subclass held an integer
whose meaning was specified by the frametype. If the frametype was
AST_FRAME_VOICE, the subclass specified the audio codec. If the frametype was
AST_FRAME_VIDEO, the subclass specified the video codec, with the 0-bit set to
specify a key frame. This was done with a union on the subclass, where the
"integer" union member specifies the traditional 32-bit subclass and the "codec"
union member specifies the new 64-bit codec bitmask. This additionally
guarantees that code compiled under the old scheme will need to be altered to
compile under the new scheme, which helps avoid incorrect assumptions about the
state of code which might otherwise compile without errors.
The IAX2 code initially used a 32-bit integer IE to specify both the codec as
well as the preferred format. An additional IE has been added, which specifies
a single byte version number as the initial part of the data. This version
number is initially specified as 00 and requires 8 bytes to follow, specifying
the 64-bit codec bitmask, in network-byte order. This schema should allow
further codec expansion in the future without allocation of any additional IEs.
Little changes are required to support further codec expansion in the future,
though the majority of the work has already been accomplished. Specifically,
the bitwise operations that are immutable operations in the gcc compiler will
need to be altered to handle larger bitmasks. Additionally, the constants that
define specific codecs will need to be changed from integers to structures.

View File

@ -1,29 +0,0 @@
As of 1.6.2, Asterisk now supports doing database transactions from the
dialplan. A number of new applications and functions have been introduced
for this purpose and this document should hopefully familiarize you with
all of them.
First, the ODBC() function has been added which is used to set up all new
database transactions. Simply write the name of the transaction to this
function, along with the arguments of "transaction" and the database name,
e.g. Set(ODBC(transaction,postgres-asterisk)=foo). In this example, the
name of the transaction is "foo". The name doesn't really matter, unless
you're manipulating multiple transactions within the same dialplan, at the
same time. Then, you use the transaction name to change which transaction
is active for the next dialplan function.
The ODBC() function is also used to turn on a mode known as forcecommit.
For most cases, you won't need to use this, but it's there. It simply
causes a transaction to be committed, when the channel hangs up. The other
property which may be set is the isolation property. Please consult with
your database vendor as to which values are supported by their ODBC driver.
Asterisk supports setting all standard ODBC values, but many databases do
not support the entire complement.
Finally, when you have run multiple statements on your transaction and you
wish to complete the transaction, use the ODBC_Commit and ODBC_Rollback
applications, along with the transaction ID (in the example above, "foo")
to commit or rollback the transaction. Please note that if you do not
explicitly commit the transaction or if forcecommit is not turned on, the
transaction will be automatically rolled back at channel destruction (after
hangup) and all related database resources released back to the pool.

View File

@ -1,63 +0,0 @@
Asterisk Channel Data Stores
============================
* What is a data store?
A data store is a way of storing complex data (such as a structure) on a channel
so it can be retrieved at a later time by another application, or the same application.
If the data store is not freed by said application though, a callback to a destroy function
occurs which frees the memory used by the data in the data store so no memory loss occurs.
* A datastore info structure
static const struct example_datastore {
.type = "example",
.destroy = callback_destroy
};
This is a needed structure that contains information about a datastore, it's used by many API calls.
* How do you create a data store?
1. Use ast_datastore_alloc function to return a pre-allocated structure
Ex: datastore = ast_datastore_alloc(&example_datastore, "uid");
This function takes two arguments: (datastore info structure, uid)
2. Attach data to pre-allocated structure.
Ex: datastore->data = mysillydata;
3. Add datastore to the channel
Ex: ast_channel_datastore_add(chan, datastore);
This function takes two arguments: (pointer to channel, pointer to data store)
Full Example:
void callback_destroy(void *data)
{
ast_free(data);
}
struct ast_datastore *datastore = NULL;
datastore = ast_datastore_alloc(&example_datastore, NULL);
datastore->data = mysillydata;
ast_channel_datastore_add(chan, datastore);
NOTE: Because you're passing a pointer to a function in your module, you'll want to include
this in your use count. When allocated increment, when destroyed decrement.
* How do you remove a data store?
1. Find the data store
Ex: datastore = ast_channel_datastore_find(chan, &example_datastore, NULL);
This function takes three arguments: (pointer to channel, datastore info structure, uid)
2. Remove the data store from the channel
Ex: ast_channel_datastore_remove(chan, datastore);
This function takes two arguments: (pointer to channel, pointer to data store)
3. If we want to now do stuff to the data on the data store
4. Free the data store (this will call the destroy call back)
Ex: ast_channel_datastore_free(datastore);
This function takes one argument: (pointer to data store)
* How do you find a data store?
1. Find the data store
Ex: datastore = ast_channel_datastore_find(chan, &example_datastore, NULL);
This function takes three arguments: (pointer to channel, datastore info structure, uid)

View File

@ -1,24 +0,0 @@
DIGIUM-MIB DEFINITIONS ::= BEGIN
IMPORTS
enterprises, MODULE-IDENTITY
FROM SNMPv2-SMI;
digium MODULE-IDENTITY
LAST-UPDATED "200806202000Z"
ORGANIZATION "Digium, Inc."
CONTACT-INFO
"Mark Spencer
Email: markster@digium.com"
DESCRIPTION
"The Digium private-enterprise MIB"
REVISION "200806202000Z"
DESCRIPTION
"Corrected imports and missing revision for last update.
Addresses bug 12905. - jeffg@opennms.org"
REVISION "200602041900Z"
DESCRIPTION
"Initial revision."
::= { enterprises 22736 }
END

View File

@ -1,433 +0,0 @@
===============================================================================
===
=== XMPP PubSub Distributed Device State
===
=== Copyright (C) 2010, Digium, Inc.
=== Leif Madsen <lmadsen@digium.com>
===
===============================================================================
-------------------------------------------------------------------------------
--- INTRODUCTION
-------------------------------------------------------------------------------
This document describes installing and utilizing XMPP PubSub events to
distribute device state and message waiting indication (MWI) events between
servers. The difference between this method and OpenAIS (see
distributed_devstate.txt) is that OpenAIS can only be used in low latency
networks; meaning only on the LAN, and not across the internet.
If you plan on distributing device state or MWI across the internet, then you
will require the use of XMPP PubSub events.
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
--- Tigase Installation
-------------------------------------------------------------------------------
-- Description --
Currently the only server supported for XMPP PubSub events is the Tigase open
source XMPP/Jabber environment. This is the server that the various Asterisk
servers will connect to in order to distribute the events. The Tigase server can
even be clustered in order to provide high availability for your device state;
however, that is beyond the scope of this document.
For more information about Tigase, visit their web site:
http://www.tigase.org
-- Download --
To download the Tigase environment, get the latest version at:
http://www.tigase.org/en/filebrowser/tigase-server
-- Install --
The Tigase server requires a working Java environment, including both a JRE
(Java Runtime Environment) and a JDK (Java Development Kit), currently at least
version 1.6.
For more information about how to install Tigase, see the web site:
http://www.tigase.org/en/content/quick-start
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
--- Tigase Configuration
-------------------------------------------------------------------------------
While installing Tigase, be sure you enable the PubSub module. Without it, the
PubSub events won't be accepted by the server, and your device state will not be
distributed.
There are a couple of things you need to configure in Tigase before you start it
in order for Asterisk to connect. The first thing we need to do is generate the
self-signed certificate. To do this we use the keytool application. More
information can be found here:
http://www.tigase.org/en/content/server-certificate
-- Generating the keystore file --
Generally, we need to run the following commands to generate a new keystore
file.
# cd /opt/Tigase-4.3.1-b1858/certs
Be sure to change the 'yourdomain' to your domain.
# keytool -genkey -alias yourdomain -keystore rsa-keystore \
-keyalg RSA -sigalg MD5withRSA
The keytool application will then ask you for a password. Use the password
'keystore' as this is the default password that Tigase will use to load the
keystore file.
You then need to specify your domain as the first value to be entered in the
security certificate.
What is your first and last name?
[Unknown]: asterisk.mydomain.tld
What is the name of your organizational unit?
[Unknown]:
What is the name of your organization?
[Unknown]:
What is the name of your City or Locality?
[Unknown]:
What is the name of your State or Province?
[Unknown]:
What is the two-letter country code for this unit?
[Unknown]:
Is CN=asterisk.mydomain.tld, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown correct?
[no]: yes
You will then be asked for another password, in which case you must just press
enter for the same password as Tigase will not work without them being the same.
Enter key password for <mykey>
(RETURN if same as keystore password):
-- Configuring init.properties --
The next step is to configure the init.properties file which is used by Tigase
to generate the tigase.xml file. Whenever you change the init.properties file
because sure to remove the current tigase.xml file so that it will be
regenerated at start up.
# cd /opt/Tigase-4.3.1-b1858/etc
Then edit the init.properties file and add the following:
config-type=--gen-config-def
--admins=admin@asterisk.mydomain.tld
--virt-hosts=asterisk.mydomain.tld
--debug=server
--user-db=derby
--user-db-uri=jdbc:derby:/opt/Tigase-4.3.1-b1858
--comp-name-1=pubsub
--comp-class-1=tigase.pubsub.PubSubComponent
Be sure to change the domain in the --admin and --virt-hosts options. The most
important lines are --comp-name-1 and --comp-class-1 which tell Tigase to load
the PubSub module.
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
--- Running Tigase
-------------------------------------------------------------------------------
You can then start the Tigase server with the tigase.sh script.
# cd /opt/Tigase-4.3.1-b1858
# ./scripts/tigase.sh start etc/tigase.conf
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
--- Adding Buddies to Tigase
-------------------------------------------------------------------------------
At this time, Asterisk is not able to automatically register your peers for you,
so you'll need to use an external application to do the initial registration.
Pidgin is an excellent multi-protocol instant messenger application which
supports XMPP. It runs on Linux, Windows, and OSX, and is open source. You can
get Pidgin from http://www.pidgin.im
Then add the two buddies we'll use in Asterisk with Pidgin by connecting to
the Tigase server. For more information about how to register new buddies, see
the Pidgin documentation.
Once the initial registration is done and loaded into Tigase, you no longer need
to worry about using Pidgin. Asterisk will then be able to load the peers into
memory at start up.
The example peers we've used in the following documentation for our two nodes
are:
server1@asterisk.mydomain.tld/astvoip1
server2@asterisk.mydomain.tld/astvoip2
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
--- Installing Asterisk
-------------------------------------------------------------------------------
Install Asterisk as usual. However, you'll need to make sure you have the
res_jabber module compiled, which requires the iksemel development library.
Additionally, be sure you have the OpenSSL development library installed so you
can connect securly to the Tigase server.
Make sure you check menuselect that res_jabber is selected so that it will
compile.
# cd asterisk-source
# ./configure
# make menuselect
---> Resource Modules
If you don't have jabber.conf in your existing configuration, because sure to
copy the sample configuration file there.
# cd configs
# cp jabber.conf.sample /etc/asterisk/jabber.conf
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
--- Configuring Asterisk
-------------------------------------------------------------------------------
We then need to configure our servers to communicate with the Tigase server. We
need to modify the jabber.conf file on the servers. The configurations below are
for a 2 server setup, but could be expanded for additional servers easily.
The key note here is to note that the pubsub_node option needs to start with
pubsub, so for example, pubsub.asterisk.mydomain.tld. Without the 'pubsub' your
Asterisk system will not be able to distribute events.
Additionally, you will need to specify each of the servers you need to connec to
using the 'buddy' option.
-- Asterisk Server 1 --
[general]
debug=no ;;Turn on debugging by default.
;autoprune=yes ;;Auto remove users from buddy list. Depending on your
;;setup (ie, using your personal Gtalk account for a test)
;;you might lose your contacts list. Default is 'no'.
autoregister=yes ;;Auto register users from buddy list.
;collection_nodes=yes ;;Enable support for XEP-0248 for use with
;;distributed device state. Default is 'no'.
;pubsub_autocreate=yes ;;Whether or not the PubSub server supports/is using
;;auto-create for nodes. If it is, we have to
;;explicitly pre-create nodes before publishing them.
;;Default is 'no'.
[asterisk]
type=client
serverhost=asterisk.mydomain.tld
pubsub_node=pubsub.asterisk.mydomain.tld
username=server1@asterisk.mydomain.tld/astvoip1
secret=welcome
distribute_events=yes
status=available
usetls=no
usesasl=yes
buddy=server2@asterisk.mydomain.tld/astvoip2
-- Asterisk Server 2 --
[general]
debug=yes ;;Turn on debugging by default.
;autoprune=yes ;;Auto remove users from buddy list. Depending on your
;;setup (ie, using your personal Gtalk account for a test)
;;you might lose your contacts list. Default is 'no'.
autoregister=yes ;;Auto register users from buddy list.
;collection_nodes=yes ;;Enable support for XEP-0248 for use with
;;distributed device state. Default is 'no'.
;pubsub_autocreate=yes ;;Whether or not the PubSub server supports/is using
;;auto-create for nodes. If it is, we have to
;;explicitly pre-create nodes before publishing them.
;;Default is 'no'.
[asterisk]
type=client
serverhost=asterisk.mydomain.tld
pubsub_node=pubsub.asterisk.mydomain.tld
username=server2@asterisk.mydomain.tld/astvoip2
secret=welcome
distribute_events=yes
status=available
usetls=no
usesasl=yes
buddy=server1@asterisk.mydomain.tld/astvoip1
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
--- Basic Testing of Asterisk with XMPP PubSub
-------------------------------------------------------------------------------
Once you have Asterisk installed with XMPP PubSub, it is time to test it out.
We need to start up our first server and make sure we get connected to the XMPP
server. We can verify this with an Asterisk console command to determine if
we're connected.
On Asterisk 1 we can run 'jabber show connected' to verify we're connected to
the XMPP server.
*CLI> jabber show connected
Jabber Users and their status:
User: server1@asterisk.mydomain.tld/astvoip1 - Connected
----
Number of users: 1
The command above has given us output which verifies we've connected our first
server.
We can then check the state of our buddies with the 'jabber show buddies' CLI
command.
*CLI> jabber show buddies
Jabber buddy lists
Client: server1@asterisk.mydomain.tld/astvoip1
Buddy: server2@asterisk.mydomain.tld
Resource: None
Buddy: server2@asterisk.mydomain.tld/astvoip2
Resource: None
The output above tells us we're not connected to any buddies, and thus we're not
distributing state to anyone (or getting it from anyone). That makes sense since
we haven't yet started our other server.
Now, let's start the other server and verify the servers are able to establish
a connection between each other.
On Asterisk 2, again we run the 'jabber show connected' command to make sure
we've connected successfully to the XMPP server.
*CLI> jabber show connected
Jabber Users and their status:
User: server2@asterisk.mydomain.tld/astvoip2 - Connected
----
Number of users: 1
And now we can check the status of our buddies.
*CLI> jabber show buddies
Jabber buddy lists
Client: server2@scooter/astvoip2
Buddy: server1@asterisk.mydomain.tld
Resource: astvoip1
node: http://www.asterisk.org/xmpp/client/caps
version: asterisk-xmpp
Jingle capable: yes
Status: 1
Priority: 0
Buddy: server1@asterisk.mydomain.tld/astvoip1
Resource: None
Excellent! So we're connected to the buddy on Asterisk 1, and we could run the
same command on Asterisk 1 to verify the buddy on Asterisk 2 is seen.
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
--- Testing Distributed Device State
-------------------------------------------------------------------------------
The easiest way to test distributed device state is to use the DEVICE_STATE()
diaplan function. For example, you could have the following piece of dialplan
on every server:
[devstate_test]
exten => 1234,hint,Custom:mystate
exten => set_inuse,1,Set(DEVICE_STATE(Custom:mystate)=INUSE)
exten => set_not_inuse,1,Set(DEVICE_STATE(Custom:mystate)=NOT_INUSE)
exten => check,1,NoOp(Custom:mystate is ${DEVICE_STATE(Custom:mystate)})
Now, you can test that the cluster-wide state of "Custom:mystate" is what
you would expect after going to the CLI of each server and adjusting the state.
server1*CLI> console dial set_inuse@devstate_test
...
server2*CLI> console dial check@devstate_test
-- Executing [check@devstate_test:1] NoOp("OSS/dsp", "Custom:mystate is INUSE") in new stack
Various combinations of setting and checking the state on different servers can
be used to verify that it works as expected. Also, you can see the status of
the hint on each server, as well, to see how extension state would reflect the
state change with distributed device state:
server2*CLI> core show hints
-= Registered Asterisk Dial Plan Hints =-
1234@devstate_test : Custom:mystate State:InUse Watchers 0
One other helpful thing here during testing and debugging is to enable debug
logging. To do so, enable debug on the console in /etc/asterisk/logger.conf.
Also, enable debug at the Asterisk CLI.
*CLI> core set debug 1
When you have this debug enabled, you will see output during the processing of
every device state change. The important thing to look for is where the known
state of the device for each server is added together to determine the overall
state.
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
--- Notes On Large Installations
-------------------------------------------------------------------------------
On larger installations where you want a fully meshed network of buddies (i.e.
all servers have all the buddies of the remote servers), you may want some
method of distributing those buddies automatically so you don't need to modify
all servers (N+1) every time you add a new server to the cluster.
The problem there is that you're confined by what's allowed in XEP-0060, and
unfortunately that means modifying affiliations by individual JID (as opposed to
the various subscription access models, which are more flexible).
See here for details:
http://xmpp.org/extensions/xep-0060.html#owner-affiliations
One method for making this slightly easier is to utilize the #exec functionality
in configuration files, and dynamically generate the buddies via script that
pulls the information from a database, or to #include a file which is
automatically generated on all the servers when you add a new node to the
cluster.
Unfortunately this still requires a reload of res_jabber.so on all the servers,
but this could also be solved through the use of the Asterisk Manager Interface
(AMI).
So while this is not the ideal situation, it is programmatically solvable with
existing technologies and features found in Asterisk today.
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
--- Questions, Comments, and Bug Reports
-------------------------------------------------------------------------------
Please utilize the Asterisk issue tracker for all bug reports at
https://issues.asterisk.org

View File

@ -1,320 +0,0 @@
===============================================================================
===
=== Distributed Device State
===
=== Copyright (C) 2007-2008, Digium, Inc.
=== Russell Bryant <russell@digium.com>
===
===============================================================================
-------------------------------------------------------------------------------
--- IMPORTANT NOTE
-------------------------------------------------------------------------------
This document includes some information about using the res_ais module for
distributed events. However, it is important to note that res_ais is still
considered experimental, as the module exposes the binary format of events
over the network between servers. This format is still subject to change
between 1.6.X releases.
-------------------------------------------------------------------------------
--- INTRODUCTION
-------------------------------------------------------------------------------
Various changes have been made related to "event handling" in Asterisk.
One of the most important things included in these changes is the ability
to share certain events between servers. The two types of events that can
currently be shared between servers are:
1) MWI - Message Waiting Indication
- This gives you a high performance option for letting servers in a
cluster be aware of changes in the state of a mailbox. Instead of
having each server have to poll an ODBC database, this lets the server
that actually made the change to the mailbox generate an event which
will get distributed to the other servers that have subscribed to this
information.
2) Device State
- This lets servers in a local cluster inform each other about changes in
the state of a device on that particular server. When the state of a
device changes on any server, the overall state of that device across
the cluster will get recalculated. So, any subscriptions to the state
of a device, such as hints in the dialplan or an application like
Queue() which reads device state, will then reflect the state of a
device across a cluster.
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
--- OpenAIS Installation
-------------------------------------------------------------------------------
--- Description ---
The current solution for providing distributed events with Asterisk is done by
using the AIS (Application Interface Specification), which provides an API for
a distributed event service. While this API is standardized, this code has
been developed exclusively against the open source implementation of AIS called
OpenAIS.
For more information about OpenAIS, visit their web site:
http://www.openais.org/
--- Download ---
To quickly downlaod OpenAIS, just check it out of svn:
$ svn co http://svn.osdl.org/openais/trunk openais-trunk
--- Compile ---
$ cd openais-trunk
$ make PREFIX=/usr
--- Install ---
By default, the current Makefile installs the libraries into /usr/lib/openais/,
which is a little bit inconvenient. So, open up the Makefile, find the lines
that start with "LIBDIR=" to define the lib installation directory, and remove
the trailing "openais" so it just gets installed in /usr/lib/.
$ sudo make install PREFIX=/usr
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
--- OpenAIS Configuration
-------------------------------------------------------------------------------
Basic OpenAIS configuration to get this working is actually pretty easy. When
you install it, it will put some default configuration files into /etc/ais/.
Edit openais.conf ...
$ ${EDITOR:-vim} /etc/ais/openais.conf
The only section that you should need to change is the totem - interface
section.
totem {
...
interface {
interface {
ringnumber: 0
bindnetaddr: 10.19.0.0
mcastaddr: 226.94.1.1
mcastport: 5405
}
}
The default mcastaddr and mcastport is probably fine. But, you need to change
the bindnetaddr to match the network address that the nodes of your cluster
will communicate on.
The one other thing that you need to do is create a user called "ais".
$ sudo adduser ais
See the OpenAIS QUICKSTART file for more information on installing,
configuring, and testing OpenAIS.
$ cd openais-trunk
$ less QUICKSTART
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
--- Running OpenAIS
-------------------------------------------------------------------------------
While testing, I would recommend starting the aisexec application in the
foreground so that you can see debug messages that verify that the nodes have
discovered each other and joined the cluster.
$ sudo aisexec -f
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
--- Installing Asterisk
-------------------------------------------------------------------------------
Install Asterisk as usual. Just make sure that you run the configure script
after OpenAIS gets installed. That way, it will find the AIS header files and
will let you build the res_ais module. Check menuselect to make sure that
res_ais is going to get compiled and installed.
$ cd asterisk-source
$ ./configure
$ make menuselect
---> Resource Modules
If you have existing configuration on the system being used for testing, just
be sure to install the addition configuration file needed for res_ais.
$ sudo cp configs/ais.conf.sample /etc/asterisk/ais.conf
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
--- Configuring Asterisk
-------------------------------------------------------------------------------
First, ensure that you have a unique "entity ID" set for each server.
*CLI> core show settings
...
Entity ID: 01:23:45:67:89:ab
The code will attempt to generate a unique entity ID for you by reading
MAC addresses off of a network interface. However, you can also set it
manually in the [options] section of asterisk.conf.
$ sudo ${EDITOR:-vim} /etc/asterisk/asterisk.conf
[options]
...
entity_id=01:23:45:67:89:ab
Edit the Asterisk ais.conf to enable distributed events. For example, if you
would like to enable distributed device state, you should add the following
section to the file:
$ sudo ${EDITOR:-vim} /etc/asterisk/ais.conf
[device_state]
type=event_channel
publish_event=device_state
subscribe_event=device_state
For more information on the contents and available options in this configuration
file, please see the sample configuration file:
$ cd asterisk-source
$ less configs/ais.conf.sample
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
--- Basic Testing of Asterisk with OpenAIS
-------------------------------------------------------------------------------
If you have OpenAIS successfully installed and running, as well as Asterisk
with OpenAIS support successfully installed, configured, and running, then you
are ready to test out some of the AIS functionality in Asterisk.
The first thing to test is to verify that all of the nodes that you think should
be in your cluster are actually there. There is an Asterisk CLI command which
will list the current cluster members using the AIS Cluster Membership Service
(CLM).
*CLI> ais clm show members
=============================================================
=== Cluster Members =========================================
=============================================================
===
=== ---------------------------------------------------------
=== Node Name: 10.19.2.255
=== ==> ID: 0xa1302ff
=== ==> Address: 10.19.2.255
=== ==> Member: Yes
=== ---------------------------------------------------------
===
=== ---------------------------------------------------------
=== Node Name: 10.19.6.187
=== ==> ID: 0xa1306bb
=== ==> Address: 10.19.6.187
=== ==> Member: Yes
=== ---------------------------------------------------------
===
=============================================================
The next thing to do is to verify that you have successfully configured some
event channels in the Asterisk ais.conf file. This command is related to the
event service (EVT), so like the previous command, uses the syntax:
"ais <service name> <command>".
*CLI> ais evt show event channels
=============================================================
=== Event Channels ==========================================
=============================================================
===
=== ---------------------------------------------------------
=== Event Channel Name: mwi
=== ==> Publishing Event Type: mwi
=== ==> Subscribing to Event Type: mwi
=== ---------------------------------------------------------
===
=== ---------------------------------------------------------
=== Event Channel Name: device_state
=== ==> Publishing Event Type: device_state
=== ==> Subscribing to Event Type: device_state
=== ---------------------------------------------------------
===
=============================================================
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
--- Testing Distributed Device State
-------------------------------------------------------------------------------
The easiest way to test distributed device state is to use the DEVICE_STATE()
diaplan function. For example, you could have the following piece of dialplan
on every server:
[devstate_test]
exten => 1234,hint,Custom:mystate
exten => set_inuse,1,Set(DEVICE_STATE(Custom:mystate)=INUSE)
exten => set_not_inuse,1,Set(DEVICE_STATE(Custom:mystate)=NOT_INUSE)
exten => check,1,NoOp(Custom:mystate is ${DEVICE_STATE(Custom:mystate)})
Now, you can test that the cluster-wide state of "Custom:mystate" is what
you would expect after going to the CLI of each server and adjusting the state.
server1*CLI> console dial set_inuse@devstate_test
...
server2*CLI> console dial check@devstate_test
-- Executing [check@devstate_test:1] NoOp("OSS/dsp", "Custom:mystate is INUSE") in new stack
Various combinations of setting and checking the state on different servers can
be used to verify that it works as expected. Also, you can see the status of
the hint on each server, as well, to see how extension state would reflect the
state change with distributed device state:
server2*CLI> core show hints
-= Registered Asterisk Dial Plan Hints =-
1234@devstate_test : Custom:mystate State:InUse Watchers 0
One other helpful thing here during testing and debugging is to enable debug
logging. To do so, enable debug on the console in /etc/asterisk/logger.conf.
Also, enable debug at the Asterisk CLI.
*CLI> core set debug 1
When you have this debug enabled, you will see output during the processing of
every device state change. The important thing to look for is where the known
state of the device for each server is added together to determine the overall
state.
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
--- Question, Comments, and Bug Reports
-------------------------------------------------------------------------------
For now, please direct all feedback to Russell Bryant <russell@digium.com>.
-------------------------------------------------------------------------------

View File

@ -1,197 +0,0 @@
Asterisk External IVR Interface
-------------------------------
If you load app_externalivr.so in your Asterisk instance, you will
have an ExternalIVR() application available in your dialplan. This
application implements a simple protocol for bidirectional
communication with an external process, while simultaneous playing
audio files to the connected channel (without interruption or
blocking).
There are two ways to use ExternalIVR(); you can execute an
application on the local system or you can establish a socket
connection to a TCP/IP socket server.
To execute a local application use the form:
ExternalIVR(/full/path/to/applcation[(arguments)],options)
The arguments are optional, however if they exist they must be
enclosed in parentheses. The external application will be executed
in a child process, with its standard file handles connected to the
Asterisk process as follows:
stdin (0) - events will be received on this handle
stdout (1) - commands can be sent on this handle
stderr (2) - messages can be sent on this handle
* Use of stderr for message communication is discouraged because
it is not supported by a socket connection.
To create a socket connection use the form:
ExternalIVR(ivr://host[:port][(arguments)],options)
The host can be a fqdn or an ip address. The port is optional, if
not specified the default of 2949 will be used. The arguments are
optional however if they exist they must be enclosed in parentheses.
TheExternalIVR application will connect to the specified socket
server and establish a bi-directional socket connection, where
events will be sent to the TCP/IP server and commands received
from it.
The specific ExternalIVR options, events and commands are detailed
below.
Upon execution, if not specifically prevented by an option, the
ExternalIVR application will answer the channel (if it's not
already answered), create an audio generator, and start playing
silence. When your application wants to send audio to the channel,
it can send a command (see below) to add a file to the generator's
playlist. The generator will then work its way through the list,
playing each file in turn until it either runs out of files to
play, the channel is hung up, or a command is received to clear
the list and start with a new file. At any time, more files can
be added to the list and the generator will play them in sequence.
While the generator is playing audio (or silence), any DTMF events
received on the channel will be sent to the child process (see
below). Note that this can happen at any time, since the generator,
the child process and the channel thread are all executing
independently. It is very important that your external application
be ready to receive events from Asterisk at all times (without
blocking), or you could cause the channel to become non-responsive.
If the child process dies, or the remote server disconnects,
ExternalIVR() will notice this and hang up the channel
immediately (and also send a message to the log).
ExternalIVR() Options
---------------------
n: 'n'oanswer, don't answer an otherwise unanswered channel.
i: 'i'gnore_hangup, instead of sending an 'H' event and exiting
ExternalIVR() upon channel hangup, it instead sends an 'I'
event and expects the external application to exit the process.
d: 'd'ead, allows the operation of ExternalIVR() on channels that
have already been hung up.
Events
------
All events are be newline-terminated strings and are sent in the
following format:
tag,timestamp[,data]
The tag can be one of the following characters:
0-9: DTMF event for keys 0 through 9
A-D: DTMF event for keys A through D
*: DTMF event for key *
#: DTMF event for key #
H: the channel was hung up by the connected party
E: the script requested an exit
Z: the previous command was unable to be executed. There may be a
data element if appropriate, see specific commands below for
details
T: the play list was interrupted (see S command below)
D: a file was dropped from the play list due to interruption (the
data element will be the dropped file name) NOTE: this tag
conflicts with the D DTMF event tag. The existence of the data
element is used to differentiate between the two cases
F: a file has finished playing (the data element will be the file
name)
P: a response to the 'P' command (see below)
G: a response to the 'G' command (see below)
I: a Inform message, meant to "inform" the client that something
has occurred. (see Inform Messages below)
The timestamp will be 10 digits long, and will be a decimal
representation of a standard Unix epoch-based timestamp.
Commands
--------
All commands are newline-terminated strings.
The child process can send one of the following commands:
S,filename
A,filename
H,message
E,message
D,dtmf[,interval][,duration]
O,option
V,name=value[,name=value[,name=value]]
G,name[,name[,name]]
L,log_message
P,TIMESTAMP
T,TIMESTAMP
The 'S' command checks to see if there is a playable audio file with
the specified name, and if so, clear's the generator's playlist and
places the file onto the list. Note that the playability check does
not take into account transcoding requirements, so it is possible for
the file to not be played even though it was found. If the file does
not exist it sends a Z response with the data element set to the file
requested. If the generator is not currently playing silence, then T
and D events will be sent to signal the playlist interruption and
notify it of the files that will not be played.
The 'A' command checks to see if there is a playable audio file with
the specified name, and if so, appends it to the generator's playlist.
The same playability and exception rules apply as for the 'S' command.
The 'H' command logs the supplied message to the Asterisk log, stops
the generator, hangs up the channel and terminates the ExternalIVR
application.
The 'E' command logs the supplied message to the Asterisk log, stops
the generator and terminates the ExternalIVR application, but continues
execution in the dialplan.
The 'D' command generates DTMF on the channel, dtmf is a string of one or
more valid DTMF digits, w can be used for a half second pause. Interval
is optional, defaults to 250 milliseconds and is the time between digits.
Duration is optional and is the duration of each digit.
The 'O' command allows the child to set/clear options in the
ExternalIVR() application.
The supported options are:
(no)autoclear: Automatically interrupt and clear the playlist
upon reception of DTMF input.
The 'T' command will answer an unanswered channel. If it fails either
answering the channel or starting the generator it sends a Z response
of "Z,TIMESTAMP,ANSWER_FAILED" or "Z,TIMESTAMP,GENERATOR_FAILED"
respectively.
The 'V' command sets the specified channel variable(s) to the specified
value(s).
The 'G' command gets the specified channel variable(s). Multiple
variables are separated by commas. Response is in name=value format.
The 'P' command gets the parameters passed into ExternalIVR() minus
the options to ExternalIVR() itself:
If ExternalIVR() is executed as:
ExternalIVR(/usr/bin/foo(arg1,arg2),n)
The response to the 'P' command would be:
P,TIMESTAMP,/usr/bin/foo,arg1,arg2
NOTE: This is the only way for a TCP/IP server to be able to retrieve
the arguments.
The 'L' command puts a message into the Asterisk log. NOTE: This is
prefered to using stderr and is the only way for a TCP/IP server to
log a message.
Inform Messages
---------------
The only inform message that currently exists is a HANGUP message,
in the form I,TIMESTAMP,HANGUP and is used to inform of a hangup
when the i option is specified.
Errors
------
Any newline-terminated output generated by the child process on its
stderr handle will be copied into the Asterisk log.

View File

@ -1,32 +0,0 @@
Followme is now realtime-enabled:
To use, you must define two backend data structures, with the following fields:
followme:
name Name of this followme entry. Specified when invoking the FollowMe
application in the dialplan. This field is the only one which is
mandatory. All of the other fields will inherit the default from
followme.conf, if not specified in this data resource.
musicclass OR The musiconhold class used for the caller while waiting to be
musiconhold OR connected.
music
context Dialplan context from which to dial numbers
takecall DTMF used to accept the call and be connected. For obvious reasons,
this needs to be a single digit, '*', or '#'.
declinecall DTMF used to refuse the call, sending it onto the next step, if any.
call_from_prompt Prompt to play to the callee, announcing the call.
norecording_prompt The alternate prompt to play to the callee, when the caller
refuses to leave a name (or the option isn't set to allow them).
options_prompt Normally, "press 1 to accept, 2 to decline".
hold_prompt Message played to the caller while dialing the followme steps.
status_prompt Normally, "Party is not at their desk".
sorry_prompt Normally, "Unable to locate party".
followme_numbers:
name Name of this followme entry. Must match the name above.
ordinal An integer, specifying the order in which these numbers will be
followed.
phonenumber The telephone number(s) you would like to call, separated by '&'.
timeout Timeout associated with this step. See the followme documentation
for more information on how this value is handled.

View File

@ -1,3 +0,0 @@
This document now lives here:
http://svn.digium.com/view/asterisk/team/group/gsoc-2009/ideas.txt?view=markup

View File

@ -1,38 +0,0 @@
Using the Hoard Memory Allocator with Asterisk
==============================================
1) Install the Hoard Memory Allocator
Download Hoard from http://www.hoard.org/ either via a package or the source
tarball.
If downloading the source, unpack the tarball and follow the instructions in
the README file to build libhoard for your platform.
2) Configure asterisk
Run ./configure in the root of the asterisk source directory, passing the
--with-hoard option specifying the location of the libhoard shared library.
For example:
./configure --with-hoard=/usr/src/hoard-371/src/
Note that we don't specify the full path to libhoard.so, just the directory
where it resides.
3) Enable Hoard in menuselect
Run 'make menuselect' in the root of the asterisk source distribution. Under
'Compiler Flags' select the 'USE_HOARD_ALLOCATOR' option. If the option is
not available (shows up with XXX next to it) this means that configure was
not able to find libhoard.so. Check that the path you passed to the
--with-hoard option is correct. Re-run ./configure with the correct option
and then repeat step 3.
4) Make and install asterisk
Run the standard build commands:
# make
# make install

View File

@ -1,107 +0,0 @@
XMPP (Jabber) is an xml based protocol primarily for presence and messaging.
It is an open standard and there are several open server implementations,
ejabberd, jabberd(2), openfire, and many others, as well as several open source
clients, Psi, gajim, gaim etc. XMPP differs from other IM applications as it
is immensly extendable. This allows us to easily integrate Asterisk with
XMPP. The Asterisk XMPP Interface is provided by res_jabber.so.
res_jabber allows for Asterisk to connect to any XMPP (Jabber) server and
is also used to provide the connection interface for chan_jingle and
chan_gtalk.
Functions (JABBER_STATUS, JABBER_RECEIVE) and applications (JabberSend)
are exposed to the dialplan.
You'll find examples of how to use these functions/applications
hereafter. We assume that 'asterisk-xmpp' is properly configured in
jabber.conf.
**** JabberSend ****
JabberSend sends an XMPP message to a buddy. Example :
context default {
_XXXX => {
JabberSend(asterisk-xmpp,buddy@gmail.com,${CALLERID(name)} is calling ${EXTEN});
Dial(SIP/${EXTEN}, 30);
Hangup();
}
}
**** JABBER_STATUS ****
Note : as of version 1.6, the corresponding application JabberStatus is still
available, but marked as deprecated in favor of this function.
JABBER_STATUS stores the status of a buddy in a dialplan variable for
further use. Here is an AEL example of how to use it :
1234 => {
Set(STATUS=${JABBER_STATUS(asterisk-xmpp,buddy@gmail.com)});
if (${STATUS}=1) {
NoOp(User is online and active, ring his Gtalk client.);
Dial(Gtalk/asterisk-xmpp/buddy@gmail.com);
} else {
NoOp(Prefer the SIP phone);
Dial(SIP/1234);
}
}
**** JABBER_RECEIVE ****
JABBER_RECEIVE waits (up to X seconds) for a XMPP message and returns
its content. Used along with JabberSend (or SendText,
provided it's implemented in the corresponding channel type),
JABBER_RECEIVE helps Asterisk interact with users while calls flow
through the dialplan.
JABBER_RECEIVE/JabberSend are not tied to the XMPP media modules
chan_gtalk and chan_jingle, and can be used anywhere in the dialplan.
In the following example, calls targeted to extension 1234 (be it
accessed from SIP, DAHDI or whatever channel type) are controlled by
user bob@domain.com. Asterisk notifies him that a call is coming, and
asks him to take an action. This dialog takes place over an XMPP chat.
context from-ext {
1234 => {
Answer();
JabberSend(asterisk-xmpp,bob@jabber.org,Call from $CALLERID(num) - choose an option to process the call);
JabberSend(asterisk-xmpp,bob@jabber.org,1 : forward to cellphone);
JabberSend(asterisk-xmpp,bob@jabber.org,2 : forward to work phone);
JabberSend(asterisk-xmpp,bob@jabber.org,Default action : forward to your voicemail);
Set(OPTION=${JABBER_RECEIVE(asterisk-xmpp,bob@jabber.org,20)});
switch (${OPTION}) {
case 1:
JabberSend(asterisk-xmpp,bob@jabber.org,(Calling cellphone...);
Dial(SIP/987654321);
break;
case 2:
JabberSend(asterisk-xmpp,bob@jabber.org,(Calling workphone...);
Dial(SIP/${EXTEN});
break;
default:
Voicemail(${EXTEN}|u)
}
}
}
When calling from a GoogleTalk or Jingle client, the CALLERID(name)
is set to the XMPP id of the caller (i.e. his JID). In the
following example, Asterisk chats back with the caller identified by the
caller id. We also take advantage of the SendText implementation in
chan_gtalk (available in chan_jingle, and chan_sip as well), to
allow the caller to establish SIP calls from his GoogleTalk client :
context gtalk-in {
s => {
NoOp(Caller id : ${CALLERID(all)});
Answer();
SendText(Please enter the number you wish to call);
Set(NEWEXTEN=${JABBER_RECEIVE(asterisk-xmpp,${CALLERID(name)})});
SendText(Calling ${NEWEXTEN} ...);
Dial(SIP/${NEWEXTEN);
Hangup();
}
}
The maintainer of res_jabber is Philippe Sultan <philippe.sultan@gmail.com>.

View File

@ -1,28 +0,0 @@
-- Audit uses of usleep() to ensure that the argument is never greater than 1 million.
On some systems, that is considered an error. In any such cases, convert the usage
over to use nanosleep(), instead.
-- Convert all existing uses of astobj.h to astobj2.h
-- (chan_sip already in progress in a branch)
-- There are many places where large character buffers are allocated in structures. There is a new system for string handling that uses dynamically allocatted memory pools which is documented in include/asterisk/stringfields.h. Examples of where they are currently used are the ast_channel structure defined in include/asterisk/channel.h, some structures in chan_sip.c, and chan_dahdi.c.
-- There is a convenient set of macros defined in include/asterisk/linkedlists.h for handling linked lists. However, there are some open-coded lists throughout the code. Converting linked lists to use these macros will make list handling more consistent and reduce the possibility of coding errors.
-- Clean up and add Doxygen Documentation. When generating the documentation with make progdocs, a lot of warnings are generated. All of these need to be fixed. There is also plenty of code that still needs to be documented. All public API functions should be documented. That is pretty much anything in include/asterisk/*.h.
-- Check all ast_copy_string() usage to ensure that buffers are not being unnecessarily zeroed before or after calling it.
-- Find any remaining open-coded struct timeval manipulation and convert to use new time library functions.
-- Use the ast_str API in strings.h to replace multiple calls to strncat(), snprintf() with funky math, etc.
-- Audit all channel/res/app/etc. modules to ensure that they do not register any entrypoints with the Asterisk core until after they are ready to service requests; all config file reading/processing, structure allocation, etc. must be completed before Asterisk is made aware of any services the module offers.
-- Ensure that Realtime-enabled modules do not depend on the order of columns returned by the database lookup (example: outboundproxy and host settings in chan_sip).
-- Convert all usage of the signal(2) system API to the more portable sigaction(2) system API.
-- Find options and arguments in Asterisk which specify a time period in seconds or milliseconds and convert them to use the new ast_app_parse_timelen() function.
-- Find applications and functions in Asterisk that would benefit from being able to encode control characters and extended ASCII and embed calls to ast_get_encoded_char, ast_get_encoded_str, and ast_str_get_encoded_str.

View File

@ -1,10 +0,0 @@
(Jingle support in asterisk is experimental)
Jingle is an xmpp based protocol for signalling the transfer of media.
Currently asterisk supports the proprietary GoogleTalk protocol that is
very similar to jingle, and hopes to soon support true jingle specs
(JEP-166,167,176,177,180,181 etc) as more clients support the true standard.
Jingle's configuration is very similar to sip.conf only as we are not the
jabber server in this case you must provide a connection for the peer to
travel out on.
chan_gtalk is for supporting the non-jingle google/libjingle spec and
chan_jingle will continue to move in the direction of the correct spec.

View File

@ -1,65 +0,0 @@
Asterisk Realtime LDAP Driver
---------------------------
With this driver Asterisk can retrieve information from an LDAP drectory, including
sip/iax users, extensions and configuration.
See configs/res_ldap.conf.sample for a configuration file sample
Here is a LDAP diff sample:
# Base SIP Phones Entry
dn: uid=phone-base,dc=myDomain,dc=myDomainExt
objectClass: top
objectClass: AstAccount
objectClass: AstAccountSIP
uid: phone-base
AstAccountAccountingCode: baseacccode
AstAccountHost: dynamic
preferredLanguage: FR
AstAccountAMAFlags: billing
AstAccountContext: ldaptest
# A Phone. realmedPassword md5 hash should be the result of
# echo -n "UID:SIPRealm:Password" | md5sum
dn: uid=phone-test,dc=myDomain,dc=myDomainExt
objectClass: top
objectClass: AstAccount
objectClass: AstAccountSIP
uid: phone-test
AstAccountAccountingCode: acc-phone-base
AstAccountFullContact: Noone <1234>
AstAccountCallerID: 1234
AstAccountBaseDN: uid=phone-base,dc=myDomain,dc=myDomainExt
realmedPassword: {MD5}f67965da780bf9c70d6e337f938cee6f
# extensions,
dn: ou=extensions,dc=myDomain,dc=myDomainExt
ou: extensions
objectClass: top
objectClass: organizationalUnit
# Extension 100 Priority 1 in context ldaptest
dn: cn=100-1,ou=extensions,dc=myDomain,dc=myDomainExt
AstExtensionApplication: NoOp
AstExtensionApplicationData: TEST LDAP
objectClass: top
objectClass: AstExtension
AstExtensionExten: 100
AstExtensionContext: ldaptest
cn: 100-1
AstExtensionPriority: 1
# Extension 100 Priority 1 in context ldaptest
dn: cn=100-2,ou=extensions,dc=myDomain,dc=myDomainExt
objectClass: top
objectClass: AstExtension
AstExtensionExten: 100
AstExtensionContext: ldaptest
cn: 100-2
AstExtensionPriority: 2
AstExtensionApplication: hangup

View File

@ -1,78 +0,0 @@
About the MacroExclusive application
------------------------------------
Steve Davies <steve@connection-telecom.com
The MacroExclusive application was added to solve the problem of
synchronisation between calls running at the same time.
This is usually an issue when you have calls manipulating global
variables or the Asterisk database, but may be useful elsewhere.
Consider this example macro, intended to return a "next" number -
each caller is intended to get a different number:
[macro-next]
exten => s,1,Set(RESULT=${COUNT})
exten => s,n,SetGlobalVar(COUNT=$[${COUNT} + 1])
The problem is that in a box with high activity, you can be sure
that two calls will come along together - both will get the same
"RESULT", or the "COUNT" value will get mangled.
Calling this Macro via MacroExclusive will use a mutex to make sure
that only one call executes in the Macro at a time. This ensures
that the two lines execute as a unit.
Note that even the s,2 line above has its own race problem. Two
calls running that line at once will step on each other and
the count will end up as +1 rather than +2.
I've also been able to use MacroExclusive where I have two Macros
that need to be mutually exclusive.
Here's the example:
[macro-push]
; push value ${ARG2} onto stack ${ARG1}
exten => s,1,Set(DB(STACK/${ARG1})=${ARG2}^${DB(STACK/${ARG1})})
[macro-pop]
; pop top value from stack ${ARG1}
exten => s,1,Set(RESULT=${DB(STACK/${ARG1})})
exten => s,n,Set(DB(STACK/${ARG1})=${CUT(RESULT,^,2)})
exten => s,n,Set(RESULT=${CUT(RESULT,^,1)})
All that futzing with the STACK/${ARG1} in the astdb needs protecting
if this is to work. But neither push nor pop can run together.
So add this "pattern":
[macro-stack]
exten => Macro(${ARG1},${ARG2},${ARG3})
... and use it like so:
exten => s,1,MacroExclusive(stack,push,MYSTACK,bananas)
exten => s,n,MacroExclusive(stack,push,MYSTACK,apples)
exten => s,n,MacroExclusive(stack,push,MYSTACK,guavas)
exten => s,n,MacroExclusive(stack,push,MYSTACK,pawpaws)
exten => s,n,MacroExclusive(stack,pop,MYSTACK) ; RESULT gets pawpaws (yum)
exten => s,n,MacroExclusive(stack,pop,MYSTACK) ; RESULT gets guavas
exten => s,n,MacroExclusive(stack,pop,MYSTACK) ; RESULT gets apples
exten => s,n,MacroExclusive(stack,pop,MYSTACK) ; RESULT gets bananas
We get to the push and pop macros "via" the stack macro. But only one call
can execute the stack macro at a time; ergo, only one of push OR pop can
run at a time.
Hope people find this useful.
Lastly, its worth pointing out that only Macros that access shared data
will require this MacroExclusive protection. And Macro's that you call
with macroExclusive should run quickly or you will clog up your Asterisk
system.
Regards,
Steve

View File

@ -1,454 +0,0 @@
Changes to manager version 1.1:
-------------------------------
* SYNTAX CLEANUPS
-----------------
- Response: headers are now either
"Success" - Action OK, this message contains response
"Error" - Action failed, reason in Message: header
"Follows" - Action OK, response follows in following Events.
- Manager version changed to 1.1
* CHANGED EVENTS AND ACTIONS
----------------------------
- The Hold/Unhold events
- Both are now "Hold" events
For hold, there's a "Status: On" header, for unhold, status is off
- Modules chan_sip/chan_iax2
- The Ping Action
- Now use Response: success
- New header "Ping: pong" :-)
- The Events action
- Now use Response: Success
- The new status is reported as "Events: On" or "Events: Off"
- The JabberSend action
- The Response: header is now the first header in the response
- now sends "Response: Error" instead of "Failure"
- Newstate and Newchannel events
- these have changed headers
"State" -> ChannelStateDesc Text based channel state
-> ChannelState Numeric channel state
- The events does not send "<unknown>" for unknown caller IDs just an empty field
- Newchannel event
- Now includes "AccountCode"
- Newstate event
- Now has "CalleridNum" for numeric caller id, like Newchannel
- The event does not send "<unknown>" for unknown caller IDs just an empty field
- Newexten and VarSet events
- Now are part of the new Dialplan privilege class, instead of the Call class
- Dial event
- Event Dial has new headers, to comply with other events
- Source -> Channel Channel name (caller)
- SrcUniqueID -> UniqueID Uniqueid
(new) -> Dialstring Dialstring in app data
- Link and Unlink events
- The "Link" and "Unlink" bridge events in channel.c are now renamed to "Bridge"
- The link state is in the bridgestate: header as "Link" or "Unlink"
- For channel.c bridges, "Bridgetype: core" is added. This opens up for
bridge events in rtp.c
- The RTP channel also reports Bridge: events with bridgetypes
- rtp-native RTP native bridge
- rtp-direct RTP peer-2-peer bridge (NAT support only)
- rtp-remote Remote (re-invite) bridge. (Not reported yet)
- The "Rename" manager event has a renamed header, to use the same
terminology for the current channel as other events
- Oldname -> Channel
- The "NewCallerID" manager event has a renamed header
- CallerID -> CallerIDnum
- The event does not send "<unknown>" for unknown caller IDs just an empty field
- Reload event
- The "Reload" event sent at manager reload now has a new header and is now implemented
in more modules than manager to alert a reload. For channels, there's a CHANNELRELOAD
event to use.
(new) -> Module: manager | CDR | DNSmgr | RTP | ENUM
(new) -> Status: enabled | disabled
- To support reload events from other modules too
- cdr module added
- Status action replies (Event: Status)
Header changes
- link -> BridgedChannel
- Account -> AccountCode
- (new) -> BridgedUniqueid
- StatusComplete Event
New header
- (new) -> Items Number of channels reported
- The ExtensionStatus manager command now has a "StatusDesc" field with text description of the state
- The Registry and Peerstatus events in chan_sip and chan_iax now use "ChannelType" instead of "ChannelDriver"
- The Response to Action: IAXpeers now have a Response: Success header
- The MeetmeJoin now has caller ID name and Caller ID number fields (like MeetMeLeave)
- Action DAHDIShowChannels
Header changes
- Channel: -> DAHDIChannel
For active channels, the Channel: and Uniqueid: headers are added
You can now add a "DAHDIChannel: " argument to DAHDIshowchannels actions
to only get information about one channel.
- Event DAHDIShowChannelsComplete
New header
- (new) -> Items: Reports number of channels reported
- Action VoicemailUsersList
Added new headers for SayEnvelope, SayCID, AttachMessage, CanReview
and CallOperator voicemail configuration settings.
- Action Originate
Now requires the new Originate privilege.
If you call out to a subshell in Originate with the Application parameter,
you now also need the System privilege.
- Event QueueEntry now also returns the Uniqueid field like other events from app_queue.
- Action IAXpeerlist
Now includes if the IAX link is a trunk or not
- Action IAXpeers
Now includes if the IAX link is a trunk or not
- Action Ping
Response now includes a timestamp
- Action SIPshowpeer
Response now includes the configured parkinglot
- Action SKINNYshowline
Response now includes the configured parkinglot
* NEW ACTIONS
-------------
- Action: DataGet
Modules: data.c
Purpose:
To be able to retrieve the asterisk data tree.
Variables:
ActionID: <id> Action ID for this transaction. Will be returned.
Path: <data path> The path to the callback node to retrieve.
Filter: <filter> Which nodes to retrieve.
Search: <search> Search condition.
- Action: IAXregistry
Modules: chan_iax2
Purpose:
To list all IAX2 peers in the IAX registry with their registration status.
Variables:
ActionID: <id> Action ID for this transaction. Will be returned.
- Action: ModuleLoad
Modules: loader.c
Purpose:
To be able to unload, reload and unload modules from AMI.
Variables:
ActionID: <id> Action ID for this transaction. Will be returned.
Module: <name> Asterisk module name (including .so extension)
or subsystem identifier:
cdr, enum, dnsmgr, extconfig, manager, rtp, http
LoadType: load | unload | reload
The operation to be done on module
If no module is specified for a reload loadtype, all modules are reloaded
- Action: ModuleCheck
Modules: loader.c
Purpose:
To check version of a module - if it's loaded
Variables:
ActionID: <id> Action ID for this transaction. Will be returned.
Module: <name> Asterisk module name (not including extension)
Returns:
If module is loaded, returns version number of the module
Note: This will have to change. I don't like sending Response: failure
on both command not found (trying this command in earlier versions of
Asterisk) and module not found.
Also, check if other manager actions behave that way.
- Action: QueueSummary
Modules: app_queue
Purpose:
To request that the manager send a QueueSummary event (see the NEW EVENTS
section for more details).
Variables:
ActionID: <id> Action ID for this transaction. Will be returned.
Queue: <name> Queue for which the summary is desired
- Action: QueuePenalty
Modules: app_queue
Purpose:
To change the penalty of a queue member from AMI
Variables:
Interface: <tech/name> The interface of the member whose penalty you wish to change
Penalty: <number> The new penalty for the member. Must be nonnegative.
Queue: <name> If specified, only set the penalty for the member for this queue;
Otherwise, set the penalty for the member in all queues to which
he belongs.
- Action: QueueRule
Modules: app_queue
Purpose:
To list queue rules defined in queuerules.conf
Variables:
Rule: <name> The name of the rule whose contents you wish to list. If this variable
is not present, all rules in queuerules.conf will be listed.
- Action: Atxfer
Modules: none
Purpose:
Initiate an attended transfer
Variables:
Channel: The transferer channel's name
Exten: The extension to transfer to
Priority: The priority to transfer to
Context: The context to transfer to
- Action: SipShowRegistry
Modules: chan_sip
Purpose:
To request that the manager send a list of RegistryEntry events.
Variables:
ActionId: <id> Action ID for this transaction. Will be returned.
- Action: QueueReload
Modules: app_queue
Purpose:
To reload queue rules, a queue's members, a queue's parameters, or all of the aforementioned
Variable:
Queuename: <name> The name of the queue to take action on. If no queue name is specified, then all queues are affected
Rules: <yes or no> Whether to reload queue_rules.conf
Members: <yes or no> Whether to reload the queue's members
Parameters: <yes or no> Whether to reload the other queue options
- Action: QueueReset
Modules: app_queue
Purpose:
Reset the statistics for a queue
Variables:
Queuename: <name> The name of the queue on which to reset statistics
- Action: SKINNYdevices
Modules: chan_skinny
Purpose:
To list all SKINNY devices configured.
Variables:
ActionId: <id> Action ID for this transaction. Will be returned.
- Action: SKINNYlines
Modules: chan_skinny
Purpose:
To list all SKINNY lines configured.
Variables:
ActionId: <id> Action ID for this transaction. Will be returned.
- Action SKINNYshowdevice
Modules: chan_skinny
Purpose:
To list the information about a specific SKINNY device.
Variables:
Device: <device> Device to show information about.
- Action SKINNYshowline
Modules: chan_skinny
Purpose:
To list the information about a specific SKINNY line.
Variables:
Line: <line> Line to show information about.
- Action: CoreSettings
Modules: manager.c
Purpose: To report core settings, like AMI and Asterisk version,
maxcalls and maxload settings.
* Integrated in SVN trunk as of May 4th, 2007
Example:
Response: Success
ActionID: 1681692777
AMIversion: 1.1
AsteriskVersion: SVN-oej-moremanager-r61756M
SystemName: EDVINA-node-a
CoreMaxCalls: 120
CoreMaxLoadAvg: 0.000000
CoreRunUser: edvina
CoreRunGroup: edvina
- Action: CoreStatus
Modules: manager.c
Purpose: To report current PBX core status flags, like
number of concurrent calls, startup and reload time.
* Integrated in SVN trunk as of May 4th, 2007
Example:
Response: Success
ActionID: 1649760492
CoreStartupTime: 22:35:17
CoreReloadTime: 22:35:17
CoreCurrentCalls: 20
- Action: MixMonitorMute
Modules: app_mixmonitor.c
Purpose:
Mute / unMute a Mixmonitor recording.
Variables:
ActionId: <id> Action ID for this transaction. Will be returned.
Channel: the channel MixMonitor is running on
Direction: Which part of the recording to mute: read, write or both (from
channel, to channel or both channels).
State: Turn mute on or off : 1 to turn on, 0 to turn off.
* NEW EVENTS
------------
- Event: FullyBooted
Modules: loader.c
Purpose:
It is handy to have a single event notification for when all Asterisk
modules have been loaded--especially for situations like running
automated tests. This event will fire 1) immediately upon all modules
loading or 2) upon connection to the AMI interface if the modules have
already finished loading before the connection was made. This ensures
that a user will never miss getting a FullyBooted event. In vary rare
circumstances, it might be possible to get two copies of the message
if the AMI connection is made right as the modules finish loading.
Example:
Event: FullyBooted
Privilege: system,all
Status: Fully Booted
- Event: Transfer
Modules: res_features, chan_sip
Purpose:
Inform about call transfer, linking transferer with transfer target
You should be able to trace the call flow with this missing piece
of information. If it works out well, the "Transfer" event should
be followed by a "Bridge" event
The transfermethod: header informs if this is a pbx core transfer
or something done on channel driver level. For SIP, check the example:
Example:
Event: Transfer
Privilege: call,all
TransferMethod: SIP
TransferType: Blind
Channel: SIP/device1-01849800
SIP-Callid: 091386f505842c87016c4d93195ec67d@127.0.0.1
TargetChannel: SIP/device2-01841200
TransferExten: 100
TransferContext: default
- Event: ChannelUpdate
Modules: chan_sip.c, chan_iax2.c
Purpose:
Updates channel information with ID of PVT in channel driver, to
be able to link events on channel driver level.
* Integrated in SVN trunk as of May 4th, 2007
Example:
Event: ChannelUpdate
Privilege: system,all
Uniqueid: 1177271625.27
Channel: SIP/olle-01843c00
Channeltype: SIP
SIPcallid: NTQzYWFiOWM4NmE0MWRkZjExMzU2YzQ3OWQwNzg3ZmI.
SIPfullcontact: sip:olle@127.0.0.1:49054
- Event: NewAccountCode
Modules: cdr.c
Purpose: To report a change in account code for a live channel
Example:
Event: NewAccountCode
Privilege: call,all
Channel: SIP/olle-01844600
Uniqueid: 1177530895.2
AccountCode: Stinas account 1234848484
OldAccountCode: OllesAccount 12345
- Event: ModuleLoadReport
Modules: loader.c
Purpose: To report that module loading is complete. Some aggressive
clients connect very quickly to AMI and needs to know when
all manager events embedded in modules are loaded
Also, if this does not happen, something is seriously wrong.
This could happen to chan_sip and other modules using DNS.
Example:
Event: ModuleLoad
ModuleLoadStatus: Done
ModuleSelection: All
ModuleCount: 24
- Event: QueueSummary
Modules: app_queue
Purpose: To report a summary of queue information. This event is generated by
issuing a QueueSummary AMI action.
Example:
Event: QueueSummary
Queue: Sales
LoggedIn: 12
Available: 5
Callers: 10
HoldTime: 47
If an actionID was specified for the QueueSummary action, it will be appended as the
last line of the QueueSummary event.
- Event: AgentRingNoAnswer
Modules: app_queue
Purpose: Reports when a queue member was rung but there was no answer.
Example:
Event: AgentRingNoAnswer
Queue: Support
Uniqueid: 1177530895.2
Channel: SIP/1000-53aee458
Member: SIP/1000
MemberName: Thaddeus McClintock
Ringtime: 10
- Event: RegistryEntry
Modules: chan_sip
Purpose: Reports the state of the SIP registrations. This event is generated by
issuing a QueueSummary AMI action.
The RegistrationTime header is expressed as epoch.
Example:
Event: RegistryEntry
Host: sip.myvoipprovider.com
Port: 5060
Username: guestuser
Refresh: 105
State: Registered
RegistrationTime: 1219161830
If an actionID was specified for the SipShowRegistry action, it will be appended as the
last line of the RegistrationsComplete event.
- Event: ChanSpyStart
Modules: app_chanspy
Purpose: Reports when an active channel starts to be monitored by someone.
Example:
Event: ChanSpyStart
SpyerChannel: SIP/4321-13bba124
SpyeeChannel: SIP/1234-56ecc098
- Event: ChanSpyStop
Modules: app_chanspy
Purpose: Reports when an active channel stops to be monitored by someone.
Example:
Event: ChanSpyStop
SpyeeChannel: SIP/1234-56ecc098
* TODO
------

View File

@ -1,25 +0,0 @@
All modules must have at least the following:
static int load_module():
Do what you need to do when you get started. This function can return
AST_MODULE_LOAD_FAILURE if an action fails and the module is prevented from loading,
AST_MODULE_LOAD_DECLINE if the module can not load because of a non-critical failure
(the configuration file was not found), or AST_MODULE_LOAD_SUCCESS if the module
loaded fine.
static int unload_module():
The module will soon be unloaded. If any channels are using your
features, you should give them a softhangup in an effort to keep the
program from crashing. Generally, unload_module is only called when the
usecount is 0 or less, but the user can force unloading at their
discretion, and thus a module should do its best to comply (although in
some cases there may be no way to avoid a crash). This function should
return 0 on success and non-zero on failure (i.e. it cannot yet be
unloaded).
AST_MODULE_INFO_STANDARD(keystr, desc);
keystr: Applicable license for module. In most cases this is ASTERISK_GPL_KEY.
desc: Description of module.

View File

@ -1,747 +0,0 @@
OSP User Guide for Asterisk V1.6
9 February 2007
Table of Contents
Revision History 3
1 Introduction 4
2 OSP Toolkit 4
2.1 Build OSP Toolkit 4
2.1.1 Unpacking the Toolkit 4
2.1.2 Preparing to build the OSP Toolkit 5
2.1.3 Building the OSP Toolkit 5
2.1.4 Installing the OSP Toolkit 6
2.1.5 Building the Enrollment Utility 6
2.2 Obtain Crypto Files 6
3 Asterisk 8
3.1 Configure for OSP Support 8
3.1.1 Build Asterisk with OSP Toolkit 8
3.1.2 osp.conf 8
3.1.3 extensions.conf 10
3.1.4 dahdi/sip/iax/h323/ooh323.conf 13
3.2 OSP Dial Plan Functions 13
3.2.1 OSPAuth 13
3.2.2 OSPLookup 14
3.2.3 OSPNext 14
3.2.4 OSPFinish 15
3.3 extensions.conf Examples 15
3.3.1 Source Gateway 15
3.3.2 Destination Gateway 17
3.3.3 Proxy 18
Asterisk is a trademark of Digium, Inc.
TransNexus and OSP Secures are trademarks of TransNexus, Inc.
Revision History
Revision Date of Issue Description
1 26 Jul 2005 OSP Module User Guide for Asterisk V1.2
1.4 16 Jun 2006 OSP Module User Guide for Asterisk V1.4
1.6.0 13 Dec 2006 OSP Module User Guide for Asterisk V1.6
1.6.1 4 Jan 2007 Clarifying edits, add revision history, add general
purpose extensions.conf example
1.6.2 9 Feb 2007 Replace OSP Toolkit site from SIPfoundry with
SourceForge
1 Introduction
This document provides instructions on how to build and configure Asterisk V1.6 with the OSP Toolkit to enable secure, multi-lateral peering. This document is also available in the Asterisk source package as doc/osp.txt. The OSP Toolkit is an open source implementation of the OSP peering protocol and is freely available from https://sourceforge.net/projects/osp-toolkit. The OSP standard defined by the European Telecommunications Standards Institute (ETSI TS 101 321) www.etsi.org. If you have questions or need help, building Asterisk with the OSP Toolkit, please post your question on the OSP mailing list at https://lists.sourceforge.net/lists/listinfo/osp-toolkit-client.
2 OSP Toolkit
Please reference the OSP Toolkit document "How to Build and Test the OSP Toolkit” available from https://sourceforge.net/projects/osp-toolkit.
2.1 Build OSP Toolkit
The software listed below is required to build and use the OSP Toolkit:
* OpenSSL (required for building) - Open Source SSL protocol and Cryptographic Algorithms (version 0.9.7g recommended) from www.openssl.org. Pre-compiled OpenSSL binary packages are not recommended because of the binary compatibility issue.
* Perl (required for building) - A programming language used by OpenSSL for compilation. Any version of Perl should work. One version of Perl is available from www.activestate.com/Products/ActivePer. If pre-compiled OpenSSL packages are used, Perl package is not required.
* C compiler (required for building) - Any C compiler should work. The GNU Compiler Collection from www.gnu.org is routinely used for building the OSP Toolkit for testing.
* OSP Server (required for testing) - Access to any OSP server should work. An open source reference OSP server developed by Cisco System is available at http://www.vovida.org/applications/downloads/openosp/. RAMS, a java based open source OSP server is available at https://sourceforge.net/projects/rams. A free version of the TransNexus commercial OSP server may be downloaded from http://www.transnexus.com/OSP%20Toolkit/Peering_Server/VoIP_Peering_Server.htm.
2.1.1 Unpacking the Toolkit
After downloading the OSP Toolkit (version 3.3.6 or later release) from www.sourceforge.net, perform the following steps in order:
1) Copy the OSP Toolkit distribution into the directory where it will reside. The default directory for the OSP Toolkit is /usr/src.
2) Un-package the distribution file by executing the following command:
gunzip c OSPToolkit-###.tar.gz | tar xvf
Where ### is the version number separated by underlines. For example, if the version is 3.3.6, then the above command would be:
gunzip c OSPToolkit-3_3_6.tar.gz | tar xvf
A new directory (TK-3_3_6-20060303) will be created within the same directory as the tar file.
3) Go to the TK-3_3_6-20060303 directory by running this command:
cd TK-3_3_6-20060303
Within this directory, you will find directories and files similar to what is listed below if the command "ls -F" is executed):
ls -F
enroll/
RelNotes.txt lib/
README.txt license.txt
bin/ src/
crypto/ test/
include/
2.1.2 Preparing to build the OSP Toolkit
4) Compile OpenSSL according to the instructions provided with the OpenSSL distribution (You would need to do this only if you dont have openssl already).
5) Copy the OpenSSL header files (the *.h files) into the crypto/openssl directory within the osptoolkit directory. The OpenSSL header files are located under the openssl/include/openssl directory.
6) Copy the OpenSSL library files (libcrypto.a and libssl.a) into the lib directory within the osptoolkit directory. The OpenSSL library files are located under the openssl directory.
Note: Since the Asterisk requires the OpenSSL package. If the OpenSSL package has been installed, steps 4 through 6 are not necessary.
7) Optionally, change the install directory of the OSP Toolkit. Open the Makefile in the /usr/src/TK-3_3_6-20060303/src directory, look for the install path variable INSTALL_PATH, and edit it to be anywhere you want (defaults /usr/local).
Note: Please change the install path variable only if you are familiar with both the OSP Toolkit and the Asterisk.
2.1.3 Building the OSP Toolkit
8) From within the OSP Toolkit directory (/usr/src/TK-3_3_6-20060303), start the compilation script by executing the following commands:
cd src
make clean; make build
2.1.4 Installing the OSP Toolkit
The header files and the library of the OSP Toolkit should be installed. Otherwise, you must specify the OSP Toolkit path for the Asterisk.
9) Use the make script to install the Toolkit.
make install
The make script is also used to install the OSP Toolkit header files and the library into the INSTALL_PATH specified in the Makefile.
Note: Please make sure you have the rights to access the INSTALL_PATH directory. For example, in order to access /usr/local directory, root privileges are required.
2.1.5 Building the Enrollment Utility
Device enrollment is the process of establishing a trusted cryptographic relationship between the VoIP device and the OSP Server. The Enroll program is a utility application for establishing a trusted relationship between an OSP client and an OSP server. Please see the document "Device Enrollment" at http://www.transnexus.com/OSP%20Toolkit/OSP%20Toolkit%20Documents/Device_Enrollment.pdf for more information about the enroll application.
10) From within the OSP Toolkit directory (example: /usr/src/TK-3_3_6-20060303), execute the following commands at the command prompt:
cd enroll
make clean; make linux
Compilation is successful if there are no errors in the compiler output. The enroll program is now located in the OSP Toolkit/bin directory (example: /usr/src/ TK-3_3_6-20060303/bin).
2.2 Obtain Crypto Files
The OSP module in Asterisk requires three crypto files containing a local certificate (localcert.pem), private key (pkey.pem), and CA certificate (cacert_0.pem). Asterisk will try to load the files from the Asterisk public/private key directory - /var/lib/asterisk/keys. If the files are not present, the OSP module will not start and the Asterisk will not support the OSP protocol. Use the enroll.sh script from the toolkit distribution to enroll Asterisk with an OSP server and obtain the crypto files. Documentation explaining how to use the enroll.sh script (Device Enrollment) to enroll with an OSP server is available at http://www.transnexus.com/OSP%20Toolkit/OSP%20Toolkit%20Documents/Device_Enrollment.pdf. Copy the files generated by the enrollment process to the Asterisk /var/lib/asterisk/keys directory.
Note: The osptestserver.transnexus.com is configured only for sending and receiving non-SSL messages, and issuing signed tokens. If you need help, post a message on the OSP mailing list at https://lists.sourceforge.net/lists/listinfo/osp-toolkit-client..
The enroll.sh script takes the domain name or IP addresses of the OSP servers that the OSP Toolkit needs to enroll with as arguments, and then generates pem files cacert_#.pem, certreq.pem, localcert.pem, and pkey.pem. The # in the cacert file name is used to differentiate the ca certificate file names for the various SPs (OSP servers). If only one address is provided at the command line, cacert_0.pem will be generated. If 2 addresses are provided at the command line, 2 files will be generated cacert_0.pem and cacert_1.pem, one for each SP (OSP server). The example below shows the usage when the client is registering with osptestserver.transnexus.com.
./enroll.sh osptestserver.transnexus.com
Generating a 512 bit RSA private key
........................++++++++++++
.........++++++++++++
writing new private key to 'pkey.pem'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]: _______
State or Province Name (full name) [Some-State]: _______
Locality Name (eg, city) []:_______
Organization Name (eg, company) [Internet Widgits Pty Ltd]: _______
Organizational Unit Name (eg, section) []:_______
Common Name (eg, YOUR name) []:_______
Email Address []:_______
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:_______
An optional company name []:_______
Error Code returned from openssl command : 0
CA certificate received
[SP: osptestserver.transnexus.com]Error Code returned from getcacert command : 0
output buffer after operation: operation=request
output buffer after nonce: operation=request&nonce=1655976791184458
X509 CertInfo context is null pointer
Unable to get Local Certificate
depth=0 /CN=osptestserver.transnexus.com/O=OSPServer
verify error:num=18:self signed certificate
verify return:1
depth=0 /CN=osptestserver.transnexus.com/O=OSPServer
verify return:1
The certificate request was successful.
Error Code returned from localcert command : 0
The files generated should be copied to the /var/lib/asterisk/keys directory.
Note: The script enroll.sh requires AT&T korn shell (ksh) or any of its compatible variants. The /usr/src/TK-3_3_6-20060303/bin directory should be in the PATH variable. Otherwise, enroll.sh cannot find the enroll file.
3 Asterisk
In Asterisk, all OSP support is implemented as dial plan functions. In Asterisk V1.6, all combinations of routing between OSP and non-OSP enabled networks using any combination of SIP, H.323 and IAX protocols are fully supported. Section
3.1 describes the three easy steps to add OSP support to Asterisk:
1. Build Asterisk with OSP Toolkit
2. Configure osp.conf file
3. Cut and paste to extensions.conf
Sections 3.2 and 3.3 provide a detailed explanation of OSP dial plan functions and configuration examples. The detailed information provided in Sections 3.2 and 3.3 is not required for operating Asterisk with OSP, but may be helpful to developers who want to customize their Asterisk OSP implementation.
3.1 Configure for OSP Support
3.1.1 Build Asterisk with OSP Toolkit
The first step is to build Asterisk with the OSP Toolkit. If the OSP Toolkit is installed in the default install directory, /usr/local, no additional configuration is required. Compile Asterisk according to the instructions provided with the Asterisk distribution.
If the OSP Toolkit is installed in another directory, such as /myosp, Asterisk must be configured with the location of the OSP Toolkit. See the example below.
--with-osptk=/myosp
Note: Please change the install path only if you familiar with both the OSP Toolkit and the Asterisk. Otherwise, the change may result in Asterisk not supporting the OSP protocol.
3.1.2 osp.conf
The /etc/asterisk/osp.conf file, shown below, contains configuration parameters for using OSP. Two parameters, servicepoint and source must be configured. The default values for all other parameters will work well for standard OSP implementations.
;
; Open Settlement Protocol Sample Configuration File
;
; This file contains configuration of OSP server providers that
; are used by the Asterisk OSP module. The section "general" is
; reserved for global options. All other sections describe specific
; OSP Providers. The provider "default" is used when no provider is
; otherwise specified.
:
: The "servicepoint" and "source" parameters must be configured. For
; most implementations the other parameters in this file can be left
; unchanged.
;
[general]
;
; Enable cryptographic acceleration hardware.
;
accelerate=no
;
; Defines the status of tokens that Asterisk will validate.
; 0 - signed tokens only
; 1 - unsigned tokens only
; 2 - both signed and unsigned
; The default value is 0, i.e. the Asterisk will only validate signed
; tokens.
;
tokenformat=0
;
[default]
;
; List all service points (OSP servers) for this provider. Use
; either domain name or IP address. Most OSP servers use port 5045.
;
;servicepoint=http://osptestserver.transnexus.com:5045/osp
servicepoint=http://OSP server IP:5045/osp
;
; Define the "source" device for requesting OSP authorization.
: This value is usually the domain name or IP address of the
: the Asterisk server.
;
;source=domain name or [IP address in brackets]
source=[host IP]
;
; Define path and file name of crypto files.
; The default path for crypto file is /var/lib/asterisk/keys. If no
; path is defined, crypto files should be in
; /var/lib/asterisk/keys directory.
;
; Specify the private key file name.
; If this parameter is unspecified or not present, the default name
; will be the osp.conf section name followed by "-privatekey.pem"
; (for example: default-privatekey.pem)
;
privatekey=pkey.pem
;
; Specify the local certificate file.
; If this parameter is unspecified or not present, the default name
; will be the osp.conf section name followed by "- localcert.pem "
; (for example: default-localcert.pem)
;
localcert=localcert.pem
;
; Specify one or more Certificate Authority key file names. If none
; are listed, a single Certificate Authority key file name is added
; with the default name of the osp.conf section name followed by
; "-cacert_0.pem " (for example: default-cacert_0.pem)
;
cacert=cacert_0.pem
;
; Configure parameters for OSP communication between Asterisk OSP
; client and OSP servers.
;
; maxconnections: Max number of simultaneous connections to the
; provider OSP server (default=20)
; retrydelay: Extra delay between retries (default=0)
; retrylimit: Max number of retries before giving up (default=2)
; timeout: Timeout for response in milliseconds (default=500)
;
maxconnections=20
retrydelay=0
retrylimit=2
timeout=500
;
; Set the authentication policy.
; 0 - NO - Accept all calls.
; 1 YES - Accept calls with valid token or no token.
; Block calls with invalid token.
; 2 EXCLUSIVE Accept calls with valid token.
; Block calls with invalid token or no token.
; Default is 1,
;
authpolicy=1
;
; Set the default destination protocol. The OSP module supports
; SIP, H323, and IAX protocols. The default protocol is set to SIP.
;
defaultprotocol=SIP
3.1.3 extensions.conf
OSP functions are implemented as dial plan functions in the extensions.conf file. To add OSP support to your Asterisk server, simply copy and paste the text box below to your extensions.conf file. These functions will enable your Asterisk server to support all OSP call scenarios. Configuration of your Asterisk server for OSP is now complete.
[globals]
DIALOUT=DAHDI/1
[SrcGW] ; OSP Source Gateway
exten => _XXXX.,1,NoOp(OSPSrcGW)
; Set calling number if necessary
exten => _XXXX.,n,Set(CALLERID(numner)=1234567890)
; OSP lookup using default provider, if fail/error jump to lookup+101
exten => _XXXX.,n(lookup),OSPLookup(${EXTEN}||j)
; Deal with outbound call according to protocol
exten => _XXXX.,n,Macro(outbound)
; Dial to destination, 60 timeout, with call duration limit
exten => _XXXX.,n,Dial(${OSPDIALSTR},60,oL($[${OSPOUTTIMELIMIT}*1000]))
; Wait 1 second
exten => _XXXX.,n,Wait,1
; Hangup
exten => _XXXX.,n,Hangup
; Deal with OSPLookup fail/error
exten => _XXXX.,lookup+101,Hangup
exten => h,1,NoOp()
; OSP report usage
exten => h,n,OSPFinish(${HANGUPCAUSE})
[DstGW] ; OSP Destination Gateway
exten => _XXXX.,1,NoOp(OSPDstGW)
; Deal with inbound call according to protocol
exten => _XXXX.,n,Macro(inbound)
; Validate token using default provider, if fail/error jump to auth+101
exten => _XXXX.,n(auth),OSPAuth(|j)
; Ringing
exten => _XXXX.,n,Ringing
; Wait 1 second
exten => _XXXX.,n,Wait,1
; Check inbound call duration limit
exten => _XXXX.,n,GoToIf($[${OSPINTIMELIMIT}=0]?100:200)
; Without duration limit
exten => _XXXX.,100,Dial(${DIALOUT},15,o)
exten => _XXXX.,n,Goto(1000)
; With duration limit
exten => _XXXX.,200,Dial(${DIALOUT},15,oL($[${OSPINTIMELIMIT}*1000]))
exten => _XXXX.,n,Goto(1000)
; Wait 1 second
exten => _XXXX.,1000,Wait,1
; Hangup
exten => _XXXX.,n,Hangup
; Deal with OSPAuth fail/error
exten => _XXXX.,auth+101,Hangup
exten => h,1,NoOp()
; OSP report usage
exten => h,n,OSPFinish(${HANGUPCAUSE})
[GeneralProxy] ; Proxy
exten => _XXXX.,1,NoOp(OSP-GeneralProxy)
; Deal with inbound call according to protocol
exten => _XXXX.,n,Macro(inbound)
; Validate token using default provider, if fail/error jump to auth+101
exten => _XXXX.,n(auth),OSPAuth(|j)
; OSP lookup using default provider, if fail/error jump to lookup+101
exten => _XXXX.,n(lookup),OSPLookup(${EXTEN}||j)
; Deal with outbound call according to protocol
exten => _XXXX.,n,Macro(outbound)
; Dial to destination, 14 timeout, with call duration limit
exten => _XXXX.,n,Dial(${OSPDIALSTR},14,oL($[${OSPOUTTIMELIMIT}*1000]))
; OSP lookup next destination using default provider, if fail/error jump to next1+101
exten => _XXXX.,n(next1),OSPNext(${HANGUPCAUSE}||j)
; Deal with outbound call according to protocol
exten => _XXXX.,n,Macro(outbound)
; Dial to destination, 15 timeout, with call duration limit
exten => _XXXX.,n,Dial(${OSPDIALSTR},15,oL($[${OSPOUTTIMELIMIT}*1000]))
; OSP lookup next destination using default provider, if fail/error jump to next2+101
exten => _XXXX.,n(next2),OSPNext(${HANGUPCAUSE}||j)
; Deal with outbound call according to protocol
exten => _XXXX.,n,Macro(outbound)
; Dial to destination, 16 timeout, with call duration limit
exten => _XXXX.,n,Dial(${OSPDIALSTR},16,oL($[${OSPOUTTIMELIMIT}*1000]))
; Hangup
exten => _XXXX.,n,Hangup
; Deal with OSPAuth fail/error
exten => _XXXX.,auth+101,Hangup
; Deal with OSPLookup fail/error
exten => _XXXX.,lookup+101,Hangup
; Deal with OSPNext fail/error
exten => _XXXX.,next1+101,Hangup
; Deal with OSPNext fail/error
exten => _XXXX.,next2+101,Hangup
exten => h,1,NoOp()
; OSP report usage
exten => h,n,OSPFinish(${HANGUPCAUSE})
[macro-inbound]
exten => s,1,NoOp(inbound)
; Get inbound protocol
exten => s,n,Set(CHANTECH=${CUT(CHANNEL,/,1)})
exten => s,n,GoToIf($["${CHANTECH}"="H323"]?100)
exten => s,n,GoToIf($["${CHANTECH}"="IAX2"]?200)
exten => s,n,GoToIf($["${CHANTECH}"="SIP"]?300)
exten => s,n,GoTo(1000)
; H323 --------------------------------------------------------
; Get peer IP
exten => s,100,Set(OSPPEERIP=${H323CHANINFO(peerip)})
; Get OSP token
exten => s,n,Set(OSPINTOKEN=${H323CHANINFO(osptoken)})
exten => s,n,GoTo(1000)
; IAX ----------------------------------------------------------
; Get peer IP
exten => s,200,Set(OSPPEERIP=${IAXPEER(CURRENTCHANNEL)})
; Get OSP token
exten => s,n,Set(OSPINTOKEN=${IAXCHANINFO(osptoken)})
exten => s,n,GoTo(1000)
; SIP ----------------------------------------------------------
; Get peer IP
exten => s,300,Set(OSPPEERIP=${SIPCHANINFO(peerip)})
; Get OSP token
exten => s,n,Set(OSPINTOKEN=${SIP_HEADER(P-OSP-Auth-Token)})
exten => s,n,GoTo(1000)
; --------------------------------------------------------------
exten => s,1000,MacroExit
[macro-outbound]
exten => s,1,NoOp(outbound)
; Set calling number which may be translated
exten => s,n,Set(CALLERID(num)=${OSPCALLING})
; Check destinatio protocol
exten => s,n,GoToIf($["${OSPTECH}"="H323"]?100)
exten => s,n,GoToIf($["${OSPTECH}"="IAX2"]?200)
exten => s,n,GoToIf($["${OSPTECH}"="SIP"]?300)
; Something wrong
exten => s,n,Hangup
exten => s,n,GoTo(1000)
; H323 --------------------------------------------------------
; Set call id
exten => s,100,Set(H323CHANINFO(callid)=${OSPOUTCALLID})
; Set OSP token
exten => s,n,Set(H323CHANINFO(osptoken)=${OSPOUTTOKEN})
exten => s,n,GoTo(1000)
; IAX ----------------------------------------------------------
; Set OSP token
exten => s,200,Set(IAXCHANINFO(osptoken)=${OSPOUTTOKEN})
exten => s,n,GoTo(1000)
; SIP ----------------------------------------------------------
exten => s,300,GoTo(1000)
; --------------------------------------------------------------
exten => s,1000,MacroExit
3.1.4 dahdi/sip/iax/h323/ooh323.conf
There is no configuration required for OSP.
3.2 OSP Dial Plan Functions
This section provides a description of each OSP dial plan function.
3.2.1 OSPAuth
OSP token validation function.
Input:
* OSPPEERIP: last hop IP address
* OSPINTOKEN: inbound OSP token
* provider: OSP service provider configured in osp.conf. If it is empty, default provider is used.
* priority jump
Output:
* OSPINHANDLE: inbound OSP transaction handle
* OSPINTIMELIMIT: inbound call duration limit
* OSPAUTHSTATUS: OSPAuth return value. SUCCESS/FAILED/ERROR
3.2.2 OSPLookup
OSP lookup function.
Input:
* OSPPEERIP: last hop IP address
* OSPINHANDLE: inbound OSP transaction handle
* OSPINTIMELIMIT: inbound call duration limit
* exten: called number
* provider: OSP service provider configured in osp.conf. If it is empty, default provider is used.
* priority jump
* callidtypes: Generate call ID for the outbound call. h: H.323; s: SIP; i: IAX. Only h, H.323, has been implemented.
Output:
* OSPOUTHANDLE: outbound transaction handle
* OSPTECH: outbound protocol
* OSPDEST: outbound destination IP address
* OSPCALLED: outbound called nummber
* OSPCALLING: outbound calling number
* OSPOUTTOKEN: outbound OSP token
* OSPRESULTS: number of remaining destinations
* OSPOUTTIMELIMIT: outbound call duration limit
* OSPOUTCALLIDTYPES: same as input callidtypes
* OSPOUTCALLID: outbound call ID. Only for H.323
* OSPDIALSTR: outbound dial string
* OSPLOOKUPSTATUS: OSPLookup return value. SUCCESS/FAILED/ERROR
3.2.3 OSPNext
OSP lookup next function.
Input:
* OSPINHANDLE: inbound transaction handle
* OSPOUTHANDLE: outbound transaction handle
* OSPINTIMELIMIT: inbound call duration limit
* OSPOUTCALLIDTYPES: types of call ID generated by Asterisk.
* OSPRESULTS: number of remain destinations
* cause: last destination disconnect cause
* priority jump
Output:
* OSPTECH: outbound protocol
* OSPDEST: outbound destination IP address
* OSPCALLED: outbound called number
* OSPCALLING: outbound calling number
* OSPOUTTOKEN: outbound OSP token
* OSPRESULTS: number of remain destinations
* OSPOUTTIMELIMIT: outbound call duration limit
* OSPOUTCALLID: outbound call ID. Only for H.323
* OSPDIALSTR: outbound dial string
* OSPNEXTSTATUS: OSPLookup return value. SUCCESS/FAILED/ERROR
3.2.4 OSPFinish
OSP report usage function.
Input:
* OSPINHANDLE: inbound transaction handle
* OSPOUTHANDLE: outbound transaction handle
* OSPAUTHSTATUS: OSPAuth return value
* OSPLOOKUPTSTATUS: OSPLookup return value
* OSPNEXTSTATUS: OSPNext return value
* cause: last destination disconnect cause
* priority jump
Output:
* OSPFINISHSTATUS: OSPLookup return value. SUCCESS/FAILED/ERROR
3.3 extensions.conf Examples
The extensions.conf file example provided in Section 3.1 is designed to handle all OSP call scenarios when Asterisk is used as a source or destination gateway to the PSTN or as a proxy between VoIP networks. The extenstion.conf examples in this section are designed for specific use cases only.
3.3.1 Source Gateway
The examples in this section apply when the Asterisk server is being used as a TDM to VoIP gateway. Calls originate on the TDM network and are converted to VoIP by Asterisk. In these cases, the Asterisk server queries an OSP server to find a route to a VoIP destination. When the call ends, Asterisk sends a CDR to the OSP server.
For SIP protocol.
[SIPSrcGW]
exten => _XXXX.,1,NoOp(SIPSrcGW)
; Set calling number if necessary
exten => _XXXX.,n,Set(CALLERID(numner)=CallingNumber)
; OSP lookup using default provider, if fail/error jump to lookup+101
exten => _XXXX.,n(lookup),OSPLookup(${EXTEN}||j)
; Set calling number which may be translated
exten => _XXXX.,n,Set(CALLERID(num)=${OSPCALLING})
; Dial to destination, 60 timeout, with call duration limit
exten => _XXXX.,n,Dial(${OSPDIALSTR},60,oL($[${OSPOUTTIMELIMIT}*1000]))
; Wait 3 seconds
exten => _XXXX.,n,Wait,3
; Hangup
exten => _XXXX.,n,Hangup
; Deal with OSPLookup fail/error
exten => _XXXX.,lookup+101,Hangup
exten => h,1,NoOp()
; OSP report usage
exten => h,n,OSPFinish(${HANGUPCAUSE})
For IAX protocol.
[IAXSrcGW]
exten => _XXXX.,1,NoOp(IAXSrcGW)
; Set calling number if necessary
exten => _XXXX.,n,Set(CALLERID(numner)=CallingNumber)
; OSP lookup using default provider, if fail/error jump to lookup+101
exten => _XXXX.,n(lookup),OSPLookup(${EXTEN}||j)
; Set outbound OSP token
exten => _XXXX.,n,Set(IAXCHANINFO(osptoken)=${OSPOUTTOKEN})
; Set calling number which may be translated
exten => _XXXX.,n,Set(CALLERID(num)=${OSPCALLING})
; Dial to destination, 60 timeout, with call duration limit
exten => _XXXX.,n,Dial(${OSPDIALSTR},60,oL($[${OSPOUTTIMELIMIT}*1000]))
; Wait 3 seconds
exten => _XXXX.,n,Wait,3
; Hangup
exten => _XXXX.,n,Hangup
; Deal with OSPLookup fail/error
exten => _XXXX.,lookup+101,Hangup
exten => h,1,NoOp()
; OSP report usage
exten => h,n,OSPFinish(${HANGUPCAUSE})
For H.323 protocol.
[H323SrcGW]
exten => _XXXX.,1,NoOp(H323SrcGW)
; Set calling number if necessary
exten => _XXXX.,n,Set(CALLERID(numner)=CallingNumber)
; OSP lookup using default provider, if fail/error jump to lookup+101
; “h” parameter is used to generate a call id
; Cisco OSP gateways use this call id to validate OSP token
exten => _XXXX.,n(lookup),OSPLookup(${EXTEN}||jh)
; Set outbound call id
exten => _XXXX.,n,Set(OH323CHANINFO(callid)=${OSPOUTCALLID})
; Set outbound OSP token
exten => _XXXX.,n,Set(OH323CHANINFO(osptoken)=${OSPOUTTOKEN})
; Set calling number which may be translated
exten => _XXXX.,n,Set(CALLERID(num)=${OSPCALLING})
; Dial to destination, 60 timeout, with call duration limit
exten => _XXXX.,n,Dial(${OSPDIALSTR},60,oL($[${OSPOUTTIMELIMIT}*1000]))
; Wait 3 seconds
exten => _XXXX.,n,Wait,3
; Hangup
exten => _XXXX.,n,Hangup
; Deal with OSPLookup fail/error
exten => _XXXX.,lookup+101,Hangup
exten => h,1,NoOp()
; OSP report usage
exten => h,n,OSPFinish(${HANGUPCAUSE})
3.3.2 Destination Gateway
The examples in this section apply when Asterisk is being used as a VoIP to TDM gateway. VoIP calls are received by Asterisk which validates the OSP peering token and completes to the TDM network. After the call ends, Asterisk sends a CDR to the OSP server.
For SIP protocol
[SIPDstGW]
exten => _XXXX.,1,NoOp(SIPDstGW)
; Get peer IP
exten => _XXXX.,n,Set(OSPPEERIP=${SIPCHANINFO(peerip)})
; Get OSP token
exten => _XXXX.,n,Set(OSPINTOKEN=${SIP_HEADER(P-OSP-Auth-Token)})
; Validate token using default provider, if fail/error jump to auth+101
exten => _XXXX.,n(auth),OSPAuth(|j)
; Ringing
exten => _XXXX.,n,Ringing
; Wait 1 second
exten => _XXXX.,n,Wait,1
; Dial phone, timeout 15 seconds, with call duration limit
exten => _XXXX.,n,Dial(${DIALOUTANALOG}/${EXTEN:1},15,oL($[${OSPINTIMELIMIT}*1000]))
; Wait 3 seconds
exten => _XXXX.,n,Wait,3
; Hangup
exten => _XXXX.,n,Hangup
; Deal with OSPAuth fail/error
exten => _XXXX.,auth+101,Hangup
exten => h,1,NoOp()
; OSP report usage
exten => h,n,OSPFinish(${HANGUPCAUSE})
For IAX protocol
[IAXDstGW]
exten => _XXXX.,1,NoOp(IAXDstGW)
; Get peer IP
exten => _XXXX.,n,Set(OSPPEERIP=${IAXPEER(CURRENTCHANNEL)})
; Get OSP token
exten => _XXXX.,n,Set(OSPINTOKEN=${IAXCHANINFO(osptoken)})
; Validate token using default provider, if fail/error jump to auth+101
exten => _XXXX.,n(auth),OSPAuth(|j)
; Ringing
exten => _XXXX.,n,Ringing
; Wait 1 second
exten => _XXXX.,n,Wait,1
; Dial phone, timeout 15 seconds, with call duration limit
exten => _XXXX.,n,Dial(${DIALOUTANALOG}/${EXTEN:1},15,oL($[${OSPINTIMELIMIT}*1000]))
; Wait 3 seconds
exten => _XXXX.,n,Wait,3
; Hangup
exten => _XXXX.,n,Hangup
; Deal with OSPAuth fail/error
exten => _XXXX.,auth+101,Hangup
exten => h,1,NoOp()
; OSP report usage
exten => h,n,OSPFinish(${HANGUPCAUSE})
For H.323 protocol
[H323DstGW]
exten => _XXXX.,1,NoOp(H323DstGW)
; Get peer IP
exten => _XXXX.,n,Set(OSPPEERIP=${H323CHANINFO(peerip)})
; Get OSP token
exten => _XXXX.,n,Set(OSPINTOKEN=${H323CHANINFO(osptoken)})
; Validate token using default provider, if fail/error jump to auth+101
exten => _XXXX.,n(auth),OSPAuth(|j)
; Ringing
exten => _XXXX.,n,Ringing
; Wait 1 second
exten => _XXXX.,n,Wait,1
; Dial phone, timeout 15 seconds, with call duration limit
exten => _XXXX.,n,Dial(${DIALOUTANALOG}/${EXTEN:1},15,oL($[${OSPINTIMELIMIT}*1000]))
; Wait 3 seconds
exten => _XXXX.,n,Wait,3
; Hangup
exten => _XXXX.,n,Hangup
; Deal with OSPAuth fail/error
exten => _XXXX.,auth+101,Hangup
exten => h,1,NoOp()
; OSP report usage
exten => h,n,OSPFinish(${HANGUPCAUSE})
3.3.3 Proxy
The example in this section applies when Asterisk is a proxy between two VoIP networks.
[GeneralProxy]
exten => _XXXX.,1,NoOp(GeneralProxy)
; Get peer IP and inbound OSP token
; SIP, un-comment the following two lines.
;exten => _XXXX.,n,Set(OSPPEERIP=${SIPCHANINFO(peerip)})
;exten => _XXXX.,n,Set(OSPINTOKEN=${SIP_HEADER(P-OSP-Auth-Token)})
; IAX, un-comment the following 2 lines
;exten => _XXXX.,n,Set(OSPPEERIP=${IAXPEER(CURRENTCHANNEL)})
;exten => _XXXX.,n,Set(OSPINTOKEN=${IAXCHANINFO(osptoken)})
; H323, un-comment the following two lines.
;exten => _XXXX.,n,Set(OSPPEERIP=${OH323CHANINFO(peerip)})
;exten => _XXXX.,n,Set(OSPINTOKEN=${OH323CHANINFO(osptoken)})
;---------------------------------------------------------------
; Validate token using default provider, if fail/error jump to auth+101
exten => _XXXX.,n(auth),OSPAuth(|j)
; OSP lookup using default provider, if fail/error jump to lookup+101
; “h” parameter is used to generate a call id for H.323 destinations
; Cisco OSP gateways use this call id to validate OSP token
exten => _XXXX.,n(lookup),OSPLookup(${EXTEN}||jh)
; Set outbound call id and OSP token
; IAX, un-comment the following line.
;exten => _XXXX.,n,Set(IAXCHANINFO(osptoken)=${OSPOUTTOKEN})
; H323, un-comment the following two lines.
;exten => _XXXX.,n,Set(OH323CHANINFO(callid)=${OSPOUTCALLID})
;exten => _XXXX.,n,Set(OH323CHANINFO(osptoken)=${OSPOUTTOKEN})
;---------------------------------------------------------------
; Set calling number which may be translated
exten => _XXXX.,n,Set(CALLERID(num)=${OSPCALLING})
; Dial to destination, 14 timeout, with call duration limit
exten => _XXXX.,n,Dial(${OSPDIALSTR},14,oL($[${OSPOUTTIMELIMIT}*1000]))
; OSP lookup next destination using default provider, if fail/error jump to next1+101
exten => _XXXX.,n(next1),OSPNext(${HANGUPCAUSE}||j)
; Set outbound call id and OSP token
; IAX, un-comment the following line.
;exten => _XXXX.,n,Set(IAXCHANINFO(osptoken)=${OSPOUTTOKEN})
; H323, un-comment the following two lines.
;exten => _XXXX.,n,Set(OH323CHANINFO(callid)=${OSPOUTCALLID})
;exten => _XXXX.,n,Set(OH323CHANINFO(osptoken)=${OSPOUTTOKEN})
;---------------------------------------------------------------
; Set calling number which may be translated
exten => _XXXX.,n,Set(CALLERID(num)=${OSPCALLING})
; Dial to destination, 15 timeout, with call duration limit
exten => _XXXX.,n,Dial(${OSPDIALSTR},15,oL($[${OSPOUTTIMELIMIT}*1000]))
; OSP lookup next destination using default provider, if fail/error jump to next2+101
exten => _XXXX.,n(next2),OSPNext(${HANGUPCAUSE}||j)
; Set outbound call id and OSP token
; IAX, un-comment the following line.
;exten => _XXXX.,n,Set(IAXCHANINFO(osptoken)=${OSPOUTTOKEN})
; H323, un-comment the following two lines.
;exten => _XXXX.,n,Set(OH323CHANINFO(callid)=${OSPOUTCALLID})
;exten => _XXXX.,n,Set(OH323CHANINFO(osptoken)=${OSPOUTTOKEN})
;---------------------------------------------------------------
; Set calling number which may be translated
exten => _XXXX.,n,Set(CALLERID(num)=${OSPCALLING})
; Dial to destination, 16 timeout, with call duration limit
exten => _XXXX.,n,Dial(${OSPDIALSTR},16,oL($[${OSPOUTTIMELIMIT}*1000]))
; Hangup
exten => _XXXX.,n,Hangup
; Deal with OSPAuth fail/error
exten => _XXXX.,auth+101,Hangup
; Deal with OSPLookup fail/error
exten => _XXXX.,lookup+101,Hangup
; Deal with 1st OSPNext fail/error
exten => _XXXX.,next1+101,Hangup
; Deal with 2nd OSPNext fail/error
exten => _XXXX.,next2+101,Hangup
exten => h,1,NoOp()
; OSP report usage
exten => h,n,OSPFinish(${HANGUPCAUSE})
19

View File

@ -1,39 +0,0 @@
Asterisk Call Queues
--------------------
<template holder while we wait for input on a good README
for call queues. Please open a bug report and add text to this
document>
* General advice on the agent channel
-------------------------------------
* Using dynamic queue members
-----------------------------
* SIP channel configuration
---------------------------
Queues depend on the channel driver reporting the proper state
for each member of the queue. To get proper signalling on
queue members that use the SIP channel driver, you need to
enable a call limit (could be set to a high value so it
is not put into action) and also make sure that both inbound
and outbound calls are accounted for.
Example:
[general]
limitonpeer = yes
[peername]
type=friend
call-limit=10
* Other references
-------------------
* queuelog.txt
* queues-with-callback-members.txt
(Should we merge those documents into this?)

View File

@ -1,84 +0,0 @@
Real-time text in Asterisk
--------------------------
The SIP channel has support for real-time text conversation calls in Asterisk (T.140).
This is a way to perform text based conversations in combination with other media,
most often video. The text is sent character by character as a media stream.
During a call sometimes there are losses of T.140 packets and a solution to that is to
use redundancy in the media stream (RTP).
See "http://en.wikipedia.org/wiki/Text_over_IP"http://en.wikipedia.org/wiki/Text_over_IP
and RFC 5194 for more information.
The supported real-time text codec is t.140.
Real-time text redundancy support is now available in Asterisk.
ITU-T T.140
-----------
You can find more information about T.140 at www.itu.int. RTP is used for the transport T.140,
as specified in RFC 4103.
How to enable T.140
-------------------
In order to enable real-time text with redundancy in Asterisk, modify sip.conf to add:
[general]
disallow=all
allow=ulaw
allow = alaw
allow=t140
allow=t140red
textsupport=yes
videosupport=yes ; needed for proper SDP handling even if only text and voice calls are handled
allow=h263 ; at least one video codec as H.261, H.263 or H.263+ is needed.
The codec settings may change, depending on your phones. The important settings here are to allow
t140 and 140red and enable text support.
General information about real-time text support in Asterisk
------------------------------------------------------------
With the configuration above, calls will be supported with any combination of real-time text,
audio and video.
Text for both t140 and t140red is handled on channel and application level in Asterisk conveyed in
Text frames, with the subtype "t140". Text is conveyed in such frames usually only containing one or
a few characters from the real-time text flow. The packetization interval is 300 ms, handled on lower
RTP level, and transmission redundancy level is 2, causing one original and two redundant transmissions
of all text so that it is reliable even in high packet loss situations. Transmitting applications do not
need to bother about the transmission interval. The t140red support handles any buffering needed during
the packetization intervals.
Clients known to support text, audio/text or audio/video/text calls with Asterisk:
----------------------------------------------------------------------------------
- Omnitor Allan eC - SIP audio/video/text softphone
- AuPix APS-50 - audio/video/text softphone.
- France Telecom eConf audio/video/text softphone.
- SIPcon1 - open source SIP audio/text softphone available in Sourceforge.
Limitations
-----------
A known general problem with Asterisk is that when a client which uses audio/video/T.140 calls to
an Asterisk with T.140 media offered but video support not specified. In this case Asterisk handles
the sdp media description (m=) incorrectly, and the sdp response is not created correctly.
To solve this problem, turn on video support in Asterisk.
Modify sip.conf to add
[general]
videosupport=yes
allow=h263 ; at least one video codec as H.261, H.263 or H.263+ is needed.
The problem with sdp is a bug and is reported to Asterisk bugtracker, it has id 0012434.
Credits
-------
- Asterisk real-time text support is developed by AuPix
- Asterisk real-time text redundancy support is developed by Omnitor
The work with Asterisk real-time text redundancy was supported with funding from the National Institute
on Disability and Rehabilitation Research (NIDRR), U.S. Department of Education, under grant number
H133E040013 as part of a co-operation between the Telecommunication Access Rehabilitation Engineering
Research Center of the University of Wisconsin Trace Center joint with Gallaudet University, and Omnitor.
Olle E. Johansson, Edvina AB, has been a liason between the Asterisk project and this project.

View File

@ -1,124 +0,0 @@
/*
* res_config_sqlite - SQLite 2 support for Asterisk
*
* This module can be used as a static/RealTime configuration module, and a CDR
* handler. See the Doxygen documentation for a detailed description of the
* module, and the configs/ directory for the sample configuration file.
*/
/*
* Tables for res_config_sqlite.so.
*/
/*
* RealTime static table.
*/
CREATE TABLE ast_config (
id INTEGER,
cat_metric INT(11) NOT NULL DEFAULT 0,
var_metric INT(11) NOT NULL DEFAULT 0,
commented TINYINT(1) NOT NULL DEFAULT 0,
filename VARCHAR(128) NOT NULL DEFAULT '',
category VARCHAR(128) NOT NULL DEFAULT 'default',
var_name VARCHAR(128) NOT NULL DEFAULT '',
var_val TEXT NOT NULL DEFAULT '',
PRIMARY KEY (id)
);
CREATE INDEX ast_config__idx__cat_metric ON ast_config(cat_metric);
CREATE INDEX ast_config__idx__var_metric ON ast_config(var_metric);
CREATE INDEX ast_config__idx__filename_commented ON ast_config(filename, commented);
/*
* CDR table (this table is automatically created if non existent).
*/
CREATE TABLE ast_cdr (
id INTEGER,
clid VARCHAR(80) NOT NULL DEFAULT '',
src VARCHAR(80) NOT NULL DEFAULT '',
dst VARCHAR(80) NOT NULL DEFAULT '',
dcontext VARCHAR(80) NOT NULL DEFAULT '',
channel VARCHAR(80) NOT NULL DEFAULT '',
dstchannel VARCHAR(80) NOT NULL DEFAULT '',
lastapp VARCHAR(80) NOT NULL DEFAULT '',
lastdata VARCHAR(80) NOT NULL DEFAULT '',
start DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
answer DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
end DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
duration INT(11) NOT NULL DEFAULT 0,
billsec INT(11) NOT NULL DEFAULT 0,
disposition VARCHAR(45) NOT NULL DEFAULT '',
amaflags INT(11) NOT NULL DEFAULT 0,
accountcode VARCHAR(20) NOT NULL DEFAULT '',
uniqueid VARCHAR(32) NOT NULL DEFAULT '',
userfield VARCHAR(255) NOT NULL DEFAULT '',
PRIMARY KEY (id)
);
/*
* SIP RealTime table.
*/
CREATE TABLE ast_sip (
id INTEGER,
commented TINYINT(1) NOT NULL DEFAULT 0,
name VARCHAR(80) NOT NULL DEFAULT '',
host VARCHAR(31) NOT NULL DEFAULT '',
nat VARCHAR(5) NOT NULL DEFAULT 'no',
type VARCHAR(6) NOT NULL DEFAULT 'friend',
accountcode VARCHAR(20) DEFAULT NULL,
amaflags VARCHAR(13) DEFAULT NULL,
callgroup VARCHAR(10) DEFAULT NULL,
callerid VARCHAR(80) DEFAULT NULL,
cancallforward CHAR(3) DEFAULT 'yes',
directmedia CHAR(3) DEFAULT 'yes',
context VARCHAR(80) DEFAULT NULL,
defaultip VARCHAR(15) DEFAULT NULL,
dtmfmode VARCHAR(7) DEFAULT NULL,
fromuser VARCHAR(80) DEFAULT NULL,
fromdomain VARCHAR(80) DEFAULT NULL,
insecure VARCHAR(4) DEFAULT NULL,
language CHAR(2) DEFAULT NULL,
mailbox VARCHAR(50) DEFAULT NULL,
md5secret VARCHAR(80) DEFAULT NULL,
deny VARCHAR(95) DEFAULT NULL,
permit VARCHAR(95) DEFAULT NULL,
mask VARCHAR(95) DEFAULT NULL,
musiconhold VARCHAR(100) DEFAULT NULL,
pickupgroup VARCHAR(10) DEFAULT NULL,
qualify CHAR(3) DEFAULT NULL,
regexten VARCHAR(80) DEFAULT NULL,
restrictcid CHAR(3) DEFAULT NULL,
rtptimeout CHAR(3) DEFAULT NULL,
rtpholdtimeout CHAR(3) DEFAULT NULL,
secret VARCHAR(80) DEFAULT NULL,
setvar VARCHAR(100) DEFAULT NULL,
disallow VARCHAR(100) DEFAULT 'all',
allow VARCHAR(100) DEFAULT 'g729,ilbc,gsm,ulaw,alaw',
fullcontact VARCHAR(80) NOT NULL DEFAULT '',
ipaddr VARCHAR(15) NOT NULL DEFAULT '',
port INT(11) NOT NULL DEFAULT 0,
regserver VARCHAR(100) DEFAULT NULL,
regseconds INT(11) NOT NULL DEFAULT 0,
username VARCHAR(80) NOT NULL DEFAULT '',
PRIMARY KEY (id)
UNIQUE (name)
);
CREATE INDEX ast_sip__idx__commented ON ast_sip(commented);
/*
* Dialplan RealTime table.
*/
CREATE TABLE ast_exten (
id INTEGER,
commented TINYINT(1) NOT NULL DEFAULT 0,
context VARCHAR(80) NOT NULL DEFAULT '',
exten VARCHAR(40) NOT NULL DEFAULT '',
priority INT(11) NOT NULL DEFAULT 0,
app VARCHAR(128) NOT NULL DEFAULT '',
appdata VARCHAR(128) NOT NULL DEFAULT '',
PRIMARY KEY (id)
);
CREATE INDEX ast_exten__idx__commented ON ast_exten(commented);
CREATE INDEX ast_exten__idx__context_exten_priority ON ast_exten(context, exten, priority);

View File

@ -1,75 +0,0 @@
Overview
-------
Asterisk currently supports configurable RTP packetization per codec for
select RTP-based channels.
Channels
-------
These channel drivers allow RTP packetization on a user/peer/friend
or global level:
chan_sip
chan_skinny
chan_h323
chan_ooh323 (Asterisk-Addons)
chan_gtalk
chan_jingle
Configuration
-------
To set a desired packetization interval on a specific codec,
append that inteval to the allow= statement.
Example:
allow=ulaw:30,alaw,g729:60
No packetization is specified in the case of alaw in this example,
so the default of 20ms is used.
Autoframing
-------
In addition, chan_sip has the ability to negotiate the desired
framing at call establishment.
In sip.conf if autoframing=yes is set in the global section, then
all calls will try to set the packetization based on the remote
endpoint's preferences. This behaviour depends on the endpoints
ability to present the desired packetization (ptime:) in the SDP.
If the endpoint does not include a ptime attribute, the call will
be established with 20ms packetization.
Autoframing can be set at the global level or on a user/peer/friend
basis. If it is enabled at the global level, it applies to all
users/peers/friends regardless of their prefered codec packetization.
Codec framing options
-------
The following table lists the minimum and maximum values that are
valid per codec, as well as the increment value used for each.
Please note that the maximum values here are only recommended
maximums, and should not exceed the RTP MTU.
Name Min Max Default Increment
g723 30 300 30 30
gsm 20 300 20 20
ulaw 10 150 20 10
alaw 10 150 20 10
g726 10 300 20 10
ADPCM 10 300 20 10
SLIN 10 70 20 10
lpc10 20 20 20 20
g729 10 230 20 10
speex 10 60 20 10
ilbc 30 30 30 30
g726_aal2 10 300 20 10
Invalid framing options are handled based on the following rules:
1. If the specified framing is less than the codec's minimum, then
the minimum value is used.
2. If the specific framing is greater than the codec's maximum, then
the maximum value is used
3. If the specificed framing does not meet the increment requirement,
the specified framing is rounded down to the closest valid
framing options.
example allow=ulaw:33 will set the codec to 30ms framing
4. If no framing is specified in the allow= directive, then the
codec default is used.

View File

@ -1,126 +0,0 @@
What is the problem with SIP retransmits?
-----------------------------------------
Sometimes you get messages in the console like these:
- "retrans_pkt: Hanging up call XX77yy - no reply to our critical packet."
- "retrans_pkt: Cancelling retransmit of OPTIONs"
The SIP protocol is based on requests and replies. Both sides send
requests and wait for replies. Some of these requests are important.
In a TCP/IP network many things can happen with IP packets. Firewalls,
NAT devices, Session Border Controllers and SIP Proxys are in the
signalling path and they will affect the call.
SIP Call setup - INVITE-200 OK - ACK
------------------------------------
To set up a SIP call, there's an INVITE transaction. The SIP software that
initiates the call sends an INVITE, then wait to get a reply. When a
reply arrives, the caller sends an ACK. This is a three-way handshake
that is in place since a phone can ring for a very long time and
the protocol needs to make sure that all devices are still on line
when call setup is done and media starts to flow.
- The first reply we're waiting for is often a "100 trying".
This message means that some type of SIP server has received our
request and makes sure that we will get a reply. It could be
the other endpoint, but it could also be a SIP proxy or SBC
that handles the request on our behalf.
- After that, you often see a response in the 18x class, like
"180 ringing" or "183 Session Progress". This typically means that our
request has reached at least one endpoint and something
is alerting the other end that there's a call coming in.
- Finally, the other side answers and we get a positive reply,
"200 OK". This is a positive answer. In that message, we get an
address that goes directly to the device that answers. Remember,
there could be multiple phones ringing. The address is specified
by the Contact: header.
- To confirm that we can reach the phone that answered our call,
we now send an ACK to the Contact: address. If this ACK doesn't
reach the phone, the call fails. If we can't send an ACK, we
can't send anything else, not even a proper hangup. Call
signalling will simply fail for the rest of the call and there's
no point in keeping it alive.
- If we get an error response to our INVITE, like "Busy" or
"Rejected", we send the ACK to the same address as we sent the
INVITE, to confirm that we got the response.
In order to make sure that the whole call setup sequence works and that
we have a call, a SIP client retransmits messages if there's too much
delay between request and expected response. We retransmit a number of
times while waiting for the first response. We retransmit the answer to an
incoming INVITE while waiting for an ACK. If we get multiple answers,
we send an ACK to each of them.
If we don't get the ACK or don't get an answer to our INVITE,
even after retransmissions, we will hangup the call with the first
error message you see above.
Other SIP requests
------------------
Other SIP requests are only based on request - reply. There's
no ACK, no three-way handshake. In Asterisk we mark some of
these as CRITICAL - they need to go through for the call to
work as expected. Some are non-critical, we don't really care
what happens with them, the call will go on happily regardless.
The qualification process - OPTIONS
-----------------------------------
If you turn on qualify= in sip.conf for a device, Asterisk will
send an OPTIONS request every minute to the device and check
if it replies. Each OPTIONS request is retransmitted a number
of times (to handle packet loss) and if we get no reply, the
device is considered unreachable. From that moment, we will
send a new OPTIONS request (with retransmits) every tenth
second.
Why does this happen?
---------------------
For some reason signalling doesn't work as expected between
your Asterisk server and the other device. There could be many reasons
why this happens.
- A NAT device in the signalling path
A misconfigured NAT device is in the signalling path
and stops SIP messages.
- A firewall that blocks messages or reroutes them wrongly
in an attempt to assist in a too clever way.
- A SIP middlebox (SBC) that rewrites contact: headers
so that we can't reach the other side with our reply
or the ACK.
- A badly configured SIP proxy that forgets to add
record-route headers to make sure that signalling works.
- Packet loss. IP and UDP are unreliable transports. If
you loose too many packets the retransmits doesn't help
and communication is impossible. If this happens with
signalling, media would be unusable anyway.
What can I do?
--------------
Turn on SIP debug, try to understand the signalling that happens
and see if you're missing the reply to the INVITE or if the
ACK gets lost. When you know what happens, you've taken the
first step to track down the problem. See the list above and
investigate your network.
For NAT and Firewall problems, there are many documents
to help you. Start with reading sip.conf.sample that is
part of your Asterisk distribution.
The SIP signalling standard, including retransmissions
and timers for these, is well documented in the IETF
RFC 3261.
Good luck sorting out your SIP issues!
/Olle E. Johansson
-- oej (at) edvina.net, Sweden, 2008-07-22
-- http://www.voip-forum.com

View File

@ -1,97 +0,0 @@
Asterisk SIP/TLS Transport
==========================
When using TLS the client will typically check the validity of the
certificate chain. So that means you either need a certificate that is
signed by one of the larger CAs, or if you use a self signed certificate
you must install a copy of your CA certificate on the client.
So far this code has been test with:
- Asterisk as client and server (TLS and TCP)
- Polycom Soundpoint IP Phones (TLS and TCP)
Polycom phones require that the host (ip or hostname) that is
configured match the 'common name' in the certificate
- Minisip Softphone (TLS and TCP)
- Cisco IOS Gateways (TCP only)
- SNOM 360 (TLS only)
- Zoiper Biz Softphone (TLS and TCP)
sip.conf options
----------------
tlsenable=[yes|no]
Enable TLS server, default is no
tlsbindaddr=<ip address>
Specify IP address to bind TLS server to, default is 0.0.0.0
tlscertfile=</path/to/certificate>
The server's certificate file. Should include the key and
certificate. This is mandatory if your going to run a TLS server.
tlscafile=</path/to/certificate>
If the server your connecting to uses a self signed certificate
you should have their certificate installed here so the code can
verify the authenticity of their certificate.
tlscadir=</path/to/ca/dir>
A directory full of CA certificates. The files must be named with
the CA subject name hash value.
(see man SSL_CTX_load_verify_locations for more info)
tlsdontverifyserver=[yes|no]
If set to yes, don't verify the servers certificate when acting as
a client. If you don't have the server's CA certificate you can
set this and it will connect without requiring tlscafile to be set.
Default is no.
tlscipher=<SSL cipher string>
A string specifying which SSL ciphers to use or not use
A list of valid SSL cipher strings can be found at:
http://www.openssl.org/docs/apps/ciphers.html#CIPHER_STRINGS
Sample config
-------------
Here are the relevant bits of config for setting up TLS between 2
asterisk servers. With server_a registering to server_b
On server_a:
[general]
tlsenable=yes
tlscertfile=/etc/asterisk/asterisk.pem
tlscafile=/etc/ssl/ca.pem ; This is the CA file used to generate both certificates
register => tls://100:test@192.168.0.100:5061
[101]
type=friend
context=internal
host=192.168.0.100 ; The host should be either IP or hostname and should
; match the 'common name' field in the servers certificate
secret=test
dtmfmode=rfc2833
disallow=all
allow=ulaw
transport=tls
port=5061
On server_b:
[general]
tlsenable=yes
tlscertfile=/etc/asterisk/asterisk.pem
[100]
type=friend
context=internal
host=dynamic
secret=test
dtmfmode=rfc2833
disallow=all
allow=ulaw
;You can specify transport= and port=5061 for TLS, but its not necessary in
;the server configuration, any type of SIP transport will work
;transport=tls
;port=5061

View File

@ -1,137 +0,0 @@
===============================================================================
===============================================================================
=== Asterisk SMDI (Simple Message Desk Interface) integration =================
===============================================================================
===============================================================================
===============================================================================
===== 1) Accessing SMDI information in the dialplan. ==========================
===============================================================================
There are two dialplan functions that can be used to access the details of
incoming SMDI messages.
*CLI> core show function SMDI_MSG_RETRIEVE
-= Info about function 'SMDI_MSG_RETRIEVE' =-
[Syntax]
SMDI_MSG_RETRIEVE(<smdi port>,<search key>[,timeout[,options]])
[Synopsis]
Retrieve an SMDI message.
[Description]
This function is used to retrieve an incoming SMDI message. It returns
an ID which can be used with the SMDI_MSG() function to access details of
the message. Note that this is a destructive function in the sense that
once an SMDI message is retrieved using this function, it is no longer in
the global SMDI message queue, and can not be accessed by any other Asterisk
channels. The timeout for this function is optional, and the default is
3 seconds. When providing a timeout, it should be in milliseconds.
The default search is done on the forwarding station ID. However, if
you set one of the search key options in the options field, you can change
this behavior.
Options:
t - Instead of searching on the forwarding station, search on the message
desk terminal.
n - Instead of searching on the forwarding station, search on the message
desk number.
*CLI> core show function SMDI_MSG
-= Info about function 'SMDI_MSG' =-
[Syntax]
SMDI_MSG(<message_id>,<component>)
[Synopsis]
Retrieve details about an SMDI message.
[Description]
This function is used to access details of an SMDI message that was
pulled from the incoming SMDI message queue using the SMDI_MSG_RETRIEVE()
function.
Valid message components are:
station - The forwarding station
callerid - The callerID of the calling party that was forwarded
type - The call type. The value here is the exact character
that came in on the SMDI link. Typically, example values
are: D - Direct Calls, A - Forward All Calls,
B - Forward Busy Calls, N - Forward No Answer Calls
Here is an example of how to use these functions:
; Retrieve the SMDI message that is associated with the number that
; was called in Asterisk.
exten => _0XXX,1,Set(SMDI_MSG_ID=${SMDI_MSG_RETRIEVE(/dev/tty0,${EXTEN})})
; Ensure that the message was retrieved.
exten => _0XXX,n,GotoIf($["x${SMDI_MSG_ID}" != "x"]?processcall:hangup)
exten => _0XXX,n(hangup),NoOp(No SMDI message retrieved for ${EXTEN})
; Grab the details out of the SMDI message.
exten => _0XXX,n(processcall),NoOp(Message found for ${EXTEN})
exten => _0XXX,n,Set(SMDI_EXTEN=${SMDI_MSG(${SMDI_MSG_ID},station)})
exten => _0XXX,n,Set(SMDI_CID=${SMDI_MSG(${SMDI_MSG_ID},callerid)})
; Map SMDI message types to the right voicemail option. If it is "B", use the
; busy option. Otherwise, use the unavailable option.
exten => _0XXX,n,GotoIf($["${SMDI_MSG(${SMDI_MSG_ID},type)}" == "B"]?usebusy:useunavail)
exten => _0XXX,n(usebusy),Set(SMDI_VM_TYPE=b)
exten => _0XXX,n,Goto(continue)
exten => _0XXX,n,(useunavil),Set(SMDI_VM_TYPE=u)
exten => _0XXX,n(continue),NoOp( Process the rest of the call ... )
===============================================================================
===== 2) Ensuring complete MWI information over SMDI ==========================
===============================================================================
Another change has been made to ensure that MWI state is properly propagated
over the SMDI link. This replaces the use of externnotify=smdi for
voicemail.conf. The issue is that we have to poll mailboxes occasionally for
changes that were made using an IMAP client. So, this ability was added to
res_smdi. To configure this, there is a new section in smdi.conf. It looks
like this:
[mailboxes]
; This section configures parameters related to MWI handling for the SMDI link.
;
; This option configures the polling interval used to check to see if the
; mailboxes have any new messages. This option is specified in seconds.
; The default value is 10 seconds.
;
;pollinginterval=10
;
; Before specifying mailboxes, you must specify an SMDI interface. All mailbox
; definitions that follow will correspond to that SMDI interface. If you
; specify another interface, then all definitions following that will correspond
; to the new interface.
;
; Every other entry in this section of the configuration file is interpreted as
; a mapping between the mailbox ID on the SMDI link, and the local Asterisk
; mailbox name. In many cases, they are the same thing, but they still must be
; listed here so that this module knows which mailboxes it needs to pay
; attention to.
;
; Syntax:
; <SMDI mailbox ID>=<Asterisk Mailbox Name>[@Asterisk Voicemail Context]
;
; If no Asterisk voicemail context is specified, "default" will be assumed.
;
;
;smdiport=/dev/ttyS0
;2565551234=1234@vmcontext1
;2565555678=5678@vmcontext2
;smdiport=/dev/ttyS1
;2565559999=9999
===============================================================================
===============================================================================
===============================================================================

View File

@ -1,147 +0,0 @@
* The SMS application
---------------------
SMS() is an application to handles calls to/from text message capable phones and
message centres using ETSI ES 201 912 protocol 1 FSK messaging over analog calls.
Basically it allows sending and receiving of text messages over the PSTN. It is
compatible with BT Text service in the UK and works on ISDN and PSTN lines. It is
designed to connect to an ISDN or DAHDI interface directly and uses FSK so would
probably not work over any sort of compressed link (like a VoIP call using GSM codec).
Typical applications include:-
1. Connection to a message centre to send text messages - probably initiated via the
manager interface or "outgoing" directory
2. Connection to an POTS line with an SMS capable phone to send messages - probably
initiated via the manager interface or "outgoing" directory
3. Acceptance of calls from the message centre (based on CLI) and storage of
received messages
4. Acceptance of calls from a POTS line with an SMS capable phone and storage of
received messages
* Arguments to sms():
- First argument is queue name
- Second is options:
a: SMS() is to act as the answering side, and so send the initial FSK frame
s: SMS() is to act as a service centre side rather than as terminal equipment
- If a third argument is specified, then SMS does not handle the call at all,
but takes the third argument as a destination number to send an SMS to
- The forth argument onward is a message to be queued to the number in the
third argument. All this does is create the file in the me-sc directory.
If 's' is set then the number is the source
address and the message placed in the sc-me directory.
All text messages are stored in /var/spool/asterisk/sms
A log is recorded in /var/log/asterisk/sms
There are two subdirectories called sc-me.<queuename> holding all
messages from service centre to phone, and me-sc.<queuename> holding all
messages from phone to service centre.
In each directory are messages in files, one per file, using any filename not
starting with a dot.
When connected as a service centre, SMS(s) will send all messages waiting in
the sc-me-<queuename> directory, deleting the files as it goes. Any
received in this mode are placed in the me-sc-<queuename> directory.
When connected as a client, SMS() will send all messages waiting in the
me-sc-<queuename> directory, deleting the files as it goes. Any received in
this mode are placed in the sc-me-<queuename> directory.
Message files created by SMS() use a time stamp/reference based filename.
The format of the sms file is lines that have the form of key=value
Keys are :
oa Originating Address
Telephone number, national number if just digits
Telephone number starting with + then digits for international
Ignored on sending messages to service centre (CLI used)
da Destination Address
Telephone number, national number if just digits
Telephone number starting with + then digits for international
scts Service Centre Time Stamp
In the format YYYY-MM-DD HH:MM:SS
pid Protocol Identifier (decimal octet value)
dcs Data coding scheme (decimal octet value)
mr Message reference (decimal octet value)
ud The message (see escaping below)
srr 0/1 Status Report Request
rp 0/1 Return Path
vp mins validity period
Omitted fields have default values.
Note that there is special format for ud, ud# instead of ud= which is followed
by raw hex (2 characters per octet). This is used in output where characters
other than 10,13,32-126,128-255 are included in the data. In this case a comment (line
starting ;) is added showing the printable characters
When generating files to send to a service centre, only da and ud need be
specified. oa is ignored.
When generating files to send to a phone, only oa and ud need be specified. da is ignored.
When receiving a message as a service centre, only the destination address is
sent, so the originating address is set to the callerid.
EXAMPLES
The following are examples of use within the UK using BT Text SMS/landline
service.
This is a context to use with a manager script.
[smsdial]
; create and send a text message, expects number+message and
; connect to 17094009
exten => _X.,1,SMS(${CALLERIDNUM},,${EXTEN},${CALLERIDNAME})
exten => _X.,n,SMS(${CALLERIDNUM})
exten => _X.,n,Hangup
The script sends
action: originate
callerid: message <from>
exten: to
channel: Local/17094009
context: smsdial
priority: 1
You put the message as the name of the caller ID (messy, I know), the
originating number and hence queue name as the number of the caller ID and the
exten as the number to which the sms is to be sent. The context uses SMS to
create the message in the queue and then SMS to communicate with 17094009 to
actually send the message.
Note that the 9 on the end of 17094009 is the sub address 9 meaning no sub
address (BT specific). If a different digit is used then that is the sub
address for the sending message source address (appended to the outgoing CLI
by BT).
For incoming calls you can use a context like this :-
[incoming]
exten => _XXXXXX/_8005875290,1,SMS(${EXTEN:3},a)
exten => _XXXXXX/_8005875290,n,System(/usr/lib/asterisk/smsin ${EXTEN:3})
exten => _XXXXXX/_80058752[0-8]0,1,SMS(${EXTEN:3}${CALLERIDNUM:8:1},a)
exten => _XXXXXX/_80058752[0-8]0,n,System(/usr/lib/asterisk/smsin ${EXTEN>:3}${CALLERIDNUM:8:1})
exten => _XXXXXX/_80058752[0-8]0,n,Hangup
In this case the called number we get from BT is 6 digits (XXXXXX) and we are
using the last 3 digits as the queue name.
Priority 1 causes the SMS to be received and processed for the incoming call.
It is from 080058752X0. The two versions handle the queue name as 3 digits (no
sub address) or 4 digits (with sub address). In both cases, after the call a
script (smsin) is run - this is optional, but is useful to actually processed
the received queued SMS. In our case we email them based on the target number.
Priority 3 hangs up.
If using the CAPI drivers they send the right CLI and so the _800... would be
_0800...

View File

@ -1,53 +0,0 @@
Asterisk SNMP Support
---------------------
Rudimentary support for SNMP access to Asterisk is available. To build
this, one needs to have Net-SNMP development headers and libraries on
the build system, including any libraries Net-SNMP depends on.
Note that on some (many?) Linux-distributions the dependency list in
the net-snmp-devel list is not complete, and additional packages will
need to be installed. This is usually seen as configure failing to
detect net-snmp-devel as the configure script does a sanity check of
the net-snmp build environment, based on the output of
'net-snmp-config --agent-libs'.
To see what your distribution requires, run 'net-snmp-config --agent-libs'.
You will receive a response similar to the following:
-L/usr/lib -lnetsnmpmibs -lnetsnmpagent -lnetsnmphelpers -lnetsnmp -ldl
-lrpm -lrpmio -lpopt -lz -lcrypto -lm -lsensors -L/usr/lib/lib -lwrap
-Wl,-E -Wl,-rpath,/usr/lib/perl5/5.8.8/i386-linux-thread-multi/CORE
-L/usr/local/lib
/usr/lib/perl5/5.8.8/i386-linux-thread-multi/auto/DynaLoader/DynaLoader.a
-L/usr/lib/perl5/5.8.8/i386-linux-thread-multi/CORE -lperl -lresolv -lnsl
-ldl -lm -lcrypt -lutil -lpthread -lc
The packages required may include the following:
* bzip2-devel
* lm_sensors-devel
* newt-devel
SNMP support comes in two varieties -- as a sub-agent to a running SNMP
daemon using the AgentX protocol, or as a full standalone agent. If
you wish to run a full standalone agent, Asterisk must run as root in
order to bind to port 161.
Configuring access when running as a full agent is something that is
left as an exercise to the reader.
To enable access to the Asterisk SNMP subagent from a master SNMP
daemon, one will need to enable AgentX support, and also make sure that
Asterisk will be able to access the Unix domain socket. One way of
doing this is to add the following to /etc/snmp/snmpd.conf:
# Enable AgentX support
master agentx
# Set permissions on AgentX socket and containing
# directory such that process in group 'asterisk'
# will be able to connect
agentXPerms 0660 0550 nobody asterisk
This assumes that you run Asterisk under group 'asterisk' (and does
not care what user you run as).

View File

@ -1,295 +0,0 @@
The Asterisk Speech Recognition API
===================================
The generic speech recognition engine is implemented in the res_speech.so module.
This module connects through the API to speech recognition software, that is
not included in the module.
To use the API, you must load the res_speech.so module before any connectors.
For your convenience, there is a preload line commented out in the modules.conf
sample file.
* Dialplan Applications:
------------------------
The dialplan API is based around a single speech utilities application file,
which exports many applications to be used for speech recognition. These include an
application to prepare for speech recognition, activate a grammar, and play back a
sound file while waiting for the person to speak. Using a combination of these applications
you can easily make a dialplan use speech recognition without worrying about what
speech recognition engine is being used.
- SpeechCreate(Engine Name):
This application creates information to be used by all the other applications.
It must be called before doing any speech recognition activities such as activating a
grammar. It takes the engine name to use as the argument, if not specified the default
engine will be used.
If an error occurs are you are not able to create an object, the variable ERROR will be
set to 1. You can then exit your speech recognition specific context and play back an
error message, or resort to a DTMF based IVR.
- SpeechLoadGrammar(Grammar Name|Path):
Loads grammar locally on a channel. Note that the grammar is only available as long as the
channel exists, and you must call SpeechUnloadGrammar before all is done or you may cause a
memory leak. First argument is the grammar name that it will be loaded as and second
argument is the path to the grammar.
- SpeechUnloadGrammar(Grammar Name):
Unloads a locally loaded grammar and frees any memory used by it. The only argument is the
name of the grammar to unload.
- SpeechActivateGrammar(Grammar Name):
This activates the specified grammar to be recognized by the engine. A grammar tells the
speech recognition engine what to recognize, and how to portray it back to you in the
dialplan. The grammar name is the only argument to this application.
- SpeechStart():
Tell the speech recognition engine that it should start trying to get results from audio
being fed to it. This has no arguments.
- SpeechBackground(Sound File|Timeout):
This application plays a sound file and waits for the person to speak. Once they start
speaking playback of the file stops, and silence is heard. Once they stop talking the
processing sound is played to indicate the speech recognition engine is working. Note it is
possible to have more then one result. The first argument is the sound file and the second is the
timeout. Note the timeout will only start once the sound file has stopped playing.
- SpeechDeactivateGrammar(Grammar Name):
This deactivates the specified grammar so that it is no longer recognized. The
only argument is the grammar name to deactivate.
- SpeechProcessingSound(Sound File):
This changes the processing sound that SpeechBackground plays back when the speech
recognition engine is processing and working to get results. It takes the sound file as the
only argument.
- SpeechDestroy():
This destroys the information used by all the other speech recognition applications.
If you call this application but end up wanting to recognize more speech, you must call
SpeechCreate again before calling any other application. It takes no arguments.
* Getting Result Information:
-----------------------------
The speech recognition utilities module exports several dialplan functions that you can use to
examine results.
- ${SPEECH(status)}:
Returns 1 if SpeechCreate has been called. This uses the same check that applications do to see if a
speech object is setup. If it returns 0 then you know you can not use other speech applications.
- ${SPEECH(spoke)}:
Returns 1 if the speaker spoke something, or 0 if they were silent.
- ${SPEECH(results)}:
Returns the number of results that are available.
- ${SPEECH_SCORE(result number)}:
Returns the score of a result.
- ${SPEECH_TEXT(result number)}:
Returns the recognized text of a result.
- ${SPEECH_GRAMMAR(result number)}:
Returns the matched grammar of the result.
- SPEECH_ENGINE(name)=value
Sets a speech engine specific attribute.
* Dialplan Flow:
-----------------
1. Create a speech recognition object using SpeechCreate()
2. Activate your grammars using SpeechActivateGrammar(Grammar Name)
3. Call SpeechStart() to indicate you are going to do speech recognition immediately
4. Play back your audio and wait for recognition using SpeechBackground(Sound File|Timeout)
5. Check the results and do things based on them
6. Deactivate your grammars using SpeechDeactivateGrammar(Grammar Name)
7. Destroy your speech recognition object using SpeechDestroy()
* Dialplan Examples:
This is pretty cheeky in that it does not confirmation of results. As well the way the
grammar is written it returns the person's extension instead of their name so we can
just do a Goto based on the result text.
- Grammar: company-directory.gram
#ABNF 1.0;
language en-US;
mode voice;
tag-format <lumenvox/1.0>;
root $company_directory;
$josh = ((Joshua | Josh) [Colp]):"6066";
$mark = (Mark [Spencer] | Markster):"4569";
$kevin = (Kevin [Fleming]):"2567";
$company_directory = ($josh | $mark | $kevin) { $ = $$ };
- Dialplan logic
[dial-by-name]
exten => s,1,SpeechCreate()
exten => s,2,SpeechActivateGrammar(company-directory)
exten => s,3,SpeechStart()
exten => s,4,SpeechBackground(who-would-you-like-to-dial)
exten => s,5,SpeechDeactivateGrammar(company-directory)
exten => s,6,Goto(internal-extensions-${SPEECH_TEXT(0)})
- Useful Dialplan Tidbits:
A simple macro that can be used for confirm of a result. Requires some sound files.
ARG1 is equal to the file to play back after "I heard..." is played.
[macro-speech-confirm]
exten => s,1,SpeechActivateGrammar(yes_no)
exten => s,2,Set(OLDTEXT0=${SPEECH_TEXT(0)})
exten => s,3,Playback(heard)
exten => s,4,Playback(${ARG1})
exten => s,5,SpeechStart()
exten => s,6,SpeechBackground(correct)
exten => s,7,Set(CONFIRM=${SPEECH_TEXT(0)})
exten => s,8,GotoIf($["${SPEECH_TEXT(0)}" = "1"]?9:10)
exten => s,9,Set(CONFIRM=yes)
exten => s,10,Set(CONFIRMED=${OLDTEXT0})
exten => s,11,SpeechDeactivateGrammar(yes_no)
* The Asterisk Speech Recognition C API
---------------------------------------
The module res_speech.so exports a C based API that any developer can use to speech
recognize enable their application. The API gives greater control, but requires the
developer to do more on their end in comparison to the dialplan speech utilities.
For all API calls that return an integer value, a non-zero value indicates an error has occurred.
- Creating a speech structure:
struct ast_speech *ast_speech_new(char *engine_name, int format)
struct ast_speech *speech = ast_speech_new(NULL, AST_FORMAT_SLINEAR);
This will create a new speech structure that will be returned to you. The speech recognition
engine name is optional and if NULL the default one will be used. As well for now format should
always be AST_FORMAT_SLINEAR.
- Activating a grammar:
int ast_speech_grammar_activate(struct ast_speech *speech, char *grammar_name)
res = ast_speech_grammar_activate(speech, "yes_no");
This activates the specified grammar on the speech structure passed to it.
- Start recognizing audio:
void ast_speech_start(struct ast_speech *speech)
ast_speech_start(speech);
This essentially tells the speech recognition engine that you will be feeding audio to it from
then on. It MUST be called every time before you start feeding audio to the speech structure.
- Send audio to be recognized:
int ast_speech_write(struct ast_speech *speech, void *data, int len)
res = ast_speech_write(speech, fr->data, fr->datalen);
This writes audio to the speech structure that will then be recognized. It must be written
signed linear only at this time. In the future other formats may be supported.
- Checking for results:
The way the generic speech recognition API is written is that the speech structure will
undergo state changes to indicate progress of recognition. The states are outlined below:
AST_SPEECH_STATE_NOT_READY - The speech structure is not ready to accept audio
AST_SPEECH_STATE_READY - You may write audio to the speech structure
AST_SPEECH_STATE_WAIT - No more audio should be written, and results will be available soon.
AST_SPEECH_STATE_DONE - Results are available and the speech structure can only be used again by
calling ast_speech_start
It is up to you to monitor these states. Current state is available via a variable on the speech
structure. (state)
- Knowing when to stop playback:
If you are playing back a sound file to the user and you want to know when to stop play back because the
individual started talking use the following.
ast_test_flag(speech, AST_SPEECH_QUIET) - This will return a positive value when the person has started talking.
- Getting results:
struct ast_speech_result *ast_speech_results_get(struct ast_speech *speech)
struct ast_speech_result *results = ast_speech_results_get(speech);
This will return a linked list of result structures. A result structure looks like the following:
struct ast_speech_result {
char *text; /*!< Recognized text */
int score; /*!< Result score */
char *grammar; /*!< Matched grammar */
struct ast_speech_result *next; /*!< List information */
};
- Freeing a set of results:
int ast_speech_results_free(struct ast_speech_result *result)
res = ast_speech_results_free(results);
This will free all results on a linked list. Results MAY NOT be used as the memory will have been freed.
- Deactivating a grammar:
int ast_speech_grammar_deactivate(struct ast_speech *speech, char *grammar_name)
res = ast_speech_grammar_deactivate(speech, "yes_no");
This deactivates the specified grammar on the speech structure.
- Destroying a speech structure:
int ast_speech_destroy(struct ast_speech *speech)
res = ast_speech_destroy(speech);
This will free all associated memory with the speech structure and destroy it with the speech recognition engine.
- Loading a grammar on a speech structure:
int ast_speech_grammar_load(struct ast_speech *speech, char *grammar_name, char *grammar)
res = ast_speech_grammar_load(speech, "builtin:yes_no", "yes_no");
- Unloading a grammar on a speech structure:
If you load a grammar on a speech structure it is preferred that you unload it as well,
or you may cause a memory leak. Don't say I didn't warn you.
int ast_speech_grammar_unload(struct ast_speech *speech, char *grammar_name)
res = ast_speech_grammar_unload(speech, "yes_no");
This unloads the specified grammar from the speech structure.

View File

@ -1,116 +0,0 @@
("Taken from the README in libss7")
Tested Switches:
================
Siemens EWSD - (ITU style) MTP2 and MTP3 comes up, ISUP inbound and outbound calls work as well.
DTI DXC 4K - (ANSI style) 56kbps link, MTP2 and MTP3 come up, ISUP inbound and outbound calls work as well.
Huawei M800 - (ITU style) MTP2 and MTP3 comes up, ISUP National, International inbound and outbound calls work as well, CallerID presentation&screening work.
and MORE~!
Thanks:
=======
Mark Spencer, for writing Asterisk and libpri and being such a great friend and boss.
Luciano Ramos, for donating a link in getting the first "real" ITU switch working.
Collin Rose and John Lodden, John for introducing me to Collin, and Collin for the first
"real" ANSI link and for holding my hand through the remaining changes that had to be
done for ANSI switches.
To Use:
=======
In order to use libss7, you must get at least the following versions of DAHDI and Asterisk:
DAHDI: 2.0.x
libss7: trunk (currently, there *only* is a trunk release).
Asterisk: 1.6.x
You must then do a `make; make install` in each of the directories that you installed
in the given order (DAHDI first, libss7 second, and Asterisk last).
NOTE: In order to check out the code, you must have the subversion client installed. This
is how to check them out from the public subversion server.
These are the commands you would type to install them:
`svn co http://svn.digium.com/svn/dahdi/linux/trunk dahdi-trunk`
`cd dahdi-trunk`
`make; make install`
`svn co http://svn.digium.com/svn/dahdi/tools/trunk dahdi-tools`
`cd dahdi-tools`
`./configure; make; make install`
`svn co http://svn.digium.com/svn/libss7/trunk libss7-trunk`
`cd libss7-trunk`
`make; make install`
`svn co http://svn.digium.com/svn/asterisk/trunk asterisk-trunk`
`cd asterisk-trunk`
`./configure; make; make install;`
This should build DAHDI, libss7, and Asterisk with SS7 support.
In the past, there was a special asterisk-ss7 branch to use which contained the SS7 code.
That code has been merged back into the trunk version of Asterisk, and the old asterisk-ss7
branch has been deprecated and removed. If you are still using the asterisk-ss7 branch, it
will not work against the current version of libss7, and you should switch to asterisk-trunk
instead.
CONFIGURATION:
In /etc/dahdi/system.conf, your signalling channel(s) should be a "dchan" and your bearers should
be set as "bchan".
The sample chan_dahdi.conf contains sample configuration for setting up an E1 link.
In brief, here is a simple ss7 linkset setup:
signalling = ss7
ss7type = itu ; or ansi if you are using an ANSI link
linkset = 1 ; Pick a number for your linkset identifier in chan_dahdi.conf
pointcode = 28 ; The decimal form of your point code. If you are using an
; ANSI linkset, you can use the xxx-xxx-xxx notation for
; specifying your linkset pointcode.
adjpointcode = 2 ; The point code of the switch adjacent to your linkset
defaultdpc = 3 ; The point code of the switch you want to send your ISUP
; traffic to. A lot of the time, this is the same as your
; adjpointcode.
; Now we configure our Bearer channels (CICs)
cicbeginswith = 1 ; Number to start counting the CICs from. So if DAHDI/1 to
; DAHDI/15 are CICs 1-15, you would set this to 1 before you
; declare channel=1-15
channel=1-15 ; Use DAHDI/1-15 and assign them to CICs 1-15
cicbeginswith = 17 ; Now for DAHDI/17 to DAHDI/31, they are CICs 17-31 so we initialize
; cicbeginswith to 17 before we declare those channels
channel = 17-31 ; This assigns CICs 17-31 to channels 17-31
sigchan = 16 ; This is where you declare which DAHDI channel is your signalling
; channel. In our case it is DAHDI/16. You can add redundant
; signalling channels by adding additional sigchan= lines.
; If we want an alternate redundant signalling channel add this
sigchan = 48 ; This would put two signalling channels in our linkset, one at
; DAHDI/16 and one at DAHDI/48 which both would be used to send/receive
; ISUP traffic.
; End of chan_dahdi.conf
This is how a basic linkset is setup. For more detailed chan_dahdi.conf SS7 config information
as well as other options available for that file, see the default chan_dahdi.conf that comes
with the samples in asterisk. If you would like, you can do a `make samples` in your
asterisk-trunk directory and it will install a sample chan_dahdi.conf for you that contains
more information about SS7 setup.
For more information, please use the asterisk-ss7 or asterisk-dev mailing
lists (I monitor them regularly) or email me directly.
Matthew Fredrickson
creslin@digium.com

View File

@ -1,76 +0,0 @@
include ../../makeopts
pdf: asterisk.pdf
asterisk.pdf: $(wildcard *.tex)
ifeq ($(findstring rubber,$(RUBBER)),)
@echo "**********************************************"
@echo "** You must install the \"rubber\" tool ***"
@echo "** to generate the Asterisk reference PDF. ***"
@echo "**********************************************"
else
@echo "**********************************************"
@echo "** The Asterisk reference PDF will now be ***"
@echo "** generated. When complete, it will be ***"
@echo "** located at asterisk.pdf. ***"
@echo "**********************************************"
ifneq ($(findstring kpsewhich,$(KPATHSEA)),)
ifeq ($(findstring fncychap.sty,$(shell find `$(KPATHSEA) --expand-braces='$${TEXMF}'| tr -d \! | sed 's/:/ /g'` -name fncychap.sty -print)),)
@echo
@echo "WARNING: The fncychap.sty document was not found"
@echo "On Ubuntu, install the texlive-latex-extra package."
@echo
@exit 1
endif
endif
@cp asterisk.tex asterisk.tex.orig
@sed -e 's/ASTERISKVERSION/$(shell echo $(ASTERISKVERSION) | sed -e 's/\//\\\//g' | sed -e 's/_/\\\\_/g')/' asterisk.tex > asterisk_local.tex
@mv asterisk_local.tex asterisk.tex
-@$(RUBBER) --pdf asterisk.tex
@mv asterisk.tex.orig asterisk.tex
endif
html:
@echo "**********************************************"
@echo "** The Asterisk reference HTML will now be ***"
@echo "** generated. When complete, it will be ***"
@echo "** located in the asterisk/ directory. ***"
@echo "** Note that the latex2html tool is ***"
@echo "** required for this to work. ***"
@echo "**********************************************"
@cp asterisk.tex asterisk.tex.orig
@sed -e 's/ASTERISKVERSION/$(ASTERISKVERSION)/' asterisk.tex > asterisk_local.tex
@mv asterisk_local.tex asterisk.tex
@latex2html asterisk.tex
@mv asterisk.tex.orig asterisk.tex
txt: asterisk.txt
asterisk.txt: $(wildcard *.tex)
ifeq ($(findstring catdvi,$(CATDVI)),)
@echo "**********************************************"
@echo "** You must install the \"catdvi\" tool ***"
@echo "** to generate the Asterisk reference TXT. ***"
@echo "**********************************************"
else
@echo "**********************************************"
@echo "** The Asterisk reference TXT will now be ***"
@echo "** generated. When complete, it will be ***"
@echo "** located at asterisk.txt. ***"
@echo "**********************************************"
ifneq ($(findstring kpsewhich,$(KPATHSEA)),)
ifeq ($(findstring fncychap.sty,$(shell find `$(KPATHSEA) --expand-braces='$${TEXMF}'| tr -d \! | sed 's/:/ /g'` -name fncychap.sty -print)),)
@echo
@echo "WARNING: The fncychap.sty document was not found"
@echo "On Ubuntu, install the texlive-latex-extra package."
@echo
@exit 1
endif
endif
@cp asterisk.tex asterisk.tex.orig
@sed -e 's/ASTERISKVERSION/$(ASTERISKVERSION)/' asterisk.tex > asterisk_local.tex
@mv asterisk_local.tex asterisk.tex
@latex asterisk.tex
-@$(CATDVI) -e 1 -U asterisk.dvi | sed -re "s/\[U\+2022\]/*/g" | sed -re "s/\[U\+02C6\]/^/g" | sed -re "s/([^^[:space:]])\s+/\1 /g" > asterisk.txt
@mv asterisk.tex.orig asterisk.tex
endif

View File

@ -1,24 +0,0 @@
Asterisk Reference Documentation
--------------------------------
1) To generate a PDF from this documentation, you will need the rubber tool,
and all of its dependencies. The web site for this tool is:
http://www.pps.jussieu.fr/~beffara/soft/rubber/
Then, once this tool is installed, running "make pdf" will generate
the PDF automatically using this tool. The result will be asterisk.pdf.
NOTE: After installing rubber, you will need to re-run the top level
configure script. It checks to see if rubber is installed, so that the
asterisk.pdf Makefile target can produce a useful error message when it is
not installed.
2) To generate HTML from this documentation, you will need the latex2html tool,
and all of its dependencies. The web site for this tool is:
http://www.latex2html.org/
Then, once this tool is installed, running "make html" will generate the
HTML documentation. The result will be an asterisk directory full of
HTML files.

File diff suppressed because it is too large Load Diff

View File

@ -1,97 +0,0 @@
\section{Asynchronous Javascript Asterisk Manger (AJAM)}
AJAM is a new technology which allows web browsers or other HTTP enabled
applications and web pages to directly access the Asterisk Manger
Interface (AMI) via HTTP. Setting up your server to process AJAM
involves a few steps:
\subsection{Setup the Asterisk HTTP server}
\begin{enumerate}
\item Uncomment the line "enabled=yes" in \path{/etc/asterisk/http.conf} to enable
Asterisk's builtin micro HTTP server.
\item If you want Asterisk to actually deliver simple HTML pages, CSS,
javascript, etc. you should uncomment "enablestatic=yes"
\item Adjust your "bindaddr" and "bindport" settings as appropriate for
your desired accessibility
\item Adjust your "prefix" if appropriate, which must be the beginning of
any URI on the server to match. The default is "asterisk" and the
rest of these instructions assume that value.
\end{enumerate}
\subsection{Allow Manager Access via HTTP}
\begin{enumerate}
\item Make sure you have both "enabled = yes" and "webenabled = yes" setup
in \path{/etc/asterisk/manager.conf}
\item You may also use "httptimeout" to set a default timeout for HTTP
connections.
\item Make sure you have a manager username/secret
\end{enumerate}
Once those configurations are complete you can reload or restart
Asterisk and you should be able to point your web browser to specific
URI's which will allow you to access various web functions. A complete
list can be found by typing "http show status" at the Asterisk CLI.
examples:
\begin{astlisting}
\begin{verbatim}
http://localhost:8088/asterisk/manager?action=login&username=foo&secret=bar
\end{verbatim}
\end{astlisting}
This logs you into the manager interface's "HTML" view. Once you're
logged in, Asterisk stores a cookie on your browser (valid for the
length of httptimeout) which is used to connect to the same session.
\begin{astlisting}
\begin{verbatim}
http://localhost:8088/asterisk/rawman?action=status
\end{verbatim}
\end{astlisting}
Assuming you've already logged into manager, this URI will give you a
"raw" manager output for the "status" command.
\begin{astlisting}
\begin{verbatim}
http://localhost:8088/asterisk/mxml?action=status
\end{verbatim}
\end{astlisting}
This will give you the same status view but represented as AJAX data,
theoretically compatible with RICO (\url{http://www.openrico.org}).
\begin{astlisting}
\begin{verbatim}
http://localhost:8088/asterisk/static/ajamdemo.html
\end{verbatim}
\end{astlisting}
If you have enabled static content support and have done a make install,
Asterisk will serve up a demo page which presents a live, but very
basic, "astman" like interface. You can login with your username/secret
for manager and have a basic view of channels as well as transfer and
hangup calls. It's only tested in Firefox, but could probably be made
to run in other browsers as well.
A sample library (astman.js) is included to help ease the creation of
manager HTML interfaces.
Note that for the demo, there is no need for *any* external web server.
\subsection{Integration with other web servers}
Asterisk's micro HTTP server is *not* designed to replace a general
purpose web server and it is intentionally created to provide only the
minimal interfaces required. Even without the addition of an external
web server, one can use Asterisk's interfaces to implement screen pops
and similar tools pulling data from other web servers using iframes,
div's etc. If you want to integrate CGI's, databases, PHP, etc. you
will likely need to use a more traditional web server like Apache and
link in your Asterisk micro HTTP server with something like this:
\begin{astlisting}
\begin{verbatim}
ProxyPass /asterisk http://localhost:8088/asterisk
\end{verbatim}
\end{astlisting}

View File

@ -1,518 +0,0 @@
\section{Introduction}
The SMS module for Asterisk was developed by Adrian Kennard, and is an
implementation of the ETSI specification for landline SMS, ETSI ES 201
912, which is available from \url{www.etsi.org}. Landline SMS is starting to
be available in various parts of Europe, and is available from BT in
the UK. However, Asterisk would allow gateways to be created in other
locations such as the US, and use of SMS capable phones such as the
Magic Messenger. SMS works using analogue or ISDN lines.
\section{Background}
Short Message Service (SMS), or texting is very popular between mobile
phones. A message can be sent between two phones, and normally
contains 160 characters. There are ways in which various types of data
can be encoded in a text message such as ring tones, and small
graphic, etc. Text messaging is being used for voting and
competitions, and also SPAM...
Sending a message involves the mobile phone contacting a message
centre (SMSC) and passing the message to it. The message centre then
contacts the destination mobile to deliver the message. The SMSC is
responsible for storing the message and trying to send it until the
destination mobile is available, or a timeout.
Landline SMS works in basically the same way. You would normally have
a suitable text capable landline phone, or a separate texting box such
as a Magic Messenger on your phone line. This sends a message to a
message centre your telco provides by making a normal call and sending
the data using 1200 Baud FSK signaling according to the ETSI spec. To
receive a message the message centre calls the line with a specific
calling number, and the text capable phone answers the call and
receives the data using 1200 Baud FSK signaling. This works
particularly well in the UK as the calling line identity is sent
before the first ring, so no phones in the house would ring when a
message arrives.
\section{Typical use with Asterisk}
Sending messages from an Asterisk box can be used for a variety of
reasons, including notification from any monitoring systems, email
subject lines, etc.
Receiving messages to an Asterisk box is typically used just to email
the messages to someone appropriate - we email and texts that are
received to our direct numbers to the appropriate person. Received
messages could also be used to control applications, manage
competitions, votes, post items to IRC, anything.
Using a terminal such as a magic messenger, an Asterisk box could ask
as a message centre sending messages to the terminal, which will beep
and pop up the message (and remember 100 or so messages in its
memory).
\section{Terminology}
\begin{itemize}
\item SMS -
Short Message Service
i.e. text messages
\item SMSC -
Short Message Service Centre
The system responsible for storing and forwarding messages
\item MO -
Mobile Originated
A message on its way from a mobile or landline device to the SMSC
\item MT -
Mobile Terminated
A message on its way from the SMSC to the mobile or landline device
\item RX -
Receive
A message coming in to the Asterisk box
\item TX -
Transmit
A message going out of the Asterisk box
\end{itemize}
\section{Sub address}
When sending a message to a landline, you simply send to the landline
number. In the UK, all of the mobile operators (bar one) understand
sending messages to landlines and pass the messages to the BTText
system for delivery to the landline.
The specification for landline SMS allows for the possibility of more
than one device on a single landline. These can be configured with Sub
addresses which are a single digit. To send a message to a specific
device the message is sent to the landline number with an extra digit
appended to the end. The telco can define a default sub address (9 in
the UK) which is used when the extra digit is not appended to the end.
When the call comes in, part of the calling line ID is the sub
address, so that only one device on the line answers the call and
receives the message.
Sub addresses also work for outgoing messages. Part of the number
called by the device to send a message is its sub address. Sending
from the default sub address (9 in the UK) means the message is
delivered with the sender being the normal landline number. Sending
from any other sub address makes the sender the landline number with
an extra digit on the end.
Using Asterisk, you can make use of the sub addresses for sending and
receiving messages. Using DDI (DID, i.e. multiple numbers on the line
on ISDN) you can also make use of many different numbers for SMS.
\section{extensions.conf}
The following contexts are recommended.
\begin{astlisting}
\begin{verbatim}
; Mobile Terminated, RX. This is used when an incoming call from the SMS arrive
s, with the queue (called number and sub address) in ${EXTEN}
; Running an app after receipt of the text allows the app to find all messages
in the queue and handle them, e.g. email them.
; The app may be something like smsq --process=somecommand --queue=${EXTEN}
to run a command for each received message
; See below for usage
[smsmtrx]
exten = _X.,1, SMS(${EXTEN},a)
exten = _X.,2,System("someapptohandleincomingsms ${EXTEN}")
exten = _X.,3,Hangup
; Mobile originated, RX. This is receiving a message from a device, e.g.
; a Magic Messenger on a sip extension
; Running an app after receipt of the text allows the app to find all messages
; in the queue and handle then, e.g. sending them to the public SMSC
; The app may be something like smsq --process=somecommand --queue=${EXTEN}
; to run a command for each received message
; See below for example usage
[smsmorx]
exten = _X.,1, SMS(${EXTEN},sa)
exten = _X.,2,System("someapptohandlelocalsms ${EXTEN}")
exten = _X.,3,Hangup
\end{verbatim}
\end{astlisting}
smsmtrx is normally accessed by an incoming call from the SMSC. In the
UK this call is from a CLI of 080058752X0 where X is the sub address.
As such a typical usage in the extensions.conf at the point of
handling an incoming call is:
\begin{astlisting}
\begin{verbatim}
exten = _X./8005875290,1,Goto(smsmtrx,${EXTEN},1)
exten = _X./_80058752[0-8]0,1,Goto(smsmtrx,${EXTEN}-${CALLERID(num):8:1},1)
\end{verbatim}
\end{astlisting}
Alternatively, if you have the correct national prefix on incoming
CLI, e.g. using dahdi\_hfc, you might use:
\begin{astlisting}
\begin{verbatim}
exten = _X./08005875290,1,Goto(smsmtrx,${EXTEN},1)
exten = _X./_080058752[0-8]0,1,Goto(smsmtrx,${EXTEN}-${CALLERID(num):9:1},1)
\end{verbatim}
\end{astlisting}
smsmorx is normally accessed by a call from a local sip device
connected to a Magic Messenger. It could however by that you are
operating Asterisk as a message centre for calls from outside. Either
way, you look at the called number and goto smsmorx. In the UK, the
SMSC number that would be dialed is 1709400X where X is the caller sub
address. As such typical usage in extension.config at the point of
handling a call from a sip phone is:
\begin{astlisting}
\begin{verbatim}
exten = 17094009,1,Goto(smsmorx,${CALLERID(num)},1)
exten = _1709400[0-8],1,Goto(smsmorx,${CALLERID(num)}-{EXTEN:7:1},1)
\end{verbatim}
\end{astlisting}
\section{Using smsq}
smsq is a simple helper application designed to make it easy to send
messages from a command line. it is intended to run on the Asterisk
box and have direct access to the queue directories for SMS and for
Asterisk.
In its simplest form you can send an SMS by a command such as
smsq 0123456789 This is a test to 0123456789
This would create a queue file for a mobile originated TX message in
queue 0 to send the text "This is a test to 0123456789" to 0123456789.
It would then place a file in the \path{/var/spool/asterisk/outgoing}
directory to initiate a call to 17094009 (the default message centre
in smsq) attached to application SMS with argument of the queue name
(0).
Normally smsq will queue a message ready to send, and will then create
a file in the Asterisk outgoing directory causing Asterisk to actually
connect to the message centre or device and actually send the pending
message(s).
Using \verb!--process!, smsq can however be used on received queues to run a
command for each file (matching the queue if specified) with various
environment variables set based on the message (see below);
smsq options:
\begin{verbatim}
--help
Show help text
--usage
Show usage
--queue
-q
Specify a specific queue
In no specified, messages are queued under queue "0"
--da
-d
Specify destination address
--oa
-o
Specify originating address
This also implies that we are generating a mobile terminated message
--ud
-m
Specify the actual message
--ud-file
-f
Specify a file to be read for the context of the message
A blank filename (e.g. --ud-file= on its own) means read stdin. Very
useful when using via ssh where command line parsing could mess up the
message.
--mt
-t
Mobile terminated message to be generated
--mo
Mobile originated message to be generated
Default
--tx
Transmit message
Default
--rx
-r
Generate a message in the receive queue
--UTF-8
Treat the file as UTF-8 encoded (default)
--UCS-1
Treat the file as raw 8 bit UCS-1 data, not UTF-8 encoded
--UCS-2
Treat the file as raw 16 bit bigendian USC-2 data
--process
Specific a command to process for each file in the queue
Implies --rx and --mt if not otherwise specified.
Sets environment variables for every possible variable, and also ud,
ud8 (USC-1 hex), and ud16 (USC-2 hex) for each call. Removes files.
--motx-channel
Specify the channel for motx calls
May contain X to use sub address based on queue name or may be full
number
Default is Local/1709400X
--motx-callerid
Specify the caller ID for motx calls
The default is the queue name without -X suffix
--motx-wait
Wait time for motx call
Default 10
--motx-delay
Retry time for motx call
Default 1
--motx-retries
Retries for motx call
Default 10
--mttx-channel
Specify the channel for mttx calls
Default is Local/ and the queue name without -X suffix
--mtttx-callerid
Specify the callerid for mttx calls
May include X to use sub address based on queue name or may be full
number
Default is 080058752X0
--mttx-wait
Wait time for mttx call
Default 10
--mttx-delay
Retry time for mttx call
Default 30
--mttx-retries
Retries for mttx call
Default 100
--default-sub-address
The default sub address assumed (e.g. for X in CLI and dialled numbers
as above) when none added (-X) to queue
Default 9
--no-dial
-x
Create queue, but do not dial to send message
--no-wait
Do not wait if a call appears to be in progress
This could have a small window where a message is queued but not
sent, so regular calls to smsq should be done to pick up any missed
messages
--concurrent
How many concurrent calls to allow (per queue), default 1
--mr
-n
Message reference
--pid
-p
Protocol ID
--dcs
Data coding scheme
--udh
Specific hex string of user data header specified (not including the
initial length byte)
May be a blank string to indicate header is included in the user data
already but user data header indication to be set.
--srr
Status report requested
--rp
Return path requested
--vp
Specify validity period (seconds)
--scts
Specify timestamp (YYYY-MM-DDTHH:MM:SS)
--spool-dir
Spool dir (in which sms and outgoing are found)
Default /var/spool/asterisk
\end{verbatim}
Other arguments starting '-' or '\verb!--!' are invalid and will cause an
error. Any trailing arguments are processed as follows:-
\begin{itemize}
\item If the message is mobile originating and no destination address
has been specified, then the first argument is assumed to be a
destination address
\item If the message is mobile terminating and no destination address
has been specified, then the first argument is assumed to be the
queue name
\item If there is no user data, or user data file specified, then any
following arguments are assumed to be the message, which are
concatenated.
\item If no user data is specified, then no message is sent. However,
unless \verb!--no-dial! is specified, smsq checks for pending messages
and generates an outgoing anyway
\end{itemize}
Note that when smsq attempts to make a file in
\path{/var/spool/asterisk/outgoing}, it checks if there is already a call
queued for that queue. It will try several filenames, up to the
\verb!--concurrent! setting. If these files exist, then this means Asterisk
is already queued to send all messages for that queue, and so Asterisk
should pick up the message just queued. However, this alone could
create a race condition, so if the files exist then smsq will wait up
to 3 seconds to confirm it still exists or if the queued messages have
been sent already. The \verb!--no-wait! turns off this behaviour. Basically,
this means that if you have a lot of messages to send all at once,
Asterisk will not make unlimited concurrent calls to the same message
centre or device for the same queue. This is because it is generally
more efficient to make one call and send all of the messages one after
the other.
smsq can be used with no arguments, or with a queue name only, and it
will check for any pending messages and cause an outgoing if there are
any. It only sets up one outgoing call at a time based on the first
queued message it finds. A outgoing call will normally send all queued
messages for that queue. One way to use smsq would be to run with no
queue name (so any queue) every minute or every few seconds to send
pending message. This is not normally necessary unless \verb!--no-dial! is
selected. Note that smsq does only check motx or mttx depending on the
options selected, so it would need to be called twice as a general
check.
UTF-8 is used to parse command line arguments for user data, and is
the default when reading a file. If an invalid UTF-8 sequence is
found, it is treated as UCS-1 data (i.e, as is).
The \verb!--process! option causes smsq to scan the specified queue (default
is mtrx) for messages (matching the queue specified, or any if queue
not specified) and run a command and delete the file. The command is
run with a number of environment variables set as follows. Note that
these are unset if not needed and not just taken from the calling
environment. This allows simple processing of incoming messages
\begin{verbatim}
$queue
Set if a queue specified
$?srr
srr is set (to blank) if srr defined and has value 1.
$?rp
rp is set (to blank) if rp defined and has value 1.
$ud
User data, UTF-8 encoding, including any control characters, but with
nulls stripped out
Useful for the content of emails, for example, as it includes any
newlines, etc.
$ude
User data, escaped UTF-8, including all characters, but control
characters \n, \r, \t, \f, \xxx and \ is escaped as \\
Useful guaranteed one line printable text, so useful in Subject lines
of emails, etc
$ud8
Hex UCS-1 coding of user data (2 hex digits per character)
Present only if all user data is in range U+0000 to U+00FF
$ud16
Hex UCS-2 coding of user data (4 hex digits per character)
other
Other fields set using their field name, e.g. mr, pid, dcs, etc. udh
is a hex byte string
\end{verbatim}
\section{File formats}
By default all queues are held in a director \path{/var/spool/asterisk/sms}.
Within this directory are sub directories mtrx, mttx, morx, motx which
hold the received messages and the messages ready to send. Also,
\path{/var/log/asterisk/sms} is a log file of all messages handled.
The file name in each queue directory starts with the queue parameter
to SMS which is normally the CLI used for an outgoing message or the
called number on an incoming message, and may have -X (X being sub
address) appended. If no queue ID is known, then 0 is used by smsq by
default. After this is a dot, and then any text. Files are scanned for
matching queue ID and a dot at the start. This means temporary files
being created can be given a different name not starting with a queue
(we recommend a . on the start of the file name for temp files).
Files in these queues are in the form of a simple text file where each
line starts with a keyword and an = and then data. udh and ud have
options for hex encoding, see below.
UTF-8. The user data (ud) field is treated as being UTF-8 encoded
unless the DCS is specified indicating 8 bit format. If 8 bit format
is specified then the user data is sent as is.
The keywords are as follows:
\begin{verbatim}
oa Originating address
The phone number from which the message came
Present on mobile terminated messages and is the CLI for morx messages
da
Destination Address
The phone number to which the message is sent
Present on mobile originated messages
scts
The service centre time stamp
Format YYYY-MM-DDTHH:MM:SS
Present on mobile terminated messages
pid
One byte decimal protocol ID
See GSM specs for more details
Normally 0 or absent
dcs
One byte decimal data coding scheme
If omitted, a sensible default is used (see below)
See GSM specs for more details
mr
One byte decimal message reference
Present on mobile originated messages, added by default if absent
srr
0 or 1 for status report request
Does not work in UK yet, not implemented in app_sms yet
rp
0 or 1 return path
See GSM specs for details
vp
Validity period in seconds
Does not work in UK yet
udh
Hex string of user data header prepended to the SMS contents,
excluding initial length byte.
Consistent with ud, this is specified as udh# rather than udh=
If blank, this means that the udhi flag will be set but any user data
header must be in the ud field
ud
User data, may be text, or hex, see below
\end{verbatim}
udh is specified as as udh\# followed by hex (2 hex digits per byte).
If present, then the user data header indicator bit is set, and the
length plus the user data header is added to the start of the user
data, with padding if necessary (to septet boundary in 7 bit format).
User data can hold an USC character codes U+0000 to U+FFFF. Any other
characters are coded as U+FEFF
ud can be specified as ud= followed by UTF-8 encoded text if it
contains no control characters, i.e. only (U+0020 to U+FFFF). Any
invalid UTF-8 sequences are treated as is (U+0080-U+00FF).
ud can also be specified as ud\# followed by hex (2 hex digits per
byte) containing characters U+0000 to U+00FF only.
ud can also be specified as ud\#\# followed by hex (4 hex digits per
byte) containing UCS-2 characters.
When written by app\_sms (e.g. incoming messages), the file is written
with ud= if it can be (no control characters). If it cannot, the a
comment line ;ud= is used to show the user data for human readability
and ud\# or ud\#\# is used.
\section{Delivery reports}
The SMS specification allows for delivery reports. These are requested
using the srr bit. However, as these do not work in the UK yet they
are not fully implemented in this application. If anyone has a telco
that does implement these, please let me know. BT in the UK have a non
standard way to do this by starting the message with *0\#, and so this
application may have a UK specific bodge in the near future to handle
these.
The main changes that are proposed for delivery report handling are :
\begin{itemize}
\item New queues for sent messages, one file for each destination
address and message reference.
\item New field in message format, user reference, allowing applications
to tie up their original message with a report.
\item Handling of the delivery confirmation/rejection and connecting to
the outgoing message - the received message file would then have
fields for the original outgoing message and user reference
allowing applications to handle confirmations better.
\end{itemize}

View File

@ -1,149 +0,0 @@
\subsubsection{Asterisk Main Configuration File}
Below is a sample of the main Asterisk configuration file,
asterisk.conf. Note that this file is not provided in
sample form, because the Makefile creates it when needed
and does not touch it when it already exists.
\begin{astlisting}
\begin{verbatim}
[directories]
; Make sure these directories have the right permissions if not
; running Asterisk as root
; Where the configuration files (except for this one) are located
astetcdir => /etc/asterisk
; Where the Asterisk loadable modules are located
astmoddir => /usr/lib/asterisk/modules
; Where additional 'library' elements (scripts, etc.) are located
astvarlibdir => /var/lib/asterisk
; Where AGI scripts/programs are located
astagidir => /var/lib/asterisk/agi-bin
; Where spool directories are located
; Voicemail, monitor, dictation and other apps will create files here
; and outgoing call files (used with pbx_spool) must be placed here
astspooldir => /var/spool/asterisk
; Where the Asterisk process ID (pid) file should be created
astrundir => /var/run/asterisk
; Where the Asterisk log files should be created
astlogdir => /var/log/asterisk
[options]
;Under "options" you can enter configuration options
;that you also can set with command line options
; Verbosity level for logging (-v)
verbose = 0
; Debug: "No" or value (1-4)
debug = 3
; Background execution disabled (-f)
nofork=yes | no
; Always background, even with -v or -d (-F)
alwaysfork=yes | no
; Console mode (-c)
console= yes | no
; Execute with high priority (-p)
highpriority = yes | no
; Initialize crypto at startup (-i)
initcrypto = yes | no
; Disable ANSI colors (-n)
nocolor = yes | no
; Dump core on failure (-g)
dumpcore = yes | no
; Run quietly (-q)
quiet = yes | no
; Force timestamping in CLI verbose output (-T)
timestamp = yes | no
; User to run asterisk as (-U) NOTE: will require changes to
; directory and device permissions
runuser = asterisk
; Group to run asterisk as (-G)
rungroup = asterisk
; Enable internal timing support (-I)
internal_timing = yes | no
; Language Options
documentation_language = en | es | ru
; These options have no command line equivalent
; Cache record() files in another directory until completion
cache_record_files = yes | no
record_cache_dir = <dir>
; Build transcode paths via SLINEAR
transcode_via_sln = yes | no
; send SLINEAR silence while channel is being recorded
transmit_silence_during_record = yes | no
; The maximum load average we accept calls for
maxload = 1.0
; The maximum number of concurrent calls you want to allow
maxcalls = 255
; Stop accepting calls when free memory falls below this amount specified in MB
minmemfree = 256
; Allow #exec entries in configuration files
execincludes = yes | no
; Don't over-inform the Asterisk sysadm, he's a guru
dontwarn = yes | no
; System name. Used to prefix CDR uniqueid and to fill \${SYSTEMNAME}
systemname = <a_string>
; Should language code be last component of sound file name or first?
; when off, sound files are searched as <path>/<lang>/<file>
; when on, sound files are search as <lang>/<path>/<file>
; (only affects relative paths for sound files)
languageprefix = yes | no
; Locking mode for voicemail
; - lockfile: default, for normal use
; - flock: for where the lockfile locking method doesn't work
; eh. on SMB/CIFS mounts
lockmode = lockfile | flock
; Entity ID. This is in the form of a MAC address. It should be universally
; unique. It must be unique between servers communicating with a protocol
; that uses this value. The only thing that uses this currently is DUNDi,
; but other things will use it in the future.
; entityid=00:11:22:33:44:55
[files]
; Changing the following lines may compromise your security
; Asterisk.ctl is the pipe that is used to connect the remote CLI
; (asterisk -r) to Asterisk. Changing these settings change the
; permissions and ownership of this file.
; The file is created when Asterisk starts, in the "astrundir" above.
;astctlpermissions = 0660
;astctlowner = root
;astctlgroup = asterisk
;astctl = asterisk.ctl
\end{verbatim}
\end{astlisting}

View File

@ -1,183 +0,0 @@
% To generate a PDF from this, install the "rubber" tool, and the LaTeX
% dependencies for it. Then, run:
%
% rubber asterisk.tex
%
% http://www.pps.jussieu.fr/~beffara/soft/rubber/
\documentclass[12pt,a4]{report}
\usepackage{hyperref}
\usepackage{underscore}
\usepackage{url}
\makeatletter
\def\url@aststyle{%
\@ifundefined{selectfont}{\def\UrlFont{\sf}}{\def\UrlFont{\small\ttfamily}}}
\makeatother
\urlstyle{ast}
\usepackage[titles]{tocloft}
\renewcommand{\cftchapfont}{%
\fontsize{11}{13}\usefont{OT1}{phv}{bc}{n}\selectfont
}
\newenvironment{astlisting}
{\begin{list}{}{\setlength{\leftmargin}{1em}}\item\scriptsize\bfseries}
{\end{list}}
\usepackage{sectsty}
\allsectionsfont{\usefont{OT1}{phv}{bc}{n}\selectfont}
\usepackage[Lenny]{fncychap}
\author{Asterisk Development Team \\ Asterisk.org}
\title{Asterisk Reference Information \\ Version ASTERISKVERSION}
\begin{document}
\maketitle
\tableofcontents
\chapter{Introduction}
This document contains various pieces of information that are useful for
reference purposes.
\section{License Information}
\input{../../LICENSE}
\subsection{Hold Music}
Digium has licensed the music included with
the Asterisk distribution From opsound.org
for use and distribution with Asterisk. It
is licensed ONLY for use as hold music within
an Asterisk based PBX.
\section{Security}
\input{security.tex}
\section{Hardware}
\input{hardware.tex}
\chapter{Configuration}
\section{General Configuration Information}
\subsection{Configuration Parser}
\input{configuration.tex}
\subsection{Asterisk.conf}
\input{asterisk-conf.tex}
\subsection{CLI Prompt}
\input{cliprompt.tex}
\subsection{Extensions}
\input{extensions.tex}
\subsection{IP Quality of Service}
\input{qos.tex}
\subsection{MP3 Support}
\input{mp3.tex}
\subsection{ICES}
\input{ices.tex}
\section{Database Support}
\subsection{Realtime Database Configuration}
\input{realtime.tex}
\subsection{FreeTDS}
\input{freetds.tex}
\section{Privacy}
\input{privacy.tex}
\chapter{Channel Variables}
\input{channelvariables.tex}
\chapter{AEL: Asterisk Extension Language}
\input{ael.tex}
\chapter{SLA: Shared Line Appearances}
\input{sla.tex}
\chapter{Channel Drivers}
\section{IAX2}
\input{chaniax.tex}
\subsection{IAX2 Jitterbuffer}
\input{jitterbuffer.tex}
\section{mISDN}
\input{misdn.tex}
\section{Local}
\input{localchannel.tex}
\section{Mobile}
\input{chan-mobile.tex}
\chapter{Distributed Universal Number Discovery (DUNDi)}
\section{Introduction}
\input{dundi.tex}
\section{Peering Agreement}
\input{../PEERING}
\chapter{ENUM}
\input{enum.tex}
\chapter{AMI: Asterisk Manager Interface}
\input{manager.tex}
\input{ajam.tex}
\chapter{CDR: Call Detail Records}
\input{billing.tex}
\input{cdrdriver.tex}
\chapter{CEL: Channel Event Logging}
\input{cel-doc.tex}
\input{celdriver.tex}
\chapter{Voicemail}
\section{ODBC Storage}
\label{odbcstorage}
\input{odbcstorage.tex}
\section{IMAP Storage}
\input{imapstorage.tex}
\chapter{SMS}
\input{app-sms.tex}
\chapter{Queues}
\input{queues-with-callback-members.tex}
\section{Queue Logs}
\input{queuelog.tex}
\chapter{Phone Provisioning}
\input{phoneprov.tex}
\chapter{Calendaring}
\input{calendaring.tex}
\chapter{Security Framework}
\input{security-events.tex}
\chapter{Secure Calls}
\input{secure-calls.tex}
\chapter{Manipulating Party ID Information}
\input{partymanip.tex}
\chapter{Call Completion Supplementary Services}
\input{ccss.tex}
\chapter{Packet Loss Concealment}
\input{plc.tex}
\chapter{Sounds Packages}
\input{sounds.tex}
\chapter{Development}
\section{Backtrace}
\input{backtrace.tex}
% This is a list of files not yet integrated into this document:
%
%Misc
%----
%asterisk-mib.txt SNMP mib for Asterisk (net-snmp)
%digium-mib.txt SNMP mib for Asterisk (net-snmp)
%
% Note that there is some developer documentation in the doc directory, but
% the goal is to have developer documentation all integrated into the doxygen
% documentation.
\end{document}

View File

@ -1,217 +0,0 @@
This document is intended to provide information on how to obtain the
backtraces required on the asterisk bug tracker, available at
\url{https://issues.asterisk.org}. The information is required by developers to
help fix problem with bugs of any kind. Backtraces provide information
about what was wrong when a program crashed; in our case,
Asterisk. There are two kind of backtraces (aka 'bt') which are
useful: bt and bt full.
First of all, when you start Asterisk, you MUST start it with option
-g. This tells Asterisk to produce a core file if it crashes.
If you start Asterisk with the safe\_asterisk script, it automatically
starts using the option -g.
If you're not sure if Asterisk is running with the -g option, type the
following command in your shell:
\begin{astlisting}
\begin{verbatim}
debian:/tmp# ps aux | grep asterisk
root 17832 0.0 1.2 2348 788 pts/1 S Aug12 0:00 /bin/sh /usr/sbin/safe_asterisk
root 26686 0.0 2.8 15544 1744 pts/1 S Aug13 0:02 asterisk -vvvg -c
[...]
\end{verbatim}
\end{astlisting}
The interesting information is located in the last column.
Second, your copy of Asterisk must have been built without
optimization or the backtrace will be (nearly) unusable. This can be
done by selecting the 'DONT\_OPTIMIZE' option in the Compiler Flags
submenu in the 'make menuselect' tree before building Asterisk.
After Asterisk crashes, a core file will be "dumped" in your \path{/tmp/}
directory. To make sure it's really there, you can just type the
following command in your shell:
\begin{astlisting}
\begin{verbatim}
debian:/tmp# ls -l /tmp/core.*
-rw------- 1 root root 10592256 Aug 12 19:40 /tmp/core.26252
-rw------- 1 root root 9924608 Aug 12 20:12 /tmp/core.26340
-rw------- 1 root root 10862592 Aug 12 20:14 /tmp/core.26374
-rw------- 1 root root 9105408 Aug 12 20:19 /tmp/core.26426
-rw------- 1 root root 9441280 Aug 12 20:20 /tmp/core.26462
-rw------- 1 root root 8331264 Aug 13 00:32 /tmp/core.26647
debian:/tmp#
\end{verbatim}
\end{astlisting}
In the event that there are multiple core files present (as in the
above example), it is important to look at the file timestamps in
order to determine which one you really intend to look at.
Now that we've verified the core file has been written to disk, the
final part is to extract 'bt' from the core file. Core files are
pretty big, don't be scared, it's normal.
\textbf{NOTE: Don't attach core files on the bug tracker, we only need the bt and bt full.}
For extraction, we use a really nice tool, called gdb. To verify that
you have gdb installed on your system:
\begin{astlisting}
\begin{verbatim}
debian:/tmp# gdb -v
GNU gdb 6.3-debian
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-linux".
debian:/tmp#
\end{verbatim}
\end{astlisting}
Which is great, we can continue. If you don't have gdb installed, go install gdb.
Now load the core file in gdb, as follows:
\begin{astlisting}
\begin{verbatim}
debian:/tmp# gdb asterisk /tmp/core.26252
[...]
(You would see a lot of output here.)
[...]
Reading symbols from /usr/lib/asterisk/modules/app_externalivr.so...done.
Loaded symbols for /usr/lib/asterisk/modules/app_externalivr.so
#0 0x29b45d7e in ?? ()
(gdb)
\end{verbatim}
\end{astlisting}
Now at the gdb prompt, type: bt
You would see output similar to:
\begin{astlisting}
\begin{verbatim}
(gdb) bt
#0 0x29b45d7e in ?? ()
#1 0x08180bf8 in ?? ()
#2 0xbcdffa58 in ?? ()
#3 0x08180bf8 in ?? ()
#4 0xbcdffa60 in ?? ()
#5 0x08180bf8 in ?? ()
#6 0x180bf894 in ?? ()
#7 0x0bf80008 in ?? ()
#8 0x180b0818 in ?? ()
#9 0x08068008 in ast_stopstream (tmp=0x40758d38) at file.c:180
#10 0x000000a0 in ?? ()
#11 0x000000a0 in ?? ()
#12 0x00000000 in ?? ()
#13 0x407513c3 in confcall_careful_stream (conf=0x8180bf8, filename=0x8181de8 "DAHDI/pseudo-1324221520") at app_meetme.c:262
#14 0x40751332 in streamconfthread (args=0x8180bf8) at app_meetme.c:1965
#15 0xbcdffbe0 in ?? ()
#16 0x40028e51 in pthread_start_thread () from /lib/libpthread.so.0
#17 0x401ec92a in clone () from /lib/libc.so.6
(gdb)
\end{verbatim}
\end{astlisting}
The bt's output is the information that we need on the bug tracker.
\begin{astlisting}
\begin{verbatim}
Now do a bt full as follows:
(gdb) bt full
#0 0x29b45d7e in ?? ()
No symbol table info available.
#1 0x08180bf8 in ?? ()
No symbol table info available.
#2 0xbcdffa58 in ?? ()
No symbol table info available.
#3 0x08180bf8 in ?? ()
No symbol table info available.
#4 0xbcdffa60 in ?? ()
No symbol table info available.
#5 0x08180bf8 in ?? ()
No symbol table info available.
#6 0x180bf894 in ?? ()
No symbol table info available.
#7 0x0bf80008 in ?? ()
No symbol table info available.
#8 0x180b0818 in ?? ()
No symbol table info available.
#9 0x08068008 in ast_stopstream (tmp=0x40758d38) at file.c:180
No locals.
#10 0x000000a0 in ?? ()
No symbol table info available.
#11 0x000000a0 in ?? ()
No symbol table info available.
#12 0x00000000 in ?? ()
No symbol table info available.
#13 0x407513c3 in confcall_careful_stream (conf=0x8180bf8, filename=0x8181de8 "DAHDI/pseudo-1324221520") at app_meetme.c:262
f = (struct ast_frame *) 0x8180bf8
trans = (struct ast_trans_pvt *) 0x0
#14 0x40751332 in streamconfthread (args=0x8180bf8) at app_meetme.c:1965
No locals.
#15 0xbcdffbe0 in ?? ()
No symbol table info available.
#16 0x40028e51 in pthread_start_thread () from /lib/libpthread.so.0
No symbol table info available.
#17 0x401ec92a in clone () from /lib/libc.so.6
No symbol table info available.
(gdb)
\end{verbatim}
\end{astlisting}
We also need gdb's output. That output gives more details compared to
the simple "bt". So we recommend that you use bt full instead of bt.
But, if you could include both, we appreciate that.
The final "extraction" would be to know all traces by all
threads. Even if asterisk runs on the same thread for each call, it
could have created some new threads.
To make sure we have the correct information, just do:
(gdb) thread apply all bt
\begin{astlisting}
\begin{verbatim}
Thread 1 (process 26252):
#0 0x29b45d7e in ?? ()
#1 0x08180bf8 in ?? ()
#2 0xbcdffa58 in ?? ()
#3 0x08180bf8 in ?? ()
#4 0xbcdffa60 in ?? ()
#5 0x08180bf8 in ?? ()
#6 0x180bf894 in ?? ()
#7 0x0bf80008 in ?? ()
#8 0x180b0818 in ?? ()
#9 0x08068008 in ast_stopstream (tmp=0x40758d38) at file.c:180
#10 0x000000a0 in ?? ()
#11 0x000000a0 in ?? ()
#12 0x00000000 in ?? ()
#13 0x407513c3 in confcall_careful_stream (conf=0x8180bf8, filename=0x8181de8 "DAHDI/pseudo-1324221520") at app_meetme.c:262
#14 0x40751332 in streamconfthread (args=0x8180bf8) at app_meetme.c:1965
#15 0xbcdffbe0 in ?? ()
#16 0x40028e51 in pthread_start_thread () from /lib/libpthread.so.0
#17 0x401ec92a in clone () from /lib/libc.so.6
(gdb)
\end{verbatim}
\end{astlisting}
That output tells us crucial information about each thread.
Now, just create an output.txt file and dump your "bt full"
(and/or "bt") ALONG WITH "thread apply all bt" into it.
Note: Please ATTACH your output, DO NOT paste it as a note.
And you're ready for upload on the bug tracker.
If you have questions or comments regarding this documentation, feel
free to pass by the \#asterisk-bugs channel on irc.freenode.net.

View File

@ -1,86 +0,0 @@
\section{Applications}
\begin{itemize}
\item SetAccount - Set account code for billing
\item SetAMAFlags - Sets AMA flags
\item NoCDR - Make sure no CDR is saved for a specific call
\item ResetCDR - Reset CDR
\item ForkCDR - Save current CDR and start a new CDR for this call
\item Authenticate - Authenticates and sets the account code
\item SetCDRUserField - Set CDR user field
\item AppendCDRUserField - Append data to CDR User field
\end{itemize}
For more information, use the "core show application $<$application$>$" command.
You can set default account codes and AMA flags for devices in
channel configuration files, like sip.conf, iax.conf etc.
\section{CDR Fields}
\begin{itemize}
\item accountcode: What account number to use, (string, 20 characters)
\item src: Caller*ID number (string, 80 characters)
\item dst: Destination extension (string, 80 characters)
\item dcontext: Destination context (string, 80 characters)
\item clid: Caller*ID with text (80 characters)
\item channel: Channel used (80 characters)
\item dstchannel: Destination channel if appropriate (80 characters)
\item lastapp: Last application if appropriate (80 characters)
\item lastdata: Last application data (arguments) (80 characters)
\item start: Start of call (date/time)
\item answer: Answer of call (date/time)
\item end: End of call (date/time)
\item duration: Total time in system, in seconds (integer), from dial to hangup
\item billsec: Total time call is up, in seconds (integer), from answer to hangup
\item disposition: What happened to the call: ANSWERED, NO ANSWER, BUSY
\item amaflags: What flags to use: DOCUMENTATION, BILL, IGNORE etc,
specified on a per channel basis like accountcode.
\item user field: A user-defined field, maximum 255 characters
\end{itemize}
In some cases, uniqueid is appended:
\begin{itemize}
\item uniqueid: Unique Channel Identifier (32 characters)
This needs to be enabled in the source code at compile time
\end{itemize}
NOTE: If you use IAX2 channels for your calls, and allow 'full' transfers
(not media-only transfers), then when the calls is transferred the server
in the middle will no longer be involved in the signaling path, and thus
will not generate accurate CDRs for that call. If you can, use media-only
transfers with IAX2 to avoid this problem, or turn off transfers completely
(although this can result in a media latency increase since the media packets
have to traverse the middle server(s) in the call).
\section{Variables}
If the channel has a CDR, that CDR has its own set of variables which can be
accessed just like channel variables. The following builtin variables are
available.
\begin{verbatim}
${CDR(clid)} Caller ID
${CDR(src)} Source
${CDR(dst)} Destination
${CDR(dcontext)} Destination context
${CDR(channel)} Channel name
${CDR(dstchannel)} Destination channel
${CDR(lastapp)} Last app executed
${CDR(lastdata)} Last app's arguments
${CDR(start)} Time the call started.
${CDR(answer)} Time the call was answered.
${CDR(end)} Time the call ended.
${CDR(duration)} Duration of the call.
${CDR(billsec)} Duration of the call once it was answered.
${CDR(disposition)} ANSWERED, NO ANSWER, BUSY
${CDR(amaflags)} DOCUMENTATION, BILL, IGNORE etc
${CDR(accountcode)} The channel's account code.
${CDR(uniqueid)} The channel's unique id.
${CDR(userfield)} The channels uses specified field.
\end{verbatim}
In addition, you can set your own extra variables by using Set(CDR(name)=value).
These variables can be output into a text-format CDR by using the cdr\_custom
CDR driver; see the cdr\_custom.conf.sample file in the configs directory for
an example of how to do this.

View File

@ -1,206 +0,0 @@
\section{Introduction}
The Asterisk Calendaring API aims to be a generic interface for integrating
Asterisk with various calendaring technologies. The goal is to be able to
support reading and writing of calendar events as well as allowing notification
of pending events through the Asterisk dialplan.
There are three calendaring modules that ship with Asterisk that provide support
for iCalendar, CalDAV, and Microsoft Exchange Server calendars. All three
modules support event notification. Both CalDAV and Exchange support reading
and writing calendars, while iCalendar is a read-only format.
\section{Configuring Asterisk Calendaring}
All asterisk calendaring modules are configured through calender.conf. Each
calendar module can define its own set of required parameters in addition to the
parameters available to all calendar types. An effort has been made to keep all
options the same in all calendaring modules, but some options will diverge over
time as features are added to each module.
An example calendar.conf might look like:
\begin{astlisting}
\begin{verbatim}
[calendar_joe]
type = ical
url = https://example.com/home/jdoe/Calendar
user = jdoe
secret = mysecret
refresh = 15
timeframe = 600
autoreminder = 10
channel = SIP/joe
context = calendar_event_notify
extension = s
waittime = 30
\end{verbatim}
\end{astlisting}
\subsection{Module-independent settings}
The settings related to calendar event notification are handled by the core
calendaring API. These settings are:
\begin{description}
\item[autoreminder] This allows the overriding of any alarms that may or may not
be set for a calendar event. It is specified in minutes.
\item[refresh] How often to refresh the calendar data; specified in minutes.
\item[timeframe] How far into the future each calendar refresh should look. This
is the amount of data that will be visible to queries from the dialplan. This
setting should always be greater than or equal to the refresh setting or events
may be missed. It is specified in minutes.
\item[channel] The channel that should be used for making the notification
attempt.
\item[waittime] How long to wait, in seconds, for the channel to answer a notification
attempt.
\end{description}
There are two ways to specify how to handle a notification. One option is
providing a context and extension, while the other is providing an application
and the arguments to that application. One (and only one) of these options
should be provided.
\begin{description}
\item[context] The context of the extension to connect to the notification
channel
\item[extension] The extension to connect to the notification. Note that the
priority will always be 1.
\end{description}
or
\begin{description}
\item[app] The dialplan application to execute upon the answer of a notification
\item[appdata] The data to pass to the notification dialplan application
\end{description}
\subsection{Module-dependent settings}
Connection-related options are specific to each module. Currently, all modules
take a url, user, and secret for configuration and no other module-specific
settings have been implemented. At this time, no support for HTTP redirects has
been implemented, so it is important to specify the correct URL--paying attention
to any trailing slashes that may be necessary.
\section{Dialplan functions}
\subsection{Read functions}
The simplest dialplan query is the CALENDAR\_BUSY query. It takes a single
option, the name of the calendar defined, and returns "1" for busy (including
tentatively busy) and "0" for not busy.
For more information about a calendar event, a combination of CALENDAR\_QUERY
and CALENDAR\_QUERY\_RESULT is used. CALENDAR\_QUERY takes the calendar name
and optionally a start and end time in "unix time" (seconds from unix epoch). It
returns an id that can be passed to CALENDAR\_QUERY\_RESULT along with a field
name to return the data in that field. If multiple events are returned in the
query, the number of the event in the list can be specified as well. The available
fields to return are:
\begin{description}
\item[summary] A short summary of the event
\item[description] The full description of the event
\item[organizer] Who organized the event
\item[location] Where the event is located
\item[calendar] The name of the calendar from calendar.conf
\item[uid] The unique identifier associated with the event
\item[start] The start of the event in seconds since Unix epoch
\item[end] The end of the event in seconds since Unix epoch
\item[busystate] The busy state 0=Free, 1=Tentative, 2=Busy
\item[attendees] A comma separated list of attendees as stored in the event and
may include prefixes such as "mailto:".
\end{description}
When an event notification is sent to the dial plan, the CALENDAR\_EVENT
function may be used to return the information about the event that is causing
the notification. The fields that can be returned are the same as those from
CALENDAR\_QUERY\_RESULT.
\subsection{Write functions}
To write an event to a calendar, the CALENDAR\_WRITE function is used. This
function takes a calendar name and also uses the same fields as
CALENDAR\_QUERY\_RESULT. As a write function, it takes a set of comma-separated
values that are in the same order as the specified fields. For example:
\begin{astlisting}
\begin{verbatim}
CALENDAR_WRITE(mycalendar,summary,organizer,start,end,busystate)=
"My event","mailto:jdoe@example.com",228383580,228383640,1)
\end{verbatim}
\end{astlisting}
\section{Dialplan Examples}
\subsection{Office hours}
A common business PBX scenario is would be executing dialplan logic based on
when the business is open and the phones staffed. If the business is closed for
holidays, it is sometimes desirable to play a message to the caller stating why
the business is closed.
The standard way to do this in asterisk has been doing a series of GotoIfTime
statements or time-based include statements. Either way can be tedious and
requires someone with access to edit asterisk config files.
With calendaring, the adminstrator only needs to set up a calendar that contains
the various holidays or even recurring events specifying the office hours. A
custom greeting filename could even be contained in the description field for
playback. For example:
\begin{astlisting}
\begin{verbatim}
[incoming]
exten => 5555551212,1,Answer
exten => 5555551212,n,GotoIf(${CALENDAR_BUSY(officehours)}?closed:attendant,s,1)
exten => 5555551212,n(closed),Set(id=${CALENDAR_QUERY(office,${EPOCH},${EPOCH})})
exten => 5555551212,n,Set(soundfile=${CALENDAR_QUERY_RESULT(${id},description)})
exten => 5555551212,n,Playback($[${ISNULL(soundfile)} ? generic-closed :: ${soundfile}])
exten => 5555551212,n,Hangup
\end{verbatim}
\end{astlisting}
\subsection{Meeting reminders}
One useful application of Asterisk Calendaring is the ability to execute
dialplan logic based on an event notification. Most calendaring technologies
allow a user to set an alarm for an event. If these alarms are set on a calendar
that Asterisk is monitoring and the calendar is set up for event notification
via calendar.conf, then Asterisk will execute notify the specified channel at
the time of the alarm. If an overrided notification time is set with the
autoreminder setting, then the notification would happen at that time instead.
The following example demonstrates the set up for a simple event notification
that plays back a generic message followed by the time of the upcoming meeting.
calendar.conf.
\begin{astlisting}
\begin{verbatim}
[calendar_joe]
type = ical
url = https://example.com/home/jdoe/Calendar
user = jdoe
secret = mysecret
refresh = 15
timeframe = 600
autoreminder = 10
channel = SIP/joe
context = calendar_event_notify
extension = s
waittime = 30
\end{verbatim}
\end{astlisting}
\begin{astlisting}
\begin{verbatim}
[calendar_event_notify]
exten => s,1,Answer
exten => s,n,Playback(you-have-a-meeting-at)
exten => s,n,SayUnixTime(${CALENDAR_EVENT(start)})
exten => s,n,Hangup
\end{verbatim}
\end{astlisting}
\subsection{Writing an event}
Both CalDAV and Exchange calendar servers support creating new events. The
following example demonstrates writing a log of a call to a calendar.
\begin{astlisting}
\begin{verbatim}
[incoming]
exten => 6000,1,Set(start=${EPOCH})
exten => 6000,n,Dial(SIP/joe)
exten => h,1,Set(end=${EPOCH})
exten => h,n,Set(CALENDAR_WRITE(calendar_joe,summary,start,end)=Call from ${CALLERID(all)},${start},${end})
\end{verbatim}
\end{astlisting}

View File

@ -1,414 +0,0 @@
\section{Introduction}
A new feature for Asterisk 1.8 is Call Completion Supplementary
Services. This document aims to explain the system and how to use it.
In addition, this document examines some potential troublesome points
which administrators may come across during their deployment of the
feature.
\section{What is CCSS?}
Call Completion Supplementary Services (often abbreviated "CCSS" or
simply "CC") allow for a caller to let Asterisk automatically alert him
when a called party has become available, given that a previous call to
that party failed for some reason. The two services offered are Call
Completion on Busy Subscriber (CCBS) and Call Completion on No Response
(CCNR).
To illustrate, let's say that Alice attempts to call Bob. Bob is
currently on a phone call with Carol, though, so Alice hears a busy
signal. In this situation, assuming that Asterisk has been configured
to allow for such activity, Alice would be able to request CCBS. Once
Bob has finished his phone call, Alice will be alerted. Alice can then
attempt to call Bob again.
\section{Glossary of Terms}
In this document, we will use some terms which may require
clarification. Most of these terms are specific to Asterisk, and are by
no means standard.
\begin{itemize}
\item CCBS: Call Completion on Busy Subscriber. When a call fails because the
recipient's phone is busy, the caller will have the opportunity to
request CCBS. When the recipient's phone is no longer busy, the caller
will be alerted. The means by which the caller is alerted is dependent
upon the type of agent used by the caller.
\item CCNR: Call Completion on No Response. When a call fails because the
recipient does not answer the phone, the caller will have the opportun-
ity to request CCNR. When the recipient's phone becomes busy and then
is no longer busy, the caller will be alerted. The means by which the
caller is alerted is dependent upon the type of the agent used by the
caller.
\item Agent: The agent is the entity within Asterisk that communicates with
and acts on behalf of the calling party.
\item Monitor: The monitor is the entity within Asterisk that communicates
with and monitors the status of the called party.
\item Generic Agent: A generic agent is an agent that uses protocol-agnostic
methods to communicate with the caller. Generic agents should only be
used for phones, and never should be used for "trunks."
\item Generic Monitor: A generic monitor is a monitor that uses protocol-
agnostic methods to monitor the status of the called party. Like with
generic agents, generic monitors should only be used for phones.
\item Native Agent: The opposite of a generic agent. A native agent uses
protocol-specific messages to communicate with the calling party.
Native agents may be used for both phones and trunks, but it must be
known ahead of time that the device with which Asterisk is communica-
ting supports the necessary signaling.
\item Native Monitor: The opposite of a generic monitor. A native monitor
uses protocol-specific messages to subscribe to and receive notifica-
tion of the status of the called party. Native monitors may be used
for both phones and trunks, but it must be known ahead of time that
the device with which Asterisk is communicating supports the
necessary signaling.
\item Offer: An offer of CC refers to the notification received by the caller
that he may request CC.
\item Request: When the caller decides that he would like to subscribe to CC,
he will make a request for CC. Furthermore, the term may refer to any
outstanding requests made by callers.
\item Recall: When the caller attempts to call the recipient after being
alerted that the recipient is available, this action is referred to
as a "recall."
\end{itemize}
\section{The CC Process}
\subsection{The Initial Call}
The only requirement for the use of CC is to configure an agent for
the caller and a monitor for at least one recipient of the call.
This is controlled using the cc\_agent\_policy for the caller and the
cc\_monitor\_policy for the recipient. For more information about these
configuration settings, see configs/samples/ccss.conf.sample. If the
agent for the caller is set to something other than "never" and at
least one recipient has his monitor set to something other than
"never," then CC will be offered to the caller at the end of the
call.
Once the initial call has been hung up, the configured
cc\_offer\_timer for the caller will be started. If the caller wishes to
request CC for the previous call, he must do so before the timer
expires.
\subsection{Requesting CC}
Requesting CC is done differently depending on the type of agent
the caller is using.
With generic agents, the CallCompletionRequest application must be
called in order to request CC. There are two different ways in which
this may be called. It may either be called before the caller hangs up
during the initial call, or the caller may hang up from the initial
call and dial an extension which calls the CallCompletionRequest
application. If the second method is used, then the caller will
have until the cc\_offer\_timer expires to request CC.
With native agents, the method for requesting CC is dependent upon
the technology being used, coupled with the make of equipment. It may
be possible to request CC using a programmable key on a phone or by
clicking a button on a console. If you are using equipment which can
natively support CC but do not know the means by which to request it,
then contact the equipment manufacturer for more information.
\subsection{Cancelling CC}
CC may be canceled after it has been requested. The method by which
this is accomplished differs based on the type of agent the calling
party uses.
When using a generic agent, the dialplan application
CallRequestCancel is used to cancel CC. When using a native monitor,
the method by which CC is cancelled depends on the protocol used.
Likely, this will be done using a button on a phone.
Keep in mind that if CC is cancelled, it cannot be un-cancelled.
\subsection{Monitoring the Called Party}
Once the caller has requested CC, then Asterisk's job is to monitor
the progress of the called parties. It is at this point that Asterisk
allocates the necessary resources to monitor the called parties.
A generic monitor uses Asterisk's device state subsystem in order
to determine when the called party has become available. For both CCBS
and CCNR, Asterisk simply waits for the phone's state to change to
a "not in use" state from a different state. Once this happens, then
Asterisk will consider the called party to be available and will alert
the caller.
A native monitor relies on the network to send a protocol-specific
message when the called party has become available. When Asterisk
receives such a message, it will consider the called party to be
available and will alert the caller.
Note that since a single caller may dial multiple parties, a monitor
is used for each called party. It is within reason that different called
parties will use different types of monitors for the same CC request.
\subsection{Alerting the Caller}
Once Asterisk has determined that the called party has become available
the time comes for Asterisk to alert the caller that the called party has
become available. The method by which this is done differs based on the
type of agent in use.
If a generic agent is used, then Asterisk will originate a call to
the calling party. Upon answering the call, if a callback macro has
been configured, then that macro will be executed on the calling
party's channel. After the macro has completed, an outbound call
will be issued to the parties involved in the original call.
If a native agent is used, then Asterisk will send an appropriate
notification message to the calling party to alert it that it may now
attempt its recall. How this is presented to the caller is dependent
upon the protocol and equipment that the caller is using. It is
possible that the calling party's phone will ring and a recall will
be triggered upon answering the phone, or it may be that the user
has a specific button that he may press to initiate a recall.
\subsection{If the Caller is unavailable}
When the called party has become available, it is possible that
when Asterisk attempts to alert the calling party of the called party's
availability, the calling party itself will have become unavailable.
If this is the case, then Asterisk will suspend monitoring of the
called party and will instead monitor the availability of the calling
party. The monitoring procedure for the calling party is the same
as is used in the section "Monitoring the Called Party." In other
words, the method by which the calling party is monitored is dependent
upon the type of agent used by the caller.
Once Asterisk has determined that the calling party has become
available again, Asterisk will then move back to the process used
in the section "Monitoring the Called Party."
\subsection{The CC recall}
The calling party will make its recall to the same extension
that was dialed. Asterisk will provide a channel variable,
CC\_INTERFACES, to be used as an argument to the Dial application
for CC recalls. It is strongly recommended that you use this
channel variable during a CC recall. Listed are two reasons:
\begin{itemize}
\item The dialplan may be written in such a way that the dialed
destintations are dynamically generated. With such a dialplan, it
cannot be guaranteed that the same interfaces will be recalled.
\item For calling destinations with native CC monitors, it may be
necessary to dial a special string in order to notify the channel
driver that the number being dialed is actually part of a CC recall.
\end{itemize}
Note that even if your call gets routed through local channels,
the CC\_INTERFACES variable will be populated with the appropriate
values for that specific extension.
When the called parties are dialed, it is expected that a called
party will answer, since Asterisk had previously determined that the
party was available. However, it is possible that the called party
may choose not to respond to the call, or he could have become busy
again. In such a situation, the calling party must re-request CC if
he wishes to still be alerted when the calling party has become
available.
\section{Miscellaneous Information and Tips}
\begin{itemize}
\item Be aware when using a generic agent that the max\_cc\_agents
configuration parameter is ignored. The main driving reason for
this is that the mechanism for cancelling CC when using a generic
agent would become much more potentially confusing to execute. By
limiting a calling party to having a single request, there is only
ever a single request to be cancelled, making the process simple.
\item Keep in mind that no matter what CC agent type is being used,
a CC request can only be made for the latest call issued.
\item If available timers are running on multiple called parties,
it is possible that one of the timers may expire before the others
do. If such a situation occurs, then the interface on which the
timer expired will cease to be monitored. If, though, one of the
other called parties becomes available before his available timer
expires, the called party whose available timer had previously
expired will still be included in the CC\_INTERFACES channel
variable on the recall.
\item It is strongly recommended that lots of thought is placed
into the settings of the CC timers. Our general recommendation is
that timers for phones should be set shorter than those for trunks.
The reason for this is that it makes it less likely for a link in
the middle of a network to cause CC to fail.
\item CC can potentially be a memory hog if used irresponsibly. The
following are recommendations to help curb the amount of resources
required by the CC engine. First, limit the maximum number of
CC requests in the system using the cc\_max\_requests option in
ccss.conf. Second, set the cc\_offer\_timer low for your callers. Since
it is likely that most calls will not result in a CC request, it is
a good idea to set this value to something low so that information
for calls does not stick around in memory for long. The final thing
that can be done is to conditionally set the cc\_agent\_policy to
"never" using the CALLCOMPLETION dialplan function. By doing this,
no CC information will be kept around after the call completes.
\item It is possible to request CCNR on answered calls. The reason
for this is that it is impossible to know whether a call that is
answered has actually been answered by a person or by something
such as voicemail or some other IVR.
\item Not all channel drivers have had the ability to set CC config
parameters in their configuration files added yet. At the time of
this writing (2009 Oct), only chan\_sip has had this ability added, with
short-term plans to add this to chan\_dahdi as well. It is
possible to set CC configuration parameters for other channel types,
though. For these channel types, the setting of the parameters can
only be accomplished using the CALLCOMPLETION dialplan function.
\item It is documented in many places that generic agents and monitors
can only be used for phones. In most cases, however, Asterisk has no
way of distinguishing between a phone and a trunk itself. The result
is that Asterisk will happily let you violate the advice given and
allow you to set up a trunk with a generic monitor or agent. While this
will not cause anything catastrophic to occur, the behavior will most
definitely not be what you want.
\item At the time of this writing (2009 Oct), Asterisk is the only
known SIP stack to write an implementation of
draft-ietf-bliss-call-completion-04. As a result, it is recommended
that for your SIP phones, use a generic agent and monitor. For SIP
trunks, you will only be able to use CC if the other end is
terminated by another Asterisk server running version 1.8 or later.
\item If the Dial application is called multiple times by a single
extension, CC will only be offered to the caller for the parties called
by the first instantiation of Dial.
\item If a phone forwards a call, then CC may only be requested for
the phone that executed the call forward. CC may not be requested
for the phone to which the call was forwarded.
\item CC is currently only supported by the Dial application. Queue,
Followme, and Page do not support CC because it is not particularly
useful for those applications.
\item Generic CC relies heavily on accurate device state reporting. In
particular, when using SIP phones it is vital to be sure that device
state is updated properly when using them. In order to facilitate proper
device state handling, be sure to set callcounter=yes for all peers and
to set limitonpeers=yes in the general section of sip.conf
\item When using SIP CC (i.e. native CC over SIP), it is important that
your minexpiry and maxexpiry values allow for available timers to run
as little or as long as they are configured. When an Asterisk server
requests call completion over SIP, it sends a SUBSCRIBE message with
an Expires header set to the number of seconds that the available
timer should run. If the Asterisk server that receives this SUBSCRIBE
has a maxexpiry set lower than what is in the received Expires header,
then the available timer will only run for maxexpiry seconds.
\item As with all Asterisk components, CC is not perfect. If you should
find a bug or wish to enhance the feature, please open an issue on
https://issues.asterisk.org. If writing an enhancement, please be sure
to include a patch for the enhancement, or else the issue will be
closed.
\end{itemize}
\section{Simple Example of generic call completion}
The following is an incredibly bare-bones example sip.conf
and dialplan to show basic usage of generic call completion.
It is likely that if you have a more complex setup, you will
need to make use of items like the CALLCOMPLETION dialplan
function or the CC\_INTERFACES channel variable.
First, let's establish a very simple sip.conf to use for this
\begin{verbatim}
[Mark]
context=phone_calls
cc_agent_policy=generic
cc_monitor_policy=generic
;We will accept defaults for the rest of the cc parameters
;We also are not concerned with other SIP details for this
;example
[Richard]
context=phone_calls
cc_agent_policy=generic
cc_monitor_policy=generic
\end{verbatim}
Now, let's write a simple dialplan
\begin{verbatim}
[phone_calls]
exten => 1000,1,Dial(SIP/Mark,20)
exten => 1000,n,Hangup
exten => 2000,1,Dial(SIP/Richard,20)
exten => 2000,n,Hangup
exten => 30,1,CallCompletionRequest
exten => 30,n,Hangup
exten => 31,1,CallCompletionCancel
exten => 31,n,Hangup
\end{verbatim}
\begin{itemize}
\item Scenario 1:
Mark picks up his phone and dials Richard by dialing 2000. Richard is
currently on a call, so Mark hears a busy signal. Mark then hangs up,
picks up the phone and dials 30 to call the CallCompletionRequest
application. After some time, Richard finishes his call and hangs up.
Mark is automatically called back by Asterisk. When Mark picks up his
phone, Asterisk will dial extension 2000 for him.
\item Scenario 2:
Richard picks up his phone and dials Mark by dialing 1000. Mark has stepped
away from his desk, and so he is unable to answer the phone within the
20 second dial timeout. Richard hangs up, picks the phone back up and then
dials 30 to request call completion. Mark gets back to his desk and dials
somebody's number. When Mark finishes the call, Asterisk detects that Mark's
phone has had some activity and has become available again and rings Richard's
phone. Once Richard picks up, Asterisk automatically dials exteision 1000 for
him.
\item Scenario 3:
Much like scenario 1, Mark calls Richard and Richard is busy. Mark hangs up,
picks the phone back up and then dials 30 to request call completion. After
a little while, Mark realizes he doesn't actually need to talk to Richard, so
he dials 31 to cancel call completion. When Richard becomes free, Mark will
not automatically be redialed by Asterisk.
\item Scenario 4:
Richard calls Mark, but Mark is busy. About thirty seconds later, Richard decides
that he should perhaps request call completion. However, since Richard's phone
has the default cc\_offer\_timer of 20 seconds, he has run out of time to
request call completion. He instead must attempt to dial Mark again manually. If
Mark is still busy, Richard can attempt to request call completion on this second
call instead.
\item Scenario 5:
Mark calls Richard, and Richard is busy. Mark requests call completion. Richard
does not finish his current call for another 2 hours (7200 seconds). Since Mark
has the default ccbs\_available\_timer of 4800 seconds set, Mark will not be
automatically recalled by Asterisk when Richard finishes his call.
\item Scenario 6:
Mark calls Richard, and Richard does not respond within the 20 second dial timeout.
Mark requests call completion. Richard does not use his phone again for another
4 hours (144000 seconds). Since Mark has the default ccnr\_available\_timer
of 7200 seconds set, Mark will not be automatically recalled by Asterisk when
Richard finishes his call.
\end{itemize}

View File

@ -1,509 +0,0 @@
\section{Storage Backends}
\subsection{Microsoft SQL Server}
Asterisk can currently store CDRs into an MSSQL database in
two different ways: cdr_odbc or cdr_tds
Call Data Records can be stored using unixODBC (which requires
the FreeTDS package) [cdr_odbc] or directly by using just the
FreeTDS package [cdr_tds] The following provide some
examples known to get asterisk working with mssql.
NOTE: Only choose one db connector.
\subsubsection{ODBC using cdr_odbc}
Compile, configure, and install the latest unixODBC package:
\begin{astlisting}
\begin{verbatim}
tar -zxvf unixODBC-2.2.9.tar.gz &&
cd unixODBC-2.2.9 &&
./configure --sysconfdir=/etc --prefix=/usr --disable-gui &&
make &&
make install
\end{verbatim}
\end{astlisting}
Compile, configure, and install the latest FreeTDS package:
\begin{astlisting}
\begin{verbatim}
tar -zxvf freetds-0.62.4.tar.gz &&
cd freetds-0.62.4 &&
./configure --prefix=/usr --with-tdsver=7.0 \
--with-unixodbc=/usr/lib &&
make && make install
\end{verbatim}
\end{astlisting}
Compile, or recompile, asterisk so that it will now add support
for cdr_odbc.
\begin{astlisting}
\begin{verbatim}
make clean && ./configure --with-odbc &&
make update &&
make &&
make install
\end{verbatim}
\end{astlisting}
Setup odbc configuration files. These are working examples
from my system. You will need to modify for your setup.
You are not required to store usernames or passwords here.
\begin{astlisting}
\begin{verbatim}
/etc/odbcinst.ini
[FreeTDS]
Description = FreeTDS ODBC driver for MSSQL
Driver = /usr/lib/libtdsodbc.so
Setup = /usr/lib/libtdsS.so
FileUsage = 1
/etc/odbc.ini
[MSSQL-asterisk]
description = Asterisk ODBC for MSSQL
driver = FreeTDS
server = 192.168.1.25
port = 1433
database = voipdb
tds_version = 7.0
language = us_english
\end{verbatim}
\end{astlisting}
Only install one database connector. Do not confuse asterisk
by using both ODBC (cdr_odbc) and FreeTDS (cdr_tds).
This command will erase the contents of cdr_tds.conf
\begin{astlisting}
\begin{verbatim}
[ -f /etc/asterisk/cdr_tds.conf ] > /etc/asterisk/cdr_tds.conf
\end{verbatim}
\end{astlisting}
NOTE: unixODBC requires the freeTDS package, but asterisk does
not call freeTDS directly.
Now set up cdr_odbc configuration files. These are working samples
from my system. You will need to modify for your setup. Define
your usernames and passwords here, secure file as well.
\begin{astlisting}
\begin{verbatim}
/etc/asterisk/cdr_odbc.conf
[global]
dsn=MSSQL-asterisk
username=voipdbuser
password=voipdbpass
loguniqueid=yes
\end{verbatim}
\end{astlisting}
And finally, create the 'cdr' table in your mssql database.
\begin{astlisting}
\begin{verbatim}
CREATE TABLE cdr (
[calldate] [datetime] NOT NULL ,
[clid] [varchar] (80) NOT NULL ,
[src] [varchar] (80) NOT NULL ,
[dst] [varchar] (80) NOT NULL ,
[dcontext] [varchar] (80) NOT NULL ,
[channel] [varchar] (80) NOT NULL ,
[dstchannel] [varchar] (80) NOT NULL ,
[lastapp] [varchar] (80) NOT NULL ,
[lastdata] [varchar] (80) NOT NULL ,
[duration] [int] NOT NULL ,
[billsec] [int] NOT NULL ,
[disposition] [varchar] (45) NOT NULL ,
[amaflags] [int] NOT NULL ,
[accountcode] [varchar] (20) NOT NULL ,
[uniqueid] [varchar] (150) NOT NULL ,
[userfield] [varchar] (255) NOT NULL
)
\end{verbatim}
\end{astlisting}
Start asterisk in verbose mode, you should see that asterisk
logs a connection to the database and will now record every
call to the database when it's complete.
\subsubsection{TDS, using cdr_tds}
Compile, configure, and install the latest FreeTDS package:
\begin{astlisting}
\begin{verbatim}
tar -zxvf freetds-0.62.4.tar.gz &&
cd freetds-0.62.4 &&
./configure --prefix=/usr --with-tdsver=7.0
make &&
make install
\end{verbatim}
\end{astlisting}
Compile, or recompile, asterisk so that it will now add support
for cdr_tds.
\begin{astlisting}
\begin{verbatim}
make clean && ./configure --with-tds &&
make update &&
make &&
make install
\end{verbatim}
\end{astlisting}
Only install one database connector. Do not confuse asterisk
by using both ODBC (cdr_odbc) and FreeTDS (cdr_tds).
This command will erase the contents of cdr_odbc.conf
\begin{astlisting}
\begin{verbatim}
[ -f /etc/asterisk/cdr_odbc.conf ] > /etc/asterisk/cdr_odbc.conf
\end{verbatim}
\end{astlisting}
Setup cdr_tds configuration files. These are working samples
from my system. You will need to modify for your setup. Define
your usernames and passwords here, secure file as well.
\begin{astlisting}
\begin{verbatim}
/etc/asterisk/cdr_tds.conf
[global]
hostname=192.168.1.25
port=1433
dbname=voipdb
user=voipdbuser
password=voipdpass
charset=BIG5
\end{verbatim}
\end{astlisting}
And finally, create the 'cdr' table in your mssql database.
\begin{astlisting}
\begin{verbatim}
CREATE TABLE cdr (
[accountcode] [varchar] (20) NULL ,
[src] [varchar] (80) NULL ,
[dst] [varchar] (80) NULL ,
[dcontext] [varchar] (80) NULL ,
[clid] [varchar] (80) NULL ,
[channel] [varchar] (80) NULL ,
[dstchannel] [varchar] (80) NULL ,
[lastapp] [varchar] (80) NULL ,
[lastdata] [varchar] (80) NULL ,
[start] [datetime] NULL ,
[answer] [datetime] NULL ,
[end] [datetime] NULL ,
[duration] [int] NULL ,
[billsec] [int] NULL ,
[disposition] [varchar] (20) NULL ,
[amaflags] [varchar] (16) NULL ,
[uniqueid] [varchar] (150) NULL ,
[userfield] [varchar] (256) NULL
)
\end{verbatim}
\end{astlisting}
Start asterisk in verbose mode, you should see that asterisk
logs a connection to the database and will now record every
call to the database when it's complete.
\subsection{MySQL}
\subsubsection{ODBC}
Using MySQL for CDR records is supported by using ODBC and the cdr_odbc module.
\subsubsection{Native}
Alternatively, there is a native MySQL CDR module.
To use it, configure the module in cdr_mysql.conf. Create a table called cdr under the database name you will be using the following schema.
\begin{astlisting}
\begin{verbatim}
CREATE TABLE cdr (
calldate datetime NOT NULL default '0000-00-00 00:00:00',
clid varchar(80) NOT NULL default '',
src varchar(80) NOT NULL default '',
dst varchar(80) NOT NULL default '',
dcontext varchar(80) NOT NULL default '',
channel varchar(80) NOT NULL default '',
dstchannel varchar(80) NOT NULL default '',
lastapp varchar(80) NOT NULL default '',
lastdata varchar(80) NOT NULL default '',
duration int(11) NOT NULL default '0',
billsec int(11) NOT NULL default '0',
disposition varchar(45) NOT NULL default '',
amaflags int(11) NOT NULL default '0',
accountcode varchar(20) NOT NULL default '',
uniqueid varchar(32) NOT NULL default '',
userfield varchar(255) NOT NULL default ''
);
\end{verbatim}
\end{astlisting}
\subsection{PostgreSQL}
If you want to go directly to postgresql database, and have the cdr_pgsql.so
compiled you can use the following sample setup.
On Debian, before compiling asterisk, just install libpqxx-dev.
Other distros will likely have a similiar package.
Once you have the compile done,
copy the sample cdr_pgsql.conf file or create your own.
Here is a sample:
\begin{astlisting}
\begin{verbatim}
/etc/asterisk/cdr_pgsql.conf
; Sample Asterisk config file for CDR logging to PostgresSQL
[global]
hostname=localhost
port=5432
dbname=asterisk
password=password
user=postgres
table=cdr
\end{verbatim}
\end{astlisting}
Now create a table in postgresql for your cdrs
\begin{astlisting}
\begin{verbatim}
CREATE TABLE cdr (
calldate timestamp NOT NULL ,
clid varchar (80) NOT NULL ,
src varchar (80) NOT NULL ,
dst varchar (80) NOT NULL ,
dcontext varchar (80) NOT NULL ,
channel varchar (80) NOT NULL ,
dstchannel varchar (80) NOT NULL ,
lastapp varchar (80) NOT NULL ,
lastdata varchar (80) NOT NULL ,
duration int NOT NULL ,
billsec int NOT NULL ,
disposition varchar (45) NOT NULL ,
amaflags int NOT NULL ,
accountcode varchar (20) NOT NULL ,
uniqueid varchar (150) NOT NULL ,
userfield varchar (255) NOT NULL
);
\end{verbatim}
\end{astlisting}
\subsection{SQLite 2}
SQLite version 2 is supported in cdr_sqlite.
\subsection{SQLite 3}
SQLite version 3 is supported in cdr_sqlite3\_custom.
\subsection{RADIUS}
\subsubsection{What is needed}
\begin{itemize}
\item FreeRADIUS server
\item Radiusclient-ng library
\item Asterisk PBX
\end{itemize}
\begin{figure}[h]
\begin{center}
\setlength{\unitlength}{4cm}
\begin{picture}(3,.75)
\put(0,0){\line(0,1){.75}}
\put(0,.75){\line(1,0){1.5}}
\put(1.5,0){\line(0,1){.75}}
\put(0,0){\line(1,0){1.5}}
\put(.1,.4){\makebox(1.3,.3){Asterisk PBX}}
\put(.1,.4){\line(1,0){1.3}}
\put(.1,.1){\line(1,0){1.3}}
\put(.1,.1){\line(0,1){.3}}
\put(1.4,.1){\line(0,1){.3}}
\put(.1,.1){\makebox(1.3,.3){RADIUS Client}}
\put(1.8,0){\line(0,1){.5}}
\put(1.8,.5){\line(1,0){1.1}}
\put(1.8,0){\line(1,0){1.1}}
\put(2.9,0){\line(0,1){.5}}
\put(1.8,.275){\makebox(1.1,.1){RADIUS Server}}
\put(1.8,.125){\makebox(1.1,.1){$(FreeRADIUS)$}}
\thicklines
\put(1.4,.3){\vector(1,0){.4}}
\put(1.8,.2){\vector(-1,0){.4}}
\thinlines
\end{picture}
\end{center}
\caption{Asterisk/RADIUS Integration}
\end{figure}
\subsubsection{Installation of the Radiusclient library}
Download the sources from
\url{http://developer.berlios.de/projects/radiusclient-ng/}
Untar the source tarball:
\begin{verbatim}
root@localhost:/usr/local/src# tar xvfz radiusclient-ng-0.5.2.tar.gz
\end{verbatim}
Compile and install the library:
\begin{verbatim}
root@localhost:/usr/local/src# cd radiusclient-ng-0.5.2
root@localhost:/usr/local/src/radiusclient-ng-0.5.2# ./configure
root@localhost:/usr/local/src/radiusclient-ng-0.5.2# make
root@localhost:/usr/local/src/radiusclient-ng-0.5.2# make install
\end{verbatim}
\subsubsection{Configuration of the Radiusclient library}
By default all the configuration files of the radiusclient library will
be in \path{/usr/local/etc/radiusclient-ng} directory.
File "radiusclient.conf"
Open the file and find lines containing the following:
authserver localhost
This is the hostname or IP address of the RADIUS server used for
authentication. You will have to change this unless the server is
running on the same host as your Asterisk PBX.
acctserver localhost
This is the hostname or IP address of the RADIUS server used for
accounting. You will have to change this unless the server is running
on the same host as your Asterisk PBX.
\textbf{File "servers"}
RADIUS protocol uses simple access control mechanism based on shared
secrets that allows RADIUS servers to limit access from RADIUS clients.
A RADIUS server is configured with a secret string and only RADIUS
clients that have the same secret will be accepted.
You need to configure a shared secret for each server you have
configured in radiusclient.conf file in the previous step. The shared
secrets are stored in \path{/usr/local/etc/radiusclient-ng/servers} file.
Each line contains hostname of a RADIUS server and shared secret
used in communication with that server. The two values are separated
by white spaces. Configure shared secrets for every RADIUS server you
are going to use.
\textbf{File "dictionary"}
Asterisk uses some attributes that are not included in the
dictionary of radiusclient library, therefore it is necessary to add
them. A file called dictionary.digium (kept in the contrib dir)
was created to list all new attributes used by Asterisk.
Add to the end of the main dictionary file
\path{/usr/local/etc/radiusclient-ng/dictionary} the line:
\$INCLUDE /path/to/dictionary.digium
\subsubsection{Install FreeRADIUS Server (Version 1.1.1)}
Download sources tarball from:
\url{http://freeradius.org/}
Untar, configure, build, and install the server:
\begin{verbatim}
root@localhost:/usr/local/src# tar xvfz freeradius-1.1.1.tar.gz
root@localhost:/usr/local/src# cd freeradius-1.1.1
root@localhost"/usr/local/src/freeradius-1.1.1# ./configure
root@localhost"/usr/local/src/freeradius-1.1.1# make
root@localhost"/usr/local/src/freeradius-1.1.1# make install
\end{verbatim}
All the configuration files of FreeRADIUS server will be in
/usr/local/etc/raddb directory.
\subsubsection{Configuration of the FreeRADIUS Server}
There are several files that have to be modified to configure the
RADIUS server. These are presented next.
File "clients.conf"
File \path{/usr/local/etc/raddb/clients.conf} contains description of
RADIUS clients that are allowed to use the server. For each of the
clients you need to specify its hostname or IP address and also a
shared secret. The shared secret must be the same string you configured
in radiusclient library.
Example:
\begin{verbatim}
client myhost {
secret = mysecret
shortname = foo
}
\end{verbatim}
This fragment allows access from RADIUS clients on "myhost" if they use
"mysecret" as the shared secret.
The file already contains an entry for localhost (127.0.0.1), so if you
are running the RADIUS server on the same host as your Asterisk server,
then modify the existing entry instead, replacing the default password.
File "dictionary"
Note: as of version 1.1.2, the dictionary.digium file ships with FreeRADIUS.
The following procedure brings the dictionary.digium file to previous versions
of FreeRADIUS.
File \path{/usr/local/etc/raddb/dictionary} contains the dictionary of
FreeRADIUS server. You have to add the same dictionary file
(dictionary.digium), which you added to the dictionary of radiusclient-ng
library. You can include it into the main file, adding the following line at the
end of file \path{/usr/local/etc/raddb/dictionary}:
\$INCLUDE /path/to/dictionary.digium
That will include the same new attribute definitions that are used
in radiusclient-ng library so the client and server will understand each
other.
\subsubsection{Asterisk Accounting Configuration}
Compilation and installation:
The module will be compiled as long as the radiusclient-ng
library has been detected on your system.
By default FreeRADIUS server will log all accounting requests into
\path{/usr/local/var/log/radius/radacct} directory in form of plain text files.
The server will create one file for each hostname in the directory. The
following example shows how the log files look like.
Asterisk now generates Call Detail Records. See \path{/include/asterisk/cdr.h}
for all the fields which are recorded. By default, records in comma
separated values will be created in \path{/var/log/asterisk/cdr-csv}.
The configuration file for cdr_radius.so module is \path{/etc/asterisk/cdr.conf}
This is where you can set CDR related parameters as well as the path to
the radiusclient-ng library configuration file.
\subsubsection{Logged Values}
\begin{verbatim}
"Asterisk-Acc-Code", The account name of detail records
"Asterisk-Src",
"Asterisk-Dst",
"Asterisk-Dst-Ctx", The destination context
"Asterisk-Clid",
"Asterisk-Chan", The channel
"Asterisk-Dst-Chan", (if applicable)
"Asterisk-Last-App", Last application run on the channel
"Asterisk-Last-Data", Argument to the last channel
"Asterisk-Start-Time",
"Asterisk-Answer-Time",
"Asterisk-End-Time",
"Asterisk-Duration", Duration is the whole length that the entire
call lasted. ie. call rx'd to hangup
"end time" minus "start time"
"Asterisk-Bill-Sec", The duration that a call was up after other
end answered which will be <= to duration
"end time" minus "answer time"
"Asterisk-Disposition", ANSWERED, NO ANSWER, BUSY
"Asterisk-AMA-Flags", DOCUMENTATION, BILL, IGNORE etc, specified on
a per channel basis like accountcode.
"Asterisk-Unique-ID", Unique call identifier
"Asterisk-User-Field" User field set via SetCDRUserField
\end{verbatim}

View File

@ -1,958 +0,0 @@
\section{Design Goals}
CEL, or Channel Event Logging, has been written with the hopes that it will help
solve some of the problems that were difficult to address in CDR records. Some
difficulties in CDR generation are the fact that the CDR record stores three
events: the "Start" time, the "Answer" time, and the "End" time. Billing time is
usually the difference between "Answer" and "End", and total call duration was
the difference in time from "Start" to "End". The trouble with this direct and
simple approach is the fact that calls can be transferred, put on hold,
conferenced, forwarded, etc. In general, those doing billing applications in
Asterisk find they have to do all sorts of very creative things to overcome the
shortcomings of CDR records, often supplementing the CDR records with AGI
scripts and manager event filters.
The fundamental assumption is that the Channel is the fundamental communication
object in asterisk, which basically provides a communication channel between two
communication ports. It makes sense to have an event system aimed at recording
important events on channels. Each event is attached to a channel, like ANSWER
or HANGUP. Some events are meant to connect two or more channels, like the
BRIDGE\_START event. Some events, like BLINDTRANSFER, are initiated by one
channel, but affect two others. These events use the Peer field, like BRIDGE
would, to point to the target channel.
The design philosophy of CEL is to generate event data that can grouped together
to form a billing record. This may not be a simple task, but we hope to provide
a few different examples that could be used as a basis for those involved in
this effort.
There are definite parallels between Manager events and CEL events, but there
are some differences. Some events that are generated by CEL are not generated
by the Manager interface (yet). CEL is optimized for databases, and Manager
events are not. The focus of CEL is billing. The Manager interface is targeted
to real-time monitoring and control of asterisk.
To give the reader a feel for the complexities involved in billing, please take
note of the following sequence of events:
Remember that 150, 151, and 152 are all Zap extension numbers, and their
respective devices are Zap/50, Zap/51, and Zap/52.
152 dials 151; 151 answers. 152 parks 151; 152 hangs up. 150 picks up the park
(dials 701). 150 and 151 converse. 151 flashes hook; dials 152, talks to 152,
then 151 flashes hook again for 3-way conference. 151 converses with the other
two for a while, then hangs up. 150 and 152 keep conversing, then hang up. 150
hangs up first.(not that it matters).
This sequence of actions will generate the following annotated list of 42 CEL
events:
{\it Note that the actual CEL events below are in CSV format and do not include
the ;;; and text after that which gives a description of what the event
represents.}
\begin{astlisting}
"EV\_CHAN\_START","2007-05-09 12:46:16","fxs.52","152","","","","s","extension","Zap/52-1","","","DOCUMENTATION","","1178736376.3","","" ;;; 152 takes the phone off-hook
"EV\_APP\_START","2007-05-09 12:46:18","fxs.52","152","152","","","151","extension","Zap/52-1","Dial","Zap/51|30|TtWw","DOCUMENTATION","","1178736376.3" ;;; 152 finishes dialing 151
"EV\_CHAN\_START","2007-05-09 12:46:18","fxs.51","151","","","","s","extension","Zap/51-1","","","DOCUMENTATION","","1178736378.4","","" ;;; 151 channel created, starts ringing
{\it (151 is ringing)}
"EV\_ANSWER","2007-05-09 12:46:19","","151","152","","","151","extension","Zap/51-1","AppDial","(Outgoing Line)","DOCUMENTATION","","1178736378.4","","" ;;; 151 answers
"EV\_ANSWER","2007-05-09 12:46:19","fxs.52","152","152","","","151","extension","Zap/52-1","Dial","Zap/51|30|TtWw","DOCUMENTATION","","1178736376.3","","" ;;; so does 152 (???)
"EV\_BRIDGE\_START","2007-05-09 12:46:20","fxs.52","152","152","","","151","extension","Zap/52-1","Dial","Zap/51|30|TtWw","DOCUMENTATION","","1178736376.3","","Zap/51-1" ;;; 152 and 151 are bridged
{\it (151 and 152 are conversing)}
"EV\_BRIDGE\_END","2007-05-09 12:46:25","fxs.52","152","152","","","151","extension","Zap/52-1","Dial","Zap/51|30|TtWw","DOCUMENTATION","","1178736376.3","","" ;;; after 5 seconds, the bridge ends (152 dials \#700?)
"EV\_BRIDGE\_START","2007-05-09 12:46:25","fxs.52","152","152","","","151","extension","Zap/52-1","Dial","Zap/51|30|TtWw","DOCUMENTATION","","1178736376.3","","Zap/51-1" ;;; extraneous 0-second bridge?
"EV\_BRIDGE\_END","2007-05-09 12:46:25","fxs.52","152","152","","","151","extension","Zap/52-1","Dial","Zap/51|30|TtWw","DOCUMENTATION","","1178736376.3","","" ;;;
"EV\_PARK\_START","2007-05-09 12:46:27","","151","152","","","","extension","Zap/51-1","Parked Call","","DOCUMENTATION","","1178736378.4","","" ;;; 151 is parked
"EV\_HANGUP","2007-05-09 12:46:29","fxs.52","152","152","","","h","extension","Zap/52-1","","","DOCUMENTATION","","1178736376.3" ,"","" ;;; 152 hangs up 2 sec later
"EV\_CHAN\_END","2007-05-09 12:46:29","fxs.52","152","152","","","h","extension","Zap/52-1","","","DOCUMENTATION","","1178736376.3","","" ;;; 152's channel goes away
{\it (151 is parked and listening to MOH! now, 150 picks up, and dials 701)}
"EV\_CHAN\_START","2007-05-09 12:47:08","fxs.50","150","","","","s","extension","Zap/50-1","","","DOCUMENTATION","","1178736428.5","","" ;;; 150 picks up the phone, dials 701
"EV\_PARK\_END","2007-05-09 12:47:11","","151","152","","","","extension","Zap/51-1","Parked Call","","DOCUMENTATION","","1178736378.4","","" ;;; 151's park comes to end
"EV\_ANSWER","2007-05-09 12:47:11","fxs.50","150","150","","","701","extension","Zap/50-1","ParkedCall","701","DOCUMENTATION","","1178736428.5","","" ;;; 150 gets answer (twice)
"EV\_ANSWER","2007-05-09 12:47:12","fxs.50","150","150","","","701","extension","Zap/50-1","ParkedCall","701","DOCUMENTATION","","1178736428.5","","" ;;;
"EV\_BRIDGE\_START","2007-05-09 12:47:12","fxs.50","150","150","","","701","extension","Zap/50-1","ParkedCall","701","DOCUMENTATION","","1178736428.5","","Zap/51-1" ;;; bridge begins between 150 and recently parked 151
{\it (150 and 151 are conversing, then 151 hits flash)}
"EV\_CHAN\_START","2007-05-09 12:47:51","fxs.51","151","","","","s","extension","Zap/51-2","","","DOCUMENTATION","","1178736471.6","","" ;;; 39 seconds later, 51-2 channel is created. (151 flashes hook)
"EV\_HOOKFLASH","2007-05-09 12:47:51","","151","152","","","","extension","Zap/51-1","Bridged Call","Zap/50-1","DOCUMENTATION","","1178736378.4","","Zap/51-2" ;;; a marker to record that 151 flashed the hook
"EV\_BRIDGE\_END","2007-05-09 12:47:51","fxs.50","150","150","","","701","extension","Zap/50-1","ParkedCall","701","DOCUMENTATION","","1178736428.5","","Zap/51-1" ;;; bridge ends between 150 and 151
"EV\_BRIDGE\_START","2007-05-09 12:47:51","fxs.50","150","150","","","701","extension","Zap/50-1","ParkedCall","701","DOCUMENTATION","","1178736428.5","","Zap/51-1" ;;; 0-second bridge from 150 to ? 150 gets no sound at all
"EV\_BRIDGE\_END","2007-05-09 12:47:51","fxs.50","150","150","","","701","extension","Zap/50-1","ParkedCall","701","DOCUMENTATION","","1178736428.5","","Zap/51-1" ;;;
"EV\_BRIDGE\_START","2007-05-09 12:47:51","fxs.50","150","150","","","701","extension","Zap/50-1","ParkedCall","701","DOCUMENTATION","","1178736428.5","","Zap/51-1" ;;; bridge start on 150
{\it (151 has dialtone after hitting flash; dials 152)}
"EV\_APP\_START","2007-05-09 12:47:55","fxs.51","151","151","","","152","extension","Zap/51-2","Dial","Zap/52|30|TtWw","DOCUMENTATION","","1178736471.6","","" ;;; 151-2 dials 152 after 4 seconds
"EV\_CHAN\_START","2007-05-09 12:47:55","fxs.52","152","","","","s","extension","Zap/52-1","","","DOCUMENTATION","","1178736475.7" ,"","" ;;; 152 channel created to ring 152.
{\it (152 ringing)}
"EV\_ANSWER","2007-05-09 12:47:58","","152","151","","","152","extension","Zap/52-1","AppDial","(Outgoing Line)","DOCUMENTATION","","1178736475.7","","" ;;; 3 seconds later, 152 answers
"EV\_ANSWER","2007-05-09 12:47:58","fxs.51","151","151","","","152","extension","Zap/51-2","Dial","Zap/52|30|TtWw","DOCUMENTATION","","1178736471.6","","" ;;; ... and 151-2 also answers
"EV\_BRIDGE\_START","2007-05-09 12:47:59","fxs.51","151","151","","","152","extension","Zap/51-2","Dial","Zap/52|30|TtWw","DOCUMENTATION","","1178736471.6","","Zap/51-1" ;;; 1 second later, bridge formed betw. 151-2 and 151
{\it (152 answers, 151 and 152 convering; 150 is listening to silence; 151 hits flash again... to start a 3way)}
"EV\_3WAY\_START","2007-05-09 12:48:58","","151","152","","","","extension","Zap/51-1","Bridged Call","Zap/50-1","DOCUMENTATION","","1178736378.4","","Zap/51-2" ;;; another hook-flash to begin a 3-way conference
"EV\_BRIDGE\_END","2007-05-09 12:48:58","fxs.50","150","150","","","701","extension","Zap/50-1","ParkedCall","701","DOCUMENTATION","","1178736428.5","","Zap/51-1" ;;; -- almost 1 minute later, the bridge ends (151 flashes hook again)
"EV\_BRIDGE\_START","2007-05-09 12:48:58","fxs.50","150","150","","","701","extension","Zap/50-1","ParkedCall","701","DOCUMENTATION","","1178736428.5","","Zap/51-1" ;;; 0-second bridge at 150. (3 way conf formed)
"EV\_BRIDGE\_END","2007-05-09 12:48:58","fxs.50","150","150","","","701","extension","Zap/50-1","ParkedCall","701","DOCUMENTATION","","1178736428.5","","Zap/51-1" ;;;
"EV\_BRIDGE\_START","2007-05-09 12:48:58","fxs.50","150","150","","","701","extension","Zap/50-1","ParkedCall","701","DOCUMENTATION","","1178736428.5","","Zap/51-1" ;;; bridge starts for 150
{\it (3way now, then 151 hangs up.)}
"EV\_BRIDGE\_END","2007-05-09 12:49:26","fxs.50","150","150","","","701","extension","Zap/50-1","ParkedCall","701","DOCUMENTATION","","1178736428.5","","Zap/51-1" ;;; 28 seconds later, bridge ends
"EV\_HANGUP","2007-05-09 12:49:26","","151","152","","","","extension","Zap/51-1","Bridged Call","Zap/50-1","DOCUMENTATION","","1178736378.4","","" ;;; 151 hangs up, leaves 150 and 152 connected
"EV\_CHAN\_END","2007-05-09 12:49:26","","151","152","","","","extension","Zap/51-1","Bridged Call","Zap/50-1","DOCUMENTATION","","1178736378.4","","" ;;; 151 channel ends
"EV\_CHAN\_END","2007-05-09 12:49:26","fxs.51","151","151","","","h","extension","Zap/51-2$<$ZOMBIE$>$","","","DOCUMENTATION","","1178736428.5","","" ;;; 152-2 channel ends (zombie)
{\it (just 150 and 152 now)}
"EV\_BRIDGE\_END","2007-05-09 12:50:13","fxs.50","150","150","","","152","extension","Zap/50-1","Dial","Zap/52|30|TtWw","DOCUMENTATION","","1178736471.6","","" ;;; 47 sec later, the bridge from 150 to 152 ends
"EV\_HANGUP","2007-05-09 12:50:13","","152","151","","","","extension","Zap/52-1","Bridged Call","Zap/50-1","DOCUMENTATION","","1178736475.7","","" ;;; 152 hangs up
"EV\_CHAN\_END","2007-05-09 12:50:13","","152","151","","","","extension","Zap/52-1","Bridged Call","Zap/50-1","DOCUMENTATION","","1178736475.7","","" ;;; 152 channel ends
"EV\_HANGUP","2007-05-09 12:50:13","fxs.50","150","150","","","h","extension","Zap/50-1","","","DOCUMENTATION","","1178736471.6","","" ;;; 150 hangs up
"EV\_CHAN\_END","2007-05-09 12:50:13","fxs.50","150","150","","","h","extension","Zap/50-1","","","DOCUMENTATION","","1178736471.6","","" ;;; 150 ends
\end{astlisting}
In terms of Manager events, the above Events correspond to the following 80
Manager events:
\begin{astlisting}
\begin{verbatim}
Event: Newchannel
Privilege: call,all
Channel: Zap/52-1
State: Rsrvd
CallerIDNum: 152
CallerIDName: fxs.52
Uniqueid: 1178801102.5
Event: Newcallerid
Privilege: call,all
Channel: Zap/52-1
CallerIDNum: 152
CallerIDName: fxs.52
Uniqueid: 1178801102.5
CID-CallingPres: 0 (Presentation Allowed, Not Screened)
Event: Newcallerid
Privilege: call,all
Channel: Zap/52-1
CallerIDNum: 152
CallerIDName: fxs.52
Uniqueid: 1178801102.5
CID-CallingPres: 0 (Presentation Allowed, Not Screened)
Event: Newstate
Privilege: call,all
Channel: Zap/52-1
State: Ring
CallerIDNum: 152
CallerIDName: fxs.52
Uniqueid: 1178801102.5
Event: Newexten
Privilege: call,all
Channel: Zap/52-1
Context: extension
Extension: 151
Priority: 1
Application: Set
AppData: CDR(myvar)=zingo
Uniqueid: 1178801102.5
Event: Newexten
Privilege: call,all
Channel: Zap/52-1
Context: extension
Extension: 151
Priority: 2
Application: Dial
AppData: Zap/51|30|TtWw
Uniqueid: 1178801102.5
Event: Newchannel
Privilege: call,all
Channel: Zap/51-1
State: Rsrvd
CallerIDNum: 151
CallerIDName: fxs.51
Uniqueid: 1178801108.6
Event: Newstate
Privilege: call,all
Channel: Zap/51-1
State: Ringing
CallerIDNum: 152
CallerIDName: fxs.52
Uniqueid: 1178801108.6
Event: Dial
Privilege: call,all
SubEvent: Begin
Source: Zap/52-1
Destination: Zap/51-1
CallerIDNum: 152
CallerIDName: fxs.52
SrcUniqueID: 1178801102.5
DestUniqueID: 1178801108.6
Event: Newcallerid
Privilege: call,all
Channel: Zap/51-1
CallerIDNum: 151
CallerIDName: <Unknown>
Uniqueid: 1178801108.6
CID-CallingPres: 0 (Presentation Allowed, Not Screened)
Event: Newstate
Privilege: call,all
Channel: Zap/52-1
State: Ringing
CallerIDNum: 152
CallerIDName: fxs.52
Uniqueid: 1178801102.5
Event: Newstate
Privilege: call,all
Channel: Zap/51-1
State: Up
CallerIDNum: 151
CallerIDName: <unknown>
Uniqueid: 1178801108.6
Event: Newstate
Privilege: call,all
Channel: Zap/52-1
State: Up
CallerIDNum: 152
CallerIDName: fxs.52
Uniqueid: 1178801102.5
Event: Link
Privilege: call,all
Channel1: Zap/52-1
Channel2: Zap/51-1
Uniqueid1: 1178801102.5
Uniqueid2: 1178801108.6
CallerID1: 152
CallerID2: 151
Event: Unlink
Privilege: call,all
Channel1: Zap/52-1
Channel2: Zap/51-1
Uniqueid1: 1178801102.5
Uniqueid2: 1178801108.6
CallerID1: 152
CallerID2: 151
Event: Link
Privilege: call,all
Channel1: Zap/52-1
Channel2: Zap/51-1
Uniqueid1: 1178801102.5
Uniqueid2: 1178801108.6
CallerID1: 152
CallerID2: 151
Event: Unlink
Privilege: call,all
Channel1: Zap/52-1
Channel2: Zap/51-1
Uniqueid1: 1178801102.5
Uniqueid2: 1178801108.6
CallerID1: 152
CallerID2: 151
Event: ParkedCall
Privilege: call,all
Exten: 701
Channel: Zap/51-1
From: Zap/52-1
Timeout: 45
CallerIDNum: 151
CallerIDName: <unknown>
Event: Dial
Privilege: call,all
SubEvent: End
Channel: Zap/52-1
DialStatus: ANSWER
Event: Newexten
Privilege: call,all
Channel: Zap/52-1
Context: extension
Extension: h
Priority: 1
Application: Goto
AppData: label1
Uniqueid: 1178801102.5
Event: Newexten
Privilege: call,all
Channel: Zap/52-1
Context: extension
Extension: h
Priority: 4
Application: Goto
AppData: label2
Uniqueid: 1178801102.5
Event: Newexten
Privilege: call,all
Channel: Zap/52-1
Context: extension
Extension: h
Priority: 2
Application: NoOp
AppData: In Hangup! myvar is zingo and accountcode is billsec is 26 and duration is 40 and end is 2007-05-10 06:45:42.
Uniqueid: 1178801102.5
Event: Newexten
Privilege: call,all
Channel: Zap/52-1
Context: extension
Extension: h
Priority: 3
Application: Goto
AppData: label3
Uniqueid: 1178801102.5
Event: Newexten
Privilege: call,all
Channel: Zap/52-1
Context: extension
Extension: h
Priority: 5
Application: NoOp
AppData: More Hangup message after hopping around"
Uniqueid: 1178801102.5
Event: Hangup
Privilege: call,all
Channel: Zap/52-1
Uniqueid: 1178801102.5
Cause: 16
Cause-txt: Normal Clearing
Event: Newchannel
Privilege: call,all
Channel: Zap/50-1
State: Rsrvd
CallerIDNum: 150
CallerIDName: fxs.50
Uniqueid: 1178801162.7
Event: Newcallerid
Privilege: call,all
Channel: Zap/50-1
CallerIDNum: 150
CallerIDName: fxs.50
Uniqueid: 1178801162.7
CID-CallingPres: 0 (Presentation Allowed, Not Screened)
Event: Newcallerid
Privilege: call,all
Channel: Zap/50-1
CallerIDNum: 150
CallerIDName: fxs.50
Uniqueid: 1178801162.7
CID-CallingPres: 0 (Presentation Allowed, Not Screened)
Event: Newstate
Privilege: call,all
Channel: Zap/50-1
State: Ring
CallerIDNum: 150
CallerIDName: fxs.50
Uniqueid: 1178801162.7
Event: Newexten
Privilege: call,all
Channel: Zap/50-1
Context: extension
Extension: 701
Priority: 1
Application: ParkedCall
AppData: 701
Uniqueid: 1178801162.7
Event: UnParkedCall
Privilege: call,all
Exten: 701
Channel: Zap/51-1
From: Zap/50-1
CallerIDNum: 151
CallerIDName: <unknown>
Event: Newstate
Privilege: call,all
Channel: Zap/50-1
State: Up
CallerIDNum: 150
CallerIDName: fxs.50
Uniqueid: 1178801162.7
Event: Link
Privilege: call,all
Channel1: Zap/50-1
Channel2: Zap/51-1
Uniqueid1: 1178801162.7
Uniqueid2: 1178801108.6
CallerID1: 150
CallerID2: 151
Event: Newchannel
Privilege: call,all
Channel: Zap/51-2
State: Rsrvd
CallerIDNum: 151
CallerIDName: fxs.51
Uniqueid: 1178801218.8
Event: Unlink
Privilege: call,all
Channel1: Zap/50-1
Channel2: Zap/51-1
Uniqueid1: 1178801162.7
Uniqueid2: 1178801108.6
CallerID1: 150
CallerID2: 151
Event: Link
Privilege: call,all
Channel1: Zap/50-1
Channel2: Zap/51-1
Uniqueid1: 1178801162.7
Uniqueid2: 1178801108.6
CallerID1: 150
CallerID2: 151
Event: Unlink
Privilege: call,all
Channel1: Zap/50-1
Channel2: Zap/51-1
Uniqueid1: 1178801162.7
Uniqueid2: 1178801108.6
CallerID1: 150
CallerID2: 151
Event: Link
Privilege: call,all
Channel1: Zap/50-1
Channel2: Zap/51-1
Uniqueid1: 1178801162.7
Uniqueid2: 1178801108.6
CallerID1: 150
CallerID2: 151
Event: Newcallerid
Privilege: call,all
Channel: Zap/51-2
CallerIDNum: 151
CallerIDName: fxs.51
Uniqueid: 1178801218.8
CID-CallingPres: 0 (Presentation Allowed, Not Screened)
Event: Newcallerid
Privilege: call,all
Channel: Zap/51-2
CallerIDNum: 151
CallerIDName: fxs.51
Uniqueid: 1178801218.8
CID-CallingPres: 0 (Presentation Allowed, Not Screened)
Event: Newstate
Privilege: call,all
Channel: Zap/51-2
State: Ring
CallerIDNum: 151
CallerIDName: fxs.51
Uniqueid: 1178801218.8
Event: Newexten
Privilege: call,all
Channel: Zap/51-2
Context: extension
Extension: 152
Priority: 1
Application: Set
AppData: CDR(myvar)=zingo
Uniqueid: 1178801218.8
Event: Newexten
Privilege: call,all
Channel: Zap/51-2
Context: extension
Extension: 152
Priority: 2
Application: Dial
AppData: Zap/52|30|TtWw
Uniqueid: 1178801218.8
Event: Newchannel
Privilege: call,all
Channel: Zap/52-1
State: Rsrvd
CallerIDNum: 152
CallerIDName: fxs.52
Uniqueid: 1178801223.9
Event: Newstate
Privilege: call,all
Channel: Zap/52-1
State: Ringing
CallerIDNum: 151
CallerIDName: fxs.51
Uniqueid: 1178801223.9
Event: Dial
Privilege: call,all
SubEvent: Begin
Source: Zap/51-2
Destination: Zap/52-1
CallerIDNum: 151
CallerIDName: fxs.51
SrcUniqueID: 1178801218.8
DestUniqueID: 1178801223.9
Event: Newcallerid
Privilege: call,all
Channel: Zap/52-1
CallerIDNum: 152
CallerIDName: <Unknown>
Uniqueid: 1178801223.9
CID-CallingPres: 0 (Presentation Allowed, Not Screened)
Event: Newstate
Privilege: call,all
Channel: Zap/51-2
State: Ringing
CallerIDNum: 151
CallerIDName: fxs.51
Uniqueid: 1178801218.8
Event: Newstate
Privilege: call,all
Channel: Zap/52-1
State: Up
CallerIDNum: 152
CallerIDName: <unknown>
Uniqueid: 1178801223.9
Event: Newstate
Privilege: call,all
Channel: Zap/51-2
State: Up
CallerIDNum: 151
CallerIDName: fxs.51
Uniqueid: 1178801218.8
Event: Link
Privilege: call,all
Channel1: Zap/51-2
Channel2: Zap/52-1
Uniqueid1: 1178801218.8
Uniqueid2: 1178801223.9
CallerID1: 151
CallerID2: 152
Event: Unlink
Privilege: call,all
Channel1: Zap/50-1
Channel2: Zap/51-1
Uniqueid1: 1178801162.7
Uniqueid2: 1178801108.6
CallerID1: 150
CallerID2: 151
Event: Link
Privilege: call,all
Channel1: Zap/50-1
Channel2: Zap/51-1
Uniqueid1: 1178801162.7
Uniqueid2: 1178801108.6
CallerID1: 150
CallerID2: 151
Event: Unlink
Privilege: call,all
Channel1: Zap/50-1
Channel2: Zap/51-1
Uniqueid1: 1178801162.7
Uniqueid2: 1178801108.6
CallerID1: 150
CallerID2: 151
Event: Link
Privilege: call,all
Channel1: Zap/50-1
Channel2: Zap/51-1
Uniqueid1: 1178801162.7
Uniqueid2: 1178801108.6
CallerID1: 150
CallerID2: 151
Event: Unlink
Privilege: call,all
Channel1: Zap/50-1
Channel2: Zap/51-1
Uniqueid1: 1178801162.7
Uniqueid2: 1178801108.6
CallerID1: 150
CallerID2: 151
Event: Hangup
Privilege: call,all
Channel: Zap/51-1
Uniqueid: 1178801108.6
Cause: 16
Cause-txt: Normal Clearing
Event: Newexten
Privilege: call,all
Channel: Zap/50-1
Context: extension
Extension: h
Priority: 1
Application: Goto
AppData: label1
Uniqueid: 1178801162.7
Event: Newexten
Privilege: call,all
Channel: Zap/50-1
Context: extension
Extension: h
Priority: 4
Application: Goto
AppData: label2
Uniqueid: 1178801162.7
Event: Newexten
Privilege: call,all
Channel: Zap/50-1
Context: extension
Extension: h
Priority: 2
Application: NoOp
AppData: In Hangup! myvar is and accountcode is billsec is 0 and duration is 0 and end is 2007-05-10 06:48:37.
Uniqueid: 1178801162.7
Event: Newexten
Privilege: call,all
Channel: Zap/50-1
Context: extension
Extension: h
Priority: 3
Application: Goto
AppData: label3
Uniqueid: 1178801162.7
Event: Newexten
Privilege: call,all
Channel: Zap/50-1
Context: extension
Extension: h
Priority: 5
Application: NoOp
AppData: More Hangup message after hopping around"
Uniqueid: 1178801162.7
Event: Masquerade
Privilege: call,all
Clone: Zap/50-1
CloneState: Up
Original: Zap/51-2
OriginalState: Up
Event: Rename
Privilege: call,all
Oldname: Zap/50-1
Newname: Zap/50-1<MASQ>
Uniqueid: 1178801162.7
Event: Rename
Privilege: call,all
Oldname: Zap/51-2
Newname: Zap/50-1
Uniqueid: 1178801218.8
Event: Rename
Privilege: call,all
Oldname: Zap/50-1<MASQ>
Newname: Zap/51-2<ZOMBIE>
Uniqueid: 1178801162.7
Event: Hangup
Privilege: call,all
Channel: Zap/51-2<ZOMBIE>
Uniqueid: 1178801162.7
Cause: 0
Cause-txt: Unknown
Event: Unlink
Privilege: call,all
Channel1: Zap/50-1
Channel2: Zap/52-1
Uniqueid1: 1178801218.8
Uniqueid2: 1178801223.9
CallerID1: 150
CallerID2: 152
Event: Hangup
Privilege: call,all
Channel: Zap/52-1
Uniqueid: 1178801223.9
Cause: 16
Cause-txt: Normal Clearing
Event: Dial
Privilege: call,all
SubEvent: End
Channel: Zap/50-1
DialStatus: ANSWER
Event: Newexten
Privilege: call,all
Channel: Zap/50-1
Context: extension
Extension: h
Priority: 1
Application: Goto
AppData: label1
Uniqueid: 1178801218.8
Event: Newexten
Privilege: call,all
Channel: Zap/50-1
Context: extension
Extension: h
Priority: 4
Application: Goto
AppData: label2
Uniqueid: 1178801218.8
Event: Newexten
Privilege: call,all
Channel: Zap/50-1
Context: extension
Extension: h
Priority: 2
Application: NoOp
AppData: In Hangup! myvar is and accountcode is billsec is 90 and duration is 94 and end is 2007-05-10 06:48:37.
Uniqueid: 1178801218.8
Event: Newexten
Privilege: call,all
Channel: Zap/50-1
Context: extension
Extension: h
Priority: 3
Application: Goto
AppData: label3
Uniqueid: 1178801218.8
Event: Newexten
Privilege: call,all
Channel: Zap/50-1
Context: extension
Extension: h
Priority: 5
Application: NoOp
AppData: More Hangup message after hopping around"
Uniqueid: 1178801218.8
Event: Hangup
Privilege: call,all
Channel: Zap/50-1
Uniqueid: 1178801218.8
Cause: 16
Cause-txt: Normal Clearing
\end{verbatim}
\end{astlisting}
And, humorously enough, the above 80 manager events, or 42 CEL events,
correspond to the following two CDR records (at the moment!):
\begin{astlisting}
""fxs.52" $<$152$>$","152","h","extension","Zap/52-1","Zap/51-1","NoOp","More Hangup message after hopping around"","2007-05-09 17:35:56","2007-05-09 17:36:20","2007-05-09 17:36:36","40","16","ANSWERED","DOCUMENTATION","","1178753756.0",""
""fxs.50" $<$150$>$","150","152","extension","Zap/50-1","Zap/51-1","NoOp","More Hangup message after hopping around"","2007-05-09 17:37:59","2007-05-09 17:38:06","2007-05-09 17:39:11","72","65","ANSWERED","DOCUMENTATION","","1178753871.3",""
\end{astlisting}
\section{Events \& Fields}
While CDRs and the Manager are basically both event tracking mechanisms, CEL
tries to track only those events that might pertain to billing issues.
See table~\ref{event-table} for a list of events raised by CEL and
table~\ref{field-table} for the list of fields passed for each CEL event.
\begin{table}[h]
\begin{tabular}{ | l | p{10cm} | }
\hline
Event & Description \\ \hline \hline
CHAN\_START & The time a channel was created \\ \hline
CHAN\_END & The time a channel was terminated \\ \hline
ANSWER & The time a channel was answered (ie, phone taken off-hook, etc) \\ \hline
HANGUP & The time at which a hangup occurred. \\ \hline
CONF\_ENTER & The time a channel was connected into a conference room \\ \hline
CONF\_EXIT & The time a channel was removed from a conference room \\ \hline
CONF\_START & The time the first person enters a conference \\ \hline
CONF\_END & The time the last person left a conf (and turned out the lights?) \\ \hline
APP\_START & The time a tracked application was started \\ \hline
APP\_END & the time a tracked application ended \\ \hline
PARK\_START & The time a call was parked \\ \hline
PARK\_END & unpark event \\ \hline
BRIDGE\_START & The time a bridge is started \\ \hline
BRIDGE\_END & The time a bridge is ended \\ \hline
3WAY\_START & When a 3-way conf starts (usually via attended xfer) \\ \hline
3WAY\_END & When one or all exit a 3-way conf \\ \hline
BLINDTRANSFER & When a blind transfer is initiated \\ \hline
ATTENDEDTRANSFER & When an attended transfer is initiated \\ \hline
TRANSFER & Generic transfer initiated; not used yet...? \\ \hline
HOOKFLASH & So far, when a hookflash event occurs on a Zap interface \\ \hline
USER\_EVENT & these are triggered from the dialplan, and have a name given by the user. \\
\hline
\end{tabular}
\caption{List of CEL Events}
\label{event-table}
\end{table}
\begin{table}[h]
\begin{tabular}{ | l | p{10cm} | }
\hline
Field & Description \\ \hline \hline
eventtype & The name of the event; see the above list; each is prefixed with "EV\_". \\ \hline
eventtime & The time the event happened \\ \hline
cidname & CID name field \\ \hline
cidnum & CID number field \\ \hline
cidani & CID ANI field \\ \hline
cidrdnis & CID RDNIS field \\ \hline
ciddnid & CID DNID field \\ \hline
exten & The extension in the dialplan \\ \hline
context & The context in the dialplan \\ \hline
channame & The name assigned to the channel in which the event took place \\ \hline
appname & The name of the current application \\ \hline
appdata & The arguments that will be handed to that application \\ \hline
amaflags & The AMA flags associated with the event; user assignable. \\ \hline
accountcode & A user assigned datum (string) \\ \hline
uniqueid & Each Channel instance gets a unique ID associated with it. \\ \hline
userfield & A user assigned datum (string) \\ \hline
linkedid & the per-call id, spans several events, possibly. \\ \hline
peer & For bridge or other 2-channel events, this would be the other channel name \\
\hline
\end{tabular}
\caption{List of CEL Event Fields}
\label{field-table}
\end{table}
\section{Applications \& Functions}
\subsection{CEL Function}
**** THIS IS NO LONGER TRUE. REWRITE. ****
The CEL function parallels the CDR function, for fetching values from the
channel or event. It has some notable notable differences, though! For
instance, CEL data is not stored on the channel. Well, not much of it, anyway!
You can use the CEL function to set the amaflags, accountcode, and userfield,
which are stored on the channel.
Channel variables are not available for reading from the CEL function, nor can
any variable name other than what's in the list, be set. CDRs have a structure
attached to the channel, where the CDR function could access the values stored
there, or set the values there. CDRs could store their own variable lists, but
CEL has no such storage. There is no reason to store any event information, as
they are immediately output to the various backends at the time they are
generated.
See the description for the CEL function from the CLI: core show function CEL
Here is a list of all the available channel field names:
\begin{verbatim}
cidname userfield
cidnum amaflags
cidani cidrdnis
ciddnid appdata
exten accountcode
context uniqueid
channame appname
peer eventtime
eventtype
\end{verbatim}
\subsection{CELGenUserEvent Application}
This application allows the dialplan to insert custom events into the event
stream.
For more information, in the CLI, type: core show application CELGenUserEvent
Its arguments take this format:
\begin{verbatim}
CELGenUserEvent(eventname)
\end{verbatim}
Please note that there is no restrictions on the name supplied. If it happens to
match a standard CEL event name, it will look like that event was
generated. This could be a blessing or a curse!
\section{Configuration Files}
\begin{itemize}
\item cel.conf
\end{itemize}
\section{Generating Billing Information}
*** This is the Next Big Task ***

View File

@ -1,451 +0,0 @@
\section{Storage Backends}
Right now, the CEL package will support CSV, Customized CSV, ODBC, PGSQL, TDS,
Sqlite3, and Radius back ends. See the doc/celdriver.tex file
for how to use these back ends.
\subsection{Microsoft SQL Server}
Asterisk can currently store Channel Events into an MSSQL database in
two different ways: cel_odbc or cel_tds
Channel Event Records can be stored using unixODBC (which requires
the FreeTDS package) [cel_odbc] or directly by using just the
FreeTDS package [cel_tds] The following provide some
examples known to get asterisk working with mssql.
NOTE: Only choose one db connector.
\subsubsection{ODBC using cel_odbc}
Compile, configure, and install the latest unixODBC package:
\begin{verbatim}
tar -zxvf unixODBC-2.2.9.tar.gz &&
cd unixODBC-2.2.9 &&
./configure --sysconfdir=/etc --prefix=/usr --disable-gui &&
make &&
make install
\end{verbatim}
Compile, configure, and install the latest FreeTDS package:
\begin{verbatim}
tar -zxvf freetds-0.62.4.tar.gz &&
cd freetds-0.62.4 &&
./configure --prefix=/usr --with-tdsver=7.0 \
--with-unixodbc=/usr/lib &&
make && make install
\end{verbatim}
Compile, or recompile, asterisk so that it will now add support
for cel_odbc.
\begin{verbatim}
make clean && ./configure --with-odbc &&
make update &&
make &&
make install
\end{verbatim}
Setup odbc configuration files. These are working examples
from my system. You will need to modify for your setup.
You are not required to store usernames or passwords here.
\begin{verbatim}
/etc/odbcinst.ini
[FreeTDS]
Description = FreeTDS ODBC driver for MSSQL
Driver = /usr/lib/libtdsodbc.so
Setup = /usr/lib/libtdsS.so
FileUsage = 1
/etc/odbc.ini
[MSSQL-asterisk]
description = Asterisk ODBC for MSSQL
driver = FreeTDS
server = 192.168.1.25
port = 1433
database = voipdb
tds_version = 7.0
language = us_english
\end{verbatim}
Only install one database connector. Do not confuse asterisk
by using both ODBC (cel_odbc) and FreeTDS (cel_tds).
This command will erase the contents of cel_tds.conf
\begin{verbatim}
[ -f /etc/asterisk/cel_tds.conf ] > /etc/asterisk/cel_tds.conf
\end{verbatim}
NOTE: unixODBC requires the freeTDS package, but asterisk does
not call freeTDS directly.
Now set up cel_odbc configuration files. These are working samples
from my system. You will need to modify for your setup. Define
your usernames and passwords here, secure file as well.
\begin{verbatim}
/etc/asterisk/cel_odbc.conf
[global]
dsn=MSSQL-asterisk
username=voipdbuser
password=voipdbpass
loguniqueid=yes
\end{verbatim}
And finally, create the 'cel' table in your mssql database.
\begin{verbatim}
CREATE TABLE cel (
[eventtype] [varchar] (30) NOT NULL ,
[eventtime] [datetime] NOT NULL ,
[cidname] [varchar] (80) NOT NULL ,
[cidnum] [varchar] (80) NOT NULL ,
[cidani] [varchar] (80) NOT NULL ,
[cidrdnis] [varchar] (80) NOT NULL ,
[ciddnid] [varchar] (80) NOT NULL ,
[exten] [varchar] (80) NOT NULL ,
[context] [varchar] (80) NOT NULL ,
[channame] [varchar] (80) NOT NULL ,
[appname] [varchar] (80) NOT NULL ,
[appdata] [varchar] (80) NOT NULL ,
[amaflags] [int] NOT NULL ,
[accountcode] [varchar] (20) NOT NULL ,
[uniqueid] [varchar] (32) NOT NULL ,
[peer] [varchar] (80) NOT NULL ,
[userfield] [varchar] (255) NOT NULL
)
\end{verbatim}
Start asterisk in verbose mode, you should see that asterisk
logs a connection to the database and will now record every
desired channel event at the moment it occurs.
\subsubsection{FreeTDS, using cel_tds}
Compile, configure, and install the latest FreeTDS package:
\begin{verbatim}
tar -zxvf freetds-0.62.4.tar.gz &&
cd freetds-0.62.4 &&
./configure --prefix=/usr --with-tdsver=7.0
make &&
make install
\end{verbatim}
Compile, or recompile, asterisk so that it will now add support
for cel_tds.
\begin{verbatim}
make clean && ./configure --with-tds &&
make update &&
make &&
make install
\end{verbatim}
Only install one database connector. Do not confuse asterisk
by using both ODBC (cel_odbc) and FreeTDS (cel_tds).
This command will erase the contents of cel_odbc.conf
\begin{verbatim}
[ -f /etc/asterisk/cel_odbc.conf ] > /etc/asterisk/cel_odbc.conf
\end{verbatim}
Setup cel_tds configuration files. These are working samples
from my system. You will need to modify for your setup. Define
your usernames and passwords here, secure file as well.
\begin{verbatim}
/etc/asterisk/cel_tds.conf
[global]
hostname=192.168.1.25
port=1433
dbname=voipdb
user=voipdbuser
password=voipdpass
charset=BIG5
\end{verbatim}
And finally, create the 'cel' table in your mssql database.
\begin{verbatim}
CREATE TABLE cel (
[eventtype] [varchar] (30) NULL ,
[eventtime] [datetime] NULL ,
[cidname] [varchar] (80) NULL ,
[cidnum] [varchar] (80) NULL ,
[cidani] [varchar] (80) NULL ,
[cidrdnis] [varchar] (80) NULL ,
[ciddnid] [varchar] (80) NULL ,
[exten] [varchar] (80) NULL ,
[context] [varchar] (80) NULL ,
[channame] [varchar] (80) NULL ,
[appname] [varchar] (80) NULL ,
[appdata] [varchar] (80) NULL ,
[amaflags] [varchar] (16) NULL ,
[accountcode] [varchar] (20) NULL ,
[uniqueid] [varchar] (32) NULL ,
[userfield] [varchar] (255) NULL ,
[peer] [varchar] (80) NULL
)
\end{verbatim}
Start asterisk in verbose mode, you should see that asterisk
logs a connection to the database and will now record every
call to the database when it's complete.
\subsection{MySQL}
Using MySQL for Channel Event records is supported by using ODBC and the cel_odbc module.
\subsection{PostreSQL}
If you want to go directly to postgresql database, and have the cel_pgsql.so
compiled you can use the following sample setup.
On Debian, before compiling asterisk, just install libpqxx-dev.
Other distros will likely have a similiar package.
Once you have the compile done,
copy the sample cel_pgsql.conf file or create your own.
Here is a sample:
\begin{verbatim}
/etc/asterisk/cel_pgsql.conf
; Sample Asterisk config file for CEL logging to PostgresSQL
[global]
hostname=localhost
port=5432
dbname=asterisk
password=password
user=postgres
table=cel
\end{verbatim}
Now create a table in postgresql for your cels
\begin{verbatim}
CREATE TABLE cel (
id serial ,
eventtype varchar (30) NOT NULL ,
eventtime timestamp NOT NULL ,
userdeftype varchar(255) NOT NULL ,
cid_name varchar (80) NOT NULL ,
cid_num varchar (80) NOT NULL ,
cid_ani varchar (80) NOT NULL ,
cid_rdnis varchar (80) NOT NULL ,
cid_dnid varchar (80) NOT NULL ,
exten varchar (80) NOT NULL ,
context varchar (80) NOT NULL ,
channame varchar (80) NOT NULL ,
appname varchar (80) NOT NULL ,
appdata varchar (80) NOT NULL ,
amaflags int NOT NULL ,
accountcode varchar (20) NOT NULL ,
peeraccount varchar (20) NOT NULL ,
uniqueid varchar (150) NOT NULL ,
linkedid varchar (150) NOT NULL ,
userfield varchar (255) NOT NULL ,
peer varchar (80) NOT NULL
);
\end{verbatim}
\subsection{SQLite 3}
SQLite version 3 is supported in cel_sqlite3_custom.
\subsection{RADIUS}
\subsubsection{What is needed}
\begin{itemize}
\item FreeRADIUS server
\item Radiusclient-ng library
\item Asterisk PBX
\end{itemize}
\begin{figure}[h]
\begin{center}
\setlength{\unitlength}{4cm}
\begin{picture}(3,.75)
\put(0,0){\line(0,1){.75}}
\put(0,.75){\line(1,0){1.5}}
\put(1.5,0){\line(0,1){.75}}
\put(0,0){\line(1,0){1.5}}
\put(.1,.4){\makebox(1.3,.3){Asterisk PBX}}
\put(.1,.4){\line(1,0){1.3}}
\put(.1,.1){\line(1,0){1.3}}
\put(.1,.1){\line(0,1){.3}}
\put(1.4,.1){\line(0,1){.3}}
\put(.1,.1){\makebox(1.3,.3){RADIUS Client}}
\put(1.8,0){\line(0,1){.5}}
\put(1.8,.5){\line(1,0){1.1}}
\put(1.8,0){\line(1,0){1.1}}
\put(2.9,0){\line(0,1){.5}}
\put(1.8,.275){\makebox(1.1,.1){RADIUS Server}}
\put(1.8,.125){\makebox(1.1,.1){$(FreeRADIUS)$}}
\thicklines
\put(1.4,.3){\vector(1,0){.4}}
\put(1.8,.2){\vector(-1,0){.4}}
\thinlines
\end{picture}
\end{center}
\caption{Asterisk/RADIUS Integration}
\end{figure}
\subsubsection{Installation of the Radiusclient library}
Installation:
\begin{verbatim}
Download the sources from:
http://developer.berlios.de/projects/radiusclient-ng/
Untar the source tarball.
root@localhost:/usr/local/src# tar xvfz radiusclient-ng-0.5.5.1.tar.gz
Compile and install the library.
root@localhost:/usr/local/src# cd radiusclient-ng-0.5.5.1
root@localhost:/usr/local/src/radiusclient-ng-0.5.5.1# ./configure
root@localhost:/usr/local/src/radiusclient-ng-0.5.5.1# make
root@localhost:/usr/local/src/radiusclient-ng-0.5.5.1# make install
\end{verbatim}
\subsubsection{Configuration of the Radiusclient library}
By default all the configuration files of the radiusclient library will
be in /usr/local/etc/radiusclient-ng directory.
File "radiusclient.conf"
Open the file and find lines containing the following:
authserver localhost
This is the hostname or IP address of the RADIUS server used for
authentication. You will have to change this unless the server is
running on the same host as your Asterisk PBX.
acctserver localhost
This is the hostname or IP address of the RADIUS server used for
accounting. You will have to change this unless the server is running
on the same host as your Asterisk PBX.
File "servers"
RADIUS protocol uses simple access control mechanism based on shared
secrets that allows RADIUS servers to limit access from RADIUS clients.
A RADIUS server is configured with a secret string and only RADIUS
clients that have the same secret will be accepted.
You need to configure a shared secret for each server you have
configured in radiusclient.conf file in the previous step. The shared
secrets are stored in /usr/local/etc/radiusclient-ng/servers file.
Each line contains hostname of a RADIUS server and shared secret
used in communication with that server. The two values are separated
by white spaces. Configure shared secrets for every RADIUS server you
are going to use.
File "dictionary"
Asterisk uses some attributes that are not included in the
dictionary of radiusclient library, therefore it is necessary to add
them. A file called dictionary.digium (kept in the contrib dir)
was created to list all new attributes used by Asterisk.
Add to the end of the main dictionary file
/usr/local/etc/radiusclient-ng/dictionary
the line:
\begin{verbatim}
\$INCLUDE /path/to/dictionary.digium
\end{verbatim}
\subsubsection{Install FreeRADIUS Server (Version 1.1.1)}
Download sources tarball from:
http://freeradius.org/
Untar, configure, build, and install the server:
\begin{verbatim}
root@localhost:/usr/local/src# tar xvfz freeradius-1.1.1.tar.gz
root@localhost:/usr/local/src# cd freeradius-1.1.1
root@localhost"/usr/local/src/freeradius-1.1.1# ./configure
root@localhost"/usr/local/src/freeradius-1.1.1# make
root@localhost"/usr/local/src/freeradius-1.1.1# make install
\end{verbatim}
All the configuration files of FreeRADIUS server will be in
/usr/local/etc/raddb directory.
\subsubsection{Configuration of the FreeRADIUS Server}
There are several files that have to be modified to configure the
RADIUS server. These are presented next.
File "clients.conf"
File /usr/local/etc/raddb/clients.conf contains description of
RADIUS clients that are allowed to use the server. For each of the
clients you need to specify its hostname or IP address and also a
shared secret. The shared secret must be the same string you configured
in radiusclient library.
Example:
\begin{verbatim}
client myhost {
secret = mysecret
shortname = foo
}
\end{verbatim}
This fragment allows access from RADIUS clients on "myhost" if they use
"mysecret" as the shared secret.
The file already contains an entry for localhost (127.0.0.1), so if you
are running the RADIUS server on the same host as your Asterisk server,
then modify the existing entry instead, replacing the default password.
File "dictionary"
Note : as of version 1.1.2, the dictionary.digium file ships with FreeRADIUS.
The following procedure brings the dictionary.digium file to previous versions
of FreeRADIUS.
File /usr/local/etc/raddb/dictionary contains the dictionary of
FreeRADIUS server. You have to add the same dictionary file
(dictionary.digium), which you added to the dictionary of radiusclient-ng
library. You can include it into the main file, adding the following line at the
end of file '/usr/local/etc/raddb/dictionary':
\$INCLUDE /path/to/dictionary.digium
That will include the same new attribute definitions that are used
in radiusclient-ng library so the client and server will understand each
other.
\subsubsection{Asterisk Accounting Configuration}
Compilation and installation:
The module will be compiled as long as the radiusclient-ng
library has been detected on your system.
By default FreeRADIUS server will log all accounting requests into
/usr/local/var/log/radius/radacct directory in form of plain text files.
The server will create one file for each hostname in the directory. The
following example shows how the log files look like.
Asterisk now generates Call Detail Records. See /include/asterisk/cel.h
for all the fields which are recorded. By default, records in comma
separated values will be created in /var/log/asterisk/cel-csv.
The configuration file for cel_radius.so module is :
/etc/asterisk/cel.conf
This is where you can set CEL related parameters as well as the path to
the radiusclient-ng library configuration file.
\subsubsection{Logged Values}
\begin{verbatim}
"Asterisk-Acc-Code", The account name of detail records
"Asterisk-CidName",
"Asterisk-CidNum",
"Asterisk-Cidani",
"Asterisk-Cidrdnis",
"Asterisk-Ciddnid",
"Asterisk-Exten",
"Asterisk-Context", The destination context
"Asterisk-Channame", The channel name
"Asterisk-Appname", Last application run on the channel
"Asterisk-App-Data", Argument to the last channel
"Asterisk-Event-Time",
"Asterisk-Event-Type",
"Asterisk-AMA-Flags", DOCUMENTATION, BILL, IGNORE etc, specified on
a per channel basis like accountcode.
"Asterisk-Unique-ID", Unique call identifier
"Asterisk-User-Field" User field set via SetCELUserField
"Asterisk-Peer" Name of the Peer for 2-channel events (like bridge)
\end{verbatim}

View File

@ -1,262 +0,0 @@
\subsection{Introduction}
Asterisk Channel Driver to allow Bluetooth Cell/Mobile Phones to be used as FXO devices, and Headsets as FXS devices.
\subsection{Features}
\begin{itemize}
\item Multiple Bluetooth Adapters supported.
\item Multiple phones can be connected.
\item Multiple headsets can be connected.
\item Asterisk automatically connects to each configured mobile phone / headset when it comes in range.
\item CLI command to discover bluetooth devices.
\item Inbound calls on the mobile network to the mobile phones are handled by Asterisk, just like inbound calls on a Zap channel.
\item CLI passed through on inbound calls.
\item Dial outbound on a mobile phone using Dial(Mobile/device/nnnnnnn) in the dialplan.
\item Dial a headset using Dial(Mobile/device) in the dialplan.
\item Application MobileStatus can be used in the dialplan to see if a mobile phone / headset is connected.
\item Supports devicestate for dialplan hinting.
\item Supports Inbound and Outbound SMS.
\item Supports 'channel' groups for implementing 'GSM Gateways'
\end{itemize}
\subsection{Requirements}
In order to use chan\_mobile, you must have a working bluetooth subsystem on your Asterisk box.
This means one or more working bluetooth adapters, and the BlueZ packages.
Any bluetooth adapter supported by the Linux kernel will do, including usb bluetooth dongles.
The BlueZ package you need is bluez-utils. If you are using a GUI then you might want to install bluez-pin also.
You also need libbluetooth, and libbluetooth-dev if you are compiling Asterisk from source.
You need to get bluetooth working with your phone before attempting to use chan\_mobile.
This means 'pairing' your phone or headset with your Asterisk box. I dont describe how to do this here as the process
differs from distro to distro. You only need to pair once per adapter.
See www.bluez.org for details about setting up Bluetooth under Linux.
\subsection{Concepts}
chan\_mobile deals with both bluetooth adapters and bluetooth devices. This means you need to tell chan\_mobile about the
bluetooth adapters installed in your server as well as the devices (phones / headsets) you wish to use.
chan\_mobile currently only allows one device (phone or headset) to be connected to an adapter at a time. This means you need
one adapter for each device you wish to use simultaneously. Much effort has gone into trying to make multiple devices per adapter
work, but in short it doesnt.
Periodically chan\_mobile looks at each configured adapter, and if it is not in use (i.e. no device connected) will initiate a
search for devices configured to use this adapater that may be in range. If it finds one it will connect the device and it
will be available for Asterisk to use. When the device goes out of range, chan\_mobile will disconnect the device and the adapter
will become available for other devices.
\subsection{Configuring chan\_mobile}
The configuration file for chan\_mobile is /etc/asterisk/mobile.conf. It is a normal Asterisk config file consisting of sections and key=value pairs.
See configs/mobile.conf.sample for an example and an explanation of the configuration.
\subsection{Using chan\_mobile}
chan\_mobile.so must be loaded either by loading it using the Asterisk CLI, or by adding it to /etc/asterisk/modules.conf
Search for your bluetooth devices using the CLI command 'mobile search'. Be patient with this command as
it will take 8 - 10 seconds to do the discovery. This requires a free adapter.
Headsets will generally have to be put into 'pairing' mode before they will show up here.
This will return something like the following :-
\begin{verbatim}
*CLI> mobile search
Address Name Usable Type Port
00:12:56:90:6E:00 LG TU500 Yes Phone 4
00:80:C8:35:52:78 Toaster No Headset 0
00:0B:9E:11:74:A5 Hello II Plus Yes Headset 1
00:0F:86:0E:AE:42 Daves Blackberry Yes Phone 7
\end{verbatim}
This is a list of all bluetooth devices seen and whether or not they are usable with chan\_mobile.
The Address field contains the 'bd address' of the device. This is like an ethernet mac address.
The Name field is whatever is configured into the device as its name.
The Usable field tells you whether or not the device supports the Bluetooth Handsfree Profile or Headset profile.
The Type field tells you whether the device is usable as a Phone line (FXO) or a headset (FXS)
The Port field is the number to put in the configuration file.
Choose which device(s) you want to use and edit /etc/asterisk/mobile.conf. There is a sample included
with the Asterisk-addons source under configs/mobile.conf.sample.
Be sure to configure the right bd address and port number from the search. If you want inbound
calls on a device to go to a specific context, add a context= line, otherwise the default will
be used. The 'id' of the device [bitinbrackets] can be anything you like, just make it unique.
If you are configuring a Headset be sure to include the type=headset line, if left out it defaults
to phone.
The CLI command 'mobile show devices' can be used at any time to show the status of configured devices,
and whether or not the device is capable of sending / receiving SMS via bluetooth.
\begin{verbatim}
*CLI> mobile show devices
ID Address Group Adapter Connected State SMS
headset 00:0B:9E:11:AE:C6 0 blue No Init No
LGTU550 00:E0:91:7F:46:44 1 dlink No Init No
\end{verbatim}
As each phone is connected you will see a message on the Asterisk console :-
\begin{verbatim}
Loaded chan_mobile.so => (Bluetooth Mobile Device Channel Driver)
-- Bluetooth Device blackberry has connected.
-- Bluetooth Device dave has connected.
\end{verbatim}
To make outbound calls, add something to you Dialplan like the following :- (modify to suit)
; Calls via LGTU5500
\begin{verbatim}
exten => _9X.,1,Dial(Mobile/LGTU550/${EXTEN:1},45)
exten => _9X.,n,Hangup
\end{verbatim}
To use channel groups, add an entry to each phones definition in mobile.conf like group=n
where n is a number.
Then if you do something like Dial(Mobile/g1/123456) Asterisk will dial 123456 on the first
connected free phone in group 1.
Phones which do not have a specific 'group=n' will be in group 0.
To dial out on a headset, you need to use some other mechanism, because the headset is not likely
to have all the needed buttons on it. res\_clioriginate is good for this :-
\begin{verbatim}
*CLI> originate Mobile/headset extension NNNNN@context
\end{verbatim}
This will call your headset, once you answer, Asterisk will call NNNNN at context context
\subsection{Dialplan hints}
chan\_mobile supports 'device status' so you can do somthing like
\begin{verbatim}
exten => 1234,hint,SIP/30&Mobile/dave&Mobile/blackberry
\end{verbatim}
\subsection{MobileStatus Application}
chan\_mobile also registers an application named MobileStatus. You can use this in your Dialplan
to determine the 'state' of a device.
For example, suppose you wanted to call dave's extension, but only if he was in the office. You could
test to see if his mobile phone was attached to Asterisk, if it is dial his extension, otherwise dial his
mobile phone.
\begin{verbatim}
exten => 40,1,MobileStatus(dave,DAVECELL)
exten => 40,2,GotoIf($["${DAVECELL}" = "1"]?3:5)
exten => 40,3,Dial(ZAP/g1/0427466412,45,tT)
exten => 40,4,Hangup
exten => 40,5,Dial(SIP/40,45,tT)
exten => 40,6,Hangup
\end{verbatim}
MobileStatus sets the value of the given variable to :-
\begin{verbatim}
1 = Disconnected. i.e. Device not in range of Asterisk, or turned off etc etc
2 = Connected and Not on a call. i.e. Free
3 = Connected and on a call. i.e. Busy
\end{verbatim}
\subsection{SMS Sending / Receiving}
If Asterisk has detected your mobile phone is capable of SMS via bluetooth, you will be able to send and
receive SMS.
Incoming SMS's cause Asterisk to create an inbound call to the context you defined in mobile.conf or the default
context if you did not define one. The call will start at extension 'sms'. Two channel variables will be available,
SMSSRC = the number of the originator of the SMS and SMSTXT which is the text of the SMS.
This is not a voice call, so grab the values of the variables and hang the call up.
So, to handle incoming SMS's, do something like the following in your dialplan
\begin{astlisting}
\begin{verbatim}
[incoming-mobile]
exten => sms,1,Verbose(Incoming SMS from ${SMSSRC} ${SMSTXT})
exten => sms,n,Hangup()
\end{verbatim}
\end{astlisting}
The above will just print the message on the console.
If you use res\_jabber, you could do something like this :-
\begin{astlisting}
\begin{verbatim}
[incoming-mobile]
exten => sms,1,JabberSend(transport,user@jabber.somewhere.com,SMS from ${SMSRC} ${SMSTXT})
exten => sms,2,Hangup()
\end{verbatim}
\end{astlisting}
To send an SMS, use the application MobileSendSMS like the following :-
\begin{verbatim}
exten => 99,1,MobileSendSMS(dave,0427123456,Hello World)
\end{verbatim}
This will send 'Hello World' via device 'dave' to '0427123456'
\subsection{DTMF Debouncing}
DTMF detection varies from phone to phone. There is a configuration variable that allows you to tune
this to your needs. e.g. in mobile.conf
\begin{verbatim}
[LGTU550]
address=00:12:56:90:6E:00
port=4
context=incoming-mobile
dtmfskip=50
\end{verbatim}
change dtmfskip to suit your phone. The default is 200. The larger the number, the more chance of missed DTMF.
The smaller the number the more chance of multiple digits being detected.
\subsection{Debugging}
Different phone manufacturers have different interpretations of the Bluetooth Handsfree Profile Spec.
This means that not all phones work the same way, particularly in the connection setup / initialisation
sequence. I've tried to make chan\_mobile as general as possible, but it may need modification to
support some phone i've never tested.
Some phones, most notably Sony Ericsson 'T' series, dont quite conform to the Bluetooth HFP spec.
chan\_mobile will detect these and adapt accordingly. The T-610 and T-630 have been tested and
work fine.
If your phone doesnt behave has expected, turn on Asterisk debugging with 'core set debug 1'.
This will log a bunch of debug messages indicating what the phone is doing, importantly the rfcomm
conversation between Asterisk and the phone. This can be used to sort out what your phone is doing
and make chan\_mobile support it.
Be aware also, that just about all mobile phones behave differently. For example my LG TU500 wont dial unless
the phone is a the 'idle' screen. i.e. if the phone is showing a 'menu' on the display, when you dial via
Asterisk, the call will not work. chan\_mobile handles this, but there may be other phones that do
other things too...
Important: Watch what your mobile phone is doing the first few times. Asterisk wont make random calls but
if chan\_mobile fails to hangup for some reason and you get a huge bill from your telco, dont blame me ;)

View File

@ -1,84 +0,0 @@
\subsection{Introduction}
This section is intended as an introduction to the Inter-Asterisk
eXchange v2 (or simply IAX2) protocol. It provides both a theoretical
background and practical information on its use.
\subsection{Why IAX2?}
The first question most people are thinking at this point is "Why do you
need another VoIP protocol? Why didn't you just use SIP or H.323?"
Well, the answer is a fairly complicated one, but in a nutshell it's like
this... Asterisk is intended as a very flexible and powerful
communications tool. As such, the primary feature we need from a VoIP
protocol is the ability to meet our own goals with Asterisk, and one with
enough flexibility that we could use it as a kind of laboratory for
inventing and implementing new concepts in the field. Neither H.323 or
SIP fit the roles we needed, so we developed our own protocol, which,
while not standards based, provides a number of advantages over both SIP
and H.323, some of which are:
\begin{itemize}
\item Interoperability with NAT/PAT/Masquerade firewalls
\begin{itemize}
\item IAX seamlessly interoperates through all sorts of NAT and PAT
and other firewalls, including the ability to place and
receive calls, and transfer calls to other stations.
\end{itemize}
\item High performance, low overhead protocol
\begin{itemize}
\item When running on low-bandwidth connections, or when running
large numbers of calls, optimized bandwidth utilization is
imperative. IAX uses only 4 bytes of overhead
\end{itemize}
\item Internationalization support
\begin{itemize}
\item IAX transmits language information, so that remote PBX
content can be delivered in the native language of the
calling party.
\end{itemize}
\item Remote dialplan polling
\begin{itemize}
\item IAX allows a PBX or IP phone to poll the availability of a
number from a remote server. This allows PBX dialplans to
be centralized.
\end{itemize}
\item Flexible authentication
\begin{itemize}
\item IAX supports cleartext, md5, and RSA authentication,
providing flexible security models for outgoing calls and
registration services.
\end{itemize}
\item Multimedia protocol
\begin{itemize}
\item IAX supports the transmission of voice, video, images, text,
HTML, DTMF, and URL's. Voice menus can be presented in both
audibly and visually.
\end{itemize}
\item Call statistic gathering
\begin{itemize}
\item IAX gathers statistics about network performance (including
latency and jitter, as well as providing end-to-end latency
measurement.
\end{itemize}
\item Call parameter communication
\begin{itemize}
\item Caller*ID, requested extension, requested context, etc are
all communicated through the call.
\end{itemize}
\item Single socket design
\begin{itemize}
\item IAX's single socket design allows up to 32768 calls to be
multiplexed.
\end{itemize}
\end{itemize}
While we value the importance of standards based (i.e. SIP) call handling,
hopefully this will provide a reasonable explanation of why we developed
IAX rather than starting with SIP.
\subsection{Configuration}
For examples of a configuration, please see the iax.conf.sample in
your the /configs directory of you source code distribution.

File diff suppressed because it is too large Load Diff

View File

@ -1,29 +0,0 @@
\subsubsection{Changing the CLI Prompt}
The CLI prompt is set with the ASTERISK\_PROMPT UNIX environment variable that
you set from the Unix shell before starting Asterisk
You may include the following variables, that will be replaced by
the current value by Asterisk:
\begin{itemize}
\item \%d - Date (year-month-date)
\item \%s - Asterisk system name (from asterisk.conf)
\item \%h - Full hostname
\item \%H - Short hostname
\item \%t - Time
\item \%u - Username
\item \%g - Groupname
\item \%\% - Percent sign
\item \%\# - '\#' if Asterisk is run in console mode, '$>$' if running as remote console
\item \%Cn[;n] - Change terminal foreground (and optional background) color to specified
A full list of colors may be found in \path{include/asterisk/term.h}
\end{itemize}
On systems which implement getloadavg(3), you may also use:
\begin{itemize}
\item \%l1 - Load average over past minute
\item \%l2 - Load average over past 5 minutes
\item \%l3 - Load average over past 15 minutes
\end{itemize}

View File

@ -1,233 +0,0 @@
\subsubsection{Introduction}
The Asterisk configuration parser in the 1.2 version
and beyond series has been improved in a number of ways. In
addition to the realtime architecture, we now have the ability to create
templates in configuration files, and use these as templates when we
configure phones, voicemail accounts and queues.
These changes are general to the configuration parser, and works in
all configuration files.
\subsubsection{General syntax}
Asterisk configuration files are defined as follows:
\begin{astlisting}
\begin{verbatim}
[section]
label = value
label2 = value
\end{verbatim}
\end{astlisting}
In some files, (e.g. mgcp.conf, dahdi.conf and agents.conf), the syntax
is a bit different. In these files the syntax is as follows:
\begin{astlisting}
\begin{verbatim}
[section]
label1 = value1
label2 = value2
object => name
label3 = value3
label2 = value4
object2 => name2
\end{verbatim}
\end{astlisting}
In this syntax, we create objects with the settings defined above the object
creation. Note that settings are inherited from the top, so in the example
above object2 has inherited the setting for "label1" from the first object.
For template configurations, the syntax for defining a section is changed
to:
\begin{astlisting}
\begin{verbatim}
[section](options)
label = value
\end{verbatim}
\end{astlisting}
The options field is used to define templates, refer to templates and hide
templates. Any object can be used as a template.
No whitespace is allowed between the closing "]" and the parenthesis "(".
\subsubsection{Comments}
All lines that starts with semi-colon ";" is treated as comments
and is not parsed.
The "\verb!;--!" is a marker for a multi-line comment. Everything after
that marker will be treated as a comment until the end-marker "\verb!--;!"
is found. Parsing begins directly after the end-marker.
\begin{astlisting}
\begin{verbatim}
;This is a comment
label = value
;-- This is
a comment --;
;-- Comment --; exten=> 1000,1,dial(SIP/lisa)
\end{verbatim}
\end{astlisting}
\subsubsection{Including other files}
In all of the configuration files, you may include the content of another
file with the \#include statement. The content of the other file will be
included at the row that the \#include statement occurred.
\begin{astlisting}
\begin{verbatim}
#include myusers.conf
\end{verbatim}
\end{astlisting}
You may also include the output of a program with the \#exec directive,
if you enable it in asterisk.conf
In asterisk.conf, add the execincludes = yes statement in the options
section:
\begin{astlisting}
\begin{verbatim}
[options]
execincludes=yes
\end{verbatim}
\end{astlisting}
The exec directive is used like this:
\begin{astlisting}
\begin{verbatim}
#exec /usr/local/bin/myasteriskconfigurator.sh
\end{verbatim}
\end{astlisting}
\subsubsection{Adding to an existing section}
\begin{astlisting}
\begin{verbatim}
[section]
label = value
[section](+)
label2 = value2
\end{verbatim}
\end{astlisting}
In this case, the plus sign indicates that the second section (with the
same name) is an addition to the first section. The second section can
be in another file (by using the \#include statement). If the section
name referred to before the plus is missing, the configuration will fail
to load.
\subsubsection{Defining a template-only section}
\begin{astlisting}
\begin{verbatim}
[section](!)
label = value
\end{verbatim}
\end{astlisting}
The exclamation mark indicates to the config parser that this is a only
a template and should not itself be used by the Asterisk module for
configuration. The section can be inherited by other sections (see
section "Using templates" below) but is not used by itself.
\subsubsection{Using templates (or other configuration sections)}
\begin{astlisting}
\begin{verbatim}
[section](name[,name])
label = value
\end{verbatim}
\end{astlisting}
The name within the parenthesis refers to other sections, either
templates or standard sections. The referred sections are included
before the configuration engine parses the local settings within the
section as though their entire contents (and anything they were
previously based upon) were included in the new section. For example
consider the following:
\begin{astlisting}
\begin{verbatim}
[foo]
disallow=all
allow=ulaw
allow=alaw
[bar]
allow=gsm
allow=g729
permit=192.168.2.1
[baz](foo,bar)
type=friend
permit=192.168.3.1
context=incoming
host=bnm
\end{verbatim}
\end{astlisting}
The [baz] section will be processed as though it had been written in the
following way:
\begin{astlisting}
\begin{verbatim}
[baz]
disallow=all
allow=ulaw
allow=alaw
allow=gsm
allow=g729
permit=192.168.2.1
type=friend
permit=192.168.3.1
context=incoming
host=bnm
\end{verbatim}
\end{astlisting}
It should also be noted that there are no guaranteed overriding semantics,
meaning that if you define something in one template, you should not expect to
be able to override it by defining it again in another template.
\subsubsection{Additional Examples}
(in top-level sip.conf)
\begin{astlisting}
\begin{verbatim}
[defaults](!)
type=friend
nat=yes
qualify=on
dtmfmode=rfc2833
disallow=all
allow=alaw
#include accounts/*/sip.conf
\end{verbatim}
\end{astlisting}
(in \path{accounts/customer1/sip.conf})
\begin{astlisting}
\begin{verbatim}
[def-customer1](!,defaults)
secret=this_is_not_secret
context=from-customer1
callerid=Customer 1 <300>
accountcode=0001
[phone1](def-customer1)
mailbox=phone1@customer1
[phone2](def-customer1)
mailbox=phone2@customer1
\end{verbatim}
\end{astlisting}
This example defines two phones - phone1 and phone2 with settings
inherited from "def-customer1". The "def-customer1" is a template that
inherits from "defaults", which also is a template.

View File

@ -1,41 +0,0 @@
\url{http://www.dundi.com}
Mark Spencer, Digium, Inc.
DUNDi is essentially a trusted, peer-to-peer system for being able to
call any phone number from the Internet. DUNDi works by creating a
network of nodes called the "DUNDi E.164 Trust Group" which are bound by
a common peering agreement known as the General Peering Agreement or
GPA. The GPA legally binds the members of the Trust Group to provide
good-faith accurate information to the other nodes on the network, and
provides standards by which the community can insure the integrity of
the information on the nodes themselves. Unlike ENUM or similar
systems, DUNDi is explicitly designed to preclude any necessity for a
single centralized system which could be a source of fees, regulation,
etc.
Much less dramatically, DUNDi can also be used within a private
enterprise to share a dialplan efficiently between multiple nodes,
without incurring a risk of a single point of failure. In this way,
administrators can locally add extensions which become immediately
available to the other nodes in the system.
For more information visit \url{http://www.dundi.com}
\section{DUNDIQUERY and DUNDIRESULT}
The DUNDIQUERY and DUNDIRESULT dialplan functions will let you initiate
a DUNDi query from the dialplan, see how many results there are, and access
each one. Here is some example usage:
\begin{astlisting}
\begin{verbatim}
exten => 1,1,Set(ID=${DUNDIQUERY(1,dundi_test,b)})
exten => 1,n,Set(NUM=${DUNDIRESULT(${ID},getnum)})
exten => 1,n,NoOp(There are ${NUM} results)
exten => 1,n,Set(X=1)
exten => 1,n,While($[${X} <= ${NUM}])
exten => 1,n,NoOp(Result ${X} is ${DUNDIRESULT(${ID},${X})})
exten => 1,n,Set(X=$[${X} + 1])
exten => 1,n,EndWhile
\end{verbatim}
\end{astlisting}

View File

@ -1,355 +0,0 @@
\section{The ENUMLOOKUP dialplan function}
The ENUMLOOKUP function is more complex than it first may appear, and
this guide is to give a general overview and set of examples that may
be well-suited for the advanced user to evaluate in their
consideration of ENUM or ENUM-like lookup strategies. This document
assumes a familiarity with ENUM (RFC3761) or ENUM-like methods, as
well as familiarity with NAPTR DNS records (RFC2915, RFC3401-3404).
For an overview of NAPTR records, and the use of NAPTRs in the ENUM
global phone-number-to-DNS mapping scheme, please see
\url{http://www.voip-info.org/tiki-index.php?page=ENUM} for more detail.
Using ENUM within Asterisk can be simple or complex, depending on how
many failover methods and redundancy procedures you wish to utilize.
Implementation of ENUM paths is supposedly defined by the person
creating the NAPTR records, but the local administrator may choose to
ignore certain NAPTR response methods (URI types) or prefer some over
others, which is in contradiction to the RFC. The ENUMLOOKUP method
simply provides administrators a method for determining NAPTR results
in either the globally unique ENUM (e164.arpa) DNS tree, or in other
ENUM-like DNS trees which are not globally unique. The methods to
actually create channels ("dial") results given by the ENUMLOOKUP
function is then up to the administrator to implement in a way that
best suits their environment.
\begin{verbatim}
Function: ENUMLOOKUP(number[,Method-type[,options[,record#[,zone-suffix]]]])
\end{verbatim}
Performs an ENUM tree lookup on the specified number, method type, and
ordinal record offset, and returns one of four different values:
\begin{enumerate}
\item post-parsed NAPTR of one method (URI) type
\item count of elements of one method (URI) type
\item count of all method types
\item full URI of method at a particular point in the list of all possible methods
\end{enumerate}
\subsection{Arguments}
\begin{itemize}
\item number
\begin{itemize}
\item telephone number or search string. Only numeric values
within this string are parsed; all other digits are ignored for
search, but are re-written during NAPTR regexp expansion.
\end{itemize}
\item service\_type
\begin{itemize}
\item tel, sip, h323, iax2, mailto, ...[any other string],
ALL. Default type is "sip".
Special name of "ALL" will create a list of method types across
all NAPTR records for the search number, and then put the results
in an ordinal list starting with 1. The position $<$number$>$
specified will then be returned, starting with 1 as the first
record (lowest value) in the list. The service types are not
hardcoded in Asterisk except for the default (sip) if no other
service type specified; any method type string (IANA-approved or
not) may be used except for the string "ALL".
\end{itemize}
\item options
\begin{itemize}
\item c
\begin{itemize}
\item count. Returns the number of records of this type are returned
(regardless of order or priority.) If "ALL" is the specified
service\_type, then a count of all methods will be returned for the
DNS record.
\end{itemize}
\end{itemize}
\item record\#
\begin{itemize}
\item which record to present if multiple answers are returned
$<$integer$>$ = The record in priority/order sequence based on the
total count of records passed back by the query. If a service\_type
is specified, all entries of that type will be sorted into an
ordinal list starting with 1 (by order first, then priority).
The default of $<$options$>$ is "1"
\end{itemize}
\item zone\_suffix
\begin{itemize}
\item allows customization of the ENUM zone. Default is e164.arpa.
\end{itemize}
\end{itemize}
\subsection{Examples}
Let's use this ENUM list as an example (note that these examples exist
in the DNS, and will hopefully remain in place as example
destinations, but they may change or become invalid over time. The
end result URIs are not guaranteed to actually work, since some of
these hostnames or SIP proxies are imaginary. Of course, the tel:
replies go to directory assistance for New York City and San
Francisco...) Also note that the complex SIP NAPTR at weight 30 will
strip off the leading "+" from the dialed string if it exists. This
is probably a better NAPTR than hard-coding the number into the NAPTR,
and it is included as a more complex regexp example, though other
simpler NAPTRs will work just as well.
\begin{verbatim}
0.2.0.1.1.6.5.1.0.3.1.loligo.com. 3600 IN NAPTR 10 100 "u"
"E2U+tel" "!^\\+13015611020$!tel:+12125551212!" .
0.2.0.1.1.6.5.1.0.3.1.loligo.com. 3600 IN NAPTR 21 100 "u"
"E2U+tel" "!^\\+13015611020$!tel:+14155551212!" .
0.2.0.1.1.6.5.1.0.3.1.loligo.com. 3600 IN NAPTR 25 100 "u"
"E2U+sip" "!^\\+13015611020$!sip:2203@sip.fox-den.com!" .
0.2.0.1.1.6.5.1.0.3.1.loligo.com. 3600 IN NAPTR 26 100 "u"
"E2U+sip" "!^\\+13015611020$!sip:1234@sip-2.fox-den.com!" .
0.2.0.1.1.6.5.1.0.3.1.loligo.com. 3600 IN NAPTR 30 100 "u"
"E2U+sip" "!^\\+*([^\\*]*)!sip:\\1@sip-3.fox-den.com!" .
0.2.0.1.1.6.5.1.0.3.1.loligo.com. 3600 IN NAPTR 55 100 "u"
"E2U+mailto" "!^\\+13015611020$!mailto:jtodd@fox-den.com!" .
\end{verbatim}
Example 1: Simplest case, using first SIP return (use all defaults
except for domain name)
\begin{verbatim}
exten => 100,1,Set(foo=${ENUMLOOKUP(+13015611020,,,,loligo.com)})
returns: ${foo}="2203@sip.fox-den.com"
\end{verbatim}
Example 2: What is the first "tel" pointer type for this number?
(after sorting by order/preference; default of "1" is assumed in
options field)
\begin{verbatim}
exten => 100,1,Set(foo=${ENUMLOOKUP(+13015611020,tel,,,loligo.com)})
returns: ${foo}="+12125551212"
\end{verbatim}
Example 3: How many "sip" pointer type entries are there for this number?
\begin{verbatim}
exten => 100,1,Set(foo=${ENUMLOOKUP(+13015611020,sip,c,,loligo.com)})
returns: ${foo}=3
\end{verbatim}
Example 4: For all the "tel" pointer type entries, what is the second
one in the list? (after sorting by preference)
\begin{verbatim}
exten => 100,1,Set(foo=${ENUMLOOKUP(+13015611020,tel,,2,loligo.com)})
returns: ${foo}="+14155551212"
\end{verbatim}
Example 5: How many NAPTRs (tel, sip, mailto, etc.) are in the list for this number?
\begin{verbatim}
exten => 100,1,Set(foo=${ENUMLOOKUP(+13015611020,ALL,c,,loligo.com)})
returns: ${foo}=6
\end{verbatim}
Example 6: Give back the second full URI in the sorted list of all NAPTR URIs:
\begin{verbatim}
exten => 100,1,Set(foo=${ENUMLOOKUP(+13015611020,ALL,,2,loligo.com)})
returns: ${foo}="tel:+14155551212" [note the "tel:" prefix in the string]
\end{verbatim}
Example 7: Look up first SIP entry for the number in the e164.arpa zone (all defaults)
\begin{verbatim}
exten => 100,1,Set(foo=${ENUMLOOKUP(+437203001721)})
returns: ${foo}="enum-test@sip.nemox.net" [note: this result is
subject to change as it is "live" DNS and not under my control]
\end{verbatim}
Example 8: Look up the ISN mapping in freenum.org alpha test zone
\begin{verbatim}
exten => 100,1,Set(foo=${ENUMLOOKUP(1234*256,,,,freenum.org)})
returns: ${foo}="1234@204.91.156.10" [note: this result is subject
to change as it is "live" DNS]
\end{verbatim}
Example 9: Give back the first SIP pointer for a number in the
\begin{verbatim}
enum.yoydynelabs.com zone (invalid lookup)
exten => 100,1,Set(foo=${ENUMLOOKUP(1234567890,sip,,1,enum.yoyodynelabs.com)})
returns: ${foo}=""
\end{verbatim}
\subsection{Usage notes and subtle features}
\begin{itemize}
\item The use of "+" in lookups is confusing, and warrants further
explanation. All E.164 numbers ("global phone numbers") by
definition need a leading "+" during ENUM lookup. If you neglect to
add a leading "+", you may discover that numbers that seem to exist
in the DNS aren't getting matched by the system or are returned with
a null string result. This is due to the NAPTR reply requiring a
"+" in the regular expression matching sequence. Older versions of
Asterisk add a "+" from within the code, which may confuse
administrators converting to the new function. Please ensure that
all ENUM (e164.arpa) lookups contain a leading "+" before lookup, so
ensure your lookup includes the leading plus sign. Other DNS trees
may or may not require a leading "+" - check before using those
trees, as it is possible the parsed NAPTRs will not provide correct
results unless you have the correct dialed string. If you get
console messages like "WARNING[24907]: enum.c:222 parse\_naptr: NAPTR
Regex match failed." then it is very possible that the returned
NAPTR expects a leading "+" in the search string (or the returned
NAPTR is mis-formed.)
\item If a query is performed of type "c" ("count") and let's say you
get back 5 records and then some seconds later a query is made
against record 5 in the list, it may not be the case that the DNS
resolver has the same answers as it did a second or two ago - maybe
there are only 4 records in the list in the newest query. The
resolver should be the canonical storage location for DNS records,
since that is the intent of ENUM. However, some obscure future
cases may have wildly changing NAPTR records within several seconds.
This is a corner case, and probably only worth noting as a very rare
circumstance. (note: I do not object to Asterisk's dnsmgr method of
locally caching DNS replies, but this method needs to honor the TTL
given by the remote zone master. Currently, the ENUMLOOKUP function
does not use the dnsmgr method of caching local DNS replies.)
\item If you want strict NAPTR value ordering, then it will be
necessary to use the "ALL" method to incrementally step through the
different returned NAPTR pointers. You will need to use string
manipulation to strip off the returned method types, since the
results will look like "sip:12125551212" in the returned value.
This is a non-trivial task, though it is required in order to have
strict RFC compliance and to comply with the desires of the remote
party who is presenting NAPTRs in a particular order for a reason.
\item Default behavior for the function (even in event of an error) is
to move to the next priority, and the result is a null value. Most
ENUM lookups are going to be failures, and it is the responsibility
of the dialplan administrator to manage error conditions within
their dialplan. This is a change from the old app\_enumlookup method
and it's arbitrary priority jumping based on result type or failure.
\item Anything other than digits will be ignored in lookup strings.
Example: a search string of "+4372030blah01721" will turn into
1.2.7.1.0.0.3.0.2.7.3.4.e164.arpa. for the lookup. The NAPTR
parsing may cause unexpected results if there are strings inside
your NAPTR lookups.
\item If there exist multiple records with the same weight and order as
a result of your query, the function will RANDOMLY select a single
NAPTR from those equal results.
\item Currently, the function ignores the settings in enum.conf as the
search zone name is now specified within the function, and the H323
driver can be chosen by the user via the dialplan. There were no
other values in this file, and so it becomes deprecated.
\item The function will digest and return NAPTRs which use older
(deprecated) style, reversed method strings such as "sip+E2U"
instead of the more modern "E2U+sip"
\item There is no provision for multi-part methods at this time. If
there are multiple NAPTRs with (as an example) a method of
"E2U+voice:sip" and then another NAPTR in the same DNS record with a
method of ""E2U+sip", the system will treat these both as method
"sip" and they will be separate records from the perspective of the
function. Of course, if both records point to the same URI and have
equal priority/weight (as is often the case) then this will cause no
serious difficulty, but it bears mentioning.
\item ISN (ITAD Subscriber Number) usage: If the search number is of
the form ABC*DEF (where ABC and DEF are at least one numeric digit)
then perform an ISN-style lookup where the lookup is manipulated to
C.B.A.DEF.domain.tld (all other settings and options apply.) See
\url{http://www.freenum.org/} for more details on ISN lookups. In the
unlikely event you wish to avoid ISN re-writes, put an "n" as the
first digit of the search string - the "n" will be ignored for the search.
\end{itemize}
\subsection{Some more Examples}
All examples below except where noted use "e164.arpa" as the
referenced domain, which is the default domain name for ENUMLOOKUP.
All numbers are assumed to not have a leading "+" as dialed by the
inbound channel, so that character is added where necessary during
ENUMLOOKUP function calls.
\begin{astlisting}
\begin{verbatim}
; example 1
;
; Assumes North American international dialing (011) prefix.
; Look up the first SIP result and send the call there, otherwise
; send the call out a PRI. This is the most simple possible
; ENUM example, but only uses the first SIP reply in the list of
; NAPTR(s).
;
exten => _011.,1,Set(enumresult=${ENUMLOOKUP(+${EXTEN:3})})
exten => _011.,n,Dial(SIP/${enumresult})
exten => _011.,n,Dial(DAHDI/g1/${EXTEN})
;
; end example 1
; example 2
;
; Assumes North American international dialing (011) prefix.
; Check to see if there are multiple SIP NAPTRs returned by
; the lookup, and dial each in order. If none work (or none
; exist) then send the call out a PRI, group 1.
;
exten => _011.,1,Set(sipcount=${ENUMLOOKUP(${EXTEN:3},sip,c)}|counter=0)
exten => _011.,n,While($["${counter}"<"${sipcount}"])
exten => _011.,n,Set(counter=$[${counter}+1])
exten => _011.,n,Dial(SIP/${ENUMLOOKUP(+${EXTEN:3},sip,,${counter})})
exten => _011.,n,EndWhile
exten => _011.,n,Dial(DAHDI/g1/${EXTEN})
;
; end example 2
; example 3
;
; This example expects an ${EXTEN} that is an e.164 number (like
; 14102241145 or 437203001721)
; Search through e164.arpa and then also search through e164.org
; to see if there are any valid SIP or IAX termination capabilities.
; If none, send call out via DAHDI channel 1.
;
; Start first with e164.arpa zone...
;
exten => _X.,1,Set(sipcount=${ENUMLOOKUP(+${EXTEN},sip,c)}|counter=0)
exten => _X.,2,GotoIf($["${counter}"<"${sipcount}"]?3:6)
exten => _X.,3,Set(counter=$[${counter}+1])
exten => _X.,4,Dial(SIP/${ENUMLOOKUP(+${EXTEN},sip,,${counter})})
exten => _X.,5,GotoIf($["${counter}"<"${sipcount}"]?3:6)
;
exten => _X.,6,Set(iaxcount=${ENUMLOOKUP(+${EXTEN},iax2,c)}|counter=0)
exten => _X.,7,GotoIf($["${counter}"<"${iaxcount}"]?8:11)
exten => _X.,8,Set(counter=$[${counter}+1])
exten => _X.,9,Dial(IAX2/${ENUMLOOKUP(+${EXTEN},iax2,,${counter})})
exten => _X.,10,GotoIf($["${counter}"<"${iaxcount}"]?8:11)
;
exten => _X.,11,NoOp("No valid entries in e164.arpa for ${EXTEN} - checking in e164.org")
;
; ...then also try e164.org, and look for SIP and IAX NAPTRs...
;
exten => _X.,12,Set(sipcount=${ENUMLOOKUP(+${EXTEN},sip,c,,e164.org)}|counter=0)
exten => _X.,13,GotoIf($["${counter}"<"${sipcount}"]?14:17)
exten => _X.,14,Set(counter=$[${counter}+1])
exten => _X.,15,Dial(SIP/${ENUMLOOKUP(+${EXTEN},sip,,${counter},e164.org)})
exten => _X.,16,GotoIf($["${counter}"<"${sipcount}"]?14:17)
;
exten => _X.,17,Set(iaxcount=${ENUMLOOKUP(+${EXTEN},iax2,c,,e164.org)}|counter=0)
exten => _X.,18,GotoIf($["${counter}"<"${iaxcount}"]?19:22)
exten => _X.,19,Set(counter=$[${counter}+1])
exten => _X.,20,Dial(IAX2/${ENUMLOOKUP(+${EXTEN},iax2,,${counter},e164.org)})
exten => _X.,21,GotoIf($["${counter}"<"${iaxcount}"]?19:22)
;
; ...then send out PRI.
;
exten => _X.,22,NoOp("No valid entries in e164.org for ${EXTEN} - sending out via DAHDI")
exten => _X.,23,Dial(DAHDI/g1/${EXTEN})
;
; end example 3
\end{verbatim}
\end{astlisting}

View File

@ -1,79 +0,0 @@
\subsubsection{The Asterisk dialplan}
The Asterisk dialplan is divided into contexts. A context is simply a group
of extensions. For each "line" that should be able to be called, an extension
must be added to a context. Then, you configure the calling "line" to have
access to this context.
If you change the dialplan, you can use the Asterisk CLI command
"dialplan reload" to load the new dialplan without disrupting
service in your PBX.
Extensions are routed according to priority and may be based on any set
of characters (a-z), digits, \#, and *. Please note that when matching a
pattern, "N", "X", and "Z" are interpreted as classes of digits.
For each extension, several actions may be listed and must be given a unique
priority. When each action completes, the call continues at the next priority
(except for some modules which use explicitly GOTO's).
Extensions frequently have data they pass to the executing application
(most frequently a string). You can see the available dialplan applications
by entering the "core show applications" command in the CLI.
In this version of Asterisk, dialplan functions are added. These can
be used as arguments to any application. For a list of the installed
functions in your Asterisk, use the "core show functions" command.
\subsubsection{Example dialplan}
The example dial plan, in the \path{configs/extensions.conf.sample} file
is installed as extensions.conf if you run "make samples" after
installation of Asterisk. This file includes many more instructions
and examples than this file, so it's worthwhile to read it.
\subsubsection{Special extensions}
There are some extensions with important meanings:
\begin{itemize}
\item s
\begin{itemize}
\item What to do when an extension context is entered (unless
overridden by the low level channel interface)
This is used in macros, and some special cases.
"s" is not a generic catch-all wildcard extension.
\end{itemize}
\item i
\begin{itemize}
\item What to do if an invalid extension is entered
\end{itemize}
\item h
\begin{itemize}
\item The hangup extension, executed at hangup
\end{itemize}
\item t
\begin{itemize}
\item What to do if nothing is entered in the requisite amount
of time.
\end{itemize}
\item T
\begin{itemize}
\item This is the extension that is executed when the 'absolute'
timeout is reached. See "core show function TIMEOUT" for more
information on setting timeouts.
\end{itemize}
\item e
\begin{itemize}
\item This extension will substitute as a catchall for any of the
'i', 't', or 'T' extensions, if any of them do not exist and
catching the error in a single routine is desired. The
function EXCEPTION may be used to query the type of exception
or the location where it occurred.
\end{itemize}
\end{itemize}
And finally, the extension context "default" is used when either a) an
extension context is deleted while an extension is in use, or b) a specific
starting extension handler has not been defined (unless overridden by the
low level channel interface).

View File

@ -1,6 +0,0 @@
The cdr\_tds module now works with most modern release versions of FreeTDS (from
at least 0.60 through 0.82). Although versions of FreeTDS prior to 0.82 will
work, we recommend using the latest available version for performance and
stability reasons.
The latest release of FreeTDS is available from http://www.freetds.org/

View File

@ -1,100 +0,0 @@
\subsection{Introduction}
A PBX is only really useful if you can get calls into it. Of course, you
can use Asterisk with VoIP calls (SIP, H.323, IAX, etc.), but you can also
talk to the real PSTN through various cards.
Supported Hardware is divided into two general groups: DAHDI devices and
non-DAHDI devices. The DAHDI compatible hardware supports pseudo-TDM
conferencing and all call features through chan\_dahdi, whereas non-DAHDI
compatible hardware may have different features.
\subsection{DAHDI compatible hardware}
\begin{itemize}
\item Digium, Inc. (Primary Developer of Asterisk)
\url{http://www.digium.com}
\begin{itemize}
\item Analog Interfaces
\begin{itemize}
\item TDM400P - The TDM400P is a half-length PCI 2.2-compliant card that supports FXS and FXO station interfaces for connecting analog telephones and analog POTS lines through a PC.
\item TDM800P - The TDM800P is a half-length PCI 2.2-compliant, 8 port card using Digium's VoiceBus technology that supports FXS and FXO station interfaces for connecting analog telephones and analog POTS lines through a PC.
\item TDM2400P - The TDM2400P is a full-length PCI 2.2-compliant card for connecting analog telephones and analog POTS lines through a PC. It supports a combination of up to 6 FXS and/or FXO modules for a total of 24 lines.
\end{itemize}
\item Digital Interfaces
\begin{itemize}
\item TE412P - The TE412P offers an on-board DSP-based echo cancellation module. It supports E1, T1, and J1 environments and is selectable on a per-card or per-port basis.
\item TE410P - The TE410P improves performance and scalability through bus mastering architecture. It supports E1, T1, and J1 environments and is selectable on a per-card or per-port basis.
\item TE407P - The TE407P offers an on-board DSP-based echo cancellation module. It supports E1, T1, and J1 environments and is selectable on a per-card or per-port basis.
\item TE405P - The TE405P improves performance and scalability through bus mastering architecture. It supports both E1, T1, J1 environments and is selectable on a per-card or per-port basis.
\item TE212P - The TE212P offers an on-board DSP-based echo cancellation module. It supports E1, T1, and J1 environments and is selectable on a per-card or per-port basis.
\item TE210P - The TE210P improves performance and scalability through bus mastering architecture. It supports E1, T1, and J1 environments and is selectable on a per-card or per-port basis.
\item TE207P - The TE207P offers an on-board DSP-based echo cancellation module. It supports E1, T1, and J1 environments and is selectable on a per-card or per-port basis.
\item TE205P - The TE205P improves performance and scalability through bus mastering architecture. It supports both E1 and T1/J1 environments and is selectable on a per-card or per-port basis.
\item TE120P - The TE120P is a single span, selectable T1, E1, or J1 card and utilizes Digium's VoiceBus\texttrademark technology. It supports both voice and data modes.
\item TE110P - The TE110P brings a high-performance, cost-effective, and flexible single span togglable T1, E1, J1 interface to the Digium line-up of telephony interface devices.
\end{itemize}
\end{itemize}
\end{itemize}
\subsection{Non-DAHDI compatible hardware}
\begin{itemize}
\item QuickNet, Inc.
\url{http://www.quicknet.net}
\begin{itemize}
\item Internet PhoneJack - Single FXS interface. Supports Linux telephony
interface. DSP compression built-in.
\item Internet LineJack - Single FXS or FXO interface. Supports Linux
telephony interface.
\end{itemize}
\end{itemize}
\subsection{mISDN compatible hardware}
mISDN homepage: \url{http://www.misdn.org/}
Any adapter with an mISDN driver should be compatible with
chan\_misdn. See the mISDN section for more information.
\begin{itemize}
\item Digium, Inc. (Primary Developer of Asterisk)
\url{http://www.digium.com}
\begin{itemize}
\item B410P - 4 Port BRI card (TE/NT)
\end{itemize}
\end{itemize}
\begin{itemize}
\item beroNet
\url{http://www.beronet.com}
\begin{itemize}
\item BN4S0 - 4 Port BRI card (TE/NT)
\item BN8S0 - 8 Port BRI card (TE/NT)
\item Billion Card - Single Port BRI card (TE (/NT with crossed cable))
\end{itemize}
\end{itemize}
\subsection{Miscellaneous other interfaces}
\begin{itemize}
\item Digium, Inc. (Primary Developer of Asterisk)
\begin{itemize}
\item TC400B - The TC400B is a half-length, low-profile PCI 2.2-compliant card for transforming complex VoIP codecs (G.729) into simple codecs.
\end{itemize}
\item ALSA
\url{http://www.alsa-project.org}
\begin{itemize}
\item Any ALSA compatible full-duplex sound card
\end{itemize}
\item OSS
\url{http://www.opensound.com}
\begin{itemize}
\item Any OSS compatible full-duplex sound card
\end{itemize}
\end{itemize}

View File

@ -1,7 +0,0 @@
The advent of icecast into Asterisk allows you to do neat things like have
a caller stream right into an ice-cast stream as well as using chan\_local
to place things like conferences, music on hold, etc. into the stream.
You'll need to specify a config file for the ices encoder. An example is
included in \path{contrib/asterisk-ices.xml}.

View File

@ -1,241 +0,0 @@
By enabling IMAP Storage, Asterisk will use native IMAP as the storage
mechanism for voicemail messages instead of using the standard file structure.
Tighter integration of Asterisk voicemail and IMAP email services allows
additional voicemail functionality, including:
\begin{itemize}
\item Listening to a voicemail on the phone will set its state to "read" in
a user's mailbox automatically.
\item Deleting a voicemail on the phone will delete it from the user's
mailbox automatically.
\item Accessing a voicemail recording email message will turn off the message
waiting indicator (MWI) on the user's phone.
\item Deleting a voicemail recording email will also turn off the message
waiting indicator, and delete the message from the voicemail system.
\end{itemize}
\subsection{Installation Notes}
\subsubsection{University of Washington IMAP C-Client}
If you do not have the University of Washington's IMAP c-client
installed on your system, you will need to download the c-client
source distribution (\url{http://www.washington.edu/imap/}) and compile it.
Asterisk supports the 2007 version of c-client as there appears to be issues
with older versions which cause Asterisk to crash in certain scenarios. It
is highly recommended that you utilize a current version of the c-client
libraries. Additionally, mail\_expunge\_full is enabled in the 2006 and later
versions.
Note that Asterisk only uses the 'c-client' portion of the UW IMAP toolkit,
but building it also builds an IMAP server and various other utilities.
Because of this, the build instructions for the IMAP toolkit are somewhat
complicated and can lead to confusion about what is needed.
If you are going to be connecting Asterisk to an existing IMAP server,
then you don't need to care about the server or utilities in the IMAP
toolkit at all. If you want to also install the UW IMAPD server, that
is outside the scope of this document.
Building the c-client library is fairly straightforward; for example, on a
Debian system there are two possibilities:
\begin{enumerate}
\item If you will not be using SSL to connect to the IMAP server:
\begin{verbatim}
$ make slx SSLTYPE=none
\end{verbatim}
\item If you will be using SSL to connect to the IMAP server:
\begin{verbatim}
$ make slx EXTRACFLAGS="-I/usr/include/openssl"
\end{verbatim}
\end{enumerate}
Additionally, you may wish to build on a 64-bit machine, in which case you
need to add -fPIC to EXTRACFLAGS. So, building on a 64-bit machine with
SSL support would look something like:
\begin{verbatim}
$ make slx EXTRACFLAGS="-fPIC -I/usr/include/openssl"
\end{verbatim}
Or without SSL support:
\begin{verbatim}
$ make slx SSLTYPE=none EXTRACFLAGS=-fPIC
\end{verbatim}
Once this completes you can proceed with the Asterisk build; there is no
need to run 'make install'.
\subsubsection{Compiling Asterisk}
Configure with ./configure --with-imap=/usr/src/imap
or wherever you built the UWashington IMAP Toolkit. This directory
will be searched for a source installation. If no source installation is
found there, then a package installation of the IMAP c-client will be
searched for in this directory. If one is not found, then configure will fail.
A second configure option is to not specify a directory (i.e.
./configure --with-imap). This will assume that you have the
imap-2007e source installed in the ../imap directory relative to the
Asterisk source. If you do not have this source, then configure will
default to the "system" option defined in the next paragraph
A third option is ./configure --with-imap=system. This will assume
that you have installed a dynamically linked version of the c-client
library (most likely via a package provided by your distro). This will
attempt to link agains -lc-client and will search for c-client headers
in your include path starting with the imap directory, and upon failure,
in the c-client directory.
When you run 'make menuselect', choose 'Voicemail Build Options' and the
IMAP\_STORAGE option should be available for selection.
After selecting the IMAP\_STORAGE option, use the 'x' key to exit
menuselect and save your changes, and the build/install Asterisk
normally.
\subsection{Modify voicemail.conf}
The following directives have been added to voicemail.conf:
\begin{astlisting}
\begin{verbatim}
imapserver=<name or IP address of IMAP mail server>
imapport=<IMAP port, defaults to 143>
imapflags=<IMAP flags, "novalidate-cert" for example>
imapfolder=<IMAP folder to store messages to>
imapgreetings=<yes or no>
greetingsfolder=<IMAP folder to store greetings in if imapgreetings is enabled>
expungeonhangup=<yes or no>
authuser=<username>
authpassword=<password>
opentimeout=<TCP open timeout in seconds>
closetimeout=<TCP close timeout in seconds>
readtimeout=<TCP read timeout in seconds>
writetimeout=<TCP write timeout in seconds>
\end{verbatim}
\end{astlisting}
The "imapfolder" can be used to specify an alternative folder on your IMAP server
to store voicemails in. If not specified, the default folder 'INBOX' will be used.
The "imapgreetings" parameter can be enabled in order to store voicemail greetings
on the IMAP server. If disabled, then they will be stored on the local file system
as normal.
The "greetingsfolder" can be set to store greetings on the IMAP server when
"imapgreetings" is enabled in an alternative folder than that set by "imapfolder"
or the default folder for voicemails.
The "expungeonhangup" flag is used to determine if the voicemail system should
expunge all messages marked for deletion when the user hangs up the phone.
Each mailbox definition should also have imapuser=$<$imap username$>$.
For example:
\begin{astlisting}
\begin{verbatim}
4123=>4123,James Rothenberger,jar@onebiztone.com,,attach=yes|imapuser=jar
\end{verbatim}
\end{astlisting}
The directives "authuser" and "authpassword" are not needed when using
Kerberos. They are defined to allow Asterisk to authenticate as a single
user that has access to all mailboxes as an alternative to Kerberos.
\subsection{IMAP Folders}
Besides INBOX, users should create "Old", "Work", "Family" and "Friends"
IMAP folders at the same level of hierarchy as the INBOX. These will be
used as alternate folders for storing voicemail messages to mimic the
behavior of the current (file-based) voicemail system.
Please note that it is not recommended to store your voicemails in the top
level folder where your users will keep their emails, especially if there
are a large number of emails. A large number of emails in the same folder(s)
that you're storing your voicemails could cause a large delay as Asterisk must
parse through all the emails. For example a mailbox with 100 emails in it could
take up to 60 seconds to receive a response.
\subsection{Separate vs. Shared Email Accounts}
As administrator you will have to decide if you want to send the voicemail
messages to a separate IMAP account or use each user's existing IMAP mailbox
for voicemail storage. The IMAP storage mechanism will work either way.
By implementing a single IMAP mailbox, the user will see voicemail messages
appear in the same INBOX as other messages. The disadvantage of this method
is that if the IMAP server does NOT support UIDPLUS, Asterisk voicemail will
expunge ALL messages marked for deletion when the user exits the voicemail
system, not just the VOICEMAIL messages marked for deletion.
By implementing separate IMAP mailboxes for voicemail and email, voicemail
expunges will not remove regular email flagged for deletion.
\subsection{IMAP Server Implementations}
There are various IMAP server implementations, each supports a potentially
different set of features.
\subsubsection{UW IMAP-2005 or earlier}
UIDPLUS is currently NOT supported on these versions of UW-IMAP. Please note
that without UID\_EXPUNGE, Asterisk voicemail will expunge ALL messages marked
for deletion when a user exits the voicemail system (hangs up the phone).
This version is *not* recommended for Asterisk.
\subsubsection{UW IMAP-2006}
This version supports UIDPLUS, which allows UID\_EXPUNGE capabilities. This
feature allow the system to expunge ONLY pertinent messages, instead of the
default behavior, which is to expunge ALL messages marked for deletion when
EXPUNGE is called. The IMAP storage mechanism is this version of Asterisk
will check if the UID\_EXPUNGE feature is supported by the server, and use it
if possible.
This version is *not* recommended for Asterisk.
\subsubsection{UW IMAP-2007}
This is the currently recommended version for use with Asterisk.
\subsubsection{Cyrus IMAP}
Cyrus IMAP server v2.3.3 has been tested using a hierarchy delimiter of '/'.
\subsection{Quota Support}
If the IMAP server supports quotas, Asterisk will check the quota when
accessing voicemail. Currently only a warning is given to the user that
their quota is exceeded.
\subsection{Application Notes}
Since the primary storage mechanism is IMAP, all message information that
was previously stored in an associated text file, AND the recording itself,
is now stored in a single email message. This means that the .gsm recording
will ALWAYS be attached to the message (along with the user's preference of
recording format if different - ie. .WAV). The voicemail message information
is stored in the email message headers. These headers include:
\begin{verbatim}
X-Asterisk-VM-Message-Num
X-Asterisk-VM-Server-Name
X-Asterisk-VM-Context
X-Asterisk-VM-Extension
X-Asterisk-VM-Priority
X-Asterisk-VM-Caller-channel
X-Asterisk-VM-Caller-ID-Num
X-Asterisk-VM-Caller-ID-Name
X-Asterisk-VM-Duration
X-Asterisk-VM-Category
X-Asterisk-VM-Orig-date
X-Asterisk-VM-Orig-time
\end{verbatim}

View File

@ -1,98 +0,0 @@
\subsubsection{The new jitterbuffer}
You must add "jitterbuffer=yes" to either the [general] part of
iax.conf, or to a peer or a user. (just like the old jitterbuffer).
Also, you can set "maxjitterbuffer=n", which puts a hard-limit on the size of the
jitterbuffer of "n milliseconds". It is not necessary to have the new jitterbuffer
on both sides of a call; it works on the receive side only.
\subsubsection{PLC}
The new jitterbuffer detects packet loss. PLC is done to try to recreate these
lost packets in the codec decoding stage, as the encoded audio is translated to slinear.
PLC is also used to mask jitterbuffer growth.
This facility is enabled by default in iLBC and speex, as it has no additional cost.
This facility can be enabled in adpcm, alaw, g726, gsm, lpc10, and ulaw by setting
genericplc =$>$ true in the [plc] section of codecs.conf.
\subsubsection{Trunktimestamps}
To use this, both sides must be using Asterisk v1.2 or later.
Setting "trunktimestamps=yes" in iax.conf will cause your box to send 16-bit timestamps
for each trunked frame inside of a trunk frame. This will enable you to use jitterbuffer
for an IAX2 trunk, something that was not possible in the old architecture.
The other side must also support this functionality, or else, well, bad things will happen.
If you don't use trunktimestamps, there's lots of ways the jitterbuffer can get confused because
timestamps aren't necessarily sent through the trunk correctly.
\subsubsection{Communication with Asterisk v1.0.x systems}
You can set up communication with v1.0.x systems with the new jitterbuffer, but
you can't use trunks with trunktimestamps in this communication.
If you are connecting to an Asterisk server with earlier versions of the software (1.0.x),
do not enable both jitterbuffer and trunking for the involved peers/users
in order to be able to communicate. Earlier systems will not support trunktimestamps.
You may also compile chan\_iax2.c without the new jitterbuffer, enabling the old
backwards compatible architecture. Look in the source code for instructions.
\subsubsection{Testing and monitoring}
You can test the effectiveness of PLC and the new jitterbuffer's detection of loss by using
the new CLI command "iax2 test losspct $<$n$>$". This will simulate n percent packet loss
coming \_in\_ to chan\_iax2. You should find that with PLC and the new JB, 10 percent packet
loss should lead to just a tiny amount of distortion, while without PLC, it would lead to
silent gaps in your audio.
"iax2 show netstats" shows you statistics for each iax2 call you have up.
The columns are "RTT" which is the round-trip time for the last PING, and then a bunch of s
tats for both the local side (what you're receiving), and the remote side (what the other
end is telling us they are seeing). The remote stats may not be complete if the remote
end isn't using the new jitterbuffer.
The stats shown are:
\begin{itemize}
\item Jit: The jitter we have measured (milliseconds)
\item Del: The maximum delay imposed by the jitterbuffer (milliseconds)
\item Lost: The number of packets we've detected as lost.
\item \%: The percentage of packets we've detected as lost recently.
\item Drop: The number of packets we've purposely dropped (to lower latency).
\item OOO: The number of packets we've received out-of-order
\item Kpkts: The number of packets we've received / 1000.
\end{itemize}
\subsubsection{Reporting problems}
There's a couple of things that can make calls sound bad using the jitterbuffer:
\begin{enumerate}
\item The JB and PLC can make your calls sound better, but they can't fix everything.
If you lost 10 frames in a row, it can't possibly fix that. It really can't help much
more than one or two consecutive frames.
\item Bad timestamps: If whatever is generating timestamps to be sent to you generates
nonsensical timestamps, it can confuse the jitterbuffer. In particular, discontinuities
in timestamps will really upset it: Things like timestamps sequences which go 0, 20, 40,
60, 80, 34000, 34020, 34040, 34060... It's going to think you've got about 34 seconds
of jitter in this case, etc..
The right solution to this is to find out what's causing the sender to send us such nonsense,
and fix that. But we should also figure out how to make the receiver more robust in
cases like this.
chan\_iax2 will actually help fix this a bit if it's more than 3 seconds or so, but at
some point we should try to think of a better way to detect this kind of thing and
resynchronize.
Different clock rates are handled very gracefully though; it will actually deal with a
sender sending 20\% faster or slower than you expect just fine.
\item Really strange network delays: If your network "pauses" for like 5 seconds, and then
when it restarts, you are sent some packets that are 5 seconds old, we are going to see
that as a lot of jitter. We already throw away up to the worst 20 frames like this,
though, and the "maxjitterbuffer" parameter should put a limit on what we do in this case.
\end{enumerate}

View File

@ -1,508 +0,0 @@
\subsection{Introduction}
In Asterisk, Local channels are a method used to treat an extension in the
dialplan as if it were an external device. In essense, Asterisk will send the
call back into the dialplan as the destination of the call, versus sending the
call to a device.
Two of the most common areas where Local channels are used include members
configured for queues, and in use with callfiles. There are also other uses
where you want to ring two destinations, but with different information, such as
different callerID for each outgoing request.
\subsection{Examples}
Local channels are best demonstrated through the use of an example. Our first
example isn't terribly useful, but will demonstrate how Local channels can
execute dialplan logic by dialing from the Dial() application.
\subsection{Trivial Local channel example}
In our dialplan (extensions.conf), we can Dial() another part of the dialplan
through the use Local channels. To do this, we can use the following dialplan:
\begin{astlisting}
\begin{verbatim}
[devices]
exten => 201,1,Verbose(2,Dial another part of the dialplan via the Local chan)
exten => 201,n,Verbose(2,Outside channel: ${CHANNEL})
exten => 201,n,Dial(Local/201@extensions)
exten => 201,n,Hangup()
[extensions]
exten => 201,1,Verbose(2,Made it to the Local channel)
exten => 201,n,Verbose(2,Inside channel: ${CHANNEL})
exten => 201,n,Dial(SIP/some-named-extension,30)
exten => 201,n,Hangup()
\end{verbatim}
\end{astlisting}
The output of the dialplan would look something like the following. The output
has been broken up with some commentary to explain what we're looking at.
\begin{astlisting}
\begin{verbatim}
-- Executing [201@devices:1] Verbose("SIP/my_desk_phone-00000014", "2,Dial another part of the dialplan via the
Local chan") in new stack
== Dial another part of the dialplan via the Local chan
\end{verbatim}
\end{astlisting}
We dial extension 201 from SIP/my\_desk\_phone which has entered the [devices]
context. The first line simply outputs some information via the Verbose()
application.
\begin{astlisting}
\begin{verbatim}
-- Executing [201@devices:2] Verbose("SIP/my_desk_phone-00000014",
"2,Outside channel: SIP/my_desk_phone-00000014") in new stack
== Outside channel: SIP/my_desk_phone-00000014
\end{verbatim}
\end{astlisting}
The next line is another Verbose() application statement that tells us our
current channel name. We can see that the channel executing the current dialplan
is a desk phone (aptly named 'my\_desk\_phone').
\begin{astlisting}
\begin{verbatim}
-- Executing [201@devices:3] Dial("SIP/my_desk_phone-00000014", "Local/201@extensions") in new stack
-- Called 201@extensions
\end{verbatim}
\end{astlisting}
Now the third step in our dialplan executes the Dial() application which calls
extension 201 in the [extensions] context of our dialplan. There is no
requirement that we use the same extension number -- we could have just as
easily used a named extension, or some other number. Remember that we're dialing
another channel, but instead of dialing a device, we're "dialing" another part
of the dialplan.
\begin{astlisting}
\begin{verbatim}
-- Executing [201@extensions:1] Verbose("Local/201@extensions-7cf4;2", "2,Made it to the Local
channel") in new stack
== Made it to the Local channel
\end{verbatim}
\end{astlisting}
Now we've verified we've dialed another part of the dialplan. We can see the
channel executing the dialplan has changed to Local/201@extensions-7cf4;2. The
part '-7cf4;2' is just the unique identifier, and will be different for you.
\begin{astlisting}
\begin{verbatim}
-- Executing [201@extensions:2] Verbose("Local/201@extensions-7cf4;2", "2,Inside channel:
Local/201@extensions-7cf4;2") in new stack
== Inside channel: Local/201@extensions-7cf4;2
\end{verbatim}
\end{astlisting}
Here we use the Verbose() application to see what our current channel name is.
As you can see the current channel is a Local channel which we created from our
SIP channel.
\begin{astlisting}
\begin{verbatim}
-- Executing [201@extensions:3] Dial("Local/201@extensions-7cf4;2", "SIP/some-named-extension,30") in new stack
\end{verbatim}
\end{astlisting}
And from here, we're using another Dial() application to call a SIP device
configured in sip.conf as [some-named-extension].
Now that we understand a simple example of calling the Local channel, let's
expand upon this example by using Local channels to call two devices at the same
time, but delay calling one of the devices.
\subsection{Delay dialing devices}
Lets say when someone calls extension 201, we want to ring both the desk phone
and their cellphone at the same time, but we want to wait about 6 seconds to
start dialing the cellphone. This is useful in a situation when someone might be
sitting at their desk, but don't want both devices ringing at the same time, but
also doesn't want to wait for the full ring cycle to execute on their desk phone
before rolling over to their cellphone.
The dialplan for this would look something like the following:
\begin{astlisting}
\begin{verbatim}
[devices]
exten => 201,1,Verbose(2,Call desk phone and cellphone but with delay)
exten => 201,n,Dial(Local/deskphone-201@extensions&Local/cellphone-201@extensions,30)
exten => 201,n,Voicemail(201@default,${IF($[${DIALSTATUS} = BUSY]?b:u)})
exten => 201,n,Hangup()
[extensions]
; Dial the desk phone
exten => deskphone-201,1,Verbose(2,Dialing desk phone of extension 201)
exten => deskphone-201,n,Dial(SIP/0004f2040001) ; SIP device with MAC address
; of 0004f2040001
; Dial the cellphone
exten => cellphone-201,1,Verbose(2,Dialing cellphone of extension 201)
exten => cellphone-201,n,Verbose(2,-- Waiting 6 seconds before dialing)
exten => cellphone-201,n,Wait(6)
exten => cellphone-201,n,Dial(DAHDI/g0/14165551212)
\end{verbatim}
\end{astlisting}
When someone dials extension 201 in the [devices] context, it will execute the
Dial() application, and call two Local channels at the same time:
\begin{itemize}
\item Local/deskphone-201@extensions
\item Local/cellphone-201@extensions
\end{itemize}
It will then ring both of those extensions for 30 seconds before rolling over to
the Voicemail() application and playing the appropriate voicemail recording
depending on whether the \$\{DIALSTATUS\} variable returned BUSY or not.
When reaching the deskphone-201 extension, we execute the Dial() application
which calls the SIP device configured as '0004f204001' (the MAC address of the
device). When reaching the cellphone-201 extension, we dial the cellphone via
the DAHDI channel using group zero (g0) and dialing phone number 1-416-555-1212.
\subsection{Dialing destinations with different information}
With Asterisk, we can place a call to multiple destinations by separating the
technology/destination pair with an ampersand (\&). For example, the following
Dial() line would ring two separate destinations for 30 seconds:
\begin{astlisting}
\begin{verbatim}
exten => 201,1,Dial(SIP/0004f2040001&DAHDI/g0/14165551212,30)
\end{verbatim}
\end{astlisting}
That line would dial both the SIP/0004f2040001 device (likely a SIP device on
the network) and dial the phone number 1-416-555-1212 via a DAHDI interface. In
our example though, we would be sending the same callerID information to both
end points, but perhaps we want to send a different callerID to one of the
destinations?
We can send different callerIDs to each of the destinations if we want by using
the Local channel. The following example shows how this is possible because we
would Dial() two different Local channels from our top level Dial(), and that
would then execute some dialplan before sending the call off to the final
destinations.
\begin{astlisting}
\begin{verbatim}
[devices]
exten => 201,1,NoOp()
exten => 201,n,Dial(Local/201@internal&Local/201@external,30)
exten => 201,n,Voicemail(201@default,${IF($[${DIALSTATUS} = BUSY]?b:u)})
exten => 201,n,Hangup()
[internal]
exten => 201,1,Verbose(2,Placing internal call for extension 201)
exten => 201,n,Set(CALLERID(name)=From Sales)
exten => 201,n,Dial(SIP/0004f2040001,30)
[external]
exten => 201,1,Verbose(2,Placing external call for extension 201)
exten => 201,n,Set(CALLERID(name)=Acme Cleaning)
exten => 201,n,Dial(DAHDI/g0/14165551212)
\end{verbatim}
\end{astlisting}
With the dialplan above, we've sent two different callerIDs to the destinations:
\begin{itemize}
\item "From Sales" was sent to the local device SIP/0004f2040001
\item "Acme Cleaning" was sent to the remote number 1-416-555-1212 via DAHDI
\end{itemize}
Because each of the channels is independent from the other, you could perform
any other call manipulation you need. Perhaps the 1-416-555-1212 number is a
cell phone and you know you can only ring that device for 18 seconds before the
voicemail would pick up. You could then limit the length of time the external
number is dialed, but still allow the internal device to be dialed for a longer
period of time.
\subsection{Using callfiles and Local channels}
Another example is to use callfiles and Local channels so that you can execute
some dialplan prior to performing a Dial(). We'll construct a callfile which
will then utilize a Local channel to lookup a bit of information in the AstDB
and then place a call via the channel configured in the AstDB.
First, lets construct our callfile that will use the Local channel to do some
lookups prior to placing our call. More information on constructing callfiles is
located in the doc/callfiles.txt file of your Asterisk source.
Our callfile will simply look like the following:
\begin{verbatim}
Channel: Local/201@devices
Application: Playback
Data: silence/1&tt-weasels
\end{verbatim}
Add the callfile information to a file such as 'callfile.new' or some other
appropriately named file.
Our dialplan will perform a lookup in the AstDB to determine which device to
call, and will then call the device, and upon answer, Playback() the silence/1
(1 second of silence) and the tt-weasels sound files.
Before looking at our dialplan, lets put some data into AstDB that we can then
lookup from the dialplan. From the Asterisk CLI, run the following command:
\begin{verbatim}
*CLI> database put phones 201/device SIP/0004f2040001
\end{verbatim}
We've now put the device destination (SIP/0004f2040001) into the 201/device key
within the phones family. This will allow us to lookup the device location for
extension 201 from the database.
We can then verify our entry in the database using the 'database show' CLI
command:
\begin{verbatim}
*CLI> database show
/phones/201/device : SIP/0004f2040001
\end{verbatim}
Now lets create the dialplan that will allow us to call SIP/0004f2040001 when we
request extension 201 from the [extensions] context via our Local channel.
\begin{astlisting}
\begin{verbatim}
[devices]
exten => 201,1,NoOp()
exten => 201,n,Set(DEVICE=${DB(phones/${EXTEN}/device)})
exten => 201,n,GotoIf($[${ISNULL(${DEVICE})}]?hangup) ; if nothing returned,
; then hangup
exten => 201,n,Dial(${DEVICE},30)
exten => 201,n(hangup(),Hangup()
\end{verbatim}
\end{astlisting}
Then, we can perform a call to our device using the callfile by moving it into
the /var/spool/asterisk/outgoing/ directory.
\begin{verbatim}
# mv callfile.new /var/spool/asterisks/outgoing
\end{verbatim}
Then after a moment, you should see output on your console similar to the
following, and your device ringing. Information about what is going on during
the output has also been added throughout.
\begin{astlisting}
\begin{verbatim}
-- Attempting call on Local/201@devices for application Playback(silence/1&tt-weasels) (Retry 1)
\end{verbatim}
\end{astlisting}
You'll see the line above as soon as Asterisk gets the request from the
callfile.
\begin{astlisting}
\begin{verbatim}
-- Executing [201@devices:1] NoOp("Local/201@devices-ecf0;2", "") in new stack
-- Executing [201@devices:2] Set("Local/201@devices-ecf0;2", "DEVICE=SIP/0004f2040001") in new stack
\end{verbatim}
\end{astlisting}
This is where we performed our lookup in the AstDB. The value of
SIP/0004f2040001 was then returned and saved to the DEVICE channel variable.
\begin{astlisting}
\begin{verbatim}
-- Executing [201@devices:3] GotoIf("Local/201@devices-ecf0;2", "0?hangup") in new stack
\end{verbatim}
\end{astlisting}
We perform a check to make sure \$\{DEVICE\} isn't NULL. If it is, we'll just
hangup here.
\begin{astlisting}
\begin{verbatim}
-- Executing [201@devices:4] Dial("Local/201@devices-ecf0;2", "SIP/0004f2040001,30") in new stack
-- Called 000f2040001
-- SIP/0004f2040001-00000022 is ringing
\end{verbatim}
\end{astlisting}
Now we call our device SIP/0004f2040001 from the Local channel.
\begin{verbatim}
-- SIP/0004f2040001-00000022 answered Local/201@devices-ecf0;2
\end{verbatim}
We answer the call.
\begin{astlisting}
\begin{verbatim}
> Channel Local/201@devices-ecf0;1 was answered.
> Launching Playback(silence/1&tt-weasels) on Local/201@devices-ecf0;1
\end{verbatim}
\end{astlisting}
We then start playing back the files.
\begin{astlisting}
\begin{verbatim}
-- <Local/201@devices-ecf0;1> Playing 'silence/1.slin' (language 'en')
== Spawn extension (devices, 201, 4) exited non-zero on 'Local/201@devices-ecf0;2'
\end{verbatim}
\end{astlisting}
At this point we now see the Local channel has been optimized out of the call
path. This is important as we'll see in examples later. By default, the Local
channel will try to optimize itself out of the call path as soon as it can. Now
that the call has been established and audio is flowing, it gets out of the way.
\begin{astlisting}
\begin{verbatim}
-- <SIP/0004f2040001-00000022> Playing 'tt-weasels.ulaw' (language 'en')
[Mar 1 13:35:23] NOTICE[16814]: pbx_spool.c:349 attempt_thread: Call completed to Local/201@devices
\end{verbatim}
\end{astlisting}
We can now see the tt-weasels file is played directly to the destination
(instead of through the Local channel which was optimized out of the call path)
and then a NOTICE stating the call was completed.
\subsection{Understanding When To Use /n}
Lets take a look at an example that demonstrates when the use of the /n
directive is necessary. If we spawn a Local channel which does a Dial()
to a SIP channel, but we use the L() option (which is used to limit the
amount of time a call can be active, along with warning tones when the
time is nearly up), it will be associated with the Local channel,
which is then optimized out of the call path, and thus won't perform
as expected.
This following dialplan will not perform as expected.
\begin{verbatim}
[services]
exten => 2,1,Dial(SIP/PHONE\_B,,L(60000:45000:15000))
[internal]
exten => 4,1,Dial(Local/2@services)
\end{verbatim}
By default, the Local channel will try to optimize itself out of the call path.
This means that once the Local channel has established the call between the
destination and Asterisk, the Local channel will get out of the way and let
Asterisk and the end point talk directly, instead of flowing through the Local
channel.
This can have some adverse effects when you're expecting information to be
available during the call that gets associated with the Local channel. When the
Local channel is optimized out of the call path, any Dial() flags, or channel
variables associated with the Local channel are also destroyed and are no longer
available to Asterisk.
We can force the Local channel to remain in the call path by utilizing the /n
directive. By adding /n to the end of the channel definition, we can keep the
Local channel in the call path, along with any channel variables, or other
channel specific information.
In order to make this behave as we expect (limiting the call), we would change:
\begin{verbatim}
[internal]
exten => 4,1,Dial(Local/2@services)
\end{verbatim}
...into the following:
\begin{verbatim}
[internal]
exten => 4,1,Dial(Local/2@services/n)
\end{verbatim}
By adding /n to the end, our Local channel will now stay in the call path and
not go away.
Why does adding the /n option all of a suddon make the 'L' option work? First
we need to show an overview of the call flow that doesn't work properly, and
discuss the information associated with the channels:
\begin{enumerate}
\item SIP device PHONE\_A calls Asterisk via a SIP INVITE
\item Asterisk accepts the INVITE and then starts processing dialplan logic in the [internal] context
\item Our dialplan calls Dial(Local/2@services) -- notice no /n
\item The Local channel then executes dialplan at extension 2 within the [services] context
\item Extension 2 within [services] then performs Dial() to PHONE\_B with the line: Dial(SIP/PHONE\_B,,L(60000:45000:15000))
\item SIP/PHONE\_B then answers the call
\item Even though the L option was given when dialing the SIP device, the L information is stored in the channel that is doing the Dial() which is the Local channel, and not the endpoint SIP channel.
\item The Local channel in the middle, containing the information for tracking the time allowance of the call, is then optimized out of the call path, losing all information about when to terminate the call.
\item SIP/PHONE\_A and SIP/PHONE\_B then continue talking indefinitely.
\end{enumerate}
Now, if we were to add /n to our dialplan at step three (3) then we would force the
Local channel to stay in the call path, and the L() option associated with the
Dial() from the Local channel would remain, and our warning sounds and timing
would work as expected.
There are two workarounds for the above described scenario:
\begin{enumerate}
\item Use what we just described, Dial(Local/2@services/n) to cause the Local
channel to remain in the call path so that the L() option used inside the
Local channel is not discarded when optimization is performed.
\item Place the L() option at the outermost part of the path so that when the middle
is optimized out of the call path, the information required to make L() work
is associated with the outside channel. The L information will then be stored
on the calling channel, which is PHONE\_A. For example:
\begin{verbatim}
[services]
exten => 2,1,Dial(SIP/PHONE_B)
[internal]
exten => 4,1,Dial(Local/2@services,,L(60000:45000:15000));
\end{verbatim}
\end{enumerate}
\subsection{Local channel modifiers}
There are additional modifiers for the Local channel as well. They include:
\begin{itemize}
\item 'n' -- Adding "/n" at the end of the string will make the Local channel not
do a native transfer (the "n" stands for "n"o release) upon the remote
end answering the line. This is an esoteric, but important feature if
you expect the Local channel to handle calls exactly like a normal
channel. If you do not have the "no release" feature set, then as soon
as the destination (inside of the Local channel) answers the line and
one audio frame passes, the variables and dial plan will revert back
to that of the original call, and the Local channel will become a
zombie and be removed from the active channels list. This is desirable
in some circumstances, but can result in unexpected dialplan behavior
if you are doing fancy things with variables in your call handling.
\item 'j' -- Adding "/j" at the end of the string allows you to use the generic
jitterbuffer on incoming calls going to Asterisk applications. For
example, this would allow you to use a jitterbuffer for an incoming
SIP call to Voicemail by putting a Local channel in the middle. The
'j' option must be used in conjunction with the 'n' option to make
sure that the Local channel does not get optimized out of the call.
This option is available starting in the Asterisk 1.6.0 branch.
\item 'm' -- Using the "/m" option will cause the Local channel to forward music on
hold (MoH) start and stop requests. Normally the Local channel acts on
them and it is started or stopped on the Local channel itself. This
options allows those requests to be forwarded through the Local
channel.
This option is available starting in the Asterisk 1.4 branch.
\item 'b' -- The "/b" option causes the Local channel to return the actual channel
that is behind it when queried. This is useful for transfer scenarios
as the actual channel will be transferred, not the Local channel.
This option is available starting in the Asterisk 1.6.0 branch.
\end{itemize}

View File

@ -1,274 +0,0 @@
\section{The Asterisk Manager TCP/IP API}
The manager is a client/server model over TCP. With the manager interface,
you'll be able to control the PBX, originate calls, check mailbox status,
monitor channels and queues as well as execute Asterisk commands.
AMI is the standard management interface into your Asterisk server.
You configure AMI in manager.conf. By default, AMI is available on
TCP port 5038 if you enable it in manager.conf.
AMI receive commands, called "actions". These generate a "response"
from Asterisk. Asterisk will also send "Events" containing various
information messages about changes within Asterisk. Some actions
generate an initial response and data in the form list of events.
This format is created to make sure that extensive reports do not
block the manager interface fully.
Management users are configured in the configuration file manager.conf and are
given permissions for read and write, where write represents their ability
to perform this class of "action", and read represents their ability to
receive this class of "event".
If you develop AMI applications, treat the headers
in Actions, Events and Responses as local to that particular
message. There is no cross-message standardization of headers.
If you develop applications, please try to reuse existing manager
headers and their interpretation. If you are unsure, discuss on
the asterisk-dev mailing list.
Manager subscribes to extension status reports from all channels,
to be able to generate events when an extension or device changes
state. The level of details in these events may depend on the channel
and device configuration. Please check each channel configuration
file for more information. (in sip.conf, check the section on
subscriptions and call limits)
\section{Command Syntax}
Management communication consists of tags of the form "header: value",
terminated with an empty newline (\textbackslash r\textbackslash n) in
the style of SMTP, HTTP, and other headers.
The first tag MUST be one of the following:
\begin{itemize}
\item Action: An action requested by the CLIENT to the Asterisk SERVER.
Only one "Action" may be outstanding at any time.
\item Response: A response to an action from the Asterisk SERVER to the CLIENT.
\item Event: An event reported by the Asterisk SERVER to the CLIENT
\end{itemize}
\section{Manager commands}
To see all of the available manager commands, use the "manager show commands"
CLI command.
You can get more information about a manager command
with the "manager show command $<$command$>$" CLI command in Asterisk.
\section{Examples}
Login - Log a user into the manager interface.
\begin{verbatim}
Action: Login
Username: testuser
Secret: testsecret
\end{verbatim}
Originate - Originate a call from a channel to an extension.
\begin{verbatim}
Action: Originate
Channel: sip/12345
Exten: 1234
Context: default
\end{verbatim}
Originate - Originate a call from a channel to an extension without waiting
for call to complete.
\begin{verbatim}
Action: Originate
Channel: sip/12345
Exten: 1234
Context: default
Async: yes
\end{verbatim}
Redirect with ExtraChannel:
Attempted goal:
Have a 'robot' program Redirect both ends of an already-connected call
to a meetme room using the ExtraChannel feature through the management interface.
\begin{verbatim}
Action: Redirect
Channel: DAHDI/1-1
ExtraChannel: SIP/3064-7e00 (varies)
Exten: 680
Priority: 1
\end{verbatim}
Where 680 is an extension that sends you to a MeetMe room.
There are a number of GUI tools that use the manager interface, please search
the mailing list archives and the documentation page on the
\url{http://www.asterisk.org} web site for more information.
\section{Ensuring all modules are loaded}
It is possible to connect to the manager interface before all Asterisk modules
are loaded. To ensure that an application does not send AMI actions that might
require a module that has not yet loaded, the application can listen for the
FullyBooted manager event. It will be sent upon connection if all modules have
been loaded, or as soon as loading is complete. The event:
\begin{verbatim}
Event: FullyBooted
Privilege: system,all
Status: Fully Booted
\end{verbatim}
\section{Device status reports}
\section{Some standard AMI headers}
\begin{verbatim}
Account: -- Account Code (Status)
AccountCode: -- Account Code (cdr_manager)
ACL: <Y | N> -- Does ACL exist for object ?
Action: <action> -- Request or notification of a particular action
Address-IP: -- IPaddress
Address-Port: -- IP port number
Agent: <string> -- Agent name
AMAflags: -- AMA flag (cdr_manager, sippeers)
AnswerTime: -- Time of answer (cdr_manager)
Append: <bool> -- CDR userfield Append flag
Application: -- Application to use
Async: -- Whether or not to use fast setup
AuthType: -- Authentication type (for login or challenge)
"md5"
BillableSeconds: -- Billable seconds for call (cdr_manager)
CallerID: -- Caller id (name and number in Originate & cdr_manager)
CallerID: -- CallerID number
Number or "<unknown>" or "unknown"
(should change to "<unknown>" in app_queue)
CallerID1: -- Channel 1 CallerID (Link event)
CallerID2: -- Channel 2 CallerID (Link event)
CallerIDName: -- CallerID name
Name or "<unknown>" or "unknown"
(should change to "<unknown>" in app_queue)
Callgroup: -- Call group for peer/user
CallsTaken: <num> -- Queue status variable
Cause: <value> -- Event change cause - "Expired"
Cause: <value> -- Hangupcause (channel.c)
CID-CallingPres: -- Caller ID calling presentation
Channel: <channel> -- Channel specifier
Channel: <dialstring> -- Dialstring in Originate
Channel: <tech/[peer/username]> -- Channel in Registry events (SIP, IAX2)
Channel: <tech> -- Technology (SIP/IAX2 etc) in Registry events
ChannelType: -- Tech: SIP, IAX2, DAHDI, MGCP etc
Channel1: -- Link channel 1
Channel2: -- Link channel 2
ChanObjectType: -- "peer", "user"
Codecs: -- Codec list
CodecOrder: -- Codec order, separated with comma ","
Command: -- Cli command to run
Context: -- Context
Count: <num> -- Number of callers in queue
Data: -- Application data
Default-addr-IP: -- IP address to use before registration
Default-Username: -- Username part of URI to use before registration
Destination: -- Destination for call (Dialstring ) (dial, cdr_manager)
DestinationContext: -- Destination context (cdr_manager)
DestinationChannel: -- Destination channel (cdr_manager)
DestUniqueID: -- UniqueID of destination (dial event)
Direction: <type> -- Audio to mute (read | write | both)
Disposition: -- Call disposition (CDR manager)
Domain: <domain> -- DNS domain
Duration: <secs> -- Duration of call (cdr_manager)
Dynamic: <Y | N> -- Device registration supported?
Endtime: -- End time stamp of call (cdr_manager)
EventList: <flag> -- Flag being "Start", "End", "Cancelled" or "ListObject"
Events: <eventmask> -- Eventmask filter ("on", "off", "system", "call", "log")
Exten: -- Extension (Redirect command)
Extension: -- Extension (Status)
Family: <string> -- ASTdb key family
File: <filename> -- Filename (monitor)
Format: <format> -- Format of sound file (monitor)
From: <time> -- Parking time (ParkedCall event)
Hint: -- Extension hint
Incominglimit: -- SIP Peer incoming limit
Key:
Key: -- ASTdb Database key
LastApplication: -- Last application executed (cdr_manager)
LastCall: <num> -- Last call in queue
LastData: -- Data for last application (cdr_manager)
Link: -- (Status)
ListItems: <number> -- Number of items in Eventlist (Optionally sent in "end" packet)
Location: -- Interface (whatever that is -maybe tech/name in app_queue )
Loginchan: -- Login channel for agent
Logintime: <number> -- Login time for agent
Mailbox: -- VM Mailbox (id@vmcontext) (mailboxstatus, mailboxcount)
MD5SecretExist: <Y | N> -- Whether secret exists in MD5 format
Membership: <string> -- "Dynamic" or "static" member in queue
Message: <text> -- Text message in ACKs, errors (explanation)
Mix: <bool> -- Boolean parameter (monitor)
MOHSuggest: -- Suggested music on hold class for peer (mohsuggest)
NewMessages: <count> -- Count of new Mailbox messages (mailboxcount)
Newname:
ObjectName: -- Name of object in list
OldName: -- Something in Rename (channel.c)
OldMessages: <count> -- Count of old mailbox messages (mailboxcount)
Outgoinglimit: -- SIP Peer outgoing limit
Paused: <num> -- Queue member paused status
Peer: <tech/name> -- "channel" specifier :-)
PeerStatus: <tech/name> -- Peer status code
"Unregistered", "Registered", "Lagged", "Reachable"
Penalty: <num> -- Queue penalty
Priority: -- Extension priority
Privilege: <privilege> -- AMI authorization class (system, call, log, verbose, command, agent, user)
Pickupgroup: -- Pickup group for peer
Position: <num> -- Position in Queue
Queue: -- Queue name
Reason: -- "Autologoff"
Reason: -- "Chanunavail"
Response: <response> -- response code, like "200 OK"
"Success", "Error", "Follows"
Restart: -- "True", "False"
RegExpire: -- SIP registry expire
RegExpiry: -- SIP registry expiry
Reason: -- Originate reason code
Seconds: -- Seconds (Status)
Secret: <password> -- Authentication secret (for login)
SecretExist: <Y | N> -- Whether secret exists
Shutdown: -- "Uncleanly", "Cleanly"
SIP-AuthInsecure:
SIP-FromDomain: -- Peer FromDomain
SIP-FromUser: -- Peer FromUser
SIP-NatSupport:
SIPLastMsg:
Source: -- Source of call (dial event, cdr_manager)
SrcUniqueID: -- UniqueID of source (dial event)
StartTime: -- Start time of call (cdr_manager)
State: -- Channel state
State: <1 | 0> -- Mute flag
Status: -- Registration status (Registry events SIP)
Status: -- Extension status (Extensionstate)
Status: -- Peer status (if monitored) ** Will change name **
"unknown", "lagged", "ok"
Status: <num> -- Queue Status
Status: -- DND status (DNDState)
Time: <sec> -- Roundtrip time (latency)
Timeout: -- Parking timeout time
Timeout: -- Timeout for call setup (Originate)
Timeout: <seconds> -- Timeout for call
Uniqueid: -- Channel Unique ID
Uniqueid1: -- Channel 1 Unique ID (Link event)
Uniqueid2: -- Channel 2 Unique ID (Link event)
User: -- Username (SIP registry)
UserField: -- CDR userfield (cdr_manager)
Val: -- Value to set/read in ASTdb
Variable: -- Variable AND value to set (multiple separated with | in Originate)
Variable: <name> -- For channel variables
Value: <value> -- Value to set
VoiceMailbox: -- VM Mailbox in SIPpeers
Waiting: -- Count of mailbox messages (mailboxstatus)
\end{verbatim}
** Please try to re-use existing headers to simplify manager message parsing in clients.
Read the CODING-GUIDELINES if you develop new manager commands or events.

View File

@ -1,282 +0,0 @@
\subsection{Introduction}
This package contains the mISDN Channel Driver for the Asterisk PBX. It
supports every mISDN Hardware and provides an interface for Asterisk.
\subsection{Features}
\begin{itemize}
\item NT and TE mode
\item PP and PMP mode
\item BRI and PRI (with BNE1 and BN2E1 Cards)
\item Hardware bridging
\item DTMF detection in HW+mISDNdsp
\item Display messages on phones (on those that support it)
\item app\_SendText
\item HOLD/RETRIEVE/TRANSFER on ISDN phones : )
\item Allow/restrict user number presentation
\item Volume control
\item Crypting with mISDNdsp (Blowfish)
\item Data (HDLC) callthrough
\item Data calling (with app\_ptyfork +pppd)
\item Echo cancellation
\item Call deflection
\item Some others
\end{itemize}
\subsection{Fast Installation Guide}
It is easy to install mISDN and mISDNuser. This can be done by:
\begin{itemize}
\item You can download latest stable releases from \url{http://www.misdn.org/downloads/}
\item Just fetch the newest head of the GIT (mISDN project moved from CVS)
In details this process described here: \url{http://www.misdn.org/index.php/GIT}
\end{itemize}
then compile and install both with:
\begin{astlisting}
\begin{verbatim}
cd mISDN ;
make && make install
\end{verbatim}
\end{astlisting}
(you will need at least your kernel headers to compile mISDN).
\begin{astlisting}
\begin{verbatim}
cd mISDNuser ;
make && make install
\end{verbatim}
\end{astlisting}
Now you can compile chan\_misdn, just by making Asterisk:
\begin{astlisting}
\begin{verbatim}
cd asterisk ;
./configure && make && make install
\end{verbatim}
\end{astlisting}
That's all!
Follow the instructions in the mISDN Package for how to load the Kernel
Modules. Also install process described in \url{http://www.misdn.org/index.php/Installing_mISDN}
\subsection{Pre-Requisites}
To compile and install this driver, you'll need at least one mISDN Driver and
the mISDNuser package. Chan\_misdn works with both, the current release version
and the development (svn trunk) version of Asterisk.
You should use Kernels $>$= 2.6.9
\subsection{Configuration}
First of all you must configure the mISDN drivers, please follow the
instructions in the mISDN package to do that, the main config file and config
script is:
\begin{astlisting}
\begin{verbatim}
/etc/init.d/misdn-init and
/etc/misdn-init.conf
\end{verbatim}
\end{astlisting}
Now you will want to configure the misdn.conf file which resides in the
Asterisk config directory (normally /etc/asterisk).
\subsubsection{misdn.conf: [general]}
The misdn.conf file contains a "general" subsection, and user subsections which
contain misdn port settings and different Asterisk contexts.
In the general subsection you can set options that are not directly port
related. There is for example the very important debug variable which you can
set from the Asterisk cli (command line interface) or in this configuration
file, bigger numbers will lead to more debug output. There's also a trace file
option, which takes a path+filename where debug output is written to.
\subsubsection{misdn.conf: [default] subsection}
The default subsection is another special subsection which can contain all the
options available in the user/port subsections. The user/port subsections inherit
their parameters from the default subsection.
\subsubsection{misdn.conf: user/port subsections}
The user subsections have names which are unequal to "general". Those subsections
contain the ports variable which mean the mISDN Ports. Here you can add
multiple ports, comma separated.
Especially for TE-Mode Ports there is a msns option. This option tells the
chan\_misdn driver to listen for incoming calls with the given msns, you can
insert a '*' as single msn, which leads to getting every incoming call. If you
want to share on PMP TE S0 with Asterisk and a phone or ISDN card you should
insert here the msns which you assign to Asterisk. Finally a context variable
resides in the user subsections, which tells chan\_misdn where to send incoming
calls to in the Asterisk dial plan (extension.conf).
\subsubsection{Dial and Options String}
The dial string of chan\_misdn got more complex, because we added more features,
so the generic dial string looks like:
\begin{astlisting}
\begin{verbatim}
mISDN/<port>[:bchannel]|g:<group>/<extension>[/<OPTIONSSTRING>]
The Optionsstring looks Like:
:<optchar><optarg>:<optchar><optarg>...
the ":" character is the delimiter.
The available options are:
a - Have Asterisk detect DTMF tones on called channel
c - Make crypted outgoing call, optarg is keyindex
d - Send display text to called phone, text is the optarg
e - Perform echo cancelation on this channel,
takes taps as optarg (32,64,128,256)
e! - Disable echo cancelation on this channel
f - Enable fax detection
h - Make digital outgoing call
h1 - Make HDLC mode digital outgoing call
i - Ignore detected DTMF tones, don't signal them to Asterisk,
they will be transported inband.
jb - Set jitter buffer length, optarg is length
jt - Set jitter buffer upper threshold, optarg is threshold
jn - Disable jitter buffer
n - Disable mISDN DSP on channel.
Disables: echo cancel, DTMF detection, and volume control.
p - Caller ID presentation,
optarg is either 'allowed' or 'restricted'
s - Send Non-inband DTMF as inband
vr - Rx gain control, optarg is gain
vt - Tx gain control, optarg is gain
\end{verbatim}
\end{astlisting}
chan\_misdn registers a new dial plan application "misdn\_set\_opt" when
loaded. This application takes the Optionsstring as argument. The Syntax is:
\begin{verbatim}
misdn_set_opt(<OPTIONSSTRING>)
\end{verbatim}
When you set options in the dialstring, the options are set in the external
channel. When you set options with misdn\_set\_opt, they are set in the current
incoming channel. So if you like to use static encryption, the scenario looks
as follows:
\begin{verbatim}
Phone1 --> * Box 1 --> PSTN_TE
PSTN_TE --> * Box 2 --> Phone2
\end{verbatim}
The encryption must be done on the PSTN sides, so the dialplan on the boxes
are:
\begin{verbatim}
* Box 1:
exten => _${CRYPT_PREFIX}X.,1,Dial(mISDN/g:outbound/:c1)
* Box 2:
exten => ${CRYPT_MSN},1,misdn_set_opt(:c1)
exten => ${CRYPT_MSN},2,dial(${PHONE2})
\end{verbatim}
\subsection{mISDN CLI commands}
At the Asterisk cli you can try to type in:
\begin{verbatim}
misdn <tab> <tab>
\end{verbatim}
Now you should see the misdn cli commands:
\begin{astlisting}
\begin{verbatim}
- clean
-> pid (cleans a broken call, use with care, leads often
to a segmentation fault)
- send
-> display (sends a Text Message to a Asterisk channel,
this channel must be an misdn channel)
- set
-> debug (sets debug level)
- show
-> config (shows the configuration options)
-> channels (shows the current active misdn channels)
-> channel (shows details about the given misdn channels)
-> stacks (shows the current ports, their protocols and states)
-> fullstacks (shows the current active and inactive misdn channels)
- restart
-> port (restarts given port (L2 Restart) )
- reload (reloads misdn.conf)
\end{verbatim}
\end{astlisting}
You can only use "misdn send display" when an Asterisk channel is created and
isdn is in the correct state. "correct state" means that you have established a
call to another phone (must not be isdn though).
Then you use it like this:
misdn send display mISDN/1/101 "Hello World!"
where 1 is the Port of the Card where the phone is plugged in, and 101 is the
msn (callerid) of the Phone to send the text to.
\subsection{mISDN Variables}
mISDN Exports/Imports a few Variables:
\begin{verbatim}
- MISDN_ADDRESS_COMPLETE : Is either set to 1 from the Provider, or you
can set it to 1 to force a sending complete.
\end{verbatim}
\subsection{Debugging and sending bug reports}
If you encounter problems, you should set up the debugging flag, usually
debug=2 should be enough. The messages are divided into Asterisk and mISDN
parts. mISDN Debug messages begin with an 'I', Asterisk messages begin with
an '*', the rest is clear I think.
Please take a trace of the problem and open a report in the Asterisk issue
tracker at \url{https://issues.asterisk.org} in the "channel drivers" project,
"chan\_misdn" category. Read the bug guidelines to make sure you
provide all the information needed.
\subsection{Examples}
Here are some examples of how to use chan\_misdn in the dialplan
(extensions.conf):
\begin{astlisting}
\begin{verbatim}
[globals]
OUT_PORT=1 ; The physical Port of the Card
OUT_GROUP=ExternE1 ; The Group of Ports defined in misdn.conf
[misdnIn]
exten => _X.,1,Dial(mISDN/${OUT_PORT}/${EXTEN})
exten => _0X.,1,Dial(mISDN/g:${OUT_GROUP}/${EXTEN:1})
exten => _1X.,1,Dial(mISDN/g:${OUT_GROUP}/${EXTEN:1}/:dHello)
exten => _1X.,1,Dial(mISDN/g:${OUT_GROUP}/${EXTEN:1}/:dHello Test:n)
\end{verbatim}
\end{astlisting}
On the last line, you will notice the last argument (Hello); this is sent
as Display Message to the Phone.
\subsection{Known Problems}
Q: I cannot hear any tone after a successful CONNECT to the other end.
A: You forgot to load mISDNdsp, which is now needed by chan\_misdn for switching
and DTMF tone detection.

View File

@ -1,11 +0,0 @@
\subsubsection{MP3 Music On Hold}
Use of the mpg123 for your music on hold is no longer recommended and is now
officially deprecated. You should now use one of the native formats for your
music on hold selections.
However, if you still need to use mp3 as your music on hold format, a format
driver for reading MP3 audio files is available in the asterisk-addons SVN
repository on svn.digium.com or in the asterisk-addons release at
\url{http://downloads.asterisk.org/pub/telephony/asterisk/}.

View File

@ -1,34 +0,0 @@
ODBC Storage allows you to store voicemail messages within a database
instead of using a file. This is \textbf{not} a full realtime engine and
\textbf{only} supports ODBC. The table description for the \texttt{voicemessages}
table is as follows:
\begin{table}[h]
\begin{center}
\begin{tabular}{ | l | l | c | c | l | l | }
\hline
Field & Type & Null & Key & Default & Extra \\ \hline \hline
msgnum & int(11) & Yes & & NULL & \\ \hline
dir & varchar(80) & Yes & MUL & NULL & \\ \hline
context & varchar(80) & Yes & & NULL & \\ \hline
macrocontext & varchar(80) & Yes & & NULL & \\ \hline
callerid & varchar(40) & Yes & & NULL & \\ \hline
origtime & varchar(40) & Yes & & NULL & \\ \hline
duration & varchar(20) & Yes & & NULL & \\ \hline
flag & varchar(8) & Yes & & NULL & \\ \hline
mailboxuser & varchar(80) & Yes & & NULL & \\ \hline
mailboxcontext & varchar(80) & Yes & & NULL & \\ \hline
recording & longblob & Yes & & NULL & \\
\hline
\end{tabular}
\end{center}
\caption{\texttt{voicemessages} Table Schema}
\end{table}
The database name (from \path{/etc/asterisk/res_odbc.conf}) is in the
\texttt{odbcstorage} variable in the general section of \path{voicemail.conf}.
You may modify the \texttt{voicemessages} table name by using
\texttt{odbctable=\textit{table\_name}} in \path{voicemail.conf}.

View File

@ -1,331 +0,0 @@
\section{Introduction}
This chapter aims to explain how to use some of the features available to
manipulate party ID information. It will not delve into specific channel
configuration options described in the respective sample configuration
files. The party ID information can consist of Caller ID, Connected Line
ID, redirecting to party ID information, and redirecting from party ID
information. Meticulous control is needed particularly when
interoperating between different channel technologies.
\begin{itemize}
\item Caller ID: The Caller ID information describes who is originating a
call.
\item Connected Line ID: The Connected Line ID information describes who
is connected to the other end of a call while a call is established.
Unlike Caller ID, the connected line information can change over the life
of a call when call transfers are performed. The connected line
information can also change in either direction because either end could
transfer the call. For ISDN it is known as Connected Line Identification
Presentation (COLP), Connected Line Identification Restriction (COLR), and
Explicit Call Transfer (ECT). For SIP it is known either as
P-Asserted-Identity or Remote-Party-Id.
\item Redirecting information: When a call is forwarded, the call
originator is informed that the call is redirecting-to a new destination.
The new destination is also informed that the incoming call is
redirecting-from the forwarding party. A call can be forwarded repeatedly
until a new destination answers it or a forwarding limit is reached.
\end{itemize}
\section{Tools available}
Asterisk contains several tools for manipulating the party ID information
for a call. Additional information can be found by using the 'core show
function' or 'core show application' console commands at the Asterisk CLI.
The following list identifies some of the more common tools for
manipulating the party ID information:
\begin{itemize}
\item CALLERID(datatype[,caller-id])
\item CONNECTEDLINE(datatype[,i])
\item REDIRECTING(datatype[,i])
\item Dial() and Queue() dialplan application 'I' option
\item Interception macros
\item Channel driver specific configuration options.
\end{itemize}
\subsection{CALLERID dialplan function}
The CALLERID function has been around for quite a while and its use is
straightforward. It is used to examine and alter the caller information
that came into the dialplan with the call. Then the call with it's caller
information passes on to the destination using the Dial() or Queue()
application.
The CALLERID information is passed during the initial call setup.
However, depending on the channel technology, the caller name may be
delayed. Q.SIG is an example where the caller name may be delayed so your
dialplan may need to wait for it.
\subsection{CONNECTEDLINE dialplan function}
The CONNECTEDLINE function does the opposite of the CALLERID function.
CONNECTEDLINE can be used to setup connected line information to be sent when the
call is answered. You can use it to send new connected line information
to the remote party on the channel when a call is transferred. The
CONNECTEDLINE information is passed when the call is answered and when the
call is transferred.
Since the connected line information can be sent while a call is
connected, you may need to prevent the channel driver from acting on a
partial update. The 'i' option is used to inhibit the channel driver from
sending the changed information immediately.
\subsection{REDIRECTING dialplan function}
The REDIRECTING function allows you to report information about
forwarded/deflected calls to the caller and to the new destination. The
use of the REDIRECTING function is the most complicated of the party
information functions.
The REDIRECTING information is passed during the initial call setup and
while the call is being routed through the network. Since the redirecting
information is sent before a call is answered, you need to prevent the
channel driver from acting on a partial update. The 'i' option is used to
inhibit the channel driver from sending the changed information
immediately.
The incoming call may have already been redirected. An incoming call has
already been redirected if the REDIRECTING(count) is not zero. (Alternate
indications are if the REDIRECTING(from-num-valid) is non-zero or if the
REDIRECTING(from-num) is not empty.)
There are several things to do when a call is forwarded by the dialplan:
\begin{itemize}
\item Setup the REDIRECTING(to-xxx) values to be sent to the caller.
\item Setup the REDIRECTING(from-xxx) values to be sent to the new
destination.
\item Increment the REDIRECTING(count).
\item Set the REDIRECTING(reason).
\item Dial() the new destination.
\end{itemize}
\subsection{Special REDIRECTING considerations for ISDN}
Special considerations for Q.SIG and ISDN point-to-point links are needed
to make the DivertingLegInformation1, DivertingLegInformation2, and
DivertingLegInformation3 messages operate properly.
You should manually send the COLR of the redirected-to party for an
incoming redirected call if the incoming call could experience further
redirects. For chan_misdn, just set the REDIRECTING(to-num,i) =
\$\{EXTEN\} and set the REDIRECTING(to-num-pres) to the COLR. For
chan_dahdi, just set the REDIRECTING(to-num,i) = CALLERID(dnid) and set
the REDIRECTING(to-num-pres) to the COLR. (Setting the
REDIRECTING(to-num,i) value may not be necessary since the channel driver
has already attempted to preset that value for automatic generation of the
needed DivertingLegInformation3 message.)
For redirected calls out a trunk line, you need to use the 'i' option on
all of the REDIRECTING statements before dialing the redirected-to party.
The call will update the redirecting-to presentation (COLR) when it
becomes available.
\subsection{Dial() and Queue() dialplan application 'I' option}
In the dialplan applications Dial() and Queue(), the 'I' option is a brute
force option to block connected line and redirecting information updates
while the application is running. Blocking the updates prevents the
update from overwriting any CONNECTEDLINE or REDIRECTING values you may
have setup before running the application.
The option blocks all redirecting updates since they should only happen
before a call is answered. The option only blocks the connected line
update from the initial answer. Connected line updates resulting from
call transfers happen after the application has completed. Better control
of connected line and redirecting information is obtained using the
interception macros.
\subsection{Interception macros}
The interception macros give the administrator an opportunity to alter
connected line and redirecting information before the channel driver is
given the information. If the macro does not change a value then that is
what is going to be passed to the channel driver.
The tag string available in CALLERID, CONNECTEDLINE, and REDIRECTING is
useful for the interception macros to provide some information about where
the information originally came from.
The 'i' option of the CONNECTEDLINE dialplan function should always be
used in the CONNECTED_LINE interception macros. The interception macro
always passes the connected line information on to the channel driver when
the macro exits. Similarly, the 'i' option of the REDIRECTING dialplan
function should always be used in the REDIRECTING interception macros.
\begin{verbatim}
${REDIRECTING_CALLEE_SEND_MACRO}
Macro to call before sending a redirecting update to the callee.
This macro may never be needed since the redirecting updates
should only go from the callee to the caller direction. It is
available for completeness.
${REDIRECTING_CALLEE_SEND_MACRO_ARGS}
Arguments to pass to ${REDIRECTING_CALLEE_SEND_MACRO}.
${REDIRECTING_CALLER_SEND_MACRO}
Macro to call before sending a redirecting update to the caller.
${REDIRECTING_CALLER_SEND_MACRO_ARGS}
Arguments to pass to ${REDIRECTING_CALLER_SEND_MACRO}.
${CONNECTED_LINE_CALLEE_SEND_MACRO}
Macro to call before sending a connected line update to the callee.
${CONNECTED_LINE_CALLEE_SEND_MACRO_ARGS}
Arguments to pass to ${CONNECTED_LINE_CALLEE_SEND_MACRO}.
${CONNECTED_LINE_CALLER_SEND_MACRO}
Macro to call before sending a connected line update to the caller.
${CONNECTED_LINE_CALLER_SEND_MACRO_ARGS}
Arguments to pass to ${CONNECTED_LINE_CALLER_SEND_MACRO}.
\end{verbatim}
\section{Manipulation examples}
The following examples show several common scenarios in which you may need
to manipulate party ID information from the dialplan.
\subsection{Simple recording playback}
\begin{verbatim}
exten => 1000,1,NoOp
; The CONNECTEDLINE information is sent when the call is answered.
exten => 1000,n,Set(CONNECTEDLINE(name,i)="Company Name")
exten => 1000,n,Set(CONNECTEDLINE(name-pres,i)=allowed)
exten => 1000,n,Set(CONNECTEDLINE(num,i)=5551212)
exten => 1000,n,Set(CONNECTEDLINE(num-pres)=allowed)
exten => 1000,n,Answer
exten => 1000,n,Playback(tt-weasels)
exten => 1000,n,Hangup
\end{verbatim}
\subsection{Straightforward dial through}
\begin{verbatim}
exten => 1000,1,NoOp
; The CONNECTEDLINE information is sent when the call is answered.
exten => 1000,n,Set(CONNECTEDLINE(name,i)="Company Name")
exten => 1000,n,Set(CONNECTEDLINE(name-pres,i)=allowed)
exten => 1000,n,Set(CONNECTEDLINE(num,i)=5551212)
exten => 1000,n,Set(CONNECTEDLINE(num-pres)=allowed)
; The I option prevents overwriting the CONNECTEDLINE information
; set above when the call is answered.
exten => 1000,n,Dial(SIP/1000,20,I)
exten => 1000,n,Hangup
\end{verbatim}
\subsection{Use of interception macro}
\begin{verbatim}
[macro-add_pfx]
; ARG1 is the prefix to add.
; ARG2 is the number of digits at the end to add the prefix to.
; When the macro ends the CONNECTEDLINE data is passed to the
; channel driver.
exten => s,1,NoOp(Add prefix to connected line)
exten => s,n,Set(NOPREFIX=${CONNECTEDLINE(number):-${ARG2}})
exten => s,n,Set(CONNECTEDLINE(num,i)=${ARG1}${NOPREFIX})
exten => s,n,MacroExit
exten => 1000,1,NoOp
exten => 1000,n,Set(__CONNECTED_LINE_CALLER_SEND_MACRO=add_pfx)
exten => 1000,n,Set(__CONNECTED_LINE_CALLER_SEND_MACRO_ARGS=45,4)
exten => 1000,n,Dial(SIP/1000,20)
exten => 1000,n,Hangup
\end{verbatim}
\subsection{Simple redirection}
\begin{verbatim}
exten => 1000,1,NoOp
; For Q.SIG or ISDN point-to-point we should determine the COLR for this
; extension and send it if the call was redirected here.
exten => 1000,n,GotoIf($[${REDIRECTING(count)}>0]?redirected:notredirected)
exten => 1000,n(redirected),Set(REDIRECTING(to-num,i)=${CALLERID(dnid)})
exten => 1000,n,Set(REDIRECTING(to-num-pres)=allowed)
exten => 1000,n(notredirected),NoOp
; Determine that the destination has forwarded the call.
; ...
exten => 1000,n,Set(REDIRECTING(from-num,i)=1000)
exten => 1000,n,Set(REDIRECTING(from-num-pres,i)=allowed)
exten => 1000,n,Set(REDIRECTING(to-num,i)=2000)
; The DivertingLegInformation3 message is needed because at this point
; we do not know the presentation (COLR) setting of the redirecting-to
; party.
exten => 1000,n,Set(REDIRECTING(count,i)=$[${REDIRECTING(count)} + 1])
exten => 1000,n,Set(REDIRECTING(reason,i)=cfu)
; The call will update the redirecting-to presentation (COLR) when it
; becomes available with a redirecting update.
exten => 1000,n,Dial(DAHDI/g1/2000,20)
exten => 1000,n,Hangup
\end{verbatim}
\section{Ideas for usage}
The following is a list of ideas in which the manipulation of party ID
information would be beneficial.
\begin{itemize}
\item IVR that updates connected name on each selection made.
\item Disguise the true number of an individual with a generic company
number.
\item Use interception macros to make outbound connected number E.164
formatted.
\item You can do a lot more in an interception macro than just manipulate
party information...
\end{itemize}
\section{Troubleshooting tips}
\begin{itemize}
\item For CONNECTEDLINE and REDIRECTING, check the usage of the 'i'
option.
\item Check channel configuration settings. The default settings may not
be what you want or expect.
\item Check packet captures. Your equipment may not support what Asterisk
sends.
\end{itemize}
\section{For further reading...}
\begin{itemize}
\item Relevant ETSI ISDN redirecting specification: EN 300 207-1
\item Relevant ETSI ISDN COLP specification: EN 300 097-1
\item Relevant ETSI ISDN ECT specification: EN 300 369-1
\item Relevant Q.SIG ISDN redirecting specification: ECMA-174
\item Relevant Q.SIG ISDN COLP specification: ECMA-148
\item Relevant Q.SIG ISDN ECT specification: ECMA-178
\item Relevant SIP RFC for P-Asserted-Id: RFC3325
\item The expired draft (draft-ietf-sip-privacy-04.txt) defines
Remote-Party-Id. Since Remote-Party-Id has not made it into an RFC at
this time, its use is non-standard by definition.
\end{itemize}

View File

@ -1,307 +0,0 @@
\section{Introduction}
Asterisk includes basic phone provisioning support through the res\_phoneprov module. The
current implementation is based on a templating system using Asterisk dialplan function
and variable substitution and obtains information to substitute into those templates from
\path{phoneprov.conf} and \path{users.conf}. A profile and set of templates is provided
for provisioning Polycom phones. Note that res\_phoneprov is currently limited to
provisioning a single user per device.
\section{Configuration of phoneprov.conf}
The configuration file, \path{phoneprov.conf}, is used to set up the built-in variables
SEVER and SERVER\_PORT, to define a default phone profile to use, and to define different
phone profiles available for provisioning.
\subsection{The [general] section}
Below is a sample of the general section of \path{phoneprov.conf}:
\begin{astlisting}
\begin{verbatim}
[general]
;serveriface=eth0
;serveraddr=192.168.1.1
;serverport=5060
default_profile=polycom
\end{verbatim}
\end{astlisting}
By default, res\_phoneprov will set the SERVER variable to the IP address on the server
that the requesting phone uses to contact the asterisk HTTP server. The SERVER\_PORT
variable will default to the \textbf{bindport} setting in sip.conf.
Should the defaults be insufficient, there are two choices for overriding the default
setting of the SERVER variable. If the IP address of the server is known, or the hostname
resolvable by the phones, the appropriate \textbf{serveraddr} value should be set.
Alternatively, the network interface that the server listens on can be set by specifying a
\textbf{serveriface} and SERVER will be set to the IP address of that interface. Only one
of these options should be set.
The default SERVER\_PORT variable can be overridden by setting the \textbf{serverport}.
If \textbf{bindport} is not set in \path{sip.conf} and serverport is not specified, it
is set to a default value of 5060.
Any user set for auto-provisioning in users.conf without a specified profile will be
assumed to belong to the profile set with \textbf{default\_profile}.
\subsection{Creating phone profiles}
A phone profile is basically a list of files that a particular group of phones needs to
function. For most phone types there are files that are identical for all phones
(firmware, for instance) as well as a configuration file that is specific to individual
phones. res\_phoneprov breaks these two groups of files into static files and dynamic
files, respectively. A sample profile:
\begin{astlisting}
\begin{verbatim}
[polycom]
staticdir => configs/
mime_type => text/xml
setvar => CUSTOM_CONFIG=/var/lib/asterisk/phoneprov/configs/custom.cfg
static_file => bootrom.ld,application/octet-stream
static_file => bootrom.ver,plain/text
static_file => sip.ld,application/octet-stream
static_file => sip.ver,plain/text
static_file => sip.cfg
static_file => custom.cfg
${TOLOWER(${MAC})}.cfg => 000000000000.cfg
${TOLOWER(${MAC})}-phone.cfg => 000000000000-phone.cfg
config/${TOLOWER(${MAC})} => polycom.xml
${TOLOWER(${MAC})}-directory.xml => 000000000000-directory.xml
\end{verbatim}
\end{astlisting}
A \textbf{static\_file} is set by specifying the file name, relative to
\path{AST\_DATA\_DIR/phoneprov}. The mime-type of the file can optionally be specified
after a comma. If \textbf{staticdir} is set, all static files will be relative to the
subdirectory of AST\_DATA\_DIR/phoneprov specified.
Since phone-specific config files generally have file names based on phone-specifc data,
dynamic filenames in res\_phoneprov can be defined with Asterisk dialplan function and
variable substitution. In the above example, \$\{TOLOWER(\$\{MAC\})\}.cfg =$>$
000000000000.cfg would define a relative URI to be served that matches the format of
MACADDRESS.cfg, all lower case. A request for that file would then point to the template
found at AST\_DATA\_DIR/phoneprov/000000000000.cfg. The template can be followed by a
comma and mime-type. Notice that the dynamic filename (URI) can contain contain
directories. Since these files are dynamically generated, the config file itself does not
reside on the filesystem--only the template. To view the generated config file, open it
in a web browser. If the config file is XML, Firefox should display it. Some browsers
will require viewing the source of the page requested.
A default mime-type for the profile can be defined by setting \textbf{mime-type}. If a
custom variable is required for a template, it can be specified with \textbf{setvar}.
Variable substitution on this value is done while building the route list, so
\$\{USERNAME\} would expand to the username of the users.conf user that registers the
dynamic filename.
NOTE: Any dialplan function that is used for generation of dynamic file names MUST be
loaded before res\_phoneprov. Add "preload =$>$ modulename.so" to
\path{modules.conf} for required functions. In the example above, "preload =$>$
func\_strings.so" would be required.
\section{Configuration of users.conf}
The asterisk-gui sets up extensions, SIP/IAX2 peers, and a host of other settings.
User-specific settings are stored in users.conf. If the asterisk-gui is not being used,
manual entries to users.conf can be made.
\subsection{The [general] section}
There are only two settings in the general section of \path{users.conf} that apply to
phone provisioning: localextenlength which maps to template variable EXTENSION\_LENGTH
and \textbf{vmexten} which maps to the VOICEMAIL\_EXTEN variable.
\subsection{Invdividual Users}
To enable auto-provisioning of a phone, the user in \path{users.conf} needs to have:
\begin{astlisting}
\begin{verbatim}
...
autoprov=yes
macaddress=deadbeef4dad
profile=polycom
\end{verbatim}
\end{astlisting}
The profile is optional if a \textbf{default\_profile} is set in \path{phoneprov.conf}.
The following is a sample users.conf entry, with the template variables commented next to
the settings:
\begin{astlisting}
\begin{verbatim}
[6001]
callwaiting = yes
context = numberplan-custom-1
hasagent = no
hasdirectory = yes
hasiax = no
hasmanager = no
hassip = yes
hasvoicemail = yes
host = dynamic
mailbox = 6001
threewaycalling = yes
deletevoicemail = no
autoprov = yes
profile = polycom
directmedia = no
nat = no
fullname = User Two ; ${DISPLAY_NAME}
secret = test ; ${SECRET}
username = 6001 ; ${USERNAME}
macaddress = deadbeef4dad ; ${MAC}
label = 6001 ; ${LABEL}
cid_number = 6001 ; ${CALLERID}
\end{verbatim}
\end{astlisting}
The variables above, are the user-specfic variables that can be substituted into dynamic
filenames and config templates.
\section{Templates}
Configuration templates are a generic way to configure phones with text-based
configuration files. Templates can use any loaded dialplan function and all of the
variables created by \path{phoneprov.conf} and \path{users.conf}. A short example is the
included 000000000000.cfg Polycom template:
\begin{astlisting}
\begin{verbatim}
<?xml version="1.0" standalone="yes"?>
<APPLICATION
APP_FILE_PATH="sip.ld"
CONFIG_FILES="${IF($[${STAT(e|${CUSTOM_CONFIG})}] ? "custom.cfg,
")}config/${TOLOWER(${MAC})}, sip.cfg"
MISC_FILES="" LOG_FILE_DIRECTORY=""
/>
\end{verbatim}
\end{astlisting}
This template uses dialplan functions, expressions, and a couple of variables to generate
a config file to instruct the Polycom where to pull other needed config files. If a phone
with MAC address 0xDEADBEEF4DAD requests this config file, and the filename that is
stored in variable CUSTOM\_CONFIG does not exist, then the generated output would be:
\begin{astlisting}
\begin{verbatim}
<?xml version="1.0" standalone="yes"?>
<APPLICATION
APP_FILE_PATH="sip.ld"
CONFIG_FILES="config/deadbeef4dad, sip.cfg"
MISC_FILES="" LOG_FILE_DIRECTORY=""
/>
\end{verbatim}
\end{astlisting}
The Polycom phone would then download both sip.cfg (which would be registered in
\path{phoneprov.conf} as a static file) and config/deadbeef4dad (which would be
registered as a dynamic file pointing to another template, polycom.xml).
res\_phoneprov also registers its own dialplan function: PP\_EACH\_USER. This function
was designed to be able to print out a particular string for each user that
res\_phoneprov knows about. An example use of this function is the template for a Polycom
contact directory:
\begin{astlisting}
\begin{verbatim}
<?xml version="1.0" standalone="yes"?>
<directory>
<item_list>
${PP_EACH_USER(<item><fn>%{DISPLAY_NAME}</fn><ct>%{CALLERID}</ct><bw>1</bw></item>|${MAC})}
</item_list>
</directory>
\end{verbatim}
\end{astlisting}
PP\_EACH\_USER takes two arguments. The first is the string to be printed for each user.
Any variables that are to be substituted need to be in the format \%\{VARNAME\} so that
Asterisk doesn't try to substitute the variable immediately before it is passed to
PP\_EACH\_USER. The second, optional, argument is a MAC address to exclude from the list
iterated over (so, in this case, a phone won't be listed in its own contact directory).
\section{Putting it all together}
Make sure that \path{manager.conf} has:
\begin{astlisting}
\begin{verbatim}
[general]
enabled = yes
webenabled = yes
\end{verbatim}
\end{astlisting}
and that \path{http.conf} has:
\begin{astlisting}
\begin{verbatim}
[general]
enabled = yes
bindaddr = 192.168.1.1 ; Your IP here ;-)
bindport = 8088 ; Or port 80 if it is the only http server running on the machine
\end{verbatim}
\end{astlisting}
With \path{phoneprov.conf} and \path{users.conf} in place, start Astersik. From the CLI,
type "http show status". An example output:
\begin{astlisting}
\begin{verbatim}
HTTP Server Status:
Prefix: /asterisk
Server Enabled and Bound to 192.168.1.1:8088
Enabled URI's:
/asterisk/httpstatus => Asterisk HTTP General Status
/asterisk/phoneprov/... => Asterisk HTTP Phone Provisioning Tool
/asterisk/manager => HTML Manager Event Interface
/asterisk/rawman => Raw HTTP Manager Event Interface
/asterisk/static/... => Asterisk HTTP Static Delivery
/asterisk/mxml => XML Manager Event Interface
Enabled Redirects:
None.
POST mappings:
None.
\end{verbatim}
\end{astlisting}
There should be a phoneprov URI listed. Next, from the CLI, type "phoneprov show routes"
and verify that the information there is correct. An example output for Polycom phones
woud look like:
\begin{astlisting}
\begin{verbatim}
Static routes
Relative URI Physical location
sip.ver configs/sip.ver
sip.ld configs/sip.ld
bootrom.ver configs/bootrom.ver
sip.cfg configs/sip.cfg
bootrom.ld configs/bootrom.ld
custom.cfg configs/custom.cfg
Dynamic routes
Relative URI Template
deadbeef4dad.cfg 000000000000.cfg
deadbeef4dad-directory.xml 000000000000-directory.xml
deadbeef4dad-phone.cfg 000000000000-phone.cfg
config/deadbeef4dad polycom.xml
\end{verbatim}
\end{astlisting}
With the above examples, the phones would be pointed to
\url{http://192.168.1.1:8080/asterisk/phoneprov} for pulling config files. Templates
would all be placed in AST\_DATA\_DIR/phoneprov and static files would be placed in
AST\_DATA\_DIR/phoneprov/configs. Examples of valid URIs would be:
\begin{itemize}
\item http://192.168.1.1:8080/asterisk/phoneprov/sip.cfg
\item http://192.168.1.1:8080/asterisk/phoneprov/deadbeef4dad.cfg
\item http://192.168.1.1:8080/asterisk/phoneprov/config/deadbeef4dad
\end{itemize}

View File

@ -1,139 +0,0 @@
\section{What is PLC?}
PLC stands for Packet Loss Concealment. PLC describes any method of generating
new audio data when packet loss is detected. In Asterisk, there are two main flavors
of PLC, generic and native. Generic PLC is a method of generating audio data on
signed linear audio streams. Signed linear audio, often abbreviated "slin," is required
since it is a raw format that has no companding, compression, or other transformations
applied. Native PLC is used by specific codec implementations, such as
iLBC and Speex, which generates the new audio in the codec's native format. Native
PLC happens automatically when using a codec that supports native PLC. Generic PLC
requires specific configuration options to be used and will be the focus of this
document.
\section{How does Asterisk detect packet loss?}
Oddly, Asterisk does not detect packet loss when reading audio in. In order to
detect packet loss, one must have a jitter buffer in use on the channel on which
Asterisk is going to write missing audio using PLC. When a jitter buffer is in use,
audio that is to be written to the channel is fed into the jitterbuffer. When the
time comes to write audio to the channel, a bridge will request that the jitter
buffer gives a frame of audio to the bridge so that the audio may be written. If
audio is requested from the jitter buffer but the jitter buffer is unable to give
enough audio to the bridge, then the jitter buffer will return an interpolation
frame. This frame contains no actual audio data and indicates the number of samples
of audio that should be inserted into the frame.
\section{A bit of background on translation}
As stated in the introduction, generic PLC can only be used on slin audio.
The majority of audio communication is not done in slin, but rather using lower
bandwidth codecs. This means that for PLC to be used, there must be a translation
step involving slin on the write path of a channel. This means that PLC cannot
be used if the codecs on either side of the bridge are the same or do not require
a translation to slin in order to translate between them. For instance, a
ulaw $<$-$>$ ulaw call will not use PLC since no translation is required. In addition,
a ulaw $<$-$>$ alaw call will also not use PLC since the translation path does not
include any step involving slin.
One item of note is that slin must be present on the write path of a channel
since that is the path where PLC is applied. Consider that Asterisk is bridging
channels A and B. A uses ulaw for audio and B uses GSM. This translation involves
slin, so things are shaping up well for PLC. Consider, however if Asterisk sets
up the translation paths like so:
\begin{verbatim}
Fig. 1
A +------------+ B
<---ulaw<---slin<---GSM| |GSM--->
| Asterisk |
ulaw--->slin--->GSM--->| |<---GSM
+------------+
\end{verbatim}
The arrows indicate the direction of audio flow. Each channel has a write
path (the top arrow) and a read path (the bottom arrow). In this setup, PLC
can be used when sending audio to A, but it cannot be used when sending audio
to B. The reason is simple, the write path to A's channel contains a slin
step, but the write path to B contains no slin step. Such a translation setup
is perfectly valid, and Asterisk can potentially set up such a path depending
on circumstances. When we use PLC, however, we want slin audio to be present
on the write paths of both A and B. A visual representation of what we want
is the following:
\begin{verbatim}
Fig. 2
A +------------+ B
<---ulaw<---slin| |slin--->GSM--->
| Asterisk |
ulaw--->slin--->| |<---slin<---GSM
+------------+
\end{verbatim}
In this scenario, the write paths for both A and B begin with slin,
and so PLC may be applied to either channel. This translation behavior has,
in the past been doable with the \texttt{transcode\_via\_sln} option in \path{asterisk.conf}.
Recent changes to the PLC code have also made the \texttt{genericplc} option in
\path{codecs.conf} imply the \texttt{transcode\_via\_sln} option. The result is that by
enabling \texttt{genericplc} in \path{codecs.conf}, the translation path set up in
Fig. 2 should automatically be used.
\section{Additional restrictions and caveats}
One restriction that has not been spelled out so far but that has been
hinted at is the presence of a bridge. The term bridge in this sense means
two channels exchanging audio with one another. A bridge is required because
use of a jitter buffer is a prerequisite for using PLC, and a jitter buffer
is only used when bridging two channels. This means that one-legged calls,
(e.g. calls to voicemail, to an IVR, to an extension that just plays back
audio) will not use PLC. In addition, MeetMe and ConfBridge calls will not
use PLC.
It should be obvious, but it bears mentioning, that PLC cannot be used
when using a technology's native bridging functionality. For instance, if
two SIP channels can exchange RTP directly, then Asterisk will never be
able to process the audio in the first place. Since translation of audio
is a requirement for using PLC, and translation will not allow for a
native bridge to be created, this is something that is not likely to be
an issue, though.
Since a jitter buffer is a requirement in order to use PLC, it should
be noted that simply enabling the jitter buffer via the \texttt{jbenable} option
may not be enough. For instance, if bridging two SIP channels together,
the default behavior will not be to enable jitter buffers on either channel.
The rationale is that the jitter will be handled at the endpoints to which
Asterisk is sending the audio. In order to ensure that a jitter buffer is
used in all cases, one must enable the \texttt{jbforce} option for channel types
on which PLC is desired.
\section{Summary}
The following are all required for PLC to be used:
\begin{itemize}
\item Enable \texttt{genericplc} in the \texttt{plc} section of \path{codecs.conf}
\item Enable (and potentially force) jitter buffers on channels
\item Two channels must be bridged together for PLC to be used
(no Meetme or one-legged calls)
\item The audio must be translated between the two channels
and must have slin as a step in the translation process.
\end{itemize}
\section{Protip}
One of the restrictions mentioned is that PLC will only
be used when two audio channels are bridged together. Through the
use of Local channels, you can create a bridge even if the call
is, for all intents and purposes, one-legged. By using a combination
of the /n and /j suffixes for a Local channel, one can ensure
that the Local channel is not optimized out of the talk path
and that a jitter buffer is applied to the Local channel as well.
Consider the following simple dialplan:
\begin{verbatim}
[example]
exten => 1,1,Playback(tt-weasels)
exten => 2,1,Dial(Local/1@example/nj)
\end{verbatim}
When dialing extension 1, PLC cannot be used because there
will be only a single channel involved. When dialing extension
2, however, Asterisk will create a bridge between the incoming
channel and the Local channel, thus allowing PLC to be used.

View File

@ -1,364 +0,0 @@
So, you want to avoid talking to pesky telemarketers/charity
seekers/poll takers/magazine renewers/etc?
\subsection{First of all}
the FTC "Don't call" database, this alone will reduce your
telemarketing call volume considerably. (see:
\url{https://www.donotcall.gov/default.aspx} ) But, this list won't protect
from the Charities, previous business relationships, etc.
\subsection{Next, Fight against autodialers!!}
Zapateller detects if callerid is present, and if not, plays the
da-da-da tones that immediately precede messages like, "I'm sorry,
the number you have called is no longer in service."
Most humans, even those with unlisted/callerid-blocked numbers, will
not immediately slam the handset down on the hook the moment they hear
the three tones. But autodialers seem pretty quick to do this.
I just counted 40 hangups in Zapateller over the last year in my
CDR's. So, that is possibly 40 different telemarketers/charities that have
hopefully slashed my back-waters, out-of-the-way, humble home phone
number from their lists.
I highly advise Zapateller for those seeking the nirvana of "privacy".
\subsection{Next, Fight against the empty CALLERID!}
A considerable percentage of the calls you don't want, come from
sites that do not provide CallerID.
Null callerid's are a fact of life, and could be a friend with an
unlisted number, or some charity looking for a handout. The
PrivacyManager application can help here. It will ask the caller to
enter a 10-digit phone number. They get 3 tries(configurable), and this is
configurable, with control being passed to next priority where you can
check the channelvariable PRIVACYMGRSTATUS. If the callerid was valid this
variable will have the value SUCCESS, otherwise it will have the value
FAILED.
PrivacyManager can't guarantee that the number they supply is any
good, tho, as there is no way to find out, short of hanging up and
calling them back. But some answers are obviously wrong. For instance,
it seems a common practice for telemarketers to use your own number
instead of giving you theirs. A simple test can detect this. More
advanced tests would be to look for -555- numbers, numbers that count
up or down, numbers of all the same digit, etc.
PrivacyManager can be told about a context where you can have patterns
that describe valid phone numbers. If none of the patterns match the
input, it will be considered a non-valid phonenumber and the user
can try again until the retry counter is reached.
This helps in resolving the issues stated in the previous paragraph.
My logs show that 39 have hung up in the PrivacyManager script over
the last year.
(Note: Demanding all unlisted incoming callers to enter their CID may
not always be appropriate for all users. Another option might be to
use call screening. See below.)
\subsection{Next, use a WELCOME MENU !}
Experience has shown that simply presenting incoming callers with
a set of options, no matter how simple, will deter them from calling
you. In the vast majority of situations, a telemarketer will simply
hang up rather than make a choice and press a key.
This will also immediately foil all autodialers that simply belch a
message in your ear and hang up.
\subsubsection{Example usage of Zapateller and PrivacyManager}
\begin{astlisting}
\begin{verbatim}
[homeline]
exten => s,1,Answer
exten => s,2,SetVar,repeatcount=0
exten => s,3,Zapateller,nocallerid
exten => s,4,PrivacyManager
;; do this if they don't enter a number to Privacy Manager
exten => s,5,GotoIf($[ "${PRIVACYMGRSTATUS}" = "FAILED" ]?s,105)
exten => s,6,GotoIf($[ "${CALLERID(num)}" = "7773334444" & "${CALLERID(name)}" : "Privacy Manager" ]?callerid-liar,s,1:s,7)
exten => s,7,Dial(SIP/yourphone)
exten => s,105,Background(tt-allbusy)
exten => s,106,Background(tt-somethingwrong)
exten => s,107,Background(tt-monkeysintro)
exten => s,108,Background(tt-monkeys)
exten => s,109,Background(tt-weasels)
exten => s,110,Hangup
\end{verbatim}
\end{astlisting}
I suggest using Zapateller at the beginning of the context, before
anything else, on incoming calls.This can be followed by the
PrivacyManager App.
Make sure, if you do the PrivacyManager app, that you take care of the
error condition! or their non-compliance will be rewarded with access
to the system. In the above, if they can't enter a 10-digit number in
3 tries, they get the humorous "I'm sorry, but all household members
are currently helping other telemarketers...", "something is terribly
wrong", "monkeys have carried them away...", various loud monkey
screechings, "weasels have...", and a hangup. There are plenty of
other paths to my torture scripts, I wanted to have some fun.
In nearly all cases now, the telemarketers/charity-seekers that
usually get thru to my main intro, hang up. I guess they can see it's
pointless, or the average telemarketer/charity-seeker is instructed
not to enter options when encountering such systems. Don't know.
\subsection{Next: Torture Them!}
I have developed an elaborate script to torture Telemarketers, and
entertain friends. (See
\url{http://www.voip-info.org/wiki-Asterisk+Telemarketer+Torture} )
While mostly those that call in and traverse my teletorture scripts
are those we know, and are doing so out of curiosity, there have been
these others from Jan 1st,2004 thru June 1st, 2004:
(the numbers may or may not be correct.)
\begin{itemize}
\item 603890zzzz -- hung up telemarket options.
\item "Integrated Sale" -- called a couple times. hung up in telemarket options
\item "UNITED STATES GOV" -- maybe a military recruiter, trying to lure one of my sons.
\item 800349zzzz -- hung up in charity intro
\item 800349zzzz -- hung up in charity choices, intro, about the only one who actually travelled to the bitter bottom of the scripts!
\item 216377zzzz -- hung up the magazine section
\item 626757zzzz = "LIR " (pronounced "Liar"?) hung up in telemarket intro, then choices
\item 757821zzzz -- hung up in new magazine subscription options.
\end{itemize}
That averages out to maybe 1 a month. That puts into question whether
the ratio of the amount of labor it took to make the scripts versus
the benefits of lower call volumes was worth it, but, well, I had fun,
so what the heck.
but, that's about it. Not a whole lot. But I haven't had to say "NO"
or "GO AWAY" to any of these folks for about a year now ...!
\subsection{Using Call Screening}
Another option is to use call screening in the Dial command. It has
two main privacy modes, one that remembers the CID of the caller, and
how the callee wants the call handled, and the other, which does not
have a "memory".
Turning on these modes in the dial command results in this sequence of
events, when someone calls you at an extension:
\begin{enumerate}
\item The caller calls the Asterisk system, and at some point, selects an
option or enters an extension number that would dial your extension.
\item Before ringing your extension, the caller is asked to supply an
introduction. The application asks them: "After the tone, say your
name". They are allowed 4 seconds of introduction.
\item After that, they are told "Hang on, we will attempt to connect you
to your party. Depending on your dial options, they will hear ringing
indications, or get music on hold. I suggest music on hold.
\item Your extension is then dialed. When (and if) you pick up, you are
told that a caller presenting themselves as $<$their recorded intro is
played$>$ is calling, and you have options, like being connected,
sending them to voicemail, torture, etc.
\item You make your selection, and the call is handled as you chose.
\end{enumerate}
There are some variations, and these will be explained in due course.
To use these options, set your Dial to something like:
\begin{astlisting}
\begin{verbatim}
exten => 3,3,Dial(DAHDI/5r3&DAHDI/6r3,35,tmPA(beep))
or
exten => 3,3,Dial(DAHDI/5r3&DAHDI/6r3,35,tmP(something)A(beep))
or
exten => 3,3,Dial(DAHDI/5r3&DAHDI/6r3,35,tmpA(beep))
\end{verbatim}
\end{astlisting}
The 't' allows the dialed party to transfer the call using '\#'. It's
optional.
The 'm' is for music on hold. I suggest it. Otherwise, the calling
party gets to hear all the ringing, and lack thereof. It is generally
better to use Music On Hold. Lots of folks hang up after the 3rd or
4th ring, and you might lose the call before you can enter an option!
The 'P' option alone will database everything using the extension as a
default 'tree'. To get multiple extensions sharing the same database, use
P(some-shared-key). Also, if the same person has multiple extensions,
use P(unique-id) on all their dial commands.
Use little 'p' for screening. Every incoming call will include a
prompt for the callee's choice.
the A(beep), will generate a 'beep' that the callee will hear if they
choose to talk to the caller. It's kind of a prompt to let the callee
know that he has to say 'hi'. It's not required, but I find it
helpful.
When there is no CallerID, P and p options will always record an intro
for the incoming caller. This intro will be stored temporarily in the
\path{/var/lib/asterisk/sounds/priv-callerintros} dir, under the name
NOCALLERID\_$<$extension$>$ $<$channelname$>$ and will be erased after the
callee decides what to do with the call.
Of course, NOCALLERID is not stored in the database. All those with no
CALLERID will be considered "Unknown".
\subsection{The 'N' and 'n' options}
Two other options exist, that act as modifiers to the privacy options
'P' and 'p'. They are 'N' and 'n'. You can enter them as dialing
options, but they only affect things if P or p are also in the
options.
'N' says, "Only screen the call if no CallerID is present". So, if a
callerID were supplied, it will come straight thru to your extension.
'n' says, "Don't save any introductions". Folks will be asked to
supply an introduction ("At the tone, say your name") every time they
call. Their introductions will be removed after the callee makes a
choice on how to handle the call. Whether the P option or the p option
is used, the incoming caller will have to supply their intro every
time they call.
\subsection{Recorded Introductions}
\subsubsection{Philosophical Side Note}
The 'P' option stores the CALLERID in the database, along with the
callee's choice of actions, as a convenience to the CALLEE, whereas
introductions are stored and re-used for the convenience of the CALLER.
\subsubsection{Introductions}
Unless instructed to not save introductions (see the 'n' option above),
the screening modes will save the recordings of the caller's names in
the directory \path{/var/lib/asterisk/sounds/priv-callerintros}, if they have
a CallerID. Just the 10-digit callerid numbers are used as filenames,
with a ".gsm" at the end.
Having these recordings around can be very useful, however...
First of all, if a callerid is supplied, and a recorded intro for that
number is already present, the caller is spared the inconvenience of
having to supply their name, which shortens their call a bit.
Next of all, these intros can be used in voicemail, played over
loudspeakers, and perhaps other nifty things. For instance:
\begin{astlisting}
\begin{verbatim}
exten => s,6,Set(PATH=/var/lib/asterisk/sounds/priv-callerintros)
exten => s,7,System(/usr/bin/play ${PATH}/${CALLERID(num)}.gsm&,0)
\end{verbatim}
\end{astlisting}
When a call comes in at the house, the above priority gets executed,
and the callers intro is played over the phone systems speakers. This
gives us a hint who is calling.
(Note: the ,0 option at the end of the System command above, is a
local mod I made to the System command. It forces a 0 result code to
be returned, whether the play command successfully completed or
not. Therefore, I don't have to ensure that the file exists or
not. While I've turned this mod into the developers, it hasn't been
incorporated yet. You might want to write an AGI or shell script to
handle it a little more intelligently)
And one other thing. You can easily supply your callers with an option
to listen to, and re-record their introductions. Here's what I did in
the home system's extensions.conf. (assume that a
Goto(home-introduction,s,1) exists somewhere in your main menu as an
option):
\begin{astlisting}
\begin{verbatim}
[home-introduction]
exten => s,1,Background(intro-options) ;; Script:
;; To hear your Introduction, dial 1.
;; to record a new introduction, dial 2.
;; to return to the main menu, dial 3.
;; to hear what this is all about, dial 4.
exten => 1,1,Playback,priv-callerintros/${CALLERID(num)}
exten => 1,2,Goto(s,1)
exten => 2,1,Goto(home-introduction-record,s,1)
exten => 3,1,Goto(homeline,s,7)
exten => 4,1,Playback(intro-intro)
;; Script:
;; This may seem a little strange, but it really is a neat
;; thing, both for you and for us. I've taped a short introduction
;; for many of the folks who normally call us. Using the Caller ID
;; from each incoming call, the system plays the introduction
;; for that phone number over a speaker, just as the call comes in.
;; This helps the folks
;; here in the house more quickly determine who is calling.
;; and gets the right ones to gravitate to the phone.
;; You can listen to, and record a new intro for your phone number
;; using this menu.
exten => 4,2,Goto(s,1)
exten => t,1,Goto(s,1)
exten => i,1,Background(invalid)
exten => i,2,Goto(s,1)
exten => o,1,Goto(s,1)
[home-introduction-record]
exten => s,1,Background(intro-record-choices) ;; Script:
;; If you want some advice about recording your
;; introduction, dial 1.
;; otherwise, dial 2, and introduce yourself after
;; the beep.
exten => 1,1,Playback(intro-record)
;; Your introduction should be short and sweet and crisp.
;; Your introduction will be limited to 4 seconds.
;; This is NOT meant to be a voice mail message, so
;; please, don't say anything about why you are calling.
;; After we are done making the recording, your introduction
;; will be saved for playback.
;; If you are the only person that would call from this number,
;; please state your name. Otherwise, state your business
;; or residence name instead. For instance, if you are
;; friend of the family, say, Olie McPherson, and both
;; you and your kids might call here a lot, you might
;; say: "This is the distinguished Olie McPherson Residence!"
;; If you are the only person calling, you might say this:
;; "This is the illustrious Kermit McFrog! Pick up the Phone, someone!!"
;; If you are calling from a business, you might pronounce a more sedate introduction,like,
;; "Fritz from McDonalds calling.", or perhaps the more original introduction:
;; "John, from the Park County Morgue. You stab 'em, we slab 'em!".
;; Just one caution: the kids will hear what you record every time
;; you call. So watch your language!
;; I will begin recording after the tone.
;; When you are done, hit the # key. Gather your thoughts and get
;; ready. Remember, the # key will end the recording, and play back
;; your intro. Good Luck, and Thank you!"
exten => 1,2,Goto(2,1)
exten => 2,1,Background(intro-start)
;; OK, here we go! After the beep, please give your introduction.
exten => 2,2,Background(beep)
exten => 2,3,Record(priv-callerintros/${CALLERID(num)}:gsm,4)
exten => 2,4,Background(priv-callerintros/${CALLERID(num)})
exten => 2,5,Goto(home-introduction,s,1)
exten => t,1,Goto(s,1)
exten => i,1,Background(invalid)
exten => i,2,Goto(s,1)
exten => o,1,Goto(s,1)
\end{verbatim}
\end{astlisting}
In the above, you'd most likely reword the messages to your liking,
and maybe do more advanced things with the 'error' conditions (i,o,t priorities),
but I hope it conveys the idea.

View File

@ -1,144 +0,0 @@
\subsubsection{Introduction}
Asterisk supports different QoS settings at the application level for various
protocols on both signaling and media. The Type of Service (TOS) byte can be
set on outgoing IP packets for various protocols. The TOS byte is used by the
network to provide some level of Quality of Service (QoS) even if the network
is congested with other traffic.
Asterisk running on Linux can also set 802.1p CoS marks in VLAN packets for the
VoIP protocols it uses. This is useful when working in a switched environment.
In fact Asterisk only set priority for Linux socket. For mapping this priority
and VLAN CoS mark you need to use this command:
\begin{verbatim}
vconfig set_egress_map [vlan-device] [skb-priority] [vlan-qos]
\end{verbatim}
The table below shows all VoIP channel drivers and other Asterisk modules that
support QoS settings for network traffic. It also shows the type(s) of
traffic for which each module can support setting QoS settings.
\begin{table}[h!]
\begin{center}
\begin{tabular}{ | l || c | c | c | c | }
\hline
& Signaling & Audio & Video & Text \\ \hline \hline
chan\_sip & + & + & + & + \\ \hline
chan\_skinny & + & + & + & \\ \hline
chan\_mgcp & + & + & & \\ \hline
chan\_unistm & + & + & & \\ \hline
chan\_h323 & & + & & \\ \hline
chan\_iax2 & \multicolumn{4}{|c|}{+} \\
\hline
\end{tabular}
\end{center}
\caption{Channel Driver QoS Settings}
\end{table}
\begin{table}[h!]
\begin{center}
\begin{tabular}{ | l || c | c | c | c | }
\hline
& Signaling & Audio & Video & Text \\ \hline \hline
dundi.conf & \multicolumn{4}{ | c | }{+ (tos setting)} \\ \hline
iaxprov.conf & \multicolumn{4}{ | c | }{+ (tos setting)} \\ \hline
\hline
\end{tabular}
\end{center}
\caption{Other ToS Settings}
\end{table}
\subsubsection{IP TOS values}
The allowable values for any of the tos* parameters are:
CS0, CS1, CS2, CS3, CS4, CS5, CS6, CS7, AF11, AF12, AF13, AF21, AF22, AF23,
AF31, AF32, AF33, AF41, AF42, AF43 and ef (expedited forwarding),
The tos* parameters also take numeric values.
Note that on a Linux system, Asterisk must be compiled with libcap in order to
use the ef tos setting if Asterisk is not run as root.
The lowdelay, throughput, reliability, mincost, and none values have been removed
in current releases.
\subsubsection{802.1p CoS values}
Because 802.1p uses 3 bits of the VLAN header, this parameter can take integer
values from 0 to 7.
\subsubsection{Recommended values}
The recommended values shown below are also included in sample configuration files:
\begin{table}[h!]
\begin{center}
\begin{tabular}{ | l || l | l | }
\hline
& tos & cos \\ \hline \hline
Signaling & cs3 & 3 \\ \hline
Audio & ef & 5 \\ \hline
Video & af41 & 4 \\ \hline
Text & af41 & 3 \\ \hline
Other & ef & \\
\hline
\end{tabular}
\end{center}
\caption{Recommended QoS Settings}
\end{table}
\subsubsection{IAX2}
In iax.conf, there is a "tos" parameter that sets the global default TOS
for IAX packets generated by chan\_iax2. Since IAX connections combine
signalling, audio, and video into one UDP stream, it is not possible
to set the TOS separately for the different types of traffic.
In iaxprov.conf, there is a "tos" parameter that tells the IAXy what TOS
to set on packets it generates. As with the parameter in iax.conf,
IAX packets generated by an IAXy cannot have different TOS settings
based upon the type of packet. However different IAXy devices can
have different TOS settings.
\subsubsection{SIP}
In sip.conf, there are four parameters that control the TOS settings:
"tos\_sip", "tos\_audio", "tos\_video" and "tos\_text". tos\_sip controls
what TOS SIP call signaling packets are set to. tos\_audio, tos\_video
and tos\_text control what TOS values are used for RTP audio, video, and text
packets, respectively.
There are four parameters to control 802.1p CoS: "cos\_sip", "cos\_audio",
"cos\_video" and "cos\_text". The behavior of these parameters is the
same as for the SIP TOS settings described above.
\subsubsection{Other RTP channels}
chan\_mgcp, chan\_h323, chan\_skinny and chan\_unistim also support TOS and
CoS via setting tos and cos parameters in their corresponding configuration
files. Naming style and behavior are the same as for chan\_sip.
\subsubsection{Reference}
IEEE 802.1Q Standard:
\url{http://standards.ieee.org/getieee802/download/802.1Q-1998.pdf}
Related protocols: IEEE 802.3, 802.2, 802.1D, 802.1Q
RFC 2474 - "Definition of the Differentiated Services Field
(DS field) in the IPv4 and IPv6 Headers", Nichols, K., et al,
December 1998.
IANA Assignments, DSCP registry
Differentiated Services Field Codepoints
\url{http://www.iana.org/assignments/dscp-registry}
To get the most out of setting the TOS on packets generated by
Asterisk, you will need to ensure that your network handles packets
with a TOS properly. For Cisco devices, see the previously mentioned
"Enterprise QoS Solution Reference Network Design Guide". For Linux
systems see the "Linux Advanced Routing \& Traffic Control HOWTO" at
\url{http://www.lartc.org/}.
For more information on Quality of
Service for VoIP networks see the "Enterprise QoS Solution Reference
Network Design Guide" version 3.3 from Cisco at:
\url{http://www.cisco.com/application/pdf/en/us/guest/netsol/ns432/c649/ccmigration\_09186a008049b062.pdf}

View File

@ -1,118 +0,0 @@
In order to properly manage ACD queues, it is important to be able to
keep track of details of call setups and teardowns in much greater detail
than traditional call detail records provide. In order to support this,
extensive and detailed tracing of every queued call is stored in the
queue log, located (by default) in \path{/var/log/asterisk/queue_log}.
These are the events (and associated information) in the queue log:
\textbf{ABANDON(position$|$origposition$|$waittime)}
The caller abandoned their position in the queue. The position is the
caller's position in the queue when they hungup, the origposition is
the original position the caller was when they first entered the
queue, and the waittime is how long the call had been waiting in the
queue at the time of disconnect.
\textbf{AGENTDUMP}
The agent dumped the caller while listening to the queue announcement.
\textbf{AGENTLOGIN(channel)}
The agent logged in. The channel is recorded.
\textbf{AGENTCALLBACKLOGIN(exten@context)}
The callback agent logged in. The login extension and context is recorded.
\textbf{AGENTLOGOFF(channel$|$logintime)}
The agent logged off. The channel is recorded, along with the total time
the agent was logged in.
\textbf{AGENTCALLBACKLOGOFF(exten@context$|$logintime$|$reason)}
The callback agent logged off. The last login extension and context is
recorded, along with the total time the agent was logged in, and the
reason for the logoff if it was not a normal logoff
(e.g., Autologoff, Chanunavail)
\textbf{COMPLETEAGENT(holdtime$|$calltime$|$origposition)}
The caller was connected to an agent, and the call was terminated normally
by the *agent*. The caller's hold time and the length of the call are both
recorded. The caller's original position in the queue is recorded in
origposition.
\textbf{COMPLETECALLER(holdtime$|$calltime$|$origposition)}
The caller was connected to an agent, and the call was terminated normally
by the *caller*. The caller's hold time and the length of the call are both
recorded. The caller's original position in the queue is recorded in
origposition.
\textbf{CONFIGRELOAD}
The configuration has been reloaded (e.g. with asterisk -rx reload)
\textbf{CONNECT(holdtime$|$bridgedchanneluniqueid$|$ringtime)}
The caller was connected to an agent. Hold time represents the amount
of time the caller was on hold. The bridged channel unique ID contains
the unique ID of the queue member channel that is taking the call. This
is useful when trying to link recording filenames to a particular
call in the queue. Ringtime represents the time the queue members phone
was ringing prior to being answered.
\textbf{ENTERQUEUE(url$|$callerid)}
A call has entered the queue. URL (if specified) and Caller*ID are placed
in the log.
\textbf{EXITEMPTY(position$|$origposition$|$waittime)}
The caller was exited from the queue forcefully because the queue had no
reachable members and it's configured to do that to callers when there
are no reachable members. The position is the caller's position in the
queue when they hungup, the origposition is the original position the
caller was when they first entered the queue, and the waittime is how
long the call had been waiting in the queue at the time of disconnect.
\textbf{EXITWITHKEY(key$|$position$|$origposition$|$waittime)}
The caller elected to use a menu key to exit the queue. The key and
the caller's position in the queue are recorded. The caller's entry
position and amoutn of time waited is also recorded.
\textbf{EXITWITHTIMEOUT(position$|$origposition$|$waittime)}
The caller was on hold too long and the timeout expired. The position in the
queue when the timeout occurred, the entry position, and the amount of time
waited are logged.
\textbf{QUEUESTART}
The queueing system has been started for the first time this session.
\textbf{RINGNOANSWER(ringtime)}
After trying for ringtime ms to connect to the available queue member,
the attempt ended without the member picking up the call. Bad queue
member!
\textbf{SYSCOMPAT}
A call was answered by an agent, but the call was dropped because the
channels were not compatible.
\textbf{TRANSFER(extension$|$context$|$holdtime$|$calltime$|$origposition)}
Caller was transferred to a different extension. Context and extension
are recorded. The caller's hold time and the length of the call are both
recorded, as is the caller's entry position at the time of the transfer.
PLEASE remember that transfers performed by SIP UA's by way of a reinvite
may not always be caught by Asterisk and trigger off this event. The only
way to be 100\% sure that you will get this event when a transfer is
performed by a queue member is to use the built-in transfer functionality
of Asterisk.

View File

@ -1,551 +0,0 @@
\section{Introduction}
Pardon, but the dialplan in this tutorial will be expressed
in AEL, the new Asterisk Extension Language. If you are
not used to its syntax, we hope you will find it to some
degree intuitive. If not, there are documents explaining
its syntax and constructs.
\section{Configuring Call Queues}
\subsection{queues.conf}
First of all, set up call queues in queue.conf
Here is an example:
\begin{astlisting}
\begin{verbatim}
=========== queues.conf ===========
| ; Cool Digium Queues |
| [general] |
| persistentmembers = yes |
| |
| ; General sales queue |
| [sales-general] |
| music=default |
| context=sales |
| strategy=ringall |
| joinempty=strict |
| leavewhenempty=strict |
| |
| ; Customer service queue |
| [customerservice] |
| music=default |
| context=customerservice |
| strategy=ringall |
| joinempty=strict |
| leavewhenempty=strict |
| |
| ; Support dispatch queue |
| [dispatch] |
| music=default |
| context=dispatch |
| strategy=ringall |
| joinempty=strict |
| leavewhenempty=strict |
===================================
\end{verbatim}
\end{astlisting}
In the above, we have defined 3 separate calling queues:
sales-general, customerservice, and dispatch.
Please note that the sales-general queue specifies a
context of "sales", and that customerservice specifies the
context of "customerservice", and the dispatch
queue specifies the context "dispatch". These three
contexts must be defined somewhere in your dialplan.
We will show them after the main menu below.
In the [general] section, specifying the persistentmembers=yes,
will cause the agent lists to be stored in astdb, and
recalled on startup.
The strategy=ringall will cause all agents to be dialed
together, the first to answer is then assigned the incoming
call.
"joinempty" set to "strict" will keep incoming callers from
being placed in queues where there are no agents to take calls.
The Queue() application will return, and the dial plan can
determine what to do next.
If there are calls queued, and the last agent logs out, the
remaining incoming callers will immediately be removed from
the queue, and the Queue() call will return, IF the "leavewhenempty" is
set to "strict".
\subsection{Routing incoming Calls to Queues}
Then in extensions.ael, you can do these things:
\subsubsection{The Main Menu}
At Digium, incoming callers are sent to the "mainmenu" context, where they
are greeted, and directed to the numbers they choose...
\begin{astlisting}
\begin{verbatim}
context mainmenu {
includes {
digium;
queues-loginout;
}
0 => goto dispatch,s,1;
2 => goto sales,s,1;
3 => goto customerservice,s,1;
4 => goto dispatch,s,1;
s => {
Ringing();
Wait(1);
Set(attempts=0);
Answer();
Wait(1);
Background(digium/ThankYouForCallingDigium);
Background(digium/YourOpenSourceTelecommunicationsSupplier);
WaitExten(0.3);
repeat:
Set(attempts=$[${attempts} + 1]);
Background(digium/IfYouKnowYourPartysExtensionYouMayDialItAtAnyTime);
WaitExten(0.1);
Background(digium/Otherwise);
WaitExten(0.1);
Background(digium/ForSalesPleasePress2);
WaitExten(0.2);
Background(digium/ForCustomerServicePleasePress3);
WaitExten(0.2);
Background(digium/ForAllOtherDepartmentsPleasePress4);
WaitExten(0.2);
Background(digium/ToSpeakWithAnOperatorPleasePress0AtAnyTime);
if( ${attempts} < 2 ) {
WaitExten(0.3);
Background(digium/ToHearTheseOptionsRepeatedPleaseHold);
}
WaitExten(5);
if( ${attempts} < 2 ) goto repeat;
Background(digium/YouHaveMadeNoSelection);
Background(digium/ThisCallWillBeEnded);
Background(goodbye);
Hangup();
}
}
\end{verbatim}
\end{astlisting}
\subsubsection{The Contexts referenced from the queues.conf file}
\begin{astlisting}
\begin{verbatim}
context sales {
0 => goto dispatch,s,1;
8 => Voicemail(${SALESVM});
s => {
Ringing();
Wait(2);
Background(digium/ThankYouForContactingTheDigiumSalesDepartment);
WaitExten(0.3);
Background(digium/PleaseHoldAndYourCallWillBeAnsweredByOurNextAvailableSalesRepresentative);
WaitExten(0.3);
Background(digium/AtAnyTimeYouMayPress0ToSpeakWithAnOperatorOr8ToLeaveAMessage);
Set(CALLERID(name)=Sales);
Queue(sales-general,t);
Set(CALLERID(name)=EmptySalQ);
goto dispatch,s,1;
Playback(goodbye);
Hangup();
}
}
\end{verbatim}
\end{astlisting}
Please note that there is only one attempt to queue a call in the sales queue. All sales agents that
are logged in will be rung.
\begin{astlisting}
\begin{verbatim}
context customerservice {
0 => {
SetCIDName(CSVTrans);
goto dispatch|s|1;
}
8 => Voicemail(${CUSTSERVVM});
s => {
Ringing();
Wait(2);
Background(digium/ThankYouForCallingDigiumCustomerService);
WaitExten(0.3);
notracking:
Background(digium/PleaseWaitForTheNextAvailableCustomerServiceRepresentative);
WaitExten(0.3);
Background(digium/AtAnyTimeYouMayPress0ToSpeakWithAnOperatorOr8ToLeaveAMessage);
Set(CALLERID(name)=Cust Svc);
Set(QUEUE_MAX_PENALTY=10);
Queue(customerservice,t);
Set(QUEUE_MAX_PENALTY=0);
Queue(customerservice,t);
Set(CALLERID(name)=EmptyCSVQ);
goto dispatch,s,1;
Background(digium/NoCustomerServiceRepresentativesAreAvailableAtThisTime);
Background(digium/PleaseLeaveAMessageInTheCustomerServiceVoiceMailBox);
Voicemail(${CUSTSERVVM});
Playback(goodbye);
Hangup();
}
}
\end{verbatim}
\end{astlisting}
Note that calls coming into customerservice will first be try to queue
calls to those agents with a QUEUE\_MAX\_PENALTY of 10, and if none are available,
then all agents are rung.
\begin{astlisting}
\begin{verbatim}
context dispatch
{
s => {
Ringing();
Wait(2);
Background(digium/ThankYouForCallingDigium);
WaitExten(0.3);
Background(digium/YourCallWillBeAnsweredByOurNextAvailableOperator);
Background(digium/PleaseHold);
Set(QUEUE_MAX_PENALTY=10);
Queue(dispatch|t);
Set(QUEUE_MAX_PENALTY=20);
Queue(dispatch|t);
Set(QUEUE_MAX_PENALTY=0);
Queue(dispatch|t);
Background(digium/NoOneIsAvailableToTakeYourCall);
Background(digium/PleaseLeaveAMessageInOurGeneralVoiceMailBox);
Voicemail(${DISPATCHVM});
Playback(goodbye);
Hangup();
}
}
\end{verbatim}
\end{astlisting}
And in the dispatch context, first agents of priority 10 are tried, then
20, and if none are available, all agents are tried.
Notice that a common pattern is followed in each of the three queue contexts:
First, you set QUEUE\_MAX\_PENALTY to a value, then you call
Queue($<$queue-name$>$,option,...) (see the Queue application documetation for details)
In the above, note that the "t" option is specified, and this allows the
agent picking up the incoming call the luxury of transferring the call to
other parties.
The purpose of specifying the QUEUE\_MAX\_PENALTY is to develop a set of priorities
amongst agents. By the above usage, agents with lower number priorities will
be given the calls first, and then, if no-one picks up the call, the QUEUE\_MAX\_PENALTY
will be incremented, and the queue tried again. Hopefully, along the line, someone
will pick up the call, and the Queue application will end with a hangup.
The final attempt to queue in most of our examples sets the QUEUE\_MAX\_PENALTY
to zero, which means to try all available agents.
\subsection{Assigning agents to Queues}
In this example dialplan, we want to be able to add and remove agents to
handle incoming calls, as they feel they are available. As they log in,
they are added to the queue's agent list, and as they log out, they are
removed. If no agents are available, the queue command will terminate, and
it is the duty of the dialplan to do something appropriate, be it sending
the incoming caller to voicemail, or trying the queue again with a higher
QUEUE\_MAX\_PENALTY.
Because a single agent can make themselves available to more than one queue,
the process of joining multiple queues can be handled automatically by the
dialplan.
\subsubsection{Agents Log In and Out}
\begin{astlisting}
\begin{verbatim}
context queues-loginout
{
6092 => {
Answer();
Read(AGENT_NUMBER,agent-enternum);
VMAuthenticate(${AGENT_NUMBER}@default,s);
Set(queue-announce-success=1);
goto queues-manip,I${AGENT_NUMBER},1;
}
6093 => {
Answer();
Read(AGENT_NUMBER,agent-enternum);
Set(queue-announce-success=1);
goto queues-manip,O${AGENT_NUMBER},1;
}
}
\end{verbatim}
\end{astlisting}
In the above contexts, the agents dial 6092 to log into their queues,
and they dial 6093 to log out of their queues. The agent is prompted
for their agent number, and if they are logging in, their passcode,
and then they are transferred to the proper extension in the
queues-manip context. The queues-manip context does all the
actual work:
\begin{astlisting}
\begin{verbatim}
context queues-manip {
// Raquel Squelch
_[IO]6121 => {
&queue-addremove(dispatch,10,${EXTEN});
&queue-success(${EXTEN});
}
// Brittanica Spears
_[IO]6165 => {
&queue-addremove(dispatch,20,${EXTEN});
&queue-success(${EXTEN});
}
// Rock Hudson
_[IO]6170 => {
&queue-addremove(sales-general,10,${EXTEN});
&queue-addremove(customerservice,20,${EXTEN});
&queue-addremove(dispatch,30,${EXTEN});
&queue-success(${EXTEN});
}
// Saline Dye-on
_[IO]6070 => {
&queue-addremove(sales-general,20,${EXTEN});
&queue-addremove(customerservice,30,${EXTEN});
&queue-addremove(dispatch,30,${EXTEN});
&queue-success(${EXTEN});
}
}
\end{verbatim}
\end{astlisting}
In the above extensions, note that the queue-addremove macro is used
to actually add or remove the agent from the applicable queue,
with the applicable priority level. Note that agents with a
priority level of 10 will be called before agents with levels
of 20 or 30.
In the above example, Raquel will be dialed first in the dispatch
queue, if she has logged in. If she is not, then the second call of
Queue() with priority of 20 will dial Brittanica if she is present,
otherwise the third call of Queue() with MAX\_PENALTY of 0 will
dial Rock and Saline simultaneously.
Also note that Rock will be among the first to be called in the sales-general
queue, and among the last in the dispatch queue. As you can see in
main menu, the callerID is set in the main menu so they can tell
which queue incoming calls are coming from.
The call to queue-success() gives some feedback to the agent
as they log in and out, that the process has completed.
\begin{astlisting}
\begin{verbatim}
macro queue-success(exten)
{
if( ${queue-announce-success} > 0 )
{
switch(${exten:0:1})
{
case I:
Playback(agent-loginok);
Hangup();
break;
case O:
Playback(agent-loggedoff);
Hangup();
break;
}
}
}
\end{verbatim}
\end{astlisting}
The queue-addremove macro is defined in this manner:
\begin{astlisting}
\begin{verbatim}
macro queue-addremove(queuename,penalty,exten)
{
switch(${exten:0:1})
{
case I: // Login
AddQueueMember(${queuename},Local/${exten:1}@agents,${penalty});
break;
case O: // Logout
RemoveQueueMember(${queuename},Local/${exten:1}@agents);
break;
case P: // Pause
PauseQueueMember(${queuename},Local/${exten:1}@agents);
break;
case U: // Unpause
UnpauseQueueMember(${queuename},Local/${exten:1}@agents);
break;
default: // Invalid
Playback(invalid);
break;
}
}
\end{verbatim}
\end{astlisting}
Basically, it uses the first character of the exten variable, to determine the
proper actions to take. In the above dial plan code, only the cases I or O are used,
which correspond to the Login and Logout actions.
\subsection{Controlling The Way Queues Call the Agents}
Notice in the above, that the commands to manipulate agents in queues have
"@agents" in their arguments. This is a reference to the agents context:
\begin{astlisting}
\begin{verbatim}
context agents
{
// General sales queue
8010 =>
{
Set(QUEUE_MAX_PENALTY=10);
Queue(sales-general,t);
Set(QUEUE_MAX_PENALTY=0);
Queue(sales-general,t);
Set(CALLERID(name)=EmptySalQ);
goto dispatch,s,1;
}
// Customer Service queue
8011 =>
{
Set(QUEUE_MAX_PENALTY=10);
Queue(customerservice,t);
Set(QUEUE_MAX_PENALTY=0);
Queue(customerservice,t);
Set(CALLERID(name)=EMptyCSVQ);
goto dispatch,s,1;
}
8013 =>
{
Dial(iax2/sweatshop/9456@from-ecstacy);
Set(CALLERID(name)=EmptySupQ);
Set(QUEUE_MAX_PENALTY=10);
Queue(support-dispatch,t);
Set(QUEUE_MAX_PENALTY=20);
Queue(support-dispatch,t);
Set(QUEUE_MAX_PENALTY=0); // means no max
Queue(support-dispatch,t);
goto dispatch,s,1;
}
6121 => &callagent(${RAQUEL},${EXTEN});
6165 => &callagent(${SPEARS},${EXTEN});
6170 => &callagent(${ROCK},${EXTEN});
6070 => &callagent(${SALINE},${EXTEN});
}
\end{verbatim}
\end{astlisting}
In the above, the variables \$\{RAQUEL\}, etc stand for
actual devices to ring that person's
phone (like DAHDI/37).
The 8010, 8011, and 8013 extensions are purely for transferring
incoming callers to queues. For instance, a customer service
agent might want to transfer the caller to talk to sales. The
agent only has to transfer to extension 8010, in this case.
Here is the callagent macro, note that if a person in the
queue is called, but does not answer, then they are automatically
removed from the queue.
\begin{astlisting}
\begin{verbatim}
macro callagent(device,exten)
{
if( ${GROUP_COUNT(${exten}@agents)}=0 )
{
Set(OUTBOUND_GROUP=${exten}@agents);
Dial(${device},300,t);
switch(${DIALSTATUS})
{
case BUSY:
Busy();
break;
case NOANSWER:
Set(queue-announce-success=0);
goto queues-manip,O${exten},1;
default:
Hangup();
break;
}
}
else
{
Busy();
}
}
\end{verbatim}
\end{astlisting}
In the callagent macro above, the \$\{exten\} will
be 6121, or 6165, etc, which is the extension of the agent.
The use of the GROUP\_COUNT, and OUTBOUND\_GROUP follow this line
of thinking. Incoming calls can be queued to ring all agents in the
current priority. If some of those agents are already talking, they
would get bothersome call-waiting tones. To avoid this inconvenience,
when an agent gets a call, the OUTBOUND\_GROUP assigns that
conversation to the group specified, for instance 6171@agents.
The \$\{GROUP\_COUNT()\} variable on a subsequent call should return
"1" for that group. If GROUP\_COUNT returns 1, then the busy()
is returned without actually trying to dial the agent.
\subsection{Pre Acknowledgement Message}
If you would like to have a pre acknowledge message with option to reject the message
you can use the following dialplan Macro as a base with the 'M' dial argument.
\begin{astlisting}
\begin{verbatim}
[macro-screen]
exten=>s,1,Wait(.25)
exten=>s,2,Read(ACCEPT,screen-callee-options,1)
exten=>s,3,Gotoif($[${ACCEPT} = 1] ?50)
exten=>s,4,Gotoif($[${ACCEPT} = 2] ?30)
exten=>s,5,Gotoif($[${ACCEPT} = 3] ?40)
exten=>s,6,Gotoif($[${ACCEPT} = 4] ?30:30)
exten=>s,30,Set(MACRO_RESULT=CONTINUE)
exten=>s,40,Read(TEXTEN,custom/screen-exten,)
exten=>s,41,Gotoif($[${LEN(${TEXTEN})} = 3]?42:45)
exten=>s,42,Set(MACRO_RESULT=GOTO:from-internal^${TEXTEN}^1)
exten=>s,45,Gotoif($[${TEXTEN} = 0] ?46:4)
exten=>s,46,Set(MACRO_RESULT=CONTINUE)
exten=>s,50,Playback(after-the-tone)
exten=>s,51,Playback(connected)
exten=>s,52,Playback(beep)
\end{verbatim}
\end{astlisting}
\subsection{Caveats}
In the above examples, some of the possible error checking has been omitted,
to reduce clutter and make the examples clearer.

View File

@ -1,150 +0,0 @@
\subsubsection{Introduction}
The Asterisk Realtime Architecture is a new set of drivers and
functions implemented in Asterisk.
The benefits of this architecture are many, both from a code management
standpoint and from an installation perspective.
The ARA is designed to be independent of storage. Currently, most
drivers are based on SQL, but the architecture should be able to handle
other storage methods in the future, like LDAP.
The main benefit comes in the database support. In Asterisk v1.0 some
functions supported MySQL database, some PostgreSQL and other ODBC.
With the ARA, we have a unified database interface internally in Asterisk,
so if one function supports database integration, all databases that has a
realtime driver will be supported in that function.
Currently there are three realtime database drivers:
\begin{itemize}
\item ODBC: Support for UnixODBC, integrated into Asterisk
The UnixODBC subsystem supports many different databases,
please check \url{www.unixodbc.org} for more information.
\item MySQL: Native support for MySQL, integrated into Asterisk
\item PostgreSQL: Native support for Postgres, integrated into Asterisk
\end{itemize}
\subsubsection{Two modes: Static and Realtime}
The ARA realtime mode is used to dynamically load and update objects.
This mode is used in the SIP and IAX2 channels, as well as in the voicemail
system. For SIP and IAX2 this is similar to the v1.0 MYSQL\_FRIENDS
functionality. With the ARA, we now support many more databases for
dynamic configuration of phones.
The ARA static mode is used to load configuration files. For the Asterisk
modules that read configurations, there's no difference between a static
file in the file system, like extensions.conf, and a configuration loaded
from a database.
You just have to always make sure the var\_metric values are properly set and
ordered as you expect in your database server if you're using the static mode
with ARA (either sequentially or with the same var\_metric value for everybody).
If you have an option that depends on another one in a given configuration
file (i.e, 'musiconhold' depending on 'agent' from agents.conf) but their
var\_metric are not sequential you'll probably get default values being assigned for
those options instead of the desired ones. You can still use the same
var\_metric for all entries in your DB, just make sure the entries
are recorded in an order that does not break the option dependency.
That doesn't happen when you use a static file in the file system. Although
this might be interpreted as a bug or limitation, it is not.
\subsubsection{Realtime SIP friends}
The SIP realtime objects are users and peers that are loaded in memory
when needed, then deleted. This means that Asterisk currently can't handle
voicemail notification and NAT keepalives for these peers. Other than that,
most of the functionality works the same way for realtime friends as for
the ones in static configuration.
With caching, the device stays in memory for a specified time. More
information about this is to be found in the sip.conf sample file.
If you specify a separate family called "sipregs" SIP registration
data will be stored in that table and not in the "sippeers" table.
\subsubsection{Realtime H.323 friends}
Like SIP realtime friends, H.323 friends also can be configured using
dynamic realtime objects.
\subsubsection{New function in the dial plan: The Realtime Switch}
The realtime switch is more than a port of functionality in v1.0 to the
new architecture, this is a new feature of Asterisk based on the
ARA. The realtime switch lets your Asterisk server do database lookups
of extensions in realtime from your dial plan. You can have many Asterisk
servers sharing a dynamically updated dial plan in real time with this
solution.
Note that this switch does NOT support Caller ID matching, only
extension name or pattern matching.
\subsubsection{Capabilities}
The realtime Architecture lets you store all of your configuration in
databases and reload it whenever you want. You can force a reload over
the AMI, Asterisk Manager Interface or by calling Asterisk from a
shell script with
asterisk -rx "reload"
You may also dynamically add SIP and IAX devices and extensions
and making them available without a reload, by using the realtime
objects and the realtime switch.
\subsubsection{Configuration in extconfig.conf}
You configure the ARA in extconfig.conf (yes, it's a strange name, but
is was defined in the early days of the realtime architecture and kind
of stuck).
The part of Asterisk that connects to the ARA use a well defined family
name to find the proper database driver. The syntax is easy:
\begin{verbatim}
<family> => <realtime driver>,<db name>[,<table>]
\end{verbatim}
The options following the realtime driver identified depends on the
driver.
Defined well-known family names are:
\begin{itemize}
\item sippeers, sipusers - SIP peers and users
\item iaxpeers, iaxusers - IAX2 peers and users
\item voicemail - Voicemail accounts
\item queues - Queues
\item queue\_members - Queue members
\item extensions - Realtime extensions (switch)
\end{itemize}
Voicemail storage with the support of ODBC described in file
\path{docs/odbcstorage.tex} (\ref{odbcstorage}).
\subsubsection{Limitations}
Currently, realtime extensions do not support realtime hints. There is
a workaround available by using func\_odbc. See the sample func\_odbc.conf
for more information.
\subsubsection{FreeTDS supported with connection pooling}
In order to use a FreeTDS-based database with realtime, you need to turn
connection pooling on in res\_odbc.conf. This is due to a limitation within
the FreeTDS protocol itself. Please note that this includes databases such
as MS SQL Server and Sybase. This support is new in the current release.
You may notice a performance issue under high load using UnixODBC. The UnixODBC
driver supports threading but you must specifically enable threading within the
UnixODBC configuration file like below for each engine:
Threading = 2
This will enable the driver to service many requests at a time, rather than
serially.

View File

@ -1,45 +0,0 @@
\section{Introduction}
Asterisk supports a channel-agnostic method for handling secure call requirements. Since there is no single meaning of what constitutes a "secure call," Asterisk allows the administrator the control to define "secure" for themselves via the dialplan and channel-specific configuration files.
\section{Channel-specific configuration}
Currently the IAX2 and SIP channels support the call security features in Asterisk. Both channel-specific configuration files (\path{iax2.conf} and \path{sip.conf}) support the encryption=yes setting. For IAX2, this setting causes Asterisk to offer encryption when placing or receiving a call. To force encryption with IAX2, the forceencrypt=yes option is required. Due to limitations of SDP, encryption=yes in \path{sip.conf} results in a call with only a secure media offer, therefor forceencrypt=yes would be redundant in \path{sip.conf}.
If a peer is defined as requiring encryption but the endpoint does not support it, the call will fail with a HANGUPCAUSE of 58 (bearer capability does not exist).
\section{Security-based dialplan branching}
Each channel that supports secure signaling or media can implement a CHANNEL read callback function that specifies whether or not that channel meets the specified criteria. Currently, chan\_iax2 and chan\_sip implement these callbacks. Channels that do not support secure media or signaling will return an empty string when queried. For example, to only allow an inbound call that has both secure signaling and media, see the following example.
\begin{astlisting}
\begin{verbatim}
exten => 123,1,GotoIf("$[${CHANNEL(secure_signaling)}" = ""]?fail)
exten => 123,n,GotoIf("$[${CHANNEL(secure_media)}" = ""]?fail)
exten => 123,n,Dial(SIP/123)
exten => 123,n,Hangup
exten => 123,n(fail),Playback(vm-goodbye)
exten => 123,n,Hangup
\end{verbatim}
\end{astlisting}
\section{Forcing bridged channels to be secure}
Administrators can force outbound channels that are to be bridged to a calling channel to conform to secure media and signaling policies. For example, to first make a call attempt that has both secure signaling and media, but gracefully fall back to non-secure signaling and media see the following example:
\begin{astlisting}
\begin{verbatim}
exten => 123,1,NoOp(We got a call)
exten => 123,n,Set(CHANNEL(secure_bridge_signaling)=1)
exten => 123,n,Set(CHANNEL(secure_bridge_media)=1)
exten => 123,n,Dial(SIP/somebody)
exten => 123,n,NoOp(HANGUPCAUSE=${HANGUPCAUSE})
exten => 123,n,GotoIf($["${HANGUPCAUSE}"="58"]?encrypt_fail)
exten => 123,n,Hangup
; notify user that retrying via insecure channel (user-provided prompt)
exten => 123,n(encrypt_fail),Playback(secure-call-fail-retry)
exten => 123,n,Set(CHANNEL(secure_bridge_signaling)=0)
exten => 123,n,Set(CHANNEL(secure_bridge_media)=0)
exten => 123,n,Dial(SIP/somebody)
exten => 123,n,Hangup
\end{verbatim}
\end{astlisting}

View File

@ -1,250 +0,0 @@
\section{Introduction}
Attacks on Voice over IP networks are becoming increasingly more common. It
has become clear that we must do something within Asterisk to help mitigate
these attacks.
Through a number of discussions with groups of developers in the Asterisk
community, the general consensus is that the best thing that we can do within
Asterisk is to build a framework which recognizes and reports events that could
potentially have security implications. Each channel driver has a different
concept of what is an "event", and then each administrator has different
thresholds of what is a "bad" event and what is a restorative event. The
process of acting upon this information is left to an external program to
correlate and then take action - block traffic, modify dialing rules, etc. It
was decided that embedding actions inside of Asterisk was inappropriate, as the
complexity of construction of such rule sets is difficult and there was no
agreement on where rules should be enabled or how they should be processed. The
addition of a major section of code to handle rule expiration and severity
interpretation was significant. As a final determining factor, there are
external programs and services which already parse log files and act in concert
with packet filters or external devices to protect or alter network security
models for IP connected hosts.
\section{Framework Overview}
This section discusses the architecture of the Asterisk modifications being
proposed.
There are two main components that we propose for the initial
implementation of the security framework:
\begin{itemize}
\item Security Event Generation
\item Security Event Logger
\end{itemize}
\subsection{Security Event Generation}
The ast\_event API is used for the generation of security events. That
way, the events are in an easily interpretable format within Asterisk to
make it easy to write modules that do things with them. There are also some
helper data structures and functions to aid Asterisk modules in reporting these
security events with the proper contents.
The next section of this document contains the current list of security events
being proposed. Each security event type has some required pieces of
information and some other optional pieces of information.
Subscribing to security events from within Asterisk can be done by
subscribing to events of type AST\_EVENT\_SECURITY. These events have an
information element, AST\_EVENT\_IE\_SECURITY\_EVENT, which identifies the security
event sub-type (from the list described in the next section). The result of the
information elements in the events contain the required and optional meta data
associated with the event sub-type.
\subsection{Security Event Logger}
In addition to the infrastructure for generating the events, one module that
is a consumer of these events has been implemented.
Asterisk trunk was recently updated to include support for dynamic logger
levels. This module takes advantage of this functionality to create a
custom "security" logger level. Then, when this module is in use, logger.conf
can be configured to put security events into a file:
\begin{verbatim}
security_log => security
\end{verbatim}
The content of this file is a well defined and easily interpretable
format for external scripts to read and act upon. The definition for the format
of the log file is described later in this chapter.
\section{Events to Log}
\begin{verbatim}
(-) required
(+) optional
Invalid Account ID
(-) Local address family/IP address/port/transport
(-) Remote address family/IP address/port/transport
(-) Service (SIP, AMI, IAX2, ...)
(-) System Name
(+) Module
(+) Account ID (username, etc)
(+) Session ID (CallID, etc)
(+) Session timestamp (required if Session ID present)
(-) Event timestamp (sub-second precision)
Failed ACL match
-> everything from invalid account ID
(+) Name of ACL (when we have named ACLs)
Invalid Challenge/Response
-> everything from invalid account ID
(-) Challenge
(-) Response
(-) Expected Response
Invalid Password
-> everything from invalid account ID
Successful Authentication
-> informational event
-> everything from invalid account ID
Invalid formatting of Request
-> everything from invalid account ID
-> account ID optional
(-) Request Type
(+) Request parameters
Session Limit Reached (such as a call limit)
-> everything from invalid account ID
Memory Limit Reached
-> everything from invalid account ID
Maximum Load Average Reached
-> everything from invalid account ID
Request Not Allowed
-> everything from invalid account ID
(-) Request Type
(+) Request parameters
Request Not Supported
-> everything from invalid account ID
(-) Request Type
Authentication Method Not Allowed
-> everything from invalid account ID
(-) Authentication Method attempted
In dialog message from unexpected host
-> everything from invalid account ID
(-) expected host
\end{verbatim}
\section{Security Log File Format}
The beginning of each line in the log file is the same as it is for other
logger levels within Asterisk.
\begin{verbatim}
[Feb 11 07:57:03] SECURITY[23736] res_security_log.c: <...>
\end{verbatim}
The part of the log entry identified by $<$...$>$ is where the security event
content resides. The security event content is a comma separated list
of key value pairs. The key is the information element type, and the value is a
quoted string that contains the associated meta data for that information
element. Any embedded quotes within the content are escaped with a
backslash.
\begin{verbatim}
INFORMATION_ELEMENT_1="IE1 content",INFORMATION_ELEMENT_2="IE2 content"
\end{verbatim}
The following table includes potential information elements and what the
associated content looks like:
\begin{verbatim}
IE: SecurityEvent
Content: This is the security event sub-type.
Values: FailedACL, InvalidAccountID, SessionLimit, MemoryLimit, LoadAverageLimit,
RequestNotSupported, RequestNotAllowed, AuthMethodNotAllowed,
ReqBadFormat, UnexpectedAddress, ChallengeResponseFailed,
InvalidPassword
IE: EventVersion
Content: This is a numeric value that indicates when updates are made to the
content of the event.
Values: Monotonically increasing integer, starting at 1
IE: Service
Content: This is the Asterisk service that generated the event.
Values: TEST, SIP, AMI
IE: Module
Content: This is the Asterisk module that generated the event.
Values: chan_sip
IE: AccountID
Content: This is a string used to identify the account associated with the
event. In most cases, this would be a username.
IE: SessionID
Content: This is a string used to identify the session associated with the
event. The format of the session identifier is specific to the
service. In the case of SIP, this would be the Call-ID.
IE: SessionTV
Content: The time that the session associated with the SessionID started.
Values: <seconds>-<microseconds> since epoch
IE: ACLName
Content: This is a string that identifies which named ACL is associated with
this event.
IE: LocalAddress
Content: This is the local address that was contacted for the related event.
Values: <Address Family>/<Transport>/<Address>/<Port>
Examples:
-> IPV4/UDP/192.168.1.1/5060
-> IPV4/TCP/192.168.1.1/5038
IE: RemoteAddress
Content: This is the remote address associated with the event.
Examples:
-> IPV4/UDP/192.168.1.2/5060
-> IPV4/TCP/192.168.1.2/5038
IE: ExpectedAddress
Content: This is the address that was expected to be the remote address.
Examples:
-> IPV4/UDP/192.168.1.2/5060
-> IPV4/TCP/192.168.1.2/5038
IE: EventTV
Content: This is the timestamp of when the event occurred.
Values: <seconds>-<microseconds> since epoch
IE: RequestType
Content: This is a service specific string that represents the invalid request
IE: RequestParams
Content: This is a service specific string that represents relevant parameters
given with a request that was considered invalid.
IE: AuthMethod
Content: This is a service specific string that represents an authentication
method that was used or requested.
IE: Challenge
Content: This is a service specific string that represents the challenge
provided to a user attempting challenge/response authentication.
IE: Response
Content: This is a service specific string that represents the response
received from a user attempting challenge/response authentication.
IE: ExpectedResponse
Content: This is a service specific string that represents the response
that was expected to be received from a user attempting
challenge/response authentication.
\end{verbatim}

View File

@ -1,80 +0,0 @@
\subsection{Introduction}
PLEASE READ THE FOLLOWING IMPORTANT SECURITY RELATED INFORMATION.
IMPROPER CONFIGURATION OF ASTERISK COULD ALLOW UNAUTHORIZED USE OF YOUR
FACILITIES, POTENTIALLY INCURRING SUBSTANTIAL CHARGES.
Asterisk security involves both network security (encryption, authentication)
as well as dialplan security (authorization - who can access services in
your pbx). If you are setting up Asterisk in production use, please make
sure you understand the issues involved.
\subsection{Network Security}
If you install Asterisk and use the "make samples" command to install
a demonstration configuration, Asterisk will open a few ports for accepting
VoIP calls. Check the channel configuration files for the ports and IP addresses.
If you enable the manager interface in manager.conf, please make sure that
you access manager in a safe environment or protect it with SSH or other
VPN solutions.
For all TCP/IP connections in Asterisk, you can set ACL lists that
will permit or deny network access to Asterisk services. Please check
the "permit" and "deny" configuration options in manager.conf and
the VoIP channel configurations - i.e. sip.conf and iax.conf.
The IAX2 protocol supports strong RSA key authentication as well as
AES encryption of voice and signalling. The SIP channel does not
support encryption in this version of Asterisk.
\subsection{Dialplan Security}
First and foremost remember this:
USE THE EXTENSION CONTEXTS TO ISOLATE OUTGOING OR TOLL SERVICES FROM ANY
INCOMING CONNECTIONS.
You should consider that if any channel, incoming line, etc can enter an
extension context that it has the capability of accessing any extension
within that context.
Therefore, you should NOT allow access to outgoing or toll services in
contexts that are accessible (especially without a password) from incoming
channels, be they IAX channels, FX or other trunks, or even untrusted
stations within you network. In particular, never ever put outgoing toll
services in the "default" context. To make things easier, you can include
the "default" context within other private contexts by using:
\begin{astlisting}
\begin{verbatim}
include => default
\end{verbatim}
\end{astlisting}
in the appropriate section. A well designed PBX might look like this:
\begin{astlisting}
\begin{verbatim}
[longdistance]
exten => _91NXXNXXXXXX,1,Dial(DAHDI/g2/${EXTEN:1})
include => local
[local]
exten => _9NXXNXXX,1,Dial(DAHDI/g2/${EXTEN:1})
include => default
[default]
exten => 6123,Dial(DAHDI/1)
\end{verbatim}
\end{astlisting}
DON'T FORGET TO TAKE THE DEMO CONTEXT OUT OF YOUR DEFAULT CONTEXT. There
isn't really a security reason, it just will keep people from wanting to
play with your Asterisk setup remotely.
\subsection{Log Security}
Please note that the Asterisk log files, as well as information printed to the
Asterisk CLI, may contain sensitive information such as passwords and call
history. Keep this in mind when providing access to these resources.

View File

@ -1,387 +0,0 @@
%\documentclass[12pt,a4]{article}
%\usepackage{hyperref}
%\author{Russell Bryant \\ Software Engineer \\ Digium, Inc.}
%\title{Shared Line Appearances}
%\begin{document}
%\maketitle
%\tableofcontents
\section{Introduction}
The "SLA" functionality in Asterisk is intended to allow a setup that emulates
a simple key system. It uses the various abstraction layers already built into
Asterisk to emulate key system functionality across various devices, including
IP channels.
\section{Configuration}
\subsection{Summary}
An SLA system is built up of virtual trunks and stations mapped to real
Asterisk devices. The configuration for all of this is done in three
different files: extensions.conf, sla.conf, and the channel specific
configuration file such as sip.conf or dahdi.conf.
\subsection{Dialplan}
The SLA implementation can automatically generate the dialplan necessary for
basic operation if the "autocontext" option is set for trunks and stations in
sla.conf. However, for reference, here is an automatically generated dialplan
to help with custom building of the dialplan to include other features, such as
voicemail (\ref{voicemail}).
However, note that there is a little bit of additional configuration needed if
the trunk is an IP channel. This is discussed in the section on trunks (\ref{trunks}).
There are extensions for incoming calls on a specific trunk, which execute the SLATrunk
application, as well as incoming calls from a station, which execute SLAStation.
Note that there are multiple extensions for incoming calls from a station. This is
because the SLA system has to know whether the phone just went off hook, or if the
user pressed a specific line button.
Also note that there is a hint for every line on every station. This lets the SLA
system control each individual light on every phone to ensure that it shows the
correct state of the line. The phones must subscribe to the state of each of their
line appearances.
Please refer to the examples section for full dialplan samples for SLA.
\subsection{Trunks}
\label{trunks}
An SLA trunk is a mapping between a virtual trunk and a real Asterisk device.
This device may be an analog FXO line, or something like a SIP trunk. A trunk
must be configured in two places. First, configure the device itself in the
channel specific configuration file such as dahdi.conf or sip.conf. Once the
trunk is configured, then map it to an SLA trunk in sla.conf.
\begin{astlisting}
\begin{verbatim}
[line1]
type=trunk
device=DAHDI/1
\end{verbatim}
\end{astlisting}
Be sure to configure the trunk's context to be the same one that is set for the
"autocontext" option in sla.conf if automatic dialplan configuration is used.
This would be done in the regular device entry in dahdi.conf, sip.conf, etc.
Note that the automatic dialplan generation creates the SLATrunk() extension
at extension 's'. This is perfect for DAHDI channels that are FXO trunks, for
example. However, it may not be good enough for an IP trunk, since the call
coming in over the trunk may specify an actual number.
If the dialplan is being built manually, ensure that calls coming in on a trunk
execute the SLATrunk() application with an argument of the trunk name, as shown
in the dialplan example before.
IP trunks can be used, but they require some additional configuration to work.
For this example, let's say we have a SIP trunk called "mytrunk" that is going
to be used as line4. Furthermore, when calls come in on this trunk, they are
going to say that they are calling the number "12564286000". Also, let's say
that the numbers that are valid for calling out this trunk are NANP numbers,
of the form \_1NXXNXXXXXX.
In sip.conf, there would be an entry for [mytrunk]. For [mytrunk],
set context=line4.
\begin{astlisting}
\begin{verbatim}
[line4]
type=trunk
device=Local/disa@line4_outbound
\end{verbatim}
\end{astlisting}
\begin{astlisting}
\begin{verbatim}
[line4]
exten => 12564286000,1,SLATrunk(line4)
[line4_outbound]
exten => disa,1,Disa(no-password,line4_outbound)
exten => _1NXXNXXXXXX,1,Dial(SIP/${EXTEN}@mytrunk)
\end{verbatim}
\end{astlisting}
So, when a station picks up their phone and connects to line 4, they are
connected to the local dialplan. The Disa application plays dialtone to the
phone and collects digits until it matches an extension. In this case, once
the phone dials a number like 12565551212, the call will proceed out the
SIP trunk.
\subsection{Stations}
An SLA station is a mapping between a virtual station and a real Asterisk device.
Currently, the only channel driver that has all of the features necessary to
support an SLA environment is chan\_sip. So, to configure a SIP phone to use
as a station, you must configure sla.conf and sip.conf.
\begin{astlisting}
\begin{verbatim}
[station1]
type=station
device=SIP/station1
trunk=line1
trunk=line2
\end{verbatim}
\end{astlisting}
Here are some hints on configuring a SIP phone for use with SLA:
\begin{enumerate}
\item Add the SIP channel as a [station] in sla.conf.
\item Configure the phone in sip.conf. If automatic dialplan configuration was
used by enabling the "autocontext" option in sla.conf, then this entry in
sip.conf should have the same context setting.
\item On the phone itself, there are various things that must be configured to
make everything work correctly:
Let's say this phone is called "station1" in sla.conf, and it uses trunks
named "line1" and line2".
\begin{enumerate}
\item Two line buttons must be configured to subscribe to the state of the
following extensions:
- station1\_line1
- station1\_line2
\item The line appearance buttons should be configured to dial the extensions
that they are subscribed to when they are pressed.
\item If you would like the phone to automatically connect to a trunk when it
is taken off hook, then the phone should be automatically configured to
dial "station1" when it is taken off hook.
\end{enumerate}
\end{enumerate}
\section{Configuration Examples}
\subsection{Basic SLA}
This is an example of the most basic SLA setup. It uses the automatic
dialplan generation so the configuration is minimal.
sla.conf:
\begin{astlisting}
\begin{verbatim}
[line1]
type=trunk
device=DAHDI/1
autocontext=line1
[line2]
type=trunk
device=DAHDI/2
autocontext=line2
[station](!)
type=station
trunk=line1
trunk=line2
autocontext=sla_stations
[station1](station)
device=SIP/station1
[station2](station)
device=SIP/station2
[station3](station)
device=SIP/station3
\end{verbatim}
\end{astlisting}
With this configuration, the dialplan is generated automatically. The first
DAHDI channel should have its context set to "line1" and the second should be
set to "line2" in dahdi.conf. In sip.conf, station1, station2, and station3
should all have their context set to "sla\_stations".
For reference, here is the automatically generated dialplan for this situation:
\begin{astlisting}
\begin{verbatim}
[line1]
exten => s,1,SLATrunk(line1)
[line2]
exten => s,2,SLATrunk(line2)
[sla_stations]
exten => station1,1,SLAStation(station1)
exten => station1_line1,hint,SLA:station1_line1
exten => station1_line1,1,SLAStation(station1_line1)
exten => station1_line2,hint,SLA:station1_line2
exten => station1_line2,1,SLAStation(station1_line2)
exten => station2,1,SLAStation(station2)
exten => station2_line1,hint,SLA:station2_line1
exten => station2_line1,1,SLAStation(station2_line1)
exten => station2_line2,hint,SLA:station2_line2
exten => station2_line2,1,SLAStation(station2_line2)
exten => station3,1,SLAStation(station3)
exten => station3_line1,hint,SLA:station3_line1
exten => station3_line1,1,SLAStation(station3_line1)
exten => station3_line2,hint,SLA:station3_line2
exten => station3_line2,1,SLAStation(station3_line2)
\end{verbatim}
\end{astlisting}
\subsection{SLA and Voicemail}
\label{voicemail}
This is an example of how you could set up a single voicemail box for the
phone system. The voicemail box number used in this example is 1234, which
would be configured in voicemail.conf.
For this example, assume that there are 2 trunks and 3 stations. The trunks
are DAHDI/1 and DAHDI/2. The stations are SIP/station1, SIP/station2, and
SIP/station3.
In dahdi.conf, channel 1 has context=line1 and channel 2 has context=line2.
In sip.conf, all three stations are configured with context=sla\_stations.
When the stations pick up their phones to dial, they are allowed to dial
NANP numbers for outbound calls, or 8500 for checking voicemail.
sla.conf:
\begin{astlisting}
\begin{verbatim}
[line1]
type=trunk
device=Local/disa@line1_outbound
[line2]
type=trunk
device=Local/disa@line2_outbound
[station](!)
type=station
trunk=line1
trunk=line2
[station1](station)
device=SIP/station1
[station2](station)
device=SIP/station2
[station3](station)
device=SIP/station3
\end{verbatim}
\end{astlisting}
extensions.conf:
\begin{astlisting}
\begin{verbatim}
[macro-slaline]
exten => s,1,SLATrunk(${ARG1})
exten => s,n,Goto(s-${SLATRUNK_STATUS},1)
exten => s-FAILURE,1,Voicemail(1234,u)
exten => s-UNANSWERED,1,Voicemail(1234,u)
[line1]
exten => s,1,Macro(slaline,line1)
[line2]
exten => s,2,Macro(slaline,line2)
[line1_outbound]
exten => disa,1,Disa(no-password,line1_outbound)
exten => _1NXXNXXXXXX,1,Dial(DAHDI/1/${EXTEN})
exten => 8500,1,VoicemailMain(1234)
[line2_outbound]
exten => disa,1,Disa(no-password|line2_outbound)
exten => _1NXXNXXXXXX,1,Dial(DAHDI/2/${EXTEN})
exten => 8500,1,VoicemailMain(1234)
[sla_stations]
exten => station1,1,SLAStation(station1)
exten => station1_line1,hint,SLA:station1_line1
exten => station1_line1,1,SLAStation(station1_line1)
exten => station1_line2,hint,SLA:station1_line2
exten => station1_line2,1,SLAStation(station1_line2)
exten => station2,1,SLAStation(station2)
exten => station2_line1,hint,SLA:station2_line1
exten => station2_line1,1,SLAStation(station2_line1)
exten => station2_line2,hint,SLA:station2_line2
exten => station2_line2,1,SLAStation(station2_line2)
exten => station3,1,SLAStation(station3)
exten => station3_line1,hint,SLA:station3_line1
exten => station3_line1,1,SLAStation(station3_line1)
exten => station3_line2,hint,SLA:station3_line2
exten => station3_line2,1,SLAStation(station3_line2)
\end{verbatim}
\end{astlisting}
\section{Call Handling}
\subsection{Summary}
This section is intended to describe how Asterisk handles calls inside of the
SLA system so that it is clear what behavior is expected.
\subsection{Station goes off hook (not ringing)}
When a station goes off hook, it should initiate a call to Asterisk with the
extension that indicates that the phone went off hook without specifying a
specific line. In the examples in this document, for the station named
"station1", this extension is simply named, "station1".
Asterisk will attempt to connect this station to the first available trunk
that is not in use. Asterisk will check the trunks in the order that they
were specified in the station entry in sla.conf. If all trunks are in use,
the call will be denied.
If Asterisk is able to acquire an idle trunk for this station, then trunk
is connected to the station and the station will hear dialtone. The station
can then proceed to dial a number to call. As soon as a trunk is acquired,
all appearances of this line on stations will show that the line is in use.
\subsection{Station goes off hook (ringing)}
When a station goes off hook while it is ringing, it should simply answer
the call that had been initiated to it to make it ring. Once the station
has answered, Asterisk will figure out which trunk to connect it to. It
will connect it to the highest priority trunk that is currently ringing.
Trunk priority is determined by the order that the trunks are listed in
the station entry in sla.conf.
\subsection{Line button on a station is pressed}
When a line button is pressed on a station, the station should initiate a
call to Asterisk with the extension that indicates which line button was
pressed. In the examples given in this document, for a station named
"station1" and a trunk named "line1", the extension would be "station1\_line1".
If the specified trunk is not in use, then the station will be connected to it and
will hear dialtone. All appearances of this trunk will then show that it
is now in use.
If the specified trunk is on hold by this station, then this station will be
reconnected to the trunk. The line appearance for this trunk on this station
will now show in use. If this was the only station that had the call on hold,
then all appearances of this trunk will now show that it is in use. Otherwise,
all stations that are not currently connected to this trunk will show it
on hold.
If the specified trunk is on hold by a different station, then this station
will be connected to the trunk only if the trunk itself and the station(s) that
have it on hold do not have private hold enabled. If connected, the appeareance
of this trunk on this station will then show in use. All stations that are not
currently connected to this trunk will show it on hold.
%\end{document}

View File

@ -1,80 +0,0 @@
\section{Introduction}
Asterisk utilizes a variety of sound prompts that are available in several file
formats and languages. Multiple languages and formats can be installed on the
same system, and Asterisk will utilize prompts from languages installed, and
will automatically pick the least CPU intensive format that is available on the
system (based on codecs in use, in additional to the codec and format modules
installed and available).
In addition to the prompts available with Asterisk, you can create your own sets
of prompts and utilize them as well. This document will tell you how the prompts
available for Asterisk are created so that the prompts you create can be as close
and consistent in the quality and volume levels as those shipped with Asterisk.
\section{Getting The Sounds Tools}
The sounds tools are available in the publicly accessible repotools repository.
You can check these tools out with Subversion via the following command:
\begin{astlisting}
\begin{verbatim}
# svn co http://svn.asterisk.org/svn/repotools
\end{verbatim}
\end{astlisting}
The sound tools are available in the subdirectory sound_tools/ which contains the
following directories:
\begin{itemize}
\item audiofilter
\item makeg722
\item scripts
\end{itemize}
\section{About The Sounds Tools}
The following sections will describe the sound tools in more detail and explain what
they are used for in the sounds package creation process.
\subsection{audiofilter}
The audiofilter application is used to "tune" the sound files in such a way that
they sound good when being used while in a compressed format. The values in the
scripts for creating the sound files supplied in repotools is essentially a
high-pass filter that drops out audio below 100Hz (or so).
(There is an ITU specification that states for 8KHz audio that is being compressed
frequencies below a certain threshold should be removed because they make the
resulting compressed audio sound worse than it should.)
The audiofilter application is used by the 'converter' script located in the
scripts subdirectory of repotools/sound_tools. The values being passed to the
audiofilter application is as follows:
\begin{astlisting}
\begin{verbatim}
audiofilter -n 0.86916 -1.73829 0.86916 -d 1.00000 -1.74152 0.77536
\end{verbatim}
\end{astlisting}
The two options -n and -d are 'numerator' and 'denominator'. Per the author,
Jean-Marc Valin, "These values are filter coefficients (-n means numerator, -d is
denominator) expressed in the z-transform domain. There represent an elliptic filter
that I designed with Octave such that 'the result sounds good'."
\subsection{makeg722}
The makeg722 application is used by the 'converters' script to generate the G.722
sound files that are shipped with Asterisk. It starts with the RAW sound files and
then converts them to G.722.
\subsection{scripts}
The scripts folder is where all the magic happens. These are the scripts that the
Asterisk open source team use to build the packaged audio files for the various
formats that are distributed with Asterisk.
\begin{itemize}
\item chkcore - used to check that the contents of core-sounds-$<$lang$>$.txt are in sync
\item chkextra - same as above, but checks the extra sound files
\item mkcore - script used to generate the core sounds packages
\item mkextra - script used to generate the extra sounds packages
\item mkmoh - script used to generate the music on hold packages
\item converters - script used to convert the master files to various formats
\end{itemize}

View File

@ -1,90 +0,0 @@
Asterisk Timing Interfaces
-------------------------------------
In the past, if internal timing were desired for an Asterisk system, then the
only source acceptable was from DAHDI. Beginning with Asterisk 1.6.1, a new
timing API was introduced which allows for various timing modules to be used.
Included with Asterisk are the following timing modules:
res_timing_pthread.so
res_timing_dahdi.so
res_timing_timerfd.so (Beginning with Asterisk 1.6.2)
res_timing_pthread uses the POSIX pthreads library in order to provide timing.
Since the code uses a commonly-implemented set of functions, res_timing_pthread
is portable to many types of systems. In fact, this is the only timing source
currently usable on a non-Linux system. Due to the fact that a single userspace
thread is used to provide timing for all users of the timer, res_timing_pthread
is also the least efficient of the timing sources and has been known to lose
its effectiveness in a heavily-loaded environment.
res_timing_dahdi uses timing mechanisms provided by DAHDI. This method of
timing was previously the only means by which Asterisk could receive timing. It
has the benefit of being efficient, and if a system is already going to use
DAHDI hardware, then it makes good sense to use this timing source. If,
however, there is no need for DAHDI other than as a timing source, this timing
source may seem unattractive. For people who are upgrading from 1.4 and are used
to the old ztdummy timing interface, res_timing_dahdi provides the interface
to dahdi_dummy, which is ztdummy's replacement.
res_timing_timerfd uses a timing mechanism provided directly by the Linux
kernel. This timing interface is only available on Linux systems using a kernel
version at least 2.6.25 and a glibc version at least 2.8. This interface has
the benefit of being very efficient, but at the time this is being written,
it is a relatively new feature on Linux, meaning that its availability is not
widespread.
What Asterisk does with the Timing Interfaces
---------------------------------------------
By default, Asterisk will build and load all of the timing interfaces. These
timing interfaces are "ordered" based on a hard-coded priority number defined
in each of the modules. As of the time of this writing, the preferences for the
modules is the following: res_timing_timerfd.so, res_timing_dahdi.so,
res_timing_pthread.so.
The only functionality that requires internal timing is IAX2 trunking. It may
also be used when generating audio for playback, such as from a file. Even
though internal timing is not a requirement for most Asterisk functionality,
it may be advantageous to use it since the alternative is to use timing based
on incoming frames of audio. If there are no incoming frames or if the incoming
frames of audio are from an unreliable or jittery source, then the
corresponding outgoing audio will also be unreliable, or even worse,
nonexistent. Using internal timing prevents such unreliability.
Customizations/Troubleshooting
---------------------------------------------
Now that you know Asterisk's default preferences for timing modules, you may
decide that you have a different preference. Maybe you're on a timerfd-capable
system but you would prefer to get your timing from DAHDI since you already are
using DAHDI to drive your hardware.
Alternatively, you may have been directed to this document due to an error you
are currently experiencing with Asterisk. If you receive an error message
regarding timing not working correctly, then you can use one of the following
suggestions to disable a faulty timing module.
1. Don't build the timing modules you know you will not use. You can disable
the compilation of any of the timing modules using menuselect. The modules are
listed in the "Resource Modules" section. Note that if you have already built
Asterisk and have received an error about a timing module not working properly,
it is not sufficient to disable it from being built. You will need to remove
the module from your modules directory (by default, /usr/lib/asterisk/modules)
to make sure that it does not get loaded again.
2. Build, but do not load the timing modules you know you will not use. You can
edit modules.conf using "noload" lines to disable the loading of specific
timing modules by default. Based on the note in the section above, you may
realize that your Asterisk setup does not require internal timing at all. If
this is the case, you can safely noload all timing modules.
Important Notes
----------------------------------------------
Some confusion has arisen regarding the fact that non-DAHDI timing interfaces
are available now. One common misconception which has arisen is that since
timing can be provided elsewhere, DAHDI is no longer required for using the
MeetMe application. Unfortunately, this is not the case. In addition to
providing timing, DAHDI also provides a conferencing engine which the MeetMe
application requires.
Starting with Asterisk 1.6.2, however, there will be a new application,
ConfBridge, which will be capable of conference bridging without the use
of DAHDI's built-in mixing engine.

View File

@ -1,127 +0,0 @@
This is a channel driver for Unistim protocol. You can use a least a Nortel i2002, i2004 and i2050.
Following features are supported : Send/Receive CallerID, Redial, SoftKeys, SendText(), Music On Hold, Message Waiting Indication (MWI), Distinctive ring, Transfer, Threeway call, History, Forward, Dynamic SoftKeys.
How to configure the i2004 :
- Power on the phone
- Wait for message "Nortel Networks"
- Press quickly the four buttons just below the LCD screen, in sequence from left to right
- If you see "Locating server", power off or reboot the phone and try again
- DHCP : 0
- SET IP : a free ip of your network
- NETMSK / DEF GW : netmask and default gateway
- S1 IP : ip of the asterisk server
- S1 PORT : 5000
- S1 ACTION : 1
- S1 RETRY COUNT : 10
- S2 : same as S1
How to place a call :
- The line=> entry in unistim.conf does not add an extension in asterisk by default.
If you want to do that, add extension=line in your phone context.
- if you have this entry on unistim.conf :
[violet]
device=006038abcdef
line => 102
then use exten => 2100,1,Dial(USTM/102@violet)
- You can display a text with :
exten => 555,1,SendText(Sends text to client. Greetings)
Rebooting a Nortel phone:
- Press mute,up,down,up,down,up,mute,9,release(red button)
Distinctive ring :
- You need to append /r to the dial string.
- The first digit must be from 0 to 7 (inclusive). It's the 'melody' selection.
- The second digit (optional) must be from 0 to 3 (inclusive). It's the ring volume. 0 still produce a sound.
Select the ring style #1 and the default volume :
exten => 2100,1,Dial(USTM/102@violet/r1)
Select the ring style #4 with a very loud volume :
exten => 2100,1,Dial(USTM/102@violet/r43)
Country code :
- You can use the following codes for country= (used for dial tone)
us fr au nl uk fi es jp no at nz tw cl se be sg il br hu lt pl za pt ee mx in de ch dk cn
- If you want a correct ring, busy and congestion tone, you also need a valid entry in
indications.conf and check if res_indications.so is loaded.
language= is also supported but it's only used by Asterisk (for more informations
see http://www.voip-info.org/wiki/view/Asterisk+multi-language ). The end user interface of the phone
will stay in english.
Bookmarks, Softkeys
- Layout :
|--------------------|
| 5 2 |
| 4 1 |
| 3 0 |
- When the second letter of bookmark= is @, then the first character is used for positioning this entry
- If this option is omitted, the bookmark will be added to the next available sofkey
- Also work for linelabel (example : linelabel="5@Line 123")
- You can change a softkey programmatically with SendText(@position@icon@label@extension) ex: SendText(@1@55@Stop Forwd@908)
Autoprovisioning :
- This feature must only be used on a trusted network. It's very insecure : all unistim phones
will be able to use your asterisk pbx.
- You must add an entry called [template]. Each new phones will be based on this profile.
- You must set a least line=>. This value will be incremented when a new phone is registered.
device= must not be specified. By default, the phone will asks for a number. It will be added into
the dialplan. Add extension=line for using the generated line number instead.
Example :
[general]
port=5000
autoprovisioning=yes
[template]
line => 100
bookmark=Support@123 ; Every phone will have a softkey Support
- If a first phone have a mac = 006038abcdef, a new device named USTM/100@006038abcdef will be created.
- If a second phone have a mac = 006038000000, it will be named USTM/101@006038000000 and so on.
- When autoprovisioning=tn, new phones will ask for a tn, if this number match a tn= entry in a device,
this phone will be mapped into.
Example:
[black]
tn=1234
line => 100
- If a user enter TN 1234, the phone will be known as USTM/100@black.
History :
- Use the two keys located in the middle of the Fixed feature keys row (on the bottom of the phone)
to enter call history.
- By default, chan_unistim add any incoming and outgoing calls in files (/var/log/asterisk/unistimHistory)
It can be a privacy issue, you can disable this feature by adding callhistory=0. If history files were created,
you also need to delete them. callhistory=0 will NOT disable normal asterisk CDR logs.
Forward :
- This feature requires chan_local (loaded by default)
Generic asterisk features :
You can use the following entries in unistim.conf
- Billing : accountcode amaflags
- Call Group : callgroup pickupgroup (untested)
- Music On Hold : musiconhold
- Language : language (see section Coutry Code)
- RTP NAT : nat (control ast_rtp_setnat, default = 0. Obscure behaviour)
Trunking :
- It's not possible to connect a Nortel Succession/Meridian/BCM to Asterisk via chan_unistim. Use either E1/T1 trunks, or buy UTPS (UNISTIM Terminal Proxy Server) from Nortel.
Wiki, Additional infos, Comments :
- http://www.voip-info.org/wiki-Asterisk+UNISTIM+channels
*BSD :
- Comment #define HAVE_IP_PKTINFO in chan_unistim.c
- Set public_ip with an IP of your computer
- Check if unistim.conf is in the correct directory
Issues :
- As always, NAT can be tricky. If a phone is behind a NAT, you should port forward UDP 5000 (or change [general] port= in unistim.conf) and UDP 10000 (or change [yourphone] rtp_port=)
- Only one phone per public IP (multiple phones behind the same NAT don't work). You can either :
- Setup a VPN
- Install asterisk inside your NAT. You can use IAX2 trunking if you're master asterisk is outside.
- If asterisk is behind a NAT, you must set [general] public_ip= with your public IP. If you don't do that or the bindaddr is invalid (or no longer valid, eg dynamic IP), phones should be able to display messages but will be unable to send/receive RTP packets (no sound)
- Don't forget : this work is based entirely on a reverse engineering, so you may encounter compatibility issues. At this time, I know three ways to establish a RTP session. You can modify [yourphone] rtp_method= with 0, 1, 2 or 3. 0 is the default method, should work. 1 can be used on new firmware (black i2004) and 2 on old violet i2004. 3 can be used on black i2004 with chrome.
- If you have difficulties, try unistim debug and set verbose 3 on the asterisk CLI. For extra debug, uncomment #define DUMP_PACKET 1 and recompile chan_unistim.

View File

@ -1,24 +0,0 @@
If you're having certain types of crashes, such as those associated with
memory corruption, a bug marshal may ask you to run Asterisk under valgrind.
You should follow these steps, to give the bug marshal the maximum amount
of information about the crash.
1. Run 'make menuselect' and in the Compiler Options, enable MALLOC_DEBUG
and DONT_OPTIMIZE. A bug marshal may also ask you to enable additional
compiler flags, such as DEBUG_THREADS, depending upon the nature of the
issue.
2. Rebuild and install Asterisk.
3. Run Asterisk as follows:
valgrind --suppressions=/usr/src/asterisk/contrib/valgrind.supp --log-fd=9 asterisk -vvvvcg 9>valgrind.txt
Where /usr/src/asterisk/ is location of asterisk source code.
4. Reproduce the issue. Following the manifestation of the issue (or when
the process crashes), upload the valgrind.txt to the issue tracker.
Please note that even if valgrind prevents Asterisk from crashing, the
information logged may STILL be of use to developers, so please upload the
resulting log file whether Asterisk crashes or not.

View File

@ -1,47 +0,0 @@
Asterisk and Video telephony
----------------------------
Asterisk supports video telephony in the core infrastructure. Internally, it's one audio stream
and one video stream in the same call. Some channel drivers and applications has video support,
but not all.
Codecs and formats
------------------
Asterisk supports the following video codecs and file formats. There's no video
transcoding so you have to make sure that both ends support the same video format.
Codec Format
----- ----------
H.263 read/write
H.264 read/write
H.261 - Passthrough only
Note that the file produced by Asterisk video format drivers is in no generic
video format. Gstreamer has support for producing these files and converting from
various video files to Asterisk video+audio files.
Note that H.264 is not enabled by default. You need to add that in the channel
configuration file.
Channel drivers
---------------
SIP The SIP channel driver (chan_sip.so) has support for video
IAX2 Supports video calls (over trunks too)
Local Forwards video calls as a proxy channel
Agent Forwards video calls as a proxy channel
oss Has support for video display/decoding, see video_console.txt
Applications
------------
This is not yet a complete list. These dialplan applications are known to handle video:
voicemail Video voicemail storage (does not attach video to e-mail)
record Records audio and video files (give audio format as argument)
playback Plays a video while being instructed to play audio
echo Echos audio and video back to the user
There is a development group working on enhancing video support for Asterisk.
If you want to participate, join the asterisk-video mailing list on http://lists.digium.com
---
Updates to this file are more than welcome!

View File

@ -1,159 +0,0 @@
--- VIDEO CONSOLE SUPPORT IN ASTERISK ---
Some console drivers (at the moment chan_oss.so) can be built with
support for sending and receiving video. In order to have this
working you need to perform the following steps:
+++ Enable building the video_console support +++
The simplest way to do it is add this one line to channels/Makefile:
chan_oss.so: _ASTCFLAGS+=-DHAVE_VIDEO_CONSOLE
+++ Install prerequisite packages +++
The video_console support relies on the presence of SDL, SDL_image
and ffmpeg libraries, and of course on the availability of X11
On Linux, these are supplied by
libncurses-dev,
libsdl1.2-dev, libsdl-image1.2-dev
libavcodec-dev, libswcale-dev
On FreeBSD, you need the following ports:
multimedia/ffmpeg (2007.10.04)
devel/sdl12 graphics/sdl_image
+++ Build and install asterisk with all the above +++
Make sure you do a 'make clean' and run configure again after you
have installed the required packages, to make sure that the required
pieces are found.
Check that chan_oss.so is generated and correctly installed.
+++ Update configuration files +++
Video support requires explicit configuration as described below:
== oss.conf ==
You need to set various parameters for video console, the easiest
way is to uncomment the following line in oss.conf by removing the
leading ';'
;[general](+,my_video,skin2)
You also need to manually copy the two files
images/kpad2.jpg images/font.png
into the places specified in oss.conf, which in the sample are set to
keypad = /tmp/kpad2.jpg
keypad_font = /tmp/font.png
other configuration parameters are described in oss.conf.sample
== sip.conf ==
To actually run a call using SIP (the same probably applies to iax.conf)
you need to enable video support as following
[general](+)
videosupport=yes
allow=h263 ; this or other video formats
allow=h263p ; this or other video formats
you can add other video formats e.g. h261, h264, mpeg if they are
supported by your version of libavcodec.
+++ RUN THE PROGRAM +++
run asterisk in console mode e.g. asterisk -vdc
If video console support has been successfully compiled in, then
you will see the "console startgui" command available on the CLI`
interface. Run the command, and you should see a window like this:
http://info.iet.unipi.it/~luigi/asterisk_video_console.jpg
To exit from this window, in the console run "console stopgui".
If you want to start a video call, you need to configure your dialplan
so that you can reach (or be reachable) by a peer who can support video.
Once done, a video call is the same as an ordinary call:
"console dial ...", "console answer", "console hangup" all work the same.
To use the GUI, and also configure video sources, see the next section.
+++ VIDEO SOURCES +++
Video sources are declared with the "videodevice=..." lines in oss.conf
where the ... is the name of a device (e.g. /dev/video0 ...) or a
string starting with X11 which identifies one instance of an X11 grabber.
You can have up to 9 sources, displayed in thumbnails in the gui, and
select which one to transmit, possibly using Picture-in-Picture.
For webcams, the only control you have is the image size and frame
rate (which at the moment is the same for all video sources).
X11 grabbers capture a region of the X11 screen (it can contain
anything, even a live video) and use it as the source.
The position of the grab region can be configured using the GUI below
independently for each video source.
The actual video sent to the remote side is the device selected as
"primary" (with the mouse, see below), possibly with a small
'Picture-in-Picture' of the "secondary" device (all selectable
with the mouse).
+++ GUI COMMANDS AND VIDEO SOURCES +++
(most of the text below is taken from channels/console_gui.c)
The GUI is made of 4 areas: remote video on the left, local video
on the right, keypad with all controls and text windows in the
center, and source device thumbnails on the top. The top row is
not displayed if no devices are specified in the config file.
________________________________________________________________
| ______ ______ ______ ______ ______ ______ ______ |
| | tn.1 | | tn.2 | | tn.3 | | tn.4 | | tn.5 | | tn.6 | | tn.7 | |
| |______| |______| |______| |______| |______| |______| |______| |
| ______ ______ ______ ______ ______ ______ ______ |
| |______| |______| |______| |______| |______| |______| |______| |
| _________________ __________________ _________________ |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | remote video | | | | local video | |
| | | | | | ______ | |
| | | | keypad | | | PIP || |
| | | | | | |______|| |
| |_________________| | | |_________________| |
| | | |
| | | |
| |__________________| |
|________________________________________________________________|
The central section is built using an image (jpg, png, maybe gif too)
for the skin and other GUI elements. Comments embedded in the image
indicate to what function each area is mapped to.
Another image (png with transparency) is used for the font.
Mouse and keyboard events are detected on the whole surface, and
handled differently according to their location:
- center/right click on the local/remote window are used to resize
the corresponding window;
- clicks on the thumbnail start/stop sources and select them as
primary or secondary video sources;
- drag on the local video window are used to move the captured
area (in the case of X11 grabber) or the picture-in-picture position;
- keystrokes on the keypad are mapped to the corresponding key;
keystrokes are used as keypad functions, or as text input
if we are in text-input mode.
- drag on some keypad areas (sliders etc.) are mapped to the
corresponding functions (mute/unmute audio and video,
enable/disable Picture-in-Picture, freeze the incoming video,
dial numbers, pick up or hang up a call, ...)
------------------------------------------------------------------------
--- $Id $---

View File

@ -1,454 +0,0 @@
GETTING ODBC STORAGE WITH POSTGRESQL WORKING WITH VOICEMAIL
1) Install PostgreSQL, PostgreSQL-devel, unixODBC, and unixODBC-devel, and
PostgreSQL-ODBC. Make sure PostgreSQL is running and listening on a TCP socket.
2) Log into your server as root, and then type:
[root@localhost ~]# su - postgres
This will log you into the system as the "postgres" user, so that you can
create a new role and database within the PostgreSQL database system. At the
new prompt, type:
$ createuser -s -D -R -l -P -e asterisk
Enter password for new role:
Enter it again:
Obviously you should enter a password when prompted. This creates the
database role (or user).
Next we need to create the asterisk database. Type:
$ createdb -O asterisk -e asterisk
This creates the database and sets the owner of the database to the asterisk
role.
Next, make sure that
you are using md5 authentication for the database user. The line in my
/var/lib/pgsql/data/pg_hba.conf looks like:
# "local" is for Unix domain socket connections only
local asterisk asterisk md5
local all all ident sameuser
# IPv4 local connections:
host all all 127.0.0.1/32 md5
As soon as you're done editing that file, log out as the postgres user.
3) Make sure you have the PostgreSQL odbc driver setup in /etc/odbcinst.ini.
Mine looks like:
[PostgreSQL]
Description = ODBC for PostgreSQL
Driver = /usr/lib/libodbcpsql.so
Setup = /usr/lib/libodbcpsqlS.so
FileUsage = 1
You can confirm that unixODBC is seeing the driver by typing:
[jsmith2@localhost tmp]$ odbcinst -q -d
[PostgreSQL]
4) Setup a DSN in /etc/odbc.ini, pointing at the PostgreSQL database and
driver. Mine looks like:
[testing]
Description = ODBC Testing
Driver = PostgreSQL
Trace = No
TraceFile = sql.log
Database = asterisk
Servername = 127.0.0.1
UserName = asterisk
Password = supersecret
Port = 5432
ReadOnly = No
RowVersioning = No
ShowSystemTables = No
ShowOidColumn = No
FakeOidIndex = No
ConnSettings =
You can confirm that unixODBC sees your DSN by typing:
[jsmith2@localhost tmp]$ odbcinst -q -s
[testing]
5) Test your database connectivity through ODBC. If this doesn't work,
something is wrong with your ODBC setup.
[jsmith2@localhost tmp]$ echo "select 1" | isql -v testing
+---------------------------------------+
| Connected! |
| |
| sql-statement |
| help [tablename] |
| quit |
| |
+---------------------------------------+
SQL> +------------+
| ?column? |
+------------+
| 1 |
+------------+
SQLRowCount returns 1
1 rows fetched
If your ODBC connectivity to PostgreSQL isn't working, you'll see an error
message instead, like this:
[jsmith2@localhost tmp]$ echo "select 1" | isql -v testing
[S1000][unixODBC]Could not connect to the server;
Could not connect to remote socket.
[ISQL]ERROR: Could not SQLConnect
bash: echo: write error: Broken pipe
6) Compile Asterisk with support for ODBC voicemail. Go to your Asterisk
source directory and run `make menuselect`. Under "Voicemail Build Options",
enable "ODBC_STORAGE".
# See doc/README.odbcstorage for more information
Recompile Asterisk and install the new version.
7) Once you've recompiled and re-installed Asterisk, check to make sure
res_odbc.so has been compiled.
localhost*CLI> show modules like res_odbc.so
Module Description Use Count
res_odbc.so ODBC Resource 0
1 modules loaded
8) Now it's time to get Asterisk configured. First, we need to tell Asterisk
about our ODBC setup. Open /etc/asterisk/res_odbc.conf and add the following:
[postgres]
enabled => yes
dsn => testing
pre-connect => yes
9) At the Asterisk CLI, unload and then load the res_odbc.so module. (You
could restart Asterisk as well, but this way makes it easier to tell what's
happening.) Notice how it says it's connected to "postgres", which is our ODBC
connection as defined in res_odbc.conf, which points to the "testing" DSN in
ODBC.
localhost*CLI> unload res_odbc.so
Jan 2 21:19:36 WARNING[8130]: res_odbc.c:498 odbc_obj_disconnect: res_odbc: disconnected 0 from postgres [testing]
Jan 2 21:19:36 NOTICE[8130]: res_odbc.c:589 unload_module: res_odbc unloaded.
localhost*CLI> load res_odbc.so
Loaded /usr/lib/asterisk/modules/res_odbc.so => (ODBC Resource)
== Parsing '/etc/asterisk/res_odbc.conf': Found
Jan 2 21:19:40 NOTICE[8130]: res_odbc.c:266 load_odbc_config: Adding ENV var: INFORMIXSERVER=my_special_database
Jan 2 21:19:40 NOTICE[8130]: res_odbc.c:266 load_odbc_config: Adding ENV var: INFORMIXDIR=/opt/informix
Jan 2 21:19:40 NOTICE[8130]: res_odbc.c:295 load_odbc_config: registered database handle 'postgres' dsn->[testing]
Jan 2 21:19:40 NOTICE[8130]: res_odbc.c:555 odbc_obj_connect: Connecting postgres
Jan 2 21:19:40 NOTICE[8130]: res_odbc.c:570 odbc_obj_connect: res_odbc: Connected to postgres [testing]
Jan 2 21:19:40 NOTICE[8130]: res_odbc.c:600 load_module: res_odbc loaded.
You can also check the status of your ODBC connection at any time from the
Asterisk CLI:
localhost*CLI> odbc show
Name: postgres
DSN: testing
Connected: yes
10) Now we can setup our voicemail table in PostgreSQL. Log into PostgreSQL and
type (or copy and paste) the following:
--
-- First, let's create our large object type, called "lo"
--
CREATE FUNCTION loin (cstring) RETURNS lo AS 'oidin' LANGUAGE internal IMMUTABLE STRICT;
CREATE FUNCTION loout (lo) RETURNS cstring AS 'oidout' LANGUAGE internal IMMUTABLE STRICT;
CREATE FUNCTION lorecv (internal) RETURNS lo AS 'oidrecv' LANGUAGE internal IMMUTABLE STRICT;
CREATE FUNCTION losend (lo) RETURNS bytea AS 'oidrecv' LANGUAGE internal IMMUTABLE STRICT;
CREATE TYPE lo ( INPUT = loin, OUTPUT = loout, RECEIVE = lorecv, SEND = losend, INTERNALLENGTH = 4, PASSEDBYVALUE );
CREATE CAST (lo AS oid) WITHOUT FUNCTION AS IMPLICIT;
CREATE CAST (oid AS lo) WITHOUT FUNCTION AS IMPLICIT;
--
-- If we're not already using plpgsql, then let's use it!
--
CREATE TRUSTED LANGUAGE plpgsql;
--
-- Next, let's create a trigger to cleanup the large object table
-- whenever we update or delete a row from the voicemessages table
--
CREATE FUNCTION vm_lo_cleanup() RETURNS "trigger"
AS $$
declare
msgcount INTEGER;
begin
-- raise notice 'Starting lo_cleanup function for large object with oid %',old.recording;
-- If it is an update action but the BLOB (lo) field was not changed, dont do anything
if (TG_OP = 'UPDATE') then
if ((old.recording = new.recording) or (old.recording is NULL)) then
raise notice 'Not cleaning up the large object table, as recording has not changed';
return new;
end if;
end if;
if (old.recording IS NOT NULL) then
SELECT INTO msgcount COUNT(*) AS COUNT FROM voicemessages WHERE recording = old.recording;
if (msgcount > 0) then
raise notice 'Not deleting record from the large object table, as object is still referenced';
return new;
else
perform lo_unlink(old.recording);
if found then
raise notice 'Cleaning up the large object table';
return new;
else
raise exception 'Failed to cleanup the large object table';
return old;
end if;
end if;
else
raise notice 'No need to cleanup the large object table, no recording on old row';
return new;
end if;
end$$
LANGUAGE plpgsql;
--
-- Now, let's create our voicemessages table
-- This is what holds the voicemail from Asterisk
--
CREATE TABLE voicemessages
(
uniqueid serial PRIMARY KEY,
msgnum int4,
dir varchar(80),
context varchar(80),
macrocontext varchar(80),
callerid varchar(40),
origtime varchar(40),
duration varchar(20),
flag varchar(8),
mailboxuser varchar(80),
mailboxcontext varchar(80),
recording lo,
label varchar(30),
"read" bool DEFAULT false
);
--
-- Let's not forget to make the voicemessages table use the trigger
--
CREATE TRIGGER vm_cleanup AFTER DELETE OR UPDATE ON voicemessages FOR EACH ROW EXECUTE PROCEDURE vm_lo_cleanup();
11) Just as a sanity check, make sure you check the voicemessages table via the
isql utility.
[jsmith2@localhost ODBC]$ echo "SELECT uniqueid, msgnum, dir, duration FROM voicemessages WHERE msgnum = 1" | isql testing
+---------------------------------------+
| Connected! |
| |
| sql-statement |
| help [tablename] |
| quit |
| |
+---------------------------------------+
SQL> +------------+------------+---------------------------------------------------------------------------------+---------------------+
| uniqueid | msgnum | dir | duration |
+------------+------------+---------------------------------------------------------------------------------+---------------------+
+------------+------------+---------------------------------------------------------------------------------+---------------------+
SQLRowCount returns 0
12) Now we can finally configure voicemail in Asterisk to use our database.
Open /etc/asterisk/voicemail.conf, and look in the [general] section. I've
changed the format to gsm (as I can't seem to get WAV or wav working), and
specify both the odbc connection and database table to use.
[general]
; Default formats for writing Voicemail
;format=g723sf|wav49|wav
format=gsm
odbcstorage=postgres
odbctable=voicemessages
You'll also want to create a new voicemail context called "odbctest" to do some
testing, and create a sample mailbox inside that context. Add the following to
the very bottom of voicemail.conf:
[odbctest]
101 => 5555,Example Mailbox
13) Once you've updated voicemail.conf, let's make the changes take effect:
localhost*CLI> unload app_voicemail.so
== Unregistered application 'VoiceMail'
== Unregistered application 'VoiceMailMain'
== Unregistered application 'MailboxExists'
== Unregistered application 'VMAuthenticate'
localhost*CLI> load app_voicemail.so
Loaded /usr/lib/asterisk/modules/app_voicemail.so => (Comedian Mail (Voicemail System))
== Registered application 'VoiceMail'
== Registered application 'VoiceMailMain'
== Registered application 'MailboxExists'
== Registered application 'VMAuthenticate'
== Parsing '/etc/asterisk/voicemail.conf': Found
You can check to make sure your new mailbox exists by typing:
localhost*CLI> show voicemail users for odbctest
Context Mbox User Zone NewMsg
odbctest 101 Example Mailbox 0
14) Now, let's add a new context called "odbc" to extensions.conf. We'll use
these extensions to do some testing:
[odbc]
exten => 100,1,Voicemail(101@odbctest)
exten => 200,1,VoicemailMain(101@odbctest)
15) Next, we need to point a phone at the odbc context. In my case, I've got a
SIP phone called "linksys" that is registering to Asterisk, so I'm setting its
context to the [odbc] context we created in the previous step. The relevant
section of my sip.conf file looks like:
[linksys]
type=friend
secret=verysecret
disallow=all
allow=ulaw
allow=gsm
context=odbc
host=dynamic
qualify=yes
I can check to see that my linksys phone is registered with Asterisk correctly:
localhost*CLI> sip show peers like linksys
Name/username Host Dyn Nat ACL Port Status
linksys/linksys 192.168.0.103 D 5060 OK (9 ms)
1 sip peers [1 online , 0 offline]
16) At last, we're finally ready to leave a voicemail message and have it
stored in our database! (Who'd have guessed it would be this much trouble?!?)
Pick up the phone, dial extension 100, and leave yourself a voicemail message.
In my case, this is what appeared on the Asterisk CLI:
localhost*CLI>
-- Executing VoiceMail("SIP/linksys-10228cac", "101@odbctest") in new stack
-- Playing 'vm-intro' (language 'en')
-- Playing 'beep' (language 'en')
-- Recording the message
-- x=0, open writing: /var/spool/asterisk/voicemail/odbctest/101/tmp/dlZunm format: gsm, 0x101f6534
-- User ended message by pressing #
-- Playing 'auth-thankyou' (language 'en')
== Parsing '/var/spool/asterisk/voicemail/odbctest/101/INBOX/msg0000.txt': Found
Now, we can check the database and make sure the record actually made it into
PostgreSQL, from within the psql utility.
[jsmith2@localhost ~]$ psql
Password:
Welcome to psql 8.1.4, the PostgreSQL interactive terminal.
Type: \copyright for distribution terms
\h for help with SQL commands
\? for help with psql commands
\g or terminate with semicolon to execute query
\q to quit
asterisk=# SELECT * FROM voicemessages;
uniqueid | msgnum | dir | context | macrocontext | callerid | origtime | duration | mailboxuser | mailboxcontext | recording | label | read | sip_id | pabx_id | iax_id
----------+--------+--------------------------------------------------+---------+--------------+-----------------------+------------+----------+-------------+----------------+-----------+-------+------+--------+---------+--------
26 | 0 | /var/spool/asterisk/voicemail/odbctest/101/INBOX | odbc | | "linksys" <linksys> | 1167794179 | 7 | 101 | odbctest | 16599 | | f | | |
(1 row)
Did you notice the the recording column is just a number? When a recording
gets stuck in the database, the audio isn't actually stored in the
voicemessages table. It's stored in a system table called the large object
table. We can look in the large object table and verify that the object
actually exists there:
asterisk=# \lo_list
Large objects
ID | Description
-------+-------------
16599 |
(1 row)
In my case, the OID is 16599. Your OID will almost surely be different. Just
make sure the OID number in the recording column in the voicemessages table
corresponds with a record in the large object table. (The trigger we added to
our voicemessages table was designed to make sure this is always the case.)
We can also pull a copy of the voicemail message back out of the database and
write it to a file, to help us as we debug things:
asterisk=# \lo_export 16599 /tmp/odcb-16599.gsm
lo_export
We can even listen to the file from the Linux command line:
[jsmith2@localhost tmp]$ play /tmp/odcb-16599.gsm
Input Filename : /tmp/odcb-16599.gsm
Sample Size : 8-bits
Sample Encoding: gsm
Channels : 1
Sample Rate : 8000
Time: 00:06.22 [00:00.00] of 00:00.00 ( 0.0%) Output Buffer: 298.36K
Done.
17) Last but not least, we can pull the voicemail message back out of the
database by dialing extension 200 and entering "5555" at the password prompt.
You should see something like this on the Asterisk CLI:
localhost*CLI>
-- Executing VoiceMailMain("SIP/linksys-10228cac", "101@odbctest") in new stack
-- Playing 'vm-password' (language 'en')
-- Playing 'vm-youhave' (language 'en')
-- Playing 'digits/1' (language 'en')
-- Playing 'vm-INBOX' (language 'en')
-- Playing 'vm-message' (language 'en')
-- Playing 'vm-onefor' (language 'en')
-- Playing 'vm-INBOX' (language 'en')
-- Playing 'vm-messages' (language 'en')
-- Playing 'vm-opts' (language 'en')
-- Playing 'vm-first' (language 'en')
-- Playing 'vm-message' (language 'en')
== Parsing '/var/spool/asterisk/voicemail/odbctest/101/INBOX/msg0000.txt': Found
-- Playing 'vm-received' (language 'en')
-- Playing 'digits/at' (language 'en')
-- Playing 'digits/10' (language 'en')
-- Playing 'digits/16' (language 'en')
-- Playing 'digits/p-m' (language 'en')
-- Playing '/var/spool/asterisk/voicemail/odbctest/101/INBOX/msg0000' (language 'en')
-- Playing 'vm-advopts' (language 'en')
-- Playing 'vm-repeat' (language 'en')
-- Playing 'vm-delete' (language 'en')
-- Playing 'vm-toforward' (language 'en')
-- Playing 'vm-savemessage' (language 'en')
-- Playing 'vm-helpexit' (language 'en')
-- Playing 'vm-goodbye' (language 'en')
That's it!
Jared Smith
2 Jan 2006
(updated 11 Mar 2007)