diff --git a/Makefile b/Makefile index 61be67f408..976d5b885f 100644 --- a/Makefile +++ b/Makefile @@ -922,14 +922,6 @@ menuselect-tree: $(foreach dir,$(filter-out main,$(MOD_SUBDIRS)),$(wildcard $(di @cat sounds/sounds.xml >> $@ @echo "" >> $@ -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 diff --git a/build_tools/prep_tarball b/build_tools/prep_tarball index 6fe06c4277..e101c5d039 100755 --- a/build_tools/prep_tarball +++ b/build_tools/prep_tarball @@ -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 diff --git a/doc/CODING-GUIDELINES b/doc/CODING-GUIDELINES deleted file mode 100644 index d1ae32dfe1..0000000000 --- a/doc/CODING-GUIDELINES +++ /dev/null @@ -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 - -- 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 - -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_" -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 - -not - -*CLI> show iax2 peer - -* 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 diff --git a/doc/HOWTO_collect_debug_information.txt b/doc/HOWTO_collect_debug_information.txt deleted file mode 100644 index b9a04ae6b9..0000000000 --- a/doc/HOWTO_collect_debug_information.txt +++ /dev/null @@ -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 diff --git a/doc/India-CID.txt b/doc/India-CID.txt deleted file mode 100644 index 5961bb5559..0000000000 --- a/doc/India-CID.txt +++ /dev/null @@ -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. - - diff --git a/doc/PEERING b/doc/PEERING deleted file mode 100644 index 1a1a25c749..0000000000 --- a/doc/PEERING +++ /dev/null @@ -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} diff --git a/doc/README.txt b/doc/README.txt new file mode 100644 index 0000000000..68a87e11ed --- /dev/null +++ b/doc/README.txt @@ -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 diff --git a/doc/advice_of_charge.txt b/doc/advice_of_charge.txt deleted file mode 100644 index 9673178ad2..0000000000 --- a/doc/advice_of_charge.txt +++ /dev/null @@ -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 diff --git a/doc/asterisk-mib.txt b/doc/asterisk-mib.txt deleted file mode 100644 index e7d6c17191..0000000000 --- a/doc/asterisk-mib.txt +++ /dev/null @@ -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 diff --git a/doc/backtrace.txt b/doc/backtrace.txt deleted file mode 100644 index cf2518de02..0000000000 --- a/doc/backtrace.txt +++ /dev/null @@ -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: - - - -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. diff --git a/doc/building_queues.txt b/doc/building_queues.txt deleted file mode 100644 index a5da7a2f83..0000000000 --- a/doc/building_queues.txt +++ /dev/null @@ -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 - -- 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 - -- 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 to [[[penalty ] as ] state_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 - -- 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 ' 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 - -- 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 - -- 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 [queue [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. diff --git a/doc/callfiles.txt b/doc/callfiles.txt deleted file mode 100644 index 3fe6cb09e6..0000000000 --- a/doc/callfiles.txt +++ /dev/null @@ -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 : 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: the channel to use for the new call, in the form - technology/resource as in the Dial application. This - value is required. - -Callerid: the caller id to use. - -WaitTime: how many seconds to wait for an answer before the call - fails (ring cycle). Default 45 seconds. - -Maxretries: number of retries before failing, not including the - initial attempt. Default = 0 e.g. don't retry if fails. - -RetryTime: how many seconds to wait before retry. The default is - 300 (5 minutes). - -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: the application to execute - -Data: the application arguments - - -To start executing applications in the dialplan: ------------------------------------------------- - -Context: the context in the dialplan - -Extension: the extension in the specified context - -Priority: the priority of the specified extension - (numeric or label) - - - -Setvar: 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: 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: 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: (