[Pkg-voip-commits] [kamailio] 01/09: Imported Upstream version 4.3.0~rc0

Victor Seva Lopez maniac-guest at moszumanska.debian.org
Sat Jun 27 13:32:54 UTC 2015


This is an automated email from the git hooks/post-receive script.

maniac-guest pushed a commit to branch master
in repository kamailio.

commit ac43f78c37a121d3e53737d82013de7865ec1d76
Author: Victor Seva <linuxmaniac at torreviejawireless.org>
Date:   Fri May 29 11:10:24 2015 +0200

    Imported Upstream version 4.3.0~rc0
---
 .cvsignore                                         |    19 +
 .gitignore                                         |    43 +
 AUTHORS                                            |     1 -
 COPYING                                            |    14 +-
 ChangeLog                                          | 15483 +++++++------------
 ISSUES                                             |     2 -
 Makefile                                           |    82 +-
 Makefile.cfg                                       |     6 +-
 Makefile.defs                                      |   101 +-
 Makefile.dirs                                      |     7 +-
 Makefile.groups                                    |    38 +-
 Makefile.libs                                      |     9 +-
 Makefile.modules                                   |    17 +-
 Makefile.radius                                    |     4 +-
 Makefile.rules                                     |    19 +-
 Makefile.shared                                    |     6 +-
 Makefile.sources                                   |     3 +-
 Makefile.targets                                   |    14 +-
 Makefile.utils                                     |     6 +-
 Makefile.vars                                      |     1 -
 NEWS                                               |     2 -
 README                                             |     7 +-
 README-MODULES                                     |    49 +-
 TODO                                               |     1 -
 action.c                                           |    47 +-
 action.h                                           |    16 +-
 async_task.c                                       |    10 +-
 async_task.h                                       |     8 +-
 atomic_ops.c                                       |    14 +-
 atomic_ops.h                                       |     7 +-
 atomic_ops_init.h                                  |    17 +-
 autover.h                                          |     7 -
 basex.c                                            |    11 +-
 basex.h                                            |     5 +-
 bit_count.c                                        |    11 +-
 bit_count.h                                        |    12 +-
 bit_scan.c                                         |    13 +-
 bit_scan.h                                         |     6 +-
 bit_test.h                                         |    12 +-
 cfg.lex                                            |     7 +
 cfg.y                                              |     9 +
 cfg/cfg.c                                          |    11 +-
 cfg/cfg.h                                          |    11 +-
 cfg/cfg_ctx.c                                      |    11 +-
 cfg/cfg_ctx.h                                      |    11 +-
 cfg/cfg_script.c                                   |    12 +-
 cfg/cfg_script.h                                   |    12 +-
 cfg/cfg_select.c                                   |    11 +-
 cfg/cfg_select.h                                   |    11 +-
 cfg/cfg_struct.c                                   |    13 +-
 cfg/cfg_struct.h                                   |    13 +-
 cfg_core.c                                         |    15 +-
 cfg_core.h                                         |    32 +-
 cfg_parser.c                                       |    14 +-
 cfg_parser.h                                       |    10 +-
 char_msg_val.h                                     |    17 +-
 clist.h                                            |    15 +-
 comp_defs.h                                        |    17 +-
 compiler_opt.h                                     |    11 +-
 config.h                                           |    20 +-
 core_cmd.c                                         |    16 +-
 core_cmd.h                                         |    15 +-
 core_stats.h                                       |     7 +-
 counters.c                                         |     9 +-
 counters.h                                         |    10 +-
 crc.c                                              |    10 +-
 crc.h                                              |     1 -
 daemonize.c                                        |    22 +-
 daemonize.h                                        |    15 +-
 data_lump.c                                        |    21 +-
 data_lump.h                                        |    23 +-
 data_lump_rpl.c                                    |    24 +-
 data_lump_rpl.h                                    |    21 +-
 dns_cache.c                                        |    92 +-
 dns_cache.h                                        |    23 +-
 dns_func.c                                         |    15 +-
 dns_func.h                                         |    18 +-
 dns_wrappers.h                                     |    23 +-
 doc/cfg.txt                                        |     6 -
 doc/config_migration.txt                           |     6 -
 doc/cvs-commit-rules.txt                           |    16 +-
 doc/dns.txt                                        |   149 +-
 doc/doxygen/main.dox                               |    13 +-
 doc/dst_blacklist.txt                              |     7 -
 doc/locking.txt                                    |    13 +-
 doc/logging-api.txt                                |     6 +-
 doc/management_api.txt                             |     8 +-
 doc/modules_init.txt                               |    33 +-
 doc/parse_headers.txt                              |     2 -
 doc/rpc/Makefile                                   |     2 +-
 doc/rpc/kamailio_rpc.txt                           |   626 +
 doc/rpc/kamailio_rpc.xml                           |   918 ++
 doc/rpc/ser_rpc.txt                                |   626 -
 doc/rpc/ser_rpc.xml                                |   915 --
 doc/ser.txt                                        |     2 -
 doc/sr-coding-style.txt                            |     6 +-
 doc/stylesheets/dbschema_k/xsl/common.xsl          |    11 +
 doc/stylesheets/dbschema_k/xsl/sql.xsl             |     6 +
 doc/tcp_tunning.txt                                |    17 +-
 doc/timers.txt                                     |    51 +-
 docbook/entities.xml                               |     2 +-
 dprint.c                                           |    16 +-
 dprint.h                                           |     8 +-
 dset.c                                             |    39 +-
 dset.h                                             |    12 +-
 dst_blacklist.c                                    |    29 +-
 dst_blacklist.h                                    |    17 +-
 endianness.c                                       |    11 +-
 endianness.h                                       |     9 +-
 error.c                                            |    19 +-
 error.h                                            |     8 +-
 etc/kamailio-basic.cfg                             |     6 +-
 etc/kamailio-oob.cfg                               |     6 +-
 etc/kamailio.cfg                                   |     6 +-
 events.c                                           |     6 +-
 events.h                                           |     3 +-
 examples/pcscf/kamailio.cfg                        |    37 +-
 examples/scscf/CxDataType_Rel8.xsd                 |   379 +
 examples/scscf/kamailio.cfg                        |     5 +-
 examples/sr                                        |    14 +-
 fastlock.h                                         |    42 +-
 fix_lumps.h                                        |    27 +-
 flags.c                                            |    23 +-
 flags.h                                            |    19 +-
 forward.c                                          |    86 +-
 forward.h                                          |    36 +-
 futexlock.h                                        |    16 +-
 globals.h                                          |    22 +-
 hash_func.c                                        |    15 +-
 hash_func.h                                        |    19 +-
 hashes.h                                           |    35 +-
 id.c                                               |    41 +-
 id.h                                               |    13 +-
 io_wait.c                                          |    18 +-
 io_wait.h                                          |    28 +-
 ip_addr.c                                          |    83 +-
 ip_addr.h                                          |    33 +-
 kstats_types.h                                     |    13 +-
 lib/README                                         |    10 +-
 lib/binrpc/README                                  |     6 +-
 lib/binrpc/binrpc_api.c                            |    20 +-
 lib/binrpc/binrpc_api.h                            |    19 +-
 lib/cds/.cvsignore                                 |     2 +
 lib/doxygen.cfg                                    |     2 +-
 lib/ims/ims_getters.c                              |     2 +-
 lib/kcore/cmpapi.c                                 |     3 +-
 lib/kcore/cmpapi.h                                 |     3 +-
 lib/kcore/faked_msg.c                              |    16 +-
 lib/kcore/faked_msg.h                              |     4 +-
 lib/kcore/kstats_wrapper.c                         |     8 +-
 lib/kcore/kstats_wrapper.h                         |    13 +-
 lib/kcore/parse_privacy.c                          |     1 +
 lib/kcore/parse_privacy.h                          |     2 -
 lib/kcore/parse_sst.c                              |     5 +-
 lib/kcore/parse_sst.h                              |     6 +-
 lib/kcore/radius.h                                 |     7 +-
 lib/kcore/regexp.c                                 |     4 +-
 lib/kcore/regexp.h                                 |     5 +-
 lib/kcore/statistics.c                             |    17 +-
 lib/kcore/statistics.h                             |    11 +-
 lib/kcore/strcommon.c                              |     3 +-
 lib/kcore/strcommon.h                              |     3 +-
 lib/presence/.cvsignore                            |     2 +
 lib/print/.cvsignore                               |     2 +
 lib/shm_regex/README                               |     2 -
 lib/shm_regex/shm_regex.c                          |    18 +-
 lib/shm_regex/shm_regex.h                          |    18 +-
 lib/srdb1/README                                   |     4 +-
 lib/srdb1/db.c                                     |    14 +-
 lib/srdb1/db.h                                     |     2 -
 lib/srdb1/db_cap.h                                 |     2 -
 lib/srdb1/db_con.h                                 |     7 +-
 lib/srdb1/db_id.c                                  |    12 +-
 lib/srdb1/db_id.h                                  |     2 -
 lib/srdb1/db_key.h                                 |     2 -
 lib/srdb1/db_locking.h                             |     2 -
 lib/srdb1/db_op.h                                  |     2 -
 lib/srdb1/db_pool.c                                |     2 -
 lib/srdb1/db_pool.h                                |     2 -
 lib/srdb1/db_pooling.h                             |     2 -
 lib/srdb1/db_query.c                               |    31 +-
 lib/srdb1/db_query.h                               |     2 -
 lib/srdb1/db_res.c                                 |     2 -
 lib/srdb1/db_res.h                                 |     2 -
 lib/srdb1/db_row.c                                 |     2 -
 lib/srdb1/db_row.h                                 |     2 -
 lib/srdb1/db_ut.c                                  |    20 +-
 lib/srdb1/db_ut.h                                  |     5 +-
 lib/srdb1/db_val.c                                 |     2 -
 lib/srdb1/db_val.h                                 |     2 -
 lib/srdb1/schema/acc_cdrs.xml                      |    22 +-
 lib/srdb1/schema/aliases.xml                       |    61 +-
 lib/srdb1/schema/location.xml                      |    35 +-
 lib/srdb1/schema/pr_presentity.xml                 |    10 +-
 lib/srdb1/schema/silo.xml                          |     6 +-
 lib/srdb1/schema/sip_trace.xml                     |    10 +-
 lib/srdb2/db.c                                     |    18 +-
 lib/srdb2/db.h                                     |    13 +-
 lib/srdb2/db_cmd.c                                 |    13 +-
 lib/srdb2/db_cmd.h                                 |    13 +-
 lib/srdb2/db_con.c                                 |    13 +-
 lib/srdb2/db_con.h                                 |    13 +-
 lib/srdb2/db_ctx.c                                 |    10 +-
 lib/srdb2/db_ctx.h                                 |    13 +-
 lib/srdb2/db_drv.c                                 |    13 +-
 lib/srdb2/db_drv.h                                 |    13 +-
 lib/srdb2/db_fld.c                                 |    13 +-
 lib/srdb2/db_fld.h                                 |    13 +-
 lib/srdb2/db_gen.c                                 |    13 +-
 lib/srdb2/db_gen.h                                 |    13 +-
 lib/srdb2/db_pool.c                                |    13 +-
 lib/srdb2/db_pool.h                                |    13 +-
 lib/srdb2/db_rec.c                                 |    13 +-
 lib/srdb2/db_rec.h                                 |    13 +-
 lib/srdb2/db_res.c                                 |    13 +-
 lib/srdb2/db_res.h                                 |    13 +-
 lib/srdb2/db_uri.c                                 |    13 +-
 lib/srdb2/db_uri.h                                 |    13 +-
 lib/srutils/README                                 |     8 +-
 lib/srutils/shautils.c                             |    10 +
 lib/srutils/shautils.h                             |     6 +
 lib/srutils/srjson.c                               |     7 +-
 lib/srutils/srjson.h                               |     6 +
 lib/srutils/sruid.c                                |     7 +-
 lib/srutils/sruid.h                                |     8 +-
 lib/srutils/tmrec.c                                |     5 +-
 list.h                                             |     2 +-
 local_timer.c                                      |    60 +-
 local_timer.h                                      |    24 +-
 lock_alloc.h                                       |    24 +-
 lock_ops.c                                         |    12 +-
 lock_ops.h                                         |    24 +-
 lock_ops_init.h                                    |    14 +-
 locking.h                                          |    28 +-
 lump_struct.h                                      |    31 +-
 lvalue.c                                           |    13 +-
 lvalue.h                                           |     9 +-
 main.c                                             |   108 +-
 md5utils.c                                         |     4 +-
 md5utils.h                                         |    13 +-
 mem/Readme.tlsf.txt                                |   102 +
 mem/f_malloc.c                                     |    26 +-
 mem/f_malloc.h                                     |    13 +-
 mem/ll_malloc.c                                    |    24 +-
 mem/ll_malloc.h                                    |    16 +-
 mem/mem.c                                          |    10 +-
 mem/mem.h                                          |    39 +-
 mem/memdbg.h                                       |     8 +-
 mem/meminfo.h                                      |     9 +-
 mem/memtest.c                                      |     4 +-
 mem/q_malloc.c                                     |    23 +-
 mem/q_malloc.h                                     |    14 +-
 mem/sf_malloc.c                                    |    23 +-
 mem/sf_malloc.h                                    |    15 +-
 mem/shm_mem.c                                      |    16 +-
 mem/shm_mem.h                                      |    33 +-
 mem/src_loc.h                                      |     8 +-
 mem/tlsf.c                                         |  1257 ++
 mem/tlsf.h                                         |    83 +
 mem/tlsfbits.h                                     |   180 +
 mod_fix.c                                          |     8 +-
 mod_fix.h                                          |     7 +-
 modparam.c                                         |    28 +-
 modparam.h                                         |    20 +-
 modules/acc/Makefile                               |     2 -
 modules/acc/README                                 |    38 +-
 modules/acc/acc_api.h                              |     2 +-
 modules/acc/acc_cdr.c                              |    84 +-
 modules/acc/acc_mod.c                              |     2 +
 modules/acc/doc/acc_admin.xml                      |    47 +-
 modules/acc_radius/Makefile                        |     2 -
 modules/alias_db/Makefile                          |     2 -
 modules/app_java/Makefile                          |     2 -
 modules/app_java/app_java_mod.c                    |   257 +
 modules/app_java/app_java_mod.h                    |    27 +
 modules/app_java/global.h                          |     5 +-
 modules/app_java/java_iface.c                      |     6 +-
 modules/app_java/java_iface.h                      |     4 +-
 modules/app_java/java_mod.c                        |   260 -
 modules/app_java/java_mod.h                        |    30 -
 modules/app_java/java_msgobj.c                     |     6 +-
 modules/app_java/java_msgobj.h                     |     4 +-
 modules/app_java/java_native_methods.c             |     6 +-
 modules/app_java/java_native_methods.h             |     4 +-
 modules/app_java/java_sig_parser.c                 |     6 +-
 modules/app_java/java_sig_parser.h                 |     4 +-
 modules/app_java/java_support.c                    |     6 +-
 modules/app_java/java_support.h                    |     4 +-
 modules/app_java/utils.c                           |     6 +-
 modules/app_java/utils.h                           |     4 +-
 modules/app_lua/Makefile                           |    58 +-
 modules/app_lua/app_lua_api.c                      |    16 +-
 modules/app_lua/app_lua_exp.c                      |   394 +-
 modules/app_lua/app_lua_sr.c                       |     8 +-
 modules/app_perl/Makefile                          |     2 -
 modules/app_python/Makefile                        |     2 -
 modules/app_python/mod_Core.c                      |     2 -
 modules/app_python/mod_Core.h                      |     2 -
 modules/app_python/mod_Logger.c                    |     2 -
 modules/app_python/mod_Logger.h                    |     2 -
 modules/app_python/mod_Ranks.c                     |     2 -
 modules/app_python/mod_Ranks.h                     |     3 -
 modules/app_python/mod_Router.c                    |     3 -
 modules/app_python/mod_Router.h                    |     3 -
 modules/app_python/python_exec.c                   |     9 +-
 modules/app_python/python_exec.h                   |     9 +-
 modules/app_python/python_iface.c                  |    15 +-
 modules/app_python/python_iface.h                  |     9 +-
 modules/app_python/python_mod.c                    |     9 +-
 modules/app_python/python_mod.h                    |     9 +-
 modules/app_python/python_msgobj.c                 |     9 +-
 modules/app_python/python_msgobj.h                 |     9 +-
 modules/app_python/python_support.c                |     9 +-
 modules/app_python/python_support.h                |     9 +-
 modules/async/Makefile                             |     1 -
 modules/async/async_mod.c                          |     2 -
 modules/async/async_sleep.c                        |     2 -
 modules/async/async_sleep.h                        |     2 -
 modules/auth/Makefile                              |     1 -
 modules/auth/api.c                                 |    32 +-
 modules/auth/api.h                                 |    26 +-
 modules/auth/auth_mod.c                            |    35 +-
 modules/auth/auth_mod.h                            |    19 +-
 modules/auth/challenge.c                           |    36 +-
 modules/auth/challenge.h                           |    28 +-
 modules/auth/nc.c                                  |    28 +-
 modules/auth/nc.h                                  |    27 +-
 modules/auth/nid.c                                 |    26 +-
 modules/auth/nid.h                                 |    26 +-
 modules/auth/nonce.c                               |    39 +-
 modules/auth/nonce.h                               |    28 +-
 modules/auth/ot_nonce.c                            |    26 +-
 modules/auth/ot_nonce.h                            |    26 +-
 modules/auth/rfc2617.c                             |    27 +-
 modules/auth/rfc2617.h                             |    27 +-
 modules/auth_db/Makefile                           |     1 -
 modules/auth_db/api.h                              |     2 -
 modules/auth_db/auth_db_mod.c                      |   422 +
 modules/auth_db/auth_db_mod.h                      |    55 +
 modules/auth_db/authdb_mod.c                       |   435 -
 modules/auth_db/authdb_mod.h                       |    57 -
 modules/auth_db/authorize.c                        |    13 +-
 modules/auth_db/authorize.h                        |     2 -
 modules/auth_diameter/Makefile                     |     1 -
 modules/auth_ephemeral/Makefile                    |     1 -
 modules/auth_radius/Makefile                       |     1 -
 modules/auth_radius/README                         |    41 +-
 modules/auth_radius/authrad_mod.c                  |    10 +-
 modules/auth_radius/authrad_mod.h                  |     1 +
 modules/auth_radius/doc/auth_radius_admin.xml      |    17 +
 modules/auth_radius/sterman.c                      |   149 +-
 modules/auth_xkeys/Makefile                        |    14 +
 modules/auth_xkeys/README                          |   179 +
 modules/auth_xkeys/auth_xkeys.c                    |   497 +
 modules/auth_xkeys/auth_xkeys.h                    |    35 +
 modules/auth_xkeys/auth_xkeys_mod.c                |   212 +
 modules/auth_xkeys/doc/Makefile                    |     4 +
 modules/auth_xkeys/doc/auth_xkeys.xml              |    36 +
 modules/auth_xkeys/doc/auth_xkeys_admin.xml        |   207 +
 modules/avp/Makefile                               |     1 -
 modules/avpops/Makefile                            |     1 -
 modules/avpops/avpops.c                            |     9 -
 modules/avpops/avpops_db.c                         |     6 -
 modules/avpops/avpops_db.h                         |     6 -
 modules/avpops/avpops_impl.c                       |     7 -
 modules/avpops/avpops_impl.h                       |     5 -
 modules/avpops/avpops_parse.c                      |     7 -
 modules/avpops/avpops_parse.h                      |     5 -
 modules/benchmark/Makefile                         |     1 -
 modules/blst/Makefile                              |     1 -
 modules/blst/blst.c                                |    13 +-
 modules/call_control/Makefile                      |     1 -
 modules/call_control/README                        |     3 +-
 modules/call_control/doc/call_control_admin.xml    |     7 +-
 modules/carrierroute/Makefile                      |     1 -
 modules/carrierroute/carrierroute.c                |    30 +-
 modules/carrierroute/carrierroute.h                |     1 +
 modules/carrierroute/cr_func.c                     |    72 +-
 modules/carrierroute/doc/carrierroute_admin.xml    |    26 +-
 modules/cdp/Makefile                               |     2 +
 modules/cdp/api_process.c                          |     6 +-
 modules/cdp/authstatemachine.c                     |    17 +-
 modules/cdp/cdp_stats.c                            |    49 +
 modules/cdp/cdp_stats.h                            |    18 +
 modules/cdp/config.h                               |     1 +
 modules/cdp/configexample/ConfigExample.xml        |     2 +-
 modules/cdp/configparser.c                         |     9 +-
 modules/cdp/diameter_code_avp.h                    |     1 +
 modules/cdp/diameter_comm.c                        |    24 +-
 modules/cdp/diameter_epc_code_avp.h                |     3 +
 modules/cdp/doc/cdp_admin.xml                      |    18 +
 modules/cdp/mod.c                                  |    31 +-
 modules/cdp/mod.h                                  |     1 -
 modules/cdp/peer.c                                 |     5 +-
 modules/cdp/peer.h                                 |    23 +-
 modules/cdp/peermanager.c                          |     6 +-
 modules/cdp/receiver.c                             |    21 +-
 modules/cdp/routing.c                              |   322 +-
 modules/cdp/routing.h                              |     3 +-
 modules/cdp/session.c                              |     4 +-
 modules/cdp/session.h                              |     2 +
 modules/cdp/statistics.c                           |    56 -
 modules/cdp/statistics.h                           |    57 -
 modules/cdp/transaction.c                          |     6 +-
 modules/cdp/transaction.h                          |     1 -
 modules/cdp/worker.c                               |    15 +
 modules/cdp_avp/epcapp.h                           |    10 +-
 modules/cdp_avp/imsapp.h                           |     2 +
 modules/cfg_db/Makefile                            |     1 -
 modules/cfg_db/README                              |    69 +-
 modules/cfg_db/cfg_db.c                            |    16 +-
 modules/cfg_db/doc/cfg_db.xml                      |     6 +-
 modules/cfg_rpc/Makefile                           |     2 -
 modules/cfg_rpc/README                             |   104 +-
 modules/cfg_rpc/doc/cfg_rpc.xml                    |     6 +-
 modules/cfgutils/Makefile                          |     1 -
 modules/cfgutils/README                            |   117 +-
 modules/cfgutils/cfgutils.c                        |   107 +
 modules/cfgutils/doc/cfgutils.xml                  |     7 +
 modules/cfgutils/doc/cfgutils_admin.xml            |    77 +-
 modules/cnxcc/Makefile                             |     4 +-
 modules/cnxcc/README                               |    30 +-
 modules/cnxcc/cnxcc.c                              |     8 +-
 modules/cnxcc/cnxcc.h                              |     8 +-
 modules/cnxcc/cnxcc_check.c                        |   127 +-
 modules/cnxcc/cnxcc_check.h                        |     2 +-
 modules/cnxcc/cnxcc_mod.c                          |  1293 +-
 modules/cnxcc/cnxcc_mod.h                          |    45 +-
 modules/cnxcc/cnxcc_redis.c                        |   544 +
 modules/cnxcc/cnxcc_redis.h                        |    63 +
 modules/cnxcc/cnxcc_rpc.c                          |   151 +-
 modules/cnxcc/cnxcc_rpc.h                          |     2 +-
 modules/cnxcc/cnxcc_select.c                       |    15 +-
 modules/cnxcc/cnxcc_select.h                       |     2 +-
 modules/cnxcc/cnxcc_sip_msg_faker.c                |    13 +-
 modules/cnxcc/cnxcc_sip_msg_faker.h                |     2 +-
 modules/cnxcc/doc/cnxcc.xml                        |     9 +-
 modules/cnxcc/doc/cnxcc_admin.xml                  |    55 +-
 modules/cnxcc/example/kamailio-cnxcc.cfg           |    14 +-
 modules/corex/Makefile                             |     1 -
 modules/corex/README                               |    42 +-
 modules/corex/doc/corex_admin.xml                  |     6 +-
 modules/counters/Makefile                          |     2 +-
 modules/counters/counters.c                        |    16 +-
 modules/cpl-c/Makefile                             |     1 -
 modules/ctl/Makefile                               |     3 +-
 modules/ctl/README                                 |    85 +-
 modules/ctl/binrpc.c                               |    18 +-
 modules/ctl/binrpc.h                               |    19 +-
 modules/ctl/binrpc_run.c                           |    17 +-
 modules/ctl/binrpc_run.h                           |    17 +-
 modules/ctl/ctl.c                                  |    19 +-
 modules/ctl/ctl.cfg                                |     2 -
 modules/ctl/ctl.h                                  |    13 +-
 modules/ctl/ctl_defaults.h                         |     6 +-
 modules/ctl/ctrl_socks.c                           |    17 +-
 modules/ctl/ctrl_socks.h                           |    17 +-
 modules/ctl/doc/ctl.xml                            |     3 +-
 modules/ctl/doc/ctl_params.xml                     |     3 +-
 modules/ctl/fifo_server.c                          |    40 +-
 modules/ctl/fifo_server.h                          |    14 +-
 modules/ctl/init_socks.c                           |    17 +-
 modules/ctl/init_socks.h                           |    17 +-
 modules/ctl/io_listener.c                          |    17 +-
 modules/ctl/io_listener.h                          |    17 +-
 modules/db2_ldap/Makefile                          |     1 -
 modules/db2_ops/Makefile                           |     1 -
 modules/db2_ops/db2_ops.c                          |    13 +-
 modules/db_berkeley/Makefile                       |     3 +-
 modules/db_berkeley/bdb_cmd.c                      |    16 +-
 modules/db_berkeley/bdb_cmd.h                      |    10 +-
 modules/db_berkeley/bdb_con.c                      |    11 +-
 modules/db_berkeley/bdb_con.h                      |    10 +-
 modules/db_berkeley/bdb_crs_compat.h               |    12 +-
 modules/db_berkeley/bdb_fld.c                      |    10 +-
 modules/db_berkeley/bdb_fld.h                      |    10 +-
 modules/db_berkeley/bdb_lib.c                      |    11 +-
 modules/db_berkeley/bdb_lib.h                      |    11 +-
 modules/db_berkeley/bdb_mod.c                      |    11 +-
 modules/db_berkeley/bdb_mod.h                      |    11 +-
 modules/db_berkeley/bdb_res.c                      |     8 +-
 modules/db_berkeley/bdb_res.h                      |     8 +-
 modules/db_berkeley/bdb_uri.c                      |    10 +-
 modules/db_berkeley/bdb_uri.h                      |    10 +-
 modules/db_berkeley/km_bdb_lib.c                   |    11 +-
 modules/db_berkeley/km_bdb_lib.h                   |    11 +-
 modules/db_berkeley/km_bdb_mi.c                    |    11 +-
 modules/db_berkeley/km_bdb_mi.h                    |     8 +-
 modules/db_berkeley/km_bdb_res.c                   |    15 +-
 modules/db_berkeley/km_bdb_res.h                   |    11 +-
 modules/db_berkeley/km_bdb_util.c                  |    11 +-
 modules/db_berkeley/km_bdb_util.h                  |    11 +-
 modules/db_berkeley/km_bdb_val.c                   |    13 +-
 modules/db_berkeley/km_bdb_val.h                   |    11 +-
 modules/db_berkeley/km_db_berkeley.c               |    19 +-
 modules/db_berkeley/km_db_berkeley.h               |    11 +-
 modules/db_cassandra/Makefile                      |     1 -
 modules/db_flatstore/Makefile                      |     1 -
 modules/db_flatstore/README                        |    95 +-
 modules/db_flatstore/doc/db_flatstore.xml          |    24 +-
 modules/db_mysql/Makefile                          |     1 -
 modules/db_mysql/doc/db_mysql_admin.xml            |    19 +
 modules/db_mysql/km_db_mysql.c                     |     9 +-
 modules/db_mysql/km_db_mysql.h                     |     7 +-
 modules/db_mysql/km_dbase.c                        |    17 +-
 modules/db_mysql/km_dbase.h                        |     2 -
 modules/db_mysql/km_my_con.c                       |    11 +-
 modules/db_mysql/km_my_con.h                       |     2 -
 modules/db_mysql/km_res.c                          |     2 -
 modules/db_mysql/km_res.h                          |     2 -
 modules/db_mysql/km_row.c                          |     2 -
 modules/db_mysql/km_row.h                          |     2 -
 modules/db_mysql/km_val.c                          |     2 -
 modules/db_mysql/km_val.h                          |     2 -
 modules/db_mysql/my_cmd.c                          |    11 +-
 modules/db_mysql/my_cmd.h                          |    13 +-
 modules/db_mysql/my_con.c                          |    13 +-
 modules/db_mysql/my_con.h                          |    13 +-
 modules/db_mysql/my_fld.c                          |    13 +-
 modules/db_mysql/my_fld.h                          |    13 +-
 modules/db_mysql/my_res.c                          |    13 +-
 modules/db_mysql/my_res.h                          |    13 +-
 modules/db_mysql/my_uri.c                          |    13 +-
 modules/db_mysql/my_uri.h                          |    13 +-
 modules/db_mysql/mysql_mod.c                       |    17 +-
 modules/db_mysql/mysql_mod.h                       |    19 +-
 modules/db_oracle/Makefile                         |     1 -
 modules/db_perlvdb/Makefile                        |     1 -
 modules/db_perlvdb/perlvdb_conv.c                  |     3 +
 modules/db_postgres/Makefile                       |     1 -
 modules/db_postgres/README                         |    39 +
 modules/db_postgres/doc/db_postgres_admin.xml      |    49 +
 modules/db_postgres/km_dbase.c                     |    43 +
 modules/db_postgres/km_pg_con.c                    |    36 +-
 modules/db_postgres/pg_cmd.c                       |     8 -
 modules/db_postgres/pg_con.c                       |    38 +-
 modules/db_postgres/pg_mod.c                       |     4 +
 modules/db_postgres/pg_mod.h                       |     2 +
 modules/db_sqlite/Makefile                         |     1 -
 modules/db_text/Makefile                           |     1 -
 modules/db_text/README                             |    54 +-
 modules/db_text/dbt_api.c                          |    17 +-
 modules/db_text/dbt_api.h                          |     6 -
 modules/db_text/dbt_base.c                         |    40 +-
 modules/db_text/dbt_file.c                         |    22 +-
 modules/db_text/dbt_lib.c                          |    12 +-
 modules/db_text/dbt_lib.h                          |     7 +-
 modules/db_text/dbt_raw_query.c                    |   201 +
 modules/db_text/dbt_raw_query.h                    |    37 +
 modules/db_text/dbt_raw_util.c                     |   253 +
 modules/db_text/dbt_raw_util.h                     |    40 +
 modules/db_text/dbt_res.c                          |    12 +-
 modules/db_text/dbt_res.h                          |     7 +-
 modules/db_text/dbt_tb.c                           |     6 -
 modules/db_text/dbt_util.c                         |     6 -
 modules/db_text/dbt_util.h                         |     6 -
 modules/db_text/dbtext.c                           |    14 +-
 modules/db_text/dbtext.h                           |    13 +-
 modules/db_text/doc/db_text.xml                    |     5 +
 modules/db_text/doc/db_text_admin.xml              |    61 +-
 modules/db_unixodbc/Makefile                       |     1 -
 modules/debugger/Makefile                          |     1 -
 modules/debugger/README                            |    48 +-
 modules/debugger/doc/debugger_admin.xml            |     6 +-
 modules/dialog/Makefile                            |     1 -
 modules/dialog/README                              |    86 +-
 modules/dialog/dialog.c                            |    28 +-
 modules/dialog/dlg_cb.c                            |    18 +-
 modules/dialog/dlg_cb.h                            |    19 +-
 modules/dialog/dlg_cseq.c                          |    10 +-
 modules/dialog/dlg_cseq.h                          |     8 +
 modules/dialog/dlg_db_handler.c                    |    14 +-
 modules/dialog/dlg_db_handler.h                    |    11 +-
 modules/dialog/dlg_handlers.c                      |    33 +-
 modules/dialog/dlg_handlers.h                      |     5 -
 modules/dialog/dlg_hash.c                          |    25 +-
 modules/dialog/dlg_hash.h                          |    14 +-
 modules/dialog/dlg_load.h                          |    13 +-
 modules/dialog/dlg_profile.c                       |     4 -
 modules/dialog/dlg_profile.h                       |    11 +-
 modules/dialog/dlg_req_within.c                    |    50 +-
 modules/dialog/dlg_req_within.h                    |    15 +-
 modules/dialog/dlg_timer.c                         |     5 -
 modules/dialog/dlg_timer.h                         |     3 -
 modules/dialog/dlg_transfer.c                      |    12 +-
 modules/dialog/dlg_transfer.h                      |    10 +-
 modules/dialog/dlg_var.c                           |    15 +-
 modules/dialog/dlg_var.h                           |    11 +-
 modules/dialog/doc/dialog_admin.xml                |    27 +
 modules/dialog_ng/Makefile                         |     1 -
 modules/dialog_ng/dialog.c                         |    59 +-
 modules/dialog_ng/dlg_cb.c                         |     2 +-
 modules/dialog_ng/dlg_db_handler.c                 |    10 +-
 modules/dialog_ng/dlg_handlers.c                   |    60 +-
 modules/dialog_ng/dlg_hash.c                       |    57 +-
 modules/dialog_ng/dlg_hash.h                       |     2 +
 modules/dialog_ng/dlg_load.h                       |     9 +-
 modules/dialog_ng/dlg_ng_stats.c                   |    34 +
 modules/dialog_ng/dlg_ng_stats.h                   |    17 +
 modules/dialog_ng/dlg_req_within.h                 |     2 -
 modules/dialplan/Makefile                          |     1 -
 modules/dialplan/README                            |   112 +-
 modules/dialplan/dialplan.c                        |   127 +-
 modules/dialplan/dialplan.h                        |    49 +-
 modules/dialplan/doc/dialplan.xml                  |     8 +
 modules/dialplan/doc/dialplan_admin.xml            |    81 +-
 modules/dialplan/dp_db.c                           |   180 +-
 modules/dialplan/dp_db.h                           |    13 +-
 modules/dialplan/dp_repl.c                         |   353 +-
 modules/dispatcher/Makefile                        |     1 -
 modules/dispatcher/README                          |   410 +-
 modules/dispatcher/api.h                           |     2 -
 modules/dispatcher/config.c                        |    15 +-
 modules/dispatcher/config.h                        |    12 +-
 modules/dispatcher/dispatch.c                      |   226 +-
 modules/dispatcher/dispatch.h                      |    28 +-
 modules/dispatcher/dispatcher.c                    |   136 +-
 modules/dispatcher/doc/dispatcher.xml              |    24 +
 modules/dispatcher/doc/dispatcher_admin.xml        |   111 +-
 modules/dispatcher/ds_ht.c                         |     2 -
 modules/dispatcher/ds_ht.h                         |    17 +-
 modules/diversion/Makefile                         |     1 -
 modules/diversion/diversion.c                      |     2 -
 modules/dmq/Makefile                               |     1 -
 modules/dmq/README                                 |   102 +-
 modules/dmq/bind_dmq.c                             |     2 +-
 modules/dmq/bind_dmq.h                             |     3 +-
 modules/dmq/dmq.c                                  |    26 +-
 modules/dmq/dmq.h                                  |     5 +-
 modules/dmq/dmq_funcs.c                            |     8 +-
 modules/dmq/dmq_funcs.h                            |     2 -
 modules/dmq/dmqnode.c                              |    19 +-
 modules/dmq/dmqnode.h                              |     3 +-
 modules/dmq/doc/dmq.xml                            |     9 +
 modules/dmq/doc/dmq_admin.xml                      |    53 +
 modules/dmq/message.c                              |     2 -
 modules/dmq/message.h                              |     2 -
 modules/dmq/notification_peer.c                    |   328 +-
 modules/dmq/notification_peer.h                    |     5 +-
 modules/dmq/peer.c                                 |     4 +-
 modules/dmq/peer.h                                 |     9 +-
 modules/dmq/worker.c                               |    40 +-
 modules/dmq/worker.h                               |     2 -
 modules/dmq_usrloc/Makefile                        |     9 +
 modules/dmq_usrloc/README                          |    79 +
 modules/dmq_usrloc/dmq_usrloc.c                    |   108 +
 modules/dmq_usrloc/doc/Makefile                    |     4 +
 modules/dmq_usrloc/doc/dmq_usrloc.xml              |    48 +
 modules/dmq_usrloc/doc/dmq_usrloc_admin.xml        |    81 +
 modules/dmq_usrloc/usrloc_sync.c                   |   519 +
 modules/dmq_usrloc/usrloc_sync.h                   |    48 +
 modules/dnssec/Makefile                            |     1 -
 modules/dnssec/dnssec_func.c                       |    15 +-
 modules/dnssec/dnssec_func.h                       |    10 +-
 modules/dnssec/dnssec_mod.c                        |    17 +-
 modules/domain/Makefile                            |     1 -
 modules/domain/domain.c                            |    10 +-
 modules/domain/domain.h                            |     3 +-
 modules/domain/domain_mod.c                        |    15 +-
 modules/domain/domain_mod.h                        |     2 -
 modules/domain/hash.c                              |     2 -
 modules/domain/hash.h                              |     2 -
 modules/domain/mi.c                                |     2 -
 modules/domain/mi.h                                |     2 -
 modules/domainpolicy/Makefile                      |     1 -
 modules/drouting/Makefile                          |     1 -
 modules/drouting/drouting.c                        |     6 +-
 modules/enum/Makefile                              |     1 -
 modules/enum/enum.c                                |     2 -
 modules/enum/enum.h                                |     2 -
 modules/enum/enum_mod.c                            |     7 -
 modules/enum/enum_mod.h                            |     2 -
 modules/erlang/Makefile                            |    26 +
 modules/erlang/README                              |   852 +
 modules/erlang/cnode.c                             |   585 +
 modules/erlang/cnode.h                             |   112 +
 modules/erlang/doc/Makefile                        |     4 +
 modules/erlang/doc/erlang.xml                      |    38 +
 modules/erlang/doc/erlang_admin.xml                |   700 +
 modules/erlang/doc/erlang_devel.xml                |   178 +
 modules/erlang/doc/erlang_use.xml                  |    95 +
 modules/erlang/epmd.c                              |   150 +
 modules/erlang/epmd.h                              |    61 +
 modules/erlang/erl_api.c                           |   343 +
 modules/erlang/erl_api.h                           |    94 +
 modules/erlang/erl_helpers.c                       |   401 +
 modules/erlang/erl_helpers.h                       |   154 +
 modules/erlang/handle_emsg.c                       |   848 +
 modules/erlang/handle_emsg.h                       |    32 +
 modules/erlang/handle_rpc.c                        |  1484 ++
 modules/erlang/handle_rpc.h                        |   102 +
 modules/erlang/mod_erlang.c                        |  1397 ++
 modules/erlang/mod_erlang.h                        |    77 +
 modules/erlang/pv_atom.c                           |   348 +
 modules/erlang/pv_atom.h                           |    37 +
 modules/erlang/pv_list.c                           |   395 +
 modules/erlang/pv_list.h                           |    36 +
 modules/erlang/pv_pid.c                            |   343 +
 modules/erlang/pv_pid.h                            |    37 +
 modules/erlang/pv_ref.c                            |   343 +
 modules/erlang/pv_ref.h                            |    37 +
 modules/erlang/pv_tuple.c                          |   395 +
 modules/erlang/pv_tuple.h                          |    37 +
 modules/erlang/pv_xbuff.c                          |  1247 ++
 modules/erlang/pv_xbuff.h                          |   103 +
 modules/erlang/worker.c                            |   452 +
 modules/erlang/worker.h                            |    59 +
 modules/exec/Makefile                              |     1 -
 modules/exec/exec.c                                |    29 +-
 modules/exec/exec.h                                |    10 +-
 modules/exec/exec_hf.c                             |    16 +-
 modules/exec/exec_hf.h                             |     9 +-
 modules/exec/exec_mod.c                            |    13 +-
 modules/exec/kill.c                                |    16 +-
 modules/exec/kill.h                                |     9 +-
 modules/geoip/Makefile                             |     1 -
 modules/geoip/README                               |     7 +-
 modules/geoip/doc/geoip_admin.xml                  |     7 +-
 modules/geoip/geoip_pv.c                           |     7 +
 modules/geoip2/Makefile                            |    15 +
 modules/geoip2/README                              |   147 +
 modules/geoip2/doc/Makefile                        |     4 +
 modules/geoip2/doc/geoip2.xml                      |    36 +
 modules/geoip2/doc/geoip2_admin.xml                |   178 +
 modules/geoip2/geoip2_mod.c                        |   139 +
 modules/geoip2/geoip2_pv.c                         |   495 +
 modules/geoip2/geoip2_pv.h                         |    40 +
 modules/group/Makefile                             |     1 -
 modules/group/group.c                              |     7 -
 modules/group/group.h                              |     5 -
 modules/group/group_mod.c                          |    11 -
 modules/group/group_mod.h                          |     5 -
 modules/group/re_group.c                           |     5 -
 modules/group/re_group.h                           |     5 -
 modules/h350/Makefile                              |     1 -
 modules/h350/h350_exp_fn.c                         |     6 -
 modules/h350/h350_exp_fn.h                         |     6 -
 modules/h350/h350_mod.c                            |     5 -
 modules/h350/h350_mod.h                            |     5 -
 modules/htable/Makefile                            |     3 +-
 modules/htable/README                              |    53 +-
 modules/htable/api.c                               |     1 -
 modules/htable/api.h                               |     1 -
 modules/htable/doc/htable_admin.xml                |    63 +-
 modules/htable/ht_api.c                            |     1 -
 modules/htable/ht_api.h                            |     1 -
 modules/htable/ht_db.c                             |     1 -
 modules/htable/ht_db.h                             |     1 -
 modules/htable/ht_dmq.c                            |     3 +-
 modules/htable/ht_dmq.h                            |     2 +-
 modules/htable/ht_var.c                            |     1 -
 modules/htable/ht_var.h                            |     1 -
 modules/imc/Makefile                               |     3 +-
 modules/ims_auth/Makefile                          |     1 -
 modules/ims_charging/Makefile                      |     4 +-
 modules/ims_charging/Ro_data.c                     |    17 +-
 modules/ims_charging/Ro_data.h                     |    11 +-
 modules/ims_charging/ccr.c                         |    20 +
 modules/ims_charging/dialog.c                      |    74 +-
 modules/ims_charging/doc/ims_charging_admin.xml    |    40 +-
 modules/ims_charging/ims_charging_stats.c          |    67 +
 modules/ims_charging/ims_charging_stats.h          |    38 +
 modules/ims_charging/ims_ro.c                      |   989 +-
 modules/ims_charging/ims_ro.h                      |     4 +-
 modules/ims_charging/mod.c                         |   184 +-
 modules/ims_charging/mod.h                         |    12 +-
 modules/ims_charging/ro_db_handler.c               |   269 +
 modules/ims_charging/ro_db_handler.h               |    45 +
 modules/ims_charging/ro_session_hash.c             |    52 +-
 modules/ims_charging/ro_session_hash.h             |    23 +-
 modules/ims_charging/ro_timer.c                    |    27 +-
 modules/ims_charging/stats.c                       |    45 -
 modules/ims_charging/stats.h                       |    29 -
 modules/ims_icscf/Makefile                         |     1 -
 modules/ims_icscf/doc/ims_icscf_admin.xml          |    45 +-
 modules/ims_icscf/mod.c                            |     5 +
 modules/ims_icscf/registration.c                   |    30 +-
 modules/ims_icscf/scscf_list.c                     |    53 +-
 modules/ims_isc/Makefile                           |     1 -
 modules/ims_isc/checker.c                          |     2 +-
 modules/ims_isc/mark.c                             |     2 +-
 modules/ims_isc/mod.c                              |    12 +-
 modules/ims_isc/third_party_reg.c                  |   418 +-
 modules/ims_isc/third_party_reg.h                  |     5 +-
 modules/ims_qos/Makefile                           |     1 -
 modules/ims_qos/README                             |   155 +-
 modules/ims_qos/cdpeventprocessor.c                |    50 +-
 modules/ims_qos/cdpeventprocessor.h                |     1 +
 modules/ims_qos/doc/ims_qos.xml                    |    15 +
 modules/ims_qos/doc/ims_qos_admin.xml              |    96 +-
 modules/ims_qos/ims_qos_stats.c                    |   118 +
 modules/ims_qos/ims_qos_stats.h                    |    39 +
 modules/ims_qos/mod.c                              |   306 +-
 modules/ims_qos/rx_aar.c                           |   110 +-
 modules/ims_qos/rx_aar.h                           |     2 +-
 modules/ims_qos/rx_asr.c                           |     7 +-
 modules/ims_qos/rx_authdata.c                      |    17 +-
 modules/ims_qos/rx_authdata.h                      |     7 +-
 modules/ims_qos/rx_avp.c                           |   155 +-
 modules/ims_qos/rx_avp.h                           |     4 +
 modules/ims_registrar_pcscf/Makefile               |     1 -
 modules/ims_registrar_pcscf/async_reginfo.c        |   206 +-
 modules/ims_registrar_pcscf/async_reginfo.h        |    17 +-
 modules/ims_registrar_pcscf/lookup.c               |     7 +-
 modules/ims_registrar_pcscf/notify.c               |    12 +-
 modules/ims_registrar_pcscf/reg_mod.c              |    83 +-
 modules/ims_registrar_pcscf/save.c                 |    15 +-
 modules/ims_registrar_pcscf/service_routes.c       |    49 +-
 modules/ims_registrar_pcscf/service_routes.h       |     5 +
 modules/ims_registrar_pcscf/subscribe.c            |    51 +-
 modules/ims_registrar_pcscf/ul_callback.c          |    46 +-
 modules/ims_registrar_scscf/Makefile               |     7 +-
 modules/ims_registrar_scscf/cxdx_avp.c             |    11 +
 modules/ims_registrar_scscf/cxdx_avp.h             |     1 +
 modules/ims_registrar_scscf/cxdx_callbacks.c       |    88 +
 modules/ims_registrar_scscf/cxdx_callbacks.h       |     3 +
 modules/ims_registrar_scscf/cxdx_sar.c             |     6 +
 .../doc/ims_registrar_scscf_admin.xml              |   166 +-
 modules/ims_registrar_scscf/lookup.c               |   312 +-
 modules/ims_registrar_scscf/lookup.h               |     3 +-
 modules/ims_registrar_scscf/reg_mod.c              |    86 +
 modules/ims_registrar_scscf/registrar_notify.c     |   813 +-
 modules/ims_registrar_scscf/registrar_notify.h     |    10 +-
 modules/ims_registrar_scscf/regpv.c                |     6 +-
 modules/ims_registrar_scscf/reply.c                |    24 +-
 modules/ims_registrar_scscf/reply.h                |     2 +-
 modules/ims_registrar_scscf/save.c                 |    84 +-
 modules/ims_registrar_scscf/sem.h                  |    90 +
 modules/ims_registrar_scscf/userdata_parser.c      |    13 +-
 modules/ims_usrloc_pcscf/Makefile                  |     1 -
 .../doc/ims_usrloc_pcscf_admin.xml                 |    28 +
 modules/ims_usrloc_pcscf/pcontact.c                |     7 +-
 modules/ims_usrloc_pcscf/pcontact.h                |     4 +-
 modules/ims_usrloc_pcscf/udomain.c                 |    92 +-
 modules/ims_usrloc_pcscf/udomain.h                 |     8 +-
 modules/ims_usrloc_pcscf/ul_mod.c                  |     2 +
 modules/ims_usrloc_pcscf/usrloc.c                  |   123 +-
 modules/ims_usrloc_pcscf/usrloc.h                  |    11 +-
 modules/ims_usrloc_scscf/Makefile                  |     3 +-
 modules/ims_usrloc_scscf/bin_utils.c               |     9 +-
 modules/ims_usrloc_scscf/contact_hslot.c           |   221 +
 modules/ims_usrloc_scscf/contact_hslot.h           |   107 +
 modules/ims_usrloc_scscf/dlist.c                   |   185 +-
 modules/ims_usrloc_scscf/hslot_sp.h                |     4 +-
 modules/ims_usrloc_scscf/impurecord.c              |   394 +-
 modules/ims_usrloc_scscf/impurecord.h              |    16 +-
 modules/ims_usrloc_scscf/subscribe.c               |   131 +-
 modules/ims_usrloc_scscf/subscribe.h               |    16 +-
 modules/ims_usrloc_scscf/ucontact.c                |   187 +-
 modules/ims_usrloc_scscf/ucontact.h                |    17 +
 modules/ims_usrloc_scscf/udomain.c                 |   860 +-
 modules/ims_usrloc_scscf/udomain.h                 |    26 +-
 modules/ims_usrloc_scscf/ul_callback.h             |     5 +-
 modules/ims_usrloc_scscf/ul_mod.c                  |    40 +-
 modules/ims_usrloc_scscf/ul_rpc.c                  |   245 +-
 modules/ims_usrloc_scscf/usrloc.c                  |    11 +-
 modules/ims_usrloc_scscf/usrloc.h                  |    75 +-
 modules/ims_usrloc_scscf/usrloc_db.c               |  1225 +-
 modules/ims_usrloc_scscf/usrloc_db.h               |    34 +-
 modules/ipops/README                               |    45 +
 modules/ipops/doc/ipops_admin.xml                  |    85 +
 modules/ipops/ipops_mod.c                          |   890 +-
 modules/ipops/ipops_pv.c                           |   566 +-
 modules/ipops/ipops_pv.h                           |     4 +
 modules/iptrtpproxy/Makefile                       |     3 +-
 .../oob/sip-router-oob-RTPPROXY.cfg.patch          |   373 +
 modules/jansson/Makefile                           |    22 +
 modules/jansson/README                             |   236 +
 modules/jansson/doc/Makefile                       |     4 +
 modules/jansson/doc/jansson.xml                    |    37 +
 modules/jansson/doc/jansson_admin.xml              |   230 +
 modules/jansson/jansson_funcs.c                    |   293 +
 modules/jansson/jansson_funcs.h                    |    35 +
 modules/jansson/jansson_mod.c                      |   149 +
 modules/jansson/jansson_path.c                     |   279 +
 modules/jansson/jansson_path.h                     |    17 +
 modules/jansson/jansson_utils.c                    |    70 +
 modules/jansson/jansson_utils.h                    |    34 +
 modules/janssonrpc-c/Makefile                      |    26 +
 modules/janssonrpc-c/README                        |   355 +
 modules/janssonrpc-c/doc/Makefile                  |     4 +
 modules/janssonrpc-c/doc/janssonrpc-c.xml          |    36 +
 modules/janssonrpc-c/doc/janssonrpc-c_admin.xml    |   408 +
 modules/janssonrpc-c/janssonrpc.h                  |   137 +
 modules/janssonrpc-c/janssonrpc_connect.c          |   317 +
 modules/janssonrpc-c/janssonrpc_connect.h          |    49 +
 modules/janssonrpc-c/janssonrpc_funcs.c            |   265 +
 modules/janssonrpc-c/janssonrpc_funcs.h            |    62 +
 modules/janssonrpc-c/janssonrpc_global.c           |    29 +
 modules/janssonrpc-c/janssonrpc_io.c               |   854 +
 modules/janssonrpc-c/janssonrpc_io.h               |    90 +
 modules/janssonrpc-c/janssonrpc_mod.c              |   362 +
 modules/janssonrpc-c/janssonrpc_request.c          |   340 +
 modules/janssonrpc-c/janssonrpc_request.h          |    65 +
 modules/janssonrpc-c/janssonrpc_server.c           |   611 +
 modules/janssonrpc-c/janssonrpc_server.h           |   130 +
 modules/janssonrpc-c/janssonrpc_srv.c              |   315 +
 modules/janssonrpc-c/janssonrpc_srv.h              |    53 +
 modules/janssonrpc-c/netstring.c                   |   323 +
 modules/janssonrpc-c/netstring.h                   |    62 +
 modules/janssonrpc-c/test/mem-test.sh              |     4 +
 modules/janssonrpc-c/test/run-tests.sh             |     4 +
 modules/janssonrpc-c/test/test.cfg                 |    94 +
 modules/janssonrpc-c/unit_tests/Makefile           |    11 +
 modules/janssonrpc-c/unit_tests/netstring.c        |   351 +
 .../janssonrpc-c/unit_tests/seatest/license.txt    |    19 +
 modules/janssonrpc-c/unit_tests/seatest/seatest.c  |   248 +
 modules/janssonrpc-c/unit_tests/seatest/seatest.h  |    74 +
 modules/janssonrpc-c/unit_tests/test.h             |    48 +
 modules/json/.gitignore                            |     4 +
 modules/jsonrpc-c/.gitignore                       |    10 +
 modules/jsonrpc-c/TODO                             |     1 +
 modules/jsonrpc-c/jsonrpc.c                        |     3 +-
 modules/jsonrpc-c/jsonrpc.h                        |     3 +-
 modules/jsonrpc-c/jsonrpc_io.c                     |     3 +-
 modules/jsonrpc-c/jsonrpc_io.h                     |     3 +-
 modules/jsonrpc-c/jsonrpc_mod.c                    |     3 +-
 modules/jsonrpc-c/jsonrpc_request.c                |     4 +-
 modules/jsonrpc-c/jsonrpc_request.h                |     4 +-
 modules/jsonrpc-c/netstring.c                      |     4 +-
 modules/jsonrpc-c/netstring.h                      |     4 +-
 modules/jsonrpc-s/Makefile                         |     1 +
 modules/jsonrpc-s/README                           |   181 +-
 modules/jsonrpc-s/doc/jsonrpc-s_admin.xml          |   220 +-
 modules/jsonrpc-s/jsonrpc-s_mod.c                  |   617 +-
 modules/kazoo/Makefile                             |     1 -
 modules/kazoo/kz_json.c                            |     2 +-
 modules/kazoo/kz_trans.c                           |    22 +-
 modules/kex/Makefile                               |     1 -
 modules/ldap/Makefile                              |     1 -
 modules/ldap/api.h                                 |     5 -
 modules/ldap/iniparser.c                           |     5 -
 modules/ldap/iniparser.h                           |     5 -
 modules/ldap/ld_session.c                          |     5 -
 modules/ldap/ld_session.h                          |     5 -
 modules/ldap/ldap_api_fn.c                         |     5 -
 modules/ldap/ldap_api_fn.h                         |     5 -
 modules/ldap/ldap_connect.c                        |     5 -
 modules/ldap/ldap_connect.h                        |     5 -
 modules/ldap/ldap_escape.c                         |     5 -
 modules/ldap/ldap_escape.h                         |     5 -
 modules/ldap/ldap_exp_fn.c                         |     5 -
 modules/ldap/ldap_exp_fn.h                         |     5 -
 modules/ldap/ldap_mod.c                            |     5 -
 modules/malloc_test/Makefile                       |     1 -
 modules/mangler/Makefile                           |     3 +-
 modules/mangler/README                             |   115 +-
 modules/mangler/common.h                           |    16 +-
 modules/mangler/contact_ops.c                      |    18 +-
 modules/mangler/contact_ops.h                      |    17 +-
 modules/mangler/doc/mangler_functions.xml          |    28 +-
 modules/mangler/doc/mangler_params.xml             |    12 +-
 modules/mangler/ip_helper.c                        |    17 +-
 modules/mangler/ip_helper.h                        |    18 +-
 modules/mangler/mangler.c                          |    20 +-
 modules/mangler/mangler.h                          |    18 +-
 modules/mangler/sdp_mangler.c                      |    17 +-
 modules/mangler/sdp_mangler.h                      |    17 +-
 modules/mangler/utils.c                            |    17 +-
 modules/mangler/utils.h                            |    17 +-
 modules/matrix/matrix.c                            |     8 +-
 modules/maxfwd/Makefile                            |     3 +-
 modules/mediaproxy/Makefile                        |     1 -
 modules/memcached/Makefile                         |     1 -
 modules/mi_datagram/Makefile                       |     3 +-
 modules/mi_datagram/datagram_fnc.c                 |     4 +-
 modules/mi_fifo/Makefile                           |     3 +-
 modules/mi_fifo/README                             |    10 +-
 modules/mi_fifo/doc/mi_fifo_admin.xml              |    11 +-
 modules/mi_fifo/mi_fifo.c                          |    25 +-
 modules/mi_rpc/Makefile                            |     1 -
 modules/mi_rpc/mi_rpc_mod.c                        |     2 -
 modules/misc_radius/Makefile                       |     1 -
 modules/mohqueue/Makefile                          |     3 +-
 modules/mohqueue/mohq.c                            |   114 +-
 modules/mohqueue/mohq.h                            |     6 +-
 modules/mohqueue/mohq_common.h                     |     5 +-
 modules/mohqueue/mohq_db.c                         |    20 +-
 modules/mohqueue/mohq_db.h                         |     6 +-
 modules/mohqueue/mohq_funcs.c                      |    62 +-
 modules/mohqueue/mohq_funcs.h                      |     6 +-
 modules/mohqueue/mohq_locks.c                      |     6 +-
 modules/mohqueue/mohq_locks.h                      |     6 +-
 modules/mqueue/Makefile                            |     1 -
 modules/msilo/Makefile                             |     3 +-
 modules/msilo/README                               |    31 +-
 modules/msilo/api.h                                |     4 +-
 modules/msilo/doc/msilo_admin.xml                  |    25 +
 modules/msilo/ms_msg_list.c                        |     5 -
 modules/msilo/ms_msg_list.h                        |     5 -
 modules/msilo/msfuncs.c                            |     2 -
 modules/msilo/msfuncs.h                            |     2 -
 modules/msilo/msilo.c                              |    38 +-
 modules/msrp/Makefile                              |     1 -
 modules/msrp/msrp_cmap.c                           |     2 -
 modules/msrp/msrp_cmap.h                           |     2 -
 modules/msrp/msrp_env.c                            |     2 -
 modules/msrp/msrp_env.h                            |     2 -
 modules/msrp/msrp_mod.c                            |     2 -
 modules/msrp/msrp_netio.c                          |     2 -
 modules/msrp/msrp_netio.h                          |     2 -
 modules/msrp/msrp_parser.c                         |     2 -
 modules/msrp/msrp_parser.h                         |     2 -
 modules/msrp/msrp_vars.c                           |     2 -
 modules/msrp/msrp_vars.h                           |     2 -
 modules/mtree/Makefile                             |     1 -
 modules/nat_traversal/Makefile                     |     1 -
 modules/nat_traversal/nat_traversal.c              |    18 +-
 modules/nathelper/Makefile                         |     3 +-
 modules/nathelper/README                           |    60 +-
 modules/nathelper/doc/nathelper_admin.xml          |    19 +
 modules/nathelper/nathelper.c                      |   110 +-
 modules/ndb_cassandra/.gitignore                   |     1 +
 modules/ndb_mongodb/README                         |    55 +-
 modules/ndb_mongodb/api.h                          |    69 +
 modules/ndb_mongodb/doc/ndb_mongodb_admin.xml      |    24 +
 modules/ndb_mongodb/mongodb_client.c               |    36 +-
 modules/ndb_mongodb/mongodb_client.h               |     1 +
 modules/ndb_mongodb/ndb_mongodb_mod.c              |    21 +-
 modules/ndb_redis/README                           |    41 +-
 modules/ndb_redis/doc/ndb_redis_admin.xml          |    36 +-
 modules/ndb_redis/ndb_redis_mod.c                  |     7 +-
 modules/ndb_redis/redis_client.c                   |    45 +-
 modules/ndb_redis/redis_client.h                   |     1 +
 modules/outbound/Makefile                          |     2 -
 modules/p_usrloc/Makefile                          |     3 +-
 modules/p_usrloc/dlist.c                           |     7 -
 modules/p_usrloc/dlist.h                           |     7 -
 modules/p_usrloc/hslot.c                           |     2 -
 modules/p_usrloc/hslot.h                           |     2 -
 modules/p_usrloc/p_usrloc_mod.c                    |    13 -
 modules/p_usrloc/p_usrloc_mod.h                    |     4 -
 modules/p_usrloc/ucontact.c                        |     7 -
 modules/p_usrloc/ucontact.h                        |     7 -
 modules/p_usrloc/udomain.c                         |     9 -
 modules/p_usrloc/udomain.h                         |     8 -
 modules/p_usrloc/ul_callback.c                     |     5 -
 modules/p_usrloc/ul_mi.c                           |     6 -
 modules/p_usrloc/ul_mi.h                           |     2 -
 modules/p_usrloc/urecord.c                         |     7 -
 modules/p_usrloc/urecord.h                         |     2 -
 modules/p_usrloc/usrloc.c                          |     7 -
 modules/p_usrloc/utime.c                           |     2 -
 modules/p_usrloc/utime.h                           |     2 -
 modules/path/Makefile                              |     1 -
 modules/pdt/Makefile                               |     3 +-
 modules/permissions/Makefile                       |     1 -
 modules/pike/Makefile                              |     3 +-
 modules/pike/ip_tree.c                             |     7 -
 modules/pike/ip_tree.h                             |    10 -
 modules/pike/pike.c                                |    10 -
 modules/pike/pike_funcs.c                          |    12 -
 modules/pike/pike_funcs.h                          |     2 -
 modules/pike/pike_mi.c                             |     5 -
 modules/pike/pike_mi.h                             |     5 -
 modules/pike/pike_rpc.c                            |    21 +
 modules/pike/pike_rpc.h                            |    20 +
 modules/pike/pike_top.c                            |    20 +
 modules/pike/pike_top.h                            |    20 +
 modules/pike/timer.c                               |     6 -
 modules/pike/timer.h                               |     4 -
 modules/pipelimit/Makefile                         |     2 +-
 modules/pipelimit/README                           |     1 +
 modules/pipelimit/doc/pipelimit_admin.xml          |     5 +
 modules/pipelimit/pipelimit.c                      |    21 +-
 modules/pipelimit/pl_db.c                          |     2 -
 modules/pipelimit/pl_db.h                          |     7 +-
 modules/pipelimit/pl_ht.c                          |     2 -
 modules/pipelimit/pl_ht.h                          |     7 +-
 modules/prefix_route/Makefile                      |     2 +
 modules/prefix_route/pr.h                          |    15 +-
 modules/prefix_route/pr_rpc.c                      |    15 +-
 modules/prefix_route/prefix_route.c                |    20 +-
 modules/prefix_route/tree.c                        |    16 +-
 modules/prefix_route/tree.h                        |    15 +-
 modules/presence/README                            |   266 +-
 modules/presence/bind_presence.c                   |     6 +-
 modules/presence/bind_presence.h                   |     7 +-
 modules/presence/doc/presence_admin.xml            |   255 +-
 modules/presence/event_list.c                      |     3 -
 modules/presence/event_list.h                      |     3 -
 modules/presence/hash.c                            |    38 +-
 modules/presence/hash.h                            |     5 -
 modules/presence/notify.c                          |    34 +-
 modules/presence/notify.h                          |     6 +-
 modules/presence/presence.c                        |    82 +-
 modules/presence/presence.h                        |    14 +-
 modules/presence/presentity.c                      |    63 +-
 modules/presence/presentity.h                      |     4 +-
 modules/presence/publish.c                         |     3 -
 modules/presence/publish.h                         |     3 -
 modules/presence/subscribe.c                       |   106 +-
 modules/presence/subscribe.h                       |    10 +-
 modules/presence/utils_func.c                      |    38 +-
 modules/presence/utils_func.h                      |     6 +-
 modules/presence_dialoginfo/notify_body.c          |     2 +-
 modules/presence_reginfo/Makefile                  |     2 +-
 modules/print/Makefile                             |     1 -
 modules/print_lib/Makefile                         |     3 +-
 modules/pua/README                                 |    25 +-
 modules/pua/add_events.c                           |     3 -
 modules/pua/add_events.h                           |     3 -
 modules/pua/doc/pua_admin.xml                      |    25 +-
 modules/pua/doc/pua_devel.xml                      |     2 +
 modules/pua/event_list.c                           |     3 -
 modules/pua/event_list.h                           |     3 -
 modules/pua/hash.c                                 |     2 -
 modules/pua/hash.h                                 |     4 +-
 modules/pua/pidf.c                                 |     5 -
 modules/pua/pidf.h                                 |     5 -
 modules/pua/pua.c                                  |    14 +-
 modules/pua/pua.h                                  |     2 -
 modules/pua/pua_bind.c                             |     2 -
 modules/pua/pua_bind.h                             |     2 -
 modules/pua/pua_callback.c                         |     2 -
 modules/pua/pua_callback.h                         |     2 -
 modules/pua/pua_db.c                               |     2 -
 modules/pua/pua_db.h                               |     2 -
 modules/pua/send_publish.c                         |    31 +-
 modules/pua/send_publish.h                         |     3 +-
 modules/pua/send_subscribe.c                       |     9 +-
 modules/pua/send_subscribe.h                       |     2 -
 modules/pua_dialoginfo/README                      |    36 +
 .../pua_dialoginfo/doc/pua_dialoginfo_admin.xml    |    44 +
 modules/pua_dialoginfo/pua_dialoginfo.c            |   449 +-
 modules/pua_mi/README                              |    56 +-
 modules/pua_mi/doc/pua_mi_admin.xml                |    31 +
 modules/pua_mi/mi_func.c                           |    30 +-
 modules/pua_mi/pua_mi.c                            |    13 +-
 modules/pua_mi/pua_mi.h                            |     2 +
 modules/pua_reginfo/Makefile                       |     4 +-
 modules/pua_reginfo/usrloc_cb.c                    |    23 +-
 modules/purple/hashtable.c                         |     4 +-
 modules/purple/purple_sip.c                        |     4 +-
 modules/pv/Makefile                                |     3 +-
 modules/pv/README                                  |    98 +-
 modules/pv/doc/pv_admin.xml                        |   110 +
 modules/pv/pv.c                                    |    90 +-
 modules/pv/pv_branch.c                             |   274 +-
 modules/pv/pv_branch.h                             |    12 +-
 modules/pv/pv_core.c                               |   101 +-
 modules/pv/pv_core.h                               |     6 +-
 modules/pv/pv_select.c                             |     2 -
 modules/pv/pv_select.h                             |     2 -
 modules/pv/pv_shv.c                                |     4 +-
 modules/pv/pv_shv.h                                |     2 -
 modules/pv/pv_stats.c                              |     2 -
 modules/pv/pv_stats.h                              |     2 -
 modules/pv/pv_svar.c                               |    55 +-
 modules/pv/pv_svar.h                               |    12 +-
 modules/pv/pv_time.c                               |     2 -
 modules/pv/pv_time.h                               |     2 -
 modules/pv/pv_trans.c                              |    86 +-
 modules/pv/pv_trans.h                              |     4 +-
 modules/pv/pv_xavp.c                               |    62 +-
 modules/pv/pv_xavp.h                               |     6 +-
 modules/qos/Makefile                               |     5 -
 modules/qos/qos.c                                  |     7 +-
 modules/qos/qos_cb.c                               |     5 -
 modules/qos/qos_cb.h                               |     5 -
 modules/qos/qos_ctx_helpers.c                      |     5 -
 modules/qos/qos_ctx_helpers.h                      |     5 -
 modules/qos/qos_handlers.c                         |     5 -
 modules/qos/qos_handlers.h                         |     5 -
 modules/qos/qos_load.h                             |     5 -
 modules/qos/qos_mi.c                               |     5 -
 modules/qos/qos_mi.h                               |     5 -
 modules/ratelimit/README                           |    24 +-
 modules/ratelimit/doc/ratelimit_admin.xml          |     2 +-
 modules/ratelimit/ratelimit.c                      |    15 +-
 modules/regex/regex_mod.c                          |     7 -
 modules/registrar/Makefile                         |     1 -
 modules/registrar/README                           |   188 +-
 modules/registrar/api.c                            |     2 -
 modules/registrar/api.h                            |     2 -
 modules/registrar/common.c                         |     9 +-
 modules/registrar/common.h                         |     2 -
 modules/registrar/config.c                         |     7 +-
 modules/registrar/config.h                         |     4 +-
 modules/registrar/doc/registrar.xml                |     5 +
 modules/registrar/doc/registrar_admin.xml          |    91 +-
 modules/registrar/lookup.c                         |   155 +-
 modules/registrar/lookup.h                         |     5 +-
 modules/registrar/path.c                           |     2 -
 modules/registrar/path.h                           |     2 -
 modules/registrar/reg_mod.c                        |   113 +-
 modules/registrar/reg_mod.h                        |    19 +-
 modules/registrar/regpv.c                          |    12 +-
 modules/registrar/regpv.h                          |     4 +-
 modules/registrar/regtime.c                        |     2 -
 modules/registrar/regtime.h                        |     2 -
 modules/registrar/reply.c                          |     8 -
 modules/registrar/reply.h                          |     2 -
 modules/registrar/rerrno.c                         |     2 -
 modules/registrar/rerrno.h                         |     2 -
 modules/registrar/save.c                           |    22 +-
 modules/registrar/save.h                           |     7 -
 modules/registrar/sip_msg.c                        |    25 +-
 modules/registrar/sip_msg.h                        |     2 -
 modules/rls/Makefile                               |     3 +-
 modules/rls/notify.c                               |     5 -
 modules/rls/notify.h                               |     6 -
 modules/rls/resource_notify.c                      |     5 -
 modules/rls/resource_notify.h                      |     5 -
 modules/rls/rls.c                                  |     5 -
 modules/rls/rls.h                                  |     5 -
 modules/rls/rls_db.c                               |     2 -
 modules/rls/subscribe.c                            |     5 -
 modules/rls/subscribe.h                            |     5 -
 modules/rr/Makefile                                |     1 -
 modules/rr/api.c                                   |     2 -
 modules/rr/api.h                                   |     2 -
 modules/rr/loose.c                                 |     2 -
 modules/rr/loose.h                                 |     2 -
 modules/rr/record.c                                |     2 -
 modules/rr/record.h                                |     2 -
 modules/rr/rr_cb.c                                 |     2 -
 modules/rr/rr_cb.h                                 |     2 -
 modules/rr/rr_mod.c                                |   158 +-
 modules/rr/rr_mod.h                                |     2 -
 modules/rtimer/Makefile                            |     3 +-
 modules/rtjson/Makefile                            |    15 +
 modules/rtjson/README                              |   235 +
 modules/rtjson/doc/Makefile                        |     4 +
 modules/rtjson/doc/rtjson.xml                      |    37 +
 modules/rtjson/doc/rtjson_admin.xml                |   252 +
 modules/rtjson/rtjson_mod.c                        |   170 +
 modules/rtjson/rtjson_routing.c                    |   717 +
 modules/rtjson/rtjson_routing.h                    |    34 +
 modules/rtpengine/Makefile                         |     5 -
 modules/rtpengine/README                           |   171 +-
 modules/rtpengine/doc/rtpengine_admin.xml          |   107 +-
 modules/rtpengine/rtpengine.c                      |   495 +-
 modules/rtpengine/rtpengine.h                      |    10 +-
 modules/rtpengine/rtpengine_db.c                   |     5 +-
 modules/rtpengine/rtpengine_funcs.c                |    10 +-
 modules/rtpengine/rtpengine_funcs.h                |     3 +-
 modules/rtpproxy/Makefile                          |     3 +-
 modules/rtpproxy/test/rtpproxy.patch               |   374 +
 modules/sanity/Makefile                            |     1 -
 modules/sanity/api.h                               |    13 +-
 modules/sanity/mod_sanity.c                        |    13 +-
 modules/sanity/mod_sanity.h                        |    13 +-
 modules/sanity/sanity.c                            |    13 +-
 modules/sanity/sanity.h                            |    13 +-
 modules/sca/Makefile                               |     1 -
 modules/sca/sca.c                                  |     4 +-
 modules/sca/sca.h                                  |     4 +-
 modules/sca/sca_appearance.c                       |     4 +-
 modules/sca/sca_appearance.h                       |     6 +-
 modules/sca/sca_call_info.c                        |     4 +-
 modules/sca/sca_call_info.h                        |     5 +-
 modules/sca/sca_common.h                           |     4 +-
 modules/sca/sca_db.c                               |     6 +-
 modules/sca/sca_db.h                               |     4 +-
 modules/sca/sca_dialog.c                           |     6 +-
 modules/sca/sca_dialog.h                           |     4 +-
 modules/sca/sca_event.c                            |     4 +-
 modules/sca/sca_event.h                            |     4 +-
 modules/sca/sca_hash.c                             |     4 +-
 modules/sca/sca_hash.h                             |     4 +-
 modules/sca/sca_notify.c                           |     4 +-
 modules/sca/sca_notify.h                           |     4 +-
 modules/sca/sca_reply.c                            |     6 +-
 modules/sca/sca_reply.h                            |     6 +-
 modules/sca/sca_rpc.c                              |     4 +-
 modules/sca/sca_rpc.h                              |     4 +-
 modules/sca/sca_subscribe.c                        |     6 +-
 modules/sca/sca_subscribe.h                        |     6 +-
 modules/sca/sca_util.c                             |     6 +-
 modules/sca/sca_util.h                             |     6 +-
 modules/sctp/Makefile                              |     1 -
 modules/sdpops/Makefile                            |     1 -
 modules/sdpops/README                              |   185 +-
 modules/sdpops/doc/sdpops_admin.xml                |    26 +
 modules/sdpops/sdpops_mod.c                        |    83 +
 modules/seas/Makefile                              |     1 -
 modules/sipcapture/Makefile                        |     1 -
 modules/sipcapture/hash_mode.h                     |     8 +-
 modules/sipcapture/hep.c                           |     2 -
 modules/sipcapture/hep.h                           |     2 -
 modules/sipcapture/sipcapture.c                    |     2 -
 modules/sipcapture/sipcapture.h                    |     2 -
 modules/sipt/Makefile                              |     1 -
 modules/sipt/README                                |    61 +-
 modules/sipt/doc/sipt_admin.xml                    |    18 +
 modules/sipt/sipt.c                                |    70 +-
 modules/sipt/ss7.h                                 |     1 +
 modules/sipt/ss7_parser.c                          |    25 +-
 modules/siptrace/Makefile                          |     3 +-
 modules/siptrace/siptrace.c                        |    24 +-
 modules/siputils/README                            |   247 +-
 modules/siputils/checks.c                          |    74 +-
 modules/siputils/checks.h                          |    22 +-
 modules/siputils/config.c                          |    10 +-
 modules/siputils/config.h                          |    15 +-
 modules/siputils/contact_ops.c                     |    15 +-
 modules/siputils/contact_ops.h                     |    15 +-
 modules/siputils/doc/siputils_admin.xml            |    49 +
 modules/siputils/options.c                         |    11 +-
 modules/siputils/options.h                         |    10 +-
 modules/siputils/ring.c                            |    14 +-
 modules/siputils/ring.h                            |    13 +-
 modules/siputils/rpid.c                            |     6 -
 modules/siputils/rpid.h                            |     6 -
 modules/siputils/sipops.c                          |    12 +-
 modules/siputils/sipops.h                          |    12 +-
 modules/siputils/siputils.c                        |    18 +-
 modules/siputils/siputils.h                        |    13 +-
 modules/siputils/utils.c                           |    16 +-
 modules/siputils/utils.h                           |    15 +-
 modules/sl/Makefile                                |     3 +-
 modules/sl/sl.c                                    |    22 +-
 modules/sl/sl.h                                    |    13 +-
 modules/sl/sl_funcs.c                              |    30 +-
 modules/sl/sl_funcs.h                              |    13 +-
 modules/sl/sl_stats.c                              |    15 +-
 modules/sl/sl_stats.h                              |    16 +-
 modules/sms/Makefile                               |     3 +-
 modules/sms/libsms_sms.h                           |    13 +-
 modules/sms/sms.c                                  |    25 +-
 modules/sms/sms_funcs.c                            |    24 +-
 modules/sms/sms_funcs.h                            |    13 +-
 modules/sms/sms_report.c                           |    13 +-
 modules/sms/sms_report.h                           |    13 +-
 modules/snmpstats/Makefile                         |     1 -
 modules/snmpstats/alarm_checks.c                   |     9 +-
 modules/snmpstats/alarm_checks.h                   |     6 -
 modules/snmpstats/hashTable.c                      |    11 +-
 modules/snmpstats/hashTable.h                      |     5 -
 modules/snmpstats/interprocess_buffer.c            |     6 +-
 modules/snmpstats/interprocess_buffer.h            |     5 -
 modules/snmpstats/kamailioNet.c                    |    16 +-
 modules/snmpstats/kamailioNet.h                    |     4 -
 modules/snmpstats/kamailioNetConfig.c              |    12 +-
 modules/snmpstats/kamailioServer.c                 |    14 +-
 modules/snmpstats/kamailioServer.h                 |     4 -
 modules/snmpstats/snmpMIBNotifications.c           |     8 -
 modules/snmpstats/snmpMIBNotifications.h           |     5 -
 modules/snmpstats/snmpObjects.c                    |     2 -
 modules/snmpstats/snmpObjects.h                    |     6 -
 modules/snmpstats/snmpSIPCommonObjects.c           |    11 -
 modules/snmpstats/snmpSIPCommonObjects.h           |     6 -
 modules/snmpstats/snmpSIPContactTable.c            |     2 -
 modules/snmpstats/snmpSIPContactTable.h            |    10 -
 modules/snmpstats/snmpSIPMethodSupportedTable.c    |     8 -
 modules/snmpstats/snmpSIPMethodSupportedTable.h    |    10 -
 modules/snmpstats/snmpSIPPortTable.c               |     8 -
 modules/snmpstats/snmpSIPPortTable.h               |     8 -
 modules/snmpstats/snmpSIPRegUserLookupTable.c      |     9 -
 modules/snmpstats/snmpSIPRegUserLookupTable.h      |    11 -
 modules/snmpstats/snmpSIPRegUserTable.c            |     6 -
 modules/snmpstats/snmpSIPRegUserTable.h            |    11 -
 modules/snmpstats/snmpSIPServerObjects.c           |    11 -
 modules/snmpstats/snmpSIPServerObjects.h           |     9 -
 modules/snmpstats/snmpSIPStatusCodesTable.c        |    11 -
 modules/snmpstats/snmpSIPStatusCodesTable.h        |     8 -
 modules/snmpstats/snmpstats.c                      |     9 +-
 modules/snmpstats/snmpstats.h                      |     6 -
 modules/snmpstats/snmpstats_globals.h              |     6 -
 modules/snmpstats/sub_agent.c                      |     6 +-
 modules/snmpstats/sub_agent.h                      |     5 -
 modules/snmpstats/utilities.c                      |     6 +-
 modules/snmpstats/utilities.h                      |     5 -
 modules/speeddial/Makefile                         |     1 -
 modules/speeddial/sdlookup.c                       |     4 -
 modules/speeddial/sdlookup.h                       |     4 -
 modules/speeddial/speeddial.c                      |     4 -
 modules/speeddial/speeddial.h                      |     4 -
 modules/sqlops/Makefile                            |     3 +-
 modules/sqlops/sql_api.c                           |     6 +-
 modules/sqlops/sql_api.h                           |     4 +-
 modules/sqlops/sql_trans.c                         |     2 -
 modules/sqlops/sql_trans.h                         |     2 -
 modules/sqlops/sql_var.c                           |     4 +-
 modules/sqlops/sql_var.h                           |     4 +-
 modules/sqlops/sqlops.c                            |     6 +-
 modules/sst/Makefile                               |     8 +-
 modules/sst/sst.c                                  |    12 +-
 modules/sst/sst_handlers.c                         |     8 +-
 modules/sst/sst_handlers.h                         |    12 +-
 modules/sst/sst_mi.c                               |    11 +-
 modules/sst/sst_mi.h                               |    11 +-
 modules/statistics/Makefile                        |     1 -
 modules/statistics/statistics.c                    |    14 +-
 modules/statistics/stats_funcs.c                   |    11 +-
 modules/statistics/stats_funcs.h                   |    11 +-
 modules/statsd/Makefile                            |    14 +
 modules/statsd/README                              |   205 +
 modules/statsd/doc/Makefile                        |     6 +
 modules/statsd/doc/statsd.xml                      |    36 +
 modules/statsd/doc/statsd_admin.xml                |   213 +
 modules/statsd/lib_statsd.c                        |   133 +
 modules/statsd/lib_statsd.h                        |    27 +
 modules/statsd/statsd.c                            |   187 +
 modules/stun/Makefile                              |     1 -
 modules/stun/config.c                              |     2 -
 modules/stun/config.h                              |     2 -
 modules/stun/kam_stun.c                            |    11 +-
 modules/stun/kam_stun.h                            |     7 +-
 modules/stun/stun_mod.c                            |     7 +-
 modules/tcpops/Makefile                            |    14 +
 modules/tcpops/README                              |   148 +
 modules/tcpops/doc/Makefile                        |     4 +
 modules/tcpops/doc/functions.xml                   |   149 +
 modules/tcpops/doc/params.xml                      |    13 +
 modules/tcpops/doc/tcpops.xml                      |    44 +
 modules/tcpops/tcpops.c                            |   187 +
 modules/tcpops/tcpops.h                            |    35 +
 modules/tcpops/tcpops_mod.c                        |   269 +
 modules/textops/Makefile                           |     3 +-
 modules/textops/api.c                              |    10 +-
 modules/textops/api.h                              |    12 +-
 modules/textops/textops.c                          |    43 +-
 modules/textops/textops.h                          |    11 +-
 modules/textops/txt_var.c                          |    12 +-
 modules/textops/txt_var.h                          |    12 +-
 modules/textopsx/Makefile                          |     3 +-
 modules/textopsx/README                            |    35 +-
 modules/textopsx/doc/functions.xml                 |    77 -
 modules/textopsx/doc/selects.xml                   |    81 +
 modules/textopsx/doc/textopsx.xml                  |     1 +
 modules/timer/Makefile                             |     1 -
 modules/timer/README                               |    59 +-
 modules/timer/doc/timer.xml                        |    18 +-
 modules/timer/timer.c                              |    13 +-
 modules/tls/Makefile                               |     1 -
 modules/tls/README                                 |   334 +-
 modules/tls/doc/params.xml                         |    52 +
 modules/tls/fixed_c_zlib.h                         |    18 +-
 modules/tls/sbufq.h                                |     7 +-
 modules/tls/tls.cfg                                |     2 -
 modules/tls/tls_bio.c                              |    10 +-
 modules/tls/tls_bio.h                              |     8 +-
 modules/tls/tls_cfg.c                              |    15 +-
 modules/tls/tls_cfg.h                              |     7 +-
 modules/tls/tls_config.c                           |    13 +-
 modules/tls/tls_config.h                           |    10 +-
 modules/tls/tls_ct_q.h                             |     6 -
 modules/tls/tls_ct_wrq.c                           |     6 -
 modules/tls/tls_ct_wrq.h                           |     6 -
 modules/tls/tls_domain.c                           |   128 +-
 modules/tls/tls_domain.h                           |     6 +-
 modules/tls/tls_dump_vf.c                          |    12 +-
 modules/tls/tls_dump_vf.h                          |    11 +-
 modules/tls/tls_init.c                             |    16 +-
 modules/tls/tls_init.h                             |     3 +-
 modules/tls/tls_locking.c                          |     2 +-
 modules/tls/tls_locking.h                          |    10 +-
 modules/tls/tls_mod.c                              |     9 +-
 modules/tls/tls_mod.h                              |     2 +-
 modules/tls/tls_rpc.c                              |     2 +-
 modules/tls/tls_rpc.h                              |     2 +-
 modules/tls/tls_select.c                           |     9 +-
 modules/tls/tls_select.h                           |    13 +-
 modules/tls/tls_server.c                           |    64 +-
 modules/tls/tls_server.h                           |     3 +-
 modules/tls/tls_util.c                             |    14 +-
 modules/tls/tls_util.h                             |     2 +-
 modules/tls/tls_verify.c                           |     2 +-
 modules/tls/tls_verify.h                           |     2 +-
 modules/tm/Makefile                                |     3 +-
 modules/tm/README                                  |   274 +-
 modules/tm/callid.c                                |    10 +-
 modules/tm/callid.h                                |     6 +-
 modules/tm/config.c                                |    10 +-
 modules/tm/config.h                                |     9 +-
 modules/tm/defs.h                                  |    11 +-
 modules/tm/dlg.c                                   |    14 +-
 modules/tm/dlg.h                                   |    11 +-
 modules/tm/doc/functions.xml                       |    28 +-
 modules/tm/doc/params.xml                          |   253 +-
 modules/tm/h_table.c                               |    48 +-
 modules/tm/h_table.h                               |    32 +-
 modules/tm/lock.c                                  |    22 +-
 modules/tm/lock.h                                  |    22 +-
 modules/tm/lw_parser.c                             |    13 +-
 modules/tm/lw_parser.h                             |    13 +-
 modules/tm/rpc_uac.c                               |     7 -
 modules/tm/rpc_uac.h                               |    10 -
 modules/tm/select.c                                |    13 +-
 modules/tm/select.h                                |    14 +-
 modules/tm/sip_msg.c                               |    30 +-
 modules/tm/sip_msg.h                               |    11 +-
 modules/tm/t_append_branches.c                     |     3 -
 modules/tm/t_append_branches.h                     |     4 -
 modules/tm/t_cancel.c                              |    36 +-
 modules/tm/t_cancel.h                              |    25 +-
 modules/tm/t_fifo.c                                |    17 +-
 modules/tm/t_fifo.h                                |    17 +-
 modules/tm/t_funcs.c                               |    39 +-
 modules/tm/t_funcs.h                               |    24 +-
 modules/tm/t_fwd.c                                 |    82 +-
 modules/tm/t_fwd.h                                 |    21 +-
 modules/tm/t_hooks.c                               |    28 +-
 modules/tm/t_hooks.h                               |    27 +-
 modules/tm/t_lookup.c                              |    69 +-
 modules/tm/t_lookup.h                              |    23 +-
 modules/tm/t_msgbuilder.c                          |    34 +-
 modules/tm/t_msgbuilder.h                          |    17 +-
 modules/tm/t_reply.c                               |    89 +-
 modules/tm/t_reply.h                               |    13 +-
 modules/tm/t_serial.c                              |     3 -
 modules/tm/t_serial.h                              |     3 -
 modules/tm/t_stats.c                               |    19 +-
 modules/tm/t_stats.h                               |    15 +-
 modules/tm/t_suspend.c                             |    30 +-
 modules/tm/t_suspend.h                             |    13 +-
 modules/tm/test.c                                  |    14 +-
 modules/tm/timer.c                                 |    35 +-
 modules/tm/timer.h                                 |    24 +-
 modules/tm/tm.c                                    |    82 +-
 modules/tm/tm_load.c                               |    21 +-
 modules/tm/tm_load.h                               |    23 +-
 modules/tm/uac.c                                   |    41 +-
 modules/tm/uac.h                                   |    17 +-
 modules/tm/ut.h                                    |    24 +-
 modules/tmrec/Makefile                             |     1 -
 modules/tmrec/doc/tmrec_admin.xml                  |     6 +-
 modules/tmrec/tmrec_mod.c                          |    12 +-
 modules/tmx/Makefile                               |     3 +-
 modules/tmx/README                                 |     2 +
 modules/tmx/doc/tmx_admin.xml                      |     8 +-
 modules/tmx/t_mi.c                                 |     7 +-
 modules/tmx/t_mi.h                                 |     5 +-
 modules/tmx/t_var.c                                |    37 +-
 modules/tmx/t_var.h                                |    10 +-
 modules/tmx/tmx_mod.c                              |    12 +-
 modules/tmx/tmx_mod.h                              |    15 +-
 modules/tmx/tmx_pretran.c                          |     8 +-
 modules/tmx/tmx_pretran.h                          |     8 +-
 modules/topoh/Makefile                             |     3 +-
 modules/topoh/README                               |     4 +
 modules/topoh/doc/topoh_admin.xml                  |     5 +
 modules/topoh/th_mask.c                            |     5 +-
 modules/topoh/th_mask.h                            |     1 -
 modules/topoh/th_msg.c                             |    12 +-
 modules/topoh/th_msg.h                             |     5 +-
 modules/topoh/topoh_mod.c                          |    23 +-
 modules/tsilo/Makefile                             |     5 +-
 modules/tsilo/README                               |    63 +-
 modules/tsilo/doc/tsilo.xml                        |     2 +-
 modules/tsilo/doc/tsilo_admin.xml                  |    46 +-
 modules/tsilo/ts_hash.c                            |     2 +-
 modules/tsilo/ts_hash.h                            |    16 +-
 modules/tsilo/ts_rpc.c                             |   219 +
 modules/tsilo/ts_rpc.h                             |    35 +
 modules/tsilo/ts_store.c                           |    48 +-
 modules/tsilo/tsilo.c                              |    48 +-
 modules/tsilo/tsilo.h                              |    11 +-
 modules/uac/Makefile                               |     3 +-
 modules/uac/README                                 |   195 +-
 modules/uac/api.h                                  |     4 +
 modules/uac/auth.c                                 |     7 -
 modules/uac/auth.h                                 |    11 +-
 modules/uac/auth_alg.c                             |     9 +-
 modules/uac/auth_alg.h                             |    10 +-
 modules/uac/auth_hdr.c                             |    11 +-
 modules/uac/auth_hdr.h                             |     6 -
 modules/uac/doc/uac_admin.xml                      |    47 +
 modules/uac/replace.c                              |    14 -
 modules/uac/replace.h                              |     6 -
 modules/uac/uac.c                                  |    59 +-
 modules/uac/uac_reg.c                              |    49 +-
 modules/uac/uac_reg.h                              |     4 +-
 modules/uac/uac_send.c                             |   175 +-
 modules/uac/uac_send.h                             |     7 +-
 modules/uac_redirect/Makefile                      |     2 +-
 modules/uac_redirect/rd_filter.c                   |     5 -
 modules/uac_redirect/rd_filter.h                   |     6 -
 modules/uac_redirect/rd_funcs.c                    |     6 -
 modules/uac_redirect/rd_funcs.h                    |     6 -
 modules/uac_redirect/redirect.c                    |   382 -
 modules/uac_redirect/uac_redirect.c                |   376 +
 modules/uid_auth_db/.cvsignore                     |     1 +
 modules/uid_auth_db/Makefile                       |     1 -
 modules/uid_avp_db/Makefile                        |     3 +-
 modules/uid_domain/Makefile                        |     3 +-
 modules/uid_gflags/Makefile                        |     3 +-
 modules/uid_gflags/README                          |    76 +-
 modules/uid_gflags/doc/fifo.xml                    |    12 +-
 modules/uid_gflags/doc/functions.xml               |    10 +-
 modules/uid_gflags/doc/params.xml                  |    12 +-
 modules/uid_gflags/doc/uid_gflags.xml              |    16 +-
 modules/uid_gflags/doc/xmlrpc.xml                  |    16 +-
 modules/uid_gflags/uid_gflags.c                    |    19 +-
 modules/uid_uri_db/Makefile                        |     3 +-
 modules/uri_db/Makefile                            |     3 +-
 modules/userblacklist/README                       |   421 +-
 modules/userblacklist/db.c                         |     2 -
 modules/userblacklist/db.h                         |     2 -
 modules/userblacklist/db_userblacklist.c           |     1 -
 modules/userblacklist/db_userblacklist.h           |     1 -
 modules/userblacklist/doc/userblacklist.xml        |     1 -
 modules/userblacklist/doc/userblacklist_admin.xml  |   370 +-
 modules/userblacklist/doc/userblacklist_db.xml     |   176 -
 modules/userblacklist/userblacklist.c              |   412 +-
 modules/usrloc/Makefile                            |     1 -
 modules/usrloc/README                              |   355 +-
 modules/usrloc/dlist.c                             |   224 +-
 modules/usrloc/dlist.h                             |    12 +-
 modules/usrloc/doc/usrloc_admin.xml                |    84 +-
 modules/usrloc/hslot.c                             |     2 -
 modules/usrloc/hslot.h                             |     2 -
 modules/usrloc/ucontact.c                          |   154 +-
 modules/usrloc/ucontact.h                          |     7 -
 modules/usrloc/udomain.c                           |    83 +-
 modules/usrloc/udomain.h                           |     7 -
 modules/usrloc/ul_callback.c                       |     5 -
 modules/usrloc/ul_callback.h                       |     5 -
 modules/usrloc/ul_mi.c                             |     6 -
 modules/usrloc/ul_mi.h                             |     2 -
 modules/usrloc/ul_mod.c                            |    25 +-
 modules/usrloc/ul_mod.h                            |    12 +-
 modules/usrloc/ul_rpc.c                            |     2 -
 modules/usrloc/ul_rpc.h                            |     2 -
 modules/usrloc/urecord.c                           |    57 +-
 modules/usrloc/urecord.h                           |     2 -
 modules/usrloc/usrloc.c                            |     8 +-
 modules/usrloc/usrloc.h                            |    15 +-
 modules/usrloc/utime.c                             |     2 -
 modules/usrloc/utime.h                             |     2 -
 modules/utils/conf.c                               |     4 +-
 modules/utils/conf.h                               |     4 +-
 modules/utils/functions.c                          |    50 +-
 modules/utils/functions.h                          |     2 +-
 modules/utils/pidf.c                               |     7 +-
 modules/utils/pidf.h                               |     7 +-
 modules/utils/utils.c                              |     8 +-
 modules/utils/utils.h                              |     8 +-
 modules/utils/xcap_auth.c                          |     6 +-
 modules/utils/xcap_auth.h                          |     2 +-
 modules/websocket/Makefile                         |     1 -
 modules/websocket/README                           |    17 +-
 modules/websocket/config.c                         |     2 -
 modules/websocket/config.h                         |     2 -
 modules/websocket/doc/websocket_admin.xml          |     3 +
 modules/websocket/utf8_decode.h                    |     2 +-
 modules/websocket/ws_conn.c                        |     2 -
 modules/websocket/ws_conn.h                        |     2 -
 modules/websocket/ws_frame.c                       |     2 -
 modules/websocket/ws_frame.h                       |     2 -
 modules/websocket/ws_handshake.c                   |     2 -
 modules/websocket/ws_handshake.h                   |     2 -
 modules/websocket/ws_mod.c                         |     2 -
 modules/websocket/ws_mod.h                         |     2 -
 modules/xcap_client/Makefile                       |     1 -
 modules/xcap_client/xcap_callbacks.c               |     5 -
 modules/xcap_client/xcap_callbacks.h               |     5 -
 modules/xcap_client/xcap_client.c                  |     5 -
 modules/xcap_client/xcap_client.h                  |     5 -
 modules/xcap_client/xcap_functions.c               |     5 -
 modules/xcap_client/xcap_functions.h               |     5 -
 modules/xcap_server/Makefile                       |     1 -
 modules/xhttp/Makefile                             |     3 +-
 modules/xhttp/README                               |    19 +-
 modules/xhttp/api.h                                |     1 -
 modules/xhttp/doc/xhttp_admin.xml                  |    23 +-
 modules/xhttp/xhttp_mod.c                          |     2 -
 modules/xhttp/xhttp_trans.c                        |     3 +-
 modules/xhttp/xhttp_trans.h                        |     3 +-
 modules/xhttp_pi/Makefile                          |     1 -
 modules/xhttp_pi/http_db_handler.c                 |     8 +-
 modules/xhttp_pi/http_db_handler.h                 |     8 +-
 modules/xhttp_pi/xhttp_pi.c                        |    16 +-
 modules/xhttp_pi/xhttp_pi.h                        |     7 +-
 modules/xhttp_pi/xhttp_pi_fnc.c                    |     8 +-
 modules/xhttp_pi/xhttp_pi_fnc.h                    |     7 +-
 modules/xhttp_rpc/Makefile                         |     1 -
 modules/xhttp_rpc/xhttp_rpc.c                      |     3 -
 modules/xhttp_rpc/xhttp_rpc.h                      |     3 -
 modules/xhttp_rpc/xhttp_rpc_fnc.c                  |     3 -
 modules/xhttp_rpc/xhttp_rpc_fnc.h                  |     3 -
 modules/xlog/Makefile                              |     3 +-
 modules/xlog/README                                |    81 +-
 modules/xlog/doc/xlog_admin.xml                    |    72 +-
 modules/xlog/xl_lib.c                              |    17 +-
 modules/xlog/xl_lib.h                              |     8 +-
 modules/xlog/xlog.c                                |    69 +-
 modules/xmlops/Makefile                            |     2 +-
 modules/xmlops/pv_xml.c                            |     1 -
 modules/xmlops/pv_xml.h                            |     1 -
 modules/xmlops/xmlops_mod.c                        |     1 -
 modules/xmlrpc/README                              |   101 +-
 modules/xmlrpc/doc/xmlrpc.xml                      |    41 +-
 modules/xmlrpc/doc/xmlrpc_admin.xml                |    16 +
 modules/xmlrpc/examples/xmlrpc_test2.py            |    21 +-
 modules/xmlrpc/http.c                              |    12 +-
 modules/xmlrpc/http.h                              |    12 +-
 modules/xmlrpc/xmlrpc.c                            |    10 +-
 modules/xmlrpc/xmlrpc.h                            |    12 +-
 modules/xmpp/Makefile                              |     1 -
 modules/xmpp/network.c                             |     2 -
 modules/xmpp/network.h                             |     6 +-
 modules/xmpp/sha.c                                 |     2 -
 modules/xmpp/util.c                                |     2 -
 modules/xmpp/xmpp.c                                |     2 -
 modules/xmpp/xmpp.h                                |     2 -
 modules/xmpp/xmpp_api.c                            |     2 -
 modules/xmpp/xmpp_api.h                            |     2 -
 modules/xmpp/xmpp_component.c                      |     6 +-
 modules/xmpp/xmpp_server.c                         |     3 -
 modules/xmpp/xode.c                                |     2 -
 modules/xmpp/xode.h                                |     2 -
 modules/xmpp/xode_from.c                           |     2 -
 modules/xmpp/xode_str.c                            |     2 -
 modules/xmpp/xpool.c                               |     2 -
 modules/xmpp/xsnprintf.c                           |     4 +-
 modules/xmpp/xstream.c                             |     2 -
 modules/xprint/Makefile                            |     3 +-
 msg_translator.c                                   |    79 +-
 msg_translator.h                                   |    30 +-
 name_alias.h                                       |    30 +-
 nonsip_hooks.c                                     |    28 +-
 nonsip_hooks.h                                     |    25 +-
 obsolete/acc_db/.cvsignore                         |     2 +
 obsolete/acc_syslog/.cvsignore                     |     2 +
 obsolete/uac/doc/replace_from.patch                |   150 +
 onsend.h                                           |    25 +-
 parser/case_acce.h                                 |     6 +-
 parser/case_allo.h                                 |     6 +-
 parser/case_auth.h                                 |     6 +-
 parser/case_call.h                                 |    10 +-
 parser/case_cont.h                                 |    10 +-
 parser/case_cseq.h                                 |     6 +-
 parser/case_date.h                                 |     6 +-
 parser/case_dive.h                                 |    11 +-
 parser/case_even.h                                 |    11 +-
 parser/case_expi.h                                 |    15 +-
 parser/case_from.h                                 |    11 +-
 parser/case_iden.h                                 |    13 +-
 parser/case_max.h                                  |    11 +-
 parser/case_min.h                                  |    11 +-
 parser/case_orga.h                                 |    11 +-
 parser/case_p_as.h                                 |     8 -
 parser/case_p_pr.h                                 |     8 -
 parser/case_path.h                                 |    11 +-
 parser/case_prio.h                                 |    11 +-
 parser/case_priv.h                                 |     6 +-
 parser/case_prox.h                                 |    15 +-
 parser/case_reas.h                                 |     8 -
 parser/case_reco.h                                 |    11 +-
 parser/case_refe.h                                 |    11 +-
 parser/case_reje.h                                 |    11 +-
 parser/case_remo.h                                 |    11 +-
 parser/case_requ.h                                 |    15 +-
 parser/case_retr.h                                 |    14 +-
 parser/case_rout.h                                 |    11 +-
 parser/case_serv.h                                 |    11 +-
 parser/case_sess.h                                 |    11 +-
 parser/case_sip.h                                  |     6 +-
 parser/case_subj.h                                 |    11 +-
 parser/case_subs.h                                 |    11 +-
 parser/case_supp.h                                 |    11 +-
 parser/case_to.h                                   |    15 +-
 parser/case_unsu.h                                 |    15 +-
 parser/case_user.h                                 |    11 +-
 parser/case_via.h                                  |    14 +-
 parser/case_www.h                                  |    11 +-
 parser/hf.c                                        |    18 +-
 parser/hf.h                                        |    20 +-
 parser/keys.h                                      |    12 +-
 parser/msg_parser.c                                |   106 +-
 parser/msg_parser.h                                |    35 +-
 parser/parse_addr_spec.c                           |    10 +-
 parser/parse_allow.c                               |     6 +-
 parser/parse_allow.h                               |     6 +-
 parser/parse_body.c                                |    14 +-
 parser/parse_body.h                                |    12 +-
 parser/parse_content.c                             |    14 +-
 parser/parse_content.h                             |     6 +-
 parser/parse_cseq.c                                |    10 +-
 parser/parse_cseq.h                                |    11 +-
 parser/parse_date.c                                |     6 +-
 parser/parse_date.h                                |     6 +-
 parser/parse_def.h                                 |     6 +-
 parser/parse_disposition.c                         |     8 +-
 parser/parse_disposition.h                         |     8 +-
 parser/parse_diversion.c                           |     6 +-
 parser/parse_diversion.h                           |     6 +-
 parser/parse_event.c                               |     9 +-
 parser/parse_event.h                               |     6 +-
 parser/parse_expires.c                             |    14 +-
 parser/parse_expires.h                             |     6 +-
 parser/parse_fline.c                               |    51 +-
 parser/parse_fline.h                               |    11 +-
 parser/parse_from.c                                |    11 +-
 parser/parse_from.h                                |     6 +-
 parser/parse_hname2.c                              |    18 +-
 parser/parse_hname2.h                              |     6 +-
 parser/parse_hostport.c                            |     6 +-
 parser/parse_hostport.h                            |    11 +-
 parser/parse_identity.c                            |    11 +-
 parser/parse_identity.h                            |     6 +-
 parser/parse_identityinfo.c                        |     6 +-
 parser/parse_identityinfo.h                        |     6 +-
 parser/parse_methods.c                             |     6 +-
 parser/parse_methods.h                             |    11 +-
 parser/parse_nameaddr.c                            |    10 +-
 parser/parse_nameaddr.h                            |     9 +-
 parser/parse_option_tags.c                         |     2 -
 parser/parse_option_tags.h                         |     2 -
 parser/parse_param.c                               |    11 +-
 parser/parse_param.h                               |    16 +-
 parser/parse_ppi_pai.c                             |     3 -
 parser/parse_refer_to.c                            |     6 +-
 parser/parse_refer_to.h                            |     6 +-
 parser/parse_require.c                             |     2 -
 parser/parse_require.h                             |     2 -
 parser/parse_retry_after.c                         |     9 +-
 parser/parse_retry_after.h                         |     6 +-
 parser/parse_rpid.c                                |     6 +-
 parser/parse_rpid.h                                |    11 +-
 parser/parse_rr.c                                  |    17 +-
 parser/parse_rr.h                                  |    11 +-
 parser/parse_sipifmatch.c                          |     6 +-
 parser/parse_sipifmatch.h                          |     6 +-
 parser/parse_subscription_state.c                  |     6 +-
 parser/parse_subscription_state.h                  |     6 +-
 parser/parse_supported.c                           |     2 -
 parser/parse_supported.h                           |     7 -
 parser/parse_to.c                                  |    10 +-
 parser/parse_to.h                                  |     6 +-
 parser/parse_uri.c                                 |    26 +-
 parser/parse_uri.h                                 |     6 +-
 parser/parse_via.c                                 |    36 +-
 parser/parse_via.h                                 |    23 +-
 parser/parser_f.c                                  |    14 +-
 parser/parser_f.h                                  |    15 +-
 pass_fd.c                                          |    34 +-
 pass_fd.h                                          |    19 +-
 pkg/kamailio/centos/6/kamailio.spec                |     4 +-
 pkg/kamailio/deb/debian/backports/precise          |     5 +
 pkg/kamailio/deb/debian/backports/squeeze          |    11 +
 pkg/kamailio/deb/debian/backports/wheezy           |     5 +
 pkg/kamailio/deb/debian/changelog                  |    54 +-
 pkg/kamailio/deb/debian/control                    |    17 +-
 pkg/kamailio/deb/debian/rules                      |    33 +-
 pkg/kamailio/deb/jessie/changelog                  |    54 +-
 pkg/kamailio/deb/jessie/control                    |    17 +-
 pkg/kamailio/deb/jessie/rules                      |    33 +-
 pkg/kamailio/deb/precise/changelog                 |    54 +-
 pkg/kamailio/deb/precise/control                   |     3 +-
 pkg/kamailio/deb/precise/rules                     |    33 +-
 pkg/kamailio/deb/squeeze/changelog                 |    54 +-
 pkg/kamailio/deb/squeeze/rules                     |    32 +-
 pkg/kamailio/deb/trusty/changelog                  |    54 +-
 pkg/kamailio/deb/trusty/control                    |    17 +-
 pkg/kamailio/deb/trusty/rules                      |    33 +-
 pkg/kamailio/deb/wheezy/changelog                  |    54 +-
 pkg/kamailio/deb/wheezy/control                    |     3 +-
 pkg/kamailio/deb/wheezy/rules                      |    33 +-
 pkg/kamailio/fedora/17/kamailio.spec               |     4 +-
 pkg/kamailio/rpm/kamailio.spec-4.1                 |     2 +-
 pkg/kamailio/rpm/kamailio.spec.CenOS               |     2 +-
 pkg/kamailio/rpm/kamailio.spec.SuSE                |     2 +-
 poll_types.h                                       |    31 +-
 ppcfg.c                                            |    10 +-
 ppcfg.h                                            |     9 +-
 proxy.c                                            |    27 +-
 proxy.h                                            |    31 +-
 pt.c                                               |    14 +-
 pt.h                                               |    14 +-
 pv_core.c                                          |    15 +-
 pv_core.h                                          |    11 +-
 pvapi.c                                            |    33 +-
 pvapi.h                                            |     9 +-
 pvar.h                                             |    13 +-
 qvalue.c                                           |    18 +-
 qvalue.h                                           |    23 +-
 rad_dict.h                                         |    21 +-
 rand/fastrand.c                                    |     2 -
 rand/fastrand.h                                    |     7 +-
 raw_listener.c                                     |    16 +-
 raw_listener.h                                     |     8 +-
 raw_sock.c                                         |    12 +-
 raw_sock.h                                         |    11 +-
 re.c                                               |    28 +-
 re.h                                               |    24 +-
 receive.c                                          |    44 +-
 receive.h                                          |    19 +-
 resolve.c                                          |   141 +-
 resolve.h                                          |    30 +-
 route.c                                            |    57 +-
 route.h                                            |    19 +-
 route_struct.c                                     |    24 +-
 route_struct.h                                     |    32 +-
 rpc.h                                              |    56 +-
 rpc_lookup.c                                       |    12 +-
 rpc_lookup.h                                       |    15 +-
 rvalue.c                                           |   102 +-
 rvalue.h                                           |    13 +-
 sched_yield.h                                      |    16 +-
 script_cb.c                                        |    26 +-
 script_cb.h                                        |    24 +-
 sctp_core.c                                        |    11 +-
 sctp_core.h                                        |     9 +-
 select.c                                           |    63 +-
 select.h                                           |    24 +-
 select_buf.c                                       |    23 +-
 select_buf.h                                       |    32 +-
 select_core.c                                      |    63 +-
 select_core.h                                      |    26 +-
 ser_time.h                                         |    12 +-
 shm_init.c                                         |    15 +-
 shm_init.h                                         |    15 +-
 signals.c                                          |    22 +-
 signals.h                                          |    22 +-
 sip-router.8                                       |     8 +-
 sip_msg_clone.c                                    |    12 +-
 sip_msg_clone.h                                    |    10 -
 sock_ut.c                                          |    10 +-
 sock_ut.h                                          |     4 +-
 socket_info.c                                      |    55 +-
 socket_info.h                                      |    24 +-
 sr_compat.c                                        |     5 +-
 sr_compat.h                                        |     2 -
 sr_module.c                                        |    65 +-
 sr_module.h                                        |    36 +-
 stats.c                                            |    20 +-
 stats.h                                            |    13 +-
 str.c                                              |     9 +-
 str.h                                              |    11 +-
 str_hash.h                                         |    10 -
 str_list.c                                         |    11 +-
 str_list.h                                         |     8 +-
 stun.c                                             |     9 +-
 stun.h                                             |     2 -
 switch.c                                           |    49 +-
 switch.h                                           |    10 -
 tags.h                                             |    24 +-
 tcp_conn.h                                         |    27 +-
 tcp_ev.h                                           |    12 +-
 tcp_info.h                                         |    17 +-
 tcp_init.h                                         |    13 +-
 tcp_int_send.h                                     |     5 +-
 tcp_main.c                                         |   184 +-
 tcp_options.c                                      |    12 +-
 tcp_options.h                                      |     9 +-
 tcp_read.c                                         |    83 +-
 tcp_read.h                                         |    10 +-
 tcp_server.h                                       |    13 +-
 tcp_stats.c                                        |    11 +-
 tcp_stats.h                                        |    12 +-
 test/acc-test.cfg                                  |   170 +
 test/atomic_test.c                                 |   102 +
 test/atomic_test2.c                                |   301 +
 test/auto.c                                        |   439 +
 test/bad_eof.cfg                                   |     1 +
 test/bad_uri.sip                                   |    32 +
 test/bad_via1.sip                                  |     6 +
 test/bad_via2.sip                                  |     4 +
 test/bad_via3.sip                                  |     3 +
 test/basex.c                                       |   399 +
 test/basex.txt                                     |    60 +
 test/bc2.sip                                       |    10 +
 test/bit_scan_test.c                               |   206 +
 test/bt.gdb                                        |     2 +
 test/bye00.sip                                     |    14 +
 test/bye_chris.sip                                 |    14 +
 test/centauri.cfg                                  |    14 +
 test/dns.sip                                       |    24 +
 test/dns_query.c                                   |   215 +
 test/echo.cfg                                      |    51 +
 test/endian_test.c                                 |   171 +
 test/file_copyright.txt                            |    24 +
 test/flood.cfg                                     |    32 +
 test/gcc_version.sh                                |    17 +
 test/gcc_version_test.sh                           |    26 +
 test/gcc_versions.txt                              |    25 +
 test/gen.cfg                                       |    41 +
 test/gethostbyaddr.c                               |   105 +
 test/gethostbyname.c                               |   100 +
 test/gplall.sh                                     |     6 +
 test/gplize.awk                                    |    62 +
 test/ifls.c                                        |   343 +
 test/inv_srv.sip                                   |    21 +
 test/invite00.sip                                  |    33 +
 test/invite01.sip                                  |    33 +
 test/invite02.sip                                  |    33 +
 test/invite03.sip                                  |    33 +
 test/invite04.sip                                  |    33 +
 test/invite05.sip                                  |    33 +
 test/invite1.sip                                   |    23 +
 test/invite3-callid.sip                            |    23 +
 test/invite4-cseq.sip                              |    23 +
 test/invite5-callid.sip                            |    23 +
 test/invite6-badbranch-via.sip                     |    23 +
 test/lock_test.c                                   |    43 +
 test/locking/Makefile                              |    63 +
 test/locking/locking_test.c                        |   304 +
 test/locking/test_results.txt                      |    40 +
 test/long.sip                                      |    66 +
 test/message.sip                                   |    11 +
 test/message02.sip                                 |    10 +
 test/message03.sip                                 |    14 +
 test/mips_lock.c                                   |    97 +
 test/mobile61.cfg                                  |    23 +
 test/module_compile_status.txt                     |    74 +
 test/ms-invite-00-rpl.sip                          |     8 +
 test/ms-invite-00.sip                              |    32 +
 test/ms-invite-01-rpl.sip                          |    10 +
 test/msbye.sip                                     |    10 +
 test/nc.cfg                                        |    24 +
 test/nmr.sip                                       |    30 +
 test/no_eom_reply.sip                              |     3 +
 test/p_uri.c                                       |    98 +
 test/parse_to_body.c                               |   112 +
 test/perf.txt                                      |   278 +
 test/pingtel.sip                                   |    15 +
 test/profile.h                                     |   190 +
 test/re_test.c                                     |   177 +
 test/register.sip                                  |    11 +
 test/register02.sip                                |    12 +
 test/register03.sip                                |    11 +
 test/register04.sip                                |    11 +
 test/repl1.sip                                     |    10 +
 test/req-test1.sip                                 |    10 +
 test/req-tm1.sip                                   |     9 +
 test/req1.sip                                      |     5 +
 test/req2.sip                                      |     5 +
 test/resolver.txt                                  |    84 +
 test/resolver_test.c                               |   147 +
 test/route.sip                                     |    25 +
 test/rport.sip                                     |    10 +
 test/ser.cfg                                       |    56 +
 test/sf.cfg                                        |   127 +
 test/sg.sip                                        |    18 +
 test/shoot.c                                       |   325 +
 test/shoot2.c                                      |   409 +
 test/short_nonce.sip                               |    11 +
 test/short_reply.sip                               |     4 +
 test/sock_conn.c                                   |    78 +
 test/sock_disc.c                                   |    71 +
 test/stateless.cfg                                 |    38 +
 test/stress.cfg                                    |    54 +
 test/struas.cfg                                    |    41 +
 test/t_debug2.cfg                                  |    58 +
 test/t_debug3.cfg                                  |    50 +
 test/tcp.cfg                                       |    38 +
 test/tcp_tunnel1.cfg                               |    33 +
 test/tcp_tunnel2.cfg                               |    35 +
 test/td.cfg                                        |    52 +
 test/test-throughput.cfg                           |    16 +
 test/test.c                                        |    78 +
 test/test.cfg                                      |    43 +
 test/test1.cfg                                     |    34 +
 test/test2.cfg                                     |    20 +
 test/test3.cfg                                     |    17 +
 test/th-uri-2.cfg                                  |    53 +
 test/th-uri-8.cfg                                  |    62 +
 test/th-uri-fast.cfg                               |    33 +
 test/th-uri.cfg                                    |    64 +
 test/tp.cfg                                        |    40 +
 test/transaction.fifo                              |    13 +
 test/travis/build_deps.sh                          |    23 +
 test/travis/build_travis.sh                        |    31 +
 test/travis/databases_travis.sh                    |    11 +
 test/tx.cfg                                        |    44 +
 test/udp.c                                         |   183 +
 test/udp_flood_disc.c                              |   220 +
 test/udp_test_proxy.c                              |   247 +
 test/unit/1.sh                                     |    37 +
 test/unit/10.sh                                    |    50 +
 test/unit/11.cfg                                   |    82 +
 test/unit/11.sh                                    |   183 +
 test/unit/12.cfg                                   |   108 +
 test/unit/12.sh                                    |    90 +
 test/unit/13.cfg                                   |    52 +
 test/unit/13.sh                                    |   127 +
 test/unit/14.cfg                                   |    33 +
 test/unit/14.sh                                    |    79 +
 test/unit/15.sh                                    |    44 +
 test/unit/16.sh                                    |    47 +
 test/unit/17.sh                                    |    72 +
 test/unit/18.sh                                    |    50 +
 test/unit/19.cfg                                   |    52 +
 test/unit/19.sh                                    |    50 +
 test/unit/2.cfg                                    |    68 +
 test/unit/2.sh                                     |    52 +
 test/unit/20.cfg                                   |    54 +
 test/unit/20.sh                                    |    54 +
 test/unit/21.cfg                                   |   100 +
 test/unit/21.sh                                    |    58 +
 test/unit/22.cfg                                   |    74 +
 test/unit/22.sh                                    |   104 +
 test/unit/23.sh                                    |   104 +
 test/unit/24.sh                                    |    58 +
 test/unit/25.cfg                                   |    51 +
 test/unit/25.sh                                    |   160 +
 test/unit/26.cfg                                   |    72 +
 test/unit/26.sh                                    |   150 +
 test/unit/27.sh                                    |    54 +
 test/unit/28.cfg                                   |    23 +
 test/unit/28.sh                                    |    71 +
 test/unit/29.sh                                    |    73 +
 test/unit/3.sh                                     |    68 +
 test/unit/30.cfg                                   |    30 +
 test/unit/30.sh                                    |    70 +
 test/unit/31.sh                                    |    50 +
 test/unit/32.sh                                    |    59 +
 test/unit/33.cfg                                   |    28 +
 test/unit/33.sh                                    |    77 +
 test/unit/34.cfg                                   |    26 +
 test/unit/34.sh                                    |    54 +
 test/unit/35.cfg                                   |    56 +
 test/unit/35.sh                                    |    72 +
 test/unit/36.sh                                    |    81 +
 test/unit/37.sh                                    |   114 +
 test/unit/38.sh                                    |    48 +
 test/unit/39.sh                                    |    62 +
 test/unit/4.sh                                     |    51 +
 test/unit/40.cfg                                   |    33 +
 test/unit/40.sh                                    |    73 +
 test/unit/41.cfg                                   |    44 +
 test/unit/41.sh                                    |    63 +
 test/unit/42.sh                                    |   148 +
 test/unit/43.sh                                    |   102 +
 test/unit/44.sh                                    |   109 +
 test/unit/45.cfg                                   |    71 +
 test/unit/45.sh                                    |    51 +
 test/unit/46.sh                                    |    94 +
 test/unit/5.cfg                                    |   427 +
 test/unit/5.sh                                     |    41 +
 test/unit/50.cfg                                   |    85 +
 test/unit/50.sh                                    |   162 +
 test/unit/6.sh                                     |    35 +
 test/unit/7.cfg                                    |  1105 ++
 test/unit/7.sh                                     |    42 +
 test/unit/8.sh                                     |    50 +
 test/unit/9.sh                                     |    50 +
 test/unit/Makefile                                 |    36 +
 test/unit/README                                   |    39 +
 test/unit/carrierroute-2.cfg                       |    30 +
 test/unit/carrierroute.cfg                         |   100 +
 test/unit/cpl_ignore.xml                           |     6 +
 test/unit/cpl_test.xml                             |    21 +
 test/unit/failure_route.xml                        |   140 +
 test/unit/include/common                           |    23 +
 test/unit/include/database                         |    69 +
 test/unit/include/require                          |    64 +
 test/unit/inv_auth.xml                             |    41 +
 test/unit/invite.sip                               |    12 +
 test/unit/presence.cfg                             |    83 +
 test/unit/publish.csv                              |     4 +
 test/unit/publish_scenario.xml                     |    86 +
 test/unit/reg_auth.xml                             |    40 +
 test/unit/register.sip                             |    11 +
 test/unit/route-empty.cfg                          |     3 +
 test/unit/subscribe_notify.csv                     |     4 +
 test/unit/subscribe_notify_scenario.xml            |    58 +
 test/unit/unregister.sip                           |    11 +
 test/use_jab.cfg                                   |    86 +
 test/via_parse.c                                   |  1583 ++
 test/xx.cfg                                        |    61 +
 test/xy.cfg                                        |    50 +
 timer.c                                            |    45 +-
 timer.h                                            |    18 +-
 timer_funcs.h                                      |    16 +-
 timer_proc.c                                       |    13 +-
 timer_proc.h                                       |     8 +-
 timer_ticks.h                                      |    17 +-
 tls_hooks.c                                        |    11 +-
 tls_hooks.h                                        |    12 +-
 tls_hooks_init.h                                   |    11 +-
 trim.h                                             |    16 +-
 tsend.c                                            |    24 +-
 tsend.h                                            |    18 +-
 types.h                                            |    11 +-
 udp_server.c                                       |    40 +-
 udp_server.h                                       |    10 +-
 usr_avp.c                                          |    28 +-
 usr_avp.h                                          |    18 +-
 ut.c                                               |     4 +-
 ut.h                                               |    23 +-
 utils/{sercmd => kamcmd}/EXAMPLES                  |     0
 utils/kamcmd/Makefile                              |   108 +
 utils/{sercmd => kamcmd}/README                    |     0
 utils/{sercmd => kamcmd}/TODO                      |     0
 utils/kamcmd/kamcmd.8                              |    35 +
 utils/{sercmd/sercmd.c => kamcmd/kamcmd.c}         |     0
 utils/{sercmd => kamcmd}/license.h                 |     0
 utils/{sercmd => kamcmd}/parse_listen_id.c         |     0
 utils/{sercmd => kamcmd}/parse_listen_id.h         |     0
 utils/kamctl/Makefile                              |   144 +-
 utils/kamctl/db_berkeley/kamailio/acc_cdrs         |     4 +-
 utils/kamctl/db_berkeley/kamailio/aliases          |     4 +-
 utils/kamctl/db_berkeley/kamailio/location         |     4 +-
 utils/kamctl/db_berkeley/kamailio/presentity       |     4 +-
 utils/kamctl/db_berkeley/kamailio/silo             |     2 +-
 utils/kamctl/db_berkeley/kamailio/sip_trace        |     4 +-
 utils/kamctl/db_berkeley/kamailio/version          |    12 +-
 utils/kamctl/db_sqlite/acc-create.sql              |     8 +-
 utils/kamctl/db_sqlite/msilo-create.sql            |     6 +-
 utils/kamctl/db_sqlite/presence-create.sql         |     3 +-
 utils/kamctl/db_sqlite/registrar-create.sql        |    11 +-
 utils/kamctl/db_sqlite/siptrace-create.sql         |     3 +-
 utils/kamctl/db_sqlite/usrloc-create.sql           |     6 +-
 utils/kamctl/dbtext/kamailio/acc_cdrs              |     2 +-
 utils/kamctl/dbtext/kamailio/aliases               |     2 +-
 utils/kamctl/dbtext/kamailio/location              |     2 +-
 utils/kamctl/dbtext/kamailio/presentity            |     2 +-
 utils/kamctl/dbtext/kamailio/silo                  |     2 +-
 utils/kamctl/dbtext/kamailio/sip_trace             |     2 +-
 utils/kamctl/dbtext/kamailio/subscriber            |     2 +-
 utils/kamctl/dbtext/kamailio/version               |    12 +-
 utils/kamctl/kamctl.fifo                           |     2 +-
 utils/kamctl/kamctlrc                              |     4 +-
 utils/kamctl/mysql/acc-create.sql                  |    54 +-
 utils/kamctl/mysql/alias_db-create.sql             |    18 +-
 utils/kamctl/mysql/auth_db-create.sql              |    22 +-
 utils/kamctl/mysql/avpops-create.sql               |    22 +-
 utils/kamctl/mysql/carrierroute-create.sql         |    60 +-
 utils/kamctl/mysql/cpl-create.sql                  |    14 +-
 utils/kamctl/mysql/dialog-create.sql               |    66 +-
 utils/kamctl/mysql/dialog_ng-create.sql            |    52 +
 utils/kamctl/mysql/dialplan-create.sql             |    20 +-
 utils/kamctl/mysql/dispatcher-create.sql           |    16 +-
 utils/kamctl/mysql/domain-create.sql               |    28 +-
 utils/kamctl/mysql/domainpolicy-create.sql         |    18 +-
 utils/kamctl/mysql/drouting-create.sql             |    54 +-
 utils/kamctl/mysql/group-create.sql                |    24 +-
 utils/kamctl/mysql/htable-create.sql               |    14 +-
 utils/kamctl/mysql/imc-create.sql                  |    26 +-
 utils/kamctl/mysql/ims_charging_create.sql         |    24 +
 utils/kamctl/mysql/ims_usrloc_scscf-create.sql     |    29 +
 utils/kamctl/mysql/lcr-create.sql                  |    68 +-
 utils/kamctl/mysql/matrix-create.sql               |    10 +-
 utils/kamctl/mysql/mohqueue-create.sql             |    36 +-
 utils/kamctl/mysql/msilo-create.sql                |    32 +-
 utils/kamctl/mysql/mtree-create.sql                |    22 +-
 utils/kamctl/mysql/pdt-create.sql                  |    12 +-
 utils/kamctl/mysql/permissions-create.sql          |    28 +-
 utils/kamctl/mysql/pipelimit-create.sql            |    10 +-
 utils/kamctl/mysql/presence-create.sql             |   189 +-
 utils/kamctl/mysql/purple-create.sql               |    12 +-
 utils/kamctl/mysql/registrar-create.sql            |    51 +-
 utils/kamctl/mysql/rls-create.sql                  |    86 +-
 utils/kamctl/mysql/rtpproxy-create.sql             |    14 +-
 utils/kamctl/mysql/sca-create.sql                  |    34 +-
 utils/kamctl/mysql/siptrace-create.sql             |    37 +-
 utils/kamctl/mysql/speeddial-create.sql            |    22 +-
 utils/kamctl/mysql/standard-create.sql             |     8 +-
 utils/kamctl/mysql/uac-create.sql                  |    26 +-
 utils/kamctl/mysql/uid_auth_db-create.sql          |    28 +-
 utils/kamctl/mysql/uid_avp_db-create.sql           |    16 +-
 utils/kamctl/mysql/uid_domain-create.sql           |    32 +-
 utils/kamctl/mysql/uid_gflags-create.sql           |    14 +-
 utils/kamctl/mysql/uid_uri_db-create.sql           |    38 +-
 utils/kamctl/mysql/uri_db-create.sql               |    14 +-
 utils/kamctl/mysql/userblacklist-create.sql        |    26 +-
 utils/kamctl/mysql/usrloc-create.sql               |    74 +-
 utils/kamctl/oracle/acc-create.sql                 |     8 +-
 utils/kamctl/oracle/msilo-create.sql               |     6 +-
 utils/kamctl/oracle/presence-create.sql            |     3 +-
 utils/kamctl/oracle/registrar-create.sql           |    11 +-
 utils/kamctl/oracle/siptrace-create.sql            |     3 +-
 utils/kamctl/oracle/usrloc-create.sql              |     6 +-
 utils/kamctl/postgres/acc-create.sql               |     8 +-
 utils/kamctl/postgres/msilo-create.sql             |     6 +-
 utils/kamctl/postgres/presence-create.sql          |     3 +-
 utils/kamctl/postgres/registrar-create.sql         |    11 +-
 utils/kamctl/postgres/siptrace-create.sql          |     3 +-
 utils/kamctl/postgres/usrloc-create.sql            |     6 +-
 utils/kamctl/xhttp_pi/acc-table                    |     6 +-
 utils/kamctl/xhttp_pi/pi_framework.xml             |    46 +-
 utils/kamctl/xhttp_pi/presence-mod                 |     3 +
 utils/kamctl/xhttp_pi/presence-table               |     1 +
 utils/kamctl/xhttp_pi/registrar-mod                |    12 +
 utils/kamctl/xhttp_pi/registrar-table              |     4 +
 utils/kamctl/xhttp_pi/siptrace-mod                 |     3 +
 utils/kamctl/xhttp_pi/siptrace-table               |     1 +
 utils/kamctl/xhttp_pi/usrloc-mod                   |    12 +
 utils/kamctl/xhttp_pi/usrloc-table                 |     4 +
 utils/pdbt/.gitignore                              |     2 +
 utils/pdbt/debian/pdb-server.init.d                |    48 +
 utils/sercmd/Makefile                              |   107 -
 utils/sercmd/sercmd.8                              |    35 -
 ver.c                                              |    18 +-
 ver.h                                              |     8 +-
 ver_defs.h                                         |     9 +-
 xavp.c                                             |    12 +-
 xavp.h                                             |     9 +-
 2283 files changed, 83297 insertions(+), 33551 deletions(-)

diff --git a/.cvsignore b/.cvsignore
new file mode 100644
index 0000000..de33b82
--- /dev/null
+++ b/.cvsignore
@@ -0,0 +1,19 @@
+cfg.tab.c
+cfg.tab.h
+lex.yy.c
+ser
+librpath.lst
+*.tar.gz
+makecfg.lst
+config.mak
+modules.lst
+*.d
+*.so
+*.so.*
+*.o
+*.deb
+*.rpm
+tags
+TAGS
+.*.swp
+test/udp_flood
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..e0ed45f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,43 @@
+# ignore autogenerated files
+autover.h
+cfg.tab.c
+cfg.tab.h
+lex.yy.c
+librpath.lst
+makecfg.lst
+config.mak
+modules.lst
+# ignore dependency files
+*.d
+# ignore binary files and objects
+/ser
+/kamailio
+*.so
+*.so.*
+*.o
+# archives
+*.tar.gz
+*.deb
+*.rpm
+# tags
+tags
+TAGS
+# vi swaps
+.*.swp
+.*.swo
+# various other binaries
+test/udp_flood
+utils/gen_ha1/gen_ha1
+utils/kamcmd/kamcmd
+utils/sercmd/sercmd
+utils/sercmd/kamcmd
+utils/protoshoot/protoshoot
+# Emacs backup files
+*~
+# Emacs file locks
+.#*
+# MacOSX auto-generated files
+libiname.lst
+*.dylib
+# man pages
+*.7
diff --git a/AUTHORS b/AUTHORS
index b766254..e000c85 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,4 +1,3 @@
-# $Id$
 # The format of this file was inspired by the Linux kernel CREDITS file.
 # 
 # Authors and contributors are listed alphabetically (first name).
diff --git a/COPYING b/COPYING
index 391d8b5..22c373a 100644
--- a/COPYING
+++ b/COPYING
@@ -2,18 +2,18 @@
 -------------------------------------------------------------------------
 IMPORTANT NOTES
 
-1) The GPL applies to this copy of SIP Router software (sip-router).
+1) The GPL applies to this copy of Kamailio software (sip-router).
 
-2) SIP-router software allows programmers to plug-in external modules to the
+2) The Kamailio software allows programmers to plug-in external modules to the
    core part. Note that GPL mandates all plug-ins developed for the
-   SIP-router software are to be released under GPL license to be GPL-ed or 
+   Kamailio software are to be released under GPL license to be GPL-ed or 
    use a GPL compatible free software license.
 
    (see http://www.gnu.org/copyleft/gpl-faq.html#GPLAndPlugins
     for a detailed explanation)
 
 3) Note that the GPL bellow is copyrighted by the Free Software Foundation,
-   but the SIP-router software is copyrighted by multiple individuals and
+   but the Kamailio software is copyrighted by multiple individuals and
    companies.
 
 -------------------------------------------------------------------------
@@ -23,12 +23,12 @@ GNU Licence FAQ
 This FAQ provides answers to most frequently asked questions. To fully
 understand implications of the GNU license, read it.
 
-- you can run SIP-router for any purpose
+- you can run Kamailio for any purpose
 - you can redistribute it as long as you include source code and
   license conditions with the distribution
-- you cannot release programs derived from SIP-router without releasing
+- you cannot release programs derived from Kamailio without releasing
   their source code
-- you can not change the copyright of any part of SIP-router
+- you can not change the copyright of any part of Kamailio
 
 
 -------------------------------------------------------------------------
diff --git a/ChangeLog b/ChangeLog
index d71f2cc..738b95b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,12555 +1,8122 @@
-===================== 2015-05-19 Version 4.2.5 Released =====================
+===================== 2013-XY-XY Version 4.1.0 Released =====================
 
-===================== Changes Since Version 4.2.5 ===========================
+===================== Changes Since Version 4.0.0 ===========================
 
-commit 832118397f710479db8ed3c7ca84fb9de4a13716
+commit 7436e3f66782597d66d052ee9c87bdb3b91756ef
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue May 19 15:24:02 2015 +0200
+Date:   Mon Nov 11 11:21:21 2013 +0100
 
-    Makefile.defs: version set to 4.2.5
+    kamctl: regenerated db schema scripts
+    
+    - updated after mohqueue default date change
 
-commit c7ac6d742b2e9eb2a90747d065327612513eae6a
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue May 19 15:13:49 2015 +0200
+commit 8ebd2350ef97c6bac856850a3230ed3e245bd3ed
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Fri Nov 8 20:30:08 2013 +0000
 
-    core: enable log_prefix for sip responses
-    
-    - reported by Klaus Darilion
-    
-    (cherry picked from commit 967ed551845044123f4e93c60091d7a1fa43692f)
+    tls: TLSv1.1 supported since openssl v1.0.1
 
-commit a2cad23e21a164360ce560e04dcc2745533474c0
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue May 19 14:07:42 2015 +0200
+commit 55dd8073c7d06f3af37cded55e520e64457c2b42
+Author: Victor Seva <linuxmaniac at torreviejawireless.org>
+Date:   Fri Nov 8 16:41:30 2013 +0100
 
-    pkg/rpm: version set to 4.2.5 in spec files
+    rtpproxy-ng: ids to sections in documentation
 
-commit dde8d9286ab5a45ed2caee6ae2e7f42e146b5a00
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue May 19 14:05:31 2015 +0200
+commit 4060340d3af8112ad73ea881ab79270c06544476
+Author: Victor Seva <linuxmaniac at torreviejawireless.org>
+Date:   Fri Nov 8 16:32:35 2013 +0100
 
-    pkg/deb: version set to 4.2.5 in spec files
+    debugger: ids to sections in documentation
 
-commit 53dbdd384670e384c714739224e3c38366a23b3f
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu May 14 19:21:25 2015 +0200
+commit 5f1d6744aa20dc5774c8403bf918a9543afe6c75
+Author: Victor Seva <linuxmaniac at torreviejawireless.org>
+Date:   Fri Nov 8 16:28:19 2013 +0100
 
-    sipcapture: fix not to access freed pointer during shut down
-    
-    (cherry picked from commit 1db6fdf41dbb4b6c95e0f86dfebc4c793858d8b5)
+    avp: ids to sections in documentation
 
-commit cd42ec08027349be350b40e78bb5fff98ed32527
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu May 14 19:16:26 2015 +0200
+commit 3e6bef55f91206d7cf956a61e0b426bab5469e7b
+Author: Victor Seva <linuxmaniac at torreviejawireless.org>
+Date:   Fri Nov 8 16:03:25 2013 +0100
 
-    core: safety check for linker when inserting xavp with index
-    
-    (cherry picked from commit ec438b45696e17af0a3b19bb7ac12b221f897517)
+    avpops: ids to sections in documentation
 
-commit b8268aff60a023bfcd188f4c2e57fb3ba9b00138
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu May 14 14:51:06 2015 +0200
+commit 0e676d0062d7db0875ccc97053304807cbc5747e
+Author: Victor Seva <linuxmaniac at torreviejawireless.org>
+Date:   Fri Nov 8 15:56:33 2013 +0100
 
-    regex: replaced allocated memory initialization with a for loop to one memset
-    
-    (cherry picked from commit abdc02f1cb26c71b4118044d8c45dec728992e15)
+    usrloc: ids to sections in documentation
 
-commit 723f170b882d98a6100ccfb931447d7630f57bde
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu May 14 14:41:44 2015 +0200
+commit a88f9d4b79a40221e058c31bbdd21c8c25ba5003
+Author: Victor Seva <linuxmaniac at torreviejawireless.org>
+Date:   Fri Nov 8 15:21:58 2013 +0100
 
-    rr: reset lump pointer to avoid using it after free for remove rr function
-    
-    (cherry picked from commit f03c86ade6af9bc529a52f7fd50004721278ae19)
+    app_lua: ids to sections in documentation
 
-commit fd6dba3b9752e9cbf21da2ca7b66b2e5c1dafce7
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu May 14 14:36:24 2015 +0200
+commit ae0e9eef521fa39ae306a2c64e4add61d5e8af6f
+Author: Robert Boisvert <rdboisvert at gmail.com>
+Date:   Wed Nov 6 14:12:10 2013 -0500
 
-    regex: safety to check to avoid working with zero size allocations
-    
-    (cherry picked from commit 5e5866b2ac8390caa9373f49345ed877c6e5f037)
+    mohqueue: remove call from queue if caller does not exist
 
-commit e71012814800462519b9040e82c892dfa39bf817
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu May 14 14:29:12 2015 +0200
+commit 456c387e08ce40ea2c0f1e5e5f94b367ff9fa361
+Author: Robert Boisvert <rdboisvert at gmail.com>
+Date:   Tue Oct 29 18:10:25 2013 -0400
 
-    textops: safety check to know there is a string to add via lump
+    mohqueue: remove sql table call_time column's default value
     
-    (cherry picked from commit ca220afe0f738f2353d16c96dd16ab279ffdcf74)
+    it is not supported in some database properly, and it is not
+    really needed.
 
-commit 3fd7f816607acbc80ed49b5743dd55870d6b1e92
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu May 14 13:40:11 2015 +0200
+commit 04b457735f0bafa6ff214cb2d69afbe721d89bf1
+Author: Andrew Mortensen <admorten at isc.upenn.edu>
+Date:   Thu Nov 7 14:52:29 2013 -0500
 
-    tm: safety check not to allocate 0 bytes in rpc command
+    modules/sca: restore correct check for NULL in SCA_CALL_INFO_EMPTY.
     
-    (cherry picked from commit 88b67575f9457312d0277e16dc06103be3a31965)
+    - should also suppress -Waddress error without relying on gcc _Pragma.
+
+commit 0fbdb8cf7a7687d6ecc8049dfdcb1244abd726af
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed Nov 6 10:34:01 2013 +0000
+
+    tls: Fix minor typo in documentation
+
+commit fe914e16945caf6c5c11b81514dff89a0739b30e
+Author: Richard Good <richard.good at smilecoms.com>
+Date:   Wed Nov 6 09:14:45 2013 +0200
+
+    modules/dialog_ng: Fix "CRITICAL bogus event 6 in state 2" problem
+    	Use TM callback TMCB_RESPONSE_READY instead of TMCB_RESPONSE_OUT to prevent race condition resulting in bogus event
 
-commit 7cb9428ec3785e42b95eb2cc30cb4ac8503e760d
+commit cb66f43187ea3bcac36681b82630456deeabc64c
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu May 14 13:24:38 2015 +0200
+Date:   Tue Nov 5 15:10:29 2013 +0100
 
-    tmx: check for empty result not to allocate 0 bytes
-    
-    - allocation of 0 size is undefined when using system malloc
-    
-    (cherry picked from commit 0db313f0047fc512dec2976cac168989b60d49c8)
+    kamctl: added shortcuts for dialog mi commands
 
-commit c468ed26732022f532080dffc8c9f8aaf854ef2f
+commit 082a6c43938cf8e3839d46fd070e391bd522d4ed
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu May 14 13:15:06 2015 +0200
+Date:   Tue Nov 5 10:33:55 2013 +0100
 
-    presence_xml: better error handling to free all allocated vars
+    dialog: init cseq to 0 if not available yet for one side
     
-    (cherry picked from commit 2d40e14d2b0b150acd34ac2d1df25936d8faaca9)
+    - based on a report by Morten Isaksen
 
-commit 8f324fb6b3955ea6d5d4e57ec022d400f2c4e124
+commit 8d6a981543a044fddc3448c93dba9ed35afac0c0
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu May 14 13:09:47 2015 +0200
+Date:   Tue Nov 5 10:15:13 2013 +0100
 
-    pua: mark that tupple was allocated so can be freed in case of errors
+    pua_dialoginfo: fixed code formatting
     
-    (cherry picked from commit 1b20aa04048d15d0861b3f5291fd3b9a1614fdf5)
+    - patch by  Kristian Høgh, FS#360
 
-commit b103dff88f4ac83acf20798c06d43b2586810a36
+commit d48d36df40dee374e63ef9b6a6c1bafc4af0e8b0
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu May 14 13:01:18 2015 +0200
+Date:   Tue Nov 5 09:41:04 2013 +0100
 
-    regex: reset pointer after free to avoid double free if an error occurs
-    
-    (cherry picked from commit 379667e878c9e0795998f600edbcbb3974846f71)
+    dispatcher: typo and ids to sections in documentation
 
-commit bae153942524b1d86e29f10208e35dbf088d7db5
+commit f33076415561d3efbfa9d804d00a4b0784898f50
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu May 14 12:54:18 2015 +0200
+Date:   Mon Nov 4 21:46:34 2013 +0100
 
-    imc: better condition to catch no result of database query
+    sl: fix startup detection of event route
     
-    (cherry picked from commit 29d7ca71fdfc8c52fb5e68fcf3bccf98dde0d089)
+    - patch by Sergey Okhapkin
 
-commit a89778423e4886ac48857253d9567d17040e3b45
+commit 90227fbf44ddc67bfb49f8f7e8fd7e1b33189349
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu May 14 10:04:26 2015 +0200
+Date:   Mon Nov 4 14:26:19 2013 +0100
 
-    pua: safety checks for str pointers
+    presence_dialoginfo: check relevance of the state for single dialog notification
     
-    (cherry picked from commit 80977adc1bd70479c1e32d867563e4e684060b25)
+    - rework from a patch in tracker, FS#341
 
-commit e759e5c8998958eca61b317135be0acb3088fac0
+commit 27a73a806cece55bc7c707735856770137c2d680
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu May 14 10:25:47 2015 +0200
+Date:   Mon Nov 4 11:21:27 2013 +0100
 
-    core: init vars for socket ttl helper function to avoid warnings
-    
-    (cherry picked from commit 23b476ed7c7b48ddd7cacf3d88e9c104db06d5dc)
+    Makefile.defs: version set to 4.1.0-pre1
 
-commit c5015138170c9624055203cde4331091d96e928e
+commit 8a246b06838b99e63d86fe186b23a23f57347548
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu May 14 12:03:28 2015 +0200
+Date:   Mon Nov 4 10:04:35 2013 +0100
 
-    presence: initialize variable to avoid compile warning
+    pua_reginfo: reflect use domain from usrloc
     
-    (cherry picked from commit c5ef9569d524ab49d538e85a905520b72e1d8dea)
+    - avoid duplicate contacts if domain is not considered
+    - patch by  Wonbin Cho, FS#350
 
-commit 50d9cf9501f2ad3fbf9a282ea58055523b34d5cc
+commit 16649609796ec336278b073d86045f72a9dd7886
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu May 14 12:28:29 2015 +0200
+Date:   Sun Nov 3 13:23:32 2013 +0100
 
-    presence: initialize result to avoid freeing garbage in case of other errors
-    
-    (cherry picked from commit c24329ed483ea3abd720af73411a2331acc947e4)
+    tls: ifdef to use TLSv1.1 only for openssl/libssl v1.0.0+
 
-commit 6495f4120a702bd852c11d3449467e5ee0994bf7
+commit f4bf810a5af5b2d133df30e625691cc7b6ad2cf5
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed May 13 15:56:23 2015 +0200
+Date:   Sun Nov 3 13:15:31 2013 +0100
 
-    evapi: use internal log functions and free io struct if client failed to connect
-    
-    (cherry picked from commit eb889f41f036afb4248303fd6a1c7db393724c58)
+    tls: refreshed the README
 
-commit 129e1456bd5369912690245b5a21b0591ead51f4
-Author: Hugh Waite <hugh.waite at acision.com>
-Date:   Mon May 18 17:00:08 2015 +0100
+commit 1e2bb79a135bef9936fb5d5e0fb9a708589452b9
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Sun Nov 3 13:14:31 2013 +0100
 
-    core: Fix crash in xavp.c
-    
-    - Inserting an xavp into a list can crash when inserting XTYPE_NULL padding entries
-    (cherry picked from commit 497b6ad2cee8481ba1f3568ed7d8a836e508016a)
+    tls: listed TLSv1.1 and TLSv1.2 as values for tls_method parameter
 
-commit 511c7fb674928e6c2d67256714bd1b7394b0d550
-Author: Hugh Waite <hugh.waite at acision.com>
-Date:   Thu May 14 13:54:20 2015 +0100
+commit ea32bf9d3cf36c3562ca34d572bbf07ed144e105
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Sun Nov 3 12:55:08 2013 +0100
 
-    app_lua: Fix memory leak in sr.modf
+    tls: extended supportd tls methods
     
-    - Free pkg memory allocated to store cloned function parameters
-    (cherry picked from commit 733f5ad7c9b2515c52b00875fb5dac689ddd9a17)
+    - TLSv1.1 and TLSv1.2 (from openssl 1.0.1e on) added to the internal
+      list
 
-commit 0ba8d570acedc165b27336ec4cef2b11e0d31595
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Tue May 12 21:38:58 2015 +0200
+commit 26fa46a421e0bb5e00e32115b610100481e64e6d
+Author: Peter Dunkley <peter.dunkley at crocodilertc.net>
+Date:   Sat Nov 2 21:45:04 2013 +0000
 
-    travisci: use regex to select 4.X branches
-    
-    (cherry picked from commit 5695978137225cc16cbe1cf8282c3eb31262257d)
+    pkg/kamailio/centos: Improvement to the CentOS init.d script
 
-commit b73897a21afec416195c159858a20fc35f6889f0
+commit 039f52deb384c71ecfb578e2cd648153dd9937d1
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue May 12 20:18:04 2015 +0200
+Date:   Sat Nov 2 19:28:36 2013 +0100
 
-    dialog: fixed backport conflict for keepalive dialog state check
+    tls: include dprint.h where log functions are used
 
-commit 0a1865e84b2b1e2b5ee06966b91680d7c7743126
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon May 11 22:13:31 2015 +0200
+commit 25ee7ea17b6553ce44eda6c0665ff80cfc41db35
+Author: Juha Heinanen <jh at tutpro.com>
+Date:   Fri Nov 1 21:27:31 2013 +0200
 
-    presence_dialoginfo: fixed several libxml2 API usage leaks
-    
-    - reported by dkovik, GH#155
-    
-    (cherry picked from commit 6390b0506856529849ef02001a992db9057c795f)
+    modules/mtree: added 'multi' param to mtree definition
+    - new 'multi' param makes it possible to store both integer and string
+      typed mtrees into single db table
 
-commit b4e39387136bf1850a486c4ae5b497050e46740b
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon May 11 17:15:10 2015 +0200
+commit 66185905850cd2ac9ab933776184da0f0882e5ac
+Author: Victor Seva <linuxmaniac at torreviejawireless.org>
+Date:   Fri Nov 1 15:33:08 2013 +0100
 
-    dialog: don't send keepalive if dialog not in confirmed state
-    
-    - if dialog is in deleted state, remove it from keep alive list
-      immediately
-    
-    (cherry picked from commit 0e22abe2b89be8936df4b8230955fbaf43ad40e7)
+    registrar: clean static values at pack_ci
+
+commit f67171cf3be1ade0e1c9dd013d560c87b3fd4359
+Author: Victor Seva <linuxmaniac at torreviejawireless.org>
+Date:   Thu Oct 10 15:21:47 2013 +0200
+
+    usrloc: db_update contact by instance + reg-id
 
-commit bf8be8c52039fc50dafd0c9c140c01ab84384977
+commit bc66a385e8a282638c8d5cfa566f971c62cd341b
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sun May 10 18:18:00 2015 +0200
+Date:   Fri Nov 1 09:39:32 2013 +0100
 
-    tm: disabled use of dedicated mutex for async continue
+    uac: reset registration authentication flag
     
-    - it can be enabled by defining ENABLE_ASYNC_MUTEX
-    - reply mutex is re-entrant and protects better the transaction
-      strucutre
-    - a dedicated lock for async continue exposes a race on removing from
-      timer when suspended transaction is resument at the same time when the
-      timer fires expiration event
-    
-    (cherry picked from commit 96b84ba4d7f5ee4a763fe7db81bbf4f9a6a3ef77)
+    - reported by  rene montilva (fs#352)
 
-commit 766542727ab054c790fc820e4a09a4cdbc4e73ae
+commit 1cc0144e434fdcf76013e9424d31928c260d4377
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu May 7 13:23:43 2015 +0200
+Date:   Wed Oct 30 22:11:04 2013 +0100
 
-    dialog: check if dialog is still in confirmed state when processing keepalive reply
+    kamctl: updated dispatcher command to current db table fields
     
-    (cherry picked from commit 04410aef38f5ed40c8f4a6796d95658407e1597c)
+    - parameters flags, priority, attrs and description are optional
 
-commit 4f2339fd9f8cff6c2649a22242dd30562d59ed76
-Author: Jon Bergli Heier <jon.bergli.heier at zisson.no>
-Date:   Thu May 7 11:08:08 2015 +0200
+commit bfc2215d71734b09a1d7acd4dbdbe919b234c30f
+Author: Juha Heinanen <jh at tutpro.com>
+Date:   Wed Oct 30 20:49:26 2013 +0200
 
-    htable: Add missing ht_slot_unlock in ht_cell_value_add
+    Revert "modules/mtree: when loading data from db, load each tree separately"
     
-    (cherry picked from commit ace37c7a60e5d931216339c179de6e91615dac7e)
+    This reverts commit 6fc84c2cf610791939ba73e38b8b5b3c0b5cd047.
 
-commit 5b0fa2fedbf4ffc81d0ac322a68bd2946363cc55
-Author: Mikko Lehto <mslehto at iki.fi>
-Date:   Wed May 6 06:32:30 2015 +0300
+commit 6fc84c2cf610791939ba73e38b8b5b3c0b5cd047
+Author: Juha Heinanen <jh at tutpro.com>
+Date:   Wed Oct 30 17:31:04 2013 +0200
 
-    sctp: fix typo scp_register_rpc -> sctp_register_rpc
-    (cherry picked from commit 177b0d2807763b13d30148f44c1cc4d3d765d67c)
+    modules/mtree: when loading data from db, load each tree separately
 
-commit 4ba9c0ed412310d97b9a4fda3830d93c486c1888
-Author: Mikko Lehto <mslehto at iki.fi>
-Date:   Tue May 5 21:54:22 2015 +0300
+commit f0751ffa2d1d99c0a54707cfe22926bea9c07123
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed Oct 30 17:12:05 2013 +0000
 
-    pua_mi: document missing mi_pua_publish parameter "id"
-    (cherry picked from commit 201dc5b600d8516368a54c70af6f02c3ea06353b)
+    modules/rls: Fix memory leak in rls
+    - Leak would occur in two error cases
+    - Also improved diagnostics to display uri on various failures
 
-commit e1d8b50c8e262c259c57f91de95efae5798538fa
+commit 76536ec5332d7897cd4259b271508cc9d4e2bc2e
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Apr 23 16:34:35 2015 +0200
+Date:   Wed Oct 30 16:08:47 2013 +0100
 
-    permissions: fixed reload trusted rpc command
-    
-    - reported by Emmanuel Schmidbauer, GH#138
-    
-    (cherry picked from commit 48663e4239f819b42e7035d9f4023c161eb71d05)
+    kamailio.cfg: removed modules_k from path for modules
 
-commit 574c8bab52d3aad39ae21dfb39a756e14f28fea9
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Apr 23 16:23:01 2015 +0200
+commit 328350a0d718990f8a87f25f8c12f1c85d61220f
+Author: Richard Good <richard.good at smilecoms.com>
+Date:   Wed Oct 30 12:50:04 2013 +0200
 
-    permissions: store src ip in zero terminated string for trusted table
-    
-    - it is printed as string via rpc, resulting in invalid chars in the
-      output
-    - reported by Emmanuel Schmidbauer, GH#137
-    
-    (cherry picked from commit 89642d3cddd90ba3e3f6d310e239492634fa6405)
+    modules/ims_charging: fixed failed reservation bug
+    	- Reservation checks dialog integrity with h_entry < 0
+    	- The hash that creates h_entry can return 0 - this check should be <= 0
 
-commit e2f304fb532da500d7fc6c790c4750a73ae848fa
-Author: mikomarrache <mikomarrache at users.noreply.github.com>
-Date:   Wed Apr 22 15:04:40 2015 +0300
+commit a7037aad9963678347bf2b1c15c4994e95570f86
+Author: Richard Good <richard.good at smilecoms.com>
+Date:   Wed Oct 30 12:49:26 2013 +0200
 
-    db_mongodb: fix typo
-    (cherry picked from commit aa87b852fbfd333f2073ac7390c3f3b6568e0024)
+    modules/ims_charging: code clean up, removed duplicate timer init and dlg bind
 
-commit ed2c270ee1b4d447796803c37241a1207dd9c191
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Apr 21 19:10:01 2015 +0200
+commit a3db949272db7dbda4fa5fd1ad68d23d56deacc0
+Author: Richard Good <richard.good at smilecoms.com>
+Date:   Wed Oct 30 09:15:51 2013 +0200
 
-    textopsx: fixed clang compile warning on comparing bool with char
-    
-    (cherry picked from commit bc5ac8caee55f8d197992fb00b4cb098eeb69843)
+    modules/tm: code cleanup removed unused method faked_resp and free_faked_resp
 
-commit b5cd3fdea7e37ce3bfb28fcde252012c0d7336ca
+commit 15a14440f07f787501e116ab4901ab5a53668f4a
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Apr 16 11:59:30 2015 +0200
+Date:   Tue Oct 29 22:00:18 2013 +0100
 
-    acc: warning set to debug level if request is missing for dialog cdrs
-    
-    - self generating bye requests don't have incoming request
-    
-    (cherry picked from commit 26543b90f80791b9e2b763fb97d78a8c90e445dc)
+    kamctl: added new db tables in kamdbctl lists
 
-commit cf9e203c912d66e5a498e50b97118af1e0be5d05
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Apr 15 18:04:10 2015 +0200
+commit 2e033c85d2c66c47de15f355298012f012adb15c
+Author: Richard Fuchs <rfuchs at sipwise.com>
+Date:   Tue Oct 29 15:30:36 2013 -0400
 
-    dialog: run both DLGCB_TERMINATED and DLGCB_TERMINATED_CONFIRMED callbacks for local BYE
+    rtpproxy-ng: fix extraction of multipart SDP body
     
-    - only DLGCB_TERMINATED was run, but that resulted in CDRs not being
-      stored by acc for that situation
-    - on a report by Mickael Marrache
-    
-    (cherry picked from commit 265dc95aac8eb4b5cee7992dde55ff08c92a7ac5)
+    reported by: Jasmin Schnatterbeck
 
-commit e6c9a20503538b70dc01a9a9ee6299fc8043606a
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Apr 15 18:03:40 2015 +0200
+commit 355ab783a99e413eb96a385ab067336316aaafda
+Author: Richard Good <richard.good at smilecoms.com>
+Date:   Tue Oct 29 12:40:42 2013 +0200
 
-    acc: DLGCB_TERMINATED callback can be run without received request
-    
-    - the case of local generated bye
-    
-    (cherry picked from commit 1e7e0279bbf53c4a530aa3a8c1d322a68d8090f9)
+    modules/cdp/acctstatemachine.c: fixed incorrect reservation expiry warning
+    	First check if acc state is OPEN before sending reservation expiry warning
 
-commit 3d2e3433fd6a3e3f886e1591b11614817078889c
+commit c4a4b4f599ba428330899e804877e85d3fdcc3a4
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Apr 15 11:25:18 2015 +0200
+Date:   Tue Oct 29 11:08:49 2013 +0100
 
-    tls: updated to use shm_available_safe()
-    
-    (cherry picked from commit c178f4427af82d6d33101677835c60de1c343073)
+    kamctl: updated db creation scripts
 
-commit f9a0c9b4d49acedc34fead30e69e997dda0220ad
+commit ecc6e35b31d59e6e9995a03c6ab00f21a23b1be9
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Apr 15 11:22:36 2015 +0200
+Date:   Tue Oct 29 11:07:03 2013 +0100
 
-    tls: removed inline specifier and renamed safe_shm_available()
+    srdb1: drop unique constrant on alias user+domain in dbaliases
     
-    - became shm_available_safe() to have the shm_ prefix which common for
-      shm functions
-    - declaring inline in c header file and implementing in c source file
-      makes clang throw compile warnings
-    
-    (cherry picked from commit c4d48f3ae363fb6f6a7d789a0f32b28eb60c2404)
+    - it doesn't work for multiple branches when use_domain is set, reported
+      by Vassilis Radis
 
-commit e463d8333d12b8d320106725938e5425d83a652b
+commit da3d48de7d52df83fcb568530441e7ac6475baae
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Apr 15 11:16:01 2015 +0200
+Date:   Tue Oct 29 10:08:04 2013 +0100
 
-    usrloc: change log level from info to dbg when socket is not local
-    
-    - common scenario when working with shared db, reducing the syslog
-      thoughput
-    - based on a patch by Mickael Marrache
-    
-    (cherry picked from commit 1f2921097316925600573402793b5332a6535e7d)
+    pua_publish: more verbose output for error case when sending publish
 
-commit 177a169e4eb883b8a38bdab2ba0dd4439d766646
-Author: Camille Oudot <camille.oudot at orange.com>
-Date:   Tue Apr 14 19:41:38 2015 +0200
+commit 73d509f04029dddc94bedba23460d43c81acc13a
+Author: Richard Good <richard.good at smilecoms.com>
+Date:   Tue Oct 29 10:51:32 2013 +0200
 
-    tls: use multiprocess-safe shm_available()
-    
-    under high load, the values returned by shm_available() can be inconsistent.
-    Use safe_shm_available() instead.
-    
-    (cherry picked from commit 1fe36fa983b8f271165750977120d758faf84d01)
+    modules/ims_registrar_pcscf: replaced incorrect LM_ERR with LM_DBG
 
-commit c8e704539cd64ce932b276f455524dd4a8d64e04
-Author: Camille Oudot <camille.oudot at orange.com>
-Date:   Tue Apr 14 19:38:14 2015 +0200
+commit 41a9fbf38ba84e542a546893a6ce9c48f14f3aa3
+Author: Jason Penton <jason.penton at smilecoms.com>
+Date:   Tue Oct 29 10:31:52 2013 +0200
 
-    mem: add a multiprocess-safe shm_available()
-    
-    new safe_shm_available() function secured with shm_lock()
-    
-    (cherry picked from commit 51e263de80532e297546f17d2f2ed528ffe9731b)
+    modules/tm: fixed placement of variable declarations to top of scope block
 
-commit 9839280c0c2aabdd7749cb7553354fb20545a0ea
-Author: Mickael Marrache <mickaelmarrache at gmail.com>
-Date:   Tue Apr 14 18:18:30 2015 +0200
+commit 716932aa77a0f22f00d2ccee8a89cd84b6674f0a
+Author: Jason Penton <jason.penton at smilecoms.com>
+Date:   Tue Oct 29 09:49:42 2013 +0200
 
-    db_mongodb: change warn to info for log message on unhandled data type log
-    
-    - less verbosity to syslog
-    
-    (cherry picked from commit ebf6483650c0cff88703e071383184b3f4ac7309)
+    modules/tm: cosmetic fixes and comment fixes
 
-commit 9ab45a4b0c557aa2bfcf121361346590e0246f73
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Apr 10 11:32:20 2015 +0200
+commit a7d9ea3ceda6b933807f0345e327849e60d0fa57
+Author: Jason Penton <jason.penton at smilecoms.com>
+Date:   Tue Oct 29 09:42:45 2013 +0200
 
-    ndb_mongodb: fixed name of the function in docs
-    
-    (cherry picked from commit c6eff0f5f6ec33fba5d61e4a6616d1bddfe6f958)
+    modules/tm: last pkg_mem leak resolved for async replies (nonshm lumps)
 
-commit d5220ac3efc2df4a1995fc79425340cfc79ecf00
+commit 3022220043bcc9c421ac175b2a3290950014a7fc
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Apr 8 16:29:33 2015 +0200
+Date:   Tue Oct 29 08:34:29 2013 +0100
 
-    kamctl: added help for 'db connect' command
-    
-    (cherry picked from commit 545037884e806df0d450fd6d7b425808c944d8a8)
+    kamctl: regenerated db script for mohqueue tables
 
-commit 2786d32a29e29c77f7b5ea0f2e044c53afa43e3c
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Apr 3 20:02:37 2015 +0200
+commit 3eeeed2aeeb924afeabc3fc8337561624f0c41d0
+Merge: 946e1f0 b5638f7
+Author: Jason Penton <jason.penton at smilecoms.com>
+Date:   Mon Oct 28 15:03:08 2013 +0200
 
-    uac_redirect: updated the example script
-    
-    (cherry picked from commit 1a3ce79cc058c57197a7b3736b3ec8b08be5c33f)
+    Merge branch 'master' of ssh://git.sip-router.org/sip-router
 
-commit a3a050c862398e6afa39f5dc1b00b0e9f93aad1a
-Author: Federico Cabiddu <federico.cabiddu at gmail.com>
-Date:   Sat May 9 18:16:28 2015 +0200
+commit 946e1f01889c67a835583f4df2c773d227693ea7
+Author: Jason Penton <jason.penton at smilecoms.com>
+Date:   Mon Oct 28 14:51:12 2013 +0200
 
-    modules/nathelper: don't include enclosing bracket in contact uri in set_contact_alias
-    
-    (cherry picked from commit b525ada2d12bf85c385a5f97859afd5d52405354)
+    modules/tm: fixed pkg memory leak in TM which happens in async reply processing
 
-commit 97f1ee6e287b6f711ddbe04700a82295341ed880
-Author: Timo Teräs <timo.teras at iki.fi>
-Date:   Mon Mar 9 16:30:53 2015 +0200
+commit b5638f712711deb8413d7e585369adf8f4a421ee
+Author: Richard Good <richard.good at smilecoms.com>
+Date:   Mon Oct 28 14:41:22 2013 +0200
 
-    sqlops: fix use-after-free by deep copying result name
-    
-    When creating a new result handle, deep copy the result name.
-    Otherwise we might end up accessing the name after it's freed.
-    
-    (cherry picked from commit 6e2604464e64cfaaf1e0327228f53f4787b69470)
+    modules/ims_qos: memory optimisation
+    	Fixed pkg memory allocation for framed IP AVP and flow buffer AVP
+    	Instead of repeatedly alloc'ing and free'ing pkg memory we allocate once and re-use
+    	Results in better pkg memory overhead
 
-commit d3005687cc7d52ef689592391a19fc89c59aa312
+commit 3856e9e81c8410b220b893a0dfe7114bba6bdc0d
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Apr 16 10:51:36 2015 +0200
-
-    uac: reset the ongoing registration flags in case of error in tm callback
-    
-    - resulted in being stuck in a state that didn't retry registration
-    - reported by AndyJRobinson, GH#124
-    
-    (cherry picked from commit 08d7b66310e7c09a70db296f533f98b32d2e4ad8)
+Date:   Sun Oct 27 16:59:32 2013 +0100
 
-commit a23331fbe5392cb6902dfd891b02162c65874f21
-Author: Camille Oudot <camille.oudot at orange.com>
-Date:   Mon Apr 13 17:04:41 2015 +0200
-
-    pv: fix memory leak when getting $conid
+    core: handle pv comparison with $null as when defined is used
     
-    cherry-picked from 0e8ef73c2095a7564735a1dab9ed32e3531fc59e
+    - reported by Victor Seva, closes FS#358
 
-commit ac36829250fb8cf8347328cdfd980fd9362a1e33
+commit 3d716a94b620e0115381b164595ef0398c816856
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Apr 7 12:34:34 2015 +0200
+Date:   Sat Oct 26 08:59:09 2013 +0200
 
-    textops: fixed reply code on no-match for search_hf() with flag f
+    kamctl: use a variable to set the now() function or a replacement for it
     
-    - true instead of false was returned
-    - reported and patch by Paolo on sr-users
-    
-    (cherry picked from commit 59f1451db54be608f1417075001d2f0aa5be8786)
+    - sqlite uses instead the string returned by 'date' call, as it doesn't
+      have now()
+    - reported by Peter Dunkley, FS#356
 
+commit 2a046e5fd3c47bc7753190425b911b4114667563
+Author: Peter Dunkley <peter.dunkley at crocodilertc.net>
+Date:   Thu Oct 24 20:44:03 2013 +0100
 
-===================== 2015-04-02 Version 4.2.4 Released =====================
+    pkg/kamailio/centos: added app_java to CentOS RPMs
 
-===================== Changes Since Version 4.2.3 ===========================
+commit 9c765e89ea7647b1e9c5e36eb0b324eec1d92b7d
+Author: Peter Dunkley <peter.dunkley at crocodilertc.net>
+Date:   Thu Oct 24 20:13:11 2013 +0100
 
-commit 144a09eb4eb01eb45e79923e4101bc5a09d04c28
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Apr 2 12:49:05 2015 +0200
+    modules/app_java: updated Makefile so that it builds on CentOS 6
 
-    Makefile.defs: version set to 4.2.4
+commit 9a67a730df4f6c6584e8c52934d5feb16f86ee2e
+Author: Richard Fuchs <rfuchs at sipwise.com>
+Date:   Thu Oct 24 12:34:05 2013 -0400
 
-commit a4cf2c8fda717ed087b075e41a1b78708e3c97a5
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Apr 2 12:13:04 2015 +0200
+    tm: fix possible segfault in cancel_branch()
 
-    pkg/rpm: version set to 4.2.4 in spec files
+commit 9ca1648fbf167748bcf9155794f703632ca87503
+Author: Charles Chance <charles.chance at sipcentric.com>
+Date:   Thu Oct 24 16:36:01 2013 +0100
 
-commit f76e0b3adb42b6e9e8b0055b75dadac6d9a4b107
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Apr 2 12:09:56 2015 +0200
+    htable: ht_dmq_handle_msg() - do not call parse_headers on cloned message
 
-    pkg/deb: version set to 4.2.4 in spec files
+commit 2c990487a780bce2ee2fe64e155ec3f1bc1bdebf
+Author: Charles Chance <charles.chance at sipcentric.com>
+Date:   Thu Oct 24 16:15:10 2013 +0100
 
-commit 9b1991a53283e2a16b5a20f88e83e4afa64b81f2
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Mar 31 15:15:27 2015 +0200
+    memcached: revert earlier doc change regarding minimum library version (we now have backward compatibility built in)
 
-    presence: query_str filled with value of the corresponding column
-    
-    - static value was used that made setting of parameter for column names
-      not being considered
-    
-    (cherry picked from commit 845bdb8884743f5e126a53eb6aeb34f1f6afb1ea)
+commit fc4f2216f867b00a6685abdf51b8165572f24f69
+Author: Carlos Ruiz Diaz <carlos.ruizdiaz at gmail.com>
+Date:   Thu Oct 24 11:05:17 2013 -0300
 
-commit 5f508193ba3abf4fbb76defc1c0f333e38ff5dfc
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat Mar 28 15:00:48 2015 +0100
+    ims_charging: fixed deadlock when interim CCA timeout occurs
 
-    tm: clone path vector back to pkg for faked message
-    
-    - it is cloned and can be changed, resulting in attempt to free a shm
-      pointer via pkg operation
-    - reported by Jose Seabra
-    
-    (cherry picked from commit 8a7c70a5b831542cde77e7945e97d51901b95310)
+commit b0797b765af78f19d942a87ea978037027da57c3
+Author: Peter Dunkley <peter.dunkley at crocodilertc.net>
+Date:   Thu Oct 24 13:10:08 2013 +0100
+
+    pkg/kamailio/centos: added memcached package to .spec
+    
+    - Also:
+      - updated README to remove memcached from list of unbuilt modules
+      - moved auth_identity into the tls package
+    - List of modules not built for CentOS is now:
+      - app_java: should be buildable but Makefile needs work
+      - app_mono: needs newer version of mono-devel than available in base or EPEL
+      - db_cassandra: needs specific versions of thrift (thrift not in base or EPEL
+        at all anyway)
+      - db_oracle: requires non-free Oracle client SDK
+      - iptrtpproxy: obsolete
+      - jabber: obsolete
+      - osp: requires OSP Toolkit which is not available in base or EPEL
+
+commit adfa299a1a01aba1c69c1129d78170056d50db42
+Author: Charles Chance <charles.chance at sipcentric.com>
+Date:   Thu Oct 24 12:14:38 2013 +0100
 
-commit 9a00a53deb90ab16f0e73a7f63390f208042e559
+    memcached: added alternate memory management wrappers for backwards compatibility with older libmemcached versions and added preprocessor check for the correct ones to use based on installed version.
+
+commit a067a3d33ad67c260a3bc377cd4203d41880ca6b
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat Mar 28 14:31:59 2015 +0100
+Date:   Thu Oct 24 07:44:03 2013 +0200
 
-    tm: reply_lock per transaction made re-entrant
-    
-    - on a report by Jason Penton
-    - re-ordered some includes to get rid of cross dependencies in defines
+    tm: use internal flags field to mark suspended replies with FL_RPL_SUSPENDED
     
-    (cherry picked from commit 3957db5fb51e23535a89b15c8f05463e5702424d)
+    - it was set on cfg flags, resulting in messing up with what was used in
+      config file
+    - reported by Juha Heinanen
 
-commit e79c347fbcc9db52ee8b3ab1a733fdfcd143c0d2
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Mar 26 15:51:54 2015 +0100
+commit 6b8b8a050e4490302d1f1f940a7fda95784cce46
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Wed Oct 23 14:53:04 2013 +0100
 
-    presence: more use of variable for received_time column instead of static value
+    modules/xcap_server: fixed fetching of an element (GET with XPath)
     
-    (cherry picked from commit beba4579778f8af0bc0d88c13a6f433dd9ffa8a0)
+    - This is a mandatory part of XCAP and DELETE/PUT of elements (using XPath)
+      is supported in xcap_server.
+    - The code to get a node from a document was all in there but never called.
 
-commit 74e136f0b3ab07f7bd55a6aa1e0522d7d1472548
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Mar 26 15:48:09 2015 +0100
+commit 3b028d308fac3a4f7ae1e74021882657753f2ee8
+Author: Charles Chance <charles.chance at sipcentric.com>
+Date:   Wed Oct 23 12:01:27 2013 +0100
 
-    presence: use name of received_time column from associated variable
-    
-    (cherry picked from commit 8729aa8cde19f39eebce7ef9be7e31ea121b9a99)
+    dmq: Fixed bug/error in original code where sip_msg was parsed after cloning to shm, leading to memory errors. Also fixed several memory leaks.
 
-commit cc1dcba334dffc965802e8eaeb156c7027a7a630
-Author: Richard Fuchs <rfuchs at sipwise.com>
-Date:   Fri Mar 20 09:43:36 2015 -0400
+commit eb97ddb20368c019b331cfd09e793a0431d49940
+Merge: f6d530e 58a3069
+Author: Jason Penton <jason.penton at smilecoms.com>
+Date:   Tue Oct 22 20:59:26 2013 +0200
 
-    tmrec: update licensing and copyright info
-    
-    (cherry picked from commit e172b7a1b66edfb302da8d498eada7da9f21643e)
+    Merge branch 'master' of ssh://git.sip-router.org/sip-router
 
-commit f7300652f8c7e252165a5b04090e35f2eca1b6a7
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Mar 20 12:57:04 2015 +0100
+commit f6d530e68ffe9db11f5f148c51f8bff0b542f028
+Author: Jason Penton <jason.penton at smilecoms.com>
+Date:   Tue Oct 22 20:57:52 2013 +0200
 
-    tm: formated the comment without + chars
-    
-    (cherry picked from commit e6cdb91037abc5a7668e7919281072b15e758739)
+    modules/cdp: allow CDP child processes to respond to dynamic cfg changes
+    	- this for example allows dumping pkg memory using core cfg variables similar to SIP workers, etc
 
-commit 28ea4c042b51152f0968ce10b0b71a4fb1d356c5
-Author: jaybeepee <jason.penton at gmail.com>
-Date:   Fri Mar 20 13:29:34 2015 +0200
+commit 58a3069927a2e37c327256cd3475d7a7f8a2f5c4
+Author: Peter Dunkley <peter.dunkley at crocodilertc.net>
+Date:   Tue Oct 22 11:08:08 2013 +0100
 
-    modules/tm: restore code to set blind uac branch last_reply > 200
-    
-    (cherry picked from commit 0ee3dc5e3edc49cf62f97ddd87a40b12c59b73ff)
+    pkg/kamailio/centos: updated README to remove mi_xmlrpc from the set of unbuilt modules
 
-commit 9a71a7e09f9a764e0c7d0e846474608bed420035
-Author: Giacomo Vacca <giacomo.vacca at gmail.com>
-Date:   Thu Mar 19 11:30:56 2015 -0400
+commit d79cffa79ab740bc3e724fc0e9b8fc9f7236af44
+Author: Peter Dunkley <peter.dunkley at crocodilertc.net>
+Date:   Tue Oct 22 11:07:40 2013 +0100
 
-    textops: minor typos in README
-    
-    (cherry picked from commit 5681e9c6e9850eedd15e53219ce2bc55fd38dd90)
+    pkg/kamailio/centos: updated .spec to add mi_xmlrpc to xmlrpc package
 
-commit b06ab1be65b96cc064f5e036bd42d014bc10f4ad
-Author: Giacomo Vacca <giacomo.vacca at gmail.com>
-Date:   Thu Mar 19 11:28:58 2015 -0400
+commit 05f0ed6d77602f3ee1a2cfc8cee1c760dc2f6800
+Author: Peter Dunkley <peter.dunkley at crocodilertc.net>
+Date:   Tue Oct 22 10:45:56 2013 +0100
 
-    textops: minor typos in doc
-    
-    (cherry picked from commit 6c866c1296a34e0733bf33a1feac57ca8bfc64d7)
+    modules/mi_xmlrpc: fixed compilation warning
 
-commit aa458695a1f7272ff1c898ed728dd97b72290ccb
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Mar 18 19:50:09 2015 +0100
+commit b3dedff1053a1d35e803f3824042732f07532b77
+Author: Muhammad Shahzad <shaheryarkh at gmail.com>
+Date:   Tue Oct 22 10:43:43 2013 +0100
 
-    tm: propagate the on_failure value in to the branch for t_suspend()
+    modules/mi_xmlrpc: patched so that it now builds for CentOS
     
-    - likely lost when on_failure was added to each branch structure
-    - reported by Mickael Marrache
-    
-    (cherry picked from commit 6484b199fb48acc2c55f318812f2c968b845ca80)
+    - Patch by Muhammad Shahzad <shaheryarkh at gmail.com>
+    - Committed by Peter Dunkley <peter.dunkley at crocodile-rcs.com>
 
-commit e1d18d0234bb43b39aed72108c0408724c6849a4
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Mar 11 09:42:02 2015 +0100
+commit 11abcfd96f30aa5f0032385ac5893c27bdf6315b
+Author: Charles Chance <charles.chance at sipcentric.com>
+Date:   Mon Oct 21 14:40:10 2013 +0100
 
-    ctl: use uid/gid from the core if not set for the module
-    
-    - otherwise it cannot do clean created files at shut down
-    
-    (cherry picked from commit 3b5633de56c2367d19122f0f3c01698af34a21e9)
+    memcached: added minimum libmemcached version required to documentation
 
-commit b2084ee2e828a94dfc0e565ef713d6101d9fb442
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Mar 11 09:40:52 2015 +0100
+commit 4bffd1950e4481a734141ae6cf755458f341f45b
+Author: Peter Dunkley <peter.dunkley at crocodilertc.net>
+Date:   Mon Oct 21 13:40:46 2013 +0100
+
+    pkg/kamailio/centos: updated README that explains which modules are not built for CentOS
+    
+    - The modules not built at this time are:
+      - app_java
+      - app_mono
+      - db_cassandra
+      - db_oracle
+      - iptrtpproxy
+      - jabber
+      - memcached
+      - mi_xmlrpc
+      - osp
+
+commit e3524fb816c1fad04b3c855e3fe88151b33e24c8
+Author: Peter Dunkley <peter.dunkley at crocodilertc.net>
+Date:   Mon Oct 21 13:37:45 2013 +0100
+
+    pkg/kamailio/centos: updated .spec to build packages with dependencies that can be met by EPEL
+    
+    - This means the computer building the RPMs needs to have access to EPEL and
+      the appropriate dependencies installed from it.  However, there will be
+      no need to have EPEL dependencies installed on a running instance _unless_
+      you want to use one of the modules with an EPEL dependency.
+    - The modules supported with EPEL are:
+      - acc_radius, auth_radius, misc_radius, peering
+      - carrierroute
+      - dnssec
+      - geoip
+      - json, jsonrpc-c
+      - ndb_redis
+
+commit 9f08b58f58585559646b470ae9f4b9801617ba73
+Author: Peter Dunkley <peter.dunkley at crocodilertc.net>
+Date:   Sun Oct 20 23:52:23 2013 +0100
 
-    core: set the global sock_uid/gid based on the user/group values
-    
-    - they were left with initial value, more or less being unused
-    
-    (cherry picked from commit d7a10e6a5ea8852681b57586eb9b4d73b75f05bf)
+    pkg/kamailio/centos: updated rel in .spec
 
-commit 4ab41baecf0f9912c2a3ed859d53ffe3e5b46a26
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat Mar 7 23:31:49 2015 +0100
+commit ce9f46a3778cd6c79f2411b5934e3ad320cf6de4
+Author: Peter Dunkley <peter.dunkley at crocodilertc.net>
+Date:   Sun Oct 20 23:46:35 2013 +0100
 
-    registrar: use proper iterator to get to the index of the $ulc() contact
-    
-    - part of a patch by Luis Azedo
-    
-    (cherry picked from commit f39b92acb2be15e03aa117bdf171087ea7a77050)
+    pkg/kamailio/centos: removed out-of-date BoxGrinder appliance files
 
-commit 6697d2ecfd254f2269317785654a5881e684210b
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Mar 5 21:26:36 2015 +0100
+commit 0de2ae72410f0672f174a8cae34d4ac12798a188
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Sun Oct 20 23:27:58 2013 +0100
 
-    enum: updated the docs in regards to max len for enum number
-    
-    - synced with the code, following on a report from Alex Balashov
-    
-    (cherry picked from commit 910be93e5caebea5cef33335d0c48de636169ff5)
+    pkg/kamailio/centos: updated documentation
 
-commit 745f951d08acdf65ff0de878fcbe3a945171ffc7
-Author: Sebastian Thörn <sebastian.thorn at loxytel.se>
-Date:   Wed Mar 4 17:16:22 2015 +0100
+commit 61ad39509ca1d739d00d0386ab5a991cf54477d8
+Author: Øyvind Kolbu <oyvind.kolbu at usit.uio.no>
+Date:   Sun Oct 20 22:04:16 2013 +0200
 
-    Fixed path ss -> ssl
+    fix dns srv failover when no UDP record is present
     
-    (cherry picked from commit a5245d5c44cd49a699caa94f844dfb128a8d9764)
+    - refactored code for srv lookup to have less code duplication
 
-commit 7993d34c292aea01cf32bea3bb300aeb666ab90d
-Author: Luis Azedo <luis at 2600hz.com>
-Date:   Wed Feb 25 18:16:48 2015 +0000
+commit 820046b04c2218273a11f905dc798812d7ca0ca6
+Author: Jason Penton <jason.penton at smilecoms.com>
+Date:   Fri Oct 18 09:21:02 2013 +0200
 
-    usrloc - fix db_delete_ucontact_ruid
-    
-    when the contact is deleted using db_delete_ucontact_ruid (default)
-    the uldb_attrs_delete is not called leaving the location_attrs with unwanted records
-    
-    created uldb_attrs_delete_ruid to be called by db_delete_ucontact_ruid
-    redirected uldb_attrs_delete to uldb_attrs_delete_ruid when ul_db_ops_ruid == 1
-    
-    (cherry picked from commit 09c51685af36071aad6054d84571c260be2ba9e2)
-    (cherry picked from commit f5a7b12ce5f73749e9ae3d7a31e2a3616539421c)
+    modules/ims_registrar_scscf: added outstanding documentation
 
-commit 21311a110cb0d70a53224d12ced09972a0a15235
+commit 37f284d2d9bbe6dac4888600d0b99ccc58d22eb9
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Feb 26 21:58:47 2015 +0100
+Date:   Thu Oct 17 18:18:17 2013 +0200
 
-    uac: skip only the invalid record when loading remote registration records
-    
-    - fixes loading only the good records before the wrong record, thus
-      working with partial valid data afterwards, even more valid records
-      were in the db
-    
-    (cherry picked from commit 634db00a82f36c6c60d272ccada4a1d5338d1cbc)
+    Makefile.defs: version set to 4.1.0-pre0
 
-commit ad6320e754971b6f872967e225729b589b334ef4
-Author: Juha Heinanen <jh at tutpro.com>
-Date:   Sun Feb 22 01:10:12 2015 +0200
+commit 324e458ad68e97edaf2240e0f79b7380e77d268c
+Author: Richard Good <richard.good at smilecoms.com>
+Date:   Thu Oct 17 16:46:09 2013 +0200
 
-    modules/siptrace: small README clarification
-    
-    (cherry picked from commit 6a97c65c122400e46a4103b756c6973f7bea134e)
+    modules/ims_qos: second iteration of ims_qos module
+    	- module now support media authorization over Diameter Rx (between P-CSCF and PCRF)
 
-commit f3128e163d13eb78002e9aa0a7e4d1c30239c1d8
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Feb 20 20:40:39 2015 +0100
+commit d5c482ca06ff4b8529ea00d421484addd0203c37
+Author: Richard Good <richard.good at smilecoms.com>
+Date:   Thu Oct 17 16:44:46 2013 +0200
 
-    xhttp: use proper function to set the ip addres of the fake via
-    
-    - for ipv6 it has to be enclosed in between [ ]
-    - reported by Sergey Okhapkin
-    
-    (cherry picked from commit 5c1a9df4fc8bd72f44066bcef13f381f01cd9d07)
+    modules/tm: Edited documentation to show that t_suspend/continue can now be used on SIP responses
 
-commit 362cb1d7eaf359dd57937a43e2fca3df96031eef
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Feb 19 21:13:39 2015 +0100
+commit 16e763c32d7a2b9fc451185e028a90b3be758f65
+Author: Richard Good <richard.good at smilecoms.com>
+Date:   Thu Oct 17 16:41:15 2013 +0200
 
-    utils: cleanup CURL handle when the POST value can't be fetched from the PVAR
-    
-    - patch provided by mikomarrache on GH #88
-    
-    (cherry picked from commit b88e165214296d1d7491cf389295800b499a5d34)
+    modules/tm: extended tm async support to SIP responses
+    	-t_suspend and t_continue functions now work with SIP responses as well as requests
+
+commit 8b8132c17c126ff4edb2f5c9544dbd30894f6108
+Author: Richard Good <richard.good at smilecoms.com>
+Date:   Thu Oct 17 16:40:07 2013 +0200
 
-commit c44df47b7e461a51af43b75fa0122704063ff8dc
-Author: grumvalski <federico.cabiddu at gmail.com>
-Date:   Sun Mar 29 17:48:20 2015 +0200
+    parser: defined new FL_RPL_SUSPENDED used for suspend on reply
 
-    modules/tsilo: return from ts_store if transaction is not defined
-    
-    (cherry picked from commit e7dc20f48c674b0eca5419c93e05a430a5b20e71)
+commit cc8bc36c67a0b8e7317c06c50a88e8e6aa15d790
+Merge: 217e508 2f368b6
+Author: Carsten Bock <carsten at ng-voice.com>
+Date:   Wed Oct 16 14:12:51 2013 +0200
 
-commit 6614c8e78ac9cb5add92aff0db2d3a24dbc65423
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Mar 18 18:36:37 2015 +0100
+    ims_charging: Merge branch 'ims_charging' into master
 
-    sqlops: fix column index for sqlops_is_null()
-    
-    - report and patch by Mihaly Zachar
+commit 2f368b676acb026bf4647af02108a24e49e30581
+Author: Carlos Ruiz Diaz <carlos.ruizdiaz at gmail.com>
+Date:   Fri Oct 11 00:07:18 2013 -0300
+
+    ims_charging: fixed bug causing dialog cb function to be called more than once
     
-    (cherry picked from commit 768dc8b566e2af04411570ef7b4d55a210a1927d)
+    - removed possible race condition in dialog cb
+    - improved the way locking was performed
 
-commit df86f2a9a09339687af5914b85fe8bd8f8f1f575
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Mar 12 15:18:58 2015 +0100
+commit 217e5089df327215dd5078a72dd5b14526640191
+Author: Jason Penton <jason.penton at smilecoms.com>
+Date:   Thu Oct 10 16:04:49 2013 +0200
 
-    jsonrpc-s: reset response body after linking it to $jsonrpl() variable
+    modules/ims_charging: restored an unlock that will cause deadlock if omitted
 
-commit 87ca6e634c627a6beb4b7355fcfcbd0070e2afe1
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Mar 10 14:58:32 2015 +0100
+commit bae7fcb9be9a4cf88693e6c4180e3c1e6f4b6c1d
+Author: Jason Penton <jason.penton at smilecoms.com>
+Date:   Thu Oct 10 15:36:59 2013 +0200
 
-    ldap: fixed copy&paste error added in previous commit
-    
-    (cherry picked from commit c6ddf3aec7eb6e8d6046b006fde64ab7479aab5e)
+    modules/ims_charging: fixed bug not initialise AVP string value for success CCA
 
-commit b2aa72a6357dd93c75a345fd433c3b86c2654313
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Mar 10 14:52:08 2015 +0100
+commit 6ccca97cba61e75e9da0b6d36f1ee38fc88e94f3
+Merge: db618dd 83add48
+Author: Jason Penton <jason.penton at smilecoms.com>
+Date:   Thu Oct 10 15:01:07 2013 +0200
 
-    ldap: more useful info on reconnect
-    
-    - reconnect message made a notice level, being not an error situation
-    - print the chosen ldap server address at info level when reconnecting
-    
-    (cherry picked from commit c5ae4020de8499e7a318783b21276dfd3fc0a6e3)
+    Merge branch 'master' of ssh://git.sip-router.org/sip-router
 
-commit bb81ec09e22bb35944879a081eba47b1cfcc816b
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Mar 10 14:38:38 2015 +0100
+commit db618ddbdc2ec92a508acd913f2f847a4fb59cae
+Author: Jason Penton <jason.penton at smilecoms.com>
+Date:   Thu Oct 10 14:59:23 2013 +0200
 
-    sqlops: more verbose log message if execution of query fails
-    
-    (cherry picked from commit 941fbda5c66da6c8069b3bce3764249bbb58baaa)
+    modules/ims_charging: corrected default termination cause code to DIAMETER_LOGOUT
+    	- also corrected typo
+    	- added other termination cause code defines for future use
 
-commit 4ae4e5f381fba4cf43d8792e56d2baa4b2edcc6f
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Mar 10 13:54:11 2015 +0100
+commit 83add48b7c1cdf0d9f64c24bcc134195699daac1
+Author: Robert Boisvert <rdboisvert at gmail.com>
+Date:   Thu Oct 10 08:25:05 2013 -0400
 
-    db_cluster: fix checking the capabilities for write operation with different priorities
+    mohqueue: fixes
     
-    - reported by Jan Hazenberg
+    * cleaned up all error paths (fixed crashes)
+    * added support for INVITEs that get stuck
+    * adjusted code to avoid compiler warnings
+    * PRACK only invoked if Require: 100rel set
+    * fixed bug that allowed a new call to be created more than once
     
-    (cherry picked from commit 8375f37cd7603216a2bb55a4e9985b3c5e54af91)
+    Documentation
+    * updated NOTES
 
-commit 7e0e8ee8e0753590e00445094b12bcefcf24605d
-Author: Luis Azedo <luis at 2600hz.com>
-Date:   Tue Mar 10 08:22:05 2015 +0000
+commit ac5835c0aff657cae169432466851c9f2cbca8ad
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Thu Oct 10 12:45:45 2013 +0200
 
-    kazoo: consumer unallocated structure prevents kazoo from starting on busy systems
-    
-    when kamailio starts, publisher begins to process without checking memory allocation initialized by consumer
-    
-    allocate bind structure once at initialization
-    change the order of child process initialization
-    change targeted binding
+    cfgutils: init probability pointer to NULL
     
-    (cherry picked from commit 6e1b56cb6d640db820254b8c69f7fd6e20865465)
+    - otherwise it can be an attempt to free it when the kamailio does not
+      start due to config errors
+    - reported by Dragos Oancea
 
-commit 4e1a1007db5441849bc3c45a1b768e6a69b79c8f
-Author: Luis Azedo <luis at 2600hz.com>
-Date:   Mon Mar 9 12:47:31 2015 +0000
+commit a3bddf300ff82b9d811acb5dd6ec2e25f0eab07c
+Author: Jason Penton <jason.penton at smilecoms.com>
+Date:   Wed Oct 9 17:55:20 2013 +0200
 
-    kazoo: only create tags if not empty
-    
-    to-tag and from-tag are created empty if not supplied in amp payload
-    this patch formats the dialog message to include the tags only if they are supplied in amp payload
-    
-    (cherry picked from commit deb0e811cddd71c45ebb36db7b41faa8d9e9ca5e)
+    module/tm: changed log level from WARN to DBG for informational message
 
-commit 7140f86bc020ef60d2b35b79e9d051a415372036
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Mar 9 12:33:58 2015 +0100
+commit 2dc78738af4a0693e0a4d3f77e2174586d53d90b
+Author: Carlos Ruiz Diaz <carlos.ruizdiaz at gmail.com>
+Date:   Tue Oct 8 15:52:09 2013 -0300
 
-    textops: stop after substituting in first header if flag f is set for subst_hf()
-    
-    - reported by Julia Boudniatsky
-    
-    (cherry picked from commit 0f5aaac47a6002bbd4fdfaf0e6897d307c2cbc0e)
+    ims_charging: removed session unlock function call when no lock was acquired
 
-commit 80a7b7593a68dd2686a5c17f9f85f561bb694785
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sun Mar 1 21:16:46 2015 +0100
+commit dcce66b2a3db3aeaa5de1a87429320731ab3795c
+Merge: 121e828 639ce58
+Author: Carsten Bock <carsten at ng-voice.com>
+Date:   Tue Oct 8 18:43:14 2013 +0200
 
-    core: cleaned debug messages and added safety check for bind address
-    
-    (cherry picked from commit 2549f7a6361de36e0dde14de3d5c4c076564871c)
+    ims_charging: Merge branch 'ims_charging' into Master.
 
-commit af726efbe52bfa082d4b8060be01b0a69c732b0d
-Author: Luis Azedo <luis at 2600hz.com>
-Date:   Tue Feb 24 22:37:32 2015 +0000
+commit 121e828e2bedd3f76a1343f7257978153e78fc8f
+Author: Peter Dunkley <peter.dunkley at crocodilertc.net>
+Date:   Tue Oct 8 02:37:43 2013 +0100
 
-    kazoo - fix compilation
-    
-    (cherry picked from commit 12af51df76e779c70470c57ef0b992831441f275)
+    pkg/kamailio/centos: added mohqueue to CentOS build
 
-commit 9b44517c6e8efe9e6445940ee7f0c505abef613d
-Author: Luis Azedo <luis at 2600hz.com>
-Date:   Tue Feb 24 22:22:32 2015 +0000
+commit 03dbfd4c97290028212ddb04eea5faf5ef4ba007
+Author: Peter Dunkley <peter.dunkley at crocodilertc.net>
+Date:   Tue Oct 8 02:27:24 2013 +0100
 
-    kazoo - fix timer interval
-    
-    amqp timer and publish proc take all cpu
-    new param amqp_timmer_process_interval in MS
-    and removed the timeout on select from tcp workers
-    
-    (cherry picked from commit 7ae9f6693406c76d7d58389d5cf4ccaa44958a02)
+    modules/mohqueue: created text README file from doc source
 
-commit 856b9e7df04d41a5564a755ce60be5bd708c80cb
-Author: Luis Azedo <luis at 2600hz.com>
-Date:   Tue Feb 24 09:33:53 2015 +0000
+commit a39adb3497b5b095126e835104d637669dee2a7e
+Author: Carsten Bock <carsten at ng-voice.com>
+Date:   Mon Oct 7 16:17:53 2013 +0200
 
-    kazoo - fix crashing on heavy load
-    
-    (cherry picked from commit 0506b9898867c5d165defa0acf1501cad13513eb)
+    ims_charging: Add statistic ccr_timeouts
 
-commit e24c9ff7038534e07682e8a7bafd903e4303590e
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Feb 23 14:29:46 2015 +0100
+commit e4e84c80232a5acc60b64adb541b54b6967189f6
+Author: Timo Teräs <timo.teras at iki.fi>
+Date:   Mon Oct 7 17:09:59 2013 +0300
 
-    sdpops: safety check when location a= line not to exceed end of message
+    mohqueue: fix build error due to get_debug_level api change
     
-    (cherry picked from commit 91596953115fe1bbe5c6f0dd0dd6e8d99cdbd285)
+    Should have tested better before merging. Should probably remove the
+    whole debug print helper and use core functions directly now that
+    the core supports per-module debugging.
 
-commit 449ba0c0a3a1c79c597452c3411fd823465c9482
-Author: Luis Azedo <luis at 2600hz.com>
-Date:   Mon Feb 23 20:55:57 2015 +0000
+commit 62860094af838710ee5b9892cfb9f99f615055f6
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Mon Oct 7 10:01:56 2013 +0100
 
-    kazoo - fix timeouts
+    tm: Restore ruid value in sip_msg struct after creating transactions from branches
     
-    timeout should be ms not sec
-    set time before state so timeout check doesn't set timeout immediately
-    separate proc for handling timeouts
-    
-    (cherry picked from commit b9e5b9181c0f9c315e0f27ad96f69d5ca8cafba3)
+    - Fixes crash when freeing memory
 
-commit 9524b3471802c09361fd290cf35b2d5096ac0767
-Author: lazedo <luis.azedo at factorlusitano.com>
-Date:   Wed Feb 18 23:01:57 2015 +0000
+commit a4370dc336e5552b93d32314249d4d613d77ef99
+Author: Jason Penton <jason.penton at smilecoms.com>
+Date:   Mon Oct 7 12:49:00 2013 +0200
 
-    db_text : missing OP_NEQ
-    
-    this affects the presence package when it queries for active_watchers
-    (cherry picked from commit 5adbfc6cc62be393ac55d296cab79f7e60b17ae4)
+    modules/tm: missing lock initialisation for async_lock
+    	- related to commit 5ab44c7c2fc78038302bf455ff49e374fc79550b
 
-commit df4df4fbe8c742d960b0fdecd5a1e9967a96b58b
-Author: lazedo <luis.azedo at factorlusitano.com>
-Date:   Mon Feb 16 13:14:06 2015 +0000
+commit ca060f98bbecb407d5d29cbe19cec821d3990330
+Merge: 6e19deb 24f66ec
+Author: Timo Teräs <timo.teras at iki.fi>
+Date:   Mon Oct 7 11:18:02 2013 +0300
 
-    usrloc - fix column types not initialized on update
-    
-    some columns were not initialized on update leading to errors in update
-    
-    ERROR: db_text [dbt_lib.c:464]: dbt_is_neq_type(): invalid datatype -1001432832
-    ERROR: db_text [dbt_base.c:560]: dbt_update(): incompatible types!
-    ERROR: db_text [dbt_base.c:599]: dbt_update(): failed to update the table!
-    (cherry picked from commit cf521e66825fea4b7498d615d435739628fe4c09)
+    Merge branch 'tteras/mohqueue'
 
-commit 458e8ba0ff7a7453050734c47f71a7b9bcaa03a6
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Feb 11 13:05:41 2015 +0100
+commit 6e19debdf9b240c71ca90bfd6cadd46f0f57ace8
+Author: Carsten Bock <carsten at ng-voice.com>
+Date:   Mon Oct 7 10:15:11 2013 +0200
 
-    sqlops: regenereated the readme file
-    
-    (cherry picked from commit 61d6b119398a87c4a877de3fba0dc9c6ec2830a7)
+    examples/pcscf: Removed dependency to Presence-User-Agent and SQLite.
 
-commit 2ee8e8d0a0808fde86941712bc7fbebcac103dcc
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Feb 11 12:50:43 2015 +0100
+commit c9395e690435cdb8fc62b7fb13b378fe0a6ca8e5
+Author: Charles Chance <charles.chance at sipcentric.com>
+Date:   Mon Oct 7 07:52:21 2013 +0100
 
-    sqlops: added note to sql_async_query() about core async_workers
-    
-    - the parameter must be set to enable the async framework used by this
-      function
-    
-    (cherry picked from commit 112e83c2e8b72be04f7ad5b896db0bf3bcbdbe8f)
+    htable: update documentation for dmq integration
 
-commit 6580596a53e26df9653d4ee13dd43144f912b51f
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Feb 11 12:37:22 2015 +0100
+commit 6a20bf80ae014801667c5a23782b33af5467c409
+Author: Charles Chance <charles.chance at sipcentric.com>
+Date:   Mon Oct 7 07:44:38 2013 +0100
 
-    db_mongodb: regenerated README file
-    
-    (cherry picked from commit 7ae56a331209adeff7c5da86e1ebd8321d586a35)
+    htable: initial dmq integration
 
-commit 921ed59eb8f766a9dc9c87138c3b6ba04d4c1bfa
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Feb 11 12:19:45 2015 +0100
+commit 24f66ecc72064c9bf40deeb324e666b6b95dfa83
+Author: Timo Teräs <timo.teras at iki.fi>
+Date:   Mon Oct 7 08:41:37 2013 +0300
 
-    db_mongodb: updated details in docs about the limitations
-    
-    (cherry picked from commit 6940ce0e991fd5b6af9ef5822dc2b1a324319174)
+    mohqueue: remove handwritten .sql, it is now autogenerated
 
-commit 1c77a5acada0cdf66e05b754ae232e8efa624be2
-Author: mikomarrache <mikomarrache at users.noreply.github.com>
-Date:   Wed Feb 11 11:47:17 2015 +0100
+commit 1af34ca5b9f799b83242a9ecddf8abe9521114dd
+Author: Robert Boisvert <rdboisvert at gmail.com>
+Date:   Thu Oct 3 11:36:08 2013 -0400
 
-    db_mongo_db: use mongoc_collection_update() for update operation
-    
-    - used instead of mongoc_collection_find_and_modify(), which returns the
-      document, but it is not needed
-    
-    (cherry picked from commit e31e4632f83e805775bbc1e208178bee11ab137b)
+    mohqueue schema files
 
-commit 1ad7c7d0a3a534ed1d388391d16fb2c715a24419
-Author: mikomarrache <mikomarrache at users.noreply.github.com>
-Date:   Wed Feb 11 11:42:14 2015 +0100
+commit f8f3d34ba5471742676831b22b1c872823a31cba
+Author: Andrew Mortensen <admorten at isc.upenn.edu>
+Date:   Sat Oct 5 13:14:09 2013 -0400
 
-    db_mongodb: use $set operator to update a specific list of fields in a document
-    
-    - fix to keep all the other fields unchanged
+    modules/sca: fix compiler warning for macro.
     
-    (cherry picked from commit 2a045585efc9a8e5b17123d320539d0c8cb6be77)
+    - correct "always evaluates to true" when using address of stack variable.
 
-commit 9b0ed6d54e47880818f934a8988c89d340739564
-Author: mikomarrache <mikomarrache at users.noreply.github.com>
-Date:   Wed Feb 11 11:37:26 2015 +0100
+commit 2f0043b153c60380e35c8ec4c33a9bbc7fb2b05c
+Author: Andrew Mortensen <admorten at isc.upenn.edu>
+Date:   Thu Sep 19 13:49:24 2013 -0400
 
-    dialog: fix initialization of slot next_id to avoid colision after restart
-    
-    - next_id was set to the highest id of a dialog loaded from database,
-      next new dialog was reusing the same value
+    modules/sca: fix return value of sca_call_info_uri_update()
     
-    (cherry picked from commit e122c5ee8c6055c033cc11f14e5308ed94461fe6)
+    - return value of 0 can bubble up as return value of sca_call_info_update(),
+      causing early script termination (exported function returning 0 in script
+      is equivalent to "exit")
+    - report and patch from Timo Teräs
 
+commit 2efe3e365e1670cc3ac8b4900a1104c3720d44fb
+Author: Andrew Mortensen <admorten at isc.upenn.edu>
+Date:   Tue Aug 20 15:54:17 2013 -0400
 
-===================== 2015-02-10 Version 4.2.3 Released =====================
+    modules/sca: AoR should not be treated as SCA if there are no subscribers.
 
-===================== Changes Since Version 4.2.2 ===========================
+commit 58a47ac21d09bf6feb1431bbe490643e9827c876
+Author: Andrew Mortensen <admorten at isc.upenn.edu>
+Date:   Tue Aug 20 15:14:26 2013 -0400
 
-commit cf4ade36b6c138da8c76f7bbd7395f63bd38508d
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Feb 10 15:08:43 2015 +0100
+    modules/sca: improved handling of host-only Contact URIs
 
-    Makefile.defs: version set to 4.2.3
+commit 3b1f87523bdc53538c1b6f409ba9470048572701
+Author: Andrew Mortensen <admorten at isc.upenn.edu>
+Date:   Mon Jul 22 00:48:46 2013 -0400
 
-commit ccc46dfcba8e64899c2a77d95fc078158443126d
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Feb 10 15:07:53 2015 +0100
+    modules/sca: restore missing prototype.
+    
+    sca_subscription_aor_has_subscribers
 
-    pkg/rpm: set version 4.2.3 in spec files
+commit 97653df1d93636771c7b2fa8e4f9aef002ee7e5b
+Author: Andrew Mortensen <admorten at isc.upenn.edu>
+Date:   Mon Jul 22 00:42:18 2013 -0400
 
-commit 2ad63ac4b6f2395facf28b88046bd326348ae384
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Feb 10 15:05:44 2015 +0100
-
-    pkg/deb: version set to 4.2.3 in spec files
-
-commit c2b03863299b490346735e8b2501098117a42310
-Author: Mikko Lehto <mslehto at iki.fi>
-Date:   Tue Feb 10 09:57:31 2015 +0100
-
-    sctp: fixes for FreeBSD 10.1 compile error and 2 warnings
+    modules/sca: detect when an AoR is no longer SCA.
     
-    - missing argument for macro SCTP_EV_REMOTE_ERROR() and two extraneous
-      parentheses
-    
-    (cherry picked from commit b06626e811edae93c5f28dc132eca7542a6dcc97)
+    Don't, for example, create an appearance for callees that do not send
+    a Call-Info header, and whose AoR also has no subscribers.
 
-commit f5b42be4a36d035332a796dde62e4f91e709f3c3
-Author: Jon Auer <jauer at corp.netwurx.net>
-Date:   Thu Feb 5 23:34:59 2015 +0000
+commit a6f80374c4dd3d09fa7e25a8e6c59dab0bf2fae5
+Author: Andrew Mortensen <admorten at isc.upenn.edu>
+Date:   Mon Jul 22 00:37:32 2013 -0400
 
-    fix compile errors in srutils/sha256 on SunOS (SmartOS)
+    modules/sca: Clear stale line-seize appearances via timer.
     
-    (cherry picked from commit fdb4c7758f0d6d6ebed8cf9d01a412ed024efb8b)
+    Some badly behaved/buggy UAs don't know when to say when.
 
-commit d8b487c9253ed68098fa4a75ab963fdfffbc3b1c
-Author: Luis Azedo <luis at 2600hz.com>
-Date:   Fri Feb 6 17:29:25 2015 +0000
+commit 84d1981ce059fcdd7a5113428b0227fbb0b977ab
+Author: Andrew Mortensen <admorten at isc.upenn.edu>
+Date:   Thu Jun 13 16:06:10 2013 -0400
 
-    kazoo : revert uuid include
-    
-    (cherry picked from commit ad76e342a8235e4a752593dd5fab5b676a89425a)
+    modules/sca: fix regression: restore purge expired timer
 
-commit 6edcfda108524397302ca2d00c804ac21cd4a01e
-Author: Luis Azedo <luis at 2600hz.com>
-Date:   Fri Feb 6 16:08:54 2015 +0000
+commit c0fb2a67a699e30fd3274c9f864918e6e02e1926
+Author: Andrew Mortensen <admorten at isc.upenn.edu>
+Date:   Thu Jun 13 15:34:00 2013 -0400
 
-    kazoo : fix memset size error  & includes
-    
-    kz_trans was calling memset with wrong size of structure
-    kx_amqp was including uuid.h from uuid directory
+    modules/sca: clear appearance on receipt of out-of-dialog SUBSCRIBE
     
-    (cherry picked from commit 5113c047d353724d1a6f5a204e5a895ff1dd519a)
+    - If a call-info SUBSCRIBE with no To-tag arrives from a subscriber
+      with an active subscription, release any appearances owned by the
+      subscriber, on the assumption that the subscriber has lost track
+      of SCA (reboot, power/network loss).
 
-commit 5e07d01aaae15d3441876d8ee154a53484d08682
-Author: Charles Chance <charles.chance at sipcentric.com>
-Date:   Fri Feb 6 10:59:35 2015 +0000
+commit ef9b12d213416f910e0c11bdeecf9112032939f8
+Author: Andrew Mortensen <admorten at isc.upenn.edu>
+Date:   Thu Jun 13 15:30:40 2013 -0400
 
-    dmq: add branches when replicating to multiple nodes
+    modules/sca: detect and clear orphaned appearances caused by answer glare
     
-    - reported by Leonardo Arena
-    
-    (cherry picked from commit ff114281fc2f523ed7bf87ea31448ce7327fdf93)
+    - set appearance state created by SCA callee answer to ACTIVE_PENDING,
+      and promote to ACTIVE on ACK from caller. If no ACK from caller is
+      received within 30 seconds (enough time for retransmission to fail),
+      the ACTIVE_PENDING appearance will be cleared by the
+      sca_appearance_purge_stale timer.
 
-commit f30a61f339f947783210053469d262e61ce58638
-Author: lazedo <luis.azedo at factorlusitano.com>
-Date:   Thu Feb 5 22:34:32 2015 +0000
+commit 1ef4587612806a94c7a81aac4f768b9bbe472b43
+Author: Andrew Mortensen <admorten at isc.upenn.edu>
+Date:   Wed May 15 16:13:23 2013 -0400
 
-    kazoo : less agressive log
+    modules/sca: reconcile Contact and From URIs in ACK callback.
     
-    changed log from INFO to DEBUG when timeout is set
-    (cherry picked from commit f9c248a66fdca5317e8820e53f1a0f99cd58ef8a)
+    - fix Music-on-Hold in Polycoms when SCA caller has MoH enabled and SCA callee
+      does SCA hold/pickup with identical To & From URIs. Previously, module would
+      end up looking up an appearance for callee in ACK callback instead of caller.
 
-commit 090afb32c19b8e76fcbcb6deaaa2f4fe42e0f38f
-Author: Luis Azedo <luis at 2600hz.com>
-Date:   Thu Feb 5 19:35:37 2015 +0000
+commit 185bd40d1a197709d28d9b966ed8fd4b4c00faf9
+Author: Andrew Mortensen <admorten at isc.upenn.edu>
+Date:   Tue May 14 16:25:06 2013 -0400
 
-    kazoo : timeout fixes & improvements
-    
-    1) fixes names in parameters (timout corrected to timeout)
+    modules/sca: improved BYE handling.
     
-    2) kazoo_query was always using the same timeout value which could be a problem, since there are different kinds of request and some may be given more time to process.
-    solved by adding amqp_query_timeout_avp parameter to allow usage of different timeouts.
-    
-    (cherry picked from commit 0c3925e6f787c6e8d2e1bc7a45fec0c99ba203d8)
+    - Clear appearances for both legs on BYE request if possible.
 
-commit a90e73327cccb5259af08cbf93f2a1b793a0ca2e
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Feb 5 11:26:34 2015 +0100
+commit 36ad80745607fca859578b8423cbd767f4c5b095
+Author: Andrew Mortensen <admorten at isc.upenn.edu>
+Date:   Tue May 14 16:23:46 2013 -0400
 
-    core: safety check for append_branch() when called with no uri and no msg
-    
-    - uri or msg parameter must be given, otherwise the new address cannot
-      be set
-    - get_redirects() from uac_redirect can execute this function with both
-      parameters invalid in case of invalid contact, reported by Javi
-      Gallart
-    
-    (cherry picked from commit 2c4ed5922a2322f3b5059f6264884acfb5dec97f)
+    modules/sca: free previous appearance owner, callee, dialog if non-NULL.
 
-commit f1f9c545c617c6756659c550881dcf73e123b292
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Feb 4 18:30:05 2015 +0100
+commit bb21b5e0bc7aaf001799e259b81aebe28168afb1
+Author: Andrew Mortensen <admorten at isc.upenn.edu>
+Date:   Thu May 2 15:12:16 2013 -0400
 
-    core: removed log message used for troubleshooting
+    modules/sca: change logging level for failed lookup by appearance-index.
     
-    (cherry picked from commit c22dfcd6359079f9ea3600bfeb31fe5edbf4f8b1)
+    - appearance-index won't be found yet if SCA callee is answering, logging
+      at WARN is misleading.
 
-commit 144a99f9695a132d4bc4d789dcf0a2a18a470447
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Feb 3 18:48:42 2015 +0100
+commit 98b8ba06dfaec49331dbfc3164e02a490e0db214
+Author: Andrew Mortensen <admorten at isc.upenn.edu>
+Date:   Tue Apr 30 23:31:12 2013 -0400
 
-    db_mongodb: build proper complex filters for db operations
-    
-    - handle ==, != (<>), >, <, <=, >=
-    - bitwise AND (&) not supported
-    
-    (cherry picked from commit f3ae358e937f4df6f0ee28e8d5df16f4245ae4b8)
+    modules/sca: space-separate dialog tags in sca.all_appearances output
 
-commit aa87917aa27bcc9f3f71da4cead1b51d17e75da7
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Jan 30 08:15:58 2015 +0100
+commit 002dc46fee94edf8b7086d7d3bb0286979213532
+Author: Andrew Mortensen <admorten at isc.upenn.edu>
+Date:   Tue Apr 30 23:10:10 2013 -0400
 
-    sl: re-attempt to bind to tm after all mods init
-    
-    - handle the situation when tm is initialized after the sl module
-    - re-binding is done on child callback with rank PROC_INIT
+    modules/sca: track appearance times.
     
-    (cherry picked from commit 85d3488c3910d447f6900df166bc6b0c16a64e9c)
+    Include time of last state chance in sca.all_appearances output.
 
-commit 29e6386a140ccc4025e2ff98ad8a3b0d5da1b6c3
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Jan 29 21:46:43 2015 +0100
+commit ac298442533c048e5ccacf6b3ad0cb36d52c2eff
+Author: Andrew Mortensen <admorten at isc.upenn.edu>
+Date:   Wed Apr 24 11:30:35 2013 -0400
 
-    lib/srdb1: init columns array to 0
-    
-    - allows proper cleanup if there is an error while filling the items
-    
-    (cherry picked from commit e59db798b84f1641f807d216c2ca460cfedb31e7)
+    modules/sca: add sca.subscription_count to rpc exports list.
 
-commit da06d9a4912f71b3e9f7af3d29a1543a4884efa9
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Jan 29 10:45:52 2015 +0100
+commit 815d70e5156c2a878e59c59182ffa957f1d75a80
+Author: Andrew Mortensen <admorten at isc.upenn.edu>
+Date:   Wed Apr 24 01:18:27 2013 -0400
 
-    sca: more error handling during initialization of the module
+    modules/sca: RPC: fix sca.show_subscription, add sca.subscription_count
     
-    - fix crash when the module doesn't initialize and calls destroy
-      function during shutdonw at startup
-    - reported by Olle E. Johansson, GH#57
-    
-    (cherry picked from commit df2a45541c5e37907374c5e7595de1f30ea84f98)
+    - sca.subscription_count will eventually be subsumed by sca.stats.
 
-commit c39e896e144c33a9f7f10a99029b9a63aff85530
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Jan 29 10:37:13 2015 +0100
+commit 2e0af20cd7a5b3e46ceb36ef3919df78c1bdf1df
+Author: Andrew Mortensen <admorten at isc.upenn.edu>
+Date:   Thu Apr 18 13:52:10 2013 -0400
 
-    dialog: proper handling cseq increment when cseq header is before via
-    
-    - reported by Fernando Aquilino
+    modules/sca: fall back to tag lookup if lookup by index fails.
     
-    (cherry picked from commit 8c3a12f6aca7c6492ee440da469834997ea89eee)
+    - Fix appearance tracking for SCA implementations with inconsistent
+      Call-Info header inclusion.
 
-commit 0d47a5cfc723be2b8ef2baeb439d5df05b5c580c
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Jan 28 22:09:21 2015 +0100
+commit a6f038343de57ca6bd257e442af41feae2b18c4d
+Author: Andrew Mortensen <admorten at isc.upenn.edu>
+Date:   Mon Apr 15 20:16:36 2013 -0400
 
-    sca: initialize sca variable to catch destroy on shutdown at startup
-    
-    - reported by GH#35
-    
-    (cherry picked from commit 010977f5febcf923a31d545bd631fbee11dd426c)
+    modules/sca: add SCA_DB_DEFAULT_FETCH_ROW_COUNT
 
-commit 23e8ab71c7c6a3baf8858e02391e67f2e8c30c97
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Jan 28 22:02:02 2015 +0100
+commit 562e49dc6e6fb9adb47adecbda8bfb94f12d86aa
+Author: Andrew Mortensen <admorten at isc.upenn.edu>
+Date:   Mon Apr 15 20:11:08 2013 -0400
 
-    userblacklist: init variables for safer destroy at startup
+    modules/sca: use DB fetch queries when restoring subscribers from database.
     
-    - reported by GH#42
-    
-    (cherry picked from commit c28551cd245f5e8ab9fc5d5c29f657cc06ad81e2)
+    - Previously used standard query, exhausting pkg memory when subscriber
+      count is high.
 
-commit 008b03ae8361ca06da9042b479c10e760391da72
-Author: Alex Balashov <abalashov at evaristesys.com>
-Date:   Sun Jan 18 17:08:18 2015 -0500
+commit 92114b530e6a206af1fe173a948cb542a62717c2
+Author: Andrew Mortensen <admorten at isc.upenn.edu>
+Date:   Mon Apr 15 20:09:01 2013 -0400
 
-    evapi: Listening socket will be bound with SO_REUSEADDR option so that rebinding does not have to wait for TIME_WAIT connections to clear.
-    
-    (cherry picked from commit cd1a59f223e2806ca4c16ab4a8dc1e0ff2b219d1)
+    modules/sca: only check if callee is SCA if callee_aor has a value.
 
-commit e2db60867748eac2e6585ef9d865b12c1e8ddfe2
-Author: Olle E. Johansson <oej at edvina.net>
-Date:   Sat Jan 17 18:43:42 2015 +0100
+commit 1e9708462f0e709e795813490d56897d0f44997c
+Author: Andrew Mortensen <admorten at isc.upenn.edu>
+Date:   Mon Apr 15 17:17:05 2013 -0400
 
-    sipcapture Add some missing \n in log messages
+    modules/sca: add check for empty AoR in lock_shared_appearance calls.
     
-    (cherry picked from commit 5bafc03222bf6fcc59dbcf8aec30def9cdb24581)
+    - Sanity checking
 
-commit a244189eeb454e7c1de85022002d69bf38482f43
-Author: Alexandr Dubovikov <alexandr.dubovikov at gmail.com>
-Date:   Sat Jan 17 20:34:35 2015 +0100
+commit 6cdc9c4f3e915fbad5da1112b9e0553726e877f2
+Author: Andrew Mortensen <admorten at isc.upenn.edu>
+Date:   Thu Apr 11 22:34:10 2013 -0400
 
-    added bool to print error once
-    (cherry picked from commit c8363905755e5d120251eed95c5fa1be45e8f216)
+    modules/sca: clear appearance on t_reply with error after receiving 18x.
+    
+    - Receiving a 18x provisional reply triggers line-seize subscription
+      termination. Releasing the seized appearance while processing a t_reply
+      with an error status *after* getting a 18x would fail because
+      sca_subscription_terminate could not find a matching line-seize
+      subscription. In that case, look up appearance by tags and release it.
 
-commit f28c1afd0815d3f31b1ce19c3252a14f11da27fb
-Author: Juha Heinanen <jh at tutpro.com>
-Date:   Sat Jan 31 04:21:34 2015 +0200
+commit 28978be4d825e08a455387209af6dda4aa4bdfde
+Author: Charles Chance <charles.chance at sipcentric.com>
+Date:   Fri Oct 4 18:40:42 2013 +0100
 
-    db_mysql: restore group ending character in db url
-    
-    - manual cherry-pick from master (git git cherry-pick -x
-      1d3b89b10bfd825e4ca73bb95b0ae489843dd9f1 failed)
+    dmq: fix memory leak in dmq_send_message()
 
-commit e8a306188cf50efb7b4a352d65494b4c736c9584
-Author: lazedo <luis.azedo at factorlusitano.com>
-Date:   Wed Jan 28 17:31:06 2015 +0000
+commit cf4275d4cb16dce4cbac48ca946a66e9f1626c35
+Author: Charles Chance <charles.chance at sipcentric.com>
+Date:   Fri Oct 4 14:57:39 2013 +0100
 
-    presence_dialoginfo : optionally send dummy dialog
-    (cherry picked from commit 5c9b3afca092dfda33c96dbf5195b8f7bbc2d4cf)
+    memcached: fix memory leak, discovered on a report by Dragos Oancea
 
-commit 25ec407671a88d6a993239958642dff114ca70d8
-Author: lazedo <luis.azedo at factorlusitano.com>
-Date:   Wed Jan 28 18:26:37 2015 +0100
+commit 0f3a566dd699090cf6a558edc3aefac2c41e24e5
+Author: Henning Westerholt <hw at kamailio.org>
+Date:   Fri Oct 4 14:47:06 2013 +0200
 
-    presence: do aux_body_processing() if exists after get_p_notify_body()
-    
-    - fix for send_notify_request()
-    
-    (cherry picked from commit cfef15ef1ca52abf4d6df129a5768baa0aaf5a07)
+    memcached: comment clarification for wrapper for libmemcache callbacks
 
-commit 387b3afc5a5c2082688cd898ecbf6457bc0715c4
-Author: Klaus Darilion <klaus.mailinglists at pernau.at>
-Date:   Thu Jan 22 09:24:52 2015 +0000
+commit 0978c77d694cecd1b7813775a498f6495ae844dc
+Author: Henning Westerholt <hw at kamailio.org>
+Date:   Fri Oct 4 14:22:39 2013 +0200
 
-    kamctl: fix variable assignment
-    
-    There must not be a space before and after the = assignment operator.
-    
-    (cherry picked from commit 513a6d8bf8d270b0a4fa9743daab5263c9688447)
+    avpops: add a note to the docs that avp_db_query is deprecated and sqlops is better
 
-commit eeae005fb3d5239dd6e3af727504fc829ea5a0fb
+commit 673243a06200b8961756ebe3957bf9bd9059c2bb
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sun Jan 25 11:00:28 2015 +0100
+Date:   Fri Oct 4 13:11:23 2013 +0200
 
-    db_postgress: disable initialization of libssl if tls is loaded
-    
-    - based on the note from docs to avoid double attempt to init the ssl
-      library
-    - http://www.postgresql.org/docs/9.4/static/libpq-ssl.html
-    
-    (cherry picked from commit f04dec82e90ec7a3e6aea4ea8e9ed23b06b165c6)
-    
-    Conflicts:
-    	modules/db_postgres/km_pg_con.c
+    nathelper: updated docs with udpping_from_path
 
-commit e6eca3e988226e3654c5c22d762048a5fff3491c
+commit 565ba8d4b71ae5a43027c51e3caf06f20a10b14d
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sun Jan 25 10:59:07 2015 +0100
+Date:   Fri Oct 4 13:07:44 2013 +0200
 
-    tls: implemented tls hook for pre-mod init execution
-    
-    - do openssl init at this callback
+    nathelper: new mod param - udpping_from_path
     
-    (cherry picked from commit f71243410d5e051def1a47cc73adb6caeeadd1cd)
+    - enable sending UDP pings with raw sockets from Path address
+    - patch by Marcus Hunger
 
-commit 93804b66c5301af75cd6930f9c6653228cce8719
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sun Jan 25 10:57:00 2015 +0100
+commit 9bb88b5b22901b258fdbcd874264b823a8443869
+Author: Juha Heinanen <jh at tutpro.com>
+Date:   Fri Oct 4 14:04:22 2013 +0300
 
-    core: tls hooks can execute a callback before modules init function is executed
-    
-    - useful to prepare tls environment before a module might access it
-    - executed after modparam but before mod_init
-    
-    (cherry picked from commit 4700831fa0f2dc52e296ce647711b03d1406497a)
+    dialplan: improved debug messages so that used dpid is shown
 
-commit e5885f2f4bb6066af8988942beff217cb282a29b
+commit 88e2da3c54a1cef967d96a5753b1f7f014ba689e
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat Jan 24 22:37:43 2015 +0100
+Date:   Fri Oct 4 12:14:25 2013 +0200
 
-    tls: updated the default tls session id string
+    acc: time_format parameter documentation
     
-    (cherry picked from commit e47018b0a65a5e26ea47d789f0bc6d471aa3a117)
+    - eclosed exaples in dotted lines like in most modules to highlight them
+      on text output
 
-commit 6a9887370e1de87afc7f0da79b09eb62b350469f
+commit df4fbc220efd333fa638831167dd4fe5e69a89a2
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Jan 23 12:50:49 2015 +0100
+Date:   Fri Oct 4 12:02:32 2013 +0200
 
-    path: received parameter enclosed in square brackets if ipv6
+    acc: new parameter acc_time_format
     
-    - received should be useless for ipv4, but still can be enforced from
-      config, so has to be well formatted because it is followed by a port
-    - reported by Sebastian Damm
-    
-    (cherry picked from commit 077b26385854feb701950d020e382c254b803e75)
+    - specify the format to print time as string for acc_time_mode=3 (using
+      localtime) and acc_time_mode=4 (using gmtime)
+    - default value is "%Y-%m-%d %H:%M:%S"
 
-commit 83b3c2425a0e886677954936a60111224edc740b
+commit fed0a07d86c9e4d365cb7a5e25d4aaacb4b9adf2
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Jan 23 12:28:42 2015 +0100
+Date:   Thu Oct 3 10:00:22 2013 +0200
 
-    jsonrpc-c: explicitely listed glibc as dependency
-    
-    (cherry picked from commit 11f300f2c7c8ffe4a6b49b471ffcd116ee218985)
+    dialog: fixed typos in log messages
 
-commit 0421282a10446dd67236b6d4c7d103ee45301c28
+commit f12aa1b3c16b475029f0a3474b30f3b17ea18056
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Jan 23 11:07:26 2015 +0100
+Date:   Thu Oct 3 09:58:04 2013 +0200
 
-    permissions: init global pointer variables to null for safe shutdown at start
+    dialog: decode alias parameter from contact address and use it as dst uri
     
-    - reported by Olle E. Johansson, GH#41
-    
-    (cherry picked from commit 165a3fc2e4dfed09bd9f46e43270d49cf5f72a87)
+    - makes dialog module to work with set_contact_alias() as first hop
+      after a nat router
 
-commit 688593f15e2a67dfaf00d3b371633b3f93e3d584
+commit a41cb60d5171566e13f18b45f50d173f38d206c0
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Jan 23 10:55:15 2015 +0100
+Date:   Thu Oct 3 09:37:54 2013 +0200
 
-    pike: check that timer var is initialized before accessing the fields
-    
-    - safe start with empty config, reported by Olle E. Johansson, GH#39
-    
-    (cherry picked from commit c87a75c5fb7aa5d940093fbbca8d9557cc9a0239)
+    nathelper: documentation for set_contact_alias()
 
-commit 767a91caac78f8f40ce140be0c313002c9aad0b5
+commit 58659b0cabb623c6420c186755c968b4550ff09c
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Jan 23 10:47:45 2015 +0100
+Date:   Thu Oct 3 09:16:38 2013 +0200
 
-    jsonrpc-c: added note that it depends on Linux specific API
-    
-    - reported by Olle E. Johansson, GH#33
+    nathelper: set_contact_alias() new function for adding alias parameter to contact uri
     
-    (cherry picked from commit 33570d9f575e3b0566ac5f0b9904940420be9ae2)
+    - similar to add_contact_alias(), but this works like
+      fix_nated_contact(), in the way that new contact uri is immediately
+      visible to other modules (e.g., dialog, presence)
 
-commit 332d8fa0aace2c331f464042084e421acaee8a80
+commit 217f9fddbca31e06075132dd75a645d612d7af93
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Jan 23 09:50:17 2015 +0100
+Date:   Thu Oct 3 09:13:39 2013 +0200
 
-    acc: removed note in the docs about no-db support for cdrs
-    
-    (cherry picked from commit 75db07b5d7794b0f67d5798917d1833a21382bb7)
+    core: helper functions to add or restore alias parameter to an uri
 
-commit ac3498deab72dd833af24e9974ad251960e8d6fa
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Jan 22 22:35:36 2015 +0100
+commit 639ce584258f2c2ad4331bbd9ae2599a86edc80b
+Author: Carlos Ruiz Diaz <carlos.ruizdiaz at gmail.com>
+Date:   Thu Oct 3 11:56:13 2013 -0400
 
-    nathelper: enclode IPv6 in square branckets for fix_nated_contact()
-    
-    - even there is no nat in ipv6
+    ims_charging: read diameter AVP MAC value dynamically from $avp
     
-    (cherry picked from commit 814c08f36f13ace21e52181da3039402f951b0a8)
+    - $avp(ro_mac_value) can be either present or not. In case it is not, default value is used
+    - $avp(cca_result_code) now supports interpolation
 
-commit 8e40cee0473dab5e7796c6479f46f5994280b76a
-Author: Martin Mikkelsen <martin.mikkelsen at zisson.no>
-Date:   Wed Jan 21 16:55:15 2015 +0100
+commit 753e93d3ad1658c104963c208c4e36b23c1dd307
+Author: Robert Boisvert <rdboisvert at gmail.com>
+Date:   Thu Oct 3 09:22:54 2013 +0300
 
-    auth: use correct parameter for pv_auth_check checks
+    modules/mohqueue: pull changes from upstream
     
-    The pv_auth_check has a flags and a checks parameter but the flags
-    parameter is used for both. This means that if flags has the 1-bit set
-    it will enable both HA1-passwords and from/to URI checks and setting the
-    1-bit in the checks parameter does not do anything.
+    Merges up to upstream commit a3f679430d853d5b1b71ba92d8547ca2c86509ec.
     
-    This fixes the parameters so that the checks parameter is used for the
-    to/from URI checks.
+    Changes in code:
+    * fixes RTP stop not being sent
+    * use pcbp->req instead of -> in rtp_destroy
+    * fixed uninitialized varbs
+    * use close_call () for no response on INVITE
+    * changed to return handled if reINVITE sent
+    * switched to using fixup_svpe functions
     
-    (cherry picked from commit 2cdda10aa232e545ba79ca71876f0160a68e324b)
+    Documentation:
+    * added comment about rtpproxy limit
+    * adjusted to remove hold sequence in transfer out
 
-commit 3271a8f4fad18f525165b7c08037355679b01767
-Author: Olle E. Johansson <oej at edvina.net>
-Date:   Mon Jan 12 14:56:48 2015 +0100
+commit 9978906d39071908234f0236ea8693844a3c5ba1
+Author: Charles Chance <charles.chance at sipcentric.com>
+Date:   Thu Oct 3 05:59:09 2013 +0100
 
-    async: Clarify difference between modparam("async","workers",x) and async_workers in core config
-    
-    (cherry picked from commit 06557a25af96d3de05d0302f202e6c4cbd0b84e9)
+    dmq: regenerated readme
 
-commit 7ce10a5c6df8a8ee679dabb42cc719bbbb4fa381
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sun Jan 11 16:51:36 2015 +0100
+commit 3f6445f4620e3866dc859b9cfb6710e28bd407e5
+Author: Charles Chance <charles.chance at sipcentric.com>
+Date:   Thu Oct 3 05:54:01 2013 +0100
 
-    core: removed unused code
-    
-    - removes also some clang compile warnings
-    
-    (cherry picked from commit c8eeed253763d4407268494f89050b7681518091)
+    dmq: add content-type header
 
-commit 4fa400f262d2426a8a714ec65c5c88ec8e67f733
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat Jan 24 18:33:45 2015 +0100
+commit 127bf3d5be959a1287ae0fac91cf89e27ed01f42
+Author: Peter Dunkley <peter.dunkley at crocodilertc.net>
+Date:   Wed Oct 2 22:14:15 2013 +0100
 
-    dialog: use proper flags for script callback that clean dlg shortcuts
-    
-    (cherry picked from commit b0679c91f22a9eb9b995175b1d1abfb836a5a3f6)
+    pkg/kamailio/centos: put core files in /tmp on CentOS
 
-commit cd0e341cba059f43ac204a5d13e4baee9c5948f1
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat Jan 24 11:21:04 2015 +0100
+commit b2c5c598a38c770c2c4a7aef7c8267ad43fc6cd7
+Author: Juha Heinanen <jh at tutpro.com>
+Date:   Wed Oct 2 20:39:22 2013 +0300
 
-    dialog: removed end of line in middle of log message
-    
-    (cherry picked from commit 3b89c83bceb70da6fcbc9495dbcfec04e3f65ba4)
+    modules/db_mysql: use autocommit var to start and stop transactions
 
-commit 96c44ab31df9cc1a4400ad16515191332ef767fc
-Author: Luis Azedo <luis at 2600hz.com>
-Date:   Fri Jan 23 23:52:57 2015 +0000
+commit f5aec1db89664ad3b1a5d20ac81da4acda7d1d92
+Author: Carsten Bock <carsten at ng-voice.com>
+Date:   Wed Oct 2 17:21:11 2013 +0200
 
-    kazoo : fix memory allocation errors
-    
-    (cherry picked from commit fa5468c24283c8ff0a1b2254e927a128d03137fd)
+    ims_charging: docs: Fixed linebreaks in examples, regenerated README
 
-commit 0c1dc464e2b4e7a47e8a54ab087799bdcadb69ea
+commit 6faf12653c1db9f011b1826061824c831bda3f58
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat Jan 17 13:30:45 2015 +0100
+Date:   Wed Oct 2 16:43:35 2013 +0200
 
-    tls: fixed installation path update for tls.cfg
+    memcached: use pv buffer to clone the memcache value in pv strucutre
     
-    (cherry picked from commit ecb32d326615242fed43a6e2655627848842afd2)
+    - avoid leak occured by usage of pkg_str_dup()
+    - reported by Dragos Oancea
 
-commit 32e85b6481b31a1f4aa46603849cb02433e50915
+commit 9909e05d46d0cdd22227b3b8c1b1d60253a135e2
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Jan 15 17:54:18 2015 +0100
+Date:   Wed Oct 2 16:43:12 2013 +0200
 
-    presence: fix counter and type for removing presentity from cache
-    
-    - report and patch by Kristian F. Høgh
-    
-    (cherry picked from commit d43e8965640bbc64e56ef33f27d4f3c3a85c73fa)
+    memcached: use pkg-config if available for flags and libs in Makefile
 
-commit 6b7bbc8e58eae9b43b47efb270c20bb3d93ec2f0
+commit 3f3c865ed04e1b0b8eb3762622662a76ce92b2e2
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Jan 15 13:40:51 2015 +0100
+Date:   Wed Oct 2 14:23:53 2013 +0200
 
-    sl: don't remove the lump added in the 'after' list of delete lump
-    
-    - they are destroyed together, making the operation useless
-    
-    (cherry picked from commit 338b00c0f2d38694cffe3536e7eeed0e0d5372dd)
+    core: helper function to get source address as uri or proxy format
 
-commit 74888e44aa4db53a3e8db49d848af97d460f7e1f
+commit 5db86a941a909c17a0f9ee1b04febbe4c60033bd
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Jan 15 13:37:42 2015 +0100
+Date:   Wed Oct 2 14:15:18 2013 +0200
 
-    core: remove_lump() clears its innner before/after lists
+    core: skip dns srv for websocket after check if domain is ip
     
-    - fixing leak issues that could be created by using sl_forward_reply()
-      in config file
-    
-    (cherry picked from commit 1fd0ca99eaa4b2c5cfcb8bd555a35088ddf49343)
+    - reported by Peter Dunkley
 
-commit 38d6c0bc62b12ecb8402d165a21813c533c55324
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Jan 15 13:15:25 2015 +0100
+commit 49720ce99e72ded34c67a9ee4d17a9cedaf0a0f4
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed Oct 2 10:04:35 2013 +0100
 
-    core: parse_ppi_pai - free header parameters for PAI and PPI
-    
-    - they are not considere in the compacted p_id_body_t and not freed
-    - specs don't mention headers parameters for PAI and PPI, but could come
-      as UA extensions
+    xcap_server: Fix memory allocation check bug in xcap_misc
     
-    (cherry picked from commit c1b4d442501591bd18e8130474eeb5c16101e549)
+    - Would cause crash if out of package memory
 
-commit b7657fde6c74673060e1d59e604c1b72ca284dbf
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Jan 15 13:11:37 2015 +0100
+commit 93af236644058b4e97162eae689f9b32b8076691
+Author: Timo Teräs <timo.teras at iki.fi>
+Date:   Wed Oct 2 09:05:22 2013 +0300
 
-    core: parse_add_spec() free params in case of parsing failure
+    mohqueue: new module
     
-    (cherry picked from commit 5a71429596851d8096de1abe5542e57e8b8f6547)
-
-commit a56b51de8d6c10e06146fbf65ae7d46793e288c9
-Author: Seudin Kasumovic <seudin.kasumovic at gmail.com>
-Date:   Mon Jan 12 16:24:04 2015 +0100
-
-    siputils: fix for e164_check()
+    module to queue up calls in music-on-hold and then retrieve them
     
-    - the condition for non-digit matching was always false
+    imported from https://github.com/rdboisvert/mohqueue
+    commit f796f259ed1728e19adb31d76af5f6c3f548f021
     
-    (cherry picked from commit 160710af0ab85dbf211fa7d445d6d4be9b66db10)
+    excluding LICENSE which is redundant now that the module is part
+    of the kamailio source tree.
 
-commit b41d779b6d8b30f311a490d76f211c1ca656ce38
-Author: Walter Doekes <walter+github at wjd.nu>
-Date:   Mon Jan 12 12:05:52 2015 +0100
+commit fd9fcd75c222b73a2b70793e5d79c7494f757a1e
+Author: Peter Dunkley <peter.dunkley at crocodilertc.net>
+Date:   Wed Oct 2 01:30:37 2013 +0100
 
-    websocket: Check frame->wsc in ws_frame_transmit for NULL.
-    
-    Add frame.wsc == NULL check in ws_frame_transmit similar to the checks
-    in ws_close and friends and ws_frame_receive to avoid crashing if the
-    tcp connection was been terminated prematurely.
+    modules/auth_ephemeral: Added MI commands for shared secret management
     
-    (cherry picked from commit c109755d347500d8dcfa92a75cb11c9cea2727c2)
+    - Can add, remove, and display shared secrets with MI commands
+    - This means you can add/revoke secrets without a restart
 
-commit 9e293335585598e6f7bf7c9e58a0bee4cc9eb068
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat Jan 10 11:38:00 2015 +0100
+commit 6c7a0f3cdaee5ea0300d014f07e4d68f45c6e20b
+Author: Peter Dunkley <peter.dunkley at crocodilertc.net>
+Date:   Wed Oct 2 01:29:45 2013 +0100
 
-    docbook/Makefile: use default system catalog implicitely
+    modules/websocket: tidied up MI commands
     
-    - custom catalog can be forced with nocatalog=no
-    
-    (cherry picked from commit 508b11011c85bb21e5bd4212a16fabb9136e22fa)
+    - Fixed leak in error situations
+    - Improved error responses
 
-commit a30cfc6c928721f32f1d0692f89e4183d468d614
+commit 1c74725dc14fc40d9b553950e212241821351878
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat Jan 10 11:33:50 2015 +0100
+Date:   Tue Oct 1 23:18:07 2013 +0200
 
-    dispatcher: refrashed description of dispatching algorithm 8
-    
-    - priority based selection
-    
-    (cherry picked from commit aaf6c2bde1d5e3cd4443ed09c3d5767828a4bda4)
+    core: don't attempt srv lookup for proto ws or wss
 
-commit d374e4b2b92dab4127df9a98ae9b374928f03a28
+commit 2934e46a18d9cfba05e657bc1dbbaa559a31b103
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Jan 9 20:36:51 2015 +0100
+Date:   Tue Oct 1 23:03:32 2013 +0200
 
-    jsonrpc-c: fixed typo in header guard
-    
-    (cherry picked from commit 8f86d2f16af57dc26229f721c9cb86b7f68208cd)
+    registrar: fix compile warning after previous patch
 
-commit f8276f7c368250fb79d470467cda4fdf20d241cd
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Jan 8 23:18:50 2015 +0100
+commit 6cfd13cbddd1869ffbc947fdecd77d18a3fcb886
+Author: Peter Dunkley <peter.dunkley at crocodilertc.net>
+Date:   Tue Oct 1 10:52:01 2013 +0100
 
-    presence: slot and presentity uri printed in log message
+    core: fix TCP connection leak
     
-    - useful for understanding while deleting subscription from memory fails
-      to find the item
-    
-    (cherry picked from commit 8006c3a2637342c21837e5332d3eeb75bb9bf7de)
+    - patch provided by Vitally Aleksandrov
 
-commit d08a925872aa9bb2b22552171281cbe18783cbef
+commit b5b570f278124bf0456d43a36a7c0eb5eaa9efe6
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Jan 13 12:39:10 2015 +0100
+Date:   Tue Oct 1 09:34:17 2013 +0200
 
-    exec: proper handling of empty headers for exec_bash_safety
-    
-    (cherry picked from commit ae491ab355f0b2441bc20060154107b9163597de)
+    tm: added t_use_uac_headers() to documentation
 
-commit f0159a194a8ac0c0f5599867764d447ef2b5bf45
+commit 0e71fec1e108e1c9b97486ced8c1328738ca13c2
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Jan 12 11:16:53 2015 +0100
+Date:   Tue Oct 1 09:27:46 2013 +0200
 
-    ratelimit: _SC_NPROCESSORS_ONLN is available on FreeBSD
+    tm: new function t_use_uac_headers()
     
-    - used for getting number of cpus
-    - reported on GH#24
+    - set internal flags to tell tm to use UAC side for building headers for
+      local generated requests (ACK, CANCEL) - useful when changing From/To
+      headers using other functions than uac_replace_[from|to]()
+
+commit 5ac033cf85921b4c364d6d463bc75ebd22c5721a
+Author: Peter Dunkley <peter.dunkley at crocodilertc.net>
+Date:   Mon Sep 30 23:38:56 2013 +0100
+
+    pkg/kamailio/centos: Added ims_charging module to .spec
     
-    (cherry picked from commit 7886ddc516f5a4cef1d3730306a2a2ded06d4986)
+    - Removed cdp package and put cdp and cdp_avp modules into ims package
 
-commit a711f12d5f4b48b3ccf385492d4c93ace7db515c
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Jan 12 11:03:22 2015 +0100
+commit 576dce3cfdbf3cfa36fcac4f26aa3312f4add37a
+Merge: 1c3e761 f96c7f5
+Author: Carsten Bock <carsten at ng-voice.com>
+Date:   Mon Sep 30 22:38:42 2013 +0200
 
-    pipelimit: _SC_NPROCESSORS_ONLN is available on FreeBSD
+    ims_charging: New module for Diameter-Ro-Operations (IMS-Charging), Merge into Master
     
-    - used for getting number of cpus
-    - reported on GH#24
+    Credits go to:
+    - Jason Penton (jason.penton at gmail.com)
+    - Carlos Ruiz Diaz (carlos at ng-voice.com)
     
-    (cherry picked from commit cf65a6ad41396bf5e67d23e12720c420688d7880)
+    Merge branch 'ims_charging'
 
-commit 840d15e03523413282426135175e25761488bcac
-Author: Alex Hermann <alex at speakup.nl>
-Date:   Tue Aug 26 16:37:08 2014 +0200
+commit f96c7f5a44e510dbc0e3483d98c8484a6a603c23
+Merge: 8b3d53b 792fc3c
+Author: Carsten Bock <carsten at ng-voice.com>
+Date:   Mon Sep 30 22:36:35 2013 +0200
 
-    dmq: Don't delete the original notification_peer on timeout
+    Merge branch 'tmp/ims_charging' of ssh://git.sip-router.org/sip-router into ims_charging
     
-    (cherry picked from commit e73aa4032873b3fca88bb809d6d4ce4f28c0f237)
-    (cherry picked from commit 69dc8ec9fce8628cdf9bf39f7a25136544ae9a29)
+    Conflicts:
+    	modules/ims_charging/README
+    	modules/ims_charging/doc/ims_charging.xml
+    	modules/ims_charging/doc/ims_charging_admin.xml
+    	modules/ims_charging/mod.c
 
-commit 120bf4a4f6854592bd910334d4d0bd97c9f94974
-Author: Charles Chance <charles.chance at sipcentric.com>
-Date:   Thu Nov 13 18:30:34 2014 +0000
+commit 8b3d53b35f22c2de2203450af23dd8282ba8a7bc
+Author: Carsten Bock <carsten at ng-voice.com>
+Date:   Mon Sep 30 20:46:30 2013 +0200
 
-    dmq: force to send replicated messages from configured server address - as reported on list by Victor Kustov
-    
-    (cherry picked from commit 7b5f79f9f384bfe3c16c399184281ebe63bb7785)
+    ims_charging: Beautified XML-Doc for IMS-Charging
 
-commit a01849a60533e3b60dab71f1a3a632ae4b84f831
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Jan 7 22:01:27 2015 +0100
+commit 1200242cadb445988b7e582fe62a3662caf99586
+Author: Carlos Ruiz Diaz <carlos.ruizdiaz at gmail.com>
+Date:   Mon Sep 30 14:40:54 2013 -0400
+
+    ims_charging: added some stats
+    
+    - billed_secs
+    - ccr_avg_response_time
+    - ccr_responses_time
+    - failed_final_ccrs
+    - failed_initial_ccrs
+    - failed_interim_ccr
+    - final_ccrs
+    - initial_ccrs
+    - interim_ccrs
+    - killed_calls
+    - successful_final_ccrs
+    - successful_initial_ccrs
+    - successful_interim_ccr
+
+commit 4a050987a20a7489f08d9b7e88566439a764d013
+Author: Carsten Bock <carsten at ng-voice.com>
+Date:   Mon Sep 30 13:30:41 2013 +0200
 
-    dialog: proper handling of dlg_set_timeout() for not confirmed dialogs
-    
-    (cherry picked from commit a41eab6bedf670f9f34f069b82a85c3a49c5e1bd)
+    ims_charging: Regenerated README after documentation update
 
+commit a0bdd980634635ca00a3ce87ac0ea03070b2a6ea
+Author: Carsten Bock <carsten at ng-voice.com>
+Date:   Mon Sep 30 13:30:38 2013 +0200
 
-===================== 2015-01-08 Version 4.2.2 Released =====================
+    ims_charging: Fixed minor typos in ims_charging-documentation
 
-===================== Changes Since Version 4.2.1 ===========================
+commit e9c7039efe2df811ba6e09829e7b713e5a25a808
+Author: Carsten Bock <carsten at ng-voice.com>
+Date:   Mon Sep 30 13:24:51 2013 +0200
 
-commit 0dbf946ac54611b0ea359799f8e007b1851f3122
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Jan 8 18:02:30 2015 +0100
+    ims_charging: Regenerated README after documentation update
 
-    htable: revert usage of dmq nodes
-    
-    - back to v4.2.1 state
+commit 46e1160be51d5c731fa1380f23d9d6dd0ca76f26
+Author: Carsten Bock <carsten at ng-voice.com>
+Date:   Mon Sep 30 13:23:05 2013 +0200
 
-commit 486bfe7f037ea27dc8705b3e81c39ba79c54a6dd
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Jan 8 17:54:56 2015 +0100
+    ims_charging: Fixed minor typos in ims_charging-documentation
 
-    Makefile.defs: version set to 4.2.2
+commit c689a44ad13b430ac425e0efd46badf4ad021950
+Author: Carsten Bock <carsten at ng-voice.com>
+Date:   Mon Sep 30 13:21:04 2013 +0200
 
-commit 6a9133a119cd2556cdfc5260b5c3442fe2290584
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Jan 8 17:52:24 2015 +0100
+    ims_charging: Fixed minor typos in ims_charging-documentation
 
-    dmq: reverted dmq to the state of v4.2.1
-    
-    - some of the tunings in master introduced side effects
+commit 5b3ef601025eeeda556b433b6257beaf88a7ee91
+Author: Carsten Bock <carsten at ng-voice.com>
+Date:   Mon Sep 30 13:20:04 2013 +0200
 
-commit d97a2f6936fd84459e167143fc5c3a2571712e89
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Jan 8 17:15:19 2015 +0100
+    ims_charging: Fixed minor typos in ims_charging-documentation
 
-    dmq: more initialization of pointers at declaration of vars
-    
-    (cherry picked from commit 4d52cc0556d2e9cf334aca89325589f1c86b4dc7)
+commit ad7fb226901ca6ebc6119df0994054ba51100951
+Author: Carsten Bock <carsten at ng-voice.com>
+Date:   Mon Sep 30 13:16:20 2013 +0200
 
-commit 4acf9930fbeed2764a74c0f2ccb6348bee9716d7
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Jan 8 16:23:51 2015 +0100
+    ims_charging: Fixed minor typos in ims_charging-documentation
 
-    pkg/rpm: set version 4.2.2 in spec files
+commit b9c8f31cfba447326869c32c87cb728c04ec0e28
+Author: Carsten Bock <carsten at ng-voice.com>
+Date:   Mon Sep 30 12:58:56 2013 +0200
 
-commit e2b91d68d1fe411621587a552c15b4b705ae17eb
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Jan 8 16:10:00 2015 +0100
+    ims_charging: Documentation updates.
 
-    dmq: initialize peer_list to NULL by default
-    
-    - credits to Olle E. Jonansson for testing and reports
+commit 792fc3cbc1a1181a482659ea5743681f1a52b911
+Author: Carlos Ruiz Diaz <carlos.ruizdiaz at gmail.com>
+Date:   Mon Sep 30 15:57:23 2013 -0400
+
+    ims_charging: updated documentation
+
+commit 6fdc83ecd7fa5313635a0041e76498704b0c8225
+Author: Carsten Bock <carsten at ng-voice.com>
+Date:   Mon Sep 30 20:46:30 2013 +0200
+
+    Beautified XML-Doc for IMS-Charging
+
+commit ef073a82f81af6e51dff19dcadfe4a8cb760c07d
+Author: Carlos Ruiz Diaz <carlos.ruizdiaz at gmail.com>
+Date:   Mon Sep 30 14:40:54 2013 -0400
+
+    ims_charging: added some stats
     
-    (cherry picked from commit b27c38b71c09e6763e8412b7e33aab77af3dfc76)
+    - billed_secs
+    - ccr_avg_response_time
+    - ccr_responses_time
+    - failed_final_ccrs
+    - failed_initial_ccrs
+    - failed_interim_ccr
+    - final_ccrs
+    - initial_ccrs
+    - interim_ccrs
+    - killed_calls
+    - successful_final_ccrs
+    - successful_initial_ccrs
+    - successful_interim_ccr
 
-commit edbed4cc15a250e4b7c12d3d322b8a6575582c21
+commit 1c3e761fbd087ee578ce305d89f6b8ee4e9ab79d
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Jan 8 16:00:47 2015 +0100
+Date:   Mon Sep 30 16:49:26 2013 +0200
 
-    dmq: be sure dmq_init_callback_done is initialized before accessing it
+    app_perl: use local buffer to print dynamic string in pv_sprintf()
     
-    (cherry picked from commit b29a45f0a23ef0f1a26598a45d3e6eddc9dbedb5)
+    - avoid pkg malloc for temporary need
+    - fix leak in case of fmt parse error, discovered on a report by Dragos
+      Oancea
 
-commit ca0171557021a5138f52fed9ea492e1d498b881d
+commit 0696e668d75be14922980dbc9f67aa91eaf688fd
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Jan 8 15:19:57 2015 +0100
+Date:   Mon Sep 30 15:54:44 2013 +0200
 
-    pkg/deb: version set to 4.2.2 in spec files
+    registrar: simplified getting value for max_contacts xavp
 
-commit 2556a840208f4d16973772547af8258f314cef8c
+commit 308f2920df586065e0bf8ef02d7c77b1c94a4836
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Jan 8 14:19:58 2015 +0100
+Date:   Mon Sep 30 15:49:10 2013 +0200
 
-    dmq: safety check for peer_list when calling the callbacks
-    
-    - can result in crashing if it is not set
-    - reported by Olle E. Johansson
+    registrar: option to take the socket from an xavp
     
-    (cherry picked from commit cc5f96f9c847d285085b0b9809ff0db76ea0a835)
+    - child named "socket" of xavp named by xavp_cfg parameter
 
-commit 3fb17ae591fcdfb0b1127f6f9547fe2c7f4c4619
+commit 89bd52a84d5e0d75572caff61346d0c3750c868a
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Jan 7 17:02:45 2015 +0100
+Date:   Mon Sep 30 15:47:30 2013 +0200
 
-    ratelimite: take in consideration number of cpus for load
-    
-    - on multi core systems, the sums of stats can go over 100%, resulting
-      in out of range for expected load_value to be 0.0 to 1.0
-    - safety checks to avoid overflows
+    core: helper functions to get xavp child nodes
     
-    (cherry picked from commit b22c63a930a3c8d4055ddeea48bb29b7fb3b2eb1)
+    - one function to get the $xavp(rootname=>childname) in code
+    - wrappers for child node, child node with int value and child node with str value
 
-commit 4b435cb33c86844e6f8339090f445ab062a24f28
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Jan 7 16:57:36 2015 +0100
+commit e266b01116513a4fcea5df1c761ef1981e17f8f8
+Author: Carsten Bock <carsten at ng-voice.com>
+Date:   Mon Sep 30 13:30:41 2013 +0200
 
-    pipelimit: take in consideration number of cpus for load
-    
-    - on multi core systems, the sums of stats can go over 100%, resulting
-      in out of range for expected load_value to be 0.0 to 1.0
-    - safety checks to avoid overflows
-    - reported by Luca M.
-    
-    (cherry picked from commit d9e87383613d4d24efe3d1eb144ad6c9cc30b2b0)
+    Regenerated README after documentation update
 
-commit 71aae0b0dda086219663af38357801e05c49124f
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Jan 7 13:15:10 2015 +0100
+commit e98012e859ea6dd2c198d650f272d3e489758a22
+Author: Carsten Bock <carsten at ng-voice.com>
+Date:   Mon Sep 30 13:30:38 2013 +0200
 
-    seas: fixed inline functions warnings for clang
-    
-    (cherry picked from commit c52e4e13ea57702aeed45a7a2059b97faf4d06f6)
+    Fixed minor typos in ims_charging-documentation
 
-commit b46dd08b927215eeb5c14373803f52dbabb0965b
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Jan 6 23:41:59 2015 +0100
+commit 1265420b8b700eec9c96fd7752a5c3d528a51c32
+Author: Carsten Bock <carsten at ng-voice.com>
+Date:   Mon Sep 30 13:24:51 2013 +0200
 
-    core: use Sia header name instead of Via for HTTP responses sent out
-    
-    (cherry picked from commit dfb34a6516e358023543f2a30664d30ed723e934)
+    Regenerated README after documentation update
 
-commit 3d59966eb252faea756a628876336a398e1d0847
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Jan 6 23:23:43 2015 +0100
+commit bcdc27641fbec8176cea19fd4cefad1830a5c4db
+Author: Carsten Bock <carsten at ng-voice.com>
+Date:   Mon Sep 30 13:23:05 2013 +0200
 
-    core: tcp - handle http read on \n\n EOH and deal with HTTP Via header
-    
-    - handling \n\n for http makes same code as for sip, being easier to
-      test injecting a request from file
-    - HTTP Via is not compatible with SIP Via, resulting in errors - replace
-      its name with Hia to be ignored. FS#237
-    
-    (cherry picked from commit 54c178a9072339233085372e60e611ba889f46b3)
+    Fixed minor typos in ims_charging-documentation
 
-commit 0a9d23605b50bef00f516255e3bc2d1ab75f0494
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Jan 6 22:24:35 2015 +0100
+commit ba0299bd965de8d513d70151c11bf13c4ec11560
+Author: Carsten Bock <carsten at ng-voice.com>
+Date:   Mon Sep 30 13:21:04 2013 +0200
 
-    utils/protoshoot: fixed name and ticks
-    
-    - version to 0.4
-    
-    (cherry picked from commit 72a616f074f554dfb177ca8ec2b55f9ff11ad352)
+    Fixed minor typos in ims_charging-documentation
 
-commit 4c824c01d2a222167c81b1478de69773dabe1f42
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Jan 5 18:50:40 2015 +0100
+commit e8a054d0e684b8f73bd0733d7d00d5e6b5e9b23f
+Author: Carsten Bock <carsten at ng-voice.com>
+Date:   Mon Sep 30 13:20:04 2013 +0200
 
-    core: cfg parser - resolve conflict between proto:host and event route name
-    
-    - there was a conflict on same kind of id:id format
-    - event route name is expected now only after an event_route
-    
-    (cherry picked from commit 5e701d6a0826611dc980db2f434bee49e0fdcf88)
+    Fixed minor typos in ims_charging-documentation
 
-commit 4fb321cb441e38ca5b0fc65904cddf4f65f0bb53
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Jan 5 15:58:50 2015 +0100
+commit 364dc576f602db40e93f446443e278290609237b
+Author: Carsten Bock <carsten at ng-voice.com>
+Date:   Mon Sep 30 13:16:20 2013 +0200
 
-    core: preprocessor subst rules are applied to pv names
-    
-    - all name is matched and substituted before pv is looked up
-    - reported in FS#139
-    
-    (cherry picked from commit 39ffe589035fce17145023204b1005702e02a66f)
+    Fixed minor typos in ims_charging-documentation
 
-commit c3ce62ca27ddd348635f048ec9e7840a5a7f4c48
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sun Jan 4 23:55:18 2015 +0100
+commit 4af2d9a46f1b7be273c079040989bd0d0c884feb
+Author: Carsten Bock <carsten at ng-voice.com>
+Date:   Mon Sep 30 12:58:56 2013 +0200
 
-    tm: safety check for CRLF at end of custom headers for local requests
-    
-    - if hdrs value is not ending in '\n', add '\r\n'
-    
-    (cherry picked from commit b60b337e04f41d4b5262cb068f1bef6f827dba27)
+    Documentation updates.
 
-commit a75107f2abb406f5d857896fea95799a994c6781
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat Jan 3 23:28:57 2015 +0100
+commit 3c7f8ba5e3febe4dc2c8eec003436492efefdf2d
+Merge: 5ab44c7 b50888c
+Author: Jason Penton <jason.penton at smilecoms.com>
+Date:   Mon Sep 30 11:21:31 2013 +0200
 
-    tls: use atomic ops for config ref counter
-    
-    - closes FS#380
-    
-    (cherry picked from commit af408c882ed70028c7dbc84b7876be996a49235e)
+    Merge branch 'master' of ssh://git.sip-router.org/sip-router
 
-commit 85be1066008b6a837f6e39e0ce2cd825af95972f
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Jan 2 22:03:22 2015 -0500
+commit b50888cf447ea3a3315e665c97f71a07bb687337
+Author: Øyvind Kolbu <oyvind.kolbu at usit.uio.no>
+Date:   Mon Sep 30 11:15:13 2013 +0200
 
-    core: don't do initgroups() if started by same user as -u
-     - closing FS#473
+    core: resolve down to A/AAAA records when no naptr records
     
-    (cherry picked from commit df92a532f82a25f0b1ea0cb18cb800562d7f7a97)
+    - try all protocols, not only UDP
 
-commit 6cbc44828291264e1d119e209a9977e14b34f7ad
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Jan 2 13:41:44 2015 +0100
+commit 5ab44c7c2fc78038302bf455ff49e374fc79550b
+Author: Jason Penton <jason.penton at smilecoms.com>
+Date:   Mon Sep 30 11:14:54 2013 +0200
 
-    presence: more verbose debug message when failing to delete item from memory
-    
-    - re-ordered comparison expression to check first lengths
-    
-    (cherry picked from commit 497777e042166e441767101db05c85ad69c13722)
+    modules/tm: extended async usage
+    	- enables resuming of tx in orginal route block tx was suspended, not only failure route
+    	- dedicated lock to prevent multiple invocations of suspend on tz (reply lock used to be used)
+    	- extra flag (T_ASYNC_CONTINUE) to mark a transaction that is being execute post suspend
 
-commit c674193b213fa92aa4c5c6d55d8fa715fe43d448
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Jan 2 11:22:21 2015 +0100
+commit 6cdae87e29bc4c62651cf843ace680e9a6999d66
+Author: Peter Dunkley <peter.dunkley at crocodilertc.net>
+Date:   Sat Sep 28 00:30:50 2013 +0100
 
-    tls: refreshed the README
+    pkg/kamailio/centos: updates to CentOS 6 build
     
-    (cherry picked from commit 5573fded91a0dc330003ba064e524407d92b2a8a)
+    - Improved startup scripts
+    - Updated .spec
+    - README listing and explaining which Kamailio modules are not built for
+      CentOS
 
-commit e8566cd87577bee028d754db88b29841cd521303
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Jan 2 11:21:39 2015 +0100
+commit 32e26c3e914366636e4dcc6e8872eea16740e090
+Author: Carlos Ruiz Diaz <carlos.ruizdiaz at gmail.com>
+Date:   Fri Sep 27 16:05:17 2013 -0400
 
-    tls: more documentation about tls method values
-    
-    - added notes about tls minimum versions
+    ims_charging: added async support
     
-    (cherry picked from commit 99311ce3fd37eebd4c9f37d25b043c4fae8dd621)
+    - Ro_ccr is now called asynchronously and resumed on an external custom cfg route
+    - Interim and final CCR are now also async
 
-commit a0f88f59c6687b8a59ec90578b01aa3bf1e45eb6
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Jan 2 11:18:47 2015 +0100
+commit 257ca31bb89cb4cb74cad226998574469873bc3b
+Author: Peter Dunkley <peter.dunkley at crocodilertc.net>
+Date:   Thu Sep 26 23:59:53 2013 +0100
 
-    tls: options to set TLS versions lower limit
+    pkg/kamailio/centos: updated .spec for CentOS 6
     
-    - example: if method is set to TLSv1.1+, then the connection must be
-      TLSv1.1 or newer
-    - closes FS#502
-    
-    (cherry picked from commit 711833b82d17a8875ffa68a3314554a59cefb0f5)
+    - Added gzcompress
+    - Updated rel to dev9
 
-commit 93bb006ef1dcaadaf077b40920afd4fcf332087d
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Jan 2 11:16:28 2015 +0100
+commit ac5d846e2e472b1c097992bc2bdcfb58100c6eaa
+Author: Peter Dunkley <peter.dunkley at crocodilertc.net>
+Date:   Thu Sep 26 23:27:31 2013 +0100
 
-    core: don't do setuid() if started by same user as -u
-    
-    - closing FS#473
-    
-    (cherry picked from commit 241ac2813d30792c713dd6e585bae3c1d6e76f47)
+    xhttp: cache the URL string when performing transformations so sequential transformations on the same string do not require a reparse.
 
-commit a8ac25dc14e4bfb744159148bb7edcdb6f77b58a
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Dec 29 21:23:01 2014 +0100
+commit 96c9a85b607e5c42ec0f0709a2807a60e7d5b1c4
+Author: Peter Dunkley <peter.dunkley at crocodilertc.net>
+Date:   Thu Sep 26 23:26:38 2013 +0100
 
-    db_mysql: fixing include in Makefile for many paths
-    
-    - sed matching should break at whitespace, to fix the case when
-      mysql_config returns multiple include paths
-    - reported by FS#503
-    
-    (cherry picked from commit 487d4160b99a1a5ea48751d2f7404cb08e1f4546)
+    pv: tweaked {param.} transformation so that if the (optional) delimiter parameter is changed between runs the param string is reparsed
 
-commit c7ed2f48858f45925e6076715a640bb897220a6e
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Dec 23 10:25:58 2014 +0100
+commit ed23dbde621a4b60d35639d3c61284b658fb6ad1
+Author: Carsten Bock <carsten at ng-voice.com>
+Date:   Thu Sep 26 20:21:11 2013 +0200
 
-    core: use corelog level for debug messages when sending out fails
-    
-    - allow better control of what is printed, FS#68
-    
-    (cherry picked from commit 40971d1ed829bc8e18a684cd4431649acd47999e)
+    Move assert_identity to ims_usrloc_pcscf as we may have more than one IMPI per Port/IP/Proto
 
-commit 8dfcf311562861dcf36c19be80ad1594169b57b1
+commit 78d25dd11a64f36c5372cff3fe5d8a65a0e13396
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Dec 23 10:24:32 2014 +0100
+Date:   Thu Sep 26 15:10:22 2013 +0200
 
-    tm: downgraded err to warn when sending out for a branch fails
-    
-    - can happen if tcp connection is not active and no connect is set, FS#68
-    
-    (cherry picked from commit c10c13b2582fd667d24e691219939e224cffaf30)
+    db_mysql: unlock tables at the end of transaction if they were locked
 
-commit 0702109631ac1cd56a5ce575c1674dc41db1a4de
+commit 8e35cef8716bbd0caa406a5080e93acb3c881c41
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Dec 23 00:51:45 2014 +0100
+Date:   Thu Sep 26 13:23:46 2013 +0200
 
-    siptrace: use the method from cseq header for tm replies
-    
-    - the hook in transaction structure is invalid for cancel replies,
-      because the transaction structure is built for invite
-    - reported by Klaus Darilion, FS#489
-    
-    (cherry picked from commit 88173da2b684a3a3f86ee01ac5de401f492ff240)
+    presence_xml: updated docs about integrated_xcap_server
 
-commit 813b25663adbaae1c4f5ea2731c1fe16cad756e2
+commit baa4fccc2870df102a66089d6e9b6ca1ff47fc25
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Dec 22 21:41:53 2014 +0100
+Date:   Thu Sep 26 12:59:59 2013 +0200
 
-    core: safety checks on proto variable for dsn resolving
-    
-    - avoid crashes if functions used inadequately with a null pointer
+    mi_rpc: compatibility with libxmlrpc-c3 library on wheezy
     
-    (cherry picked from commit aff1dcd3dc63c0fe124fc138d553da0723c615a8)
+    - patch by Muhammad Shahzad
 
-commit b97ee8732103edc6391c2625ea38c448c371054a
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Dec 22 21:37:43 2014 +0100
+commit 378bd71de3b035b497469f89a640931d0792ce4f
+Author: Peter Dunkley <peter.dunkley at crocodilertc.net>
+Date:   Wed Sep 25 16:12:50 2013 +0100
 
-    nat_traversal: use local variable for port and proto on keepalive resolve
-    
-    - safe execution for those resolving functions expecting PROTO_NONE
-    - reported by Jason Penton, FS#491
-    
-    (cherry picked from commit 0bbcbe8328d558a9bf3cb151ab53be93b09c2669)
+    xhttp: added transformation to break a URL into "path" and "querystring"
 
-commit d47f5722d68105cade1b940c3cf0fb749215e093
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Dec 22 18:37:25 2014 +0100
+commit 454a28dad2fef3f1adaf0acec9a7f1c320fe6571
+Author: Peter Dunkley <peter.dunkley at crocodilertc.net>
+Date:   Wed Sep 25 16:11:57 2013 +0100
 
-    tm: don't clean local vars when trying to append a new branch to an active canceled transaction
+    pv: updated param transformations so that you can (optionally) specify what the parameter delimiter is
     
-    - they are not set, reported by Ovidiu Sas, FS#498
-    
-    (cherry picked from commit 7a6b86576220b423c4dc5ccab7e7f22a50be27bd)
+    - default behaviour unchanged
+    - this allows HTTP URL parameters to be decoded
 
-commit 53b9d2218793a91abe705670e8dbb96d07ee15fb
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Dec 17 23:34:21 2014 +0100
+commit e0abe290c6ff287574e2abcadcc7a0f11197e268
+Author: Peter Dunkley <peter.dunkley at crocodilertc.net>
+Date:   Wed Sep 25 16:11:23 2013 +0100
 
-    auth_db: more details for is_subscriber()
-    
-    (cherry picked from commit 7bf4c6d72774b521b4e9bbc5375c4e952a224676)
+    core: updated parse_param so that the delimiter for parameters can be user-defined
 
-commit 0b0b47277becda0926db0e60b6119a2621c28891
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Dec 17 23:30:29 2014 +0100
+commit b6b5b7bf5d08ad20cc00cf89ef3d2f03e913c882
+Author: Victor Seva <linuxmaniac at torreviejawireless.org>
+Date:   Mon Sep 23 21:30:32 2013 +0200
 
-    auth_db: fixed is_subscriber() when load_credentials is not set
-    
-    - the flag parameter can be also explicit on skipping the credentials
-    
-    (cherry picked from commit d948ca564b4f669905485e040e295f54bd3f36a2)
+    avpops: refresh README
+
+commit 3abb169001022567aa0be629677b9e445d1c3ca5
+Author: Victor Seva <linuxmaniac at torreviejawireless.org>
+Date:   Sat Sep 21 11:26:45 2013 +0200
+
+    avpops: update avp_check documentation related to xavp vars as parameters
+
+commit dd049bad86eca2371b8f6ae1fd73656ff56e4e15
+Author: Victor Seva <linuxmaniac at torreviejawireless.org>
+Date:   Sat Sep 21 10:49:57 2013 +0200
+
+    avops: avp_check() xavp as first parameter
 
-commit 3d90d4412e04e9a244459715d6ca0a97027cd201
+commit 8a6a4f5d38ac693e7a79e0e761521375f3f5405b
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Dec 15 23:11:15 2014 +0100
+Date:   Mon Sep 23 20:06:20 2013 +0200
 
-    dispatcher: better phrasing of comment in the code
+    gzcompress: removed empty section in functions chapter
     
-    (cherry picked from commit d035d0fe5e6f8298c7973432216ee0ba16840124)
+    - use deflate overall config example
 
-commit 8d3bd7c6bed2fcae9d3529ea22fad2d1d05f7d7d
+commit 65783f24859f5da45678f2c8a005ca867cc02b86
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Dec 15 12:37:42 2014 +0100
+Date:   Mon Sep 23 19:01:10 2013 +0200
 
-    dispatcher: proper filling of weights array when summ is less than 100
-    
-    - more comments on building the array for weight based distribution
-    
-    (cherry picked from commit a2b52c52e8a2503c53825b82fb66d7af11b9bc4e)
+    gzcompress: added a small usage example in docs
 
-commit b172dc23f8ee9778868e44839b1632684697fe9d
+commit 3c65fd74f2473e857996ae1abf2d8fb8dcfaaaab
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sun Dec 14 22:21:14 2014 +0100
+Date:   Mon Sep 23 18:50:14 2013 +0200
 
-    dispatcher: take in consideration the value of maxload attribute
-    
-    (cherry picked from commit ecd5c5846483e9069df875a181b58de7f8035604)
+    gzcompress: readme updated to reflect default encoding value to deflate
 
-commit 2d1032b3c8a1184357615b37da99dfd76526afa7
+commit d1263e418b7acbcc6ac798e25fc8bbcd8483fcec
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Dec 10 16:14:16 2014 +0100
+Date:   Mon Sep 23 18:49:06 2013 +0200
 
-    siputils: fix for e164_check()
-    
-    - the condition for non-digit matching was always false
+    gzcompress: default encoding header value set to deflate
     
-    (cherry picked from commit fbcfa198a2c89868fa021f6a63774425e480b27b)
+    - it is what UA use for this zlib compression algorithm
 
-commit df180f1ddea079b432dd89bcdee90ce8a6cbde77
+commit adf32ec8b3e6329d1c75f158a11395a077fc54ea
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Dec 1 11:53:23 2014 +0100
+Date:   Mon Sep 23 18:42:54 2013 +0200
 
-    tmx: proper indentation to match the module style
+    core: aliased http_reply_hack to http_reply_parse
     
-    (cherry picked from commit 6c14b13f118dc20daec39bdde40c030c14e2d9c3)
+    - a more relevant name for the core parameter that enables parsing http
+      replies
 
-commit 82a60e0c7a7e33908bae52d11fe4911df91823c2
+commit d84a95b2dff1c373add8822ae7f1d9da495b5cd5
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Nov 26 16:39:07 2014 +0100
+Date:   Mon Sep 23 18:41:51 2013 +0200
 
-    registrar: don't free r-uri branch attributes in lookup_branches()
+    gzcompress: enable compression for http messages
     
-    - just clear the values in sip_msg_t structure so the pointers can be
-      reused and avoid double free
-    - reported by Anthony Messina
-    
-    (cherry picked from commit 9a46223c077c8d058cdc633563b0d9f14af332ae)
+    - tested replying with compressed body to an HTTP request from FireFox
 
-commit 67ecb465428b4ff91b3b898f538a12d3dc1577da
-Author: Alex Hermann <alex at speakup.nl>
-Date:   Thu Nov 13 19:54:26 2014 +0000
+commit 33557b2de1631601be9b03447e3167d06e8ce1cb
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Mon Sep 23 18:40:48 2013 +0200
 
-    dmq: Let the handler know about the sending node
-    
-    Try to find a node based on the from uri of the incoming request and hand
-    it to the request handler.
-    
-    (cherry picked from commit c2dcf4dbd884b13423159a7d94a3cb9f4e1a3e87)
+    parser: added macros to check if it is a SIP or HTTP reply
 
-commit 373c643a4cf63c8ddfae23f39103e36156032428
-Author: Alex Hermann <alex at speakup.nl>
-Date:   Thu Nov 13 19:45:32 2014 +0000
+commit bd716593efb83d4124c0c0cb824bf158d547ca0d
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Sat Sep 21 00:10:43 2013 +0200
 
-    dmq: Add init_callback() to API
-    
-    The init_callback is called after DMQ has synced with the notification_peer.
-    This callback can thus be used to send/broadcast messages as early as
-    possible.
-    
-    (cherry picked from commit b1aadf4cf9ea8fa91465fadc24ad268398a74880)
+    gzcompress: new module to compress/decompress SIP message body using zlib
 
-commit e09ad6120e6373f9f635ee4907603c53ce4b7eda
-Author: Alex Hermann <alex at speakup.nl>
-Date:   Tue Aug 26 16:37:08 2014 +0200
+commit dcfa15de586e28a025e34590e800571b0e3abddf
+Author: Charles Chance <charles.chance at sipcentric.com>
+Date:   Fri Sep 20 21:07:30 2013 +0100
 
-    dmq: Don't delete the original notification_peer on timeout
-    
-    (cherry picked from commit e73aa4032873b3fca88bb809d6d4ce4f28c0f237)
-    (cherry picked from commit 69dc8ec9fce8628cdf9bf39f7a25136544ae9a29)
+    dmq: code cleanup, remove redundant includes
 
-commit 1db387a5f75f84f4eb7a446041cd6657090dc1b8
-Author: Charles Chance <charles.chance at sipcentric.com>
-Date:   Thu Nov 13 18:30:34 2014 +0000
+commit 4b53052e3c912c927927529cd98a05957e02ab18
+Author: Ovidiu Sas <osas at voipembedded.com>
+Date:   Thu Sep 19 09:19:16 2013 -0400
 
-    dmq: force to send replicated messages from configured server address - as reported on list by Victor Kustov
-    
-    (cherry picked from commit 7b5f79f9f384bfe3c16c399184281ebe63bb7785)
+    presence_conference: fix what it looks like a copy/paste error
 
-commit c76b6edeb0ce5a39b9346d44dfca589423df0958
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Jan 7 11:30:01 2015 +0100
+commit 1af47db737d8ca6fcfc43f4abb3d3768f5a8257c
+Author: Ovidiu Sas <osas at voipembedded.com>
+Date:   Thu Sep 19 09:01:04 2013 -0400
 
-    jsonrpc-s: safety check for str value of jsonrpc and method fileds
-    
-    - reported by Alex Balashov
-    
-    (cherry picked from commit 29fe7a813b17af898dbe0c4e978dd05766f41aec)
+    pdb: fix warning dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
 
-commit bff4e99d81353dbf02e0a6f609f762237ff589fd
+commit 6592870dbd2b388b3884d85b9cc69e323f1d175a
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Nov 25 12:20:36 2014 +0100
+Date:   Fri Sep 20 15:00:14 2013 +0200
 
-    usrloc: fixed issue updating last_modified
+    sl: use global variable for event route index for local response
     
-    - introduced in previos commit
-    
-    (cherry picked from commit 767c2bc60f7f5a601118329df2c16b2646dbb58f)
+    - rt should have been no longer used after previous commit
+    - reported by Ovidiu Sas
 
-commit 84100f0399c765c58d0de74086f97bc70440f5e9
+commit 8ca99e58442becd4513bb03730806c37f86f0d8f
 Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Mon Nov 24 14:48:16 2014 +0100
+Date:   Fri Sep 20 13:38:29 2013 +0200
 
-    usrloc: fix db_update_addr and db_delete_ucontact_addr
-    
-    use query WHERE columns depending on matching_mode option
-    
-    (cherry picked from commit e8a795a6a413ae453f619e3deaf36c26b85b0077)
+    pv: use pv_get_buffer on pv_core
 
-commit a0d6ec4487530147d90c0dd988824fd57260cfcc
+commit 039081166803f4be4226026e51f43ee9793876a3
 Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Tue Jan 6 21:55:25 2015 +0100
+Date:   Thu Sep 19 13:27:21 2013 +0200
 
-    test/travis: move travis scripts to tests/travis ( Closes #20 )
-    
-    (cherry picked from commit d8642e20ae37e7724b9b9c517054b5d41c3c52f8)
-    
-    Conflicts:
-    	.travis.yml
-    	test/travis/databases_travis.sh
+    pv: get all values for second key for xavp
 
-commit 0e87a461e9c2a2914204f1597070d54af3798bd5
-Author: Luis Azedo <luis at 2600hz.com>
-Date:   Tue Jan 6 01:00:02 2015 +0000
+commit 16f87ae1b1f78938ed56a7c9a336a2853022b86c
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Fri Sep 20 13:39:15 2013 +0200
 
-    kazoo : missing operator
+    sl: lookup event route for local response at startup
     
-    (cherry picked from commit 6cf4ba4ed83b5f9e8dd736efee86174602cdd14e)
+    - group lookup of sl event routes in one function
 
-commit d2bd1e573c72a24cd9e6382cdfd96a79b139f31d
-Author: Luis Azedo <luis at 2600hz.com>
-Date:   Tue Jan 6 00:03:08 2015 +0000
+commit f8697d13be92a79bdfcfd6a824d5e312f7b0d9e0
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Fri Sep 20 11:20:42 2013 +0200
 
-    kazoo : missing operator
-    
-    (cherry picked from commit fd3520acd7ab75890a0f514dfb349d94c2ce2807)
+    Makefile.defs: version set to 4.1.0-dev9
 
-commit 4f6e524633924320c6bcc018611e90883191d00f
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Mon Jan 5 19:07:08 2015 +0100
+commit e35fe9c6095361414565b1099dea1ad5950fb38d
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Fri Sep 20 11:18:09 2013 +0200
 
-    travis-ci: set proper email notification options
-    
-    (cherry picked from commit 04999c90b074bf1571036ab88bb0a384a58f97a2)
+    registrar: note about empty value for received_param
 
-commit 6a1c998785bf763d16c11e261deea4a2d83e0f78
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Mon Jan 5 15:38:26 2015 +0100
+commit 2f213e313a86e16665f6d0acfec959bf23f72b7d
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Fri Sep 20 11:15:16 2013 +0200
 
-    travis-ci: build only supported branches. Send email notifications on failure only
+    registrar: if rcv_parm value is empty, don't add received to contacts in 200ok reply
     
-    (cherry picked from commit dc9928ec99901ec713d1a79b02a8554ed5f6618e)
+    - otherwise results in malformed value
 
-commit 2d88f43202dee40c322755758d8ef1061f58acc3
-Author: Luis Azedo <luis at 2600hz.com>
-Date:   Mon Jan 5 13:24:39 2015 +0000
+commit 664b2f30de6518636085d676a32247c7d46bd2da
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Fri Sep 20 11:09:15 2013 +0200
 
-    kazoo :  fix transform
-    
-    (cherry picked from commit 767fb51adbaecf37a0812731d9bf63a86f2b3c0e)
+    registrar: list of allowed route blocks updated for save()
 
-commit 11dc171ae98212bb22321e03f3c10e15b6017a80
-Author: lazedo <luis.azedo at factorlusitano.com>
-Date:   Fri Dec 26 18:46:41 2014 +0000
+commit e2376e34fbabd929d0736bddb8e82ceb25cc3738
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Fri Sep 20 11:07:31 2013 +0200
 
-    kazoo : fork process with tcp option
+    registrar: relax usage of save() for failure route
 
-commit a2aa22d8f23a8bcad0ed83831d0f6f10e9059a7c
+commit 0968ce561b3bb8ea2ad2c7c53c03091e8518a6fe
 Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Thu Dec 18 21:41:46 2014 +0100
+Date:   Fri Sep 20 11:08:52 2013 +0200
 
-    pkg/kamailio: Initial Travis CI configuration
-    
-    (cherry picked from commit 3cdfb23b6e9d13fea3ee0994b450279c3cc6a488)
+    avpops: allow xavp semantics on second parameter
 
-commit 9bb59f922da4474e3b30e7f47cf841c9e40c3ffd
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Dec 18 00:52:48 2014 +0100
+commit df472fa9bdaa1a796dd220c99a64b1539c8854b5
+Author: Victor Seva <linuxmaniac at torreviejawireless.org>
+Date:   Fri Sep 20 11:07:14 2013 +0200
 
-    dispatcher: readme file updated
+    pv: Move pv_xavp_name_t declaration to core pvar.h
 
-commit 3cb767da8e049da87fd4e4c8dd824a59cd10b971
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sun Dec 14 14:21:06 2014 +0100
+commit 5acf191aee9d10b26b730df20d622e527c656db3
+Author: Ovidiu Sas <osas at voipembedded.com>
+Date:   Wed Sep 18 17:10:10 2013 -0400
 
-    dispatcher: dedicated section for attributes in docs
-    
-    - file format has it own section too
-    
-    (cherry picked from commit 610a93ea038f9eb10ac611263891813b734fc7a0)
-    
-    Conflicts:
-    	modules/dispatcher/doc/dispatcher_admin.xml
+    xcap_client: fix what it seems to be an old copy/paste error
 
-commit d80dfcc179af4cb45552722887a35cfe8efcc435
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Dec 11 23:37:24 2014 +0100
+commit 11ea7e73f0b541c2759d89a125b69a23cecb9ba9
+Author: Ovidiu Sas <osas at voipembedded.com>
+Date:   Wed Sep 18 16:57:56 2013 -0400
 
-    core: set log prefix only for sip messages
-    
-    (cherry picked from commit 79a23a4fc154ad1ff174c3a8c2a14c3c5f85f402)
+    xcap_client: fix what it seems to be an old copy/paste error
 
-commit 8a6660697bf08d0522fcd7ffa60698ebcdc4f990
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Dec 10 10:54:56 2014 +0100
+commit e45df83ddb68a90e91cc99fcdbb364f7b09ea541
+Author: Peter Dunkley <peter.dunkley at crocodilertc.net>
+Date:   Thu Sep 19 18:15:21 2013 +0100
 
-    dialog: reset local variables shortcuts after reply and failure processing
-    
-    - avoid using wrong values to find dialogs with processing of next messages
-    - reported by Julia Boudniatsky
+    modules/auth_ephemeral: many improvements
     
-    (cherry picked from commit dcdb73d792719e38844eef60f821365b587893d7)
+    - Some general tidying up of the code
+    - Support for both draft-uberti-rtcweb-turn-rest format usernames
+      and the original format
+    - New non-digest authenticate function that can be used to authenticate
+      WebSocket handshakes (based on URL and Cookie: contents) - this means no SIP
+      level authentication is required for WebSocket traffic
+    - Check functions to verify that the From:/To: URIs match the user-string part
+      of ephemeral usernames
+    - Check function so you can re-check the timestamp (for example, when caching the
+      ephemeral username during WebSocket handshakes you may want to check it is still
+      valid when a SIP request arrives)
 
-commit 2f04794b8357ccfa1304ce53ff5795c6f4f0ca7f
-Author: Hugh Waite <hugh.waite at acision.com>
-Date:   Tue Dec 9 19:05:31 2014 +0000
+commit f7fe8b68ffb100fbaa27344e4bee7ba69c760584
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Thu Sep 19 15:59:18 2013 +0200
 
-    registrar: Fix memory leak around path and outbound header parsing
+    pkg: kamailio - provide -f $CFGFILE to init.d config check function
     
-    - Fix leak of parsed URI and URI parameters during a call to save()
-    (cherry picked from commit 56c880120c07443eceb732117f0f1aa3558dcfe5)
+    - reported by Grant Bagdasarian
 
-commit 725501d7a96348f08376646112bd58c009b4b06f
-Author: Olle E. Johansson <oej at edvina.net>
-Date:   Mon Dec 8 13:22:38 2014 +0100
+commit 7730b5c3cf6b889f34de6004ce87341c746968ca
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Thu Sep 19 15:50:29 2013 +0200
 
-    pv Update error in docs.
+    core: msg_ldata_t field is memset to 0 in the shm clone
 
-commit 0a377769262f95579878b6a48fad04fcdfca1e79
-Author: Olle E. Johansson <oej at edvina.net>
-Date:   Sun Dec 7 09:19:00 2014 +0100
+commit 859a322a1f664fcdd9563619fa0448be2911aa07
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Thu Sep 19 15:49:48 2013 +0200
 
-    evapi Add link to external library.
-    (cherry picked from commit 8370ef43f0fbd2ee447ab65c5b5172677a47f644)
+    outbound: updated access cached flow through local data structire in sip_msg_t
 
-commit b4c4f72bdcdeec12068276a97fde62ba17921e51
+commit 4b99ad9e3bc364745d21eef11a392168eeb17077
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Dec 8 09:11:32 2014 +0100
+Date:   Thu Sep 19 15:49:17 2013 +0200
 
-    auth_db: added sections ids for functions
-    
-    - better reference for web indexing
-    
-    (cherry picked from commit d17f162ee565b80ecd46b6f8f916a683748bf08b)
+    tm: reset local data structure for faked request after failure handlers
 
-commit 9243615c6a6a4616d5aca621902eac7f0878cb0a
+commit 949e1f3c3e1f1afa02c696403399a093905c3f0a
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sun Dec 7 20:26:37 2014 +0100
+Date:   Thu Sep 19 15:45:43 2013 +0200
 
-    acc: fixed computation of extra accounting fields
-    
-    - introduced in previous commit
-    - reported by and credits for troubleshooting to Anthony Messina
+    parser: refactored a bit sip_msg_t struct for extra fields needed per process
     
-    (cherry picked from commit 0cf6fdc78d2171dba8d31370b84da99d8c94fb29)
+    - a new structure to keep cached decoded flow for outbound, previously
+      was declared inline
+    - easier to reset it for shm clone and tm faked environment
+    - new fields that are needed inside the sip_msg_t but not cloned in shm,
+      must be added in the msg_ldata_t structure, accessible via ldv field
 
-commit b59e77cebcb5b9db2dff3aa9d4afaa4190210985
+commit a3a8457e9bfe4dea48c0acd7421952014346a907
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sun Dec 7 19:44:38 2014 +0100
+Date:   Thu Sep 19 15:17:38 2013 +0200
 
-    auth_db: added ids to parameters
+    core: fix for warning dereferencing type-punned pointer will break strict-aliasing rules
     
-    - better reference for web indexing
-    
-    (cherry picked from commit 4eebd5d5cbf6c3f8c6b350c6d7e62f4f2a3e7610)
+    - related to timer list operation
 
-commit a9fc427270ad903a08042fcbc71d45ad4781474a
+commit 10cc1dd7a3f4481c677022e7ff0da87f004077f0
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sun Dec 7 12:23:07 2014 +0100
+Date:   Thu Sep 19 15:12:29 2013 +0200
 
-    tmx: added its for mi functions in doc
-    
-    - better indexing for web
-    
-    (cherry picked from commit 7d6c87d4ba129dd2e7d28e183dbbf43b2df12557)
+    parser: added note about new fields in sip_msg_t
 
-commit 693e8bcafbcda774a7cfd16f03923eb17c1e3d7c
+commit 659b920399ee2a75973c610f5dec4c6292903f67
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat Dec 6 01:03:14 2014 +0100
+Date:   Thu Sep 19 13:25:41 2013 +0200
 
-    tmx: added section ids for functions
+    core: set to NULL the pointers to several sip msg fileds in cloned structure
     
-    (cherry picked from commit dc6d9ba4c4f581e37c2bcbb7f1a3b4defe847e13)
+    - instance, ruid and location_ua are reset to null for the clone in shm,
+      otherwise they point to pkg and the shm can be used from other
+      process, resulting in crash
+    - reported and credits for testing and troubleshooting to Alex Balashov
 
-commit db8859587bb5b97637e1f815ab631fc42e8d49c9
+commit cebbacc3167f0fd4a4f3fd96393b5cf85e13d861
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Dec 5 22:40:25 2014 +0100
+Date:   Thu Sep 19 13:24:57 2013 +0200
 
-    exec: use proper header field iterator to print env variables
-    
-    - issue introduced with the patch for shellshock
-    - reported by and credits for troubleshooting to Kristian Kielhofner
-    
-    (cherry picked from commit 8855e3e7fcece4ca2ab33e1f9c54b15831152400)
+    tm: faked request fields are freed using wrapper functions from core
 
-commit f03a1769c55b4992613e153bd8d7bd012fc67525
+commit cae9659766c84e9451e4ea41e61bf85337c89693
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Dec 5 18:17:39 2014 +0100
+Date:   Thu Sep 19 13:23:53 2013 +0200
 
-    core: keep the password only if the user part is set
-    
-    - a report by Timo Klecker
+    parser: use wrapper functions to reset fields in sip_msg_t
     
-    (cherry picked from commit 8c3d167b63096d3b465c53aca92ee18c5255188c)
+    - used for freeing the structure
 
-commit 4fb1266b2222df1c3452683cc64dbce2d0ba5b98
+commit deb007275ae6444037e74c82a48fc879a0cc98ad
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Dec 5 16:39:32 2014 +0100
+Date:   Thu Sep 19 12:34:33 2013 +0200
 
-    acc: free extra attributes for db, radius and diameter
-    
-    - after the commit to allocate memory for extra attributes, only log
-      accounting was freeing the memory
-    - reported by Luca M.
-    
-    (cherry picked from commit 3afb2ea88fea4765a73e37f24b40dff8c8487122)
+    parser: ppi/pai - fix warning dereferencing type-punned pointer will break strict-aliasing rules
 
-commit 0ac4c8e579214a75b102f2f1c6877dffb2db8597
-Author: Juha Heinanen <jh at tutpro.com>
-Date:   Wed Dec 3 09:13:49 2014 +0200
+commit aa9f500c80cb5372c40f1eb7f18b4e33dcd6acf5
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Thu Sep 19 12:27:35 2013 +0200
 
-    modules/pua: do not override send_publish return value at error
+    core: a bit of cleaning in sip_msg_t comments
 
-commit fad00aeb2fb96cd9796ef41568e9b3cb535f300c
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Dec 1 11:50:15 2014 +0100
+commit 8bb61ea287ccf670ef9cfe990d319249eafbe7c5
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed Sep 18 21:58:12 2013 +0100
 
-    nat_traversal: use dedicated function for testing via address against source ip
+    modules/app_lua: Fix off-by-one error in modf
     
-    (cherry picked from commit c6c4230fb0c4ca18f5c681c7195d3e1531255f3a)
+    - Fixes calling sr.modf with additional parameters
 
-commit a2832bf95bf0fa4e866ee4a04cabe944d5374ffb
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Dec 1 11:48:39 2014 +0100
+commit 771e9093e343951e12f4875692e9ecc567a277a1
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed Sep 18 21:34:16 2013 +0100
 
-    nathelper: use dedicated function for testing via address against source ip
+    modules/sdpops: Check for valid sdp body in sdp_remove_line_by_prefix
     
-    - reported by Igor Potjevlesch
-    - previous used functions was checking the presence of rport and
-      received parameters, ending in a wrong result for nat testing
-    
-    (cherry picked from commit 0b10377df11977d7ddd7e6bf30fe060d1fe200aa)
+    - Fixes crash when used on requests with no body
 
-commit 7ebf861b27ae7e90092bc875d75772e5a1c941d5
+commit b9c6e70871085e63add429984eac8ee7afc9e49e
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Dec 1 11:47:19 2014 +0100
+Date:   Thu Sep 19 00:09:55 2013 +0200
 
-    core: dedicated function to check Via address with source ip
-    
-    - received_via_test() as alternative to received_test() which looks also
-      for rport and received parameters, confusing nat detection tests
+    README: updated version number
     
-    (cherry picked from commit 194743bf0de92ae09fdc817e57863f6bdb159539)
+    - bits of formatting for ToC
 
-commit 15435f96b50a7bf71d321eb925988ebb7498bdf0
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Thu Nov 27 16:45:06 2014 -0500
+commit 89969601d66422fd4dab50b0bb303bb17465c193
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Wed Sep 18 22:23:41 2013 +0200
 
-    tmx: fix warning: may be used uninitialized in this function
+    pua_reginfo: documented the parameter for reginfo_handle_notify()
     
-    (cherry picked from commit 022ae9be87b11838345a3d22b1170b280aef8aa7)
+    - reported in FS#340
 
-commit 2c61fc8af3766844084c3ab669ded2527e458a63
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Thu Nov 27 16:16:26 2014 -0500
+commit 9ee44c6079c8d30138ece619295974e17993aa04
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Wed Sep 18 22:17:55 2013 +0200
 
-    tm: fix warning: may be used uninitialized in this function
+    pua_reginfo: add ruid for location records
     
-    (cherry picked from commit 76ad065338e6970c09c5ed8bc0f84fd2bfdf0ac2)
+    - patch by Wonbin Cho, FS#339
 
-commit 9eb85067e4c93ad952f87abcfc1d2ede6d194b97
+commit ed6884e854cdae63c4f62871a32bdcdcddb8853e
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Nov 25 16:07:31 2014 +0100
+Date:   Wed Sep 18 22:02:04 2013 +0200
 
-    kamctl: supress all output of which command searching for g/readlink
+    pua_reginfo: unlock udomain only when aor is set
     
-    - based on patch and report by Morten Tryfoss, FS#492
-    
-    (cherry picked from commit ed301d16f30195d9352245f782269f2b3ddf40cf)
+    - patch by Wonbin Cho, FS#338
 
-commit 31d6d85beda8c2fd49d35c32ec8982fb7a09e4d9
-Author: Morten Tryfoss <morten at tryfoss.no>
-Date:   Tue Nov 25 10:18:04 2014 +0100
+commit 3bc87f139bc9635e23a4e92b03d24e00b97706dd
+Author: Carlos Ruiz Diaz <carlos.ruizdiaz at gmail.com>
+Date:   Wed Sep 18 13:39:23 2013 -0400
 
-    fixes for centos rpm specs
+    ims_registrar_scscf: fixed bug caused by uninitialized global variable
     
-    - updates for rtpengine and the new modules
-    
-    (cherry picked from commit 16fd690d1857dfb16681d918f11ed0863cd3845c)
-
-commit 32791c6329bc54ad0b542c2459489a83433eae3c
-Author: Olle E. Johansson <oej at edvina.net>
-Date:   Wed Nov 19 13:15:36 2014 +0000
-
-    dbtext database definition: several fields in subscriber can be null
+    - "rerrno" variable was not initialized and caused corruption in transaction states
 
-commit 27b566619cb69345a35f7af82b0b2a6a1c4ed5a6
-Author: Juha Heinanen <jh at tutpro.com>
-Date:   Tue Nov 18 04:32:35 2014 +0200
-
-    nathelper: improved add_contact_alias() description
-    - thanks to Dan Christian Bogos for pointing out the deficiency
-    (cherry picked from commit c04f9554df58b1323a46f6e40337fa34b34f1cc9)
+commit 96e760147469a385a0b5512f74afcff8f56cafd1
+Author: Ovidiu Sas <osas at voipembedded.com>
+Date:   Tue Sep 17 09:24:51 2013 -0400
 
-commit ca60c77acddc13d36ab691f8cac1f566323f6d86
-Author: Olle E. Johansson <oej at edvina.net>
-Date:   Thu Nov 13 12:16:25 2014 +0100
+    dispatcher: fix mi/rpc reload command
 
-    app_python	Avoid collission in name space - rename init_modules to ap_init_modules
+commit 5e775ff328b73b816e61a0a4718b194591a98251
+Author: Victor Seva <linuxmaniac at torreviejawireless.org>
+Date:   Wed Sep 18 14:15:17 2013 +0200
 
+    avops: use pv_cache_get instead of pv_parse_spec.
 
-===================== 2014-11-11 Version 4.2.1 Released =====================
+commit 519de2cdd1ed7fb969d3bb2cf5792d4180078cbb
+Author: Juha Heinanen <jh at tutpro.com>
+Date:   Wed Sep 18 08:18:33 2013 +0300
 
-===================== Changes Since Version 4.2.0 ===========================
+    modules/lcr: fixed checking of IPv4 address in to_any_gw_2 function
+    
+    - Patch was provided by Reinier Boon.
 
-commit 23a70da2e560ff9cae84271930321dc3075a2ad3
+commit af8923703276bb41ea269cc19a7812fea325a250
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Nov 11 13:38:23 2014 +0100
+Date:   Tue Sep 17 15:00:37 2013 +0200
 
-    Makefile.defs: version set to 4.2.1
+    debugger: reset_msgid parameter was in functions sections
+    
+    - added some section ids
 
-commit 79aea2314f3f4ef93645726c53ae3b9e9a66037b
+commit 2710177c2673034d3f026dfa79432e986b8c3a90
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Nov 11 12:56:52 2014 +0100
+Date:   Tue Sep 17 14:55:07 2013 +0200
 
-    pkg/deb: version set to 4.2.1 in spec files
+    debugger: documentation for cfgpkgcheck parameter
 
-commit 3bd165bc6efa87920cc0bbdf5084755ebc62d66e
+commit d1e456b251602e1336e4dbede1e9f8b5d1c19415
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Nov 11 12:46:54 2014 +0100
+Date:   Tue Sep 17 14:47:49 2013 +0200
 
-    pkg/rpm: set version 4.2.1 in spec files
+    debugger: new parameter cfgpkgcheck to do pkg memory check before each action
 
-commit 00c884a644689ec9e135283c26d0d9f90711bb4c
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Nov 10 15:42:39 2014 +0100
+commit af7c3a816529cde599af9a62bfd174b2de3a2fb6
+Author: Ovidiu Sas <osas at voipembedded.com>
+Date:   Sun Sep 15 18:10:06 2013 -0400
 
-    tm: handle BRANCH_FAILURE_ROUTE in t_check_trans() test
-    
-    (cherry picked from commit 08248bae17024246442046376a4350007a100025)
+    xmlrpc: fix warning: âc.lenâay be used uninitialized in this function [-Wmaybe-uninitialized]
 
-commit 69db8e643ac2356e443eddd9eecb14430f3e7452
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat Nov 8 11:10:11 2014 +0100
+commit 78a1c7e972b66c882e9466404d1cb6c08982eb91
+Author: Ovidiu Sas <osas at voipembedded.com>
+Date:   Sun Sep 15 18:06:18 2013 -0400
 
-    htable: elaborated docs about sht_lock() and sht_unlock()
-    
-    (cherry picked from commit 44269cd654a6ab0557ca242f25ec41158e7dcbaf)
+    ipops: fix warning: variable âtâet but not used [-Wunused-but-set-variable]
 
-commit 7e6a27a907806fc48c35895c471c7d1ab97f2d27
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat Nov 8 10:57:00 2014 +0100
+commit aa15067b8a1f44d57551f646acd5058c08abe41f
+Author: Mikko Lehto <mslehto at iki.fi>
+Date:   Sun Sep 15 16:55:04 2013 -0400
 
-    htable: make locking to access a slot re-entrant for a process
-    
-    - proper functionality for sht_lock()/sht_unlock()
-    
-    (cherry picked from commit 4f07daab9cb95e13c7c89a9a566d4a8c88b9145e)
+    rtpproxy(-ng): patch: has_sdp() does not exist
 
-commit 4bd289f1d893fd36c4fe508f34c0d2a58901d119
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Nov 6 18:43:50 2014 +0100
+commit d1219dc0d0c5e2eab0672a439aa7ce6486c31ba3
+Author: Ovidiu Sas <osas at voipembedded.com>
+Date:   Sun Sep 15 16:38:34 2013 -0400
 
-    htable: use mode everywhere to control the locks for add operation
-    
-    (cherry picked from commit c7ff8a88e773e8d25958f86d178f05ee10fd0410)
+    xhttp_pi: fix crash when checking bad configs
 
-commit 39d6a77084f6c32af1f0de646410a247e55355c3
+commit a68e48bc3c322be79a608d91f40d10329c2e9664
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Nov 4 16:32:13 2014 +0100
+Date:   Mon Sep 16 20:31:44 2013 +0200
 
-    pua_reginfo: avoid sending notify when processing location record action triggered by itself
+    corex: new pv $cfg(key) - return attributes for config file
     
-    (cherry picked from commit e070257321853d799a6325ac5e94f69b4ccb85e7)
-
-commit 2965000599c1b03ad9b90eb6c773d03953b6e603
-Author: Alex Hermann <alex at speakup.nl>
-Date:   Mon Nov 10 12:24:11 2014 +0100
-
-    perl: Sync log levels with kamailio core
+    - $cfg(line) - the line of the current action.
+    - $cfg(name) - the name of the current conf file
     
-    (cherry picked from commit 92fa1ac28b4991cd83338d1f99e898dfe1d8742f)
-
-commit f39c6ae6934550eff8ba5b01bfe94abfea6a094e
-Author: Alex Hermann <alex at speakup.nl>
-Date:   Thu Oct 23 17:49:44 2014 +0200
-
-    dialog: fix crash when trying to RPC export a "remote" profile
+    Example of usage:
     
-    (cherry picked from commit 79695ed2628db60199647baf653ce5f9b9005fe9)
+    append_to_reply("P-Cfg-Line: $cfg(line)\r\n");
 
-commit 0b46ce64d443c5d271f32b2ec759eca0f066105e
-Author: Alex Hermann <alex at speakup.nl>
-Date:   Thu Oct 23 17:46:26 2014 +0200
+commit ca568ee6996cc93e8518f277cf34111bc0c78299
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Mon Sep 16 09:53:15 2013 +0200
 
-    dialog: break loop when profile entry doesn't exist
-    
-    (cherry picked from commit a65a212c1e7587182f113a94f3d0d8b46c97baa0)
+    core: added wrapper functions to return cfg line and name for current action
 
-commit 950fb8e421daea12d268bc09b53297a175ccc758
-Author: Alex Hermann <alex at speakup.nl>
-Date:   Thu Oct 23 17:46:00 2014 +0200
+commit 4294b7bf3b67f1405869e865c171e268e60d5ee7
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Sun Sep 15 22:35:38 2013 +0200
 
-    dialog: release lock when profile has been found
+    core: store current executed cfg action in a global variable
     
-    (cherry picked from commit 10a655b5545f5170f339a9f18d702f4e85dd5778)
+    - can be retrieved by module to access name of config file and the line
 
-commit c161bd375b2e00215fa3d657aa6ec273ce515e6c
-Author: Alex Hermann <alex at speakup.nl>
-Date:   Thu Oct 30 17:15:38 2014 +0100
+commit e63af00eaa92eed106356cbb1dd6afd8b09f3e69
+Author: Charles Chance <charles.chance at sipcentric.com>
+Date:   Sun Sep 15 23:38:56 2013 +0100
 
-    perl: check for and handle memory allocation failures
-    
-    (cherry picked from commit 293caa403bba6741d15254a42d106392fc657888)
+    dmq: added dmq_load_api to exported functions
 
-commit d14ba3700928a16b500cf832c1101d2fdd12a0e2
-Author: Alex Hermann <alex at speakup.nl>
-Date:   Thu Oct 30 17:12:28 2014 +0100
+commit 923d09f0c1ece04c8d3c2755b5b201b3a2cd2deb
+Author: Charles Chance <charles.chance at sipcentric.com>
+Date:   Sun Sep 15 23:38:45 2013 +0100
 
-    core: Don't log errors when dns find no more records
-    
-    If the proxy is listeneing on both ipv4 and ipv6, DNS attempts are done for
-    both A and AAAA records. If the last of these lookup fails with no records
-    found, don't log an error if the first lookup did already return records.
-    
-    (cherry picked from commit 3aec75e97b579cc67340c0fb81b276321b4ab73a)
+    dmq: regenerated readme
 
-commit 51b7e8f539ada81cdb8e7fe49d5c0ccf5e3cc274
-Author: Alex Hermann <alex at speakup.nl>
-Date:   Tue Oct 16 14:57:42 2012 +0200
+commit b44f00adbf57cb4306a0dcde7a8a1425afe40a8f
+Author: Charles Chance <charles.chance at sipcentric.com>
+Date:   Sun Sep 15 23:38:30 2013 +0100
 
-    dispatcher: Ignore IPv6 addresses if IPv6 lookups are disabled.
-    
-    (cherry picked from commit 2d7f748ef690846365e4dd5bc5a91df21e39321c)
+    dmq: updated documentation
 
-commit 2d311c5897f68362f3bde53a3bbe21316d7c769f
-Author: Alex Hermann <alex at speakup.nl>
-Date:   Tue Oct 14 15:58:41 2014 +0200
+commit 102074ce6085f963ac03dcb087e1c00941c0337d
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Sat Sep 14 09:46:50 2013 +0200
 
-    tm: backup xavps before running callbacks
-    
-    regular avps were being backupped, just not xavps.
-    
-    (cherry picked from commit e1f96b11379abd60fd53c49a376f6cf3cb1fc69d)
+    tm: readme regenerated
 
-commit 3ed4a1b4d29b7ab2eac4d40d3efbf6a3e00efe4f
-Author: Alex Hermann <alex at speakup.nl>
-Date:   Fri Oct 10 11:06:43 2014 +0200
+commit f328b864418020b1e166b13804fe173110500d75
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Sat Sep 14 09:46:23 2013 +0200
 
-    core: fork_*_utimer()'s interval is in microseconds
-    
-    Sync comments with code and function names
-    
-    (cherry picked from commit e2596876b830783de88934d45c9c5563ba2c3577)
+    tm: added missing documentation for t_check_status()
 
-commit 2a0fab2d66b299cb6003cead79a986324d16560d
-Author: Alex Hermann <alex at speakup.nl>
-Date:   Thu Oct 9 17:54:20 2014 +0200
+commit 6a51d9e87ac2e51a3c0473e11b3347739ec33dd8
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Fri Sep 13 13:47:00 2013 +0200
 
-    core: time_t is unsigned, handle integer underflow correctly
-    
-    When the processing of the timer code takes longer than the interval, don't
-    sleep for 4Gs.
-    
-    (cherry picked from commit 8adcf8f0e3ba2fa969583f6630dbd9e3aaecfcac)
+    textops: free result of subst transformation when is larger than target buffer
 
-commit 0c7df3a8375ee3dba52e42c098d70c54e779183c
-Author: Alex Hermann <alex at speakup.nl>
-Date:   Thu Oct 2 16:33:26 2014 +0200
+commit 56d02f02627bb1d2eca7befaaefbed17ced1f52f
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Fri Sep 13 11:08:48 2013 +0200
 
-    tm: remove dead code
-    
-    (cherry picked from commit 3d24997fd1ba34bd4e426656b1533530718008a0)
+    usrloc: fixed xml tags and regenerated readme
 
-commit 50c60c511259bff8c8e782f949547a9f0967c5c6
-Author: Alex Hermann <alex at speakup.nl>
-Date:   Thu Oct 2 16:46:23 2014 +0200
+commit 605360798fbad43cbd3ef1aca3ae76cd9c95c50f
+Author: Vitaliy Aleksandrov <vitalik.voip at gmail.com>
+Date:   Fri Sep 13 11:05:07 2013 +0200
 
-    tm: log an error message as error, not debug
-    
-    (cherry picked from commit 54f19e018a1a569b532555311505d4962de49bd7)
+    usrloc: update connection id for registration refresh
 
-commit 579c53be3fd6ad7cd8e90e56fb703084f5b94a78
-Author: Alex Hermann <alex at speakup.nl>
-Date:   Tue Oct 14 11:39:12 2014 +0200
+commit f3190358e02141c98304c4c0019bba95490da32c
+Author: Peter Dunkley <peter.dunkley at crocodilertc.net>
+Date:   Thu Sep 12 22:54:35 2013 +0100
 
-    dmq: unlock in failure path in build_notification_body()
+    pkg/kamailio/centos: moved stun from it's own RPM to the main RPM
     
-    (cherry picked from commit 5f05db99979e6c74d8303437d6c422478a1fbc7c)
+    - stun no longer has external dependencies and doesn't need to be in its own
+      RPM
 
-commit b4c2800ced527f056dd907efe4b0987e94689ce8
-Author: Alex Hermann <alex at speakup.nl>
-Date:   Tue Oct 14 11:38:36 2014 +0200
+commit 291d6ece47d164d64487c8545de87c64fdc31718
+Author: Peter Dunkley <peter.dunkley at crocodilertc.net>
+Date:   Thu Sep 12 22:41:37 2013 +0100
 
-    dmq: handle failure to build callback parameter
-    
-    (cherry picked from commit e98c601c43edbfbf7b389e04e9fb16839577ef5a)
+    Makefiles: moved stun to the standard module group now that it has no external dependencies
 
-commit 2109a705b4ccabca6642d00121e7253f0a2a661e
-Author: Alex Hermann <alex at speakup.nl>
-Date:   Mon Oct 20 22:35:59 2014 +0200
+commit 42722f3e70d3316b7c6881907b626b02303d58a6
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Thu Sep 12 16:36:28 2013 +0100
 
-    dmq: check if dmq socket exists
-    
-    (cherry picked from commit c6d2480efd95336ae34a2fb732dd4cb62ac89cbb)
+    modules/stun: removed dependency on OpenSSL
 
-commit 9cc499e8350ee8f37dfb844c02497d7233e146d1
-Author: Alex Hermann <alex at speakup.nl>
-Date:   Fri Aug 22 15:56:22 2014 +0200
+commit 0d0c4cc11022a62edfcf5041b36fe4cf5ca95a4d
+Merge: 5651be2 6cea922
+Author: Carsten Bock <Carsten.Bock at silentcircle-llc.com>
+Date:   Thu Sep 12 17:16:09 2013 +0200
 
-    mi_datagram: Send error response on out-of-memory
+    Added support for HTTP-Post to utils: http_query
     
-    (cherry picked from commit 902a77af1501f78fcc1205a37a5307e1d300f301)
+    Merge branch 'carstenbock/utils_post'
 
-commit 293d7cb86bc1c59ede155dfbcf8627ccfcbc1710
-Author: Alex Hermann <alex at speakup.nl>
-Date:   Fri Aug 22 15:16:00 2014 +0200
+commit 5651be2fa5a5d923a89aa70a050d23bcbfda9c38
+Author: Peter Dunkley <peter.dunkley at crocodilertc.net>
+Date:   Wed Sep 11 13:09:31 2013 +0100
 
-    core: Document the right type for 'str*' in the RPC interface
+    pkg/kamailio/centos: CentOS build updates
     
-    (cherry picked from commit a4eacbb469909978b7a9eff8767dcbdd5110ee99)
+    - CentOS .spec is now separate from Fedora .spec. This is because I no
+      longer have a Fedora system to test/maintain this on. Old .spec with
+      Fedora support is in pkg/kamailio/fedora and can be taken on by
+      someone else if needed.
+    - Updated rel in .spec to dev8
 
-commit a7ab7030ea0f5afb08009985a245e1499e1f8517
-Author: Alex Hermann <alex at speakup.nl>
-Date:   Tue Aug 19 12:36:23 2014 +0200
+commit 0f7bc9da0d132720531f3176ee216466f5877146
+Author: Peter Dunkley <peter.dunkley at crocodilertc.net>
+Date:   Wed Sep 11 11:30:50 2013 +0100
 
-    core: sip_msg_shm_clone: clone parsed maxforwards value in shm
-    
-    maxfwd module modified the msg buf directly instead of adding a lump. In
-    addition it is filling the parsed value of the header field.
-    
-    Clone this field into shm so later code can at least determine if the msg
-    has been mangled so it can retreive the original value of the header.
-    
-    (cherry picked from commit 42f506c08073c5f8ca84f1f12ea9e6c820f162d8)
+    core: Raspberry-pi builds now work without needing to specify extra flags
 
-commit ae01e2ed5e7decace416fefbfd64073ffd3d62ac
-Author: Alex Hermann <alex at speakup.nl>
-Date:   Mon Oct 20 15:38:51 2014 +0200
+commit 6f17209a70e84d91976ea42b476ae248b9b37501
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Tue Sep 10 14:14:52 2013 +0200
 
-    kcore: print_rr_body: return number of printed Record-Route bodies
-    
-    Act like the documentation, return the number of printed RR bodies, not the
-    total number of RR bodies.
+    kamdbctl: added missing dbuid tables group creation
     
-    (cherry picked from commit aa4fabe05dd3b6dc841325fe279596293d327a92)
+    - patch by elactrum [at] jamailca.com
 
-commit d68066614211d1a406c0c12f11ce907340e42255
-Author: Alex Hermann <alex at speakup.nl>
-Date:   Mon Oct 20 15:38:11 2014 +0200
+commit abf0026782c0ba4643feb25ded022e8c12725584
+Author: Victor Seva <linuxmaniac at torreviejawireless.org>
+Date:   Mon Sep 9 16:52:47 2013 +0200
 
-    tm: Fix setting flags for record-route headers
-    
-    The flags where set in add_uac() by counting the number of record-route
-    headers added by prepare_new_uac(). The latter function backups and
-    restores the list of lumps, so add_uac() only sees the original list,
-    which is not what has happened on the branch being handled.
-    
-    Moving setting the flags into prepare_new_uac() fixes this.
-    
-    This fixed the dialog module, which has to remove the correct number
-    of RR headers from the callee's routeset (which it does based on the
-    tm flags).
+    uac_redirect: get_redirect() check reason value before using it.
     
-    (cherry picked from commit ee9b78709516b935e087b0efcb620c13aad1a740)
+    This fix a core dump when get_redirects() config fuction is called with just
+    the one parameter.
 
-commit 2f465eccc23ce472daa709322809e863b3702f16
-Author: Luis Azedo <luis at 2600hz.com>
-Date:   Mon Nov 10 13:35:53 2014 +0000
+commit 774752e4d12bd03f01362af55a5e422eade690b2
+Author: Carsten Bock <carsten at ng-voice.com>
+Date:   Thu Sep 5 19:10:15 2013 +0200
 
-    Revert "kazoo : remove dependencies"
+    Another Fix for the ims_charging Module:
+    - Use P-Asserted-Identity instead of From-Header
     
-    This reverts commit 1630ec25958bda98a98864cbef57000dab8f2aeb.
-
-commit 1630ec25958bda98a98864cbef57000dab8f2aeb
-Author: Luis Azedo <luis at 2600hz.com>
-Date:   Mon Nov 10 13:25:30 2014 +0000
-
-    kazoo : remove dependencies
-
-commit 9a2d304f961d87d70ad6d27e85c3dac6d05f2a01
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Thu Nov 6 19:05:48 2014 +0100
-
-    pkg/kamailio/deb: add kazoo module package
+    fixed by Carlos Ruiz Díaz (carlos at ng-voice.com)
 
-commit 8eea9aa8faafd5a248a00caaba43379fc7b52423
+commit 6dc04484e39ceab4887b375d2510f35892d695eb
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Nov 5 14:29:34 2014 +0100
+Date:   Thu Sep 5 11:54:03 2013 +0200
 
-    json: unreference the json object in json_get_field()
+    acc: for time_mode=1, save timestamp in time_attr and microsecs in time_exten
     
-    - the parsed json object has to be freed
-    - reported by dongwflj at 163.com
-    
-    (cherry picked from commit def8d2600422a442b971c204df98594b0dfdaacd)
+    - database records stores time as datetime value
+    - new parameter time_exten to allow customization of attribute name
 
-commit bcfd43b42eb8115d7698201250a15f5ddd82b4c9
+commit 367a0e72be1d5e5de0fa84ca2a8d11f7d5b54abe
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Nov 5 14:04:33 2014 +0100
+Date:   Thu Sep 5 11:08:17 2013 +0200
 
-    mqueue: elaborated the docs for mq_size() to reflect return codes
-    
-    (cherry picked from commit cf9303b8063e77426e0506bed09577fe7a584fb1)
+    acc: fixed c&p typo of parameter name in docs
 
-commit 281c668b5e3a0ef9f7edde2bbea6b81201bd00b0
+commit a722cee262664162f183e00788c2d53c4c98b217
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Nov 5 13:59:53 2014 +0100
+Date:   Thu Sep 5 10:04:57 2013 +0200
 
-    mqueue: fix mq_size() not to return 0
-    
-    - return 0 for a config function is considered 'exit' by interpreter
-    - if size of the queue is 0, the function return -1
-    - for other error cases, the return code was decremented by 1
-    
-    (cherry picked from commit bde57b53386e792651b5ac86ea32d16ab721a07c)
+    kamctl: added scripts to define table acc_cdrs
 
-commit 3ddda387934842542c2952ee912db55ba91f1c0e
+commit b91f07fce16f5feb0c31f7af59ab9351e274221f
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Nov 4 10:20:46 2014 +0100
+Date:   Thu Sep 5 10:04:14 2013 +0200
 
-    benchmark: sync'ed log level values in documentation
-    
-    (cherry picked from commit 61ab723bb46f46f9013587e26ee07f39e5388ff8)
+    lib/srdb1: added id for definition of column start_time in acc_cdrs table
 
-commit aeb98d3deae7a551f11a6bb947378da7448e11fe
+commit dd3c6f19c18cf0c2844f2b2ce155e3f5d7af447a
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Nov 3 18:41:01 2014 +0100
+Date:   Thu Sep 5 10:02:01 2013 +0200
 
-    uac: use transaction to propagate uac_auth() flag
-    
-    - needed by dialog to increase the cseq
-    - local request is no longer accessible at forwarding callback
-    
-    (cherry picked from commit 952227ef749da464c7990fa7f056764daf4bda0d)
+    lib/srdb1: initial db schema for acc_cdrs table
 
-commit e82f1b2c3ab45472fcabf0ed4053d8ecc057d0ca
+commit 9b44e4b48862947f2ea634c6dd611ce7c07546a2
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Oct 31 12:35:56 2014 +0100
+Date:   Wed Sep 4 22:59:13 2013 +0200
 
-    dialog: increase local cseq after REFER generated by dlg_bridge
-    
-    - otherwise the next BYE can be rejected
+    registrar: reset r-uri pointer after backup in lookup_branches()
     
-    (cherry picked from commit c76ee9facb771d2eae792214e6d4cef39c94a9eb)
+    - otherwise can be invalidated by next branch lookup
 
-commit 4aea47fa023b705947af1bff747745cf105a64bf
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Oct 31 12:33:38 2014 +0100
+commit 37e63951b2b05875f07a1d30b8352e3f10a99072
+Author: Carsten Bock <carsten at ng-voice.com>
+Date:   Wed Sep 4 18:20:20 2013 +0200
 
-    tm: update headers shortcuts if buffer rebuilt after event_route[tm:local-requests]
+    Bug-Fixes:
+    - Use P-Asserted-Identity instead of From-Header as User in CCR
+    - Store RURI in the ro_session structure (it may have been changed by an Application-Server)
     
-    - affecting transactions for local generated requests
-    - bulding local ACK uses the shortcuts and they ended up being broken
-    - reported by Kristian F. Høgh
-    
-    (cherry picked from commit b6d3dc61a78e549c9a75ddfa2fbb86aa2a1682c5)
+    Fixed by: Carlos Ruiz Díaz (carlos at ng-voice.com)
 
-commit 4f74bfc615ce29088762eed7e41873fd07c4d2d0
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Oct 31 11:09:53 2014 +0100
+commit 96c85efbc40a6d0571e8122cbad30410d2274b24
+Author: Carsten Bock <carsten at ng-voice.com>
+Date:   Wed Sep 4 14:27:47 2013 +0200
 
-    main.c: fix compile warning
-    
-    (cherry picked from commit e4f18cb322d54035fb6825df3a2f712ed03a71db)
+    Initial structure for the docs of the IMS-Charging module (incomplete)
 
-commit bf78e8498a9ac9441fcdb7141b0cf2a7b8739e83
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Oct 31 00:31:11 2014 +0100
+commit 20399521b7df9e808f0999275132cc5460a0104b
+Author: Carsten Bock <carsten at ng-voice.com>
+Date:   Wed Sep 4 14:00:01 2013 +0200
 
-    tm: do all the clean local msg structure in one place
-    
-    - uri/dst-uri were clened before the entire local sip message, not being
-      visible while rebuilding the content
-    
-    (cherry picked from commit a2252afe90e0acd779e64c47eacc174b4bbdc41c)
+    add IMS-Charging to Makefile.groups
 
-commit 7b220da5d06b316617e33d04e5cdc481672e5e83
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Oct 30 22:29:01 2014 +0100
+commit 29cb7be4445995f73e9f425d99c9c5ee818c92de
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed Sep 4 12:04:18 2013 +0100
 
-    pipelimit: update the limit of pipe for pl_check(pipeid, alg, limit)
+    modules/rtpproxy-ng: Allow PV in second rtpproxy_manage parameter
     
-    - affects the dynamic pipes that could have been created by same
-      function on a previous execution, allowing to be on-the-fly updated
-    - reported by Alex Balashov
-    
-    (cherry picked from commit 280f947eac5c66bfa6151c75983ffa9e533dd709)
+    - Incorrect fixup function caused a crash when the second parameter was given
 
-commit 34c82570c23a0d133c82483bfd9425eb9a65b06e
+commit 362d374a61953aee3cf9f96eadaef63c5f22763e
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Oct 30 20:47:42 2014 +0100
+Date:   Wed Sep 4 13:04:23 2013 +0200
 
-    rr: dont set msg flag FL_RR_ADDED for record_route() in branch_route
-    
-    - the operation is specific only for the branch
+    topoh: safety check for missing To header
     
-    (cherry picked from commit 58ad681ab68a14e8fe2b0f6ebc6cf03bdabeea80)
+    - based on a patch by Michel de Weerd, FS#303
 
-commit 631e558f97728b91b3c0b3341c6c4ecc16902a82
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Oct 30 11:41:41 2014 +0100
+commit acbbae2af3cb2ad1a5b07a7305c5f9761bc78389
+Author: Jason Penton <jason.penton at smilecoms.com>
+Date:   Wed Sep 4 12:52:16 2013 +0200
 
-    tm: safety catch inside t_check_trans() when already in a tm routing block
-    
-    - transaction is known and some of these routing blocks are inside tm
-      lock, which can result in deadlock if not tested
-    - reported by Andrew Pogrebennyk, FS#482
-    
-    (cherry picked from commit a8d50919bd614b704f3a4e08ff90d844b2c29829)
+    modules/ims_charging: new module for IMS charging
+    	- currently supports Ro interface
 
-commit b5ead3683782495da208fad2dffef61f893371b3
+commit 7abd496560c6274680d451f49355ad1f6a14a6a7
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Oct 30 10:23:51 2014 +0100
+Date:   Wed Sep 4 12:33:45 2013 +0200
 
-    sqlops: use row index for storing result of sql_pvquery()
-    
-    - reported by Savolainen Dmitri, FS#487
+    db_postgres: use variable for make tool in module Makefile
     
-    (cherry picked from commit 367840503010d1be0da23e79525f2f88eb09ebcf)
+    - fixes builds in BSD systems
+    - patch by Victor (coyote), FS#335
 
-commit 3209d2245cbc3d2def94065aed0ccdab23678a64
+commit 2aa5095252f9434c7c2a63ecb130bdaf1346fde9
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Oct 30 10:10:15 2014 +0100
+Date:   Wed Sep 4 11:44:23 2013 +0200
 
-    htable: safety check for key type and value
-    
-    - reported by FS#486
-    
-    (cherry picked from commit f5d9b59ee5aabb1da934ae2ce8101250041c05d1)
-
-commit 7d31ee740c49034f83192feffdcba2f7b8601fab
-Author: Hugh Waite <hugh.waite at acision.com>
-Date:   Wed Oct 29 16:18:28 2014 +0000
-
-    registrar: Prevent incorrect application of path when forwarding a register
-    
-    - Reset the internal path pointer after a save() to prevent it being added
-      as a Route: header, e.g. when running t_replicate()
-    
-    (cherry picked from commit 61a1eee4fe2b7e3a7c6a8f82c86ac52957439053)
-
-commit e968d72f51787f53b154c2cbc614188e60d8f9fb
-Author: Hugh Waite <hugh.waite at acision.com>
-Date:   Mon Oct 20 15:02:59 2014 +0100
-
-    sdpops/documentation: Add id's to function sections
-    
-    (cherry picked from commit 69cd679496c482aabd17f2c7fbde7a5282864308)
+    rtpproxy: updated rtpproxy_manage() to handle PRACKs with sdp
 
-commit 49c39a3b2409636d1360d943e6785a34002c9009
-Author: Hugh Waite <hugh.waite at acision.com>
-Date:   Wed Oct 8 21:11:55 2014 +0100
+commit 72996942662b944b74e6632e1670c989402bf8af
+Author: Vitaliy Aleksandrov <vitalik.voip at gmail.com>
+Date:   Wed Sep 4 09:56:28 2013 +0200
 
-    core/parser: Fix extract_sendrecv_mode to always return mode if valid
+    usrloc: detect lost tcp connnections on timer and set associated contact as expired
     
-    - All four sendrecv directions return 0
-    - is_on_hold flag set for inactive and sendonly
-    
-    (cherry picked from commit 0a019df8f2922a940a41742ce0e4560bb6523d6c)
+    - new module parameter to control this feature: handle_lost_tcp
+    - at this moment it is not implemented for db only mode
 
-commit d503b1159af85ae17667ae943a515c3e9700c276
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Tue Oct 28 17:26:43 2014 +0200
+commit 392a59ab1c12efee1072581f9519fc258444d086
+Author: Vitaliy Aleksandrov <vitalik.voip at gmail.com>
+Date:   Wed Sep 4 09:55:23 2013 +0200
 
-    modules/dialog_ng: prevent seg fault if socket struct is null
-    
-    (cherry picked from commit de369d4b466078c4c5aada0fc55d9689b2d13047)
+    registrar: propagate tcp connection id in contact info structure
 
-commit 96d3484b8f381be96162af94eb4afa5b9d110e3b
-Author: lucian balanceanu <lucian.balanceanu at 1and1.ro>
-Date:   Fri Oct 24 17:29:35 2014 +0300
+commit ea45a9b0ff6851d01e09aa62dfe9e7e006552609
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Tue Sep 3 23:16:50 2013 +0200
 
-    cr: fix some cr kamctl fifo problems
-    
-    - initialize builtin structures with appropiate values
-    
-    (cherry picked from commit 22d125e3b73688b227a951dce1ce12b4c798229a)
+    pua: basic framework for handling xcap-diff event
 
-commit c059fd51289945f34cfd38ad478e5ca62ad5c78c
-Author: lucian balanceanu <lucian.balanceanu at 1and1.ro>
-Date:   Fri Oct 24 17:12:34 2014 +0300
+commit 0c15125767f8a9001e9c892fee18df3dbad56d2f
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Tue Sep 3 23:15:55 2013 +0200
 
-    cr: decreased logging severity of some messages
-    
-    - moved some informative messages from ERR to INFO, DBG
+    presence_xml: basic framework for handling xcap-diff event
     
-    (cherry picked from commit 2a57414fd952f36f88b1ab2dc038934a8ddf6d64)
+    = can be diabled via modparam disable_xcapdiff
 
-commit 8c52d68aa4cf432f693a4e7eff9e56da251423f0
+commit 70ec02cfc9a203ea100d6550be3aa5f51f4fa473
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Oct 21 16:32:26 2014 +0200
+Date:   Tue Sep 3 16:16:30 2013 +0200
 
-    tls: note that SSLv3 should not be used if high security is needed
+    acc: option to write dialog-based cdrs to database
     
-    - the note was already for SSLv2
-    
-    (cherry picked from commit 5fe0d14745303c61d3fafe9decbb735d5424a442)
+    - new module parameter cdrs_table has to be set and classic db
+      accounting enabled at compile time and db_url set
+    - cdr_log_enable - new parameter to turn off writing cdrs to syslog,
+      cdr_enable being now used as top level control flag for both cdrs to
+      syslog or db
 
-commit adc3d44f70f2c79bfeea95b1336798ce227d8170
-Author: Olle E. Johansson <oej at edvina.net>
-Date:   Tue Oct 14 09:25:12 2014 +0200
+commit 4812b91a3c00e71a3ac9636b88bc75e5368fa657
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Tue Sep 3 15:11:47 2013 +0200
 
-    test/unit: Add Sipsak URL in README
-    
-    (cherry picked from commit c2180873931408e7ff35e826f82505a7a99167e6)
+    acc: increment crt position when adding extra time value
 
-commit a0cadc6c6a435b43545d28f1ecc7c01240db0f16
+commit 4c917438596852b3870ce0236bad8cbd04961270
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Oct 13 23:50:21 2014 +0200
+Date:   Tue Sep 3 14:31:58 2013 +0200
 
-    test/unit: updates to units 27, 28, 29, 31 ane 33
-    
-    - parametrizied 11.cfg
-    
-    (cherry picked from commit 4d898e9391ff4990eb5ce2319c9a5ca7d66d98b4)
+    Makefiles.defs: version set to 4.1.0-dev8
 
-commit 3987ba284a09a71ed6a1f266867414ddcaf4953a
+commit ea6514c2af00561643af6a2b671fbd4411048ca1
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Oct 13 22:49:38 2014 +0200
+Date:   Tue Sep 3 13:47:24 2013 +0200
 
-    test/unit: sipsak listed as dependency in readme
-    
-    (cherry picked from commit dad6e668c3839bafb20fcee31fdd35a1ce7ceac7)
-    
-    Conflicts:
-    	test/unit/README
+    acc: updated readme with the new parameters
 
-commit 2b4bb3e0153cd951d3559382185382a838f3a728
+commit ede2d6747aabf32538797dfedf13682c5c242831
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Oct 13 22:47:28 2014 +0200
+Date:   Tue Sep 3 13:35:08 2013 +0200
 
-    test/unit: updated unit 25.sh
-    
-    (cherry picked from commit 66b93da82ed075c0a4d9d6b1e5f93932432a1aee)
+    acc: cast to double for safer conversion in time_mode==2
 
-commit fcc470429bf5dfee411cca052db424c29002499c
+commit d7884500e89d32bffd34e915b473458645c6dedf
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Oct 13 22:35:07 2014 +0200
+Date:   Tue Sep 3 13:28:54 2013 +0200
 
-    test/unit: updates to unit 22
+    acc: new parameter time_mode
     
-    (cherry picked from commit 6f476de8d0e658c148328ace7f0f27f0574fb52e)
+    - store additional time value in time_attr attribute/db column
+    - if time_mode==1, then time_attr stores the microseconds
+    - if time_mode==2, then time_attr store the seconds.miliseconds
+      (proposed by FS#163)
+    - if time_mode==0 (default), then it is like now, only timestamp stored
+    - time_attr value can be set via parameter with same name - it
+      represents syslog value or db table column
+    - for db accounting, when time_mode==1, the type of column has to be
+      int, and for time_mode==2, the type of column has to be double
+    - features implemented only for syslog and db accounting
 
-commit 97cab82e1217776b248a424b6d0ee6aaf9b092de
+commit 1cec15e057bdec4455e70af951def19e36a78e8e
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Oct 29 12:07:57 2014 +0100
+Date:   Mon Sep 2 14:09:18 2013 +0200
 
-    dialog: fixed adding contact header to REFER generated by dlg_bridge
+    kamctl: added commands to set extra columns in subscriber table
     
-    - reported by Paul Smith
-    
-    (cherry picked from commit ab7519006b6a53792d66b6903a4b0694083179b6)
+    - useful to deal with columns added for load_credentials of auth_db
+      module
+    - 'sets' - sets a column with string value
+    - 'setn' - sets a column with numeric value
 
-commit 7d6ad74fece3cb038ce3c8c3e82bd7380bfca3fa
-Author: Elena-Ramona Modroiu <ramona at asipto.com>
-Date:   Tue Oct 28 11:41:47 2014 +0100
+commit 7e44ff0be6cbb48c9360bee8601ec3dbff050c02
+Author: Carlos Ruiz Diaz <carlos.ruizdiaz at gmail.com>
+Date:   Sun Sep 1 19:56:57 2013 -0400
 
-    htable: set str shortcut to iterator name
-    
-    - intended for optimization of iterator search by name
-    (cherry picked from commit 583c705374c9e1da7817bf204b3da225c784e54a)
+    Fixed potential bug in exceptional condition when max-time updated is called
 
-commit c46df63add89b5840759fef0137b110fe7c971f2
+commit 2685cd9bb6933c2d4b4b97e3b4ed6b98005255c9
 Author: Juha Heinanen <jh at tutpro.com>
-Date:   Sun Oct 26 19:11:28 2014 +0200
+Date:   Thu Aug 29 17:05:41 2013 +0300
 
-    modules/tmx: downgraded info message to debug message
-    - INFO: tmx [t_var.c:738]: pv_get_t_branch(): branch flags is [32768]
-    (cherry picked from commit b3635962175dae2ba4d2df3e056248d08f0f6ad1)
+    parser/fline.c: syslog message cleanup when request line parsing fails
 
-commit 8107f39a866817e12dcd5ef5a95dc562fcf121a2
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sun Oct 26 16:32:13 2014 +0100
+commit fbcee0221cd6e22477dc9d1d5a7767c1e572235a
+Author: Richard Fuchs <rfuchs at sipwise.com>
+Date:   Wed Aug 28 15:03:01 2013 -0400
 
-    textops: include sdp_helpr_funcs.h to get rid of compile warning
+    rtpproxy-ng: fix possible segfault in rtpproxy_manage
     
-    - needed for use of get_mixed_part_delimiter()
-    - reported by Juha Heinanen
-    (cherry picked from commit 8608da35d224c70d2bd8cfc728f3d07e1ea7a3ce)
+    Reported by Hugh Waite
 
-commit 7a6e87eea35a9599d5a52d2cbf5f7dd8362e067c
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Fri Oct 24 11:48:53 2014 +0200
+commit e0e0a753d1365d340c17f33bd868085bee304910
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Wed Aug 28 12:02:34 2013 +0200
 
-    textops: fix append_body_part
-    
-    append was adding double '--' to the delimiter
-    
-    (cherry picked from commit e71c7f014f1217cb4431f2644e8c4c32cc6544f2)
+    dialog: fixed typo related to module name inside log message
 
-commit 324e085a2f982120a075befb6ef420ca0b2fac75
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Oct 23 00:54:59 2014 +0200
+commit bf68c071723bda24b07e64660f77872e2bceff1b
+Author: Victor Seva <linuxmaniac at torreviejawireless.org>
+Date:   Tue Aug 27 18:43:39 2013 +0200
 
-    async: fixed typo in docs and adjusted example
+    permissions: fix ws support on allow_trusted function.
     
-    (cherry picked from commit 46f3342428cd52fb01756c696e4e0f44199109da)
+    Thanks to Alex Hermann <alex at speakup.nl>
+    Reminder: Never commit with more than one glass of wine.
 
-commit 6649d9809ed6e527aaef45bb7a137c49e3d9d3de
+commit 14835f89fc2b761f73a0caad67d229ec3fedba29
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Oct 22 19:14:03 2014 +0200
+Date:   Tue Aug 27 14:44:17 2013 +0200
 
-    uac: proper set of enabled/disabled flag for reg reocrds via rpc
-    
-    - patch by Savolainen Dmitri, FS#483
+    core: set to-params pointer to null after freeing
     
-    (cherry picked from commit da844d7cc76e4db3b4bb2d9e5ba62cdfb394b110)
+    - avoid potential double freeing issues or invalid pointer access
 
-commit 2c7374e3b671546355f5d546f0555e2fc65ace3f
+commit 727aa357d9ee8abcb8471733e22886d2cff386db
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Oct 22 19:08:25 2014 +0200
+Date:   Tue Aug 27 14:00:17 2013 +0200
 
-    uac: release lock when listing records via rpc
+    kamdbctl: new command add-tables
     
-    - patch by Savolainen Dmitri, FS#484
-    
-    (cherry picked from commit f63865041136aec65e2f7824967a702b23191364)
+    - creates only tables that are groupped under same id, thus have the sql
+      script in a file
+    - syntax: kamdbctl add-tables <gid>
+    - there has to be a <gid>-create.sql script
+    - eg: kamdbctl add-tables lcr
 
-commit 800a84c203a5a22236514bddfdc1762debfc5a14
+commit a075383454c92bed225b7904920090f515a938d5
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Oct 22 19:01:32 2014 +0200
+Date:   Tue Aug 27 11:16:52 2013 +0200
 
-    uac: set hash ids for record refresh command
-    
-    - reported by Savolainen Dmitri, FS#485
+    kamctl: use FIFOPATH instead of OSER_FIFO in kamctlrc
     
-    (cherry picked from commit 148c03b35ae3489910a02ba530441862b805be65)
+    - no longer relation to former project name, however OSER_FIFO can still
+      be set to keep the compatibility with older deployemnts, but will be
+      used only when FIFOPATH is not explicitely set
 
-commit 438f8838a23646d99c5c119c3719e18d79d1b402
+commit 8097c2bccb2161f63900bbd5fb87a10eacdd282c
 Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Mon Oct 20 13:07:41 2014 +0200
+Date:   Tue Aug 27 00:07:58 2013 +0200
 
-    pkg/kamailio/deb: Add kazoo module to kamailio-extra-modules
-    
-    (cherry picked from commit 3869b9d6eac5af5120bc275201d6c04e7596d929)
+    permissions: update allow_trusted documentation.
 
-commit dc4ce76cc54ba58006fac6f4eec5084fdaff4a3b
-Author: Luis Azedo <luis at 2600hz.com>
-Date:   Tue Oct 21 18:35:03 2014 +0100
+commit 573c9031a44168df356818f572f10f69791a1458
+Author: Victor Seva <linuxmaniac at torreviejawireless.org>
+Date:   Tue Aug 27 00:03:49 2013 +0200
 
-    kazoo : compatibility issues with json-c & rabbitmq recent versions
+    permissions: fix ws support on allow_trusted function.
 
-commit 6d89d2328a375a6660e46a5031d66b16e05d0efb
+commit b2a536f0f577026ffa57d0b603c60e6232bc8e78
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Oct 17 09:42:13 2014 +0200
+Date:   Fri Aug 23 21:04:06 2013 +0200
 
-    pipelimit: enhanced docs for pl_check() function
-    
-    - documented the algorithm and limit parameters
-    
-    (cherry picked from commit 24e76b1932fa8c4e1136ad82cb582a97c50244c4)
+    tm: readme regenerated
 
-commit f78361d777c20436641bf16a024f12e6a8f3ed7f
+commit ef9b69bbb54302e9985dd37d79831b6f80463fc1
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Oct 17 09:40:33 2014 +0200
+Date:   Fri Aug 23 21:03:13 2013 +0200
 
-    pipelimit: fix dynamic pipe limit check
-    
-    - proper add and check at the same time
-    
-    (cherry picked from commit b76afe7c0699b936bec3d7bb1c3a740bf08fdb1c)
-
-
-===================== 2014-10-16 Version 4.2.0 Released =====================
+    tm: removed note about no-implentation for no-reply flag for t_relay_to()
 
-===================== Changes Since Version 4.1.0 ===========================
-
-commit f73862c80d27abdcebb2a8e931d0dd16c3aa8e02
+commit 6073949aa224ea7a973058891a88a58cc0841860
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Oct 16 14:34:51 2014 +0200
+Date:   Fri Aug 23 21:02:24 2013 +0200
 
-    Makefile.defs: version set to 4.2.0
+    tm: updated xml docs with t_set_disable_internal_reply()
 
-commit 33813b2057a73c64362e26473ac64a6501c5d7c7
+commit 0f2f9c85eff0b6ad35b4c58dfcde74c8a65559d6
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Oct 16 14:32:33 2014 +0200
+Date:   Fri Aug 23 20:53:55 2013 +0200
 
-    pkg/deb: version set to 4.2.0 in specs
+    tm: re-added the option for no-internal reply on error
+    
+    - new function t_set_disable_internal_reply(0|1) to disable|enable this
+      option per transaction
+    - t_relay_to() flags re-enabled for this option
 
-commit a6ca57d60df230aa3d334a1276bbfba2cfdd29a1
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Oct 16 14:27:54 2014 +0200
+commit 7255693f73bae008e5c7b6b560c52394f7c85308
+Author: Carsten Bock <carsten at ng-voice.com>
+Date:   Fri Aug 23 17:29:43 2013 +0200
 
-    pkg/rpm: set version to 4.2.0 in specs
+    Very basic DNS-Zone file-example for IMS (for use in the online-tutorial on howto install IMS with Kamailio)
 
-commit d353917c9e880da60282e39cb8c5c06193f6e4c5
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Oct 16 10:19:22 2014 +0200
+commit 6cea9227c7dc973757d03150685e322fcff115b9
+Author: Carsten Bock <carsten at ng-voice.com>
+Date:   Thu Aug 22 16:36:48 2013 +0200
 
-    ChangeLog: updates to content in preparation for 4.2.0 release
+    Define missing fixup_functions.
 
-commit 3948305d86f6211428f60c58e138b18aacb3dde5
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Oct 16 09:55:58 2014 +0200
+commit b23a74a4732f276315176d9b438bd2596e616799
+Author: Carsten Bock <carsten at ng-voice.com>
+Date:   Wed Aug 21 20:14:16 2013 +0200
 
-    pkg/rpm: updated values for memory size in specs
-    
-    (cherry picked from commit 22aef82dbc60f67dd606e568308114118de729a0)
+    Fix fixup functions.
 
-commit 39042d58ee0af46545c3d3bfbb68bbaa8f44dbcf
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Oct 16 09:55:10 2014 +0200
+commit 8017fa7c67dbb3dd4bdd937be9b841097a44674e
+Author: Carsten Bock <carsten at ng-voice.com>
+Date:   Wed Aug 21 20:02:23 2013 +0200
 
-    pkg/deb: updated default values for memory in init.d scripts
-    
-    (cherry picked from commit a8e3b9187ba14177add9b3550761b95fd7098911)
+    Add support for sending POST-Requests to http_query() method.
 
-commit 450eaed84907357626f84ded58ae04537a63507f
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Oct 16 01:06:09 2014 +0200
+commit 134158df11ebf9b6c3deaf71b6010588535eb386
+Author: Peter Dunkley <peter.dunkley at crocodilertc.net>
+Date:   Thu Aug 22 20:39:41 2013 +0100
 
-    textops: fix not initialized variable for muti-part body
-    
-    (cherry picked from commit f1178c4d0e12f7d7e05bd6551ec3a841f1f23055)
+    pkg/kamailio/(centos|fedora): Added rtpproxy-ng module to the build
 
-commit 78a5d5d1f1cb8c59b5ff64d7df9c6ecd1634fcf8
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Oct 16 01:03:54 2014 +0200
+commit c2ccd37891167fb691b2aabc44e12c45cea7d1da
+Merge: fd68623 dd76f37
+Author: Richard Fuchs <rfuchs at sipwise.com>
+Date:   Thu Aug 22 14:19:31 2013 -0400
 
-    dialog: proper de-serialization of expires value for a profile
+    rtpproxy-ng: adding module
     
-    (cherry picked from commit ab9d9a242ec60b820496794953610a84b303d2f3)
+    Merge branch 'rfuchs/rtpproxy-ng'
 
-commit 980bf253a9458180e7a34eefd9bc221b1744c0a6
+commit fd68623bebb7053f4b652d7fe58d676b6a019d7c
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Oct 16 00:58:27 2014 +0200
+Date:   Thu Aug 22 17:51:49 2013 +0200
 
-    htable: initialize the value for iterator list index
+    core: efectively run the event_route[core:receive-parse-error]
     
-    (cherry picked from commit 853bb22836c888b19edc9db00edb1df0c0be0554)
+    - reported by Juha Heinanen
 
-commit c07c94c3fe7809d4b0e4ec143d9e1ebef8a7cfc3
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Oct 16 00:57:29 2014 +0200
+commit 0efe5a4d9adb08575938d2c4eb83ec3a79d38e20
+Author: Carlos Ruiz Diaz <carlos.ruizdiaz at gmail.com>
+Date:   Thu Aug 22 11:16:31 2013 -0400
 
-    websocket: safety guard when computing the list of connections
+    Added support for max-time update of monitored calls
     
-    - avoid going further if connection is null -- unlikely to happen as len
-      of the list is computed before
-    
-    (cherry picked from commit 19e8a5618f86833995d17200267910e44471141d)
+    - updated example config file
+    - updated documentation
 
-commit d3ceeccfe0d5f65d173b910b4a43d3767fdce0b4
+commit 86bdfaa3efe7804bcfde3da4f63b252c74e417b7
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Oct 16 00:08:27 2014 +0200
+Date:   Thu Aug 22 15:44:05 2013 +0200
 
-    kamailio.cfg: overwrite log level name for cfgtrace
-    
-    - avoid mixing its messages with typical logs printed from code
+    core: fix condition to lookup envet_route[core:receive-parse-error]
     
-    (cherry picked from commit c3f57334976cd1b9741ea9336554c9ecfc3e014e)
+    - reported by Juha Heinanen
 
-commit f13e739c767ddfbaaddecc92b492bcf37970a2be
+commit 2d826efb7dbcf9b3b49c376bcd079ab1e7642a44
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Oct 16 00:03:22 2014 +0200
+Date:   Thu Aug 22 13:01:55 2013 +0200
 
-    corex: fix name in the example for send_data() function
+    core: execute event_route[core:receive-parse-error] block on error of initial sip message parsing
     
-    (cherry picked from commit 101af78891607fae2e63d5976c8e13b90334c03f)
+    - note that the SIP message is broken in this case, but it gets access
+      to source and local socket addresses (ip, port, proto, af) as well as
+      the whole message buffer and its size
 
-commit c8bf1d1ff7422e8e20410baffcc85c5ede58c482
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Oct 15 11:53:56 2014 +0200
+commit d03651fb4c3a6b50923029e121eed201fb1ff550
+Author: Juha Heinanen <jh at tutpro.com>
+Date:   Thu Aug 22 08:20:52 2013 +0300
 
-    evapi: fixed typo in the Makefile pkg-config search
+    modules/lcr: added some linefeed chars missing from syslog messages
     
-    (cherry picked from commit 9253db2075d53548ee8e2b99f41cb1747a9ad12e)
+    - Patch provided by Kevin Scott Adams.
 
-commit 5b7315b7c68aa5fe09cd91db0f85a7fd80d648ec
+commit 3ccf4b43e81bd2654cb306a3c2cc21b97cb51f62
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Oct 14 16:13:43 2014 +0200
+Date:   Thu Aug 22 00:14:53 2013 +0200
 
-    ndb_mongodb: fixed c&p typo for section id
+    core: print src address details if initial message parsing fails
     
-    (cherry picked from commit bd4233e1441b903e9893779962b681dbfc493a3b)
+    - reported by Juha Heinanen
 
-commit 83ea1bc5582391681dc8465052f53ad115ed2e00
+commit fe24ed17b0620bd9446d741ea3f65b7b0cb8b765
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Oct 14 14:46:30 2014 +0200
+Date:   Wed Aug 21 11:20:07 2013 +0200
 
-    doc/rpc_list: regenerated rpc commands lists
+    kamailio.cfg: use is_first_hop() for adding alias parameter to contact uri
     
-    (cherry picked from commit fa16440977eaa32ba7f1fd82d6c35daa40e27dd2)
+    - done for natted devices
 
-commit e6e65283abd41043e3188240d89cd8c7549daada
+commit bbecaa597aa4fb3fa08773cd6cd9b8558c7ce3a8
 Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Mon Oct 13 23:40:51 2014 +0200
+Date:   Wed Aug 21 11:04:08 2013 +0200
 
-    pkg/kamailio/deb: update version to 4.2.0~rc1
+    avpops: allow use of avps as second parameter on re operation at avp_check function
 
-commit 1103028d36259d1304b81deef15da44e8c1c7275
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Oct 13 18:03:04 2014 +0200
+commit c86b04459a716af353d0ca40a793d6b13c6a6fe7
+Author: Victor Seva <linuxmaniac at torreviejawireless.org>
+Date:   Tue Aug 20 10:24:53 2013 +0200
 
-    Makefile.defs: version set to 4.2.0-rc1
+    fixed spelling errors catched by lintian
 
-commit 432ac22171872d0d4a63180482fc4e4a894cb3df
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Oct 13 18:01:44 2014 +0200
+commit 64e39dbf89bc1581722abeaadf7811e0883390bd
+Author: Elena-Ramona Modroiu <ramona at asipto.com>
+Date:   Mon Aug 19 17:43:16 2013 +0200
 
-    tm: updated readme with default value for failure_reply_mode
-    
-    - addapted from master commit 469c150
+    htable: updated readme with rpc command htable.stats
 
-commit fca7a813f092f863a9063dd867011a9e603cf242
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Oct 13 13:23:17 2014 +0200
+commit d33106994516e27944657c3bf17c3ccb5a521a50
+Author: Elena-Ramona Modroiu <ramona at asipto.com>
+Date:   Mon Aug 19 17:39:26 2013 +0200
 
-    core: default size for shared memory is 64MB
-    
-    - decent size at least for 64b architecture where pointer overhead is
-      bigger
+    htbale: added rpc command htable.stats
     
-    (cherry picked from commit d3ce0717198cc0147c84c3526eb34468f847aad2)
+    - print stats about htables: name, number of slots, number of items, max
+      number of items per slot, min number of items per slot
 
-commit f24a05c221656eb004b45eddeddf06bfd1952278
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Oct 13 13:14:49 2014 +0200
+commit ee7dcac57501cd0563c69ae967ba785cec035062
+Author: Elena-Ramona Modroiu <ramona at asipto.com>
+Date:   Mon Aug 19 16:48:01 2013 +0200
 
-    tm: default value for failure_reply_mode set to 3
+    htable: lifted limit for max number of slots to 2^31
     
-    - discard previous replies if a new serial forking step is done
-    
-    (cherry picked from commit 8118c85bc53494c5a1d6e0a9fd655778f8ca8b61)
+    - there can be systems with large amount of memory
+    - clarification in docs about the case when the value is out of exected
+      range
 
-commit 20719de7755e85a75f6b10b28c58c81e6f46fa63
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Oct 13 13:10:33 2014 +0200
+commit 71594a81f012432782d1f7b6f59c725130928ee7
+Author: Jason Penton <jason.penton at smilecoms.com>
+Date:   Mon Aug 19 13:41:45 2013 +0200
 
-    core: pv print default buffer size set to 8kB
-    
-    (cherry picked from commit b1a8a624146056e38c725b70273174324dd134a4)
+    cdp: fixed spelling and removed some erroneous code
 
-commit ae897e06da2a5babee5f678a34ebda42654a6f0a
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Oct 13 13:07:17 2014 +0200
+commit ea442b3155bf25ff48f7fd125b2ffa72a5631852
+Author: Carsten Bock <carsten at ng-voice.com>
+Date:   Sun Aug 18 17:47:08 2013 +0200
 
-    core: default tcp read buffer size set to 16kB
-    
-    (cherry picked from commit eccc58969ca38b9eecd22a0d1ecccf440d9e8ec4)
+    Only update received info, if a contact is "new" contact. In case of multiple registration for one AoR, each registration will have a different contact.
 
-commit 5350c4e3479256a25ee3b6416a59a1484c63786f
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Oct 13 12:32:08 2014 +0200
+commit ec1c1bab23e4fff3bd5cd60c2f254e646dcbc9ee
+Author: Carsten Bock <carsten at ng-voice.com>
+Date:   Fri Aug 16 17:08:15 2013 +0200
 
-    pua_mi: removed empty sections from docs
-    
-    - updated title for mi commands sections to match indexing expected
-      value (reported by Juha Heinanen)
-    
-    (cherry picked from commit aaca5cc26960e52361bdfcc4e498908c39805207)
+    Do some debug output, when searching for user based on IP/Port/Proto.
 
-commit 2c3bdd64135a369de072747e087af97be7aacbab
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Oct 13 12:30:11 2014 +0200
+commit 157a466d46f6cccaf790ca3ad3d400489ebdd1ed
+Author: Peter Dunkley <peter.dunkley at crocodilertc.net>
+Date:   Wed Aug 14 21:30:45 2013 +0100
 
-    dispatcher: normalized section name for rpc commands in docs
-    
-    - easier for indexing
-    
-    (cherry picked from commit 45eae146d49a8e9bc55fe553815fa6739b8cebe6)
+    pkg/kamailio/(centos|fedora): Updated .spec
 
-commit 98826710632d0903f3aef7473582d239f584a542
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Oct 13 11:57:48 2014 +0200
+commit 9061cf2a85ac89cf403910b7b4fa93b29dccb350
+Author: Victor Seva <linuxmaniac at torreviejawireless.org>
+Date:   Tue Aug 13 11:45:02 2013 +0200
 
-    db_cluster: safey check to be sure the command is implemented by db connector
-    
-    - reported by Miguel Reis, FS#476
+    modules/debugger: refresh README
+
+commit 5cbedc6b515b50f9ade7457abedba18747d98f75
+Author: Victor Seva <linuxmaniac at torreviejawireless.org>
+Date:   Tue Aug 13 10:14:42 2013 +0200
+
+    modules/debugger: Added module parameter reset_msgid. Added RPC command dbg.reset_msgid
     
-    (cherry picked from commit d1541b8299581cdfaf84169e307f47116def5cbf)
+    The message id ($mi) will be reset but internally there is no change. This can be
+    useful for unit tests cases.
 
-commit d510ff69559934d9ab586fef3e6e9bad00cf0a8b
+commit b0e9132ccd1e8385b8b4faf72db806320d48e2f5
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Oct 13 11:34:40 2014 +0200
+Date:   Tue Aug 13 09:37:21 2013 +0200
 
-    uac: init avp_value lenght to be safe when avp is not found for restoring From/To URI
-    
-    - reported by Klaus Darilion, FS#479
-    
-    (cherry picked from commit a4432c327044e720d4a2ac388f7aa0692f36e873)
+    usrloc: safety checks to catch empty ruid
 
-commit f13a0d825b3b41eff5197c143f28b6d38e0b7132
+commit 66c8e730d59f9816f09573f5300e4463e5997876
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Oct 13 00:06:18 2014 +0200
+Date:   Tue Aug 13 09:19:02 2013 +0200
 
-    kamdbctl: search for greadlink first
-    
-    - bsd version of readlink is different than gnu version
+    usrloc: more verbose log messages in case of failure to update db records
+
+commit d1cda7ca9a64cf818b82f7b777fa2dd640717c53
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Mon Aug 12 11:15:55 2013 +0100
+
+    presence: Iterate correctly around presence updates
     
-    (cherry picked from commit ba1967df93fa9bcd39070c325f72081b5adf7748)
+    - timer_send_notify should increment the subset by one on each loop
 
-commit 8767ad287a3e60239e997bd27698299527703fb5
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Oct 13 00:05:24 2014 +0200
+commit 4f42993660c52c757918ca2806f7ffe6af0674ce
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Mon Aug 12 11:05:55 2013 +0100
 
-    kamctl: search for greadlink first
+    rls: Fix memory leak in rls notify.c
     
-    - bsd version of readlink is different than gnu version
+    - xml is leaked in an error case
+
+commit e88af0a02de79fac583c126f08d762f7ef3f1b01
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Tue Jul 16 10:51:29 2013 +0100
+
+    outbound: Fix freeing null pointer in destroy function
     
-    (cherry picked from commit b209f27df95ffb27ea8fef00a402f2a27b8871a7)
+    - Only appears in error cases, e.g. syntax check
+
+commit 0c590e00796573681fd7ee0a99dd324919a9e4e9
+Author: Dragos Dinu <dragos.dinu at 1and1.ro>
+Date:   Wed Aug 7 17:29:06 2013 +0300
 
-commit 4128e3cdd8e9bbc0f539b22b3c52c579625905cb
+    Fixed two bugs related to new capture_mode changes.
+
+commit 93c39f86ce0cd337212579bd7bd1e58cabed79ca
+Author: Carsten Bock <carsten at ng-voice.com>
+Date:   Wed Aug 7 01:20:43 2013 +0200
+
+    Fix previous commit (forgot this file)
+
+commit 25240becdd83801a788b65f52eada5dd63665e8c
+Author: Carsten Bock <carsten at ng-voice.com>
+Date:   Tue Aug 6 22:48:39 2013 +0200
+
+    Extension to the API: lookup_terminate_dlg(unsigned int, unsigned int, str hdrs)
+    - Terminate a dialog using the API by providing h_entry and h_id (similar to the MI-Function)
+
+commit e6e0419a46c3e5127d07c95390931d10b2a01c3b
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sun Oct 12 23:23:03 2014 +0200
+Date:   Sun Aug 4 14:22:41 2013 +0200
 
-    kamctl: support of fnmatch operator for dialplan
-    
-    - do not reload rules in memory after each change in database to allow
-      batch updates. Reload command has to be done explicitely
-    - parameters of addrule after match expression are optional
+    imc: wrap bit shift defines in parenthesis
     
-    (cherry picked from commit 860ebc3e971ed562c441054f7c09def1a505ea34)
+    - avoid priority conflicts when using the defines
+    - reported by Shankar
 
-commit 53eb694e38836b19e8af7ffaa59b7014cd5f497e
+commit 6a981d3d922c914054d4c8dc7e672bb6a4ddb5f5
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sun Oct 12 18:58:02 2014 +0200
+Date:   Thu Aug 1 15:58:59 2013 +0200
 
-    dialplan: extended debug message to be more useful
+    db_flatstore: free id pointer if no more space for table name
     
-    (cherry picked from commit 37c6e7ec80a16b93751d535de3b7784c1270d8b8)
+    - related to previus commit on this module
+    - keep table name null terminated
 
-commit c94a027b23776a9e5e42250e777470d02f54b115
-Author: Lucian Balaceanu <lucian.balaceanu at 1and1.ro>
-Date:   Sun Oct 12 10:28:29 2014 +0200
+commit 8fb0f711aaa611eac8b2776c7e5ae3c5e19243ac
+Author: Federico Cabiddu <fcabiddu at orange-vallee.net>
+Date:   Mon Jul 29 07:59:34 2013 +0200
 
-    core: execute onsend_route for replies before sending out
-    
-    - control execution of onsend_route block for replies via parameter
-      onsend_route_reply
+    db_flatstore: fixup for new_flat_id function
     
-    (cherry picked from commit 214b161e644c2d7468d9ac3ea13ad0be5196d143)
+    - locally copy table's name
 
-commit 6c7bbcddf48dbfc1bf563eba9a9e10991ac52cc3
+commit 4bc07b15ae9a490273b2696b2860f78ebbd18104
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Oct 10 21:16:51 2014 +0200
+Date:   Thu Aug 1 14:35:16 2013 +0200
 
-    tm: handle r-uri alias parameter for local generated requests within a dialog
+    kamctl: shortcut command to do q query to a database based on key and value
     
-    (cherry picked from commit 3e01905143ace159b18e11a31edf39018d754bba)
+    - kamctl db smatch table key value - return the record from table that
+      has column key matching the value as string (quoted value)
+    - kamctl db nmatch table key value - return the record from table that
+      has column key matching the value as non-quoted
+    - examples:
+    
+    kamctl db smatch subscriber username test
+    kamctl db nmatch subscriber id 123
 
-commit 6f4c872f302111abda6aa810fb462b08809aaac9
+commit 9a0147b8e050bb8ac7b443e4a3139bb326308cba
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Oct 10 12:19:29 2014 +0200
+Date:   Thu Aug 1 14:12:30 2013 +0200
 
-    core: safety check for server_header lenght
-    
-    - don't add the header in local generated replies if the value is empty
+    acc: remove comment from previous patch
     
-    (cherry picked from commit 866ddc109bfd7c681e13ce529d271e8a2a33a972)
+    - references to tracker should be in comments of the commit, not in the
+      code
+    - use tabs for indentation
 
-commit f90edc4efed7fb4bc2d0f6d1a20a69e1751485d3
+commit 341f810dca0cc0596e22f2ac1bca86de0b8d142d
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Oct 10 12:11:52 2014 +0200
+Date:   Wed Jul 31 12:22:12 2013 +0200
 
-    tm: safety check for user_agent_header value
+    app_perl: push the sip msg structure to perl after initializing it
     
-    - don't add the header in local generated requests if the value is empty
+    - reported by David Cunningham
+
+commit 7ba6cbfcaf70cb546ea3a9f148a0f0b0bc38c16d
+Author: Federico Cabiddu <fcabiddu at orange-vallee.net>
+Date:   Mon Jul 29 07:59:13 2013 +0200
+
+    acc: acc_db_set_table_name fixup
     
-    (cherry picked from commit cea9b91dacdb23b22fc1a7dd8454994eab9efa6e)
+    - add termination char to db_table_name_buf
 
-commit aa0175dfe854625f90f1d521e6c3cd5445301804
-Author: Juha Heinanen <jh at tutpro.com>
-Date:   Mon Oct 13 19:00:08 2014 +0300
+commit 1bf5c8328e8b4ed13f6404bf617cac9e26c05e63
+Merge: 0e9b4b3 fb3a5f7
+Author: Carlos Ruiz Diaz <carlos.ruizdiaz at gmail.com>
+Date:   Mon Jul 29 09:49:57 2013 -0400
 
-    modules/pua: reduced log level of cleaning message
-    (cherry picked from commit 53f12ab00ae9ea2075ad207a1cc53dc52c242e3a)
+    Merge branch 'master' of ssh://git.sip-router.org/sip-router
 
-commit 9f177b5d810f4f2f13030e5b20c3a4671b662232
-Author: Olle E. Johansson <oej at edvina.net>
-Date:   Sun Oct 12 21:50:04 2014 +0200
+commit 0e9b4b351e70323fd8581d298f1a7d682f2310fe
+Author: Carlos Ruiz Diaz <carlos.ruizdiaz at gmail.com>
+Date:   Mon Jul 29 09:46:35 2013 -0400
 
-    siptrace Documentation updates, add section ID's
+    Modified cnxcc_set_max_credit behavior
+    
+    - Updated documentation
+    - Updated examples
 
-commit 6a69cfbfd6745bcaeee14a5bc5ce8ab38f5a7b50
-Author: Olle E. Johansson <oej at edvina.net>
-Date:   Sun Oct 12 20:38:27 2014 +0200
+commit fb3a5f7022ebd20fc516b5b8303a0274bda18258
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Fri Jul 26 14:55:38 2013 +0200
 
-    uri_db Documentation update, section IDs added
+    acc: safety check for accounted values not to be NULL
+    
+    - based on a patch by  Federico Cabiddu, FS#327
 
-commit 8ea81d7303d1b4ec3e4a2481ecaf49692923be29
-Author: Olle E. Johansson <oej at edvina.net>
-Date:   Sun Oct 12 20:19:05 2014 +0200
+commit 3d33733f299dda595704108aef73a2912dc3069f
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Fri Jul 26 14:52:21 2013 +0200
 
-    CA example README update
+    uac_redirect: fixup for using acc table parameter
+    
+    - set reason parameter for acc function
+    - based on a patch by  Federico Cabiddu, FS#327
 
-commit af67db379b3053e4743c45bf93e6c6636f84cdd0
-Author: Olle E. Johansson <oej at edvina.net>
-Date:   Sun Oct 12 20:06:28 2014 +0200
+commit 1aea13af9b3eea3788e90411bd94cb9e0b0c4ea3
+Author: Camille Oudot <camille.oudot at orange.com>
+Date:   Tue Jul 23 11:11:01 2013 +0200
 
-    README - updating version number
+    modules/ims_registrar_scscf: safety check in async_cdp_callback
 
-commit 65659addafd0a492cafbb6c9cbaf3644442f333a
-Author: Juha Heinanen <jh at tutpro.com>
-Date:   Sun Oct 12 13:41:41 2014 +0300
+commit 6ff74701652a11497bd82ee3ba2ac7547d1ce666
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Thu Jul 25 10:14:55 2013 +0200
 
-    modules/pua: db_mode=2 send_publish fixes
+    app_perl: move initialization of SIP message var after initialization of temporary environment
     
-    - plus small debug message edits
-    (cherry picked from commit 6822ff45e931ad3e93b22ebf7d1beb350bf27e70)
+    - upon a report by David Cunningham of a leak in operating system
+      memory
 
-commit 24b5a1cac18c8da397663fc5561b9fe44ed214e2
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Thu Oct 9 09:57:13 2014 +0200
+commit da057e5730dd9f82101437e0ee3ceca02b64602c
+Author: Alexandr Dubovikov <alexandr.dubovikov at gmail.com>
+Date:   Tue Jul 23 10:37:03 2013 +0200
 
-    pkg/kamailio/deb: update version to 4.2.0~rc0
+    modules/sipcapture:  Added support for multiple capture modes.
+    			(c) Dragos Dinu (1and1)
 
-commit 30dc30150b8a7efad84e4fa2ac2d4693274a7d98
-Author: Hugh Waite <hugh.waite at acision.com>
-Date:   Wed Oct 8 19:01:20 2014 +0100
+commit ab601ea9a1b2561c2eaa860583cdeed478b9ea8d
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Sat Jul 20 10:01:25 2013 +0200
 
-    core: xavp: Fix xavp_insert to prevent corrupted linked lists
-    
-    - Inserting data at a given index will pad the xavp with XTYPE_NULL entries
-    - Inserting data will replace a NULL entry if present
-    (cherry picked from commit 1828c8ab644243878fc6db9ff0f2592e656dc09a)
+    Makefile: sercmd renamed to kamcmd in uninstall option
 
-commit 5bd4d15dfda23cdd758788a145972afbfb869c60
+commit 2a77bcd36a2b8b91a6d4af3f6ee6828265af39a5
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Oct 8 23:45:54 2014 +0200
+Date:   Thu Jul 18 20:59:54 2013 +0200
 
-    Makefile.defs: version set to 4.2.0-rc0
+    Makefile.defs: removed SCTP conditions for core locating libsctp
     
-    - branch for release series 4.2.x
+    - the code is now in a module, only generic hooks are in the core, that
+      can be turned on/off by SCTP variable (no lib dependency)
 
-commit ffd4d514293aff09325eaf17fa1d511a83571e74
+commit d3a0a8b15af59846fdaee5d9ceae61484f1d7301
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Oct 8 23:37:20 2014 +0200
+Date:   Wed Jul 17 20:19:28 2013 +0200
 
-    dialog: regenerated readme file
+    uac: restrict check of multiple from/to header changes to request route blocks
+    
+    - it can occur many times in due to branch route usage
+    - reported by Andrew Pogrebennyk, FS#323
 
-commit ebe64df20181f4e569548961b9a1ca64b5cfa444
+commit 6624d10b5edbfaf32726875fbbf2ac2221807c84
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Oct 8 23:36:42 2014 +0200
+Date:   Wed Jul 17 12:26:11 2013 +0200
 
-    dialog: sync'ed parameter names for columns with source code
+    uac: $uac_req(sock) - new attribute to set local send socket
+    
+    - local socket can be set for generated requests:
+    
+    $uac_req(sock) = "udp:127.0.0.1:5060";
 
-commit 9a770b1f55dc478c5f449d1c3baafdf9375740ba
-Author: Juha Heinanen <jh at tutpro.com>
-Date:   Wed Oct 8 18:54:31 2014 +0300
+commit 9a3aa5e6e7949dd08146910a301fbeebdf052742
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Wed Jul 17 12:24:42 2013 +0200
 
-    modules/pua_mi: fixed section tag
+    tm: enhanced local request API to set send socket
 
-commit 941de2f0c8bfeb81f138ef03ce55e9da6534e82a
+commit 6335d07c4c77ed60fb8c2b5acc84d7c4b503221c
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Oct 7 08:55:26 2014 +0200
+Date:   Wed Jul 17 12:22:31 2013 +0200
 
-    acc: docs for clone_msg parameter
+    core: helper functions to lookup local socket from proto:host:port
 
-commit 15fc8b9c59aaf31f005e38f54d363f1e9d0a068e
+commit 716ffd2787a68734a21a1374c3dc6dd4783844bd
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Oct 7 08:48:31 2014 +0200
+Date:   Wed Jul 17 00:04:06 2013 +0200
 
-    acc: option to work on a cloned sip msg request for getting acc attributes
+    presence_dialoginfo: add schema to entity
     
-    - it applies for callback done in tm on reply received
-    - avoids working on the shm stored request that can be concurently
-      accessed and some header shortcuts can become set
-    - clone_msg - new parameter to control this behavior, default is 1 (use
-      a cloned structure)
+    - patch by Pawel Sternal, FS#324
 
-commit bb493249566f5572eae23df90a383f0f3112d365
+commit acd0bfb5acc98e791ab6cf011dfa758efba2be8f
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sun Oct 5 22:48:39 2014 +0200
+Date:   Tue Jul 16 21:40:06 2013 +0200
 
-    kamctl: refreshed the sql scripts from schema xml files
+    usrloc: fixed type for db_ops_parameter
+    
+    - reported by Alex Hermann
 
-commit 050b5667fcba38c5889da75556695a26a2ea7dd5
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sun Oct 5 22:25:20 2014 +0200
+commit d07e4f709ceaccc84bbab42dfd55d10992e84a3b
+Author: Carsten Bock <carsten at ng-voice.com>
+Date:   Tue Jul 16 18:02:50 2013 +0200
 
-    test/unit: updated unit 21.sh
+    Example-Configs: Fixed config due to last updates
 
-commit 061f868088365ab9348ad1797ba5efd979fd6ad7
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sun Oct 5 21:56:13 2014 +0200
+commit 9a2b943bfccea83ac52ecb63f39c724f4b9504d4
+Author: Carsten Bock <carsten at ng-voice.com>
+Date:   Tue Jul 16 18:00:51 2013 +0200
 
-    test/unit: updated unit 20.sh
+    ims_registrar_pcscf: Bug-Fix for pcscf_assert_identity (minor)
 
-commit e675f20af9a4d9a4b5e7b11277f4a4e0c774e128
+commit b4c3b811d33846dd0900922bbe5a3d9472839663
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sun Oct 5 21:55:51 2014 +0200
+Date:   Mon Jul 15 23:45:33 2013 +0200
 
-    lib/srdb1: end of line after several debug messages
+    ipops: documented dns_query()
 
-commit bc4792f39a7a0b2ac971f82f01c436d488f2f393
+commit 257225e6918c1387049b74663225ee9b3b722ddf
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sun Oct 5 10:08:20 2014 +0200
+Date:   Mon Jul 15 23:38:25 2013 +0200
 
-    kamdbctl: check if kamctlrc is in the same folder
+    ipops: reset address types for new dns queries
 
-commit aba6ee05e525a66a9e7168336c76d069a1dccc24
+commit 20f3846d6d39e8fd599464d1e5ce48bfec326586
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sun Oct 5 10:07:34 2014 +0200
+Date:   Mon Jul 15 23:32:33 2013 +0200
+
+    ipops: new function dns_query(hostname, pvid)
+    
+    - store the result of dns query in a variable $dns(pvid=>key)
+    - dns query is using getaddrinfo()
+    - $dns(pvid=>key) - new pv allowing to navigate through the result of a dns query
+    - key can be:
+    	- count - number of addresses
+    	- ipv4 - set to 1 if at least one ipv4 address (otherwise 0)
+    	- ipv6 - set to 1 if at least one ipv6 address (otherwise 0)
+    	- addr[index] - the address as string from position index in the list (0 based indexing)
+    	- type[index] - the type of address from position index in the list (0 based indexing), the value is 4 for ipv4 and 6 for ipv6
+    - example:
+    
+    	if(dns_query("test.com", "xyz"))
+    	{
+    		xlog("===== number of addresses: $dns(xyz=>count)\n");
+    		xlog("===== ipv4 address found: $dns(xyz=>ipv4)\n");
+    		xlog("===== ipv6 address found: $dns(xyz=>ipv6)\n");
+    		$var(i) = 0;
+    		while($var(i)<$dns(xyz=>count)) {
+    			xlog("===== #[$var(i)] type ($dns(xyz=>addr[$var(i)])) addr [$dns(xyz=>addr[$var(i)])]\n");
+    			$var(i) = $var(i) + 1;
+    		}
+    	}
+
+commit dd76f37bfff59d5ae07b34346d0ab0a81136649b
+Merge: 66c7553 9ac9b5c
+Author: Richard Fuchs <rfuchs at sipwise.com>
+Date:   Fri Jul 12 12:27:06 2013 -0400
 
-    kamctl: check if kamctlrc is in the same folder
+    Merge branch 'master' into rfuchs/rtpproxy-ng
 
-commit 9d646005e52efc1a5d5e4e0390228a7d4021f5c3
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sun Oct 5 10:03:43 2014 +0200
+commit 66c7553c1131fda7b83807891110f7de393be098
+Author: Richard Fuchs <rfuchs at sipwise.com>
+Date:   Fri Jul 12 12:26:07 2013 -0400
 
-    utils/kamctl: lookup new versions of dbutils tools in kamdbctl.db_berkeley
+    rtpproxy-ng: implement second parameter to rtpproxy_offer/answer/manage
 
-commit bc1743d87f2722c1af7743cc27af98c16c031a3a
+commit 9ac9b5c35858efd7c71163c604d18a1fa35e3a02
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sun Oct 5 10:02:33 2014 +0200
+Date:   Fri Jul 12 18:09:09 2013 +0200
 
-    test/unit: fixes for unit 17 (db_berkeley)
+    ipops: added dsn_int_match_ip(hostname, ipaddr)
+    
+    - function that uses the internal resolver to match a hostname with an
+      ip (similar operation like 'scr_ip=="hostname"')
+    - rename dns_nc_match_ip() to dns_sys_match_ip() to be more suggestive
+      about what kind of resolver is used
 
-commit 5822dc04f01b20ddfe9d37e9c0eea53fa658164b
+commit ccebf9e536d7d5ea8fc824ea089d501e888b37c8
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sun Oct 5 10:01:42 2014 +0200
+Date:   Fri Jul 12 13:31:12 2013 +0200
 
-    db_berkely: end log message with new line
+    ipops: new cfg function dns_nc_match_ip(hostname, ipaddr)
+    
+    - do dns query for the hostname and compare the result to see if is a
+      match with ipaddr
 
-commit 3627d33e720d51046a37b49e91d509370064015d
-Author: Olle E. Johansson <oej at edvina.net>
-Date:   Sun Oct 5 21:32:08 2014 +0200
+commit 9a25e712529cb7aacbae8e64a2e1be4da3c9a8c3
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Fri Jul 12 10:22:33 2013 +0200
 
-    QOS minor doc updates
+    dispatcher: allow pv in ds_is_from_list(setid) parameter
 
-commit f4111c41057d1a195bf30ed2cfa0ebb6049349a2
-Author: Olle E. Johansson <oej at edvina.net>
-Date:   Sun Oct 5 21:10:31 2014 +0200
+commit 80935f9e8bbe20e5c320828183999b5d395ec34c
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Fri Jul 12 00:44:51 2013 +0200
 
-    nathelper Minor doc updates, section ID's added
+    core: avoid doing dns srv again after naptr function that includes srv lookup
 
-commit c1c285b30844eedea9b0390bf4a603fd30d641df
-Author: Olle E. Johansson <oej at edvina.net>
-Date:   Sun Oct 5 20:03:59 2014 +0200
+commit 3823001dd83902d97f3dda9c9f51c370ab04073d
+Author: Alexandr Dubovikov <alexandr.dubovikov at gmail.com>
+Date:   Fri Jul 12 10:14:31 2013 +0200
 
-    msilo minor doc updates, add section ID's
+    modules/sipcapture: a sip message must be stored after bad parsing also.
 
-commit 5236f6e6623057e959ef79ff7f1f61cfa2dbb096
-Author: Olle E. Johansson <oej at edvina.net>
-Date:   Sun Oct 5 19:25:07 2014 +0200
+commit 25b6241ce310ca0ae67896fec2bb50d4c8d80fcb
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Thu Jul 11 21:57:58 2013 +0200
 
-    diversion minor doc updates, adding section ID's
+    dialplan: don't free attrs pvar at shutdown, it is core pv cache reference
+    
+    - reported by Juha Heinanen
 
-commit 5ac8ebafe7fb88663a163b2139001bca2e8571a7
-Author: Olle E. Johansson <oej at edvina.net>
-Date:   Sun Oct 5 19:16:53 2014 +0200
+commit ecb0ede7b20f24af97a42c4d034c46709c3ec38c
+Author: Juha Heinanen <jh at tutpro.com>
+Date:   Thu Jul 11 22:47:37 2013 +0300
 
-    pua_xmpp Minor doc updates
+    modules/tls: config param can now specify a file or directory
 
-commit 110f03f861b21323868256f160c047adaeefa6e0
-Author: Olle E. Johansson <oej at edvina.net>
-Date:   Sun Oct 5 19:09:55 2014 +0200
+commit eba7dcbe6b3ba7b88c0fa0b231cb265a68995e47
+Author: Richard Fuchs <rfuchs at sipwise.com>
+Date:   Thu Jul 11 15:36:54 2013 -0400
 
-    regex Minor doc updates
+    rtpproxy-ng: implement $rtpstat and document start_recording()
 
-commit 9143a2e0e4bf85e3547dbf0d4287a2a80d99de0d
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 23:15:54 2014 -0400
+commit d7d27cd803284ced4d709da543e64e553e0547ca
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Thu Jul 11 20:43:54 2013 +0200
 
-    usr_avp.c: logging: convert LOG to LM_*
+    Makefile.defs: version set to 4.1.0-dev7
 
-commit 7540a139ac60dbb751593a45863bc041c8303313
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 23:08:46 2014 -0400
+commit ca8facabe26f081d1cededeb78ceaa96e4ea9ff2
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Thu Jul 11 16:47:47 2013 +0200
 
-    udp_server.c: logging: convert LOG to LM_*
+    db_unixodbc: fixed typo added by previous commit
 
-commit 8a1f2eded885cb7f2d73ebb1ea46f3a320efa742
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 22:53:34 2014 -0400
+commit c6819b9a02d59b3ad8640fbaaf2fc0b9ef3d5021
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Thu Jul 11 16:43:31 2013 +0200
 
-    tcp_read.c: logging: convert LOG to LM_*
+    db_unixodbc: renamed files with reserved name on some oses
 
-commit 3a82f963a2d6032cd9180d053091d637fca51ef8
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 22:42:25 2014 -0400
+commit aa0156ea441644545236a349cc62afb4983b5476
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Thu Jul 11 16:26:15 2013 +0200
 
-    tcp_main.c: logging: convert LOG to LM_*
+    disptacher: added documentation for parameter attrs_pvname
 
-commit 14839f0692498e9e6ba30ae14c815c990978465d
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 21:50:19 2014 -0400
+commit 09a7a4cd718c0e26d3a948515ec4f6f6a68c64c4
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Thu Jul 11 16:25:06 2013 +0200
 
-    switch.c: logging: convert LOG to LM_*
+    dispatcher: new parameter to specify the pv where to store attrs for matched address in ds_is_from_list()
+    
+    - attrs_pvname can be set to get attributes of matched address in
+      config file
 
-commit 153ab772ce2285d2522c7a1913ae53acd111d76f
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 21:44:56 2014 -0400
+commit 617a444fcbe84290a701228bd78e279bbde4818e
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Thu Jul 11 15:27:16 2013 +0200
 
-    sr_module.c: logging: convert LOG to LM_*
+    pv: added transformations for url encode/decode
+    
+    - patch by JoshE, FS#311
 
-commit 3478802ca2bfb898c6820f147032f2c56b637cac
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 21:33:56 2014 -0400
+commit 12a5a409e7e196e1d0401b125b2de72a9f2e5aff
+Author: Victor Seva <linuxmaniac at torreviejawireless.org>
+Date:   Thu Jul 11 15:03:08 2013 +0200
 
-    socket_info.c: logging: convert LOG to LM_*
+    modules/nathelper: removed natping_proceses limit
 
-commit 500f06d314a6c2ba05fb2af5a1bdcfd7eda4df1d
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 21:26:28 2014 -0400
+commit 0c6fef5fdc2a586ebfa607d3b5344266c08ca996
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Thu Jul 11 14:36:02 2013 +0200
 
-    select_buf.c: logging: convert LOG to LM_*
+    pipelimit: avoid double locking when changing pipe via rpc
 
-commit cdc727b2871a4392ca769b35a9004ff995016e72
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 21:25:37 2014 -0400
+commit 04fd56dc1b84b70a04438ccbf719eb85177524ad
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Thu Jul 11 14:32:48 2013 +0200
 
-    select.c: logging: convert LOG to LM_*
+    pipelimit: avoid double locking when changing pipe via mi
+    
+    - reported by Krischan Udelhoven, FS#315
 
-commit 931c45dd129676bd668f0c15fd71e0d22799cbdb
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 21:24:54 2014 -0400
+commit 4a425a88be796c4b2c8447e6eafc53652ddf8e72
+Author: Elena-Ramona Modroiu <ramona at asipto.com>
+Date:   Sat Jul 6 19:03:49 2013 +0200
 
-    route.c: logging: convert LOG to LM_*
+    htable: sht_lock() and sht_unlock() documented in readme
 
-commit 8e1c2b1a550969f6c4d15964d10d498179f4fab6
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 21:08:14 2014 -0400
+commit bc5cc684efad11f9affe648f3d0f6da98e43ad25
+Author: Elena-Ramona Modroiu <ramona at asipto.com>
+Date:   Sat Jul 6 18:31:17 2013 +0200
 
-    resolve.c: logging: convert LOG to LM_*
+    htable: two new functions to lock htable slots based on item name
+    
+    - sht_lock("htable=>key") and sht_unlock("htable=>key")
+    - useful to update existing items without aditional locks
 
-commit 6e62abb8572118dc4fd19e602acc2a579ad629f1
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 20:59:35 2014 -0400
+commit ddea262fd70521eec450e57519f63a63880a94df
+Author: Richard Fuchs <rfuchs at sipwise.com>
+Date:   Tue Jul 9 12:28:48 2013 -0400
 
-    receive.c: logging: convert LOG to LM_*
+    rtpproxy-ng: initial checkin
 
-commit af8bbc2e13ed2831a88acf65fd7cf7e2b18eec78
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 20:56:28 2014 -0400
+commit 8cd7a48479594052b6b6e70d48946e8963e1625d
+Author: Victor Seva <linuxmaniac at torreviejawireless.org>
+Date:   Tue Jul 9 17:50:06 2013 +0200
 
-    re.c: logging: convert LOG to LM_*
+    modules/app_lua: added param to sr.xavp.get to choose between all the values (default) or just the first ones.
 
-commit 6537bcc04971be84c5006a39c76cd58167c177ef
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 20:50:10 2014 -0400
+commit 4a79fcdd9965c6c3195601baeb82d489d970aa12
+Author: Victor Seva <linuxmaniac at torreviejawireless.org>
+Date:   Tue Jul 9 15:55:35 2013 +0200
 
-    raw_listener.c: logging: convert LOG to LM_*
+    modules/app_lua: fix sr.xavp.get. Get all the values not only the first one.
 
-commit 7afea2225e210cd8652dea22f4813d82c20126ee
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 20:48:51 2014 -0400
+commit 01c2fa43da42a4efab59fe787c332dbf9e318399
+Author: Torrey Searle <tsearle at gmail.com>
+Date:   Tue Jul 9 14:55:22 2013 +0200
 
-    pt.c: logging: convert LOG to LM_*
+    modules/sipt: deleted unused method
 
-commit 4283934eac82b063596bf32158d6a98bcb542816
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 20:40:59 2014 -0400
+commit edc838f04fd182b8997f94c50effd5b0c0153a25
+Author: Torrey Searle <tsearle at gmail.com>
+Date:   Tue Jul 9 11:21:52 2013 +0200
 
-    proxy.c: logging: convert LOG to LM_*
+    modules/sipt: ss7 messages are now modified in place
+    
+     - lumps are now used to modify individual ss7 headers instead
+       of rebuilding the full body from scratch.  This should result
+       in a performance increase
 
-commit eeeb3693f93bae48f300ca916668510cf329bd69
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 20:38:22 2014 -0400
+commit e03462112b108bd0615465f45258fd70c2704100
+Author: Victor Seva <linuxmaniac at torreviejawireless.org>
+Date:   Sun Jul 7 07:25:34 2013 +0200
 
-    msg_translator.c: logging: convert LOG to LM_*
+    modules/debugger: refresh README
 
-commit 2990e54f50e071101ced7b63c81f89045053f42f
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 20:20:49 2014 -0400
+commit 9f363d37ba9e1c72b5abf25ec69ba9d367d6be99
+Author: Victor Seva <linuxmaniac at torreviejawireless.org>
+Date:   Sun Jul 7 07:24:30 2013 +0200
 
-    flags.c: logging: convert LOG to LM_*
+    modules/debugger: add dbg_pv_dump config function documentation.
 
-commit 08d458183d8c6c5dea8cae3f4256676988b8473d
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 20:16:23 2014 -0400
+commit 77f5db57c4d5bf5a5e37985a228c8693ec685a6d
+Author: Victor Seva <linuxmaniac at torreviejawireless.org>
+Date:   Sun Jul 7 07:23:11 2013 +0200
 
-    dst_blacklist.c: logging: convert LOG to LM_*
+    modules/debugger: add dbg_pv_dump config function.
+    
+    It dumps the content of pv_cache on json format.
 
-commit e3d78d57cdba73c9374e996813d78d4485c940c0
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 20:14:38 2014 -0400
+commit faf2f6b9897c3b9acf69a1bbe22b827f386a863e
+Author: Victor Seva <linuxmaniac at torreviejawireless.org>
+Date:   Sat Jul 6 15:13:00 2013 +0200
 
-    dns_cache.c: logging: convert LOG to LM_*
+    modules/sdpops: refresh README
 
-commit 4c2e5693fe00f0326a33954553751d59b42166d3
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 17:53:34 2014 -0400
+commit 2a855d384d37b5a83c879663780441b2f533fced
+Author: Victor Seva <linuxmaniac at torreviejawireless.org>
+Date:   Sat Jul 6 15:09:47 2013 +0200
 
-    error.c: logging: convert LOG to LM_*
+    modules/sdpops: update documentation sdp_[with|remove]_transport
 
-commit 1e3aab0b17f1a5d2eec6a6c84a01361dd4c7fdf8
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 17:50:53 2014 -0400
+commit c252677700bdc81241a39816a3febee70f729344
+Author: Victor Seva <linuxmaniac at torreviejawireless.org>
+Date:   Sat Jul 6 15:00:49 2013 +0200
 
-    data_lump_rpl.c: logging: convert LOG to LM_*
+    modules/sdpops: added sdp_with_transport/sdp_remove_transport functions.
 
-commit 7fb04ae669a969edec08e228800ff0ebbda8372b
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 17:49:29 2014 -0400
+commit 97781390e663116f9e5d11f5644e1145487b6cfb
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Fri Jul 5 09:23:32 2013 +0200
 
-    data_lump.c: logging: convert LOG to LM_*
+    dialog: added timer process to clean unconfirmed dialogs older than 5min
+    
+    - timer runs every 90sec (customization to be added in the future)
+    - safety procedure for cleaning dialog list
 
-commit b908f660e11d67b1d6a5e39b1add6e8fba591981
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 17:41:36 2014 -0400
+commit 647a99bd21f6059505ea1ee65ac93c6c00fc8c8d
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Thu Jul 4 22:34:41 2013 +0200
 
-    daemonize.c: logging: convert LOG to LM_*
+    textopsx: updated docs for msg_apply_changes() and added sections ids
 
-commit a2a91d7d6e4ae84a93f802545e5db8a902616df1
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 17:39:30 2014 -0400
+commit 85f6a45e6d74044488b63a89ce8feaaf3c4b00bb
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Thu Jul 4 22:29:06 2013 +0200
 
-    main.c: logging: convert LOG to LM_*
+    textopsx: enable usage of msg_apply_changes() for sip replies
 
-commit 3a7f6bb32cdd82d11e38cd9dd8d1658666adf7cc
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 17:26:34 2014 -0400
+commit 8248a1b2ed725933f84a343b4936ed4fdef4a869
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Thu Jul 4 22:27:32 2013 +0200
 
-    route_struct.c: logging: convert LOG to LM_*
+    core: helper function to generate sip reply content without removing top via
 
-commit 0b6225253049c0a8af2630bd40f0b908634765cb
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 17:24:17 2014 -0400
+commit d4cef7f5e49105c65df9651a1ad086b035f8ffdb
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Thu Jul 4 11:48:26 2013 +0200
 
-    sip_msg_clone.c: logging: convert LOG to LM_*
+    tm: avoid double execution of response-in callbacks
+    
+    - double execution of response-in callbacks could happen when using tm
+      pvs inside core reply route, being done in transaction matching
+      function, which is executed again by tm reply received function
 
-commit b661d51d28471237747bc4dca30b35e4b176d412
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 17:22:31 2014 -0400
+commit 230a138991b25f7f9b07b4f9cbeffbdd6acef2e8
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Thu Jul 4 11:47:18 2013 +0200
 
-    lock_ops.c: logging: convert LOG to LM_*
+    core: new internam sip msg flag FL_TM_RPL_MATCHED
+    
+    - mark sip reply when matched first time by tm
+    - used to avoid double execution of response-in callbacks
 
-commit 5f1205c8c98ea508d60830de48a2b43eb14f28e3
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 17:20:41 2014 -0400
+commit 27474179bdeef0ddaba05389f510446a387d85e1
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Thu Jul 4 10:31:46 2013 +0100
 
-    lock_ops.h: logging: convert LOG to LM_*
+    modules/websocket: Fix connection leaks
+    
+    - Decrease the TCP connection reference count after each use
 
-commit 36d0ecf473c83ebb12ee4a0d2d8f4dcc83f93d2c
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 17:15:35 2014 -0400
+commit ffdae5987b99b9bfd39992d407a3a0a33aa772ab
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Thu Jul 4 10:30:51 2013 +0100
 
-    ip_addr.c: logging: convert LOG to LM_*
+    core: Fix connection leak with websockets
+    
+    - Decrease connection ref count after using connection
 
-commit 44f49c060217322e4469582073e728097313a851
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 17:13:26 2014 -0400
+commit fb4dc4b7b866239a90a4d6441ed319664697edab
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Thu Jul 4 09:33:56 2013 +0100
 
-    ip_addr.h: logging: convert LOG to LM_*
+    core: Improve tcp stats output
+    
+    - Add connection ref count
+    - Add websocket protocols
 
-commit c68b4078e6b81ebec77071434f3dabc396ad5a07
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 17:08:23 2014 -0400
+commit d0f88e19577d9b914922f83049075b7786f3d8df
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed Jul 3 10:46:44 2013 +0100
 
-    forward.c: logging: convert LOG to LM_*
+    modules/websocket: Fix pkg memory leaks
+    
+    - Fix pkg memory leaks in error cases
+    - Fix incorrect memory allocation size for ws connections
+    - Fix typo in websocket stats
 
-commit e23c76c97a3483f56ad3aff0f8ffd9ba513fc84e
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 16:53:49 2014 -0400
+commit 074f12c5a444188aa023797ac70e2d38d225cb18
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed Jul 3 10:39:32 2013 +0100
 
-    forward.h: logging: convert LOG to LM_*
+    modules/tls: Free TLS data for secure websocket connections
 
-commit eadbcc1899c7e128142a33b28710b6c4c47bffdd
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 16:48:57 2014 -0400
+commit c5081ad634742d88e56e4fcc097b756098119e4e
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Wed Jul 3 23:23:40 2013 +0200
 
-    modparam.c: logging: convert LOG to LM_*
+    uac_redirect: fetch all contact headers in redirect replies
+    
+    - only first header was considered for redirect handling
+    - based on a report by Geoffrey Mina
+    - generate fake ruid (used as instance and user-agent) to satisfy the
+      requirements of t_load_contacts()/t_next_contacts()
 
-commit 2ee98a71e4e4478983b3b576b432f63c7003d514
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 16:45:07 2014 -0400
+commit fa0339b1906690f009786fc9ed92c73a8c9e6520
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Tue Jul 2 23:32:37 2013 +0200
 
-    tcp_conn.h: logging: convert LOG to LM_*
+    dialog: detect if no trasaction is created after config execution for new dialogs
+    
+    - release the dialog to avoid endless storage in state 1
 
-commit fca9a2e3978e552a32136299e974b22c163e4a6a
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 16:43:44 2014 -0400
+commit b4682cac2e2f151288a411018da077b6d1526eca
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Tue Jul 2 21:40:32 2013 +0200
 
-    script_cb.c: logging: convert LOG to LM_*
+    kamailio-basic.cfg: added basic cfg config file
+    
+    - get the same set of configs as expected by former ser flavour
 
-commit a539b5612a1189fa193db8429732cfb5c0183990
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 16:41:51 2014 -0400
+commit 6cf3ab0ca6f38d1d2e60dbc644bb4d2fb563919a
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Mon Jul 1 15:22:33 2013 +0200
 
-    rad_dict.h: logging: convert LOG to LM_*
+    dialog: increment cseq in early stage for PRACK and UPDATE
+    
+    - rework from a patch by Halina Nowak
 
-commit 347dd3c74d82447479928f05340b5fde1029ac2e
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 16:38:02 2014 -0400
+commit 71d7dc6bc750406d510e0571e05da3966911cfea
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Mon Jul 1 14:51:03 2013 +0200
 
-    nonsip_hooks.c: logging: convert LOG to LM_*
+    dialog: avoid realloc of memory for cseq when setting leg info
+    
+    - free already allocated structs when needed
+    - has part of a patch by Halina Nowak
 
-commit 0fe3535561dba78824e973c099aec2444b02601c
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 16:36:35 2014 -0400
+commit ed6dbb0ca11206049bee9ab515ce071eb70e7b63
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Mon Jul 1 14:44:45 2013 +0200
 
-    local_timer.c: logging: convert LOG to LM_*
+    dialog: fixed callee cseq reference
+    
+    - part of patch by Halina Nowak
 
-commit bac61abf195ba2bfd33584ef2706e7d00227ee96
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 16:33:48 2014 -0400
+commit 1123ed46ee847be83f35aa485a1ef6712566bc09
+Author: Victor Seva <linuxmaniac at torreviejawireless.org>
+Date:   Mon Jul 1 13:37:42 2013 +0200
 
-    dset.c: logging: convert LOG to LM_*
+    core: Also consider PROTO_WS(S) in forward().
 
-commit 103ba4ab9dad2f59c862cef09a80d52f585e9fcf
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Oct 3 22:25:48 2014 +0200
+commit 8f6dc39a0fcd9035a2bd5bff01e51fc3fc7671fd
+Author: Richard Good <richard.good at smilecoms.com>
+Date:   Mon Jul 1 11:47:50 2013 +0200
 
-    test/unit: updates to unit tests 10..19
+    dialog_ng: include dialog function dlg_get in dialog_ng
+    	- In first iteration of dialog_ng module the dialog function dlg_get was not included
+    	- This function is now included; it searches and sets current dialog based on Call-ID, From-Tag and To-Tag
 
-commit 1c5f9e094b4ac7f3a7ab7cae0551986769c5bb7a
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 16:26:15 2014 -0400
+commit b252d4ec79446bd915fe2eb6bcf8556d3275343c
+Author: Henning Westerholt <hw at kamailio.org>
+Date:   Sun Jun 30 16:06:16 2013 +0200
 
-    timer.c: logging: convert LOG to LM_*
+    memcached: document new memory parameter for memory manager setting
 
-commit 7552e5e2cb115fa60fdf8e9998e293d6501c086e
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 16:07:26 2014 -0400
+commit 736fab01bafba394f4b81aa20a63bf827baa2a13
+Author: Henning Westerholt <hw at kamailio.org>
+Date:   Sun Jun 30 15:50:29 2013 +0200
 
-    io_wait.c: logging: convert LOG to LM_*
+    memcached: update module docs, patch from Charles Chance, charles dot chance at sipcentric dot com
 
-commit 5716744ff21e7e7b15981f40652370e1a8f64248
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 15:58:31 2014 -0400
+commit df41d7f4e0cd8bd0c328f94360a6b3a3f3e9d59b
+Author: Henning Westerholt <hw at kamailio.org>
+Date:   Sun Jun 30 15:42:17 2013 +0200
 
-    io_wait.h: logging: convert LOG to LM_*
+    memcached: fix crash during shutdown, make used memory manager configurable
+    
+    * fix a crash during shutwdown, as reported from Dragos Oancea, droancea at yahoo dot com
+    * make memcache client library memory manager configurable, as default use
+      the one from the system as this is probably the most tested configuration
+      in the field
+    * the internal memory manager should provide a better performance in this case,
+      but as the old library has some issues with the internal one, we better stay
+      with this
+    * documentation will be provided in the next commit
 
-commit 1faacc76a1c866beb9e63da5a370f6501dffbca1
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 15:23:10 2014 -0400
+commit 811ed09b1c8cff014d3135967c8a3cda1bec569d
+Author: Richard Good <richard.good at smilecoms.com>
+Date:   Tue Jun 25 15:42:44 2013 +0200
 
-    stats.c: logging: convert LOG to LM_*
+    modules/ims_icscf: updated documentation
+     	- updated documentation to use route blocks after async diameter
 
-commit 849744c6ed72f324839ae4e02ae48393324bac51
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 15:19:35 2014 -0400
+commit 8f1904fd0a0b305b2c528df0d1d3c27d5eef0c7d
+Author: Richard Good <richard.good at smilecoms.com>
+Date:   Tue Jun 25 15:41:42 2013 +0200
 
-    stats.h: logging: convert LOG to LM_*
+    modules/ims_auth: updated documentation
+    	- updated documentation to use route blocks after async diameter
 
-commit 5e8e40a4737ac305b5df065583e6f94b0359bdb3
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 15:16:27 2014 -0400
+commit bf08aa1a3859766caf0842fdd30b9fc2f4a4ff43
+Author: Richard Good <richard.good at smilecoms.com>
+Date:   Tue Jun 25 14:11:13 2013 +0200
 
-    socket_info.h: logging: convert LOG to LM_*
+    IMS example config files: update icscf and scscf config files to correctly use async route blocks
+    	- This fix updates the example ICSCF and SCSCF config files to correctly use route blocks for the replies of any asynchronous Diameter messages
 
-commit 9ffdc951d391fb511da0932c14c00465b1cabd0a
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 15:15:19 2014 -0400
+commit 0d5622531d71d0b0ab3fb25a13c3ea1f46581512
+Author: Richard Good <richard.good at smilecoms.com>
+Date:   Tue Jun 25 14:09:00 2013 +0200
 
-    tcp_ev.h: logging: convert LOG to LM_*
+    modules/ims_icscf: execute route block on async reply to UAR and LIR
+    	- Changed this to make the use of async CDP cleaner
+    	- Fixes inconsistencies we are experiencing with async TM and not using route blocks
+    	- Note this fix is for UAR replies called from I_perform_user_authorization_request() and LIR replies called from I_perform_location_information_request()
 
-commit 4c7fb7768edb9542217695dc3be47c7457e78c3d
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 15:14:03 2014 -0400
+commit 6af810edde27d087c86432f42d9aec0636b3a740
+Author: Richard Good <richard.good at smilecoms.com>
+Date:   Tue Jun 25 14:07:12 2013 +0200
 
-    lock_alloc.h: logging: convert LOG to LM_*
+    modules/ims_auth: execute route block on async reply on REG MAR
+            - changed this to make the use of async CDP cleaner
+            - Fixes inconsistencies we are experiencing with async TM and not using route blocks
+            - Note this fix is for REG MAR called from ims_www_challenge()
 
-commit a7652a586b7dc03369b0824b08ac721c02b83dc4
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 15:12:27 2014 -0400
+commit 87ea473c15454742fc9f3a0cedd46cf09c663f3c
+Author: Richard Good <richard.good at smilecoms.com>
+Date:   Tue Jun 25 14:04:46 2013 +0200
 
-    pass_fd.c: logging: convert LOG to LM_*
+    modules/ims_registrar_scscf: execute route block on async reply on REG SAR
+    	- changed this to make the use of async CDP cleaner
+    	- Fixes inconsistencies we are experiencing with async TM and not using route blocks
+    	- Note this fix is REG SAR called from save()
 
-commit 4b3179f1bdd162c9220d1405efd400831c71548b
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 15:00:38 2014 -0400
+commit 584508d5374726bf523a23693da86f0763b34767
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Sun Jun 23 05:37:34 2013 +0200
 
-    str.c: logging: convert LOG to LM_*
+    core: allow c++ style of one line comments
+    
+    - can make easier the read of config files with defines and comments
 
-commit 17ae94369cff94b323c915d9d0b6a42b44c3dea7
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 14:59:28 2014 -0400
+commit 756620fd0c1912e492781f05fde944f9035d95b3
+Author: Carsten Bock <carsten at ng-voice.com>
+Date:   Mon Jun 24 22:13:26 2013 +0200
 
-    dprint.c: logging: convert LOG to LM_*
+    examples: Make S-CSCF more quiet
 
-commit e0b5e4559638e6935e92ecc2ff1a88f084983522
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 14:58:05 2014 -0400
+commit 14ef8ff8d460bc22f0df4793e11455487ea91aab
+Author: Carsten Bock <carsten at ng-voice.com>
+Date:   Mon Jun 24 22:10:33 2013 +0200
 
-    crc.c: logging: convert LOG to LM_*
+    auth_ims: New option to store authentication vectors using the IMPU only, instead of IMPI/IMPU.
+    (this is required to work with some SIP-clients)
+    - added some more debug info
+    - replaced the hashing function with core_hash from Kamailio-core
 
-commit 94b74cf8bf80c1fc17eebef8b5b0767a05234de0
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 14:55:49 2014 -0400
+commit 9fc55badeaa54d2cfde7a152459b957f8ae5a192
+Author: Carsten Bock <carsten at ng-voice.com>
+Date:   Mon Jun 24 18:08:29 2013 +0200
 
-    id.c: logging: convert LOG to LM_*
+    Added missing parameters to documentation
 
-commit 51e77d3ef5527bd2907f37dddfea384def9c329f
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 14:51:32 2014 -0400
+commit 72d79d20964ac192dbe1cbe35f48c21ec749c39a
+Author: Carsten Bock <carsten at ng-voice.com>
+Date:   Mon Jun 24 18:08:05 2013 +0200
 
-    name_alias.h: logging: convert LOG to LM_*
+    Fixed Editor note
 
-commit 6d239c28060e8be0cab99637f8f7240069530990
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 14:49:35 2014 -0400
+commit bd1a534515678f69385d00b08699b434e1fab8df
+Author: Jason Penton <jason.penton at smilecoms.com>
+Date:   Mon Jun 24 15:24:49 2013 +0200
 
-    char_msg_val.h: concatenate ERR log
+    modules/ims_registrar_scscf: execute route block on async reply of unreg. SAR
+    	- changed this to make the use of saync CDP cleaner
+    	- fixes inconsistencies we are experienceing with async TM and not using route block
 
-commit 2c9d2bf4d6505d6c71fae4d994216944a2f475e1
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 14:45:42 2014 -0400
+commit 678ab425062e6c6a30b5f1d37025c2bbdcd5425d
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Fri Jun 21 04:23:38 2013 +0200
 
-    timer_funcs.h: logging: convert LOG to LM_*
+    auth: set ids for elements in the documentation
+    
+    - split checks parameters in own section for easier reference
 
-commit b75ecbceba4e585b761c20271c6d319b5cbde9e2
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 14:43:39 2014 -0400
+commit fc83d3b1f1dd0934e5638b91d11e27f47880b411
+Author: Carlos Ruiz Diaz <carlos.ruizdiaz at gmail.com>
+Date:   Thu Jun 20 17:34:49 2013 -0400
 
-    char_msg_val.h: logging: convert LOG to LM_*
+    Added support to limit number of calls per customer/profile
+    
+    - added function cnxcc_set_max_channels() per customer/profile
+    - added function cnxcc_get_channel_count() per customer/profile
+    - added function cnxcc_terminate_all() to terminate calls per customer/profile
+    - added select @cnxcc.channels["customer/profile"].count
+    - added modified version of kamailio-cnxcc.cfg to reflect changes and examples
 
-commit d0ed596cd420d9a16a339d64c572c8c72bac1017
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 14:43:15 2014 -0400
+commit 8f261c5baeb01d5bee0437249b7f6d3d81bee209
+Author: Victor Seva <linuxmaniac at torreviejawireless.org>
+Date:   Thu Jun 20 08:34:05 2013 +0200
 
-    fix_lumps.h: logging: convert LOG to LM_*
+    modules/dialplan: allow xavp vars as parameters.
 
-commit eaf74185d78bb9d3edea50c84dbebb32571c2fb2
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 14:28:48 2014 -0400
+commit 6b27e0d5519f8e29bc31c553a67367975acfe7ec
+Author: Victor Seva <linuxmaniac at torreviejawireless.org>
+Date:   Thu Jun 20 08:32:47 2013 +0200
 
-    ut.h: logging: convert LOG to LM_*
+    modules/dialplan: use pv_cache_get function instead of create pv_spec_t
 
-commit bb71813843d6c3d1cd074308851b3af0387d68d3
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Oct 3 14:19:36 2014 -0400
+commit 1207edd603937e3e43ce20207bfeae0284f16489
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Mon Jun 17 14:48:52 2013 +0200
 
-    action.c: logging: convert LOG to LM_*
+    pv: $xavp(name) is marked as PVT_XAVP type
 
-commit 44e29820a759405adb7657334e86ea474196e6fd
-Author: Hugh Waite <hugh.waite at acision.com>
-Date:   Thu Oct 2 18:37:00 2014 +0100
+commit 424691bfae61b00fa6d5f1f75e95fe60bf823526
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Mon Jun 17 14:47:56 2013 +0200
 
-    rr: Fix memory leak when using outbound
+    core: define PVT_XAVP as type for xavp pseudo-variables
     
-    - Flow token memory is freed after building the rr header
+    - they may need special handling for debug purposes
 
-commit 0921a4f6a2215b3e60bcc0dee4afe826f55a91d2
+commit c5573dddc4c11898fb68365e9a311aff0f1690c8
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Oct 2 17:58:09 2014 +0200
+Date:   Mon Jun 17 11:00:29 2013 +0200
 
-    test/unit: updated test units 8 and 9
+    pipelimit: fixed typo in module parameter name
+    
+    - patch by Krischan Udelhoven
 
-commit bf8c98fc71cba974a2b98c36e2c9f6966768d529
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Oct 2 17:34:41 2014 +0200
+commit 03188db86347013ef43d3615c12be4b696349098
+Author: Victor Seva <linuxmaniac at torreviejawireless.org>
+Date:   Mon Jun 17 10:48:45 2013 +0200
 
-    tsilo: fix clang warnings on inline prototypes in header files
+    modules/app_lua: fixed runtime warning: exports dlflags interface is deprecated
 
-commit b7bc7a5450b1e31697fb389a503463eac644b796
+commit 4f3d04d547c66a1b59398cf80e93974175141514
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Oct 2 17:31:34 2014 +0200
+Date:   Sun Jun 16 17:17:36 2013 +0200
 
-    core: be prepared to get Via received param with brackets around ipv6 addr
+    topoh: safety check for To header
     
-    - helper function to generate similar value
+    - protection for the case when sanity module checks are not enabled
+    - reported in FS#303 by Michel de Weerd
 
-commit f50c1e9fab16fb611f7bbc6002f4c8607bc8fbf2
+commit 330aeda83dc7ed927cf994e4b21ff44ab2d2c215
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Oct 2 16:47:35 2014 +0200
+Date:   Sun Jun 16 16:40:59 2013 +0200
 
-    core: more verbose log message for failing to find local socket
+    mtree: fixed typo in log function name
 
-commit 51f5826732bbbb2af394c0b0a75db2a310f57b18
+commit 69c409e14c568fae45e449122e5b4efbf009bf41
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Oct 2 16:34:02 2014 +0200
+Date:   Sun Jun 16 16:39:14 2013 +0200
 
-    tm: more verbose debug when failing to find socket for forwarding
+    core: added function to get the pv cache table
+    
+    - pv cache struct moved to header file
 
-commit 4f8f45bdcb7c4c82192bd8d0f7c8d2166dd75dac
+commit ea772b354f84eccff0190234025f057879ff33ed
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Oct 2 12:16:15 2014 +0200
+Date:   Sat Jun 15 22:03:58 2013 +0200
 
-    test/unit: updates to auth parameter in unit 7 cfg
+    kamctl: new commands can be defined in separate files
+    
+    - write new kamctl commands either in CFGDIR/kamctl.newcmd.ext or
+      ~/.kamctl/kamctl.newcmd.ext
+    - 'newcmd' has to be replaced with the name of the command
+    - the file must include cmd_newcmd() function which is executed with the
+      parameters after the command name
+    - example: adding new command 'sample'
+    	- content of ~/.kamctl/kamctl.sample.ext file:
+    
+    usage_sample() {
+        echo
+        mecho " -- command 'sample' - kamctl sample extension command"
+        echo
+    cat <<EOF
+     test ............................... print test message
+     help ............................... help text
+    EOF
+    }
+    
+    cmd_sample() {
+        case $1 in
+            test)
+                echo "message from sample test command"
+            ;;
+            *)
+                usage_sample
+            ;;
+        esac
+        exit 1;
+    }
+    
+    - new command 'sample' can be executed with:
+    
+    kamctl sample test
 
-commit 73fef4d500e58600758ac1c2b4eadf66d4b506a1
+commit 0b82af2019d523c680d156d9b95ae33043c79bd0
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Oct 2 11:55:59 2014 +0200
+Date:   Sat Jun 15 19:33:50 2013 +0200
 
-    test/unit: updates to unit 7
+    kamctl: set internal version to 4.1.0
 
-commit 509659a83a53f8d979da37cee24941d22f5fffdc
+commit af6a5d7422b614e5a143bc987806181086360c34
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Oct 2 11:54:54 2014 +0200
+Date:   Sat Jun 15 19:31:43 2013 +0200
 
-    lcr: declare inline function static to work with llvm linker
+    tm: readme updated based on latest docbook
 
-commit 321575dcd18e42fe6c62942ef417dd8acf7f466d
+commit 5f1b144a7e63b464af3e5e0e7b74cf7e7e1e8668
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Oct 2 10:18:11 2014 +0200
+Date:   Sat Jun 15 19:30:59 2013 +0200
 
-    mohqueue: fixed db_qtable parameter name
-    
-    - reported by Marino Mileti
+    tm: documented dn_reuse_rcv_socket parameter
 
-commit 1f1b81ed76dda3a889ffec52c173c53b2225dee4
+commit 30e26f22600c3f50f0ea556bf2872ef7b0807c6a
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Oct 2 09:51:46 2014 +0200
+Date:   Sat Jun 15 19:08:38 2013 +0200
 
-    usrloc: hash_size default value set to 10
+    tm: new module parameter - dns_reuse_rcv_socket
     
-    - as discussed on mailing lists
+    - control reuse of the receive socket for additional branches added by
+      dns failover
+    - if 1, the rcv socket is used, if not it depends on mhomed - when that
+      is 0, the first socket is used, otherwise will be selected based on
+      routing table
+    - default is 0
+    - therefore beware when setting this parameter and mhomed=1
+    - based on discussion for FS#313
 
-commit 2376ef7c6f3317054c844ae9b99366d084065121
+commit 350f4f8971a679f0d6566361b2a7bb17956a6a7e
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Oct 2 09:48:36 2014 +0200
+Date:   Sat Jun 15 18:54:59 2013 +0200
 
-    core: default pkg memory size set to 8MB
+    tm: copy tm routing blocks ids for new branches added by dns failover
     
-    - as per discussion on mailing lists
+    - patch by Jasmin Schnatterbeck, part of FS#313
 
-commit ccdf1c61834ac2f4cfe139ac83e83dfd72d90139
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Wed Oct 1 12:54:31 2014 -0400
+commit e7da9f72beb1c97b79a516ecdd19db8971dea508
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Sat Jun 15 18:23:48 2013 +0200
 
-    core: daemonize.c: convert logs to new format
+    kamailio.cfg: route subscribe for event message-summary to voicemail server
 
-commit c873758624da24359117b3fa158cc56ccd0a5d73
+commit da016636be6e0ca9a65b645b6e30ec0b1dafeef4
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Oct 1 17:27:49 2014 +0200
+Date:   Fri Jun 14 08:42:37 2013 +0200
 
-    core: change the uid and gid for pid and pgid files
-    
-    - use the user and group given to daemon to update ownership of pid and
-      pgid files
-    - reported by Ovidiu Sas, FS#472
+    kamctl: added show command to display user attributes in subscriber table
 
-commit e1e40d3a58bf3ed6c4f2df830e29d5468d7bee82
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Oct 1 16:53:44 2014 +0200
+commit 519fe88fc41cae4674ce4bc943b84eb522af654b
+Author: Victor Seva <linuxmaniac at torreviejawireless.org>
+Date:   Wed Jun 12 15:58:29 2013 +0200
 
-    core: fixed overwriting mpath value given in command line via config
-    
-     - -L is in the group of options evaluated before config
+    core: do not repeat key names on xavp_get_list_key_names function result
 
-commit 4bfc11009df67de7584cd1634997a86ad023322c
+commit b5538401a01057318063a4e4646c9e7a2fb967c0
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Oct 1 16:52:41 2014 +0200
+Date:   Wed Jun 12 08:50:26 2013 +0200
 
-    test/unit: use SRC_DIR to point to kamailio source and updated tests 4, 5, 6
+    mtree: print more details if the record in db is broken
 
-commit 2b21542f93740508e334605551fe4332eec7db11
+commit 862e267267ccd58e096f267ac5aab03cee042b7c
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Oct 1 14:51:07 2014 +0200
+Date:   Tue Jun 11 18:47:54 2013 +0200
 
-    test/unit: 3.sh is back in working stage
-    
-    - used for testing creating database structure with latin1 charset
+    mtree: make log message on not maching character a debug instead of error
 
-commit 0247bd79f6753c6153a4b17f82803e4349e7745e
+commit 407608dfef8e80ef0beaefc61df96e40060b952f
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Oct 1 14:45:28 2014 +0200
+Date:   Tue Jun 11 18:41:05 2013 +0200
 
-    kamctl: note in kamctlrc how to enable automatic creation of dbuid tables
+    registrar: readme regenerated
 
-commit 765532005914b9f457596aaac715cf2a0b863078
+commit c228851e068a080050c79107c760f8ab5ffae967
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Oct 1 14:44:40 2014 +0200
+Date:   Tue Jun 11 18:39:31 2013 +0200
 
-    kamdbctl: option to run without asking mysql root password if empty
-    
-    - provide PWSKIP=yes - good for automate testing
+    registrar: fixed typo in example of xavp_rcd parameter
 
-commit 2a2cdb864b9e3758ab08a404c93e24db4856d815
+commit 9589466916305146fb4f982542c3f3a51126dcef
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Sep 30 18:11:02 2014 +0200
+Date:   Tue Jun 11 18:37:32 2013 +0200
 
-    core: memlog and memdbg default value is L_DBG+1
+    registrar: more debug messages when adding ruid xavp
     
-    - too verbose if just trying to use debug=3 in kamailio.cfg and mem
-      operations are useful only on troubleshooting memory, which is not the
-      typical troubleshooting case
+    - free local ruid xavp if cannot be added to root list
 
-commit daeb7834431ccc598ce95cba97925cd0fef83ead
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Sep 30 18:08:16 2014 +0200
+commit 106916abc67d2badc43eac03ef175efbbac4f6d1
+Author: Camille Oudot <camille.oudot at orange.com>
+Date:   Tue Jun 11 16:34:49 2013 +0200
 
-    test/unit: 2.sh updated to work with latest kamailio
+    modules/ims_isc: several safety checks
+    
+    - fixed potential buffer overflow
+    - fixed potential crash if regcomp fails
 
-commit 452f32235034916468cab577de3ca0d0f56fd5ea
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Sep 30 18:07:53 2014 +0200
+commit bddb9a5bf38d4904a9e18dc187fc8c0507001ab5
+Author: Camille Oudot <camille.oudot at orange.com>
+Date:   Tue Jun 11 16:24:15 2013 +0200
 
-    benchmark: declare inline functions static to work with clang linker
-    
-    - otherwise it results in no symbol found at module loading time
+    modules/ims_isc: fix several compiler warnings
 
-commit 8a51aa250c4e22e5933d0ff39a7a4b300007bb72
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Sep 30 18:06:36 2014 +0200
+commit 4af0bc13901525a5638c2c64b863f377e033903f
+Author: Vicente Hernando <vhernando at systemonenoc.com>
+Date:   Mon Jun 10 12:14:54 2013 +0200
 
-    sms: declare inline functions static to work with clang linker
-    
-    - otherwise it results in no symbol found at module loading time
+    app_lua: solve crash when setting a variable not convertible to string.
 
-commit c4f7356f2d8c057f59cb61948aa04664cecd35f7
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Sep 30 17:53:44 2014 +0200
+commit b5f0a62a2acfbf0f4ce9cd146cb342d717e662a9
+Author: Camille Oudot <camille.oudot at orange.com>
+Date:   Tue May 28 17:53:07 2013 +0200
 
-    core: exit with -1 if there is a mismatch in version of module and core
-    
-    - return code to shell 0 is like succesful run, some scripts not being
-      able to say it was a failure to start
+    modules/ims_registrar_scscf: safety check for log line when recieving an SAR_UNREGISTERED_USER response
 
-commit fad3b2482f98888351f4133f47a433b5bb36c3b7
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Sep 30 17:37:50 2014 +0200
+commit fd8dfb71d0eeae891ad0c83ff332929d54f3a3ec
+Author: Ovidiu Sas <osas at voipembedded.com>
+Date:   Fri Jun 7 12:09:38 2013 -0400
 
-    test/unit: README updated with more details about running unit tests
+    Makefile: update de-stable target: squeeze -> wheezy
 
-commit cfc6d928c5c7c80fcbbc24db48e64b389ce1afdb
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Sep 30 17:37:23 2014 +0200
+commit e41230071e367015ecf794c147c60fda0bcd1907
+Author: Ovidiu Sas <osas at voipembedded.com>
+Date:   Thu Jun 6 15:21:19 2013 -0400
 
-    test/unit: 1.sh updated to work with latest kamailio
+    registrar: print bogus AoR in error log
 
-commit 84d00119fa1bc4bcd06d3189fa5ca67564338aa2
+commit ea6354c53c8871e4e117b7434645ab4fee811612
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Sep 30 17:34:16 2014 +0200
+Date:   Thu Jun 6 15:58:58 2013 +0200
 
-    test/unit: Makefile option to run individual test unit
-    
-    - head parameter swapped to work on bsd/darwin
+    acc_radius: exit at startup if radius_config is not set
 
-commit 4e24dac93e905cd055b9fabc3cce49071f911b9b
+commit 8e937d260d0ff41f50be56e0a46ede44554f3f99
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Sep 30 17:32:58 2014 +0200
+Date:   Thu Jun 6 11:47:10 2013 +0200
 
-    test/unit: kill using application name
+    cfgutils: updated docs to specify correct time unit for usleep
     
-    - on some OS, killall with full path doesn't work
-    - kamailio is searched first, being default flavour now
+    - it is microseconds, pointed by David K
 
-commit 8cf3dd993eba3a7ba29b3a5996d1fc4ea7d27b3a
+commit c4b29f6fac6155b9b087737df5956b687ff4e36a
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Sep 30 17:32:37 2014 +0200
+Date:   Thu Jun 6 09:09:14 2013 +0200
 
-    test/unit: removed search on modules_k folder
+    kamailio.cfg: reset $du for voicemail re-routing in failure route
 
-commit 6b8acf3204a8615762b0b5dcc6aac152f40b2ca0
+commit c8e928a2c78ee963f807791bea5aacdd31e05936
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Sep 30 11:29:18 2014 +0200
+Date:   Thu Jun 6 09:05:28 2013 +0200
 
-    websocket: fix checking payload_len safety check for fragmentation
+    siputils: added new function is_first_hop()
     
-    - a crafted websocket frame  using values spanning max unsinged int could have
-      caused a failed detection of unsupported fragmentation and invalid memory access
-    - thanks to Peter Dunkley and Hugh Waite for assisting and pin-pointing
-      where everything happens
+    - detect if it is first hop after original sender
+    - added section ids for functions, remove a duplicate content for
+      is_rpid_user_e164()
 
-commit 852f3dcc58dd07ac3047e0ea75829d3306be70f1
+commit 0193489cca56f58b512f5379c078c98a366c17e2
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Sep 29 11:37:30 2014 +0200
+Date:   Wed Jun 5 22:44:13 2013 +0200
 
-    kamctl: address dump command to list subnets
+    kamailio.cfg: few updates related to nat traversal
     
-    - address table is loaded in memory inside two structures, a matter
-      whether it is a IP or net address. Dump both structures via kamctl
-      address dump
+    - added "co" flags to rtpproxy_manage() to change all IPs in sdp, many
+      phone get confused if only media ip is changed
+    - add nat=yes parameter only for in branch route to avoid multiple
+      occurences
 
-commit f4721b3b896a92d30e611a3d6213715935bc70de
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Mon Sep 29 10:20:13 2014 +0200
+commit 4b65964dbe1f38bcf867301d43933f9bbf91ab7d
+Author: Jason Penton <jason.penton at smilecoms.com>
+Date:   Wed Jun 5 08:58:29 2013 +0200
 
-    pkg/kamailio/deb: update version to 4.2.0~pre1
+    module/ims_auth: protection against crash if there is no auth vector initialised.
+    	- patch submitted by Camille Oudot
 
-commit ed1a5476e82fa675861a86fb3c75555c578555d2
-Author: fcabiddu <federico.cabiddu at gmail.com>
-Date:   Fri Sep 26 18:19:39 2014 +0200
+commit 2e466866468a71d4a6e7589cae69ae606b194716
+Author: Jason Penton <jason.penton at smilecoms.com>
+Date:   Wed Jun 5 08:46:13 2013 +0200
 
-    tm: t_append_branches extra checks for cancelled transaction
+    modules/ims_isc: Add support for P-Serverd-User header
+    	- This header allows a triggered Application Server to know the IMS user for who it was
+    	triggered, and in what state (originating/terminating, registered/unregistered)
+    	- Thanks to Camille Oudot for patch!
 
-commit a135e7956fcf780fd44dddcfbc2c671630b5d44d
-Author: Federico Cabiddu <federico.cabiddu at gmail.com>
-Date:   Mon Sep 29 07:57:12 2014 +0200
+commit cb4cfa492aa977df3f80b7d93001559ecb1bcdec
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Tue Jun 4 23:21:11 2013 +0200
 
-    tsilo: prefixed module's functions with ts_
+    sercmd: pass OS define at compile time
 
-commit 181c30705b3cb82245463015d98644c278131af2
+commit af1c2af129edeb49c6f2c826ec2c675e72c2486d
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sun Sep 28 21:44:35 2014 +0200
+Date:   Tue Jun 4 22:17:52 2013 +0200
 
-    tm: beter detection of brackets in From/To values in UAC print functions
+    sercmd: possibility to enable EXTRA_DEBUG via compile time option
     
-    - commit fb0cd1cd6a891ab5dc5f559bb6740ba62ac3daf4 fixed the case of
-      avoiding double <> when dispaly name was present, but affected when
-      header parameters were given
-    - reported by Juha Heinanen
+    - should get rid of empty DBG() resulting in unused init variable
 
-commit dfcdc7b858ca916f9c9ae3509cb82fb4b547fa91
-Author: Olle E. Johansson <oej at edvina.net>
-Date:   Sun Sep 28 21:44:51 2014 +0200
+commit 0f54ee9c29faf767a5ec38de9f70bfaab8836ac9
+Author: Juha Heinanen <jh at tutpro.com>
+Date:   Tue Jun 4 10:44:36 2013 +0300
 
-    msrp: Minor doc updates, added section ID's
+    modules/lcr: use pv_cache_get
+    
+    - Applied patch by Victor Seva.
 
-commit ba95571544ca0905905c025efb0ae76cbe1042c3
-Author: Olle E. Johansson <oej at edvina.net>
-Date:   Sun Sep 28 21:26:49 2014 +0200
+commit 76709d2ea2eb3c05cf62a3368310f50e8bfee355
+Author: Klaus Darilion <klaus.mailinglists at pernau.at>
+Date:   Mon Jun 3 22:13:20 2013 +0000
 
-    dialplan: Minor doc update, adding section ID's
+    modules/auth_db: regenerate README
 
-commit decae860504ea27a559dc0e52d50833baf4cee63
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sun Sep 28 12:50:41 2014 +0200
+commit 2940d5012250a134745a2cf9abed2f88ed95576e
+Author: Klaus Darilion <klaus.mailinglists at pernau.at>
+Date:   Mon Jun 3 22:10:20 2013 +0000
 
-    Makefile.defs: version set 4.2.0-pre1
+    modules/auth_db: document authentication return values
 
-commit 131139883c03f3851ad99e96c59dfe3c349ec011
+commit 5bed1c2f9721405d5e6e0678f583aee474d4b9b9
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sun Sep 28 12:49:27 2014 +0200
+Date:   Mon Jun 3 23:23:15 2013 +0200
 
-    tm: use advertised addr/port if set for socket in rm rpc uac commands
+    Makefile: added install-initd-centos target
     
-    - reported by Juha Heinanen
+    - install centos specific init.d scripts
 
-commit c725f1dec14863e069bfd1e5c26857a1005528d5
+commit a17a32e5f7a3120c200d6e48fe91d7aa1dfd28b1
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sun Sep 28 12:48:53 2014 +0200
-
-    core: helper functions to get addr and port to be used in signaling from socket info
-
-commit 073620366761402e129d4585bb5728dae7469df6
-Author: Olle E. Johansson <oej at edvina.net>
-Date:   Fri Sep 26 22:15:02 2014 +0200
+Date:   Mon Jun 3 20:53:05 2013 +0200
 
-    exec: Minor doc updates, adding section ID's
+    dialog: shift next timer run for keepalives of dialog
+    
+    - reported by Daniel Tryba
 
-commit b5c5090cc902043c8d0dddcfbf21b415c7643df6
-Author: Olle E. Johansson <oej at edvina.net>
-Date:   Fri Sep 26 22:14:15 2014 +0200
+commit 26b15ad0006defeb8df17dff090fd93ffa11ede6
+Author: Victor Seva <linuxmaniac at torreviejawireless.org>
+Date:   Mon Jun 3 18:43:51 2013 +0200
 
-    registrar  Minor doc updates, adding section ID's
+    modules/debugger: fixed last commit.
+    
+    - checked malloc result on dbg_init_pvcache.
+    - checked result of dbg_init_pvcache on mod_init.
+    - removed commented code.
 
-commit 8e6c83182677ec234c5f44c5dfcb40e421a21bcb
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Sep 26 09:16:39 2014 +0200
+commit 2312e2adc626f42d36d240a417bb488f19e95017
+Author: Victor Seva <linuxmaniac at torreviejawireless.org>
+Date:   Mon Jun 3 15:10:27 2013 +0200
 
-    dialog: fixed typo/copy&paste oversight to dlg pointer name in clean routine
+    modules/debugger: new parameter log_assign
     
-    - credits to Alex Balshov for report, troubleshooting and spotting the
-      fix
+    This parameter enables logging every single assign action on the config.
 
-commit b66033d0546bf57cfb0cd16f1072da80c5a79d34
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Sep 26 08:59:17 2014 +0200
+commit 5d45ea50a7ebb53cfcfb04553a3152e61d1e6831
+Author: Elena-Ramona Modroiu <ramona at asipto.com>
+Date:   Mon Jun 3 11:13:56 2013 +0200
 
-    tm: extra checks to see if the transaction was canceled before forwarding branches
+    htable: documented the new rpc commands
     
-    - catch cases when CANCEL arrives during branch_route execution
-    - reported  Sławomir Bocheński, FS#468
+    - htable.sets and htable.seti
 
-commit 2328948053cfd3bfec0ceef0e3ceca96a01f3271
-Author: Olle E. Johansson <oej at edvina.net>
-Date:   Fri Sep 26 08:35:13 2014 +0200
+commit 83eb9b7d7a9b4e1e2bf35d4e2b00573c176c8290
+Author: Elena-Ramona Modroiu <ramona at asipto.com>
+Date:   Mon Jun 3 11:05:58 2013 +0200
 
-    call_control: Minor doc updates, adding section ID's
+    htable: added rpc commands for setting items in a hash table
+    
+    - htable.sets - set to a string value
+    - htable.seti - set to an integer value
 
-commit c4c25a07c77ca5e2ceccd11cdab29ed93d86d29a
-Author: Olle E. Johansson <oej at edvina.net>
-Date:   Thu Sep 25 22:09:15 2014 +0200
+commit 7cb062ce8eb9935b69298b61aa6a59450b97dbaf
+Author: Juha Heinanen <jh at tutpro.com>
+Date:   Sat Jun 1 17:47:58 2013 +0300
 
-    enum: Minor updates to docs. Added section ID's
+    modules/usrloc: rpc statistics command update
+    
+    - ul.db_users and ul.db_contacts now deal with unexpired records only
+    - new command ul.db_expired_contacts tells number of expired contacts
 
-commit 820998136ffda07b607bc9833c340b6b62e24219
-Author: Olle E. Johansson <oej at edvina.net>
-Date:   Thu Sep 25 22:00:45 2014 +0200
+commit 09cc2207b265d51dcbc28279623bf9c597fa3b46
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Fri May 31 17:05:40 2013 +0200
 
-    app_java: minor doc updates
+    pua: release lock on not finding temp dialog
     
-    - Added section ID's
+    - patch by Halina Nowak
 
-commit 6b96fa92093ec41ae343da1537afd82666c9be5c
-Author: Olle E. Johansson <oej at edvina.net>
-Date:   Thu Sep 25 21:45:23 2014 +0200
+commit d5c4dda7932e8efe018beb77f8ca2e29a44aa185
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Thu May 30 17:59:01 2013 +0200
 
-    xlog: Minor documentation updates
+    core: don't free pvar spec - is reference to cache
     
-    Added section ID's
+    - reported by Peter Dunkley
 
-commit 77462923e9c6f34c96f1d50440334964f0277efc
-Author: Olle E. Johansson <oej at edvina.net>
-Date:   Thu Sep 25 21:31:55 2014 +0200
+commit 0577abba2abd869a0c3fb051289068e79986e6cd
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed May 29 14:47:21 2013 +0100
 
-    Pike: Documentation updates
+    documentation: Rebuild all modified READMEs
 
-commit 5ace8b081bb4bec2e94b48252311b63339794e24
-Author: Olle E. Johansson <oej at edvina.net>
-Date:   Thu Sep 25 21:31:25 2014 +0200
+commit f67f6880bfa9f7a9f31b4a46106482ff41120c3c
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed May 29 14:46:40 2013 +0100
 
-    tls: documentation updates
+    uid_uri_db: Fix TOC in documentation
 
-commit fa6154cc346b77934ad57d0c96b8e8c7c1913dbc
-Author: Olle E. Johansson <oej at edvina.net>
-Date:   Thu Sep 25 20:46:03 2014 +0200
+commit 7bf8e5a0f125cf1878fbd7a81504ab67659fa3a9
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed May 29 14:46:24 2013 +0100
 
-    statistics: minor update of docs
+    uid_gflags: Fix TOC in documentation
 
-commit 3923dbdbca3d605b96290b1c087e41bd32a58fdd
-Author: Olle E. Johansson <oej at edvina.net>
-Date:   Thu Sep 25 20:38:09 2014 +0200
+commit 0882e6f8c2217b75f8d5082e1df5bf8f9291e125
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed May 29 14:46:04 2013 +0100
 
-    sanity Update docs, add standard section IDs
+    uid_domain: Fix TOC in documentation
 
-commit 59fdd0a402ebac61d882ac2c579b87a0ec27eaef
-Author: Olle E. Johansson <oej at edvina.net>
-Date:   Thu Sep 25 20:22:16 2014 +0200
+commit db6762f45eb2f5809487b254e35edb55ea097fc1
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed May 29 14:45:49 2013 +0100
 
-    permissions: Update docs about "mask" field. We do support IPv6.
+    uid_avp_db: Fix TOC in documentation
 
-commit 4dab127de5370d6b0a295d7d373bbadef98449ff
-Author: Olle E. Johansson <oej at edvina.net>
-Date:   Thu Sep 25 20:18:12 2014 +0200
+commit 0bf496b9e9368d564835d5f97827ba7a7fcc8242
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed May 29 14:45:28 2013 +0100
 
-    permissions: Update docs
-    
-    - Add overview
-    - Add section ID's
-    - Add missing WS and WSS transports
+    uid_auth_db: Fix TOC in documentation
 
-commit 21eb073c25b66b110193f1607b93f256f7d9fdfa
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Sep 25 16:59:34 2014 +0200
+commit 402d1fb0036cab8588e94acf3ea6d80ccf1a00b0
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed May 29 14:44:45 2013 +0100
 
-    exec: add parameter to control the option for bash exec safety check of CVE-2014-6271
-    
-    - parameter: bash_safety - default is 1 (enabled), set to 0 to disable
-    - just in case someone needs that kind of header and knows what
-      he/she does
+    xprint: Fix TOC in documentation
 
-commit d5d57c0df931c9d60432def919c837cc76e4ce42
-Author: Seudin Kasumovic <seudin.kasumovic at gmail.com>
-Date:   Thu Sep 25 16:56:28 2014 +0200
+commit 06369a4f2b2dbe3b58ca2c34c0cf2f228a343fd7
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed May 29 14:44:28 2013 +0100
 
-    exec: safety check against bash vulnerability CVE-2014-6271
+    xmlops: Fix TOC in documentation
 
-commit 22b559cb25c25b3801b1849a5da76a8ec937ef83
-Author: Hugh Waite <hugh.waite at acision.com>
-Date:   Tue Sep 23 13:29:15 2014 +0100
+commit 631e2450beb3cba5a0f3b85ecfd319a8ba98db00
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed May 29 14:44:09 2013 +0100
 
-    usrloc: restore usrloc attributes in DB_ONLY mode
-    
-    - restores xavps per location during a lookup
+    tm: Fix TOC in documentation
 
-commit 5b733fa361afced0418947c965b256dbe7ae3a68
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Sep 24 23:46:00 2014 +0200
+commit 528098292d5a5dc43052f0d9f59105622c064f74
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed May 29 14:43:57 2013 +0100
 
-    dialog: set again the dialog ids in context for BYE processing
-    
-    - they can be reset by event route execution
+    tls: Fix TOC in documentation
 
-commit fa54c6997abe0a944a7454e21884cc95fea85b89
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Sep 23 23:50:58 2014 +0200
+commit 6ea032c426e09a932c260842cf884cdd1cca69e5
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed May 29 14:43:42 2013 +0100
 
-    dispatcher: added ids to some sections in docs
+    timer: Fix TOC in documentation
 
-commit 2e047d4536f36627651abba08fbd4d511b299b05
-Author: Olle E. Johansson <oej at edvina.net>
-Date:   Tue Sep 23 21:57:44 2014 +0200
+commit f198c3248b152e407313462619a402a730f9f29e
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed May 29 14:43:24 2013 +0100
 
-    uuid Minor doc updates
+    textopsx: Fix TOC in documentation
 
-commit 615b79edafc990d2a82394c8b020fd7687dc7bc5
-Author: Olle E. Johansson <oej at edvina.net>
-Date:   Tue Sep 23 21:49:18 2014 +0200
+commit e1a98837a273921a307518d0f83c690adabfa201
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed May 29 14:43:09 2013 +0100
 
-    jsonrpc-s Update docs
-    
-    JSON-RPC is called JSON-RPC with a hyphen.
+    sms: Fix TOC in documentation
 
-commit 3b6133bb3e7ba1d075fd173fc0322d391f10160b
-Author: Olle E. Johansson <oej at edvina.net>
-Date:   Tue Sep 23 21:38:53 2014 +0200
+commit c0b97566f8cfd0038a8fc5ea514dd7cf3b37f831
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed May 29 14:42:54 2013 +0100
 
-    xmlrpc Update docs, change SER to &kamailio;, fix typo
+    sl: Fix TOC in documentation
 
-commit fb0cd1cd6a891ab5dc5f559bb6740ba62ac3daf4
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Sep 22 22:21:33 2014 +0200
+commit 87e43eead7d3d6c8740bd397e512629a4230bf30
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed May 29 14:42:35 2013 +0100
 
-    tm: test ending angle bracket for From/To URI when genrating local requests
-    
-    - the value can start with a display name and can end up with double
-      angle bracketting
+    sanity: Fix TOC in documentation
 
-commit a1e96cbd5a3b43598c59cb50693e6b739801b804
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Sep 22 22:04:39 2014 +0200
+commit d99ffcd886b12a8b3adb43549d0603a86ef803da
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed May 29 14:42:20 2013 +0100
 
-    core: add received parameter to via if rport parameter is present
-    
-    - required by RFC3581, section 4.
+    print_lib: Fix TOC in documentation
 
-commit 288d8abb1b84a1a42121d62f61affe7cb9a4f12e
-Author: Olle E. Johansson <oej at edvina.net>
-Date:   Mon Sep 22 14:28:32 2014 +0200
+commit 762d01b4783b9d9e1b97420a7e0ab901b84eb243
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed May 29 14:42:05 2013 +0100
 
-    permissions: Fix typo in documentation
+    print: Fix TOC in documentation
 
-commit a232785704f682ce05dddd747c8a9fdc23c67244
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sun Sep 21 20:49:53 2014 +0200
+commit c8a00e093aa009cff5069cfa683b3efc361497d7
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed May 29 14:41:51 2013 +0100
 
-    kamailio-oob.cfg: sync'ed basic common parts with kamailio.cfg
+    prefix_route: Fix TOC in documentation
 
-commit c3b2a816518dafe72ea4d6496ede943f2e685b5f
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat Sep 20 22:23:14 2014 +0200
+commit cc15d526784ec2f734db452bc3f5157493225416
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed May 29 14:41:28 2013 +0100
 
-    kamailio-basic.cfg: updates to track minimal common parts with kamailio.cfg
+    mangler: Fix TOC in documentation
 
-commit fef8a44e22990cdc4fa88b0d54932db997e45522
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Sep 19 22:05:17 2014 +0200
+commit 5829244ff407abd8cb0735b998dcd7ffb351f87b
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed May 29 14:40:54 2013 +0100
 
-    kamailio: note that NAT OPTIONS keepalive can be enabled with define WITH_NATSIPPING
+    malloc_test: Fix TOC in documentation
 
-commit be1ed10d61918285bdbb3686ac8d43a31f5e63bc
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Sep 19 21:55:24 2014 +0200
+commit eabae931b7fcf1c4dae9bce2945a55c9dd48fee8
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed May 29 14:40:31 2013 +0100
 
-    kamailio.cfg: coherent formating
-    
-    - compacted some sub-routes by reducing if-block identation with returns
+    iptrtpproxy: Fix TOC in documentation
 
-commit cab397a9a89a735cb12004c3f8721247ae6aba9a
-Author: lazedo <luis.azedo at factorlusitano.com>
-Date:   Fri Sep 19 06:39:38 2014 +0100
+commit e8ab0f1552c4bd0fbeb8f2bb42b79bb8acbce57e
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed May 29 14:40:06 2013 +0100
 
-    kazoo : missing options & corrections to publish. regenerated README
+    db_flatstore: Fix TOC in documentation
 
-commit c59ebbd8f63e9b447d5aba79c06d6206e33b2436
-Author: Luis Azedo <luis at 2600hz.com>
-Date:   Wed Sep 17 02:04:48 2014 +0100
+commit 9ca893c26257caf8d80e7fae25128a6e28f37518
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed May 29 14:39:45 2013 +0100
 
-    kazoo : handle target-uri properly
+    db2_ops: Fix TOC in documentation
 
-commit 27a26dad73819eff7c0fe0c18cac54f64ec69718
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Sep 18 18:32:20 2014 +0200
+commit 2a743dcd16f2546dabf41a5b0de498a6faaf00ed
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed May 29 14:38:43 2013 +0100
 
-    evapi: use EVENT_ROUTE as route block identifier
-    
-    - for event routes executed by the module
+    db2_ldap: Fix TOC in documentation
 
-commit b19bc8a5c15707289e2d46c211fda4585257397c
-Author: Olle E. Johansson <oej at edvina.net>
-Date:   Wed Sep 17 12:50:05 2014 +0200
+commit 09c617d4e3bd17e5f2234aac03f90f4fa25c3bb6
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed May 29 14:38:25 2013 +0100
 
-    evapi: update docs
+    ctl: Fix TOC in documentation
 
-commit 834dce1f4d0dbd2aac3b63477459f1045239010f
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Sep 17 00:57:40 2014 +0200
+commit a966e236f5d4ae9d98048d5432978658c70a7f26
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed May 29 14:38:07 2013 +0100
 
-    htable: lookup event route for expired items at startup
-    
-    - searching it by name at runtime can become an overhead for lot of
-      entries in htable
+    counters: Fix TOC in documentation
 
-commit a306ea024d1098df81ce9c68ec558e6c3a0e7086
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Sep 16 23:43:34 2014 +0200
+commit 48c393f24a0a6c9a2841f7710cfdbc475c90d214
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed May 29 14:37:45 2013 +0100
 
-    dialog: allocate buffer for new request after updating CSeq value
-    
-    - new buffer is higher than the old one -- situation only when dialog is
-      taking care of updating cseq downstream (e.g., after authentication)
+    cfg_rpc: Fix TOC in documentation
 
-commit c2b0be97a3ef8e4e1bff34a5c73328a63979aa61
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Sep 16 23:38:35 2014 +0200
+commit c1cb95ee9e29f4373973f7676a224d2892a8902e
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed May 29 14:37:26 2013 +0100
 
-    core: safety check for outbound buffer
-    
-    - pointer can end up being NULL if replacement fails to be built (e.g.,
-      via topoh)
+    cfg_db: Fix TOC in documentation
 
-commit ec8fe1e7ea904a51ca933d0b15408ca464002cbe
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Sep 16 23:33:20 2014 +0200
+commit 216d3f4c8d8b3a40867b4f8438e8ac5027cf1bdf
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed May 29 14:37:03 2013 +0100
 
-    core: hanlde replacement buffer free for WS/WSS frame sending
-    
-    - affected when using topoh for ws/wss traffic
+    blst: Fix TOC in documentation
 
-commit 02e43f87b2fa3be61bc4c63a9f8359457e3e0484
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Sep 16 19:05:57 2014 +0200
+commit 84a96c85d21a34c9082efd6622bccd73bfb1a2b5
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed May 29 14:11:23 2013 +0100
 
-    dialog: check if the transaction is created for BYE closing the dialog
-    
-    - if not, release the dialog, because there will be no tm callbacks
-      called later to release it. In this way avoid zombie dialog.
-    - reported by Ovidiu Sas, FS#424
+    avp: Fix TOC in documentation
 
-commit 1735feed8e287e92c3d81cf6a4d873460f6ee878
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Sep 16 18:13:02 2014 +0200
+commit e59a2b0fa195fc2360049ccd438dc02ee19aedf3
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed May 29 14:10:31 2013 +0100
 
-    utils/kamctl: removed unused default values
-    
-    - test if DEFAULT_Q is set inside the function using it, because it has
-      single place usage
+    auth_identity: Fix TOC in documentation
 
-commit 640206f068ec5c52edd4c23399a99ef8a9e3b753
-Author: Richard Fuchs <rfuchs at sipwise.com>
-Date:   Tue Sep 16 10:41:43 2014 -0400
+commit 985cee9f4e904e92d473efecb15f4211c8a75501
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed May 29 14:09:08 2013 +0100
 
-    rtpengine: fix encoding of "direction" flag
+    auth_ephemeral: Minor documentation improvement
 
-commit a78764174a893131124852490f47239051892139
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Sep 16 09:27:05 2014 +0200
+commit ffe8aa173c6106844707bcf5d0f8da4f28631921
+Author: Henning Westerholt <hw at kamailio.org>
+Date:   Wed May 29 12:38:10 2013 +0200
 
-    core: notice message about exports dlflags made debug
+    DB scheme: remove default MySQL engine definition
     
-    - it is anyhow for developers, not admins
+    * remove default MySQL engine definition from table definitions
+    * if nothing is specified then MySQL server will choose the default from its cfg
+    * if you like to specify it, change the MYSQL_TABLE_TYPE define in
+      lib/srdb1/schema/entities.xml and run "make dbschema" in the top level directory
+    * the stylesheet doesn't check the engine type, Kamailio supports MyISAM and InnoDB
 
-commit 6a0201d83a4d441c0e3b74bd64d3a6557c4a1fe3
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Sep 15 10:47:04 2014 +0200
+commit 5aa71845f630f6b933b0a415749a7b1dae66605a
+Author: Henning Westerholt <hw at kamailio.org>
+Date:   Wed May 29 12:30:58 2013 +0200
 
-    usrloc: db_ops_ruid default value to 1
+    Revert "DB scheme: as discussed on sr-users list, change default mysql engine to InnoDB"
+    
+    This reverts commit fa49fe070adadfff893b338f2a2d69776c043653.
 
-commit d6489cab8ca8a0b96074ed6e26054517a1547cbf
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Sep 15 09:35:09 2014 +0200
+commit a21137507bea759d4945402dc47486ac324724db
+Author: Victor Seva <linuxmaniac at torreviejawireless.org>
+Date:   Wed May 29 12:25:50 2013 +0200
 
-    db_mongodb: proper handling for null values in insert
+    core: added helper function pv_cache_get_name() in order
+     to get the name of a pv_spec_t on pv_cache.
 
-commit a6f3d41f5bb23f2a153ca481b495110339c9cb45
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Sep 15 00:05:28 2014 +0200
+commit a2316f35deef2586f79dc575367224af853e9b70
+Author: Victor Seva <linuxmaniac at torreviejawireless.org>
+Date:   Wed May 29 12:25:09 2013 +0200
 
-    db_mongodb: log query content in debug level
+    core: Add callback to be able to log assign actions.
 
-commit c1edef1f89894a9382ef424a43aefabe0fb10443
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Sep 15 00:01:36 2014 +0200
+commit 6fba3230222214fccb72fd07817f29693d98b877
+Author: Victor Seva <linuxmaniac at torreviejawireless.org>
+Date:   Wed May 29 12:24:00 2013 +0200
 
-    usrloc: option to control if the null fields should be in insert statement
-    
-    - ammeds previous patch 1e84aeb91cf8e7a79a9ac9091ed993be944a667b that
-      introduced skipping adding the null fields
-    - while it was more optimal for sql backends, for non-sql that doesn't
-      have a schema auto-default could break the rows
-    - default is to skip the null fields
+    core: use pointer to pv_spec_t on lvalue union. Use pv_cache_get() on interpreter.
 
-commit 666ffd55f4d2a14d89bbe7d18f75a9e2d398420b
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sun Sep 14 14:54:28 2014 +0200
+commit fa49fe070adadfff893b338f2a2d69776c043653
+Author: Henning Westerholt <hw at kamailio.org>
+Date:   Wed May 29 11:49:59 2013 +0200
 
-    db_mongodb: proper result conversion to DB APIv1
+    DB scheme: as discussed on sr-users list, change default mysql engine to InnoDB
 
-commit fea60616b97d49f50cc1b00e8f67e2889de5116c
+commit b480ac55508e5d9b92cc9560e0b1d338d04f3b11
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sun Sep 14 14:32:05 2014 +0200
+Date:   Wed May 29 10:49:40 2013 +0200
 
-    lib/srdb1: helper function to reallocate the index for result rows
+    topoh: safety check for Via header when removed from script
     
-    - useful for db connectors that don't know in advance the number of rows in result
+    - reported by Guillaume Bour, FS#300
 
-commit 321952a4f5cad7386fef0b8b2e0f550455cbe7d8
+commit 8cba441b17c75cd078a499c24268c8a60c6b1771
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sun Sep 14 09:35:45 2014 +0200
+Date:   Tue May 28 15:48:22 2013 +0200
 
-    utils/misc/vim: added log_error to syntax file
+    misc_radius: updated readme
+    
+    - from a patch by Victor V. Kustov
 
-commit 199891c536e357b95b101b623f70527a4f57b70e
+commit 355490abd8c6e82a45cb96338ceca938c99ed744
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sun Sep 14 09:33:44 2014 +0200
+Date:   Tue May 28 15:43:27 2013 +0200
 
-    db_mongodb: build proper initial result structure
+    misc_radius: handle IPv4 returned attributes
+    
+    - populate attributes for negative replies when common_response is set
+    - patch by Victor V. Kustov
 
-commit fd573c98c75319c724d74bc9effc090fd8eff8e5
-Merge: f0e3c7a fb66389
-Author: Luis Azedo <luis at 2600hz.com>
-Date:   Sat Sep 13 19:02:30 2014 +0100
+commit 6a92939ee4b7db6216814dc88e57eccefabb05af
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Tue May 28 00:46:26 2013 +0100
 
-    Merge branch 'lazedo/kazoo'
+    modules/auth_ephemeral: updated to use SHA1_DIGEST_LENGTH #define from openssl/sha.h
 
-commit f0e3c7a2dba1275e713a4d2f15a3a13f6cb4d67b
-Author: lester <federico.cabiddu at gmail.com>
-Date:   Sat Sep 13 19:54:55 2014 +0200
+commit ec893a2c6cb5c0fd21207cbf0ffab09f65418df2
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Tue May 28 00:27:37 2013 +0100
 
-    tsilo: fixed documentation for t_store
+    modules/auth_ephemeral: tidied up the headers and tidied up more debug
 
-commit 952157e2f13469c3265c4186fd6deb6f6c7f53bd
-Author: Juha Heinanen <jh at tutpro.com>
-Date:   Sat Sep 13 19:10:41 2014 +0300
+commit ba2a6ac4230dd9169943f55a9c06af3faa694356
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Tue May 28 00:20:20 2013 +0100
 
-    modules/auth: updated docbook version
+    modules/auth_ephemeral: updated to handle usernames from the web-service that just consist of timestamps
+    
+    - tidied up the diagnostic output
 
-commit a192f2073fe1c81def8cff1487004ee58dc856aa
+commit a435f770e7162f73aea560a77851f8fb639a495a
+Merge: 45227df 74bf08e
 Author: Juha Heinanen <jh at tutpro.com>
-Date:   Sat Sep 13 18:39:14 2014 +0300
-
-    modules/auth: fixed docbook reference
-
-commit 62e3101ed3e30d0eac959969c8ba419a3a1adcd9
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat Sep 13 16:49:38 2014 +0200
-
-    auth_db: doc updates for load_credentials
-
-commit eda5ea9fb78e2b442407ab4f31662b9e30d38c01
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat Sep 13 16:46:07 2014 +0200
+Date:   Mon May 27 17:58:33 2013 +0300
 
-    auth_db: load_credentials defaults now to empty list (null value)
+    Merge branch 'master' of ssh://git.sip-router.org/sip-router
     
-    - it was 'rpid', but is not a common use case these days
-    - you can get it back via config with:
-    modparam("auth_db", "load_credentials", "rpid")
-
-commit fb66389261c03d57d6c182cf490c5730d97c7e22
-Author: Luis Azedo <luis at 2600hz.com>
-Date:   Sat Sep 13 05:07:26 2014 +0100
-
-    kazoo : remove expires parameters for presence. they should be in the
-    payload. handle expires = 0
+    - i did pull , but there was race conditions with somebody else's push
 
-commit cc7b8a9a050afe245831c20356b1000e09b6e749
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Sep 12 21:13:14 2014 -0400
-
-    dialog: fix warning: unused variable [-Wunused-variable]
-
-commit 3d8082cf1a1c0a24ab2693fd881a1beea87a7755
-Author: lazedo <luis.azedo at factorlusitano.com>
-Date:   Fri Sep 12 20:43:46 2014 +0100
+commit 45227df1bc87e448c74fe31c001e85f525c654a0
+Author: Juha Heinanen <jh at tutpro.com>
+Date:   Mon May 27 17:57:07 2013 +0300
 
-    kazoo : remove spaces between xml elements
+    modules/usrloc: renamed ul.users and ul.contacts rpc commands
+    
+    - new, more descriptive names are ul.db_users and ul.db_contacts
 
-commit 19ceb74638b7e53fbe6d01a7b51ac07470738d42
-Merge: b1ba03f 121cdbc
+commit 74bf08ef30cf18fb609c2c067584f1515ede23da
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Sep 12 20:44:08 2014 +0200
+Date:   Mon May 27 16:54:02 2013 +0200
 
-    git failed to do fast forward and rebase to avoid the merge notification
-    
-    Merge branch 'master' of ssh://git.sip-router.org/kamailio
+    core: enclose uri in angle brakets for redirect contact header
     
-    * 'master' of ssh://git.sip-router.org/kamailio:
-      Rollback accidental changes from commit (74f53b7d7f6ff00144152aff453e6b388447320c)
-      pkg/kamailio/deb: update to 4.2.0~pre0
+    - safer for uri with parameters and no q
+    - reported by Dan Bogos
 
-commit b1ba03f1fe41522b62aa727966c4dec3062cbbb9
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Sep 12 20:41:55 2014 +0200
+commit d0d298070fdbb015a96f209fa3c925ba71e3a37b
+Author: Juha Heinanen <jh at tutpro.com>
+Date:   Mon May 27 13:54:23 2013 +0300
 
-    usrloc: safety check for debug message printing path value from rpc add command
+    modules/usrloc: added two new rpc commands ul.users and ul.contacts
     
-    - reported and patch by Thomas Arimont, FS#467
+    - for accessing number of different AoRs and contacts in a location table
 
-commit 0ac16c52d49ef04f4a3054381efae2e83afa4258
-Author: lazedo <luis.azedo at factorlusitano.com>
-Date:   Fri Sep 12 19:24:47 2014 +0100
+commit 6531b8d495ead58a85cb101d914b5bf18c2ecddb
+Author: Klaus Darilion <klaus.mailinglists at pernau.at>
+Date:   Mon May 27 10:44:51 2013 +0000
 
-    kazoo : remove dead code and unused var warnings
+    modules/dialog: regenerate README
 
-commit 73f1669102ed9fd30b8e0ecad7fe4fde5eb26ea2
-Author: Luis Azedo <luis at 2600hz.com>
-Date:   Fri Sep 12 18:23:35 2014 +0100
+commit 68209cc2b15c2c0674d7cf4529607e148e3fc1b4
+Author: Klaus Darilion <klaus.mailinglists at pernau.at>
+Date:   Mon May 27 10:44:03 2013 +0000
 
-    kazoo : event key/subkey & documentation corrections
+    modules/dialog: improve documentation of DID matching
 
-commit a2e0e0af6be365f733a77df6ebdb2fde44882761
-Author: Luis Azedo <luis at 2600hz.com>
-Date:   Fri Sep 12 16:24:07 2014 +0100
+commit ace89166f84657b2ea4a70e8d9e2ccfbd032b1ba
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Mon May 27 00:49:46 2013 +0100
 
-    kazoo : documentation
+    pkg/kamailio/(centos|fedora): Added RPM for auth_ephemeral module
 
-commit e300df1940b3309b9da13f915580364b8ef6a648
-Author: lazedo <luis.azedo at factorlusitano.com>
-Date:   Fri Sep 12 16:23:20 2014 +0100
+commit 2a29b2ba260584634f05c684ef39ab45e2dc51b6
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Mon May 27 00:32:19 2013 +0100
 
-    kazoo : remove dead code
+    core: updated groups to include new auth_ephemeral module
 
-commit 121cdbc0db12c12f3a1ab46b03e6d91062b2f734
-Author: Carsten Bock <carsten at ng-voice.com>
-Date:   Fri Sep 12 13:03:05 2014 +0200
+commit 0bea7f63afa0fd544ad93465db94ddef4ed67a00
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Mon May 27 00:25:03 2013 +0100
 
-    Rollback accidental changes from commit (74f53b7d7f6ff00144152aff453e6b388447320c)
+    modules/auth_ephemeral: new module for ephemeral credential based authentication
 
-commit 36332ee8566aa6c89c7e940940ab7221a50a8fc3
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Fri Sep 12 02:48:59 2014 +0200
+commit 375d878b5f318acc08b155c29398e4abb74edbd5
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Sun May 26 17:11:25 2013 +0200
 
-    pkg/kamailio/deb: update to 4.2.0~pre0
+    sctp: added rpc commands to module documentation
 
-commit 7fb8c88c1d4aeb50d1e637697132ab0994dcdb28
+commit ca923db8727333ad7df14126bb377418a829cce3
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Sep 11 22:36:56 2014 +0200
+Date:   Sun May 26 17:04:23 2013 +0200
 
-    dispatcher: free dset root structure at reload
+    sctp: rpc commands are prefixed with sctp
     
-    - reported by Heenan, Timothy Steven
+    - no longer part of core and proper matching of the module
 
-commit 722ee5ea86d38337d2ea901fbd5c087c9cc43ab3
-Author: Luis Azedo <luis at 2600hz.com>
-Date:   Thu Sep 11 17:32:56 2014 +0100
-
-    kazoo: remove dependency on tm module
-
-commit a13e3b46dba4470deb748eec3b700386f453f6f9
+commit 352a7dccf2570af857d7e2e50fed600c4762278d
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Sep 11 17:46:52 2014 +0200
+Date:   Sun May 26 16:14:51 2013 +0200
 
-    app_java: allocate enough space to store terminating NULL pointer in split
+    topoh: safety check for SIP messages
     
-    - on a report by Tom Johnson
+    - received callback can be executed for non-sip messages
+    - reported by Julia
 
-commit 74f53b7d7f6ff00144152aff453e6b388447320c
-Merge: 42ce934 dfe22fd
-Author: Carsten Bock <carsten at ng-voice.com>
-Date:   Thu Sep 11 16:56:51 2014 +0200
+commit dfd8ec8c1e9f0a5c3c7aad6ec984e7a664e5af49
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Sun May 26 13:54:15 2013 +0100
 
-    Merge branch 'master' of ssh://git.sip-router.org/sip-router into carstenbock/db_cassandra_deb
+    pkg/kamailio/(centos|fedora): Added rpm for sctp module
     
-    Conflicts:
-    	Makefile.groups
-    	pkg/kamailio/deb/wheezy/control
-    	pkg/kamailio/deb/wheezy/rules
+    - Also updated release to dev6
 
-commit dfe22fd0c69d58702e8d12ba4f6b7891bb48896e
-Author: lazedo <luis.azedo at factorlusitano.com>
-Date:   Thu Sep 11 14:47:33 2014 +0100
+commit 1977645ceb12ca2d0f2f767046606f6c5ae2c3bb
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Sun May 26 10:43:24 2013 +0200
 
-    support vhost in connection
+    dmq: many safety checks for mem mallocs and function return codes
+    
+    - added license header in the files
 
-commit 0d9cf1bd0b34f0fe718d6f52edf72b5a890b62fe
-Author: lazedo <luis.azedo at factorlusitano.com>
-Date:   Thu Sep 11 14:47:33 2014 +0100
+commit a85e7e5c192e4f597d17c98f4036d83639c6bc1f
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Sun May 26 10:12:24 2013 +0200
 
-    support vhost in connection
+    core: safety check for initialized SCTP API
+    
+    - reported by Juha Heinanen
 
-commit 9673bbe0fff1c3f05803a7a51f16cee9d299601f
-Author: Carsten Bock <carsten at ng-voice.com>
-Date:   Thu Sep 11 12:19:18 2014 +0200
+commit 59c4a6550862ed7c3e8c63a3a5d5c1dcd404bd6d
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Sat May 25 21:28:33 2013 +0200
 
-    ims_registrar_pcscf: Safety check, if (r) is set (caused a crash)
+    tm: return current branch id if sending fails and tm_failure_exec_mode=1
+    
+    - reported by Juha Heinanen
 
-commit 23a35c0598696a7a4e97c95466b321ade05bf823
+commit 93d97e53741d786692903bd9df9622cd55e4cfea
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Sep 11 12:10:44 2014 +0200
+Date:   Sat May 25 21:04:43 2013 +0200
 
-    Makefile.defs: version set to 4.2.0-pre0
-    
-    - pre-release phase - testing period, no new features till branching 4.2
+    sctp: documented module parameters
 
-commit 14183ffa5e1bab1659d1df87a77057d50c376029
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Thu Sep 4 07:09:02 2014 -0700
+commit 2e6675bd92968fd96865ee266ca4ba10c7cc1cdc
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Sat May 25 17:14:23 2013 +0200
 
-    msg_parser: fix To parameter with null value parsing
+    Makefile.defs: version set to 4.1.0-dev6
 
-commit 81fbf1504548c0978f4e8f056df594f57d681e88
-Author: Carsten Bock <carsten at ng-voice.com>
-Date:   Thu Sep 11 11:17:43 2014 +0200
+commit c4cf64ea992e0f0f46f1c6fc23c6f38c05a80b0f
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Sat May 25 17:05:58 2013 +0200
 
-    ims_auth: Fix crash, if the third parameter was ommited on ims_www_challenge.
+    sctp: added skeleton files for docbook module documentation
 
-commit 35e94c97dfb2f6519c87e566b5158e5b9b9f39ef
+commit 25c3df171d219eb71c63f4832b69f33b470c9c96
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Sep 11 00:16:53 2014 +0200
+Date:   Sat May 25 16:42:21 2013 +0200
 
-    core: new parameter - log_prefix
+    Makefile.groups: added compile group for sctp module
     
-    - can be used to set what prefix to be printed for each log message
-      while processing a SIP message
-    - can contain variables
-    - example:
-      log_prefix="[$mt $hdr(CSeq) $ci]"
+    - depends on libsctp-dev
 
-commit 975288957ae47e2bcf3472780fe4f085605297fa
-Author: Alexandr Dubovikov <alexandr.dubovikov at gmail.com>
-Date:   Wed Sep 10 22:25:56 2014 +0200
+commit 1bdbdb64e4862ddb69c2bf13be0f9be93968bb1e
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Sat May 25 16:30:33 2013 +0200
 
-    modules:sipcapture fixed duplicate value
+    protoshoot: use Makefile pattern for utils
+    
+    - link to libsctp if SCTP support is enabled
 
-commit fc103f947d2c2eeb4ed6f6e30f45bc9603ca86c4
-Author: Carsten Bock <carsten at ng-voice.com>
-Date:   Wed Sep 10 21:52:11 2014 +0200
+commit a2afc3d42224d0c35e4867ad50251e7aa6231879
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Sat May 25 15:42:14 2013 +0200
 
-    ims_usrloc_pcscf: Set proper field for service routes, when saving to DB
+    core: filled sctp core api
+    
+    - cleanup of not needed members
 
-commit b05795313b031d50a78589ba2bd89dd0d1811166
-Author: Carsten Bock <carsten at ng-voice.com>
-Date:   Wed Sep 10 21:51:20 2014 +0200
+commit 61f5f6a63409f856a03b48e9ced22ad5c724acb2
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Sat May 25 15:41:27 2013 +0200
 
-    ims_registrar_pcscf: Add option to ignore "REGISTERED STATE", when checking for a registered client.
+    sctp: register sctp core api
+    
+    - done in mod_register() function
+    - initialize the sctp options before modparams
 
-commit 54671510ee5864f51cf5079fd2d59df6b00b88d8
-Author: Alexandr Dubovikov <alexandr.dubovikov at gmail.com>
-Date:   Wed Sep 10 20:49:07 2014 +0200
+commit e9f7980602cadcc179425cad57a4d0f89c63fb55
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Sat May 25 15:39:13 2013 +0200
 
-    modules:sipcapture  fixed sql schema to version 4. Added optimized partrotation script.
+    core: remove sctp options init from core
+    
+    - will be done in mod_register() from sctp module
+    - don't print anymore info about sctp unsupported socket options in
+      output of -v, they are known now only in sctp module which is not
+      loaded at that time
+    - sctp will print a warn message in mod init about unsupported socket
+      options
 
-commit a35f99d0bceeb49edc0ebe782fad04db8476f3d9
+commit cbbaf9abd5f34b50c47ac2ac350c77d3f36b511b
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Sep 10 20:16:31 2014 +0200
+Date:   Sat May 25 11:57:02 2013 +0200
 
-    topoh: documentation updated for mask_ip parameter
+    sctp: exported sctp parameters via module interface
 
-commit a0cd3fb7e3ae77c1305c05038d45ce55581b44aa
+commit e549d96b571ae509a67984be789b281ed2230bc3
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Sep 10 20:11:36 2014 +0200
+Date:   Sat May 25 11:24:22 2013 +0200
 
-    topoh: allow server ip to be used as mask ip
+    core: readded conditions for core sctp forwarding functions
+    
+    - typo fixed in log message
 
-commit 6435d8a8666423eda76a0bddae5ee74690882969
+commit 66e90f9888daefdb92dcebd28e188ce7f912a4f9
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Sep 10 20:11:14 2014 +0200
+Date:   Sat May 25 10:56:11 2013 +0200
 
-    core: fix execution of callbacks list for net_data_in
+    core: added sctp callbacks api
+    
+    - functions needed in core - callbacks to be set by sctp module
 
-commit ec1dfe890db6bd8ea50edc55e6774908d74a672e
+commit d60d41136575408ea7ea9031c735476967755e46
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Sep 10 18:55:44 2014 +0200
+Date:   Sat May 25 10:54:33 2013 +0200
 
-    usrloc: new parameter db_raw_fetch_type
+    sctp: add module interface for sctp transport
     
-    - specify what type of query should be used in DB-only mode for
-      retrieving contacts for specific needs (e.g., sending NAT keepalives)
+    - sctp support is now implemented as a standalone module
+    - the core still needs SCTP=1 (now default) and -DUSE_SCTP to get the
+      hooks enabled
 
-commit 81e749aedccd96310a65a8578da48e3d9b80df26
+commit af2473d426870650a0f4a2cb820894ee4dd793d0
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Sep 10 18:35:19 2014 +0200
+Date:   Sat May 25 10:53:04 2013 +0200
 
-    Makefile.groups: ndb_mongodb added to mongodb modules group
+    Makefile.defs: don't link to libsctp on Linux for SCTP support
+    
+    - only sctp module needs to link to it
 
-commit 97b8731504d6103e301c77f3523b451524d0d461
+commit f91c9696cc92ec4b74dd2494c39bbf2ffe062fab
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Sep 10 18:06:38 2014 +0200
+Date:   Sat May 25 09:35:22 2013 +0200
 
-    ndb_mongodb: new module offering a non-db connector to MongoDB from config file
+    core: added file sctp core interface
 
-commit 17fa8ffec54baa65d2a138fe46f236d4d6d4a231
-Author: Carsten Bock <carsten at ng-voice.com>
-Date:   Wed Sep 10 17:47:07 2014 +0200
+commit 7f8e7a8568740be65eada1cbd59110bb765f4d5a
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Sat May 25 09:33:39 2013 +0200
 
-    ims: Updated example configurations
+    sctp: new module for SCTP transport
     
-    Enhancements:
-    - Added Ro to the S-CSCF
-    - Added database support, optionally use db_cluster
-    - Replaced RTPProxy with RTPEngine module, support for originating WebRTC on the Proxy-CSCF (with SRTP Breaking)
-    - Optionally engage a SBC between the P-CSCF and the Core, SEMS sample configuration
-    - smaller adjustments
+    - moved the sctp specific code from core to a module to make it easy to
+      enable/disable sctp by loading/not loading the module instead of
+      recompiling
 
-commit a2cf37e0edc89f5bef9ae193122053de4652249f
-Author: Carsten Bock <carsten at ng-voice.com>
-Date:   Wed Sep 10 17:32:40 2014 +0200
+commit 6287caecc438ace98a3ce3dc7a53e6064d7894dc
+Author: Henning Westerholt <hw at kamailio.org>
+Date:   Fri May 24 15:38:03 2013 +0200
 
-    ims_*_pcscf: Several bugfixes
+    core: remove syn_branch functionality for calculating Via branch parameter
+    
+    * remove syn_branch parameter and functionality from core and tm module for
+      calculating the Via branch parameter
+    * reported from Richard Brady, rnbrady at gmail dot com to sr-dev
+    * kamailio is not standard compliant with this setting enabled (RFC 3261,
+      17.2.3 and 16.11) for stateless forwarding of replies
+    * the performance reason that motivated this functionality are today not
+      valid anymore, even embedded systems have more than enough power to
+      calculate MD5 and other modules uses more expensive operations anyway
+    * adapt a bunch of example and test configuration that used this parameter,
+      it has been also removed from the core cookbook wiki
 
-commit dae74e974a028082a3250805da83223220123c10
-Author: Luis Azedo <luis at 2600hz.com>
-Date:   Wed Sep 10 15:23:45 2014 +0100
+commit 28942a00bc7be5194625b9ed08facd2f95ebea81
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Fri May 24 00:36:57 2013 +0200
 
-    proposed change for dbtext query results.
-    this behaviour was observed by interacting with module presence.
+    pv: added $_s(format) variable
     
-    presentity clean runs from timer every 6 secs.
-    if the first run returns a large set of rows, it iterates all rows doing
-    some notifications and deleting the presentity.
-    if it takes more then 6 secs to complete, the next run will override the
-    results internal structure pointer maintained in the connection level.
+    - evaluate the format as a dynamic string
     
-    the proposed patch, maintains the query result internal structure within
-    the result, using the ptr field for that.
+    $var(x) = "sip:" + $rU + "@" + $fd;
+    
+    is equivalent of:
+    
+    $var(x) = $_s(sip:$rU@$fd);
+    
+    - it can be more compact sometimes in config
 
-commit 84be6b8e4ddeda5955e67678c8af1080a292b707
-Author: Federico Cabiddu <federico.cabiddu at gmail.com>
-Date:   Wed Sep 10 13:23:10 2014 +0200
+commit 76c883eb88359f6075712f648a1dfc675872487a
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Thu May 23 12:06:45 2013 +0200
 
-    tsilo: initial commit
+    auth: add chapter tag around sections for Admin Guide
+    
+    - the ToC isn't properly generated otherwise
+    - reported by Andrew Pogrebennyk
 
-commit 468a2c645f5fcb66376b81b06e69eb8f5377bb02
-Author: Federico Cabiddu <federico.cabiddu at gmail.com>
-Date:   Tue Sep 9 14:14:46 2014 +0000
+commit b3c69488bf80e76c2359f6d9611cbcf2edf6c67f
+Author: Victor Seva <linuxmaniac at torreviejawireless.org>
+Date:   Thu May 23 09:45:03 2013 +0200
 
-    tm: new api function t_append_branches
+    modules/debugger: update documentation. This is Kamailio!
 
-commit ccaa53b1227e6ac516efc42db1315ea96fe4e95a
-Author: Federico Cabiddu <federico.cabiddu at gmail.com>
-Date:   Tue Sep 9 07:32:41 2014 +0000
+commit 169e92b86d6a1a98be92d0012bd831785855b968
+Author: Victor Seva <linuxmaniac at torreviejawireless.org>
+Date:   Thu May 23 09:07:53 2013 +0200
 
-    registrar: new api function lookup_to_dset
+    modules/debugger: refresh README
 
-commit 603c5d20655bde63f6dc8af5ce2c0a16baee5ed3
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Sep 10 12:58:29 2014 +0200
+commit 6417ac9f99a0c97254206797070bbe3095002847
+Author: Victor Seva <linuxmaniac at torreviejawireless.org>
+Date:   Thu May 23 09:04:12 2013 +0200
 
-    Makefile.groups: added group for monogdb
-    
-    - db_mongodb included in it, depends on mongodb-c-driver library
+    modules/debugger: use cfg framework to be able to activate/deactivate debug per module.
+    add missing files from commit.
 
-commit c716e1a5167a0fcd963d13e74b1811c0f049cd7a
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Sep 10 12:54:37 2014 +0200
+commit feb00c92297eb2d4520a59f1a676cf998add1b5d
+Author: Victor Seva <linuxmaniac at torreviejawireless.org>
+Date:   Thu May 23 08:58:38 2013 +0200
 
-    Makefile.groups: group for kazoo module
+    modules/debugger: use cfg framework to be able to activate/deactivate debug per module.
     
-    - depends on rabitmq, libxml2 and libjson
+    mod_hash_size has to be set with a value > 0 on startup.
 
-commit e134574be9b63cecce308d7483f5a7e70f287e1c
-Author: lazedo <luis.azedo at factorlusitano.com>
-Date:   Wed Sep 10 11:04:15 2014 +0100
+commit 31880a46d7f634b568cc192bec6db3d969e738ef
+Author: Klaus Darilion <klaus.mailinglists at pernau.at>
+Date:   Tue May 21 12:39:15 2013 +0000
 
-    kazoo initial commit
+    modules/auth_db: detailed documentation of URI checking in auth_check function
 
-commit 53771bd598012b1029b06797c3d49026a8514cdd
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Sep 10 11:39:13 2014 +0200
+commit 2669197352bfc20bc916c00f74ac14380f8a62f8
+Author: Juha Heinanen <jh at tutpro.com>
+Date:   Mon May 20 21:03:30 2013 +0300
 
-    db_mongodb: new module offering DB APIv1 connector for MongoDB NoSQL server
+    modules/usrloc: fixed unregister bug in db_mode=3
     
-    - initial version, tested for INSERT (e.g., can be used with acc module)
-    - UPDATE and DELETE implemented as well, no option to test them yet
-      alone
-    - SELECT implemented for basic queries, but store result not implemented
-      yet -- needs to map the requested fields and types (to be fixed very
-      soon)
-    - no raw query yet (an ndb alternative to follow)
+    - Commit ce1d16ce1c8009918c294307de53f35378868b52 introduced unregister
+      but that appeared in db_mode=3 when db_ops_ruid param is not set.
+    - Reported by Peter Dunkley.
 
-commit d202dac87dab4bb92de9aa26ac9614225938524f
-Author: Carsten Bock <carsten at ng-voice.com>
-Date:   Wed Sep 10 11:13:44 2014 +0200
+commit c9448d9657f0e5792072c6803643c8d9075d711a
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Mon May 20 18:33:52 2013 +0100
 
-    ims_registrar_pcscf: Fix previous commit (copy&paste error)
+    modules/rr: completely reverted after_strict() to its pre-outbound form
 
-commit 6f79459b8aea611acce81468198e0b7e775a51d5
-Author: Carsten Bock <carsten at ng-voice.com>
-Date:   Wed Sep 10 10:41:42 2014 +0200
+commit f0ae598a3e63e62d12a143c6cd42b698ad1f2eed
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Sun May 19 23:56:06 2013 +0100
 
-    ims_usrloc_pcscf: New hashing_type: "2" Hash over received IP, fallback to Host from contact (especially for NAT)
+    modules/websocket: Improved module_loaded() check for nathelper and outbound so it only fires when the SIP subprotocol is enabled
 
-commit eec712826c17ba8270e35033d608781ce74940d5
-Author: Carsten Bock <carsten at ng-voice.com>
-Date:   Wed Sep 10 10:39:34 2014 +0200
+commit 45d4e808f0551a5eeb832574327a2b5b7aecf2c5
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Sun May 19 23:18:19 2013 +0200
 
-    ims_registrar_pcscf: Optimization: fallback2ip can be set to "2", in order to check for the source IP first, before checking the contact-host of the request.
+    uac: reorder fileds in uac structure
 
-commit 9556f8a37575c8f9a3a212f07e9fa9632116e06e
-Author: Charles Chance <charles.chance at sipcentric.com>
-Date:   Wed Sep 10 00:41:48 2014 +0100
+commit 97a899e37acda1ef0c70a009f4fd9d221ee8a58e
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Sun May 19 23:16:55 2013 +0200
 
-    dmq: update documentation with new functions dmq_t_replicate() and dmq_is_from_node()
+    seat: removed no longer necessary init of tm uac struct
 
-commit 3bf32dc0003b447a5695be5ff9d22d70f393c62f
-Author: Charles Chance <charles.chance at sipcentric.com>
-Date:   Tue Sep 9 23:52:46 2014 +0100
+commit b867893d0bbdda0c926a7cd0b6b3a46d4324631e
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Sun May 19 23:15:42 2013 +0200
 
-    dmq: include resolved IP address in RPC list_nodes output
+    dialog: remove unnecessary tm uac struct init
 
-commit d99a9c7f47613078f9d8ab42959e954fc58518f7
-Author: Charles Chance <charles.chance at sipcentric.com>
-Date:   Tue Sep 9 23:42:35 2014 +0100
+commit 94833f8b8b94398566991713730b66a792b57056
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Sun May 19 23:09:52 2013 +0200
 
-    dmq: add the following config functions:
+    tm: initialize the uac structure to 0 for local generated requests
     
-    - dmq_t_replicate(): Replicates current SIP message to all active DMQ nodes. Includes built-in loop detection which can be skipped with optional parameter.
-    - dmq_is_from_node(): Checks whether current message has come from another node, based on source IP.
+    - safer for adding new fields to it not set via set_uac_req()
 
-commit b7bbcd730b21e7480dc1f1e26de58750395e6ff6
-Author: Charles Chance <charles.chance at sipcentric.com>
-Date:   Tue Sep 9 23:41:47 2014 +0100
-
-    dmq: resolve IP address and store in node structure
+commit a53580d39c2fadf2ddc6f9805f15ac833cfd4c20
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Sun May 19 14:55:52 2013 +0200
 
-commit 1110d4e6b5ec2f949951c9433a80bced778272d9
-Author: Juha Heinanen <jh at tutpro.com>
-Date:   Tue Sep 9 20:41:47 2014 +0300
+    tm: new parameter - failure_exec_mode
+    
+    - specify whether to consider or not execution of failure routing blocks
+      for braches that had local delivery error (e.g., no open tcp
+      connection and set_forward_no_connect() used in config)
 
-    modules/rtpengine: generated README
+commit 78669def2790205270032f9a750b19cc86f3d560
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Sun May 19 10:22:10 2013 +0200
 
-commit 0db2ee84ae1c24fae6196f42034c68e5d16ea189
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Tue Sep 9 18:26:02 2014 +0200
+    tm: added icode to uac_client structure
+    
+    - store internal processing code, to give hints of what happened
+    - could be used to map sip warning codes
+      http://www.iana.org/assignments/sip-parameters/sip-parameters.xml#sip-parameters-5
+    - delivery failure on case of no connection mapped temporarly to 908
 
-    modules/ims_qos: new mod_param: authorize_video_flow
-    	authorize_video_flows is a flag that specifies whether or not to authorize video flows.
+commit cbcf86a036e6f8607f783ce18491121b0d58d2b0
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Sun May 19 10:16:40 2013 +0200
 
-commit e5c9f006060b5b4d00c9ab56f25521debee32216
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Tue Sep 9 16:56:00 2014 +0200
+    tm: keep uac_client structure aligned on 32b
+    
+    - otherwise it may create troubles on restrictive archs
 
-    modules/ims_qos: store AAR flow descriptions in CDP session
-    	When flow_descriptions are installed save the active and new
-    	This allows Rx to fallback to previous flow descriptions if there is an upstream failure
+commit 90c69665edcfc9aebf265f280375251306442b98
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Sun May 19 10:03:02 2013 +0200
 
-commit e6591dc75d34e8522060ea71148b4cdcae139234
-Author: Richard Fuchs <rfuchs at sipwise.com>
-Date:   Tue Sep 9 10:37:53 2014 -0400
+    tm: use - instead if _ in branch-failure examples
+    
+    - it is what is expected by module
 
-    rtpengine: docs update
+commit 1a099f704ffbb93f5c6389e86daa5af90aeb72f1
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Sat May 18 22:20:57 2013 +0100
 
-commit d54bcfad39f6b3f79a826cab4df83bb7eea189a9
-Author: Richard Fuchs <rfuchs at sipwise.com>
-Date:   Tue Sep 9 10:30:45 2014 -0400
+    pkg/kamailio/(centos|fedora): Updated changelog in .spec
 
-    rtpengine: support arbitrary direction= flags for interface bridging
+commit 5cff9062807ed181eae3a1db2d70fa625f647a4c
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Sat May 18 22:17:22 2013 +0100
 
-commit f049d553bf4de88c7f1c94c7aeaeb02620d6fec6
-Author: Richard Fuchs <rfuchs at sipwise.com>
-Date:   Tue Sep 9 10:07:33 2014 -0400
+    pkg/kamailio/(centos|fedora): refactored .spec
 
-    rtpengine: support daisy-chaining two RTP proxies
+commit 7ebf6affca7b2585353baa91f1560ff606979973
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Sat May 18 20:43:05 2013 +0100
 
-commit 4776b44ea9c5546c37fea9f3886148a17c735fe5
-Author: Elena-Ramona Modroiu <ramona at asipto.com>
-Date:   Tue Sep 9 15:24:47 2014 +0200
+    modules/websocket: Updated documentation
 
-    htable: documentation for iterator functions
+commit 20438793a5199ea90f0261a3b72b1b70e9566a30
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Sat May 18 20:42:53 2013 +0100
 
-commit 0c62f0d960ce4786bbf8d0bd9b7b0ce8fcf0cd7b
-Author: Elena-Ramona Modroiu <ramona at asipto.com>
-Date:   Tue Sep 9 14:56:35 2014 +0200
-
-    htable: iterator implementation for hash tables
-    
-    - new functions:
-        - sht_iterator_start(iname, hname)
-        - sht_iterator_next(iname)
-        - sht_iterator_end(iname)
-    - iname is a string to identify the iterator
-    - hname is the name of a hash table
-    - note that the slot is left locked by sht_iterator_next(), therefore
-      there must be no update to the hash table content in between
-      sht_iterator_start() and sht_iterator_end()
-    - sht_iterator_end() must be called for each sht_iterator_start() with
-      the same iterator name
-    - internally can be up to 4 iterators at one time, they can have different names
-    - the current item in the iterator is accessible via:
-        - $shtitkey(iname)
-        - $shtitval(iname)
-    - example
-    
-    sht_iterator_start("i1", "h1");
-    while(sht_iterator_next("i1")) {
-        xlog("h1[$shtitkey(i1)] is: $shtitval(i1)\n");
-    }
-    sht_iterator_end("i1");
+    modules/outbound: Updated documentation
 
-commit 43de8b203c569f8ebe47f28a9049d671a92852ea
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Sep 9 12:28:09 2014 +0200
+commit 6dc38a3618b2ad08bbc6feeee1c44ca19e0c5bd6
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Sat May 18 20:42:24 2013 +0100
 
-    jsonrpc: reset the local reply structure before executing new commands
+    modules/msrp: Updated documentation
 
-commit accfbe0abb0d811e249b687cb6047c9234a6d884
-Author: Hugh Waite <hugh.waite at acision.com>
-Date:   Mon Sep 8 17:46:55 2014 +0100
+commit a1136bf809e7d088332d54440a72edee4e30c26a
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Sat May 18 20:27:45 2013 +0100
 
-    parser: Fix parsing of Retry-After header
+    modules/outbound: moved the check for "Supported: outbound" to after the checks on the Route: header
     
-    - Allow no space between duration and optional comment
+    - In the scenario when a call comes from a non-outbound end-point to an
+      outbound end-point the outbound options-tag will not be present, but outbound
+      should still be used on the final leg between the edge-proxy and the
+      end-point.
 
-commit 74a2f193bcf2c9be893cf72b2cede750a72eea5d
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Sep 9 12:13:33 2014 +0200
+commit 8750305d4686ccae3a168454c4191f9b05d93ee3
+Merge: e81b3aa abdf40d
+Author: Konstantin Mosesov <ez at voipgroup.org.ua>
+Date:   Sat May 18 13:59:07 2013 +0300
 
-    jsonrpc-s: documentation for jsonrpc_exec(cmd)
+    Merge branch 'master' of ssh://git.sip-router.org/sip-router
 
-commit 01e234a1e42fadcb9f3d14eedbcace1bb2ae56bb
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Sep 9 12:06:03 2014 +0200
+commit e81b3aac19ab567813d6cb21fcba3d9bd6e1cc90
+Author: Konstantin Mosesov <ez at voipgroup.org.ua>
+Date:   Sat May 18 13:56:22 2013 +0300
 
-    jsonrpc-s: new config variable $jsonrpl(key)
+    parser/sdp: Fixed segfault in sdp_print() when no SDP body.
     
-    - access jsonrpc reply when using jsonrpc_exec(cmd)
-    - the key can be:
-      - code - the response code as when the jsonrpc would have been executed over
-      	http
-      - text - the text following the code as when the jsonrpc would have
-      	been executed over http
-      - body - the body of the jsonrpc response - the full json document
-
-commit 7bbe69bf6aa0798c674898aeb23b81249b177e34
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Sep 9 11:38:12 2014 +0200
-
-    jsonrpc-s: new fucntion jsonrpc_exec(cmd)
+    - Failed scenario:
+    remove_body();
+    msg_apply_changes();
+    sdp_print("1");
     
-    - execute the jsonrpc command given as parameter
-    - cmd has to be a full json rpc document
-    - example:
-        jsonrpc_exec('{"jsonrpc": "2.0", "method": "dispatcher.reload", "id": 1}')
-    - the cmd can be a dynamic string with variables
+    - Result: sdp=0x0
 
-commit 94f1d28e2a08736b2abc69bcb6fd4bc538948f34
-Author: Alexandr Dubovikov <alexandr.dubovikov at gmail.com>
-Date:   Tue Sep 9 10:21:12 2014 +0200
+commit abdf40dabb7e7d44398056b9c2c72c0615debb52
+Author: Henning Westerholt <hw at kamailio.org>
+Date:   Sat May 18 10:07:25 2013 +0200
 
-    modules/sipcapture: Added RTCP and LOG functionality. Updated kamilio.cfg, SQL schema, rotation script for Homer 3.6
+    core and modules: make IPv6 default, remove compile time flags
+    
+    * Make IPv6 the default in the core and affected modules
+    * it has been default switched on since a long time, and was introduced in 2002
+    * even on embedded systems one probably want now proper IPv6 support
+    * there was an issue in cygwin in 2008, but IPv6 is there also available since v1.7
+    * remove over 160 #ifdefs, cleanup the code a lot and removes many of rarely
+      tested alternative code paths to ease support of the codebase
+    * note for gentoo maintainer: please review your packages, they will maybe not
+      work now correctly anymore if somebody specified -ipv6 in the use flags
 
-commit 03f2c33ea95ef865017f57035f4b2a3a24e55883
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Sep 9 09:14:38 2014 +0200
+commit 1b0ad814aec79a44b865ad2d3552c4693fe2ea6d
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Sat May 18 00:18:43 2013 +0100
 
-    presence: documented local_log_level parameter
+    modules/{various}: updated because there is now an extra parameter on the append_branch() function
 
-commit 2ae18b74b76627d5bad05dcce4bc7a9e6f628863
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Sep 9 09:10:49 2014 +0200
+commit 42063cacea9bf0f001f44b11216572b4f46e6e2d
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Sat May 18 00:17:48 2013 +0100
 
-    presence: new parameter local_log_level
-    
-    - control verbosity of some log messages
-    - default value: L_INFO
+    modules/ims_registrar_scscf: use #define from core .h to specify the maximum UA length
 
-commit b10359955348294d81efd9ebb80f68d81cf72e54
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Sep 8 23:04:35 2014 +0200
+commit 3ec65f1cfebad258e7ef0cc622ed143284c3edf1
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Sat May 18 00:15:59 2013 +0100
 
-    usrloc: documented expires_type parameter
+    modules/tm: copy user-agent string retrieved from usrloc into branches when serial forking
 
-commit cb6e934a591451c23f7736bd88ea5953cacd9ebf
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Sep 8 22:36:30 2014 +0200
+commit 5aeef2c932581a67d535ade10995cc35ff85640a
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Sat May 18 00:15:21 2013 +0100
 
-    usrloc: option to set datetime columns as bigint
-    
-    - should handle better daylight shifting, reported by Alistair
-      Cunningham
-    - new parameter expires_type - if set to 1, it expects expires and last
-      modified columns to be bigint
-    - the change to the type of columns has to be done manually to the
-      database server
-    - default values is 0, expecting to work with datetime columns (existing
-      behavior)
+    modules/registrar: store user-agent string retrieved from usrloc in msg and branch structures
 
-commit 3ea4bc0b15414e0bf4b57d1f7a563ad38347d938
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Sep 8 18:57:37 2014 +0200
+commit 7bb5f98d7fd77ca6c21fb11e16d69116ef12cbb2
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Sat May 18 00:14:07 2013 +0100
 
-    dispatcher: reset whitespaces to tabs for identation
+    modules/pv: added PVs to provide access to the user-agent string retrieved from usrloc
 
-commit c7adc3cd7610fe1b6479225a0623e0ab9fa3907e
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Sep 8 18:49:28 2014 +0200
+commit 8ca114df0fad44e4819cf80840f90e526ff655b4
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Sat May 18 00:13:11 2013 +0100
 
-    presence: reduce verbosity for log message printed when sending notify
-    
-    - info changed with dbg
-    - patch by Luis Azedo <luis.azedo at factorlusitano.com>
+    core: added fields to message structure and branch structure to hold user-agent string retrieved from usrloc
 
-commit 9a46452cf724457edeea2cd0fd88a6652d22a61d
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Sep 8 18:45:52 2014 +0200
+commit 381a052a8864198a62057dc307fdf39bbffe5436
+Author: Konstantin Mosesov <ez at voipgroup.org.ua>
+Date:   Fri May 17 21:35:59 2013 +0300
 
-    pv: new variable $su to return source address in uri format
-    
-    - $su is expanded "sip:$si:$sp;transport=$pr"
-    - example: "sip:127.0.0.1:5060;transport=udp"
+    modules/sdpops: Added new function sdp_get_line_startswith(avpvar, string).
 
-commit 309b25afb335444c11d6a86efc997fc4b88fdfb4
-Author: Elena-Ramona Modroiu <ramona at asipto.com>
-Date:   Mon Sep 8 18:43:35 2014 +0200
+commit 121c5a49f81effdac42977d716332215d6a95e4f
+Author: Konstantin Mosesov <ez at voipgroup.org.ua>
+Date:   Fri May 17 21:14:29 2013 +0300
 
-    htable: documented sht_reset(...)
+    uac: Added ability to set Call-Id through $uac_req(callid).
 
-commit fcd13777bab83eeedc7628145b8e4f7430668372
-Author: Elena-Ramona Modroiu <ramona at asipto.com>
-Date:   Mon Sep 8 18:39:36 2014 +0200
+commit 012816e404b52de697514e4f897ec8a8abe42abc
+Author: Victor Seva <linuxmaniac at torreviejawireless.org>
+Date:   Fri May 17 17:49:14 2013 +0200
 
-    htable: new config function sht_reset("tname")
-    
-    - remove all items in the hash table
+    modules/debugger: refresh README
 
-commit a39e8db53e6a99545385c6b8d4bfc77217f788c4
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Sep 8 17:15:34 2014 +0200
+commit dbefbe319ba13b008ad46576dbc8a00d305e9910
+Author: Victor Seva <linuxmaniac at torreviejawireless.org>
+Date:   Fri May 17 17:48:17 2013 +0200
 
-    dispatcher: regenerated readme file
+    modules/debugger: Added dbg.mod_level RPC command
 
-commit 121cb0f4feb2cc1a670d17432593ff7e025d65a5
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Sep 8 17:13:12 2014 +0200
+commit e46e0c78ee4f535cd09b8ee9fcdba4ee7bb5b518
+Author: Vicente Hernando <vhernando at systemonenoc.com>
+Date:   Fri May 17 13:31:19 2013 +0200
 
-    dispatcher: swap the order between uri and mode parameters in the new ds_is_from_list(...)
-    
-    - allow to have ds_is_from_list() only with group id and mode, uri is
-      the last parameter, still optional
-    - patch provided by Luis Azedo <luis.azedo at factorlusitano.com>
+    modules/uac: update README
 
-commit 1e84aeb91cf8e7a79a9ac9091ed993be944a667b
-Author: Luis Azedo <luis.azedo at factorlusitano.com>
-Date:   Mon Sep 8 17:07:11 2014 +0200
+commit fed1818b65c6cbab89cd7aa64ad8f5f6535d706c
+Author: Vicente Hernando <vhernando at systemonenoc.com>
+Date:   Fri May 17 13:30:05 2013 +0200
 
-    usrloc: don't add columns without values in the sql query
-    
-    - works better with db_text as well as the resulted query is smaller
+    modules/uac: upgrade doc to module.type.name format
 
-commit 5bffcf8bdc83628aea4f5e3cda06b20ce88f659f
+commit 257366739a7087953c0ff9e0dff82f3d2cf7c8b4
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Sep 8 14:14:17 2014 +0200
+Date:   Fri May 17 10:13:06 2013 +0200
 
-    presence: take in consideration send_fast_notify when sending empty NOTIFY
-    
-    - patch by Luis Azedo <luis.azedo at factorlusitano.com>
+    Makefile.defs: version set to 4.1.0-dev5
 
-commit 37e1fb443f1243125bc1d0c09c5ad8f6d86336d6
+commit 86fce4b7b5e8bb56c65d628409ee50ecfb2756c4
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Sep 5 17:46:14 2014 +0200
+Date:   Fri May 17 10:12:00 2013 +0200
 
-    dispatcher: extended the documentation for ds_is_from_list()
+    debugger: documented new parameters related to per module log level
 
-commit 6016958dfe71996689abc897baa629afb3b1c552
+commit 72f1b495c42933fea96a019e140dc6333fda2eb3
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Sep 5 17:21:40 2014 +0200
+Date:   Fri May 17 09:58:19 2013 +0200
 
-    dispatcher: new variant - ds_is_from_list(groupid, uri, mode)
+    debugger: option to set debug level per module
     
-    - can match against records in dispatcher groups
-    - if groupid==1 - will match against all groups
-    - if uri is empty, then will match against source address (ip, port,
-      proto). Otherwise it has to be a full SIP URI value. The matching
-      is not taking in consideration any parameter apart of transport
-    - mode is a bitmask to tell the matching rules
-    	- if it is 0, will match everything: ip, port and protocol
-    	- if bit one is set, will skip matching the port
-    	- if bit two is set, will skip matching the protocol
+    - new parameters:
+    	- mod_hash_size - size of internal hash table to store levels per
+    	  module (used to compute power of two with it)
+    	- mod_level_mode - enable/disable per module log level
+    	- mod_level - specify module log level
+    modparam("debugger", "mod_hash_size", 5)
+    modparam("debugger", "mod_level_mode", 1)
+    modparam("debugger", "mod_level", "core=3");
+    modparam("debugger", "mod_level", "usrloc=3");
 
-commit 3b159696b1e418360de30b370ec61390cd0ca7e3
+commit 34378c35b7cd037051af71081a9fa4d8b188c157
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Sep 5 16:18:38 2014 +0200
+Date:   Fri May 17 09:56:34 2013 +0200
 
-    core: proper reverse order execution for net_data_out event callbacks
+    core: updated dprint api to enable support for debug level per module
+    
+    - a callback can be registered to return the log level based on module
+      name
 
-commit 1f1705a6b5f262e8fab88181edddd3fc5276f0a0
+commit e081c2880b46174ad836ab1f56e3062bb17b4332
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Sep 5 16:11:51 2014 +0200
+Date:   Fri May 17 00:46:42 2013 +0200
 
-    core: allow up to three callback functions for net_data_in and net_data_out
+    core: fixed printing function name in log message
     
-    - they are added normal for net_data_in and reverse for net_data_out,
-      allowing nested execution (e.g., first module registering the two
-      callbacks with have the first net_data_in and the last net_data_out)
-    - allow topoh module can be used with other functionalities needed the same
-      callbacks
+    - based on http://gcc.gnu.org/onlinedocs/gcc/Function-Names.html
 
-commit 072d61918c10006779123b00ab597c1c09334e1c
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Sep 5 16:06:00 2014 +0200
+commit a4fb559b5634f91259bb96af991c5574719e6871
+Author: Victor Seva <linuxmaniac at torreviejawireless.org>
+Date:   Fri May 3 09:21:04 2013 +0200
 
-    corex: fixed for loop in previous commit
+    utils/kamctl: Add contact path parameter
 
-commit af69a3075ac4a7a46d72b0d60e6bc1740a56b7a7
-Author: Juha Heinanen <jh at tutpro.com>
-Date:   Fri Sep 5 17:11:47 2014 +0300
+commit ad0e5daa8865024440ea37a9e978eeeb7577602f
+Author: Victor Seva <linuxmaniac at torreviejawireless.org>
+Date:   Thu May 2 18:30:50 2013 +0200
 
-    modules/mtree: fixed return value of mt_match when mode=2
-    - initialize pv_values avp by mt_match when mode=2
-    - documented mt_match return value
+    modules/usrloc: use 6th param to set the contact path
 
-commit 36729fc15334711a22ee08616ba4dafa071479c6
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Sep 5 15:39:56 2014 +0200
+commit c454e4b0129695c7647f6af8e42a38d785d58a7d
+Author: Victor Seva <linuxmaniac at torreviejawireless.org>
+Date:   Thu May 2 16:56:45 2013 +0200
 
-    corex: documented functions used for management of sip msg internal flags
+    Fix ul.dump q output value
 
-commit 9108218677d52c4ca2b430bcfcae72fe574c85cd
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Sep 5 15:31:30 2014 +0200
+commit f66912d541403dc2b7e2ed0846a553ff76cec3ed
+Author: Vicente Hernando <vhernando at systemonenoc.com>
+Date:   Thu May 16 12:11:36 2013 +0200
 
-    dialog: documented the track_cseq_updates module parameter
+    modules:uac updated README after avoiding quotes in display.
 
-commit 94f18a957484f5e9eada7402f64c8626a6863fa6
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Sep 5 15:11:57 2014 +0200
+commit 251c0218e7d5e09f43a2b834a5450c20bb4f6d60
+Author: Vicente Hernando <vhernando at systemonenoc.com>
+Date:   Thu May 16 12:06:55 2013 +0200
 
-    dialog: add option to increment cseq upon local authentication to next hop
+    modules/uac: avoid adding double quotes in uac_replace_* functions
     
-    - feature has to be enabled via module parameter track_cseq_updates
-    - it does it only for downstream direction (requests from caller and
-      callee, as it is the typical use case of calling via a provider, after
-      authenticating the caller locally, provider asks for another 'trunk'
-      authentication)
-    - diff of cseq value is stored in dialog var named 'cseq_diff',
-      therefore be sure it is not overwritten from config
+    - updated uac doc with a note and examples.
 
-commit eeec4d9905f1ff76fedc46741acf0109d2f556ca
+commit fe7e4a5152674aa9c81c09dd2fc9938d9e9e762e
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Sep 5 15:06:54 2014 +0200
+Date:   Wed May 15 22:45:18 2013 +0200
 
-    corex: functions for management of msg internal flags
-    
-    - msg_iflag_set("flagname")
-    - msg_iflag_reset("flagname")
-    - msg_iflag_is_set("flagname")
+    pv: clone result of several string transformations
     
-    - flagname can be: USE_UAC_FROM, USE_UAC_TO or UAC_AUTH
-    - this functions should not be used in configuration file for (re)setting
-      the flags, those are done by various functions internally, however, in
-      very particular cases they might be useful (e.g., changing From/To via
-      textops functions)
+    - it is safer for assigning back to the same variable on which the
+      transformation was applied
+    - reported by Martin Mikkelsen
 
-commit 0b08a0bb0051bab16ce8c89ff37dbc874ae37cd7
+commit 9330607f1d1132d4e7719d6a92fd26f4ff06665a
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Sep 5 15:06:00 2014 +0200
+Date:   Wed May 15 19:02:58 2013 +0200
 
-    uac: mark request with FL_UAC_AUTH upon using uac_auth()
+    misc_radius: documented common_response parameter
 
-commit b2dcdf63af755200a58baa2c3182806e0f6142e2
+commit 0eb9ef443db58109f5ed2f3ae7851ad368082bb8
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Sep 5 15:04:41 2014 +0200
+Date:   Wed May 15 18:58:01 2013 +0200
 
-    core/parser: new internal msg flag - FL_UAC_AUTH
+    misc_radius: new parameter common_response
     
-    - to mark requests that had local uac authentication done (e.g., via
-      uac_auth() from uac module)
-    - it is an indication that cseq should be increased
+    - get the radius response specific attributes in avps
+    - patch by Victor V. Kustov
 
-commit ad4bbd282b22a8fb55544b57f0eb8b8e799b5e3d
+commit 6038bae188863f541994976d299c38f50b0a699b
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Sep 4 15:56:35 2014 +0200
+Date:   Tue May 14 19:52:45 2013 +0200
 
-    rr: documentation for remove_record_route()
+    utils/misc: updated vim syntax file
 
-commit a207fb24036df343f4cce812ff7305ccb73a41b6
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Sep 4 15:51:21 2014 +0200
+commit ce1d16ce1c8009918c294307de53f35378868b52
+Author: Juha Heinanen <jh at tutpro.com>
+Date:   Tue May 14 11:05:00 2013 +0300
 
-    rr: remove_record_route() - config function to remove record-route lumps
-    
-    - re-added from ser rr module
+    modules/usrloc: reduce work if contact attributes are not in use
 
-commit e990a74e447cd9e516c4df5cb2aa5c35c46f419a
-Author: Alex Hermann <alex at speakup.nl>
-Date:   Mon Sep 1 17:54:38 2014 +0200
+commit 6c3853981a7574cd162117ef0d98dba205193d1b
+Author: Juha Heinanen <jh at tutpro.com>
+Date:   Mon May 13 15:26:57 2013 +0300
 
-    dmq: Add an RPC interface to query the nodes in the cluster
+    modules/usrloc and registrar: added possibility to unregister without aor
+    
+    - added possibility to unregister without aor if usrloc uses db_mode=3
+    - added new usrloc api function delete_urecord_by_ruid()
 
-commit bc2fd3ec9077a0177914efc6f6bac697c1706d10
-Author: Alex Hermann <alex at speakup.nl>
-Date:   Mon Sep 1 15:28:23 2014 +0200
+commit 65881c31b9a8aa1d4646891e8ea20d22646ce850
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Mon May 13 11:01:28 2013 +0200
 
-    jsonrpc-s: Link to srutils for access to srjson
+    Makefile.defs: devel version set to 4.1.0-dev4
 
-commit 1a553312279dc9452c1b091c0372caa39e36adb7
-Author: Alex Hermann <alex at speakup.nl>
-Date:   Mon Sep 1 17:50:54 2014 +0200
+commit 8e644b8e1ccd9c4d6383a2863f9bf247f789a987
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Mon May 13 11:00:08 2013 +0200
 
-    jsonrpc-s: Don't make up a random reply when the reply is empty
-    
-    In case the function was registered with RET_ARRAY, return an empty array,
-    as that is a valid response.
+    tm: fixed warning related to failure branch routing block execution
     
-    Else, there is no sane response, send an empty object for now. This should
-    maybe become an error repsonse instead.
+    - routing blocks id are >=1, the condition was always true because the
+      field in tm struct is unsigned int
+    - gcc warning was: comparison is always true due to limited range of data
+      type
 
-commit 549f96e5608a137299a9bf962b65a85890ad37b3
-Author: Alex Hermann <alex at speakup.nl>
-Date:   Tue Aug 26 18:52:38 2014 +0200
+commit 80e8058d9acea7c994819d043456fd1b449b048b
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Mon May 13 10:59:20 2013 +0200
 
-    dmq: Parse Content-Length header if it isn't parsed yet
+    core: debug message to show mapping of routing block names to ids
 
-commit 4abbae4bc58395692f3fcd7026a40348d1f30fda
-Author: Alex Hermann <alex at speakup.nl>
-Date:   Fri Aug 22 15:55:05 2014 +0200
+commit 32951506dff11df32c03230c1548553838140574
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Mon May 13 10:35:35 2013 +0200
 
-    dmq: More efficient peer storage
+    msrp: cache in a local variable if tls module is loaded
     
-    Allocate only 1 hunk of memory for the entire peer's storage needs.
+    - avoid looping at runtime through the list of modules
 
-commit 78a87972b8b2961c306f8cbd16af1e7d7885ff31
-Author: Alex Hermann <alex at speakup.nl>
-Date:   Fri Aug 22 15:51:49 2014 +0200
+commit 0ca1a789e52e5d559983c3cfb4d851ae375c7758
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Sun May 12 14:18:13 2013 +0100
 
-    dmq: Broadcast nodelists to all hosts
-    
-    Update all hosts with updated state on shutdown.
+    modules/outbound: reduced the level of some outbound related diagnostics
 
-commit 9c3524a68d729fdd235e514bbc74d5f058c111da
-Author: Alex Hermann <alex at speakup.nl>
-Date:   Fri Aug 22 15:48:28 2014 +0200
+commit b0b3887b099fd16906d9e42fcc05d2f899574426
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Sun May 12 14:17:55 2013 +0100
 
-    dmq: Handle Max-Forwards correctly when maxfwd module is used.
-    
-    The maxfwd module will change the current msg buffer with a decreased
-    Max-Forwards header. Detect this sitation via the 'parsed' field and handle
-    it.
+    modules/rr: reduced the level of some outbound related diagnostics
 
-commit 42e653b5e5fbd9781037c131778674e27e125a72
-Author: Alex Hermann <alex at speakup.nl>
-Date:   Fri Aug 22 15:46:08 2014 +0200
+commit 4fafe7bd6d781748722de4fb565808063c8f6c4d
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Sun May 12 14:10:24 2013 +0100
 
-    dmq: Use the received status updates from peer hosts to update in-memory status
+    modules/rr: reduced the level of an outbound related diagnostic message
 
-commit 4d75916422ccdf815aa542718d9bfa87c0133067
-Author: Alex Hermann <alex at speakup.nl>
-Date:   Fri Aug 22 15:42:51 2014 +0200
+commit ee2847c5f508fc8757221e5772c03b62d07f172a
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Sun May 12 14:09:58 2013 +0100
 
-    dmq: Set node status to value in uri
-    
-    The status was forced to ACTIVE regardless of the status in the uri.
+    modules/path: reduced the level of an outbound related diagnostic message
 
-commit 3e34dbf68bcb33fc57973f7a1d735820f11c796b
-Author: Alex Hermann <alex at speakup.nl>
-Date:   Mon Aug 11 19:06:42 2014 +0200
+commit 116ba23c60be15f5fdc1e0cf0f9a9a7affdd32b3
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Sun May 12 14:09:28 2013 +0100
 
-    dmq: Various sanity checks and initializations
+    modules/websocket: Added check to stop Kamailio starting if WebSocket is loaded without xhttp
 
-commit fd3eb9ffa647d3e3cf234f2ee240bcf1d5df9fac
-Author: Alex Hermann <alex at speakup.nl>
-Date:   Thu Aug 7 17:20:20 2014 +0200
+commit afdae93c5eba15496498be292c0c99608d801757
+Author: Juha Heinanen <jh at tutpro.com>
+Date:   Sun May 12 16:10:40 2013 +0300
 
-    dmq: fix copy-paste error resulting in the peer's description not being copied
+    modules/presence: downgraded unsupported event syslog message
+    
+    - Downgraded unsupported event syslog message from error to notice.
 
-commit 3e53527030ab360e010cfdda756efff516c54f11
-Author: Alex Hermann <alex at speakup.nl>
-Date:   Thu Jul 17 13:02:12 2014 +0200
+commit 116daef9b55d82a016d1fd3e3d877a2468c55d1a
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Sun May 12 13:57:44 2013 +0100
 
-    dmq: Set send_socket to the correct address
-    
-    Documentation says the server_address is the address used to send messages
-    from. Make the code actually do this.
-    
-    UDP is hardcoded for now because DMQ doesn't work with other protocols (yet).
+    modules/msrp: Use "msrps://" URIs for the server when TLS is loaded. TLS is mandatory for MSRP relays.
 
-commit 02932c9af755f155a35ec5243cd33530e74929ae
-Author: Alex Hermann <alex at speakup.nl>
-Date:   Tue Sep 2 16:38:15 2014 +0200
+commit 30c8ead0b18678950b7596d4247d51cb56614d42
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Sun May 12 13:57:00 2013 +0100
 
-    dmq: Fix indenting
+    modules/msrp: added warning when MSRP is loaded in a configuration without TLS.  TLS is mandatory for MSRP relays.
 
-commit 2d77ac31fb1bf488ef986978edbc2b05982a38ba
-Author: Alex Hermann <alex at speakup.nl>
-Date:   Tue Jul 15 10:26:42 2014 +0200
+commit b220a571d010851ee72c6bf6263a958335283b62
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Sun May 12 13:55:46 2013 +0100
 
-    dialog: Allow '_' in dlg profile names
+    modules/websocket: added warning when websocket module is loaded in a configuration without either the nathelper or outbound modules
 
-commit 684afd9cdefaa46fea3993a1a01316521c8631cd
-Author: Alex Hermann <alex at speakup.nl>
-Date:   Fri Aug 22 11:44:56 2014 +0200
+commit 2bb07b9d2df567e24f86b291bee7748db104252b
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Sun May 12 13:54:59 2013 +0100
 
-    dialog: Send properly structured responses on RPC requests
-    
-    Instead of dumping random blobs in structured protocols (json, xmlrpc),
-    return properly structured data.
-    
-    Each dialog is a struct with named fields, a list of dialogs is an array
-    of structs. Variables and profiles are arrays in the dialog struct.
-    
-    Dialog contexts still todo.
+    modules/outbound: added warning message when outbound module is loaded in a configuraiton that does not load the stun module
 
-commit 3d5f8af6efb5a33e46427a1a9b273e445a3064c7
-Author: Alex Hermann <alex at speakup.nl>
-Date:   Fri Aug 22 13:55:42 2014 +0200
+commit 9af456f292e25be2c5689212ed097177a5a16338
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Fri May 10 20:04:02 2013 +0100
 
-    dialog: Correctly restore dialog lifetime from DB
+    modules/websocket: Added ws_close() exported function
     
-    Restore the lifetime to the configured value instead of the offset from the
-    time the reload from the DB took place.
+    - Enables immediate closure of a WebSocket connection from the configuration
+      file.
 
-commit 811bb515c09e7270d1d7f8a28d280e184874e487
-Author: Alex Hermann <alex at speakup.nl>
-Date:   Mon Jul 7 16:38:29 2014 +0200
+commit 399dd84d28da82d751e40488cda604a4e03fcbf3
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Fri May 10 20:02:51 2013 +0100
 
-    dialog: Set the dialog context on transaction failure
+    modules/pv: added new $conid PV
     
-    Before, the dialog context would be derived from the callid and tags. This
-    could select the wrong dialog in case of spirals. This patch sets the correct
-    dialog context by storing the it in the transaction and restoring it on a
-    failure. Now the correct dialog variables are available in failure_route.
+    - Returns the TCP connection ID that the current message arrived on (for
+      TCP/TLS/WS/WSS) or $null (for UDP/SCTP)
 
-commit 25a3297915fbcc0a267d444d245526de978a5d62
-Author: Alex Hermann <alex at speakup.nl>
-Date:   Mon Jul 7 16:38:29 2014 +0200
+commit 81d3eebd51089686949ab22da60166d4f3a460a7
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Tue May 7 19:15:36 2013 +0200
 
-    dialog: Set the dialog context on incoming replies
+    core: get rid of deferencing type-punned warning in deb wheezy
     
-    Before, the dialog context would be derived from the callid and tags. This
-    could select the wrong dialog in case of spirals. This patch sets the correct
-    dialog context by storing the it in the transaction and restoring it on an
-    incoming response. Now the correct dialog variables are available in
-    onreply_route.
+    - reported by Victor Seva
 
-commit 33f054a793dc843959de356f0dc201e66d306583
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Wed Sep 3 22:32:03 2014 +0200
+commit acf033559f728e9967eb32f5340b0508a232172b
+Author: Carsten Bock <carsten at ng-voice.com>
+Date:   Tue May 7 22:31:34 2013 +0800
 
-    modules/ims_auth: ims_www_challenge allows specification of auth algorithm from cfg
-    	- e.g. ims_www_challenge("REG_MAR_REPLY", "$td", "MD5");
-    	- useful for non-ims clients that do not do AKA
+    Remove "ignore_failed_auth" Parameter from example config - otherwise you may register without correct password.
+    (the parameter was added for loadtesting only)
 
-commit 961542fa1ce9d077d0737e4971a827409b74a122
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Wed Sep 3 19:57:22 2014 +0200
+commit 994155161263dab7a7f7c01105ea474702cf7fee
+Author: Richard Fuchs <rfuchs at sipwise.com>
+Date:   Mon May 6 11:03:07 2013 -0400
 
-    modules/pv: added pseudo-variable ($aa) for access to algorithm in autorization header
+    path: support SPVE in add_path*() and add second parameter
+    
+    This includes a major rewrite and code cleanup of prepend_path(), which
+    doesn't perform any other functional changes.
 
-commit f4cfbe9a7ca5fbf1cb44c544abcc27aa65198ae1
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Wed Sep 3 13:26:14 2014 -0400
+commit fa9b8664a3b7c7a035c738a37b8ef0ef44190cb8
+Author: Juha Heinanen <jh at tutpro.com>
+Date:   Fri May 3 19:53:12 2013 +0300
 
-    db_text: fix clang compiler warning
+    modules/rls: added support for escaped chars in rls-services document
 
-commit f4c7ac4c0ef5eed2352dc4f0a8070cfbec502efa
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Wed Sep 3 13:21:13 2014 -0400
+commit 86d706bd4a1e31160883a4f094f3e04f9380de04
+Author: Carsten Bock <carsten at ng-voice.com>
+Date:   Fri May 3 18:45:07 2013 +0200
 
-    db_text: fix clang compiler warning
+    Make XML-RCP configurable in example scripts
+    - Improvement: Automatically enable TCP, if XML-RPC is requested
+    - Improvement: Allow the configuration of TCP-Children (especially for XML-RPC)
+    - Improvement: Add missing configuration information
 
-commit abe9d1642a70cfd7d5440db692a484b991253862
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Wed Sep 3 13:17:32 2014 -0400
+commit 141808e9c0789e56f29297e2d2c185e091ebb66a
+Author: Henning Westerholt <hw at kamailio.org>
+Date:   Thu May 2 23:41:28 2013 +0200
 
-    db_flatstore: fix clang compiler warning
+    memcached: port to more recent memory manager callback structure
+    
+    * port to more recent memory manager callback structure
+    * add small wrapper for calloc, implemented not optimal at the moment
+      because the pkg_calloc from core/mem is not exported yet
+    * add initial code to check for server connection during startup, not
+      enabled yet as its work in progress
+    * reorder structure a bit to allow for clean shutdown because of internal mm
 
-commit 89f9f0c10c10c09218576129e3fdc3da55355c48
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Wed Sep 3 13:15:35 2014 -0400
+commit 0332acbc4cf2339f3b6b068f460d00e92221a8ef
+Author: Henning Westerholt <hw at kamailio.org>
+Date:   Thu May 2 21:36:17 2013 +0200
 
-    lib/srdb1: fix clang compiler warning
+    memcache: fix "maybe used uninitialized" warning from gcc
 
-commit 241d6387989be258880131e578598591869a3645
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Sep 3 09:46:41 2014 +0200
+commit 003d87edc23f62de98a1a22db03b12ea58abcbc6
+Author: Henning Westerholt <hw at kamailio.org>
+Date:   Thu May 2 21:17:57 2013 +0200
 
-    xmlrpc: initial support for 'u' specifier
-    
-    - auto-convert to unsigned int
+    mangler: fix double definition of contact_flds_separator, reported from ld
 
-commit 938373a28545a51f335e9489541b106c8261b81d
+commit d6dba0e1b649bcfacaac2dd3496b497e944ebaba
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Sep 3 09:45:42 2014 +0200
+Date:   Thu May 2 13:43:58 2013 +0200
 
-    jsonrpc-s: initial support for 'u' specifier
-    
-    - auto-convert to unsigned int
+    Makefile: fixed path to kamailio.default in deb specs dir
 
-commit f925ea38f98c3c6f0908064586338a3fb971def6
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Sep 3 09:28:53 2014 +0200
+commit 50e9baf2131befa2243a221566b6505a55216208
+Author: Juha Heinanen <jh at tutpro.com>
+Date:   Wed May 1 18:04:47 2013 +0300
 
-    doc/rpc: updated content to reflect renaming of printf() to rpl_printf()
+    modules/registrar: added regid_mode module param
+    - Tells if REGISTER contact regid (if present) is used when REGISTER request
+      is saved even if request does not indicate support for outbound.
 
-commit edfc839ed2c0778f0ce370e5b1caf10f865cf524
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Wed Sep 3 12:05:21 2014 +0200
+commit cc00df26d2e3298751541cc0d4ad35bf0ac361f4
+Author: Juha Heinanen <jh at tutpro.com>
+Date:   Wed May 1 12:34:25 2013 +0300
 
-    modules/ims_registrar_pcscf: fixed transport lookup code
+    modules/htable: added htable.reload rpc command
 
-commit 331b0cf3e9a739f44fc23a3c7d07da725145aa76
-Merge: 9f3cad7 09cff24
-Author: Hugh Waite <hugh.waite at acision.com>
-Date:   Wed Sep 3 11:49:49 2014 +0100
+commit 0ff087e9715298abf3187c52a9d1ac70031f1499
+Author: Juha Heinanen <jh at tutpro.com>
+Date:   Wed May 1 11:54:20 2013 +0300
 
-    Merge branch 'master' of ssh://git.sip-router.org/kamailio
+    modules/mtree: added mtree.reload rcp command
 
-commit 9f3cad7fbd74bf45c242bc6f587dce96c796fcc1
-Author: Hugh Waite <hugh.waite at acision.com>
-Date:   Wed Sep 3 11:42:58 2014 +0100
+commit c57575c5b289c3468eb5c651c1e56699f554298a
+Author: Juha Heinanen <jh at tutpro.com>
+Date:   Wed May 1 09:43:51 2013 +0300
 
-    htable: Fix declarations of variable ht_expired_cell
-    
-    - Removed unused extern delaration in htable.c
-    - Reported by Ovidiu Sas
+    modules/usrloc: added missing rpc commands
+    - added missing rpc commands ul.rm, ul.rm_contact, ul.flush, and ul.add
+      by patch provided by Víctor Seva
 
-commit 09cff24f443123b78ae7443c324ee9038aa96069
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Sep 3 05:27:15 2014 +0200
+commit 878b343f374a62d7ea5ebe5e85b00c391956b623
+Author: Torrey Searle <tsearle at gmail.com>
+Date:   Tue Apr 30 12:01:00 2013 +0200
 
-    jsonrpc-s: auto-convert int to str if required by scanning spec
-    
-    - check if there spec string has still mandatory chars
+    data_lump return a comment back to it's owner
 
-commit 4b7cd3fd867eca3d82cf4668d2ad37c0bc4f7780
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Tue Sep 2 14:30:52 2014 -0400
+commit 8f74c57605fdd1d31c7808a3b8afc79cc981b370
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Mon Apr 29 20:54:52 2013 +0100
 
-    xhttp_pi: proper handling for unknown db column types
+    modules/websocket: fixed mandatory headers check
 
-commit 1378ccf131885f027d1e1cd4bbaac1347a29e317
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Tue Sep 2 14:29:44 2014 -0400
+commit a2e7f65ee8b86d37a6772619ae10087a05219192
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Mon Apr 29 20:38:06 2013 +0100
 
-    lib/srdb1: new col type DB1_UNKNOWN
+    modules/websocket: doubled the size of the buffer for adding headers to WebSocket handshake responses
 
-commit 613d188f92401c60549ea0337ea0dcf3c68067d7
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Tue Sep 2 14:25:42 2014 -0400
+commit 3d5c66997e77ae4f4c181e5a77c943156a7db00a
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Mon Apr 29 20:34:36 2013 +0100
 
-    xhttp_pi: proper sizeof for memset
+    websocket: added "cors_mode" parameter to enable "Cross-origin resource sharing" on WebSocket handshakes
+    - I don't know of any WebSocket clients that require this (yet).  But having it
+      in there won't break anything.
 
-commit 61af5c6b3523fe866f1d884ba4e9e077cce1588a
-Author: James Wyatt <james.wyatt at acision.com>
-Date:   Tue Sep 2 12:52:47 2014 +0100
+commit 14d4ea782a9a24da9755963ea12807f255cebce5
+Author: Richard Fuchs <rfuchs at sipwise.com>
+Date:   Mon Apr 29 11:26:18 2013 -0400
 
-    htable: Add event route when htable entries expire
-    
-    - event_route[htable:expired:<table>] called when an entry expires
-    - pseudo-vars $shtrecord(key) and $shtrecord(value) access the expired content
+    db_mysql: add cast to remove compile warning
 
-commit e1b63b0e926b926b062569496827f5e506c67c0e
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Tue Sep 2 11:20:29 2014 +0200
+commit 218a83c50a217c420502d484738b6b3401c89b8c
+Merge: edebc03 aefea54
+Author: Juha Heinanen <jh at tutpro.com>
+Date:   Sat Apr 27 18:10:28 2013 +0300
 
-    pkg/kamailio/deb: update to 4.2.0~dev9
+    Merge branch 'master' of ssh://git.sip-router.org/sip-router
+    - Forgot to pull before push.
 
-commit 5fd8a1bdaae82decdb606901fe7bf3e6e9149803
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Sep 2 10:29:22 2014 +0200
+commit edebc03f65445f968accb58b5a761817aaee55e8
+Author: Juha Heinanen <jh at tutpro.com>
+Date:   Sat Apr 27 18:07:21 2013 +0300
 
-    msilo: proper walk through sent list for cleanup
-    
-    - reported by Bhupendra Singh
+    modules/usrloc: fixed typo in db_ops_ruid param name
 
-commit 6fe4e56937563a413cfd83794e0fe71a20caf3d5
+commit aefea5477dc7878d5e818628e04ddcb088fd2858
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Sep 2 09:50:57 2014 +0200
+Date:   Fri Apr 26 19:55:43 2013 +0200
 
-    Makefile.defs: don't set gcc flag -maltivec if not advertised for powerpc
+    tm: wrap around expression adjusting length for To/From headers
     
-    - reported at FS#444,
-      https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=729635
-    - following a patch by Roland Stigge <stigge at antcom.de> on debian bug
-      tracker
+    - applies for local requests
 
-commit b77613398fe7a69d4ac52add3630c94373cbe3e8
+commit ff890a4eee1888ed3e1e080a18bd72124ab99690
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Sep 1 23:45:13 2014 +0200
+Date:   Fri Apr 26 19:00:36 2013 +0200
 
-    core: return OK as string for a successful dns.delete rpc command
+    tm: fixed name of the target uri used for From header
     
-    - closes FS#260
+    - effect of previous commit
 
-commit dbd8ea9b1fa216e59d4c36e2eb4b671202824259
+commit f22dcd559c739dd99275cd2444cf481d458d2fab
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Sep 1 23:36:25 2014 +0200
+Date:   Fri Apr 26 18:32:55 2013 +0200
 
-    tm: rebuild the local request if uri was changed in event route
+    dispatcher: proper localization of To uri for keepalives
     
-    - rebuild was done only on changes over headers and body, with an
-      eventual new r-uri being used in that case
-    - no should work also when only r-uri is changed
-    - closes FS#158
+    - it was affected by introduction of <> around the URI in To header
+    - reported by Peter Dunkley
 
-commit 3e6e4cc03f629b01f779d1556a10b1b2944777bb
-Author: Alex Villacis Lasso <a_villacis at palosanto.com>
-Date:   Mon Sep 1 23:17:04 2014 +0200
-
-    db_unixodbc: allow more than 1024 bytes in a database field
-    
-    - closes FS#443
-
-commit e404d123610b63ddd1c75d39667b373c40071eab
-Author: Kristian Frederik Høgh <kfh at uni-tel.dk>
-Date:   Mon Sep 1 22:03:20 2014 +0200
-
-    tm: rebuild local Via when force socket is changed in event_route[tm:local-request]
-    
-    - new forced socket is also set for sending out
-
-commit 822504084742d44c7ec25569f61a830f5d309aa1
-Merge: ef7630d c158c6e
+commit 57ed79b9d45c29d37c405c3fa582c1d1011a2315
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Sep 1 19:37:10 2014 +0200
+Date:   Fri Apr 26 18:24:01 2013 +0200
 
-    Makefile.def: corrected commit message regarding the devel version
+    tm: adjust size of the hooks to From/To headers for local genrated requests
+    
+    - take in cosideration <> if it is the case
 
-commit ef7630da94895efa5aa40f17e886945c54356718
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Sep 1 19:31:16 2014 +0200
+commit 2e1ade7c66217280455136fb85aeb3a8e8e6917d
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Fri Apr 26 15:29:47 2013 +0100
 
-    Makefile.defs: version set to 4.2.0-dev9
+    modules/siptrace: Support for ws: and wss: (fake protocols as per tls:)
 
-commit c158c6e068297246f4e0270fa04843daaa466bd4
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Sep 1 19:31:16 2014 +0200
+commit 5b96c7e6ec3cfd8354a6a257a87144196d57fec3
+Author: Marius Zbihlei <mariuszbi at gmail.com>
+Date:   Fri Apr 26 09:56:26 2013 +0100
 
-    Makefile.defs: version set to 5.2.0-dev9
+    core: fixed compilation on Solaris, due to missing gethostbyname2
+    
+    TODO: provide a wrapper over dnssec for getipnode...() for Solaris
 
-commit 322bfb147e1ef355db391adb9423ab32cf86188c
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Sep 1 19:27:50 2014 +0200
+commit 5e96920289cbf448ac684d8cb1333d75f65a729a
+Author: Ovidiu Sas <osas at voipembedded.com>
+Date:   Thu Apr 25 14:50:41 2013 -0400
 
-    xmlrpc: rpc commands updated to use rpl_printf()
+    snmpstats: fix cross-compilation
 
-commit dc48839f2c5362361a8681d6d0d9c27433401be8
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Sep 1 19:27:38 2014 +0200
+commit ad11cdca0941cd114e17bb80337a7557818220d5
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Thu Apr 25 18:16:28 2013 +0100
 
-    xhttp_rpc: rpc commands updated to use rpl_printf()
+    modules/msrp: Use "msrps://" instead of "msrp://" in headers when the transport is WSS
 
-commit 159c276036e8f99f7bbf37bdf99350888447699f
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Sep 1 19:27:25 2014 +0200
+commit 4c7195915b38ba343484833532b82b42879d7138
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Thu Apr 25 16:13:48 2013 +0100
 
-    xhttp_pi: rpc commands updated to use rpl_printf()
+    modules/websocket: fixed segmentation fault relating to recent counter changes
 
-commit 13dd700bc808114ddf8a6d06ab0bdd559dc556f3
+commit 4e4b1339bfd3a832f5feeb1d2a2380c7455ec82b
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Sep 1 19:27:12 2014 +0200
+Date:   Thu Apr 25 14:50:40 2013 +0200
 
-    siptrace: rpc commands updated to use rpl_printf()
+    tm: add angle brackets around From/To URI for local generated requests
+    
+    - safer for special cases of URI format
 
-commit f72b66eff5ad5f894c19112e5d89fc7cee4b910a
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Sep 1 19:27:01 2014 +0200
+commit 744a8d317b894a1360e3441a9e69ac9190a1745b
+Author: Juha Heinanen <jh at tutpro.com>
+Date:   Thu Apr 25 14:12:21 2013 +0300
 
-    sipcapture: rpc commands updated to use rpl_printf()
+    modules/outbound: added force_no_outbound flag
 
-commit fb987a685575ae8b2374e717e930a9c767ba5646
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Sep 1 19:26:44 2014 +0200
+commit 81f622b9ef7d32434659f1e6d9a21c8013cefec7
+Author: Klaus Darilion <klaus.mailinglists at pernau.at>
+Date:   Thu Apr 25 08:12:07 2013 +0000
 
-    sca: rpc commands updated to use rpl_printf()
+    sipcapture/siptrace: set default db_url to read-write URL
 
-commit 14738552280f7cd98c5827fc5175b9ab631ff05f
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Sep 1 19:26:33 2014 +0200
+commit c923dec79e20b77f0b42f0ef286eb396bb06f29c
+Author: Victor Seva <linuxmaniac at torreviejawireless.org>
+Date:   Mon Apr 22 17:09:19 2013 +0200
 
-    ratelimit: rpc commands updated to use rpl_printf()
+    app_lua: Added sr.xavp.get function in order to get a table with all the values of a xavp.
 
-commit 5d2bf455980e1a9402ce97ad3d0ba5688f6851fa
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Sep 1 19:26:17 2014 +0200
+commit 0c866d07dd2124b92329106c1cea19bef6ccca9a
+Author: Victor Seva <linuxmaniac at torreviejawireless.org>
+Date:   Mon Apr 22 10:48:08 2013 +0200
 
-    qos: rpc commands updated to use rpl_printf()
+    app_lua: Added sr.xavp.get_keys function.
 
-commit 3fd39e264d38a1a7d557d1d704dca15a8dcf3044
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Sep 1 19:25:56 2014 +0200
+commit 288e2739da28251e12086b52358c3a0d18e91fa5
+Author: Victor Seva <linuxmaniac at torreviejawireless.org>
+Date:   Mon Apr 22 10:46:17 2013 +0200
 
-    pv: rpc commands updated to use rpl_printf()
+    core[xavp]: Added helper function to get a list of keys from a xavp variable.
 
-commit 62822a20d476f279dbb1bb020ebd8ddd859d9e3f
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Sep 1 19:25:47 2014 +0200
+commit ac99219b0a850e0305eaf661b028536cfc28e2cb
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Wed Apr 24 22:01:59 2013 +0100
 
-    presence: rpc commands updated to use rpl_printf()
+    modules/presence_xml: fixed issue with parsing some pres-rules documents
+    
+    - pres-rules that contain external links in a <conditions /> node don't
+      have to have <identity /> nodes in the <conditions /> node.
+    - Kamailio returns an error when it finds a <conditions /> node with
+      no <identity /> node inside it.
+    - Kamailio doesn't support external links, but it should skip over
+      the <conditions /> nodes that contain them rather than return
+      an error as later <conditions /> nodes may contain entries it can
+      work with.
 
-commit 9b190498b98e4849519eedbfb38c2145dca87624
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Sep 1 19:25:35 2014 +0200
+commit 96a1af2f261085db695d8a3b23c1a16f39b393fa
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Wed Apr 24 21:07:07 2013 +0100
 
-    prefix_route: rpc commands updated to use rpl_printf()
+    examples: added WebSocket edge proxy example using outbound for NAT traversal
 
-commit 1926e1412b50c5b843ce1c36119bf60b128b0502
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Sep 1 19:25:08 2014 +0200
+commit 4f68c5626530a1bfe2c7ce72eb3de24b3e7e73dc
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Wed Apr 24 21:06:36 2013 +0100
 
-    permissions: rpc commands updated to use rpl_printf()
+    examples: added outbound edge proxy and registrar example configurations
 
-commit 6944d4f67de63834291365d7d55ad4607a33d82e
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Sep 1 19:24:55 2014 +0200
+commit a0c85d1187dd75a8ab6db9604baee93a5d4f478f
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Wed Apr 24 21:04:56 2013 +0100
 
-    pipelimit: rpc commands updated to use rpl_printf()
+    examples: updated basic websocket example
 
-commit 95a5b8184ea87af660c546025a23b67441e3ebc6
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Sep 1 19:24:43 2014 +0200
+commit cf908dc57b4f62e8daf28c7a0199284bd0b4dc69
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Wed Apr 24 21:04:24 2013 +0100
 
-    mi_rpc: rpc commands updated to use rpl_printf()
+    modules/outbound: Updated examples (edge proxy and registrar) in documentation
 
-commit 7c7755a39ab91c199c9452bbf43585011c5db120
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Sep 1 19:24:30 2014 +0200
+commit e8cf4ef94d8759641ce682b50bad303baa58a2e8
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Wed Apr 24 16:34:29 2013 +0100
 
-    kex: rpc commands updated to use rpl_printf()
+    modules/rr: Fixes relating to outbound and record-routing
 
-commit 05b40e59adbdc51f6e75e4e9e81635fff2ab1f9d
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Sep 1 19:24:15 2014 +0200
+commit 9b1f607ccd3575a2c3a4aba7f6c36e637f9d7022
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Wed Apr 24 14:28:36 2013 +0100
 
-    jsonrpc-s: rpc commands updated to use rpl_printf()
+    pkg/kamailio/(centos|fedora): Updated rel in .spec file
 
-commit 293fdb64ef2f4aa34c5eb7eaf9927aa5e10e4f85
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Sep 1 19:23:58 2014 +0200
+commit 0b8cbbd8359a3c049b0da7a743de3b996412ab35
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Wed Apr 24 14:26:09 2013 +0100
 
-    drouting: rpc commands updated to use rpl_printf()
+    core: Fixed error where ";transport=wss" parameter was sometimes added to URIs
+    
+    - It should always be ";transport=ws" with WebSocket
 
-commit 9e5cd66772afe6fa508587165aa2d87dbcf511c0
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Sep 1 19:23:38 2014 +0200
+commit 1e84948d120ef2b1206f90458d47486239cfd81b
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Wed Apr 24 14:24:45 2013 +0100
 
-    dialog: rpc commands updated to use rpl_printf()
+    modules/rr: Double-route and outbound support in loose.c
+    
+    - Have removed outbound support from strict routing for now as it was incorrect
+      and I don't have a system to test with.
 
-commit 945c54616bf972fb577e2f2a197145547e75a013
+commit 0125cdf0e75271a8478a3eadacc54ea1c1eb4da0
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Sep 1 19:23:20 2014 +0200
+Date:   Wed Apr 24 17:26:15 2013 +0200
 
-    db_text: rpc commands updated to use rpl_printf()
+    usrloc: update call-id value in db when matching record by ruid
 
-commit f1878cdba8875c51d6135733e008d1da6bd89acc
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Sep 1 19:23:04 2014 +0200
+commit ef0a17f0e4c9426f64168eb24568ba906e554315
+Author: Jon Bonilla <jbonilla at sipwise.com>
+Date:   Wed Apr 24 16:46:55 2013 +0200
 
-    ctl: rpc commands updated to use rpl_printf()
+    pkg/deb: Deprecate lenny
+    
+    Lenny is not a supported version of debian any more.
+    At sip-router squeeze and wheezy are being mantained at the moment.
+    Let's deprecate lenny for future releases.
 
-commit 9218d922c910174ed1b497057010fbe7430226b8
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Sep 1 19:22:50 2014 +0200
+commit d9b7cfcd63b5432bc956f0be3a9b4d5eea026786
+Author: Jon Bonilla <jbonilla at sipwise.com>
+Date:   Wed Apr 24 16:42:59 2013 +0200
 
-    cfg_rpc: rpc commands updated to use rpl_printf()
+    pkg/deb: Change memcache module dependencies
+    
+    libmemcached-dev is the new dependency deprecating libmemcache
 
-commit 3ab6500e11b2e16b509f79956581f0fda5cce0ea
+commit 9106eca16924dd6dc797295ba2d74ee16865acaf
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Sep 1 19:22:29 2014 +0200
+Date:   Wed Apr 24 16:27:13 2013 +0200
 
-    app_lua: rpc commands updated to use rpl_printf()
+    usrloc: regenerated the readme for db_ops_ruid parameter
 
-commit 55cdb375e1db99e572dff2a64ff0d905252f6689
+commit e66842c2fc34d8dc8980efa821f7039685edef87
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Sep 1 19:21:50 2014 +0200
+Date:   Wed Apr 24 15:41:34 2013 +0200
 
-    core: dst_blacklist rpc commands updated to use rpl_printf()
+    usrloc: documented db_ops_ruid parameter
 
-commit a8fa4225f208f3b2e6fb8c9a0635edd3817553a3
+commit 61e08282c905c2ee03a2be618b1e700fc0acbdeb
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Sep 1 19:21:16 2014 +0200
+Date:   Wed Apr 24 15:34:16 2013 +0200
 
-    core: dns_cache rpc commands updated to use rpl_printf()
+    usrloc: option to do db update/delete ops using ruid
+    
+    - new parameter db_obs_ruid - if set to 1, db update/delete operations
+      are done using ruid value
+    - if paramter set to 0 (default) the old style using aor, contact and
+      call-id is done
 
-commit 3548620c199fed6f86251cf86faab33ab97c7f15
+commit 52d339408f499c867548f2531be1cac119b31e3b
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Sep 1 19:16:54 2014 +0200
+Date:   Wed Apr 24 13:38:32 2013 +0200
 
-    core: rpc - replaced api member printf with rpl_printf
+    core: new global parameter - modinit_delay
     
-    - clang is throwing error: no member named '__printf_chk' in 'struct rpc'
-    - reported in FS#457, follwing report on Debian:
-      https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=755852
+    - sepecify microseconds to sleep after initializing a module in order to
+      cope with systems having rate limits on new connections to db or other
+      servers
 
-commit 04da8d891cdf1314e24cf025b64ed1cc70ce7b5e
+commit 735f83d6346c97d6f7b1da26a2fee1b6270872b1
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Sep 1 18:29:20 2014 +0200
+Date:   Wed Apr 24 13:36:08 2013 +0200
 
-    app_lua: search for for lua 5.1 compilation flags
+    registrar: added debug message to print generated ruid for contact
     
-    - lua 5.2 embedded api is not compatible with 5.1
-    - an upgrade to c code in app_lua is required, till then, lua-5.1 has to
-      be installed (can co-exist with lua 5.2)
+    - formatted condition to fit 80 char long line
 
-commit 620ce0e287a846be064f3507e892d73937331ec7
+commit a74980270b655124c276279e54b8f82965f3f4b8
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Sep 1 16:21:17 2014 +0200
+Date:   Wed Apr 24 10:26:49 2013 +0200
 
-    INSTALL: removed question about windows messenger (it doesn't exist anymore)
+    sqlops: use one char buf for empty strings in db results
     
-    - coherent usage of upper case for section titles
-    - added notes about tracker and faq
+    - safe for the parts of code that want to access it even for write
 
-commit 2824e49d4c2d64918a3d8c00f37498caec445b83
-Author: Sven Neuhaus <neuhaus at users.noreply.github.com>
-Date:   Fri Aug 29 13:14:18 2014 +0200
+commit 0e09fba67dc5d75d5e73bb7d35deecf721b37cfc
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Wed Apr 24 11:49:21 2013 +0100
 
-    Fix some typos and capitalisation in INSTALL
+    modules/rr: refactored process_outbound()
+    
+    - Still need to update loose.c to properly handle double-RRs with flow-tokens
 
-commit 37fea3e2fe4958ebc080df7c0808bba835748354
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Aug 29 23:18:27 2014 +0200
+commit c38c0ba0ab3244aa387de706a4555fab28c67ad7
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Wed Apr 24 11:48:21 2013 +0100
 
-    ims_usrloc_pcscf: fixed invalid quotation tokens and removed empty functions section
+    modules/rr: add double record-routes when outbound is enabled
+    
+    - Note: loose.c does not yet handle these properly
 
-commit f096ee13ca09d79d3f0e8fa5c73a6e14987d8317
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Aug 29 23:14:19 2014 +0200
+commit fdb6c8cbafec7849367f16f5dc56ffa20885bef4
+Author: Klaus Darilion <klaus.mailinglists at pernau.at>
+Date:   Wed Apr 24 09:09:25 2013 +0000
 
-    cdp: removed empty functions sections from docs
+    core: fix default read-only DB URL
 
-commit e99b2ff97a0612d0336a5419951d5de1d03f8be2
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Aug 29 23:13:00 2014 +0200
+commit 53319656247a2aa685f4d9b6f667192f945bc62a
+Author: Torrey Searle <tsearle at gmail.com>
+Date:   Tue Apr 23 14:04:39 2013 +0200
 
-    topoh: removed empty functions section from docs
+    modules/sipt add value tables to docs, add section ids to pvars
 
-commit c97c762a00596ebbbb4a3b4a14b3ef9e703600b5
+commit 20646b530baa1a2807e52048a8d99d31d2171bb6
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Aug 29 22:40:53 2014 +0200
+Date:   Tue Apr 23 13:02:49 2013 +0200
 
-    json: remove empty parameters section from docs
+    usrloc: re-init sruid struct for each child
     
-    - breaks indexing, as there is no title for sub-section
+    - avoid overapping values for xmlrpc handling
 
-commit 36b8a21cc8ec1cd89cfdea60a11e83711c0694b5
+commit 6835b9bc1c80035a603016cf8149afefbf535929
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Aug 29 22:40:19 2014 +0200
-
-    utils/misc/vim: syntax highlight rules for // comments
+Date:   Tue Apr 23 11:59:09 2013 +0200
 
-commit 6ea8693fd7abf0fe5c48342e18ae8d2c94830e6b
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Fri Aug 29 15:55:20 2014 +0200
+    uac: regenerated readme with new wiki link
 
-    modules/dialog_ng: added DB support for dialog_ng
-    	- thanks to a lot of work contributed by Carlos Ruiz Diaz
-
-commit 21ab9b3cf1a93019495e8204fbfe56331614bef9
+commit 2b97e81b281802283ebc665da6f9190f0a9705ab
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Aug 29 15:54:31 2014 +0200
+Date:   Tue Apr 23 11:58:17 2013 +0200
 
-    utils/misc/vim: added newer cfg tokens to vim syntax highlighting
+    docbook: uptdated wiki link in entities file
 
-commit 460ac01f75eeb527debf2e4d135fb83b386ccf42
+commit b89c747bc717c0f9053e53c53a74f9744c1b8606
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Aug 29 15:03:12 2014 +0200
+Date:   Tue Apr 23 11:52:13 2013 +0200
 
-    utils/misc/vim: added target in Makefile to remove old ser vim files
+    uac: added possibility to authenticate generated requests
     
-    - make clean-ser
+    - $uac_req(auser) - specify the authentication username
+    - $uac_req(apasswd) - specify the authentication password
+    - if both attributes above are set and the request is challenged with
+      401/407, then the request is resent with auth header
 
-commit e4b6e43605bb530a44cd42f4f4a7cb4ff77332bf
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Aug 29 14:58:39 2014 +0200
+commit b57d14afeed443bd3ff847a455c1f07bdca7dd09
+Author: Torrey Searle <tsearle at gmail.com>
+Date:   Tue Apr 23 10:39:01 2013 +0200
 
-    utils/misc/vim: vim specific files migrated to name kamailio
-    
-    - vim syntax and autodetect files use now kamailio, to be easier
-      correlated with the name of packaged distribution
-    - syntax highlighting is identified now my kamailio (e.g., 'setf kamailio')
+    modules/sipt forgot to stage the documentation (pvars added)
 
-commit 607e0f0bccaa20f6cbdfbba409d0faa4ea220ce6
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Aug 29 14:46:19 2014 +0200
+commit d02ebb2584d2e4f676a9f8c4e0f6095045de86db
+Author: Torrey Searle <tsearle at gmail.com>
+Date:   Tue Apr 23 10:37:09 2013 +0200
 
-    removed old unused modules folders - modules_k and modules_s
+    modules/sipt regenerate README with new api
 
-commit 9f7fec41c065af9608f6547b2ed0d43614c5a284
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Wed Aug 27 14:56:30 2014 +0200
+commit 781b0a68cbf3a9b93bda0ebafb9ae64257c202d3
+Author: Torrey Searle <tsearle at gmail.com>
+Date:   Tue Apr 23 10:30:11 2013 +0200
 
-    modules/ims_registrar_pcscf: new module function lookup_transport
-    	- this allows terminating P-CSCF to check(and possibly) change the transport for the request before relaying/fwding to terminating UE
+    modules/sipt refactor get functions into pvars
+    
+    return value of 0 in a function causes the script to exit, so
+    pvars are used instead to safely get the values
+    
+    also getting screening and presentation information added
 
-commit e7f714f48285ef5ee6ff03759dfbecae5e51b609
+commit ee928f8229dffdcb2d980e6ca192a9a7778e893b
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Aug 26 13:03:33 2014 +0200
+Date:   Mon Apr 22 18:10:38 2013 +0200
 
-    registrar: reset indentation to use tabs
+    core: include <netinet/in.h> in new dns_func.c file to fix compilation of freebsd
     
-    - follow up to previous commit
+    - patch by Victor V. Kustov
 
-commit 76473abd05503e4dffb63cf5ddc1d39c5170238d
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Aug 26 13:01:42 2014 +0200
+commit 717cd63e7f52f9298e6ba6f55f12129ab5e61ccd
+Author: Torrey Searle <tsearle at gmail.com>
+Date:   Mon Apr 22 10:11:17 2013 +0200
 
-    dispatcher: fixed warning on unsigned compared with <0
-    
-    - added in previous commit
-    - reset indentation for dispacher.c file
+    modules/sipt added new method sipt_set_calling
 
-commit ba0cf0014908645e6b17b6e305e2e1ae4235a94f
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Fri Aug 22 05:20:42 2014 -0700
+commit 066011935c7a2636ea976923e46d33ae5fb4c793
+Author: Henning Westerholt <hw at kamailio.org>
+Date:   Sun Apr 21 21:56:28 2013 +0200
 
-    registrar: randomize expires value received from UAC
+    memcached: port module to use the newer libmemcached library
+    * based on a patch from Charles Chance, sipcentric.com
+    * He added new functionality to set the expiry directly in the key
+    * Added memory manager wrapping functions and some more logging,
+    * smaller cleanups in the code structure
+    * This is work in progress, the memory management stuff is not yet
+    * finished, as this needs different logic for client lib version
+    * before and after 0.32. It will not work at the moment correctly.
 
-commit 499fb7b7d58c812dd8c867adbbed27e0c61f26d0
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Mon Aug 25 04:05:48 2014 -0700
+commit dedede1cc7d384be3b4436a474b53d03f91a966a
+Author: Marius Zbihlei <mariuszbi at gmail.com>
+Date:   Sun Apr 21 20:28:21 2013 +0100
 
-    dispatcher: fix ds_mark_dst parameter parsing
+    modules/dnssec added cleanup of context
 
-commit ee9ea2f543975769ca544dcf3b75b97698e3b53e
+commit e206fdf4bfb398f5175726d75bfa5f9b8f5a9b70
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Aug 25 16:56:16 2014 +0200
+Date:   Sun Apr 21 21:17:29 2013 +0200
 
-    core: update content for -D option in man page
+    Makefile.defs: version set to 4.1.0-dev3
 
-commit 2b33768745130b91e984b679f9eed01a6267d8cc
+commit 7ec7231a86bc895b22a8ae5b617764b6171ac6d4
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Aug 25 16:55:27 2014 +0200
+Date:   Sun Apr 21 21:16:49 2013 +0200
 
-    core: main - proper info for -D command line option
+    Makefile: added target to install init.d script on debian
 
-commit 7450805ac0c8dbe620f146ddf14eba7bee69171e
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Mon Aug 25 15:03:11 2014 +0200
+commit be4b94efde40180d642af0e87f15f4c9bdc4ce7b
+Author: Henning Westerholt <hw at kamailio.org>
+Date:   Sun Apr 21 19:51:34 2013 +0200
 
-    modules/ims_registrar_pcscf: Replaced deprecated STR_PARAM with PARAM_STR
+    tests: fix test sipp scenario
 
-commit a00ee5174b573edd243caf4de68113e9460791eb
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Mon Aug 25 12:53:38 2014 +0200
+commit 731f1b2a72a04901b11e34de91bc1c276e47fce1
+Author: Henning Westerholt <hw at kamailio.org>
+Date:   Sun Apr 21 19:25:51 2013 +0200
 
-    modules/ims_registrar_pcscf: new parameter force_icscf_uri
-    	New module parameter force_icscf_uri - if set we use it as the ICSCF next hop
-    	If not set (default) we use DNS SRV to find ICSCF next hop
+    tests: fix module paths
 
-commit a1b6093aaee9e96f00475752273c9c925ba390d3
-Author: Luis Azedo <luis.azedo at factorlusitano.com>
-Date:   Fri Aug 22 16:05:15 2014 +0200
+commit 65d2823cd6236cfebc26f4a1d5b6e5ee2a3d2156
+Author: Henning Westerholt <hw at kamailio.org>
+Date:   Sun Apr 21 18:54:48 2013 +0200
 
-    json: fixed parameter number for free fixup function
+    tests: remove some unnecessary directory changes
 
-commit 0b2462d745ac05587539f6c937aed5580ad92c8c
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Aug 22 15:58:31 2014 +0200
+commit cd46c51dd12e85ba1508ce5752762269686eeded
+Author: Henning Westerholt <hw at kamailio.org>
+Date:   Sun Apr 21 18:49:19 2013 +0200
 
-    dispatcher: regenerated the documentation for update on ds_select_dst()
+    tests: fix some old paths
 
-commit 15d1022b575ae06f92f5a966bc12e144f3def5c5
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Thu Aug 21 08:20:09 2014 -0700
+commit 59117e598386d013d9c9f62282aa434dc5806c03
+Author: Henning Westerholt <hw at kamailio.org>
+Date:   Sun Apr 21 18:30:21 2013 +0200
 
-    dispatcher: option to limit the number of items in dst_avp list
+    tests: use bash compliant return values
 
-commit 4108c7a125a3e50d1d670bc4c842b29cc32ec438
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Aug 22 15:53:47 2014 +0200
+commit b3682521361ce0cdbaf50f843a2d80bcb1b8b41d
+Author: Marius Zbihlei <mariuszbi at gmail.com>
+Date:   Sun Apr 21 15:26:05 2013 +0100
 
-    pua_dialoginfo: proper jump to end of the structure
+    modules/dnssec: added support for libval query parameter flags
     
-    - void has no standard size
-    - descovered on a report by Charles Chance
+    Documentation in the README
 
-commit d5c6185f4369833113e21802baafe18288fb4254
+commit ebeb18ffed8e81ae472b4c07097b58fbea115b5b
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Aug 22 15:52:12 2014 +0200
+Date:   Sun Apr 21 16:07:34 2013 +0200
 
-    dialog: documentation for dlg_remote_profile() config function
+    pv: updated link to wiki site
 
-commit 9c8020d2ab0b522bd63dc521270e80d0f7bd6212
+commit f0c467f64c044de0b0f37addccb97d3ccff78706
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Aug 22 15:37:53 2014 +0200
+Date:   Sun Apr 21 16:06:56 2013 +0200
 
-    dialog: new config function - dlg_remote_profile
-    
-    - dlg_remote_profile(cmd, profile, value, uid, expires)
-    - manage non-local profiles from configuration file
-    - cmd can be add (insert a remote profile) and rm (remove a remote profile)
+    acc: updated link to pseudo-variables cookbook
 
-commit 157a50f7fe6034213741b2a4cd5dc3142cc8dcee
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Aug 22 14:11:37 2014 +0200
+commit a5a7d62271bf1674015d8ab1d928c0325224b77e
+Author: Marius Zbihlei <mariuszbi at gmail.com>
+Date:   Sun Apr 21 13:32:26 2013 +0100
 
-    dialog: added cleanup of expired remote profiles via internal timer
+    modules/dnssec: removed unused variable
 
-commit 8d2e86cabe73195463937f4945f600ceabe3585a
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Aug 22 00:16:01 2014 +0200
+commit 61519687d5cca6e77ba2ba456f845c140a66ccc1
+Author: Marius Zbihlei <mariuszbi at gmail.com>
+Date:   Sun Apr 21 13:30:16 2013 +0100
 
-    dialog: internal refactoring to allow adding remote profile
-    
-    - this is a profile item without a local dialog
-    - allow opperations to add or remove such profiles
+    modules/dnssec: removed bogus param
 
-commit 219ac1743051d05396d13203aee6115ffbc9a7d7
+commit 325aa35f76f7727abe010b03a0dd03b5f487e26a
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Aug 21 18:21:14 2014 +0200
+Date:   Sun Apr 21 13:38:30 2013 +0200
 
-    dialog: add a unique id for each profile item
+    Makefile.groups: proper fixing of all modules list
     
-    - internal sruid is used for generating uids
+    - reported by Vicente Hernando
 
-commit d2e6918acc75178d8669615bff068914bd34abfa
+commit fc80791c65fa46389168bd5e16af6b33c1bbc36c
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Aug 20 12:17:25 2014 +0200
+Date:   Sun Apr 21 13:09:43 2013 +0200
 
-    lib/srutils: add sruid_next_safe() function
+    Makefile.groups: fixed another type of double parenthesis
     
-    - checks to see if the sruid was initialized by same process and if not,
-      triggers a reinit
-    - pid is stored inside the sruid struct
+    - reported by Vicente Hernando
 
-commit 542336ab49a7b8cbca953a69c138a5ec38a96d7a
+commit edd7f8ed5b8b893276c86bb054e6f7523ad69f33
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Aug 19 18:00:49 2014 +0200
+Date:   Fri Apr 19 22:50:26 2013 +0200
 
-    dlg: keep dialog value 0-terminated in memory
-    
-    - more flexibility in searching/matching
+    Makefile.groups: fixed typo
 
-commit 6677714ccfaa395a70fd1ce2cd99cab58e46d2c1
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Aug 19 17:44:55 2014 +0200
+commit ea964748dc638af82d2363317ca2eade98a279ac
+Author: Juha Heinanen <jh at tutpro.com>
+Date:   Fri Apr 19 17:39:05 2013 +0300
 
-    dialog: refactored json serialization for dialog profiles
-    
-    - there is no restriction to add a dialog in same profile many times
-      (could be with/without different value). Current serialization
-      resulted in having many fields with same name in an object structure,
-      which was ok for local json handling, but failed for various external
-      tools
-    - profile structure extended in memory with unique id, expires and
-      flags, to be used for better identification of the profile cell
-    - note: upon kamailio upgrade, old dialog profiles are no longer loaded, as the
-      json structure is now different
+    modules/outbound: downgraded one INFO to DGB
 
-commit cd335addc40f358b6b80bfa5b9df8b468319838a
-Author: lucian balanceanu <lucian.balanceanu at 1and1.ro>
-Date:   Thu Aug 21 10:02:49 2014 +0300
+commit 7a96d912032939b8eb108e0e84b70bbf0642e2ab
+Author: Juha Heinanen <jh at tutpro.com>
+Date:   Fri Apr 19 17:36:27 2013 +0300
 
-    core: call onsend_route for replies
+    modules/outbound: for non-reg requests, check if outbound is supported
     
-    - this feature is aimed at tracing replies with sip_trace; e.g.:
-      onsend_route { sip_trace("sip:10.84.1.49:5060"); } would now trace the
-      requests passing Kamailio, as well as the replies;
-      This patch has been proposed earlier: http://lists.sip-router.org/pipermail/sr-users/2012-May/073250.html
+       4.3.  Sending Non-REGISTER Requests
+       ...
+       UAs that support this specification SHOULD include the outbound
+       option tag in a Supported header field in a request that is not a
+       REGISTER request.
 
-commit e88b500f8fb6077ac17e5413ffe8770d72e5c6ac
-Author: lucian balanceanu <lucian.balanceanu at 1and1.ro>
-Date:   Wed Aug 20 18:08:03 2014 +0300
+commit 752de05cc567c7502b1e723a09e350ce8d447664
+Author: Juha Heinanen <jh at tutpro.com>
+Date:   Fri Apr 19 13:24:52 2013 +0300
 
-    sipcapture: retry insert in DB on initial failure
-    
-    - added insert_retries and insert_retry_timeout parameters, which
-      control how many times and for how long Kamailio should try to
-      rewrite to the Homer database in case the first attempt fails;
-      trying to rewrite proves useful especially in heavy load scenarios.
+    modules/rr: if outbound request is outgoing, do nothing outbound
+      specific in loose_route()
 
-commit 6b2f7d0b9d405d8ffd2310f788254453d6748f0b
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Tue Aug 19 17:21:57 2014 +0200
+commit e3c0a3abb6045e841fbb4b1b61a518b2b87a217d
+Author: Ovidiu Sas <osas at voipembedded.com>
+Date:   Thu Apr 18 16:03:50 2013 -0400
 
-    debugger: fix reset_msgid
-    
-    Don't change the msg->id when that message has been processed already
+    seas: fix warning [-Wunused-result]
+     - ignoring return value of write, declared with attribute warn_unused_result [-Wunused-result]
 
-commit cb04eea7b4e2a382a0315529d38d2f4ec5a60d93
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Aug 19 18:19:46 2014 +0200
+commit c0f4b6cf664ac552d0c994e99adb13991a37ef28
+Author: Ovidiu Sas <osas at voipembedded.com>
+Date:   Thu Apr 18 16:01:16 2013 -0400
 
-    tmx: mark pretran struct as linked when adding to a non-empty slot
-    
-    - otherwise is not going to be unlinked properly, with high potential of
-      ending in an infinite loop
-    - reported by Juha Heinanen
+    seas: fix compiler warning [-Wunused-but-set-variable]
 
-commit 8863703388f1be349675e4b72329eb702ad33ecd
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Aug 19 11:32:00 2014 +0200
-
-    tm: more details about processing doen by t_check_trans()
-    
-    - note that last reply is resent for retransmissions matching a
-      transaction
-
-commit 92ff234d8b39c422aca683d4fbb0cfacc24a77b4
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Aug 19 11:10:14 2014 +0200
+commit 12cd241d95b8d38cea6e60676b752f8ef8a2ed8c
+Author: Ovidiu Sas <osas at voipembedded.com>
+Date:   Thu Apr 18 15:54:14 2013 -0400
 
-    tmx: be sure From header is parsed before accessing the tag
-    
-    - reported by Juha Heinanen
+    seas: fix compiler warning [-Wunused-but-set-variable]
 
-commit bd12eaf0f26cfca55eda063263109d434be31c60
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Mon Aug 18 22:21:13 2014 +0200
+commit 21e51107a5a08b182abc7bffbac1fec1be27950b
+Author: Ovidiu Sas <osas at voipembedded.com>
+Date:   Thu Apr 18 15:51:50 2013 -0400
 
-    modules/ims_qos: ignore reply retransmissions if Rx session being processed
-    	On receipt of Rx_AAR command check if session exists and it is not in state open
-    	If so then assume this is a retransmit and ignore
+    seas: fix compiler warning [-Wunused-but-set-variable]
 
-commit 571b1e66c1bfd557b3be8aa99cdf78be83caf97f
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Aug 18 22:15:42 2014 +0200
+commit 2abf2d4a42c05004319e682d2ad07d69bf2fc89e
+Author: Ovidiu Sas <osas at voipembedded.com>
+Date:   Thu Apr 18 15:50:25 2013 -0400
 
-    tmx: documented precheck_trans parameter
+    seas: fix compiler warning:
+     - warning: variable flags set but not used [-Wunused-but-set-variable]
 
-commit 2ceae3188beb73da7d5975e7abf232226dd12063
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Aug 18 22:07:58 2014 +0200
+commit 21386829d819c06c42871cf5b68d0d3a63ef0222
+Author: Ovidiu Sas <osas at voipembedded.com>
+Date:   Thu Apr 18 15:48:03 2013 -0400
 
-    tmx: precheck_trans - new parameter to enable/disable pre-transaction check
-    
-    - enable/disable usage of t_precheck_trans() - don't init internal
-      structures
+    seas: fix compiler warning:
+     - warning: variable flags set but not used [-Wunused-but-set-variable]
 
-commit 392becb3e592f06f4ff843b303f1ddc765fa1a9f
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Aug 18 22:05:30 2014 +0200
+commit 200eddad28abd6bc51da3285dd52d5f8c88c4e56
+Author: Ovidiu Sas <osas at voipembedded.com>
+Date:   Thu Apr 18 15:45:50 2013 -0400
 
-    tmx: documentation for t_precheck_trans()
+    seas: fix compiler warning
+     - warning: variable flags2 set but not used [-Wunused-but-set-variable]
 
-commit dd30e06fabe554746b1f4565e16b024ee1795fbe
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Aug 18 21:54:13 2014 +0200
+commit 63736be1e4d2d6e82a0f7be6a85a96ee66c10146
+Author: Ovidiu Sas <osas at voipembedded.com>
+Date:   Thu Apr 18 15:42:40 2013 -0400
 
-    kamailio.cfg: use t_precheck_trans() to catch retransmissions faster
+    seas: fix compiler warning:
+     - warning: variable falgs set but not used [-Wunused-but-set-variable]
 
-commit 2fbc66fb8789a9e0749aca301119ab7c046676c5
+commit 8393ccdc1558f56ba819a442d0c50d25f51a934d
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Aug 18 21:52:09 2014 +0200
-
-    tmx: t_precheck_tran() - light filtering of retransmissions
-    
-    - keep track of processed messages per process to catch retransmissions
-      in early phase, to avoid simultaneous processing until transaction is
-      created
-
-commit 72ddccb2aa8a7b40bbd6b0339f884f0ba3181429
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Mon Aug 18 13:03:14 2014 +0200
-
-    modules/ims_qos:
-    	Use same framed-ip-address and subscription-id through Rx session
-    	Save framed-ip-address and subscription-id for initial Rx AAR and re-use for
-    	subsequent AARs in the same Rx session
+Date:   Thu Apr 18 21:28:54 2013 +0200
 
-commit 939f29361571385e4222494caab4a1b6272405c5
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Mon Aug 18 13:02:30 2014 +0200
-
-    modules/ims_charging: added support for video charging
-    	Previously service identifier was hard coded
-    	This change adds configurable parameter for voice service id and rating group and video service id and rating group
-    	If INVITE SDP includes audio only we use voice parameter, if INVITE SDP includes video we use video parameters
+    dnssec: added reference to wikipedia's DNSSEC article
 
-commit 73fb0285f8447cc4eb8d9806c3cf573403f5ab72
+commit 343379957ab783a32c48822de479a9d8c2dafdf3
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Aug 15 22:17:28 2014 +0200
+Date:   Thu Apr 18 21:22:47 2013 +0200
 
-    core: rpc core.psx is returning an array
-    
-    - otherwise it breaks unique member name for structures, because it
-      returs many records
+    xlog: link to wiki updated
 
-commit fcb2eef025b7272d1c5e2ff14e880d169a6bf528
+commit e2f9e909a2abd02cebb292cc8cb3500aa4c07036
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Aug 15 21:52:52 2014 +0200
+Date:   Thu Apr 18 21:22:01 2013 +0200
 
-    jsonrpc-s: handle struct_add() to an array node
-    
-    - wraps each member in an object and adds to array (similar to xmlrpc
-      behaviour)
+    dnssec: make web links clickable for html version
 
-commit 1257d6832381d50280dff9133f0d5da7c4a58231
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Aug 15 16:14:34 2014 +0200
+commit b3c8f92fe48ac90802c989c74c3a34cfea065861
+Author: Ovidiu Sas <osas at voipembedded.com>
+Date:   Thu Apr 18 14:09:09 2013 -0400
 
-    textopsx: documented return behavior of msg_apply_changes()
+    dns_cache.c: fix compiler warnings
+     - warningâsr_sums[*].r_sum may be used uninitialized in this function [-Wuninitialized]
+     - warningâsr_sums[*].rr may be used uninitialized in this function [-Wuninitialized]
 
-commit 55960106bbaa908057c3f619034b146fda7df48b
+commit 38a4b85dc327e18af7e22e585f02413d7f08c56c
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Aug 15 16:01:38 2014 +0200
+Date:   Thu Apr 18 18:01:35 2013 +0200
 
-    textopsx: msg_apply_changes() exits config execution if result is not parsing well
+    Makefile.groups: dnssec module added to dedicated compile group
     
-    - sip_msg_t structure is can be invalid
-    - similar behavior with the case when the message is broken from the
-      network, it doesn't get to config file
-    - reported by Marco B.
+    - it depends on libval and other external libs
 
-commit 11ade9c99d910da6c56d3d5499c0a5b6bd902e3d
-Merge: fbcf59b 0640f7c
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Fri Aug 15 15:32:34 2014 +0200
+commit be3819d410bf5a9f11c3744d9978e60103746041
+Author: Jason Penton <jason.penton at smilecoms.com>
+Date:   Wed Apr 17 17:10:21 2013 +0200
 
-    Merge branch 'master' of ssh://git.sip-router.org/sip-router
+    modules/dialog_ng: fixed incorrect log level
 
-commit fbcf59bb4f8c1559f8361a7fd96bc9521fb250b9
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Fri Aug 15 15:29:30 2014 +0200
+commit ee2cdfdaf8e2dc177fed64c6f4ab05a85f9fb0c6
+Author: Jason Penton <jason.penton at smilecoms.com>
+Date:   Wed Apr 17 16:49:21 2013 +0200
 
-    modules/ims_registrar_pcscf: added new module param ignore_contact_rxport_check to ignore check on received port
-    	- this is particular useful for clients that register using UDP but switch to TCP for INVITEs that are too big
-    	and cant be carried by UDP. Before this change, searching for the contact would fail because of a difference
-    	in the received ports between REGISTER and other subsequent messages that don't use UDP
+    modules/cdp: Initial framework for Credit Control Application
+    	- inital support for RFC 4006
+    	- this will be used to build IMS Ro charging interface TS32.299
 
-commit 0640f7cd971115429f9d573f02e41b21a8642cb0
-Author: Muhammad Shahzad Shafi <shahzad at voip-demos.com>
-Date:   Fri Aug 8 14:00:24 2014 +0200
+commit e237f9573435a8a11672b155c1cf9a64638b87d2
+Author: Jason Penton <jason.penton at smilecoms.com>
+Date:   Wed Apr 17 16:40:32 2013 +0200
 
-    added support for network io intercept
+    modules/dialog_ng: API added function to get current dialog from msg
 
-commit 4b5f137891767264688523dfa5a12bd29e998565
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Aug 15 12:55:33 2014 +0200
+commit 2190c572cd1bc4b57a3c2dd5241e556b834c728c
+Author: Juha Heinanen <jh at tutpro.com>
+Date:   Tue Apr 16 14:28:59 2013 +0300
 
-    jsonrpc-s: implemented rpc struct_printf() api function
+    modules/usrloc: init _ul_sruid also in mi_child_init
 
-commit 34ba948cdabf7139c8563e531f18c4a486b31a00
+commit 2a77ed2bdc9341ecf7d7200e420a1f49e4e9b6ab
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Aug 14 18:24:31 2014 +0200
+Date:   Sun Apr 14 10:11:29 2013 +0200
 
-    parser/rr: free_rr() is expecting rr_t** parameter
+    auth: skip processing of PRACK in consume_credentials()
     
-    - give the parameter as &r, following the commit
-      b40d92962b680ac29dd38ffe3c8f1aa1e39d3a97
-
-commit 6a7c9fafd6ec44ad76e5914b57371a8412c04697
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Aug 14 18:14:11 2014 +0200
-
-    jsonrpc-s: removed unused variable
-
-commit 1b7e7f6dec7e4a351db19d3377850828e263784b
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Aug 14 18:11:47 2014 +0200
-
-    jsonrpc-s: completed the rpc printf() api function
-
-commit 985199614aedc4b2062e5b94eea0edbef0685647
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Aug 14 18:02:10 2014 +0200
-
-    Makefile.groups: added new modules nosip and jsonrpc-s to group extra
+    - report and patch suggestions by Jorj Bauer
 
-commit 4fff506212669d8981c9a05c9b4e31939eb71e55
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Aug 14 17:57:45 2014 +0200
+commit 56f7a8b98778f9c9b71f613a5df5eaa1705a7a00
+Author: Ovidiu Sas <osas at voipembedded.com>
+Date:   Sat Apr 13 15:37:18 2013 -0400
 
-    uac: removed unused variables
+    tls: fix compiler warning
+     - tls_config.c:61:19: warning: ât.val.sâ is used uninitialized in this function [-Wuninitialized]
 
-commit 6fb686de57f783b3c29e5b4e11ad1509882616bb
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Aug 14 17:49:18 2014 +0200
+commit d992d3b223a3319a360f033d1d904873160f706e
+Author: Juha Heinanen <jh at tutpro.com>
+Date:   Sat Apr 13 17:44:15 2013 +0300
 
-    dialog: when adding a new dialog, lock the slot until the structure is linked
+    siputils:  added new function is_supported(option)
     
-    - search for dialog based on sip attributes and if no result found, then
-      lock the hash table slot until the new structure is built and linked
-      in the table
-    - should avoid simulataneous creation for same dialog if there is a
-      not-handled retransmission or parallel forking upstream, resulting in
-      many processing managing duplicated requests
+    - Checks if given option is listed in any of the Supported: headers of
+      the request.
 
-commit c125cf6f36aedb75b4f1e0b32dbe5bdd0a48b8b5
+commit 2d27dd1080cd490e93646b38d3912dcbe3761ca5
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Aug 14 14:59:09 2014 +0200
+Date:   Sat Apr 13 11:26:48 2013 +0200
 
-    dialog: release of dialog for not-forwarded initial request done by creator
+    xcap_server: init etag variable for PUT operations
     
-    - avoid releasing new dialog in case of upstream paralel forking
-      or retransmission by other processes than the other which created the
-      dialog
-    - it could result in destroying the dialog in initial state if the
-      request was not forwarded yet, likely to happen because creator
-      process runs more callbacks
+    - the function xcaps_get_db_etag() may not found a record to db and will
+      not initialize it, resulting in bogus value passed to
+      check_preconditions()
+    - reported by Juha Heinanen, FS#283
 
-commit fcf5f5b3115c0c40f4df9eb066489bb3e590c3b1
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Aug 14 14:46:21 2014 +0200
+commit 22019e51e1e561a46eb9490c684b979f02be4e48
+Merge: 3c54420 f88dd6d
+Author: Marius Zbihlei <mariuszbi at gmai.com>
+Date:   Sat Apr 13 08:44:43 2013 +0100
 
-    dialog: simplified dlg referencing on creation and spiral detection
+    Merge branch 'dnssec'
+    
+    Added support for DNSSEC as module
 
-commit 773e3c37cfeefc679f64cac7e99f0e74072457e4
+commit 3c54420914c011bdd874a97c4c40ee9dacb59788
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Aug 14 11:14:44 2014 +0200
+Date:   Fri Apr 12 00:50:24 2013 +0200
 
-    pv: updated include paths to sha256 wrapper functions
+    core: safety check for content-lenght size in tcp read
+    
+    - avoid getting negative
+    - upon a report by Kevin Wojtysiak
 
-commit b6bd830ea93024324354dc3fb5eceaddbd8d20a3
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Aug 14 11:14:10 2014 +0200
+commit 1a22767e39d50af450a49256b4425503a2d0d388
+Author: Juha Heinanen <jh at tutpro.com>
+Date:   Thu Apr 11 09:31:37 2013 +0300
 
-    lib/srutils: new files with wrappers around sha256 and other hashing functions
+    modules/path: unescaped received param value also in path rr callback
 
-commit 1edbdbd53d2f5df0b47c8e9e892f35852362a5bd
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Aug 14 11:12:43 2014 +0200
+commit 2003bc3b1cc73caa36e9b4892d8d25f810d6c458
+Author: Juha Heinanen <jh at tutpro.com>
+Date:   Thu Apr 11 08:11:35 2013 +0300
 
-    lib/kcore: moved wrappers around sha256 to srutils
+    modules/registrar: unescape received value using kcore function
     
-    - the sha256 functions are in srutils and these created not necessary
-      inter-library dependency, confusing some linkers
+    - Now that unescaped received value goes into separate buffer, it is
+      possible to use kcore unescape function.
 
-commit 0039d7ea856e98c6c6c0c1ae6386e367ef36af1a
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Aug 14 11:09:36 2014 +0200
+commit 262b5880616d8b58cf9b012b460793f9879087b3
+Author: Juha Heinanen <jh at tutpro.com>
+Date:   Wed Apr 10 22:42:43 2013 +0300
 
-    Makefile: use one tab for install-cfg and added nop not to confuse some versions of shell
-    
-    - apparently they evaluate wrongly the sequence: escape (\), new line,
-      tab, done
+    modules/registrar: fixed bug in un-escaping of path/received
 
-commit b4e8f3f4c09b57ce6f60f542963a80b79fc0205b
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Thu Aug 14 10:48:16 2014 +0200
+commit d9c0024033278975a38c010b768e8f95c2dbb144
+Author: Juha Heinanen <jh at tutpro.com>
+Date:   Wed Apr 10 18:04:03 2013 +0300
 
-    modules/ims_qos: Do not add MCD AVP to AAR if src or dst ports are 0
-    	Check if src or dst ports in SDP are 0 and if so do not add an MCD AVP for this
+    modules/path: b/f generate valid received param value
 
-commit f44dad86621685cf7fde45e4ad36f0f0bbcfb15a
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Thu Aug 14 10:46:59 2014 +0200
+commit c01b97dd39a418acd0db7b4515d155c45d4092e6
+Author: Juha Heinanen <jh at tutpro.com>
+Date:   Wed Apr 10 18:00:04 2013 +0300
 
-    modules/ims_qos: Support Rx_AAR on AAR update
-    	Previously if Rx_AAR was called for an AAR update the function returned true
-    	Now this function gets the previous Rx session and sends an AAR update
+    modules/registrar: unescape path header received param value
 
-commit 62b59b95bcc45c7ff87a95d7c7e796bf356913bf
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Aug 14 09:13:57 2014 +0200
+commit ff2b0751b7a7925769afd14eae8c01b3af063568
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Wed Apr 10 15:01:52 2013 +0100
 
-    jsonrpc-s: new module implementing a JSONRPC server over HTTP
+    pkg/kamailio/(centos|fedora): Updated .spec
     
-    - it uses internal json library
-    - requires xhttp module to handle http messages
+    - Added sipt module
+    - Increased rel to dev2
 
-commit 3e7a7b19e2d524c100cd09b01cf277950cd01d9e
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Aug 14 09:11:22 2014 +0200
+commit 94ce2b1de63432baaaecd9285608380a40a70550
+Author: Richard Fuchs <rfuchs at sipwise.com>
+Date:   Wed Apr 10 09:34:49 2013 -0400
 
-    corex: rpc corex.list_sockets and corex.list_aliases return array
+    db_mysql: fix segfault when recursive queries are made
     
-    - type of return value set to RET_ARRAY
+    The MySQL result object (MYSQL_RES) should not be stored within the
+    srdb1 connection object, but rather within the srdb1 result object.
+    Otherwise recursive queries overwrite each other's result sets, which
+    results in segfault.
 
-commit 6e23e6159c49ba20fcb1430f2a654a754e8cc0a7
-Merge: f1f227e 21e54da
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Wed Aug 13 08:16:39 2014 +0200
+commit 8366a26fb8e3c6d5815cd4cd5bde48575e9f6b71
+Author: Richard Fuchs <rfuchs at sipwise.com>
+Date:   Wed Apr 10 09:33:53 2013 -0400
 
-    Merge branch 'master' of ssh://git.sip-router.org/sip-router
+    srdb1: add new db-private generic pointer to struct db1_res
 
-commit b40d92962b680ac29dd38ffe3c8f1aa1e39d3a97
-Author: Hugh Waite <hugh.waite at acision.com>
-Date:   Tue Aug 12 19:56:45 2014 +0100
+commit d17b02ed5014b4e32bd0060f32cabd750956779c
+Author: Vicente Hernando <vhernando at systemonenoc.com>
+Date:   Wed Apr 10 13:55:57 2013 +0200
 
-    core/parser: Free rr correctly in error cases
-    
-    - Fix potential memory leak if parameters are parsed into rr structure
+    modules/pipelimit: check correctly for all arguments in mi_set_pipe
 
-commit 392689597376eb6f047c12504bcce367f5940260
-Author: Hugh Waite <hugh.waite at acision.com>
-Date:   Tue Aug 12 19:52:27 2014 +0100
+commit d20439c0398f6821f9e0e861a597d1dee62f6c91
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed Apr 10 12:31:41 2013 +0100
 
-    outbound: Fix memory leak
+    modules/tm: documentation: Updated branch_failure route name format
     
-    - Free parameters parsed when checking for ob markers
+    - Updated event_route[tm:branch-failure:name] documentation
+    - Updated t_next_contact_flow function
 
-commit 21e54da18f9bc6f87f913a897c9183074de4c937
-Author: Marcus Hunger <hunger at sipgate.de>
-Date:   Tue Aug 12 16:09:28 2014 +0200
+commit 6e28b187ab4d9cb100e58cb7667c0ee64e8b6deb
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed Apr 10 11:33:15 2013 +0100
 
-    rtpproxy: swap tags for lookup command (l) to fix one way audio on reinvite
+    modules/tm: Enable named branch_failure routes
     
-    - affected cases when the lookup was used explicitely
+    - branch failure routes must be named with the format:
+    -- "tm:branch-failure:myroute"
+    - and enabled with the function:
+    -- t_on_branch_failure("myroute")
 
-commit 651fd496f106792558c3d28f60a3d5ac3f834042
-Author: lucian balanceanu <lucian.balanceanu at 1and1.ro>
-Date:   Mon Aug 11 14:09:57 2014 +0300
+commit fb4d9dae890705388275abe1fa06358187917d01
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed Apr 10 11:27:59 2013 +0100
 
-    siptrace: added force_send_sock
-    
-    - the local interface in form of SIP uri from where to send
-      the duplicated traffic. In the absence of this parameter
-      kamailio automatically picks an interface.
+    core: Allow colon separated tokens in event_route names
     
-      Credit goes to the 1&1 team.
+    - Event routes can have named routes following the format:
+    -- <module>:<event>:<name>
+    -
 
-commit 32a26c25927145a54f9c631cc0b5d498c18907d0
-Author: lucian balanceanu <lucian.balanceanu at 1and1.ro>
-Date:   Mon Aug 11 13:55:31 2014 +0300
+commit a1edd20adff116ce78083ca9744e7072e0305728
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed Apr 10 11:10:27 2013 +0100
 
-    siptrace: adds optional addr param to sip_trace()
-    
-    - address is a SIP uri which specifies the address
-      of the capturing server. This parameter trumps
-      duplicate_uri and allows tracing to more than one
-      server.
+    modules/registrar: Remove unnecessary BRANCH_FAILURE flags
     
-      Credit goes to the 1&1 team.
+    Functions that run in an event route require the EVENT_ROUTE / REQUEST_ROUTE
+    flag set, not the BRANCH_FAILURE_ROUTE flag
 
-commit 82e67c07eebe9f7277156a6a6d87ffd5e04c892d
-Author: Jorj Bauer <jorj at isc.upenn.edu>
-Date:   Fri Aug 8 09:26:21 2014 -0400
+commit 200357577d70f13ad1f01d8f831eca274ca2e669
+Author: Juha Heinanen <jh at tutpro.com>
+Date:   Wed Apr 10 09:17:58 2013 +0300
 
-        modules/sca: fix 180 replies in sca_call_info_invite_reply_18x_handler()
-    
-        - Per Broadworks Release 13.0v1 documentation, 180s should produce
-          "appearance-state=progressing" just like 183s do; Polycom OS 3.3.4
-          doesn't care, but 4.x swaps leg information when it hears
-          "appearance-state=alerting"
-        - report and patch from  Joao Vitor Arruda
+    modules/tm: updated README on t_branch_timeout and t_branch_replied usage
 
-commit f1f227e661697cd527f6ab7077c275ddfc8ba23d
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Fri Aug 8 11:38:00 2014 +0200
+commit 2be84576fb5bc7d973b84b7a9f6a61b28ce2cead
+Merge: 3b785c2 12f441f
+Author: Juha Heinanen <jh at tutpro.com>
+Date:   Wed Apr 10 09:11:55 2013 +0300
 
-    modules/ims_usrloc_pcscf: fixed bug when updating DB record for P-CSCF contact
+    Merge branch 'master' of ssh://git.sip-router.org/sip-router
+    
+    modules/tm: allow calling of t_branch_timeout and t_branch_replied from
+        tm:branch-failure event route
 
-commit d8d7f13e073dc00532326433c689030f6950e26d
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Fri Aug 8 08:36:13 2014 +0200
+commit 3b785c288916269664bf77d916572945ce93e489
+Author: Juha Heinanen <jh at tutpro.com>
+Date:   Wed Apr 10 09:09:54 2013 +0300
 
-    modules/ims_icscf: for UAR pass in empty realm instead of RURI domain
-    	- this allows for authenticating against different domain from the domain in RURI
+    modules/tm: allow calling of t_branch_timeout() and t_branch_replied()
+        from tm:branch-failure event route
 
-commit 451cce6b5a4edada89a05f80e220b08be58a56a4
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Fri Aug 8 08:34:48 2014 +0200
+commit 12f441f4b75f15ab25fc42889bfce65940d0c0d0
+Author: Richard Fuchs <rfuchs at sipwise.com>
+Date:   Tue Apr 9 16:38:22 2013 -0400
 
-    modules/ims_auth: use IMS lib for getting IMPI/IMPUs (cleanup)
+    pv: implement pv transformation {en,de}code.base64
 
-commit d6b98639bd6f11661d61060c58597d53b01dadd0
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Fri Aug 8 08:33:56 2014 +0200
+commit dbb01573bc30eb59e712536d43c0caad357d90fa
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Sun Apr 7 20:32:02 2013 +0200
 
-    lib/ims: When getting IMPI, only check check realm credentials if a realm is passed in
+    snmpstats Update dev note
 
-commit 2eb751c89e81af4d55cd1a3e4928da7c9d9276c4
-Author: lucian balanceanu <lucian.balanceanu at 1and1.ro>
-Date:   Thu Aug 7 16:57:35 2014 +0300
+commit 5886fa623776eae7a33ff8777e68d29a170f0fac
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Sun Apr 7 10:17:16 2013 +0200
 
-    userblacklist: updated 1&1 module maintainers
+    lib/kcore Make sure that the bytes waiting stats also report IPv6 sockets
 
-commit 1342fe8e81cefbfd5ab1991b3e47f6fc0838f04c
-Author: lucian balanceanu <lucian.balanceanu at 1and1.ro>
-Date:   Thu Aug 7 16:57:04 2014 +0300
+commit 2a895f5dcfd5b7ce003e37b2b1db6690852e3ff5
+Author: Juha Heinanen <jh at tutpro.com>
+Date:   Tue Apr 9 18:28:01 2013 +0300
 
-    pdb: Updated 1&1 module maintainers
+    modules/tm: load_contacts() now prefers contacts whose path is empty
+    
+    - For contacts with the same q, order contacts so that contacts that
+      have empty path are preferred over ones that have path defined.  In
+      practice, this affects only contacts with the same ua instance id.
 
-commit 2c8e0297c3558b1b6823c8efe806ffae0ff2a609
-Author: lucian balanceanu <lucian.balanceanu at 1and1.ro>
-Date:   Thu Aug 7 16:56:07 2014 +0300
+commit 34290a9be20cd5986a569caeba3a2fd0efbeeb1f
+Author: Juha Heinanen <jh at tutpro.com>
+Date:   Tue Apr 9 17:25:59 2013 +0300
 
-    p_usrloc: Updated 1&1 module maintainers
+    modules/rr: loose_route() return code 2 documentation
 
-commit 4870a4913e0032d888c22afcb6ae1a50ea807b53
-Author: lucian balanceanu <lucian.balanceanu at 1and1.ro>
-Date:   Thu Aug 7 16:52:49 2014 +0300
+commit fd5a1d772cc08af05e669ee00e926ee488f734f8
+Author: Juha Heinanen <jh at tutpro.com>
+Date:   Tue Apr 9 17:08:43 2013 +0300
 
-    carrierroute: Updated 1&1 maintainers
+    modules/rr: new loose_route() result code
+    
+    - Introduced new loose_route() result code 2 that is returned if
+      route calculation based on flow-token has been successful.
 
-commit 89bd0b5d7ce94b33a24d65ab6fff7175583bc76a
-Author: Carsten Bock <carsten at ng-voice.com>
-Date:   Thu Aug 7 12:24:16 2014 +0200
+commit 1dde1f64524db71b374ee81943fc259e8c818892
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Tue Apr 9 11:32:17 2013 +0100
 
-    ims_usrloc_pcscf: Set NULL properly also for the CONTACT row
+    modules/tm: Fix uninitialised instance and ruid values
+    
+    In t_next_contacts:
+    - Ensure instance was initialised to null when not present
+    - Extract ruid value before storing a subsequent flow
 
-commit 7b7754a41711aa09d63d219c3930dc5090eaf326
-Author: Carsten Bock <carsten at ng-voice.com>
-Date:   Tue Aug 5 17:21:06 2014 +0200
+commit 0d41a8d0a251b351104b3feba8fde5373e928d92
+Author: Vicente Hernando <vhernando at systemonenoc.com>
+Date:   Tue Apr 9 01:03:49 2013 +0200
 
-    ims_usrloc_scscf: In case the contact_id after insert_update is 0, do the old query again (last_inserted_id is only set, if there was really an UPDATE or INSERT, not if nothing was changed)
+    modules/ndb_redis: b/f redisc_exec returns false if redis server is down.
 
-commit 6b833a82cb8c0978fae54afa086eff6d5479fa17
+commit a177a33b9938a36cfaedbce61734a1525e5b1665
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Aug 5 13:10:34 2014 +0200
+Date:   Tue Apr 9 00:21:44 2013 +0200
 
-    pua_xmpp: fixed wrong define guardian id
+    .gitignore: added protoshoot binary the ignore list of git
 
-commit c0794dfa98fccabd1da31d91e1d56c601fb15d9c
+commit 13fd48f89555f5421e8285669e303bcefe44f149
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Aug 5 13:09:40 2014 +0200
+Date:   Tue Apr 9 00:18:35 2013 +0200
 
-    ims_isc: removed unused variable
+    parser: safety check for max port length in URI
+    
+    - can't be longer than 5, a port being 16b value
+    - reported by Kevin Wojtysiak
 
-commit 55b42c5ba9e78b1d6662d45f1b68898bc67548c9
+commit 28a8b87885e373bee8cc81985277ae718973fdfd
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Aug 5 13:09:16 2014 +0200
-
-    pua: solved warning on comparing unsigned expression
-
-commit 1b7526fe4de38a29037c0e0e35316b80ae2b625d
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 29 08:09:18 2014 -0700
+Date:   Tue Apr 9 00:15:47 2013 +0200
 
-    doc: replace STR_PARAM with PARAM_STR
-
-commit 4d23bafa1b37aca9564780dfbec3b560f7e6026e
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 29 08:04:11 2014 -0700
-
-    obsolete modules: replace STR_PARAM with PARAM_STRING. Blind replace
-
-commit 6dd60aeea99c28c1d51c65e9da01bdc8360e586e
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 29 08:01:16 2014 -0700
-
-    uac: replace STR_PARAM with PARAM_STR
-
-commit 6a993eb32981aa4e0a7c743c1feec373bd61d27a
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 29 07:13:43 2014 -0700
-
-    cpl-c: replace STR_PARAM with PARAM_STR
-
-commit 5da0d7881b88b27bbc11d98350a3c8eaa5d00993
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 29 07:01:41 2014 -0700
-
-    evapi: replace STR_PARAM with PARAM_STRING
+    rr: use port.len to check for buffer overflow instead of max port len
+    
+    - reported by Kevin Wojtysiak
 
-commit c1fbe4343bc060d8ab662e3fe6ccf0001a98f7a4
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 29 07:00:09 2014 -0700
+commit a9e555e6e41271e015c47d29ba85276673d3b7b6
+Author: Andrew Mortensen <admorten at isc.upenn.edu>
+Date:   Mon Apr 8 15:01:41 2013 -0400
 
-    sst: replace STR_PARAM with PARAM_STRING
+    modules/sca: reduce verbosity of RPC sca.all_subscriptions output
+    
+    - accommodate more subscriptions without hitting kamcmd buffer limits.
 
-commit 71be4657776b78303453e9743df06094fd1b3827
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 29 06:58:22 2014 -0700
+commit 7eaaf7ec7a3727ea38a330d51771b0446c58d8d6
+Author: Vicente Hernando <vhernando at systemonenoc.com>
+Date:   Mon Apr 8 12:13:54 2013 +0200
 
-    jsonrpc-c: replace STR_PARAM with PARAM_STRING
+    modules/ndb_redis: avoid warning unused next_rpl variable.
 
-commit 45aee434dc9117ac52964c6a6e624e3717445dcb
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 29 06:57:19 2014 -0700
+commit a43f2ebd4c952be55b2844f94d3a8b587a9e5202
+Author: Vicente Hernando <vhernando at systemonenoc.com>
+Date:   Mon Apr 8 11:47:51 2013 +0200
 
-    corex: replace STR_PARAM with PARAM_STRING
+    modules/ndb_redis: b/f restore correctly last char in argument strings.
 
-commit d53592fe7b8e6fb70db4c506a6a2c955f6a13956
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 29 06:56:43 2014 -0700
+commit 4924d136c7fd1886e411436c8005945b41c08f74
+Author: Vicente Hernando <vhernando at systemonenoc.com>
+Date:   Mon Apr 8 11:32:40 2013 +0200
 
-    peering: replace STR_PARAM with PARAM_STRING
+    modules/ndb_redis: follow section id guidelines.
 
-commit 797abc5a209fcc5d01079306bc0e1ef860fa24ba
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 29 06:55:56 2014 -0700
+commit f4e4c3f8741868a310a59ec165a82e0353b7f161
+Author: Torrey Searle <tsearle at gmail.com>
+Date:   Mon Apr 8 11:18:44 2013 +0200
 
-    mediaproxy: replace STR_PARAM with PARAM_STR
+    modules/sipt: adapt module to use SUBTYPE_ISUP
 
-commit 51b233159a5cca5ed787dd5970bda25559f872e2
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 29 06:47:07 2014 -0700
+commit 25135d4deb54281bffdf372ad948ef0fa38b2d7b
+Author: Torrey Searle <tsearle at gmail.com>
+Date:   Mon Apr 8 11:17:04 2013 +0200
 
-    xhttp_rpc: replace STR_PARAM with PARAM_STR
+    parser/parse_content: add support for the ISUP subtype
 
-commit a4996ef1884110473d02cf41657d8528a4f08d2e
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 29 06:45:43 2014 -0700
+commit b7829454810379c46ed74ff78dd3e8099ac05fb4
+Author: Juha Heinanen <jh at tutpro.com>
+Date:   Sun Apr 7 20:07:23 2013 +0300
 
-    xmlops: replace STR_PARAM with PARAM_STRING
+    modules/textops: free spve params of in_list function
 
-commit cbc8cfb27eae574d99e2417d492ba076e7928d7c
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 29 06:45:03 2014 -0700
+commit 87da891388c3e76c80ac677e7b2342ce9f86a3f1
+Author: Juha Heinanen <jh at tutpro.com>
+Date:   Sun Apr 7 18:01:19 2013 +0300
 
-    mqueue: replace STR_PARAM with PARAM_STRING
+    modules/registrar: b/f route param was passed uninitialized to parse_rr_body
 
-commit e8025176e64abb9c48516a1b97b63647f4950650
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 29 06:44:18 2014 -0700
+commit 75dfe341aba8bdc6f0ead4f060f05c34c69e267e
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Sun Apr 7 10:03:12 2013 +0200
 
-    auth_ephemeral: replace STR_PARAM with PARAM_STRING
+    snmpstats Avoid compiler warnings with older versions of net-snmp
+    
+    Centos has an older version of net-snmp that has slightly different
+    structure definitions than the current one.
 
-commit f829556fe1278f9892d9fba3c88f240821484406
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 29 06:43:21 2014 -0700
+commit f2c17f4325d5b03697e76bd4b4ee8050d5e4d6c8
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Sun Apr 7 09:53:24 2013 +0200
 
-    regex: replace STR_PARAM with PARAM_STRING
+    snmpstats Final fixes for IPv6 support.
 
-commit 1bac69c812e926a7910de30d8b6fe101a67a042e
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 29 06:41:47 2014 -0700
+commit 0fd0906680ce0f022820fd15819486eb4acfe24a
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Sun Apr 7 09:45:21 2013 +0200
 
-    pua_usrloc: replace STR_PARAM with PARAM_STR
+    snmpstats minor typo fixes
 
-commit 293721acdcde8b1e753c0c229b5c3e9d5a44ed56
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 29 06:39:10 2014 -0700
+commit dbde9b609c2a3538fca1e7db72e518f97b3f018a
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Sat Apr 6 22:06:47 2013 +0200
 
-    pua_xmpp: replace STR_PARAM with PARAM_STR
+    snmpstats Add IPv6 support in list of active interfaces
+    
+    Output from SNMPwalk after this patch:
+    KAMAILIO-SIP-COMMON-MIB::kamailioSIPTransportRcv.ipv6."20:01:DB:80:21:2e:00:00:00:00:00:00:00:00:00:22".5080 = BITS: 40 udp(1)
 
-commit 2fd033d4862802ac6dc6aad77ed4626cb8d334bf
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 29 06:37:05 2014 -0700
+commit bddf66407ef7521f3d1f1e941b4c1e104e59d1ef
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Sat Apr 6 22:04:51 2013 +0200
 
-    cfgutils: replace STR_PARAM with PARAM_STRING
+    snmpstats fix typo in Makefile.
 
-commit c2154c706e19afd588905bd960dfb3f5d65ce186
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 29 06:35:59 2014 -0700
+commit 7bbf8fece2cc93c5b1ddd2c3dcc12e8a920dd54d
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Sat Apr 6 22:02:48 2013 +0200
 
-    xcap_client: replace STR_PARAM with PARAM_STRING
+    snmpstats Add disabled section in Makefile for compilation on Centos systems
+    
+    Net-SNMP and snmpd can be built with embedded perl and libwrap support. If that's
+    the case on your system you need to enable the EMBEDDED_PERL section in the
+    Makefile. Maybe this could be enabled automatically.
 
-commit 42e093439d9fe7f53c59dbe2704dd45b3244670f
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 29 06:33:45 2014 -0700
+commit e28a06a7a8f5558bb81cfc09d5cb70b9c6938328
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Sat Apr 6 21:56:59 2013 +0200
 
-    db_oracle: replace STR_PARAM with PARAM_STRING
+    lib/kcore Fix IPv6 support in interface list
+    
+    Added a new function that takes family as an argument. In order to list both
+    IPv4 and IPv6 you need to call that function once per address family.
+    Keep the old IPv4-only function for backwards compatibility.
 
-commit b09c462b797299ea245bf07add76fe3030e89008
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 29 06:31:48 2014 -0700
+commit a56a0e32a329ec05a6bb33713b120a949a0cf04b
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Sat Apr 6 14:59:19 2013 +0200
 
-    websocket: replace STR_PARAM with PARAM_STR
+    pipelimit Add section IDs to xml documentation
 
-commit 428035bfc5459763f7b67fdeab432624b312d381
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 29 06:08:04 2014 -0700
+commit 0f4168e0e6b53c8993121f7a751cabecc2d3e1f3
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Sat Apr 6 14:51:59 2013 +0200
 
-    dialplan: replace STR_PARAM with PARAM_STR
+    ipops Add section IDs to README xml files
 
-commit 3e5a7383f6ade32d14469b3ee396d9e8822bc2ff
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 29 05:54:24 2014 -0700
+commit 1eeae38650ce70ade73f7e03fd3be78f1d97e0e5
+Author: Torrey Searle <tsearle at gmail.com>
+Date:   Sat Apr 6 11:59:55 2013 +0200
 
-    nathelper: replace STR_PARAM with PARAM_STR
+    modules/sipt/doc: add section headers & fix README file
 
-commit ba29610b268b640982db2f2254e7fdb2fd9fcdcc
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 29 05:08:40 2014 -0700
+commit 0ecde91fe6e911997b1f5ee33eb50fa6778b7a89
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Fri Apr 5 21:30:06 2013 +0200
 
-    app_mono: replace STR_PARAM with PARAM_STRING
+    rr: added missing s in sips for record route
+    
+    - reported by Sander van Grieken
 
-commit a2613acc416095ceb9711659aff966ebb61cf86b
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 29 05:07:29 2014 -0700
+commit 6433c3b1c2d84d6a6168e7bdccf9c4f13dc50586
+Author: Alexandr Dubovikov <alexandr.dubovikov at gmail.com>
+Date:   Fri Apr 5 21:21:33 2013 +0200
 
-    ims_qos: replace STR_PARAM with PARAM_STR
+    modules/sipcapture: added customization for X-CID header.
+    		thanks for the patch goes to Markus Monka <mmonka at gmail.com>
 
-commit 104a1b80e22c35164c909c7fcf949b46b29c74ea
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 29 05:01:50 2014 -0700
+commit 19c8f0eaac2b77f06f2842d3a7d481268afa096a
+Author: Alexandr Dubovikov <alexandr.dubovikov at gmail.com>
+Date:   Fri Apr 5 21:10:57 2013 +0200
 
-    xhttp_pi: replace STR_PARAM with PARAM_STR
+    modules/sipcapture: fixed ERR message for HEPv3,
+    		added table param for sip_capture() function
 
-commit 7495a6b1454819ad27078e6546f9b5951c7dfcd3
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 29 04:58:44 2014 -0700
+commit d992e4dc8742807f71645f385d68d60b90746fb3
+Author: Torrey Searle <tsearle at gmail.com>
+Date:   Fri Apr 5 18:43:06 2013 +0200
 
-    db_cluster: replace STR_PARAM with PARAM_STRING
+    modules/sipt: updated README
 
-commit 8926ebbdc92681eef443b8625b7529980f5568e2
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 29 04:56:53 2014 -0700
+commit 59b9208700e578df5000f8ad732c2e444712b0fa
+Author: Torrey Searle <tsearle at gmail.com>
+Date:   Fri Apr 5 18:38:36 2013 +0200
 
-    snmpstats: replace STR_PARAM with PARAM_STRING
+    modules/sipt: added some additional getter methods
+    
+    new functions: sipt_get_cpc() sipt_get_calling_party_nai() sipt_get_called_party_nai()
 
-commit 801f0df04b188b34594504e1dcde68aba3b0418c
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 29 04:50:05 2014 -0700
+commit 38053da7b5951b13be413aac61f89ad418aba99e
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Fri Apr 5 14:12:22 2013 +0100
 
-    tmrec: replace STR_PARAM with PARAM_STRING
+    modules/websocket: Update README xml with section IDs
 
-commit 7059d08c1a6071a9bbc7c6ffbe69b386e8f568f7
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 29 04:48:54 2014 -0700
+commit b38d9c93207a219bbcbc4ad40886b983a391c90b
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Fri Apr 5 14:07:18 2013 +0100
 
-    h350: replace STR_PARAM with PARAM_STRING
+    modules/tm: Added branch_failure event route to tm documentation
 
-commit bbf33a0d15b2c888cda147d49688af10b752a0e7
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 29 04:33:24 2014 -0700
+commit 8def957134e6068c14d2180d8497c6eb1f2a6cc5
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Fri Apr 5 13:35:51 2013 +0100
 
-    pdb: replace STR_PARAM with PARAM_STRING
+    modules/websocket: re-added declaration of ws_keepalive_mechanism to ws_frame.c
+    
+    - Accidentally removed when configuration framework stuff was added.
 
-commit 4e81b1632921dc5104842740b6ea3d9ada565387
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 29 04:29:13 2014 -0700
+commit 52741b4c709713b0cd0a3b9b81701ce2cf95b731
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Fri Apr 5 13:33:19 2013 +0100
 
-    app_java: replace STR_PARAM with PARAM_STRING
+    Revert "modules/websocket: b/f defined missing ws_keepalive_mechanism variable"
+    
+    This reverts commit caf4769ec0f243df71e79ee3c0781afbe5884bac.
 
-commit a2808458b5ff1a2b359d501b108f1c9155b01078
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 29 04:24:48 2014 -0700
+commit caf4769ec0f243df71e79ee3c0781afbe5884bac
+Author: Juha Heinanen <jh at tutpro.com>
+Date:   Fri Apr 5 15:17:07 2013 +0300
 
-    ims_auth: replace STR_PARAM with PARAM_STR
+    modules/websocket: b/f defined missing ws_keepalive_mechanism variable
 
-commit 1bd3093e82df04888fbdfc0212cb5a18e4ee422b
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 29 03:11:57 2014 -0700
+commit 2168999d8f198268526404946b0def97b87fd8f5
+Merge: 98d76f9 6a9048a
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Fri Apr 5 09:33:38 2013 +0100
+
+    Merge remote branch 'origin/hpw/branch_failure_route'
+    
+    * origin/hpw/branch_failure_route:
+      modules/tm: Fix t_next_contact_flow return value
+      modules/tmx: Add $T_reply_ruid pv to return ruid for a branch reply
+      modules/tm: Make ruid available in uac structure
+      modules/registrar: Allow unregister for ruids in branch_failure_route
+      modules/usrloc: Fix get_urecord_by_ruid to return static aor
+      modules/tm: Fix setting instance in uac branches
+      modules/tm: Enable retrieving of branch instance id from uac structure
+      modules/xprint: Updated to use the new get_branch()/next_branch() functions
+      modules/pv: Updated to use the new get_branch()/next_branch() functions
+      modules/permissions: Updated to use the new get_branch()/next_branch() functions
+      modules/domain: Updated to use the new get_branch()/next_branch() functions
+      core: Update get_branch() to return instance from appended branches
+      modules/tm: Update t_next_contact_flows for use in branch_failure event_route
+      core: Add defines required for a new branch_failure_route type
+      modules/tm: Create branch-failure event route
+      Revert "core: Initial revision of branch_failure_route"
+      core: Initial revision of branch_failure_route
+      modules/tm: Initial revision of branch_failure_route
+
+commit 98d76f94f2a4587b7a93e8e9982ff8017cabd9a3
+Author: Jason Penton <jason.penton at smilecoms.com>
+Date:   Fri Apr 5 09:09:00 2013 +0200
+
+    lib/ims: Added cscf_get_p_charging_vector to retrieve icid,term_ioi,orig_ioi
+
+commit 0964bc96b1e3cd3bb7478388f6df3cb69fffce64
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Thu Apr 4 22:27:02 2013 +0200
 
-    matrix: replace STR_PARAM with PARAM_STR
+    snmpstats Add support for the new transports as well as new roles
+    
+    The edgeproxyServer is a SIP Outbound edge proxy that manages flows to NATted clients.
+    The sipcaptureServer collects SIP messages for Homer SIP capture
 
-commit aa1fc5b382d86f5ae0c610a14b9476aaf3f03910
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 29 03:07:59 2014 -0700
+commit ac19c57490f2d7758fb0d66e5fc473dcd464d325
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Thu Apr 4 21:57:31 2013 +0200
 
-    purple: replace STR_PARAM with PARAM_STR
+    snmpstats Align transports to RFC 4780
 
-commit 2b724d52ae78b60eddebbf731048e40f1d0d93dd
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 29 03:03:31 2014 -0700
+commit 53579abc49fcb61ba7358d64e2d25bdabfe42afd
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Wed Apr 3 22:17:27 2013 +0200
 
-    ims_charging: replace STR_PARAM with PARAM_STR
+    group Update README xml with section ID's
 
-commit 24ef39392d6b80615301b50d56ab7d30f5895017
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Mon Jul 28 08:35:00 2014 -0700
+commit 0f7821b1ab454e0b0a7ec49f76f1f63c65f12a90
+Author: Torrey Searle <tsearle at gmail.com>
+Date:   Thu Apr 4 17:08:39 2013 +0200
 
-    xmpp: replace STR_PARAM with PARAM_STRING
+    modules/sipt: regenerate README
 
-commit 3efe72105c906a6768df78d907d1239d9c0c30cd
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Mon Jul 28 08:29:34 2014 -0700
+commit 6cff96362ef9c2a675ff170f804cad08db2a1f87
+Author: Torrey Searle <tsearle at gmail.com>
+Date:   Thu Apr 4 17:06:31 2013 +0200
 
-    ndb_redis: replace STR_PARAM with PARAM_STRING
+    modules/sipt/doc: fix typo in method name
 
-commit 04e4d5f383e5d0528b121e111c1f3679d95ea829
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Mon Jul 28 07:43:04 2014 -0700
+commit e09e20ad7524e2d1469187812b8920723481014f
+Author: Torrey Searle <tsearle at gmail.com>
+Date:   Thu Apr 4 15:43:29 2013 +0200
 
-    avpops: replace STR_PARAM with PARAM_STR
+    modules/sipt: resolve a compiler warning on osx
 
-commit 7ba2418b53c9c92f6d12569cb680c4a5fddf5cac
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Mon Jul 28 07:38:27 2014 -0700
+commit 9dde9cb53367b75643c4f95f5aea2b7ce1d1f859
+Author: Carsten Bock <carsten at ng-voice.com>
+Date:   Thu Apr 4 12:06:37 2013 +0200
 
-    nat_traversal: replace STR_PARAM with PARAM_STRING
+    ims_auth: Log, which AVP could not be found.
 
-commit 341efdf030d31cd41b59e9308266c2caeaf57409
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Mon Jul 28 07:15:00 2014 -0700
+commit b523c774721afaa34f36dc278805736e04b3d27c
+Author: Torrey Searle <tsearle at gmail.com>
+Date:   Thu Apr 4 11:56:03 2013 +0200
 
-    geoip: replace STR_PARAM with PARAM_STRING
+    modules/sipt: Update README in separate commit per best practices
 
-commit 9a978d228dfa308a3730be291b36d04975c50761
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Mon Jul 28 07:13:55 2014 -0700
+commit 8cdbaddbf8ec9bfedc32732a6fed6753fab424ec
+Author: Torrey Searle <tsearle at gmail.com>
+Date:   Thu Apr 4 11:40:26 2013 +0200
 
-    xhttp: replace STR_PARAM with PARAM_STRING
+    modules/sipt/doc: corrected documentation typos
 
-commit 4ca5c2de24bb6a8af376b6ceb156f11105a04bf4
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Mon Jul 28 06:30:53 2014 -0700
+commit a45583716671406f6a76cfdf8778517a28cbf2e3
+Author: Torrey Searle <tsearle at gmail.com>
+Date:   Thu Apr 4 10:20:08 2013 +0200
 
-    mi_datagram: replace STR_PARAM with PARAM_STRING
+    modules/sipt: initial import of module
 
-commit 0985b5ab258f4415842aa21a3a14955117e6e1e5
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Mon Jul 28 06:28:57 2014 -0700
+commit 6a547b27a6e4715f2ccc3094018ed564066f7834
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Thu Apr 4 00:38:56 2013 +0100
 
-    mi_fifo: replace STR_PARAM with PARAM_STRING
+    doc/cfg_list: added stun to cfg docbook Makefile
 
-commit 80f51c94606165c3a69be83d9ad05eb72129a8fe
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Mon Jul 28 06:26:19 2014 -0700
+commit 91b357872f06e988fd09003cffc02742d2731ce3
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Thu Apr 4 00:38:25 2013 +0100
 
-    carrierroute: replace STR_PARAM with PARAM_STR
+    modules/stun: added read-only stun_active cfg value
 
-commit 3230d3de3cdf86e4e6406c562a9649d2c31b8d6d
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Mon Jul 28 05:57:14 2014 -0700
+commit 0c49defdd27567e522c0555a9a40b0c76f5ef865
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Thu Apr 4 00:38:01 2013 +0100
 
-    misc_radius: replace STR_PARAM with PARAM_STRING
+    modules/websocket: removed some unnecessary includes
 
-commit 48065a046b3cc40981912d4b7bf30af57df93d3b
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Mon Jul 28 05:54:54 2014 -0700
+commit fc1f1b750f911f7fa2d453f6ce61f011844536a9
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Thu Apr 4 00:37:22 2013 +0100
 
-    uac_redirect: replace STR_PARAM with PARAM_STRING
+    modules/outbound: a bit of tidying up
 
-commit 414b653c94e80bd862ac9a88c741b8ba6c6e7d83
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Mon Jul 28 05:52:24 2014 -0700
+commit 124a40aa8c2de6831bc801899aeaa9ec05bebf77
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Thu Apr 4 00:23:54 2013 +0100
 
-    domain: replace STR_PARAM with PARAM_STR
+    doc/cfg_list: added outbound and websocket to cfg doc generation
 
-commit e22d2caf320aa02f85d648dea3b7045107692549
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Mon Jul 28 05:47:41 2014 -0700
+commit a33d556fc5c6c11d6364daed01bf91dbf552784b
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Thu Apr 4 00:23:16 2013 +0100
 
-    auth_db: replace STR_PARAM with PARAM_STR
+    modules/websocket: updated copyright year
+    
+    - also remove configuration framework stuff in preparation for putting it
+      in separate files.
 
-commit fac144713950463e3862787e855272835da505fb
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Mon Jul 28 05:43:47 2014 -0700
+commit fe912bc27e41906902f5d25838eac95304c332eb
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Thu Apr 4 00:22:49 2013 +0100
 
-    group: replace STR_PARAM with PARAM_STR
+    modules/websocket: moved config framework stuff to separate files
+    
+    - To facilitate docbook
 
-commit 0dc64228350e7ba62552046688f9646d2b228c8e
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Mon Jul 28 05:27:07 2014 -0700
+commit f85976ec461fc8325c9fa55e2b38ffef132098e1
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Thu Apr 4 00:22:15 2013 +0100
 
-    sca: replace STR_PARAM with PARAM_STR
+    modules/outbound: updated year in copyright statement
 
-commit 18194e2ec895936d7b00f010b3659754d3e328e1
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Mon Jul 28 05:22:35 2014 -0700
+commit cf5a4dcc3454f3c0e08228d0824f57db8aa2e192
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Thu Apr 4 00:21:47 2013 +0100
 
-    pua: replace STR_PARAM with PARAM_STR
+    modules/outbound: fixed typo
 
-commit 969b716adcc2e01469c4115ea1e046f45d8287d4
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Mon Jul 28 05:19:19 2014 -0700
+commit 5dc7bf64ede0d41cead968ac52677df022f262a8
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Thu Apr 4 00:20:55 2013 +0100
 
-    pua_bla: replace STR_PARAM with PARAM_STR
+    modules/outbound: Removed extern for ds_ping_reply_codes_update
 
-commit 782755fcaccba55d777027cd1700defea9c22bce
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Mon Jul 28 05:15:54 2014 -0700
+commit 7fffcebb7ec85bfdffd3712b8f7d8ee91575fe22
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Wed Apr 3 21:55:47 2013 +0200
 
-    uri_db: replace STR_PARAM with PARAM_STR
+    pike Add counter for blocked IP addresses
 
-commit 3246487eaf3b51ae64b4f141233ea928647f7496
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Mon Jul 28 05:07:00 2014 -0700
+commit ddfadf58f4a99fb160554e81e43fca5ddf0c38ad
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Wed Apr 3 21:27:45 2013 +0200
 
-    app_perl: replace STR_PARAM with PARAM_STRING
+    pike Update README with section ID's
 
-commit 979c7ef05f990e71f90f0b61caf80e6e26bae6e6
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Mon Jul 28 05:02:40 2014 -0700
+commit ba074d8a9ad0c415237e9c604a3adb432c51b754
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Wed Apr 3 21:22:47 2013 +0200
 
-    call_control: replace STR_PARAM with PARAM_STR
+    sst Update documentation and add reference to dialog_ng module
 
-commit 81708806c99c111e0374e7268695c1cfff06475e
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Mon Jul 28 03:48:08 2014 -0700
+commit 530e1e9e3f5100c4e6fc8ecb1f2005c07e7b860a
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Wed Apr 3 21:11:08 2013 +0200
 
-    userblacklist: replace STR_PARAM with PARAM_STR
+    snmpstats Documentation updates
 
-commit 6e31671a9ccd9bbc4e7dd50c1608c73fe3f3f3b6
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Mon Jul 28 03:43:11 2014 -0700
+commit 43cc6015e8604e309672da4d754b5022d1e256c9
+Author: Andrew Mortensen <admorten at isc.upenn.edu>
+Date:   Wed Apr 3 14:54:36 2013 -0400
 
-    rtimer: replace STR_PARAM with PARAM_STRING
+    modules/sca: ensure line-seize sub update uses index from request
+    
+    - lazy removal of line-seize subscriptions that were not used for a
+      call could lead to failure to release expired seized appearance.
+      Client must have a lingering, expired line-seize subscription that
+      hasn't yet been purged by the timer, and indices must not match.
+      Fix ensures that the appearance-index from the new line-seize
+      subscription overwrites the index left over from the expired one.
 
-commit 89d757171b7416cae3053ac371ae1bbf5653784b
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Mon Jul 28 03:42:18 2014 -0700
+commit 3339e7a5bd205599fed63f82536626732b3f23d9
+Author: Andrew Mortensen <admorten at isc.upenn.edu>
+Date:   Wed Apr 3 14:46:27 2013 -0400
 
-    ndb_cassandra: replace STR_PARAM with PARAM_STR
+    modules/sca: fix SCA_CALL_INFO_EMPTY macro
+    
+    - test should be a logical OR, not AND.
 
-commit a97a7d9d2beade6980ba6d5bd0abe4e0e88e73ec
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Mon Jul 28 03:38:20 2014 -0700
+commit 348876e0097f70b6e155e1afe58030d5bd6077fc
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Wed Apr 3 20:56:49 2013 +0200
 
-    imc: replace STR_PARAM with PARAM_STR
+    timer Documentation update (section IDs)
 
-commit 4ea4bd521965ff161aa01cab3b124cc7959b2b57
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Mon Jul 28 03:32:13 2014 -0700
+commit 7670fafb184f0f16bf5903b4c75c3d327891756f
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Wed Apr 3 20:53:49 2013 +0200
 
-    pua_reginfo: replace STR_PARAM with PARAM_STR and some indention fixes
+    sipcapture Update to README xml files (section IDs)
 
-commit 324279ee4055c64803aee0313e13cb588a7d3241
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Mon Jul 28 03:25:48 2014 -0700
+commit 244bfd5004804b20d983afd6e9caccfd9f70fde4
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Wed Apr 3 20:20:47 2013 +0200
 
-    mi_rpc: replace STR_PARAM with PARAM_STRING
+    snmpstats Add transport indications to the mib
+    
+    This commit adds support for the config framework to the snmpstats module.
 
-commit 192e1cbc56e621535cf370b48259a82646b31b19
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Mon Jul 28 03:22:50 2014 -0700
+commit 7bc2efb300dcce267984cd3804349295ec8d2ed5
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Wed Apr 3 20:01:35 2013 +0200
 
-    mohqueue: replace STR_PARAM with PARAM_STR and some indention fixes
+    core Make sure Kamailio doesn't crash if TCP is disabled and RPC core.tcp_list RPC command is issued
 
-commit 9ac2fe9f7f371e39e03002daf0dc7d35a517cedc
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Mon Jul 28 03:09:26 2014 -0700
+commit d7959e5e63130889b6b589096388eaa6b76216d1
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Wed Apr 3 09:22:49 2013 +0200
 
-    app_python: replace STR_PARAM with PARAM_STR
+    kex Update README XML with section id's
 
-commit 584f4ea62760c31395773a742e43fccdb4d5b67c
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Mon Jul 28 03:05:10 2014 -0700
+commit 3814b0ef258fb904aa3571058a9e76dc990bd252
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Wed Apr 3 09:14:41 2013 +0200
 
-    pua_dialoginfo: replace STR_PARAM with PARAM_STRING
+    tls Reformat section IDs
 
-commit ca3da467f59dbaed2d20aa45314ac12a362e2deb
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Jul 30 15:58:27 2014 +0200
+commit 6a9048a14bae1fd9a66239533a9af23ad390ab20
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed Apr 3 16:18:14 2013 +0100
 
-    dialog: if ACK for 200ok is not coming in 60sec, dialog lifetime is shortened for 10 more sec
+    modules/tm: Fix t_next_contact_flow return value
     
-    - should handle the situation when caller cancels the call but the
-      callee answered before getting the cancel
-    - reported by Alex Balashov
+    - Return 1 if a new flow was found
+    - Return -1 if not found
 
-commit fcdf5f9cfff634ebfa736d7084d5e5483a36355b
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Jul 30 15:27:09 2014 +0200
+commit 4ae14b095cb0a24f743a6c90db2f273dcfb163aa
+Author: Carsten Bock <carsten at ng-voice.com>
+Date:   Wed Apr 3 16:57:44 2013 +0200
 
-    dialog: documentation for timer_procs parameter
+    b/f: Initialize rtpp_set_list properly (set it to 0), this can otherwise cause errors.
 
-commit 1157db7c72b1629b72f4d06bd01c5bc694a816b2
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Jul 30 15:15:40 2014 +0200
+commit 6759d6bbdd5ff918759789bde00b8e74235b4051
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed Apr 3 15:55:47 2013 +0100
 
-    dialog: option to run dialog main timer tasks via dedicated process
+    modules/tmx: Add $T_reply_ruid pv to return ruid for a branch reply
     
-    - timer_procs - new parameter, if set to 1, a dedicated timer process is
-      used, if set to 0 (default), the core timer is used (existing
-      behavior)
-    - to add: option to work with many dedicated timer processes
+    - Can be run from a failure_route or branch_failure_route
 
-commit d1c97010ed8d3c7a19580c20b8cd81c6a485eadf
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Jul 30 15:03:45 2014 +0200
+commit ef9115b65fc21f8d64687b2787a50aa025d188c7
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed Apr 3 15:18:22 2013 +0100
 
-    core: fork_sync_timer() uses milisecond precision to catch up on delayed execution
+    modules/tm: Make ruid available in uac structure
     
-    - previously was using a step of a second
+    - ruid is stored per uac
+    - ruid can be retrieved when a response to the branch is received
 
-commit 295716363562d88bce3db39e0f1bc605b1cc8257
-Author: Pawel.Kuzak <pawel.kuzak at 1und1.de>
-Date:   Wed Jul 30 13:59:49 2014 +0300
+commit 4cdd9f7502a11bc48d0413811606444b24b984e2
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed Apr 3 15:06:35 2013 +0100
 
-    acc: fix cdr extra2strar allocation issues
+    modules/registrar: Allow unregister for ruids in branch_failure_route
     
-    - for more than 10 string cdr_extra parameters, the addresses used
-      by the new parameters overwrite the previous ones; our solution is
-      to allocate memory for the cdr extra params with pkg_malloc() and
-      free it once it is no longer needed.
+    - unregister(domain, uri, ruid) is accepted in branch_failure_route
+    - unregister(domain) is not.
 
-commit c5afbe15361bbf7e9493ad02dcabfd4c6d420109
-Author: Hugh Waite <hugh.waite at acision.com>
-Date:   Sat Jul 26 01:18:50 2014 +0100
+commit 445e23e221d54e105f256e54c06c6e5a28ba848c
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed Apr 3 15:04:38 2013 +0100
 
-    tm: Generate synonym_id based on original request
+    modules/usrloc: Fix get_urecord_by_ruid to return static aor
     
-    - Prevent allocating pkg memory in a shm-alloc'd copy
-    - Prevents a crash that can occur in requests with pre-3261 branch tags
+    - Fixed a bug which returned a pointer to a stack variable
+    - Fixed some potential (?) infinite loops
 
-commit c1b51e38f0904217b0a07b8b9aedc51519fe250e
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Jul 28 14:24:21 2014 +0200
+commit befb822c7548c063c9643e8e6b27b1a6e9ff1631
+Author: Carsten Bock <carsten at ng-voice.com>
+Date:   Wed Apr 3 12:55:01 2013 +0200
 
-    pv: new variables - $expires(min) and $expires(max)
-    
-    - return the min and max of expires value for sip message
-    - contact headers are checked with higher priority, if no expires
-      parameter there, then Expires header is used
-    - if none is found, $null is returned
+    b/f: an error would be nice, if the module fails to load ;-)
 
-commit c445e0c299a21cb268101c716147d53f1d897dcf
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Jul 28 09:32:03 2014 +0200
+commit 3b76b3bb674420ffcee1cb400ee812bf9e7db418
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Tue Apr 2 20:35:44 2013 +0200
 
-    ims_registrar_scscf: fixed compile error of removed vars by moving to PARAM_STR
-    
-    - reported by Victor Seva
+    utils Add section ID's to README xml
 
-commit 90093f8633b807a2067c8e0500533ba3ad590a89
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Sat Jul 26 10:05:18 2014 +0200
+commit 43d59fe1093e7319848794a7c266d3605f764d1a
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Tue Apr 2 20:31:07 2013 +0200
 
-    pkg/kamailio/deb: Update version to 4.2.0~dev8
+    db_cluster Add section IDs to XML file and update some text
 
-commit bf727eeceb85ad06472274906f2b8d40b1b2610a
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Jul 25 23:26:18 2014 +0200
+commit 68a8ef2ed9e616f563a28d87d591f5deebd23085
+Author: Jason Penton <jason.penton at smilecoms.com>
+Date:   Tue Apr 2 20:29:50 2013 +0200
 
-    Makefile.defs: version set to 4.2.0-dev8
+    modules/dialog_ng: fixed bad append bug and added null sentinel
+    	- thanks Hugh
 
-commit fc383b13c32d4f89fbb8a7de14a07cbb26f38693
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Jul 25 23:16:31 2014 +0200
+commit f0f31127878ecde2dac854598030f0d7d5374f18
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Tue Apr 2 20:08:43 2013 +0200
 
-    sms: domain is not allocated in pkg by the module
-    
-    - skip freeing in mod destroy
+    acc Update documentation with section IDs
 
-commit 1556fa1137db9a9281987bd50aef25fe12ccec8f
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Wed Jul 23 08:25:37 2014 -0700
+commit 70c5705a6cfd9ba8fc8f5519145eb5d4b13770da
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Tue Apr 2 19:26:35 2013 +0200
 
-    rtpproxy: replace STR_PARAM with PARAM_STRING
+    db_mysql Correct e-mail address that had a typo.
 
-commit 448202fde68948d39222004b8fdfaa4c515026ae
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Wed Jul 23 08:21:33 2014 -0700
+commit 9e7f627c5e9a4c34193e4662fbe341b70fa308bf
+Author: Jason Penton <jason.penton at smilecoms.com>
+Date:   Tue Apr 2 19:44:46 2013 +0200
 
-    rtpengine: replace STR_PARAM with PARAM_STRING
+    modules/dialog_ng: bug fix for concurrent dialog did generation
+    	- spotted by Camille @ Orange - tks!
 
-commit 003302140615d679cb05908bb7adaab4298b69e2
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Wed Jul 23 08:16:37 2014 -0700
+commit b961a960581394913dc79240fe983723a57e5b26
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Tue Apr 2 13:23:27 2013 +0100
 
-    sms: replace STR_PARAM with PARAM_STRING
+    modules/stun: fixed typo
 
-commit ea98475aec73bdf508c497e781c2bc56fd7646e4
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Wed Jul 23 08:11:24 2014 -0700
+commit fe977dfcb940b1c48dd26fe5fe61a25aed23b96a
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Tue Apr 2 14:13:01 2013 +0200
 
-    speeddial: replace STR_PARAM with PARAM_STRING
+    db_mysql Add transaction support
+    
+    Patch contributed via Google+ by Håkon Nassjöen <haakon.nassjoen at gmail.com>
 
-commit 3b9ebea72590ffbbad0f0fb2318fe40180bf8b94
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Wed Jul 23 08:08:23 2014 -0700
+commit e9267d7e6a0c6a1715f70916a6879f4288f14a57
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Tue Apr 2 11:09:27 2013 +0200
 
-    msilo: replace STR_PARAM with PARAM_STRING
+    cfgutils Adding ID's to xml sections for alfabetic indexes
 
-commit d4e5e4b185ba1deffba80d451bf37e906189b528
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Wed Jul 23 08:01:39 2014 -0700
+commit 399ab478349f320a44180abbb1546c93981b566a
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Mon Apr 1 22:40:21 2013 +0200
 
-    permissions: replace STR_PARAM with PARAM_STRING
+    app_lua: readme regenerated to be in sync with xml docbook file
 
-commit c3951098b50cd002bdcc72b1600f4bdc9f7c1788
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Wed Jul 23 07:57:55 2014 -0700
+commit 1262b4401954661028e10bfb3b54d0ed00876711
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Mon Apr 1 20:41:48 2013 +0200
 
-    osp: replace STR_PARAM with PARAM_STRING
+    snmpstats add entry for outbound module
 
-commit e45b14a41fb7d14247b809b50ee9a1044ee8f63b
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Wed Jul 23 07:51:23 2014 -0700
+commit 7d272f893c3e0f260db1af5fc07dccd7d93690df
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Mon Apr 1 10:06:33 2013 +0200
 
-    mtree: replace STR_PARAM with PARAM_STRING
+    snmpstats Documentation updates
 
-commit ee6d8aecd63f4ede0d99837eb726a8ace1281a20
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Wed Jul 23 07:47:16 2014 -0700
+commit 5397c6c4d9a9b3f50561893855d7469cfbf58858
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Mon Apr 1 09:12:01 2013 +0200
 
-    mi_xmlrpc: replace STR_PARAM with PARAM_STRING
+    outbound add config framework variable to indicate active module
 
-commit 2044937e95e4c7e42a2165b939a655f2de300d06
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Wed Jul 23 07:45:59 2014 -0700
+commit 709acbb709c43d1b9d391bebf8a99b3bfe3c3e28
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Sat Mar 30 19:01:52 2013 +0100
 
-    acc_radius: replace STR_PARAM with PARAM_STRING
+    cfg.h - config framework - doxygenify documentation
 
-commit ea76a64b3ec439271008503697de45766a9084db
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Wed Jul 23 07:43:02 2014 -0700
+commit 2df6f560bcc54d2966732d397713a9cf3233d5fe
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Sun Mar 31 21:49:10 2013 +0200
 
-    presence_xml: replace STR_PARAM with PARAM_STRING
+    dialog: SDP can be passed to MI/RPC dlg_bridge
+    
+    - rework from a patch of Patrick E.
 
-commit 0ce7ce2adac5a26f1cf9b523211e7bb762da4b84
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Wed Jul 23 07:41:09 2014 -0700
+commit aa6154afcf3e2d59ad09659d7e60bf3691f1d2e3
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Sat Mar 30 22:31:31 2013 +0100
 
-    dmq: replace STR_PARAM with PARAM_STRING
+    doc/rpc_list: updated the docs with lists of rpc commands
 
-commit a8cf14df1aef16c21c813892aa63c7deec7cee1e
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Wed Jul 23 07:26:07 2014 -0700
+commit 11bc294a9d64e31014ccb836290467984c28ce65
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Sat Mar 30 20:59:24 2013 +0100
 
-    pdt: replace STR_PARAM with PARAM_STRING
+    dialog_ng: set kamailio mod interface always
+    
+    - it breaks rpc list generation otherwise
 
-commit 4faa262958dc5edbca617794b53ff82a89cfaa30
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 22 08:54:27 2014 -0700
+commit 688f2902977ee52d0c3d89a1f6459ca0d8c624f9
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Sat Mar 30 20:28:03 2013 +0000
 
-    drouting: replace STR_PARAM with PARAM_STRING
+    modules/websocket: moved some configuration across to the cfg framework
+    
+    - As suggested by @oej
 
-commit 827d20c2cc6c277b8e59d3c9268c7aa01cf0f996
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 22 08:48:46 2014 -0700
+commit 21fa34f61ba4d9778e6b79d978818b47d0928639
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Sat Mar 30 12:21:02 2013 +0000
 
-    sqlops: replace STR_PARAM with PARAM_STRING
+    modules/websocket: added lots more SIP/MSRP specific statistics
+    
+    - also updated output of dump MI command to include sub-protocol information
 
-commit 7922d0bfe88884b7c2296e71f9013b9a40b457d9
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 22 08:47:55 2014 -0700
+commit 63b50d3b0e3a2250effd9a1aa92b7776854364a6
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Sat Mar 30 11:36:41 2013 +0000
 
-    ratelimit: replace STR_PARAM with PARAM_STRING
+    modules/websocket: added some sub-protocol related statistics
 
-commit 856df3f6bcc8206210c71eb73e3e963ab9296e13
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 22 08:45:30 2014 -0700
+commit f88dd6d7197af1e4bf5a9e24cdf9ac8975ae2345
+Author: Marius Zbihlei <mariuszbi at gmai.com>
+Date:   Sat Mar 30 11:19:24 2013 +0000
 
-    debugger: replace STR_PARAM with PARAM_STRING
+    modules/dnssec Added copyright notices
+    
+    Also forgot a memset..
 
-commit 62bac5f85662ad42e58f5fb15dd339458af89d30
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 22 08:43:25 2014 -0700
+commit 75ade496d319ac16df0b00ca578c1cc9b866010a
+Author: Marius Zbihlei <mariuszbi at gmai.com>
+Date:   Sat Mar 30 10:56:18 2013 +0000
 
-    seas: replace STR_PARAM with PARAM_STRING
+    modules/dnssec New dnssec resolver module based on libval
+    
+    To use, simply load the module
+    It will overide the system resolvers (i.e. gethostbyname, res_search) with libval's provided wrappers that support
+    DNSSEC.
+    Further functionality will be added.
 
-commit e3239f6fb684ef9bac811c5afc0ca4858a20a64c
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 22 08:39:33 2014 -0700
+commit 243da7b8a96db33090fd6e2e5d84f4dcd47652b5
+Author: Jon Bonilla <jbonilla at sipwise.com>
+Date:   Sat Mar 30 11:46:00 2013 +0100
 
-    registrar: replace STR_PARAM with PARAM_STRING
+    Set lucid version to 4.0.0
 
-commit db70d08c7b5731985026ad6389c5f5de802712d9
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 22 08:08:00 2014 -0700
+commit 0d279eb512ac6740fe1da6e96f7580303f09c025
+Author: Marius Zbihlei <mariuszbi at gmai.com>
+Date:   Sat Mar 30 10:44:39 2013 +0000
 
-    pipelimit: replace STR_PARAM with PARAM_STRING
+    core: refactored DNS primitives and removed DNSSEC support from core
+    
+    The library functions can now be easily overwritten by modules(dnssec) to allow enhanced resolving capabilities
 
-commit 68875ad3b1c29380ebe13738531e3bf337a66241
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 22 08:01:47 2014 -0700
+commit f139948421f2232efae6c2bdd6ea95547b6de533
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Sat Mar 30 09:49:16 2013 +0100
 
-    dialog_ng: replace STR_PARAM with PARAM_STRING
+    snmpstats Add support for the Websocket module statistics
+    
+    Hint to developers: If you add statistics and selects in your module, you
+    make it very easy to add SNMP support for your module. Then SNMPstats
+    can just use generic APIs to find your data. Please also add a generic
+    way of finding out if a module is configured and used too, if possible.
+    Sometimes modules are just loaded, but not used anywhere. Better to
+    reflect real data in SNMP if possible.
+    
+    Using the old "SER" way of using selects for config data that
+    is allowed to change at runtime opens up for SNMP writes to manage
+    your module as well.
+    
+    And of course, using selects and counters/statistics variables also
+    helps the RPC interface, so it's both cool and the Right Thing To Do (TM).
+    
+    Yes, commit messages can be informative as well. :-)
 
-commit 397364edd99d0e34f23f04c877b6d8515337560e
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 22 07:52:14 2014 -0700
+commit b9476db0c1e1ce869c1da2f87dfaf411edf69277
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Sat Mar 30 09:24:19 2013 +0100
 
-    dispatcher: replace STR_PARAM with PARAM_STRING
+    core: set TOS for tcp IPv6 sockets
 
-commit 2f9070e6f5fa3041fda4fda9adf5aee791d641a1
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 22 06:29:10 2014 -0700
+commit b57f64533dbc538f3d5282d0196598062f0b4652
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Sat Mar 30 09:15:00 2013 +0100
 
-    rtpproxy: replace STR_PARAM with PARAM_STRING
+    core: set TOS for IPv6 sctp sockets
 
-commit 4a9c0493477933ef04ef35d626022538248ed7cb
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 22 06:11:25 2014 -0700
+commit 222066ba16ec4b2064c4fc50e533e27f4c4fb74d
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Fri Mar 29 12:19:36 2013 +0100
 
-    presence: replace STR_PARAM with PARAM_STRING
+    app_lua: clean local reload array and shut down
 
-commit c135633f4bc1a40d29f3cfcd803c1bbad0349bf6
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 22 05:46:20 2014 -0700
+commit e2bd2192b5ddc33d0e8fd486467842d9cceda131
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Sat Mar 30 09:10:02 2013 +0100
 
-    xlog: replace STR_PARAM with PARAM_STRING
+    stun	Add clarification to the README
+    
+    And a big thank you to Peter Dunkley and Crocodile RCS for doing the
+    work involved in making this a module, instead of a compile time
+    options. Modules are cool. And easier to handle by pre-compiled
+    distributions/packages.
 
-commit a26ca629c3397555c45f7977547025c7b6e13cf6
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 22 05:43:06 2014 -0700
+commit ce0c420ba30388256e958a0bdf6d8f37138c3f97
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Fri Mar 29 23:35:39 2013 +0000
 
-    p_usrloc: replace STR_PARAM with PARAM_STR
+    modules/outbound: changed some INFO level output to DBG
 
-commit c10fcd407d04dc3f1633d925a96accee2b0b588c
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 22 05:31:18 2014 -0700
+commit bce42abfd19f5beb26fc27ab77fed5f679a378ee
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Fri Mar 29 23:31:54 2013 +0000
 
-    siptrace: replace STR_PARAM with PARAM_STR
+    modules/rr: fixed outbound related segmentation fault
 
-commit 65b0fbaa0f8c798da6b4bc04c2eb83eb1cf103b2
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 22 05:16:49 2014 -0700
+commit 7dfdcfed55916cce7541d28251cb4c82a0823829
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Fri Mar 29 23:31:39 2013 +0000
 
-    lcr: replace STR_PARAM with PARAM_STR
+    modules/outbound: fixed segmentation fault
 
-commit 83de3e6a130f6cf3cceb36067848d35175dc2e2a
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 22 05:07:43 2014 -0700
+commit 56be9d6100c22333a14f18f0a506bd8652240e9d
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Fri Mar 29 23:12:58 2013 +0000
 
-    sipcapture: replace STR_PARAM with PARAM_STR
+    core: added structure to hold cached decoded flow-token to sip_msg structure
 
-commit e04aff80be9db7ffeb83e62ae78f5a972a12bd8a
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 22 04:57:20 2014 -0700
+commit dc1e11b5d03ec033ba7fee421f57d56fa223fddb
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Fri Mar 29 23:12:18 2013 +0000
 
-    rls: replace STR_PARAM with PARAM_STR
+    modules/rr: updated because outbound:decode_flow_token() arguments changed
 
-commit 282ff5dd198a4f35853f51f5e9678b044f27f900
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 22 04:46:49 2014 -0700
+commit 2bff7566a0506ea06ab2de735db30af3e4c9c110
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Fri Mar 29 23:11:24 2013 +0000
 
-    alias_db: replace STR_PARAM with PARAM_STR
+    modules/outbound: cache decoded flow-token in sip_msg structure
+    
+    - Saves multiple OpenSSL calls if the same flow-token is needed in more
+      than one place
 
-commit 38210774b65ea40ce35e96d713c544529dad9a9e
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 22 04:44:47 2014 -0700
+commit 030d591a1e80b32d88b606bf0bc0d8ed80ad3b31
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Fri Mar 29 22:32:13 2013 +0000
 
-    app_lua: replace STR_PARAM with PARAM_STR
+    modules/outbound: updated edge proxy example to use STUN module
 
-commit ef3def8cba78d2a58ab89a93424665986f886655
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 22 04:43:45 2014 -0700
+commit 2857eb4b2de20c18ac31212c5336092f08184309
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Fri Mar 29 22:28:00 2013 +0000
 
-    ims_registrar_scscf: replace STR_PARAM with PARAM_STR
+    modules/stun: removed unnecessary include
 
-commit 66dec49579804c72c82b53108e68cd052e7bdbe2
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 22 03:14:04 2014 -0700
+commit c264ea399e17a87a59282b654bdbdebea2841e34
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Fri Mar 29 21:49:56 2013 +0000
 
-    topoh: replace STR_PARAM with PARAM_STR
+    pkg/kamailio/(centos|fedora): Updated .spec to build new stun module
+    
+    - Also updated rel to dev1
 
-commit 740c3f5a63ad62e9506486b9288474549d1b57d9
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 22 03:01:36 2014 -0700
+commit e090a714728950b40cf09956137db4ce93d08960
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Fri Mar 29 21:49:29 2013 +0000
 
-    diversion: replace STR_PARAM with PARAM_STR
+    modules/outbound: updated to reflect STUN being in a module now
 
-commit e9ed544ff0a0f421881e4990615fddd9d21ee437
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 22 02:58:20 2014 -0700
+commit c22230bddf3aeebdae9062d3c5c4c37ce59f8a96
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Fri Mar 29 21:49:07 2013 +0000
 
-    utils: replace STR_PARAM with PARAM_STR
+    core: Updated modules list in Makefile.groups to include stun
 
-commit 9dc4aa338c83270c15603497f5624281710e443a
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 22 01:49:06 2014 -0700
+commit c573aa70bba657ba58202c4125d354439478adb2
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Fri Mar 29 21:47:57 2013 +0000
 
-    ldap: replace STR_PARAM with PARAM_STR
+    core: removed STUN from core
+    
+    - Added hooks so that STUN messages can be passed to a module
+    - Removed STUN configuration file parameters
 
-commit 06baf447abcdf46466e76a97bd0797abc49bdaa5
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 22 01:46:08 2014 -0700
+commit 55510ba22e248ea774e7c04b0132c9c5af858d15
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Fri Mar 29 21:46:20 2013 +0000
 
-    rr: replace STR_PARAM with PARAM_STR
+    core: removed ser_stun.[ch] from core
+    
+    - STUN now in a module
 
-commit 11e6c3a8b770530195881ef2820634fa0bed7324
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 22 01:24:37 2014 -0700
+commit 02718defd1785fe5b94255077a9945354ee6cc19
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Fri Mar 29 21:45:45 2013 +0000
 
-    enum: replace STR_PARAM with PARAM_STR
+    modules/stun: Module documentation for STUN
 
-commit 86aee26f72a900199b9a8a933d971a7af0f64160
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Tue Jul 22 01:17:30 2014 -0700
+commit 4afa7a1f9dfc61679db11a5e76e3d3de10be1391
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Fri Mar 29 21:44:48 2013 +0000
 
-    siputils: replace STR_PARAM with PARAM_STR
-
-commit 93a5ece8d28126236aec6363d362dc60277ec163
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Mon Jul 21 08:32:33 2014 -0700
-
-    usrloc: replace STR_PARAM with PARAM_STR
+    modules/stun: STUN module
+    
+    - Based on ser_stun.[ch]
+    - No longer a compile time option in Kamailio core
 
-commit ca7e87a799822d68307e07ab7f978a4144a3e3a6
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Mon Jul 21 08:27:13 2014 -0700
+commit 84ad1a93976a0f8251ab0d86319d91d48a3a4d91
+Merge: 45b4d0b 33108f4
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Fri Mar 29 14:55:58 2013 +0000
 
-    memcached: replace STR_PARAM with PARAM_STRING
+    Merge branch 'master' of ssh://git.sip-router.org/sip-router
+    
+    * 'master' of ssh://git.sip-router.org/sip-router:
+      modules/registrar: changed instance related INFO to DBG
 
-commit bbf2d0399819ab50ac825f1153238dd6ca4bb045
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Mon Jul 21 08:24:19 2014 -0700
+commit 45b4d0b480ca0c0c02327bcbd925865a7571fcf5
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Fri Mar 29 14:54:52 2013 +0000
 
-    domainpolicy: replace STR_PARAM with PARAM_STR
+    lib/srdb1, kamctl: Add new rtpproxy db table to schema
 
-commit 109c2270efce2c77f36d965e18974cb1e07fa98e
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Mon Jul 21 08:21:42 2014 -0700
+commit 33108f4843fdef6d45773849089446b0c408ecf3
+Author: Juha Heinanen <jh at tutpro.com>
+Date:   Fri Mar 29 16:30:51 2013 +0200
 
-    prefix_route: replace STR_PARAM with PARAM_STRING
+    modules/registrar: changed instance related INFO to DBG
 
-commit 08299a9c5fae5e8eaa6a896c2e62578580fb3ca7
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Mon Jul 21 08:19:31 2014 -0700
+commit 9a0e58667f705197b8e5291b54909fd370b2b7ab
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Fri Mar 29 14:07:59 2013 +0000
 
-    pv: replace STR_PARAM with PARAM_STRING
+    modules/rtpproxy: Add database support to rtpproxy
+    
+    - If db_url modparam is set rtpproxy sets will be loaded from database
+    - If the instance is marked as disabled in database it will be loaded as disabled
+    
+    - Currently no persistence (enable/disable MI command does not affect DB)
+    - Loaded during mod_init - cannot be reloaded at runtime (as before)
 
-commit 139f0566bb8201c9925d53ffcdaa3db97bd2551e
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Mon Jul 21 08:09:32 2014 -0700
+commit f9a7a9476f3d925fbfbde706ff7690423e96e7c8
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Fri Mar 29 12:05:17 2013 +0100
 
-    xcap_server: replace STR_PARAM with PARAM_STR
+    app_lua: moved local array for reload as global variable
+    
+    - avoid runtime allocation/free for each execution when reload is
+      enabled
+    - renamed sr_reload to _app_lua_sr_reload for better namespacing
+      conflict resolution
 
-commit c3f03b75c2cc4e18c1e4b7f02db9eff5eae8cca5
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Mon Jul 21 07:58:33 2014 -0700
+commit c9082cb51b204d5001b0bb819d72669fdcdf3d98
+Author: Victor Seva <linuxmaniac at torreviejawireless.org>
+Date:   Fri Mar 29 10:21:42 2013 +0100
 
-    statistics: replace STR_PARAM with PARAM_STRING
+    modules/app_lua: Fix not C standard initialization
 
-commit 15cdee0778cf448f1f20e5cae40a6ea00d8d3d32
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Mon Jul 21 07:57:38 2014 -0700
+commit 9d908f1d24df8c1644c3fbed3d99f5011106cae6
+Author: Victor Seva <linuxmaniac at torreviejawireless.org>
+Date:   Thu Mar 28 10:18:10 2013 +0100
 
-    ims_isc: replace STR_PARAM with PARAM_STR
+    modules/app_lua: Added reload parameter to deactivate the reload check
 
-commit 0ce3ac8049d3f5207332bdff8711d82468bab7ae
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Mon Jul 21 07:53:09 2014 -0700
+commit db397f15b9d2faacda9a8175398e1df524fd1875
+Author: Víctor <linuxmaniac at torreviejawireless.org>
+Date:   Wed Mar 27 21:30:40 2013 +0100
 
-    auth_diameter: replace STR_PARAM with PARAM_STRING
+    modules/app_lua: add app_lua.list and app_lua.reload rpc commands
 
-commit 31c1415eb7b3937a5716a8e008238e5b194c8cfc
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Fri Jul 18 08:12:26 2014 -0700
+commit 50b116cf4c9c33c4f23c1d5b66fd313a7f40c572
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Fri Mar 29 11:02:31 2013 +0100
 
-    dialog: Replacing STR_PARAM with PARAM_STRING or PARAM_STR to give up of depracated defines
+    usrloc: use NULL domain for updating ul attributes for use_domain=0
+    
+    - use counter var for db matching keys
 
-commit d33033563558fd7937449ba43446e8465491e6d4
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Fri Jul 18 07:58:25 2014 -0700
+commit afc8b3e7ae13198c7bca42f7f7fc5499418cfa59
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Fri Mar 29 09:25:09 2013 +0100
 
-    ims_usrloc_pcscf: Replacing STR_PARAM with PARAM_STRING or PARAM_STR to give up of depracated defines
+    Makefile.defs: version set to 4.1.0-dev2
 
-commit 081f2fbc638a05b746710c04800e8e6476665469
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Fri Jul 18 07:55:24 2014 -0700
+commit c77ec4ed4cc756373b0f20885d4f04d2276c00c1
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Fri Mar 29 09:23:43 2013 +0100
 
-    htable: Replacing STR_PARAM with PARAM_STRING or PARAM_STR to give up of depracated defines
+    Makefile: pure target associated to maintainer-clean
 
-commit 6864c39077dc7cbb98ec696dde6cd1ce34cc61d8
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Fri Jul 18 07:50:01 2014 -0700
+commit c26d6bb13fb699ec2cb9e916d8a562d3ee4c8f0d
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Fri Mar 29 09:38:29 2013 +0100
 
-    ims_usrloc_scscf: Replacing STR_PARAM with PARAM_STRING or PARAM_STR to give up of depracated defines
+    snmpstats Adding more memory data variables
+    
+    Also, remove dependency of the kex module by interfacing directly
+    with the core the same way as the kex module does get memory information.
 
-commit 3ef1b5f481b2bb1437fec86a557cb2ac8e467701
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Fri Jul 18 07:23:19 2014 -0700
+commit 60953cd884af7d070ce44844a874f2bd75833998
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Fri Mar 29 01:08:02 2013 +0000
 
-    auth_radius: Replacing STR_PARAM with PARAM_STRING to give up of depracated defines
+    modules/outbound: updated edge proxy example in README
 
-commit 0e2c3d192fcfa65a7535814671118e8e0a4b0f46
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Fri Jul 18 07:18:13 2014 -0700
+commit f6b72765da5cf12f8dc1e4157a3e526d5d0aa956
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Thu Mar 28 22:50:59 2013 +0100
 
-    ims_icscf: Replacing STR_PARAM with PARAM_STRING or PARAM_STR to give up of depracated defines
+    snmpstats Adding another list of TCP settings
+    
+    Just a few more to go, then TLS
 
-commit 5d04fc5a2eef90da801d47b146964a931100b7c2
-Author: Alekzander Spiridonov <sipidronov at gmail.com>
-Date:   Fri Jul 18 07:01:02 2014 -0700
+commit 57bb2450a5b0db4c18dd139ae3ae28f480b379c7
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Thu Mar 28 21:30:57 2013 +0100
 
-    acc: Replacing STR_PARAM with PARAM_STRING to give up of depracated defines
+    snmpstats Add a few more TCP connection settings
 
-commit b61ac1ca1cc410915e61c122350b8af3e4690a93
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Jul 25 18:08:41 2014 +0200
+commit 464ce5d71d738f706f0d4a26573444809496068e
+Merge: 1d8597f 084be45
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Thu Mar 28 10:00:05 2013 +0000
+
+    Merge branch 'master' into hpw/branch_failure_route
+    
+    * master: (33 commits)
+      core: set TOS for IPv6 UDP sockets
+      rtpproxy: add missing wrapper function for unforce_rtp_proxy
+      modules/outbound: further improvement to the use_outbound() check
+      rtpproxy: support pvars in function parameters
+      modules/rr: copy the flow-token for "incoming" messages when using outbound
+      modules/outbound: improved check for outbound
+      modules/rr: only use flow-token for routing if it doesn't point to the source of the request
+      pkg/kamailio/(centos|fedora): Updated .spec after addition of cnxcc module
+      Makefile.groups: cnxcc module added to extra list
+      core: auto-define cfg directive MOD_modname for each loaded module
+      snmpstats Add tcpasync and tcpmaxconns
+      snmpstats Add IDs to sections in documentation
+      cnxcc: added new module for credit control
+      snmpstats activate new parts of the KAMAILIO-MIB
+      snmpstats Add information about version and tcp connections
+      usrloc: new option for db_mode - DB_READONLY (4)
+      enum: define the max size for numbers
+      db_mysql: new module parameter - insert_delayed
+      Makefile: exclude debian sym link when generating tarball
+      msrp: fix compile warning of argument type in dbg message
+      ...
+
+commit 1d8597f99b43154c1a078ade47984e6faf9f149c
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Thu Mar 28 09:48:04 2013 +0000
 
-    uac: documentation for rpc command uac.reg_refresh
+    modules/tm: Fix setting instance in uac branches
 
-commit 09ced05fc90602675366ccfc041bbb7278cd3b59
+commit 084be456bc0fab015cf9964ac85651fa60ea77c9
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Jul 25 18:03:03 2014 +0200
+Date:   Wed Mar 27 20:53:00 2013 +0100
 
-    uac: new rpc command uac.reg_refresh
+    core: set TOS for IPv6 UDP sockets
     
-    - load a record from database based on l_uuid. If record is already in
-      memory, then the password field is updated, otherwise a new full
-      record is added in memory
+    - reported by Klaus Feichtinger, FS#179
 
-commit ce7aee6e59d2b4980625f9c4dfef171048341319
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Jul 25 17:17:22 2014 +0200
+commit 9e6af79d0cf1b0e10694880147a28966313fb5a4
+Author: Richard Fuchs <rfuchs at sipwise.com>
+Date:   Wed Mar 27 13:30:05 2013 -0400
 
-    tmx: documented reason code parameter for t_cancel_callid()
+    rtpproxy: add missing wrapper function for unforce_rtp_proxy
 
-commit 08f8911c8ddb527544c2ea603b5e0db7626d3196
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Jul 25 17:11:37 2014 +0200
+commit a5f8f4cd4da60168fd73d7999c09181582ec5943
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Wed Mar 27 16:51:52 2013 +0000
 
-    tmx: t_cancel_callid() can take a 4th parameter with reason header code for cancel
+    modules/outbound: further improvement to the use_outbound() check
 
-commit 213ad230a87638bbd0f1591c8b7cefdd4e6b1fd3
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Jul 25 14:43:45 2014 +0200
+commit cd3358dd935781489e2b7122fe20a19310f97546
+Author: Richard Fuchs <rfuchs at sipwise.com>
+Date:   Wed Mar 27 12:46:28 2013 -0400
 
-    htable: debug message to show initialization of hash table structures
+    rtpproxy: support pvars in function parameters
 
-commit 4b335f6419468d6873ce314221b2b786ae64366a
-Author: Pawel Kuzak <pawel.kuzak at 1und1.de>
-Date:   Fri Jul 25 14:28:48 2014 +0300
+commit 0c1725c8ccb08280a9c161e34fa9e43347cae7b0
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Wed Mar 27 16:33:17 2013 +0000
 
-    userblacklist: added check_whitelist function
-    
-    - check_whitelist(string table) finds the longest prefix that
-      matches the request URI for the given table and returns true
-      if the match is set to whitelist
+    modules/rr: copy the flow-token for "incoming" messages when using outbound
 
-commit adae5dc02c0c1f0537546ec0a855d40e8a75ff10
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Jul 25 13:30:46 2014 +0200
+commit b2fb355fe5c9c64727d873cbe8d6fd883ebd2537
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Wed Mar 27 16:32:59 2013 +0000
 
-    nosip: fixed compile warnings related to unused variables
+    modules/outbound: improved check for outbound
 
-commit 0ae40714ef85da45863b5af8409856787501b4c2
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Jul 25 13:29:22 2014 +0200
+commit 874669f483e1efba032bd695eb6cee4275673874
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Wed Mar 27 15:43:02 2013 +0000
 
-    nosip: removed unused function prototype
+    modules/rr: only use flow-token for routing if it doesn't point to the source of the request
 
-commit 8bde82a2b85d22caf6d0cc36be2a1736ff1aad21
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Jul 25 13:00:16 2014 +0200
+commit 2f85ac8828b2d336069c618ef4d209d61809c19f
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed Mar 27 14:36:59 2013 +0000
 
-    tm: check the length of uri param for t_replicate
+    modules/tm: Enable retrieving of branch instance id from uac structure
     
-    - if emtpty string is given, then parameter is ignored and address of
-      next hop is taken from r-uri or dst-uri
+    - Add instance to uac structure and populate when uac created
+    - Add get_this_branch_instance function to retrieve instance in a branch failure route
 
-commit bb1a5ba30b3d6ba98696844899a61b7df3bc0cc4
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Jul 25 12:41:52 2014 +0200
+commit 5d1a3b87fde83455f63075d8fdf39b7b99d4053c
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed Mar 27 14:25:32 2013 +0000
 
-    auth_db: proper condition for caller id skip check flag
+    modules/xprint: Updated to use the new get_branch()/next_branch() functions
 
-commit b96c2d43c686f64b1fd54c7fc9ba01f8a1a2ad37
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Jul 25 12:29:50 2014 +0200
+commit 800d56979226ad80e045fb316e19fb3b77ce7f57
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Wed Mar 27 13:59:44 2013 +0000
 
-    auth_db: note about the new flag to skip caller id check for auth_check()
+    pkg/kamailio/(centos|fedora): Updated .spec after addition of cnxcc module
 
-commit 8c98ff6472adf4a1aad986913de86bf3c262810f
+commit 94272bdb6ce2a15ba2e165eef59561c2d2992a5f
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Jul 25 12:25:23 2014 +0200
+Date:   Wed Mar 27 13:39:28 2013 +0100
 
-    auth_db: new flag for auth_check() to skip caller id check for forwarding requests
-    
-    - caller id check is skipped for INVITE, BYE, PRACK, UPDATE, MESSAGE --
-      these requests can come with an anonymous caller id
+    Makefile.groups: cnxcc module added to extra list
 
-commit 1be7c3ebc9b29046c023290ad580bb83c3e6e44d
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Jul 25 12:01:37 2014 +0200
+commit a1e0c05e953140b026325117c3d8ace5a2ccf900
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed Mar 27 11:53:18 2013 +0000
 
-    tm: docs - added note about t_replicate() without params
+    modules/pv: Updated to use the new get_branch()/next_branch() functions
+    
+    - New instance parameter is currently not used
 
-commit c5b6b6021e75cd4e73f54f9131524b588709950c
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Jul 25 11:58:50 2014 +0200
+commit 691ebf0178aa25b5ef19eb6a220d335be3900a3b
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed Mar 27 11:52:15 2013 +0000
 
-    tm: enable t_replicate() without any parameter
-    
-    - r-uri or dst-uri will be used for sending out
+    modules/permissions: Updated to use the new get_branch()/next_branch() functions
 
-commit 6395e97f14c8be6bf20466b94140bd106406aea2
-Author: Carsten Bock <carsten at ng-voice.com>
-Date:   Wed Jul 23 16:55:20 2014 +0200
+commit 58c9ba973415caf2a39c0c6fefbd66986d475a89
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed Mar 27 11:46:45 2013 +0000
 
-    Improve example for Proxy-CSCF Rx Usage
+    modules/domain: Updated to use the new get_branch()/next_branch() functions
 
-commit 81ee937ed9e7db314ad6a2849dd3b17ab5aebae3
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Jul 22 13:45:13 2014 +0200
+commit 42a1548a57ec8e3a8779f1644347340c25aa1bdd
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Wed Mar 27 11:44:08 2013 +0000
 
-    uac: documented rpc command uac.reg_reload
+    core: Update get_branch() to return instance from appended branches
+    
+    - get_branch() and next_branch() updated
+    - modified select_core.c to use new function definition
 
-commit 24edcab2012f43f25a0b3f6fb5e0645854ecb050
+commit 14525efb68380b759347e64441cb90f97c1e3595
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Jul 22 13:42:54 2014 +0200
+Date:   Tue Mar 26 23:45:50 2013 +0100
 
-    uac: clean old records in timer callback after a while from a reload
+    core: auto-define cfg directive MOD_modname for each loaded module
+    
+    - example: if acc module is loaded, MOD_acc is defined in cfg
+    - suggestion by Olle E. Johansson
 
-commit 99da07de696c1f5368bf74ea82fe7df7f8db61a0
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Jul 22 13:33:24 2014 +0200
+commit e1dc02d523867fc9934e862397e6da6b256c7b1b
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Tue Mar 26 22:16:03 2013 +0100
 
-    uac: new rpc command - uac.reg_reload
+    snmpstats Add tcpasync and tcpmaxconns
     
-    - reload the records from database
-    - old records are kept for at least 150sec more to be sure no active
-      registration process is using them
-    - therefore reload cannot executed more often than 150sec
+    This is to test if I can reach core configuration settings for TCP. Tests prove that it's
+    possible. Will go ahead and add other settings as well.
+    
+    One question is if we should allow changing these variables in SNMP, like we do
+    over the RPC interface or selects. Let's think about that.
 
-commit 361052ff5ea85a304f68860e9c50de93ef742fee
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Jul 21 17:28:11 2014 +0200
+commit 63a72893c84aad1edd7b139dbe36e3c337d4e9ae
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Tue Mar 26 21:29:48 2013 +0100
 
-    uac: documented rpc commands uac.reg_enable and uac.reg_disable
+    snmpstats Add IDs to sections in documentation
 
-commit dd1ca987775be186761f8c83ea7ee9584bbebc96
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Jul 21 17:24:28 2014 +0200
+commit 76a967f1db16540257fe8a54fe85e3993060b304
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Tue Mar 26 12:10:11 2013 +0000
 
-    uac: added commands to enable/disable records in remote registration table
+    modules/tm: Update t_next_contact_flows for use in branch_failure event_route
     
-    - introduced a mutex per slot in memory hash table to avoid races on
-      updating the fields of registration records
+    - Rename to t_next_contact_flow as only one flow will be used
+    - Selects and uses the next flow with the same instance_id as the failed branch
 
-commit 54d7dcb7574589a831b1561f5ec93a7d9a572459
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Jul 21 13:25:38 2014 +0200
+commit 0b79baecf4a36a47522fd222614e370c5d044e8f
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Tue Mar 26 11:43:35 2013 +0000
 
-    uac: documented the new rpc command uac.reg_info
+    core: Add defines required for a new branch_failure_route type
 
-commit eb29edeea30603ebc57ed1771058fc10aee76ce2
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Jul 21 13:22:45 2014 +0200
+commit 54a98bc741daba4d0c14c587d22dddf3c01a2e30
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Tue Mar 26 11:40:38 2013 +0000
 
-    uac: refreshed the readme file
+    modules/tm: Create branch-failure event route
 
-commit 6173c75eb967a20bb25bb0d71e464415f6488156
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Jul 21 13:22:20 2014 +0200
+commit 054af083489cba1d7072768734abdc5cf8ef916b
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Tue Mar 26 11:22:31 2013 +0000
 
-    uac: documented old uac.reg_dump rpc command
+    Revert "core: Initial revision of branch_failure_route"
+    
+    Remove new branch_failure_route in favour of an event_route
+    
+    This reverts commit a5946574cb9917f0a9a90ea547c9357f3f6477bd.
 
-commit 529ebb934208160328a439b5048e9418e63e3e3c
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Jul 21 13:17:32 2014 +0200
+commit 96596e282af0a967c93e162169c6729d183557b9
+Author: Carlos Ruiz Díaz <carlos.ruizdiaz at gmail.com>
+Date:   Tue Mar 26 00:58:28 2013 -0300
 
-    uac: new rpc command to retrieve information for one registration record
-    
-    - uac.reg_info attr val
-    - attr can be l_uuid, l_username, r_username, auth_username
+    cnxcc: added new module for credit control
 
-commit dab956c0f9faca63dde6b2ce25386ca42ddc33e7
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Jul 21 12:41:01 2014 +0200
+commit d269473c935ccd1b867ba215c8b4701f8cf24027
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Sun Mar 24 21:52:41 2013 +0100
 
-    corex: docs for send_data() function
+    snmpstats activate new parts of the KAMAILIO-MIB
 
-commit f4c26ffb8e0aaf05def0adc64bdcf07e8173c984
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Jul 21 12:32:30 2014 +0200
+commit 90c51c7b0f85494bc95afc4b976c142051cb7792
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Sun Mar 24 21:49:02 2013 +0100
 
-    corex: new function send_data(uri, data)
+    snmpstats Add information about version and tcp connections
+    
+    Output from SNMPwalk with the new additions:
+    
+    KAMAILIO-MIB::kamailioNetTcpConnEstablished.0 = Counter32: 0
+    KAMAILIO-MIB::kamailioNetTcpConnFailed.0 = Counter32: 0
+    KAMAILIO-MIB::kamailioNetTcpConnReset.0 = Counter32: 0
+    KAMAILIO-MIB::kamailioNetTcpConnSuccess.0 = Counter32: 0
+    KAMAILIO-MIB::kamailioNetTcpConnOpened.0 = Gauge32: 0
+    KAMAILIO-MIB::kamailioNetTcpConnPassiveOpen.0 = Counter32: 0
+    KAMAILIO-MIB::kamailioNetTcpConnReject.0 = Counter32: 0
+    KAMAILIO-MIB::kamailioNetTcpEnabled.0 = INTEGER: true(1)
+    
+    KAMAILIO-MIB::kamailioSrvMaxMemory.0 = Gauge32: 33554432
+    KAMAILIO-MIB::kamailioSrvFreeMemory.0 = Gauge32: 31709088
     
-    - send arbitrary formated data to uri
-    - uri param has to be a valid sip uri
-    - both parameters can include pseudo-variables
+    KAMAILIO-MIB::kamailioSrvCnfFullVersion.0 = STRING: kamailio 4.5.0 (i386/linux) 50af49
+    KAMAILIO-MIB::kamailioSrvCnfVerName.0 = STRING: kamailio
+    KAMAILIO-MIB::kamailioSrvCnfVerVersion.0 = STRING: 4.5.0
+    KAMAILIO-MIB::kamailioSrvCnfVerArch.0 = STRING: i386
+    KAMAILIO-MIB::kamailioSrvCnfVerOs.0 = STRING: linux
+    KAMAILIO-MIB::kamailioSrvCnfVerId.0 = STRING: 50af49
+    KAMAILIO-MIB::kamailioSrvCnfVerCompTime.0 = STRING: 12:12:27 Mar 24 2023
+    KAMAILIO-MIB::kamailioSrvCnfVerCompiler.0 = STRING: gcc 4.1.2
+    KAMAILIO-MIB::kamailioSrvCnfVerFlags.0 = STRING: STATS: Off, USE_IPV6, USE_TCP, USE_TLS, TLS_HOOKS, USE_RAW_SOCKS, DISABLE_NAGLE, USE_MCAST, DNS_IP_HACK, SHM_MEM, SHM_MMAP, PKG_MALLOC, USE_FUTEX, FAST_LOCK-ADAPTIVE_WAIT, USE_DNS_CACHE, USE_DNS_FAILOVER, USE_NAPTR, USE_DST_BLACKLIST, HAVE_RESOLV_RES
 
-commit 6559c4383858d472637807c6ec4dd1e0616507fa
+commit d80ea02f5d96477e1c6deca581500cfa4a24380e
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Jul 21 10:10:45 2014 +0200
+Date:   Sun Mar 24 13:53:50 2013 +0100
 
-    msilo: check if the register has contacts with positive expires value
+    usrloc: new option for db_mode - DB_READONLY (4)
     
-    - otherwise is un-registration and no new contact to dump messages
-    - reported by Anthony Messina
+    - location records are loaded only at startup
+    - no write back to database, not even at shutdown
+    - useful when registrations are replicated to another node that does the
+      db storage at runtime
+    - started from a patch by Marcus Hunger
 
-commit e5519a2762f892ef97f2c4da2e3f8bfd6078211a
-Author: Carlos Ruiz Diaz <carlos.ruizdiaz at gmail.com>
-Date:   Sun Jul 20 08:40:22 2014 -0500
+commit ef8fae0e21ca09725c7f9c06384e0a4ce37c4c6e
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Sun Mar 24 13:24:58 2013 +0100
 
-    cnxcc: use of pseudo-variables in *cnxcc:call-shutdown* event route
+    enum: define the max size for numbers
     
-    - Ticket FS#450
-    - Patch contributed by Guillaume Bour
+    - set it to 22 (previously hardcoded value was 17)
+    - easier to adjust and check for overlenght
+    - patch by Marcus Hunger
 
-commit 516eee4a8f9d49e7810784587edd08517b868c12
-Author: Carlos Ruiz Diaz <carlos.ruizdiaz at gmail.com>
-Date:   Sun Jul 20 08:19:32 2014 -0500
+commit 61c706ef813520ce0ac6767e6be7ef6e52bd6b3a
+Author: Daniel-Constantin Mierla <miconda at gmail.com>
+Date:   Sun Mar 24 13:07:39 2013 +0100
 
-    Added LF character at the end of every log message
+    db_mysql: new module parameter - insert_delayed
     
-    - requested in ticket FS#452
+    - if set to 1, then all INSERT API queries will be converted in INSERT
+      DELAYED (only DB API insert, not for raw queries)
 
-commit a29089207ac592ff2ae079e2ebd918722b22f1d5
+commit 9cbe03b3b42826c656b73a8793a8c2db9e7c3d29
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Jul 18 16:58:14 2014 +0200
+Date:   Sun Mar 24 12:50:50 2013 +0100
 
-    nosip: new module allowing to handle non-sip packets via event route
-    
-    - packets that fail to be parsed as SIP messages are given to
-      event_route[nosip:msg]
-    - use cases can be imagined as needed, one could be re-engaging SIP
-      worker processes in handling suspended transactions
+    Makefile: exclude debian sym link when generating tarball
 
-commit 3e51a293bccf6dd69f5560a00a8d20d54a0836ce
+commit 7339d847adfd098c58426e96e5e3730ad580d543
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Jul 18 16:57:35 2014 +0200
+Date:   Sun Mar 24 12:38:45 2013 +0100
 
-    tmx: fixed type in doc example for t_continue()
+    msrp: fix compile warning of argument type in dbg message
+    
+    - reported by Olle E. Johansson
 
-commit 6284b608f1af46119b737eb48a47bcf95a58e367
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Jul 18 16:03:40 2014 +0200
+commit bb76415ba7b623242a84b295728e61d307ab48fb
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Sun Mar 24 11:45:43 2013 +0100
+
+    snmpstats Clear upp method-supported logic a bit and add "dialog-ng" for call statefullness
+
+commit 3580d7fbc3318a2eefaa62e60fcad363e953cccb
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Sun Mar 24 11:38:27 2013 +0100
 
-    core: execute callback functions for event SREV_RCV_NOSIP
+    snmpstats Add SNMP support for shared memory
     
-    - it is done only if parsing sip message fails
-    - reminder that the log level for core parsing error can be controlled
-      with corelog global parameter
+    This is just the first proof-of-concept addition, will add more of the
+    core variables for memory and TCP connections
 
-commit ac0bd3790b40a4788cea83542b99fe9dd08116bf
+commit 1826a5f4e3a981e30956da61e11ea551aae0b714
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Jul 18 16:01:29 2014 +0200
+Date:   Sat Mar 23 10:44:31 2013 +0100
 
-    core: new core event executed when a non sip packet is received
+    rr: use sips to build RR headers of R-URI has sips
     
-    - event type SREV_RCV_NOSIP
+    - reported by Hugh James, FS#277
 
-commit 072d314828962c4ada3a15557d704a2efa5b015d
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Jul 18 16:00:42 2014 +0200
+commit 4baf0389c57a7e705c5b01dd95da0e8978dc784a
+Author: Ovidiu Sas <osas at voipembedded.com>
+Date:   Wed Mar 20 13:23:49 2013 -0400
 
-    core: moved debug message about async task init after checking if it is enabled
+    p_usrloc: commenting out unused db_timer_udomain() to get rid of compiler warnings
 
-commit d877c3ac0576fe9a0aea1262c6ec05eb7eb26e3e
-Author: Carsten Bock <carsten at ng-voice.com>
-Date:   Fri Jul 18 19:17:00 2014 +0800
+commit 67609608aa4306de9a34a28a3a31880ad0d17e8e
+Author: Ovidiu Sas <osas at voipembedded.com>
+Date:   Wed Mar 20 13:16:27 2013 -0400
 
-    ims_usrloc_scscf: Bugfix/Improvement: Use "last-inserted ID" instead of doing a separate query (may cause issues with Replication/Database-Clusters)
+    kamailio/utils/sercmd: remove unused but set variable
 
-commit f2dc27ced23a03241045607f394ca2d6834e90f8
-Author: Timo Teräs <timo.teras at iki.fi>
-Date:   Thu Jul 17 23:40:10 2014 +0200
+commit b7a41ef47ad5d7fa90e577673cc2f38ab5ef2237
+Author: Ovidiu Sas <osas at voipembedded.com>
+Date:   Wed Mar 20 13:15:08 2013 -0400
 
-    websocket: option to compile the module without libunistring
-    
-    - patch discussed on sr-dev
-    - dcm: aded define wrapper to have this as compile time option and
-      included the MIT license from the code site
+    kamailio/utils/sercmd: remove unused but set variable
 
-commit c2b334bf41cbe6fa7b7e15d825dca1fa36c33770
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Jul 17 19:13:42 2014 +0200
+commit ff94115921a08ba4da29baf2761db47bd0b7f8f5
+Author: Ovidiu Sas <osas at voipembedded.com>
+Date:   Wed Mar 20 13:13:27 2013 -0400
 
-    usrloc: refresh call-id value in case of update of location record
-    
-    - related to FS#448
+    kamailio/utils/sercmd: remove unused but set variable
 
-commit d19c9fc484dc9eaf9ecc5d7855fec4f90a8d4a1f
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Jul 17 17:27:03 2014 +0200
+commit 387adace552c22eaf15a049b23694bcd79cea3a8
+Author: Ovidiu Sas <osas at voipembedded.com>
+Date:   Wed Mar 20 13:02:16 2013 -0400
 
-    registrar: README regenerated after fixing typo and xacp_cfg socket option
+    auth_diameter: remove unused but set variable
 
-commit 6c569e1a759c70398cac0375b0da9dad41928713
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Jul 17 17:26:37 2014 +0200
+commit 941c48ae6909994ae090c9d52766cd4dd5d4f938
+Author: Ovidiu Sas <osas at voipembedded.com>
+Date:   Wed Mar 20 13:00:27 2013 -0400
 
-    registrar: documented the option to take socket value via xavp
+    auth_diameter: remove unused but set variable
 
-commit 66c497fdf4ac1c3b889a7c3b50c3e5fed770cf0b
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Jul 4 13:46:35 2014 +0200
+commit 94e7ae77a6674d5e6a6d025a8e85f7b1c8733057
+Author: Carsten Bock <carsten at ng-voice.com>
+Date:   Wed Mar 20 17:31:34 2013 +0100
 
-    usrloc: generate callid at startup and increase cseq for records added via mi
-    
-    - should fix FS#448, reported by Savolainen Dmitri
+    Updated example config for S-CSCF
 
-commit 9e1ff4488a8ea5061e9f508cfa3b875912393ae0
-Author: Anthony Messina <amessina at messinet.com>
-Date:   Fri Jul 4 11:36:37 2014 +0200
+commit 0d8cec6b6cd9027ef7313608db7e27667643fdf6
+Author: Anca Vamanu <anca.vamanu at 1and1.ro>
+Date:   Wed Mar 20 15:39:12 2013 +0200
 
-    all: updated FSF address in GPL text
+    modules/drouting Improvement for do_routing in failure route
+    
+    Improvement for sort_order 2 : if the failure groups have repeating
+    gateways the module will take care internally not to try again a gateway
+    that was already tried.
 
-commit 639fce79466baf77bbd707eb9cef6473dcb3eb7c
-Author: Richard Fuchs <rfuchs at sipwise.com>
-Date:   Wed Jul 2 14:53:36 2014 -0400
+commit 6bb98ddd9ee4913c7a56ca5ffa57d9f74e7bc1b3
+Author: Lucian Balaceanu <lucian.balaceanu at 1and1.ro>
+Date:   Wed Mar 20 14:27:30 2013 +0200
 
-    rtpengine: add support for TOS=... flag
+    modules/carrierroute Improvement for cr_route in failure route
+    
+    Small improvement in cr_route() function - when it is called from
+    failure_route it will take care not choose a previously choosen gateway.
+    
+    Added cr_reload sercmd.
 
-commit da9d56be28e050dd0cb4aed50efcbda043a3e5cf
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Jul 1 16:10:20 2014 +0200
+commit a5946574cb9917f0a9a90ea547c9357f3f6477bd
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Tue Mar 19 15:43:46 2013 +0000
 
-    tm: run reply callbacks under lock
+    core: Initial revision of branch_failure_route
     
-    - callback functions can modify the request from transaction (e.g., acc for
-      parsing headers needed for accounting)
+    - New branch_failure_route defined
+    - cfg route is called but xlog() causes segfault
 
-commit 2e28163f2f3e756c89f8cc43df0644be38c5e06f
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Jun 30 14:37:40 2014 +0200
+commit 4e0cf550f75835b3f97bda9bb7934389a54b1f18
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Tue Mar 19 15:41:55 2013 +0000
 
-    tmx: handle branch_route for $T_reply_code
+    modules/tm: Initial revision of branch_failure_route
     
-    - use latest sent reply code
-    - related to the log message reported in FS#445
+    - New branch_failure_route defined
+    - cfg route is called but xlog() causes segfault
 
-commit 8fac19ba52345a4dd10480ef4efb62012bbbbff6
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Jun 30 12:34:24 2014 +0200
+commit a0b01f77de163cf7ea9d71d5293a1bfa20d31fa6
+Author: Henning Westerholt <hw at kamailio.org>
+Date:   Tue Mar 19 15:32:25 2013 +0100
 
-    kamctl: use DEFAULT_Q variable in ul_add command
+    rtpproxy: fix spelling error in docs, reported from Victor V. Kustov, coyote at bks dot tv
 
-commit 5db25855613f922059b53d7149e97b4985120de0
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Jun 30 12:11:45 2014 +0200
+commit c218ae122d5de9757bacc114a4bf4a374b7ea9c7
+Merge: ea3a03d 92bbfd0
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Tue Mar 19 09:38:17 2013 +0000
 
-    geoip: free allocated pointers at startup in case of error
+    Merge branch 'master' of ssh://git.sip-router.org/sip-router
     
-    - cleaner shut down
+    * 'master' of ssh://git.sip-router.org/sip-router:
+      modules/sca: seize appearance for SCA callee answering w/o Call-Info
 
-commit 1faf19fa7d34528b6cc15ffcb1ec91a6c6074e90
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Jun 30 12:05:19 2014 +0200
+commit 92bbfd0b04306dd53e8eae444f46de768239875b
+Author: Andrew Mortensen <admorten at isc.upenn.edu>
+Date:   Mon Mar 18 15:03:24 2013 -0400
 
-    core: reset cur_opt shortcut after use, it points to local variable
+    modules/sca: seize appearance for SCA callee answering w/o Call-Info
     
-    - safety to prevent invalid access on future extensions
-
-commit 6feeb886b58f4cd1cefeef132245c009bf8ca07f
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Jun 30 11:06:41 2014 +0200
+    - Yealink firmware 7.70.0.130 doesn't include a Call-Info header with
+      200 OK response to INVITE.
 
-    uac: print new and old uri in log message in case of error
+commit ea3a03de4f1a3ba163302ab2d5ee140bab49a85c
+Merge: 3a45d92 fac2d49
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Mon Mar 18 17:24:03 2013 +0000
 
-commit 269220f9a657ca10085ae8889312d052b65b12f8
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Thu Jun 26 09:46:16 2014 +0200
+    Merge branch 'master' of ssh://git.sip-router.org/sip-router
+    
+    * 'master' of ssh://git.sip-router.org/sip-router:
+      modules/sca: cast logging of time_t to long int to quiet warnings.
 
-    modules/cdp: prevent possible seg fault if no MSCC AVP present in CCA response to update GSU timers
+commit fac2d49b667c5c18fce01387d9c02afcce8ec55f
+Author: Andrew Mortensen <admorten at isc.upenn.edu>
+Date:   Mon Mar 18 10:32:45 2013 -0400
 
-commit 71ecad37d231f6fda652892550ff8b9a8d193f59
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Tue Jun 17 13:06:20 2014 -0400
+    modules/sca: cast logging of time_t to long int to quiet warnings.
+    
+    - Report from Olle Johansson. Latent Y2K38 problem, but that needs a
+      project-wide solution.
 
-    auth: README regenerated
+commit 3a45d925c7f06072aef9edba3b0ef8c17e12c6e2
+Merge: dd0b43e 07ddc78
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Mon Mar 18 11:57:17 2013 +0000
 
-commit c9c8f8d71fdad33caebaea07922901618bcd7825
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Tue Jun 17 11:47:50 2014 -0400
+    Merge branch 'master' of ssh://git.sip-router.org/sip-router
+    
+    * 'master' of ssh://git.sip-router.org/sip-router:
+      modules/app_java: refactoring, changed parameter 'force_kam_cmd_exec' to 'force_cmd_exec', updated docs     - moved ThrowNewException from utils to java_support     - removed macro FORCE_CAST_O2P     - removed get_struct_sip_msg     - renamed parameter 'force_kam_cmd_exec' to 'force_cmd_exec'     - updated docs caused parameter change
+      modules/app_java: README to README-draft, added actual README
+      modules/app_java: moved README, removed other formats except xml from doc directory.
+      modules/app_java: added documentation, removed *.class,*.jar
+      modules/sca: fix -Waddress warnings caused by static strs in SCA_STR_EMPTY
+      modules/sca: process BYE without Call-Info from shared line.
+      modules/outbound: Warn during mod_init() if STUN is not built or enabled
+      modules/outbound: free shared memory for flow-token key during shutdown
+      sca: reduce log level to DBG when replacing RURI when retrieving held call.
+      modules/outbound: Fixed bug in outbound mod_init
+      modules/outbound: The flow-token key is now automatically generated
+
+commit 07ddc78df819edff18cc339cb234c22d140bd3a4
+Author: Konstantin Mosesov <ez at voipgroup.org.ua>
+Date:   Mon Mar 18 02:04:17 2013 +0200
 
-    auth: document '-8' return code for pv_www_authenticate
+    modules/app_java: refactoring, changed parameter 'force_kam_cmd_exec' to 'force_cmd_exec', updated docs
+        - moved ThrowNewException from utils to java_support
+        - removed macro FORCE_CAST_O2P
+        - removed get_struct_sip_msg
+        - renamed parameter 'force_kam_cmd_exec' to 'force_cmd_exec'
+        - updated docs caused parameter change
 
-commit c9301c99d3c9acb663023cf02393d0e7ed74c133
-Author: Hugh Waite <hugh.waite at acision.com>
-Date:   Mon Jun 16 11:53:11 2014 +0100
+commit 87a21516e1c75d11513df901567183b0146337ab
+Author: Konstantin Mosesov <ez at voipgroup.org.ua>
+Date:   Mon Mar 18 01:45:49 2013 +0200
 
-    registrar: Add check for contact header before checking outbound support
-    
-    - Fixes crash when processing REGISTER without a contact
+    modules/app_java: README to README-draft, added actual README
 
-commit 8772bd49cbcc6b43466515d0ad60b49106f8fbe0
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Sun Jun 15 01:32:32 2014 +0200
+commit a01d84bf61ade1b0362c16a41acec262a41b919a
+Author: Konstantin Mosesov <ez at voipgroup.org.ua>
+Date:   Mon Mar 18 01:20:29 2013 +0200
 
-    pkg/kamailio/deb: Add Ubuntu trusty support
+    modules/app_java: moved README, removed other formats except xml from doc directory.
 
-commit 8d7d72add168c2fa592214853470f4a31515c510
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Sat Jun 14 18:50:56 2014 +0200
+commit fc425b1c36a335af1ee5ca183cca72b6a472843f
+Author: Konstantin Mosesov <ez at voipgroup.org.ua>
+Date:   Sun Mar 17 01:16:20 2013 +0200
 
-    pkg/kamailio/deb: Use gcj-jdk
+    modules/app_java: added documentation, removed *.class,*.jar
 
-commit 00d2c27cbd0c36fd8979d5b92a3f860a5e657c60
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Sat Jun 14 18:20:06 2014 +0200
+commit d80b4afc7d0dddebd9ffe06e0174a79871daf822
+Author: Andrew Mortensen <admorten at isc.upenn.edu>
+Date:   Sat Mar 16 16:35:29 2013 -0400
 
-    app_java: Use generic libgcj
+    modules/sca: fix -Waddress warnings caused by static strs in SCA_STR_EMPTY
+    
+    - Tested on Ubunut 12.04 LTS. Report from Konstantin Mosesov.
 
-commit 4fab97fb54334a55b1fce4e0d2f417fda5727c3a
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Jun 13 12:00:21 2014 +0200
+commit 287cccf2af17e5f2f8fe09c41025b4d27bb4fda9
+Author: Andrew Mortensen <admorten at isc.upenn.edu>
+Date:   Fri Mar 15 17:01:23 2013 -0400
 
-    dialog: backup and restore exiting route type when executing dialog event_route blocks
+    modules/sca: process BYE without Call-Info from shared line.
     
-    - reported by Nuno Miguel Reis
+    - Ciscos & Aastras don't seem include Call-Info header in BYE. Look up
+      dialog by tags and release associated appearance-index.
 
-commit 1c715b1a2a66a4a15d1a8def33ef369212712bb1
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Thu Jun 12 12:46:39 2014 -0400
+commit 85b26219f9e4c3c8c7c990a4897d40645b4ad6e7
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Fri Mar 15 15:04:07 2013 +0000
 
-    core: fix crash related to core sockets_list  command
-     - reported by Nuno Reis <nreis at wavecom.pt>
+    modules/outbound: Warn during mod_init() if STUN is not built or enabled
+    
+    - STUN is required for outbound with UDP.  Don't want to stop Kamailio starting
+      when the outbound module is loaded and STUN is not available - but a warning
+      seems appropriate.
 
-commit 81a1ebc76d4cea28ce46ec0cc0d6d62cf26fd3a8
-Author: Richard Fuchs <rfuchs at sipwise.com>
-Date:   Thu Jun 12 11:06:44 2014 -0400
+commit 9d9d51438acd1d534f14ecbc8eb0030b45333177
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Fri Mar 15 14:54:41 2013 +0000
 
-    rtpengine: allow usage of arbitrary/unknown flags within the protocol
+    modules/outbound: free shared memory for flow-token key during shutdown
 
-commit 91072bbdeaf951f07ae0324c2ba566bd46919f97
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Thu Jun 12 12:57:27 2014 +0200
+commit a51bc822f70f4185b55455456dc147205cbbbdc7
+Author: Andrew Mortensen <admorten at isc.upenn.edu>
+Date:   Fri Mar 15 10:22:26 2013 -0400
 
-    pkg/kamailio/deb: new 4.2.0~dev7 version
+    sca: reduce log level to DBG when replacing RURI when retrieving held call.
 
-commit 2aa00ae5b53b823d8b9b0b6f5ee2a8ce1c98b739
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Jun 12 12:15:59 2014 +0200
+commit c924645fcfb706fc20ed715a00531d785f99cbde
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Fri Mar 15 14:07:04 2013 +0000
 
-    Makefile.defs: version set to 4.2.0-dev7
+    modules/outbound: Fixed bug in outbound mod_init
 
-commit e6c0c2f9871eab5a73371d48dfa24e4ece2512d8
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Jun 12 12:12:02 2014 +0200
+commit f474e85616f6f98a6ac193c7425f6c85af8efa20
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Fri Mar 15 12:14:31 2013 +0000
 
-    acc: clear new parsed headers when evaluating acc attributes
+    modules/outbound: The flow-token key is now automatically generated
     
-    - the structures are in pkg, while request is taken from shm clone, can
-      cause reference to the space of another process
-    - reported by Igor Potjevlesch
+    - Uses OpenSSL RAND_bytes() to select 20 cryptographically strong pseudo-random
+      bytes for the key.
+    - Flow-token key can no longer be manually set.
 
-commit 655711330b2ffd82dc84330ef0e0fbbad82a9160
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Jun 12 11:48:01 2014 +0200
+commit dd0b43e2ac06ed901f959d9e5a90312d865dedfd
+Merge: 1c27645 3445718
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Fri Mar 15 12:08:16 2013 +0000
 
-    acc: allow recording to the rest of backends even when setting db table fails
+    Merge branch 'master' of ssh://git.sip-router.org/sip-router
     
-    - such error doesn't affect radius or custom backends
+    * 'master' of ssh://git.sip-router.org/sip-router: (40 commits)
+      modules/registrar: fixed lock usage in unregister()
+      modules/pv: can only retrieve $ruid for a request
+      ims_icscf: fix include list for BSD
+      modules/pv: added new $ruid and $branch(ruid) PVs
+      modules/xprint: updated use of get_branch() and next_branch() to cope with additional argument
+      modules/tm: updated use of get_branch() and next_branch() to cope with additional argument
+      modules/pv: updated use of get_branch() and next_branch() to cope with additional argument
+      modules/permissions: updated use of get_branch() and next_branch() to cope with additional argument
+      modules/domain: updated use of get_branch() and next_branch() to cope with additional argument
+      core: updated use of get_branch() and next_branch() to cope with additional argument
+      core: updated get_branch() and next_branch() to return ruid (if set)
+      modules/tm: updated t_serial to store/retrieve ruid
+      modules/registrar: tidied up unregister() function
+      modules/ims_isc: updated to include new argument to append_branch()
+      modules/ims_icscf: updated to include new argument to append_branch()
+      modules/exec: updated to include new argument to append_branch()
+      modules/enum: updated to include new argument to append_branch()
+      modules/dialplan: updated to include new argument to append_branch()
+      modules/cpl-c: updated to include new argument to append_branch()
+      modules/corex: updated to include new argument to append_branch()
+      ...
+
+commit 3445718155b324c3c9e4eac0d6137b6d8dca8cbf
+Merge: e930f94 d6eac37
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Fri Mar 15 11:28:25 2013 +0000
+
+    Merge branch 'outbound'
+    
+    * outbound: (46 commits)
+      modules/registrar: fixed lock usage in unregister()
+      modules/pv: can only retrieve $ruid for a request
+      modules/pv: added new $ruid and $branch(ruid) PVs
+      modules/xprint: updated use of get_branch() and next_branch() to cope with additional argument
+      modules/tm: updated use of get_branch() and next_branch() to cope with additional argument
+      modules/pv: updated use of get_branch() and next_branch() to cope with additional argument
+      modules/permissions: updated use of get_branch() and next_branch() to cope with additional argument
+      modules/domain: updated use of get_branch() and next_branch() to cope with additional argument
+      core: updated use of get_branch() and next_branch() to cope with additional argument
+      core: updated get_branch() and next_branch() to return ruid (if set)
+      modules/tm: updated t_serial to store/retrieve ruid
+      modules/registrar: tidied up unregister() function
+      modules/ims_isc: updated to include new argument to append_branch()
+      modules/ims_icscf: updated to include new argument to append_branch()
+      modules/exec: updated to include new argument to append_branch()
+      modules/enum: updated to include new argument to append_branch()
+      modules/dialplan: updated to include new argument to append_branch()
+      modules/cpl-c: updated to include new argument to append_branch()
+      modules/corex: updated to include new argument to append_branch()
+      modules/avpops: updated to include new argument to append_branch()
+      ...
+
+commit d6eac37fb61a79e7d99b749aa20ff903523ff2d0
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Fri Mar 15 11:15:16 2013 +0000
 
-commit dd00819f7cca976e699a20960956abff760df957
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Jun 12 11:39:55 2014 +0200
+    modules/registrar: fixed lock usage in unregister()
+
+commit 86440c81639e1aff66e7449a121ac8ae6d43197a
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Fri Mar 15 11:14:06 2013 +0000
 
-    auth: proper fixup for optional method parameter in pv_www_authenticate()
+    modules/pv: can only retrieve $ruid for a request
     
-    - reported by Muhammad Shahzad
+    - cache it in an avp for the request if you need it later
 
-commit 28be6c3c79c02600f03a51b2393b289fbe8c9bd9
+commit e930f94b71d2e5c40fa44d78738ce5efb747c5b1
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Jun 12 09:59:44 2014 +0200
+Date:   Fri Mar 15 09:03:26 2013 +0100
 
-    core: sync definition of destroy_rpcs()
+    ims_icscf: fix include list for BSD
     
-    - reported by Victor Seva
+    - patch by Victor V. Kustov
 
-commit 35329870fe22115fd24a396b743e4814278ce46a
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Jun 11 19:01:17 2014 +0200
+commit 44e43d541baf52a327485d8627de3b95961bdaf9
+Merge: b53624e 81b5473
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Fri Mar 15 00:02:38 2013 +0000
 
-    auth: enhanced log message when method param fails to be retrieved
+    Merge branch 'master' into outbound
+    
+    * master:
+      sca: fix private hold handling
+      xhttp_pi: escape special characters
 
-commit 88a9ffee284338d536b6f7e072e5c99b29d983ee
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Jun 11 17:12:37 2014 +0200
+commit b53624e388c283ae1294bf595af123c3b77f6b93
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Thu Mar 14 23:55:14 2013 +0000
 
-    dialog: execute internal event_route blocks under local_route type
-    
-    - request_route type triggers additional script callbacks that could
-      reset the transaction and can cause crashing
-    - reported by  Nuno Miguel Reis, FS#440
+    modules/pv: added new $ruid and $branch(ruid) PVs
 
-commit 67de76fce11b3c7ac80955590a441d7be6563368
-Author: Carsten Bock <carsten at ng-voice.com>
-Date:   Tue Jun 10 12:22:03 2014 +0200
+commit 0137a2a91d29cbd80829b79dcb4cfd9659b7e9be
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Thu Mar 14 23:35:02 2013 +0000
 
-    ims_registrar_pcscf: Bugfix: Update Received Info, when updating contact (it may have changed)
+    modules/xprint: updated use of get_branch() and next_branch() to cope with additional argument
 
-commit ad5f82c598e564e3d937fffa401ad04e1966b9f2
-Merge: 57177cf bed067f
-Author: lucian balanceanu <lucian.balanceanu at 1and1.ro>
-Date:   Tue Jun 10 12:31:19 2014 +0300
+commit 0860555382575943b5f704b53a48e63db90754d8
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Thu Mar 14 23:34:48 2013 +0000
 
-    Merge branch 'master' of ssh://git.sip-router.org/sip-router
+    modules/tm: updated use of get_branch() and next_branch() to cope with additional argument
 
-commit 57177cf1cf63b64cd1eedb817dd056f0be51a38e
-Author: Sven Knoblich, Lucian Balaceanu <lucian.balaceanu at 1and1.ro>
-Date:   Tue Jun 10 11:47:27 2014 +0300
+commit a16fb22d12696f707839f7b97da471d02121e228
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Thu Mar 14 23:34:34 2013 +0000
 
-    acc: log cdrs for expired dialogs
-    
-    	- added the cdr_expired_dlg_enable module parameter to toggle on/off
-    	  the cdr writing feature (default is off=0)
-    	  If enabled, only the dlg_vars in the cdr_extra will get printed on
-    	  dialog expiry; the other parameters' values in the cdr extra will
-    	  be left empty
+    modules/pv: updated use of get_branch() and next_branch() to cope with additional argument
 
-commit bed067f3fb8423f0d138903f8d58941d19b81360
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Sat Jun 7 09:19:38 2014 +0200
+commit cb68cab9ce13142592590042283ca1aa3f85ac84
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Thu Mar 14 23:34:18 2013 +0000
 
-    debugger: show routename in cfgtrace output
+    modules/permissions: updated use of get_branch() and next_branch() to cope with additional argument
 
-commit c44685cbcefb8f6ecfa6f11369699906db832c39
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Sat Jun 7 09:19:03 2014 +0200
+commit f63b55b96e9a2900cf73183fdaa41992c3c31dc5
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Thu Mar 14 23:34:01 2013 +0000
 
-    core: add route name to action struct
+    modules/domain: updated use of get_branch() and next_branch() to cope with additional argument
 
-commit 459f86fe167f784db491d3155a302ee758fef708
-Author: Carsten Bock <carsten at ng-voice.com>
-Date:   Sat Jun 7 01:26:05 2014 +0200
+commit 55e069d5c169d9022582c51a9bce82adc136c29c
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Thu Mar 14 23:33:23 2013 +0000
 
-    ims_usrloc_pcscf: Bugfix: Fix priorities in if statement
+    core: updated use of get_branch() and next_branch() to cope with additional argument
 
-commit 5f5df3fda7662575719253f0a16e6ae03bf6f69a
-Author: Carsten Bock <carsten at ng-voice.com>
-Date:   Sat Jun 7 00:47:22 2014 +0200
+commit 8e6c690ea3cdfd9dd1349f2ce144d7dfd432b50d
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Thu Mar 14 23:32:42 2013 +0000
 
-    Bugfix: Fix previous commit
+    core: updated get_branch() and next_branch() to return ruid (if set)
 
-commit 33304281cbdd0b992e4db01eb0114735068f67ab
-Author: Carsten Bock <carsten at ng-voice.com>
-Date:   Fri Jun 6 19:38:12 2014 +0200
+commit 87e624ffe1e66104b04d34bd2102f458f5785bf0
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Thu Mar 14 23:16:27 2013 +0000
 
-    Bugfix: Add missing */
+    modules/tm: updated t_serial to store/retrieve ruid
 
-commit a9155e4c73d533d0837bfd480ff7d838d18dc995
-Author: Carsten Bock <carsten at ng-voice.com>
-Date:   Fri Jun 6 19:09:55 2014 +0200
+commit dd90d9685cb66843ff48c55b0100de9f98bfdf52
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Thu Mar 14 23:05:32 2013 +0000
 
-    ims_usrloc_pcscf: Add option, to disable the "received check" upon lookup.
+    modules/registrar: tidied up unregister() function
 
-commit c1a6e04fd6b3f6b97893abe77a6a19ff6dbb0054
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Fri Jun 6 11:40:13 2014 +0200
+commit b49ea76814d2933bb9bc58f82230c4569be171af
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Thu Mar 14 22:58:44 2013 +0000
 
-    modules/ims_auth: small cleanup/refactor in ims_get_body
+    modules/ims_isc: updated to include new argument to append_branch()
 
-commit 2c73e20aabd71bc34f2294a53c8bff8d7a3881f2
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Fri Jun 6 11:38:50 2014 +0200
+commit 01f4a316eeb2ed9b7110cb5ee8c96c4923b9acaa
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Thu Mar 14 22:58:24 2013 +0000
 
-    modules/ims_auth: remove useless/incorrect log line
+    modules/ims_icscf: updated to include new argument to append_branch()
 
-commit f30f7bf4d723f78546ee2a8db607d80279bdd529
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Tue Jun 3 09:42:41 2014 +0200
+commit 4ed5c06088fc87a32ecb59a291f83e947aee7070
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Thu Mar 14 22:58:04 2013 +0000
 
-    modules/ims_registrar_scscf: updated doc for cxdx_forced_peer
+    modules/exec: updated to include new argument to append_branch()
 
-commit b957dfd27e5350828f500520af33394806142296
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Tue Jun 3 09:42:18 2014 +0200
+commit 08b7df7556f6677ed6049825cf20155162269fd4
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Thu Mar 14 22:57:49 2013 +0000
 
-    modules/ims_qos: updated doc for rx_forced_peer
+    modules/enum: updated to include new argument to append_branch()
 
-commit 6fa36e1d98a64a9d5d3d40444068fde69dc5b1b3
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Tue Jun 3 09:41:56 2014 +0200
+commit dab406ed0301bfea5a9e6234119082e445dd5806
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Thu Mar 14 22:57:30 2013 +0000
 
-    modules/ims_icscf: updated doc for cxdx_forced_peer
+    modules/dialplan: updated to include new argument to append_branch()
 
-commit c95b3e610708178b643db484cdc63f40ac6d8a45
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Tue Jun 3 09:41:29 2014 +0200
+commit cb10662ae458b799d9746948aba59fb513af318d
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Thu Mar 14 22:57:06 2013 +0000
 
-    modules/ims_charging: updated doc for ro_forced_peer
+    modules/cpl-c: updated to include new argument to append_branch()
 
-commit 50f28af8d9bf4088da44753c3b8e3948aaa9f544
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Tue Jun 3 09:41:05 2014 +0200
+commit 4d3639a674af7ae8102e3ae3e94e84674d9848ae
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Thu Mar 14 22:56:51 2013 +0000
 
-    modules/ims_auth: updated docs for cxdx_forced_peer
+    modules/corex: updated to include new argument to append_branch()
 
-commit 69de17d3bb1d032f9a41752362194d718336e20d
-Author: Torrey Searle <tsearle at gmail.com>
-Date:   Mon Jun 2 19:51:19 2014 +0200
+commit bc8fd8b3b458bf088a83e6c6f17bd21743aaf8e9
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Thu Mar 14 22:56:27 2013 +0000
 
-    srdb1: fix memory leak in db-id
-    
-    - When getting an existing connection from the pool, free the newly
-      created db-id as the pool connection already has a reference to the
-      existing one.  Fixes FS#436
+    modules/avpops: updated to include new argument to append_branch()
 
-commit c4e2df2b494a80ff8493fcc5df66b75478c31789
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Mon Jun 2 11:07:02 2014 +0200
+commit 821d92298d22c6fa2d17e85b3c0f021cd0dbeb8e
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Thu Mar 14 22:55:46 2013 +0000
 
-    modules/ims_charging: improvement on failed CCR during initial routing (no longer just wait for timeout)
-    	- some minor cleanup too
+    modules/alias_db: updated to include new argument to append_branch()
 
-commit 6214fe8702626a4d9edc1ca45e3cd657ee8093ee
-Author: Juha Heinanen <jh at tutpro.com>
-Date:   Sat May 31 19:38:30 2014 +0300
+commit 4fb8d035a952e1f719e60470e7bea2e3877331d5
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Thu Mar 14 22:46:51 2013 +0000
 
-    modules/acc: renamed module param reason_from_reason_hf => reason_from_hf
-    
-    - as per Daniel's suggestion
+    core: updated to include new argument for append_branch()
 
-commit 7f136429e5b676077c4f71c5cc178dd0c125951b
-Author: Juha Heinanen <jh at tutpro.com>
-Date:   Sat May 31 10:34:19 2014 +0300
+commit ac7b94dbd991ba5c25d9afece2b6172b829f514b
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Thu Mar 14 22:46:08 2013 +0000
 
-    modules/acc: added reason_from_reason_hf module paramater
-    
-    - in schema, increased size of sip_reason field to 128 chars
+    modules/registrar: fill in ruid in msg and branch structures during lookup()
 
-commit 8e2fcd278c9172a1774a1a1bae72f2e6d37b1770
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Fri May 30 18:26:48 2014 +0200
+commit e3ba8f38f7bd008f72705fb6acd082e65b5a140e
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Thu Mar 14 22:42:16 2013 +0000
 
-    modules/ims_charging: possible seg fault on diameter CCR timeout fixed
+    core: added ruid to msg and branch structures
 
-commit 3a2b5f5a9fa46a5f8502f9ca355a9f689b6cd61e
-Merge: 70f7dbe c842bda
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Fri May 30 16:52:46 2014 +0200
+commit 0e634d5828ec7e2c9418089007cdac0318e4aced
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Thu Mar 14 22:00:54 2013 +0000
 
-    Merge branch 'master' of ssh://git.sip-router.org/sip-router
+    modules/registrar: fixed typo
 
-commit 70f7dbedd7c7f188270bf6d3649bd9d67d4c2b7e
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Fri May 30 16:51:20 2014 +0200
+commit f892c3c87b181c4b3d32b080f2dbb8ba0b88807f
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Thu Mar 14 21:57:59 2013 +0000
 
-    modules/cdp: omitted last_selected time when choosing a loadbalanced peer
+    parser: fixed typo
 
-commit c842bda9dac46724c58b734d092391c79867f2fb
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri May 30 13:34:08 2014 +0200
+commit 98c0aa3930031e681f0211bc7f07e208c2288703
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Thu Mar 14 21:55:34 2013 +0000
 
-    core/parse/sdp: proper parsing of a=rtpmap line
-    
-    - error handling when malformed line, avoiding crash to due to invalid
-      offsetting when clockrate is missing
-    - reported by  Michael Ricordeau, FS#435
+    parser: updated path for some of the includes in files moved from lib/kcore
 
-commit 6bc322ee1abcd78a18be049c41e7981d920dec82
-Merge: 6e51019 e633ca6
-Author: Olle E. Johansson <oej at edvina.net>
-Date:   Fri May 30 09:21:24 2014 +0100
+commit 19ff7249507118ddfcf34e8dd02407ae3663314f
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Thu Mar 14 21:52:33 2013 +0000
 
-    Arrghh. Poor memory. My apologies for this commit.
-    
-    Merge branch 'master' of ssh://git.sip-router.org/sip-router
+    modules/sst: updated path to parse_supported.h
 
-commit 6e51019b0a2c60178b9ca03b9bb2a5fef49ca7ba
-Author: Olle E. Johansson <oej at edvina.net>
-Date:   Fri May 30 09:20:49 2014 +0100
+commit 59189c400f807deb92b5ee897ea2e19cc086c500
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Thu Mar 14 21:52:18 2013 +0000
 
-    auth_radius: Improve error message to simplify debugging
+    modules/rls: updated path to parse_supported.h
 
-commit e633ca6b7e748a77825d3208e86bf9bce18944a5
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu May 29 17:06:13 2014 +0200
+commit 1a920fc0a69916670ad2cd04e85926546e69a2d5
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Thu Mar 14 21:51:44 2013 +0000
 
-    pv: safety check for PAI header parsed structure
-    
-    - reported by Igor Potjevlesch
+    modules/registrar: updated path to parse_(require|supported).h
 
-commit 79bcd31ae4f30a60c6d3f2a88b505a35ba0f6927
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Thu May 29 13:04:33 2014 +0200
+commit 0497e50dfe195e3b633741f2fcb476ff234285f4
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Thu Mar 14 21:51:11 2013 +0000
 
-    modules/cdp: added loadbalancing across diameter peers within the same realm and with the same metric
+    modules/ims_registrar_scscf: updated path to parse_supported.h
 
-commit 5e9a4997841f328f20cb7459a08f643ad065412d
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Thu May 29 12:57:16 2014 +0200
+commit 96347fb3b2d747712c52579abec081b8eec545d1
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Thu Mar 14 21:50:20 2013 +0000
 
-    modules/ims_charging: possible crash fixed on CCR timeout and some cleanup
-    	- diameter destination realm correctly setup for routing/load balancing of request to multiple peers
+    lib/kcore, parser: moved parse_(options_tags|require|supported) to parser
 
-commit 91a362e2f1bae90e2564491560aff8bad5b04564
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed May 28 15:47:10 2014 +0200
+commit 81b5473f5a191a5aa81295acf0d96a22160f7f31
+Author: Andrew Mortensen <admorten at isc.upenn.edu>
+Date:   Fri Mar 1 16:33:59 2013 -0500
 
-    pkg/rpm: use pkg memory size when checking config in init script
+    sca: fix private hold handling
     
-    - for large configs, check can fail due to low memory
+    - private hold call-info was being ignored in hold reINVITEs, causing
+      inaccurate "active" notifications to go to subscribers.
 
-commit 93ae7f441c6e7760d026e5b8e01a86f05ce59b97
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Wed May 28 12:12:35 2014 +0200
+commit a00662049f2f245f53dfb23a07da9229e2ebe159
+Author: Ovidiu Sas <osas at voipembedded.com>
+Date:   Thu Mar 14 12:16:32 2013 -0400
 
-    modules/cdp: added RPC cmd to list diameter information, including peers and their detail
+    xhttp_pi: escape special characters
 
-commit a0c35bbfa84fd2212c05e5af1d2423a4a2e5e547
-Author: Hugh Waite <hugh.waite at acision.com>
-Date:   Tue May 27 15:42:08 2014 +0100
+commit 6b4d87a4321f8edefbf93b1323502d4bab965290
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Thu Mar 14 14:19:31 2013 +0000
 
-    rls: Fix memory leak with duplicate entries in lists
-    
-    - When duplicate detection is requested, free the string and container
-    - When duplicate detection is not requested, insert the duplicate anyway
+    modules/registrar: Updated documentation for outbound related modparams
 
-commit 81287cb27c87c641f3d314fbabc921345323b864
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Tue May 27 20:55:11 2014 +0200
+commit 2a4300284364c4be42b1e4262966d17e5a546799
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Thu Mar 14 14:19:05 2013 +0000
 
-    modules/cdp: new RPC commands to disable/enable a peer dynamically
-    	- this is useful to disable a particular diameter peer in a cluster
+    modules/register: Fixed mod init check of flow_timer modparam
 
-commit dc2299c7d19869dc16a66d1b4c6696e204a75e12
-Merge: 0d7d5dc 37f0964
-Author: Henning Westerholt <hw at kamailio.org>
-Date:   Tue May 27 12:17:37 2014 +0200
+commit c9f8bfdf7a124c9136b28cf78936ac14cec511b9
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Thu Mar 14 12:25:52 2013 +0000
 
-    Merge branch 'master' of ssh://git.sip-router.org/sip-router
-    
-    * 'master' of ssh://git.sip-router.org/sip-router:
-      db_mysql: proper handling of mysql_next_result(...) return code
-      ims_charging: bugfix: Make ims_charging:ccr_timeouts resettable
+    modules/registrar: fixes to checking of Require: and Supported: headers for outbound
 
-commit 0d7d5dc4d7219c5beb9a150cc56e74edac9dc4d5
-Author: Henning Westerholt <hw at kamailio.org>
-Date:   Tue May 27 12:14:24 2014 +0200
+commit 1c276452b2880cc47994f17460403c58e0ef5c87
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Thu Mar 14 11:57:55 2013 +0000
 
-    db_mysql: fixes FS#434, Kamailio will eat sometimes 100% CPU due a bug in db_mysql
+    documentation: Fix Content-Length typos
     
-    * Fixes FS#434 reported from Maxim, incorrect mysql API usage for mysql_next_result(..)
-    * According MySQL doc, return values for mysql_next_result(..) can be the following:
-      0 - Successful and there are more results
-      -1 - Successful and there are no more results
-      >0 - An error occured
-    * Thus, if there will be an error when reading a next result, the code will be infinitely
-      looped in “while” cycle and current process will eat 100% CPU (The mysql_more_results
-      will not help here because it just checks a local flag that will be set to TRUE in cases
-      when there will be more than one result).
-    * The solution is to replace " > 0” with " == 0”:
+    - Fix typos in textops/textopsx documenation
+    - Regenerate cfg list documentation
 
-commit 37f0964278e925d5530563b38c82a57de1f7fa59
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue May 27 12:07:42 2014 +0200
+commit 90cbe54c01fe9513a0041f19e8a73f3ff7dccaf6
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Thu Mar 14 10:41:24 2013 +0000
 
-    db_mysql: proper handling of mysql_next_result(...) return code
+    core: Fix Content-Length typos
     
-    - it indicates the presence of another result if return is 0
-    - reported by  Maxim (simax), FS#434
+    One typo in the HTTP11CONTINUE response headers
+    One in the tcp option help string for 'accept_no_cl'
+    Two in code comments
 
-commit 88724f2cc7ca5988713246b3e4d7bfac4612072d
-Author: Carsten Bock <carsten at ng-voice.com>
-Date:   Tue May 27 11:56:32 2014 +0200
+commit 9e3c6550c02efc1181aba85fc6b7e871fb632da5
+Merge: 9a4afee 289bc23
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Thu Mar 14 10:10:49 2013 +0000
 
-    ims_charging: bugfix: Make ims_charging:ccr_timeouts resettable
+    Merge branch 'master' into outbound
+    
+    * master:
+      Makefile.groups: Updated package group for app_java.
 
-commit dfccb6d5b1e1ae7eeca85007157ccced97c7f2e5
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon May 26 15:55:22 2014 +0200
+commit 289bc2399c09f5f449fd835f9a046597e4f2b38f
+Author: Konstantin Mosesov <ez at voipgroup.org.ua>
+Date:   Wed Mar 13 22:29:20 2013 +0200
 
-    app_perl: added documentation for perl_destroy_func parameter
+    Makefile.groups: Updated package group for app_java.
 
-commit 6fba7ed75cf5c2cc1d267bb7262df4d228e26273
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon May 26 15:47:07 2014 +0200
-
-    app_perl: new param perl_destroy_func to specify perl destroy function
-    
-    - if set, the module will execute the specified perl function before
-      re-initializing the interpreter at runtime
-
-commit 794af34f4f996de6b6d238b8267ae48650bd2857
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon May 26 15:00:29 2014 +0200
-
-    tls: added missed include file for accessing outgoing connection certificate
-
-commit 4992519eed88d94847d742c52e882082b1b41264
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon May 26 14:47:37 2014 +0200
-
-    auth_db: auth_check() to get the auth header from the used api
-    
-    - this avoids using a different auth header that might be in the request
-      before checking usernames in from/to headers against auth user
-
-commit 1d6d5cd5d4ff7cd488edfaea5600f02b7d3612fa
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon May 26 14:17:43 2014 +0200
-
-    tls: execute event_route[tls:connection-out]
+commit 9a4afeecf8d1166533fefd4df2afc850a44c9ec3
+Merge: 71c197d 7d46ff0e
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Wed Mar 13 16:57:11 2013 +0000
+
+    Merge branch 'master' into outbound
+    
+    * master: (68 commits)
+      modules/permissions: DNS domain names in address table
+      modules/app_java  - New module app_java: Java Native Interface support.
+      nathelper: Decrease ambiguity by renaming sipping_disable_bflag to natping_disable_bflag
+      registrar: New set_q_override function
+      parser,modules/pv,modules/sipcapture: Improved parsing of P-Asserted/Preferred-Identity headers
+      Makefile.dirs: updated the list with module directories
+      NEWS Update with reference to Wiki
+      INSTALL update for release
+      README - last minute small edits
+      tm: set proper buffer len when Max-Forward header is not added
+      core: try to detect ipv6 addresses only when USE_IPV6 is used
+      pkg: deb specs updated for v4.0.0
+      INSTALL: updates for v4.0.0
+      ChangeLog_k: removed obsolete file
+      ChangeLog: updated content to prepare for v4.0.0
+      sca: fix regression dropping Expires header from SUBSCRIBE replies.
+      sca: move SUBSCRIBE response handling to sca_subscription_reply
+      sca: reject out-of-dialog attempts to seize privately held call.
+      sca: make sca_reply a generic reply function.
+      pkg/kamailio/(centos|fedora): added docbook2X build requirement
+      ...
     
-    - done when a new outgoing tls connection is opened
-    - ongoing work, to allow an option to drop the connection based on
-      config decision
-
-commit 9d9e7399b731c8546c2c58ca27971016f221baed
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon May 26 14:16:49 2014 +0200
-
-    core: option to specify whether the send info has to be set before sending out
+    Conflicts:
+    	modules/registrar/save.h
 
-commit 80f241b0b1e13021d3494aa7a489d313d6c03f5b
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon May 26 14:13:30 2014 +0200
+commit 7d46ff0e5487d9e925c78a57fd7ee036858f0c15
+Author: avamanu <avamanu at avamanu.(none)>
+Date:   Wed Mar 13 17:49:21 2013 +0200
 
-    core: added field to link sip msg in onsend structure
+    modules/permissions: DNS domain names in address table
     
-    - to be used when opening an ongoing stream (tcp/tls) connection
-
-commit ea56896eb36a8fffd96bb4ec1e5af4d5defa24d9
-Author: Konstantin Mosesov <ez at voipgroup.org.ua>
-Date:   Sat May 24 17:16:07 2014 +0400
-
-    Added app_java to modules list
-
-commit 815dbe7a4b0fa93380bf75bfb30afe5e174360c2
-Author: Konstantin Mosesov <ez at voipgroup.org.ua>
-Date:   Sat May 24 17:14:30 2014 +0400
-
-    Added requirements for modules app_python and app_java
-
-commit 379f2ae99385996a167495e9a3f5075d5de68baa
-Author: Konstantin Mosesov <ez at voipgroup.org.ua>
-Date:   Sat May 24 06:00:47 2014 +0400
-
-    New generated file
-
-commit e8f67102e75ed3ef310afe66849dee96e064f033
-Author: Konstantin Mosesov <ez at voipgroup.org.ua>
-Date:   Sat May 24 05:59:56 2014 +0400
-
-    Added application name in error description.
-
-commit 5bede9a9a77ad01e06d849485d6ce4274eca3fd4
-Author: Konstantin Mosesov <ez at voipgroup.org.ua>
-Date:   Sat May 24 05:58:19 2014 +0400
+    Added the possibility to check also against DNS domain names with
+    allow_address() function.
+    Now in the address table one group can have exact IPs, subnet IPs
+    and DNS domain names.
 
-    Fixed misstypes and indents in docs.
-
-commit 5a05370f35bdeb7277b2f53f5c3e95fb672d4024
+commit c5f47af145e19f11fafc3ca570e994185f33542d
 Author: Konstantin Mosesov <ez at voipgroup.org.ua>
-Date:   Sat May 24 05:57:16 2014 +0400
-
-    Fixed bug with JAVA_HOME detection.
-
-commit 8aa989618f79a0bd17a025b2f3ab38943fd6d6e5
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Fri May 23 18:06:03 2014 +0200
-
-    modules:ims_registrar_scscf: notify partial reg info body incorrect when q is set
-
-commit f10fd6f868df40f12f4c878c0321b414709d2c56
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Fri May 23 18:04:03 2014 +0200
-
-    modules:ims_registrar_scscf: fixed domain lockup when generating notifications if impu not found
+Date:   Wed Mar 13 17:53:54 2013 +0200
 
-commit 6a82057688023c2786809d8508217799c6d41c65
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Fri May 23 18:01:42 2014 +0200
-
-    modules:ims_registrar_pcscf:  added support for notification event deactivated
-
-commit 9b9d15875aa09a5574ff0754309f4f77161d3194
-Author: Carsten Bock <carsten at ng-voice.com>
-Date:   Thu May 22 21:07:17 2014 +0200
+    modules/app_java  - New module app_java: Java Native Interface support.
 
-    Core: Bugfix: Do not reset tcp_listeners: We may only listen on TCP.
-
-commit 1323d05b304d2f527ca67036b23beb5967d0e89a
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Thu May 22 14:52:43 2014 +0200
-
-    modules/ims_usrloc_pcscf: fixed bug, not fetching associated IMPUs from DB during preload of domain on startup
-
-commit 65e945a66fa0df8742b0af55d3cc56e28f36e1cb
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Wed May 21 21:51:11 2014 +0200
+commit 93b2b3ba7951bc84a208fb296b3c7b4e52516389
+Author: Richard Fuchs <rfuchs at sipwise.com>
+Date:   Tue Mar 12 09:43:57 2013 -0400
 
-    modules/ims_usrloc_scscf: Added ability to do AKA resync of auth vectors
-            - this functionality is required for AKA authentication between network and SIM should they get out
-                    of sync with each other re. sequence numbers
+    nathelper: Decrease ambiguity by renaming sipping_disable_bflag to natping_disable_bflag
 
-commit 8166802f171367fd3d60ac27cfeda3443c6f95b4
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Wed May 21 21:47:38 2014 +0200
+commit 857d35f827e0113d1e24caee1b137e91c3e30b42
+Merge: e84eedf 29f0779
+Author: Jason Penton <jason.penton at smilecoms.com>
+Date:   Tue Mar 12 13:05:19 2013 +0200
 
-    modules/ims_auth: fixed unlocking of usrloc hash slots
-    	- can cause deadlock
+    Merge branch 'master' of ssh://git.sip-router.org/sip-router
 
-commit eea7f9d04090a736c8a0f2b2a350c08635cc8e39
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed May 21 09:55:46 2014 +0200
+commit 29f0779226712f631eff5664f08cdada96f4eef0
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Mon Mar 11 17:37:12 2013 +0000
 
-    core: allow listening on tls without listening on tcp
+    registrar: New set_q_override function
     
-    - reported in FS#425
-
-commit 196c65fdc5d2526d3c777b22ec37eef200cd08ae
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Tue May 20 13:47:44 2014 -0400
-
-    dispatcher: ds_select_dst/domain can take args as string (not only int)
-     - internal converion of string->int (if possible)
-
-commit 8a334551001bdd658b39901c43fc12fe89c82b5a
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Tue May 20 13:45:40 2014 -0400
+    The set_q_override function will override the value of the q parameter
+    from the Contact header in subsequent calls to the save() function for
+    the current request.
+    Currently exported as a C-API function
 
-    sr_module: new fixup function: get_is_fparam()
-     - retrieve parameter value as string or/and integer (if possible)
-
-commit d931ce355d994fbd12c7c60d766ff0d12c4829d0
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue May 20 16:14:32 2014 +0200
+commit 09441e89d3bb10d7a4b8c0192e429a8ca1827461
+Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
+Date:   Mon Mar 11 16:55:23 2013 +0000
 
-    kex: count unsupported methods only for SIP requests
+    parser,modules/pv,modules/sipcapture: Improved parsing of
+    P-Asserted/Preferred-Identity headers
     
-    - reported by Juha Heinanen, FS#432
-
-commit 365a60772de9c1d2f19ecf52b12f6d75b348e996
-Author: Juha Heinanen <jh at tutpro.com>
-Date:   Tue May 20 16:22:58 2014 +0300
-
-    modules/siputils:  generate error message if parsing of is_gruu() uri fails
-
-commit a313a8d33afdee6c7eb70cd57161aef8e70c5bcf
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue May 20 09:16:01 2014 +0200
+    parser:
+    - Abstracted addr-spec parsing from parse_to.c into new file.
+    (parse_addr_spec.c)
+    - Added support for comma separated addr-spec values.
+    - Created new P-Asserted-Identity and P-Preferred-Identity header parsers
+    that parse all instances and allows comma separated values.
+    modules/pv:
+    - Added PV index to $ai, $pu, $pU, $pd and $pn variables to retreive the
+    n'th URI instance. E.g. $(ai[1])
+    modules/sipcapture:
+    - Updated to use the new structure
+    - Maintains previous behaviour - only uses the first URI
 
-    core: print number of parameters used for searching cfg function
-
-commit a80a8b2366282f967263507be47727aa3417d67d
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue May 20 08:46:04 2014 +0200
-
-    sdpops: added note about dtmf and telepheone-event to docs of spd_keep_codecs_by_name()
-
-commit e6b7ec384211475d9f8ce7c468d44c90c1521059
-Author: Juha Heinanen <jh at tutpro.com>
-Date:   Mon May 19 12:16:58 2014 +0300
-
-    modules/kex: fixed type of stats.get_statistics result
-
-commit d81fd1bf067b78b55ad348db2531c4ba9b10dddb
+commit c72aabf37beb308f99b46f764ee9c01b0d875da3
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon May 19 08:56:38 2014 +0200
-
-    dialog: add wait-for-ack callback before response unref
-    
-    - in case of a sipral for ending in a negative response from initial
-      state, ack to second iteration can unref prematurely the dialog
-    - reported by Pawel Sternal, FS#427
-
-commit 9ab3aa5d6104fb0b22ee25b8a423b48edc548f74
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Tue Mar 18 11:18:56 2014 +0100
-
-    textops: Refresh README
+Date:   Mon Mar 11 15:57:31 2013 +0100
 
-commit 2be579ffa48c1445a5c768b4a9b6a6532ac58363
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Sun Mar 16 10:04:38 2014 +0100
-
-    textops: add new multipart functions documentation
+    Makefile.dirs: updated the list with module directories
 
-commit a9d5d28b8b750b06736b78680da66cfbd3d67e69
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Fri Mar 21 21:59:41 2014 +0100
+commit 697a272672e434b017cd7e3c6782c5cefa0f2de8
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Mon Mar 11 11:43:49 2013 +0100
 
-    textops: functions to convert, append and remove multipart bodies
+    NEWS Update with reference to Wiki
 
-commit 8f007d20933f1d1deaac1c9c5ece9be2a4b9987c
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Fri Mar 21 21:56:04 2014 +0100
+commit 220b782018c3158a05f695eac5b1bff0f7ad239f
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Mon Mar 11 11:36:54 2013 +0100
 
-    core: add check_boundaries() to build_req_buf_from_sip_req().
-    
-    This checks and fixes the boundaries of a multipart body if the
-    FL_BODY_MULTIPART flag is set.
+    INSTALL update for release
 
-commit 802771362eee707ecb55c2a907f96d2dbaff620e
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Mon Apr 28 16:20:57 2014 +0200
+commit 0bdc78ffb5e4a2f4d77df39372dad66cdf3c141d
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Mon Mar 11 11:16:09 2013 +0100
 
-    core: add str_append helper function
+    README - last minute small edits
 
-commit c36f326d3c7372b149592d438df75f3d7b0a0233
+commit 2d38b046b6202a35c0adf4c8b61f0d665432dd4f
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sun May 18 19:07:38 2014 +0200
+Date:   Mon Mar 11 09:38:37 2013 +0100
 
-    mtree: replace tree structure even there are no records in db table
+    tm: set proper buffer len when Max-Forward header is not added
     
-    - reload didn't replaced old tree if no records in db table
     - reported by Juha Heinanen
 
-commit 7992a2b8d42bb7e8bcf1738cf042013ed126a47a
+commit b035aa9f2cc19d387b1b8f33a7888ffee27a4138
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu May 15 13:59:03 2014 +0200
+Date:   Sun Mar 10 23:53:26 2013 +0100
 
-    siputils: allocate enough space to hold ending zero for tel uri in tel2sip()
+    core: try to detect ipv6 addresses only when USE_IPV6 is used
     
     - reported by Juha Heinanen
 
-commit 2e55d7bd218c9f954da7d289ec1be090bb4d88b0
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu May 15 12:48:04 2014 +0200
-
-    core: use port 5061 for checking self when uri has transport tls
-    
-    - 5060 was used, failing to match myself condition
-
-commit 1d90f4de94dfc887cc6129624fd5e6ad989abd37
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu May 15 12:46:14 2014 +0200
-
-    topoh: match on all ports if none is in the uri for checking self
-    
-    - forcing default 5060 can fail for multi-listen case and tls
-
-commit 7134959725011baa504a027c4561e0054dd907ae
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed May 14 23:37:54 2014 +0200
-
-    kamcmd: proper size for memset, based on malloc
-
-commit 1cefc0c5f83eb4b7b6ffefc6ab383d7aae6de07f
+commit a349d9aab2d95b9b1cbc58870ead9a7294bcdcaa
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed May 14 23:28:24 2014 +0200
+Date:   Sun Mar 10 22:46:50 2013 +0100
 
-    parser/sdp: assign stream var only if session is not null
+    pkg: deb specs updated for v4.0.0
 
-commit 71332ed9ce59de50de04c940fd600b50b1f1dc80
+commit b4ebc4a8164cfee995fb3ed0570702ae0547c0ce
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed May 14 23:19:05 2014 +0200
+Date:   Sun Mar 10 22:07:11 2013 +0100
 
-    rls: free item in case of duplicate when trying to add to str list
+    INSTALL: updates for v4.0.0
 
-commit 4f2da3e025fa281f88e80bb841a51d6546219ae8
+commit ff04edd6ee7ddc213b346afffeec04a995bf16fa
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed May 14 23:12:33 2014 +0200
+Date:   Fri Mar 8 23:22:06 2013 +0100
 
-    rls: proper header define guard and check of null returned value
+    ChangeLog_k: removed obsolete file
 
-commit e53c715c74fb5b58f4f68b81acb60de66b19b8cc
+commit 28111e7943f209ed936a6e9f1d5278d6235cedbb
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed May 14 23:08:06 2014 +0200
+Date:   Fri Mar 8 23:20:06 2013 +0100
 
-    ipops: free dns pv structure on invalid pv name
+    ChangeLog: updated content to prepare for v4.0.0
 
-commit 74743d6ef3bf74c1226ba5a1b6bebfbe19b06b93
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed May 14 23:03:19 2014 +0200
-
-    db_flatstore: free result before returning null on no more pkg
-    
-    - partial allocation when doing an incomplete new connection
-
-commit ace56c6bd2221920b965185c1c9a5997cd3f2768
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed May 14 22:56:37 2014 +0200
-
-    core: free previous allocated variable if no more pkg to build rve struct
-    
-    - cleaner shut down if not enough memory at startup
-
-commit f1a09e44268c77641216a78878f2c73c6e5a4d66
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed May 14 22:53:35 2014 +0200
-
-    pv: proper length for line transformation when handling last line of value
-
-commit 661bcef49ba3be944ba215b8a379256e3fe94a60
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Wed May 14 17:00:30 2014 -0400
-
-    dispatcher: expand attrs while running rpc command dispatcher.list
-
-commit 6cc1f4101ce4a9db25865afc5ac19c3f6578889b
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Wed May 14 16:07:24 2014 -0400
-
-    dispatcher: fix weight attr comparison
-
-commit 4f4641ea2a4018a72558c40d4878e9af7053be2d
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed May 14 09:58:50 2014 +0200
-
-    presence_dialoginfo: get rid of unused variables warning
-    
-    - priority and winning_priority are used in an alternative winning node
-      selection which is disabled now
-    - reported by Jua Heinanen
-
-commit e39a90e11bfed2b4445c37db1532488aa9e3e725
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon May 12 22:54:54 2014 +0200
-
-    dialog: if sending BYE fails at timeout, unref dialog
-    
-    - destroy dialog structures
-
-commit 6c02bdb04d6e214728c13c6222e347783b66337b
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Mon May 12 23:06:09 2014 +0200
-
-    pkg/kamailio/deb: append pkg-config as Build-Depends
-
-commit 5ab17c022b5bab6dfd3749dee71961cad14cbe83
-Author: Carlos Ruiz Diaz <carlos.ruizdiaz at gmail.com>
-Date:   Sun May 11 22:08:43 2014 -0500
-
-    cnxcc: Added credit vs cost per second check *before* starting the call
-
-commit 4460dce0e2fff775d6cf7328008c6cf6270537cd
-Author: Vitaliy Aleksandrov <vitalik.voip at gmail.com>
-Date:   Thu May 8 15:01:02 2014 +0100
+commit 3b557293a33f6f3003fdd62a45e02cf8736b534e
+Author: Andrew Mortensen <admorten at isc.upenn.edu>
+Date:   Mon Mar 4 23:13:53 2013 -0500
 
-    websocket: Fix crash in websocket module
+    sca: fix regression dropping Expires header from SUBSCRIBE replies.
     
-    - Avoid race condition by maintaining a connection reference count
-    - Fixes FS#406
+    - extra_headers.len lacked Expires header length after snprintf.
 
-commit feba7dd8e09a3b8c9f781b95b16c1b708fce4195
-Author: Juha Heinanen <jh at tutpro.com>
-Date:   Thu May 8 15:24:51 2014 +0300
+commit d528c27b6fa69530bfde4a6ce83c5d4dcc6499a5
+Author: Andrew Mortensen <admorten at isc.upenn.edu>
+Date:   Sun Mar 3 17:01:53 2013 -0500
 
-    modules/utils: http_query now stores result also in case of 4xx replies
+    sca: move SUBSCRIBE response handling to sca_subscription_reply
     
-    - Applied patch by Mikko Lehto.
+    - create necessary headers, pass to newly generic sca_reply function.
 
-commit 7a827a612f93b9dd938f9b78c0de3ac2d98a0c77
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu May 8 08:40:28 2014 +0200
+commit e565748048d7a6b6fda0a28959e092380c5bc26a
+Author: Andrew Mortensen <admorten at isc.upenn.edu>
+Date:   Sun Mar 3 17:00:44 2013 -0500
 
-    presence_dialoginfo: interetate through all 'dialog' nodes of xml document
+    sca: reject out-of-dialog attempts to seize privately held call.
     
-    - PUBLISH request can carry info for many dialogs
-    - reported and patch by Klaus Feichtinger
+    - per spec, reject with 403 Forbidden.
 
-commit 2b2569ea4e4d2af817e8e021408d551a99572f59
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat May 3 23:44:22 2014 +0200
+commit d6d71b0e217226fe43491a0e9ba75ec0a6649cd5
+Author: Andrew Mortensen <admorten at isc.upenn.edu>
+Date:   Sun Mar 3 16:59:23 2013 -0500
 
-    core/mem: f_malloc - simplified join in realloc
+    sca: make sca_reply a generic reply function.
     
-    - restore proper usage counters
-
-commit a7d59baca2d03b48f020b10adf6e6e614494a35e
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat May 3 22:13:16 2014 +0200
-
-    core/mem: f_malloc - groupped few updates of usage stats in insert free function
-
-commit b14bfbfd85e9cc112d15e7b01728e4197bb48353
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Sat May 3 21:50:15 2014 +0200
-
-    pkg/kamailio/deb: update version to 4.2.0~dev6
-
-commit d12ac993176f4282b6a740490fd9c645132c98e7
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat May 3 21:36:28 2014 +0200
-
-    kex: remove debug message added in previous commit
+    - take a pre-filled extra_headers parameter instead, add with add_lump_rpl.
 
-commit 8c2888fcd33bee45cb4654222da619e70ed44ecc
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat May 3 21:06:34 2014 +0200
-
-    mem/q_malloc: free old pointer if allocation in realloc fails
-
-commit 41a37b570758445d723d4d78b9786f8e6cb5722c
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat May 3 21:03:34 2014 +0200
-
-    mem/f_malloc: free old pointer if allocation in realloc fails
-
-commit 3dda7122eb3d875fa318816524c4a6741b7997a8
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat May 3 20:56:19 2014 +0200
-
-    Makefile.defs: version set to 4.2.0-dev6
-
-commit ace9adb04ad75aa7f35d951c966c614b7e4f60b8
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat May 3 20:52:53 2014 +0200
-
-    Makefile.defs: memory manager set to f_malloc
-
-commit 4eae467f30cc1075272a8357e67783aab363a150
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat May 3 20:52:06 2014 +0200
+commit dd2ef87af7dac6fb1411d58a0dd2e6125b99da80
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Thu Mar 7 02:11:35 2013 +0000
 
-    xmlrpc: removed unused variable in rpc_array_add
-    
-    - reported by Juha Heinanen
+    pkg/kamailio/(centos|fedora): added docbook2X build requirement
 
-commit aac0c2119644c3e5578e979f6471acc3c0cbbf50
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat May 3 20:10:00 2014 +0200
+commit df1af285d60e2d066c2753e8f3815a7dc4f97684
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Wed Mar 6 11:08:32 2013 +0000
 
-    core/mem: f_malloc updates for pool type and refactoring of parts
-    
-    - removed define on statistics, it was always on for the past several
-      years - the code is cleaner
-    - total free fragements is kept in root memory block to avoid computing
-      it at runtime by walking hash slots
-    - attempt to join fragments when a malloc fails to reuse existing
-      fragments - should help when mem_join is 0, being very fast up to the
-      moment of an out of memory, when does the attempt of joining
-    - pkg stats updated to use the single event callback at the end of
-      malloc, free or realloc operations
+    pkg/kamailio/(centos|fedora): re-added perl files
 
-commit e67052535020fa01156219add2c8c2b7931bce26
+commit f4a4ad8effe41a30705a49da3097818c83d3be6e
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat May 3 20:07:41 2014 +0200
+Date:   Tue Mar 5 18:35:08 2013 +0100
 
-    core/mem: q_malloc updates to set pool type and pkg stats refactoring
+    Makefile.groups: fixed typo in the name of perl mods list
     
-    - total free fragments are kept in memory root block to avoid computing
-      them by walking the hash table
-    - use single event callback to update per process pkg stats, executed at
-      the end of malloc, free or realloc opperations
+    - reported by Peter Dunkley
 
-commit 8b1cef2c8844e6b89e23f93ceb33278977adaa13
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat May 3 20:05:32 2014 +0200
+commit 3262a99d41a16b478f7186be6334dce901ddc25c
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Tue Mar 5 17:08:54 2013 +0000
 
-    kex: use the new pkg update stats event callback
-    
-    - print total size and total free fragments for each process
-    - should solve the issue when values of pkg stats were innacurate
+    pkg/kamailio/(centos|fedora): updated .spec to match latest changes
 
-commit 91b3628fe41021a593c63e1e6aad0e91ffb64eb2
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat May 3 20:05:12 2014 +0200
+commit 76aa97c074ddbdd82217633ff4fb0c6401d1666f
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Tue Mar 5 15:53:46 2013 +0000
 
-    core/mem: ll_malloc initialization updated to be able to set pool type
+    pkg/kamailio/(centos|fedora): updated rel and ver in .spec
 
-commit 5baa85b048032c2b07c066fbe19d944d2cae1dee
+commit 49251e62da99bf05f257e12306cafec614feb408
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat May 3 20:04:34 2014 +0200
+Date:   Tue Mar 5 17:11:51 2013 +0100
 
-    core/mem: sf_malloc initialization updated to be able to set pool type
+    Makefile.groups: mi_xmlrpc has a dedicated pkg grpup depending on xmlrpc-c library
 
-commit bccf5cd079827965cfaf9b5c9864213e368db135
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat May 3 20:02:47 2014 +0200
+commit 98be8f70d4df6011991d04b5c0d86a1aac6a0737
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Tue Mar 5 12:09:42 2013 +0100
 
-    core: repaced the two pkg update event callbacks with one
+    db_sqlite Make sure module compiles on BSD systems too
     
-    - simplified usage as can be executed at the end of memory operations
-      (malloc, free, realloc)
+    Copied from db_unixodbc/Makefile
 
-commit c996d5ddc947d05670b89215aa1c3169fd1d1dda
+commit 6375044137494f1203f26580e16f63c92225c596
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat May 3 20:02:06 2014 +0200
+Date:   Mon Mar 4 23:41:31 2013 +0100
 
-    core/mem: set shm type when initializing shared memory pool
+    Makefile.groups: restored outbound as packaging group
 
-commit 8ef30f91ba2a03097cb5ce717cebee4cb29c069d
+commit 068e6e5903801ca7cb7d1ca304d35bca70a34b58
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat May 3 20:01:23 2014 +0200
+Date:   Mon Mar 4 19:56:54 2013 +0100
 
-    pkg/mem: set pkg type when intializing memory pool
+    usrloc: added missing state from AoR contact dump
 
-commit ffa1beb6bb04dde73841ca076e3627dfe297305e
+commit d83b9aefd5afa25b2d18a8bf92357fbd33d627bf
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat May 3 19:57:19 2014 +0200
+Date:   Mon Mar 4 16:30:34 2013 +0100
 
-    core/mem: define internal types for pkg and shm pools
+    dispatcher: release lock instead of destroy when cleaning active calls hash table
     
-    - to allow easier identification when doing operations over mem block
+    - this could happen when dispatcher list was reloaded
+    - reported and fix by Dmitry, closes FS#275
 
-commit 62a9e6f671c207f1e200f903784558fd317f8a8c
+commit 1d0e8dd793b3bab7f42ad8e956a704c6f287a6e1
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat May 3 11:45:34 2014 +0200
+Date:   Mon Mar 4 16:20:13 2013 +0100
 
-    Makefile.defs: compile with debugging symbols when using clang
-    
-    - added -g parameter to be on pair with gcc
+    Makefile.defs: version set to 4.1.0-dev1
 
-commit 4e7f95bf315ba4d058ba039a62290b056cf503bf
+commit 3cf821d9983418d68ca33edc35ff5eb2e592d16f
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat May 3 09:18:40 2014 +0200
+Date:   Mon Mar 4 16:19:20 2013 +0100
 
-    mem/f_malloc: link previous free fragment to speed up join
+    Makefile.groups: refer to pkg groups instead of K
 
-commit 892a24f7256e60e2a0116655e0052c284479b7d2
+commit 09c7b67beee9529d6a7c06e600c7f294bf453eda
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri May 2 23:58:12 2014 +0200
+Date:   Mon Mar 4 16:14:42 2013 +0100
 
-    mem/f_malloc: check returned pointer for bitmask index
+    db_postgres: handle prepare statements in DB APIv2
     
-    - if null, reset slot and search on bigger chunks slots
-
-commit d3d2c582cd518ddac61ec005ecfffce12450563e
-Author: Juha Heinanen <jh at tutpro.com>
-Date:   Sat May 3 17:30:26 2014 +0300
-
-    modules/sdpops: turned two sdp_with_ice() INFO messages to DBG messages
+    - patch by  Markus Bucher, closes FS#272
 
-commit bb3eed8aabea9f63c9922f71714aea242771db02
+commit b5024f320b578c831d3ee13b077bb87954bc61b0
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri May 2 21:50:14 2014 +0200
+Date:   Mon Mar 4 16:09:36 2013 +0100
 
-    dialog: copy dlg var value locally on get operation
+    Makefile: updated the groups of modules
     
-    - reference to shared memory exposes risk on accessing an invalid
-      pointer if anothe process updates it
-    - reported by Dragos Oancea
-
-commit c56ccc8d156dcf01be7debe528d8572a82b43fad
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Fri May 2 12:15:53 2014 +0200
-
-    modules/ims_registrar_scscf: fix to remove subscriptions when UE explicitly deregisters
-
-commit f149fe0bf499c2ed9a4238cea5bdf2ecbb28c941
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Fri May 2 12:15:05 2014 +0200
-
-    modules/ims_registrar_scscf: Fix to not send notifies to UEs that explicitly deregister
-
-commit 5f49f1ab481ef4c8b9fc236d905485390969f894
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Fri May 2 12:14:00 2014 +0200
-
-    modules/ims_registrar_scscf: added mod_param ue_unsubscribe_on_dereg
-    	New mod param ue_unsubscribe_on_dereg: for UEs that do no send UNSUBSCRIBE for reg event when deregistering
+    - they are kept in Makefile.groups to keep main Makefile cleaner
+    - most of modules are in lists groupped mostly by dependency
+    - compilation and packaging groups are build using the lists
+    - exclude_modules list is automatically built from all modules without
+      those part of lists with external dependencies
 
-commit 450f78a13a2a762b87a8200d64ddf873d4253808
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Thu May 1 09:09:49 2014 +0200
-
-    modules/ims_qos: switch flow descriptors. point of reference from NW persepcitve and not UE
-
-commit b834cde74f8a4b41ec24ceb8332adff8bb3922bb
+commit 01cbe8bf98d6ad1ef8cf7e0b9f646fde81831fc6
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Apr 30 21:46:55 2014 +0200
+Date:   Mon Mar 4 10:46:01 2013 +0100
 
-    core: compute the len for dns srv name
+    Makefile.defs: -DWITH_AS_SUPPORT is on by default
     
-    - fixes dns srv for cache, reported by Rob Eijgenraam, FS#426
-
-commit 1d8215d82038db81b82e449b93aaea40d07cadca
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Wed Apr 30 10:43:58 2014 +0200
-
-    modules/ims_qos: port in flow control media sub component is clipped becuase of lack of space in buffer for nul terminator
-
-commit 658aabd74b8da2c6ecc1337be0f26007a64daef9
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Apr 29 23:02:08 2014 +0200
-
-    pipelimit: if db url or table name are empty, skip loading pipes from db
-
-commit 6ef0bf9e6594e672f7959b5ed3f23474387091b4
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Apr 29 22:52:38 2014 +0200
-
-    pipelimit: docs updated with hash_size parameter and pl_check() changes
+    - it was for kamailio flavour only
+    - can be disabled with WITHAS=0 and exclude_modules+=seas
 
-commit 4c651606eb9f432404846047e19149a3710a6db3
+commit 23a22e2c8d73843798d66ec1bebe22cf7702213b
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Apr 29 22:43:27 2014 +0200
+Date:   Sun Mar 3 23:53:14 2013 +0100
 
-    pipelimit: added hash_size parameter
+    Makefile: split module groups definitions in Makefile.groups
     
-    - can be used to set the number of slots for the internal hash table,
-      which is computed as 2^hash_size (aka 1<<hash_size)
-    - default is 6 (2^6 = 64 slots)
+    - the part was quite big and it is more config related than build rules
+    - it has to be updated with the current list of modules
 
-commit c1ab03dd1f1d9166df0df1f20e61db0f47ffd37b
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Apr 29 22:35:46 2014 +0200
+commit 522d06e75bf3c549af007701332f7db53a1b5ab6
+Author: Andrew Mortensen <admorten at isc.upenn.edu>
+Date:   Thu Feb 14 16:55:36 2013 -0500
 
-    pipelimit: added pl_check(pipeid, alg, limit)
+    sca: fix race condition when two endpoints seize same index simultaneously
     
-    - when alg and limit parameters are given, pl_check() creates the pipe
-      if it doesn't exists
-    - if exists, then no change is done to existing pipe (alg and limit are
-      not changed)
+    - return 480 Temporarily Unavailable to loser of race.
 
-commit da199e1978313b39553e9fb62012fe55cfd186d8
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Apr 29 21:59:53 2014 +0200
+commit 7c940fa74dd0d39d798b5ed63edf8079f24f2bde
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Sat Mar 2 16:25:24 2013 +0100
 
-    pipelimit: moved log messages out of lock
-    
-    - free allocated cell if the algorithm is invalid
+    pv Minor doc update
 
-commit 159978cf2a98748f3225155d8946bcbd768b51e3
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Apr 29 20:02:19 2014 +0200
+commit ab1d5bf573b43daf204eb1572083c8f12791a3e1
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Sat Mar 2 15:53:08 2013 +0100
 
-    rtmier: reset avps and xavp lists after route blocks execution
-    
-    - avoid leaks if someone is using avp/xavp with rtimer - there is a fake
-      message used there, thus not the normal sip message routing that
-      resets avps/xavps
+    pv Add RPC commands shvGet and shvSet to manipulate and list shared variables
 
-commit 25a0534b11b5585eafa579d0ea3760438afd4ef7
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Apr 29 00:12:16 2014 +0200
+commit 68094dd3639d1f4cc497e4affb1a89909947c7b3
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Sat Mar 2 09:41:18 2013 +0100
 
-    textopsx: msg_apply_changes() returns error if record route was added
+    presence Add RPC command presence.cleanup
 
-commit 79a01b9df71bdc4329ee14e29d5c5ef230116bd2
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Apr 29 00:05:16 2014 +0200
+commit c2c4c393a3c68ed3fb6fd53a71febdd93398f77c
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Sat Mar 2 07:56:48 2013 +0100
 
-    core: new internal msg flag added - FL_RR_ADDED
+    cfgutils  Add functions for checking if a route exists
     
-    - marks a sip request when record route is added
-
-commit cc84b46d473236d162a852c3604eacfc88e56ba2
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Apr 29 00:01:53 2014 +0200
+    Adding check_route_exists() and route_if_exists() functions.
 
-    rr: use internal msg flags to mark a request with record route added
-
-commit 0dc5f4bcc7c95bffed4855cba537ccf8a1cad876
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Fri Mar 21 21:52:03 2014 +0100
+commit 0d69ffe84069e9cd9e41de194cbeff002e3d31b9
+Author: Olle E. Johansson <oej at edvina.net>
+Date:   Sat Mar 2 07:56:21 2013 +0100
 
-    parser: add internal flag FL_BODY_MULTIPART
-    
-    This will be set if the body has been converted to multipart/mixed
-    or a new part has been appended to it. This will trigger the core
-    to check and fix the boundaries of the body.
+    cfgutils documentation
 
-commit 8fcdd23aaa49cb6c1ecb34c4c6b4a88078a860f7
+commit b23510e0adb6060a257c8662700450ed7faef080
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 28 13:51:56 2014 +0200
+Date:   Fri Mar 1 18:12:23 2013 +0100
 
-    acc: no request is needed for setting end time on dialog termination
+    rtpproxy: proper fixup function for rtpproxy_manage(...)
     
-    - callback function cdr_on_end() doesn't use it at all
-    - reported by Eduardo Lejarreta, FS#256
-
-commit d28c4043637169c4e90f638102c1f4dfa06716f2
-Author: Juha Heinanen <jh at tutpro.com>
-Date:   Mon Apr 28 12:15:54 2014 +0300
-
-    modules/sdpops: added sdp_with_ice() function for checking if sdp
-      contains ICE candidate attribute(s)
-
-commit e4792b84483c6299d096477007b1d3f54f992c67
-Author: Juha Heinanen <jh at tutpro.com>
-Date:   Mon Apr 28 12:08:42 2014 +0300
-
-    modules/pv: use just a comma as header delimiter
+    - second parameter was resolved as spve type, although fixed as str
+    - reported by  Markus Bucher, FS#273
 
-commit f9d95734ba7c04a0188077914161395c2e94f3eb
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 28 09:51:42 2014 +0200
+commit 71c197dfe0b787a2abeadb730fda5241f294237c
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Fri Mar 1 11:41:18 2013 +0000
 
-    pipelimit: run timer at 1000ms
+    modules/registrar: updated module documentation
     
-    - proper execution on timer_interval
-    - reported by Julia <juliabo at gmail.com>
+    - Added ruid parameter to unregister
+    - Added missing attributes to $ulc() description
 
-commit d0f0ba702bd44524bc9f52e07341db03267b15f7
-Author: Carlos Ruiz Diaz <carlos.ruizdiaz at gmail.com>
-Date:   Sun Apr 27 21:22:49 2014 -0500
+commit 0a919692b299e2eb819f7c97fa218189849d4566
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Fri Mar 1 11:19:42 2013 +0000
 
-    cnxcc: fixed deadlock when call gets terminated under certain conditions
+    modules/registrar: added additional unregister() exported function to allow the removal of a specific contact
     
-    - fixed some indentation problems introduced by Eclipse IDE
-
-commit c3386295d7607a58d37a65b6822bf5f98b3fefa0
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Apr 24 18:02:34 2014 +0200
+    - Contact is removed by using the ruid (unique ID for the location record)
+    - Getting the ruid to use here is a problem still to be solved.
 
-    drouting: removed old contraint on route index
-
-commit 94d5ace90a10bbbb08576f891c9bb90d583e55d4
-Author: Carsten Bock <carsten at ng-voice.com>
-Date:   Thu Apr 24 12:04:41 2014 +0200
-
-    Updated example configurations for IMS:
-    - use NAPTR query (comment from Franz Edler & Andrea Meroni on sr-users)
-    - Rx (P-CSCF) is now asynchronous
-
-commit d1b3dd1abacd98c1cb42978448fc7a20630459ea
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Apr 23 23:09:20 2014 +0200
+commit 65dc9c8cf35fc3e631380d65e8c99e8f84d465cc
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Thu Feb 28 14:40:41 2013 +0000
 
-    dispatcher: refactored rpc command dispatcher.list to give proper xmlrpc output
+    modules/registrar: RFC 5626 section 6 support
     
-    - sets and destinations within sets are printed as an array of
-      structures
+    - Behaviour when outbound in use but first edge proxy does not
+      support it.
 
-commit 72a52d2cbd76eb47e832551ab46bcd6b93e7c203
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Apr 23 23:07:21 2014 +0200
+commit abc1e61dea4e96235ca54955f664effc66568d6d
+Author: Richard Fuchs <rfuchs at sipwise.com>
+Date:   Wed Feb 27 11:17:03 2013 -0500
 
-    xhttp_rpc: added handling for specifier '['
+    nathelper: add new option sipping_disable_bflag
     
-    - add array into rpc result
-    - new rpc api member aliased to rpc_struct_add (needs update for proper
-      array value insertion)
+    sipping_disable_bflag can be set on a per-registration basis
+    to disable NAT pings completely
 
-commit 1a01a1bf5d8cf8659af87898f9b02236997f19cb
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Apr 23 23:04:53 2014 +0200
+commit aabb7adb933185f4bc12dcd82cdee357246c8c2f
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Wed Feb 27 15:29:35 2013 +0000
 
-    xmlrpc: implemented specifier '[' for array
+    modules/registrar: add Require: outbound to 200 OK when required by client and supported by server
     
-    - it is only for add operations (no scan)
-    - implemented new rpc member array_add
+    - Reported by @oej
 
-commit 9a404279c9e4d07795c82848795622f5f0da0ca2
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Apr 23 23:03:10 2014 +0200
+commit 936b6892a8a0ff25b108635e48a146b7cbc3a7ff
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Wed Feb 27 14:03:27 2013 +0000
 
-    ctl: init binrpc callbacks in mod init and implement '[' specifier
-    
-    - '[' allows adding an array
-    - implemented rpc api member array_add
+    lib/kcore: added parser for Require: header
 
-commit fa9d76128f0e20384a800c7c741365680d6eb799
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Apr 23 23:01:07 2014 +0200
+commit be95ad30bf92cce4611f41e7d52d7a12f557e863
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Wed Feb 27 14:03:13 2013 +0000
 
-    ctl: fifo server implementation was lacking adding struct values
-    
-    - specifier '{' was not handled for adding values
-    - implemented adding array with '[' specifier
-    - array_add aliased to rpc_struct_add for the moment
+    parser: updated for parse_supported refactoring
 
-commit 83247604e8c79b2df8c1e80347a96201e31d49ba
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Apr 23 22:59:22 2014 +0200
+commit 167283826a4b534bc68d96e5e8eb6bc686a6d293
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Wed Feb 27 14:02:47 2013 +0000
 
-    core: new rpc api to add values in an array
-    
-    - memeber named array_add
+    modules/sst: updated for parse_supported refactoring
 
-commit 5943a8005baf8ce1239d2cf728373cb26975483a
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Apr 23 22:12:48 2014 +0200
+commit 35e981d6c22bf4a5326cad34c2f2aa0d45d77e08
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Wed Feb 27 14:02:28 2013 +0000
 
-    tm: reset local lock reply status after functions that do unlock
+    modules/rls: updated for parse_supported refactoring
 
-commit c9aa1aab82c807e37b870787f6b56c88b067ddf1
-Author: Juha Heinanen <jh at tutpro.com>
-Date:   Wed Apr 23 16:45:49 2014 +0300
+commit 6c24a8dfa84d1e92fdd53e4c8c2bd7bc1715ceb5
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Wed Feb 27 14:02:05 2013 +0000
 
-    modules/rtpengine: documented 'force_relay' ICE flag value
+    modules/registrar: updated for parse_supported refactoring
 
-commit 9a07154c0fd8bde372bd1c8b5967b413d11a13c9
-Author: Juha Heinanen <jh at tutpro.com>
-Date:   Wed Apr 23 09:33:13 2014 -0400
+commit 2855d20641d171ffcf3e711292cc8648d74ce5b0
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Wed Feb 27 14:01:18 2013 +0000
 
-    rtpengine: support ICE=force_relay flag
-    
-    author: Juha Heinanen <jh at tutpro.com>
+    modules/ims_registrar_scscf: updated for parse_supported refactoring
 
-commit 67fa31e3f01c4d70ad9561949bca4aaa230d0f46
-Author: Elena-Ramona Modroiu <ramona at asipto.com>
-Date:   Wed Apr 23 09:53:41 2014 +0200
+commit af75f69a581e19f8008c326f882aae0f65f86ea8
+Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
+Date:   Wed Feb 27 13:59:56 2013 +0000
 
-    htable: set RET_ARRAY flag for rpc commands returning more than one value
+    lib/kcore: abstracted the option-tag parsing code out of parse_supported.[ch]
     
-    - fix failure in xmlrpc parsing
+    - This is to make it easier to add parsers for other similar headers
+      (for example, Require:)
 
-commit fe9c519ca6ef6625f0b0d9c7027158641c636087
+commit 9f9b56088e706970bab2ab644a51d267fabcae6c
 Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Apr 22 20:51:31 2014 +0200
+Date:   Wed Feb 27 09:22:14 2013 +0100
 
-    sercmd: refactored reading the rest from socket on reply too long
+    Makefile.defs: version set to 4.1.0-dev0
     
-    - patch by by Savolainen Dmitri, FS#422
-
-commit 5712eb5fdfa498a1678a7a2c01ddbaeff0458d35
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Apr 22 17:19:43 2014 +0200
-
-    mtree: shift values for reload count and time from temporary structure
-
-commit 731685fc58ac2a650ed79cdc27a0b0f6d8599994
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Apr 22 17:11:52 2014 +0200
-
-    mtree: store reload count and timestamp for trees
-    
-    - print these details via mi/rpc summary command
-    - count is not stored when reload many tables from one table (cannot
-      easily get reference to the previous loaded tree structure)
-
-commit 148d67a8de1524b88b6b3f957baf51e34342e7c8
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Apr 22 16:58:58 2014 +0200
-
-    mtree: return 404 if mtree is not found for rpc mtree.summary
-
-commit 1b234185fd8ac87a7431d189eb83b702c5618404
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Apr 22 16:41:14 2014 +0200
-
-    xmlrpc: don't generate internal xmlrpc reply for optional parameter read
-
-commit 31feee65720cbf0bf8a87a5989360f336ac9fdd4
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Apr 22 16:29:51 2014 +0200
-
-    xmlrpc: fixed optional parameter read handling
-
-commit 910224d3d55ee225628e57e8da8fbff648cd7977
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Apr 22 16:07:28 2014 +0200
-
-    mtree: docs updated for mtree.summary
-
-commit 40e9b5b3238e65c14ad6c4d1be0cb3e0c779c642
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Apr 22 16:06:32 2014 +0200
-
-    mtree: rpc mtree.summary can take as parameter the name of the tree
-
-commit 546dbde191dfb752abde2cd5a4a7cf9955a31768
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Apr 22 15:56:30 2014 +0200
-
-    mtree: rpc mtree.summary returns an array to comply with xmlrpc format
-
-commit 2e8ff29fd33ccb6f2da609bec638dbd2d457be08
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Apr 22 13:01:41 2014 +0200
-
-    xmlrpc: keep pkg for sip message related ops
-
-commit 5b4879495b0b1f0c61b7cbd3c48da964f4d79be4
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Apr 22 12:35:40 2014 +0200
-
-    xmlrpc: added guardian define for http.h and fixed usability by defaulting to system malloc
-    
-    - with pkg the module is barely usable due to large overhead of xml tags
-
-commit 68f511f4972b8ac294b7429aadb27b22f2dfd554
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Apr 22 10:19:02 2014 +0200
-
-    sctp: enclose pre-init static function in between ifdef USE_SCTP
-    
-    - it is not used otherwise and some compilers can throw warnings
-    - reported by Juha Heinanen
-
-commit f0e8c293e28b3761d0f13e2c604eb1cfbbad7ace
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Apr 22 10:12:21 2014 +0200
-
-    avpops: switched from initialize struct with {0} to memset
-    
-    - apparently gcc doesn't like it although it should be the standard
-    - clang is ok with it
-    - reported by Juha Heinanen
-
-commit c2badcf570582b0e5d3621f416e2b08a0d028e0a
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Mon Apr 21 22:53:15 2014 +0200
-
-    pkg/kamailio/deb: update changelog to 4.2.0~dev5
-
-commit 2a53577bc80848e8ead9b3e9f2c3eb8ac6f89610
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 21 21:59:38 2014 +0200
-
-    Makefile.defs: version set to 4.2.0-dev5
-
-commit 314ea152c51cd8d4b46a49c05a3fed564c81c0ea
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 21 21:53:27 2014 +0200
-
-    exec: free local variable if there is no more memory in next attempt
-
-commit 9f042bb2798f29d476148ab2887a05709d5258fc
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 21 21:52:16 2014 +0200
-
-    htable: init allocated memory after checking parameter
-    
-    - avoid useless operation and extra check for leak
-
-commit f619a813ef46c76dd25c50b86f8af6cd768ac38f
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 21 21:50:17 2014 +0200
-
-    mi_rpc: don't access fields in structure after free in mi_rpc_async_close()
-
-commit f2d95b0e8326ae7d61b31288d3b695e1db85ec77
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 21 21:49:27 2014 +0200
-
-    nathelper: free local variable if getting anchor for contact header fails
-
-commit ed60b891f915017b385a722f2a9c0bf171802eab
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 21 21:47:06 2014 +0200
-
-    rr: free forgotten allocated local variable trans in case of error
-
-commit 0a1acc7cbf21e2332ca25d94bb320a3b8708357c
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 21 21:45:46 2014 +0200
-
-    sipcapture: free proper db_url field and destroy capture mode data list
-
-commit b6b023038452a7cb1ded28bf82f81622b34ce201
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 21 21:44:42 2014 +0200
-
-    pv: removed mistaken pkg_malloc() left for $cnt()
-
-commit cee4b58e1728be7de2c15ae25c4c1be0dd3088fb
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 21 21:43:59 2014 +0200
-
-    textops: cleanup on error parsing methods at startup
-
-commit 5fe289cae2ece412eeaec4efefcb411a7ed434aa
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 21 21:43:05 2014 +0200
-
-    tls: free the file path clone when all went ok
-
-commit 09ebe81a4ccb4346af778cc21c789b0db0e193d9
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 21 21:41:59 2014 +0200
-
-    tm: clean contacts in case of failure in t_load_contacts()
-
-commit 8589936aac4a6341b4d56bfe2ed7d4d90a169d56
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 21 21:41:00 2014 +0200
-
-    xhttp: wrong variable was used for checking memory allocation
-
-commit 9f8f66c44f5d44f945bba3b63160967a19044b8b
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 21 21:40:15 2014 +0200
-
-    xlog: clean exit at startup in case on error looking up facility
-
-commit b3d312bc3795f394e5907ac54bb59560e829e38b
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 21 21:39:07 2014 +0200
-
-    core: proper destroy of tcp connection at shutdown
-    
-    - don't access connection fields after freeing structure
-
-commit 5ce86dca571fab39f96855bc63191d9abe5914e0
-Author: Juha Heinanen <jh at tutpro.com>
-Date:   Mon Apr 21 19:24:30 2014 +0300
-
-    modules/sdpops: added sdp_transport(pv) function
-
-commit 0bda1dc8238f6be5bc83711e0439dabff39c9120
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 21 17:57:09 2014 +0200
-
-    core: safety check accessing variables in dbg message during fixup operation
-
-commit 511de7f5dc047368799e18d028e1e3f2864e05ac
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 21 17:56:01 2014 +0200
-
-    core: link regex before replacement field allocation can fail
-    
-    - regex will be freed properly if there was an error for replacement
-
-commit 3257da4abf7ea9cc64676ee66b6f70d600ac5c58
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 21 17:54:26 2014 +0200
-
-    core: check if proto is not null before setting it
-    
-    - coherent checking across no_naptr_srv_sip_resolvehost()
-
-commit 256b1e17e5449ef844b885d542a9c1f66fad044a
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 21 17:52:53 2014 +0200
-
-    core: safety check for freeing either pkg or shm values for var, when applicable
-    
-    - just an improvement to avoid doing both operations by mistake
-
-commit 2abbeb8fd31e41a34a013ff65eada197f171f321
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 21 17:52:07 2014 +0200
-
-    core: safety checks for pointer in dbg message printed inside dns cache
-
-commit b1106fb492a3e6e8ab73d37912b9a86d14373e75
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 21 17:50:53 2014 +0200
-
-    core: free allocated memory in case of failing to get more for modparams
-    
-    - keep shutdown at startup error clean
-
-commit 6f47c9ee24adea03df58e84d296e9682e5f81286
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 21 17:50:09 2014 +0200
-
-    core: safety check when declaring a cfg structure with empty content
-
-commit 3c062c1299dabd76e8461389b67506a25d1fcc02
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 21 17:48:16 2014 +0200
-
-    core: free line_buf in case of error building via
-    
-    - free buf in a very unlikely error converting src_ip to str in static
-      buffer
-    - coherent checking of msg pointer in the function
-
-commit 69d43fbacdf121b6c3ab22686f9089d9c7859591
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 21 17:46:36 2014 +0200
-
-    srutils/tmrec: reset pointer after free to avoid double deallocation
-
-commit 6a82b6121f771b6b847aecf4c5a0c42d0388c5d0
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 21 17:45:52 2014 +0200
-
-    db_text: fixed access after free and proper size for allocated memory
-
-commit af81862f5930d4c33639c204a7d88aeb484d3f0d
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 21 17:44:34 2014 +0200
-
-    call_control: replaced dynamic str* a local variable
-    
-    - it was freed afterwards and could leak in case of error hanling
-
-commit 98bb8c7e5166d2ff494daa9c488073d16dcfb405
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 21 17:43:47 2014 +0200
-
-    avpops: initialize local variable to avoid warning on db ops function
-
-commit 33d001a91fae080546755f63101c9b05fdf49b22
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 21 17:43:00 2014 +0200
-
-    acc: avoid memleak at startup when failing to initialize a custome accounting  engine
-
-commit 74ae88f55dd4c1ed395bbb32a6c7a835de5775ee
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 21 17:42:04 2014 +0200
-
-    tls: avoid leaking duplicated file name on re-iteration
-    
-    - reset file name pointer to avoid double free in case of error handling
-
-commit 53642d60ff2a680f724d5f439cf2b868bd082c3e
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 21 17:40:27 2014 +0200
-
-    mem: remove trailing ; to allow using as single instruction in conditinal blocks
-    
-    - this is for system malloc with extra debug for private memory
-
-commit 89c48cda56a67bd99288f6f390802f14b340e6da
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 21 17:39:50 2014 +0200
-
-    benchmark: avoid memory leaks when dealing with invalid mi commands
-
-commit d2f71f30011cb885f494e5d7d82ffdd15ff5dc7b
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 21 17:38:19 2014 +0200
-
-    auth_diameter: avoid double free in case of error and don't access freed pointer
-
-commit f65bf2c37bfaae740dd3cd8d686308cfa44b42f2
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 21 17:36:01 2014 +0200
-
-    db_mysql: reset prev_token to avoid double free in case of url parse error
-    
-    - when db api v2 is used (ser modules)
-
-commit e114105450d8a5152448afd28de16e290297e38d
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 21 17:35:39 2014 +0200
-
-    db_mysql: remove line accessing freed result
-
-commit 17cc9b0054bd071cad478534e8615ba73c65cc29
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 21 17:34:24 2014 +0200
-
-    debugger: check for define of PKG_MEMORY to execute pkg checks
-    
-    - allow compilation with system malloc for private memory
-
-commit ecfe8a90dc2445060b41a8b7c7ab65238b0652d4
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 21 17:33:33 2014 +0200
-
-    rtpengine: chef for SHM_MEM define for kamailio embedded mode
-    
-    - allow compilation with system malloc for private memory
-
-commit 2f01858d0be09cecd5e21e3e10fdd9d6425be028
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 21 17:30:40 2014 +0200
-
-    tm: release re for t_check_status(pv)
-    
-    - the canse when parameter is a variable and it contains a bad regex
-
-commit 387c369a11730afe680fb32138b93d4024f5b88d
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 21 17:29:15 2014 +0200
-
-    tm: fixed typo in previous commit related to name of struct contact variable
-
-commit d8e242c64d6c3d167c5a2b326ec77727d6d38217
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 21 14:08:10 2014 +0200
-
-    mem: DBG_SYS_MALLOC can be set to get verbose mem ops with system allocator
-    
-    - PKG_MEMORY has to be undefined in Makefile.defs
-
-commit a55e0f0fd7cf028c3263bcce30ec808ff08568da
-Author: Juha Heinanen <jh at tutpro.com>
-Date:   Mon Apr 21 18:35:30 2014 +0300
-
-    modules/tmx: fixed typo in $T_branch README listing
-
-commit 9708bcfbb49586661aa96b34bd8c317a5dbd2006
-Author: Juha Heinanen <jh at tutpro.com>
-Date:   Mon Apr 21 18:31:30 2014 +0300
-
-    modules/tmx: replaced $T_reply_flags with $T_branch(flags)
-
-commit d771fbfe982548e5fc2b087d3e1897e9011d5dd6
-Author: Juha Heinanen <jh at tutpro.com>
-Date:   Mon Apr 21 17:34:33 2014 +0300
-
-    modules/tmx: removed unused function
-
-commit 770434e87ec14b9662314e8a13d587f547e876cb
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 21 11:12:23 2014 +0200
-
-    tm: free struct contacts in case of error retrieving r-uri in t_load_contacts()
-
-commit 2c74ba02c843349a6ad30f7e668a7a194dac679c
-Author: Timo Teräs <timo.teras at iki.fi>
-Date:   Mon Apr 21 10:57:11 2014 +0300
-
-    core: fix some #includes to be posix compliant
-    
-    sys/poll.h and sys/fcntl.h are GNUisms and might not exist on
-    strictly posix compliant systems. This fixes to use the posix
-    specified standard locations of these headers.
-    
-    E.g musl c-library will give warnings on using these non-standard
-    glibc 'internal' headers.
-
-commit 9051ab74c9f6b97580a832e66385747c94c94380
-Author: Juha Heinanen <jh at tutpro.com>
-Date:   Sun Apr 20 15:17:22 2014 +0300
-
-    modules/tmx: added $T_reply_flags pv and fixed bug in t_reuse_branch()
-
-commit 575aabb238e75904ec7cad0c3a2b70dc48b0e40d
-Author: Juha Heinanen <jh at tutpro.com>
-Date:   Sun Apr 20 09:53:33 2014 +0300
-
-    modules/tmx: added new function t_reuse_branch()
-
-commit b0ab6f7083e8ab40b8158c5b2cf528efcbe14dfb
-Author: Torrey Searle <tsearle at gmail.com>
-Date:   Sat Apr 19 11:16:24 2014 +0200
-
-    modules/sipt:  refactored pseudovars to be of the form $sipt(header[.field])
-
-commit c290e58b7f50bdd7f9d691c4890baf1c9f74cb0d
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Sat Apr 19 11:06:48 2014 +0200
-
-    json|jsonrpc-c: fix detection of json-c lib
-
-commit c6246840abe0c75df03c603aa8e56f70a4799bce
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat Apr 19 00:35:57 2014 +0200
-
-    usrloc: fixed c&p error for variable name in ul_rpc_add()
-
-commit 37b0bea4ea6dcad3fbe1a2a93229bb1441ab8679
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat Apr 19 00:35:00 2014 +0200
-
-    tmx: check if t is null or undefined for returning branch index
-
-commit 458b803efa2de5b1a3bcdd83400f6ef7c6fad2a0
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat Apr 19 00:34:23 2014 +0200
-
-    tls: test if conection is still active for peer verification
-
-commit 110882edfee749679e0b05528bd4e1bcfd2321b3
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat Apr 19 00:32:17 2014 +0200
-
-    textops: use local variable to copute the offset in buffer for hdr ops helper function
-    
-    - when a prefix was given (e.g., append_uri_hf()), it could have led to
-      usage of invalid value
-
-commit 48c42830f8d9f5927453dc091765c2434845c725
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat Apr 19 00:31:23 2014 +0200
-
-    rr: coherent check for optional user part of advertised rr
-
-commit 4dd1387aad64bc9380eeac744eb0ad07d5a591d4
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat Apr 19 00:30:02 2014 +0200
-
-    registrar: test returned value for socket when socket flag is set and xavp is used to hold it
-
-commit bf6cb8e2dfedb5b8c6cc367ff6e8355a8313d887
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat Apr 19 00:28:56 2014 +0200
-
-    pv: return error if shm is not initialized when $shv() is used
-
-commit a6cf59395c472b999d5cc4197de80cd9385dfd11
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat Apr 19 00:27:54 2014 +0200
-
-    msilo: check to be sure len is positive before trying to copy string
-
-commit 6626f9a73700f9af8d46945e250fc8ab88f5aefe
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat Apr 19 00:26:53 2014 +0200
-
-    mqueue: use static var to return pointer to dynamic queue name
-
-commit 53f67e60f491bb5b9f56ce010410de8eff23430a
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat Apr 19 00:25:21 2014 +0200
-
-    dialplan: fixed typo in define for guarding .h file
-    
-    - init local variable to avoid warning
-
-commit 69d67c01e03d1363948b3597bb2afdf3cd0145a2
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat Apr 19 00:24:16 2014 +0200
-
-    dialog: detect the param value type for setting by routing block
-
-commit ccd1593834a47973bddeea94037fe8d3fd862cdd
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat Apr 19 00:22:52 2014 +0200
-
-    ctl: free allocated pointer in case of error
-
-commit c1feccdba8f4c4b624b948595f9166b83e65ed6a
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat Apr 19 00:21:50 2014 +0200
-
-    parser/contact: cleaned log messages and safety check for invalid iterator call
-
-commit 58acedef5a7748310b1032b534c3174f1e3d1a62
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat Apr 19 00:21:09 2014 +0200
-
-    core: safety check for finding select final node
-
-commit fcc6dbd6d9b50bdbee7ba22c22f8f06a98bfb2ca
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat Apr 19 00:20:19 2014 +0200
-
-    core: print rdata pointer and wrap null condition around it in dbg message
-
-commit a7251ba4140df3fa9b4fd3ea6a4d48ffbe156597
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Apr 18 19:01:22 2014 +0200
-
-    uac: safe initialization of vars and debug message for uac_replace_to()
-
-commit a2513a2bc820f935c62f14749ddaefaf77951891
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Apr 18 18:51:33 2014 +0200
-
-    textops: init s field of uri str structure for proper evaluation
-    
-    - otherwise can get uninitialized to last if block of
-      get_uri_and_skip_until_params()
-
-commit f0186bf375d4653b5354df35a9a8d065b56522ee
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Apr 18 18:38:53 2014 +0200
-
-    textopsx: init local variable to avoid testing invalid value
-
-commit bf7b6c25cdefc2a6a473c6fe8f496c858e05d020
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Apr 18 18:11:38 2014 +0200
-
-    core: added some safety checks for cfg framework pointers
-    
-    - avoid dereferencing null in corner cases
-
-commit 118d3051bd1c84ba725c719dd6d86e8335d9c274
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Fri Apr 18 22:15:31 2014 +0200
-
-    pkg/kamailio/deb: use libjson-c-dev when possible.
-
-commit 679833f9f098e1ebc5e2b66978a5535af557924c
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Fri Apr 18 22:07:47 2014 +0200
-
-    json|jsonrpc-c: use new naming json-c lib if available
-
-commit 5bc9e43eb6827220468f526c3df9d4c775311e51
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Apr 18 17:22:43 2014 +0200
-
-    sercmd: read the rest from socket if message was too big for rcv buffer
-    
-    - reported by Savolainen Dmitri, FS#422
-
-commit ac2e49b41840e0b05750b20c367a6c380caa983a
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Apr 18 10:49:24 2014 +0200
-
-    tm: lock replies before restoring flags for onreply_route
-
-commit 27c383c9224055e3d1b01238ff47785449e4057c
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Apr 17 16:16:04 2014 +0200
-
-    tmx: properly receive the branch index for $T(...) in the branch_failure_route
-
-commit 5c5b587d44a46b3a4d48c7e7926c42a44cd4d8c8
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Apr 17 15:49:36 2014 +0200
-
-    dialog: set lower limit for dlg_ka_interval parameter to 30 sec
-    
-    - avoid many keepalives in shorter interval than retransmission timeout
-      could be
-    - an improvement would be to export the fr_timer value from tm and have
-      condition based on it
-    - reported by FS#417, Bill Radis
-
-commit 4a9a98a07869a2415b82b70b23907ccd490d6c12
-Merge: 37983c9 31469a0
-Author: Luis Martin Gil <martingil.luis at gmail.com>
-Date:   Thu Apr 17 12:56:11 2014 +0000
-
-    Merge branch 'luismartingil/msrp_crash'
-
-commit 31469a0541874b1b0a5dda89aec0eed4ad94d97e
-Author: Luis Martin Gil <martingil.luis at gmail.com>
-Date:   Thu Apr 17 12:49:52 2014 +0000
-
-    	msrp: improved parser
-    
-            - Added more logic to the parser: Not allowing multiple
-    	To-Paths or From-Paths
-
-commit 164435ab191964bc9f0054874536c022dcf11063
-Author: Luis Martin Gil <martingil.luis at gmail.com>
-Date:   Thu Apr 17 12:29:47 2014 +0000
-
-            msrp: improved parser
-    
-            - changed indentation as required by Daniel
-    	  http://sip-router.org/tracker/index.php?do=details&task_id=419#comment1390
-
-commit 37983c9f57536c57c5d34ce2d8a1c8f411e61e39
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Apr 16 19:43:45 2014 +0200
-
-    db_mysql: properly free db result structure if db_mysql_convert_result() fails
-    
-    - reported by Torrey Searle, FS#420
-
-commit 23ad1fb98941507338edba7136327896033ed18f
-Author: Luis Martin Gil <martingil.luis at gmail.com>
-Date:   Wed Apr 16 14:55:35 2014 +0000
-
-        msrp: improved parser
-    
-        - msrp parser patched so Kamailio doesn't crash when receiving
-          non-rfc4975 compliant msrp messages
-
-commit a11a1f4ebce11368eef01824913e9ff115042a28
-Author: Juha Heinanen <jh at tutpro.com>
-Date:   Wed Apr 16 15:32:05 2014 +0300
-
-    modules/acc: insert_mode readme enhancements
-
-commit 3f84ebbb5504831483248e5b58b3ecd60368b3aa
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Apr 16 13:31:20 2014 +0200
-
-    db_mysql: fixed c&p error for insert_async operation
-    
-    - reported by Juha Heinanen
-
-commit bbcc447c6bd5e01cae5932fa11cbaceccef5a389
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Apr 16 12:38:13 2014 +0200
-
-    sqlops: removed unused variables in sql_do_query_async()
-    
-    - reported by Juha Heinanen
-
-commit 6c5ebff42c1ee702ab4a859ffdd5ffeccbf8e11d
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Apr 16 12:14:44 2014 +0200
-
-    app_perl: print return code if perl_parse() failes
-
-commit 73c440e87fc256cda99ab572c0a259c13acac700
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Apr 16 08:41:51 2014 +0200
-
-    maxfwd: max_limit default value set to 70
-    
-    - recommended value by RFC
-    - lower value can create issues when terminating to PSTN/ISUP where
-      can be used to set the Hop Counter
-    - patch by Sebastian Damm, FS#418
-
-commit 09d136d053cde9a59c6f2937b8e1fa56f590fad0
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Apr 15 18:53:34 2014 +0200
-
-    tm: fix condition added in previous commit testing xavp list addition to core
-
-commit 4f95cfa6266bd66a1516629ed3445d98da433b2b
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Apr 15 18:19:19 2014 +0200
-
-    tm: safety check for cases when xavps for serial forking fail to be added to root list
-    
-    - in error cases remove xavp group from the root list instead of local destroy, otherwise it
-      stays linked in root list and can cause invalid memory access
-    - discovered on investigating memory leak issue reported by Geoffrey M.
-
-commit c5e0bda5e20adeaa2a899fcc55ad12cf4678cf39
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Apr 15 17:50:52 2014 +0200
-
-    tm: free extra attributes stored in uac branch
-    
-    - credits to Geoffrey M. for reporting and giving access for
-      troubleshooting
-
-commit c90369b406db09e9e3d9d690ed3d7742b5cc5c48
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Apr 15 14:19:51 2014 +0200
-
-    kamailio.cfg: enable_full_lr set to 0
-    
-    - it is default RFC recommendation and what of most UAs expect today
-    - lr=on was needed for some old UAs that were discontinued meanwhile
-
-commit c92ec42ac07a4a000a95dcd1f3c1a349ce35ea82
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 14 22:37:02 2014 +0200
-
-    acc: extended documentation for db_insert_mode parameter
-    
-    - if set to 2, async insert operation is used to store the acc record in
-      database table
-
-commit 922e034e35410d2008d7d4d907fd535c1f5ad3fa
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 14 22:33:13 2014 +0200
-
-    acc: if db_insert_mode==2, use async db insert to store the record
-    
-    - the acc record will be stored via async framework if db driver
-      implement insert_async()
-
-commit 23bc165dc1f697714a922afb5806abe162033ad1
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 14 22:27:20 2014 +0200
-
-    sqlops: documentation for sql_query_async()
-
-commit 6f8863392ac230d85289d5edcab1d0d83fc85b00
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 14 22:18:52 2014 +0200
-
-    sqlops: new cfg function - sql_query_asycn(con, sql)
-    
-    - execute sql statement via async raw query, if implemented by db driver
-      module (e.g., db_mysql)
-    - the query is executed in another process and result is not available
-      back to config, thus it should be used only for sql statements that
-      don't return values (e.g., insert, delete, update...)
-
-commit 0d78e9a9cc56b642255fbdf5af1e1a9bf4d874cb
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 14 22:17:51 2014 +0200
-
-    db_mysql: implemented async raw query and async insert
-    
-    - both use the core async framework
-
-commit ca92959a8709982554721c63376a5fb009fb0aff
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 14 22:16:20 2014 +0200
-
-    lib/srdb1: extented DBv1 with async raw query and async insert
-    
-    - functions that should be executed in async mode
-
-commit 5457bcbc51012e93775c3aaefa32c73f956aa279
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 14 20:19:44 2014 +0200
-
-    lib/srdb1: clone db url in db_id structure
-
-commit 879aec4c22202d86b1abf75c428221e72e0a85c5
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 14 15:37:33 2014 +0200
-
-    async: allow module to start without internal async timer procs
-    
-    - async_route() and async_sleep() will return false
-    - useful when only async_task_route() is used
-
-commit 93a0a29f445a21a1397bd9ce6b34563fbf889fd2
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 14 14:31:53 2014 +0200
-
-    async: fixed type in the title of async_route() example
-
-commit 272b23738de76d397c145c44c22a943fe198f753
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 14 14:28:13 2014 +0200
-
-    async: documentation for async_task_route()
-
-commit d5a22ca880d04549b4f65086bcfd2f3f67311bcb
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 14 14:17:36 2014 +0200
-
-    core: async_workers - new core parameter
-    
-    - specify how many processes to create for asyn framework
-    - default is 0 (asyn framework disabled)
-    - you must set it to >0 to enable it
-
-commit cab6c3abedb9036ebd75483c860b0caa74388e4c
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 14 14:16:48 2014 +0200
-
-    async: new function async_task_route(rname)
-    
-    - execute actions in a routing block via core async framework
-
-commit 9467ebbfdeea640923dbb77b4bea97ccda795903
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Apr 14 14:13:36 2014 +0200
-
-    core: framework for creating asynchronous pool of workers
-    
-    - dedicated group of processes that can get tasks from other processes
-      via memory pipe
-    - react immediately, no time based polling
-    - should reduce the need for other components to create extra processes
-      for special handling
-
-commit eb5b9c6965d1da46f8cb45d3ac2eb6598b3b6dea
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sun Apr 13 22:19:15 2014 +0200
-
-    pv: use pv cache to lookup avp name for $cnt(...)
-
-commit 997f13c89d16361799651cd77214ffdcf26d532c
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sun Apr 13 16:22:38 2014 +0200
-
-    ipops: new pv to get hostname details:
-    
-    - $HN(n) - hostname
-    - $HN(d) - domain
-    - $HN(f) - fullname
-    - $HN(i) - ip address
-    - based on gethsontname and resolving it
-
-commit 0bea3e5cf97593b2955aec4bb545b4f8698bd964
-Author: Juha Heinanen <jh at tutpro.com>
-Date:   Sun Apr 13 10:34:30 2014 +0300
-
-    modules/sdpops: fixed typo in readme example
-
-commit 933a621f40eaa31b193e76f162f9cc016b49aeac
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Apr 11 23:03:05 2014 +0200
-
-    dialog: proper detection of keepalive flag for destination
-    
-    - credit to Bill Radis, FS#416, for report and fix
-
-commit 3d9040bb5494bafe3411744da17bf43de6a22604
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Apr 11 16:21:27 2014 +0200
-
-    tmrec: fixed typo in header file guard define
-
-commit 5beb495d47fa16ed94c36e340011c09de50db9c7
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Apr 11 16:18:59 2014 +0200
-
-    srdb1: removed extern inline function prototypes
-    
-    - the .c files are not linked against modules code, thus inline
-      replacing request cannot be resolved by compilers, the strict ones
-      (e.g., llvm) throw error
-
-commit da0fe20153eb9fc4b8f79a2f5260cb871bb3fc0d
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Apr 11 16:14:06 2014 +0200
-
-    cnxcc: inline functions defined in other objects throw warning in llvm
-    
-    - an option would be defining whole function inside the .h file
-
-commit 4cb7abe093ce0c56a4661377f9792fc417f83786
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Apr 11 16:11:05 2014 +0200
-
-    srdb1: get rid of llvm warnings related to extern inline definitions
-
-commit 82e742fcdd7c22391cae8e3b36d42f23d684dee8
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Apr 11 16:04:24 2014 +0200
-
-    tmx: allow spanning over second for fetching stats
-    
-    - try to catch the same snapshot for all tm stats
-    - re-enabled stats for received and relayed replies, computed from what
-      is relayed and was was local reply
-    - todo: check if drops replies are caught later or is ok
-
-commit 198e123e89c849da39efec1973c25c3c25a2be89
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Apr 10 08:56:13 2014 +0200
-
-    tm: avoid tryin to mitigate relaying 487 for local canceling branches when a reply is forced from config
-    
-    - it can result in deadlock if there is a local retransmission timeout
-      and the response code is overwritten by admin in failure route with a
-      t_reply()
-    - reported by Jason Penton
-
-commit 7126d8aa7a5fa5fd0a5cafdf17c359dab01df5ef
-Author: Juha Heinanen <jh at tutpro.com>
-Date:   Wed Apr 9 20:50:13 2014 +0300
-
-    modules/rtpengine: rtpengine does not use ser_memmem
-
-commit 2d4d54b4f4593dee767db240a3eafce5489d628f
-Author: Juha Heinanen <jh at tutpro.com>
-Date:   Wed Apr 9 20:45:12 2014 +0300
-
-    modules/nathelper: use ser_memmem from core
-
-commit 5c25ba35f37d2a9774caec7215261687c2ad17a0
-Author: Juha Heinanen <jh at tutpro.com>
-Date:   Wed Apr 9 20:35:58 2014 +0300
-
-    modules/sdpops: use ser_memmem from core
-
-commit 5ab74a287014087dbf6f95f96eeea55deb174f35
-Author: Juha Heinanen <jh at tutpro.com>
-Date:   Wed Apr 9 20:30:23 2014 +0300
-
-    core, parser: moved ser_mem[r]mem() functions from parser to ut.c
-
-commit b1900f66cc4acd254f1e6750538f31a3653fcd7f
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Apr 9 18:49:32 2014 +0200
-
-    uac: safety check to be sure the reg hash table is initialized
-    
-    - reported by Alex Villacís Lasso
-
-commit 9bf9a7448848580aa883dbdfb26125e27d5ac32d
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Apr 9 10:42:15 2014 +0200
-
-    evapi: netstring format option applies for sent messages
-
-commit 5ac454af6aedb91265c3359a523354541cabd161
-Author: Fred Posner <fred at palner.com>
-Date:   Tue Apr 8 21:54:43 2014 +0200
-
-    sqlops: note about return value of query functions
-
-commit 8adf574962534e0c682318cbbc226d5a12b3b924
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Apr 8 16:46:46 2014 +0200
-
-    evapi: documented netstring_format parameter
-
-commit 58559544b7bb94421feb51db415910db6de2359d
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Apr 8 16:40:24 2014 +0200
-
-    evapi: option to retrive data from clients encapsulated in netstring format
-
-commit dfaf1f1cf9d80fd3c952c762a6b264b9e0b03253
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Apr 8 15:31:56 2014 +0200
-
-    corex: documented corex.shm_status and corex.shm_summary rpc commands
-
-commit 1006878b21494d11c9f5ac241b79abea92e9f34f
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Apr 8 15:31:19 2014 +0200
-
-    corex: rpc commands to dump shm status and summary to syslog
-
-commit ff55c8c3ea528022f83fc01f8c0df82fd02e7b13
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Tue Apr 8 11:58:22 2014 +0200
-
-    pkg/deb: update debian version to 4.2.0~dev4
-
-commit ee6aa89811d7e02beb250f6b3831b32c2dbeeea7
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Apr 8 11:52:01 2014 +0200
-
-    Makefile.defs: version set to 4.2.0-dev4
-
-commit a42976948e1b6cabd978c1d61d30cea9cdc27cc2
-Author: Torrey Searle <tsearle at gmail.com>
-Date:   Mon Apr 7 11:18:27 2014 +0200
-
-    modules/sipt: finalise $sipt_event_info support
-
-commit 2da4dc5b0054f0182f67560fe15958565c0e360b
-Author: Torrey Searle <tsearle at gmail.com>
-Date:   Mon Apr 7 09:43:11 2014 +0200
-
-    modules/sipt: Fix a bug in updating calling party
-
-commit 2639e3ddcb82434544012b537d2ca72264a5c9ee
-Author: Torrey Searle <tsearle at gmail.com>
-Date:   Mon Apr 7 09:23:16 2014 +0200
-
-    modules/sipt: initial support for parsing CPG and ACM messages
-
-commit 6a993cfbec280632c715151fdbbd8d2a3e41e378
-Author: Juha Heinanen <jh at tutpro.com>
-Date:   Sat Apr 5 11:28:34 2014 +0300
-
-    modules/sdpops: added sdp_with_transport_like() function
-    (cherry picked from commit a9b6cf96644589b462f02d009df768fece7e5c03)
-
-commit 9beb8de04fb5c37fef265c54503870e5550fa02b
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Fri Apr 4 11:02:03 2014 +0200
-
-    utils/kamctl/mysql: added schema for ims_usrloc_scscf
-
-commit 1d44402af09d6252be3bbf6fa2b68140b09de2cf
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Fri Apr 4 10:58:55 2014 +0200
-
-    utils/kamctl/mysql: sdded chema for ims_usrloc_pcscf
-
-commit 3a1720a4d63ef5c83c5a6f739dadb06f3c292f50
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Thu Apr 3 15:24:59 2014 +0200
-
-    modules/ims_charging: updated debug line with new usrloc contact match mode
-
-commit afb7ae6b66b077225687c4529150b9ce053b0b8c
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Thu Apr 3 15:23:49 2014 +0200
-
-    modules:ims_usrloc_scscf: add new contact match mode CONTACT_PORT_IP_ONLY
-    	new match mode CONTACT_PORT_IP_ONLY allows to match contact based
-    	only on port and IP - ignoring user part
-    	Useful as some IMS clients use contact as IMPI at IP:PORT and others use E164 at IP:PORT
-
-commit 59255567a90b8cbee6525af14afa388e97b2e395
-Author: Torrey Searle <tsearle at gmail.com>
-Date:   Thu Apr 3 14:41:23 2014 +0200
-
-    modules/sipt: reduce log level for no ss7 message found
-
-commit acd1f73f7a5b35a556e02501cccaeeb8948b7529
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Wed Apr 2 15:26:50 2014 -0400
-
-    xhttp_pi: update inline doc for xhttp_pi samples
-
-commit 8598b812f59b37d7f4b7469aa1a7f61b93ece2a7
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Wed Apr 2 18:06:15 2014 +0200
-
-    ims_usrloc_pcscf: fixed bug where contact pointer is not bumped in continue sections of loops
-
-commit b26de0ab6b3b996984bbedb189ba131732805ae9
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Tue Apr 1 19:48:24 2014 -0400
-
-    xhttp_pi: samples regenerated
-
-commit cfce181526d1686aa431eb358ea35d793f7df12f
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Tue Apr 1 19:46:41 2014 -0400
-
-    xhttp_pi: update pi_framework_mod.xsl to generate new pi_http samples
-     - add link_cmd to the primary key for DB_UPDATE commands
-
-commit 9295d98384e6b8c4b807efa421d5825ba4fb4115
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Tue Apr 1 19:44:17 2014 -0400
-
-    xhttp_pi: run DB1_UPDATE commands with prefilled values
-
-commit dd004947906628784ffdf15a0fe5cf4421040ddc
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Tue Apr 1 18:34:28 2014 -0400
-
-    xhttp_pi: fix escaping
-
-commit 9606520cb0ccbd6a51c1c2d599cf0cb2879bfdf8
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Tue Apr 1 12:50:56 2014 +0200
-
-    example/icscf/kamailio.cfg: Removed unecessary append_branch() after LIR
-
-commit 77e2c6beb250726f8bc5dec5d71ec175264e0c0f
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Mar 31 09:48:58 2014 +0200
-
-    evapi: fixed c&p typo in example
-
-commit 193f27a0da5e2e3da7737da0bd7b035912be59d5
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Mar 31 09:41:17 2014 +0200
-
-    evapi: docs updated with evapi_close(), new event routes and pvs
-
-commit 5ef20abd1fdb45f5398eecedc81af3fad13024a3
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Mar 31 09:29:06 2014 +0200
-
-    evapi: added evapi_close() function
-    
-    - close client connection from cfg file
-
-commit b78239c7b389f871b8489fddc3a5a2988be460ec
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Mar 31 09:18:22 2014 +0200
-
-    evapi: pass local env via sip msg structure
-
-commit f7be3b0588367081f1ed7224a74da59e284d53ab
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Mar 31 00:55:06 2014 +0200
-
-    evapi: exported pv $evapi(key)
-    
-    - key can be:
-    	* srcaddr - source ip of client connection
-    	* srcport - source port of client connection
-    	* msg - message received from client
-    	* conidx - internal index of client connection
-
-commit 0abf67a47450f0350a7826ec0719e66f4fc61022
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sun Mar 30 15:27:53 2014 +0200
-
-    evapi: execute cfg event routes
-    
-    - event_route[evapi:connection-new] - new client connected
-    - event_route[evapi:connection-closed] - client connection closed
-    - event_route[evapi:message-received] - message received from client
-
-commit 3d673225829b6dc87281816a7a074417671f395e
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sun Mar 30 14:19:04 2014 +0200
-
-    evapi: store src ip and port in client connection struct
-
-commit d1c607183049fba9997bbb401da76d3277ab3426
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sun Mar 30 00:22:17 2014 +0100
-
-    core: new global parameter max_recursive_level
-    
-    - replace define ROUTE_MAX_REC_LEV with config paramter
-    - number of allowed recusive levels can be set in config now
-    - it affects calls of route blocks and chained if { ... } else if { ...
-      } else ...
-
-commit a4b4ff805b4d6adcd8bc88c253f79fc44baab82e
-Author: Richard Fuchs <rfuchs at sipwise.com>
-Date:   Sat Mar 29 08:07:32 2014 -0400
-
-    rtpengine: fix inconsistent function naming
-
-commit 5c6c74ab5334eba88f5a4fd4b65bd3497fab0500
-Author: Richard Fuchs <rfuchs at sipwise.com>
-Date:   Fri Mar 28 11:51:15 2014 -0400
-
-    rtpengine: support loading rtpp sets from DB
-    
-    Source:
-    http://sip-router.org/tracker/index.php?do=details&task_id=401&project=1
-    
-    Author: Emmanuel BUU (neutrino38)
-
-commit 794fa76d0a951eec394728d32866619dcebc0bcc
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Fri Mar 28 11:48:22 2014 +0200
-
-    modules/ims_usrloc_pcscf: added storage for IPSEC security as well as DB storage
-
-commit f802733daf34d96020f7a7cc58e5a70f2b476717
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Fri Mar 28 11:44:51 2014 +0200
-
-    modules/ims_usrloc_pcscf: hash now on IP only and some contact search changes
-    	- hash on IP required, considering with IPSEC/TLS there could be multiple contacts per IP... - these all need to resolve to the same contact
-    	- the contact searches updated accordingly and simplified using uri parser
-    	- new contact search returns a contact regardless of state the contact is in... up to consumer to test the state the are/are not interested in
-
-commit 7deddf5646b1ff60d42321dba53ab53ceb8aab69
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Fri Mar 28 11:38:23 2014 +0200
-
-    Revert "ims_usrloc_pcscf: Improvement: Let the consumer decide, if we want to retrieve REGISTERED only or all contacts (especially, if we have more than one contact per IP/Port)"
-    	- this is already done in changes coming in...
-    	- rely on the consumer to check the status of the contact if one is found
-    
-    This reverts commit fe8a06a2e1b18219e52b3a85abd3f3961cc9773a.
-
-commit 1288838adf41bc6f152cd72e94c413f786af2f37
-Merge: b745f58 7c1b8e7
-Author: Richard Fuchs <rfuchs at sipwise.com>
-Date:   Thu Mar 27 15:34:57 2014 -0400
-
-    Merge branch 'rfuchs/rtpengine'
-
-commit 7c1b8e768d7d0f1988babe15ebd9d5cb43b355bc
-Author: Richard Fuchs <rfuchs at sipwise.com>
-Date:   Thu Mar 27 14:49:57 2014 -0400
-
-    rtpengine: update docs
-
-commit b745f5869e86bc7cce774dc4b54be9a1be90e3e5
-Author: Olle E. Johansson <oej at edvina.net>
-Date:   Thu Mar 27 17:31:51 2014 +0100
-
-    permissions: peer_tag_mode is integer, not string
-    
-    Fixing example in doc file
-
-commit 7526431e8a582e1267667534b59893bacb99a5fd
-Author: Richard Fuchs <rfuchs at sipwise.com>
-Date:   Wed Mar 26 15:30:18 2014 -0400
-
-    rtpengine: modernize interface, remove legacy interface
-
-commit d39bebef356338df1f57a448b4e2bcbe0d7534fc
-Author: Richard Fuchs <rfuchs at sipwise.com>
-Date:   Wed Mar 26 15:03:17 2014 -0400
-
-    rtpengine: rename from rtpproxy-ng
-
-commit 193431802ed1407bb66b722fbf6a5cc89d690a40
-Author: Elena-Ramona Modroiu <ramona at asipto.com>
-Date:   Tue Mar 25 12:05:56 2014 +0100
-
-    kamdbctl: added rtpproxy table to the extra group
-    
-    - it was not listed at all, thus not created
-
-commit 1a0150482658ab9f90ec513184298b1e98bcc57c
-Author: Elena-Ramona Modroiu <ramona at asipto.com>
-Date:   Tue Mar 25 12:03:11 2014 +0100
-
-    htable: debug message when deleting an item via mi command
-
-commit 2376c833aad92bf8661f985d5917d952874a7509
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Mar 24 22:53:22 2014 +0100
-
-    dialog: lock for updating the cseq
-    
-    - race can happen on processing two requests at the same time within
-      same dialog
-
-commit a95cae3fb6a62120b7fe2770fb565195178bb6f7
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Mon Mar 24 16:01:44 2014 -0400
-
-    ctl: fix crash when listing in struc format
-     - example: kamcmd core.sockets_list
-
-commit edc78dfb148c22f0d256485193bbdb0185b76d2f
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Mar 24 10:12:26 2014 +0100
-
-    db_unixodbc: free local variables in case of errors or no result
-    
-    - reported by Alex Villacís Lasso
-
-commit a0ef714c12d9d9ae4cf152d6a62bd8a7d6bb5c34
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Mar 24 10:11:59 2014 +0100
-
-    db_unixodbc: use odbc_config to find paths for include and libs
-
-commit b8aee4b00258044b9999d961765c8ab53406e5b7
-Author: Carsten Bock <carsten at ng-voice.com>
-Date:   Sat Mar 22 16:49:20 2014 +0100
-
-    tls: Added note to docs about OpenSSL requirement for Elliptic Curve Diffie Hellman (ECDH)
-
-commit 49d318720cec2d46ae28edff4a0bddb564d32d44
-Author: Carsten Bock <carsten at ng-voice.com>
-Date:   Sat Mar 22 15:30:27 2014 +0100
-
-    tls: Add support for Elliptic-Curve Diffie-Hellman Ciphers (ECDH)
-
-commit 3a56e12090fe7b614430947d8393e16a4fc91b92
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Tue Mar 18 11:17:51 2014 +0100
-
-    textops: fix doc. insert_hf append_hf functions id are duplicated.
-
-commit fe8a06a2e1b18219e52b3a85abd3f3961cc9773a
-Author: Carsten Bock <carsten at ng-voice.com>
-Date:   Thu Mar 20 18:22:38 2014 +0100
-
-    ims_usrloc_pcscf: Improvement: Let the consumer decide, if we want to retrieve REGISTERED only or all contacts (especially, if we have more than one contact per IP/Port)
-
-commit 045a99c1717377702a35f46a232b0e9b85643026
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Mar 20 14:40:17 2014 +0100
-
-    evapi: evapi_relay() reduced to one parameter
-    
-    - more flexibility in the format of full event data
-    - new function evapi_async_relay() - suspend request processing using tm
-      before sending event out
-
-commit 216faa86af3d6db70fae9186ab2776efc27a5f55
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Wed Mar 19 22:36:47 2014 -0400
-
-    xhttp_pi: fix copy/paste error that can lead to a crash when 'order_by_cols' are used
-
-commit 058b98574e2cf78084cba608fafe8b7cc5d1cf74
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Wed Mar 19 22:32:24 2014 -0400
-
-    dispatcher: add base function for w_ds_select_domain and w_ds_select_dst
-
-commit a99e71e609c9f703458ac4304d80c7078f46a129
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Mar 20 00:28:23 2014 +0100
-
-    doc: updated year and removed unused revhistory from bookinfo.xml
-
-commit 509570a29bbecd6839fcd858c17a20dc04383f23
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Mar 20 00:12:14 2014 +0100
-
-    lib/srdb1/schema: added docbook-xml target to Makefile
-    
-    - generate docbook for dbschema in xml format
-
-commit 3e7d4b34caedd035e192943a9d40bccc5f46364e
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Mar 19 22:25:34 2014 +0100
-
-    debugger: new parameter log_level_name
-    
-    - allow overwriting default log level name for cfgtrace messages
-
-commit 691f2633a3227787394bfbebf21803185c0ea914
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Mar 19 22:15:12 2014 +0100
-
-    core: LOG_LN() new macro to print log messages overwriting log level name
-
-commit 8a6fb78081e68c9aea461db8989232c3e69335e7
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Mar 19 22:06:21 2014 +0100
-
-    core: new maro LOG__(...) to allow overwriting default name for log level
-    
-    - LOG_(...) is pinting to it now
-
-commit 27f2ae83d9adf59bc9158dd40bf1b960c8ffaa19
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Mar 19 18:37:06 2014 +0100
-
-    lib/kcore: link it against lib/srutils
-    
-    - reported by Carsten Bock
-
-commit 408d7e9bfd485d3fc6c7eb99894098283729aad0
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Mar 19 16:30:21 2014 +0100
-
-    core: L_NPRL aliased to L_ALERT-1 to allow printing messages without level name
-    
-    - new defines LM_NPRL() and NPRL() are using it
-
-commit 9e756aea4884b6e9f0dd359bb4a935fc3fed1e75
-Author: Carsten Bock <carsten at ng-voice.com>
-Date:   Tue Mar 18 22:10:09 2014 +0100
-
-    core: Minor bug-fix: Only free path vector, if it contains data
-
-commit 6c0370b806aebcdd6c7c000536be3d9ae6154837
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Mar 18 17:10:56 2014 +0100
-
-    mtree: safety checks for column types and values
-    
-    - following the report FS#412 by adeel
-
-commit ff91a65db150210a0c55ce57df9f476a9e0ee25e
-Author: lucian balanceanu <lucian.balanceanu at 1and1.ro>
-Date:   Tue Mar 18 17:20:36 2014 +0200
-
-    pv: changes to SHA string transformations
-    
-    - addressed memset faulty usage, changed location of sha256 files,
-      removed sha2utils.h as we can use defines in sha256.h, removed
-      redundant code
-
-commit 84457e881eb9b2796d7507373fc6299941440e39
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Mar 17 21:49:05 2014 +0100
-
-    registrar: fixed name of pv in docs
-    
-    - -> was used instead of => inside $ucl(...)
-    - reported by Corey Edwards, FS#411
-
-commit e8ca4fc9a74d21a057f2efed14459d49d5e6e82a
-Merge: 969d680 1c45598
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Mon Mar 17 16:11:16 2014 +0200
-
-    Merge branch 'master' of ssh://git.sip-router.org/sip-router
-
-commit 1c455988cdbd7a763dc74f9ec49612009f9a5a3b
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Sun Mar 16 09:39:56 2014 +0100
-
-    textops: ids to sections in documentation
-
-commit 6f96f4fbc788940f8dd1135e73107445d204b553
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat Mar 15 00:29:43 2014 +0100
-
-    core: -f parameter can take the value '-' to read config from stdin
-    
-    - allos piping the config from various sources (e.g., downloading from
-      web)
-    - example: cat /etc/kamailio/kamailio.cfg | /usr/sbin/kamailio -f -
-
-commit 713a0a1f068f9eb45a76dfe012b7f0ce6319221a
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat Mar 15 00:12:37 2014 +0100
-
-    core: print warning message if number of #!if(n)def is different than of #!endif
-    
-    - should help discovering if a conditional block is left unclosed
-
-commit ef86e60ef178fc451a69c5fe527fcd897fe0573b
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Mar 14 21:02:51 2014 +0100
-
-    kamailio.cfg: catch friendly-scanner if antiflood is enabled
-
-commit e446ad1bdb5df6feb8dda4efe3f5597f333c796f
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Mar 14 20:00:44 2014 +0100
-
-    etc: updated version reference in comments
-
-commit f96af0d1d682f794a749d6e26fbabc58dde18d4f
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Mar 14 19:59:02 2014 +0100
-
-    etc: cleaned up folder, moving unused files to examples
-
-commit 78e65fe7f5283fea19ee19d0a87edee315fe7eed
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Mar 14 18:02:56 2014 +0100
-
-    evapi: fixed c&p error in the docs
-
-commit b17de9bdc53ae3474341e632f7faa89d69b667c8
-Author: Carsten Bock <carsten at ng-voice.com>
-Date:   Thu Mar 13 14:59:58 2014 +0100
-
-    carrierroute: Minor typo in previous fix
-
-commit 4c4f2c2bedb4ad3a920847d061798109867bb5bd
-Author: Carsten Bock <carsten at ng-voice.com>
-Date:   Thu Mar 13 14:52:49 2014 +0100
-
-    carrierroute: Remove dependency on libconfuse, based on the patch by Lucian Balaceanu with the Comments based on Marius Zbihlei
-
-commit 969d680c571128cd8df398e574cfdfc7a92440fd
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Fri Mar 14 15:41:27 2014 +0200
-
-    modules/ims_registrar_pcscf: when search for contacts also include possible security ports
-    	- with IPSEC, the received port could be different from the initial registration
-    	which occurs after security has been negotiated
-
-commit 2f4877a9e3e104a90b03fcb380899848d3643997
-Author: Irina Grigorescu <irina.grigorescu at 1and1.ro>
-Date:   Fri Mar 14 12:17:39 2014 +0200
-
-    pv: added SHA string transformations
-    
-    - added sha256, sha384 and sha512 string transformations to return sha
-      over PV value
-
-commit 422e55d75aabf1833ad5e6b1cb069f434b9dbf99
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Thu Mar 13 10:41:07 2014 +0100
-
-    pkg/kamailio/deb: add explicity zlib1g-dev dependency for gzcompress
-
-commit 07f4ffcbc4dc7dc6affd65f0930d86320a59602d
-Merge: 0a1b189 a1de51c
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Thu Mar 13 11:31:53 2014 +0200
-
-    Merge branch 'master' of ssh://git.sip-router.org/sip-router
-
-commit 0a1b1890dbeea316e55ccef66f96d17e29843d76
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Thu Mar 13 10:47:55 2014 +0200
-
-    modules/ims_usrloc_pcscf: preload of pcscf contacts was omitting rx_port and proto
-
-commit 660b0cf139c0e2e9279838154354f78d7e51c6d4
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Thu Mar 13 10:47:26 2014 +0200
-
-    modules/ims_usrloc_pcscf: more debug logging...
-
-commit a1de51c55d7bf31c7e9a793ec898073ab158b3cf
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Thu Mar 13 00:14:47 2014 +0100
-
-    pkg/kamailio/deb: new kamailio-extra-modules package.
-    
-    Adding gzcompress, uuid and ev modules to extra.
-
-commit da2e3d712c1025b02df6a047ba06b8d8d7d8c80a
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Thu Mar 13 10:08:07 2014 +0200
-
-    modules/ims_usrloc_pcscf: search for contacts should not be based on reg_state
-    	- up to consumer to check state of contact
-
-commit afc1ced933eacba986c17978afb9e0ae201b2f58
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Mar 12 21:57:15 2014 +0100
-
-    Makefile.groups: created group for modules depending on libev
-
-commit 0acecd065ef0852fedeb723bd7c727f12d26316f
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Mar 12 21:50:02 2014 +0100
-
-    evapi: new module to push event details via tcp to external applications
-    
-    - uses libev for handling connections
-
-commit 942ac25bcb937d35bd184cda96fbb2f2319e8d1b
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Mar 12 13:16:51 2014 +0100
-
-    utils/route_graph: increased max depth value
-
-commit 99d50e2da0753d7482ed2884e665e08e235daf5e
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Mon Mar 10 19:49:39 2014 +0200
-
-    modules/corex: corrected freeing of msg. w.r.t path vecor
-            - now use FL_SHM_CLONE internal msg flag to decide whether or not to pkg free path_vec
-
-commit 1ccdadc89cdf5ddab069e4c912a9b6834c6631f1
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Mon Mar 10 19:48:10 2014 +0200
-
-    parser/msg_parser: corrected freeing of msg. w.r.t path vecor
-    	- now use FL_SHM_CLONE internal msg flag to decide whether or not to pkg free path_vec
-
-commit f15de29015546d173a1d3135f90653e05d85171f
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Mon Mar 10 14:38:51 2014 +0200
-
-    modules/corex: only free path_vector from pkg if it is still in pkg... not shm cloned
-    	- related to earlier commit 4ab0f53ff247f411dde7b88d5b7d82fc7e17baa9
-
-commit 4ab0f53ff247f411dde7b88d5b7d82fc7e17baa9
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Mon Mar 10 14:35:47 2014 +0200
-
-    core: parser: path_vector is now copied into shared memory when cloning
-    	- fixes in place to cater for freeing memory correctly
-
-commit 876bdccb031e2378a798ddacc6b6ac2e6e35efc5
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Mon Mar 10 14:29:02 2014 +0200
-
-    modules/ims_charging: use new lib/ims to get contact from req URI
-
-commit 497ded52eaafd7a43520dee41910efa85ef042c4
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Mon Mar 10 14:28:32 2014 +0200
-
-    lib/ims: added new function to get contact from request uri
-
-commit 84ea778d6340625fc4d3c2eafbc73ddad08548a7
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Mon Mar 10 14:27:59 2014 +0200
-
-    modules/ims_charging: logging fix
-
-commit 45e6878a398f7ba75ce253a7bfcbb66bc7a5c088
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Mon Mar 10 14:26:29 2014 +0200
-
-    modules/textopx: Prevent msg_apply_changes() from adding the router header if path is set.
-    	This avoids adding router header twice when calling msg_apply_changes
-
-commit 81d63a3f9726117288d6c5950c6d56e3a2749116
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Mon Mar 10 12:39:28 2014 +0200
-
-    modules/ims_usrloc_pcscf: added storage for security data (IPSEC/TLS)
-    	-new module ims_security going to be added soon that requires this
-
-commit b02792a2bd3b8a07a5496fe00ec563b6d8142639
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Mon Mar 10 12:38:40 2014 +0200
-
-    modules/ims_usrloc_pcscf: included hashing optimisation in search function for contacts
-
-commit c5eb9b7a742ea439edee77133b21095979cd3bc6
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Mar 10 00:25:22 2014 +0100
-
-    Makefile.groups: greated group for uuid module
-    
-    - depends on libuuid
-
-commit 7726383031399fa9a4f8a67f1ff2cb15ea124b37
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sun Mar 9 17:37:13 2014 +0100
-
-    uuid: new module to generate unique strings using libuuid
-    
-    - new class of variables exported - $uuid(type)
-    - type can be:
-    	- g - generic/default uuid generation
-    	- r - random uuid generation
-    	- t - time based uuid generation
-    	- s - time safe uuid generation
-
-commit e22293d865926a200e336293692886f983904275
-Author: Corey Edwards <tensai at zmonkey.org>
-Date:   Sat Mar 8 11:28:36 2014 -0500
-
-    kamailio.init: fix typo: s/log_faiulre_msg/log_failure_msg/
-
-commit 67c2101fc60e4a963a6133f7a71f5faf510ca214
-Author: Juha Heinanen <jh at tutpro.com>
-Date:   Fri Mar 7 23:54:05 2014 +0200
-
-    modules/xmlrpc: xmlrpc scalar <int> value can be positive or negative
-
-commit 02edf111af9d13e5bed1de768ca9f206a3537483
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Fri Mar 7 11:08:51 2014 +0200
-
-    modules/ims_registrar_scscf:  updated documentation
-
-commit bbcb7da488b7844ab7c64e800895c60cab0dc601
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Fri Mar 7 11:07:11 2014 +0200
-
-    lib/ims/ims_getters: Changed cscf_get_called_party_id to cscf_get_public_identity_from_called_party_id
-    	Changed function to get identity from called part id header instead of full header
-    	Fixes clients that attach extra info (e.g. phone-context)
-    	Changed references to this method in ims_charging and ims_registrar_pcscf
-
-commit 15537553aabfd59bb0fe2af45174ab4a4575120f
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Mar 6 14:51:05 2014 +0100
-
-    nathelper: readme updated for carrier grade nat address space matching
-
-commit 048448f059b64863d41ca146650f7d26b195cdce
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Mar 6 14:49:22 2014 +0100
-
-    nathelper: mention the match of a natted address against rfc6598 (carrier grade nat)
-
-commit b992cfe8e88d069a0b3b0cfa31fe0d60a555cc4c
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Mar 6 14:48:13 2014 +0100
-
-    nathelper: added carrier grade nat address space (rfc6598)
-
-commit 01f76bb99cfd4cebb580ed10ecd478049b038f48
-Author: Charles Chance <charles.chance at sipcentric.com>
-Date:   Thu Mar 6 13:35:46 2014 +0000
-
-    nat_traversal: added RFC6598 shared address space to client NAT tests
-
-commit 7488a1daf3f53a0bfdb8deb1baafa0798de99380
-Merge: 38f8a8e f475f28
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Thu Mar 6 11:18:28 2014 +0200
-
-    Merge branch 'master' of ssh://git.sip-router.org/sip-router
-
-commit f475f2886f37b2a9cb5782ef1f5b9a6e94cee4dc
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Mar 6 09:49:51 2014 +0100
-
-    db_cassandra: return 0 in case of successful operations
-    
-    - following better DB APIv1 convention and avoiding inappropriate
-      failure detection in some modules
-    - reported and patch by Jay Binks
-
-commit 38f8a8e2151337c1515bd50a888c450399a9da9d
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Thu Mar 6 11:00:24 2014 +0200
-
-    modules/ims_qos: use cscf_get_public_identity instead of cscf_get_to_uri in ex_aar.c
-             When getting public identity from To header use ims_getters method instead of reading directly from message
-             This allows ims_qos to identify subscribers to authorize even when clients add extra info
-             (e.g. phone context) after the identity in the request URI
-
-commit 871ca61d1fac900b17d9c6857012e3bf90a71e1a
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Thu Mar 6 10:58:52 2014 +0200
-
-    modules/ims_charging: use cscf_get_public_identity_from_requri instead of msg->first_line.u.request.uri in mod.c and ims_charging.c
-            When getting public identity from Req URI use ims_getters method instead of reading directly from message
-            This allows ims_charging to identify subscribers to charge even when clients add extra info
-            (e.g. phone context) after the identity in the request URI
-
-commit eb8551205f651263f6c7cdf3afa41ad4b77a87e8
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Wed Mar 5 13:40:24 2014 +0200
-
-    modules/ims_charging: updated documentation for new parameter: single_ro_session_per_dialog
-
-commit 909a898ab518dc8ca213cfc2e55b8d01b1f8b59b
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Wed Mar 5 13:37:05 2014 +0200
-
-    modules/ims_charging: new capability to add dialog data to contact when charging session is created
-    	When charging session is created dialog data is added to contact in usrloc (to be removed if contact is removed)
-    	New exported parameter: single_ro_session_per_dialog allows to call Ro_CCR on term and orig in config file but only 1 charging session is created
-
-commit 7ba6a2af28651ba363059cb444832b6cfce9a9db
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Wed Mar 5 13:31:57 2014 +0200
-
-    modules/ims_usrloc_scscf: add dialog data to contact and tear down dialog when contact is removed
-            Added info to contact structure to store active dialogs for contact
-            When contact is removed terminate all active dialogs
-            Added new API functions: api->add_dialog_data_to_contact and api->remove_dialog_data_from_contact
-
-commit 920f02bde0f7b6e3484850f4677c603b9c8740c8
-Author: Juha Heinanen <jh at tutpro.com>
-Date:   Wed Mar 5 07:03:54 2014 +0200
-
-    modules/kex: ask pkg.stats to return array value
-
-commit 864127e6e02144c40c138d6921862b1512d01c66
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Mar 4 17:31:57 2014 +0100
-
-    sqlops: reset the result container before new query is executed
-    
-    - it was lost in commit 9b62514b4a90e169c9126b7bda6d87cc4c213ad2
-    - reported by Jonas Böttner
-
-commit 01cd0a309ea85eaf6509e5266a825f6ffb834964
-Author: Carsten Bock <carsten at ng-voice.com>
-Date:   Tue Mar 4 15:51:04 2014 +0100
-
-    ims_registrar_pcscf: Make sure, the contact stays NULL if the ip,port or reg_state is incorrect.
-
-commit f27df26ca01394250cbe12c5ccf694c6afd3707f
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Mar 4 09:59:07 2014 +0100
-
-    sqlops: safety check for result row field
-    
-    - it might not be set in case of a failure in the middle of result
-      conversion from db to internal memory
-    - freeing the partial result could result in a crash
-    - reported by Juha Heinanen
-
-commit 2cfe0862faafa736b342f15d640581acdf15808c
-Author: Carsten Bock <carsten at ng-voice.com>
-Date:   Tue Mar 4 11:50:19 2014 +0100
-
-    ims_registrar_pcscf: Make sure, Contact-Info-Structure is properly initialized.
-
-commit 80536540caf19a594f91ed9999c7f812f4f40e82
-Author: Carsten Bock <carsten at ng-voice.com>
-Date:   Tue Mar 4 11:35:31 2014 +0100
-
-    kamctl: Minor typo (missing ;;), resulted in Syntax Error: syntax error near unexpected token `)' (on Debian 7)
-
-commit 56ed48bf48c3d78ff5d214833e09a5759f0b5928
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Mar 4 09:43:39 2014 +0100
-
-    geoip: for safety checks for the case when geoip_match() is not executed
-    
-    - but the geoip pv is accessed
-    - reported by Juha Heinanen
-
-commit c318fb9bd1f3674c0bf85f8b50db030039d4e5bd
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Mar 3 21:16:38 2014 +0100
-
-    db_cluster: proper title for example in docs
-
-commit 0411d363ab8eb9cf146852a1c6cd8cf146acfc6d
-Author: Morten Tryfoss <morten at tryfoss.no>
-Date:   Mon Mar 3 19:53:42 2014 +0100
-
-    db_cluster: new parameter max_query_length
-    
-    - set threshold in second after which a connection is marked inactive if
-      the query fails
-    - allow to let connectioncs being active if the error is due to some sql
-      mistake
-    - default is 0 (set connection innactive immediately, same behavior as
-      so far)
-
-commit a9b3286a5ace0f66852054634b46c0647c8d1271
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Mar 3 19:15:30 2014 +0100
-
-    uac_redirect: select the contacts with highest q when a limit is set
-    
-    - reported by  Stefan Prelle, FS#349
-
-commit e395c9bb0131d7fce80af67c54cd813532e5f2ed
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Mar 3 18:16:54 2014 +0100
-
-    kamctl: db connect - new command for db management subset
-    
-    - execute to command line client tool and stay connected using the
-      attributes from kamctlrc
-    - handy when kamctlrc is set, to avoid typing all the attributes when
-      willing to connect to kamailio database
-
-commit 6513ee05dd20253c0f555b18081f0eceb4baf7aa
-Author: Torrey Searle <tsearle at gmail.com>
-Date:   Mon Mar 3 14:54:10 2014 +0100
-
-    app_perl: update constants for debug levels
-
-commit ec9e735955f58ef21bac21ba57eafd07db675e4d
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Mar 3 14:39:25 2014 +0100
-
-    kamctl: delete former fifo files if they exist
-    
-    - reported by Morten Tryfoss, FS#399
-
-commit 47f6cfd76a9d801a83ca14b55926d389f6c3c2da
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sun Mar 2 15:40:17 2014 +0100
-
-    tm: t_continue() polishing
-    
-    - variables declared at beginning of function to work on old C standard
-      compilers
-    - log messages compacted - function name and log level are prefixed
-      automatically
-    - stay under 80 chars per line to fit in text terminals
-
-commit 9e8bda16871191181f3f10c63327ed6c81e153b3
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Sun Mar 2 20:04:09 2014 +0200
-
-    modules/ims_usrloc_pcscf: fields not being added to DB storage on contact insertion
-
-commit dce7353674ea3d93ade93c89bbb4652e7ec624be
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sun Mar 2 10:19:25 2014 +0100
-
-    tm: declare variable at the top of function declaration in t_suspend()
-    
-    - compliant with older versions of C standards
-    - simpliefied log messages
-
-commit 78c8eb1fa4b118661262fd6add9a0e9f60ca8cd1
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sun Mar 2 09:51:40 2014 +0100
-
-    tm: execute FAILURE_CB_TYPE callbacks for resuming suspended request
-    
-    - suspended request creates the transaction and a branch, callbacks
-      cannot executed anymore for request and branch route execution
-    - otherwise it results in crashes, reported by FS#400 and FS#404
-
-commit 6c3725d5535e0b5bff5c63251d37e7139f92321c
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat Mar 1 10:46:57 2014 +0100
-
-    tm: 487 Request Terminated has priority when transaction is cancelled and no reply received from downstream
-    
-    - for cancel_b_method 1, timeout was sent back even when transaction was
-      canceled
-
-commit 721ffe3576e8e7891c27f8578eb244a857ede759
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Feb 27 08:48:42 2014 +0100
-
-    geoip: safety check to see if the result structure is filled
-    
-    - return $null if not
-    - reported by Juha Heinanen
-
-commit a111b33ae7b64dbf9486f2fc4b7f3007f4015e77
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Feb 26 20:30:34 2014 +0100
-
-    parser/parse_fline: print offset in log message when failing to parse first line
-
-commit a9e900a3dd5c958f3188376c3c4d3179c68e2c32
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Feb 26 20:20:29 2014 +0100
-
-    parser/parse_addr_spec: comma allowd for start of tag value and mid tag value chars
-
-commit 6156d2572e06fa661ef23face24c38203485d81a
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Feb 26 19:52:10 2014 +0100
-
-    parser/parse_addr_spec: allow comma in tag parameter
-    
-    - some user agents uses it and it was in older versions
-
-commit 11e9f93d3bad8cfedcd55bdc4fc6c559309c4635
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Feb 26 18:56:44 2014 +0100
-
-    parser/parse_addr_spec: allow comman inside quoted values no matter of being allowed separator
-    
-    - comma is valid inside quoted parameters values
-
-commit 4133a44cc9b1702b3a36b9386464983d2fe9aedc
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Feb 26 18:03:20 2014 +0100
-
-    sl: fixed use of forward_reply_nocb() in sl_forward_reply()
-    
-    - previous related commit was not doing it
-
-commit 0b122416932030c9459f16d46438489b115941aa
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Feb 26 10:45:24 2014 +0100
-
-    mtree: enahced docs to specify that the mtree parameter can be set many times
-
-commit 5e37d0c92024fb5424d3c02368bad5b115c8f971
-Author: Charles Chance <charles.chance at sipcentric.com>
-Date:   Tue Feb 25 20:49:59 2014 +0000
-
-    dmq: added function to broadcast message from config file.
-
-commit 2847c47d7a2cbc15620d6f33b3641be1ca6207a7
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Tue Feb 25 12:30:01 2014 -0500
-
-    htable: README enhancements for array keys
-
-commit 2e4c13669ce025e0315b41a5eefa28fe2ca373a2
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Tue Feb 25 11:34:19 2014 -0500
-
-    htable: fix some copy/paste errors in README
-
-commit 1e47014ccfae08069be00f6786cdb7b10829daa5
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Tue Feb 25 11:20:55 2014 -0500
-
-    htable: remove a leftover debugging log
-
-commit d9c34bec5ea0570f66df23e7e7d6f79f4721f04e
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Feb 24 21:32:45 2014 +0100
-
-    nat_traversal: proper size for realloc
-    
-    - reported by Venky
-
-commit 9b88eb7ee2d243882383a44f601baa21fd679cd5
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Feb 24 19:15:13 2014 +0100
-
-    dialog: don't add dialog profiles when loading from db and state is terminated
-
-commit edf61acb57ed5e8ee0ca9ec1f796e43ce993be48
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Feb 24 18:53:55 2014 +0100
-
-    dialog: remove dialog from profile as soon as gets to terminated state
-
-commit 94bad4414b36334061ef0d3ec42747d672eaf058
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Feb 24 18:17:00 2014 +0100
-
-    mtree: reset tree statistics upon reload
-    
-    - related to FS#398, reported by JoshE
-
-commit 3cdebcbb27568487574ed56274733e5c64431cc0
-Author: Henning Westerholt <hw at kamailio.org>
-Date:   Mon Feb 24 11:23:42 2014 +0100
-
-    pdb: add debian init file
-
-commit 21454415b93773811ff8c4be702956c86fb14366
-Author: Henning Westerholt <hw at kamailio.org>
-Date:   Mon Feb 24 11:23:17 2014 +0100
-
-    pdb: remove pdb from global gitignore
-
-commit 7512ee9d47da257973e4b5bde18ba788d0be47ad
-Author: Henning Westerholt <hw at kamailio.org>
-Date:   Mon Feb 24 11:22:50 2014 +0100
-
-    pdb: move gitignore to own directory
-
-commit d313471b37d77ebd0eedb7cc207b2b94e1f5defc
-Author: Henning Westerholt <hw at kamailio.org>
-Date:   Mon Feb 24 11:10:22 2014 +0100
-
-    pdb: remove internal reference, pointed out from Carsten Bock
-
-commit e82121b95c8418c81072a2d09bd74b3abfe49d27
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Mon Feb 24 11:03:17 2014 +0200
-
-    modules/ims_usrloc_scscf: incorret assignment that causes incorrect shm free on pkg_malloc'd memory
-
-commit 1b2896147423875b1f16d5171cf982d549404e52
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Fri Feb 21 22:56:09 2014 +0100
-
-    pkg/kamailio/deb: update changelog files to dev3 version
-
-commit 5961824bdd52cb71f9b7db4b24d5e136f3110444
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Feb 21 21:14:10 2014 +0100
-
-    registrar: docs updated with expire_range parameter
-
-commit 806e967e2e39e0140b992719e10693b9c768d758
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Feb 21 21:07:43 2014 +0100
-
-    registrar: allow randomization of expire value coming from UA
-    
-    - new parameter expire_range
-    - requested in FS#249
-
-commit 4b595236246a40abac937088c4e8ec5bc5812a52
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Feb 21 20:12:32 2014 +0100
-
-    Makefile.defs: version set to 4.2.0-dev3
-
-commit 895ae33c976adbd44de86c7864b3bb1ae7144bf5
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Feb 21 20:09:33 2014 +0100
-
-    kamailio.cfg: catch OPTIONS keepalive requests in route[REQINIT]
-
-commit 0a4519af5c1ea3f61362fba7451eb4acc479d488
-Author: David M. Lee <dlee at digium.com>
-Date:   Mon Feb 10 15:22:11 2014 -0600
-
-    call_control: Passthrough sip_application
-    
-    Current patches being submitted to CDRTool and the call_control daemon
-    allow for SIP application type to be specified. This allows audio or
-    video services to be rated differently, or even different ratings for
-    application subtypes (audio.inbound vs. audio.outbound).
-    
-    This patch allows the sip_application value to be passed through to the
-    call_control daemon.
-
-commit 376d8b3972d96b70d1e12cc57104475b2ee7ade8
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Feb 21 18:26:34 2014 +0100
-
-    topoh: let replies for CANCEL requests be handled
-    
-    - CANCEL is hop by hop, but can have the call-id hidden when sending out
-
-commit 41f12e01b20a6b32d26297fbdf6ce17d40823ef2
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Feb 21 17:58:19 2014 +0100
-
-    topoh: don't encode/decode content for local generated messages
-    
-    - requests generated by kamailio don't have headers that should be
-      hidden
-    - replies to them don't have anything hidden
-    - update as part of report from FS#390
-
-commit 9ff18b15c24a933fa061663add3223b8256a88d1
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Feb 21 15:37:24 2014 +0100
-
-    core/parser: fix loop on broken values matching the prefix of a good value in parse_option_tag_body()
-    
-    - reported by Savolainen Dmitri, FS#396
-
-commit f46beec41b3b5caa3977ddd452b3671bebf69069
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Fri Feb 21 11:42:27 2014 +0100
-
-    pkg/kamailio/deb: init script. Get back SHM_MEMORY PKG_MEMORY and CFGFILE
-
-commit 1787b4239f3494fe7a88b0868a807e86a3b92639
-Author: Alex Hermann <alex at speakup.nl>
-Date:   Fri Feb 21 00:10:35 2014 +0100
-
-    tm: safety check for uas callid value when callid_matching is 1
-    
-    - according to the documentation is for UA that cannot match the
-      responses when call-id is changed, but is not the case of self
-      generated requests
-    - closes FS#390
-
-commit c33583e6456d3500f8a9c870eb01a01d1a1fe8f4
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Feb 20 23:15:56 2014 +0100
-
-    async: free the async item after resuming the execution
-    
-    - reported by Surendra Pullaiah
-
-commit aa2ee6e1d9482b486ebc3f45b26ea886a2f3dbf0
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Feb 20 11:04:49 2014 +0100
-
-    usrloc: remove the filter on nat_bflag for keepalive contact expiration
-    
-    - keepalives can be sent even for non-natted contacts
-    - reported by Kristian Kielhofner
-
-commit 6f5126e49a5b2ce14c96cf12d0ad1cbbc9fa539a
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Wed Feb 19 20:01:23 2014 +0200
-
-    modules/ims_usrloc_scscf: added DB storage for S-CSCF usrloc
-    	- currently support NO_DB and DB_WRITETHROUGH
-
-commit ba68be91bc206d27284cdaf9fb3ccc189fe33d4a
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Tue Feb 18 16:44:40 2014 +0100
-
-    pkg/kamailio/deb: use freeradius-client lib on sid and jessie
-
-commit 424ab9dd4abd9b11b7cf4642335652145128fa7c
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Tue Feb 18 16:30:28 2014 +0100
-
-    pkg/kamailio/deb: fix init script
-
-commit e8f26d65d7229e048fc2f106919322660710e8d1
-Author: Richard Fuchs <rfuchs at sipwise.com>
-Date:   Mon Feb 17 13:30:21 2014 -0500
-
-    rtpproxy-ng: increase the receive buffer size to 64k
-
-commit e005b899b23c4d85a1b6072cc19ec6bc24d20c7a
-Author: Juha Heinanen <jh at tutpro.com>
-Date:   Sun Feb 16 10:56:24 2014 +0200
-
-    modules/rtpproxy-ng: added setid_avp module param
-        which can be used (instead of set_rtp_proxy_set function) to select
-        used rtpproxy set
-
-commit 92b947059dbde8ada3c757d7e6af48d79f9e7e12
-Author: Juha Heinanen <jh at tutpro.com>
-Date:   Sat Feb 15 04:16:14 2014 +0200
-
-    modules/utils: fixed memory leak and possible crash
-    
-    - patch against 4.0 was provided by Guillaume Bour
-
-commit 8be7de6d1d383c2e0e476e739a6b3fa5101bac12
-Author: Charles Chance <charles.chance at sipcentric.com>
-Date:   Fri Feb 14 10:21:00 2014 +0000
-
-    dmq: fixed crash caused by freeing pointer too early on tm callback
-
-commit ef550ca12e26306214f1e532c6a755d5e33d420d
-Merge: 1d6b1d8 982a002
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Fri Feb 14 10:01:55 2014 +0200
-
-    Merge branch 'master' of ssh://git.sip-router.org/sip-router
-
-commit 1d6b1d8765d7a6d21c291d2076a3a80a1710c11c
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Fri Feb 14 09:57:45 2014 +0200
-
-    lib/ims:modules/ims_charging,ims_icscf,ims_qos,ims_registrar_scscf: fixed pkg_mem leak
-    	- fixed leak when parsing msg headers on a shm msg
-    	- instead now pass in flag to say if parsing is on shm_msg or not (is_shm)
-    	- assumes all common headers are already parsed before pkg_mem msg is cloned
-
-commit 982a002fb89b9a2bcb65d678e1fd37918398e86d
-Author: Juha Heinanen <jh at tutpro.com>
-Date:   Thu Feb 13 22:33:18 2014 +0200
-
-    modules/lcr: add index of selected gw to defunct_gw_avp
-        also when ping_interval value is positive
-
-commit 7611a9595349d4978080efab0ed09b123b0f3cce
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Thu Feb 13 09:37:37 2014 +0200
-
-    modules/ims_registrar_pcscf: fixed pkg_mem leak when sending subscribe
-
-commit f5725d357950527ca202da680bbaaa509e3683fe
-Author: Juha Heinanen <jh at tutpro.com>
-Date:   Thu Feb 13 08:26:08 2014 +0200
-
-    modules/lcr: issue INFO level log message when gw is activated
-        due to valid OPTIONS ping response
-
-commit 059bd9c5576e7e14bc69506330990a165286d9c1
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Wed Feb 12 16:14:35 2014 -0500
-
-    htable: adding flags and expires fields to htable.get RPC command
-
-commit 1fac5be2ee1f36510a27bc5c3dd7d21450a8589a
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Wed Feb 12 13:45:00 2014 -0500
-
-    htable: relax table definition for htable and handle/accept more db types
-
-commit 5c690f5c5cf4f283ad004a28b758871bc2fd5c19
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Wed Feb 12 18:20:51 2014 +0200
-
-    lib/ims: fixed pkg_mem leak when getting service route
-
-commit 4e58ba4608593c4b03ea0cddb5ef7cf83b81a5c8
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Wed Feb 12 14:44:22 2014 +0100
-
-    fix typos detected by lintian tool from built binaries
-
-commit c2a606c1b03b1014caa9053d64d43d09c4744d04
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Wed Feb 12 14:00:16 2014 +0100
-
-    pkg/kamailio/deb: clean lintian warnings
-
-commit 574765a22cbf6844418948c13d07f49f119c0363
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Wed Feb 12 08:59:43 2014 +0200
-
-    modules/ims_charging: change to use asserted_identities for subscription id if present
-    	Change to use asserted-identity header and called-party-id header as subscription id when present, otherwise use from_uri and to_uri as before
-    	Change to use asserted-identity for subscription id when direction is orig and called-asserted-identity when direction is term
-
-commit ec24f51a8efc31864c560054a039aa0c2cd5ab62
-Merge: 71f2247 289c33f
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Wed Feb 12 08:56:37 2014 +0200
-
-    Merge branch 'master' of ssh://git.sip-router.org/sip-router
-
-commit 289c33fcaf2cc93dfad517c8b7bb2a9fcfb4b773
-Author: Juha Heinanen <jh at tutpro.com>
-Date:   Wed Feb 12 05:11:03 2014 +0200
-
-    modules/lcr: fixed name of ping_inactivate_threshold param in README
-
-commit 71f2247cf4dc6f8d3a0b148461322f6b680f1174
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Tue Feb 11 09:42:27 2014 +0200
-
-    examples/config: added p-asserted-identity logic on P-CSCF and add Called-Party_ID AVP on S-CSCF
-
-commit b1d0d33276071f6c69d5cb2215a7b2b1e044764d
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Tue Feb 11 08:49:44 2014 +0200
-
-    modules/ims_registrar_pcscf: Added new exported function pcscf_assert_called_identity
-    	pcscf_assert_called_identity function used to assert the identity for SIP responses
-    	Function retrieves Called-Party-ID AVP from SIP request and adds to SIP response as P-Asserted-Identity as per TS 24.229 section 5.2.6.4.4
-
-commit 12d0feed38cd036cbc0e7c9f0c0c540d0e9eca4a
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Tue Feb 11 08:48:34 2014 +0200
-
-    lib/ims: added function to get Called-Party_ID AVP from message
-
-commit b6abf075448de90a7b135dfa42e58fa61255ca2e
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Tue Feb 11 08:44:26 2014 +0200
-
-    modules/ims_charging: allow E164 to be used as subscription-type in CCR requests
-
-commit 532459374af8354c030fdce8ff837beab793be6c
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Tue Feb 11 08:41:27 2014 +0200
-
-    modules/ims_qos: use asserted_identity for subscription-id and allow e164 as subscription type
-    	use p_asserted_identity as default subscription-id for AAR requests
-    	allow E164 to be used as subscription type for AAR requests
-
-commit 5b7255d8861d699903692f1457e3e60d9f39837c
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Tue Feb 11 07:52:50 2014 +0200
-
-    modules/ims_usrloc_pcscf: added new hash storage based on IP:PORT. backwards compatible with original scheme using new modparam
-    	- new modparam is hashing_type - see module documentation
-
-commit 065439c0fbabe2806fcd615cec5e2445db59beec
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Mon Feb 10 19:41:20 2014 -0500
-
-    htable: fix crash if key_value is not string
-
-commit 3630f36c1e34562e93267d87f9e83a69cf8dd861
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Mon Feb 10 18:05:12 2014 +0200
-
-    modules/ims_registrar_pcscf: Add domain unlock to prevent deadlock when processing notifies
-
-commit 5e5377bc0f4f30b84cfdd2ac50813f82a6b52870
-Author: Juha Heinanen <jh at tutpro.com>
-Date:   Sun Feb 9 11:07:08 2014 +0200
-
-    modules/sctp: reverted accidental commit on sctp module while committing
-      lcr changes
-
-commit 85fdd590ca7b8e29c9fb7b8385d534418da05cf1
-Author: Juha Heinanen <jh at tutpro.com>
-Date:   Sun Feb 9 10:58:48 2014 +0200
-
-    modules/lcr: added capability to inactive a faulty gateway and re-activate
-      it automatically by successful response to OPTIONS ping
-
-commit 3cde37cf10795b4eb785ffd141a8b28e64864f5d
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Feb 6 16:03:27 2014 +0100
-
-    db_cassandra: clone key in a zero-termniated local buffer
-    
-    - rework from a patch by Jay Binks
-
-commit 740d407be4e35ee945658365ae38a1bba30fafc7
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Feb 5 09:52:19 2014 +0100
-
-    core: fix condition on script callback number done inside EXTRA_DEBUG
-    
-    - reported by Seudin Kasumovic, FS#388
-
-commit 34720cbbf6f448a727a34164b690dabf393684ec
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Mon Feb 3 14:21:09 2014 +0100
-
-    pkg/kamailio/deb: clean lintian errors
-
-commit 3d1541f9c2b09171e703ddae0137dbb5758f6969
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Mon Feb 3 14:13:15 2014 +0100
-
-    pkg/kamailio/deb: update debian copyright file
-
-commit 408178aa7516e661818b847f52185f4ac3cde941
-Author: Carsten Bock <carsten at ng-voice.com>
-Date:   Tue Feb 4 09:49:20 2014 +0100
-
-    tm: Fix docs on t_relay_to (Typo)
-    (as noticed by Victor V. Kustov)
-
-commit 32f688659fcc6f7c44d9095e585951780e277522
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Feb 3 11:40:43 2014 +0100
-
-    db_cluster: updated the old application name in doc examples
-
-commit 4b0e63b74db47712335f97b54675c82a058ee0da
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Mon Feb 3 11:13:46 2014 +0100
-
-    pkg/kamailio/deb: update changelog files to dev2 version
-
-commit 9623eaa91daf85affcaf9377ae85f2782ae614c9
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Mon Feb 3 09:28:15 2014 +0100
-
-    pkg/kamailio/deb: wrap-and-sort control files
-
-commit 806489af70241ab6825a5e6e7cd00bb9c6e33e1a
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Thu Jan 30 18:17:12 2014 +0100
-
-    pkg/kamailio/deb: unifying debian packaging
-
-commit a4b1683f89708e311f6a37b4ab57004391e49cc9
-Author: Alexandr Dubovikov <alexandr.dubovikov at gmail.com>
-Date:   Mon Feb 3 11:07:48 2014 +0100
-
-    modules/sipcapture: Added X-Rtp stats from Siemens and MediaProxy-Ng.
-    
-    	Thanks Lorenzo Mangani for the patch.
-
-commit c3466508d9486b566dff62ecbc0c509eacdd924e
-Author: Carsten Bock <carsten at ng-voice.com>
-Date:   Mon Feb 3 10:04:06 2014 +0100
-
-    presence: Regenerated README
-
-commit 77d81c02bf24b5ef266ad6dfecf393342cfe4000
-Author: Carsten Bock <carsten at ng-voice.com>
-Date:   Mon Feb 3 09:58:59 2014 +0100
-
-    presence: Clarify the db_lock_type in the docs in conjunction with the mode DB_ONLY and a MySQL-Backend.
-
-commit 5a6fbb29f5776743df4a97ce93b848d662da6b08
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Feb 3 09:58:37 2014 +0100
-
-    Makefile.defs: version set to 4.2.0-dev2
-
-commit e697c6c912fda05dfb19efd54155da3fe730e778
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Fri Jan 31 09:51:22 2014 +0200
-
-    examples/pcscf and scscf: Changed config file to use new P-CSCF subscription and publish reg event
-
-commit 0dc253581ee3c7699c69edac695379dd68b1a902
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Fri Jan 31 09:48:02 2014 +0200
-
-    modules/ims_qos: Changed Rx event processor child from PROC_NOCHLDINIT to PROC_SIPINIT
-
-commit ddc93ce8a9b39faf29e0a2f6b1fa5a48609945ce
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Fri Jan 31 09:45:55 2014 +0200
-
-    modules/ims_registrar_pcscf: New features to support P-CSCF subscription and publishing reg event
-    	Migrated pua_reginfo functionality to ims_registrar_pcscf so ims_usrloc_pcscf is used
-    	New features include subscribing to reg event on Registration, processing notifications and publishing when reg event changes
-
-commit 784280cfacf0f1459481aab12bb2739bd3ab84cd
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Fri Jan 31 09:42:59 2014 +0200
-
-    modules/ims_registrar_scscf: New features to fully support subscription to reg_event
-    	Main change to support PUBLISH of reg event information
-    	And to use new usrloc API storage of callid/totag/fromtag presentity combination to correctly process usbsequent SUBSCRIBE
-
-commit 5bf9b5669da36d395b8b0f2af4ebc2d078c4249e
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Fri Jan 31 09:39:07 2014 +0200
-
-    modules/ims_registrar_scscf: lookup.c - fixed term_impu_registered to work for tel URI as well as SIP URI
-
-commit 73ad320cc6ddc2df267cc05b3856eed1698c0e3b
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Fri Jan 31 09:36:57 2014 +0200
-
-    modules/ims_usrloc_scscf: New features to fully support subscription to reg_event
-    	Main change add API to presence module library to store the callid/totag/fromtag presentity combination
-    	Also only remove IMPU from usrloc if there are no subscriptions to it
-
-commit 52c05835058a0813df1bf2291669bfe539f52a71
-Author: Luis Martin Gil <martingil.luis at gmail.com>
-Date:   Fri Jan 31 02:46:17 2014 +0000
-
-    	pkg/centos: added snmpstats MIB files to spec file
-    
-    	- Some files were missing from the snmpstats module
-    	when packing into rpm. Adding them to the rpm spec file
-
-commit 40ea6ffd76cf32aafc594038d17555edbc816b50
-Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
-Date:   Thu Jan 30 21:58:43 2014 +0000
-
-    mqueue: Add new psuedo-variable to return mqueue size
-    
-    - Using PV will return a value when the length is zero
-
-commit 011809fb0c7e616745224cd559d8215d86771444
-Author: Carsten Bock <carsten at ng-voice.com>
-Date:   Thu Jan 30 21:55:11 2014 +0100
-
-    presence: bugfix: Add option to disable per-Table lock for database layer
-    (causes trouble with MySQL in DB_ONLY mode)
-
-commit c57e597c99db09bea2bfa9533b2553ede0572720
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Thu Jan 30 14:25:02 2014 -0500
-
-    dialog: fix datestop output for list* RPC commands
-
-commit b61f173a8dc40592809912e137e42d8ffe1154fa
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Jan 30 12:14:48 2014 +0100
-
-    core: test the limits of nested select level before accessing array value
-
-commit e7a0840a1334280650d4abb865843da0072adec6
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Jan 30 12:12:44 2014 +0100
-
-    utils/db_berkeley: release file description in error cases
-
-commit 2977c559d89ba7e04b9b5a32336baa9789078921
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Thu Jan 30 11:33:51 2014 +0200
-
-    modules/ims_usrloc_pcscf: fix segfault when running in DB mode (deleting contact)
-
-commit d0ebc7fa4b4b20bee83f57b3f0d0e6e75b5f0b08
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Jan 29 22:10:09 2014 +0100
-
-    sercmd: memset with proper size
-
-commit 33e7e899e5aa7dc291ec45a711100e6200896f14
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Wed Jan 29 15:39:47 2014 -0500
-
-    dialog: enhance list* RPC commands
-     - human readable format for dialog start/stop timestamps
-     - adding lifetime parameter
-
-commit 5b21e976eee13579a309a5626ff8d676fd1ccdc0
-Merge: 039c0c9 cfb815e
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Wed Jan 29 09:05:01 2014 +0200
-
-    Merge branch 'master' of ssh://git.sip-router.org/sip-router
-
-commit 039c0c9f926c6f755211b5392f1ae4040a56d5ad
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Wed Jan 29 09:03:26 2014 +0200
-
-    modules/rls:  Edit to cater for changed presence API
-    	Presence API has changed - delete_shtable now takes subs_t pointer instead of str to_tag to compare full dialog tag set
-
-commit 74d73953327ad7702922b27ba37c71e3283659c3
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Wed Jan 29 09:00:37 2014 +0200
-
-    modules/presence: Changed delete_shtable function to check dialog's full tag set
-    	Changed delete_shtable to take subs_t pointer as parameter to compare dialog's full tag set before deleting
-    	This changes presence API and delete_shtable is exported function - only effected module is rls
-
-commit cfb815e440804c2870126c1c098362d5a117f97c
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Jan 28 18:54:50 2014 +0100
-
-    core: avoid warning of using bitwise operator with boolean result
-    
-    - on a report generated by cppcheck sent by David Binderman
-
-commit 935f06eb8c34fe5fe82588cdd5b4af2f68c51466
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Jan 28 18:47:42 2014 +0100
-
-    core/parse_methods: removed duplicate check for same characters
-    
-    - on a report generated by cppcheck sent by David Binderman
-
-commit 79bfabdc2ae35a5b280c6a23ff611a005dac333c
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Jan 28 18:43:13 2014 +0100
-
-    xhttp: check first the possition limits then access the data
-    
-    - in the eval function for the transformation
-    - on a report generated by cppcheck sent by David Binderman
-
-commit 480b6d4dfc954fbbb8afb9dbbbf17b80dcdf71ce
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Jan 28 18:39:19 2014 +0100
-
-    db_postgres: fixed condition checking the parameter for db uri parsing
-    
-    - on a report generated by cppcheck sent by David Binderman
-
-commit c0b2e567b2a27d5d29ede39409d6299f7d375d87
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Jan 28 18:36:21 2014 +0100
-
-    db_mysql: fixed condition checking the parameter for db uri parsing
-    
-    - on a report generated by cppcheck sent by David Binderman
-
-commit 88a1a1b25b5228ef2e34ee01e0dd5d4e4f6ffe20
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Jan 28 18:30:30 2014 +0100
-
-    db_cluster: fix caseness in testing the connection flags for reading
-    
-    - on a report generated by cppcheck sent by David Binderman
-
-commit 1d63ad4715cf046955f27726f3d0003fcfb5ffac
-Author: Andrew Mortensen <admorten at isc.upenn.edu>
-Date:   Mon Jan 27 12:03:55 2014 -0500
-
-    modules/sca: use sca_create_canonical_aor in INVITE/2OO OK handler.
-    
-    - abstract AoR construction for future improvements.
-
-commit ba5c2f973cafcb1d871337ffefb8fa95f5463eee
-Author: Andrew Mortensen <admorten at isc.upenn.edu>
-Date:   Mon Jan 27 12:01:19 2014 -0500
-
-    modules/sca: optionally update call-info state for only caller or callee.
-    
-    - sca_call_info_update can now take an int argument (1=caller, 2=callee)
-      limiting call-info state update to only that leg's AoR.
-
-commit b03e871a62f3895bfb70fe5b72b0142afa613684
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Mon Jan 27 16:29:46 2014 +0100
-
-    pkg/kamailio/deb: fix typo on depends
-
-commit e56ff0e6a5745321c6a4a5f362cc728177acef0d
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Jan 24 15:43:59 2014 +0100
-
-    core/parser: handle the case when username field in auth header has proto scheme
-    
-    - some phones put there "sip:username at domain", so far it was handling
-      "username" and "username at domain"
-
-commit cbd525649237c3beb05ad7bcb38969fb3629b90e
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Jan 24 08:56:20 2014 +0100
-
-    gzcompress: fixed info about header_value parameter in docs
-
-commit 20302744b22858e0e215e74e2a6656677881bb4a
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Thu Jan 23 17:25:04 2014 +0200
-
-    modules/presence: fix crash in main/attendant process when using presence module in library mode
-
-commit 48bb4b562d7d7ec20b45dbe555836bb8969b988d
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Thu Jan 23 17:21:04 2014 +0200
-
-    modules/rls: changed default hash size from 512 to 9 to avoid overflow
-
-commit b9b83d251810f70545c72c2207b2864460572872
-Author: Henning Westerholt <hw at kamailio.org>
-Date:   Thu Jan 23 13:14:02 2014 +0100
-
-    memcached: add new parameter 'stringify', patch from Federico Cabiddu
-    * add a new parameter 'stringify' to the memcached module to force the module
-      to evaluate all returned values as strings. This is useful if other parts
-      of the memcached infrastructure are not able to set the correct value flags
-    * patch from Federico Cabiddu, federico dot cabiddu at gmail dot com
-    * add documentation for the new parameter
-
-commit f9ab76f6a82776d9ec48daedbc6880b0b21e552d
-Author: Henning Westerholt <hw at kamailio.org>
-Date:   Thu Jan 23 13:06:47 2014 +0100
-
-    memcached: fix doc section IDs, copy and paste error from dmq
-
-commit cd007447bdd3fc4caa2d8eec3cec8a7b16422c10
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Jan 22 23:27:19 2014 +0100
-
-    cnxcc: formated some examples not to exceed boundaries of blocks in html output
-
-commit cdbcef56191e48c0277ff56e078eeaa20946422f
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Jan 21 10:22:10 2014 +0100
-
-    dispatcher: readme was updated
-
-commit f210c266311498393b93d66b41e8c08d89cbc731
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Jan 21 10:13:51 2014 +0100
-
-    dispatcher: more details on how destination select functions work
-
-commit 1b53001ad3ad1e9bfd3e64f8e03c35d4e5f54e8d
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Jan 20 17:24:18 2014 +0100
-
-    tm: free from and to display names that can be set for local request from seas module
-    
-    - reported and patch by Ziad Habchi
-
-commit 70b082b0abfbee473e3742280b0ea72cf0d73a1e
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Mon Jan 20 10:23:58 2014 -0500
-
-    kex: update README file
-
-commit 3615f3c26405f1c1bcd3721674e9d87e4b589146
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Thu Jan 16 18:02:31 2014 -0500
-
-    xhttp_rpc: fix arg parsing
-
-commit 6f685460f1d7fd6ff07e55f2a807322168638988
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Thu Jan 16 14:46:32 2014 -0500
-
-    kex: new stats RPC commands
-
-commit f3f2f09beda60e1f7f4e6dfc0359f788991aeef6
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Thu Jan 16 13:08:29 2014 +0200
-
-    modules/tm: fixed bug where AVPs are not restored correctly if async used within failure route
-    	- related to mail by José Seabra on Jan 10 2014 entitiled - kamailio-4.1.1 avp issue within failure routes
-
-commit ed33effd4a65302cd893ef2e8f0f8fcc3e88fb57
-Author: Torrey Searle <tsearle at gmail.com>
-Date:   Thu Jan 16 12:02:09 2014 +0100
-
-    modules/sipt: optional pointer should be updated when modifying called party
-
-commit 662bfcf71aae0ec7aa74996a447e48f82fb5dfdc
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Jan 15 17:01:07 2014 +0100
-
-    dispatcher: readme regenerated with updated config example
-
-commit a248b53249d76e6b53f72bc64acd4c14fb5db660
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Jan 15 17:00:45 2014 +0100
-
-    dispatcher: updated example config to use new db url attributes
-
-commit 2f9e8d2e122edc5b7950ee6ab0991851c9cd7bbd
-Author: Carlos Ruiz Diaz <carlos.ruizdiaz at gmail.com>
-Date:   Tue Jan 14 10:04:53 2014 -0300
-
-    db_cassandra: bug fixes for raw queries using sqlops
-
-commit 555d01b145763ead41e22abf98130e1d3ff35739
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Tue Jan 14 12:30:26 2014 +0200
-
-    modules/ims_registrar_pcscf: added -lpthread to Makefile to fix on Ubuntu 12
-
-commit d3ddb1766fad5f197023a7d6a18cfce64cdb9f8d
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Tue Jan 14 12:29:58 2014 +0200
-
-    modules/ims_qos: added -lpthread to Makefile to fix on Ubuntu 12
-
-commit aea7e2bd069a0c130d5fe1d05d128b580df20c5b
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Tue Jan 14 12:29:00 2014 +0200
-
-    modules/cdp: added -lpthread to Makefile to fix on Ubuntu 12
-
-commit 777548d79f17a6eb81d241e18b22329e9654e951
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Jan 14 08:59:17 2014 +0100
-
-    snmpstats: fixed path for deploying mibs when net-snmp-config is used
-
-commit 99ed4d76ceb77b451e99f969513575e655738e81
-Author: Carsten Bock <carsten at ng-voice.com>
-Date:   Mon Jan 13 12:04:13 2014 +0100
-
-    ims_registrar_scscf: Fix memory corruption in build_contacts, in case no contacts available
-
-commit cdc55243b6d977315d169d527b199b318b04863e
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Mon Jan 13 11:29:16 2014 +0200
-
-    modules/ims_usrloc_pcscf: added future DB modes... not yet supported
-
-commit d812a8ef9e02f9d3e0d98a57c33dcaffed76b559
-Author: Jason Penton <jason.penton at gmail.com>
-Date:   Mon Jan 13 11:21:45 2014 +0200
-
-    modules/ims_usrloc_pcscf: Added DB support for persistent storage
-    	- currently supports Write-Through mode.
-
-commit 5bb685592660b6d55238c343d3cee0fbde8ef607
-Author: Carsten Bock <carsten at ng-voice.com>
-Date:   Sat Jan 11 01:39:21 2014 +0100
-
-    ims_auth: Fix for SIP Digest (Segmentation fault)
-    - Fix by Marek Bazler (marek.bazler at acision.com)
-
-commit 5dde71f7fb9715a18dabfe0beeb152b0821c6fb0
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Jan 9 19:19:31 2014 +0100
-
-    snmpstats: use $(share_prefix) for deploying MIBS
-
-commit 619cbfa607882512c8bd458a39cb497d6d6593cb
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Wed Jan 8 19:17:04 2014 +0100
-
-    pkg/deb: Add 4.2.0~dev1 version
-
-commit 3da6084797b9f78a555a3108c5bb08e176a10da6
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Jan 8 18:24:04 2014 +0100
-
-    Makefile.defs: version set to 4.2.0-dev1
-
-commit b5993240da29f1c13a2900ecf479f95973afd599
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Jan 8 18:23:04 2014 +0100
-
-    dialog: added prefix to global variable to reduce the risk of symbol conflict
-
-commit cf6e157bc8a8ce44102bb47f8527e2d663e8c678
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Jan 8 18:17:19 2014 +0100
-
-    dialog: added missing semicolon
-
-commit 97c3a6ad01700f2c2d03e163df65c5aba097165c
-Author: Federico Cabiddu <federico.cabiddu at gmail.com>
-Date:   Wed Jan 8 12:17:49 2014 +0100
-
-    modules/dialog: docs updated for timeout_noreset parameter and timeout-noreset property
-
-commit c70823c0454561dda63eb1e95f66bd96605474db
-Author: Federico Cabiddu <federico.cabiddu at gmail.com>
-Date:   Wed Jan 8 10:43:00 2014 +0100
-
-    modules/dialog: added parameter and dialog property to disable timeout reset
-
-commit 80d55e19f18a93cc15f7f4eadb2828210bf15970
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Jan 8 18:09:18 2014 +0100
-
-    uac_redirect: fixed typo in comments
-
-commit 37e8d6478f677be90178f26ac9348e2f9fd38a58
-Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
-Date:   Wed Jan 8 09:45:22 2014 +0000
-
-    rtpproxy: Documentation: clarify rtpp_inst_pvar usage
-    
-    - The instance 'URL' is stored in the pvar
-    - Added an example usage
-
-commit b393656c1113eb3630470389f142c53fbc085a90
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Tue Jan 7 13:59:37 2014 +0100
-
-    usrloc: add user_col to the update contact query with instance
-
-commit 3a5af040ed8dc84d37a8e1d21d9b1fbe4cf2263d
-Merge: 221cdf8 34d9088
-Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
-Date:   Tue Jan 7 11:57:31 2014 +0000
-
-    Merge branch 'master' of ssh://git.sip-router.org/kamailio
-    
-    * 'master' of ssh://git.sip-router.org/kamailio:
-      permissions: fixed previous commit which used invalid variable
-      presence_dialoginfo: handle all states to get most relevant xml
-      tls: the pointer of cfg structure
-      websocket: store sub protocol value for later use in encode_and_send_ws_frame()
-      htable: free temporary slots used to reload hash table via rpc command
-      htable: use system malloc for temporary allocation of hash table realod slots
-      permissions: refreshed the README file
-      permissions: note about peer tag mode that applies only for allow_trusted()
-      permissions: set peer tag avp for allow_address_group()
-
-commit 221cdf8497c2375133dd73ff0bed44ed6180245b
-Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
-Date:   Tue Jan 7 11:11:23 2014 +0000
-
-    rtpproxy: Allow any pvar for rtpproxy instance
-
-commit 34d9088d74cb8269960cc20912a675a67598e7d7
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Jan 7 10:23:11 2014 +0100
-
-    permissions: fixed previous commit which used invalid variable
-    
-    - reported by Kelvin Chua
-
-commit f845465eb96770e0c02c92ae862cdc94f561e29e
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Jan 7 00:58:20 2014 +0100
-
-    presence_dialoginfo: handle all states to get most relevant xml
-    
-    - patch from FS#341
-
-commit 208934d47ac1585d42029234267bcceab40ae218
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Jan 7 00:10:34 2014 +0100
-
-    tls: the pointer of cfg structure
-    
-    - synchronize when updating the list of tls configs and their reference
-      count
-    - with parts from patch by Ding Ma, FS#380, contributed under BSD license
-
-commit 438eafc92ecf9d3b52f95c9952bc26b147fdf328
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Jan 6 23:11:33 2014 +0100
-
-    websocket: store sub protocol value for later use in encode_and_send_ws_frame()
-    
-    - the ws connection pointer can be set null if the browser closes the
-      connection
-    - patch by Vitaliy Aleksandrov, FS#364
-
-commit f35c49085bdcc623ef45aa33a99af3265d3e6eeb
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Jan 6 22:52:11 2014 +0100
-
-    htable: free temporary slots used to reload hash table via rpc command
-    
-    - use system memory for temporary slots
-
-commit 13626ccffeaa7654c58576c3d1cc417dea865ca9
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Jan 6 22:46:48 2014 +0100
-
-    htable: use system malloc for temporary allocation of hash table realod slots
-    
-    - copes better with large number of slots, without a need to use shm
-
-commit 2fd9fe3b46d21f9e958b09162ec6f2fd1ed04ec7
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Jan 6 19:52:13 2014 +0100
-
-    permissions: refreshed the README file
-
-commit 15f8a92baf58ee70e837b3b7e7f208b1a2678a0a
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Jan 6 19:51:41 2014 +0100
-
-    permissions: note about peer tag mode that applies only for allow_trusted()
-
-commit 0c67042fa629ee4744cfc31a15e571b7340b0881
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Jan 6 19:48:54 2014 +0100
-
-    permissions: set peer tag avp for allow_address_group()
-    
-    - also for allow_source_address_group()
-    - reported by Kelvin Chua
-
-commit 661d7d3a6231713861a8a1236dd7d783113c2890
-Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
-Date:   Sun Jan 5 18:16:04 2014 +0000
-
-    modules/websocket: added OpenSSL licensing exception
-
-commit 6741c47ad75806355cd7564d419df56acc68987b
-Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
-Date:   Sun Jan 5 18:15:33 2014 +0000
-
-    modules/outbound: added OpenSSL licensing exception
-
-commit 99960be1d55df2ba4ca596c42c8e78e36dad3cf1
-Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
-Date:   Sun Jan 5 18:15:07 2014 +0000
-
-    modules/auth_ephemeral: added OpenSSL licensing exception
-
-commit d1869a457268fed9dc55d55a475a44cd3e2a3ef6
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Fri Jan 3 13:09:06 2014 +0100
-
-    app_lua: remove duplicate code and merge functionality for sr.xavp.get
-
-commit 55280b28321d735babbdb529c78a0f0a458e524f
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Fri Jan 3 10:02:30 2014 +0100
-
-    app_lua: sr.xavp.get() allow get all values of a var and <0 indx
-
-commit 80710111c0ca30b0965a0d2df472c00bbd171050
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Jan 3 10:08:48 2014 +0100
-
-    acc: regenerated README
-
-commit d26eff22c8a543c63a40cd7d91bb3c70f04aabc6
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Jan 3 10:04:39 2014 +0100
-
-    acc: added note about MySQL InnoDB not supporting INSERT DELAYED
-    
-    - reported by Daniel Tryba
-
-commit cff3406513c30d41ce1118a1f0997e254531bdb9
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Fri Jan 3 08:57:17 2014 +0100
-
-    acc: refresh README
-
-commit 1e82ef702f9a0c3dec3e24e4f91dc879d7ba5280
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Thu Jan 2 20:39:43 2014 +0100
-
-    acc: add documentation note indicating the use of pseudo-variables
-
-commit 81c6e0bc108b8f4211ffade6de7a7448d1ba72f9
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Thu Jan 2 20:39:43 2014 +0100
-
-    acc: allow pseudo-variables as first parameter for functions.
-
-commit 53689b55632c6208e6326f1a5f4b3c45da216f43
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Jan 2 13:22:28 2014 +0100
-
-    htable: use pkg for temporary hash table slots used for reload
-    
-    - free the temporary slots after reload, reported in FS#385
-
-commit 3ca144aed1e550eac919b6c36a5103acdedbe22b
-Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
-Date:   Sat Dec 21 19:05:37 2013 +0000
-
-    pkg: Add gzcompress module to CentOS spec file
-
-commit e7dc20ba0b787a05ab111367f6f8b176f92826b9
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Jan 2 11:27:02 2014 +0100
-
-    modules: refresed READMEs for some modules that had xml files updated
-
-commit 99d1170469c60206992c083f2ba0e9dc6b580d37
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Jan 2 11:25:56 2014 +0100
-
-    tmrec: updated the examples with tmrec duration
-    
-    - hint to read rfc2445 for duration format
-
-commit cc34c8e2c1e0eeafa0088c2d159260e4b10652c9
-Author: Alexandr Dubovikov <alexandr.dubovikov at gmail.com>
-Date:   Tue Dec 31 23:24:02 2013 +0100
-
-    modules/sipcapture:  Fixed bad timestamp in the raw socket mode
-    
-    HEPpy New Year!
-
-commit 0e0b8cd883718bb5d19999e800159add7714f69e
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Dec 27 23:31:41 2013 +0100
-
-    htable: added section id for functions and parameters
-
-commit 4eb338611e716e7a32f252acbae52bace6047a0a
-Author: Juha Heinanen <jh at tutpro.com>
-Date:   Thu Dec 26 17:51:04 2013 +0200
-
-    modules/pua: added some missing lock releases
-
-commit ef66bf4ce961a7379bb21e848f70d03defb8864c
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Fri Dec 20 10:09:35 2013 +0200
-
-    modules:/ims_registrar_scscf: when processing subscriptions to reg events allow the ruri to be the contact of the S-CSCF and get the presentity from the to-header
-
-commit 81b9c83b2fa3bd32d502a1ae9014cc7d6747e710
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Dec 19 21:15:12 2013 +0100
-
-    acc: use r-uri winning branch even for local generated replies
-    
-    - it was only for received and relayed replies
-    - reported by Kelvin Chua
-
-commit 8b023bbab187020bff7883bad1e671c3cf2860c6
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Dec 19 20:49:38 2013 +0100
-
-    kamctl: don't force global exit if gdb is not found
-    
-    - it is not a general requirement, only for trap command
-
-commit e54b3ec673cb32664a1e8de2e591190f22216724
-Author: Juha Heinanen <jh at tutpro.com>
-Date:   Thu Dec 19 16:21:25 2013 +0200
-
-    modules/pv: fixed params and param transformation
-    
-    - params need to be taken from sip_params field of sip_uri struct
-
-commit b488b17294b73b5b42a4f8205a8fd4b43a5f588c
-Merge: 52d727d 7138022
-Author: Carlos Ruiz Diaz <carlos.ruizdiaz at gmail.com>
-Date:   Wed Dec 18 15:30:28 2013 -0300
-
-    Merge branch 'master' of ssh://git.sip-router.org/sip-router
-
-commit 52d727dc249a88b31348b008045cc6071ab215a7
-Author: Carlos Ruiz Diaz <carlos.ruizdiaz at gmail.com>
-Date:   Wed Dec 18 15:28:39 2013 -0300
-
-    ims_registrar_scscf: fix crash caused by an uninitialized AVP
-
-commit 71380228bf5804f51292205de2dfae1b4945b9de
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Tue Dec 17 12:53:20 2013 -0500
-
-    utils/kamctl: new command 'trap'
-     - useful to get a full bt dump of all kamailio processes
-     - handy in dead-lock investigatigations
-
-commit 09b7a15e24800a5617695722a43d92b6fedfd77f
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Mon Dec 16 09:04:15 2013 +0100
-
-    pkg/kamailio/deb: merge changes from Debian
-
-commit 2f310077fd5b89ebec0d3ac6e001a0d9ba6702e2
-Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
-Date:   Mon Dec 16 15:57:25 2013 +0000
-
-    ims_registrar_pcscf: Use correct modparam for configurable fallback2ip
-
-commit 4243c57511007f5af5df6d29939189925fd023da
-Author: Carsten Bock <carsten at ng-voice.com>
-Date:   Mon Dec 16 11:08:29 2013 +0100
-
-    ims_registrar_pcscf: Fallback to IP/Port/Proto search is now configurable; fallback to ip-search will be done, if no contact-header present (and the fallback is enabled).
-    
-    Thanks to Camille Oudot & Hugh Waite for the improvement requests!
-
-commit b15aefa31e45f1ad6a45b64905f9fae24e0f790e
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Dec 16 09:26:03 2013 +0100
-
-    db_flatstore: update timestamp for kamailio specific rpc rotate
-    
-    - do also in 'rotate' command, not only in 'k_rotate'
-    - from a patch by Abdelkader Allam
-
-commit 50b647f0e51ee951c1a6441e8bb99228980dbd89
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Sun Dec 15 20:07:10 2013 +0100
-
-    snmpstats: use basedir for INSTALLMIDIRS
-
-commit 61e1237c158edb1c83a656dd91e7665867b8fe74
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Sun Dec 15 08:49:42 2013 +0100
-
-    pkg/kamailio/deb: add openssl dependence
-
-commit ded4959bf1954dc114c9503d8294e7287bf373e7
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Thu Dec 12 10:09:07 2013 +0100
-
-    pkg/kamailio/deb: set JAVA_HOME and use libgcj12-dev instead of gcj-jdk
-
-commit 5c1b8e0f0f5565aa69440a331c520fc549856092
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Thu Dec 12 08:53:59 2013 +0100
-
-    app_java: detect JAVA_HOME and use proper libgcj versioning
-
-commit 0620105b03dce2391b98374b1ec6d08f48040594
-Author: Seudin Kasumovic <seudin.kasumovic at gmail.com>
-Date:   Thu Dec 12 15:58:48 2013 +0100
-
-    mtree: added mi/rpc command to match against records in memory trees
-    
-    - FS#373
-
-commit ab75785aa707f10fdbccfb0531a0f35e820f5ebc
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Dec 12 15:50:27 2013 +0100
-
-    snmpstats: fixe MIB file definitions
-    
-    - patch by takeshi, FS#363
-
-commit 0ebc983a422cd5ee4baa39bb3ef3bdbeeefd4571
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Dec 11 23:58:11 2013 +0100
-
-    tm: reset temporary linking of reply to transaction after branch failure route execution
-    
-    - reported by Robert Boisvert, FS#379
-
-commit 3c88f1de9d647db8a14bae45af1fa3b34f74d4e6
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Dec 11 23:01:41 2013 +0100
-
-    avpops: create a local pv structure when parameter is only flags
-    
-    - flags details are stored inside it
-    - fixes crash at startup reported by Kevin Scott Adams, FS#381
-
-commit a44d5311b583bc457b44550870dfbd4ea3fbcea4
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Wed Dec 11 14:11:19 2013 +0100
-
-    pkg/kamailio/deb: removing lucid
-
-commit 4d4ab8becd7d806f8cae43149aab1e73bbe54969
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Wed Dec 11 13:48:36 2013 +0100
-
-    pkg/kamailio/deb: use gcj-* instead default-* one
-
-commit af1734cea213b2a07c9d725fff158cd4899725d1
-Author: Carsten Bock <carsten at ng-voice.com>
-Date:   Wed Dec 11 13:47:57 2013 +0100
-
-    lib/ims: Replaced custom getter for P-Asserted-Identity with the Parser from Core
-
-commit 943a5941f5ab479803fb30e19e9fa607f0f0fe14
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Dec 11 09:49:52 2013 +0100
-
-    core: safety check for double free in q_malloc as in f_malloc
-
-commit 838e2d42a90a9368d77113b87fe8cce190b82575
-Author: Juha Heinanen <jh at tutpro.com>
-Date:   Wed Dec 11 03:19:44 2013 +0200
-
-    modules/dialplan: increased size of repl_exp and attrs cols to 64 chars
-
-commit d32b9a32327183c6ec536ec5959038f8bd20d7fa
-Author: Carsten Bock <carsten at ng-voice.com>
-Date:   Mon Dec 9 23:15:42 2013 +0100
-
-    ims_registrar_pcscf: ims_usrloc_pcscf return 0 if found, not 1
-
-commit caa9954d3c017ce741245d8f2b338158caf2270f
-Author: Carsten Bock <carsten at ng-voice.com>
-Date:   Mon Dec 9 23:00:08 2013 +0100
-
-    Improved Free at cscf_get_service_route(), caused a reproducable crash
-
-commit 82362cd189b1f5dea8b4ec85ac82293576eb5ca4
-Author: Carsten Bock <carsten at ng-voice.com>
-Date:   Mon Dec 9 21:11:38 2013 +0100
-
-    Use Contact-Header for Service-Route/Asserted-Identity Lookup, fallback to IP/Port/Proto as fallback
-
-commit 6b0bcff43c0b3c22f399211aeb7e9279f7c35814
-Author: Carsten Bock <carsten at ng-voice.com>
-Date:   Mon Dec 9 20:07:12 2013 +0100
-
-    ims_registrar_pcscf: Bugfix: Properly handle the case, when we do not have a Asserted Identity
-
-commit 888635bfa3719afeeea6f5f0d407aa862ceb34ac
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Dec 9 10:06:15 2013 +0100
-
-    usrloc: avoid double locking when preloading attributes
-    
-    - reported by Seudin Kasumovic, FS#378
-
-commit 67d218e29457ffd75148c8c520b26ec6f3f41719
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Dec 9 10:05:11 2013 +0100
-
-    registrar: handle error case when deleting contact fails for unregister()
-    
-    - reformatted file
-
-commit 21027d0c17558f3a1a4797049448cbbdfe50554f
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sat Dec 7 13:35:45 2013 +0100
-
-    tm: safety checks inside t_next_contacts()
-
-commit 7d6dc390bac2b49615444bcbad74cd39f3c82302
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Dec 6 19:03:08 2013 +0100
-
-    tls: removed unsigned int comparison with <0
-
-commit b131f4402cf604bbe90123aa95a6cbc8412c2de0
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Dec 6 18:54:52 2013 +0100
-
-    sipcapture: fixed clang compile warnings
-    
-    - extra parameters for sprintf() match format specifiers
-
-commit ed034d4d9096d8c77269828c8efdafb26eac5372
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Dec 6 18:34:49 2013 +0100
-
-    ratelimit: signed check for pipe number in rpc_set_queue()
-    
-    - rpc can reand signed value
-
-commit d54eb083f59fb55ccbc79e49b5b3e05426bd3795
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Dec 6 18:30:49 2013 +0100
-
-    pike: memset of address print buffer with proper size
-
-commit 26e04f2053c9f33333bbbf79af6897428a1d9a88
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Dec 6 18:25:30 2013 +0100
-
-    permissions: signess warning fix
-
-commit cd04947b0ccb1c861274483f458bfc7f4329accb
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Dec 6 18:23:17 2013 +0100
-
-    maxforwards: use standard format instead of GNU old-style field designator
-
-commit efda774f6391f1e909a9967898c64fb25f53eeba
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Dec 6 18:20:16 2013 +0100
-
-    ctl: removed not needed extra paranthesis
-
-commit 89262590e4d47e480fb4984f18e12b4e4edb4ca6
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Dec 6 18:18:48 2013 +0100
-
-    acc: strftime() returns 0 on error
-
-commit 30359b3cfce2ce909153e06b1954778c4eababa7
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Dec 6 18:15:22 2013 +0100
-
-    pv: use int index for looking up flag index
-    
-    - some functions used for check may return negative on error
-
-commit 551524cfc83b922c23e2d26f8cc5950df2a0af54
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Dec 6 18:02:36 2013 +0100
-
-    usrloc: proper index for domain column when laoding extra attributes
-    
-    - patch by Seudin Kasumovic, FS#377
-
-commit f0fb6f1e9fbb2f7f0c2bed5ba0d50a56cf5cf444
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Dec 6 17:16:25 2013 +0100
-
-    core: fixed several clang compiler warnings
-
-commit 0713c0de50f8c2f4da2ee0ef33b0505c37792392
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Dec 6 16:33:04 2013 +0100
-
-    Makefile.defs: compiler optimization level made variable
-    
-    - allow using -O3 for clang, which gives error on the former default -O9
-
-commit a8d0d9e9224c2e7399c95c533dff67a6303891d2
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Dec 6 11:41:38 2013 +0100
-
-    snmpstats: use install-cfg target to deploy MIBs
-    
-    - existing target was no longer valid from v3.0
-
-commit 041b12dc6e5ad88e981d44180436a90518cbcf0d
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Dec 6 11:32:41 2013 +0100
-
-    sdpops: fix setting 0 instead of \r for sdp_get_line_startswith()
-    
-    - reported by Tuan Viet Nguyen
-
-commit 4dcbd1b1cbd4854607d286094c42d257623c548d
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Dec 5 09:58:38 2013 +0100
-
-    Makefile.groups: include gzcompress, sipt and mohqueue in packaging groups
-
-commit 32f9c9187a9d886c46b24ee38173274da63febda
-Author: Hugh Waite <hugh at polybius.local>
-Date:   Wed Dec 4 21:59:16 2013 +0000
-
-    dialog_ng: Fix segfault in dlg_new_dialog
-
-commit 146e2b093ba57a9c48f2059863d214fcdfc1bd1a
-Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
-Date:   Wed Dec 4 18:30:37 2013 +0000
-
-    rtpproxy: Add parameter to set an AVP to store the chosen RTPProxy instance IP address
-
-commit 2ffeea75931600e2da70d696a9965a5b7329211b
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Dec 4 15:02:22 2013 +0100
-
-    doc/rpc_list: regenerated the lists of rpc commands
-
-commit 56c772fbd1490a7cef3f748c61d1c7d7be3167a3
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Wed Dec 4 14:34:04 2013 +0100
-
-    doc/rpc_list: added sctp in the list of modules exporting rpc commands
-
-commit 87915a89bd186ecca8d4be505f15494831c4f108
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Wed Dec 4 11:00:44 2013 +0100
-
-    pkg/kamailio/deb: update changelog
-
-commit e043c3a44b163e511e62af5c7290fb587141b400
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Wed Dec 4 09:10:37 2013 +0100
-
-    pkg/kamailio/deb: add new modules
-
-commit 89c6d73dd51eb9b96f50d3f04219612fa7725224
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Dec 3 23:38:41 2013 +0100
-
-    core: don't increment failed dns query counter for reverse dns lookup at startup
-    
-    - it can happen before counters are intialized, thus check that before
-    - reported by Hugh Waite, FS#375
-
-commit 8161152b320f3b430523ea08e86a56f79405c2f4
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Dec 3 23:38:08 2013 +0100
-
-    core: added function to check if counters have been initialized
-
-commit 90379ff3987024c4fc83b1802c372f46690b1062
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Tue Dec 3 22:28:37 2013 +0100
-
-    Revert "pkg/kamailio/deb: removing old releases"
-    
-    This reverts commit badefd700ee8de321afd3de44e00a93649f177e1.
-
-commit badefd700ee8de321afd3de44e00a93649f177e1
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Tue Dec 3 16:48:18 2013 +0100
-
-    pkg/kamailio/deb: removing old releases
-
-commit daee150595e6fabdf53aa66425d32234ec7bbde7
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Tue Dec 3 16:46:32 2013 +0100
-
-    pkg/kamailio/deb: add jessie release
-
-commit 50b1c3a52c150201a563060cd1059a49ada89af2
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Tue Dec 3 16:11:00 2013 +0100
-
-    pkg/kamailio/deb: Add dnssec module ( jessie only )
-
-commit 419964e1e778c9a3d4c8e46d57e374b576949047
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Tue Dec 3 15:55:21 2013 +0100
-
-    pkg/kamailio/deb: update changelog using version 4.2.0~dev0
-
-commit 450d7ecb49a64e71dd28273b470911bd933bc209
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Tue Dec 3 15:51:41 2013 +0100
-
-    pkg/kamailio/deb: add new modules app_java, autheph, sctp
-
-commit f17c51fe48149a6b7634cee2e36ee463e1ee9fef
-Author: Victor Seva <linuxmaniac at torreviejawireless.org>
-Date:   Tue Dec 3 16:42:06 2013 +0100
-
-    pkg/kamailio/deb/debian: fix mono deps
-
-commit 120a9aa055c44eef26c1a635ceb75a150a284b56
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Tue Dec 3 18:09:30 2013 +0200
-
-    modules/ims_registrar_scscf: fixed comparison of P-asserted-id and Path header
-    	In can_subscribe_to_reg() we check if the P-Asserted-Identity in the Subscribe is in the Register path header (i.e. is this the P-CSCF subscribing to UE reg-event)
-    	This fix changes the comparison to compare P-asserted-id without "sip:" to cater for all compliant path header formats
-
-commit e6758e35c99aded27ca1e1842b70265b52f44823
-Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
-Date:   Tue Dec 3 13:06:37 2013 +0000
-
-    websocket: Set pointers to NULL when freeing ws connection structures
-     - Fixes double free crash FS#364
-     - Reported by Vitaliy Aleksandrov
-
-commit dbb4e81f27156c350c89674ad598e002fa6e4e54
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Dec 3 12:51:15 2013 +0100
-
-    stun: refreshed the readme
-
-commit 305e7b5693e71d2027f8e6462129f8c9f01ad76d
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Tue Dec 3 12:50:29 2013 +0100
-
-    stun: updated docs to reflect that it no longer depends on external libs
-
-commit 1721d5fa200702aa7bd3602b099d1da31ee6c6ea
-Author: Peter Dunkley <peter.dunkley at crocodilertc.net>
-Date:   Tue Dec 3 01:49:10 2013 +0000
-
-    pkg/kamailio/centos: updated .spec and README for Kamailio 4.2.0
-
-commit 0023247e4e82b60b92e945935323dda96b285f23
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Dec 2 23:24:41 2013 +0100
-
-    kamctl: updated version number
-
-commit 83555dc3a358e8bcff0ea00b19eadf9447b56421
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Dec 2 23:20:03 2013 +0100
-
-    kamailio.cfg: updated the comment about kamailio version
-
-commit 66ed11c90e38d948fd75f908b3edd409bca74134
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Dec 2 22:01:34 2013 +0100
-
-    kamailio.cfg: use set_contact_alias() instead of add_contact_alias()
-
-commit f61ff34aac7c7bae3a96fb698a899c8a0e692a9f
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Dec 2 20:42:12 2013 +0100
-
-    mem: malloc(0) should return a valid pointer for free according to specs
-
-commit 7771e9cdb58ea1cef008e2a70f53c5f183c26ebe
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Dec 2 18:17:34 2013 +0100
-
-    tls: clarified licensing based on development history
-    
-    - some were c&p as they refered to files related to components that were
-      developed later than the (c) year (e.g., selects)
-    - added openssl exception to gpl parts based on agreement from the
-      developers of those components - most of the code was released long time
-      ago under BSD by iptelorg. Code was rewrote for 3.1 when asynchronous
-      support was developed.
-
-commit cb23be9456c178957399ec9d8ce8a1420d50fc32
-Author: Federico Cabiddu <federico.cabiddu at gmail.com>
-Date:   Mon Dec 2 17:05:35 2013 +0100
-
-    permissions: re-init db connection for reload cmd
-    
-    - some workers for specific mi/rpc commands may not have a db connection from the start
-
-commit 219d3240b6d8ee8360da43aeeb4084cc866cec2e
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Mon Dec 2 16:21:01 2013 +0100
-
-    ndb_cassandra: replaced < and > with < and > in docbook xml file
-    
-    - it fixes readme generation errors
-
-commit df1c03a06fde83d7145266c099c26dd291a3ff59
-Merge: f4f1462 992ca11
-Author: Luis Martin Gil <martingil.luis at gmail.com>
-Date:   Sat Nov 30 21:09:46 2013 +0000
-
-    Merge branch 'luismartingil/ndb_cassandra'
-
-commit 992ca11279eafe7fee300d0d8a29229b88eaeba0
-Author: Luis Martin Gil <martingil.luis at gmail.com>
-Date:   Sat Nov 30 21:06:38 2013 +0000
-
-    ndb_cassandra: Changing root Makefile not to compile the module by default.
-    
-    - Reusing existing db_cassandra module in the Makefile.groups
-    structure in order to not compile the ndb_cassandra module by default.
-
-commit f4f1462816f20f74fd0cc1381d816257303b1943
-Merge: f557b9c fcb520e
-Author: Luis Martin Gil <martingil.luis at gmail.com>
-Date:   Sat Nov 30 10:49:27 2013 -0500
-
-    Merge branch 'luismartingil/ndb_cassandra'
-
-commit fcb520e9e6b6ea9748691d302088e41f98778f53
-Author: Luis Martin Gil <martingil.luis at gmail.com>
-Date:   Sat Nov 30 10:47:42 2013 -0500
-
-    ndb_cassandra: Fixed dates and username in comments.
-
-commit f557b9c150de28966fe98dbc396703bd73e464d2
-Author: Richard Good <richard.good at smilecoms.com>
-Date:   Fri Nov 29 11:59:46 2013 +0200
-
-    modules/ims_registrar_scscf: added missing domain unlock
-    	registrar_notify.c: missing domain unlock in can_subscribe_to_reg() when all checks fail
-
-commit 52a34d269931f6f3a50b3fc532405624b9e38d23
-Author: Vicente Hernando <vhernando at systemonenoc.com>
-Date:   Thu Nov 28 12:16:05 2013 +0100
-
-    modules/ndb_redis: solved bug in second call to redisvCommand.
-
-commit 0e711165f9e26b04110cadda9b372eae0387df41
-Author: Camille Oudot <camille.oudot at orange.com>
-Date:   Tue Nov 26 16:08:35 2013 +0100
-
-    modules/ims_registrar_pcscf: fix log
-
-commit dd3ce694280e9748740680a19837b530f48b5bc5
-Author: Richard Fuchs <rfuchs at sipwise.com>
-Date:   Tue Nov 26 10:36:18 2013 -0500
-
-    rtpproxy-ng: remove trailing double \r\n from multipart SDP
-
-commit 5caf33ceaea8449adfe134fa784c10b2d0f5d068
-Author: Luis Martin Gil <martingil.luis at gmail.com>
-Date:   Mon Nov 25 18:20:02 2013 -0500
-
-    ndb_cassandra: Initial commit of the module
-    
-    - Simply adding all the files of the new module.
-
-commit 504973f1dabdc60212cba2bacaede9fe8a36e952
-Author: Camille Oudot <camille.oudot at orange.com>
-Date:   Wed Nov 6 16:28:44 2013 +0100
-
-    lib/kcore: make escape_param() conform to RFC3261
-
-commit 60372d613544af1f8f06122eb77fa2a9636a6c3a
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sun Nov 24 16:06:41 2013 +0100
-
-    tmx: backup and restore existing T and branch pointers for t_cancel_callid()
-    
-    - reported and initial patch by Guillaume Bour
-
-commit 777dd5e28ff6b4fcc3b1c44e841eb415c974075f
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Sun Nov 24 16:05:49 2013 +0100
-
-    tm: exported set_t() and get_t_branch() viam tm api
-    
-    - allows to backup and restore pointers to T and branch
-
-commit 54020b00893ee259baee714d7d17adc6d31f9112
-Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
-Date:   Fri Nov 22 09:39:40 2013 +0000
-
-    modules/avpops: Fix 'uninitialised variable' warning
-
-commit a55018deb431ef32ee2bcd45610903327850757d
-Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
-Date:   Fri Nov 22 09:35:55 2013 +0000
-
-    modules/usrloc: Update contact field when updating a contact in the DB
-    - Fixes FS#368
-
-commit 27eba09b603b265ce4213d238c132249189ae6e8
-Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
-Date:   Fri Nov 22 09:28:38 2013 +0000
-
-    modules/registrar: Invalidate temporary GRUUs when the Call-ID changes for a sip.instance
-    - Fixes FS#368
-
-commit 321fb280f81d2e00531feff1562f064a7222ffe9
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Nov 21 19:14:36 2013 +0100
-
-    sl: README updated
-
-commit e7b73f7e0160eac1ca445201fbf796df0dd13ce0
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Nov 21 19:14:17 2013 +0100
-
-    sl: docs updated to reflect usage of send_reply()
-
-commit c77aaf38eafe1d3549d266feebf76ac0b50738ea
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Nov 21 19:09:43 2013 +0100
-
-    sl: allow send_reply() in the route block types supported by t_reply() and sl_send_reply()
-    
-    - reported by Juha Heinanen, FS#362
-
-commit 715ba52de2031786fd9f05832d5bf73d17d46e47
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Nov 21 17:37:33 2013 +0100
-
-    tm: propagate reply/failure route indexes to local uac branch
-    
-    - affects the updates done in event_route[tm:local-request]
-    - reported by Pawel Sternal, FS#371
-
-commit 56e4f4518028e73f9ebd053242a100a5c3b7eb53
-Author: Timo Teräs <timo.teras at iki.fi>
-Date:   Fri Nov 15 16:06:25 2013 +0200
-
-    modules/sca: fix hash entry deletion
-    
-    sca_hash_table_slot_kv_delete_unsafe() uses internally sca_hash_entry
-    but incorrectly called sca_hash_table_slot_kv_find_unsafe() to
-    initialize the entry. That function returns the node value, not the
-    node itself. Use instead sca_hash_table_slot_kv_find_entry_unsafe().
-    
-    Should fix the crash in FS#366.
-
-commit 10115f88637d1371a8ddeb5fe9c36c31ada49fc4
-Author: Ovidiu Sas <osas at voipembedded.com>
-Date:   Fri Nov 15 09:08:03 2013 -0500
-
-    usrloc: fix crash while printing error log
-     - fix a copy/paste error that lead to a NULL pointer
-
-commit b1f4dbeef93511563164de2f030f510f5a2cf2d9
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Nov 15 10:08:12 2013 +0100
-
-    app_perl: docs updated with reset_cycles parameter and rpc commands
-
-commit de2c39a1857d74443c6b1fa4f06cbb18d3dd8026
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Nov 15 09:52:29 2013 +0100
-
-    app_perl: added rpc commands to set/get the value for reset_cycles
-
-commit b5527627601c9e41ebbfaccb98bc2cf0bc003bdb
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Fri Nov 15 09:28:25 2013 +0100
-
-    app_perl: added mechanism to avoid leaks specific to persistent perl interpreter
-    
-    - it is not easy to track the scope of variables, especially in libs,
-      the solution being to re-init the interpreter
-    - new module parameter reset_cycles to specify the number of execution
-      cycles after which the interpreter is reset. Default is 0 - don't
-      reset at all
-
-commit 34ad8c295b45bc52cc5a071bf2b5651865389f94
-Author: Daniel-Constantin Mierla <miconda at gmail.com>
-Date:   Thu Nov 14 23:00:32 2013 +0100
-
-    app_perl: declare extern environ variable
-    
-    - without it doesn't compile on darwin and it is recommended way to do
-    - provide some fake argc and argv to PERL_SYS_INIT3() to avoid compile
-      warnings
-
+    - master branch is open for adding new features to be part of v4.1.x
 
-===================== 2013-12-04 Version 4.1.0 Released =====================
+===================== 2013-03-11 Version 4.0.0 Released =====================
diff --git a/ISSUES b/ISSUES
index 941aea9..f82cfad 100644
--- a/ISSUES
+++ b/ISSUES
@@ -1,6 +1,4 @@
 #
-# $Id$
-#
 
 This is a collection of issues which have shown up
 since the version 0.8.8 was released. The issues are
diff --git a/Makefile b/Makefile
index 8786cc8..efd58cc 100644
--- a/Makefile
+++ b/Makefile
@@ -1,69 +1,8 @@
-# $Id$
-#
-# sip_router makefile
+# Kamailio makefile
 #
 # WARNING: requires gmake (GNU Make)
 #  Arch supported: Linux, FreeBSD, SunOS (tested on Solaris 8), OpenBSD (3.2),
-#  NetBSD (1.6).
-#
-#  History:
-#  --------
-#              created by andrei
-#  2003-02-24  make install no longer overwrites ser.cfg  - patch provided
-#               by Maxim Sobolev   <sobomax at FreeBSD.org> and 
-#                  Tomas Björklund <tomas at webservices.se>
-#  2003-03-11  PREFIX & LOCALBASE must also be exported (andrei)
-#  2003-04-07  hacked to work with solaris install (andrei)
-#  2003-04-17  exclude modules overwritable from env. or cmd. line,
-#               added include_modules and skip_modules (andrei)
-#  2003-05-30  added extra_defs & EXTRA_DEFS
-#               Makefile.defs force-included to allow recursive make
-#               calls -- see comment (andrei)
-#  2003-06-02  make tar changes -- unpacks in $NAME-$RELEASE  (andrei)
-#  2003-06-03  make install-cfg will properly replace the module path
-#               in the cfg (re: /usr/.*lib/ser/modules)
-#              ser.cfg.default is installed only if there is a previous
-#               cfg. -- fixes packages containing ser.cfg.default (andrei)
-#  2003-08-29  install-modules-doc split from install-doc, added 
-#               install-modules-all, removed README.cfg (andrei)
-#              added skip_cfg_install (andrei)
-#  2004-09-02  install-man will automatically "fix" the path of the files
-#               referred in the man pages
-#  2006-02-14  added utils & install-utils (andrei)
-#  2006-03-15  added nodeb parameter for make tar (andrei)
-#  2006-09-29  added modules-doc as target and doc_format= as make option (greger)
-#  2006-12-09  added new group_include as make option and defined groups 
-#               defining which modules to include. Also added new target 
-#               print-modules that you can use to check which modules will be 
-#               compiled (greger)
-#  2007-01-10  added new group_include targets mysql, radius, and presence 
-#               improved print-modules output fixed problem in include/exclude
-#               logic when using group_include (greger)
-#  2007-03-01  fail if a module or a required utility make fail unless 
-#              err_fail=0; don't try to make modules with no Makefiles (andrei)
-#  2007-03-16  moved the exports to Makefile.defs (andrei)
-#  2007-03-29  install-modules changed to use make -C modpath install (andrei)
-#  2007-05-04  "if ! foo" not supported in standard sh, switched to 
-#                "if foo; then :; else ... ; fi" (andrei)
-#  2008-06-23  added 2 new targets: README and man (re-generate the README
-#              or manpages for all the modules) (andrei)
-#  2008-06-25  make cfg support (use a pre-built cfg.: config.mak) (andrei)
-#  2008-06-28  added clean-all, proper-all, install-modules-man and error 
-#               checks for install-utils & doc (andrei)
-#  2008-07-01  split module list from config.mak into modules.lst so that
-#               the modules list can be changed without rebuilding the whole
-#               ser (andrei)
-#              added cfg-defs, new target that only rebuilds config.mak
-#  2009-03-10  replaced DEFS with C_DEFS (DEFS are now used only for
-#              "temporary" defines inside modules or libs) (andrei)
-#  2009-03-27  multiple modules directory support, see modules_dirs (andrei)
-#  2009-04-02  workaround for export not supported in gnu make 3.80
-#               target specific variables: use mk_params for each
-#               $(MAKE) invocation (andrei)
-#  2009-04-22  don't rebuild config.mak or modules.lst if not needed
-#              (e.g. on clean) (andrei)
-#  2009-06-24  auto-generate autover.h, containing the REPO_VER macro, defined
-#               to the top git commit sha (if git is found) (andrei)
+#  NetBSD (1.6), OS/X
 #
 
 # check make version
@@ -263,10 +202,10 @@ cmodules=$(foreach mods,$(modules_dirs), $($(mods)))
 
 
 # list of utils directories that should be compiled by make utils
-C_COMPILE_UTILS=	utils/sercmd
+C_COMPILE_UTILS=	utils/kamcmd
 # list of binaries that should be installed alongside
 # (they should be created after make utils, see C_COMPILE_UTILS)
-C_INSTALL_BIN=	# sercmd is now installed by ctl
+C_INSTALL_BIN=	# kamcmd is now installed by ctl
 
 # which utils know to install themselves and should be installed
 # along the core (list of utils directories)
@@ -732,6 +671,9 @@ mk-install_dirs: $(cfg_prefix)/$(cfg_dir) $(bin_prefix)/$(bin_dir) \
 $(cfg_prefix)/$(cfg_dir): 
 		mkdir -p $(cfg_prefix)/$(cfg_dir)
 
+$(run_prefix)/$(run_dir): 
+		mkdir -p $(run_prefix)/$(run_dir)
+
 $(bin_prefix)/$(bin_dir):
 		mkdir -p $(bin_prefix)/$(bin_dir)
 
@@ -978,10 +920,10 @@ clean: clean-libs
 clean-extra-names:
 	@rm -f $(filter-out $(MAIN_NAME), sip-router ser kamailio)
 
-# proper/distclean a.s.o modules, utils and libs too
+# proper/distclean-old a.s.o modules, utils and libs too
 
 proper: clean-extra-names proper-modules proper-utils proper-libs
-distclean: distclean-modules distclean-utils distclean-libs
+distclean-old: distclean-modules distclean-utils distclean-libs
 realclean: realclean-modules realclean-utils realclean-libs
 maintainer-clean: maintainer-clean-modules maintainer-clean-utils \
  maintainer-clean-libs
@@ -994,7 +936,7 @@ clean-all: clean
 maintainer-clean: modules=$(modules_all)
 
 # on make proper clean also the build config (w/o module list)
-proper realclean distclean maintainer-clean: clean_cfg
+proper realclean distclean-old maintainer-clean: clean_cfg
 
 # on maintainer clean, remove also the configured module list
 maintainer-clean: clean_modules_cfg clean_makefile_vars
@@ -1017,7 +959,7 @@ clean_modules_cfg clean-modules-cfg:
 
 # clean everything generated - shortcut on maintainer-clean
 .PHONY: pure
-pure: maintainer-clean
+pure distclean: maintainer-clean
 
 .PHONY: install_initd_debian install-initd-debian
 install_initd_debian install-initd-debian:
@@ -1085,6 +1027,7 @@ uninstall:
 	@echo " *LIBDIR Path is: ${lib_prefix}/${lib_dir}"
 	@echo " *MANDIR Path is: ${man_prefix}/${man_dir}"
 	@echo " *SHRDIR Path is: ${share_prefix}/${share_dir}"
+	@echo " *RUNDIR Path is: $(run_prefix)/$(run_dir)"
 	@if [ "${PREFIX}" != "/usr/local" ] ; then \
 		echo "-Custom PREFIX Path" ; \
 		if [ "${PREFIX}" = "/" -o "${PREFIX}" = "/usr" ] ; then \
@@ -1115,6 +1058,7 @@ uninstall:
 		echo "rm -rf ${doc_prefix}/${doc_dir}" ; \
 		echo "rm -rf ${lib_prefix}/${lib_dir}" ; \
 		echo "rm -rf ${share_prefix}/${share_dir}" ; \
+		echo "rm -rf $(run_prefix)/$(run_dir)" ; \
 		echo ; \
 		echo "-WARNING: before running the commands, be sure they don't delete any system directory or file" ; \
 	fi ;
diff --git a/Makefile.cfg b/Makefile.cfg
index 0ef3ead..8797a4a 100644
--- a/Makefile.cfg
+++ b/Makefile.cfg
@@ -1,13 +1,9 @@
-#
-# $Id$
+# Kamailio build system
 #
 # remake cfg defs (include)
 #
 # depends on COREPATH being defined 
 #
-# History:
-# --------
-#  2008-06-27  initial version (andrei)
 #
 
 
diff --git a/Makefile.defs b/Makefile.defs
index 93050c3..95657ba 100644
--- a/Makefile.defs
+++ b/Makefile.defs
@@ -1,3 +1,4 @@
+# Kamailio build system
 
 #
 # makefile defs (CC, LD,a.s.o)
@@ -9,75 +10,6 @@
 #   exclude_modules, skip_modules, include_modules
 #   extra_defs
 #
-# History:
-# --------
-#              created by andrei
-#  2003-02-24  added LOCALBASE, fixed doc_dir for freebsd - patch provided
-#               by Maxim Sobolev <sobomax at FreeBSD.org>
-#  2003-02-25  added -DDISABLE_NAGLE (andrei)
-#  2003-03-02  added -DDIGEST_DOMAIN (janakj)
-#  2003-03-10  added -xcode=pic32 for module compilation w/ sun cc
-#               (too many symbols for pic13)  (andrei)
-#  2003-04-16  added CC_EXTRA_OPTS, s/march/mcpu, added CPU (cpu to optimize 
-#               for, used only with gcc-3.x) (andrei)
-#  2003-05-23  check if this makefile was already included (andrei)
-#              removed -DDIGEST_DOMAIN (andrei)
-#  2003-05-30  added extra_defs (andrei)
-#  2003-06-06  moved compiler detection before DEFS (andrei)
-#  2003-06-10  removed -m32 for gcc 3.x/sparc64  -- it will use 
-#              arch. default: -m32 on solaris, -m64 on *bsd (andrei)
-#  2003-09-25  added -pthread into LIBS when compiling on FreeBSD/alpha
-#              and other FreeBSD arches for which no fast locking assembly
-#              code exists (sobomax)
-#  2003-11-08  mips1 support introduced (andrei)
-#  2003-11-24  openbsd 3.4 (elf) fixes (andrei)
-#  2004-07-27  darwin (mac os x) port  (andrei)
-#  2004-09-12  mips2 & cobalt support introduced (andrei)
-#  2004-09-28  x86_64 support introduced (andrei)
-#  2004-12-14  gcc-3.4 special case added (andrei)
-#  2004-12-15  HAVE_ALLOCA_H added (andrei)
-#  2004-12-19  amd64 transformed in x86_64 (andrei)
-#  2005-04-27  alpha support added (andrei)
-#  2005-06-01  use $(LOCALBASE) instead of /usr/{local,pkg} (andrei)
-#  2005-06-26  numeric OSREL & HAVE_KQUEUE added to the *BSD (andrei)
-#  2005-07-04  HAVE_DEVPOLL added to solaris (andrei)
-#  2005-07-06  gcc 4.0 optimizations support (andrei)
-#  2005-07-25  better solaris arch detection (andrei)
-#  2005-09-12  -mallign-double removed (too many problems) (andrei)
-#  2005-10-02  distcc get gcc version hack (andrei)
-#  2006-03-30  64 bit mode compile by default on sparc64 (-m64), added
-#              CC_GCC_LIKE_ASM and SPARC64_MODE (andrei)
-#              sparc <= v8 support (andrei)
-#  2006-03-31  armv6 & mips64 support added
-#              mips and arm set to NOSMP by default (andrei)
-#  2006-07-10  added -DPROFILING (hscholz)
-#  2007-02-09  added TLS_HOOKS and CORE_TLS support, obsoleted TLS=1
-#              added TLS_EXTRA_LIBS (andrei)
-#  2007-03-16  added LIB building options: LIB_LDFLAGS, LIB_SONAME, LIB_RPATH,
-#                INSTALL_LIB, libraries install paths (andrei)
-#  2007-05-14  futex support if linux 2.5.70+ and 
-#               use_futex=yes (default) (andrei)
-#  2007-05-26  changed darwin module link flags (instead of -bundle_loader ser
-#               -flat_namespace -undefined suppress) (andrei)
-#  2007-07-07  use isainfo -n to detect cpu type on solaris (andrei)
-#  2007-07-07  added HAVE_SCHED_SETSCHEDULER for linux (andrei)
-#  2007-07-18  added DNS_WATCHDOG_SUPPORT (Miklos)
-#  2007-07-30  added USE_DNS_CACHE_STATS and USE_DST_BLACKLIST_STATS (Gergo)
-#  2008-06-26  support for make cfg / config.mak and hack to load 
-#               automatically config.mak when included from a module, lib 
-#               a.s.o (not from the main Makefile)  (andrei)
-#  2009-03-10  replaced DEFS with C_DEFS and INCLUDES with C_INCLUDES (DEFS
-#              and INCLUDES are now used only for "temporary" defines/includes
-#              inside modules or libs) (andrei)
-#  2009-09-29  for gcc 4.2+ use -fno-strict-overflow (andrei)
-#  2009-09-30  find the target architecture from the compiler and not
-#              from the host (andrei)
-#  2009-10-01  use -fsigned-char for gcc on ppc, ppc64, arm and arm6
-#              (on those archs char is unsigned by default) (andrei)
-#  2010-03-10  added CC_MKDEP_OPTS, which contains to the list of options
-#               needed to generate dependencies on-the-fly while compiling
-#               or is empty if the compiler doesn't support it (andrei)
-
 
 # default silent, unless Q= 0|no|off|verbose|noisy
 quiet?=$(if $(filter 0 no off verbose noisy,$(Q)),verbose,silent)
@@ -163,12 +95,14 @@ INSTALL_FLAVOUR=$(FLAVOUR)
 
 # version number
 VERSION = 4
-PATCHLEVEL = 2
-SUBLEVEL = 5
+PATCHLEVEL = 3
+SUBLEVEL =  0
+EXTRAVERSION = -rc0
 
 # memory manager switcher
 # 0 - f_malloc (fast malloc)
 # 1 - q_malloc (quick malloc)
+# 2 - tlsf_malloc (O(1) malloc and free)
 MEMMNG ?= 0
 # memory debugger switcher
 # 0 - off (no-debug mode)
@@ -444,7 +378,7 @@ share_dir = share/$(MAIN_NAME)/
 # lib/$(MAIN_NAME)/modules , lib/$(MAIN_NAME)/modules-s, lib/$(MAIN_NAME)/modules-k
 modules_dir = $(LIBDIR)/$(MAIN_NAME)/
 lib_dir = $(LIBDIR)/$(MAIN_NAME)/
-
+run_dir = var/run/$(MAIN_NAME)/
 doc_dir = doc/$(MAIN_NAME)/
 man_dir = man/
 data_dir = $(MAIN_NAME)/
@@ -496,6 +430,10 @@ LOCALBASE ?= /usr/local
 # Doxygen directory
 doxygen_dir=doc/doxygen
 
+BASEDIR ?= $(DESTDIR)
+basedir = $(BASEDIR)
+runbasedir = $(BASEDIR)
+
 # install location
 PREFIX ?= $(LOCALBASE)
 prefix = $(PREFIX)
@@ -505,13 +443,12 @@ prefix = $(PREFIX)
 #  basedir=/tmp
 #  prefix=/usr/local
 
-BASEDIR ?= $(DESTDIR)
-basedir = $(BASEDIR)
 # install prefixes for various stuff
 cfg_prefix = $(basedir)$(prefix)
 bin_prefix = $(basedir)$(prefix)
 modules_prefix = $(basedir)$(prefix)
 lib_prefix = $(basedir)$(prefix)
+run_prefix = $(runbasedir)
 doc_prefix = $(basedir)$(prefix)
 man_prefix = $(basedir)$(prefix)
 ut_prefix = $(basedir)$(prefix)
@@ -524,6 +461,7 @@ cfg_target = $(prefix)/$(cfg_dir)
 bin_target = $(prefix)/$(bin_dir)
 #modules_target = $(prefix)/$(modules_dir)
 lib_target = $(prefix)/$(lib_dir)
+run_target = $(run_prefix)/$(run_dir)
 doc_target = $(prefix)/$(doc_dir)
 data_target = $(prefix)/$(data_dir)
 
@@ -564,6 +502,8 @@ data_target = $(prefix)/$(data_dir)
 #		(not true anymore, q_malloc performs approx. the same)
 # -DF_MALLOC
 #		an even faster malloc, not recommended for debugging
+# -DTLSF_MALLOC=1
+#       an implemetation of the "two levels segregation fit" malloc algorithm
 # -DDL_MALLOC
 #		a malloc implementation based on Doug Lea's dl_malloc
 # -DSF_MALLOC 
@@ -680,6 +620,7 @@ C_DEFS= $(extra_defs) \
 	 -D__CPU_$(ARCH) $(os_defs) \
 	 -DSER_VER=$(SER_VER) \
 	 -DCFG_DIR='"$(cfg_target)"'\
+	 -DRUN_DIR='"$(run_target)"'\
 	 -DPKG_MALLOC \
 	 -DSHM_MEM  -DSHM_MMAP \
 	 -DDNS_IP_HACK \
@@ -724,6 +665,12 @@ ifeq 	($(MEMDBG), 1)
 		C_DEFS+= -DDBG_QM_MALLOC
 endif
 	C_DEFS+= -DMEM_JOIN_FREE
+else ifeq ($(MEMMNG), 2)
+#	use tlsf malloc
+	C_DEFS+= -DTLSF_MALLOC=1
+ifeq 	($(MEMDBG), 1)
+		C_DEFS+= -DDBG_TLSF_MALLOC
+endif
 else
 #	use f_malloc
 	C_DEFS+= -DF_MALLOC
@@ -2073,12 +2020,12 @@ saved_fixed_vars:=	MAIN_NAME  CFG_NAME SCR_NAME FLAVOUR INSTALL_FLAVOUR \
 # extra: prefix DESTDIR BASEDIR basedirt
 saved_chg_vars:=\
 		CC_EXTRA_OPTS CPU CFLAGS_RM CFLAGS MOD_CFLAGS LIB_CFLAGS UTILS_CFLAGS \
-		BASEDIR basedir DESTDIR LIBDIR \
-		PREFIX prefix\
+		BASEDIR basedir DESTDIR LIBDIR RUNBASEDIR runbasedir \
+		PREFIX prefix \
 		cfg_prefix cfg_dir bin_prefix bin_dir modules_prefix modules_dir \
 		doc_prefix doc_dir man_prefix man_dir ut_prefix ut_dir \
 		share_prefix share_dir lib_prefix lib_dir data_prefix data_dir \
-		cfg_target lib_target data_target
+		cfg_target lib_target data_target run_prefix run_dir run_target
 
 
 #export relevant variables to the sub-makes
diff --git a/Makefile.dirs b/Makefile.dirs
index 3f10cf3..f36b2c0 100644
--- a/Makefile.dirs
+++ b/Makefile.dirs
@@ -1,11 +1,6 @@
-# $Id$
-#
+# Kamailio build system
 # path config makefile
 #
-# History:
-# --------
-#  2009-03-27  initial version (andrei)
-
 ifneq ($(makefile_dirs_included),1)
 
 override makefile_dirs_included:=1
diff --git a/Makefile.groups b/Makefile.groups
index f2e6033..c1fd1eb 100644
--- a/Makefile.groups
+++ b/Makefile.groups
@@ -1,3 +1,4 @@
+# Kamailio build system
 # Module groups definitions
 #
 
@@ -13,12 +14,13 @@ mod_list_basic=async auth benchmark blst cfg_rpc cfgutils corex counters \
 				   mediaproxy mi_datagram mi_fifo mi_rpc mqueue \
 				   nat_traversal nathelper path pike pv ratelimit rr rtimer \
 				   rtpproxy sanity sdpops siputils sl statistics textops \
-				   textopsx tm tmx topoh xlog rtpengine stun sipt
+				   textopsx tm tmx topoh xlog rtpengine stun sipt tcpops \
+				   auth_xkeys
 
 # - extra used modules, with no extra dependency
-mod_list_extra=avp auth_diameter call_control cnxcc dmq domainpolicy msrp pdb \
+mod_list_extra=avp auth_diameter call_control dmq domainpolicy msrp pdb \
 			     qos sca seas sms sst timer tmrec uac_redirect xhttp \
-				 xhttp_rpc xprint jsonrpc-s nosip
+				 xhttp_rpc xprint jsonrpc-s nosip usrloc_dmq
 
 # - common modules depending on database
 mod_list_db=acc alias_db auth_db avpops cfg_db db_text db_flatstore \
@@ -125,15 +127,21 @@ mod_list_python=app_python
 # - modules depending on geoip library
 mod_list_geoip=geoip
 
+# - modules depending on new geoip library
+mod_list_geoip2=geoip2
+
 # - modules depending on sqlite library
 mod_list_sqlite=db_sqlite
 
 # - modules depending on oracle library
 mod_list_oracle=db_oracle
 
-# - modules depending on json library
+# - modules depending on json (+libevent) library
 mod_list_json=json jsonrpc-c
 
+# - modules depending on jansson (+libevent) library
+mod_list_jansson=jansson janssonrpc-c
+
 # - modules depending on redis library
 mod_list_redis=ndb_redis
 
@@ -169,6 +177,12 @@ mod_list_kazoo=kazoo
 # - modules depending on mongodb
 mod_list_mongodb=db_mongodb ndb_mongodb
 
+# - modules depending on redis and event library
+mod_list_cnxcc=cnxcc
+
+# - modules depending on erlang library
+mod_list_erlang=erlang
+
 # - all modules
 mod_list_all=$(sort $(mod_list_basic) $(mod_list_extra) \
 			   $(mod_list_db) $(mod_list_dbuid) \
@@ -193,7 +207,9 @@ mod_list_all=$(sort $(mod_list_basic) $(mod_list_extra) \
 			   $(mod_list_sctp) $(mod_list_autheph) \
 			   $(mod_list_gzcompress) $(mod_list_uuid) \
 			   $(mod_list_ev) $(mod_list_kazoo) \
-			   $(mod_list_mongodb))
+			   $(mod_list_mongodb) $(mod_list_cnxcc) \
+			   $(mod_list_jansson) $(mod_list_geoip2) \
+			   $(mod_list_erlang))
 
 
 
@@ -321,12 +337,18 @@ module_group_kpython=$(mod_list_python)
 # pkg geoip module
 module_group_kgeoip=$(mod_list_geoip)
 
+# pkg geoip2 module
+module_group_kgeoip2=$(mod_list_geoip2)
+
 # pkg sqlite module
 module_group_ksqlite=$(mod_list_sqlite)
 
 # K json modules
 module_group_kjson=$(mod_list_json)
 
+# K jansson modules
+module_group_kjansson=$(mod_list_jansson)
+
 # pkg redis module
 module_group_kredis=$(mod_list_redis)
 
@@ -366,6 +388,12 @@ module_group_kkazoo=$(mod_list_kazoo)
 # pkg mongodb modules
 module_group_kmongodb=$(mod_list_mongodb)
 
+# pkg cnxcc module
+module_group_kcnxcc=$(mod_list_cnxcc)
+
+# pkg erlang module
+module_group_kerlang=$(mod_list_erlang)
+
 # list of static modules
 #
 static_modules:=
diff --git a/Makefile.libs b/Makefile.libs
index 6182580..3acc671 100644
--- a/Makefile.libs
+++ b/Makefile.libs
@@ -1,15 +1,8 @@
-#
-# $Id$
+# Kamailio build system
 #
 # module Makefile
 #(to be included from each library makefile)
 #
-# History:
-# --------
-#  2007-03-16  created by andrei
-#  2007-05-19  rebuild on changed install name on darwin  (andrei)
-#  2008-06-27  make cfg / config.mak support (andrei)
-
 # NAME, MAJOR_VER and MINOR_VER should be pre-defined in the library 
 # makefile
 #
diff --git a/Makefile.modules b/Makefile.modules
index 76494c5..f74c92c 100644
--- a/Makefile.modules
+++ b/Makefile.modules
@@ -1,23 +1,8 @@
-#
-# $Id$
+# Kamailio build system
 #
 # module Makefile
 #(to be included from each module)
 #
-# History:
-# --------
-#  2007-03-29  if a module depends on SER_LIBS, it will be rebuilt on install
-#               with the proper rpath; libraries will be automatically
-#               installed if needed (andrei)
-#  2008-06-23  added the README & man targets (andrei)
-#  2008-06-27  make cfg / config.mak support (andrei)
-#  2009-03-10  replaced DEFS with C_DEFS and INCLUDES with C_INCLUDES (DEFS
-#              and INCLUDES are now used only for "temporary" defines/includes
-#              inside modules or libs) (andrei)
-#  2009-10-01  added support for automatically installing extra utils,
-#               scripts and cfg files (andrei)
-#  2010-03-04  don't overwrite already installed .cfgs, save the .cfg as
-#              .sample in this case (andrei)
 #
 
 #
diff --git a/Makefile.radius b/Makefile.radius
index 0abc2a7..ddbc4af 100644
--- a/Makefile.radius
+++ b/Makefile.radius
@@ -1,6 +1,4 @@
-#
-# $Id$
-#
+# Kamailio build system
 #
 # Radiusclient library detection comes here
 #
diff --git a/Makefile.rules b/Makefile.rules
index 0243284..1d0407d 100644
--- a/Makefile.rules
+++ b/Makefile.rules
@@ -1,6 +1,4 @@
-#
-# $Id$
-#
+# Kamailio build system
 #
 # common Makefile rules, included by main Makefile & the  modules
 #
@@ -15,21 +13,6 @@
 #  built if necessary. Format: path/shortname, where shortname is the 
 #  name passed to -l (e.g. for libprint.so the shortname is print)
 #
-# History:
-# --------
-#  2007-03-29  set rpath differently for make install
-#              automatically build listed SER_LIBS if needed (andrei)
-#  2008-06-23  automatically rebuild if make time defines or includes
-#              changed (via makecfg.lst)
-#  2009-03-10  support for C_DEFS and C_INCLUDES (DEFS and INCLUDES are now
-#              used only for "temporary" defines/includes inside modules or
-#              libs, C_DEFS and C_INCLUDES are used for the common stuff)
-#              (andrei)
-#  2010-03-09  generate dependencies when compiling .o instead of on
-#               include .d and fix build errors when a .h is moved
-#              support for using MKDEP="makedepend-f-"      (andrei)
-#  2010-03-10  support for on the-fly dependency generation (while compiling,
-#               see CC_MKDEP_OPTS)  (andrei)
 
 
 # check if the saved cfg corresponds with the current one
diff --git a/Makefile.shared b/Makefile.shared
index fec2e79..82a29d2 100644
--- a/Makefile.shared
+++ b/Makefile.shared
@@ -1,12 +1,8 @@
-#
-# $Id$
+# Kamailio build system
 #
 # shared functions 
 #
 #
-# History:
-# --------
-#  2008-06-27  initial version (andrei)
 #
 
 escape_values=$(subst $$,\$$,$(subst ",\", $(1)))
diff --git a/Makefile.sources b/Makefile.sources
index 056e9b7..7bc49e7 100644
--- a/Makefile.sources
+++ b/Makefile.sources
@@ -1,5 +1,4 @@
-#
-# $Id$
+# Kamailio build system
 #
 # common Makefile variables 
 # (source files, objs, etc)
diff --git a/Makefile.targets b/Makefile.targets
index eeb0f5a..9f9bf66 100644
--- a/Makefile.targets
+++ b/Makefile.targets
@@ -1,23 +1,16 @@
+# Kamailio build system
 
-#
-# $Id$
-#
-#
 # Makefile targets that should be treated specially, 
 # e.g.:  non obj/executable affecting targets => don't build dependencies for
 #  them or don't try any action that would be useful only for generating
 #  actual code
 #
-# History:
-# --------
-#  2008-06-26  initial version (andrei) 
-#
 
 ifeq (,$(strip $(modules_dirs)))
 include $(COREPATH)/Makefile.dirs
 endif
 
-clean_targets:=	clean proper distclean realclean maintainer-clean local-clean \
+clean_targets:=	clean proper distclean-old realclean maintainer-clean local-clean \
 				clean-all proper-all distclean-all realclean-all \
 				clean_cfg clean-cfg clean_modules_cfg clean-modules-cfg \
 				clean-modules proper-modules realclean-modules \
@@ -26,7 +19,8 @@ clean_targets:=	clean proper distclean realclean maintainer-clean local-clean \
 				maintaner-clean-utils \
 				clean-libs proper-libs realclean-libs distclean-libs \
 				maintainer-clean-libs \
-				clean-tmp clean_doxygen clean-extra-names
+				clean-tmp clean_doxygen clean-extra-names \
+				pure distclean
 doc_targets:=	README man install-doc install-man install-ser-man \
 		install-every-module-doc install-every-module-man \
 		$(foreach m,$(modules_dirs),$(m)-doc $(m)-readme $(m)-man) \
diff --git a/Makefile.utils b/Makefile.utils
index 261c456..c0f7232 100644
--- a/Makefile.utils
+++ b/Makefile.utils
@@ -1,12 +1,8 @@
-#
-# $Id$
+# Kamailio build system
 #
 # utils Makefile
 #(to be included from each util/ subdirectory)
 #
-# History:
-# --------
-#  2009-04-23  initial version derived from Makefile.modules (andrei)
 
 #
 # Variables that should be defined in the util Makefiles, prior to including
diff --git a/Makefile.vars b/Makefile.vars
deleted file mode 100644
index a8bb6ba..0000000
--- a/Makefile.vars
+++ /dev/null
@@ -1 +0,0 @@
-FLAVOUR?=kamailio
diff --git a/NEWS b/NEWS
index 8b6d326..f9792f2 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,3 @@
-$Id$
-
 Release notes for Kamailio/SIP Router (sr)
 ***********************************************
 
diff --git a/README b/README
index c255a0e..0683a91 100644
--- a/README
+++ b/README
@@ -1,6 +1,6 @@
 
 
-Kamailio v4.2
+Kamailio v4.3
 =============
 
 http://www.kamailio.org
@@ -35,7 +35,8 @@ of other leading SIP vendors.
 The Kamailio software enables a flexible plug-in model for new applications: Third parties 
 can easily link their plug-ins with the server code and provide thereby advanced and
 customized services. With a modern RPC interface, 3rd party application can integrate
-and interact with services provided by Kamailio.
+and interact with services provided by Kamailio. By using the EVAPI interface or the
+embedded HTTP server restful applications can be built.
 
 Kamailio's performance and robustness allows it to serve millions of users and accommodate needs
 of very large operators. With a low-cost dual-CPU, the Kamailio server is able to power 
@@ -81,7 +82,7 @@ Kamailio is the result of a merge of the code base and years of experience from
 both developer teams. In release 4.0, during the spring of 2013, the
 merger of the products was completed and a unified product was released.
 
-See http://www.sip-router.org/ for the story of SER, OpenSER/Kamailio and kamailio.org.
+See http://www.kamailio.org/ for the story of SER, OpenSER/Kamailio and kamailio.org.
 
 V. Obtaining Help
 =================
diff --git a/README-MODULES b/README-MODULES
index 88b4807..a664bb2 100644
--- a/README-MODULES
+++ b/README-MODULES
@@ -1,14 +1,17 @@
 
 
-SIP-ROUTER modules
+Kamailio  modules
 ==================
 
-This is the second major release of the merged SIP Server - Kamailio and SER. 
-In the previous release some modules where provided in two versions, in Kamailio
+This is a major release of the merged SIP Server - Kamailio and SER. 
+
+In  previous releases (v3.x) some modules where provided in two versions, in Kamailio
 and SER flavours. These are now merged. In some cases, the functionality has 
 changed. You can still do the same operation, but how you do it may be different.
 
-Modules are in the "modules" directory.
+Modules are found in the "modules" directory. After installation that can
+be /usr/local/lib/kamailio/modules or /usr/lib/kamailio/modules.
+
 In previous releases there was a "modules_k" and "modules_s" directory, but in
 this release these directories are empty.
 
@@ -16,15 +19,16 @@ What is a module?
 =================
 A module consists of a lot of functions that enhance the core. Some of the modules
 depends on other modules. It's all properly documented in the README that belongs
-to each module (available as web pages on the sip-router.org web site).
+to each module (available as web pages on the kamailio.org web site).
 
-A module providers up to five different APIs:
+A module providers up to six different APIs:
 
-- Enhancements to the core SIP-router routing script (functions)
-- Commands for the management interface (MI and RPC)
+- Enhancements to the core Kamailio routing script (functions)
+- Commands for the management interfaces (MI and RPC)
 - Development interface for other modules
 - Pseudo-variables
 - Selects and config framework variables
+- Event-Routes
 
 A single module may provide a selection of this, maybe only one of them.
 
@@ -33,18 +37,19 @@ Kamailio Modules
 acc			Accounting
 acc_radius		Accounting with RADIUS backend
 alias_db		Alias management in database modules
+app_java		Lang :: Execute embedded Java applications
 app_lua			Lang :: Execute embedded LUA scripts
 app_mono		Lang :: Execute embedded MONO scripts (like C#, Java, javascript)
 app_perl		Lang :: Embedded perl script support
 app_python		Lang :: Execute embedded Python scripts
-app_java		Lang :: Execute embedded Java compiled code
 async			Asynchronus SIP request handling functions
 auth			MD5 digest authentication support
 auth_db			Authentication using a database module
 auth_diameter		Authentication based on Diameter
+auth_ephemeral		User authentication with ephemeral credentials
 auth_identity		SIP Identity support (RFC 4474)
 auth_radius		Radius authentication
-acp			Collection of functions for handling AVP's (from SER)
+avp			Collection of functions for handling AVP's (from SER)
 avpops			Attribute-value pair operations ("variables")
 benchmark		Development benchmark module
 blst			Blacklisting API for configuration scripts
@@ -63,42 +68,51 @@ db_berkeley		Database :: Berkeley DB (Oracle)
 db_cluster		Generic database connectors clustering and failover
 db_cassandra		Database :: Cassandra database server connector
 db_flatstore		Database :: Flatstore
+db_mongodb		Database :: MongoDB
 db_mysql		Database :: Mysql
 db_oracle		Database :: Oracle support
 db_perlvdb		Database :: Use perl database functions
 db_postgres		Database :: PostgreSQL
 db_text			Database :: Text support
 db_unixodbc		Database :: Unix ODBC support
-db2_ldap		Database connector to LDAP using the DB2 API
-db2_ops			Database operations for DB API v2
+db2_ldap		DB2 :: Database connector to LDAP using the DB2 API
+db2_ops			DB2 :: Database operations for DB API v2
 debugger		Interactive configuration processing debugger
 dialog			Dialog ("call") state module
 dialplan		Dialplan management
 dialog_ng		Dialog tracking module - next generation
 dispatcher		Load balancing and failover
 diversion		Call redirect support (SIP Diversion: header)
-dmq			Devel :: Distributed message queue system using SIP (early development)
+dmq			Distributed message queue system using SIP
+dnssec			DNSsec support in the DNS resolver
 domain			Proxy :: Multiple domain support using databases
 domainpolicy		Proxy :: Obsolete module - This module is no longer maintained
 drouting		Proxy :: Dynamic routing
 enum			Enum support
 exec			External exec module
+evapi			Network event broadcast API
 geoip			GeoIP API to configuration file
 group			Utils :: Group membership checking
+gzcompress		Compress and decompress SIP message body with zlib
 h350			LDAP/ITU H.350 multimedia schema support
 htable			Utils :: Hash table support
 imc			IM :: Instant messaging conference
 ims_auth		IMS authentication module
+ims_charging		IMS charging component module
 ims_icscf		IMS ICSCF component module
 ims_isc			IMS ISC component module
 ims_qos			IMS Diameter Rx interface
 ims_registrar_pcscf	IMS PCSCF registrar module
 ims_registrar_scscf	IMS SCSCF registrar module
+ims_usrloc_pcscf	IMS PCSCF usrloc module
+ims_usrloc_scscf	IMS SCSCF usrloc module
 ipops			IP and DNS related operations
 iptrtpproxy		NAT traversal :: Kernel based RTP proxy
 jabber			IM :: Jabber gateway
 json			Access to JSON document attributes
 jsonrpc-c		JSON-RPC client over netstrings protocol
+jsonrpc-s		JSON-RPC interface to the Kamailio RPC API
+kazoo			Middle layer connector for Kazoo VoIP platform
 kex			Proxy :: Kamailio core functions (backwards compatibility)
 lcr			Least cost routing
 ldap			LDAP Directory access
@@ -115,11 +129,14 @@ mi_xmlrpc		Management Interface :: XML-rpc
 misc_radius		Various Radius functions
 msilo			Text message storage
 msrp			Embedded MSRP relay (RFC 4975 and RFC 4976)
+mohqueue		Music on hold queuing system
 mqueue			Message queue system for configuration file
 nat_traversal		NAT :: NAT traversal module
 nathelper		NAT :: NAT traversal module :: RTPproxy (SIPPY software)
-ndb_redis		Connector to REDIS NoSQL Database engine
 ndb_cassandra		Connector to Apache Cassandra
+ndb_mongodb		Connector to MongoDB
+ndb_redis		Connector to REDIS NoSQL Database engine
+nosip			Handle non-sip messages received by SIP workers via event_route
 osp			Open Settlement Protocol support
 outbound		SIP Outbound Implementation
 p_usrloc		Partitioned and distributed user location services
@@ -156,12 +173,14 @@ registrar		Registrar/location server support
 rls			Presence :: Resource list server
 rr			Proxy :: Record routing
 rtimer			Utils :: Timer based routing script processing
+rtpengine		NAT :: RTPEngine media relay control functions
 rtpproxy		NAT :: Nat traversal module for RTPproxy control
 sanity			Syntax checking for incoming SIP requests
 sca			PRESENCE :: Shared call appearances
 sdpops			SDP operations
 seas			Application server interface
 sipcapture		SIP Capture Server module (used in the Homer project)
+sipt			SIP-T and SIP-I operations
 siptrace		Store SIP messages in database
 siputils		Various utilities for SIP call handling
 sl			Proxy :: Stateless handling of SIP messages
@@ -171,6 +190,7 @@ speeddial		Per-user speed-dial controller module
 sqlops			SQL operations
 sst			SIP Session Timers implementation
 statistics		Script statistics support
+statsd			Connector for statsd application
 textops			Text operations
 textopsx		Extra Text operations
 timer			Execute routing blocks on core timers (From SER)
@@ -189,6 +209,7 @@ uri_db			URI operation with database support
 userblacklist		User-specific blacklists
 usrloc			Proxy :: Location server
 utils			Various utilities (http query, xcap status)
+uuid			Unique string value generator using libuuid
 websocket		HTTP :: Websocket transport layer for proxy
 xcap_client		Presence :: XCAP support
 xcap_server		Presence :: XCAP server implementation
diff --git a/TODO b/TODO
index 709fce7..9f5c6be 100644
--- a/TODO
+++ b/TODO
@@ -1,4 +1,3 @@
-$Id$
 
 ( - todo, x - done)
 x change subst_run/str to return error (different from not found)
diff --git a/action.c b/action.c
index 43cac50..726c000 100644
--- a/action.c
+++ b/action.c
@@ -1,22 +1,15 @@
-
 /*
- * $Id$
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -25,39 +18,11 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * ---------
- *  2003-02-28  scratchpad compatibility abandoned (jiri)
- *  2003-01-29  removed scratchpad (jiri)
- *  2003-03-19  fixed set* len calculation bug & simplified a little the code
- *              (should be a little faster now) (andrei)
- *              replaced all mallocs/frees w/ pkg_malloc/pkg_free (andrei)
- *  2003-04-01  Added support for loose routing in forward (janakj)
- *  2003-04-12  FORCE_RPORT_T added (andrei)
- *  2003-04-22  strip_tail added (jiri)
- *  2003-10-02  added SET_ADV_ADDR_T & SET_ADV_PORT_T (andrei)
- *  2003-10-29  added FORCE_TCP_ALIAS_T (andrei)
- *  2004-11-30  added FORCE_SEND_SOCKET_T (andrei)
- *  2005-12-12  return & drop/exit differentiation (andrei)
- *  2005-12-19  select framework (mma)
- *  2006-04-12  updated *_send() calls to use a struct dest_info (andrei)
- *  2006-07-27  dns cache and dns based send address failover support (andrei)
- *  2006-12-06  on popular request last_retcode set also by module functions
- *              (andrei)
- *  2007-06-14  run_actions & do_action need a ctx or handle now, no more
- *               static vars (andrei)
- *  2008-11-18  support for variable parameter module functions (andrei)
- *  2008-12-03  use lvalues/rvalues for assignments (andrei)
- *  2008-12-17  added UDP_MTU_TRY_PROTO_T (andrei)
- *  2009-05-04  switched IF_T to rval_expr (andrei)
- *  2009-09-15  added SET_{FWD,RPL}_NO_CONNECT, SET_{FWD,RPL}_CLOSE (andrei)
- *  2010-06-01  special hack/support for fparam fixups so that they can handle
- *               variable RVEs (andrei)
  */
 
 /*!
  * \file
- * \brief SIP-router core :: 
+ * \brief Kamailio core :: Config file actions
  * \ingroup core
  * Module: \ref core
  */
@@ -567,7 +532,7 @@ int do_action(struct run_act_ctx* h, struct action* a, struct sip_msg* msg)
 				ret=E_BUG;
 				goto error;
 			}
-			/* DBG("XXX: message length %d, max %d\n",
+			/* LM_DBG("message length %d, max %d\n",
 				msg->len, a->val[0].u.number ); */
 			ret = msg->len >= a->val[0].u.number ? 1 : -1;
 			break;
@@ -1572,7 +1537,7 @@ int run_actions(struct run_act_ctx* h, struct action* a, struct sip_msg* msg)
 	}
 
 	if (unlikely(a==0)){
-		DBG("DEBUG: run_actions: null action list (rec_level=%d)\n", h->rec_lev);
+		LM_DBG("null action list (rec_level=%d)\n", h->rec_lev);
 		ret=1;
 	}
 
diff --git a/action.h b/action.h
index f8a30f6..d6f7810 100644
--- a/action.h
+++ b/action.h
@@ -1,22 +1,14 @@
 /*
- * $Id$
- *
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -28,7 +20,7 @@
 
 /*!
  * \file
- * \brief SIP-router core ::
+ * \brief Kamailio core :: Actions
  * \ingroup core
  * Module: \ref core
  */
diff --git a/async_task.c b/async_task.c
index 63a7809..019f493 100644
--- a/async_task.c
+++ b/async_task.c
@@ -1,7 +1,7 @@
-/**
+/*
  * Copyright (C) 2014 Daniel-Constantin Mierla (asipto.com)
  *
- * This file is part of Extensible SIP Router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -15,6 +15,12 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
+/*!
+* \file
+* \brief Kamailio core :: Asynchronus tasks
+* \ingroup core
+* Module: \ref core
+*/
 
 #include <stdio.h>
 #include <unistd.h>
diff --git a/async_task.h b/async_task.h
index 4c317a1..321ad06 100644
--- a/async_task.h
+++ b/async_task.h
@@ -1,7 +1,7 @@
-/**
+/*
  * Copyright (C) 2014 Daniel-Constantin Mierla (asipto.com)
  *
- * This file is part of Extensible SIP Router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -16,6 +16,10 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+/** Kamailio core :: Aync tasks
+ * @ingroup core
+ * Module: core
+ */
 
 #ifndef _ASYNC_TASK_H_
 #define _ASYNC_TASK_H_
diff --git a/atomic_ops.c b/atomic_ops.c
index e631f9f..2433557 100644
--- a/atomic_ops.c
+++ b/atomic_ops.c
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- * 
  * Copyright (C) 2006 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -15,18 +13,10 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/*
- *  atomic operations init
- */
-/* 
- * History:
- * --------
- *  2006-03-08  created by andrei
- *  2007-05-11  added lock_set support (andrei)
- */
+
 /*!
  * \file
- * \brief SIP-router core :: 
+ * \brief Kamailio core :: atomic operations init
  * \ingroup core
  * Module: \ref core
  */
diff --git a/atomic_ops.h b/atomic_ops.h
index c2c0249..b757bdc 100644
--- a/atomic_ops.h
+++ b/atomic_ops.h
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- * 
  * Copyright (C) 2006 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -18,13 +16,14 @@
 
 /*!
  * \file
- * \brief SIP-router core :: Atomic operations and memory barriers
+ * \brief Kamailio core :: Atomic operations and memory barriers
+ * Copyright (C) 2006 iptelorg GmbH
  * \ingroup core
  * Module: \ref core
  * See \ref atomic
  */
 
-/*
+/**
  * \page atomicops  Atomic operations and memory barriers
  *
  *  WARNING: atomic ops do not include memory barriers
diff --git a/atomic_ops_init.h b/atomic_ops_init.h
index c254c31..a66389e 100644
--- a/atomic_ops_init.h
+++ b/atomic_ops_init.h
@@ -1,16 +1,14 @@
 /* 
- * $Id$
- * 
  * Copyright (C) 2006 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -22,7 +20,9 @@
 
 /*!
  * \file
- * \brief SIP-router core :: atomic_ops init functions
+ * \brief Kamailio core :: atomic_ops init functions
+ *
+ * Copyright (C) 2006 iptelorg GmbH
  *
  * \ingroup core
  * Module: \ref core
@@ -30,11 +30,6 @@
  * Needed for lock intializing if no native asm locks are available
  *  for the current arch./compiler combination, see \ref atomic_ops.c
  */
-/* 
- * History:
- * --------
- *  2006-03-30  created by andrei
- */
 
 #ifndef __atomic_ops_init_h
 #define __atomic_ops_init_h
diff --git a/autover.h b/autover.h
deleted file mode 100644
index 18a9539..0000000
--- a/autover.h
+++ /dev/null
@@ -1,7 +0,0 @@
-/* this file is autogenerated by make autover.h
- * DO NOT EDIT IT
- */
-
-#define REPO_VER "8dec35"
-#define REPO_HASH "8dec35"
-#define REPO_STATE ""
diff --git a/basex.c b/basex.c
index 472c254..4a49478 100644
--- a/basex.c
+++ b/basex.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * convert/decode to/from ascii using various bases
  *
  * Copyright (C) 2008 iptelorg GmbH
@@ -16,19 +14,14 @@
  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-/*
+ *
  * Defines:
  *  BASE64_LOOKUP_TABLE - use small lookup tables for conversions (faster
  *                         in general)
- *
- * History:
- * --------
- *  2008-06-11  created by andrei
  */
 /*!
  * \file
- * \brief SIP-router core :: convert/decode to/from ascii using various bases
+ * \brief Kamailio core :: convert/decode to/from ascii using various bases
  * \ingroup core
  * Module: \ref core
  */
diff --git a/basex.h b/basex.h
index dc42530..f6cde08 100644
--- a/basex.h
+++ b/basex.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * convert/decode to/from ascii using various bases
  *
  * Copyright (C) 2008 iptelorg GmbH
@@ -20,8 +18,9 @@
 
 /*!
  * \file
- * \brief SIP-router core :: convert/decode to/from ascii using various bases
+ * \brief Kamailio core :: convert/decode to/from ascii using various bases
  *
+ * Copyright (C) 2008 iptelorg GmbH
  * \ingroup core
  *
  * Module: \ref core
diff --git a/bit_count.c b/bit_count.c
index faef43c..5a60cf9 100644
--- a/bit_count.c
+++ b/bit_count.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2010 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -15,9 +13,12 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  *
- * History
- * -------
- *  2010-04-26	Initial version (Miklos)
+ */
+/*!
+ * \file 
+ * \brief Kamailio core ::
+ * \ingroup core
+ * Module: \ref core
  */
 
 #include "bit_count.h"
diff --git a/bit_count.h b/bit_count.h
index 6e7f62c..65f7202 100644
--- a/bit_count.h
+++ b/bit_count.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2010 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -15,16 +13,18 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  *
- * History
- * -------
- *  2010-04-26	Initial version (Miklos)
  */
 
-/* Implements the bit counting function:
+/** Kamailio core ::  Implements the bit counting function:
+ * Copyright (C) 2010 iptelorg GmbH
+ * @ingroup core
+ * Module: core
+ *
  *   int bit_count(unsigned int u)
  *   Returns the number of bits in u.
  */
 
+
 #ifndef _BIT_COUNT_H
 #define _BIT_COUNT_H
 
diff --git a/bit_scan.c b/bit_scan.c
index 24b5219..66066c6 100644
--- a/bit_scan.c
+++ b/bit_scan.c
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- * 
  * Copyright (C) 2007 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -15,17 +13,10 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/*
- *  bit scan operations, see bit_scan.h.
- */
-/* 
- * History:
- * --------
- *  2007-06-23  created by andrei
- */
+
 /*!
  * \file
- * \brief SIP-router core :: 
+ * \brief Kamailio core ::  bit scan operations, see bit_scan.h.
  * \ingroup core
  * Module: \ref core
  */
diff --git a/bit_scan.h b/bit_scan.h
index 6745bd7..3e690b5 100644
--- a/bit_scan.h
+++ b/bit_scan.h
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- * 
  * Copyright (C) 2007 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -17,7 +15,9 @@
  */
 /*!
  * \file
- * \brief SIP-router core :: bit scan operations
+ * \brief Kamailio core :: bit scan operations
+ *
+ * Copyright (C) 2007 iptelorg GmbH
  * \ingroup core
  * Module: \ref core
  *
diff --git a/bit_test.h b/bit_test.h
index 9f83215..7745c04 100644
--- a/bit_test.h
+++ b/bit_test.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2010 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -15,13 +13,13 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  *
- * History
- * -------
- *  2010-04-26	Initial version (Miklos)
- *  2011-01-05	bit_test_and_reset added (Miklos)
  */
 
-/* Bit test functions:
+/** Kamailio core :: Bit test functions
+ * @ingroup core
+ * Module: core
+ *
+ * Bit test functions:
  *  - int bit_test(int offset, unsigned int *addr)
  *      Returns the bit found at offset position 
  *      in a bitstring pointed by addr.
diff --git a/cfg.lex b/cfg.lex
index 3321489..95edfdb 100644
--- a/cfg.lex
+++ b/cfg.lex
@@ -378,6 +378,7 @@ DNS_CACHE_MAX_TTL	dns_cache_max_ttl
 DNS_CACHE_MEM		dns_cache_mem
 DNS_CACHE_GC_INT	dns_cache_gc_interval
 DNS_CACHE_DEL_NONEXP	dns_cache_del_nonexp|dns_cache_delete_nonexpired
+DNS_CACHE_REC_PREF	dns_cache_rec_pref
 /* ipv6 auto bind */
 AUTO_BIND_IPV6		auto_bind_ipv6
 /* blacklist */
@@ -416,6 +417,7 @@ USER		"user"|"uid"
 GROUP		"group"|"gid"
 CHROOT		"chroot"
 WDIR		"workdir"|"wdir"
+RUNDIR		"rundir"|"run_dir"
 MHOMED		mhomed
 DISABLE_TCP		"disable_tcp"
 TCP_CHILDREN	"tcp_children"
@@ -490,6 +492,7 @@ VERSION_TABLE_CFG		"version_table"
 SERVER_ID     "server_id"
 
 MAX_RECURSIVE_LEVEL		"max_recursive_level"
+MAX_BRANCHES_PARAM		"max_branches"|"max_branches"
 
 LATENCY_LOG				latency_log
 LATENCY_LIMIT_DB		latency_limit_db
@@ -777,6 +780,8 @@ IMPORTFILE      "import_file"
 								return DNS_CACHE_GC_INT; }
 <INITIAL>{DNS_CACHE_DEL_NONEXP}	{ count(); yylval.strval=yytext;
 								return DNS_CACHE_DEL_NONEXP; }
+<INITIAL>{DNS_CACHE_REC_PREF}	{ count(); yylval.strval=yytext;
+								return DNS_CACHE_REC_PREF; }
 <INITIAL>{AUTO_BIND_IPV6}	{ count(); yylval.strval=yytext;
 								return AUTO_BIND_IPV6; }
 <INITIAL>{DST_BLST_INIT}	{ count(); yylval.strval=yytext;
@@ -817,6 +822,7 @@ IMPORTFILE      "import_file"
 <INITIAL>{GROUP}	{ count(); yylval.strval=yytext; return GROUP; }
 <INITIAL>{CHROOT}	{ count(); yylval.strval=yytext; return CHROOT; }
 <INITIAL>{WDIR}	{ count(); yylval.strval=yytext; return WDIR; }
+<INITIAL>{RUNDIR}	{ count(); yylval.strval=yytext; return RUNDIR; }
 <INITIAL>{MHOMED}	{ count(); yylval.strval=yytext; return MHOMED; }
 <INITIAL>{DISABLE_TCP}	{ count(); yylval.strval=yytext; return DISABLE_TCP; }
 <INITIAL>{TCP_CHILDREN}	{ count(); yylval.strval=yytext; return TCP_CHILDREN; }
@@ -949,6 +955,7 @@ IMPORTFILE      "import_file"
 <INITIAL>{VERSION_TABLE_CFG}  { count(); yylval.strval=yytext; return VERSION_TABLE_CFG;}
 <INITIAL>{SERVER_ID}  { count(); yylval.strval=yytext; return SERVER_ID;}
 <INITIAL>{MAX_RECURSIVE_LEVEL}  { count(); yylval.strval=yytext; return MAX_RECURSIVE_LEVEL;}
+<INITIAL>{MAX_BRANCHES_PARAM}  { count(); yylval.strval=yytext; return MAX_BRANCHES_PARAM;}
 <INITIAL>{LATENCY_LOG}  { count(); yylval.strval=yytext; return LATENCY_LOG;}
 <INITIAL>{MSG_TIME}  { count(); yylval.strval=yytext; return MSG_TIME;}
 <INITIAL>{ONSEND_RT_REPLY}	{ count(); yylval.strval=yytext; return ONSEND_RT_REPLY; }
diff --git a/cfg.y b/cfg.y
index 6289c61..85e69a6 100644
--- a/cfg.y
+++ b/cfg.y
@@ -425,6 +425,7 @@ extern char *default_routename;
 %token DNS_CACHE_MEM
 %token DNS_CACHE_GC_INT
 %token DNS_CACHE_DEL_NONEXP
+%token DNS_CACHE_REC_PREF
 
 /* ipv6 auto bind */
 %token AUTO_BIND_IPV6
@@ -467,6 +468,7 @@ extern char *default_routename;
 %token GROUP
 %token CHROOT
 %token WDIR
+%token RUNDIR
 %token MHOMED
 %token DISABLE_TCP
 %token TCP_ACCEPT_ALIASES
@@ -543,6 +545,7 @@ extern char *default_routename;
 %token CFG_DESCRIPTION
 %token SERVER_ID
 %token MAX_RECURSIVE_LEVEL
+%token MAX_BRANCHES_PARAM
 %token LATENCY_LOG
 %token LATENCY_LIMIT_DB
 %token LATENCY_LIMIT_ACTION
@@ -898,6 +901,8 @@ assign_stm:
 	| DNS_CACHE_GC_INT error { yyerror("boolean value expected"); }
 	| DNS_CACHE_DEL_NONEXP EQUAL NUMBER   { IF_DNS_CACHE(default_core_cfg.dns_cache_del_nonexp=$3); }
 	| DNS_CACHE_DEL_NONEXP error { yyerror("boolean value expected"); }
+	| DNS_CACHE_REC_PREF EQUAL NUMBER   { IF_DNS_CACHE(default_core_cfg.dns_cache_rec_pref=$3); }
+	| DNS_CACHE_REC_PREF error { yyerror("boolean value expected"); }
 	| AUTO_BIND_IPV6 EQUAL NUMBER {IF_AUTO_BIND_IPV6(auto_bind_ipv6 = $3);}
 	| AUTO_BIND_IPV6 error { yyerror("boolean value expected"); }
 	| DST_BLST_INIT EQUAL NUMBER   { IF_DST_BLACKLIST(dst_blacklist_init=$3); }
@@ -995,6 +1000,9 @@ assign_stm:
 	| WDIR EQUAL STRING     { working_dir=$3; }
 	| WDIR EQUAL ID         { working_dir=$3; }
 	| WDIR EQUAL error      { yyerror("string value expected"); }
+	| RUNDIR EQUAL STRING     { runtime_dir=$3; }
+	| RUNDIR EQUAL ID         { runtime_dir=$3; }
+	| RUNDIR EQUAL error      { yyerror("string value expected"); }
 	| MHOMED EQUAL NUMBER { mhomed=$3; }
 	| MHOMED EQUAL error { yyerror("boolean value expected"); }
 	| DISABLE_TCP EQUAL NUMBER {
@@ -1572,6 +1580,7 @@ assign_stm:
 	| HTTP_REPLY_PARSE EQUAL error { yyerror("boolean value expected"); }
     | SERVER_ID EQUAL NUMBER { server_id=$3; }
     | MAX_RECURSIVE_LEVEL EQUAL NUMBER { set_max_recursive_level($3); }
+    | MAX_BRANCHES_PARAM EQUAL NUMBER { sr_dst_max_branches = $3; }
     | LATENCY_LOG EQUAL NUMBER { default_core_cfg.latency_log=$3; }
 	| LATENCY_LOG EQUAL error  { yyerror("number  expected"); }
     | LATENCY_LIMIT_DB EQUAL NUMBER { default_core_cfg.latency_limit_db=$3; }
diff --git a/cfg/cfg.c b/cfg/cfg.c
index 329ee05..ea1355e 100644
--- a/cfg/cfg.c
+++ b/cfg/cfg.c
@@ -1,16 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2007 iptelorg GmbH
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -19,9 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History
- * -------
- *  2007-12-03	Initial version (Miklos)
  */
 
 #include <string.h>
diff --git a/cfg/cfg.h b/cfg/cfg.h
index c599aff..b3c5a1b 100644
--- a/cfg/cfg.h
+++ b/cfg/cfg.h
@@ -1,16 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2007 iptelorg GmbH
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -19,9 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History
- * -------
- *  2007-12-03	Initial version (Miklos)
  */
 
 #ifndef _CFG_H
diff --git a/cfg/cfg_ctx.c b/cfg/cfg_ctx.c
index bf88752..7d27246 100644
--- a/cfg/cfg_ctx.c
+++ b/cfg/cfg_ctx.c
@@ -1,16 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2007 iptelorg GmbH
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -19,9 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History
- * -------
- *  2007-12-03	Initial version (Miklos)
  */
 
 #include <string.h>
diff --git a/cfg/cfg_ctx.h b/cfg/cfg_ctx.h
index 06cf7a7..abcb424 100644
--- a/cfg/cfg_ctx.h
+++ b/cfg/cfg_ctx.h
@@ -1,16 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2007 iptelorg GmbH
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -19,9 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History
- * -------
- *  2007-12-03	Initial version (Miklos)
  */
 
 #ifndef _CFG_CTX_H
diff --git a/cfg/cfg_script.c b/cfg/cfg_script.c
index 067506b..d22d46b 100644
--- a/cfg/cfg_script.c
+++ b/cfg/cfg_script.c
@@ -1,16 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2008 iptelorg GmbH
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -19,10 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History
- * -------
- *  2008-01-24	dynamic groups are introduced in order to make
- *		variable declaration possible in the script (Miklos)
  */
 
 #include <string.h>
diff --git a/cfg/cfg_script.h b/cfg/cfg_script.h
index 7403988..7a4ac01 100644
--- a/cfg/cfg_script.h
+++ b/cfg/cfg_script.h
@@ -1,16 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2008 iptelorg GmbH
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -19,10 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History
- * -------
- *  2008-01-24	dynamic groups are introduced in order to make
- *		variable declaration possible in the script (Miklos)
  */
 
 #ifndef _CFG_SCRIPT_H
diff --git a/cfg/cfg_select.c b/cfg/cfg_select.c
index cb3d22a..ae8b0c8 100644
--- a/cfg/cfg_select.c
+++ b/cfg/cfg_select.c
@@ -1,16 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2008 iptelorg GmbH
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -19,9 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History
- * -------
- *  2008-01-10	Initial version (Miklos)
  */
 #include <stdio.h>
 
diff --git a/cfg/cfg_select.h b/cfg/cfg_select.h
index 3b05b09..585bc66 100644
--- a/cfg/cfg_select.h
+++ b/cfg/cfg_select.h
@@ -1,16 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2008 iptelorg GmbH
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -19,9 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History
- * -------
- *  2008-01-10	Initial version (Miklos)
  */
 
 #ifndef _CFG_SELECT_H
diff --git a/cfg/cfg_struct.c b/cfg/cfg_struct.c
index 27b0b83..8bfe429 100644
--- a/cfg/cfg_struct.c
+++ b/cfg/cfg_struct.c
@@ -1,16 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2007 iptelorg GmbH
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -19,11 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History
- * -------
- *  2007-12-03	Initial version (Miklos)
- *  2008-01-24	dynamic groups are introduced in order to make
- *		variable declaration possible in the script (Miklos)
  */
 
 #include <string.h>
diff --git a/cfg/cfg_struct.h b/cfg/cfg_struct.h
index 4b6d3c4..452bb90 100644
--- a/cfg/cfg_struct.h
+++ b/cfg/cfg_struct.h
@@ -1,16 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2007 iptelorg GmbH
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -19,11 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History
- * -------
- *  2007-12-03	Initial version (Miklos)
- *  2008-01-24	dynamic groups are introduced in order to make
- *		variable declaration possible in the script (Miklos)
  */
 
 #ifndef _CFG_STRUCT_H
diff --git a/cfg_core.c b/cfg_core.c
index f38e628..98a9c01 100644
--- a/cfg_core.c
+++ b/cfg_core.c
@@ -1,16 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2007 iptelorg GmbH
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -19,12 +17,9 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History
- * -------
- *  2007-12-03	Initial version (Miklos)
- *  2008-01-31  added DNS resolver parameters (Miklos)
  */
-/** core runtime config.
+
+/** Kamailio core :: core runtime config.
  * @file cfg_core.c
  * @ingroup core
  * Module: @ref core
diff --git a/cfg_core.h b/cfg_core.h
index 21e3759..f7db8d0 100644
--- a/cfg_core.h
+++ b/cfg_core.h
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2007 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,6 +17,15 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
+ *
+ */
+
+/** Kamailio core :: runtime configuration variables
+ * @file cfg_core.h
+ * @ingroup core
+ *
+ * Module: @ref core
+ *
  * HOWTO:
  *	If you need a new configuration variable within the core, put it into
  *	struct cfg_goup_core, and define it in cfg_core.c:core_cfg_def array.
@@ -31,16 +33,6 @@
  *	cfg_core.c:default_core_cfg
  *	Include this header file in your source code, and retrieve the
  *	value with cfg_get(core, core_cfg, variable_name).
- *
- * History
- * -------
- *  2007-12-03	Initial version (Miklos)
- */
-/** core runtime config.
- * @file cfg_core.h
- * @ingroup core
- *
- * Module: @ref core
  */
 
 
diff --git a/cfg_parser.c b/cfg_parser.c
index d764709..d8cb21e 100644
--- a/cfg_parser.c
+++ b/cfg_parser.c
@@ -1,18 +1,17 @@
 /*
- * $Id$
  * Standalone Configuration File Parser
  *
  * Copyright (C) 2008 iptelorg GmbH
  * Written by Jan Janak <jan at iptel.org>
  *
- * This file is part of SER, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SER is free software; you can redistribute it and/or modify it under the
+ * Kamailio is free software; you can redistribute it and/or modify it under the
  * terms of the GNU General Public License as published by the Free Software
  * Foundation; either version 2 of the License, or (at your option) any later
  * version.
  *
- * SER is distributed in the hope that it will be useful, but WITHOUT ANY
+ * Kamailio is distributed in the hope that it will be useful, but WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
  * details.
@@ -23,7 +22,8 @@
  */
 /*!
  * \file
- * \brief SIP-router core :: 
+ * \brief Kamailio core :: Standalone Configuration File Parser
+ * \author Jan Janak <jan at iptel.org>
  * \ingroup core
  *
  * Module: \ref core
@@ -283,7 +283,7 @@ static void print_token(cfg_token_t* token)
 	char* buf;
 
 	if ((buf = pkg_malloc(token->val.len * 2)) == NULL) {
-		DBG("token(%d, '%.*s', <%d,%d>-<%d,%d>)\n", 
+		LM_DBG("token(%d, '%.*s', <%d,%d>-<%d,%d>)\n", 
 			token->type, STR_FMT(&token->val),
 			token->start.line, token->start.col, 
 			token->end.line, token->end.col);
@@ -298,7 +298,7 @@ static void print_token(cfg_token_t* token)
 			default: buf[j++] = token->val.s[i];
 			}
 		}
-		DBG("token(%d, '%.*s', <%d,%d>-<%d,%d>)\n", 
+		LM_DBG("token(%d, '%.*s', <%d,%d>-<%d,%d>)\n", 
 			token->type, j, buf,
 			token->start.line, token->start.col, 
 			token->end.line, token->end.col);
diff --git a/cfg_parser.h b/cfg_parser.h
index 13e95b8..5ca2065 100644
--- a/cfg_parser.h
+++ b/cfg_parser.h
@@ -1,18 +1,17 @@
 /*
- * $Id$
  * Standalone Configuration File Parser
  *
  * Copyright (C) 2008 iptelorg GmbH
  * Written by Jan Janak <jan at iptel.org>
  *
- * This file is part of SER, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SER is free software; you can redistribute it and/or modify it under the
+ * Kamailio is free software; you can redistribute it and/or modify it under the
  * terms of the GNU General Public License as published by the Free Software
  * Foundation; either version 2 of the License, or (at your option) any later
  * version.
  *
- * SER is distributed in the hope that it will be useful, but WITHOUT ANY
+ * Kamailio is distributed in the hope that it will be useful, but WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
  * details.
@@ -24,7 +23,8 @@
 
 /*!
  * \file
- * \brief SIP-router core :: Standalone Configuration File Parser
+ * \brief Kamailio core :: Standalone Configuration File Parser
+ * Written by Jan Janak <jan at iptel.org>
  *
  * \ingroup core
  * Module: \ref core
diff --git a/char_msg_val.h b/char_msg_val.h
index 9565617..4d6887d 100644
--- a/char_msg_val.h
+++ b/char_msg_val.h
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- * 
  * Copyright (C) 2010 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -15,20 +13,13 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/*
- * char_msg_val.h
- */
-/*
- * History:
- * --------
- *  2010-02-10  moved from parser/msg_parser.h and added tag only mode
- *               by default (andrei)
-*/
+
 /** compute the characteristic value of a message.
  * @file
  * @ingroup core
- */
-/* Defines:
+ * \author andrei
+ *
+ * Defines:
  *  BRANCH_INCLUDE_FROMTO_BODY - if defined the old (pre 3.1) mode of
  *   including the full from & to bodies will be used (instead of only the
  *   tags).
diff --git a/clist.h b/clist.h
index 6f42b4f..2f1f8b5 100644
--- a/clist.h
+++ b/clist.h
@@ -1,18 +1,16 @@
 /*
- * $Id$
- *
  * circular list maintenance macros
  *
  * Copyright (C) 2005 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,16 +22,13 @@
 
 /*!
  * \file
- * \brief SIP-router core :: circular list maintenance macros
+ * \brief Kamailio core :: circular list maintenance macros
  *
+ * \author andrei
  * \ingroup core
  * Module: \ref core
  */
 
-/* History:
- * --------
- *  2005-08-08  created by andrei
- */
 
 #ifndef _clist_h
 #define _clist_h
diff --git a/comp_defs.h b/comp_defs.h
index 28d5c0b..158baa1 100644
--- a/comp_defs.h
+++ b/comp_defs.h
@@ -1,16 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -19,8 +17,13 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-
-/*! \brief compatibility defs for emergency roll-back if things do not work ;
+/*!
+ * \file
+ * \brief Kamailio core :: compatibility defs for emergency roll-back if things do not work 
+ *      
+ * \ingroup core 
+ * Module: \ref core                    
+ *  
  * if that happens:
  * 	- a) define PRESERVE_ZT (affects most of parser)
  * 	- b) define DONT_REMOVE_ZT (affects first line)
diff --git a/compiler_opt.h b/compiler_opt.h
index 3a90297..b784249 100644
--- a/compiler_opt.h
+++ b/compiler_opt.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- * 
  * Copyright (C) 2007 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -18,8 +16,9 @@
 
 /*!
  * \file
- * \brief SIP-router core :: Compiler specific optimizations
+ * \brief Kamailio core :: Compiler specific optimizations
  * \see \ref CompilerOptions
+ * \auth Andrei
  *
  * \ingroup core
  * Module: \ref core
@@ -45,12 +44,6 @@
 \endverbatim
  */
 
-/* 
- * History:
- * --------
- *  2007-05-14  created by andrei
- */
-
 #ifndef __compiler_opt_h
 #define __compiler_opt_h
 
diff --git a/config.h b/config.h
index 172ee7d..2bde88d 100644
--- a/config.h
+++ b/config.h
@@ -1,16 +1,14 @@
 /*
- *  $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -19,17 +17,12 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2003-04-05  DEFAULT_*_URL introduced (jiri)
- * 2003-07-04  fixed SRV lookup prefix for TLS/sips (andrei)
- * 2005-04-25  MAX_BRANCH_PARAM_LEN too small, fixed (andrei)
- *
  */
 
 /*!
  * \file
- * \brief SIP-router core :: Configuration options
+ * \brief Kamailio core :: Configuration options
+ * \author jiri, andrei
  *
  * These settings are settable by the user before compilation
  *
@@ -169,7 +162,8 @@
 #define MAX_RECEIVED_SIZE	59	/*!< forwarding  -- Via buffer dimensioning - Received header */
 #define MAX_RPORT_SIZE		13	/*!< forwarding  -- Via buffer dimensioning - Rport */
 
-#define MAX_BRANCHES    	12	/*!< maximum number of branches per transaction */
+#define MAX_BRANCHES_DEFAULT	12	/*!< default maximum number of branches per transaction */
+#define MAX_BRANCHES_LIMIT		32	/*!< limit of maximum number of branches per transaction */
 
 #define MAX_PRINT_TEXT 		256	/*!< max length of the text of fifo 'print' command */
 
diff --git a/core_cmd.c b/core_cmd.c
index afa4cf5..966bcbf 100644
--- a/core_cmd.c
+++ b/core_cmd.c
@@ -1,16 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2005 iptelorg GmbH
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -20,7 +18,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-/** core rpcs.
+/** Kamailio Core :: core rpcs.
  * @file core_cmd.c
  * @ingroup core
  */
@@ -759,7 +757,7 @@ static void core_tcp_list(rpc_t* rpc, void* c)
 	char* state;
 	char* type;
 	struct tcp_connection* con;
-	int i, len, timeout;
+	int i, len, timeout, lifetime;
 
 	if (tcp_disable) {
 		rpc->fault(c, 500, "tcp support disabled");
@@ -791,6 +789,7 @@ static void core_tcp_list(rpc_t* rpc, void* c)
 				BUG("failed to convert destination ip");
 			dst_ip[len] = 0;
 			timeout = TICKS_TO_S(con->timeout - get_ticks_raw());
+			lifetime = TICKS_TO_S(con->lifetime);
 			switch(con->state) {
 				case S_CONN_ERROR:
 					state = "CONN_ERROR";
@@ -816,11 +815,12 @@ static void core_tcp_list(rpc_t* rpc, void* c)
 				default:
 					state = "UNKNOWN";
 			}
-			rpc->struct_add(handle, "dssddsdsd",
+			rpc->struct_add(handle, "dssdddsdsd",
 					"id", con->id,
 					"type", type,
 					"state", state,
 					"timeout", timeout,
+					"lifetime", lifetime,
 					"ref_count", con->refcnt,
 					"src_ip", src_ip,
 					"src_port", con->rcv.src_port,
diff --git a/core_cmd.h b/core_cmd.h
index 4e092d2..fd71ef3 100644
--- a/core_cmd.h
+++ b/core_cmd.h
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2005 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -27,7 +20,7 @@
 
 /*!
  * \file
- * \brief SIP-router core :: 
+ * \brief Kamailio core :: Register RPC
  * \ingroup core
  * Module: \ref core
  */
diff --git a/core_stats.h b/core_stats.h
index 4a65fd9..603f304 100644
--- a/core_stats.h
+++ b/core_stats.h
@@ -21,14 +21,9 @@
  * they won't do anything).
  * @file
  * @ingroup core
+ * @author andrei
  */
  
-/*
- * History:
- * --------
- *  2010-02-01  initial version (andrei)
-*/
-
 #ifndef __core_stats_h
 #define __core_stats_h
 
diff --git a/counters.c b/counters.c
index 3bfe542..04356a7 100644
--- a/counters.c
+++ b/counters.c
@@ -15,18 +15,11 @@
  */
 
 /**
- * @brief counters/stats
+ * @brief Kamailio core :: counters/stats
  * @file
  * @ingroup: core
  */
 
-/*
- * History:
- * --------
- *  2010-08-06  initial version (andrei)
- *  2010-08-24  counters can be used (inc,add) before prefork_init (andrei)
-*/
-
 #include "counters.h"
 #include "str_hash.h"
 #include "str.h"
diff --git a/counters.h b/counters.h
index 9fd7c32..35a36cf 100644
--- a/counters.h
+++ b/counters.h
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- * 
  * Copyright (C) 2010 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -15,7 +13,8 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/** counter/stats.
+/** Kamailio core :: counter/stats.
+ * @author andrei
  * @file counters.h
  * @ingroup:  core
  *
@@ -31,11 +30,6 @@
  *  4. get a counter value (the handle can be obtained like above)
  *    val = counter_get(h);
  */
-/*
- * History:
- * --------
- *  2010-08-06  initial version (andrei)
-*/
 
 #ifndef __counters_h
 #define __counters_h
diff --git a/crc.c b/crc.c
index 7d63cad..4628463 100644
--- a/crc.c
+++ b/crc.c
@@ -1,18 +1,16 @@
 /*
- * $Id$
- *
  *  Crc - 32 + 16 BIT ANSI X3.66 + CCITT CRC checksum files
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -23,7 +21,7 @@
  */
 /*!
  * \file
- * \brief SIP-router core ::  Crc - 32 + 16 BIT ANSI X3.66 + CCITT CRC checksum files
+ * \brief Kamailio core ::  Crc - 32 + 16 BIT ANSI X3.66 + CCITT CRC checksum files
  * \ingroup core
  *
  * Module: \ref core
diff --git a/crc.h b/crc.h
index 1318e27..a52348f 100644
--- a/crc.h
+++ b/crc.h
@@ -1,4 +1,3 @@
-/* $Id$*/
 
 #ifndef _CRC_H_
 #define _CRC_H_
diff --git a/daemonize.c b/daemonize.c
index f8992d7..9d936d4 100644
--- a/daemonize.c
+++ b/daemonize.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -15,20 +13,10 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/*
- * 
- * History:
- * --------
- *  2004-02-20  removed from ser main.c into its own file (andrei)
- *  2004-03-04  moved setuid/setgid in do_suid() (andrei)
- *  2004-03-25  added increase_open_fds & set_core_dump (andrei)
- *  2004-05-03  applied pgid patch from janakj
- *  2007-06-07  added mlock_pages (no swap) support (andrei)
-  *             added set_rt_prio() (andrei)
- */
+
 /*!
  * \file
- * \brief SIP-router core :: 
+ * \brief Kamailio core :: Daemon init
  * \ingroup core
  * Module: \ref core
  */
@@ -500,7 +488,7 @@ int increase_open_fds(int target)
 		goto error;
 	}
 	orig=lim;
-	DBG("current open file limits: %lu/%lu\n",
+	LM_DBG("current open file limits: %lu/%lu\n",
 			(unsigned long)lim.rlim_cur, (unsigned long)lim.rlim_max);
 	if ((lim.rlim_cur==RLIM_INFINITY) || (target<=lim.rlim_cur))
 		/* nothing to do */
@@ -515,7 +503,7 @@ int increase_open_fds(int target)
 		lim.rlim_max=target;
 		lim.rlim_cur=target;
 	}
-	DBG("increasing open file limits to: %lu/%lu\n",
+	LM_DBG("increasing open file limits to: %lu/%lu\n",
 			(unsigned long)lim.rlim_cur, (unsigned long)lim.rlim_max);
 	if (setrlimit(RLIMIT_NOFILE, &lim)<0){
 		LM_CRIT("cannot increase the open file limit to"
@@ -592,7 +580,7 @@ int set_core_dump(int enable, long unsigned int size)
 		}
 	}
 done:
-	DBG("core dump limits set to %lu\n", (unsigned long)newlim.rlim_cur);
+	LM_DBG("core dump limits set to %lu\n", (unsigned long)newlim.rlim_cur);
 	return 0;
 error:
 	return -1;
diff --git a/daemonize.h b/daemonize.h
index efae0d9..a9b40f7 100644
--- a/daemonize.h
+++ b/daemonize.h
@@ -1,5 +1,4 @@
 /*
- * $Id$
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
@@ -15,13 +14,15 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/*
+/*!
+ * \file
+ * \brief Kamailio core :: Daemonize
+ * \author andrei
+ *      
+ * \ingroup core 
+ * Module: \ref core                    
+ *  
  * 
- * History:
- * --------
- *  2004-02-20  created by andrei
- *  2007-06-07  added mem_lock_pages() (andrei)
- *  2010-08-19  send status via pipe code derived from 9167c1 (ibc) (andrei)
  */
 
 #ifndef _daemonize_h
diff --git a/data_lump.c b/data_lump.c
index 6beb93f..daab9aa 100644
--- a/data_lump.c
+++ b/data_lump.c
@@ -1,16 +1,14 @@
-/* $Id$
- *
- *
+/*
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -19,19 +17,10 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2003-01-19  support for duplication lump lists added (jiri)
- *  2003-03-31  added subst lumps --they expand in ip addr, port a.s.o (andrei)
- *  2003-04-01  added conditional lump support functions (andrei)
- *  2003-10-20  anchor_lump & del_lump will automatically choose the lump list
- *              based on  msg->eoh comparisons (andrei)
- *  2003-10-28  added extra checks (paranoia) for {anchor,del}_lump (andrei)
- *  2005-03-24  the type of type attribute changed to enum _hdr_types_t (janakj)
  */
 /*!
  * \file
- * \brief SIP-router core :: 
+ * \brief Kamailio core :: Data lumps
  * \ingroup core
  * Module: \ref core
  */
diff --git a/data_lump.h b/data_lump.h
index 9dcfd2d..72d664b 100644
--- a/data_lump.h
+++ b/data_lump.h
@@ -1,18 +1,16 @@
 /*
- * $Id$
- *
  * adding/removing headers or any other data chunk from a message
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -22,20 +20,11 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-/* History:
- * --------
- *  2003-01-29  s/int/enum ... more convenient for gdb (jiri)
- *  2003-03-31  added subst lumps -- they expand in ip addr, port a.s.o (andrei)
- *  2003-04-01  added opt (condition) lumps (andrei)
- *  2003-04-02  added more subst lumps: SUBST_{SND,RCV}_ALL  
- *              => ip:port;transport=proto (andrei)
- *  2005-03-22  the type of type attribute changed to enum _hdr_types_t (janakj)
- *
- */
-
 /*!
  * \file
- * \brief SIP-router core :: Data_lumps
+ * \brief Kamailio core :: Data_lumps
+ * \author jiri, andrei, janakj
+ * adding/removing headers or any other data chunk from a message
  * \ingroup core
  * Module: \ref core
  */
diff --git a/data_lump_rpl.c b/data_lump_rpl.c
index c5231e5..6ce77f8 100644
--- a/data_lump_rpl.c
+++ b/data_lump_rpl.c
@@ -1,22 +1,14 @@
 /*
- * $Id$
- *
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -25,18 +17,10 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * 2002-02-14 : created by bogdan
- * 2003-09-11 : lump_rpl type added - LUMP_RPL_BODY & LUMP_RPL_HDR (bogdan)
- * 2003-11-11 : build_lump_rpl merged into add_lump_rpl; types -> flags ;
- *              flags LUMP_RPL_NODUP and LUMP_RPL_NOFREE added (bogdan)
- * 2006-10-16   add_lump_rpl2 added: same as the old add_lump_rpl, but
- *               returns a lump_rpl**, making a specific lump removal much
- *               more easy (andrei)
  */
 /*!
  * \file
- * \brief SIP-router core :: 
+ * \brief Kamailio core :: Data lump handling
  * \ingroup core
  * Module: \ref core
  */
diff --git a/data_lump_rpl.h b/data_lump_rpl.h
index 4db3211..9396273 100644
--- a/data_lump_rpl.h
+++ b/data_lump_rpl.h
@@ -1,17 +1,14 @@
 /*
- * $Id$
- *
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -20,20 +17,12 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * 2002-02-14 : created by bogdan
- * 2003-09-11 : lump_rpl type added - LUMP_RPL_BODY & LUMP_RPL_HDR (bogdan)
- * 2003-11-11 : build_lump_rpl merged into add_lump_rpl; type removed;
- *              flags LUMP_RPL_BODY, LUMP_RPL_NODUP and LUMP_RPL_NOFREE
- *              added (bogdan)
- * 2006-10-16   add_lump_rpl2 added: same as the old add_lump_rpl, but
- *               returns a lump_rpl**, making a specific lump removal much
- *               more easy (andrei)
  */
 
 /*!
  * \file
- * \brief SIP-router core :: Data lumps
+ * \brief Kamailio core :: Data lumps
+ * \author bogdan, andrei
  * \ingroup core
  * Module: \ref core
  */
diff --git a/dns_cache.c b/dns_cache.c
index 2e963a8..cb2d5be 100644
--- a/dns_cache.c
+++ b/dns_cache.c
@@ -1,23 +1,16 @@
 /*
- * $Id$
- *
  * resolver related functions
  *
  * Copyright (C) 2006 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -26,31 +19,10 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/* History:
- * --------
- *  2006-07-13  created by andrei
- *  2006-10-06  port fix (andrei)
- *  2007-06-14  dns iterate through A & AAAA records fix (andrei)
- *  2007-06-15  srv rr weight based load balancing support (andrei)
- *  2007-06-16  naptr support (andrei)
- *  2008-07-18  DNS watchdog support -- can be used to inform the core
- *              that the DNS servers are down (Miklos)
- *  2008-07-25  various rpc commands to manipulate the content
- *		of the cache (Miklos)
- *  2007-07-30  DNS cache measurements added (Gergo)
- *  2007-08-17  dns_cache_del_nonexp config option is introduced (Miklos)
- *  2008-02-04  DNS cache options are adapted for the configuration
- *		framework (Miklos)
- *  2008-02-11  dns_cache_init cfg parameter is introduced (Miklos)
- *  2008-10-17  fixed srv continue with 0 hostname (when falling back to
-                  aaaa) (andrei)
- *  2009-03-30  TXT record support, more rpcs (andrei)
- *  2009-03-30  EBL record support (andrei)
- *  2009-04-01  PTR record support (andrei)
- */
+
 /*!
  * \file
- * \brief SIP-router core :: 
+ * \brief Kamailio core :: DNS cache handling
  * \ingroup core
  * Module: \ref core
  */
@@ -562,8 +534,7 @@ inline static struct dns_hash_entry* _dns_hash_find(str* name, int type,
 again:
 	*h=dns_hash_no(name->s, name->len, type);
 #ifdef DNS_CACHE_DEBUG
-	DBG("dns_hash_find(%.*s(%d), %d), h=%d\n", name->len, name->s,
-												name->len, type, *h);
+	LM_DBG("(%.*s(%d), %d), h=%d\n", name->len, name->s, name->len, type, *h);
 #endif
 	clist_foreach_safe(&dns_hash[*h], e, tmp, next){
 		if (
@@ -823,7 +794,7 @@ inline static int dns_cache_add(struct dns_hash_entry* e)
 	atomic_inc(&e->refcnt);
 	h=dns_hash_no(e->name, e->name_len, e->type);
 #ifdef DNS_CACHE_DEBUG
-	DBG("dns_cache_add: adding %.*s(%d) %d (flags=%0x) at %d\n",
+	LM_DBG("adding %.*s(%d) %d (flags=%0x) at %d\n",
 			e->name_len, e->name, e->name_len, e->type, e->ent_flags, h);
 #endif
 	LOCK_DNS_HASH();
@@ -865,7 +836,7 @@ inline static int dns_cache_add_unsafe(struct dns_hash_entry* e)
 	atomic_inc(&e->refcnt);
 	h=dns_hash_no(e->name, e->name_len, e->type);
 #ifdef DNS_CACHE_DEBUG
-	DBG("dns_cache_add: adding %.*s(%d) %d (flags=%0x) at %d\n",
+	LM_DBG("adding %.*s(%d) %d (flags=%0x) at %d\n",
 			e->name_len, e->name, e->name_len, e->type, e->ent_flags, h);
 #endif
 	*dns_cache_mem_used+=e->total_size; /* no need for atomic ops, written
@@ -890,8 +861,7 @@ inline static struct dns_hash_entry* dns_cache_mk_bad_entry(str* name,
 	ticks_t now;
 
 #ifdef DNS_CACHE_DEBUG
-	DBG("dns_cache_mk_bad_entry(%.*s, %d, %d, %d)\n", name->len, name->s,
-									type, ttl, flags);
+	LM_DBG("(%.*s, %d, %d, %d)\n", name->len, name->s, type, ttl, flags);
 #endif
 	size=sizeof(struct dns_hash_entry)+name->len-1+1;
 	e=shm_malloc(size);
@@ -1237,8 +1207,7 @@ inline static struct dns_hash_entry* dns_cache_mk_rd_entry(str* name, int type,
 	*tail=0; /* mark the end of our tmp_lst */
 	if (size==0){
 #ifdef DNS_CACHE_DEBUG
-		DBG("dns_cache_mk_rd_entry: entry %.*s (%d) not found\n",
-				name->len, name->s, type);
+		LM_DBG("entry %.*s (%d) not found\n", name->len, name->s, type);
 #endif
 		return 0;
 	}
@@ -1768,7 +1737,7 @@ inline static struct dns_hash_entry* dns_get_related(struct dns_hash_entry* e,
 	ret=0;
 	l=e;
 #ifdef DNS_CACHE_DEBUG
-	DBG("dns_get_related(%p (%.*s, %d), %d, *%p) (%d)\n", e,
+	LM_DBG("(%p (%.*s, %d), %d, *%p) (%d)\n", e,
 			e->name_len, e->name, e->type, type, *records, cname_chain_len);
 #endif
 	clist_init(l, next, prev);
@@ -1935,7 +1904,7 @@ inline static struct dns_hash_entry* dns_cache_do_request(str* name, int type)
 					((struct cname_rdata*)l->prev->rr_lst->rdata)->name;
 				cname_val.len=
 					((struct cname_rdata*)l->prev->rr_lst->rdata)->name_len;
-				DBG("dns_cache_do_request: cname detected: %.*s (%d)\n",
+				LM_DBG("cname detected: %.*s (%d)\n",
 						cname_val.len, cname_val.s, cname_val.len);
 			}
 			/* add all the records to the hash */
@@ -1999,7 +1968,7 @@ inline static struct dns_hash_entry* dns_cache_do_request(str* name, int type)
 			UNLOCK_DNS_HASH();
 			/* if only cnames found => try to resolve the last one */
 			if (cname_val.s){
-				DBG("dns_cache_do_request: dns_get_entry(cname: %.*s (%d))\n",
+				LM_DBG("dns_get_entry(cname: %.*s (%d))\n",
 						cname_val.len, cname_val.s, cname_val.len);
 				e=dns_get_entry(&cname_val, type);
 			}
@@ -2188,7 +2157,7 @@ error:
  *    *no=0;
  *    now=get_ticks_raw();
  *    while(rr=dns_entry_get_rr(e, no, now){
- *       DBG("address %d\n", *no);
+ *       LM_DBG("address %d\n", *no);
  *       *no++;  ( get the next address next time )
  *     }
  *  }
@@ -2264,7 +2233,7 @@ inline static unsigned dns_srv_random(unsigned max)
  *    srv_reset_tried(&tried);
  *    now=get_ticks_raw();
  *    while(rr=dns_srv_get_nxt_rr(e, &tried, &no, now){
- *       DBG("address %d\n", *no);
+ *       LM_DBG("address %d\n", *no);
  *     }
  *  }
  *
@@ -2358,7 +2327,7 @@ retry:
 	for (i=0; (i<idx) && (r_sums[i].r_sum<rand_w); i++);
 found:
 #ifdef DNS_CACHE_DEBUG
-	DBG("dns_srv_get_nxt_rr(%p, %lx, %d, %u): selected %d/%d in grp. %d"
+	LM_DBG("(%p, %lx, %d, %u): selected %d/%d in grp. %d"
 			" (rand_w=%d, rr=%p rd=%p p=%d w=%d rsum=%d)\n",
 		e, (unsigned long)*tried, *no, now, i, idx, n, rand_w, r_sums[i].rr,
 		(r_sums[i].rr)?r_sums[i].rr->rdata:0,
@@ -2423,7 +2392,7 @@ inline static struct hostent* dns_entry2he(struct dns_hash_entry* e)
 				memcpy(p_addr[i], ((struct a_rdata*)rr->rdata)->ip, len);
 	}
 	if (i==0){
-		DBG("DEBUG: dns_entry2he: no good records found (%d) for %.*s (%d)\n",
+		LM_DBG("no good records found (%d) for %.*s (%d)\n",
 				rr_no, e->name_len, e->name, e->type);
 		return 0; /* no good record found */
 	}
@@ -2759,9 +2728,8 @@ struct naptr_rdata* dns_naptr_sip_iterate(struct dns_rr* naptr_head,
 			continue; /* already tried */
 		}
 #ifdef DNS_CACHE_DEBUG
-		DBG("naptr_iterate: found a valid sip NAPTR rr %.*s,"
-					" proto %d\n", naptr->repl_len, naptr->repl,
-					(int)naptr_proto);
+		LM_DBG("found a valid sip NAPTR rr %.*s, proto %d\n",
+				naptr->repl_len, naptr->repl, (int)naptr_proto);
 #endif
 		if ((naptr_proto_supported(naptr_proto))){
 			if (naptr_choose(&naptr_saved, &saved_proto,
@@ -2773,9 +2741,8 @@ struct naptr_rdata* dns_naptr_sip_iterate(struct dns_rr* naptr_head,
 	if (naptr_saved){
 		/* found something */
 #ifdef DNS_CACHE_DEBUG
-		DBG("naptr_iterate: choosed NAPTR rr %.*s, proto %d"
-					" tried: 0x%x\n", naptr_saved->repl_len,
-					naptr_saved->repl, (int)saved_proto, *tried);
+		LM_DBG("choosed NAPTR rr %.*s, proto %d tried: 0x%x\n",
+			naptr_saved->repl_len, naptr_saved->repl, (int)saved_proto, *tried);
 #endif
 		*tried|=1<<idx;
 		*proto=saved_proto;
@@ -2840,7 +2807,7 @@ struct hostent* dns_naptr_sip_resolvehost(str* name, unsigned short* port,
 												&srv_name, &n_proto)){
 			if ((he=dns_srv_get_he(&srv_name, port, dns_flags))!=0){
 #ifdef DNS_CACHE_DEBUG
-				DBG("dns_naptr_sip_resolvehost(%.*s, %d, %d) srv, ret=%p\n",
+				LM_DBG("(%.*s, %d, %d) srv, ret=%p\n",
 							name->len, name->s, (int)*port, (int)*proto, he);
 #endif
 				dns_hash_put(e);
@@ -2956,8 +2923,7 @@ inline static int dns_a_resolve( struct dns_hash_entry** e,
 		ret=-E_DNS_EOR;
 	}
 error:
-	DBG("dns_a_resolve(%.*s, %d) returning %d\n",
-			name->len, name->s, *rr_no, ret);
+	LM_DBG("(%.*s, %d) returning %d\n", name->len, name->s, *rr_no, ret);
 	return ret;
 }
 
@@ -3198,7 +3164,7 @@ inline static int dns_srv_resolve_ip(struct dns_srv_handle* h,
 	}while(ret<0);
 error:
 #ifdef DNS_CACHE_DEBUG
-	DBG("dns_srv_resolve_ip(\"%.*s\", %d, %d), ret=%d, ip=%s\n",
+	LM_DBG("(\"%.*s\", %d, %d), ret=%d, ip=%s\n",
 			name->len, name->s, h->srv_no, h->ip_no, ret,
 			ip?ZSW(ip_addr2a(ip)):"");
 #endif
@@ -3290,7 +3256,7 @@ inline static int dns_srv_sip_resolve(struct dns_srv_handle* h,  str* name,
 						{
 							h->proto = *proto = srv_proto_list[i].proto;
 #ifdef DNS_CACHE_DEBUG
-							DBG("dns_srv_sip_resolve(%.*s, %d, %d), srv0, ret=%d\n",
+							LM_DBG("(%.*s, %d, %d), srv0, ret=%d\n",
 								name->len, name->s, h->srv_no, h->ip_no, ret);
 #endif
 							return ret;
@@ -3309,7 +3275,7 @@ inline static int dns_srv_sip_resolve(struct dns_srv_handle* h,  str* name,
 			ret=dns_srv_resolve_ip(h, &srv_name, ip, port, flags);
 			if (proto)
 				*proto=h->proto;
-			DBG("dns_srv_sip_resolve(%.*s, %d, %d), srv, ret=%d\n",
+			LM_DBG("(%.*s, %d, %d), srv, ret=%d\n",
 					name->len, name->s, h->srv_no, h->ip_no, ret);
 			return ret;
 	}
@@ -3323,7 +3289,7 @@ inline static int dns_srv_sip_resolve(struct dns_srv_handle* h,  str* name,
 	if (proto)
 		*proto=h->proto;
 #ifdef DNS_CACHE_DEBUG
-	DBG("dns_srv_sip_resolve(%.*s, %d, %d), ip, ret=%d\n",
+	LM_DBG("(%.*s, %d, %d), ip, ret=%d\n",
 			name->len, name->s, h->srv_no, h->ip_no, ret);
 #endif
 	return ret;
@@ -3398,7 +3364,7 @@ inline static int dns_naptr_sip_resolve(struct dns_srv_handle* h,  str* name,
 									from previous dns_srv_sip_resolve calls */
 			if ((ret=dns_srv_resolve_ip(h, &srv_name, ip, port, flags))>=0){
 #ifdef DNS_CACHE_DEBUG
-				DBG("dns_naptr_sip_resolve(%.*s, %d, %d), srv0, ret=%d\n",
+				LM_DBG("(%.*s, %d, %d), srv0, ret=%d\n",
 								name->len, name->s, h->srv_no, h->ip_no, ret);
 #endif
 				dns_hash_put(e);
@@ -3945,7 +3911,7 @@ void dns_cache_flush(int del_permanent)
 	struct dns_hash_entry* e;
 	struct dns_hash_entry* tmp;
 
-	DBG("dns_cache_flush(): removing elements from the cache\n");
+	LM_DBG("removing elements from the cache\n");
 	LOCK_DNS_HASH();
 		for (h=0; h<DNS_HASH_SIZE; h++){
 			clist_foreach_safe(&dns_hash[h], e, tmp, next){
diff --git a/dns_cache.h b/dns_cache.h
index e93b59b..fc7b037 100644
--- a/dns_cache.h
+++ b/dns_cache.h
@@ -1,18 +1,16 @@
 /*
- * $Id$
- *
  * resolver/dns related functions, dns cache and failover
  *
  * Copyright (C) 2006 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -22,16 +20,11 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-/* History:
- * --------
- *  2006-07-13  created by andrei
- *  2007-06-16  naptr support (andrei)
- *  2007-07-30  DNS cache measurements added (Gergo)
- */
 
 /**
  * @file
- * @brief SIP-router core :: resolver/dns related functions, dns cache and failover
+ * @brief Kamailio core :: resolver/dns related functions, dns cache and failover
+ * @author andrei
  * @ingroup core
  * Module: @ref core
  */
@@ -166,10 +159,8 @@ struct dns_hash_entry{
 };
 
 
-#if MAX_BRANCHES < 16
-/* forking is limited by tm to 12 by default */
-typedef unsigned short srv_flags_t;
-#elif MAX_BRANCHES < 32
+/* to fit in the limit of MAX_BRANCHES */
+#if MAX_BRANCHES_LIMIT < 32
 typedef unsigned int srv_flags_t;
 #else
 typedef unsigned long long srv_flags_t;
diff --git a/dns_func.c b/dns_func.c
index da2ce7b..7875457 100644
--- a/dns_func.c
+++ b/dns_func.c
@@ -1,7 +1,5 @@
 
 /* 
- * $Id$
- * 
  * Copyright (C) 2013  mariuszbi at gmail.com
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -16,14 +14,13 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/*
- * DNS wrappers
+/*!
+ * \file 
+ * \brief Kamailio core :: DNS wrappers
+ * \author mariuszbi at gmail.com
+ * \ingroup core
+ * Module: \ref core
  */
-/*
- * History:
- * --------
- *  2013-03 initial version (marius)
-*/
 
 #include "dns_func.h"
 
diff --git a/dns_func.h b/dns_func.h
index 623c3b8..2ed8022 100644
--- a/dns_func.h
+++ b/dns_func.h
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- * 
  * Copyright (C) 2013 mariuszbi at gmail.com
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -15,14 +13,16 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/*
- * DNS Wrapper functions 
+/*!
+ * \file
+ * \brief Kamailio core :: DNS wrapper functions
+ * \author mariuszbi at gmail.com
+ *      
+ * \ingroup core 
+ * Module: \ref core                    
+ *  
+ *
  */
-/*
- * History:
- * --------
- *  2013-03  initial version (marius)
-*/
 
 #ifndef DNS_FUNC_H
 #define DNS_FUNC_H
diff --git a/dns_wrappers.h b/dns_wrappers.h
index d71c882..760c4c1 100644
--- a/dns_wrappers.h
+++ b/dns_wrappers.h
@@ -1,23 +1,16 @@
 /*
- * $Id$
- *
  * resolver related functions
  *
  * Copyright (C) 2006 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -26,14 +19,11 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/* History:
- * --------
- *  2006-07-23  created by andrei
- */
 
 /**
  * @file
- * @brief SIP-router core :: resolver related functions
+ * @brief Kamailio core :: resolver related functions
+ * @author andrei
  * @ingroup core
  * Module: @ref core
  */
@@ -42,7 +32,6 @@
 #define __dns_wrappers_h
 
 struct hostent* dns_resolvehost(char* name);
-struct hostent* dns_sip_resolvehost(str* name, unsigned short* port,
-										char* proto);
+struct hostent* dns_sip_resolvehost(str* name, unsigned short* port, char* proto);
 
 #endif
diff --git a/doc/cfg.txt b/doc/cfg.txt
index dd9e959..374cce4 100644
--- a/doc/cfg.txt
+++ b/doc/cfg.txt
@@ -1,9 +1,3 @@
-# $Id$
-#
-# History:
-# --------
-# 2007-12-06:	Created by Miklos
-
 SIP-router Configuration Framework
 
 1. Overview
diff --git a/doc/config_migration.txt b/doc/config_migration.txt
index d55510c..9200cea 100644
--- a/doc/config_migration.txt
+++ b/doc/config_migration.txt
@@ -1,9 +1,3 @@
-# $Id$
-#
-# History:
-# --------
-# 2009-05-06  created by andrei
-
 =============================================================
 = Config migration guide from ser or kamailio to sip-router =
 =============================================================
diff --git a/doc/cvs-commit-rules.txt b/doc/cvs-commit-rules.txt
index 6fa8d74..b5153e4 100644
--- a/doc/cvs-commit-rules.txt
+++ b/doc/cvs-commit-rules.txt
@@ -1,23 +1,23 @@
-# $Id$
-#
-# SIP-router git commit rules
-
+Kamailio git commit rules
+=========================
 
 1. Changing other people's code:
 --------------------------------
- - send a patch to the code/module mantainer and/or sr-dev (don't commit changes to code you don't own if you don't have the mantainer's approval)
+ - send a patch to the code/module mantainer and/or sr-dev 
+   (don't commit changes to code you don't own if you don't have the mantainer's approval)
 Exceptions:
  a. compilation (this includes warning) fixes
  b. bug fixes
- c. api changes (some external functions definitions change)
+ c. API changes (some external functions definitions change)
  d. small changes due to a new release in the very near future (allowed only for the release manager)
 
 2. Code requirements
 --------------------
 2.1 Unstable branch:
- - the code must compile (at least on one architecture). If the code does not compile, but you still want to commit it, comment it out (#if 0 ... #endif)
+ - the code must compile (at least on one architecture). If the code does not compile, 
+   but you still want to commit it, comment it out (#if 0 ... #endif)
  - the code should compile without warnings (with -Wall) (exceptions: very difficult to avoid warnings)
- - follow SIP-router coding style
+ - follow Kamailio coding style
 
 2.2. Stable branch (everything for unstable branch +)
 ------------------------------------------------------
diff --git a/doc/dns.txt b/doc/dns.txt
index 7942ace..a424308 100644
--- a/doc/dns.txt
+++ b/doc/dns.txt
@@ -1,27 +1,22 @@
-# $Id$
-#
-# History:
-# --------
-# 2006-09-08  created by andrei
-# 2007-06-18  added naptr & friends, dns_srv_lb, more compile options (andrei)
-#
-
-SIP-router and DNS Overview
+
+Kamailio and DNS Overview
 ---------------------------
 
- The dns subsystem in sip-router can either directly use libresolv and a combination
-  of the locally configured dns server, /etc/hosts and the local Network 
+ The DNS subsystem in Kamailio can either directly use libresolv and a combination
+  of the locally configured DNS server, /etc/hosts and the local Network 
   Information Service (NIS/YP a.s.o) or cache the query results (both positive
   and negative) and look first in its internal cache.
- When its internal dns cache is enabled, sip-router can also use dns failover: if
-  one destination resolves to multiple addresses sip-router can try all of them until
+
+ When its internal DNS cache is enabled, Kamailio can also use DNS failover: if
+  one destination resolves to multiple addresses Kamailio can try all of them until
   it finds one to which it can successfully send the packet or it exhausts all 
-  of them. sip-router (The tm module to be more precise) uses the DNS failover also 
+  of them. Kamailio (The tm module to be more precise) uses the DNS failover also 
   when the destination host doesn't send any reply to a forwarded invite within the
   SIP timeout interval (whose value can be configured using the tm fr_timer
   parameter).
-  When SRV based load balancing is enabled sip-router can even do DNS based load 
-  balancing (see RFC2782 and the dns_srv_lb option below).
+  When SRV based load balancing is enabled Kamailio can even do DNS based load 
+  balancing (see RFC2782 and the dns_srv_lb option below). This is using the
+  weight value in the DNS SRV record.
 
 
 DNS Cache and Failover Drawbacks
@@ -29,18 +24,18 @@ DNS Cache and Failover Drawbacks
 
  Using the DNS cache and the DNS failover has also some drawbacks: 
 
-  1. only the locally configured DNS server (usually in /etc/resolv.conf) is
-  used for the requests (/etc/hosts and the local Network Information Service
-  are ignored). 
-     Workaround: disable the dns cache (use_dns_cache=off or compile without -DUSE_DNS_CACHE).
+  1. Only the locally configured DNS server (usually in /etc/resolv.conf) is
+     used for the requests (/etc/hosts and the local Network Information Service
+     are ignored). 
+     Workaround: disable the DNS cache (use_dns_cache=off or compile without -DUSE_DNS_CACHE).
 
-  2. the DNS cache uses extra memory
+  2. The DNS cache uses extra memory
       Workaround: disable the DNS cache.
 
-  3. the DNS failover introduces a very small performance penalty 
+  3. The DNS failover introduces a very small performance penalty 
      Workaround: disable the DNS failover (use_dns_failover=off).
 
-  4. the DNS failover increases the memory usage (the internal structures
+  4. The DNS failover increases the memory usage (the internal structures
      used to represent the transaction are bigger when the DNS failover support is
      compiled).
      Workaround: compile without DNS failover support (-DUSE_DNS_FAILOVER).
@@ -49,9 +44,9 @@ DNS Cache and Failover Drawbacks
  
  On the other hand using the DNS cache saves lots of DNS queries and makes
  DNS based failover and DNS based load balancing possible. If the destination
- blacklist is enabled, sip-router can do failover even if forwarding in stateless 
+ blacklist is enabled, Kamailio can do failover even if forwarding in stateless 
  mode.
- In the ideal case with the DNS cache enabled sip-router will do only one query for
+ In the ideal case with the DNS cache enabled Kamailio will do only one query for
  a NAPTR (if enabled) or SRV lookup and then it will use the results for the
  record's TTL (for example if all the resulting records have 1 minute TTL,
  the server won't make another query for this domain for 1 minute). Even negative
@@ -64,29 +59,29 @@ DNS Cache and Failover Drawbacks
 DNS Resolver Options
 --------------------
 
- The DNS resolver options control how sip-router will interact with the external
+ The DNS resolver options control how Kamailio will interact with the external
  DNS servers. These options (with the dns_try_ipv6 exception) are passed to
- libresolv and are used each time a dns request is made.
+ libresolv and are used each time a DNS request is made.
 
  The default values are system specific and generally depend on the
  /etc/resolv.conf content. For servers doing a lot of DNS requests it is
- highly recommended to change the default values in the sip-router config file
-  (even if using sip-router's internal dns cache).
+ highly recommended to change the default values in the Kamailio config file
+  (even if using Kamailio's internal DNS cache).
 
-   dns_try_ipv6 = on | off - if on and sip-router listens on at least one ipv6 socket,
+   dns_try_ipv6 = on | off - if on and Kamailio listens on at least one ipv6 socket,
       ipv6 (AAAA) lookups will be performed if the ipv4 (A) lookups fail. 
       If off only ipv4 (A) lookups will be used.
-      Default: on if sip-router is compiled with ipv6 support.
+      Default: on if Kamailio is compiled with ipv6 support.
 
-   dns_try_naptr = on | off - if on sip-router will first try a NAPTR lookup for
+   dns_try_naptr = on | off - if on Kamailio will first try a NAPTR lookup for
       destinations that don't have the protocol or port specified and 
       are not simple ip addresses (as described in RFC 3263). This will 
       introduce a slight performance penalty and will probably cause extra
       DNS lookups. For example a lookup for a non-existing domain will
       produce one extra query: NAPTR(domain), SRV(_sip._udp.domain) 
       and A/AAAA(domain).
-      If the result of a query contains several NAPTR records, sip-router will select
-      among them according to the RFC2915 and sip-router preference towards a
+      If the result of a query contains several NAPTR records, Kamailio will select
+      among them according to the RFC2915 and Kamailio preference towards a
       specific protocol (see dns_udp_pref, dns_tcp_pref and dns_tls_pref 
       below). For an RFC3263 compliant configuration (choose the remote side
       preferred protocol if supported), set dns_udp_pref, dns_tcp_pref and
@@ -96,17 +91,17 @@ DNS Resolver Options
    dns_udp_pref = number - udp protocol preference when doing NAPTR lookups.
       This option works together with dns_tcp_pref, dns_tls_pref and 
       dns_sctp_pref. If all this options have the same positive value and more
-      NAPTR records are available, ser will select the NAPTR record preferred
+      NAPTR records are available, Kamailio will select the NAPTR record preferred
       by the remote side (according to RFC2915). If the values are positive
-      but different, ser will select the NAPTR record whose protocol it
+      but different, Kamailio will select the NAPTR record whose protocol it
       prefers the most (the protocol with the highest dns_<proto>_pref
       number). If there are several NAPTR records with the same preferred
-      protocol, ser will select among them based on their order and preference
+      protocol, Kamailio will select among them based on their order and preference
       (see RFC2915).
       To completely disable selecting a specific protocol, use  a negative
       number. For example dns_tcp_pref=-1 will completely disable selection
       of tcp NAPTR records, even if this will result in the NAPTR lookup
-      failure. Note: if a protocol is disabled in ser (e.g. tls_disable=1)
+      failure. Note: if a protocol is disabled in Kamailio (e.g. tls_disable=1)
       the corresponding NAPTR records selection will be also disabled,
       irrespective of the dns_<proto>_preference value.
       Default: dns_udp_pref=30, dns_tcp_pref=20,  dns_tls_pref=10 and 
@@ -121,14 +116,14 @@ DNS Resolver Options
 
    dns_sctp_pref = number (see dns_udp_pref above)
 
-   dns_retr_time = time - time in s before retrying a dns request.
+   dns_retr_time = time - time in s before retrying a DNS request.
       Default: system specific, depends also on the/etc/resolv.conf content
       (usually 5 s).
 
-   dns_retr_no = no. - number of dns retransmissions before giving up.
+   dns_retr_no = no. - number of DNS retransmissions before giving up.
       Default: see above (usually 4)
 
-   dns_servers_no = no. - how many dns servers from the ones defined in 
+   dns_servers_no = no. - how many DNS servers from the ones defined in 
       /etc/resolv.conf will be used. Default: all of them.
 
    dns_use_search_list= yes/no - if no, the search list in /etc/resolv.conf
@@ -137,7 +132,7 @@ DNS Resolver Options
       HINT: even if you don't have a search list defined, setting this option
       to "no" will still be "faster", because an empty search list is in 
       fact search "" (so even if the search list is empty/missing there will
-      still be 2 dns queries, eg. foo+'.' and foo+""+'.')
+      still be 2 DNS queries, eg. foo+'.' and foo+""+'.')
 
    dns_search_full_match = yes/no - controls the check of the name part
       which is found in the answer expanding the searched name before
@@ -147,11 +142,11 @@ DNS Resolver Options
       If set to no - no additional check is done.
       If set to yes - the additional part is checked against the search list.
 
- The maximum time a dns request can take (before failing) is:
- (dns_retr_time*dns_retr_no)*(search_list_domains) If dns_try_ipv6 is yes,
+ The maximum time a DNS request can take (before failing) is:
+ (dns_retr_time*dns_retr_no) * (search_list_domains) If dns_try_ipv6 is yes,
  mutliply it again by 2.
 
- The option combination that produces the "fastest" dns resolver config
+ The option combination that produces the "fastest" DNS resolver config
   (the "faster" in the sense that it gives up the quickest) is:
 
       dns_try_ipv6=no
@@ -160,19 +155,19 @@ DNS Resolver Options
       dns_servers_no=1
       dns_use_search_list=no
 
- The recommended dns configuration is to have a "close" dns caching recursive
- server configured in /etc/resolv.conf, set the dns resolver options in ser's
- config as in the above example and enable the dns cache (in ser).
+ The recommended DNS configuration is to have a "close" DNS caching recursive
+ server configured in /etc/resolv.conf, set the DNS resolver options in Kamailio's
+ config as in the above example and enable the DNS cache (in Kamailio).
  Pay particular attention to dns_servers_no and dns_use_search_list. It's a
  good idea to make sure you don't need / use the search list or more then one
- dns server (to avoid unnecessary extra lookups).
+ DNS server (to avoid unnecessary extra lookups).
 
 
 DNS Resolver Compile Options
 ----------------------------
 
    USE_NAPTR - if defined the naptr lookup support will be compiled in.
-      NAPTR support still has to be enabled from ser's config file (it's
+      NAPTR support still has to be enabled from Kamailio's config file (it's
       off by default).
 
    RESOLVE_DBG - if defined, the resolver will be very verbose: it will log
@@ -185,8 +180,8 @@ DNS Resolver Compile Options
 DNS Cache and Failover Config Variables
 ---------------------------------------
 
-   use_dns_cache = on | off - if off the dns cache won't be used (all dns
-      lookups will result into a dns request).  When on all the dns request
+   use_dns_cache = on | off - if off the DNS cache won't be used (all dns
+      lookups will result into a DNS request).  When on all the DNS request
       results will be cached.
       WARNING: when enabled /etc/hosts will be completely bypassed, all the dns
       request will go directly to the system configured (resolv.conf) dns
@@ -200,17 +195,17 @@ DNS Cache and Failover Config Variables
       re-tried using the next ip/record. In tm's case a new branch will be
       created for each new send attempt.
       Default: off.
-   Depends on use_dns_cache being on. If tm is used along with dns failover is
+   Depends on use_dns_cache being on. If tm is used along with DNS failover is
    recommended to also turn on dst_blacklist.
 
    dns_srv_lb = on | off or
-   dns_srv_loadbalancing = on | off - if on instead of doing simple dns 
-        failover (like above), ser will load balance requests to different srv
-        records of the same priority based on the srv records weights (like 
+   dns_srv_loadbalancing = on | off - if on instead of doing simple DNS 
+        failover (like above), Kamailio will load balance requests to different srv
+        records of the same priority based on the SRV records weights (like 
         described in RFC2782). For a destination which has different priorities
-        for all its srv records, this option will be equivalent with simple
-        dns failover.
-        Note: this option requires having dns failover enabled (see 
+        for all its SRV records, this option will be equivalent with simple
+        DNS failover.
+        Note: this option requires having DNS failover enabled (see 
         use_dns_failover above).
         Default: off.
 
@@ -229,13 +224,13 @@ DNS Cache and Failover Config Variables
    dns_tls_pref =  number - shared with the resolver (see resolver 
         description).
 
-   dns_cache_flags = dns cache specific resolver flags, used for overriding
+   dns_cache_flags = DNS cache specific resolver flags, used for overriding
      the default behaviour (low level).
       Possible values:
-         1 - ipv4 only: only DNS A requests are performed, even if ser listens
+         1 - ipv4 only: only DNS A requests are performed, even if Kamailio listens
                         also on ipv6 addresses.
          2 - ipv6 only: only DNS AAAA requests are performed. Ignored if
-                        dns_try_ipv6 is off or ser doesn't listen on any ipv6
+                        dns_try_ipv6 is off or Kamailio doesn't listen on any ipv6
                         address.
          4 - prefer ipv6: try first to resolve a host name to an ipv6 address
                           (DNS AAAA request) and only if this fails try an ipv4
@@ -257,10 +252,10 @@ DNS Cache and Failover Config Variables
       dns_cache_max_ttl will be used instead.
       Default: MAXINT
 
-   dns_cache_mem = maximum memory used for the dns cache in Kb.
+   dns_cache_mem = maximum memory used for the DNS cache in Kb.
       Default: 500 Kb
 
-   dns_cache_gc_interval = how often (in s) the dns cache will be garbage 
+   dns_cache_gc_interval = how often (in s) the DNS cache will be garbage 
       collected.
       Default:  120 s.
       
@@ -270,37 +265,37 @@ DNS Cache and Failover Config Variables
       ones. The last-recently used entries are deleted first.
       Default: no
 
-   dns_cache_init = on | off - if off, the dns cache is not initialized
+   dns_cache_init = on | off - if off, the DNS cache is not initialized
       at startup and cannot be enabled runtime, that saves some memory.
       Default: on
 
 DNS Cache Compile Options
 -------------------------
 
-   USE_DNS_CACHE - if defined the dns cache support will be compiled in 
+   USE_DNS_CACHE - if defined the DNS cache support will be compiled in 
       (default). If not needed/wanted the dns_cache can be disabled from the
-      ser's config file. The only advantages for not compiling the dns cache
+      Kamailio's config file. The only advantages for not compiling the DNS cache
       support is a slight decrease of the executable size and an extremely 
-      small performance increase (1 less comparison per dns request).
+      small performance increase (1 less comparison per DNS request).
 
-   USE_DNS_FAILOVER - if defined the dns failover support will be compiled in.
-      (default). Compiling the dns failover support has a few disadvantages,
+   USE_DNS_FAILOVER - if defined the DNS failover support will be compiled in.
+      (default). Compiling the DNS failover support has a few disadvantages,
       see the "Drawbacks" section.
 
    DNS_SRV_LB  - if defined (default) support for load balancing using 
-       srv records weights (as described in RFC2782) will be compiled in.
-       Note however that it still must be enabled from the ser config, it's
+       SRV records weights (as described in RFC2782) will be compiled in.
+       Note however that it still must be enabled from the Kamailio config, it's
        disabled by default (see the dns_srv_lb config option).
 
    USE_NAPTR  - (shared with the resolver)  if defined NAPTR support will
        be compiled in (default). Note that even if compiled, NAPTR support
-       must be enabled also from the ser config (see the dns_try_naptr option).
+       must be enabled also from the Kamailio config (see the dns_try_naptr option).
 
    NAPTR_CACHE_ALL_ARS - if defined all the additional records in a NAPTR
-       answer will be cached. Normally ser would cache only "related" records
+       answer will be cached. Normally Kamailio would cache only "related" records
        (records that are directly referred), but for answers with lots of 
         A/AAAA records it might happen that not all of the SRV records will fit
-       in the AR section. In this case, without this compile option ser will 
+       in the AR section. In this case, without this compile option Kamailio will 
        not cache the un-referred A/AAAA records. BY default this option is
        disabled.
 
@@ -312,10 +307,10 @@ DNS Cache Compile Options
        If this option is not defined (experimental), everything in the AR
        section will be added to the cache.
 
-   DNS_CACHE_DEBUG - if defined the dns cache will be very verbose (it will
+   DNS_CACHE_DEBUG - if defined the DNS cache will be very verbose (it will
        log lots of messages at the L_DBG levell).
  
- Note: To remove a compile options,  edit sip-router's Makefile.defs and remove it 
+ Note: To remove a compile options,  edit Kamailio's Makefile.defs and remove it 
    from DEFS list. To add a compile options add it to the make command line,
      e.g.: make proper; make all extra_defs=-DUSE_DNS_FAILOVER
    or for a permanent solution, edit Makefile.defs and add it to DEFS 
diff --git a/doc/doxygen/main.dox b/doc/doxygen/main.dox
index 26807eb..5bf7286 100644
--- a/doc/doxygen/main.dox
+++ b/doc/doxygen/main.dox
@@ -1,5 +1,5 @@
 /**
- * \mainpage The SIP Router Development Documentation
+ * \mainpage The Kamailio Development Documentation
  *
  * This development documentation contains annotated and documented
  * source files. For the sake of clarity the documentation is split into the
@@ -10,18 +10,21 @@
  * \ref db_api Database Abstraction Layer is a group of data structures and functions that
  * are used by all SIP Router modules that need to access a database.
  *
- * \section sr_modules SIP Router Modules
+ * \section sr_modules Kamailio Modules
  * Please click on the "modules" tab above for more information about the modules
  *
  * The documentation can be generated using doxygen by running "make doxygen"
  *
- * \section License SIP-router license
- * SIP-router is free software; you can redistribute it and/or modify
+ * \section Other information
+ * If you want other informaiton about Kamailio, please visit http://www.kamailio.org
+ *
+ * \section License Kamailio license
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/doc/dst_blacklist.txt b/doc/dst_blacklist.txt
index 219016c..8782978 100644
--- a/doc/dst_blacklist.txt
+++ b/doc/dst_blacklist.txt
@@ -1,10 +1,3 @@
-# $Id$
-#
-# History:
-# --------
-# 2006-09-08  created by andrei
-#
-
 Destination blacklist Overview
 ------------------------------
 
diff --git a/doc/locking.txt b/doc/locking.txt
index 277c58c..7507a5d 100644
--- a/doc/locking.txt
+++ b/doc/locking.txt
@@ -1,19 +1,12 @@
-# $Id$
-#
-# History:
-#---------
-#  2003-03-11  created by andrei
-#  2006-04-04  minor archs updates, added lock_try(..)  (andrei)
 
-
-SIP-router locking interface
+Kamailio locking interface
 ============================
 
 1. Why use it?
 --------------
 
 The main reason for creating it was to have a single transparent interface to various locking methods. 
-For example right now SIP-router uses the following locking methods, depending on their availability on the 
+For example right now Kamailio uses the following locking methods, depending on their availability on the 
 target system:
 	FAST_LOCK - fast inline assembly locks, defined in fast_lock.h. They are currently available for 
 	x86, x86_64, sparc, sparc64, arm , armv6 (no smp mode supported yet), ppc, ppc64, mips, mips64 
@@ -39,7 +32,7 @@ target system:
 -----------------
 
 First of all you have to include locking.h. Then when compiling the code one or all of FAST_LOCK, 
-USE_PTHREAD_MUTEX, USE_PTHREAD_SEM or USE_SYSV_SEM must be defined (the SIP-router Makefile.defs takes 
+USE_PTHREAD_MUTEX, USE_PTHREAD_SEM or USE_SYSV_SEM must be defined (the Kamailio Makefile.defs takes 
 care of this, you should need to change it only for new arhitectures or compilers).
 
 locking.h defines 2 new types: gen_lock_t and lock_set_t.
diff --git a/doc/logging-api.txt b/doc/logging-api.txt
index c8573e8..cfdfbbb 100644
--- a/doc/logging-api.txt
+++ b/doc/logging-api.txt
@@ -7,7 +7,7 @@
                          Ondrej Martinek <ondra at iptel.org>
                                               January 2009
 
-This document contains the short description of the logging API in SIP-router
+This document contains the short description of the logging API in Kamailio
 for developers.
 
 Source files:
@@ -121,7 +121,7 @@ Source files:
 !!! IMPORTANT! READ ME!
 !!!
 !!!  These changes (mainly the first two) require reformating of the most log
-!!!  messages in SIP-router core and module source files.  This step can be done
+!!!  messages in Kamailio core and module source files.  This step can be done
 !!!  automatically by running "scripts/logging/fix-logs-all" script BUT it
 !!!  was NOT originally performed because it would have generated too many
 !!!  changes in CVS which was discouraged by Andrei.  Instead, the developers
@@ -130,5 +130,3 @@ Source files:
 !!! IMPORTANT! READ ME!
 !!!  
 
---
-$Id$
diff --git a/doc/management_api.txt b/doc/management_api.txt
index 86d6872..3cc8418 100644
--- a/doc/management_api.txt
+++ b/doc/management_api.txt
@@ -1,7 +1,7 @@
-Management API's in SIP-router
+Management API's in Kamailio
 ------------------------------
 
-SIP-router has an API based on RPC. This allows modules and core to expose commands that can be 
+Kamailio has an API based on RPC. This allows modules and core to expose commands that can be 
 issued by external applications. Commands can change states, read status variables or expose
 internal structures.
 
@@ -14,7 +14,7 @@ you can adapt the interface to one of several protocols supported:
 
 The MI interfaces can often run over Unix fifo sockets, UDP or TCP connections.
 
-The "sercmd" application is the command line tool used to connect to SIP-router
+The "kamcmd" application is the command line tool used to connect to Kamailio
 over the command line. Use it to discover available commands.
 
 For backwards compatibilty, the kamctrl and kamdbctrl commands are still supported.
@@ -25,7 +25,7 @@ web site in the wiki section.
 Modules
 -------
 
-mi_rpc		Exports Kamailio's MI interface over SIP-router's RPC interface
+mi_rpc		Exports Kamailio's MI interface over Kamailio's RPC interface
 xmlrpc		Exports the RPC interface using XML-rpc
 ctl		Implements the binrpc transport interface for SER rpcs
 		Also implements the old SER fifo-based management interface.
diff --git a/doc/modules_init.txt b/doc/modules_init.txt
index 30d404b..936c4cb 100644
--- a/doc/modules_init.txt
+++ b/doc/modules_init.txt
@@ -1,12 +1,5 @@
-#$Id$
-#
-#
-# History
-#--------
-#  2007-06-07  created by Andrei Pelinescu <andrei at iptel.org>
-#
-
-SIP-router Module intialization description
+
+Kamailio Module intialization description
 ===========================================
 
 This document is a very brief overview on what possibilities are for a module
@@ -24,21 +17,21 @@ mod_init is called after parsing the config, loading all the modules and
 going into daemon mode. mod_init is called in the main process context,
 before changing the uid or gid (so if you want to do something requiring
 higher privileges this is the place to do it). This is not the right place
-to fork more SIP-router processes, but instead is the only place where one can 
+to fork more Kamailio processes, but instead is the only place where one can 
 register future forked processes (see register_procs()).
 
 mod_init is ideal for initializing per process variables, assuming that you
-don't need different values for each SIP-router child (in which case see 
+don't need different values for each Kamailio child (in which case see 
 mod_child_init below) and shared memory variables assuming that you don't 
-need SIP-router's number of processes (which is not available at this point).
+need Kamailio's number of processes (which is not available at this point).
 
 
 mod_child_init
 ---------------
 
-mod_child_init is called for each forked SIP-router process with 2 exceptions:
+mod_child_init is called for each forked Kamailio process with 2 exceptions:
  - it's called for the main process too and it's called twice
- - it's not called for SIP-router processes forked with PROC_NOCHLDINIT
+ - it's not called for Kamailio processes forked with PROC_NOCHLDINIT
 
 mod_child_init is always called after mod_init. It takes one parameter, the
  process rank. This parameter can be used to differentiate between normal
@@ -48,7 +41,7 @@ There are two very special rank values: PROC_INIT (as of 2007-06-06) and
 mod_child_init(PROC_INIT) is the first mod_child_init call made, and it's
  guaranteed to happen before any child process is forked. The process context
   is the "main" process (as for mod_init), but this time we have a little bit
- more information: we know the number of SIP-router processes. This is the right
+ more information: we know the number of Kamailio processes. This is the right
   place to initialize things like shared arrays[get_max_procs()].
 Note also that everything done here will be inherited in all the future
  children processes (since it's executed in the "main" process context before
@@ -56,14 +49,14 @@ Note also that everything done here will be inherited in all the future
 
 mod_child_init(PROC_MAIN) is another call that is done in the same "main"
  process context. This call happens just before initializing the main tcp
-  process. This is the only right place for forking more SIP-router processes
+  process. This is the only right place for forking more Kamailio processes
   (see fork_process()). WARNING: the context is the same "main" process as
  for mod_child_init(PROC_INIT) and mod_init() so care must be taken not to
  initialize things twice or three times for the "main" process.
 
 Except for the "main" process case mod_child_init(rank) will be called only
 once for each new child process, just after forking. A positive non-zero rank
- means the current process is a normal SIP-router process and a negative rank has
+ means the current process is a normal Kamailio process and a negative rank has
   some special meaning (grep PROC_ sr_module.h for more info).
 mod_child_init(rank) is the best place for initializing per process variables,
  opening per process database connections, new sockets a.s.o. Note however
@@ -76,7 +69,7 @@ mod_child_init(rank) is the best place for initializing per process variables,
 mod_child_init in the no-fork case
 ----------------------------------
 
-If SIP-router is started in no-fork mode it will try to start as few processes as
+If Kamailio is started in no-fork mode it will try to start as few processes as
 possible (as of this date it will start 3 processes the main process and the
 2 timers). In this case mod_child_init() will be called 3 times in the
 same "main" process context: mod_child_init(PROC_INIT);
@@ -84,7 +77,7 @@ mod_child_init(PROC_MAIN) and mod_child_init(1) (since the first process is
 also the "main" one).
 
 
-Forking new SIP-router processes from a module
+Forking new Kamailio processes from a module
 ---------------------------------------
 
 static int mod_init()
@@ -140,7 +133,7 @@ mod_child_init(PROC_INIT)
   process.
 
 mod_child_init(PROC_MAIN)
- - the only place from where another SIP-router process can be forked 
+ - the only place from where another Kamailio process can be forked 
    (see fork_process  ()), but remember first to register the number of 
    to-be-forked processes in mod_init()
 
diff --git a/doc/parse_headers.txt b/doc/parse_headers.txt
index f82060e..c06c527 100644
--- a/doc/parse_headers.txt
+++ b/doc/parse_headers.txt
@@ -1,5 +1,3 @@
-# $Id$
-#
 # parse headers api changes
 #
 # 2004.02.23  created (andrei)
diff --git a/doc/rpc/Makefile b/doc/rpc/Makefile
index 0c39088..6dbb8f9 100644
--- a/doc/rpc/Makefile
+++ b/doc/rpc/Makefile
@@ -1,4 +1,4 @@
-docs = ser_rpc.xml
+docs = kamailio_rpc.xml
 docbook_dir = ../../docbook
 
 include $(docbook_dir)/Makefile
diff --git a/doc/rpc/kamailio_rpc.txt b/doc/rpc/kamailio_rpc.txt
new file mode 100644
index 0000000..a9b2aec
--- /dev/null
+++ b/doc/rpc/kamailio_rpc.txt
@@ -0,0 +1,626 @@
+1. The Kamailio RPC Control Interface
+     __________________________________________________________________
+
+   1.1. Overview of Operation
+   1.2. Module API
+
+        1.2.1. RPC Functions
+        1.2.2. Data Types
+        1.2.3. Getting Parameters
+
+              1.2.3.1. scan
+              1.2.3.2. struct_scan
+              1.2.3.3. Retrieving Parameters Example
+
+        1.2.4. Building Reply
+
+              1.2.4.1. fault
+              1.2.4.2. send
+              1.2.4.3. add
+              1.2.4.4. rpl_printf
+              1.2.4.5. struct_add
+
+        1.2.5. Real World Example
+
+   1.3. Client Examples
+   1.4. Implementing New Transports
+   1.5. Examples using xmlrpc
+
+1.1. Overview of Operation
+
+   The RPC (Remote Procedure Call) interface is an interface for
+   communicating with external applications. Using it an external
+   application can call a function or procedure that will be executed
+   inside Kamailio. Function parameters are supported as well as returning
+   multiple values as results.
+
+   By itself RPC consists of two APIs, one for defining RPC functions in a
+   transport independent way (called the rpc module api) and one for
+   implementing RPC transports.
+
+   The RPC transports are implemented by writting a RPC transport module.
+   The most used transport modules are ctl , xmlrpc and jsonrpc-s .
+
+   ctl implements a proprietary fast and space efficient RPC encoding over
+   different protocols (unix sockets, UDP, TCP, fifo).
+
+   xmlrpc uses the de-facto XML-RPC standard encoding (over HTTP TCP or
+   TLS).
+
+   jsonrpc-s uses the de-facto JSON-RPC standard encoding (over HTTP TCP
+   or TLS).
+
+   For more information about the existing transport modules, please refer
+   to their documentation.
+
+   When writing a RPC procedure or function, one needs only use the RPC
+   API and it will work automatically with all the transports and
+   encodings. One needs only to load the desired RPC transport module
+   (e.g. xmlrpc).
+
+   The RPC interface (or API) was created in such a way that would allow
+   supporting XML-RPC (because XML-RPC is a de-facto standard), while in
+   the same time being very easy to use.
+
+1.2. Module API
+
+   Each module can export RPC functions just like it can export parameters
+   and functions to be called from the script. Whenever Kamailio receives
+   an RPC request, it will search through the list of exported RPC
+   functions and the function with matching name will be executed. A
+   couple of essential RPC functions are also embedded into the SIP server
+   core.
+
+   This section gives a detailed overview of the whole RPC API.
+   Section 1.2.1, "RPC Functions" describes the prototype and conventions
+   used in RPC functions. Section 1.2.2, "Data Types" gives a detailed
+   overview of available data types that can be used in function
+   parameters and return value. Section 1.2.3, "Getting Parameters"
+   describes functions of the RPC API that can be used to retrieve
+   parameters of the function, and finally Section 1.2.4, "Building Reply"
+   describes functions of the API that can be used to build the result
+   value that will be sent in the reply to the caller.
+
+   The whole RPC API is described in header file kamailio/rpc.h. This file
+   defines the set of functions that must be implemented by RPC transport
+   modules, as described in Section 1.4, "Implementing New Transports",
+   prototypes of RPC functions and structures used for the communication
+   between RPC transport modules and ordinary modules exporting RPC
+   functions.
+
+1.2.1. RPC Functions
+
+   RPC functions are standard C functions with the following prototype:
+typedef void (*rpc_function_t)(rpc_t* rpc, void* ctx);
+
+   RPC functions take two parameters, first parameter is a pointer to
+   rpc_t structure and the context. The rpc_t structure contains
+   references to all API functions available to the RPC function as well
+   as all data necessary to create the response. RPC functions do not
+   return any value, instead the return value is created using functions
+   from the context. The motivation for this decision is the fact that RPC
+   functions should always return a response and even the API functions
+   called from RPC functions should have the possibility to indicate an
+   error (and should not rely on RPC functions doing so).
+
+   If no reply is sent explicitely, the RPC transport module will
+   automatically send a "success" reply (e.g. 200 OK for XML-RPC) when the
+   RPC function finishes. If no values are added to the response, the
+   reponse will be an empty "success" reply (e.g. a 200 OK with empty body
+   for XML-RPC). RPC API functions will automatically send an error reply
+   upon a failure.
+
+   Each RPC function has associated an array of documentation strings. The
+   purpose of the documentation strings is to give a short overview of the
+   function, accepted parameters, and format of the reply. By convention
+   the name of the documentation string array is same as the name of the
+   function with "_doc" suffix.
+
+   Each module containing RPC functions has to export all the RPC
+   functions to the Kamailio core in order to make them visible to the RPC
+   transport modules. The export process involves a rpc_export_t structure
+   (either by itself or in an array):
+typedef struct rpc_export {
+    const char* name;        /* Name of the RPC function (null terminated) */
+    rpc_function_t function; /* Pointer to the function */
+    const char** doc_str;    /* Documentation strings, method signature and desc
+ription */
+    unsigned int flags;      /* Various flags, reserved for future use */
+} rpc_export_t;
+
+   The flags attribute of the rpc_export structure is reserved for future
+   use and is currently unused.
+
+   There are several ways of exporting the RPC functions to the Kamailio
+   core:
+     * register a null terminated array of rpc_export_t structures using
+       the rpc_register_array() function (defined in rpc_lookup.h), from
+       the module init function (mod_init()). This is the recommended
+       method for all the new modules.
+       Example 1. usrloc RPC Exports Declaration
+       The rpc_export_t array for the modules_s/usrloc module looks like:
+rpc_export_t ul_rpc[] = {
+    {"usrloc.statistics",      rpc_stats,           rpc_stats_doc,          0},
+    {"usrloc.delete_aor",      rpc_delete_aor,      rpc_delete_aor_doc,     0},
+    {"usrloc.delete_contact",  rpc_delete_contact,  rpc_delete_contact_doc, 0},
+    {"usrloc.dump",            rpc_dump,            rpc_dump_doc,           0},
+    {"usrloc.flush",           rpc_flush,           rpc_flush_doc,          0},
+    {"usrloc.add_contact",     rpc_add_contact,     rpc_add_contact_doc,    0},
+    {"usrloc.show_contacts",   rpc_show_contacts,   rpc_show_contacts_doc,  0},
+    {0, 0, 0, 0}
+};
+
+       To register it from the module init function one would use
+       something similar to:
+        if (rpc_register_array(ul_rpc) != 0) {
+                ERR("failed to register RPC commands\n");
+                return -1;
+        }
+     * register RPCs one by one using the rpc_register_function() (defined
+       in rpc_lookup.h), from the module init function.
+     * register a null terminated array of rpc_export_t structures using
+       the Kamailio module interface SER_MOD_INTERFACE For this purpose,
+       the module_exports structure of the Kamailio module API contains a
+       new attribute called rpc_methods:
+struct module_exports {
+    char* name;                 /* null terminated module name */
+    cmd_export_t* cmds;         /* null terminated array of the exported command
+s */
+    rpc_export_t* rpc_methods;  /* null terminated array of exported rpc methods
+ */
+    param_export_t* params;     /* null terminated array of the exported module
+parameters */
+
+    init_function init_f;         /* Initialization function */
+    response_function response_f; /* function used for responses */
+    destroy_function destroy_f;   /* function called upon shutdown */
+    onbreak_function onbreak_f;
+    child_init_function init_child_f;  /* function called by all processes after
+ the fork */
+};
+       rpc_methods is a pointer to an array of rpc_export_t structures.
+       The last element of the array is a bumper containing zeroes in all
+       the attributes of the structure. The following program listing
+       shows the exported RPC functions of the modules_s/usrloc module,
+       using the rpc_export_t array ul_rpc defined above, in the
+       rpc_register_array() example:
+       Example 2. usrloc Module Exports Declaration
+struct module_exports exports = {
+    "usrloc",
+    cmds,      /* Exported functions */
+    ul_rpc,    /* RPC methods */
+    params,    /* Export parameters */
+    mod_init,  /* Module initialization function */
+    0,         /* Response function */
+    destroy,   /* Destroy function */
+    0,         /* OnCancel function */
+    child_init /* Child initialization function */ };
+
+Note
+       This mode works only with modules using the SER flavour module
+       interface. It does not work for Kamailio modules and it will
+       probably not work for future sip-router modules. It is safer and
+       recommended to use instead the rpc_register_array() function.
+
+   By convention the name of every exported function consists of two parts
+   delimited by a dot. The first part is the name of the module or
+   Kamailio subsystem this function belongs to. The second part is the
+   name of the function.
+
+1.2.2. Data Types
+
+   The RPC API defines several basic and one compound data type that can
+   be used in communication with the caller of RPC functions. The RPC API
+   uses formating strings to describe data types. Each data type is
+   described by exactly one character in the formating string. For
+   example, if an RPC function calls function add of the RPC API and it
+   passes two parameters to it, the first one of type string and the
+   second one of type integer, the function parameters will look like:
+add("sd", string_param, int_param);
+
+   Character "s" in the formating string tells to the function that the
+   2nd parameter should be interpreted as string, character "d" in the
+   formating string tells to the function that the 3rd parameter should be
+   interpreted as signed integer.
+
+   Integer.  Integer type represents a signed 32-bit integer.
+   Corresponding character in the formating string is "d". This parameter
+   can be stored in C-style variable with type int.
+
+   Float.  Float type represents a signed floating point number.
+   Corresponding character in the formating string is "f". Data of this
+   type can be stored in C-style variables of type double.
+
+   String.  String type represents a string of characters. The string may
+   contain zeroes. This data type is represented by two characters in the
+   formatting string, either "s" or "S". "s" indicates to the conversion
+   function that the result should be stored in a variable of type char*
+   and it should be zero terminated. "S" indicates to the conversion
+   function that the result will be stored in a variable of type str which
+   contains both the pointer to the beginning of the string and its
+   length.
+
+   Structure.  Structure is the only compound data type currently defined
+   in the API. A structure is a collection of attributes. Each attribute
+   is identified using name (string) and each attribute can be one of the
+   basic data types, that is integer, float, or string. Nesting of
+   structures is not allowed (in other words, structure attributes cannot
+   be of type struct again). Corresponding character in the formatting
+   string is "{".
+
+   Optional parameters.  Optional parameters can be used, but only in the
+   scan function. For optional parameters the scan function will not
+   automatically generate a rpc fault if the input ends. Note that in this
+   case the scan will still return a negative value (minus the number of
+   parameters successfully read). Optional parameters can be marked in the
+   format string by preceding the first optional parameter type with a
+   "*". All the parameters following a "*" are considered to be optional.
+   For example for the format string "ds*dds", the last 3 parameters (2
+   ints and a string) are optional.
+
+   Table 1. Data Type Overview
+   Name Formating String Char C-Style Variable
+   Integer d int
+   Float f double
+   String s char*
+   String S str*
+   Optional modifier * marks all further parameters as optional
+   Autoconvert modifier . requires auto-conversion for the next parameter
+
+1.2.3. Getting Parameters
+
+   Each RPC function call can contain parameters. Parameters have no name,
+   their meaning is determined by their position in the parameter set.
+
+Note
+
+   You can pass all parameters to a function within a structure if you
+   want to make them position independent. Then each parameter can be
+   retrieved by its name regardless of its position.
+
+   There are two functions in the RPC API that can be used to obtain
+   function call parameters: scan and struct_scan.
+
+1.2.3.1. scan
+
+   Function scan can be used to retrieve parameters from the parameter
+   set. The function accepts variable number of parameters. The first
+   parameter is the formatting string that determines the type of the
+   parameters to be retrieved. Each parameter is represented by exactly
+   one parameter type character in the string. The variable part of
+   parameters must contain as many pointers to C variables as there are
+   formatting non-modifiers characters in the formatting string.
+
+Warning
+
+   The function will crash if you fail to provide enough parameters.
+
+   Besides characters representing parameter types, the formatting string
+   can contain two special modifiers: "*" and ".". The modifiers do not
+   have a correspondent in the variable part of the parameters.
+
+   The meaning of "*" modifier is that any further parameters (defined by
+   other type characters in the formatting string) are optional (they can
+   be missing in the input and no rpc fault will automatically be
+   generated).
+
+   The '.' modifiers turns on type autoconversion for the next parameter.
+   This means that if the type of the next parameter differs from the type
+   specified in the formatting string, the parameter will be automatically
+   converted to the formatting string type (if possible) and if the
+   automatic conversion succeeds, no fault will be generated.
+
+   The function returns the number of parameters read on success (a number
+   greater or equal 0) and - (minus) the number of parameters read on
+   error (for example for an error after reading 2 parameters it will
+   return -2). When a failure occurs (incorrect parameter type or no more
+   parameters in the parameter set) the function will return a negative
+   number (- number of parameters read so far) and it will also
+   automatically change the reply that will be sent to the caller to
+   indicate that a failure has occurred on the server (unless the "*" is
+   used and the error is lack of more parameters).
+
+   The prototype of the function is:
+int scan((void* ctx, char* fmt, ...)
+
+   It is possible to either call the function once to scan all the
+   parameters:
+rpc->scan(ctx, "sdf", &string_val, &int_val, &double_val);
+
+   Or you can call the same function several times and it will continue
+   where it left off previously:
+rpc->scan(ctx, "s", &string_val);
+rpc->scan(ctx, "d", &int_val);
+rpc->scan(ctx, "f", &double_val);
+
+1.2.3.2. struct_scan
+
+   Function struct_scan can be used to retrieve named attributes from a
+   parameter of type structure.
+
+Note
+
+   This function is obsolete and not implemented by all the rpc transports
+   (e.g.: ctl / binrpc). Consider using the normal scan instead.
+
+   When retrieving a structure parameter from the parameter set:
+rpc->scan(ctx, "{", &handle);
+
+   The corresponding variable (named handle in the example above) will
+   contain the index of the structure parameter within the parameter set,
+   but the index cannot be used to retrieve the contents of the structure.
+   To retrieve the contents of the structure you can use function
+   struct_scan. The function gets the handle as the first parameter:
+rpc->struct_scan(handle, "sd", "str_attr", &str_val, "int_attr", &int_val);
+
+   The second parameter is the formatting string followed by pairs of
+   parameters. First parameter in each pair is the name of the attribute
+   to retrieve (string) and the second parameter in each pair is the
+   pointer to the variable to store the value of the parameter. The
+   function returns the number of parameters (name value pairs) read on
+   success and - number of parameters read so far on an error (just like
+   the scan function). The function also indicates an error if a requested
+   attribute is missing in the structure.
+
+1.2.3.3. Retrieving Parameters Example
+
+   Example 3. Retrieving Parameters
+static void rpc_delete_contact(rpc_t* rpc, void* ctx)
+{
+    str aor, contact;
+    char* table;
+    void *handle;
+    int   expires;
+    double q;
+
+    if (rpc->scan(ctx, "sS{", &table, &aor, &handle) < 0) {
+        /* Reply is set automatically by scan upon failure,
+         * no need to do anything here
+         */
+        return;
+    }
+
+    if (rpc->struct_scan(handle, "Sdf", "Contact", &contact,
+                                        "Expires", &expires,
+                                        "Q",       &q        ) < 0) {
+        /* Reply is set automatically by struct_scan upon failure,
+         * no need to do anything here
+         */
+        return;
+    }
+
+    /* Process retrieved parameters here */
+}
+
+/* variable number of parameters:
+   echo back all the parameters, string type required */
+static void core_prints(rpc_t* rpc, void* c)
+{
+        char* string = 0;
+        while((rpc->scan(c, "*s", &string)>0))
+                rpc->add(c, "s", string);
+}
+
+/* variable number of parameters and auto conversion:
+   echo back all the parameters, works with any type (everything is
+   internally converted to string, notice the '.' modifier) */
+static void core_echo(rpc_t* rpc, void* c)
+{
+        char* string = 0;
+        while((rpc->scan(c, "*.s", &string)>0))
+                rpc->add(c, "s", string);
+}
+
+1.2.4. Building Reply
+
+   The RPC API contains several functions that can be used to modify
+   and/or send a reply. The functions use formatting strings and parameter
+   lists just like functions described in Section 1.2.3, "Getting
+   Parameters".
+
+   Each RPC function call must return a reply. The reply can be either a
+   failure reply or success reply. Failure replies contain only the status
+   code and reason phrase. Success replies can have arbitrary amount of
+   data attached to them. Status codes 3xx, 4xx, 5xx, and 6xx indicate
+   failures. Status code 2xx indicates success.
+
+   The default reply is 200 OK with no data attached to it. This is what
+   will be returned by the RPC transport module if you do not call any of
+   the reply-related functions described in this section.
+
+   Example 4. Sending default reply
+static void rpc_dummy(rpc_t* rpc, void *ctx)
+{
+  /* 200 OK with no data will be returned */
+}
+
+1.2.4.1. fault
+
+   You can use fault function to indicate that an error has occurred on
+   the server to the caller. The function accepts two parameters. The
+   first parameter is the status code and the second parameter is the
+   reason phrase.
+static void rpc_my_function(rpc_t* rpc, void *ctx)
+{
+    rpc->fault(ctx, 600, "Not Yet Implemented");
+}
+
+   If your function first creates some result using add, or printf
+   functions then all the data will be lost once you call fault function.
+   Failure replies must not contain any data:
+static void rpc_my_function(rpc_t* rpc, void *ctx)
+{
+    rpc->add(ctx, "s", "result1");
+    rpc->add(ctx, "d", variable);
+
+    /* Reply created by previous functions will be
+     * deleted and a failure reply 600 Not Yet Implemented
+     * will be created instead
+     */
+    rpc->fault(ctx, 600, "Not Yet Implemented");
+
+    /* You can also add data here, but that will have no
+     * effect
+     */
+    rpc->add(ctx, "s", "result2");
+}
+
+   Similarly you can also call add or printf functions after calling
+   fault, in this case they will have no effect:
+static void rpc_my_function(rpc_t* rpc, void *ctx)
+{
+    rpc->fault(ctx, 600, "Not Yet Implemented");
+
+    /* You can also add data here, but that will have no
+     * effect and only 600 Not Yet Implemented will be returned
+     */
+    rpc->add(ctx, "s", "result2");
+}
+
+1.2.4.2. send
+
+   RPC functions can use function send to explicitly send the reply. Each
+   RPC function call generates exactly one reply. No reply will be sent
+   after the function finishes if it already sent the reply using send
+   function explicitly. This function is especially useful if the RPC
+   function needs to perform some (potentially destructive) actions after
+   the reply has been sent.
+
+   Example 5. Kill the server
+static void core_kill(rpc_t* rpc, void *ctx)
+{
+    int sig_no;
+
+    if (rpc->scan(ctx, "d", &sig_no) < 0) return;
+    rpc->send(ctx, );     /* First send a reply */
+    kill(0, sig_no); /* Then kill the server */
+}
+
+1.2.4.3. add
+
+   Function add can be used to add arbitrary data to the result set. Its
+   parameters and use are analogical to scan function described in
+   Section 1.2.3.1, "scan". The first parameter of the function is the
+   formatting string that determines the types of additional parameters:
+static void rpc_func(rpc_t* rpc, void *ctx)
+{
+    str str_result;
+    int int_result;
+    void *handle;
+    double float_result;
+
+    if (rpc->add(ctx, "Sdf{", &str_result, int_result, float_result, &handle) <
+0) return;
+}
+
+   Naturally you can call this function several times, adding only one
+   piece of data at a time. The function returns 0 on success and -1 on an
+   error. In case of an error the reply is set automatically with
+   corresponding error code and reason phrase.
+
+   The last character in the formatting string of the function above
+   indicates that the last data to be added will be a structure. This
+   deserves some clarification. In this case, the function will create an
+   empty structure and the handle to the newly created structure will be
+   stored in handle variable (hence the last parameter is pointer to an
+   integer). In this particular example parameters str_result, int_result,
+   and float_result will be used for reading while parameter handle will
+   be used for writing by the function.
+
+   You can set the attributes of the newly created structure using
+   struct_add function described in Section 1.2.4.5, "struct_add".
+
+1.2.4.4. rpl_printf
+
+   rpl_printf is a convenience function. The function adds data of type
+   string to the result set. The first parameter of the function is again
+   a formatting string, but this time it is standard printf-like
+   formatting string:
+if (rpc->rpl_printf(ctx, "Unable to delete %d entries from table %s", num_entrie
+s, table_name) < 0) return;
+
+   The return value of the function is the same as of add function.
+
+1.2.4.5. struct_add
+
+   Function struct_add can be used to add attributes to a structure
+   (created previously by add function). The first parameter of the
+   function is handle obtained through add function, the second parameters
+   is formatting string that determines the types of attributes to be
+   added. There must be two parameters per each character in the
+   formatting string, the first one is the name of the attribute, the
+   second parameter is the value of the attribute. If a parameter with
+   such a name already exist in the structure then it will be overwritten
+   with the new value.
+static void rpc_func(rpc_t* rpc, void *ctx)
+{
+    void *handle;
+
+        /* Create empty structure and obtain its handle */
+    if (rpc->add(ctx, "{", &handle) < 0) return;
+        /* Fill-in the structure */
+    if (rpc->struct_add(handle, "sd", "attr1", str_val,
+                                      "attr2", int_val ) < 0)
+        return;
+}
+
+   The function returns -1 on an error (and sets the status code and
+   reason phrase of the reply accordingly) and 0 on success.
+
+1.2.5. Real World Example
+
+   The following example illustrates the use of most of the functions from
+   the API together:
+
+   Example 6. Real World Example RPC Function
+static void rpc_register(rpc_t* rpc, void *ctx)
+{
+    char* domain;
+    str aor;
+    contact_t contact, new_contact;
+    void *handle;
+
+        /* Extract the domain, address of record from the request */
+    if (rpc->scan(ctx, "sS{", &domain, &aor, &handle) < 0) return;
+        /* Extract the structure describing the contact to be processed */
+    if (rpc->struct_scan(handle, "Sdf", "Contact", &contact.c,
+                                        "Expires", &contact.expires,
+                                        "Q",       &contact.q       ) < 0)
+        return;
+
+        /* Process the contact, new_contact will contain updated value after pro
+cessing */
+    if (process_contact(domain, &aor, &new_contact, &contact) < 0) {
+           /* Processing failed, indicate the failure to the caller */
+        rpc->fault(ctx, 500, "Error While Processing Contact");
+        return;
+    }
+
+        /* Return the domain and the address of record */
+    rpc->add(ctx, "sS{", &domain, &aor, &handle) < 0) return;
+        /* And also add the new values for contact, q, and expires parameters */
+    rpc->struct_add(handle, "Sdf", "Contact", &new_contact.c,
+                                   "Expires", &new_contact.expires,
+                                   "Q",       &new_contact.q       );
+}
+
+1.3. Client Examples
+
+     * sercmd (C application that uses the binrpc interface implemented by
+       the ctl module).
+     * ser_ctl (python application that uses the XML-RPC interface
+       implemented by the xmlrpc module).
+     * serweb (php application that can use the XML-RPC interface to call
+       ser functions).
+
+1.4. Implementing New Transports
+
+   To be done.
+
+   Examples:
+     * ctl
+     * xmlrpc
+
+1.5. Examples using xmlrpc
+
+   See the xmlrpc module documentation: modules/xmlrpc/README.
diff --git a/doc/rpc/kamailio_rpc.xml b/doc/rpc/kamailio_rpc.xml
new file mode 100644
index 0000000..72ddaf1
--- /dev/null
+++ b/doc/rpc/kamailio_rpc.xml
@@ -0,0 +1,918 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+	"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+	[ <!ENTITY % local.common.attrib
+	 "xmlns:xi CDATA #FIXED 'http://www.w3.org/2001/XInclude'">
+	<!ENTITY % docentities SYSTEM "../../docbook/entities.xml">
+	%docentities;
+
+]>
+<!-- Include general documentation entities -->
+
+<section id="rpc.main" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <!--
+    <sectioninfo>
+        <releaseinfo role="cvs">$Revision$</releaseinfo>
+        <pubdate role="cvs">$Date$</pubdate>
+    </sectioninfo>
+    -->
+ 
+    <title>
+	The Kamailio RPC Control Interface
+    </title>
+
+	<section id="rpc.overview">
+	<title>Overview of Operation</title>
+	<para>
+		The RPC (Remote Procedure Call) interface is an interface for
+		communicating with external applications. Using it an external
+		application can call a function or procedure that will be executed
+		inside Kamailio. Function parameters are supported as well as returning
+		multiple values as results.
+	</para>
+	<para>
+		By itself RPC consists of two APIs, one for defining RPC functions
+		in a transport independent way (called the rpc module api) and one
+		for implementing RPC transports.
+	</para>
+	<para>
+		The RPC transports are implemented by writting a RPC
+		transport module. The most used transport modules are
+		<ulink url='http://www.kamailio.org/docs/modules/devel/modules/ctl/ctl.html'>
+		<emphasis>ctl</emphasis>
+		</ulink>,
+		<ulink url='http://www.kamailio.org/docs/modules/devel/modules/xmlrpc/xmlrpc.html'>
+		<emphasis>xmlrpc</emphasis>
+		</ulink>
+		and
+		<ulink url='http://www.kamailio.org/docs/modules/devel/modules/jsonrpc-s/jsonrpc-s.html'>
+		<emphasis>jsonrpc-s</emphasis>
+		</ulink>.
+	</para>
+	<para>
+		ctl implements a proprietary fast and space efficient
+		 RPC encoding over different protocols (unix sockets, UDP, TCP, fifo).
+	</para>
+	<para>
+		xmlrpc uses the de-facto XML-RPC standard encoding
+		 (over HTTP TCP or TLS).
+	</para>
+	<para>
+		jsonrpc-s uses the de-facto JSON-RPC standard encoding
+		 (over HTTP TCP or TLS).
+	</para>
+	<para>
+		 For more information about the existing transport modules, please 
+		 refer to their documentation.
+	</para>
+	<para>
+		When writing a RPC procedure or function, one needs only use the
+		RPC API and it will work automatically with all the transports and
+		encodings. One needs only to load the desired RPC transport module
+		(e.g. xmlrpc).
+	</para>
+	<para>
+		The RPC interface (or API) was created in such a way that would allow
+		supporting XML-RPC (because XML-RPC is a de-facto standard), while in
+		the same time being very easy to use.
+	</para>
+	</section>
+
+    <section id="rpc.module_api">
+	<title>Module API</title>
+	<para>
+	    Each module can export RPC functions just like it can export
+	    parameters and functions to be called from the script. Whenever &kamailio;
+	    receives an RPC request, it will search through the list of
+	    exported RPC functions and the function with matching name will be
+	    executed. A couple of essential RPC functions are also embedded into
+	    the SIP server core.
+	</para>
+	<para>
+	    This section gives a detailed overview of the whole RPC API. <xref
+	    linkend="rpc.rpc_functions"/> describes the prototype and
+	    conventions used in RPC functions. <xref linkend="rpc.data_types"/>
+	    gives a detailed overview of available data types that can be used
+	    in function parameters and return value. <xref
+	    linkend="rpc.getting_parameters"/> describes functions of the RPC
+	    API that can be used to retrieve parameters of the function, and
+	    finally <xref linkend="rpc.creating_result"/> describes functions of
+	    the API that can be used to build the result value that will be
+	    sent in the reply to the caller.
+	</para>
+	<para>
+	    The whole RPC API is described in header file
+	    <filename>kamailio/rpc.h</filename>.  This file defines the set
+	    of functions that must be implemented by RPC transport modules, as
+	    described in <xref linkend="rpc.new_transport"/>, prototypes of RPC
+	    functions and structures used for the communication between RPC
+	    transport modules and ordinary modules exporting RPC functions.
+	</para>
+	<section id="rpc.rpc_functions">
+	    <title>RPC Functions</title>
+	    <para>
+		RPC functions are standard C functions with the following
+		prototype:
+		<programlisting>
+typedef void (*rpc_function_t)(rpc_t* rpc, void* ctx);
+		</programlisting>
+		RPC functions take two parameters, first parameter is a pointer
+		to rpc_t structure and the context. The rpc_t structure
+		contains references to all API functions available to the RPC
+		function as well as all data necessary to create the
+		response. RPC functions do not return any value, instead the
+		return value is created using functions from the context. The
+		motivation for this decision is the fact that RPC functions
+		should always return a response and even the API functions
+		called from RPC functions should have the possibility to
+		indicate an error (and should not rely on RPC functions doing so).
+	    </para>
+	    <para>
+		If no reply is sent explicitely, the RPC transport module will
+		automatically send a "success" reply (e.g. 200 OK for XML-RPC)
+		when the RPC function finishes.
+		If no values are added to the response, the reponse will be an
+		empty "success" reply (e.g. a 200 OK with empty body for
+		XML-RPC).
+		RPC API functions will automatically send an error reply upon a
+		failure.
+	    </para>
+	    <para>
+		Each RPC function has associated an array of documentation
+		strings. The purpose of the documentation strings is to give a
+		short overview of the function, accepted parameters, and format
+		of the reply. By convention the name of the documentation string
+		array is same as the name of the function with "_doc" suffix.
+	    </para>
+	    <para>
+		Each module containing RPC functions has to export all the
+		RPC functions to the &kamailio; core in order to make them visible to the RPC
+		transport modules.
+		The export process involves a <emphasis>rpc_export_t</emphasis> 
+		structure (either by itself or in an array):
+		<programlisting>
+<emphasis>
+typedef struct rpc_export {
+    const char* name;        /* Name of the RPC function (null terminated) */
+    rpc_function_t function; /* Pointer to the function */
+    const char** doc_str;    /* Documentation strings, method signature and description */
+    unsigned int flags;      /* Various flags, reserved for future use */
+} rpc_export_t;
+</emphasis>
+		</programlisting>
+		</para>
+		<para>
+		The <varname>flags</varname> attribute of the
+		<varname>rpc_export</varname> structure is reserved for future
+		use and is currently unused.
+	    </para>
+		<para>
+		There are several ways of exporting the RPC functions to the &kamailio; core:
+		<itemizedlist>
+			<listitem><para>
+				register a null terminated array of rpc_export_t structures
+				using the <function>rpc_register_array()</function> function
+				(defined in rpc_lookup.h), from the module init function
+				(mod_init()). This is the <emphasis>recommended</emphasis>
+				method for all the new modules.
+				<example><title>usrloc RPC Exports Declaration</title>
+					<para>
+					The <varname>rpc_export_t</varname> array for the modules_s/usrloc
+					module looks like:
+					</para>
+					<programlisting>
+<emphasis>
+rpc_export_t ul_rpc[] = {
+    {"usrloc.statistics",      rpc_stats,           rpc_stats_doc,          0},
+    {"usrloc.delete_aor",      rpc_delete_aor,      rpc_delete_aor_doc,     0},
+    {"usrloc.delete_contact",  rpc_delete_contact,  rpc_delete_contact_doc, 0},
+    {"usrloc.dump",            rpc_dump,            rpc_dump_doc,           0},
+    {"usrloc.flush",           rpc_flush,           rpc_flush_doc,          0},
+    {"usrloc.add_contact",     rpc_add_contact,     rpc_add_contact_doc,    0},
+    {"usrloc.show_contacts",   rpc_show_contacts,   rpc_show_contacts_doc,  0},
+    {0, 0, 0, 0}
+};
+</emphasis>
+					</programlisting>
+					<para>
+					To register it from the module init function one would use
+					something similar to:
+					</para>
+					<programlisting>
+	if (rpc_register_array(ul_rpc) != 0) {
+		ERR("failed to register RPC commands\n");
+		return -1;
+	}
+					</programlisting>
+				</example>
+			</para></listitem>
+			<listitem><para>
+				register RPCs one by one using the
+				<function>rpc_register_function()</function>
+				(defined in rpc_lookup.h), from the module init function.
+			</para></listitem>
+			<listitem><para>
+				register a null terminated array of rpc_export_t structures
+				using the &kamailio;  module interface SER_MOD_INTERFACE
+				For this purpose, the
+				<varname>module_exports</varname> structure of the &kamailio; module API
+				contains a new attribute called <varname>rpc_methods</varname>:
+				<programlisting>
+struct module_exports {
+    char* name;                 /* null terminated module name */	
+    cmd_export_t* cmds;         /* null terminated array of the exported commands */
+    <emphasis>rpc_export_t* rpc_methods;</emphasis>  /* null terminated array of exported rpc methods */
+    param_export_t* params;     /* null terminated array of the exported module parameters */
+    
+    init_function init_f;         /* Initialization function */
+    response_function response_f; /* function used for responses */
+    destroy_function destroy_f;   /* function called upon shutdown */
+    onbreak_function onbreak_f;
+    child_init_function init_child_f;  /* function called by all processes after the fork */
+};
+				</programlisting>
+				<varname>rpc_methods</varname> is a pointer to an array of
+				rpc_export_t structures. The last element of the array is a
+				bumper containing zeroes in all the attributes of the
+				structure. The following program listing shows the exported RPC
+				functions of the modules_s/usrloc module, using the rpc_export_t array
+				<emphasis>ul_rpc</emphasis> defined above, in the 
+				rpc_register_array() example:
+				<example><title>usrloc Module Exports Declaration</title>
+					<programlisting>
+struct module_exports exports = {
+    "usrloc",
+    cmds,      /* Exported functions */ 
+    <emphasis>ul_rpc</emphasis>,    /* RPC methods */
+    params,    /* Export parameters */ 
+    mod_init,  /* Module initialization function */ 
+    0,         /* Response function */ 
+    destroy,   /* Destroy function */ 
+    0,         /* OnCancel function */ 
+    child_init /* Child initialization function */ };
+
+					</programlisting>
+				</example>
+				<note><para>
+					This mode works only with modules using the SER flavour module
+					interface. It does not work for &kamailio; modules and it
+					will probably not work for future sip-router modules. It is
+					safer and recommended to use instead the
+					<function>rpc_register_array()</function> function.
+				</para></note>
+			</para></listitem>
+		</itemizedlist>
+		</para>
+		<para>
+			By convention the name of every exported function consists of
+			two parts delimited by a dot. The first part is the name of the
+			module or &kamailio; subsystem this function belongs to. The second
+			part is the name of the function.
+		</para>
+	</section>
+
+	<section id="rpc.data_types">
+	    <title>Data Types</title>
+	    <para>
+		The RPC API defines several basic and one compound data type
+		that can be used in communication with the caller of RPC
+		functions. The RPC API uses formating strings to describe data
+		types. Each data type is described by exactly one character in
+		the formating string. For example, if an RPC function calls
+		function <function>add</function> of the RPC API and it passes
+		two parameters to it, the first one of type string and the
+		second one of type integer, the function parameters will look
+		like:
+		<programlisting>
+add("sd", string_param, int_param);
+		</programlisting>
+		Character "s" in the formating string tells to the function
+		that the 2nd parameter should be interpreted as string,
+		character "d" in the formating string tells to the function
+		that the 3rd parameter should be interpreted as signed integer.
+	    </para>
+	    <formalpara>
+		<title>Integer</title>
+		<para>
+		    Integer type represents a signed 32-bit
+		    integer. Corresponding character in the formating string is
+		    "d". This parameter can be stored in C-style variable with
+		    type <varname>int</varname>.
+		</para>
+	    </formalpara>
+	    <formalpara>
+		<title>Float</title>
+		<para>
+		    Float type represents a signed floating point
+		    number. Corresponding character in the formating string is
+		    "f". Data of this type can be stored in C-style variables
+		    of type <varname>double</varname>.
+		</para>
+	    </formalpara>
+	    <formalpara>
+		<title>String</title>
+		<para>
+		    String type represents a string of characters. The string
+		    may contain zeroes. This data type is represented by two
+		    characters in the formatting string, either "s" or "S". "s"
+		    indicates to the conversion function that the result should
+		    be stored in a variable of type <varname>char*</varname>
+		    and it should be zero terminated. "S" indicates to the
+		    conversion function that the result will be stored in
+		    a variable of type <varname>str</varname> which contains
+		    both the pointer to the beginning of the string and its
+		    length.
+		</para>
+	    </formalpara>
+	    <formalpara>
+		<title>Structure</title>
+		<para>
+		    Structure is the only compound data type currently defined
+		    in the API. A structure is a collection of attributes. Each
+		    attribute is identified using name (string) and each
+		    attribute can be one of the basic data types, that
+		    is integer, float, or string. Nesting of structures is not
+		    allowed (in other words, structure attributes cannot be of
+		    type struct again). Corresponding character in the
+		    formatting string is "{".
+		</para>
+	    </formalpara>
+		<formalpara>
+		<title>Optional parameters</title>
+		<para>
+			Optional parameters can be used, but only in the
+			<function>scan</function> function.  For optional parameters the
+			<function>scan</function> function will not automatically generate
+			a rpc fault if the input ends. Note that in this case the
+			<function>scan</function> will still return a negative value
+			(minus the number of parameters successfully read).
+			Optional parameters can be marked in the format string by
+			preceding the first optional parameter type with a "*".
+			All the parameters following a "*" are considered to be optional.
+			For example for the format string "ds*dds", the last 3 parameters
+			(2 ints and a string) are optional.
+		</para>
+		</formalpara>
+	    <table>
+		<title>Data Type Overview</title>
+		<tgroup cols="3">
+		    <tbody>
+			<row rowsep="1">
+			    <entry>Name</entry>
+			    <entry>Formating String Char</entry>
+			    <entry>C-Style Variable</entry>
+			</row>
+			<row>
+			    <entry>Integer</entry>
+			    <entry>d</entry>
+			    <entry>int</entry>
+			</row>
+			<row>
+			    <entry>Float</entry>
+			    <entry>f</entry>
+			    <entry>double</entry>
+			</row>
+			<row>
+			    <entry>String</entry>
+			    <entry>s</entry>
+			    <entry>char*</entry>
+			</row>
+			<row>
+			    <entry>String</entry>
+			    <entry>S</entry>
+			    <entry>str*</entry>
+			</row>
+			<row>
+				<entry>Optional modifier</entry>
+				<entry>*</entry>
+				<entry>marks all further parameters as optional</entry>
+			</row>
+			<row>
+				<entry>Autoconvert modifier</entry>
+				<entry>.</entry>
+				<entry>requires auto-conversion for the next parameter</entry>
+			</row>
+		    </tbody>
+		</tgroup>
+	    </table>
+	</section>
+
+	<section id="rpc.getting_parameters">
+	    <title>Getting Parameters</title>
+	    <para>
+		Each RPC function call can contain parameters. Parameters have
+		no name, their meaning is determined by their position in the
+		parameter set.
+		<note>
+		    <para>
+			You can pass all parameters to a function within a
+			structure if you want to make them position
+			independent. Then each parameter can be retrieved by
+			its name regardless of its position.
+		    </para>
+		</note>
+		There are two functions in the RPC API that can be used to
+		obtain function call parameters: <function>scan</function> and
+		<function>struct_scan</function>.
+	    </para>
+	    <section id="rpc.scan">
+		<title><function>scan</function></title>
+		<para>
+		    Function <function>scan</function> can be used to retrieve
+		    parameters from the parameter set. The function accepts
+		    variable number of parameters. The first parameter is the
+		    formatting string that determines the type of the
+		    parameters to be retrieved. Each parameter is represented by
+		    exactly one parameter type character in the string.
+			The variable part of parameters must contain as many pointers to C
+			variables as there are formatting non-modifiers characters in the
+			formatting string.
+		    <warning>
+			<para>
+			    The function will crash if you fail to provide
+			    enough parameters.
+			</para>
+		    </warning>
+		</para>
+		<para>
+			Besides characters representing parameter types, the formatting
+			string can contain two special modifiers: "*" and ".". The
+			modifiers do not have a correspondent in the variable part of the
+			parameters.
+		</para>
+		<para>
+			The meaning of "*" modifier is that any further parameters
+			(defined by other type characters in the formatting string) are
+			optional (they can be missing in the input and no rpc fault will
+			automatically be generated).
+		</para>
+		<para>
+			The '.' modifiers turns on type autoconversion for the next
+			parameter. This means that if the type of the next parameter 
+			differs from the type specified in the formatting string, the
+			parameter will be automatically converted to the formatting string
+			type (if possible) and if the automatic conversion succeeds, no
+			fault will be generated.
+		</para>
+		<para>
+			The function returns the number of parameters read on success
+			(a number greater or equal 0) and - (minus) the number of
+			parameters read on error (for example for an error after 
+			reading 2 parameters it will return -2).
+			When a failure occurs (incorrect parameter type or no more
+			parameters in the parameter set) the function will
+			return a negative number (- number of parameters read so far)
+			and it will also automatically change the reply that will be
+			sent to the caller to indicate that a failure has occurred on 
+			the server (unless the "*" is used and the error is lack
+			of more parameters).
+		</para>
+		<para>
+			The prototype of the function is:
+		    <programlisting>
+int scan((void* ctx, char* fmt, ...)
+		    </programlisting>
+		    It is possible to either call the function once to scan all
+		    the parameters:
+		    <programlisting>
+rpc->scan(ctx, "sdf", &string_val, &int_val, &double_val);
+		    </programlisting>
+		    Or you can call the same function several times and it will
+		    continue where it left off previously:
+		    <programlisting>
+rpc->scan(ctx, "s", &string_val);
+rpc->scan(ctx, "d", &int_val);
+rpc->scan(ctx, "f", &double_val);
+		    </programlisting>
+		</para>
+		<para>
+		</para>
+	    </section>
+	    <section>
+		<title><function>struct_scan</function></title>
+		<para>
+			Function <function>struct_scan</function> can be used to
+			retrieve named attributes from a parameter of type
+			structure.
+			<note><para>
+			This function is obsolete and not implemented by all the
+			rpc transports (e.g.: ctl / binrpc). Consider using the normal
+			<function>scan</function> instead.
+			</para></note>
+			When retrieving a structure parameter from the
+			parameter set:
+		    <programlisting>
+rpc->scan(ctx, "{", &handle);
+		    </programlisting>
+		    The corresponding variable (named 
+		    <varname>handle</varname> in the example above) will contain
+		    the index of the structure parameter within the parameter
+		    set, but the index cannot be used to retrieve the contents
+		    of the structure. To retrieve the contents of the structure
+		    you can use function <function>struct_scan</function>. The
+		    function gets the handle as the first parameter:
+		    <programlisting>
+rpc->struct_scan(handle, "sd", "str_attr", &str_val, "int_attr", &int_val);
+		    </programlisting>
+		    The second parameter is the formatting string followed by
+		    pairs of parameters. First parameter in each pair is the
+		    name of the attribute to retrieve (string) and the second
+		    parameter in each pair is the pointer to the variable to
+		    store the value of the parameter. The function returns the
+			number of parameters (name value pairs) read on
+		    success and - number of parameters read so far on an error
+			(just like the <function>scan</function> function). The function
+			also indicates an error if a requested attribute is missing in
+		    the structure.
+		</para>
+	    </section>
+	
+		<section><title>Retrieving Parameters Example</title>
+		<example>
+		<title>Retrieving Parameters</title>
+		<programlisting>
+<![CDATA[
+static void rpc_delete_contact(rpc_t* rpc, void* ctx)
+{
+    str aor, contact;
+    char* table;
+    void *handle;
+    int   expires;
+    double q;
+
+    if (rpc->scan(ctx, "sS{", &table, &aor, &handle) < 0) {
+        /* Reply is set automatically by scan upon failure,
+         * no need to do anything here
+         */
+        return;
+    }
+
+    if (rpc->struct_scan(handle, "Sdf", "Contact", &contact,
+                                        "Expires", &expires,
+                                        "Q",       &q        ) < 0) {
+        /* Reply is set automatically by struct_scan upon failure,
+         * no need to do anything here
+         */
+        return;
+    }
+
+    /* Process retrieved parameters here */
+}
+
+/* variable number of parameters:
+   echo back all the parameters, string type required */
+static void core_prints(rpc_t* rpc, void* c)
+{
+	char* string = 0;
+	while((rpc->scan(c, "*s", &string)>0))
+		rpc->add(c, "s", string);
+}
+
+/* variable number of parameters and auto conversion:
+   echo back all the parameters, works with any type (everything is 
+   internally converted to string, notice the '.' modifier) */
+static void core_echo(rpc_t* rpc, void* c)
+{
+	char* string = 0;
+	while((rpc->scan(c, "*.s", &string)>0))
+		rpc->add(c, "s", string);
+}
+
+]]>
+		</programlisting>
+	    </example>
+		</section>
+	</section>
+
+	<section id="rpc.creating_result">
+	    <title>Building Reply</title>
+	    <para>
+		The RPC API contains several functions that can be used to
+		modify and/or send a reply. The functions use formatting
+		strings and parameter lists just like functions described in
+		<xref linkend="rpc.getting_parameters"/>.
+	    </para>
+	    <para>
+		Each RPC function call must return a reply. The reply can be
+		either a failure reply or success reply. Failure replies
+		contain only the status code and reason phrase. Success
+		replies can have arbitrary amount of data attached to
+		them. Status codes 3xx, 4xx, 5xx, and 6xx indicate
+		failures. Status code 2xx indicates success.
+	    </para>
+	    <para>
+		The default reply is 200 OK with no data attached to it. This
+		is what will be returned by the RPC transport module if you do
+		not call any of the reply-related functions described in this
+		section.
+		<example>
+		    <title>Sending default reply</title>
+		    <programlisting>
+<![CDATA[
+static void rpc_dummy(rpc_t* rpc, void *ctx)
+{
+  /* 200 OK with no data will be returned */
+}
+]]>
+		    </programlisting>
+		</example>
+	    </para>
+	    <section>
+		<title>fault</title>
+		<para>
+		    You can use <function>fault</function> function to indicate
+		    that an error has occurred on the server to the caller. The
+		    function accepts two parameters. The first parameter is the
+		    status code and the second parameter is the reason phrase.
+		    <programlisting>
+<![CDATA[
+static void rpc_my_function(rpc_t* rpc, void *ctx)
+{
+    rpc->fault(ctx, 600, "Not Yet Implemented");
+}
+]]>
+		    </programlisting>
+		    If your function first creates some result using
+		    <function>add</function>, or <function>printf</function>
+		    functions then all the data will be lost once you call
+		    <function>fault</function> function. Failure replies must
+		    not contain any data:
+		    <programlisting>
+<![CDATA[
+static void rpc_my_function(rpc_t* rpc, void *ctx)
+{
+    rpc->add(ctx, "s", "result1");
+    rpc->add(ctx, "d", variable);
+
+    /* Reply created by previous functions will be
+     * deleted and a failure reply 600 Not Yet Implemented
+     * will be created instead
+     */
+    rpc->fault(ctx, 600, "Not Yet Implemented");
+
+    /* You can also add data here, but that will have no
+     * effect
+     */
+    rpc->add(ctx, "s", "result2");
+}
+]]>
+		    </programlisting>
+		    Similarly you can also call <function>add</function> or
+		    <function>printf</function> functions after calling
+		    <function>fault</function>, in this case they will have no
+		    effect:
+		    <programlisting>
+<![CDATA[
+static void rpc_my_function(rpc_t* rpc, void *ctx)
+{
+    rpc->fault(ctx, 600, "Not Yet Implemented");
+
+    /* You can also add data here, but that will have no
+     * effect and only 600 Not Yet Implemented will be returned
+     */
+    rpc->add(ctx, "s", "result2");
+}
+]]>
+		    </programlisting>
+		</para>
+	    </section>
+	    <section>
+		<title>send</title>
+		<para>
+		    RPC functions can use function <function>send</function> to
+		    explicitly send the reply. Each RPC function call generates
+		    exactly one reply. No reply will be sent after the function
+		    finishes if it already sent the reply using
+		    <function>send</function> function explicitly. This
+		    function is especially useful if the RPC function needs to
+		    perform some (potentially destructive) actions after the
+		    reply has been sent.
+		</para>
+		<example>
+		    <title>Kill the server</title>
+		    <programlisting>
+<![CDATA[
+static void core_kill(rpc_t* rpc, void *ctx)
+{
+    int sig_no;
+
+    if (rpc->scan(ctx, "d", &sig_no) < 0) return;
+    rpc->send(ctx, );     /* First send a reply */
+    kill(0, sig_no); /* Then kill the server */
+}
+]]>
+		    </programlisting>
+		</example>
+		
+	    </section>
+	    <section>
+		<title>add</title>
+		<para>
+		    Function <function>add</function> can be used to add
+		    arbitrary data to the result set. Its parameters and use
+		    are analogical to <function>scan</function> function
+		    described in <xref linkend="rpc.scan"/>. The first
+		    parameter of the function is the formatting string that
+		    determines the types of additional parameters:
+		    <programlisting>
+<![CDATA[
+static void rpc_func(rpc_t* rpc, void *ctx)
+{
+    str str_result;
+    int int_result;
+    void *handle;
+    double float_result;
+
+    if (rpc->add(ctx, "Sdf{", &str_result, int_result, float_result, &handle) < 0) return;
+}
+]]>
+		    </programlisting>
+		    Naturally you can call this function several times, adding
+		    only one piece of data at a time. The function returns 0 on
+		    success and -1 on an error. In case of an error the reply
+		    is set automatically with corresponding error code and
+		    reason phrase.
+		</para>
+		<para>
+		    The last character in the formatting string of the function
+		    above indicates that the last data to be added will be a
+		    structure. This deserves some clarification. In this case,
+		    the function will create an empty structure and the handle
+		    to the newly created structure will be stored in
+		    <varname>handle</varname> variable (hence the last
+		    parameter is pointer to an integer). In this particular
+		    example parameters <varname>str_result</varname>,
+		    <varname>int_result</varname>, and
+		    <varname>float_result</varname> will be used for reading
+		    while parameter <varname>handle</varname> will be used for
+		    writing by the function.
+		</para>
+		<para>
+		    You can set the attributes of the newly created structure
+		    using <function>struct_add</function> function described in
+		    <xref linkend="rpc.struct_add"/>.
+		</para>
+	    </section>
+	    <section>
+		<title>rpl_printf</title>
+		<para>
+		    <varname>rpl_printf</varname> is a convenience function. The
+		    function adds data of type string to the result set. The
+		    first parameter of the function is again a formatting
+			string, but this time it is standard
+			<function>printf</function>-like formatting string:
+		    <programlisting>
+<![CDATA[
+if (rpc->rpl_printf(ctx, "Unable to delete %d entries from table %s", num_entries, table_name) < 0) return;
+]]>
+		    </programlisting>
+		    The return value of the function is the same as of
+		    <function>add</function> function.
+		</para>
+	    </section>
+	    <section id="rpc.struct_add">
+		<title>struct_add</title>
+		<para>
+		    Function <function>struct_add</function> can be used to add
+		    attributes to a structure (created previously by
+		    <function>add</function> function). The first parameter of
+		    the function is handle obtained through
+		    <function>add</function> function, the second parameters is
+		    formatting string that determines the types of attributes
+		    to be added. There must be two parameters per each
+		    character in the formatting string, the first one is the
+		    name of the attribute, the second parameter is the value
+		    of the attribute. If a parameter with such a name already
+		    exist in the structure then it will be overwritten with the
+		    new value.
+		    <programlisting>
+<![CDATA[
+static void rpc_func(rpc_t* rpc, void *ctx)
+{
+    void *handle;
+
+        /* Create empty structure and obtain its handle */
+    if (rpc->add(ctx, "{", &handle) < 0) return;
+        /* Fill-in the structure */
+    if (rpc->struct_add(handle, "sd", "attr1", str_val,
+                                      "attr2", int_val ) < 0)
+        return;
+}
+]]>
+		    </programlisting>
+		    The function returns -1 on an error (and sets the status
+		    code and reason phrase of the reply accordingly) and 0 on success.
+		</para>
+	    </section>
+	</section>
+
+	<section>
+	    <title>Real World Example</title>
+	    <para>
+		The following example illustrates the use of most of the
+		functions from the API together:
+	    </para>
+	    <example>
+		<title>Real World Example RPC Function</title>
+		<programlisting>
+<![CDATA[
+static void rpc_register(rpc_t* rpc, void *ctx)
+{
+    char* domain;
+    str aor;
+    contact_t contact, new_contact;
+    void *handle;
+
+        /* Extract the domain, address of record from the request */
+    if (rpc->scan(ctx, "sS{", &domain, &aor, &handle) < 0) return;
+        /* Extract the structure describing the contact to be processed */
+    if (rpc->struct_scan(handle, "Sdf", "Contact", &contact.c,
+                                        "Expires", &contact.expires,
+                                        "Q",       &contact.q       ) < 0)
+        return;
+
+        /* Process the contact, new_contact will contain updated value after processing */
+    if (process_contact(domain, &aor, &new_contact, &contact) < 0) {
+           /* Processing failed, indicate the failure to the caller */
+        rpc->fault(ctx, 500, "Error While Processing Contact");
+        return;
+    }
+
+        /* Return the domain and the address of record */
+    rpc->add(ctx, "sS{", &domain, &aor, &handle) < 0) return;
+        /* And also add the new values for contact, q, and expires parameters */
+    rpc->struct_add(handle, "Sdf", "Contact", &new_contact.c,
+                                   "Expires", &new_contact.expires,
+                                   "Q",       &new_contact.q       );
+}
+]]>
+		</programlisting>
+	    </example>
+	</section>
+    </section>
+
+	<section id="rpc.client_examples">
+	<title>Client Examples</title>
+	<para>
+	<itemizedlist>
+		<listitem><para>
+		<emphasis>sercmd</emphasis> (C application that uses the
+		<emphasis>binrpc</emphasis> interface implemented by the
+		<emphasis>ctl</emphasis> module).
+		</para></listitem>
+		<listitem><para>
+		<emphasis>ser_ctl</emphasis> (python application that uses the
+		<emphasis>XML-RPC</emphasis> interface implemented by the
+		<emphasis>xmlrpc</emphasis>
+		module).
+		</para></listitem>
+		<listitem><para>
+		<emphasis>serweb</emphasis> (php application that can use
+		the <emphasis>XML-RPC</emphasis> interface to call ser 
+		functions).
+		</para></listitem>
+	</itemizedlist>
+	</para>
+	</section>
+
+    <section id="rpc.new_transport">
+	<title>Implementing New Transports</title>
+	<remark>
+	To be done.
+	</remark>
+	<!-- TODO:
+	- create a new module
+	- take a look at sip_router/rpc.h
+	- implement all functions in that header field
+	- no garbage collection in rpc functions, the module needs to keep
+	track of all allocated data
+	- return value default to true
+	- parameter type conflict is an error
+	- missing struct attribute is an error
+	- always send a reply, prepare replies so that you do not have to
+	allocate memory at runtime
+	- str strings do not have to be zero terminated
+	- no structure/array nesting allowed
+	- printf creates string attribute
+        -->
+	<para>
+		Examples:
+		<itemizedlist>
+			<listitem><para>
+				<emphasis>ctl</emphasis>
+			</para></listitem>
+			<listitem><para>
+				<emphasis>xmlrpc</emphasis>
+			</para></listitem>
+		</itemizedlist>
+	</para>
+    </section>
+
+<section id="rpc.xmlrpc_examples">
+	<title>Examples using xmlrpc</title>
+	<para>See the <varname>xmlrpc</varname> module documentation:
+	<ulink url='http://www.kamailio.org/docs/modules/devel/modules/xmlrpc.html'>modules/xmlrpc/README</ulink>.
+	</para>
+</section>
+
+</section>
diff --git a/doc/rpc/ser_rpc.txt b/doc/rpc/ser_rpc.txt
deleted file mode 100644
index 06b8044..0000000
--- a/doc/rpc/ser_rpc.txt
+++ /dev/null
@@ -1,626 +0,0 @@
-1. RPC Control Interface
-     __________________________________________________________________
-
-   1.1. Overview of Operation
-   1.2. Module API
-
-        1.2.1. RPC Functions
-        1.2.2. Data Types
-        1.2.3. Getting Parameters
-
-              1.2.3.1. scan
-              1.2.3.2. struct_scan
-              1.2.3.3. Retrieving Parameters Example
-
-        1.2.4. Building Reply
-
-              1.2.4.1. fault
-              1.2.4.2. send
-              1.2.4.3. add
-              1.2.4.4. rpl_printf
-              1.2.4.5. struct_add
-
-        1.2.5. Real World Example
-
-   1.3. Client Examples
-   1.4. Implementing New Transports
-   1.5. Examples using xmlrpc
-
-1.1. Overview of Operation
-
-   The RPC (Remote Procedure Call) interface is an interface for
-   communicating with external applications. Using it an external
-   application can call a function or procedure that will be executed
-   inside SIP Server (SER or Kamailio). Function parameters are supported
-   as well as returning multiple values as results.
-
-   By itself RPC consists of two APIs, one for defining RPC functions in a
-   transport independent way (called the rpc module api) and one for
-   implementing RPC transports.
-
-   The RPC transports are implemented by writting a RPC transport module.
-   The most used transport modules are ctl , xmlrpc and jsonrpc-s .
-
-   ctl implements a proprietary fast and space efficient RPC encoding over
-   different protocols (unix sockets, UDP, TCP, fifo).
-
-   xmlrpc uses the de-facto XML-RPC standard encoding (over HTTP TCP or
-   TLS).
-
-   jsonrpc-s uses the de-facto JSON-RPC standard encoding (over HTTP TCP
-   or TLS).
-
-   For more information about the existing transport modules, please refer
-   to their documentation.
-
-   When writing a RPC procedure or function, one needs only use the RPC
-   API and it will work automatically with all the transports and
-   encodings. One needs only to load the desired RPC transport module
-   (e.g. xmlrpc).
-
-   The RPC interface (or API) was created in such a way that would allow
-   supporting XML-RPC (because XML-RPC is a de-facto standard), while in
-   the same time being very easy to use.
-
-1.2. Module API
-
-   Each module can export RPC functions just like it can export parameters
-   and functions to be called from the script. Whenever SIP server
-   receives an RPC request, it will search through the list of exported
-   RPC functions and the function with matching name will be executed. A
-   couple of essential RPC functions are also embedded into the SIP server
-   core.
-
-   This section gives a detailed overview of the whole RPC API.
-   Section 1.2.1, "RPC Functions" describes the prototype and conventions
-   used in RPC functions. Section 1.2.2, "Data Types" gives a detailed
-   overview of available data types that can be used in function
-   parameters and return value. Section 1.2.3, "Getting Parameters"
-   describes functions of the RPC API that can be used to retrieve
-   parameters of the function, and finally Section 1.2.4, "Building Reply"
-   describes functions of the API that can be used to build the result
-   value that will be sent in the reply to the caller.
-
-   The whole RPC API is described in header file sip_router/rpc.h. This
-   file defines the set of functions that must be implemented by RPC
-   transport modules, as described in Section 1.4, "Implementing New
-   Transports", prototypes of RPC functions and structures used for the
-   communication between RPC transport modules and ordinary modules
-   exporting RPC functions.
-
-1.2.1. RPC Functions
-
-   RPC functions are standard C functions with the following prototype:
-typedef void (*rpc_function_t)(rpc_t* rpc, void* ctx);
-
-   RPC functions take two parameters, first parameter is a pointer to
-   rpc_t structure and the context. The rpc_t structure contains
-   references to all API functions available to the RPC function as well
-   as all data necessary to create the response. RPC functions do not
-   return any value, instead the return value is created using functions
-   from the context. The motivation for this decision is the fact that RPC
-   functions should always return a response and even the API functions
-   called from RPC functions should have the possibility to indicate an
-   error (and should not rely on RPC functions doing so).
-
-   If no reply is sent explicitely, the RPC transport module will
-   automatically send a "success" reply (e.g. 200 OK for XML-RPC) when the
-   RPC function finishes. If no values are added to the response, the
-   reponse will be an empty "success" reply (e.g. a 200 OK with empty body
-   for XML-RPC). RPC API functions will automatically send an error reply
-   upon a failure.
-
-   Each RPC function has associated an array of documentation strings. The
-   purpose of the documentation strings is to give a short overview of the
-   function, accepted parameters, and format of the reply. By convention
-   the name of the documentation string array is same as the name of the
-   function with "_doc" suffix.
-
-   Each module containing RPC functions has to export all the RPC
-   functions to SIP server core in order to make them visible to the RPC
-   transport modules. The export process involves a rpc_export_t structure
-   (either by itself or in an array):
-typedef struct rpc_export {
-    const char* name;        /* Name of the RPC function (null terminated) */
-    rpc_function_t function; /* Pointer to the function */
-    const char** doc_str;    /* Documentation strings, method signature and desc
-ription */
-    unsigned int flags;      /* Various flags, reserved for future use */
-} rpc_export_t;
-
-   The flags attribute of the rpc_export structure is reserved for future
-   use and is currently unused.
-
-   There are several ways of exporting the RPC functions to the SIP server
-   core:
-     * register a null terminated array of rpc_export_t structures using
-       the rpc_register_array() function (defined in rpc_lookup.h), from
-       the module init function (mod_init()). This is the recommended
-       method for all the new modules.
-       Example 1. usrloc RPC Exports Declaration
-       The rpc_export_t array for the modules_s/usrloc module looks like:
-rpc_export_t ul_rpc[] = {
-    {"usrloc.statistics",      rpc_stats,           rpc_stats_doc,          0},
-    {"usrloc.delete_aor",      rpc_delete_aor,      rpc_delete_aor_doc,     0},
-    {"usrloc.delete_contact",  rpc_delete_contact,  rpc_delete_contact_doc, 0},
-    {"usrloc.dump",            rpc_dump,            rpc_dump_doc,           0},
-    {"usrloc.flush",           rpc_flush,           rpc_flush_doc,          0},
-    {"usrloc.add_contact",     rpc_add_contact,     rpc_add_contact_doc,    0},
-    {"usrloc.show_contacts",   rpc_show_contacts,   rpc_show_contacts_doc,  0},
-    {0, 0, 0, 0}
-};
-
-       To register it from the module init function one would use
-       something similar to:
-        if (rpc_register_array(ul_rpc) != 0) {
-                ERR("failed to register RPC commands\n");
-                return -1;
-        }
-     * register RPCs one by one using the rpc_register_function() (defined
-       in rpc_lookup.h), from the module init function.
-     * register a null terminated array of rpc_export_t structures using
-       the SIP server module interface SER_MOD_INTERFACE (specific for SER
-       flavour). For this purpose, the module_exports structure of SIP
-       server module API contains a new attribute called rpc_methods:
-struct module_exports {
-    char* name;                 /* null terminated module name */
-    cmd_export_t* cmds;         /* null terminated array of the exported command
-s */
-    rpc_export_t* rpc_methods;  /* null terminated array of exported rpc methods
- */
-    param_export_t* params;     /* null terminated array of the exported module
-parameters */
-
-    init_function init_f;         /* Initialization function */
-    response_function response_f; /* function used for responses */
-    destroy_function destroy_f;   /* function called upon shutdown */
-    onbreak_function onbreak_f;
-    child_init_function init_child_f;  /* function called by all processes after
- the fork */
-};
-       rpc_methods is a pointer to an array of rpc_export_t structures.
-       The last element of the array is a bumper containing zeroes in all
-       the attributes of the structure. The following program listing
-       shows the exported RPC functions of the modules_s/usrloc module,
-       using the rpc_export_t array ul_rpc defined above, in the
-       rpc_register_array() example:
-       Example 2. usrloc Module Exports Declaration
-struct module_exports exports = {
-    "usrloc",
-    cmds,      /* Exported functions */
-    ul_rpc,    /* RPC methods */
-    params,    /* Export parameters */
-    mod_init,  /* Module initialization function */
-    0,         /* Response function */
-    destroy,   /* Destroy function */
-    0,         /* OnCancel function */
-    child_init /* Child initialization function */ };
-
-Note
-       This mode works only with modules using the SER flavour module
-       interface. It does not work for kamailio modules and it will
-       probably not work for future sip-router modules. It is safer and
-       recommended to use instead the rpc_register_array() function.
-
-   By convention the name of every exported function consists of two parts
-   delimited by a dot. The first part is the name of the module or SIP
-   server subsystem this function belongs to. The second part is the name
-   of the function.
-
-1.2.2. Data Types
-
-   The RPC API defines several basic and 1 compound data type that can be
-   used in communication with the caller of RPC functions. The RPC API
-   uses formating strings to describe data types. Each data type is
-   described by exactly one character in the formating string. For
-   example, if an RPC function calls function add of the RPC API and it
-   passes two parameters to it, the first one of type string and the
-   second one of type integer, the function parameters will look like:
-add("sd", string_param, int_param);
-
-   Character "s" in the formating string tells to the function that the
-   2nd parameter should be interpreted as string, character "d" in the
-   formating string tells to the function that the 3rd parameter should be
-   interpreted as signed integer.
-
-   Integer.  Integer type represents a signed 32-bit integer.
-   Corresponding character in the formating string is "d". This parameter
-   can be stored in C-style variable with type int.
-
-   Float.  Float type represents a signed floating point number.
-   Corresponding character in the formating string is "f". Data of this
-   type can be stored in C-style variables of type double.
-
-   String.  String type represents a string of characters. The string may
-   contain zeroes. This data type is represented by two characters in the
-   formatting string, either "s" or "S". "s" indicates to the conversion
-   function that the result should be stored in a variable of type char*
-   and it should be zero terminated. "S" indicates to the conversion
-   function that the result will be stored in a variable of type str which
-   contains both the pointer to the beginning of the string and its
-   length.
-
-   Structure.  Structure is the only compound data type currently defined
-   in the API. A structure is a collection of attributes. Each attribute
-   is identified using name (string) and each attribute can be one of the
-   basic data types, that is integer, float, or string. Nesting of
-   structures is not allowed (in other words, structure attributes cannot
-   be of type struct again). Corresponding character in the formatting
-   string is "{".
-
-   Optional parameters.  Optional parameters can be used, but only in the
-   scan function. For optional parameters the scan function will not
-   automatically generate a rpc fault if the input ends. Note that in this
-   case the scan will still return a negative value (minus the number of
-   parameters successfully read). Optional parameters can be marked in the
-   format string by preceding the first optional parameter type with a
-   "*". All the parameters following a "*" are considered to be optional.
-   For example for the format string "ds*dds", the last 3 parameters (2
-   ints and a string) are optional.
-
-   Table 1. Data Type Overview
-   Name Formating String Char C-Style Variable
-   Integer d int
-   Float f double
-   String s char*
-   String S str
-   Optional modifier * marks all further parameters as optional
-   Autoconvert modifier . requires auto-conversion for the next parameter
-
-1.2.3. Getting Parameters
-
-   Each RPC function call can contain parameters. Parameters have no name,
-   their meaning is determined by their position in the parameter set.
-
-Note
-
-   You can pass all parameters to a function within a structure if you
-   want to make them position independent. Then each parameter can be
-   retrieved by its name regardless of its position.
-
-   There are two functions in the RPC API that can be used to obtain
-   function call parameters: scan and struct_scan.
-
-1.2.3.1. scan
-
-   Function scan can be used to retrieve parameters from the parameter
-   set. The function accepts variable number of parameters. The first
-   parameter is the formatting string that determines the type of the
-   parameters to be retrieved. Each parameter is represented by exactly
-   one parameter type character in the string. The variable part of
-   parameters must contain as many pointers to C variables as there are
-   formatting non-modifiers characters in the formatting string.
-
-Warning
-
-   The function will crash if you fail to provide enough parameters.
-
-   Besides characters representing parameter types, the formatting string
-   can contain two special modifiers: "*" and ".". The modifiers do not
-   have a correspondent in the variable part of the parameters.
-
-   The meaning of "*" modifier is that any further parameters (defined by
-   other type characters in the formatting string) are optional (they can
-   be missing in the input and no rpc fault will automatically be
-   generated).
-
-   The '.' modifiers turns on type autoconversion for the next parameter.
-   This means that if the type of the next parameter differs from the type
-   specified in the formatting string, the parameter will be automatically
-   converted to the formatting string type (if possible) and if the
-   automatic conversion succeeds, no fault will be generated.
-
-   The function returns the number of parameters read on success (a number
-   greater or equal 0) and - (minus) the number of parameters read on
-   error (for example for an error after reading 2 parameters it will
-   return -2). When a failure occurs (incorrect parameter type or no more
-   parameters in the parameter set) the function will return a negative
-   number (- number of parameters read so far) and it will also
-   automatically change the reply that will be sent to the caller to
-   indicate that a failure has occurred on the server (unless the "*" is
-   used and the error is lack of more parameters).
-
-   The prototype of the function is:
-int scan((void* ctx, char* fmt, ...)
-
-   It is possible to either call the function once to scan all the
-   parameters:
-rpc->scan(ctx, "sdf", &string_val, &int_val, &double_val);
-
-   Or you can call the same function several times and it will continue
-   where it left off previously:
-rpc->scan(ctx, "s", &string_val);
-rpc->scan(ctx, "d", &int_val);
-rpc->scan(ctx, "f", &double_val);
-
-1.2.3.2. struct_scan
-
-   Function struct_scan can be used to retrieve named attributes from a
-   parameter of type structure.
-
-Note
-
-   This function is obsolete and not implemented by all the rpc transports
-   (e.g.: ctl / binrpc). Consider using the normal scan instead.
-
-   When retrieving a structure parameter from the parameter set:
-rpc->scan(ctx, "{", &handle);
-
-   The corresponding variable (named handle in the example above) will
-   contain the index of the structure parameter within the parameter set,
-   but the index cannot be used to retrieve the contents of the structure.
-   To retrieve the contents of the structure you can use function
-   struct_scan. The function gets the handle as the first parameter:
-rpc->struct_scan(handle, "sd", "str_attr", &str_val, "int_attr", &int_val);
-
-   The second parameter is the formatting string followed by pairs of
-   parameters. First parameter in each pair is the name of the attribute
-   to retrieve (string) and the second parameter in each pair is the
-   pointer to the variable to store the value of the parameter. The
-   function returns the number of parameters (name value pairs) read on
-   success and - number of parameters read so far on an error (just like
-   the scan function). The function also indicates an error if a requested
-   attribute is missing in the structure.
-
-1.2.3.3. Retrieving Parameters Example
-
-   Example 3. Retrieving Parameters
-static void rpc_delete_contact(rpc_t* rpc, void* ctx)
-{
-    str aor, contact;
-    char* table;
-    void *handle;
-    int   expires;
-    double q;
-
-    if (rpc->scan(ctx, "sS{", &table, &aor, &handle) < 0) {
-        /* Reply is set automatically by scan upon failure,
-         * no need to do anything here
-         */
-        return;
-    }
-
-    if (rpc->struct_scan(handle, "Sdf", "Contact", &contact,
-                                        "Expires", &expires,
-                                        "Q",       &q        ) < 0) {
-        /* Reply is set automatically by struct_scan upon failure,
-         * no need to do anything here
-         */
-        return;
-    }
-
-    /* Process retrieved parameters here */
-}
-
-/* variable number of parameters:
-   echo back all the parameters, string type required */
-static void core_prints(rpc_t* rpc, void* c)
-{
-        char* string = 0;
-        while((rpc->scan(c, "*s", &string)>0))
-                rpc->add(c, "s", string);
-}
-
-/* variable number of parameters and auto conversion:
-   echo back all the parameters, works with any type (everything is
-   internally converted to string, notice the '.' modifier) */
-static void core_echo(rpc_t* rpc, void* c)
-{
-        char* string = 0;
-        while((rpc->scan(c, "*.s", &string)>0))
-                rpc->add(c, "s", string);
-}
-
-1.2.4. Building Reply
-
-   The RPC API contains several functions that can be used to modify
-   and/or send a reply. The functions use formatting strings and parameter
-   lists just like functions described in Section 1.2.3, "Getting
-   Parameters".
-
-   Each RPC function call must return a reply. The reply can be either a
-   failure reply or success reply. Failure replies contain only the status
-   code and reason phrase. Success replies can have arbitrary amount of
-   data attached to them. Status codes 3xx, 4xx, 5xx, and 6xx indicate
-   failures. Status code 2xx indicates success.
-
-   The default reply is 200 OK with no data attached to it. This is what
-   will be returned by the RPC transport module if you do not call any of
-   the reply-related functions described in this section.
-
-   Example 4. Sending default reply
-static void rpc_dummy(rpc_t* rpc, void *ctx)
-{
-  /* 200 OK with no data will be returned */
-}
-
-1.2.4.1. fault
-
-   You can use fault function to indicate that an error has occurred on
-   the server to the caller. The function accepts two parameters. The
-   first parameter is the status code and the second parameter is the
-   reason phrase.
-static void rpc_my_function(rpc_t* rpc, void *ctx)
-{
-    rpc->fault(ctx, 600, "Not Yet Implemented");
-}
-
-   If your function first creates some result using add, or printf
-   functions then all the data will be lost once you call fault function.
-   Failure replies must not contain any data:
-static void rpc_my_function(rpc_t* rpc, void *ctx)
-{
-    rpc->add(ctx, "s", "result1");
-    rpc->add(ctx, "d", variable);
-
-    /* Reply created by previous functions will be
-     * deleted and a failure reply 600 Not Yet Implemented
-     * will be created instead
-     */
-    rpc->fault(ctx, 600, "Not Yet Implemented");
-
-    /* You can also add data here, but that will have no
-     * effect
-     */
-    rpc->add(ctx, "s", "result2");
-}
-
-   Similarly you can also call add or printf functions after calling
-   fault, in this case they will have no effect:
-static void rpc_my_function(rpc_t* rpc, void *ctx)
-{
-    rpc->fault(ctx, 600, "Not Yet Implemented");
-
-    /* You can also add data here, but that will have no
-     * effect and only 600 Not Yet Implemented will be returned
-     */
-    rpc->add(ctx, "s", "result2");
-}
-
-1.2.4.2. send
-
-   RPC functions can use function send to explicitly send the reply. Each
-   RPC function call generates exactly one reply. No reply will be sent
-   after the function finishes if it already sent the reply using send
-   function explicitly. This function is especially useful if the RPC
-   function needs to perform some (potentially destructive) actions after
-   the reply has been sent.
-
-   Example 5. Kill the server
-static void core_kill(rpc_t* rpc, void *ctx)
-{
-    int sig_no;
-
-    if (rpc->scan(ctx, "d", &sig_no) < 0) return;
-    rpc->send(ctx, );     /* First send a reply */
-    kill(0, sig_no); /* Then kill the server */
-}
-
-1.2.4.3. add
-
-   Function add can be used to add arbitrary data to the result set. Its
-   parameters and use are analogical to scan function described in
-   Section 1.2.3.1, "scan". The first parameter of the function is the
-   formatting string that determines the types of additional parameters:
-static void rpc_func(rpc_t* rpc, void *ctx)
-{
-    str str_result;
-    int int_result;
-    void *handle;
-    double float_result;
-
-    if (rpc->add(ctx, "Sdf{", &str_result, int_result, float_result, &handle) <
-0) return;
-}
-
-   Naturally you can call this function several times, adding only one
-   piece of data at a time. The function returns 0 on success and -1 on an
-   error. In case of an error the reply is set automatically with
-   corresponding error code and reason phrase.
-
-   The last character in the formatting string of the function above
-   indicates that the last data to be added will be a structure. This
-   deserves some clarification. In this case, the function will create an
-   empty structure and the handle to the newly created structure will be
-   stored in handle variable (hence the last parameter is pointer to an
-   integer). In this particular example parameters str_result, int_result,
-   and float_result will be used for reading while parameter handle will
-   be used for writing by the function.
-
-   You can set the attributes of the newly created structure using
-   struct_add function described in Section 1.2.4.5, "struct_add".
-
-1.2.4.4. rpl_printf
-
-   rpl_printf is a convenience function. The function adds data of type
-   string to the result set. The first parameter of the function is again
-   a formatting string, but this time it is standard printf-like
-   formatting string:
-if (rpc->rpl_printf(ctx, "Unable to delete %d entries from table %s", num_entrie
-s, table_name) < 0) return;
-
-   The return value of the function is the same as of add function.
-
-1.2.4.5. struct_add
-
-   Function struct_add can be used to add attributes to a structure
-   (created previously by add function). The first parameter of the
-   function is handle obtained through add function, the second parameters
-   is formatting string that determines the types of attributes to be
-   added. There must be two parameters per each character in the
-   formatting string, the first one is the name of the attribute, the
-   second parameter is the value of the attribute. If a parameter with
-   such a name already exist in the structure then it will be overwritten
-   with the new value.
-static void rpc_func(rpc_t* rpc, void *ctx)
-{
-    void *handle;
-
-        /* Create empty structure and obtain its handle */
-    if (rpc->add(ctx, "{", &handle) < 0) return;
-        /* Fill-in the structure */
-    if (rpc->struct_add(handle, "sd", "attr1", str_val,
-                                      "attr2", int_val ) < 0)
-        return;
-}
-
-   The function returns -1 on an error (and sets the status code and
-   reason phrase of the reply accordingly) and 0 on success.
-
-1.2.5. Real World Example
-
-   The following example illustrates the use of most of the functions from
-   the API together:
-
-   Example 6. Real World Example RPC Function
-static void rpc_register(rpc_t* rpc, void *ctx)
-{
-    char* domain;
-    str aor;
-    contact_t contact, new_contact;
-    void *handle;
-
-        /* Extract the domain, address of record from the request */
-    if (rpc->scan(ctx, "sS{", &domain, &aor, &handle) < 0) return;
-        /* Extract the structure describing the contact to be processed */
-    if (rpc->struct_scan(handle, "Sdf", "Contact", &contact.c,
-                                        "Expires", &contact.expires,
-                                        "Q",       &contact.q       ) < 0)
-        return;
-
-        /* Process the contact, new_contact will contain updated value after pro
-cessing */
-    if (process_contact(domain, &aor, &new_contact, &contact) < 0) {
-           /* Processing failed, indicate the failure to the caller */
-        rpc->fault(ctx, 500, "Error While Processing Contact");
-        return;
-    }
-
-        /* Return the domain and the address of record */
-    rpc->add(ctx, "sS{", &domain, &aor, &handle) < 0) return;
-        /* And also add the new values for contact, q, and expires parameters */
-    rpc->struct_add(handle, "Sdf", "Contact", &new_contact.c,
-                                   "Expires", &new_contact.expires,
-                                   "Q",       &new_contact.q       );
-}
-
-1.3. Client Examples
-
-     * sercmd (C application that uses the binrpc interface implemented by
-       the ctl module).
-     * ser_ctl (python application that uses the XML-RPC interface
-       implemented by the xmlrpc module).
-     * serweb (php application that can use the XML-RPC interface to call
-       ser functions).
-
-1.4. Implementing New Transports
-
-   To be done.
-
-   Examples:
-     * ctl
-     * xmlrpc
-
-1.5. Examples using xmlrpc
-
-   See the xmlrpc module documentation: modules/xmlrpc/README.
diff --git a/doc/rpc/ser_rpc.xml b/doc/rpc/ser_rpc.xml
deleted file mode 100644
index 73b9f08..0000000
--- a/doc/rpc/ser_rpc.xml
+++ /dev/null
@@ -1,915 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
-	"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
-	[ <!ENTITY % local.common.attrib
-	 "xmlns:xi CDATA #FIXED 'http://www.w3.org/2001/XInclude'">]
->
-
-<section id="rpc.main" xmlns:xi="http://www.w3.org/2001/XInclude">
-    <!--
-    <sectioninfo>
-        <releaseinfo role="cvs">$Revision$</releaseinfo>
-        <pubdate role="cvs">$Date$</pubdate>
-    </sectioninfo>
-    -->
- 
-    <title>
-	RPC Control Interface
-    </title>
-
-	<section id="rpc.overview">
-	<title>Overview of Operation</title>
-	<para>
-		The RPC (Remote Procedure Call) interface is an interface for
-		communicating with external applications. Using it an external
-		application can call a function or procedure that will be executed
-		inside SIP Server (SER or Kamailio). Function parameters are
-		supported as well as returning multiple values as results.
-	</para>
-	<para>
-		By itself RPC consists of two APIs, one for defining RPC functions
-		in a transport independent way (called the rpc module api) and one
-		for implementing RPC transports.
-	</para>
-	<para>
-		The RPC transports are implemented by writting a RPC
-		transport module. The most used transport modules are
-		<ulink url='http://www.kamailio.org/docs/modules/devel/modules/ctl/ctl.html'>
-		<emphasis>ctl</emphasis>
-		</ulink>,
-		<ulink url='http://www.kamailio.org/docs/modules/devel/modules/xmlrpc/xmlrpc.html'>
-		<emphasis>xmlrpc</emphasis>
-		</ulink>
-		and
-		<ulink url='http://www.kamailio.org/docs/modules/devel/modules/jsonrpc-s/jsonrpc-s.html'>
-		<emphasis>jsonrpc-s</emphasis>
-		</ulink>.
-	</para>
-	<para>
-		ctl implements a proprietary fast and space efficient
-		 RPC encoding over different protocols (unix sockets, UDP, TCP, fifo).
-	</para>
-	<para>
-		xmlrpc uses the de-facto XML-RPC standard encoding
-		 (over HTTP TCP or TLS).
-	</para>
-	<para>
-		jsonrpc-s uses the de-facto JSON-RPC standard encoding
-		 (over HTTP TCP or TLS).
-	</para>
-	<para>
-		 For more information about the existing transport modules, please 
-		 refer to their documentation.
-	</para>
-	<para>
-		When writing a RPC procedure or function, one needs only use the
-		RPC API and it will work automatically with all the transports and
-		encodings. One needs only to load the desired RPC transport module
-		(e.g. xmlrpc).
-	</para>
-	<para>
-		The RPC interface (or API) was created in such a way that would allow
-		supporting XML-RPC (because XML-RPC is a de-facto standard), while in
-		the same time being very easy to use.
-	</para>
-	</section>
-
-    <section id="rpc.module_api">
-	<title>Module API</title>
-	<para>
-	    Each module can export RPC functions just like it can export
-	    parameters and functions to be called from the script. Whenever SIP server
-	    receives an RPC request, it will search through the list of
-	    exported RPC functions and the function with matching name will be
-	    executed. A couple of essential RPC functions are also embedded into
-	    the SIP server core.
-	</para>
-	<para>
-	    This section gives a detailed overview of the whole RPC API. <xref
-	    linkend="rpc.rpc_functions"/> describes the prototype and
-	    conventions used in RPC functions. <xref linkend="rpc.data_types"/>
-	    gives a detailed overview of available data types that can be used
-	    in function parameters and return value. <xref
-	    linkend="rpc.getting_parameters"/> describes functions of the RPC
-	    API that can be used to retrieve parameters of the function, and
-	    finally <xref linkend="rpc.creating_result"/> describes functions of
-	    the API that can be used to build the result value that will be
-	    sent in the reply to the caller.
-	</para>
-	<para>
-	    The whole RPC API is described in header file
-	    <filename>sip_router/rpc.h</filename>.  This file defines the set
-	    of functions that must be implemented by RPC transport modules, as
-	    described in <xref linkend="rpc.new_transport"/>, prototypes of RPC
-	    functions and structures used for the communication between RPC
-	    transport modules and ordinary modules exporting RPC functions.
-	</para>
-	<section id="rpc.rpc_functions">
-	    <title>RPC Functions</title>
-	    <para>
-		RPC functions are standard C functions with the following
-		prototype:
-		<programlisting>
-typedef void (*rpc_function_t)(rpc_t* rpc, void* ctx);
-		</programlisting>
-		RPC functions take two parameters, first parameter is a pointer
-		to rpc_t structure and the context. The rpc_t structure
-		contains references to all API functions available to the RPC
-		function as well as all data necessary to create the
-		response. RPC functions do not return any value, instead the
-		return value is created using functions from the context. The
-		motivation for this decision is the fact that RPC functions
-		should always return a response and even the API functions
-		called from RPC functions should have the possibility to
-		indicate an error (and should not rely on RPC functions doing so).
-	    </para>
-	    <para>
-		If no reply is sent explicitely, the RPC transport module will
-		automatically send a "success" reply (e.g. 200 OK for XML-RPC)
-		when the RPC function finishes.
-		If no values are added to the response, the reponse will be an
-		empty "success" reply (e.g. a 200 OK with empty body for
-		XML-RPC).
-		RPC API functions will automatically send an error reply upon a
-		failure.
-	    </para>
-	    <para>
-		Each RPC function has associated an array of documentation
-		strings. The purpose of the documentation strings is to give a
-		short overview of the function, accepted parameters, and format
-		of the reply. By convention the name of the documentation string
-		array is same as the name of the function with "_doc" suffix.
-	    </para>
-	    <para>
-		Each module containing RPC functions has to export all the
-		RPC functions to SIP server core in order to make them visible to the RPC
-		transport modules.
-		The export process involves a <emphasis>rpc_export_t</emphasis> 
-		structure (either by itself or in an array):
-		<programlisting>
-<emphasis>
-typedef struct rpc_export {
-    const char* name;        /* Name of the RPC function (null terminated) */
-    rpc_function_t function; /* Pointer to the function */
-    const char** doc_str;    /* Documentation strings, method signature and description */
-    unsigned int flags;      /* Various flags, reserved for future use */
-} rpc_export_t;
-</emphasis>
-		</programlisting>
-		</para>
-		<para>
-		The <varname>flags</varname> attribute of the
-		<varname>rpc_export</varname> structure is reserved for future
-		use and is currently unused.
-	    </para>
-		<para>
-		There are several ways of exporting the RPC functions to the SIP server core:
-		<itemizedlist>
-			<listitem><para>
-				register a null terminated array of rpc_export_t structures
-				using the <function>rpc_register_array()</function> function
-				(defined in rpc_lookup.h), from the module init function
-				(mod_init()). This is the <emphasis>recommended</emphasis>
-				method for all the new modules.
-				<example><title>usrloc RPC Exports Declaration</title>
-					<para>
-					The <varname>rpc_export_t</varname> array for the modules_s/usrloc
-					module looks like:
-					</para>
-					<programlisting>
-<emphasis>
-rpc_export_t ul_rpc[] = {
-    {"usrloc.statistics",      rpc_stats,           rpc_stats_doc,          0},
-    {"usrloc.delete_aor",      rpc_delete_aor,      rpc_delete_aor_doc,     0},
-    {"usrloc.delete_contact",  rpc_delete_contact,  rpc_delete_contact_doc, 0},
-    {"usrloc.dump",            rpc_dump,            rpc_dump_doc,           0},
-    {"usrloc.flush",           rpc_flush,           rpc_flush_doc,          0},
-    {"usrloc.add_contact",     rpc_add_contact,     rpc_add_contact_doc,    0},
-    {"usrloc.show_contacts",   rpc_show_contacts,   rpc_show_contacts_doc,  0},
-    {0, 0, 0, 0}
-};
-</emphasis>
-					</programlisting>
-					<para>
-					To register it from the module init function one would use
-					something similar to:
-					</para>
-					<programlisting>
-	if (rpc_register_array(ul_rpc) != 0) {
-		ERR("failed to register RPC commands\n");
-		return -1;
-	}
-					</programlisting>
-				</example>
-			</para></listitem>
-			<listitem><para>
-				register RPCs one by one using the
-				<function>rpc_register_function()</function>
-				(defined in rpc_lookup.h), from the module init function.
-			</para></listitem>
-			<listitem><para>
-				register a null terminated array of rpc_export_t structures
-				using the SIP server module interface SER_MOD_INTERFACE (specific
-				for SER flavour).
-				For this purpose, the
-				<varname>module_exports</varname> structure of SIP server module API
-				contains a new attribute called <varname>rpc_methods</varname>:
-				<programlisting>
-struct module_exports {
-    char* name;                 /* null terminated module name */	
-    cmd_export_t* cmds;         /* null terminated array of the exported commands */
-    <emphasis>rpc_export_t* rpc_methods;</emphasis>  /* null terminated array of exported rpc methods */
-    param_export_t* params;     /* null terminated array of the exported module parameters */
-    
-    init_function init_f;         /* Initialization function */
-    response_function response_f; /* function used for responses */
-    destroy_function destroy_f;   /* function called upon shutdown */
-    onbreak_function onbreak_f;
-    child_init_function init_child_f;  /* function called by all processes after the fork */
-};
-				</programlisting>
-				<varname>rpc_methods</varname> is a pointer to an array of
-				rpc_export_t structures. The last element of the array is a
-				bumper containing zeroes in all the attributes of the
-				structure. The following program listing shows the exported RPC
-				functions of the modules_s/usrloc module, using the rpc_export_t array
-				<emphasis>ul_rpc</emphasis> defined above, in the 
-				rpc_register_array() example:
-				<example><title>usrloc Module Exports Declaration</title>
-					<programlisting>
-struct module_exports exports = {
-    "usrloc",
-    cmds,      /* Exported functions */ 
-    <emphasis>ul_rpc</emphasis>,    /* RPC methods */
-    params,    /* Export parameters */ 
-    mod_init,  /* Module initialization function */ 
-    0,         /* Response function */ 
-    destroy,   /* Destroy function */ 
-    0,         /* OnCancel function */ 
-    child_init /* Child initialization function */ };
-
-					</programlisting>
-				</example>
-				<note><para>
-					This mode works only with modules using the SER flavour module
-					interface. It does not work for kamailio modules and it
-					will probably not work for future sip-router modules. It is
-					safer and recommended to use instead the
-					<function>rpc_register_array()</function> function.
-				</para></note>
-			</para></listitem>
-		</itemizedlist>
-		</para>
-		<para>
-			By convention the name of every exported function consists of
-			two parts delimited by a dot. The first part is the name of the
-			module or SIP server subsystem this function belongs to. The second
-			part is the name of the function.
-		</para>
-	</section>
-
-	<section id="rpc.data_types">
-	    <title>Data Types</title>
-	    <para>
-		The RPC API defines several basic and 1 compound data type
-		that can be used in communication with the caller of RPC
-		functions. The RPC API uses formating strings to describe data
-		types. Each data type is described by exactly one character in
-		the formating string. For example, if an RPC function calls
-		function <function>add</function> of the RPC API and it passes
-		two parameters to it, the first one of type string and the
-		second one of type integer, the function parameters will look
-		like:
-		<programlisting>
-add("sd", string_param, int_param);
-		</programlisting>
-		Character "s" in the formating string tells to the function
-		that the 2nd parameter should be interpreted as string,
-		character "d" in the formating string tells to the function
-		that the 3rd parameter should be interpreted as signed integer.
-	    </para>
-	    <formalpara>
-		<title>Integer</title>
-		<para>
-		    Integer type represents a signed 32-bit
-		    integer. Corresponding character in the formating string is
-		    "d". This parameter can be stored in C-style variable with
-		    type <varname>int</varname>.
-		</para>
-	    </formalpara>
-	    <formalpara>
-		<title>Float</title>
-		<para>
-		    Float type represents a signed floating point
-		    number. Corresponding character in the formating string is
-		    "f". Data of this type can be stored in C-style variables
-		    of type <varname>double</varname>.
-		</para>
-	    </formalpara>
-	    <formalpara>
-		<title>String</title>
-		<para>
-		    String type represents a string of characters. The string
-		    may contain zeroes. This data type is represented by two
-		    characters in the formatting string, either "s" or "S". "s"
-		    indicates to the conversion function that the result should
-		    be stored in a variable of type <varname>char*</varname>
-		    and it should be zero terminated. "S" indicates to the
-		    conversion function that the result will be stored in
-		    a variable of type <varname>str</varname> which contains
-		    both the pointer to the beginning of the string and its
-		    length.
-		</para>
-	    </formalpara>
-	    <formalpara>
-		<title>Structure</title>
-		<para>
-		    Structure is the only compound data type currently defined
-		    in the API. A structure is a collection of attributes. Each
-		    attribute is identified using name (string) and each
-		    attribute can be one of the basic data types, that
-		    is integer, float, or string. Nesting of structures is not
-		    allowed (in other words, structure attributes cannot be of
-		    type struct again). Corresponding character in the
-		    formatting string is "{".
-		</para>
-	    </formalpara>
-		<formalpara>
-		<title>Optional parameters</title>
-		<para>
-			Optional parameters can be used, but only in the
-			<function>scan</function> function.  For optional parameters the
-			<function>scan</function> function will not automatically generate
-			a rpc fault if the input ends. Note that in this case the
-			<function>scan</function> will still return a negative value
-			(minus the number of parameters successfully read).
-			Optional parameters can be marked in the format string by
-			preceding the first optional parameter type with a "*".
-			All the parameters following a "*" are considered to be optional.
-			For example for the format string "ds*dds", the last 3 parameters
-			(2 ints and a string) are optional.
-		</para>
-		</formalpara>
-	    <table>
-		<title>Data Type Overview</title>
-		<tgroup cols="3">
-		    <tbody>
-			<row rowsep="1">
-			    <entry>Name</entry>
-			    <entry>Formating String Char</entry>
-			    <entry>C-Style Variable</entry>
-			</row>
-			<row>
-			    <entry>Integer</entry>
-			    <entry>d</entry>
-			    <entry>int</entry>
-			</row>
-			<row>
-			    <entry>Float</entry>
-			    <entry>f</entry>
-			    <entry>double</entry>
-			</row>
-			<row>
-			    <entry>String</entry>
-			    <entry>s</entry>
-			    <entry>char*</entry>
-			</row>
-			<row>
-			    <entry>String</entry>
-			    <entry>S</entry>
-			    <entry>str*</entry>
-			</row>
-			<row>
-				<entry>Optional modifier</entry>
-				<entry>*</entry>
-				<entry>marks all further parameters as optional</entry>
-			</row>
-			<row>
-				<entry>Autoconvert modifier</entry>
-				<entry>.</entry>
-				<entry>requires auto-conversion for the next parameter</entry>
-			</row>
-		    </tbody>
-		</tgroup>
-	    </table>
-	</section>
-
-	<section id="rpc.getting_parameters">
-	    <title>Getting Parameters</title>
-	    <para>
-		Each RPC function call can contain parameters. Parameters have
-		no name, their meaning is determined by their position in the
-		parameter set.
-		<note>
-		    <para>
-			You can pass all parameters to a function within a
-			structure if you want to make them position
-			independent. Then each parameter can be retrieved by
-			its name regardless of its position.
-		    </para>
-		</note>
-		There are two functions in the RPC API that can be used to
-		obtain function call parameters: <function>scan</function> and
-		<function>struct_scan</function>.
-	    </para>
-	    <section id="rpc.scan">
-		<title><function>scan</function></title>
-		<para>
-		    Function <function>scan</function> can be used to retrieve
-		    parameters from the parameter set. The function accepts
-		    variable number of parameters. The first parameter is the
-		    formatting string that determines the type of the
-		    parameters to be retrieved. Each parameter is represented by
-		    exactly one parameter type character in the string.
-			The variable part of parameters must contain as many pointers to C
-			variables as there are formatting non-modifiers characters in the
-			formatting string.
-		    <warning>
-			<para>
-			    The function will crash if you fail to provide
-			    enough parameters.
-			</para>
-		    </warning>
-		</para>
-		<para>
-			Besides characters representing parameter types, the formatting
-			string can contain two special modifiers: "*" and ".". The
-			modifiers do not have a correspondent in the variable part of the
-			parameters.
-		</para>
-		<para>
-			The meaning of "*" modifier is that any further parameters
-			(defined by other type characters in the formatting string) are
-			optional (they can be missing in the input and no rpc fault will
-			automatically be generated).
-		</para>
-		<para>
-			The '.' modifiers turns on type autoconversion for the next
-			parameter. This means that if the type of the next parameter 
-			differs from the type specified in the formatting string, the
-			parameter will be automatically converted to the formatting string
-			type (if possible) and if the automatic conversion succeeds, no
-			fault will be generated.
-		</para>
-		<para>
-			The function returns the number of parameters read on success
-			(a number greater or equal 0) and - (minus) the number of
-			parameters read on error (for example for an error after 
-			reading 2 parameters it will return -2).
-			When a failure occurs (incorrect parameter type or no more
-			parameters in the parameter set) the function will
-			return a negative number (- number of parameters read so far)
-			and it will also automatically change the reply that will be
-			sent to the caller to indicate that a failure has occurred on 
-			the server (unless the "*" is used and the error is lack
-			of more parameters).
-		</para>
-		<para>
-			The prototype of the function is:
-		    <programlisting>
-int scan((void* ctx, char* fmt, ...)
-		    </programlisting>
-		    It is possible to either call the function once to scan all
-		    the parameters:
-		    <programlisting>
-rpc->scan(ctx, "sdf", &string_val, &int_val, &double_val);
-		    </programlisting>
-		    Or you can call the same function several times and it will
-		    continue where it left off previously:
-		    <programlisting>
-rpc->scan(ctx, "s", &string_val);
-rpc->scan(ctx, "d", &int_val);
-rpc->scan(ctx, "f", &double_val);
-		    </programlisting>
-		</para>
-		<para>
-		</para>
-	    </section>
-	    <section>
-		<title><function>struct_scan</function></title>
-		<para>
-			Function <function>struct_scan</function> can be used to
-			retrieve named attributes from a parameter of type
-			structure.
-			<note><para>
-			This function is obsolete and not implemented by all the
-			rpc transports (e.g.: ctl / binrpc). Consider using the normal
-			<function>scan</function> instead.
-			</para></note>
-			When retrieving a structure parameter from the
-			parameter set:
-		    <programlisting>
-rpc->scan(ctx, "{", &handle);
-		    </programlisting>
-		    The corresponding variable (named 
-		    <varname>handle</varname> in the example above) will contain
-		    the index of the structure parameter within the parameter
-		    set, but the index cannot be used to retrieve the contents
-		    of the structure. To retrieve the contents of the structure
-		    you can use function <function>struct_scan</function>. The
-		    function gets the handle as the first parameter:
-		    <programlisting>
-rpc->struct_scan(handle, "sd", "str_attr", &str_val, "int_attr", &int_val);
-		    </programlisting>
-		    The second parameter is the formatting string followed by
-		    pairs of parameters. First parameter in each pair is the
-		    name of the attribute to retrieve (string) and the second
-		    parameter in each pair is the pointer to the variable to
-		    store the value of the parameter. The function returns the
-			number of parameters (name value pairs) read on
-		    success and - number of parameters read so far on an error
-			(just like the <function>scan</function> function). The function
-			also indicates an error if a requested attribute is missing in
-		    the structure.
-		</para>
-	    </section>
-	
-		<section><title>Retrieving Parameters Example</title>
-		<example>
-		<title>Retrieving Parameters</title>
-		<programlisting>
-<![CDATA[
-static void rpc_delete_contact(rpc_t* rpc, void* ctx)
-{
-    str aor, contact;
-    char* table;
-    void *handle;
-    int   expires;
-    double q;
-
-    if (rpc->scan(ctx, "sS{", &table, &aor, &handle) < 0) {
-        /* Reply is set automatically by scan upon failure,
-         * no need to do anything here
-         */
-        return;
-    }
-
-    if (rpc->struct_scan(handle, "Sdf", "Contact", &contact,
-                                        "Expires", &expires,
-                                        "Q",       &q        ) < 0) {
-        /* Reply is set automatically by struct_scan upon failure,
-         * no need to do anything here
-         */
-        return;
-    }
-
-    /* Process retrieved parameters here */
-}
-
-/* variable number of parameters:
-   echo back all the parameters, string type required */
-static void core_prints(rpc_t* rpc, void* c)
-{
-	char* string = 0;
-	while((rpc->scan(c, "*s", &string)>0))
-		rpc->add(c, "s", string);
-}
-
-/* variable number of parameters and auto conversion:
-   echo back all the parameters, works with any type (everything is 
-   internally converted to string, notice the '.' modifier) */
-static void core_echo(rpc_t* rpc, void* c)
-{
-	char* string = 0;
-	while((rpc->scan(c, "*.s", &string)>0))
-		rpc->add(c, "s", string);
-}
-
-]]>
-		</programlisting>
-	    </example>
-		</section>
-	</section>
-
-	<section id="rpc.creating_result">
-	    <title>Building Reply</title>
-	    <para>
-		The RPC API contains several functions that can be used to
-		modify and/or send a reply. The functions use formatting
-		strings and parameter lists just like functions described in
-		<xref linkend="rpc.getting_parameters"/>.
-	    </para>
-	    <para>
-		Each RPC function call must return a reply. The reply can be
-		either a failure reply or success reply. Failure replies
-		contain only the status code and reason phrase. Success
-		replies can have arbitrary amount of data attached to
-		them. Status codes 3xx, 4xx, 5xx, and 6xx indicate
-		failures. Status code 2xx indicates success.
-	    </para>
-	    <para>
-		The default reply is 200 OK with no data attached to it. This
-		is what will be returned by the RPC transport module if you do
-		not call any of the reply-related functions described in this
-		section.
-		<example>
-		    <title>Sending default reply</title>
-		    <programlisting>
-<![CDATA[
-static void rpc_dummy(rpc_t* rpc, void *ctx)
-{
-  /* 200 OK with no data will be returned */
-}
-]]>
-		    </programlisting>
-		</example>
-	    </para>
-	    <section>
-		<title>fault</title>
-		<para>
-		    You can use <function>fault</function> function to indicate
-		    that an error has occurred on the server to the caller. The
-		    function accepts two parameters. The first parameter is the
-		    status code and the second parameter is the reason phrase.
-		    <programlisting>
-<![CDATA[
-static void rpc_my_function(rpc_t* rpc, void *ctx)
-{
-    rpc->fault(ctx, 600, "Not Yet Implemented");
-}
-]]>
-		    </programlisting>
-		    If your function first creates some result using
-		    <function>add</function>, or <function>printf</function>
-		    functions then all the data will be lost once you call
-		    <function>fault</function> function. Failure replies must
-		    not contain any data:
-		    <programlisting>
-<![CDATA[
-static void rpc_my_function(rpc_t* rpc, void *ctx)
-{
-    rpc->add(ctx, "s", "result1");
-    rpc->add(ctx, "d", variable);
-
-    /* Reply created by previous functions will be
-     * deleted and a failure reply 600 Not Yet Implemented
-     * will be created instead
-     */
-    rpc->fault(ctx, 600, "Not Yet Implemented");
-
-    /* You can also add data here, but that will have no
-     * effect
-     */
-    rpc->add(ctx, "s", "result2");
-}
-]]>
-		    </programlisting>
-		    Similarly you can also call <function>add</function> or
-		    <function>printf</function> functions after calling
-		    <function>fault</function>, in this case they will have no
-		    effect:
-		    <programlisting>
-<![CDATA[
-static void rpc_my_function(rpc_t* rpc, void *ctx)
-{
-    rpc->fault(ctx, 600, "Not Yet Implemented");
-
-    /* You can also add data here, but that will have no
-     * effect and only 600 Not Yet Implemented will be returned
-     */
-    rpc->add(ctx, "s", "result2");
-}
-]]>
-		    </programlisting>
-		</para>
-	    </section>
-	    <section>
-		<title>send</title>
-		<para>
-		    RPC functions can use function <function>send</function> to
-		    explicitly send the reply. Each RPC function call generates
-		    exactly one reply. No reply will be sent after the function
-		    finishes if it already sent the reply using
-		    <function>send</function> function explicitly. This
-		    function is especially useful if the RPC function needs to
-		    perform some (potentially destructive) actions after the
-		    reply has been sent.
-		</para>
-		<example>
-		    <title>Kill the server</title>
-		    <programlisting>
-<![CDATA[
-static void core_kill(rpc_t* rpc, void *ctx)
-{
-    int sig_no;
-
-    if (rpc->scan(ctx, "d", &sig_no) < 0) return;
-    rpc->send(ctx, );     /* First send a reply */
-    kill(0, sig_no); /* Then kill the server */
-}
-]]>
-		    </programlisting>
-		</example>
-		
-	    </section>
-	    <section>
-		<title>add</title>
-		<para>
-		    Function <function>add</function> can be used to add
-		    arbitrary data to the result set. Its parameters and use
-		    are analogical to <function>scan</function> function
-		    described in <xref linkend="rpc.scan"/>. The first
-		    parameter of the function is the formatting string that
-		    determines the types of additional parameters:
-		    <programlisting>
-<![CDATA[
-static void rpc_func(rpc_t* rpc, void *ctx)
-{
-    str str_result;
-    int int_result;
-    void *handle;
-    double float_result;
-
-    if (rpc->add(ctx, "Sdf{", &str_result, int_result, float_result, &handle) < 0) return;
-}
-]]>
-		    </programlisting>
-		    Naturally you can call this function several times, adding
-		    only one piece of data at a time. The function returns 0 on
-		    success and -1 on an error. In case of an error the reply
-		    is set automatically with corresponding error code and
-		    reason phrase.
-		</para>
-		<para>
-		    The last character in the formatting string of the function
-		    above indicates that the last data to be added will be a
-		    structure. This deserves some clarification. In this case,
-		    the function will create an empty structure and the handle
-		    to the newly created structure will be stored in
-		    <varname>handle</varname> variable (hence the last
-		    parameter is pointer to an integer). In this particular
-		    example parameters <varname>str_result</varname>,
-		    <varname>int_result</varname>, and
-		    <varname>float_result</varname> will be used for reading
-		    while parameter <varname>handle</varname> will be used for
-		    writing by the function.
-		</para>
-		<para>
-		    You can set the attributes of the newly created structure
-		    using <function>struct_add</function> function described in
-		    <xref linkend="rpc.struct_add"/>.
-		</para>
-	    </section>
-	    <section>
-		<title>rpl_printf</title>
-		<para>
-		    <varname>rpl_printf</varname> is a convenience function. The
-		    function adds data of type string to the result set. The
-		    first parameter of the function is again a formatting
-			string, but this time it is standard
-			<function>printf</function>-like formatting string:
-		    <programlisting>
-<![CDATA[
-if (rpc->rpl_printf(ctx, "Unable to delete %d entries from table %s", num_entries, table_name) < 0) return;
-]]>
-		    </programlisting>
-		    The return value of the function is the same as of
-		    <function>add</function> function.
-		</para>
-	    </section>
-	    <section id="rpc.struct_add">
-		<title>struct_add</title>
-		<para>
-		    Function <function>struct_add</function> can be used to add
-		    attributes to a structure (created previously by
-		    <function>add</function> function). The first parameter of
-		    the function is handle obtained through
-		    <function>add</function> function, the second parameters is
-		    formatting string that determines the types of attributes
-		    to be added. There must be two parameters per each
-		    character in the formatting string, the first one is the
-		    name of the attribute, the second parameter is the value
-		    of the attribute. If a parameter with such a name already
-		    exist in the structure then it will be overwritten with the
-		    new value.
-		    <programlisting>
-<![CDATA[
-static void rpc_func(rpc_t* rpc, void *ctx)
-{
-    void *handle;
-
-        /* Create empty structure and obtain its handle */
-    if (rpc->add(ctx, "{", &handle) < 0) return;
-        /* Fill-in the structure */
-    if (rpc->struct_add(handle, "sd", "attr1", str_val,
-                                      "attr2", int_val ) < 0)
-        return;
-}
-]]>
-		    </programlisting>
-		    The function returns -1 on an error (and sets the status
-		    code and reason phrase of the reply accordingly) and 0 on success.
-		</para>
-	    </section>
-	</section>
-
-	<section>
-	    <title>Real World Example</title>
-	    <para>
-		The following example illustrates the use of most of the
-		functions from the API together:
-	    </para>
-	    <example>
-		<title>Real World Example RPC Function</title>
-		<programlisting>
-<![CDATA[
-static void rpc_register(rpc_t* rpc, void *ctx)
-{
-    char* domain;
-    str aor;
-    contact_t contact, new_contact;
-    void *handle;
-
-        /* Extract the domain, address of record from the request */
-    if (rpc->scan(ctx, "sS{", &domain, &aor, &handle) < 0) return;
-        /* Extract the structure describing the contact to be processed */
-    if (rpc->struct_scan(handle, "Sdf", "Contact", &contact.c,
-                                        "Expires", &contact.expires,
-                                        "Q",       &contact.q       ) < 0)
-        return;
-
-        /* Process the contact, new_contact will contain updated value after processing */
-    if (process_contact(domain, &aor, &new_contact, &contact) < 0) {
-           /* Processing failed, indicate the failure to the caller */
-        rpc->fault(ctx, 500, "Error While Processing Contact");
-        return;
-    }
-
-        /* Return the domain and the address of record */
-    rpc->add(ctx, "sS{", &domain, &aor, &handle) < 0) return;
-        /* And also add the new values for contact, q, and expires parameters */
-    rpc->struct_add(handle, "Sdf", "Contact", &new_contact.c,
-                                   "Expires", &new_contact.expires,
-                                   "Q",       &new_contact.q       );
-}
-]]>
-		</programlisting>
-	    </example>
-	</section>
-    </section>
-
-	<section id="rpc.client_examples">
-	<title>Client Examples</title>
-	<para>
-	<itemizedlist>
-		<listitem><para>
-		<emphasis>sercmd</emphasis> (C application that uses the
-		<emphasis>binrpc</emphasis> interface implemented by the
-		<emphasis>ctl</emphasis> module).
-		</para></listitem>
-		<listitem><para>
-		<emphasis>ser_ctl</emphasis> (python application that uses the
-		<emphasis>XML-RPC</emphasis> interface implemented by the
-		<emphasis>xmlrpc</emphasis>
-		module).
-		</para></listitem>
-		<listitem><para>
-		<emphasis>serweb</emphasis> (php application that can use
-		the <emphasis>XML-RPC</emphasis> interface to call ser 
-		functions).
-		</para></listitem>
-	</itemizedlist>
-	</para>
-	</section>
-
-    <section id="rpc.new_transport">
-	<title>Implementing New Transports</title>
-	<remark>
-	To be done.
-	</remark>
-	<!-- TODO:
-	- create a new module
-	- take a look at sip_router/rpc.h
-	- implement all functions in that header field
-	- no garbage collection in rpc functions, the module needs to keep
-	track of all allocated data
-	- return value default to true
-	- parameter type conflict is an error
-	- missing struct attribute is an error
-	- always send a reply, prepare replies so that you do not have to
-	allocate memory at runtime
-	- str strings do not have to be zero terminated
-	- no structure/array nesting allowed
-	- printf creates string attribute
-        -->
-	<para>
-		Examples:
-		<itemizedlist>
-			<listitem><para>
-				<emphasis>ctl</emphasis>
-			</para></listitem>
-			<listitem><para>
-				<emphasis>xmlrpc</emphasis>
-			</para></listitem>
-		</itemizedlist>
-	</para>
-    </section>
-
-<section id="rpc.xmlrpc_examples">
-	<title>Examples using xmlrpc</title>
-	<para>See the <varname>xmlrpc</varname> module documentation:
-	<ulink url='http://sip-router.org/docbook/sip-router/branch/master/modules/xmlrpc/xmlrpc.html'>modules/xmlrpc/README</ulink>.
-	</para>
-</section>
-
-</section>
diff --git a/doc/ser.txt b/doc/ser.txt
index ee77b52..ee22c99 100644
--- a/doc/ser.txt
+++ b/doc/ser.txt
@@ -1,5 +1,3 @@
-$Id$
-
 iptel.org SIP Express Router (SER) is a high-performance, 
 configurable, free server implementing Session Initiation 
 Protocol (SIP, RFC3216). SIP is a signaling protocol that 
diff --git a/doc/sr-coding-style.txt b/doc/sr-coding-style.txt
index eedcf30..61f2a69 100644
--- a/doc/sr-coding-style.txt
+++ b/doc/sr-coding-style.txt
@@ -1,6 +1,4 @@
-# $Id$
-#
-# SIP-router Coding Style
+# Kamailio Coding Style
 #
 #  2004-06-07  Andrei Pelinescu - Onciul <pelinescu-onciul at fokus.franhofer.de>
 
@@ -47,7 +45,7 @@ Doxygen
 -------
 - try to always add doxygen comments to functions and variables declared in your code. 
   Especially remember to document public functions, functions and structures
-  that are part of the SIP-router API.
+  that are part of the Kamailio API.
 - each file needs a declaration of the purpose of the file in the \file section
 
 If you are editing someone elses code, try to use his coding conventions
diff --git a/doc/stylesheets/dbschema_k/xsl/common.xsl b/doc/stylesheets/dbschema_k/xsl/common.xsl
index 060127e..67f624f 100644
--- a/doc/stylesheets/dbschema_k/xsl/common.xsl
+++ b/doc/stylesheets/dbschema_k/xsl/common.xsl
@@ -41,6 +41,17 @@
     <xsl:template match="text()|@*"/>
     <xsl:template match="text()|@*" mode="drop"/>
 
+    <xsl:template name="quotechar">
+	<xsl:choose>
+	    <xsl:when test="$db='mysql'">
+			<xsl:text>`</xsl:text>
+	    </xsl:when>
+	    <xsl:otherwise>
+			<xsl:text></xsl:text>
+		</xsl:otherwise>
+	</xsl:choose>
+    </xsl:template>
+
     <!-- Return the name of the context element, first look for a database
          specific name, use the common name if no database-specific name
          is found.
diff --git a/doc/stylesheets/dbschema_k/xsl/sql.xsl b/doc/stylesheets/dbschema_k/xsl/sql.xsl
index 8b15a4f..ba55a5e 100644
--- a/doc/stylesheets/dbschema_k/xsl/sql.xsl
+++ b/doc/stylesheets/dbschema_k/xsl/sql.xsl
@@ -55,7 +55,9 @@
 	<xsl:apply-templates select="version"/>
 
 	<xsl:text>CREATE TABLE </xsl:text>
+	<xsl:call-template name="quotechar"/>
 	<xsl:value-of select="$table.name"/>
+	<xsl:call-template name="quotechar"/>
 	<xsl:text> (&#x0A;</xsl:text>
 
 	<!-- Process all columns -->
@@ -173,7 +175,9 @@
 
     <xsl:template match="column">
 	<xsl:text>    </xsl:text>
+	<xsl:call-template name="quotechar"/>
 	<xsl:call-template name="get-name"/>
+	<xsl:call-template name="quotechar"/>
 	<xsl:text> </xsl:text>
 
 	<xsl:call-template name="column.type"/>
@@ -245,9 +249,11 @@
 <!-- ################ COLREF ################  -->
 
     <xsl:template match="colref">
+	<xsl:call-template name="quotechar"/>
 	<xsl:call-template name="get-column-name">
 	    <xsl:with-param name="select" select="@linkend"/>
 	</xsl:call-template>
+	<xsl:call-template name="quotechar"/>
 	<xsl:if test="not(position()=last())">
 	    <xsl:text>, </xsl:text>
 	</xsl:if>
diff --git a/doc/tcp_tunning.txt b/doc/tcp_tunning.txt
index aa72a3c..39097d5 100644
--- a/doc/tcp_tunning.txt
+++ b/doc/tcp_tunning.txt
@@ -1,17 +1,11 @@
-# $Id$
-#
-# History:
-# --------
-# 2006-01-26  created by andrei
-
-SIP-router TCP Tunning/monitoring for lots of open connections
+Kamailio TCP Tunning/monitoring for lots of open connections
 ==============================================================
 
 0. Introduction
 ----------------
 
 This document describes very briefly various settings that should improve
-sip-router+TCP performance for sites handling a lot of TCP traffic (> 1000 open
+Kamailio TCP performance for sites handling a lot of TCP traffic (> 1000 open
 connections or very high connection/disconnection rates).
 
 For now it deals only with Linux specific optimizations.
@@ -77,7 +71,6 @@ iptables  - remove the ip_conntrack module (it limits the maximum tcp
   all the iptables modules.
 
 
-
 2. Monitoring (values to watch for)
 -----------------------------------
 
@@ -96,15 +89,15 @@ fs.inode-state  -  format: nr. allocated, nr. free, preshrink
 /proc/net/sockstat
 
 
-3. Sip-router settings
+3. Kamailio settings
 ----------------------
 
 - Don't forget to increase tcp_max_connections and the amount of shared memory
-- You should increase the number of ser "tcp_children" processes (-N no)
+- You should increase the number of Kamailio "tcp_children" processes (-N no)
   As a rule of thumb, (maximum simultaneous connections)/2000 should be ok
 - You might have to decrease TCP_BUF_SIZE to a smaller value (e.g 8K)
 - You might want to increase PKG_MEM_POOL_SIZE (for large queues)
 
-- You might need to increase the maximum open fds limit before starting ser
+- You might need to increase the maximum open fds limit before starting Kamailio
   (e.g. ulimit -n 1000000)
 
diff --git a/doc/timers.txt b/doc/timers.txt
index e149aa0..69bff18 100644
--- a/doc/timers.txt
+++ b/doc/timers.txt
@@ -1,18 +1,12 @@
-# $Id$
-#
-# History:
-# --------
-# 2005-11-30    created by andrei
 
-
-SIP-router :: timer interface
+Kamailio :: timer interface
 =============================
 
 
 1. Introduction
 ---------------
 
-SIP-router's timer interface is based on a 3 level hierarchical timing wheel
+Kamailio's timer interface is based on a 3 level hierarchical timing wheel
 (see [1]). Most timeouts will go in the first "wheel" (all timeouts < 1<<14 
 ticks, which by default mean 1024 s). Each wheel acts as a circular buffer.
 The big advantage of this scheme is that most of the time you just run all the 
@@ -78,10 +72,12 @@ timer_free(t);
 
 To use a timer you need a timer_ln structure. This structure must be stored
  in shared memory.
-You can either use timer_alloc() which will return a pointer to a shared memory allocated timer_ln structure or you can "attach" timer_ln as a member to one
+You can either use timer_alloc() which will return a pointer to a shared memory 
+allocated timer_ln structure or you can "attach" timer_ln as a member to one
  of your structures which is already stored in the shared memory.
 
-The timer_ln structure must be always initialized. Use the timer_init(...) macro for this. To the timer_init macro takes as parameters a pointer to the timer_ln structure, a pointer to a timer_handler_f function, a void* parameter for this
+The timer_ln structure must be always initialized. Use the timer_init(...) macro for this. 
+To the timer_init macro takes as parameters a pointer to the timer_ln structure, a pointer to a timer_handler_f function, a void* parameter for this
  function and some timer flags.
 Example:
 
@@ -145,15 +141,26 @@ timer_add(&f->timer, rand());
 timer_del(&f->timer); /* if the timer is already expired => f is already
                          deleted => problems */
 
-The above timer_del/free_in_one_shot_timer race example is very simple, but consider that you can have much more complex scenarios, when timer_del can be called from different processes on some asynchronous events. If this looks like your intended usage, make sure you use some  reference counters or some other protection mechanism to avoid the above race.
+The above timer_del/free_in_one_shot_timer race example is very simple, but 
+consider that you can have much more complex scenarios, when timer_del can be 
+called from different processes on some asynchronous events. If this looks like your 
+intended usage, make sure you use some  reference counters or some other 
+protection mechanism to avoid the above race.
 
 4.5 timer_allow_del
 -------------------
 
-Marks a timer as "to be deleted when the handler ends", usefull when the timer handler knows it won't prolong the timer anymore (it will return 0) and will do some time consuming work. Calling this function will cause simultaneous timer_dels to return immediately (they won't  wait anymore for the timer handle to finish). It will also allow  self-deleting from the timer handle without logging a bug.
- WARNING: - if you rely on timer_del to know when the timer handle execution finishes (e.g. to free resources used in the timer handle), don't use this function.
-          - call this function only if this is your last timer handle run (the timer handle will return 0)
-          - this function can be called only from a timer handle (in timer context), all other calls will have no effect and will log a bug message
+Marks a timer as "to be deleted when the handler ends", usefull when the timer handler 
+knows it won't prolong the timer anymore (it will return 0) and will do some time 
+consuming work. Calling this function will cause simultaneous timer_dels to return 
+immediately (they won't  wait anymore for the timer handle to finish). 
+It will also allow  self-deleting from the timer handle without logging a bug.
+ WARNING: - if you rely on timer_del to know when the timer handle execution 
+	    finishes (e.g. to free resources used in the timer handle), don't use this function.
+          - call this function only if this is your last timer handle run
+	    (the timer handle will return 0)
+          - this function can be called only from a timer handle (in timer context), 
+  	    all other calls will have no effect and will log a bug message
 
 
 4.6 Getting the ticks value
@@ -179,26 +186,30 @@ TICKS_TO_S(t)  /* converts from ticks to s, rounded down */
 4.8 Ticks value comparison
 ---------------------------
 
-The ticks value can (and will) overflow so ticks values should never be compared directly (e.g. ticks1<ticks2). To compare them include timer_ticks.h and use
- one of the macros:
+The ticks value can (and will) overflow so ticks values should never be compared directly
+(e.g. ticks1<ticks2). To compare them include timer_ticks.h and use
+one of the macros:
 
 TICKS_LT(t1, t2)  /*  t1 < t2 */
 TICKS_GT(t1, t2)  /*  t1 > t2 */
 TICKS_LE(t1, t2)  /*  t1 <= t2 */
 TICKS_GE(t1, t2)  /*  t1 >= t2 */
 
-These macros work as long as the difference between t1 and t2 is less then 2^(sizeof(ticks_t)*8-1). For the default TIMER_TICKS_HZ values, this means 4.25 years.
+These macros work as long as the difference between t1 and t2 is less than 2^(sizeof(ticks_t)*8-1). 
+For the default TIMER_TICKS_HZ values, this means 4.25 years.
 
 4.9 Backward compatibility
 --------------------------
 
-The old  register_timer and get_ticks() are still supported for backward compatibility. This means that you don't have to change your existing working code.
+The old  register_timer and get_ticks() are still supported for backward compatibility. 
+This means that you don't have to change your existing working code.
 
 
 5.0 Debugging
 -------------
 
-The timers have built-in debugging information. To activate it you only need to define TIMER_DEBUG (recompile ser with make CC_EXTRA_OPTS=-DTIMER_DEBUG all).
+The timers have built-in debugging information. To activate it you only need to
+define TIMER_DEBUG (recompile Kamailio with make CC_EXTRA_OPTS=-DTIMER_DEBUG all).
 The timer debug log level is by default L_WARN. [ FIXME: add it as script option]
 TIMER_DEBUG enables extra sanity checks and it will log a lot of information
  (like the caller of timer_* functions, where a timer was added a.s.o).
diff --git a/docbook/entities.xml b/docbook/entities.xml
index 2498298..4081ec1 100644
--- a/docbook/entities.xml
+++ b/docbook/entities.xml
@@ -47,7 +47,7 @@
 <!ENTITY ser "SER">
 <!ENTITY sername "SIP Express Router">
 <!ENTITY sercmd "kamcmd">
-<!ENTITY ctlsocket "ser_ctl">
+<!ENTITY ctlsocket "kamailio_ctl">
 
 <!ENTITY serhome "http://iptel.org/ser">
 <!ENTITY serbugs "http://sip-router.org/tracker">
diff --git a/dprint.c b/dprint.c
index 7d41562..71b89e6 100644
--- a/dprint.c
+++ b/dprint.c
@@ -1,24 +1,16 @@
 /*
- * $Id$
- *
  * debug print 
  *
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -29,7 +21,7 @@
  */
 /*!
  * \file
- * \brief SIP-router core :: 
+ * \brief Kamailio core :: Debug print
  * \ingroup core
  * Module: \ref core
  */
diff --git a/dprint.h b/dprint.h
index 3c57d9c..5729f96 100644
--- a/dprint.h
+++ b/dprint.h
@@ -1,14 +1,14 @@
 /*
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -20,7 +20,7 @@
 
 /**
  * @file
- * @brief SIP-router core :: debug printing
+ * @brief Kamailio core :: debug printing
  * @ingroup core
  * Module: @ref core
  */
diff --git a/dset.c b/dset.c
index 9c28445..2fb3b70 100644
--- a/dset.c
+++ b/dset.c
@@ -1,23 +1,16 @@
 /*
- * $Id$
- *
  * destination set
  *
  * Copyright (C) 2001-2004 FhG FOKUS
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -27,7 +20,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-/** destination set / branches support.
+/** Kamailio core :: destination set / branches support.
  * @file dset.c
  * @ingroup core
  * Module: @ref core
@@ -39,6 +32,7 @@
 #include "parser/parser_f.h"
 #include "parser/parse_uri.h"
 #include "parser/msg_parser.h"
+#include "globals.h"
 #include "ut.h"
 #include "hash_func.h"
 #include "error.h"
@@ -58,9 +52,9 @@
 
 /* 
  * Where we store URIs of additional transaction branches
- * (-1 because of the default branch, #0)
+ * (sr_dst_max_branches - 1 : because of the default branch for r-uri, #0 in tm)
  */
-static struct branch branches[MAX_BRANCHES - 1];
+static struct branch *branches = NULL;
 
 /* how many of them we have */
 unsigned int nr_branches = 0;
@@ -78,6 +72,23 @@ static qvalue_t ruri_q = Q_UNSPECIFIED;
 static flag_t ruri_bflags;
 
 
+int init_dst_set(void)
+{
+	if(sr_dst_max_branches<=0 || sr_dst_max_branches>=MAX_BRANCHES_LIMIT) {
+		LM_ERR("invalid value for max branches parameter: %u\n",
+				sr_dst_max_branches);
+		return -1;
+	}
+	/* sr_dst_max_branches - 1 : because of the default branch for r-uri, #0 in tm */
+	branches = (branch_t*)pkg_malloc((sr_dst_max_branches-1)*sizeof(branch_t));
+	if(branches==NULL) {
+		LM_ERR("not enough memory to initialize destination branches\n");
+		return -1;
+	}
+	memset(branches, 0, (sr_dst_max_branches-1)*sizeof(branch_t));
+	return 0;
+}
+
 /*! \brief
  * Return pointer to branch[idx] structure
  * @param idx - branch index
@@ -333,7 +344,7 @@ int append_branch(struct sip_msg* msg, str* uri, str* dst_uri, str* path,
 	/* if we have already set up the maximum number
 	 * of branches, don't try new ones 
 	 */
-	if (unlikely(nr_branches == MAX_BRANCHES - 1)) {
+	if (unlikely(nr_branches == sr_dst_max_branches - 1)) {
 		LM_ERR("max nr of branches exceeded\n");
 		ser_error = E_TOO_MANY_BRANCHES;
 		return -1;
diff --git a/dset.h b/dset.h
index ff7e838..752450f 100644
--- a/dset.h
+++ b/dset.h
@@ -1,16 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2004 FhG FOKUS
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -22,7 +20,7 @@
 
 /*!
  * \file
- * \brief SIP-router core :: Destination set handling
+ * \brief Kamailio core :: Destination set handling
  * \ingroup core
  * Module: \ref core
  */
@@ -258,4 +256,6 @@ int setbflagsval(unsigned int branch, flag_t val);
 int uri_add_rcv_alias(sip_msg_t *msg, str *uri, str *nuri);
 int uri_restore_rcv_alias(str *uri, str *nuri, str *suri);
 
+int init_dst_set(void);
+
 #endif /* _DSET_H */
diff --git a/dst_blacklist.c b/dst_blacklist.c
index a69d215..a2a4696 100644
--- a/dst_blacklist.c
+++ b/dst_blacklist.c
@@ -1,23 +1,16 @@
 /*
- * $Id$
- *
  * resolver related functions
  *
  * Copyright (C) 2006 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -26,20 +19,10 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/* History:
- * --------
- *  2006-07-29  created by andrei
- *  2007-05-39  added hooks for add; more locks to reduce contention (andrei)
- *  2007-06-26  added hooks for search (andrei)
- *  2007-07-30  added dst_blacklist_del() and dst_blacklist_add_to()  (andrei)
- *  2007-07-30  dst blacklist measurements added (Gergo)
- *  2008-02-11  dns_blacklist_init cfg parameter is introduced (Miklos)
- *  2009-02-26  added dst_blacklist_su* variant (andrei)
- */
 
 /*!
  * \file
- * \brief SIP-router core :: 
+ * \brief Kamailio core :: resolver related functions
  * \ingroup core
  * Module: \ref core
  */
@@ -685,7 +668,7 @@ inline static int dst_blacklist_clean_expired(unsigned int target,
 			/* check for timeout only "between" hash cells */
 			now=get_ticks_raw();
 			if ((now-start_time)>=timeout){
-				DBG("_dst_blacklist_clean_expired_unsafe: timeout: %d > %d\n",
+				LM_DBG("timeout: %d > %d\n",
 						TICKS_TO_MS(now-start_time), TICKS_TO_MS(timeout));
 				goto skip;
 			}
@@ -694,7 +677,7 @@ inline static int dst_blacklist_clean_expired(unsigned int target,
 skip:
 	start=h; /* next time we start where we left */
 	if (no){
-		DBG("dst_blacklist_clean_expired, %d entries removed\n", no);
+		LM_DBG("%d entries removed\n", no);
 	}
 	return no;
 }
diff --git a/dst_blacklist.h b/dst_blacklist.h
index 491d56e..43461c3 100644
--- a/dst_blacklist.h
+++ b/dst_blacklist.h
@@ -1,14 +1,14 @@
 /*
  * Copyright (C) 2006 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -18,20 +18,13 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-/** SIP-router core :: Destination blacklists.
+/** Kamailio core :: Destination blacklists.
  * @file
+ * @author andrei, Gergo
  * @ingroup core
  * Module: @ref core
  */
 
-/* History:
- * --------
- *  2006-07-29  created by andrei
- *  2007-07-30  dst blacklist measurements added (Gergo)
- *  2009-12-22  blacklist ignore mask support and dst_blacklist_{add,su}
- *               switched to macros (andrei)
- */
-
 #ifndef dst_black_list_h
 #define dst_black_list_h
 
diff --git a/endianness.c b/endianness.c
index 8f621e8..1151739 100644
--- a/endianness.c
+++ b/endianness.c
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- * 
  * Copyright (C) 2008 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -15,17 +13,10 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/*
- *  endianness compile and runtime  tests
- * 
- * History:
- * --------
- *  2008-06-13  created by andrei
- */
 
 /*!
  * \file
- * \brief SIP-router core :: 
+ * \brief Kamailio core :: endianness compile and runtime  tests
  * \ingroup core
  * Module: \ref core
  */
diff --git a/endianness.h b/endianness.h
index e69518c..53f0fba 100644
--- a/endianness.h
+++ b/endianness.h
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- * 
  * Copyright (C) 2008 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -17,11 +15,10 @@
  */
 
 /** @file
- *  endianness compile and runtime  tests
+ *  Kamailio core :: endianness compile and runtime  tests
+ *  @author andrei
+ *  @ingroup core
  * 
- * History:
- * --------
- *  2008-06-13  created by andrei
  *
  * Defines:
  *  -  __IS_LITTLE_ENDIAN if the system is little endian and
diff --git a/error.c b/error.c
index e54c3d1..51146b1 100644
--- a/error.c
+++ b/error.c
@@ -1,22 +1,14 @@
 /*
- * $Id$
- *
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -25,14 +17,11 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2003-04-04 phrase length corrected not to include trailer 0 (jiri)
  */
 
 /*!
  * \file
- * \brief SIP-router core :: 
+ * \brief Kamailio core :: Error handling
  * \ingroup core
  * Module: \ref core
  */
diff --git a/error.h b/error.h
index ebafc1b..829073e 100644
--- a/error.h
+++ b/error.h
@@ -1,16 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/etc/kamailio-basic.cfg b/etc/kamailio-basic.cfg
index 3f072b3..b20de64 100644
--- a/etc/kamailio-basic.cfg
+++ b/etc/kamailio-basic.cfg
@@ -1,6 +1,6 @@
 #!KAMAILIO
 #
-# Kamailio (OpenSER) SIP Server v4.2 - default configuration script
+# Kamailio (OpenSER) SIP Server v4.3 - default configuration script
 #     - web: http://www.kamailio.org
 #     - git: http://sip-router.org
 #
@@ -191,8 +191,10 @@ loadmodule "debugger.so"
 
 
 # ----- mi_fifo params -----
-modparam("mi_fifo", "fifo_name", "/tmp/kamailio_fifo")
+#modparam("mi_fifo", "fifo_name", "/var/run/kamailio/kamailio_fifo")
 
+# ----- ctl params -----
+#modparam("ctl", "binrpc", "unix:/var/run/kamailio/kamailio_ctl")
 
 # ----- tm params -----
 # auto-discard branches from previous serial forking leg
diff --git a/etc/kamailio-oob.cfg b/etc/kamailio-oob.cfg
index 2aa3289..2de8a2b 100644
--- a/etc/kamailio-oob.cfg
+++ b/etc/kamailio-oob.cfg
@@ -1,6 +1,6 @@
 #!KAMAILIO
 #
-# Kamailio (OpenSER) SIP Server v4.2 - default configuration script
+# Kamailio (OpenSER) SIP Server v4.3 - default configuration script
 #     - web: http://www.kamailio.org
 #     - git: http://sip-router.org
 #
@@ -315,8 +315,10 @@ loadmodule "xhttp_pi.so"
 
 
 # ----- mi_fifo params -----
-modparam("mi_fifo", "fifo_name", "/tmp/kamailio_fifo")
+#modparam("mi_fifo", "fifo_name", "/var/run/kamailio/kamailio_fifo")
 
+# ----- ctl params -----
+#modparam("ctl", "binrpc", "unix:/var/run/kamailio/kamailio_ctl")
 
 # ----- tm params -----
 # auto-discard branches from previous serial forking leg
diff --git a/etc/kamailio.cfg b/etc/kamailio.cfg
index 94cca60..1190e80 100644
--- a/etc/kamailio.cfg
+++ b/etc/kamailio.cfg
@@ -1,6 +1,6 @@
 #!KAMAILIO
 #
-# Kamailio (OpenSER) SIP Server v4.2 - default configuration script
+# Kamailio (OpenSER) SIP Server v4.3 - default configuration script
 #     - web: http://www.kamailio.org
 #     - git: http://sip-router.org
 #
@@ -288,8 +288,10 @@ loadmodule "debugger.so"
 
 
 # ----- mi_fifo params -----
-modparam("mi_fifo", "fifo_name", "/tmp/kamailio_fifo")
+#modparam("mi_fifo", "fifo_name", "/var/run/kamailio/kamailio_fifo")
 
+# ----- ctl params -----
+#modparam("ctl", "binrpc", "unix:/var/run/kamailio/kamailio_ctl")
 
 # ----- tm params -----
 # auto-discard branches from previous serial forking leg
diff --git a/events.c b/events.c
index 0e1d85d..5312e7a 100644
--- a/events.c
+++ b/events.c
@@ -1,9 +1,7 @@
 /**
- * $Id$
- *
  * Copyright (C) 2009 SIP-Router.org
  *
- * This file is part of Extensible SIP Router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -20,7 +18,7 @@
 
 /*!
  * \file
- * \brief SIP-router core :: 
+ * \brief Kamailio core :: event handling
  * \ingroup core
  * Module: \ref core
  */
diff --git a/events.h b/events.h
index 32540a0..8218453 100644
--- a/events.h
+++ b/events.h
@@ -1,9 +1,8 @@
 /**
- * $Id$
  *
  * Copyright (C) 2009 SIP-Router.org
  *
- * This file is part of Extensible SIP Router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
diff --git a/examples/pcscf/kamailio.cfg b/examples/pcscf/kamailio.cfg
index 877d7bd..c2d5f55 100644
--- a/examples/pcscf/kamailio.cfg
+++ b/examples/pcscf/kamailio.cfg
@@ -655,7 +655,7 @@ route[NAT] {
 #!ifdef WITH_NAT
 	force_rport();
 	if (nat_uac_test("19") && !ds_is_from_list()) {
-		if(is_method("INVITE|SUBSCRIBE")) {
+		if(is_method("INVITE|SUBSCRIBE|UPDATE")) {
 			set_contact_alias();
 		}
 		setflag(FLT_NAT);
@@ -795,8 +795,25 @@ route[REGISTER] {
 
 #!ifdef WITH_RX	
 	xlog("L_DBG","Subscribing to signalling bearer status\n");
-	if (Rx_AAR_Register("REG_AAR_REPLY", "location") == 0)
-		exit;
+
+	Rx_AAR_Register("REG_AAR_REPLY", "location");
+	switch ($retcode) {
+		case -1:
+			# There was an error sending the AAR-Request:
+			xlog("L_ERR", "Diameter: AAR failed on subscription to signalling\n");
+			send_reply("403", "Can't register to QoS for signalling");
+			exit;
+			break;
+		case 0:
+			# We are waiting for an async reply, just exit here.
+			exit;
+			break;
+		case 1:
+			# We did not need to send AAR, so just continue as normal
+			route(REGISTER_CONTINUE);
+			break;
+	}
+	exit;
 }
 
 route[REG_AAR_REPLY] {
@@ -809,8 +826,12 @@ route[REG_AAR_REPLY] {
 			send_reply("403", "Can't register to QoS for signalling");
 			exit;
 	}
-#!endif
+	# Proceed with Registering:
+	route(REGISTER_CONTINUE);
+}
 
+route[REGISTER_CONTINUE] {
+#!endif
 #!ifndef WITH_SBC
 #!ifdef WITH_WEBSOCKET
 	if (($Rp == MY_WS_PORT || $Rp == MY_WSS_PORT) && (proto == WS || proto == WSS)) {
@@ -962,7 +983,7 @@ route[Orig_Initial]
 
 #!ifdef WITH_RX
 	xlog("L_DBG","Diameter: Orig authorizing media via Rx\n");	
-	if(Rx_AAR("ORIG_SESSION_AAR","orig")==0){
+	if(Rx_AAR("ORIG_SESSION_AAR","orig","",-1)==0){
 		exit;
 	}
 }
@@ -1014,7 +1035,7 @@ onreply_route[Orig_Initial_reply]
 #!ifdef WITH_RX
 	if (t_check_status("180|183|200")){
 		xlog("L_DBG","Diameter: Orig authorizing media via Rx\n");	
-		if(Rx_AAR("ORIG_SESSION_AAR_REPLY","orig")==0){
+		if(Rx_AAR("ORIG_SESSION_AAR_REPLY","orig","",-1)==0){
 			exit;
 		}
 	}
@@ -1068,7 +1089,7 @@ route[Term_Initial]
 
 #!ifdef WITH_RX
 	xlog("L_DBG","Diameter: Term authorizing media via Rx\n");	
-	if(Rx_AAR("TERM_SESSION_AAR","term")==0){
+	if(Rx_AAR("TERM_SESSION_AAR","term","",-1)==0){
 		exit;
 	}
 }
@@ -1117,7 +1138,7 @@ onreply_route[Term_Initial_reply]
 #!ifdef WITH_RX
 	if (t_check_status("180|183|200")){
 		xlog("L_DBG","Diameter: Orig authorizing media via Rx\n");	
-		if(Rx_AAR("TERM_SESSION_AAR_REPLY","term")==0){
+		if(Rx_AAR("TERM_SESSION_AAR_REPLY","term","",-1)==0){
 			exit;
 		}
 	}
diff --git a/examples/scscf/CxDataType_Rel8.xsd b/examples/scscf/CxDataType_Rel8.xsd
new file mode 100644
index 0000000..2e057eb
--- /dev/null
+++ b/examples/scscf/CxDataType_Rel8.xsd
@@ -0,0 +1,379 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
+	<xs:simpleType name="tPriority" final="list restriction">
+		<xs:restriction base="xs:int">
+			<xs:minInclusive value="0"/>
+		</xs:restriction>
+	</xs:simpleType>
+	<xs:simpleType name="tProfilePartIndicator" final="list restriction">
+		<xs:restriction base="xs:unsignedByte">
+			<xs:maxInclusive value="1"/>
+			<xs:enumeration value="0">
+				<xs:annotation>
+					<xs:documentation>
+						<label xml:lang="en">REGISTERED</label>
+						<definition xml:lang="en">iFC is part of the registered profile</definition>
+					</xs:documentation>
+				</xs:annotation>
+			</xs:enumeration>
+			<xs:enumeration value="1">
+				<xs:annotation>
+					<xs:documentation>
+						<label xml:lang="en">UNREGISTERED</label>
+						<definition xml:lang="en">iFC is part of the unregistered profile</definition>
+					</xs:documentation>
+				</xs:annotation>
+			</xs:enumeration>
+		</xs:restriction>
+	</xs:simpleType>
+	<xs:simpleType name="tSharedIFCSetID" final="list restriction">
+		<xs:restriction base="xs:int">
+			<xs:minInclusive value="0"/>
+		</xs:restriction>
+	</xs:simpleType>
+	<xs:simpleType name="tGroupID" final="list restriction">
+		<xs:restriction base="xs:int">
+			<xs:minInclusive value="0"/>
+		</xs:restriction>
+	</xs:simpleType>
+	<xs:simpleType name="tRegistrationType" final="list restriction">
+		<xs:restriction base="xs:unsignedByte">
+			<xs:maxInclusive value="2"/>
+			<xs:enumeration value="0">
+				<xs:annotation>
+					<xs:documentation>
+						<label xml:lang="en">INITIAL_REGISTRATION</label>
+						<definition xml:lang="en">Matches to REGISTER messages that are related to initial registration</definition>
+					</xs:documentation>
+				</xs:annotation>
+			</xs:enumeration>
+			<xs:enumeration value="1">
+				<xs:annotation>
+					<xs:documentation>
+						<label xml:lang="en">RE-REGISTRATION</label>
+						<definition xml:lang="en">Matches to REGISTER messages that are related to re-registration</definition>
+					</xs:documentation>
+				</xs:annotation>
+			</xs:enumeration>
+			<xs:enumeration value="2">
+				<xs:annotation>
+					<xs:documentation>
+						<label xml:lang="en">DE-REGISTRATION</label>
+						<definition xml:lang="en">Matches to REGISTER messages that are related to de-registration</definition>
+					</xs:documentation>
+				</xs:annotation>
+			</xs:enumeration>
+		</xs:restriction>
+	</xs:simpleType>
+	<xs:simpleType name="tDefaultHandling" final="list restriction">
+		<xs:restriction base="xs:unsignedByte">
+			<xs:maxInclusive value="1"/>
+			<xs:enumeration value="0">
+				<xs:annotation>
+					<xs:documentation>
+						<label xml:lang="en">SESSION_CONTINUED</label>
+						<definition xml:lang="en">Session Continued</definition>
+					</xs:documentation>
+				</xs:annotation>
+			</xs:enumeration>
+			<xs:enumeration value="1">
+				<xs:annotation>
+					<xs:documentation>
+						<label xml:lang="en">SESSION_TERMINATED</label>
+						<definition xml:lang="en">Session Terminated</definition>
+					</xs:documentation>
+				</xs:annotation>
+			</xs:enumeration>
+		</xs:restriction>
+	</xs:simpleType>
+	<xs:simpleType name="tDirectionOfRequest" final="list restriction">
+		<xs:restriction base="xs:unsignedByte">
+			<xs:maxInclusive value="3"/>
+			<xs:enumeration value="0">
+				<xs:annotation>
+					<xs:documentation>
+						<label xml:lang="en">ORIGINATING_SESSION</label>
+						<definition xml:lang="en">Originating Session</definition>
+					</xs:documentation>
+				</xs:annotation>
+			</xs:enumeration>
+			<xs:enumeration value="1">
+				<xs:annotation>
+					<xs:documentation>
+						<label xml:lang="en">TERMINATING_REGISTERED</label>
+						<definition xml:lang="en">Terminating Session for registered user</definition>
+					</xs:documentation>
+				</xs:annotation>
+			</xs:enumeration>
+			<xs:enumeration value="2">
+				<xs:annotation>
+					<xs:documentation>
+						<label xml:lang="en">TERMINATING_UNREGISTERED</label>
+						<definition xml:lang="en">Terminating Session for unregistered user</definition>
+					</xs:documentation>
+				</xs:annotation>
+			</xs:enumeration>
+			<xs:enumeration value="3">
+				<xs:annotation>
+					<xs:documentation>
+						<label xml:lang="en">ORIGINATING_UNREGISTERED</label>
+						<definition xml:lang="en">Originating Session for an unregistered user</definition>
+					</xs:documentation>
+				</xs:annotation>
+			</xs:enumeration>
+		</xs:restriction>
+	</xs:simpleType>
+	<xs:simpleType name="tPrivateID" final="list restriction">
+		<xs:restriction base="xs:anyURI"/>
+	</xs:simpleType>
+	<xs:simpleType name="tSIP_URL" final="list restriction">
+		<xs:restriction base="xs:anyURI"/>
+	</xs:simpleType>
+	<xs:simpleType name="tTEL_URL" final="list restriction">
+		<xs:restriction base="xs:anyURI"/>
+	</xs:simpleType>
+	<xs:simpleType name="tIdentity" final="list restriction">
+		<xs:union memberTypes="tSIP_URL tTEL_URL"/>
+	</xs:simpleType>
+	<xs:simpleType name="tIdentityType" final="list restriction">
+		<xs:restriction base="xs:unsignedByte">
+			<xs:minInclusive value="0"/>
+			<xs:maxInclusive value="4"/>
+			<xs:enumeration value="0">
+				<xs:annotation>
+					<xs:documentation>
+						<label xml:lang="en">PUBLIC_USER_IDENTITY</label>
+						<definition xml:lang="en">Identity is a Public User Identity.</definition>
+					</xs:documentation>
+				</xs:annotation>
+			</xs:enumeration>
+			<xs:enumeration value="1">
+				<xs:annotation>
+					<xs:documentation>
+						<label xml:lang="en">DISTINCT_PSI</label>
+						<definition xml:lang="en">Identity is a distinct Public Service Identity.</definition>
+					</xs:documentation>
+				</xs:annotation>
+			</xs:enumeration>
+			<xs:enumeration value="2">
+				<xs:annotation>
+					<xs:documentation>
+						<label xml:lang="en">WILDCARDED_PSI</label>
+						<definition xml:lang="en">Identity matches a wildcarded Public Service Identity.</definition>
+					</xs:documentation>
+				</xs:annotation>
+			</xs:enumeration>
+			<xs:enumeration value="3">
+				<xs:annotation>
+					<xs:documentation>
+						<label xml:lang="en">WILDCARDED_IMPU</label>
+						<definition xml:lang="en">Identity is a Wildcarded Public User Identity.</definition>
+					</xs:documentation>
+				</xs:annotation>
+			</xs:enumeration>
+			<xs:enumeration value="4">
+				<xs:annotation>
+					<xs:documentation>
+						<label xml:lang="en">IMPU WILDCARD</label>
+						<definition xml:lang="en">Identity is a Wildcard for Public User Identities.</definition>
+					</xs:documentation>
+				</xs:annotation>
+			</xs:enumeration>
+		</xs:restriction>
+	</xs:simpleType>
+	<xs:complexType name="tPublicIdentityExtension">
+		<xs:sequence>
+			<xs:element name="IdentityType" type="tIdentityType" minOccurs="0"/>
+			<xs:element name="WildcardedPSI" type="xs:anyURI" minOccurs="0"/>
+			<xs:element name="Extension" type="tPublicIdentityExtension2" minOccurs="0"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="tPublicIdentityExtension2">
+		<xs:sequence>
+			<xs:element name="DisplayName" type="tDisplayName" minOccurs="0"/>
+			<xs:element name="AliasIdentityGroupID" type="tAliasIdentityGroupID" minOccurs="0"/>
+			<xs:element name="Extension" type="tPublicIdentityExtension3" minOccurs="0"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="tPublicIdentityExtension3">
+		<xs:sequence>
+			<xs:element name="WildcardedIMPU" type="xs:anyURI" minOccurs="0"/>
+			<xs:element name="ServiceLevelTraceInfo" type="tServiceLevelTraceInfo" minOccurs="0"/>
+			<xs:element name="SIPURIParameters" type="tString" minOccurs="0"/>
+			<xs:element name="Extension" type="tExtension" minOccurs="0"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:simpleType name="tDisplayName" final="list restriction">
+		<xs:restriction base="xs:string">
+			<xs:minLength value="0"/>
+		</xs:restriction>
+	</xs:simpleType>
+	<xs:simpleType name="tAliasIdentityGroupID" final="list restriction">
+		<xs:restriction base="xs:string">
+			<xs:minLength value="0"/>
+		</xs:restriction>
+	</xs:simpleType>
+	<xs:simpleType name="tServiceLevelTraceInfo" final="list restriction">
+		<xs:restriction base="xs:string">
+			<xs:minLength value="0"/>
+		</xs:restriction>
+	</xs:simpleType>
+	<xs:simpleType name="tServiceInfo" final="list restriction">
+		<xs:restriction base="xs:string">
+			<xs:minLength value="0"/>
+		</xs:restriction>
+	</xs:simpleType>
+	<xs:simpleType name="tString" final="list restriction">
+		<xs:restriction base="xs:string">
+			<xs:minLength value="0"/>
+		</xs:restriction>
+	</xs:simpleType>
+	<xs:simpleType name="tBool">
+		<xs:restriction base="xs:boolean"/>
+	</xs:simpleType>
+	<xs:simpleType name="tSubscribedMediaProfileId" final="list restriction">
+		<xs:restriction base="xs:int">
+			<xs:minInclusive value="0"/>
+		</xs:restriction>
+	</xs:simpleType>
+	<xs:complexType name="tExtension">
+		<xs:sequence>
+			<xs:any processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="tServiceProfileExtension">
+		<xs:sequence>
+			<xs:element name="SharedIFCSetID" type="tSharedIFCSetID" minOccurs="0" maxOccurs="unbounded"/>
+			<xs:element name="Extension" type="tExtension" minOccurs="0"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="tSePoTriExtension">
+		<xs:sequence>
+			<xs:element name="RegistrationType" type="tRegistrationType" minOccurs="0" maxOccurs="2"/>
+			<xs:element name="Extension" type="tExtension" minOccurs="0"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="tListOfServiceIds">
+		<xs:sequence>
+			<xs:element name="ServiceId" type="tString" minOccurs="0" maxOccurs="unbounded"/>
+			<xs:element name="Extension" type="tExtension" minOccurs="0"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="tCNServicesAuthorizationExtension">
+		<xs:sequence>
+			<xs:element name="ListOfServiceIds" type="tListOfServiceIds" minOccurs="0"/>
+			<xs:element name="Extension" type="tExtension" minOccurs="0"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="tIMSSubscription">
+		<xs:sequence>
+			<xs:element name="PrivateID" type="tPrivateID"/>
+			<xs:element name="ServiceProfile" type="tServiceProfile" maxOccurs="unbounded"/>
+			<xs:element name="Extension" type="tExtension" minOccurs="0"/>
+			<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="tServiceProfile">
+		<xs:sequence>
+			<xs:element name="PublicIdentity" type="tPublicIdentity" maxOccurs="unbounded"/>
+			<xs:element name="CoreNetworkServicesAuthorization" type="tCoreNetworkServicesAuthorization" minOccurs="0"/>
+			<xs:element name="InitialFilterCriteria" type="tInitialFilterCriteria" minOccurs="0" maxOccurs="unbounded"/>
+			<xs:element name="Extension" type="tServiceProfileExtension" minOccurs="0"/>
+			<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="tCoreNetworkServicesAuthorization">
+		<xs:sequence>
+			<xs:element name="SubscribedMediaProfileId" type="tSubscribedMediaProfileId" minOccurs="0"/>
+			<xs:element name="Extension" type="tCNServicesAuthorizationExtension" minOccurs="0"/>
+			<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="tInitialFilterCriteria">
+		<xs:sequence>
+			<xs:element name="Priority" type="tPriority"/>
+			<xs:element name="TriggerPoint" type="tTrigger" minOccurs="0"/>
+			<xs:element name="ApplicationServer" type="tApplicationServer"/>
+			<xs:element name="ProfilePartIndicator" type="tProfilePartIndicator" minOccurs="0"/>
+			<xs:element name="Extension" type="tExtension" minOccurs="0"/>
+			<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="tTrigger">
+		<xs:sequence>
+			<xs:element name="ConditionTypeCNF" type="tBool"/>
+			<xs:element name="SPT" type="tSePoTri" maxOccurs="unbounded"/>
+			<xs:element name="Extension" type="tExtension" minOccurs="0"/>
+			<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="tSePoTri">
+		<xs:sequence>
+			<xs:element name="ConditionNegated" type="tBool" default="0" minOccurs="0"/>
+			<xs:element name="Group" type="tGroupID" maxOccurs="unbounded"/>
+			<xs:choice>
+				<xs:element name="RequestURI" type="tString"/>
+				<xs:element name="Method" type="tString"/>
+				<xs:element name="SIPHeader" type="tHeader"/>
+				<xs:element name="SessionCase" type="tDirectionOfRequest"/>
+				<xs:element name="SessionDescription" type="tSessionDescription"/>
+			</xs:choice>
+			<xs:element name="Extension" type="tSePoTriExtension" minOccurs="0"/>
+			<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="tHeader">
+		<xs:sequence>
+			<xs:element name="Header" type="tString"/>
+			<xs:element name="Content" type="tString" minOccurs="0"/>
+			<xs:element name="Extension" type="tExtension" minOccurs="0"/>
+			<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="tSessionDescription">
+		<xs:sequence>
+			<xs:element name="Line" type="tString"/>
+			<xs:element name="Content" type="tString" minOccurs="0"/>
+			<xs:element name="Extension" type="tExtension" minOccurs="0"/>
+			<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="tApplicationServer">
+		<xs:sequence>
+			<xs:element name="ServerName" type="tSIP_URL"/>
+			<xs:element name="DefaultHandling" type="tDefaultHandling" minOccurs="0"/>
+			<xs:element name="ServiceInfo" type="tServiceInfo" minOccurs="0"/>
+			<xs:element name="Extension" type="tApplicationServerExtension" minOccurs="0"/>
+			<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="tPublicIdentity">
+		<xs:sequence>
+			<xs:element name="BarringIndication" type="tBool" default="0" minOccurs="0"/>
+			<xs:element name="Identity" type="tIdentity"/>
+			<xs:element name="Extension" type="tPublicIdentityExtension" minOccurs="0"/>
+			<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="tApplicationServerExtension">
+		<xs:sequence>
+			<xs:element name="IncludeRegisterRequest" type="tIncludeRegisterRequest" minOccurs="0" maxOccurs="1"/>
+			<xs:element name="IncludeRegisterResponse" type="tIncludeRegisterResponse" minOccurs="0" maxOccurs="1"/>
+			<xs:element name="Extension" type="tExtension" minOccurs="0"/>
+			<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="tIncludeRegisterRequest">
+		<xs:sequence>
+			<xs:element name="Extension" type="tExtension" minOccurs="0"/>
+			<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="tIncludeRegisterResponse">
+		<xs:sequence>
+			<xs:element name="Extension" type="tExtension" minOccurs="0"/>
+			<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:element name="IMSSubscription" type="tIMSSubscription"/>
+</xs:schema>
diff --git a/examples/scscf/kamailio.cfg b/examples/scscf/kamailio.cfg
index f8c2ee6..b8f7a1e 100644
--- a/examples/scscf/kamailio.cfg
+++ b/examples/scscf/kamailio.cfg
@@ -308,6 +308,9 @@ modparam("enum", "domain_suffix", ENUM_SUFFIX)
 # ----- sanity params -----
 modparam("sanity", "autodrop", 0)
 
+# -- presence params --
+modparam("presence", "subs_remove_match", 1)   #means we match subscriptions on all attributes
+
 # ----------------- Settings for Dispatcher ---------------
 modparam("dispatcher", "list_file", "/etc/kamailio/dispatcher.list")
 # Dispatcher: Enable Failover-Support
@@ -768,7 +771,7 @@ route[orig]
 	# before we allow call - lets check credit
 	if (is_method("INVITE")) {
 		xlog("L_DBG","Sending initial CCR Request for call\n");
-		$var(cc_ret) = Ro_CCR("CHARGING_CCR_REPLY", "orig", "SCUR", "", "30", "location");
+		$var(cc_ret) = Ro_CCR("CHARGING_CCR_REPLY", "orig", 30, "0", "0");
 		if ($var(cc_ret) < 0) {
 			xlog("L_ERR","CCR Request failure\n");
 			sl_send_reply("402","Payment required");
diff --git a/examples/sr b/examples/sr
index 99cd0f0..c950a80 100755
--- a/examples/sr
+++ b/examples/sr
@@ -38,9 +38,9 @@ MYDIR=$HM/core
 CORE=$MYDIR/core
 TMP=/tmp/srcore.$$
 
-sip-router_start() {
+sip_router_start() {
 	if [ -r $BIN -a -r $CORE ] ; then
-		echo "before startup sip-router core found on `date` at $HOSTNAME" > $TMP
+		echo "before startup sip-router core found on `date` at `hostname`" > $TMP
 		echo "----------------------------------" >> $TMP
 		DATE=`date "+%Y-%m-%d--%H-%M"`
 		NEWCORE=$MYDIR/core.$DATE
@@ -60,7 +60,7 @@ sip-router_start() {
 	echo
 }
 
-sip-router_stop() {
+sip_router_stop() {
 	echo "Stopping SIP router: "
 	killproc $BINNAME
 	RETVAL=$?
@@ -84,15 +84,15 @@ monit_stop() {
 # See how we were called.
 case "$1" in
   serstart)
-	sip-router_start
+	sip_router_start
 	;;
   sip-routerstop)
-    sip-router_stop
+    sip_router_stop
 	;;
   sip-routerrestart)
-	sip-router_stop
+	sip_router_stop
 	echo
-	sip-router_start
+	sip_router_start
 	;;
   start)
     monit_start
diff --git a/fastlock.h b/fastlock.h
index a09f0e9..f2e9ced 100644
--- a/fastlock.h
+++ b/fastlock.h
@@ -1,10 +1,6 @@
 /*
  * fast architecture specific locking
  *
- * $Id$
- *
- * 
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -19,38 +15,12 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/*
- *
- *History:
- *--------
- *  2002-02-05  created by andrei
- *  2003-01-16  added PPC locking code contributed by Dinos Dorkofikis
- *               <kdor at intranet.gr>
- *  2004-09-12  added MIPS locking for ISA>=2 (>r3000)  (andrei)
- *  2004-12-16  for now use the same locking code for sparc32 as for sparc64
- *               (it will work only if NOSMP is defined) (andrei)
- *  2005-04-27  added alpha locking code (andrei)
- *  2005-05-25  PPC locking code enabled for PPC64; added a lwsync to
- *               the tsl part and replaced the sync with a lwsync for the
- *               unlock part (andrei)
- *  2006-03-08  mips2 NOSMP (skip sync), optimized x86 & mips clobbers and
- *               input/output constraints (andrei)
- *  2006-04-03  optimization: call lock_get memory barrier outside tsl,in the 
- *               calling function, only if the lock operation succeeded
- *               (membar_getlock()) (andrei)
- *              added try_lock(); more x86 optimizations, x86  release_lock
- *               fix (andrei)
- * 2006-04-04  sparc* optimizations, sparc32 smp support, armv6 no smp support,
- *              ppc, mips*, alpha optimizations (andrei)
- * 2006-04-05  ppc fixes (s/stw/stwx/, s/lwz/lwzx), early clobber added
- *             where needed (andrei)
- * 2006-11-22  arm early clobber added: according to the swp instruction 
- *              specification the address register must be != from the other 2
- *              (Julien Blache <jblache at debian.org>)
- *
- */
-
-/*
+/*!
+* \file
+* \brief Kamailio core :: fast architecture specific locking
+* \author andrei
+* \ingroup core
+* Module: \ref core
  * WARNING: the code was not tested on the following architectures:
  *           - arm6  (cross-compiles ok, no test)
  *           - alpha (cross-compiles ok, no test)
diff --git a/fix_lumps.h b/fix_lumps.h
index b21cf46..0bd0ab2 100644
--- a/fix_lumps.h
+++ b/fix_lumps.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * here, we delete message lumps which are generated in
  * core functions using pkg_malloc and applied to shmem
  * requests; not doing so would result ugly memory problems
@@ -9,14 +7,14 @@
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -25,14 +23,17 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/*
- * History:
- * -------
- *  2003-11-24  changed free_via_lump to free_via_clen_lump and make it
- *              handle CONTENTLENGTH lumps also (andrei)
- *  2005-07-04  lumps in SHM or dup'ed lumps are not freed and an warning
- *               message is logged (temporary fix) (andrei)
- */
+/*!
+* \file
+* \brief Kamailio core :: Lump handling
+* \ingroup core
+* Module: \ref core
+ * here, we delete message lumps which are generated in
+ * core functions using pkg_malloc and applied to shmem
+ * requests; not doing so would result ugly memory problems
+ *
+ * I admit it is not a nice hack; -jiri 
+*/
 
 
 
diff --git a/flags.c b/flags.c
index 883e312..5dbdd4f 100644
--- a/flags.c
+++ b/flags.c
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,16 +17,10 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/*
- * History:
- * --------
- *  2003-03-19  replaced all mallocs/frees w/ pkg_malloc/pkg_free (andrei)
- *  2006-02-02  named flags support (andrei)
- */
 
 /*!
  * \file
- * \brief SIP-router core :: 
+ * \brief Kamailio core :: Flags
  * \ingroup core
  * Module: \ref core
  */
@@ -270,7 +257,7 @@ static int fixup_t_flag(void** param, int param_no)
 	char *c;
 	int token;
 
-	DBG("DEBUG: fixing flag: %s\n", (char *) (*param));
+	LM_DBG("fixing flag: %s\n", (char *) (*param));
 
 	if (param_no!=1) {
 		LM_ERR("TM module: only parameter #1 for flags can be fixed\n");
diff --git a/flags.h b/flags.h
index 5050d8d..3876082 100644
--- a/flags.h
+++ b/flags.h
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,6 +17,12 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
+/*!
+* \file
+* \brief Kamailio core :: Flag handling
+* \ingroup core
+* Module: \ref core
+*/
 
 
 
diff --git a/forward.c b/forward.c
index 81e39fe..4e82b1d 100644
--- a/forward.c
+++ b/forward.c
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,41 +17,11 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * -------
- *  2001-??-??  created by andrei
- *  ????-??-??  lots of changes by a lot of people
- *  2003-01-23  support for determination of outbound interface added :
- *               get_out_socket (jiri)
- *  2003-01-24  reply to rport support added, contributed by
- *               Maxim Sobolev <sobomax at FreeBSD.org> and modified by andrei
- *  2003-02-11  removed calls to upd_send & tcp_send & replaced them with
- *               calls to msg_send (andrei)
- *  2003-03-19  replaced all mallocs/frees w/ pkg_malloc/pkg_free (andrei)
- *  2003-04-02  fixed get_send_socket for tcp fwd to udp (andrei)
- *  2003-04-03  added su_setport (andrei)
- *  2003-04-04  update_sock_struct_from_via now differentiates between
- *               local replies  & "normal" replies (andrei)
- *  2003-04-12  update_sock_struct_from via uses also FL_FORCE_RPORT for
- *               local replies (andrei)
- *  2003-08-21  check_self properly handles ipv6 addresses & refs   (andrei)
- *  2003-10-21  check_self updated to handle proto (andrei)
- *  2003-10-24  converted to the new socket_info lists (andrei)
- *  2004-10-10  modified check_self to use grep_sock_info (andrei)
- *  2004-11-08  added force_send_socket support in get_send_socket (andrei)
- *  2005-12-11  onsend_router support; forward_request to no longer
- *              pkg_malloc'ed (andrei)
- *  2006-04-12  forward_{request,reply} use now struct dest_info (andrei)
- *  2006-04-21  basic comp via param support (andrei)
- *  2006-07-31  forward_request can resolve destination on its own, uses the 
- *              dns cache and falls back on send error to other ips (andrei)
- *  2007-10-08  get_send_socket() will ignore force_send_socket if the forced
- *               socket is multicast (andrei)
  */
 
 /*!
  * \file
- * \brief SIP-router core :: 
+ * \brief Kamailio core :: Message forwarding
  * \ingroup core
  * Module: \ref core
  */
@@ -208,7 +171,7 @@ retry:
 	su2ip_addr(&ip, &from);
 	si=find_si(&ip, 0, proto);
 	if (si==0) goto error;
-	DBG("DEBUG: get_out_socket: socket determined: %p\n", si );
+	LM_DBG("socket determined: %p\n", si );
 	if (unlikely(mhomed_sock_cache_disabled)){
 		close(*temp_sock);
 		*temp_sock=-1;
@@ -271,7 +234,7 @@ struct socket_info* get_send_socket2(struct socket_info* force_send_socket,
 			if (likely(mismatch)) *mismatch=SS_MISMATCH_PROTO;
 		}
 		if (unlikely(force_send_socket->address.af!=to->s.sa_family)){
-			DBG("get_send_socket: force_send_socket of different af"
+			LM_DBG("force_send_socket of different af"
 					" (dst %d - %s:%s forced %d -%s:%s:%d)\n",
 					to->s.sa_family, proto2a(proto), su2a(to, sizeof(*to)),
 					force_send_socket->address.af,
@@ -391,7 +354,7 @@ static struct _check_self_func {
 	struct _check_self_func *next;
 } *_check_self_func_list = NULL;
 
-/* check if _check_self_func_list is set
+/** check if _check_self_func_list is set
  * - return 1 if yes, 0 if no
  */
 int is_check_self_func_list_set(void)
@@ -399,7 +362,7 @@ int is_check_self_func_list_set(void)
 	return (_check_self_func_list)?1:0;
 }
 
-/* register a function to be called when matching for myself
+/** register a function to be called when matching for myself
  * - return 0 on success, -1 on error
  * - f must have same prototype as check_self() and return same kind of values
  */
@@ -418,7 +381,7 @@ int register_check_self_func(check_self_f f)
 	return 0;
 }
 
-/* run registered check self functions
+/** run registered check self functions
  * returns 1 if true, 0 if false
  */
 int run_check_self_func(str* host, unsigned short port, unsigned short proto)
@@ -433,7 +396,8 @@ int run_check_self_func(str* host, unsigned short port, unsigned short proto)
 	return 0;
 }
 
-/* checks if the proto: host:port is one of the address we listen on;
+/** checks if the proto: host:port is one of the address we listen on;
+ *
  * if port==0, the  port number is ignored
  * if proto==0 (PROTO_NONE) the protocol is ignored
  * returns 1 if true, 0 if false, -1 on error
@@ -445,7 +409,7 @@ int check_self(str* host, unsigned short port, unsigned short proto)
 	if (grep_sock_info(host, port, proto)) goto found;
 	/* try to look into the aliases*/
 	if (grep_aliases(host->s, host->len, port, proto)==0){
-		DBG("check_self: host != me\n");
+		LM_DBG("host != me\n");
 		return (_check_self_func_list==NULL)?0:run_check_self_func(host,
 														port, proto);
 	}
@@ -453,7 +417,7 @@ found:
 	return 1;
 }
 
-/* checks if the proto:port is one of the ports we listen on;
+/** checks if the proto:port is one of the ports we listen on;
  * if proto==0 (PROTO_NONE) the protocol is ignored
  * returns 1 if true, 0 if false, -1 on error
  */
@@ -468,7 +432,7 @@ int check_self_port(unsigned short port, unsigned short proto)
 
 
 
-/* forwards a request to dst
+/** forwards a request to dst
  * parameters:
  *   msg       - sip msg
  *   dst       - destination name, if non-null it will be resolved and
@@ -589,8 +553,8 @@ int forward_request(struct sip_msg* msg, str* dst, unsigned short port,
 		}
 #endif
 		 /* send it! */
-		DBG("Sending:\n%.*s.\n", (int)len, buf);
-		DBG("orig. len=%d, new_len=%d, proto=%d\n",
+		LM_DBG("Sending:\n%.*s.\n", (int)len, buf);
+		LM_DBG("orig. len=%d, new_len=%d, proto=%d\n",
 				msg->len, len, send_info->proto );
 	
 		if (run_onsend(msg, send_info, buf, len)==0){
@@ -707,7 +671,7 @@ int update_sock_struct_from_via( union sockaddr_union* to,
 	}else{
 		/* "normal" reply, we use rport's & received value if present */
 		if (via->rport && via->rport->value.s){
-			DBG("update_sock_struct_from_via: using 'rport'\n");
+			LM_DBG("using 'rport'\n");
 			port=str2s(via->rport->value.s, via->rport->value.len, &err);
 			if (err){
 				LM_ERR("bad rport value(%.*s)\n",
@@ -716,13 +680,13 @@ int update_sock_struct_from_via( union sockaddr_union* to,
 			}
 		}
 		if (via->received){
-			DBG("update_sock_struct_from_via: using 'received'\n");
+			LM_DBG("using 'received'\n");
 			name=&(via->received->value);
 			/* making sure that we won't do SRV lookup on "received"
 			 * (possible if no DNS_IP_HACK is used)*/
 			if (port==0) port=via->port?via->port:SIP_PORT; 
 		}else{
-			DBG("update_sock_struct_from_via: using via host\n");
+			LM_DBG("using via host\n");
 			name=&(via->host);
 			if (port==0) port=via->port;
 		}
@@ -735,7 +699,7 @@ int update_sock_struct_from_via( union sockaddr_union* to,
 	    Yes -- it happened on generating a 408 by TM; -jiri
 	    sip_resolvehost now accepts str -janakj
 	*/
-	DBG("update_sock_struct_from_via: trying SRV lookup\n");
+	LM_DBG("trying SRV lookup\n");
 	proto=via->proto;
 	he=sip_resolvehost(name, &port, &proto);
 	
@@ -750,7 +714,7 @@ int update_sock_struct_from_via( union sockaddr_union* to,
 
 
 
-/* removes first via & sends msg to the second
+/** removes first via & sends msg to the second
  * - mode param controls if modules sip response callbacks are executed */
 static int do_forward_reply(struct sip_msg* msg, int mode)
 {
@@ -825,7 +789,7 @@ static int do_forward_reply(struct sip_msg* msg, int mode)
 		if (msg->via1->i && msg->via1->i->value.s){
 			s=msg->via1->i->value.s;
 			len=msg->via1->i->value.len;
-			DBG("forward_reply: i=%.*s\n",len, ZSW(s));
+			LM_DBG("i=%.*s\n",len, ZSW(s));
 			if (reverse_hex2int(s, len, (unsigned int*)&dst.id)<0){
 				LM_ERR("bad via i param \"%.*s\"\n", len, ZSW(s));
 				dst.id=0;
@@ -866,7 +830,7 @@ static int do_forward_reply(struct sip_msg* msg, int mode)
 	STATS_TX_RESPONSE(  (msg->first_line.u.reply.statuscode/100) );
 #endif
 
-	DBG(" reply forwarded to %.*s:%d\n", 
+	LM_DBG("reply forwarded to %.*s:%d\n", 
 			msg->via2->host.len, msg->via2->host.s,
 			(unsigned short) msg->via2->port);
 
@@ -879,13 +843,13 @@ error:
 	return -1;
 }
 
-/* removes first via & sends msg to the second */
+/** removes first via & sends msg to the second */
 int forward_reply(struct sip_msg* msg)
 {
 	return do_forward_reply(msg, 0);
 }
 
-/* removes first via & sends msg to the second - no module callbacks */
+/** removes first via & sends msg to the second - no module callbacks */
 int forward_reply_nocb(struct sip_msg* msg)
 {
 	return do_forward_reply(msg, 1);
diff --git a/forward.h b/forward.h
index e1cd093..f1418d0 100644
--- a/forward.h
+++ b/forward.h
@@ -1,21 +1,14 @@
 /*
- *  $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,22 +17,13 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/*
- * History:
- * -------
- *  2001-??-?? created by andrei
- *  ????-??-?? lots of changes by a lot of people
- *  2003-02-11 added inline msg_send (andrei)
- *  2003-04-07 changed all ports to host byte order (andrei)
- *  2003-04-12  FORCE_RPORT_T added (andrei)
- *  2003-04-15  added tcp_disable support (andrei)
- *  2006-04-12  reduced msg_send() parameter list: it uses now a struct 
- *               dest_info param. (andrei)
- *  2007-10-08  msg_send() will ignore a mcast send_sock and choose another
- *               one by itself (andrei)
- */
-
-
+/*!
+* \file
+* \brief Kamailio core :: Message forwarding
+* \author andrei
+* \ingroup core
+* Module: \ref core
+*/
 
 #ifndef forward_h
 #define forward_h
diff --git a/futexlock.h b/futexlock.h
index 0f39d83..7aa7c73 100644
--- a/futexlock.h
+++ b/futexlock.h
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- * 
  * Copyright (C) 2007 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -15,7 +13,13 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/*
+/*!
+* \file
+* \brief Kamailio core :: locks
+* \author andrei
+* \ingroup core
+* Module: \ref core
+ *
  * futex based lock (mutex) implementation  (linux 2.6+ only)
  * based on Ulrich Drepper implementation in "Futexes Are Tricky"
  * (http://people.redhat.com/drepper/futex.pdf)
@@ -29,12 +33,6 @@
  *
  *  Config defines:
  */
-/* 
- * History:
- * --------
- *  2007-05-13  created by andrei
- *  2007-06-12  added ADAPTIVE_WAIT busy waiting (andrei)
- */
 
 #ifndef _futexlock_h
 #define _futexlock_h
diff --git a/globals.h b/globals.h
index 0a62d3e..60ffd25 100644
--- a/globals.h
+++ b/globals.h
@@ -1,24 +1,17 @@
 /*
- * $Id$
- *
  * global variables
  *
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -27,6 +20,12 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
+/*!
+* \file
+* \brief Kamailio core :: Global variables
+* \ingroup core
+* Module: \ref core
+*/
 
 
 
@@ -50,6 +49,8 @@ extern int config_check;
 extern char* stat_file;
 extern unsigned short port_no;
 
+extern unsigned int sr_dst_max_branches; /* max number of branches per transaction */
+
 extern time_t up_since;
 extern pid_t creator_pid;  /* pid of first process before daemonization */
 extern int uid;
@@ -127,6 +128,7 @@ extern int sock_gid;
 extern int sock_mode;
 extern char* chroot_dir;
 extern char* working_dir;
+extern char* runtime_dir;
 extern int sr_auto_aliases;
 extern int sr_msg_time;
 extern str version_table;
diff --git a/hash_func.c b/hash_func.c
index 88957bc..939361a 100644
--- a/hash_func.c
+++ b/hash_func.c
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -27,7 +20,7 @@
 
 /*!
  * \file
- * \brief SIP-router core :: 
+ * \brief Kamailio core :: Hash functions
  * \ingroup core
  * Module: \ref core
  */
diff --git a/hash_func.h b/hash_func.h
index 2d79afd..203e10b 100644
--- a/hash_func.h
+++ b/hash_func.h
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,6 +17,12 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
+/*!
+* \file
+* \brief Kamailio core :: Hash support
+* \ingroup core
+* Module: \ref core
+*/
 
 
 
diff --git a/hashes.h b/hashes.h
index 9932905..5b8e2f2 100644
--- a/hashes.h
+++ b/hashes.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2006 iptelorg GmbH 
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -15,14 +13,13 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/*
- * History:
- * --------
- *  2006-02-02  created by andrei
- *  2006-11-24  added numeric string optimized hash function (andrei)
- *  2006-12-13  split into hashes.h (more generic) and str_hash.h (andrei)
- *  2007-02-22  added case insensitive versions (andrei)
- */
+/*!
+* \file
+* \brief Kamailio core :: hash support
+* \author Andrei
+* \ingroup core
+* Module: \ref core
+*/
 
 
 #ifndef _hashes_h
@@ -32,7 +29,7 @@
 
 
 
-/* internal use: hash update
+/** internal use: hash update
  * params: char* s   - string start,
  *         char* end - end
  *         char* p,  and unsigned v temporary vars (used)
@@ -57,7 +54,7 @@
 		(h)+=(v)^((v)>>3); \
 	}while(0)
 
-/* like hash_update_str, but case insensitive 
+/** like hash_update_str, but case insensitive 
  * params: char* s   - string start,
  *         char* end - end
  *         char* p,  and unsigned v temporary vars (used)
@@ -75,12 +72,12 @@
 	}while(0)
 
 
-/* internal use: call it to adjust the h from hash_update_str */
+/** internal use: call it to adjust the h from hash_update_str */
 #define hash_finish(h) (((h)+((h)>>11))+(((h)>>13)+((h)>>23)))
 
 
 
-/* "raw" 2 strings hash
+/** "raw" 2 strings hash
  * returns an unsigned int (which you can use modulo table_size as hash value)
  */
 inline static unsigned int get_hash2_raw(const str* key1, const str* key2)
@@ -98,7 +95,7 @@ inline static unsigned int get_hash2_raw(const str* key1, const str* key2)
 
 
 
-/* "raw" 1 string hash
+/** "raw" 1 string hash
  * returns an unsigned int (which you can use modulo table_size as hash value)
  */
 inline static unsigned int get_hash1_raw(const char* s, int len)
@@ -115,7 +112,7 @@ inline static unsigned int get_hash1_raw(const char* s, int len)
 
 
 
-/* a little slower than hash_* , but better distribution for 
+/** a little slower than hash_* , but better distribution for 
  * numbers and about the same for strings */
 #define hash_update_str2(s, end, p, v, h) \
 	do{ \
@@ -128,7 +125,7 @@ inline static unsigned int get_hash1_raw(const char* s, int len)
 		(h)=16777259*(h)+((v)^((v)<<17)); \
 	}while(0)
 
-/*  like hash_update_str2 but case insensitive */
+/**  like hash_update_str2 but case insensitive */
 #define hash_update_case_str2(s, end, p, v, h) \
 	do{ \
 		for ((p)=(s); (p)<=((end)-4); (p)+=4){ \
@@ -141,12 +138,12 @@ inline static unsigned int get_hash1_raw(const char* s, int len)
 		(h)=16777259*(h)+((v)^((v)<<17)); \
 	}while(0)
 
-/* internal use: call it to adjust the h from hash_update_str */
+/** internal use: call it to adjust the h from hash_update_str */
 #define hash_finish2(h) (((h)+((h)>>7))+(((h)>>13)+((h)>>23)))
 
 
 
-/* a little slower than get_hash1_raw() , but better distribution for 
+/** a little slower than get_hash1_raw() , but better distribution for 
  * numbers and about the same for strings */
 inline static unsigned int get_hash1_raw2(const char* s, int len)
 {
diff --git a/id.c b/id.c
index 7b9dbbb..5f1413b 100644
--- a/id.c
+++ b/id.c
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2005 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -27,7 +20,7 @@
 
 /*!
  * \file
- * \brief SIP-router core :: 
+ * \brief Kamailio core :: UID handling
  * \ingroup core
  * Module: \ref core
  */
@@ -42,7 +35,7 @@ static str uid_name = STR_STATIC_INIT(AVP_UID);
 static str did_name = STR_STATIC_INIT(AVP_DID);
 
 
-/*
+/**
  * Set From UID
  */
 int set_from_uid(str* uid)
@@ -63,7 +56,7 @@ int set_from_uid(str* uid)
 }
 
 
-/* Extract username attribute from authorized credentials */
+/** Extract username attribute from authorized credentials */
 static inline str* cred_user(struct sip_msg* msg)
 {
 	struct hdr_field* h;
@@ -77,7 +70,7 @@ static inline str* cred_user(struct sip_msg* msg)
 	return &cred->digest.username.user;
 }
 
-/*
+/**
  * Set From UID
  */
 int get_from_uid(str* uid, struct sip_msg* msg)
@@ -125,7 +118,8 @@ int get_from_uid(str* uid, struct sip_msg* msg)
 	}
 }
 
-
+/** Get to UID
+ */
 int get_to_uid(str* uid, struct sip_msg* msg)
 {
 	static char buf[MAX_URI_SIZE];
@@ -142,20 +136,19 @@ int get_to_uid(str* uid, struct sip_msg* msg)
 		if (msg->REQ_METHOD == METHOD_REGISTER) {
 			if ((msg->to==0) && 
 				(parse_headers(msg, HDR_TO_F, 0) < 0 || msg->to == 0)) {
-				DBG("get_to_uid: Error while parsing To URI: "
-					" to header bad or missing\n");
+				LM_DBG("Error while parsing To URI: to header bad or missing\n");
 				return -1;
 			}
 			to = get_to(msg);
 			if (parse_uri(to->uri.s, to->uri.len, &puri) == -1) {
-				DBG("get_to_uid: Error while parsing To URI\n");
+				LM_DBG("Error while parsing To URI\n");
 				return -1;
 			}
 			p = puri.user.s;
 			uid->len = puri.user.len;
 		} else {
 			if (!msg->parsed_uri_ok && (parse_sip_msg_uri(msg) < 0)) {
-				DBG("Error while parsing the Request-URI\n");
+				LM_DBG("Error while parsing the Request-URI\n");
 				return -1;
 			}
 			p = msg->parsed_uri.user.s;
@@ -163,11 +156,11 @@ int get_to_uid(str* uid, struct sip_msg* msg)
 		}
 			
 		if (uid->len > MAX_URI_SIZE) {
-			DBG("get_to_uid: Username too long\n");
+			LM_DBG("Username too long\n");
 			return -1;
 		}
 		if (p == NULL || uid->len == 0) {
-			DBG("get_to_uid: Username is empty\n");
+			LM_DBG("Username is empty\n");
 			return -1;
 		}
 		memcpy(buf, p, uid->len);
@@ -181,7 +174,7 @@ int get_to_uid(str* uid, struct sip_msg* msg)
 }
 
 
-/*
+/**
  * Set To UID
  */
 int set_to_uid(str* uid)
@@ -202,7 +195,7 @@ int set_to_uid(str* uid)
 }
 
 
-/*
+/**
  * Return current To domain id
  */
 int get_to_did(str* did, struct sip_msg* msg)
@@ -218,7 +211,7 @@ int get_to_did(str* did, struct sip_msg* msg)
 }
 
 
-/*
+/**
  * Return current To domain id
  */
 int get_from_did(str* did, struct sip_msg* msg)
diff --git a/id.h b/id.h
index 68e2132..42cf2aa 100644
--- a/id.h
+++ b/id.h
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2005 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/io_wait.c b/io_wait.c
index 9a80700..5d2d9fc 100644
--- a/io_wait.c
+++ b/io_wait.c
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- * 
  * Copyright (C) 2005 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -15,21 +13,11 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/* 
- * tcp io wait common stuff used by tcp_main.c & tcp_read.c
- * (see io_wait.h)
- */
-/* 
- * History:
- * --------
- *  2005-06-15  created by andrei
- *  2005-06-26  added kqueue (andrei)
- *  2005-07-04  added /dev/poll (andrei)
- */
 
 /*!
  * \file
- * \brief SIP-router core :: 
+ * \brief Kamailio core :: tcp io wait common stuff used by tcp_main.c & tcp_read.c
+ * (see io_wait.h)
  * \ingroup core
  * Module: \ref core
  */
@@ -153,7 +141,7 @@ retry1:
 			goto error;
 	}
 
-	DBG("init_sigio: trying signal %d... \n", h->signo);
+	LM_DBG("trying signal %d... \n", h->signo);
 	
 	if (sigaddset(&h->sset, h->signo)==-1){
 		LM_ERR("sigaddset failed for %d: %s [%d]\n",
diff --git a/io_wait.h b/io_wait.h
index 28681e0..0485e39 100644
--- a/io_wait.h
+++ b/io_wait.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2005 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -15,10 +13,16 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/*
- * tcp io wait common stuff used by tcp_main.c & tcp_read.c
+/*!
+* \file
+* \brief Kamailio core :: tcp io wait common stuff used by tcp_main.c & tcp_read.c
+* \ingroup core
+* Module: \ref core
+* \author andrei
+*
  * All the functions are inline because of speed reasons and because they are
  * used only from 2 places.
+ *
  * You also have to define:
  *     int handle_io(struct fd_map* fm, short events, int idx) (see below)
  *     (this could be trivially replaced by a callback pointer entry attached
@@ -33,22 +37,6 @@
  *     local_free   (defaults to pkg_free)
  *
  */
-/*
- * History:
- * --------
- *  2005-06-13  created by andrei
- *  2005-06-26  added kqueue (andrei)
- *  2005-07-01  added /dev/poll (andrei)
- *  2006-05-30  sigio 64 bit workarround enabled for kernels < 2.6.5 (andrei)
- *  2007-11-22  when handle_io() is called in a loop check & stop if the fd was
- *               removed inside handle_io() (andrei)
- *  2007-11-29  support for write (POLLOUT); added io_watch_chg() (andrei)
- *  2008-02-04  POLLRDHUP & EPOLLRDHUP support (automatically enabled if POLLIN
- *               is set) (andrei)
- *  2010-06-17  re-enabled & enhanced the EV_ERROR for kqueue (andrei)
- */
-
-
 
 #ifndef _io_wait_h
 #define _io_wait_h
diff --git a/ip_addr.c b/ip_addr.c
index 458eaa0..8504740 100644
--- a/ip_addr.c
+++ b/ip_addr.c
@@ -1,24 +1,16 @@
 /*
- * $Id$
- *
- *
  * ip address & address family related functions
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -27,14 +19,8 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/*
- * History:
- * --------
- *  2003-03-19  replaced all mallocs/frees w/ pkg_malloc/pkg_free
- *  2004-10-01  mk_net fixes bad network addresses now (andrei)
- */
 
-/** inernal ip addresses representation functions.
+/** Kamailio core :: internal ip addresses representation functions.
  * @file ip_addr.c
  * @ingroup core
  * Module: @ref core
@@ -321,7 +307,50 @@ int is_mcast(struct ip_addr* ip)
 
 #endif /* USE_MCAST */
 
-
+/** get string for known protocols.
+ * @param iproto - protocol number
+ * @param utype  - 1 if result is used for URI, or 0
+ * @param vtype  - 1 if result is wanted uppercase, or 0 for lowercase
+ * @param sproto - the string for the proto
+ * @return  0 if it is a valid and supported protocol, negative otherwise
+ */
+int get_valid_proto_string(unsigned int iproto, int utype, int vtype,
+		str *sproto)
+{
+	switch(iproto){
+		case PROTO_NONE:
+			return -1;
+		case PROTO_UDP:
+			sproto->len = 3;
+			sproto->s = (vtype)?"UDP":"udp";
+			return 0;
+		case PROTO_TCP:
+			sproto->len = 3;
+			sproto->s = (vtype)?"TCP":"tcp";
+			return 0;
+		case PROTO_TLS:
+			sproto->len = 3;
+			sproto->s = (vtype)?"TLS":"tls";
+			return 0;
+		case PROTO_SCTP:
+			sproto->len = 4;
+			sproto->s = (vtype)?"SCTP":"sctp";
+			return 0;
+		case PROTO_WS:
+		case PROTO_WSS:
+			if(iproto==PROTO_WS || utype) {
+				/* ws-only in SIP URI */
+				sproto->len = 2;
+				sproto->s = (vtype)?"WS":"ws";
+			} else {
+				sproto->len = 3;
+				sproto->s = (vtype)?"WSS":"wss";
+			}
+			return 0;
+		default:
+			return -2;
+	}
+}
 
 /** get protocol name (asciiz).
  * @param proto - protocol number
@@ -329,22 +358,14 @@ int is_mcast(struct ip_addr* ip)
  */
 char* get_proto_name(unsigned int proto)
 {
+	str sproto;
 	switch(proto){
 		case PROTO_NONE:
 			return "*";
-		case PROTO_UDP:
-			return "udp";
-		case PROTO_TCP:
-			return "tcp";
-		case PROTO_TLS:
-			return "tls";
-		case PROTO_SCTP:
-			return "sctp";
-		case PROTO_WS:
-		case PROTO_WSS:
-			return "ws";
 		default:
-			return "unknown";
+			if(get_valid_proto_string(proto, 1, 0, &sproto)<0)
+				return "unknown";
+			return sproto.s;
 	}
 }
 
diff --git a/ip_addr.h b/ip_addr.h
index 2a08349..bce06fa 100644
--- a/ip_addr.h
+++ b/ip_addr.h
@@ -1,22 +1,17 @@
-/* $Id$
+/* 
  *
  * ip address family related structures
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -25,17 +20,12 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/*
- * History:
- * --------
- *  2003-02-13  added struct dest_info (andrei)
- *  2003-04-06  all ports are stored/passed in host byte order now (andrei)
- *  2006-04-20  comp support in recv_info and dest_info (andrei)
- *  2006-04-21  added init_dst_from_rcv (andrei)
- *  2007-06-26  added ip_addr_mk_any() (andrei)
- *  2008-05-21  added su2a(), ip_addr2sbuf(), ip4tosbuf(), ip62sbuf() (andrei)
- *  2009-09-14  added send flags support to dest_info (andrei)
- */
+/*!
+* \file
+* \brief Kamailio core :: ip address family related structures
+* \ingroup core
+* Module: \ref core
+*/
 
 #ifndef ip_addr_h
 #define ip_addr_h
@@ -255,7 +245,8 @@ void print_net(struct net* net);
 char* get_proto_name(unsigned int proto);
 #define proto2a get_proto_name
 
-
+int get_valid_proto_string(unsigned int iproto, int utype, int vtype,
+		str *sproto);
 
 #ifdef USE_MCAST
 /* Returns 1 if the given address is a multicast address */
diff --git a/kstats_types.h b/kstats_types.h
index b8d1629..11a4d34 100644
--- a/kstats_types.h
+++ b/kstats_types.h
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- * 
  * Copyright (C) 2010 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -15,7 +13,8 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/** kamailio statistics types.
+
+/** Kamailio Core :: kamailio statistics types.
  * This file contains type declaration for kamailio statistics.
  * They are needed when modules are loaded (sr_module.c).
  * The rest of kamailio stats are in lib/kcore (include
@@ -24,13 +23,9 @@
  * Note: kamailio statistics are obsolete. Use sr counters in new code
  * (counters.h).
  * @file kstats_types.h
- * @ingroup: core
+ * @ingroup core
+ * @author andrei
  */
-/*
- * History:
- * --------
- *  2010-08-18  initial version (andrei)
-*/
 
 #ifndef __kstats_types_h
 #define __kstats_types_h
diff --git a/lib/README b/lib/README
index 3caf1a6..b490787 100644
--- a/lib/README
+++ b/lib/README
@@ -48,7 +48,7 @@ Compilation with ser:
 --------------------
 
 Compilation and installation of these libraries is NOT DONE by running
-main ser makefile now - it MUST be done MANUALLY. To compile and install
+main Kamailio makefile now - it MUST be done MANUALLY. To compile and install
 libraries simply run
 
    make install
@@ -62,15 +62,15 @@ AFTER COMPILATION of libraries you can COMPILE MODULES using this
 libraries like PA, RLS or dialog.
 
 
-Running with ser (Linux):
+Running with Kamailio (Linux):
 ----------------
 
 The path to installed libraries must be known to linker on startup. This
-can be done by setting variable LD_LIBRARY_PATH before running ser. For
+can be done by setting variable LD_LIBRARY_PATH before running Kamailio. For
 example, if libraries were installed to default directory (/usr/local),
-you should set LD_LIBRARY_PATH=/usr/local/lib/ser. In the case of 
+you should set LD_LIBRARY_PATH=/usr/local/lib/kamailio. In the case of 
 nonstandard installation, you can use something like 
-LD_LIBRARY_PATH=/my/ser/directory/lib/ser.
+LD_LIBRARY_PATH=/my/ser/directory/lib/kamailio.
 
 Compilation without ser:
 --------------------
diff --git a/lib/binrpc/README b/lib/binrpc/README
index c58ee9f..8704682 100644
--- a/lib/binrpc/README
+++ b/lib/binrpc/README
@@ -1,4 +1,4 @@
-binrcp library
+binrpc library
 --------------
 
 prepared by Vladimir Marek
@@ -7,7 +7,7 @@ inspirated by sercmd from Andrei Pelinescu-Onciul
 Description:
 ------------
 
-This library using binrpc implementation from CTL module of SER and encapsulets
+This library using binrpc implementation from CTL module of Kamailio and encapsulates
 it for socket communication. It offers simple functional interface for sending
 messages over UNIX sockets, TCP or UDP protocol. The messages are encoded into
 binary RCP format that is much more efficient then standard XMLRPC.
@@ -31,4 +31,4 @@ Warning
 -------
 
 Double check alignment which is used for compilation to avoid nasty problem with
-structure size (if using libbinrpc library). This may occur e.g. in binrpc_parse_response!!!
\ No newline at end of file
+structure size (if using libbinrpc library). This may occur e.g. in binrpc_parse_response!!!
diff --git a/lib/binrpc/binrpc_api.c b/lib/binrpc/binrpc_api.c
index fb914cf..656b623 100644
--- a/lib/binrpc/binrpc_api.c
+++ b/lib/binrpc/binrpc_api.c
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2006 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -25,13 +18,9 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
  
-/*
+/**
  * send commands using binrpc
  *
- * History:
- * --------
- *  2006-11-09  created by vlada
- *  2006-12-20  extended by tma
  */
 
 #include <sys/types.h>
@@ -1162,6 +1151,7 @@ int binrpc_response_to_text(
 		goto error;
 	}
 
+	memset(&val, 0, sizeof(struct binrpc_val));
 	resp_handle->in_pkt.offset = resp_handle->in_pkt.in_struct = resp_handle->in_pkt.in_array = 0;
 	
 	p=resp_handle->reply_buf;
diff --git a/lib/binrpc/binrpc_api.h b/lib/binrpc/binrpc_api.h
index 1f9f22e..c04394a 100644
--- a/lib/binrpc/binrpc_api.h
+++ b/lib/binrpc/binrpc_api.h
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2006 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -25,12 +18,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-/*
- * History:
- * --------
- *  2006-11-09  created (vlada)
- */
-
 #ifndef BINRPC_API_H_
 #define BINRPC_API_H_
 
diff --git a/lib/cds/.cvsignore b/lib/cds/.cvsignore
new file mode 100644
index 0000000..724a897
--- /dev/null
+++ b/lib/cds/.cvsignore
@@ -0,0 +1,2 @@
+libser_cds.so.*
+
diff --git a/lib/doxygen.cfg b/lib/doxygen.cfg
index 98694f6..7ff61a8 100644
--- a/lib/doxygen.cfg
+++ b/lib/doxygen.cfg
@@ -3,7 +3,7 @@
 #---------------------------------------------------------------------------
 # Project related configuration options
 #---------------------------------------------------------------------------
-PROJECT_NAME           = "SER libraries"
+PROJECT_NAME           = "Kamailio libraries"
 PROJECT_NUMBER         = 1
 OUTPUT_DIRECTORY       = doc/
 CREATE_SUBDIRS         = NO
diff --git a/lib/ims/ims_getters.c b/lib/ims/ims_getters.c
index 1751641..3823806 100644
--- a/lib/ims/ims_getters.c
+++ b/lib/ims/ims_getters.c
@@ -177,7 +177,7 @@ str cscf_get_private_identity_no_realm(struct sip_msg *msg, str realm)
 {
 	str pi={0,0};
 	struct hdr_field* h=0;
-	int ret,i;
+	int i;
 
 	if (parse_headers(msg,HDR_AUTHORIZATION_F,0)!=0) {
 		return pi;
diff --git a/lib/kcore/cmpapi.c b/lib/kcore/cmpapi.c
index 055e099..ca1a782 100644
--- a/lib/kcore/cmpapi.c
+++ b/lib/kcore/cmpapi.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
@@ -23,6 +21,7 @@
 /*!
  * \file
  * \brief comparison functions
+ * \ingroup libkcore
  */
 
 #include "../../parser/parse_uri.h"
diff --git a/lib/kcore/cmpapi.h b/lib/kcore/cmpapi.h
index ba2b4e2..b001608 100644
--- a/lib/kcore/cmpapi.h
+++ b/lib/kcore/cmpapi.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
@@ -23,6 +21,7 @@
 /*!
  * \file
  * \brief comparison functions
+ * \ingroup libkcore
  */
 
 #ifndef _CMPAPI_H_
diff --git a/lib/kcore/faked_msg.c b/lib/kcore/faked_msg.c
index 70d175f..ae010e9 100644
--- a/lib/kcore/faked_msg.c
+++ b/lib/kcore/faked_msg.c
@@ -1,6 +1,4 @@
 /**
- * $Id$
- *
  * Copyright (C) 2009 Daniel-Constantin Mierla (asipto.com)
  *
  * This file is part of kamailio, a free SIP server.
@@ -19,6 +17,12 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
+/*!
+* \file
+* \brief Faked message handling
+* \ingroup libkcore
+* Module: \ref libkcore
+*/
 
 #include "../../dprint.h"
 #include "../../globals.h"
@@ -67,7 +71,7 @@ int faked_msg_init(void)
 	return 0;
 }
 
-struct sip_msg* faked_msg_next(void)
+sip_msg_t* faked_msg_next(void)
 {
 	_faked_msg.id = 1 + _faked_msg_no++;
 	_faked_msg.pid = my_pid();
@@ -75,3 +79,9 @@ struct sip_msg* faked_msg_next(void)
 	clear_branches();
 	return &_faked_msg;
 }
+
+sip_msg_t* faked_msg_get_next(void)
+{
+	faked_msg_init();
+	return faked_msg_next();
+}
diff --git a/lib/kcore/faked_msg.h b/lib/kcore/faked_msg.h
index 650f932..fe704ca 100644
--- a/lib/kcore/faked_msg.h
+++ b/lib/kcore/faked_msg.h
@@ -1,5 +1,4 @@
 /**
- * $Id$
  *
  * Copyright (C) 2009 Daniel-Constantin Mierla (asipto.com)
  *
@@ -26,6 +25,7 @@
 #include "../../parser/msg_parser.h"
 
 int faked_msg_init(void);
-struct sip_msg* faked_msg_next(void);
+sip_msg_t* faked_msg_next(void);
+sip_msg_t* faked_msg_get_next(void);
 
 #endif
diff --git a/lib/kcore/kstats_wrapper.c b/lib/kcore/kstats_wrapper.c
index 4feeebb..0c4eef0 100644
--- a/lib/kcore/kstats_wrapper.c
+++ b/lib/kcore/kstats_wrapper.c
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- * 
  * Copyright (C) 2010 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -18,12 +16,8 @@
 /** k compatible statistics implemented in terms of sr counters.
  * @file kstats_wrapper.h
  * @ingroup: libkcore
+ * @author andrei
  */
-/*
- * History:
- * --------
- *  2010-08-08  initial version (andrei)
-*/
 
 #include "kstats_wrapper.h"
 
diff --git a/lib/kcore/kstats_wrapper.h b/lib/kcore/kstats_wrapper.h
index 80cc9f8..1fe5694 100644
--- a/lib/kcore/kstats_wrapper.h
+++ b/lib/kcore/kstats_wrapper.h
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- * 
  * Copyright (C) 2010 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -31,13 +29,10 @@
  * @file kstats_wrapper.h
  * @ingroup: libkcore
  */
-/*
- * History:
- * --------
- *  2010-08-08  initial version (andrei)
- *  2010-08-18  type declaration needed by sr_module.c moved to
- *               ../../kstats_types.h (andrei)
-*/
+
+/*! @defgroup libkcore Kamailio compatibility core library
+ *
+ */
 
 #ifndef __kstats_wrapper_h
 #define __kstats_wrapper_h
diff --git a/lib/kcore/parse_privacy.c b/lib/kcore/parse_privacy.c
index a64c0d5..46beb3f 100644
--- a/lib/kcore/parse_privacy.c
+++ b/lib/kcore/parse_privacy.c
@@ -28,6 +28,7 @@
  * \file
  * \brief Privacy value parser
  * \ingroup parser
+ * Copyright (c) 2006 Juha Heinanen
  */
 
 #include <stdlib.h>
diff --git a/lib/kcore/parse_privacy.h b/lib/kcore/parse_privacy.h
index 447593e..1bb67b9 100644
--- a/lib/kcore/parse_privacy.h
+++ b/lib/kcore/parse_privacy.h
@@ -1,6 +1,4 @@
 /*
- * $Id: parse_privacy.h 4720 2008-08-23 10:56:15Z henningw $
- *
  * Copyright (c) 2006 Juha Heinanen
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/lib/kcore/parse_sst.c b/lib/kcore/parse_sst.c
index 7a18f04..7ab497a 100644
--- a/lib/kcore/parse_sst.c
+++ b/lib/kcore/parse_sst.c
@@ -1,5 +1,4 @@
 /*
- * $Id$
  * 
  * Copyright (c) 2006 SOMA Networks, Inc. <http://www.somanetworks.com/>
  *
@@ -19,15 +18,13 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2006-02-17 Initial revision (dhsueh at somanetworks.com)
  */
 
 /*!
  * \file
  * \brief SST parser
  * \ingroup parser
+ * \author dhsueh at somanetworks.com
  */
 
 #include "parse_sst.h"
diff --git a/lib/kcore/parse_sst.h b/lib/kcore/parse_sst.h
index 9476ed7..91a16c9 100644
--- a/lib/kcore/parse_sst.h
+++ b/lib/kcore/parse_sst.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (c) 2006 SOMA Networks, Inc. <http://www.somanetworks.com/>
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,15 +17,13 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2006-02-17 Initial revision (dhsueh at somanetworks.com)
  */
 
 /*!
  * \file
  * \brief SST parser
  * \ingroup parser
+ * \author dhsueh at somanetworks.com
  */
 
 #ifndef PARSE_SST_H
diff --git a/lib/kcore/radius.h b/lib/kcore/radius.h
index eadb4ea..58896af 100644
--- a/lib/kcore/radius.h
+++ b/lib/kcore/radius.h
@@ -19,17 +19,12 @@
  *
  * WARNING: Don't forget to update the dictionary if you update this file !!!
  *
- * History:
- * --------
- * 2005-06-28  multi leg call support added (bogdan)
- * 2008-09-03  added type field to attribute structure, which is set
- *             during INIT_AV.
- *
  */
 
 /*!
  * \file
  * \brief Radius support
+ * \ingroup libkcore
  */
 
 
diff --git a/lib/kcore/regexp.c b/lib/kcore/regexp.c
index 96cb96b..2dc4694 100644
--- a/lib/kcore/regexp.c
+++ b/lib/kcore/regexp.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Regular expression functions
  *
  * Copyright (C) 2003 Juha Heinanen
@@ -26,6 +24,8 @@
 /*!
  * \file 
  * \brief Regular Expression functions
+ * Copyright (C) 2003 Juha Heinanen
+ * \ingroup libkcore
  */
 
 #include <sys/types.h>
diff --git a/lib/kcore/regexp.h b/lib/kcore/regexp.h
index 11f42fe..77d7401 100644
--- a/lib/kcore/regexp.h
+++ b/lib/kcore/regexp.h
@@ -1,8 +1,6 @@
 /*
  * $Id$
  *
- * Regular expression definitions
- *
  * Copyright (C) 2003 Juha Heinanen
  *
  * This file is part of Kamailio, a free SIP server.
@@ -26,6 +24,9 @@
 /*!
  * \file 
  * \brief Regular expression definitions 
+ * Copyright (C) 2003 Juha Heinanen
+ * \author Juha Heinanen
+ * \ingroup libkcore
  */
 
 
diff --git a/lib/kcore/statistics.c b/lib/kcore/statistics.c
index 83ca76d..d18b804 100644
--- a/lib/kcore/statistics.c
+++ b/lib/kcore/statistics.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2006 Voice Sistem SRL
  *
  * This file is part of Kamailio, a free SIP server.
@@ -20,17 +18,14 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  *
  *
- * History:
- * ---------
- *  2006-01-16  first version (bogdan)
- *  2006-11-28  added get_stat_var_from_num_code() (Jeffrey Magder -
- *              SOMA Networks)
- *  2010-08-08  removed all the parts emulated by kstats_wrapper.[ch] (andrei)
  */
 
 /*!
  * \file
  * \brief Statistics support
+ * \author bogdan, andrei
+ * \author Jeffrey Magder - SOMA Networks
+ * \ingroup libkcore
  */
 
 
@@ -376,6 +371,12 @@ static int get_used_waiting_queue(
 	
 	int  waitingQueueSize = 0;
 
+#ifndef __OS_linux
+	/* /proc/net/tcp and /proc/net/udp only exists on Linux systems, so don't bother with
+	   trying to open these files */
+	return 0;
+#endif
+
 	/* Set up the file we want to open. */
 	if (forTCP) {
 		fileToOpen = "/proc/net/tcp";
diff --git a/lib/kcore/statistics.h b/lib/kcore/statistics.h
index 89a90a5..8860aa8 100644
--- a/lib/kcore/statistics.h
+++ b/lib/kcore/statistics.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2006 Voice Sistem SRL
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,17 +17,14 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  *
- * History:
- * ---------
- *  2006-01-16  first version (bogdan)
- *  2006-11-28  added get_stat_var_from_num_code() (Jeffrey Magder -
- *              SOMA Networks)
- *  2010-08-08  removed all the parts emulated by kstats_wrapper.[ch] (andrei)
  */
 
 /*!
  * \file
  * \brief Kamailio statistics handling
+ * \ingroup libkcore
+ * \author bogdan
+ * \author Jeffrey Magder - SOMA Networks
  */
 
 
diff --git a/lib/kcore/strcommon.c b/lib/kcore/strcommon.c
index ce27ab3..ccc135c 100644
--- a/lib/kcore/strcommon.c
+++ b/lib/kcore/strcommon.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2007 voice-system.ro
  *
  * This file is part of Kamailio, a free SIP server.
@@ -24,6 +22,7 @@
 /*!
  * \file
  * \brief Generic string handling functions
+ * \ingroup libkcore
  */
 
 #include "../../ut.h"
diff --git a/lib/kcore/strcommon.h b/lib/kcore/strcommon.h
index c3d0c70..a1edc3a 100644
--- a/lib/kcore/strcommon.h
+++ b/lib/kcore/strcommon.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2007 voice-system.ro
  *
  * This file is part of Kamailio, a free SIP server.
@@ -23,6 +21,7 @@
 /*!
  * \file
  * \brief Common string handling functions
+ * \ingroup libkcore
  */
 
 #ifndef _STRCOMMON_H_
diff --git a/lib/presence/.cvsignore b/lib/presence/.cvsignore
new file mode 100644
index 0000000..30e34ea
--- /dev/null
+++ b/lib/presence/.cvsignore
@@ -0,0 +1,2 @@
+libser_presence.so.*
+
diff --git a/lib/print/.cvsignore b/lib/print/.cvsignore
new file mode 100644
index 0000000..ba8401c
--- /dev/null
+++ b/lib/print/.cvsignore
@@ -0,0 +1,2 @@
+libprint.so.*
+
diff --git a/lib/shm_regex/README b/lib/shm_regex/README
index bfec807..ce4cde4 100644
--- a/lib/shm_regex/README
+++ b/lib/shm_regex/README
@@ -1,5 +1,3 @@
-$Id$
-
 Wrapper functions for regcomp, regexec, regfree, and regerror using shared
 memory allocators instead of libc malloc/realloc/free. The original functions
 are prefixed with "shm_".
diff --git a/lib/shm_regex/shm_regex.c b/lib/shm_regex/shm_regex.c
index 58df667..3d5d40b 100644
--- a/lib/shm_regex/shm_regex.c
+++ b/lib/shm_regex/shm_regex.c
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2009 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,11 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History
- * -------
- *  2009-04-03	Initial version (Miklos)
- *  2010-04-25  Use own struct with locking to work-around libc locking failure
- *              on multi-core hw (skeller)
  */
 
 #include <malloc.h>	/* hook prototypes */
diff --git a/lib/shm_regex/shm_regex.h b/lib/shm_regex/shm_regex.h
index 4430f7b..0136446 100644
--- a/lib/shm_regex/shm_regex.h
+++ b/lib/shm_regex/shm_regex.h
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2009 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,11 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History
- * -------
- *  2009-04-03	Initial version (Miklos)
- *  2010-04-25  Use own struct with locking to work-around libc locking failure
- *              on multi-core hw (skeller)
  */
 
 #ifndef _SHM_REGEX_H
diff --git a/lib/srdb1/README b/lib/srdb1/README
index bbdc03e..b710ca4 100644
--- a/lib/srdb1/README
+++ b/lib/srdb1/README
@@ -1,6 +1,4 @@
-$Id$
-
-This directory contains generic database support interface. The interface 
+This directory contains the generic database support interface - db1. The interface 
 should be used by all modules willing to communicate with a database. Kamailio
 can then switch from one database to another simply by loading a different 
 database support module. Directory example contains a very simple example 
diff --git a/lib/srdb1/db.c b/lib/srdb1/db.c
index 98d3cde..e7323e3 100644
--- a/lib/srdb1/db.c
+++ b/lib/srdb1/db.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  * Copyright (C) 2007-2008 1&1 Internet AG
  * 
@@ -20,12 +18,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
- /*
-  * History:
-  * --------
-  *  2004-06-06  bind_dbmod takes dbf as parameter (andrei)
-  *  2006-10-10  Added support for retrieving the last inserted ID (Carsten Bock, BASIS AudioNet GmbH)
-  */
 
 /**
  * \file lib/srdb1/db.c
@@ -78,19 +70,19 @@ int db_check_api(db_func_t* dbf, char *mname)
 
 	/* All modules must export db_use_table */
 	if (dbf->use_table == 0) {
-		LM_ERR("module %s does not export db_use_table function\n", mname);
+		LM_ERR("module %s does not export db_use_table function. Please check if module is loaded.\n", mname);
 		goto error;
 	}
 
 	/* All modules must export db_init */
 	if (dbf->init == 0) {
-		LM_ERR("module %s does not export db_init function\n", mname);
+		LM_ERR("module %s does not export db_init function. Please check if module is loaded.\n", mname);
 		goto error;
 	}
 
 	/* All modules must export db_close */
 	if (dbf->close == 0) {
-		LM_ERR("module %s does not export db_close function\n", mname);
+		LM_ERR("module %s does not export db_close function. Please check if module is loaded.\n", mname);
 		goto error;
 	}
 
diff --git a/lib/srdb1/db.h b/lib/srdb1/db.h
index c35b7fe..4c18542 100644
--- a/lib/srdb1/db.h
+++ b/lib/srdb1/db.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  * Copyright (C) 2007-2008 1&1 Internet AG
  *
diff --git a/lib/srdb1/db_cap.h b/lib/srdb1/db_cap.h
index 0f3bfaa..e2f785c 100644
--- a/lib/srdb1/db_cap.h
+++ b/lib/srdb1/db_cap.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2004 FhG Fokus
  * Copyright (C) 2007-2008 1&1 Internet AG
  *
diff --git a/lib/srdb1/db_con.h b/lib/srdb1/db_con.h
index c042e3d..63e160f 100644
--- a/lib/srdb1/db_con.h
+++ b/lib/srdb1/db_con.h
@@ -1,6 +1,4 @@
 /* 
- * $Id$ 
- *
  * Copyright (C) 2001-2003 FhG Fokus
  * Copyright (C) 2007-2008 1&1 Internet AG
  *
@@ -39,12 +37,17 @@
  */
 typedef struct {
 	const str* table;      /*!< Default table that should be used              */
+	const char *tquote;    /*!< Char to quote special tokens (table/column names) */
 	unsigned long tail;    /*!< Variable length tail, database module specific */
 } db1_con_t;
 
 
 /** Return the table of the connection handle */
 #define CON_TABLE(cn)      ((cn)->table)
+/** Return the tquote of the connection handle */
+#define CON_TQUOTE(cn)     ((cn)->tquote)
+/** Return the tquote of the connection handle or empty str if null */
+#define CON_TQUOTESZ(cn)   (((cn)->tquote)?((cn)->tquote):"")
 /** Return the tail of the connection handle */
 #define CON_TAIL(cn)       ((cn)->tail)
 
diff --git a/lib/srdb1/db_id.c b/lib/srdb1/db_id.c
index 32d479b..f1969c1 100644
--- a/lib/srdb1/db_id.c
+++ b/lib/srdb1/db_id.c
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- *
  * Copyright (C) 2001-2005 iptel.org
  * Copyright (C) 2007-2008 1&1 Internet AG
  *
@@ -83,7 +81,7 @@ static int parse_db_url(struct db_id* id, const str* url)
 	};
 
 	enum state st;
-	unsigned int len, i;
+	unsigned int len, i, j, a;
 	const char* begin;
 	char* prev_token;
 
@@ -164,6 +162,14 @@ static int parse_db_url(struct db_id* id, const str* url)
 				st = ST_HOST;
 				id->username = prev_token;
 				prev_token = 0;
+				a = 0;
+				/* go to last '@' to support when it is part of password */
+				for(j = i+1; j < len; j++) {
+					if(url->s[j]=='@') {
+						a = j;
+					}
+				}
+				if(a!=0) i = a;
 				if (dupl_string(&id->password, begin, url->s + i) < 0) goto err;
 				begin = url->s + i + 1;
 				break;
diff --git a/lib/srdb1/db_id.h b/lib/srdb1/db_id.h
index 94243ad..bca7e5c 100644
--- a/lib/srdb1/db_id.h
+++ b/lib/srdb1/db_id.h
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- *
  * Copyright (C) 2001-2005 iptel.org
  * Copyright (C) 2007-2008 1&1 Internet AG
  * 
diff --git a/lib/srdb1/db_key.h b/lib/srdb1/db_key.h
index 744c6a4..b69a2d1 100644
--- a/lib/srdb1/db_key.h
+++ b/lib/srdb1/db_key.h
@@ -1,6 +1,4 @@
 /* 
- * $Id$ 
- *
  * Copyright (C) 2001-2003 FhG Fokus
  * Copyright (C) 2007-2008 1&1 Internet AG
  *
diff --git a/lib/srdb1/db_locking.h b/lib/srdb1/db_locking.h
index f2a622b..0837487 100644
--- a/lib/srdb1/db_locking.h
+++ b/lib/srdb1/db_locking.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * This file is part of Kamailio, a free SIP server.
  *
  * Kamailio is free software; you can redistribute it and/or modify
diff --git a/lib/srdb1/db_op.h b/lib/srdb1/db_op.h
index f3bfc5c..31dbe44 100644
--- a/lib/srdb1/db_op.h
+++ b/lib/srdb1/db_op.h
@@ -1,6 +1,4 @@
 /* 
- * $Id$ 
- *
  * Copyright (C) 2001-2003 FhG Fokus
  * Copyright (C) 2007-2008 1&1 Internet AG
  *
diff --git a/lib/srdb1/db_pool.c b/lib/srdb1/db_pool.c
index 53ae789..6408bcf 100644
--- a/lib/srdb1/db_pool.c
+++ b/lib/srdb1/db_pool.c
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- *
  * Copyright (C) 2001-2005 iptel.org
  * Copyright (C) 2007-2008 1&1 Internet AG
  *
diff --git a/lib/srdb1/db_pool.h b/lib/srdb1/db_pool.h
index 8c008dc..298e147 100644
--- a/lib/srdb1/db_pool.h
+++ b/lib/srdb1/db_pool.h
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- *
  * Copyright (C) 2001-2005 iptel.org
  * Copyright (C) 2007-2008 1&1 Internet AG
  *
diff --git a/lib/srdb1/db_pooling.h b/lib/srdb1/db_pooling.h
index 8851b65..2577347 100644
--- a/lib/srdb1/db_pooling.h
+++ b/lib/srdb1/db_pooling.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  * Copyright (C) 2007-2008 1&1 Internet AG
  *
diff --git a/lib/srdb1/db_query.c b/lib/srdb1/db_query.c
index 193ffef..80a6556 100644
--- a/lib/srdb1/db_query.c
+++ b/lib/srdb1/db_query.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2007-2008 1&1 Internet AG
  *
  * This file is part of Kamailio, a free SIP server.
@@ -80,7 +78,8 @@ static int db_do_query_internal(const db1_con_t* _h, const db_key_t* _k, const d
 	}
 
 	if (!_c) {
-		ret = snprintf(sql_buf, sql_buffer_size, "select * from %.*s ", CON_TABLE(_h)->len, CON_TABLE(_h)->s);
+		ret = snprintf(sql_buf, sql_buffer_size, "select * from %s%.*s%s ",
+				CON_TQUOTESZ(_h), CON_TABLE(_h)->len, CON_TABLE(_h)->s, CON_TQUOTESZ(_h));
 		if (ret < 0 || ret >= sql_buffer_size) goto error;
 		off = ret;
 	} else {
@@ -88,11 +87,12 @@ static int db_do_query_internal(const db1_con_t* _h, const db_key_t* _k, const d
 		if (ret < 0 || ret >= sql_buffer_size) goto error;
 		off = ret;
 
-		ret = db_print_columns(sql_buf + off, sql_buffer_size - off, _c, _nc);
+		ret = db_print_columns(sql_buf + off, sql_buffer_size - off, _c, _nc, CON_TQUOTESZ(_h));
 		if (ret < 0) return -1;
 		off += ret;
 
-		ret = snprintf(sql_buf + off, sql_buffer_size - off, "from %.*s ", CON_TABLE(_h)->len, CON_TABLE(_h)->s);
+		ret = snprintf(sql_buf + off, sql_buffer_size - off, "from %s%.*s%s ",
+				CON_TQUOTESZ(_h), CON_TABLE(_h)->len, CON_TABLE(_h)->s, CON_TQUOTESZ(_h));
 		if (ret < 0 || ret >= (sql_buffer_size - off)) goto error;
 		off += ret;
 	}
@@ -205,15 +205,15 @@ int db_do_insert_cmd(const db1_con_t* _h, const db_key_t* _k, const db_val_t* _v
 	}
 
 	if(mode==1)
-		ret = snprintf(sql_buf, sql_buffer_size, "insert delayed into %.*s (",
-				CON_TABLE(_h)->len, CON_TABLE(_h)->s);
+		ret = snprintf(sql_buf, sql_buffer_size, "insert delayed into %s%.*s%s (",
+				CON_TQUOTESZ(_h), CON_TABLE(_h)->len, CON_TABLE(_h)->s, CON_TQUOTESZ(_h));
 	else
-		ret = snprintf(sql_buf, sql_buffer_size, "insert into %.*s (",
-				CON_TABLE(_h)->len, CON_TABLE(_h)->s);
+		ret = snprintf(sql_buf, sql_buffer_size, "insert into %s%.*s%s (",
+				CON_TQUOTESZ(_h), CON_TABLE(_h)->len, CON_TABLE(_h)->s, CON_TQUOTESZ(_h));
 	if (ret < 0 || ret >= sql_buffer_size) goto error;
 	off = ret;
 
-	ret = db_print_columns(sql_buf + off, sql_buffer_size - off, _k, _n);
+	ret = db_print_columns(sql_buf + off, sql_buffer_size - off, _k, _n, CON_TQUOTESZ(_h));
 	if (ret < 0) return -1;
 	off += ret;
 
@@ -268,7 +268,8 @@ int db_do_delete(const db1_con_t* _h, const db_key_t* _k, const db_op_t* _o,
 		return -1;
 	}
 
-	ret = snprintf(sql_buf, sql_buffer_size, "delete from %.*s", CON_TABLE(_h)->len, CON_TABLE(_h)->s);
+	ret = snprintf(sql_buf, sql_buffer_size, "delete from %s%.*s%s",
+			CON_TQUOTESZ(_h), CON_TABLE(_h)->len, CON_TABLE(_h)->s, CON_TQUOTESZ(_h));
 	if (ret < 0 || ret >= sql_buffer_size) goto error;
 	off = ret;
 
@@ -311,7 +312,8 @@ int db_do_update(const db1_con_t* _h, const db_key_t* _k, const db_op_t* _o,
 		return -1;
 	}
 
-	ret = snprintf(sql_buf, sql_buffer_size, "update %.*s set ", CON_TABLE(_h)->len, CON_TABLE(_h)->s);
+	ret = snprintf(sql_buf, sql_buffer_size, "update %s%.*s%s set ",
+			CON_TQUOTESZ(_h), CON_TABLE(_h)->len, CON_TABLE(_h)->s, CON_TQUOTESZ(_h));
 	if (ret < 0 || ret >= sql_buffer_size) goto error;
 	off = ret;
 
@@ -356,11 +358,12 @@ int db_do_replace(const db1_con_t* _h, const db_key_t* _k, const db_val_t* _v,
 		return -1;
 	}
 
-	ret = snprintf(sql_buf, sql_buffer_size, "replace %.*s (", CON_TABLE(_h)->len, CON_TABLE(_h)->s);
+	ret = snprintf(sql_buf, sql_buffer_size, "replace %s%.*s%s (",
+			CON_TQUOTESZ(_h), CON_TABLE(_h)->len, CON_TABLE(_h)->s, CON_TQUOTESZ(_h));
 	if (ret < 0 || ret >= sql_buffer_size) goto error;
 	off = ret;
 
-	ret = db_print_columns(sql_buf + off, sql_buffer_size - off, _k, _n);
+	ret = db_print_columns(sql_buf + off, sql_buffer_size - off, _k, _n, CON_TQUOTESZ(_h));
 	if (ret < 0) return -1;
 	off += ret;
 
diff --git a/lib/srdb1/db_query.h b/lib/srdb1/db_query.h
index bc12f99..fc60a87 100644
--- a/lib/srdb1/db_query.h
+++ b/lib/srdb1/db_query.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2007-2008 1&1 Internet AG
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/lib/srdb1/db_res.c b/lib/srdb1/db_res.c
index ca7b128..b07965b 100644
--- a/lib/srdb1/db_res.c
+++ b/lib/srdb1/db_res.c
@@ -1,6 +1,4 @@
 /* 
- * $Id$ 
- *
  * Copyright (C) 2001-2003 FhG Fokus
  * Copyright (C) 2007-2008 1&1 Internet AG
  *
diff --git a/lib/srdb1/db_res.h b/lib/srdb1/db_res.h
index 39f4e21..c424d9d 100644
--- a/lib/srdb1/db_res.h
+++ b/lib/srdb1/db_res.h
@@ -1,6 +1,4 @@
 /* 
- * $Id$ 
- *
  * Copyright (C) 2001-2003 FhG Fokus
  * Copyright (C) 2007-2008 1&1 Internet AG
  *
diff --git a/lib/srdb1/db_row.c b/lib/srdb1/db_row.c
index e77786a..bee34c8 100644
--- a/lib/srdb1/db_row.c
+++ b/lib/srdb1/db_row.c
@@ -1,6 +1,4 @@
 /* 
- * $Id$ 
- *
  * Copyright (C) 2001-2003 FhG Fokus
  * Copyright (C) 2007-2008 1&1 Internet AG
  *
diff --git a/lib/srdb1/db_row.h b/lib/srdb1/db_row.h
index 9a0ba20..33c65be 100644
--- a/lib/srdb1/db_row.h
+++ b/lib/srdb1/db_row.h
@@ -1,6 +1,4 @@
 /* 
- * $Id$ 
- *
  * Copyright (C) 2001-2003 FhG Fokus
  * Copyright (C) 2007-2008 1&1 Internet AG
  *
diff --git a/lib/srdb1/db_ut.c b/lib/srdb1/db_ut.c
index 344e4c6..6ed8c16 100644
--- a/lib/srdb1/db_ut.c
+++ b/lib/srdb1/db_ut.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  * Copyright (C) 2007-2008 1&1 Internet AG
  *
@@ -272,7 +270,7 @@ inline int db_time2str(time_t _v, char* _s, int* _l)
 /*
  * Print list of columns separated by comma
  */
-inline int db_print_columns(char* _b, const int _l, const db_key_t* _c, const int _n)
+int db_print_columns(char* _b, const int _l, const db_key_t* _c, const int _n, const char *_tq)
 {
 	int i, ret, len = 0;
 
@@ -283,11 +281,11 @@ inline int db_print_columns(char* _b, const int _l, const db_key_t* _c, const in
 
 	for(i = 0; i < _n; i++)	{
 		if (i == (_n - 1)) {
-			ret = snprintf(_b + len, _l - len, "%.*s ", _c[i]->len, _c[i]->s);
+			ret = snprintf(_b + len, _l - len, "%s%.*s%s ", _tq, _c[i]->len, _c[i]->s, _tq);
 			if (ret < 0 || ret >= (_l - len)) goto error;
 			len += ret;
 		} else {
-			ret = snprintf(_b + len, _l - len, "%.*s,", _c[i]->len, _c[i]->s);
+			ret = snprintf(_b + len, _l - len, "%s%.*s%s,", _tq, _c[i]->len, _c[i]->s, _tq);
 			if (ret < 0 || ret >= (_l - len)) goto error;
 			len += ret;
 		}
@@ -352,16 +350,19 @@ int db_print_where(const db1_con_t* _c, char* _b, const int _l, const db_key_t*
 				LM_ERR("Error while converting value to string\n");
 				return -1;
 			}
-			ret = snprintf(_b + len, _l - len, "%.*s&%.*s=%.*s", _k[i]->len, _k[i]->s, tmp_len, tmp_buf, tmp_len, tmp_buf);
+			ret = snprintf(_b + len, _l - len, "%s%.*s%s&%.*s=%.*s", CON_TQUOTESZ(_c),
+					_k[i]->len, _k[i]->s, CON_TQUOTESZ(_c), tmp_len, tmp_buf, tmp_len, tmp_buf);
 			if (ret < 0 || ret >= (_l - len)) goto error;
 			len += ret;
 		} else {
 			if (_o) {
-				ret = snprintf(_b + len, _l - len, "%.*s%s", _k[i]->len, _k[i]->s, _o[i]);
+				ret = snprintf(_b + len, _l - len, "%s%.*s%s%s", CON_TQUOTESZ(_c),
+						_k[i]->len, _k[i]->s, CON_TQUOTESZ(_c), _o[i]);
 				if (ret < 0 || ret >= (_l - len)) goto error;
 				len += ret;
 			} else {
-				ret = snprintf(_b + len, _l - len, "%.*s=", _k[i]->len, _k[i]->s);
+				ret = snprintf(_b + len, _l - len, "%s%.*s%s=", CON_TQUOTESZ(_c),
+						_k[i]->len, _k[i]->s, CON_TQUOTESZ(_c));
 				if (ret < 0 || ret >= (_l - len)) goto error;
 				len += ret;
 			}
@@ -402,7 +403,8 @@ int db_print_set(const db1_con_t* _c, char* _b, const int _l, const db_key_t* _k
 	}
 
 	for(i = 0; i < _n; i++) {
-		ret = snprintf(_b + len, _l - len, "%.*s=", _k[i]->len, _k[i]->s);
+		ret = snprintf(_b + len, _l - len, "%s%.*s%s=",
+				CON_TQUOTESZ(_c), _k[i]->len, _k[i]->s, CON_TQUOTESZ(_c));
 		if (ret < 0 || ret >= (_l - len)) goto error;
 		len += ret;
 
diff --git a/lib/srdb1/db_ut.h b/lib/srdb1/db_ut.h
index 30c75d3..009a190 100644
--- a/lib/srdb1/db_ut.h
+++ b/lib/srdb1/db_ut.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  * Copyright (C) 2007-2008 1&1 Internet AG
  *
@@ -133,9 +131,10 @@ int db_str2time(const char* _s, time_t* _v);
  * \param _l length of the target
  * \param _c keys that should be printed
  * \param _n number of keys
+ * \param _tq char to quote special tokens or empty string
  * \return the length of the printed result on success, negative on errors
  */
-int db_print_columns(char* _b, const int _l, const db_key_t* _c, const int _n);
+int db_print_columns(char* _b, const int _l, const db_key_t* _c, const int _n, const char *_tq);
 
 
 /**
diff --git a/lib/srdb1/db_val.c b/lib/srdb1/db_val.c
index df9199c..4a1b0a7 100644
--- a/lib/srdb1/db_val.c
+++ b/lib/srdb1/db_val.c
@@ -1,6 +1,4 @@
 /*
- * $Id$ 
- *
  * Copyright (C) 2001-2003 FhG Fokus
  * Copyright (C) 2008-2009 1&1 Internet AG
  *
diff --git a/lib/srdb1/db_val.h b/lib/srdb1/db_val.h
index 4e03412..7b0d7f5 100644
--- a/lib/srdb1/db_val.h
+++ b/lib/srdb1/db_val.h
@@ -1,6 +1,4 @@
 /* 
- * $Id$ 
- *
  * Copyright (C) 2001-2003 FhG Fokus
  * Copyright (C) 2007-2008 1&1 Internet AG
  *
diff --git a/lib/srdb1/schema/acc_cdrs.xml b/lib/srdb1/schema/acc_cdrs.xml
index 22cba14..1fe7447 100644
--- a/lib/srdb1/schema/acc_cdrs.xml
+++ b/lib/srdb1/schema/acc_cdrs.xml
@@ -9,7 +9,7 @@
 
 <table id="acc_cdrs" xmlns:db="http://docbook.org/ns/docbook">
     <name>acc_cdrs</name>
-    <version>1</version>
+    <version>2</version>
     <type db="mysql">&MYSQL_TABLE_TYPE;</type>
     <description>
         <db:para>This table is used by the ACC module to report on CDRs relying on dialog callbacks. More information is available at: &KAMAILIO_MOD_DOC;acc.html
@@ -28,26 +28,24 @@
 
 	<column id="start_time">
         <name>start_time</name>
-        <type>string</type>
-        <size>32</size>
-        <description>Start time</description>
-        <default/>
+        <type>datetime</type>
+        <description>Start date and time</description>
+        <default>2000-01-01 00:00:00</default>
     </column>
 
     <column>
         <name>end_time</name>
-        <type>string</type>
-        <size>32</size>
-        <description>End time</description>
-        <default/>
+        <type>datetime</type>
+        <description>End date and time</description>
+        <default>2000-01-01 00:00:00</default>
     </column>
 
     <column>
         <name>duration</name>
-        <type>string</type>
-        <size>32</size>
+        <type>float</type>
+        <size>10,3</size>
         <description>Duration</description>
-        <default/>
+        <default>0</default>
     </column>
 
     <index>
diff --git a/lib/srdb1/schema/aliases.xml b/lib/srdb1/schema/aliases.xml
index 5f135b9..449ca60 100644
--- a/lib/srdb1/schema/aliases.xml
+++ b/lib/srdb1/schema/aliases.xml
@@ -9,7 +9,7 @@
 
 <table id="aliases" xmlns:db="http://docbook.org/ns/docbook">
     <name>aliases</name>
-    <version>6</version>
+    <version>8</version>
     <type db="mysql">&MYSQL_TABLE_TYPE;</type>
     <description>
         <db:para>This table for the registrar module is similar to the "location" table, (the aliases index makes lookup of missed calls much faster). Thus, the function lookup("alias") can be used to map aliases to AORs. More information is available at: &KAMAILIO_MOD_DOC;registrar.html. Most people uses the dbaliases table with the alias_db module now.
@@ -35,23 +35,23 @@
         <natural/>
     </column>
 
-    <column id="username">
+	<column id="username">
         <name>&USERCOL;</name>
         <type>string</type>
         <size>&user_len;</size>
         <default/>
+        <description>Username / phone number </description>
         <natural/>
-        <description>Alias Username / Phone Number </description>
     </column>
 
     <column id="domain">
         <name>domain</name>
         <type>string</type>
         <size>&domain_len;</size>
-		<null/>
-		<default><null/></default>
-        <natural/>
+        <null/>
+        <default><null/></default>
         <description>Domain name</description>
+        <natural/>
     </column>
 
     <column id="contact">
@@ -74,13 +74,13 @@
     <column>
         <name>path</name>
         <type>string</type>
-        <size>&uri_len;</size>
+        <size>&long_hf_len;</size>
         <null/>
         <default><null/></default>
         <description>Path Header(s) per RFC 3327</description>
     </column>
 
-    <column>
+    <column id="expires">
         <name>expires</name>
         <type>datetime</type>
         <default>&DEFAULT_ALIASES_EXPIRES;</default>
@@ -125,7 +125,7 @@
         <type>int</type>
         <size>&flag_len;</size>
         <default>0</default>
-        <description>Flags</description>
+        <description>Internal flags</description>
     </column>
 
     <column>
@@ -133,7 +133,7 @@
         <type>int</type>
         <size>&flag_len;</size>
         <default>0</default>
-        <description>CFlags</description>
+        <description>Branch and contact flags</description>
     </column>
 
     <column>
@@ -179,9 +179,42 @@
         <description>The value of reg-id contact parameter</description>
     </column>
 
+    <column>
+        <name>server_id</name>
+        <type>int</type>
+        <size>11</size>
+        <default>0</default>
+        <description>The value of server_id from configuration file</description>
+    </column>
+
+    <column>
+        <name>connection_id</name>
+        <type>int</type>
+        <size>11</size>
+        <default>0</default>
+        <description>The value of connection id for location record</description>
+    </column>
+
+    <column>
+        <name>keepalive</name>
+        <type>int</type>
+        <size>11</size>
+        <default>0</default>
+        <description>The value to control sending keep alive requests</description>
+    </column>
+
 
-	<index>
-        <name>alias_idx</name>
+    <column>
+        <name>partition</name>
+        <type>int</type>
+        <size>11</size>
+        <default>0</default>
+        <description>The value to of the partition for keep alive requests</description>
+    </column>
+
+
+    <index>
+        <name>account_contact_idx</name>
         <colref linkend="username"/>
         <colref linkend="domain"/>
         <colref linkend="contact"/>
@@ -191,5 +224,9 @@
         <colref linkend="ruid"/>
         <unique/>
     </index>
+    <index>
+        <name>expires_idx</name>
+        <colref linkend="expires"/>
+    </index>
 
 </table>
diff --git a/lib/srdb1/schema/location.xml b/lib/srdb1/schema/location.xml
index be92306..698fcc0 100644
--- a/lib/srdb1/schema/location.xml
+++ b/lib/srdb1/schema/location.xml
@@ -9,7 +9,7 @@
 
 <table id="location" xmlns:db="http://docbook.org/ns/docbook">
     <name>location</name>
-    <version>6</version>
+    <version>8</version>
     <type db="mysql">&MYSQL_TABLE_TYPE;</type>
     <description>
         <db:para>Persistent user location information for the usrloc module. More information can be found at: &KAMAILIO_MOD_DOC;usrloc.html
@@ -179,6 +179,39 @@
         <description>The value of reg-id contact parameter</description>
     </column>
 
+    <column>
+        <name>server_id</name>
+        <type>int</type>
+        <size>11</size>
+        <default>0</default>
+        <description>The value of server_id from configuration file</description>
+    </column>
+
+    <column>
+        <name>connection_id</name>
+        <type>int</type>
+        <size>11</size>
+        <default>0</default>
+        <description>The value of connection id for location record</description>
+    </column>
+
+    <column>
+        <name>keepalive</name>
+        <type>int</type>
+        <size>11</size>
+        <default>0</default>
+        <description>The value to control sending keep alive requests</description>
+    </column>
+
+
+    <column>
+        <name>partition</name>
+        <type>int</type>
+        <size>11</size>
+        <default>0</default>
+        <description>The value to of the partition for keep alive requests</description>
+    </column>
+
 
     <index>
         <name>account_contact_idx</name>
diff --git a/lib/srdb1/schema/pr_presentity.xml b/lib/srdb1/schema/pr_presentity.xml
index eb793ca..88c3e9a 100644
--- a/lib/srdb1/schema/pr_presentity.xml
+++ b/lib/srdb1/schema/pr_presentity.xml
@@ -9,7 +9,7 @@
 
 <table id="presentity" xmlns:db="http://docbook.org/ns/docbook">
     <name>presentity</name>
-    <version>3</version>
+    <version>4</version>
     <type db="mysql">&MYSQL_TABLE_TYPE;</type>
     <description>
         <db:para>Table for the presence module. More information can be found at: &KAMAILIO_MOD_DOC;presence.html
@@ -84,6 +84,14 @@
         <description>Sender contact</description>
     </column>
 
+    <column>
+        <name>priority</name>
+        <type>int</type>
+        <size>11</size>
+		<default>0</default>
+        <description>Priority of the record</description>
+	</column>
+
     <index>
         <name>presentity_idx</name>
         <colref linkend="username"/>
diff --git a/lib/srdb1/schema/silo.xml b/lib/srdb1/schema/silo.xml
index 67eeb67..c605602 100644
--- a/lib/srdb1/schema/silo.xml
+++ b/lib/srdb1/schema/silo.xml
@@ -9,7 +9,7 @@
 
 <table id="silo" xmlns:db="http://docbook.org/ns/docbook">
     <name>silo</name>
-    <version>7</version>
+    <version>8</version>
     <type db="mysql">&MYSQL_TABLE_TYPE;</type>
     <description>
         <db:para> This table us used by the msilo module to provide offline message storage More information about the msilo module can be found at: &KAMAILIO_MOD_DOC;msilo.html
@@ -92,14 +92,14 @@
     <column>
         <name>body</name>
         <type>binary</type>
-        <default/>
+        <null/>
         <description>Body of the message</description>
     </column>
 
     <column>
         <name>extra_hdrs</name>
         <type>text</type>
-        <default/>
+        <null/>
         <description>Extra headers that must be restored</description>
     </column>
 
diff --git a/lib/srdb1/schema/sip_trace.xml b/lib/srdb1/schema/sip_trace.xml
index 39f6b58..00043f4 100644
--- a/lib/srdb1/schema/sip_trace.xml
+++ b/lib/srdb1/schema/sip_trace.xml
@@ -9,7 +9,7 @@
 
 <table id="sip_trace" xmlns:db="http://docbook.org/ns/docbook">
     <name>sip_trace</name>
-    <version>3</version>
+    <version>4</version>
     <type db="mysql">&MYSQL_TABLE_TYPE;</type>
     <description>
         <db:para>This table is used to store incoming/outgoing SIP messages in database. More informations can be found in the siptrace module documentation at: &KAMAILIO_MOD_DOC;siptrace.html.
@@ -105,6 +105,14 @@
     </column>
 
     <column>
+        <name>totag</name>
+        <type>string</type>
+        <size>&id_len;</size>
+        <default/>
+        <description>To tag</description>
+    </column>
+
+    <column>
         <name>direction</name>
         <type>string</type>
         <size>4</size>
diff --git a/lib/srdb2/db.c b/lib/srdb2/db.c
index da4d3f7..0527bcc 100644
--- a/lib/srdb2/db.c
+++ b/lib/srdb2/db.c
@@ -1,22 +1,15 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  * Copyright (C) 2006-2007 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -25,11 +18,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
- /*
-  * History:
-  * --------
-  *  2004-06-06  bind_dbmod takes dbf as parameter (andrei)
-  */
 
 /** \ingroup DB_API
  * @{
diff --git a/lib/srdb2/db.h b/lib/srdb2/db.h
index 4fa7b7f..cafb970 100644
--- a/lib/srdb2/db.h
+++ b/lib/srdb2/db.h
@@ -1,22 +1,15 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG FOKUS
  * Copyright (C) 2006-2007 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/lib/srdb2/db_cmd.c b/lib/srdb2/db_cmd.c
index 8265f2d..1fbfe15 100644
--- a/lib/srdb2/db_cmd.c
+++ b/lib/srdb2/db_cmd.c
@@ -1,22 +1,15 @@
 /* 
- * $Id$ 
- *
  * Copyright (C) 2001-2005 FhG FOKUS
  * Copyright (C) 2006-2007 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/lib/srdb2/db_cmd.h b/lib/srdb2/db_cmd.h
index af9dbd1..0376344 100644
--- a/lib/srdb2/db_cmd.h
+++ b/lib/srdb2/db_cmd.h
@@ -1,22 +1,15 @@
 /* 
- * $Id$ 
- *
  * Copyright (C) 2001-2005 FhG FOKUS
  * Copyright (C) 2006-2007 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/lib/srdb2/db_con.c b/lib/srdb2/db_con.c
index 0c8c1c6..dea05ac 100644
--- a/lib/srdb2/db_con.c
+++ b/lib/srdb2/db_con.c
@@ -1,22 +1,15 @@
 /* 
- * $Id$ 
- *
  * Copyright (C) 2001-2003 FhG FOKUS
  * Copyright (C) 2006-2007 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/lib/srdb2/db_con.h b/lib/srdb2/db_con.h
index 2640091..b905175 100644
--- a/lib/srdb2/db_con.h
+++ b/lib/srdb2/db_con.h
@@ -1,22 +1,15 @@
 /* 
- * $Id$ 
- *
  * Copyright (C) 2001-2003 FhG FOKUS
  * Copyright (C) 2006-2007 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/lib/srdb2/db_ctx.c b/lib/srdb2/db_ctx.c
index 4ff8bb9..b99d36c 100644
--- a/lib/srdb2/db_ctx.c
+++ b/lib/srdb2/db_ctx.c
@@ -1,22 +1,20 @@
 /* 
- * $Id$ 
- *
  * Copyright (C) 2001-2003 FhG FOKUS
  * Copyright (C) 2006-2007 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
+ * For a license to use the Kamailio software under conditions
  * other than those described here, or to purchase support for this
  * software, please contact iptel.org by e-mail at the following addresses:
  *    info at iptel.org
  *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/lib/srdb2/db_ctx.h b/lib/srdb2/db_ctx.h
index bd6e004..4268d47 100644
--- a/lib/srdb2/db_ctx.h
+++ b/lib/srdb2/db_ctx.h
@@ -1,22 +1,15 @@
 /* 
- * $Id$ 
- *
  * Copyright (C) 2001-2003 FhG FOKUS
  * Copyright (C) 2006-2007 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/lib/srdb2/db_drv.c b/lib/srdb2/db_drv.c
index aeccc17..9870fc7 100644
--- a/lib/srdb2/db_drv.c
+++ b/lib/srdb2/db_drv.c
@@ -1,22 +1,15 @@
 /* 
- * $Id$ 
- *
  * Copyright (C) 2001-2003 FhG FOKUS
  * Copyright (C) 2006-2007 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/lib/srdb2/db_drv.h b/lib/srdb2/db_drv.h
index a54ac98..4bca902 100644
--- a/lib/srdb2/db_drv.h
+++ b/lib/srdb2/db_drv.h
@@ -1,22 +1,15 @@
 /* 
- * $Id$ 
- *
  * Copyright (C) 2001-2003 FhG FOKUS
  * Copyright (C) 2006-2007 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/lib/srdb2/db_fld.c b/lib/srdb2/db_fld.c
index 3719784..749cc4f 100644
--- a/lib/srdb2/db_fld.c
+++ b/lib/srdb2/db_fld.c
@@ -1,22 +1,15 @@
 /* 
- * $Id$ 
- *
  * Copyright (C) 2001-2005 FhG FOKUS
  * Copyright (C) 2006-2007 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/lib/srdb2/db_fld.h b/lib/srdb2/db_fld.h
index 5007319..c8f957c 100644
--- a/lib/srdb2/db_fld.h
+++ b/lib/srdb2/db_fld.h
@@ -1,22 +1,15 @@
 /* 
- * $Id$ 
- *
  * Copyright (C) 2001-2003 FhG Fokus
  * Copyright (C) 2006-2007 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/lib/srdb2/db_gen.c b/lib/srdb2/db_gen.c
index 9f155f9..cf13156 100644
--- a/lib/srdb2/db_gen.c
+++ b/lib/srdb2/db_gen.c
@@ -1,22 +1,15 @@
 /* 
- * $Id$ 
- *
  * Copyright (C) 2001-2003 FhG FOKUS
  * Copyright (C) 2006-2007 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/lib/srdb2/db_gen.h b/lib/srdb2/db_gen.h
index fe18edb..a0a7466 100644
--- a/lib/srdb2/db_gen.h
+++ b/lib/srdb2/db_gen.h
@@ -1,22 +1,15 @@
 /* 
- * $Id$ 
- *
  * Copyright (C) 2001-2003 FhG FOKUS
  * Copyright (C) 2006-2007 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/lib/srdb2/db_pool.c b/lib/srdb2/db_pool.c
index f2fbadc..4f3c1b0 100644
--- a/lib/srdb2/db_pool.c
+++ b/lib/srdb2/db_pool.c
@@ -1,22 +1,15 @@
 /* 
- * $Id$
- *
  * Copyright (C) 2001-2005 iptel.org
  * Copyright (C) 2006-2007 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/lib/srdb2/db_pool.h b/lib/srdb2/db_pool.h
index c5f8cf4..21969cc 100644
--- a/lib/srdb2/db_pool.h
+++ b/lib/srdb2/db_pool.h
@@ -1,22 +1,15 @@
 /* 
- * $Id$
- *
  * Copyright (C) 2001-2005 iptel.org
  * Copyright (C) 2006-2007 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/lib/srdb2/db_rec.c b/lib/srdb2/db_rec.c
index fcc055c..18feed0 100644
--- a/lib/srdb2/db_rec.c
+++ b/lib/srdb2/db_rec.c
@@ -1,22 +1,15 @@
 /* 
- * $Id$ 
- *
  * Copyright (C) 2001-2003 FhG FOKUS
  * Copyright (C) 2006-2007 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/lib/srdb2/db_rec.h b/lib/srdb2/db_rec.h
index d650761..2f23938 100644
--- a/lib/srdb2/db_rec.h
+++ b/lib/srdb2/db_rec.h
@@ -1,22 +1,15 @@
 /* 
- * $Id$ 
- *
  * Copyright (C) 2001-2003 FhG FOKUS
  * Copyright (C) 2006-2007 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/lib/srdb2/db_res.c b/lib/srdb2/db_res.c
index f81c2be..064fee5 100644
--- a/lib/srdb2/db_res.c
+++ b/lib/srdb2/db_res.c
@@ -1,22 +1,15 @@
 /* 
- * $Id$ 
- *
  * Copyright (C) 2001-2003 FhG FOKUS
  * Copyright (C) 2006-2007 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/lib/srdb2/db_res.h b/lib/srdb2/db_res.h
index faf1fcb..fc8af94 100644
--- a/lib/srdb2/db_res.h
+++ b/lib/srdb2/db_res.h
@@ -1,22 +1,15 @@
 /* 
- * $Id$ 
- *
  * Copyright (C) 2001-2003 FhG FOKUS
  * Copyright (C) 2006-2007 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/lib/srdb2/db_uri.c b/lib/srdb2/db_uri.c
index 9423202..5c01e82 100644
--- a/lib/srdb2/db_uri.c
+++ b/lib/srdb2/db_uri.c
@@ -1,22 +1,15 @@
 /* 
- * $Id$
- *
  * Copyright (C) 2001-2005 FhG FOKUS
  * Copyright (C) 2006-2007 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/lib/srdb2/db_uri.h b/lib/srdb2/db_uri.h
index 14e4baf..51c007c 100644
--- a/lib/srdb2/db_uri.h
+++ b/lib/srdb2/db_uri.h
@@ -1,22 +1,15 @@
 /* 
- * $Id$
- *
  * Copyright (C) 2001-2005 FhG FOKUS
  * Copyright (C) 2006-2007 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/lib/srutils/README b/lib/srutils/README
index 8a8df24..5a0e9a2 100644
--- a/lib/srutils/README
+++ b/lib/srutils/README
@@ -1,7 +1,7 @@
 Library collecting various utility components needed by several modules
 #######################################################################
 
-The licesing matches the rules for core - owned by FhG or more liberal
+The licensing matches the rules for core - owned by FhG or more liberal
 like BSD or MIT style.
 
 1. TMREC
@@ -15,17 +15,17 @@ COS - RFC 2445)
 =========
 
 Adapted verision of cJSON - a C JSON parsing library - that integrates better
-with Kamailio/SER environment.
+with Kamailio environment.
 
 The changes so far:
   - rename cJSON to srjson to avoid name space conflicts
   - ability to specify malloc/free functions per JSON document. In
-  Kamailio/SER, based on needs, it can be PKG or SHM type of used memory.
+  Kamailio based on needs, it can be PKG or SHM type of used memory.
   - ability to add a string value by pointer and length - the very common
   str structure
 
 Next targets:
-  - option to clone or not the full JSON document buffer and parse using
+- option to clone or not the full JSON document buffer and parse using
   the clone (tied to and becomes usefule with the next item in this list)
   - don't clone the string values when parsing a JSON document, but set
   references to names and string values
diff --git a/lib/srutils/shautils.c b/lib/srutils/shautils.c
index 25f9e38..21cb6cc 100644
--- a/lib/srutils/shautils.c
+++ b/lib/srutils/shautils.c
@@ -19,6 +19,16 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
+/*! @defgroup srutils Various utilities
+ *
+ * Kamailio core library.
+ */
+/*!
+* \file
+* \brief srutils :: SHA and other hashing utilities
+* \ingroup srutils
+* Module: \ref srutils
+*/
 
 #include "../../md5.h"
 #include "../../ut.h"
diff --git a/lib/srutils/shautils.h b/lib/srutils/shautils.h
index 1d7b0e4..1ca8d07 100644
--- a/lib/srutils/shautils.h
+++ b/lib/srutils/shautils.h
@@ -19,6 +19,12 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
+/*!
+* \file
+* \brief srutils :: SHA and other hashing utilities
+* \ingroup srutils
+* Module: \ref srutils
+*/
 
 #ifndef _SHAUTILS_H_
 #define _SHAUTILS_H_
diff --git a/lib/srutils/srjson.c b/lib/srutils/srjson.c
index 4a7e261..b8c1945 100644
--- a/lib/srutils/srjson.c
+++ b/lib/srutils/srjson.c
@@ -20,8 +20,11 @@
    THE SOFTWARE.
    */
 
-/**
- * srjson - JSON parser in C - MIT License
+/*!
+ * \file
+ * \brief srutils :: SRjson - JSON parser in C - MIT License
+ * \ingroup srutils
+ * Module: \ref srutils
  * - addapted from cJSON to fit better within Kamailio/SER environment
  */
 
diff --git a/lib/srutils/srjson.h b/lib/srutils/srjson.h
index 4d8306f..02d65d7 100644
--- a/lib/srutils/srjson.h
+++ b/lib/srutils/srjson.h
@@ -19,6 +19,12 @@
   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   THE SOFTWARE.
 */
+/*!
+* \file
+* \brief srutils :: SRjson
+* \ingroup srutils
+* Module: \ref srutils
+*/
 
 #ifndef _srjson__h_
 #define _srjson__h_
diff --git a/lib/srutils/sruid.c b/lib/srutils/sruid.c
index ca67bfc..385252e 100644
--- a/lib/srutils/sruid.c
+++ b/lib/srutils/sruid.c
@@ -1,5 +1,4 @@
 /*
- * $Id$
  *
  * sruid - unique id generator
  *
@@ -21,6 +20,12 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
+/*!
+* \file
+* \brief srutils :: Unique ID generator
+* \ingroup srutils
+* Module: \ref srutils
+*/
 
 #include <stdio.h>
 #include <unistd.h>
diff --git a/lib/srutils/sruid.h b/lib/srutils/sruid.h
index a459188..6f1ea1d 100644
--- a/lib/srutils/sruid.h
+++ b/lib/srutils/sruid.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * sruid - unique id generator
  *
  * Copyright (C) 2012 Daniel-Constantin Mierla (asipto.com)
@@ -21,6 +19,12 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
+/*!
+* \file
+* \brief srutils :: Unique ID generator
+* \ingroup srutils
+* Module: \ref srutils
+*/
 
 #ifndef _SRUID_H_
 #define _SRUID_H_
diff --git a/lib/srutils/tmrec.c b/lib/srutils/tmrec.c
index 4b88349..07c7820 100644
--- a/lib/srutils/tmrec.c
+++ b/lib/srutils/tmrec.c
@@ -1,5 +1,4 @@
 /*
- * $Id$
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
@@ -25,7 +24,9 @@
  * Time Recurence Library according to iCalendar (RFC 2445)
  * - implemented at FhG Fokus, 2003 - external link:
  *   https://github.com/miconda/tmrec
- * - this is a clone adapted for kamailio/ser
+ * \brief srutils :: <description of this file>
+ * \ingroup srutils
+ * Module: \ref srutils
  */
 
 #include <stdio.h>
diff --git a/list.h b/list.h
index d712253..bdbecca 100644
--- a/list.h
+++ b/list.h
@@ -1,4 +1,4 @@
-/*-
+/*
  * Copyright (c) 1991, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
diff --git a/local_timer.c b/local_timer.c
index 1673e0e..6b541fd 100644
--- a/local_timer.c
+++ b/local_timer.c
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2007 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,19 +17,13 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/* local, per process timer routines
- * WARNING: this should be used only within the same process, the timers
- *  are not multi-process safe or multi-thread safe
- *  (there are no locks)
- *
- * History:
- * --------
- *  2006-02-03  created by andrei
- */
 
 /*!
  * \file
- * \brief SIP-router core :: 
+ * \brief Kamailio core :: local, per process timer routines
+ * WARNING: this should be used only within the same process, the timers
+ *  are not multi-process safe or multi-thread safe
+ *  (there are no locks)
  * \ingroup core
  * Module: \ref core
  */
@@ -53,7 +40,7 @@
 
 
 
-/* init a local_timer handle
+/** init a local_timer handle
  * returns 0 on success, -1 on error */
 int init_local_timer(struct local_timer *t, ticks_t crt_ticks)
 {
@@ -70,7 +57,7 @@ int init_local_timer(struct local_timer *t, ticks_t crt_ticks)
 	for (r=0; r<H2_ENTRIES; r++)
 		_timer_init_list(&t->timer_lst.h2[r]);
 	_timer_init_list(&t->timer_lst.expired);
-	DBG("init_local_timer: timer_list between %p and %p\n",
+	LM_DBG("timer_list between %p and %p\n",
 			&t->timer_lst.h0[0], &t->timer_lst.h2[H2_ENTRIES]);
 	return 0;
 }
@@ -83,7 +70,7 @@ void destroy_local_timer(struct local_timer* lt)
 
 
 
-/* generic add timer entry to the timer lists function (see _timer_add)
+/** generic add timer entry to the timer lists function (see _timer_add)
  * tl->expire must be set previously, delta is the difference in ticks
  * from current time to the timer desired expire (should be tl->expire-*tick)
  * If you don't know delta, you probably want to call _timer_add instead.
@@ -124,7 +111,7 @@ static inline void local_timer_redist(struct local_timer* l,
 
 
 
-/* local timer add function (no lock, not multithread or multiprocess safe,
+/** local timer add function (no lock, not multithread or multiprocess safe,
  * designed for local process use only)
  * t = current ticks
  * tl must be filled (the intial_timeout and flags must be set)
@@ -141,7 +128,7 @@ static inline int _local_timer_add(struct local_timer *h, ticks_t t,
 
 
 
-/* "public", safe timer add functions (local process use only)
+/** "public", safe timer add functions (local process use only)
  * adds a timer at delta ticks from the current time
  * returns -1 on error, 0 on success
  * WARNING: to re-add a deleted or expired timer you must call
@@ -154,8 +141,8 @@ int local_timer_add(struct local_timer* h, struct timer_ln* tl, ticks_t delta,
 	int ret;
 	
 	if (unlikely(tl->flags & F_TIMER_ACTIVE)){
-		DBG("timer_add called on an active timer %p (%p, %p),"
-					" flags %x\n", tl, tl->next, tl->prev, tl->flags);
+		LM_DBG("called on an active timer %p (%p, %p), flags %x\n",
+				tl, tl->next, tl->prev, tl->flags);
 		ret=-1; /* refusing to add active or non-reinit. timer */
 		goto error;
 	}
@@ -173,7 +160,7 @@ error:
 
 
 
-/* safe timer delete
+/** safe timer delete
  * deletes tl and inits the list pointer to 0
  * WARNING: to be able to reuse a deleted timer you must call
  *          timer_reinit(tl) on it
@@ -183,32 +170,29 @@ void local_timer_del(struct local_timer* h, struct timer_ln* tl)
 {
 	/* quick exit if timer inactive */
 	if (unlikely(!(tl->flags & F_TIMER_ACTIVE))){
-		DBG("timer_del called on an inactive timer %p (%p, %p),"
-					" flags %x\n", tl, tl->next, tl->prev, tl->flags);
+		LM_DBG("called on an inactive timer %p (%p, %p), flags %x\n",
+				tl, tl->next, tl->prev, tl->flags);
 		return;
 	}
 	if (likely((tl->next!=0)&&(tl->prev!=0))){
 		_timer_rm_list(tl); /* detach */
 		tl->next=tl->prev=0;
 	}else{
-		DBG("timer_del: (f) timer %p (%p, %p) flags %x "
-			"already detached\n",
+		LM_DBG("(f) timer %p (%p, %p) flags %x already detached\n",
 			tl, tl->next, tl->prev, tl->flags);
 	}
 }
 
 
 
-/* called from timer_handle*/
+/** called from timer_handle*/
 inline static void local_timer_list_expire(struct local_timer* l, 
 											ticks_t t, struct timer_head* h)
 {
 	struct timer_ln * tl;
 	ticks_t ret;
 	
-	/*DBG("timer_list_expire @ ticks = %lu, list =%p\n",
-			(unsigned long) *ticks, h);
-	*/
+	/*LM_DBG("@ ticks = %lu, list =%p\n", (unsigned long) *ticks, h); */
 	while(h->next!=(struct timer_ln*)h){
 		tl=h->next;
 		_timer_rm_list(tl); /* detach */
@@ -226,7 +210,7 @@ inline static void local_timer_list_expire(struct local_timer* l,
 
 
 
-/* run all the handler that expire at t ticks */
+/** run all the handler that expire at t ticks */
 static inline void local_timer_expire(struct local_timer* h, ticks_t t)
 {
 	/* trust the compiler for optimizing */
@@ -245,7 +229,7 @@ static inline void local_timer_expire(struct local_timer* h, ticks_t t)
 
 
 
-/* "main" local timer routine, should be called with a proper ticks value
+/** "main" local timer routine, should be called with a proper ticks value
  * WARNING: it should never be called twice for the same ticks value
  * (it could cause too fast expires for long timers), ticks must be also
  *  always increasing */
diff --git a/local_timer.h b/local_timer.h
index 75503ce..e981809 100644
--- a/local_timer.h
+++ b/local_timer.h
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2007 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,14 +17,17 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/* local timer routines
+/*!
+* \file
+* \brief Kamailio core :: local timer routines
+* \ingroup core
+* \author andrei
+* Module: \ref core
+*
  * WARNING: this should be used only from within the same process.
  * The local timers are not multi-process or multi-thread safe 
  *  (there are no locks)
  *
- * History:
- * --------
- *  2007-11-22  created by andrei
  */
 
 #ifndef _local_timer_h
diff --git a/lock_alloc.h b/lock_alloc.h
index 84e9dac..145aa81 100644
--- a/lock_alloc.h
+++ b/lock_alloc.h
@@ -1,21 +1,20 @@
-/* $Id$ */
 /*
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
+ * For a license to use the Kamailio software under conditions
  * other than those described here, or to purchase support for this
  * software, please contact iptel.org by e-mail at the following addresses:
  *    info at iptel.org
  *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -25,15 +24,14 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-/*
- *   ser locking library
+/*!
+* \file
+* \brief Kamailio core :: Kamailio locking library
+* \author andrei
+* \ingroup core
+* Module: \ref core
+*
  *   WARNING: don't include this directly include instead locking.h!
- * History:
- * --------
- *  2003-03-06  created by andrei (contains parts of the original locking.h)
- *  2003-03-17  fixed cast warning in shm_free (forced to void*) (andrei)
- *  2004-07-28  s/lock_set_t/gen_lock_set_t/ because of a type conflict
- *              on darwin (andrei)
  *
 Implements: (see also locking.h)
 
diff --git a/lock_ops.c b/lock_ops.c
index 3392c58..c932a84 100644
--- a/lock_ops.c
+++ b/lock_ops.c
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- * 
  * Copyright (C) 2007 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -15,18 +13,10 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/*
- *  lock operations init
- */
-/* 
- * History:
- * --------
- *  2007-05-14  created by andrei
- */
 
 /*!
  * \file
- * \brief SIP-router core :: 
+ * \brief Kamailio core ::  lock operations init
  * \ingroup core
  *
  * Module: \ref core
diff --git a/lock_ops.h b/lock_ops.h
index 097d5bb..0baa4e6 100644
--- a/lock_ops.h
+++ b/lock_ops.h
@@ -1,4 +1,3 @@
-/* $Id$ */
 /*
  *
  * Copyright (C) 2001-2003 FhG Fokus
@@ -16,25 +15,16 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/*
- *   ser locking library
+/*!
+* \file
+* \brief Kamailio core :: Kamailio locking library
+* \ingroup core
+* \author andrei
+* Module: \ref core
+*
  *   WARNING: do not include this file directly, use instead locking.h
  *   (unless you don't need to alloc/dealloc locks)
  *
- *  2002-12-16  created by andrei
- *  2003-02-20  s/gen_lock_t/gen_lock_t/ to avoid a type conflict 
- *               on solaris  (andrei)
- *  2003-03-05  lock set support added for FAST_LOCK & SYSV (andrei)
- *  2003-03-06  removed *_alloc,*_dealloc & moved them to lock_alloc.h
- *              renamed locking.h to lock_ops.h (all this to solve
- *              the locking.h<->shm_mem.h interdependency) (andrei)
- *  2003-03-10  lock set support added also for PTHREAD_MUTEX & POSIX_SEM
- *               (andrei)
- *  2003-03-17  possible signal interruptions treated for sysv (andrei)
- *  2004-07-28  s/lock_set_t/gen_lock_set_t/ because of a type conflict
- *              on darwin (andrei)
- *  2006-04-04  added lock_try(lock) and lock_set_try(s,i) (andrei)
- *  2007-05-13  added futex support (andrei)
  *
 Implements:
 
diff --git a/lock_ops_init.h b/lock_ops_init.h
index edad6bb..6eff737 100644
--- a/lock_ops_init.h
+++ b/lock_ops_init.h
@@ -1,5 +1,4 @@
 /* 
- * $Id$
  * 
  * Copyright (C) 2007 iptelorg GmbH
  *
@@ -15,13 +14,12 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/*
- * lock_ops init functions
- */
-/* 
- * History:
- * --------
- *  2007-05-14  created by andrei
+/*!
+* \file
+* \brief Kamailio core :: lock_ops init functions
+* \ingroup core
+* \author andrei
+* Module: \ref core
  */
 
 #ifndef __lock_ops_init_h
diff --git a/locking.h b/locking.h
index 6dfc11f..2d7e934 100644
--- a/locking.h
+++ b/locking.h
@@ -1,21 +1,15 @@
-/* $Id$ */
 /*
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -25,17 +19,13 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-/*
- *   ser locking library
+/*!
+* \file
+* \brief Kamailio core :: Kamailio locking library
+* \ingroup core
+* \author andrei
+* Module: \ref core
  *
- *  2002-12-16  created by andrei
- *  2003-02-20  s/gen_lock_t/gen_lock_t/ to avoid a type conflict 
- *               on solaris  (andrei)
- *  2003-03-05  lock set support added for FAST_LOCK & SYSV (andrei)
- *  2003-03-06  split in two: lock_ops.h & lock_alloc.h, to avoid
- *               shm_mem.h<->locking.h interdependency (andrei)
- *  2004-07-28  s/lock_set_t/gen_lock_set_t/ because of a type conflict
- *              on darwin (andrei)
  *
 Implements (in lock_ops.h & lock_alloc.h):
 
diff --git a/lump_struct.h b/lump_struct.h
index a9e53b2..ba07fa4 100644
--- a/lump_struct.h
+++ b/lump_struct.h
@@ -1,23 +1,17 @@
 /*
- * $Id$
  *
  * adding/removing headers or any other data chunk from a message
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -26,18 +20,13 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/* History:
- * --------
- *  2003-01-29  s/int/enum ... more convenient for gdb (jiri)
- *  2003-03-31  added subst lumps -- they expand in ip addr, port a.s.o (andrei)
- *  2003-04-01  added opt (condition) lumps (andrei)
- *  2003-04-02  added more subst lumps: SUBST_{SND,RCV}_ALL  
- *              => ip:port;transport=proto (andrei)
- *  2003-10-20  split from data_lump.h (andrei)
- *  2005-03-24  the type of type attribute changed to enum _hdr_types_t (janakj)
- *
- */
-
+/*!
+* \file
+* \brief Kamailio core :: Adding/removing headers or any other data chunk from a message
+* \ingroup core
+* \author jiri, andrei, janakj
+* Module: \ref core
+*/
 
 #ifndef lump_struct_h
 #define lump_struct_h
diff --git a/lvalue.c b/lvalue.c
index 156e506..89e1f4e 100644
--- a/lvalue.c
+++ b/lvalue.c
@@ -16,22 +16,11 @@
 
 /**
  * @file 
- * @brief SIP-router core :: lvalues (assignment)
+ * @brief Kamailio core :: lvalues (assignment)
  * \ingroup core
  * Module: \ref core
  */
 
-/* 
- * History:
- * --------
- *  2008-11-30  initial version (andrei)
- *  2009-04-24  delete avps after finding their new value and not before
- *               (fixed $avp=$avp)
- *              when assigning something undefined (e.g. non-existing avp),
- *              delete the lvalue (similar to perl)  (andrei)
- */
-
-
 #include "lvalue.h"
 #include "dprint.h"
 #include "route.h"
diff --git a/lvalue.h b/lvalue.h
index b5eccd4..9413b22 100644
--- a/lvalue.h
+++ b/lvalue.h
@@ -1,5 +1,4 @@
 /* 
- * $Id$
  * 
  * Copyright (C) 2008 iptelorg GmbH
  *
@@ -17,12 +16,8 @@
  */
 /**
  * @file 
- * @brief lvalues (assignment)
- */
-/* 
- * History:
- * --------
- *  2008-11-30  initial version (andrei)
+ * @brief Kamailio core :: lvalues (assignment)
+ * @author andrei
  */
 
 #ifndef __lvalue_h_
diff --git a/main.c b/main.c
index 7150bfe..1ff7f6a 100644
--- a/main.c
+++ b/main.c
@@ -1,16 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -19,73 +17,15 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * -------
- *  2002-01-29  argc/argv globalized via my_{argc|argv} (jiri)
- *  2003-01-23  mhomed added (jiri)
- *  2003-03-19  replaced all malloc/frees w/ pkg_malloc/pkg_free (andrei)
- *  2003-03-29  pkg cleaners for fifo and script callbacks introduced (jiri)
- *  2003-03-31  removed snmp part (obsolete & no place in core) (andrei)
- *  2003-04-06  child_init called in all processes (janakj)
- *  2003-04-08  init_mallocs split into init_{pkg,shm}_mallocs and
- *               init_shm_mallocs called after cmd. line parsing (andrei)
- *  2003-04-15  added tcp_disable support (andrei)
- *  2003-05-09  closelog() before openlog to force opening a new fd
- *               (needed on solaris) (andrei)
- *  2003-06-11  moved all signal handlers init. in install_sigs and moved it
- *               after daemonize (so that we won't catch anymore our own
- *               SIGCHLD generated when becoming session leader) (andrei)
- *              changed is_main default value to 1 (andrei)
- *  2003-06-28  kill_all_children is now used instead of kill(0, sig)
- *                see comment above it for explanations. (andrei)
- *  2003-06-29  replaced port_no_str snprintf w/ int2str (andrei)
- *  2003-10-10  added switch for config check (-c) (andrei)
- *  2003-10-24  converted to the new socket_info lists (andrei)
- *  2004-03-30  core dump is enabled by default
- *              added support for increasing the open files limit    (andrei)
- *  2004-04-28  sock_{user,group,uid,gid,mode} added
- *              user2uid() & user2gid() added  (andrei)
- *  2004-09-11  added timeout on children shutdown and final cleanup
- *               (if it takes more than 60s => something is definitely wrong
- *                => kill all or abort)  (andrei)
- *              force a shm_unlock before cleaning-up, in case we have a
- *               crashed childvwhich still holds the lock  (andrei)
- *  2004-12-02  removed -p, extended -l to support [proto:]address[:port],
- *               added parse_phostport, parse_proto (andrei)
- *  2005-06-16  always record the pid in pt[process_no].pid twice: once in the
- *               parent & once in the child to avoid a short window when one
- *               of them might use it "unset" (andrei)
- *  2005-07-25  use sigaction for setting the signal handlers (andrei)
- *  2006-07-13  added dns cache/failover init. (andrei)
- *  2006-10-13  added global variables stun_refresh_interval, stun_allow_stun
- *               and stun_allow_fp (vlada)
- *  2006-10-25  don't log messages from signal handlers if NO_SIG_DEBUG is
- *               defined; improved exit kill timeout (andrei)
- *              init_childs(PROC_MAIN) before starting tcp_main, to allow
- *               tcp usage for module started processes (andrei)
- * 2007-01-18  children shutdown procedure moved into shutdown_children;
- *               safer shutdown on start-up error (andrei)
- * 2007-02-09  TLS support split into tls-in-core (CORE_TLS) and generic TLS
- *             (USE_TLS)  (andrei)
- * 2007-06-07  added support for locking pages in mem. and using real time
- *              scheduling policies (andrei)
- * 2007-07-30  dst blacklist and DNS cache measurements added (Gergo)
- * 2008-08-08  sctp support (andrei)
- * 2008-08-19  -l support for mmultihomed addresses/addresses lists
- *                (e.g. -l (eth0, 1.2.3.4, foo.bar) ) (andrei)
- * 2010-04-19  added daemon_status_fd pipe to communicate the parent process
- *              with the main process in daemonize mode, so the parent process
- *              can return the proper exit status code (ibc)
- * 2010-08-19  moved the daemon status stuff to daemonize.c (andrei)
  */
 
-/** main file (init, daemonize, startup) 
+/** Kamailio core :: main file (init, daemonize, startup) 
  * @file main.c
  * @ingroup core
  * Module: core
  */
 
-/*! @defgroup core SIP-router core
+/*! @defgroup core Kamailio core
  *
  * sip router core part.
  */
@@ -413,6 +353,7 @@ int received_dns = 0;
 int sr_auto_aliases=1;
 char* working_dir = 0;
 char* chroot_dir = 0;
+char* runtime_dir = "" RUN_DIR;
 char* user=0;
 char* group=0;
 int uid = 0;
@@ -425,6 +366,9 @@ int sock_mode= S_IRUSR| S_IWUSR| S_IRGRP| S_IWGRP; /* rw-rw---- */
 
 int server_id = 0; /* Configurable unique ID of the server */
 
+/* maximum number of branches for transaction */
+unsigned int sr_dst_max_branches = MAX_BRANCHES_DEFAULT;
+
 /* set timeval for each received sip message */
 int sr_msg_time = 1;
 
@@ -733,9 +677,9 @@ void handle_sigs(void)
 		case SIGTERM:
 			/* we end the program in all these cases */
 			if (sig_flag==SIGINT)
-				DBG("INT received, program terminates\n");
+				LM_DBG("INT received, program terminates\n");
 			else
-				DBG("SIGTERM received, program terminates\n");
+				LM_DBG("SIGTERM received, program terminates\n");
 			LM_NOTICE("Thank you for flying " NAME "!!!\n");
 			/* shutdown/kill all the children */
 			shutdown_children(SIGTERM, 1);
@@ -800,12 +744,12 @@ void handle_sigs(void)
 #endif
 			/* exit */
 			shutdown_children(SIGTERM, 1);
-			DBG("terminating due to SIGCHLD\n");
+			LM_DBG("terminating due to SIGCHLD\n");
 			exit(0);
 			break;
 
 		case SIGHUP: /* ignoring it*/
-					DBG("SIGHUP received, ignoring it\n");
+					LM_DBG("SIGHUP received, ignoring it\n");
 					break;
 		default:
 			LM_CRIT("unhandled signal %d\n", sig_flag);
@@ -881,7 +825,7 @@ void sig_usr(int signo)
 			case SIGCHLD:
 #ifndef 			STOP_JIRIS_CHANGES
 #ifdef SIG_DEBUG /* signal unsafe stuff follows */
-					DBG("SIGCHLD received: "
+					LM_DBG("SIGCHLD received: "
 						"we do not worry about grand-children\n");
 #endif
 #else
@@ -1310,7 +1254,7 @@ int main_loop(void)
 			if (default_core_cfg.udp4_raw < 0) {
 				/* auto-detect => use it */
 				default_core_cfg.udp4_raw = 1; /* enabled */
-				DBG("raw socket possible => turning it on\n");
+				LM_DBG("raw socket possible => turning it on\n");
 			}
 			if (default_core_cfg.udp4_raw_ttl < 0) {
 				/* auto-detect */
@@ -1483,7 +1427,7 @@ int main_loop(void)
 				if (default_core_cfg.udp4_raw < 0) {
 					/* auto-detect => use it */
 					default_core_cfg.udp4_raw = 1; /* enabled */
-					DBG("raw socket possible => turning it on\n");
+					LM_DBG("raw socket possible => turning it on\n");
 				}
 				if (default_core_cfg.udp4_raw_ttl < 0) {
 					/* auto-detect */
@@ -1744,7 +1688,7 @@ int main_loop(void)
 			fprintf(stderr, "% 3d   % 5d - %s\n", r, pt[r].pid, pt[r].desc);
 		}
 #endif
-		DBG("Expect maximum %d  open fds\n", get_max_open_fds());
+		LM_DBG("Expect maximum %d  open fds\n", get_max_open_fds());
 		/* in daemonize mode send the exit code back to the parent process */
 		if (!dont_daemonize) {
 			if (daemon_status_send(0) < 0) {
@@ -1962,8 +1906,12 @@ int main(int argc, char** argv)
 					printf("flags: %s\n", ver_flags );
 					print_ct_constants();
 					printf("id: %s\n", ver_id);
-					printf("compiled on %s with %s\n",
+					if(strlen(ver_compiled_time)>0)
+						printf("compiled on %s with %s\n",
 							ver_compiled_time, ver_compiler );
+					else
+						printf("compiled with %s\n",
+							ver_compiler );
 
 					exit(0);
 					break;
@@ -2086,17 +2034,17 @@ try_again:
 			if (errno==EINTR) goto try_again; /* interrupted by signal */
 			LM_WARN("could not read from /dev/urandom (%d)\n", errno);
 		}
-		DBG("read %u from /dev/urandom\n", seed);
+		LM_DBG("read %u from /dev/urandom\n", seed);
 			close(rfd);
 	}else{
 		LM_WARN("could not open /dev/urandom (%d)\n", errno);
 	}
 	seed+=getpid()+time(0);
-	DBG("seeding PRNG with %u\n", seed);
+	LM_DBG("seeding PRNG with %u\n", seed);
 	srand(seed);
 	fastrand_seed(rand());
 	srandom(rand()+time(0));
-	DBG("test random numbers %u %lu %u\n", rand(), random(), fastrand());
+	LM_DBG("test random numbers %u %lu %u\n", rand(), random(), fastrand());
 
 	/*register builtin  modules*/
 	register_builtin_modules();
@@ -2120,6 +2068,10 @@ try_again:
 	pp_ifdef_level_check();
 	print_rls();
 
+	if(init_dst_set()<0) {
+		LM_ERR("failed to initialize destination set structure\n");
+		goto error;
+	}
 	/* options with higher priority than cfg file */
 	optind = 1;  /* reset getopt */
 	while((c=getopt(argc,argv,options))!=-1) {
@@ -2550,7 +2502,7 @@ try_again:
 	 * function being called before this point may rely on the
 	 * number of processes !
 	 */
-	DBG("Expect (at least) %d SER processes in your process list\n",
+	LM_DBG("Expect (at least) %d kamailio processes in your process list\n",
 			get_max_procs());
 
 #if defined USE_DNS_CACHE && defined USE_DNS_CACHE_STATS
diff --git a/md5utils.c b/md5utils.c
index b610cf9..8702f22 100644
--- a/md5utils.c
+++ b/md5utils.c
@@ -23,7 +23,7 @@
 
 /*!
  * \file
- * \brief SIP-router core :: md5 hash support
+ * \brief Kamailio core :: md5 hash support
  * \ingroup core
  * Module: \ref core
  */
@@ -64,6 +64,6 @@ void MD5StringArray (char *dst, str src[], int size)
   U_MD5Final (digest, &context);
 
   string2hex(digest, 16, dst );
-  DBG("DEBUG: MD5 calculated: %.*s\n", MD5_LEN, dst );
+  LM_DBG("MD5 calculated: %.*s\n", MD5_LEN, dst );
 
 }
diff --git a/md5utils.h b/md5utils.h
index a16c8f3..a8df9cb 100644
--- a/md5utils.h
+++ b/md5utils.h
@@ -1,19 +1,14 @@
 /* 
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -25,7 +20,7 @@
 
 /*!
  * \file
- * \brief SIP-router core :: md5 hash support
+ * \brief Kamailio core :: MD5 digest support
  * \ingroup core
  * Module: \ref core
  */
diff --git a/mem/Readme.tlsf.txt b/mem/Readme.tlsf.txt
new file mode 100644
index 0000000..f56d0b7
--- /dev/null
+++ b/mem/Readme.tlsf.txt
@@ -0,0 +1,102 @@
+Two Level Segregated Fit memory allocator implementation.
+Written by Matthew Conte (matt at baisoku.org).
+Public Domain, no restrictions.
+
+	http://tlsf.baisoku.org
+
+Features
+--------
+* O(1) cost for malloc, free, realloc, memalign
+* Extremely low overhead per allocation (4 bytes)
+* Low overhead per TLSF management of pools (~3kB)
+* Low fragmentation
+* Compiles to only a few kB of code and data
+* Support for adding and removing memory pool regions on the fly
+
+Caveats
+-------
+* Currently, assumes architecture can make 4-byte aligned accesses
+* Not designed to be thread safe; the user must provide this
+
+Notes
+-----
+This code was based on the TLSF 1.4 spec and documentation found at:
+
+	http://rtportal.upv.es/rtmalloc/allocators/tlsf/index.shtml
+
+It also leverages the TLSF 2.0 improvement to shrink the per-block overhead
+from 8 to 4 bytes.
+
+Known Issues
+------------
+* Due to the internal block structure size and the implementation
+details of tlsf_memalign, there is worst-case behavior when requesting
+small (<16 byte) blocks aligned to 8-byte boundaries. Overuse of memalign
+will generally increase fragmentation, but this particular case will leave
+lots of unusable "holes" in the pool. The solution would be to internally
+align all blocks to 8 bytes, but this will require significantl changes
+to the implementation. Contact me if you are interested.
+
+History
+-------
+2014/02/08 - v3.0
+   * This version is based on improvements from 3DInteractive GmbH
+   * Interface changed to allow more than one memory pool
+   * Separated pool handling from control structure (adding, removing, debugging)
+   * Control structure and pools can still be constructed in the same memory block
+   * Memory blocks for control structure and pools are checked for alignment
+   * Added functions to retrieve control structure size, alignment size, min and
+     max block size, overhead of pool structure, and overhead of a single allocation
+   * Minimal Pool size is tlsf_block_size_min() + tlsf_pool_overhead()
+   * Pool must be empty when it is removed, in order to allow O(1) removal
+
+2011/10/20 - v2.0
+   * 64-bit support
+   * More compiler intrinsics for ffs/fls
+   * ffs/fls verification during TLSF creation in debug builds
+
+2008/04/04 - v1.9
+   * Add tlsf_heap_check, a heap integrity check
+   * Support a predefined tlsf_assert macro
+   * Fix realloc case where block should shrink; if adjacent block is
+     in use, execution would go down the slow path
+
+2007/02/08 - v1.8
+   * Fix for unnecessary reallocation in tlsf_realloc
+
+2007/02/03 - v1.7
+   * tlsf_heap_walk takes a callback
+   * tlsf_realloc now returns NULL on failure
+   * tlsf_memalign optimization for 4-byte alignment
+   * Usage of size_t where appropriate
+
+2006/11/21 - v1.6
+   * ffs/fls broken out into tlsfbits.h
+   * tlsf_overhead queries per-pool overhead
+
+2006/11/07 - v1.5
+   * Smart realloc implementation
+   * Smart memalign implementation
+
+2006/10/11 - v1.4
+   * Add some ffs/fls implementations
+   * Minor code footprint reduction
+
+2006/09/14 - v1.3
+   * Profiling indicates heavy use of blocks of
+     size 1-128, so implement small block handling
+   * Reduce pool overhead by about 1kb
+   * Reduce minimum block size from 32 to 12 bytes
+   * Realloc bug fix
+
+2006/09/09 - v1.2
+   * Add tlsf_block_size
+   * Static assertion mechanism for invariants
+   * Minor bugfixes 
+
+2006/09/01 - v1.1
+   * Add tlsf_realloc
+   * Add tlsf_walk_heap
+
+2006/08/25 - v1.0
+   * First release
diff --git a/mem/f_malloc.c b/mem/f_malloc.c
index 053b589..fa8cb49 100644
--- a/mem/f_malloc.c
+++ b/mem/f_malloc.c
@@ -1,7 +1,7 @@
 /*
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of sip-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -16,30 +16,6 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/*
- * History:
- * --------
- *              created by andrei
- *  2003-07-06  added fm_realloc (andrei)
- *  2004-07-19  fragments book keeping code and support for 64 bits
- *               memory blocks (64 bits machine & size >=2^32) 
- *              GET_HASH s/</<=/ (avoids waste of 1 hash cell)   (andrei)
- *  2004-11-10  support for > 4Gb mem., switched to long (andrei)
- *  2005-03-02  added fm_info() (andrei)
- *  2005-12-12  fixed realloc shrink real_used accounting (andrei)
- *              fixed initial size (andrei)
- *  2006-02-03  fixed realloc out of mem. free bug (andrei)
- *  2006-04-07  s/DBG/MDBG (andrei)
- *  2007-02-23  added fm_available() (andrei)
- *  2007-06-23  added hash bitmap (andrei)
- *  2009-09-28  added fm_sums() (patch from Dragos Vingarzan)
- *  2010-03-11  fix big fragments bug (smaller fragment was wrongly
- *               returned sometimes) (andrei)
- *  2010-03-12  fix real_used stats for realloc: a realloc that shrank an
- *               allocation accounted twice fro the frag. overhead (andrei)
- *  2010-09-30  fixed search for big fragments using the hash bitmap
- *               (only the first bucket was tried) (andrei)
- */
 
 /**
  * \file
diff --git a/mem/f_malloc.h b/mem/f_malloc.h
index 099284a..fef53cb 100644
--- a/mem/f_malloc.h
+++ b/mem/f_malloc.h
@@ -1,7 +1,7 @@
 /*
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of sip-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -16,17 +16,6 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/*
- * History:
- * --------
- *  2003-05-21  on sparc64 roundto 8 even in debugging mode (so malloc'ed
- *               long longs will be 64 bit aligned) (andrei)
- *  2004-07-19  support for 64 bit (2^64 mem. block) and more info
- *               for the future de-fragmentation support (andrei)
- *  2004-11-10  support for > 4Gb mem., switched to long (andrei)
- *  2007-06-23  added hash bitmap (andrei)
- */
-
 /**
  * \file
  * \brief Simple, very fast, malloc library
diff --git a/mem/ll_malloc.c b/mem/ll_malloc.c
index 3226844..7e3b7d1 100644
--- a/mem/ll_malloc.c
+++ b/mem/ll_malloc.c
@@ -1,8 +1,9 @@
-/* $Id$
- *
+/*
  * shared memory, multi-process safe, pool based, mostly lockless version of 
  *  f_malloc
  *
+ * This file is part of Kamailio, a free SIP server.
+ *
  * Copyright (C) 2007 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -17,25 +18,6 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/*
- * History:
- * --------
- *              created by andrei
- *  2003-07-06  added fm_realloc (andrei)
- *  2004-07-19  fragments book keeping code and support for 64 bits
- *               memory blocks (64 bits machine & size >=2^32) 
- *              GET_HASH s/</<=/ (avoids waste of 1 hash cell)   (andrei)
- *  2004-11-10  support for > 4Gb mem., switched to long (andrei)
- *  2005-03-02  added fm_info() (andrei)
- *  2005-12-12  fixed realloc shrink real_used accounting (andrei)
- *              fixed initial size (andrei)
- *  2006-02-03  fixed realloc out of mem. free bug (andrei)
- *  2006-04-07  s/DBG/MDBG (andrei)
- *  2007-02-23  added fm_available() (andrei)
- *  2007-06-09  forked from the fm_maloc code (andrei)
- *  2007-06-11  forked from the sfm_maloc code (andrei)
- */
-
 
 #ifdef LL_MALLOC
 
diff --git a/mem/ll_malloc.h b/mem/ll_malloc.h
index 34c4fb3..ad366cd 100644
--- a/mem/ll_malloc.h
+++ b/mem/ll_malloc.h
@@ -1,8 +1,9 @@
-/* $Id$
- *
+/*
  * shared memory, multi-process safe, pool based, mostly lockless version of 
  *  f_malloc
  *
+ * This file is part of Kamailio, a free SIP server.
+ *
  * Copyright (C) 2007 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -17,17 +18,6 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/*
- * History:
- * --------
- *  2003-05-21  on sparc64 roundto 8 even in debugging mode (so malloc'ed
- *               long longs will be 64 bit aligned) (andrei)
- *  2004-07-19  support for 64 bit (2^64 mem. block) and more info
- *               for the future de-fragmentation support (andrei)
- *  2004-11-10  support for > 4Gb mem., switched to long (andrei)
- *  2007-06-11  forked from the sf_malloc code (andrei)
- */
-
 
 #if !defined(ll_malloc_h)  
 #define ll_malloc_h
diff --git a/mem/mem.c b/mem/mem.c
index 51d9050..18fb9af 100644
--- a/mem/mem.c
+++ b/mem/mem.c
@@ -1,7 +1,7 @@
 /*
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of sip-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -16,10 +16,6 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  *
  *
- * History:
- * --------
- *  2003-04-08  init_mallocs split into init_{pkg,shm}_malloc (andrei)
- * 
  */
 
 /**
@@ -55,6 +51,8 @@
 		struct fm_block* mem_block = 0;
 	#elif defined DL_MALLOC
 		/* don't need this */
+	#elif defined TLSF_MALLOC
+		tlsf_t mem_block = 0;
 	#else
 		struct qm_block* mem_block = 0;
 	#endif
@@ -79,6 +77,8 @@ int init_pkg_mallocs(void)
 			mem_block=fm_malloc_init(mem_pool, pkg_mem_size, MEM_TYPE_PKG);
 	#elif DL_MALLOC
 		/* don't need this */
+	#elif TLSF_MALLOC
+		mem_block = tlsf_create_with_pool(mem_pool, pkg_mem_size);
 	#else
 		if (mem_pool)
 			mem_block=qm_malloc_init(mem_pool, pkg_mem_size, MEM_TYPE_PKG);
diff --git a/mem/mem.h b/mem/mem.h
index 65ea670..432f29a 100644
--- a/mem/mem.h
+++ b/mem/mem.h
@@ -1,7 +1,7 @@
 /*
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of sip-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -16,16 +16,6 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/*
- * History:
- * --------
- *  2003-03-10  __FUNCTION__ is a gcc-ism, defined it to "" for sun cc
- *               (andrei)
- *  2003-03-07  split init_malloc into init_pkg_mallocs & init_shm_mallocs 
- *               (andrei)
- *  2007-02-23   added pkg_info() and pkg_available() (andrei)
- */
-
 /**
  * \defgroup mem SIP-router memory manager
  * \brief  SIP-router internal memory manager
@@ -59,6 +49,14 @@
 	#elif defined(DBG_QM_MALLOC)
 		#define DBG_F_MALLOC
 	#endif
+#elif defined TLSF_MALLOC
+	#ifdef DBG_TLSF_MALLOC
+		#ifndef DBG_QM_MALLOC
+			#define DBG_QM_MALLOC
+		#endif
+	#elif defined(DBG_QM_MALLOC)
+		#define DBG_TLSF_MALLOC
+	#endif
 #endif
 
 #ifdef PKG_MALLOC
@@ -67,6 +65,9 @@
 		extern struct fm_block* mem_block;
 #	elif defined DL_MALLOC
 #		include "dl_malloc.h"
+#	elif defined TLSF_MALLOC
+#		include "tlsf.h"
+		extern tlsf_t mem_block;
 #   else
 #		include "q_malloc.h"
 		extern struct qm_block* mem_block;
@@ -85,6 +86,13 @@
 				_SRC_FUNCTION_, _SRC_LINE_)
 #			define pkg_realloc(p, s) fm_realloc(mem_block, (p), (s), \
 					_SRC_LOC_, _SRC_FUNCTION_, _SRC_LINE_)
+#		elif defined TLSF_MALLOC
+#			define pkg_malloc(s) tlsf_malloc(mem_block, (s), _SRC_LOC_, \
+				_SRC_FUNCTION_, _SRC_LINE_)
+#			define pkg_free(p)   tlsf_free(mem_block, (p), _SRC_LOC_,  \
+				_SRC_FUNCTION_, _SRC_LINE_)
+#			define pkg_realloc(p, s) tlsf_realloc(mem_block, (p), (s), \
+					_SRC_LOC_, _SRC_FUNCTION_, _SRC_LINE_)
 #		else
 #			define pkg_malloc(s) qm_malloc(mem_block, (s),_SRC_LOC_, \
 				_SRC_FUNCTION_, _SRC_LINE_)
@@ -102,6 +110,10 @@
 #			define pkg_malloc(s) dlmalloc((s))
 #			define pkg_realloc(p, s) dlrealloc((p), (s))
 #			define pkg_free(p)   dlfree((p))
+#		elif defined TLSF_MALLOC
+#			define pkg_malloc(s) tlsf_malloc(mem_block, (s))
+#			define pkg_realloc(p, s) tlsf_realloc(mem_block, (p), (s))
+#			define pkg_free(p)   tlsf_free(mem_block, (p))
 #		else
 #			define pkg_malloc(s) qm_malloc(mem_block, (s))
 #			define pkg_realloc(p, s) qm_realloc(mem_block, (p), (s))
@@ -118,6 +130,11 @@
 #		define pkg_info(mi)  0
 #		define pkg_available()  0
 #		define pkg_sums()  0
+#	elif defined TLSF_MALLOC
+#		define pkg_status()  tlsf_status(mem_block)
+#		define pkg_info(mi)  tlsf_meminfo(mem_block, (mi))
+#		define pkg_available()  tlsf_available(mem_block)
+#		define pkg_sums()  tlsf_sums(mem_block)
 #	else
 #		define pkg_status()    qm_status(mem_block)
 #		define pkg_info(mi)    qm_info(mem_block, mi)
diff --git a/mem/memdbg.h b/mem/memdbg.h
index b59f281..65af555 100644
--- a/mem/memdbg.h
+++ b/mem/memdbg.h
@@ -1,6 +1,8 @@
 /*
  * Copyright (C) 2006 iptelorg GmbH
  *
+ * This file is part of Kamailio, a free SIP server.
+ *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
  * copyright notice and this permission notice appear in all copies.
@@ -14,12 +16,6 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/*
- * History:
- * --------
- *  2006-04-07             created by andrei
- */
-
 /**
  * \file
  * \brief Malloc debug messages
diff --git a/mem/meminfo.h b/mem/meminfo.h
index 7458384..9c7760d 100644
--- a/mem/meminfo.h
+++ b/mem/meminfo.h
@@ -1,7 +1,7 @@
 /*
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of sip-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -16,13 +16,6 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/*
- * History:
- * --------
- *  2005-03-02  created (andrei)
- *  2005-07-25  renamed meminfo to mem_info due to name conflict on solaris
- */
-
 /**
  * \file
  * \brief Memory manager (malloc) informations and statistics
diff --git a/mem/memtest.c b/mem/memtest.c
index 2cec6c6..1b8f178 100644
--- a/mem/memtest.c
+++ b/mem/memtest.c
@@ -1,9 +1,7 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of sip-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
diff --git a/mem/q_malloc.c b/mem/q_malloc.c
index b6a0546..11ccd37 100644
--- a/mem/q_malloc.c
+++ b/mem/q_malloc.c
@@ -1,7 +1,7 @@
 /*
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of sip-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -16,25 +16,6 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/*
- * History:
- * --------
- *  ????-??-??  created by andrei
- *  2003-04-14  more debugging added in DBG_QM_MALLOC mode (andrei)
- *  2003-06-29  added qm_realloc (andrei)
- *  2004-07-19  fragments book keeping code and support for 64 bits
- *               memory blocks (64 bits machine & size>=2^32) (andrei)
- *              GET_HASH s/</<=/ (avoids waste of 1 hash cell) (andrei)
- *  2004-11-10  support for > 4Gb mem., switched to long (andrei)
- *  2005-03-02  added qm_info() (andrei)
- *  2005-12-12  fixed realloc shrink real_used & used accounting;
- *              fixed initial size (andrei)
- *  2006-02-03  fixed realloc out of mem. free bug (andrei)
- *  2006-04-07  s/DBG/MDBG (andrei)
- *  2007-02-23  added fm_available() (andrei)
- *  2009-09-28  added fm_sums() (patch from Dragos Vingarzan)
- */
-
 /**
  * \file
  * \brief Simple & fast malloc library
@@ -42,7 +23,7 @@
  */
 
 
-#if !defined(q_malloc) && !(defined F_MALLOC)
+#if !defined(q_malloc) && !(defined F_MALLOC) && !defined(TLSF_MALLOC)
 #define q_malloc
 
 #include <stdlib.h>
diff --git a/mem/q_malloc.h b/mem/q_malloc.h
index ee107f9..e02853d 100644
--- a/mem/q_malloc.h
+++ b/mem/q_malloc.h
@@ -1,7 +1,7 @@
 /*
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of sip-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -16,23 +16,13 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/*
- * History:
- * --------
- *  2003-05-21  on sparc64 roundto 8 even in debugging mode (so malloc'ed
- *               long longs will be 64 bit aligned) (andrei)
- *  2004-07-19  support for 64 bit (2^64 mem. block) and more info
- *               for the future de-fragmentation support (andrei)
- *  2004-11-10  support for > 4Gb mem. (switched to long) (andrei)
- */
-
 /**
  * \file
  * \brief Simple & fast malloc library
  * \ingroup mem
  */
 
-#if !defined(q_malloc_h) && !defined(F_MALLOC)
+#if !defined(q_malloc_h) && !defined(F_MALLOC) && !defined(TLSF_MALLOC)
 #define q_malloc_h
 
 #include "meminfo.h"
diff --git a/mem/sf_malloc.c b/mem/sf_malloc.c
index c83d557..5cb0258 100644
--- a/mem/sf_malloc.c
+++ b/mem/sf_malloc.c
@@ -1,7 +1,8 @@
-/* $Id$
- *
+/*
  * shared memory, multi-process safe, pool based version of f_malloc
  *
+ * This file is part of Kamailio, a free SIP server.
+ *
  * Copyright (C) 2007 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -16,24 +17,6 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/*
- * History:
- * --------
- *              created by andrei
- *  2003-07-06  added fm_realloc (andrei)
- *  2004-07-19  fragments book keeping code and support for 64 bits
- *               memory blocks (64 bits machine & size >=2^32) 
- *              GET_HASH s/</<=/ (avoids waste of 1 hash cell)   (andrei)
- *  2004-11-10  support for > 4Gb mem., switched to long (andrei)
- *  2005-03-02  added fm_info() (andrei)
- *  2005-12-12  fixed realloc shrink real_used accounting (andrei)
- *              fixed initial size (andrei)
- *  2006-02-03  fixed realloc out of mem. free bug (andrei)
- *  2006-04-07  s/DBG/MDBG (andrei)
- *  2007-02-23  added fm_available() (andrei)
- *  2007-06-09  forked from the fm_maloc code (andrei)
- */
-
 
 #ifdef SF_MALLOC
 
diff --git a/mem/sf_malloc.h b/mem/sf_malloc.h
index 3e74a68..262d2bb 100644
--- a/mem/sf_malloc.h
+++ b/mem/sf_malloc.h
@@ -1,7 +1,8 @@
-/* $Id$
- *
+/*
  * shared memory, multi-process safe, pool based version of f_malloc
  *
+ * This file is part of Kamailio, a free SIP server.
+ *
  * Copyright (C) 2007 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -16,16 +17,6 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/*
- * History:
- * --------
- *  2003-05-21  on sparc64 roundto 8 even in debugging mode (so malloc'ed
- *               long longs will be 64 bit aligned) (andrei)
- *  2004-07-19  support for 64 bit (2^64 mem. block) and more info
- *               for the future de-fragmentation support (andrei)
- *  2004-11-10  support for > 4Gb mem., switched to long (andrei)
- *  2007-06-09  forked from the f_malloc code (andrei)
- */
 
 
 #if !defined(sf_malloc_h)  
diff --git a/mem/shm_mem.c b/mem/shm_mem.c
index 4401002..2c58c44 100644
--- a/mem/shm_mem.c
+++ b/mem/shm_mem.c
@@ -1,9 +1,7 @@
 /*
-
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of sip-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -18,16 +16,6 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/*
- * History:
- * --------
- *  2003-03-12  split shm_mem_init in shm_getmem & shm_mem_init_mallocs
- *               (andrei)
- *  2004-07-27  ANON mmap support, needed on darwin (andrei)
- *  2004-09-19  shm_mem_destroy: destroy first the lock & then unmap (andrei)
- *  2007-06-10   support for sfm_malloc & shm_malloc_destroy() (andrei)
- */
-
 /**
  * \file
  * \brief  Shared memory functions
@@ -76,6 +64,8 @@ static void* shm_mempool=(void*)-1;
 	struct fm_block* shm_block;
 #elif DL_MALLOC
 	mspace shm_block;
+#elif TLSF_MALLOC
+	tlsf_t shm_block;
 #else
 	struct qm_block* shm_block;
 #endif
diff --git a/mem/shm_mem.h b/mem/shm_mem.h
index f726a05..d31ce6b 100644
--- a/mem/shm_mem.h
+++ b/mem/shm_mem.h
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of sip-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -18,16 +18,6 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/*
- * History:
- * --------
- *  2003-06-29  added shm_realloc & replaced shm_resize (andrei)
- *  2003-11-19  reverted shm_resize to the old version, using
- *               realloc causes terrible fragmentation  (andrei)
- *  2005-03-02   added shm_info() & re-eneabled locking on shm_status (andrei)
- *  2007-02-23   added shm_available() (andrei)
- *  2007-06-10   support for sf_malloc (andrei)
- */
 
 /**
  * \file
@@ -67,6 +57,14 @@
 	#elif defined(DBG_QM_MALLOC)
 		#define DBG_F_MALLOC
 	#endif
+#elif defined TLSF_MALLOC
+	#ifdef DBG_TLSF_MALLOC
+		#ifndef DBG_QM_MALLOC
+			#define DBG_QM_MALLOC
+		#endif
+	#elif defined(DBG_QM_MALLOC)
+		#define DBG_TLSF_MALLOC
+	#endif
 #endif
 
 
@@ -153,6 +151,19 @@
 #	define  shm_malloc_init(buf, len, type) create_mspace_with_base(buf, len, 0)
 #	define shm_malloc_destroy(b) do{}while(0)
 #	define shm_malloc_on_fork() do{}while(0)
+#elif defined TLSF_MALLOC
+#	include "tlsf.h"
+	extern pool_t shm_block;
+#	define MY_MALLOC tlsf_malloc
+#	define MY_FREE tlsf_free
+#	define MY_REALLOC tlsf_realloc
+#	define MY_STATUS tlsf_status
+#	define MY_MEMINFO	tlsf_meminfo
+#	define MY_SUMS tlsf_sums
+#	define shm_malloc_init(mem, bytes, type) tlsf_create_with_pool((void*) mem, bytes)
+#	define shm_malloc_destroy(b) do{}while(0)
+#	define shm_available() tlsf_available(shm_block)
+#	define shm_malloc_on_fork() do{}while(0)
 #else
 #	include "q_malloc.h"
 	extern struct qm_block* shm_block;
diff --git a/mem/src_loc.h b/mem/src_loc.h
index 5de5ef5..33c2df6 100644
--- a/mem/src_loc.h
+++ b/mem/src_loc.h
@@ -1,6 +1,8 @@
 /* 
  * Copyright (C) 2009 iptelorg GmbH
  *
+ * This file is part of Kamailio, a free SIP server.
+ *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
  * copyright notice and this permission notice appear in all copies.
@@ -14,12 +16,6 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/*
- * History:
- * --------
- *  2009-10-08  initial version (andrei)
-*/
-
 /**
  * \file
  * \brief Helper definitions for internal memory manager
diff --git a/mem/tlsf.c b/mem/tlsf.c
new file mode 100644
index 0000000..d4feb34
--- /dev/null
+++ b/mem/tlsf.c
@@ -0,0 +1,1257 @@
+#include <assert.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "tlsf.h"
+#include "tlsfbits.h"
+#include "src_loc.h"
+#include "../dprint.h"
+#include "../cfg/cfg.h"
+
+/*
+** Constants.
+*/
+
+/* Public constants: may be modified. */
+enum tlsf_public
+{
+	/* log2 of number of linear subdivisions of block sizes. */
+	SL_INDEX_COUNT_LOG2 = 5,
+};
+
+/* Private constants: do not modify. */
+enum tlsf_private
+{
+#if defined (TLSF_64BIT)
+	/* All allocation sizes and addresses are aligned to 8 bytes. */
+	ALIGN_SIZE_LOG2 = 3,
+#else
+	/* All allocation sizes and addresses are aligned to 4 bytes. */
+	ALIGN_SIZE_LOG2 = 2,
+#endif
+	ALIGN_SIZE = (1 << ALIGN_SIZE_LOG2),
+
+	/*
+	** We support allocations of sizes up to (1 << FL_INDEX_MAX) bits.
+	** However, because we linearly subdivide the second-level lists, and
+	** our minimum size granularity is 4 bytes, it doesn't make sense to
+	** create first-level lists for sizes smaller than SL_INDEX_COUNT * 4,
+	** or (1 << (SL_INDEX_COUNT_LOG2 + 2)) bytes, as there we will be
+	** trying to split size ranges into more slots than we have available.
+	** Instead, we calculate the minimum threshold size, and place all
+	** blocks below that size into the 0th first-level list.
+	*/
+
+#if defined (TLSF_64BIT)
+	/*
+	** TODO: We can increase this to support larger sizes, at the expense
+	** of more overhead in the TLSF structure.
+	*/
+	FL_INDEX_MAX = 39,
+#else
+	FL_INDEX_MAX = 30,
+#endif
+	SL_INDEX_COUNT = (1 << SL_INDEX_COUNT_LOG2),
+	FL_INDEX_SHIFT = (SL_INDEX_COUNT_LOG2 + ALIGN_SIZE_LOG2),
+	FL_INDEX_COUNT = (FL_INDEX_MAX - FL_INDEX_SHIFT + 1),
+
+	SMALL_BLOCK_SIZE = (1 << FL_INDEX_SHIFT),
+};
+
+/*
+** Cast and min/max macros.
+*/
+
+#define tlsf_cast(t, exp)	((t) (exp))
+#define tlsf_min(a, b)		((a) < (b) ? (a) : (b))
+#define tlsf_max(a, b)		((a) > (b) ? (a) : (b))
+
+/*
+** Set assert macro, if it has not been provided by the user.
+*/
+#if !defined (tlsf_assert)
+#define tlsf_assert assert
+#endif
+
+/*
+** Static assertion mechanism.
+*/
+
+#define _tlsf_glue2(x, y) x ## y
+#define _tlsf_glue(x, y) _tlsf_glue2(x, y)
+#define tlsf_static_assert(exp) \
+	typedef char _tlsf_glue(static_assert, __LINE__) [(exp) ? 1 : -1]
+
+/* This code has been tested on 32- and 64-bit (LP/LLP) architectures. */
+tlsf_static_assert(sizeof(int) * CHAR_BIT == 32);
+tlsf_static_assert(sizeof(size_t) * CHAR_BIT >= 32);
+tlsf_static_assert(sizeof(size_t) * CHAR_BIT <= 64);
+
+/* SL_INDEX_COUNT must be <= number of bits in sl_bitmap's storage type. */
+tlsf_static_assert(sizeof(unsigned int) * CHAR_BIT >= SL_INDEX_COUNT);
+
+/* Ensure we've properly tuned our sizes. */
+tlsf_static_assert(ALIGN_SIZE == SMALL_BLOCK_SIZE / SL_INDEX_COUNT);
+
+/*
+** Data structures and associated constants.
+*/
+#ifdef DBG_TLSF_MALLOC
+typedef struct {
+	const char* file;
+	const char* func;
+	unsigned long line;
+} alloc_info_t;
+#endif
+/*
+** Block header structure.
+**
+** There are several implementation subtleties involved:
+** - The prev_phys_block field is only valid if the previous block is free.
+** - The prev_phys_block field is actually stored at the end of the
+**   previous block. It appears at the beginning of this structure only to
+**   simplify the implementation.
+** - The next_free / prev_free fields are only valid if the block is free.
+*/
+typedef struct block_header_t
+{
+	/* Points to the previous physical block. */
+	struct block_header_t* prev_phys_block;
+
+#ifdef DBG_TLSF_MALLOC
+	alloc_info_t alloc_info;
+#endif
+
+	/* The size of this block, excluding the block header. */
+	size_t size;
+
+	/* Next and previous free blocks. */
+	struct block_header_t* next_free;
+	struct block_header_t* prev_free;
+} block_header_t;
+
+/*
+** Since block sizes are always at least a multiple of 4, the two least
+** significant bits of the size field are used to store the block status:
+** - bit 0: whether block is busy or free
+** - bit 1: whether previous block is busy or free
+*/
+static const size_t block_header_free_bit = 1 << 0;
+static const size_t block_header_prev_free_bit = 1 << 1;
+
+/*
+** The size of the block header exposed to used blocks is the size field.
+** The prev_phys_block field is stored *inside* the previous free block.
+*/
+#ifdef DBG_TLSF_MALLOC
+static const size_t block_header_overhead = sizeof(size_t) + sizeof(alloc_info_t);
+#else
+static const size_t block_header_overhead = sizeof(size_t);
+#endif
+
+/* User data starts directly after the size field in a used block. */
+static const size_t block_start_offset =
+	offsetof(block_header_t, size) + sizeof(size_t);
+
+/*
+** A free block must be large enough to store its header minus the size of
+** the prev_phys_block field, and no larger than the number of addressable
+** bits for FL_INDEX.
+*/
+static const size_t block_size_min =
+	sizeof(block_header_t) - sizeof(block_header_t*);
+static const size_t block_size_max = tlsf_cast(size_t, 1) << FL_INDEX_MAX;
+
+#ifdef TLSF_STATS
+	#define TLSF_INCREASE_REAL_USED(control, increment) do {control->real_used += (increment) ; control->max_used = tlsf_max(control->real_used, control->max_used);}while(0)
+	#define TLSF_INCREASE_FRAGMENTS(control) do {control->fragments++ ; control->max_fragments = tlsf_max(control->fragments, control->max_fragments);}while(0)
+#endif
+
+/* The TLSF control structure. */
+typedef struct control_t
+{
+	/* Empty lists point at this block to indicate they are free. */
+	block_header_t block_null;
+#ifdef TLSF_STATS
+	size_t total_size;
+	size_t allocated;
+	size_t real_used;
+	size_t max_used;
+	size_t fragments;
+	size_t max_fragments;
+#endif
+	/* Bitmaps for free lists. */
+	unsigned int fl_bitmap;
+	unsigned int sl_bitmap[FL_INDEX_COUNT];
+
+	/* Head of free lists. */
+	block_header_t* blocks[FL_INDEX_COUNT][SL_INDEX_COUNT];
+} control_t;
+
+/* A type used for casting when doing pointer arithmetic. */
+typedef ptrdiff_t tlsfptr_t;
+
+/*
+** block_header_t member functions.
+*/
+
+static size_t block_size(const block_header_t* block)
+{
+	return block->size & ~(block_header_free_bit | block_header_prev_free_bit);
+}
+
+static void block_set_size(block_header_t* block, size_t size)
+{
+	const size_t oldsize = block->size;
+	block->size = size | (oldsize & (block_header_free_bit | block_header_prev_free_bit));
+}
+
+static int block_is_last(const block_header_t* block)
+{
+	return 0 == block_size(block);
+}
+
+static int block_is_free(const block_header_t* block)
+{
+	return tlsf_cast(int, block->size & block_header_free_bit);
+}
+
+static void block_set_free(block_header_t* block)
+{
+	block->size |= block_header_free_bit;
+}
+
+static void block_set_used(block_header_t* block)
+{
+	block->size &= ~block_header_free_bit;
+}
+
+static int block_is_prev_free(const block_header_t* block)
+{
+	return tlsf_cast(int, block->size & block_header_prev_free_bit);
+}
+
+static void block_set_prev_free(block_header_t* block)
+{
+	block->size |= block_header_prev_free_bit;
+}
+
+static void block_set_prev_used(block_header_t* block)
+{
+	block->size &= ~block_header_prev_free_bit;
+}
+
+static block_header_t* block_from_ptr(const void* ptr)
+{
+	return tlsf_cast(block_header_t*,
+		tlsf_cast(unsigned char*, ptr) - block_start_offset);
+}
+
+static void* block_to_ptr(const block_header_t* block)
+{
+	return tlsf_cast(void*,
+		tlsf_cast(unsigned char*, block) + block_start_offset);
+}
+
+/* Return location of next block after block of given size. */
+static block_header_t* offset_to_block(const void* ptr, size_t size)
+{
+	return tlsf_cast(block_header_t*, tlsf_cast(tlsfptr_t, ptr) + size);
+}
+
+/* Return location of previous block. */
+static block_header_t* block_prev(const block_header_t* block)
+{
+	return block->prev_phys_block;
+}
+
+/* Return location of next existing block. */
+static block_header_t* block_next(const block_header_t* block)
+{
+	block_header_t* next = offset_to_block(block_to_ptr(block),
+		block_size(block) - sizeof(block_header_t*));
+	tlsf_assert(!block_is_last(block));
+	return next;
+}
+
+/* Link a new block with its physical neighbor, return the neighbor. */
+static block_header_t* block_link_next(block_header_t* block)
+{
+	block_header_t* next = block_next(block);
+	next->prev_phys_block = block;
+	return next;
+}
+
+static void block_mark_as_free(block_header_t* block)
+{
+	/* Link the block to the next block, first. */
+	block_header_t* next = block_link_next(block);
+	block_set_prev_free(next);
+	block_set_free(block);
+}
+
+static void block_mark_as_used(block_header_t* block)
+{
+	block_header_t* next = block_next(block);
+	block_set_prev_used(next);
+	block_set_used(block);
+}
+
+static size_t align_up(size_t x, size_t align)
+{
+	tlsf_assert(0 == (align & (align - 1)) && "must align to a power of two");
+	return (x + (align - 1)) & ~(align - 1);
+}
+
+static size_t align_down(size_t x, size_t align)
+{
+	tlsf_assert(0 == (align & (align - 1)) && "must align to a power of two");
+	return x - (x & (align - 1));
+}
+
+static void* align_ptr(const void* ptr, size_t align)
+{
+	const tlsfptr_t aligned =
+		(tlsf_cast(tlsfptr_t, ptr) + (align - 1)) & ~(align - 1);
+	tlsf_assert(0 == (align & (align - 1)) && "must align to a power of two");
+	return tlsf_cast(void*, aligned);
+}
+
+/*
+** Adjust an allocation size to be aligned to word size, and no smaller
+** than internal minimum.
+*/
+static size_t adjust_request_size(size_t size, size_t align)
+{
+	size_t adjust = 0;
+	if (size && size < block_size_max)
+	{
+		const size_t aligned = align_up(size, align);
+		adjust = tlsf_max(aligned, block_size_min);
+	}
+	return adjust;
+}
+
+/*
+** TLSF utility functions. In most cases, these are direct translations of
+** the documentation found in the white paper.
+*/
+
+static void mapping_insert(size_t size, int* fli, int* sli)
+{
+	int fl, sl;
+	if (size < SMALL_BLOCK_SIZE)
+	{
+		/* Store small blocks in first list. */
+		fl = 0;
+		sl = tlsf_cast(int, size) / (SMALL_BLOCK_SIZE / SL_INDEX_COUNT);
+	}
+	else
+	{
+		fl = tlsf_fls_sizet(size);
+		sl = tlsf_cast(int, size >> (fl - SL_INDEX_COUNT_LOG2)) ^ (1 << SL_INDEX_COUNT_LOG2);
+		fl -= (FL_INDEX_SHIFT - 1);
+	}
+	*fli = fl;
+	*sli = sl;
+}
+
+/* This version rounds up to the next block size (for allocations) */
+static void mapping_search(size_t size, int* fli, int* sli)
+{
+	if (size >= (1 << SL_INDEX_COUNT_LOG2))
+	{
+		const size_t round = (1 << (tlsf_fls_sizet(size) - SL_INDEX_COUNT_LOG2)) - 1;
+		size += round;
+	}
+	mapping_insert(size, fli, sli);
+}
+
+static block_header_t* search_suitable_block(control_t* control, int* fli, int* sli)
+{
+	int fl = *fli;
+	int sl = *sli;
+
+	/*
+	** First, search for a block in the list associated with the given
+	** fl/sl index.
+	*/
+	unsigned int sl_map = control->sl_bitmap[fl] & (~0 << sl);
+	if (!sl_map)
+	{
+		/* No block exists. Search in the next largest first-level list. */
+		const unsigned int fl_map = control->fl_bitmap & (~0 << (fl + 1));
+		if (!fl_map)
+		{
+			/* No free blocks available, memory has been exhausted. */
+			return 0;
+		}
+
+		fl = tlsf_ffs(fl_map);
+		*fli = fl;
+		sl_map = control->sl_bitmap[fl];
+	}
+	tlsf_assert(sl_map && "internal error - second level bitmap is null");
+	sl = tlsf_ffs(sl_map);
+	*sli = sl;
+
+	/* Return the first block in the free list. */
+	return control->blocks[fl][sl];
+}
+
+/* Remove a free block from the free list.*/
+static void remove_free_block(control_t* control, block_header_t* block, int fl, int sl)
+{
+	block_header_t* prev = block->prev_free;
+	block_header_t* next = block->next_free;
+	tlsf_assert(prev && "prev_free field can not be null");
+	tlsf_assert(next && "next_free field can not be null");
+	next->prev_free = prev;
+	prev->next_free = next;
+
+	/* If this block is the head of the free list, set new head. */
+	if (control->blocks[fl][sl] == block)
+	{
+		control->blocks[fl][sl] = next;
+
+		/* If the new head is null, clear the bitmap. */
+		if (next == &control->block_null)
+		{
+			control->sl_bitmap[fl] &= ~(1 << sl);
+
+			/* If the second bitmap is now empty, clear the fl bitmap. */
+			if (!control->sl_bitmap[fl])
+			{
+				control->fl_bitmap &= ~(1 << fl);
+			}
+		}
+	}
+#if defined TLSF_STATS
+	control->fragments--;
+#endif
+}
+
+/* Insert a free block into the free block list. */
+static void insert_free_block(control_t* control, block_header_t* block, int fl, int sl)
+{
+	block_header_t* current = control->blocks[fl][sl];
+	tlsf_assert(current && "free list cannot have a null entry");
+	tlsf_assert(block && "cannot insert a null entry into the free list");
+	block->next_free = current;
+	block->prev_free = &control->block_null;
+	current->prev_free = block;
+
+	tlsf_assert(block_to_ptr(block) == align_ptr(block_to_ptr(block), ALIGN_SIZE)
+		&& "block not aligned properly");
+	/*
+	** Insert the new block at the head of the list, and mark the first-
+	** and second-level bitmaps appropriately.
+	*/
+	control->blocks[fl][sl] = block;
+	control->fl_bitmap |= (1 << fl);
+	control->sl_bitmap[fl] |= (1 << sl);
+#if defined TLSF_STATS
+	TLSF_INCREASE_FRAGMENTS(control);
+#endif
+}
+
+/* Remove a given block from the free list. */
+static void block_remove(control_t* control, block_header_t* block)
+{
+	int fl, sl;
+	mapping_insert(block_size(block), &fl, &sl);
+	remove_free_block(control, block, fl, sl);
+}
+
+/* Insert a given block into the free list. */
+static void block_insert(control_t* control, block_header_t* block)
+{
+	int fl, sl;
+	mapping_insert(block_size(block), &fl, &sl);
+	insert_free_block(control, block, fl, sl);
+}
+
+static int block_can_split(block_header_t* block, size_t size)
+{
+	return block_size(block) >= sizeof(block_header_t) + size;
+}
+
+/* Split a block into two, the second of which is free. */
+static block_header_t* block_split(block_header_t* block, size_t size)
+{
+	/* Calculate the amount of space left in the remaining block. */
+	block_header_t* remaining =
+		offset_to_block(block_to_ptr(block), size - sizeof(block_header_t*));
+
+	const size_t remain_size = block_size(block) - (size + block_header_overhead);
+
+	tlsf_assert(block_to_ptr(remaining) == align_ptr(block_to_ptr(remaining), ALIGN_SIZE)
+		&& "remaining block not aligned properly");
+
+	tlsf_assert(block_size(block) == remain_size + size + block_header_overhead);
+	block_set_size(remaining, remain_size);
+	tlsf_assert(block_size(remaining) >= 0 && "block split with invalid size");
+
+	block_set_size(block, size);
+	block_mark_as_free(remaining);
+
+	return remaining;
+}
+
+/* Absorb a free block's storage into an adjacent previous free block. */
+static block_header_t* block_absorb(block_header_t* prev, block_header_t* block)
+{
+	tlsf_assert(!block_is_last(prev) && "previous block can't be last!");
+	/* Note: Leaves flags untouched. */
+	prev->size += block_size(block) + block_header_overhead;
+	block_link_next(prev);
+	return prev;
+}
+
+/* Merge a just-freed block with an adjacent previous free block. */
+static block_header_t* block_merge_prev(control_t* control, block_header_t* block)
+{
+	if (block_is_prev_free(block))
+	{
+		block_header_t* prev = block_prev(block);
+		tlsf_assert(prev && "prev physical block can't be null");
+		tlsf_assert(block_is_free(prev) && "prev block is not free though marked as such");
+		block_remove(control, prev);
+		block = block_absorb(prev, block);
+	}
+
+	return block;
+}
+
+/* Merge a just-freed block with an adjacent free block. */
+static block_header_t* block_merge_next(control_t* control, block_header_t* block)
+{
+	block_header_t* next = block_next(block);
+	tlsf_assert(next && "next physical block can't be null");
+
+	if (block_is_free(next))
+	{
+		tlsf_assert(!block_is_last(block) && "previous block can't be last!");
+		block_remove(control, next);
+		block = block_absorb(block, next);
+	}
+
+	return block;
+}
+
+/* Trim any trailing block space off the end of a block, return to pool. */
+static void block_trim_free(control_t* control, block_header_t* block, size_t size)
+{
+	tlsf_assert(block_is_free(block) && "block must be free");
+	if (block_can_split(block, size))
+	{
+		block_header_t* remaining_block = block_split(block, size);
+		block_link_next(block);
+		block_set_prev_free(remaining_block);
+#ifdef DBG_TLSF_MALLOC
+		remaining_block->alloc_info.file = _SRC_LOC_;
+		remaining_block->alloc_info.func = _SRC_FUNCTION_;
+		remaining_block->alloc_info.line = _SRC_LINE_;
+#endif
+		block_insert(control, remaining_block);
+	}
+}
+
+/* Trim any trailing block space off the end of a used block, return to pool. */
+static void block_trim_used(control_t* control, block_header_t* block, size_t size)
+{
+	tlsf_assert(!block_is_free(block) && "block must be used");
+	if (block_can_split(block, size))
+	{
+		/* If the next block is free, we must coalesce. */
+		block_header_t* remaining_block = block_split(block, size);
+		block_set_prev_used(remaining_block);
+
+		remaining_block = block_merge_next(control, remaining_block);
+#ifdef DBG_TLSF_MALLOC
+		remaining_block->alloc_info.file = _SRC_LOC_;
+		remaining_block->alloc_info.func = _SRC_FUNCTION_;
+		remaining_block->alloc_info.line = _SRC_LINE_;
+#endif
+		block_insert(control, remaining_block);
+	}
+}
+
+static block_header_t* block_trim_free_leading(control_t* control, block_header_t* block, size_t size)
+{
+	block_header_t* remaining_block = block;
+	if (block_can_split(block, size))
+	{
+		/* We want the 2nd block. */
+		remaining_block = block_split(block, size - block_header_overhead);
+		block_set_prev_free(remaining_block);
+
+		block_link_next(block);
+		block_insert(control, block);
+	}
+
+	return remaining_block;
+}
+
+static block_header_t* block_locate_free(control_t* control, size_t size)
+{
+	int fl = 0, sl = 0;
+	block_header_t* block = 0;
+
+	if (size)
+	{
+		mapping_search(size, &fl, &sl);
+		block = search_suitable_block(control, &fl, &sl);
+	}
+
+	if (block)
+	{
+		tlsf_assert(block_size(block) >= size);
+		remove_free_block(control, block, fl, sl);
+	}
+
+	return block;
+}
+#ifdef DBG_TLSF_MALLOC
+static void* block_prepare_used(control_t* control, block_header_t* block, size_t size,
+		const char *file, const char *function, unsigned long line)
+#else
+static void* block_prepare_used(control_t* control, block_header_t* block, size_t size)
+#endif
+{
+	void* p = 0;
+	if (block)
+	{
+		block_trim_free(control, block, size);
+		block_mark_as_used(block);
+		p = block_to_ptr(block);
+#ifdef TLSF_STATS
+		TLSF_INCREASE_REAL_USED(control, block->size + (p - (void *)block));
+		control->allocated += block->size;
+#endif
+#ifdef DBG_TLSF_MALLOC
+		block->alloc_info.file = file;
+		block->alloc_info.func = function;
+		block->alloc_info.line = line;
+#endif
+	}
+	return p;
+}
+
+/* Clear structure and point all empty lists at the null block. */
+static void control_construct(control_t* control)
+{
+	int i, j;
+
+	control->block_null.next_free = &control->block_null;
+	control->block_null.prev_free = &control->block_null;
+
+	control->fl_bitmap = 0;
+	for (i = 0; i < FL_INDEX_COUNT; ++i)
+	{
+		control->sl_bitmap[i] = 0;
+		for (j = 0; j < SL_INDEX_COUNT; ++j)
+		{
+			control->blocks[i][j] = &control->block_null;
+		}
+	}
+}
+
+/*
+** Debugging utilities.
+*/
+
+typedef struct integrity_t
+{
+	int prev_status;
+	int status;
+} integrity_t;
+
+#define tlsf_insist(x) { tlsf_assert(x); if (!(x)) { status--; } }
+
+static void integrity_walker(void* ptr, size_t size, int used, void* user)
+{
+	block_header_t* block = block_from_ptr(ptr);
+	integrity_t* integ = tlsf_cast(integrity_t*, user);
+	const int this_prev_status = block_is_prev_free(block) ? 1 : 0;
+	const int this_status = block_is_free(block) ? 1 : 0;
+	const size_t this_block_size = block_size(block);
+
+	int status = 0;
+	tlsf_insist(integ->prev_status == this_prev_status && "prev status incorrect");
+	tlsf_insist(size == this_block_size && "block size incorrect");
+
+	integ->prev_status = this_status;
+	integ->status += status;
+}
+
+int tlsf_check(tlsf_t tlsf)
+{
+	int i, j;
+
+	control_t* control = tlsf_cast(control_t*, tlsf);
+	int status = 0;
+
+	/* Check that the free lists and bitmaps are accurate. */
+	for (i = 0; i < FL_INDEX_COUNT; ++i)
+	{
+		for (j = 0; j < SL_INDEX_COUNT; ++j)
+		{
+			const int fl_map = control->fl_bitmap & (1 << i);
+			const int sl_list = control->sl_bitmap[i];
+			const int sl_map = sl_list & (1 << j);
+			const block_header_t* block = control->blocks[i][j];
+
+			/* Check that first- and second-level lists agree. */
+			if (!fl_map)
+			{
+				tlsf_insist(!sl_map && "second-level map must be null");
+			}
+
+			if (!sl_map)
+			{
+				tlsf_insist(block == &control->block_null && "block list must be null");
+				continue;
+			}
+
+			/* Check that there is at least one free block. */
+			tlsf_insist(sl_list && "no free blocks in second-level map");
+			tlsf_insist(block != &control->block_null && "block should not be null");
+
+			while (block != &control->block_null)
+			{
+				int fli, sli;
+				tlsf_insist(block_is_free(block) && "block should be free");
+				tlsf_insist(!block_is_prev_free(block) && "blocks should have coalesced");
+				tlsf_insist(!block_is_free(block_next(block)) && "blocks should have coalesced");
+				tlsf_insist(block_is_prev_free(block_next(block)) && "block should be free");
+				tlsf_insist(block_size(block) >= block_size_min && "block not minimum size");
+
+				mapping_insert(block_size(block), &fli, &sli);
+				tlsf_insist(fli == i && sli == j && "block size indexed in wrong list");
+				block = block->next_free;
+			}
+		}
+	}
+
+	return status;
+}
+
+#undef tlsf_insist
+
+static void default_walker(void* ptr, size_t size, int used, void* user)
+{
+	(void)user;
+	printf("\t%p %s size: %x (%p)\n", ptr, used ? "used" : "free", (unsigned int)size, block_from_ptr(ptr));
+}
+
+void tlsf_walk_pool(pool_t pool, tlsf_walker walker, void* user)
+{
+	tlsf_walker pool_walker = walker ? walker : default_walker;
+	block_header_t* block = pool + tlsf_size() - sizeof(block_header_t*);
+
+	while (block && !block_is_last(block))
+	{
+		pool_walker(
+			block_to_ptr(block),
+			block_size(block),
+			!block_is_free(block),
+			user);
+		block = block_next(block);
+	}
+}
+
+size_t tlsf_block_size(void* ptr)
+{
+	size_t size = 0;
+	if (ptr)
+	{
+		const block_header_t* block = block_from_ptr(ptr);
+		size = block_size(block);
+	}
+	return size;
+}
+
+int tlsf_check_pool(pool_t pool)
+{
+	/* Check that the blocks are physically correct. */
+	integrity_t integ = { 0, 0 };
+	tlsf_walk_pool(pool, integrity_walker, &integ);
+
+	return integ.status;
+}
+
+/*
+** Size of the TLSF structures in a given memory block passed to
+** tlsf_create, equal to the size of a control_t
+*/
+size_t tlsf_size()
+{
+	return sizeof(control_t);
+}
+
+size_t tlsf_align_size()
+{
+	return ALIGN_SIZE;
+}
+
+size_t tlsf_block_size_min()
+{
+	return block_size_min;
+}
+
+size_t tlsf_block_size_max()
+{
+	return block_size_max;
+}
+
+/*
+** Overhead of the TLSF structures in a given memory block passes to
+** tlsf_add_pool, equal to the overhead of a free block and the
+** sentinel block.
+*/
+size_t tlsf_pool_overhead()
+{
+	return 2 * block_header_overhead;
+}
+
+size_t tlsf_alloc_overhead()
+{
+	return block_header_overhead;
+}
+
+pool_t tlsf_add_pool(tlsf_t tlsf, void* mem, size_t bytes)
+{
+	block_header_t* block;
+	block_header_t* next;
+
+	const size_t pool_overhead = tlsf_pool_overhead();
+	const size_t pool_bytes = align_down(bytes - pool_overhead, ALIGN_SIZE);
+
+	if (((ptrdiff_t)mem % ALIGN_SIZE) != 0)
+	{
+		printf("tlsf_add_pool: Memory must be aligned by %u bytes.\n",
+			(unsigned int)ALIGN_SIZE);
+		return 0;
+	}
+
+	if (pool_bytes < block_size_min || pool_bytes > block_size_max)
+	{
+#if defined (TLSF_64BIT)
+		printf("tlsf_add_pool: Memory size must be between 0x%x and 0x%x00 bytes.\n",
+			(unsigned int)(pool_overhead + block_size_min),
+			(unsigned int)((pool_overhead + block_size_max) / 256));
+#else
+		printf("tlsf_add_pool: Memory size must be between %u and %u bytes.\n",
+			(unsigned int)(pool_overhead + block_size_min),
+			(unsigned int)(pool_overhead + block_size_max));
+#endif
+		return 0;
+	}
+
+	/*
+	** Create the main free block. Offset the start of the block slightly
+	** so that the prev_phys_block field falls outside of the pool -
+	** it will never be used.
+	*/
+	block = mem - sizeof (size_t);/*offset_to_block(mem, -(tlsfptr_t)block_header_overhead);*/
+	block_set_size(block, pool_bytes);
+	block_set_free(block);
+	block_set_prev_used(block);
+	block_insert(tlsf_cast(control_t*, tlsf), block);
+#ifdef TLSF_STATS
+	tlsf_cast(control_t*, tlsf)->total_size += block->size;
+#endif
+#ifdef DBG_TLSF_MALLOC
+	block->alloc_info.file = _SRC_LOC_;
+	block->alloc_info.func = _SRC_FUNCTION_;
+	block->alloc_info.line = _SRC_LINE_;
+#endif
+	/* Split the block to create a zero-size sentinel block. */
+	next = block_link_next(block);
+	block_set_size(next, 0);
+	block_set_used(next);
+	block_set_prev_free(next);
+
+	return mem;
+}
+
+void tlsf_remove_pool(tlsf_t tlsf, pool_t pool)
+{
+	control_t* control = tlsf_cast(control_t*, tlsf);
+	block_header_t* block = offset_to_block(pool, -(int)block_header_overhead);
+
+	int fl = 0, sl = 0;
+
+	tlsf_assert(block_is_free(block) && "block should be free");
+	tlsf_assert(!block_is_free(block_next(block)) && "next block should not be free");
+	tlsf_assert(block_size(block_next(block)) == 0 && "next block size should be zero");
+
+	mapping_insert(block_size(block), &fl, &sl);
+	remove_free_block(control, block, fl, sl);
+#ifdef TLSF_STATS
+	tlsf_cast(control_t*, tlsf)->total_size -= block->size;
+#endif
+}
+
+/*
+** TLSF main interface.
+*/
+
+#if _DEBUG
+int test_ffs_fls()
+{
+	/* Verify ffs/fls work properly. */
+	int rv = 0;
+	rv += (tlsf_ffs(0) == -1) ? 0 : 0x1;
+	rv += (tlsf_fls(0) == -1) ? 0 : 0x2;
+	rv += (tlsf_ffs(1) == 0) ? 0 : 0x4;
+	rv += (tlsf_fls(1) == 0) ? 0 : 0x8;
+	rv += (tlsf_ffs(0x80000000) == 31) ? 0 : 0x10;
+	rv += (tlsf_ffs(0x80008000) == 15) ? 0 : 0x20;
+	rv += (tlsf_fls(0x80000008) == 31) ? 0 : 0x40;
+	rv += (tlsf_fls(0x7FFFFFFF) == 30) ? 0 : 0x80;
+
+#if defined (TLSF_64BIT)
+	rv += (tlsf_fls_sizet(0x80000000) == 31) ? 0 : 0x100;
+	rv += (tlsf_fls_sizet(0x100000000) == 32) ? 0 : 0x200;
+	rv += (tlsf_fls_sizet(0xffffffffffffffff) == 63) ? 0 : 0x400;
+#endif
+
+	if (rv)
+	{
+		printf("tlsf_create: %x ffs/fls tests failed!\n", rv);
+	}
+	return rv;
+}
+#endif
+
+tlsf_t tlsf_create(void* mem)
+{
+#if _DEBUG
+	if (test_ffs_fls())
+	{
+		return 0;
+	}
+#endif
+
+	if (((tlsfptr_t)mem % ALIGN_SIZE) != 0)
+	{
+		printf("tlsf_create: Memory must be aligned to %u bytes.\n",
+			(unsigned int)ALIGN_SIZE);
+		return 0;
+	}
+
+	control_construct(tlsf_cast(control_t*, mem));
+#ifdef TLSF_STATS
+	tlsf_cast(control_t*, mem)->real_used = tlsf_size();
+	tlsf_cast(control_t*, mem)->max_used = tlsf_size();
+	tlsf_cast(control_t*, mem)->allocated = 0;
+	tlsf_cast(control_t*, mem)->total_size = tlsf_size();
+	tlsf_cast(control_t*, mem)->fragments = 0;
+	tlsf_cast(control_t*, mem)->max_fragments = 0;
+#endif
+	return tlsf_cast(tlsf_t, mem);
+}
+
+tlsf_t tlsf_create_with_pool(void* mem, size_t bytes)
+{
+	tlsf_t tlsf = tlsf_create(mem);
+	tlsf_add_pool(tlsf, (char*)mem + tlsf_size(), bytes - tlsf_size());
+	return tlsf;
+}
+
+void tlsf_destroy(tlsf_t tlsf)
+{
+	/* Nothing to do. */
+	(void)tlsf;
+}
+
+pool_t tlsf_get_pool(tlsf_t tlsf)
+{
+	return tlsf_cast(pool_t, (char*)tlsf + tlsf_size());
+}
+
+#ifdef DBG_TLSF_MALLOC
+void* tlsf_malloc(tlsf_t tlsf, size_t size,
+		const char *file, const char *function, unsigned long line)
+#else
+void* tlsf_malloc(tlsf_t tlsf, size_t size)
+#endif
+{
+	control_t* control = tlsf_cast(control_t*, tlsf);
+	const size_t adjust = adjust_request_size(size, ALIGN_SIZE);
+	block_header_t* block = block_locate_free(control, adjust);
+#ifdef DBG_TLSF_MALLOC
+	return block_prepare_used(control, block, adjust, file, function, line);
+#else
+	return block_prepare_used(control, block, adjust);
+#endif
+}
+
+#ifdef DBG_TLSF_MALLOC
+void tlsf_free(tlsf_t tlsf, void* ptr,
+		const char *file, const char *function, unsigned long line)
+#else
+void tlsf_free(tlsf_t tlsf, void* ptr)
+#endif
+{
+	/* Don't attempt to free a NULL pointer. */
+	if (ptr)
+	{
+		control_t* control = tlsf_cast(control_t*, tlsf);
+		block_header_t* block = block_from_ptr(ptr);
+		tlsf_assert(!block_is_free(block) && "block already marked as free");
+#if defined TLSF_STATS
+		control->allocated -= block->size;
+		control->real_used -= (block->size + (ptr - (void *)block));
+#endif
+#ifdef DBG_TLSF_MALLOC
+		block->alloc_info.file = file;
+		block->alloc_info.func = function;
+		block->alloc_info.line = line;
+#endif
+		block_mark_as_free(block);
+		block = block_merge_prev(control, block);
+		block = block_merge_next(control, block);
+		block_insert(control, block);
+	}
+}
+
+/*
+** The TLSF block information provides us with enough information to
+** provide a reasonably intelligent implementation of realloc, growing or
+** shrinking the currently allocated block as required.
+**
+** This routine handles the somewhat esoteric edge cases of realloc:
+** - a non-zero size with a null pointer will behave like malloc
+** - a zero size with a non-null pointer will behave like free
+** - a request that cannot be satisfied will leave the original buffer
+**   untouched
+** - an extended buffer size will leave the newly-allocated area with
+**   contents undefined
+*/
+#ifdef DBG_TLSF_MALLOC
+void* tlsf_realloc(tlsf_t tlsf, void* ptr, size_t size,
+		const char *file, const char *function, unsigned long line)
+#else
+void* tlsf_realloc(tlsf_t tlsf, void* ptr, size_t size)
+#endif
+{
+	control_t* control = tlsf_cast(control_t*, tlsf);
+	void* p = 0;
+
+	/* Zero-size requests are treated as free. */
+	if (ptr && size == 0)
+	{
+#ifdef DBG_TLSF_MALLOC
+		tlsf_free(tlsf, ptr, file, function, line);
+#else
+		tlsf_free(tlsf, ptr);
+#endif
+	}
+	/* Requests with NULL pointers are treated as malloc. */
+	else if (!ptr)
+	{
+#ifdef DBG_TLSF_MALLOC
+		p = tlsf_malloc(tlsf, size, file, function, line);
+#else
+		p = tlsf_malloc(tlsf, size);
+#endif
+	}
+	else
+	{
+		block_header_t* block = block_from_ptr(ptr);
+		block_header_t* next = block_next(block);
+
+		const size_t cursize = block_size(block);
+		const size_t combined = cursize + block_size(next) + block_header_overhead;
+		const size_t adjust = adjust_request_size(size, ALIGN_SIZE);
+
+		tlsf_assert(!block_is_free(block) && "block already marked as free");
+
+		/*
+		** If the next block is used, or when combined with the current
+		** block, does not offer enough space, we must reallocate and copy.
+		*/
+		if (adjust > cursize && (!block_is_free(next) || adjust > combined))
+		{
+#ifdef DBG_TLSF_MALLOC
+			p = tlsf_malloc(tlsf, size, file, function, line);
+#else
+			p = tlsf_malloc(tlsf, size);
+#endif
+			if (p)
+			{
+				const size_t minsize = tlsf_min(cursize, size);
+				memcpy(p, ptr, minsize);
+#ifdef DBG_TLSF_MALLOC
+				tlsf_free(tlsf, ptr, file, function, line);
+#else
+				tlsf_free(tlsf, ptr);
+#endif
+			}
+		}
+		else
+		{
+#ifdef TLSF_STATS
+			control->allocated -= block->size;
+			control->real_used -= block->size;
+#endif
+			/* Do we need to expand to the next block? */
+			if (adjust > cursize)
+			{
+				block_merge_next(control, block);
+				block_mark_as_used(block);
+			}
+
+			/* Trim the resulting block and return the original pointer. */
+			block_trim_used(control, block, adjust);
+			p = ptr;
+#ifdef TLSF_STATS
+			control->allocated += block->size;
+			TLSF_INCREASE_REAL_USED(control, block->size);
+#endif
+		}
+	}
+
+	return p;
+}
+
+#ifdef TLSF_STATS
+
+void tlsf_meminfo(tlsf_t pool, struct mem_info *info)
+{
+	control_t* control = tlsf_cast(control_t*, pool);
+	memset(info, 0, sizeof(*info));
+	info->free = control->total_size - control->real_used;
+	info->max_used = control->max_used;
+	info->real_used = control->real_used;
+	info->total_frags = control->fragments;
+	info->used = control->allocated;
+	info->total_size = control->total_size;
+}
+
+size_t tlsf_available(tlsf_t pool)
+{
+	control_t* control = tlsf_cast(control_t*, pool);
+	return control->total_size - control->real_used;
+}
+
+static void tlsf_status_cb(void* ptr, size_t size, int used, void* user)
+{
+#ifdef DBG_TLSF_MALLOC
+	block_header_t* block = block_from_ptr(ptr);
+#endif
+
+#ifdef DBG_TLSF_MALLOC
+	LOG_(DEFAULT_FACILITY, *(int*)user, "tlsf_status: ", "(%p): used=%s size=%zu was %s from %s: %s(%ld)\n",
+			ptr, used ? "true" : "false", size, used ? "alloc'd" : "free'd", block->alloc_info.file, block->alloc_info.func, block->alloc_info.line);
+#else
+	LOG_(DEFAULT_FACILITY, *(int*)user, "tlsf_status: ", "(%p): used=%s size=%zu\n",
+			ptr, used ? "true" : "false", size);
+#endif
+
+
+}
+
+void tlsf_status(tlsf_t pool)
+{
+	int memlog;
+	control_t* control = tlsf_cast(control_t*, pool);
+
+	memlog=cfg_get(core, core_cfg, memlog);
+	LOG_(DEFAULT_FACILITY, memlog, "tlsf_status: ", "status of pool (%p):\n", pool);
+#ifdef TLSF_STATS
+	LOG_(DEFAULT_FACILITY, memlog, "tlsf_status: ", "heap size= %zu\n",
+			control->total_size);
+	LOG_(DEFAULT_FACILITY, memlog, "tlsf_status: ",
+			"used= %zu, used+overhead=%zu, free=%zu, fragments=%zu\n",
+			control->allocated, control->real_used, control->total_size - control->real_used, control->fragments);
+	LOG_(DEFAULT_FACILITY, memlog, "tlsf_status: ",
+			"max used (+overhead)=%zu, max fragments=%zu\n", control->max_used, control->max_fragments);
+#endif
+	LOG_(DEFAULT_FACILITY, memlog, "tlsf_status: ",
+			"dumping all fragments:\n");
+	tlsf_walk_pool(pool, tlsf_status_cb, (void *) &memlog);
+}
+
+#ifdef DBG_TLSF_MALLOC
+typedef struct _mem_counter{
+	const char *file;
+	const char *func;
+	unsigned long line;
+
+	unsigned long size;
+	int count;
+
+	struct _mem_counter *next;
+} mem_counter;
+
+static mem_counter* get_mem_counter(mem_counter **root, block_header_t* f)
+{
+	mem_counter *x;
+	if (!*root) goto make_new;
+	for(x=*root;x;x=x->next)
+		if (x->file == f->alloc_info.file && x->func == f->alloc_info.func && x->line == f->alloc_info.line)
+			return x;
+make_new:
+	x = malloc(sizeof(mem_counter));
+	x->file = f->alloc_info.file;
+	x->func = f->alloc_info.func;
+	x->line = f->alloc_info.line;
+	x->count = 0;
+	x->size = 0;
+	x->next = *root;
+	*root = x;
+	return x;
+}
+
+
+void tlsf_sums(tlsf_t pool)
+{
+	int memlog;
+	block_header_t* block = pool + tlsf_size() - sizeof(block_header_t*);
+	mem_counter *root = NULL, *x;
+
+	memlog=cfg_get(core, core_cfg, memlog);
+
+	LOG_(DEFAULT_FACILITY, memlog, "tlsf_sums: ",
+			"pool (%p) summarizing all alloc'ed. fragments:\n", pool);
+
+
+	while (block && !block_is_last(block))
+	{
+		if(!block_is_free(block)) {
+			x = get_mem_counter(&root, block);
+			x->count++;
+			x->size+=block_size(block);
+		}
+
+		block = block_next(block);
+	}
+
+	x = root;
+	while(x){
+		LOG_(DEFAULT_FACILITY, memlog, "tlsf_sums: ",
+				" count=%6d size=%10lu bytes from %s: %s(%ld)\n",
+			x->count,x->size,
+			x->file, x->func, x->line
+			);
+		root = x->next;
+		free(x);
+		x = root;
+	}
+	LOG_(DEFAULT_FACILITY, memlog, "tlsf_sums: ",
+			"-----------------------------\n");
+}
+#else
+void tlsf_sums(tlsf_t pool)
+{}
+#endif /* defined DBG_TLSF_MALLOC */
+
+#endif
+
diff --git a/mem/tlsf.h b/mem/tlsf.h
new file mode 100644
index 0000000..bcf4190
--- /dev/null
+++ b/mem/tlsf.h
@@ -0,0 +1,83 @@
+#ifndef INCLUDED_tlsf
+#define INCLUDED_tlsf
+
+/*
+** Two Level Segregated Fit memory allocator, version 3.0.
+** Written by Matthew Conte, and placed in the Public Domain.
+**	http://tlsf.baisoku.org
+**
+** Based on the original documentation by Miguel Masmano:
+**	http://rtportal.upv.es/rtmalloc/allocators/tlsf/index.shtml
+**
+** Please see the accompanying Readme.txt for implementation
+** notes and caveats.
+**
+** This implementation was written to the specification
+** of the document, therefore no GPL restrictions apply.
+*/
+
+#include <stddef.h>
+#include "meminfo.h"
+#define TLSF_STATS
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/* tlsf_t: a TLSF structure. Can contain 1 to N pools. */
+/* pool_t: a block of memory that TLSF can manage. */
+typedef void* tlsf_t;
+typedef void* pool_t;
+
+/* Create/destroy a memory pool. */
+tlsf_t tlsf_create(void* mem);
+tlsf_t tlsf_create_with_pool(void* mem, size_t bytes);
+void tlsf_destroy(tlsf_t tlsf);
+pool_t tlsf_get_pool(tlsf_t tlsf);
+
+/* Add/remove memory pools. */
+pool_t tlsf_add_pool(tlsf_t tlsf, void* mem, size_t bytes);
+void tlsf_remove_pool(tlsf_t tlsf, pool_t pool);
+
+/* malloc/memalign/realloc/free replacements. */
+#ifdef DBG_TLSF_MALLOC
+void* tlsf_malloc(tlsf_t tlsf, size_t size,
+		const char *file, const char *function, unsigned long line);
+void* tlsf_realloc(tlsf_t tlsf, void* ptr, size_t size,
+		const char *file, const char *function, unsigned long line);
+void tlsf_free(tlsf_t tlsf, void* ptr,
+		const char *file, const char *function, unsigned long line);
+#else
+void* tlsf_malloc(tlsf_t tlsf, size_t bytes);
+void* tlsf_realloc(tlsf_t tlsf, void* ptr, size_t size);
+void tlsf_free(tlsf_t tlsf, void* ptr);
+#endif
+
+/* Returns internal block size, not original request size */
+size_t tlsf_block_size(void* ptr);
+
+/* Overheads/limits of internal structures. */
+size_t tlsf_size();
+size_t tlsf_align_size();
+size_t tlsf_block_size_min();
+size_t tlsf_block_size_max();
+size_t tlsf_pool_overhead();
+size_t tlsf_alloc_overhead();
+
+/* Debugging. */
+typedef void (*tlsf_walker)(void* ptr, size_t size, int used, void* user);
+void tlsf_walk_pool(pool_t pool, tlsf_walker walker, void* user);
+/* Returns nonzero if any internal consistency check fails. */
+int tlsf_check(tlsf_t tlsf);
+int tlsf_check_pool(pool_t pool);
+
+void tlsf_meminfo(tlsf_t pool, struct mem_info *info);
+void tlsf_status(tlsf_t pool);
+void tlsf_sums(tlsf_t pool);
+size_t tlsf_available(tlsf_t pool);
+
+#if defined(__cplusplus)
+};
+#endif
+
+#endif
diff --git a/mem/tlsfbits.h b/mem/tlsfbits.h
new file mode 100644
index 0000000..3be2579
--- /dev/null
+++ b/mem/tlsfbits.h
@@ -0,0 +1,180 @@
+#ifndef INCLUDED_tlsfbits
+#define INCLUDED_tlsfbits
+
+#if defined(__cplusplus)
+#define tlsf_decl inline
+#else
+#define tlsf_decl static
+#endif
+
+/*
+** Architecture-specific bit manipulation routines.
+**
+** TLSF achieves O(1) cost for malloc and free operations by limiting
+** the search for a free block to a free list of guaranteed size
+** adequate to fulfill the request, combined with efficient free list
+** queries using bitmasks and architecture-specific bit-manipulation
+** routines.
+**
+** Most modern processors provide instructions to count leading zeroes
+** in a word, find the lowest and highest set bit, etc. These
+** specific implementations will be used when available, falling back
+** to a reasonably efficient generic implementation.
+**
+** NOTE: TLSF spec relies on ffs/fls returning value 0..31.
+** ffs/fls return 1-32 by default, returning 0 for error.
+*/
+
+/*
+** Detect whether or not we are building for a 32- or 64-bit (LP/LLP)
+** architecture. There is no reliable portable method at compile-time.
+*/
+#if defined (__alpha__) || defined (__ia64__) || defined (__x86_64__) \
+	|| defined (_WIN64) || defined (__LP64__) || defined (__LLP64__)
+#define TLSF_64BIT
+#endif
+
+/*
+** gcc 3.4 and above have builtin support, specialized for architecture.
+** Some compilers masquerade as gcc; patchlevel test filters them out.
+*/
+#if defined (__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) \
+	&& defined (__GNUC_PATCHLEVEL__)
+
+tlsf_decl int tlsf_ffs(unsigned int word)
+{
+	return __builtin_ffs(word) - 1;
+}
+
+tlsf_decl int tlsf_fls(unsigned int word)
+{
+	const int bit = word ? 32 - __builtin_clz(word) : 0;
+	return bit - 1;
+}
+
+#elif defined (_MSC_VER) && (_MSC_VER >= 1400) && (defined (_M_IX86) || defined (_M_X64))
+/* Microsoft Visual C++ support on x86/X64 architectures. */
+
+#include <intrin.h>
+
+#pragma intrinsic(_BitScanReverse)
+#pragma intrinsic(_BitScanForward)
+
+tlsf_decl int tlsf_fls(unsigned int word)
+{
+	unsigned long index;
+	return _BitScanReverse(&index, word) ? index : -1;
+}
+
+tlsf_decl int tlsf_ffs(unsigned int word)
+{
+	unsigned long index;
+	return _BitScanForward(&index, word) ? index : -1;
+}
+
+#elif defined (_MSC_VER) && defined (_M_PPC)
+/* Microsoft Visual C++ support on PowerPC architectures. */
+
+#include <ppcintrinsics.h>
+
+tlsf_decl int tlsf_fls(unsigned int word)
+{
+	const int bit = 32 - _CountLeadingZeros(word);
+	return bit - 1;
+}
+
+tlsf_decl int tlsf_ffs(unsigned int word)
+{
+	const unsigned int reverse = word & (~word + 1);
+	const int bit = 32 - _CountLeadingZeros(reverse);
+	return bit - 1;
+}
+
+#elif defined (__ARMCC_VERSION)
+/* RealView Compilation Tools for ARM */
+
+tlsf_decl int tlsf_ffs(unsigned int word)
+{
+	const unsigned int reverse = word & (~word + 1);
+	const int bit = 32 - __clz(reverse);
+	return bit - 1;
+}
+
+tlsf_decl int tlsf_fls(unsigned int word)
+{
+	const int bit = word ? 32 - __clz(word) : 0;
+	return bit - 1;
+}
+
+#elif defined (__ghs__)
+/* Green Hills support for PowerPC */
+
+#include <ppc_ghs.h>
+
+tlsf_decl int tlsf_ffs(unsigned int word)
+{
+	const unsigned int reverse = word & (~word + 1);
+	const int bit = 32 - __CLZ32(reverse);
+	return bit - 1;
+}
+
+tlsf_decl int tlsf_fls(unsigned int word)
+{
+	const int bit = word ? 32 - __CLZ32(word) : 0;
+	return bit - 1;
+}
+
+#else
+/* Fall back to generic implementation. */
+
+tlsf_decl int tlsf_fls_generic(unsigned int word)
+{
+	int bit = 32;
+
+	if (!word) bit -= 1;
+	if (!(word & 0xffff0000)) { word <<= 16; bit -= 16; }
+	if (!(word & 0xff000000)) { word <<= 8; bit -= 8; }
+	if (!(word & 0xf0000000)) { word <<= 4; bit -= 4; }
+	if (!(word & 0xc0000000)) { word <<= 2; bit -= 2; }
+	if (!(word & 0x80000000)) { word <<= 1; bit -= 1; }
+
+	return bit;
+}
+
+/* Implement ffs in terms of fls. */
+tlsf_decl int tlsf_ffs(unsigned int word)
+{
+	return tlsf_fls_generic(word & (~word + 1)) - 1;
+}
+
+tlsf_decl int tlsf_fls(unsigned int word)
+{
+	return tlsf_fls_generic(word) - 1;
+}
+
+#endif
+
+/* Possibly 64-bit version of tlsf_fls. */
+#if defined (TLSF_64BIT)
+tlsf_decl int tlsf_fls_sizet(size_t size)
+{
+	int high = (int)(size >> 32);
+	int bits = 0;
+	if (high)
+	{
+		bits = 32 + tlsf_fls(high);
+	}
+	else
+	{
+		bits = tlsf_fls((int)size & 0xffffffff);
+
+	}
+	return bits;
+}
+#else
+#define tlsf_fls_sizet tlsf_fls
+#endif
+
+#undef tlsf_decl
+
+#endif
diff --git a/mod_fix.c b/mod_fix.c
index dc04d2f..46505f4 100644
--- a/mod_fix.c
+++ b/mod_fix.c
@@ -14,15 +14,9 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* 
- * History:
- * --------
- *  2008-11-25  initial version (andrei)
- */
-
 /*!
  * \file
- * \brief SIP-router core :: kamailio compatible fixups
+ * \brief Kamailio core :: kamailio compatible fixups
  * \ingroup core
  * Module: \ref core
  */
diff --git a/mod_fix.h b/mod_fix.h
index c7740d0..e02aa6d 100644
--- a/mod_fix.h
+++ b/mod_fix.h
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- * 
  * Copyright (C) 2008 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -15,10 +13,13 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
+
 /**
  * @file mod_fix.h
- * @brief Generic fixup functions for module function parameter.
+ * @brief Kamailio core :: Generic fixup functions for module function parameter.
  * (kamailio compatibility)
+ * @ingroup core
+ * Module: \ref core
  */
 
 #ifndef _mod_fix_h_
diff --git a/modparam.c b/modparam.c
index 17d0642..087f11e 100644
--- a/modparam.c
+++ b/modparam.c
@@ -1,22 +1,14 @@
 /*
- * $Id$
- *
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -25,17 +17,11 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * -------
- * 2003-03-20  regex support in modparam (janakj)
- * 2004-03-12  extra flag USE_FUNC_PARAM added to modparam type -
- *             instead of copying the param value, a func is called (bogdan)
- * 2005-07-01  PARAM_STRING & PARAM_STR support
  */
 
 /*!
  * \file
- * \brief SIP-router core :: 
+ * \brief Kamailio core :: Configuration parameters for modules (modparams)
  * \ingroup core
  * Module: \ref core
  */
@@ -92,8 +78,7 @@ int set_mod_param_regex(char* regex, char* name, modparam_t type, void* val)
 	mod_found = 0;
 	for(t = modules; t; t = t->next) {
 		if (regexec(&preg, t->exports.name, 0, 0, 0) == 0) {
-			DBG("set_mod_param_regex: '%s' matches module '%s'\n",
-					regex, t->exports.name);
+			LM_DBG("'%s' matches module '%s'\n", regex, t->exports.name);
 			mod_found = 1;
 			/* PARAM_STR (PARAM_STRING) may be assigned also to PARAM_STRING(PARAM_STR) so let get both module param */
 			ptr = find_param_export(t, name, type | ((type & (PARAM_STR|PARAM_STRING))?PARAM_STR|PARAM_STRING:0), &param_type);
@@ -109,8 +94,7 @@ int set_mod_param_regex(char* regex, char* name, modparam_t type, void* val)
 				} else {
 					val2 = val;
 				}
-				DBG("set_mod_param_regex: found <%s> in module %s [%s]\n",
-						name, t->exports.name, t->path);
+				LM_DBG("found <%s> in module %s [%s]\n", name, t->exports.name, t->path);
 				if (param_type & PARAM_USE_FUNC) {
 					if ( ((param_func_t)(ptr))(param_type, val2) < 0) {
 						regfree(&preg);
diff --git a/modparam.h b/modparam.h
index 8974c68..91c6867 100644
--- a/modparam.h
+++ b/modparam.h
@@ -1,22 +1,14 @@
 /*
- * $Id$
- *
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -25,6 +17,12 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
+/*!
+* \file
+* \brief Kamailio core :: Module parameter handling (modparam)
+* \ingroup core
+* Module: \ref core
+*/
 
 
 #ifndef modparam_h
diff --git a/modules/acc/Makefile b/modules/acc/Makefile
index 707680f..07a7e80 100644
--- a/modules/acc/Makefile
+++ b/modules/acc/Makefile
@@ -1,5 +1,3 @@
-# $Id$
-#
 # acc module makefile
 #
 #
diff --git a/modules/acc/README b/modules/acc/README
index bbf84fe..2c742ee 100644
--- a/modules/acc/README
+++ b/modules/acc/README
@@ -134,6 +134,7 @@ Sven Knoblich
               6.51. time_format (str)
               6.52. reason_from_hf (int)
               6.53. clone_msg (int)
+              6.54. cdr_on_failed (int)
 
         7. Functions
 
@@ -199,10 +200,11 @@ Sven Knoblich
    1.51. time_format example
    1.52. reason_from_hf
    1.53. clone_msg
-   1.54. acc_log_request usage
-   1.55. acc_db_request usage
-   1.56. acc_rad_request usage
-   1.57. acc_diam_request usage
+   1.54. cdr_on_failed
+   1.55. acc_log_request usage
+   1.56. acc_db_request usage
+   1.57. acc_rad_request usage
+   1.58. acc_diam_request usage
 
 Chapter 1. Admin Guide
 
@@ -300,6 +302,7 @@ Chapter 1. Admin Guide
         6.51. time_format (str)
         6.52. reason_from_hf (int)
         6.53. clone_msg (int)
+        6.54. cdr_on_failed (int)
 
    7. Functions
 
@@ -564,11 +567,6 @@ Note
    information given will not be stored in the CDR as they cannot be
    accessed by the end of the call when the CDR is logged.
 
-   Note that CDR generation does not involve any kind of database storage
-   (yet). In order to persist the CDRs into a database you will have to
-   set up an exterior process (i.e., a script living outside of Kamailio)
-   and implement the storage task yourself.
-
    Sometimes, dialogs expire because the UA has a problem and a final
    message is never transmitted. You can toggle on/off the generation of
    CDR-based logging in such cases with only the dlg_vars showing by using
@@ -726,6 +724,7 @@ $dlg_var(callee) = $avp(callee); #callee='C'
    6.51. time_format (str)
    6.52. reason_from_hf (int)
    6.53. clone_msg (int)
+   6.54. cdr_on_failed (int)
 
 6.1. early_media (integer)
 
@@ -1411,6 +1410,19 @@ modparam("acc", "reason_from_hf", 1)
 modparam("acc", "clone_msg", 0)
 ...
 
+6.54. cdr_on_failed (int)
+
+   If set to 1, the module stores the CDR for a failed dialog (calls not
+   answered). If set to 0, those records are not stored, only those for
+   answered calls.
+
+   Default value is 1.
+
+   Example 1.54. cdr_on_failed
+...
+modparam("acc", "cdr_on_failed", 0)
+...
+
 7. Functions
 
    7.1. acc_log_request(comment)
@@ -1431,7 +1443,7 @@ modparam("acc", "clone_msg", 0)
 
    This function can be used from ANY_ROUTE.
 
-   Example 1.54. acc_log_request usage
+   Example 1.55. acc_log_request usage
 ...
 acc_log_request("Some comment");
 $var(code) = 404;
@@ -1453,7 +1465,7 @@ acc_log_request("$var(code) Error: $avp(reason)");
 
    This function can be used from ANY_ROUTE.
 
-   Example 1.55. acc_db_request usage
+   Example 1.56. acc_db_request usage
 ...
 acc_db_request("Some comment", "SomeTable");
 acc_db_request("Some comment", "acc_$time(year)_$time(mon)");
@@ -1471,7 +1483,7 @@ acc_db_request("$var(code) Error: $avp(reason)", "SomeTable");
 
    This function can be used from ANY_ROUTE.
 
-   Example 1.56. acc_rad_request usage
+   Example 1.57. acc_rad_request usage
 ...
 acc_rad_request("Some comment");
 acc_rad_request("$var(code) Error: $avp(reason)");
@@ -1488,7 +1500,7 @@ acc_rad_request("$var(code) Error: $avp(reason)");
 
    This function can be used from ANY_ROUTE.
 
-   Example 1.57. acc_diam_request usage
+   Example 1.58. acc_diam_request usage
 ...
 acc_diam_request("Some comment");
 acc_diam_request("$var(code) Error: $avp(reason)");
diff --git a/modules/acc/acc_api.h b/modules/acc/acc_api.h
index f2efbe4..f252b58 100644
--- a/modules/acc/acc_api.h
+++ b/modules/acc/acc_api.h
@@ -110,7 +110,7 @@ typedef struct acc_engine {
 #define ACC_CORE_LEN  6
 
 
-enum {TYPE_NULL = 0, TYPE_INT, TYPE_STR};
+enum {TYPE_NULL = 0, TYPE_INT, TYPE_STR, TYPE_DOUBLE, TYPE_DATE};
 
 
 typedef int (*register_engine_f)(acc_engine_t *eng);
diff --git a/modules/acc/acc_cdr.c b/modules/acc/acc_cdr.c
index d5685a6..d5b16e3 100644
--- a/modules/acc/acc_cdr.c
+++ b/modules/acc/acc_cdr.c
@@ -88,6 +88,9 @@ extern str cdr_end_str;
 extern str cdr_duration_str;
 extern str acc_cdrs_table;
 extern int cdr_log_enable;
+extern int _acc_cdr_on_failed;
+
+static int string2time( str* time_str, struct timeval* time_value);
 
 /* write all basic information to buffers(e.g. start-time ...) */
 static int cdr_core2strar( struct dlg_cell* dlg,
@@ -110,13 +113,13 @@ static int cdr_core2strar( struct dlg_cell* dlg,
     duration = dlgb.get_dlg_var( dlg, (str*)&cdr_duration_str);
 
     values[0] = ( start != NULL ? *start : empty_string);
-    types[0] = ( start != NULL ? TYPE_STR : TYPE_NULL);
+    types[0] = ( start != NULL ? TYPE_DATE : TYPE_NULL);
 
     values[1] = ( end != NULL ? *end : empty_string);
-    types[1] = ( end != NULL ? TYPE_STR : TYPE_NULL);
+    types[1] = ( end != NULL ? TYPE_DATE : TYPE_NULL);
 
     values[2] = ( duration != NULL ? *duration : empty_string);
-    types[2] = ( duration != NULL ? TYPE_STR : TYPE_NULL);
+    types[2] = ( duration != NULL ? TYPE_DOUBLE : TYPE_NULL);
 
     return MAX_CDR_CORE;
 }
@@ -137,6 +140,10 @@ static int db_write_cdr( struct dlg_cell* dialog,
 	db1_con_t *dh=NULL;
 	void *vf=NULL;
 	void *vh=NULL;
+	struct timeval timeval_val;
+	long long_val;
+	double double_val;
+	char * end;
 
 	if(acc_cdrs_table.len<=0)
 		return 0;
@@ -156,9 +163,45 @@ static int db_write_cdr( struct dlg_cell* dialog,
 
 	for(i=0; i<m; i++) {
 		db_cdr_keys[i] = &cdr_attrs[i];
-		VAL_TYPE(db_cdr_vals+i)=DB1_STR;
-		VAL_NULL(db_cdr_vals+i)=0;
-		VAL_STR(db_cdr_vals+i) = cdr_value_array[i];
+		switch(cdr_type_array[i]) {
+			case TYPE_NULL:
+				VAL_NULL(db_cdr_vals+i)=1;
+				break;
+			case TYPE_INT:
+				VAL_TYPE(db_cdr_vals+i)=DB1_INT;
+				VAL_NULL(db_cdr_vals+i)=0;
+				long_val = strtol(cdr_value_array[i].s, &end, 10);
+				if(errno && (errno != EAGAIN)) {
+					LM_ERR("failed to convert string to integer - %d.\n", errno);
+					goto error;
+				}
+				VAL_INT(db_cdr_vals+i) = long_val;
+				break;
+			case TYPE_STR:
+				VAL_TYPE(db_cdr_vals+i)=DB1_STR;
+				VAL_NULL(db_cdr_vals+i)=0;
+				VAL_STR(db_cdr_vals+i) = cdr_value_array[i];
+				break;
+			case TYPE_DATE:
+				VAL_TYPE(db_cdr_vals+i)=DB1_DATETIME;
+				VAL_NULL(db_cdr_vals+i)=0;
+				if(string2time(&cdr_value_array[i], &timeval_val) < 0) {
+					LM_ERR("failed to convert string to timeval.\n");
+					goto error;
+				}
+				VAL_TIME(db_cdr_vals+i) = timeval_val.tv_sec;
+				break;
+			case TYPE_DOUBLE:
+				VAL_TYPE(db_cdr_vals+i)=DB1_DOUBLE;
+				VAL_NULL(db_cdr_vals+i)=0;
+				double_val = strtod(cdr_value_array[i].s, &end);
+				if(errno && (errno != EAGAIN)) {
+					LM_ERR("failed to convert string to double - %d.\n", errno);
+					goto error;
+				}
+				VAL_DOUBLE(db_cdr_vals+i) = double_val;
+				break;
+		}
 	}
 
     /* get extra values */
@@ -649,6 +692,23 @@ static void cdr_on_expired( struct dlg_cell* dialog,
     }
 
     LM_DBG("dialog '%p' expired!\n", dialog);
+    /* compute duration for timed out acknowledged dialog */
+	if ( params && params->dlg_data ) {
+		if ( (void*)CONFIRMED_DIALOG_STATE == params->dlg_data) {
+			if( set_end_time( dialog) != 0)
+			{
+				LM_ERR( "failed to set end time!\n");
+				return;
+			}	
+			
+			if( set_duration( dialog) != 0)
+			{
+				LM_ERR( "failed to set duration!\n");
+				return;
+			}
+			
+		}
+	}
 
     if( cdr_expired_dlg_enable  && (write_cdr( dialog, 0) != 0))
     {
@@ -693,11 +753,13 @@ static void cdr_on_create( struct dlg_cell* dialog,
         return;
     }
 
-    if( dlgb.register_dlgcb( dialog, DLGCB_FAILED, cdr_on_failed, 0, 0) != 0)
-    {
-        LM_ERR("can't register create dialog FAILED callback\n");
-        return;
-    }
+	if(_acc_cdr_on_failed==1) {
+		if( dlgb.register_dlgcb( dialog, DLGCB_FAILED, cdr_on_failed, 0, 0) != 0)
+		{
+			LM_ERR("can't register create dialog FAILED callback\n");
+			return;
+		}
+	}
 
     if( dlgb.register_dlgcb( dialog, DLGCB_TERMINATED, cdr_on_end, 0, 0) != 0)
     {
diff --git a/modules/acc/acc_mod.c b/modules/acc/acc_mod.c
index 2939cd3..91b47d0 100644
--- a/modules/acc/acc_mod.c
+++ b/modules/acc/acc_mod.c
@@ -120,6 +120,7 @@ int acc_time_mode  = 0;
 str acc_time_attr  = str_init("time_attr");
 str acc_time_exten  = str_init("time_exten");
 int _acc_clone_msg  = 1;
+int _acc_cdr_on_failed = 1;
 
 /*@}*/
 
@@ -317,6 +318,7 @@ static param_export_t params[] = {
 	{"cdrs_table",           PARAM_STR, &acc_cdrs_table       },
 	{"time_format",          PARAM_STRING, &acc_time_format   },
 	{"clone_msg",            PARAM_INT, &_acc_clone_msg       },
+	{"cdr_on_failed",        PARAM_INT, &_acc_cdr_on_failed   },
 	{0,0,0}
 };
 
diff --git a/modules/acc/doc/acc_admin.xml b/modules/acc/doc/acc_admin.xml
index eb7acdc..820f480 100644
--- a/modules/acc/doc/acc_admin.xml
+++ b/modules/acc/doc/acc_admin.xml
@@ -25,7 +25,7 @@
 	<para>
 		To account a transaction and to choose which set of backends to be 
 		used, the script writer just has to set some flags (see the module
-		parameters section for flag definitions <xref linkend="ACC-param-id"/>).
+		parameters section for flag definitions <xref linkend="acc.i.params"/>).
 		If the accounting flag for a specific backend is set, the acc module 
 		will then report on completed transaction. A typical usage of the 
 		module takes no acc-specific script command -- the functionality 
@@ -38,7 +38,7 @@
 		The accounting module will log by default a fixed set of attributes 
 		for the transaction - if you customize your accounting by adding more
 		information to be logged, please see the next chapter about extra
-		accounting - <xref linkend="ACC-extra-id"/>.
+		accounting - <xref linkend="acc.i.extra-accounting"/>.
 	</para>
 	<para>
 		The fixed minimal accounting information is: 
@@ -155,7 +155,7 @@ if (uri=~"sip:+40") /* calls to Romania */ {
 	</section>
 	</section>
 
-	<section id="ACC-extra-id">
+	<section id="acc.i.extra-accounting">
 		<title>Extra accounting</title>
 		<section>
 			<title>Overview</title>
@@ -237,7 +237,7 @@ if (uri=~"sip:+40") /* calls to Romania */ {
 		</section>
 	</section>
 
-	<section id="multi-call-legs">
+	<section id="acc.i.multi-call-legs">
 		<title>Multi Call-Legs accounting</title>
 		<section>
 			<title>Overview</title>
@@ -358,10 +358,10 @@ if (uri=~"sip:+40") /* calls to Romania */ {
 				- <xref linkend="acc.p.cdr_expired_dlg_enable"/>. Default behavior is not logging.
                 </para>
         </section>
-		<section id="cdr-extra-id">
+		<section id="acc.i.cdr-extra">
 			<title>CDR Extra</title>
 					This section is similar to the <quote>LOG accounting</quote> part of
-					<xref linkend="ACC-extra-id"/>.
+					<xref linkend="acc.i.extra-accounting"/>.
 			<section>
 				<title>Definitions and syntax</title>
 					<para>
@@ -390,7 +390,7 @@ if (uri=~"sip:+40") /* calls to Romania */ {
 			<section>
 				<title>Overview</title>
 				<para>
-				As mentioned in <xref linkend="multi-call-legs"/>, a leg represents a parallel
+				As mentioned in <xref linkend="acc.i.multi-call-legs"/>, a leg represents a parallel
 				or forwarded call. In contrast to the normal accounting the cdr logging uses dialogs
 				instead of transaction to log data. This may reduce the amount of information 
 				but it also make it possible to combine all important data in one cdr at 
@@ -495,7 +495,7 @@ $dlg_var(callee) = $avp(callee); #callee='C'
 		</section>
 	</section>
 
-	<section id="ACC-param-id">
+	<section id="acc.i.params">
 	<title>Parameters</title>
 	<!-- Generic ACC parameters -->
 	<section id="acc.p.early_media">
@@ -642,7 +642,7 @@ modparam("acc", "acc_prepare_flag", 5)
 		<title><varname>multi_leg_info</varname> (string)</title>
 		<para>
 		Defines the AVP set to be used in per-call-leg accounting.
-		See <xref linkend="multi-call-legs"/> for a 
+		See <xref linkend="acc.i.multi-call-legs"/> for a 
 		detailed description of the Multi Call-Legs accounting.
 		</para>
 		<para>
@@ -746,7 +746,7 @@ modparam("acc", "log_facility", "LOG_DAEMON")
 		<title><varname>log_extra</varname> (string)</title>
 		<para>
 		Extra values to be logged.
-		See section <xref linkend="ACC-extra-id"/> for more details.
+		See section <xref linkend="acc.i.extra-accounting"/> for more details.
 		</para>
 		<para>
 		Default value is NULL.
@@ -844,7 +844,7 @@ modparam("acc", "service_type", 16)
 		<title><varname>radius_extra</varname> (string)</title>
 		<para>
 		Extra values to be logged via RADIUS - RADIUS specific.
-		See section <xref linkend="ACC-extra-id"/> for more details.
+		See section <xref linkend="acc.i.extra-accounting"/> for more details.
 		</para>
 		<para>
 		Default value is NULL.
@@ -1077,7 +1077,7 @@ modparam("acc", "acc_time_column", "time")
 		<title><varname>db_extra</varname> (string)</title>
 		<para>
 		Extra values to be logged into database - DB specific.
-		See section <xref linkend="ACC-extra-id"/> for more details.
+		See section <xref linkend="acc.i.extra-accounting"/> for more details.
 		</para>
 		<para>
 		Default value is NULL.
@@ -1193,7 +1193,7 @@ modparam("acc", "diameter_client_port", 3000)
 		<title><varname>diameter_extra</varname> (string)</title>
 		<para>
 		Extra values to be logged via DIAMETER - DIAMETER specific.
-		See section <xref linkend="ACC-extra-id"/> for more details.
+		See section <xref linkend="acc.i.extra-accounting"/> for more details.
 		</para>
 		<para>
 		Default value is NULL.
@@ -1285,7 +1285,7 @@ modparam("acc", "cdr_facility", "LOG_DAEMON")
 		<title><varname>cdr_extra</varname> (string)</title>
 		<para>
 		Set of pseudo-variables defining custom CDR fields. See
-        <xref linkend="cdr-extra-id"/> for more details.
+        <xref linkend="acc.i.cdr-extra"/> for more details.
 		</para>
 		<para>
 		Default value is NULL.
@@ -1542,6 +1542,25 @@ modparam("acc", "clone_msg", 0)
 </programlisting>
 		</example>
 	</section>
+	<section id="acc.p.cdr_on_failed">
+		<title><varname>cdr_on_failed</varname> (int)</title>
+		<para>
+		If set to 1, the module stores the CDR for a failed dialog (calls not
+		answered). If set to 0, those records are not stored, only those for
+		answered calls.
+		</para>
+		<para>
+		Default value is 1.
+		</para>
+		<example>
+		<title>cdr_on_failed</title>
+		<programlisting format="linespecific">
+...
+modparam("acc", "cdr_on_failed", 0)
+...
+</programlisting>
+		</example>
+	</section>
 	</section>
 
 	<section>
diff --git a/modules/acc_radius/Makefile b/modules/acc_radius/Makefile
index 1710b34..56754c2 100644
--- a/modules/acc_radius/Makefile
+++ b/modules/acc_radius/Makefile
@@ -1,5 +1,3 @@
-# $Id$
-#
 # acc_radius module makefile
 #
 #
diff --git a/modules/alias_db/Makefile b/modules/alias_db/Makefile
index e5c6eea..2bbb7b5 100644
--- a/modules/alias_db/Makefile
+++ b/modules/alias_db/Makefile
@@ -1,5 +1,3 @@
-# $Id$
-#
 # User aliases
 #
 # 
diff --git a/modules/app_java/Makefile b/modules/app_java/Makefile
index ca854ed..f3a40ae 100644
--- a/modules/app_java/Makefile
+++ b/modules/app_java/Makefile
@@ -1,5 +1,3 @@
-# $Id$
-#
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
 
diff --git a/modules/app_java/app_java_mod.c b/modules/app_java/app_java_mod.c
new file mode 100644
index 0000000..f49d8a5
--- /dev/null
+++ b/modules/app_java/app_java_mod.c
@@ -0,0 +1,257 @@
+/**
+ * Copyright (C) 2013 Konstantin Mosesov
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <libgen.h>
+
+#include "../../str.h"
+#include "../../sr_module.h"
+
+#include <jni.h>
+
+#include "global.h"
+
+#include "utils.h"
+#include "app_java_mod.h"
+#include "java_iface.h"
+#include "java_support.h"
+
+#include "java_native_methods.h"
+
+MODULE_VERSION
+
+static char* class_name = "Kamailio";
+static char* child_init_mname = "child_init";
+static char* java_options_str = "-Djava.compiler=NONE";
+
+static int mod_init(void);
+static int child_init(int rank);
+static void mod_destroy(void);
+
+
+/** module parameters */
+static param_export_t params[] = {
+    {"class_name",         PARAM_STRING, &class_name },
+    {"child_init_method",  PARAM_STRING, &child_init_mname }, /* Unused parameter? */
+    {"java_options",	   PARAM_STRING, &java_options_str },
+    {"force_cmd_exec", INT_PARAM, &force_cmd_exec },
+    {0,0,0}
+};
+
+
+/*
+ * Exported functions
+ */
+static cmd_export_t cmds[] = {
+    { "java_method_exec",		(cmd_function)j_nst_exec_0,	2,	NULL,	0,	ANY_ROUTE },
+    { "java_method_exec",		(cmd_function)j_nst_exec_1,	3,	NULL,	0,	ANY_ROUTE },
+    { "java_s_method_exec",		(cmd_function)j_s_nst_exec_0,	2,	NULL,	0,	ANY_ROUTE },
+    { "java_s_method_exec",		(cmd_function)j_s_nst_exec_1,	3,	NULL,	0,	ANY_ROUTE },
+
+    { "java_staticmethod_exec",		(cmd_function)j_st_exec_0,	2,	NULL,	0,	ANY_ROUTE },
+    { "java_staticmethod_exec",		(cmd_function)j_st_exec_1,	3,	NULL,	0,	ANY_ROUTE },
+    { "java_s_staticmethod_exec",	(cmd_function)j_s_st_exec_0,	2,	NULL,	0,	ANY_ROUTE },
+    { "java_s_staticmethod_exec",	(cmd_function)j_s_st_exec_1,	3,	NULL,	0,	ANY_ROUTE },
+
+    { 0, 0, 0, 0, 0, 0 }
+};
+
+/** module exports */
+struct module_exports exports = {
+    APP_NAME,                       /* module name */
+//    RTLD_NOW | RTLD_GLOBAL,         /* dlopen flags */
+    DEFAULT_DLFLAGS,		    /* dlopen flags */
+    cmds,                           /* exported functions */
+    params,                         /* exported parameters */
+    0,                              /* exported statistics */
+    0,                              /* exported MI functions */
+    0,                              /* exported pseudo-variables */
+    0,                              /* extra processes */
+    mod_init,                       /* module initialization function */
+    (response_function) NULL,       /* response handling function */
+    (destroy_function) mod_destroy, /* destroy function */
+    child_init                      /* per-child init function */
+};
+
+static int mod_init(void)
+{
+    JavaVMInitArgs  vm_args;
+    jint res;
+    JavaVMOption *options;
+    char **opts;
+    int nOptions;
+
+    if (force_cmd_exec < 0 || force_cmd_exec > 1)
+    {
+	LM_ERR("Parameter force_cmd_exec should be either 0 or 1\n");
+	return -1;
+    }
+
+    if (force_cmd_exec)
+    {
+	LM_NOTICE("%s: Parameter force_cmd_exec may cause a memory leaks if used from embedded languages\n", APP_NAME);
+    }
+
+    options = (JavaVMOption *)pkg_malloc(sizeof(JavaVMOption));
+    if (!options)
+    {
+	LM_ERR("pkg_malloc() failed: Couldn't initialize Java VM: Not enough memory\n");
+	return -1;
+    }
+    memset(options, 0, sizeof(JavaVMOption));
+
+    LM_INFO("Initializing Java VM with options: %s\n", java_options_str);
+
+    opts = split(java_options_str, " ");
+    for (nOptions=0; opts[nOptions] != NULL; nOptions++)
+    {
+	options[nOptions].optionString = opts[nOptions];
+    }
+
+    /* IMPORTANT: specify vm_args version # if you use JDK1.1.2 and beyond */
+    vm_args.version = JNI_VERSION_1_2;
+    vm_args.nOptions = nOptions;
+    vm_args.ignoreUnrecognized = JNI_FALSE;
+    vm_args.options = options;
+
+    res = JNI_CreateJavaVM(&jvm, (void **)&env, &vm_args);
+    if (res < 0)
+    {
+	handle_VM_init_failure(res);
+	return -1;
+    }
+
+    LM_INFO("%s: Java VM initialization OK\n", APP_NAME);
+
+    // attach to current thread
+    (*jvm)->AttachCurrentThread(jvm, (void **)&env, NULL);
+    if ((*env)->ExceptionCheck(env))
+    {
+	handle_exception();
+	return -1;
+    }
+
+    KamailioClass = (*env)->FindClass(env, class_name);
+    if (!KamailioClass || (*env)->ExceptionCheck(env))
+    {
+	handle_exception();
+	(*jvm)->DetachCurrentThread(jvm);
+	return -1;
+    }
+
+    KamailioClassRef = (*env)->NewGlobalRef(env, KamailioClass);
+    if (!KamailioClassRef || (*env)->ExceptionCheck(env))
+    {
+	handle_exception();
+	(*jvm)->DetachCurrentThread(jvm);
+	return -1;
+    }
+
+    KamailioID = (*env)->GetMethodID(env, KamailioClass, "<init>", "()V");
+    if (!KamailioID || (*env)->ExceptionCheck(env))
+    {
+	handle_exception();
+	(*jvm)->DetachCurrentThread(jvm);
+	return -1;
+    }
+
+    // calling constructor
+    KamailioClassInstance = (*env)->NewObject(env, KamailioClass, KamailioID);
+    if (!KamailioClassInstance || (*env)->ExceptionCheck(env))
+    {
+	handle_exception();
+	(*jvm)->DetachCurrentThread(jvm);
+	return -1;
+    }
+
+    // keep a reference to kamailio class instance
+    KamailioClassInstanceRef = (*env)->NewGlobalRef(env, KamailioClassInstance);
+    if (!KamailioClassInstanceRef || (*env)->ExceptionCheck(env))
+    {
+	handle_exception();
+	(*jvm)->DetachCurrentThread(jvm);
+	return -1;
+    }
+
+    LM_INFO("%s: module initialization OK\n", APP_NAME);
+
+    if (jvm != NULL)
+        (*jvm)->DetachCurrentThread(jvm);
+
+    return 0;
+}
+
+static int child_init(int rank)
+{
+    int retval;
+    jmethodID child_init_id;
+
+    // attach to current thread
+    (*jvm)->AttachCurrentThread(jvm, (void **)&env, NULL);
+    if ((*env)->ExceptionCheck(env))
+    {
+        handle_exception();
+        return -1;
+    }
+
+    child_init_id = (*env)->GetMethodID(env, KamailioClass, "child_init", "(I)I");
+    if ((*env)->ExceptionCheck(env))
+    {
+	handle_exception();
+    	(*jvm)->DetachCurrentThread(jvm);
+	return -1;
+    }
+
+    retval = (int)(*env)->CallIntMethod(env, KamailioClassInstanceRef, child_init_id, rank);
+    if ((*env)->ExceptionCheck(env))
+    {
+	handle_exception();
+    	(*jvm)->DetachCurrentThread(jvm);
+	return -1;
+    }
+
+    (*env)->DeleteLocalRef(env, child_init_id);
+    (*jvm)->DetachCurrentThread(jvm);
+
+    msg = NULL;
+
+    return retval;
+}
+
+static void mod_destroy(void)
+{
+    if (env != NULL)
+    {
+	(*env)->DeleteGlobalRef(env, KamailioClassInstanceRef);
+	(*env)->DeleteGlobalRef(env, KamailioClassRef);
+    }
+
+    if (jvm != NULL)
+    {
+	(*jvm)->DetachCurrentThread(jvm);
+	(*jvm)->DestroyJavaVM(jvm);
+    }
+
+    if (msg)
+    {
+	pkg_free(msg);
+    }
+
+}
diff --git a/modules/app_java/app_java_mod.h b/modules/app_java/app_java_mod.h
new file mode 100644
index 0000000..65227e6
--- /dev/null
+++ b/modules/app_java/app_java_mod.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2013 Konstantin Mosesov
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef __JAVA_MOD_H__
+#define	__JAVA_MOD_H__
+
+int force_cmd_exec;
+
+#endif
diff --git a/modules/app_java/global.h b/modules/app_java/global.h
index 35c82b0..0fc6b6c 100644
--- a/modules/app_java/global.h
+++ b/modules/app_java/global.h
@@ -1,6 +1,4 @@
-/**
- * $Id$
- *
+/*
  * Copyright (C) 2013 Konstantin Mosesov
  *
  * This file is part of Kamailio, a free SIP server.
@@ -10,7 +8,6 @@
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- *
  * This file is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
diff --git a/modules/app_java/java_iface.c b/modules/app_java/java_iface.c
index abecd58..ada3c97 100644
--- a/modules/app_java/java_iface.c
+++ b/modules/app_java/java_iface.c
@@ -1,6 +1,4 @@
-/**
- * $Id$
- *
+/*
  * Copyright (C) 2013 Konstantin Mosesov
  *
  * This file is part of Kamailio, a free SIP server.
@@ -31,7 +29,7 @@
 #include "global.h"
 #include "java_iface.h"
 #include "utils.h"
-#include "java_mod.h"
+#include "app_java_mod.h"
 #include "java_iface.h"
 #include "java_support.h"
 #include "java_native_methods.h"
diff --git a/modules/app_java/java_iface.h b/modules/app_java/java_iface.h
index 8c17575..3ff66a4 100644
--- a/modules/app_java/java_iface.h
+++ b/modules/app_java/java_iface.h
@@ -1,6 +1,4 @@
-/**
- * $Id$
- *
+/*
  * Copyright (C) 2013 Konstantin Mosesov
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/app_java/java_mod.c b/modules/app_java/java_mod.c
deleted file mode 100644
index 5e22d08..0000000
--- a/modules/app_java/java_mod.c
+++ /dev/null
@@ -1,260 +0,0 @@
-/**
- * $Id$
- *
- * Copyright (C) 2013 Konstantin Mosesov
- *
- * This file is part of Kamailio, a free SIP server.
- *
- * This file is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version
- *
- *
- * This file is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- *
- */
-
-#include <libgen.h>
-
-#include "../../str.h"
-#include "../../sr_module.h"
-
-#include <jni.h>
-
-#include "global.h"
-
-#include "utils.h"
-#include "java_mod.h"
-#include "java_iface.h"
-#include "java_support.h"
-
-#include "java_native_methods.h"
-
-MODULE_VERSION
-
-static char* class_name = "Kamailio";
-static char* child_init_mname = "child_init";
-static char* java_options_str = "-Djava.compiler=NONE";
-
-static int mod_init(void);
-static int child_init(int rank);
-static void mod_destroy(void);
-
-
-/** module parameters */
-static param_export_t params[] = {
-    {"class_name",         PARAM_STRING, &class_name },
-    {"child_init_method",  PARAM_STRING, &child_init_mname }, /* Unused parameter? */
-    {"java_options",	   PARAM_STRING, &java_options_str },
-    {"force_cmd_exec", INT_PARAM, &force_cmd_exec },
-    {0,0,0}
-};
-
-
-/*
- * Exported functions
- */
-static cmd_export_t cmds[] = {
-    { "java_method_exec",		(cmd_function)j_nst_exec_0,	2,	NULL,	0,	ANY_ROUTE },
-    { "java_method_exec",		(cmd_function)j_nst_exec_1,	3,	NULL,	0,	ANY_ROUTE },
-    { "java_s_method_exec",		(cmd_function)j_s_nst_exec_0,	2,	NULL,	0,	ANY_ROUTE },
-    { "java_s_method_exec",		(cmd_function)j_s_nst_exec_1,	3,	NULL,	0,	ANY_ROUTE },
-
-    { "java_staticmethod_exec",		(cmd_function)j_st_exec_0,	2,	NULL,	0,	ANY_ROUTE },
-    { "java_staticmethod_exec",		(cmd_function)j_st_exec_1,	3,	NULL,	0,	ANY_ROUTE },
-    { "java_s_staticmethod_exec",	(cmd_function)j_s_st_exec_0,	2,	NULL,	0,	ANY_ROUTE },
-    { "java_s_staticmethod_exec",	(cmd_function)j_s_st_exec_1,	3,	NULL,	0,	ANY_ROUTE },
-
-    { 0, 0, 0, 0, 0, 0 }
-};
-
-/** module exports */
-struct module_exports exports = {
-    APP_NAME,                       /* module name */
-//    RTLD_NOW | RTLD_GLOBAL,         /* dlopen flags */
-    DEFAULT_DLFLAGS,		    /* dlopen flags */
-    cmds,                           /* exported functions */
-    params,                         /* exported parameters */
-    0,                              /* exported statistics */
-    0,                              /* exported MI functions */
-    0,                              /* exported pseudo-variables */
-    0,                              /* extra processes */
-    mod_init,                       /* module initialization function */
-    (response_function) NULL,       /* response handling function */
-    (destroy_function) mod_destroy, /* destroy function */
-    child_init                      /* per-child init function */
-};
-
-static int mod_init(void)
-{
-    JavaVMInitArgs  vm_args;
-    jint res;
-    JavaVMOption *options;
-    char **opts;
-    int nOptions;
-
-    if (force_cmd_exec < 0 || force_cmd_exec > 1)
-    {
-	LM_ERR("Parameter force_cmd_exec should be either 0 or 1\n");
-	return -1;
-    }
-
-    if (force_cmd_exec)
-    {
-	LM_NOTICE("%s: Parameter force_cmd_exec may cause a memory leaks if used from embedded languages\n", APP_NAME);
-    }
-
-    options = (JavaVMOption *)pkg_malloc(sizeof(JavaVMOption));
-    if (!options)
-    {
-	LM_ERR("pkg_malloc() failed: Couldn't initialize Java VM: Not enough memory\n");
-	return -1;
-    }
-    memset(options, 0, sizeof(JavaVMOption));
-
-    LM_INFO("Initializing Java VM with options: %s\n", java_options_str);
-
-    opts = split(java_options_str, " ");
-    for (nOptions=0; opts[nOptions] != NULL; nOptions++)
-    {
-	options[nOptions].optionString = opts[nOptions];
-    }
-
-    /* IMPORTANT: specify vm_args version # if you use JDK1.1.2 and beyond */
-    vm_args.version = JNI_VERSION_1_2;
-    vm_args.nOptions = nOptions;
-    vm_args.ignoreUnrecognized = JNI_FALSE;
-    vm_args.options = options;
-
-    res = JNI_CreateJavaVM(&jvm, (void **)&env, &vm_args);
-    if (res < 0)
-    {
-	handle_VM_init_failure(res);
-	return -1;
-    }
-
-    LM_INFO("%s: Java VM initialization OK\n", APP_NAME);
-
-    // attach to current thread
-    (*jvm)->AttachCurrentThread(jvm, (void **)&env, NULL);
-    if ((*env)->ExceptionCheck(env))
-    {
-	handle_exception();
-	return -1;
-    }
-
-    KamailioClass = (*env)->FindClass(env, class_name);
-    if (!KamailioClass || (*env)->ExceptionCheck(env))
-    {
-	handle_exception();
-	(*jvm)->DetachCurrentThread(jvm);
-	return -1;
-    }
-
-    KamailioClassRef = (*env)->NewGlobalRef(env, KamailioClass);
-    if (!KamailioClassRef || (*env)->ExceptionCheck(env))
-    {
-	handle_exception();
-	(*jvm)->DetachCurrentThread(jvm);
-	return -1;
-    }
-
-    KamailioID = (*env)->GetMethodID(env, KamailioClass, "<init>", "()V");
-    if (!KamailioID || (*env)->ExceptionCheck(env))
-    {
-	handle_exception();
-	(*jvm)->DetachCurrentThread(jvm);
-	return -1;
-    }
-
-    // calling constructor
-    KamailioClassInstance = (*env)->NewObject(env, KamailioClass, KamailioID);
-    if (!KamailioClassInstance || (*env)->ExceptionCheck(env))
-    {
-	handle_exception();
-	(*jvm)->DetachCurrentThread(jvm);
-	return -1;
-    }
-
-    // keep a reference to kamailio class instance
-    KamailioClassInstanceRef = (*env)->NewGlobalRef(env, KamailioClassInstance);
-    if (!KamailioClassInstanceRef || (*env)->ExceptionCheck(env))
-    {
-	handle_exception();
-	(*jvm)->DetachCurrentThread(jvm);
-	return -1;
-    }
-
-    LM_INFO("%s: module initialization OK\n", APP_NAME);
-
-    if (jvm != NULL)
-        (*jvm)->DetachCurrentThread(jvm);
-
-    return 0;
-}
-
-static int child_init(int rank)
-{
-    int retval;
-    jmethodID child_init_id;
-
-    // attach to current thread
-    (*jvm)->AttachCurrentThread(jvm, (void **)&env, NULL);
-    if ((*env)->ExceptionCheck(env))
-    {
-        handle_exception();
-        return -1;
-    }
-
-    child_init_id = (*env)->GetMethodID(env, KamailioClass, "child_init", "(I)I");
-    if ((*env)->ExceptionCheck(env))
-    {
-	handle_exception();
-    	(*jvm)->DetachCurrentThread(jvm);
-	return -1;
-    }
-
-    retval = (int)(*env)->CallIntMethod(env, KamailioClassInstanceRef, child_init_id, rank);
-    if ((*env)->ExceptionCheck(env))
-    {
-	handle_exception();
-    	(*jvm)->DetachCurrentThread(jvm);
-	return -1;
-    }
-
-    (*env)->DeleteLocalRef(env, child_init_id);
-    (*jvm)->DetachCurrentThread(jvm);
-
-    msg = NULL;
-
-    return retval;
-}
-
-static void mod_destroy(void)
-{
-    if (env != NULL)
-    {
-	(*env)->DeleteGlobalRef(env, KamailioClassInstanceRef);
-	(*env)->DeleteGlobalRef(env, KamailioClassRef);
-    }
-
-    if (jvm != NULL)
-    {
-	(*jvm)->DetachCurrentThread(jvm);
-	(*jvm)->DestroyJavaVM(jvm);
-    }
-
-    if (msg)
-    {
-	pkg_free(msg);
-    }
-
-}
diff --git a/modules/app_java/java_mod.h b/modules/app_java/java_mod.h
deleted file mode 100644
index ad0126c..0000000
--- a/modules/app_java/java_mod.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/**
- * $Id$
- *
- * Copyright (C) 2013 Konstantin Mosesov
- *
- * This file is part of Kamailio, a free SIP server.
- *
- * This file is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version
- *
- *
- * This file is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- *
- */
-
-#ifndef __JAVA_MOD_H__
-#define	__JAVA_MOD_H__
-
-int force_cmd_exec;
-
-#endif
diff --git a/modules/app_java/java_msgobj.c b/modules/app_java/java_msgobj.c
index 1a8ae56..0a43786 100644
--- a/modules/app_java/java_msgobj.c
+++ b/modules/app_java/java_msgobj.c
@@ -1,6 +1,4 @@
-/**
- * $Id$
- *
+/*
  * Copyright (C) 2013 Konstantin Mosesov
  *
  * This file is part of Kamailio, a free SIP server.
@@ -33,7 +31,7 @@
 
 #include "global.h"
 #include "utils.h"
-#include "java_mod.h"
+#include "app_java_mod.h"
 #include "java_iface.h"
 #include "java_support.h"
 #include "java_native_methods.h"
diff --git a/modules/app_java/java_msgobj.h b/modules/app_java/java_msgobj.h
index efd8ecd..1c53b4a 100644
--- a/modules/app_java/java_msgobj.h
+++ b/modules/app_java/java_msgobj.h
@@ -1,6 +1,4 @@
-/**
- * $Id$
- *
+/*
  * Copyright (C) 2013 Konstantin Mosesov
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/app_java/java_native_methods.c b/modules/app_java/java_native_methods.c
index cb9bd9a..c141659 100644
--- a/modules/app_java/java_native_methods.c
+++ b/modules/app_java/java_native_methods.c
@@ -1,6 +1,4 @@
-/**
- * $Id$
- *
+/*
  * Copyright (C) 2013 Konstantin Mosesov
  *
  * This file is part of Kamailio, a free SIP server.
@@ -30,7 +28,7 @@
 
 #include "global.h"
 #include "utils.h"
-#include "java_mod.h"
+#include "app_java_mod.h"
 #include "java_iface.h"
 #include "java_support.h"
 #include "java_msgobj.h"
diff --git a/modules/app_java/java_native_methods.h b/modules/app_java/java_native_methods.h
index acbe5a8..bd57cc6 100644
--- a/modules/app_java/java_native_methods.h
+++ b/modules/app_java/java_native_methods.h
@@ -1,6 +1,4 @@
-/**
- * $Id$
- *
+/*
  * Copyright (C) 2013 Konstantin Mosesov
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/app_java/java_sig_parser.c b/modules/app_java/java_sig_parser.c
index b07ce39..61d8895 100644
--- a/modules/app_java/java_sig_parser.c
+++ b/modules/app_java/java_sig_parser.c
@@ -1,6 +1,4 @@
-/**
- * $Id$
- *
+/*
  * Copyright (C) 2013 Konstantin Mosesov
  *
  * This file is part of Kamailio, a free SIP server.
@@ -33,7 +31,7 @@
 
 #include "global.h"
 #include "utils.h"
-#include "java_mod.h"
+#include "app_java_mod.h"
 #include "java_iface.h"
 #include "java_support.h"
 #include "java_native_methods.h"
diff --git a/modules/app_java/java_sig_parser.h b/modules/app_java/java_sig_parser.h
index 3ab0ecb..c304938 100644
--- a/modules/app_java/java_sig_parser.h
+++ b/modules/app_java/java_sig_parser.h
@@ -1,6 +1,4 @@
-/**
- * $Id$
- *
+/*
  * Copyright (C) 2013 Konstantin Mosesov
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/app_java/java_support.c b/modules/app_java/java_support.c
index d0337e1..af87ed6 100644
--- a/modules/app_java/java_support.c
+++ b/modules/app_java/java_support.c
@@ -1,6 +1,4 @@
-/**
- * $Id$
- *
+/*
  * Copyright (C) 2013 Konstantin Mosesov
  *
  * This file is part of Kamailio, a free SIP server.
@@ -32,7 +30,7 @@
 #include "global.h"
 
 #include "utils.h"
-#include "java_mod.h"
+#include "app_java_mod.h"
 #include "java_iface.h"
 #include "java_support.h"
 
diff --git a/modules/app_java/java_support.h b/modules/app_java/java_support.h
index f0e5dd4..31411e9 100644
--- a/modules/app_java/java_support.h
+++ b/modules/app_java/java_support.h
@@ -1,6 +1,4 @@
-/**
- * $Id$
- *
+/*
  * Copyright (C) 2013 Konstantin Mosesov
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/app_java/utils.c b/modules/app_java/utils.c
index b2ff2a3..072a97b 100644
--- a/modules/app_java/utils.c
+++ b/modules/app_java/utils.c
@@ -1,6 +1,4 @@
-/**
- * $Id$
- *
+/*
  * Copyright (C) 2013 Konstantin Mosesov
  *
  * This file is part of Kamailio, a free SIP server.
@@ -32,7 +30,7 @@
 
 #include "global.h"
 #include "utils.h"
-#include "java_mod.h"
+#include "app_java_mod.h"
 #include "java_iface.h"
 #include "java_support.h"
 #include "java_native_methods.h"
diff --git a/modules/app_java/utils.h b/modules/app_java/utils.h
index a2c68be..c761437 100644
--- a/modules/app_java/utils.h
+++ b/modules/app_java/utils.h
@@ -1,6 +1,4 @@
-/**
- * $Id$
- *
+/*
  * Copyright (C) 2013 Konstantin Mosesov
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/app_lua/Makefile b/modules/app_lua/Makefile
index 864e6d9..b66044c 100644
--- a/modules/app_lua/Makefile
+++ b/modules/app_lua/Makefile
@@ -1,5 +1,3 @@
-# $Id$
-#
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
 
@@ -17,14 +15,20 @@ ifeq ($(BUILDER),)
 	endif
 	ifeq ($(BUILDER),)
 		LUA51 = $(shell ls $(LOCALBASE)/lib/liblua* | grep liblua5.1)
-		DEFS+=-I$(LOCALBASE)/include
-		LIBS+=-L$(LOCALBASE)/lib -lm
-		ifeq ($(LUA51),)
-			DEFS+=-I$(LOCALBASE)/include/lua
-			LIBS+=-llua
+		DEFS+= -I$(LOCALBASE)/include
+		LIBS+= -L$(LOCALBASE)/lib -lm
+		ifneq ($(LUA51),)
+			DEFS+= -I$(LOCALBASE)/include/lua5.1
+			LIBS+= -llua5.1
 		else
-			DEFS+=-I$(LOCALBASE)/include/lua5.1
-			LIBS+=-llua5.1
+			LUA52 = $(shell ls $(LOCALBASE)/lib/liblua* | grep liblua5.2)
+			ifneq ($(LUA52),)
+				DEFS+= -DLUA_COMPAT_MODULE -I$(LOCALBASE)/include/lua5.2
+				LIBS+= -llua5.2
+			else
+				DEFS+= -I$(LOCALBASE)/include/lua
+				LIBS+= -llua
+			endif
 		endif
 	else
 		LUAVER=XX
@@ -32,9 +36,14 @@ ifeq ($(BUILDER),)
 		ifeq ($(LUALIBS),)
 			LUALIBS = $(shell pkg-config --silence-errors --libs lua5.1)
 			ifeq ($(LUALIBS),)
-				LUALIBS = $(shell pkg-config --silence-errors --libs lua)
-				ifneq ($(LUALIBS),)
-					LUAVER=5X
+				LUALIBS = $(shell pkg-config --silence-errors --libs lua5.2)
+				ifeq ($(LUALIBS),)
+					LUALIBS = $(shell pkg-config --silence-errors --libs lua)
+					ifneq ($(LUALIBS),)
+						LUAVER=5X
+					endif
+				else
+					LUAVER=52
 				endif
 			else
 				LUAVER=51
@@ -44,12 +53,18 @@ ifeq ($(BUILDER),)
 		endif
 		ifeq ($(LUAVER),XX)
 			LUA51 = $(shell ls /usr/lib/liblua* | grep liblua5.1)
-			ifeq ($(LUA51),)
-				DEFS+=-I/usr/include/lua
-				LIBS= -llua -lm
+			ifneq ($(LUA51),)
+				DEFS+= -I/usr/include/lua5.1
+				LIBS = -llua5.1 -lm
 			else
-				DEFS+=-I/usr/include/lua5.1
-				LIBS= -llua5.1 -lm
+				LUA52 = $(shell ls /usr/lib/liblua* | grep liblua5.2)
+				ifneq ($(LUA51),)
+					DEFS+= -DLUA_COMPAT_MODULE -I/usr/include/lua5.2
+					LIBS = -llua5.2 -lm
+				else
+					DEFS+= -I/usr/include/lua
+					LIBS = -llua -lm
+				endif
 			endif
 		else
 			ifeq ($(LUAVER),51)
@@ -60,8 +75,13 @@ ifeq ($(BUILDER),)
 					DEFS+= $(shell pkg-config --cflags lua-5.1)
 					LIBS = $(shell pkg-config --libs lua-5.1)
 				else
-					DEFS+= $(shell pkg-config --cflags lua)
-					LIBS = $(shell pkg-config --libs lua)
+					ifeq ($(LUAVER),52)
+						DEFS+= -DLUA_COMPAT_MODULE $(shell pkg-config --cflags lua5.2)
+						LIBS = $(shell pkg-config --libs lua5.2)
+					else
+						DEFS+= $(shell pkg-config --cflags lua)
+						LIBS = $(shell pkg-config --libs lua)
+					endif
 				endif
 			endif
 		endif
diff --git a/modules/app_lua/app_lua_api.c b/modules/app_lua/app_lua_api.c
index 760fe6d..769c5a2 100644
--- a/modules/app_lua/app_lua_api.c
+++ b/modules/app_lua/app_lua_api.c
@@ -216,7 +216,7 @@ int lua_sr_init_probe(void)
 	sr_lua_load_t *li;
 	struct stat sbuf;
 
-	L = lua_open();
+	L = luaL_newstate();
 	if(L==NULL)
 	{
 		LM_ERR("cannot open lua\n");
@@ -267,7 +267,7 @@ int lua_sr_init_child(void)
 	char *txt;
 
 	memset(&_sr_L_env, 0, sizeof(sr_lua_env_t));
-	_sr_L_env.L = lua_open();
+	_sr_L_env.L = luaL_newstate();
 	if(_sr_L_env.L==NULL)
 	{
 		LM_ERR("cannot open lua\n");
@@ -277,10 +277,14 @@ int lua_sr_init_child(void)
 	lua_sr_openlibs(_sr_L_env.L);
 
 	/* set SR lib version */
+#if LUA_VERSION_NUM >= 502
+	lua_pushstring(_sr_L_env.L, SRVERSION);
+	lua_setglobal(_sr_L_env.L, "SRVERSION");
+#else
 	lua_pushstring(_sr_L_env.L, "SRVERSION");
 	lua_pushstring(_sr_L_env.L, SRVERSION);
 	lua_settable(_sr_L_env.L, LUA_GLOBALSINDEX);
-
+#endif
 	if(_sr_lua_load_list != NULL)
 	{
 		_sr_L_env.LL = luaL_newstate();
@@ -293,10 +297,14 @@ int lua_sr_init_child(void)
 		lua_sr_openlibs(_sr_L_env.LL);
 
 		/* set SR lib version */
+#if LUA_VERSION_NUM >= 502
+		lua_pushstring(_sr_L_env.L, SRVERSION);
+		lua_setglobal(_sr_L_env.L, "SRVERSION");
+#else
 		lua_pushstring(_sr_L_env.LL, "SRVERSION");
 		lua_pushstring(_sr_L_env.LL, SRVERSION);
 		lua_settable(_sr_L_env.LL, LUA_GLOBALSINDEX);
-
+#endif
 		/* force loading lua lib now */
 		if(luaL_dostring(_sr_L_env.LL, "sr.probe()")!=0)
 		{
diff --git a/modules/app_lua/app_lua_exp.c b/modules/app_lua/app_lua_exp.c
index 5199345..6853b2d 100644
--- a/modules/app_lua/app_lua_exp.c
+++ b/modules/app_lua/app_lua_exp.c
@@ -55,6 +55,7 @@
 #include "../../modules/cfgutils/api.h"
 #include "../../modules/tmx/api.h"
 #include "../../modules/mqueue/api.h"
+#include "../../modules/ndb_mongodb/api.h"
 
 #include "app_lua_api.h"
 
@@ -82,6 +83,7 @@
 #define SR_LUA_EXP_MOD_CFGUTILS   (1<<21)
 #define SR_LUA_EXP_MOD_TMX        (1<<22)
 #define SR_LUA_EXP_MOD_MQUEUE     (1<<23)
+#define SR_LUA_EXP_MOD_NDB_MONGODB (1<<24)
 
 /**
  *
@@ -210,6 +212,12 @@ static tmx_api_t _lua_tmxb;
 static mq_api_t _lua_mqb;
 
 /**
+ * mqueue
+ */
+static ndb_mongodb_api_t _lua_ndb_mongodbb;
+
+
+/**
  *
  */
 static int lua_sr_sl_send_reply (lua_State *L)
@@ -280,7 +288,7 @@ static int lua_sr_sl_get_reply_totag (lua_State *L)
 /**
  *
  */
-static const luaL_reg _sr_sl_Map [] = {
+static const luaL_Reg _sr_sl_Map [] = {
 	{"send_reply",      lua_sr_sl_send_reply},
 	{"get_reply_totag", lua_sr_sl_get_reply_totag},
 	{NULL, NULL}
@@ -606,17 +614,125 @@ static int lua_sr_tm_t_replicate(lua_State *L)
 /**
  *
  */
-static const luaL_reg _sr_tm_Map [] = {
-	{"t_reply",        lua_sr_tm_t_reply},
-	{"t_relay",        lua_sr_tm_t_relay},
-	{"t_on_failure",   lua_sr_tm_t_on_failure},
-	{"t_on_branch",    lua_sr_tm_t_on_branch},
-	{"t_on_reply",     lua_sr_tm_t_on_reply},
-	{"t_check_trans",  lua_sr_tm_t_check_trans},
-	{"t_is_canceled",  lua_sr_tm_t_is_canceled},
-	{"t_newtran",      lua_sr_tm_t_newtran},
-	{"t_release",      lua_sr_tm_t_release},
-	{"t_replicate",    lua_sr_tm_t_replicate},
+#define BRANCH_FAILURE_ROUTE_PREFIX "tm:branch-failure"
+static int lua_sr_tm_t_on_branch_failure(lua_State *L)
+{
+	static str rt_name = {NULL, 0};
+	char *name;
+	int rt_name_len;
+	int i;
+	sr_lua_env_t *env_L;
+
+	env_L = sr_lua_env_get();
+
+	if(!(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_TM))
+	{
+		LM_WARN("weird: tm function executed but module not registered\n");
+		return app_lua_return_error(L);
+	}
+
+	if(env_L->msg==NULL)
+	{
+		LM_WARN("invalid parameters from Lua env\n");
+		return app_lua_return_error(L);
+	}
+
+	name = (char*)lua_tostring(L, -1);
+	if(name==NULL)
+	{
+		LM_WARN("invalid parameters from Lua\n");
+		return app_lua_return_error(L);
+	}
+	rt_name_len = strlen(BRANCH_FAILURE_ROUTE_PREFIX) + 1 + strlen(name);
+	if (rt_name_len > rt_name.len)
+	{
+		if ((rt_name.s = pkg_realloc(rt_name.s, rt_name_len+1)) == NULL)
+		{
+			LM_ERR("No memory left in branch_failure fixup\n");
+			return -1;
+		}
+		rt_name.len = rt_name_len;
+	}
+	sprintf(rt_name.s, "%s:%s", BRANCH_FAILURE_ROUTE_PREFIX, name);
+
+	i = route_get(&event_rt, rt_name.s);
+	if(i < 0 || event_rt.rlist[i]==0)
+	{
+		LM_WARN("no actions in branch_failure_route[%s]\n", name);
+		return app_lua_return_error(L);
+	}
+
+	_lua_xtmb.t_on_branch_failure((unsigned int)i);
+	return app_lua_return_int(L, 1);
+}
+
+/**
+ *
+ */
+static int lua_sr_tm_t_load_contacts(lua_State *L)
+{
+	int ret;
+	sr_lua_env_t *env_L;
+
+	env_L = sr_lua_env_get();
+
+	if(!(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_TM))
+	{
+		LM_WARN("weird: tm function executed but module not registered\n");
+		return app_lua_return_error(L);
+	}
+	if(env_L->msg==NULL)
+	{
+		LM_WARN("invalid parameters from Lua env\n");
+		return app_lua_return_error(L);
+	}
+
+	ret = _lua_tmb.t_load_contacts(env_L->msg, NULL, NULL);
+	return app_lua_return_int(L, ret);
+}
+
+/**
+ *
+ */
+static int lua_sr_tm_t_next_contacts(lua_State *L)
+{
+	int ret;
+	sr_lua_env_t *env_L;
+
+	env_L = sr_lua_env_get();
+
+	if(!(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_TM))
+	{
+		LM_WARN("weird: tm function executed but module not registered\n");
+		return app_lua_return_error(L);
+	}
+	if(env_L->msg==NULL)
+	{
+		LM_WARN("invalid parameters from Lua env\n");
+		return app_lua_return_error(L);
+	}
+
+	ret = _lua_tmb.t_next_contacts(env_L->msg, NULL, NULL);
+	return app_lua_return_int(L, ret);
+}
+
+/**
+ *
+ */
+static const luaL_Reg _sr_tm_Map [] = {
+	{"t_reply",             lua_sr_tm_t_reply},
+	{"t_relay",             lua_sr_tm_t_relay},
+	{"t_on_failure",        lua_sr_tm_t_on_failure},
+	{"t_on_branch",         lua_sr_tm_t_on_branch},
+	{"t_on_reply",          lua_sr_tm_t_on_reply},
+	{"t_check_trans",       lua_sr_tm_t_check_trans},
+	{"t_is_canceled",       lua_sr_tm_t_is_canceled},
+	{"t_newtran",           lua_sr_tm_t_newtran},
+	{"t_release",           lua_sr_tm_t_release},
+	{"t_replicate",         lua_sr_tm_t_replicate},
+	{"t_on_branch_failure", lua_sr_tm_t_on_branch_failure},
+	{"t_load_contacts",     lua_sr_tm_t_load_contacts},
+	{"t_next_contacts",     lua_sr_tm_t_next_contacts},
 	{NULL, NULL}
 };
 
@@ -871,7 +987,7 @@ static int lua_sr_sqlops_xquery(lua_State *L)
 /**
  *
  */
-static const luaL_reg _sr_sqlops_Map [] = {
+static const luaL_Reg _sr_sqlops_Map [] = {
 	{"query",   lua_sr_sqlops_query},
 	{"value",   lua_sr_sqlops_value},
 	{"is_null", lua_sr_sqlops_is_null},
@@ -980,7 +1096,7 @@ static int lua_sr_rr_add_rr_param(lua_State *L)
 /**
  *
  */
-static const luaL_reg _sr_rr_Map [] = {
+static const luaL_Reg _sr_rr_Map [] = {
 	{"record_route",    lua_sr_rr_record_route},
 	{"loose_route",     lua_sr_rr_loose_route},
 	{"add_rr_param",    lua_sr_rr_add_rr_param},
@@ -1129,7 +1245,7 @@ static int lua_sr_auth_consume_credentials(lua_State *L)
 /**
  *
  */
-static const luaL_reg _sr_auth_Map [] = {
+static const luaL_Reg _sr_auth_Map [] = {
 	{"www_challenge",            lua_sr_auth_www_challenge},
 	{"proxy_challenge",          lua_sr_auth_proxy_challenge},
 	{"pv_www_authenticate",      lua_sr_auth_pv_www_authenticate},
@@ -1200,7 +1316,7 @@ static int lua_sr_auth_db_proxy_authenticate(lua_State *L)
 /**
  *
  */
-static const luaL_reg _sr_auth_db_Map [] = {
+static const luaL_Reg _sr_auth_db_Map [] = {
 	{"www_authenticate",      lua_sr_auth_db_www_authenticate},
 	{"proxy_authenticate",    lua_sr_auth_db_proxy_authenticate},
 	{NULL, NULL}
@@ -1248,7 +1364,7 @@ static int lua_sr_maxfwd_process_maxfwd(lua_State *L)
 /**
  *
  */
-static const luaL_reg _sr_maxfwd_Map [] = {
+static const luaL_Reg _sr_maxfwd_Map [] = {
 	{"process_maxfwd",      lua_sr_maxfwd_process_maxfwd},
 	{NULL, NULL}
 };
@@ -1399,7 +1515,7 @@ static int lua_sr_registrar_registered(lua_State *L)
 /**
  *
  */
-static const luaL_reg _sr_registrar_Map [] = {
+static const luaL_Reg _sr_registrar_Map [] = {
 	{"save",      lua_sr_registrar_save},
 	{"lookup",    lua_sr_registrar_lookup},
 	{"registered",lua_sr_registrar_registered},
@@ -1551,7 +1667,7 @@ static int lua_sr_dispatcher_is_from(lua_State *L)
 /**
  *
  */
-static const luaL_reg _sr_dispatcher_Map [] = {
+static const luaL_Reg _sr_dispatcher_Map [] = {
 	{"select",      lua_sr_dispatcher_select},
 	{"next",        lua_sr_dispatcher_next},
 	{"mark",        lua_sr_dispatcher_mark},
@@ -1606,7 +1722,7 @@ static int lua_sr_xhttp_reply(lua_State *L)
 /**
  *
  */
-static const luaL_reg _sr_xhttp_Map [] = {
+static const luaL_Reg _sr_xhttp_Map [] = {
 	{"reply",       lua_sr_xhttp_reply},
 	{NULL, NULL}
 };
@@ -1651,7 +1767,7 @@ static int lua_sr_sdpops_with_media(lua_State *L)
 /**
  *
  */
-static const luaL_reg _sr_sdpops_Map [] = {
+static const luaL_Reg _sr_sdpops_Map [] = {
 	{"sdp_with_media",       lua_sr_sdpops_with_media},
 	{NULL, NULL}
 };
@@ -1776,7 +1892,7 @@ static int lua_sr_pres_handle_subscribe(lua_State *L)
 /**
  *
  */
-static const luaL_reg _sr_presence_Map [] = {
+static const luaL_Reg _sr_presence_Map [] = {
 	{"pres_auth_status",       lua_sr_pres_auth_status},
 	{"handle_publish",         lua_sr_pres_handle_publish},
 	{"handle_subscribe",       lua_sr_pres_handle_subscribe},
@@ -1862,7 +1978,7 @@ static int lua_sr_pres_check_activities(lua_State *L)
 /**
  *
  */
-static const luaL_reg _sr_presence_xml_Map [] = {
+static const luaL_Reg _sr_presence_xml_Map [] = {
 	{"pres_check_basic",       lua_sr_pres_check_basic},
 	{"pres_check_activities",  lua_sr_pres_check_activities},
 	{NULL, NULL}
@@ -1907,7 +2023,7 @@ static int lua_sr_textops_is_privacy(lua_State *L)
 /**
  *
  */
-static const luaL_reg _sr_textops_Map [] = {
+static const luaL_Reg _sr_textops_Map [] = {
 	{"is_privacy",       lua_sr_textops_is_privacy},
 	{NULL, NULL}
 };
@@ -1947,7 +2063,7 @@ static int lua_sr_pua_usrloc_set_publish(lua_State *L)
 /**
  *
  */
-static const luaL_reg _sr_pua_usrloc_Map [] = {
+static const luaL_Reg _sr_pua_usrloc_Map [] = {
 	{"set_publish",            lua_sr_pua_usrloc_set_publish},
 	{NULL, NULL}
 };
@@ -2026,7 +2142,7 @@ static int lua_sr_siputils_is_uri_user_e164(lua_State *L)
 /**
  *
  */
-static const luaL_reg _sr_siputils_Map [] = {
+static const luaL_Reg _sr_siputils_Map [] = {
 	{"has_totag",            lua_sr_siputils_has_totag},
 	{"is_uri_user_e164",     lua_sr_siputils_is_uri_user_e164},
 	{NULL, NULL}
@@ -2114,7 +2230,7 @@ static int lua_sr_rls_handle_notify(lua_State *L)
 /**
  *
  */
-static const luaL_reg _sr_rls_Map [] = {
+static const luaL_Reg _sr_rls_Map [] = {
 	{"handle_subscribe",       lua_sr_rls_handle_subscribe},
 	{"handle_notify",          lua_sr_rls_handle_notify},
 	{NULL, NULL}
@@ -2159,7 +2275,7 @@ static int lua_sr_alias_db_lookup(lua_State *L)
 /**
  *
  */
-static const luaL_reg _sr_alias_db_Map [] = {
+static const luaL_Reg _sr_alias_db_Map [] = {
 	{"lookup",       lua_sr_alias_db_lookup},
 	{NULL, NULL}
 };
@@ -2259,7 +2375,7 @@ static int lua_sr_msilo_dump(lua_State *L)
 /**
  *
  */
-static const luaL_reg _sr_msilo_Map [] = {
+static const luaL_Reg _sr_msilo_Map [] = {
 	{"store",       lua_sr_msilo_store},
 	{"dump",        lua_sr_msilo_dump},
 	{NULL, NULL}
@@ -2268,7 +2384,7 @@ static const luaL_reg _sr_msilo_Map [] = {
 /**
  *
  */
-static int lua_sr_uac_replace_from(lua_State *L)
+static int lua_sr_uac_replace_x(lua_State *L, int htype)
 {
 	int ret;
 	sr_lua_env_t *env_L;
@@ -2309,15 +2425,64 @@ static int lua_sr_uac_replace_from(lua_State *L)
 		return app_lua_return_error(L);
 	}
 
-	ret = _lua_uacb.replace_from(env_L->msg, &param[0], &param[1]);
+	if(htype==1) {
+		ret = _lua_uacb.replace_to(env_L->msg, &param[0], &param[1]);
+	} else {
+		ret = _lua_uacb.replace_from(env_L->msg, &param[0], &param[1]);
+	}
 	return app_lua_return_int(L, ret);
 }
 
 /**
  *
  */
-static const luaL_reg _sr_uac_Map [] = {
+static int lua_sr_uac_replace_from(lua_State *L)
+{
+	return lua_sr_uac_replace_x(L, 0);
+}
+
+/**
+ *
+ */
+static int lua_sr_uac_replace_to(lua_State *L)
+{
+	return lua_sr_uac_replace_x(L, 1);
+}
+
+/**
+ *
+ */
+static int lua_sr_uac_req_send(lua_State *L)
+{
+	int ret;
+	sr_lua_env_t *env_L;
+
+	env_L = sr_lua_env_get();
+
+	if (!(_sr_lua_exp_reg_mods & SR_LUA_EXP_MOD_UAC))
+	{
+		LM_WARN("weird:uac function executed but module not registered\n");
+		return app_lua_return_error(L);
+	}
+
+	if (env_L->msg == NULL)
+	{
+		LM_WARN("invalid parameters from Lua env\n");
+		return app_lua_return_error(L);
+	}
+
+	ret = _lua_uacb.req_send();
+
+	return app_lua_return_int(L, ret);
+}
+
+/**
+ *
+ */
+static const luaL_Reg _sr_uac_Map [] = {
 	{"replace_from",lua_sr_uac_replace_from},
+	{"replace_to",lua_sr_uac_replace_to},
+	{"uac_req_send",lua_sr_uac_req_send},
 	{NULL, NULL}
 };
 
@@ -2355,7 +2520,7 @@ static int lua_sr_sanity_check(lua_State *L)
 /**
  *
  */
-static const luaL_reg _sr_sanity_Map [] = {
+static const luaL_Reg _sr_sanity_Map [] = {
 	{"sanity_check",       lua_sr_sanity_check},
 	{NULL, NULL}
 };
@@ -2416,7 +2581,7 @@ static int lua_sr_cfgutils_unlock(lua_State *L)
 /**
  *
  */
-static const luaL_reg _sr_cfgutils_Map [] = {
+static const luaL_Reg _sr_cfgutils_Map [] = {
 	{"lock",      lua_sr_cfgutils_lock},
 	{"unlock",    lua_sr_cfgutils_unlock},
 	{NULL, NULL}
@@ -2450,7 +2615,7 @@ static int lua_sr_tmx_t_suspend(lua_State *L)
 /**
  *
  */
-static const luaL_reg _sr_tmx_Map [] = {
+static const luaL_Reg _sr_tmx_Map [] = {
 	{"t_suspend", lua_sr_tmx_t_suspend},
 	{NULL, NULL}
 };
@@ -2488,7 +2653,7 @@ static int lua_sr_mq_add(lua_State *L)
 /**
  *
  */
-static const luaL_reg _sr_mqueue_Map [] = {
+static const luaL_Reg _sr_mqueue_Map [] = {
 	{"add", lua_sr_mq_add},
 	{NULL, NULL}
 };
@@ -2496,6 +2661,147 @@ static const luaL_reg _sr_mqueue_Map [] = {
 /**
  *
  */
+static int lua_sr_ndb_mongodb_cmd_x(lua_State *L, int ctype)
+{
+	int ret = 0;
+	str param[6];
+
+	if(!(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_NDB_MONGODB))
+	{
+		LM_WARN("weird: ndb_mongodb function executed but module not registered\n");
+		return app_lua_return_error(L);
+	}
+	if(lua_gettop(L)!=5)
+	{
+		LM_WARN("invalid number of parameters from Lua\n");
+		return app_lua_return_error(L);
+	}
+
+	param[0].s = (char *) lua_tostring(L, -5);
+	param[0].len = strlen(param[0].s);
+	param[1].s = (char *) lua_tostring(L, -4);
+	param[1].len = strlen(param[1].s);
+	param[2].s = (char *) lua_tostring(L, -3);
+	param[2].len = strlen(param[2].s);
+	param[3].s = (char *) lua_tostring(L, -2);
+	param[3].len = strlen(param[3].s);
+	param[4].s = (char *) lua_tostring(L, -1);
+	param[4].len = strlen(param[4].s);
+
+	if(ctype==1) {
+		ret = _lua_ndb_mongodbb.cmd_simple(&param[0], &param[1], &param[2], &param[3], &param[4]);
+	} else if(ctype==2) {
+		ret = _lua_ndb_mongodbb.find(&param[0], &param[1], &param[2], &param[3], &param[4]);
+	} else if(ctype==3) {
+		ret = _lua_ndb_mongodbb.find_one(&param[0], &param[1], &param[2], &param[3], &param[4]);
+	} else {
+		ret = _lua_ndb_mongodbb.cmd(&param[0], &param[1], &param[2], &param[3], &param[4]);
+	}
+	return app_lua_return_int(L, ret);
+}
+
+/**
+ *
+ */
+static int lua_sr_ndb_mongodb_cmd(lua_State *L)
+{
+	return lua_sr_ndb_mongodb_cmd_x(L, 0);
+}
+
+/**
+ *
+ */
+static int lua_sr_ndb_mongodb_cmd_simple(lua_State *L)
+{
+	return lua_sr_ndb_mongodb_cmd_x(L, 1);
+}
+
+/**
+ *
+ */
+static int lua_sr_ndb_mongodb_find(lua_State *L)
+{
+	return lua_sr_ndb_mongodb_cmd_x(L, 2);
+}
+
+/**
+ *
+ */
+static int lua_sr_ndb_mongodb_find_one(lua_State *L)
+{
+	return lua_sr_ndb_mongodb_cmd_x(L, 3);
+}
+
+/**
+ *
+ */
+static int lua_sr_ndb_mongodb_next_reply(lua_State *L)
+{
+	int ret = 0;
+	str param[1];
+
+	if(!(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_NDB_MONGODB))
+	{
+		LM_WARN("weird: ndb_mongodb function executed but module not registered\n");
+		return app_lua_return_error(L);
+	}
+	if(lua_gettop(L)!=1)
+	{
+		LM_WARN("invalid number of parameters from Lua\n");
+		return app_lua_return_error(L);
+	}
+
+	param[0].s = (char *) lua_tostring(L, -1);
+	param[0].len = strlen(param[0].s);
+
+	ret = _lua_ndb_mongodbb.next_reply(&param[0]);
+
+	return app_lua_return_int(L, ret);
+}
+
+/**
+ *
+ */
+static int lua_sr_ndb_mongodb_free_reply(lua_State *L)
+{
+	int ret = 0;
+	str param[1];
+
+	if(!(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_NDB_MONGODB))
+	{
+		LM_WARN("weird: ndb_mongodb function executed but module not registered\n");
+		return app_lua_return_error(L);
+	}
+	if(lua_gettop(L)!=1)
+	{
+		LM_WARN("invalid number of parameters from Lua\n");
+		return app_lua_return_error(L);
+	}
+
+	param[0].s = (char *) lua_tostring(L, -1);
+	param[0].len = strlen(param[0].s);
+
+	ret = _lua_ndb_mongodbb.free_reply(&param[0]);
+
+	return app_lua_return_int(L, ret);
+}
+
+/**
+ *
+ */
+static const luaL_Reg _sr_ndb_mongodb_Map [] = {
+	{"cmd", lua_sr_ndb_mongodb_cmd},
+	{"cmd_simple", lua_sr_ndb_mongodb_cmd_simple},
+	{"find", lua_sr_ndb_mongodb_find},
+	{"find_one", lua_sr_ndb_mongodb_find_one},
+	{"next_reply", lua_sr_ndb_mongodb_next_reply},
+	{"free_reply", lua_sr_ndb_mongodb_free_reply},
+	{NULL, NULL}
+};
+
+/**
+ *
+ */
 int lua_sr_exp_init_mod(void)
 {
 	if(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_SL)
@@ -2744,6 +3050,17 @@ int lua_sr_exp_init_mod(void)
 		}
 		LM_DBG("loaded mqueue api\n");
 	}
+	if(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_NDB_MONGODB)
+	{
+		/* bind the NDB_MONGODB API */
+		if (ndb_mongodb_load_api(&_lua_ndb_mongodbb) < 0)
+		{
+			LM_ERR("cannot bind to NDB_MONGODB API\n");
+			return -1;
+		}
+		LM_DBG("loaded ndb_mongodb api\n");
+	}
+
 	return 0;
 }
 
@@ -2829,6 +3146,9 @@ int lua_sr_exp_register_mod(char *mname)
 	} else 	if(len==6 && strcmp(mname, "mqueue")==0) {
 		_sr_lua_exp_reg_mods |= SR_LUA_EXP_MOD_MQUEUE;
 		return 0;
+	} else 	if(len==11 && strcmp(mname, "ndb_mongodb")==0) {
+		_sr_lua_exp_reg_mods |= SR_LUA_EXP_MOD_NDB_MONGODB;
+		return 0;
 	}
 
 	return -1;
@@ -2887,5 +3207,7 @@ void lua_sr_exp_openlibs(lua_State *L)
 		luaL_openlib(L, "sr.tmx", _sr_tmx_Map,                0);
 	if(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_MQUEUE)
 		luaL_openlib(L, "sr.mq", _sr_mqueue_Map,              0);
+	if(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_NDB_MONGODB)
+		luaL_openlib(L, "sr.ndb_mongodb", _sr_ndb_mongodb_Map, 0);
 }
 
diff --git a/modules/app_lua/app_lua_sr.c b/modules/app_lua/app_lua_sr.c
index b75b724..e529421 100644
--- a/modules/app_lua/app_lua_sr.c
+++ b/modules/app_lua/app_lua_sr.c
@@ -687,7 +687,7 @@ static int lua_sr_resetdsturi (lua_State *L)
 /**
  *
  */
-static const luaL_reg _sr_core_Map [] = {
+static const luaL_Reg _sr_core_Map [] = {
 	{"probe",        lua_sr_probe},
 	{"dbg",          lua_sr_dbg},
 	{"err",          lua_sr_err},
@@ -864,7 +864,7 @@ static int lua_sr_hdr_append_to_reply (lua_State *L)
 /**
  *
  */
-static const luaL_reg _sr_hdr_Map [] = {
+static const luaL_Reg _sr_hdr_Map [] = {
 	{"append", lua_sr_hdr_append},
 	{"remove", lua_sr_hdr_remove},
 	{"insert", lua_sr_hdr_insert},
@@ -1127,7 +1127,7 @@ static int lua_sr_pv_is_null (lua_State *L)
 /**
  *
  */
-static const luaL_reg _sr_pv_Map [] = {
+static const luaL_Reg _sr_pv_Map [] = {
 	{"get",      lua_sr_pv_get},
 	{"seti",     lua_sr_pv_seti},
 	{"sets",     lua_sr_pv_sets},
@@ -1404,7 +1404,7 @@ static int lua_sr_xavp_get_keys (lua_State *L)
 /**
  *
  */
-static const luaL_reg _sr_xavp_Map [] = {
+static const luaL_Reg _sr_xavp_Map [] = {
 	{"get", lua_sr_xavp_get},
 	{"get_keys",  lua_sr_xavp_get_keys},
 	{NULL, NULL}
diff --git a/modules/app_perl/Makefile b/modules/app_perl/Makefile
index f1f7b94..eb23db5 100644
--- a/modules/app_perl/Makefile
+++ b/modules/app_perl/Makefile
@@ -1,5 +1,3 @@
-# $Id$
-#
 # perl module makefile
 #
 # 
diff --git a/modules/app_python/Makefile b/modules/app_python/Makefile
index 88f2636..d1854c1 100644
--- a/modules/app_python/Makefile
+++ b/modules/app_python/Makefile
@@ -1,5 +1,3 @@
-# $Id$
-#
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
 
diff --git a/modules/app_python/mod_Core.c b/modules/app_python/mod_Core.c
index d256cca..cbd0f63 100644
--- a/modules/app_python/mod_Core.c
+++ b/modules/app_python/mod_Core.c
@@ -1,6 +1,4 @@
 /**
- * $Id$
- *
  * Copyright (C) 2012 Konstantin Mosesov
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/app_python/mod_Core.h b/modules/app_python/mod_Core.h
index 6ad312c..4ed95ba 100644
--- a/modules/app_python/mod_Core.h
+++ b/modules/app_python/mod_Core.h
@@ -1,6 +1,4 @@
 /**
- * $Id$
- *
  * Copyright (C) 2012 Konstantin Mosesov
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/app_python/mod_Logger.c b/modules/app_python/mod_Logger.c
index 707440b..0d94216 100644
--- a/modules/app_python/mod_Logger.c
+++ b/modules/app_python/mod_Logger.c
@@ -1,6 +1,4 @@
 /**
- * $Id$
- *
  * Copyright (C) 2012 Konstantin Mosesov
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/app_python/mod_Logger.h b/modules/app_python/mod_Logger.h
index 8829c2b..9bdd09f 100644
--- a/modules/app_python/mod_Logger.h
+++ b/modules/app_python/mod_Logger.h
@@ -1,6 +1,4 @@
 /**
- * $Id$
- *
  * Copyright (C) 2012 Konstantin Mosesov
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/app_python/mod_Ranks.c b/modules/app_python/mod_Ranks.c
index 7688ad4..128390c 100644
--- a/modules/app_python/mod_Ranks.c
+++ b/modules/app_python/mod_Ranks.c
@@ -1,6 +1,4 @@
 /**
- * $Id$
- *
  * Copyright (C) 2012 Konstantin Mosesov
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/app_python/mod_Ranks.h b/modules/app_python/mod_Ranks.h
index 96fb544..1044b60 100644
--- a/modules/app_python/mod_Ranks.h
+++ b/modules/app_python/mod_Ranks.h
@@ -1,6 +1,4 @@
 /**
- * $Id$
- *
  * Copyright (C) 2012 Konstantin Mosesov
  *
  * This file is part of Kamailio, a free SIP server.
@@ -10,7 +8,6 @@
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- *
  * This file is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
diff --git a/modules/app_python/mod_Router.c b/modules/app_python/mod_Router.c
index 9cd008c..c6da323 100644
--- a/modules/app_python/mod_Router.c
+++ b/modules/app_python/mod_Router.c
@@ -1,6 +1,4 @@
 /**
- * $Id$
- *
  * Copyright (C) 2012 Konstantin Mosesov
  *
  * This file is part of Kamailio, a free SIP server.
@@ -10,7 +8,6 @@
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- *
  * This file is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
diff --git a/modules/app_python/mod_Router.h b/modules/app_python/mod_Router.h
index d932a42..b6e3e7d 100644
--- a/modules/app_python/mod_Router.h
+++ b/modules/app_python/mod_Router.h
@@ -1,6 +1,4 @@
 /**
- * $Id$
- *
  * Copyright (C) 2012 Konstantin Mosesov
  *
  * This file is part of Kamailio, a free SIP server.
@@ -10,7 +8,6 @@
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- *
  * This file is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
diff --git a/modules/app_python/python_exec.c b/modules/app_python/python_exec.c
index eace0f8..2127b3c 100644
--- a/modules/app_python/python_exec.c
+++ b/modules/app_python/python_exec.c
@@ -1,15 +1,14 @@
-/* $Id$
- *
+/*
  * Copyright (C) 2009 Sippy Software, Inc., http://www.sippysoft.com
  *
- * This file is part of SIP-Router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-Router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-Router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/modules/app_python/python_exec.h b/modules/app_python/python_exec.h
index 9c43663..f9b32f3 100644
--- a/modules/app_python/python_exec.h
+++ b/modules/app_python/python_exec.h
@@ -1,15 +1,14 @@
-/* $Id$
- *
+/*
  * Copyright (C) 2009 Sippy Software, Inc., http://www.sippysoft.com
  *
- * This file is part of SIP-Router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-Router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-Router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/modules/app_python/python_iface.c b/modules/app_python/python_iface.c
index 4993757..92699c2 100644
--- a/modules/app_python/python_iface.c
+++ b/modules/app_python/python_iface.c
@@ -1,15 +1,14 @@
-/* $Id$
- *
+/* 
  * Copyright (C) 2009 Sippy Software, Inc., http://www.sippysoft.com
  *
- * This file is part of SIP-Router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-Router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-Router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -20,12 +19,6 @@
  *
 */
 
-/*
- * Changed
- *	2012-12-10 ez: Moved a part of functional to mod_Core.c, mod_Logger.c, mod_Ranks.c, mod_Router.c
- *
-*/
-
 // Python includes
 #include <Python.h>
 
diff --git a/modules/app_python/python_iface.h b/modules/app_python/python_iface.h
index b01b115..a594b69 100644
--- a/modules/app_python/python_iface.h
+++ b/modules/app_python/python_iface.h
@@ -1,15 +1,14 @@
-/* $Id$
- *
+/*
  * Copyright (C) 2009 Sippy Software, Inc., http://www.sippysoft.com
  *
- * This file is part of SIP-Router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-Router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-Router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/modules/app_python/python_mod.c b/modules/app_python/python_mod.c
index 74aa1ef..f297069 100644
--- a/modules/app_python/python_mod.c
+++ b/modules/app_python/python_mod.c
@@ -1,15 +1,14 @@
-/* $Id$
- *
+/*
  * Copyright (C) 2009 Sippy Software, Inc., http://www.sippysoft.com
  *
- * This file is part of SIP-Router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-Router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-Router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/modules/app_python/python_mod.h b/modules/app_python/python_mod.h
index e6b9b80..80590df 100644
--- a/modules/app_python/python_mod.h
+++ b/modules/app_python/python_mod.h
@@ -1,15 +1,14 @@
-/* $Id$
- *
+/* 
  * Copyright (C) 2009 Sippy Software, Inc., http://www.sippysoft.com
  *
- * This file is part of SIPRouter, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-Router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-Router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/modules/app_python/python_msgobj.c b/modules/app_python/python_msgobj.c
index 2c878d0..125a0b4 100644
--- a/modules/app_python/python_msgobj.c
+++ b/modules/app_python/python_msgobj.c
@@ -1,15 +1,14 @@
-/* $Id$
- *
+/* 
  * Copyright (C) 2009 Sippy Software, Inc., http://www.sippysoft.com
  *
- * This file is part of SIP-Router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-Router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-Router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/modules/app_python/python_msgobj.h b/modules/app_python/python_msgobj.h
index c4c556f..825025f 100644
--- a/modules/app_python/python_msgobj.h
+++ b/modules/app_python/python_msgobj.h
@@ -1,15 +1,14 @@
-/* $Id$
- *
+/* 
  * Copyright (C) 2009 Sippy Software, Inc., http://www.sippysoft.com
  *
- * This file is part of SIP-Router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-Router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-Router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/modules/app_python/python_support.c b/modules/app_python/python_support.c
index a095aff..6ec6fe2 100644
--- a/modules/app_python/python_support.c
+++ b/modules/app_python/python_support.c
@@ -1,15 +1,14 @@
-/* $Id$
- *
+/* 
  * Copyright (C) 2009 Sippy Software, Inc., http://www.sippysoft.com
  *
- * This file is part of SIP-Router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-Router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-Router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/modules/app_python/python_support.h b/modules/app_python/python_support.h
index b83a3aa..032340d 100644
--- a/modules/app_python/python_support.h
+++ b/modules/app_python/python_support.h
@@ -1,15 +1,14 @@
-/* $Id$
- *
+/* 
  * Copyright (C) 2009 Sippy Software, Inc., http://www.sippysoft.com
  *
- * This file is part of SIP-Router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-Router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-Router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/modules/async/Makefile b/modules/async/Makefile
index d2acbee..8d910d4 100644
--- a/modules/async/Makefile
+++ b/modules/async/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # WARNING: do not run this directly, it should be run by the master Makefile
 
diff --git a/modules/async/async_mod.c b/modules/async/async_mod.c
index 5314439..8cd6fac 100644
--- a/modules/async/async_mod.c
+++ b/modules/async/async_mod.c
@@ -1,6 +1,4 @@
 /**
- * $Id$
- *
  * Copyright (C) 2011 Daniel-Constantin Mierla (asipto.com)
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/async/async_sleep.c b/modules/async/async_sleep.c
index f353de1..8ed62e6 100644
--- a/modules/async/async_sleep.c
+++ b/modules/async/async_sleep.c
@@ -1,6 +1,4 @@
 /**
- * $Id$
- *
  * Copyright (C) 2011 Daniel-Constantin Mierla (asipto.com)
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/async/async_sleep.h b/modules/async/async_sleep.h
index b08f98f..0eb2fd7 100644
--- a/modules/async/async_sleep.h
+++ b/modules/async/async_sleep.h
@@ -1,6 +1,4 @@
 /**
- * $Id$
- *
  * Copyright (C) 2011 Daniel-Constantin Mierla (asipto.com)
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/auth/Makefile b/modules/auth/Makefile
index fcf4b32..275d043 100644
--- a/modules/auth/Makefile
+++ b/modules/auth/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # auth example module makefile
 #
diff --git a/modules/auth/api.c b/modules/auth/api.c
index b54321e..3407346 100644
--- a/modules/auth/api.c
+++ b/modules/auth/api.c
@@ -1,36 +1,24 @@
 /*
- * $Id$
- *
  * Digest Authentication Module
- *
+ * 
  * Copyright (C) 2001-2003 FhG Fokus
- *
- * This file is part of ser, a free SIP server.
- *
- * ser is free software; you can redistribute it and/or modify
+ * 
+ * This file is part of Kamailio, a free SIP server.
+ * 
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
- *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * 
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
+ * 
  * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
+ * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- */
-/*
- * History:
- * --------
- *  ...
- * 2008-07-01 set c->stale in auth_check_hdr_md5 (andrei)
+ *
  */
 
 #include <string.h>
diff --git a/modules/auth/api.h b/modules/auth/api.h
index dadf3b5..99bf2c2 100644
--- a/modules/auth/api.h
+++ b/modules/auth/api.h
@@ -1,30 +1,24 @@
 /*
- * $Id$
- *
  * Digest Authentication Module
- *
+ * 
  * Copyright (C) 2001-2003 FhG Fokus
- *
- * This file is part of ser, a free SIP server.
- *
- * ser is free software; you can redistribute it and/or modify
+ * 
+ * This file is part of Kamailio, a free SIP server.
+ * 
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
- *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * 
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
+ * 
  * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
+ * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
  */
 
 #ifndef API_H
diff --git a/modules/auth/auth_mod.c b/modules/auth/auth_mod.c
index e08048a..fe57a89 100644
--- a/modules/auth/auth_mod.c
+++ b/modules/auth/auth_mod.c
@@ -1,41 +1,24 @@
 /*
- * $Id$
- *
  * Digest Authentication Module
- *
+ * 
  * Copyright (C) 2001-2003 FhG Fokus
- *
- * This file is part of ser, a free SIP server.
- *
- * ser is free software; you can redistribute it and/or modify
+ * 
+ * This file is part of Kamailio, a free SIP server.
+ * 
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
- *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * 
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
+ * 
+ * You should have received a copy of the GNU General Public License 
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2003-02-26 checks and group moved to separate modules (janakj)
- * 2003-03-10 New module interface (janakj)
- * 2003-03-16 flags export parameter added (janakj)
- * 2003-03-19 all mallocs/frees replaced w/ pkg_malloc/pkg_free (andrei)
- * 2003-04-28 rpid contributed by Juha Heinanen added (janakj)
- * 2007-10-19 auth extra checks: longer nonces that include selected message
- *            parts to protect against various reply attacks without keeping
- *            state (andrei)
  */
 
 
diff --git a/modules/auth/auth_mod.h b/modules/auth/auth_mod.h
index 2df332e..47e666b 100644
--- a/modules/auth/auth_mod.h
+++ b/modules/auth/auth_mod.h
@@ -1,23 +1,16 @@
 /*
- * $Id$
- *
  * Digest Authentication Module
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -26,12 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2003-04-28 rpid contributed by Juha Heinanen added (janakj)
- * 2007-10-19 auth extra checks: longer nonces that include selected message
- *            parts to protect against various reply attacks without keeping
- *            state (andrei)
  */
 
 #ifndef AUTH_MOD_H
diff --git a/modules/auth/challenge.c b/modules/auth/challenge.c
index a24a733..6d537d2 100644
--- a/modules/auth/challenge.c
+++ b/modules/auth/challenge.c
@@ -1,40 +1,24 @@
 /*
- * $Id$
- *
- * Challenge related functions
- *
+ * Digest Authentication Module
+ * 
  * Copyright (C) 2001-2003 FhG Fokus
- *
- * This file is part of ser, a free SIP server.
- *
- * ser is free software; you can redistribute it and/or modify
+ * 
+ * This file is part of Kamailio, a free SIP server.
+ * 
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
- *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * 
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
+ * 
  * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
+ * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2003-01-20 snprintf in build_auth_hf replaced with memcpy to avoid
- *            possible issues with too small buffer
- * 2003-01-26 consume_credentials no longer complains about ACK/CANCEL(jiri)
- * 2007-10-19 auth extra checks: longer nonces that include selected message
- *            parts to protect against various reply attacks without keeping
- *            state (andrei)
- * 2008-07-08 nonce-count (nc) support (andrei)
  */
 
 #include "../../data_lump.h"
diff --git a/modules/auth/challenge.h b/modules/auth/challenge.h
index 7b32719..2645642 100644
--- a/modules/auth/challenge.h
+++ b/modules/auth/challenge.h
@@ -1,30 +1,24 @@
 /*
- * $Id$
- *
- * Challenge related functions
- *
+ * Digest Authentication Module
+ * 
  * Copyright (C) 2001-2003 FhG Fokus
- *
- * This file is part of ser, a free SIP server.
- *
- * ser is free software; you can redistribute it and/or modify
+ * 
+ * This file is part of Kamailio, a free SIP server.
+ * 
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
- *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * 
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
+ * 
  * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
+ * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
  */
 
 
diff --git a/modules/auth/nc.c b/modules/auth/nc.c
index 2d46803..632dea4 100644
--- a/modules/auth/nc.c
+++ b/modules/auth/nc.c
@@ -1,30 +1,24 @@
 /*
- * $Id$
- *
- * nonce-count (nc) tracking
- *
+ * Digest Authentication Module
+ * 
  * Copyright (C) 2008 iptelorg GmbH
- *
- * This file is part of ser, a free SIP server.
- *
- * ser is free software; you can redistribute it and/or modify
+ * 
+ * This file is part of Kamailio, a free SIP server.
+ * 
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
- *
- * ser is distributed in the hope that it will be useful,
+ * 
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
+ * 
  * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
+ * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- */
-/*
- * History:
- * --------
- * 2008-07-04  initial version (andrei)
+ *
  */
 
 int nc_enabled=0;
diff --git a/modules/auth/nc.h b/modules/auth/nc.h
index cd85510..721892e 100644
--- a/modules/auth/nc.h
+++ b/modules/auth/nc.h
@@ -1,36 +1,31 @@
 /*
- * $Id$
- *
+ * Digest Authentication Module
  * nonce-count (nc) tracking
  *
  * Copyright (C) 2008 iptelorg GmbH
- *
- * This file is part of ser, a free SIP server.
- *
- * ser is free software; you can redistribute it and/or modify
+ * 
+ * This file is part of Kamailio, a free SIP server.
+ * 
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
- *
- * ser is distributed in the hope that it will be useful,
+ * 
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
+ * 
  * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
+ * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
  */
+
 /*
  * Defines: 
  *  USE_NC   - if not defined no NC specific code will be compiled
  */
-/*
- * History:
- * --------
- * 2008-07-04  initial version (andrei)
- */
-
 
 #ifndef _nc_h
 #define _nc_h
diff --git a/modules/auth/nid.c b/modules/auth/nid.c
index 9fe7668..72dafa3 100644
--- a/modules/auth/nid.c
+++ b/modules/auth/nid.c
@@ -1,37 +1,33 @@
 /*
- * $Id$
- *
+ * Digest Authentication Module
  * nonce id and pool management (stuff common to nonce-count and one
  * time nonces)
  *
  * Copyright (C) 2008 iptelorg GmbH
- *
- * This file is part of ser, a free SIP server.
- *
- * ser is free software; you can redistribute it and/or modify
+ * 
+ * This file is part of Kamailio, a free SIP server.
+ * 
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
- *
- * ser is distributed in the hope that it will be useful,
+ * 
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
+ * 
  * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
+ * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
  */
+
 /*
  * Defines: 
  *  USE_NC, USE_OT_NONCE  - if neither of them defined no code will be 
  *                          compiled
  */
-/*
- * History:
- * --------
- * 2008-07-08  initial version (andrei)
- */
 
 unsigned int nid_pool_no; /* number of index pools, 2^k */
 
diff --git a/modules/auth/nid.h b/modules/auth/nid.h
index 36be98d..d32718f 100644
--- a/modules/auth/nid.h
+++ b/modules/auth/nid.h
@@ -1,37 +1,33 @@
 /*
- * $Id$
- *
+ * Digest Authentication Module
  * nonce id and pool management (stuff common to nonce-count and one
  * time nonces)
  *
  * Copyright (C) 2008 iptelorg GmbH
- *
- * This file is part of ser, a free SIP server.
- *
- * ser is free software; you can redistribute it and/or modify
+ * 
+ * This file is part of Kamailio, a free SIP server.
+ * 
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
- *
- * ser is distributed in the hope that it will be useful,
+ * 
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
+ * 
  * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
+ * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
  */
+
 /*
  * Defines: 
  *  USE_NC, USE_OT_NONCE  - if neither of them defined no code will be 
  *                          compiled
  */
-/*
- * History:
- * --------
- * 2008-07-08  initial version (andrei)
- */
 
 #ifndef _nid_h
 #define _nid_h
diff --git a/modules/auth/nonce.c b/modules/auth/nonce.c
index 6a06956..95b967e 100644
--- a/modules/auth/nonce.c
+++ b/modules/auth/nonce.c
@@ -1,43 +1,26 @@
 /*
- * $Id$
- *
+ * Digest Authentication Module
  * Nonce related functions
- *
+ * 
  * Copyright (C) 2001-2003 FhG Fokus
- *
- * This file is part of ser, a free SIP server.
- *
- * ser is free software; you can redistribute it and/or modify
+ * 
+ * This file is part of Kamailio, a free SIP server.
+ * 
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
- *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * 
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
+ * 
  * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
+ * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
  */
-/*
- * History:
- * --------
- *            ...
- * 2007-10-19 auth extra checks: longer nonces that include selected message
- *            parts to protect against various reply attacks without keeping
- *            state (andrei)
- * 2008-07-01 switched to base64 for nonces; check staleness in check_nonce
- *            (andrei)
- * 2008-07-04 nonce-count support (andrei)
- */
-
 
 #include <time.h>
 #include <string.h>
diff --git a/modules/auth/nonce.h b/modules/auth/nonce.h
index 88a544f..53a225e 100644
--- a/modules/auth/nonce.h
+++ b/modules/auth/nonce.h
@@ -1,33 +1,27 @@
 /*
- * $Id$
- *
+ * Digest Authentication Module
  * Nonce related functions
- *
+ * 
  * Copyright (C) 2001-2003 FhG Fokus
- *
- * This file is part of ser, a free SIP server.
- *
- * ser is free software; you can redistribute it and/or modify
+ * 
+ * This file is part of Kamailio, a free SIP server.
+ * 
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
- *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * 
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
+ * 
  * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
+ * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
  */
 
-
 #ifndef NONCE_H
 #define NONCE_H
 
diff --git a/modules/auth/ot_nonce.c b/modules/auth/ot_nonce.c
index 887c24c..09abbcd 100644
--- a/modules/auth/ot_nonce.c
+++ b/modules/auth/ot_nonce.c
@@ -1,30 +1,26 @@
 /*
- * $Id$
- *
+ * Digest Authentication Module
+ * 
  * one-time nonce support
  *
  * Copyright (C) 2008 iptelorg GmbH
- *
- * This file is part of ser, a free SIP server.
- *
- * ser is free software; you can redistribute it and/or modify
+ * 
+ * This file is part of Kamailio, a free SIP server.
+ * 
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
- *
- * ser is distributed in the hope that it will be useful,
+ * 
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
+ * 
  * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
+ * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- */
-/*
- * History:
- * --------
- * 2008-07-10  initial version (andrei)
+ *
  */
 
 int otn_enabled=0;
diff --git a/modules/auth/ot_nonce.h b/modules/auth/ot_nonce.h
index c884496..28d66f0 100644
--- a/modules/auth/ot_nonce.h
+++ b/modules/auth/ot_nonce.h
@@ -1,25 +1,26 @@
 /*
- * $Id$
- *
+ * Digest Authentication Module
+ * 
  * one-time nonce support
  *
  * Copyright (C) 2008 iptelorg GmbH
- *
- * This file is part of ser, a free SIP server.
- *
- * ser is free software; you can redistribute it and/or modify
+ * 
+ * This file is part of Kamailio, a free SIP server.
+ * 
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
- *
- * ser is distributed in the hope that it will be useful,
+ * 
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
+ * 
  * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
+ * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
  */
 /*
  * Defines: 
@@ -28,11 +29,6 @@
  *  OTN_CELL_T_LONG - uses unsigned long instead os unsigned int for the
  *                    array cells
  */
-/*
- * History:
- * --------
- * 2008-07-10  initial version (andrei)
- */
 
 
 #ifndef _ot_nonce_h
diff --git a/modules/auth/rfc2617.c b/modules/auth/rfc2617.c
index 29983d1..78ee2eb 100644
--- a/modules/auth/rfc2617.c
+++ b/modules/auth/rfc2617.c
@@ -1,30 +1,25 @@
 /*
- * $Id$
- *
+ * Digest Authentication Module
  * Digest response calculation as per RFC2617
- *
+ * 
  * Copyright (C) 2001-2003 FhG Fokus
- *
- * This file is part of ser, a free SIP server.
- *
- * ser is free software; you can redistribute it and/or modify
+ * 
+ * This file is part of Kamailio, a free SIP server.
+ * 
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
- *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * 
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
+ * 
  * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
+ * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
  */
 
 
diff --git a/modules/auth/rfc2617.h b/modules/auth/rfc2617.h
index 3160449..9bb1909 100644
--- a/modules/auth/rfc2617.h
+++ b/modules/auth/rfc2617.h
@@ -1,30 +1,25 @@
 /*
- * $Id$
- *
+ * Digest Authentication Module
  * Digest response calculation as per RFC2617
- *
+ * 
  * Copyright (C) 2001-2003 FhG Fokus
- *
- * This file is part of ser, a free SIP server.
- *
- * ser is free software; you can redistribute it and/or modify
+ * 
+ * This file is part of Kamailio, a free SIP server.
+ * 
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
- *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * 
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
+ * 
  * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
+ * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
  */
 
 
diff --git a/modules/auth_db/Makefile b/modules/auth_db/Makefile
index 1f8d9b9..6ec6584 100644
--- a/modules/auth_db/Makefile
+++ b/modules/auth_db/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # Digest Authentication - Database support
 #
diff --git a/modules/auth_db/api.h b/modules/auth_db/api.h
index 9e18c55..5e479b5 100644
--- a/modules/auth_db/api.h
+++ b/modules/auth_db/api.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Digest Authentication - Database support
  *
  * Copyright (C) 2001-2003 FhG Fokus
diff --git a/modules/auth_db/auth_db_mod.c b/modules/auth_db/auth_db_mod.c
new file mode 100644
index 0000000..abd9c29
--- /dev/null
+++ b/modules/auth_db/auth_db_mod.c
@@ -0,0 +1,422 @@
+/* 
+ * Digest Authentication Module
+ *
+ * Copyright (C) 2001-2003 FhG Fokus
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "../../sr_module.h"
+#include "../../lib/srdb1/db.h"
+#include "../../dprint.h"
+#include "../../error.h"
+#include "../../mod_fix.h"
+#include "../../trim.h"
+#include "../../mem/mem.h"
+#include "../../parser/parse_uri.h"
+#include "../../modules/auth/api.h"
+#include "authorize.h"
+
+MODULE_VERSION
+
+#define TABLE_VERSION 6
+
+/*
+ * Module destroy function prototype
+ */
+static void destroy(void);
+
+
+/*
+ * Module child-init function prototype
+ */
+static int child_init(int rank);
+
+
+/*
+ * Module initialization function prototype
+ */
+static int mod_init(void);
+
+
+static int w_is_subscriber(sip_msg_t *msg, char *_uri, char* _table,
+		char *_flags);
+static int auth_fixup(void** param, int param_no);
+static int auth_check_fixup(void** param, int param_no);
+int parse_aaa_pvs(char *definition, pv_elem_t **pv_def, int *cnt);
+
+#define USER_COL "username"
+#define DOMAIN_COL "domain"
+#define PASS_COL "ha1"
+#define PASS_COL_2 "ha1b"
+
+/*
+ * Module parameter variables
+ */
+static str db_url           = str_init(DEFAULT_RODB_URL);
+str user_column             = str_init(USER_COL);
+str domain_column           = str_init(DOMAIN_COL);
+str pass_column             = str_init(PASS_COL);
+str pass_column_2           = str_init(PASS_COL_2);
+
+static int version_table_check = 1;
+
+int calc_ha1                = 0;
+int use_domain              = 0; /* Use also domain when looking up in table */
+
+db1_con_t* auth_db_handle    = 0; /* database connection handle */
+db_func_t auth_dbf;
+auth_api_s_t auth_api;
+
+char *credentials_list      = 0;
+pv_elem_t *credentials      = 0; /* Parsed list of credentials to load */
+int credentials_n           = 0; /* Number of credentials in the list */
+
+/*
+ * Exported functions
+ */
+static cmd_export_t cmds[] = {
+	{"www_authorize",      (cmd_function)www_authenticate,   2, auth_fixup, 0,
+		REQUEST_ROUTE},
+	{"www_authenticate",   (cmd_function)www_authenticate,   2, auth_fixup, 0,
+		REQUEST_ROUTE},
+	{"www_authenticate",   (cmd_function)www_authenticate2,  3, auth_fixup, 0,
+REQUEST_ROUTE},
+	{"proxy_authorize",    (cmd_function)proxy_authenticate, 2, auth_fixup, 0,
+		REQUEST_ROUTE},
+	{"proxy_authenticate", (cmd_function)proxy_authenticate, 2, auth_fixup, 0,
+		REQUEST_ROUTE},
+	{"auth_check",         (cmd_function)auth_check,         3, auth_check_fixup, 0,
+		REQUEST_ROUTE},
+	{"is_subscriber",      (cmd_function)w_is_subscriber,    3, auth_check_fixup, 0,
+		ANY_ROUTE},
+	{"bind_auth_db",       (cmd_function)bind_auth_db,       0, 0, 0,
+		0},
+	{0, 0, 0, 0, 0, 0}
+};
+
+
+/*
+ * Exported parameters
+ */
+static param_export_t params[] = {
+	{"db_url",            PARAM_STR, &db_url            },
+	{"user_column",       PARAM_STR, &user_column       },
+	{"domain_column",     PARAM_STR, &domain_column     },
+	{"password_column",   PARAM_STR, &pass_column       },
+	{"password_column_2", PARAM_STR, &pass_column_2     },
+	{"calculate_ha1",     INT_PARAM, &calc_ha1            },
+	{"use_domain",        INT_PARAM, &use_domain          },
+	{"load_credentials",  PARAM_STRING, &credentials_list    },
+	{"version_table",     INT_PARAM, &version_table_check },
+	{0, 0, 0}
+};
+
+
+/*
+ * Module interface
+ */
+struct module_exports exports = {
+	"auth_db", 
+	DEFAULT_DLFLAGS, /* dlopen flags */
+	cmds,       /* Exported functions */
+	params,     /* Exported parameters */
+	0,          /* exported statistics */
+	0,          /* exported MI functions */
+	0,          /* exported pseudo-variables */
+	0,          /* extra processes */
+	mod_init,   /* module initialization function */
+	0,          /* response function */
+	destroy,    /* destroy function */
+	child_init  /* child initialization function */
+};
+
+
+static int child_init(int rank)
+{
+	if (rank==PROC_INIT || rank==PROC_MAIN || rank==PROC_TCP_MAIN)
+		return 0; /* do nothing for the main process */
+	
+	auth_db_handle = auth_dbf.init(&db_url);
+	if (auth_db_handle == 0){
+		LM_ERR("unable to connect to the database\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+
+static int mod_init(void)
+{
+	bind_auth_s_t bind_auth;
+
+	/* Find a database module */
+	if (db_bind_mod(&db_url, &auth_dbf) < 0){
+		LM_ERR("unable to bind to a database driver\n");
+		return -1;
+	}
+
+	/* bind to auth module and import the API */
+	bind_auth = (bind_auth_s_t)find_export("bind_auth_s", 0, 0);
+	if (!bind_auth) {
+		LM_ERR("unable to find bind_auth function. Check if you load"
+				" the auth module.\n");
+		return -2;
+	}
+
+	if (bind_auth(&auth_api) < 0) {
+		LM_ERR("unable to bind auth module\n");
+		return -3;
+	}
+
+	/* process additional list of credentials */
+	if (parse_aaa_pvs(credentials_list, &credentials, &credentials_n) != 0) {
+		LM_ERR("failed to parse credentials\n");
+		return -5;
+	}
+
+	return 0;
+}
+
+
+static void destroy(void)
+{
+	if (auth_db_handle) {
+		auth_dbf.close(auth_db_handle);
+		auth_db_handle = 0;
+	}
+	if (credentials) {
+		pv_elem_free_all(credentials);
+		credentials = 0;
+		credentials_n = 0;
+	}
+}
+
+
+/**
+ * check if the subscriber identified by _uri has a valid record in
+ * database table _table
+ */
+static int w_is_subscriber(sip_msg_t *msg, char *_uri, char* _table,
+		char *_flags)
+{
+	str suri;
+	str stable;
+	int iflags;
+	int ret;
+	sip_uri_t puri;
+
+	if(msg==NULL || _uri==NULL || _table==NULL || _flags==NULL) {
+		LM_ERR("invalid parameters\n");
+		return AUTH_ERROR;
+	}
+
+	if (get_str_fparam(&suri, msg, (fparam_t*)_uri) < 0) {
+		LM_ERR("failed to get uri value\n");
+		return -1;
+	}
+
+	if (suri.len==0) {
+		LM_ERR("invalid uri parameter - empty value\n");
+		return -1;
+	}
+	if(parse_uri(suri.s, suri.len, &puri)<0){
+		LM_ERR("invalid uri parameter format\n");
+		return -1;
+	}
+
+	if (get_str_fparam(&stable, msg, (fparam_t*)_table) < 0) {
+		LM_ERR("failed to get table value\n");
+		return -1;
+	}
+
+	if (stable.len==0) {
+		LM_ERR("invalid table parameter - empty value\n");
+		return -1;
+	}
+
+	if(fixup_get_ivalue(msg, (gparam_p)_flags, &iflags)!=0)
+	{
+		LM_ERR("invalid flags parameter\n");
+		return -1;
+	}
+
+	LM_DBG("uri [%.*s] table [%.*s] flags [%d]\n", suri.len, suri.s,
+			stable.len,  stable.s, iflags);
+	ret = fetch_credentials(msg, &puri.user,
+				(iflags&AUTH_DB_SUBS_USE_DOMAIN)?&puri.host:NULL,
+				&stable, iflags);
+
+	if(ret>=0)
+		return 1;
+	return ret;
+}
+
+/*
+ * Convert the char* parameters
+ */
+static int auth_fixup(void** param, int param_no)
+{
+	db1_con_t* dbh = NULL;
+	str name;
+
+	if(strlen((char*)*param)<=0) {
+		LM_ERR("empty parameter %d not allowed\n", param_no);
+		return -1;
+	}
+
+	if (param_no == 1 || param_no == 3) {
+		return fixup_var_str_12(param, 1);
+	} else if (param_no == 2) {
+		name.s = (char*)*param;
+		name.len = strlen(name.s);
+
+		dbh = auth_dbf.init(&db_url);
+		if (!dbh) {
+			LM_ERR("unable to open database connection\n");
+			return -1;
+		}
+		if(version_table_check!=0
+				&& db_check_table_version(&auth_dbf, dbh, &name,
+					TABLE_VERSION) < 0) {
+			LM_ERR("error during table version check.\n");
+			auth_dbf.close(dbh);
+			return -1;
+		}
+		auth_dbf.close(dbh);
+	}
+	return 0;
+}
+
+/*
+ * Convert cfg parameters to run-time structures
+ */
+static int auth_check_fixup(void** param, int param_no)
+{
+	if(strlen((char*)*param)<=0) {
+		LM_ERR("empty parameter %d not allowed\n", param_no);
+		return -1;
+	}
+	if (param_no == 1) {
+		return fixup_var_str_12(param, 1);
+	}
+	if (param_no == 2) {
+		return fixup_var_str_12(param, 2);
+	}
+	if (param_no == 3) {
+		return fixup_igp_null(param, 1);
+	}
+	return 0;
+}
+
+/*
+ * Parse extra credentials list
+ */
+int parse_aaa_pvs(char *definition, pv_elem_t **pv_def, int *cnt)
+{
+	pv_elem_t *pve;
+	str pv;
+	char *p;
+	char *end;
+	char *sep;
+
+	p = definition;
+	if (p==0 || *p==0)
+		return 0;
+
+	*pv_def = 0;
+	*cnt = 0;
+
+	/* get element by element */
+	while ( (end=strchr(p,';'))!=0 || (end=p+strlen(p))!=p ) {
+		/* new pv_elem_t */
+		if ( (pve=(pv_elem_t*)pkg_malloc(sizeof(pv_elem_t)))==0 ) {
+			LM_ERR("no more pkg mem\n");
+			goto error;
+		}
+		memset( pve, 0, sizeof(pv_elem_t));
+
+		/* definition is between p and e */
+		/* search backwards because PV definition may contain '=' characters */
+		for (sep = end; sep >= p && *sep != '='; sep--); 
+		if (sep > p) {
+			/* pv=column style */
+			/* set column name */
+			pve->text.s = sep + 1;
+			pve->text.len = end - pve->text.s;
+			trim(&pve->text);
+			if (pve->text.len == 0)
+				goto parse_error;
+			/* set pv spec */
+			pv.s = p;
+			pv.len = sep - p;
+			trim(&pv);
+			if (pv.len == 0)
+				goto parse_error;
+		} else {
+			/* no pv, only column name */
+			pve->text.s = p;
+			pve->text.len = end - pve->text.s;
+			trim(&pve->text);
+			if (pve->text.len == 0)
+				goto parse_error;
+			/* create an avp definition for the spec parser */
+			pv.s = (char*)pkg_malloc(pve->text.len + 7);
+			if (pv.s == NULL) {
+				LM_ERR("no more pkg mem\n");
+				goto parse_error;
+			}
+			pv.len = snprintf(pv.s, pve->text.len + 7, "$avp(%.*s)",
+			                  pve->text.len, pve->text.s);
+		}
+
+		/* create a pv spec */
+		LM_DBG("column: %.*s  pv: %.*s\n", pve->text.len, pve->text.s, pv.len, pv.s);
+		pve->spec = pv_spec_lookup(&pv, NULL);
+		if(pve->spec==NULL || pve->spec->setf == NULL) {
+			LM_ERR("PV is not writeable: %.*s\n", pv.len, pv.s);
+			goto parse_error;
+		}
+
+		/* link the element */
+		pve->next = *pv_def;
+		*pv_def = pve;
+		(*cnt)++;
+		pve = 0;
+		/* go to the end */
+		p = end;
+		if (*p==';')
+			p++;
+		if (*p==0)
+			break;
+	}
+
+	return 0;
+parse_error:
+	LM_ERR("parse failed in \"%s\" at pos %d(%s)\n",
+		definition, (int)(long)(p-definition),p);
+error:
+	pkg_free( pve );
+	pv_elem_free_all( *pv_def );
+	*pv_def = 0;
+	*cnt = 0;
+	return -1;
+}
diff --git a/modules/auth_db/auth_db_mod.h b/modules/auth_db/auth_db_mod.h
new file mode 100644
index 0000000..ffeb4ba
--- /dev/null
+++ b/modules/auth_db/auth_db_mod.h
@@ -0,0 +1,55 @@
+/*
+ * Digest Authentication - Database support
+ *
+ * Copyright (C) 2001-2003 FhG Fokus
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+
+#ifndef AUTHDB_MOD_H
+#define AUTHDB_MOD_H
+
+#include "../../str.h"
+#include "../../lib/srdb1/db.h"
+#include "../../modules/auth/api.h"
+#include "../../parser/msg_parser.h"
+
+
+/*
+ * Module parameters variables
+ */
+
+extern str user_column;     /* 'username' column name */
+extern str domain_column;   /* 'domain' column name */
+extern str pass_column;     /* 'password' column name */
+extern str pass_column_2;   /* Column containing HA1 string constructed
+			     * of user at domain username
+			     */
+
+extern int calc_ha1;          /* if set to 1, ha1 is calculated by the server */
+extern int use_domain;        /* If set to 1 then the domain will be used when selecting a row */
+
+extern db1_con_t* auth_db_handle; /* database connection handle */
+extern db_func_t auth_dbf;
+
+extern auth_api_s_t auth_api;
+
+extern pv_elem_t *credentials;
+extern int credentials_n;
+
+#endif /* AUTHDB_MOD_H */
diff --git a/modules/auth_db/authdb_mod.c b/modules/auth_db/authdb_mod.c
deleted file mode 100644
index ec44e67..0000000
--- a/modules/auth_db/authdb_mod.c
+++ /dev/null
@@ -1,435 +0,0 @@
-/* 
- * $Id$
- *
- * Digest Authentication Module
- *
- * Copyright (C) 2001-2003 FhG Fokus
- *
- * This file is part of Kamailio, a free SIP server.
- *
- * Kamailio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version
- *
- * Kamailio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- *
- * History:
- * --------
- * 2003-02-26: checks and group moved to separate modules (janakj)
- * 2003-03-11: New module interface (janakj)
- * 2003-03-16: flags export parameter added (janakj)
- * 2003-03-19  all mallocs/frees replaced w/ pkg_malloc/pkg_free (andrei)
- * 2003-04-05: default_uri #define used (jiri)
- * 2004-06-06  cleanup: static & auth_db_{init,bind,close.ver} used (andrei)
- * 2005-05-31  general definition of AVPs in credentials now accepted - ID AVP,
- *             STRING AVP, AVP aliases (bogdan)
- * 2006-03-01 pseudo variables support for domain name (bogdan)
- */
-
-#include <stdio.h>
-#include <string.h>
-#include "../../sr_module.h"
-#include "../../lib/srdb1/db.h"
-#include "../../dprint.h"
-#include "../../error.h"
-#include "../../mod_fix.h"
-#include "../../trim.h"
-#include "../../mem/mem.h"
-#include "../../parser/parse_uri.h"
-#include "../../modules/auth/api.h"
-#include "authorize.h"
-
-MODULE_VERSION
-
-#define TABLE_VERSION 6
-
-/*
- * Module destroy function prototype
- */
-static void destroy(void);
-
-
-/*
- * Module child-init function prototype
- */
-static int child_init(int rank);
-
-
-/*
- * Module initialization function prototype
- */
-static int mod_init(void);
-
-
-static int w_is_subscriber(sip_msg_t *msg, char *_uri, char* _table,
-		char *_flags);
-static int auth_fixup(void** param, int param_no);
-static int auth_check_fixup(void** param, int param_no);
-int parse_aaa_pvs(char *definition, pv_elem_t **pv_def, int *cnt);
-
-#define USER_COL "username"
-#define DOMAIN_COL "domain"
-#define PASS_COL "ha1"
-#define PASS_COL_2 "ha1b"
-
-/*
- * Module parameter variables
- */
-static str db_url           = str_init(DEFAULT_RODB_URL);
-str user_column             = str_init(USER_COL);
-str domain_column           = str_init(DOMAIN_COL);
-str pass_column             = str_init(PASS_COL);
-str pass_column_2           = str_init(PASS_COL_2);
-
-static int version_table_check = 1;
-
-int calc_ha1                = 0;
-int use_domain              = 0; /* Use also domain when looking up in table */
-
-db1_con_t* auth_db_handle    = 0; /* database connection handle */
-db_func_t auth_dbf;
-auth_api_s_t auth_api;
-
-char *credentials_list      = 0;
-pv_elem_t *credentials      = 0; /* Parsed list of credentials to load */
-int credentials_n           = 0; /* Number of credentials in the list */
-
-/*
- * Exported functions
- */
-static cmd_export_t cmds[] = {
-	{"www_authorize",      (cmd_function)www_authenticate,   2, auth_fixup, 0,
-		REQUEST_ROUTE},
-	{"www_authenticate",   (cmd_function)www_authenticate,   2, auth_fixup, 0,
-		REQUEST_ROUTE},
-	{"www_authenticate",   (cmd_function)www_authenticate2,  3, auth_fixup, 0,
-REQUEST_ROUTE},
-	{"proxy_authorize",    (cmd_function)proxy_authenticate, 2, auth_fixup, 0,
-		REQUEST_ROUTE},
-	{"proxy_authenticate", (cmd_function)proxy_authenticate, 2, auth_fixup, 0,
-		REQUEST_ROUTE},
-	{"auth_check",         (cmd_function)auth_check,         3, auth_check_fixup, 0,
-		REQUEST_ROUTE},
-	{"is_subscriber",      (cmd_function)w_is_subscriber,    3, auth_check_fixup, 0,
-		ANY_ROUTE},
-	{"bind_auth_db",       (cmd_function)bind_auth_db,       0, 0, 0,
-		0},
-	{0, 0, 0, 0, 0, 0}
-};
-
-
-/*
- * Exported parameters
- */
-static param_export_t params[] = {
-	{"db_url",            PARAM_STR, &db_url            },
-	{"user_column",       PARAM_STR, &user_column       },
-	{"domain_column",     PARAM_STR, &domain_column     },
-	{"password_column",   PARAM_STR, &pass_column       },
-	{"password_column_2", PARAM_STR, &pass_column_2     },
-	{"calculate_ha1",     INT_PARAM, &calc_ha1            },
-	{"use_domain",        INT_PARAM, &use_domain          },
-	{"load_credentials",  PARAM_STRING, &credentials_list    },
-	{"version_table",     INT_PARAM, &version_table_check },
-	{0, 0, 0}
-};
-
-
-/*
- * Module interface
- */
-struct module_exports exports = {
-	"auth_db", 
-	DEFAULT_DLFLAGS, /* dlopen flags */
-	cmds,       /* Exported functions */
-	params,     /* Exported parameters */
-	0,          /* exported statistics */
-	0,          /* exported MI functions */
-	0,          /* exported pseudo-variables */
-	0,          /* extra processes */
-	mod_init,   /* module initialization function */
-	0,          /* response function */
-	destroy,    /* destroy function */
-	child_init  /* child initialization function */
-};
-
-
-static int child_init(int rank)
-{
-	if (rank==PROC_INIT || rank==PROC_MAIN || rank==PROC_TCP_MAIN)
-		return 0; /* do nothing for the main process */
-	
-	auth_db_handle = auth_dbf.init(&db_url);
-	if (auth_db_handle == 0){
-		LM_ERR("unable to connect to the database\n");
-		return -1;
-	}
-
-	return 0;
-}
-
-
-static int mod_init(void)
-{
-	bind_auth_s_t bind_auth;
-
-	/* Find a database module */
-	if (db_bind_mod(&db_url, &auth_dbf) < 0){
-		LM_ERR("unable to bind to a database driver\n");
-		return -1;
-	}
-
-	/* bind to auth module and import the API */
-	bind_auth = (bind_auth_s_t)find_export("bind_auth_s", 0, 0);
-	if (!bind_auth) {
-		LM_ERR("unable to find bind_auth function. Check if you load"
-				" the auth module.\n");
-		return -2;
-	}
-
-	if (bind_auth(&auth_api) < 0) {
-		LM_ERR("unable to bind auth module\n");
-		return -3;
-	}
-
-	/* process additional list of credentials */
-	if (parse_aaa_pvs(credentials_list, &credentials, &credentials_n) != 0) {
-		LM_ERR("failed to parse credentials\n");
-		return -5;
-	}
-
-	return 0;
-}
-
-
-static void destroy(void)
-{
-	if (auth_db_handle) {
-		auth_dbf.close(auth_db_handle);
-		auth_db_handle = 0;
-	}
-	if (credentials) {
-		pv_elem_free_all(credentials);
-		credentials = 0;
-		credentials_n = 0;
-	}
-}
-
-
-/**
- * check if the subscriber identified by _uri has a valid record in
- * database table _table
- */
-static int w_is_subscriber(sip_msg_t *msg, char *_uri, char* _table,
-		char *_flags)
-{
-	str suri;
-	str stable;
-	int iflags;
-	int ret;
-	sip_uri_t puri;
-
-	if(msg==NULL || _uri==NULL || _table==NULL || _flags==NULL) {
-		LM_ERR("invalid parameters\n");
-		return AUTH_ERROR;
-	}
-
-	if (get_str_fparam(&suri, msg, (fparam_t*)_uri) < 0) {
-		LM_ERR("failed to get uri value\n");
-		return -1;
-	}
-
-	if (suri.len==0) {
-		LM_ERR("invalid uri parameter - empty value\n");
-		return -1;
-	}
-	if(parse_uri(suri.s, suri.len, &puri)<0){
-		LM_ERR("invalid uri parameter format\n");
-		return -1;
-	}
-
-	if (get_str_fparam(&stable, msg, (fparam_t*)_table) < 0) {
-		LM_ERR("failed to get table value\n");
-		return -1;
-	}
-
-	if (stable.len==0) {
-		LM_ERR("invalid table parameter - empty value\n");
-		return -1;
-	}
-
-	if(fixup_get_ivalue(msg, (gparam_p)_flags, &iflags)!=0)
-	{
-		LM_ERR("invalid flags parameter\n");
-		return -1;
-	}
-
-	LM_DBG("uri [%.*s] table [%.*s] flags [%d]\n", suri.len, suri.s,
-			stable.len,  stable.s, iflags);
-	ret = fetch_credentials(msg, &puri.user,
-				(iflags&AUTH_DB_SUBS_USE_DOMAIN)?&puri.host:NULL,
-				&stable, iflags);
-
-	if(ret>=0)
-		return 1;
-	return ret;
-}
-
-/*
- * Convert the char* parameters
- */
-static int auth_fixup(void** param, int param_no)
-{
-	db1_con_t* dbh = NULL;
-	str name;
-
-	if(strlen((char*)*param)<=0) {
-		LM_ERR("empty parameter %d not allowed\n", param_no);
-		return -1;
-	}
-
-	if (param_no == 1 || param_no == 3) {
-		return fixup_var_str_12(param, 1);
-	} else if (param_no == 2) {
-		name.s = (char*)*param;
-		name.len = strlen(name.s);
-
-		dbh = auth_dbf.init(&db_url);
-		if (!dbh) {
-			LM_ERR("unable to open database connection\n");
-			return -1;
-		}
-		if(version_table_check!=0
-				&& db_check_table_version(&auth_dbf, dbh, &name,
-					TABLE_VERSION) < 0) {
-			LM_ERR("error during table version check.\n");
-			auth_dbf.close(dbh);
-			return -1;
-		}
-		auth_dbf.close(dbh);
-	}
-	return 0;
-}
-
-/*
- * Convert cfg parameters to run-time structures
- */
-static int auth_check_fixup(void** param, int param_no)
-{
-	if(strlen((char*)*param)<=0) {
-		LM_ERR("empty parameter %d not allowed\n", param_no);
-		return -1;
-	}
-	if (param_no == 1) {
-		return fixup_var_str_12(param, 1);
-	}
-	if (param_no == 2) {
-		return fixup_var_str_12(param, 2);
-	}
-	if (param_no == 3) {
-		return fixup_igp_null(param, 1);
-	}
-	return 0;
-}
-
-/*
- * Parse extra credentials list
- */
-int parse_aaa_pvs(char *definition, pv_elem_t **pv_def, int *cnt)
-{
-	pv_elem_t *pve;
-	str pv;
-	char *p;
-	char *end;
-	char *sep;
-
-	p = definition;
-	if (p==0 || *p==0)
-		return 0;
-
-	*pv_def = 0;
-	*cnt = 0;
-
-	/* get element by element */
-	while ( (end=strchr(p,';'))!=0 || (end=p+strlen(p))!=p ) {
-		/* new pv_elem_t */
-		if ( (pve=(pv_elem_t*)pkg_malloc(sizeof(pv_elem_t)))==0 ) {
-			LM_ERR("no more pkg mem\n");
-			goto error;
-		}
-		memset( pve, 0, sizeof(pv_elem_t));
-
-		/* definition is between p and e */
-		/* search backwards because PV definition may contain '=' characters */
-		for (sep = end; sep >= p && *sep != '='; sep--); 
-		if (sep > p) {
-			/* pv=column style */
-			/* set column name */
-			pve->text.s = sep + 1;
-			pve->text.len = end - pve->text.s;
-			trim(&pve->text);
-			if (pve->text.len == 0)
-				goto parse_error;
-			/* set pv spec */
-			pv.s = p;
-			pv.len = sep - p;
-			trim(&pv);
-			if (pv.len == 0)
-				goto parse_error;
-		} else {
-			/* no pv, only column name */
-			pve->text.s = p;
-			pve->text.len = end - pve->text.s;
-			trim(&pve->text);
-			if (pve->text.len == 0)
-				goto parse_error;
-			/* create an avp definition for the spec parser */
-			pv.s = (char*)pkg_malloc(pve->text.len + 7);
-			if (pv.s == NULL) {
-				LM_ERR("no more pkg mem\n");
-				goto parse_error;
-			}
-			pv.len = snprintf(pv.s, pve->text.len + 7, "$avp(%.*s)",
-			                  pve->text.len, pve->text.s);
-		}
-
-		/* create a pv spec */
-		LM_DBG("column: %.*s  pv: %.*s\n", pve->text.len, pve->text.s, pv.len, pv.s);
-		pve->spec = pv_spec_lookup(&pv, NULL);
-		if(pve->spec==NULL || pve->spec->setf == NULL) {
-			LM_ERR("PV is not writeable: %.*s\n", pv.len, pv.s);
-			goto parse_error;
-		}
-
-		/* link the element */
-		pve->next = *pv_def;
-		*pv_def = pve;
-		(*cnt)++;
-		pve = 0;
-		/* go to the end */
-		p = end;
-		if (*p==';')
-			p++;
-		if (*p==0)
-			break;
-	}
-
-	return 0;
-parse_error:
-	LM_ERR("parse failed in \"%s\" at pos %d(%s)\n",
-		definition, (int)(long)(p-definition),p);
-error:
-	pkg_free( pve );
-	pv_elem_free_all( *pv_def );
-	*pv_def = 0;
-	*cnt = 0;
-	return -1;
-}
diff --git a/modules/auth_db/authdb_mod.h b/modules/auth_db/authdb_mod.h
deleted file mode 100644
index 75ee611..0000000
--- a/modules/auth_db/authdb_mod.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * $Id$
- *
- * Digest Authentication - Database support
- *
- * Copyright (C) 2001-2003 FhG Fokus
- *
- * This file is part of Kamailio, a free SIP server.
- *
- * Kamailio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version
- *
- * Kamailio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-
-#ifndef AUTHDB_MOD_H
-#define AUTHDB_MOD_H
-
-#include "../../str.h"
-#include "../../lib/srdb1/db.h"
-#include "../../modules/auth/api.h"
-#include "../../parser/msg_parser.h"
-
-
-/*
- * Module parameters variables
- */
-
-extern str user_column;     /* 'username' column name */
-extern str domain_column;   /* 'domain' column name */
-extern str pass_column;     /* 'password' column name */
-extern str pass_column_2;   /* Column containing HA1 string constructed
-			     * of user at domain username
-			     */
-
-extern int calc_ha1;          /* if set to 1, ha1 is calculated by the server */
-extern int use_domain;        /* If set to 1 then the domain will be used when selecting a row */
-
-extern db1_con_t* auth_db_handle; /* database connection handle */
-extern db_func_t auth_dbf;
-
-extern auth_api_s_t auth_api;
-
-extern pv_elem_t *credentials;
-extern int credentials_n;
-
-#endif /* AUTHDB_MOD_H */
diff --git a/modules/auth_db/authorize.c b/modules/auth_db/authorize.c
index 13c1044..6d582c2 100644
--- a/modules/auth_db/authorize.c
+++ b/modules/auth_db/authorize.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Digest Authentication - Database support
  *
  * Copyright (C) 2001-2003 FhG Fokus
@@ -21,15 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * history:
- * ---------
- * 2003-02-28 scratchpad compatibility abandoned
- * 2003-01-27 next baby-step to removing ZT - PRESERVE_ZT (jiri)
- * 2004-06-06 updated to the new DB api, added auth_db_{init,bind,close,ver}
- *             (andrei)
- * 2005-05-31 general definition of AVPs in credentials now accepted - ID AVP,
- *            STRING AVP, AVP aliases (bogdan)
- * 2006-03-01 pseudo variables support for domain name (bogdan)
  */
 
 
@@ -49,7 +38,7 @@
 #include "../../mod_fix.h"
 #include "../../mem/mem.h"
 #include "api.h"
-#include "authdb_mod.h"
+#include "auth_db_mod.h"
 #include "authorize.h"
 
 
diff --git a/modules/auth_db/authorize.h b/modules/auth_db/authorize.h
index 3746fd6..e5eb76a 100644
--- a/modules/auth_db/authorize.h
+++ b/modules/auth_db/authorize.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Digest Authentication - Database support
  *
  * Copyright (C) 2001-2003 FhG Fokus
diff --git a/modules/auth_diameter/Makefile b/modules/auth_diameter/Makefile
index e7e229c..fc8860c 100644
--- a/modules/auth_diameter/Makefile
+++ b/modules/auth_diameter/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # Digest Authentication - Diameter support
 #
diff --git a/modules/auth_ephemeral/Makefile b/modules/auth_ephemeral/Makefile
index eedbe86..7574ebe 100644
--- a/modules/auth_ephemeral/Makefile
+++ b/modules/auth_ephemeral/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
diff --git a/modules/auth_radius/Makefile b/modules/auth_radius/Makefile
index f2fcaf3..8affb47 100644
--- a/modules/auth_radius/Makefile
+++ b/modules/auth_radius/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # Digest Authentication - Radius support
 #
diff --git a/modules/auth_radius/README b/modules/auth_radius/README
index 1875408..5837333 100644
--- a/modules/auth_radius/README
+++ b/modules/auth_radius/README
@@ -22,11 +22,11 @@ Jan Janak
 
    <jan at iptel.org>
 
-   Copyright © 2002, 2003 FhG FOKUS
+   Copyright � 2002, 2003 FhG FOKUS
 
-   Copyright © 2005 Voice Sistem SRL
+   Copyright � 2005 Voice Sistem SRL
 
-   Copyright © 2008-2010 Juha Heinanen
+   Copyright � 2008-2010 Juha Heinanen
      __________________________________________________________________
 
    Table of Contents
@@ -46,6 +46,7 @@ Jan Janak
               4.2. service_type (integer)
               4.3. auth_extra (string)
               4.4. use_ruri_flag (integer)
+              4.5. radius_avps_mode (integer)
 
         5. Functions
 
@@ -54,13 +55,14 @@ Jan Janak
 
    List of Examples
 
-   1.1. “SIP-AVP” RADIUS AVP exmaples
+   1.1. "SIP-AVP" RADIUS AVP exmaples
    1.2. radius_config parameter usage
    1.3. service_type parameter usage
    1.4. auth_extra parameter usage
    1.5. use_ruri_flag parameter usage
-   1.6. radius_www_authorize usage
-   1.7. proxy_authorize usage
+   1.6. radius_avps_mode parameter usage
+   1.7. radius_www_authorize usage
+   1.8. proxy_authorize usage
 
 Chapter 1. Admin Guide
 
@@ -79,6 +81,7 @@ Chapter 1. Admin Guide
         4.2. service_type (integer)
         4.3. auth_extra (string)
         4.4. use_ruri_flag (integer)
+        4.5. radius_avps_mode (integer)
 
    5. Functions
 
@@ -107,7 +110,7 @@ Chapter 1. Admin Guide
    queries.
 
    The additional credentials are embedded in the RADIUS reply as AVPs
-   “SIP-AVP”. The syntax of the value is:
+   "SIP-AVP". The syntax of the value is:
      * value = SIP_AVP_NAME SIP_AVP_VALUE
      * SIP_AVP_NAME = STRING_NAME | '#'ID_NUMBER
      * SIP_AVP_VALUE = ':'STRING_VALUE | '#'NUMBER_VALUE
@@ -117,7 +120,7 @@ Chapter 1. Admin Guide
 
    The RPID value may be fetch via this mechanism.
 
-   Example 1.1. “SIP-AVP” RADIUS AVP exmaples
+   Example 1.1. "SIP-AVP" RADIUS AVP exmaples
 ....
 "email:joe at yahoo.com"
     - STRING NAME AVP (email) with STRING VALUE (joe at yahoo.com)
@@ -153,13 +156,14 @@ Chapter 1. Admin Guide
    4.2. service_type (integer)
    4.3. auth_extra (string)
    4.4. use_ruri_flag (integer)
+   4.5. radius_avps_mode (integer)
 
 4.1. radius_config (string)
 
    This is the location of the configuration file of radius client
    libraries.
 
-   Default value is “/usr/local/etc/radiusclient-ng/radiusclient.conf”.
+   Default value is "/usr/local/etc/radiusclient-ng/radiusclient.conf".
 
    Example 1.2. radius_config parameter usage
 modparam("auth_radius", "radius_config", "/etc/radiusclient.conf")
@@ -170,7 +174,7 @@ modparam("auth_radius", "radius_config", "/etc/radiusclient.conf")
    default should be fine for most people. See your radius client include
    files for numbers to be put in this parameter if you need to change it.
 
-   Default value is “15”.
+   Default value is "15".
 
    Example 1.3. service_type parameter usage
 modparam("auth_radius", "service_type", 15)
@@ -199,11 +203,22 @@ modparam("auth_radius", "auth_extra", "Acct-Session-Id=$ci")
    authentication. At the time of this writing, certain versions of
    Linksys WRT54GL are known to do that.
 
-   Default value is “-1”.
+   Default value is "-1".
 
    Example 1.5. use_ruri_flag parameter usage
 modparam("auth_radius", "use_ruri_flag", 22)
 
+4.5. radius_avps_mode (integer)
+
+   If set to 1, all RADIUS AVPs returned by RADIUS server are stored in
+   Kamailio AVPs list. If set to 0, only the SIP_AVP type of RADIUS AVPs
+   are stored in Kamailio AVPs list.
+
+   Default value is 0.
+
+   Example 1.6. radius_avps_mode parameter usage
+modparam("auth_radius", "radius_avps_mode", 1)
+
 5. Functions
 
    5.1. radius_www_authorize(realm [, uri_user])
@@ -248,7 +263,7 @@ modparam("auth_radius", "use_ruri_flag", 22)
 
    This function can be used from REQUEST_ROUTE.
 
-   Example 1.6. radius_www_authorize usage
+   Example 1.7. radius_www_authorize usage
 ...
     if (!radius_www_authorize("$td")) {
         switch ($rc) {
@@ -300,7 +315,7 @@ modparam("auth_radius", "use_ruri_flag", 22)
 
    This function can be used from REQUEST_ROUTE.
 
-   Example 1.7. proxy_authorize usage
+   Example 1.8. proxy_authorize usage
 ...
     if (!radius_proxy_authorize("$pd", "$pU")) { # Realm and URI user are taken
         switch ($rc) {                           # from P-Preferred-Identity
diff --git a/modules/auth_radius/authrad_mod.c b/modules/auth_radius/authrad_mod.c
index 789f3f5..f4a9eac 100644
--- a/modules/auth_radius/authrad_mod.c
+++ b/modules/auth_radius/authrad_mod.c
@@ -65,6 +65,7 @@ static char* radius_config = DEFAULT_RADIUSCLIENT_CONF;
 static int service_type = -1;
 
 int use_ruri_flag = -1;
+int ar_radius_avps_mode = 0;
 
 static char *auth_extra_str = 0;
 struct extra_attr *auth_extra = 0;
@@ -89,10 +90,11 @@ static cmd_export_t cmds[] = {
  * Exported parameters
  */
 static param_export_t params[] = {
-	{"radius_config",    PARAM_STRING, &radius_config   },
-	{"service_type",     INT_PARAM, &service_type    },
-	{"use_ruri_flag",    INT_PARAM, &use_ruri_flag   },
-	{"auth_extra",       PARAM_STRING, &auth_extra_str  },
+	{"radius_config",    PARAM_STRING, &radius_config	},
+	{"service_type",     INT_PARAM, &service_type	},
+	{"use_ruri_flag",    INT_PARAM, &use_ruri_flag	},
+	{"auth_extra",       PARAM_STRING, &auth_extra_str	},
+	{"radius_avps_mode",	 INT_PARAM, &ar_radius_avps_mode	},
 	{0, 0, 0}
 };
 
diff --git a/modules/auth_radius/authrad_mod.h b/modules/auth_radius/authrad_mod.h
index 15ba1b3..c6561d3 100644
--- a/modules/auth_radius/authrad_mod.h
+++ b/modules/auth_radius/authrad_mod.h
@@ -40,6 +40,7 @@ extern void *rh;
 extern struct extra_attr *auth_extra;
 
 extern int use_ruri_flag;
+extern int ar_radius_avps_mode;
 
 extern auth_api_s_t auth_api;
 
diff --git a/modules/auth_radius/doc/auth_radius_admin.xml b/modules/auth_radius/doc/auth_radius_admin.xml
index 5deb681..79c92db 100644
--- a/modules/auth_radius/doc/auth_radius_admin.xml
+++ b/modules/auth_radius/doc/auth_radius_admin.xml
@@ -188,6 +188,23 @@ modparam("auth_radius", "use_ruri_flag", 22)
                 </programlisting>
                 </example>
         </section>
+	<section id="auth_radius.p.radius_avps_mode">
+		<title><varname>radius_avps_mode</varname> (integer)</title>
+		<para>
+			If set to 1, all RADIUS AVPs returned by RADIUS server are stored
+			in &kamailio; AVPs list. If set to 0, only the SIP_AVP type of RADIUS
+			AVPs are stored in &kamailio; AVPs list.
+		</para>
+		<para>
+			Default value is 0.
+		</para>
+		<example>
+		<title><varname>radius_avps_mode</varname> parameter usage</title>
+		<programlisting format="linespecific">
+modparam("auth_radius", "radius_avps_mode", 1)
+		</programlisting>
+		</example>
+	</section>
 	</section>
 
 	<section>
diff --git a/modules/auth_radius/sterman.c b/modules/auth_radius/sterman.c
index 2cf7de8..88eef1d 100644
--- a/modules/auth_radius/sterman.c
+++ b/modules/auth_radius/sterman.c
@@ -70,80 +70,77 @@ static str val_arr[MAX_EXTRA];
 static inline int extract_avp(VALUE_PAIR* vp, unsigned short *flags,
 			      int_str *name, int_str *value)
 {
-	static str names, values;
-	unsigned int r;
-	char *p;
-	char *end;
-
-	/* empty? */
-	if (vp->lvalue==0 || vp->strvalue==0)
-		goto error;
-
-	p = vp->strvalue;
-	end = vp->strvalue + vp->lvalue;
-
-	LM_DBG("string is <%.*s>\n", (int)(long)(end-p), p);
-
-	/* get name */
-	if (*p!='#') {
-		/* name AVP */
-		*flags |= AVP_NAME_STR;
-		names.s = p;
-	} else {
-		names.s = ++p;
-	}
-
-	names.len = 0;
-	while( p<end && *p!=':' && *p!='#')
-		p++;
-	if (names.s==p || p==end) {
-		LM_ERR("empty AVP name\n");
-		goto error;
-	}
-	names.len = p - names.s;
-	LM_DBG("AVP name is <%.*s>\n", names.len, names.s);
-
-	/* get value */
-	if (*p!='#') {
-		/* string value */
-		*flags |= AVP_VAL_STR;
-	}
-	values.s = ++p;
-	values.len = end-values.s;
-	if (values.len==0) {
-		LM_ERR("empty AVP value\n");
-		goto error;
-	}
-	LM_DBG("AVP val is <%.*s>\n", values.len, values.s);
-
-	if ( !((*flags)&AVP_NAME_STR) ) {
-		/* convert name to id*/
-		if (str2int(&names,&r)!=0 ) {
-			LM_ERR("invalid AVP ID '%.*s'\n", names.len,names.s);
-			goto error;
-		}
-		name->n = (int)r;
-	} else {
-		name->s = names;
-	}
-
-	if ( !((*flags)&AVP_VAL_STR) ) {
-		/* convert value to integer */
-		if (str2int(&values,&r)!=0 ) {
-			LM_ERR("invalid AVP numrical value '%.*s'\n", values.len,values.s);
-			goto error;
-		}
-		value->n = (int)r;
+	char *p, *q, *r;
+
+	LM_DBG("vp->name '%.*s'\n",(int)strlen(vp->name),vp->name);
+	LM_DBG("vp->attribute '%d'\n",vp->attribute);
+	LM_DBG("vp->type '%d'\n",vp->type);
+	LM_DBG("vp->lvalue '%d'\n",vp->lvalue);
+	if (vp->type == PW_TYPE_STRING) 
+		LM_DBG("vp->strvalue '%.*s'\n",(int)strlen(vp->strvalue),vp->strvalue);
+
+	if ( vp->attribute == attrs[A_SIP_AVP].v && vp->type == PW_TYPE_STRING ) {
+		p = strchr(vp->strvalue,'#');
+		q = strchr(vp->strvalue,':');
+		if (!q && p == vp->strvalue && vp->strvalue+sizeof(char) != '\0' ) {
+				r = p;
+				r = strchr(r++,'#');
+		} else 
+			r = NULL;
+		errno = 0;
+		if ( p == vp->strvalue && q ) {
+			/* int name and str value */
+			*flags |= AVP_VAL_STR;
+			name->n = strtol(++p,&q,10);
+			value->s.s = ++q;
+			value->s.len = strlen(q);
+		} else if ( p && !r && p > vp->strvalue && !q ) {
+			/* str name and int value */
+			*flags |= AVP_NAME_STR;
+			name->s.len = p - vp->strvalue;
+			name->s.s = vp->strvalue;
+			value->n = strtol(++p,&r,10);
+		} else if ( p && p != r && !q ) {
+			/* int name and int vale */
+			name->n = strtol(++p,&q,10);
+			value->n = strtol(++r,&q,10);
+		} else if ( (!p || p > q) && q ) {
+			/* str name and str value */
+			*flags |= AVP_VAL_STR|AVP_NAME_STR;
+			name->s.len = q - vp->strvalue;
+			name->s.s = vp->strvalue;
+			value->s.len = strlen(++q);
+			value->s.s = q;
+		} else /* error - unknown */
+			return 0;
+	    if ( errno != 0 )
+			return 0;
+	} else if (vp->type == PW_TYPE_STRING) {
+			*flags |= AVP_VAL_STR|AVP_NAME_STR;
+			/* if start of value is the name of value */
+			if (vp->strvalue == strstr(vp->strvalue,vp->name))
+				/* then get value after name + one char delimiter */
+				p = vp->strvalue + strlen(vp->name) + sizeof(char);
+			else
+				p = vp->strvalue;
+			value->s.len = vp->lvalue - (p - vp->strvalue);
+			value->s.s = p;
+			name->s.len = strlen(vp->name); 
+			name->s.s = vp->name;
+	} else if ((vp->type == PW_TYPE_INTEGER) || (vp->type == PW_TYPE_IPADDR) || (vp->type == PW_TYPE_DATE)) {
+			*flags |= AVP_NAME_STR;
+			value->n = vp->lvalue;
+			name->s.len = strlen(vp->name); 
+			name->s.s = vp->name;
 	} else {
-		value->s = values;
+			LM_ERR("Unknown AVP type '%d'!\n",vp->type);
+			return 0;
 	}
-
-	return 0;
-error:
-	return -1;
+	if ( ! name->s.len )
+	   return 0;
+	return 1;
 }
 
-
 /*
  * Generate AVPs from the database result
  */
@@ -153,14 +150,16 @@ static int generate_avps(VALUE_PAIR* received)
 	unsigned short flags;
 	VALUE_PAIR *vp;
 
+	LM_DBG("getting AVPs from RADIUS Reply\n");
 	vp = received;
-
-	LM_DBG("getting SIP AVPs from avpair %d\n",	attrs[A_SIP_AVP].v);
-
-	for( ; (vp=rc_avpair_get(vp,attrs[A_SIP_AVP].v,0)) ; vp=vp->next) {
+	if ( ! ar_radius_avps_mode )
+		vp=rc_avpair_get(vp,attrs[A_SIP_AVP].v,0);
+	for( ; vp; vp=((ar_radius_avps_mode)?vp->next:rc_avpair_get(vp->next,attrs[A_SIP_AVP].v,0)) ) {
 		flags = 0;
-		if (extract_avp( vp, &flags, &name, &val)!=0 )
+		if (!extract_avp( vp, &flags, &name, &val)){
+			LM_ERR("error while extracting AVP '%.*s'\n",(int)strlen(vp->name),vp->name);
 			continue;
+		}
 		if (add_avp( flags, name, val) < 0) {
 			LM_ERR("unable to create a new AVP\n");
 		} else {
diff --git a/modules/auth_xkeys/Makefile b/modules/auth_xkeys/Makefile
new file mode 100644
index 0000000..ecfed10
--- /dev/null
+++ b/modules/auth_xkeys/Makefile
@@ -0,0 +1,14 @@
+#
+# WARNING: do not run this directly, it should be run by the master Makefile
+
+include ../../Makefile.defs
+auto_gen=
+NAME=auth_xkeys.so
+LIBS=
+
+DEFS+=-DKAMAILIO_MOD_INTERFACE
+
+SERLIBPATH=../../lib
+SER_LIBS+=$(SERLIBPATH)/srutils/srutils
+SER_LIBS+=$(SERLIBPATH)/kcore/kcore
+include ../../Makefile.modules
diff --git a/modules/auth_xkeys/README b/modules/auth_xkeys/README
new file mode 100644
index 0000000..c2cd6aa
--- /dev/null
+++ b/modules/auth_xkeys/README
@@ -0,0 +1,179 @@
+AUTH_XKEYS Module
+
+Daniel-Constantin Mierla
+
+   <miconda at gmail.com>
+
+Edited by
+
+Daniel-Constantin Mierla
+
+   <miconda at gmail.com>
+
+   Copyright � 2015 asipto.com
+     __________________________________________________________________
+
+   Table of Contents
+
+   1. Admin Guide
+
+        1. Overview
+        2. Dependencies
+
+              2.1. Kamailio Modules
+              2.2. External Libraries or Applications
+
+        3. Parameters
+
+              3.1. xkey (str)
+
+        4. Functions
+
+              4.1. auth_xkeys_add(hdr, kid, alg, data)
+              4.2. auth_xkeys_check(hdr, kid, alg, data)
+
+   List of Examples
+
+   1.1. Set xkey parameter
+   1.2. auth_xkeys_add usage
+   1.3. auth_xkeys_check usage
+
+Chapter 1. Admin Guide
+
+   Table of Contents
+
+   1. Overview
+   2. Dependencies
+
+        2.1. Kamailio Modules
+        2.2. External Libraries or Applications
+
+   3. Parameters
+
+        3.1. xkey (str)
+
+   4. Functions
+
+        4.1. auth_xkeys_add(hdr, kid, alg, data)
+        4.2. auth_xkeys_check(hdr, kid, alg, data)
+
+1. Overview
+
+   This module provides a custom mechanism to authenticate a SIP entity
+   using a list of shared keys.
+
+   It is similar to the API key based authentication used by many web
+   services. In short, the sender adds a particular header with a hash
+   token computed with the shared key and some values from the SIP request
+   (e.g., local IP, From/To/R-URI username, Call-ID, CSeq). The receiver
+   will check the hash value and decide whether the SIP message is
+   authenticated or not. The sender and receiver have to agree beforehand
+   on the name of the server, shared secret, algorithm to be used and what
+   data is going to be hashed.
+
+   The module is designed to work with many shared keys on the same group,
+   for more flexibility in adding/removing keys. The last added key in the
+   group is used to add the header, but older ones are used for matching
+   the hash value. That allows to change the active shared key without
+   affecting ongoing traffic. If one decides to use a new share key, add
+   it first to receiver (it will still authenticate with older key) and
+   then to the sender. Once both nodes are provisioned with the new key,
+   the older one can be removed.
+
+   For proper protection, it is recommended to use this authentication
+   mechanism over a secure channel (e.g., TLS, VPN, private network).
+
+   The benefit is avoiding the extra traffic and processing required by
+   WWW-Digest authentication schema (no more 401/407 and a follow up
+   request with credentials).
+
+   Another goal is to provide more elasticity for scalability needs of the
+   core SIP network nodes. Most of the nodes in the core network or the
+   interconnecting peers trust each other based on IP address. But adding
+   a new node requires updates to the exiting ones to trust the IP address
+   of the new node. On large deployments, that can become rather complex.
+   For example, as a replacement for IP trust relationships, the sender
+   can hash the local IP with the secret shared key, add it in the header
+   and the receiver will check if the source ip hased with the key results
+   in the same value.
+
+   Not being a challenge-reply mechanism, this can be used to authenticate
+   SIP responses from trusted peers.
+
+2. Dependencies
+
+   2.1. Kamailio Modules
+   2.2. External Libraries or Applications
+
+2.1. Kamailio Modules
+
+   The following modules must be loaded before this module:
+     * none.
+
+2.2. External Libraries or Applications
+
+   The following libraries or applications must be installed before
+   running Kamailio with this module loaded:
+     * none
+
+3. Parameters
+
+   3.1. xkey (str)
+
+3.1. xkey (str)
+
+   Specify the attributes for a shared secret. The value is in the format
+   'name1=value1;name2=value2;...'. The attributes can be:
+     * id - the id of the group for keys
+     * name - the name of the key within group
+     * value - the value of the key
+     * expires - expiration time (seconds)
+
+   Default value is empty.
+
+   Example 1.1. Set xkey parameter
+...
+modparam("auth_xkeys", "xkey", "id=abc;name=xyz;value=secret;expires=72000")
+...
+
+4. Functions
+
+   4.1. auth_xkeys_add(hdr, kid, alg, data)
+   4.2. auth_xkeys_check(hdr, kid, alg, data)
+
+4.1. auth_xkeys_add(hdr, kid, alg, data)
+
+   Add a header computed with the first key in the group kid, hasing with
+   algorithm alg over the content of parameter data. The parameters can
+   include variables.
+
+   The algorithm can be: sha256, sha384, sha512.
+
+   This function can be used from ANY_ROUTE.
+
+   Example 1.2. auth_xkeys_add usage
+...
+auth_xkeys_add("X-My-Key", "abc", "sha256", "$Ri:$fu:$ru:$hdr(CSeq)");
+...
+
+4.2. auth_xkeys_check(hdr, kid, alg, data)
+
+   Check if the value of header hdr matches the value computed with the
+   first key in the group kid, hasing with algorithm alg over the content
+   of parameter data. The parameters can include variables.
+
+   The algorithm can be: sha256, sha384, sha512.
+
+   Note that the header is not removed by the function, it is recommended
+   to remove it if sending to untrusted destination.
+
+   This function can be used from ANY_ROUTE.
+
+   Example 1.3. auth_xkeys_check usage
+...
+if(!auth_xkeys_add("X-My-Key", "abc", "sha256", "$si:$fu:$ru:$hdr(CSeq)")) {
+    send_reply("403", "Forbidden");
+    exit;
+}
+remove_hf("X-My-Key");
+...
diff --git a/modules/auth_xkeys/auth_xkeys.c b/modules/auth_xkeys/auth_xkeys.c
new file mode 100644
index 0000000..6798948
--- /dev/null
+++ b/modules/auth_xkeys/auth_xkeys.c
@@ -0,0 +1,497 @@
+/**
+ * Copyright (C) 2015 Daniel-Constantin Mierla (asipto.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "../../dprint.h"
+#include "../../ut.h"
+#include "../../trim.h"
+#include "../../pvapi.h"
+#include "../../data_lump.h"
+#include "../../mem/shm_mem.h"
+#include "../../parser/hf.h"
+#include "../../parser/parse_param.h"
+#include "../../parser/msg_parser.h"
+#include "../../lib/srutils/shautils.h"
+#include "../../lib/kcore/cmpapi.h"
+#include "../../rpc.h"
+#include "../../rpc_lookup.h"
+
+#include "auth_xkeys.h"
+
+typedef struct _auth_xkey {
+	str kid;
+	str kname;
+	str kvalue;
+	time_t kexpires;
+	struct _auth_xkey *next;
+	struct _auth_xkey *next_id;
+} auth_xkey_t;
+
+static auth_xkey_t **_auth_xkeys_list = NULL;
+
+/**
+ *
+ */
+int auth_xkeys_list_init(void)
+{
+	if(_auth_xkeys_list!=NULL)
+		return 0;
+	_auth_xkeys_list = shm_malloc(sizeof(auth_xkey_t));
+	if(_auth_xkeys_list==NULL) {
+		LM_ERR("no more shared memory\n");
+		return -1;
+	}
+	memset(_auth_xkeys_list, 0, sizeof(auth_xkey_t*));
+	return 0;
+}
+
+/**
+ *
+ */
+int authx_xkey_insert(auth_xkey_t *nkey)
+{
+	auth_xkey_t *ukey;
+	auth_xkey_t *itp;
+	auth_xkey_t *itc;
+	int ksize;
+	char *p;
+
+	if(auth_xkeys_list_init())
+		return -1;
+	if(nkey==NULL)
+		return -1;
+
+	ksize = sizeof(auth_xkey_t) + nkey->kid.len + nkey->kname.len
+		+ nkey->kvalue.len + 3;
+	ukey = (auth_xkey_t*)shm_malloc(ksize);
+	if(ukey==NULL) {
+		LM_ERR("no more shared memory\n");
+		return -1;
+	}
+	memset(ukey, 0, ksize);
+	p = (char*)ukey + sizeof(auth_xkey_t);
+
+	ukey->kid.len = nkey->kid.len;
+	ukey->kid.s = p;
+	strncpy(ukey->kid.s, nkey->kid.s, ukey->kid.len);
+	ukey->kid.s[ukey->kid.len] = '\0';
+	p += ukey->kid.len + 1;
+
+	ukey->kname.len = nkey->kname.len;
+	ukey->kname.s = p;
+	strncpy(ukey->kname.s, nkey->kname.s, ukey->kname.len);
+	ukey->kname.s[ukey->kname.len] = '\0';
+	p += ukey->kname.len + 1;
+
+	ukey->kvalue.len = nkey->kvalue.len;
+	ukey->kvalue.s = p;
+	strncpy(ukey->kvalue.s, nkey->kvalue.s, ukey->kvalue.len);
+	ukey->kvalue.s[ukey->kvalue.len] = '\0';
+	p += ukey->kvalue.len + 1;
+
+	ukey->kexpires = nkey->kexpires;
+
+	if(*_auth_xkeys_list==NULL) {
+		*_auth_xkeys_list = ukey;
+		return 0;
+	}
+
+	itp = NULL;
+	for(itc = *_auth_xkeys_list; itc; itc = itc->next_id) {
+		if(itc->kid.len==ukey->kid.len
+				&& strncasecmp(itc->kid.s, ukey->kid.s, ukey->kid.len)==0)
+			break;
+		itp = itc;
+	}
+	if(itc==NULL) {
+		/* new id */
+		ukey->next_id = *_auth_xkeys_list;
+		*_auth_xkeys_list = ukey;
+		return 0;
+	}
+
+	if(itp!=NULL) {
+		itp->next_id = ukey;
+	} else {
+		*_auth_xkeys_list = ukey;
+	}
+	ukey->next_id = itc->next_id;
+	ukey->next = itc;
+	itc->next_id = NULL;
+	return 0;
+}
+
+/**
+ *
+ */
+int authx_xkey_add_params(str *sparam)
+{
+	param_t* params_list = NULL;
+	param_hooks_t phooks;
+	param_t *pit=NULL;
+	auth_xkey_t tmp;
+	unsigned int uv;
+
+	if (parse_params(sparam, CLASS_ANY, &phooks, &params_list)<0)
+		return -1;
+
+	memset(&tmp, 0, sizeof(auth_xkey_t));
+
+	for (pit = params_list; pit; pit=pit->next)
+	{
+		if (pit->name.len==2
+				&& strncasecmp(pit->name.s, "id", 2)==0) {
+			tmp.kid = pit->body;
+		} else if(pit->name.len==4
+				&& strncasecmp(pit->name.s, "name", 4)==0) {
+			tmp.kname = pit->body;
+		} else if(pit->name.len==5
+				&& strncasecmp(pit->name.s, "value", 5)==0) {
+			tmp.kvalue = pit->body;
+		}  else if(pit->name.len==7
+				&& strncasecmp(pit->name.s, "expires", 7)==0) {
+			str2int(&pit->body, &uv);
+			tmp.kexpires = time(NULL) + uv;
+		}
+	}
+	if(tmp.kid.len<=0 || tmp.kname.len<=0 || tmp.kvalue.len<=0) {
+		LM_ERR("invalid parameters (%d/%d/%d)\n", tmp.kid.len,
+				tmp.kname.len, tmp.kvalue.len);
+		return -1;
+	}
+
+	if(authx_xkey_insert(&tmp)<0) {
+		LM_ERR("unable to insert the key [%.*s:%.*s]\n",
+				tmp.kid.len, tmp.kid.s, tmp.kname.len, tmp.kname.s);
+		return -1;
+	}
+
+	return 0;
+}
+
+/**
+ *
+ */
+int auth_xkeys_add(sip_msg_t* msg, str *hdr, str *key,
+		str *alg, str *data)
+{
+	str xdata;
+	auth_xkey_t *itc;
+	char xout[SHA512_DIGEST_STRING_LENGTH];
+	struct lump* anchor;
+
+	if(_auth_xkeys_list==NULL || *_auth_xkeys_list==NULL) {
+		LM_ERR("no stored keys\n");
+		return -1;
+	}
+	if(parse_headers(msg, HDR_EOH_F, 0)<0) {
+		LM_ERR("error parsing headers\n");
+		return -1;
+	}
+
+	for(itc = *_auth_xkeys_list; itc; itc = itc->next_id) {
+		if(itc->kid.len==key->len
+				&& strncasecmp(itc->kid.s, key->s, key->len)==0)
+			break;
+	}
+	if(itc==NULL) {
+		LM_DBG("no key chain id [%.*s]\n", key->len, key->s);
+		return -1;
+	}
+
+	xdata.s = pv_get_buffer();
+	xdata.len = data->len + itc->kvalue.len + 1;
+	if(xdata.len + 1 >= pv_get_buffer_size()) {
+		LM_ERR("size of data and key is too big\n");
+		return -1;
+	}
+
+	strncpy(xdata.s, itc->kvalue.s, itc->kvalue.len);
+	xdata.s[itc->kvalue.len] = ':';
+	strncpy(xdata.s + itc->kvalue.len + 1, data->s, data->len);
+	if(alg->len==6 && strncasecmp(alg->s, "sha256", 6)==0) {
+		compute_sha256(xout, (u_int8_t*)xdata.s, xdata.len);
+		xdata.len = SHA256_DIGEST_STRING_LENGTH - 1;
+	} else if(alg->len==6 && strncasecmp(alg->s, "sha384", 6)==0) {
+		compute_sha384(xout, (u_int8_t*)xdata.s, xdata.len);
+		xdata.len = SHA384_DIGEST_STRING_LENGTH - 1;
+	} else if(alg->len==6 && strncasecmp(alg->s, "sha512", 6)==0) {
+		compute_sha512(xout, (u_int8_t*)xdata.s, xdata.len);
+		xdata.len = SHA512_DIGEST_STRING_LENGTH - 1;
+	} else {
+		LM_ERR("unknown algorithm [%.*s]\n", alg->len, alg->s);
+		return -1;
+	}
+
+	if(xdata.len + hdr->len + 6 >= pv_get_buffer_size()) {
+		LM_ERR("size of new header is too big for pv buffer\n");
+		return -1;
+	}
+
+	strncpy(xdata.s, hdr->s, hdr->len);
+	xdata.s[hdr->len] = ':';
+	xdata.s[hdr->len+1] = ' ';
+	strncpy(xdata.s + hdr->len + 2, xout, xdata.len);
+	xdata.len += hdr->len + 2;
+	xdata.s[xdata.len] = '\r';
+	xdata.s[xdata.len+1] = '\n';
+	xdata.s[xdata.len+2] = '\0';
+	xdata.len += 2;
+
+	anchor = anchor_lump(msg, msg->unparsed - msg->buf, 0, 0);
+	if(anchor == 0) {
+		LM_ERR("can't get anchor\n");
+		return -1;
+	}
+	if (insert_new_lump_before(anchor, xdata.s, xdata.len, 0) == 0) {
+		LM_ERR("cannot insert the new header [%.*s]\n", hdr->len, hdr->s);
+		return -1;
+	}
+	return 0;
+}
+
+/**
+ *
+ */
+int auth_xkeys_check(sip_msg_t* msg, str *hdr, str *key,
+		str *alg, str *data)
+{
+	hdr_field_t *hf;
+	str xdata;
+	auth_xkey_t *itc;
+	char xout[SHA512_DIGEST_STRING_LENGTH];
+	str hbody;
+
+	if(_auth_xkeys_list==NULL || *_auth_xkeys_list==NULL) {
+		LM_ERR("no stored keys\n");
+		return -1;
+	}
+	if(parse_headers(msg, HDR_EOH_F, 0)<0) {
+		LM_ERR("error parsing headers\n");
+		return -1;
+	}
+
+	for (hf=msg->headers; hf; hf=hf->next) {
+		if (cmp_hdrname_str(&hf->name, hdr)==0)
+			break;
+	}
+	if(hf==NULL) {
+		LM_DBG("no header with name [%.*s]\n", hdr->len, hdr->s);
+		return -1;
+	}
+	if(hf->body.len<=0) {
+		LM_DBG("empty header with name [%.*s]\n", hdr->len, hdr->s);
+		return -1;
+	}
+	hbody = hf->body;
+	trim(&hbody);
+	if(hbody.len!=SHA256_DIGEST_STRING_LENGTH-1
+			&& hbody.len!=SHA384_DIGEST_STRING_LENGTH-1
+			&& hbody.len!=SHA512_DIGEST_STRING_LENGTH-1) {
+		LM_DBG("not maching digest size for [%.*s]\n",
+				hf->body.len, hf->body.s);
+		return -1;
+	}
+
+	for(itc = *_auth_xkeys_list; itc; itc = itc->next_id) {
+		if(itc->kid.len==key->len
+				&& strncasecmp(itc->kid.s, key->s, key->len)==0)
+			break;
+	}
+	if(itc==NULL) {
+		LM_DBG("no key chain id [%.*s]\n", key->len, key->s);
+		return -1;
+	}
+	xdata.s = pv_get_buffer();
+	for(; itc; itc = itc->next) {
+		xdata.len = data->len + itc->kvalue.len + 1;
+		if(xdata.len + 1 >= pv_get_buffer_size()) {
+			LM_WARN("size of data and key is too big - ignoring\n");
+			continue;
+		}
+		strncpy(xdata.s, itc->kvalue.s, itc->kvalue.len);
+		xdata.s[itc->kvalue.len] = ':';
+		strncpy(xdata.s + itc->kvalue.len + 1, data->s, data->len);
+		if(alg->len==6 && strncasecmp(alg->s, "sha256", 6)==0) {
+			if(hbody.len!=SHA256_DIGEST_STRING_LENGTH-1) {
+				LM_DBG("not maching sha256 digest size for [%.*s]\n",
+						hf->body.len, hf->body.s);
+				return -1;
+			}
+			compute_sha256(xout, (u_int8_t*)xdata.s, xdata.len);
+			if(strncasecmp(xout, hbody.s, hbody.len)==0) {
+				LM_DBG("no digest sha256 matched for key [%.*s:%.*s]\n",
+						key->len, key->s, itc->kname.len, itc->kname.s);
+				return 0;
+			}
+		} else if(alg->len==6 && strncasecmp(alg->s, "sha384", 6)==0) {
+			if(hbody.len!=SHA384_DIGEST_STRING_LENGTH-1) {
+				LM_DBG("not maching sha384 digest size for [%.*s]\n",
+						hf->body.len, hf->body.s);
+				return -1;
+			}
+			compute_sha384(xout, (u_int8_t*)xdata.s, xdata.len);
+			if(strncasecmp(xout, hbody.s, hbody.len)==0) {
+				LM_DBG("no digest sha384 matched for key [%.*s:%.*s]\n",
+						key->len, key->s, itc->kname.len, itc->kname.s);
+				return 0;
+			}
+		} else if(alg->len==6 && strncasecmp(alg->s, "sha512", 6)==0) {
+			if(hbody.len!=SHA512_DIGEST_STRING_LENGTH-1) {
+				LM_DBG("not maching sha512 digest size for [%.*s]\n",
+						hf->body.len, hf->body.s);
+				return -1;
+			}
+			compute_sha512(xout, (u_int8_t*)xdata.s, xdata.len);
+			if(strncasecmp(xout, hbody.s, hbody.len)==0) {
+				LM_DBG("no digest sha512 matched for key [%.*s:%.*s]\n",
+						key->len, key->s, itc->kname.len, itc->kname.s);
+				return 0;
+			}
+		} else {
+			LM_ERR("unknown algorithm [%.*s]\n", alg->len, alg->s);
+			return -1;
+		}
+	}
+
+	LM_DBG("no digest matched for key [%.*s]\n", key->len, key->s);
+	return -1;
+}
+
+
+static const char* auth_xkeys_rpc_list_doc[2] = {
+	"List existing keys",
+	0
+};
+
+/*
+ * RPC command to list the keys
+ */
+static void auth_xkeys_rpc_list(rpc_t* rpc, void* ctx)
+{
+	void* th;
+	void* ih;
+	void* vh;
+	auth_xkey_t *itc;
+	auth_xkey_t *itd;
+
+	if(_auth_xkeys_list==NULL || *_auth_xkeys_list==NULL) {
+		rpc->fault(ctx, 500, "No keys");
+		return;
+	}
+	/* add entry node */
+	if (rpc->add(ctx, "{", &th) < 0) {
+		rpc->fault(ctx, 500, "Internal error root reply");
+		return;
+	}
+	for(itc = *_auth_xkeys_list; itc; itc = itc->next_id) {
+		if(rpc->struct_add(th, "S[",
+					"KID", &itc->kid,
+					"KEYS",  &ih)<0) {
+			rpc->fault(ctx, 500, "Internal error keys array");
+			return;
+		}
+
+		for(itd=itc; itd; itd = itd->next) {
+			if(rpc->struct_add(ih, "{",
+						"KEY", &vh)<0) {
+				rpc->fault(ctx, 500, "Internal error creating keys data");
+				return;
+			}
+			if(rpc->struct_add(vh, "SDd",
+						"NAME",  &itd->kname,
+						"VALUE", &itd->kvalue,
+						"EXPIRES", itd->kexpires)<0)
+			{
+				rpc->fault(ctx, 500, "Internal error creating dest struct");
+				return;
+			}
+		}
+	}
+	return;
+}
+
+static const char* auth_xkeys_rpc_set_doc[2] = {
+	"Set expires of existing key or add a new key",
+	0
+};
+
+/*
+ * RPC command to set the expires of a key or add a new key
+ */
+static void auth_xkeys_rpc_set(rpc_t* rpc, void* ctx)
+{
+	auth_xkey_t tmp;
+	auth_xkey_t *itc;
+
+	memset(&tmp, 0, sizeof(auth_xkey_t));
+
+	if(rpc->scan(ctx, ".SSSd", &tmp.kid, &tmp.kname,
+				&tmp.kvalue, &tmp.kexpires)<4)
+	{
+		rpc->fault(ctx, 500, "Invalid Parameters");
+		return;
+	}
+	for(itc = *_auth_xkeys_list; itc; itc = itc->next_id) {
+		if(itc->kid.len==tmp.kid.len
+				&& strncasecmp(itc->kid.s, tmp.kid.s, tmp.kid.len)==0)
+			break;
+	}
+	if(itc==NULL) {
+		LM_DBG("no key chain id [%.*s]\n", tmp.kid.len, tmp.kid.s);
+		/* add one */
+		if(authx_xkey_insert(&tmp)<0) {
+			LM_ERR("unable to insert the key [%.*s:%.*s]\n",
+				tmp.kid.len, tmp.kid.s, tmp.kname.len, tmp.kname.s);
+			rpc->fault(ctx, 500, "Insert failure");
+			return;
+		}
+		return;
+	}
+	itc->kexpires = time(NULL) + tmp.kexpires;
+	return;
+}
+
+rpc_export_t auth_xkeys_rpc_cmds[] = {
+	{"auth_xkeys_.list",   auth_xkeys_rpc_list,
+		auth_xkeys_rpc_list_doc,   0},
+	{"auth_xkeys_.set",   auth_xkeys_rpc_set,
+		auth_xkeys_rpc_set_doc,   0},
+	{0, 0, 0, 0}
+};
+
+/**
+ *
+ */
+int auth_xkeys_init_rpc(void)
+{
+	if (rpc_register_array(auth_xkeys_rpc_cmds)!=0)
+	{
+		LM_ERR("failed to register RPC commands\n");
+		return -1;
+	}
+	return 0;
+}
diff --git a/modules/auth_xkeys/auth_xkeys.h b/modules/auth_xkeys/auth_xkeys.h
new file mode 100644
index 0000000..1381928
--- /dev/null
+++ b/modules/auth_xkeys/auth_xkeys.h
@@ -0,0 +1,35 @@
+/**
+ * Copyright (C) 2015 Daniel-Constantin Mierla (asipto.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _AUTH_XKEYS_H_
+#define _AUTH_XKEYS_H_
+
+#include "../../str.h"
+
+int authx_xkey_add_params(str *sparam);
+int auth_xkeys_add(sip_msg_t* msg, str *hdr, str *key,
+		str *alg, str *data);
+int auth_xkeys_check(sip_msg_t* msg, str *hdr, str *key,
+		str *alg, str *data);
+int auth_xkeys_init_rpc(void);
+
+#endif
diff --git a/modules/auth_xkeys/auth_xkeys_mod.c b/modules/auth_xkeys/auth_xkeys_mod.c
new file mode 100644
index 0000000..9443de1
--- /dev/null
+++ b/modules/auth_xkeys/auth_xkeys_mod.c
@@ -0,0 +1,212 @@
+/**
+ * Copyright (C) 2015 Daniel-Constantin Mierla (asipto.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../../sr_module.h"
+#include "../../dprint.h"
+#include "../../ut.h"
+#include "../../pvar.h"
+#include "../../mod_fix.h"
+#include "../../timer_proc.h"
+#include "../../route_struct.h"
+
+#include "auth_xkeys.h"
+
+MODULE_VERSION
+
+
+static int  mod_init(void);
+static int  child_init(int);
+static void mod_destroy(void);
+
+int authx_xkey_param(modparam_t type, void* val);
+
+static int w_auth_xkeys_add(sip_msg_t* msg, char* hdr, char* key,
+		char* alg, char* data);
+static int fixup_auth_xkeys_add(void** param, int param_no);
+static int w_auth_xkeys_check(sip_msg_t* msg, char* hdr, char* key,
+		char* alg, char* data);
+static int fixup_auth_xkeys_check(void** param, int param_no);
+
+/* timer for cleaning up the expired keys */
+/* int auth_xkeys_timer_mode = 0; */
+
+
+static cmd_export_t cmds[]={
+	{"auth_xkeys_add", (cmd_function)w_auth_xkeys_add,
+		4, fixup_auth_xkeys_add,
+		0, ANY_ROUTE},
+	{"auth_xkeys_check", (cmd_function)w_auth_xkeys_check,
+		4, fixup_auth_xkeys_check,
+		0, ANY_ROUTE},
+	{0, 0, 0, 0, 0, 0}
+};
+
+static param_export_t params[]={
+	{"xkey",           PARAM_STRING|USE_FUNC_PARAM, (void*)authx_xkey_param},
+	/* {"timer_mode",     PARAM_INT,   &auth_xkeys_timer_mode}, */
+	{0, 0, 0}
+};
+
+struct module_exports exports = {
+	"auth_xkeys",
+	DEFAULT_DLFLAGS, /* dlopen flags */
+	cmds,
+	params,
+	0,
+	0,              /* exported MI functions */
+	0,              /* exported pseudo-variables */
+	0,              /* extra processes */
+	mod_init,       /* module initialization function */
+	0,              /* response function */
+	mod_destroy,    /* destroy function */
+	child_init      /* per child init function */
+};
+
+
+
+/**
+ * init module function
+ */
+static int mod_init(void)
+{
+	if(auth_xkeys_init_rpc()<0)
+	{
+		LM_ERR("failed to register RPC commands\n");
+		return -1;
+	}
+	return 0;
+}
+
+/**
+ * @brief Initialize async module children
+ */
+static int child_init(int rank)
+{
+	return 0;
+}
+/**
+ * destroy module function
+ */
+static void mod_destroy(void)
+{
+}
+
+
+static int w_auth_xkeys_add(sip_msg_t* msg, char* hdr, char* key,
+		char* alg, char* data)
+{
+	str shdr;
+	str skey;
+	str salg;
+	str sdata;
+
+	if(fixup_get_svalue(msg, (gparam_t*)hdr, &shdr)!=0)
+	{
+		LM_ERR("cannot get the header name\n");
+		return -1;
+	}
+	if(fixup_get_svalue(msg, (gparam_t*)key, &skey)!=0)
+	{
+		LM_ERR("cannot get the key id\n");
+		return -1;
+	}
+	if(fixup_get_svalue(msg, (gparam_t*)alg, &salg)!=0)
+	{
+		LM_ERR("cannot get the algorithm\n");
+		return -1;
+	}
+	if(fixup_get_svalue(msg, (gparam_t*)data, &sdata)!=0)
+	{
+		LM_ERR("cannot get the hasing data\n");
+		return -1;
+	}
+
+	if(auth_xkeys_add(msg, &shdr, &skey, &salg, &sdata)<0)
+		return -1;
+
+	return 1;
+}
+
+static int w_auth_xkeys_check(sip_msg_t* msg, char* hdr, char* key,
+		char* alg, char* data)
+{
+	str shdr;
+	str skey;
+	str salg;
+	str sdata;
+
+	if(fixup_get_svalue(msg, (gparam_t*)hdr, &shdr)!=0)
+	{
+		LM_ERR("cannot get the header name\n");
+		return -1;
+	}
+	if(fixup_get_svalue(msg, (gparam_t*)key, &skey)!=0)
+	{
+		LM_ERR("cannot get the key id\n");
+		return -1;
+	}
+	if(fixup_get_svalue(msg, (gparam_t*)alg, &salg)!=0)
+	{
+		LM_ERR("cannot get the algorithm\n");
+		return -1;
+	}
+	if(fixup_get_svalue(msg, (gparam_t*)data, &sdata)!=0)
+	{
+		LM_ERR("cannot get the hasing data\n");
+		return -1;
+	}
+
+	if(auth_xkeys_check(msg, &shdr, &skey, &salg, &sdata)<0)
+		return -1;
+
+	return 1;
+}
+
+static int fixup_auth_xkeys_add(void** param, int param_no)
+{
+	if(fixup_spve_null(param, 1)<0)
+		return -1;
+	return 0;
+}
+
+static int fixup_auth_xkeys_check(void** param, int param_no)
+{
+	if(fixup_spve_null(param, 1)<0)
+		return -1;
+	return 0;
+}
+
+int authx_xkey_param(modparam_t type, void* val)
+{
+	str s;
+
+	if(val==NULL)
+		return -1;
+	s.s = (char*)val;
+	s.len = strlen(s.s);
+	return authx_xkey_add_params(&s);
+}
diff --git a/modules/auth_xkeys/doc/Makefile b/modules/auth_xkeys/doc/Makefile
new file mode 100644
index 0000000..7efb7b9
--- /dev/null
+++ b/modules/auth_xkeys/doc/Makefile
@@ -0,0 +1,4 @@
+docs = auth_xkeys.xml
+
+docbook_dir = ../../../docbook
+include $(docbook_dir)/Makefile.module
diff --git a/modules/auth_xkeys/doc/auth_xkeys.xml b/modules/auth_xkeys/doc/auth_xkeys.xml
new file mode 100644
index 0000000..f77f913
--- /dev/null
+++ b/modules/auth_xkeys/doc/auth_xkeys.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding='ISO-8859-1'?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+<!-- Include general documentation entities -->
+<!ENTITY % docentities SYSTEM "../../../docbook/entities.xml">
+%docentities;
+
+]>
+
+<book xmlns:xi="http://www.w3.org/2001/XInclude">
+    <bookinfo>
+	<title>AUTH_XKEYS Module</title>
+	<productname class="trade">kamailio.org</productname>
+	<authorgroup>
+	    <author>
+		<firstname>Daniel-Constantin</firstname>
+		<surname>Mierla</surname>
+		<email>miconda at gmail.com</email>
+	    </author>
+	    <editor>
+		<firstname>Daniel-Constantin</firstname>
+		<surname>Mierla</surname>
+		<email>miconda at gmail.com</email>
+	    </editor>
+	</authorgroup>
+	<copyright>
+	    <year>2015</year>
+	    <holder>asipto.com</holder>
+	</copyright>
+    </bookinfo>
+    <toc></toc>
+    
+    <xi:include href="auth_xkeys_admin.xml"/>
+
+</book>
diff --git a/modules/auth_xkeys/doc/auth_xkeys_admin.xml b/modules/auth_xkeys/doc/auth_xkeys_admin.xml
new file mode 100644
index 0000000..2b46674
--- /dev/null
+++ b/modules/auth_xkeys/doc/auth_xkeys_admin.xml
@@ -0,0 +1,207 @@
+<?xml version="1.0" encoding='ISO-8859-1'?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+<!-- Include general documentation entities -->
+<!ENTITY % docentities SYSTEM "../../../docbook/entities.xml">
+%docentities;
+
+]>
+<!-- Module User's Guide -->
+
+<chapter>
+	
+	<title>&adminguide;</title>
+	
+	<section>
+	<title>Overview</title>
+	<para>
+		This module provides a custom mechanism to authenticate a SIP entity
+		using a list of shared keys.
+	</para>
+	<para>
+		It is similar to the API key based authentication used by many web
+		services. In short, the sender adds a particular header with a hash
+		token computed with the shared key and some values from the SIP
+		request (e.g., local IP, From/To/R-URI username, Call-ID, CSeq). The
+		receiver will check the hash value and decide whether the SIP message
+		is authenticated or not. The sender and receiver have to agree
+		beforehand on the name of the server, shared secret, algorithm to be
+		used and what data is going to be hashed.
+	</para>
+	<para>
+		The module is designed to work with many shared keys on the same
+		group, for more flexibility in adding/removing keys. The last added
+		key in the group is used to add the header, but older ones are used
+		for matching the hash value. That allows to change the active shared
+		key without affecting ongoing traffic. If one decides to use a new
+		share key, add it first to receiver (it will still authenticate with
+		older key) and then to the sender. Once both nodes are provisioned
+		with the new key, the older one can be removed.
+	</para>
+	<para>
+		For proper protection, it is recommended to use this
+		authentication mechanism over a secure channel (e.g., TLS, VPN,
+		private network).
+	</para>
+	<para>
+		The benefit is avoiding the extra traffic and processing required
+		by WWW-Digest authentication schema (no more 401/407 and a follow up
+		request with credentials).
+	</para>
+	<para>
+		Another goal is to provide more elasticity for scalability needs of
+		the core SIP network nodes. Most of the nodes in the core network or
+		the interconnecting peers trust each other based on IP address. But
+		adding a new node requires updates to the exiting ones to trust the
+		IP address of the new node. On large deployments, that can become
+		rather complex. For example, as a replacement for IP trust
+		relationships, the sender can hash the local IP with the secret
+		shared key, add it in the header and the receiver will check if the
+		source ip hased with the key results in the same value.
+	</para>
+	<para>
+		Not being a challenge-reply mechanism, this can be used to authenticate
+		SIP responses from trusted peers.
+	</para>
+	</section>
+
+	<section>
+	<title>Dependencies</title>
+	<section>
+		<title>&kamailio; Modules</title>
+		<para>
+		The following modules must be loaded before this module:
+			<itemizedlist>
+			<listitem>
+			<para>
+				<emphasis>none</emphasis>.
+			</para>
+			</listitem>
+			</itemizedlist>
+		</para>
+	</section>
+	<section>
+		<title>External Libraries or Applications</title>
+		<para>
+		The following libraries or applications must be installed before running
+		&kamailio; with this module loaded:
+			<itemizedlist>
+			<listitem>
+			<para>
+				<emphasis>none</emphasis>
+			</para>
+			</listitem>
+			</itemizedlist>
+		</para>
+	</section>
+	</section>
+	<section>
+	<title>Parameters</title>
+	<section id="auth_xkeys.p.xkey">
+		<title><varname>xkey</varname> (str)</title>
+		<para>
+			Specify the attributes for a shared secret. The value is in
+			the format 'name1=value1;name2=value2;...'. The attributes can be:
+		</para>
+			<itemizedlist>
+			<listitem>
+			<para>
+				<emphasis>id</emphasis> - the id of the group for keys
+			</para>
+			</listitem>
+			<listitem>
+			<para>
+				<emphasis>name</emphasis> - the name of the key within group
+			</para>
+			</listitem>
+			<listitem>
+			<para>
+				<emphasis>value</emphasis> - the value of the key
+			</para>
+			</listitem>
+			<listitem>
+			<para>
+				<emphasis>expires</emphasis> - expiration time (seconds)
+			</para>
+			</listitem>
+			</itemizedlist>
+		<para>
+		<emphasis>
+			Default value is empty.
+		</emphasis>
+		</para>
+		<example>
+		<title>Set <varname>xkey</varname> parameter</title>
+		<programlisting format="linespecific">
+...
+modparam("auth_xkeys", "xkey", "id=abc;name=xyz;value=secret;expires=72000")
+...
+</programlisting>
+		</example>
+	</section>
+	</section>
+
+	<section>
+	<title>Functions</title>
+	<section id="auth_xkeys.f.auth_xkeys_add">
+	    <title>
+		<function moreinfo="none">auth_xkeys_add(hdr, kid, alg, data)</function>
+	    </title>
+	    <para>
+		Add a header computed with the first key in the group kid, hasing with
+		algorithm alg over the content of parameter data. The parameters can
+		include variables.
+		</para>
+		<para>
+		The algorithm can be: sha256, sha384, sha512.
+		</para>
+		<para>
+		This function can be used from ANY_ROUTE.
+		</para>
+		<example>
+		<title><function>auth_xkeys_add</function> usage</title>
+		<programlisting format="linespecific">
+...
+auth_xkeys_add("X-My-Key", "abc", "sha256", "$Ri:$fu:$ru:$hdr(CSeq)");
+...
+</programlisting>
+	    </example>
+	</section>
+
+	<section id="auth_xkeys.f.auth_xkeys_check">
+	    <title>
+		<function moreinfo="none">auth_xkeys_check(hdr, kid, alg, data)</function>
+	    </title>
+	    <para>
+		Check if the value of header hdr matches the value computed with the
+		first key in the group kid, hasing with algorithm alg over the content
+		of parameter data. The parameters can include variables.
+		</para>
+		<para>
+		The algorithm can be: sha256, sha384, sha512.
+		</para>
+		<para>
+		Note that the header is not removed by the function, it is recommended
+		to remove it if sending to untrusted destination.
+		</para>
+		<para>
+		This function can be used from ANY_ROUTE.
+		</para>
+		<example>
+		<title><function>auth_xkeys_check</function> usage</title>
+		<programlisting format="linespecific">
+...
+if(!auth_xkeys_add("X-My-Key", "abc", "sha256", "$si:$fu:$ru:$hdr(CSeq)")) {
+    send_reply("403", "Forbidden");
+    exit;
+}
+remove_hf("X-My-Key");
+...
+</programlisting>
+	    </example>
+	</section>
+
+	</section>
+</chapter>
+
diff --git a/modules/avp/Makefile b/modules/avp/Makefile
index 54e2ae1..19de30a 100644
--- a/modules/avp/Makefile
+++ b/modules/avp/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # print example module makefile
 #
diff --git a/modules/avpops/Makefile b/modules/avpops/Makefile
index 1d77601..faf1bd1 100644
--- a/modules/avpops/Makefile
+++ b/modules/avpops/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # avpops module makefile
 #
diff --git a/modules/avpops/avpops.c b/modules/avpops/avpops.c
index 1f23337..ac079ad 100644
--- a/modules/avpops/avpops.c
+++ b/modules/avpops/avpops.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2004-2006 Voice Sistem SRL
  *
  * This file is part of Kamailio.
@@ -19,13 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  *
- * History:
- * ---------
- *  2004-10-04  first version (ramona)
- *  2004-11-15  added support for db schemes for avp_db_load (ramona)
- *  2004-11-17  aligned to new AVP core global aliases (ramona)
- *  2005-01-30  "fm" (fast match) operator added (ramona)
- *  2005-01-30  avp_copy (copy/move operation) added (ramona)
  */
 
 
diff --git a/modules/avpops/avpops_db.c b/modules/avpops/avpops_db.c
index 1c0103f..4f5e446 100644
--- a/modules/avpops/avpops_db.c
+++ b/modules/avpops/avpops_db.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2004-2006 Voice Sistem SRL
  *
  * This file is part of Kamailio.
@@ -19,10 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  *
- * History:
- * ---------
- *  2004-10-04  first version (ramona)
- *  2004-11-11  added support for db schemes for avp_db_load (ramona)
  */
 
 
diff --git a/modules/avpops/avpops_db.h b/modules/avpops/avpops_db.h
index fbd21f3..c305f7b 100644
--- a/modules/avpops/avpops_db.h
+++ b/modules/avpops/avpops_db.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2004-2006 Voice Sistem SRL
  *
  * This file is part of Kamailio.
@@ -19,10 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  *
- * History:
- * ---------
- *  2004-10-04  first version (ramona)
- *  2004-11-11  added support for db schemes for avp_db_load (ramona)
  */
 
 
diff --git a/modules/avpops/avpops_impl.c b/modules/avpops/avpops_impl.c
index 5d25202..5d1351a 100644
--- a/modules/avpops/avpops_impl.c
+++ b/modules/avpops/avpops_impl.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2004-2006 Voice Sistem SRL
  *
  * This file is part of Kamailio.
@@ -19,11 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  *
- * History:
- * ---------
- *  2004-10-04  first version (ramona)
- *  2005-01-30  "fm" (fast match) operator added (ramona)
- *  2005-01-30  avp_copy (copy/move operation) added (ramona)
  */
 
 #include <stdlib.h>
diff --git a/modules/avpops/avpops_impl.h b/modules/avpops/avpops_impl.h
index 7194476..3e80521 100644
--- a/modules/avpops/avpops_impl.h
+++ b/modules/avpops/avpops_impl.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2004-2006 Voice Sistem SRL
  *
  * This file is part of Kamailio.
@@ -19,9 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  *
- * History:
- * ---------
- *  2004-10-04  first version (ramona)
  */
 
 
diff --git a/modules/avpops/avpops_parse.c b/modules/avpops/avpops_parse.c
index 42c014f..e1e6da3 100644
--- a/modules/avpops/avpops_parse.c
+++ b/modules/avpops/avpops_parse.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2004-2006 Voice Sistem SRL
  *
  * This file is part of Kamailio.
@@ -19,11 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  *
- * History:
- * ---------
- *  2004-10-04  first version (ramona)
- *  2004-11-11  DB scheme added (ramona)
- *  2004-11-17  aligned to new AVP core global aliases (ramona)
  */
 
 
diff --git a/modules/avpops/avpops_parse.h b/modules/avpops/avpops_parse.h
index 5b8a573..801dc23 100644
--- a/modules/avpops/avpops_parse.h
+++ b/modules/avpops/avpops_parse.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2004-2006 Voice Sistem SRL
  *
  * This file is part of Kamailio.
@@ -19,9 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  *
- * History:
- * ---------
- *  2004-10-04  first version (ramona)
  */
 
 
diff --git a/modules/benchmark/Makefile b/modules/benchmark/Makefile
index 4afd9fa..e65a0c0 100644
--- a/modules/benchmark/Makefile
+++ b/modules/benchmark/Makefile
@@ -1,4 +1,3 @@
-# $Id: Makefile,v 1.1.1.1 2005/06/13 16:47:32 bogdan_iancu Exp $
 #
 # User aliases
 #
diff --git a/modules/blst/Makefile b/modules/blst/Makefile
index 152bc26..b08f187 100644
--- a/modules/blst/Makefile
+++ b/modules/blst/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 
 include ../../Makefile.defs
diff --git a/modules/blst/blst.c b/modules/blst/blst.c
index 1d959b0..d1f1df0 100644
--- a/modules/blst/blst.c
+++ b/modules/blst/blst.c
@@ -1,5 +1,4 @@
-/*$Id$
- *
+/*
  * Copyright (C) 2007 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -14,13 +13,11 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/*
- *
- * Blacklist related script functions
+
+/*! \file
+ * \brief
+ * blst module :: Blacklist related script functions
  *
- * History:
- * -------
- *  2007-07-30  created by andrei
  */
 
 
diff --git a/modules/call_control/Makefile b/modules/call_control/Makefile
index 1d349fa..8df7ba5 100644
--- a/modules/call_control/Makefile
+++ b/modules/call_control/Makefile
@@ -1,4 +1,3 @@
-# $Id: Makefile,v 1.1 2005/12/12 08:57:22 dan Exp $
 #
 # call_control module makefile
 #
diff --git a/modules/call_control/README b/modules/call_control/README
index 66c6c01..28f5f1f 100644
--- a/modules/call_control/README
+++ b/modules/call_control/README
@@ -10,7 +10,7 @@ Dan Pascu
 
    <dan at ag-projects.com>
 
-   Copyright � 2005-2008 Dan Pascu
+   Copyright (c) 2005-2008 Dan Pascu
      __________________________________________________________________
 
    Table of Contents
@@ -151,6 +151,7 @@ Chapter 1. Admin Guide
 4.1. Kamailio Modules
 
    The following modules must be loaded before this module:
+     * pv module
      * dialog module
 
 4.2. External Libraries or Applications
diff --git a/modules/call_control/doc/call_control_admin.xml b/modules/call_control/doc/call_control_admin.xml
index bce0916..b9d1709 100644
--- a/modules/call_control/doc/call_control_admin.xml
+++ b/modules/call_control/doc/call_control_admin.xml
@@ -139,7 +139,12 @@
         <itemizedlist>
           <listitem>
             <para>
-              <emphasis>dialog</emphasis> module 
+              <emphasis>pv</emphasis> module
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              <emphasis>dialog</emphasis> module
             </para>
           </listitem>
         </itemizedlist>
diff --git a/modules/carrierroute/Makefile b/modules/carrierroute/Makefile
index 4117bbb..957be8c 100644
--- a/modules/carrierroute/Makefile
+++ b/modules/carrierroute/Makefile
@@ -1,4 +1,3 @@
-# $Id: Makefile,v 1.6 2003/05/23 15:43:43 andrei Exp $
 #
 # carrierroute Makefile
 #
diff --git a/modules/carrierroute/carrierroute.c b/modules/carrierroute/carrierroute.c
index 01ce734..a9cc847 100644
--- a/modules/carrierroute/carrierroute.c
+++ b/modules/carrierroute/carrierroute.c
@@ -78,7 +78,7 @@ const str CR_EMPTY_PREFIX = str_init("null");
 
 int mode = 0;
 int cr_match_mode = 10;
-
+int cr_avoid_failed_dests = 1;
 
 /************* Declaration of Interface Functions **************************/
 static int mod_init(void);
@@ -108,17 +108,18 @@ static param_export_t params[]= {
 	carrierfailureroute_DB_COLS
 	carrier_name_DB_COLS
 	domain_name_DB_COLS
-	{"subscriber_table",       PARAM_STR, &subscriber_table },
-	{"subscriber_user_col",    PARAM_STR, &subscriber_username_col },
-	{"subscriber_domain_col",  PARAM_STR, &subscriber_domain_col },
-	{"subscriber_carrier_col", PARAM_STR, &cr_preferred_carrier_col },
-	{"config_source",          PARAM_STRING, &config_source },
-	{"default_tree",           PARAM_STR, &default_tree },
-	{"config_file",            PARAM_STRING, &config_file },
-	{"use_domain",             INT_PARAM, &default_carrierroute_cfg.use_domain },
-	{"fallback_default",       INT_PARAM, &default_carrierroute_cfg.fallback_default },
-	{"fetch_rows",             INT_PARAM, &default_carrierroute_cfg.fetch_rows },
-	{"match_mode",             INT_PARAM, &cr_match_mode },
+	{"subscriber_table",          PARAM_STR, &subscriber_table },
+	{"subscriber_user_col",       PARAM_STR, &subscriber_username_col },
+	{"subscriber_domain_col",     PARAM_STR, &subscriber_domain_col },
+	{"subscriber_carrier_col",    PARAM_STR, &cr_preferred_carrier_col },
+	{"config_source",             PARAM_STRING, &config_source },
+	{"default_tree",              PARAM_STR, &default_tree },
+	{"config_file",               PARAM_STRING, &config_file },
+	{"use_domain",                INT_PARAM, &default_carrierroute_cfg.use_domain },
+	{"fallback_default",          INT_PARAM, &default_carrierroute_cfg.fallback_default },
+	{"fetch_rows",                INT_PARAM, &default_carrierroute_cfg.fetch_rows },
+	{"match_mode",                INT_PARAM, &cr_match_mode },
+	{"avoid_failed_destinations", INT_PARAM, &cr_avoid_failed_dests },
 	{0,0,0}
 };
 
@@ -180,6 +181,11 @@ static int mod_init(void) {
 		return -1;
 	}
 
+	if (cr_avoid_failed_dests != 0 && cr_avoid_failed_dests != 1) {
+		LM_ERR("avoid_failed_dests must be 0 or 1");
+		return -1;
+	}
+
 	if (strcmp(config_source, "db") == 0) {
 		mode = CARRIERROUTE_MODE_DB;
 
diff --git a/modules/carrierroute/carrierroute.h b/modules/carrierroute/carrierroute.h
index bbcda95..83e6da1 100644
--- a/modules/carrierroute/carrierroute.h
+++ b/modules/carrierroute/carrierroute.h
@@ -53,6 +53,7 @@ extern const str CR_EMPTY_PREFIX;
 
 extern int mode;
 extern int cr_match_mode;
+extern int cr_avoid_failed_dests;
 
 extern int_str cr_uris_avp;
 
diff --git a/modules/carrierroute/cr_func.c b/modules/carrierroute/cr_func.c
index 70afe62..6d026c4 100644
--- a/modules/carrierroute/cr_func.c
+++ b/modules/carrierroute/cr_func.c
@@ -494,29 +494,30 @@ static int rewrite_on_rule(struct route_flags *rf_head, flag_t flags, str * dest
 				rr->next!= NULL && rr->dice_to <= prob ; rr = rr->next) {}
 
 			//LM_DBG("CR: candidate hashed destination is: <%.*s>\n", rr->host.len, rr->host.s);
-
-			if (is_route_type(FAILURE_ROUTE) && (mode == CARRIERROUTE_MODE_DB) ){
-				build_used_uris_list(used_dests, &no_dests);
-
-				if (cr_uri_already_used(rr->host, used_dests, no_dests) ) {
-					//LM_DBG("CR: selecting new destination !!! \n");
-					for (rr = rf->rule_list;
-								rr!= NULL && cr_uri_already_used(rr->host, used_dests, no_dests); rr = rr->next) {}
-					/* are there any destinations that were not already used? */
-					if (rr == NULL) {
-						LM_NOTICE("All gateways from this group were already used\n");
-						return -1;
+			if (cr_avoid_failed_dests) {
+				if (is_route_type(FAILURE_ROUTE) && (mode == CARRIERROUTE_MODE_DB) ){
+					build_used_uris_list(used_dests, &no_dests);
+
+					if (cr_uri_already_used(rr->host, used_dests, no_dests) ) {
+						//LM_DBG("CR: selecting new destination !!! \n");
+						for (rr = rf->rule_list;
+									rr!= NULL && cr_uri_already_used(rr->host, used_dests, no_dests); rr = rr->next) {}
+						/* are there any destinations that were not already used? */
+						if (rr == NULL) {
+							LM_NOTICE("All gateways from this group were already used\n");
+							return -1;
+						}
+
+						/* this is a hack: we do not take probabilities into consideration if first destination
+						 * was previously tried */
+
+						do {
+							int rule_no = rand() % rf->rule_num;
+							//LM_DBG("CR: trying rule_no=%d \n", rule_no);
+							for (rr = rf->rule_list; (rule_no > 0) && (rr->next!=NULL) ; rule_no-- , rr = rr->next) {}
+						} while (cr_uri_already_used(rr->host, used_dests, no_dests));
+						LM_DBG("CR: candidate selected destination is: <%.*s>\n", rr->host.len, rr->host.s);
 					}
-
-					/* this is a hack: we do not take probabilities into consideration if first destination
-					 * was previously tried */
-
-					do {
-						int rule_no = rand() % rf->rule_num;
-						//LM_DBG("CR: trying rule_no=%d \n", rule_no);
-						for (rr = rf->rule_list; (rule_no > 0) && (rr->next!=NULL) ; rule_no-- , rr = rr->next) {}
-					} while (cr_uri_already_used(rr->host, used_dests, no_dests));
-					LM_DBG("CR: candidate selected destination is: <%.*s>\n", rr->host.len, rr->host.s);
 				}
 			}
 			/*This should be regarded as an ELSE branch for the if above
@@ -534,21 +535,22 @@ static int rewrite_on_rule(struct route_flags *rf_head, flag_t flags, str * dest
 				}
 			}
 
-			//LM_DBG("CR: destination is: <%.*s>\n", rr->host.len, rr->host.s);
-			cr_new_uri.s = rr->host;
-			/* insert used destination into avp, in case corresponding request fails and
-			 * another destination has to be used; this new destination must not be one
-			 * that failed before
-			 */
-
-			if (mode == CARRIERROUTE_MODE_DB){
-				if ( add_avp( AVP_VAL_STR | AVP_NAME_STR, cr_uris_avp, cr_new_uri) < 0){
-					LM_ERR("set AVP failed\n");
-					return -1;
+			if (cr_avoid_failed_dests) {
+				//LM_DBG("CR: destination is: <%.*s>\n", rr->host.len, rr->host.s);
+				cr_new_uri.s = rr->host;
+				/* insert used destination into avp, in case corresponding request fails and
+				 * another destination has to be used; this new destination must not be one
+				 * that failed before
+				 */
+
+				if (mode == CARRIERROUTE_MODE_DB){
+					if ( add_avp( AVP_VAL_STR | AVP_NAME_STR, cr_uris_avp, cr_new_uri) < 0){
+						LM_ERR("set AVP failed\n");
+						return -1;
+					}
+					//print_cr_uri_avp();
 				}
-				//print_cr_uri_avp();
 			}
-
 			break;
 		}
 		case alg_crc32_nofallback:
diff --git a/modules/carrierroute/doc/carrierroute_admin.xml b/modules/carrierroute/doc/carrierroute_admin.xml
index 2780114..dca543b 100644
--- a/modules/carrierroute/doc/carrierroute_admin.xml
+++ b/modules/carrierroute/doc/carrierroute_admin.xml
@@ -337,6 +337,29 @@ modparam("carrierroute", "match_mode", 10)
 </programlisting>
 		</example>
 	</section>
+
+	<section>
+		<title><varname>avoid_failed_destinations</varname> (integer)</title>
+		<para>
+		Integer parameter to toggle on/off the possibility that in the failurerouting cases 
+		destinations that previously failed are avoided. Possible values are 0 (off), 1 (on).
+		Also see cr_route section.
+		</para>
+		<para>
+		<emphasis>
+			Default value is <quote>1</quote>.
+		</emphasis>
+		</para>
+		<example>
+		<title>Set <varname>avoid_failed_destinations</varname> parameter</title>
+		<programlisting format="linespecific">
+...
+modparam("carrierroute", "avoid_failed_destinations", 0)
+...
+</programlisting>
+		</example>
+	</section>
+
 </section>
 
     <section>
@@ -414,7 +437,8 @@ cr_tree_rewrite_uri(tree, domain)
         number of channels.
 		</para>
 		<para>
-		The function pays special attention to the failurerouting cases, so that
+		Depending on the value of the avoid_failed_destinations module parameter,
+		the function pays special attention to the failurerouting cases, so that
 		any destination that has failed to provide a successful response will not
 		be reused in a subsequent call of cr_route. This situation can appear when
 		different route domains contain a set of common gateways.
diff --git a/modules/cdp/Makefile b/modules/cdp/Makefile
index ef185cd..7215b3d 100644
--- a/modules/cdp/Makefile
+++ b/modules/cdp/Makefile
@@ -1,3 +1,5 @@
+# cdp Makefile
+
 include ../../Makefile.defs
 auto_gen=
 NAME=cdp.so
diff --git a/modules/cdp/api_process.c b/modules/cdp/api_process.c
index 9516183..56ca2db 100644
--- a/modules/cdp/api_process.c
+++ b/modules/cdp/api_process.c
@@ -47,8 +47,10 @@
 #include "transaction.h"
 #include "receiver.h"
 #include "peerstatemachine.h"
+#include "cdp_stats.h"
 
 extern unsigned int* latency_threshold_p;	/**<max delay for Diameter call */
+extern struct cdp_counters_h cdp_cnts_h;
 
 handler_list *handlers = 0; /**< list of handlers */
 gen_lock_t *handlers_lock;	/**< lock for list of handlers */
@@ -108,8 +110,8 @@ int api_callback(peer *p,AAAMessage *msg,void* ptr)
             if (elapsed_msecs > *latency_threshold_p) {
             	LM_ERR("Received diameter response outside of threshold (%d) - %ld\n", *latency_threshold_p, elapsed_msecs);
             }
-            update_stat(replies_received, 1);
-            update_stat(replies_response_time, elapsed_msecs);
+	    counter_inc(cdp_cnts_h.replies_received);
+	    counter_add(cdp_cnts_h.replies_response_time, elapsed_msecs);
 			auto_drop = t->auto_drop;
 			if (t->cb){
 				(t->cb)(0,*(t->ptr),msg, elapsed_msecs);
diff --git a/modules/cdp/authstatemachine.c b/modules/cdp/authstatemachine.c
index a65bdc6..be8cbaf 100644
--- a/modules/cdp/authstatemachine.c
+++ b/modules/cdp/authstatemachine.c
@@ -145,7 +145,7 @@ void add_auth_session_timers(cdp_auth_session_t *x, AAAMessage *msg) {
         }
         set_4bytes(data, v);
         avp = AAACreateAVP(AVP_Authorization_Lifetime, AAA_AVP_FLAG_MANDATORY, 0, data, 4, AVP_DUPLICATE_DATA);
-        if (avp) AAAAddAVPToMessage(msg, avp, 0);
+        if (avp) AAAAddAVPToMessage(msg, avp, msg->avpList.tail);
     }
     if (x->lifetime != -1) {
         avp = AAAFindMatchingAVP(msg, 0, AVP_Auth_Grace_Period, 0, 0);
@@ -153,7 +153,7 @@ void add_auth_session_timers(cdp_auth_session_t *x, AAAMessage *msg) {
             v = x->grace_period;
             set_4bytes(data, v);
             avp = AAACreateAVP(AVP_Auth_Grace_Period, AAA_AVP_FLAG_MANDATORY, 0, data, 4, AVP_DUPLICATE_DATA);
-            if (avp) AAAAddAVPToMessage(msg, avp, 0);
+            if (avp) AAAAddAVPToMessage(msg, avp, msg->avpList.tail);
         }
     }
     avp = AAAFindMatchingAVP(msg, 0, AVP_Session_Timeout, 0, 0);
@@ -165,7 +165,7 @@ void add_auth_session_timers(cdp_auth_session_t *x, AAAMessage *msg) {
         }
         set_4bytes(data, v);
         avp = AAACreateAVP(AVP_Session_Timeout, AAA_AVP_FLAG_MANDATORY, 0, data, 4, AVP_DUPLICATE_DATA);
-        if (avp) AAAAddAVPToMessage(msg, avp, 0);
+        if (avp) AAAAddAVPToMessage(msg, avp, msg->avpList.tail);
     }
 }
 
@@ -243,14 +243,12 @@ inline int auth_client_statefull_sm_process(cdp_session_t* s, int event, AAAMess
                     //LM_INFO("state machine: i was in pending and i am going to open\n");
                     break;
                 case AUTH_EV_RECV_ANS_UNSUCCESS:
-                    x->state = AUTH_ST_DISCON;
-                    //LM_INFO("state machine: i was in pending and i am going to discon\n");
-                    Send_STR(s, msg);
-                    break;
+		    LM_DBG("In state AUTH_ST_PENDING and received AUTH_EV_RECV_ANS_UNSUCCESS - nothing to do but clean up session\n");
                 case AUTH_EV_SESSION_TIMEOUT:
                 case AUTH_EV_SERVICE_TERMINATED:
                 case AUTH_EV_SESSION_GRACE_TIMEOUT:
                     cdp_session_cleanup(s, NULL);
+		    s=0;
                     break;
 
                 default:
@@ -784,7 +782,8 @@ void Send_STR(cdp_session_t* s, AAAMessage* msg) {
     AAAAddAVPToMessage(str, avp, str->avpList.tail);
     //todo - add all the other avps
 
-    p = get_routing_peer(str);
+    /* we are already locked on the auth session*/
+    p = get_routing_peer(s, str);
 
     if (!p) {
         LM_ERR("unable to get routing peer in Send_STR \n");
@@ -822,7 +821,7 @@ void Send_ASR(cdp_session_t* s, AAAMessage* msg) {
     AAAAddAVPToMessage(asr, avp, asr->avpList.tail);
     //todo - add all the other avps
 
-    p = get_routing_peer(asr);
+    p = get_routing_peer(s, asr);
     if (!p) {
         LM_ERR("unable to get routing peer in Send_ASR \n");
         if (asr) AAAFreeMessage(&asr); //needed in frequency
diff --git a/modules/cdp/cdp_stats.c b/modules/cdp/cdp_stats.c
new file mode 100644
index 0000000..37087bc
--- /dev/null
+++ b/modules/cdp/cdp_stats.c
@@ -0,0 +1,49 @@
+#include "cdp_stats.h"
+
+struct cdp_counters_h cdp_cnts_h;
+enum sctp_info_req { CDP_AVG_RSP };
+
+static counter_val_t cdp_internal_stats(counter_handle_t h, void* what);
+
+counter_def_t cdp_cnt_defs[] = {
+    {&cdp_cnts_h.timeout, "timeout", 0, 0, 0,
+	"number of timeouts on CDP requests"},
+    {&cdp_cnts_h.replies_received, "replies_received", 0, 0, 0,
+	"total number of replies received"},
+    {&cdp_cnts_h.replies_response_time, "replies_response_time", 0, 0, 0,
+	"total time waiting for replies"},
+    {&cdp_cnts_h.queuelength, "queuelength", 0, 0, 0,
+	"current length of worker queue tasks"},
+    {0, "average_response_time", 0,
+	cdp_internal_stats, (void*) (long) CDP_AVG_RSP,
+	"average response time for CDP replies"},
+    {0, 0, 0, 0, 0, 0}
+};
+
+int cdp_init_counters() {
+    if (counter_register_array("cdp", cdp_cnt_defs) < 0)
+	goto error;
+    return 0;
+error:
+    return -1;
+}
+
+void cdp_destroy_counters() {
+    
+}
+
+/** helper function for some stats (which are kept internally).
+ */
+static counter_val_t cdp_internal_stats(counter_handle_t h, void* what) {
+    enum sctp_info_req w;
+
+    w = (int) (long) what;
+    switch (w) {
+	case CDP_AVG_RSP:
+	    if (counter_get_val(cdp_cnts_h.replies_received) == 0) 
+		return 0;
+	    else
+		return counter_get_val(cdp_cnts_h.replies_response_time)/counter_get_val(cdp_cnts_h.replies_received);
+    };
+    return 0;
+}
\ No newline at end of file
diff --git a/modules/cdp/cdp_stats.h b/modules/cdp/cdp_stats.h
new file mode 100644
index 0000000..f85f17a
--- /dev/null
+++ b/modules/cdp/cdp_stats.h
@@ -0,0 +1,18 @@
+#ifndef CDP_STATS_H
+#define	CDP_STATS_H
+
+#include "../../counters.h"
+
+struct cdp_counters_h {
+    counter_handle_t timeout;
+    counter_handle_t replies_received;
+    counter_handle_t replies_response_time;
+    counter_handle_t avg_response_time;
+    counter_handle_t queuelength;
+};
+
+int cdp_init_counters();
+void cdp_destroy_counters();
+
+#endif	/* CDP_STATS_H */
+
diff --git a/modules/cdp/config.h b/modules/cdp/config.h
index 394c3eb..35ee4c1 100644
--- a/modules/cdp/config.h
+++ b/modules/cdp/config.h
@@ -54,6 +54,7 @@ typedef struct{
 	str fqdn;	/**< FQDN of the peer */
 	str realm;	/**< Realm of the peer */
 	int port;	/**< TCP port of the peer; the Diameter uri is then aaa://fqdn:port. */
+    str src_addr; /**< IP address used to connect to the peer */
 } peer_config;
 
 
diff --git a/modules/cdp/configexample/ConfigExample.xml b/modules/cdp/configexample/ConfigExample.xml
index 5f44bdc..da9436a 100644
--- a/modules/cdp/configexample/ConfigExample.xml
+++ b/modules/cdp/configexample/ConfigExample.xml
@@ -54,7 +54,7 @@
 		a dedicated receiver process will be forked. All other unkwnown peers will share a single
 		receiver.
 	-->
-	<Peer FQDN="hss.open-ims.test" Realm="open-ims.test" port="3868"/>
+	<Peer FQDN="hss.open-ims.test" Realm="open-ims.test" port="3868" src_addr="192.168.1.1"/>
 
 	<!--
 		Definition of incoming connection acceptors. If no bind is specified, the acceptor will bind
diff --git a/modules/cdp/configparser.c b/modules/cdp/configparser.c
index 584dff9..ade821d 100644
--- a/modules/cdp/configparser.c
+++ b/modules/cdp/configparser.c
@@ -331,7 +331,12 @@ dp_config* parse_dp_config(xmlDocPtr doc)
 				x->peers[x->peers_cnt].port = atoi((char*)xc);
 				xmlFree(xc);
 			}
-			x->peers_cnt++;		
+			xc = xmlGetProp(child,(xmlChar*)"src_addr");
+			if (xc){
+				quote_trim_dup(&(x->peers[x->peers_cnt].src_addr),(char*)xc);
+				xmlFree(xc);
+			}
+			x->peers_cnt++;
 		}
 		else if (xmlStrlen(child->name)==8 && strncasecmp((char*)child->name,"Acceptor",8)==0){
 			//Acceptor
@@ -459,7 +464,7 @@ dp_config* parse_dp_config(xmlDocPtr doc)
 												rei->next = re;
 												break;
 											}
-										} 					
+										}					
 								}
 							}
 						}
diff --git a/modules/cdp/diameter_code_avp.h b/modules/cdp/diameter_code_avp.h
index f3bc375..e61fe17 100644
--- a/modules/cdp/diameter_code_avp.h
+++ b/modules/cdp/diameter_code_avp.h
@@ -265,6 +265,7 @@ typedef enum {
 	AVP_MIP6_Agent_Info				  =  486, //RFC5447
 	
 	AVP_Service_Selection			  =  493, //RFC5778  
+	AVP_Call_Id                       =  494,
 	
 }AAA_AVPCodeNr;
 
diff --git a/modules/cdp/diameter_comm.c b/modules/cdp/diameter_comm.c
index 94b1b5e..3df8280 100644
--- a/modules/cdp/diameter_comm.c
+++ b/modules/cdp/diameter_comm.c
@@ -132,8 +132,14 @@ AAAReturnCode AAASendMessage(
 		AAATransactionCallback_f *callback_f,
 		void *callback_param)
 {
+        cdp_session_t* cdp_session;
 	peer *p;
-	p = get_routing_peer(message);
+        cdp_session = cdp_get_session(message->sessionId->data);
+        
+	p = get_routing_peer(cdp_session, message);
+        if (cdp_session) {
+            AAASessionsUnlock(cdp_session->hash);
+        }
 	if (!p) {
 		LM_ERR("AAASendMessage(): Can't find a suitable connected peer in the routing table.\n");
 		goto error;
@@ -238,12 +244,16 @@ AAAMessage* AAASendRecvMessage(AAAMessage *message)
 	gen_sem_t *sem=0;
 	cdp_trans_t *t;
 	AAAMessage *ans;
-    struct timeval start, stop;
-    long elapsed_usecs=0, elapsed_millis=0;
-
-    gettimeofday(&start, NULL);
-
-	p = get_routing_peer(message);
+        struct timeval start, stop;
+        long elapsed_usecs=0, elapsed_millis=0;
+        cdp_session_t* cdp_session;
+
+        gettimeofday(&start, NULL);
+        cdp_session = cdp_get_session(message->sessionId->data);
+	p = get_routing_peer(cdp_session, message);
+        if (cdp_session) {
+            AAASessionsUnlock(cdp_session->hash);
+        }
 	if (!p) {
 		LM_ERR("AAASendRecvMessage(): Can't find a suitable connected peer in the routing table.\n");
 		goto error;
diff --git a/modules/cdp/diameter_epc_code_avp.h b/modules/cdp/diameter_epc_code_avp.h
index dad3026..ef4d561 100644
--- a/modules/cdp/diameter_epc_code_avp.h
+++ b/modules/cdp/diameter_epc_code_avp.h
@@ -146,6 +146,9 @@ enum {
 	AVP_EPC_Served_Party_IP_Address						= 848,
 	AVP_EPC_Authorized_QoS								= 849,
 	AVP_EPC_Application_Server_Information				= 850,
+	AVP_EPC_Trunk_Group_Id								= 851,
+	AVP_EPC_Incoming_Trunk_Group_Id						= 852,
+	AVP_EPC_Outgoing_Trunk_Group_Id						= 853,
 	AVP_EPC_Bearer_Service								= 854,
 	AVP_EPC_Service_ID									= 855,
 	AVP_EPC_Associated_URI								= 856,
diff --git a/modules/cdp/doc/cdp_admin.xml b/modules/cdp/doc/cdp_admin.xml
index cdf65d2..234e270 100644
--- a/modules/cdp/doc/cdp_admin.xml
+++ b/modules/cdp/doc/cdp_admin.xml
@@ -126,6 +126,24 @@ modparam("cdp", "latency_threshold", 1000)
 </programlisting>
       </example>
     </section>
+    <section>
+      <title>workerq_length_threshold_percentage (int)</title>
+
+      <para>The threshold of the length of the worker queue as a percentage of 
+	  the maximum queue size - when exceeded a warning is written to the log
+	  file. 0  means disabled</para>
+
+      <para><emphasis> Default value is <quote>0</quote>. </emphasis></para>
+
+      <example>
+        <title>Set <varname>workerq_length_threshold_percentage</varname> parameter</title>
+
+        <programlisting format="linespecific">...
+modparam("cdp", "workerq_length_threshold_percentage", 25)
+...
+	</programlisting>
+      </example>
+    </section>
   </section>
 
   <section>
diff --git a/modules/cdp/mod.c b/modules/cdp/mod.c
index 6857d82..4b01895 100644
--- a/modules/cdp/mod.c
+++ b/modules/cdp/mod.c
@@ -55,6 +55,7 @@
 #include "../../rpc.h"
 #include "../../rpc_lookup.h"
 #include "../../cfg/cfg_struct.h"
+#include "cdp_stats.h"
 
 MODULE_VERSION
 
@@ -62,6 +63,7 @@ char* config_file="DiameterPeer.xml"; 	/**< default DiameterPeer configuration f
 unsigned int latency_threshold = 500;			/**< default threshold for Diameter calls (ms) */
 unsigned int *latency_threshold_p = &latency_threshold;
 unsigned int workerq_latency_threshold = 100;	/**< default threshold for putting a task into worker queue (ms) */
+unsigned int workerq_length_threshold_percentage = 0;	/**< default threshold for worker queue length, percentage of max queue length - by default disabled */
 
 extern dp_config *config; 				/**< DiameterPeer configuration structure */
 
@@ -165,15 +167,10 @@ static param_export_t cdp_params[] = {
 	{ "config_file",				PARAM_STRING,	&config_file}, 				/**< configuration filename */
 	{ "latency_threshold", 			PARAM_INT, 		&latency_threshold},		/**<threshold above which we will log*/
 	{ "workerq_latency_threshold", 	PARAM_INT, 		&workerq_latency_threshold},/**<time threshold putting job into queue*/
+	{ "workerq_length_threshold_percentage", 	PARAM_INT, 		&workerq_length_threshold_percentage},/**<queue length threshold - percentage of max queue length*/
 	{ 0, 0, 0 }
 };
 
-stat_export_t mod_stats[] = {
-	{"avg_response_time" ,  STAT_IS_FUNC, 	(stat_var**)get_avg_cdp_response_time	},
-	{"timeouts" ,  			0, 				(stat_var**)&stat_cdp_timeouts  		},
-	{0,0,0}
-};
-
 /**
  * Exported module interface
  */
@@ -182,7 +179,7 @@ struct module_exports exports = {
 	DEFAULT_DLFLAGS,
 	cdp_cmds,                       		/**< Exported functions */
 	cdp_params,                     		/**< Exported parameters */
-	mod_stats,
+	0,
 	0,										/**< MI cmds */
 	0,										/**< pseudovariables */
 	0,										/**< extra processes */
@@ -204,23 +201,11 @@ static int cdp_init( void )
 		LM_ERR("failed to register RPC commands for CDP module\n");
 		return -1;
 	}
-#ifdef STATISTICS
-	/* register statistics */
-	if ( register_stat("cdp", "replies_response_time", &replies_response_time,0 )!=0 ) {
-		LM_ERR("failed to register stat\n");
-		return -1;
-	}
-
-	if ( register_stat("cdp", "replies_received", &replies_received, 0)!=0 ) {
-		LM_ERR("failed to register stat\n");
-		return -1;
-	}
-
-	if (register_module_stats( exports.name, mod_stats)!=0 ) {
-		LM_ERR("failed to register core statistics\n");
-		return -1;
+	
+	if (cdp_init_counters() != 0) {
+	    LM_ERR("Failed to register counters for CDP modules\n");
+	    return -1;
 	}
-#endif
 
 	if (!diameter_peer_init(config_file)){
 		LM_ERR("error initializing the diameter peer\n");
diff --git a/modules/cdp/mod.h b/modules/cdp/mod.h
index ef4475e..e52102f 100644
--- a/modules/cdp/mod.h
+++ b/modules/cdp/mod.h
@@ -47,7 +47,6 @@
 #define _CDP__H
 
 #include "../../sr_module.h"
-#include "statistics.h"
 
 #define M_NAME "cdp"
 
diff --git a/modules/cdp/peer.c b/modules/cdp/peer.c
index 1ebb2d5..0114f74 100644
--- a/modules/cdp/peer.c
+++ b/modules/cdp/peer.c
@@ -56,7 +56,7 @@
  * @param port - port of the peer to connect to
  * @returns the new peer* if ok, NULL on error
  */
-peer* new_peer(str fqdn,str realm,int port)
+peer* new_peer(str fqdn,str realm,int port,str src_addr)
 {
 	peer *x;
 	x = shm_malloc(sizeof(peer));
@@ -69,6 +69,8 @@ peer* new_peer(str fqdn,str realm,int port)
 	if (!x->fqdn.s) goto error;	
 	shm_str_dup_macro(x->realm,realm);
 	if (!x->realm.s) goto error;	
+	shm_str_dup_macro(x->src_addr,src_addr);
+	if (!x->src_addr.s) goto error;
 	x->port = port;
 	x->lock = lock_alloc();
 	x->lock = lock_init(x->lock);
@@ -99,6 +101,7 @@ void free_peer(peer *x,int locked)
 	if (!locked) lock_get(x->lock);
 	if (x->fqdn.s) shm_free(x->fqdn.s);
 	if (x->realm.s) shm_free(x->realm.s);	
+	if (x->src_addr.s) shm_free(x->src_addr.s);
 	lock_destroy(x->lock);
 	lock_dealloc((void*)x->lock);
 	shm_free(x);
diff --git a/modules/cdp/peer.h b/modules/cdp/peer.h
index 67e3cff..db70316 100644
--- a/modules/cdp/peer.h
+++ b/modules/cdp/peer.h
@@ -3,23 +3,23 @@
  *
  * Copyright (C) 2012 Smile Communications, jason.penton at smilecoms.com
  * Copyright (C) 2012 Smile Communications, richard.good at smilecoms.com
- * 
+ *
  * The initial version of this code was written by Dragos Vingarzan
  * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
  * Fruanhofer Institute. It was and still is maintained in a separate
  * branch of the original SER. We are therefore migrating it to
  * Kamailio/SR and look forward to maintaining it from here on out.
  * 2011/2012 Smile Communications, Pty. Ltd.
- * ported/maintained/improved by 
+ * ported/maintained/improved by
  * Jason Penton (jason(dot)penton(at)smilecoms.com and
- * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an
  * effort to add full IMS support to Kamailio/SR using a new and
  * improved architecture
- * 
+ *
  * NB: Alot of this code was originally part of OpenIMSCore,
- * FhG Fokus. 
+ * FhG Fokus.
  * Copyright (C) 2004-2006 FhG Fokus
- * Thanks for great work! This is an effort to 
+ * Thanks for great work! This is an effort to
  * break apart the various CSCF functions into logically separate
  * components. We hope this will drive wider use. We also feel
  * that in this way the architecture is more complete and thereby easier
@@ -37,10 +37,10 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
+ *
  */
 
 #ifndef __PEER_H
@@ -100,7 +100,8 @@ typedef struct _peer_t{
 	str fqdn;				/**< FQDN of the peer */
 	str realm;				/**< Realm of the peer */
 	int port;				/**< TCP Port of the peer */
-	
+	str src_addr;			/**< IP Address used to connect to the peer */
+
 	app_config *applications;/**< list of supported applications */
 	int applications_cnt;	/**< size of list of supporter applications*/
 	
@@ -127,7 +128,7 @@ typedef struct _peer_t{
 	struct _peer_t *prev;	/**< previous peer in the peer list */
 } peer;
 
-peer* new_peer(str fqdn,str realm,int port);
+peer* new_peer(str fqdn,str realm,int port,str src_addr);
 void free_peer(peer *x,int locked);
 
 inline void touch_peer(peer *p);
diff --git a/modules/cdp/peermanager.c b/modules/cdp/peermanager.c
index 962d3cc..ad99276 100644
--- a/modules/cdp/peermanager.c
+++ b/modules/cdp/peermanager.c
@@ -92,7 +92,7 @@ int peer_manager_init(dp_config *config)
 	*endtoend_id |= rand() & 0xFFFFF;
 
 	for(i=0;i<config->peers_cnt;i++){
-		p = new_peer(config->peers[i].fqdn,config->peers[i].realm,config->peers[i].port);
+		p = new_peer(config->peers[i].fqdn,config->peers[i].realm,config->peers[i].port,config->peers[i].src_addr);
 		if (!p) continue;
 		p->is_dynamic = 0;
 		add_peer(p);
@@ -209,6 +209,8 @@ peer *get_peer_from_sock(int sock)
 peer *get_peer_from_fqdn(str fqdn,str realm)
 {
 	peer *i;
+	str dumb;
+
 	lock_get(peer_list_lock);
 	i = peer_list->head;
 	while(i){
@@ -218,7 +220,7 @@ peer *get_peer_from_fqdn(str fqdn,str realm)
 	}
 	lock_release(peer_list_lock);
 	if (!i&&config->accept_unknown_peers){
-		i = new_peer(fqdn,realm,3868);
+		i = new_peer(fqdn,realm,3868,dumb);
 		if (i){
 			i->is_dynamic=1;
 			touch_peer(i);
diff --git a/modules/cdp/receiver.c b/modules/cdp/receiver.c
index c7d0813..77ae508 100644
--- a/modules/cdp/receiver.c
+++ b/modules/cdp/receiver.c
@@ -836,7 +836,7 @@ int peer_connect(peer *p)
 	int sock;
 	unsigned int option = 1;
 
-	struct addrinfo *ainfo=0,*res=0,hints;
+	struct addrinfo *ainfo=0,*res=0,*sainfo=0,hints;
 	char buf[256],host[256],serv[256];
 	int error;
 
@@ -870,6 +870,25 @@ int peer_connect(peer *p)
 			continue;
 		}
 
+		/* try to set the local socket used to connect to the peer */
+		if (p->src_addr.s && p->src_addr.len > 0) {
+			LM_DBG("peer_connect(): connetting to peer via src addr=%.*s",p->src_addr.len, p->src_addr.s);
+			memset (&hints, 0, sizeof(hints));
+			hints.ai_flags = AI_NUMERICHOST;
+			hints.ai_socktype = SOCK_STREAM;
+			error = getaddrinfo(p->src_addr.s, NULL, &hints, &sainfo);
+
+			if (error!=0){
+				LM_WARN("peer_connect(): error getting client socket on %.*s:%s\n",
+					p->src_addr.len,p->src_addr.s,gai_strerror(error));
+			} else {
+				if (bind(sock, sainfo->ai_addr, sainfo->ai_addrlen )) {
+					LM_WARN("peer_connect(): error opening client socket on %.*s:%s\n",
+						p->src_addr.len,p->src_addr.s,strerror(errno));
+				}
+			}
+		}
+
 		{// Connect with timeout
 			int x;
 			x=fcntl(sock,F_GETFL,0);
diff --git a/modules/cdp/routing.c b/modules/cdp/routing.c
index 8e38368..31b03e3 100644
--- a/modules/cdp/routing.c
+++ b/modules/cdp/routing.c
@@ -50,7 +50,7 @@
 
 #define LB_MAX_PEERS 20			/**< maximum peers that can be loadbalanced accross i.e. same metric */
 
-extern dp_config *config;		/**< Configuration for this diameter peer 	*/
+extern dp_config *config; /**< Configuration for this diameter peer 	*/
 int gcount = 0;
 
 /**
@@ -59,15 +59,14 @@ int gcount = 0;
  * @param app_id - the application id to look for
  * @param vendor_id - the vendor id to look for, 0 if not vendor specific 
  * @returns 0 if not found, 1 if found
- */ 
-int peer_handles_application(peer *p,int app_id,int vendor_id)
-{
-	int i;
-	LM_DBG("Checking if peer %.*s handles application %d for vendord %d\n",p->fqdn.len,p->fqdn.s,app_id,vendor_id);
-	if (!p || !p->applications || !p->applications_cnt) return 0;
-	for(i=0;i<p->applications_cnt;i++)
-		if (p->applications[i].id==app_id && p->applications[i].vendor==vendor_id) return 1;		
-	return 0;
+ */
+int peer_handles_application(peer *p, int app_id, int vendor_id) {
+    int i;
+    LM_DBG("Checking if peer %.*s handles application %d for vendord %d\n", p->fqdn.len, p->fqdn.s, app_id, vendor_id);
+    if (!p || !p->applications || !p->applications_cnt) return 0;
+    for (i = 0; i < p->applications_cnt; i++)
+        if (p->applications[i].id == app_id && p->applications[i].vendor == vendor_id) return 1;
+    return 0;
 }
 
 /**
@@ -75,56 +74,84 @@ int peer_handles_application(peer *p,int app_id,int vendor_id)
  * @param r - the list of routing entries to look into
  * @returns - the peer or null if none connected
  */
-peer* get_first_connected_route(routing_entry *r,int app_id,int vendor_id)
-{
-	peer *peers[LB_MAX_PEERS];
-	int peer_count=0;
-	int prev_metric=0;
-	routing_entry *i;
-	peer *p;
-	int j;
-	time_t least_recent_time;
-
-	LM_DBG("get_first_connected_route in list %p for app_id %d and vendor_id %d\n",
-		r,app_id,vendor_id);
-	for(i=r;i;i=i->next){
-		if (peer_count >= LB_MAX_PEERS)
-			break;
-		p = get_peer_by_fqdn(&(i->fqdn));
-		if (!p)
-			LM_DBG("The peer %.*s does not seem to be connected or configured\n",
-				i->fqdn.len,i->fqdn.s);
-		else
-			LM_DBG("The peer %.*s state is %s\n",i->fqdn.len,i->fqdn.s,
-				(p->state==I_Open||p->state==R_Open)?"opened":"closed");
-		if (p && !p->disabled && (p->state==I_Open || p->state==R_Open) && peer_handles_application(p,app_id,vendor_id)) {
-			LM_DBG("The peer %.*s matches - will forward there\n",i->fqdn.len,i->fqdn.s);
-			if (peer_count!=0) {//check the metric
-				if (i->metric != prev_metric)
-					break;
-				//metric must be the same
-				peers[peer_count++] = p;
-			} else {//we're first
-				prev_metric = i->metric;
-				peers[peer_count++] = p;
-			}
-		}
-	}
-
-	if (peer_count==0)
-		return 0;
-
-	least_recent_time = peers[0]->last_selected;
-	p = peers[0];
-	for (j=1; j<peer_count; j++) {
-		if (peers[j]->last_selected < least_recent_time) {
-			least_recent_time = peers[j]->last_selected;
-			p = peers[j];
-		}
-	}
-
-	p->last_selected = time(NULL);
-	return p;
+peer* get_first_connected_route(cdp_session_t* cdp_session, routing_entry *r, int app_id, int vendor_id) {
+    peer * peers[LB_MAX_PEERS];
+    int peer_count = 0;
+    int prev_metric = 0;
+    routing_entry *i;
+    peer *p;
+    int j;
+    time_t least_recent_time;
+
+    if (cdp_session) {
+        /*try and find an already used peer for this session - sticky*/
+        if ((cdp_session->sticky_peer_fqdn.len > 0) && cdp_session->sticky_peer_fqdn.s) {
+            //we have an old sticky peer. let's make sure it's up and connected before we use it.
+            p = get_peer_by_fqdn(&cdp_session->sticky_peer_fqdn);
+            if (p && !p->disabled && (p->state == I_Open || p->state == R_Open) && peer_handles_application(p, app_id, vendor_id)) {
+                p->last_selected = time(NULL);
+                LM_DBG("Found a sticky peer [%.*s] for this session - re-using\n", p->fqdn.len, p->fqdn.s);
+                return p;
+            }
+        }
+    }
+
+    for (i = r; i; i = i->next) {
+        if (peer_count >= LB_MAX_PEERS)
+            break;
+        p = get_peer_by_fqdn(&(i->fqdn));
+        if (!p)
+            LM_DBG("The peer %.*s does not seem to be connected or configured\n",
+                i->fqdn.len, i->fqdn.s);
+        else
+            LM_DBG("The peer %.*s state is %s\n", i->fqdn.len, i->fqdn.s,
+                (p->state == I_Open || p->state == R_Open) ? "opened" : "closed");
+        if (p && !p->disabled && (p->state == I_Open || p->state == R_Open) && peer_handles_application(p, app_id, vendor_id)) {
+            LM_DBG("The peer %.*s matches - will forward there\n", i->fqdn.len, i->fqdn.s);
+            if (peer_count != 0) {//check the metric
+                if (i->metric != prev_metric)
+                    break;
+                //metric must be the same
+                peers[peer_count++] = p;
+            } else {//we're first
+                prev_metric = i->metric;
+                peers[peer_count++] = p;
+            }
+        }
+    }
+
+    if (peer_count == 0) {
+        return 0;
+    }
+
+    least_recent_time = peers[0]->last_selected;
+    p = peers[0];
+    for (j = 1; j < peer_count; j++) {
+        if (peers[j]->last_selected < least_recent_time) {
+            least_recent_time = peers[j]->last_selected;
+            p = peers[j];
+        }
+    }
+
+    if (cdp_session) {
+        if (cdp_session->sticky_peer_fqdn_buflen <= p->fqdn.len) {
+            LM_DBG("not enough storage for sticky peer - allocating more\n");
+            if (cdp_session->sticky_peer_fqdn.s)
+                shm_free(cdp_session->sticky_peer_fqdn.s);
+
+            cdp_session->sticky_peer_fqdn.s = (char*) shm_malloc(p->fqdn.len + 1);
+            if (!cdp_session->sticky_peer_fqdn.s) {
+                LM_ERR("no more shm memory\n");
+                return 0;
+            }
+            cdp_session->sticky_peer_fqdn_buflen = p->fqdn.len + 1;
+            memset(cdp_session->sticky_peer_fqdn.s, 0, p->fqdn.len + 1);
+        }
+        cdp_session->sticky_peer_fqdn.len = p->fqdn.len;
+        memcpy(cdp_session->sticky_peer_fqdn.s, p->fqdn.s, p->fqdn.len);
+    }
+    p->last_selected = time(NULL);
+    return p;
 }
 
 /**
@@ -135,92 +162,91 @@ peer* get_first_connected_route(routing_entry *r,int app_id,int vendor_id)
  * - Then we look for the first connected peer in the default routes
  * @param m - the Diameter message to find the destination peer for
  * @returns - the connected peer or null if none connected found
- */  
-peer* get_routing_peer(AAAMessage *m)
-{
-	str destination_realm={0,0},destination_host={0,0};
-	AAA_AVP *avp,*avp_vendor,*avp2;
-	AAA_AVP_LIST group;	
-	peer *p;
-	routing_realm *rr;
-	int app_id=0,vendor_id=0;
-	
-	LM_DBG("getting diameter routing peer for realm: [%.*s]\n", m->dest_realm->data.len, m->dest_realm->data.s);
-
-	app_id = m->applicationId;	
-	avp = AAAFindMatchingAVP(m,0,AVP_Vendor_Specific_Application_Id,0,AAA_FORWARD_SEARCH);
-	if (avp){
-		group = AAAUngroupAVPS(avp->data);
-		avp_vendor = AAAFindMatchingAVPList(group,group.head,AVP_Vendor_Id,0,0);				
-		avp2 = AAAFindMatchingAVPList(group,group.head,AVP_Auth_Application_Id,0,0);				
-		if (avp_vendor&&avp2){
-			vendor_id = get_4bytes(avp_vendor->data.s);
-			app_id = get_4bytes(avp2->data.s);
-		}
-		avp2 = AAAFindMatchingAVPList(group,group.head,AVP_Acct_Application_Id,0,0);				
-		if (avp_vendor&&avp2){
-			vendor_id = get_4bytes(avp_vendor->data.s);
-			app_id = get_4bytes(avp2->data.s);
-		}
-		AAAFreeAVPList(&group);
-	}
-
-	avp_vendor = AAAFindMatchingAVP(m,0,AVP_Vendor_Id,0,AAA_FORWARD_SEARCH);				
-	avp = AAAFindMatchingAVP(m,0,AVP_Auth_Application_Id,0,AAA_FORWARD_SEARCH);
-	if (avp){
-		if (avp_vendor) vendor_id = get_4bytes(avp_vendor->data.s);
-		else vendor_id = 0;
-		app_id = get_4bytes(avp->data.s);		
-	}
-	
-	avp = AAAFindMatchingAVP(m,0,AVP_Acct_Application_Id,0,AAA_FORWARD_SEARCH);
-	if (avp){
-		if (avp_vendor) vendor_id = get_4bytes(avp_vendor->data.s);
-		else vendor_id = 0;
-		app_id = get_4bytes(avp->data.s);		
-	}
-	
-	avp = AAAFindMatchingAVP(m,0,AVP_Destination_Host,0,AAA_FORWARD_SEARCH);
-	if (avp) destination_host = avp->data;
-	
-	if (destination_host.len){
-		/* There is a destination host present in the message try and route directly there */
-		p = get_peer_by_fqdn(&destination_host);
-		if (p && (p->state==I_Open || p->state==R_Open) && peer_handles_application(p,app_id,vendor_id)) {
-			p->last_selected = time(NULL);
-			return p;
-		}
-		/* the destination host peer is not connected at the moment, try a normal route then */
-	}
-	
-	avp = AAAFindMatchingAVP(m,0,AVP_Destination_Realm,0,AAA_FORWARD_SEARCH);
-	if (avp) destination_realm = avp->data;
-	
-	if (!config->r_table) {
-		LM_ERR("get_routing_peer(): Empty routing table.\n");
-		return 0;
-	}
-	
-	if (destination_realm.len){
-		/* first search for the destination realm */
-		for(rr=config->r_table->realms;rr;rr=rr->next)
-			if (rr->realm.len == destination_realm.len &&
-				strncasecmp(rr->realm.s,destination_realm.s,destination_realm.len)==0)
-					break;
-		if (rr) {
-			p = get_first_connected_route(rr->routes,app_id,vendor_id);
-			if (p) return p;
-			else LM_ERR("get_routing_peer(): No connected Route peer found for Realm <%.*s>. Trying DefaultRoutes next...\n",
-					destination_realm.len,destination_realm.s);
-		}	 
-	}
-	/* if not found in the realms or no destination_realm, 
-	 * get the first connected host in default routes */
-	LM_DBG("no routing peer found, trying default route\n");
-	p = get_first_connected_route(config->r_table->routes,app_id,vendor_id);
-	if (!p){
-		LM_ERR("get_routing_peer(): No connected DefaultRoute peer found for app_id %d and vendor id %d.\n",
-				app_id,vendor_id);
-	}
-	return p;
+ */
+peer* get_routing_peer(cdp_session_t* cdp_session, AAAMessage *m) {
+    str destination_realm = {0, 0}, destination_host = {0, 0};
+    AAA_AVP *avp, *avp_vendor, *avp2;
+    AAA_AVP_LIST group;
+    peer *p;
+    routing_realm *rr;
+    int app_id = 0, vendor_id = 0;
+
+    LM_DBG("getting diameter routing peer for realm: [%.*s]\n", m->dest_realm->data.len, m->dest_realm->data.s);
+
+    app_id = m->applicationId;
+    avp = AAAFindMatchingAVP(m, 0, AVP_Vendor_Specific_Application_Id, 0, AAA_FORWARD_SEARCH);
+    if (avp) {
+        group = AAAUngroupAVPS(avp->data);
+        avp_vendor = AAAFindMatchingAVPList(group, group.head, AVP_Vendor_Id, 0, 0);
+        avp2 = AAAFindMatchingAVPList(group, group.head, AVP_Auth_Application_Id, 0, 0);
+        if (avp_vendor && avp2) {
+            vendor_id = get_4bytes(avp_vendor->data.s);
+            app_id = get_4bytes(avp2->data.s);
+        }
+        avp2 = AAAFindMatchingAVPList(group, group.head, AVP_Acct_Application_Id, 0, 0);
+        if (avp_vendor && avp2) {
+            vendor_id = get_4bytes(avp_vendor->data.s);
+            app_id = get_4bytes(avp2->data.s);
+        }
+        AAAFreeAVPList(&group);
+    }
+
+    avp_vendor = AAAFindMatchingAVP(m, 0, AVP_Vendor_Id, 0, AAA_FORWARD_SEARCH);
+    avp = AAAFindMatchingAVP(m, 0, AVP_Auth_Application_Id, 0, AAA_FORWARD_SEARCH);
+    if (avp) {
+        if (avp_vendor) vendor_id = get_4bytes(avp_vendor->data.s);
+        else vendor_id = 0;
+        app_id = get_4bytes(avp->data.s);
+    }
+
+    avp = AAAFindMatchingAVP(m, 0, AVP_Acct_Application_Id, 0, AAA_FORWARD_SEARCH);
+    if (avp) {
+        if (avp_vendor) vendor_id = get_4bytes(avp_vendor->data.s);
+        else vendor_id = 0;
+        app_id = get_4bytes(avp->data.s);
+    }
+
+    avp = AAAFindMatchingAVP(m, 0, AVP_Destination_Host, 0, AAA_FORWARD_SEARCH);
+    if (avp) destination_host = avp->data;
+
+    if (destination_host.len) {
+        /* There is a destination host present in the message try and route directly there */
+        p = get_peer_by_fqdn(&destination_host);
+        if (p && (p->state == I_Open || p->state == R_Open) && peer_handles_application(p, app_id, vendor_id)) {
+            p->last_selected = time(NULL);
+            return p;
+        }
+        /* the destination host peer is not connected at the moment, try a normal route then */
+    }
+
+    avp = AAAFindMatchingAVP(m, 0, AVP_Destination_Realm, 0, AAA_FORWARD_SEARCH);
+    if (avp) destination_realm = avp->data;
+
+    if (!config->r_table) {
+        LM_ERR("get_routing_peer(): Empty routing table.\n");
+        return 0;
+    }
+
+    if (destination_realm.len) {
+        /* first search for the destination realm */
+        for (rr = config->r_table->realms; rr; rr = rr->next)
+            if (rr->realm.len == destination_realm.len &&
+                    strncasecmp(rr->realm.s, destination_realm.s, destination_realm.len) == 0)
+                break;
+        if (rr) {
+            p = get_first_connected_route(cdp_session, rr->routes, app_id, vendor_id);
+            if (p) return p;
+            else LM_ERR("get_routing_peer(): No connected Route peer found for Realm <%.*s>. Trying DefaultRoutes next...\n",
+                    destination_realm.len, destination_realm.s);
+        }
+    }
+    /* if not found in the realms or no destination_realm, 
+     * get the first connected host in default routes */
+    LM_DBG("no routing peer found, trying default route\n");
+    p = get_first_connected_route(cdp_session, config->r_table->routes, app_id, vendor_id);
+    if (!p) {
+        LM_ERR("get_routing_peer(): No connected DefaultRoute peer found for app_id %d and vendor id %d.\n",
+                app_id, vendor_id);
+    }
+    return p;
 }
diff --git a/modules/cdp/routing.h b/modules/cdp/routing.h
index d1fa35e..10be370 100644
--- a/modules/cdp/routing.h
+++ b/modules/cdp/routing.h
@@ -49,8 +49,9 @@
 #include "peer.h"
 #include "diameter.h"
 #include "utils.h"
+#include "session.h"
 
-peer* get_routing_peer(AAAMessage *m);
+peer* get_routing_peer(cdp_session_t* cdp_session, AAAMessage *m);
 
 #endif
 
diff --git a/modules/cdp/session.c b/modules/cdp/session.c
index 98382a7..f3399f9 100644
--- a/modules/cdp/session.c
+++ b/modules/cdp/session.c
@@ -123,7 +123,9 @@ void free_session(cdp_session_t *x)
 
 		if(x->dest_host.s) shm_free(x->dest_host.s);
 		if(x->dest_realm.s) shm_free(x->dest_realm.s);
-
+                if (x->sticky_peer_fqdn_buflen && x->sticky_peer_fqdn.s) {
+                    shm_free(x->sticky_peer_fqdn.s);
+                }
 		shm_free(x);
 	}
 }
diff --git a/modules/cdp/session.h b/modules/cdp/session.h
index c99161b..fcacc8c 100644
--- a/modules/cdp/session.h
+++ b/modules/cdp/session.h
@@ -230,6 +230,8 @@ typedef struct _cdp_session_t {
 	unsigned int vendor_id;				/**< specific vendor id for this session */
 	cdp_session_type_t type;
 	str dest_host, dest_realm; 			/*the destination host and realm, used only for auth, for the moment*/
+        str sticky_peer_fqdn;                           /*peer that we would like to stick for for this session*/
+        int sticky_peer_fqdn_buflen;                     /*length of buffer available for sticky peer*/
 	union {
 		cdp_auth_session_t auth;
 		cdp_acc_session_t acc;
diff --git a/modules/cdp/statistics.c b/modules/cdp/statistics.c
deleted file mode 100644
index d4d3169..0000000
--- a/modules/cdp/statistics.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * $Id$
- *
- * Copyright (C) 2012 Smile Communications, jason.penton at smilecoms.com
- * Copyright (C) 2012 Smile Communications, richard.good at smilecoms.com
- * 
- * The initial version of this code was written by Dragos Vingarzan
- * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
- * Fruanhofer Institute. It was and still is maintained in a separate
- * branch of the original SER. We are therefore migrating it to
- * Kamailio/SR and look forward to maintaining it from here on out.
- * 2011/2012 Smile Communications, Pty. Ltd.
- * ported/maintained/improved by 
- * Jason Penton (jason(dot)penton(at)smilecoms.com and
- * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
- * effort to add full IMS support to Kamailio/SR using a new and
- * improved architecture
- * 
- * NB: Alot of this code was originally part of OpenIMSCore,
- * FhG Fokus. 
- * Copyright (C) 2004-2006 FhG Fokus
- * Thanks for great work! This is an effort to 
- * break apart the various CSCF functions into logically separate
- * components. We hope this will drive wider use. We also feel
- * that in this way the architecture is more complete and thereby easier
- * to manage in the Kamailio/SR environment
- *
- * This file is part of Kamailio, a free SIP server.
- *
- * Kamailio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version
- *
- * Kamailio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- */
-
-#include "statistics.h"
-
-unsigned long get_avg_cdp_response_time() {
-
-	long rpls_received = get_stat_val(replies_received);
-	if (!rpls_received)
-		return 0;
-
-	return get_stat_val(replies_response_time)/rpls_received;
-}
-
diff --git a/modules/cdp/statistics.h b/modules/cdp/statistics.h
deleted file mode 100644
index 470df05..0000000
--- a/modules/cdp/statistics.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * $Id$
- *
- * Copyright (C) 2012 Smile Communications, jason.penton at smilecoms.com
- * Copyright (C) 2012 Smile Communications, richard.good at smilecoms.com
- * 
- * The initial version of this code was written by Dragos Vingarzan
- * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
- * Fruanhofer Institute. It was and still is maintained in a separate
- * branch of the original SER. We are therefore migrating it to
- * Kamailio/SR and look forward to maintaining it from here on out.
- * 2011/2012 Smile Communications, Pty. Ltd.
- * ported/maintained/improved by 
- * Jason Penton (jason(dot)penton(at)smilecoms.com and
- * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
- * effort to add full IMS support to Kamailio/SR using a new and
- * improved architecture
- * 
- * NB: Alot of this code was originally part of OpenIMSCore,
- * FhG Fokus. 
- * Copyright (C) 2004-2006 FhG Fokus
- * Thanks for great work! This is an effort to 
- * break apart the various CSCF functions into logically separate
- * components. We hope this will drive wider use. We also feel
- * that in this way the architecture is more complete and thereby easier
- * to manage in the Kamailio/SR environment
- *
- * This file is part of Kamailio, a free SIP server.
- *
- * Kamailio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version
- *
- * Kamailio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- */
-
-#ifndef STATISTICS_H_
-#define STATISTICS_H_
-
-#include "../../lib/kcore/statistics.h"
-
-stat_var* stat_cdp_timeouts;
-stat_var* replies_received;
-stat_var* replies_response_time;
-
-unsigned long get_avg_cdp_response_time();
-
-#endif /* STATISTICS_H_ */
diff --git a/modules/cdp/transaction.c b/modules/cdp/transaction.c
index e0e50aa..f98f6af 100644
--- a/modules/cdp/transaction.c
+++ b/modules/cdp/transaction.c
@@ -47,8 +47,9 @@
 
 #include "timer.h"
 #include "globals.h"
+#include "cdp_stats.h"
 
-
+extern struct cdp_counters_h cdp_cnts_h;
 cdp_trans_list_t *trans_list=0;		/**< list of transactions */
 
 /**
@@ -197,7 +198,8 @@ int cdp_trans_timer(time_t now, void* ptr)
 	while(x)
 	{
 		if (now>x->expires){
-            update_stat(stat_cdp_timeouts, 1);		//Transaction has timed out waiting for response
+            counter_inc(cdp_cnts_h.timeout);		//Transaction has timed out waiting for response
+	    
 			x->ans = 0;
 			if (x->cb){
 				(x->cb)(1,*(x->ptr),0, (now - x->expires));
diff --git a/modules/cdp/transaction.h b/modules/cdp/transaction.h
index b5b5626..5524993 100644
--- a/modules/cdp/transaction.h
+++ b/modules/cdp/transaction.h
@@ -47,7 +47,6 @@
 #define __TRANSACTION_H_
 
 #include <time.h>
-#include "statistics.h"
 #include "utils.h"
 #include "diameter.h"
 #include "diameter_api.h"
diff --git a/modules/cdp/worker.c b/modules/cdp/worker.c
index 5ab215c..cc1617d 100644
--- a/modules/cdp/worker.c
+++ b/modules/cdp/worker.c
@@ -58,18 +58,21 @@
 #include "diameter_api.h"
 
 #include "../../cfg/cfg_struct.h"
+#include "cdp_stats.h"
 
 /* defined in ../diameter_peer.c */
 int dp_add_pid(pid_t pid);
 void dp_del_pid(pid_t pid);
 
 extern dp_config *config; /**< Configuration for this diameter peer 	*/
+extern struct cdp_counters_h cdp_cnts_h;
 
 task_queue_t *tasks; /**< queue of tasks */
 
 cdp_cb_list_t *callbacks; /**< list of callbacks for message processing */
 
 extern unsigned int workerq_latency_threshold; /**<max delay for putting task into worker queue */
+extern unsigned int workerq_length_threshold_percentage;	/**< default threshold for worker queue length, percentage of max queue length */
 /**
  * Initializes the worker structures, like the task queue.
  */
@@ -207,6 +210,8 @@ void cb_remove(cdp_cb_t *cb) {
 int put_task(peer *p, AAAMessage *msg) {
 
     struct timeval start, stop;
+    int num_tasks, length_percentage;
+    
     long elapsed_useconds=0, elapsed_seconds=0, elapsed_millis=0;
     lock_get(tasks->lock);
 
@@ -228,6 +233,8 @@ int put_task(peer *p, AAAMessage *msg) {
 
         lock_get(tasks->lock);
     }
+    
+    counter_inc(cdp_cnts_h.queuelength);
 
     gettimeofday(&stop, NULL);
     elapsed_useconds = stop.tv_usec - start.tv_usec;
@@ -246,6 +253,13 @@ int put_task(peer *p, AAAMessage *msg) {
         LM_WARN("Error releasing tasks->empty semaphore > %s!\n", strerror(errno));
     lock_release(tasks->lock);
 
+    if(workerq_length_threshold_percentage > 0) {
+        num_tasks = tasks->end - tasks->start;
+	length_percentage = num_tasks/tasks->max*100;
+	if(length_percentage > workerq_length_threshold_percentage) {
+	    LM_WARN("Queue length has exceeded length threshold percentage [%i] and is length [%i]", length_percentage, num_tasks);
+	}
+    }
     //int num_tasks = tasks->end - tasks->start;
     //LM_ERR("Added task to task queue.  Queue length [%i]", num_tasks);
 
@@ -276,6 +290,7 @@ task_t take_task() {
         lock_get(tasks->lock);
     }
 
+    counter_add(cdp_cnts_h.queuelength, -1);
     t = tasks->queue[tasks->start];
     tasks->queue[tasks->start].msg = 0;
     tasks->start = (tasks->start + 1) % tasks->max;
diff --git a/modules/cdp_avp/epcapp.h b/modules/cdp_avp/epcapp.h
index c76d09a..484164f 100644
--- a/modules/cdp_avp/epcapp.h
+++ b/modules/cdp_avp/epcapp.h
@@ -654,7 +654,7 @@ cdp_avp_ptr		(Called_Asserted_Identity,				EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MAND
 cdp_avp_ptr		(Called_Party_Address,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		UTF8String,		str)	
 
 cdp_avp_ptr		(Calling_Party_Address,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		UTF8String,		str)	
-
+	
 cdp_avp			(Cause_Code,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Integer32,		int32_t)	
 
 cdp_avp_ptr		(Content_Disposition,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		UTF8String,		str)	
@@ -766,6 +766,14 @@ cdp_avp_add_ptr	(Time_Stamps,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,
 cdp_avp_get		(Time_Stamps,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)	
 
 cdp_avp_ptr		(User_Session_Id,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		UTF8String,		str)	
+	
+cdp_avp_add_ptr	(Trunk_Group_Id,				EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(Trunk_Group_Id,				EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)	
+	
+	
+cdp_avp_ptr		(Incoming_Trunk_Group_Id,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		UTF8String,		str)	
+	
+cdp_avp_ptr		(Outgoing_Trunk_Group_Id,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		UTF8String,		str)	
 
 
 
diff --git a/modules/cdp_avp/imsapp.h b/modules/cdp_avp/imsapp.h
index 8ac14f0..1eabb71 100644
--- a/modules/cdp_avp/imsapp.h
+++ b/modules/cdp_avp/imsapp.h
@@ -273,6 +273,8 @@ cdp_avp			(Multiple_Registration_Indication,IMS_vendor_id_3GPP,0,							Enumerat
 cdp_avp_add_ptr	(Restoration_Info,				IMS_vendor_id_3GPP,0,							Grouped,		AAA_AVP_LIST*)	
 cdp_avp_get		(Restoration_Info,				IMS_vendor_id_3GPP,0,							Grouped,		AAA_AVP_LIST)	
 
+cdp_avp_ptr		(Access_Network_Information,            IMS_vendor_id_3GPP,	0,		UTF8String,		str)        
+
 
 /*
  * ETSI something, that probably does not exist anymore
diff --git a/modules/cfg_db/Makefile b/modules/cfg_db/Makefile
index b91a04d..90273c1 100644
--- a/modules/cfg_db/Makefile
+++ b/modules/cfg_db/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # cfg_db module makefile
 # 
diff --git a/modules/cfg_db/README b/modules/cfg_db/README
index e1e49d8..2459205 100644
--- a/modules/cfg_db/README
+++ b/modules/cfg_db/README
@@ -1,4 +1,3 @@
-
 The configuration database module - cfg_db
 
 Tomas Mandys
@@ -6,7 +5,7 @@ Tomas Mandys
    Iptel.org
 
    Copyright � 2008 Tomas Mandys
-     _________________________________________________________________
+     __________________________________________________________________
 
    Table of Contents
 
@@ -43,31 +42,31 @@ Chapter 1. Admin Guide
 
 1. Overview
 
-   The   module  implements  a  database  driver  for  the  configuration
-   parameters  API.  When  configuration  parameters  are  being declared
-   (typically  when  starting) API then driver is notified and has chance
-   to  set  value  (of any parameter) based on value taken from database.
-   It's  primarily targeted for interfacing with 3rd party software which
-   is aware of the Kamailio configuration.
-
-   A  parameter is uniquely identified by a group_name plus a name, which
-   is  used  by  the  driver  to  check  if a value can be found. Because
-   configuration  parameters  may be spread in many tables, a translation
-   table  is  used to indicate where to start searching. Multiple look-up
+   The module implements a database driver for the configuration
+   parameters API. When configuration parameters are being declared
+   (typically when starting) API then driver is notified and has chance to
+   set value (of any parameter) based on value taken from database. It's
+   primarily targeted for interfacing with 3rd party software which is
+   aware of the Kamailio configuration.
+
+   A parameter is uniquely identified by a group_name plus a name, which
+   is used by the driver to check if a value can be found. Because
+   configuration parameters may be spread in many tables, a translation
+   table is used to indicate where to start searching. Multiple look-up
    tables may be defined for single parameter, tables are searched in the
    first round by exact match until parameter is found, all tables listed
-   with  wildcard  (asterisk)  in  group  name are searched in the second
+   with wildcard (asterisk) in group name are searched in the second
    round. If a parameter is not found then its value is left unchanged.
 
-   Configuration  parameters  are  normally  declared  in C code and this
+   Configuration parameters are normally declared in C code and this
    module additionally supports also declaring custom parameters in extra
-   table.  Such  parameters  may  be  used  typically in script only. All
-   parameters  listed in the table are declared in the first step, values
-   are  initialized in the second step using the same procedure as C-code
+   table. Such parameters may be used typically in script only. All
+   parameters listed in the table are declared in the first step, values
+   are initialized in the second step using the same procedure as C-code
    parameters.
 
-   The  module  does  not  reflect changes made in parameters when SER is
-   running.  It  just  declares  variables and assigns values when SER is
+   The module does not reflect changes made in parameters when Kamailio is
+   running. It just declares variables and assigns values when Kamailio is
    starting. That's all.
 
 2. Dependencies
@@ -96,33 +95,33 @@ modparam("cfg_db", "db_url", "mysql://SER:123@127.0.0.1:12345/SER");
 
 3.2. transl_tbl (string) := "cfg_transl"
 
-   Name  of  table  used  for pointing group_name+name into configuration
-   table.  If  empty/null field values are found then default values will
-   be  used.  The default values are declared in record having group_name
-   called  <default>.  The C-code "absolutely" default values ("cfg_var",
-   "group_name",  "name", "value"). The other keyword is asterisk * which
-   matches   all  parameters  and  will  be  used  if  parameter  is  not
-   explicitely mentioned.
+   Name of table used for pointing group_name+name into configuration
+   table. If empty/null field values are found then default values will be
+   used. The default values are declared in record having group_name
+   called <default>. The C-code "absolutely" default values ("cfg_var",
+   "group_name", "name", "value"). The other keyword is asterisk * which
+   matches all parameters and will be used if parameter is not explicitely
+   mentioned.
 
 3.3. custom_tbl (string) := "cfg_custom"
 
-   Name  of  table  used  for  extra param declaration (group_name, name,
-   type, min/max value, description).
+   Name of table used for extra param declaration (group_name, name, type,
+   min/max value, description).
 
 4. Examples
 
    Example 1.2. Content of tables
         cfg_transl table:
-        group_name|name|cfg_table|cfg_table_group_name_field|cfg_table_name_fie
-ld|cfg_table_value_field
+        group_name|name|cfg_table|cfg_table_group_name_field|cfg_table_name_fiel
+d|cfg_table_value_field
         core|use_dst_blacklist|cfg_dns|||
         core|dst_blacklist_mem|cfg_dns|||
         core|dst_blacklist_expire|||
-        my|route_addr|cfg_my|my_group_name|my_name|my_value     ; overrides <de
-fault> values
+        my|route_addr|cfg_my|my_group_name|my_name|my_value     ; overrides <def
+ault> values
         my|use_rtp_proxy|cfg_my|my_group_name|my_name|my_value
-        *|*|||| ; matches all param ids, points to tables defined in row <defau
-lt>
+        *|*|||| ; matches all param ids, points to tables defined in row <defaul
+t>
         <default>||cfg_var|group_name|name|value  ; default cfg_table* values
 
         cfg_custom table:
diff --git a/modules/cfg_db/cfg_db.c b/modules/cfg_db/cfg_db.c
index a571ef3..a1d13a1 100644
--- a/modules/cfg_db/cfg_db.c
+++ b/modules/cfg_db/cfg_db.c
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2007 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,9 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History
- * -------
- *  2008-01-05	Initial version (tma)
  */
 
 #include "../../sr_module.h"
diff --git a/modules/cfg_db/doc/cfg_db.xml b/modules/cfg_db/doc/cfg_db.xml
index 720cd2e..42312ef 100644
--- a/modules/cfg_db/doc/cfg_db.xml
+++ b/modules/cfg_db/doc/cfg_db.xml
@@ -37,7 +37,7 @@
 		API then driver is notified and has chance to set value (of any
 		parameter) based on value taken from database. It's primarily
 		targeted for interfacing with 3rd party software which is aware
-		of the Kamailio configuration.
+		of the &kamailio; configuration.
 		</para>
 		<para>
 		A parameter is uniquely identified by a <emphasis>group_name</emphasis> plus a
@@ -56,8 +56,8 @@
 		in the second step using the same procedure as C-code parameters.
 		</para>
 		<para>
-		The module does not reflect changes made in parameters when &ser; is running.
-		It just declares variables and assigns values when &ser; is starting. That's all.
+		The module does not reflect changes made in parameters when &kamailio; is running.
+		It just declares variables and assigns values when &kamailio; is starting. That's all.
 		</para>
 	</section>
 
diff --git a/modules/cfg_rpc/Makefile b/modules/cfg_rpc/Makefile
index fbb72ed..6be8b1b 100644
--- a/modules/cfg_rpc/Makefile
+++ b/modules/cfg_rpc/Makefile
@@ -1,5 +1,3 @@
-# $Id$
-#
 # cfg_rpc module makefile
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
diff --git a/modules/cfg_rpc/README b/modules/cfg_rpc/README
index 6827a60..ea0df0e 100644
--- a/modules/cfg_rpc/README
+++ b/modules/cfg_rpc/README
@@ -1,4 +1,3 @@
-
 cfg_rpc Module
 
 Miklos Tirpak
@@ -6,7 +5,7 @@ Miklos Tirpak
    <miklos at iptel.org>
 
    Copyright � 2007 iptelorg GmbH
-     _________________________________________________________________
+     __________________________________________________________________
 
    Table of Contents
 
@@ -78,18 +77,18 @@ Chapter 1. Admin Guide
 
 1. Overview
 
-   The  module  implements  RPC  commands  to  set  and get configuration
-   variables  on-the-fly, that are declared by SIP Router core and by the
+   The module implements RPC commands to set and get configuration
+   variables on-the-fly, that are declared by Kamailio core and by the
    modules.
 
-   For  example, it can be used to fine-tune values for global parameters
-   such  as  debug,  tcp/sctp/dns  attributes, a.s.o. without the need of
-   restart.
+   For example, it can be used to fine-tune values for global parameters
+   such as debug, tcp/sctp/dns attributes, without the need of restart.
 
-   RPC  connector  modules,  such  as  "ctl"  or "xmlrpc", although not a
-   dependecy,  should  be  loaded  in  order  to execute the RPC commands
-   exported  by this module. When ctl module is loaded, the tool 'kamcmd'
-   can be used to execute the RPC commands implemented in this module.
+   RPC connector modules, such as "ctl" or "xmlrpc", although not a
+   dependecy, should be loaded in order to execute the RPC commands
+   exported by this module. When the ctl module is loaded, the tool
+   'kamcmd' can be used to execute the RPC commands implemented in this
+   module.
 
 2. Dependencies
 
@@ -103,7 +102,7 @@ Chapter 1. Admin Guide
 
 2.2. External Libraries or Applications
 
-   The  following  libraries  or  applications  must  be installed before
+   The following libraries or applications must be installed before
    running SIP Router with this module loaded:
      * None.
 
@@ -128,12 +127,11 @@ Chapter 1. Admin Guide
    3.17. cfg.add_group_inst
    3.18. cfg.del_group_inst
 
-   The  module  implements  the  RPC  commands  documented  in  the  next
-   sections.
+   The module implements the RPC commands documented in the next sections.
 
 3.1. cfg.list
 
-   cfg.list  -  List  the  configuration  variables. The function has one
+   cfg.list - List the configuration variables. The function has one
    optional parameter: group name.
 
    Example 1.1. Use cfg.get RPC command
@@ -143,8 +141,8 @@ Chapter 1. Admin Guide
 
 3.2. cfg.get
 
-   cfg.get  -  Get  the  value  of a configuration variable. The function
-   accepts  two parameters: group name, variable name. The group name can
+   cfg.get - Get the value of a configuration variable. The function
+   accepts two parameters: group name, variable name. The group name can
    optionally contain the group instance id, for example foo[5].
 
    Example 1.2. Use cfg.get RPC command
@@ -154,10 +152,10 @@ Chapter 1. Admin Guide
 
 3.3. cfg.seti
 
-   cfg.seti  -  Set  the value of a configuration variable and commit the
+   cfg.seti - Set the value of a configuration variable and commit the
    change immediately. The function accepts three parameters: group name,
-   variable  name,  integer  value. The group name can optionally contain
-   the group instance id, for example foo[5].
+   variable name, integer value. The group name can optionally contain the
+   group instance id, for example foo[5].
 
    Example 1.3. Use cfg.seti RPC command
 ...
@@ -170,7 +168,7 @@ Chapter 1. Admin Guide
 
 3.5. cfg.sets
 
-   cfg.sets  -  Set  the value of a configuration variable and commit the
+   cfg.sets - Set the value of a configuration variable and commit the
    change immediately. The function accepts three parameters: group name,
    variable name, string value. The group name can optionally contain the
    group instance id, for example foo[5].
@@ -181,51 +179,51 @@ Chapter 1. Admin Guide
 
 3.7. cfg.set
 
-   cfg.set  -  Set  the  value of a configuration variable and commit the
-   change  immediately. This is a wrapper command for cfg.set_now_int and
-   cfg.set_now_string  depending  on  the type of the value provided. The
-   function   accepts   three  parameters:  group  name,  variable  name,
-   int/string  value.  The  group  name  can optionally contain the group
+   cfg.set - Set the value of a configuration variable and commit the
+   change immediately. This is a wrapper command for cfg.set_now_int and
+   cfg.set_now_string depending on the type of the value provided. The
+   function accepts three parameters: group name, variable name,
+   int/string value. The group name can optionally contain the group
    instance id, for example foo[5].
 
 3.8. cfg.del
 
-   cfg.del  -  Delete  the value of a configuration variable from a group
-   instance  and commit the change immediately. The value is reset to the
+   cfg.del - Delete the value of a configuration variable from a group
+   instance and commit the change immediately. The value is reset to the
    default value and it follows the changes of that. The function accepts
    two parameters: group name, variable name. The group name must contain
    the group instance id, for example foo[5].
 
 3.9. cfg.set_delayed_int
 
-   cfg.set_delayed_int  - Prepare the change of a configuration variable,
-   but  does  not  commit  the  new value yet. The function accepts three
-   parameters:  group  name, variable name, integer value. The group name
+   cfg.set_delayed_int - Prepare the change of a configuration variable,
+   but does not commit the new value yet. The function accepts three
+   parameters: group name, variable name, integer value. The group name
    can optionally contain the group instance id, for example foo[5].
 
 3.10. cfg.set_delayed_string
 
-   cfg.set_delayed_string   -  Prepare  the  change  of  a  configuration
-   variable,  but does not commit the new value yet. The function accepts
-   three  parameters:  group name, variable name, string value. The group
+   cfg.set_delayed_string - Prepare the change of a configuration
+   variable, but does not commit the new value yet. The function accepts
+   three parameters: group name, variable name, string value. The group
    name can optionally contain the group instance id, for example foo[5].
 
 3.11. cfg.set_delayed
 
-   cfg.set_delayed  - Prepare the change of a configuration variable, but
-   does  not  commit  the  new  value  yet. This is a wrapper command for
-   cfg.set_delayed_int  and  cfg.set_delayed_string depending on the type
-   of  the  value  provided. The function accepts three parameters: group
-   name,  variable  name, int/string value. The group name can optionally
-   contain the group instance id, for example foo[5].
+   cfg.set_delayed - Prepare the change of a configuration variable, but
+   does not commit the new value yet. This is a wrapper command for
+   cfg.set_delayed_int and cfg.set_delayed_string depending on the type of
+   the value provided. The function accepts three parameters: group name,
+   variable name, int/string value. The group name can optionally contain
+   the group instance id, for example foo[5].
 
 3.12. cfg.del_delayed
 
    cfg.del_delayed - Prepare the deletion of the value of a configuration
-   variable  from  a  group instance, but does not commit the change yet.
-   The  value is reset to the default value and it follows the changes of
-   that.  The function accepts two parameters: group name, variable name.
-   The group name must contain the group instance id, for example foo[5].
+   variable from a group instance, but does not commit the change yet. The
+   value is reset to the default value and it follows the changes of that.
+   The function accepts two parameters: group name, variable name. The
+   group name must contain the group instance id, for example foo[5].
 
 3.13. cfg.commit
 
@@ -234,27 +232,27 @@ Chapter 1. Admin Guide
 
 3.14. cfg.rollback
 
-   cfg.rollback  -  Drop the prepared configuration changes. The function
+   cfg.rollback - Drop the prepared configuration changes. The function
    does not have any parameters.
 
 3.15. cfg.help
 
-   cfg.help  -  Print  the  description  of a configuration variable. The
+   cfg.help - Print the description of a configuration variable. The
    function accepts two parameters: group name, variable name.
 
 3.16. cfg.diff
 
-   cfg.diff  -  List the pending configuration changes that have not been
+   cfg.diff - List the pending configuration changes that have not been
    committed yet. The function does not have any parameters.
 
 3.17. cfg.add_group_inst
 
-   cfg.add_group_inst  -  Add a new instance to an existing configuration
-   group.  The  function  accepts one parameter: group name[instance id],
-   for example foo[5].
+   cfg.add_group_inst - Add a new instance to an existing configuration
+   group. The function accepts one parameter: group name[instance id], for
+   example foo[5].
 
 3.18. cfg.del_group_inst
 
-   cfg.del_group_inst  -  Delete an instance of an existing configuration
-   group.  The  function  accepts one parameter: group name[instance id],
-   for example foo[5].
+   cfg.del_group_inst - Delete an instance of an existing configuration
+   group. The function accepts one parameter: group name[instance id], for
+   example foo[5].
diff --git a/modules/cfg_rpc/doc/cfg_rpc.xml b/modules/cfg_rpc/doc/cfg_rpc.xml
index c7a9990..b57eea3 100644
--- a/modules/cfg_rpc/doc/cfg_rpc.xml
+++ b/modules/cfg_rpc/doc/cfg_rpc.xml
@@ -31,17 +31,17 @@
 	<para>
 	    The module implements RPC commands to set and get
 	    configuration variables on-the-fly, that are declared
-		by &siprouter; core and by the modules.
+		by &kamailio; core and by the modules.
 	</para>
 	<para>
 		For example, it can be used to fine-tune values for
 		global parameters such as debug, tcp/sctp/dns attributes,
-	    a.s.o. without the need of restart.
+	    	without the need of restart.
 	</para>
 	<para>
 		RPC connector modules, such as <quote>ctl</quote> or <quote>xmlrpc</quote>, although
 		not a dependecy, should be loaded in order to execute
-		the RPC commands exported by this module. When ctl module
+		the RPC commands exported by this module. When the ctl module
 		is loaded, the tool '&sercmd;' can be used to execute
 		the RPC commands implemented in this module.
 	</para>
diff --git a/modules/cfgutils/Makefile b/modules/cfgutils/Makefile
index c92c078..b9ec198 100644
--- a/modules/cfgutils/Makefile
+++ b/modules/cfgutils/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # cfgutils module makefile
 #
diff --git a/modules/cfgutils/README b/modules/cfgutils/README
index 48307f1..be905fe 100644
--- a/modules/cfgutils/README
+++ b/modules/cfgutils/README
@@ -22,14 +22,18 @@ Olle E. Johansson
 
    <oej at edvina.net>
 
+Juha Heinanen
+
+   <jh at tutpro.com>
+
 Edited by
 
 Daniel-Constantin Mierla
 
    <miconda at gmail.com>
 
-   Copyright � 2013, 2007, 2008, 2004 Edvina AB, 1und1 Internet AG, BASIS
-   AudioNet GmbH, Elena-Ramona Modroiu, FhG FOKUS
+   Copyright (c) 2014, 2013, 2007, 2008, 2004 Edvina AB, 1und1 Internet
+   AG, BASIS AudioNet GmbH, Elena-Ramona Modroiu, Juha Heinanen, FhG FOKUS
      __________________________________________________________________
 
    Table of Contents
@@ -79,9 +83,15 @@ Daniel-Constantin Mierla
               5.8. is_gflag
               5.9. get_gflags
 
-        6. Exported pseudo-variables
+        6. RPC Commands
+
+              6.1. cfgutils.set_gflag
+              6.2. cfgutils.reset_gflag
+              6.3. cfgutils.is_gflag
 
-              6.1. $RANDOM
+        7. Exported pseudo-variables
+
+              7.1. $RANDOM
 
    List of Examples
 
@@ -117,7 +127,10 @@ Daniel-Constantin Mierla
    1.30. reset_gflag usage
    1.31. is_gflag usage
    1.32. get_gflags usage
-   1.33. RANDOM pseudo-variable usage
+   1.33. cfgutils.set_gflag usage
+   1.34. cfgutils.reset_gflag usage
+   1.35. cfgutils.is_gflag usage
+   1.36. RANDOM pseudo-variable usage
 
 Chapter 1. Admin Guide
 
@@ -166,9 +179,15 @@ Chapter 1. Admin Guide
         5.8. is_gflag
         5.9. get_gflags
 
-   6. Exported pseudo-variables
+   6. RPC Commands
+
+        6.1. cfgutils.set_gflag
+        6.2. cfgutils.reset_gflag
+        6.3. cfgutils.is_gflag
 
-        6.1. $RANDOM
+   7. Exported pseudo-variables
+
+        7.1. $RANDOM
 
 1. Overview
 
@@ -218,8 +237,8 @@ Chapter 1. Admin Guide
    The size of bitmap is 32.
 
    The module exports external commands that can be used to change the
-   global flags via Management Interface. The MI commands are:
-   "set_gflag", "reset_gflag" and "is_gflag".
+   global flags via Management Interface and RPC. See relevant sections
+   below.
 
 2. Dependencies
 
@@ -338,7 +357,7 @@ rand_reset_prob();
 ...
 rand_get_prob();
 
-4.5. sleep(time)
+4.5.  sleep(time)
 
    Waits "time" seconds.
 
@@ -353,7 +372,7 @@ rand_get_prob();
 sleep("1");
 ...
 
-4.6. usleep(time)
+4.6.  usleep(time)
 
    Waits "time" micro-seconds.
 
@@ -369,7 +388,7 @@ sleep("1");
 usleep("5000");
 ...
 
-4.7. abort()
+4.7.  abort()
 
    Debugging function that aborts the server. Depending on the
    configuration of the server a core dump will be created.
@@ -382,7 +401,7 @@ usleep("5000");
 abort();
 ...
 
-4.8. pkg_status()
+4.8.  pkg_status()
 
    Debugging function that dumps the status for the private (PKG) memory.
    This information is logged to the default log facility, depending on
@@ -397,7 +416,7 @@ abort();
 pkg_status();
 ...
 
-4.9. pkg_summary()
+4.9.  pkg_summary()
 
    Debugging function that dumps the summary for the private (PKG) memory
    usage. This information is logged to the default log facility,
@@ -412,7 +431,7 @@ pkg_status();
 pkg_summary();
 ...
 
-4.10. shm_status()
+4.10.  shm_status()
 
    Debugging function that dumps the status for the shared (SHM) memory.
    This information is logged to the default log facility, depending on
@@ -427,7 +446,7 @@ pkg_summary();
 shm_status();
 ...
 
-4.11. shm_summary()
+4.11.  shm_summary()
 
    Debugging function that dumps the summary for the shared (SHM) memory
    usage. This information is logged to the default log facility,
@@ -613,7 +632,7 @@ $ kamctl fifo rand_set_prob 10
 
    This command don't need a parameter.
 
-   Example 1.25. rand_reset_prob usage
+   Example 1.25.  rand_reset_prob usage
 ...
 $ kamctl fifo rand_reset_prob
 ...
@@ -677,7 +696,7 @@ $ kamctl fifo set_gflag 0x3
    The parameter value must be a bitmask in decimal or hexadecimal format.
    The bitmask has a 32 bit size.
 
-   Example 1.30. reset_gflag usage
+   Example 1.30.  reset_gflag usage
 ...
 $ kamctl fifo reset_gflag 1
 $ kamctl fifo reset_gflag 0x3
@@ -716,22 +735,74 @@ TRUE
    Return the bitmap with all flags. The function gets no parameters and
    returns the bitmap in hexadecimal and decimal format.
 
-   Example 1.32. get_gflags usage
+   Example 1.32.  get_gflags usage
 ...
 $ kamctl fifo get_gflags
 0x3039
 12345
 ...
 
-6. Exported pseudo-variables
+6. RPC Commands
+
+   6.1. cfgutils.set_gflag
+   6.2. cfgutils.reset_gflag
+   6.3. cfgutils.is_gflag
+
+6.1. cfgutils.set_gflag
+
+   Set the value of some flags (specified by bitmask) to 1.
+
+   The parameter value must be a bitmask in decimal or hexadecimal format.
+   The bitmask has a 32 bit size.
+
+   Example 1.33. cfgutils.set_gflag usage
+...
+$ kamctl cfgutils.set_gflag s:1
+...
+
+6.2. cfgutils.reset_gflag
+
+   Reset the value of some flags to 0.
+
+   Reset the value of some flags (specified by bitmask) to 1.
+
+   The parameter value must be a bitmask in decimal or hexadecimal format.
+   The bitmask has a 32 bit size.
+
+   Example 1.34.  cfgutils.reset_gflag usage
+...
+$ kamctl cfgutils.reset_gflag s:0x1
+...
+
+6.3. cfgutils.is_gflag
+
+   Returns string "TRUE" if all the flags from the given set are set and
+   "FALSE" if at least one is not set.
+
+   The parameter value must be a bitmask in decimal or hexadecimal format.
+   The bitmask has a 32 bit size.
+
+   Example 1.35. cfgutils.is_gflag usage
+...
+$ kamctl cfgutils.set_gflag s:1024
+$ kamctl cfgutils.is_gflag s:1024
+TRUE
+$ kamctl cfgutils.is_gflag s:1023
+FALSE
+$ kamctl cfgutils.set_gflag s:0x7FFF
+$ kamctl cfgutils.is_gflag s:1023
+TRUE
+...
+
+7. Exported pseudo-variables
 
-   6.1. $RANDOM
+   7.1. $RANDOM
 
-6.1. $RANDOM
+7.1. $RANDOM
 
    Returns a random value from the [0 - 2^31) range.
 
-   Example 1.33. RANDOM pseudo-variable usage
+   Example 1.36. RANDOM pseudo-variable usage
 ...
 if (rand_event()) {
   $avp(i:10) = ($RANDOM / 16777216); # 2^24
diff --git a/modules/cfgutils/cfgutils.c b/modules/cfgutils/cfgutils.c
index da07a4a..c658892 100644
--- a/modules/cfgutils/cfgutils.c
+++ b/modules/cfgutils/cfgutils.c
@@ -72,6 +72,7 @@
 #include "../../hashes.h"
 #include "../../locking.h"
 #include "../../route.h"
+#include "../../rpc_lookup.h"
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/types.h>
@@ -215,6 +216,106 @@ static mi_export_t mi_cmds[] = {
 };
 
 
+static void rpc_is_gflag(rpc_t* rpc, void* c)
+{
+	str flag_str;
+	unsigned int flag;
+	
+	if (rpc->scan(c, "S", &flag_str) != 1) {
+		rpc->fault(c, 400, "flag parameter error");
+		return;
+	}
+
+	flag = 0;
+	if ((strno2int(&flag_str, &flag) < 0) || !flag) {
+		rpc->fault(c, 400, "incorrect flag parameter value");
+		return;
+	}
+
+	if (((*gflags) & flag) == flag)
+		rpc->add(c, "s", "TRUE");
+	else
+		rpc->add(c, "s", "FALSE");
+
+	return;
+}
+
+
+static void rpc_set_gflag(rpc_t* rpc, void* c)
+{
+	str flag_str;
+	unsigned int flag;
+	
+	if (rpc->scan(c, "S", &flag_str) != 1) {
+		rpc->fault(c, 400, "flag parameter error");
+		return;
+	}
+
+	flag = 0;
+	if ((strno2int(&flag_str, &flag) < 0) || !flag) {
+		rpc->fault(c, 400, "incorrect flag parameter value '%.*s'",
+			   flag_str.len, flag_str.s);
+		return;
+	}
+
+	lock_get(gflags_lock);
+	(*gflags) |= flag;
+	lock_release(gflags_lock);
+	
+	return;
+}
+
+
+static void rpc_reset_gflag(rpc_t* rpc, void* c)
+{
+	str flag_str;
+	unsigned int flag;
+	
+	if (rpc->scan(c, "S", &flag_str) != 1) {
+		rpc->fault(c, 400, "flag parameter error");
+		return;
+	}
+
+	flag = 0;
+	if ((strno2int(&flag_str, &flag) < 0) || !flag) {
+		rpc->fault(c, 400, "incorrect flag parameter value");
+		return;
+	}
+
+	lock_get(gflags_lock);
+	(*gflags) &= ~ flag;
+	lock_release(gflags_lock);
+	
+	return;
+}
+
+
+static const char* is_gflag_doc[2] = {
+	"Checks if the bits specified by the argument are all set.",
+	0
+};
+
+
+static const char* set_gflag_doc[2] = {
+	"Sets the bits specified by the argument.",
+	0
+};
+
+
+static const char* reset_gflag_doc[2] = {
+	"Resets the bits specified by the argument.",
+	0
+};
+
+
+static rpc_export_t rpc_cmds[] = {
+	{"cfgutils.is_gflag", rpc_is_gflag, is_gflag_doc, 0},
+	{"cfgutils.set_gflag", rpc_set_gflag, set_gflag_doc, 0},
+	{"cfgutils.reset_gflag", rpc_reset_gflag, reset_gflag_doc, 0},
+	{0, 0, 0, 0}
+};
+
+
 static pv_export_t mod_items[] = {
 	{ {"RANDOM", sizeof("RANDOM")-1}, PVT_OTHER, pv_get_random_val, 0,
 		0, 0, 0, 0 },
@@ -774,6 +875,12 @@ static int route_exists(struct sip_msg *msg, char *route)
 
 static int mod_init(void)
 {
+	/* Register RPC commands */
+	if (rpc_register_array(rpc_cmds)!=0) {
+		LM_ERR("failed to register RPC commands\n");
+		return -1;
+	}
+
 	if(register_mi_mod(exports.name, mi_cmds)!=0)
 	{
 		LM_ERR("failed to register MI commands\n");
diff --git a/modules/cfgutils/doc/cfgutils.xml b/modules/cfgutils/doc/cfgutils.xml
index ec45314..9bb66ee 100644
--- a/modules/cfgutils/doc/cfgutils.xml
+++ b/modules/cfgutils/doc/cfgutils.xml
@@ -42,6 +42,11 @@
 		<surname>Johansson</surname>
 		<email>oej at edvina.net</email>
 		</author>
+		<author>
+		<firstname>Juha</firstname>
+		<surname>Heinanen</surname>
+		<email>jh at tutpro.com</email>
+		</author>
 		<editor>
 		<firstname>Daniel-Constantin</firstname>
 		<surname>Mierla</surname>
@@ -49,6 +54,7 @@
 		</editor>
 	</authorgroup>
 	<copyright>
+		<year>2014</year>
 		<year>2013</year>
 		<year>2007</year>
 		<year>2008</year>
@@ -57,6 +63,7 @@
 		<holder>1und1 Internet AG</holder>
 		<holder>BASIS AudioNet GmbH</holder>
 		<holder>Elena-Ramona Modroiu</holder>
+		<holder>Juha Heinanen</holder>
 		<holder>&fhg;</holder>
 	</copyright>
 	</bookinfo>
diff --git a/modules/cfgutils/doc/cfgutils_admin.xml b/modules/cfgutils/doc/cfgutils_admin.xml
index bc50a85..f62fd68 100644
--- a/modules/cfgutils/doc/cfgutils_admin.xml
+++ b/modules/cfgutils/doc/cfgutils_admin.xml
@@ -73,9 +73,8 @@
 	</para>
 	<para>
 	The module exports external commands that can be used to change
-	the global flags via Management Interface. The MI commands are:
-	<quote>set_gflag</quote>, <quote>reset_gflag</quote> and
-	<quote>is_gflag</quote>.
+	the global flags via Management Interface and RPC. See relevant
+	sections below.
 	</para>
 	</section>
 	<section>
@@ -807,6 +806,78 @@ $ &ctltool; fifo get_gflags
 			</example>
 		</section>
 </section>
+	<section>
+		<title><acronym>RPC</acronym> Commands</title>
+		<section  id="cfgutils.rpc.set_gflag">
+			<title><function moreinfo="none">cfgutils.set_gflag</function></title>
+			<para>
+			Set the value of some flags (specified by bitmask) to 1.
+			</para>
+			<para>
+			The parameter value must be a bitmask in decimal or
+			hexadecimal format.  The bitmask has a 32 bit size.
+			</para>
+			<example>
+			<title><function moreinfo="none">cfgutils.set_gflag</function> usage</title>
+			<programlisting format="linespecific">
+...
+$ &ctltool; cfgutils.set_gflag s:1
+...
+</programlisting>
+			</example>
+
+		</section>
+		<section  id="cfgutils.rpc.reset_gflag">
+			<title><function moreinfo="none">cfgutils.reset_gflag</function></title>
+			<para>
+			Reset the value of some flags to 0.
+			</para>
+			<para>
+			Reset the value of some flags (specified by bitmask)
+			to 1.
+			</para>
+			<para>
+			The parameter value must be a bitmask in decimal or
+			hexadecimal format.  The bitmask has a 32 bit size.
+			</para>
+			<example>
+			<title>
+				<function moreinfo="none">cfgutils.reset_gflag</function> usage</title>
+			<programlisting format="linespecific">
+...
+$ &ctltool; cfgutils.reset_gflag s:0x1
+...
+</programlisting>
+			</example>
+		</section>
+		<section  id="cfgutils.rpc.is_gflag">
+			<title><function moreinfo="none">cfgutils.is_gflag</function></title>
+			<para>
+			Returns string "TRUE" if all the
+			flags from the given set are set
+			and "FALSE" if at least one is not set.
+			</para>
+			<para>
+			The parameter value must be a bitmask in decimal or
+			hexadecimal format.  The bitmask has a 32 bit size.
+			</para>
+			<example>
+			<title><function moreinfo="none">cfgutils.is_gflag</function> usage</title>
+			<programlisting format="linespecific">
+...
+$ &ctltool; cfgutils.set_gflag s:1024
+$ &ctltool; cfgutils.is_gflag s:1024
+TRUE
+$ &ctltool; cfgutils.is_gflag s:1023
+FALSE
+$ &ctltool; cfgutils.set_gflag s:0x7FFF
+$ &ctltool; cfgutils.is_gflag s:1023
+TRUE
+...
+</programlisting>
+			</example>
+		</section>
+</section>
 	
 <section>
 	<title>Exported pseudo-variables</title>
diff --git a/modules/cnxcc/Makefile b/modules/cnxcc/Makefile
index be6c1f1..e5c69df 100644
--- a/modules/cnxcc/Makefile
+++ b/modules/cnxcc/Makefile
@@ -1,6 +1,5 @@
-# $Id$
 #
-# example module makefile
+# cnxcc module makefile
 #
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
@@ -9,6 +8,7 @@ include ../../Makefile.defs
 auto_gen=
 NAME=cnxcc.so
 
+LIBS=-lhiredis -levent
 DEFS+=-DOPENSER_MOD_INTERFACE
 SERLIBPATH=../../lib
 SER_LIBS+=$(SERLIBPATH)/kmi/kmi
diff --git a/modules/cnxcc/README b/modules/cnxcc/README
index da1e5f6..87605dd 100644
--- a/modules/cnxcc/README
+++ b/modules/cnxcc/README
@@ -1,10 +1,12 @@
 cnxcc Module
 
-Carlos Ruiz Diaz
+Carlos Ruiz Díaz
 
    ConexionGroup S.A.
 
-   Copyright © 2013 Carlos Ruiz Diaz, carlos.ruizdiaz at gmail.com
+   Copyright © 2013 Carlos Ruiz Díaz, carlos.ruizdiaz at gmail.com
+
+   Copyright © 2014 Carlos Ruiz Díaz, carlos at latamvoices.com
      __________________________________________________________________
 
    Table of Contents
@@ -15,10 +17,11 @@ Carlos Ruiz Diaz
         2. Dependencies
 
               2.1. Modules
+              2.2. Libraries
 
         3. Parameters
 
-              3.1. dlg_flag (integer)
+              3.1. redis (integer)
               3.2. credit_check_period (integer)
 
         4. Functions
@@ -58,10 +61,11 @@ Chapter 1. Admin Guide
    2. Dependencies
 
         2.1. Modules
+        2.2. Libraries
 
    3. Parameters
 
-        3.1. dlg_flag (integer)
+        3.1. redis (integer)
         3.2. credit_check_period (integer)
 
    4. Functions
@@ -106,7 +110,7 @@ Chapter 1. Admin Guide
    that are equal to the cost per second of both calls.
 
    If your accounting program does not maintain the state of the call in
-   real time, this module can provide you that ability.
+   real time, this module can provide you with that ability.
 
    Cnxcc can also provide more common means of monitoring, i.e., by time
    limit or by maximum simultaneous calls.
@@ -114,25 +118,31 @@ Chapter 1. Admin Guide
 2. Dependencies
 
    2.1. Modules
+   2.2. Libraries
 
 2.1. Modules
 
    The following module must be loaded before this module:
      * dialog
 
+2.2. Libraries
+
+   The following module must be loaded before this module:
+     * hiredis-devel >= 0.11.0
+     * libevent-devel >= 2.0.18-2
+
 3. Parameters
 
-   3.1. dlg_flag (integer)
+   3.1. redis (integer)
    3.2. credit_check_period (integer)
 
-3.1.  dlg_flag (integer)
+3.1.  redis (integer)
 
-   Flag to indicate if the dialog must be monitored or not. Messages are
-   flagged with this value if we call one of the monitoring functions.
+   Redis datasource connection information
 
    Example 1.1. dlg_flag
 ...
-modparam("cnxcc", "dlg_flag", 29)
+modparam("cnxcc", "redis", "addr=127.0.0.1;port=6379;db=1")
 ...
 
 3.2. credit_check_period (integer)
diff --git a/modules/cnxcc/cnxcc.c b/modules/cnxcc/cnxcc.c
index 4feba4f..e869af4 100644
--- a/modules/cnxcc/cnxcc.c
+++ b/modules/cnxcc/cnxcc.c
@@ -18,7 +18,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  */
 #include <time.h>
@@ -28,17 +28,17 @@
 
 #include "cnxcc.h"
 
-void get_datetime(str *dest)
+inline void get_datetime(str *dest)
 {
 	timestamp2isodt(dest, get_current_timestamp());
 }
 
-unsigned int get_current_timestamp()
+inline unsigned int get_current_timestamp()
 {
 	return time(NULL);
 }
 
-int timestamp2isodt(str *dest, unsigned int timestamp)
+inline int timestamp2isodt(str *dest, unsigned int timestamp)
 {
 	time_t  		tim;
 	struct tm 		*tmPtr;
diff --git a/modules/cnxcc/cnxcc.h b/modules/cnxcc/cnxcc.h
index 6780bdf..9454e16 100644
--- a/modules/cnxcc/cnxcc.h
+++ b/modules/cnxcc/cnxcc.h
@@ -18,7 +18,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  */
 
@@ -31,9 +31,9 @@
 #define DATETIME_LENGTH		DATETIME_SIZE - 1
 
 
-void get_datetime(str *dest);
-unsigned int get_current_timestamp();
-int timestamp2isodt(str *dest, unsigned int timestamp);
+inline void get_datetime(str *dest);
+inline unsigned int get_current_timestamp();
+inline int timestamp2isodt(str *dest, unsigned int timestamp);
 double str2double(str *string);
 
 #endif /* _CNXCC_H */
diff --git a/modules/cnxcc/cnxcc_check.c b/modules/cnxcc/cnxcc_check.c
index 1f4a3b1..6f10419 100644
--- a/modules/cnxcc/cnxcc_check.c
+++ b/modules/cnxcc/cnxcc_check.c
@@ -18,7 +18,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  */
 
@@ -30,43 +30,41 @@
 #include "cnxcc_mod.h"
 #include "cnxcc.h"
 #include "cnxcc_check.h"
+#include "cnxcc_redis.h"
 
 extern data_t _data;
 
-void check_calls_by_money(unsigned int ticks, void *param)
-{
-	struct str_hash_entry *h_entry 	= NULL,
-			  *tmp		= NULL;
-	call_t *tmp_call		= NULL;
+void check_calls_by_money(unsigned int ticks, void *param) {
+	struct str_hash_entry *h_entry = NULL,
+	                      *tmp = NULL;
+	call_t *tmp_call = NULL;
 	int i;
 
 	lock_get(&_data.money.lock);
+
 	if (_data.money.credit_data_by_client->table)
 		for(i = 0; i < _data.money.credit_data_by_client->size; i++)
-			clist_foreach_safe(&_data.money.credit_data_by_client->table[i], h_entry, tmp, next)
-			{
-				credit_data_t *credit_data	= (credit_data_t *) h_entry->u.p;
-				call_t *call			= NULL;
-				double total_consumed_money	= 0;
+			clist_foreach_safe(&_data.money.credit_data_by_client->table[i], h_entry, tmp, next) {
+				credit_data_t *credit_data = (credit_data_t *) h_entry->u.p;
+				call_t *call = NULL;
+				double total_consumed_money = 0, consumption_diff = 0/*, distributed_consumption = 0*/;
 
-				if (i > SAFE_ITERATION_THRESHOLD)
-				{
+/*				if (i > SAFE_ITERATION_THRESHOLD) {
 					LM_ERR("Too many iterations for this loop: %d\n", i);
 					break;
-				}
+				}*/
+
 				lock_get(&credit_data->lock);
 
-				clist_foreach_safe(credit_data->call_list, call, tmp_call, next)
-				{
+				clist_foreach_safe(credit_data->call_list, call, tmp_call, next) {
 					int consumed_time = 0;
 
 					if (!call->confirmed)
 						continue;
 
-					consumed_time 		= get_current_timestamp() - call->start_timestamp;
+					consumed_time = get_current_timestamp() - call->start_timestamp;
 
-					if (consumed_time > call->money_based.initial_pulse)
-					{
+					if (consumed_time > call->money_based.initial_pulse) {
 						call->consumed_amount = (call->money_based.cost_per_second * call->money_based.initial_pulse)
 												+
 												call->money_based.cost_per_second *
@@ -74,10 +72,9 @@ void check_calls_by_money(unsigned int ticks, void *param)
 												call->money_based.final_pulse;
 					}
 
-					total_consumed_money	+= call->consumed_amount;
+					total_consumed_money += call->consumed_amount;
 
-					if (call->consumed_amount > call->max_amount)
-					{
+					if (call->consumed_amount > call->max_amount) {
 						LM_ALERT("[%.*s] call has exhausted its credit. Breaking the loop\n", call->sip_data.callid.len, call->sip_data.callid.s);
 						break;
 					}
@@ -89,26 +86,35 @@ void check_calls_by_money(unsigned int ticks, void *param)
 																			call->consumed_amount
 																			);
 				}
-				
-				if (credit_data->concurrent_calls == 0)
-				{
+
+				if (credit_data->concurrent_calls == 0) {
 					lock_release(&credit_data->lock);
 					continue;
 				}
 
-				credit_data->consumed_amount	= credit_data->ended_calls_consumed_amount + total_consumed_money;
+				if (_data.redis) {
+					LM_INFO("ec=%f, ca=%f, ca2=%f", credit_data->ended_calls_consumed_amount, total_consumed_money, credit_data->consumed_amount);
 
-				LM_DBG("Client [%.*s] | Ended-Calls-Credit-Spent: %f  TotalCredit/MaxCredit: %f/%f\n", credit_data->call_list->client_id.len, credit_data->call_list->client_id.s,
-																									credit_data->ended_calls_consumed_amount,
-																									credit_data->consumed_amount,
-																									credit_data->max_amount);
+					consumption_diff = credit_data->ended_calls_consumed_amount + total_consumed_money - credit_data->consumed_amount;
+					if (consumption_diff > 0)
+						redis_incr_by_double(credit_data, "consumed_amount", consumption_diff);
+				}
 
-				if (credit_data->consumed_amount >= credit_data->max_amount)
-				{
-					lock_release(&_data.money.lock);
+				credit_data->consumed_amount = credit_data->ended_calls_consumed_amount + total_consumed_money /* + distributed_consumption */;
+
+				LM_DBG("Client [%.*s] | Ended-Calls-Credit-Spent: %f  TotalCredit/MaxCredit: %f/%f\n",
+							credit_data->call_list->client_id.len, credit_data->call_list->client_id.s,
+							credit_data->ended_calls_consumed_amount,
+							credit_data->consumed_amount,
+							credit_data->max_amount);
+
+				if (credit_data->consumed_amount >= credit_data->max_amount) {
 					terminate_all_calls(credit_data);
+
+					// make sure the rest of the servers kill the calls belonging to this customer
+					redis_publish_to_kill_list(credit_data);
 					lock_release(&credit_data->lock);
-					return;
+					break;
 				}
 
 				lock_release(&credit_data->lock);
@@ -117,43 +123,40 @@ void check_calls_by_money(unsigned int ticks, void *param)
 	lock_release(&_data.money.lock);
 }
 
-void check_calls_by_time(unsigned int ticks, void *param)
-{
-	struct str_hash_entry *h_entry 	= NULL,
-			*tmp		= NULL;
-	call_t *tmp_call		= NULL;
+void check_calls_by_time(unsigned int ticks, void *param) {
+	struct str_hash_entry *h_entry = NULL;
+	struct str_hash_entry *tmp = NULL;
+	call_t *tmp_call = NULL;
 	int i;
 
 	lock_get(&_data.time.lock);
 
 	if (_data.time.credit_data_by_client->table)
 		for(i = 0; i < _data.time.credit_data_by_client->size; i++)
-			clist_foreach_safe(&_data.time.credit_data_by_client->table[i], h_entry, tmp, next)
-			{
-				credit_data_t *credit_data	= (credit_data_t *) h_entry->u.p;
-				call_t *call			= NULL;
-				int total_consumed_secs		= 0;
+			clist_foreach_safe(&_data.time.credit_data_by_client->table[i], h_entry, tmp, next) {
+				credit_data_t *credit_data = (credit_data_t *) h_entry->u.p;
+				call_t *call = NULL;
+				int total_consumed_secs = 0;
+				double consumption_diff = 0/*, distributed_consumption = 0*/;
 
 				lock_get(&credit_data->lock);
 
-				if (i > SAFE_ITERATION_THRESHOLD)
+				/*if (i > SAFE_ITERATION_THRESHOLD)
 				{
-					LM_ERR("Too many iterations for this loop: %d\n", i);
+					LM_ERR("Too many iterations for this loop: %d", i);
 					break;
-				}
+				} */
 
 				LM_DBG("Iterating through calls of client [%.*s]\n", credit_data->call_list->client_id.len, credit_data->call_list->client_id.s);
 
-				clist_foreach_safe(credit_data->call_list, call, tmp_call, next)
-				{
+				clist_foreach_safe(credit_data->call_list, call, tmp_call, next) {
 					if (!call->confirmed)
 						continue;
 
-					call->consumed_amount	= get_current_timestamp() - call->start_timestamp;
+					call->consumed_amount = get_current_timestamp() - call->start_timestamp;
 					total_consumed_secs	+= call->consumed_amount;
 
-					if (call->consumed_amount > call->max_amount)
-					{
+					if (call->consumed_amount > call->max_amount) {
 						LM_ALERT("[%.*s] call has exhausted its time. Breaking the loop\n", call->sip_data.callid.len, call->sip_data.callid.s);
 						break;
 					}
@@ -165,25 +168,31 @@ void check_calls_by_time(unsigned int ticks, void *param)
 																			);
 				}
 
-				if (credit_data->concurrent_calls == 0)
-				{
+				if (credit_data->concurrent_calls == 0) {
 					lock_release(&credit_data->lock);
 					continue;
 				}
 
-				credit_data->consumed_amount	= credit_data->ended_calls_consumed_amount + total_consumed_secs;
+				if (_data.redis) {
+					consumption_diff = credit_data->ended_calls_consumed_amount + total_consumed_secs - credit_data->consumed_amount;
+					if (consumption_diff > 0)
+						redis_incr_by_double(credit_data, "consumed_amount", consumption_diff);
+				}
+
+				credit_data->consumed_amount = credit_data->ended_calls_consumed_amount + total_consumed_secs /*+ distributed_consumption*/;
 
 				LM_DBG("Client [%.*s] | Ended-Calls-Time: %d  TotalTime/MaxTime: %d/%d\n", credit_data->call_list->client_id.len, credit_data->call_list->client_id.s,
 																									(int) credit_data->ended_calls_consumed_amount,
 																									(int) credit_data->consumed_amount,
 																									(int) credit_data->max_amount);
 
-				if (credit_data->consumed_amount >= credit_data->max_amount)
-				{				
-					lock_release(&_data.time.lock);
+				if (credit_data->consumed_amount >= credit_data->max_amount) {
 					terminate_all_calls(credit_data);
+
+					// make sure the rest of the servers kill the calls belonging to this customer
+					redis_publish_to_kill_list(credit_data);
 					lock_release(&credit_data->lock);
-					return;
+					break;
 				}
 
 				lock_release(&credit_data->lock);
diff --git a/modules/cnxcc/cnxcc_check.h b/modules/cnxcc/cnxcc_check.h
index 5032acf..afb8654 100644
--- a/modules/cnxcc/cnxcc_check.h
+++ b/modules/cnxcc/cnxcc_check.h
@@ -18,7 +18,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  */
 
diff --git a/modules/cnxcc/cnxcc_mod.c b/modules/cnxcc/cnxcc_mod.c
index d42ea7d..2c7f03e 100644
--- a/modules/cnxcc/cnxcc_mod.c
+++ b/modules/cnxcc/cnxcc_mod.c
@@ -18,7 +18,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  */
 
@@ -65,154 +65,155 @@
 #include "cnxcc_check.h"
 #include "cnxcc_rpc.h"
 #include "cnxcc_select.h"
+#include "cnxcc_redis.h"
 
 MODULE_VERSION
 
-#define HT_SIZE			229
-#define MODULE_NAME		"cnxcc"
-#define NUMBER_OF_TIMERS	2
+#define HT_SIZE 229
+#define MODULE_NAME	"cnxcc"
+#define NUMBER_OF_TIMERS 2
 
-#define TRUE			1
-#define FALSE			0
+#define TRUE	1
+#define FALSE	!TRUE
 
 data_t _data;
 struct dlg_binds _dlgbinds;
 
-static int fixup_par(void** param, int param_no);
+static int __fixup_pvar(void** param, int param_no);
 
 /*
  *  module core functions
  */
-static int mod_init(void);
-static int child_init(int);
-static int init_hashtable(struct str_hash_table *ht);
+static int __mod_init(void);
+static int __child_init(int);
+static int __init_hashtable(struct str_hash_table *ht);
 
 /*
  * Memory management functions
  */
-static int shm_str_hash_alloc(struct str_hash_table *ht, int size);
-static void free_credit_data_hash_entry(struct str_hash_entry *e);
+static int __shm_str_hash_alloc(struct str_hash_table *ht, int size);
+static void __free_credit_data_hash_entry(struct str_hash_entry *e);
 
 /*
  * PV management functions
  */
-static int pv_parse_calls_param(pv_spec_p sp, str *in);
-static int pv_get_calls(struct sip_msg *msg, pv_param_t *param, pv_value_t *res);
-//static int get_str_pv(struct sip_msg* msg, str *pv_name, str *pvvalue);
+static int __pv_parse_calls_param(pv_spec_p sp, str *in);
+static int __pv_get_calls(struct sip_msg *msg, pv_param_t *param, pv_value_t *res);
 
 /*
  * Billing management functions
  */
-static int set_max_time(struct sip_msg* msg, char* number, char* str2);
-static int update_max_time(struct sip_msg* msg, char* number, char* str2);
-static int set_max_credit(struct sip_msg* msg, char *str_pv_client, char *str_pv_credit, char *str_pv_cps, char *str_pv_inip, char *str_pv_finp);
-static int set_max_channels(struct sip_msg* msg, char* str_pv_client, char* str_pv_max_chan);
-static int get_channel_count(struct sip_msg* msg, char* str_pv_client, char* str_pv_max_chan);
-static int terminate_all(struct sip_msg* msg, char* str_pv_client);
-
-static void start_billing(str *callid, str *from_uri, str *to_uri, str tags[2]);
-static void setup_billing(str *callid, unsigned int h_entry, unsigned int h_id);
-static void stop_billing(str *callid);
-static int add_call_by_cid(str *cid, call_t *call, credit_type_t type);
-static credit_data_t *get_or_create_credit_data_entry(str *client_id, credit_type_t type);
-static call_t *alloc_new_call_by_time(credit_data_t *credit_data, struct sip_msg *msg, int max_secs);
-static call_t *alloc_new_call_by_money(credit_data_t *credit_data, struct sip_msg *msg, double credit, double cost_per_second, int initial_pulse, int final_pulse);
-static void notify_call_termination(sip_data_t *data);
-static void free_call(call_t *call);
-static int has_to_tag(struct sip_msg *msg);
+static int __set_max_time(struct sip_msg* msg, char* number, char* str2);
+static int __update_max_time(struct sip_msg* msg, char* number, char* str2);
+static int __set_max_credit(struct sip_msg* msg, char *str_pv_client, char *str_pv_credit,
+                            char *str_pv_cps, char *str_pv_inip, char *str_pv_finp);
+static int __set_max_channels(struct sip_msg* msg, char* str_pv_client, char* str_pv_max_chan);
+static int __get_channel_count(struct sip_msg* msg, char* str_pv_client, char* str_pv_max_chan);
+static int __terminate_all(struct sip_msg* msg, char* str_pv_client);
+
+static void __start_billing(str *callid, str *from_uri, str *to_uri, str tags[2]);
+static void __setup_billing(str *callid, unsigned int h_entry, unsigned int h_id);
+static void __stop_billing(str *callid);
+static int __add_call_by_cid(str *cid, call_t *call, credit_type_t type);
+static call_t *__alloc_new_call_by_time(credit_data_t *credit_data, struct sip_msg *msg, int max_secs);
+static call_t *__alloc_new_call_by_money(credit_data_t *credit_data, struct sip_msg *msg, double credit,
+		                                 double cost_per_second, int initial_pulse, int final_pulse);
+static void __notify_call_termination(sip_data_t *data);
+static void __free_call(call_t *call);
+static int __has_to_tag(struct sip_msg *msg);
+static credit_data_t *__alloc_new_credit_data(str *client_id, credit_type_t type);
+static credit_data_t *__get_or_create_credit_data_entry(str *client_id, credit_type_t type);
 
 /*
  * MI interface
  */
-static struct mi_root *mi_credit_control_stats(struct mi_root *tree, void *param);
+static struct mi_root *__mi_credit_control_stats(struct mi_root *tree, void *param);
 
 /*
  * Dialog management callback functions
  */
-static void dialog_terminated_callback(struct dlg_cell *cell, int type, struct dlg_cb_params *params);
-static void dialog_confirmed_callback(struct dlg_cell *cell, int type, struct dlg_cb_params *params);
-static void dialog_created_callback(struct dlg_cell *cell, int type, struct dlg_cb_params *params);
-
-static pv_export_t mod_pvs[] =
-{
-	{ {"cnxcc", sizeof("cnxcc")-1 }, PVT_OTHER, pv_get_calls, 0,
-		                pv_parse_calls_param, 0, 0, 0 },
+static void __dialog_terminated_callback(struct dlg_cell *cell, int type, struct dlg_cb_params *params);
+static void __dialog_confirmed_callback(struct dlg_cell *cell, int type, struct dlg_cb_params *params);
+static void __dialog_created_callback(struct dlg_cell *cell, int type, struct dlg_cb_params *params);
+
+static pv_export_t mod_pvs[] = {
+	{ {"cnxcc", sizeof("cnxcc")-1 }, PVT_OTHER, __pv_get_calls, 0, __pv_parse_calls_param, 0, 0, 0 },
 	{ {0, 0}, 0, 0, 0, 0, 0, 0, 0 }
 };
 
-static cmd_export_t cmds[] =
-{
-	{"cnxcc_set_max_time",   (cmd_function) set_max_time, 2, fixup_pvar_pvar, fixup_free_pvar_pvar, ANY_ROUTE},
-	{"cnxcc_update_max_time",   (cmd_function) update_max_time, 2, fixup_pvar_pvar, fixup_free_pvar_pvar, ANY_ROUTE},
-	{"cnxcc_set_max_credit",   (cmd_function) set_max_credit, 5, fixup_par, NULL, ANY_ROUTE},
-	{"cnxcc_set_max_channels",   (cmd_function) set_max_channels, 2, fixup_pvar_pvar, NULL, ANY_ROUTE},
-	{"cnxcc_get_channel_count",   (cmd_function) get_channel_count, 2, fixup_pvar_pvar, NULL, ANY_ROUTE},
-	{"cnxcc_terminate_all",   (cmd_function) terminate_all, 1, fixup_pvar_null, NULL, ANY_ROUTE},
-
+static cmd_export_t cmds[] = {
+	{"cnxcc_set_max_time", (cmd_function) __set_max_time, 2, fixup_pvar_pvar,
+        fixup_free_pvar_pvar, ANY_ROUTE},
+    {"cnxcc_update_max_time", (cmd_function) __update_max_time, 2, fixup_pvar_pvar,
+        fixup_free_pvar_pvar, ANY_ROUTE},
+    {"cnxcc_set_max_credit", (cmd_function) __set_max_credit, 5, __fixup_pvar,
+        NULL, ANY_ROUTE},
+    {"cnxcc_set_max_channels", (cmd_function) __set_max_channels, 2, fixup_pvar_pvar,
+        NULL, ANY_ROUTE},
+    {"cnxcc_get_channel_count", (cmd_function) __get_channel_count, 2, fixup_pvar_pvar,
+        NULL, ANY_ROUTE},
+    {"cnxcc_terminate_all", (cmd_function) __terminate_all, 1, fixup_pvar_null,
+        NULL, ANY_ROUTE},
 	{0,0,0,0,0,0}
 };
 
-static param_export_t params[] =
-{
-	{"dlg_flag",  			INT_PARAM,			&_data.ctrl_flag	},
-	{"credit_check_period",  	INT_PARAM,			&_data.check_period	},
+static param_export_t params[] = {
+	{"dlg_flag", INT_PARAM,	&_data.ctrl_flag },
+	{"credit_check_period", INT_PARAM,	&_data.check_period },
+	{"redis", STR_PARAM, &_data.redis_cnn_str.s },
 	{ 0, 0, 0 }
 };
 
-static const char* rpc_active_clients_doc[2] =
-{
+static const char* rpc_active_clients_doc[2] = {
 	"List of clients with active calls",
-	0
+	NULL
 };
 
-static const char* rpc_check_client_stats_doc[2] =
-{
+static const char* rpc_check_client_stats_doc[2] = {
 	"Check specific client calls",
-	0
+	NULL
 };
 
-static const char* rpc_kill_call_doc[2] =
-{
+static const char* rpc_kill_call_doc[2] = {
 	"Kill call using its call ID",
-	0
+	NULL
 };
 
-rpc_export_t ul_rpc[] =
-{
-    {"cnxcc.active_clients",	rpc_active_clients,	rpc_active_clients_doc,	0},
-    {"cnxcc.check_client",		rpc_check_client_stats,	rpc_check_client_stats_doc,	0},
-    {"cnxcc.kill_call",			rpc_kill_call,	rpc_kill_call_doc,	0},
-    {0, 0, 0, 0}
+rpc_export_t ul_rpc[] = {
+    { "cnxcc.active_clients", rpc_active_clients, rpc_active_clients_doc,	0},
+    { "cnxcc.check_client", rpc_check_client_stats, rpc_check_client_stats_doc,	0},
+    { "cnxcc.kill_call", rpc_kill_call, rpc_kill_call_doc, 0},
+    { NULL, NULL, NULL, 0}
 };
 
 /* selects declaration */
 select_row_t sel_declaration[] = {
-        { NULL, SEL_PARAM_STR, STR_STATIC_INIT("cnxcc"), sel_root, SEL_PARAM_EXPECTED},
-        { sel_root, SEL_PARAM_STR, STR_STATIC_INIT("channels"), sel_channels, SEL_PARAM_EXPECTED|CONSUME_NEXT_STR|FIXUP_CALL},
-        { sel_channels, SEL_PARAM_STR, STR_STATIC_INIT("count"), sel_channels_count, 0},
-
+        { NULL, SEL_PARAM_STR, STR_STATIC_INIT("cnxcc"), sel_root,
+        		SEL_PARAM_EXPECTED},
+        { sel_root, SEL_PARAM_STR, STR_STATIC_INIT("channels"), sel_channels,
+        		SEL_PARAM_EXPECTED|CONSUME_NEXT_STR|FIXUP_CALL},
+        { sel_channels, SEL_PARAM_STR, STR_STATIC_INIT("count"), sel_channels_count,
+        		0},
         { NULL, SEL_PARAM_STR, STR_NULL, NULL, 0}
 };
 
 /** module exports */
-struct module_exports exports =
-{
+struct module_exports exports = {
 	MODULE_NAME,
-	DEFAULT_DLFLAGS,/* dlopen flags */
+	DEFAULT_DLFLAGS, /* dlopen flags */
 	cmds,
 	params,
-	0,          	/* exported statistics */
-	0, 	    	/* exported MI functions */
-	mod_pvs,	/* exported pseudo-variables */
-	0,          	/* extra processes */
-	mod_init,   	/* module initialization function */
-	0,
-	0,
-	child_init	/* per-child init function */
+	NULL,          	/* exported statistics */
+	NULL, 		    /* exported MI functions */
+	mod_pvs,  	    /* exported pseudo-variables */
+	NULL,          	/* extra processes */
+	__mod_init,   	/* module initialization function */
+	NULL,
+	NULL,
+	__child_init	/* per-child init function */
 };
 
-static int fixup_par(void** param, int param_no)
-{
+static int __fixup_pvar(void** param, int param_no) {
 	str var;
 
 	var.s	= (char *) *param;
@@ -233,8 +234,10 @@ static int fixup_par(void** param, int param_no)
 	return 0;
 }
 
-static int mod_init(void)
-{
+static int __mod_init(void) {
+	int len;
+	char *chr;
+
 	LM_INFO("Loading " MODULE_NAME " module\n");
 
 	_data.cs_route_number = route_get(&event_rt, "cnxcc:call-shutdown");
@@ -242,53 +245,53 @@ static int mod_init(void)
 	if (_data.cs_route_number < 0)
 		LM_INFO("No cnxcc:call-shutdown event route found\n");
 
-	if (_data.cs_route_number > 0 && event_rt.rlist[_data.cs_route_number] == NULL)
-	{
+	if (_data.cs_route_number > 0 && event_rt.rlist[_data.cs_route_number] == NULL) {
 		LM_INFO("cnxcc:call-shutdown route is empty\n");
 		_data.cs_route_number	= -1;
 	}
 
-	if (_data.check_period <= 0)
-	{
+	if (_data.check_period <= 0) {
 		LM_INFO("credit_check_period cannot be less than 1 second\n");
 		return -1;
 	}
 
-	_data.time.credit_data_by_client	= shm_malloc(sizeof(struct str_hash_table));
-	_data.time.call_data_by_cid 		= shm_malloc(sizeof(struct str_hash_table));
-	_data.money.credit_data_by_client	= shm_malloc(sizeof(struct str_hash_table));
-	_data.money.call_data_by_cid 		= shm_malloc(sizeof(struct str_hash_table));
+	if (_data.redis_cnn_str.s)
+		_data.redis_cnn_str.len = strlen(_data.redis_cnn_str.s);
+
+	_data.time.credit_data_by_client = shm_malloc(sizeof(struct str_hash_table));
+	_data.time.call_data_by_cid = shm_malloc(sizeof(struct str_hash_table));
+	_data.money.credit_data_by_client = shm_malloc(sizeof(struct str_hash_table));
+	_data.money.call_data_by_cid = shm_malloc(sizeof(struct str_hash_table));
 	_data.channel.credit_data_by_client	= shm_malloc(sizeof(struct str_hash_table));
-	_data.channel.call_data_by_cid 		= shm_malloc(sizeof(struct str_hash_table));
+	_data.channel.call_data_by_cid = shm_malloc(sizeof(struct str_hash_table));
 
-	_data.stats				= (stats_t *) shm_malloc(sizeof(stats_t));
+	_data.stats = (stats_t *) shm_malloc(sizeof(stats_t));
 
-	if (!_data.stats)
-	{
+	if (!_data.stats) {
 		LM_ERR("Error allocating shared memory stats\n");
 		return -1;
 	}
 
-	_data.stats->active	= 0;
-	_data.stats->dropped	= 0;
-	_data.stats->total	= 0;
+	_data.stats->active = 0;
+	_data.stats->dropped = 0;
+	_data.stats->total = 0;
 
-	if (init_hashtable(_data.time.credit_data_by_client) != 0)
+	if (__init_hashtable(_data.time.credit_data_by_client) != 0)
 		return -1;
 
-	if (init_hashtable(_data.time.call_data_by_cid) != 0)
+	if (__init_hashtable(_data.time.call_data_by_cid) != 0)
 		return -1;
 
-	if (init_hashtable(_data.money.credit_data_by_client) != 0)
+	if (__init_hashtable(_data.money.credit_data_by_client) != 0)
 		return -1;
 
-	if (init_hashtable(_data.money.call_data_by_cid) != 0)
+	if (__init_hashtable(_data.money.call_data_by_cid) != 0)
 		return -1;
 
-	if (init_hashtable(_data.channel.credit_data_by_client) != 0)
+	if (__init_hashtable(_data.channel.credit_data_by_client) != 0)
 		return -1;
 
-	if (init_hashtable(_data.channel.call_data_by_cid) != 0)
+	if (__init_hashtable(_data.channel.call_data_by_cid) != 0)
 		return -1;
 
 	lock_init(&_data.lock);
@@ -296,7 +299,7 @@ static int mod_init(void)
 	lock_init(&_data.money.lock);
 	lock_init(&_data.channel.lock);
 
-	register_mi_cmd(mi_credit_control_stats, "cnxcc_stats", NULL, NULL, 0);
+	register_mi_cmd(__mi_credit_control_stats, "cnxcc_stats", NULL, NULL, 0);
 
 	/*
 	 * One for time based monitoring
@@ -304,102 +307,154 @@ static int mod_init(void)
 	 */
 	register_dummy_timers(NUMBER_OF_TIMERS);
 
-	if (rpc_register_array(ul_rpc) != 0)
-	{
+	if (rpc_register_array(ul_rpc) != 0) {
 		LM_ERR("Failed registering RPC commands\n");
 		return -1;
 	}
 
-	if (load_dlg_api(&_dlgbinds) != 0)
-	{
+	if (load_dlg_api(&_dlgbinds) != 0) {
 		LM_ERR("Error loading dialog API\n");
 	    return -1;
 	}
 
-	_dlgbinds.register_dlgcb(NULL, DLGCB_CREATED, dialog_created_callback, NULL, NULL);
+	_dlgbinds.register_dlgcb(NULL, DLGCB_CREATED, __dialog_created_callback, NULL, NULL);
 
-	 register_select_table(sel_declaration);
+	register_select_table(sel_declaration);
+
+	// redis configuration setup
+	if (_data.redis_cnn_str.len <= 0)
+		return 0;
+
+	// replace ";" for " ", so we can use a simpler pattern in sscanf()
+	for(chr = _data.redis_cnn_str.s; *chr; chr++)
+		if (*chr == ';')
+			*chr = ' ';
+
+	memset(_data.redis_cnn_info.host, 0, sizeof(_data.redis_cnn_info.host));
+	sscanf(_data.redis_cnn_str.s, "addr=%s port=%d db=%d", _data.redis_cnn_info.host,
+                                                           &_data.redis_cnn_info.port,
+                                                           &_data.redis_cnn_info.db);
+
+	len = strlen(_data.redis_cnn_info.host);
+	//
+	// Redis modparam validations
+	//
+	if (len == 0) {
+		LM_ERR("invalid host address [%s]", _data.redis_cnn_info.host);
+		return -1;
+	}
+
+	if (_data.redis_cnn_info.port <= 0) {
+		LM_ERR("invalid port number [%d]", _data.redis_cnn_info.port);
+		return -1;
+	}
+
+	if (_data.redis_cnn_info.db < 0) {
+		LM_ERR("invalid db number [%d]",_data.redis_cnn_info.db);
+		return -1;
+	}
 
+	LM_INFO("Redis connection info: ip=[%s], port=[%d], database=[%d]", _data.redis_cnn_info.host,
+			                                                            _data.redis_cnn_info.port,
+			                                                            _data.redis_cnn_info.db);
+
+	register_procs(3/* 2 timers + 1 redis async receiver */);
 	return 0;
 }
 
-static int child_init(int rank)
-{
+static int __child_init(int rank) {
+	int pid = 0;
+
+	if (rank!=PROC_INIT && rank!=PROC_MAIN && rank!=PROC_TCP_MAIN) {
+		if (_data.redis_cnn_str.len <= 0)
+			return 0;
+
+		_data.redis = redis_connect(_data.redis_cnn_info.host,
+                                        _data.redis_cnn_info.port,
+                                        _data.redis_cnn_info.db);
+		return (!_data.redis) ? -1 : 0;
+	}
+
 	if (rank != PROC_MAIN)
 		return 0;
 
+	if(fork_dummy_timer(PROC_TIMER, "CNXCC TB TIMER", 1, check_calls_by_money, NULL, _data.check_period) < 0) {
+		LM_ERR("Failed registering TB TIMER routine as process\n");
+		return -1;
+	}
 
-	if(fork_dummy_timer(PROC_TIMER, "CNXCC TB TIMER", 1,
-			check_calls_by_money, NULL, _data.check_period) < 0)
-	{
-		LM_ERR("failed to register TB TIMER routine as process\n");
+	if(fork_dummy_timer(PROC_TIMER, "CNXCC MB TIMER", 1, check_calls_by_time, NULL, _data.check_period) < 0) {
+		LM_ERR("Failed registering MB TIMER routine as process\n");
 		return -1;
 	}
 
-	if(fork_dummy_timer(PROC_TIMER, "CNXCC MB TIMER", 1, check_calls_by_time, NULL, _data.check_period) < 0)
-	{
-		LM_ERR("failed to register MB TIMER routine as process\n");
+	if (_data.redis_cnn_str.len <= 0)
+		return 0;
+
+
+	pid = fork_process(PROC_NOCHLDINIT, "Redis Async receiver", 1);
+
+	if (pid < 0) {
+		LM_ERR("error forking Redis receiver\n");
 		return -1;
 	}
+	else if (pid == 0) {
+		_data.redis = redis_connect_async(_data.redis_cnn_info.host,
+                                          _data.redis_cnn_info.port,
+                                          _data.redis_cnn_info.db);
+
+		return (!_data.redis) ? -1 : 0;;
+	}
 
 	return 0;
 }
 
-static int init_hashtable(struct str_hash_table *ht)
-{
-	if (shm_str_hash_alloc(ht, HT_SIZE) != 0)
-	{
+static int __init_hashtable(struct str_hash_table *ht) {
+	if (__shm_str_hash_alloc(ht, HT_SIZE) != 0) {
 		LM_ERR("Error allocating shared memory hashtable\n");
 		return -1;
 	}
 
 	str_hash_init(ht);
-
 	return 0;
 }
 
-static void dialog_created_callback(struct dlg_cell *cell, int type, struct dlg_cb_params *params)
-{
-	struct sip_msg *msg	= NULL;
+static void __dialog_created_callback(struct dlg_cell *cell, int type, struct dlg_cb_params *params) {
+	struct sip_msg *msg = NULL;
 
-	msg	= params->direction == SIP_REPLY ? params->rpl : params->req;
+	msg = params->direction == SIP_REPLY ? params->rpl : params->req;
 
-	if (msg == NULL)
-	{
+	if (msg == NULL) {
 		LM_ERR("Error getting direction of SIP msg\n");
 		return;
 	}
 
-	if (isflagset(msg, _data.ctrl_flag) == -1)
-	{
+	if (isflagset(msg, _data.ctrl_flag) == -1) {
 		LM_DBG("Flag is not set for this message. Ignoring\n");
 		return;
 	}
 
 	LM_DBG("Dialog created for CID [%.*s]\n", cell->callid.len, cell->callid.s);
 
-	_dlgbinds.register_dlgcb(cell, DLGCB_CONFIRMED, dialog_confirmed_callback, NULL, NULL);
-	_dlgbinds.register_dlgcb(cell, DLGCB_TERMINATED|DLGCB_FAILED|DLGCB_EXPIRED, dialog_terminated_callback, NULL, NULL);
+	_dlgbinds.register_dlgcb(cell, DLGCB_CONFIRMED, __dialog_confirmed_callback, NULL, NULL);
+	_dlgbinds.register_dlgcb(cell, DLGCB_TERMINATED|DLGCB_FAILED|DLGCB_EXPIRED, __dialog_terminated_callback, NULL, NULL);
 
-	setup_billing(&cell->callid, cell->h_entry, cell->h_id);
+	__setup_billing(&cell->callid, cell->h_entry, cell->h_id);
 }
 
-static void dialog_confirmed_callback(struct dlg_cell *cell, int type, struct dlg_cb_params *params)
-{
+static void __dialog_confirmed_callback(struct dlg_cell *cell, int type, struct dlg_cb_params *params) {
 	LM_DBG("Dialog confirmed for CID [%.*s]\n", cell->callid.len, cell->callid.s);
 
-	start_billing(&cell->callid, &cell->from_uri, &cell->to_uri, cell->tag);
+	__start_billing(&cell->callid, &cell->from_uri, &cell->to_uri, cell->tag);
 }
 
-static void dialog_terminated_callback(struct dlg_cell *cell, int type, struct dlg_cb_params *params)
-{
+static void __dialog_terminated_callback(struct dlg_cell *cell, int type, struct dlg_cb_params *params) {
 	LM_DBG("Dialog terminated for CID [%.*s]\n", cell->callid.len, cell->callid.s);
 
-	stop_billing(&cell->callid);
+	__stop_billing(&cell->callid);
 }
 
-static void notify_call_termination(sip_data_t *data)
-{
+static void __notify_call_termination(sip_data_t *data) {
 	struct run_act_ctx ra_ctx;
 	struct sip_msg *msg;
 
@@ -407,8 +462,7 @@ static void notify_call_termination(sip_data_t *data)
 		return;
 
 	if (faked_msg_init_with_dlg_info(&data->callid, &data->from_uri, &data->from_tag,
-				&data->to_uri, &data->to_tag, &msg) != 0)
-	{
+					&data->to_uri, &data->to_tag, &msg) != 0) {
 		LM_ERR("[%.*s]: error generating faked sip message\n", data->callid.len, data->callid.s);
 		return;
 	}
@@ -420,20 +474,18 @@ static void notify_call_termination(sip_data_t *data)
 		LM_ERR("Error executing cnxcc:call-shutdown route\n");
 }
 
-int try_get_credit_data_entry(str *client_id, credit_data_t **credit_data)
-{
+int try_get_credit_data_entry(str *client_id, credit_data_t **credit_data) {
 	struct str_hash_entry *cd_entry	= NULL;
-	hash_tables_t *hts		= NULL;
-	*credit_data			= NULL;
+	hash_tables_t *hts = NULL;
+	*credit_data = NULL;
 
 	/* by money */
-	hts				= &_data.money;
+	hts = &_data.money;
 	lock_get(&hts->lock);
 
-	cd_entry			= str_hash_get(hts->credit_data_by_client, client_id->s, client_id->len);
+	cd_entry = str_hash_get(hts->credit_data_by_client, client_id->s, client_id->len);
 
-	if (cd_entry != NULL)
-	{
+	if (cd_entry != NULL) {
 		*credit_data	= cd_entry->u.p;
 		lock_release(&hts->lock);
 		return 0;
@@ -442,13 +494,12 @@ int try_get_credit_data_entry(str *client_id, credit_data_t **credit_data)
 	lock_release(&hts->lock);
 
 	/* by time */
-	hts				= &_data.time;
+	hts = &_data.time;
 	lock_get(&hts->lock);
 
-	cd_entry			= str_hash_get(hts->credit_data_by_client, client_id->s, client_id->len);
+	cd_entry = str_hash_get(hts->credit_data_by_client, client_id->s, client_id->len);
 
-	if (cd_entry != NULL)
-	{
+	if (cd_entry != NULL) {
 		*credit_data	= cd_entry->u.p;
 		lock_release(&hts->lock);
 		return 0;
@@ -457,37 +508,34 @@ int try_get_credit_data_entry(str *client_id, credit_data_t **credit_data)
 	lock_release(&hts->lock);
 
 	/* by channel */
-	hts				= &_data.channel;
+	hts = &_data.channel;
 	lock_get(&hts->lock);
 
-	cd_entry			= str_hash_get(hts->credit_data_by_client, client_id->s, client_id->len);
+	cd_entry = str_hash_get(hts->credit_data_by_client, client_id->s, client_id->len);
 
-	if (cd_entry != NULL)
-	{
+	if (cd_entry != NULL) {
 		*credit_data	= cd_entry->u.p;
 		lock_release(&hts->lock);
 		return 0;
 	}
 
 	lock_release(&hts->lock);
-
 	return -1;
 }
 
-int try_get_call_entry(str *callid, call_t **call, hash_tables_t **hts)
-{
-	struct str_hash_entry *call_entry	= NULL;
-	*call					= NULL;
+int try_get_call_entry(str *callid, call_t **call, hash_tables_t **hts) {
+	struct str_hash_entry *call_entry = NULL;
+
+	*call = NULL;
 
 	/* by money */
-	*hts				= &_data.money;
+	*hts = &_data.money;
 	lock_get(&(*hts)->lock);
 
-	call_entry			= str_hash_get((*hts)->call_data_by_cid, callid->s, callid->len);
+	call_entry = str_hash_get((*hts)->call_data_by_cid, callid->s, callid->len);
 
-	if (call_entry != NULL)
-	{
-		*call	= call_entry->u.p;
+	if (call_entry != NULL) {
+		*call = call_entry->u.p;
 		lock_release(&(*hts)->lock);
 		return 0;
 	}
@@ -495,14 +543,13 @@ int try_get_call_entry(str *callid, call_t **call, hash_tables_t **hts)
 	lock_release(&(*hts)->lock);
 
 	/* by time */
-	*hts				= &_data.time;
+	*hts = &_data.time;
 	lock_get(&(*hts)->lock);
 
-	call_entry			= str_hash_get((*hts)->call_data_by_cid, callid->s, callid->len);
+	call_entry = str_hash_get((*hts)->call_data_by_cid, callid->s, callid->len);
 
-	if (call_entry != NULL)
-	{
-		*call	= call_entry->u.p;
+	if (call_entry != NULL) {
+		*call = call_entry->u.p;
 		lock_release(&(*hts)->lock);
 		return 0;
 	}
@@ -510,80 +557,73 @@ int try_get_call_entry(str *callid, call_t **call, hash_tables_t **hts)
 	lock_release(&(*hts)->lock);
 
 	/* by channel */
-	*hts				= &_data.channel;
+	*hts = &_data.channel;
 	lock_get(&(*hts)->lock);
 
-	call_entry			= str_hash_get((*hts)->call_data_by_cid, callid->s, callid->len);
+	call_entry = str_hash_get((*hts)->call_data_by_cid, callid->s, callid->len);
 
-	if (call_entry != NULL)
-	{
-		*call	= call_entry->u.p;
+	if (call_entry != NULL) {
+		*call = call_entry->u.p;
 		lock_release(&(*hts)->lock);
 		return 0;
 	}
 
 	lock_release(&(*hts)->lock);
-
 	return -1;
 }
 
-static void stop_billing(str *callid)
-{
-	struct str_hash_entry *cd_entry		= NULL;
-	call_t *call				= NULL;
-	hash_tables_t *hts			= NULL;
-	credit_data_t *credit_data		= NULL;
+static void __stop_billing(str *callid) {
+	struct str_hash_entry *cd_entry	= NULL;
+	call_t *call			= NULL;
+	hash_tables_t *hts		= NULL;
+	credit_data_t *credit_data	= NULL;
 
 	/*
 	 * Search call data by call-id
 	 */
-	if (try_get_call_entry(callid, &call, &hts) != 0)
-	{
+	if (try_get_call_entry(callid, &call, &hts) != 0) {
 		LM_ERR("Call [%.*s] not found\n", callid->len, callid->s);
 		return;
 	}
 
-	if (call == NULL)
-	{
+	if (call == NULL) {
 		LM_ERR("[%.*s] call pointer is null\n", callid->len, callid->s);
 		return;
 	}
 
-	if (hts == NULL)
-	{
+	if (hts == NULL) {
 		LM_ERR("[%.*s] result hashtable pointer is null\n", callid->len, callid->s);
 		return;
 	}
 
 	lock_get(&hts->lock);
+
 	/*
 	 * Search credit_data by client_id
 	 */
-	cd_entry	= str_hash_get(hts->credit_data_by_client, call->client_id.s, call->client_id.len);
+	cd_entry = str_hash_get(hts->credit_data_by_client, call->client_id.s, call->client_id.len);
 
-	if (cd_entry == NULL)
-	{
+	if (cd_entry == NULL) {
 		LM_ERR("Credit data not found for CID [%.*s], client-ID [%.*s]\n", callid->len, callid->s, call->client_id.len, call->client_id.s);
 		lock_release(&hts->lock);
 		return;
 	}
 
-	credit_data	= (credit_data_t *) cd_entry->u.p;
+	credit_data = (credit_data_t *) cd_entry->u.p;
 
-	if (credit_data == NULL)
-	{
+	if (credit_data == NULL) {
 		LM_ERR("[%.*s]: credit_data pointer is null\n", callid->len, callid->s);
 		lock_release(&hts->lock);
 		return;
 	}
 
 	lock_release(&hts->lock);
+
 	/*
 	 * Update calls statistics
 	 */
 	lock_get(&_data.lock);
 
-;
 	_data.stats->active--;
 	_data.stats->total--;
 
@@ -596,21 +636,26 @@ static void stop_billing(str *callid)
 	/*
 	 * This call just ended and we need to remove it from the summ.
 	 */
-	if (call->confirmed)
-	{
+	if (call->confirmed) {
 		credit_data->concurrent_calls--;
 		credit_data->ended_calls_consumed_amount += call->consumed_amount;
+
+		if (_data.redis) {
+			redis_incr_by_int(credit_data, "concurrent_calls", -1);
+			redis_incr_by_double(credit_data, "ended_calls_consumed_amount", call->consumed_amount);
+		}
 	}
 
 	credit_data->number_of_calls--;
 
-	if (credit_data->concurrent_calls < 0)
-	{
+	if (_data.redis)
+		redis_incr_by_int(credit_data, "number_of_calls", -1);
+
+	if (credit_data->concurrent_calls < 0) {
 		LM_ERR("[BUG]: number of concurrent calls dropped to negative value: %d\n", credit_data->concurrent_calls);
 	}
 
-	if (credit_data->number_of_calls < 0)
-	{
+	if (credit_data->number_of_calls < 0) {
 		LM_ERR("[BUG]: number of calls dropped to negative value: %d\n", credit_data->number_of_calls);
 	}
 
@@ -618,17 +663,23 @@ static void stop_billing(str *callid)
 	 * Remove (and free) the call from the list of calls of the current credit_data
 	 */
 	clist_rm(call, next, prev);
-	free_call(call);
+	__free_call(call);
 
 	/*
 	 * In case there are no active calls for a certain client, we remove the client-id from the hash table.
 	 * This way, we can save memory for useful clients.
 	 */
-	if (credit_data->number_of_calls == 0)
-	{
+	if (credit_data->number_of_calls == 0) {
 		LM_DBG("Removing client [%.*s] and its calls from the list\n", credit_data->call_list->client_id.len, credit_data->call_list->client_id.s);
 
+		credit_data->deallocating = 1;
 		lock(&hts->lock);
+
+		if (_data.redis) {
+			redis_clean_up_if_last(credit_data);
+			shm_free(credit_data->str_id);
+		}
+
 		/*
 		 * Remove the credit_data_t from the hash table
 		 */
@@ -650,7 +701,7 @@ static void stop_billing(str *callid)
 		/*
 		 * Free the whole entry
 		 */
-		free_credit_data_hash_entry(cd_entry);
+		__free_credit_data_hash_entry(cd_entry);
 
 		/*
 		 * return without releasing the acquired lock over credit_data. Why? Because we just freed it.
@@ -661,8 +712,7 @@ static void stop_billing(str *callid)
 	lock_release(&credit_data->lock);
 }
 
-static void setup_billing(str *callid, unsigned int h_entry, unsigned int h_id)
-{
+static void __setup_billing(str *callid, unsigned int h_entry, unsigned int h_id) {
 	call_t *call		= NULL;
 	hash_tables_t *hts	= NULL;
 
@@ -673,20 +723,17 @@ static void setup_billing(str *callid, unsigned int h_entry, unsigned int h_id)
 	/*
 	 * Search call data by call-id
 	 */
-	if (try_get_call_entry(callid, &call, &hts) != 0)
-	{
+	if (try_get_call_entry(callid, &call, &hts) != 0) {
 		LM_ERR("Call [%.*s] not found\n", callid->len, callid->s);
 		return;
 	}
 
-	if (call == NULL)
-	{
+	if (call == NULL) {
 		LM_ERR("[%.*s] call pointer is null\n", callid->len, callid->s);
 		return;
 	}
 
-	if (hts == NULL)
-	{
+	if (hts == NULL) {
 		LM_ERR("[%.*s] result hashtable pointer is null\n", callid->len, callid->s);
 		return;
 	}
@@ -703,20 +750,19 @@ static void setup_billing(str *callid, unsigned int h_entry, unsigned int h_id)
 
 	lock_get(&call->lock);
 
-	call->dlg_h_entry		= h_entry;
-	call->dlg_h_id			= h_id;
+	call->dlg_h_entry	= h_entry;
+	call->dlg_h_id		= h_id;
 
 	LM_DBG("Call [%.*s] from client [%.*s], created\n", callid->len, callid->s, call->client_id.len, call->client_id.s);
 
 	lock_release(&call->lock);
 }
 
-static void start_billing(str *callid, str *from_uri, str *to_uri, str tags[2])
-{
-	struct str_hash_entry *cd_entry		= NULL;
-	call_t *call				= NULL;
-	hash_tables_t *hts			= NULL;
-	credit_data_t *credit_data		= NULL;
+static void __start_billing(str *callid, str *from_uri, str *to_uri, str tags[2]) {
+	struct str_hash_entry *cd_entry	= NULL;
+	call_t *call			= NULL;
+	hash_tables_t *hts		= NULL;
+	credit_data_t *credit_data	= NULL;
 
 	LM_DBG("Billing started for call [%.*s]\n", callid->len, callid->s);
 
@@ -725,21 +771,18 @@ static void start_billing(str *callid, str *from_uri, str *to_uri, str tags[2])
 	/*
 	 * Search call data by call-id
 	 */
-	if (try_get_call_entry(callid, &call, &hts) != 0)
-	{
+	if (try_get_call_entry(callid, &call, &hts) != 0) {
 		LM_ERR("Call [%.*s] not found\n", callid->len, callid->s);
 		return;
 	}
 
-	if (call == NULL)
-	{
+	if (call == NULL) {
 		LM_ERR("[%.*s] call pointer is null\n", callid->len, callid->s);
 		return;
 	}
 
-	if (hts == NULL)
-	{
-		LM_ERR("[%.*s] result hashtable pointer is null\n", callid->len, callid->s);
+	if (hts == NULL) {
+		LM_ERR("[%.*s] result hashtable pointer is null", callid->len, callid->s);
 		return;
 	}
 
@@ -748,19 +791,17 @@ static void start_billing(str *callid, str *from_uri, str *to_uri, str tags[2])
 	/*
 	 * Search credit_data by client_id
 	 */
-	cd_entry			= str_hash_get(hts->credit_data_by_client, call->client_id.s, call->client_id.len);
+	cd_entry = str_hash_get(hts->credit_data_by_client, call->client_id.s, call->client_id.len);
 
-	if (cd_entry == NULL)
-	{
+	if (cd_entry == NULL) {
 		LM_ERR("Credit data not found for CID [%.*s], client-ID [%.*s]\n", callid->len, callid->s, call->client_id.len, call->client_id.s);
 		lock_release(&hts->lock);
 		return;
 	}
 
-	credit_data	= (credit_data_t *) cd_entry->u.p;
+	credit_data = (credit_data_t *) cd_entry->u.p;
 
-	if (credit_data == NULL)
-	{
+	if (credit_data == NULL) {
 		LM_ERR("[%.*s]: credit_data pointer is null\n", callid->len, callid->s);
 		lock_release(&hts->lock);
 		return;
@@ -777,21 +818,30 @@ static void start_billing(str *callid, str *from_uri, str *to_uri, str tags[2])
 	 */
 	credit_data->concurrent_calls++;
 
-	if (credit_data->max_amount == 0)
+	if (_data.redis)
+		redis_incr_by_int(credit_data, "concurrent_calls", 1);
+
+	if (credit_data->max_amount == 0) {
 		credit_data->max_amount	= call->max_amount; // first time setup
 
-	if (call->max_amount > credit_data->max_amount)
-	{
-		LM_ALERT("Maximum-speak-time/credit changed, maybe a credit reload? %f > %f. Client [%.*s]\n", call->max_amount, credit_data->max_amount,
+		if (_data.redis)
+			redis_insert_double_value(credit_data, "max_amount", credit_data->max_amount);
+	}
+
+	if (call->max_amount > credit_data->max_amount) {
+		LM_ALERT("Maximum-talk-time/credit changed, maybe a credit reload? %f > %f. Client [%.*s]\n", call->max_amount, credit_data->max_amount,
 																							call->client_id.len, call->client_id.s);
 
+
+		if (_data.redis)
+			redis_insert_double_value(credit_data, "max_amount", call->max_amount - credit_data->max_amount);
+
 		credit_data->max_amount += call->max_amount - credit_data->max_amount;
 	}
 
 	/*
 	 * Update max_amount, discounting what was already consumed by other calls of the same client
 	 */
-
 	call->max_amount = credit_data->max_amount - credit_data->consumed_amount;
 
 	lock_release(&credit_data->lock);
@@ -801,8 +851,7 @@ static void start_billing(str *callid, str *from_uri, str *to_uri, str tags[2])
 	/*
 	 * Store from-tag value
 	 */
-	if (shm_str_dup(&call->sip_data.from_tag, &tags[0]) != 0)
-	{
+	if (shm_str_dup(&call->sip_data.from_tag, &tags[0]) != 0) {
 		LM_ERR("No more pkg memory\n");
 		goto exit;
 	}
@@ -810,21 +859,19 @@ static void start_billing(str *callid, str *from_uri, str *to_uri, str tags[2])
 	/*
 	 * Store to-tag value
 	 */
-	if (shm_str_dup(&call->sip_data.to_tag, &tags[1]) != 0)
-	{
+	if (shm_str_dup(&call->sip_data.to_tag, &tags[1]) != 0) {
 		LM_ERR("No more pkg memory\n");
 		goto exit;
 	}
 
 	if(shm_str_dup(&call->sip_data.from_uri, from_uri) != 0 ||
-	   shm_str_dup(&call->sip_data.to_uri  , to_uri)   != 0)
-	{
+	   shm_str_dup(&call->sip_data.to_uri  , to_uri)   != 0) {
 		LM_ERR("No more pkg memory\n");
 		goto exit;
 	}
 
 	call->start_timestamp	= get_current_timestamp();
-	call->confirmed			= TRUE;
+	call->confirmed		= TRUE;
 
 	LM_DBG("Call [%.*s] from client [%.*s], confirmed. from=<%.*s>;tag=%.*s, to=<%.*s>;tag=%.*s\n",
 			callid->len, callid->s, call->client_id.len, call->client_id.s,
@@ -832,26 +879,24 @@ static void start_billing(str *callid, str *from_uri, str *to_uri, str tags[2])
 			call->sip_data.from_tag.len, call->sip_data.from_tag.s,
 			call->sip_data.to_uri.len, call->sip_data.to_uri.s,
 			call->sip_data.to_tag.len, call->sip_data.to_tag.s);
-
 exit:
 	lock_release(&call->lock);
 }
 
+// must be called with lock held on credit_data
+void terminate_all_calls(credit_data_t *credit_data) {
+	call_t *call = NULL,
+           *tmp = NULL;
 
-void terminate_all_calls(credit_data_t *credit_data)
-{
-	call_t 	*call 	= NULL,
-		*tmp 	= NULL;
+	credit_data->deallocating = 1;
 
-	clist_foreach_safe(credit_data->call_list, call, tmp, next)
-	{
+	clist_foreach_safe(credit_data->call_list, call, tmp, next) {
 		LM_DBG("Killing call with CID [%.*s]\n", call->sip_data.callid.len, call->sip_data.callid.s);
 
 		/*
 		 * Update number of calls forced to end
 		 */
 		_data.stats->dropped++;
-
 		terminate_call(call);
 	}
 }
@@ -859,25 +904,20 @@ void terminate_all_calls(credit_data_t *credit_data)
 /*
  * WARNING: When calling this function, the proper lock should have been acquired
  */
-static void free_call(call_t *call)
-{
-	struct str_hash_entry *e	= NULL;
+static void __free_call(call_t *call) {
+	struct str_hash_entry *e = NULL;
 
 	LM_DBG("Freeing call [%.*s]\n", call->sip_data.callid.len, call->sip_data.callid.s);
+	e = str_hash_get(_data.money.call_data_by_cid, call->sip_data.callid.s, call->sip_data.callid.len);
 
-	e 	= str_hash_get(_data.money.call_data_by_cid, call->sip_data.callid.s, call->sip_data.callid.len);
-
-	if (e == NULL)
-	{
-		e	= str_hash_get(_data.time.call_data_by_cid, call->sip_data.callid.s, call->sip_data.callid.len);
+	if (e == NULL) {
+		e = str_hash_get(_data.time.call_data_by_cid, call->sip_data.callid.s, call->sip_data.callid.len);
 
-		if (e == NULL)
-		{
-			e	= str_hash_get(_data.channel.call_data_by_cid, call->sip_data.callid.s, call->sip_data.callid.len);
+		if (e == NULL) {
+			e = str_hash_get(_data.channel.call_data_by_cid, call->sip_data.callid.s, call->sip_data.callid.len);
 
-			if (e == NULL)
-			{
-				LM_ERR("Call [%.*s] not found. Couldn't be able to free it from hashtable\n", call->sip_data.callid.len, call->sip_data.callid.s);
+			if (e == NULL) {
+				LM_ERR("Call [%.*s] not found. Couldn't be able to free it from hashtable", call->sip_data.callid.len, call->sip_data.callid.s);
 				return;
 			}
 		}
@@ -889,7 +929,9 @@ static void free_call(call_t *call)
 	shm_free(e);
 
 	str_shm_free_if_not_null(call->sip_data.callid);
+	str_shm_free_if_not_null(call->sip_data.to_uri);
 	str_shm_free_if_not_null(call->sip_data.to_tag);
+	str_shm_free_if_not_null(call->sip_data.from_uri);
 	str_shm_free_if_not_null(call->sip_data.from_tag);
 
 	shm_free(call);
@@ -898,16 +940,14 @@ static void free_call(call_t *call)
 /*
  * WARNING: When calling this function, the proper lock should have been acquired
  */
-static void free_credit_data_hash_entry(struct str_hash_entry *e)
-{
+static void __free_credit_data_hash_entry(struct str_hash_entry *e) {
 	shm_free(e->key.s);
 //	shm_free(((credit_data_t *) e->u.p)->call);
 	shm_free(e->u.p);
 	shm_free(e);
 }
 
-static int shm_str_hash_alloc(struct str_hash_table *ht, int size)
-{
+static int __shm_str_hash_alloc(struct str_hash_table *ht, int size) {
 	ht->table	= shm_malloc(sizeof(struct str_hash_head) * size);
 
 	if (!ht->table)
@@ -917,94 +957,113 @@ static int shm_str_hash_alloc(struct str_hash_table *ht, int size)
 	return 0;
 }
 
-static credit_data_t *get_or_create_credit_data_entry(str *client_id, credit_type_t type)
-{
-	struct str_hash_table *ht	= NULL;
-	gen_lock_t *lock		= NULL;
-	struct str_hash_entry *e	= NULL;
+int terminate_call(call_t *call) {
+	LM_DBG("Got kill signal for call [%.*s] client [%.*s] h_id [%u] h_entry [%u]. Dropping it now\n",
+		call->sip_data.callid.len,
+		call->sip_data.callid.s,
+		call->client_id.len,
+		call->client_id.s,
+		call->dlg_h_id,
+		call->dlg_h_entry);
 
-	switch(type)
-	{
+	struct mi_root *root, *result	= NULL;
+	struct mi_node *node, *node1	= NULL;
+	struct mi_cmd *end_dlg_cmd		= NULL;
+
+	root	= init_mi_tree(0, 0, 0);
+	if (root == NULL) {
+		LM_ERR("Error initializing tree to terminate call\n");
+		goto error;
+	}
+
+	node	= &root->node;
+	node1	= addf_mi_node_child(node, MI_DUP_VALUE, MI_SSTR("h_entry"), "%u", call->dlg_h_entry);
+	if (node1 == NULL) {
+		LM_ERR("Error initializing h_entry node to terminate call\n");
+		goto error;
+	}
+
+	node1	= addf_mi_node_child(node, MI_DUP_VALUE, MI_SSTR("h_id"), "%u", call->dlg_h_id);
+	if (node1 == NULL) {
+		LM_ERR("Error initializing dlg_h_id node to terminate call\n");
+		goto error;
+	}
+
+	end_dlg_cmd = lookup_mi_cmd(MI_SSTR("dlg_end_dlg"));
+	if (node == NULL) {
+		LM_ERR("Error initializing dlg_end_dlg command\n");
+		goto error;
+	}
+
+	result	= run_mi_cmd(end_dlg_cmd, root);
+	if (result == NULL) {
+		LM_ERR("Error executing dlg_end_dlg command\n");
+		goto error;
+	}
+
+	if (result->code == 200) {
+		LM_DBG("dlg_end_dlg sent to call [%.*s]\n", call->sip_data.callid.len, call->sip_data.callid.s);
+		free_mi_tree(root);
+		free_mi_tree(result);
+
+		__notify_call_termination(&call->sip_data);
+		return 0;
+	}
+
+	LM_ERR("Error executing dlg_end_dlg command. Return code was [%d]\n", result->code);
+error:
+	if (root)
+		free_mi_tree(root);
+
+	return -1;
+}
+
+static credit_data_t *__get_or_create_credit_data_entry(str *client_id, credit_type_t type) {
+	struct str_hash_table *ht = NULL;
+	gen_lock_t *lock = NULL;
+	struct str_hash_entry *e = NULL;
+	credit_data_t *credit_data = NULL;
+
+	switch(type) {
 	case CREDIT_MONEY:
-		ht	= _data.money.credit_data_by_client;
-		lock	=  &_data.money.lock;
+		ht = _data.money.credit_data_by_client;
+		lock =  &_data.money.lock;
 		break;
 	case CREDIT_TIME:
-		ht	= _data.time.credit_data_by_client;
-		lock	=  &_data.time.lock;
+		ht = _data.time.credit_data_by_client;
+		lock =  &_data.time.lock;
 		break;
 	case CREDIT_CHANNEL:
-		ht	= _data.channel.credit_data_by_client;
-		lock	=  &_data.channel.lock;
+		ht = _data.channel.credit_data_by_client;
+		lock =  &_data.channel.lock;
 		break;
 	default:
-		LM_ERR("Something went terribly wrong\n");
+		LM_ERR("BUG: Something went terribly wrong\n");
 		return NULL;
 	}
 
-
 	lock_get(lock);
-	e		= str_hash_get(ht, client_id->s, client_id->len);
+	e = str_hash_get(ht, client_id->s, client_id->len);
 	lock_release(lock);
 
 	/*
 	 * Alloc new call_array_t if it doesn't exist
 	 */
 	if (e != NULL)
-	{
 		LM_DBG("Found key %.*s in hash table\n", e->key.len, e->key.s);
-	}
-	else
-	{
-		credit_data_t *credit_data	= NULL;
-		e				= shm_malloc(sizeof(struct str_hash_entry));
-
+	else if (e == NULL) {
+		e = shm_malloc(sizeof(struct str_hash_entry));
 		if (e == NULL)
-		{
-			LM_ERR("No shared memory left\n");
-			return NULL;
-		}
+			goto no_memory;
 
 		if (shm_str_dup(&e->key, client_id) != 0)
-		{
-			LM_ERR("No shared memory left\n");
-			return NULL;
-		}
+			goto no_memory;
 
-		e->flags			= 0;
-		e->u.p				= (void *) shm_malloc(sizeof(credit_data_t));
-		credit_data			= (credit_data_t *) e->u.p;
-
-		lock_init(&credit_data->lock);
-
-		credit_data->call_list 		= shm_malloc(sizeof(call_t));
-
-		if (credit_data->call_list == NULL)
-		{
-			LM_ERR("No shared memory left\n");
-			return NULL;
-		}
+		e->u.p = credit_data = __alloc_new_credit_data(client_id, type);
+		e->flags = 0;
 
-		credit_data->max_amount				= 0;
-		credit_data->concurrent_calls			= 0;
-		credit_data->consumed_amount			= 0;
-		credit_data->ended_calls_consumed_amount	= 0;
-		credit_data->number_of_calls			= 0;
-
-		credit_data->type				= type;
-
-		/*
-		 * Copy the client_id value to the root of the calls list.
-		 * This will be used later to get the credit_data_t of the
-		 * call when it is being searched by call ID.
-		 */
-		if (shm_str_dup(&credit_data->call_list->client_id, client_id) != 0)
-		{
-			LM_ERR("No shared memory left\n");
-			return NULL;
-		}
-
-		clist_init(credit_data->call_list, next, prev);
+		if (credit_data == NULL)
+			goto no_memory;
 
 		lock_get(lock);
 		str_hash_add(ht, e);
@@ -1014,111 +1073,99 @@ static credit_data_t *get_or_create_credit_data_entry(str *client_id, credit_typ
 	}
 
 	return (credit_data_t *) e->u.p;
+
+no_memory:
+	LM_ERR("No shared memory left\n");
+	return NULL;
 }
 
-int terminate_call(call_t *call)
-{
-	LM_DBG("Got kill signal for call [%.*s] client [%.*s] h_id [%u] h_entry [%u]. Dropping it now\n",
-						call->sip_data.callid.len,
-						call->sip_data.callid.s,
-						call->client_id.len,
-						call->client_id.s,
-						call->dlg_h_id,
-						call->dlg_h_entry);
+static credit_data_t *__alloc_new_credit_data(str *client_id, credit_type_t type) {
+	credit_data_t *credit_data = shm_malloc(sizeof(credit_data_t));;
 
-	struct mi_root *root, *result	= NULL;
-	struct mi_node *node, *node1	= NULL;
-	struct mi_cmd *end_dlg_cmd	= NULL;
+	lock_init(&credit_data->lock);
 
-	root	= init_mi_tree(0, 0, 0);
-	if (root == NULL)
-	{
-		LM_ERR("Error initializing tree to terminate call\n");
-		goto error;
-	}
+	credit_data->call_list = shm_malloc(sizeof(call_t));
 
-	node	= &root->node;
+	if (credit_data->call_list == NULL)
+		goto no_memory;
 
-	node1	= addf_mi_node_child(node, MI_DUP_VALUE, MI_SSTR("h_entry"), "%u", call->dlg_h_entry);
-	if (node1 == NULL)
-	{
-		LM_ERR("Error initializing h_entry node to terminate call\n");
-		goto error;
-	}
+	clist_init(credit_data->call_list, next, prev);
 
-	node1	= addf_mi_node_child(node, MI_DUP_VALUE, MI_SSTR("h_id"), "%u", call->dlg_h_id);
-	if (node1 == NULL)
-	{
-		LM_ERR("Error initializing dlg_h_id node to terminate call\n");
-		goto error;
-	}
+	/*
+	 * Copy the client_id value to the root of the calls list.
+	 * This will be used later to get the credit_data_t of the
+	 * call when it is being searched by call ID.
+	 */
+	if (shm_str_dup(&credit_data->call_list->client_id, client_id) != 0)
+		goto no_memory;
 
-	end_dlg_cmd = lookup_mi_cmd(MI_SSTR("dlg_end_dlg"));
-	if (node == NULL)
-	{
-		LM_ERR("Error initializing dlg_end_dlg command\n");
-		goto error;
+	if (_data.redis) {
+		credit_data->str_id = shm_malloc(client_id->len + 1);
+
+		if (!credit_data->str_id)
+			goto no_memory;
+
+		memset(credit_data->str_id, 0, client_id->len + 1);
+		snprintf(credit_data->str_id, client_id->len + 1, "%.*s", client_id->len, client_id->s);
 	}
 
-	result		= run_mi_cmd(end_dlg_cmd, root);
-	if (result == NULL)
-	{
-		LM_ERR("Error executing dlg_end_dlg command\n");
+	credit_data->max_amount	= 0;
+	credit_data->concurrent_calls = 0;
+	credit_data->consumed_amount = 0;
+	credit_data->ended_calls_consumed_amount= 0;
+	credit_data->number_of_calls = 0;
+	credit_data->type = type;
+	credit_data->deallocating = 0;
+
+	if (!_data.redis)
+		return credit_data;
+
+	if (redis_get_or_create_credit_data(credit_data) < 0)
 		goto error;
-	}
 
-	if (result->code == 200)
-	{
-		LM_DBG("dlg_end_dlg sent to call [%.*s]\n", call->sip_data.callid.len, call->sip_data.callid.s);
-		free_mi_tree(root);
-		free_mi_tree(result);
-		
-		notify_call_termination(&call->sip_data);
-		return 0;
-	}
+	return credit_data;
 
-	LM_ERR("Error executing dlg_end_dlg command. Return code was [%d]\n", result->code);
+no_memory:
+ 	 LM_ERR("No shared memory left\n");
 error:
-	if (root)
-		free_mi_tree(root);
-
-	return -1;
+ 	 return NULL;
 }
 
-static call_t *alloc_new_call_by_money(credit_data_t *credit_data, struct sip_msg *msg, double credit, double cost_per_second, int initial_pulse, int final_pulse)
-{
-	call_t *call		= NULL;
-
+static call_t *__alloc_new_call_by_money(credit_data_t *credit_data, struct sip_msg *msg, 
+					double credit, double cost_per_second, int initial_pulse, int final_pulse) {
+	call_t *call = NULL;
 	lock_get(&credit_data->lock);
 
-	if (credit_data->call_list == NULL)
-	{
+	if (credit_data->call_list == NULL) {
 		LM_ERR("Credit data call list is NULL\n");
 		goto error;
 	}
 
-	call 			= shm_malloc(sizeof(call_t));
-	if (call == NULL)
-	{
+	call = shm_malloc(sizeof(call_t));
+	if (call == NULL) {
 		LM_ERR("No shared memory left\n");
 		goto error;
 	}
 
-	if ( (!msg->callid && parse_headers(msg, HDR_CALLID_F, 0) != 0) ||
-		   shm_str_dup(&call->sip_data.callid, &msg->callid->body) != 0 )
-	{
+	if ((!msg->callid && parse_headers(msg, HDR_CALLID_F, 0) != 0) ||
+		shm_str_dup(&call->sip_data.callid, &msg->callid->body) != 0 ) {
 		LM_ERR("Error processing CALLID hdr\n");
 		goto error;
 	}
 
+	call->sip_data.to_uri.s		= NULL;
+	call->sip_data.to_uri.len 	= 0;
 	call->sip_data.to_tag.s		= NULL;
 	call->sip_data.to_tag.len 	= 0;
+
+	call->sip_data.from_uri.s	= NULL;
+	call->sip_data.from_uri.len	= 0;
 	call->sip_data.from_tag.s	= NULL;
-	call->sip_data.from_tag.len 	= 0;
+	call->sip_data.from_tag.len	= 0;
 
-	call->consumed_amount		= initial_pulse * cost_per_second;
-	call->confirmed			= FALSE;
-	call->max_amount		= credit;
+	call->consumed_amount = initial_pulse * cost_per_second;
+	call->confirmed	= FALSE;
+	call->max_amount = credit;
 
 	call->money_based.cost_per_second	= cost_per_second;
 	call->money_based.initial_pulse		= initial_pulse;
@@ -1127,8 +1174,8 @@ static call_t *alloc_new_call_by_money(credit_data_t *credit_data, struct sip_ms
 	/*
 	 * Reference the client_id from the root of the list
 	 */
-	call->client_id.s			= credit_data->call_list->client_id.s;
-	call->client_id.len			= credit_data->call_list->client_id.len;
+	call->client_id.s		= credit_data->call_list->client_id.s;
+	call->client_id.len		= credit_data->call_list->client_id.len;
 
 	/*
 	 * Insert the newly created call to the list of calls
@@ -1141,6 +1188,8 @@ static call_t *alloc_new_call_by_money(credit_data_t *credit_data, struct sip_ms
 	 * Increase the number of calls for this client. This call is not yet confirmed.
 	 */
 	credit_data->number_of_calls++;
+	if (_data.redis)
+		redis_incr_by_int(credit_data, "number_of_calls", 1);
 
 	lock_release(&credit_data->lock);
 
@@ -1153,46 +1202,47 @@ error:
 	return NULL;
 }
 
-static call_t *alloc_new_call_by_time(credit_data_t *credit_data, struct sip_msg *msg, int max_secs)
-{
-	call_t *call		= NULL;
+static call_t *__alloc_new_call_by_time(credit_data_t *credit_data, struct sip_msg *msg, int max_secs) {
+	call_t *call = NULL;
 
 	lock_get(&credit_data->lock);
 
-	if (credit_data->call_list == NULL)
-	{
+	if (credit_data->call_list == NULL) {
 		LM_ERR("Credit data call list is NULL\n");
 		goto error;
 	}
 
-	call 				= shm_malloc(sizeof(call_t));
-	if (call == NULL)
-	{
+	call = shm_malloc(sizeof(call_t));
+	if (call == NULL) {
 		LM_ERR("No shared memory left\n");
 		goto error;
 	}
 
 	if ( (!msg->callid && parse_headers(msg, HDR_CALLID_F, 0) != 0) ||
-		   shm_str_dup(&call->sip_data.callid, &msg->callid->body) != 0 )
-	{
+		   shm_str_dup(&call->sip_data.callid, &msg->callid->body) != 0 ) {
 		LM_ERR("Error processing CALLID hdr\n");
 		goto error;
 	}
+	
+        call->sip_data.to_uri.s         = NULL;
+        call->sip_data.to_uri.len       = 0;
+        call->sip_data.to_tag.s         = NULL;
+        call->sip_data.to_tag.len       = 0;
 
-	call->sip_data.to_tag.s		= NULL;
-	call->sip_data.to_tag.len 	= 0;
-	call->sip_data.from_tag.s	= NULL;
-	call->sip_data.from_tag.len 	= 0;
+        call->sip_data.from_uri.s       = NULL;
+        call->sip_data.from_uri.len     = 0;
+        call->sip_data.from_tag.s       = NULL;
+        call->sip_data.from_tag.len     = 0;
 
-	call->consumed_amount		= 0;
-	call->confirmed			= FALSE;
-	call->max_amount		= max_secs;
+	call->consumed_amount	= 0;
+	call->confirmed		= FALSE;
+	call->max_amount	= max_secs;
 
 	/*
 	 * Reference the client_id from the root of the list
 	 */
-	call->client_id.s		= credit_data->call_list->client_id.s;
-	call->client_id.len		= credit_data->call_list->client_id.len;
+	call->client_id.s	= credit_data->call_list->client_id.s;
+	call->client_id.len	= credit_data->call_list->client_id.len;
 
 	/*
 	 * Insert the newly created call to the list of calls
@@ -1205,6 +1255,8 @@ static call_t *alloc_new_call_by_time(credit_data_t *credit_data, struct sip_msg
 	 * Increase the number of calls for this client. This call is not yet confirmed.
 	 */
 	credit_data->number_of_calls++;
+	if (_data.redis)
+		redis_incr_by_int(credit_data, "number_of_calls", 1);
 
 	lock_release(&credit_data->lock);
 
@@ -1217,36 +1269,37 @@ error:
 	return NULL;
 }
 
-static call_t *alloc_new_call_by_channel(credit_data_t *credit_data, struct sip_msg *msg, int max_chan)
-{
-	call_t *call	= NULL;
+static call_t *alloc_new_call_by_channel(credit_data_t *credit_data, struct sip_msg *msg, int max_chan) {
+	call_t *call = NULL;
 
 	lock_get(&credit_data->lock);
 
-	if (credit_data->call_list == NULL)
-	{
+	if (credit_data->call_list == NULL) {
 		LM_ERR("Credit data call list is NULL\n");
 		goto error;
 	}
 
-	call 		= shm_malloc(sizeof(call_t));
-	if (call == NULL)
-	{
+	call = shm_malloc(sizeof(call_t));
+	if (call == NULL) {
 		LM_ERR("No shared memory left\n");
 		goto error;
 	}
 
 	if ( (!msg->callid && parse_headers(msg, HDR_CALLID_F, 0) != 0) ||
-		   shm_str_dup(&call->sip_data.callid, &msg->callid->body) != 0 )
-	{
+		shm_str_dup(&call->sip_data.callid, &msg->callid->body) != 0 ) {
 		LM_ERR("Error processing CALLID hdr\n");
 		goto error;
 	}
 
-	call->sip_data.to_tag.s		= NULL;
-	call->sip_data.to_tag.len 	= 0;
-	call->sip_data.from_tag.s	= NULL;
-	call->sip_data.from_tag.len 	= 0;
+        call->sip_data.to_uri.s         = NULL;
+        call->sip_data.to_uri.len       = 0;
+        call->sip_data.to_tag.s         = NULL;
+        call->sip_data.to_tag.len       = 0;
+
+        call->sip_data.from_uri.s       = NULL;
+        call->sip_data.from_uri.len     = 0;
+        call->sip_data.from_tag.s       = NULL;
+        call->sip_data.from_tag.len     = 0;
 
 	call->consumed_amount		= 0;
 	call->confirmed			= FALSE;
@@ -1269,6 +1322,8 @@ static call_t *alloc_new_call_by_channel(credit_data_t *credit_data, struct sip_
 	 * Increase the number of calls for this client. This call is not yet confirmed.
 	 */
 	credit_data->number_of_calls++;
+	if (_data.redis)
+		redis_incr_by_int(credit_data, "number_of_calls", 1);
 
 	lock_release(&credit_data->lock);
 
@@ -1282,14 +1337,12 @@ error:
 	return NULL;
 }
 
-static int add_call_by_cid(str *cid, call_t *call, credit_type_t type)
-{
+static int __add_call_by_cid(str *cid, call_t *call, credit_type_t type) {
 	struct str_hash_table *ht	= NULL;
 	gen_lock_t *lock		= NULL;
 	struct str_hash_entry *e	= NULL;
 
-	switch(type)
-	{
+	switch(type) {
 	case CREDIT_MONEY:
 		ht	= _data.money.call_data_by_cid;
 		lock	=  &_data.money.lock;
@@ -1303,50 +1356,43 @@ static int add_call_by_cid(str *cid, call_t *call, credit_type_t type)
 		lock	=  &_data.channel.lock;
 		break;
 	default:
-		LM_ERR("Something went terribly wrong");
+		LM_ERR("Something went terribly wrong\n");
 		return -1;
 	}
 
-	e	= str_hash_get(ht, cid->s, cid->len);
+	e = str_hash_get(ht, cid->s, cid->len);
 
-	if (e != NULL)
-	{
+	if (e != NULL) {
 		LM_DBG("e != NULL\n");
 
 		call_t *value	= (call_t *) e->u.p;
-
-		if (value == NULL)
-		{
+		if (value == NULL) {
 			LM_ERR("Value of CID [%.*s] is NULL\n", cid->len, cid->s);
 			return -1;
 		}
 
-		LM_WARN("value cid: len=%d | value [%.*s]\n", value->sip_data.callid.len, value->sip_data.callid.len, value->sip_data.callid.s);
-		LM_WARN("added cid: len=%d | value [%.*s]\n", cid->len, cid->len, cid->s);
+		LM_WARN("value cid: len=%d | value [%.*s]", value->sip_data.callid.len, value->sip_data.callid.len, value->sip_data.callid.s);
+		LM_WARN("added cid: len=%d | value [%.*s]", cid->len, cid->len, cid->s);
 
 		if (value->sip_data.callid.len != cid->len ||
-			strncasecmp(value->sip_data.callid.s, cid->s, cid->len) != 0)
-		{
+			strncasecmp(value->sip_data.callid.s, cid->s, cid->len) != 0) {
 			LM_ERR("Value of CID is [%.*s] and differs from value being added [%.*s]\n", cid->len, cid->s,
-																			value->sip_data.callid.len, value->sip_data.callid.s);
+													value->sip_data.callid.len, value->sip_data.callid.s);
 			return -1;
 		}
 
 		LM_DBG("CID already present\n");
-
 		return 0;
 	}
 
-	e	= shm_malloc(sizeof(struct str_hash_entry));
+	e = shm_malloc(sizeof(struct str_hash_entry));
 
-	if (e == NULL)
-	{
+	if (e == NULL) {
 		LM_ERR("No shared memory left\n");
 		return -1;
 	}
 
-	if (shm_str_dup(&e->key, cid) != 0)
-	{
+	if (shm_str_dup(&e->key, cid) != 0) {
 		LM_ERR("No shared memory left\n");
 		return -1;
 	}
@@ -1360,19 +1406,15 @@ static int add_call_by_cid(str *cid, call_t *call, credit_type_t type)
 	return 0;
 }
 
-static inline void set_ctrl_flag(struct sip_msg* msg)
-{
-	if (_data.ctrl_flag != -1)
-	{
+static inline void set_ctrl_flag(struct sip_msg* msg) {
+	if (_data.ctrl_flag != -1) {
 		LM_DBG("Flag set!\n");
 		setflag(msg, _data.ctrl_flag);
 	}
 }
 
-static inline int get_pv_value(struct sip_msg* msg, pv_spec_t* spec, pv_value_t* value)
-{
-	if (pv_get_spec_value(msg, spec, value) != 0)
-	{
+static inline int get_pv_value(struct sip_msg* msg, pv_spec_t* spec, pv_value_t* value) {
+	if (pv_get_spec_value(msg, spec, value) != 0) {
 		LM_ERR("Can't get PV's value\n");
 		return -1;
 	}
@@ -1380,19 +1422,18 @@ static inline int get_pv_value(struct sip_msg* msg, pv_spec_t* spec, pv_value_t*
 	return 0;
 }
 
-static int set_max_credit(struct sip_msg* msg,
+static int __set_max_credit(struct sip_msg* msg,
 				char *str_pv_client,
 				char *str_pv_credit, char *str_pv_cps,
-				char *str_pv_inip, char *str_pv_finp)
-{
+				char *str_pv_inip, char *str_pv_finp) {
 	credit_data_t *credit_data 	= NULL;
 	call_t *call			= NULL;
 
-	pv_spec_t *client_id_spec	= (pv_spec_t *) str_pv_client,
-			  *credit_spec	= (pv_spec_t *) str_pv_credit,
-			  *cps_spec	= (pv_spec_t *) str_pv_cps,
-			  *initial_pulse_spec	= (pv_spec_t *) str_pv_inip,
-			  *final_pulse_spec	= (pv_spec_t *) str_pv_finp;
+	pv_spec_t *client_id_spec = (pv_spec_t *) str_pv_client,
+		  *credit_spec	  = (pv_spec_t *) str_pv_credit,
+		  *cps_spec	  = (pv_spec_t *) str_pv_cps,
+		  *initial_pulse_spec	= (pv_spec_t *) str_pv_inip,
+		  *final_pulse_spec	= (pv_spec_t *) str_pv_finp;
 
 	pv_value_t client_id_val,
 			credit_val,
@@ -1401,84 +1442,67 @@ static int set_max_credit(struct sip_msg* msg,
 			final_pulse_val;
 
 	double credit		= 0,
-		cost_per_second	= 0;
+	       cost_per_second	= 0;
 
 	unsigned int initial_pulse	= 0,
 			final_pulse	= 0;
 
-	if (msg->first_line.type == SIP_REQUEST && msg->first_line.u.request.method_value == METHOD_INVITE)
-	{
-		if (has_to_tag(msg))
-		{
+	if (msg->first_line.type == SIP_REQUEST && msg->first_line.u.request.method_value == METHOD_INVITE) {
+		if (__has_to_tag(msg)) {
 			LM_ERR("INVITE is a reINVITE\n");
 			return -1;
 		}
 
-		if (pv_get_spec_value(msg, client_id_spec, &client_id_val) != 0)
-		{
+		if (pv_get_spec_value(msg, client_id_spec, &client_id_val) != 0) {
 			LM_ERR("Can't get client_id's value\n");
 			return -1;
 		}
 
-		if (pv_get_spec_value(msg, credit_spec, &credit_val) != 0)
-		{
+		if (pv_get_spec_value(msg, credit_spec, &credit_val) != 0) {
 			LM_ERR("Can't get credit's value\n");
 			return -1;
 		}
 
 		credit	= str2double(&credit_val.rs);
 
-		if (credit <= 0)
-		{
+		if (credit <= 0) {
 			LM_ERR("credit value must be > 0: %f", credit);
 			return -1;
 		}
 
-		if (pv_get_spec_value(msg, cps_spec, &cps_val) != 0)
-		{
+		if (pv_get_spec_value(msg, cps_spec, &cps_val) != 0) {
 			LM_ERR("Can't get cost_per_sec's value\n");
 			return -1;
 		}
 
 		cost_per_second	= str2double(&cps_val.rs);
 
-		if (cost_per_second <= 0)
-		{
+		if (cost_per_second <= 0) {
 			LM_ERR("cost_per_second value must be > 0: %f\n", cost_per_second);
 			return -1;
 		}
 
-		if (pv_get_spec_value(msg, initial_pulse_spec, &initial_pulse_val) != 0)
-		{
+		if (pv_get_spec_value(msg, initial_pulse_spec, &initial_pulse_val) != 0) {
 			LM_ERR("Can't get initial_pulse's value\n");
 			return -1;
 		}
 
-		if (str2int(&initial_pulse_val.rs, &initial_pulse) != 0)
-		{
-			LM_ERR("initial_pulse value is invalid: %.*s\n", initial_pulse_val.rs.len, initial_pulse_val.rs.s);
+		if (str2int(&initial_pulse_val.rs, &initial_pulse) != 0) {
+			LM_ERR("initial_pulse value is invalid: %.*s", initial_pulse_val.rs.len, initial_pulse_val.rs.s);
 			return -1;
 		}
 
-		if (pv_get_spec_value(msg, final_pulse_spec, &final_pulse_val) != 0)
-		{
+		if (pv_get_spec_value(msg, final_pulse_spec, &final_pulse_val) != 0) {
 			LM_ERR("Can't get final_pulse's value\n");
 			return -1;
 		}
 
-		if (str2int(&final_pulse_val.rs, &final_pulse) != 0)
-		{
-			LM_ERR("final_pulse value is invalid: %.*s\n", final_pulse_val.rs.len, final_pulse_val.rs.s);
-			return -1;
-		}
-
-		if (credit < cost_per_second) {
-			LM_ERR("Not enough credit to start the call: credit=[%f] < cost_per_sec=[%f]\n", credit, cost_per_second);
+		if (str2int(&final_pulse_val.rs, &final_pulse) != 0) {
+			LM_ERR("final_pulse value is invalid: %.*s", final_pulse_val.rs.len, final_pulse_val.rs.s);
 			return -1;
 		}
 
-		if (client_id_val.rs.len == 0 || client_id_val.rs.s == NULL)
-		{
+		if (client_id_val.rs.len == 0 || client_id_val.rs.s == NULL) {
 			LM_ERR("[%.*s]: client ID cannot be null\n", msg->callid->body.len, msg->callid->body.s);
 			return -1;
 		}
@@ -1486,31 +1510,27 @@ static int set_max_credit(struct sip_msg* msg,
 		LM_DBG("Setting up new call for client [%.*s], max-credit[%f], "
 				"cost-per-sec[%f], initial-pulse [%d], "
 				"final-pulse [%d], call-id[%.*s]\n", client_id_val.rs.len, client_id_val.rs.s,
-													 credit,
-													 cost_per_second, initial_pulse,
-													 final_pulse, msg->callid->body.len, msg->callid->body.s);
+									 credit,
+									 cost_per_second, initial_pulse,
+									 final_pulse, msg->callid->body.len, msg->callid->body.s);
 		set_ctrl_flag(msg);
 
-		if ((credit_data = get_or_create_credit_data_entry(&client_id_val.rs, CREDIT_MONEY)) == NULL)
-		{
+		if ((credit_data = __get_or_create_credit_data_entry(&client_id_val.rs, CREDIT_MONEY)) == NULL) {
 			LM_ERR("Error retrieving credit data from shared memory for client [%.*s]\n", client_id_val.rs.len, client_id_val.rs.s);
 			return -1;
 		}
 
-		if ((call = alloc_new_call_by_money(credit_data, msg, credit, cost_per_second, initial_pulse, final_pulse)) == NULL)
-		{
+		if ((call = __alloc_new_call_by_money(credit_data, msg, credit, cost_per_second, initial_pulse, final_pulse)) == NULL) {
 			LM_ERR("Unable to allocate new call for client [%.*s]\n", client_id_val.rs.len, client_id_val.rs.s);
 			return -1;
 		}
 
-		if (add_call_by_cid(&call->sip_data.callid, call, CREDIT_MONEY) != 0)
-		{
+		if (__add_call_by_cid(&call->sip_data.callid, call, CREDIT_MONEY) != 0) {
 			LM_ERR("Unable to allocate new cid_by_client for client [%.*s]\n", client_id_val.rs.len, client_id_val.rs.s);
 			return -1;
 		}
 	}
-	else
-	{
+	else {
 		LM_ALERT("MSG was not an INVITE\n");
 		return -1;
 	}
@@ -1518,38 +1538,32 @@ static int set_max_credit(struct sip_msg* msg,
 	return 1;
 }
 
-static int terminate_all(struct sip_msg* msg, char* str_pv_client)
-{
+static int __terminate_all(struct sip_msg* msg, char* str_pv_client) {
 	credit_data_t *credit_data 	= NULL;
 	pv_spec_t *client_id_spec	= (pv_spec_t *) str_pv_client;
 
 	pv_value_t client_id_val;
 
-	if (pv_get_spec_value(msg, client_id_spec, &client_id_val) != 0)
-	{
+	if (pv_get_spec_value(msg, client_id_spec, &client_id_val) != 0) {
 		LM_ERR("[%.*s]: can't get client_id pvar value\n", msg->callid->body.len, msg->callid->body.s);
 		return -1;
 	}
 
-	if (client_id_val.rs.len == 0 || client_id_val.rs.s == NULL)
-	{
+	if (client_id_val.rs.len == 0 || client_id_val.rs.s == NULL) {
 		LM_ERR("[%.*s]: client ID cannot be null\n", msg->callid->body.len, msg->callid->body.s);
 		return -1;
 	}
 
-	if (try_get_credit_data_entry(&client_id_val.rs, &credit_data) != 0)
-	{
+	if (try_get_credit_data_entry(&client_id_val.rs, &credit_data) != 0) {
 		LM_DBG("[%.*s] not found\n", msg->callid->body.len, msg->callid->body.s);
 		return -1;
 	}
 
 	terminate_all_calls(credit_data);
-
 	return 1;
 }
 
-static int get_channel_count(struct sip_msg* msg, char* str_pv_client, char* str_pv_chan_count)
-{
+static int __get_channel_count(struct sip_msg* msg, char* str_pv_client, char* str_pv_chan_count) {
 	credit_data_t *credit_data 	= NULL;
 	pv_spec_t *chan_count_spec	= (pv_spec_t *) str_pv_chan_count,
 		  *client_id_spec	= (pv_spec_t *) str_pv_client;
@@ -1557,44 +1571,39 @@ static int get_channel_count(struct sip_msg* msg, char* str_pv_client, char* str
 	pv_value_t chan_count_val, client_id_val;
 	int value			= -1;
 
-	if (pv_get_spec_value(msg, client_id_spec, &client_id_val) != 0)
-	{
+	if (pv_get_spec_value(msg, client_id_spec, &client_id_val) != 0) {
 		LM_ERR("[%.*s]: can't get client_id pvar value\n", msg->callid->body.len, msg->callid->body.s);
 		return -1;
 	}
 
-	if (client_id_val.rs.len == 0 || client_id_val.rs.s == NULL)
-	{
+	if (client_id_val.rs.len == 0 || client_id_val.rs.s == NULL) {
 		LM_ERR("[%.*s]: client ID cannot be null\n", msg->callid->body.len, msg->callid->body.s);
 		return -1;
 	}
 
-	if (try_get_credit_data_entry(&client_id_val.rs, &credit_data) == 0) 
+	if (try_get_credit_data_entry(&client_id_val.rs, &credit_data) == 0)
 		value	= credit_data->number_of_calls;
 	else
 		LM_ALERT("[%.*s] not found\n", msg->callid->body.len, msg->callid->body.s);
 
-	if (!pv_is_w(chan_count_spec))
-	{
+	if (!pv_is_w(chan_count_spec)) {
 		LM_ERR("pvar is not writable\n");
 		return -1;
 	}
 
 	memset(&chan_count_val, 0, sizeof(chan_count_val));
 
-	chan_count_val.flags 	= PV_VAL_STR;
+	chan_count_val.flags = PV_VAL_STR;
 
 	if (value > 0)
-		chan_count_val.rs.s 	= int2str(value, &chan_count_val.rs.len);
-	else
-	{
+		chan_count_val.rs.s = int2str(value, &chan_count_val.rs.len);
+	else {
 		char buff[2]		= { '-', '1' };
 		chan_count_val.rs.s 	= buff;
 		chan_count_val.rs.len	= 2;
 	}
 
-	if (pv_set_spec_value(msg, chan_count_spec, 0, &chan_count_val) != 0)
-	{
+	if (pv_set_spec_value(msg, chan_count_spec, 0, &chan_count_val) != 0) {
 		LM_ERR("Error writing value to pvar");
 		return -1;
 	}
@@ -1602,8 +1611,7 @@ static int get_channel_count(struct sip_msg* msg, char* str_pv_client, char* str
 	return 1;
 }
 
-static int set_max_channels(struct sip_msg* msg, char* str_pv_client, char* str_pv_max_chan)
-{
+static int __set_max_channels(struct sip_msg* msg, char* str_pv_client, char* str_pv_max_chan) {
 	credit_data_t *credit_data 	= NULL;
 	call_t *call			= NULL;
 	pv_spec_t *max_chan_spec	= (pv_spec_t *) str_pv_max_chan,
@@ -1613,41 +1621,35 @@ static int set_max_channels(struct sip_msg* msg, char* str_pv_client, char* str_
 
 	set_ctrl_flag(msg);
 
-	if (parse_headers(msg, HDR_CALLID_F, 0) != 0)
-	{
+	if (parse_headers(msg, HDR_CALLID_F, 0) != 0) {
 		LM_ERR("Error parsing Call-ID");
 		return -1;
 	}
 
-	if (msg->first_line.type == SIP_REQUEST && msg->first_line.u.request.method_value == METHOD_INVITE)
-	{
-		if (has_to_tag(msg))
+	if (msg->first_line.type == SIP_REQUEST && msg->first_line.u.request.method_value == METHOD_INVITE) {
+		if (__has_to_tag(msg))
 		{
 			LM_ERR("INVITE is a reINVITE\n");
 			return -1;
 		}
 
-		if (pv_get_spec_value(msg, max_chan_spec, &max_chan_val) != 0)
-		{
+		if (pv_get_spec_value(msg, max_chan_spec, &max_chan_val) != 0) {
 			LM_ERR("Can't get max_chan pvar value\n");
 			return -1;
 		}
-		max_chan	= max_chan_val.ri;
+		max_chan = max_chan_val.ri;
 
-		if (max_chan <= 0)
-		{
+		if (max_chan <= 0) {
 			LM_ERR("[%.*s] MAX_CHAN cannot be less than or equal to zero: %d\n", msg->callid->body.len, msg->callid->body.s, max_chan);
 			return -1;
 		}
 
-		if (pv_get_spec_value(msg, client_id_spec, &client_id_val) != 0)
-		{
+		if (pv_get_spec_value(msg, client_id_spec, &client_id_val) != 0) {
 			LM_ERR("[%.*s]: can't get client_id pvar value\n", msg->callid->body.len, msg->callid->body.s);
 			return -1;
 		}
 
-		if (client_id_val.rs.len == 0 || client_id_val.rs.s == NULL)
-		{
+		if (client_id_val.rs.len == 0 || client_id_val.rs.s == NULL) {
 			LM_ERR("[%.*s]: client ID cannot be null\n", msg->callid->body.len, msg->callid->body.s);
 			return -1;
 		}
@@ -1656,41 +1658,36 @@ static int set_max_channels(struct sip_msg* msg, char* str_pv_client, char* str_
 												max_chan,
 												msg->callid->body.len, msg->callid->body.s);
 
-		if ((credit_data = get_or_create_credit_data_entry(&client_id_val.rs, CREDIT_CHANNEL)) == NULL)
-		{
+		if ((credit_data = __get_or_create_credit_data_entry(&client_id_val.rs, CREDIT_CHANNEL)) == NULL) {
 			LM_ERR("Error retrieving credit data from shared memory for client [%.*s]\n", client_id_val.rs.len, client_id_val.rs.s);
 			return -1;
 		}
 
 		if (credit_data->number_of_calls + 1 > max_chan)
-			return -2; // you have, among calls being setup plus those established, more than you maximum quota
+			return -2; // you have, between calls being setup plus those established, more than you maximum quota
 
 		if (credit_data->concurrent_calls + 1 > max_chan)
 			return -3; // you have the max amount of established calls already
 
-		if ((call = alloc_new_call_by_channel(credit_data, msg, max_chan)) == NULL)
-		{
+		if ((call = alloc_new_call_by_channel(credit_data, msg, max_chan)) == NULL) {
 			LM_ERR("Unable to allocate new call for client [%.*s]\n", client_id_val.rs.len, client_id_val.rs.s);
 			return -1;
 		}
 
-		if (add_call_by_cid(&call->sip_data.callid, call, CREDIT_CHANNEL) != 0)
-		{
+		if (__add_call_by_cid(&call->sip_data.callid, call, CREDIT_CHANNEL) != 0) {
 			LM_ERR("Unable to allocate new cid_by_client for client [%.*s]\n", client_id_val.rs.len, client_id_val.rs.s);
 			return -1;
 		}
 
 		return 1;
 	}
-	else
-	{
+	else {
 		LM_ALERT("MSG was not an INVITE\n");
 		return -1;
 	}
 }
 
-static int set_max_time(struct sip_msg* msg, char* str_pv_client, char* str_pv_maxsecs)
-{
+static int __set_max_time(struct sip_msg* msg, char* str_pv_client, char* str_pv_maxsecs) {
 	credit_data_t *credit_data 	= NULL;
 	call_t *call			= NULL;
 	pv_spec_t *max_secs_spec	= (pv_spec_t *) str_pv_maxsecs,
@@ -1700,69 +1697,58 @@ static int set_max_time(struct sip_msg* msg, char* str_pv_client, char* str_pv_m
 
 	set_ctrl_flag(msg);
 
-	if (parse_headers(msg, HDR_CALLID_F, 0) != 0)
-	{
-		LM_ERR("Error parsing Call-ID\n");
+	if (parse_headers(msg, HDR_CALLID_F, 0) != 0) {
+		LM_ERR("Error parsing Call-ID");
 		return -1;
 	}
 
-	if (msg->first_line.type == SIP_REQUEST && msg->first_line.u.request.method_value == METHOD_INVITE)
-	{
-		if (has_to_tag(msg))
-		{
+	if (msg->first_line.type == SIP_REQUEST && msg->first_line.u.request.method_value == METHOD_INVITE) {
+		if (__has_to_tag(msg)) {
 			LM_ERR("INVITE is a reINVITE\n");
 			return -1;
 		}
 
-		if (pv_get_spec_value(msg, max_secs_spec, &max_secs_val) != 0)
-		{
+		if (pv_get_spec_value(msg, max_secs_spec, &max_secs_val) != 0) {
 			LM_ERR("Can't get max_secs PV value\n");
 			return -1;
 		}
-		max_secs	= max_secs_val.ri;
+		max_secs = max_secs_val.ri;
 
-		if (max_secs <= 0)
-		{
+		if (max_secs <= 0) {
 			LM_ERR("[%.*s] MAXSECS cannot be less than or equal to zero: %d\n", msg->callid->body.len, msg->callid->body.s, max_secs);
 			return -1;
 		}
 
-		if (pv_get_spec_value(msg, client_id_spec, &client_id_val) != 0)
-		{
+		if (pv_get_spec_value(msg, client_id_spec, &client_id_val) != 0) {
 			LM_ERR("[%.*s]: can't get client_id PV value\n", msg->callid->body.len, msg->callid->body.s);
 			return -1;
 		}
 
-		if (client_id_val.rs.len == 0 || client_id_val.rs.s == NULL)
-		{
+		if (client_id_val.rs.len == 0 || client_id_val.rs.s == NULL) {
 			LM_ERR("[%.*s]: client ID cannot be null\n", msg->callid->body.len, msg->callid->body.s);
 			return -1;
 		}
 
 		LM_DBG("Setting up new call for client [%.*s], max-secs[%d], call-id[%.*s]\n", client_id_val.rs.len, client_id_val.rs.s,
-																		max_secs,
-																		msg->callid->body.len, msg->callid->body.s);
+												max_secs,
+												msg->callid->body.len, msg->callid->body.s);
 
-		if ((credit_data = get_or_create_credit_data_entry(&client_id_val.rs, CREDIT_TIME)) == NULL)
-		{
+		if ((credit_data = __get_or_create_credit_data_entry(&client_id_val.rs, CREDIT_TIME)) == NULL) {
 			LM_ERR("Error retrieving credit data from shared memory for client [%.*s]\n", client_id_val.rs.len, client_id_val.rs.s);
 			return -1;
 		}
 
-		if ((call = alloc_new_call_by_time(credit_data, msg, max_secs)) == NULL)
-		{
+		if ((call = __alloc_new_call_by_time(credit_data, msg, max_secs)) == NULL) {
 			LM_ERR("Unable to allocate new call for client [%.*s]\n", client_id_val.rs.len, client_id_val.rs.s);
 			return -1;
 		}
 
-		if (add_call_by_cid(&call->sip_data.callid, call, CREDIT_TIME) != 0)
-		{
+		if (__add_call_by_cid(&call->sip_data.callid, call, CREDIT_TIME) != 0) {
 			LM_ERR("Unable to allocate new cid_by_client for client [%.*s]\n", client_id_val.rs.len, client_id_val.rs.s);
 			return -1;
 		}
 	}
-	else
-	{
+	else {
 		LM_ALERT("MSG was not an INVITE\n");
 		return -1;
 	}
@@ -1770,50 +1756,44 @@ static int set_max_time(struct sip_msg* msg, char* str_pv_client, char* str_pv_m
 	return 1;
 }
 
-static int update_max_time(struct sip_msg* msg, char* str_pv_client, char* str_pv_secs)
-{
+static int __update_max_time(struct sip_msg* msg, char* str_pv_client, char* str_pv_secs) {
 	credit_data_t *credit_data 	= NULL;
 	pv_spec_t *secs_spec		= (pv_spec_t *) str_pv_secs,
 		  *client_id_spec	= (pv_spec_t *) str_pv_client;
 	pv_value_t secs_val, client_id_val;
-	int secs				= 0;
+	int secs			= 0;
 
 	set_ctrl_flag(msg);
 
-	if (parse_headers(msg, HDR_CALLID_F, 0) != 0)
-	{
+	if (parse_headers(msg, HDR_CALLID_F, 0) != 0) {
 		LM_ERR("Error parsing Call-ID");
 		return -1;
 	}
 
-	if (pv_get_spec_value(msg, secs_spec, &secs_val) != 0)
-	{
+	if (pv_get_spec_value(msg, secs_spec, &secs_val) != 0) {
 		LM_ERR("Can't get secs PV value\n");
 		return -1;
 	}
 	secs	= secs_val.ri;
 
-	if (secs <= 0)
-	{
+	if (secs <= 0) {
 		LM_ERR("[%.*s] MAXSECS cannot be less than or equal to zero: %d\n", msg->callid->body.len, msg->callid->body.s, secs);
 		return -1;
 	}
 
-	if (pv_get_spec_value(msg, client_id_spec, &client_id_val) != 0)
-	{
+	if (pv_get_spec_value(msg, client_id_spec, &client_id_val) != 0) {
 		LM_ERR("[%.*s]: can't get client_id PV value\n", msg->callid->body.len, msg->callid->body.s);
 		return -1;
 	}
 
-	if (client_id_val.rs.len == 0 || client_id_val.rs.s == NULL)
-	{
+	if (client_id_val.rs.len == 0 || client_id_val.rs.s == NULL) {
 		LM_ERR("[%.*s]: client ID cannot be null\n", msg->callid->body.len, msg->callid->body.s);
 		return -1;
 	}
 
 	LM_DBG("Updating call for client [%.*s], max-secs[%d], call-id[%.*s]\n", client_id_val.rs.len, client_id_val.rs.s,
-													secs,
-													msg->callid->body.len, msg->callid->body.s);
+										secs,
+										msg->callid->body.len, msg->callid->body.s);
 
 
 
@@ -1825,35 +1805,32 @@ static int update_max_time(struct sip_msg* msg, char* str_pv_client, char* str_p
 	       *tmp_call		= NULL;
 
 	lock_get(&_data.time.lock);
-	e				= str_hash_get(ht, client_id_val.rs.s, client_id_val.rs.len);
+	e = str_hash_get(ht, client_id_val.rs.s, client_id_val.rs.len);
 	lock_release(&_data.time.lock);
 
-	if (e == NULL)
-	{
+	if (e == NULL) {
 		LM_ERR("Client [%.*s] was not found\n", client_id_val.rs.len, client_id_val.rs.s);
 		return -1;
 	}
 		
-	credit_data			= (credit_data_t *) e->u.p;
-
+	credit_data = (credit_data_t *) e->u.p;
 	lock_get(&credit_data->lock);
 
 	LM_DBG("Updating max-secs for [%.*s] from [%f] to [%f]\n", e->key.len, e->key.s, credit_data->max_amount, credit_data->max_amount + secs);
 	
-	credit_data->max_amount		+= secs;
+	credit_data->max_amount				+= secs;
 
 	if (credit_data->number_of_calls > 0)
 		update_fraction	= secs / credit_data->number_of_calls;
 
-	clist_foreach_safe(credit_data->call_list, call, tmp_call, next)
-	{
+	clist_foreach_safe(credit_data->call_list, call, tmp_call, next) {
 		if (!call->confirmed)
 			continue;
 		
 		call->max_amount	+= update_fraction;
 	}
 
-//redit_data->consumed_amount		= 0;
+//redit_data->consumed_amount			= 0;
 
 
 	lock_release(&credit_data->lock);
@@ -1861,10 +1838,8 @@ static int update_max_time(struct sip_msg* msg, char* str_pv_client, char* str_p
 	return 1;
 }
 
-static int has_to_tag(struct sip_msg *msg)
-{
-	if (msg->to == NULL && parse_headers(msg, HDR_TO_F, 0) != 0)
-	{
+static int __has_to_tag(struct sip_msg *msg) {
+	if (msg->to == NULL && parse_headers(msg, HDR_TO_F, 0) != 0) {
 		LM_ERR("Cannot parse to-tag\n");
 		return 0;
 	}
@@ -1872,13 +1847,11 @@ static int has_to_tag(struct sip_msg *msg)
 	return !(get_to(msg)->tag_value.s == NULL || get_to(msg)->tag_value.len == 0);
 }
 
-static int pv_parse_calls_param(pv_spec_p sp, str *in)
-{
+static int __pv_parse_calls_param(pv_spec_p sp, str *in) {
 	if (sp == NULL || in == NULL || in->len == 0)
 		return -1;
 
-	switch(in->len)
-	{
+	switch(in->len) {
 	case 5:
 		if (strncmp("total", in->s, in->len) == 0)
 			sp->pvp.pvn.u.isname.name.n	= CNX_PV_TOTAL;
@@ -1906,10 +1879,8 @@ static int pv_parse_calls_param(pv_spec_p sp, str *in)
 	return 0;
 }
 
-static int pv_get_calls(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
-{
-	switch(param->pvn.u.isname.name.n)
-	{
+static int __pv_get_calls(struct sip_msg *msg, pv_param_t *param, pv_value_t *res) {
+	switch(param->pvn.u.isname.name.n) {
 	case CNX_PV_ACTIVE:
 		return pv_get_uintval(msg, param, res, _data.stats->active);
 	case CNX_PV_TOTAL:
@@ -1924,42 +1895,38 @@ static int pv_get_calls(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
 	return -1;
 }
 
-static struct mi_root *mi_credit_control_stats(struct mi_root *tree, void *param)
-{
+static struct mi_root *__mi_credit_control_stats(struct mi_root *tree, void *param) {
 	char *p;
 	int len;
 	struct mi_root *rpl_tree;
 	struct mi_node *node, *node1;
 
-	rpl_tree	= init_mi_tree(200, "OK", 2);
-	node		= &rpl_tree->node;
+	rpl_tree = init_mi_tree(200, "OK", 2);
+	node	 = &rpl_tree->node;
 
 	node1 = add_mi_node_child(node, 0, MI_SSTR("CNX Credit Control"), 0, 0);
-	if (node1 == NULL)
-	{
+	if (node1 == NULL) {
 		LM_ERR("Error creating child node\n");
 		goto error;
 	}
 
-	p	= int2str((unsigned long) _data.stats->active, &len);
-	if (p == NULL)
-	{
+	p = int2str((unsigned long) _data.stats->active, &len);
+	if (p == NULL) {
 		LM_ERR("Error converting INT to STR\n");
 		goto error;
 	}
 	add_mi_node_child(node1, MI_DUP_VALUE, MI_SSTR("active"), p, len);
 
-	p	= int2str((unsigned long) _data.stats->dropped, &len);
-	if (p == NULL)
-	{
+	p = int2str((unsigned long) _data.stats->dropped, &len);
+	if (p == NULL) {
 		LM_ERR("Error converting INT to STR\n");
 		goto error;
 	}
+
 	add_mi_node_child(node1, MI_DUP_VALUE, MI_SSTR("dropped"), p, len);
 
-	p	= int2str((unsigned long) _data.stats->total, &len);
-	if (p == NULL)
-	{
+	p = int2str((unsigned long) _data.stats->total, &len);
+	if (p == NULL) {
 		LM_ERR("Error converting INT to STR\n");
 		goto error;
 	}
diff --git a/modules/cnxcc/cnxcc_mod.h b/modules/cnxcc/cnxcc_mod.h
index 12febe3..2eb3e67 100644
--- a/modules/cnxcc/cnxcc_mod.h
+++ b/modules/cnxcc/cnxcc_mod.h
@@ -18,7 +18,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  */
 #ifndef _CNXCC_MOD_H
@@ -30,37 +30,34 @@
 
 #define str_shm_free_if_not_null(_var_) if (_var_.s != NULL)  { shm_free(_var_.s); _var_.s = NULL; _var_.len = 0; }
 
-typedef struct stats
-{
+typedef struct stats {
 	unsigned int total;
 	unsigned int active;
 	unsigned int dropped;
 } stats_t;
 
-typedef enum cnxpvtypes
-{
+typedef enum cnxpvtypes {
 	CNX_PV_ACTIVE = 1,
 	CNX_PV_TOTAL,
 	CNX_PV_DROPPED
 } cnxpvtypes_t;
 
-typedef enum credit_type
-{
+typedef enum credit_type {
 	CREDIT_TIME,
 	CREDIT_MONEY,
 	CREDIT_CHANNEL
 } credit_type_t;
 
-typedef struct hash_tables
-{
+typedef struct hash_tables {
 	struct str_hash_table *credit_data_by_client;
 	struct str_hash_table *call_data_by_cid;
 
 	gen_lock_t lock;
 } hash_tables_t;
 
-typedef struct data
-{
+struct redis;
+
+typedef struct data {
 	gen_lock_t lock;
 
 	hash_tables_t time;
@@ -84,10 +81,17 @@ typedef struct data
 
 	int check_period;
 
+	str redis_cnn_str;
+	struct {
+		char host[40];
+		int port;
+		int db;
+	} redis_cnn_info;
+	struct redis *redis;
+
 } data_t;
 
-typedef struct sip_data
-{
+typedef struct sip_data {
 	str callid;
 	str from_uri;
 	str from_tag;
@@ -95,8 +99,7 @@ typedef struct sip_data
 	str to_tag;
 } sip_data_t;
 
-typedef struct money_spec_data
-{
+typedef struct money_spec_data {
 	double cost_per_second;
 	int initial_pulse;
 	int final_pulse;
@@ -104,8 +107,7 @@ typedef struct money_spec_data
 } money_spec_data_t;
 
 struct call;
-typedef struct call
-{
+typedef struct call {
 	struct call *prev;
 	struct call *next;
 
@@ -126,15 +128,13 @@ typedef struct call
 	sip_data_t sip_data;
 } call_t;
 
-typedef struct call_array
-{
+typedef struct call_array {
 	call_t *array;
 	int length;
 
 } call_array_t;
 
-typedef struct credit_data
-{
+typedef struct credit_data {
 	gen_lock_t lock;
 
 	double max_amount;
@@ -147,6 +147,9 @@ typedef struct credit_data
 
 	call_t *call_list;
 
+	char *str_id;
+	// flag to mark this instance in the process of being eliminated
+	int deallocating:1;
 } credit_data_t;
 
 
diff --git a/modules/cnxcc/cnxcc_redis.c b/modules/cnxcc/cnxcc_redis.c
new file mode 100644
index 0000000..ca31b83
--- /dev/null
+++ b/modules/cnxcc/cnxcc_redis.c
@@ -0,0 +1,544 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2014 Carlos Ruiz Díaz (caruizdiaz.com),
+ *                    ConexionGroup (www.conexiongroup.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <stdlib.h>
+#include "cnxcc_redis.h"
+#include "cnxcc_mod.h"
+
+#define DEFAULT_EXPIRE_SECS 70
+extern data_t _data;
+
+static int __redis_select_db(redisContext *ctxt, int db);
+static int __redis_exec(credit_data_t *credit_data, const char *cmd, redisReply **rpl);
+static struct redis *__redis_connect(struct redis *redis);
+static void __async_connect_cb(const redisAsyncContext *c, int status);
+static void __async_disconnect_cb(const redisAsyncContext *c, int status);
+static void __subscription_cb(redisAsyncContext *c, void *r, void *privdata);
+static struct redis *__redis_connect_async(struct redis *redis);
+static struct redis *__alloc_redis(char *ip, int port, int db);
+static void __redis_subscribe_to_kill_list(struct redis *redis) ;
+
+
+static inline const char *__get_table_name(credit_type_t type) {
+	switch(type) {
+	case CREDIT_MONEY:
+		return "money";
+		break;
+	case CREDIT_TIME:
+		return "time";
+		break;
+	case CREDIT_CHANNEL:
+		return "channel";
+		break;
+	default:
+		LM_ERR("BUG: Something went terribly wrong: invalid credit type\n");
+		return NULL;
+	}
+}
+
+int redis_get_or_create_credit_data(credit_data_t *credit_data) {
+	int exists = 0;
+
+	// concurrent_calls is just a dummy key. It can be any of the valid keys
+	if (redis_get_int(credit_data, "HEXISTS", "concurrent_calls" , &exists) < 0)
+		goto error;
+
+	if (!exists) {  // doesn't exist
+		LM_INFO("credit_data with ID=[%s] DOES NOT exist in the cluster, creating it...\n", credit_data->str_id);
+		return redis_insert_credit_data(credit_data);
+	}
+
+	LM_INFO("credit_data with ID=[%s] DOES exist in the cluster, retrieving it...\n", credit_data->str_id);
+
+	if (redis_get_double(credit_data, "HGET", "consumed_amount", &credit_data->consumed_amount) < 0)
+		goto error;
+
+	if (redis_get_double(credit_data, "HGET", "ended_calls_consumed_amount", &credit_data->ended_calls_consumed_amount) < 0)
+		goto error;
+
+	if (redis_get_double(credit_data, "HGET", "max_amount", &credit_data->max_amount) < 0)
+		goto error;
+
+	if (redis_get_int(credit_data, "HGET", "type", (int *) &credit_data->type) < 0)
+		goto error;
+
+	return 1;
+error:
+	return -1;
+}
+
+int redis_insert_credit_data(credit_data_t *credit_data) {
+	LM_DBG("Inserting credit_data_t using ID [%s]\n", credit_data->str_id);
+
+	if (redis_insert_int_value(credit_data, "concurrent_calls", credit_data->concurrent_calls) < 0)
+		goto error;
+
+	if (redis_insert_double_value(credit_data, "consumed_amount", credit_data->consumed_amount) < 0)
+		goto error;
+
+	if (redis_insert_double_value(credit_data, "ended_calls_consumed_amount", credit_data->ended_calls_consumed_amount) < 0)
+		goto error;
+
+	if (redis_insert_double_value(credit_data, "max_amount", credit_data->max_amount) < 0)
+		goto error;
+
+	if (redis_insert_int_value(credit_data, "number_of_calls", credit_data->number_of_calls) < 0)
+		goto error;
+
+	if (redis_insert_int_value(credit_data, "type", credit_data->type) < 0)
+		goto error;
+
+	// make sure when don't have any leftover member on the kill list for this new entry
+	if (redis_remove_kill_list_member(credit_data) < 0)
+		goto error;
+
+	return 1;
+error:
+	return -1;
+}
+
+static struct redis *__alloc_redis(char *ip, int port, int db) {
+	struct redis *redis = pkg_malloc(sizeof(struct redis));
+	int len = strlen(ip);
+
+	redis->ip = pkg_malloc(len + 1);
+	strcpy(redis->ip, ip);
+
+	redis->port = port;
+	redis->db = db;
+	redis->ctxt = NULL;
+
+	return redis;
+}
+
+struct redis *redis_connect_all(char *ip, int port, int db) {
+	return __redis_connect_async(__redis_connect(__alloc_redis(ip, port, db)));
+}
+
+struct redis *redis_connect(char *ip, int port, int db) {
+	return __redis_connect(__alloc_redis(ip, port, db));
+}
+
+struct redis *redis_connect_async(char *ip, int port, int db) {
+	return __redis_connect_async(__alloc_redis(ip, port, db));
+}
+
+static struct redis *__redis_connect_async(struct redis *redis) {
+	redis->eb = event_base_new();
+
+	LM_INFO("Connecting (ASYNC) to Redis at %s:%d\n", redis->ip, redis->port);
+
+	redis->async_ctxt = redisAsyncConnect(redis->ip, redis->port);
+
+	if (redis->async_ctxt->err) {
+		LM_ERR("%s\n", redis->async_ctxt->errstr);
+		return NULL;
+	}
+
+	redisLibeventAttach(redis->async_ctxt, redis->eb);
+
+	redisAsyncSetConnectCallback(redis->async_ctxt, __async_connect_cb);
+	redisAsyncSetDisconnectCallback(redis->async_ctxt, __async_disconnect_cb);
+
+	redisAsyncCommand(redis->async_ctxt, NULL, NULL, "SELECT %d", redis->db);
+	__redis_subscribe_to_kill_list(redis);
+
+	event_base_dispatch(redis->eb);
+	return redis;
+}
+
+static struct redis *__redis_connect(struct redis *redis) {
+	struct timeval timeout = { 1, 500000 }; // 1.5 seconds
+
+	LM_INFO("Connecting to Redis at %s:%d\n", redis->ip, redis->port);
+
+	if (redis->ctxt)
+		redisFree(redis->ctxt);
+
+	redis->ctxt = redisConnectWithTimeout(redis->ip, redis->port, timeout);
+
+	if (redis->ctxt == NULL || redis->ctxt->err) {
+		if (!redis->ctxt)
+			LM_ERR("Connection error: can't allocate Redis context\n");
+		else {
+			LM_ERR("Connection error: %s\n", redis->ctxt->errstr);
+			redisFree(redis->ctxt);
+		}
+
+		return NULL;
+	}
+
+	if (!__redis_select_db(redis->ctxt, redis->db))
+		return NULL;
+
+	return redis;
+}
+
+static int __redis_select_db(redisContext *ctxt, int db) {
+	redisReply *rpl;
+	rpl = redisCommand(ctxt, "SELECT %d", db);
+
+	if (!rpl || rpl->type == REDIS_REPLY_ERROR) {
+		if (!rpl)
+			LM_ERR("%s\n", ctxt->errstr);
+		else {
+			LM_ERR("%.*s\n", rpl->len, rpl->str);
+			freeReplyObject(rpl);
+		}
+		return -1;
+	}
+
+	return 1;
+}
+
+static int __redis_exec(credit_data_t *credit_data, const char *cmd, redisReply **rpl) {
+	redisReply *rpl_aux;
+	char cmd_buffer[1024];
+
+	*rpl = redisCommand(_data.redis->ctxt, cmd);
+
+	if (!(*rpl) || (*rpl)->type == REDIS_REPLY_ERROR) {
+		if (!*rpl)
+			LM_ERR("%s\n", _data.redis->ctxt->errstr);
+		else {
+			LM_ERR("%.*s\n", (*rpl)->len, (*rpl)->str);
+			freeReplyObject(*rpl);
+		}
+
+		// reconnect on error
+		__redis_connect(_data.redis);
+		return -1;
+	}
+
+	if (credit_data == NULL) {
+		freeReplyObject(*rpl);
+		return 1;
+	}
+
+	// this will update the TTL of the key to DEFAULT_EXPIRE_SECS for every r/w.
+	// It will guarantee us that if a server crashes, the key will automatically disappear
+	// from Redis if no other client is updating the key, leaving us with some level of
+	// consistency
+	snprintf(cmd_buffer, sizeof(cmd_buffer), "EXPIRE cnxcc:%s:%s %d",
+                                                __get_table_name(credit_data->type),
+                                                credit_data->str_id,
+                                                DEFAULT_EXPIRE_SECS);
+
+	return __redis_exec(NULL, cmd_buffer, &rpl_aux);
+}
+
+int redis_incr_by_double(credit_data_t *credit_data, const char *key, double value) {
+	redisReply *rpl = NULL;
+	int ret = -1;
+	char cmd_buffer[1024];
+
+	snprintf(cmd_buffer, sizeof(cmd_buffer), "HINCRBYFLOAT cnxcc:%s:%s %s %f", __get_table_name(credit_data->type), credit_data->str_id, key, value);
+
+	ret = __redis_exec(credit_data, cmd_buffer, &rpl);
+	if (ret > 0)
+		freeReplyObject(rpl);
+
+	return ret;
+}
+
+int redis_get_double(credit_data_t *credit_data, const char *instruction, const char *key, double *value) {
+	str str_double = {0, 0};
+	char buffer[128];
+
+	if (redis_get_str(credit_data, instruction, key, &str_double) < 0)
+		return -1;
+
+	snprintf(buffer, sizeof(buffer), "%.*s", str_double.len, str_double.s);
+	*value = atof(buffer);
+
+	LM_DBG("Got DOUBLE value: %s=%f\n", key, *value);
+
+	pkg_free(str_double.s);
+	return 1;
+}
+
+int redis_incr_by_int(credit_data_t *credit_data, const char *key, int value) {
+	redisReply *rpl = NULL;
+	int ret = -1;
+	char cmd_buffer[1024];
+
+	snprintf(cmd_buffer, sizeof(cmd_buffer), "HINCRBY cnxcc:%s:%s %s %d", __get_table_name(credit_data->type), credit_data->str_id, key, value);
+
+	ret = __redis_exec(credit_data, cmd_buffer, &rpl);
+	if (ret > 0)
+		freeReplyObject(rpl);
+
+	return ret;
+}
+
+int redis_get_int(credit_data_t *credit_data, const char *instruction, const char *key, int *value) {
+	redisReply *rpl = NULL;
+	char cmd_buffer[1024];
+	snprintf(cmd_buffer, sizeof(cmd_buffer), "%s cnxcc:%s:%s %s", instruction, __get_table_name(credit_data->type), credit_data->str_id, key);
+
+	if (__redis_exec(credit_data, cmd_buffer, &rpl) < 0)
+		return -1;
+
+	if (rpl->type == REDIS_REPLY_INTEGER)
+		*value = rpl->integer;
+	else if (rpl->type == REDIS_REPLY_NIL)
+		*value = 0;
+	else {
+		*value = atoi(rpl->str);
+	}
+
+	freeReplyObject(rpl);
+
+	LM_DBG("Got INT value: %s=%di\n", key, *value);
+	return 1;
+}
+
+int redis_get_str(credit_data_t *credit_data, const char *instruction, const char *key, str *value) {
+	redisReply *rpl = NULL;
+	char cmd_buffer[1024];
+	snprintf(cmd_buffer, sizeof(cmd_buffer), "%s cnxcc:%s:%s %s", instruction, __get_table_name(credit_data->type), credit_data->str_id, key);
+
+	value->s = NULL;
+	value->len = 0;
+
+	if (__redis_exec(credit_data, cmd_buffer, &rpl) < 0)
+		return -1;
+
+	if (rpl->type != REDIS_REPLY_STRING && rpl->type != REDIS_REPLY_NIL) {
+		LM_ERR("Redis reply to [%s] is not a string/nil: type[%d]\n", cmd_buffer, rpl->type);
+		freeReplyObject(rpl);
+		return -1;
+	}
+
+	if (rpl->type == REDIS_REPLY_NIL) {
+		LM_INFO("Value of %s is (nil)\n", key);
+		goto done;
+	}
+
+	if (rpl->len <= 0) {
+		LM_ERR("RPL len is equal to %d\n", rpl->len);
+		goto done;
+	}
+
+	value->s = pkg_malloc(rpl->len);
+	value->len = rpl->len;
+	memcpy(value->s, rpl->str, rpl->len);
+
+done:
+	freeReplyObject(rpl);
+
+	LM_INFO("Got STRING value: %s=[%.*s]\n", key, value->len, value->s);
+	return 1;
+}
+
+int redis_remove_credit_data(credit_data_t *credit_data) {
+	redisReply *rpl = NULL;
+	char cmd_buffer[1024];
+	int ret;
+
+	snprintf(cmd_buffer, sizeof(cmd_buffer), "DEL cnxcc:%s:%s",  __get_table_name(credit_data->type), credit_data->str_id);
+
+	ret = __redis_exec(NULL, cmd_buffer, &rpl);
+
+//	if (ret > 0)
+//		freeReplyObject(rpl);
+
+	return ret;
+}
+
+int redis_append_kill_list_member(credit_data_t *credit_data) {
+	redisReply *rpl = NULL;
+	char cmd_buffer[1024];
+	int ret;
+
+	snprintf(cmd_buffer, sizeof(cmd_buffer), "SADD cnxcc:kill_list:%s \"%s\"", __get_table_name(credit_data->type), credit_data->str_id);
+
+	ret = __redis_exec(credit_data, cmd_buffer, &rpl);
+
+	if (ret > 0)
+		freeReplyObject(rpl);
+
+	return ret;
+}
+
+int redis_remove_kill_list_member(credit_data_t *credit_data) {
+	redisReply *rpl = NULL;
+	char cmd_buffer[1024];
+	int ret;
+
+	snprintf(cmd_buffer, sizeof(cmd_buffer), "SREM cnxcc:kill_list:%s \"%s\"", __get_table_name(credit_data->type), credit_data->str_id);
+
+	ret = __redis_exec(credit_data, cmd_buffer, &rpl);
+
+	if (ret > 0)
+		freeReplyObject(rpl);
+
+	return ret;
+}
+
+int redis_insert_str_value(credit_data_t *credit_data, const char* key, str *value) {
+	redisReply *rpl = NULL;
+	int ret = -1;
+	char cmd_buffer[2048];
+
+	if (value == NULL) {
+		LM_ERR("str value is null\n");
+		return -1;
+	}
+
+	if (value->len == 0) {
+		LM_WARN("[%s] value is empty\n", key);
+		return 1;
+	}
+
+	snprintf(cmd_buffer, sizeof(cmd_buffer), "HSET cnxcc:%s:%s %s \"%.*s\"", __get_table_name(credit_data->type), credit_data->str_id, key, value->len, value->s);
+
+	ret = __redis_exec(credit_data, cmd_buffer, &rpl);
+	if (ret > 0)
+		freeReplyObject(rpl);
+
+	return ret;
+}
+
+int redis_insert_int_value(credit_data_t *credit_data, const char* key, int value) {
+	redisReply *rpl = NULL;
+	int ret = -1;
+	char cmd_buffer[1024];
+
+	snprintf(cmd_buffer, sizeof(cmd_buffer), "HSET cnxcc:%s:%s %s %d", __get_table_name(credit_data->type), credit_data->str_id, key, value);
+
+	ret = __redis_exec(credit_data, cmd_buffer, &rpl);
+	if (ret > 0)
+		freeReplyObject(rpl);
+
+	return ret;
+}
+
+int redis_insert_double_value(credit_data_t *credit_data, const char* key, double value) {
+	redisReply *rpl = NULL;
+	int ret = -1;
+	char cmd_buffer[1024];
+
+	snprintf(cmd_buffer, sizeof(cmd_buffer), "HSET cnxcc:%s:%s %s %f", __get_table_name(credit_data->type), credit_data->str_id, key, value);
+
+	ret = __redis_exec(credit_data, cmd_buffer, &rpl);
+	if (ret > 0)
+		freeReplyObject(rpl);
+
+	return ret;
+}
+
+int redis_kill_list_member_exists(credit_data_t *credit_data) {
+	redisReply *rpl;
+	int exists = 0;
+	char cmd_buffer[1024];
+
+	snprintf(cmd_buffer, sizeof(cmd_buffer), "SISMEMBER cnxcc:kill_list:%s \"%s\"", __get_table_name(credit_data->type), credit_data->str_id);
+
+	if (__redis_exec(credit_data, cmd_buffer, &rpl) < 0)
+		return -1;
+
+	exists = rpl->integer;
+
+	freeReplyObject(rpl);
+
+	return exists;
+}
+
+int redis_clean_up_if_last(credit_data_t *credit_data) {
+	int counter = 0;
+
+	if (redis_get_int(credit_data, "HGET", "number_of_calls", &counter) < 0)
+		return -1;
+
+	return counter > 0 ? 1 : redis_remove_credit_data(credit_data);
+}
+
+static void __redis_subscribe_to_kill_list(struct redis *redis) {
+	redisAsyncCommand(redis->async_ctxt, __subscription_cb, NULL, "SUBSCRIBE cnxcc:kill_list");
+}
+
+int redis_publish_to_kill_list(credit_data_t *credit_data) {
+	redisReply *rpl;
+	char cmd_buffer[1024];
+	snprintf(cmd_buffer, sizeof(cmd_buffer), "PUBLISH cnxcc:kill_list %s", credit_data->str_id);
+
+	return __redis_exec(NULL, cmd_buffer, &rpl) < 0;
+}
+
+static void __async_connect_cb(const redisAsyncContext *c, int status) {
+	if (status != REDIS_OK) {
+		LM_ERR("error connecting to Redis db in async mode\n");
+		abort();
+	}
+
+	LM_INFO("connected to Redis in async mode\n");
+}
+
+static void __async_disconnect_cb(const redisAsyncContext *c, int status) {
+	LM_ERR("async DB connection was lost\n");
+}
+
+static void __subscription_cb(redisAsyncContext *c, void *r, void *privdata) {
+	 redisReply *reply = r;
+	 str key;
+	 credit_data_t *credit_data;
+
+	 if (reply == NULL) {
+		 LM_ERR("reply is NULL\n");
+		 return;
+	 }
+
+	 if ( reply->type != REDIS_REPLY_ARRAY || reply->elements != 3 )
+		 return;
+
+	 if (strcmp(reply->element[1]->str, "cnxcc:kill_list" ) != 0)
+		 return;
+
+	 if (!reply->element[2]->str)
+		 return;
+
+	 key.len = strlen(reply->element[2]->str);
+
+	 if (key.len <= 0) {
+		 LM_ERR("Invalid credit_data key\n");
+		 return;
+	 }
+
+	 key.s = reply->element[2]->str;
+
+	 if (try_get_credit_data_entry(&key, &credit_data) < 0)
+		 return;
+
+	 lock_get(&credit_data->lock);
+
+	 if (credit_data->deallocating)
+		 goto done; // no need to terminate the calls. They are already being terminated
+
+	 LM_ALERT("Got kill list entry for key [%.*s]\n", key.len, key.s);
+	 terminate_all_calls(credit_data);
+done:
+	 lock_release(&credit_data->lock);
+
+}
diff --git a/modules/cnxcc/cnxcc_redis.h b/modules/cnxcc/cnxcc_redis.h
new file mode 100644
index 0000000..7dade38
--- /dev/null
+++ b/modules/cnxcc/cnxcc_redis.h
@@ -0,0 +1,63 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2014 Carlos Ruiz Díaz (caruizdiaz.com),
+ *                    ConexionGroup (www.conexiongroup.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef CNXCC_STORAGE_H_
+#define CNXCC_REDIS_H_
+
+#include <hiredis/hiredis.h>
+#include <hiredis/async.h>
+#include <hiredis/adapters/libevent.h>
+
+#include "../../str.h"
+#include "cnxcc_mod.h"
+
+struct redis {
+        int db;
+        short port;
+        char* ip;
+        redisContext *ctxt;
+        redisAsyncContext *async_ctxt;
+        struct event_base *eb;
+};
+
+struct redis *redis_connect(char *ip, int port, int db);
+struct redis *redis_connect_async(char *ip, int port, int db);
+struct redis *redis_connect_all(char *ip, int port, int db);
+int redis_get_int(credit_data_t *credit_data, const char *instruction, const char *key, int *value);
+int redis_get_str(credit_data_t *credit_data, const char *instruction, const char *key, str *value);
+int redis_get_double(credit_data_t *credit_data, const char *instruction, const char *key, double *value);
+int redis_get_or_create_credit_data(credit_data_t *credit_data);
+int redis_insert_credit_data(credit_data_t *credit_data);
+int redis_insert_int_value(credit_data_t *credit_data, const char* key, int value);
+int redis_insert_double_value(credit_data_t *credit_data, const char* key, double value);
+int redis_insert_str_value(credit_data_t *credit_data, const char* key, str *value);
+int redis_kill_list_member_exists(credit_data_t *credit_data);
+int redis_incr_by_int(credit_data_t *credit_data, const char *key, int value);
+int redis_incr_by_double(credit_data_t *credit_data, const char *key, double value);
+int redis_clean_up_if_last(credit_data_t *credit_data);
+int redis_remove_kill_list_member(credit_data_t *credit_data);
+int redis_append_kill_list_member(credit_data_t *credit_data);
+int redis_publish_to_kill_list(credit_data_t *credit_data);
+
+#endif /* CNXCC_REDIS_H_ */
diff --git a/modules/cnxcc/cnxcc_rpc.c b/modules/cnxcc/cnxcc_rpc.c
index 8224d33..5fe0a69 100644
--- a/modules/cnxcc/cnxcc_rpc.c
+++ b/modules/cnxcc/cnxcc_rpc.c
@@ -18,7 +18,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  */
 
@@ -33,27 +33,23 @@
 
 extern data_t _data;
 
-void rpc_kill_call(rpc_t* rpc, void* ctx)
-{
+void rpc_kill_call(rpc_t* rpc, void* ctx) {
 	call_t *call;
 	hash_tables_t *hts;
 	str callid;
 
-	if (!rpc->scan(ctx, "S", &callid))
-	{
+	if (!rpc->scan(ctx, "S", &callid)) {
 		LM_ERR("%s: error reading RPC param\n", __FUNCTION__);
 		return;
 	}
 
-	if (try_get_call_entry(&callid, &call, &hts) != 0)
-	{
+	if (try_get_call_entry(&callid, &call, &hts) != 0) {
 		LM_ERR("%s: call [%.*s] not found\n", __FUNCTION__, callid.len, callid.s);
 		rpc->fault(ctx, 404, "CallID Not Found");
 		return;
 	}
 
-	if (call == NULL)
-	{
+	if (call == NULL) {
 		LM_ERR("%s: call [%.*s] is in null state\n", __FUNCTION__, callid.len, callid.s);
 		rpc->fault(ctx, 500, "Call is NULL");
 		return;
@@ -68,29 +64,25 @@ void rpc_kill_call(rpc_t* rpc, void* ctx)
 	lock_release(&call->lock);
 }
 
-void rpc_check_client_stats(rpc_t* rpc, void* ctx)
-{
+void rpc_check_client_stats(rpc_t* rpc, void* ctx) {
 	call_t *call, *tmp;
 	int index	= 0;
 	str client_id, rows;
 	char row_buffer[512];
 	credit_data_t *credit_data;
 
-	if (!rpc->scan(ctx, "S", &client_id))
-	{
+	if (!rpc->scan(ctx, "S", &client_id)) {
 		LM_ERR("%s: error reading RPC param\n", __FUNCTION__);
 		return;
 	}
 
-	if (try_get_credit_data_entry(&client_id, &credit_data) != 0)
-	{
+	if (try_get_credit_data_entry(&client_id, &credit_data) != 0) {
 		LM_ERR("%s: client [%.*s] not found\n", __FUNCTION__, client_id.len, client_id.s);
 		rpc->fault(ctx, 404, "Not Found");
 		return;
 	}
 
-	if (credit_data == NULL)
-	{
+	if (credit_data == NULL) {
 		LM_ERR("%s: credit data for client [%.*s] is NULL\n", __FUNCTION__, client_id.len, client_id.s);
 		rpc->fault(ctx, 500, "Internal Server Error");
 		return;
@@ -98,8 +90,7 @@ void rpc_check_client_stats(rpc_t* rpc, void* ctx)
 
 	lock_get(&credit_data->lock);
 
-	if (credit_data->number_of_calls <= 0)
-	{
+	if (credit_data->number_of_calls <= 0) {
 		lock_release(&credit_data->lock);
 		LM_INFO("No calls for current client\n");
 		return;
@@ -111,43 +102,40 @@ void rpc_check_client_stats(rpc_t* rpc, void* ctx)
 	if (rows.s == NULL)
 		goto nomem;
 
-	clist_foreach_safe(credit_data->call_list, call, tmp, next)
-	{
+	clist_foreach_safe(credit_data->call_list, call, tmp, next) {
 		int row_len = 0;
 
 		memset(row_buffer, 0, sizeof(row_buffer));
 
 		if (credit_data->type == CREDIT_MONEY)
 			snprintf(row_buffer, sizeof(row_buffer), "id:%d,confirmed:%s,local_consumed_amount:%f,global_consumed_amount:%f,local_max_amount:%f,global_max_amount:%f,call_id:%.*s,start_timestamp:%d"
-																",inip:%d,finp:%d,cps:%f;",
-																 index,
-																 call->confirmed ? "yes" : "no",
-																 call->consumed_amount,
-																 credit_data->consumed_amount,
-																 call->max_amount,
-																 credit_data->max_amount,
-																 call->sip_data.callid.len, call->sip_data.callid.s,
-																 call->start_timestamp,
-																 call->money_based.initial_pulse,
-																 call->money_based.final_pulse,
-																 call->money_based.cost_per_second
-																 );
+								",inip:%d,finp:%d,cps:%f;",
+								index,
+								call->confirmed ? "yes" : "no",
+								call->consumed_amount,
+								credit_data->consumed_amount,
+								call->max_amount,
+								credit_data->max_amount,
+								call->sip_data.callid.len, call->sip_data.callid.s,
+								call->start_timestamp,
+								call->money_based.initial_pulse,
+								call->money_based.final_pulse,
+								call->money_based.cost_per_second);
 		else
 			snprintf(row_buffer, sizeof(row_buffer), "id:%d,confirmed:%s,local_consumed_amount:%d,global_consumed_amount:%d,local_max_amount:%d,global_max_amount:%d,call_id:%.*s,start_timestamp:%d;",
-					 	 	 	 	 	 	 	 	 	 	 	 index,
-																 call->confirmed ? "yes" : "no",
-																 (int) call->consumed_amount,
-																 (int) credit_data->consumed_amount,
-																 (int) call->max_amount,
-																 (int) credit_data->max_amount,
-																 call->sip_data.callid.len, call->sip_data.callid.s,
-																 call->start_timestamp);
+								index,
+								call->confirmed ? "yes" : "no",
+								(int) call->consumed_amount,
+								(int) credit_data->consumed_amount,
+								(int) call->max_amount,
+								(int) credit_data->max_amount,
+								call->sip_data.callid.len, call->sip_data.callid.s,
+								call->start_timestamp);
 
 		row_len 	= strlen(row_buffer);
 		rows.s		= pkg_realloc(rows.s, rows.len + row_len);
 
-		if (rows.s == NULL)
-		{
+		if (rows.s == NULL) {
 			lock_release(&credit_data->lock);
 			goto nomem;
 		}
@@ -160,8 +148,7 @@ void rpc_check_client_stats(rpc_t* rpc, void* ctx)
 
 	lock_release(&credit_data->lock);
 
-	if (rpc->add(ctx, "S", &rows) < 0)
-	{
+	if (rpc->add(ctx, "S", &rows) < 0) {
 		LM_ERR("%s: error creating RPC struct\n", __FUNCTION__);
 	}
 
@@ -175,8 +162,7 @@ nomem:
 	rpc->fault(ctx, 500, "No more memory\n");
 }
 
-static int iterate_over_table(hash_tables_t *hts, str *result, credit_type_t type)
-{
+static int iterate_over_table(hash_tables_t *hts, str *result, credit_type_t type) {
 	struct str_hash_entry *h_entry, *tmp;
 	char row_buffer[512];
 	int index = 0;
@@ -185,8 +171,7 @@ static int iterate_over_table(hash_tables_t *hts, str *result, credit_type_t typ
 
 	if (hts->credit_data_by_client->table)
 		for(index = 0; index < hts->credit_data_by_client->size; index++)
-			clist_foreach_safe(&hts->credit_data_by_client->table[index], h_entry, tmp, next)
-			{
+			clist_foreach_safe(&hts->credit_data_by_client->table[index], h_entry, tmp, next) {
 				credit_data_t *credit_data	= (credit_data_t *) h_entry->u.p;
 				lock_get(&credit_data->lock);
 
@@ -194,39 +179,36 @@ static int iterate_over_table(hash_tables_t *hts, str *result, credit_type_t typ
 
 				memset(row_buffer, 0, sizeof(row_buffer));
 
-				if (type == CREDIT_TIME)
-				{
+				if (type == CREDIT_TIME) {
 					snprintf(row_buffer, sizeof(row_buffer), "client_id:%.*s,"
-															 "number_of_calls:%d,"
-															 "concurrent_calls:%d,"
-															 "type:%d,"
-															 "max_amount:%d,"
-															 "consumed_amount:%d;",
-															 credit_data->call_list->client_id.len, credit_data->call_list->client_id.s,
-															 credit_data->number_of_calls,
-															 credit_data->concurrent_calls,
-															 type,
-															 (int) credit_data->max_amount,
-															 (int) credit_data->consumed_amount);
+											"number_of_calls:%d,"
+											"concurrent_calls:%d,"
+											"type:%d,"
+											"max_amount:%d,"
+											"consumed_amount:%d;",
+											credit_data->call_list->client_id.len, credit_data->call_list->client_id.s,
+											credit_data->number_of_calls,
+											credit_data->concurrent_calls,
+											type,
+											(int) credit_data->max_amount,
+											(int) credit_data->consumed_amount);
 				}
-				else if (type == CREDIT_MONEY)
-				{
+				else if (type == CREDIT_MONEY) {
 					snprintf(row_buffer, sizeof(row_buffer), "client_id:%.*s,"
-															 "number_of_calls:%d,"
-															 "concurrent_calls:%d,"
-															 "type:%d,"
-															 "max_amount:%f,"
-															 "consumed_amount:%f;",
-															 credit_data->call_list->client_id.len, credit_data->call_list->client_id.s,
-															 credit_data->number_of_calls,
-															 credit_data->concurrent_calls,
-															 type,
-															 credit_data->max_amount,
-															 credit_data->consumed_amount);
+											"number_of_calls:%d,"
+											"concurrent_calls:%d,"
+											"type:%d,"
+											"max_amount:%f,"
+											"consumed_amount:%f;",
+											credit_data->call_list->client_id.len, credit_data->call_list->client_id.s,
+											credit_data->number_of_calls,
+											credit_data->concurrent_calls,
+											type,
+											credit_data->max_amount,
+											credit_data->consumed_amount);
 				}
-				else
-				{
-					LM_ERR("Unknown credit type: %d", type);
+				else {
+					LM_ERR("Unknown credit type: %d\n", type);
 					return -1;
 				}
 
@@ -235,8 +217,7 @@ static int iterate_over_table(hash_tables_t *hts, str *result, credit_type_t typ
 				row_len 	= strlen(row_buffer);
 				result->s	= pkg_realloc(result->s, result->len + row_len);
 
-				if (result->s == NULL)
-				{
+				if (result->s == NULL) {
 					lock_release(&hts->lock);
 					goto nomem;
 				}
@@ -255,8 +236,7 @@ nomem:
 	return -1;
 }
 
-void rpc_active_clients(rpc_t* rpc, void* ctx)
-{
+void rpc_active_clients(rpc_t* rpc, void* ctx) {
 	str rows;
 
 	rows.s	 = pkg_malloc(10);
@@ -269,8 +249,7 @@ void rpc_active_clients(rpc_t* rpc, void* ctx)
 	iterate_over_table(&_data.time, &rows, CREDIT_TIME);
 	iterate_over_table(&_data.money, &rows, CREDIT_MONEY);
 
-	if (!rpc->add(ctx, "S", &rows) < 0)
-	{
+	if (!rpc->add(ctx, "S", &rows) < 0) {
 		LM_ERR("%s: error creating RPC struct\n", __FUNCTION__);
 	}
 
@@ -280,7 +259,7 @@ void rpc_active_clients(rpc_t* rpc, void* ctx)
 	return;
 
 nomem:
-	LM_ERR("No more pkg memory");
+	LM_ERR("No more pkg memory\n");
 	rpc->fault(ctx, 500, "No more memory\n");
 }
 
diff --git a/modules/cnxcc/cnxcc_rpc.h b/modules/cnxcc/cnxcc_rpc.h
index c50bdad..99dacfd 100644
--- a/modules/cnxcc/cnxcc_rpc.h
+++ b/modules/cnxcc/cnxcc_rpc.h
@@ -18,7 +18,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  */
 
diff --git a/modules/cnxcc/cnxcc_select.c b/modules/cnxcc/cnxcc_select.c
index 121bd08..bd01b49 100644
--- a/modules/cnxcc/cnxcc_select.c
+++ b/modules/cnxcc/cnxcc_select.c
@@ -18,7 +18,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  */
 
@@ -29,24 +29,21 @@
 
 extern data_t _data;
 
-int sel_root(str* res, select_t* s, struct sip_msg* msg)  /* dummy */
-{
+int sel_root(str* res, select_t* s, struct sip_msg* msg)  /* dummy */ {
 	return 0;
 }
 
-int sel_channels(str* res, select_t* s, struct sip_msg* msg)
-{
+int sel_channels(str* res, select_t* s, struct sip_msg* msg) {
 	LM_DBG("sel_channels\n");
 
 	return 0;
 }
 
-int sel_channels_count(str* res, select_t* s, struct sip_msg* msg)
-{
+int sel_channels_count(str* res, select_t* s, struct sip_msg* msg) {
 	LM_DBG("sel_channels_count for [%.*s]\n",  s->params[2].v.s.len, s->params[2].v.s.s);
 
 	credit_data_t *credit_data	= NULL;
-	int value			= 0;
+	int value					= 0;
 
 	if (s->params[2].v.s.len <= 0)
 	{
@@ -54,7 +51,7 @@ int sel_channels_count(str* res, select_t* s, struct sip_msg* msg)
 		return -1;
 	}
 
-	if (try_get_credit_data_entry(&s->params[2].v.s, &credit_data) == 0)
+	if (try_get_credit_data_entry(&s->params[2].v.s, &credit_data) >= 0)
 		value = credit_data->number_of_calls;
 	else
 		LM_DBG("Client [%.*s] not found\n", s->params[2].v.s.len, s->params[2].v.s.s);
diff --git a/modules/cnxcc/cnxcc_select.h b/modules/cnxcc/cnxcc_select.h
index 8319e7e..f1cd3f9 100644
--- a/modules/cnxcc/cnxcc_select.h
+++ b/modules/cnxcc/cnxcc_select.h
@@ -18,7 +18,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  */
 
diff --git a/modules/cnxcc/cnxcc_sip_msg_faker.c b/modules/cnxcc/cnxcc_sip_msg_faker.c
index 41c09e0..165c6cb 100644
--- a/modules/cnxcc/cnxcc_sip_msg_faker.c
+++ b/modules/cnxcc/cnxcc_sip_msg_faker.c
@@ -18,7 +18,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  */
 
@@ -34,26 +34,23 @@ char _faked_sip_msg_buf[FAKED_SIP_MSG_BUF_LEN];
 
 static struct sip_msg _faked_msg;
 
-int faked_msg_init_with_dlg_info(str *callid, str *from_uri, str *from_tag, str *to_uri, str *to_tag, struct sip_msg **msg)
-{
+int faked_msg_init_with_dlg_info(str *callid, str *from_uri, str *from_tag, str *to_uri, str *to_tag, struct sip_msg **msg) {
 	memset(_faked_sip_msg_buf, 0, FAKED_SIP_MSG_BUF_LEN);
 
 	sprintf(_faked_sip_msg_buf, FAKED_SIP_MSG_FORMAT,
 				from_uri->len, from_uri->s, from_tag->len, from_tag->s,
 				to_uri->len, to_uri->s, to_tag->len, to_tag->s,
 				callid->len, callid->s);
-
+ 
 	LM_DBG("fake msg:\n%s\n", _faked_sip_msg_buf);
-	memset(&_faked_msg, 0, sizeof(struct sip_msg));
 
 	_faked_msg.buf = _faked_sip_msg_buf;
 	_faked_msg.len = strlen(_faked_sip_msg_buf);
 
 	_faked_msg.set_global_address	= default_global_address;
-	_faked_msg.set_global_port		= default_global_port;
+	_faked_msg.set_global_port	= default_global_port;
 
-	if (parse_msg(_faked_msg.buf, _faked_msg.len, &_faked_msg) != 0)
-	{
+	if (parse_msg(_faked_msg.buf, _faked_msg.len, &_faked_msg) != 0) {
 		LM_ERR("parse_msg failed\n");
 		return -1;
 	}
diff --git a/modules/cnxcc/cnxcc_sip_msg_faker.h b/modules/cnxcc/cnxcc_sip_msg_faker.h
index b038d57..6f79e5c 100644
--- a/modules/cnxcc/cnxcc_sip_msg_faker.h
+++ b/modules/cnxcc/cnxcc_sip_msg_faker.h
@@ -18,7 +18,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  */
 #ifndef CNXCC_SIP_MSG_FAKER_H_
diff --git a/modules/cnxcc/doc/cnxcc.xml b/modules/cnxcc/doc/cnxcc.xml
index 866be3f..6f05bce 100644
--- a/modules/cnxcc/doc/cnxcc.xml
+++ b/modules/cnxcc/doc/cnxcc.xml
@@ -15,7 +15,7 @@
     <authorgroup>
 	<author>
 	<firstname>Carlos</firstname>
-	<surname>Ruiz Diaz</surname>
+	<surname>Ruiz Díaz</surname>
 	<affiliation>
 	    <orgname>ConexionGroup S.A.</orgname>
 	</affiliation>
@@ -26,8 +26,13 @@
     </authorgroup>
     <copyright>
 	<year>2013</year>
-	<holder>Carlos Ruiz Diaz, carlos.ruizdiaz at gmail.com</holder>
+	<holder>Carlos Ruiz Díaz, carlos.ruizdiaz at gmail.com</holder>
     </copyright>
+    <copyright>
+	<year>2014</year>
+	<holder>Carlos Ruiz Díaz, carlos at latamvoices.com</holder>
+    </copyright>
+
     </bookinfo>
 
     <toc></toc>
diff --git a/modules/cnxcc/doc/cnxcc_admin.xml b/modules/cnxcc/doc/cnxcc_admin.xml
index 6716e84..36a058a 100644
--- a/modules/cnxcc/doc/cnxcc_admin.xml
+++ b/modules/cnxcc/doc/cnxcc_admin.xml
@@ -35,7 +35,7 @@
 	</para>
 	<para>
 		If your accounting program does not maintain the state of the call in real time, this module can provide you
-		that ability.
+		with that ability.
 	</para>
 	<para>
 		Cnxcc can also provide more common means of monitoring, i.e., by time limit or by maximum simultaneous calls.
@@ -59,22 +59,41 @@
 		</itemizedlist>
 	    </para>
 	</section>
+	<section>
+	    <title>Libraries</title>
+	    <para>
+		The following module must be loaded before this module: 
+		<itemizedlist>
+		    <listitem>
+		    <para>
+			<emphasis> hiredis-devel >= 0.11.0 </emphasis>
+		    </para>
+		    </listitem>
+		    <listitem>
+		    <para>
+			<emphasis> libevent-devel >= 2.0.18-2 </emphasis>
+		    </para>
+		    </listitem>
+
+		</itemizedlist>
+	    </para>
+	</section>
+
     </section>
 
     <section>
 	<title>Parameters</title>
 	<section>
-		<title><varname> dlg_flag </varname> (integer)</title>
+		<title><varname> redis </varname> (integer)</title>
 	    <para>
-		Flag to indicate if the dialog must be monitored or not. Messages are flagged with this value if we call one of
-		the monitoring functions.
+		Redis datasource connection information
 	    </para>
 	    <example>
 
 		<title>dlg_flag</title>
 		<programlisting format="linespecific">
 ...
-modparam("cnxcc", "dlg_flag", 29)
+modparam("cnxcc", "redis", "addr=127.0.0.1;port=6379;db=1")
 ...		
 		</programlisting>
 	    </example>
@@ -144,8 +163,7 @@ $var(cps)   = "2.00";         # cost per second
 $var(initial_p)   = "030";    # intial pulse
 $var(final_p)   = "006";      # final pulse
 
-cnxcc_set_max_credit("$var(customer)", "$var(credit)", "$var(cps)",
-                     "$var(initial_p)", "$var(final_p)");
+cnxcc_set_max_credit("$var(customer)", "$var(credit)", "$var(cps)", "$var(initial_p)", "$var(final_p)");
 ...		
 		</programlisting>
 	    </example>
@@ -275,17 +293,17 @@ $var(max_chan)  = 2;
 $var(retcode)   = cnxcc_set_max_channels("$var(customer)", "$var(max_chan)");
 
 if ($var(retcode) == -1) {
-    xlog("Error setting up credit control");
-    return;
+	xlog("Error setting up credit control");
+	return;
 }
 
 if ($var(retcode) < -1) {
-    xlog("Too many channels for customer");
-    sl_send_reply(403, "Forbidden");
+        xlog("Too many channels for customer");
+        sl_send_reply(403, "Forbidden");
 
-    if (!cnxcc_terminate_all("$var(customer)")) {
-        xlog("Error terminating customer's calls");
-    }
+        if (!cnxcc_terminate_all("$var(customer)")) {
+		xlog("Error terminating customer's calls");
+	}
 
 	exit;
 }
@@ -325,7 +343,7 @@ if ($var(retcode) < -1) {
 $var(customer)  = "john-doe-123-basic";
 
 if (!cnxcc_terminate_all("$var(customer)")) {
-    xlog("Error terminating customer's calls");
+	xlog("Error terminating customer's calls");
 }
 ...
 		</programlisting>
@@ -400,9 +418,9 @@ if (!cnxcc_terminate_all("$var(customer)")) {
 ...
 event_route[cnxcc:call-shutdown]
 {
-    xlog("L_INFO", "[$ci]: call killed");
+	xlog("L_INFO", "[$ci]: call killed");
 
-    # perform some kind of notification, database update, email sending, etc.
+        # perform some kind of notification, database update, email sending, etc.
 }
 ...
 		</programlisting>
@@ -439,7 +457,7 @@ route[CNXCC]
                           "$var(cost_per_sec)",
                           "$var(i_pulse)",
                           "$var(f_pulse)")) {
-             xlog("Error setting up credit control");
+		 xlog("Error setting up credit control");
       	}
 }
 
@@ -447,6 +465,7 @@ event_route[cnxcc:call-shutdown]
 {
 	xlog("L_INFO", "[$ci]: call killed");
 
+
 }	    
 ...
 	    </programlisting>
diff --git a/modules/cnxcc/example/kamailio-cnxcc.cfg b/modules/cnxcc/example/kamailio-cnxcc.cfg
index 3656a6f..9a8c6e3 100644
--- a/modules/cnxcc/example/kamailio-cnxcc.cfg
+++ b/modules/cnxcc/example/kamailio-cnxcc.cfg
@@ -468,8 +468,8 @@ modparam("rtimer", "exec", "timer=ta;route=UPDATE_MAX_TIME")
 #!endif
 
 loadmodule "cnxcc.so"
-modparam("cnxcc", "dlg_flag", CC_FLAG)
 modparam("cnxcc", "credit_check_period", 1) #check every 1 second
+modparam("cnxcc", "redis", "addr=127.0.0.1;port=6379;db=1")
 
 ####### Routing Logic ########
 
@@ -577,7 +577,8 @@ route[CNXCC]
 				  "$var(i_pulse)", 
 				  "$var(f_pulse)")) {
 		xlog("Error setting up credit control");
-		return;
+		sl_reply_error();
+		exit;
 	}
 #!endif
 
@@ -589,7 +590,8 @@ route[CNXCC]
 
 	if ($var(retcode) == -1) {
 		xlog("Error setting up credit control");
-		return;
+		sl_reply_error();
+		exit;
 	}
 
         $var(count)     = -1;
@@ -620,7 +622,8 @@ route[CNXCC]
 	if (!cnxcc_set_max_time("$var(client)",
                                   "$var(max_time)")) {
                 xlog("Error setting up credit control");
-                return;
+		sl_reply_error();
+                exit;
         }
 #!endif
 
@@ -659,7 +662,8 @@ route[UPDATE_MAX_TIME]
         if (!cnxcc_update_max_time("$var(client)",
                                   "$var(update_time)")) {
                 xlog("Error updating max-time");
-                return;
+		sl_reply_error();
+                exit;
         }
 
 }
diff --git a/modules/corex/Makefile b/modules/corex/Makefile
index 5c8cb4e..34ab4ef 100644
--- a/modules/corex/Makefile
+++ b/modules/corex/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # WARNING: do not run this directly, it should be run by the master Makefile
 
diff --git a/modules/corex/README b/modules/corex/README
index 20397c6..e7025de 100644
--- a/modules/corex/README
+++ b/modules/corex/README
@@ -16,7 +16,7 @@ Muhammad Shahzad Shafi
 
    <shahzad at voip-demos.com>
 
-   Copyright � 2012 asipto.com
+   Copyright (c) 2012 asipto.com
      __________________________________________________________________
 
    Table of Contents
@@ -33,7 +33,7 @@ Muhammad Shahzad Shafi
 
               3.1. alias_subdomains (string)
               3.2. network_io_intercept (int)
-              3.3. msg_min_len (int)
+              3.3. min_msg_len (int)
               3.4. msg_avp (string)
 
         4. Functions
@@ -64,7 +64,7 @@ Muhammad Shahzad Shafi
 
    1.1. Set alias_subdomains parameter
    1.2. Set network_io_intercept parameter
-   1.3. Set msg_min_len parameter
+   1.3. Set min_msg_len parameter
    1.4. Set msg_avp parameter
    1.5. append_branch usage
    1.6. send usage
@@ -90,7 +90,7 @@ Chapter 1. Admin Guide
 
         3.1. alias_subdomains (string)
         3.2. network_io_intercept (int)
-        3.3. msg_min_len (int)
+        3.3. min_msg_len (int)
         3.4. msg_avp (string)
 
    4. Functions
@@ -159,7 +159,7 @@ Chapter 1. Admin Guide
 
    3.1. alias_subdomains (string)
    3.2. network_io_intercept (int)
-   3.3. msg_min_len (int)
+   3.3. min_msg_len (int)
    3.4. msg_avp (string)
 
 3.1. alias_subdomains (string)
@@ -191,7 +191,7 @@ modparam("corex", "alias_subdomains", "udp:sip-router.org:5060")
 modparam("corex", "network_io_intercept", 1)
 ...
 
-3.3. msg_min_len (int)
+3.3. min_msg_len (int)
 
    Minimum content length of the packet to execute the
    event_route[network:msg]. This only works if network_io_intercept
@@ -199,9 +199,9 @@ modparam("corex", "network_io_intercept", 1)
 
    Default value is 0.
 
-   Example 1.3. Set msg_min_len parameter
+   Example 1.3. Set min_msg_len parameter
 ...
-modparam("corex", "msg_min_len", 32)
+modparam("corex", "min_msg_len", 32)
 ...
 
 3.4. msg_avp (string)
@@ -229,7 +229,7 @@ modparam("corex", "msg_avp", "$avp(msg)")
    4.7. msg_iflag_reset(flagname)
    4.8. msg_iflag_is_set(flagname)
 
-4.1. append_branch([ uri, [ q ] ])
+4.1.  append_branch([ uri, [ q ] ])
 
    Append a new branch to the destination set, useful to build the set of
    destination addresses for parallel forking or redirect replies.
@@ -251,7 +251,7 @@ modparam("corex", "msg_avp", "$avp(msg)")
     append_branch("$avp(uri)", "0.5");
 ...
 
-4.2. send([ host [ :port ] ])
+4.2.  send([ host [ :port ] ])
 
    Send the original SIP message to a specific destination in stateless
    mode. No changes are applied to received message, no Via header is
@@ -273,12 +273,12 @@ modparam("corex", "msg_avp", "$avp(msg)")
         send("$var(res)");
 ...
 
-4.3. send_tcp([ host [ :port ] ])
+4.3.  send_tcp([ host [ :port ] ])
 
    This function is identical to send() described above, except that it
    sends the SIP message using the TCP protocol instead of UDP.
 
-4.4. send_data(uri, data)
+4.4.  send_data(uri, data)
 
    Send the data to address specified by uri. Both parameters can contain
    pseudo-variables. The uri parameter has to be a valid SIP URI. The data
@@ -291,7 +291,7 @@ modparam("corex", "msg_avp", "$avp(msg)")
         send_data("sip:example.com:5070;transport=sctp", "Message at $Ts");
 ...
 
-4.5. is_incoming()
+4.5.  is_incoming()
 
    Returns true if contents of message buffer $mb are the data received
    from remote host, otherwise false indicating that the contents of $mb
@@ -313,7 +313,7 @@ event_route[network:msg] {
 }
 ...
 
-4.6. msg_iflag_set(flagname)
+4.6.  msg_iflag_set(flagname)
 
    Set internal SIP message flag. The parameter flagname can be:
    USE_UAC_FROM, USE_UAC_TO or UAC_AUTH.
@@ -330,7 +330,7 @@ event_route[network:msg] {
     msg_iflag_set("UAC_AUTH");
 ...
 
-4.7. msg_iflag_reset(flagname)
+4.7.  msg_iflag_reset(flagname)
 
    Reset the internal flag given as parameter.
 
@@ -341,7 +341,7 @@ event_route[network:msg] {
     msg_iflag_reset("UAC_AUTH");
 ...
 
-4.8. msg_iflag_is_set(flagname)
+4.8.  msg_iflag_is_set(flagname)
 
    Test if the internal flag given as parameter is set.
 
@@ -361,28 +361,28 @@ event_route[network:msg] {
    5.3. corex.shm_status
    5.4. corex.shm_summary
 
-5.1. corex.list_sockets
+5.1.  corex.list_sockets
 
    Print the list of sockets the application is listening on.
 
    Example:
                 kamcmd corex.list_sockets
 
-5.2. corex.list_aliases
+5.2.  corex.list_aliases
 
    Print the list of hostname aliases used to match the myself condition.
 
    Example:
                 kamcmd corex.list_aliases
 
-5.3. corex.shm_status
+5.3.  corex.shm_status
 
    Trigger shm status dump to syslog.
 
    Example:
                 kamcmd corex.shm_status
 
-5.4. corex.shm_summary
+5.4.  corex.shm_summary
 
    Trigger shm summary dump to syslog.
 
@@ -393,7 +393,7 @@ event_route[network:msg] {
 
    6.1. event_route[network:msg]
 
-6.1. event_route[network:msg]
+6.1.  event_route[network:msg]
 
    Event route block to be executed when new data is received from network
    or the data that is about to be sent to a remote host by a SIP worker
diff --git a/modules/corex/doc/corex_admin.xml b/modules/corex/doc/corex_admin.xml
index d2b84c7..9e65649 100644
--- a/modules/corex/doc/corex_admin.xml
+++ b/modules/corex/doc/corex_admin.xml
@@ -119,7 +119,7 @@ modparam("corex", "network_io_intercept", 1)
         </example>
     </section>
     <section>
-        <title><varname>msg_min_len</varname> (int)</title>
+        <title><varname>min_msg_len</varname> (int)</title>
         <para>
             Minimum content length of the packet to execute the event_route[network:msg].
 			This only works if network_io_intercept parameter is set to non-zero.
@@ -130,10 +130,10 @@ modparam("corex", "network_io_intercept", 1)
         </emphasis>
         </para>
         <example>
-        <title>Set <varname>msg_min_len</varname> parameter</title>
+        <title>Set <varname>min_msg_len</varname> parameter</title>
         <programlisting format="linespecific">
 ...
-modparam("corex", "msg_min_len", 32)
+modparam("corex", "min_msg_len", 32)
 ...
 </programlisting>
         </example>
diff --git a/modules/counters/Makefile b/modules/counters/Makefile
index 2f325fb..46eb67f 100644
--- a/modules/counters/Makefile
+++ b/modules/counters/Makefile
@@ -1,5 +1,5 @@
-# $Id$
 #
+# Kamailio :: counters module
 
 include ../../Makefile.defs
 auto_gen=
diff --git a/modules/counters/counters.c b/modules/counters/counters.c
index 260f6cd..7d7f85e 100644
--- a/modules/counters/counters.c
+++ b/modules/counters/counters.c
@@ -1,5 +1,4 @@
-/*$Id$
- *
+/*
  * Copyright (C) 2010 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -20,15 +19,14 @@
  * @file
  * @ingroup counters
  * Module: counters.
+ * @author andrei
  */
- 
-/*
- * History:
- * -------
- *  2010-08-06  created by andrei
- */
-
 
+/*!
+ * \defgroup counters Counters/statistics
+ * 
+ */
+ 
 #include "../../modparam.h"
 #include "../../dprint.h"
 #include "../../compiler_opt.h"
diff --git a/modules/cpl-c/Makefile b/modules/cpl-c/Makefile
index 374a9fe..d3c6da8 100644
--- a/modules/cpl-c/Makefile
+++ b/modules/cpl-c/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # WARNING: do not run this directly, it should be run by the master Makefile
 
diff --git a/modules/ctl/Makefile b/modules/ctl/Makefile
index 21707fb..96c0960 100644
--- a/modules/ctl/Makefile
+++ b/modules/ctl/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
@@ -7,7 +6,7 @@ include ../../Makefile.defs
 auto_gen=
 NAME=ctl.so
 LIBS=
-MOD_INSTALL_UTILS=../../utils/sercmd
+MOD_INSTALL_UTILS=../../utils/kamcmd
 # fifo support
 DEFS+=-DUSE_FIFO
 # use system malloc
diff --git a/modules/ctl/README b/modules/ctl/README
index ae19ce4..09f35d4 100644
--- a/modules/ctl/README
+++ b/modules/ctl/README
@@ -1,4 +1,3 @@
-
 The Ctl Module
 
 Andrei Pelinescu-Onciul
@@ -6,7 +5,7 @@ Andrei Pelinescu-Onciul
    iptelorg GmbH
 
    Copyright � 2009 iptelorg GmbH
-     _________________________________________________________________
+     __________________________________________________________________
 
    Table of Contents
 
@@ -39,9 +38,9 @@ Andrei Pelinescu-Onciul
    1.4. Set user parameter
    1.5. Set group parameter
    1.6. Set fifo parameter
-   1.7. Set the autoconversion parameter 
-   1.8. Set the binrpc_max_body_size parameter 
-   1.9. Set the binrpc_struct_max_body_size parameter 
+   1.7. Set the autoconversion parameter
+   1.8. Set the binrpc_max_body_size parameter
+   1.9. Set the binrpc_struct_max_body_size parameter
    1.10. print usage
    1.11. ctl.connections usage
    1.12. ctl.who usage
@@ -71,20 +70,20 @@ Chapter 1. Admin Guide
 
 1. Overview
 
-   This  module  implements  the  binrpc transport interface for Kamailio
+   This module implements the binrpc transport interface for Kamailio
    RPCs. It supports various transports over which it speaks binrpc: Unix
    datagram sockets, Unix stream sockets, UDP and TCP. It also supports a
-   backward  compatible  FIFO  interface  (using  the  old  Kamailio FIFO
+   backward compatible FIFO interface (using the old Kamailio FIFO
    protocol).
 
    By default (if no parameters are changed in the config file) it uses a
-   Unix  stream  socket under /tmp: /tmp/ser_ctl. This socket is also the
-   default for kamcmd.
+   Unix stream socket under /var/run/kamailio:
+   /var/run/kamailio/kamailio_ctl. This socket is also the default for
+   kamcmd.
 
    In general it's used in conjunction with kamcmd. kamcmd is a Unix tool
-   for   invoking  Kamailio  RPC  functions.  It  can  be  used  both  in
-   interactive mode (supports tab-completion and history) or command line
-   mode.
+   for invoking Kamailio RPC functions. It can be used both in interactive
+   mode (supports tab-completion and history) or command line mode.
 
    Example 1.1. kamcmd example usage
 $ kamcmd ps
@@ -104,11 +103,11 @@ $ kamcmd ps
 
 2. BINRPC
 
-   binrpc  is a ser proprietary binary protocol for invoking rpcs. It was
-   designed  such that it would minimize the packet sizes and it would be
+   binrpc is a ser proprietary binary protocol for invoking rpcs. It was
+   designed such that it would minimize the packet sizes and it would be
    very fast to parse (as opposed to XML-rpc).
 
-   The    binrpc    encoding    format   is   fully   documented   inside
+   The binrpc encoding format is fully documented inside
    modules/ctl/binrpc.h.
 
 3. Parameters
@@ -124,19 +123,19 @@ $ kamcmd ps
 
 3.1. binrpc (string)
 
-   Specifies  the  transport  used for the binrpc protocol. The following
-   transport  protocol  are supported: Unix datagram sockets, Unix stream
+   Specifies the transport used for the binrpc protocol. The following
+   transport protocol are supported: Unix datagram sockets, Unix stream
    sockets, UDP and TCP.
 
    The format is: [ protocol:] address_port|path .
 
      * For Unix sockets: [unixd|unixs|unix]:path where "unixd" means Unix
-       datagram  sockets  and  "unix"  "unixs"  mean Unix stream sockets.
-       Examples:    "unixd:/tmp/unix_dgram",    "unixs:/tmp/unix_stream",
+       datagram sockets and "unix" "unixs" mean Unix stream sockets.
+       Examples: "unixd:/tmp/unix_dgram", "unixs:/tmp/unix_stream",
        "unix:/tmp/unix_stream".
-     * For  UDP or TCP sockets: [udp|tcp]:address:port. If the address is
+     * For UDP or TCP sockets: [udp|tcp]:address:port. If the address is
        "*" or missing, it will bind to all the local addresses (0.0.0.0).
-       Examples:  "udp:localhost:2046", "tcp:localhost:2046", "tcp:3012",
+       Examples: "udp:localhost:2046", "tcp:localhost:2046", "tcp:3012",
        "udp:*:3012".
 
    If the protocol part is missing and the address/path part looks like a
@@ -145,18 +144,19 @@ $ kamcmd ps
      * "/tmp/unix_test" - equivalent to "unixs:/tmp/unix_test".
      * "localhost:3000" - equivalent to "udp:localhost:3000".
 
-   Multiple  transports  /  listen  addresses  can  be specified, just by
+   Multiple transports / listen addresses can be specified, just by
    setting the parameter multiple times.
 
-   Default:"unix:/tmp/ser_ctl" (Unix stream socket). The default value is
-   used only if no binrpc parameter is found in the config file.
+   Default: "unix:/var/run/kamailio/kamailio_ctl" (Unix stream socket).
+   The default value is used only if no binrpc parameter is found in the
+   config file.
 
    Example 1.2. Set binrpc parameter
 loadmodule "ctl"
 # optional listen addresses, if no one is specified,
 # ctl will listen on unixs:/tmp/ser_ctl
 
-modparam("ctl", "binrpc", "unix:/tmp/ser_ctl") # default
+modparam("ctl", "binrpc", "unix:/tmp/kamailio_ctl") # default
 modparam("ctl", "binrpc", "udp:localhost:2046")
 modparam("ctl", "binrpc", "tcp:localhost:2046")
 modparam("ctl", "binrpc", "unixd:/tmp/unix_dgram")  # unix datagram
@@ -197,13 +197,12 @@ modparam("ctl", "group", 100)
 3.5. fifo (integer)
 
    fifo used for the obsolete fifo protocol. The fifo protocol can be run
-   over    a    real    fifo,    over    UDP   or   over   TCP.   Format:
-   [protocol:]path|address.  If  no  protocol is specified the default is
-   "fifo".      Examples:     "fifo:/tmp/ser_fifo",     "/tmp/ser_fifo2",
-   "udp:*:2050",  "tcp:localhost:2050".  For  more details on the UDP and
-   TCP  formats see binrpc. Multiple fifos or fifo transports can be used
-   in the same time (just by setting the fifo parameter multiple times in
-   the config).
+   over a real fifo, over UDP or over TCP. Format:
+   [protocol:]path|address. If no protocol is specified the default is
+   "fifo". Examples: "fifo:/tmp/ser_fifo", "/tmp/ser_fifo2", "udp:*:2050",
+   "tcp:localhost:2050". For more details on the UDP and TCP formats see
+   binrpc. Multiple fifos or fifo transports can be used in the same time
+   (just by setting the fifo parameter multiple times in the config).
 
    Default: not set (no fifo will be used).
 
@@ -216,8 +215,8 @@ modparam("ctl", "fifo", "tcp:*:2050")              # fifo over tcp
 
 3.6. autoconversion (integer)
 
-   Enable  or  disable  automatic  type  conversion globally, for all the
-   methods  parameters. If on, a type mismatch in a method parameter will
+   Enable or disable automatic type conversion globally, for all the
+   methods parameters. If on, a type mismatch in a method parameter will
    not cause a fault if it is possible to automatically convert it to the
    expected type.
 
@@ -225,30 +224,30 @@ modparam("ctl", "fifo", "tcp:*:2050")              # fifo over tcp
 
    It is recommended to leave this parameter to its default off value and
    fix instead the client application (which should use the proper types)
-   or  to  modify the target rpc to accept any type (see the rpc scan '.'
+   or to modify the target rpc to accept any type (see the rpc scan '.'
    modifier).
 
-   Example 1.7. Set the autoconversion parameter 
+   Example 1.7. Set the autoconversion parameter
 modparam("ctl", "autoconversion", 1)
 
 3.7. binrpc_max_body_size (integer)
 
-   Set  the  size  of  binrpc  buffer  for  RPC  reply.  Value represents
+   Set the size of binrpc buffer for RPC reply. Value represents
    kilobytes.
 
    Default: 4 (meaning 4KB);
 
-   Example 1.8. Set the binrpc_max_body_size parameter 
+   Example 1.8. Set the binrpc_max_body_size parameter
 modparam("ctl", "binrpc_max_body_size", 10)
 
 3.8. binrpc_struct_max_body_size (integer)
 
-   Set  the  size  of  binrpc  structure  buffer  for  RPC  reply.  Value
-   represents kilobytes.
+   Set the size of binrpc structure buffer for RPC reply. Value represents
+   kilobytes.
 
    Default: 1 (meaning 1KB);
 
-   Example 1.9. Set the binrpc_struct_max_body_size parameter 
+   Example 1.9. Set the binrpc_struct_max_body_size parameter
 modparam("ctl", "binrpc_struct_max_body_size", 3)
 
 4. SIP-router RPC Functions
@@ -263,7 +262,7 @@ modparam("ctl", "binrpc_struct_max_body_size", 3)
 
    Example 1.10. print usage
  $ kamcmd -f"[%v] %v:%v %v\n" ctl.listen
-[binrpc] unix_stream:/tmp/ser_ctl
+[binrpc] unix_stream:/tmp/kamailio_ctl
 
 # note: the above command is equivalent with kamcmd listen
 
@@ -281,6 +280,6 @@ modparam("ctl", "binrpc_struct_max_body_size", 3)
 
    Example 1.12. ctl.who usage
  $ kamcmd -f"[%v] %v: %v %v -> %v %v\n" ctl.who
-[binrpc] unix_stream: <anonymous unix socket>  -> /tmp/ser_ctl
+[binrpc] unix_stream: <anonymous unix socket>  -> /tmp/kamailio_ctl
 
 # note the above command is equivalent to kamcmd who
diff --git a/modules/ctl/binrpc.c b/modules/ctl/binrpc.c
index 10b9dad..e7454be 100644
--- a/modules/ctl/binrpc.c
+++ b/modules/ctl/binrpc.c
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2006 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,11 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/* History:
- * --------
- *  2006-02-08  created by andrei
- */
-
 
 
 #include "binrpc.h"
diff --git a/modules/ctl/binrpc.h b/modules/ctl/binrpc.h
index f19a5cb..5b47d88 100644
--- a/modules/ctl/binrpc.h
+++ b/modules/ctl/binrpc.h
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2006 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,11 +17,7 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/* History:
- * --------
- *  2006-02-08  created by andrei
- *  2006-11-03  replies with no payload are allowed (andrei)
- */
+
 /* binrpc is  supposed to be a minimalist binary rpc implementation */
 
 
diff --git a/modules/ctl/binrpc_run.c b/modules/ctl/binrpc_run.c
index 19d9ed2..b06781b 100644
--- a/modules/ctl/binrpc_run.c
+++ b/modules/ctl/binrpc_run.c
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2006 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,10 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/* History:
- * --------
- *  2006-02-08  created by andrei
- */
 
 
 #include "binrpc.h"
diff --git a/modules/ctl/binrpc_run.h b/modules/ctl/binrpc_run.h
index aa0960c..bbc985b 100644
--- a/modules/ctl/binrpc_run.h
+++ b/modules/ctl/binrpc_run.h
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2006 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,10 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/* History:
- * --------
- *  2006-02-08  created by andrei
- */
 
 #ifndef _binrpc_run_h
 #define _binrpc_run_h
diff --git a/modules/ctl/ctl.c b/modules/ctl/ctl.c
index 6786f33..f630f8a 100644
--- a/modules/ctl/ctl.c
+++ b/modules/ctl/ctl.c
@@ -1,21 +1,15 @@
 /*
- * $Id$
  *
  * Copyright (C) 2006 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,13 +18,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/* History:
- * --------
- *  2006-02-08  created by andrei
- *  2007-01-18  use PROC_RPC rank when forking (andrei)
- */
-
-
 
 #include "../../sr_module.h"
 #include "../../ut.h"
diff --git a/modules/ctl/ctl.cfg b/modules/ctl/ctl.cfg
index 11126a0..a9fe0f9 100644
--- a/modules/ctl/ctl.cfg
+++ b/modules/ctl/ctl.cfg
@@ -1,5 +1,3 @@
-# $id$
-#
 # ctl example configuration file
 #
 # to test use:
diff --git a/modules/ctl/ctl.h b/modules/ctl/ctl.h
index 5c71da3..b40299e 100644
--- a/modules/ctl/ctl.h
+++ b/modules/ctl/ctl.h
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2012 sip-router.org
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/modules/ctl/ctl_defaults.h b/modules/ctl/ctl_defaults.h
index 5c10c17..b41aa53 100644
--- a/modules/ctl/ctl_defaults.h
+++ b/modules/ctl/ctl_defaults.h
@@ -1,15 +1,13 @@
-/* $Id$
- */
 
 #ifndef __ctl_defaults_h
 #define __ctl_defaults_h
 /*listen by default on: */
 #ifdef SRNAME
 /* this is used when compiling sercmd tool */
-#define DEFAULT_CTL_SOCKET  "unixs:/tmp/" SRNAME "_ctl"
+#define DEFAULT_CTL_SOCKET  "unixs:" RUN_DIR "/" SRNAME "_ctl"
 #else
 /* this is used when compiling sip server */
-#define DEFAULT_CTL_SOCKET  "unixs:/tmp/" NAME "_ctl"
+#define DEFAULT_CTL_SOCKET  "unixs:" RUN_DIR "/" NAME "_ctl"
 #endif
 /* port used by default for tcp/udp if no port is explicitely specified */
 #define DEFAULT_CTL_PORT 2049
diff --git a/modules/ctl/ctrl_socks.c b/modules/ctl/ctrl_socks.c
index dac5a1d..d750432 100644
--- a/modules/ctl/ctrl_socks.c
+++ b/modules/ctl/ctrl_socks.c
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2006 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,10 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/* History:
- * --------
- *  2006-02-14  created by andrei
- */
 
 #include "ctrl_socks.h"
 #include "init_socks.h"
diff --git a/modules/ctl/ctrl_socks.h b/modules/ctl/ctrl_socks.h
index 586b0d6..d602c33 100644
--- a/modules/ctl/ctrl_socks.h
+++ b/modules/ctl/ctrl_socks.h
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2006 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,10 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/* History:
- * --------
- *  2006-02-14  created by andrei
- */
 
 #ifndef _ctrl_socks_h
 #define _ctrl_socks_h
diff --git a/modules/ctl/doc/ctl.xml b/modules/ctl/doc/ctl.xml
index 5ac9950..f2e0219 100644
--- a/modules/ctl/doc/ctl.xml
+++ b/modules/ctl/doc/ctl.xml
@@ -40,7 +40,8 @@
 	</para>
 	<para>
 		By default (if no parameters are changed in the config file) it uses
-		a Unix stream socket under /tmp: /tmp/&ctlsocket;. This socket is also the
+		a Unix stream socket under /var/run/&kamailiobinary;:
+		/var/run/&kamailiobinary;/&ctlsocket;. This socket is also the
 		default for &sercmd;.
 	</para>
 	<para>
diff --git a/modules/ctl/doc/ctl_params.xml b/modules/ctl/doc/ctl_params.xml
index 3017e8f..3bd2553 100644
--- a/modules/ctl/doc/ctl_params.xml
+++ b/modules/ctl/doc/ctl_params.xml
@@ -63,7 +63,8 @@
 		setting the parameter multiple times.
 	</para>
 	<para>
-		<emphasis>Default:</emphasis>"unix:/tmp/&ctlsocket;" (Unix stream socket).
+		<emphasis>Default:</emphasis>
+		"unix:/var/run/&kamailiobinary;/&kamailiobinary;_ctl" (Unix stream socket).
 		The default value is used <emphasis>only</emphasis> if no
 		<varname>binrpc</varname> parameter is found in the config file.
 	</para>
diff --git a/modules/ctl/fifo_server.c b/modules/ctl/fifo_server.c
index 43ec76c..44fbb3d 100644
--- a/modules/ctl/fifo_server.c
+++ b/modules/ctl/fifo_server.c
@@ -1,23 +1,15 @@
 /*
- * $Id$
- *
- *
  * Copyright (C) 2001-2003 FhG Fokus
  * Copyright (C) 2005 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -26,6 +18,16 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
+ */
+
+/*! \file
+ * \brief ctl module
+ * \ingroup ctl
+ *
+ */
+
+/*! \defgroup ctl Control binrpc socket
+ *
  * Fifo server is a very powerful tool used to access easily
  * ser's internals via textual interface, similarly to
  * how internals of many operating systems are accessible
@@ -52,22 +54,6 @@
  * File test/transaction.fifo illustrates example of use
  * of t_uac command (part of TM module).
  *
- * History:
- * --------
- *  2003-03-29  destroy pkg mem introduced (jiri)
- *  2003-03-19  replaced all mallocs/frees w/ ctl_malloc/ctl_free (andrei)
- *  2003-01-29  new built-in fifo commands: arg and pwd (jiri)
- *  2003-10-07  fifo security fixes: permissions, always delete old fifo,
- *               reply fifo checks -- added fifo_check (andrei)
- *  2003-10-13  added fifo_dir for reply fifos (andrei)
- *  2003-10-30  DB interface exported via FIFO (bogdan)
- *  2004-03-09  open_fifo_server split into init_ and start_ (andrei)
- *  2004-04-29  added chown(sock_user, sock_group)  (andrei)
- *  2004-06-06  updated to the new DB interface  & init_db_fifo (andrei)
- *  2004-09-19  fifo is deleted on exit (destroy_fifo)  (andrei)
- *  2005-03-02  meminfo fifo cmd added (andrei)
- *  2006-02-17  hacked to process fifo request as a part of the ctrl module
- *              and to work also over tcp, udp or unix sockets (andrei)
  */
 
 #ifdef USE_FIFO
diff --git a/modules/ctl/fifo_server.h b/modules/ctl/fifo_server.h
index 05ae587..d40390b 100644
--- a/modules/ctl/fifo_server.h
+++ b/modules/ctl/fifo_server.h
@@ -1,23 +1,15 @@
 /*
- * $Id$
- *
- *
  * Copyright (C) 2001-2003 FhG Fokus
  * Copyright (C) 2005 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/modules/ctl/init_socks.c b/modules/ctl/init_socks.c
index 37eb5ad..0bbaebc 100644
--- a/modules/ctl/init_socks.c
+++ b/modules/ctl/init_socks.c
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2006 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,10 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/* History:
- * --------
- *  2006-02-14  created by andrei
- */
 
 #include "init_socks.h"
 #include "../../dprint.h"
diff --git a/modules/ctl/init_socks.h b/modules/ctl/init_socks.h
index a3cb602..07f6f96 100644
--- a/modules/ctl/init_socks.h
+++ b/modules/ctl/init_socks.h
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2006 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,10 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/* History:
- * --------
- *  2006-02-14  created by andrei
- */
 
 #ifndef _init_socks_h
 #define _init_socks_h
diff --git a/modules/ctl/io_listener.c b/modules/ctl/io_listener.c
index 1f97230..185c925 100644
--- a/modules/ctl/io_listener.c
+++ b/modules/ctl/io_listener.c
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2006 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,10 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/* History:
- * --------
- *  2006-02-15  created by andrei
- */
 
 #include "../../globals.h"
 #include "../../pt.h"  /* process_count */
diff --git a/modules/ctl/io_listener.h b/modules/ctl/io_listener.h
index 774957d..bb427a0 100644
--- a/modules/ctl/io_listener.h
+++ b/modules/ctl/io_listener.h
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2006 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,10 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/* History:
- * --------
- *  2006-02-15  created by andrei
- */
 
 #ifndef _io_listener_h
 #define _io_listener_h
diff --git a/modules/db2_ldap/Makefile b/modules/db2_ldap/Makefile
index 3408a5d..ec5d47f 100644
--- a/modules/db2_ldap/Makefile
+++ b/modules/db2_ldap/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # WARNING: do not run this directly, it should be run by the master Makefile
 
diff --git a/modules/db2_ops/Makefile b/modules/db2_ops/Makefile
index a02971b..d197023 100644
--- a/modules/db2_ops/Makefile
+++ b/modules/db2_ops/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # db_ops module makefile
 #
diff --git a/modules/db2_ops/db2_ops.c b/modules/db2_ops/db2_ops.c
index 96deacd..a90af0a 100644
--- a/modules/db2_ops/db2_ops.c
+++ b/modules/db2_ops/db2_ops.c
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2006 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/modules/db_berkeley/Makefile b/modules/db_berkeley/Makefile
index 55b304f..cef88d1 100644
--- a/modules/db_berkeley/Makefile
+++ b/modules/db_berkeley/Makefile
@@ -1,6 +1,5 @@
-# $Id:  $
 #
-# example module makefile
+# db_berkeley module makefile
 #
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
diff --git a/modules/db_berkeley/bdb_cmd.c b/modules/db_berkeley/bdb_cmd.c
index 98292aa..682d4e3 100644
--- a/modules/db_berkeley/bdb_cmd.c
+++ b/modules/db_berkeley/bdb_cmd.c
@@ -1,18 +1,16 @@
 /*
- * $Id$
- *
- * BDB Database Driver for SIP-router
+ * BDB Database Driver for Kamailio
  *
  * Copyright (C) 2008 iptelorg GmbH
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify it under the
+ * Kamailio is free software; you can redistribute it and/or modify it under the
  * terms of the GNU General Public License as published by the Free Software
  * Foundation; either version 2 of the License, or (at your option) any later
  * version.
  *
- * SIP-router is distributed in the hope that it will be useful, but WITHOUT ANY
+ * Kamailio is distributed in the hope that it will be useful, but WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
  * details.
@@ -509,17 +507,11 @@ int bdb_cmd_first(db_res_t* res)
 
 int bdb_cmd_next(db_res_t* res)
 {
-	db_con_t *con;
-	bdb_res_t *bres;
-	bdb_con_t *bcon;
 	bdb_cmd_t *bcmd;
 	DBT key, data;
 	int ret;
 	static char dbuf[MAX_ROW_SIZE];
 
-	con = res->cmd->ctx->con[db_payload_idx];
-	bres = DB_GET_PAYLOAD(res);
-	bcon = DB_GET_PAYLOAD(con);
 	bcmd = DB_GET_PAYLOAD(res->cmd);
 
 	if (bcmd->next_flag == 2 || bcmd->next_flag == -2) return 1;
diff --git a/modules/db_berkeley/bdb_cmd.h b/modules/db_berkeley/bdb_cmd.h
index da628cf..52f4046 100644
--- a/modules/db_berkeley/bdb_cmd.h
+++ b/modules/db_berkeley/bdb_cmd.h
@@ -1,18 +1,16 @@
 /*
- * $Id$
- *
- * BDB Database Driver for SIP-router
+ * BDB Database Driver for Kamailio
  *
  * Copyright (C) 2008 iptelorg GmbH
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify it under the
+ * Kamailio is free software; you can redistribute it and/or modify it under the
  * terms of the GNU General Public License as published by the Free Software
  * Foundation; either version 2 of the License, or (at your option) any later
  * version.
  *
- * SIP-router is distributed in the hope that it will be useful, but WITHOUT ANY
+ * Kamailio is distributed in the hope that it will be useful, but WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
  * details.
diff --git a/modules/db_berkeley/bdb_con.c b/modules/db_berkeley/bdb_con.c
index 400507d..73b94c6 100644
--- a/modules/db_berkeley/bdb_con.c
+++ b/modules/db_berkeley/bdb_con.c
@@ -1,18 +1,16 @@
 /*
- * $Id$
- *
  * BDB Database Driver for SER
  *
  * Copyright (C) 2008 iptelorg GmbH
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify it under the
+ * Kamailio is free software; you can redistribute it and/or modify it under the
  * terms of the GNU General Public License as published by the Free Software
  * Foundation; either version 2 of the License, or (at your option) any later
  * version.
  *
- * SIP-router is distributed in the hope that it will be useful, but WITHOUT ANY
+ * Kamailio is distributed in the hope that it will be useful, but WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
  * details.
@@ -51,12 +49,9 @@
  */
 static void bdb_con_free(db_con_t* con, bdb_con_t *payload)
 {
-	bdb_uri_t *buri;
 	if (!payload)
 		return;
 
-	buri = DB_GET_PAYLOAD(con->uri);
-
 	/* Delete the structure only if there are no more references
 	 * to it in the connection pool
 	 */
diff --git a/modules/db_berkeley/bdb_con.h b/modules/db_berkeley/bdb_con.h
index 05bc514..e0494d2 100644
--- a/modules/db_berkeley/bdb_con.h
+++ b/modules/db_berkeley/bdb_con.h
@@ -1,18 +1,16 @@
 /* 
- * $Id$ 
- *
- * BDB Database Driver for SIP-router
+ * BDB Database Driver for Kamailio
  *
  * Copyright (C) 2008 iptelorg GmbH
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify it under the
+ * Kamailio is free software; you can redistribute it and/or modify it under the
  * terms of the GNU General Public License as published by the Free Software
  * Foundation; either version 2 of the License, or (at your option) any later
  * version.
  *
- * SIP-router is distributed in the hope that it will be useful, but WITHOUT ANY
+ * Kamailio is distributed in the hope that it will be useful, but WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
  * details.
diff --git a/modules/db_berkeley/bdb_crs_compat.h b/modules/db_berkeley/bdb_crs_compat.h
index 1badf38..34e8c48 100644
--- a/modules/db_berkeley/bdb_crs_compat.h
+++ b/modules/db_berkeley/bdb_crs_compat.h
@@ -1,18 +1,16 @@
 /*
- * $Id$
- *
- * BDB Compatibility layer for SIP-router
+ * BDB Compatibility layer for Kamailio
  *
  * Copyright (C) 2010 Marius Zbihlei marius.zbihlei at 1and1 dot ro
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify it under the
+ * Kamailio is free software; you can redistribute it and/or modify it under the
  * terms of the GNU General Public License as published by the Free Software
  * Foundation; either version 2 of the License, or (at your option) any later
  * version.
  *
- * SIP-router is distributed in the hope that it will be useful, but WITHOUT ANY
+ * Kamailio is distributed in the hope that it will be useful, but WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
  * details.
@@ -40,4 +38,4 @@
 #endif
 #endif
 
-#endif //BDB_CRS_COMPAT_H
\ No newline at end of file
+#endif //BDB_CRS_COMPAT_H
diff --git a/modules/db_berkeley/bdb_fld.c b/modules/db_berkeley/bdb_fld.c
index 8e5d8b6..87c8be9 100644
--- a/modules/db_berkeley/bdb_fld.c
+++ b/modules/db_berkeley/bdb_fld.c
@@ -1,18 +1,16 @@
 /*
- * $Id$
- *
- * BDB Database Driver for SIP-router
+ * BDB Database Driver for Kamailio
  *
  * Copyright (C) 2008 iptelorg GmbH
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify it under the
+ * Kamailio is free software; you can redistribute it and/or modify it under the
  * terms of the GNU General Public License as published by the Free Software
  * Foundation; either version 2 of the License, or (at your option) any later
  * version.
  *
- * SIP-router is distributed in the hope that it will be useful, but WITHOUT ANY
+ * Kamailio is distributed in the hope that it will be useful, but WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
  * details.
diff --git a/modules/db_berkeley/bdb_fld.h b/modules/db_berkeley/bdb_fld.h
index 7dbc474..36b9e7d 100644
--- a/modules/db_berkeley/bdb_fld.h
+++ b/modules/db_berkeley/bdb_fld.h
@@ -1,18 +1,16 @@
 /*
- * $Id$
- *
- * BDB Database Driver for SIP-router
+ * BDB Database Driver for Kamailio
  *
  * Copyright (C) 2008 iptelorg GmbH
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify it under the
+ * Kamailio is free software; you can redistribute it and/or modify it under the
  * terms of the GNU General Public License as published by the Free Software
  * Foundation; either version 2 of the License, or (at your option) any later
  * version.
  *
- * SIP-router is distributed in the hope that it will be useful, but WITHOUT ANY
+ * Kamailio is distributed in the hope that it will be useful, but WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
  * details.
diff --git a/modules/db_berkeley/bdb_lib.c b/modules/db_berkeley/bdb_lib.c
index c847702..d4bce75 100644
--- a/modules/db_berkeley/bdb_lib.c
+++ b/modules/db_berkeley/bdb_lib.c
@@ -1,19 +1,17 @@
 /*
- * $Id: bdb_lib.c 4585 2008-08-06 08:20:30Z klaus_darilion $
- *
  * db_berkeley module, portions of this code were templated using
  * the dbtext and postgres modules.
 
  * Copyright (C) 2007 Cisco Systems
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -22,9 +20,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  * 
- * History:
- * --------
- * 2007-09-19  genesis (wiquan)
  */
 
 /*! \file
diff --git a/modules/db_berkeley/bdb_lib.h b/modules/db_berkeley/bdb_lib.h
index aad730f..1c97418 100644
--- a/modules/db_berkeley/bdb_lib.h
+++ b/modules/db_berkeley/bdb_lib.h
@@ -1,19 +1,17 @@
 /*
- * $Id$
- *
  * db_berkeley module, portions of this code were templated using
  * the dbtext and postgres modules.
 
  * Copyright (C) 2007 Cisco Systems
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -22,9 +20,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  * 
- * History:
- * --------
- * 2007-09-19  genesis (wiquan)
  */
 
 /*! \file
diff --git a/modules/db_berkeley/bdb_mod.c b/modules/db_berkeley/bdb_mod.c
index 0c0c755..1983dcd 100644
--- a/modules/db_berkeley/bdb_mod.c
+++ b/modules/db_berkeley/bdb_mod.c
@@ -1,19 +1,17 @@
 /*
- * $Id$
- *
  * db_berkeley module, portions of this code were templated using
  * the dbtext and postgres modules.
 
  * Copyright (C) 2007 Cisco Systems
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -22,9 +20,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  * 
- * History:
- * --------
- * 2007-09-19  genesis (wiquan)
  */
 
 /*! \file
diff --git a/modules/db_berkeley/bdb_mod.h b/modules/db_berkeley/bdb_mod.h
index 7db0fd0..cdbb84e 100644
--- a/modules/db_berkeley/bdb_mod.h
+++ b/modules/db_berkeley/bdb_mod.h
@@ -1,19 +1,17 @@
 /*
- * $Id$
- *
  * db_berkeley module, portions of this code were templated using
  * the dbtext and postgres modules.
 
  * Copyright (C) 2007 Cisco Systems
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -22,9 +20,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  * 
- * History:
- * --------
- * 2007-09-19  genesis (wiquan)
  */
 
 /*! \file
diff --git a/modules/db_berkeley/bdb_res.c b/modules/db_berkeley/bdb_res.c
index 2136330..89112c2 100644
--- a/modules/db_berkeley/bdb_res.c
+++ b/modules/db_berkeley/bdb_res.c
@@ -1,17 +1,15 @@
 /* 
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  * Copyright (C) 2006-2007 iptelorg GmbH
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/modules/db_berkeley/bdb_res.h b/modules/db_berkeley/bdb_res.h
index 406da00..008359e 100644
--- a/modules/db_berkeley/bdb_res.h
+++ b/modules/db_berkeley/bdb_res.h
@@ -1,17 +1,15 @@
 /* 
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  * Copyright (C) 2006-2007 iptelorg GmbH
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/modules/db_berkeley/bdb_uri.c b/modules/db_berkeley/bdb_uri.c
index 672fc6b..d326958 100644
--- a/modules/db_berkeley/bdb_uri.c
+++ b/modules/db_berkeley/bdb_uri.c
@@ -1,18 +1,16 @@
 /*
- * $Id$
- *
- * BDB Database Driver for SIP-router
+ * BDB Database Driver for Kamailio
  *
  * Copyright (C) 2008 iptelorg GmbH
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify it under the
+ * Kamailio is free software; you can redistribute it and/or modify it under the
  * terms of the GNU General Public License as published by the Free Software
  * Foundation; either version 2 of the License, or (at your option) any later
  * version.
  *
- * SIP-router is distributed in the hope that it will be useful, but WITHOUT ANY
+ * Kamailio is distributed in the hope that it will be useful, but WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
  * details.
diff --git a/modules/db_berkeley/bdb_uri.h b/modules/db_berkeley/bdb_uri.h
index db8cb40..739a524 100644
--- a/modules/db_berkeley/bdb_uri.h
+++ b/modules/db_berkeley/bdb_uri.h
@@ -1,18 +1,16 @@
 /*
- * $Id$
- *
- * BDB Database Driver for SIP-router
+ * BDB Database Driver for Kamailio
  *
  * Copyright (C) 2008 iptelorg GmbH
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify it under the
+ * Kamailio is free software; you can redistribute it and/or modify it under the
  * terms of the GNU General Public License as published by the Free Software
  * Foundation; either version 2 of the License, or (at your option) any later
  * version.
  *
- * SIP-router is distributed in the hope that it will be useful, but WITHOUT ANY
+ * Kamailio is distributed in the hope that it will be useful, but WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
  * details.
diff --git a/modules/db_berkeley/km_bdb_lib.c b/modules/db_berkeley/km_bdb_lib.c
index f7693e3..600053d 100644
--- a/modules/db_berkeley/km_bdb_lib.c
+++ b/modules/db_berkeley/km_bdb_lib.c
@@ -1,19 +1,17 @@
 /*
- * $Id$
- *
  * db_berkeley module, portions of this code were templated using
  * the dbtext and postgres modules.
 
  * Copyright (C) 2007 Cisco Systems
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -22,9 +20,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  * 
- * History:
- * --------
- * 2007-09-19  genesis (wiquan)
  */
 
 /*! \file
diff --git a/modules/db_berkeley/km_bdb_lib.h b/modules/db_berkeley/km_bdb_lib.h
index c12a664..d109409 100644
--- a/modules/db_berkeley/km_bdb_lib.h
+++ b/modules/db_berkeley/km_bdb_lib.h
@@ -1,19 +1,17 @@
 /*
- * $Id$
- *
  * db_berkeley module, portions of this code were templated using
  * the dbtext and postgres modules.
 
  * Copyright (C) 2007 Cisco Systems
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -22,9 +20,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  * 
- * History:
- * --------
- * 2007-09-19  genesis (wiquan)
  */
 
 /*! \file
diff --git a/modules/db_berkeley/km_bdb_mi.c b/modules/db_berkeley/km_bdb_mi.c
index e941189..b5b97c9 100644
--- a/modules/db_berkeley/km_bdb_mi.c
+++ b/modules/db_berkeley/km_bdb_mi.c
@@ -1,18 +1,16 @@
 /*
- * $Id:  $
- *
  * db_berkeley MI functions
  *
  * Copyright (C) 2007  Cisco Systems
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -21,9 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2007-11-05  created (wiquan)
  */
 
 /*! \file
diff --git a/modules/db_berkeley/km_bdb_mi.h b/modules/db_berkeley/km_bdb_mi.h
index 8379dda..12c4cb3 100644
--- a/modules/db_berkeley/km_bdb_mi.h
+++ b/modules/db_berkeley/km_bdb_mi.h
@@ -1,18 +1,16 @@
 /*
- * $Id: $
- *
  * Header file for db_berkeley MI functions
  *
  * Copyright (C) 2007 Cisco Systems
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/modules/db_berkeley/km_bdb_res.c b/modules/db_berkeley/km_bdb_res.c
index 7c18564..44b945a 100644
--- a/modules/db_berkeley/km_bdb_res.c
+++ b/modules/db_berkeley/km_bdb_res.c
@@ -1,19 +1,17 @@
 /*
- * $Id$
- *
  * db_berkeley module, portions of this code were templated using
  * the dbtext and postgres modules.
 
  * Copyright (C) 2007 Cisco Systems
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -22,9 +20,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  * 
- * History:
- * --------
- * 2007-09-19  genesis (wiquan)
  */
 
 /*! \file
@@ -434,6 +429,8 @@ int bdb_is_neq_type(db_type_t _t0, db_type_t _t1)
 		case DB1_BITMAP:
 			if (_t0==DB1_INT)
 				return 0;
+		default:
+			break;
 	}
 	return 1;
 }
@@ -550,6 +547,8 @@ int bdb_cmp_val(db_val_t* _vp, db_val_t* _v)
 		case DB1_BITMAP:
 			return (_vp->val.int_val<_v->val.bitmap_val)?-1:
 				(_vp->val.int_val>_v->val.bitmap_val)?1:0;
+		default:
+			break;
 	}
 	return -2;
 }
diff --git a/modules/db_berkeley/km_bdb_res.h b/modules/db_berkeley/km_bdb_res.h
index 2e0de75..3998d67 100644
--- a/modules/db_berkeley/km_bdb_res.h
+++ b/modules/db_berkeley/km_bdb_res.h
@@ -1,19 +1,17 @@
 /*
- * $Id$
- *
  * sleepycat module, portions of this code were templated using
  * the dbtext and postgres modules.
 
  * Copyright (C) 2007 Cisco Systems
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -22,9 +20,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  * 
- * History:
- * --------
- * 2007-09-19  genesis (wiquan)
  */
 
 /*! \file
diff --git a/modules/db_berkeley/km_bdb_util.c b/modules/db_berkeley/km_bdb_util.c
index 9489799..148d65d 100644
--- a/modules/db_berkeley/km_bdb_util.c
+++ b/modules/db_berkeley/km_bdb_util.c
@@ -1,19 +1,17 @@
 /*
- * $Id$
- *
  * db_berkeley module, portions of this code were templated using
  * the dbtext and postgres modules.
 
  * Copyright (C) 2007 Cisco Systems
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -22,9 +20,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  * 
- * History:
- * --------
- * 2007-09-19  genesis (wiquan)
  */
 
 /*! \file
diff --git a/modules/db_berkeley/km_bdb_util.h b/modules/db_berkeley/km_bdb_util.h
index 60959dc..be98e3a 100644
--- a/modules/db_berkeley/km_bdb_util.h
+++ b/modules/db_berkeley/km_bdb_util.h
@@ -1,19 +1,17 @@
 /*
- * $Id$
- *
  * db_berkeley module, portions of this code were templated using
  * the dbtext and postgres modules.
 
  * Copyright (C) 2007 Cisco Systems
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -22,9 +20,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  * 
- * History:
- * --------
- * 2007-09-19  genesis (wiquan)
  */
 
 /*! \file
diff --git a/modules/db_berkeley/km_bdb_val.c b/modules/db_berkeley/km_bdb_val.c
index 062714c..15de46f 100644
--- a/modules/db_berkeley/km_bdb_val.c
+++ b/modules/db_berkeley/km_bdb_val.c
@@ -1,19 +1,17 @@
 /*
- * $Id$
- *
  * db_berkeley module, portions of this code were templated using
  * the dbtext and postgres modules.
 
  * Copyright (C) 2007 Cisco Systems
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -22,9 +20,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  * 
- * History:
- * --------
- * 2007-09-19  genesis (wiquan)
  */
  
 /*! \file
@@ -178,6 +173,8 @@ int bdb_str2val(db_type_t _t, db_val_t* _v, char* _s, int _l)
 		VAL_TYPE(_v) = DB1_BLOB;
 		LM_DBG("got blob len %d\n", _l);
 		return 0;
+	default:
+		break;
 	}
 
 	return -6;
diff --git a/modules/db_berkeley/km_bdb_val.h b/modules/db_berkeley/km_bdb_val.h
index c1d5bb8..63e2475 100644
--- a/modules/db_berkeley/km_bdb_val.h
+++ b/modules/db_berkeley/km_bdb_val.h
@@ -1,19 +1,17 @@
 /*
- * $Id$
- *
  * db_berkeley module, portions of this code were templated using
  * the dbtext and postgres modules.
 
  * Copyright (C) 2007 Cisco Systems
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -22,9 +20,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  * 
- * History:
- * --------
- * 2007-09-19  genesis (wiquan)
  */
 
 /*! \file
diff --git a/modules/db_berkeley/km_db_berkeley.c b/modules/db_berkeley/km_db_berkeley.c
index 0660177..9b0806e 100644
--- a/modules/db_berkeley/km_db_berkeley.c
+++ b/modules/db_berkeley/km_db_berkeley.c
@@ -1,19 +1,17 @@
 /*
- * $Id$
- *
  * db_berkeley module, portions of this code were templated using
  * the dbtext and postgres modules.
 
  * Copyright (C) 2007 Cisco Systems
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -22,9 +20,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  * 
- * History:
- * --------
- * 2007-09-19  genesis (wiquan)
  */
 
 /*! \file
@@ -781,13 +776,13 @@ int bdb_delete(db1_con_t* _h, db_key_t* _k, db_op_t* _op, db_val_t* _v, int _n)
 	tbl_cache_p _tbc = NULL;
 	table_p _tp = NULL;
 	char kbuf[MAX_ROW_SIZE];
-	int i, j, ret, klen;
+	int ret, klen;
 	int *lkey=NULL;
 	DBT key;
 	DB *db;
 	DBC *dbcp;
 
-	i = j = ret = 0;
+	ret = 0;
 	klen=MAX_ROW_SIZE;
 
 	if (_op)
@@ -909,13 +904,13 @@ int _bdb_delete_cursor(db1_con_t* _h, db_key_t* _k, db_op_t* _op, db_val_t* _v,
 	db1_res_t* _r   = NULL;
 	char kbuf[MAX_ROW_SIZE];
 	char dbuf[MAX_ROW_SIZE];
-	int i, ret, klen=MAX_ROW_SIZE;
+	int ret, klen=MAX_ROW_SIZE;
 	DBT key, data;
 	DB *db;
 	DBC *dbcp;
 	int *lkey=NULL;
 	
-	i = ret = 0;
+	ret = 0;
 	
 	if ((!_h) || !CON_TABLE(_h))
 		return -1;
diff --git a/modules/db_berkeley/km_db_berkeley.h b/modules/db_berkeley/km_db_berkeley.h
index b2f9571..7fa80d5 100644
--- a/modules/db_berkeley/km_db_berkeley.h
+++ b/modules/db_berkeley/km_db_berkeley.h
@@ -1,19 +1,17 @@
 /*
- * $Id$
- *
  * db_berkeley module, portions of this code were templated using
  * the dbtext and postgres modules.
 
  * Copyright (C) 2007 Cisco Systems
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -22,9 +20,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  * 
- * History:
- * --------
- * 2007-09-19  genesis (wiquan)
  */
 
 /*! \file
diff --git a/modules/db_cassandra/Makefile b/modules/db_cassandra/Makefile
index 7278092..4f62886 100644
--- a/modules/db_cassandra/Makefile
+++ b/modules/db_cassandra/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # db_cassandra module makefile
 #
diff --git a/modules/db_flatstore/Makefile b/modules/db_flatstore/Makefile
index 6b008b2..e322122 100644
--- a/modules/db_flatstore/Makefile
+++ b/modules/db_flatstore/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # WARNING: do not run this directly, it should be run by the master Makefile
 
diff --git a/modules/db_flatstore/README b/modules/db_flatstore/README
index 33df463..27b54ba 100644
--- a/modules/db_flatstore/README
+++ b/modules/db_flatstore/README
@@ -1,4 +1,3 @@
-
 Db_flatstore Module
 
 Jan Janak
@@ -7,7 +6,7 @@ Jan Janak
    <jan at iptel.org>
 
    Copyright � 2004, 2005 FhG FOKUS
-     _________________________________________________________________
+     __________________________________________________________________
 
    Table of Contents
 
@@ -37,73 +36,71 @@ Chapter 1. Admin Guide
 
    1.1. Rotating Log Files
 
-   Db_flatstore  is  one  of the SIP Router database modules. It does not
+   Db_flatstore is one of the Kamailio database modules. It does not
    export any functions executable from the configuration scripts, but it
-   exports  a  subset  of  functions from the database API and thus other
-   modules  can use it as a database driver, instead of, for example, the
-   Mysql module.
-
-   The  module  does  not implement all functions of the database API, it
-   supports  only  one  function,  insert.  This means that the module is
-   limited   but  very  fast.  It  is  especially  suitable  for  storing
-   accounting  information on sites with extremely high traffic. If MySQL
-   is  too  slow  or if you get a huge amount of accounting data then you
-   can consider using this module. Please note that the acc module is the
-   only module that was tested with the flastore module.
-
-   The  format  of  the files produced by this module is plain text. Each
-   line  consists  of  several  fields,  fields  are separated by the "|"
-   character  (vertical  bar).  New information is always appended at the
-   end  of the file. Searching, deleting and updating of existing data is
-   not supported by the module.
-
-   The  acc  module  can  be  configured  to  use  db_flatstore module as
-   database backend using the db_url_parameter:
+   exports a subset of functions from the database API and thus other
+   modules can use it as a database driver, instead of, for example, the
+   db_mysql module.
+
+   The module does not implement all functions of the database API, it
+   supports only one function, insert. This means that the module is
+   limited but very fast. It is especially suitable for storing accounting
+   information on sites with extremely high traffic. If MySQL is too slow
+   or if you get a huge amount of accounting data then you can consider
+   using this module. Please note that the acc module is the only module
+   that was tested with the flastore module.
+
+   The format of the files produced by this module is plain text. Each
+   line consists of several fields, fields are separated by the "|"
+   character (vertical bar). New information is always appended at the end
+   of the file. Searching, deleting and updating of existing data is not
+   supported by the module.
+
+   The acc module can be configured to use db_flatstore module as database
+   backend using the db_url_parameter:
 modparam("acc", "db_url", "flatstore:/var/log/acc")
 
-   This  configuration option tells the acc module that it should use the
-   db_flatstore  module  and  the  db_flatstore  module should create all
-   files  in the /var/log/acc directory. The directory must exist and SIP
-   Router  processes  must  have  permissions  to  create  files  in that
-   directory.
+   This configuration option tells the acc module that it should use the
+   db_flatstore module and the db_flatstore module should create all files
+   in the /var/log/acc directory. The directory must exist and Kamailio
+   processes must have permissions to create files in that directory.
 
    Name of files in that directory will follow the following pattern:
 <table_name>_<process_name>.log
 
-   For  example,  entries writen by the SIP Router process 8 into the acc
+   For example, entries writen by the Kamailio process 8 into the acc
    table would be written in file acc_8.log. For each table there will be
-   several  files,  one file for every SIP Router process that wrote some
-   data  into that table. The main reason why there are several files for
-   each  table  is  that  it is much faster to have one file per process,
-   because  it does not require any locking and thus SIP Router processes
-   will  not  block  each other. To get the complete data for a table you
-   can  simply concatenate the contents of files with the same table name
-   but different process id.
+   several files, one file for every Kamailio process that wrote some data
+   into that table. The main reason why there are several files for each
+   table is that it is much faster to have one file per process, because
+   it does not require any locking and thus Kamailio processes will not
+   block each other. To get the complete data for a table you can simply
+   concatenate the contents of files with the same table name but
+   different process id.
 
 1.1. Rotating Log Files
 
-   The module implements a SIP Router management interface command called
-   flatstore.rotate.  When  SIP Router receives the command it will close
-   and  reopen  all  files  used by the db_flatstore module. The rotation
-   itself  has  to  be  done  by another application (such as logrotate).
-   Follow  these  steps  to  rotate  files  generated by the db_flatstore
-   module:
+   The module implements a Kamailio management interface command called
+   flatstore.rotate. When Kamailio receives the command it will close and
+   reopen all files used by the db_flatstore module. The rotation itself
+   has to be done by another application (such as logrotate). Follow these
+   steps to rotate files generated by the db_flatstore module:
      * Rename the files that you want to rotate:
 cd /var/log/acc
 mv acc_1.log acc_1.log.20050605
 mv acc_2.log acc_2.log.20050605
 mv acc_4.log acc_3.log.20050605
 ...
-       Note  that at this point SIP Router will still be writing all data
+       Note that at this point Kamailio will still be writing all data
        into the renamed files.
-     * Send  SIP  Router  the  management command to close and reopen the
+     * Send Kamailio the management command to close and reopen the
        renamed files:
 kamcmd flatstore.rotate
-       This will force SIP Router to close the renamed files and open new
-       ones  with  original  names,  such as acc_1.log. New files will be
-       open  at  the  point when SIP Router has some data to write. It is
-       normal  that the files will be not created immediately if there is
-       no traffic on the SIP server.
+       This will force Kamailio to close the renamed files and open new
+       ones with original names, such as acc_1.log. New files will be open
+       at the point when Kamailio has some data to write. It is normal
+       that the files will be not created immediately if there is no
+       traffic on the SIP server.
      * Move the renamed files somewhere else and process them.
 
 2. Parameters
diff --git a/modules/db_flatstore/doc/db_flatstore.xml b/modules/db_flatstore/doc/db_flatstore.xml
index 0535da9..78970f7 100644
--- a/modules/db_flatstore/doc/db_flatstore.xml
+++ b/modules/db_flatstore/doc/db_flatstore.xml
@@ -31,11 +31,11 @@
     <section id="flatstore.overview">
 	<title>Overview</title>
 	<para>
-	    Db_flatstore is one of the &siprouter; database modules. It does
+	    Db_flatstore is one of the &kamailio; database modules. It does
 	    not export any functions executable from the configuration scripts,
 	    but it exports a subset of functions from the database API and thus
 	    other modules can use it as a database driver, instead of, for
-	    example, the Mysql module.
+	    example, the db_mysql module.
 	</para>
 	<para>
 	    The module does not implement all functions of the database API, it
@@ -63,7 +63,7 @@ modparam("acc", "db_url", "flatstore:/var/log/acc")
 	<para>
 	    This configuration option tells the acc module that it should use the
 	    db_flatstore module and the db_flatstore module should create all files
-	    in the /var/log/acc directory. The directory must exist and &siprouter;
+	    in the /var/log/acc directory. The directory must exist and &kamailio;
 	    processes must have permissions to create files in that directory.
 	</para>
 	<para>
@@ -73,12 +73,12 @@ modparam("acc", "db_url", "flatstore:/var/log/acc")
 <table_name>_<process_name>.log
 	</programlisting>
 	<para>
-	    For example, entries writen by the &siprouter; process 8 into the acc
+	    For example, entries writen by the &kamailio; process 8 into the acc
 	    table would be written in file acc_8.log. For each table there will be 
-	    several files, one file for every &siprouter; process that wrote some data into
+	    several files, one file for every &kamailio; process that wrote some data into
 	    that table. The main reason why there are several files for each
 	    table is that it is much faster to have one file per process,
-	    because it does not require any locking and thus &siprouter; processes will
+	    because it does not require any locking and thus &kamailio; processes will
 	    not block each other. To get the complete data for a table you can
 	    simply concatenate the contents of files with the same table name
 	    but different process id.
@@ -86,8 +86,8 @@ modparam("acc", "db_url", "flatstore:/var/log/acc")
 	<section id="rotating">
 	    <title>Rotating Log Files</title>
 	    <para>
-		The module implements a &siprouter; management interface command called
-	        flatstore.rotate. When &siprouter; receives the command it will
+		The module implements a &kamailio; management interface command called
+	        flatstore.rotate. When &kamailio; receives the command it will
 		close and reopen all files used by the db_flatstore module. 
 		The rotation itself has to be done by another application 
 		(such as logrotate). Follow these steps to rotate files generated by 
@@ -104,21 +104,21 @@ mv acc_2.log acc_2.log.20050605
 mv acc_4.log acc_3.log.20050605
 ...
 			</screen>
-			Note that at this point &siprouter; will still be writing all
+			Note that at this point &kamailio; will still be writing all
 			data into the renamed files.
 		    </para>
 		</listitem>
 		<listitem>
 		    <para>
-			Send &siprouter; the management command to close and reopen the
+			Send &kamailio; the management command to close and reopen the
 			renamed files:
 			<screen>
 &sercmd; flatstore.rotate
 			</screen>
-			This will force &siprouter; to close the renamed files and open
+			This will force &kamailio; to close the renamed files and open
 			new ones with original names, such as
 			<filename>acc_1.log</filename>. New files will be open
-			at the point when &siprouter; has some data to write. It is
+			at the point when &kamailio; has some data to write. It is
 			normal that the files will be not created immediately
 			if there is no traffic on the SIP server.
 		    </para>
diff --git a/modules/db_mysql/Makefile b/modules/db_mysql/Makefile
index 3d99764..1cea920 100644
--- a/modules/db_mysql/Makefile
+++ b/modules/db_mysql/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # WARNING: do not run this directly, it should be run by the master Makefile
 
diff --git a/modules/db_mysql/doc/db_mysql_admin.xml b/modules/db_mysql/doc/db_mysql_admin.xml
index 738c464..fdc1a5c 100644
--- a/modules/db_mysql/doc/db_mysql_admin.xml
+++ b/modules/db_mysql/doc/db_mysql_admin.xml
@@ -141,6 +141,25 @@ modparam("db_mysql", "insert_delayed", 1)
 </programlisting>
 		</example>
 	</section>
+        <section id="db_mysql.p.update_affected_found">
+		<title><varname>update_affected_found</varname> (integer)</title>
+		<para>
+		If set to 1, all UPDATE SQL queries will return the number of matched rows instead of the number of "updated" rows.
+		</para>
+		<para>
+		<emphasis>
+			Default value is 0 (1 - on / 0 - off).
+		</emphasis>
+		</para>
+		<example>
+		<title>Set <varname>update_affected_found</varname> parameter</title>
+		<programlisting format="linespecific">
+...
+modparam("db_mysql", "update_affected_found", 1)
+...
+</programlisting>
+		</example>
+	</section>
 	</section>
 	<section>
 	<title>Functions</title>
diff --git a/modules/db_mysql/km_db_mysql.c b/modules/db_mysql/km_db_mysql.c
index ab39ff0..201c018 100644
--- a/modules/db_mysql/km_db_mysql.c
+++ b/modules/db_mysql/km_db_mysql.c
@@ -1,6 +1,4 @@
 /* 
- * $Id$ 
- *
  * MySQL module interface
  *
  * Copyright (C) 2001-2003 FhG Fokus
@@ -22,12 +20,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/*
- * History:
- * --------
- *  2003-03-11  updated to the new module exports interface (andrei)
- *  2003-03-16  flags export parameter added (janakj)
- */
 
 /*! \file
  *  \brief DB_MYSQL :: Core
@@ -51,6 +43,7 @@
 unsigned int db_mysql_timeout_interval = 2;   /* Default is 6 seconds */
 unsigned int db_mysql_auto_reconnect = 1;     /* Default is enabled   */
 unsigned int db_mysql_insert_all_delayed = 0; /* Default is off */
+unsigned int db_mysql_update_affected_found = 0; /* Default is off */
 
 /* MODULE_VERSION */
 
diff --git a/modules/db_mysql/km_db_mysql.h b/modules/db_mysql/km_db_mysql.h
index f817765..80afd4a 100644
--- a/modules/db_mysql/km_db_mysql.h
+++ b/modules/db_mysql/km_db_mysql.h
@@ -1,6 +1,4 @@
 /* 
- * $Id$ 
- *
  * MySQL module interface
  *
  * Copyright (C) 2001-2003 FhG Fokus
@@ -22,10 +20,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2003-03-11  updated to the new module exports interface (andrei)
- *  2003-03-16  flags export parameter added (janakj)
  */
 
 /*! \file
@@ -43,6 +37,7 @@
 extern unsigned int db_mysql_timeout_interval;
 extern unsigned int db_mysql_auto_reconnect;
 extern unsigned int db_mysql_insert_all_delayed;
+extern unsigned int db_mysql_update_affected_found;
 
 int db_mysql_bind_api(db_func_t *dbb);
 
diff --git a/modules/db_mysql/km_dbase.c b/modules/db_mysql/km_dbase.c
index a3a0e77..a323be2 100644
--- a/modules/db_mysql/km_dbase.c
+++ b/modules/db_mysql/km_dbase.c
@@ -1,6 +1,4 @@
 /* 
- * $Id$ 
- *
  * MySQL module core functions
  *
  * Copyright (C) 2001-2003 FhG Fokus
@@ -142,7 +140,8 @@ void db_mysql_async_exec_task(void *param)
 		return;
 	}
 	if(db_mysql_submit_query(dbc, &p[1])<0) {
-		LM_ERR("failed to execute query on async worker\n");
+		LM_ERR("failed to execute query [%.*s] on async worker\n",
+		       (p[1].len>100)?100:p[1].len, p[1].s);
 	}
 	db_mysql_close(dbc);
 }
@@ -185,7 +184,7 @@ int db_mysql_submit_query_async(const db1_con_t* _h, const str* _s)
 	return 0;
 }
 
-
+static char *db_mysql_tquote = "`";
 /**
  * Initialize the database module.
  * No function should be called before this
@@ -194,7 +193,10 @@ int db_mysql_submit_query_async(const db1_con_t* _h, const str* _s)
  */
 db1_con_t* db_mysql_init(const str* _url)
 {
-	return db_do_init(_url, (void *)db_mysql_new_connection);
+	db1_con_t *c;
+	c = db_do_init(_url, (void *)db_mysql_new_connection);
+	if(c) CON_TQUOTE(c) = db_mysql_tquote;
+	return c;
 }
 
 
@@ -783,11 +785,12 @@ done:
 		return -1;
 	}
  
-	ret = snprintf(mysql_sql_buf, sql_buffer_size, "insert into %.*s (", CON_TABLE(_h)->len, CON_TABLE(_h)->s);
+	ret = snprintf(mysql_sql_buf, sql_buffer_size, "insert into %s%.*s%s (",
+			CON_TQUOTESZ(_h), CON_TABLE(_h)->len, CON_TABLE(_h)->s, CON_TQUOTESZ(_h));
 	if (ret < 0 || ret >= sql_buffer_size) goto error;
 	off = ret;
 
-	ret = db_print_columns(mysql_sql_buf + off, sql_buffer_size - off, _k, _n);
+	ret = db_print_columns(mysql_sql_buf + off, sql_buffer_size - off, _k, _n, CON_TQUOTESZ(_h));
 	if (ret < 0) return -1;
 	off += ret;
 
diff --git a/modules/db_mysql/km_dbase.h b/modules/db_mysql/km_dbase.h
index a37e850..7896497 100644
--- a/modules/db_mysql/km_dbase.h
+++ b/modules/db_mysql/km_dbase.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * MySQL module core functions
  *
  * Copyright (C) 2001-2003 FhG Fokus
diff --git a/modules/db_mysql/km_my_con.c b/modules/db_mysql/km_my_con.c
index bfd81e9..5558d66 100644
--- a/modules/db_mysql/km_my_con.c
+++ b/modules/db_mysql/km_my_con.c
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- *
  * Copyright (C) 2001-2004 iptel.org
  * Copyright (C) 2008 1&1 Internet AG
  *
@@ -44,6 +42,7 @@ struct my_con* db_mysql_new_connection(const struct db_id* id)
 {
 	struct my_con* ptr;
 	char *host, *grp, *egrp;
+	unsigned int connection_flag = 0;
 
 	if (!id) {
 		LM_ERR("invalid parameter value\n");
@@ -101,12 +100,16 @@ struct my_con* db_mysql_new_connection(const struct db_id* id)
 	mysql_options(ptr->con, MYSQL_OPT_READ_TIMEOUT, (const char *)&db_mysql_timeout_interval);
 	mysql_options(ptr->con, MYSQL_OPT_WRITE_TIMEOUT, (const char *)&db_mysql_timeout_interval);
 
+	if (db_mysql_update_affected_found) { 
+	    connection_flag |= CLIENT_FOUND_ROWS;
+	}
+	
 #if (MYSQL_VERSION_ID >= 40100)
 	if (!mysql_real_connect(ptr->con, host, id->username, id->password,
-				id->database, id->port, 0, CLIENT_MULTI_STATEMENTS)) {
+				id->database, id->port, 0, connection_flag|CLIENT_MULTI_STATEMENTS)) {
 #else
 	if (!mysql_real_connect(ptr->con, host, id->username, id->password,
-				id->database, id->port, 0, 0)) {
+				id->database, id->port, 0, connection_flag)) {
 #endif
 		LM_ERR("driver error: %s\n", mysql_error(ptr->con));
 		/* increase error counter */
diff --git a/modules/db_mysql/km_my_con.h b/modules/db_mysql/km_my_con.h
index cd353dc..45fed57 100644
--- a/modules/db_mysql/km_my_con.h
+++ b/modules/db_mysql/km_my_con.h
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  * Copyright (C) 2008 1&1 Internet AG
  *
diff --git a/modules/db_mysql/km_res.c b/modules/db_mysql/km_res.c
index 35844b0..c7dbb9e 100644
--- a/modules/db_mysql/km_res.c
+++ b/modules/db_mysql/km_res.c
@@ -1,6 +1,4 @@
 /* 
- * $Id$ 
- *
  * MySQL module result related functions
  *
  * Copyright (C) 2001-2003 FhG Fokus
diff --git a/modules/db_mysql/km_res.h b/modules/db_mysql/km_res.h
index e7c8156..5c73bee 100644
--- a/modules/db_mysql/km_res.h
+++ b/modules/db_mysql/km_res.h
@@ -1,6 +1,4 @@
 /* 
- * $Id$ 
- *
  * MySQL module result related functions
  *
  * Copyright (C) 2001-2003 FhG Fokus
diff --git a/modules/db_mysql/km_row.c b/modules/db_mysql/km_row.c
index f84a63c..4e6ab23 100644
--- a/modules/db_mysql/km_row.c
+++ b/modules/db_mysql/km_row.c
@@ -1,6 +1,4 @@
 /* 
- * $Id$ 
- *
  * MySQL module row related functions
  *
  * Copyright (C) 2001-2003 FhG Fokus
diff --git a/modules/db_mysql/km_row.h b/modules/db_mysql/km_row.h
index 9962975..231d26a 100644
--- a/modules/db_mysql/km_row.h
+++ b/modules/db_mysql/km_row.h
@@ -1,6 +1,4 @@
 /* 
- * $Id$ 
- *
  * MySQL module row related functions
  *
  * Copyright (C) 2001-2003 FhG Fokus
diff --git a/modules/db_mysql/km_val.c b/modules/db_mysql/km_val.c
index 4bc55cb..418bebc 100644
--- a/modules/db_mysql/km_val.c
+++ b/modules/db_mysql/km_val.c
@@ -1,6 +1,4 @@
 /* 
- * $Id$ 
- *
  * Copyright (C) 2001-2003 FhG Fokus
  * Copyright (C) 2008 1&1 Internet AG
  *
diff --git a/modules/db_mysql/km_val.h b/modules/db_mysql/km_val.h
index dd8a85d..345541b 100644
--- a/modules/db_mysql/km_val.h
+++ b/modules/db_mysql/km_val.h
@@ -1,6 +1,4 @@
 /* 
- * $Id$ 
- *
  * Copyright (C) 2001-2003 FhG Fokus
  * Copyright (C) 2008 1&1 Internet AG
  *
diff --git a/modules/db_mysql/my_cmd.c b/modules/db_mysql/my_cmd.c
index a482102..666692c 100644
--- a/modules/db_mysql/my_cmd.c
+++ b/modules/db_mysql/my_cmd.c
@@ -2,19 +2,14 @@
  * Copyright (C) 2001-2003 FhG Fokus
  * Copyright (C) 2006-2007 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/modules/db_mysql/my_cmd.h b/modules/db_mysql/my_cmd.h
index 6b51d16..d8a3d64 100644
--- a/modules/db_mysql/my_cmd.h
+++ b/modules/db_mysql/my_cmd.h
@@ -1,22 +1,15 @@
 /* 
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  * Copyright (C) 2006-2007 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/modules/db_mysql/my_con.c b/modules/db_mysql/my_con.c
index 919f6fc..15a1027 100644
--- a/modules/db_mysql/my_con.c
+++ b/modules/db_mysql/my_con.c
@@ -1,22 +1,15 @@
 /* 
- * $Id$
- *
  * Copyright (C) 2001-2004 iptel.org
  * Copyright (C) 2006-2007 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/modules/db_mysql/my_con.h b/modules/db_mysql/my_con.h
index 667e35b..7194320 100644
--- a/modules/db_mysql/my_con.h
+++ b/modules/db_mysql/my_con.h
@@ -1,22 +1,15 @@
 /* 
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  * Copyright (C) 2006-2007 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/modules/db_mysql/my_fld.c b/modules/db_mysql/my_fld.c
index 0ef1168..b5975d6 100644
--- a/modules/db_mysql/my_fld.c
+++ b/modules/db_mysql/my_fld.c
@@ -1,22 +1,15 @@
 /* 
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  * Copyright (C) 2006-2007 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/modules/db_mysql/my_fld.h b/modules/db_mysql/my_fld.h
index b93387b..0a024ce 100644
--- a/modules/db_mysql/my_fld.h
+++ b/modules/db_mysql/my_fld.h
@@ -1,22 +1,15 @@
 /* 
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  * Copyright (C) 2006-2007 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/modules/db_mysql/my_res.c b/modules/db_mysql/my_res.c
index c9608c1..0c93d40 100644
--- a/modules/db_mysql/my_res.c
+++ b/modules/db_mysql/my_res.c
@@ -1,22 +1,15 @@
 /* 
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  * Copyright (C) 2006-2007 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/modules/db_mysql/my_res.h b/modules/db_mysql/my_res.h
index 8f1ee87..5546aa7 100644
--- a/modules/db_mysql/my_res.h
+++ b/modules/db_mysql/my_res.h
@@ -1,22 +1,15 @@
 /* 
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  * Copyright (C) 2006-2007 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/modules/db_mysql/my_uri.c b/modules/db_mysql/my_uri.c
index c1dc388..10faa13 100644
--- a/modules/db_mysql/my_uri.c
+++ b/modules/db_mysql/my_uri.c
@@ -1,24 +1,17 @@
 /* 
- * $Id$ 
- *
  * MySQL module interface
  *
  * Copyright (C) 2001-2003 FhG FOKUS
  * Copyright (C) 2006-2007 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/modules/db_mysql/my_uri.h b/modules/db_mysql/my_uri.h
index 4033339..704c134 100644
--- a/modules/db_mysql/my_uri.h
+++ b/modules/db_mysql/my_uri.h
@@ -1,24 +1,17 @@
 /* 
- * $Id$ 
- *
  * MySQL module interface
  *
  * Copyright (C) 2001-2003 FhG FOKUS
  * Copyright (C) 2006-2007 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/modules/db_mysql/mysql_mod.c b/modules/db_mysql/mysql_mod.c
index 8d369c7..f537a6d 100644
--- a/modules/db_mysql/mysql_mod.c
+++ b/modules/db_mysql/mysql_mod.c
@@ -1,22 +1,15 @@
 /*
- * $Id$
- *
  * MySQL module interface
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the Kamailio software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
  * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
@@ -26,13 +19,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/*
- * History:
- * --------
- *  2003-03-11  updated to the new module exports interface (andrei)
- *  2003-03-16  flags export parameter added (janakj)
- *  2013-04-02  added transaction support (haakon.nessjoen at gmail.com)
- */
 /** @addtogroup mysql
  *  @{
  */
@@ -109,6 +95,7 @@ static param_export_t params[] = {
 	{"timeout_interval", INT_PARAM, &db_mysql_timeout_interval},
 	{"auto_reconnect",   INT_PARAM, &db_mysql_auto_reconnect},
 	{"insert_delayed",   INT_PARAM, &db_mysql_insert_all_delayed},
+	{"update_affected_found", INT_PARAM, &db_mysql_update_affected_found},
 	{0, 0, 0}
 };
 
diff --git a/modules/db_mysql/mysql_mod.h b/modules/db_mysql/mysql_mod.h
index 8e9095c..fd686d7 100644
--- a/modules/db_mysql/mysql_mod.h
+++ b/modules/db_mysql/mysql_mod.h
@@ -1,23 +1,16 @@
 /* 
- * $Id$ 
- *
  * MySQL module interface
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -26,12 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/*
- * History:
- * --------
- *  2003-03-11  updated to the new module exports interface (andrei)
- *  2003-03-16  flags export parameter added (janakj)
- */
 
 #ifndef _MYSQL_MOD_H
 #define _MYSQL_MOD_H
diff --git a/modules/db_oracle/Makefile b/modules/db_oracle/Makefile
index 2ea24e2..4b156e6 100644
--- a/modules/db_oracle/Makefile
+++ b/modules/db_oracle/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # WARNING: do not run this directly, it should be run by the master Makefile
 
diff --git a/modules/db_perlvdb/Makefile b/modules/db_perlvdb/Makefile
index fb2e780..47830a2 100644
--- a/modules/db_perlvdb/Makefile
+++ b/modules/db_perlvdb/Makefile
@@ -1,4 +1,3 @@
-# $Id: Makefile 769 2007-01-22 09:09:43Z bastian $
 #
 # WARNING: do not run this directly, it should be run by the master Makefile
 
diff --git a/modules/db_perlvdb/perlvdb_conv.c b/modules/db_perlvdb/perlvdb_conv.c
index d019006..5a0c7c0 100644
--- a/modules/db_perlvdb/perlvdb_conv.c
+++ b/modules/db_perlvdb/perlvdb_conv.c
@@ -140,6 +140,9 @@ inline SV *valdata(db_val_t* val) {
 		case DB1_BITMAP:
 			data = newSViv(VAL_BITMAP(val));
 			break;
+
+		default:
+			break;
 	}
 
 	return data;
diff --git a/modules/db_postgres/Makefile b/modules/db_postgres/Makefile
index aa8da69..3ed607b 100644
--- a/modules/db_postgres/Makefile
+++ b/modules/db_postgres/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # WARNING: do not run this directly, it should be run by the master Makefile
 
diff --git a/modules/db_postgres/README b/modules/db_postgres/README
index 76f10ce..7bfd597 100644
--- a/modules/db_postgres/README
+++ b/modules/db_postgres/README
@@ -24,12 +24,16 @@ Greg Fausak
         3. Parameters
 
               3.1. retries (integer)
+              3.2. timeout (integer)
+              3.3. tcp_keepalive (integer)
 
         4. Functions
 
    List of Examples
 
    1.1. Set retries parameter
+   1.2. Set timeout parameter
+   1.3. Set tcp_keepalive parameter
 
 Chapter 1. Admin Guide
 
@@ -44,6 +48,8 @@ Chapter 1. Admin Guide
    3. Parameters
 
         3.1. retries (integer)
+        3.2. timeout (integer)
+        3.3. tcp_keepalive (integer)
 
    4. Functions
 
@@ -73,6 +79,8 @@ Chapter 1. Admin Guide
 3. Parameters
 
    3.1. retries (integer)
+   3.2. timeout (integer)
+   3.3. tcp_keepalive (integer)
 
 3.1. retries (integer)
 
@@ -88,6 +96,37 @@ Chapter 1. Admin Guide
 modparam("db_postgres", "retries", 3)
 ...
 
+3.2. timeout (integer)
+
+   Setting this variable to any value larger than zero (which is the
+   default value) enables both a connection timeout and a query timeout.
+   If a connection attempt or a query takes longer than this many seconds,
+   the operation will be aborted and an error will be returned.
+
+   Note that this timeout is applied to each underlying operation (i.e.
+   for each connection attempt), so depending on circumstances and on the
+   value of the “retries” variable, a single query from the SIP proxy's
+   point of view can take longer than the “timeout”.
+
+   Example 1.2. Set timeout parameter
+...
+modparam("db_postgres", "timeout", 10)
+...
+
+3.3. tcp_keepalive (integer)
+
+   Enable the TCP keepalive timer and set the number of seconds the
+   connection must be idle before to start sending keepalive packets.
+   Defaults to zero, which disables TCP keepalive packets.
+
+   Only supported on platforms which understand and support the
+   “TCP_KEEPIDLE” socket option.
+
+   Example 1.3. Set tcp_keepalive parameter
+...
+modparam("db_postgres", "tcp_keepalive", 600)
+...
+
 4. Functions
 
    NONE
diff --git a/modules/db_postgres/doc/db_postgres_admin.xml b/modules/db_postgres/doc/db_postgres_admin.xml
index 3092c56..2d0901c 100644
--- a/modules/db_postgres/doc/db_postgres_admin.xml
+++ b/modules/db_postgres/doc/db_postgres_admin.xml
@@ -81,6 +81,55 @@ modparam("db_postgres", "retries", 3)
 </programlisting>
 		</example>
 	</section>
+
+	<section>
+		<title><varname>timeout</varname> (integer)</title>
+		<para>
+			Setting this variable to any value larger than zero (which is the
+			default value) enables both a connection timeout and a query
+			timeout. If a connection attempt or a query takes longer than this
+			many seconds, the operation will be aborted and an error will be
+			returned.
+		</para>
+		<para>
+			Note that this timeout is applied to each underlying operation
+			(i.e. for each connection attempt), so depending on circumstances
+			and on the value of the <quote>retries</quote> variable, a single
+			query from the &sip; proxy's point of view can take longer than the
+			<quote>timeout</quote>.
+		</para>
+		<example>
+		<title>Set <varname>timeout</varname> parameter</title>
+		<programlisting format="linespecific">
+...
+modparam("db_postgres", "timeout", 10)
+...
+</programlisting>
+		</example>
+	</section>
+
+	<section>
+		<title><varname>tcp_keepalive</varname> (integer)</title>
+		<para>
+			Enable the TCP keepalive timer and set the number of seconds the
+			connection must be idle before to start sending keepalive packets.
+			Defaults to zero, which disables TCP keepalive packets.
+		</para>
+		<para>
+		<emphasis>
+			Only supported on platforms which understand and support the
+			<quote>TCP_KEEPIDLE</quote> socket option.
+		</emphasis>
+		</para>
+		<example>
+		<title>Set <varname>tcp_keepalive</varname> parameter</title>
+		<programlisting format="linespecific">
+...
+modparam("db_postgres", "tcp_keepalive", 600)
+...
+</programlisting>
+		</example>
+	</section>
 	</section>
 
 	<section>
diff --git a/modules/db_postgres/km_dbase.c b/modules/db_postgres/km_dbase.c
index 61cd94a..50ffd7f 100644
--- a/modules/db_postgres/km_dbase.c
+++ b/modules/db_postgres/km_dbase.c
@@ -167,6 +167,10 @@ static int db_postgres_submit_query(const db1_con_t* _con, const str* _s)
 	int i, retries;
 	ExecStatusType pqresult;
 	PGresult *res = NULL;
+	int sock, ret;
+	fd_set fds;
+	time_t max_time;
+	struct timeval wait_time;
 
 	if(! _con || !_s || !_s->s)
 	{
@@ -217,6 +221,44 @@ static int db_postgres_submit_query(const db1_con_t* _con, const str* _s)
 		/* exec the query */
 
 		if (PQsendQuery(CON_CONNECTION(_con), s)) {
+			if (pg_timeout <= 0)
+				goto do_read;
+
+			max_time = time(NULL) + pg_timeout;
+
+			while (1) {
+				sock = PQsocket(CON_CONNECTION(_con));
+				FD_ZERO(&fds);
+				FD_SET(sock, &fds);
+
+				wait_time.tv_usec = 0;
+				wait_time.tv_sec = max_time - time(NULL);
+				if (wait_time.tv_sec <= 0 || wait_time.tv_sec > 0xffffff)
+					goto timeout;
+
+				ret = select(sock + 1, &fds, NULL, NULL, &wait_time);
+				if (ret < 0) {
+					if (errno == EINTR)
+						continue;
+					LM_WARN("select() error\n");
+					goto reset;
+				}
+				if (!ret) {
+timeout:
+					LM_WARN("timeout waiting for postgres reply\n");
+					goto reset;
+				}
+
+				if (!PQconsumeInput(CON_CONNECTION(_con))) {
+					LM_WARN("error reading data from postgres server: %s\n",
+							PQerrorMessage(CON_CONNECTION(_con)));
+					goto reset;
+				}
+				if (!PQisBusy(CON_CONNECTION(_con)))
+					break;
+			}
+
+do_read:
 			/* Get the result of the query */
 			while ((res = PQgetResult(CON_CONNECTION(_con))) != NULL) {
 				db_postgres_free_query(_con);
@@ -239,6 +281,7 @@ static int db_postgres_submit_query(const db1_con_t* _con, const str* _s)
 				PQerrorMessage(CON_CONNECTION(_con)));
 		if(PQstatus(CON_CONNECTION(_con))!=CONNECTION_OK)
 		{
+reset:
 			LM_DBG("reseting the connection to postgress server\n");
 			PQreset(CON_CONNECTION(_con));
 		}
diff --git a/modules/db_postgres/km_pg_con.c b/modules/db_postgres/km_pg_con.c
index a8e0494..d053c55 100644
--- a/modules/db_postgres/km_pg_con.c
+++ b/modules/db_postgres/km_pg_con.c
@@ -26,12 +26,15 @@
  */
 
 #include "km_pg_con.h"
+#include "pg_mod.h"
 #include "../../mem/mem.h"
 #include "../../dprint.h"
 #include "../../ut.h"
 #include "../../tls_hooks_init.h" 
 #include <string.h>
 #include <time.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
 
 
 /*!
@@ -46,6 +49,9 @@ struct pg_con* db_postgres_new_connection(struct db_id* id)
 {
 	struct pg_con* ptr;
 	char *ports;
+	int i = 0;
+	const char *keywords[10], *values[10];
+	char to[16];
 
 	LM_DBG("db_id = %p\n", id);
  
@@ -67,6 +73,8 @@ struct pg_con* db_postgres_new_connection(struct db_id* id)
 
 	if (id->port) {
 		ports = int2str(id->port, 0);
+		keywords[i] = "port";
+		values[i++] = ports;
 		LM_DBG("opening connection: postgres://xxxx:xxxx@%s:%d/%s\n", ZSW(id->host),
 			id->port, ZSW(id->database));
 	} else {
@@ -75,11 +83,27 @@ struct pg_con* db_postgres_new_connection(struct db_id* id)
 			ZSW(id->database));
 	}
 
+	keywords[i] = "host";
+	values[i++] = id->host;
+	keywords[i] = "dbname";
+	values[i++] = id->database;
+	keywords[i] = "user";
+	values[i++] = id->username;
+	keywords[i] = "password";
+	values[i++] = id->password;
+	if (pg_timeout > 0) {
+		snprintf(to, sizeof(to)-1, "%d", pg_timeout + 3);
+		keywords[i] = "connect_timeout";
+		values[i++] = to;
+	}
+
+	keywords[i] = values[i] = NULL;
+
 	/* don't attempt to re-init openssl if done already */
 	if(tls_loaded()) PQinitSSL(0);
 
- 	ptr->con = PQsetdbLogin(id->host, ports, NULL, NULL, id->database, id->username, id->password);
-	LM_DBG("PQsetdbLogin(%p)\n", ptr->con);
+	ptr->con = PQconnectdbParams(keywords, values, 1);
+	LM_DBG("PQconnectdbParams(%p)\n", ptr->con);
 
 	if( (ptr->con == 0) || (PQstatus(ptr->con) != CONNECTION_OK) )
 	{
@@ -92,6 +116,14 @@ struct pg_con* db_postgres_new_connection(struct db_id* id)
 	ptr->timestamp = time(0);
 	ptr->id = id;
 
+#if defined(SO_KEEPALIVE) && defined(TCP_KEEPIDLE)
+	if (pg_keepalive) {
+		i = 1;
+		setsockopt(PQsocket(ptr->con), SOL_SOCKET, SO_KEEPALIVE, &i, sizeof(i));
+		setsockopt(PQsocket(ptr->con), IPPROTO_TCP, TCP_KEEPIDLE, &pg_keepalive, sizeof(pg_keepalive));
+	}
+#endif
+
 	return ptr;
 
  err:
diff --git a/modules/db_postgres/pg_cmd.c b/modules/db_postgres/pg_cmd.c
index db7ad66..7267cd3 100644
--- a/modules/db_postgres/pg_cmd.c
+++ b/modules/db_postgres/pg_cmd.c
@@ -180,10 +180,8 @@ static void free_pg_params(struct pg_params* params)
  */
 static int check_types(db_cmd_t* cmd) 
 { 
-	struct pg_cmd* pcmd; 
 	struct pg_con* pcon;
 	
-	pcmd = DB_GET_PAYLOAD(cmd);
 	/* FIXME: The function should take the connection as one of parameters */
 	pcon = DB_GET_PAYLOAD(cmd->ctx->con[db_payload_idx]);
 
@@ -369,11 +367,8 @@ int pg_cmd(db_cmd_t* cmd)
 
 int pg_getopt(db_cmd_t* cmd, char* optname, va_list ap)
 {
-	struct pg_cmd* pcmd;
 	long long* id;
 
-	pcmd = (struct pg_cmd*)DB_GET_PAYLOAD(cmd);
-
 	if (!strcasecmp("last_id", optname)) {
 		id = va_arg(ap, long long*);
 		if (id == NULL) {
@@ -393,9 +388,6 @@ int pg_getopt(db_cmd_t* cmd, char* optname, va_list ap)
 
 int pg_setopt(db_cmd_t* cmd, char* optname, va_list ap)
 {
-	struct pg_cmd* pcmd;
-
-	pcmd = (struct pg_cmd*)DB_GET_PAYLOAD(cmd);
 	return 1;
 }
 
diff --git a/modules/db_postgres/pg_con.c b/modules/db_postgres/pg_con.c
index 32b9be7..86c68fa 100644
--- a/modules/db_postgres/pg_con.c
+++ b/modules/db_postgres/pg_con.c
@@ -39,6 +39,7 @@
 #include "pg_con.h"
 #include "pg_uri.h"
 #include "pg_sql.h"
+#include "pg_mod.h"
 
 #include "../../mem/mem.h"
 #include "../../dprint.h"
@@ -47,6 +48,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <netinet/in.h>
+#include <netinet/tcp.h>
 #include <time.h>
 
 
@@ -237,7 +239,9 @@ int pg_con_connect(db_con_t* con)
 	struct pg_con* pcon;
 	struct pg_uri* puri;
 	char* port_str;
-	int ret;
+	int ret, i = 0;
+	const char *keywords[10], *values[10];
+	char to[16];
 	
 	pcon = DB_GET_PAYLOAD(con);
 	puri = DB_GET_PAYLOAD(con->uri);
@@ -251,6 +255,8 @@ int pg_con_connect(db_con_t* con)
 
 	if (puri->port > 0) {
 		port_str = int2str(puri->port, 0);
+		keywords[i] = "port";
+		values[i++] = port_str;
 	} else {
 		port_str = NULL;
 	}
@@ -260,12 +266,26 @@ int pg_con_connect(db_con_t* con)
 		pcon->con = NULL;
 	}
 
-	pcon->con = PQsetdbLogin(puri->host, port_str,
-							 NULL, NULL, puri->database,
-							 puri->username, puri->password);
+	keywords[i] = "host";
+	values[i++] = puri->host;
+	keywords[i] = "dbname";
+	values[i++] = puri->database;
+	keywords[i] = "user";
+	values[i++] = puri->username;
+	keywords[i] = "password";
+	values[i++] = puri->password;
+	if (pg_timeout > 0) {
+		snprintf(to, sizeof(to)-1, "%d", pg_timeout + 3);
+		keywords[i] = "connect_timeout";
+		values[i++] = to;
+	}
+
+	keywords[i] = values[i] = NULL;
+
+	pcon->con = PQconnectdbParams(keywords, values, 1);
 	
 	if (pcon->con == NULL) {
-		ERR("postgres: PQsetdbLogin ran out of memory\n");
+		ERR("postgres: PQconnectdbParams ran out of memory\n");
 		goto error;
 	}
 	
@@ -285,6 +305,14 @@ int pg_con_connect(db_con_t* con)
 	    PQprotocolVersion(pcon->con), 0 );
 #endif
 
+#if defined(SO_KEEPALIVE) && defined(TCP_KEEPIDLE)
+	if (pg_keepalive) {
+		i = 1;
+		setsockopt(PQsocket(pcon->con), SOL_SOCKET, SO_KEEPALIVE, &i, sizeof(i));
+		setsockopt(PQsocket(pcon->con), IPPROTO_TCP, TCP_KEEPIDLE, &pg_keepalive, sizeof(pg_keepalive));
+	}
+#endif
+
 	ret = timestamp_format(pcon->con);
 	if (ret == 1 || ret == -1) {
 		/* Assume INT8 representation if detection fails */
diff --git a/modules/db_postgres/pg_mod.c b/modules/db_postgres/pg_mod.c
index 1b2d9f7..14f50a3 100644
--- a/modules/db_postgres/pg_mod.c
+++ b/modules/db_postgres/pg_mod.c
@@ -61,6 +61,8 @@ int pg_retries = 2;  /* How many times should the module try re-execute failed c
 					  * 0 disables reconnecting */
 
 int pg_lockset = 4;
+int pg_timeout = 0; /* default = no timeout */
+int pg_keepalive = 0;
 
 /*
  * Postgres module interface
@@ -92,6 +94,8 @@ static cmd_export_t cmds[] = {
 static param_export_t params[] = {
 	{"retries",         PARAM_INT, &pg_retries },
 	{"lockset",         PARAM_INT, &pg_lockset },
+	{"timeout",         PARAM_INT, &pg_timeout },
+	{"tcp_keepalive",   PARAM_INT, &pg_keepalive },
 	{0, 0, 0}
 };
 
diff --git a/modules/db_postgres/pg_mod.h b/modules/db_postgres/pg_mod.h
index 10c0535..194c7df 100644
--- a/modules/db_postgres/pg_mod.h
+++ b/modules/db_postgres/pg_mod.h
@@ -41,6 +41,8 @@
  */
 
 extern int pg_retries;
+extern int pg_timeout;
+extern int pg_keepalive;
 
 /** @} */
 
diff --git a/modules/db_sqlite/Makefile b/modules/db_sqlite/Makefile
index 150e1d6..30c67fe 100644
--- a/modules/db_sqlite/Makefile
+++ b/modules/db_sqlite/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # WARNING: do not run this directly, it should be run by the master Makefile
 
diff --git a/modules/db_text/Makefile b/modules/db_text/Makefile
index eb0a08c..909276f 100644
--- a/modules/db_text/Makefile
+++ b/modules/db_text/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # example module makefile
 #
diff --git a/modules/db_text/README b/modules/db_text/README
index 530170f..df3e46b 100644
--- a/modules/db_text/README
+++ b/modules/db_text/README
@@ -16,6 +16,12 @@ Daniel-Constantin Mierla
 
    <miconda at gmail.com>
 
+Edited by
+
+Olle E. Johansson
+
+   <oej at edvina.net>
+
    Copyright � 2003, 2004 FhG FOKUS
      __________________________________________________________________
 
@@ -37,6 +43,7 @@ Daniel-Constantin Mierla
         3. Parameters
 
               3.1. db_mode (integer)
+              3.2. emptystring (integer)
 
         4. Exported RPC Functions
 
@@ -54,11 +61,12 @@ Daniel-Constantin Mierla
    1.2. Minimal Kamailio location dbtext table definition
    1.3. Minimal Kamailio subscriber dbtext table example
    1.4. Set db_mode parameter
-   1.5. Load the dbtext module
-   1.6. Definition of 'subscriber' table (one line)
-   1.7. Definition of 'location' and 'aliases' tables (one line)
-   1.8. Definition of 'version' table and sample records
-   1.9. Configuration file
+   1.5. Set emptystring parameter
+   1.6. Load the dbtext module
+   1.7. Definition of 'subscriber' table (one line)
+   1.8. Definition of 'location' and 'aliases' tables (one line)
+   1.9. Definition of 'version' table and sample records
+   1.10. Configuration file
 
 Chapter 1. Admin Guide
 
@@ -78,6 +86,7 @@ Chapter 1. Admin Guide
    3. Parameters
 
         3.1. db_mode (integer)
+        3.2. emptystring (integer)
 
    4. Exported RPC Functions
 
@@ -111,7 +120,8 @@ Chapter 1. Admin Guide
    NOTE: even when db_text is in non-caching mode, the module does not
    write back to hard drive after changes. In this mode, the module checks
    if the corresponding file on disk has changed, and reloads it. The
-   write to disk happens at Kamailio shut down.
+   write to disk happens at Kamailio shut down. If db_text is in caching
+   mode, many "reload" functions in various modules will not work.
 
 1.1. Design of dbtext engine
 
@@ -150,7 +160,8 @@ Chapter 1. Admin Guide
      * each other line is a row with data. The line ends with "\n".
      * the fields are separated by ":".
      * no value between two ':' (or between ':' and start/end of a row)
-       means "null" value.
+       means "null" value. If the parameter "emptystring" is enabled,
+       db_text sets a NULL string to an empty string value.
      * next characters must be escaped in strings: "\n", "\r", "\t", ":".
      * 0 -- the zero value must be escaped too.
 
@@ -199,8 +210,7 @@ suser:supasswd:xxx:alpha.org:xxx
 3. Parameters
 
    3.1. db_mode (integer)
-
-   None.
+   3.2. emptystring (integer)
 
 3.1. db_mode (integer)
 
@@ -216,11 +226,25 @@ suser:supasswd:xxx:alpha.org:xxx
 modparam("db_text", "db_mode", 1)
 ...
 
+3.2. emptystring (integer)
+
+   db_text by default handles an empty string as a NULL value. Some
+   modules, like the dialplan module, does not accept NULL strings. If you
+   enable emptystring an empty string will not be NULL, but an empty
+   string.
+
+   Default value is "0" (off).
+
+   Example 1.5. Set emptystring parameter
+...
+modparam("db_text", "emptystring", 1)
+...
+
 4. Exported RPC Functions
 
    4.1. db_text.dump
 
-4.1.  db_text.dump
+4.1. db_text.dump
 
    Write back to hard drive all modified tables.
 
@@ -244,7 +268,7 @@ modparam("db_text", "db_mode", 1)
    database path. So, either you provide an absolute path to database
    directory or a relative one to "CFG_DIR" directory.
 
-   Example 1.5. Load the dbtext module
+   Example 1.6. Load the dbtext module
 ...
 loadmodule "/path/to/kamailio/modules_k/db_text.so"
 ...
@@ -263,7 +287,7 @@ modparam("module_name", "db_url", "text:///path/to/dbtext/database")
    in order to have authentication. To use with the given configuration
    file, the table files must be placed in the '/tmp/serdb' directory.
 
-   Example 1.6. Definition of 'subscriber' table (one line)
+   Example 1.7. Definition of 'subscriber' table (one line)
 ...
 username(str) domain(str) password(str) first_name(str) last_name(str) phone(str
 ) email_address(str) datetime_created(int) datetime_modified(int) confirmation(s
@@ -271,14 +295,14 @@ tr) flag(str) sendnotification(str) greeting(str) ha1(str) ha1b(str) perms(str)
 allow_find(str) timezone(str,null) rpid(str,null)
 ...
 
-   Example 1.7. Definition of 'location' and 'aliases' tables (one line)
+   Example 1.8. Definition of 'location' and 'aliases' tables (one line)
 ...
 username(str) domain(str,null) contact(str,null) received(str) expires(int,null)
  q(double,null) callid(str,null) cseq(int,null) last_modified(str) flags(int) us
 er_agent(str) socket(str)
 ...
 
-   Example 1.8. Definition of 'version' table and sample records
+   Example 1.9. Definition of 'version' table and sample records
 ...
 table_name(str) table_version(int)
 subscriber:3
@@ -286,7 +310,7 @@ location:6
 aliases:6
 ...
 
-   Example 1.9. Configuration file
+   Example 1.10. Configuration file
 ...
 #
 # $Id$
diff --git a/modules/db_text/dbt_api.c b/modules/db_text/dbt_api.c
index 8dff6f7..f81012b 100644
--- a/modules/db_text/dbt_api.c
+++ b/modules/db_text/dbt_api.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * DBText library
  *
  * Copyright (C) 2001-2003 FhG Fokus
@@ -21,9 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2003-02-05  created by Daniel
  * 
  */
 
@@ -59,7 +54,7 @@ static int dbt_get_columns(db1_res_t* _r, dbt_result_p _dres)
 		return -2;
 	}
 	if (db_allocate_columns(_r, RES_COL_N(_r)) != 0) {
-		LM_ERR("could not allocate columns");
+		LM_ERR("could not allocate columns\n");
 		return -3;
 	}
 
@@ -75,7 +70,7 @@ static int dbt_get_columns(db1_res_t* _r, dbt_result_p _dres)
 			db_free_columns(_r);
 			return -4;
 		}
-		LM_DBG("allocate %d bytes for RES_NAMES[%d] at %p",
+		LM_DBG("allocate %d bytes for RES_NAMES[%d] at %p\n",
 				(int)sizeof(str), col,
 				RES_NAMES(_r)[col]);
 		RES_NAMES(_r)[col]->s = _dres->colv[col].name.s;
@@ -114,7 +109,7 @@ static int dbt_convert_row(db1_res_t* _res, db_row_t* _r, dbt_row_p _r1)
 	}
 
 	if (db_allocate_row(_res, _r) != 0) {
-		LM_ERR("could not allocate row");
+		LM_ERR("could not allocate row\n");
 		return -2;
 	}
 
@@ -129,7 +124,7 @@ static int dbt_convert_row(db1_res_t* _res, db_row_t* _r, dbt_row_p _r1)
 			break;
 
 			case DB1_BIGINT:
-				LM_ERR("BIGINT not supported");
+				LM_ERR("BIGINT not supported\n");
 				return -1;
 
 			case DB1_DOUBLE:
@@ -178,7 +173,7 @@ static int dbt_convert_row(db1_res_t* _res, db_row_t* _r, dbt_row_p _r1)
 			break;
 
 			default:
-				LM_ERR("val type [%d] not supported", RES_TYPES(_res)[i]);
+				LM_ERR("val type [%d] not supported\n", RES_TYPES(_res)[i]);
 				return -1;
 		}
 	}
@@ -202,7 +197,7 @@ static int dbt_convert_rows(db1_res_t* _r, dbt_result_p _dres)
 		return 0;
 	}
 	if (db_allocate_rows(_r) < 0) {
-		LM_ERR("could not allocate rows");
+		LM_ERR("could not allocate rows\n");
 		return -2;
 	}
 	row = 0;
diff --git a/modules/db_text/dbt_api.h b/modules/db_text/dbt_api.h
index cb63ef8..381a718 100644
--- a/modules/db_text/dbt_api.h
+++ b/modules/db_text/dbt_api.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * DBText library
  *
  * Copyright (C) 2001-2003 FhG Fokus
@@ -21,10 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  * 
- * History:
- * --------
- * 2003-02-05  created by Daniel
- * 
  */
 
 
diff --git a/modules/db_text/dbt_base.c b/modules/db_text/dbt_base.c
index 4454574..7ca4563 100644
--- a/modules/db_text/dbt_base.c
+++ b/modules/db_text/dbt_base.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * DBText module core functions
  *
  * Copyright (C) 2001-2003 FhG Fokus
@@ -21,11 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  * 
- * History:
- * --------
- * 2009-03-01 added support for ORDER-BY clause by Edgar Holleis
- * 2003-01-30 created by Daniel
- * 
  */
 
 #include <string.h>
@@ -96,7 +89,7 @@ db1_con_t* dbt_init(const str* _sqlurl)
 	memset(_res, 0, sizeof(db1_con_t) + sizeof(dbt_con_t));
 	_res->tail = (unsigned long)((char*)_res+sizeof(db1_con_t));
 
-	LM_INFO("using database at: %.*s", _s.len, _s.s);
+	LM_INFO("using database at: %.*s\n", _s.len, _s.s);
 	DBT_CON_CONNECTION(_res) = dbt_cache_get_db(&_s);
 	if (!DBT_CON_CONNECTION(_res))
 	{
@@ -327,12 +320,17 @@ clean:
 }
 
 /*
- * Raw SQL query -- is not the case to have this method
+ * Affected Rows
  */
-int dbt_raw_query(db1_con_t* _h, char* _s, db1_res_t** _r)
+int dbt_affected_rows(db1_con_t* _h)
 {
-	*_r = NULL;
-    return -1;
+	if (!_h || !CON_TABLE(_h))
+	{
+		LM_ERR("invalid parameter\n");
+		return -1;
+	}
+
+	return ((dbt_con_p)_h->tail)->affected;
 }
 
 /*
@@ -350,6 +348,9 @@ int dbt_insert(db1_con_t* _h, db_key_t* _k, db_val_t* _v, int _n)
 		LM_ERR("invalid parameter\n");
 		return -1;
 	}
+
+	((dbt_con_p)_h->tail)->affected = 0;
+    
 	if(!_k || !_v || _n<=0)
 	{
 		LM_ERR("no key-value to insert\n");
@@ -407,6 +408,8 @@ int dbt_insert(db1_con_t* _h, db_key_t* _k, db_val_t* _v, int _n)
 		goto clean;
 	}
 
+	((dbt_con_p)_h->tail)->affected = 1;
+    
 	/* dbt_print_table(_tbc, NULL); */
 	
 	/* unlock databse */
@@ -452,6 +455,8 @@ int dbt_delete(db1_con_t* _h, db_key_t* _k, db_op_t* _o, db_val_t* _v, int _n)
 		return -1;
 	}
 
+	((dbt_con_p)_h->tail)->affected = 0;
+
 	/* lock database */
 	_tbc = dbt_db_get_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h));
 	if(!_tbc)
@@ -464,6 +469,7 @@ int dbt_delete(db1_con_t* _h, db_key_t* _k, db_op_t* _o, db_val_t* _v, int _n)
 	if(!_k || !_v || _n<=0)
 	{
 		LM_DBG("deleting all records\n");
+		((dbt_con_p)_h->tail)->affected = _tbc->nrrows;
 		dbt_table_free_rows(_tbc);
 		/* unlock databse */
 		dbt_release_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h));
@@ -490,6 +496,9 @@ int dbt_delete(db1_con_t* _h, db_key_t* _k, db_op_t* _o, db_val_t* _v, int _n)
 			_tbc->nrrows--;
 			// free row
 			dbt_row_free(_tbc, _drp);
+
+			((dbt_con_p)_h->tail)->affected++;
+
 		}
 		_drp = _drp0;
 	}
@@ -530,7 +539,9 @@ int dbt_update(db1_con_t* _h, db_key_t* _k, db_op_t* _o, db_val_t* _v,
 		LM_ERR("invalid parameters\n");
 		return -1;
 	}
-	
+
+	((dbt_con_p)_h->tail)->affected = 0;
+    
 	/* lock database */
 	_tbc = dbt_db_get_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h));
 	if(!_tbc)
@@ -569,6 +580,9 @@ int dbt_update(db1_con_t* _h, db_key_t* _k, db_op_t* _o, db_val_t* _v,
 					goto error;
 				}
 			}
+
+			((dbt_con_p)_h->tail)->affected++;
+
 		}
 		_drp = _drp->next;
 	}
diff --git a/modules/db_text/dbt_file.c b/modules/db_text/dbt_file.c
index 62fa82f..5d9ca84 100644
--- a/modules/db_text/dbt_file.c
+++ b/modules/db_text/dbt_file.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * DBText library
  *
  * Copyright (C) 2001-2003 FhG Fokus
@@ -21,10 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  * 
- * History:
- * --------
- * 2003-02-03 created by Daniel
- * 
  */
 
 #include <stdio.h>
@@ -232,7 +226,7 @@ dbt_table_p dbt_load_file(const str *tbn, const str *dbn)
 						c = fgetc(fin);
 					if(c=='N' || c=='n')
 					{
-						//LM_DBG("NULL flag set!\n");
+						LM_DBG("column[%d] NULL flag set!\n", ccol+1);
 						colp->flag |= DBT_FLAG_NULL;
 					}
 					else if(colp->type==DB1_INT && dtp->auto_col<0
@@ -408,10 +402,16 @@ dbt_table_p dbt_load_file(const str *tbn, const str *dbn)
 						
 						bp = 0;
 						if(c==DBT_DELIM || 
-								(ccol == dtp->nrcols-1
-								 && (c == DBT_DELIM_R || c==EOF)))
-							dtval.nul = 1;
-						else
+							(ccol == dtp->nrcols-1
+							 && (c == DBT_DELIM_R || c==EOF))) {
+							/* If empty_string is enabled, we'll just return
+							 * an empty string and avoid NULL
+							 */
+							if (empty_string == 0) {
+								/* Default - NULL */
+								dtval.nul = 1;
+							}
+						} else
 						{
 							dtval.nul = 0;
 							while(c!=DBT_DELIM && c!=DBT_DELIM_R && c!=EOF)
diff --git a/modules/db_text/dbt_lib.c b/modules/db_text/dbt_lib.c
index c4aee80..32364a0 100644
--- a/modules/db_text/dbt_lib.c
+++ b/modules/db_text/dbt_lib.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * DBText library
  *
  * Copyright (C) 2001-2003 FhG Fokus
@@ -21,10 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  * 
- * History:
- * --------
- * 2003-01-30 created by Daniel
- * 
  */
 
 #include <stdio.h>
@@ -264,7 +258,7 @@ dbt_table_p dbt_db_get_table(dbt_cache_p _dc, const str *_s)
 	int hashidx;
 
 	if(!_dbt_cachetbl || !_dc || !_s || !_s->s || _s->len<=0) {
-		LM_ERR("invalid parameter");
+		LM_ERR("invalid parameter\n");
 		return NULL;
 	}
 
@@ -304,7 +298,7 @@ dbt_table_p dbt_db_get_table(dbt_cache_p _dc, const str *_s)
 
 	if(!_tbc)
 	{
-		LM_ERR("could not load database from file [%.*s]", _s->len, _s->s);
+		LM_ERR("could not load database from file [%.*s]\n", _s->len, _s->s);
 		lock_release(&_dbt_cachetbl[hashidx].sem);
 		return NULL;
 	}
@@ -438,7 +432,7 @@ int dbt_is_neq_type(db_type_t _t0, db_type_t _t1)
 				return 0;
 
 		case DB1_BIGINT:
-			LM_ERR("BIGINT not supported");
+			LM_ERR("BIGINT not supported\n");
 			return 0;
 
 		case DB1_DATETIME:
diff --git a/modules/db_text/dbt_lib.h b/modules/db_text/dbt_lib.h
index 4f8c203..2505a58 100644
--- a/modules/db_text/dbt_lib.h
+++ b/modules/db_text/dbt_lib.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * DBText library
  *
  * Copyright (C) 2001-2003 FhG Fokus
@@ -21,10 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  * 
- * History:
- * --------
- * 2003-01-30 created by Daniel
- * 
  */
 
 
@@ -54,6 +48,7 @@
  *  * Module parameters variables
  *   */
 extern int db_mode; /* Database usage mode: 0 = no cache, 1 = cache */
+extern int empty_string; /* If TRUE, an empty string is an empty string, otherwise NULL */
 
 typedef db_val_t dbt_val_t, *dbt_val_p;
 
diff --git a/modules/db_text/dbt_raw_query.c b/modules/db_text/dbt_raw_query.c
new file mode 100644
index 0000000..ad13600
--- /dev/null
+++ b/modules/db_text/dbt_raw_query.c
@@ -0,0 +1,201 @@
+/*
+ * DBText module core functions
+ *
+ * Copyright (C) 2001-2003 FhG Fokus
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#define _GNU_SOURCE
+#include <string.h>
+
+#include "../../str.h"
+#include "../../mem/mem.h"
+#include "../../mem/shm_mem.h"
+ 
+#include "dbtext.h"
+#include "dbt_res.h"
+#include "dbt_api.h"
+#include "dbt_raw_util.h"
+
+
+int dbt_raw_query_select(db1_con_t* _h, str* _s, db1_res_t** _r)
+{
+    int res = -1;
+    int i, len;
+    char* table_ptr = NULL;
+    char* fields_end_ptr = NULL;
+    char* fields_ptr = NULL;
+    char* where_ptr = NULL;
+    char** tokens = NULL;
+    str table;
+    dbt_table_p _tbc = NULL;
+	int cols;
+	int n = 0;
+	int ncols = 0;
+	int nc = 0;
+	db_key_t *result_cols = NULL;
+	db_key_t* _k = NULL;
+	db_op_t* _op = NULL;
+	db_val_t* _v = NULL;
+
+    fields_end_ptr = strcasestr(_s->s, " from ");
+    if(fields_end_ptr == NULL)
+    	return res;
+
+    len = fields_end_ptr - (_s->s + 6) + 1;
+    fields_ptr = pkg_malloc(len);
+    strncpy(fields_ptr, _s->s + 6, len);
+    fields_ptr[len] = '\0';
+    fields_ptr = dbt_trim(fields_ptr);
+
+
+
+    where_ptr = strcasestr(_s->s, " where ");
+    if(where_ptr == NULL) {
+    	len = strlen(fields_end_ptr + 6);
+    } else {
+    	len = where_ptr - (fields_end_ptr + 6);
+    	nc = dbt_build_where(where_ptr + 7, &_k, &_op, &_v);
+    }
+
+    table_ptr = pkg_malloc(len);
+    strncpy(table_ptr, fields_end_ptr + 6, len);
+    table_ptr[len] = '\0';
+    dbt_trim(table_ptr);
+
+    table.s = table_ptr;
+    table.len = len;
+
+	if(dbt_use_table(_h, &table) != 0) {
+		LM_ERR("use table is invalid %.*s\n", table.len, table.s);
+		goto error;
+	}
+
+	_tbc = dbt_db_get_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h));
+	if(!_tbc)
+	{
+		LM_ERR("table %.*s does not exist!\n", CON_TABLE(_h)->len, CON_TABLE(_h)->s);
+		goto error;
+	}
+
+    tokens = dbt_str_split(fields_ptr, ',', &ncols);
+    pkg_free(fields_ptr);
+    fields_ptr = NULL;
+    if (!tokens) {
+		LM_ERR("error extracting tokens\n");
+    	goto error;
+    }
+
+    if(ncols == 1 && strncmp(*tokens, "*", 1) == 0) {
+    	cols = _tbc->nrcols;
+    	result_cols = pkg_malloc(sizeof(db_key_t) * cols);
+    	memset(result_cols, 0, sizeof(db_key_t) * cols);
+    	for(n=0; n < cols; n++) {
+    		result_cols[n] = &_tbc->colv[n]->name;
+    	}
+    } else {
+    	cols = ncols;
+    	result_cols = pkg_malloc(sizeof(db_key_t) * cols);
+    	memset(result_cols, 0, sizeof(db_key_t) * cols);
+    	for(n=0; *(tokens + n); n++) {
+    		result_cols[n]->s = *(tokens + n);
+    		result_cols[n]->len = strlen(*(tokens + n));
+    	}
+    }
+
+
+	dbt_release_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h));
+
+	res = dbt_query(_h, _k, _op, _v, result_cols, nc, cols, NULL, _r);
+
+error:
+	if(tokens) {
+	    for (i = 0; *(tokens + i); i++) {
+	    	pkg_free(*(tokens + i));
+	    }
+	    pkg_free(tokens);
+	}
+    if(fields_ptr)
+    	pkg_free(fields_ptr);
+
+    if(table_ptr)
+    	pkg_free(table_ptr);
+
+    dbt_clean_where(nc, _k, _op, _v);
+
+    if(result_cols) {
+    	pkg_free(result_cols);
+    }
+
+ 	return res;
+}
+
+int dbt_raw_query_update(db1_con_t* _h, str* _s, db1_res_t** _r)
+{
+    int res = -1;
+
+
+
+ 	return res;
+}
+
+int dbt_raw_query_delete(db1_con_t* _h, str* _s, db1_res_t** _r)
+{
+    int res = -1;
+
+
+
+ 	return res;
+}
+
+/*
+ * Raw SQL query -- is not the case to have this method
+ */
+int dbt_raw_query(db1_con_t* _h, str* _s, db1_res_t** _r)
+{
+	*_r = NULL;
+    int res = -1;
+
+	if(!_h) {
+		LM_ERR("invalid connection\n");
+		return res;
+	}
+
+	if(!_s) {
+		LM_ERR("sql query is null\n");
+		return res;
+	}
+
+	if(_s->s == NULL) {
+		LM_ERR("sql query is null\n");
+    	return res;
+	}
+
+    dbt_trim(_s->s);
+    _s->len = strlen(_s->s);
+
+    if(strncasecmp(_s->s, "select", 6) == 0) {
+    	return dbt_raw_query_select(_h, _s, _r);
+    } else if(strncasecmp(_s->s, "update", 6) == 0) {
+    	return dbt_raw_query_update(_h, _s, _r);
+    } else if(strncasecmp(_s->s, "delete", 6) == 0) {
+    	return dbt_raw_query_delete(_h, _s, _r);
+    };
+
+    return res;
+}
diff --git a/modules/db_text/dbt_raw_query.h b/modules/db_text/dbt_raw_query.h
new file mode 100644
index 0000000..68103da
--- /dev/null
+++ b/modules/db_text/dbt_raw_query.h
@@ -0,0 +1,37 @@
+/*
+ * DBText library
+ *
+ * Copyright (C) 2001-2003 FhG Fokus
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ */
+
+
+#ifndef _DBT_RAW_QUERY_H_
+#define _DBT_RAW_QUERY_H_
+
+#include "../../str.h"
+
+
+
+int dbt_raw_query_select(db1_con_t* _h, str* _s, db1_res_t** _r);
+int dbt_raw_query_update(db1_con_t* _h, str* _s, db1_res_t** _r);
+int dbt_raw_query_delete(db1_con_t* _h, str* _s, db1_res_t** _r);
+
+#endif
+
diff --git a/modules/db_text/dbt_raw_util.c b/modules/db_text/dbt_raw_util.c
new file mode 100644
index 0000000..a35bacb
--- /dev/null
+++ b/modules/db_text/dbt_raw_util.c
@@ -0,0 +1,253 @@
+/*
+ * DBText library
+ *
+ * Copyright (C) 2001-2003 FhG Fokus
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ */
+
+#include <sys/types.h>
+#include <string.h>
+#include <regex.h>
+#include <ctype.h>
+
+#include "../../mem/mem.h"
+
+#include "dbt_raw_util.h"
+
+static const char* _regexp = "\\s*(and|or)?\\s*(\\w*)\\s*(>=|<=|<>|=|>|<)\\s*(')?([a-zA-Z0-9_-]*)(')?";
+
+char** dbt_str_split(char* a_str, const char a_delim, int* c)
+{
+    char** result    = 0;
+    size_t count     = 0;
+    char* tmp        = a_str;
+    char* last_comma = 0;
+    char delim[2];
+    delim[0] = a_delim;
+    delim[1] = 0;
+    int len = 0;
+
+    /* Count how many elements will be extracted. */
+    while (*tmp)
+    {
+        if (a_delim == *tmp)
+        {
+            count++;
+            last_comma = tmp;
+        }
+        tmp++;
+    }
+
+    /* Add space for trailing token. */
+    count += last_comma < (a_str + strlen(a_str) - 1);
+
+    *c = count;
+
+    /* Add space for terminating null string so caller
+       knows where the list of returned strings ends. */
+    count++;
+
+    result = pkg_malloc(sizeof(char*) * count);
+
+    if (result)
+    {
+        size_t idx  = 0;
+        char* token = strtok(a_str, delim);
+
+        while (token)
+        {
+            assert(idx < count);
+            len = strlen(token);
+            char* ptr = pkg_malloc( (len+1) * sizeof(char));
+        	memcpy(ptr, token, len);
+        	ptr[len] = '\0';
+            *(result + idx) = dbt_trim(ptr);
+            token = strtok(0, delim);
+            idx++;
+        }
+        assert(idx == count - 1);
+        *(result + idx) = 0;
+    }
+
+    return result;
+}
+
+
+char* dbt_trim(char *str)
+{
+    size_t len = 0;
+    char *frontp = str;
+    char *endp = NULL;
+
+    if( str == NULL ) { return NULL; }
+    if( str[0] == '\0' ) { return str; }
+
+    len = strlen(str);
+    endp = str + len;
+
+    /* Move the front and back pointers to address the first non-whitespace
+     * characters from each end.
+     */
+    while( isspace(*frontp) ) { ++frontp; }
+    if( endp != frontp )
+    {
+        while( isspace(*(--endp)) && endp != frontp ) {}
+    }
+
+    if( str + len - 1 != endp )
+            *(endp + 1) = '\0';
+    else if( frontp != str &&  endp == frontp )
+            *str = '\0';
+
+    /* Shift the string so that it starts at str so that if it's dynamically
+     * allocated, we can still free it on the returned pointer.  Note the reuse
+     * of endp to mean the front of the string buffer now.
+     */
+    endp = str;
+    if( frontp != str )
+    {
+            while( *frontp ) { *endp++ = *frontp++; }
+            *endp = '\0';
+    }
+
+
+    return str;
+}
+
+
+#define MAX_MATCH 7
+#define MAX_CLAUSES 12
+
+void dbt_clean_where(int n, db_key_t* _k, db_op_t* _op, db_val_t* _v)
+{
+	int i;
+	if(_k) {
+		for(i=0; i < n; i++) {
+			pkg_free(_k[i]->s);
+		}
+		pkg_free(_k);
+	}
+
+	if(_op) {
+		for(i=0; i < n; i++) {
+			pkg_free((char*)_op[i]);
+		}
+		pkg_free(_op);
+	}
+
+	if(_v) {
+		for(i=0; i < n; i++) {
+			if(_v[i].type == DB1_STR)
+			pkg_free(_v[i].val.str_val.s);
+		}
+		pkg_free(_v);
+	}
+}
+
+int dbt_build_where(char* where, db_key_t** _k, db_op_t** _o, db_val_t** _v)
+{
+	db_key_t* _k1 = NULL;
+	char** _o1 = NULL;
+	db_val_t* _v1 = NULL;
+	regmatch_t* matches = NULL;
+	int l;
+	int len;
+	regex_t preg;
+	int offset = 0;
+	int idx = -1;
+
+	*_k = NULL;
+	*_o = NULL;
+	*_v = NULL;
+
+	len = strlen(where);
+
+	if (regcomp(&preg, _regexp, REG_EXTENDED | REG_NEWLINE)) {
+		LM_ERR("error compiling regexp\n");
+		return -1;
+	}
+
+	_k1 = pkg_malloc(sizeof(db_key_t) * MAX_CLAUSES);
+	memset(_k1, 0, sizeof(db_key_t) * MAX_CLAUSES);
+	_o1 = pkg_malloc(sizeof(char*) * MAX_CLAUSES);
+	memset(_o1, 0, sizeof(db_op_t) * MAX_CLAUSES);
+	_v1 = pkg_malloc(sizeof(db_val_t) * MAX_CLAUSES);
+	memset(_v1, 0, sizeof(db_val_t) * MAX_CLAUSES);
+
+	matches = (regmatch_t*)pkg_malloc(sizeof(regmatch_t) * MAX_MATCH);
+	if(matches==NULL) {
+		LM_ERR("error getting pkg memory\n");
+		return -1;
+	}
+
+	while(offset < len) {
+		char* buffer = where + offset;
+
+		if (regexec(&preg, buffer, MAX_MATCH, matches, REG_ICASE)) {
+			LM_ERR("error running regexp\n");
+			break;
+		}
+		if(matches[0].rm_so == -1) {
+			break;
+		}
+		idx++;
+
+		// TODO figure out a way to combine and / or
+		//      needs changes in dbt_query / dbt_row_match
+
+		l = matches[2].rm_eo - matches[2].rm_so;
+		_k1[idx] = pkg_malloc(sizeof(str)+l+1);
+		_k1[idx]->len = l;
+		_k1[idx]->s = (char*) (_k1[idx]+sizeof(str));
+		strncpy(_k1[idx]->s, buffer+matches[2].rm_so, l);
+		_k1[idx]->s[l]='\0';
+
+		l = matches[3].rm_eo - matches[3].rm_so;
+		_o1[idx] = (char*) pkg_malloc(l+1);
+		strncpy(_o1[idx], buffer+matches[3].rm_so, l);
+		_o1[idx][l]='\0';
+
+		l = matches[5].rm_eo - matches[5].rm_so;
+		if(matches[4].rm_so == -1) {
+			_v1[idx].type = DB1_INT;
+			_v1[idx].val.int_val = 0;
+		} else {
+			_v1[idx].type = DB1_STR;
+			_v1[idx].val.str_val.len = l;
+			_v1[idx].val.str_val.s = pkg_malloc(l+1);
+			strncpy(_v1[idx].val.str_val.s, buffer+matches[5].rm_so, l);
+		}
+/*		int n;
+		for(n=0; n < MAX_MATCH; n++) {
+			LM_ERR("MATCH RESULT %d - %d,%d\n", n, matches[n].rm_so, matches[n].rm_eo);
+		}
+*/
+		if(matches[0].rm_eo != -1)
+			offset += matches[0].rm_eo;
+
+	}
+	regfree(&preg);
+	pkg_free(matches);
+
+	*_k = _k1;
+	*_o = (db_op_t*)_o1;
+	*_v = _v1;
+
+	return idx+1;
+}
diff --git a/modules/db_text/dbt_raw_util.h b/modules/db_text/dbt_raw_util.h
new file mode 100644
index 0000000..7c7f575
--- /dev/null
+++ b/modules/db_text/dbt_raw_util.h
@@ -0,0 +1,40 @@
+/*
+ * DBText library
+ *
+ * Copyright (C) 2001-2003 FhG Fokus
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ */
+
+
+#ifndef _DBT_RAW_UTIL_H_
+#define _DBT_RAW_UTIL_H_
+
+#include "../../str.h"
+#include "../../lib/srdb1/db_key.h"
+#include "../../lib/srdb1/db_op.h"
+#include "../../lib/srdb1/db_val.h"
+
+
+char** dbt_str_split(char* a_str, const char a_delim, int* c);
+char* dbt_trim(char *str);
+int dbt_build_where(char* where, db_key_t** _k, db_op_t** _op, db_val_t** _v);
+void dbt_clean_where(int n, db_key_t* _k, db_op_t* _op, db_val_t* _v);
+
+#endif
+
diff --git a/modules/db_text/dbt_res.c b/modules/db_text/dbt_res.c
index 5eb75e8..268879b 100644
--- a/modules/db_text/dbt_res.c
+++ b/modules/db_text/dbt_res.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * DBText module core functions
  *
  * Copyright (C) 2001-2003 FhG Fokus
@@ -21,14 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2009-03-01 added support for ORDER-BY clause by Edgar Holleis
- * 2003-06-05 fixed bug: when comparing two values and the first was less than
- *           the second one, the result of 'dbt_row_match' was always true,
- *           thanks to Gabriel, (Daniel)
- * 2003-02-04 created by Daniel
- * 
  */
 
 #include <stdio.h>
@@ -461,7 +451,7 @@ int dbt_cmp_val(dbt_val_p _vp, db_val_t* _v)
 					(_vp->val.int_val>_v->val.int_val)?1:0;
 
 		case DB1_BIGINT:
-			LM_ERR("BIGINT not supported");
+			LM_ERR("BIGINT not supported\n");
 			return -1;
 
 		case DB1_DOUBLE:
diff --git a/modules/db_text/dbt_res.h b/modules/db_text/dbt_res.h
index a143097..7ad26ad 100644
--- a/modules/db_text/dbt_res.h
+++ b/modules/db_text/dbt_res.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * DBText module core functions
  *
  * Copyright (C) 2001-2003 FhG Fokus
@@ -21,10 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  * 
- * History:
- * --------
- * 2003-02-04 created by Daniel
- * 
  */
 
 
@@ -47,6 +41,7 @@ typedef struct _dbt_result
 typedef struct _dbt_con
 {
 	dbt_cache_p con;
+	int affected;
 } dbt_con_t, *dbt_con_p;
 
 #define DBT_CON_CONNECTION(db_con) (((dbt_con_p)((db_con)->tail))->con)
diff --git a/modules/db_text/dbt_tb.c b/modules/db_text/dbt_tb.c
index 02f2aa6..b0d6c49 100644
--- a/modules/db_text/dbt_tb.c
+++ b/modules/db_text/dbt_tb.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * DBText library
  *
  * Copyright (C) 2001-2003 FhG Fokus
@@ -21,10 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  * 
- * History:
- * --------
- * 2003-02-03 created by Daniel
- * 
  */
 
 #include <stdio.h>
diff --git a/modules/db_text/dbt_util.c b/modules/db_text/dbt_util.c
index 919b4e0..2d96b66 100644
--- a/modules/db_text/dbt_util.c
+++ b/modules/db_text/dbt_util.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * DBText library
  *
  * Copyright (C) 2001-2003 FhG Fokus
@@ -21,10 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  * 
- * History:
- * -------
- * 2003-01-30 created by Daniel
- * 
  */
 
 #include <string.h>
diff --git a/modules/db_text/dbt_util.h b/modules/db_text/dbt_util.h
index 9f19c4d..483987e 100644
--- a/modules/db_text/dbt_util.h
+++ b/modules/db_text/dbt_util.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * DBText library
  *
  * Copyright (C) 2001-2003 FhG Fokus
@@ -21,10 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2003-01-30 created by Daniel
- * 
  */
 
 
diff --git a/modules/db_text/dbtext.c b/modules/db_text/dbtext.c
index abdb0da..4f1d4a6 100644
--- a/modules/db_text/dbtext.c
+++ b/modules/db_text/dbtext.c
@@ -1,9 +1,8 @@
 /*
- * $Id$
- *
  * DBText module interface
  *
  * Copyright (C) 2001-2003 FhG Fokus
+ * Copyright (C) 2014 Edvina AB, Olle E. Johansson
  *
  * This file is part of Kamailio, a free SIP server.
  *
@@ -21,12 +20,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  * 
- * History:
- * --------
- * 2003-01-30 created by Daniel
- * 2003-03-11 New module interface (janakj)
- * 2003-03-16 flags export parameter added (janakj)
- * 
  */
 
 #include <stdio.h>
@@ -48,6 +41,7 @@ static void destroy(void);
  * Module parameter variables
  */
 int db_mode = 0;  /* Database usage mode: 0 = cache, 1 = no cache */
+int empty_string = 0;  /* Treat empty string as "" = 0, 1 = NULL */
 
 int dbt_bind_api(db_func_t *dbb);
 
@@ -65,6 +59,7 @@ static cmd_export_t cmds[] = {
  */
 static param_export_t params[] = {
 	{"db_mode", INT_PARAM, &db_mode},
+	{"emptystring", INT_PARAM, &empty_string},
 	{0, 0, 0}
 };
 
@@ -130,6 +125,9 @@ int dbt_bind_api(db_func_t *dbb)
 	dbb->insert      = (db_insert_f)dbt_insert;
 	dbb->delete      = (db_delete_f)dbt_delete; 
 	dbb->update      = (db_update_f)dbt_update;
+	dbb->affected_rows = (db_affected_rows_f) dbt_affected_rows;
+	dbb->raw_query   = (db_raw_query_f) dbt_raw_query;
+	dbb->cap         = DB_CAP_ALL | DB_CAP_AFFECTED_ROWS | DB_CAP_RAW_QUERY;
 
 	return 0;
 }
diff --git a/modules/db_text/dbtext.h b/modules/db_text/dbtext.h
index 936bb3d..92e6236 100644
--- a/modules/db_text/dbtext.h
+++ b/modules/db_text/dbtext.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * DBText module core functions
  *
  * Copyright (C) 2001-2003 FhG Fokus
@@ -21,10 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2003-01-30 created by Daniel
- * 
  */
 
 
@@ -66,7 +60,7 @@ int dbt_query(db1_con_t* _h, db_key_t* _k, db_op_t* _op, db_val_t* _v,
 /*
  * Raw SQL query
  */
-int dbt_raw_query(db1_con_t* _h, char* _s, db1_res_t** _r);
+int dbt_raw_query(db1_con_t* _h,  str* _s, db1_res_t** _r);
 
 
 /*
@@ -87,5 +81,10 @@ int dbt_delete(db1_con_t* _h, db_key_t* _k, db_op_t* _o, db_val_t* _v, int _n);
 int dbt_update(db1_con_t* _h, db_key_t* _k, db_op_t* _o, db_val_t* _v,
 	      db_key_t* _uk, db_val_t* _uv, int _n, int _un);
 
+/*
+ * Affected rows
+ */
+int dbt_affected_rows(db1_con_t* _h);
+
 #endif
 
diff --git a/modules/db_text/doc/db_text.xml b/modules/db_text/doc/db_text.xml
index 7836c92..b7446ba 100644
--- a/modules/db_text/doc/db_text.xml
+++ b/modules/db_text/doc/db_text.xml
@@ -28,6 +28,11 @@
 		<surname>Mierla</surname>
 		<email>miconda at gmail.com</email>
 	    </editor>
+	    <editor>
+		<firstname>Olle E.</firstname>
+		<surname>Johansson</surname>
+		<email>oej at edvina.net</email>
+	    </editor>
 	</authorgroup>
 	<copyright>
 	    <year>2003</year>
diff --git a/modules/db_text/doc/db_text_admin.xml b/modules/db_text/doc/db_text_admin.xml
index a9df023..6d6078a 100644
--- a/modules/db_text/doc/db_text_admin.xml
+++ b/modules/db_text/doc/db_text_admin.xml
@@ -36,7 +36,8 @@
 		NOTE: even when db_text is in non-caching mode, the module does not write
 		back to hard drive after changes. In this mode, the module checks if
 		the corresponding file on disk has changed, and reloads it. The write
-		to disk happens at &kamailio; shut down.
+		to disk happens at &kamailio; shut down. If db_text is in caching
+		mode, many "reload" functions in various modules will not work.
 	</para>
 		<section>
 		<title>Design of dbtext engine</title>
@@ -159,7 +160,8 @@
 			<listitem>
 				<para>
 				no value between two ':' (or between ':' and start/end of a row)
-				means <quote>null</quote> value.
+				means <quote>null</quote> value. If the parameter "emptystring" is
+				enabled, db_text sets a NULL string to an empty string value.
 				</para>
 			</listitem>
 			<listitem>
@@ -245,30 +247,51 @@ suser:supasswd:xxx:alpha.org:xxx
 	</section>
 	<section>
 	<title>Parameters</title>
-		<para>
-			<emphasis>None</emphasis>.
-	   	</para>
 		<section>
 			<title><varname>db_mode</varname> (integer)</title>
-		<para>
-		Set caching mode (0) or non-caching mode (1). In caching mode, data
-		is loaded at startup. In non-caching mode, the module check every time
-		a table is requested whether the corresponding file on disk has
-		changed, and if yes, will re-load the table from file.
-		</para>
-		<para>
-		<emphasis>
-			Default value is <quote>0</quote>.
-		</emphasis>
-		</para>
-		<example>
-		<title>Set <varname>db_mode</varname> parameter</title>
+			<para>
+			Set caching mode (0) or non-caching mode (1). In caching mode, data
+			is loaded at startup. In non-caching mode, the module check every time
+			a table is requested whether the corresponding file on disk has
+			changed, and if yes, will re-load the table from file.
+			</para>
+
+			<para>
+			<emphasis>
+				Default value is <quote>0</quote>.
+			</emphasis>
+			</para>
+			<example>
+			<title>Set <varname>db_mode</varname> parameter</title>
 		<programlisting format="linespecific">
 ...
 modparam("db_text", "db_mode", 1)
 ...
 </programlisting>
-		</example>
+			</example>
+		</section>
+		<section>
+			<title><varname>emptystring</varname> (integer)</title>
+			<para>
+			db_text by default handles an empty string as a NULL value.
+			Some modules, like the dialplan module, does not accept
+			NULL strings. If you enable emptystring an empty string
+			will not be NULL, but an empty string.
+			</para>
+
+			<para>
+			<emphasis>
+				Default value is <quote>0</quote> (off).
+			</emphasis>
+			</para>
+			<example>
+			<title>Set <varname>emptystring</varname> parameter</title>
+		<programlisting format="linespecific">
+...
+modparam("db_text", "emptystring", 1)
+...
+</programlisting>
+			</example>
 		</section>
 	</section>
 	<section>
diff --git a/modules/db_unixodbc/Makefile b/modules/db_unixodbc/Makefile
index 6661a65..6e22090 100644
--- a/modules/db_unixodbc/Makefile
+++ b/modules/db_unixodbc/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # WARNING: do not run this directly, it should be run by the master Makefile
 
diff --git a/modules/debugger/Makefile b/modules/debugger/Makefile
index a87111c..abf9d35 100644
--- a/modules/debugger/Makefile
+++ b/modules/debugger/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # WARNING: do not run this directly, it should be run by the master Makefile
 
diff --git a/modules/debugger/README b/modules/debugger/README
index d0a9e71..03786a7 100644
--- a/modules/debugger/README
+++ b/modules/debugger/README
@@ -10,7 +10,7 @@ Daniel-Constantin Mierla
 
    <miconda at gmail.com>
 
-   Copyright � 2010 Daniel-Constantin Mierla (asipto.com)
+   Copyright © 2010 Daniel-Constantin Mierla (asipto.com)
      __________________________________________________________________
 
    Table of Contents
@@ -178,7 +178,7 @@ Chapter 1. Admin Guide
    startup. You can change the value at runtime without restart, globally
    or per process.
 
-   Default value is "0" (disabled).
+   Default value is “0” (disabled).
 
    Example 1.1. Set cfgtrace parameter
 ...
@@ -190,7 +190,7 @@ modparam("debugger", "cfgtrace", 1)
    Control whether every line (global) breakpoint is enabled or disabled
    at startup.
 
-   Default value is "0" (disabled).
+   Default value is “0” (disabled).
 
    Example 1.2. Set breakpoint parameter
 ...
@@ -201,7 +201,7 @@ modparam("debugger", "breakpoint", 1)
 
    What log level is to be used to print module-specific messages.
 
-   Default value is "-1" (L_ERR).
+   Default value is “-1” (L_ERR).
 
    Example 1.3. Set log_level parameter
 ...
@@ -212,7 +212,7 @@ modparam("debugger", "log_level", 1)
 
    What log level name is to be used to print cfg trace messages.
 
-   Default value is "NULL" (use default log names).
+   Default value is “NULL” (use default log names).
 
    Example 1.4. Set log_level_name parameter
 ...
@@ -225,7 +225,7 @@ modparam("debugger", "log_level_name", "exec")
    using this setting, you can configure syslog to send debug messages to
    a separate log channel, like a specific kamailio-debug log file.
 
-   Default value is "NULL" (default from core).
+   Default value is “NULL” (default from core).
 
    Example 1.5. Set log_facility parameter
 ...
@@ -236,7 +236,7 @@ modparam("debugger", "log_facility", "LOG_DAEMON")
 
    String to print before any module-specific messages.
 
-   Default value is "*** cfgtrace:".
+   Default value is “*** cfgtrace:”.
 
    Example 1.6. Set log_prefix parameter
 ...
@@ -248,7 +248,7 @@ modparam("debugger", "log_prefix", "from-debugger-with-love:")
    Microseconds to sleep before checking for new commands when waiting at
    a breakpoint.
 
-   Default value is "100000" (that is 0.1 sec).
+   Default value is “100000” (that is 0.1 sec).
 
    Example 1.7. Set step_usleep parameter
 ...
@@ -262,7 +262,7 @@ modparam("debugger", "step_usleep", 500000)
    blocking RPC process forever in case the worker process 'forgets' to
    write back a reply.
 
-   Default value is "200".
+   Default value is “200”.
 
    Example 1.8. Set step_loops parameter
 ...
@@ -276,7 +276,7 @@ modparam("debugger", "step_loops", 100)
    slots). This parameter is accesible readonly via the Kamailio config
    framework.
 
-   Default value is "0" - feature disabled.
+   Default value is “0” - feature disabled.
 
    Example 1.9. Set mod_hash_size parameter
 ...
@@ -286,9 +286,10 @@ modparam("debugger", "mod_hash_size", 5)
 3.10. mod_level_mode (int)
 
    Enable or disable per module log level (0 - disabled, 1 - enabled).
-   This parameter is tunable via the Kamailio config framework.
+   This parameter is tunable via the Kamailio config framework. To use per
+   module log level you also have to set mod_hash_size.
 
-   Default value is "0".
+   Default value is “0”.
 
    Example 1.10. Set mod_level_mode parameter
 ...
@@ -299,7 +300,8 @@ modparam("debugger", "mod_level_mode", 1)
 
    Specify module log level - the value must be in the format:
    modulename=level. The parameter can be set many times. For core log
-   level, use module name 'core'.
+   level, use module name 'core'. You also must enable mod_level_mode and
+   mod_hash_size.
 
    Example 1.11. Set mod_level parameter
 ...
@@ -312,7 +314,7 @@ modparam("debugger", "mod_level", "tm=3")
    Enable or disable log assign actions on config (0 - disabled, 1 -
    enabled).
 
-   Default value is "0".
+   Default value is “0”.
 
    Example 1.12. Set log_assign parameter
 ...
@@ -324,7 +326,7 @@ modparam("debugger", "log_assign", 1)
    If set, before each config action is done pkg memory check, useful to
    detect buffer overflows.
 
-   Default value is "0" (disabled).
+   Default value is “0” (disabled).
 
    Example 1.13. Set cfgpkgcheck parameter
 ...
@@ -336,7 +338,7 @@ modparam("debugger", "cfgpkgcheck", 1)
    Used to enable or disable the ability to reset the msgid ($mi) through
    the dbg.reset_msgid RPC command. (0 - disabled, 1 - enabled).
 
-   Default value is "0" - feature disabled.
+   Default value is “0” - feature disabled.
 
    Example 1.14. Set reset_msgid parameter
 ...
@@ -348,7 +350,7 @@ modparam("debugger", "reset_msgid", 1)
    4.1. dbg_breakpoint(mode)
    4.2. dbg_pv_dump([mask] [, level])
 
-4.1. dbg_breakpoint(mode)
+4.1.  dbg_breakpoint(mode)
 
    Anchor a breakpoint at the current line of the config (the one on which
    this function is called). The 'mode' specifies whether the breakpoint
@@ -363,7 +365,7 @@ if($si=="10.0.0.10")
         dbg_breakpoint("1");
 ...
 
-4.2. dbg_pv_dump([mask] [, level])
+4.2.  dbg_pv_dump([mask] [, level])
 
    Prints the content of pv_cache on json format. Defaults are mask=31 and
    level = "L_DBG"
@@ -416,7 +418,7 @@ x":0,"$var(empty)":0}
    5.4. dbg.mod_level
    5.5. dbg.reset_msgid
 
-5.1. dbg.ls
+5.1.  dbg.ls
 
    List Kamailio processes with info related to interactive debugging.
 
@@ -430,7 +432,7 @@ x":0,"$var(empty)":0}
                 dbg.ls
                 dbg.ls 1234
 
-5.2. dbg.trace
+5.2.  dbg.trace
 
    Control config script running trace.
 
@@ -447,7 +449,7 @@ x":0,"$var(empty)":0}
                 dbg.trace off
                 dbg.trace on 1234
 
-5.3. dbg.bp
+5.3.  dbg.bp
 
    Control breakpoints and config execution.
 
@@ -485,7 +487,7 @@ x":0,"$var(empty)":0}
                 dbg.bp eval 1234 $fu
                 dbg.bp move 1234
 
-5.4. dbg.mod_level
+5.4.  dbg.mod_level
 
    Specify module log level.
 
@@ -499,7 +501,7 @@ x":0,"$var(empty)":0}
                 dbg.mod_level core 3
                 dbg.mod_level tm 3
 
-5.5. dbg.reset_msgid
+5.5.  dbg.reset_msgid
 
    Resets the message sequence ($mi). Internally there is no real change.
    This can be useful for unit test cases in order to be able to replicate
diff --git a/modules/debugger/doc/debugger_admin.xml b/modules/debugger/doc/debugger_admin.xml
index 710d8a3..031e9e0 100644
--- a/modules/debugger/doc/debugger_admin.xml
+++ b/modules/debugger/doc/debugger_admin.xml
@@ -269,7 +269,8 @@ modparam("debugger", "mod_hash_size", 5)
 	    <title><varname>mod_level_mode</varname> (int)</title>
 	    <para>
 			Enable or disable per module log level (0 - disabled, 1 - enabled).
-			This parameter is tunable via the Kamailio config framework.
+			This parameter is tunable via the Kamailio config framework. To use
+			per module log level you also have to set <varname>mod_hash_size</varname>.
 	    </para>
 	    <para>
 		<emphasis>
@@ -291,7 +292,8 @@ modparam("debugger", "mod_level_mode", 1)
 	    <para>
 		Specify module log level - the value must be in the format:
 		modulename=level. The parameter can be set many times. For core
-		log level, use module name 'core'.
+		log level, use module name 'core'. You also must enable
+		<varname>mod_level_mode</varname> and <varname>mod_hash_size</varname>.
 	    </para>
 	    <example>
 		<title>Set <varname>mod_level</varname> parameter</title>
diff --git a/modules/dialog/Makefile b/modules/dialog/Makefile
index 7ca6d68..b579c4a 100644
--- a/modules/dialog/Makefile
+++ b/modules/dialog/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # WARNING: do not run this directly, it should be run by the master Makefile
 
diff --git a/modules/dialog/README b/modules/dialog/README
index 4e720c3..c812043 100644
--- a/modules/dialog/README
+++ b/modules/dialog/README
@@ -92,6 +92,7 @@ Alex Balashov
               5.49. timeout_noreset (int)
               5.50. timer_procs (int)
               5.51. track_cseq_updates (int)
+              5.52. lreq_callee_headers (string)
 
         6. Functions
 
@@ -220,23 +221,24 @@ Alex Balashov
    1.49. Set timeout_noreset parameter
    1.50. Set timer_procs parameter
    1.51. Set track_cseq_updates parameter
-   1.52. set_dlg_profile usage
-   1.53. unset_dlg_profile usage
-   1.54. is_in_profile usage
-   1.55. get_profile_size usage
-   1.56. dlg_isflagset usage
-   1.57. dlg_setflag usage
-   1.58. dlg_resetflag usage
-   1.59. dlg_bye usage
-   1.60. dlg_refer usage
-   1.61. dlg_manage usage
-   1.62. dlg_bridge usage
-   1.63. dlg_get usage
-   1.64. is_known_dlg() usage
-   1.65. dlg_set_timeout usage
-   1.66. dlg_set_timeout_by_profile usage
-   1.67. dlg_set_property usage
-   1.68. dlg_remote_profile usage
+   1.52. Set lreq_callee_headers parameter
+   1.53. set_dlg_profile usage
+   1.54. unset_dlg_profile usage
+   1.55. is_in_profile usage
+   1.56. get_profile_size usage
+   1.57. dlg_isflagset usage
+   1.58. dlg_setflag usage
+   1.59. dlg_resetflag usage
+   1.60. dlg_bye usage
+   1.61. dlg_refer usage
+   1.62. dlg_manage usage
+   1.63. dlg_bridge usage
+   1.64. dlg_get usage
+   1.65. is_known_dlg() usage
+   1.66. dlg_set_timeout usage
+   1.67. dlg_set_timeout_by_profile usage
+   1.68. dlg_set_property usage
+   1.69. dlg_remote_profile usage
 
 Chapter 1. Admin Guide
 
@@ -303,6 +305,7 @@ Chapter 1. Admin Guide
         5.49. timeout_noreset (int)
         5.50. timer_procs (int)
         5.51. track_cseq_updates (int)
+        5.52. lreq_callee_headers (string)
 
    6. Functions
 
@@ -446,6 +449,7 @@ Chapter 1. Admin Guide
    The following modules must be loaded before this module:
      * TM - Transaction module
      * RR - Record-Route module
+     * PV - Pseudovariables module
 
 4.2. External Libraries or Applications
 
@@ -506,6 +510,7 @@ Chapter 1. Admin Guide
    5.49. timeout_noreset (int)
    5.50. timer_procs (int)
    5.51. track_cseq_updates (int)
+   5.52. lreq_callee_headers (string)
 
 5.1. enable_stats (integer)
 
@@ -1175,6 +1180,19 @@ modparam("dialog", "timer_procs", 1)
 modparam("dialog", "track_cseq_updates", 1)
 ...
 
+5.52. lreq_callee_headers (string)
+
+   SIP headers to be added when sending local generated requests (e.g.,
+   BYE) to callee. It can be useful when you use topoh module with call-id
+   masking (see the docs of topoh module).
+
+   Default value is "null".
+
+   Example 1.52. Set lreq_callee_headers parameter
+...
+modparam("dialog", "lreq_callee_headers", "TH: dlh\r\n")
+...
+
 6. Functions
 
    6.1. set_dlg_profile(profile,[value])
@@ -1211,7 +1229,7 @@ modparam("dialog", "track_cseq_updates", 1)
    This function can be used from REQUEST_ROUTE, BRANCH_ROUTE, REPLY_ROUTE
    and FAILURE_ROUTE.
 
-   Example 1.52. set_dlg_profile usage
+   Example 1.53. set_dlg_profile usage
 ...
 set_dlg_profile("inbound_call");
 set_dlg_profile("caller","$fu");
@@ -1230,7 +1248,7 @@ set_dlg_profile("caller","$fu");
    This function can be used from BRANCH_ROUTE, REPLY_ROUTE and
    FAILURE_ROUTE.
 
-   Example 1.53. unset_dlg_profile usage
+   Example 1.54. unset_dlg_profile usage
 ...
 unset_dlg_profile("inbound_call");
 unset_dlg_profile("caller","$fu");
@@ -1253,7 +1271,7 @@ unset_dlg_profile("caller","$fu");
    This function can be used from REQUEST_ROUTE, BRANCH_ROUTE, REPLY_ROUTE
    and FAILURE_ROUTE.
 
-   Example 1.54. is_in_profile usage
+   Example 1.55. is_in_profile usage
 ...
 if (is_in_profile("inbound_call")) {
         log("this request belongs to a inbound call\n");
@@ -1282,7 +1300,7 @@ if (is_in_profile("caller","XX")) {
    This function can be used from REQUEST_ROUTE, BRANCH_ROUTE, REPLY_ROUTE
    and FAILURE_ROUTE.
 
-   Example 1.55. get_profile_size usage
+   Example 1.56. get_profile_size usage
 ...
 if(get_profile_size("inbound_call","$avp(size)"))
     xlog("currently there are $avp(size) inbound calls\n");
@@ -1301,7 +1319,7 @@ if(get_profile_size("caller","$fu","$avp(size)"))
    This function can be used from BRANCH_ROUTE, REQUEST_ROUTE,
    ONREPLY_ROUTE and FAILURE_ROUTE.
 
-   Example 1.56. dlg_isflagset usage
+   Example 1.57. dlg_isflagset usage
 ...
 if(dlg_isflagset("1"))
 {
@@ -1319,7 +1337,7 @@ if(dlg_isflagset("1"))
    This function can be used from BRANCH_ROUTE, REQUEST_ROUTE,
    ONREPLY_ROUTE and FAILURE_ROUTE.
 
-   Example 1.57. dlg_setflag usage
+   Example 1.58. dlg_setflag usage
 ...
 dlg_setflag("1");
 ...
@@ -1334,7 +1352,7 @@ dlg_setflag("1");
    This function can be used from BRANCH_ROUTE, REQUEST_ROUTE,
    ONREPLY_ROUTE and FAILURE_ROUTE.
 
-   Example 1.58. dlg_resetflag usage
+   Example 1.59. dlg_resetflag usage
 ...
 redlg_setflag("1");
 ...
@@ -1350,7 +1368,7 @@ redlg_setflag("1");
    This function can be used from BRANCH_ROUTE, REQUEST_ROUTE,
    ONREPLY_ROUTE and FAILURE_ROUTE.
 
-   Example 1.59. dlg_bye usage
+   Example 1.60. dlg_bye usage
 ...
 dlg_bye("all");
 ...
@@ -1367,7 +1385,7 @@ dlg_bye("all");
    This function can be used from BRANCH_ROUTE, REQUEST_ROUTE,
    ONREPLY_ROUTE and FAILURE_ROUTE.
 
-   Example 1.60. dlg_refer usage
+   Example 1.61. dlg_refer usage
 ...
 dlg_refer("caller", "sip:announcement at kamailio.org");
 ...
@@ -1380,7 +1398,7 @@ dlg_refer("caller", "sip:announcement at kamailio.org");
 
    This function can be used from REQUEST_ROUTE.
 
-   Example 1.61. dlg_manage usage
+   Example 1.62. dlg_manage usage
 ...
 modparam("dialog", "default_timeout", 100)
 ...
@@ -1408,7 +1426,7 @@ route {
    This function can be used from BRANCH_ROUTE, REQUEST_ROUTE,
    ONREPLY_ROUTE and FAILURE_ROUTE.
 
-   Example 1.62. dlg_bridge usage
+   Example 1.63. dlg_bridge usage
 ...
 dlg_bridge("sip:user at kamailio.org", "sip:annoucement at kamailio.org",
    "sip:kamailio.org:5080");
@@ -1427,7 +1445,7 @@ dlg_bridge("sip:user at kamailio.org", "sip:annoucement at kamailio.org",
    This function can be used from BRANCH_ROUTE, REQUEST_ROUTE,
    ONREPLY_ROUTE and FAILURE_ROUTE.
 
-   Example 1.63. dlg_get usage
+   Example 1.64. dlg_get usage
 ...
 if(dlg_get("abcdef", "123", "456"))
 {
@@ -1451,7 +1469,7 @@ if(dlg_get("abcdef", "123", "456"))
    This function can be used from REQUEST_ROUTE, BRANCH_ROUTE, REPLY_ROUTE
    and FAILURE_ROUTE.
 
-   Example 1.64. is_known_dlg() usage
+   Example 1.65. is_known_dlg() usage
 ...
 if(!uri == myself) {
         if(is_known_dlg()) {
@@ -1475,7 +1493,7 @@ if(!uri == myself) {
 
    This function can be used from ANY_ROUTE.
 
-   Example 1.65. dlg_set_timeout usage
+   Example 1.66. dlg_set_timeout usage
 ...
 if(dlg_set_timeout("180", "123", "456"))
 {
@@ -1497,7 +1515,7 @@ if(dlg_set_timeout("180", "123", "456"))
 
    This function can be used from ANY_ROUTE.
 
-   Example 1.66. dlg_set_timeout_by_profile usage
+   Example 1.67. dlg_set_timeout_by_profile usage
 ...
 # All dialogs belonging to user abc123 (tracked via set_dlg_profile())
 # will be timed out in 3 seconds.
@@ -1529,7 +1547,7 @@ dlg_set_timeout_by_profile("users", "abc123", "3");
 
    This function can be used from ANY_ROUTE.
 
-   Example 1.67. dlg_set_property usage
+   Example 1.68. dlg_set_property usage
 ...
 dlg_set_property("ka-src");
 dlg_set_property("ka-dst");
@@ -1557,7 +1575,7 @@ dlg_set_property("timeout-noreset");
 
    This function can be used from ANY_ROUTE.
 
-   Example 1.68. dlg_remote_profile usage
+   Example 1.69. dlg_remote_profile usage
 ...
 $var(exp) = 3600 + $Ts;
 dlg_remote_profile("add", "caller", "test", "$sruid", "$var(exp)");
diff --git a/modules/dialog/dialog.c b/modules/dialog/dialog.c
index 96bca17..16328b0 100644
--- a/modules/dialog/dialog.c
+++ b/modules/dialog/dialog.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * dialog module - basic support for dialog tracking
  *
  * Copyright (C) 2006 Voice Sistem SRL
@@ -22,20 +20,13 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2006-04-14 initial version (bogdan)
- *  2006-11-28 Added statistic support for the number of early and failed
- *              dialogs. (Jeffrey Magder - SOMA Networks) 
- *  2007-04-30 added dialog matching without DID (dialog ID), but based only
- *              on RFC3261 elements - based on an original patch submitted 
- *              by Michel Bensoussan <michel at extricom.com> (bogdan)
- *  2007-05-15 added saving dialogs' information to database (ancuta)
- *  2007-07-04 added saving dialog cseq, contact, record route 
- *              and bind_addresses(sock_info) for caller and callee (ancuta)
- *  2008-04-14 added new type of callback to be triggered when dialogs are 
- *              loaded from DB (bogdan)
- *  2010-06-16 added sip-router rpc interface (osas)
+ */
+
+/*!
+ * \file
+ * \brief Module interface
+ * \ingroup dialog
+ * Module: \ref dialog
  */
 
 /**
@@ -147,6 +138,8 @@ int dlg_ka_timer = 0;
 int dlg_ka_interval = 0;
 int dlg_clean_timer = 90;
 
+str dlg_lreq_callee_headers = {0};
+
 /* db stuff */
 static str db_url = str_init(DEFAULT_DB_URL);
 static unsigned int db_update_period = DB_DEFAULT_UPDATE_PERIOD;
@@ -297,6 +290,7 @@ static param_export_t mod_params[]={
 	{ "timeout_noreset",       INT_PARAM, &dlg_timeout_noreset      },
 	{ "timer_procs",           PARAM_INT, &dlg_timer_procs          },
 	{ "track_cseq_updates",    PARAM_INT, &_dlg_track_cseq_updates  },
+	{ "lreq_callee_headers",   PARAM_STR, &dlg_lreq_callee_headers  },
 	{ 0,0,0 }
 };
 
@@ -373,7 +367,7 @@ static int fixup_profile(void** param, int param_no)
 	if (param_no==1) {
 		profile = search_dlg_profile( &s );
 		if (profile==NULL) {
-			LM_CRIT("profile <%s> not definited\n",s.s);
+			LM_CRIT("profile <%s> not defined\n",s.s);
 			return E_CFG;
 		}
 		pkg_free(*param);
diff --git a/modules/dialog/dlg_cb.c b/modules/dialog/dlg_cb.c
index 3888fd7..240a565 100644
--- a/modules/dialog/dlg_cb.c
+++ b/modules/dialog/dlg_cb.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2006 Voice Sistem SRL
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,14 +17,14 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2006-04-14  initial version (bogdan)
- * 2008-04-04  added direction reporting in dlg callbacks (bogdan)
- * 2008-04-14  DLGCB_CREATED may be registered before the module 
- *              initialization (bogdan)
- * 2008-04-15  added new type of callback to be triggered when dialogs are 
- *              loaded from DB (bogdan)
+ */
+
+
+/*!
+ * \file
+ * \brief Callbacks
+ * \ingroup dialog
+ * Module: \ref dialog
  */
 
 
diff --git a/modules/dialog/dlg_cb.h b/modules/dialog/dlg_cb.h
index 387c068..349e24b 100644
--- a/modules/dialog/dlg_cb.h
+++ b/modules/dialog/dlg_cb.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2006 Voice Sistem SRLs
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,14 +17,13 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2006-04-11  initial version (bogdan)
- * 2008-04-04  added direction reporting in dlg callbacks (bogdan)
- * 2008-04-14  added new type of callback to be triggered when dialogs are 
- *              loaded from DB (bogdan)
- * 2008-04-17  added new type of callback to be triggered right before the
- *              dialog is destroyed (deleted from memory) (bogdan)
+ */
+
+/*!
+ * \file
+ * \brief Callbacks
+ * \ingroup dialog
+ * Module: \ref dialog
  */
 
 #ifndef _DIALOG_DLG_CB_H_
@@ -61,6 +58,8 @@ typedef int (*set_dlg_variable_f)( struct dlg_cell* dlg,
 typedef str* (*get_dlg_variable_f)( struct dlg_cell* dlg,
                                     str* key);
 
+#define CONFIRMED_DIALOG_STATE 1
+
 #define DLGCB_LOADED          (1<<0)
 #define DLGCB_CREATED         (1<<1)
 #define DLGCB_FAILED          (1<<2)
diff --git a/modules/dialog/dlg_cseq.c b/modules/dialog/dlg_cseq.c
index ad1713c..58a6bb8 100644
--- a/modules/dialog/dlg_cseq.c
+++ b/modules/dialog/dlg_cseq.c
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (C) 2014 Daniel-Constantin Mierla (asipto.com)
  *
  * This file is part of Kamailio, a free SIP server.
@@ -20,6 +20,14 @@
  *
  */
 
+
+/*!
+ * \file
+ * \brief Cseq handling
+ * \ingroup dialog
+ * Module: \ref dialog
+ */
+
 #include <stdio.h>
 #include <unistd.h>
 #include <stdlib.h>
diff --git a/modules/dialog/dlg_cseq.h b/modules/dialog/dlg_cseq.h
index 3528fcc..28b9a2a 100644
--- a/modules/dialog/dlg_cseq.h
+++ b/modules/dialog/dlg_cseq.h
@@ -20,6 +20,14 @@
  *
  */
 
+
+/*!
+ * \file
+ * \brief CSeq handling
+ * \ingroup dialog
+ * Module: \ref dialog
+ */
+
 #ifndef _DLG_CSEQ_H_
 #define _DLG_CSEQ_H_
 
diff --git a/modules/dialog/dlg_db_handler.c b/modules/dialog/dlg_db_handler.c
index 5655b99..9e8d2c4 100644
--- a/modules/dialog/dlg_db_handler.c
+++ b/modules/dialog/dlg_db_handler.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2007 Voice System SRL
  * Copyright (C) 2011 Carsten Bock, carsten at ng-voice.com
  *
@@ -20,11 +18,13 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2007-05-10  initial version (ancuta)
- * 2007-07-06 additional information saved in the database: cseq, contact, 
- *  		   route set and socket_info for both caller and callee (ancuta)
+ */
+
+/*!
+ * \file
+ * \brief Database interface
+ * \ingroup dialog
+ * Module: \ref dialog
  */
 
 #include <stdlib.h>
diff --git a/modules/dialog/dlg_db_handler.h b/modules/dialog/dlg_db_handler.h
index 4bb9a2a..cca0517 100644
--- a/modules/dialog/dlg_db_handler.h
+++ b/modules/dialog/dlg_db_handler.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2007 Voice System SRL
  * Copyright (C) 2011 Carsten Bock, carsten at ng-voice.com
  *
@@ -20,11 +18,14 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2007-05-10  initial version (ancuta)
  */
 
+/*!
+ * \file
+ * \brief Database interface
+ * \ingroup dialog
+ * Module: \ref dialog
+ */
 
 #ifndef _DLG_DB_HANDLER_H_
 #define _DLG_DB_HANDLER_H_
diff --git a/modules/dialog/dlg_handlers.c b/modules/dialog/dlg_handlers.c
index 0ec52bb..aae6efb 100644
--- a/modules/dialog/dlg_handlers.c
+++ b/modules/dialog/dlg_handlers.c
@@ -17,28 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2006-04-14  initial version (bogdan)
- * 2006-11-28  Added support for tracking the number of early dialogs, and the
- *             number of failed dialogs. This involved updates to dlg_onreply()
- *             (Jeffrey Magder - SOMA Networks)
- * 2007-03-06  syncronized state machine added for dialog state. New tranzition
- *             design based on events; removed num_1xx and num_2xx (bogdan)
- * 2007-04-30  added dialog matching without DID (dialog ID), but based only
- *             on RFC3261 elements - based on an original patch submitted
- *             by Michel Bensoussan <michel at extricom.com> (bogdan)
- * 2007-05-17  new feature: saving dialog info into a database if
- *             realtime update is set(ancuta)
- * 2007-07-06  support for saving additional dialog info : cseq, contact,
- *             route_set and socket_info for both caller and callee (ancuta)
- * 2007-07-10  Optimized dlg_match_mode 2 (DID_NONE), it now employs a proper
- *             hash table lookup and isn't dependant on the is_direction
- *             function (which requires an RR param like dlg_match_mode 0
- *             anyways.. ;) ; based on a patch from
- *             Tavis Paquette <tavis at galaxytelecom.net>
- *             and Peter Baer <pbaer at galaxytelecom.net>  (bogdan)
- * 2008-04-04  added direction reporting in dlg callbacks (bogdan)
  */
 
 
@@ -1393,11 +1371,15 @@ void dlg_ontimeout(struct dlg_tl *tl)
 	dlg_cell_t *dlg;
 	int new_state, old_state, unref;
 	sip_msg_t *fmsg;
+	void* timeout_cb = 0;
 
 	/* get the dialog tl payload */
 	dlg = ((struct dlg_cell*)((char *)(tl) -
 			(unsigned long)(&((struct dlg_cell*)0)->tl)));
 
+	/* mark dialog as expired */
+	dlg->dflags |= DLG_FLAG_EXPIRED;
+
 	if(dlg->state==DLG_STATE_CONFIRMED_NA
 				|| dlg->state==DLG_STATE_CONFIRMED)
 	{
@@ -1432,6 +1414,11 @@ void dlg_ontimeout(struct dlg_tl *tl)
 	}
 
 	next_state_dlg( dlg, DLG_EVENT_REQBYE, &old_state, &new_state, &unref);
+    /* used for computing duration for timed out acknowledged dialog */
+	if (DLG_STATE_CONFIRMED == old_state) {
+		timeout_cb = (void *)CONFIRMED_DIALOG_STATE;
+	}	
+
 	dlg_run_event_route(dlg, NULL, old_state, new_state);
 
 	if (new_state==DLG_STATE_DELETED && old_state!=DLG_STATE_DELETED) {
@@ -1441,7 +1428,7 @@ void dlg_ontimeout(struct dlg_tl *tl)
 			dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
 
 		/* dialog timeout */
-		run_dlg_callbacks( DLGCB_EXPIRED, dlg, NULL, NULL, DLG_DIR_NONE, 0);
+		run_dlg_callbacks( DLGCB_EXPIRED, dlg, NULL, NULL, DLG_DIR_NONE, timeout_cb);
 
 		dlg_unref(dlg, unref+1);
 
diff --git a/modules/dialog/dlg_handlers.h b/modules/dialog/dlg_handlers.h
index 8c29b9f..faf63d0 100644
--- a/modules/dialog/dlg_handlers.h
+++ b/modules/dialog/dlg_handlers.h
@@ -17,11 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2006-04-14  initial version (bogdan)
- * 2007-03-06  syncronized state machine added for dialog state. New tranzition
- *             design based on events; removed num_1xx and num_2xx (bogdan)
  */
 
 
diff --git a/modules/dialog/dlg_hash.c b/modules/dialog/dlg_hash.c
index f98207b..536fe32 100644
--- a/modules/dialog/dlg_hash.c
+++ b/modules/dialog/dlg_hash.c
@@ -18,27 +18,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2006-04-14  initial version (bogdan)
- * 2007-03-06  syncronized state machine added for dialog state. New tranzition
- *             design based on events; removed num_1xx and num_2xx (bogdan)
- * 2007-04-30  added dialog matching without DID (dialog ID), but based only
- *             on RFC3261 elements - based on an original patch submitted 
- *             by Michel Bensoussan <michel at extricom.com> (bogdan)
- * 2007-07-06  additional information stored in order to save it in the db:
- *             cseq, route_set, contact and sock_info for both caller and 
- *             callee (ancuta)
- * 2007-07-10  Optimized dlg_match_mode 2 (DID_NONE), it now employs a proper
- *             hash table lookup and isn't dependant on the is_direction 
- *             function (which requires an RR param like dlg_match_mode 0 
- *             anyways.. ;) ; based on a patch from 
- *             Tavis Paquette <tavis at galaxytelecom.net> 
- *             and Peter Baer <pbaer at galaxytelecom.net>  (bogdan)
- * 2008-04-17  added new type of callback to be triggered right before the
- *              dialog is destroyed (deleted from memory) (bogdan)
- * 2008-04-17  added new dialog flag to avoid state tranzitions from DELETED to
- *             CONFIRMED_NA due delayed "200 OK" (bogdan)
  */
 
 
@@ -203,10 +182,10 @@ int dlg_ka_run(ticks_t ti)
 		} else {
 			if((dka->iflags & DLG_IFLAG_KA_SRC)
 					&& (dlg->state==DLG_STATE_CONFIRMED))
-				dlg_send_ka(dlg, DLG_CALLER_LEG, 0);
+				dlg_send_ka(dlg, DLG_CALLER_LEG);
 			if((dka->iflags & DLG_IFLAG_KA_DST)
 					&& (dlg->state==DLG_STATE_CONFIRMED))
-				dlg_send_ka(dlg, DLG_CALLEE_LEG, 0);
+				dlg_send_ka(dlg, DLG_CALLEE_LEG);
 			if(dlg->state==DLG_STATE_DELETED) {
 				shm_free(dka);
 				dka = NULL;
diff --git a/modules/dialog/dlg_hash.h b/modules/dialog/dlg_hash.h
index 62fcec9..d79d994 100644
--- a/modules/dialog/dlg_hash.h
+++ b/modules/dialog/dlg_hash.h
@@ -18,19 +18,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2006-04-14  initial version (bogdan)
- * 2006-11-28  Added num_100s and num_200s to dlg_cell, to aid in adding 
- *             statistics tracking of the number of early, and active dialogs.
- *             (Jeffrey Magder - SOMA Networks)
- * 2007-03-06  syncronized state machine added for dialog state. New tranzition
- *             design based on events; removed num_1xx and num_2xx (bogdan)
- * 2007-07-06  added flags, cseq, contact, route_set and bind_addr 
- *             to struct dlg_cell in order to store these information into db
- *             (ancuta)
- * 2008-04-17  added new dialog flag to avoid state tranzitions from DELETED to
- *             CONFIRMED_NA due delayed "200 OK" (bogdan)
  */
 
 /*!
@@ -80,6 +67,7 @@
 #define DLG_FLAG_DEL           (1<<8) /*!< delete this var */
 
 #define DLG_FLAG_TM            (1<<9) /*!< dialog is set in transaction */
+#define DLG_FLAG_EXPIRED       (1<<10)/*!< dialog is expired */
 
 /* internal flags stored in db */
 #define DLG_IFLAG_TIMEOUTBYE        (1<<0) /*!< send bye on time-out */
diff --git a/modules/dialog/dlg_load.h b/modules/dialog/dlg_load.h
index 0787287..a68426a 100644
--- a/modules/dialog/dlg_load.h
+++ b/modules/dialog/dlg_load.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * dialog module - basic support for dialog tracking
  *
  * Copyright (C) 2006 Voice Sistem SRL
@@ -21,9 +19,14 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2006-04-14  initial version (bogdan)
+ */
+
+
+/*!
+ * \file
+ * \brief Functions related to dialog handling
+ * \ingroup dialog
+ * Module: \ref dialog
  */
 
 #ifndef _DIALOG_DLG_LOAD_H_
diff --git a/modules/dialog/dlg_profile.c b/modules/dialog/dlg_profile.c
index b459ac5..39dc1df 100644
--- a/modules/dialog/dlg_profile.c
+++ b/modules/dialog/dlg_profile.c
@@ -17,10 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2008-04-20  initial version (bogdan)
- *
  */
 
 
diff --git a/modules/dialog/dlg_profile.h b/modules/dialog/dlg_profile.h
index 07fb2b5..be21f0f 100644
--- a/modules/dialog/dlg_profile.h
+++ b/modules/dialog/dlg_profile.h
@@ -17,13 +17,16 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2008-04-20  initial version (bogdan)
- *
  */
 
 
+/*!
+ * \file
+ * \brief Profile handling
+ * \ingroup dialog
+ * Module: \ref dialog
+ */
+
 
 #ifndef _DIALOG_DLG_PROFILE_H_
 #define _DIALOG_DLG_PROFILE_H_
diff --git a/modules/dialog/dlg_req_within.c b/modules/dialog/dlg_req_within.c
index 5668c3c..f862ab2 100644
--- a/modules/dialog/dlg_req_within.c
+++ b/modules/dialog/dlg_req_within.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2007 Voice System SRL
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,12 +17,16 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2007-07-10  initial version (ancuta)
- * 2008-04-04  added direction reporting in dlg callbacks (bogdan)
 */
 
+
+/*!
+ * \file
+ * \brief Requests
+ * \ingroup dialog
+ * Module: \ref dialog
+ */
+
 #include <stdlib.h>
 #include <string.h>
 
@@ -50,7 +52,7 @@
 #define MAX_FWD_HDR_LEN    (sizeof(MAX_FWD_HDR) - 1)
 
 extern str dlg_extra_hdrs;
-
+extern str dlg_lreq_callee_headers;
 
 
 int free_tm_dlg(dlg_t *td)
@@ -284,12 +286,19 @@ static inline int build_extra_hdr(struct dlg_cell * cell, str *extra_hdrs,
 		str *str_hdr)
 {
 	char *p;
+	int blen;
 
 	str_hdr->len = MAX_FWD_HDR_LEN + dlg_extra_hdrs.len;
 	if(extra_hdrs && extra_hdrs->len>0)
 		str_hdr->len += extra_hdrs->len;
 
-	str_hdr->s = (char*)pkg_malloc( str_hdr->len * sizeof(char) );
+	blen = str_hdr->len + 1 /* '\0' */;
+
+	/* reserve space for callee headers in local requests */
+	if(dlg_lreq_callee_headers.len>0)
+		blen += dlg_lreq_callee_headers.len + 2 /* '\r\n' */;
+
+	str_hdr->s = (char*)pkg_malloc( blen * sizeof(char) );
 	if(!str_hdr->s){
 		LM_ERR("out of pkg memory\n");
 		goto error;
@@ -324,6 +333,7 @@ static inline int send_bye(struct dlg_cell * cell, int dir, str *hdrs)
 	str met = {"BYE", 3};
 	int result;
 	dlg_iuid_t *iuid = NULL;
+	str lhdrs;
 
 	/* do not send BYE request for non-confirmed dialogs (not supported) */
 	if (cell->state != DLG_STATE_CONFIRMED_NA && cell->state != DLG_STATE_CONFIRMED) {
@@ -347,7 +357,20 @@ static inline int send_bye(struct dlg_cell * cell, int dir, str *hdrs)
 		goto err;
 	}
 
-	set_uac_req(&uac_r, &met, hdrs, NULL, dialog_info, TMCB_LOCAL_COMPLETED,
+	lhdrs = *hdrs;
+
+	if(dir==DLG_CALLEE_LEG && dlg_lreq_callee_headers.len>0) {
+		/* space allocated in hdrs->s by build_extra_hdrs() */
+		memcpy(lhdrs.s+lhdrs.len, dlg_lreq_callee_headers.s,
+				dlg_lreq_callee_headers.len);
+		lhdrs.len += dlg_lreq_callee_headers.len;
+		if(dlg_lreq_callee_headers.s[dlg_lreq_callee_headers.len-1]!='\n') {
+			strncpy(lhdrs.s+lhdrs.len, CRLF, CRLF_LEN);
+			lhdrs.len += CRLF_LEN;
+		}
+	}
+
+	set_uac_req(&uac_r, &met, &lhdrs, NULL, dialog_info, TMCB_LOCAL_COMPLETED,
 				bye_reply_cb, (void*)iuid);
 	result = d_tmb.t_request_within(&uac_r);
 
@@ -374,7 +397,7 @@ err:
  * 		DLG_CALLER_LEG (0): caller
  * 		DLG_CALLEE_LEG (1): callee
  */
-int dlg_send_ka(dlg_cell_t *dlg, int dir, str *hdrs)
+int dlg_send_ka(dlg_cell_t *dlg, int dir)
 {
 	uac_req_t uac_r;
 	dlg_t* di;
@@ -410,8 +433,13 @@ int dlg_send_ka(dlg_cell_t *dlg, int dir, str *hdrs)
 		goto err;
 	}
 
-	set_uac_req(&uac_r, &met, hdrs, NULL, di, TMCB_LOCAL_COMPLETED,
+	if(dir==DLG_CALLEE_LEG && dlg_lreq_callee_headers.len>0) {
+		set_uac_req(&uac_r, &met, &dlg_lreq_callee_headers, NULL, di,
+				TMCB_LOCAL_COMPLETED, dlg_ka_cb, (void*)iuid);
+	} else {
+		set_uac_req(&uac_r, &met, NULL, NULL, di, TMCB_LOCAL_COMPLETED,
 				dlg_ka_cb, (void*)iuid);
+	}
 	result = d_tmb.t_request_within(&uac_r);
 
 	if(result < 0){
diff --git a/modules/dialog/dlg_req_within.h b/modules/dialog/dlg_req_within.h
index fd631cb..420928e 100644
--- a/modules/dialog/dlg_req_within.h
+++ b/modules/dialog/dlg_req_within.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2007 Voice System SRL
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,13 +17,14 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2007-07-10  initial version (ancuta)
 */
 
-
-
+/*!
+ * \file
+ * \brief Request
+ * \ingroup dialog
+ * Module: \ref dialog
+ */
 
 #ifndef DLG_REQUEST_WITHIN_H
 #define DLG_REQUEST_WITHIN_H
@@ -52,6 +51,6 @@ dlg_t* build_dlg_t(struct dlg_cell * cell, int dir);
 int free_tm_dlg(dlg_t *td);
 int dlg_bye(struct dlg_cell *dlg, str *hdrs, int side);
 int dlg_bye_all(struct dlg_cell *dlg, str *hdrs);
-int dlg_send_ka(dlg_cell_t *dlg, int dir, str *hdrs);
+int dlg_send_ka(dlg_cell_t *dlg, int dir);
 
 #endif
diff --git a/modules/dialog/dlg_timer.c b/modules/dialog/dlg_timer.c
index 923511f..9f96f6a 100644
--- a/modules/dialog/dlg_timer.c
+++ b/modules/dialog/dlg_timer.c
@@ -17,11 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2006-04-14  initial version (bogdan)
- * 2007-03-06  to avoid races, tests on timer links are done under locks
- *             (bogdan)
  */
 
 /*!
diff --git a/modules/dialog/dlg_timer.h b/modules/dialog/dlg_timer.h
index b7f3aee..367237e 100644
--- a/modules/dialog/dlg_timer.h
+++ b/modules/dialog/dlg_timer.h
@@ -17,9 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2006-04-14  initial version (bogdan)
  */
 
 /*!
diff --git a/modules/dialog/dlg_transfer.c b/modules/dialog/dlg_transfer.c
index b4d8be8..978f1a2 100644
--- a/modules/dialog/dlg_transfer.c
+++ b/modules/dialog/dlg_transfer.c
@@ -1,6 +1,4 @@
-/**
- * $Id$
- *
+/*
  * Copyright (C) 2009 Daniel-Constantin Mierla (asipto.com)
  *
  * This file is part of kamailio, a free SIP server.
@@ -20,6 +18,14 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
+
+/*!
+ * \file
+ * \brief Call transfer
+ * \ingroup dialog
+ * Module: \ref dialog
+ */
+
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
diff --git a/modules/dialog/dlg_transfer.h b/modules/dialog/dlg_transfer.h
index 3c8c8c2..910373c 100644
--- a/modules/dialog/dlg_transfer.h
+++ b/modules/dialog/dlg_transfer.h
@@ -1,6 +1,4 @@
 /**
- * $Id$
- *
  * Copyright (C) 2009 Daniel-Constantin Mierla (asipto.com)
  *
  * This file is part of kamailio, a free SIP server.
@@ -19,6 +17,14 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
+
+
+/*!
+ * \file
+ * \brief Call transfer
+ * \ingroup dialog
+ * Module: \ref dialog
+ */
 		       
 #ifndef _DLG_TRANSFER_H_
 #define _DLG_TRANSFER_H_
diff --git a/modules/dialog/dlg_var.c b/modules/dialog/dlg_var.c
index b3d4f05..b4f821e 100644
--- a/modules/dialog/dlg_var.c
+++ b/modules/dialog/dlg_var.c
@@ -1,6 +1,4 @@
-/**
- * $Id$
- *
+/*
  * Copyright (C) 2009 Daniel-Constantin Mierla (asipto.com)
  * Copyright (C) 2011 Carsten Bock, carsten at ng-voice.com
  *
@@ -20,6 +18,13 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
+
+/*!
+ * \file
+ * \brief Dialog variables
+ * \ingroup dialog
+ * Module: \ref dialog
+ */
 		       
 #include "../../route.h"
 #include "../../script_cb.h"
@@ -51,10 +56,10 @@ int dlg_cfg_cb(sip_msg_t *msg, unsigned int flags, void *cbp)
 					/* release to destroy dialog if created by this process
 					 * and request was not forwarded */
 					if(dlg->state==DLG_STATE_UNCONFIRMED) {
-						LM_DBG("new dialog with no trasaction after config"
+						LM_DBG("new dialog with no transaction after config"
 									" execution\n");
 					} else {
-						LM_DBG("dialog with no expected trasaction after"
+						LM_DBG("dialog with no expected transaction after"
 								" config execution\n");
 					}
 					dlg_release(dlg);
diff --git a/modules/dialog/dlg_var.h b/modules/dialog/dlg_var.h
index 7691a16..7d4c360 100644
--- a/modules/dialog/dlg_var.h
+++ b/modules/dialog/dlg_var.h
@@ -1,6 +1,4 @@
-/**
- * $Id$
- *
+/*
  * Copyright (C) 2009 Daniel-Constantin Mierla (asipto.com)
  * Copyright (C) 2011 Carsten Bock, carsten at ng-voice.com
  *
@@ -20,6 +18,13 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
+
+/*!
+ * \file
+ * \brief Dialog variables
+ * \ingroup dialog
+ * Module: \ref dialog
+ */
 		       
 #ifndef _DLG_VAR_H_
 #define _DLG_VAR_H_
diff --git a/modules/dialog/doc/dialog_admin.xml b/modules/dialog/doc/dialog_admin.xml
index 0a27161..b3fdf34 100644
--- a/modules/dialog/doc/dialog_admin.xml
+++ b/modules/dialog/doc/dialog_admin.xml
@@ -121,6 +121,11 @@
 				<emphasis>RR</emphasis> - Record-Route module
 			</para>
 			</listitem>
+			<listitem>
+			<para>
+				<emphasis>PV</emphasis> - Pseudovariables module
+			</para>
+			</listitem>
 			</itemizedlist>
 		</para>
 	</section>
@@ -1306,6 +1311,28 @@ modparam("dialog", "track_cseq_updates", 1)
 		</example>
 	</section>
 
+	<section id="dialog.p.lreq_callee_headers">
+		<title><varname>lreq_callee_headers</varname> (string)</title>
+		<para>
+			SIP headers to be added when sending local generated requests
+			(e.g., BYE) to callee. It can be useful when you use topoh module
+			with call-id masking (see the docs of topoh module).
+		</para>
+		<para>
+		<emphasis>
+			Default value is <quote>null</quote>.
+		</emphasis>
+		</para>
+		<example>
+		<title>Set <varname>lreq_callee_headers</varname> parameter</title>
+		<programlisting format="linespecific">
+...
+modparam("dialog", "lreq_callee_headers", "TH: dlh\r\n")
+...
+</programlisting>
+		</example>
+	</section>
+
 	</section>
 
 
diff --git a/modules/dialog_ng/Makefile b/modules/dialog_ng/Makefile
index 082ee36..c9165bc 100644
--- a/modules/dialog_ng/Makefile
+++ b/modules/dialog_ng/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # WARNING: do not run this directly, it should be run by the master Makefile
 
diff --git a/modules/dialog_ng/dialog.c b/modules/dialog_ng/dialog.c
index 1814a98..cdf54e4 100644
--- a/modules/dialog_ng/dialog.c
+++ b/modules/dialog_ng/dialog.c
@@ -32,6 +32,7 @@
 #include "dlg_var.h"
 #include "dlg_req_within.h"
 #include "dlg_db_handler.h"
+#include "dlg_ng_stats.h"
 
 MODULE_VERSION
 
@@ -65,9 +66,6 @@ struct tm_binds d_tmb;
 struct rr_binds d_rrb;
 pv_spec_t timeout_avp;
 
-int active_dlgs_cnt = 0;
-int early_dlgs_cnt	= 0;
-
 /* db stuff */
 int dlg_db_mode_param = DB_MODE_NONE;
 static int db_fetch_rows = 200;
@@ -136,7 +134,7 @@ static param_export_t mod_params[] = {
     //In this new dialog module we always match using DID
     //{ "dlg_match_mode", INT_PARAM, &seq_match_mode},
 
-    { "db_url",				PARAM_STRING, &db_url 				},
+    { "db_url",				PARAM_STR, &db_url 				},
     { "db_mode",			INT_PARAM, &dlg_db_mode_param		},
     { "db_update_period",	INT_PARAM, &db_update_period		},
     { "db_fetch_rows",		INT_PARAM, &db_fetch_rows			}
@@ -345,6 +343,7 @@ int load_dlg(struct dlg_binds *dlgb) {
     dlgb->lookup_terminate_dlg = w_api_lookup_terminate_dlg;
     dlgb->get_dlg_expires = api_get_dlg_expires;
     dlgb->get_dlg = dlg_get_msg_dialog;
+    dlgb->release_dlg = dlg_release;
 
     return 1;
 }
@@ -361,7 +360,11 @@ static int mod_init(void) {
         LM_ERR("failed to register RPC commands\n");
         return -1;
     }
-
+    
+    if (dialog_ng_stats_init() != 0) {
+	LM_ERR("Failed to register dialog_ng counters\n");
+	return -1;
+    }
 
     if (faked_msg_init() < 0)
         return -1;
@@ -592,6 +595,7 @@ static void mod_destroy(void) {
     destroy_dlg_callbacks(DLGCB_CREATED | DLGCB_LOADED);
     destroy_dlg_handlers();
     destroy_dlg_profiles();
+    dialog_ng_stats_destroy();
 }
 
 static int w_set_dlg_profile(struct sip_msg *msg, char *profile, char *value) {
@@ -911,14 +915,53 @@ static void rpc_end_dlg_entry_id(rpc_t *rpc, void *c) {
     dlg = lookup_dlg(h_entry, h_id);
     if (dlg) {
         //dlg_bye_all(dlg, (rpc_extra_hdrs.len>0)?&rpc_extra_hdrs:NULL);
-        unref_dlg(dlg, 1);
-    }
+    unref_dlg(dlg, 1);
+}
 }*/
 
+static const char *rpc_end_dlg_entry_id_doc[2] = {
+    "End a given dialog based on [h_entry] [h_id]", 0
+};
+
+
+
+
+
+/* Wrapper for terminating dialog from API - from other modules */
+static void rpc_end_dlg_entry_id(rpc_t *rpc, void *c) {
+    unsigned int h_entry, h_id;
+    struct dlg_cell * dlg = NULL;
+    str rpc_extra_hdrs = {NULL,0};
+    int n;
+
+    n = rpc->scan(c, "dd", &h_entry, &h_id);
+    if (n < 2) {
+	    LM_ERR("unable to read the parameters (%d)\n", n);
+	    rpc->fault(c, 500, "Invalid parameters");
+	    return;
+    }
+    if(rpc->scan(c, "*S", &rpc_extra_hdrs)<1)
+    {
+	    rpc_extra_hdrs.s = NULL;
+	    rpc_extra_hdrs.len = 0;
+    }
+
+    dlg = lookup_dlg(h_entry, h_id);//increments ref count!
+    if(dlg==NULL) {
+	    rpc->fault(c, 404, "Dialog not found");
+	    return;
+    }
+
+    unref_dlg(dlg, 1);
+
+    dlg_terminate(dlg, NULL, NULL/*reason*/, 2, NULL);
+
+}
+
 
 static rpc_export_t rpc_methods[] = {
 	{"dlg2.list", rpc_print_dlgs, rpc_print_dlgs_doc, 0},
-    //{"dlg.end_dlg", rpc_end_dlg_entry_id, rpc_end_dlg_entry_id_doc, 0},
+        {"dlg2.end_dlg", rpc_end_dlg_entry_id, rpc_end_dlg_entry_id_doc, 0},
     {0, 0, 0, 0}
 };
 
diff --git a/modules/dialog_ng/dlg_cb.c b/modules/dialog_ng/dlg_cb.c
index ebbf5d6..3365e7b 100644
--- a/modules/dialog_ng/dlg_cb.c
+++ b/modules/dialog_ng/dlg_cb.c
@@ -235,7 +235,7 @@ void run_create_callbacks(struct dlg_cell *dlg, struct sip_msg *msg)
 {
 	struct dlg_callback *cb;
 
-	if (create_cbs==NULL || create_cbs->first==NULL)
+	if (create_cbs==NULL || create_cbs==POINTER_CLOSED_MARKER || create_cbs->first==NULL)
 		return;
 
 	params.req = msg;
diff --git a/modules/dialog_ng/dlg_db_handler.c b/modules/dialog_ng/dlg_db_handler.c
index 99fa7cd..226edb4 100644
--- a/modules/dialog_ng/dlg_db_handler.c
+++ b/modules/dialog_ng/dlg_db_handler.c
@@ -38,11 +38,13 @@
 #include "../../str.h"
 #include "../../socket_info.h"
 #include "../../lib/srutils/srjson.h"
+#include "../../lib/kcore/statistics.h"
 
 #include "dlg_hash.h"
 #include "dlg_var.h"
 #include "dlg_profile.h"
 #include "dlg_db_handler.h"
+#include "dlg_ng_stats.h"
 
 str id_column			= str_init(ID_COL);		// 0
 str h_entry_column		= str_init(HASH_ENTRY_COL);	// 1
@@ -123,8 +125,8 @@ static db1_con_t* dialog_db_handle    = 0; /* database connection handle */
 static db_func_t dialog_dbf;
 
 extern int dlg_enable_stats;
-extern int active_dlgs_cnt;
-extern int early_dlgs_cnt;
+
+extern struct dialog_ng_counters_h dialog_ng_cnts_h;
 
 #define GET_FIELD_IDX(_val, _idx)\
 		(_val + _idx)
@@ -546,10 +548,10 @@ static int load_dialog_info_from_db(int dlg_hash_size, int fetch_num_rows)
 			dlg->state 		= VAL_INT(GET_FIELD_IDX(values, DLGI_STATE_COL_IDX));
 
 			if (dlg->state==DLG_STATE_CONFIRMED) {
-				active_dlgs_cnt++;
+				counter_inc(dialog_ng_cnts_h.active);
 			}
 			else if (dlg->state==DLG_STATE_EARLY) {
-				early_dlgs_cnt++;
+				counter_inc(dialog_ng_cnts_h.active);
 			}
 
 			dlg->tl.timeout = (unsigned int)(VAL_INT(GET_FIELD_IDX(values, DLGI_TIMEOUT_COL_IDX)));
diff --git a/modules/dialog_ng/dlg_handlers.c b/modules/dialog_ng/dlg_handlers.c
index 95fc73d..96f7d3e 100644
--- a/modules/dialog_ng/dlg_handlers.c
+++ b/modules/dialog_ng/dlg_handlers.c
@@ -30,6 +30,7 @@
 #include "dlg_profile.h"
 #include "dlg_var.h"
 #include "dlg_db_handler.h"
+#include "dlg_ng_stats.h"
 
 static str rr_param; /*!< record-route parameter for matching */
 static int dlg_flag; /*!< flag for dialog tracking */
@@ -43,13 +44,7 @@ int spiral_detected = -1;
 
 extern struct rr_binds d_rrb; /*!< binding to record-routing module */
 extern struct tm_binds d_tmb;
-
-
-/* statistic variables */
-extern stat_var *early_dlgs; /*!< number of early dialogs */
-extern stat_var *processed_dlgs; /*!< number of processed dialogs */
-extern stat_var *expired_dlgs; /*!< number of expired dialogs */
-extern stat_var *failed_dlgs; /*!< number of failed dialogs */
+extern struct dialog_ng_counters_h dialog_ng_cnts_h;
 
 extern pv_elem_t *ruri_param_model; /*!< pv-string to get r-uri */
 
@@ -220,12 +215,11 @@ int populate_leg_info(struct dlg_cell *dlg, struct sip_msg *msg,
     } else {
         skip_recs = 0;
         /* was the 200 OK received or local generated */
-        /*skip_recs = dlg->from_rr_nb +
+        skip_recs = dlg->from_rr_nb +
                 ((t->relayed_reply_branch >= 0) ?
                 ((t->uac[t->relayed_reply_branch].flags & TM_UAC_FLAG_R2) ? 2 :
                 ((t->uac[t->relayed_reply_branch].flags & TM_UAC_FLAG_RR) ? 1 : 0))
                 : 0);
-         * */
     }
 
     if (msg->record_route) {
@@ -504,6 +498,10 @@ static void dlg_onreply(struct cell* t, int type, struct tmcb_params *param) {
 	if (dlg_db_mode == DB_MODE_REALTIME)
 	    update_dialog_dbinfo(dlg);
 
+	if (old_state != DLG_STATE_EARLY) {
+	    counter_inc(dialog_ng_cnts_h.early);
+	}
+
 	run_dlg_callbacks(DLGCB_EARLY, dlg, req, rpl, DLG_DIR_UPSTREAM, 0);
 	return;
     }
@@ -556,7 +554,11 @@ static void dlg_onreply(struct cell* t, int type, struct tmcb_params *param) {
         } else {
             ref_dlg(dlg, 1);
         }
-
+	
+	if (old_state == DLG_STATE_EARLY) 
+	    counter_add(dialog_ng_cnts_h.early, -1);
+	
+	counter_inc(dialog_ng_cnts_h.active);
         run_dlg_callbacks(DLGCB_CONFIRMED, dlg, req, rpl, DLG_DIR_UPSTREAM, 0);
 
         if (unref) unref_dlg(dlg, unref);
@@ -604,7 +606,9 @@ static void dlg_onreply(struct cell* t, int type, struct tmcb_params *param) {
         if (unref)
             unref_dlg(dlg, unref);
 
-        return;
+		if (old_state == DLG_STATE_EARLY)
+		    counter_add(dialog_ng_cnts_h.early, -1);
+		return;
     }
 
     if (unref) unref_dlg(dlg, unref);
@@ -1195,18 +1199,19 @@ void dlg_onroute(struct sip_msg* req, str *route_params, void *param) {
                     dlg->callid.len, dlg->callid.s,
                     dlg->from_tag.len, dlg->from_tag.s);
 
-        } else {
-            unref++;
-        }
-        /* dialog terminated (BYE) */
-        dlg_terminated(req, dlg, dir);
-        unref_dlg(dlg, unref);
-
+		} else {
+			unref++;
+		}
+		/* dialog terminated (BYE) */
+		dlg_terminated(req, dlg, dir);
+		unref_dlg(dlg, unref);
+		counter_add(dialog_ng_cnts_h.active, -1);
+		counter_inc(dialog_ng_cnts_h.processed);
         return;
     }
 
     if ((event == DLG_EVENT_REQ || event == DLG_EVENT_REQACK)
-            && new_state == DLG_STATE_CONFIRMED) {
+            && (new_state == DLG_STATE_CONFIRMED || new_state==DLG_STATE_EARLY)) {
 
         timeout = get_dlg_timeout(req);
         if (timeout != default_timeout) {
@@ -1288,9 +1293,8 @@ void dlg_ontimeout(struct dlg_tl *tl) {
         }
     }
 
-    if ((dlg->dflags & DLG_FLAG_TOBYE)
-            && (dlg->state == DLG_STATE_CONFIRMED)) {
-        //TODO: dlg_bye_all(dlg, NULL);
+    if (dlg->state == DLG_STATE_CONFIRMED) {
+        dlg_bye_all(dlg, NULL);
         unref_dlg(dlg, 1);
         return;
     }
@@ -1302,11 +1306,12 @@ void dlg_ontimeout(struct dlg_tl *tl) {
                 dlg->callid.len, dlg->callid.s,
                 dlg->from_tag.len, dlg->from_tag.s);
 
-
-        /* dialog timeout */
-        run_dlg_callbacks(DLGCB_EXPIRED, dlg, NULL, NULL, DLG_DIR_NONE, 0);
-
-        unref_dlg(dlg, unref + 1);
+		/* dialog timeout */
+		run_dlg_callbacks(DLGCB_EXPIRED, dlg, NULL, NULL, DLG_DIR_NONE, 0);
+		unref_dlg(dlg, unref + 1);
+		counter_add(dialog_ng_cnts_h.active, -1);
+		counter_inc(dialog_ng_cnts_h.expired);
+		counter_inc(dialog_ng_cnts_h.processed);
     } else {
         unref_dlg(dlg, 1);
     }
@@ -1410,6 +1415,7 @@ void internal_print_all_dlg(struct dlg_cell *dlg) {
         LM_DBG("Dialog out callee cseq: %.*s\n", dlg_out->callee_cseq.len, dlg_out->callee_cseq.s);
         LM_DBG("Dialog out callee contact: %.*s\n", dlg_out->callee_contact.len, dlg_out->callee_contact.s);
         LM_DBG("Dialog out callee route set: %.*s\n", dlg_out->callee_route_set.len, dlg_out->callee_route_set.s);
+        LM_DBG("Dialog out state (deleted): %i\n", dlg_out->deleted);
 
         LM_DBG("----------");
         dlg_out = dlg_out->next;
diff --git a/modules/dialog_ng/dlg_hash.c b/modules/dialog_ng/dlg_hash.c
index 763b225..ed72279 100644
--- a/modules/dialog_ng/dlg_hash.c
+++ b/modules/dialog_ng/dlg_hash.c
@@ -1052,7 +1052,7 @@ static inline void log_next_state_dlg(const int event, const struct dlg_cell * d
 void next_state_dlg(struct dlg_cell *dlg, int event,
         int *old_state, int *new_state, int *unref, str * to_tag) {
     struct dlg_entry *d_entry;
-
+    
 
 
     d_entry = &(d_table->entries[dlg->h_entry]);
@@ -1067,15 +1067,32 @@ void next_state_dlg(struct dlg_cell *dlg, int event,
     struct dlg_cell_out *dlg_out;
     dlg_out = d_entry_out->first;
     int found = -1;
+    int delete = 1;
 
     switch (event) {
         case DLG_EVENT_TDEL:
             switch (dlg->state) {
                 case DLG_STATE_UNCONFIRMED:
                 case DLG_STATE_EARLY:
-                    dlg->state = DLG_STATE_DELETED;
-                    unref_dlg_unsafe(dlg, 1, d_entry);
-                    *unref = 1;
+		    if (to_tag) {
+                        LM_DBG("Going to check if there is another active branch - we only change state to DELETED if there are no other active branches\n");
+                        while (dlg_out) {
+                            if (dlg_out->to_tag.len != to_tag->len || memcmp(dlg_out->to_tag.s, to_tag->s, dlg_out->to_tag.len) != 0) {
+				if(dlg_out->deleted != 1) {
+				    LM_DBG("Found a dlg_out that is not for this event and is not in state deleted, therefore there is another active branch\n");
+				    delete = 0;
+                                    //we should delete this dlg_out tho...
+                                    dlg_out->deleted=1;
+				}
+                            }
+                            dlg_out = dlg_out->next;
+                        }
+                    } 
+		    if(delete) {
+			dlg->state = DLG_STATE_DELETED;
+			unref_dlg_unsafe(dlg, 1, d_entry);
+			*unref = 1;
+		    }
                     break;
                 case DLG_STATE_CONFIRMED:
                     unref_dlg_unsafe(dlg, 1, d_entry);
@@ -1091,7 +1108,7 @@ void next_state_dlg(struct dlg_cell *dlg, int event,
             switch (dlg->state) {
                 case DLG_STATE_UNCONFIRMED:
                 case DLG_STATE_EARLY:
-                    dlg->state = DLG_STATE_EARLY;
+		    dlg->state = DLG_STATE_EARLY;
                     break;
                 default:
                     log_next_state_dlg(event, dlg);
@@ -1101,8 +1118,22 @@ void next_state_dlg(struct dlg_cell *dlg, int event,
             switch (dlg->state) {
                 case DLG_STATE_UNCONFIRMED:
                 case DLG_STATE_EARLY:
-                    dlg->state = DLG_STATE_DELETED;
-                    *unref = 1;
+		    if (to_tag) {
+                        LM_DBG("Going to check if there is another active branch - we only change state to DELETED if there are no other active branches\n");
+                        while (dlg_out) {
+                            if (dlg_out->to_tag.len != to_tag->len || memcmp(dlg_out->to_tag.s, to_tag->s, dlg_out->to_tag.len) != 0) {
+				if(dlg_out->deleted != 1) {
+				    LM_DBG("Found a dlg_out that is not for this event and is not in state deleted, therefore there is another active branch\n");
+				    delete = 0;
+				}
+                            }
+                            dlg_out = dlg_out->next;
+                        }
+                    } 
+		    if(delete) {
+			dlg->state = DLG_STATE_DELETED;
+			*unref = 1;
+		    }
                     break;
                 default:
                     log_next_state_dlg(event, dlg);
@@ -1716,6 +1747,18 @@ error:
     return NULL;
 }
 
+/*!
+ * \brief decrement dialog ref counter by 1
+ * \see dlg_unref
+ * \param dlg dialog
+ */
+void dlg_release(struct dlg_cell *dlg)
+{
+	if(dlg==NULL)
+		return;
+	unref_dlg(dlg, 1);
+}
+
 time_t api_get_dlg_expires(str *callid, str *ftag, str *ttag) {
     struct dlg_cell *dlg;
     time_t expires = 0;
diff --git a/modules/dialog_ng/dlg_hash.h b/modules/dialog_ng/dlg_hash.h
index 9efc3a0..2a5fe5d 100644
--- a/modules/dialog_ng/dlg_hash.h
+++ b/modules/dialog_ng/dlg_hash.h
@@ -610,6 +610,8 @@ int update_dlg_did(struct dlg_cell *dlg, str *new_did);
 
 time_t api_get_dlg_expires(str *callid, str *ftag, str *ttag);
 
+void dlg_release(struct dlg_cell *dlg);
+
 char* state_to_char(unsigned int state);
 
 #endif
diff --git a/modules/dialog_ng/dlg_load.h b/modules/dialog_ng/dlg_load.h
index cbdf94e..8de4c43 100644
--- a/modules/dialog_ng/dlg_load.h
+++ b/modules/dialog_ng/dlg_load.h
@@ -43,15 +43,18 @@ typedef struct dlg_cell *(*get_dlg_f)(struct sip_msg *msg);
 /* get_dlg_lifetime function prototype */
 typedef time_t (*get_dlg_expires_f)(str *callid, str *ftag, str *ttag);
 
+typedef void (*release_dlg_f)(struct dlg_cell *dlg);
+
 struct dlg_binds {
 	register_dlgcb_f  		register_dlgcb;
-	register_dlgcb_nodlg_f 	register_dlgcb_nodlg;
+	register_dlgcb_nodlg_f          register_dlgcb_nodlg;
 	terminate_dlg_f 		terminate_dlg;
-	lookup_terminate_dlg_f 	lookup_terminate_dlg;
+	lookup_terminate_dlg_f          lookup_terminate_dlg;
 	set_dlg_variable_f 		set_dlg_var;
 	get_dlg_variable_f 		get_dlg_var;
 	get_dlg_expires_f 		get_dlg_expires;
-	get_dlg_f				get_dlg;
+	get_dlg_f			get_dlg;
+        release_dlg_f                   release_dlg;
 };
 
 
diff --git a/modules/dialog_ng/dlg_ng_stats.c b/modules/dialog_ng/dlg_ng_stats.c
new file mode 100644
index 0000000..bbfd961
--- /dev/null
+++ b/modules/dialog_ng/dlg_ng_stats.c
@@ -0,0 +1,34 @@
+#include "dlg_ng_stats.h"
+
+struct dialog_ng_counters_h dialog_ng_cnts_h;
+
+/* dialog_ng counters definitions */
+counter_def_t dialog_ng_cnt_defs[] =  {
+	{&dialog_ng_cnts_h.active, "active", 0, 0, 0,
+		"number of current active (answered) dialogs"},
+	{&dialog_ng_cnts_h.early, "early", 0, 0, 0,
+		"number of current early dialogs"},
+	{&dialog_ng_cnts_h.expired, "expired", 0, 0, 0,
+		"number of expired dialogs (forcibly killed)"},
+	{&dialog_ng_cnts_h.processed, "processed", 0, 0, 0,
+		"number of processed dialogs"},
+	{0, 0, 0, 0, 0, 0 }
+};
+
+/** intialize dialog_ng statistics.
+ * @return < 0 on errror, 0 on success.
+ */
+int dialog_ng_stats_init()
+{
+	if (counter_register_array("dialog_ng", dialog_ng_cnt_defs) < 0)
+		goto error;
+	return 0;
+error:
+	return -1;
+}
+
+
+void dialog_ng_stats_destroy()
+{
+	/* do nothing */
+}
\ No newline at end of file
diff --git a/modules/dialog_ng/dlg_ng_stats.h b/modules/dialog_ng/dlg_ng_stats.h
new file mode 100644
index 0000000..b9ed67f
--- /dev/null
+++ b/modules/dialog_ng/dlg_ng_stats.h
@@ -0,0 +1,17 @@
+#ifndef DIALOG_NG_STATS_H
+#define	DIALOG_NG_STATS_H
+
+#include "../../counters.h"
+
+struct dialog_ng_counters_h {
+    counter_handle_t active;
+    counter_handle_t early;
+    counter_handle_t expired;
+    counter_handle_t processed;
+
+};
+
+int dialog_ng_stats_init();
+void dialog_ng_stats_destroy();
+
+#endif	/* DIALOG_NG_STATS_H */
\ No newline at end of file
diff --git a/modules/dialog_ng/dlg_req_within.h b/modules/dialog_ng/dlg_req_within.h
index 69a7e2f..2055509 100644
--- a/modules/dialog_ng/dlg_req_within.h
+++ b/modules/dialog_ng/dlg_req_within.h
@@ -43,8 +43,6 @@
 #define MI_DLG_OPERATION_ERR_LEN	(sizeof(MI_DLG_OPERATION_ERR)-1)
 
 extern struct tm_binds d_tmb;
-//extern int dlg_enable_stats;
-//extern stat_var * active_dlgs;
 
 struct mi_root * mi_terminate_dlg(struct mi_root *cmd_tree, void *param );
 
diff --git a/modules/dialplan/Makefile b/modules/dialplan/Makefile
index 987ddf7..bda9364 100644
--- a/modules/dialplan/Makefile
+++ b/modules/dialplan/Makefile
@@ -1,4 +1,3 @@
-# $Id:$
 #
 # WARNING: do not run this directly, it should be run by the master Makefile
 
diff --git a/modules/dialplan/README b/modules/dialplan/README
index 037309d..88cc07b 100644
--- a/modules/dialplan/README
+++ b/modules/dialplan/README
@@ -12,9 +12,15 @@ Edited by
 
 Juha Heinanen
 
+Edited by
+
+Olle E. Johansson
+
    Copyright � 2007-2008 Voice Sistem SRL
 
    Copyright � 2008-2010 Juha Heinanen
+
+   Copyright � 2014 Olle E. Johansson, Edvina AB
      __________________________________________________________________
 
    Table of Contents
@@ -43,6 +49,7 @@ Juha Heinanen
               5.10. attrs_col (string)
               5.11. attrs_pvar (string)
               5.12. fetch_rows (int)
+              5.13. match_dynamic (int)
 
         6. Functions
 
@@ -55,8 +62,9 @@ Juha Heinanen
 
         8. Exported RPC Commands
 
-              8.1. dialplan.reload
-              8.2. dialplan.translate
+              8.1. dialplan.dump
+              8.2. dialplan.reload
+              8.3. dialplan.translate
 
         9. Installation
 
@@ -76,9 +84,10 @@ Juha Heinanen
    1.10. Set attrs_col parameter
    1.11. Set attrs_pvar parameter
    1.12. Set fetch_rows parameter
-   1.13. dp_translate usage
+   1.13. Set match_dynamic parameter
    1.14. dp_translate usage
-   1.15. Example of rules
+   1.15. dp_translate usage
+   1.16. Example of rules
 
 Chapter 1. Admin Guide
 
@@ -106,6 +115,7 @@ Chapter 1. Admin Guide
         5.10. attrs_col (string)
         5.11. attrs_pvar (string)
         5.12. fetch_rows (int)
+        5.13. match_dynamic (int)
 
    6. Functions
 
@@ -118,8 +128,9 @@ Chapter 1. Admin Guide
 
    8. Exported RPC Commands
 
-        8.1. dialplan.reload
-        8.2. dialplan.translate
+        8.1. dialplan.dump
+        8.2. dialplan.reload
+        8.3. dialplan.translate
 
    9. Installation
 
@@ -127,30 +138,39 @@ Chapter 1. Admin Guide
 
    This module implements generic string translations based on matching
    and replacement rules. It can be used to manipulate the request URI or
-   a PV and to translate to a new format/value.
+   a PV and to translate it to a new format/value. Dialplan can also be
+   used to match a given URI and retrieve a set of attributes based on the
+   match. It is a very flexible module that can be used to handle call
+   routing, prefix rewrites and much more.
 
 2. How it works
 
-   At startup, the module will load a set of transformation rules from a
-   database. Rules are grouped into dialplans. Every database row will be
-   stored in memory as a translation rule. Each rule will describe how the
-   matching will be made, how the input value will be modified and which
-   attributes that will be set for the matching transformation.
+   At startup the module will load a set of matching and transformation
+   rules from a database. Rules are grouped into dialplans. Every database
+   row will be stored in memory as a dialplan rule. Each rule will
+   describe how the matching will be made, how the input value will be
+   modified and which attributes that will be set for the matching
+   transformation.
 
    The module expects an input value which will be matched against a rule
    by using regular expressions (see 'man pcresyntax' for syntax), string
    or fnmatch (see 'man fnmatch') matching. Overlapping matching
-   expressions can be controlled via priorities. Once a rule is matched,
-   the defined transformation (if any) is applied and the result is
-   returned as output value. Also, if any string attribute is associated
-   to the rule, this will be returned to the script along with the output
-   value. This can be used to identify the used rule.
+   expressions can be controlled via priorities. One priority can have
+   multiple dialplan entries. Priorities need not be numbered with
+   consecutive numbers. The next higher priority will be used after trying
+   to match all entries in one priority.
+
+   Once a rule is matched, the defined transformation (if any) is applied
+   and the result is returned as output value. Also, if any string
+   attribute is associated to the rule, this will be returned to the
+   script along with the output value. This can be used to identify the
+   used rule.
 
    The first matching rule will be processed.
 
 3. Dialplan use cases
 
-   The module can be used to implement multiple dialplans - do to
+   The module can be used to implement multiple dialplans - to do
    auto-completion of dialed numbers (like national to international), to
    convert generic numbers to specific numbers (like for emergency
    numbers).
@@ -196,6 +216,7 @@ Chapter 1. Admin Guide
    5.10. attrs_col (string)
    5.11. attrs_pvar (string)
    5.12. fetch_rows (int)
+   5.13. match_dynamic (int)
 
 5.1. db_url (string)
 
@@ -334,6 +355,24 @@ modparam("dialplan", "attrs_pvar", "$avp(s:dest)")
 modparam("dialplan", "fetch_rows", 4000)
 ...
 
+5.13. match_dynamic (int)
+
+   If set to 1, the match and substitution expressions can include script
+   variables and their values are evaluated at runtime.
+
+   During the loading process, the values that contain variables are no
+   longer pre-compiled to PCRE structure in memory, because the values
+   change at runtime, thus expect slightly slower performances. Values
+   without script variables are pre-compiled even if this parameter is
+   enabled.
+
+   Default value is "0" (disabled).
+
+   Example 1.13. Set match_dynamic parameter
+...
+modparam("dialplan", "match_dynamic", 1)
+...
+
 6. Functions
 
    6.1. dp_translate(id, [src[/dest]])
@@ -373,13 +412,13 @@ modparam("dialplan", "fetch_rows", 4000)
 
    This function can be used from ANY_ROUTE.
 
-   Example 1.13. dp_translate usage
+   Example 1.14. dp_translate usage
 ...
 dp_translate("240", "$ruri.user/$avp(s:dest)");
 xlog("translated to var $avp(s:dest) \n");
 ...
 
-   Example 1.14. dp_translate usage
+   Example 1.15. dp_translate usage
 ...
 $avp(s:src) = $ruri.user;
 dp_translate("$var(x)", "$avp(s:src)/$var(y)");
@@ -422,10 +461,22 @@ xlog("translated to var $var(y) \n");
 
 8. Exported RPC Commands
 
-   8.1. dialplan.reload
-   8.2. dialplan.translate
+   8.1. dialplan.dump
+   8.2. dialplan.reload
+   8.3. dialplan.translate
+
+8.1. dialplan.dump
+
+   Dumps the content of one dialplan ID
+
+   Name: dialplan.dump
+
+   Parameters: Dialplan ID
+
+   Example:
+                kamcmd dialplan.dump 100
 
-8.1. dialplan.reload
+8.2. dialplan.reload
 
    Forces an update of the translation rules from the database.
 
@@ -436,7 +487,7 @@ xlog("translated to var $var(y) \n");
    Example:
                 kamcmd dialplan.reload
 
-8.2. dialplan.translate
+8.3. dialplan.translate
 
    Will apply a translation rule identified by a dialplan id and an input
    string.
@@ -462,12 +513,12 @@ xlog("translated to var $var(y) \n");
    Some sample records from a dialplan table are presented in the next
    figure.
 
-   Example 1.15. Example of rules
+   Example 1.16. Example of rules
 ...
 dpid: 1
 pr: 1
 match_op: 1
-match_exp: ^0([1-9][0-9]+)$
+match_exp: ^0[1-9][0-9]+$
 match_len: 0
 subst_exp: ^0([1-9][0-9]+)$
 repl_exp: 0049\1
@@ -476,7 +527,7 @@ attrs: de
 dpid: 1
 pr: 2
 match_op: 1
-match_exp: ^0([1-9][0-9]+)$
+match_exp: ^0[1-9][0-9]+$
 match_len: 0
 subst_exp: ^0(.+)$
 repl_exp: $var(prefix)\1
@@ -490,9 +541,10 @@ attrs: xyz
    private variables ($var(...)) and AVPs with static name are among those
    that are safe to use in replacement expressions.
 
-   The match_op field specify matching operator, valid values: 0 - string
-   comparison; 1 - regular expression matching (pcre); 2 - fnmatch
-   (shell-like pattern) matching.
+   The match_op field specify matching operator, valid values:
+     * 0 - string comparison;
+     * 1 - regular expression matching (pcre);
+     * 2 - fnmatch (shell-like pattern) matching.
 
 Chapter 2. Developer's Guide
 
diff --git a/modules/dialplan/dialplan.c b/modules/dialplan/dialplan.c
index ebbd6bd..9a7fe33 100644
--- a/modules/dialplan/dialplan.c
+++ b/modules/dialplan/dialplan.c
@@ -1,18 +1,18 @@
 /*
- *  $Id$
- *
  * Copyright (C)  2007-2008 Voice Sistem SRL
  *
  * Copyright (C)  2008 Juha Heinanen
  *
- * This file is part of SIP-router, a free SIP server.
+ * Copyright (C)  2014 Olle E. Johansson, Edvina AB
+ *
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -21,20 +21,16 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2007-08-01 initial version (ancuta onofrei)
- *  2008-10-09 module is now using pcre regexp lib (juha heinanen)
  */
 
 /*!
  * \file
- * \brief SIP-router dialplan :: Module interface
+ * \brief Kamailio dialplan :: Module interface
  * \ingroup dialplan
  * Module: \ref dialplan
  */
 
-/*! \defgroup dialplan SIP-router dialplan transformations module
+/*! \defgroup dialplan Kamailio dialplan transformations module
  *
  */
 
@@ -64,7 +60,7 @@
 
 MODULE_VERSION
 
-#define DEFAULT_PARAM    "$ruri.user"
+#define DEFAULT_PARAM    "$rU"
 
 static int mod_init(void);
 static int child_init(int rank);
@@ -85,6 +81,7 @@ str default_param_s = str_init(DEFAULT_PARAM);
 dp_param_p default_par2 = NULL;
 
 int dp_fetch_rows = 1000;
+int dp_match_dynamic = 0;
 
 static param_export_t mod_params[]={
 	{ "db_url",			PARAM_STR,	&dp_db_url },
@@ -97,8 +94,9 @@ static param_export_t mod_params[]={
 	{ "subst_exp_col",	PARAM_STR,	&subst_exp_column },
 	{ "repl_exp_col",	PARAM_STR,	&repl_exp_column },
 	{ "attrs_col",		PARAM_STR,	&attrs_column },
-	{ "attrs_pvar",	    PARAM_STR,	&attr_pvar_s},
-	{ "fetch_rows",		INT_PARAM,	&dp_fetch_rows},
+	{ "attrs_pvar",	    PARAM_STR,	&attr_pvar_s },
+	{ "fetch_rows",		PARAM_INT,	&dp_fetch_rows },
+	{ "match_dynamic",	PARAM_INT,	&dp_match_dynamic },
 	{0,0,0}
 };
 
@@ -165,7 +163,7 @@ static int mod_init(void)
 	}
 	memset(default_par2, 0, sizeof(dp_param_t));
 
-	/* A.Spiridonov: Some weird sections with default_param processing */
+	/* emulate "$rU/$rU" as second parameter for dp_translate() */
 	default_param_s.len = strlen(default_param_s.s);
 	default_par2->v.sp[0] = pv_cache_get(&default_param_s);
 	if (default_par2->v.sp[0]==NULL) {
@@ -179,7 +177,6 @@ static int mod_init(void)
 		LM_ERR("output pv is invalid\n");
 		return -1;
 	}
-	/* End of weird sections */
 
 	if(dp_fetch_rows<=0)
 		dp_fetch_rows = 1000;
@@ -342,7 +339,7 @@ static int dp_translate_f(struct sip_msg* msg, char* str1, char* str2)
 	LM_DBG("input %.*s with dpid %i => output %.*s\n",
 			input.len, input.s, idp->dp_id, output.len, output.s);
 
-	/*set the output*/
+	/* set the output */
 	if (dp_update(msg, repl_par->v.sp[0], repl_par->v.sp[1],
 				&output, attrs_par) !=0){
 		LM_ERR("cannot set the output\n");
@@ -656,12 +653,108 @@ static void dialplan_rpc_translate(rpc_t* rpc, void* ctx)
 	return;
 }
 
+/*
+ * RPC command to dump dialplan 
+ */
+static void dialplan_rpc_dump(rpc_t* rpc, void* ctx)
+{
+	dpl_id_p idp;
+	dpl_index_p indexp;
+	dpl_node_p rulep;
+	int dpid;
+	void* th;
+	void* ih;
+	void* sh;
+
+	if (rpc->scan(ctx, "d", &dpid) < 1)
+	{
+		rpc->fault(ctx, 500, "Missing parameter");
+		return;
+	}
+
+	if ((idp = select_dpid(dpid)) == 0 ) {
+		LM_ERR("no information available for dpid %i\n", dpid);
+		rpc->fault(ctx, 500, "Dialplan ID not matched");
+		return;
+	}
+
+	LM_DBG("trying to dump dpid %i\n", idp->dp_id);
+
+	/* add entry node */
+	if (rpc->add(ctx, "{", &th) < 0)
+	{
+		rpc->fault(ctx, 500, "Internal error root reply");
+		return;
+	}
+
+	if(rpc->struct_add(th, "d[",
+				"DPID",  dpid,
+				"ENTRIES", &ih)<0)
+	{
+		rpc->fault(ctx, 500, "Internal error sets structure");
+		return;
+	}
+
+	for(indexp=idp->first_index; indexp!=NULL;indexp=indexp->next) {
+		LM_DBG("INDEX LEN: %i\n", indexp->len);
+                for(rulep = indexp->first_rule; rulep!= NULL;rulep = rulep->next) {
+			LM_DBG("DPID: %i PRIO : %i\n", rulep->dpid, rulep->pr);
+			if (rpc->struct_add(ih, "{","ENTRY", &sh) < 0)
+			{
+				rpc->fault(ctx, 500, "Internal error root reply");
+				return;
+			}
+
+			if (rpc->struct_add(sh, "dd", "PRIO", rulep->pr, 
+				"MATCHOP", rulep->matchop)<0)
+			{
+				rpc->fault(ctx, 500, "Internal error adding prio");
+				return;
+			}
+			if (rpc->struct_add(sh, "s", "MATCHEXP", rulep->match_exp) < 0 )
+			{
+				rpc->fault(ctx, 500, "Internal error adding match exp");
+				return;
+			}
+			if (rpc->struct_add(sh, "d", "MATCHLEN", rulep->matchlen) < 0 )
+			{
+				rpc->fault(ctx, 500, "Internal error adding expression data and attribute");
+				return;
+			}
+			if (rpc->struct_add(sh, "s", "SUBSTEXP", rulep->subst_exp) < 0 )
+			{
+				rpc->fault(ctx, 500, "Internal error adding subst exp");
+				return;
+			}
+			if (rpc->struct_add(sh, "s", "REPLEXP", rulep->repl_exp) < 0 )
+			{
+				rpc->fault(ctx, 500, "Internal error adding replace exp ");
+				return;
+			}
+			if (rpc->struct_add(sh, "s", "ATTRS", rulep->attrs) < 0 )
+			{
+				rpc->fault(ctx, 500, "Internal error adding attribute");
+				return;
+			}
+		}
+	}
+
+	return;
+}
+
+static const char* dialplan_rpc_dump_doc[2] = {
+	"Dump dialplan content",
+	0
+};
+
 
 rpc_export_t dialplan_rpc_list[] = {
 	{"dialplan.reload", dialplan_rpc_reload,
 		dialplan_rpc_reload_doc, 0},
 	{"dialplan.translate",   dialplan_rpc_translate,
 		dialplan_rpc_translate_doc, 0},
+	{"dialplan.dump",   dialplan_rpc_dump,
+		dialplan_rpc_dump_doc, 0},
 	{0, 0, 0, 0}
 };
 
diff --git a/modules/dialplan/dialplan.h b/modules/dialplan/dialplan.h
index f033474..a1df18f 100644
--- a/modules/dialplan/dialplan.h
+++ b/modules/dialplan/dialplan.h
@@ -1,17 +1,14 @@
-
 /*
- * $Id$
- *
  * Copyright (C)  2007-2008 Voice Sistem SRL
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -20,14 +17,11 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2007-08-01 initial version (ancuta onofrei)
  */
 
 /*!
  * \file
- * \brief SIP-router dialplan :: Module interface
+ * \brief Kamailio dialplan :: Module interface
  * \ingroup dialplan
  * Module: \ref dialplan
  */
@@ -46,18 +40,25 @@
 
 #define MAX_REPLACE_WITH	10
 
-typedef struct dpl_node{
-	int dpid;
-	int pr;
-	int matchop;
-	int matchlen;
-	str match_exp, subst_exp, repl_exp; /*keeping the original strings*/
-	pcre *match_comp, *subst_comp; /*compiled patterns*/
-	struct subst_expr * repl_comp; 
-	str attrs;
-
-	struct dpl_node * next; /*next rule*/
-}dpl_node_t, *dpl_node_p;
+#define DP_TFLAGS_PV_MATCH		(1 << 0)
+#define DP_TFLAGS_PV_SUBST		(1 << 1)
+
+typedef struct dpl_node {
+	int dpid;         /* dialplan id */
+	int pr;           /* priority */
+	int matchop;      /* matching operator */
+	int matchlen;     /* matching value length */
+	str match_exp;    /* match-first string */
+	str subst_exp;    /* match string with subtitution groupping */
+	str repl_exp;     /* replacement expression string */
+	pcre *match_comp; /* compiled matching expression */
+	pcre *subst_comp; /* compiled substitution expression */
+	struct subst_expr *repl_comp; /* compiled replacement */
+	str attrs;        /* attributes string */
+	unsigned int tflags; /* flags for type of values for matching */
+
+	struct dpl_node * next; /* next rule */
+} dpl_node_t, *dpl_node_p;
 
 /*For every distinct length of a matching string*/
 typedef struct dpl_index{
@@ -96,5 +97,7 @@ dpl_id_p select_dpid(int id);
 struct subst_expr* repl_exp_parse(str subst);
 void repl_expr_free(struct subst_expr *se);
 int translate(struct sip_msg *msg, str user_name, str* repl_user, dpl_id_p idp, str *);
-int rule_translate(struct sip_msg *msg, str , dpl_node_t * rule,  str *);
+int rule_translate(struct sip_msg *msg, str , dpl_node_t * rule, pcre *subst_comp,  str *);
+
+pcre *reg_ex_comp(const char *pattern, int *cap_cnt, int mtype);
 #endif
diff --git a/modules/dialplan/doc/dialplan.xml b/modules/dialplan/doc/dialplan.xml
index ddaf1ab..386e7eb 100644
--- a/modules/dialplan/doc/dialplan.xml
+++ b/modules/dialplan/doc/dialplan.xml
@@ -32,6 +32,10 @@
 		<firstname>Juha</firstname>
 		<surname>Heinanen</surname>
 		</editor>
+		<editor>
+		<firstname>Olle E.</firstname>
+		<surname>Johansson</surname>
+		</editor>
 	</authorgroup>
 	<copyright>
 		<year>2007-2008</year>
@@ -41,6 +45,10 @@
 		<year>2008-2010</year>
 		<holder>Juha Heinanen</holder>
 	</copyright>
+	<copyright>
+		<year>2014</year>
+		<holder>Olle E. Johansson, Edvina AB</holder>
+	</copyright>
 	</bookinfo>
 	<toc></toc>
 	
diff --git a/modules/dialplan/doc/dialplan_admin.xml b/modules/dialplan/doc/dialplan_admin.xml
index 3f84002..5bfa870 100644
--- a/modules/dialplan/doc/dialplan_admin.xml
+++ b/modules/dialplan/doc/dialplan_admin.xml
@@ -18,16 +18,19 @@
 	<para>
 	This module implements generic string translations based on matching and
 	replacement rules. It can be used to manipulate the request URI or a PV and to 
-	translate to a new format/value.
+	translate it to a new format/value. Dialplan can also be used to match
+	a given URI and retrieve a set of attributes based on the match. It is a very
+	flexible module that can be used to handle call routing, prefix rewrites
+	and much more.
 	</para>
 	</section>
 
 	<section id="dialplan.introduction">
 	<title>How it works</title>
 	<para>
-	At startup, the module will load a set of transformation rules from a 
+	At startup the module will load a set of matching and transformation rules from a 
 	database. Rules are grouped into dialplans. Every database row will be
-	stored in memory as a translation rule. Each rule will describe how the 
+	stored in memory as a dialplan rule. Each rule will describe how the 
 	matching will be made, how the input value will be modified and which 
 	attributes that will be set for the matching transformation.
 	</para>
@@ -35,7 +38,12 @@
 	The module expects an input value which will be matched against a rule
 	by using regular expressions (see 'man pcresyntax' for syntax), string
 	or fnmatch (see 'man fnmatch') matching. Overlapping matching expressions
-	can be controlled via priorities. 
+	can be controlled via priorities. One priority can have multiple
+	dialplan entries. Priorities need not be numbered with consecutive
+	numbers. The next higher priority will be used after trying to match all 
+	entries in one priority.
+	</para>
+	<para>
 	Once a rule is matched, the defined transformation (if any) is applied and 
 	the result is returned as output value. Also, if any string attribute is 
 	associated to the rule, this will be returned to the script along with
@@ -49,7 +57,7 @@
 	<section id="dialplan.usecases">
 	<title>Dialplan use cases</title>
 	<para>
-	The module can be used to implement multiple dialplans - do to 
+	The module can be used to implement multiple dialplans - to do
 	auto-completion of dialed numbers (like national to international),
 	to convert generic numbers to specific numbers (like for emergency numbers).
 	</para>
@@ -61,8 +69,8 @@
 	<para>
 	Non-SIP string translation can be implemented - like converting country 
 	names from all possible formats to a canonical format:
-	(UK, England, United Kingdom) -> GB.
-	</para>
+	<emphasis>(UK, England, United Kingdom) -> GB.
+	</emphasis></para>
 	<para>
 	Any other string-base translation or detection for whatever other purposes.
 	</para>
@@ -351,6 +359,34 @@ modparam("dialplan", "fetch_rows", 4000)
 		</example>
 	</section>
 
+	<section id="dialplan.p.match_dynamic">
+		<title><varname>match_dynamic</varname> (int)</title>
+		<para>
+		If set to 1, the match and substitution expressions can
+		include script variables and their values are evaluated at
+		runtime.
+		</para>
+		<para>
+		During the loading process, the values that contain
+		variables are no longer pre-compiled to PCRE structure in
+		memory, because the values change at runtime, thus expect slightly
+		slower performances. Values without script variables are pre-compiled
+		even if this parameter is enabled.
+		</para>
+		<para>
+		<emphasis>
+			Default value is <quote>0</quote> (disabled).
+		</emphasis>
+		</para>
+		<example>
+		<title>Set <varname>match_dynamic</varname> parameter</title>
+		<programlisting format="linespecific">
+...
+modparam("dialplan", "match_dynamic", 1)
+...
+		</programlisting>
+		</example>
+	</section>
 
 	</section>
 
@@ -517,6 +553,22 @@ xlog("translated to var $var(y) \n");
 	<section>
 	<title>Exported RPC Commands</title>
 
+		<section id="dialplan.r.dp.dump">
+			<title><varname>dialplan.dump</varname></title>
+			<para>
+			Dumps the content of one dialplan ID
+			</para>
+			<para>
+			Name: <emphasis>dialplan.dump</emphasis>
+			</para>
+			<para>Parameters: <emphasis>Dialplan ID</emphasis></para>
+			<para>
+			Example:
+			</para>
+        <programlisting  format="linespecific">
+		&sercmd; dialplan.dump 100
+		</programlisting>
+		</section>
 		<section id="dialplan.r.dp.reload">
 			<title><varname>dialplan.reload</varname></title>
 			<para>
@@ -582,7 +634,7 @@ xlog("translated to var $var(y) \n");
 dpid: 1
 pr: 1
 match_op: 1
-match_exp: ^0([1-9][0-9]+)$
+match_exp: ^0[1-9][0-9]+$
 match_len: 0
 subst_exp: ^0([1-9][0-9]+)$
 repl_exp: 0049\1
@@ -591,7 +643,7 @@ attrs: de
 dpid: 1
 pr: 2
 match_op: 1
-match_exp: ^0([1-9][0-9]+)$
+match_exp: ^0[1-9][0-9]+$
 match_len: 0
 subst_exp: ^0(.+)$
 repl_exp: $var(prefix)\1
@@ -609,8 +661,17 @@ attrs: xyz
 		</para>
 		<para>
 		The match_op field specify matching operator, valid values:
-		0 - string comparison; 1 - regular expression matching (pcre);
+        	<itemizedlist>
+               	<listitem>
+		0 - string comparison; 
+               	</listitem>
+               	<listitem>
+		1 - regular expression matching (pcre);
+               	</listitem>
+               	<listitem>
 		2 - fnmatch (shell-like pattern) matching.
+               	</listitem>
+        	</itemizedlist>
 		</para>
     </section>
 
diff --git a/modules/dialplan/dp_db.c b/modules/dialplan/dp_db.c
index 1db9d7d..a61efb1 100644
--- a/modules/dialplan/dp_db.c
+++ b/modules/dialplan/dp_db.c
@@ -1,16 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C)  2007-2008 Voice Sistem SRL
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -19,15 +17,11 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2007-08-01 initial version (ancuta onofrei)
- *  2008-10-09 module is now using pcre regexp lib (juha heinanen)
  */
 
 /*!
  * \file
- * \brief SIP-router dialplan :: database interface
+ * \brief Kamailio dialplan :: database interface
  * \ingroup dialplan
  * Module: \ref dialplan
  */
@@ -55,6 +49,7 @@ str repl_exp_column =   str_init(REPL_EXP_COL);
 str attrs_column    =   str_init(ATTRS_COL); 
 
 extern int dp_fetch_rows;
+extern int dp_match_dynamic;
 
 static db1_con_t* dp_db_handle    = 0; /* database connection handle */
 static db_func_t dp_dbf;
@@ -84,6 +79,52 @@ dpl_id_p* rules_hash = NULL;
 int * crt_idx, *next_idx;
 
 
+/**
+ * check if string has pvs
+ * returns -1 if error, 0 if found, 1 if not found
+ */
+int dpl_check_pv(str *in)
+{
+	char *p;
+	pv_spec_t *spec = NULL;
+	str s;
+	int len;
+
+	if(in==NULL || in->s==NULL)
+		return -1;
+
+	LM_DBG("parsing [%.*s]\n", in->len, in->s);
+
+	if(in->len == 0)
+		return 1;
+
+	p = in->s;
+
+	while(is_in_str(p,in))
+	{
+		while(is_in_str(p,in) && *p!=PV_MARKER)
+			p++;
+		if(*p == '\0' || !is_in_str(p,in))
+			break;
+		/* last char is $ ? */
+		if(!is_in_str(p+1, in))
+			break;
+		s.s = p;
+		s.len = in->s+in->len-p;
+		len = 0;
+		spec = pv_spec_lookup(&s, &len);
+		if(spec!=NULL) {
+			/* found a variable */
+			LM_DBG("string [%.*s] has variables\n", in->len, in->s);
+			return 0;
+		}
+		if(len) p += len;
+		else p++;
+	}
+
+	/* not found */
+	return 1;
+}
 
 int init_db_data(void)
 {
@@ -294,12 +335,19 @@ err2:
 }
 
 
-int str_to_shm(str src, str * dest)
+int dpl_str_to_shm(str src, str *dest, int mterm)
 {
+	int mdup = 0;
+
 	if(src.len ==0 || src.s ==0)
 		return 0;
 
-	dest->s = (char*)shm_malloc((src.len+1) * sizeof(char));
+	if(mterm!=0 && PV_MARKER=='$') {
+		if(src.len>1 && src.s[src.len-1]=='$' && src.s[src.len-2]!='$') {
+			mdup = 1;
+		}
+	}
+	dest->s = (char*)shm_malloc((src.len+1+mdup) * sizeof(char));
 	if(!dest->s){
 		LM_ERR("out of shm memory\n");
 		return -1;
@@ -308,13 +356,20 @@ int str_to_shm(str src, str * dest)
 	memcpy(dest->s, src.s, src.len);
 	dest->s[src.len] = '\0';
 	dest->len = src.len;
+	if(mdup) {
+		dest->s[dest->len] = '$';
+		dest->len++;
+		dest->s[dest->len] = '\0';
+	}
 
 	return 0;
 }
 
 
-/* Compile pcre pattern and return pointer to shm copy of result */
-static pcre *reg_ex_comp(const char *pattern, int *cap_cnt)
+/* Compile pcre pattern
+ * if mtype==0 - return pointer to shm copy of result
+ * if mtype==1 - return pcre pointer that has to be pcre_free() */
+pcre *reg_ex_comp(const char *pattern, int *cap_cnt, int mtype)
 {
 	pcre *re, *result;
 	const char *error;
@@ -341,15 +396,19 @@ static pcre *reg_ex_comp(const char *pattern, int *cap_cnt)
 				pattern, rc);
 		return (pcre *)0;
 	}
-	result = (pcre *)shm_malloc(size);
-	if (result == NULL) {
+	if(mtype==0) {
+		result = (pcre *)shm_malloc(size);
+		if (result == NULL) {
+			pcre_free(re);
+			LM_ERR("not enough shared memory for compiled PCRE pattern\n");
+			return (pcre *)0;
+		}
+		memcpy(result, re, size);
 		pcre_free(re);
-		LM_ERR("not enough shared memory for compiled PCRE pattern\n");
-		return (pcre *)0;
+		return result;
+	} else {
+		return re;
 	}
-	memcpy(result, re, size);
-	pcre_free(re);
-	return result;
 }
 
 
@@ -362,6 +421,7 @@ dpl_node_t * build_rule(db_val_t * values)
 	str match_exp, subst_exp, repl_exp, attrs;
 	int matchop;
 	int cap_cnt=0;
+	unsigned int tflags=0;
 
 	matchop = VAL_INT(values+2);
 
@@ -371,17 +431,24 @@ dpl_node_t * build_rule(db_val_t * values)
 		return NULL;
 	}
 
-	match_comp = subst_comp =0;
+	match_comp = subst_comp = 0;
 	repl_comp = 0;
 	new_rule = 0;
 
 	GET_STR_VALUE(match_exp, values, 3);
 	if(matchop == DP_REGEX_OP){
-		match_comp = reg_ex_comp(match_exp.s, &cap_cnt);
-		if(!match_comp){
-			LM_ERR("failed to compile match expression %.*s\n",
-					match_exp.len, match_exp.s);
-			goto err;
+		if(unlikely(dp_match_dynamic==1)) {
+			if(dpl_check_pv(&match_exp)==0) {
+				tflags |= DP_TFLAGS_PV_MATCH;
+			}
+		}
+		if(!(tflags&DP_TFLAGS_PV_MATCH)) {
+			match_comp = reg_ex_comp(match_exp.s, &cap_cnt, 0);
+			if(!match_comp){
+				LM_ERR("failed to compile match expression %.*s\n",
+						match_exp.len, match_exp.s);
+				goto err;
+			}
 		}
 	}
 
@@ -395,26 +462,36 @@ dpl_node_t * build_rule(db_val_t * values)
 		}
 	}
 
+	cap_cnt = 0;
 	GET_STR_VALUE(subst_exp, values, 5);
 	if(subst_exp.s && subst_exp.len){
-		subst_comp = reg_ex_comp(subst_exp.s, &cap_cnt);
-		if(!subst_comp){
-			LM_ERR("failed to compile subst expression %.*s\n",
-					subst_exp.len, subst_exp.s);
-			goto err;
+		if(unlikely(dp_match_dynamic==1)) {
+			if(dpl_check_pv(&subst_exp)==0) {
+				tflags |= DP_TFLAGS_PV_SUBST;
+			}
 		}
-		if (cap_cnt > MAX_REPLACE_WITH) {
-			LM_ERR("subst expression %.*s has too many sub-expressions\n",
-					subst_exp.len, subst_exp.s);
-			goto err;
+		if(!(tflags&DP_TFLAGS_PV_SUBST)) {
+			subst_comp = reg_ex_comp(subst_exp.s, &cap_cnt, 0);
+			if(!subst_comp){
+				LM_ERR("failed to compile subst expression %.*s\n",
+						subst_exp.len, subst_exp.s);
+				goto err;
+			}
+			if (cap_cnt > MAX_REPLACE_WITH) {
+				LM_ERR("subst expression %.*s has too many sub-expressions\n",
+						subst_exp.len, subst_exp.s);
+				goto err;
+			}
 		}
 	}
 
 	LM_DBG("building rule for [%d:%.*s/%.*s/%.*s]\n", matchop,
 			match_exp.len, ZSW(match_exp.s), subst_exp.len, ZSW(subst_exp.s),
 			repl_exp.len, ZSW(repl_exp.s));
-	if (repl_comp && (cap_cnt < repl_comp->max_pmatch) && 
-			(repl_comp->max_pmatch != 0)) {
+	if (!(tflags&(DP_TFLAGS_PV_SUBST|DP_TFLAGS_PV_MATCH)) &&
+		repl_comp && (cap_cnt < repl_comp->max_pmatch) &&
+		(repl_comp->max_pmatch != 0))
+	{
 		LM_ERR("repl_exp %.*s refers to %d sub-expressions, but "
 				"subst_exp %.*s has only %d\n",
 				repl_exp.len, repl_exp.s, repl_comp->max_pmatch,
@@ -429,13 +506,15 @@ dpl_node_t * build_rule(db_val_t * values)
 	}
 	memset(new_rule, 0, sizeof(dpl_node_t));
 
-	if(str_to_shm(match_exp, &new_rule->match_exp)!=0)
+	if(dpl_str_to_shm(match_exp, &new_rule->match_exp,
+				tflags&DP_TFLAGS_PV_MATCH)!=0)
 		goto err;
 
-	if(str_to_shm(subst_exp, &new_rule->subst_exp)!=0)
+	if(dpl_str_to_shm(subst_exp, &new_rule->subst_exp,
+				tflags&DP_TFLAGS_PV_SUBST)!=0)
 		goto err;
 
-	if(str_to_shm(repl_exp, &new_rule->repl_exp)!=0)
+	if(dpl_str_to_shm(repl_exp, &new_rule->repl_exp, 0)!=0)
 		goto err;
 
 	/*set the rest of the rule fields*/
@@ -444,14 +523,15 @@ dpl_node_t * build_rule(db_val_t * values)
 	new_rule->matchlen	= 	VAL_INT(values+4);
 	new_rule->matchop	=	matchop;
 	GET_STR_VALUE(attrs, values, 7);
-	if(str_to_shm(attrs, &new_rule->attrs)!=0)
+	if(dpl_str_to_shm(attrs, &new_rule->attrs, 0)!=0)
 		goto err;
 
-	LM_DBG("attrs are %.*s\n", new_rule->attrs.len, new_rule->attrs.s);
+	LM_DBG("attrs are: '%.*s'\n", new_rule->attrs.len, new_rule->attrs.s);
 
 	new_rule->match_comp = match_comp;
 	new_rule->subst_comp = subst_comp;
 	new_rule->repl_comp  = repl_comp;
+	new_rule->tflags     = tflags;
 
 	return new_rule;
 
@@ -662,15 +742,15 @@ void list_hash(int h_index)
 }
 
 
-void list_rule(dpl_node_t * rule)
+void list_rule(dpl_node_t *rule)
 {
-	LM_DBG("RULE %p: pr %i next %p op %d match_exp %.*s, "
+	LM_DBG("RULE %p: pr %i next %p op %d tflags %u match_exp %.*s, "
 			"subst_exp %.*s, repl_exp %.*s and attrs %.*s\n", rule,
 			rule->pr, rule->next,
-			rule->matchop,
-			rule->match_exp.len, rule->match_exp.s, 
-			rule->subst_exp.len, rule->subst_exp.s,
-			rule->repl_exp.len, rule->repl_exp.s,
-			rule->attrs.len,	rule->attrs.s);
+			rule->matchop, rule->tflags,
+			rule->match_exp.len, ZSW(rule->match_exp.s),
+			rule->subst_exp.len, ZSW(rule->subst_exp.s),
+			rule->repl_exp.len, ZSW(rule->repl_exp.s),
+			rule->attrs.len,	ZSW(rule->attrs.s));
 
 }
diff --git a/modules/dialplan/dp_db.h b/modules/dialplan/dp_db.h
index b511c85..6eb0e1b 100644
--- a/modules/dialplan/dp_db.h
+++ b/modules/dialplan/dp_db.h
@@ -1,16 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C)  2007-2008 Voice Sistem SRL
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -19,14 +17,11 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2007-08-01 initial version (ancuta onofrei)
  */
 
 /*!
  * \file
- * \brief SIP-router dialplan :: Database interface
+ * \brief Kamailio dialplan :: Database interface
  * \ingroup dialplan
  * Module: \ref dialplan
  */
diff --git a/modules/dialplan/dp_repl.c b/modules/dialplan/dp_repl.c
index eeb9dd1..bfeda07 100644
--- a/modules/dialplan/dp_repl.c
+++ b/modules/dialplan/dp_repl.c
@@ -1,18 +1,16 @@
 /*
- * $Id$
- *
  * Copyright (C) 2007-2008 Voice Sistem SRL
  *
  * Copyright (C) 2008 Juha Heinanen
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -21,14 +19,11 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2007-08-01 initial version (ancuta onofrei)
  */
 
 /*!
  * \file
- * \brief SIP-router dialplan :: database interface - reply parsing
+ * \brief Kamailio dialplan :: database interface - reply parsing
  * \ingroup dialplan
  * Module: \ref dialplan
  */
@@ -37,9 +32,259 @@
 #include <fnmatch.h>
 
 #include "../../re.h"
+#include "../../str_list.h"
 #include "../../mem/shm_mem.h"
 #include "dialplan.h"
 
+typedef struct dpl_dyn_pcre
+{
+	pcre *re;
+	int cnt;
+	str expr;
+
+	struct dpl_dyn_pcre * next; /* next rule */
+} dpl_dyn_pcre_t, *dpl_dyn_pcre_p;
+
+static void dpl_get_avp_val(avp_t *avp, str *dst) {
+	avp_value_t val;
+
+	if (avp==0 || dst==0) return;
+
+	/* Warning! it uses static buffer from int2str !!! */
+
+	get_avp_val(avp, &val);
+	if (avp->flags & AVP_VAL_STR) {
+		*dst = val.s;
+	}
+	else { /* probably (!) number */
+		dst->s = int2str(val.n, &dst->len);
+	}
+}
+
+int dpl_dyn_printf_s(sip_msg_t *msg, const pv_elem_p elem,
+	const pv_elem_p avp_elem, str *val, pv_elem_p *elem_prev, str *vexpr)
+{
+	pv_elem_p e = NULL;
+	pv_elem_p t = NULL;
+	str s = STR_NULL;
+	int ret = -1;
+
+	if(elem==NULL||avp_elem==NULL||elem_prev==NULL) return -1;
+	if(str_append(&(avp_elem->text), val, &s)<0) return -1;
+
+	if(pv_parse_format(&s, &e)<0) {
+		LM_ERR("parsing expression: %.*s\n", s.len, s.s);
+		goto clean;
+	}
+	if(*elem_prev==NULL && elem!=avp_elem) {
+		LM_DBG("search for elem_prev\n");
+		for(t=elem; t!=NULL; t=t->next) {
+			if(t->next==avp_elem) { *elem_prev = t;
+				LM_DBG("found!\n");
+			}
+		}
+	}
+	if(*elem_prev) (*elem_prev)->next = e;
+	e->next = avp_elem->next;
+	if(pv_printf_s(msg, e, vexpr)<0){
+		LM_ERR("cannot get avp pcre dynamic expression value\n");
+		goto clean;
+	}
+	ret = 0;
+clean:
+	if(s.s) pkg_free(s.s);
+	if(e) pkg_free(e);
+	if(*elem_prev) (*elem_prev)->next = avp_elem;
+	return ret;
+}
+
+int dpl_get_avp_values(sip_msg_t *msg, const pv_elem_p elem,
+	const pv_elem_p avp_elem, struct str_list **out)
+{
+	struct usr_avp *avp = NULL;
+	unsigned short name_type;
+	int_str avp_name, avp_value;
+	struct search_state state;
+	int sum = 0;
+	str s = STR_NULL;
+	str ts = STR_NULL;
+	pv_elem_p elem_prev = NULL;
+	struct str_list *tl = NULL;
+
+	if(elem==NULL||avp_elem==NULL||out==NULL||*out==NULL) {
+		LM_ERR("wrong parameters\n");
+		return -1;
+	}
+	if(pv_get_avp_name(msg, &(avp_elem->spec->pvp), &avp_name, &name_type)!=0) {
+		LM_ERR("invalid avp name\n");
+		return -1;
+	}
+	avp = search_first_avp(name_type, avp_name, &avp_value, &state);
+	if(avp==NULL) {
+		LM_ERR("can't find first avp\n");
+		return -1;
+	}
+	tl = *out;
+	dpl_get_avp_val(avp, &s);
+	dpl_dyn_printf_s(msg, elem, avp_elem, &s, &elem_prev, &tl->s);
+	/*LM_DBG("elem[%p] avp_elem[%p], elem_prev[%p] [%.*s]\n",
+			elem, avp_elem, elem_prev, tl->s.len, tl->s.s);*/
+	sum = tl->s.len;
+	while ((avp=search_next_avp(&state, &avp_value))!=0) {
+		dpl_get_avp_val(avp, &s);
+		dpl_dyn_printf_s(msg, elem, avp_elem, &s, &elem_prev, &ts);
+		if(append_str_list(ts.s, ts.len, &tl, &sum)==NULL) {
+			while(*out) {
+				tl = (*out)->next;
+				pkg_free(*out);
+				*out = tl;
+			}
+			return -1;
+		}
+		/*LM_DBG("elem[%p] avp_elem[%p], elem_prev[%p] [%.*s] out[%p] out->next[%p]\n",
+			elem, avp_elem, elem_prev, tl->s.len, tl->s.s,
+			*out, (*out)->next); */
+	}
+	return 0;
+}
+
+int dpl_detect_avp_indx(const pv_elem_p elem, pv_elem_p *avp)
+{
+	int num, num_avp_all;
+	pv_elem_p e = elem;;
+	if(elem==NULL||avp==NULL) return -1;
+
+	for(e=elem, num=num_avp_all=0; e!=NULL; e=e->next, num++) {
+		if(e->spec!=NULL && e->spec->type==PVT_AVP &&
+			e->spec->pvp.pvi.type==PV_IDX_ITR)
+		{
+			*avp = e;
+			num_avp_all++;
+		}
+	}
+	if(num_avp_all==1) return 1; /* just one avp_indx supported */
+	return 0;
+}
+
+pcre *dpl_dyn_pcre_comp(sip_msg_t *msg, str *expr, str *vexpr, int *cap_cnt)
+{
+	pcre *re = NULL;
+	int ccnt = 0;
+
+	if(expr==NULL || expr->s==NULL || expr->len<=0 ||
+	   vexpr==NULL || vexpr->s==NULL || vexpr->len<=0)
+		return NULL;
+
+	re = reg_ex_comp(vexpr->s, &ccnt, 1);
+	if(!re) {
+		if(expr!=vexpr)
+			LM_ERR("failed to compile pcre expression: %.*s (%.*s)\n",
+				expr->len, expr->s, vexpr->len, vexpr->s);
+		else
+			LM_ERR("failed to compile pcre expression: %.*s\n",
+				vexpr->len, vexpr->s);
+		return NULL;
+	}
+	if(cap_cnt) {
+		*cap_cnt = ccnt;
+	}
+	if(expr!=vexpr)
+		LM_DBG("compiled dynamic pcre expression: %.*s (%.*s) %d\n",
+				expr->len, expr->s, vexpr->len, vexpr->s, ccnt);
+	else
+		LM_DBG("compiled dynamic pcre expression: %.*s %d\n",
+				vexpr->len, vexpr->s, ccnt);
+	return re;
+}
+
+dpl_dyn_pcre_p dpl_dynamic_pcre_list(sip_msg_t *msg, str *expr)
+{
+	pv_elem_p elem = NULL;
+	pv_elem_p avp_elem = NULL;
+	dpl_dyn_pcre_p re_list = NULL;
+	dpl_dyn_pcre_p rt = NULL;
+	struct str_list *l = NULL;
+	struct str_list *t = NULL;
+	pcre *re = NULL;
+	int cnt = 0;
+	str vexpr = STR_NULL;
+
+	if(expr==NULL || expr->s==NULL || expr->len<=0)
+	{
+		LM_ERR("wrong parameters\n");
+		return NULL;
+	}
+
+	if(pv_parse_format(expr, &elem)<0) {
+		LM_ERR("parsing pcre expression: %.*s\n",
+				expr->len, expr->s);
+		return NULL;
+	}
+	LM_DBG("parsed pcre expression: %.*s\n", expr->len, expr->s);
+	if(dpl_detect_avp_indx(elem, &avp_elem)) {
+		l = pkg_malloc(sizeof(struct str_list));
+		if(l==NULL) {
+			PKG_MEM_ERROR;
+			return NULL;
+		}
+		memset(l, 0, sizeof(struct str_list));
+		if(dpl_get_avp_values(msg, elem, avp_elem, &l)<0) {
+			LM_ERR("can't get list of avp values\n");
+			goto error;
+		}
+		t = l;
+		while(t) {
+			re = dpl_dyn_pcre_comp(msg, &(t->s), &(t->s), &cnt);
+			if(re!=NULL) {
+				rt = pkg_malloc(sizeof(dpl_dyn_pcre_t));
+				if(rt==NULL) {
+					PKG_MEM_ERROR;
+					goto error;
+				}
+				rt->re = re;
+				rt->expr.s = t->s.s;
+				rt->expr.len = t->s.len;
+				rt->cnt = cnt;
+				rt->next = re_list;
+				re_list = rt;
+			}
+			t = t->next;
+		}
+	}
+	else {
+		if(pv_printf_s(msg, elem, &vexpr)<0){
+			LM_ERR("cannot get pcre dynamic expression value: %.*s\n",
+					expr->len, expr->s);
+			goto error;
+		}
+		re = dpl_dyn_pcre_comp(msg, expr, &vexpr, &cnt);
+		if(re!=NULL) {
+			rt = pkg_malloc(sizeof(dpl_dyn_pcre_t));
+			if(rt==NULL) {
+				PKG_MEM_ERROR;
+				goto error;
+			}
+			rt->re = re;
+			rt->expr.s = expr->s;
+			rt->expr.len = expr->len;
+			rt->cnt = cnt;
+			rt->next = re_list;
+			re_list = rt;
+		}
+	}
+	goto clean;
+error:
+	while(re_list) {
+		rt = re_list->next;
+		if(re_list->re) pcre_free(re_list->re);
+		pkg_free(re_list);
+		re_list = rt;
+	}
+clean:
+	if(elem) pv_elem_free_all(elem);
+	while(l) { t = l->next; pkg_free(l); l = t;}
+	return re_list;
+}
 
 void repl_expr_free(struct subst_expr *se)
 {
@@ -124,14 +369,14 @@ error:
 }
 
 
+
 #define MAX_PHONE_NB_DIGITS		127
 static char dp_output_buf[MAX_PHONE_NB_DIGITS+1];
-int rule_translate(struct sip_msg *msg, str string, dpl_node_t * rule,
-		str * result)
+int rule_translate(sip_msg_t *msg, str string, dpl_node_t * rule,
+		pcre *subst_comp, str * result)
 {
 	int repl_nb, offset, match_nb, rc, cap_cnt;
 	struct replace_with token;
-	pcre *subst_comp;
 	struct subst_expr * repl_comp;
 	str match;
 	pv_value_t sv;
@@ -144,9 +389,7 @@ int rule_translate(struct sip_msg *msg, str string, dpl_node_t * rule,
 	result->s = dp_output_buf;
 	result->len = 0;
 
-	subst_comp 	= rule->subst_comp;
-	repl_comp 	= rule->repl_comp;
-
+	repl_comp = rule->repl_comp;
 	if(!repl_comp){
 		LM_DBG("null replacement\n");
 		return 0;
@@ -159,16 +402,21 @@ int rule_translate(struct sip_msg *msg, str string, dpl_node_t * rule,
 		if (rc != 0) {
 			LM_ERR("pcre_fullinfo on compiled pattern yielded error: %d\n",
 					rc);
-			return -1;;
+			return -1;
 		}
 		if(repl_comp->max_pmatch > cap_cnt){
-			LM_ERR("illegal access to the %i-th subexpr of the subst expr\n",
-					repl_comp->max_pmatch);
+			LM_ERR("illegal access to %i-th subexpr of subst expr (max %d)\n",
+					repl_comp->max_pmatch, cap_cnt);
+			return -1;
+		}
+		if (rule->tflags&DP_TFLAGS_PV_SUBST && (cap_cnt > MAX_REPLACE_WITH)) {
+			LM_ERR("subst expression %.*s has too many sub-expressions\n",
+				rule->subst_exp.len, rule->subst_exp.s);
 			return -1;
 		}
 
 		/*search for the pattern from the compiled subst_exp*/
-		if (pcre_exec(rule->subst_comp, NULL, string.s, string.len,
+		if (pcre_exec(subst_comp, NULL, string.s, string.len,
 					0, 0, ovector, 3 * (MAX_REPLACE_WITH + 1)) <= 0) {
 			LM_ERR("the string %.*s matched "
 					"the match_exp %.*s but not the subst_exp %.*s!\n", 
@@ -310,13 +558,15 @@ error:
 
 #define DP_MAX_ATTRS_LEN	128
 static char dp_attrs_buf[DP_MAX_ATTRS_LEN+1];
-int translate(struct sip_msg *msg, str input, str *output, dpl_id_p idp,
+int translate(sip_msg_t *msg, str input, str *output, dpl_id_p idp,
 		str *attrs)
 {
 	dpl_node_p rulep;
 	dpl_index_p indexp;
 	int user_len, rez;
 	char b;
+	dpl_dyn_pcre_p re_list = NULL;
+	dpl_dyn_pcre_p rt = NULL;
 
 	if(!input.s || !input.len) {
 		LM_ERR("invalid input string\n");
@@ -338,9 +588,35 @@ search_rule:
 		switch(rulep->matchop) {
 
 			case DP_REGEX_OP:
-				LM_DBG("regex operator testing\n");
-				rez = pcre_exec(rulep->match_comp, NULL, input.s, input.len,
+				LM_DBG("regex operator testing over [%.*s]\n",
+						input.len, input.s);
+				if(rulep->tflags&DP_TFLAGS_PV_MATCH) {
+					re_list = dpl_dynamic_pcre_list(msg, &rulep->match_exp);
+					if(re_list==NULL) {
+						/* failed to compile dynamic pcre -- ignore */
+						LM_DBG("failed to compile dynamic pcre[%.*s]\n",
+							rulep->match_exp.len, rulep->match_exp.s);
+						continue;
+					}
+					rez = -1;
+					do {
+						if(rez<0) {
+							rez = pcre_exec(re_list->re, NULL, input.s, input.len,
+									0, 0, NULL, 0);
+							LM_DBG("match check: [%.*s] %d\n",
+								re_list->expr.len, re_list->expr.s, rez);
+						}
+						else LM_DBG("match check skipped: [%.*s] %d\n",
+								re_list->expr.len, re_list->expr.s, rez);
+						rt = re_list->next;
+						pcre_free(re_list->re);
+						pkg_free(re_list);
+						re_list = rt;
+					} while(re_list);
+				} else {
+					rez = pcre_exec(rulep->match_comp, NULL, input.s, input.len,
 						0, 0, NULL, 0);
+				}
 				break;
 
 			case DP_EQUAL_OP:
@@ -404,11 +680,34 @@ repl:
 					attrs->len, attrs->s);
 		}
 	}
-
-	if(rule_translate(msg, input, rulep, output)!=0){
-		LM_ERR("could not build the output\n");
-		return -1;
+	if(rulep->tflags&DP_TFLAGS_PV_SUBST) {
+		re_list = dpl_dynamic_pcre_list(msg, &rulep->match_exp);
+		if(re_list==NULL) {
+			/* failed to compile dynamic pcre -- ignore */
+			LM_DBG("failed to compile dynamic pcre[%.*s]\n",
+				rulep->subst_exp.len, rulep->subst_exp.s);
+			return -1;
+		}
+		rez = -1;
+		do {
+			if(rez<0) {
+				rez = rule_translate(msg, input, rulep, re_list->re, output);
+				LM_DBG("subst check: [%.*s] %d\n",
+					re_list->expr.len, re_list->expr.s, rez);
+			}
+			else LM_DBG("subst check skipped: [%.*s] %d\n",
+					re_list->expr.len, re_list->expr.s, rez);
+			rt = re_list->next;
+			pcre_free(re_list->re);
+			pkg_free(re_list);
+			re_list = rt;
+		} while(re_list);
+	}
+	else {
+		if(rule_translate(msg, input, rulep, rulep->subst_comp, output)!=0){
+			LM_ERR("could not build the output\n");
+			return -1;
+		}
 	}
-
 	return 0;
 }
diff --git a/modules/dispatcher/Makefile b/modules/dispatcher/Makefile
index 7bc6e5b..e20162d 100644
--- a/modules/dispatcher/Makefile
+++ b/modules/dispatcher/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # example module makefile
 #
diff --git a/modules/dispatcher/README b/modules/dispatcher/README
index 8f2c96a..76dabec 100644
--- a/modules/dispatcher/README
+++ b/modules/dispatcher/README
@@ -16,11 +16,27 @@ Carsten Bock
 
    ng-voice GmbH
 
+Edited by
+
+Olle E. Johansson
+
+   Edvina AB
+
+Edited by
+
+Alessandro Arrichiello
+
+   Hewlett Packard
+
    Copyright � 2004 FhG FOKUS
 
    Copyright � 2005 Voice Sistem
 
    Copyright � 2010 Daniel-Constantin Mierla (asipto.com)
+
+   Copyright � 2014 Olle E. Johansson, Edvina AB
+
+   Copyright � 2015 Alessandro Arrichiello, Hewlett Packard
      __________________________________________________________________
 
    Table of Contents
@@ -50,20 +66,23 @@ Carsten Bock
               3.13. cnt_avp (str)
               3.14. dstid_avp (str)
               3.15. attrs_avp (str)
-              3.16. hash_pvar (str)
-              3.17. setid_pvname (str)
-              3.18. attrs_pvname (str)
-              3.19. ds_ping_method (string)
-              3.20. ds_ping_from (string)
-              3.21. ds_ping_interval (int)
-              3.22. ds_probing_threshold (int)
-              3.23. ds_ping_reply_codes (string)
-              3.24. ds_probing_mode (int)
-              3.25. ds_hash_size (int)
-              3.26. ds_hash_expire (int)
-              3.27. ds_hash_initexpire (int)
-              3.28. ds_hash_check_interval (int)
-              3.29. outbound_proxy (str)
+              3.16. sock_avp (str)
+              3.17. hash_pvar (str)
+              3.18. setid_pvname (str)
+              3.19. attrs_pvname (str)
+              3.20. ds_ping_method (string)
+              3.21. ds_ping_from (string)
+              3.22. ds_ping_interval (int)
+              3.23. ds_probing_threshold (int)
+              3.24. ds_inactive_threshold (int)
+              3.25. ds_ping_reply_codes (string)
+              3.26. ds_probing_mode (int)
+              3.27. ds_hash_size (int)
+              3.28. ds_hash_expire (int)
+              3.29. ds_hash_initexpire (int)
+              3.30. ds_hash_check_interval (int)
+              3.31. outbound_proxy (str)
+              3.32. ds_default_socket (str)
 
         4. Functions
 
@@ -72,9 +91,10 @@ Carsten Bock
               4.3. ds_next_dst()
               4.4. ds_next_domain()
               4.5. ds_mark_dst([state])
-              4.6. ds_is_from_list([groupid [, mode [, uri] ] ])
-              4.7. ds_load_update()
-              4.8. ds_load_unset()
+              4.6. ds_list_exist(groupid)
+              4.7. ds_is_from_list([groupid [, mode [, uri] ] ])
+              4.8. ds_load_update()
+              4.9. ds_load_unset()
 
         5. MI Commands
 
@@ -121,27 +141,31 @@ Carsten Bock
    1.13. Set the "cnt_avp" parameter
    1.14. Set the "dstid_avp" parameter
    1.15. Set the "attrs_avp" parameter
-   1.16. Use $avp(i:273) for hashing:
-   1.17. Use combination of PVs for hashing:
-   1.18. Set the "setid_pvname" parameter
-   1.19. Set the "attrs_pvname" parameter
-   1.20. Set the "ds_ping_method" parameter
-   1.21. Set the "ds_ping_from" parameter
-   1.22. Set the "ds_ping_interval" parameter
-   1.23. Set the "ds_probing_threshhold" parameter
-   1.24. Set the "ds_ping_reply_codes" parameter
-   1.25. Set the "ds_probing_mode" parameter
-   1.26. Set the "ds_hash_size" parameter
-   1.27. Set the "ds_hash_expire" parameter
-   1.28. Set the "ds_hash_initexpire" parameter
-   1.29. Set the "ds_hash_check_interval" parameter
-   1.30. Set the "outbound_proxy" parameter
-   1.31. ds_select_dst usage
-   1.32. ds_mark_dst usage
-   1.33. ds_mark_dst usage
-   1.34. ds_load_unset usage
-   1.35. dispatcher list file
-   1.36. Kamailio config script - sample dispatcher usage
+   1.16. Set the "sock_avp" parameter
+   1.17. Use $avp(i:273) for hashing:
+   1.18. Use combination of PVs for hashing:
+   1.19. Set the "setid_pvname" parameter
+   1.20. Set the "attrs_pvname" parameter
+   1.21. Set the "ds_ping_method" parameter
+   1.22. Set the "ds_ping_from" parameter
+   1.23. Set the "ds_ping_interval" parameter
+   1.24. Set the "ds_probing_threshold" parameter
+   1.25. Set the "ds_inactive_threshold" parameter
+   1.26. Set the "ds_ping_reply_codes" parameter
+   1.27. Set the "ds_probing_mode" parameter
+   1.28. Set the "ds_hash_size" parameter
+   1.29. Set the "ds_hash_expire" parameter
+   1.30. Set the "ds_hash_initexpire" parameter
+   1.31. Set the "ds_hash_check_interval" parameter
+   1.32. Set the "outbound_proxy" parameter
+   1.33. Set the "ds_default_socket" parameter
+   1.34. ds_select_dst usage
+   1.35. ds_mark_dst usage
+   1.36. ds_list_exist usage
+   1.37. ds_is_from_list usage
+   1.38. ds_load_unset usage
+   1.39. dispatcher list file
+   1.40. Kamailio config script - sample dispatcher usage
 
 Chapter 1. Admin Guide
 
@@ -170,20 +194,23 @@ Chapter 1. Admin Guide
         3.13. cnt_avp (str)
         3.14. dstid_avp (str)
         3.15. attrs_avp (str)
-        3.16. hash_pvar (str)
-        3.17. setid_pvname (str)
-        3.18. attrs_pvname (str)
-        3.19. ds_ping_method (string)
-        3.20. ds_ping_from (string)
-        3.21. ds_ping_interval (int)
-        3.22. ds_probing_threshold (int)
-        3.23. ds_ping_reply_codes (string)
-        3.24. ds_probing_mode (int)
-        3.25. ds_hash_size (int)
-        3.26. ds_hash_expire (int)
-        3.27. ds_hash_initexpire (int)
-        3.28. ds_hash_check_interval (int)
-        3.29. outbound_proxy (str)
+        3.16. sock_avp (str)
+        3.17. hash_pvar (str)
+        3.18. setid_pvname (str)
+        3.19. attrs_pvname (str)
+        3.20. ds_ping_method (string)
+        3.21. ds_ping_from (string)
+        3.22. ds_ping_interval (int)
+        3.23. ds_probing_threshold (int)
+        3.24. ds_inactive_threshold (int)
+        3.25. ds_ping_reply_codes (string)
+        3.26. ds_probing_mode (int)
+        3.27. ds_hash_size (int)
+        3.28. ds_hash_expire (int)
+        3.29. ds_hash_initexpire (int)
+        3.30. ds_hash_check_interval (int)
+        3.31. outbound_proxy (str)
+        3.32. ds_default_socket (str)
 
    4. Functions
 
@@ -192,9 +219,10 @@ Chapter 1. Admin Guide
         4.3. ds_next_dst()
         4.4. ds_next_domain()
         4.5. ds_mark_dst([state])
-        4.6. ds_is_from_list([groupid [, mode [, uri] ] ])
-        4.7. ds_load_update()
-        4.8. ds_load_unset()
+        4.6. ds_list_exist(groupid)
+        4.7. ds_is_from_list([groupid [, mode [, uri] ] ])
+        4.8. ds_load_update()
+        4.9. ds_load_unset()
 
    5. MI Commands
 
@@ -273,20 +301,23 @@ Chapter 1. Admin Guide
    3.13. cnt_avp (str)
    3.14. dstid_avp (str)
    3.15. attrs_avp (str)
-   3.16. hash_pvar (str)
-   3.17. setid_pvname (str)
-   3.18. attrs_pvname (str)
-   3.19. ds_ping_method (string)
-   3.20. ds_ping_from (string)
-   3.21. ds_ping_interval (int)
-   3.22. ds_probing_threshold (int)
-   3.23. ds_ping_reply_codes (string)
-   3.24. ds_probing_mode (int)
-   3.25. ds_hash_size (int)
-   3.26. ds_hash_expire (int)
-   3.27. ds_hash_initexpire (int)
-   3.28. ds_hash_check_interval (int)
-   3.29. outbound_proxy (str)
+   3.16. sock_avp (str)
+   3.17. hash_pvar (str)
+   3.18. setid_pvname (str)
+   3.19. attrs_pvname (str)
+   3.20. ds_ping_method (string)
+   3.21. ds_ping_from (string)
+   3.22. ds_ping_interval (int)
+   3.23. ds_probing_threshold (int)
+   3.24. ds_inactive_threshold (int)
+   3.25. ds_ping_reply_codes (string)
+   3.26. ds_probing_mode (int)
+   3.27. ds_hash_size (int)
+   3.28. ds_hash_expire (int)
+   3.29. ds_hash_initexpire (int)
+   3.30. ds_hash_check_interval (int)
+   3.31. outbound_proxy (str)
+   3.32. ds_default_socket (str)
 
 3.1. list_file (string)
 
@@ -500,7 +531,24 @@ Note
  modparam("dispatcher", "attrs_avp", "$avp(dsattrs)")
  ...
 
-3.16. hash_pvar (str)
+3.16. sock_avp (str)
+
+   The name of the avp which will hold the list with the sockets
+   associated to the addresses stored in dst_avp avp.
+
+Note
+
+   If you want to do load balancing fail over, you have to set this
+   parameter to use the correct socket for each gateway.
+
+   Default value is "null" - don't add AVPs.
+
+   Example 1.16. Set the "sock_avp" parameter
+ ...
+ modparam("dispatcher", "sock_avp", "$avp(dssocket)")
+ ...
+
+3.17. hash_pvar (str)
 
    String with PVs used for the hashing algorithm 7.
 
@@ -511,41 +559,41 @@ Note
 
    Default value is "null" - disabled.
 
-   Example 1.16. Use $avp(i:273) for hashing:
+   Example 1.17. Use $avp(i:273) for hashing:
  ...
  modparam("dispatcher", "hash_pvar", "$avp(i:273)")
  ...
 
-   Example 1.17. Use combination of PVs for hashing:
+   Example 1.18. Use combination of PVs for hashing:
  ...
  modparam("dispatcher", "hash_pvar", "hash the $fU@$ci")
  ...
 
-3.17. setid_pvname (str)
+3.18. setid_pvname (str)
 
    The name of the PV where to store the set ID (group ID) when calling
    ds_is_from_list() with no parameter.
 
    Default value is "null" - don't set PV.
 
-   Example 1.18. Set the "setid_pvname" parameter
+   Example 1.19. Set the "setid_pvname" parameter
  ...
  modparam("dispatcher", "setid_pvname", "$var(setid)")
  ...
 
-3.18. attrs_pvname (str)
+3.19. attrs_pvname (str)
 
    The name of the PV where to store the attributes of matching address
    when calling ds_is_from_list().
 
    Default value is "null" - don't set PV.
 
-   Example 1.19. Set the "attrs_pvname" parameter
+   Example 1.20. Set the "attrs_pvname" parameter
  ...
  modparam("dispatcher", "attrs_pvname", "$var(attrs)")
  ...
 
-3.19. ds_ping_method (string)
+3.20. ds_ping_method (string)
 
    With this method you can define, with which method you want to probe
    the gateways. Pinging gateways feature depends on ds_ping_interval
@@ -553,12 +601,12 @@ Note
 
    Default value is "OPTIONS".
 
-   Example 1.20. Set the "ds_ping_method" parameter
+   Example 1.21. Set the "ds_ping_method" parameter
  ...
  modparam("dispatcher", "ds_ping_method", "INFO")
  ...
 
-3.20. ds_ping_from (string)
+3.21. ds_ping_from (string)
 
    With this Method you can define the "From:"-Line for the request, sent
    to the failed gateways. This method is only available, if compiled with
@@ -566,12 +614,12 @@ Note
 
    Default value is "sip:dispatcher at localhost".
 
-   Example 1.21. Set the "ds_ping_from" parameter
+   Example 1.22. Set the "ds_ping_from" parameter
  ...
  modparam("dispatcher", "ds_ping_from", "sip:proxy at sip.somehost.com")
  ...
 
-3.21. ds_ping_interval (int)
+3.22. ds_ping_interval (int)
 
    With this parameter you can define the interval for sending a request
    to a gateway marked as inactive upon a failed request routing to it.
@@ -580,12 +628,12 @@ Note
 
    Default value is "0".
 
-   Example 1.22. Set the "ds_ping_interval" parameter
+   Example 1.23. Set the "ds_ping_interval" parameter
  ...
  modparam("dispatcher", "ds_ping_interval", 30)
  ...
 
-3.22. ds_probing_threshold (int)
+3.23. ds_probing_threshold (int)
 
    If you want to set a gateway into inactive mode, there can be a
    specific number of failed requests until it will change from "active"
@@ -596,12 +644,27 @@ Note
 
    Default value is "1" (set inactive with first failure).
 
-   Example 1.23. Set the "ds_probing_threshhold" parameter
+   Example 1.24. Set the "ds_probing_threshold" parameter
+ ...
+ modparam("dispatcher", "ds_probing_threshold", 10)
+ ...
+
+3.24. ds_inactive_threshold (int)
+
+   If you want to set a gateway into active mode (after being inactive),
+   there can be a specific number of successful requests until it will
+   change from "inactive" to "active". The number of attempts can be set
+   with this parameter. This parameter can be modified via ser config
+   framework.
+
+   Default value is "1" (set active with first success).
+
+   Example 1.25. Set the "ds_inactive_threshold" parameter
  ...
- modparam("dispatcher", "ds_probing_threshhold", 10)
+ modparam("dispatcher", "ds_inactive_threshold", 10)
  ...
 
-3.23. ds_ping_reply_codes (string)
+3.25. ds_ping_reply_codes (string)
 
    This parameter defines the valid response codes, which are accepted as
    a valid reply to the PING-Method. It is a list separated by colons,
@@ -613,13 +676,13 @@ Note
 
    Default value is "" (only 200 OK is accepted).
 
-   Example 1.24. Set the "ds_ping_reply_codes" parameter
+   Example 1.26. Set the "ds_ping_reply_codes" parameter
  ...
  modparam("dispatcher", "ds_ping_reply_codes", "class=2;code=403;code=488;class=
 3")
  ...
 
-3.24. ds_probing_mode (int)
+3.26. ds_probing_mode (int)
 
    Controls what gateways are tested to see if they are reachable. If set
    to 0, only the gateways with state PROBING are tested; if set to 1, all
@@ -629,12 +692,12 @@ Note
 
    Default value is "0".
 
-   Example 1.25. Set the "ds_probing_mode" parameter
+   Example 1.27. Set the "ds_probing_mode" parameter
  ...
  modparam("dispatcher", "ds_probing_mode", 1)
  ...
 
-3.25. ds_hash_size (int)
+3.27. ds_hash_size (int)
 
    The value to be used as power of two to set the number of slots to hash
    table storing data for call load dispatching (e.g., value 8 will create
@@ -643,24 +706,24 @@ Note
 
    Default value is "0".
 
-   Example 1.26. Set the "ds_hash_size" parameter
+   Example 1.28. Set the "ds_hash_size" parameter
  ...
  modparam("dispatcher", "ds_hash_size", 9)
  ...
 
-3.26. ds_hash_expire (int)
+3.28. ds_hash_expire (int)
 
    Expiration time in seconds to remove the load on a destination if no
    BYE was received meanwhile.
 
    Default value is "7200".
 
-   Example 1.27. Set the "ds_hash_expire" parameter
+   Example 1.29. Set the "ds_hash_expire" parameter
  ...
  modparam("dispatcher", "ds_hash_expire", 3600)
  ...
 
-3.27. ds_hash_initexpire (int)
+3.29. ds_hash_initexpire (int)
 
    Expiration time in seconds to remove the load on a destination if no
    200 for INVITE was received meanwhile and state updated with
@@ -668,34 +731,47 @@ Note
 
    Default value is "7200".
 
-   Example 1.28. Set the "ds_hash_initexpire" parameter
+   Example 1.30. Set the "ds_hash_initexpire" parameter
  ...
  modparam("dispatcher", "ds_hash_initexpire", 60)
  ...
 
-3.28. ds_hash_check_interval (int)
+3.30. ds_hash_check_interval (int)
 
    Time interval in seconds to scan internal hash table with call load
    dispatching data for expired items.
 
    Default value is "30".
 
-   Example 1.29. Set the "ds_hash_check_interval" parameter
+   Example 1.31. Set the "ds_hash_check_interval" parameter
  ...
  modparam("dispatcher", "ds_hash_check_interval", 60)
  ...
 
-3.29. outbound_proxy (str)
+3.31. outbound_proxy (str)
 
    SIP URI of outbound proxy to be used when sending pings.
 
    By default no outbound proxy is defined.
 
-   Example 1.30. Set the "outbound_proxy" parameter
+   Example 1.32. Set the "outbound_proxy" parameter
  ...
  modparam("dispatcher", "outbound_proxy", "sip:outbound.example.com")
  ...
 
+3.32. ds_default_socket (str)
+
+   Default socket to be used for sending pings and dispatching requests
+   when a gateway has no send socket configured.
+
+   By default no default socket is defined, the first configuration script
+   listen directive is used.
+
+   Example 1.33. Set the "ds_default_socket" parameter
+ ...
+ modparam("dispatcher", "ds_default_socket", "udp:192.168.0.125:5060")
+ ...
+
 4. Functions
 
    4.1. ds_select_dst(set, alg[, limit])
@@ -703,11 +779,12 @@ Note
    4.3. ds_next_dst()
    4.4. ds_next_domain()
    4.5. ds_mark_dst([state])
-   4.6. ds_is_from_list([groupid [, mode [, uri] ] ])
-   4.7. ds_load_update()
-   4.8. ds_load_unset()
+   4.6. ds_list_exist(groupid)
+   4.7. ds_is_from_list([groupid [, mode [, uri] ] ])
+   4.8. ds_load_update()
+   4.9. ds_load_unset()
 
-4.1. ds_select_dst(set, alg[, limit])
+4.1.  ds_select_dst(set, alg[, limit])
 
    The method selects a destination from addresses set. It returns true if
    a new destination is set. The selected address is set to dst_uri field
@@ -734,10 +811,11 @@ Note
           + "5" - hash over authorization-username (Proxy-Authorization or
             "normal" authorization). If no username is found, round robin
             is used.
-          + "6" - random (using rand()).
+          + "6" - random destination (using rand()).
           + "7" - hash over the content of PVs string. Note: This works
             only when the parameter hash_pvar is set.
-          + "8" - use first destination (good for failover).
+          + "8" - select destination sorted by priority attribute value
+            (serial forking ordered by priority).
           + "9" - use weight based load distribution. You have to set the
             attribute 'weight' per each address in destination set.
           + "10" - use call load distribution. You have to set the
@@ -768,7 +846,7 @@ Note
 
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE.
 
-   Example 1.31. ds_select_dst usage
+   Example 1.34. ds_select_dst usage
 ...
 ds_select_dst("1", "0");
 ...
@@ -778,7 +856,7 @@ ds_select_dst("1", "$var(a)");
 ds_select_dst("1", "4", "3");
 ...
 
-4.2. ds_select_domain(set, alg[, limit])
+4.2.  ds_select_domain(set, alg[, limit])
 
    The method selects a destination from addresses set and rewrites the
    host and port from R-URI. The parameters have same meaning as for
@@ -791,21 +869,21 @@ ds_select_dst("1", "4", "3");
 
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE.
 
-4.3. ds_next_dst()
+4.3.  ds_next_dst()
 
    Takes the next destination address from the AVPs with id 'dst_avp_id'
    and sets the dst_uri (outbound proxy address).
 
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE.
 
-4.4. ds_next_domain()
+4.4.  ds_next_domain()
 
    Takes the next destination address from the AVPs with id 'dst_avp_id'
    and sets the domain part of the request URI.
 
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE.
 
-4.5. ds_mark_dst([state])
+4.5.  ds_mark_dst([state])
 
    Mark the last used address from destination set as inactive ("i"/"I"),
    active ("a"/"A"), disabled ("d"/"D") or trying ("t"/"T"). Apart of
@@ -832,7 +910,7 @@ ds_select_dst("1", "4", "3");
 
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE.
 
-   Example 1.32. ds_mark_dst usage
+   Example 1.35. ds_mark_dst usage
 ...
 failure_route[tryagain] {
 ...
@@ -842,7 +920,21 @@ failure_route[tryagain] {
 }
 ...
 
-4.6. ds_is_from_list([groupid [, mode [, uri] ] ])
+4.6.  ds_list_exist(groupid)
+
+   Check if a specific group is defined in dispatcher list or database.
+     * groupid - A group ID to check.
+
+   This function can be used from ANY_ROUTE.
+
+   Example 1.36. ds_list_exist usage
+...
+if(ds_list_exist("10")) {
+    ...
+}
+...
+
+4.7.  ds_is_from_list([groupid [, mode [, uri] ] ])
 
    This function returns true, if there is a match of source address or
    uri with an address in the given group of the dispatcher-list;
@@ -878,7 +970,7 @@ failure_route[tryagain] {
 
    This function can be used from ANY_ROUTE.
 
-   Example 1.33. ds_mark_dst usage
+   Example 1.37. ds_is_from_list usage
 ...
 if(ds_is_from_list()) {
     ...
@@ -886,12 +978,15 @@ if(ds_is_from_list()) {
 if(ds_is_from_list("10")) {
     ...
 }
-if(ds_is_from_list("10", "sip:127.0.0.1:5080", "3")) {
+if(ds_is_from_list("10", "3")) {
+    ...
+}
+if(ds_is_from_list("10", "3", "sip:127.0.0.1:5080")) {
     ...
 }
 ...
 
-4.7. ds_load_update()
+4.8.  ds_load_update()
 
    Updates the load state:
      * if it is a BYE or CANCEL - remove the load from destination address
@@ -902,14 +997,14 @@ if(ds_is_from_list("10", "sip:127.0.0.1:5080", "3")) {
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE,
    BRANCH_ROUTE and ONREPLY_ROUTE.
 
-4.8. ds_load_unset()
+4.9.  ds_load_unset()
 
    Remove the call load for the destination that routed the call.
 
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE,
    BRANCH_ROUTE and ONREPLY_ROUTE.
 
-   Example 1.34. ds_load_unset usage
+   Example 1.38. ds_load_unset usage
 ...
 route {
     ...
@@ -939,7 +1034,7 @@ onreply_route {
    5.2. ds_list
    5.3. ds_reload
 
-5.1. ds_set_state
+5.1.  ds_set_state
 
    Sets the status for a destination address (can be use to mark the
    destination as active or inactive).
@@ -964,7 +1059,7 @@ onreply_route {
                 _address_
                 _empty_line_
 
-5.2. ds_list
+5.2.  ds_list
 
    It lists the groups and included destinations.
 
@@ -976,7 +1071,7 @@ onreply_route {
                 :ds_list:_reply_fifo_file_
                 _empty_line_
 
-5.3. ds_reload
+5.3.  ds_reload
 
    It reloads the groups and included destinations. For algorithm 10 (call
    load distribution), old internal list of active calls is destroyed
@@ -996,7 +1091,7 @@ onreply_route {
    6.2. dispatcher.list
    6.3. dispatcher.reload
 
-6.1. dispatcher.set_state
+6.1.  dispatcher.set_state
 
    Sets the state for a destination address (can be use to mark the
    destination as active or inactive).
@@ -1020,7 +1115,7 @@ onreply_route {
 kamcmd dispatcher.set_state ip 2 sip:127.0.0.1:5080
 ...
 
-6.2. dispatcher.list
+6.2.  dispatcher.list
 
    Lists the groups and included destinations.
 
@@ -1031,7 +1126,7 @@ kamcmd dispatcher.set_state ip 2 sip:127.0.0.1:5080
    Example:
                 kamcmd dispatcher.list
 
-6.3. dispatcher.reload
+6.3.  dispatcher.reload
 
    Reloads the groups and included destinations. The command is disabled
    for call load based dispatching (algorithm 10) since removal of
@@ -1069,9 +1164,6 @@ kamcmd dispatcher.set_state ip 2 sip:127.0.0.1:5080
      * priority: sets the priority in destination list (based on it is
        done the initial ordering inside the set)
      * attributes: extra fields in form of name1=value1;...;nameN=valueN.
-       There are some reserved names for attributes used by the module for
-       specific load balancing algorithms, see the section 'Special
-       Attributes'.
 
 7.1.1. Special Attributes
 
@@ -1099,13 +1191,13 @@ setid(int) destination(sip uri) flags(int,opt) priority(int,opt) attrs(str,opt)
 
    Full line example:
 ...
-1 sip:127.0.0.1:5080 0 0 duid=abc;my=xyz
+1 sip:127.0.0.1:5080 0 0 duid=abc;socket=udp:192.168.0.125:5060;my=xyz
 ...
 
    For database, each element of a line resides in a different column.
    Next is a dispatcher.list file example:
 
-   Example 1.35. dispatcher list file
+   Example 1.39. dispatcher list file
 ...
 # $Id$
 # dispatcher destination sets
@@ -1130,7 +1222,7 @@ r,opt)
 
    Next picture shows a sample usage of the dispatcher module.
 
-   Example 1.36. Kamailio config script - sample dispatcher usage
+   Example 1.40. Kamailio config script - sample dispatcher usage
 ...
 #!KAMAILIO
 #
@@ -1421,7 +1513,7 @@ failure_route[RTF_DISPATCH] {
    8.1. dispatcher:dst-down
    8.2. dispatcher:dst-up
 
-8.1. dispatcher:dst-down
+8.1.  dispatcher:dst-down
 
    When defined, the module calls event_route[dispatcher:ds-down] when a
    destination goes down (becomes probing). A typical use case is to
@@ -1432,7 +1524,7 @@ event_route[dispatcher:dst-down] {
 }
 ...
 
-8.2. dispatcher:dst-up
+8.2.  dispatcher:dst-up
 
    When defined, the module calls event_route[dispatcher:ds-up] when a
    destination that was previously down (probing) comes up. A typical use
@@ -1453,51 +1545,51 @@ Chapter 2. Frequently Asked Questions
 
    2.1.
 
-   Does dispatcher provide a fair distribution?
+       Does dispatcher provide a fair distribution?
 
-   The algoritms doing hashing over parts of SIP message don't guarantee a
-   fair distribution. You should do some measurements to decide what
-   hashing algorithm fits better in your environment.
+       The algoritms doing hashing over parts of SIP message don't guarantee a
+       fair distribution. You should do some measurements to decide what
+       hashing algorithm fits better in your environment.
 
-   Other distribution algorithms such as round robin or call load
-   dispatching do a fair distribution in terms of delivered calls to
-   gateways.
+       Other distribution algorithms such as round robin or call load
+       dispatching do a fair distribution in terms of delivered calls to
+       gateways.
 
    2.2.
 
-   Is dispatcher dialog stateful?
+       Is dispatcher dialog stateful?
 
-   No. Dispatcher is stateless, although some distribution algorithms are
-   designed to select same destination for subsequent requests of the same
-   dialog (e.g., hashing the call-id).
+       No. Dispatcher is stateless, although some distribution algorithms are
+       designed to select same destination for subsequent requests of the same
+       dialog (e.g., hashing the call-id).
 
    2.3.
 
-   Where can I find more about Kamailio?
+       Where can I find more about Kamailio?
 
-   Take a look at http://www.kamailio.org/.
+       Take a look at http://www.kamailio.org/.
 
    2.4.
 
-   Where can I post a question about this module?
+       Where can I post a question about this module?
 
-   First at all check if your question was already answered on one of our
-   mailing lists:
-     * User Mailing List -
-       http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-users
-     * Developer Mailing List -
-       http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-dev
+       First at all check if your question was already answered on one of our
+       mailing lists:
+         * User Mailing List -
+           http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-users
+         * Developer Mailing List -
+           http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-dev
 
-   E-mails regarding any stable version should be sent to
-   <sr-users at lists.sip-router.org> and e-mail regarding development
-   versions or GIT snapshots should be send to
-   <sr-dev at lists.sip-router.org>.
+       E-mails regarding any stable version should be sent to
+       <sr-users at lists.sip-router.org> and e-mail regarding development
+       versions or GIT snapshots should be send to
+       <sr-dev at lists.sip-router.org>.
 
-   If you want to keep the mail private, send it to
-   <sr-users at lists.sip-router.org>.
+       If you want to keep the mail private, send it to
+       <sr-users at lists.sip-router.org>.
 
    2.5.
 
-   How can I report a bug?
+       How can I report a bug?
 
-   Please follow the guidelines provided at: http://sip-router.org/tracker
+       Please follow the guidelines provided at: http://sip-router.org/tracker
diff --git a/modules/dispatcher/api.h b/modules/dispatcher/api.h
index df4d765..2d68ae0 100644
--- a/modules/dispatcher/api.h
+++ b/modules/dispatcher/api.h
@@ -1,6 +1,4 @@
 /**
- * $Id$
- *
  * dispatcher module
  * 
  * Copyright (C) 2004-2006 FhG Fokus
diff --git a/modules/dispatcher/config.c b/modules/dispatcher/config.c
index 8d07da1..fea2ffa 100644
--- a/modules/dispatcher/config.c
+++ b/modules/dispatcher/config.c
@@ -1,6 +1,5 @@
 /*
- * $Id$
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
  * SIP-router is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -31,16 +30,22 @@
 #include "config.h"
 
 struct cfg_group_dispatcher	default_dispatcher_cfg = {
-		3,	/* Probing threshhold */	
+		1,	/* Probing threshold */	
+		1,      /* Inactive threshold */
 		{0,0}	/* reply codes */
 	    };
 
 void	*dispatcher_cfg = &default_dispatcher_cfg;
 
 cfg_def_t	dispatcher_cfg_def[] = {
-	{"probing_threshhold",		CFG_VAR_INT | CFG_ATOMIC, 	0, 0, 0, 0,
+	{"probing_threshold",		CFG_VAR_INT | CFG_ATOMIC,
+		0, 0, 0, 0,
 		"Number of failed requests, before a destination is set to probing."},
-	{"ping_reply_codes",		CFG_VAR_STR | CFG_CB_ONLY_ONCE ,			0, 0, 0, ds_ping_reply_codes_update,
+	{"inactive_threshold",           CFG_VAR_INT | CFG_ATOMIC,
+		0, 0, 0, 0,
+        "Number of successful requests, before a destination is set to active."},
+	{"ping_reply_codes",		CFG_VAR_STR | CFG_CB_ONLY_ONCE
+		,			0, 0, 0, ds_ping_reply_codes_update,
 		"Additional, valid reply codes for the OPTIONS Pinger. Default is \"\""},
 	{0, 0, 0, 0, 0, 0}
 };
diff --git a/modules/dispatcher/config.h b/modules/dispatcher/config.h
index 9f028af..2fd3559 100644
--- a/modules/dispatcher/config.h
+++ b/modules/dispatcher/config.h
@@ -1,7 +1,12 @@
 /*
- * $Id$
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -27,7 +32,8 @@
 #include "../../str.h"
 
 struct cfg_group_dispatcher {
-	int probing_threshhold;
+	int probing_threshold;
+	int inactive_threshold;
 	str ds_ping_reply_codes_str;
 };
 
diff --git a/modules/dispatcher/dispatch.c b/modules/dispatcher/dispatch.c
index f9b9cc0..7491a5f 100644
--- a/modules/dispatcher/dispatch.c
+++ b/modules/dispatcher/dispatch.c
@@ -1,10 +1,9 @@
 /*
- * $Id$
- *
  * dispatcher module
  *
  * Copyright (C) 2004-2006 FhG Fokus
  * Copyright (C) 2005 Voice-System.ro
+ * Copyright (C) 2015 Daniel-Constantin Mierla (asipto.com)
  *
  * This file is part of Kamailio, a free SIP server.
  *
@@ -21,23 +20,6 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- *
- * History
- * -------
- * 2004-07-31  first version, by daniel
- * 2005-04-22  added ruri  & to_uri hashing (andrei)
- * 2005-12-10  added failover support via avp (daniel)
- * 2006-08-15  added support for authorization username hashing (carsten)
- * 2007-01-11  Added a function to check if a specific gateway is in a
- * group (carsten)
- * 2007-01-12  Added a threshhold for automatic deactivation (carsten)
- * 2007-02-09  Added active probing of failed destinations and automatic
- * re-enabling of destinations (carsten)
- * 2007-05-08  Ported the changes to SVN-Trunk, renamed ds_is_domain to
- * ds_is_from_list and modified the function to work with IPv6 adresses.
- * 2007-07-18  removed index stuff
- * 			   added DB support to load/reload data(ancuta)
- * 2007-09-17  added list-file support for reload data (carstenbock)
  */
 
 /*! \file
@@ -232,6 +214,9 @@ int ds_set_attrs(ds_dest_t *dest, str *attrs)
 		} else if(pit->name.len==7
 				&& strncasecmp(pit->name.s, "maxload", 7)==0) {
 			str2sint(&pit->body, &dest->attrs.maxload);
+		} else if(pit->name.len==6
+				&& strncasecmp(pit->name.s, "socket", 6)==0) {
+			dest->attrs.socket = pit->body;
 		}
 	}
 	return 0;
@@ -253,6 +238,8 @@ int add_dest2list(int id, str uri, int flags, int priority, str *attrs,
 	struct hostent* he;
 	struct sip_uri puri;
 	int orig_id = 0, orig_nr = 0;
+	str host;
+	int port, proto;
 	ds_set_t *orig_ds_lists = ds_lists[list_idx];
 
 	/* check uri */
@@ -315,6 +302,7 @@ int add_dest2list(int id, str uri, int flags, int priority, str *attrs,
 	strncpy(dp->uri.s, uri.s, uri.len);
 	dp->uri.s[uri.len]='\0';
 	dp->uri.len = uri.len;
+
 	dp->flags = flags;
 	dp->priority = priority;
 
@@ -324,6 +312,22 @@ int add_dest2list(int id, str uri, int flags, int priority, str *attrs,
 		goto err;
 	}
 
+	/* check socket attribute */
+	if (dp->attrs.socket.s && dp->attrs.socket.len > 0) {
+		if (parse_phostport(dp->attrs.socket.s, &host.s, &host.len,
+				&port, &proto)!=0) {
+			LM_ERR("bad socket <%.*s>\n", dp->attrs.socket.len, dp->attrs.socket.s);
+			goto err;
+		}
+		dp->sock = grep_sock_info( &host, (unsigned short)port, proto);
+		if (dp->sock==0) {
+			LM_ERR("non-local socket <%.*s>\n", dp->attrs.socket.len, dp->attrs.socket.s);
+			goto err;
+		}
+	} else if (ds_default_sockinfo) {
+		dp->sock = ds_default_sockinfo;
+	}
+
 	/* The Hostname needs to be \0 terminated for resolvehost, so we
 	 * make a copy here. */
 	strncpy(hn, puri.host.s, puri.host.len);
@@ -340,7 +344,7 @@ int add_dest2list(int id, str uri, int flags, int priority, str *attrs,
 	hostent2ip_addr(&dp->ip_address, he, 0);
 
 	/* Copy the port out of the URI */
-	dp->port = puri.port_no;		
+	dp->port = puri.port_no;
 	/* Copy the proto out of the URI */
 	dp->proto = puri.proto;
 
@@ -593,11 +597,11 @@ int ds_load_list(char *lfile)
 		while(*p && (*p==' ' || *p=='\t' || *p=='\r' || *p=='\n'))
 			p++;
 		if(*p=='\0' || *p=='#')
-			goto add_destination; /* no priority given */
+			goto add_destination; /* no attrs given */
 
 		/* get attributes */
 		attrs.s = p;
-		while(*p && *p!=' ' && *p!='\t' && *p!='\r' && *p!='\n' && *p!='#')
+		while(*p && *p!=' ' && *p!='\t' && *p!='\r' && *p!='\n')
 			p++;
 		attrs.len = p-attrs.s;
 
@@ -1266,6 +1270,33 @@ static inline int ds_get_index(int group, ds_set_t **index)
 	return 0;
 }
 
+/*
+ * Check if a destination set exists
+ */
+int ds_list_exist(int set)
+{
+	ds_set_t *si = NULL;
+	LM_DBG("-- Looking for set %d\n", set);
+
+	/* get the index of the set */
+	si = _ds_list;
+	while(si)
+	{
+		if(si->id == set)
+		{
+			break;
+		}
+		si = si->next;
+	}
+
+	if(si==NULL)
+	{
+		LM_INFO("destination set [%d] not found\n", set);
+		return -1;	/* False */
+	}
+	LM_INFO("destination set [%d] found\n", set);
+	return 1;	/* True */
+}
 
 /**
  *
@@ -1570,7 +1601,8 @@ int ds_load_unset(struct sip_msg *msg)
 /**
  *
  */
-static inline int ds_update_dst(struct sip_msg *msg, str *uri, int mode)
+static inline int ds_update_dst(struct sip_msg *msg, str *uri,
+								struct socket_info *sock, int mode)
 {
 	struct action act;
 	struct run_act_ctx ra_ctx;
@@ -1601,6 +1633,8 @@ static inline int ds_update_dst(struct sip_msg *msg, str *uri, int mode)
 			ruri_mark_new(); /* re-use uri for serial forking */
 			break;
 	}
+	if (sock)
+		msg->force_send_socket = sock;
 	return 0;
 }
 
@@ -1625,6 +1659,7 @@ int ds_select_dst_limit(sip_msg_t *msg, int set, int alg, unsigned int limit, in
 	unsigned int hash;
 	int_str avp_val;
 	ds_set_t *idx = NULL;
+	char buf[2+16+1];
 
 	if(msg==NULL)
 	{
@@ -1802,7 +1837,7 @@ int ds_select_dst_limit(sip_msg_t *msg, int set, int alg, unsigned int limit, in
 
 	hash = i;
 
-	if(ds_update_dst(msg, &idx->dlist[hash].uri, mode)!=0)
+	if(ds_update_dst(msg, &idx->dlist[hash].uri, idx->dlist[hash].sock, mode)!=0)
 	{
 		LM_ERR("cannot set dst addr\n");
 		return -1;
@@ -1833,6 +1868,17 @@ int ds_select_dst_limit(sip_msg_t *msg, int set, int alg, unsigned int limit, in
 							avp_val)!=0)
 					return -1;
 			}
+
+			/* only add sock_avp if dst_avp is set */
+			if(sock_avp_name.n!=0 && idx->dlist[idx->nr-1].sock)
+			{
+				avp_val.s.len = 1 + sprintf(buf, "%p", idx->dlist[idx->nr-1].sock);
+				avp_val.s.s = buf;
+				if(add_avp(AVP_VAL_STR|sock_avp_type, sock_avp_name,
+							avp_val)!=0)
+					return -1;
+			}
+
 			if(alg==DS_ALG_LOAD)
 			{
 				if(idx->dlist[idx->nr-1].attrs.duid.len<=0)
@@ -1853,7 +1899,7 @@ int ds_select_dst_limit(sip_msg_t *msg, int set, int alg, unsigned int limit, in
 		/* add to avp */
 
 		for(i=hash-1; i>=0 && cnt<limit; i--)
-		{	
+		{
 			if(ds_skip_dst(idx->dlist[i].flags)
 					|| (ds_use_default!=0 && i==(idx->nr-1)))
 				continue;
@@ -1873,6 +1919,16 @@ int ds_select_dst_limit(sip_msg_t *msg, int set, int alg, unsigned int limit, in
 							avp_val)!=0)
 					return -1;
 			}
+
+			if(sock_avp_name.n!=0 && idx->dlist[i].sock)
+			{
+				avp_val.s.len = 1 + sprintf(buf, "%p", idx->dlist[i].sock);
+				avp_val.s.s = buf;
+				if(add_avp(AVP_VAL_STR|sock_avp_type, sock_avp_name,
+							avp_val)!=0)
+					return -1;
+			}
+
 			if(alg==DS_ALG_LOAD)
 			{
 				if(idx->dlist[i].attrs.duid.len<=0)
@@ -1891,7 +1947,7 @@ int ds_select_dst_limit(sip_msg_t *msg, int set, int alg, unsigned int limit, in
 		}
 
 		for(i=idx->nr-1; i>hash && cnt<limit; i--)
-		{	
+		{
 			if(ds_skip_dst(idx->dlist[i].flags)
 					|| (ds_use_default!=0 && i==(idx->nr-1)))
 				continue;
@@ -1910,6 +1966,16 @@ int ds_select_dst_limit(sip_msg_t *msg, int set, int alg, unsigned int limit, in
 							avp_val)!=0)
 					return -1;
 			}
+
+			if(sock_avp_name.n!=0 && idx->dlist[i].sock)
+			{
+				avp_val.s.len = 1 + sprintf(buf, "%p", idx->dlist[i].sock);
+				avp_val.s.s = buf;
+				if(add_avp(AVP_VAL_STR|sock_avp_type, sock_avp_name,
+							avp_val)!=0)
+					return -1;
+			}
+
 			if(alg==DS_ALG_LOAD)
 			{
 				if(idx->dlist[i].attrs.duid.len<=0)
@@ -1939,6 +2005,15 @@ int ds_select_dst_limit(sip_msg_t *msg, int set, int alg, unsigned int limit, in
 						avp_val)!=0)
 				return -1;
 		}
+		if(sock_avp_name.n!=0 && idx->dlist[hash].sock)
+		{
+			avp_val.s.len = 1 + sprintf(buf, "%p", idx->dlist[hash].sock);
+			avp_val.s.s = buf;
+			if(add_avp(AVP_VAL_STR|sock_avp_type, sock_avp_name,
+						avp_val)!=0)
+				return -1;
+		}
+
 		if(alg==DS_ALG_LOAD)
 		{
 			if(idx->dlist[hash].attrs.duid.len<=0)
@@ -1980,7 +2055,9 @@ int ds_next_dst(struct sip_msg *msg, int mode)
 	struct search_state st;
 	struct usr_avp *avp;
 	struct usr_avp *prev_avp;
+	struct socket_info *sock = NULL;
 	int_str avp_value;
+	int_str sock_avp_value;
 	int alg = 0;
 
 	if(!(ds_flags&DS_FAILOVER_ON) || dst_avp_name.n==0)
@@ -2012,6 +2089,18 @@ int ds_next_dst(struct sip_msg *msg, int mode)
 		}
 	}
 
+	if(sock_avp_name.n!=0)
+	{
+		prev_avp = search_first_avp(sock_avp_type,
+				attrs_avp_name, &sock_avp_value, &st);
+		if(prev_avp!=NULL)
+		{
+			if (sscanf( sock_avp_value.s.s, "%p", (void**)&sock ) != 1)
+				sock = NULL;
+			destroy_avp(prev_avp);
+		}
+	}
+
 	prev_avp = search_first_avp(dst_avp_type, dst_avp_name, &avp_value, &st);
 	if(prev_avp==NULL)
 		return -1; /* used avp deleted -- strange */
@@ -2021,7 +2110,7 @@ int ds_next_dst(struct sip_msg *msg, int mode)
 	if(avp==NULL || !(avp->flags&AVP_VAL_STR))
 		return -1; /* no more avps or value is int */
 
-	if(ds_update_dst(msg, &avp_value.s, mode)!=0)
+	if(ds_update_dst(msg, &avp_value.s, sock, mode)!=0)
 	{
 		LM_ERR("cannot set dst addr\n");
 		return -1;
@@ -2078,12 +2167,49 @@ int ds_mark_dst(struct sip_msg *msg, int state)
 }
 
 /**
- *
+ * Get state for given destination
+ */
+int ds_get_state(int group, str *address)
+{
+	int i=0;
+	int state = 0;
+	ds_set_t *idx = NULL;
+
+	if(_ds_list==NULL || _ds_list_nr<=0)
+	{
+		LM_ERR("the list is null\n");
+		return -1;
+	}
+
+	/* get the index of the set */
+	if(ds_get_index(group, &idx)!=0)
+	{
+		LM_ERR("destination set [%d] not found\n", group);
+		return -1;
+	}
+
+	while(i<idx->nr)
+	{
+		if(idx->dlist[i].uri.len==address->len
+				&& strncasecmp(idx->dlist[i].uri.s, address->s,
+					address->len)==0)
+		{
+			/* destination address found */
+			state = idx->dlist[i].flags;
+		}
+		i++;
+	}
+	return state;
+}
+
+/**
+ * Update destionation's state
  */
 int ds_update_state(sip_msg_t *msg, int group, str *address, int state)
 {
 	int i=0;
 	int old_state = 0;
+	int init_state = 0;
 	ds_set_t *idx = NULL;
 
 	if(_ds_list==NULL || _ds_list_nr<=0)
@@ -2111,6 +2237,9 @@ int ds_update_state(sip_msg_t *msg, int group, str *address, int state)
 			/* reset the bits used for states */
 			idx->dlist[i].flags &= ~(DS_STATES_ALL);
 
+			/* we need the initial state for inactive counter */
+			init_state = state;
+
 			if((state & DS_TRYING_DST) && (old_state & DS_INACTIVE_DST))
 			{
 				/* old state is inactive, new state is trying => keep it inactive
@@ -2129,15 +2258,30 @@ int ds_update_state(sip_msg_t *msg, int group, str *address, int state)
 
 			if(state & DS_TRYING_DST)
 			{
-				idx->dlist[i].failure_count++;
-				if (idx->dlist[i].failure_count >= probing_threshhold)
+				idx->dlist[i].message_count++;
+				/* Destination is not replying.. Increasing failure counter */
+				if (idx->dlist[i].message_count >= probing_threshold)
 				{
+					/* Destionation has too much lost messages.. Bringing it to inactive state */
 					idx->dlist[i].flags &= ~DS_TRYING_DST;
 					idx->dlist[i].flags |= DS_INACTIVE_DST;
-					idx->dlist[i].failure_count = 0;
+					idx->dlist[i].message_count = 0;
 				}
 			} else {
-				idx->dlist[i].failure_count = 0;
+				if(!(init_state & DS_TRYING_DST) && (old_state & DS_INACTIVE_DST)){
+					idx->dlist[i].message_count++;
+					/* Destination was inactive but it is just replying.. Increasing successful counter */
+					if (idx->dlist[i].message_count < inactive_threshold)
+					{
+						/* Destination has not enough successful replies.. Leaving it into inactive state */
+						idx->dlist[i].flags |= DS_INACTIVE_DST;
+					}else{
+						/* Destination has enough replied messages.. Bringing it to active state */
+						idx->dlist[i].message_count = 0;
+					}
+				}else{
+					idx->dlist[i].message_count = 0;
+				}
 			}
 
 			if (!ds_skip_dst(old_state) && ds_skip_dst(idx->dlist[i].flags))
@@ -2266,10 +2410,10 @@ int ds_print_list(FILE *fout)
 			else if (list->dlist[j].flags&DS_TRYING_DST) {
 				fprintf(fout, "    Trying");
 				/* print the tries for this host. */
-				if (list->dlist[j].failure_count > 0) {
+				if (list->dlist[j].message_count > 0) {
 					fprintf(fout, " (Fail %d/%d)",
-							list->dlist[j].failure_count,
-							probing_threshhold);
+							list->dlist[j].message_count,
+							probing_threshold);
 				} else {
 					fprintf(fout, "           ");
 				}
@@ -2495,7 +2639,8 @@ static void ds_options_callback( struct cell *t, int type,
 		state = 0;
 		if (ds_probing_mode==DS_PROBE_ALL)
 			state |= DS_PROBING_DST;
-		if (ds_update_state(fmsg, group, &uri, state) != 0)
+		/* Check if in the meantime someone disabled the target through RPC or MI */
+		if (!(ds_get_state(group, &uri) & DS_DISABLED_DST) && ds_update_state(fmsg, group, &uri, state) != 0)
 		{
 			LM_ERR("Setting the state failed (%.*s, group %d)\n", uri.len,
 					uri.s, group);
@@ -2504,8 +2649,8 @@ static void ds_options_callback( struct cell *t, int type,
 		state = DS_TRYING_DST;
 		if (ds_probing_mode!=DS_PROBE_NONE)
 			state |= DS_PROBING_DST;
-
-		if (ds_update_state(fmsg, group, &uri, state) != 0)
+		/* Check if in the meantime someone disabled the target through RPC or MI */
+		if (!(ds_get_state(group, &uri) & DS_DISABLED_DST) && ds_update_state(fmsg, group, &uri, state) != 0)
 		{
 			LM_ERR("Setting the probing state failed (%.*s, group %d)\n",
 					uri.len, uri.s, group);
@@ -2555,6 +2700,11 @@ void ds_check_timer(unsigned int ticks, void* param)
 				set_uac_req(&uac_r, &ds_ping_method, 0, 0, 0,
 						TMCB_LOCAL_COMPLETED, ds_options_callback,
 						(void*)(long)list->id);
+				if (list->dlist[j].attrs.socket.s != NULL && list->dlist[j].attrs.socket.len > 0) {
+					uac_r.ssock = &list->dlist[j].attrs.socket;
+				} else if (ds_default_socket.s != NULL && ds_default_socket.len > 0) {
+					uac_r.ssock = &ds_default_socket;
+				}
 				if (tmb.t_request(&uac_r,
 							&list->dlist[j].uri,
 							&list->dlist[j].uri,
diff --git a/modules/dispatcher/dispatch.h b/modules/dispatcher/dispatch.h
index e0466d8..bd43553 100644
--- a/modules/dispatcher/dispatch.h
+++ b/modules/dispatcher/dispatch.h
@@ -1,6 +1,4 @@
 /**
- * $Id$
- *
  * dispatcher module
  * 
  * Copyright (C) 2004-2006 FhG Fokus
@@ -20,16 +18,6 @@
  * You should have received a copy of the GNU General Public License 
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- *
- * History
- * -------
- * 2004-07-31  first version, by daniel
- * 2007-01-11  Added a function to check if a specific gateway is in
- *		a group (carsten)
- * 2007-02-09  Added active probing of failed destinations and automatic
- *		re-enabling of destinations
- * 2007-05-08  Ported the changes to SVN-Trunk and renamed ds_is_domain
- *		to ds_is_from_list.
  */
 
 /*! \file
@@ -86,6 +74,8 @@ extern int_str dstid_avp_name;
 extern unsigned short dstid_avp_type;
 extern int_str attrs_avp_name;
 extern unsigned short attrs_avp_type;
+extern int_str sock_avp_name;
+extern unsigned short sock_avp_type;
 
 extern pv_elem_t * hash_param_model;
 
@@ -98,10 +88,14 @@ extern pv_spec_t ds_attrs_pv;
 extern struct tm_binds tmb;
 extern str ds_ping_method;
 extern str ds_ping_from;
-extern int probing_threshhold; /*!< number of failed requests,
-								 before a destination is taken into probing */ 
+extern int probing_threshold; /*!< number of failed requests,
+								before a destination is taken into probing */
+extern int inactive_threshold; /*!< number of successful requests, 
+								before a destination is taken into active */
 extern int ds_probing_mode;
 extern str ds_outbound_proxy;
+extern str ds_default_socket;
+extern struct socket_info * ds_default_sockinfo;
 
 int init_data(void);
 int init_ds_db(void);
@@ -120,6 +114,8 @@ int ds_mark_dst(struct sip_msg *msg, int mode);
 int ds_print_list(FILE *fout);
 int ds_print_mi_list(struct mi_node* rpl);
 int ds_print_sets(void);
+int ds_list_exist(int set);
+
 
 int ds_load_unset(struct sip_msg *msg);
 int ds_load_update(struct sip_msg *msg);
@@ -150,6 +146,7 @@ typedef struct _ds_attrs
 {
 	str body;
 	str duid;
+	str socket;
 	int maxload;
 	int weight;
 } ds_attrs_t;
@@ -161,10 +158,11 @@ typedef struct _ds_dest
 	int priority;
 	int dload;
 	ds_attrs_t attrs;
+	struct socket_info * sock;
 	struct ip_addr ip_address; 	/*!< IP-Address of the entry */
 	unsigned short int port; 	/*!< Port of the URI */
 	unsigned short int proto; 	/*!< Protocol of the URI */
-	int failure_count;
+	int message_count;
 	struct _ds_dest *next;
 } ds_dest_t;
 
diff --git a/modules/dispatcher/dispatcher.c b/modules/dispatcher/dispatcher.c
index 13f3f56..2e2c12f 100644
--- a/modules/dispatcher/dispatcher.c
+++ b/modules/dispatcher/dispatcher.c
@@ -1,10 +1,9 @@
 /**
- * $Id$
- *
- * dispatcher module -- stateless load balancing
+ * dispatcher module - load balancing
  *
  * Copyright (C) 2004-2005 FhG Fokus
  * Copyright (C) 2006 Voice Sistem SRL
+ * Copyright (C) 2015 Daniel-Constantin Mierla (asipto.com)
  *
  * This file is part of Kamailio, a free SIP server.
  *
@@ -18,21 +17,9 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- *
- * History
- * -------
- * 2004-07-31  first version, by daniel
- * 2007-01-11  Added a function to check if a specific gateway is in a group
- *				(carsten - Carsten Bock, BASIS AudioNet GmbH)
- * 2007-02-09  Added active probing of failed destinations and automatic
- *				re-enabling of destinations (carsten)
- * 2007-05-08  Ported the changes to SVN-Trunk and renamed ds_is_domain
- *				to ds_is_from_list.  (carsten)
- * 2007-07-18  Added support for load/reload groups from DB 
- * 			   reload triggered from ds_reload MI_Command (ancuta)
  */
 
 /*! \file
@@ -41,7 +28,7 @@
  */
 
 /*! \defgroup dispatcher Dispatcher :: Load balancing and failover module
- * 	The dispatcher module implements a set of functions for distributing SIP requests on a 
+ * 	The dispatcher module implements a set of functions for distributing SIP requests on a
  *	set of servers, but also grouping of server resources.
  *
  *	- The module has an internal API exposed to other modules.
@@ -82,13 +69,14 @@ MODULE_VERSION
 /** parameters */
 char *dslistfile = CFG_DIR"dispatcher.list";
 int  ds_force_dst   = 1;
-int  ds_flags       = 0; 
-int  ds_use_default = 0; 
+int  ds_flags       = 0;
+int  ds_use_default = 0;
 static str dst_avp_param = {NULL, 0};
 static str grp_avp_param = {NULL, 0};
 static str cnt_avp_param = {NULL, 0};
 static str dstid_avp_param = {NULL, 0};
 static str attrs_avp_param = {NULL, 0};
+static str sock_avp_param = {NULL, 0};
 str hash_pvar_param = {NULL, 0};
 
 int_str dst_avp_name;
@@ -101,11 +89,15 @@ int_str dstid_avp_name;
 unsigned short dstid_avp_type;
 int_str attrs_avp_name;
 unsigned short attrs_avp_type;
+int_str sock_avp_name;
+unsigned short sock_avp_type;
 
 pv_elem_t * hash_param_model = NULL;
 
-int probing_threshhold = 1; /* number of failed requests, before a destination
+int probing_threshold = 1; /* number of failed requests, before a destination
 							   is taken into probing */
+int inactive_threshold = 1; /* number of replied requests, before a destination
+							   is taken into back in active state */
 str ds_ping_method = str_init("OPTIONS");
 str ds_ping_from   = str_init("sip:dispatcher at localhost");
 static int ds_ping_interval = 0;
@@ -115,6 +107,9 @@ static str ds_ping_reply_codes_str= {NULL, 0};
 static int** ds_ping_reply_codes = NULL;
 static int* ds_ping_reply_codes_cnt;
 
+str ds_default_socket       = {NULL, 0};
+struct socket_info * ds_default_sockinfo = NULL;
+
 int ds_hash_size = 0;
 int ds_hash_expire = 7200;
 int ds_hash_initexpire = 7200;
@@ -161,7 +156,10 @@ static int w_ds_is_from_list0(struct sip_msg*, char*, char*);
 static int w_ds_is_from_list1(struct sip_msg*, char*, char*);
 static int w_ds_is_from_list2(struct sip_msg*, char*, char*);
 static int w_ds_is_from_list3(struct sip_msg*, char*, char*, char*);
+static int w_ds_list_exist(struct sip_msg*, char*);
+
 static int fixup_ds_is_from_list(void** param, int param_no);
+static int fixup_ds_list_exist(void** param,int param_no);
 
 static void destroy(void);
 
@@ -197,6 +195,8 @@ static cmd_export_t cmds[]={
 		fixup_ds_is_from_list, 0, ANY_ROUTE},
 	{"ds_is_from_list",  (cmd_function)w_ds_is_from_list3, 3,
 		fixup_ds_is_from_list, 0, ANY_ROUTE},
+	{"ds_list_exist",  (cmd_function)w_ds_list_exist, 1,
+		fixup_ds_list_exist, 0, ANY_ROUTE},
 	{"ds_load_unset",    (cmd_function)w_ds_load_unset,   0,
 		0, 0, ANY_ROUTE},
 	{"ds_load_update",   (cmd_function)w_ds_load_update,  0,
@@ -224,10 +224,12 @@ static param_export_t params[]={
 	{"cnt_avp",         PARAM_STR, &cnt_avp_param},
 	{"dstid_avp",       PARAM_STR, &dstid_avp_param},
 	{"attrs_avp",       PARAM_STR, &attrs_avp_param},
+	{"sock_avp",        PARAM_STR, &sock_avp_param},
 	{"hash_pvar",       PARAM_STR, &hash_pvar_param},
 	{"setid_pvname",    PARAM_STR, &ds_setid_pvname},
 	{"attrs_pvname",    PARAM_STR, &ds_attrs_pvname},
-	{"ds_probing_threshhold", INT_PARAM, &probing_threshhold},
+	{"ds_probing_threshold", INT_PARAM, &probing_threshold},
+	{"ds_inactive_threshold", INT_PARAM, &inactive_threshold},
 	{"ds_ping_method",     PARAM_STR, &ds_ping_method},
 	{"ds_ping_from",       PARAM_STR, &ds_ping_from},
 	{"ds_ping_interval",   INT_PARAM, &ds_ping_interval},
@@ -238,6 +240,7 @@ static param_export_t params[]={
 	{"ds_hash_initexpire", INT_PARAM, &ds_hash_initexpire},
 	{"ds_hash_check_interval", INT_PARAM, &ds_hash_check_interval},
 	{"outbound_proxy",  PARAM_STR, &ds_outbound_proxy},
+	{"ds_default_socket",  PARAM_STR, &ds_default_socket},
 	{0,0,0}
 };
 
@@ -272,6 +275,8 @@ struct module_exports exports= {
 static int mod_init(void)
 {
 	pv_spec_t avp_spec;
+	str host;
+	int port, proto;
 
 	if(register_mi_mod(exports.name, mi_cmds)!=0)
 	{
@@ -303,11 +308,26 @@ static int mod_init(void)
 		{
 			return -1;
 		}
-	}	
-	/* Copy Threshhold to Config */
-	cfg_get(dispatcher, dispatcher_cfg, probing_threshhold)
-		= probing_threshhold;
-
+	}
+	/* copy threshholds to config */
+	cfg_get(dispatcher, dispatcher_cfg, probing_threshold)
+		= probing_threshold;
+	cfg_get(dispatcher, dispatcher_cfg, inactive_threshold)
+		= inactive_threshold;
+
+	if (ds_default_socket.s && ds_default_socket.len > 0) {
+		if (parse_phostport( ds_default_socket.s, &host.s, &host.len,
+				&port, &proto)!=0) {
+			LM_ERR("bad socket <%.*s>\n", ds_default_socket.len, ds_default_socket.s);
+			return -1;
+		}
+		ds_default_sockinfo = grep_sock_info( &host, (unsigned short)port, proto);
+		if (ds_default_sockinfo==0) {
+			LM_WARN("non-local socket <%.*s>\n", ds_default_socket.len, ds_default_socket.s);
+			return -1;
+		}
+		LM_INFO("default dispatcher socket set to <%.*s>\n", ds_default_socket.len, ds_default_socket.s);
+	}
 
 	if(init_data()!= 0)
 		return -1;
@@ -432,12 +452,34 @@ static int mod_init(void)
 		attrs_avp_type = 0;
 	}
 
+	if (sock_avp_param.s && sock_avp_param.len > 0)
+	{
+		if (pv_parse_spec(&sock_avp_param, &avp_spec)==0
+				|| avp_spec.type!=PVT_AVP)
+		{
+			LM_ERR("malformed or non AVP %.*s AVP definition\n",
+					sock_avp_param.len, sock_avp_param.s);
+			return -1;
+		}
+
+		if(pv_get_avp_name(0, &(avp_spec.pvp), &sock_avp_name,
+					&sock_avp_type)!=0)
+		{
+			LM_ERR("[%.*s]- invalid AVP definition\n", sock_avp_param.len,
+					sock_avp_param.s);
+			return -1;
+		}
+	} else {
+		sock_avp_name.n = 0;
+		sock_avp_type = 0;
+	}
+
 	if (hash_pvar_param.s && *hash_pvar_param.s) {
 		if(pv_parse_format(&hash_pvar_param, &hash_param_model) < 0
 				|| hash_param_model==NULL) {
 			LM_ERR("malformed PV string: %s\n", hash_pvar_param.s);
 			return -1;
-		}		
+		}
 	} else {
 		hash_param_model = NULL;
 	}
@@ -525,7 +567,7 @@ static void destroy(void)
 		ds_disconnect_db();
 	ds_hash_load_destroy();
 	if(ds_ping_reply_codes)
-		shm_free(ds_ping_reply_codes);	
+		shm_free(ds_ping_reply_codes);
 
 }
 
@@ -720,7 +762,7 @@ static int w_ds_load_update(struct sip_msg *msg, char *str1, char *str2)
  */
 static int ds_warn_fixup(void** param, int param_no)
 {
-	if(!dst_avp_param.s || !grp_avp_param.s || !cnt_avp_param.s)
+	if(!dst_avp_param.s || !grp_avp_param.s || !cnt_avp_param.s || !sock_avp_param.s)
 	{
 		LM_ERR("failover functions used, but AVPs paraamters required"
 				" are NULL -- feature disabled\n");
@@ -901,6 +943,26 @@ static int fixup_ds_is_from_list(void** param, int param_no)
 	return 0;
 }
 
+/* Check if a given set exist in memory */
+static int w_ds_list_exist(struct sip_msg *msg, char *param)
+{
+	int set;
+
+	if(fixup_get_ivalue(msg, (gparam_p)param, &set)!=0)
+	{
+		LM_ERR("cannot get set id param value\n");
+		return -1;
+	}
+	LM_DBG("--- Looking for dispatcher set %d\n", set);
+	return ds_list_exist(set);
+}
+
+static int fixup_ds_list_exist(void** param, int param_no)
+{
+	return fixup_igp_null(param, param_no);
+	return 0;
+}
+
 static int ds_parse_reply_codes() {
 	param_t* params_list = NULL;
 	param_t *pit=NULL;
@@ -913,7 +975,7 @@ static int ds_parse_reply_codes() {
 	int* ds_ping_reply_codes_old = NULL;
 
 	/* Validate String: */
-	if (cfg_get(dispatcher, dispatcher_cfg, ds_ping_reply_codes_str).s == 0 
+	if (cfg_get(dispatcher, dispatcher_cfg, ds_ping_reply_codes_str).s == 0
 			|| cfg_get(dispatcher, dispatcher_cfg, ds_ping_reply_codes_str).len<=0)
 		return 0;
 
@@ -965,7 +1027,7 @@ static int ds_parse_reply_codes() {
 				str2sint(&pit->body, &code);
 				if ((code >= 1) && (code < 7)) {
 					/* Add every code from this class, e.g. 100 to 199 */
-					for (i = (code*100); i <= ((code*100)+99); i++) 
+					for (i = (code*100); i <= ((code*100)+99); i++)
 						ds_ping_reply_codes_new[pos++] = i;
 				}
 			}
@@ -984,7 +1046,7 @@ static int ds_parse_reply_codes() {
 		*ds_ping_reply_codes_cnt = list_size;
 		// Free the old memory area:
 		if(ds_ping_reply_codes_old)
-			shm_free(ds_ping_reply_codes_old);	
+			shm_free(ds_ping_reply_codes_old);
 		/* Less or equal? Set the number of codes first. */
 	} else {
 		// Done:
@@ -994,7 +1056,7 @@ static int ds_parse_reply_codes() {
 		*ds_ping_reply_codes = ds_ping_reply_codes_new;
 		// Free the old memory area:
 		if(ds_ping_reply_codes_old)
-			shm_free(ds_ping_reply_codes_old);	
+			shm_free(ds_ping_reply_codes_old);
 	}
 	/* Print the list as INFO: */
 	for (i =0; i< *ds_ping_reply_codes_cnt; i++)
@@ -1149,12 +1211,14 @@ static void dispatcher_rpc_list(rpc_t* rpc, void* ctx)
 					rpc->fault(ctx, 500, "Internal error creating dest struct");
 					return;
 				}
-				if(rpc->struct_add(wh, "SSdd",
+				if(rpc->struct_add(wh, "SSddS",
 							"BODY", &(list->dlist[j].attrs.body),
 							"DUID", (list->dlist[j].attrs.duid.s)?
 							&(list->dlist[j].attrs.duid):&data,
 							"MAXLOAD", list->dlist[j].attrs.maxload,
-							"WEIGHT", list->dlist[j].attrs.weight)<0)
+							"WEIGHT", list->dlist[j].attrs.weight,
+							"SOCKET", (list->dlist[j].attrs.socket.s)?
+							&(list->dlist[j].attrs.socket):&data)<0)
 				{
 					rpc->fault(ctx, 500, "Internal error creating attrs struct");
 					return;
diff --git a/modules/dispatcher/doc/dispatcher.xml b/modules/dispatcher/doc/dispatcher.xml
index dada67e..471ebbe 100644
--- a/modules/dispatcher/doc/dispatcher.xml
+++ b/modules/dispatcher/doc/dispatcher.xml
@@ -31,6 +31,22 @@
                 <email>carsten at ng-voice.com</email>
                 </address>
             </editor>
+            <editor>
+                <firstname>Olle E.</firstname>
+                <surname>Johansson</surname>
+                <affiliation><orgname>Edvina AB</orgname></affiliation>
+                <address>
+                <email>oej at edvina.net</email>
+                </address>
+            </editor>
+            <editor>
+                <firstname>Alessandro</firstname>
+                <surname>Arrichiello</surname>
+                <affiliation><orgname>Hewlett Packard</orgname></affiliation>
+                <address>
+                <email>alezzandro at gmail.com</email>
+                </address>
+            </editor>
 	</authorgroup>
 	<copyright>
 	    <year>2004</year>
@@ -44,6 +60,14 @@
 	    <year>2010</year>
 	    <holder>Daniel-Constantin Mierla (asipto.com)</holder>
 	</copyright>
+ 	<copyright>
+	    <year>2014</year>
+	    <holder>Olle E. Johansson, Edvina AB</holder>
+	</copyright>
+	<copyright>
+            <year>2015</year>
+            <holder>Alessandro Arrichiello, Hewlett Packard</holder>
+        </copyright>
    </bookinfo>
     <toc></toc>
     
diff --git a/modules/dispatcher/doc/dispatcher_admin.xml b/modules/dispatcher/doc/dispatcher_admin.xml
index ce27422..8edb8c6 100644
--- a/modules/dispatcher/doc/dispatcher_admin.xml
+++ b/modules/dispatcher/doc/dispatcher_admin.xml
@@ -421,6 +421,30 @@ modparam("dispatcher", "force_dst", 1)
  </programlisting>
  		</example>
  	</section>
+	<section id="dispatcher.p.sock_avp">
+		<title><varname>sock_avp</varname> (str)</title>
+		<para>
+			The name of the avp which will hold the list with the sockets associated to the addresses stored in dst_avp avp.
+		</para>
+		<note>
+		<para>
+			If you want to do load balancing fail over, you have to set this parameter to use the correct socket for each gateway.
+		</para>
+		</note>
+		<para>
+		<emphasis>
+			Default value is <quote>null</quote> - don't add AVPs.
+		</emphasis>
+		</para>
+		<example>
+		<title>Set the <quote>sock_avp</quote> parameter</title>
+ <programlisting format="linespecific">
+ ...
+ modparam("dispatcher", "sock_avp", "$avp(dssocket)")
+ ...
+ </programlisting>
+		</example>
+	</section>
  	<section id="dispatcher.p.hash_pvar">
  		<title><varname>hash_pvar</varname> (str)</title>
  		<para>
@@ -574,14 +598,36 @@ modparam("dispatcher", "force_dst", 1)
  		</emphasis>
  		</para>
  		<example>
- 		<title>Set the <quote>ds_probing_threshhold</quote> parameter</title>
+ 		<title>Set the <quote>ds_probing_threshold</quote> parameter</title>
  <programlisting format="linespecific">
  ...
- modparam("dispatcher", "ds_probing_threshhold", 10)
+ modparam("dispatcher", "ds_probing_threshold", 10)
  ...
  </programlisting>
  		</example>
 	</section>
+	<section id="dispatcher.p.ds_inactive_threshold">
+                <title><varname>ds_inactive_threshold</varname> (int)</title>
+                <para>
+                If you want to set a gateway into active mode (after being inactive), there can be
+                a specific number of successful requests until it will change from "inactive"
+                to "active". The number of attempts can be set with this parameter.
+                This parameter can be modified via ser config framework.
+                </para>
+                <para>
+                <emphasis>
+                Default value is <quote>1</quote> (set active with first success).
+                </emphasis>
+                </para>
+                <example>
+                <title>Set the <quote>ds_inactive_threshold</quote> parameter</title>
+ <programlisting format="linespecific">
+ ...
+ modparam("dispatcher", "ds_inactive_threshold", 10)
+ ...
+ </programlisting>
+                </example>
+        </section>
  	<section id="dispatcher.p.ds_ping_reply_codes">
  		<title><varname>ds_ping_reply_codes</varname> (string)</title>
  		<para>
@@ -731,6 +777,26 @@ modparam("dispatcher", "force_dst", 1)
  		</example>
 	</section>
 
+	<section id="dispatcher.p.ds_default_socket">
+		<title><varname>ds_default_socket</varname> (str)</title>
+		<para>
+		Default socket to be used for sending pings and dispatching requests when a gateway has no send socket configured.
+		</para>
+		<para>
+		<emphasis>
+			By default no default socket is defined, the first configuration script <emphasis>listen</emphasis> directive is used.
+		</emphasis>
+		</para>
+		<example>
+		<title>Set the <quote>ds_default_socket</quote> parameter</title>
+ <programlisting format="linespecific">
+ ...
+ modparam("dispatcher", "ds_default_socket", "udp:192.168.0.125:5060")
+ ...
+ </programlisting>
+		</example>
+	</section>
+
 	</section>
 
 	<section>
@@ -993,6 +1059,34 @@ failure_route[tryagain] {
 </programlisting>
 		</example>
  	</section>
+  	<section  id="dispatcher.f.ds_list_exist">
+ 		<title>
+		<function moreinfo="none">ds_list_exist(groupid)</function>
+ 		</title>
+ 		<para>
+		Check if a specific group is defined in dispatcher list
+		or database.
+		</para>
+		<itemizedlist>
+		<listitem>
+			<para><emphasis>groupid</emphasis> - A group ID to check.
+			</para>
+		</listitem>
+		</itemizedlist>
+		<para>
+			This function can be used from ANY_ROUTE.
+		</para>
+		<example>
+		<title><function>ds_list_exist</function> usage</title>
+		<programlisting format="linespecific">
+...
+if(ds_list_exist("10")) {
+    ...
+}
+...
+</programlisting>
+	</example>
+	</section>
   	<section  id="dispatcher.f.ds_is_from_list">
  		<title>
 		<function moreinfo="none">ds_is_from_list([groupid [, mode [, uri] ] ])</function>
@@ -1047,7 +1141,7 @@ failure_route[tryagain] {
 			This function can be used from ANY_ROUTE.
 		</para>
 		<example>
-		<title><function>ds_mark_dst</function> usage</title>
+		<title><function>ds_is_from_list</function> usage</title>
 		<programlisting format="linespecific">
 ...
 if(ds_is_from_list()) {
@@ -1056,7 +1150,10 @@ if(ds_is_from_list()) {
 if(ds_is_from_list("10")) {
     ...
 }
-if(ds_is_from_list("10", "sip:127.0.0.1:5080", "3")) {
+if(ds_is_from_list("10", "3")) {
+    ...
+}
+if(ds_is_from_list("10", "3", "sip:127.0.0.1:5080")) {
     ...
 }
 ...
@@ -1323,9 +1420,7 @@ onreply_route {
 			</listitem>
 			<listitem>
 			<para>attributes: extra fields in form of
-				name1=value1;...;nameN=valueN. There are some reserved names
-				for attributes used by the module for specific load balancing
-				algorithms, see the section 'Special Attributes'.
+				name1=value1;...;nameN=valueN.
 			</para>
 			</listitem>
 		</itemizedlist>
@@ -1378,7 +1473,7 @@ setid(int) destination(sip uri) flags(int,opt) priority(int,opt) attrs(str,opt)
 		</para>
 		<programlisting format="linespecific">
 ...
-1 sip:127.0.0.1:5080 0 0 duid=abc;my=xyz
+1 sip:127.0.0.1:5080 0 0 duid=abc;socket=udp:192.168.0.125:5060;my=xyz
 ...
 </programlisting>
 
diff --git a/modules/dispatcher/ds_ht.c b/modules/dispatcher/ds_ht.c
index 78362d1..9977420 100644
--- a/modules/dispatcher/ds_ht.c
+++ b/modules/dispatcher/ds_ht.c
@@ -1,6 +1,4 @@
 /**
- * $Id$
- *
  * Copyright (C) 2010 Daniel-Constantin Mierla (asipto.com)
  *
  * This file is part of kamailio, a free SIP server.
diff --git a/modules/dispatcher/ds_ht.h b/modules/dispatcher/ds_ht.h
index 6c27943..38fa197 100644
--- a/modules/dispatcher/ds_ht.h
+++ b/modules/dispatcher/ds_ht.h
@@ -1,9 +1,8 @@
 /**
- * $Id$
  *
  * Copyright (C) 2010 Daniel-Constantin Mierla (asipto.com)
  *
- * This file is part of kamailio, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
  * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -33,13 +32,13 @@
 
 typedef struct _ds_cell
 {
-    unsigned int cellid;
-	str callid;
-	str duid;
-	int dset;
-	int state;
-	time_t  expire;
-	time_t  initexpire;
+    unsigned int cellid;   /* item hash id */
+	str callid;            /* sip call-id */
+	str duid;              /* destination unique id (duid attribute) */
+	int dset;              /* destination set */
+	int state;             /* state */
+	time_t  expire;        /* expiration of the item */
+	time_t  initexpire;    /* expiration in initial state of the item */
     struct _ds_cell *prev;
     struct _ds_cell *next;
 } ds_cell_t;
diff --git a/modules/diversion/Makefile b/modules/diversion/Makefile
index 3138160..360538d 100644
--- a/modules/diversion/Makefile
+++ b/modules/diversion/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # Diversion Header Field Support2
 #
diff --git a/modules/diversion/diversion.c b/modules/diversion/diversion.c
index 0dd0c67..868390d 100644
--- a/modules/diversion/diversion.c
+++ b/modules/diversion/diversion.c
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- *
  * Diversion Header Field Support
  *
  * Copyright (C) 2004 FhG Fokus
diff --git a/modules/dmq/Makefile b/modules/dmq/Makefile
index 6e94c16..0e9babc 100644
--- a/modules/dmq/Makefile
+++ b/modules/dmq/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # distributed message queue system for inter-intstance communication
 #
diff --git a/modules/dmq/README b/modules/dmq/README
index 8bc19e4..e9290c7 100644
--- a/modules/dmq/README
+++ b/modules/dmq/README
@@ -6,6 +6,10 @@ Charles Chance
 
    Sipcentric Ltd.
 
+Olle E. Johansson
+
+   Edvina AB
+
 Edited by
 
 Marius Ovidiu Bucur
@@ -17,6 +21,8 @@ Charles Chance
    Copyright © 2011 Marius Bucur
 
    Copyright © 2013 Charles Chance, Sipcentric Ltd.
+
+   Copyright © 2015 Olle E. Johansson, Edvina AB
      __________________________________________________________________
 
    Table of Contents
@@ -33,8 +39,9 @@ Charles Chance
 
               3.1. server_address(str)
               3.2. notification_address(str)
-              3.3. num_workers(int)
-              3.4. ping_interval(int)
+              3.3. multi_notify(int)
+              3.4. num_workers(int)
+              3.5. ping_interval(int)
 
         4. Functions
 
@@ -58,15 +65,17 @@ Charles Chance
 
    List of Examples
 
-   1.1. Set server_address parameter
-   1.2. Set notification_address parameter
-   1.3. Set num_workers parameter
-   1.4. Set ping_interval parameter
-   1.5. dmq_handle_message usage
-   1.6. dmq_send_message usage
-   1.7. dmq_bcast_message usage
-   1.8. dmq_t_replicate usage
-   1.9. dmq_is_from_node usage
+   1.1. Example of a KDMQ message
+   1.2. Set server_address parameter
+   1.3. Set notification_address parameter
+   1.4. Set multi_notify parameter
+   1.5. Set num_workers parameter
+   1.6. Set ping_interval parameter
+   1.7. dmq_handle_message usage
+   1.8. dmq_send_message usage
+   1.9. dmq_bcast_message usage
+   1.10. dmq_t_replicate usage
+   1.11. dmq_is_from_node usage
    2.1. dmq_api_t structure
    2.2. register_dmq_peer usage
    2.3. bcast_message usage
@@ -86,8 +95,9 @@ Chapter 1. Admin Guide
 
         3.1. server_address(str)
         3.2. notification_address(str)
-        3.3. num_workers(int)
-        3.4. ping_interval(int)
+        3.3. multi_notify(int)
+        3.4. num_workers(int)
+        3.5. ping_interval(int)
 
    4. Functions
 
@@ -113,6 +123,29 @@ Chapter 1. Admin Guide
    grouping of peers can be compared to a topic in a typical pub/sub
    system.
 
+   DMQ sends SIP requests using the KDMQ request method, that is private
+   to Kamailio.
+
+   Example 1.1. Example of a KDMQ message
+
+   This message is for basic DMQ bus handling. Other messages are produced
+   by other modules, like the htable module.
+KDMQ sip:notification_peer at 192.168.40.15:5090 SIP/2.0
+Via: SIP/2.0/UDP 192.168.40.15;branch=z9hG4bK55e5.423d95110000
+To: <sip:notification_peer at 192.168.40.15:5090>
+From: <sip:notification_peer at 192.168.40.15:5060>;tag=2cdb7a33a7f21abb98fd3a44968
+e3ffd-5b01
+CSeq: 10 KDMQ
+Call-ID: 1fe138e07b5d0a7a-50419 at 192.168.40.15
+Content-Length: 116
+User-Agent: kamailio (4.3.0 (x86_64/linneaus))
+Max-Forwards: 1
+Content-Type: text/plain
+
+sip:192.168.40.16:5060;status=active
+sip:192.168.40.15:5060;status=disabled
+sip:192.168.40.17:5060;status=active
+
 2. Dependencies
 
    2.1. Kamailio Modules
@@ -134,8 +167,9 @@ Chapter 1. Admin Guide
 
    3.1. server_address(str)
    3.2. notification_address(str)
-   3.3. num_workers(int)
-   3.4. ping_interval(int)
+   3.3. multi_notify(int)
+   3.4. num_workers(int)
+   3.5. ping_interval(int)
 
 3.1. server_address(str)
 
@@ -144,7 +178,7 @@ Chapter 1. Admin Guide
 
    Default value is “NULL”.
 
-   Example 1.1. Set server_address parameter
+   Example 1.2. Set server_address parameter
 ...
 modparam("dmq", "server_address", "sip:10.0.0.20:5060")
 ...
@@ -156,30 +190,46 @@ modparam("dmq", "server_address", "sip:10.0.0.20:5060")
 
    Default value is “NULL”.
 
-   Example 1.2. Set notification_address parameter
+   Example 1.3. Set notification_address parameter
 ...
 modparam("dmq", "notification_address", "sip:10.0.0.21:5060")
 ...
 
-3.3. num_workers(int)
+3.3. multi_notify(int)
+
+   Enables the ability to resolve multiple IPv4/IPv6 addresses for a
+   single notification address.
+
+   A value of zero resolves to the first IP address found. A non-zero
+   value resolves to all IP addresses associated with the host. This
+   includes addresses from DNS SRV records, A and AAAA records.
+
+   Default value is “0”.
+
+   Example 1.4. Set multi_notify parameter
+...
+modparam("dmq", "multi_notify", 1)
+...
+
+3.4. num_workers(int)
 
    The number of worker threads for sending/receiving messages.
 
    Default value is “2”.
 
-   Example 1.3. Set num_workers parameter
+   Example 1.5. Set num_workers parameter
 ...
 modparam("dmq", "num_threads", 4)
 ...
 
-3.4. ping_interval(int)
+3.5. ping_interval(int)
 
    The number of seconds between node pings (for checking status of other
    nodes).
 
    Minimum value is “60” (default).
 
-   Example 1.4. Set ping_interval parameter
+   Example 1.6. Set ping_interval parameter
 ...
 modparam("dmq", "ping_interval", 90)
 ...
@@ -199,7 +249,7 @@ modparam("dmq", "ping_interval", 90)
 
    This function can be used from REQUEST_ROUTE.
 
-   Example 1.5. dmq_handle_message usage
+   Example 1.7. dmq_handle_message usage
 ...
         if(is_method("KDMQ"))
         {
@@ -219,7 +269,7 @@ modparam("dmq", "ping_interval", 90)
 
    This function can be used from any route.
 
-   Example 1.6. dmq_send_message usage
+   Example 1.8. dmq_send_message usage
 ...
         dmq_send_message("peer_name", "sip:10.0.0.21:5060", "Message body...", "
 text/plain");
@@ -237,7 +287,7 @@ text/plain");
 
    This function can be used from any route.
 
-   Example 1.7. dmq_bcast_message usage
+   Example 1.9. dmq_bcast_message usage
 ...
         dmq_bcast_message("peer_name", "Message body...", "text/plain");
 ...
@@ -259,7 +309,7 @@ text/plain");
 
    This function can be used from REQUEST_ROUTE only.
 
-   Example 1.8. dmq_t_replicate usage
+   Example 1.10. dmq_t_replicate usage
 ...
         dmq_t_replicate();
 ...
@@ -271,7 +321,7 @@ text/plain");
 
    This function can be used from REQUEST_ROUTE only.
 
-   Example 1.9. dmq_is_from_node usage
+   Example 1.11. dmq_is_from_node usage
 ...
         # Example REGISTER block
         if (dmq_is_from_node()) {
diff --git a/modules/dmq/bind_dmq.c b/modules/dmq/bind_dmq.c
index 37c2a7e..04e7494 100644
--- a/modules/dmq/bind_dmq.c
+++ b/modules/dmq/bind_dmq.c
@@ -1,5 +1,4 @@
 /**
- * $Id$
  *
  * dmq module - distributed message queue
  *
@@ -34,6 +33,7 @@ int bind_dmq(dmq_api_t* api) {
 	api->register_dmq_peer = register_dmq_peer;
 	api->send_message = dmq_send_message;
 	api->bcast_message = bcast_dmq_message;
+	api->find_dmq_node_uri = find_dmq_node_uri2;
 	return 0;
 }
 
diff --git a/modules/dmq/bind_dmq.h b/modules/dmq/bind_dmq.h
index 0447040..57f983f 100644
--- a/modules/dmq/bind_dmq.h
+++ b/modules/dmq/bind_dmq.h
@@ -1,5 +1,4 @@
 /**
- * $Id$
  *
  * dmq module - distributed message queue
  *
@@ -34,11 +33,13 @@ typedef int (*bcast_message_t)(dmq_peer_t* peer, str* body, dmq_node_t* except,
 		dmq_resp_cback_t* resp_cback, int max_forwards, str* content_type);
 typedef int (*send_message_t)(dmq_peer_t* peer, str* body, dmq_node_t* node,
 		dmq_resp_cback_t* resp_cback, int max_forwards, str* content_type);
+typedef dmq_node_t* (*find_dmq_node_uri_t)(str* uri);
 
 typedef struct dmq_api {
 	register_dmq_peer_t register_dmq_peer;
 	bcast_message_t bcast_message;
 	send_message_t send_message;
+	find_dmq_node_uri_t find_dmq_node_uri;
 } dmq_api_t;
 
 typedef int (*bind_dmq_f)(dmq_api_t* api);
diff --git a/modules/dmq/dmq.c b/modules/dmq/dmq.c
index fcbd8f8..7e1ac35 100644
--- a/modules/dmq/dmq.c
+++ b/modules/dmq/dmq.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * dmq module - distributed message queue
  *
  * Copyright (C) 2011 Bucur Marius - Ovidiu
@@ -65,8 +63,9 @@ str dmq_server_socket = {0, 0};
 struct sip_uri dmq_server_uri;
 
 str dmq_notification_address = {0, 0};
+int multi_notify = 0;
 struct sip_uri dmq_notification_uri;
-int ping_interval = MIN_PING_INTERVAL;
+int ping_interval = 60;
 
 /* TM bind */
 struct tm_binds tmb;
@@ -75,12 +74,12 @@ sl_api_t slb;
 
 /** module variables */
 str dmq_request_method = str_init("KDMQ");
-dmq_worker_t* workers;
-dmq_peer_list_t* peer_list;
+dmq_worker_t* workers = NULL;
+dmq_peer_list_t* peer_list = 0;
 /* the list of dmq servers */
-dmq_node_list_t* node_list;
+dmq_node_list_t* node_list = NULL;
 // the dmq module is a peer itself for receiving notifications regarding nodes
-dmq_peer_t* dmq_notification_peer;
+dmq_peer_t* dmq_notification_peer = NULL;
 
 /** module functions */
 static int mod_init(void);
@@ -112,6 +111,7 @@ static param_export_t params[] = {
 	{"ping_interval", INT_PARAM, &ping_interval},
 	{"server_address", PARAM_STR, &dmq_server_address},
 	{"notification_address", PARAM_STR, &dmq_notification_address},
+	{"multi_notify", INT_PARAM, &multi_notify},
 	{0, 0, 0}
 };
 
@@ -239,7 +239,14 @@ static int mod_init(void)
 		LM_ERR("error in shm_malloc\n");
 		return -1;
 	}
-	
+
+	dmq_init_callback_done = shm_malloc(sizeof(int));
+	if (!dmq_init_callback_done) {
+		LM_ERR("no more shm\n");
+		return -1;
+	}
+	*dmq_init_callback_done = 0;
+
 	/**
 	 * add the dmq notification peer.
 	 * the dmq is a peer itself so that it can receive node notifications
@@ -326,6 +333,9 @@ static void destroy(void) {
 	if (dmq_server_socket.s) {
 		pkg_free(dmq_server_socket.s);
 	}
+	if (dmq_init_callback_done) {
+		shm_free(dmq_init_callback_done);
+	}
 }
 
 static int handle_dmq_fixup(void** param, int param_no)
diff --git a/modules/dmq/dmq.h b/modules/dmq/dmq.h
index eedadb3..d878191 100644
--- a/modules/dmq/dmq.h
+++ b/modules/dmq/dmq.h
@@ -1,6 +1,4 @@
 /**
- * $Id$
- *
  * dmq module - distributed message queue
  *
  * Copyright (C) 2011 Bucur Marius - Ovidiu
@@ -36,7 +34,7 @@
 #include "worker.h"
 
 #define DEFAULT_NUM_WORKERS	2
-#define MIN_PING_INTERVAL	60
+#define MIN_PING_INTERVAL	5
 
 extern int num_workers;
 extern dmq_worker_t* workers;
@@ -47,6 +45,7 @@ extern str dmq_request_method;
 extern str dmq_server_socket;
 extern struct sip_uri dmq_server_uri;
 extern str dmq_notification_address;
+extern int multi_notify;
 extern struct sip_uri dmq_notification_uri;
 /* sl and tm */
 extern struct tm_binds tmb;
diff --git a/modules/dmq/dmq_funcs.c b/modules/dmq/dmq_funcs.c
index 2ec32d2..35c121b 100644
--- a/modules/dmq/dmq_funcs.c
+++ b/modules/dmq/dmq_funcs.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * dmq module - distributed message queue
  *
  * Copyright (C) 2011 Bucur Marius - Ovidiu
@@ -410,9 +408,9 @@ int cfg_dmq_t_replicate(struct sip_msg* msg, char* s)
 		 *   - ourself
 		 *   - any inactive nodes
 		 */
-                if(node->local || node->status != DMQ_NODE_ACTIVE) {
-                        LM_DBG("skipping node %.*s\n", STR_FMT(&node->orig_uri));
-                        node = node->next;
+		if(node->local || node->status != DMQ_NODE_ACTIVE) {
+			LM_DBG("skipping node %.*s\n", STR_FMT(&node->orig_uri));
+			node = node->next;
 			continue;
 		}
 
diff --git a/modules/dmq/dmq_funcs.h b/modules/dmq/dmq_funcs.h
index 55f67ac..02c0516 100644
--- a/modules/dmq/dmq_funcs.h
+++ b/modules/dmq/dmq_funcs.h
@@ -1,6 +1,4 @@
 /**
- * $Id$
- *
  * dmq module - distributed message queue
  *
  * Copyright (C) 2011 Bucur Marius - Ovidiu
diff --git a/modules/dmq/dmqnode.c b/modules/dmq/dmqnode.c
index 5ac3951..7b0bf63 100644
--- a/modules/dmq/dmqnode.c
+++ b/modules/dmq/dmqnode.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * dmq module - distributed message queue
  *
  * Copyright (C) 2011 Bucur Marius - Ovidiu
@@ -228,15 +226,22 @@ error:
  */
 dmq_node_t* find_dmq_node_uri(dmq_node_list_t* list, str* uri)
 {
-	dmq_node_t *ret, *find;
-	find =  build_dmq_node(uri, 0);
-	if(find==NULL)
+	dmq_node_t *ret, find;
+
+	memset(&find, 0, sizeof(find));
+	if(parse_uri(uri->s, uri->len, &find.uri) < 0) {
+		LM_ERR("error parsing uri\n");
 		return NULL;
-	ret = find_dmq_node(list, find);
-	destroy_dmq_node(find, 0);
+	}
+	ret = find_dmq_node(list, &find);
 	return ret;
 }
 
+dmq_node_t* find_dmq_node_uri2(str* uri)
+{
+	return find_dmq_node_uri(node_list, uri);
+}
+
 /**
  * @brief destroy dmq node
  */
diff --git a/modules/dmq/dmqnode.h b/modules/dmq/dmqnode.h
index 10e2962..2ef7b5f 100644
--- a/modules/dmq/dmqnode.h
+++ b/modules/dmq/dmqnode.h
@@ -1,6 +1,4 @@
 /**
- * $Id$
- *
  * dmq module - distributed message queue
  *
  * Copyright (C) 2011 Bucur Marius - Ovidiu
@@ -66,6 +64,7 @@ int update_node_list(dmq_node_list_t* remote_list);
 dmq_node_t* add_dmq_node(dmq_node_list_t* list, str* uri);
 dmq_node_t* find_dmq_node(dmq_node_list_t* list, dmq_node_t* node);
 dmq_node_t* find_dmq_node_uri(dmq_node_list_t* list, str* uri);
+dmq_node_t* find_dmq_node_uri2(str* uri);
 int del_dmq_node(dmq_node_list_t* list, dmq_node_t* node);
 int cmp_dmq_node(dmq_node_t* node, dmq_node_t* cmpnode);
 dmq_node_t* shm_dup_node(dmq_node_t* node);
diff --git a/modules/dmq/doc/dmq.xml b/modules/dmq/doc/dmq.xml
index f64c11b..250a771 100644
--- a/modules/dmq/doc/dmq.xml
+++ b/modules/dmq/doc/dmq.xml
@@ -26,6 +26,11 @@
                 <surname>Chance</surname>
 		<affiliation>Sipcentric Ltd.</affiliation>
             </author>
+            <author>
+                <firstname>Olle E.</firstname>
+                <surname>Johansson</surname>
+		<affiliation>Edvina AB</affiliation>
+            </author>
             <editor>
                 <firstname>Marius Ovidiu</firstname>
                 <surname>Bucur</surname>
@@ -46,6 +51,10 @@
             <year>2013</year>
             <holder>Charles Chance, Sipcentric Ltd.</holder>
         </copyright>
+        <copyright>
+            <year>2015</year>
+            <holder>Olle E. Johansson, Edvina AB</holder>
+        </copyright>
   </bookinfo>
     <toc></toc>
     
diff --git a/modules/dmq/doc/dmq_admin.xml b/modules/dmq/doc/dmq_admin.xml
index 7eabc1a..14b4a8e 100644
--- a/modules/dmq/doc/dmq_admin.xml
+++ b/modules/dmq/doc/dmq_admin.xml
@@ -26,6 +26,36 @@
 	Peers are grouped by name in order to ensure the correct messages are passed to the relevant peers. 
 	This grouping of peers can be compared to a topic in a typical pub/sub system.
 	</para>
+	<para>
+	DMQ sends SIP requests using the <emphasis>KDMQ</emphasis> request method, that is private 
+	to Kamailio.
+	</para>
+<example>
+                <title>Example of a KDMQ message</title>
+		<para>
+		This message is for basic DMQ bus handling. Other messages are produced
+		by other modules, like the <emphasis>htable</emphasis> module.
+		</para>
+                <programlisting format="linespecific">
+
+
+KDMQ sip:notification_peer at 192.168.40.15:5090 SIP/2.0
+Via: SIP/2.0/UDP 192.168.40.15;branch=z9hG4bK55e5.423d95110000
+To: <sip:notification_peer at 192.168.40.15:5090>
+From: <sip:notification_peer at 192.168.40.15:5060>;tag=2cdb7a33a7f21abb98fd3a44968e3ffd-5b01
+CSeq: 10 KDMQ
+Call-ID: 1fe138e07b5d0a7a-50419 at 192.168.40.15
+Content-Length: 116
+User-Agent: kamailio (4.3.0 (x86_64/linneaus))
+Max-Forwards: 1
+Content-Type: text/plain
+
+sip:192.168.40.16:5060;status=active
+sip:192.168.40.15:5060;status=disabled
+sip:192.168.40.17:5060;status=active
+
+</programlisting>
+                </example>
 	
 	</section>
 
@@ -101,6 +131,29 @@ modparam("dmq", "notification_address", "sip:10.0.0.21:5060")
 </programlisting>
 		</example>
 	</section>
+	<section id="dmq.p.multi_notify">
+		<title><varname>multi_notify</varname>(int)</title>
+		<para>
+		Enables the ability to resolve multiple IPv4/IPv6 addresses for 
+		a single notification address.
+		</para>
+		<para>
+		A value of zero resolves to the first IP address found. 
+		A non-zero value resolves to all IP addresses associated with the host. 
+		This includes addresses from DNS SRV records, A and AAAA records.
+		</para>
+		<para>
+		<emphasis>Default value is <quote>0</quote>.</emphasis>
+		</para>
+		<example>
+		<title>Set <varname>multi_notify</varname> parameter</title>
+		<programlisting format="linespecific">
+...
+modparam("dmq", "multi_notify", 1)
+...
+</programlisting>
+		</example>
+	</section>
         <section id="dmq.p.num_workers">
                 <title><varname>num_workers</varname>(int)</title>
                 <para>
diff --git a/modules/dmq/message.c b/modules/dmq/message.c
index ca5bd66..7144429 100644
--- a/modules/dmq/message.c
+++ b/modules/dmq/message.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * dmq module - distributed message queue
  *
  * Copyright (C) 2011 Bucur Marius - Ovidiu
diff --git a/modules/dmq/message.h b/modules/dmq/message.h
index f6bf9cc..f3d2046 100644
--- a/modules/dmq/message.h
+++ b/modules/dmq/message.h
@@ -1,6 +1,4 @@
 /**
- * $Id$
- *
  * dmq module - distributed message queue
  *
  * Copyright (C) 2011 Bucur Marius - Ovidiu
diff --git a/modules/dmq/notification_peer.c b/modules/dmq/notification_peer.c
index 2acb9a8..3abefde 100644
--- a/modules/dmq/notification_peer.c
+++ b/modules/dmq/notification_peer.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * dmq module - distributed message queue
  *
  * Copyright (C) 2011 Bucur Marius - Ovidiu
@@ -26,16 +24,25 @@
 
 #include "notification_peer.h"
 
+#define MAXDMQURILEN	255
+#define MAXDMQHOSTS	30
+
 str notification_content_type = str_init("text/plain");
 dmq_resp_cback_t notification_callback = {&notification_resp_callback_f, 0};
 
+int *dmq_init_callback_done = 0;
+
+
 /**
  * @brief add notification peer
  */
 int add_notification_peer()
 {
 	dmq_peer_t not_peer;
+
+	memset(&not_peer, 0, sizeof(dmq_peer_t));
 	not_peer.callback = dmq_notification_callback;
+	not_peer.init_callback = NULL;
 	not_peer.description.s = "notification_peer";
 	not_peer.description.len = 17;
 	not_peer.peer_id.s = "notification_peer";
@@ -58,27 +65,278 @@ error:
 	return -1;
 }
 
+/**********
+* Create IP URI
+*
+* INPUT:
+*   Arg (1) = container for hosts
+*   Arg (2) = host index
+*   Arg (3) = host name pointer
+*   Arg (4) = host name length
+*   Arg (5) = parsed URI pointer
+* OUTPUT: 0=unable to create URI
+**********/
+
+int create_IP_uri (char **puri_list, int host_index, char *phost,
+	int hostlen, sip_uri_t *puri)
+
+{
+	int pos;
+	char *plist;
+	char *perr = "notification host count reached max!\n";
+
+	/**********
+	* insert
+	* o scheme
+	* o user name/password
+	* o host
+	* o port
+	* o parameters
+	**********/
+
+	plist = puri_list [host_index];
+	if (puri->type == SIPS_URI_T) {
+		strncpy (plist, "sips:", 5);
+		pos = 5;
+	} else {
+		strncpy (plist, "sip:", 4);
+		pos = 4;
+	}
+	if (puri->user.s) {
+		strncpy (&plist [pos], puri->user.s, puri->user.len);
+		pos += puri->user.len;
+		if (puri->passwd.s) {
+			plist [pos++] = ':';
+			strncpy (&plist [pos], puri->passwd.s, puri->passwd.len);
+			pos += puri->passwd.len;
+		}
+		plist [pos++] = '@';
+	}
+	if ((pos + hostlen) > MAXDMQURILEN) {
+		LM_WARN ("%s", perr);
+		return 0;
+	}
+	strncpy (&plist [pos], phost, hostlen);
+	pos += hostlen;
+	if (puri->port_no) {
+		if ((pos + 6) > MAXDMQURILEN) {
+			LM_WARN ("%s", perr);
+			return 0;
+		}
+		plist [pos++] = ':';
+		pos += ushort2sbuf (puri->port_no, &plist [pos], 5);
+	}
+	if (puri->params.s) {
+		if ((pos + puri->params.len) >= MAXDMQURILEN) {
+			LM_WARN ("%s", perr);
+			return 0;
+		}
+		plist [pos++] = ';';
+		strncpy (&plist [pos], puri->params.s, puri->params.len);
+		pos += puri->params.len;
+	}
+	plist [pos] = '\0';
+	return 1;
+}
+
+/**********
+* Get DMQ Host List
+*
+* INPUT:
+*   Arg (1) = container for hosts
+*   Arg (2) = maximum number of hosts
+*   Arg (3) = host string pointer
+*   Arg (4) = parsed URI pointer
+*   Arg (5) = search SRV flag
+* OUTPUT: number of hosts found
+**********/
+
+int get_dmq_host_list (char **puri_list, int max_hosts, str *phost,
+	sip_uri_t *puri, int bSRV)
+
+{
+	int host_cnt, len;
+	unsigned short origport, port;
+	str pstr [1];
+	char pname [256], pIP [IP6_MAX_STR_SIZE + 2];
+	struct rdata *phead, *prec;
+	struct srv_rdata *psrv;
+
+	/**********
+	* o IP address?
+	* o make null terminated name
+	* o search SRV?
+	**********/
+
+	if (str2ip (phost) || str2ip6 (phost)) {
+		if (!create_IP_uri (puri_list, 0, phost->s, phost->len, puri)) {
+			LM_DBG ("adding DMQ node IP host %.*s=%s\n",
+				phost->len, phost->s, puri_list [0]);
+			return 0;
+		}
+		return 1;
+	}
+	strncpy (pname, phost->s, phost->len);
+	pname [phost->len] = '\0';
+	host_cnt = 0;
+	if (bSRV) {
+		/**********
+		* get SRV records
+		**********/
+
+		port = puri->port_no;
+		phead = get_record (pname, T_SRV, RES_ONLY_TYPE);
+		for (prec = phead; prec; prec = prec->next) {
+			/**********
+			* o matching port?
+			* o check max
+			* o save original port
+			* o check target
+			* o restore port
+			**********/
+
+			psrv = (struct srv_rdata *) prec->rdata;
+			if (port && (port != psrv->port))
+				{ continue; }
+			if (host_cnt == max_hosts) {
+				LM_WARN ("notification host count reached max!\n");
+				free_rdata_list (phead);
+				return host_cnt;
+			}
+			pstr->s = psrv->name;
+			pstr->len = psrv->name_len;
+			origport = puri->port_no;
+			puri->port_no = psrv->port;
+			host_cnt += get_dmq_host_list (&puri_list [host_cnt],
+				MAXDMQHOSTS - host_cnt, pstr, puri, 0);
+			puri->port_no = origport;
+		}
+		if (phead)
+			free_rdata_list (phead);
+	}
+
+	/**********
+	* get A records
+	**********/
+
+	phead = get_record (pname, T_A, RES_ONLY_TYPE);
+	for (prec = phead; prec; prec = prec->next) {
+		/**********
+		* o check max
+		* o create URI
+		**********/
+
+		if (host_cnt == max_hosts) {
+			LM_WARN ("notification host count reached max!\n");
+			free_rdata_list (phead);
+			return host_cnt;
+		}
+		len = ip4tosbuf (((struct a_rdata *) prec->rdata)->ip,
+			pIP, IP4_MAX_STR_SIZE);
+		pIP [len] = '\0';
+		if (create_IP_uri (puri_list, host_cnt, pIP, len, puri)) {
+			LM_DBG ("adding DMQ node A host %s=%s\n", pname, puri_list [host_cnt]);
+			host_cnt++;
+		}
+	}
+	if (phead)
+		free_rdata_list (phead);
+
+	/**********
+	* get AAAA records
+	**********/
+
+	phead = get_record (pname, T_AAAA, RES_ONLY_TYPE);
+	for (prec = phead; prec; prec = prec->next) {
+		/**********
+		* o check max
+		* o create URI
+		**********/
+
+		if (host_cnt == max_hosts) {
+			LM_WARN ("notification host count reached max!\n");
+			free_rdata_list (phead);
+			return host_cnt;
+		}
+		pIP [0] = '[';
+		len = ip6tosbuf (((struct aaaa_rdata *) prec->rdata)->ip6,
+			&pIP [1], IP6_MAX_STR_SIZE) + 1;
+		pIP [len++] = ']';
+		pIP [len] = '\0';
+		if (create_IP_uri (puri_list, host_cnt, pIP, len, puri)) {
+			LM_DBG
+        ("adding DMQ node AAAA host %s=%s\n", pname, puri_list [host_cnt]);
+			host_cnt++;
+		}
+	}
+	if (phead)
+		free_rdata_list (phead);
+	return host_cnt;
+}
+
 /**
  * @brief add a server node and notify it
  */
-dmq_node_t* add_server_and_notify(str* server_address)
+dmq_node_t* add_server_and_notify(str *paddr)
 {
-	/* add the notification server to the node list - if any */
-	dmq_node_t* node;
-	
-	node = add_dmq_node(node_list, server_address);
-	if(!node) {
-		LM_ERR("error adding notification node\n");
-		goto error;
+	char puri_data [MAXDMQHOSTS * (MAXDMQURILEN + 1)];
+	char *puri_list [MAXDMQHOSTS];
+	dmq_node_t *pfirst, *pnode;
+	int host_cnt, index;
+	sip_uri_t puri [1];
+	str pstr [1];
+
+	/**********
+	* o init data area
+	* o get list of hosts
+	* o process list
+	**********/
+
+	if (!multi_notify) {
+		pfirst = add_dmq_node (node_list, paddr);
+	} else {
+		/**********
+		* o init data area
+		* o get list of hosts
+		* o process list
+		**********/
+
+		for (index = 0; index < MAXDMQHOSTS; index++) {
+			puri_list [index] = &puri_data [index * (MAXDMQURILEN + 1)];
+		}
+		if (parse_uri (paddr->s, paddr->len, puri) < 0) {
+			/* this is supposed to be good but just in case... */
+			LM_ERR ("add_server_and_notify address invalid\n");
+			return 0;
+		}
+		pfirst = NULL;
+		host_cnt =
+			get_dmq_host_list (puri_list, MAXDMQHOSTS, &puri->host, puri, 1);
+		for (index = 0; index < host_cnt; index++) {
+			pstr->s = puri_list [index];
+			pstr->len = strlen (puri_list [index]);
+			if (!find_dmq_node_uri(node_list, pstr)) { // check for duplicates
+				pnode = add_dmq_node (node_list, pstr);
+				if (pnode && !pfirst)
+					{ pfirst = pnode; }
+			}
+		}
 	}
-	/* request initial list from the notification server */
-	if(request_nodelist(node, 2) < 0) {
-		LM_ERR("error requesting initial nodelist\n");
-		goto error;
+
+	/**********
+	* o found at least one?
+	* o request node list
+	**********/
+
+	if (!pfirst) {
+		LM_ERR ("error adding notification node\n");
+		return NULL;
 	}
-	return node;
-error:
-	return NULL;
+	if (request_nodelist (pfirst, 2) < 0) {
+		LM_ERR ("error requesting initial nodelist\n");
+		return NULL;
+	}
+	return pfirst;
 }
 
 /**
@@ -165,10 +423,29 @@ error:
 	return -1;
 }
 
+
+int run_init_callbacks() {
+	dmq_peer_t* crt;
+
+	if(peer_list==0) {
+		LM_WARN("peer list is null\n");
+		return 0;
+	}
+	crt = peer_list->peers;
+	while(crt) {
+		if (crt->init_callback) {
+			crt->init_callback();
+		}
+		crt = crt->next;
+	}
+	return 0;
+}
+
+
 /**
  * @brief dmq notification callback
  */
-int dmq_notification_callback(struct sip_msg* msg, peer_reponse_t* resp)
+int dmq_notification_callback(struct sip_msg* msg, peer_reponse_t* resp, dmq_node_t* dmq_node)
 {
 	int nodes_recv;
 	str* response_body = NULL;
@@ -206,6 +483,10 @@ int dmq_notification_callback(struct sip_msg* msg, peer_reponse_t* resp)
 				&notification_callback, maxforwards, &notification_content_type);
 	}
 	pkg_free(response_body);
+	if (dmq_init_callback_done && !*dmq_init_callback_done) {
+		*dmq_init_callback_done = 1;
+		run_init_callbacks();
+	}
 	return 0;
 error:
 	return -1;
@@ -292,8 +573,17 @@ int notification_resp_callback_f(struct sip_msg* msg, int code,
 		dmq_node_t* node, void* param)
 {
 	int ret;
+	int nodes_recv;
+
 	LM_DBG("notification_callback_f triggered [%p %d %p]\n", msg, code, param);
-	if(code == 408) {
+	if(code == 200) {
+		nodes_recv = extract_node_list(node_list, msg);
+		LM_DBG("received %d new or changed nodes\n", nodes_recv);
+		if (dmq_init_callback_done && !*dmq_init_callback_done) {
+			*dmq_init_callback_done = 1;
+			run_init_callbacks();
+		}
+	} else if(code == 408) {
 		/* deleting node - the server did not respond */
 		LM_ERR("deleting server %.*s because of failed request\n", STR_FMT(&node->orig_uri));
 		if (STR_EQ(node->orig_uri, dmq_notification_address)) {
diff --git a/modules/dmq/notification_peer.h b/modules/dmq/notification_peer.h
index 72df4ec..9248b39 100644
--- a/modules/dmq/notification_peer.h
+++ b/modules/dmq/notification_peer.h
@@ -1,6 +1,4 @@
 /**
- * $Id$
- *
  * dmq module - distributed message queue
  *
  * Copyright (C) 2011 Bucur Marius - Ovidiu
@@ -34,9 +32,10 @@
 #include "dmq_funcs.h"
 
 extern str notification_content_type;
+extern int *dmq_init_callback_done;
 
 int add_notification_peer();
-int dmq_notification_callback(struct sip_msg* msg, peer_reponse_t* resp);
+int dmq_notification_callback(struct sip_msg* msg, peer_reponse_t* resp, dmq_node_t* dmq_node);
 int extract_node_list(dmq_node_list_t* update_list, struct sip_msg* msg);
 str* build_notification_body();
 int build_node_str(dmq_node_t* node, char* buf, int buflen);
diff --git a/modules/dmq/peer.c b/modules/dmq/peer.c
index b93cf3a..9529379 100644
--- a/modules/dmq/peer.c
+++ b/modules/dmq/peer.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * dmq module - distributed message queue
  *
  * Copyright (C) 2011 Bucur Marius - Ovidiu
@@ -97,7 +95,7 @@ dmq_peer_t* find_peer(str peer_id)
 /**
  * @empty callback
  */
-int empty_peer_callback(struct sip_msg* msg, peer_reponse_t* resp)
+int empty_peer_callback(struct sip_msg* msg, peer_reponse_t* resp, dmq_node_t* dmq_node)
 {
 	return 0;
 }
diff --git a/modules/dmq/peer.h b/modules/dmq/peer.h
index 7ce4434..7878f6e 100644
--- a/modules/dmq/peer.h
+++ b/modules/dmq/peer.h
@@ -1,6 +1,4 @@
 /**
- * $Id$
- *
  * dmq module - distributed message queue
  *
  * Copyright (C) 2011 Bucur Marius - Ovidiu
@@ -28,6 +26,7 @@
 
 #include <string.h>
 #include <stdlib.h>
+#include "dmqnode.h"
 #include "../../lock_ops.h"
 #include "../../str.h"
 #include "../../mem/mem.h"
@@ -41,12 +40,14 @@ typedef struct peer_response {
 	str body;
 } peer_reponse_t;
 
-typedef int(*peer_callback_t)(struct sip_msg*, peer_reponse_t* resp);
+typedef int(*peer_callback_t)(struct sip_msg*, peer_reponse_t* resp, dmq_node_t* node);
+typedef int(*init_callback_t)();
 
 typedef struct dmq_peer {
 	str peer_id;
 	str description;
 	peer_callback_t callback;
+	init_callback_t init_callback;
 	struct dmq_peer* next;
 } dmq_peer_t;
 
@@ -64,7 +65,7 @@ typedef dmq_peer_t* (*register_dmq_peer_t)(dmq_peer_t*);
 
 dmq_peer_t* add_peer(dmq_peer_list_t* peer_list, dmq_peer_t* peer);
 dmq_peer_t* find_peer(str peer_id);
-int empty_peer_callback(struct sip_msg* msg, peer_reponse_t* resp);
+int empty_peer_callback(struct sip_msg* msg, peer_reponse_t* resp, dmq_node_t* dmq_node);
 
 #endif
 
diff --git a/modules/dmq/worker.c b/modules/dmq/worker.c
index a9ec65d..b47cdb7 100644
--- a/modules/dmq/worker.c
+++ b/modules/dmq/worker.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * dmq module - distributed message queue
  *
  * Copyright (C) 2011 Bucur Marius - Ovidiu
@@ -29,6 +27,8 @@
 #include "../../data_lump_rpl.h"
 #include "../../mod_fix.h"
 #include "../../sip_msg_clone.h"
+#include "../../parser/parse_from.h"
+#include "../../parser/parse_to.h"
 
 /**
  * @brief set the body of a response
@@ -37,13 +37,9 @@ static int set_reply_body(struct sip_msg* msg, str* body, str* content_type)
 {
 	char* buf;
 	int len;
-	int value_len;
-	str nb = *body;
-	str nc = *content_type;
 
 	/* add content-type */
-	value_len = nc.len;
-	len=sizeof("Content-Type: ") - 1 + value_len + CRLF_LEN;
+	len=sizeof("Content-Type: ") - 1 + content_type->len + CRLF_LEN;
 	buf=pkg_malloc(sizeof(char)*(len));
 
 	if (buf==0) {
@@ -51,8 +47,8 @@ static int set_reply_body(struct sip_msg* msg, str* body, str* content_type)
 		return -1;
 	}
 	memcpy(buf, "Content-Type: ", sizeof("Content-Type: ") - 1);
-	memcpy(buf+sizeof("Content-Type: ") - 1, nc.s, value_len);
-	memcpy(buf+sizeof("Content-Type: ") - 1 + value_len, CRLF, CRLF_LEN);
+	memcpy(buf+sizeof("Content-Type: ") - 1, content_type->s, content_type->len);
+	memcpy(buf+sizeof("Content-Type: ") - 1 + content_type->len, CRLF, CRLF_LEN);
 	if (add_lump_rpl(msg, buf, len, LUMP_RPL_HDR) == 0) {
 		LM_ERR("failed to insert content-type lump\n");
 		pkg_free(buf);
@@ -61,7 +57,7 @@ static int set_reply_body(struct sip_msg* msg, str* body, str* content_type)
 	pkg_free(buf);
 
 	/* add body */
-	if (add_lump_rpl(msg, nb.s, nb.len, LUMP_RPL_BODY) == 0) {
+	if (add_lump_rpl(msg, body->s, body->len, LUMP_RPL_BODY) == 0) {
 		LM_ERR("cannot add body lump\n");
 		return -1;
 	}
@@ -78,6 +74,8 @@ void worker_loop(int id)
 	dmq_job_t* current_job;
 	peer_reponse_t peer_response;
 	int ret_value;
+	int not_parsed;
+	dmq_node_t *dmq_node = NULL;
 
 	worker = &workers[id];
 	for(;;) {
@@ -92,7 +90,19 @@ void worker_loop(int id)
 			current_job = job_queue_pop(worker->queue);
 			/* job_queue_pop might return NULL if queue is empty */
 			if(current_job) {
-				ret_value = current_job->f(current_job->msg, &peer_response);
+				/* extract the from uri */
+				if (current_job->msg->from->parsed) {
+					not_parsed = 0;
+				} else {
+					not_parsed = 1;
+				}
+				if (parse_from_header(current_job->msg) < 0) {
+					LM_ERR("bad sip message or missing From hdr\n");
+				} else {
+					dmq_node = find_dmq_node_uri(node_list, &((struct to_body*)current_job->msg->from->parsed)->uri);
+				}
+
+				ret_value = current_job->f(current_job->msg, &peer_response, dmq_node);
 				if(ret_value < 0) {
 					LM_ERR("running job failed\n");
 					continue;
@@ -117,6 +127,10 @@ void worker_loop(int id)
 					del_nonshm_lump_rpl(&current_job->msg->reply_lump);
 					pkg_free(peer_response.body.s);
 				}
+				if((current_job->msg->from->parsed)&&(not_parsed)){
+					free_to(current_job->msg->from->parsed);
+				}
+
 				LM_DBG("sent reply\n");
 				shm_free(current_job->msg);
 				shm_free(current_job);
@@ -158,6 +172,10 @@ int add_dmq_job(struct sip_msg* msg, dmq_peer_t* peer)
 		LM_ERR("error in add_dmq_job: no workers spawned\n");
 		goto error;
 	}
+	if (!workers[0].queue) {
+		LM_ERR("workers not (yet) initialized\n");
+		goto error;
+	}
 	/* initialize the worker with the first one */
 	worker = workers;
 	/* search for an available worker, or, if not possible,
diff --git a/modules/dmq/worker.h b/modules/dmq/worker.h
index 66ebdcb..b8a5dd1 100644
--- a/modules/dmq/worker.h
+++ b/modules/dmq/worker.h
@@ -1,6 +1,4 @@
 /**
- * $Id$
- *
  * dmq module - distributed message queue
  *
  * Copyright (C) 2011 Bucur Marius - Ovidiu
diff --git a/modules/dmq_usrloc/Makefile b/modules/dmq_usrloc/Makefile
new file mode 100644
index 0000000..71125d5
--- /dev/null
+++ b/modules/dmq_usrloc/Makefile
@@ -0,0 +1,9 @@
+include ../../Makefile.defs
+auto_gen=
+NAME=dmq_usrloc.so
+
+DEFS+=-DKAMAILIO_MOD_INTERFACE
+
+SERLIBPATH=../../lib
+SER_LIBS+=$(SERLIBPATH)/srutils/srutils
+include ../../Makefile.modules
diff --git a/modules/dmq_usrloc/README b/modules/dmq_usrloc/README
new file mode 100644
index 0000000..c22b9fa
--- /dev/null
+++ b/modules/dmq_usrloc/README
@@ -0,0 +1,79 @@
+dmq_usrloc Module
+
+Andrey Rybkin
+
+   bks.tv
+   <rybkin.a at bks.tv>
+
+Edited by
+
+Andrey Rybkin
+
+   bks.tv
+   <rybkin.a at bks.tv>
+
+   Copyright � 2014
+     __________________________________________________________________
+
+   Table of Contents
+
+   1. Admin Guide
+
+        1. Overview
+        2. Dependencies
+
+              2.1. Kamailio Modules
+
+        3. Parameters
+
+              3.1. enable (int)
+
+   List of Examples
+
+   1.1. Set enable parameter
+
+Chapter 1. Admin Guide
+
+   Table of Contents
+
+   1. Overview
+   2. Dependencies
+
+        2.1. Kamailio Modules
+
+   3. Parameters
+
+        3.1. enable (int)
+
+1. Overview
+
+   The module adds user location (usrloc) records replication between
+   multiple servers via DMQ module.
+
+2. Dependencies
+
+   2.1. Kamailio Modules
+
+2.1. Kamailio Modules
+
+   The following modules must be loaded before this module:
+     * DMQ module..
+     * USRLOC module..
+
+3. Parameters
+
+   3.1. enable (int)
+
+3.1. enable (int)
+
+   The parameter controls whetner the replication is active or not. The
+   value can be:
+     * 0 - replication is disabled
+     * 1 - replication is enabled
+
+   Default value is 0.
+
+   Example 1.1. Set enable parameter
+...
+modparam("dmq_usrloc", "enable", 1)
+...
diff --git a/modules/dmq_usrloc/dmq_usrloc.c b/modules/dmq_usrloc/dmq_usrloc.c
new file mode 100644
index 0000000..cd5fedd
--- /dev/null
+++ b/modules/dmq_usrloc/dmq_usrloc.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2014 Andrey Rybkin <rybkin.a at bks.tv>
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <stdio.h>
+#include "../../sr_module.h"
+#include "../../dprint.h"
+#include "../../error.h"
+#include "../../modules/usrloc/usrloc.h"
+#include "../usrloc/ul_callback.h"
+#include "../../modules/sl/sl.h"
+#include "../../mod_fix.h"
+
+#include "usrloc_sync.h"
+
+static int mod_init(void); 
+static int child_init(int);
+
+int dmq_usrloc_enable = 0;
+
+usrloc_api_t dmq_ul;
+
+MODULE_VERSION
+
+static param_export_t params[] = {
+	{"enable", INT_PARAM, &dmq_usrloc_enable},
+	{0, 0, 0}
+};
+
+struct module_exports exports = {
+	"dmq_usrloc",				/* module name */
+	DEFAULT_DLFLAGS,		/* dlopen flags */
+	0,						/* exported functions */
+	params,					/* exported parameters */
+	0,						/* exported statistics */
+	0,   					/* exported MI functions */
+	0,						/* exported pseudo-variables */
+	0,						/* extra processes */
+	mod_init,				/* module initialization function */
+	0,   					/* response handling function */
+	0, 						/* destroy function */
+	child_init              /* per-child init function */
+};
+
+
+static int mod_init(void)
+{
+	bind_usrloc_t bind_usrloc;
+	LM_INFO("dmq usrloc replication mode = %d\n", dmq_usrloc_enable);
+
+	if (dmq_usrloc_enable) {
+
+		bind_usrloc = (bind_usrloc_t)find_export("ul_bind_usrloc", 1, 0);
+		if (!bind_usrloc) {
+			LM_ERR("can't bind usrloc\n");
+			return -1;
+		}
+		if (bind_usrloc(&dmq_ul) < 0) {
+			LM_ERR("Can't bind ul\n");
+			return -1;
+		}
+		if(dmq_ul.register_ulcb != NULL) {
+			if(dmq_ul.register_ulcb(ULCB_MAX, dmq_ul_cb_contact, 0)< 0)
+			{
+				LM_ERR("can not register callback for expired contacts\n");
+				return -1;
+			}
+		}
+		if (!usrloc_dmq_initialize()){
+			LM_DBG("dmq_usrloc initialized\n");
+		} else {
+			LM_ERR("Error in dmq_usrloc_initialize()\n");
+		}
+	}
+	return 0;
+}
+
+static int child_init(int rank)
+{
+
+	if (rank == PROC_MAIN) {
+		LM_DBG("child_init PROC_MAIN\n");
+		return 0;
+	}
+	if(rank == PROC_INIT || rank == PROC_TCP_MAIN) {
+		LM_DBG("child_init PROC_INIT\n");
+		return 0;
+	}
+	return 0;
+}
diff --git a/modules/dmq_usrloc/doc/Makefile b/modules/dmq_usrloc/doc/Makefile
new file mode 100644
index 0000000..ff1d628
--- /dev/null
+++ b/modules/dmq_usrloc/doc/Makefile
@@ -0,0 +1,4 @@
+docs = dmq_usrloc.xml
+
+docbook_dir = ../../../docbook
+include $(docbook_dir)/Makefile.module
diff --git a/modules/dmq_usrloc/doc/dmq_usrloc.xml b/modules/dmq_usrloc/doc/dmq_usrloc.xml
new file mode 100644
index 0000000..a886580
--- /dev/null
+++ b/modules/dmq_usrloc/doc/dmq_usrloc.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding='ISO-8859-1'?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+<!-- Include general documentation entities -->
+<!ENTITY % docentities SYSTEM "../../../docbook/entities.xml">
+%docentities;
+
+]>
+
+<book xmlns:xi="http://www.w3.org/2001/XInclude">
+    <bookinfo>
+	<title>dmq_usrloc Module</title>
+	<productname class="trade">&kamailioname;</productname>
+	<authorgroup>
+	    <author>
+		<firstname>Andrey</firstname>
+		<surname>Rybkin</surname>
+		<affiliation><orgname>bks.tv</orgname></affiliation>
+		<email>rybkin.a at bks.tv</email>
+		<address>
+		<otheraddr>
+		<ulink></ulink>
+		</otheraddr>
+		</address>
+	    </author>
+	    <editor>
+		<firstname>Andrey</firstname>
+		<surname>Rybkin</surname>
+		<affiliation><orgname>bks.tv</orgname></affiliation>
+		<email>rybkin.a at bks.tv</email>
+		<address>
+		<otheraddr>
+		<ulink></ulink>
+		</otheraddr>
+		</address>
+	    </editor>
+	</authorgroup>
+	<copyright>
+	    <year>2014</year>
+	</copyright>
+    </bookinfo>
+    <toc></toc>
+    
+    <xi:include href="dmq_usrloc_admin.xml"/>
+    
+    
+</book>
diff --git a/modules/dmq_usrloc/doc/dmq_usrloc_admin.xml b/modules/dmq_usrloc/doc/dmq_usrloc_admin.xml
new file mode 100644
index 0000000..abd529d
--- /dev/null
+++ b/modules/dmq_usrloc/doc/dmq_usrloc_admin.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding='ISO-8859-1'?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+<!-- Include general documentation entities -->
+<!ENTITY % docentities SYSTEM "../../../docbook/entities.xml">
+%docentities;
+
+]>
+<!-- Module User's Guide -->
+
+<chapter>
+	
+	<title>&adminguide;</title>
+	
+	<section>
+	<title>Overview</title>
+	<para>
+		The module adds user location (usrloc) records replication
+		between multiple servers via DMQ module.
+	</para>
+	</section>
+	<section>
+	<title>Dependencies</title>
+	<section>
+		<title>&kamailio; Modules</title>
+		<para>
+		The following modules must be loaded before this module:
+			<itemizedlist>
+			<listitem>
+			<para>
+				<emphasis>DMQ module.</emphasis>.
+			</para>
+			</listitem>
+			<listitem>
+			<para>
+				<emphasis>USRLOC module.</emphasis>.
+			</para>
+			</listitem>
+			</itemizedlist>
+		</para>
+	</section>
+	</section>
+	<section>
+	<title>Parameters</title>
+	<section id="usrloc_dmq.p.enable">
+		<title><varname>enable</varname> (int)</title>
+		<para>
+			The parameter controls whetner the replication is active or not.
+			The value can be:
+			<itemizedlist>
+			<listitem>
+			<para>
+				0 - replication is disabled
+			</para>
+			</listitem>
+			<listitem>
+			<para>
+				1 - replication is enabled
+			</para>
+			</listitem>
+			</itemizedlist>
+		</para>
+		<para>
+		<emphasis>
+			Default value is 0.
+		</emphasis>
+		</para>
+		<example>
+		<title>Set <varname>enable</varname> parameter</title>
+		<programlisting format="linespecific">
+...
+modparam("dmq_usrloc", "enable", 1)
+...
+</programlisting>
+	</example>
+	</section>
+	</section>
+
+</chapter>
+
diff --git a/modules/dmq_usrloc/usrloc_sync.c b/modules/dmq_usrloc/usrloc_sync.c
new file mode 100644
index 0000000..e68949c
--- /dev/null
+++ b/modules/dmq_usrloc/usrloc_sync.c
@@ -0,0 +1,519 @@
+/*
+* Copyright (C) 2014 Andrey Rybkin <rybkin.a at bks.tv>
+*
+* This file is part of Kamailio, a free SIP server.
+*
+* This file is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version
+*
+*
+* This file is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*
+*/
+
+#include "usrloc_sync.h"
+#include "../usrloc/usrloc.h"
+#include "../usrloc/ul_callback.h"
+#include "../usrloc/dlist.h"
+#include "../../dprint.h"
+#include "../../parser/parse_from.h"
+#include "../../parser/parse_addr_spec.h"
+
+static str usrloc_dmq_content_type = str_init("application/json");
+static str dmq_200_rpl  = str_init("OK");
+static str dmq_400_rpl  = str_init("Bad Request");
+static str dmq_500_rpl  = str_init("Server Internal Error");
+
+dmq_api_t usrloc_dmqb;
+dmq_peer_t* usrloc_dmq_peer = NULL;
+dmq_resp_cback_t usrloc_dmq_resp_callback = {&usrloc_dmq_resp_callback_f, 0};
+
+int usrloc_dmq_send_all();
+int usrloc_dmq_request_sync();
+int usrloc_dmq_send_contact(ucontact_t* ptr, str aor, int action, dmq_node_t* node);
+
+#define MAX_AOR_LEN 256
+
+static int add_contact(str aor, ucontact_info_t* ci)
+{
+	urecord_t* r;
+	udomain_t* _d;
+	ucontact_t* c;
+	str contact;
+	int res;
+
+	dmq_ul.get_udomain("location", &_d);
+	res = dmq_ul.get_urecord(_d, &aor, &r);
+	if (res < 0) {
+		LM_ERR("failed to retrieve record from usrloc\n");
+		goto error;
+	} else if ( res == 0) {
+		LM_DBG("'%.*s' found in usrloc\n", aor.len, ZSW(aor.s));
+		res = dmq_ul.get_ucontact(r, ci->c, ci->callid, ci->path, ci->cseq, &c);
+		LM_DBG("get_ucontact = %d\n", res);
+		if (res==-1) {
+			LM_ERR("Invalid cseq\n");
+			goto error;
+		} else if (res > 0 ) {
+			LM_DBG("Not found contact\n");
+			contact.s = ci->c->s;
+			contact.len = ci->c->len;
+			dmq_ul.insert_ucontact(r, &contact, ci, &c);
+		} else if (res == 0) {
+			LM_DBG("Found contact\n");
+			dmq_ul.update_ucontact(r, c, ci);
+		}
+	} else {
+		LM_DBG("'%.*s' Not found in usrloc\n", aor.len, ZSW(aor.s));
+		dmq_ul.insert_urecord(_d, &aor, &r);
+		LM_DBG("Insert record\n");
+		contact.s = ci->c->s;
+		contact.len = ci->c->len;
+		dmq_ul.insert_ucontact(r, &contact, ci, &c);
+		LM_DBG("Insert ucontact\n");
+	}
+
+		LM_DBG("Release record\n");
+		dmq_ul.release_urecord(r);
+		LM_DBG("Unlock udomain\n");
+		dmq_ul.unlock_udomain(_d, &aor);
+		return 0;
+	error:
+		dmq_ul.unlock_udomain(_d, &aor);
+		return -1;
+}
+
+void usrloc_get_all_ucontact(dmq_node_t* node)
+{
+ 	int rval, len=0;
+	void *buf, *cp;
+	str c;
+	str path;
+	str ruid;
+	unsigned int aorhash;
+	struct socket_info* send_sock;
+	unsigned int flags;
+
+	len = 0;
+	buf = NULL;
+
+  str aor;
+  urecord_t* r;
+  udomain_t* _d;
+  ucontact_t* ptr = 0;
+  int res;
+
+  if (dmq_ul.get_all_ucontacts == NULL){
+    LM_ERR("dmq_ul.get_all_ucontacts is NULL\n");
+    goto done;
+  }
+	rval = dmq_ul.get_all_ucontacts(buf, len, 0, 0, 1);
+	if (rval<0) {
+		LM_ERR("failed to fetch contacts\n");
+		goto done;
+	}
+	if (rval > 0) {
+		if (buf != NULL)
+			pkg_free(buf);
+		len = rval * 2;
+		buf = pkg_malloc(len);
+		if (buf == NULL) {
+			LM_ERR("out of pkg memory\n");
+			goto done;
+		}
+		rval = dmq_ul.get_all_ucontacts(buf, len, 0, 0, 1);
+		if (rval != 0) {
+			pkg_free(buf);
+			goto done;
+		}
+	}
+	if (buf == NULL)
+		goto done;
+	  cp = buf;
+    while (1) {
+        memcpy(&(c.len), cp, sizeof(c.len));
+        if (c.len == 0)
+            break;
+        c.s = (char*)cp + sizeof(c.len);
+        cp =  (char*)cp + sizeof(c.len) + c.len;
+        memcpy( &send_sock, cp, sizeof(send_sock));
+        cp = (char*)cp + sizeof(send_sock);
+        memcpy( &flags, cp, sizeof(flags));
+        cp = (char*)cp + sizeof(flags);
+        memcpy( &(path.len), cp, sizeof(path.len));
+        path.s = path.len ? ((char*)cp + sizeof(path.len)) : NULL ;
+        cp =  (char*)cp + sizeof(path.len) + path.len;
+        memcpy( &(ruid.len), cp, sizeof(ruid.len));
+        ruid.s = ruid.len ? ((char*)cp + sizeof(ruid.len)) : NULL ;
+        cp =  (char*)cp + sizeof(ruid.len) + ruid.len;
+        memcpy( &aorhash, cp, sizeof(aorhash));
+        cp = (char*)cp + sizeof(aorhash);
+
+        dmq_ul.get_udomain("location", &_d);
+
+        res = dmq_ul.get_urecord_by_ruid(_d, aorhash, &ruid, &r, &ptr);
+        aor = r->aor;
+        if (res > 0) {
+            LM_DBG("'%.*s' Not found in usrloc\n", aor.len, ZSW(aor.s));
+            dmq_ul.release_urecord(r);
+            dmq_ul.unlock_udomain(_d, &aor);
+            continue;
+        }
+        LM_DBG("- AoR: %.*s  AoRhash=%d  Flags=%d\n", aor.len, aor.s, aorhash, flags);
+
+        while (ptr) {
+            usrloc_dmq_send_contact(ptr, aor, DMQ_UPDATE, node);
+            ptr = ptr->next;
+        }
+        dmq_ul.release_urecord(r);
+        dmq_ul.unlock_udomain(_d, &aor);
+    }
+	pkg_free(buf);
+
+done:
+	c.s = ""; c.len = 0;
+}
+
+
+int usrloc_dmq_initialize()
+{
+	dmq_peer_t not_peer;
+
+	/* load the DMQ API */
+	if (dmq_load_api(&usrloc_dmqb)!=0) {
+		LM_ERR("cannot load dmq api\n");
+		return -1;
+	} else {
+		LM_DBG("loaded dmq api\n");
+	}
+	not_peer.callback = usrloc_dmq_handle_msg;
+	not_peer.init_callback = usrloc_dmq_request_sync;
+	not_peer.description.s = "usrloc";
+	not_peer.description.len = 6;
+	not_peer.peer_id.s = "usrloc";
+	not_peer.peer_id.len = 6;
+	usrloc_dmq_peer = usrloc_dmqb.register_dmq_peer(&not_peer);
+	if(!usrloc_dmq_peer) {
+		LM_ERR("error in register_dmq_peer\n");
+		goto error;
+	} else {
+		LM_DBG("dmq peer registered\n");
+	}
+	return 0;
+error:
+	return -1;
+}
+
+
+int usrloc_dmq_send(str* body, dmq_node_t* node) {
+	if (!usrloc_dmq_peer) {
+		LM_ERR("dlg_dmq_peer is null!\n");
+		return -1;
+	}
+	if (node) {
+		LM_DBG("sending dmq message ...\n");
+		usrloc_dmqb.send_message(usrloc_dmq_peer, body, node, &usrloc_dmq_resp_callback, 1, &usrloc_dmq_content_type);
+	} else {
+		LM_DBG("sending dmq broadcast...\n");
+		usrloc_dmqb.bcast_message(usrloc_dmq_peer, body, 0, &usrloc_dmq_resp_callback, 1, &usrloc_dmq_content_type);
+	}
+	return 0;
+}
+
+
+/**
+* @brief ht dmq callback
+*/
+int usrloc_dmq_handle_msg(struct sip_msg* msg, peer_reponse_t* resp, dmq_node_t* node)
+{
+	int content_length;
+	str body;
+	srjson_doc_t jdoc;
+	srjson_t *it = NULL;
+	static ucontact_info_t ci;
+
+	int action, expires, cseq, flags, cflags, q, last_modified, methods, reg_id;
+	str aor, ruid, c, received, path, callid, user_agent, instance;
+
+	parse_from_header(msg);
+	body = ((struct to_body*)msg->from->parsed)->uri;
+
+	LM_DBG("dmq message received from %.*s\n", body.len, body.s);
+
+	if(!msg->content_length) {
+		LM_ERR("no content length header found\n");
+		goto invalid;
+	}
+	content_length = get_content_length(msg);
+	if(!content_length) {
+		LM_DBG("content length is 0\n");
+		goto invalid;
+	}
+
+	body.s = get_body(msg);
+	body.len = content_length;
+
+	if (!body.s) {
+		LM_ERR("unable to get body\n");
+		goto error;
+	}
+
+	srjson_InitDoc(&jdoc, NULL);
+	jdoc.buf = body;
+	if(jdoc.root == NULL) {
+		jdoc.root = srjson_Parse(&jdoc, jdoc.buf.s);
+		if(jdoc.root == NULL)
+		{
+			LM_ERR("invalid json doc [[%s]]\n", jdoc.buf.s);
+			goto invalid;
+		}
+	}
+
+	for(it=jdoc.root->child; it; it = it->next)
+	{
+		if (it->string == NULL) continue;
+
+		if (strcmp(it->string, "action")==0) {
+			action = it->valueint;
+		} else if (strcmp(it->string, "aor")==0) {
+			aor.s = it->valuestring;
+			aor.len = strlen(aor.s);
+		} else if (strcmp(it->string, "ruid")==0) {
+			ruid.s = it->valuestring;
+			ruid.len = strlen(ruid.s);
+		} else if (strcmp(it->string, "c")==0) {
+			c.s = it->valuestring;
+			c.len = strlen(c.s);
+		} else if (strcmp(it->string, "received")==0) {
+			received.s = it->valuestring;
+			received.len = strlen(received.s);
+		} else if (strcmp(it->string, "path")==0) {
+			path.s = it->valuestring;
+			path.len = strlen(path.s);
+		} else if (strcmp(it->string, "callid")==0) {
+			callid.s = it->valuestring;
+			callid.len = strlen(callid.s);
+		} else if (strcmp(it->string, "user_agent")==0) {
+			user_agent.s = it->valuestring;
+			user_agent.len = strlen(user_agent.s);
+		} else if (strcmp(it->string, "instance")==0) {
+			instance.s = it->valuestring;
+			instance.len = strlen(instance.s);
+		} else if (strcmp(it->string, "expires")==0) { //
+			expires = it->valueint;
+		} else if (strcmp(it->string, "cseq")==0) {
+			cseq = it->valueint;
+		} else if (strcmp(it->string, "flags")==0) {
+			flags = it->valueint;
+		} else if (strcmp(it->string, "cflags")==0) {
+			cflags = it->valueint;
+		} else if (strcmp(it->string, "q")==0) {
+			q = it->valueint;
+		} else if (strcmp(it->string, "last_modified")==0) {
+			last_modified = it->valueint;
+		} else if (strcmp(it->string, "methods")==0) {
+			methods = it->valueint;
+		} else if (strcmp(it->string, "reg_id")==0) {
+			reg_id = it->valueint;
+		} else {
+			LM_ERR("unrecognized field in json object\n");
+		}
+	}
+	srjson_DestroyDoc(&jdoc);
+	memset( &ci, 0, sizeof(ucontact_info_t));
+	ci.ruid = ruid;
+	ci.c = &c;
+	ci.received = received;
+	ci.path = &path;
+	ci.expires = expires;
+	ci.q = q;
+	ci.callid = &callid;
+	ci.cseq = cseq;
+	ci.flags = flags;
+	ci.flags |= FL_RPL;
+	ci.cflags = cflags;
+	ci.user_agent = &user_agent;
+	ci.methods = methods;
+	ci.instance = instance;
+	ci.reg_id = reg_id;
+	ci.tcpconn_id = -1;
+	ci.last_modified = last_modified;
+
+	switch(action) {
+		case DMQ_UPDATE:
+						LM_DBG("Received DMQ_UPDATE. Update contact info...\n");
+						add_contact(aor, &ci);
+						break;
+		case DMQ_RM:
+						LM_DBG("Received DMQ_RM. Delete contact info...\n");
+						break;
+		case DMQ_SYNC:
+						LM_DBG("Received DMQ_SYNC. Sending all contacts...\n");
+						usrloc_get_all_ucontact(node);
+						break;
+		case DMQ_NONE:
+						LM_DBG("Received DMQ_NONE. Not used...\n");
+						break;
+
+		default:  goto invalid;
+	}
+
+	resp->reason = dmq_200_rpl;
+	resp->resp_code = 200;
+	return 0;
+
+invalid:
+	resp->reason = dmq_400_rpl;
+	resp->resp_code = 400;
+	return 0;
+
+error:
+	resp->reason = dmq_500_rpl;
+	resp->resp_code = 500;
+	return 0;
+}
+
+
+int usrloc_dmq_request_sync() {
+	srjson_doc_t jdoc;
+	LM_DBG("requesting sync from dmq peers\n");
+	srjson_InitDoc(&jdoc, NULL);
+
+	jdoc.root = srjson_CreateObject(&jdoc);
+	if(jdoc.root==NULL) {
+		LM_ERR("cannot create json root\n");
+		goto error;
+	}
+
+	srjson_AddNumberToObject(&jdoc, jdoc.root, "action", DMQ_SYNC);
+	jdoc.buf.s = srjson_PrintUnformatted(&jdoc, jdoc.root);
+	if(jdoc.buf.s==NULL) {
+		LM_ERR("unable to serialize data\n");
+		goto error;
+	}
+	jdoc.buf.len = strlen(jdoc.buf.s);
+	LM_DBG("sending serialized data %.*s\n", jdoc.buf.len, jdoc.buf.s);
+	if (usrloc_dmq_send(&jdoc.buf, 0)!=0) {
+		goto error;
+	}
+
+	jdoc.free_fn(jdoc.buf.s);
+	jdoc.buf.s = NULL;
+	srjson_DestroyDoc(&jdoc);
+	return 0;
+
+error:
+	if(jdoc.buf.s!=NULL) {
+		jdoc.free_fn(jdoc.buf.s);
+		jdoc.buf.s = NULL;
+	}
+	srjson_DestroyDoc(&jdoc);
+	return -1;
+}
+
+int usrloc_dmq_send_contact(ucontact_t* ptr, str aor, int action, dmq_node_t* node) {
+	srjson_doc_t jdoc;
+	srjson_InitDoc(&jdoc, NULL);
+
+	int flags;
+
+	jdoc.root = srjson_CreateObject(&jdoc);
+	if(jdoc.root==NULL) {
+		LM_ERR("cannot create json root\n");
+		goto error;
+	}
+
+	flags = ptr->flags;
+	flags &= ~FL_RPL;
+
+	srjson_AddNumberToObject(&jdoc, jdoc.root, "action", action);
+
+	srjson_AddStrToObject(&jdoc, jdoc.root, "aor", aor.s, aor.len);
+	srjson_AddStrToObject(&jdoc, jdoc.root, "ruid", ptr->ruid.s, ptr->ruid.len);
+	srjson_AddStrToObject(&jdoc, jdoc.root, "c", ptr->c.s, ptr->c.len);
+	srjson_AddStrToObject(&jdoc, jdoc.root, "received", ptr->received.s, ptr->received.len);
+	srjson_AddStrToObject(&jdoc, jdoc.root, "path", ptr->path.s, ptr->path.len);
+	srjson_AddStrToObject(&jdoc, jdoc.root, "callid", ptr->callid.s, ptr->callid.len);
+	srjson_AddStrToObject(&jdoc, jdoc.root, "user_agent", ptr->user_agent.s, ptr->user_agent.len);
+	srjson_AddStrToObject(&jdoc, jdoc.root, "instance", ptr->instance.s, ptr->instance.len);
+	srjson_AddNumberToObject(&jdoc, jdoc.root, "expires", ptr->expires);
+	srjson_AddNumberToObject(&jdoc, jdoc.root, "cseq", ptr->cseq);
+	srjson_AddNumberToObject(&jdoc, jdoc.root, "flags", flags);
+	srjson_AddNumberToObject(&jdoc, jdoc.root, "cflags", ptr->cflags);
+	srjson_AddNumberToObject(&jdoc, jdoc.root, "q", ptr->q);
+	srjson_AddNumberToObject(&jdoc, jdoc.root, "last_modified", ptr->last_modified);
+	srjson_AddNumberToObject(&jdoc, jdoc.root, "methods", ptr->methods);
+	srjson_AddNumberToObject(&jdoc, jdoc.root, "reg_id", ptr->reg_id);
+
+	jdoc.buf.s = srjson_PrintUnformatted(&jdoc, jdoc.root);
+	if(jdoc.buf.s==NULL) {
+		LM_ERR("unable to serialize data\n");
+		goto error;
+	}
+	jdoc.buf.len = strlen(jdoc.buf.s);
+
+	LM_DBG("sending serialized data %.*s\n", jdoc.buf.len, jdoc.buf.s);
+	if (usrloc_dmq_send(&jdoc.buf, node)!=0) {
+		goto error;
+	}
+
+	jdoc.free_fn(jdoc.buf.s);
+	jdoc.buf.s = NULL;
+	srjson_DestroyDoc(&jdoc);
+	return 0;
+
+error:
+	if(jdoc.buf.s!=NULL) {
+		jdoc.free_fn(jdoc.buf.s);
+		jdoc.buf.s = NULL;
+	}
+	srjson_DestroyDoc(&jdoc);
+	return -1;
+}
+
+int usrloc_dmq_resp_callback_f(struct sip_msg* msg, int code,
+                            dmq_node_t* node, void* param)
+{
+	LM_DBG("dmq response callback triggered [%p %d %p]\n", msg, code, param);
+	return 0;
+}
+
+void dmq_ul_cb_contact(ucontact_t* ptr, int type, void* param)
+{
+	str aor;
+
+		LM_DBG("Callback from usrloc with type=%d\n", type);
+		aor.s = ptr->aor->s;
+		aor.len = ptr->aor->len;
+
+		if (!(ptr->flags & FL_RPL)) {
+
+			switch(type){
+				case UL_CONTACT_INSERT:
+											usrloc_dmq_send_contact(ptr, aor, DMQ_UPDATE, 0);
+										break;
+				case UL_CONTACT_UPDATE:
+											usrloc_dmq_send_contact(ptr, aor, DMQ_UPDATE, 0);
+										break;
+				case UL_CONTACT_DELETE:
+											//usrloc_dmq_send_contact(ptr, aor, DMQ_RM);
+											LM_DBG("Contact <%.*s> deleted\n", aor.len, aor.s);
+										break;
+				case UL_CONTACT_EXPIRE:
+											//usrloc_dmq_send_contact(ptr, aor, DMQ_UPDATE);
+											LM_DBG("Contact <%.*s> expired\n", aor.len, aor.s);
+										break;
+			}
+		} else {
+			LM_DBG("Contact recieved from DMQ... skip\n");
+		}
+}
diff --git a/modules/dmq_usrloc/usrloc_sync.h b/modules/dmq_usrloc/usrloc_sync.h
new file mode 100644
index 0000000..c00e199
--- /dev/null
+++ b/modules/dmq_usrloc/usrloc_sync.h
@@ -0,0 +1,48 @@
+/*
+* Copyright (C) 2014 Andrey Rybkin <rybkin.a at bks.tv>
+*
+* This file is part of Kamailio, a free SIP server.
+*
+* This file is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version
+*
+*
+* This file is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*
+*/
+
+#ifndef _DMQ_SYNC_USRLOC_H_
+#define _DMQ_SYNC_USRLOC_H_
+
+#include "../dmq/bind_dmq.h"
+#include "../../lib/srutils/srjson.h"
+#include "../../parser/msg_parser.h"
+#include "../../parser/parse_content.h"
+#include "../usrloc/usrloc.h"
+
+
+extern usrloc_api_t dmq_ul;
+
+typedef enum {
+	DMQ_NONE,
+	DMQ_UPDATE,
+	DMQ_RM,
+	DMQ_SYNC,
+} usrloc_dmq_action_t;
+
+int usrloc_dmq_resp_callback_f(struct sip_msg* msg, int code, dmq_node_t* node, void* param);
+int usrloc_dmq_initialize();
+int usrloc_dmq_handle_msg(struct sip_msg* msg, peer_reponse_t* resp, dmq_node_t* node);
+int usrloc_dmq_request_sync();
+void dmq_ul_cb_contact(ucontact_t* c, int type, void* param);
+
+#endif
diff --git a/modules/dnssec/Makefile b/modules/dnssec/Makefile
index a5ae601..e88b4a2 100644
--- a/modules/dnssec/Makefile
+++ b/modules/dnssec/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # example module makefile
 #
diff --git a/modules/dnssec/dnssec_func.c b/modules/dnssec/dnssec_func.c
index 1ddc602..58df952 100644
--- a/modules/dnssec/dnssec_func.c
+++ b/modules/dnssec/dnssec_func.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * DNSSEC module
  *
  * Copyright (C) 2013 mariuszbi at gmail.com
@@ -21,10 +19,17 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2013-03	initial implementation
  */
+/*!
+ * \brief DNSsec support
+ * \ingroup DNSsec 
+ * \author mariuszbi at gmail.com
+ */
+/*!
+ * \defgroup DNSsec DNS security extensions support
+ *
+ */
+
 
 #include <validator/validator-config.h>
 #include <validator/validator.h>
diff --git a/modules/dnssec/dnssec_func.h b/modules/dnssec/dnssec_func.h
index 7baaac0..abb6dee 100644
--- a/modules/dnssec/dnssec_func.h
+++ b/modules/dnssec/dnssec_func.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * DNSSEC module
  *
  * Copyright (C) 2013 mariuszbi at gmail.com
@@ -21,9 +19,11 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2013-03	initial implementation
+ */
+/*!
+ * \brief DNSsec support
+ * \ingroup DNSsec
+ * \author mariuszbi at gmail.com
  */
 
 #ifndef DNSSEC_FUNC_H
diff --git a/modules/dnssec/dnssec_mod.c b/modules/dnssec/dnssec_mod.c
index 1f399f5..f563219 100644
--- a/modules/dnssec/dnssec_mod.c
+++ b/modules/dnssec/dnssec_mod.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * DNSSEC module
  *
  * Copyright (C) 2013 mariuszbi at gmail.com
@@ -21,9 +19,11 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2013-03	initial implementation
+ */
+/*!
+ * \brief DNSsec support
+ * \ingroup DNSsec
+ * \author mariuszbi at gmail.com
  */
 
 
@@ -107,13 +107,6 @@ static int dnssec_init(void)
 {
 	LOG(L_INFO, "DNSSEC  - initializing\n");
 
-/*	if(register_mi_mod(exports.name, mi_cmds)!=0)
-	{
-		LM_ERR("failed to register MI commands\n");
-		return -1;
-	}
-*/
-	
 	//set parameters
 	if(flags) set_context_flags(flags);
 
diff --git a/modules/domain/Makefile b/modules/domain/Makefile
index f759f7a..f837c97 100644
--- a/modules/domain/Makefile
+++ b/modules/domain/Makefile
@@ -1,4 +1,3 @@
-# Makefile v 1.0 2002/12/27
 #
 # Domain module makefile
 #
diff --git a/modules/domain/domain.c b/modules/domain/domain.c
index 7e2ef4f..19943ab 100644
--- a/modules/domain/domain.c
+++ b/modules/domain/domain.c
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- *
  * Domain table related functions
  *
  * Copyright (C) 2002-2012 Juha Heinanen
@@ -21,12 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2004-06-07  updated to the new DB api, moved reload_table here, created 
- *               domain_db_{init.bind,ver,close} (andrei)
- *  2004-09-06  is_uri_host_local() can now be called also from
- *              failure route (juhe)
  */
 
 #include "domain_mod.h"
@@ -48,7 +40,7 @@ static db_func_t domain_dbf;
 int domain_db_bind(const str* db_url)
 {
 	if (db_bind_mod(db_url, &domain_dbf )) {
-	        LM_ERR("Cannot bind to database module!");
+	        LM_ERR("Cannot bind to database module!\n");
 		return -1;
 	}
 	return 0;
diff --git a/modules/domain/domain.h b/modules/domain/domain.h
index f3d4355..664c844 100644
--- a/modules/domain/domain.h
+++ b/modules/domain/domain.h
@@ -1,5 +1,4 @@
-/* domain.h v 0.1 2002/12/27
- *
+/* 
  * Header file for domain table relates functions
  *
  * Copyright (C) 2002-2012 Juha Heinanen
diff --git a/modules/domain/domain_mod.c b/modules/domain/domain_mod.c
index 6a31227..81f3091 100644
--- a/modules/domain/domain_mod.c
+++ b/modules/domain/domain_mod.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Domain module
  *
  * Copyright (C) 2002-2012 Juha Heinanen
@@ -21,16 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * -------
- * 2003-03-11: New module interface (janakj)
- * 2003-03-16: flags export parameter added (janakj)
- * 2003-04-05: default_uri #define used (jiri)
- * 2003-04-06: db connection closed in mod_init (janakj)
- * 2004-06-06: updated to the new DB api, cleanup: static dbf & handler,
- *             calls to domain_db_{bind,init,close,ver} (andrei)
- * 2006-01-22: added is_domain_local(variable) function (dan)
- *
  */
 
 
@@ -188,7 +176,8 @@ static int mod_init(void)
 
     /* Bind database */
     if (domain_db_bind(&db_url)) {
-	LM_ERR("no database module found\n");
+	LM_DBG("Usign db_url [%.*s]\n", db_url.len, db_url.s);
+	LM_ERR("no database module found. Have you configure thed \"db_url\" modparam properly?\n");
 	return -1;
     }
 
diff --git a/modules/domain/domain_mod.h b/modules/domain/domain_mod.h
index 89c0e25..4f7a9a9 100644
--- a/modules/domain/domain_mod.h
+++ b/modules/domain/domain_mod.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Domain module headers
  *
  * Copyright (C) 2002-2012 Juha Heinanen
diff --git a/modules/domain/hash.c b/modules/domain/hash.c
index ddaae61..951cf35 100644
--- a/modules/domain/hash.c
+++ b/modules/domain/hash.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Hash functions for cached domain table
  *
  * Copyright (C) 2002-2012 Juha Heinanen
diff --git a/modules/domain/hash.h b/modules/domain/hash.h
index de30503..990d459 100644
--- a/modules/domain/hash.h
+++ b/modules/domain/hash.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Header file for hash table functions
  *
  * Copyright (C) 2002-2012 Juha Heinanen
diff --git a/modules/domain/mi.c b/modules/domain/mi.c
index 585a401..c3a5403 100644
--- a/modules/domain/mi.c
+++ b/modules/domain/mi.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Domain MI functions
  *
  * Copyright (C) 2006 Voice Sistem SRL
diff --git a/modules/domain/mi.h b/modules/domain/mi.h
index ba1f355..b5f1285 100644
--- a/modules/domain/mi.h
+++ b/modules/domain/mi.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Header file for domain MI functions
  *
  * Copyright (C) 2006 Voice Sistem SRL
diff --git a/modules/domainpolicy/Makefile b/modules/domainpolicy/Makefile
index 91af98e..cfe6853 100644
--- a/modules/domainpolicy/Makefile
+++ b/modules/domainpolicy/Makefile
@@ -1,4 +1,3 @@
-# Makefile v 1.0 2002/12/27
 #
 # Domain Policy module makefile
 #
diff --git a/modules/drouting/Makefile b/modules/drouting/Makefile
index a92749e..1d85b9c 100644
--- a/modules/drouting/Makefile
+++ b/modules/drouting/Makefile
@@ -1,4 +1,3 @@
-# $Id: Makefile,v 1.1.1.1 2007/05/09 11:25:33 bogdan Exp $
 #
 # WARNING: do not run this directly, it should be run by the master Makefile
 
diff --git a/modules/drouting/drouting.c b/modules/drouting/drouting.c
index 1c94fe3..3c79f26 100644
--- a/modules/drouting/drouting.c
+++ b/modules/drouting/drouting.c
@@ -563,7 +563,7 @@ static inline str* build_ruri(struct sip_uri *uri, int strip, str *pri,
 	}
 	memcpy(p, uri->user.s+strip, uri->user.len-strip);
 	p += uri->user.len-strip;
-	if (uri->passwd.len) {
+	if (uri->passwd.s && uri->passwd.len) {
 		*(p++)=':';
 		memcpy(p, uri->passwd.s, uri->passwd.len);
 		p += uri->passwd.len;
@@ -571,12 +571,12 @@ static inline str* build_ruri(struct sip_uri *uri, int strip, str *pri,
 	*(p++)='@';
 	memcpy(p, hostport->s, hostport->len);
 	p += hostport->len;
-	if (uri->params.len) {
+	if (uri->params.s && uri->params.len) {
 		*(p++)=';';
 		memcpy(p, uri->params.s, uri->params.len);
 		p += uri->params.len;
 	}
-	if (uri->headers.len) {
+	if (uri->headers.s && uri->headers.len) {
 		*(p++)='?';
 		memcpy(p, uri->headers.s, uri->headers.len);
 		p += uri->headers.len;
diff --git a/modules/enum/Makefile b/modules/enum/Makefile
index aa00d54..8a8f4ef 100644
--- a/modules/enum/Makefile
+++ b/modules/enum/Makefile
@@ -1,4 +1,3 @@
-# Makefile v 1.0 2002/12/27
 #
 # Enum module makefile
 #
diff --git a/modules/enum/enum.c b/modules/enum/enum.c
index b5ac3c8..3c21c2f 100644
--- a/modules/enum/enum.c
+++ b/modules/enum/enum.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Enum and E164 related functions
  *
  * Copyright (C) 2002-2010 Juha Heinanen
diff --git a/modules/enum/enum.h b/modules/enum/enum.h
index 39bc52c..838caf6 100644
--- a/modules/enum/enum.h
+++ b/modules/enum/enum.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Header file for Enum and E164 related functions
  *
  * Copyright (C) 2002-2008 Juha Heinanen
diff --git a/modules/enum/enum_mod.c b/modules/enum/enum_mod.c
index b1ffb66..2bab489 100644
--- a/modules/enum/enum_mod.c
+++ b/modules/enum/enum_mod.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Enum module
  *
  * Copyright (C) 2002-2008 Juha Heinanen
@@ -21,11 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * -------
- * 2003-03-11: New module interface (janakj)
- * 2003-03-16: flags export parameter added (janakj)
- * 2003-12-15: added suffix parameter to enum_query (jh)
  */
 
 /*!
diff --git a/modules/enum/enum_mod.h b/modules/enum/enum_mod.h
index ab92cdc..b4da805 100644
--- a/modules/enum/enum_mod.h
+++ b/modules/enum/enum_mod.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Enum module headers
  *
  * Copyright (C) 2002-2003 Juha Heinanen
diff --git a/modules/erlang/Makefile b/modules/erlang/Makefile
new file mode 100644
index 0000000..61e0336
--- /dev/null
+++ b/modules/erlang/Makefile
@@ -0,0 +1,26 @@
+# 
+# WARNING: do not run this directly, it should be run by the master Makefile
+
+include ../../Makefile.defs
+auto_gen=
+NAME=erlang.so
+
+ERLANG=$(shell which erl)
+
+ifneq ($(ERLANG),)
+ERLANG_LIBDIR=$(shell $(ERLANG) -noshell -eval 'io:format("~n~s/lib~n", [[code:lib_dir("erl_interface")]]).' -s erlang halt | tail -n 1)
+ERLANG_INCDIR=$(shell $(ERLANG) -noshell -eval 'io:format("~n~s/include~n", [[code:lib_dir("erl_interface")]]).' -s erlang halt | tail -n 1)
+else
+$(error Not found Erlang)
+endif
+LIBS=-L$(ERLANG_LIBDIR) -lei -lpthread
+
+SERLIBPATH=../../lib
+SER_LIBS+=$(SERLIBPATH)/kcore/kcore
+
+DEFS+=-I$(ERLANG_INCDIR)
+DEFS+=-DKAMAILIO_MOD_INTERFACE -D_REENTRANT
+
+
+include ../../Makefile.modules
+
diff --git a/modules/erlang/README b/modules/erlang/README
new file mode 100644
index 0000000..65724c9
--- /dev/null
+++ b/modules/erlang/README
@@ -0,0 +1,852 @@
+ERLANG Module
+
+Seudin Kasumovic
+
+   <seudin.kasumovic at gmail.com>
+
+Edited by
+
+Seudin Kasumovic
+
+   <seudin.kasumovic at gmail.com>
+
+   Copyright © 2015 Bicom Systems Ltd.
+     __________________________________________________________________
+
+   Table of Contents
+
+   1. Admin Guide
+
+        1. Overview
+        2. Dependencies
+
+              2.1. Kamailio Modules
+              2.2. External Libraries or Applications
+
+        3. Parameters
+
+              3.1. no_cnodes (int)
+              3.2. cnode_alivename (str)
+              3.3. cnode_host (str)
+              3.4. erlang_nodename (str)
+              3.5. cookie (str)
+              3.6. trace_level (int)
+              3.7. rpc_reply_with_struct (int)
+
+        4. Exported pseudo variables
+
+              4.1. Overview
+              4.2. Attributes
+              4.3. $erl_atom(name)
+              4.4. $erl_list(name)
+              4.5. $erl_tuple(name)
+              4.6. $erl_pid(name)
+              4.7. $erl_ref(name)
+              4.8. $erl_xbuff(name)
+
+        5. Functions
+
+              5.1. erl_rpc(mod,fun,args,reply)
+              5.2. erl_reg_send(server,msg)
+              5.3. erl_send(pid,msg)
+              5.4. erl_reply(msg)
+
+        6. Event routes
+
+              6.1. Registered pseudo process
+              6.2. event_route[erlang:self]
+
+   2. Using Kamailio from Erlang
+
+        1. RPC calls from Erlang
+
+   3. Developer Guide
+
+        1. Available Functions
+
+              1.1. erl_load_api(erl_api)
+              1.2. rpc(reply,module,function,args)
+              1.3. reg_send(server,msg)
+              1.4. send(pid,msg)
+              1.5. reply(msg)
+              1.6. xavp2xbuff(xbuff,xavp)
+              1.7. xbuff2xavp(xavp,xbuff)
+
+   List of Examples
+
+   1.1. Set no_cnodes parameter
+   1.2. Set cnode_alivename parameter
+   1.3. Set cnode_host parameter
+   1.4. Set erlang_nodename parameter
+   1.5. Set cookie parameter
+   1.6. Set trace_level parameter
+   1.7. Example of using attribute length
+   1.8. Example of using attributes type and format
+   1.9. Example set and print to log $erl_atom
+   1.10. Example of using $erl_list
+   1.11. Example of using erl_tuple
+   1.12. Example of using $erl_pid
+   1.13. Example of using erl_ref
+   1.14. Example of using $erl_xbuff
+   1.15. Example of using erl_rpc
+   1.16. Example of using erl_reg_send
+   1.17. Example of using erl_send
+   1.18. Example of use erl_reply
+   1.19. Example of registered process
+   1.20. Example of using default event route
+   2.1. Example of RPC call from erlang shell with no response
+   2.2. Example, check is line registered
+   2.3. Example get config variable
+   2.4. Example get dialog statistics
+   3.1. Example of using API
+
+Chapter 1. Admin Guide
+
+   Table of Contents
+
+   1. Overview
+   2. Dependencies
+
+        2.1. Kamailio Modules
+        2.2. External Libraries or Applications
+
+   3. Parameters
+
+        3.1. no_cnodes (int)
+        3.2. cnode_alivename (str)
+        3.3. cnode_host (str)
+        3.4. erlang_nodename (str)
+        3.5. cookie (str)
+        3.6. trace_level (int)
+        3.7. rpc_reply_with_struct (int)
+
+   4. Exported pseudo variables
+
+        4.1. Overview
+        4.2. Attributes
+        4.3. $erl_atom(name)
+        4.4. $erl_list(name)
+        4.5. $erl_tuple(name)
+        4.6. $erl_pid(name)
+        4.7. $erl_ref(name)
+        4.8. $erl_xbuff(name)
+
+   5. Functions
+
+        5.1. erl_rpc(mod,fun,args,reply)
+        5.2. erl_reg_send(server,msg)
+        5.3. erl_send(pid,msg)
+        5.4. erl_reply(msg)
+
+   6. Event routes
+
+        6.1. Registered pseudo process
+        6.2. event_route[erlang:self]
+
+1. Overview
+
+   Erlang is a general-purpose programming language and runtime
+   environment. Erlang has built-in support for concurrency, distribution
+   and fault tolerance. This module provides interact with Erlang node.
+   The module allows sending, receiving Erlang messages and RPC calls
+   between each other.
+
+2. Dependencies
+
+   2.1. Kamailio Modules
+   2.2. External Libraries or Applications
+
+2.1. Kamailio Modules
+
+   The following modules must be loaded before this module:
+     * None
+
+2.2. External Libraries or Applications
+
+   The following libraries or applications must be installed before
+   running Kamailio with this module loaded:
+     * ei - Erlang interface C library.
+       The routines for handling the Erlang binary term format and
+       communicate with with distributed Erlang. For more details see
+       Erlang Interface Reference Manual
+     * epmd - Erlang Port Mapper Daemon.
+       This daemon acts as a name server on all hosts involved in
+       distributed Erlang computations. For more details see Erlang Port
+       Mapper Daemon Manual.
+
+   epmd must running on the same host where Kamailio is running. Erlang
+   does not need to be installed on the same host where Kamailio is
+   running.
+
+3. Parameters
+
+   3.1. no_cnodes (int)
+   3.2. cnode_alivename (str)
+   3.3. cnode_host (str)
+   3.4. erlang_nodename (str)
+   3.5. cookie (str)
+   3.6. trace_level (int)
+   3.7. rpc_reply_with_struct (int)
+
+3.1. no_cnodes (int)
+
+   Number of erlang C node processes to be started to handle the
+   communication tasks. A C node is a C program written to act as a hidden
+   node in a distributed Erlang system.
+
+   Default value is 1.
+
+   Example 1.1. Set no_cnodes parameter
+...
+modparam("erlang", "no_cnodes", 2)
+...
+
+3.2. cnode_alivename (str)
+
+   alivename is the registered name of the Kamailio process.
+
+   Note, if the no_cnodes greater then 1, then alivename of Kamailio
+   process will be suffixed with number.
+
+   Example 1.2. Set cnode_alivename parameter
+...
+modparam("erlang", "cnode_alivename", "proxy")
+...
+
+3.3. cnode_host (str)
+
+   C node host is the name of the machine we're running on. If long names
+   are to be used, it should be fully qualified.
+
+   Example 1.3. Set cnode_host parameter
+...
+modparam("erlang", "cnode_host", "kamailio.lan")
+...
+
+3.4. erlang_nodename (str)
+
+   The format of the node name is an name at host where name is the name
+   given by the user and host is the full host name if long names are
+   used, or the first part of the host name if short names are used.
+
+   Example 1.4. Set erlang_nodename parameter
+...
+modparam("erlang", "erlang_nodename", "node1 at erlang.lan")
+...
+
+3.5. cookie (str)
+
+   Each node has its own magic cookie. When a nodes tries to connect to
+   another node, the magic cookies are compared If they do not match, the
+   connected node rejects the connection.
+
+   Example 1.5. Set cookie parameter
+...
+modparam("erlang", "cookie", "secretcookie")
+...
+
+3.6. trace_level (int)
+
+   Used to set tracing on the distribution. The parameter is different
+   verbosity level. A higher level means more information. Useful in
+   development, but in production should be disabled.
+
+   The different tracelevels has the following messages:
+    1. Verbose error messages
+    2. Above messages and verbose warning messages
+    3. Above messages and progress reports for connection handling
+    4. Above messages and progress reports for communication
+    5. Above messages and progress reports for data conversion
+
+   Default value is 0, no verbose is set. To see trace log on stdout,
+   Kamailio must be started with -E option.
+
+   Example 1.6. Set trace_level parameter
+...
+modparam("erlang", "trace_level", 5)
+...
+
+3.7. rpc_reply_with_struct (int)
+
+   Prepend Erlang atom struct in RPC Kamailio reply where RPC struct is
+   generated. Some libraries for converting erlang term in JSON require
+   atom struct as first element in tuple to convert list of properties
+   into javscript object.
+   Default value is 0 (disabled).
+
+4. Exported pseudo variables
+
+   4.1. Overview
+   4.2. Attributes
+   4.3. $erl_atom(name)
+   4.4. $erl_list(name)
+   4.5. $erl_tuple(name)
+   4.6. $erl_pid(name)
+   4.7. $erl_ref(name)
+   4.8. $erl_xbuff(name)
+
+4.1. Overview
+
+   Erlang provides a number of data types but not all of them are
+   supported by Kamailio. This module provides several of them as pseudo
+   variables. These pseudo variables allow user to create Erlang message
+   or function arguments and receive result from Erlang node. Some Erlang
+   variables can contain other data types, so we introduced several
+   attributes to determine type, length, or get formatted output useful
+   for debug, quick compare or put into the log.
+
+4.2. Attributes
+
+   Exported pseudo variable has several attributes to get type, length and
+   formatted output readable by transformations or user. Pseudo variable
+   by self determine variable type, but we need to know what type on some
+   position is.
+     * type
+       get variable type. Possible types are: atom, integer, list, string,
+       tuple, pid and ref.
+     * length
+       get length of list or tuple.
+     * format
+       Prints a term, in clear text. It tries to resemble the term
+       printing in the Erlang shell.
+
+   Example 1.7. Example of using attribute length
+...
+xlogl("L_DEBUG","The number of elements in list L: $erl_list(L=>length)\n");
+xlogl("L_DEBUG","The number of elements in tuple T: $erl_tuple(T=>length)\n");
+...
+
+> example of log output:
+
+DEBUG: <script>: 120:The number of elements in list L: 4
+DEBUG: <script>: 121:The number of elements in tuple T: 2
+...
+
+   Example 1.8. Example of using attributes type and format
+...
+xlogl("L_DEBUG","list L in clear text: $erl_list(L=>format), the type at index 2
+: $erl_list(L[2]=>type)\n");
+xlogl("L_DEBUG","tuple T in clear text: $erltuple(T=>format), the type at index
+1: $erl_tuple[T[1]=>type)\n");
+...
+
+> example of log output:
+
+DEBUG: <script>: 130:list L in clear text: [example, list, 4, "items"], the type
+ at index 2: integer
+DEBUG: <script>: 131:tuple T in clear text: {example, tuple}, the type at index
+1: atom
+...
+
+4.3. $erl_atom(name)
+
+   erl_atom pseudo variable allows create analog to Erlang atom data type.
+   Erlang atom is a literal, a constant with name. Formatted output pseudo
+   variable atom could be enclosed in single quotes (') if it does not
+   begin with a lower-case letter or if it contains other characters than
+   alphanumeric characters, underscore (_), or @.
+
+   Example 1.9. Example set and print to log $erl_atom
+...
+$erl_atom(A) = "badrpc";
+xlogl("L_DEBUG","$$erl_atom(A): $erl_atom(A=>format)\n");
+...
+
+> log output is:
+
+DEBUG: <script>: 123:$erl_atom(A): badrpc
+...
+
+4.4. $erl_list(name)
+
+   Compound data type with a variable number of terms. Formally, a list is
+   either the empty list [] or consists of one or more elements.
+
+   Behavior of the list is the same as AVP variable. Set value without
+   index prepends element on list. You are able to replace element at
+   given index. List supports [*] index to get whole list or reset all
+   elements in the list. To create empty list set whole list to $null.
+
+   Example 1.10. Example of using $erl_list
+...
+$erl_atom(E) = "example";
+$erl_list(L) = "list";
+$erl_list(L) = "of";
+$erl_list(L) = $erl_atom(E);
+
+xlogl("L_DEBUG","length(L): $erl_list(L=>length), format(L): $erl_list(L=>format
+)\n");
+
+# empty list
+$erl_tuple(E[*]) = $null;
+
+xlogl("L_DEBUG","length(E): $erl_list(E=>length), format(E): $erl_list(L=>format
+)\n");
+...
+
+> log output is:
+
+DEBUG: <script>: 143:length(L): 3, format(L): [example, "of", "list"]
+DEBUG: <script>: 148:length(E): 0, format(E): []
+...
+
+4.5. $erl_tuple(name)
+
+   From the Erlang point of view the tuple compound data type with a fixed
+   number of terms. The module implementation of tuple has the same
+   behavior as the list.
+
+   Example 1.11. Example of using erl_tuple
+...
+$erl_atom(line) = "line";
+$erl_atom(id)   = "id";
+$erl_atom(owner)= "owner";
+
+$var(user)  = "Bob";
+
+$erl_tuple(owner) = $var(user);
+$erl_tuple(owner) = $erl_atom(owner);
+
+$erl_tuple(id) = 23;
+$erl_tuple(id) = $erl_atom(id);
+
+$erl_list(L) = $erl_tuple(owner);
+$erl_list(L) = $erl_tuple(id);
+
+$erl_tuple(T) = $erl_list(L);
+$erl_tuple(T) = $erl_atom(line);
+
+xlogl("L_DEBUG","length(T): $erl_tuple(T=>length), format(T): $erl_tuple(T=>form
+at)\n");
+...
+
+> log output is:
+...
+DEBUG: <script>: 153:length(T): 2, format(T): {line, [{id, 23}, {owner, "Bob"}]}
+...
+
+4.6. $erl_pid(name)
+
+   erl_pid holds Eralng process identifier. Provides access to Erlang PID
+   value and could be used in send message.
+
+   Example 1.12. Example of using $erl_pid
+...
+if ($erl_xbuff(msg[0]=>type) == "pid") {
+        $erl_pid(pid) = $erl_xbuff(msg[0]);
+        xlogl("L_INFO","Received PID: $erl_pid(pid=>format)\n");
+}
+...
+
+4.7. $erl_ref(name)
+
+   erl_ref holds Erlang reference. Provides access to reference value and
+   could be used in send message.
+
+   Example 1.13. Example of using erl_ref
+...
+if ($erl_xbuff(msg[0]=>type) == "ref") {
+        $erl_ref(ref) = $erl_xbuff(msg[0]);
+        xlogl("L_INFO","Reference: $erl_ref(ref=>format)\n");
+}
+...
+
+4.8. $erl_xbuff(name)
+
+   erl_xbuff is created as generic pseudo variable to acts as other pseudo
+   variables exported from module. It's useful when in advance we don't
+   know what variable type to expect. The behavior of variable depends of
+   initialization. Module functions expect this PV as return value, and PV
+   for incoming Erlang message.
+
+   Example 1.14. Example of using $erl_xbuff
+...
+# Tuple T from previous example
+
+$erl_xbuff(X) = $erl_tuple(T);
+
+xlogl("L_DEBUG","typeof(X): $erl_xbuff(X=>type), length(X): $erl_xbuff(X=>length
+), format(X): $erl_xbuff(X=>format)\n");
+...
+
+> log output is:
+...
+DEBUG: <script>: 410:typeof(X): tuple, length(X): 2, format(X): {line, [{id, 23}
+, {owner, "Bob"}]}
+...
+
+5. Functions
+
+   5.1. erl_rpc(mod,fun,args,reply)
+   5.2. erl_reg_send(server,msg)
+   5.3. erl_send(pid,msg)
+   5.4. erl_reply(msg)
+
+5.1.  erl_rpc(mod,fun,args,reply)
+
+   This function supports calling Erlang functions on remote nodes.
+
+   The parameter mod and fun are module and function name respectively. It
+   can be a static string or a dynamic string value with config variables.
+
+   The parameter args is list of arguments passed to function, so it must
+   be list, or xbuff that contains list.
+
+   The parameter reply is result from RPC call. It must be xbuff to accept
+   any result.
+
+   Function returns false on error to send or wrong arguments passed to
+   function. If executing remote function caused error function still
+   returns true but error is encoded into repl parameter.
+
+   Example 1.15. Example of using erl_rpc
+...
+# example of call erlang:list_to_tuple(["one","two"])
+# on remote node
+
+$erl_list(L) = "two";
+$erl_list(L) = "one";
+
+# put list into list
+$erl_list(args) = $erl_list(L);
+
+erl_rpc("erlang", "list_to_tuple", "$erl_list(args)", "$erl_xbuff(repl)");
+
+xlogl("L_DEBUG","type(repl): $erl_xbuff(repl=>type), format(repl): $erl_xbuff(re
+pl=>format)\n");
+
+> log output:
+...
+DEBUG: <script>: 386:type(repl): tuple, format(repl): {"one", "two"}
+...
+
+5.2. erl_reg_send(server,msg)
+
+   This function sends an Erlang term to a registered process.
+
+   The argument server is the registered name of the intended recipient
+   process on remote node.
+
+   The argument msg is containing the message to be sent.
+
+   Example 1.16. Example of using erl_reg_send
+...
+# example of send message to registered process
+# {notifier,'node1 at erlang.lan'} ! {example,message}
+
+$erl_atom(example) = "example";
+$erl_atom(message) = "message";
+
+$erl_tuple(M) = $erl_atom(message);
+$erl_tuple(M) = $erl_atom(example);
+
+erl_reg_send("notifier","$erl_tuple(M)");
+...
+
+5.3. erl_send(pid,msg)
+
+   This function sends an Erlang term to a process. This function can be
+   used from ANY_ROUTE. The argument pid is the Erlang process id of the
+   intended recipient process on remote node. The argument msg is
+   containing the message to be sent.
+
+   Example 1.17. Example of using erl_send
+...
+# example of send message to process
+# Pid ! {example,message}
+
+$erl_atom(notifier) = "notifier";
+$erl_list(args) = $erl_atom(notifier);
+
+erl_rpc("erlang", "whereis", "$erl_list(args)", "$erl_xbuff(pid)");
+
+$erl_atom(example) = "example";
+$erl_atom(message) = "message";
+
+$erl_tuple(M) = $erl_atom(message);
+$erl_tuple(M) = $erl_atom(example);
+
+erl_send("$erl_xbuff(pid)","$erl_tuple(M)");
+...
+
+5.4. erl_reply(msg)
+
+   Function to send message from event route (pseudo process). Function
+   sends reply message msg to the sender process.
+
+   Example 1.18. Example of use erl_reply
+...
+# event route acts as registered process
+event_route[erlang:greetings] {
+
+        xlogl("L_INFO","Received message: $erl_xbuff(msg=>format)\n");
+
+        $erl_atom(hello) = "hello";
+        $erl_tuple(reply) = "Erlang";
+        $erl_tuple(reply) = $erl_atom(hello);
+
+        # reply greeting
+        erl_reply("$erl_tuple(reply)");
+}
+...
+
+%% in erlang shell
+
+(node1 at erlang.lan)24> {greetings,'proxy at kamailio.lan'} ! {hello,"Kamailio"}.
+{hello,"Kamailio"}
+(node1 at erlang.lan)25> flush().
+Shell got {hello,"Erlang"}
+ok
+
+> logged info message:
+INFO: <script>: 951:Received message: {"hello", "Kamailio"}
+>
+
+6. Event routes
+
+   6.1. Registered pseudo process
+   6.2. event_route[erlang:self]
+
+   To allow Kamailio C node to have similar to erlang registered processes
+   we can use event routes. Event routes executed when asynchronous
+   message received from erlang node.
+
+   Event route receives message in $erl_xbuff(msg) and sender process in
+   $erl_xbuff(pid). Reply message is optional and can be sent with
+   erl_reply.
+
+6.1. Registered pseudo process
+
+   To create pseudo erlang registered process in Kamailio scrip create
+   event route in form of event_route[erlang:<my_process_name>]. Where
+   <my_process_name> is the name of pseudo process.
+
+   Example 1.19. Example of registered process
+...
+# event route acts as registered process
+event_route[erlang:handler] {
+
+        xlogl("L_INFO","Received message: $erl_xbuff(msg=>format)\n");
+
+}
+...
+
+%% in erlang shell send message to registered process
+
+(node1 at erlang.lan)12> {handler,'proxy at kamailio.lan'} ! {"hello","Kamailio"}.
+{"hello","Kamailio"}
+
+> logged info message:
+INFO: <script>: 951:Received message: {"hello", "Kamailio"}
+>
+
+6.2. event_route[erlang:self]
+
+   The reserved pseudo process name to receive messages sent to Kamailio C
+   node. The message are sent to non registered process.
+
+   Example 1.20. Example of using default event route
+...
+# default event route from erlang
+event_route[erlang:self] {
+
+        xlogl("L_INFO","Received message: $erl_xbuff(msg=>format)\n");
+
+        if(pv_isset("$erl_xbuff(msg[1])") && $erl_xbuff(msg[1]=>type) == "pid")
+{
+                xlogl("L_INFO","Echo reply to: $erl_xbuff(msg[1]=>format)\n");
+                erl_send("$erl_xbuff(msg[1])","$erl_xbuff(msg[0])");
+        }
+}
+...
+
+%% in erlang shell send message to registered process
+
+(node1 at erlang.lan)12> Pid=rpc:call('proxy at kamailio.lan',erlang,whereis,[self]).
+<14808.9.0>
+(node1 at erlang.lan)14> Pid ! ["hello from",self()].
+["hello from",<0.247.0>]
+(node1 at erlang.lan)15> flush().
+Shell got "hello from"
+ok
+
+> logged info messages:
+INFO: <script>: 653:Received message: ["hello from", <node1 at erlang.lan.247.0>]
+INFO: <script>: 656:Echo reply to: <node1 at erlang.lan.247.0>]
+>
+
+Chapter 2. Using Kamailio from Erlang
+
+   Table of Contents
+
+   1. RPC calls from Erlang
+
+1. RPC calls from Erlang
+
+   This module implements the erlang transport and encoding interface for
+   Kamailio RPCs. It's allow to call any exported RPC in Kamailio from
+   erlang node.
+
+   The string in RPC response is binary encoded to allow from erlang side
+   conversion into appropriate encoding and further transformations.
+
+   Here are some examples:
+
+   Example 2.1. Example of RPC call from erlang shell with no response
+(node1 at erlang.lan)26> rpc:call('proxy at kamailio.lan',domain,reload,[]).
+ok
+
+   Example 2.2. Example, check is line registered
+(node1 at erlang.lan)29> rpc:call('proxy at kamailio.lan',ul,lookup,["location","1001@
+orange.voip"]).
+[{[{<<"Contact">>,
+    {[{<<"Address">>,
+       <<"sip:1001 at 10.1.130.138:5161;transport=udp">>},
+      {<<"Expires">>,96},
+      {<<"Q">>,-1.0},
+      {<<"Call-ID">>,<<"5c89766276627815 at 10.1.130.138">>},
+      {<<"CSeq">>,10335},
+      {<<"User-Agent">>,<<"Grandstream GXP2000 1.2.5.3">>},
+      {<<"Received">>,<<"sip:198.51.100.137:62770">>},
+      {<<"Path">>,
+       <<"<sip:172.16.23.130;lr;received=sip:198.51.100.137:62"...>>},
+      {<<"State">>,<<"CS_SYNC">>},
+      {<<"Flags">>,0},
+      {<<"CFlags">>,64},
+      {<<"Socket">>,<<"udp:172.16.23.130:5070">>},
+      {<<"Methods">>,8159},
+      {<<"Ruid">>,<<"uloc-5534a79b-37ea-8">>},
+      {<<"Instance">>,<<"[not set]">>},
+      {<<"Reg-Id">>,0},
+      {<<"Last-Keepalive">>,1429543986},
+      {<<"Last-Modified">>,1429543906}]}}]}]
+
+   Example 2.3. Example get config variable
+(node1 at erlang.lan)26> rpc:call('proxy at kamailio.lan',"cfg","get",["registrar","bi
+ndip"]).
+[<<"172.16.23.130">>]
+
+   Example 2.4. Example get dialog statistics
+(node1 at erlang.lan)26>rpc:call('proxy at kamailio.lan',"stats","get_statistics",["di
+alog:"]).
+[<<"dialog:active_dialogs = 3">>,
+ <<"dialog:early_dialogs = 0">>,
+ <<"dialog:expired_dialogs = 0">>,
+ <<"dialog:failed_dialogs = 2">>,
+ <<"dialog:processed_dialogs = 15">>]
+
+Chapter 3. Developer Guide
+
+   Table of Contents
+
+   1. Available Functions
+
+        1.1. erl_load_api(erl_api)
+        1.2. rpc(reply,module,function,args)
+        1.3. reg_send(server,msg)
+        1.4. send(pid,msg)
+        1.5. reply(msg)
+        1.6. xavp2xbuff(xbuff,xavp)
+        1.7. xbuff2xavp(xavp,xbuff)
+
+1. Available Functions
+
+   1.1. erl_load_api(erl_api)
+   1.2. rpc(reply,module,function,args)
+   1.3. reg_send(server,msg)
+   1.4. send(pid,msg)
+   1.5. reply(msg)
+   1.6. xavp2xbuff(xbuff,xavp)
+   1.7. xbuff2xavp(xavp,xbuff)
+
+1.1.  erl_load_api(erl_api)
+
+   Function to be called directly from other modules to load the API. On
+   success return 0, on error 1.
+
+   Meaning of the parameters is as follows:
+     * erl_api_t* erl_api - API bindings structure.
+
+1.2.  rpc(reply,module,function,args)
+
+   This function supports calling Erlang functions on remote nodes. On
+   success function returns 0.
+
+   Meaning of parameters is as follows:
+     * ei_x_buff* reply - dynamic ei buffer where RPC reply returns.
+     * str *module - string containing module name.
+     * str *function - string containing function name.
+     * ei_x_buff *args - dynamic ei buffer with encoded arguments.
+
+1.3.  reg_send(server,msg)
+
+   This function sends an Erlang term to a registered process. On success
+   return 0.
+
+   Meaning of parameters is as follows:
+     * str *server - string containing registered name of the intended
+       recipient process on remote node.
+     * ei_x_buff *msg - dynamic ei buffer with encoded erlang term. The
+       msg must be encoded with version byte.
+
+1.4.  send(pid,msg)
+
+   This function sends an Erlang term to a process. On success return 0.
+
+   Meaning of parameters is as follows:
+     * erlang_pid *pid - pid of the intended recipient process on remote
+       node.
+     * ei_x_buff *msg - dynamic ei buffer with encoded erlang term. The
+       msg must be encoded with version byte.
+
+1.5.  reply(msg)
+
+   Function to send reply on processed message.
+
+   Meaning of parameters is as follows:
+     * ei_x_buff *msg - dynamic ei buffer with encoded erlang term.
+
+1.6.  xavp2xbuff(xbuff,xavp)
+
+   Function encodes XAVP variable into ei dynamic buffer. How to create
+   XAVP variable see source code.
+
+   Meaning of parameters is as follows:
+     * ei_x_buff *xbuff - dynamic ei buffer where XAVP variable will be
+       encoded.
+     * sr_xavp_t *xavp - XAVP variable to be encoded.
+
+1.7.  xbuff2xavp(xavp,xbuff)
+
+   Function decodes ei dynamic buffer into XAVP variable.
+
+   Meaning of parameters is as follows:
+     * sr_xavp_t **xavp - XAVP variable where ei buffer will be decoded.
+     * ei_x_buff *xbuff - dynamic ei buffer.
+
+   Example 3.1. Example of using API
+/* note: new without version byte */
+ei_x_new(&ei_req);
+
+/* ei_x_buff <- XAVP */
+if (erl_api.xavp2xbuff(&ei_req,xreq)) {
+        LM_ERR("failed to encode\n");
+        ei_x_free(&ei_req);
+        return -1;
+}
+
+memset((void*)&ei_rep,0,sizeof(ei_x_buff));
+
+erl_api.rpc(&ei_rep,&module,&function,&ei_req);
+...
+
+/* must be XAVP */
+xrepl->val.type = SR_XTYPE_XAVP;
+
+/* XAVP <- ei_x_buff */
+if (erl_api.xbuff2xavp(&xrepl->val.v.xavp,&ei_rep)){
+        LM_ERR("failed to decode\n");
+        ei_x_free(&ei_req);
+        ei_x_free(&ei_rep);
+        return -1;
+}
diff --git a/modules/erlang/cnode.c b/modules/erlang/cnode.c
new file mode 100644
index 0000000..f0f6e03
--- /dev/null
+++ b/modules/erlang/cnode.c
@@ -0,0 +1,585 @@
+/**
+ * Copyright (C) 2015 Bicom Systems Ltd, (bicomsystems.com)
+ *
+ * Author: Seudin Kasumovic (seudin.kasumovic at gmail.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "../../mem/mem.h"
+#define HANDLE_IO_INLINE
+#include "../../io_wait.h"
+#include "../../pt.h"  /* process_count */
+
+#ifndef USE_TCP
+#error	"USE_TCP must be enabled for this module"
+#endif
+
+#include "../../pass_fd.h"
+
+#include "mod_erlang.h"
+#include "erl_helpers.h"
+#include "cnode.h"
+#include "epmd.h"
+#include "worker.h"
+#include "handle_emsg.h"
+
+#define IO_LISTEN_TIMEOUT	10
+#define CONNECT_TIMEOUT	500 /* ms */
+
+static io_wait_h io_h;
+
+cnode_handler_t *enode = NULL;
+csockfd_handler_t *csocket_handler = NULL;
+erlang_pid *cnode_reply_to_pid = NULL;
+
+/**
+ * @brief Initialize Kamailo as C node by active connect as client.
+ */
+int cnode_connect_to(cnode_handler_t *phandler, ei_cnode *ec, const str *nodename )
+{
+	struct sockaddr addr = { 0 };
+	socklen_t addrlen = sizeof(struct sockaddr);
+	int port;
+
+	int rfd;
+	int ai_error;
+	ip_addr_t ip;
+
+	phandler->request.buff = NULL;
+	phandler->response.buff = NULL;
+	phandler->sockfd = -1;
+	phandler->destroy_f = NULL;
+
+	LM_DBG("connecting to Erlang node %.*s ...\n", STR_FMT(nodename));
+
+	if ((rfd = ei_connect_tmo(ec, nodename->s, CONNECT_TIMEOUT)) < 0)
+	{
+		switch (erl_errno)
+		{
+		case EHOSTUNREACH:
+			LM_ERR("remote node %.*s is unreachable.\n", STR_FMT(nodename));
+			break;
+		case ENOMEM:
+			LM_ERR("%s.\n", strerror(erl_errno));
+			break;
+		case EIO:
+			LM_ERR("%s. %s.\n", strerror(erl_errno), strerror(errno));
+			break;
+		default:
+			LM_ERR("%s.\n",strerror(erl_errno));
+			break;
+		}
+		LM_ERR("failed erl_errno=%d %s.\n",erl_errno,strerror(erl_errno));
+		return -1;
+	}
+
+	phandler->ec = *ec;
+	phandler->handle_f = handle_cnode;
+	phandler->wait_tmo_f = wait_cnode_tmo;
+	phandler->destroy_f = destroy_cnode;
+
+	erl_set_nonblock(rfd);
+
+	phandler->sockfd = rfd;
+
+	/* get addr on socket */
+	if ((ai_error = getpeername(rfd, &addr, &addrlen)))
+	{
+		LM_ERR("%s\n",strerror(errno));
+	}
+	else
+	{
+		sockaddr2ip_addr(&ip,&addr);
+		port = sockaddr_port(&addr);
+
+		LM_DBG("... connected to %.*s %s:%u\n", STR_FMT(nodename), ip_addr2strz(&ip), port);
+	}
+
+	strcpy(phandler->conn.nodename, nodename->s);
+
+	/* for #Pid */
+	phandler->ec.self.num = phandler->sockfd;
+	phandler->new = NULL;
+
+	if (ei_x_new(&phandler->request))
+	{
+		LOG(L_ERR,"failed to allocate ei_x_buff: %s.\n", strerror(erl_errno));
+		return -1;
+	}
+
+	if (ei_x_new_with_version(&phandler->response))
+	{
+		LOG(L_ERR,"failed to allocate ei_x_buff: %s.\n", strerror(erl_errno));
+		return -1;
+	}
+
+	enode = phandler;
+	return 0;
+}
+
+int destroy_cnode(handler_common_t *phandler_t)
+{
+	cnode_handler_t *phandler = (cnode_handler_t*)phandler_t;
+
+	if(phandler->request.buff) ei_x_free(&phandler->request);
+	if(phandler->response.buff) ei_x_free(&phandler->response);
+
+	erl_close_socket(phandler->sockfd);
+
+	return 0;
+}
+
+int init_cnode_sockets(int cnode_id)
+{
+	char buff[EI_MAXALIVELEN+1];
+	str alivename;
+	ei_cnode ec;
+	int poll_method;
+	handler_common_t *phandler;
+
+	/* generate cnode name */
+	alivename.s = buff;
+	if (no_cnodes > 1) {
+		alivename.len = snprintf(buff,EI_MAXALIVELEN,"%.*s%d",STR_FMT(&cnode_alivename),cnode_id);
+	} else {
+		alivename = cnode_alivename;
+	}
+
+	if (alivename.len > EI_MAXALIVELEN) {
+		LM_ERR("alive name %.*s too long max allowed size is %d\n",STR_FMT(&cnode_alivename), EI_MAXALIVELEN);
+		return -1;
+	}
+
+	/* init Erlang connection */
+	if (erl_init_ec(&ec,&alivename,&cnode_host,&cookie)) {
+		LM_CRIT("failed to initialize ei_cnode\n");
+		return -1;
+	}
+
+	poll_method=choose_poll_method();
+
+	LM_DBG("using %s as the I/O watch method (auto detected)\n", poll_method_name(poll_method));
+
+	if (init_io_wait(&io_h,get_max_open_fds(),poll_method))
+	{
+		LM_CRIT("init_io_wait failed\n");
+		return -1;
+	}
+
+	phandler = (handler_common_t*)pkg_malloc(sizeof(csockfd_handler_t));
+	if (!phandler) {
+		LM_ERR("not enough memory\n");
+		return -1;
+	}
+
+	io_handler_ins(phandler);
+
+	if (csockfd_init((csockfd_handler_t*)phandler, &ec)) {
+		return -1;
+	}
+
+	if (io_watch_add(&io_h,phandler->sockfd,POLLIN,ERL_CSOCKFD_H,phandler)) {
+		LM_CRIT("io_watch_add failed\n");
+		return -1;
+	}
+
+	phandler = (handler_common_t*)pkg_malloc(sizeof(cnode_handler_t));
+	if (!phandler) {
+		LM_CRIT("not enough memory\n");
+		return -1;
+	}
+
+	io_handler_ins(phandler);
+
+	/* connect to remote Erlang node */
+	if (cnode_connect_to((cnode_handler_t*)phandler,&ec, erlang_nodename.s?&erlang_nodename:&erlang_node_sname)) {
+		/* continue even failed to connect, connection can be established
+		 * from Erlang side too */
+		io_handler_del(phandler);
+	} else if (io_watch_add(&io_h,phandler->sockfd,POLLIN,ERL_CNODE_H,phandler)){
+		LM_CRIT("io_watch_add failed\n");
+		return -1;
+	}
+
+	phandler = (handler_common_t*)pkg_malloc(sizeof(epmd_handler_t));
+	if (!phandler) {
+		LM_CRIT("not enough memory\n");
+		return -1;
+	}
+
+	io_handler_ins(phandler);
+
+	/* start epmd handler - publish Kamailo C node */
+	if (epmd_init((epmd_handler_t*)phandler) < 0 ) {
+		return -1;
+	}
+
+	if (io_watch_add(&io_h,phandler->sockfd,POLLIN,ERL_EPMD_H,phandler)){
+		LM_CRIT("io_watch_add failed\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+void cnode_main_loop(int cnode_id)
+{
+	char _cnode_name[MAXNODELEN];
+	str *enode_name;
+	int r;
+
+	if (snprintf(_cnode_name, MAXNODELEN, "%.*s%d@%.*s", STR_FMT(&cnode_alivename), cnode_id+1,STR_FMT(&cnode_host)) >= MAXNODELEN)
+	{
+		LM_CRIT("the node name <%.*s%d@%.*s> is too large max length allowed is %d\n",
+				STR_FMT(&cnode_alivename), cnode_id+1, STR_FMT(&cnode_host), MAXNODELEN-1);
+		return;
+	}
+
+	erl_init_common();
+
+	if (init_cnode_sockets(cnode_id)) {
+		io_handlers_delete();
+		erl_free_common();
+		return;
+	}
+
+	enode_name = erlang_nodename.s?&erlang_nodename:&erlang_node_sname;
+
+	/* main loop */
+	switch(io_h.poll_method){
+		case POLL_POLL:
+			while(1){
+				r = io_wait_loop_poll(&io_h, IO_LISTEN_TIMEOUT, 0);
+				if(!r && enode_connect()) {
+					LM_ERR("failed reconnect to %.*s\n",STR_FMT(enode_name));
+				}
+			}
+			break;
+#ifdef HAVE_SELECT
+		case POLL_SELECT:
+			while(1){
+				r = io_wait_loop_select(&io_h, IO_LISTEN_TIMEOUT, 0);
+				if(!r && enode_connect()) {
+					LM_ERR("failed reconnect to %.*s\n",STR_FMT(enode_name));
+				}
+			}
+			break;
+#endif
+#ifdef HAVE_SIGIO_RT
+		case POLL_SIGIO_RT:
+			while(1){
+				r = io_wait_loop_sigio_rt(&io_h, IO_LISTEN_TIMEOUT);
+				if(!r && enode_connect()) {
+					LM_ERR("failed reconnect to %.*s\n",STR_FMT(enode_name));
+				}
+			}
+			break;
+#endif
+#ifdef HAVE_EPOLL
+			case POLL_EPOLL_LT:
+				while(1){
+					r = io_wait_loop_epoll(&io_h, IO_LISTEN_TIMEOUT, 0);
+					if(!r && enode_connect()) {
+						LM_ERR("failed reconnect to %.*s\n",STR_FMT(enode_name));
+					}
+				}
+				break;
+			case POLL_EPOLL_ET:
+				while(1){
+					r = io_wait_loop_epoll(&io_h, IO_LISTEN_TIMEOUT, 1);
+					if(!r && enode_connect()) {
+						LM_ERR("failed reconnect to %.*s\n",STR_FMT(enode_name));
+					}
+				}
+				break;
+#endif
+#ifdef HAVE_KQUEUE
+			case POLL_KQUEUE:
+				while(1){
+					r = io_wait_loop_kqueue(&io_h, IO_LISTEN_TIMEOUT, 0);
+					if(!r && enode_connect()) {
+						LM_ERR("failed reconnect to %.*s\n",STR_FMT(enode_name));
+					}
+				}
+				break;
+#endif
+#ifdef HAVE_DEVPOLL
+                case POLL_DEVPOLL:
+                	while(1){
+						r = io_wait_loop_devpoll(&io_h, IO_LISTEN_TIMEOUT, 0);
+						if(!r && enode_connect()) {
+							LM_ERR("failed reconnect to %.*s\n",STR_FMT(enode_name));
+						}
+                	}
+                	break;
+#endif
+                default:
+                	LM_CRIT("BUG: io_listen_loop: no support for poll method "
+                			" %s (%d)\n", poll_method_name(io_h.poll_method),
+							io_h.poll_method);
+                	goto error;
+        }
+
+error:
+	LOG(L_CRIT, "ERROR: cnode_main_loop exiting ...\n");
+}
+
+/* generic handle io routine, it will call the appropriate
+ *  handle_xxx() based on the fd_map type
+ *
+ * params:  fm  - pointer to a fd hash entry
+ *          idx - index in the fd_array (or -1 if not known)
+ * return: -1 on error
+ *          0 on EAGAIN or when by some other way it is known that no more
+ *            io events are queued on the fd (the receive buffer is empty).
+ *            Usefull to detect when there are no more io events queued for
+ *            sigio_rt, epoll_et, kqueue.
+ *         >0 on successfully read from the fd (when there might be more io
+ *            queued -- the receive buffer might still be non-empty)
+ */
+int handle_io(struct fd_map* fm, short events, int idx)
+{
+	int type;
+	handler_common_t *phandler;
+
+	phandler = (handler_common_t*)fm->data;
+
+	if (phandler->handle_f(phandler)) {
+		io_watch_del(&io_h,fm->fd,idx,IO_FD_CLOSING);
+		io_handler_del(phandler);
+		if (fm->type == ERL_WORKER_H) {
+			LM_CRIT("error on unix socket, not recoverable error -- aborting\n");
+			abort();
+		}
+		return -1;
+	}
+
+	if (phandler->new) {
+		switch (fm->type) {
+		case ERL_CSOCKFD_H:
+			type = ERL_WORKER_H;
+			break;
+		case ERL_EPMD_H:
+			type = ERL_CNODE_H;
+			break;
+		default:
+			LM_ERR("should not be here!\n");
+			return -1;
+		}
+		LM_DBG("add new handler type=%d\n",type);
+		if (io_watch_add(&io_h,phandler->new->sockfd,POLLIN,type,(void*)phandler->new)) {
+			LM_ERR("failed to add new handler\n");
+			return -1;
+		}
+		io_handler_ins(phandler->new);
+		phandler->new = NULL;
+	}
+
+	return 1;
+}
+
+/**
+ * @brief Handle requests from remote Erlang node.
+ */
+int handle_cnode(handler_common_t *phandler)
+{
+	int got;
+	cnode_handler_t *listener;
+	erlang_msg emsg; /* Incoming message */
+	ei_x_buff *request;
+	ei_x_buff *response;
+	int response_start_index;
+
+	listener = (cnode_handler_t*) phandler;
+	request = &listener->request;
+	response = &listener->response;
+
+	response_start_index = response->index; /* save */
+	request->index = 0;
+
+	listener->tick_tmo = 0; /* reset ERL_TICK timer for all events */
+
+	memset((void*)&emsg,0,sizeof(erlang_msg));
+
+	if ((got = ei_xreceive_msg_tmo(listener->sockfd, &emsg, request,
+			CONNECT_TIMEOUT)) == ERL_TICK)
+	{ /* ignore */
+		LM_DBG("%s received ERL_TICK from <%s>.\n", listener->ec.thisnodename, listener->conn.nodename);
+		return 0;
+	}
+	else if (got == ERL_ERROR)
+	{
+		switch (erl_errno)
+		{
+		case EAGAIN:
+			/* or */
+		case ETIMEDOUT:
+			response->index = response_start_index; /* restore version point */
+			return 0;
+			break;
+		case EIO:
+			LM_ERR("I/O error while receiving message from %s or connection closed.\n", listener->conn.nodename);
+			enode = NULL;
+			return -1;
+			break;
+		case ENOMEM:
+			LM_ERR("Failed to receive message from %s, not enough memory. Closing connection.\n", listener->conn.nodename);
+			enode = NULL;
+			return -1;
+			break;
+		default:
+			LM_ERR("Close connection to %s. %s.\n", listener->conn.nodename, strerror(erl_errno));
+			enode = NULL;
+			return -1;
+		}
+	}
+	else if (got == ERL_MSG)
+	{
+		response->index = response_start_index; /* restore version point */
+		switch (emsg.msgtype)
+		{
+		case ERL_LINK:
+			LM_WARN("ERL_LINK from <%s> -- discarding.\n", listener->conn.nodename);
+			break;
+		case ERL_REG_SEND:
+			PRINT_DBG_REG_SEND(listener->conn.nodename,emsg.from, listener->ec.thisnodename, emsg.toname,request);
+			handle_erlang_msg(listener, &emsg);
+			break;
+		case ERL_SEND:
+			PRINT_DBG_SEND(listener->conn.nodename,emsg.to,request);
+			handle_erlang_msg(listener, &emsg);
+			break;
+		case ERL_EXIT:
+			LM_WARN("received ERL_EXIT from <%s> -- discarding.\n", listener->conn.nodename);
+			break;
+		case ERL_UNLINK:
+			LM_WARN("ERL_UNLINK from <%s> -- discarding.\n", listener->conn.nodename);
+			break;
+		case ERL_NODE_LINK:
+			LM_WARN("ERL_NODE_LINK from <%s> -- discarding.\n", listener->conn.nodename);
+			break;
+		case ERL_GROUP_LEADER:
+			LM_WARN("ERL_GROUP_LEADER from <%s> -- discarding.\n", listener->conn.nodename);
+			break;
+		case ERL_EXIT2:
+			LM_WARN("ERL_EXIT2 from <%s> -- discarding.\n", listener->conn.nodename);
+			break;
+		case ERL_PASS_THROUGH:
+			LM_WARN("ERL_PASS_THROUGH from <%s> -- discarding.\n", listener->conn.nodename);
+			break;
+		default:
+			LM_WARN("Received unknown msgtype <%ld> from <%s> -- discarding.\n", emsg.msgtype, listener->conn.nodename);
+			break;
+		}
+	}
+	else
+	{
+		LM_ERR("unknown return value from ei_xreceive_msg_tmo.\n");
+	}
+
+	response->index = response_start_index; /* restore to version point */
+
+	return  0;
+}
+
+int wait_cnode_tmo(handler_common_t *phandler_t)
+{
+	return 0;
+}
+
+int csockfd_init(csockfd_handler_t *phandler, const ei_cnode *ec)
+{
+	phandler->handle_f = handle_csockfd;
+	phandler->wait_tmo_f = NULL;
+	phandler->sockfd = csockfd;
+	phandler->ec = *ec;
+	phandler->new = NULL;
+
+	erl_set_nonblock(csockfd);
+
+	csocket_handler = phandler;
+
+	csockfd = 0;
+	return 0;
+}
+
+int handle_csockfd(handler_common_t *phandler_t)
+{
+	csockfd_handler_t *phandler;
+	int data[2];
+	int fd = -1;
+
+	phandler = (csockfd_handler_t*)phandler_t;
+
+	if (receive_fd(phandler->sockfd,(void*)data,sizeof(data),&fd,0) == -1) {
+		LM_ERR("failed to receive socket: %s\n",strerror(errno));
+		return -1;
+	}
+
+	phandler->new = (handler_common_t*)pkg_malloc(sizeof(worker_handler_t));
+	if(!phandler->new) {
+		LM_ERR("not enough memory\n");
+		return -1;
+	}
+
+	io_handler_ins(phandler->new);
+
+	return worker_init((worker_handler_t*)phandler->new,fd,&phandler_t->ec);
+}
+
+/*
+ * \brief Connect to Erlang node if not connected
+ */
+int enode_connect() {
+
+	handler_common_t *phandler;
+
+	if (!csocket_handler) {
+		return -1;
+	}
+
+	if (enode) {
+		return 0;
+	}
+
+	LM_DBG("not connected, trying to connect...\n");
+
+	phandler = (handler_common_t*)pkg_malloc(sizeof(cnode_handler_t));
+
+	if (!phandler) {
+		LM_CRIT("not enough memory\n");
+		return -1;
+	}
+
+	io_handler_ins(phandler);
+
+	/* connect to remote Erlang node */
+	if (cnode_connect_to((cnode_handler_t*)phandler,&csocket_handler->ec, erlang_nodename.s?&erlang_nodename:&erlang_node_sname)) {
+		/* continue even failed to connect, connection can be established
+		 * from Erlang side too */
+		io_handler_del(phandler);
+	} else if (io_watch_add(&io_h,phandler->sockfd,POLLIN,ERL_CNODE_H,phandler)){
+		LM_CRIT("io_watch_add failed\n");
+		erl_close_socket(phandler->sockfd);
+		io_handler_del(phandler);
+		return -1;
+	}
+
+	return 0;
+}
diff --git a/modules/erlang/cnode.h b/modules/erlang/cnode.h
new file mode 100644
index 0000000..32d8333
--- /dev/null
+++ b/modules/erlang/cnode.h
@@ -0,0 +1,112 @@
+/**
+ * Copyright (C) 2015 Bicom Systems Ltd, (bicomsystems.com)
+ *
+ * Author: Seudin Kasumovic (seudin.kasumovic at gmail.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef CNODE_H_
+#define CNODE_H_
+
+#include <ei.h>
+
+/**
+ * Listener for handling requests from connected nodes.
+ */
+typedef struct cnode_handler_s
+{
+	/* d-linked list  */
+	struct handler_common_s *prev;
+	struct handler_common_s *next;
+
+	/* if need to add new in i/o handler */
+	struct handler_common_s *new;
+
+	/*
+	 * this handler is erlang C node server
+	 * handles requests from remote erlang node
+	 */
+	int (*handle_f)(handler_common_t *phandler_t);
+	int (*wait_tmo_f)(handler_common_t *phandler_t);
+	int (*destroy_f)(handler_common_t *phandler_t);
+	int sockfd; /* connection socket to remote erlang node */
+	ei_cnode ec; /* erlang C node (actually it's kamailio node) */
+
+	/*
+	 * connection descriptor
+	 * remote node info
+	 */
+	ErlConnect conn;
+
+	/* request/response buffers */
+	ei_x_buff request;
+	ei_x_buff response;
+
+	/*
+	 * ERL_TICK time out
+	 */
+	int tick_tmo;
+} cnode_handler_t;
+
+/*
+ * active connection to Erlang node
+ */
+extern cnode_handler_t *enode;
+
+/* where to reply - reset to NULL after use */
+extern erlang_pid *cnode_reply_to_pid;
+
+typedef struct csockfd_handler_s
+{
+	/* d-linked list  */
+	struct handler_common_s *prev;
+	struct handler_common_s *next;
+	struct handler_common_s *new;
+
+	/* handle receive fd over csockfd */
+	int (*handle_f)(handler_common_t *phandler_t);
+	int (*wait_tmo_f)(handler_common_t *phandler_t);
+	int (*destroy_f)(handler_common_t *phandler_t);
+	int sockfd; /* its csockfd */
+	ei_cnode ec; /* erlang C node (actually it's kamailio node) */
+} csockfd_handler_t;
+
+extern csockfd_handler_t *csocket_handler;
+
+int init_cnode_sockets(int idx);
+void cnode_main_loop(int idx);
+
+int handle_csockfd(handler_common_t *phandler_t);
+int csockfd_init(csockfd_handler_t *phandler_t, const ei_cnode *ei);
+
+int handle_cnode(handler_common_t *phandler_t);
+int wait_cnode_tmo(handler_common_t *phandler_t);
+int destroy_cnode(handler_common_t *phandler_t);
+
+int cnode_connect_to(cnode_handler_t *phandler, ei_cnode *ec, const str *nodename );
+int enode_connect();
+
+enum erl_handle_type {
+	ERL_EPMD_H = 1,
+	ERL_CNODE_H,
+	ERL_WORKER_H,
+	ERL_CSOCKFD_H
+};
+
+#endif /* CNODE_H_ */
diff --git a/modules/erlang/doc/Makefile b/modules/erlang/doc/Makefile
new file mode 100644
index 0000000..78384b0
--- /dev/null
+++ b/modules/erlang/doc/Makefile
@@ -0,0 +1,4 @@
+docs = erlang.xml
+
+docbook_dir = ../../../docbook
+include $(docbook_dir)/Makefile.module
diff --git a/modules/erlang/doc/erlang.xml b/modules/erlang/doc/erlang.xml
new file mode 100644
index 0000000..59c2127
--- /dev/null
+++ b/modules/erlang/doc/erlang.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding='ISO-8859-1'?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+<!-- Include general documentation entities -->
+<!ENTITY % docentities SYSTEM "../../../docbook/entities.xml">
+%docentities;
+
+]>
+
+<book xmlns:xi="http://www.w3.org/2001/XInclude">
+	<bookinfo>
+		<title>ERLANG Module</title>
+		<productname class="trade">sip-router.org</productname>
+		<authorgroup>
+			<author>
+				<firstname>Seudin</firstname>
+				<surname>Kasumovic</surname>
+				<email>seudin.kasumovic at gmail.com</email>
+			</author>
+			<editor>
+				<firstname>Seudin</firstname>
+				<surname>Kasumovic</surname>
+				<email>seudin.kasumovic at gmail.com</email>
+	    	</editor>
+		</authorgroup>
+		<copyright>
+			<year>2015</year>
+			<holder><ulink url="http://www.bicomsystems.com">Bicom Systems Ltd.</ulink></holder>
+		</copyright>
+	</bookinfo>
+	<toc></toc>
+    
+    <xi:include href="erlang_admin.xml"/>
+    <xi:include href="erlang_use.xml"/>
+    <xi:include href="erlang_devel.xml"/>
+    
+</book>
diff --git a/modules/erlang/doc/erlang_admin.xml b/modules/erlang/doc/erlang_admin.xml
new file mode 100644
index 0000000..4341f55
--- /dev/null
+++ b/modules/erlang/doc/erlang_admin.xml
@@ -0,0 +1,700 @@
+<?xml version="1.0" encoding='ISO-8859-1'?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+<!-- Include general documentation entities -->
+<!ENTITY % docentities SYSTEM "../../../docbook/entities.xml">
+%docentities;
+
+]>
+<!-- Module User's Guide -->
+
+<chapter>
+	
+	<title>&adminguide;</title>
+	
+	<section>
+		<title>Overview</title>
+		<para>
+			Erlang is a general-purpose programming language and runtime environment.
+			Erlang has built-in support for concurrency, distribution and fault tolerance.
+			This module provides interact with Erlang node. The module allows sending,
+			receiving Erlang messages and RPC calls between each other.
+		</para>
+	</section>
+
+	<section>
+		<title>Dependencies</title>
+		<section>
+			<title>&kamailio; Modules</title>
+			<para>
+				The following modules must be loaded before this module:
+				<itemizedlist mark="none">
+					<listitem>
+						<para>
+							<emphasis>None</emphasis>
+						</para>
+					</listitem>
+				</itemizedlist>
+			</para>
+		</section>
+		<section>
+			<title>External Libraries or Applications</title>
+			<para>
+			The following libraries or applications must be installed before running
+			&kamailio; with this module loaded:
+			<itemizedlist mark="none">
+			<listitem>
+				<para>
+					<emphasis>ei</emphasis> - Erlang interface C library.
+					<para>
+						The routines for handling the Erlang binary term format
+						and communicate with with distributed Erlang.
+						For more details see <ulink url="http://www.erlang.org/doc/apps/erl_interface/index.html">Erlang Interface Reference Manual</ulink>
+					</para>
+				</para>
+			</listitem>
+			<listitem>
+				<para>
+					<emphasis>epmd</emphasis> - Erlang Port Mapper Daemon.
+					<para>
+						This daemon acts as a name server on all hosts involved in distributed
+						Erlang computations. For more details see <ulink url="http://www.erlang.org/doc/man/epmd.html">
+						Erlang Port Mapper Daemon Manual</ulink>.
+					</para>
+				</para>
+			</listitem>
+			</itemizedlist>
+			</para>
+			<para>
+				<emphasis>epmd</emphasis> must running on the same host where &kamailio; is running.
+				Erlang does not need to be installed on the same host where &kamailio; is running.
+			</para>
+		</section>
+	</section>
+	<section>
+		<title>Parameters</title>
+		<section id="erlang.p.no_cnodes">
+			<title><varname>no_cnodes</varname> (int)</title>
+			<para>
+				Number of erlang C node processes to be started to handle the communication
+				tasks. A C node is a C program written to act as a hidden node in a distributed Erlang system.
+			</para>
+			<para>
+			<emphasis>
+				Default value is 1.
+			</emphasis>
+			</para>
+			<example>
+				<title>Set <varname>no_cnodes</varname> parameter</title>
+				<programlisting format="linespecific">
+...
+modparam("erlang", "no_cnodes", 2)	
+...
+				</programlisting>
+			</example>
+		</section>
+		<section id="erlang.p.cnode_alivename">
+			<title><varname>cnode_alivename</varname> (str)</title>
+			<para>
+				<emphasis>alivename</emphasis> is the registered name of the &kamailio; process.
+			</para>
+			<para>
+				<emphasis>Note,</emphasis> if the <varname>no_cnodes</varname> greater then 1,
+				then <emphasis>alivename</emphasis> of &kamailio; process will be suffixed with number.
+			</para>
+			<example>
+				<title>Set <varname>cnode_alivename</varname> parameter</title>
+				<programlisting format="linespecific">
+...
+modparam("erlang", "cnode_alivename", "proxy")
+...
+				</programlisting>
+			</example>
+		</section>
+		<section id="erlang.p.cnode_host">
+			<title><varname>cnode_host</varname> (str)</title>
+			<para>
+				C node <emphasis>host</emphasis> is the name of the machine we're running on.
+				If long names are to be used, it should be fully qualified.
+			</para>
+			<example>
+				<title>Set <varname>cnode_host</varname> parameter</title>
+				<programlisting format="linespecific">
+...
+modparam("erlang", "cnode_host", "kamailio.lan")
+...
+				</programlisting>
+			</example>
+		</section>
+		<section id="erlang.p.erlang_nodename">
+			<title><varname>erlang_nodename</varname> (str)</title>
+			<para>
+				The format of the node name is an <emphasis>name at host</emphasis>
+				where name is the name given by the user and host is the full
+				host name if long names are used, or the first part of the host
+				name if short names are used.
+			</para>
+			<example>
+				<title>Set <varname>erlang_nodename</varname> parameter</title>
+				<programlisting format="linespecific">
+...
+modparam("erlang", "erlang_nodename", "node1 at erlang.lan")
+...
+				</programlisting>
+			</example>
+		</section>
+		<section id="erlang.p.cookie">
+			<title><varname>cookie</varname> (str)</title>
+			<para>
+				Each node has its own magic cookie. When a nodes tries to connect
+				to another node, the magic cookies are compared If they do not match,
+				the connected node rejects the connection.
+			</para>
+			<example>
+				<title>Set <varname>cookie</varname> parameter</title>
+				<programlisting format="linespecific">
+...
+modparam("erlang", "cookie", "secretcookie")
+...
+				</programlisting>
+			</example>
+		</section>
+		<section id="erlang.p.trace_level">
+			<title><varname>trace_level</varname> (int)</title>
+			<para>
+				Used to set tracing on the distribution. The parameter is different
+				verbosity level. A higher level means more information. Useful in
+				development, but in production should be disabled.
+			</para>
+			<para>
+				The different tracelevels has the following messages:
+				<itemizedlist>
+					<orderedlist>
+						<listitem>
+							Verbose error messages
+						</listitem>
+						<listitem>
+							Above messages and verbose warning messages
+						</listitem>
+						<listitem>
+							Above messages and progress reports for connection handling
+						</listitem>
+						<listitem>
+							Above messages and progress reports for communication
+						</listitem>
+						<listitem>
+							Above messages and progress reports for data conversion
+						</listitem>
+					</orderedlist>
+				</itemizedlist>
+			</para>
+			<emphasis>
+				Default value is 0, no verbose is set.
+			</emphasis>
+			<emphasis>
+				To see trace log on stdout, &kamailio; must be started with <emphasis>-E</emphasis> option.
+			</emphasis>
+			<example>
+				<title>Set <varname>trace_level</varname> parameter</title>
+				<programlisting format="linespecific">
+...
+modparam("erlang", "trace_level", 5)
+...
+				</programlisting>
+			</example>
+		</section>
+		<section>
+			<title><varname>rpc_reply_with_struct</varname> (int)</title>
+			<para>
+				Prepend Erlang atom struct in RPC &kamailio; reply where RPC struct is generated.
+				Some libraries for converting erlang term in JSON require atom struct
+				as first element in tuple to convert list of properties into javscript object.
+			</para>
+			<emphasis>
+				Default value is 0 (disabled).
+			</emphasis>
+		</section>
+	</section>
+	<section>
+		<title>Exported pseudo variables</title>
+		<section>
+			<title>Overview</title>
+			<para>
+				Erlang provides a number of data types but not all of them are supported by &kamailio;.
+				This module provides several of them as pseudo variables. These pseudo variables
+				allow user to create Erlang message or function arguments and receive result from
+				Erlang node. Some Erlang variables can contain other data types, so we introduced several
+				attributes to determine type, length, or get formatted output useful for debug,
+				quick compare or put into the log.
+			</para>
+		</section>
+		<section>
+			<title>Attributes</title>
+			<para>
+				Exported pseudo variable has several attributes to get type, length and formatted output
+				readable by transformations or user. Pseudo variable by self determine variable type, but
+				we need to know what type on some position is. 
+			</para>
+			<itemizedlist>
+				<listitem>
+					<varname>type</varname>
+					<para>
+						get variable type. Possible types are: <emphasis>atom, integer,
+						list, string</emphasis>, <emphasis>tuple</emphasis>,
+						<emphasis>pid</emphasis> and <emphasis>ref</emphasis>.
+					</para>
+				</listitem>
+				<listitem>
+					<varname>length</varname>
+					<para>
+						get length of list or tuple.
+					</para>
+				</listitem>
+				<listitem>
+					<varname>format</varname>
+					<para>
+						Prints a term, in clear text. It tries to resemble the
+						term printing in the Erlang shell.
+					</para>
+				</listitem>
+			</itemizedlist>
+			<example>
+				<title>Example of using attribute <emphasis>length</emphasis></title>
+				<programlisting format="linespecific">
+...
+xlogl("L_DEBUG","The number of elements in list L: $erl_list(L=>length)\n");
+xlogl("L_DEBUG","The number of elements in tuple T: $erl_tuple(T=>length)\n");
+...
+
+> example of log output:
+
+DEBUG: <script>: 120:The number of elements in list L: 4
+DEBUG: <script>: 121:The number of elements in tuple T: 2
+...
+				</programlisting>
+			</example>
+			<example>
+				<title>Example of using attributes <emphasis>type</emphasis> and <emphasis>format</emphasis></title>
+				<programlisting format="linespecific">
+...
+xlogl("L_DEBUG","list L in clear text: $erl_list(L=>format), the type at index 2: $erl_list(L[2]=>type)\n");
+xlogl("L_DEBUG","tuple T in clear text: $erltuple(T=>format), the type at index 1: $erl_tuple[T[1]=>type)\n");
+...
+
+> example of log output:
+
+DEBUG: <script>: 130:list L in clear text: [example, list, 4, "items"], the type at index 2: integer
+DEBUG: <script>: 131:tuple T in clear text: {example, tuple}, the type at index 1: atom
+...
+				</programlisting>
+			</example>
+		</section>
+		<section id="erlang.v.erl_atom">
+			<title><varname>$erl_atom(name)</varname></title>
+			<para>
+				<emphasis>erl_atom</emphasis> pseudo variable allows create analog to Erlang atom data type.
+				Erlang atom is a literal, a constant with name. Formatted output pseudo
+				variable atom could be enclosed in single quotes (') if it does 
+				not begin with a lower-case letter or if it contains other characters
+				than alphanumeric characters, underscore (_), or @.
+			</para>
+			<para>
+
+			</para>
+			<example>
+				<title>Example set and print to log $erl_atom</title>
+				<programlisting format="linespecific">
+...
+$erl_atom(A) = "badrpc";
+xlogl("L_DEBUG","$$erl_atom(A): $erl_atom(A=>format)\n");
+...
+
+> log output is:
+
+DEBUG: <script>: 123:$erl_atom(A): badrpc
+...
+				</programlisting>
+			</example>
+		</section>
+		<section id="erlang.v.erl_list">
+			<title><varname>$erl_list(name)</varname></title>
+			<para>
+				Compound data type with a variable number of terms. Formally,
+				a list is either the empty list [] or consists of one or more 
+				elements.
+			</para>
+			<para>
+				Behavior of the list is the same as AVP variable. Set value without
+				index prepends element on list. You are able to replace element at
+				given index. List supports [*] index to get whole list or reset all
+				elements in the list. To create empty list set whole list to
+				<emphasis>$null</emphasis>.
+			</para>
+			<example>
+				<title>Example of using $erl_list</title>
+				<programlisting format="linespecific">
+...
+$erl_atom(E) = "example";
+$erl_list(L) = "list";
+$erl_list(L) = "of";
+$erl_list(L) = $erl_atom(E);
+
+xlogl("L_DEBUG","length(L): $erl_list(L=>length), format(L): $erl_list(L=>format)\n");
+
+# empty list
+$erl_tuple(E[*]) = $null;
+
+xlogl("L_DEBUG","length(E): $erl_list(E=>length), format(E): $erl_list(L=>format)\n");
+...
+
+> log output is:
+
+DEBUG: <script>: 143:length(L): 3, format(L): [example, "of", "list"]
+DEBUG: <script>: 148:length(E): 0, format(E): []
+...
+				</programlisting>
+			</example>
+		</section>
+		<section id="erlang.v.erl_tuple">
+			<title><varname>$erl_tuple(name)</varname></title>
+			<para>
+				From the Erlang point of view the tuple compound data type with
+				a fixed number of terms. The module implementation of tuple has
+				the same behavior as the list.
+			</para>
+			<example>
+				<title>Example of using erl_tuple</title>
+				<programlisting format="linespecific">
+...
+$erl_atom(line) = "line";
+$erl_atom(id)   = "id";
+$erl_atom(owner)= "owner";
+
+$var(user)  = "Bob";
+
+$erl_tuple(owner) = $var(user);
+$erl_tuple(owner) = $erl_atom(owner);
+
+$erl_tuple(id) = 23;
+$erl_tuple(id) = $erl_atom(id);
+
+$erl_list(L) = $erl_tuple(owner);
+$erl_list(L) = $erl_tuple(id);
+
+$erl_tuple(T) = $erl_list(L);
+$erl_tuple(T) = $erl_atom(line);
+
+xlogl("L_DEBUG","length(T): $erl_tuple(T=>length), format(T): $erl_tuple(T=>format)\n");
+...
+
+> log output is:
+...
+DEBUG: <script>: 153:length(T): 2, format(T): {line, [{id, 23}, {owner, "Bob"}]}
+...
+				</programlisting>
+			</example>
+		</section>
+		<section id="erlang.v.erl_pid">
+			<title><varname>$erl_pid(name)</varname></title>
+			<para>
+				<emphasis>erl_pid</emphasis> holds Eralng process identifier. Provides
+				access to Erlang PID value and could be used in send message.
+			</para>
+			<example>
+				<title>Example of using $erl_pid</title>
+				<programlisting format="linespecific">
+...
+if ($erl_xbuff(msg[0]=>type) == "pid") {
+	$erl_pid(pid) = $erl_xbuff(msg[0]);
+	xlogl("L_INFO","Received PID: $erl_pid(pid=>format)\n");
+}
+...
+				</programlisting>
+			</example>
+		</section>
+		<section id="erlang.v.erl_ref">
+			<title><varname>$erl_ref(name)</varname></title>
+			<para>
+				<emphasis>erl_ref</emphasis> holds Erlang reference. Provides
+				access to reference value and could be used in send message.
+			</para>
+			<example>
+				<title>Example of using erl_ref</title>
+				<programlisting format="linespecific">
+...
+if ($erl_xbuff(msg[0]=>type) == "ref") {
+	$erl_ref(ref) = $erl_xbuff(msg[0]);
+	xlogl("L_INFO","Reference: $erl_ref(ref=>format)\n");
+}
+...
+				</programlisting>
+			</example>
+		</section>
+		<section id="erlang.v.erl_xbuff">
+			<title><varname>$erl_xbuff(name)</varname></title>
+			<para>
+				<emphasis>erl_xbuff</emphasis> is created as generic pseudo variable
+				to acts as other pseudo variables exported from module. It's useful
+				when in advance we don't know what variable type to expect.
+				The behavior of variable depends of initialization. Module
+				functions expect this PV as return value, and PV for incoming
+				Erlang message.
+			</para>
+			<example>
+				<title>Example of using $erl_xbuff</title>
+				<programlisting format="linespecific">
+...
+# Tuple T from previous example
+
+$erl_xbuff(X) = $erl_tuple(T);
+
+xlogl("L_DEBUG","typeof(X): $erl_xbuff(X=>type), length(X): $erl_xbuff(X=>length), format(X): $erl_xbuff(X=>format)\n");
+...
+
+> log output is:
+...
+DEBUG: <script>: 410:typeof(X): tuple, length(X): 2, format(X): {line, [{id, 23}, {owner, "Bob"}]}
+...
+				</programlisting>
+			</example>
+		</section>
+	</section>
+
+	<section>
+		<title>Functions</title>
+		<section id="erlang.f.erl_rpc">
+			<title>
+				<function moreinfo="none">erl_rpc(mod,fun,args,reply)</function>
+			</title>
+			<para>
+				This function supports calling Erlang functions on remote nodes.
+			</para>
+			<para>
+				The parameter <emphasis>mod</emphasis> and <emphasis>fun</emphasis>
+				are module and function name respectively. It can be a static 
+				string or a dynamic string value with config variables.
+			</para>
+			<para>
+				The parameter <emphasis>args</emphasis> is list of arguments passed to
+				function, so it must be <emphasis>list</emphasis>, or <emphasis>xbuff</emphasis> that contains list.
+			</para>
+			<para>
+				The parameter <emphasis>reply</emphasis> is result from RPC call. It must
+				be <emphasis>xbuff</emphasis> to accept any result.
+			</para>
+			<para>
+				Function returns false on error to send or wrong arguments passed to function.
+				If executing remote function caused error function still returns
+				true but error is encoded into <emphasis>repl</emphasis> parameter.
+			</para>
+			<example>
+				<title>Example of using erl_rpc</title>
+				<programlisting format="linespecific">
+...
+# example of call erlang:list_to_tuple(["one","two"])
+# on remote node
+
+$erl_list(L) = "two";
+$erl_list(L) = "one";
+
+# put list into list
+$erl_list(args) = $erl_list(L);
+
+erl_rpc("erlang", "list_to_tuple", "$erl_list(args)", "$erl_xbuff(repl)");
+
+xlogl("L_DEBUG","type(repl): $erl_xbuff(repl=>type), format(repl): $erl_xbuff(repl=>format)\n");
+
+> log output:
+...
+DEBUG: <script>: 386:type(repl): tuple, format(repl): {"one", "two"}
+...
+				</programlisting>
+			</example>
+		</section>
+		<section id="erlang.f.erl_reg_send">
+			<title><function moreinfo="none">erl_reg_send(server,msg)</function></title>
+			<para>
+				This function sends an Erlang term to a registered process.
+			</para>
+			<para>
+				The argument <emphasis>server</emphasis> is the registered name
+				of the intended recipient process on remote node.
+			</para>
+			<para>
+				The argument <emphasis>msg</emphasis> is containing the message to be sent.
+			</para>
+			<example>
+				<title>Example of using erl_reg_send</title>
+				<programlisting format="linespecific">
+...
+# example of send message to registered process
+# {notifier,'node1 at erlang.lan'} ! {example,message}
+
+$erl_atom(example) = "example";
+$erl_atom(message) = "message";
+
+$erl_tuple(M) = $erl_atom(message);
+$erl_tuple(M) = $erl_atom(example);
+
+erl_reg_send("notifier","$erl_tuple(M)");
+...
+				</programlisting>
+			</example>
+		</section>
+		<section id="erlang.f.erl_send">
+			<title><function moreinfo="none">erl_send(pid,msg)</function></title>
+			<para>
+				This function sends an Erlang term to a process. This function
+				can be used from ANY_ROUTE. The argument <emphasis>pid</emphasis>
+				is the Erlang process id of the intended recipient process on
+				remote node. The argument <emphasis>msg</emphasis> is containing
+				the message to be sent.
+			</para>
+			<example>
+				<title>Example of using erl_send</title>
+				<programlisting format="linespecific">
+...
+# example of send message to process
+# Pid ! {example,message}
+
+$erl_atom(notifier) = "notifier";
+$erl_list(args) = $erl_atom(notifier);
+
+erl_rpc("erlang", "whereis", "$erl_list(args)", "$erl_xbuff(pid)");
+
+$erl_atom(example) = "example";
+$erl_atom(message) = "message";
+
+$erl_tuple(M) = $erl_atom(message);
+$erl_tuple(M) = $erl_atom(example);
+
+erl_send("$erl_xbuff(pid)","$erl_tuple(M)");
+...
+				</programlisting>
+			</example>
+		</section>
+		<section id="erlang.f.erl_reply">
+			<title><function>erl_reply(msg)</function></title>
+			<para>
+				Function to send message from event route (pseudo process).
+				Function sends reply message <emphasis>msg</emphasis> to the sender process.
+			</para>
+			<example>
+				<title>Example of use erl_reply</title>
+				<programlisting format="linespecific">
+...
+# event route acts as registered process
+event_route[erlang:greetings] {
+
+	xlogl("L_INFO","Received message: $erl_xbuff(msg=>format)\n");
+
+	$erl_atom(hello) = "hello";
+	$erl_tuple(reply) = "Erlang";
+	$erl_tuple(reply) = $erl_atom(hello);
+
+	# reply greeting
+	erl_reply("$erl_tuple(reply)");
+}
+...
+
+%% in erlang shell
+
+(node1 at erlang.lan)24> {greetings,'proxy at kamailio.lan'} ! {hello,"Kamailio"}.
+{hello,"Kamailio"}
+(node1 at erlang.lan)25> flush().
+Shell got {hello,"Erlang"}
+ok
+
+> logged info message:
+INFO: <script>: 951:Received message: {"hello", "Kamailio"}
+>
+				</programlisting>
+			</example>
+		</section>
+	</section>
+
+	<section>
+		<title>Event routes</title>
+		<para>
+			To allow &kamailio; C node to have similar to erlang registered processes
+			we can use event routes. Event routes executed when asynchronous message received
+			from erlang node.
+		</para>
+		<para>
+			Event route receives message in <varname>$erl_xbuff(msg)</varname> and sender
+			process in <varname>$erl_xbuff(pid)</varname>. Reply message is optional
+			and can be sent with <emphasis>erl_reply</emphasis>.
+		</para>
+		<section>
+			<title>Registered pseudo process</title>
+			<para>
+				To create pseudo erlang registered process in &kamailio; scrip create event route in form of
+				<varname>event_route[erlang:<emphasis><my_process_name></emphasis>]</varname>. Where
+				<emphasis><my_process_name></emphasis> is the name of pseudo process.
+			</para>
+			<example>
+				<title>Example of registered process</title>
+				<programlisting format="linespecific">
+...
+# event route acts as registered process
+event_route[erlang:handler] {
+
+	xlogl("L_INFO","Received message: $erl_xbuff(msg=>format)\n");
+
+}
+...
+
+%% in erlang shell send message to registered process
+
+(node1 at erlang.lan)12> {handler,'proxy at kamailio.lan'} ! {"hello","Kamailio"}.
+{"hello","Kamailio"}
+
+> logged info message:
+INFO: <script>: 951:Received message: {"hello", "Kamailio"}
+>
+				</programlisting>
+			</example>
+		</section>
+		<section id="erlang.e.self">
+			<title><varname>event_route[erlang:self]</varname></title>
+			<para>
+				The reserved pseudo process name to receive messages sent to &kamailio; C node.
+				The message are sent to non registered process.
+			</para>
+			<example>
+				<title>Example of using default event route</title>
+				<programlisting format="linespecific">
+...
+# default event route from erlang
+event_route[erlang:self] {
+
+	xlogl("L_INFO","Received message: $erl_xbuff(msg=>format)\n");
+
+	if(pv_isset("$erl_xbuff(msg[1])") && $erl_xbuff(msg[1]=>type) == "pid") {
+		xlogl("L_INFO","Echo reply to: $erl_xbuff(msg[1]=>format)\n");
+		erl_send("$erl_xbuff(msg[1])","$erl_xbuff(msg[0])");
+	}
+}
+...
+
+%% in erlang shell send message to registered process
+
+(node1 at erlang.lan)12> Pid=rpc:call('proxy at kamailio.lan',erlang,whereis,[self]).
+<14808.9.0>
+(node1 at erlang.lan)14> Pid ! ["hello from",self()].
+["hello from",<0.247.0>]
+(node1 at erlang.lan)15> flush().
+Shell got "hello from"
+ok
+
+> logged info messages:
+INFO: <script>: 653:Received message: ["hello from", <node1 at erlang.lan.247.0>]
+INFO: <script>: 656:Echo reply to: <node1 at erlang.lan.247.0>]
+>
+				</programlisting>
+			</example>
+		</section>
+	</section>
+</chapter>
+
diff --git a/modules/erlang/doc/erlang_devel.xml b/modules/erlang/doc/erlang_devel.xml
new file mode 100644
index 0000000..eacf28b
--- /dev/null
+++ b/modules/erlang/doc/erlang_devel.xml
@@ -0,0 +1,178 @@
+<?xml version="1.0" encoding='ISO-8859-1'?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+<!-- Include general documentation entities -->
+<!ENTITY % docentities SYSTEM "../../../docbook/entities.xml">
+%docentities;
+
+]>
+<!-- Module Developer's Guide -->
+
+<chapter>
+	<title>&develguide;</title>
+	<section>
+		<title>Available Functions</title>
+		<section>
+			<title>
+				<function moreinfo="none">erl_load_api(erl_api)</function>
+			</title>
+			<para>
+				Function to be called directly from other modules to load the API.
+				On success return 0, on error 1.
+			</para>
+			<para>Meaning of the parameters is as follows:</para>
+			<itemizedlist mark="none">
+				<listitem>
+					<para><emphasis>erl_api_t* erl_api</emphasis> - API bindings structure.</para>
+				</listitem>
+			</itemizedlist>
+		</section>
+		<section>
+			<title>
+				<function moreinfo="none">rpc(reply,module,function,args)</function>
+			</title>
+			<para>
+				This function supports calling Erlang functions on remote nodes. On success function returns 0.
+			</para>
+			<para>Meaning of parameters is as follows:</para>
+			<itemizedlist mark="none">
+				<listitem>
+					<para><emphasis>ei_x_buff* reply</emphasis> - dynamic ei buffer where RPC reply returns.</para>
+				</listitem>
+				<listitem>
+					<para><emphasis>str *module</emphasis> - string containing module name.</para>
+				</listitem>
+				<listitem>
+					<para><emphasis>str *function</emphasis> - string containing function name.</para>
+				</listitem>
+				<listitem>
+					<para><emphasis>ei_x_buff *args</emphasis> - dynamic ei buffer with encoded arguments.</para>
+				</listitem>
+			</itemizedlist>
+		</section>
+		<section>
+			<title>
+				<function moreinfo="none">reg_send(server,msg)</function>
+			</title>
+			<para>
+				This function sends an Erlang term to a registered process. On success return 0.
+			</para>
+			<para>Meaning of parameters is as follows:</para>
+			<itemizedlist mark="none">
+				<listitem>
+					<para><emphasis>str *server</emphasis> - string containing
+					registered name of the intended recipient process on remote node.</para>
+				</listitem>
+				<listitem>
+					<para><emphasis>ei_x_buff *msg</emphasis> - dynamic ei buffer
+					with encoded erlang term. The msg must be encoded with version byte.</para>
+				</listitem>
+			</itemizedlist>
+		</section>
+		<section>
+			<title>
+				<function moreinfo="none">send(pid,msg)</function>
+			</title>
+			<para>
+				This function sends an Erlang term to a process. On success return 0.
+			</para>
+			<para>Meaning of parameters is as follows:</para>
+			<itemizedlist mark="none">
+				<listitem>
+					<para><emphasis>erlang_pid *pid</emphasis> - pid of the intended
+					recipient process on remote node.</para>
+				</listitem>
+				<listitem>
+					<para><emphasis>ei_x_buff *msg</emphasis> - dynamic ei buffer
+					with encoded erlang term. The msg must be encoded with version byte.</para>
+				</listitem>
+			</itemizedlist>
+		</section>
+		<section>
+			<title>
+				<function moreinfo="none">reply(msg)</function>
+			</title>
+			<para>
+				Function to send reply on processed message.
+			</para>
+			<para>Meaning of parameters is as follows:</para>
+			<itemizedlist mark="none">
+				<listitem>
+					<para><emphasis>ei_x_buff *msg</emphasis> - dynamic ei buffer
+					with encoded erlang term.</para>
+				</listitem>
+			</itemizedlist>
+		</section>
+		<section>
+			<title>
+				<function moreinfo="none">xavp2xbuff(xbuff,xavp)</function>
+			</title>
+			<para>
+				Function encodes XAVP variable into ei dynamic buffer. How to create XAVP variable
+				see source code.
+			</para>
+			<para>Meaning of parameters is as follows:</para>
+			<itemizedlist mark="none">
+				<listitem>
+					<para><emphasis>ei_x_buff *xbuff</emphasis> - dynamic ei buffer
+					where XAVP variable will be encoded.</para>
+				</listitem>
+				<listitem>
+					<para><emphasis>sr_xavp_t *xavp</emphasis> - XAVP variable to be encoded.</para>
+				</listitem>
+			</itemizedlist>
+		</section>
+		<section>
+			<title>
+				<function moreinfo="none">xbuff2xavp(xavp,xbuff)</function>
+			</title>
+			<para>
+				Function decodes ei dynamic buffer into XAVP variable.
+			</para>
+			<para>Meaning of parameters is as follows:</para>
+			<itemizedlist mark="none">
+				<listitem>
+					<para><emphasis>sr_xavp_t **xavp</emphasis> - XAVP variable where ei buffer will be decoded.</para>
+				</listitem>
+				<listitem>
+					<para><emphasis>ei_x_buff *xbuff</emphasis> - dynamic ei buffer.</para>
+				</listitem>
+			</itemizedlist>
+		</section>
+		<example>
+				<title>Example of using API</title>
+				<programlisting format="linespecific" language="C">
+<![CDATA[
+
+/* note: new without version byte */
+ei_x_new(&ei_req);
+
+/* ei_x_buff <- XAVP */
+if (erl_api.xavp2xbuff(&ei_req,xreq)) {
+	LM_ERR("failed to encode\n");
+	ei_x_free(&ei_req);
+	return -1;
+}
+
+memset((void*)&ei_rep,0,sizeof(ei_x_buff));
+
+erl_api.rpc(&ei_rep,&module,&function,&ei_req);
+...
+
+/* must be XAVP */
+xrepl->val.type = SR_XTYPE_XAVP;
+
+/* XAVP <- ei_x_buff */
+if (erl_api.xbuff2xavp(&xrepl->val.v.xavp,&ei_rep)){
+	LM_ERR("failed to decode\n");
+	ei_x_free(&ei_req);
+	ei_x_free(&ei_rep);
+	return -1;
+}
+
+]]>
+				</programlisting>
+			</example>
+	</section>
+</chapter>
diff --git a/modules/erlang/doc/erlang_use.xml b/modules/erlang/doc/erlang_use.xml
new file mode 100644
index 0000000..1d91905
--- /dev/null
+++ b/modules/erlang/doc/erlang_use.xml
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding='ISO-8859-1'?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+<!-- Include general documentation entities -->
+<!ENTITY % docentities SYSTEM "../../../docbook/entities.xml">
+%docentities;
+
+]>
+<!--  -->
+
+<chapter>
+	<title>Using &kamailio; from Erlang</title>
+	<section>
+		<title>RPC calls from Erlang</title>
+		<para>
+			This module implements the erlang transport and encoding interface for &kamailio; RPCs. It's allow to call any exported RPC in &kamailio;
+			from erlang node.
+		</para>
+		<para>
+			The string in RPC response is binary encoded to allow from erlang side conversion into appropriate encoding and further transformations.
+		</para>
+		<para>
+			Here are some examples:
+		</para>
+		<example>
+			<title>Example of RPC call from erlang shell with no response</title>
+			<programlisting format="linespecific">
+<![CDATA[
+
+(node1 at erlang.lan)26> rpc:call('proxy at kamailio.lan',domain,reload,[]).
+ok
+
+]]>
+			</programlisting>
+		</example>
+		<example>
+			<title>Example, check is line registered</title>
+			<programlisting format="linespecific">
+<![CDATA[
+
+(node1 at erlang.lan)29> rpc:call('proxy at kamailio.lan',ul,lookup,["location","1001 at orange.voip"]).
+[{[{<<"Contact">>,
+    {[{<<"Address">>,
+       <<"sip:1001 at 10.1.130.138:5161;transport=udp">>},
+      {<<"Expires">>,96},
+      {<<"Q">>,-1.0},
+      {<<"Call-ID">>,<<"5c89766276627815 at 10.1.130.138">>},
+      {<<"CSeq">>,10335},
+      {<<"User-Agent">>,<<"Grandstream GXP2000 1.2.5.3">>},
+      {<<"Received">>,<<"sip:198.51.100.137:62770">>},
+      {<<"Path">>,
+       <<"<sip:172.16.23.130;lr;received=sip:198.51.100.137:62"...>>},
+      {<<"State">>,<<"CS_SYNC">>},
+      {<<"Flags">>,0},
+      {<<"CFlags">>,64},
+      {<<"Socket">>,<<"udp:172.16.23.130:5070">>},
+      {<<"Methods">>,8159},
+      {<<"Ruid">>,<<"uloc-5534a79b-37ea-8">>},
+      {<<"Instance">>,<<"[not set]">>},
+      {<<"Reg-Id">>,0},
+      {<<"Last-Keepalive">>,1429543986},
+      {<<"Last-Modified">>,1429543906}]}}]}]
+
+]]>
+			</programlisting>
+		</example>
+		<example>
+			<title>Example get config variable</title>
+			<programlisting format="linespecific">
+<![CDATA[
+
+(node1 at erlang.lan)26> rpc:call('proxy at kamailio.lan',"cfg","get",["registrar","bindip"]).
+[<<"172.16.23.130">>]
+
+]]>
+			</programlisting>
+		</example>
+		<example>
+			<title>Example get dialog statistics</title>
+			<programlisting format="linespecific">
+<![CDATA[
+
+(node1 at erlang.lan)26>rpc:call('proxy at kamailio.lan',"stats","get_statistics",["dialog:"]).
+[<<"dialog:active_dialogs = 3">>,
+ <<"dialog:early_dialogs = 0">>,
+ <<"dialog:expired_dialogs = 0">>,
+ <<"dialog:failed_dialogs = 2">>,
+ <<"dialog:processed_dialogs = 15">>]
+
+]]>
+			</programlisting>
+		</example>
+	</section>
+</chapter>
diff --git a/modules/erlang/epmd.c b/modules/erlang/epmd.c
new file mode 100644
index 0000000..3a47e0f
--- /dev/null
+++ b/modules/erlang/epmd.c
@@ -0,0 +1,150 @@
+/**
+ * Copyright (C) 2015 Bicom Systems Ltd, (bicomsystems.com)
+ *
+ * Author: Seudin Kasumovic (seudin.kasumovic at gmail.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <ei.h>
+#include <netinet/ip.h> /*IPTOS_LOWDELAY*/
+
+#include "../../dprint.h"
+#include "../../ip_addr.h"
+
+#include "mod_erlang.h"
+#include "erl_helpers.h"
+#include "epmd.h"
+#include "cnode.h"
+
+#ifndef CONNECT_TIMEOUT
+#define CONNECT_TIMEOUT 500 /* ms */
+#endif
+
+/**
+ * \brief Initialize EPMD handler
+ */
+int epmd_init(epmd_handler_t *epmd)
+{
+	epmd->sockfd = erl_init_node(&epmd->ec, &cnode_alivename, &cnode_host, &cookie);
+	epmd->handle_f = handle_epmd;
+	epmd->wait_tmo_f = NULL;
+	epmd->destroy_f  = NULL;
+	epmd->new        = NULL;
+
+	return epmd->sockfd;
+}
+
+/**
+ * \brief Handle connections from epmd.
+ */
+int handle_epmd(handler_common_t *phandler)
+{
+	struct ip_addr ip;
+	struct sockaddr addr = { 0 };
+	struct sockaddr *paddr;
+	socklen_t addrlen = sizeof(struct sockaddr);
+	int port;
+	int ai_error;
+	int sockfd;
+	int on;
+
+	epmd_handler_t *me;
+	cnode_handler_t *remotenode = NULL;
+	ErlConnect conn;
+
+	paddr = &addr;
+	me = (epmd_handler_t*) phandler;
+
+	if ((sockfd = ei_accept_tmo(&me->ec, me->sockfd, &conn, CONNECT_TIMEOUT))
+			== ERL_ERROR) {
+		LM_ERR("error on accept connection: %s.\n", strerror(erl_errno));
+
+		if (erl_errno == ETIMEDOUT) {
+			return 0;
+		} else if (errno) {
+			LM_ERR("socket error: %s\n", strerror(errno));
+			return -1;
+		} else {
+			/* if errno didn't get set, assume nothing *too much* horrible occurred */
+			LM_NOTICE("ignored error in ei_accept, probably: bad client version, "
+					"bad cookie or bad node name\n");
+		}
+		return 0;
+	}
+
+	/* get remote address info of connected socket */
+	if ((ai_error = getpeername(sockfd, paddr, &addrlen)))
+	{
+		LM_ERR("%s\n",strerror(errno));
+	}
+	else
+	{
+		sockaddr2ip_addr(&ip,paddr);
+		port = sockaddr_port(paddr);
+
+		LM_DBG("connected from %s port %u\n", ip_addr2strz(&ip), port);
+	}
+
+	remotenode = (cnode_handler_t*)pkg_malloc(sizeof(cnode_handler_t));
+	if (!remotenode) {
+		erl_close_socket(sockfd);
+		return -1;
+	}
+
+	/* tos */
+	on=IPTOS_LOWDELAY;
+	if (setsockopt(sockfd, IPPROTO_IP, IP_TOS, (void*)&on,sizeof(on)) ==-1) {
+			LM_WARN("setsockopt set tos failed: %s\n", strerror(errno));
+			/* continue since this is not critical */
+	}
+
+	if (erl_set_nonblock(sockfd)){
+		LM_ERR("set non blocking socket failed\n");
+	}
+
+	memset((void*)remotenode,0,sizeof(cnode_handler_t));
+
+	remotenode->handle_f = handle_cnode;
+	remotenode->wait_tmo_f = wait_cnode_tmo;
+	remotenode->destroy_f = destroy_cnode;
+	remotenode->sockfd = sockfd;
+	remotenode->ec = me->ec;
+	remotenode->conn = conn;
+	/* for #Pid */
+	remotenode->ec.self.num = sockfd;
+
+	if (ei_x_new(&remotenode->request))
+	{
+		LOG(L_ERR,"failed to allocate ei_x_buff: %s.\n", strerror(erl_errno));
+		return -1;
+	}
+
+	if (ei_x_new_with_version(&remotenode->response))
+	{
+		LOG(L_ERR,"failed to allocate ei_x_buff: %s.\n", strerror(erl_errno));
+		return -1;
+	}
+
+	phandler->new = (handler_common_t*)remotenode;
+
+	/* activate node */
+	enode = remotenode;
+
+	return 0;
+}
diff --git a/modules/erlang/epmd.h b/modules/erlang/epmd.h
new file mode 100644
index 0000000..d5d4507
--- /dev/null
+++ b/modules/erlang/epmd.h
@@ -0,0 +1,61 @@
+/**
+ * Copyright (C) 2015 Bicom Systems Ltd, (bicomsystems.com)
+ *
+ * Author: Seudin Kasumovic (seudin.kasumovic at gmail.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef EPMD_H_
+#define EPMD_H_
+
+#include <ei.h>
+
+/*
+ * @brief Handler for epmd connections.
+ */
+typedef struct epmd_handler_s
+{
+	/* d-linked list  */
+	struct handler_common_s *prev;
+	struct handler_common_s *next;
+
+	/* if need to add new in i/o handler */
+	struct handler_common_s *new;
+
+	/*
+	 * Handle connections from local epmd daemon.
+	 *
+	 * returns:
+	 *  0 - ok to continue
+	 * -1 - epmd lost (we die regards we can't recovery)
+	 * sockfd - socket of new accepted connection to be added into
+	 * poll
+	 */
+	int (*handle_f)(handler_common_t *handler);
+	int (*wait_tmo_f)(handler_common_t *handler);
+	int (*destroy_f)(handler_common_t *handler);
+	int sockfd; /* socket to epmd */
+	ei_cnode ec; /* erlang C node (actually it's me) */
+
+} epmd_handler_t;
+
+int epmd_init(epmd_handler_t *epmd);
+int handle_epmd(handler_common_t *phandler);
+
+#endif /* EPMD_H_ */
diff --git a/modules/erlang/erl_api.c b/modules/erlang/erl_api.c
new file mode 100644
index 0000000..36d08f3
--- /dev/null
+++ b/modules/erlang/erl_api.c
@@ -0,0 +1,343 @@
+/**
+ * Copyright (C) 2015 Bicom Systems Ltd, (bicomsystems.com)
+ *
+ * Author: Seudin Kasumovic (seudin.kasumovic at gmail.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "mod_erlang.h"
+#include "erl_helpers.h"
+#include "erl_api.h"
+#include "pv_xbuff.h"
+#include "cnode.h"
+
+#include <sys/socket.h>
+#include <ei.h>
+
+int _impl_api_rpc_call(ei_x_buff* reply, const str *module,const str *function, const ei_x_buff *args);
+int _impl_reg_send(const str *server, const ei_x_buff *msg);
+int _impl_send(const erlang_pid *pid, const ei_x_buff *msg);
+int _impl_reply(const ei_x_buff *msg);
+int xavp2xbuff(ei_x_buff *xbuff, sr_xavp_t *xavp);
+int xbuff2xavp(sr_xavp_t **xavp, ei_x_buff *xbuff);
+
+/*!
+* \brief Function exported by module - it will load the other functions
+ * \param erl_api Erlang API export binding
+ * \return 1
+ */
+int load_erl( erl_api_t *erl_api )
+{
+	erl_api->rpc = _impl_api_rpc_call;
+	erl_api->reg_send = _impl_reg_send;
+	erl_api->send = _impl_send;
+	erl_api->reply = _impl_reply;
+	erl_api->xavp2xbuff = xavp2xbuff;
+	erl_api->xbuff2xavp = xbuff2xavp;
+
+	return 1;
+}
+
+/**
+ * API implementation
+ */
+int xavp2xbuff(ei_x_buff *xbuff, sr_xavp_t *xavp)
+{
+	return xavp_encode(xbuff,xavp,0);
+}
+
+
+int xbuff2xavp(sr_xavp_t **xavp, ei_x_buff *xbuff)
+{
+	int i=0, version=0;
+	if (ei_decode_version(xbuff->buff,&i,&version))
+	{
+		LM_DBG("no version byte encoded in reply\n");
+	}
+
+	return xavp_decode(xbuff,&i,xavp,0);
+}
+
+int _impl_api_rpc_call(ei_x_buff *reply, const str *module,const str *function, const ei_x_buff *args)
+{
+	struct msghdr msgh;
+	struct iovec cnt[8];
+	int pid_no = my_pid();
+	eapi_t api = API_RPC_CALL;
+	int buffsz=0;
+	int rc;
+
+	memset(&msgh, 0, sizeof(msgh));
+	memset(&cnt, 0, sizeof(cnt));
+
+	/* Kamailio PID */
+	cnt[0].iov_base = (void*)&pid_no;
+	cnt[0].iov_len  = sizeof(pid_no);
+
+	/* method */
+	cnt[1].iov_base = (void*)&api;
+	cnt[1].iov_len = sizeof(api);
+
+	/* put size of following data */
+	cnt[2].iov_base = (void*)&module->len;
+	cnt[2].iov_len  = sizeof(int);
+
+	cnt[3].iov_base = (void*)&function->len;
+	cnt[3].iov_len  = sizeof(int);
+
+	buffsz = args->index; /* occupied size */
+	cnt[4].iov_base = (void*) &buffsz;
+	cnt[4].iov_len = sizeof(buffsz);
+
+	/* module name */
+	cnt[5].iov_base = (void*)module->s;
+	cnt[5].iov_len  = module->len;
+
+	/* function name */
+	cnt[6].iov_base = (void*)function->s;
+	cnt[6].iov_len  = function->len;
+
+	/* Erlang arguments content */
+	cnt[7].iov_base = (void*)args->buff;
+	cnt[7].iov_len = buffsz; /* occupied size */
+
+	msgh.msg_iov = cnt;
+	msgh.msg_iovlen = 8;
+
+	while ((rc = sendmsg(csockfd, &msgh, 0)) == -1 && errno == EAGAIN)
+		;
+
+	if (rc == -1) {
+		LM_ERR("sendmsg failed: %s\n",strerror(errno));
+		return -1;
+	}
+
+	/*receive into reply buffer */
+	cnt[1].iov_base = &buffsz;
+	cnt[1].iov_len  = sizeof(buffsz);
+
+	/* peek reply size safe */
+	msgh.msg_iovlen = 2;
+	while ((rc = recvmsg(csockfd, &msgh, MSG_PEEK)) == -1 && errno == EAGAIN)
+		;
+
+	if (rc == -1) {
+		LM_ERR("recvmsg failed: %s\n",strerror(errno));
+		return -1;
+	}
+
+	if (reply->buffsz < buffsz) {
+		ei_x_free(reply);
+		reply->buffsz = buffsz + 1;
+		reply->buff = (char*)malloc(reply->buffsz);
+	}
+
+	cnt[2].iov_base = (void*)reply->buff;
+	cnt[2].iov_len  = buffsz;
+
+	msgh.msg_iovlen = 3;
+	while ((rc = recvmsg(csockfd, &msgh, MSG_WAITALL)) == -1 && errno == EAGAIN)
+		;
+
+	if (rc == -1) {
+		LM_ERR("recvmsg failed: %s\n",strerror(errno));
+		return -1;
+	}
+
+	if(pid_no != my_pid()) {
+		/* should never happened */
+		LM_CRIT("BUG: got other process reply (pid_no=%d)\n",pid_no);
+		return -1;
+	}
+
+	return 0;
+}
+
+int _impl_reg_send(const str *server, const ei_x_buff *msg)
+{
+	struct msghdr msgh;
+	struct iovec cnt[6];
+	int pid_no = my_pid();
+	eapi_t api = API_REG_SEND;
+	int buffsz;
+	int rc;
+	int i=0,version;
+
+	memset(&msgh, 0, sizeof(msgh));
+	memset(&cnt, 0, sizeof(cnt));
+
+	if (ei_decode_version(msg->buff,&i,&version)) {
+		LM_ERR("msg must be encoded with version\n");
+		return -1;
+	}
+
+	/* Kamailio PID */
+	cnt[0].iov_base = (void*)&pid_no;
+	cnt[0].iov_len  = sizeof(pid_no);
+
+	/* method */
+	cnt[1].iov_base = (void*)&api;
+	cnt[1].iov_len = sizeof(api);
+
+	/* put size of following data */
+	cnt[2].iov_base = (void*)&server->len;
+	cnt[2].iov_len  = sizeof(int);
+
+	buffsz = msg->index; /* occupied size */
+	cnt[3].iov_base = (void*)&buffsz;
+	cnt[3].iov_len = sizeof(buffsz);
+
+	/* module name */
+	cnt[4].iov_base = (void*)server->s;
+	cnt[4].iov_len  = server->len;
+
+	/* Erlang arguments content */
+	cnt[5].iov_base = (void*)msg->buff;
+	cnt[5].iov_len = buffsz; /* occupied size */
+
+	msgh.msg_iov = cnt;
+	msgh.msg_iovlen = 6;
+
+	while ((rc = sendmsg(csockfd, &msgh, 0)) == -1 && errno == EAGAIN)
+		;
+
+	if (rc == -1) {
+		LM_ERR("sendmsg failed: %s\n",strerror(errno));
+		return -1;
+	}
+
+	/* no reply */
+
+	return 0;
+}
+
+int _impl_reply(const ei_x_buff *msg)
+{
+	int i=0,version;
+
+	if (ei_decode_version(msg->buff,&i,&version)) {
+		LM_ERR("msg must be encoded with version\n");
+		return -1;
+	}
+
+	/* must be in call back / event route */
+
+	if (csockfd) {
+		LM_ERR("not in callback\n");
+		return -1;
+	} else if (!enode) {
+		LM_ERR("not connected\n");
+		return -1;
+	}
+	/* copy into reply */
+	if (enode->response.buffsz < msg->buffsz) {
+		/* realocate */
+		enode->response.buff=realloc(enode->response.buff,msg->buffsz);
+		if (!enode->response.buff) {
+			LM_ERR("realloc failed: not enough memory\n");
+			return -1;
+		}
+		enode->response.buffsz = msg->buffsz;
+	}
+
+	memcpy((void*)enode->response.buff,(void*)msg->buff,msg->buffsz);
+	enode->response.index = msg->index;
+
+	return 0;
+}
+
+int _impl_send(const erlang_pid *pid, const ei_x_buff *msg)
+{
+	struct msghdr msgh;
+	struct iovec cnt[6];
+	int pid_no = my_pid();
+	eapi_t api = API_SEND;
+	int buffsz;
+	int rc;
+	int i=0,version;
+
+	if (ei_decode_version(msg->buff,&i,&version)) {
+		LM_ERR("msg must be encoded with version\n");
+		return -1;
+	}
+
+	if (enode) {
+
+		/* copy into reply */
+		if (enode->response.buffsz < msg->buffsz) {
+			/* realocate */
+			enode->response.buff=realloc(enode->response.buff,msg->buffsz);
+			if (!enode->response.buff) {
+				LM_ERR("realloc failed: not enough memory\n");
+				return -1;
+			}
+			enode->response.buffsz = msg->buffsz;
+		}
+
+		memcpy((void*)enode->response.buff,(void*)msg->buff,msg->buffsz);
+		enode->response.index = msg->index;
+
+		/* address process */
+		cnode_reply_to_pid = (erlang_pid *)pid;
+		return 0;
+	} else if (csockfd) {
+
+		/* send via cnode */
+		memset(&msgh, 0, sizeof(msgh));
+		memset(&cnt, 0, sizeof(cnt));
+
+		/* Kamailio PID */
+		cnt[0].iov_base = (void*)&pid_no;
+		cnt[0].iov_len  = sizeof(pid_no);
+
+		/* method */
+		cnt[1].iov_base = (void*)&api;
+		cnt[1].iov_len = sizeof(api);
+
+		/* put size of following data */
+		buffsz = msg->index; /* occupied size */
+		cnt[2].iov_base = (void*)&buffsz;
+		cnt[2].iov_len = sizeof(buffsz);
+
+		/* module name */
+		cnt[3].iov_base = (void*)pid;
+		cnt[3].iov_len  = sizeof(erlang_pid);
+
+		/* Erlang arguments content */
+		cnt[4].iov_base = (void*)msg->buff;
+		cnt[4].iov_len = buffsz; /* occupied size */
+
+		msgh.msg_iov = cnt;
+		msgh.msg_iovlen = 5;
+
+		while ((rc = sendmsg(csockfd, &msgh, 0)) == -1 && errno == EAGAIN)
+			;
+
+		if (rc == -1) {
+			LM_ERR("sendmsg failed: %s\n",strerror(errno));
+			return -1;
+		}
+	} else {
+		LM_ERR("not connected\n");
+		return -1;
+	}
+
+	/* no reply */
+	return 0;
+}
diff --git a/modules/erlang/erl_api.h b/modules/erlang/erl_api.h
new file mode 100644
index 0000000..5f6ce74
--- /dev/null
+++ b/modules/erlang/erl_api.h
@@ -0,0 +1,94 @@
+/**
+ * Copyright (C) 2015 Bicom Systems Ltd, (bicomsystems.com)
+ *
+ * Author: Seudin Kasumovic (seudin.kasumovic at gmail.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef ERL_API_H_
+#define ERL_API_H_
+
+#include "../../sr_module.h"
+#include "../../str.h"
+#include "../../xavp.h"
+#include <ei.h>
+
+typedef int (*erl_rpc_f)(ei_x_buff* reply, const str *module,const str *function, const ei_x_buff *args);
+typedef int (*erl_reg_send_f)(const str *server,const ei_x_buff *msg);
+typedef int (*erl_reply_f)(const ei_x_buff *msg);
+typedef int (*erl_send_f)(const erlang_pid *pid,const ei_x_buff *msg);
+
+/* data serialization */
+typedef int (*xavp2xbuff_f)(ei_x_buff *xbuff, sr_xavp_t *xavp);
+typedef int (*xbuff2xavp_f)(sr_xavp_t **xavp, ei_x_buff *xbuff);
+
+typedef struct erl_api_s {
+	erl_rpc_f rpc;
+	erl_reg_send_f reg_send;
+	erl_send_f send;
+	erl_reply_f reply;
+	xavp2xbuff_f xavp2xbuff;
+	xbuff2xavp_f xbuff2xavp;
+} erl_api_t;
+
+typedef  int (*load_erl_f)( erl_api_t* );
+
+/*!
+* \brief API bind function exported by the module - it will load the other functions
+ * \param erl_api Erlang API export binding
+ * \return 1
+ */
+int load_erl( erl_api_t *erl_api );
+
+/*!
+ * \brief Function to be called directly from other modules to load the Erlang API
+ * \param erl_api Erlang API export binding
+ * \return 0 on success, -1 if the API loader could not imported
+ */
+inline static int erl_load_api( erl_api_t *erl_api )
+{
+        load_erl_f load_erl_v;
+
+        /* import the Erlang API auto-loading function */
+        if ( !(load_erl_v=(load_erl_f)find_export("load_erl", 0, 0))) {
+                LM_ERR("failed to import load_erl\n");
+                return -1;
+        }
+        /* let the auto-loading function load all Erlang stuff */
+        load_erl_v( erl_api );
+
+        return 0;
+}
+
+/**
+ * debugging macro
+ * uses LM_DBG to print ei_x_buff
+ */
+#define EI_X_BUFF_PRINT(buf) \
+do{ \
+	char *mbuf = NULL; \
+	int i = 0, v=0; \
+	ei_decode_version((buf)->buff,&i,&v);\
+	i=v?i:0; \
+	ei_s_print_term(&mbuf, (buf)->buff, &i); \
+	LM_DBG(#buf": %s\n", mbuf); \
+	free(mbuf); \
+} while(0)
+
+#endif /* ERL_API_H_ */
diff --git a/modules/erlang/erl_helpers.c b/modules/erlang/erl_helpers.c
new file mode 100644
index 0000000..cc43e92
--- /dev/null
+++ b/modules/erlang/erl_helpers.c
@@ -0,0 +1,401 @@
+/**
+ * Copyright (C) 2015 Bicom Systems Ltd, (bicomsystems.com)
+ *
+ * Author: Seudin Kasumovic (seudin.kasumovic at gmail.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "erl_helpers.h"
+#include "mod_erlang.h"
+
+#include "../../resolve.h"
+#include "../../ip_addr.h"
+#include "../../str.h"
+
+#include <netinet/ip.h> /*IPTOS_LOWDELAY*/
+
+/* fall back if Kamailio host name is not given */
+char thishostname[512] = {0};
+struct sockaddr_in *thisaddr = NULL;
+
+int erl_set_nonblock(int sockfd)
+{
+	int flags;
+
+	flags = fcntl(sockfd, F_GETFD);
+
+	if (flags == -1) {
+		LM_ERR("socket %d read settings error: %s\n",sockfd,strerror(errno));
+	} else if (fcntl(sockfd, F_SETFD, flags|O_NONBLOCK) == -1) {
+		LM_ERR("socket %d set O_NONBLOCK failed: %s\n",sockfd,strerror(errno));
+	} else {
+		return 0;
+	}
+
+	return -1;
+}
+
+void erl_close_socket(int sockfd)
+{
+	if (sockfd > 0) {
+		shutdown(sockfd, SHUT_RDWR);
+		close(sockfd);
+	}
+}
+
+/** \brief allocate & bind a server socket using TCP.
+ *
+ * 	Allocate & bind a server socket using TCP.
+ *
+ */
+int erl_passive_socket(const char *hostname, int qlen,
+		struct addrinfo **ai_ret)
+{
+	int sockfd; /* socket descriptor and socket type	*/
+	int on = 1;
+	int error_num = 0;
+	int port;
+	struct addrinfo *ai;
+	struct addrinfo hints;
+	struct ip_addr ip;
+	socklen_t addrlen = sizeof(struct sockaddr);
+
+	memset(&hints, 0, sizeof(struct addrinfo));
+
+	hints.ai_family = AF_UNSPEC;
+	/* = AF_INET;  IPv4 address family */
+	/* = AF_UNSPEC; Allow IPv4 or IPv6 */
+	hints.ai_socktype = SOCK_STREAM;
+	hints.ai_flags = AI_V4MAPPED;
+	hints.ai_protocol = IPPROTO_TCP;
+
+	if ((error_num = getaddrinfo(hostname, 0 /* unused */, &hints, &ai)))
+	{
+		LM_CRIT("failed to resolve %s: %s\n", hostname, gai_strerror(error_num));
+		return -1;
+	}
+
+	/* Allocate a socket */
+	sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+	if (sockfd < 0)
+	{
+		LM_CRIT("failed to create socket. %s.\n", strerror(errno));
+		freeaddrinfo(ai);
+		return -1;
+	}
+
+	/* initialize TCP */
+#if  !defined(TCP_DONT_REUSEADDR)
+	if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(int))) {
+		LM_ERR("failed to enable SO_REUSEADDR for socket on %s %s, %s\n",
+				hostname, ip_addr2strz(&ip), strerror(errno));
+	}
+#endif
+	/* tos */
+	on=IPTOS_LOWDELAY;
+	if (setsockopt(sockfd, IPPROTO_IP, IP_TOS, (void*)&on,sizeof(on)) ==-1) {
+			LM_WARN("setsockopt tos: %s\n", strerror(errno));
+			/* continue since this is not critical */
+	}
+
+	/* Bind the socket */
+	if (bind(sockfd, ai->ai_addr, ai->ai_addrlen) < 0)
+	{
+		port=sockaddr_port(ai->ai_addr);
+		LM_CRIT("failed to bind socket on %s %s:%u. %s.\n", hostname,
+				ip_addr2strz(&ip), port, strerror(errno));
+
+		erl_close_socket(sockfd);
+		freeaddrinfo(ai);
+		return -1;
+	}
+
+	if (ai->ai_socktype == SOCK_STREAM && listen(sockfd, qlen) < 0)
+	{
+		LM_CRIT("failed to listen socket on %s, %s. %s.\n", hostname,
+				ip_addr2strz(&ip), strerror(errno));
+
+		erl_close_socket(sockfd);
+		freeaddrinfo(ai);
+
+		return -1;
+	}
+
+	/* get addr on socket */
+	if (getsockname(sockfd, ai->ai_addr, &addrlen)){
+		LM_ERR("getsockname failed: %s\n",strerror(errno));
+	}
+
+	if (ai_ret && *ai_ret == NULL)
+	{
+		*ai_ret = ai;
+	}
+	else if (ai_ret)
+	{
+		freeaddrinfo(*ai_ret);
+		*ai_ret = ai;
+	}
+	else
+	{
+		freeaddrinfo(ai);
+	}
+
+	return sockfd;
+}
+
+/** @brief allocate active socket using TCP.
+ *
+ * 	Allocate active client socket using TCP.
+ *
+ */
+int erl_active_socket(const char *hostname, int qlen, struct addrinfo **ai_ret)
+{
+	int error_num = 0;
+	struct addrinfo *ai;
+	struct addrinfo hints;
+
+	memset(&hints, 0, sizeof(struct addrinfo));
+
+	hints.ai_family = AF_UNSPEC;
+	/* = AF_INET;  IPv4 address family */
+	/* = AF_UNSPEC; Allow IPv4 or IPv6 */
+	hints.ai_socktype = SOCK_STREAM;
+	hints.ai_flags = AI_V4MAPPED;
+	hints.ai_protocol = IPPROTO_TCP;
+
+	if ((error_num = getaddrinfo(hostname, 0 /* unused */, &hints, &ai)))
+	{
+		LM_CRIT("failed to resolve %s: %s\n", hostname, gai_strerror(error_num));
+		return -1;
+	}
+
+	if (ai_ret && *ai_ret == NULL)
+	{
+		*ai_ret = ai;
+	}
+	else if (ai_ret)
+	{
+		freeaddrinfo(*ai_ret);
+		*ai_ret = ai;
+	}
+	else
+	{
+		freeaddrinfo(ai);
+	}
+
+	return 0;
+}
+
+/*
+ * Call before any erl_interface library function.
+ */
+void erl_init_common()
+{
+	/* distribution trace level */
+	if (trace_level)
+	{
+		ei_set_tracelevel(trace_level);
+	}
+}
+
+/*
+ * Free allocated memory for common patterns.
+ */
+void erl_free_common()
+{
+}
+
+/**
+ * @brief Initialize Erlang connection
+ */
+int erl_init_ec(ei_cnode *ec, const str *alivename, const str *hostname, const str *cookie)
+{
+	/* identifies a specific instance of a C node. */
+	short creation = getpid();
+	struct addrinfo *ai = NULL;
+	struct sockaddr *addr = NULL;
+	ip_addr_t ip;
+
+	char nodename[MAXNODELEN];
+
+	int result;
+	int port;
+
+	/* copy the nodename into something we can modify */
+	if (snprintf(nodename, MAXNODELEN, "%.*s@%.*s", STR_FMT(alivename), STR_FMT(hostname)) >= MAXNODELEN) {
+		LM_CRIT("the node name %.*s@%.*s is too large max length allowed is %d\n", STR_FMT(alivename), STR_FMT(hostname), MAXNODELEN-1);
+		return -1;
+	}
+
+	if (erl_active_socket(hostname->s, 128, &ai)) {
+		return -1;
+	}
+
+	addr = (struct sockaddr*) ai->ai_addr;
+	sockaddr2ip_addr(&ip,addr);
+
+	if ((result = ei_connect_xinit(ec, hostname->s, alivename->s, nodename, (Erl_IpAddr) &(((struct sockaddr_in*)ai->ai_addr)->sin_addr), cookie->s, creation)) < 0) {
+
+		LM_CRIT("failed to initialize self as cnode name %s\n", nodename);
+		return -1;
+	}
+
+	port = sockaddr_port(addr);
+
+	LM_DBG("initialized ec for cnode '%s' on %.*s[%s] creation %d.\n", nodename, STR_FMT(hostname), ip_addr2strz(&ip), creation);
+
+	freeaddrinfo(ai);
+	return 0;
+}
+/**
+ * \brief Initialize C node server and returns listen socket.
+ */
+int erl_init_node(ei_cnode *ec, const str *alivename, const str *hostname, const str *cookie)
+{
+	/* identifies a specific instance of a C node. */
+	short creation = getpid();
+	struct addrinfo *ai = NULL;
+	struct sockaddr *addr = NULL;
+	ip_addr_t ip;
+
+	char nodename[MAXNODELEN];
+
+	int result;
+	int listen_fd;
+	int port;
+
+	unsigned timeout_ms = CONNECT_TIMEOUT;
+	int epmdfd;
+
+	/* copy the nodename into something we can modify */
+	if (snprintf(nodename, MAXNODELEN, "%.*s@%.*s", STR_FMT(alivename), STR_FMT(hostname)) >= MAXNODELEN) {
+		LM_CRIT("the node name %.*s@%.*s is too large max length allowed is %d\n", STR_FMT(alivename), STR_FMT(hostname), MAXNODELEN-1);
+		return -1;
+	}
+
+	if ((listen_fd = erl_passive_socket(hostname->s, 128, &ai)) == -1) {
+		return -1;
+	}
+
+	/* use first ip address only, it's internal Erlang connection to empd */
+	addr = (struct sockaddr*) ai->ai_addr;
+
+	if ((result = ei_connect_xinit(ec, hostname->s, alivename->s, nodename, (Erl_IpAddr) &(((struct sockaddr_in*)ai->ai_addr)->sin_addr), cookie->s, creation)) < 0) {
+
+		LM_CRIT("failed to initialize self as node %s\n", nodename);
+		erl_close_socket(listen_fd);
+		return -1;
+	}
+
+	port = sockaddr_port(addr);
+	sockaddr2ip_addr(&ip, addr);
+
+	/* publish */
+	if ((epmdfd = ei_publish_tmo(ec, port, timeout_ms)) == -1) {
+
+		LM_ERR("Failed to publish port %u to epmd, check is epmd started\n", port);
+
+		erl_close_socket(listen_fd);
+		return -1;
+	} else {
+		LM_DBG("listen on %s:%u[%u]/[%d] as %s\n",ip_addr2strz(&ip),port,listen_fd,epmdfd,nodename);
+	}
+
+	freeaddrinfo(ai);
+	return listen_fd;
+}
+
+void io_handler_ins(handler_common_t* phandler)
+{
+	if (io_handlers) {
+		io_handlers->prev = phandler;
+		phandler->next = io_handlers;
+	} else {
+		phandler->next = NULL;
+	}
+
+	phandler->prev = NULL;
+	io_handlers = phandler;
+}
+
+void io_handler_del(handler_common_t* phandler)
+{
+	handler_common_t* p = phandler;
+
+	if (p == io_handlers) {
+		io_handlers = phandler->next;
+	} else {
+		phandler->prev->next = phandler->next;
+	}
+
+	if(phandler->destroy_f) phandler->destroy_f(phandler);
+
+	pkg_free((void*)phandler);
+}
+
+void io_handlers_delete()
+{
+	handler_common_t* p;
+
+	while(io_handlers){
+		p = io_handlers;
+		io_handlers = io_handlers->next;
+		pkg_free((void*)p);
+	}
+}
+
+/**
+ * Decode string/binary into destination buffer.
+ *
+ */
+int ei_decode_strorbin(char *buf, int *index, int maxlen, char *dst)
+{
+	int type, size, res;
+	long len;
+
+	ei_get_type(buf, index, &type, &size);
+
+	if (type == ERL_NIL_EXT || size == 0)
+	{
+		dst[0] = '\0';
+		return 0;
+	}
+
+	if (type != ERL_STRING_EXT && type != ERL_BINARY_EXT)
+	{
+		return -1;
+	}
+	else if (size > maxlen)
+	{
+		LM_ERR("buffer size %d too small for %s with size %d\n",
+				maxlen, type == ERL_BINARY_EXT ? "binary" : "string", size);
+		return -1;
+	}
+	else if (type == ERL_BINARY_EXT)
+	{
+		res = ei_decode_binary(buf, index, dst, &len);
+		dst[len] = '\0';
+	}
+	else
+	{
+		res = ei_decode_string(buf, index, dst);
+	}
+
+	return res;
+}
diff --git a/modules/erlang/erl_helpers.h b/modules/erlang/erl_helpers.h
new file mode 100644
index 0000000..2aed063
--- /dev/null
+++ b/modules/erlang/erl_helpers.h
@@ -0,0 +1,154 @@
+/**
+ * Copyright (C) 2015 Bicom Systems Ltd, (bicomsystems.com)
+ *
+ * Author: Seudin Kasumovic (seudin.kasumovic at gmail.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef ERL_HELPERS_H_
+#define ERL_HELPERS_H_
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <ei.h>
+
+#include "../../str.h"
+#include "../../dprint.h"
+
+#define CONNECT_TIMEOUT	500 /* ms */
+#define sockaddr_port(addr)	((addr)->sa_family == AF_INET ? ntohs(((struct sockaddr_in *)(addr))->sin_port) : ntohs(((struct sockaddr_in6 *)(addr))->sin6_port))
+
+#define EI_X_BUFF_NULL	{0, 0, 0}
+
+extern char thishostname[512];
+
+/* common members of listener */
+typedef struct handler_common_s
+{
+	/* d-linked list  */
+	struct handler_common_s *prev;
+	struct handler_common_s *next;
+
+	/* if need to add new in i/o handler */
+	struct handler_common_s *new;
+
+	/* listener function */
+	int (*handle_f)(struct handler_common_s *phandler_t);
+	int (*wait_tmo_f)(struct handler_common_s *phandler_t);
+	int (*destroy_f)(struct handler_common_s *phandler_t);
+	int sockfd;
+	ei_cnode ec; /* erlang C node descriptor */
+
+} handler_common_t;
+
+extern handler_common_t* io_handlers;
+
+typedef struct erlang_ref_ex_s {
+	erlang_ref ref;
+	char nodename[MAXATOMLEN];
+	int with_node;
+} erlang_ref_ex_t;
+
+void erl_init_common();
+void erl_free_common();
+
+int erl_set_nonblock(int sockfd);
+void erl_close_socket(int sockfd);
+
+int erl_passive_socket(const char *hostname, int qlen, struct addrinfo **ai_ret);
+int erl_active_socket(const char *hostname, int qlen, struct addrinfo **ai_ret);
+
+int erl_init_ec(ei_cnode *ec, const str *alivename, const str *hostname, const str *cookie);
+int erl_init_node(ei_cnode *ec, const str *alivename, const str *hostname, const str *cookie);
+
+void io_handler_ins(handler_common_t* phandler);
+void io_handler_del(handler_common_t* phandler);
+void io_handlers_delete();
+
+#define PRINT_DBG_REG_SEND(node,from,cnode,to,msg) \
+		do { \
+			char *mbuf = NULL; \
+			char *pbuf = NULL; \
+			ei_x_buff xpid = {0,0,0}; \
+			int i=0,v=0; \
+			ei_decode_version((msg)->buff,&i,&v);\
+			i=v?i:0; \
+			ei_s_print_term(&mbuf, (msg)->buff, &i); \
+			ei_x_encode_pid(&xpid,&from); \
+			i = 0; \
+			ei_s_print_term(&pbuf,xpid.buff,&i); \
+			LM_DBG("ERL_REG_SEND: {%s,'%s'} <- %s from {%s,'%s'}\n", to, cnode, mbuf, pbuf, node); \
+			free(mbuf), free(pbuf), ei_x_free(&xpid); \
+		} while(0)
+
+#define PRINT_DBG_SEND(node,to,msg) \
+		do { \
+			char *mbuf = NULL; \
+			char *pbuf = NULL; \
+			ei_x_buff xpid = {0,0,0}; \
+			int i=0,v=0; \
+			ei_decode_version((msg)->buff,&i,&v);\
+			i=v?i:0; \
+			ei_s_print_term(&mbuf, (msg)->buff, &i); \
+			ei_x_encode_pid(&xpid,&to); \
+			i = 0; \
+			ei_s_print_term(&pbuf,xpid.buff,&i); \
+			LM_DBG("ERL_SEND: %s <- %s from '%s'\n", pbuf, mbuf, node); \
+			free(mbuf), free(pbuf), ei_x_free(&xpid); \
+		} while(0)
+
+#define ei_x_print_reg_msg(buf, dest, send) \
+do{ \
+	char *mbuf = NULL; \
+	int i = 1; \
+	ei_s_print_term(&mbuf, (buf)->buff, &i); \
+	if (send) LM_DBG("sending %s to %s\n", mbuf, dest); \
+	else LM_DBG("received %s from/for %s\n", mbuf, dest); \
+	free(mbuf); \
+} while(0)
+
+#define ei_x_print_msg(buf, pid, send) \
+do { \
+	char *pbuf = NULL; \
+	int i = 0; \
+	ei_x_buff pidbuf; \
+	ei_x_new(&pidbuf); \
+	ei_x_encode_pid(&pidbuf, pid); \
+	ei_s_print_term(&pbuf, pidbuf.buff, &i); \
+	ei_x_print_reg_msg(buf, pbuf, send); \
+	free(pbuf); \
+} while(0)
+
+int ei_decode_strorbin(char *buf, int *index, int maxlen, char *dst);
+
+typedef enum {
+	API_RPC_CALL,
+	API_REG_SEND,
+	API_SEND
+} eapi_t;
+
+#endif /* ERL_HELPERS_H_ */
diff --git a/modules/erlang/handle_emsg.c b/modules/erlang/handle_emsg.c
new file mode 100644
index 0000000..e43bb1f
--- /dev/null
+++ b/modules/erlang/handle_emsg.c
@@ -0,0 +1,848 @@
+/**
+ * Copyright (C) 2015 Bicom Systems Ltd, (bicomsystems.com)
+ *
+ * Author: Seudin Kasumovic (seudin.kasumovic at gmail.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <ei.h>
+
+#include "handle_emsg.h"
+#include "handle_rpc.h"
+#include "erl_helpers.h"
+#include "cnode.h"
+#include "pv_xbuff.h"
+#include "mod_erlang.h"
+
+#include "../../dprint.h"
+#include "../../sr_module.h"
+#include "../../cfg/cfg_struct.h"
+#include "../../lib/kcore/faked_msg.h"
+
+int handle_msg_req_tuple(cnode_handler_t *phandler, erlang_msg * msg);
+int handle_req_ref_tuple(cnode_handler_t *phandler, erlang_msg * msg);
+int handle_rpc_response(cnode_handler_t *phandler, erlang_msg * msg, int arity);
+int handle_rex_call(cnode_handler_t *phandler,erlang_ref_ex_t *ref, erlang_pid *pid);
+int handle_net_kernel(cnode_handler_t *phandler, erlang_msg * msg);
+void encode_error_msg(ei_x_buff *response, erlang_ref_ex_t *ref, const char *type, const char *msg );
+
+int handle_reg_send(cnode_handler_t *phandler, erlang_msg * msg)
+{
+	int rt, backup_rt;
+	struct run_act_ctx ctx;
+	sip_msg_t *fmsg;
+	sip_msg_t tmsg;
+	char *route;
+	size_t sz;
+	ei_x_buff *request = &phandler->request;
+	sr_xavp_t *xreq = NULL;
+	sr_xavp_t *xpid = NULL;
+	str msg_name = str_init("msg");
+	str pid_name = str_init("pid");
+	sr_xval_t val;
+	sr_data_t *data = NULL;
+
+	sz = sizeof("erlang")+strlen(msg->toname)+2;
+	route = (char*)pkg_malloc(sz);
+	if (!route) {
+		LM_ERR("not enough memory");
+		return -1;
+	}
+
+	snprintf(route,sz,"erlang:%s",msg->toname);
+
+	rt = route_get(&event_rt, route);
+	if (rt < 0 || event_rt.rlist[rt] == NULL) {
+		LM_WARN("ERL_REG_SEND message to unknown process %s\n", route);
+		pkg_free(route);
+		PRINT_DBG_REG_SEND(phandler->conn.nodename, msg->from, phandler->ec.thisnodename, msg->toname,request);
+		return 0;
+	}
+
+	LM_DBG("executing registered process %s\n", route);
+
+	fmsg = faked_msg_next();
+	memcpy(&tmsg, fmsg, sizeof(sip_msg_t));
+	fmsg = &tmsg;
+
+	if ((xreq = pv_xbuff_get_xbuff(&msg_name))) {
+		LM_DBG("free previous $xbuff(msg) value\n");
+		xavp_destroy_list(&xreq->val.v.xavp);
+	} else {
+		xreq = xbuff_new(&msg_name);
+	}
+
+	if (!xreq) {
+		LM_ERR("failed to create $xbuff(msg) variable\n");
+		goto err;
+	}
+
+	/* decode request into $xbuff(msg) */
+	xreq->val.type = SR_XTYPE_XAVP;
+
+	/* XAVP <- ei_x_buff */
+	if (erl_api.xbuff2xavp(&xreq->val.v.xavp,request)){
+		LM_ERR("failed to decode message\n");
+		goto err;
+	}
+
+	if ((xpid = pv_xbuff_get_xbuff(&pid_name))) {
+		LM_DBG("free previous $xbuff(pid) value\n");
+		xavp_destroy_list(&xpid->val.v.xavp);
+	} else {
+		xpid = xbuff_new(&pid_name);
+	}
+
+	if (!xpid) {
+		LM_ERR("failed to create $xbuff(pid) variable\n");
+		goto err;
+	}
+
+	/* put erl_pid into $xbuff(pid) */
+	data = (sr_data_t*)shm_malloc(sizeof(sr_data_t)+sizeof(erlang_pid));
+	if (!data) {
+		LM_ERR("not enough shared memory\n");
+		goto err;
+	}
+
+	memset((void*)data,0,sizeof(sr_data_t)+sizeof(erlang_pid));
+
+	data->p = (void*)data+sizeof(sr_data_t);
+	data->pfree = xbuff_data_free;
+
+	memcpy(data->p,(void*)&msg->from,sizeof(erlang_pid));
+
+	val.type = SR_XTYPE_DATA;
+	val.v.data = data;
+
+	xpid->val.v.xavp = xavp_new_value(&pid_name,&val);
+	if (!xpid->val.v.xavp) {
+		LM_ERR("failed to create xavp!\n");
+		goto err;
+	}
+	xpid->val.type = SR_XTYPE_XAVP;
+
+	/* registered process reply to from */
+	cnode_reply_to_pid = &msg->from;
+
+	backup_rt = get_route_type();
+	set_route_type(EVENT_ROUTE);
+	init_run_actions_ctx(&ctx);
+	run_top_route(event_rt.rlist[rt], fmsg, &ctx);
+	set_route_type(backup_rt);
+
+	pkg_free(route);
+	free_xbuff_fmt_buff();
+	xavp_destroy_list(xavp_get_crt_list());
+	return 0;
+
+err:
+	shm_free(data);
+	pkg_free(route);
+	free_xbuff_fmt_buff();
+	xavp_destroy_list(xavp_get_crt_list());
+	return -1;
+}
+
+/*
+ * handle ERL_SEND
+ */
+int handle_send(cnode_handler_t *phandler, erlang_msg * msg)
+{
+	int rt, backup_rt;
+	struct run_act_ctx ctx;
+	sip_msg_t *fmsg;
+	sip_msg_t tmsg;
+	char route[]="erlang:self";
+	ei_x_buff *request = &phandler->request;
+	sr_xavp_t *xreq = NULL;
+	str msg_name = str_init("msg");
+
+	rt = route_get(&event_rt, route);
+	if (rt < 0 || event_rt.rlist[rt] == NULL) {
+		LM_WARN("ERL_SEND message not handled, missing event route %s\n", route);
+		PRINT_DBG_REG_SEND(phandler->conn.nodename, msg->from, phandler->ec.thisnodename, msg->toname,request);
+		return 0;
+	}
+
+	LM_DBG("executing self process %s\n", route);
+
+	fmsg = faked_msg_next();
+	memcpy(&tmsg, fmsg, sizeof(sip_msg_t));
+	fmsg = &tmsg;
+
+	if ((xreq = pv_xbuff_get_xbuff(&msg_name))) {
+		LM_DBG("free previous value\n");
+		xavp_destroy_list(&xreq->val.v.xavp);
+	} else {
+		xreq = xbuff_new(&msg_name);
+	}
+
+	if (!xreq) {
+		LM_ERR("failed to create $xbuff(msg) variable\n");
+		goto err;
+	}
+
+	/* decode request into $xbuff(msg) */
+	xreq->val.type = SR_XTYPE_XAVP;
+
+	/* XAVP <- ei_x_buff */
+	if (erl_api.xbuff2xavp(&xreq->val.v.xavp,request)){
+		LM_ERR("failed to decode message\n");
+		goto err;
+	}
+
+	backup_rt = get_route_type();
+	set_route_type(EVENT_ROUTE);
+	init_run_actions_ctx(&ctx);
+	run_top_route(event_rt.rlist[rt], fmsg, &ctx);
+	set_route_type(backup_rt);
+
+	free_xbuff_fmt_buff();
+	xavp_destroy_list(xavp_get_crt_list());
+	return 0;
+
+err:
+	free_xbuff_fmt_buff();
+	xavp_destroy_list(xavp_get_crt_list());
+	return -1;
+}
+
+int handle_req_ref_tuple(cnode_handler_t *phandler, erlang_msg * msg)
+{
+	erlang_ref ref;
+	erlang_pid pid;
+	int arity;
+	ei_x_buff *request = &phandler->request;
+	ei_x_buff *response = &phandler->response;
+
+	ei_decode_tuple_header(request->buff, &request->index, &arity);
+
+	if (ei_decode_ref(request->buff, &request->index, &ref))
+	{
+		LM_WARN("Invalid reference.\n");
+		return -1;
+	}
+
+	if (ei_decode_pid(request->buff, &request->index, &pid))
+	{
+		LM_ERR("Invalid pid in a reference/pid tuple\n");
+		return -1;
+	}
+
+	if (0)
+	{
+		ei_x_encode_atom(response, "ok");
+	}
+	else
+	{
+		ei_x_encode_tuple_header(response, 2);
+		ei_x_encode_atom(response, "error");
+		ei_x_encode_atom(response, "not_found");
+	}
+
+	return -1;
+}
+
+/* catch the response to ei_rpc_to (which comes back as {rex, {Ref, Pid}}
+ The {Ref,Pid} bit can be handled by handle_ref_tuple
+ */
+int handle_rpc_response(cnode_handler_t *phandler, erlang_msg * msg, int arity)
+{
+	int type, size, arity2, tmpindex;
+	ei_x_buff *request = &phandler->request;
+
+	ei_get_type(request->buff, &request->index, &type, &size);
+	switch (type)
+	{
+	case ERL_SMALL_TUPLE_EXT:
+	case ERL_LARGE_TUPLE_EXT:
+		tmpindex = request->index;
+		ei_decode_tuple_header(request->buff, &tmpindex, &arity2);
+		return handle_req_ref_tuple(phandler, msg);
+	default:
+		LM_ERR("Unknown RPC response.\n");
+		break;
+	}
+	/* no reply */
+	return -1;
+}
+
+int handle_msg_req_tuple(cnode_handler_t *phandler, erlang_msg * msg)
+{
+	char tupletag[MAXATOMLEN];
+	int arity;
+	int ret = 0;
+	ei_x_buff *request = &phandler->request;
+
+	ei_decode_tuple_header(request->buff, &request->index, &arity);
+	if (ei_decode_atom(request->buff, &request->index, tupletag))
+	{
+		LM_ERR("error: badarg\n");
+	}
+	else
+	{
+		if (!strncmp(tupletag, "rex", MAXATOMLEN))
+		{
+			ret = handle_rpc_response(phandler, msg, arity);
+		}
+		else
+		{
+			LM_ERR("error: undef\n");
+		}
+	}
+	return ret;
+}
+
+/* respond on net_adm:ping
+ * e.g. message:
+ *
+ * {'$gen_call', {<tbe1 at tbe.lan.343.0>, #Ref<194674.122.0>}, {is_auth, 'tbe1 at tbe.lan'}} for net_kernel
+ */
+int handle_net_kernel(cnode_handler_t *phandler, erlang_msg * msg)
+{
+	int version, size, type, arity;
+	char atom[MAXATOMLEN];
+	erlang_ref ref;
+	erlang_pid pid;
+	ei_x_buff *request = &phandler->request;
+	ei_x_buff *response = &phandler->response;
+
+	/* start from first arg */
+	request->index = 0;
+	ei_decode_version(request->buff, &request->index, &version);
+	ei_get_type(request->buff, &request->index, &type, &size);
+
+	if (type != ERL_SMALL_TUPLE_EXT && type != ERL_SMALL_TUPLE_EXT)
+	{
+		LM_ERR("not a tuple\n");
+		return -1;
+	}
+
+	ei_decode_tuple_header(request->buff, &request->index, &arity);
+
+	if (arity != 3)
+	{
+		LM_ERR("wrong arity\n");
+		return -1;
+	}
+
+	if (ei_decode_atom(request->buff, &request->index, atom) || strncmp(atom,
+			"$gen_call", MAXATOMLEN))
+	{
+		LM_ERR("not atom '$gen_call'\n");
+		return -1;
+	}
+
+	ei_get_type(request->buff, &request->index, &type, &size);
+
+	if (type != ERL_SMALL_TUPLE_EXT && type != ERL_SMALL_TUPLE_EXT)
+	{
+		LM_ERR("not a tuple\n");
+		return -1;
+	}
+
+	ei_decode_tuple_header(request->buff, &request->index, &arity);
+
+	if (arity != 2)
+	{
+		LM_ERR("wrong arity\n");
+		return -1;
+	}
+
+	if (ei_decode_pid(request->buff, &request->index, &pid)
+			|| ei_decode_ref(request->buff, &request->index, &ref))
+	{
+		LM_ERR("decoding pid and ref error\n");
+		return -1;
+	}
+
+	ei_get_type(request->buff, &request->index, &type, &size);
+
+	if (type != ERL_SMALL_TUPLE_EXT)
+	{
+		LM_ERR("not a tuple\n");
+		return -1;
+	}
+
+	ei_decode_tuple_header(request->buff, &request->index, &arity);
+
+	if (arity != 2)
+	{
+		LM_ERR("bad arity\n");
+		return -1;
+	}
+
+	if (ei_decode_atom(request->buff, &request->index, atom) || strncmp(atom,
+			"is_auth", MAXATOMLEN))
+	{
+		LM_ERR("not is_auth\n");
+		return -1;
+	}
+
+	/* To ! {Tag, Reply} */
+	ei_x_encode_tuple_header(response, 2);
+	ei_x_encode_ref(response, &ref);
+	ei_x_encode_atom(response, "yes");
+
+	ei_x_print_msg(response, &pid, 1);
+
+	ei_send_tmo(phandler->sockfd, &pid, response->buff, response->index, CONNECT_TIMEOUT);
+
+	return -1;
+}
+
+int erlang_whereis(cnode_handler_t *phandler,erlang_ref_ex_t *ref, erlang_pid *pid)
+{
+	ei_x_buff *response = &phandler->response;
+
+	ei_x_encode_pid(response,&phandler->ec.self);
+
+	return 0;
+}
+
+static int handle_erlang_calls(cnode_handler_t *phandler,erlang_ref_ex_t *ref, erlang_pid *pid, const char *method)
+{
+	ei_x_buff *response = &phandler->response;
+
+	if (strcmp(method,"whereis")==0)
+	{
+		return erlang_whereis(phandler,ref,pid);
+	}
+	else {
+		encode_error_msg(response, ref, "badrpc", "Method Not Found");
+	}
+
+	return 0;
+}
+
+/* handle rex calls
+ *
+ * example:
+ *
+ * {call, tbe, dlg_bye, [123, 456], <tbe1 at tbe.lan.31.0>}
+ *
+ */
+int handle_rex_call(cnode_handler_t *phandler,erlang_ref_ex_t *ref, erlang_pid *pid)
+{
+	char module[MAXATOMLEN];
+	char method[MAXATOMLEN];
+	char proc[2*MAXATOMLEN];
+	erl_rpc_ctx_t ctx;
+	rpc_export_t* exp;
+	int arity;
+	ei_x_buff *request = &phandler->request;
+	ei_x_buff *response = &phandler->response;
+	int size, type;
+
+	/* already decoded {call,
+	 * continue with
+	 * module,method...}
+	 */
+
+	ei_get_type(request->buff,&request->index,&type,&size);
+#ifdef ERL_SMALL_ATOM_EXT
+	if (type == ERL_ATOM_EXT || type == ERL_SMALL_ATOM_EXT)
+	{
+#else
+	if (type == ERL_ATOM_EXT)
+	{
+#endif
+		if (ei_decode_atom(request->buff,&request->index,module))
+		{
+			encode_error_msg(response, ref, "error", "Failed to decode module name");
+			return 0;
+		}
+	}
+	else if (ei_decode_strorbin(request->buff, &request->index, MAXATOMLEN, module))
+	{
+		encode_error_msg(response, ref, "error", "Failed to decode module name");
+		return 0;
+	}
+
+	ei_get_type(request->buff,&request->index,&type,&size);
+
+#ifdef ERL_SMALL_ATOM_EXT
+	if (type == ERL_ATOM_EXT || type == ERL_SMALL_ATOM_EXT)
+	{
+#else
+	if (type == ERL_ATOM_EXT)
+	{
+#endif
+		if (ei_decode_atom(request->buff,&request->index,method))
+		{
+			encode_error_msg(response, ref, "error", "Failed to decode method name");
+			return 0;
+		}
+	}
+	else if (ei_decode_strorbin(request->buff, &request->index, MAXATOMLEN, method))
+	{
+		encode_error_msg(response, ref, "error", "Failed to decode method name");
+		return 0;
+	}
+
+	if (strcmp(module,"erlang") == 0)
+	{
+		/* start encoding */
+		ei_x_encode_tuple_header(response, 2);
+		if (ref->with_node)
+		{
+			ei_x_encode_tuple_header(response,2);
+			ei_x_encode_ref(response, &ref->ref);
+			ei_x_encode_atom(response,ref->nodename);
+		}
+		else {
+			ei_x_encode_ref(response, &ref->ref);
+		}
+
+		return handle_erlang_calls(phandler,ref,pid,method);
+	}
+
+	/* be up to date with cfg */
+	cfg_update();
+
+	sprintf(proc,"%s.%s",module,method);
+
+	exp=find_rpc_export(proc,0);
+
+	if (!exp || !exp->function)
+	{
+		encode_error_msg(response, ref, "badrpc", "Method Not Found");
+
+		return 0;
+	}
+
+	ei_get_type(request->buff,&request->index,&type,&size);
+
+	/* open list for decoding */
+	if (ei_decode_list_header(request->buff,&request->index,&arity))
+	{
+		LOG(L_ERR, "Expected list of parameters type=<%c> arity=<%d>\n", type, size);
+		encode_error_msg(response, ref, "badarith", "Expected list of parameters.");
+		return 0;
+	}
+
+	/* start encoding */
+	ei_x_encode_tuple_header(response, 2);
+	if (ref->with_node)
+	{
+		ei_x_encode_tuple_header(response,2);
+		ei_x_encode_ref(response, &ref->ref);
+		ei_x_encode_atom(response,ref->nodename);
+	}
+	else {
+		ei_x_encode_ref(response, &ref->ref);
+	}
+
+	/* init context */
+	ctx.phandler = phandler;
+	ctx.pid = pid;
+	ctx.ref = ref;
+	ctx.response_sent = 0;
+	ctx.request = request;
+	ctx.request_index = request->index;
+	ctx.response = response;
+	ctx.reply_params = 0;
+	ctx.tail = 0;
+	ctx.fault = 0;
+	ctx.fault_p = &ctx.fault;
+	ctx.optional = 0;
+	ctx.no_params = 0;
+	ctx.response_index = response->index;
+	ctx.size = arity;
+
+	/* call rpc */
+	exp->function(&erl_rpc_func_param,(void*)&ctx);
+
+	if (ctx.no_params)
+	{
+		ei_x_encode_list_header(response,ctx.no_params);
+	}
+
+	if (erl_rpc_send(&ctx, 0))
+	{
+		response->index = ctx.response_index;
+		ei_x_encode_atom(response, "error");
+		ei_x_encode_tuple_header(response,2);
+		ei_x_encode_string(response, "Inernal Error: Failed to encode reply");
+	}
+	else
+	{
+		ei_x_encode_empty_list(response);
+	}
+
+	empty_recycle_bin();
+
+	/* we sent response so it's false for up calls */
+	return 0;
+}
+
+/* {'$gen_call', {<tbe1 at tbe.lan.14488.1>, #Ref<62147.65.0>}, {call, tbe, dlg_bye, [123, 456], <tbe1 at tbe.lan.31.0>}} for rex */
+int handle_rex_msg(cnode_handler_t *phandler, erlang_msg * msg)
+{
+	int version, size, type, arity;
+	char atom[MAXATOMLEN];
+	erlang_ref_ex_t ref;
+	erlang_pid pid;
+	ei_x_buff *request = &phandler->request;
+	ei_x_buff *response = &phandler->response;
+
+	/* start from first arg */
+	request->index = 0;
+	ei_decode_version(request->buff, &request->index, &version);
+	ei_get_type(request->buff, &request->index, &type, &size);
+
+	if (type != ERL_SMALL_TUPLE_EXT && type != ERL_SMALL_TUPLE_EXT)
+	{
+		LM_ERR("not a tuple\n");
+		return -1;
+	}
+
+	ei_decode_tuple_header(request->buff, &request->index, &arity);
+
+	if (arity != 3)
+	{
+		LM_ERR("wrong arity %d\n", arity);
+		return -1;
+	}
+
+	if (ei_decode_atom(request->buff, &request->index, atom) || strncmp(atom,
+			"$gen_call", MAXATOMLEN))
+	{
+		LM_ERR("not $gen_call\n");
+		return -1;
+	}
+
+	ei_get_type(request->buff, &request->index, &type, &size);
+
+	if (type != ERL_SMALL_TUPLE_EXT && type != ERL_SMALL_TUPLE_EXT)
+	{
+		LM_ERR("not a tuple\n");
+		goto err;
+	}
+
+	ei_decode_tuple_header(request->buff, &request->index, &arity);
+
+	if (arity != 2)
+	{
+		LM_ERR("wrong arity\n");
+		goto err;
+	}
+
+	if (ei_decode_pid(request->buff, &request->index, &pid) )
+	{
+		LM_ERR("decoding pid error\n");
+		goto err2;
+	}
+
+	ref.with_node = 0;
+	/* we can got with host accompanied {#Ref<18224.110.0>, 'reg-two at pbx.lan'} */
+	ei_get_type(request->buff, &request->index, &type, &size);
+	if (type == ERL_REFERENCE_EXT || type == ERL_NEW_REFERENCE_EXT)
+	{
+		if (ei_decode_ref(request->buff, &request->index, &ref.ref))
+		{
+			LM_ERR("decoding ref error\n");
+			goto err2;
+		}
+	}
+	else if (type != ERL_SMALL_TUPLE_EXT)
+	{
+		LM_ERR("not a tuple type {#Ref<x.y.z>, 'node at host.tld'} %c\n", type);
+		goto err;
+	}
+	else {
+		if (ei_decode_tuple_header(request->buff, &request->index, &arity) || arity !=2)
+			goto err2;
+
+		if (ei_decode_ref(request->buff, &request->index, &ref.ref))
+		{
+			LM_ERR("decoding ref error\n");
+			goto err2;
+		}
+
+		if (ei_decode_atom(request->buff, &request->index, ref.nodename))
+		{
+			LM_ERR("decoding node in ref error\n");
+			goto err2;
+		}
+		ref.with_node = 1;
+	}
+
+	ei_get_type(request->buff, &request->index, &type, &size);
+
+	if (type != ERL_SMALL_TUPLE_EXT)
+	{
+		LM_ERR("not a tuple\n");
+		goto err;
+	}
+
+	ei_decode_tuple_header(request->buff, &request->index, &arity);
+
+	if (arity != 5)
+	{
+		LM_ERR("bad arity %d\n", arity);
+		goto err;
+	}
+
+	if (ei_decode_atom(request->buff, &request->index, atom) == 0 && strncmp(atom,
+			"call", MAXATOMLEN) == 0)
+	{
+		return handle_rex_call(phandler, &ref, &pid);
+	}
+
+err:
+	/* To ! {Tag, Reply} */
+	ei_x_encode_tuple_header(response, 2);
+
+	if (ref.with_node)
+	{
+		ei_x_encode_tuple_header(response,2);
+		ei_x_encode_ref(response, &ref.ref);
+		ei_x_encode_atom(response,ref.nodename);
+	}
+	else {
+		ei_x_encode_ref(response, &ref.ref);
+	}
+
+	ei_x_encode_tuple_header(response,2);
+	ei_x_encode_atom(response, "badrpc");
+	ei_x_encode_string(response, "Unsupported rex request.");
+
+	ei_x_print_msg(response, &pid, 1);
+
+	ei_send_tmo(phandler->sockfd, &pid, response->buff, response->index, CONNECT_TIMEOUT);
+err2:
+	return -1;
+}
+
+
+int handle_erlang_msg(cnode_handler_t *phandler, erlang_msg * msg)
+{
+	int type, type2, size, version, arity, tmpindex;
+	int ret = 0;
+	ei_x_buff * request = &phandler->request;
+	ei_x_buff * response = &phandler->response;
+	erlang_pid from;
+
+	if (msg->msgtype == ERL_REG_SEND )
+	{
+		cnode_reply_to_pid = &msg->from;
+
+		if (!strncmp(msg->toname, "net_kernel",MAXATOMLEN)) {
+			/* respond to ping stuff */
+			ret = handle_net_kernel(phandler, msg);
+		} else if (!strncmp(msg->toname, "rex",MAXATOMLEN)) {
+			/* respond to rex stuff */
+			ret = handle_rex_msg(phandler, msg);
+		} else {
+			/* try registered process */
+			handle_reg_send(phandler,msg);
+		}
+	} else if (msg->msgtype == ERL_SEND) {
+		ret = handle_send(phandler, msg);
+	} else {
+		/* TODO: fix below after adding #Pid and #Ref in PVs */
+		request->index = 0;
+		ei_decode_version(request->buff, &request->index, &version);
+		ei_get_type(request->buff, &request->index, &type, &size);
+
+		switch (type)
+		{
+		case ERL_SMALL_TUPLE_EXT:
+		case ERL_LARGE_TUPLE_EXT:
+			tmpindex = request->index;
+			ei_decode_tuple_header(request->buff, &tmpindex, &arity);
+			ei_get_type(request->buff, &tmpindex, &type2, &size);
+
+			switch (type2)
+			{
+			case ERL_ATOM_EXT:
+				ret = handle_msg_req_tuple(phandler, msg);
+				break;
+			case ERL_REFERENCE_EXT:
+			case ERL_NEW_REFERENCE_EXT:
+				ret = handle_req_ref_tuple(phandler, msg);
+				break;
+			case ERL_PID_EXT:
+				ei_decode_pid(request->buff,&tmpindex,&from);
+				ret = handle_send(phandler, msg);
+				break;
+			default:
+				LM_ERR("nothing to do with term type=<%d> type2=<%d> -- discarding\n", type, type2);
+				break;
+			}
+			break;
+		default:
+			LM_ERR("not handled term type=<%d> size=<%d> -- discarding\n", type, size);
+			break;
+		}
+	}
+
+	if (ret)
+	{
+		/* reset pid */
+		cnode_reply_to_pid = NULL;
+		return ret;
+	}
+	else if (response->index > 1 && cnode_reply_to_pid)
+	{
+		ei_x_print_msg(response, cnode_reply_to_pid, 1);
+
+		if (ei_send(phandler->sockfd, cnode_reply_to_pid, response->buff, response->index))
+		{
+			LM_ERR("ei_send failed on node=<%s> socket=<%d>, %s\n",
+					phandler->ec.thisnodename,phandler->sockfd, strerror(erl_errno));
+		}
+
+		/* reset pid */
+		cnode_reply_to_pid = NULL;
+		return ret;
+	}
+	else
+	{
+		LM_DBG("** no reply **\n");
+
+		/* reset pid */
+		cnode_reply_to_pid = NULL;
+		return 0;
+	}
+}
+
+void encode_error_msg(ei_x_buff *response, erlang_ref_ex_t *ref, const char *type, const char *msg )
+{
+	ei_x_encode_tuple_header(response, 2);
+
+	if (ref->with_node)
+	{
+		ei_x_encode_tuple_header(response,2);
+		ei_x_encode_ref(response, &ref->ref);
+		ei_x_encode_atom(response,ref->nodename);
+	}
+	else {
+		ei_x_encode_ref(response, &ref->ref);
+	}
+
+	ei_x_encode_tuple_header(response,2);
+	ei_x_encode_atom(response, type);
+	ei_x_encode_string(response, msg);
+}
diff --git a/modules/erlang/handle_emsg.h b/modules/erlang/handle_emsg.h
new file mode 100644
index 0000000..60ee441
--- /dev/null
+++ b/modules/erlang/handle_emsg.h
@@ -0,0 +1,32 @@
+/**
+ * Copyright (C) 2015 Bicom Systems Ltd, (bicomsystems.com)
+ *
+ * Author: Seudin Kasumovic (seudin.kasumovic at gmail.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef HANDLE_EMSG_H_
+#define HANDLE_EMSG_H_
+
+#include "erl_helpers.h"
+#include "cnode.h"
+
+int handle_erlang_msg(cnode_handler_t *handler, erlang_msg * msg);
+
+#endif /* HANDLE_EMSG_H_ */
diff --git a/modules/erlang/handle_rpc.c b/modules/erlang/handle_rpc.c
new file mode 100644
index 0000000..20700e2
--- /dev/null
+++ b/modules/erlang/handle_rpc.c
@@ -0,0 +1,1484 @@
+/**
+ * Copyright (C) 2015 Bicom Systems Ltd, (bicomsystems.com)
+ *
+ * Author: Seudin Kasumovic (seudin.kasumovic at gmail.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <stdarg.h>
+#include <stdlib.h>
+
+#include "../../mem/mem.h"
+#include "../../dprint.h"
+
+#include "handle_rpc.h"
+#include "mod_erlang.h"
+
+/* create empty recycle bin */
+static struct erl_rpc_garbage *recycle_bin = 0;
+
+static int get_int(int *int_ptr,erl_rpc_ctx_t *ctx, int reads, int autoconvert);
+static int get_double(double *double_prt,erl_rpc_ctx_t *ctx, int reads, int autoconvert);
+static int get_str(str *str_ptr, erl_rpc_ctx_t *ctx, int reads, int autoconvert);
+static int find_member(erl_rpc_ctx_t *ctx, int arity, const char* member_name);
+static int add_to_recycle_bin(int type, void* ptr, erl_rpc_ctx_t *ctx);
+
+erl_rpc_param_t *erl_new_param(erl_rpc_ctx_t *ctx);
+void erl_rpc_append_param(erl_rpc_ctx_t *ctx, erl_rpc_param_t *param);
+
+/*
+ * RPC holder
+ */
+rpc_t erl_rpc_func_param;
+
+/*
+ * Function returns always success - we uses EPMD for transport
+ */
+int erl_rpc_send(erl_rpc_ctx_t *ctx, int depth)
+{
+	if (ctx->response_sent) return 0;
+	ctx->response_sent = 1;
+	erl_rpc_ctx_t *handler;
+	erl_rpc_param_t *fault = *(ctx->fault_p);
+
+	if (fault)
+	{
+		LM_ERR("fault: %d %.*s\n",fault->type, STR_FMT(&fault->value.S));
+		/* restore clear point */
+		ctx->response->index = ctx->response_index;
+
+		/* {error,{struct,[ {"code", 400}, {"error","Error message"}]}}*/
+		if (ei_x_encode_tuple_header(ctx->response,1)) goto error;	/* {error,{_,_}} */
+		if (rpc_reply_with_struct && ei_x_encode_atom(ctx->response,"struct")) goto error;	/* {error,{struct,_}} */
+		if (ei_x_encode_list_header(ctx->response,2)) goto error;	/* {error,{struct,[_,_]}} */
+		if (ei_x_encode_tuple_header(ctx->response,2)) goto error;	/* {error,{struct,[{_,_},_]}} */
+		if (ei_x_encode_atom(ctx->response,"code")) goto error;		/* {error,{struct,[{code,_},_]}} */
+		if (ei_x_encode_long(ctx->response,fault->type)) goto error;/* {error,{struct,[{code,400},_]}} */
+		if (ei_x_encode_tuple_header(ctx->response,2)) goto error;	/* {error,{struct,[{code,400},{_,_}]}} */
+		if (ei_x_encode_binary(ctx->response,"error",sizeof("error")-1)) goto error;	/* {error,{struct,[{code,400},{<<"error">>,_}]}} */
+		if (ei_x_encode_binary(ctx->response,(void*)fault->value.S.s,fault->value.S.len)) /* {error,{struct,[{code,400},{<<"error">>,<<Msg>>}]}} */
+			goto error;
+		if (ei_x_encode_empty_list(ctx->response)) goto error;
+	}
+	else if (ctx->reply_params)
+	{
+		while(ctx->reply_params)
+		{
+			if (ctx->reply_params->member_name)
+			{
+				/* {"member_name", _} */
+				if (ei_x_encode_tuple_header(ctx->response,2)) goto error;
+				if (ei_x_encode_binary(ctx->response,ctx->reply_params->member_name, strlen(ctx->reply_params->member_name)))
+					goto error;
+			}
+			/* {"member_name", MemberValue} */
+			switch (ctx->reply_params->type) {
+				case ERL_INTEGER_EXT:
+					if(ei_x_encode_long(ctx->response,ctx->reply_params->value.n)) goto error;
+					break;
+				case ERL_FLOAT_EXT:
+					if(ei_x_encode_double(ctx->response,ctx->reply_params->value.d)) goto error;
+					break;
+				case ERL_STRING_EXT:
+					if(ei_x_encode_binary(ctx->response,ctx->reply_params->value.S.s,ctx->reply_params->value.S.len)) goto error;
+					break;
+				case ERL_SMALL_TUPLE_EXT: /* add as {struct,list(no_params)} */
+					handler = (erl_rpc_ctx_t*)ctx->reply_params->value.handler;
+					if (ei_x_encode_tuple_header(ctx->response,1)) goto error;
+					if (rpc_reply_with_struct && ei_x_encode_atom(ctx->response,"struct")) goto error;
+					if (ei_x_encode_list_header(ctx->response,handler->no_params)) goto error;
+					if (erl_rpc_send(handler, depth++)) goto error;
+					if (ei_x_encode_empty_list(ctx->response)) goto error;
+					break;
+				case ERL_LIST_EXT: /* add as [list(no_params)] */
+					handler = (erl_rpc_ctx_t*)ctx->reply_params->value.handler;
+					if (ei_x_encode_list_header(ctx->response,handler->no_params)) goto error;
+					if (erl_rpc_send(handler, depth++)) goto error;
+					if (handler->no_params)
+						if (ei_x_encode_empty_list(ctx->response)) goto error;
+					break;
+				default:
+					LM_ERR("Unknown type '%c' for encoding RPC reply\n",ctx->reply_params->type);
+					break;
+			}
+			ctx->reply_params=ctx->reply_params->next;
+		}
+	}
+	else if (!depth)
+	{
+		/* restore start point */
+		LM_WARN("encode empty response -> ok");
+		ctx->response->index = ctx->response_index;
+		if (ei_x_encode_atom(ctx->response,"ok")) goto error;
+	}
+
+	return 0;
+
+error:
+	LM_ERR("error while encoding response\n");
+	return -1;
+}
+
+void erl_rpc_fault(erl_rpc_ctx_t* ctx, int code, char* fmt, ...)
+{
+	static char buf[FAULT_BUF_LEN];
+	erl_rpc_param_t *fault = *(ctx->fault_p);
+	int len;
+
+	va_list ap;
+
+	if (fault) return;
+
+	va_start(ap, fmt);
+	len = vsnprintf(buf, FAULT_BUF_LEN, fmt, ap);
+	va_end(ap);
+
+	fault=(erl_rpc_param_t*)pkg_malloc(sizeof(erl_rpc_param_t));
+
+	if (fault == 0)
+	{
+		LM_ERR("Not enough memory\n");
+		return;
+	}
+
+	if (add_to_recycle_bin(JUNK_PKGCHAR,(void*)fault,ctx))
+	{
+		pkg_free(fault);
+		return;
+	}
+
+	fault->type = code;
+	fault->value.S.s = buf;
+	fault->value.S.len = len;
+	ctx->fault = fault;
+}
+
+int erl_rpc_add(erl_rpc_ctx_t* ctx, char* fmt, ...)
+{
+	void **void_ptr;
+	int int_ptr;
+	double double_ptr;
+	char *char_ptr;
+	str *str_ptr;
+	erl_rpc_ctx_t *handler;
+	erl_rpc_param_t *param;
+
+	int reads=0;
+
+	va_list ap;
+
+	va_start(ap,fmt);
+
+	while(*fmt)
+	{
+		if ((param = erl_new_param(ctx))==0)
+		{
+			goto error;
+		}
+
+		switch(*fmt)
+		{
+		case 'b': /* Bool */
+		case 't': /* Date and time */
+		case 'd': /* Integer */
+			int_ptr = va_arg(ap, int);
+			param->type = ERL_INTEGER_EXT;
+			param->value.n = int_ptr;
+			break;
+
+		case 'f': /* double */
+			double_ptr = va_arg(ap, double);
+			param->type = ERL_FLOAT_EXT;
+			param->value.d = double_ptr;
+			break;
+
+		case 'S': /* str structure */
+			str_ptr = va_arg(ap, str*);
+
+			param->type = ERL_STRING_EXT;
+			param->value.S = *str_ptr;
+
+			break;
+
+		case 's':/* zero terminated string */
+
+			char_ptr = va_arg(ap, char *);
+
+			param->type = ERL_STRING_EXT;
+			param->value.S.len = strlen(char_ptr);
+
+			param->value.S.s = (char*)pkg_malloc(param->value.S.len);
+
+			if (!param->value.S.s)
+			{
+				LM_ERR("Not enough memory\n");
+				goto error;
+			}
+
+			if (add_to_recycle_bin(JUNK_PKGCHAR, param->value.S.s, ctx))
+			{
+				pkg_free(param->value.S.s);
+				goto error;
+			}
+
+			memcpy(param->value.S.s,char_ptr,param->value.S.len);
+
+			break;
+		case '{':
+			void_ptr = va_arg(ap,void**);
+
+			handler = (erl_rpc_ctx_t*)pkg_malloc(sizeof(erl_rpc_ctx_t));
+
+			if (!handler)
+			{
+				LM_ERR("Not enough memory\n");
+				goto error;
+			}
+
+			if (add_to_recycle_bin(JUNK_PKGCHAR,(void*)handler,ctx))
+			{
+				pkg_free(handler);
+				goto error;
+			}
+
+			*handler = *ctx;
+			handler->no_params = 0;
+			handler->reply_params=0;
+			handler->tail = 0;
+
+			/* go where we stopped */
+			*(erl_rpc_ctx_t**)void_ptr = handler;
+
+			param->type = ERL_SMALL_TUPLE_EXT;
+			param->value.handler = (void*)handler;
+
+			break;
+
+		case '[':
+			void_ptr = va_arg(ap,void**);
+
+			handler = (erl_rpc_ctx_t*)pkg_malloc(sizeof(erl_rpc_ctx_t));
+
+			if (!handler)
+			{
+				LM_ERR("Not enough memory\n");
+				goto error;
+			}
+
+			if (add_to_recycle_bin(JUNK_PKGCHAR,(void*)handler,ctx))
+			{
+				pkg_free(handler);
+				goto error;
+			}
+
+			*handler = *ctx;
+			handler->no_params = 0;
+			handler->reply_params=0;
+			handler->tail = 0;
+
+			/* go where we stopped */
+			*(erl_rpc_ctx_t**)void_ptr = handler;
+
+			param->type = ERL_LIST_EXT;
+			param->value.handler = (void*)handler;
+
+			break;
+		 default:
+			 LM_ERR("Invalid type '%c' in formatting string\n", *fmt);
+			 goto error;
+		}
+
+		erl_rpc_append_param(ctx,param);
+
+		reads++;
+		fmt++;
+	}
+	va_end(ap);
+	return reads;
+
+error:
+	LM_ERR("Failed to encode parameter #%d into response.\n",reads);
+	va_end(ap);
+	return -reads;
+}
+
+int erl_rpc_scan(erl_rpc_ctx_t* ctx, char* fmt, ...)
+{
+	int* int_ptr;
+	char** char_ptr;
+	str* str_ptr;
+	double* double_ptr;
+	void** void_ptr;
+	str s; /* helper str */
+
+	int reads = 0;
+	int modifiers = 0;
+	int autoconv = 0;
+
+	int type,size;
+	erl_rpc_ctx_t *handler;
+
+	va_list ap;
+
+	va_start(ap,fmt);
+
+	while(*fmt && ctx->size)
+	{
+		/* optional and we at the end of decoding params */
+		if (ctx->optional && !ctx->size)
+		{
+			break;
+		}
+
+		if (ei_get_type(ctx->request->buff,&ctx->request_index,&type,&size))
+		{
+			erl_rpc_fault(ctx,400,"Can't determine data type, for parameter #%d",reads);
+			LM_ERR("Can't determine data type, for parameter #%d",reads);
+
+			goto error;
+		}
+
+		switch(*fmt)
+		{
+		case '*': /* start of optional parameters */
+			modifiers++;
+			ctx->optional = 1;
+			reads++;
+			fmt++;
+			continue;
+		case '.':  /* autoconvert */
+			modifiers++;
+			autoconv = 1;
+			reads++;
+			fmt++;
+			continue;
+		case 'b': /* Bool */
+		case 't': /* Date and time */
+		case 'd': /* Integer */
+			int_ptr = va_arg(ap, int*);
+
+			if (get_int(int_ptr,ctx,reads,autoconv))
+			{
+				goto error;
+			}
+
+			break;
+		case 'f': /* double */
+			double_ptr = va_arg(ap, double*);
+
+			if (get_double(double_ptr,ctx,reads,autoconv))
+			{
+				goto error;
+			}
+
+			break;
+		case 'S': /* str structure */
+
+			str_ptr = va_arg(ap, str*);
+
+			if (get_str(str_ptr,ctx,reads,autoconv))
+			{
+				goto error;
+			}
+
+			break;
+		case 's':/* zero terminated string */
+
+			char_ptr = va_arg(ap, char **);
+			if (get_str(&s,ctx,reads,autoconv))
+			{
+				goto error;
+			}
+
+			*char_ptr = s.s;
+
+			break;
+		case '{':
+			void_ptr = va_arg(ap,void**);
+
+			if (type!=ERL_SMALL_TUPLE_EXT && type!=ERL_LARGE_TUPLE_EXT)
+			{
+				erl_rpc_fault(ctx,400,"Bad type of parameter #%d (t=%c).",reads,type);
+				goto error;
+			}
+
+			handler = (erl_rpc_ctx_t*)pkg_malloc(sizeof(erl_rpc_ctx_t));
+
+			if (!handler)
+			{
+				erl_rpc_fault(ctx,500, "Internal Server Error (No memory left)");
+				LM_ERR("Not enough memory\n");
+				goto error;
+			}
+
+			*handler = *ctx; /* copy state */
+			handler->optional = 0;
+			handler->no_params = 0;
+			handler->size = size; /* size of tuple */
+
+			if (add_to_recycle_bin(JUNK_PKGCHAR,handler,ctx))
+			{
+				pkg_free(handler);
+				goto error;
+			}
+
+			/* skip element */
+			if (ei_skip_term(ctx->request->buff,&ctx->request_index))
+			{
+				goto error;
+			}
+
+			/* go where we stopped */
+			*(erl_rpc_ctx_t**)void_ptr = handler;
+
+			break;
+		 default:
+			 LM_ERR("Invalid parameter type in formatting string: %c\n", *fmt);
+			 erl_rpc_fault(ctx, 500, "Server Internal Error (Invalid Formatting String)");
+			 goto error;
+		}
+
+		autoconv = 0; /* reset autovoncersion for next parameter */
+		reads++;
+		fmt++;
+		ctx->size--;
+	}
+    va_end(ap);
+    return reads-modifiers;
+
+error:
+    va_end(ap);
+    return -(reads-modifiers);
+
+}
+
+int erl_rpc_struct_scan(erl_rpc_ctx_t* ctx, char* fmt, ...)
+{
+	int* int_ptr;
+	char** char_ptr;
+	str* str_ptr;
+	double* double_ptr;
+	char* member_name;
+	str s; /* helper str */
+
+	int reads = 0;
+	int modifiers = 0;
+	int index;
+	int autoconv = 0;
+
+	int arity;
+
+	va_list ap;
+
+	/* save index */
+	index = ctx->request_index;
+
+	if(ei_decode_tuple_header(ctx->request->buff,&ctx->request_index, &arity))
+	{
+		erl_rpc_fault(ctx,400,"Bad tuple");
+		return -1;
+	}
+
+	va_start(ap,fmt);
+
+	while(*fmt)
+	{
+		member_name = va_arg(ap, char*);
+
+		if (find_member(ctx,arity,member_name))
+		{
+			goto error;
+		}
+
+		switch(*fmt)
+		{
+		case 'b': /* Bool */
+		case 't': /* Date and time */
+		case 'd': /* Integer */
+			int_ptr = va_arg(ap, int*);
+
+			if (get_int(int_ptr,ctx,reads,autoconv))
+			{
+				goto error;
+			}
+
+			break;
+		case 'f': /* double */
+			double_ptr = va_arg(ap, double*);
+
+			if (get_double(double_ptr,ctx,reads,autoconv))
+			{
+				goto error;
+			}
+
+			break;
+		case 'S': /* str structure */
+
+			str_ptr = va_arg(ap, str*);
+
+			if (get_str(str_ptr,ctx,reads,autoconv))
+			{
+				goto error;
+			}
+
+			break;
+		case 's':/* zero terminated string */
+
+			char_ptr = va_arg(ap,char**);
+
+			if (get_str(&s,ctx,reads,autoconv))
+			{
+				goto error;
+			}
+
+			*char_ptr = s.s;
+
+			break;
+
+		 default:
+			 LM_ERR("Invalid parameter type in formatting string: %c\n", *fmt);
+			 erl_rpc_fault(ctx, 500, "Server Internal Error (Invalid Formatting String)");
+			 goto error;
+		}
+
+		reads++;
+		fmt++;
+	}
+
+	/* restore index */
+	ctx->request_index = index;
+
+    va_end(ap);
+    return reads-modifiers;
+
+error:
+    va_end(ap);
+    return -(reads-modifiers);
+}
+
+#define RPC_BUF_SIZE 1024
+
+/*
+ * adds formated string into RPC response buffer as Erlang string/list
+ */
+int erl_rpc_printf(erl_rpc_ctx_t* ctx, char* fmt, ...)
+{
+	int n, buff_size;
+	char *buff = 0;
+	va_list ap;
+	erl_rpc_param_t *param;
+
+	buff = (char*)pkg_malloc(RPC_BUF_SIZE);
+	if (!buff) {
+			erl_rpc_fault(ctx, 500, "Internal Server Error (No memory left)");
+			ERR("No memory left\n");
+			return -1;
+	}
+
+	buff_size = RPC_BUF_SIZE;
+
+	while(1)
+	{
+		/* Try to print in the allocated space. */
+		va_start(ap, fmt);
+		n = vsnprintf(buff, buff_size, fmt, ap);
+		va_end(ap);
+			 /* If that worked, return the string. */
+		if (n > -1 && n < buff_size)
+		{
+			if(add_to_recycle_bin(JUNK_PKGCHAR,(void*)buff,ctx))
+			{
+				goto error;
+			}
+			else if ((param = erl_new_param(ctx)))
+			{
+				param->type = ERL_STRING_EXT;
+				param->value.S.s = buff;
+				param->value.S.len = n;
+				erl_rpc_append_param(ctx,param);
+			}
+			else
+			{
+				goto error;
+			}
+
+			return 0;
+		}
+
+		/* Else try again with more space. */
+		if (n > -1)
+		{	/* glibc 2.1 */
+			buff_size = n + 1; /* precisely what is needed */
+		}
+		else
+		{	/* glibc 2.0 */
+			buff_size *= 2;  /* twice the old size */
+		}
+		if ((buff = pkg_realloc(buff, buff_size)) == 0)
+		{
+			erl_rpc_fault(ctx, 500, "Internal Server Error (No memory left)");
+			ERR("No memory left\n");
+			goto error;
+		}
+	}
+
+	return 0;
+
+error:
+	if(buff) pkg_free(buff);
+	return -1;
+}
+
+int erl_rpc_struct_add(erl_rpc_ctx_t* ctx, char* fmt, ...)
+{
+	void **void_ptr;
+	char *char_ptr;
+	str *str_ptr;
+	erl_rpc_ctx_t *handler;
+	erl_rpc_param_t *param;
+
+	int reads=0;
+
+	va_list ap;
+
+	va_start(ap,fmt);
+
+	while(*fmt)
+	{
+		if ((param = erl_new_param(ctx))==0)
+		{
+			goto error;
+		}
+
+		param->member_name = va_arg(ap, char*);
+
+		switch(*fmt)
+		{
+		case 'b': /* Bool */
+		case 't': /* Date and time */
+		case 'd': /* Integer */
+			param->type = ERL_INTEGER_EXT;
+			param->value.n = va_arg(ap, int);;
+			break;
+
+		case 'f': /* double */
+			param->type = ERL_FLOAT_EXT;
+			param->value.d = va_arg(ap, double);
+			break;
+
+		case 'S': /* str structure */
+			str_ptr = va_arg(ap, str*);
+
+			param->type = ERL_STRING_EXT;
+			param->value.S = *str_ptr;
+			break;
+
+		case 's':/* zero terminated string */
+
+			char_ptr = va_arg(ap, char *);
+
+			param->type = ERL_STRING_EXT;
+			param->value.S.len = strlen(char_ptr);
+
+			param->value.S.s = (char*)pkg_malloc(param->value.S.len);
+
+			if (!param->value.S.s)
+			{
+				LM_ERR("Not enough memory\n");
+				goto error;
+			}
+
+			if (add_to_recycle_bin(JUNK_PKGCHAR, param->value.S.s, ctx))
+			{
+				pkg_free(param->value.S.s);
+				goto error;
+			}
+
+			memcpy(param->value.S.s,char_ptr,param->value.S.len);
+
+			break;
+
+		case '{':
+			void_ptr = va_arg(ap,void**);
+
+			handler = (erl_rpc_ctx_t*)pkg_malloc(sizeof(erl_rpc_ctx_t));
+
+			if (!handler)
+			{
+				LM_ERR("Not enough memory\n");
+				goto error;
+			}
+
+			if (add_to_recycle_bin(JUNK_PKGCHAR,(void*)handler,ctx))
+			{
+				pkg_free(handler);
+				goto error;
+			}
+
+			*handler = *ctx;
+			handler->no_params = 0;
+			handler->reply_params=0;
+			handler->tail = 0;
+
+			/* go where we stopped */
+			*(erl_rpc_ctx_t**)void_ptr = handler;
+
+			param->type = ERL_SMALL_TUPLE_EXT;
+			param->value.handler = (void*)handler;
+
+			break;
+
+		case '[':
+			void_ptr = va_arg(ap,void**);
+
+			handler = (erl_rpc_ctx_t*)pkg_malloc(sizeof(erl_rpc_ctx_t));
+
+			if (!handler)
+			{
+				LM_ERR("Not enough memory\n");
+				goto error;
+			}
+
+			if (add_to_recycle_bin(JUNK_PKGCHAR,(void*)handler,ctx))
+			{
+				pkg_free(handler);
+				goto error;
+			}
+
+			*handler = *ctx;
+			handler->no_params = 0;
+			handler->reply_params=0;
+			handler->tail = 0;
+
+			/* go where we stopped */
+			*(erl_rpc_ctx_t**)void_ptr = handler;
+
+			param->type = ERL_LIST_EXT;
+			param->value.handler = (void*)handler;
+
+			break;
+
+		 default:
+			 LM_ERR("Invalid type '%c' in formatting string\n", *fmt);
+			 goto error;
+		}
+
+		erl_rpc_append_param(ctx,param);
+
+		reads++;
+		fmt++;
+	}
+	va_end(ap);
+	return reads;
+
+error:
+
+	LM_ERR("Failed to encode parameter #%d into response.\n",reads);
+	va_end(ap);
+	return -reads;
+}
+
+int erl_rpc_array_add(erl_rpc_ctx_t* ctx, char* fmt, ...)
+{
+	void **void_ptr;
+	char *char_ptr;
+	str *str_ptr;
+	erl_rpc_ctx_t *handler;
+	erl_rpc_param_t *param;
+
+	int reads=0;
+
+	va_list ap;
+
+	va_start(ap,fmt);
+
+	LM_DBG("ctx=%p add fmt=<%s>\n",(void*)ctx,fmt);
+
+	while(*fmt)
+	{
+		if ((param = erl_new_param(ctx))==0)
+		{
+			goto error;
+		}
+
+		param->member_name = NULL;
+
+		switch(*fmt)
+		{
+		case 'b': /* Bool */
+		case 't': /* Date and time */
+		case 'd': /* Integer */
+			param->type = ERL_INTEGER_EXT;
+			param->value.n = va_arg(ap, int);;
+			break;
+
+		case 'f': /* double */
+			param->type = ERL_FLOAT_EXT;
+			param->value.d = va_arg(ap, double);
+			break;
+
+		case 'S': /* str structure */
+			str_ptr = va_arg(ap, str*);
+
+			param->type = ERL_STRING_EXT;
+			param->value.S = *str_ptr;
+			break;
+
+		case 's':/* zero terminated string */
+
+			char_ptr = va_arg(ap, char *);
+
+			param->type = ERL_STRING_EXT;
+			param->value.S.len = strlen(char_ptr);
+
+			param->value.S.s = (char*)pkg_malloc(param->value.S.len);
+
+			if (!param->value.S.s)
+			{
+				LM_ERR("Not enough memory\n");
+				goto error;
+			}
+
+			if (add_to_recycle_bin(JUNK_PKGCHAR, param->value.S.s, ctx))
+			{
+				pkg_free(param->value.S.s);
+				goto error;
+			}
+
+			memcpy(param->value.S.s,char_ptr,param->value.S.len);
+
+			break;
+
+		case '{':
+			void_ptr = va_arg(ap,void**);
+
+			handler = (erl_rpc_ctx_t*)pkg_malloc(sizeof(erl_rpc_ctx_t));
+
+			if (!handler)
+			{
+				LM_ERR("Not enough memory\n");
+				goto error;
+			}
+
+			if (add_to_recycle_bin(JUNK_PKGCHAR,(void*)handler,ctx))
+			{
+				pkg_free(handler);
+				goto error;
+			}
+
+			*handler = *ctx;
+			handler->no_params = 0;
+			handler->reply_params=0;
+			handler->tail = 0;
+
+			/* go where we stopped */
+			*(erl_rpc_ctx_t**)void_ptr = handler;
+
+			param->type = ERL_SMALL_TUPLE_EXT;
+			param->value.handler = (void*)handler;
+
+			break;
+
+		case '[':
+			void_ptr = va_arg(ap,void**);
+
+			handler = (erl_rpc_ctx_t*)pkg_malloc(sizeof(erl_rpc_ctx_t));
+
+			if (!handler)
+			{
+				LM_ERR("Not enough memory\n");
+				goto error;
+			}
+
+			if (add_to_recycle_bin(JUNK_PKGCHAR,(void*)handler,ctx))
+			{
+				pkg_free(handler);
+				goto error;
+			}
+
+			*handler = *ctx;
+			handler->no_params = 0;
+			handler->reply_params=0;
+			handler->tail = 0;
+
+			/* go where we stopped */
+			*(erl_rpc_ctx_t**)void_ptr = handler;
+
+			param->type = ERL_LIST_EXT;
+			param->value.handler = (void*)handler;
+
+			break;
+
+		 default:
+			 LM_ERR("Invalid type '%c' in formatting string\n", *fmt);
+			 goto error;
+		}
+
+		erl_rpc_append_param(ctx,param);
+
+		reads++;
+		fmt++;
+	}
+	va_end(ap);
+	return reads;
+
+error:
+
+	LM_ERR("Failed to encode parameter #%d into response.\n",reads);
+	va_end(ap);
+	return -reads;
+}
+
+int erl_rpc_struct_printf(erl_rpc_ctx_t* ctx, char* name, char* fmt, ...)
+{
+	int n, buff_size;
+	char *buff;
+	va_list ap;
+	erl_rpc_param_t *param;
+
+	LM_ERR("parsing name:%s fmt: %s\n",name, fmt);
+
+	buff = (char*)pkg_malloc(RPC_BUF_SIZE);
+	if (!buff) {
+			ERR("No memory left\n");
+			return -1;
+	}
+
+	buff_size = RPC_BUF_SIZE;
+
+	while(1)
+	{
+		/* Try to print in the allocated space. */
+		va_start(ap, fmt);
+		n = vsnprintf(buff, buff_size, fmt, ap);
+		va_end(ap);
+			 /* If that worked, return the string. */
+		if (n > -1 && n < buff_size)
+		{
+
+			if(add_to_recycle_bin(JUNK_PKGCHAR,(void*)buff,ctx))
+			{
+				goto error;
+			}
+			else if ((param = erl_new_param(ctx)))
+			{
+				param->type = ERL_STRING_EXT;
+				param->value.S.s = buff;
+				param->value.S.len = n;
+				param->member_name = name;
+				erl_rpc_append_param(ctx,param);
+			}
+			else
+			{
+				goto error;
+			}
+
+			return 0;
+		}
+
+		/* Else try again with more space. */
+		if (n > -1)
+		{	/* glibc 2.1 */
+			buff_size = n + 1; /* precisely what is needed */
+		}
+		else
+		{	/* glibc 2.0 */
+			buff_size *= 2;  /* twice the old size */
+		}
+		if ((buff = pkg_realloc(buff, buff_size)) == 0)
+		{
+			ERR("No memory left\n");
+			goto error;
+		}
+	}
+
+	return 0;
+
+error:
+	if(buff) pkg_free(buff);
+	return -1;
+}
+
+int erl_rpc_capabilities(erl_rpc_ctx_t* ctx)
+{
+	return 0; /* no RPC_DELAYED_REPLY */
+}
+
+/** Add a memory to the list of memory blocks that
+ * need to be re-claimed later.
+ *
+ * @param type The type of the memory block.
+ * @param ptr A pointer to the memory block.
+ * @param ctx The context.
+ * @return 0 on success, a negative number on error.
+ * @sa empty_recycle_bin()
+ */
+static int add_to_recycle_bin(int type, void *ptr, erl_rpc_ctx_t *ctx)
+{
+	struct erl_rpc_garbage *p;
+
+	p = (struct erl_rpc_garbage*)pkg_malloc(sizeof(struct erl_rpc_garbage));
+
+	if (!p)
+	{
+			LM_ERR("Not enough memory\n");
+			return -1;
+	}
+
+	p->type = type;
+	p->ptr = ptr;
+	p->next = recycle_bin;
+	recycle_bin = p;
+	return 0;
+}
+
+/** Re-claims all memory allocated in the process of building XML-RPC
+ * reply.
+ */
+void empty_recycle_bin(void)
+{
+        struct erl_rpc_garbage* p;
+             /* Collect garbage */
+        while(recycle_bin)
+        {
+                p = recycle_bin;
+                recycle_bin = recycle_bin->next;
+                switch(p->type)
+                {
+                case JUNK_EI_X_BUFF:
+
+                	if (p->ptr)
+                	{
+                		ei_x_free((ei_x_buff*)p->ptr);
+						pkg_free(p->ptr);
+					}
+
+					break;
+
+                case JUNK_PKGCHAR:
+
+                	if (p->ptr)
+					{
+						pkg_free(p->ptr);
+					}
+
+					break;
+
+                default:
+                	ERR("BUG: Unsupported junk type\n");
+                }
+
+                pkg_free(p);
+        }
+}
+
+/*
+ * Get int parameter
+ */
+static int get_int(int *int_ptr,erl_rpc_ctx_t *ctx, int reads, int autoconvert)
+{
+	int type, size;
+	char *p;
+	char *endptr;
+	double d;
+	long l;
+
+	if (ei_get_type(ctx->request->buff,&ctx->request_index,&type,&size))
+	{
+		if(ctx->optional) return 0;
+
+		erl_rpc_fault(ctx,400,"Can't determine data type of parameter #%d",reads);
+		return -1;
+	}
+
+	switch(type)
+	{
+	case ERL_SMALL_INTEGER_EXT:
+	case ERL_INTEGER_EXT:
+		if(ei_decode_long(ctx->request->buff, &ctx->request_index, &l))
+		{
+			erl_rpc_fault(ctx,400,"Bad value of parameter #%d.",reads);
+			return -1;
+		}
+		*int_ptr = (int)l;
+
+		break;
+	case ERL_STRING_EXT:
+	case ERL_LIST_EXT:
+
+		if (autoconvert == 0)
+		{
+			erl_rpc_fault(ctx,400,"Bad type of parameter #%d",reads);
+			return -1;
+		}
+
+		/* allocate buffer */
+		p = (char*)pkg_malloc(size+1);
+
+		if (!p)
+		{
+			erl_rpc_fault(ctx,500, "Internal Server Error (No memory left)");
+			LM_ERR("Not enough memory\n");
+			return -1;
+		}
+
+		*int_ptr = strtol(p,&endptr,10);
+		if (p == endptr)
+		{
+			erl_rpc_fault(ctx,400,"Unable to convert %s into integer for parameter at position %d",p,reads);
+			pkg_free(p);
+			return -1;
+		}
+
+		pkg_free(p);
+		break;
+
+	case ERL_FLOAT_EXT:
+
+		if (autoconvert == 0)
+		{
+			erl_rpc_fault(ctx,400,"Bad type of parameter #%d",reads);
+			return -1;
+		}
+
+		if (ei_decode_double(ctx->request->buff,&ctx->request_index,&d))
+		{
+			erl_rpc_fault(ctx,400, "Can't read parameter #%d",reads);
+			return -1;
+		}
+
+		*int_ptr=(int)d;
+		break;
+
+	default:
+		LM_ERR("Unsupported type ('%c') for conversion into integer parameter #%d.\n",type,reads);
+		erl_rpc_fault(ctx,400,"Unsupported type ('%c') for conversion into integer parameter #%d.",type,reads);
+		return -1;
+	}
+
+	return 0;
+}
+
+static int get_double(double *double_prt,erl_rpc_ctx_t *ctx, int reads, int autoconvert)
+{
+	int type, size;
+	char *p;
+	char *endptr;
+	long n;
+
+	if (ei_get_type(ctx->request->buff,&ctx->request_index,&type,&size)){
+		erl_rpc_fault(ctx,400,"Can't determine data type of parameter #%d",reads);
+		return -1;
+	}
+
+	switch(type)
+	{
+	case ERL_FLOAT_EXT:
+
+		if (ei_decode_double(ctx->request->buff,&ctx->request_index,double_prt))
+		{
+			erl_rpc_fault(ctx,400, "Bad value of parameter #%d.",reads);
+			return -1;
+		}
+
+		break;
+	case ERL_STRING_EXT:
+	case ERL_LIST_EXT:
+
+		if (autoconvert == 0)
+		{
+			erl_rpc_fault(ctx,400,"Bad type of parameter #%d",reads);
+			return -1;
+		}
+
+		/* allocate buffer */
+		p = (char*)pkg_malloc(size+1);
+
+		if (!p)
+		{
+			erl_rpc_fault(ctx,500, "Internal Server Error (No memory left)");
+			LM_ERR("Not enough memory\n");
+			return -1;
+		}
+
+		*double_prt = strtod(p,&endptr);
+		if (p == endptr)
+		{
+			erl_rpc_fault(ctx,400,"Unable to convert %s into double, parameter at position #%d",p,reads);
+			pkg_free(p);
+			return -1;
+		}
+
+		pkg_free(p);
+		break;
+
+	case ERL_SMALL_INTEGER_EXT:
+	case ERL_INTEGER_EXT:
+
+		if (autoconvert == 0)
+		{
+			erl_rpc_fault(ctx,400,"Bad type of parameter #%d",reads);
+			return -1;
+		}
+
+		if(ei_decode_long(ctx->request->buff, &ctx->request_index, &n))
+		{
+			erl_rpc_fault(ctx,400,"Can't read parameter #%d",reads);
+			return -1;
+		}
+
+		*double_prt=n;
+
+		break;
+	default:
+		erl_rpc_fault(ctx,400,"Can't convert to double parameter #%d.",reads);
+		return -1;
+	}
+
+	return 0;
+}
+
+#define MAX_DIGITS	20
+
+static int get_str(str *str_ptr, erl_rpc_ctx_t *ctx, int reads, int autoconvert)
+{
+	int type, size;
+	char *p;
+	double d;
+	long n;
+
+	if (ei_get_type(ctx->request->buff,&ctx->request_index,&type,&size))
+	{
+		erl_rpc_fault(ctx,400,"Can't determine data type of parameter #%d",reads);
+		return -1;
+	}
+
+	switch(type)
+	{
+	case ERL_FLOAT_EXT:
+
+		if (autoconvert == 0)
+		{
+			erl_rpc_fault(ctx,400,"Bad type of parameter #%d",reads);
+			return -1;
+		}
+
+		if (ei_decode_double(ctx->request->buff,&ctx->request_index,&d))
+		{
+			erl_rpc_fault(ctx,400, "Bad value of parameter #%d.",reads);
+			return -1;
+		}
+
+		p=(char*)pkg_malloc(MAX_DIGITS);
+
+		if (!p)
+		{
+			erl_rpc_fault(ctx,500, "Internal Server Error (No memory left)");
+			LM_ERR("Not enough memory\n");
+			return -1;
+		}
+
+		if (add_to_recycle_bin(JUNK_PKGCHAR, p, ctx))
+		{
+			pkg_free(p);
+			return -1;
+		}
+
+		str_ptr->len=snprintf(p, MAX_DIGITS, "%f", d);
+		str_ptr->s = p;
+
+		break;
+
+	case ERL_STRING_EXT:
+	case ERL_LIST_EXT:
+	case ERL_BINARY_EXT:
+
+		/* allocate buffer */
+		p = (char*)pkg_malloc(size+1);
+
+		if (!p)
+		{
+			erl_rpc_fault(ctx,500, "Internal Server Error (No memory left)");
+			LM_ERR("Not enough memory\n");
+			return -1;
+		}
+
+		if (add_to_recycle_bin(JUNK_PKGCHAR, p, ctx))
+		{
+			pkg_free(p);
+			return -1;
+		}
+
+		if(ei_decode_strorbin(ctx->request->buff,&ctx->request_index,size+1,p))
+		{
+			erl_rpc_fault(ctx,400, "Can't read parameter #%d",reads);
+			return -1;
+		}
+
+		str_ptr->s=p;
+		str_ptr->len=size;
+
+		break;
+
+	case ERL_SMALL_INTEGER_EXT:
+	case ERL_INTEGER_EXT:
+
+		if (autoconvert == 0)
+		{
+			erl_rpc_fault(ctx,400,"Bad type of parameter #%d",reads);
+			return -1;
+		}
+
+		if (ei_decode_long(ctx->request->buff,&ctx->request_index,&n))
+		{
+			erl_rpc_fault(ctx,400, "Bad value of parameter #%d.",reads);
+			return -1;
+		}
+
+		p=(char*)pkg_malloc(MAX_DIGITS);
+
+		if (!p)
+		{
+			erl_rpc_fault(ctx,500, "Internal Server Error (No memory left)");
+			LM_ERR("Not enough memory\n");
+			return -1;
+		}
+
+		if (add_to_recycle_bin(JUNK_PKGCHAR, p, ctx))
+		{
+			pkg_free(p);
+			return -1;
+		}
+
+		str_ptr->len=snprintf(p, MAX_DIGITS, "%ld", n);
+		str_ptr->s = p;
+
+		break;
+	default:
+		erl_rpc_fault(ctx,400,"Can't convert to string parameter #%d.",reads);
+		return -1;
+	}
+
+	LM_ERR("parameter #%d:<%.*s>\n",reads,STR_FMT(str_ptr));
+
+	return 0;
+}
+
+/*
+ * Find member in tuple (aka RPC struct)
+ */
+static int find_member(erl_rpc_ctx_t *ctx, int arity, const char* member_name)
+{
+	int index,i=0;
+	int type,size;
+	char key_name[MAXATOMLEN];
+
+	/* save position */
+	index = ctx->request_index;
+
+	/* { name, Value, name, Value...} */
+	while (i < arity)
+	{
+		if (ei_get_type(ctx->request->buff,&ctx->request_index,&type,&size))
+		{
+			erl_rpc_fault(ctx,400,"Bad struct member type");
+			goto error;
+		}
+
+		if(ei_decode_atom(ctx->request->buff,&ctx->request_index, key_name))
+		{
+			erl_rpc_fault(ctx,400,"Bad member name");
+			goto error;
+		}
+
+		if (strcasecmp(member_name,key_name))
+		{
+			if(ei_skip_term(ctx->request->buff,&ctx->request_index))
+			{
+				erl_rpc_fault(ctx,400,"Unexpected end of struct tuple");
+				goto error;
+			}
+			continue;
+		}
+		else
+		{
+			/* return at current position */
+			return 0;
+		}
+
+		i++;
+	}
+
+	erl_rpc_fault(ctx,400, "Member %s not found",member_name);
+
+error:
+	ctx->request_index = index;
+	return -1;
+}
+
+void init_rpc_handlers()
+{
+	erl_rpc_func_param.send = (rpc_send_f)erl_rpc_send;
+	erl_rpc_func_param.fault = (rpc_fault_f)erl_rpc_fault;
+	erl_rpc_func_param.add = (rpc_add_f)erl_rpc_add;
+	erl_rpc_func_param.scan = (rpc_scan_f)erl_rpc_scan;
+	erl_rpc_func_param.rpl_printf = (rpc_rpl_printf_f)erl_rpc_printf;
+	erl_rpc_func_param.struct_add = (rpc_struct_add_f)erl_rpc_struct_add;
+	erl_rpc_func_param.array_add = (rpc_array_add_f)erl_rpc_array_add;
+	erl_rpc_func_param.struct_scan = (rpc_struct_scan_f)erl_rpc_struct_scan;
+	erl_rpc_func_param.struct_printf = (rpc_struct_printf_f)erl_rpc_struct_printf;
+	erl_rpc_func_param.capabilities = (rpc_capabilities_f)erl_rpc_capabilities;
+	erl_rpc_func_param.delayed_ctx_new = 0;
+	erl_rpc_func_param.delayed_ctx_close = 0;
+}
+
+erl_rpc_param_t *erl_new_param(erl_rpc_ctx_t *ctx)
+{
+	erl_rpc_param_t *p = (erl_rpc_param_t *)pkg_malloc(sizeof(erl_rpc_param_t));
+
+	if (add_to_recycle_bin(JUNK_PKGCHAR,(void*)p,ctx))
+	{
+		erl_rpc_fault(ctx,500, "Internal Server Error (No memory left)");
+		LM_ERR("Not enough memory\n");
+
+		pkg_free(p);
+		return 0;
+	}
+
+	p->next = 0;
+	p->member_name = 0;
+	return p;
+}
+
+void erl_rpc_append_param(erl_rpc_ctx_t *ctx, erl_rpc_param_t *param)
+{
+
+	if (ctx->tail)
+	{
+		ctx->tail->next = param;
+		ctx->tail = param;
+	}
+	else
+	{
+		ctx->reply_params = ctx->tail = param;
+	}
+
+	param->next = 0;
+	ctx->no_params++;
+}
diff --git a/modules/erlang/handle_rpc.h b/modules/erlang/handle_rpc.h
new file mode 100644
index 0000000..7a3cad1
--- /dev/null
+++ b/modules/erlang/handle_rpc.h
@@ -0,0 +1,102 @@
+/**
+ * Copyright (C) 2015 Bicom Systems Ltd, (bicomsystems.com)
+ *
+ * Author: Seudin Kasumovic (seudin.kasumovic at gmail.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "../../rpc.h"
+#include "erl_helpers.h"
+#include "cnode.h"
+
+#ifndef HANDLE_RPC_H_
+#define HANDLE_RPC_H_
+
+#define FAULT_BUF_LEN 1024
+
+/*
+ * RPC structure to store reply before marshaling.
+ */
+typedef struct erl_rpc_param_s {
+	int type;
+	union {
+		int n;
+		double d;
+		str S;
+		void* handler;
+	} value;
+	char *member_name;
+	struct erl_rpc_param_s *next;
+} erl_rpc_param_t;
+
+typedef struct erl_rpc_ctx {
+	cnode_handler_t *phandler;
+	erlang_ref_ex_t *ref;
+	erlang_pid *pid;
+	ei_x_buff *request;
+	int request_index;
+	ei_x_buff *response;
+	int response_sent;
+	int response_index;
+	erl_rpc_param_t *reply_params; /* encoded into reply as {ok,[<reply_params>]} */
+	erl_rpc_param_t *tail;
+	erl_rpc_param_t *fault; /* is set has precedence on reply_params
+	 	 	 	 	 	 	   encoded as {error, {code, <fault message>}} */
+	erl_rpc_param_t **fault_p;
+	int no_params; /* number of encoding params */
+	int optional; /* are params optional */
+	int size; /* size of decoding structure or main list */
+} erl_rpc_ctx_t;
+
+int erl_rpc_send(erl_rpc_ctx_t* ctx, int depth);					/* Send the reply to the Erlang Node */
+void erl_rpc_fault(erl_rpc_ctx_t* ctx, int code, char* fmt, ...);	/* Signal a failure to the client */
+int erl_rpc_add(erl_rpc_ctx_t* ctx, char* fmt, ...);				/* Add a new piece of data to the result */
+int erl_rpc_scan(erl_rpc_ctx_t* ctx, char* fmt, ...);				/* Retrieve request parameters */
+int erl_rpc_printf(erl_rpc_ctx_t* ctx, char* fmt, ...);				/* Add printf-like formated data to the result set */
+int erl_rpc_struct_add(erl_rpc_ctx_t* ctx, char* fmt, ...);			/* Add a new structure into structure */
+int erl_rpc_array_add(erl_rpc_ctx_t* ctx, char* fmt, ...);			/* Add a new structure into array */
+int erl_rpc_struct_scan(erl_rpc_ctx_t* ctx, char* fmt, ...);		/* Scan attributes of a structure */
+int erl_rpc_struct_printf(erl_rpc_ctx_t* ctx, char* name, char* fmt, ...); /* Struct version of rpc_printf */
+int erl_rpc_capabilities(erl_rpc_ctx_t* ctx);	/* capabilities */
+
+void init_rpc_handlers();
+void empty_recycle_bin(void);
+
+/**
+ * Garbage collection data structure.
+ */
+struct erl_rpc_garbage {
+        enum {
+                JUNK_EI_X_BUFF,   /**< This type indicates that the memory block was
+								   * allocated for the erlang EI interface, this
+								   * type needs to be freed differently
+								   */
+                JUNK_PKGCHAR      /** This type indicates a pkg_malloc'ed string */
+        } type;               /**< Type of the memory block */
+        void* ptr;            /**< Pointer to the memory block obtained from pkg_malloc */
+        struct erl_rpc_garbage* next; /**< The linked list of all allocated memory blocks */
+};
+
+
+/** Pointers to the functions that implement the RPC interface
+ * of Erlang module
+ */
+extern rpc_t erl_rpc_func_param;
+
+#endif /* HANDLE_RPC_H_ */
diff --git a/modules/erlang/mod_erlang.c b/modules/erlang/mod_erlang.c
new file mode 100644
index 0000000..032a037
--- /dev/null
+++ b/modules/erlang/mod_erlang.c
@@ -0,0 +1,1397 @@
+/**
+ * Copyright (C) 2015 Bicom Systems Ltd, (bicomsystems.com)
+ *
+ * Author: Seudin Kasumovic (seudin.kasumovic at gmail.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include "../../ver.h"
+#include "../../sr_module.h"
+#include "../../pt.h"
+#include "../../cfg/cfg_struct.h"
+#include "../../mod_fix.h"
+#include "../../script_cb.h"
+
+#ifndef USE_TCP
+#error	"USE_TCP must be enabled for this module"
+#endif
+
+#include "../../pass_fd.h"
+
+#include "mod_erlang.h"
+#include "erl_helpers.h"
+#include "cnode.h"
+#include "handle_rpc.h"
+
+#include "pv_xbuff.h"
+#include "pv_tuple.h"
+#include "pv_atom.h"
+#include "pv_list.h"
+#include "pv_pid.h"
+#include "pv_ref.h"
+
+MODULE_VERSION
+
+/* module exports */
+static int child_init(int rank);
+static int mod_init(void);
+static void mod_destroy(void);
+static int postprocess_request(struct sip_msg *msg, unsigned int flags, void *_param);
+
+/*  exported functions */
+static int erl_rpc(struct sip_msg *msg, char *module, char *function, char *args, char *reply);
+static int erl_reg_send_k(struct sip_msg *msg, char *_server, char *_emsg);
+static int erl_send_k(struct sip_msg *msg, char *_server, char *_emsg);
+static int erl_reply_k(struct sip_msg *msg, char *_emsg);
+
+/* fix-ups */
+static int fixup_rpc(void** param, int param_no);
+static int fixup_send(void** param, int param_no);
+static int fixup_reg(void** param, int param_no);
+static int fixup_reply(void** param, int param_no);
+
+/* initialize common vars */
+str cookie = STR_NULL;
+int trace_level = 0;
+str cnode_alivename = STR_NULL;
+str cnode_host = STR_NULL;
+int no_cnodes=1;
+int rpc_reply_with_struct = 0;
+
+str erlang_nodename  = STR_NULL;
+str erlang_node_sname = STR_NULL;
+
+int *usocks[2];
+int csockfd;
+
+handler_common_t* io_handlers = NULL;
+
+erl_api_t erl_api;
+
+static pv_export_t pvs[] = {
+		{
+				{ "erl_tuple", (sizeof("erl_tuple")-1) },
+				PVT_OTHER,
+				pv_tuple_get,
+				pv_tuple_set,
+				pv_xbuff_parse_name,
+				0,
+				0,
+				0
+		},
+		{
+				{ "erl_atom", (sizeof("erl_atom")-1) },
+				PVT_OTHER,
+				pv_atom_get,
+				pv_atom_set,
+				pv_atom_parse_name,
+				0,
+				0,
+				0
+		},
+		{
+				{ "erl_list", (sizeof("erl_list")-1) },
+				PVT_OTHER,
+				pv_list_get,
+				pv_list_set,
+				pv_xbuff_parse_name,
+				0,
+				0,
+				0
+		},
+		{
+				{ "erl_xbuff", (sizeof("erl_xbuff")-1) },
+				PVT_OTHER,
+				pv_xbuff_get,
+				pv_xbuff_set,
+				pv_xbuff_parse_name,
+				0,
+				0,
+				0
+		},
+		{
+				{ "erl_pid", (sizeof("erl_pid")-1) },
+				PVT_OTHER,
+				pv_pid_get,
+				pv_pid_set,
+				pv_pid_parse_name,
+				0,
+				0,
+				0
+		},
+		{
+				{ "erl_ref", (sizeof("erl_ref")-1) },
+				PVT_OTHER,
+				pv_ref_get,
+				pv_ref_set,
+				pv_ref_parse_name,
+				0,
+				0,
+				0
+		},
+		{{0,0}, 0, 0, 0, 0, 0, 0, 0}
+};
+
+/* exported parameters */
+static param_export_t parameters[] =
+{
+		/* Kamailo C node parameters */
+		{ "no_cnodes", PARAM_INT, &no_cnodes },
+		{ "cnode_alivename", PARAM_STR, &cnode_alivename },
+		{ "cnode_host", PARAM_STR, &cnode_host },
+
+		/* Erlang node parameters */
+		{ "erlang_nodename", PARAM_STR, &erlang_nodename },
+		{ "erlang_node_sname", PARAM_STR, &erlang_node_sname },
+
+		{ "cookie", PARAM_STR, &cookie },
+		{ "trace_level", PARAM_INT, &trace_level }, /* tracing level on the distribution */
+		{ "rpc_reply_with_struct", PARAM_INT, &rpc_reply_with_struct},
+		{ 0, 0, 0 }
+};
+
+/* exported commands */
+
+static cmd_export_t commands[] =
+{
+		{"erl_rpc", (cmd_function)erl_rpc, 4, fixup_rpc, 0, ANY_ROUTE},
+		{"erl_send", (cmd_function)erl_send_k, 2, fixup_send, 0, ANY_ROUTE},
+		{"erl_reg_send", (cmd_function)erl_reg_send_k, 2, fixup_reg, 0, ANY_ROUTE},
+		{"erl_reply", (cmd_function)erl_reply_k, 1, fixup_reply, 0, EVENT_ROUTE},
+		{"load_erl",(cmd_function)load_erl,0, 0,         0,         0}, /* API loader */
+		{ 0, 0, 0, 0, 0, 0 }
+};
+
+
+struct module_exports exports = {
+		"erlang",
+		DEFAULT_DLFLAGS,
+		commands,
+		parameters,
+		NULL,
+		NULL,
+		pvs,
+		NULL,
+		mod_init,
+		NULL,
+		mod_destroy,
+		child_init
+};
+
+/**
+ * \brief Initialize Erlang module
+ */
+static int mod_init(void)
+{
+	/* check required parameters */
+
+	if (!cookie.s || cookie.len == 0)
+	{
+		LM_CRIT("Erlang cookie parameter is required\n");
+		return -1;
+	}
+	cookie.s[cookie.len]=0;
+
+	if ((!erlang_nodename.s || erlang_nodename.len == 0)
+			&& (!erlang_node_sname.s || erlang_node_sname.len == 0)) {
+		LM_CRIT("Erlang node name is required\n");
+		return -1;
+	}
+	if (erlang_nodename.s) {
+		erlang_nodename.s[erlang_nodename.len]=0;
+	}
+	if (erlang_node_sname.s) {
+		erlang_node_sname.s[erlang_node_sname.len]=0;
+	}
+
+	if (!cnode_alivename.s || !cnode_alivename.len) {
+		LM_CRIT("Kamailio C node alive name is required\n");
+		return -1;
+	}
+	cnode_alivename.s[cnode_alivename.len]=0;
+
+	if (!cnode_host.s || !cnode_host.len) {
+		LM_WARN("Kamailio host name is not set, trying with gethostname...\n");
+		return -1;
+	}
+
+	if (erl_load_api(&erl_api)) {
+		LM_CRIT("failed to load erl API\n");
+		return -1;
+	}
+
+	if (compile_xbuff_re()) {
+		return -1;
+	}
+
+	if (register_script_cb(postprocess_request, POST_SCRIPT_CB | REQUEST_CB, 0)
+			!= 0)
+	{
+		LOG(L_CRIT, "could not register request post processing call back.\n");
+		return -1;
+	}
+
+	/* init RPC handler for Erlang calls */
+	init_rpc_handlers();
+
+	/* add space for extra processes */
+	register_procs(no_cnodes);
+
+	/* add child to update local config framework structures */
+	cfg_register_child(no_cnodes);
+
+	return 0;
+}
+
+#define MAX_CNODE_DESC_LEN (MAXNODELEN + sizeof("Erlang C node "))
+
+/**
+ * \brief Initialize Erlang module children
+ */
+static int child_init(int rank)
+{
+	char _cnode_desc[MAX_CNODE_DESC_LEN];
+	int pair[2], data[2];
+	int i,j,pid;
+
+	if (rank == PROC_INIT) {
+
+#ifdef SHM_MEM
+		usocks[KSOCKET]=(int*)shm_malloc(sizeof(int)*no_cnodes);
+		if (!usocks[KSOCKET]) {
+			LM_ERR("Not enough memory\n");
+			return -1;
+		}
+
+		usocks[CSOCKET]=(int*)shm_malloc(sizeof(int)*no_cnodes);
+		if (!usocks[CSOCKET]) {
+			LM_ERR("Not enough memory\n");
+			return -1;
+		}
+#else
+		usocks[KSOCKET]=(int*)pkg_malloc(sizeof(int)*no_cnodes);
+		if (!usocks[KSOCKET]) {
+			LM_ERR("Not enough memory\n");
+			return -1;
+		}
+
+		usocks[CSOCKET]=(int*)pkg_malloc(sizeof(int)*no_cnodes);
+		if (!usocks[CSOCKET]) {
+			LM_ERR("Not enough memory\n");
+			return -1;
+		}
+#endif
+
+		for(i=0;i<no_cnodes;i++) {
+			if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair)) {
+				LOG(L_CRIT,"failed create socket pair: %s. -- don't start -- \n", strerror(errno));
+				return -1;
+			}
+			usocks[KSOCKET][i]=pair[KSOCKET];
+			usocks[CSOCKET][i]=pair[CSOCKET];
+		}
+
+		return 0;
+	}
+
+	if (rank == PROC_MAIN) {
+		for (j=0; j<no_cnodes; j++) {
+
+			snprintf(_cnode_desc, MAX_CNODE_DESC_LEN, "%s%.*s%d@%.*s", "Erlang C Node ", STR_FMT(&cnode_alivename), j+1, STR_FMT(&cnode_host));
+
+			if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair)) {
+				LOG(L_CRIT,"failed create socket pair: %s. -- don't start -- \n", strerror(errno));
+				return -1;
+			}
+
+			if ((pid = fork_process(PROC_NOCHLDINIT, _cnode_desc, 0)) == -1) {
+				return -1; /* error -- don't start -- */
+			} else if (pid == 0) {
+				/* child */
+				if(cfg_child_init()) {
+					LM_CRIT("failed cfg_child_init\n");
+					return -1;
+				}
+
+				for (i=0;i<no_cnodes;i++)
+				{
+					close(usocks[KSOCKET][i]);
+					if (i!=j) close(usocks[CSOCKET][i]);
+				}
+
+				csockfd = usocks[CSOCKET][j];
+
+				/* enter Erlang C Node main loop (cnode process) */
+				cnode_main_loop(j);
+
+				LM_CRIT("failed to start Erlang C node main loop!\n");
+
+				return -1;
+			}
+
+			/* parent */
+		}
+
+		return 0;
+	}
+
+	for (i=0;i<no_cnodes;i++) {
+		close(usocks[CSOCKET][i]);
+	}
+
+	if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair)) {
+		LOG(L_CRIT,"failed create socket pair: %s. -- don't start -- \n", strerror(errno));
+		return -1;
+	}
+
+	data[0] = pair[CSOCKET];
+	data[1] = my_pid();
+
+	if (send_fd(usocks[KSOCKET][process_no % no_cnodes],(void*)&data,sizeof(data),pair[CSOCKET])==-1) {
+		LM_CRIT("failed to send socket %d over socket %d to cnode\n",pair[CSOCKET],usocks[KSOCKET][process_no % no_cnodes]);
+		return -1;
+	}
+
+	csockfd = pair[KSOCKET];
+
+	erl_set_nonblock(csockfd);
+
+	erl_init_common();
+
+	for (i=0;i<no_cnodes;i++) {
+		close(usocks[KSOCKET][i]);
+	}
+
+	return 0;
+}
+
+/**
+ * @brief Destroy module allocated resources
+ */
+static void mod_destroy(void)
+{
+#ifdef SHM_MEM
+		shm_free(usocks[0]);
+		shm_free(usocks[1]);
+#else
+		pkg_free(usocks[0]);
+		pkg_free(usocks[1]);
+#endif
+		free_tuple_fmt_buff();
+		free_atom_fmt_buff();
+		free_list_fmt_buff();
+		free_xbuff_fmt_buff();
+		free_pid_fmt_buff();
+		free_ref_fmt_buff();
+}
+
+static int postprocess_request(struct sip_msg *msg, unsigned int flags, void *_param)
+{
+	free_tuple_fmt_buff();
+	free_atom_fmt_buff();
+	free_list_fmt_buff();
+	free_xbuff_fmt_buff();
+	free_pid_fmt_buff();
+	free_ref_fmt_buff();
+	return 0;
+}
+
+/**
+ * Erlang RPC.
+ */
+static int erl_rpc(struct sip_msg *msg, char *_m, char *_f, char *_a, char *_r)
+{
+	erl_param_t *m=(erl_param_t*)_m;
+	erl_param_t *f=(erl_param_t*)_f;
+	erl_param_t *a=(erl_param_t*)_a;
+	erl_param_t *r=(erl_param_t*)_r;
+
+	str module;
+	str function;
+	str vname;
+	sr_xavp_t *xreq=NULL;
+	sr_xavp_t *xrepl=NULL;
+	pv_spec_t sp;
+	pv_spec_t *nsp = NULL;
+	pv_param_t  pvp;
+	pv_name_t *pvn;
+	pv_index_t *pvi;
+	int idx;
+	int idxf;
+	int attr;
+	ei_x_buff ei_req;
+	ei_x_buff ei_rep;
+
+	switch (m->type) {
+	case ERL_PARAM_FPARAM:
+		if(get_str_fparam(&module,msg,&m->value.fp)) {
+			LM_ERR("can't get module name\n");
+		}
+		break;
+	default:
+		LM_ERR("unexpected type for module name parameter\n");
+		return -1;
+	}
+
+	switch (f->type) {
+	case ERL_PARAM_FPARAM:
+		if(get_str_fparam(&function,msg,&f->value.fp)) {
+			LM_ERR("can't get function name\n");
+		}
+		break;
+	default:
+		LM_ERR("unexpected type for function name parameter\n");
+		return -1;
+	}
+
+	switch(a->type){
+	case ERL_PARAM_FPARAM:
+		if(get_str_fparam(&vname,msg,&a->value.fp)){
+			LM_ERR("can't get name of arguments parameter\n");
+			return -1;
+		}
+		xreq = pv_list_get_list(&vname);
+		if (!xreq){
+			xreq = pv_xbuff_get_xbuff(&vname);
+		}
+		if (!xreq) {
+			LM_ERR("can't find variable $list(%.*s) nor $xbuff(%.*s)",STR_FMT(&vname),STR_FMT(&vname));
+			return -1;
+		}
+		break;
+	case ERL_PARAM_XBUFF_SPEC:
+		sp = a->value.sp;
+		pvp = sp.pvp; /* work on copy */
+
+		if (pvp.pvn.type != PV_NAME_INTSTR || !(pvp.pvn.u.isname.type & AVP_NAME_STR)) {
+			LM_ERR("unsupported name of list\n");
+			return -1;
+		}
+
+		if( pvp.pvn.type == PV_NAME_PVAR) {
+			nsp = pvp.pvn.u.dname;
+		}
+
+		if (nsp) {
+			pvi = &nsp->pvp.pvi;
+			pvn = &nsp->pvp.pvn;
+		} else {
+			pvi = &pvp.pvi;
+			pvn = &pvp.pvn;
+		}
+
+		if (sp.setf == pv_list_set ) {
+			xreq = pv_list_get_list(&pvn->u.isname.name.s);
+		} else if (sp.setf == pv_xbuff_set) {
+			xreq = pv_xbuff_get_xbuff(&pvn->u.isname.name.s);
+		}  else if (sp.setf == pv_tuple_set) {
+			xreq = pv_tuple_get_tuple(&pvn->u.isname.name.s);
+		}
+
+		/* fix index */
+		attr = xbuff_get_attr_flags(pvi->type);
+		pvi->type = xbuff_fix_index(pvi->type);
+
+		/* get the index */
+		if(pv_get_spec_index(msg, &pvp, &idx, &idxf))
+		{
+			LM_ERR("invalid index\n");
+			return -1;
+		}
+
+		if (xbuff_is_attr_set(attr)) {
+			LM_WARN("attribute is not expected here!\n");
+		}
+
+		if (!xreq) {
+			LM_ERR("undefined variable '%.*s'\n",STR_FMT(&pvn->u.isname.name.s));
+			return -1;
+		}
+
+		xreq = xreq->val.v.xavp;
+
+		if ((idxf != PV_IDX_ALL) && !xbuff_is_no_index(attr) ) {
+			xreq = xavp_get_nth(&xreq->val.v.xavp,idx,NULL);
+		}
+
+		if (!xreq) {
+			LM_ERR("undefined value in '%.*s' at index %d\n",STR_FMT(&pvn->u.isname.name.s),idx);
+			return -1;
+		}
+
+		if (xreq->val.type != SR_XTYPE_XAVP || xreq->name.s[0] != 'l') {
+			LM_ERR("given value in parameter args is not list\n");
+			return -1;
+		}
+		break;
+	default:
+		LM_ERR("unexpected type for arguments parameter\n");
+		return -1;
+	}
+
+	switch(r->type){
+	case ERL_PARAM_FPARAM:
+		if(get_str_fparam(&vname,msg,&r->value.fp)){
+			LM_ERR("can't get name of arguments parameter\n");
+			return -1;
+		}
+		xrepl = pv_xbuff_get_xbuff(&vname);
+		break;
+	case ERL_PARAM_XBUFF_SPEC:
+		sp = r->value.sp;
+		pvp = sp.pvp; /* work on copy */
+
+		if (pvp.pvn.type != PV_NAME_INTSTR || !(pvp.pvn.u.isname.type & AVP_NAME_STR)) {
+			LM_ERR("unsupported name of xbuff\n");
+			return -1;
+		}
+
+		if( pvp.pvn.type == PV_NAME_PVAR) {
+			nsp = pvp.pvn.u.dname;
+		}
+
+		if (nsp) {
+			pvi = &nsp->pvp.pvi;
+			pvn = &nsp->pvp.pvn;
+		} else {
+			pvi = &pvp.pvi;
+			pvn = &pvp.pvn;
+		}
+
+		if (sp.setf == pv_xbuff_set ) {
+			xrepl = pv_xbuff_get_xbuff(&pvn->u.isname.name.s);
+		} else {
+			LM_ERR("unsupported variable type, xbuff only\n");
+			return -1;
+		}
+
+		/* fix index */
+		attr = xbuff_get_attr_flags(pvi->type);
+		pvi->type = xbuff_fix_index(pvi->type);
+
+		/* get the index */
+		if(pv_get_spec_index(msg, &pvp, &idx, &idxf))
+		{
+			LM_ERR("invalid index\n");
+			return -1;
+		}
+
+		if (xbuff_is_attr_set(attr)) {
+			LM_WARN("attribute is not expected here!\n");
+		}
+
+		if ((idxf != PV_IDX_ALL) && !xbuff_is_no_index(attr) ) {
+			LM_ERR("index is not expected here!\n");
+			return -1;
+		}
+
+		break;
+	default:
+		LM_ERR("unexpected type for arguments parameter\n");
+		return -1;
+	}
+
+	/* note: new without version byte */
+	ei_x_new(&ei_req);
+
+	/* ei_x_buff <- XAVP */
+	if (erl_api.xavp2xbuff(&ei_req,xreq)) {
+		LM_ERR("failed to encode\n");
+		ei_x_free(&ei_req);
+		return -1;
+	}
+
+	memset((void*)&ei_rep,0,sizeof(ei_x_buff));
+
+	erl_api.rpc(&ei_rep,&module,&function,&ei_req);
+
+	if (xrepl) {
+		xavp_destroy_list(&xrepl->val.v.xavp);
+	} else {
+		xrepl = xbuff_new(&pvn->u.isname.name.s);
+	}
+
+	/* must be XAVP */
+	xrepl->val.type = SR_XTYPE_XAVP;
+
+	/* XAVP <- ei_x_buff */
+	if (erl_api.xbuff2xavp(&xrepl->val.v.xavp,&ei_rep)){
+		LM_ERR("failed to decode\n");
+		ei_x_free(&ei_req);
+		ei_x_free(&ei_rep);
+		return -1;
+	}
+
+	ei_x_free(&ei_req);
+	ei_x_free(&ei_rep);
+
+	return 1;
+}
+
+static int fixup_rpc(void** param, int param_no)
+{
+	erl_param_t *erl_param;
+
+	str s;
+
+	erl_param=(erl_param_t*)pkg_malloc(sizeof(erl_param_t));
+	if(!erl_param) {
+		LM_ERR("no more memory\n");
+		return -1;
+	}
+	memset(erl_param,0,sizeof(erl_param_t));
+
+	if(param_no==1 || param_no==2) {
+		if (fix_param_types(FPARAM_STR|FPARAM_STRING|FPARAM_AVP|FPARAM_PVS|FPARAM_PVE,param)){
+			LM_ERR("wrong parameter #%d\n",param_no);
+			return -1;
+		}
+		erl_param->type = ERL_PARAM_FPARAM;
+		erl_param->value.fp = *(fparam_t*)*param;
+	}
+
+	if (param_no==3 || param_no==4) {
+
+		s.s = (char*)*param; s.len = strlen(s.s);
+
+		if (pv_parse_avp_name(&erl_param->value.sp,&s)) {
+			LM_ERR("failed to parse parameter #%d\n",param_no);
+			pkg_free((void*)erl_param);
+			return E_UNSPEC;
+		}
+
+		if (erl_param->value.sp.pvp.pvn.type == PV_NAME_INTSTR) {
+			if (fix_param_types(FPARAM_STR|FPARAM_STRING,param)) {
+				LM_ERR("wrong parameter #%d\n",param_no);
+				pkg_free((void*)erl_param);
+				return E_UNSPEC;
+			}
+			erl_param->type = ERL_PARAM_FPARAM;
+			erl_param->value.fp = *(fparam_t*)*param;
+		} else if(pv_parse_spec( &s, &erl_param->value.sp)==NULL || erl_param->value.sp.type!=PVT_OTHER) {
+
+			/* only XBUFF is accepted for args and reply */
+			LM_ERR("wrong parameter #%d: accepted types are list of xbuff\n",param_no);
+			pv_spec_free(&erl_param->value.sp);
+			pkg_free((void*)erl_param);
+			return E_UNSPEC;
+		} else {
+			/* lets check what is acceptable */
+			if (erl_param->value.sp.setf != pv_list_set && erl_param->value.sp.setf != pv_xbuff_set) {
+				LM_ERR("wrong parameter #%d: accepted types are list of xbuff\n",param_no);
+				pkg_free((void*)erl_param);
+				return E_UNSPEC;
+			}
+			erl_param->type = ERL_PARAM_XBUFF_SPEC;
+		}
+	}
+
+	*param = (void*)erl_param;
+
+	return 0;
+}
+
+static int erl_reg_send_k(struct sip_msg *msg, char *_server, char *_emsg)
+{
+	erl_param_t *param_server=(erl_param_t*)_server;
+	erl_param_t *param_emsg=(erl_param_t*)_emsg;
+
+	str server;
+	str str_msg;
+	sr_xavp_t *xmsg=NULL;
+	pv_spec_t sp;
+	pv_spec_t *nsp = NULL;
+	pv_param_t  pvp;
+	pv_name_t *pvn;
+	pv_index_t *pvi;
+	int idx;
+	int idxf;
+	int attr;
+	ei_x_buff ei_msg;
+
+	switch (param_server->type) {
+	case ERL_PARAM_FPARAM:
+		if(get_str_fparam(&server,msg,&param_server->value.fp)) {
+			LM_ERR("can't get server process name\n");
+		}
+		break;
+	default:
+		LM_ERR("unexpected type for server name parameter\n");
+		return -1;
+	}
+
+	ei_x_new_with_version(&ei_msg);
+
+	switch(param_emsg->type){
+	case ERL_PARAM_FPARAM:
+		if(get_str_fparam(&str_msg,msg,&param_emsg->value.fp)){
+			LM_ERR("can't get emsg parameter\n");
+			goto err;
+		}
+
+		ei_x_encode_string_len(&ei_msg,str_msg.s,str_msg.len);
+
+		break;
+	case ERL_PARAM_XBUFF_SPEC:
+		sp = param_emsg->value.sp;
+		pvp = sp.pvp; /* work on copy */
+
+		if (pvp.pvn.type != PV_NAME_INTSTR || !(pvp.pvn.u.isname.type & AVP_NAME_STR)) {
+			LM_ERR("unsupported name of list\n");
+			return -1;
+		}
+
+		if( pvp.pvn.type == PV_NAME_PVAR) {
+			nsp = pvp.pvn.u.dname;
+		}
+
+		if (nsp) {
+			pvi = &nsp->pvp.pvi;
+			pvn = &nsp->pvp.pvn;
+		} else {
+			pvi = &pvp.pvi;
+			pvn = &pvp.pvn;
+		}
+
+		if (sp.setf == pv_list_set ) {
+			xmsg = pv_list_get_list(&pvn->u.isname.name.s);
+		} else if (sp.setf == pv_xbuff_set) {
+			xmsg = pv_xbuff_get_xbuff(&pvn->u.isname.name.s);
+		}  else if (sp.setf == pv_tuple_set) {
+			xmsg = pv_tuple_get_tuple(&pvn->u.isname.name.s);
+		}
+
+		/* fix index */
+		attr = xbuff_get_attr_flags(pvi->type);
+		pvi->type = xbuff_fix_index(pvi->type);
+
+		/* get the index */
+		if(pv_get_spec_index(msg, &pvp, &idx, &idxf))
+		{
+			LM_ERR("invalid index\n");
+			return -1;
+		}
+
+		if (xbuff_is_attr_set(attr)) {
+			LM_WARN("attribute is not expected here!\n");
+		}
+
+		if (!xmsg) {
+			LM_ERR("undefined variable '%.*s'\n",STR_FMT(&pvn->u.isname.name.s));
+			return -1;
+		}
+
+		xmsg = xmsg->val.v.xavp;
+
+		if ((idxf != PV_IDX_ALL) && !xbuff_is_no_index(attr) ) {
+			xmsg = xavp_get_nth(&xmsg->val.v.xavp,idx,NULL);
+		}
+
+		if (!xmsg) {
+			LM_ERR("undefined value in '%.*s' at index %d\n",STR_FMT(&pvn->u.isname.name.s),idx);
+			goto err;
+		}
+
+		/* ei_x_buff <- XAVP */
+		if (erl_api.xavp2xbuff(&ei_msg,xmsg)) {
+			LM_ERR("failed to encode %.*s\n",STR_FMT(&pvn->u.isname.name.s));
+			goto err;
+		}
+
+		break;
+	default:
+		LM_ERR("unexpected type for emsg parameter\n");
+		return -1;
+	}
+
+	if (erl_api.reg_send(&server,&ei_msg)) {
+		goto err;
+	}
+
+	ei_x_free(&ei_msg);
+
+	return 1;
+
+err:
+	ei_x_free(&ei_msg);
+
+	return -1;
+}
+
+static int fixup_reg(void** param, int param_no)
+{
+	erl_param_t *erl_param;
+
+	str s;
+
+	erl_param=(erl_param_t*)pkg_malloc(sizeof(erl_param_t));
+
+	if(!erl_param) {
+		LM_ERR("no more memory\n");
+		return -1;
+	}
+
+	memset(erl_param,0,sizeof(erl_param_t));
+
+	if(param_no==1) {
+		if (fix_param_types(FPARAM_STR|FPARAM_STRING|FPARAM_AVP|FPARAM_PVS|FPARAM_PVE|FPARAM_INT,param)){
+			LM_ERR("wrong parameter #%d\n",param_no);
+			return -1;
+		}
+		erl_param->type = ERL_PARAM_FPARAM;
+		erl_param->value.fp = *(fparam_t*)*param;
+	}
+
+	if (param_no==2) {
+
+		s.s = (char*)*param; s.len = strlen(s.s);
+
+		if (pv_parse_avp_name(&erl_param->value.sp,&s)) {
+			LM_ERR("failed to parse parameter #%d\n",param_no);
+			pkg_free((void*)erl_param);
+			return E_UNSPEC;
+		}
+
+		if (erl_param->value.sp.pvp.pvn.type == PV_NAME_INTSTR) {
+			if (fix_param_types(FPARAM_STR|FPARAM_STRING,param)) {
+				LM_ERR("wrong parameter #%d\n",param_no);
+				pkg_free((void*)erl_param);
+				return E_UNSPEC;
+			}
+			erl_param->type = ERL_PARAM_FPARAM;
+			erl_param->value.fp = *(fparam_t*)*param;
+		} else if(pv_parse_spec( &s, &erl_param->value.sp)==NULL) {
+
+			/* only XBUFF is accepted for emsg and reply */
+			LM_ERR("wrong parameter #%d\n",param_no);
+			pv_spec_free(&erl_param->value.sp);
+			pkg_free((void*)erl_param);
+			return E_UNSPEC;
+		} else {
+			if (erl_param->value.sp.type ==PVT_XAVP) {
+				LM_ERR("XAVP not acceptable for parameter #%d\n",param_no);
+				pkg_free((void*)erl_param);
+				return E_UNSPEC;
+			}
+
+			if (erl_param->value.sp.setf == pv_list_set
+					|| erl_param->value.sp.setf == pv_xbuff_set
+					|| erl_param->value.sp.setf == pv_tuple_set
+					|| erl_param->value.sp.setf == pv_atom_set) {
+
+				erl_param->type = ERL_PARAM_XBUFF_SPEC;
+			} else {
+				erl_param->type = ERL_PARAM_FPARAM;
+				erl_param->value.fp = *(fparam_t*)*param;
+			}
+		}
+	}
+
+	*param = (void*)erl_param;
+
+	return 0;
+}
+
+static int erl_reply_k(struct sip_msg *msg, char *_emsg)
+{
+	erl_param_t *param_emsg=(erl_param_t*)_emsg;
+
+	str str_msg;
+	sr_xavp_t *xmsg=NULL;
+	pv_spec_t sp;
+	pv_spec_t *nsp = NULL;
+	pv_param_t  pvp;
+	pv_name_t *pvn;
+	pv_index_t *pvi;
+	int idx;
+	int idxf;
+	int attr;
+	ei_x_buff ei_msg;
+
+	ei_x_new_with_version(&ei_msg);
+
+	switch(param_emsg->type){
+	case ERL_PARAM_FPARAM:
+		if(get_str_fparam(&str_msg,msg,&param_emsg->value.fp)){
+			LM_ERR("can't get emsg parameter\n");
+			goto err;
+		}
+
+		ei_x_encode_string_len(&ei_msg,str_msg.s,str_msg.len);
+
+		break;
+	case ERL_PARAM_XBUFF_SPEC:
+		sp = param_emsg->value.sp;
+		pvp = sp.pvp; /* work on copy */
+
+		if (pvp.pvn.type != PV_NAME_INTSTR || !(pvp.pvn.u.isname.type & AVP_NAME_STR)) {
+			LM_ERR("unsupported name of list\n");
+			return -1;
+		}
+
+		if( pvp.pvn.type == PV_NAME_PVAR) {
+			nsp = pvp.pvn.u.dname;
+		}
+
+		if (nsp) {
+			pvi = &nsp->pvp.pvi;
+			pvn = &nsp->pvp.pvn;
+		} else {
+			pvi = &pvp.pvi;
+			pvn = &pvp.pvn;
+		}
+
+		if (sp.setf == pv_list_set ) {
+			xmsg = pv_list_get_list(&pvn->u.isname.name.s);
+		} else if (sp.setf == pv_xbuff_set) {
+			xmsg = pv_xbuff_get_xbuff(&pvn->u.isname.name.s);
+		}  else if (sp.setf == pv_tuple_set) {
+			xmsg = pv_tuple_get_tuple(&pvn->u.isname.name.s);
+		}
+
+		/* fix index */
+		attr = xbuff_get_attr_flags(pvi->type);
+		pvi->type = xbuff_fix_index(pvi->type);
+
+		/* get the index */
+		if(pv_get_spec_index(msg, &pvp, &idx, &idxf))
+		{
+			LM_ERR("invalid index\n");
+			return -1;
+		}
+
+		if (xbuff_is_attr_set(attr)) {
+			LM_WARN("attribute is not expected here!\n");
+		}
+
+		if (!xmsg) {
+			LM_ERR("undefined variable '%.*s'\n",STR_FMT(&pvn->u.isname.name.s));
+			return -1;
+		}
+
+		xmsg = xmsg->val.v.xavp;
+
+		if ((idxf != PV_IDX_ALL) && !xbuff_is_no_index(attr) ) {
+			xmsg = xavp_get_nth(&xmsg->val.v.xavp,idx,NULL);
+		}
+
+		if (!xmsg) {
+			LM_ERR("undefined value in '%.*s' at index %d\n",STR_FMT(&pvn->u.isname.name.s),idx);
+			goto err;
+		}
+
+		/* ei_x_buff <- XAVP */
+		if (erl_api.xavp2xbuff(&ei_msg,xmsg)) {
+			LM_ERR("failed to encode %.*s\n",STR_FMT(&pvn->u.isname.name.s));
+			goto err;
+		}
+
+		break;
+	default:
+		LM_ERR("unexpected type for emsg parameter\n");
+		return -1;
+	}
+
+	if (erl_api.reply(&ei_msg)) {
+		goto err;
+	}
+
+	ei_x_free(&ei_msg);
+
+	return 1;
+
+err:
+	ei_x_free(&ei_msg);
+
+	return -1;
+}
+
+static int fixup_reply(void** param, int param_no)
+{
+	erl_param_t *erl_param;
+
+	str s;
+
+	erl_param=(erl_param_t*)pkg_malloc(sizeof(erl_param_t));
+
+	if(!erl_param) {
+		LM_ERR("no more memory\n");
+		return -1;
+	}
+
+	memset(erl_param,0,sizeof(erl_param_t));
+
+	if (param_no==1) {
+
+		s.s = (char*)*param; s.len = strlen(s.s);
+
+		if (pv_parse_avp_name(&erl_param->value.sp,&s)) {
+			LM_ERR("failed to parse parameter #%d\n",param_no);
+			pkg_free((void*)erl_param);
+			return E_UNSPEC;
+		}
+
+		if (erl_param->value.sp.pvp.pvn.type == PV_NAME_INTSTR) {
+			if (fix_param_types(FPARAM_STR|FPARAM_STRING,param)) {
+				LM_ERR("wrong parameter #%d\n",param_no);
+				pkg_free((void*)erl_param);
+				return E_UNSPEC;
+			}
+			erl_param->type = ERL_PARAM_FPARAM;
+			erl_param->value.fp = *(fparam_t*)*param;
+		} else if(pv_parse_spec( &s, &erl_param->value.sp)==NULL) {
+
+			/* only XBUFF is accepted for emsg and reply */
+			LM_ERR("wrong parameter #%d\n",param_no);
+			pv_spec_free(&erl_param->value.sp);
+			pkg_free((void*)erl_param);
+			return E_UNSPEC;
+		} else {
+			if (erl_param->value.sp.type ==PVT_XAVP) {
+				LM_ERR("XAVP not acceptable for parameter #%d\n",param_no);
+				pkg_free((void*)erl_param);
+				return E_UNSPEC;
+			}
+
+			if (erl_param->value.sp.setf == pv_list_set
+					|| erl_param->value.sp.setf == pv_xbuff_set
+					|| erl_param->value.sp.setf == pv_tuple_set
+					|| erl_param->value.sp.setf == pv_atom_set) {
+
+				erl_param->type = ERL_PARAM_XBUFF_SPEC;
+			} else {
+				erl_param->type = ERL_PARAM_FPARAM;
+				erl_param->value.fp = *(fparam_t*)*param;
+			}
+		}
+	}
+
+	*param = (void*)erl_param;
+
+	return 0;
+}
+
+static int erl_send_k(struct sip_msg *msg, char *_pid, char *_emsg)
+{
+	erl_param_t *param_pid=(erl_param_t*)_pid;
+	erl_param_t *param_emsg=(erl_param_t*)_emsg;
+
+	str str_msg;
+	sr_xavp_t *xmsg=NULL;
+	pv_spec_t sp;
+	pv_spec_t *nsp = NULL;
+	pv_param_t  pvp;
+	pv_name_t *pvn;
+	pv_index_t *pvi;
+	int idx;
+	int idxf;
+	int attr;
+	ei_x_buff ei_msg;
+	erlang_pid *pid;
+
+	switch (param_pid->type) {
+	case ERL_PARAM_XBUFF_SPEC:
+		sp = param_pid->value.sp;
+		pvp = sp.pvp; /* work on copy */
+
+		if (pvp.pvn.type != PV_NAME_INTSTR || !(pvp.pvn.u.isname.type & AVP_NAME_STR)) {
+			LM_ERR("unsupported name of pid\n");
+			return -1;
+		}
+
+		if( pvp.pvn.type == PV_NAME_PVAR) {
+			nsp = pvp.pvn.u.dname;
+		}
+
+		if (nsp) {
+			pvi = &nsp->pvp.pvi;
+			pvn = &nsp->pvp.pvn;
+		} else {
+			pvi = &pvp.pvi;
+			pvn = &pvp.pvn;
+		}
+
+		if (sp.getf == pv_pid_get ) {
+			xmsg = pv_pid_get_pid(&pvn->u.isname.name.s);
+		} else if (sp.getf == pv_xbuff_get) {
+			xmsg = pv_xbuff_get_xbuff(&pvn->u.isname.name.s);
+		} else {
+			LM_ERR("BUG: unexpected type for pid parameter\n");
+			return -1;
+		}
+
+		/* fix index */
+		attr = xbuff_get_attr_flags(pvi->type);
+		pvi->type = xbuff_fix_index(pvi->type);
+
+		/* get the index */
+		if(pv_get_spec_index(msg, &pvp, &idx, &idxf))
+		{
+			LM_ERR("invalid index\n");
+			return -1;
+		}
+
+		if (xbuff_is_attr_set(attr)) {
+			LM_WARN("attribute is not expected here!\n");
+		}
+
+		if (!xmsg) {
+			LM_ERR("undefined variable '%.*s'\n",STR_FMT(&pvn->u.isname.name.s));
+			return -1;
+		}
+
+		xmsg = xmsg->val.v.xavp;
+
+		if ((idxf != PV_IDX_ALL) && !xbuff_is_no_index(attr) ) {
+			xmsg = xavp_get_nth(&xmsg->val.v.xavp,idx,NULL);
+		}
+
+		if (!xmsg) {
+			LM_ERR("undefined value in '%.*s' at index %d\n",STR_FMT(&pvn->u.isname.name.s),idx);
+			goto err;
+		}
+
+		/* erlang_pid <- XAVP */
+		if (xmsg->name.s[0] == 'p' && xmsg->val.type == SR_XTYPE_DATA && xmsg->val.v.data) {
+			pid = xmsg->val.v.data->p;
+		} else {
+			LM_ERR("invalid value for pid parameter\n");
+			return -1;
+		}
+		break;
+	default:
+		LM_ERR("unexpected type for pid parameter\n");
+		return -1;
+	}
+
+	ei_x_new_with_version(&ei_msg);
+
+	switch(param_emsg->type){
+	case ERL_PARAM_FPARAM:
+		if(get_str_fparam(&str_msg,msg,&param_emsg->value.fp)){
+			LM_ERR("can't get emsg parameter\n");
+			goto err;
+		}
+
+		ei_x_encode_string_len(&ei_msg,str_msg.s,str_msg.len);
+
+		break;
+	case ERL_PARAM_XBUFF_SPEC:
+		sp = param_emsg->value.sp;
+		pvp = sp.pvp; /* work on copy */
+
+		if (pvp.pvn.type != PV_NAME_INTSTR || !(pvp.pvn.u.isname.type & AVP_NAME_STR)) {
+			LM_ERR("unsupported name of list\n");
+			return -1;
+		}
+
+		if( pvp.pvn.type == PV_NAME_PVAR) {
+			nsp = pvp.pvn.u.dname;
+		}
+
+		if (nsp) {
+			pvi = &nsp->pvp.pvi;
+			pvn = &nsp->pvp.pvn;
+		} else {
+			pvi = &pvp.pvi;
+			pvn = &pvp.pvn;
+		}
+
+		if (sp.getf == pv_list_get ) {
+			xmsg = pv_list_get_list(&pvn->u.isname.name.s);
+		} else if (sp.getf == pv_xbuff_get) {
+			xmsg = pv_xbuff_get_xbuff(&pvn->u.isname.name.s);
+		} else if (sp.getf == pv_tuple_get) {
+			xmsg = pv_tuple_get_tuple(&pvn->u.isname.name.s);
+		} else if (sp.getf == pv_atom_get) {
+			xmsg = pv_atom_get_atom(&pvn->u.isname.name.s);
+		} else if (sp.getf == pv_pid_get) {
+			xmsg = pv_pid_get_pid(&pvn->u.isname.name.s);
+		}
+
+		/* fix index */
+		attr = xbuff_get_attr_flags(pvi->type);
+		pvi->type = xbuff_fix_index(pvi->type);
+
+		/* get the index */
+		if(pv_get_spec_index(msg, &pvp, &idx, &idxf))
+		{
+			LM_ERR("invalid index\n");
+			return -1;
+		}
+
+		if (xbuff_is_attr_set(attr)) {
+			LM_WARN("attribute is not expected here!\n");
+		}
+
+		if (!xmsg) {
+			LM_ERR("undefined variable '%.*s'\n",STR_FMT(&pvn->u.isname.name.s));
+			return -1;
+		}
+
+		xmsg = xmsg->val.v.xavp;
+
+		if ((idxf != PV_IDX_ALL) && !xbuff_is_no_index(attr) ) {
+			xmsg = xavp_get_nth(&xmsg->val.v.xavp,idx,NULL);
+		}
+
+		if (!xmsg) {
+			LM_ERR("undefined value in '%.*s' at index %d\n",STR_FMT(&pvn->u.isname.name.s),idx);
+			goto err;
+		}
+
+		/* ei_x_buff <- XAVP */
+		if (erl_api.xavp2xbuff(&ei_msg,xmsg)) {
+			LM_ERR("failed to encode %.*s\n",STR_FMT(&pvn->u.isname.name.s));
+			goto err;
+		}
+
+		break;
+	default:
+		LM_ERR("unexpected type for emsg parameter\n");
+		return -1;
+	}
+
+	if (erl_api.send(pid,&ei_msg)) {
+		goto err;
+	}
+
+	ei_x_free(&ei_msg);
+
+	return 1;
+
+err:
+	ei_x_free(&ei_msg);
+
+	return -1;
+}
+
+static int fixup_send(void** param, int param_no)
+{
+	erl_param_t *erl_param;
+
+	str s;
+
+	erl_param=(erl_param_t*)pkg_malloc(sizeof(erl_param_t));
+
+	if(!erl_param) {
+		LM_ERR("no more memory\n");
+		return -1;
+	}
+
+	memset(erl_param,0,sizeof(erl_param_t));
+
+	if (param_no==1) {
+
+		s.s = (char*)*param; s.len = strlen(s.s);
+
+		if (pv_parse_avp_name(&erl_param->value.sp,&s)) {
+			LM_ERR("failed to parse parameter #%d\n",param_no);
+			pkg_free((void*)erl_param);
+			return E_UNSPEC;
+		}
+
+		if (erl_param->value.sp.pvp.pvn.type == PV_NAME_INTSTR) {
+			if (fix_param_types(FPARAM_STR|FPARAM_STRING,param)) {
+				LM_ERR("wrong parameter #%d\n",param_no);
+				pkg_free((void*)erl_param);
+				return E_UNSPEC;
+			}
+			erl_param->type = ERL_PARAM_FPARAM;
+			erl_param->value.fp = *(fparam_t*)*param;
+		} else if(pv_parse_spec( &s, &erl_param->value.sp)==NULL) {
+
+			/* only XBUFF is accepted for emsg */
+			LM_ERR("wrong parameter #%d\n",param_no);
+			pv_spec_free(&erl_param->value.sp);
+			pkg_free((void*)erl_param);
+			return E_UNSPEC;
+		} else {
+			if (erl_param->value.sp.type ==PVT_XAVP) {
+				LM_ERR("XAVP not acceptable for parameter #%d\n",param_no);
+				pkg_free((void*)erl_param);
+				return E_UNSPEC;
+			}
+
+			if (erl_param->value.sp.getf == pv_pid_get
+					|| erl_param->value.sp.getf == pv_xbuff_get) {
+				erl_param->type = ERL_PARAM_XBUFF_SPEC;
+			} else {
+				erl_param->type = ERL_PARAM_FPARAM;
+				erl_param->value.fp = *(fparam_t*)*param;
+			}
+		}
+	}
+
+	if (param_no==2) {
+
+		s.s = (char*)*param; s.len = strlen(s.s);
+
+		if (pv_parse_avp_name(&erl_param->value.sp,&s)) {
+			LM_ERR("failed to parse parameter #%d\n",param_no);
+			pkg_free((void*)erl_param);
+			return E_UNSPEC;
+		}
+
+		if (erl_param->value.sp.pvp.pvn.type == PV_NAME_INTSTR) {
+			if (fix_param_types(FPARAM_STR|FPARAM_STRING,param)) {
+				LM_ERR("wrong parameter #%d\n",param_no);
+				pkg_free((void*)erl_param);
+				return E_UNSPEC;
+			}
+			erl_param->type = ERL_PARAM_FPARAM;
+			erl_param->value.fp = *(fparam_t*)*param;
+		} else if(pv_parse_spec( &s, &erl_param->value.sp)==NULL) {
+
+			/* only XBUFF is accepted for emsg */
+			LM_ERR("wrong parameter #%d\n",param_no);
+			pv_spec_free(&erl_param->value.sp);
+			pkg_free((void*)erl_param);
+			return E_UNSPEC;
+		} else {
+			if (erl_param->value.sp.type ==PVT_XAVP) {
+				LM_ERR("XAVP not acceptable for parameter #%d\n",param_no);
+				pkg_free((void*)erl_param);
+				return E_UNSPEC;
+			}
+
+			if (erl_param->value.sp.getf == pv_list_get
+					|| erl_param->value.sp.getf == pv_xbuff_get
+					|| erl_param->value.sp.getf == pv_tuple_get
+					|| erl_param->value.sp.getf == pv_atom_get
+					|| erl_param->value.sp.getf == pv_pid_get) {
+
+				erl_param->type = ERL_PARAM_XBUFF_SPEC;
+			} else {
+				erl_param->type = ERL_PARAM_FPARAM;
+				erl_param->value.fp = *(fparam_t*)*param;
+			}
+		}
+	}
+
+	*param = (void*)erl_param;
+
+	return 0;
+}
diff --git a/modules/erlang/mod_erlang.h b/modules/erlang/mod_erlang.h
new file mode 100644
index 0000000..34b06a6
--- /dev/null
+++ b/modules/erlang/mod_erlang.h
@@ -0,0 +1,77 @@
+/**
+ * Copyright (C) 2015 Bicom Systems Ltd, (bicomsystems.com)
+ *
+ * Author: Seudin Kasumovic (seudin.kasumovic at gmail.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef MOD_ERLANG_H_
+#define MOD_ERLANG_H_
+
+#include "../../str.h"
+#include "../../pvar.h"
+#include "../../xavp.h"
+#include "erl_api.h"
+
+extern str cookie; /* Erlang cookie */
+extern int trace_level; /* Tracing level on the distribution */
+extern str cnode_alivename;
+extern str cnode_host;
+extern int no_cnodes;
+extern int rpc_reply_with_struct;
+
+extern str erlang_nodename;
+extern str erlang_node_sname;
+
+/* sockets kamailio <-> cnode */
+extern int *usocks[2];
+
+extern int csockfd; /* socket to cnode process */
+
+#define KSOCKET	0
+#define CSOCKET	1
+
+/**
+ * types of command parameter
+ */
+typedef enum {
+	ERL_PARAM_FPARAM,
+	ERL_PARAM_XBUFF_SPEC
+} erl_param_type;
+
+/**
+ * command parameter
+ *
+ * combine str and PV
+ */
+typedef struct erl_param_s {
+	erl_param_type type;
+	union {
+		fparam_t fp;
+		pv_spec_t sp;
+	} value;
+} erl_param_t;
+
+/**
+ * Erlang ei bind
+ */
+
+extern erl_api_t erl_api;
+
+#endif /* MOD_ERLANG_H_ */
diff --git a/modules/erlang/pv_atom.c b/modules/erlang/pv_atom.c
new file mode 100644
index 0000000..9adad47
--- /dev/null
+++ b/modules/erlang/pv_atom.c
@@ -0,0 +1,348 @@
+/**
+ * Copyright (C) 2015 Bicom Systems Ltd, (bicomsystems.com)
+ *
+ * Author: Seudin Kasumovic (seudin.kasumovic at gmail.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <stdlib.h>
+
+#include "../../str.h"
+#include "../../xavp.h"
+#include "../../pvapi.h"
+
+#include "pv_atom.h"
+#include "pv_xbuff.h"
+
+#include <ei.h>
+
+static str atom_list=str_init("[atoms]");
+static char *atom_fmt_buff = NULL;
+static int counter;
+
+int pv_atom_parse_name(pv_spec_t *sp, str *in)
+{
+	char *p;
+	str idx;
+	str name;
+	str attr;
+	int l;
+
+	if (in->s == NULL || in->len <= 0)
+		return -1;
+
+	p = in->s;
+
+	name.s = p;
+
+	while (is_in_str(p, in)) {
+		if (*p == '[' || *p== '=')
+			break;
+		if (!is_pv_xbuff_valid_char(*p)) {
+			l = p-in->s;
+			LM_ERR("invalid character in var name %.*s at %d\n",STR_FMT(in),l);
+			goto error;
+		}
+		p++;
+	}
+
+	/* from in->s to p */
+	name.len = p - in->s;
+
+	if (pv_parse_avp_name(sp,&name))
+		goto error;
+
+	if (is_in_str(p,in) && *p =='[')
+	{
+		idx.s=++p;
+
+		while (is_in_str(p,in)) {
+			if (*p == ']' || *p == '=')
+				break;
+			p++;
+		}
+
+		if (is_in_str(p,in) && *p==']') {
+			idx.len = p - idx.s;
+
+			LM_ERR("index isn't allowed for this variable\n");
+			goto error;
+		}
+		p++;
+	} else {
+		xbuff_set_attr_flag(sp->pvp.pvi.type,XBUFF_NO_IDX);
+	}
+
+	if (is_in_str(p,in) && *p =='=')
+	{
+		p++;
+
+		if (!is_in_str(p,in) || *p!='>') {
+			l = p-in->s;
+			LM_ERR("invalid operator (expected =>) for accessing attribute in token %.*s at position %d\n",STR_FMT(in),l);
+			goto error;
+		}
+
+		attr.s = ++p;
+
+		while (is_in_str(p,in)) {
+			if (!is_pv_xbuff_valid_char(*p)) {
+				l = p-in->s;
+				LM_ERR("invalid character in attribute name in token %.*s at %d\n",STR_FMT(in),l);
+				goto error;
+			}
+			p++;
+		}
+
+		attr.len = p - attr.s;
+
+		if (attr.len > 0 ) {
+
+			if (STR_EQ(attr,xbuff_attr_name(XBUFF_ATTR_TYPE))) {
+				xbuff_set_attr_flag(sp->pvp.pvi.type,XBUFF_ATTR_TYPE);
+			} else if (STR_EQ(attr,xbuff_attr_name(XBUFF_ATTR_FORMAT))) {
+				xbuff_set_attr_flag(sp->pvp.pvi.type,XBUFF_ATTR_FORMAT);
+			} else if (STR_EQ(attr,xbuff_attr_name(XBUFF_ATTR_LENGTH))) {
+				LM_ERR("attribute isn't supported for this variable\n");
+				goto error;
+			} else {
+				LM_ERR("unknown attribute %.*s\n",STR_FMT(&attr));
+				goto error;
+			}
+		}
+	}
+
+	if (p < in->s + in->len) {
+		l = p-in->s;
+		LM_ERR("unexpected token in %.*s at %d\n",STR_FMT(in),l);
+		goto error;
+	}
+
+	return 0;
+
+error:
+
+	return -1;
+}
+
+sr_xavp_t *xavp_get_atoms()
+{
+	sr_xavp_t *list;
+	list = xavp_get(&atom_list,NULL);
+
+	if(!list) counter = 0;
+
+	return list;
+}
+
+sr_xavp_t *pv_atom_get_atom(str *name)
+{
+	return xavp_get_child(&atom_list, name);
+}
+
+int pv_atom_set(struct sip_msg* msg,  pv_param_t* param, int op, pv_value_t* val)
+{
+	str name;
+	sr_xavp_t *atoms_root;
+	sr_xavp_t *atom;
+	sr_xavp_t *new,*old=NULL;
+	sr_xavp_t *atom_xavp;
+	sr_xval_t atom_val;
+
+	if (param->pvn.type != PV_NAME_INTSTR || !(param->pvn.u.isname.type & AVP_NAME_STR)) {
+		LM_ERR("invalid variable name type\n");
+		return -1;
+	}
+
+	if(pv_xbuff_new_xavp(&atom_xavp,val,&counter,'a')) {
+		LM_ERR("failed to create new value\n");
+		return -1;
+	}
+
+	/* atom name */
+	name = param->pvn.u.isname.name.s;
+
+	memset((void*)&atom_val,0,sizeof(sr_xval_t));
+
+	atoms_root = xavp_get_atoms();
+
+	if(!atoms_root) {
+
+		atom_val.type = SR_XTYPE_XAVP;
+		atom_val.v.xavp = atom_xavp;
+		atom = xavp_add_xavp_value(&atom_list,&name,&atom_val,xavp_get_crt_list());
+
+		if (!atom)
+			goto err;
+
+		return 0;
+	}
+
+	atom = xavp_get_child(&atom_list, &name);
+
+	if (!atom) {
+
+		atom_val.type = SR_XTYPE_XAVP;
+		atom_val.v.xavp = atom_xavp;
+
+		new = xavp_add_value(&name,&atom_val,&atoms_root->val.v.xavp);
+
+		if (!new)
+			goto err;
+
+		return 0;
+	}
+
+	old = atom->val.v.xavp;
+	new = atom_xavp;
+
+	if (old) {
+		xavp_destroy_list(&old);
+	}
+
+	atom->val.v.xavp = new;
+
+	return 0;
+
+err:
+	LM_ERR("failed to set atom value\n");
+	xavp_destroy_list(&atom_xavp);
+
+	return -1;
+}
+
+int pv_atom_get_value(struct sip_msg *msg, pv_param_t *param,
+		pv_value_t *res, sr_xavp_t *avp)
+{
+	static char _pv_xavp_buf[128];
+	str s;
+
+	if (!avp) return pv_get_null(msg,param,res);
+
+	switch(avp->val.type) {
+	case SR_XTYPE_NULL:
+		return pv_get_null(msg, param, res);
+		break;
+	case SR_XTYPE_STR:
+		if(snprintf(_pv_xavp_buf, 128, "<<atom:%p>>", avp)<0)
+			return pv_get_null(msg, param, res);
+		break;
+	case SR_XTYPE_XAVP:
+		if(snprintf(_pv_xavp_buf, 128, "<<atom:%p>>", avp->val.v.xavp)<0)
+			return pv_get_null(msg, param, res);
+		break;
+	case SR_XTYPE_DATA:
+	case SR_XTYPE_INT:
+	case SR_XTYPE_TIME:
+	case SR_XTYPE_LONG:
+	case SR_XTYPE_LLONG:
+		LM_ERR("BUG: unexpected atom value\n");
+		return pv_get_null(msg, param, res);
+		break;
+	default:
+		return pv_get_null(msg, param, res);
+	}
+	s.s = _pv_xavp_buf;
+	s.len = strlen(_pv_xavp_buf);
+	return pv_get_strval(msg, param, res, &s);
+}
+
+int pv_atom_get(struct sip_msg* msg,  pv_param_t* param, pv_value_t* res)
+{
+	str name;
+	sr_xavp_t *atoms_root;
+	sr_xavp_t *atom;
+	sr_xavp_t *xavp;
+	int attr;
+	int i;
+
+	ei_x_buff xbuff;
+
+	if(param==NULL)
+	{
+		LM_ERR("bad parameters\n");
+		return -1;
+	}
+
+	if (param->pvn.type != PV_NAME_INTSTR || !(param->pvn.u.isname.type & AVP_NAME_STR))
+				return -1;
+
+	/* tuple name */
+	name = param->pvn.u.isname.name.s;
+	/* attributes */
+	attr = xbuff_get_attr_flags(param->pvi.type);
+
+	atoms_root = xavp_get_atoms();
+	if(!atoms_root) {
+		return pv_get_null(msg,param,res);
+	}
+
+	atom = xavp_get(&name,atoms_root->val.v.xavp);
+	if (!atom) {
+		return pv_get_null(msg,param,res);
+	}
+
+	xavp = atom->val.v.xavp;
+
+	switch (xbuff_is_attr_set(attr)) {
+	case XBUFF_ATTR_TYPE:
+		return pv_get_strval(msg,param,res,&xbuff_types[XBUFF_TYPE_ATOM]);
+		break;
+	case XBUFF_ATTR_LENGTH: /* always 1 */
+		return pv_get_uintval(msg,param,res,1);
+		break;
+	case XBUFF_ATTR_FORMAT:
+		/*
+		 * Prints a term, in clear text, to the PV value pointed to by res.
+		 * It tries to resemble the term printing in the erlang shell.
+		 */
+		ei_x_new_with_version(&xbuff);
+		if (xavp && xavp_encode(&xbuff,xavp,1)) {
+			ei_x_free(&xbuff);
+			return -1;
+		} else {
+			ei_x_encode_atom(&xbuff,"undefined");
+		}
+		i = 1;
+		if (ei_s_print_term(&atom_fmt_buff,xbuff.buff,&i)<0) {
+			LM_ERR("BUG: xbuff[index] doesn't contain a valid term!\n");
+			ei_x_free(&xbuff);
+			return -1;
+		}
+		i = pv_get_strzval(msg,param,res,atom_fmt_buff);
+		ei_x_free(&xbuff);
+		return i;
+	}
+
+	if (!xavp) {
+		return pv_get_null(msg,param,res);
+	}
+
+	return pv_atom_get_value(msg,param,res,xavp);
+}
+
+/*
+ * free format buffer for tuple
+ */
+void free_atom_fmt_buff() {
+	if (atom_fmt_buff) {
+		free(atom_fmt_buff);
+	}
+	atom_fmt_buff = 0;
+}
diff --git a/modules/erlang/pv_atom.h b/modules/erlang/pv_atom.h
new file mode 100644
index 0000000..fdd30cf
--- /dev/null
+++ b/modules/erlang/pv_atom.h
@@ -0,0 +1,37 @@
+/**
+ * Copyright (C) 2015 Bicom Systems Ltd, (bicomsystems.com)
+ *
+ * Author: Seudin Kasumovic (seudin.kasumovic at gmail.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef PV_ATOM_H_
+#define PV_ATOM_H_
+
+#include "../../pvar.h"
+int pv_atom_parse_name(pv_spec_t *sp, str *in);
+
+int pv_atom_set(struct sip_msg*, pv_param_t*, int, pv_value_t*);
+int pv_atom_get(struct sip_msg*, pv_param_t*, pv_value_t*);
+
+void free_atom_fmt_buff();
+
+sr_xavp_t *pv_atom_get_atom(str *name);
+
+#endif /* PV_ATOM_H_ */
diff --git a/modules/erlang/pv_list.c b/modules/erlang/pv_list.c
new file mode 100644
index 0000000..cd109a2
--- /dev/null
+++ b/modules/erlang/pv_list.c
@@ -0,0 +1,395 @@
+/**
+ * Copyright (C) 2015 Bicom Systems Ltd, (bicomsystems.com)
+ *
+ * Author: Seudin Kasumovic (seudin.kasumovic at gmail.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <stdlib.h>
+
+#include "../../pvar.h"
+
+#include "pv_list.h"
+#include "pv_xbuff.h"
+
+static str list_list=str_init("[lists]");
+
+static int counter;
+static char *list_fmt_buff = NULL;
+
+sr_xavp_t *xavp_get_lists()
+{
+	sr_xavp_t *list;
+	list = xavp_get(&list_list,NULL);
+
+	if(!list) counter = 0;
+
+	return list;
+}
+
+sr_xavp_t *pv_list_get_list(str *name)
+{
+	return xavp_get_child(&list_list, name);
+}
+
+int pv_list_set(struct sip_msg* msg,  pv_param_t* param, int op, pv_value_t* val)
+{
+	str name;
+	sr_xavp_t *lists_root;
+	sr_xavp_t *list;
+	sr_xavp_t *lh,*new,*old,*prv=NULL;
+	sr_xavp_t *list_xavp;
+	sr_xavp_t *item_xavp;
+	sr_xval_t list_val;
+	pv_param_t p;
+	pv_value_t empty;
+	int idx = 0;
+	int idxf = 0;
+	int attr = 0;
+
+	if (param->pvn.type != PV_NAME_INTSTR || !(param->pvn.u.isname.type & AVP_NAME_STR)) {
+		LM_ERR("invalid variable name type\n");
+		return -1;
+	}
+
+	memset((void*)&empty,0,sizeof(pv_value_t));
+	empty.flags = PV_VAL_NULL;
+
+	/* list name */
+	name = param->pvn.u.isname.name.s;
+
+	lists_root = xavp_get_lists();
+
+	if(!lists_root) {
+
+		if(pv_xbuff_new_xavp(&list_xavp,&empty,&counter,'l')) {
+			LM_ERR("failed to create new value\n");
+			return -1;
+		}
+
+		list_val.type = SR_XTYPE_XAVP;
+		list_val.v.xavp = list_xavp;
+		list = xavp_add_xavp_value(&list_list,&name,&list_val,xavp_get_crt_list());
+
+		if (!list)
+			goto err;
+	}
+
+	list=xavp_get_child(&list_list, &name);
+
+	if (!list) {
+
+		if(pv_xbuff_new_xavp(&list_xavp,&empty,&counter,'l')) {
+			LM_ERR("failed to create new value\n");
+			return -1;
+		}
+
+		list_val.type = SR_XTYPE_XAVP;
+		list_val.v.xavp = list_xavp;
+
+		list=xavp_add_value(&name,&list_val,&lists_root->val.v.xavp);
+
+		if (!list)
+			goto err;
+	}
+
+	lh = list->val.v.xavp;
+
+	if(pv_xbuff_new_xavp(&item_xavp,val,&counter,0)) {
+		LM_ERR("failed to create new value\n");
+		return -1;
+	}
+
+	/* work on copy of index! */
+	p = *param;
+
+	/* fix index */
+	attr = xbuff_get_attr_flags(p.pvi.type);
+	p.pvi.type = xbuff_fix_index(p.pvi.type);
+
+	/* get the index */
+	if(pv_get_spec_index(msg, &p, &idx, &idxf))
+	{
+		LM_ERR("invalid index\n");
+		return -1;
+	}
+
+	if (xbuff_is_attr_set(attr)) {
+		LM_ERR("read only attribute %.*s\n",STR_FMT(&xbuff_attr_name(attr)));
+		return -1;
+	}
+
+	/* prepend on list when no index */
+	if (xbuff_is_no_index(attr)) {
+		if (lh->val.type == SR_XTYPE_NULL) {
+			lh->val.type = SR_XTYPE_XAVP;
+			lh->val.v.xavp = item_xavp;
+			return 0;
+		} else {
+			return xavp_add(item_xavp,&lh->val.v.xavp);
+		}
+	}
+
+	if (idxf == PV_IDX_ALL) {
+		xavp_destroy_list(&lh->val.v.xavp);
+		if (item_xavp->val.type == SR_XTYPE_NULL) {
+			/* create empty list */
+			xavp_destroy_list(&item_xavp);
+
+			memset((void*)&lh->val,0,sizeof(sr_xval_t));
+			lh->val.type = SR_XTYPE_NULL;
+			return 0;
+		} else {
+			return xavp_add(item_xavp,&lh->val.v.xavp);
+		}
+	}
+
+	/* set by index */
+	old = xavp_get_nth(&lh->val.v.xavp,idx,&prv);
+	new = item_xavp;
+
+	if (old) {
+		new->next = old->next;
+		if (prv) {
+			prv->next = new;
+		} else {
+			new->next = old->next;
+			lh->val.v.xavp = new;
+		}
+		old->next = NULL;
+		xavp_destroy_list(&old);
+	} else {
+		if (prv) {
+			prv->next = new;
+		} else {
+			lh->val.v.xavp = new;
+		}
+	}
+
+	return 0;
+
+err:
+	LM_ERR("failed to add value into list\n");
+	xavp_destroy_list(&list_xavp);
+	xavp_destroy_list(&item_xavp);
+
+	return -1;
+}
+
+int pv_list_get_value(struct sip_msg *msg, pv_param_t *param,
+		pv_value_t *res, sr_xavp_t *avp)
+{
+	static char _pv_xavp_buf[128];
+	str s;
+
+	if (!avp) return pv_get_null(msg,param,res);
+
+	switch(avp->val.type) {
+	case SR_XTYPE_NULL:
+		return pv_get_null(msg, param, res);
+		break;
+	case SR_XTYPE_INT:
+		return pv_get_sintval(msg, param, res, avp->val.v.i);
+		break;
+	case SR_XTYPE_STR:
+		switch (avp->name.s[0]) {
+		case 'a':
+			if(snprintf(_pv_xavp_buf, 128, "<<atom:%p>>", avp->val.v.xavp)<0)
+				return pv_get_null(msg, param, res);
+			break;
+		default:
+			return pv_get_strval(msg, param, res, &avp->val.v.s);
+		}
+		break;
+	case SR_XTYPE_TIME:
+		if(snprintf(_pv_xavp_buf, 128, "%lu", (long unsigned)avp->val.v.t)<0)
+			return pv_get_null(msg, param, res);
+		break;
+	case SR_XTYPE_LONG:
+		if(snprintf(_pv_xavp_buf, 128, "%ld", (long unsigned)avp->val.v.l)<0)
+			return pv_get_null(msg, param, res);
+		break;
+	case SR_XTYPE_LLONG:
+		if(snprintf(_pv_xavp_buf, 128, "%lld", avp->val.v.ll)<0)
+			return pv_get_null(msg, param, res);
+		break;
+	case SR_XTYPE_XAVP:
+		switch(avp->name.s[0]) {
+		case 't':
+			if(snprintf(_pv_xavp_buf, 128, "<<tuple:%p>>", avp->val.v.xavp)<0)
+				return pv_get_null(msg, param, res);
+			break;
+		case 'l':
+		default:
+			if(snprintf(_pv_xavp_buf, 128, "<<list:%p>>", avp->val.v.xavp)<0)
+				return pv_get_null(msg, param, res);
+		}
+		break;
+	case SR_XTYPE_DATA:
+		if (avp->name.s[0] == 'p') {
+			if(snprintf(_pv_xavp_buf, 128, "<<pid:%p>>", avp->val.v.data)<0)
+				return pv_get_null(msg, param, res);
+		} else if(snprintf(_pv_xavp_buf, 128, "<<binary:%p>>", avp->val.v.data)<0)
+			return pv_get_null(msg, param, res);
+		break;
+	default:
+		return pv_get_null(msg, param, res);
+	}
+	s.s = _pv_xavp_buf;
+	s.len = strlen(_pv_xavp_buf);
+	return pv_get_strval(msg, param, res, &s);
+}
+
+int pv_list_get(struct sip_msg* msg,  pv_param_t* param, pv_value_t* res)
+{
+	str name;
+	pv_spec_t *nsp = NULL;
+	pv_name_t *pvn;
+	pv_index_t *pvi;
+	sr_xavp_t *lists_root;
+	sr_xavp_t *list;
+	sr_xavp_t *lh;
+	sr_xavp_t *xavp;
+	pv_param_t p;
+	int idx=0;
+	int idxf=0;
+	int attr;
+	int i,count;
+
+	ei_x_buff xbuff;
+
+	if(param==NULL)
+	{
+		LM_ERR("bad parameters\n");
+		return -1;
+	}
+
+	if (param->pvn.type != PV_NAME_INTSTR || !(param->pvn.u.isname.type & AVP_NAME_STR))
+				return -1;
+
+	if( param->pvn.type == PV_NAME_PVAR) {
+			nsp = param->pvn.u.dname;
+	}
+
+	/* work on copy of index! */
+	p = *param;
+
+	if (nsp) {
+		pvi = &nsp->pvp.pvi;
+		pvn = &nsp->pvp.pvn;
+	} else {
+		pvi = &p.pvi;
+		pvn = &p.pvn;
+	}
+
+	/* list name */
+	name = pvn->u.isname.name.s;
+
+	/* fix index */
+	attr = xbuff_get_attr_flags(pvi->type);
+	pvi->type = xbuff_fix_index(pvi->type);
+
+	/* get the index */
+	if(pv_get_spec_index(msg, &p, &idx, &idxf))
+	{
+		LM_ERR("invalid index\n");
+		return -1;
+	}
+
+	lists_root = xavp_get_lists();
+	if(!lists_root) {
+		return pv_get_null(msg,param,res);
+	}
+
+	list = xavp_get(&name,lists_root->val.v.xavp);
+	if (!list) {
+		return pv_get_null(msg,param,res);
+	}
+
+	lh = list->val.v.xavp;
+
+	switch (xbuff_is_attr_set(attr)) {
+	case XBUFF_ATTR_TYPE:
+		if (xbuff_is_no_index(attr)) {
+			return pv_get_strval(msg,param,res,&xbuff_types[XBUFF_TYPE_LIST]);
+		} else {
+			xavp = xavp_get_nth(&lh->val.v.xavp,idx,NULL);
+			return pv_xbuff_get_type(msg,param,res,xavp);
+		}
+		break;
+	case XBUFF_ATTR_LENGTH:
+		xavp = xbuff_is_no_index(attr) ? lh : xavp_get_nth(&lh->val.v.xavp,idx,NULL);
+
+		if (xavp) {
+			count = xavp_get_count(xavp->val.v.xavp);
+			return pv_get_uintval(msg,param,res,(unsigned int)count);
+		} else {
+			return pv_get_null(msg,param,res);
+		}
+		break;
+	case XBUFF_ATTR_FORMAT:
+		/*
+		 * Prints a term, in clear text, to the PV value pointed to by res.
+		 * It tries to resemble the term printing in the erlang shell.
+		 */
+		ei_x_new_with_version(&xbuff);
+
+		xavp = xbuff_is_no_index(attr) ? lh : xavp_get_nth(&lh->val.v.xavp,idx,NULL);
+		if (!xavp || xavp_encode(&xbuff,xavp,1)) {
+			ei_x_free(&xbuff);
+			return -1;
+		}
+		i = 1;
+		if (ei_s_print_term(&list_fmt_buff,xbuff.buff,&i)<0) {
+			LM_ERR("BUG: xbuff[index] doesn't contain a valid term!\n");
+			ei_x_free(&xbuff);
+			return -1;
+		}
+		i = pv_get_strzval(msg,param,res,list_fmt_buff);
+		ei_x_free(&xbuff);
+		return i;
+	}
+
+	/* get whole list */
+	if ((idxf == PV_IDX_ALL) || xbuff_is_no_index(attr)) {
+		return pv_list_get_value(msg,param,res,list);
+	}
+
+	if (lh->val.type == SR_XTYPE_NULL) {
+		return pv_get_null(msg,param,res);
+	}
+
+	/* get by idx */
+	xavp = xavp_get_nth(&lh->val.v.xavp,idx,NULL);
+	if (!xavp) {
+		return pv_get_null(msg,param,res);
+	}
+
+	return pv_list_get_value(msg,param,res,xavp);
+}
+
+/*
+ * free format buffer for list
+ */
+void free_list_fmt_buff() {
+	if (list_fmt_buff) {
+		free(list_fmt_buff);
+	}
+	list_fmt_buff = 0;
+}
diff --git a/modules/erlang/pv_list.h b/modules/erlang/pv_list.h
new file mode 100644
index 0000000..f65f9ed
--- /dev/null
+++ b/modules/erlang/pv_list.h
@@ -0,0 +1,36 @@
+/**
+ * Copyright (C) 2015 Bicom Systems Ltd, (bicomsystems.com)
+ *
+ * Author: Seudin Kasumovic (seudin.kasumovic at gmail.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+#ifndef PV_LIST_H_
+#define PV_LIST_H_
+
+#include "../../pvar.h"
+#include "../../xavp.h"
+
+int pv_list_set(struct sip_msg*, pv_param_t*, int, pv_value_t*);
+int pv_list_get(struct sip_msg*, pv_param_t*, pv_value_t*);
+
+sr_xavp_t *pv_list_get_list(str *name);
+
+void free_list_fmt_buff();
+
+#endif /* PV_LIST_H_ */
diff --git a/modules/erlang/pv_pid.c b/modules/erlang/pv_pid.c
new file mode 100644
index 0000000..4266b02
--- /dev/null
+++ b/modules/erlang/pv_pid.c
@@ -0,0 +1,343 @@
+/**
+ * Copyright (C) 2015 Bicom Systems Ltd, (bicomsystems.com)
+ *
+ * Author: Seudin Kasumovic (seudin.kasumovic at gmail.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <stdlib.h>
+
+#include "../../str.h"
+#include "../../xavp.h"
+#include "../../pvapi.h"
+
+#include "pv_pid.h"
+#include "pv_xbuff.h"
+
+static str pid_list=str_init("[pids]");
+static char *pid_fmt_buff = NULL;
+static int counter;
+
+sr_xavp_t *pv_pid_get_pid(str *name)
+{
+	return xavp_get_child(&pid_list,name);
+}
+
+int pv_pid_parse_name(pv_spec_t *sp, str *in)
+{
+	char *p;
+	str idx;
+	str name;
+	str attr;
+	int l;
+
+	if (in->s == NULL || in->len <= 0)
+		return -1;
+
+	p = in->s;
+
+	name.s = p;
+
+	while (is_in_str(p, in)) {
+		if (*p == '[' || *p== '=')
+			break;
+		if (!is_pv_xbuff_valid_char(*p)) {
+			l = p-in->s;
+			LM_ERR("invalid character in var name %.*s at %d\n",STR_FMT(in),l);
+			goto error;
+		}
+		p++;
+	}
+
+	/* from in->s to p */
+	name.len = p - in->s;
+
+	if (pv_parse_avp_name(sp,&name))
+		goto error;
+
+	if (is_in_str(p,in) && *p =='[')
+	{
+		idx.s=++p;
+
+		while (is_in_str(p,in)) {
+			if (*p == ']' || *p == '=')
+				break;
+			p++;
+		}
+
+		if (is_in_str(p,in) && *p==']') {
+			idx.len = p - idx.s;
+
+			LM_ERR("index isn't allowed for this variable\n");
+			goto error;
+		}
+		p++;
+	} else {
+		xbuff_set_attr_flag(sp->pvp.pvi.type,XBUFF_NO_IDX);
+	}
+
+	if (is_in_str(p,in) && *p =='=')
+	{
+		p++;
+
+		if (!is_in_str(p,in) || *p!='>') {
+			l = p-in->s;
+			LM_ERR("invalid operator (expected =>) for accessing attribute in token %.*s at position %d\n",STR_FMT(in),l);
+			goto error;
+		}
+
+		attr.s = ++p;
+
+		while (is_in_str(p,in)) {
+			if (!is_pv_xbuff_valid_char(*p)) {
+				l = p-in->s;
+				LM_ERR("invalid character in attribute name in token %.*s at %d\n",STR_FMT(in),l);
+				goto error;
+			}
+			p++;
+		}
+
+		attr.len = p - attr.s;
+
+		if (attr.len > 0 ) {
+
+			if (STR_EQ(attr,xbuff_attr_name(XBUFF_ATTR_TYPE))) {
+				xbuff_set_attr_flag(sp->pvp.pvi.type,XBUFF_ATTR_TYPE);
+			} else if (STR_EQ(attr,xbuff_attr_name(XBUFF_ATTR_FORMAT))) {
+				xbuff_set_attr_flag(sp->pvp.pvi.type,XBUFF_ATTR_FORMAT);
+			} else if (STR_EQ(attr,xbuff_attr_name(XBUFF_ATTR_LENGTH))) {
+				LM_ERR("attribute isn't supported for this variable\n");
+				goto error;
+			} else {
+				LM_ERR("unknown attribute %.*s\n",STR_FMT(&attr));
+				goto error;
+			}
+		}
+	}
+
+	if (p < in->s + in->len) {
+		l = p-in->s;
+		LM_ERR("unexpected token in %.*s at %d\n",STR_FMT(in),l);
+		goto error;
+	}
+
+	return 0;
+
+error:
+
+	return -1;
+}
+
+sr_xavp_t *xavp_get_pids()
+{
+	sr_xavp_t *list;
+	list = xavp_get(&pid_list,NULL);
+
+	if(!list) counter = 0;
+
+	return list;
+}
+
+int pv_pid_set(struct sip_msg* msg,  pv_param_t* param, int op, pv_value_t* val)
+{
+	str name;
+	sr_xavp_t *pid_root;
+	sr_xavp_t *pid;
+	sr_xavp_t *new,*old=NULL;
+	sr_xavp_t *pid_xavp;
+	sr_xval_t pid_val;
+
+	if (param->pvn.type != PV_NAME_INTSTR || !(param->pvn.u.isname.type & AVP_NAME_STR)) {
+		LM_ERR("invalid variable name type\n");
+		return -1;
+	}
+
+	if(pv_xbuff_new_xavp(&pid_xavp,val,&counter,'p')) {
+		LM_ERR("failed to create new value\n");
+		return -1;
+	}
+
+	/* pid var name */
+	name = param->pvn.u.isname.name.s;
+
+	memset((void*)&pid_val,0,sizeof(sr_xval_t));
+
+	pid_root = xavp_get_pids();
+
+	if(!pid_root) {
+
+		pid_val.type = SR_XTYPE_XAVP;
+		pid_val.v.xavp = pid_xavp;
+		pid = xavp_add_xavp_value(&pid_list,&name,&pid_val,xavp_get_crt_list());
+
+		if (!pid)
+			goto err;
+
+		return 0;
+	}
+
+	pid = xavp_get_child(&pid_list, &name);
+
+	if (!pid) {
+
+		pid_val.type = SR_XTYPE_XAVP;
+		pid_val.v.xavp = pid_xavp;
+
+		new = xavp_add_value(&name,&pid_val,&pid_root->val.v.xavp);
+
+		if (!new)
+			goto err;
+
+		return 0;
+	}
+
+	old = pid->val.v.xavp;
+	new = pid_xavp;
+
+	if (old) {
+		xavp_destroy_list(&old);
+	}
+
+	pid->val.v.xavp = new;
+
+	return 0;
+
+err:
+	LM_ERR("failed to set pid value\n");
+	xavp_destroy_list(&pid_xavp);
+
+	return -1;
+}
+
+int pv_pid_get_value(struct sip_msg *msg, pv_param_t *param,
+		pv_value_t *res, sr_xavp_t *avp)
+{
+	static char _pv_xavp_buf[128];
+	str s;
+
+	if (!avp) return pv_get_null(msg,param,res);
+
+	switch(avp->val.type) {
+	case SR_XTYPE_NULL:
+		return pv_get_null(msg, param, res);
+		break;
+	case SR_XTYPE_DATA:
+		if(snprintf(_pv_xavp_buf, 128, "<<pid:%p>>", avp->val.v.data)<0)
+			return pv_get_null(msg, param, res);
+		break;
+	case SR_XTYPE_XAVP:
+	case SR_XTYPE_STR:
+	case SR_XTYPE_INT:
+	case SR_XTYPE_TIME:
+	case SR_XTYPE_LONG:
+	case SR_XTYPE_LLONG:
+		LM_ERR("BUG: unexpected pid value\n");
+		return pv_get_null(msg, param, res);
+		break;
+	default:
+		return pv_get_null(msg, param, res);
+	}
+	s.s = _pv_xavp_buf;
+	s.len = strlen(_pv_xavp_buf);
+	return pv_get_strval(msg, param, res, &s);
+}
+
+int pv_pid_get(struct sip_msg* msg,  pv_param_t* param, pv_value_t* res)
+{
+	str name;
+	sr_xavp_t *pids_root;
+	sr_xavp_t *pid;
+	sr_xavp_t *xavp;
+	int attr;
+	int i;
+
+	ei_x_buff xbuff;
+
+	if(param==NULL)
+	{
+		LM_ERR("bad parameters\n");
+		return -1;
+	}
+
+	if (param->pvn.type != PV_NAME_INTSTR || !(param->pvn.u.isname.type & AVP_NAME_STR))
+				return -1;
+
+	/* pid name */
+	name = param->pvn.u.isname.name.s;
+	/* attributes */
+	attr = xbuff_get_attr_flags(param->pvi.type);
+
+	pids_root = xavp_get_pids();
+	if(!pids_root) {
+		return pv_get_null(msg,param,res);
+	}
+
+	pid = xavp_get(&name,pids_root->val.v.xavp);
+	if (!pid) {
+		return pv_get_null(msg,param,res);
+	}
+
+	xavp = pid->val.v.xavp;
+
+	switch (xbuff_is_attr_set(attr)) {
+	case XBUFF_ATTR_TYPE:
+		return pv_get_strval(msg,param,res,&xbuff_types[XBUFF_TYPE_PID]);
+		break;
+	case XBUFF_ATTR_LENGTH: /* always 1 */
+		return pv_get_uintval(msg,param,res,1);
+		break;
+	case XBUFF_ATTR_FORMAT:
+		/*
+		 * Prints a term, in clear text, to the PV value pointed to by res.
+		 * It tries to resemble the term printing in the erlang shell.
+		 */
+		ei_x_new_with_version(&xbuff);
+		if (xavp && xavp_encode(&xbuff,xavp,1)) {
+			ei_x_free(&xbuff);
+			return -1;
+		} else {
+			ei_x_encode_atom(&xbuff,"undefined");
+		}
+		i = 1;
+		if (ei_s_print_term(&pid_fmt_buff,xbuff.buff,&i)<0) {
+			LM_ERR("BUG: xbuff[index] doesn't contain a valid term!\n");
+			ei_x_free(&xbuff);
+			return -1;
+		}
+		i = pv_get_strzval(msg,param,res,pid_fmt_buff);
+		ei_x_free(&xbuff);
+		return i;
+	}
+
+	if (!xavp) {
+		return pv_get_null(msg,param,res);
+	}
+
+	return pv_pid_get_value(msg,param,res,xavp);
+}
+
+/*
+ * free format buffer for tuple
+ */
+void free_pid_fmt_buff() {
+	if (pid_fmt_buff) {
+		free(pid_fmt_buff);
+	}
+	pid_fmt_buff = 0;
+}
diff --git a/modules/erlang/pv_pid.h b/modules/erlang/pv_pid.h
new file mode 100644
index 0000000..1fa18a9
--- /dev/null
+++ b/modules/erlang/pv_pid.h
@@ -0,0 +1,37 @@
+/**
+ * Copyright (C) 2015 Bicom Systems Ltd, (bicomsystems.com)
+ *
+ * Author: Seudin Kasumovic (seudin.kasumovic at gmail.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef PV_PID_H_
+#define PV_PID_H_
+
+#include "../../pvar.h"
+
+int pv_pid_parse_name(pv_spec_t *sp, str *in);
+int pv_pid_set(struct sip_msg* msg,  pv_param_t* param, int op, pv_value_t* val);
+int pv_pid_get(struct sip_msg*, pv_param_t*, pv_value_t*);
+
+sr_xavp_t *pv_pid_get_pid(str *name);
+
+void free_pid_fmt_buff();
+
+#endif /* PV_PID_H_ */
diff --git a/modules/erlang/pv_ref.c b/modules/erlang/pv_ref.c
new file mode 100644
index 0000000..0d17d4d
--- /dev/null
+++ b/modules/erlang/pv_ref.c
@@ -0,0 +1,343 @@
+/**
+ * Copyright (C) 2015 Bicom Systems Ltd, (bicomsystems.com)
+ *
+ * Author: Seudin Kasumovic (seudin.kasumovic at gmail.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <stdlib.h>
+
+#include "../../str.h"
+#include "../../xavp.h"
+#include "../../pvapi.h"
+
+#include "pv_ref.h"
+#include "pv_xbuff.h"
+
+static str ref_list=str_init("[refs]");
+static char *ref_fmt_buff = NULL;
+static int counter;
+
+sr_xavp_t *pv_ref_get_ref(str *name)
+{
+	return xavp_get_child(&ref_list,name);
+}
+
+int pv_ref_parse_name(pv_spec_t *sp, str *in)
+{
+	char *p;
+	str idx;
+	str name;
+	str attr;
+	int l;
+
+	if (in->s == NULL || in->len <= 0)
+		return -1;
+
+	p = in->s;
+
+	name.s = p;
+
+	while (is_in_str(p, in)) {
+		if (*p == '[' || *p== '=')
+			break;
+		if (!is_pv_xbuff_valid_char(*p)) {
+			l = p-in->s;
+			LM_ERR("invalid character in var name %.*s at %d\n",STR_FMT(in),l);
+			goto error;
+		}
+		p++;
+	}
+
+	/* from in->s to p */
+	name.len = p - in->s;
+
+	if (pv_parse_avp_name(sp,&name))
+		goto error;
+
+	if (is_in_str(p,in) && *p =='[')
+	{
+		idx.s=++p;
+
+		while (is_in_str(p,in)) {
+			if (*p == ']' || *p == '=')
+				break;
+			p++;
+		}
+
+		if (is_in_str(p,in) && *p==']') {
+			idx.len = p - idx.s;
+
+			LM_ERR("index isn't allowed for this variable\n");
+			goto error;
+		}
+		p++;
+	} else {
+		xbuff_set_attr_flag(sp->pvp.pvi.type,XBUFF_NO_IDX);
+	}
+
+	if (is_in_str(p,in) && *p =='=')
+	{
+		p++;
+
+		if (!is_in_str(p,in) || *p!='>') {
+			l = p-in->s;
+			LM_ERR("invalid operator (expected =>) for accessing attribute in token %.*s at position %d\n",STR_FMT(in),l);
+			goto error;
+		}
+
+		attr.s = ++p;
+
+		while (is_in_str(p,in)) {
+			if (!is_pv_xbuff_valid_char(*p)) {
+				l = p-in->s;
+				LM_ERR("invalid character in attribute name in token %.*s at %d\n",STR_FMT(in),l);
+				goto error;
+			}
+			p++;
+		}
+
+		attr.len = p - attr.s;
+
+		if (attr.len > 0 ) {
+
+			if (STR_EQ(attr,xbuff_attr_name(XBUFF_ATTR_TYPE))) {
+				xbuff_set_attr_flag(sp->pvp.pvi.type,XBUFF_ATTR_TYPE);
+			} else if (STR_EQ(attr,xbuff_attr_name(XBUFF_ATTR_FORMAT))) {
+				xbuff_set_attr_flag(sp->pvp.pvi.type,XBUFF_ATTR_FORMAT);
+			} else if (STR_EQ(attr,xbuff_attr_name(XBUFF_ATTR_LENGTH))) {
+				LM_ERR("attribute isn't supported for this variable\n");
+				goto error;
+			} else {
+				LM_ERR("unknown attribute %.*s\n",STR_FMT(&attr));
+				goto error;
+			}
+		}
+	}
+
+	if (p < in->s + in->len) {
+		l = p-in->s;
+		LM_ERR("unexpected token in %.*s at %d\n",STR_FMT(in),l);
+		goto error;
+	}
+
+	return 0;
+
+error:
+
+	return -1;
+}
+
+sr_xavp_t *xavp_get_refs()
+{
+	sr_xavp_t *list;
+	list = xavp_get(&ref_list,NULL);
+
+	if(!list) counter = 0;
+
+	return list;
+}
+
+int pv_ref_set(struct sip_msg* msg,  pv_param_t* param, int op, pv_value_t* val)
+{
+	str name;
+	sr_xavp_t *ref_root;
+	sr_xavp_t *ref;
+	sr_xavp_t *new,*old=NULL;
+	sr_xavp_t *ref_xavp;
+	sr_xval_t ref_val;
+
+	if (param->pvn.type != PV_NAME_INTSTR || !(param->pvn.u.isname.type & AVP_NAME_STR)) {
+		LM_ERR("invalid variable name type\n");
+		return -1;
+	}
+
+	if(pv_xbuff_new_xavp(&ref_xavp,val,&counter,'r')) {
+		LM_ERR("failed to create new value\n");
+		return -1;
+	}
+
+	/* ref var name */
+	name = param->pvn.u.isname.name.s;
+
+	memset((void*)&ref_val,0,sizeof(sr_xval_t));
+
+	ref_root = xavp_get_refs();
+
+	if(!ref_root) {
+
+		ref_val.type = SR_XTYPE_XAVP;
+		ref_val.v.xavp = ref_xavp;
+		ref = xavp_add_xavp_value(&ref_list,&name,&ref_val,xavp_get_crt_list());
+
+		if (!ref)
+			goto err;
+
+		return 0;
+	}
+
+	ref = xavp_get_child(&ref_list, &name);
+
+	if (!ref) {
+
+		ref_val.type = SR_XTYPE_XAVP;
+		ref_val.v.xavp = ref_xavp;
+
+		new = xavp_add_value(&name,&ref_val,&ref_root->val.v.xavp);
+
+		if (!new)
+			goto err;
+
+		return 0;
+	}
+
+	old = ref->val.v.xavp;
+	new = ref_xavp;
+
+	if (old) {
+		xavp_destroy_list(&old);
+	}
+
+	ref->val.v.xavp = new;
+
+	return 0;
+
+err:
+	LM_ERR("failed to set ref value\n");
+	xavp_destroy_list(&ref_xavp);
+
+	return -1;
+}
+
+int pv_ref_get_value(struct sip_msg *msg, pv_param_t *param,
+		pv_value_t *res, sr_xavp_t *avp)
+{
+	static char _pv_xavp_buf[128];
+	str s;
+
+	if (!avp) return pv_get_null(msg,param,res);
+
+	switch(avp->val.type) {
+	case SR_XTYPE_NULL:
+		return pv_get_null(msg, param, res);
+		break;
+	case SR_XTYPE_DATA:
+		if(snprintf(_pv_xavp_buf, 128, "<<ref:%p>>", avp->val.v.data)<0)
+			return pv_get_null(msg, param, res);
+		break;
+	case SR_XTYPE_XAVP:
+	case SR_XTYPE_STR:
+	case SR_XTYPE_INT:
+	case SR_XTYPE_TIME:
+	case SR_XTYPE_LONG:
+	case SR_XTYPE_LLONG:
+		LM_ERR("BUG: unexpected ref value\n");
+		return pv_get_null(msg, param, res);
+		break;
+	default:
+		return pv_get_null(msg, param, res);
+	}
+	s.s = _pv_xavp_buf;
+	s.len = strlen(_pv_xavp_buf);
+	return pv_get_strval(msg, param, res, &s);
+}
+
+int pv_ref_get(struct sip_msg* msg,  pv_param_t* param, pv_value_t* res)
+{
+	str name;
+	sr_xavp_t *refs_root;
+	sr_xavp_t *ref;
+	sr_xavp_t *xavp;
+	int attr;
+	int i;
+
+	ei_x_buff xbuff;
+
+	if(param==NULL)
+	{
+		LM_ERR("bad parameters\n");
+		return -1;
+	}
+
+	if (param->pvn.type != PV_NAME_INTSTR || !(param->pvn.u.isname.type & AVP_NAME_STR))
+				return -1;
+
+	/* ref name */
+	name = param->pvn.u.isname.name.s;
+	/* attributes */
+	attr = xbuff_get_attr_flags(param->pvi.type);
+
+	refs_root = xavp_get_refs();
+	if(!refs_root) {
+		return pv_get_null(msg,param,res);
+	}
+
+	ref = xavp_get(&name,refs_root->val.v.xavp);
+	if (!ref) {
+		return pv_get_null(msg,param,res);
+	}
+
+	xavp = ref->val.v.xavp;
+
+	switch (xbuff_is_attr_set(attr)) {
+	case XBUFF_ATTR_TYPE:
+		return pv_get_strval(msg,param,res,&xbuff_types[XBUFF_TYPE_REF]);
+		break;
+	case XBUFF_ATTR_LENGTH: /* always 1 */
+		return pv_get_uintval(msg,param,res,1);
+		break;
+	case XBUFF_ATTR_FORMAT:
+		/*
+		 * Prints a term, in clear text, to the PV value pointed to by res.
+		 * It tries to resemble the term printing in the erlang shell.
+		 */
+		ei_x_new_with_version(&xbuff);
+		if (xavp && xavp_encode(&xbuff,xavp,1)) {
+			ei_x_free(&xbuff);
+			return -1;
+		} else {
+			ei_x_encode_atom(&xbuff,"undefined");
+		}
+		i = 1;
+		if (ei_s_print_term(&ref_fmt_buff,xbuff.buff,&i)<0) {
+			LM_ERR("BUG: xbuff[index] doesn't contain a valid term!\n");
+			ei_x_free(&xbuff);
+			return -1;
+		}
+		i = pv_get_strzval(msg,param,res,ref_fmt_buff);
+		ei_x_free(&xbuff);
+		return i;
+	}
+
+	if (!xavp) {
+		return pv_get_null(msg,param,res);
+	}
+
+	return pv_ref_get_value(msg,param,res,xavp);
+}
+
+/*
+ * free format buffer for tuple
+ */
+void free_ref_fmt_buff() {
+	if (ref_fmt_buff) {
+		free(ref_fmt_buff);
+	}
+	ref_fmt_buff = 0;
+}
diff --git a/modules/erlang/pv_ref.h b/modules/erlang/pv_ref.h
new file mode 100644
index 0000000..8694efd
--- /dev/null
+++ b/modules/erlang/pv_ref.h
@@ -0,0 +1,37 @@
+/**
+ * Copyright (C) 2015 Bicom Systems Ltd, (bicomsystems.com)
+ *
+ * Author: Seudin Kasumovic (seudin.kasumovic at gmail.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef PV_REF_H_
+#define PV_REF_H_
+
+#include "../../pvar.h"
+
+int pv_ref_parse_name(pv_spec_t *sp, str *in);
+int pv_ref_set(struct sip_msg* msg,  pv_param_t* param, int op, pv_value_t* val);
+int pv_ref_get(struct sip_msg*, pv_param_t*, pv_value_t*);
+
+sr_xavp_t *pv_ref_get_ref(str *name);
+
+void free_ref_fmt_buff();
+
+#endif /* PV_PID_H_ */
diff --git a/modules/erlang/pv_tuple.c b/modules/erlang/pv_tuple.c
new file mode 100644
index 0000000..b58ef8b
--- /dev/null
+++ b/modules/erlang/pv_tuple.c
@@ -0,0 +1,395 @@
+/**
+ * Copyright (C) 2015 Bicom Systems Ltd, (bicomsystems.com)
+ *
+ * Author: Seudin Kasumovic (seudin.kasumovic at gmail.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <stdlib.h>
+
+#include "../../pvar.h"
+
+#include "pv_tuple.h"
+#include "pv_xbuff.h"
+
+static str tuple_list=str_init("[tuples]");
+
+static int counter;
+static char *tuple_fmt_buff = NULL;
+
+sr_xavp_t *xavp_get_tuples()
+{
+	sr_xavp_t *list;
+	list = xavp_get(&tuple_list,NULL);
+
+	if(!list) counter = 0;
+
+	return list;
+}
+
+sr_xavp_t *pv_tuple_get_tuple(str *name)
+{
+	return xavp_get_child(&tuple_list,name);
+}
+
+int pv_tuple_set(struct sip_msg* msg,  pv_param_t* param, int op, pv_value_t* val)
+{
+	str name;
+	sr_xavp_t *tuples_root;
+	sr_xavp_t *tuple;
+	sr_xavp_t *th,*new,*old,*prv=NULL;
+	sr_xavp_t *tuple_xavp;
+	sr_xavp_t *elem_xavp;
+	sr_xval_t tuple_val;
+	pv_param_t p;
+	pv_value_t empty;
+	int idx = 0;
+	int idxf = 0;
+	int attr = 0;
+
+	if (param->pvn.type != PV_NAME_INTSTR || !(param->pvn.u.isname.type & AVP_NAME_STR)) {
+		LM_ERR("invalid variable name type\n");
+		return -1;
+	}
+
+	memset((void*)&empty,0,sizeof(pv_value_t));
+	empty.flags = PV_VAL_NULL;
+
+	memset((void*)&tuple_val,0,sizeof(sr_xval_t));
+
+	/* list name */
+	name = param->pvn.u.isname.name.s;
+
+	tuples_root = xavp_get_tuples();
+
+	if(!tuples_root) {
+
+		if(pv_xbuff_new_xavp(&tuple_xavp,&empty,&counter,'t')) {
+			LM_ERR("failed to create new value\n");
+			return -1;
+		}
+		tuple_val.type = SR_XTYPE_XAVP;
+		tuple_val.v.xavp = tuple_xavp;
+
+		tuple = xavp_add_xavp_value(&tuple_list,&name,&tuple_val,xavp_get_crt_list());
+
+		if (!tuple)
+			goto err;
+	}
+
+	tuple=xavp_get_child(&tuple_list, &name);
+
+	if (!tuple) {
+
+		if(pv_xbuff_new_xavp(&tuple_xavp,&empty,&counter,'t')) {
+			LM_ERR("failed to create new value\n");
+			return -1;
+		}
+
+		tuple_val.type = SR_XTYPE_XAVP;
+		tuple_val.v.xavp = tuple_xavp;
+
+		tuple=xavp_add_value(&name,&tuple_val,&tuples_root->val.v.xavp);
+
+		if (!tuple)
+			goto err;
+	}
+
+	th = tuple->val.v.xavp;
+
+	if(pv_xbuff_new_xavp(&elem_xavp,val,&counter,0)) {
+		LM_ERR("failed to create new value\n");
+		return -1;
+	}
+
+	/* work on copy of index! */
+	p = *param;
+
+	/* fix index */
+	attr = xbuff_get_attr_flags(p.pvi.type);
+	p.pvi.type = xbuff_fix_index(p.pvi.type);
+
+	/* get the index */
+	if(pv_get_spec_index(msg, &p, &idx, &idxf))
+	{
+		LM_ERR("invalid index\n");
+		return -1;
+	}
+
+	if (xbuff_is_attr_set(attr)) {
+		LM_ERR("read only attribute %.*s\n",STR_FMT(&xbuff_attr_name(attr)));
+		return -1;
+	}
+
+	/* prepend on list when no index */
+	if (xbuff_is_no_index(attr)) {
+		if (th->val.type == SR_XTYPE_NULL) {
+			th->val.type = SR_XTYPE_XAVP;
+			th->val.v.xavp = elem_xavp;
+			return 0;
+		} else {
+			return xavp_add(elem_xavp,&th->val.v.xavp);
+		}
+	}
+
+	if (idxf == PV_IDX_ALL) {
+		xavp_destroy_list(&th->val.v.xavp);
+		if (elem_xavp->val.type == SR_XTYPE_NULL) {
+			/* create empty list */
+			xavp_destroy_list(&elem_xavp);
+
+			memset((void*)&th->val,0,sizeof(sr_xval_t));
+			th->val.type = SR_XTYPE_NULL;
+			return 0;
+		} else {
+			return xavp_add(elem_xavp,&th->val.v.xavp);
+		}
+	}
+
+	/* set by index */
+	old = xavp_get_nth(&th->val.v.xavp,idx,&prv);
+	new = elem_xavp;
+
+	if (old) {
+		new->next = old->next;
+		if (prv) {
+			prv->next = new;
+		} else {
+			new->next = old->next;
+			th->val.v.xavp = new;
+		}
+		old->next = NULL;
+		xavp_destroy_list(&old);
+	} else {
+		if (prv) {
+			prv->next = new;
+		} else {
+			th->val.v.xavp = new;
+		}
+	}
+
+	return 0;
+
+err:
+	LM_ERR("failed to add value into tuple\n");
+	xavp_destroy_list(&tuple_xavp);
+	xavp_destroy_list(&elem_xavp);
+
+	return -1;
+}
+
+int pv_tuple_get_value(struct sip_msg *msg, pv_param_t *param,
+		pv_value_t *res, sr_xavp_t *avp)
+{
+	static char _pv_xavp_buf[128];
+	str s;
+
+	if (!avp) return pv_get_null(msg,param,res);
+
+	switch(avp->val.type) {
+	case SR_XTYPE_NULL:
+		return pv_get_null(msg, param, res);
+		break;
+	case SR_XTYPE_INT:
+		return pv_get_sintval(msg, param, res, avp->val.v.i);
+		break;
+	case SR_XTYPE_STR:
+		switch (avp->name.s[0]) {
+		case 'a':
+			if(snprintf(_pv_xavp_buf, 128, "<<atom:%p>>", avp->val.v.xavp)<0)
+				return pv_get_null(msg, param, res);
+			break;
+		default:
+			return pv_get_strval(msg, param, res, &avp->val.v.s);
+		}
+		break;
+	case SR_XTYPE_TIME:
+		if(snprintf(_pv_xavp_buf, 128, "%lu", (long unsigned)avp->val.v.t)<0)
+			return pv_get_null(msg, param, res);
+		break;
+	case SR_XTYPE_LONG:
+		if(snprintf(_pv_xavp_buf, 128, "%ld", (long unsigned)avp->val.v.l)<0)
+			return pv_get_null(msg, param, res);
+		break;
+	case SR_XTYPE_LLONG:
+		if(snprintf(_pv_xavp_buf, 128, "%lld", avp->val.v.ll)<0)
+			return pv_get_null(msg, param, res);
+		break;
+	case SR_XTYPE_XAVP:
+		switch(avp->name.s[0]) {
+		case 'l':
+			if(snprintf(_pv_xavp_buf, 128, "<<list:%p>>", avp->val.v.xavp)<0)
+				return pv_get_null(msg, param, res);
+			break;
+		case 't':
+		default:
+				if(snprintf(_pv_xavp_buf, 128, "<<tuple:%p>>", avp->val.v.xavp)<0)
+					return pv_get_null(msg, param, res);
+		}
+		break;
+	case SR_XTYPE_DATA:
+		if (avp->name.s[0] == 'p') {
+			if(snprintf(_pv_xavp_buf, 128, "<<pid:%p>>", avp->val.v.data)<0)
+				return pv_get_null(msg, param, res);
+		} else if(snprintf(_pv_xavp_buf, 128, "<<binary:%p>>", avp->val.v.data)<0)
+			return pv_get_null(msg, param, res);
+		break;
+	default:
+		return pv_get_null(msg, param, res);
+	}
+	s.s = _pv_xavp_buf;
+	s.len = strlen(_pv_xavp_buf);
+	return pv_get_strval(msg, param, res, &s);
+}
+
+int pv_tuple_get(struct sip_msg* msg,  pv_param_t* param, pv_value_t* res)
+{
+	str name;
+	pv_spec_t *nsp = NULL;
+	pv_name_t *pvn;
+	pv_index_t *pvi;
+	sr_xavp_t *tuples_root;
+	sr_xavp_t *tuple;
+	sr_xavp_t *th;
+	sr_xavp_t *xavp;
+	pv_param_t p;
+	int idx=0;
+	int idxf=0;
+	int attr;
+	int i,count;
+
+	ei_x_buff xbuff;
+
+	if(param==NULL)
+	{
+		LM_ERR("bad parameters\n");
+		return -1;
+	}
+
+	if (param->pvn.type != PV_NAME_INTSTR || !(param->pvn.u.isname.type & AVP_NAME_STR))
+				return -1;
+
+	if( param->pvn.type == PV_NAME_PVAR) {
+			nsp = param->pvn.u.dname;
+	}
+
+	/* work on copy of index! */
+	p = *param;
+
+	if (nsp) {
+		pvi = &nsp->pvp.pvi;
+		pvn = &nsp->pvp.pvn;
+	} else {
+		pvi = &p.pvi;
+		pvn = &p.pvn;
+	}
+
+	/* list name */
+	name = pvn->u.isname.name.s;
+
+	/* fix index */
+	attr = xbuff_get_attr_flags(pvi->type);
+	pvi->type = xbuff_fix_index(pvi->type);
+
+	/* get the index */
+	if(pv_get_spec_index(msg, &p, &idx, &idxf))
+	{
+		LM_ERR("invalid index\n");
+		return -1;
+	}
+
+	tuples_root = xavp_get_tuples();
+	if(!tuples_root) {
+		return pv_get_null(msg,param,res);
+	}
+
+	tuple = xavp_get(&name,tuples_root->val.v.xavp);
+	if (!tuple) {
+		return pv_get_null(msg,param,res);
+	}
+
+	th = tuple->val.v.xavp;
+
+	switch (xbuff_is_attr_set(attr)) {
+	case XBUFF_ATTR_TYPE:
+		if (xbuff_is_no_index(attr)) {
+			return pv_get_strval(msg,param,res,&xbuff_types[XBUFF_TYPE_TUPLE]);
+		} else {
+			xavp = xavp_get_nth(&th->val.v.xavp,idx,NULL);
+			return pv_xbuff_get_type(msg,param,res,xavp);
+		}
+		break;
+	case XBUFF_ATTR_LENGTH:
+		xavp = xbuff_is_no_index(attr) ? th : xavp_get_nth(&th->val.v.xavp,idx,NULL);
+		if (xavp) {
+			count = xavp_get_count(xavp->val.v.xavp);
+			return pv_get_uintval(msg,param,res,(unsigned int)count);
+		} else {
+			return pv_get_null(msg,param,res);
+		}
+		break;
+	case XBUFF_ATTR_FORMAT:
+		/*
+		 * Prints a term, in clear text, to the PV value pointed to by res.
+		 * It tries to resemble the term printing in the erlang shell.
+		 */
+		ei_x_new_with_version(&xbuff);
+		xavp = xbuff_is_no_index(attr) ? th : xavp_get_nth(&th->val.v.xavp,idx,NULL);
+		if (!xavp || xavp_encode(&xbuff,xavp,1)) {
+			ei_x_free(&xbuff);
+			return -1;
+		}
+		i = 1;
+		if (ei_s_print_term(&tuple_fmt_buff,xbuff.buff,&i)<0) {
+			LM_ERR("BUG: xbuff[index] doesn't contain a valid term!\n");
+			ei_x_free(&xbuff);
+			return -1;
+		}
+		i = pv_get_strzval(msg,param,res,tuple_fmt_buff);
+		ei_x_free(&xbuff);
+		return i;
+	}
+
+	/* get whole list */
+	if ((idxf == PV_IDX_ALL) || xbuff_is_no_index(attr)) {
+		return pv_tuple_get_value(msg,param,res,tuple);
+	}
+
+	if (th->val.type == SR_XTYPE_NULL) {
+		return pv_get_null(msg,param,res);
+	}
+
+	/* get by idx */
+	xavp = xavp_get_nth(&th->val.v.xavp,idx,NULL);
+	if (!xavp) {
+		return pv_get_null(msg,param,res);
+	}
+
+	return pv_tuple_get_value(msg,param,res,xavp);
+}
+
+/*
+ * free format buffer for tuple
+ */
+void free_tuple_fmt_buff() {
+	if (tuple_fmt_buff) {
+		free(tuple_fmt_buff);
+	}
+	tuple_fmt_buff = 0;
+}
diff --git a/modules/erlang/pv_tuple.h b/modules/erlang/pv_tuple.h
new file mode 100644
index 0000000..a824841
--- /dev/null
+++ b/modules/erlang/pv_tuple.h
@@ -0,0 +1,37 @@
+/**
+ * Copyright (C) 2015 Bicom Systems Ltd, (bicomsystems.com)
+ *
+ * Author: Seudin Kasumovic (seudin.kasumovic at gmail.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef PV_TUPLE_H_
+#define PV_TUPLE_H_
+
+#include "../../pvar.h"
+#include "../../xavp.h"
+
+int pv_tuple_set(struct sip_msg*, pv_param_t*, int, pv_value_t*);
+int pv_tuple_get(struct sip_msg*, pv_param_t*, pv_value_t*);
+
+sr_xavp_t *pv_tuple_get_tuple(str *name);
+
+void free_tuple_fmt_buff();
+
+#endif /* PV_TUPLE_H_ */
diff --git a/modules/erlang/pv_xbuff.c b/modules/erlang/pv_xbuff.c
new file mode 100644
index 0000000..cdfbd58
--- /dev/null
+++ b/modules/erlang/pv_xbuff.c
@@ -0,0 +1,1247 @@
+/**
+ * Copyright (C) 2015 Bicom Systems Ltd, (bicomsystems.com)
+ *
+ * Author: Seudin Kasumovic (seudin.kasumovic at gmail.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <stdlib.h>
+
+#include "../../str.h"
+#include "../../hashes.h"
+
+#include "pv_xbuff.h"
+
+str xbuff_attributes[] = {
+		STR_STATIC_INIT("type"),
+		STR_STATIC_INIT("format"),
+		STR_STATIC_INIT("length"),
+		STR_NULL
+};
+
+str xbuff_types[] = {
+		STR_STATIC_INIT("atom"),
+		STR_STATIC_INIT("integer"),
+		STR_STATIC_INIT("string"),
+		STR_STATIC_INIT("tuple"),
+		STR_STATIC_INIT("list"),
+		STR_STATIC_INIT("pid"),
+		STR_STATIC_INIT("ref"),
+		STR_NULL
+};
+
+/**
+ * atom,tuple,xbuff & list regex
+ */
+regex_t xbuff_type_re = {0};
+
+static str xbuff_list=str_init("[xbuffs]");
+
+static int counter;
+static char *xbuff_fmt_buff = NULL;
+
+void xbuff_data_free(void *p, sr_xavp_sfree_f sfree);
+
+sr_xavp_t *xavp_get_xbuffs()
+{
+	sr_xavp_t *list;
+	list = xavp_get(&xbuff_list,NULL);
+
+	if(!list) counter = 0;
+
+	return list;
+}
+
+sr_xavp_t *pv_xbuff_get_xbuff(str *name)
+{
+	return xavp_get_child(&xbuff_list,name);
+}
+
+sr_xavp_t *xbuff_new(str *name)
+{
+	sr_xavp_t *xbuffs_root;
+	sr_xavp_t *xbuff;
+	sr_xval_t xbuff_val;
+
+	memset((void*)&xbuff_val,0,sizeof(sr_xval_t));
+	xbuff_val.type = SR_XTYPE_NULL;
+
+	xbuffs_root = xavp_get_xbuffs();
+
+	if(!xbuffs_root)
+	{
+		xbuff = xavp_add_xavp_value(&xbuff_list,name,&xbuff_val,xavp_get_crt_list());
+	}
+
+	xbuff=xavp_get_child(&xbuff_list, name);
+
+	if (!xbuff) {
+
+		xbuff_val.type = SR_XTYPE_NULL;
+		xbuff_val.v.xavp = NULL;
+
+		xbuff=xavp_add_value(name,&xbuff_val,&xbuffs_root->val.v.xavp);
+	}
+
+	return xbuff;
+}
+
+/***
+ * if compile success returns 0
+ */
+int compile_xbuff_re()
+{
+	char *pattern = "^<<\\(tuple\\|list\\|atom\\|pid\\|ref\\):\\(0x[[:xdigit:]]\\+\\)>>$";
+	size_t bfsz = 128;
+	char errbuff[128];
+	int e;
+
+	if((e=regcomp(&xbuff_type_re,pattern,0))) {
+		regerror(e,&xbuff_type_re,errbuff,bfsz);
+		LM_ERR("failed to compile pattern '%s' error: %s\n",pattern,errbuff);
+		return -1;
+	}
+
+	return 0;
+}
+
+int xbuff_match_type_re(str *s, xbuff_type_t *type, sr_xavp_t **addr)
+{
+	size_t nmatch = 3;
+	regmatch_t matches[3];
+	int e;
+	size_t bfsz = 128;
+	char errbuff[128];
+	str tname;
+	str a;
+	xbuff_type_t t;
+
+	matches[0].rm_so = 0;
+	matches[0].rm_eo = s->len;
+
+	e = regexec(&xbuff_type_re,s->s,nmatch,matches,REG_STARTEND);
+
+	if (e == 0) {
+
+		tname.s   = s->s + matches[1].rm_so;
+		tname.len = matches[1].rm_eo - matches[1].rm_so;
+
+		a.s   = s->s + matches[2].rm_so;
+		a.len = matches[2].rm_eo - matches[1].rm_so;
+
+		if (STR_EQ(tname,xbuff_types[XBUFF_TYPE_ATOM])) {
+			t = XBUFF_TYPE_ATOM;
+		} else if (STR_EQ(tname,xbuff_types[XBUFF_TYPE_LIST])) {
+			t = XBUFF_TYPE_LIST;
+		} else if (STR_EQ(tname,xbuff_types[XBUFF_TYPE_TUPLE])) {
+			t = XBUFF_TYPE_TUPLE;
+		} else if (STR_EQ(tname,xbuff_types[XBUFF_TYPE_PID])) {
+			t = XBUFF_TYPE_PID;
+		} else if (STR_EQ(tname,xbuff_types[XBUFF_TYPE_REF])) {
+			t = XBUFF_TYPE_REF;
+		} else {
+			LM_ERR("BUG: unknown xbuff type");
+			return -1;
+		}
+
+		if(type) *type = t;
+
+		if (addr)
+			sscanf(a.s,"%lx>>",(long unsigned int *)addr);
+
+		return 0;
+
+	} else if (e != REG_NOMATCH) {
+		regerror(e,&xbuff_type_re,errbuff,bfsz);
+		LM_ERR("regexec error: %s\n",errbuff);
+	}
+
+	return -1;
+}
+
+int is_pv_xbuff_valid_char(char c)
+{
+	if((c>='0' && c<='9') || (c>='a' && c<='z') || (c>='A' && c<='Z')
+			|| (c=='_'))
+		return 1;
+	return 0;
+}
+
+int pv_xbuff_parse_name(pv_spec_t *sp, str *in)
+{
+	char *p;
+	str idx;
+	str name;
+	str attr;
+	int l;
+
+	if (in->s == NULL || in->len <= 0)
+		return -1;
+
+	p = in->s;
+
+	name.s = p;
+
+	while (is_in_str(p, in)) {
+		if (*p == '[' || *p== '=')
+			break;
+		if (!is_pv_xbuff_valid_char(*p)) {
+			l = p-in->s;
+			LM_ERR("invalid character in var name %.*s at %d\n",STR_FMT(in),l);
+			goto error;
+		}
+		p++;
+	}
+
+	/* from in->s to p */
+	name.len = p - in->s;
+
+	if (pv_parse_avp_name(sp,&name))
+		goto error;
+
+	if (is_in_str(p,in) && *p =='[')
+	{
+		idx.s=++p;
+
+		while (is_in_str(p,in)) {
+			if (*p == ']' || *p == '=')
+				break;
+			p++;
+		}
+
+		if (is_in_str(p,in) && *p==']') {
+			idx.len = p - idx.s;
+
+			if (pv_parse_index(sp,&idx))
+				goto error;
+		}
+		p++;
+	} else {
+		xbuff_set_attr_flag(sp->pvp.pvi.type,XBUFF_NO_IDX);
+	}
+
+	if (is_in_str(p,in) && *p =='=')
+	{
+		p++;
+
+		if (!is_in_str(p,in) || *p!='>') {
+			l = p-in->s;
+			LM_ERR("invalid operator (expected =>) for accessing attribute in token %.*s at position %d\n",STR_FMT(in),l);
+			goto error;
+		}
+
+		attr.s = ++p;
+
+		while (is_in_str(p,in)) {
+			if (!is_pv_xbuff_valid_char(*p)) {
+				l = p-in->s;
+				LM_ERR("invalid character in attribute name in token %.*s at %d\n",STR_FMT(in),l);
+				goto error;
+			}
+			p++;
+		}
+
+		attr.len = p - attr.s;
+
+		if (attr.len > 0 ) {
+
+			if (STR_EQ(attr,xbuff_attr_name(XBUFF_ATTR_TYPE))) {
+				xbuff_set_attr_flag(sp->pvp.pvi.type,XBUFF_ATTR_TYPE);
+			} else if (STR_EQ(attr,xbuff_attr_name(XBUFF_ATTR_FORMAT))) {
+				xbuff_set_attr_flag(sp->pvp.pvi.type,XBUFF_ATTR_FORMAT);
+			} else if (STR_EQ(attr,xbuff_attr_name(XBUFF_ATTR_LENGTH))) {
+				xbuff_set_attr_flag(sp->pvp.pvi.type,XBUFF_ATTR_LENGTH);
+			} else {
+				LM_ERR("unknown attribute %.*s\n",STR_FMT(&attr));
+				goto error;
+			}
+
+			if (sp->pvp.pvi.type & PV_IDX_ALL) {
+				LM_ERR("index [*] (all) isn't compatible with attribute %.*s\n",STR_FMT(&attr));
+				goto error;
+			}
+		}
+	}
+
+	if (p < in->s + in->len) {
+		l = p-in->s;
+		LM_ERR("unexpected token in %.*s at %d\n",STR_FMT(in),l);
+		goto error;
+	}
+
+	return 0;
+
+error:
+
+	return -1;
+}
+
+
+int pv_xbuff_new_xavp(sr_xavp_t **new, pv_value_t *pval, int *counter, char prefix)
+{
+	char s[101];
+	str name;
+	sr_xavp_t *xavp = NULL;
+	sr_xavp_t *cxavp = NULL;
+	sr_xval_t nval;
+	xbuff_type_t type;
+
+	if (!new) return -1;
+
+	memset((void*)&nval,0,sizeof(sr_xval_t));
+
+	if (pval->flags&PV_VAL_NULL) {
+		nval.type = SR_XTYPE_NULL;
+		s[0] = prefix ? prefix : 'n';
+	} else if (pval->flags&PV_VAL_INT) {
+		nval.type = SR_XTYPE_INT;
+		nval.v.i = pval->ri;
+		s[0] = prefix ? prefix : 'i';
+	} else if (pval->flags&PV_VAL_STR) {
+		/* check what it is */
+		if (xbuff_match_type_re(&pval->rs,&type,&xavp)) {
+			nval.type = SR_XTYPE_STR;
+			nval.v.s = pval->rs;
+			s[0] = prefix ? prefix : 's';
+		} else {
+			switch (type) {
+			case XBUFF_TYPE_ATOM:
+				s[0] = 'a';
+				nval = xavp->val;
+				break;
+			case XBUFF_TYPE_LIST:
+				s[0] = 'l';
+				/* copy tree */
+				cxavp = xbuff_copy_xavp(xavp);
+
+				if (!cxavp)
+					return -1;
+
+				nval = cxavp->val;
+
+				/* free overhead */
+				cxavp->next = NULL;
+				cxavp->val.v.xavp = NULL;
+				xavp_destroy_list(&cxavp);
+
+				break;
+			case XBUFF_TYPE_TUPLE:
+				s[0] = 't';
+
+				/* copy tree */
+				cxavp = xbuff_copy_xavp(xavp);
+
+				if (!cxavp)
+					return -1;
+
+				nval = cxavp->val;
+
+				/* free overhead */
+				cxavp->next = NULL;
+				cxavp->val.v.xavp = NULL;
+				xavp_destroy_list(&cxavp);
+				break;
+			case XBUFF_TYPE_PID:
+				s[0] = 'p';
+				nval.type = SR_XTYPE_DATA;
+				nval.v.data = (sr_data_t*)shm_malloc(sizeof(sr_data_t)+sizeof(erlang_pid));
+				if (!nval.v.data) {
+					LM_ERR("not enough shared memory\n");
+					return -1;
+				}
+				memcpy((void*)nval.v.data,(void*)xavp,sizeof(sr_data_t)+sizeof(erlang_pid));
+				break;
+			case XBUFF_TYPE_REF:
+				s[0] = 'r';
+				nval.type = SR_XTYPE_DATA;
+				nval.v.data = (sr_data_t*)shm_malloc(sizeof(sr_data_t)+sizeof(erlang_ref));
+				if (!nval.v.data) {
+					LM_ERR("not enough shared memory\n");
+					return -1;
+				}
+				memcpy((void*)nval.v.data,(void*)xavp,sizeof(sr_data_t)+sizeof(erlang_ref));
+				break;
+			case XBUFF_TYPE_INT:
+			case XBUFF_TYPE_STR:
+			default:
+				LM_ERR("BUG: unexpected XBUFF type!\n");
+				return -1;
+			}
+		}
+	}
+
+	name.s = s;
+	name.len = snprintf(s+1,99,"%d",(*counter)++) + 1;
+
+	cxavp = xavp_new_value(&name,&nval);
+
+	if (!cxavp) {
+		return -1;
+	}
+
+	*new = cxavp;
+
+	return 0;
+}
+
+int pv_xbuff_get_type(struct sip_msg *msg, pv_param_t *param,
+		pv_value_t *res, sr_xavp_t *avp)
+{
+	if (!avp) return pv_get_null(msg,param,res);
+
+	switch(avp->name.s[0]){
+	case 'n':
+		return pv_get_null(msg,param,res);
+		break;
+	case 'i':
+		return pv_get_strval(msg,param,res,&xbuff_types[XBUFF_TYPE_INT]);
+		break;
+	case 'l':
+		return pv_get_strval(msg,param,res,&xbuff_types[XBUFF_TYPE_LIST]);
+		break;
+	case 'a':
+		return pv_get_strval(msg, param, res, &xbuff_types[XBUFF_TYPE_ATOM]);
+		break;
+	case 's':
+		return pv_get_strval(msg, param, res, &xbuff_types[XBUFF_TYPE_STR]);
+		break;
+	case 't':
+		return pv_get_strval(msg, param, res, &xbuff_types[XBUFF_TYPE_TUPLE]);
+		break;
+	case 'p':
+		return pv_get_strval(msg, param, res, &xbuff_types[XBUFF_TYPE_PID]);
+		break;
+	case 'r':
+		return pv_get_strval(msg, param, res, &xbuff_types[XBUFF_TYPE_REF]);
+		break;
+	}
+
+	return pv_get_null(msg, param, res);
+}
+
+int pv_xbuff_set(struct sip_msg* msg,  pv_param_t* param, int op, pv_value_t* val)
+{
+	str name;
+	sr_xavp_t *xbuffs_root;
+	sr_xavp_t *xbuff;
+	sr_xavp_t *new,*old,*prv=NULL;
+	sr_xavp_t *xbuff_xavp;
+	sr_xval_t xbuff_val;
+	pv_param_t p;
+	int idx = 0;
+	int idxf = 0;
+	int attr = 0;
+
+	if (param->pvn.type != PV_NAME_INTSTR || !(param->pvn.u.isname.type & AVP_NAME_STR)) {
+		LM_ERR("invalid variable name type\n");
+		return -1;
+	}
+
+	/* xbuff name */
+	name = param->pvn.u.isname.name.s;
+
+	xbuffs_root = xavp_get_xbuffs();
+
+	if(!xbuffs_root) {
+
+		memset((void*)&xbuff_val,0,sizeof(sr_xval_t));
+
+		xbuff_val.type = SR_XTYPE_NULL;
+
+		xbuff = xavp_add_xavp_value(&xbuff_list,&name,&xbuff_val,xavp_get_crt_list());
+
+		if (!xbuff)
+			goto err;
+	}
+
+	if(pv_xbuff_new_xavp(&xbuff_xavp,val,&counter,0)) {
+		LM_ERR("failed to create new value\n");
+		return -1;
+	}
+
+	xbuff=xavp_get_child(&xbuff_list, &name);
+
+	if (!xbuff) {
+
+		xbuff_val.type = SR_XTYPE_NULL;
+		xbuff_val.v.xavp = NULL;
+
+		xbuff=xavp_add_value(&name,&xbuff_val,&xbuffs_root->val.v.xavp);
+
+		if (!xbuff)
+			goto err;
+	}
+
+	/* work on copy of index! */
+	p = *param;
+
+	/* fix index */
+	attr = xbuff_get_attr_flags(p.pvi.type);
+	p.pvi.type = xbuff_fix_index(p.pvi.type);
+
+	/* get the index */
+	if(pv_get_spec_index(msg, &p, &idx, &idxf))
+	{
+		LM_ERR("invalid index\n");
+		return -1;
+	}
+
+	if (xbuff_is_attr_set(attr)) {
+		LM_ERR("read only attribute %.*s\n",STR_FMT(&xbuff_attr_name(attr)));
+		return -1;
+	}
+
+	/* check container type */
+
+	if (xbuff->val.v.xavp == NULL) {
+		xbuff->val.type = SR_XTYPE_XAVP;
+		xbuff->val.v.xavp = xbuff_xavp;
+		return 0;
+	}
+
+	switch (xbuff->val.v.xavp->name.s[0]) {
+	case 'l': /* list  */
+	case 't': /* tuple */
+
+		/* prepend on list when no index */
+		if (xbuff_is_no_index(attr)) {
+			return xavp_add(xbuff_xavp,&xbuff->val.v.xavp);
+		}
+
+		/* reset list given value */
+		if (idxf == PV_IDX_ALL) {
+			xavp_destroy_list(&xbuff->val.v.xavp);
+			if (xbuff_xavp->val.type == SR_XTYPE_NULL) {
+				/* create empty list/tuple */
+				xavp_destroy_list(&xbuff_xavp);
+				return 0;
+			} else {
+				return xavp_add(xbuff_xavp,&xbuff->val.v.xavp);
+			}
+		}
+
+		/* set by index */
+		old = xavp_get_nth(&xbuff->val.v.xavp,idx,&prv);
+		new = xbuff_xavp;
+
+		if (old) {
+			new->next = old->next;
+			if (prv) {
+				prv->next = new;
+			} else {
+				new->next = old->next;
+				xbuff->val.v.xavp = new;
+			}
+			old->next = NULL;
+			xavp_destroy_list(&old);
+		} else {
+			if (prv) {
+				prv->next = new;
+			} else {
+				xbuff->val.v.xavp = new;
+			}
+		}
+		break;
+	case 'n': /* null (empty) */
+	case 's': /* string  */
+	case 'a': /* atom    */
+	case 'i': /* integer */
+	default:  /* default */
+		xavp_destroy_list(&xbuff->val.v.xavp);
+		xbuff->val.v.xavp = xbuff_xavp;
+		break;
+	}
+
+	return 0;
+
+err:
+	LM_ERR("failed to add value into xbuff\n");
+	xavp_destroy_list(&xbuff_xavp);
+
+	return -1;
+}
+
+int pv_xbuff_get_value(struct sip_msg *msg, pv_param_t *param,
+		pv_value_t *res, sr_xavp_t *avp)
+{
+	static char _pv_xavp_buf[128];
+	str s;
+
+	if (!avp) return pv_get_null(msg,param,res);
+
+	switch(avp->val.type) {
+	case SR_XTYPE_NULL:
+		return pv_get_null(msg, param, res);
+		break;
+	case SR_XTYPE_INT:
+		return pv_get_sintval(msg, param, res, avp->val.v.i);
+		break;
+	case SR_XTYPE_STR:
+		switch (avp->name.s[0]) {
+		case 'a':
+			if(snprintf(_pv_xavp_buf, 128, "<<atom:%p>>", avp->val.v.xavp)<0)
+				return pv_get_null(msg, param, res);
+			break;
+		default:
+			return pv_get_strval(msg, param, res, &avp->val.v.s);
+		}
+		break;
+	case SR_XTYPE_TIME:
+		if(snprintf(_pv_xavp_buf, 128, "%lu", (long unsigned)avp->val.v.t)<0)
+			return pv_get_null(msg, param, res);
+		break;
+	case SR_XTYPE_LONG:
+		if(snprintf(_pv_xavp_buf, 128, "%ld", (long unsigned)avp->val.v.l)<0)
+			return pv_get_null(msg, param, res);
+		break;
+	case SR_XTYPE_LLONG:
+		if(snprintf(_pv_xavp_buf, 128, "%lld", avp->val.v.ll)<0)
+			return pv_get_null(msg, param, res);
+		break;
+	case SR_XTYPE_DATA:
+		switch (avp->name.s[0]) {
+		case 'p':
+			if(snprintf(_pv_xavp_buf, 128, "<<pid:%p>>", avp->val.v.data)<0)
+				return pv_get_null(msg, param, res);
+			break;
+		case 'r':
+			if(snprintf(_pv_xavp_buf, 128, "<<ref:%p>>", avp->val.v.data)<0)
+				return pv_get_null(msg, param, res);
+			break;
+		default:
+			if(snprintf(_pv_xavp_buf, 128, "<<binary:%p>>", avp->val.v.data)<0)
+				return pv_get_null(msg, param, res);
+		}
+		break;
+	case SR_XTYPE_XAVP:
+		switch(avp->name.s[0]) {
+		case 't':
+			if(snprintf(_pv_xavp_buf, 128, "<<tuple:%p>>", avp->val.v.xavp)<0)
+				return pv_get_null(msg, param, res);
+			break;
+		case 'l':
+		default:
+			if(snprintf(_pv_xavp_buf, 128, "<<list:%p>>", avp->val.v.xavp)<0)
+				return pv_get_null(msg, param, res);
+//			break;
+//		default:
+//			LM_ERR("unexpected type!\n");
+//			return pv_get_null(msg, param, res);
+		}
+		break;
+	default:
+		return pv_get_null(msg, param, res);
+	}
+	s.s = _pv_xavp_buf;
+	s.len = strlen(_pv_xavp_buf);
+	return pv_get_strval(msg, param, res, &s);
+}
+
+int pv_xbuff_get(struct sip_msg* msg,  pv_param_t* param, pv_value_t* res)
+{
+	str name;
+	pv_spec_t *nsp = NULL;
+	pv_name_t *pvn;
+	pv_index_t *pvi;
+	sr_xavp_t *xbuffs_root;
+	sr_xavp_t *xbuff;
+	sr_xavp_t *xavp;
+	pv_param_t p;
+	int idx=0;
+	int idxf=0;
+	int attr;
+	int i,count;
+
+	ei_x_buff x_buff;
+
+	if(param==NULL)
+	{
+		LM_ERR("bad parameters\n");
+		return -1;
+	}
+
+	if (param->pvn.type != PV_NAME_INTSTR || !(param->pvn.u.isname.type & AVP_NAME_STR))
+				return -1;
+
+	if( param->pvn.type == PV_NAME_PVAR) {
+			nsp = param->pvn.u.dname;
+	}
+
+	/* work on copy of index! */
+	p = *param;
+
+	if (nsp) {
+		pvi = &nsp->pvp.pvi;
+		pvn = &nsp->pvp.pvn;
+	} else {
+		pvi = &p.pvi;
+		pvn = &p.pvn;
+	}
+
+	/* list name */
+	name = pvn->u.isname.name.s;
+
+	/* fix index */
+	attr = xbuff_get_attr_flags(pvi->type);
+	pvi->type = xbuff_fix_index(pvi->type);
+
+	/* get the index */
+	if(pv_get_spec_index(msg, &p, &idx, &idxf))
+	{
+		LM_ERR("invalid index\n");
+		return -1;
+	}
+
+	xbuffs_root = xavp_get_xbuffs();
+	if(!xbuffs_root) {
+		return pv_get_null(msg,param,res);
+	}
+
+	xbuff = xavp_get(&name,xbuffs_root->val.v.xavp);
+	if (!xbuff) {
+		return pv_get_null(msg,param,res);
+	}
+
+	xavp = xbuff->val.v.xavp;
+
+	switch (xbuff_is_attr_set(attr)) {
+	case XBUFF_ATTR_TYPE:
+		if (xbuff_is_no_index(attr)) {
+			return pv_xbuff_get_type(msg,param,res,xavp);
+		} else {
+			if(xavp && (xavp->name.s[0]=='l'||xavp->name.s[0]=='t')) {
+				xavp=xavp->val.v.xavp;
+			}
+			xavp = xavp_get_nth(&xavp,idx,NULL);
+			return pv_xbuff_get_type(msg,param,res,xavp);
+		}
+		break;
+	case XBUFF_ATTR_LENGTH:
+		if (xbuff_is_no_index(attr)) {
+			xavp = xbuff->val.v.xavp;
+		} else {
+			if(xavp && (xavp->name.s[0]=='l'||xavp->name.s[0]=='t')) {
+				xavp=xavp->val.v.xavp;
+			}
+			xavp = xavp_get_nth(&xavp,idx,NULL);
+		}
+		count = xavp ? xavp_get_count(xavp->val.v.xavp) : 0;
+		return pv_get_uintval(msg,param,res,(unsigned int)count);
+		break;
+	case XBUFF_ATTR_FORMAT:
+		if (xbuff_is_no_index(attr)) {
+			xavp = xbuff->val.v.xavp;
+		} else {
+			if(xavp && (xavp->name.s[0]=='l'||xavp->name.s[0]=='t')) {
+				xavp=xavp->val.v.xavp;
+			}
+			xavp = xavp_get_nth(&xavp,idx,NULL);
+		}
+
+		/*
+		 * Prints a term, in clear text, to the PV value pointed to by res.
+		 * It tries to resemble the term printing in the erlang shell.
+		 */
+		ei_x_new_with_version(&x_buff);
+		if (!xavp || xavp_encode(&x_buff,xavp,1)) {
+			ei_x_free(&x_buff);
+			return pv_get_null(msg,param,res);
+		}
+
+		i = 1;
+		if (ei_s_print_term(&xbuff_fmt_buff,x_buff.buff,&i)<0) {
+			LM_ERR("BUG: xbuff doesn't contain a valid term!\n");
+			ei_x_free(&x_buff);
+			return -1;
+		}
+		i = pv_get_strzval(msg,param,res,xbuff_fmt_buff);
+		ei_x_free(&x_buff);
+		return i;
+	}
+
+	if (!xavp) {
+		return pv_get_null(msg,param,res);
+	}
+
+	/* get whole xbuff */
+	if (idxf == PV_IDX_ALL) {
+		return pv_xbuff_get_value(msg,param,res,xavp);
+	}
+
+	/* get by idx */
+	if (xavp->name.s[0]=='l'||xavp->name.s[0]=='t') {
+		xavp = xavp->val.v.xavp;
+	}
+
+	xavp = xavp_get_nth(&xavp,idx,NULL);
+	if (!xavp) {
+		return pv_get_null(msg,param,res);
+	}
+
+	return pv_xbuff_get_value(msg,param,res,xavp);
+}
+
+/**
+ * Recursive copy XAVPs, preserve order
+ */
+sr_xavp_t *xbuff_copy_xavp(sr_xavp_t *xavp)
+{
+	sr_xavp_t *new = NULL;
+	sr_xavp_t *cp  = NULL;
+
+	if (!xavp) return NULL;
+
+	while (xavp) {
+		if (new) {
+			new->next = xavp_new_value(&xavp->name,&xavp->val);
+			new = new->next;
+		} else {
+			new = xavp_new_value(&xavp->name,&xavp->val);
+		}
+
+		if (!new) {
+			LM_ERR("not enough memory\n");
+			return cp;
+		}
+
+		if (!cp) cp = new;
+
+		if (xavp->val.type == SR_XTYPE_XAVP)
+			new->val.v.xavp = xbuff_copy_xavp(xavp->val.v.xavp);
+
+		xavp = xavp->next;
+	}
+
+	return cp;
+}
+
+/**
+ * XAVP extension
+ */
+
+/* copy from xavp.c (not exported from XAVP) */
+sr_xavp_t *xavp_new_value(str *name, sr_xval_t *val)
+{
+	sr_xavp_t *avp;
+	int size;
+	unsigned int id;
+
+	if(name==NULL || name->s==NULL || val==NULL)
+		return NULL;
+	id = get_hash1_raw(name->s, name->len);
+
+	size = sizeof(sr_xavp_t) + name->len + 1;
+	if(val->type == SR_XTYPE_STR)
+		size += val->v.s.len + 1;
+	avp = (sr_xavp_t*)shm_malloc(size);
+	if(avp==NULL)
+		return NULL;
+	memset(avp, 0, size);
+	avp->id = id;
+	avp->name.s = (char*)avp + sizeof(sr_xavp_t);
+	memcpy(avp->name.s, name->s, name->len);
+	avp->name.s[name->len] = '\0';
+	avp->name.len = name->len;
+	memcpy(&avp->val, val, sizeof(sr_xval_t));
+	if(val->type == SR_XTYPE_STR)
+	{
+		avp->val.v.s.s = avp->name.s + avp->name.len + 1;
+		memcpy(avp->val.v.s.s, val->v.s.s, val->v.s.len);
+		avp->val.v.s.s[val->v.s.len] = '\0';
+		avp->val.v.s.len = val->v.s.len;
+	}
+
+	return avp;
+}
+
+sr_xavp_t *xavp_get_nth(sr_xavp_t **list, int idx, sr_xavp_t **prv)
+{
+	sr_xavp_t *avp;
+	int n = 0;
+
+	if (list && *list)
+		avp = *list;
+	else
+		return NULL;
+
+	while (avp) {
+
+		if (idx == n)
+			return avp;
+		n++;
+
+		if (prv)
+			*prv = avp;
+
+		avp = avp->next;
+	}
+
+	return NULL;
+}
+
+/**
+ * Encode XAVPs into ei_x_buff
+ */
+int xavp_encode(ei_x_buff *xbuff, sr_xavp_t *xavp,int level)
+{
+	int n;
+
+	while(xavp) {
+		switch (xavp->name.s[0]) {
+		case 'a':
+			ei_x_encode_atom_len(xbuff,xavp->val.v.s.s,xavp->val.v.s.len);
+			break;
+		case 's':
+			ei_x_encode_string_len(xbuff,xavp->val.v.s.s,xavp->val.v.s.len);
+			break;
+		case 'i':
+			ei_x_encode_long(xbuff,xavp->val.v.i);
+			break;
+		case 't':
+			n = xavp_get_count(xavp->val.v.xavp);
+			ei_x_encode_tuple_header(xbuff,n);
+			if (xavp_encode(xbuff,xavp->val.v.xavp,level+1)) return -1;
+			break;
+		case 'l':
+			n = xavp_get_count(xavp->val.v.xavp);
+			ei_x_encode_list_header(xbuff, n);
+			if (xavp_encode(xbuff, xavp->val.v.xavp, level + 1)) return -1;
+			ei_x_encode_empty_list(xbuff);
+			break;
+		case 'p':
+			ei_x_encode_pid(xbuff,xavp->val.v.data->p);
+			break;
+		case 'r':
+			ei_x_encode_ref(xbuff,xavp->val.v.data->p);
+			break;
+		case 'n':
+			ei_x_encode_atom(xbuff,"undefined");
+			break;
+		default:
+			LM_ERR("BUG: unknown type for %.*s\n",STR_FMT(&xavp->name));
+			return -1;
+		}
+		xavp = xavp->next;
+	}
+
+	return 0;
+}
+
+/**
+ * Decode XAVP from ei_x_buff
+ */
+int xavp_decode(ei_x_buff *xbuff, int *index, sr_xavp_t **xavp,int level)
+{
+	int i=0;
+	int type, size, arity;
+	int l;
+	char _s[128];
+	char _fmt[128];
+	str name;
+	sr_xval_t val;
+	sr_xavp_t **tail;
+	sr_xavp_t *new;
+	char *pbuf=0;
+	erlang_pid *pid;
+	erlang_ref *ref;
+	erlang_fun fun;
+	double d;
+	char *p = NULL;
+	sr_data_t *data;
+
+	name.s = _s;
+
+	if (!xavp || !xbuff) return -1;
+
+	if (ei_get_type(xbuff->buff,index,&type,&size)) {
+		LM_ERR("failed to get type\n");
+		return -1;
+	}
+
+
+	switch (type) {
+	case ERL_ATOM_EXT:
+#ifdef ERL_SMALL_ATOM_EXT
+	case ERL_SMALL_ATOM_EXT:
+#endif
+		name.len = snprintf(_s,sizeof(_s),"a%d",counter++);
+		pbuf = (char*)pkg_realloc(pbuf,size+1);
+
+		if (!pbuf) {
+			LM_ERR("not enough memory!\n");
+			return -1;
+		}
+
+		ei_decode_atom(xbuff->buff,index,pbuf);
+
+		val.type = SR_XTYPE_STR;
+		val.v.s.s = pbuf;
+		val.v.s.len = size;
+
+		*xavp = xavp_new_value(&name,&val);
+		if (!*xavp) {
+			LM_ERR("failed to create new xavp!\n");
+			goto err;
+		}
+
+		break;
+	case ERL_LIST_EXT:
+	case ERL_SMALL_TUPLE_EXT:
+	case ERL_LARGE_TUPLE_EXT:
+
+		name.len = snprintf(_s,sizeof(_s),"%c%d", type == ERL_LIST_EXT ? 'l' : 't', counter++);
+
+		val.v.xavp = NULL;
+
+		if (type == ERL_LIST_EXT) {
+			ei_decode_list_header(xbuff->buff,index,&arity);
+		} else {
+			ei_decode_tuple_header(xbuff->buff,index,&arity);
+		}
+
+		if (arity == 0) {
+			val.type = SR_XTYPE_NULL;
+		} else {
+			val.type = SR_XTYPE_XAVP;
+		}
+
+		*xavp = xavp_new_value(&name,&val);
+		if (!*xavp) {
+			LM_ERR("failed to create new xavp!\n");
+			goto err;
+		}
+
+		tail = &(*xavp)->val.v.xavp;
+
+		for(l=0;l<arity;l++) {
+
+			new = NULL;
+
+			if (xavp_decode(xbuff,index,&new,level+1)) {
+				LM_ERR("failed to decode %.*s\n",STR_FMT(&name));
+				return -1;
+			}
+
+			if (!new) {
+				LM_ERR("failed to create new xavp!\n");
+				goto err;
+			}
+
+			*tail = new;
+			tail = &new->next;
+		}
+
+		break;
+	case ERL_STRING_EXT:
+		name.len = snprintf(_s,sizeof(_s),"s%d",counter++);
+
+		pbuf = (char*)pkg_realloc(pbuf,size+1);
+
+		if (!pbuf) {
+			LM_ERR("not enough memory!\n");
+			return -1;
+		}
+
+		ei_decode_string(xbuff->buff,index,pbuf);
+
+		val.type = SR_XTYPE_STR;
+		val.v.s.s = pbuf;
+		val.v.s.len = size;
+
+		*xavp = xavp_new_value(&name,&val);
+		if (!*xavp) {
+			LM_ERR("failed to create new xavp!\n");
+			goto err;
+		}
+		break;
+	case ERL_SMALL_INTEGER_EXT:
+		name.len = snprintf(_s,sizeof(_s),"i%d",counter++);
+
+		ei_decode_long(xbuff->buff,index,&val.v.l);
+		val.type = SR_XTYPE_INT;
+
+		*xavp = xavp_new_value(&name,&val);
+		if (!*xavp) {
+			LM_ERR("failed to create new xavp!\n");
+			goto err;
+		}
+		break;
+	case ERL_SMALL_BIG_EXT:
+	case ERL_INTEGER_EXT:
+		name.len = snprintf(_s,sizeof(_s),"i%d",counter++);
+
+		if (size > sizeof(long)) {
+			ei_decode_longlong(xbuff->buff,index,&val.v.ll);
+			val.type = SR_XTYPE_LLONG;
+		} else {
+			ei_decode_long(xbuff->buff,index,&val.v.l);
+			val.type = SR_XTYPE_LONG;
+		}
+
+		*xavp = xavp_new_value(&name,&val);
+		if (!*xavp) {
+			LM_ERR("failed to create new xavp!\n");
+			goto err;
+		}
+		break;
+	case ERL_FLOAT_EXT:
+	case NEW_FLOAT_EXT:
+		name.len = snprintf(_s,sizeof(_s),"s%d",counter++);
+
+		ei_decode_double(xbuff->buff,index,&d);
+		val.v.s.s = _fmt;
+		val.v.s.len = snprintf(_fmt,sizeof(_fmt),"%g",d);
+
+		val.type = SR_XTYPE_STR;
+
+		*xavp = xavp_new_value(&name,&val);
+		if (!*xavp) {
+			LM_ERR("failed to create new xavp!\n");
+			goto err;
+		}
+		break;
+
+	case ERL_PID_EXT:
+		name.len = snprintf(_s,sizeof(_s),"p%d",counter++);
+
+		data = (sr_data_t*)shm_malloc(sizeof(sr_data_t)+sizeof(erlang_pid));
+		if (!data) {
+			LM_ERR("not enough shared memory\n");
+			goto err;
+		}
+
+		memset((void*)data,0,sizeof(sr_data_t)+sizeof(erlang_pid));
+
+		data->p = pid = (void*)data+sizeof(sr_data_t);
+		data->pfree = xbuff_data_free;
+
+		if (ei_decode_pid(xbuff->buff,index,pid)<0) {
+			LM_ERR("failed to decode pid\n");
+			shm_free(data);
+			goto err;
+		}
+
+		val.type = SR_XTYPE_DATA;
+		val.v.data = data;
+
+		*xavp = xavp_new_value(&name,&val);
+		if (!*xavp) {
+			LM_ERR("failed to create new xavp!\n");
+			shm_free(data);
+			goto err;
+		}
+
+		break;
+	case ERL_REFERENCE_EXT:
+	case ERL_NEW_REFERENCE_EXT:
+		name.len = snprintf(_s,sizeof(_s),"r%d",counter++);
+
+		data = (sr_data_t*)shm_malloc(sizeof(sr_data_t)+sizeof(erlang_ref));
+		if (!data) {
+			LM_ERR("not enough shared memory\n");
+			goto err;
+		}
+
+		memset((void*)data,0,sizeof(sr_data_t)+sizeof(erlang_ref));
+
+		data->p = ref = (void*)data+sizeof(sr_data_t);
+		data->pfree = xbuff_data_free;
+
+		if (ei_decode_ref(xbuff->buff,index,ref)<0) {
+			LM_ERR("failed to decode pid\n");
+			shm_free(data);
+			goto err;
+		}
+
+		val.type = SR_XTYPE_DATA;
+		val.v.data = data;
+
+		*xavp = xavp_new_value(&name,&val);
+		if (!*xavp) {
+			LM_ERR("failed to create new xavp!\n");
+			shm_free(data);
+			goto err;
+		}
+
+		break;
+	case ERL_FUN_EXT:
+		name.len = snprintf(_s,sizeof(_s),"s%d",counter++);
+		i = *index;
+
+		ei_decode_fun(xbuff->buff,index,&fun);
+
+		if (ei_s_print_term(&p,xbuff->buff,&i)<0) {
+			LM_ERR("failed to decode fun\n");
+			goto err;
+		}
+		val.type = SR_XTYPE_STR;
+		val.v.s.s = p;
+		val.v.s.len = strlen(p);
+
+		*xavp = xavp_new_value(&name,&val);
+		if (!*xavp) {
+			LM_ERR("failed to create new xavp!\n");
+			goto err;
+		}
+		break;
+	default:
+		LM_ERR("unknown type %c(%d)\n",(char)type,type);
+	}
+
+	pkg_free(pbuf);
+	free(p);
+	return 0;
+
+err:
+	pkg_free(pbuf);
+	free(p);
+	return -1;
+}
+
+int xavp_get_count(sr_xavp_t *list)
+{
+	int count = 0;
+
+	while(list) {
+		list = list->next;
+		count++;
+	}
+	return count;
+}
+
+/*
+ * free format buffer for list
+ */
+void free_xbuff_fmt_buff() {
+	if (xbuff_fmt_buff) {
+		free(xbuff_fmt_buff);
+	}
+	xbuff_fmt_buff = 0;
+}
+
+void xbuff_destroy_all()
+{
+	sr_xavp_t *list;
+	list = xavp_get_xbuffs();
+	if (list) xavp_destroy_list(&list);
+}
+
+/* does nothing but must be executed in xavp_free[_unsafe] */
+void xbuff_data_free(void *p, sr_xavp_sfree_f sfree) {
+}
diff --git a/modules/erlang/pv_xbuff.h b/modules/erlang/pv_xbuff.h
new file mode 100644
index 0000000..aebaaac
--- /dev/null
+++ b/modules/erlang/pv_xbuff.h
@@ -0,0 +1,103 @@
+/**
+ * Copyright (C) 2015 Bicom Systems Ltd, (bicomsystems.com)
+ *
+ * Author: Seudin Kasumovic (seudin.kasumovic at gmail.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef PV_XBUFF_H_
+#define PV_XBUFF_H_
+
+#include "../../pvar.h"
+#include "../../xavp.h"
+
+#include <regex.h>
+#include <ei.h>
+
+typedef enum {
+	XBUFF_ATTR_TYPE   = (1<<2),
+	XBUFF_ATTR_FORMAT = (1<<3),
+	XBUFF_ATTR_LENGTH = (1<<4),
+	XBUFF_NO_IDX      = (1<<5)
+} xbuff_attr_t;
+
+typedef enum {
+	XBUFF_TYPE_ATOM,
+	XBUFF_TYPE_INT,
+	XBUFF_TYPE_STR,
+	XBUFF_TYPE_TUPLE,
+	XBUFF_TYPE_LIST,
+	XBUFF_TYPE_PID,
+	XBUFF_TYPE_REF,
+	XBUFF_TYPE_COUNT
+} xbuff_type_t;
+
+#define XBUFF_IDX_MASK      3
+
+int pv_xbuff_parse_name(pv_spec_t *sp, str *in);
+int pv_xbuff_new_xavp(sr_xavp_t **new, pv_value_t *pval, int *counter, char prefix);
+int pv_xbuff_get_type(struct sip_msg *msg, pv_param_t *param,
+		pv_value_t *res, sr_xavp_t *avp);
+
+sr_xavp_t *pv_xbuff_get_xbuff(str *name);
+int xavp_decode(ei_x_buff *xbuff, int *index, sr_xavp_t **xavp,int level);
+sr_xavp_t *xbuff_new(str *name);
+
+extern str xbuff_attributes[];
+
+extern str xbuff_types[];
+
+#define xbuff_attr_name(flag) (xbuff_attributes[(flag)>>XBUFF_IDX_MASK])
+#define xbuff_set_attr_flag(type,flag) type |= flag
+#define xbuff_get_attr_flags(type) ((type)&~XBUFF_IDX_MASK)
+#define xbuff_is_attr_set(flags) ((attr)&~XBUFF_NO_IDX)
+#define xbuff_is_no_index(attr) ((attr)&XBUFF_NO_IDX)
+#define xbuff_fix_index(type) ((type)&XBUFF_IDX_MASK)
+
+int compile_xbuff_re();
+int xbuff_match_type_re(str *s, xbuff_type_t *type, sr_xavp_t **addr);
+
+int is_pv_xbuff_valid_char(char c);
+
+sr_xavp_t *xbuff_copy_xavp(sr_xavp_t *xavp);
+
+int pv_xbuff_set(struct sip_msg*, pv_param_t*, int, pv_value_t*);
+int pv_xbuff_get(struct sip_msg*, pv_param_t*, pv_value_t*);
+void free_xbuff_fmt_buff();
+
+/* destroy all xbuffs */
+void xbuff_destroy_all();
+
+/**
+ * atom,tuple,xbuf,pid and list
+ */
+extern regex_t xbuff_type_re;
+
+/**
+ * XAVP extension
+ */
+
+sr_xavp_t *xavp_new_value(str *name, sr_xval_t *val);
+sr_xavp_t *xavp_get_nth(sr_xavp_t **list, int idx, sr_xavp_t **prv);
+int xavp_get_count(sr_xavp_t *list);
+int xavp_encode(ei_x_buff *xbuff, sr_xavp_t *xavp,int level);
+
+void xbuff_data_free(void *p, sr_xavp_sfree_f sfree);
+
+#endif /* PV_XBUFF_H_ */
diff --git a/modules/erlang/worker.c b/modules/erlang/worker.c
new file mode 100644
index 0000000..0bf1be8
--- /dev/null
+++ b/modules/erlang/worker.c
@@ -0,0 +1,452 @@
+/**
+ * Copyright (C) 2015 Bicom Systems Ltd, (bicomsystems.com)
+ *
+ * Author: Seudin Kasumovic (seudin.kasumovic at gmail.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <stdlib.h>
+#include "worker.h"
+#include "cnode.h"
+#include "../../mem/mem.h"
+
+#include "erl_api.h"
+
+int worker_rpc_impl(ei_cnode *ec, int s, int wpid);
+int worker_reg_send_impl(ei_cnode *ec, int s, int wpid);
+int worker_send_impl(ei_cnode *ec, int s, int wpid);
+
+int worker_init(worker_handler_t *phandler, int fd, const ei_cnode *ec)
+{
+	if (erl_set_nonblock(fd)){
+		LM_ERR("set non blocking failed\n");
+	}
+
+	phandler->handle_f = handle_worker;
+	phandler->wait_tmo_f = wait_tmo_worker;
+	phandler->destroy_f = NULL;
+	phandler->sockfd = fd;
+	phandler->ec = *ec;
+	phandler->next = NULL;
+
+	return 0;
+}
+
+int handle_worker(handler_common_t *phandler)
+{
+	worker_handler_t* w = (worker_handler_t*)phandler;
+	struct msghdr msg;
+	struct iovec cnt[2];
+	int wpid = 0;
+	eapi_t api;
+	int rc;
+
+	/* ensure be connected */
+	enode_connect();
+
+	memset((void*)&msg,0,sizeof(msg));
+
+	/* Kamailio worker PID */
+	cnt[0].iov_base = &wpid;
+	cnt[0].iov_len  = sizeof(wpid);
+
+	/* method */
+	cnt[1].iov_base = &api;
+	cnt[1].iov_len  = sizeof(api);
+
+	msg.msg_iov = cnt;
+	msg.msg_iovlen = 2;
+
+	while ((rc = recvmsg(w->sockfd, &msg, MSG_WAITALL)) == -1 && errno == EAGAIN)
+		;
+
+	if (rc < 0){
+		LM_ERR("recvmsg failed (socket=%d): %s\n",w->sockfd,strerror(errno));
+		return -1;
+	}
+
+	switch(api) {
+	case API_RPC_CALL:
+		if (worker_rpc_impl(&w->ec,w->sockfd,wpid))
+			return -1;
+		break;
+	case API_REG_SEND:
+		if (worker_reg_send_impl(&w->ec,w->sockfd,wpid))
+			return -1;
+		break;
+	case API_SEND:
+		if (worker_send_impl(&w->ec,w->sockfd,wpid))
+			return -1;
+		break;
+	default:
+		LM_ERR("BUG: bad method or not implemented!\n");
+		return 1;
+	}
+
+	return 0;
+}
+
+int wait_tmo_worker(handler_common_t* phandler){
+
+	return 0;
+}
+
+/**
+ * internal implementation
+ */
+int worker_rpc_impl(ei_cnode *ec, int s,int wpid)
+{
+	str module = STR_NULL;
+	str function = STR_NULL;
+	ei_x_buff args;
+	ei_x_buff reply;
+	struct msghdr msgh;
+	struct iovec cnt[6];
+	int rc;
+
+	memset((void*)&args,0,sizeof(args));
+	memset((void*)&reply,0,sizeof(reply));
+	memset((void*)&msgh,0,sizeof(msgh));
+
+	/* module name length */
+	cnt[0].iov_base = &module.len;
+	cnt[0].iov_len  = sizeof(int);
+
+	/* function name length */
+	cnt[1].iov_base = &function.len;
+	cnt[1].iov_len  = sizeof(int);
+
+	/* Erlang args size */
+	cnt[2].iov_base = &args.buffsz;
+	cnt[2].iov_len  = sizeof(int);
+
+	/* get data size */
+	msgh.msg_iov    = cnt;
+	msgh.msg_iovlen = 3;
+	while ((rc = recvmsg(s, &msgh, MSG_PEEK)) == -1 && errno == EAGAIN)
+		;
+
+	if (rc == -1){
+		LM_ERR("recvmsg failed (socket=%d): %s\n",s,strerror(errno));
+		goto err;
+	}
+
+	/* allocate space */
+	module.s = (char*)pkg_malloc(module.len+1);
+	if (!module.s) {
+		LM_ERR("not enough memory\n");
+		goto err;
+	}
+
+	function.s = (char*)pkg_malloc(function.len+1);
+	if (!function.s) {
+		LM_ERR("not enough memory\n");
+		goto err;
+	}
+
+	args.buff = (char*)malloc(args.buffsz);
+	if (!args.buff) {
+		LM_ERR("malloc: not enough memory\n");
+		goto err;
+	}
+
+	/* buffers */
+	cnt[3].iov_base = module.s;
+	cnt[3].iov_len  = module.len;
+
+	cnt[4].iov_base = function.s;
+	cnt[4].iov_len  = function.len;
+
+	cnt[5].iov_base = args.buff;
+	cnt[5].iov_len  = args.buffsz;
+
+	/* get whole data */
+	msgh.msg_iovlen = 6;
+	while ((rc = recvmsg(s, &msgh, MSG_WAITALL)) == -1 && errno == EAGAIN)
+		;
+
+	if (rc == -1){
+		LM_ERR("recvmsg failed (socket=%d): %s\n",s,strerror(errno));
+		goto err;
+	}
+
+	/* fix str */
+	module.s[module.len] = 0;
+	function.s[function.len] = 0;
+
+	LM_DBG("rpc: %.*s:%.*s(args)\n",STR_FMT(&module),STR_FMT(&function));
+
+	EI_X_BUFF_PRINT(&args);
+
+	if(!enode) {
+		LM_NOTICE("there is no connected Erlang node\n");
+		/* reply up with error */
+		ei_x_format(&reply, "{error,cnode,~a}", "no_erlang_node");
+		goto reply;
+	}
+
+	/* do RPC */
+	if ((rc = ei_rpc(ec,enode->sockfd,module.s,function.s,args.buff,args.buffsz,&reply)) == ERL_ERROR)
+	{
+		reply.index = 0; /* re-use reply buffer */
+
+		if (erl_errno)
+		{
+			ei_x_format(&reply, "{error,cnode,~s}", strerror(erl_errno));
+			LM_ERR("ei_rpc failed on node=<%s> socket=<%d>: %s\n",enode->conn.nodename,enode->sockfd,strerror(erl_errno));
+		}
+		else if (errno)
+		{
+			ei_x_format(&reply, "{error,cnode,~s}", strerror(errno));
+			LM_ERR("ei_rpc failed on node=<%s> socket=<%d>: %s\n",enode->conn.nodename,enode->sockfd,strerror(errno));
+		}
+		else
+		{
+			ei_x_format(&reply, "{error,cnode,~s}", "Unknown error.");
+			LM_ERR("ei_rpc failed on node=<%s> socket=<%d>, Unknown error.\n",ec->thisalivename,enode->sockfd);
+		}
+	}
+
+reply:
+	EI_X_BUFF_PRINT(&reply);
+
+	cnt[0].iov_base = (void*)&wpid;
+	cnt[0].iov_len  = sizeof(int);
+
+	/* send reply to Kamailio worker */
+	cnt[1].iov_base = (void*)&reply.buffsz;
+	cnt[1].iov_len  = sizeof(int);
+
+	cnt[2].iov_base = (void*)reply.buff;
+	cnt[2].iov_len  = reply.buffsz;
+
+	msgh.msg_iovlen = 3;
+	while ((rc = sendmsg(s, &msgh, 0)) == -1 && errno == EAGAIN)
+		;
+
+	if (rc == -1) {
+		LM_ERR("sendmsg failed on socket=%d rpid_no=%d; %s\n",s, wpid, strerror(errno));
+		goto err;
+	};
+
+	pkg_free(module.s);
+	pkg_free(function.s);
+	free(args.buff);
+	ei_x_free(&reply);
+	return 0;
+
+err:
+	pkg_free(module.s);
+	pkg_free(function.s);
+	free(args.buff);
+	ei_x_free(&reply);
+	abort(); /* cant't recover */
+	return -1;
+}
+
+int worker_reg_send_impl(ei_cnode *ec, int s,int wpid)
+{
+	str server = STR_NULL;
+	ei_x_buff emsg;
+	struct msghdr msgh;
+	struct iovec cnt[6];
+	int rc;
+
+	memset((void*)&emsg,0,sizeof(emsg));
+
+	memset((void*)&msgh,0,sizeof(msgh));
+
+	/* server name length */
+	cnt[0].iov_base = &server.len;
+	cnt[0].iov_len  = sizeof(int);
+
+	/* Erlang args size */
+	cnt[1].iov_base = &emsg.buffsz;
+	cnt[1].iov_len  = sizeof(int);
+
+	/* get data size */
+	msgh.msg_iov    = cnt;
+	msgh.msg_iovlen = 2;
+
+	while ((rc = recvmsg(s, &msgh, MSG_PEEK)) == -1 && errno == EAGAIN)
+		;
+
+	if (rc == -1){
+		LM_ERR("recvmsg failed (socket=%d): %s\n",s,strerror(errno));
+		return -1;
+	}
+
+	/* allocate space */
+	server.s = (char*)pkg_malloc(server.len+1);
+	if (!server.s) {
+		LM_ERR("not enough memory\n");
+		goto err;
+	}
+
+	emsg.buff = (char*)malloc(emsg.buffsz);
+	if (!emsg.buff) {
+		LM_ERR("malloc: not enough memory\n");
+		goto err;
+	}
+
+	/* buffers */
+	cnt[2].iov_base = server.s;
+	cnt[2].iov_len  = server.len;
+
+	cnt[3].iov_base = emsg.buff;
+	cnt[3].iov_len  = emsg.buffsz;
+
+	/* get whole data */
+	msgh.msg_iovlen = 4;
+	while ((rc = recvmsg(s, &msgh, MSG_WAITALL)) == -1 && errno == EAGAIN)
+		;
+
+	if (rc == -1){
+		LM_ERR("recvmsg failed (socket=%d): %s\n",s,strerror(errno));
+		goto err;
+	}
+
+	/* fix str */
+	server.s[server.len] = 0;
+
+	if(!enode) {
+		LM_NOTICE("there is no connected Erlang node\n");
+		goto err;
+	}
+
+	LM_DBG(">> {%.*s,'%s'} ! emsg\n",STR_FMT(&server),enode->conn.nodename);
+
+	EI_X_BUFF_PRINT(&emsg);
+
+	/* do ERL_REG_SEND */
+	if ((rc = ei_reg_send(ec,enode->sockfd,server.s,emsg.buff,emsg.buffsz)) == ERL_ERROR)
+	{
+		if (erl_errno)
+		{
+			LM_ERR("ei_reg_send failed on node=<%s> socket=<%d>: %s\n",enode->conn.nodename,enode->sockfd,strerror(erl_errno));
+		}
+		else if (errno)
+		{
+			LM_ERR("ei_reg_send failed on node=<%s> socket=<%d>: %s\n",enode->conn.nodename,enode->sockfd,strerror(errno));
+		}
+		else
+		{
+			LM_ERR("ei_reg_send failed on node=<%s> socket=<%d>, Unknown error.\n",ec->thisalivename,enode->sockfd);
+		}
+	}
+
+	pkg_free(server.s);
+	free(emsg.buff);
+
+	return 0;
+
+err:
+	pkg_free(server.s);
+	free(emsg.buff);
+
+	return -1;
+}
+
+int worker_send_impl(ei_cnode *ec, int s,int wpid)
+{
+	erlang_pid pid;
+	ei_x_buff emsg;
+	struct msghdr msgh;
+	struct iovec cnt[6];
+	int rc;
+
+	memset((void*)&emsg,0,sizeof(emsg));
+
+	memset((void*)&msgh,0,sizeof(msgh));
+
+	/* Erlang args size */
+	cnt[0].iov_base = &emsg.buffsz;
+	cnt[0].iov_len  = sizeof(int);
+
+	/* get data size */
+	msgh.msg_iov    = cnt;
+	msgh.msg_iovlen = 1;
+
+	while ((rc = recvmsg(s, &msgh, MSG_PEEK)) == -1 && errno == EAGAIN)
+		;
+
+	if (rc == -1){
+		LM_ERR("recvmsg failed (socket=%d): %s\n",s,strerror(errno));
+		return -1;
+	}
+
+	emsg.buff = (char*)malloc(emsg.buffsz);
+	if (!emsg.buff) {
+		LM_ERR("malloc: not enough memory\n");
+		goto err;
+	}
+
+	/* buffers */
+	cnt[1].iov_base = &pid;
+	cnt[1].iov_len  = sizeof(erlang_pid);
+
+	cnt[2].iov_base = emsg.buff;
+	cnt[2].iov_len  = emsg.buffsz;
+
+	/* get whole data */
+	msgh.msg_iovlen = 3;
+	while ((rc = recvmsg(s, &msgh, MSG_WAITALL)) == -1 && errno == EAGAIN)
+		;
+
+	if (rc == -1){
+		LM_ERR("recvmsg failed (socket=%d): %s\n",s,strerror(errno));
+		goto err;
+	}
+
+	if(!enode) {
+		LM_NOTICE("there is no connected Erlang node\n");
+		goto err;
+	}
+
+	LM_DBG(">> <%s.%d.%d> ! emsg\n",pid.node,pid.num,pid.serial);
+
+	EI_X_BUFF_PRINT(&emsg);
+
+	/* do ERL_SEND */
+	if ((rc = ei_send(enode->sockfd,&pid,emsg.buff,emsg.buffsz)) == ERL_ERROR)
+	{
+		if (erl_errno)
+		{
+			LM_ERR("ei_send failed on node=<%s> socket=<%d>: %s\n",enode->conn.nodename,enode->sockfd,strerror(erl_errno));
+		}
+		else if (errno)
+		{
+			LM_ERR("ei_send failed on node=<%s> socket=<%d>: %s\n",enode->conn.nodename,enode->sockfd,strerror(errno));
+		}
+		else
+		{
+			LM_ERR("ei_send failed on node=<%s> socket=<%d>, Unknown error.\n",ec->thisalivename,enode->sockfd);
+		}
+	}
+
+	free(emsg.buff);
+
+	return 0;
+
+err:
+
+	free(emsg.buff);
+
+	return -1;
+}
diff --git a/modules/erlang/worker.h b/modules/erlang/worker.h
new file mode 100644
index 0000000..4c29135
--- /dev/null
+++ b/modules/erlang/worker.h
@@ -0,0 +1,59 @@
+/**
+ * Copyright (C) 2015 Bicom Systems Ltd, (bicomsystems.com)
+ *
+ * Author: Seudin Kasumovic (seudin.kasumovic at gmail.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef WORKER_H_
+#define WORKER_H_
+
+#include <ei.h>
+#include "erl_helpers.h"
+
+typedef struct worker_handler_s
+{
+	/* d-linked list  */
+	struct handler_common_s *prev;
+	struct handler_common_s *next;
+
+	/* if need to add new in i/o handler */
+	struct handler_common_s *new;
+
+	/*
+	 * handler for socket pair requests
+	 *
+	 * if function return
+	 * 0  - ok
+	 * -1 - RPC error (we die)
+	 * -2 - remote C Node disconnected (remove node from list)
+	 */
+	int (*handle_f)(handler_common_t *phandler_t);
+	int (*wait_tmo_f)(handler_common_t *phandler_t);
+	int (*destroy_f)(handler_common_t *handler);
+	int sockfd; /* kamailio to cnode socket r/w */
+	ei_cnode ec; /* erlang C node (actually it's me) */
+
+} worker_handler_t;
+
+int worker_init(worker_handler_t *phandler, int fd, const ei_cnode *ec);
+int handle_worker(handler_common_t *phandler_t);
+int wait_tmo_worker(handler_common_t *phandler_t);
+
+#endif /* WORKER_H_ */
diff --git a/modules/exec/Makefile b/modules/exec/Makefile
index 0e6309d..8386673 100644
--- a/modules/exec/Makefile
+++ b/modules/exec/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # exec module makefile
 #
diff --git a/modules/exec/exec.c b/modules/exec/exec.c
index 98a8f6f..4958535 100644
--- a/modules/exec/exec.c
+++ b/modules/exec/exec.c
@@ -1,8 +1,4 @@
 /*
- *
- * $Id$
- *
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
@@ -21,13 +17,28 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History
- * --------
- * 2003-02-28 scratchpad compatibility abandoned (jiri)
- * 2003-01-28 scratchpad removed
- * 2004-07-21 rewrite uri done via action() (bogdan)
  */
 
+/*!
+ * \file
+ * \brief Exec module:: Module interface
+ * \ingroup exec
+ * Module: \ref exec
+ */
+
+/**
+ * @defgroup exec Execute external applications
+ * @brief Kamailio exec module
+ *
+ * The exec module allows external commands to be executed from a Kamailio script.
+ * The commands may be any valid shell commands--the command string is passed to the 
+ * shell using “popen” command. Kamailio passes additional information about the request
+ * in environment variables.
+ *
+ */
+
+
+
 
 #include <stdio.h>
 #include <strings.h>
diff --git a/modules/exec/exec.h b/modules/exec/exec.h
index 4d19732..a9a23c1 100644
--- a/modules/exec/exec.h
+++ b/modules/exec/exec.h
@@ -1,8 +1,4 @@
 /*
- *
- * $Id$
- *
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
@@ -21,6 +17,12 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
+/*!
+ * \file
+ * \brief Exec module:: Module interface
+ * \ingroup exec 
+ * Module: \ref exec
+ */
 
 #ifndef _EXEC_H
 #define _EXEC_H
diff --git a/modules/exec/exec_hf.c b/modules/exec/exec_hf.c
index bbdbaaf..c20c265 100644
--- a/modules/exec/exec_hf.c
+++ b/modules/exec/exec_hf.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,15 +17,15 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * history
- * -------
- *  2003-02-28 scratchpad compatibility abandoned
- *  2003-01-29 scratchpad removed
- *  2003-01-27 next baby-step to removing ZT - PRESERVE_ZT (jiri)
- *  2003-03-19  all mallocs/frees replaced w/ pkg_malloc/pkg_free (andrei)
  */
 
-/* functions for creating environment variables out of a request's
+/*!
+ * \file
+ * \brief Exec module:: Module interface
+ * \ingroup exec 
+ * Module: \ref exec
+ *
+ * functions for creating environment variables out of a request's
  * header; known compact header field names are translated to
  * canonical form; multiple header field occurrences are merged
  * into a single variable
diff --git a/modules/exec/exec_hf.h b/modules/exec/exec_hf.h
index aa6587b..4aa8eeb 100644
--- a/modules/exec/exec_hf.h
+++ b/modules/exec/exec_hf.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
@@ -20,6 +18,13 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
+/*!
+ * \file
+ * \brief Exec module:: Header Field handling
+ * \ingroup exec 
+ * Module: \ref exec
+ */
+
 #ifndef _EXEC_HF_H
 #define _EXEC_HF_H
 
diff --git a/modules/exec/exec_mod.c b/modules/exec/exec_mod.c
index b872456..0e1aa10 100644
--- a/modules/exec/exec_mod.c
+++ b/modules/exec/exec_mod.c
@@ -1,8 +1,6 @@
 /*
  * execution module
  *
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
@@ -21,10 +19,13 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * -------
- * 2003-03-11: New module interface (janakj)
- * 2003-03-16: flags export parameter added (janakj)
+ */
+
+/*!
+ * \file
+ * \brief Exec module:: Module interface
+ * \ingroup exec 
+ * Module: \ref exec
  */
 
 
diff --git a/modules/exec/kill.c b/modules/exec/kill.c
index 643d8c7..51c948e 100644
--- a/modules/exec/kill.c
+++ b/modules/exec/kill.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,10 +17,13 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2003-03-11  changed to the new locking scheme: locking.h (andrei)
- *
+ */
+
+/*!
+ * \file
+ * \brief Exec module:: Kill
+ * \ingroup exec 
+ * Module: \ref exec
  *
  * in this file, we implement the ability to send a kill signal to
  * a child after some time; its a quick ugly hack, for example kill
@@ -36,7 +37,8 @@
  * and last but not least -- we don't know the child pid (we use popen)
  * so we cannot close anyway
  *
- *
+ * From the README:
+ *  (There is kill.c but it is not used along with the current mechanisms based on popen. Besides that kill.c is ugly).
  */
 
 
diff --git a/modules/exec/kill.h b/modules/exec/kill.h
index 8d9ba36..132a105 100644
--- a/modules/exec/kill.h
+++ b/modules/exec/kill.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
@@ -20,6 +18,13 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
+/*!
+ * \file
+ * \brief Exec module:: Kill process
+ * \ingroup exec 
+ * Module: \ref exec
+ */
+
 
 #ifndef _KILL_H
 #define _KILL_H
diff --git a/modules/geoip/Makefile b/modules/geoip/Makefile
index 6052c79..a315246 100644
--- a/modules/geoip/Makefile
+++ b/modules/geoip/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # WARNING: do not run this directly, it should be run by the master Makefile
 
diff --git a/modules/geoip/README b/modules/geoip/README
index a8ac4cc..ed56446 100644
--- a/modules/geoip/README
+++ b/modules/geoip/README
@@ -68,7 +68,9 @@ Chapter 1. Admin Guide
 1. Overview
 
    This module allows real-time queries against the Max Mind GeoIP
-   database to be performed from the config script.
+   database to be performed from the config script. It uses the old
+   version of API, still very common on OS distributions. For using the
+   new version of GeoIP API, see geoip2 module.
 
    The Max Mind GeoIP database is a map of IP network address assignments
    to geographical locales that can be useful -- though approximate -- in
@@ -160,6 +162,7 @@ if(geoip_match("$si", "src"))
           + regc - region
           + regn - region name
           + metro - metro code
+          + contc - continent code
 
    Exported pseudo-variables are documented at
-   http://www.kamailio.org/dokuwiki/.
+   http://www.kamailio.org/wiki/.
diff --git a/modules/geoip/doc/geoip_admin.xml b/modules/geoip/doc/geoip_admin.xml
index 7bd6427..e4db7e7 100644
--- a/modules/geoip/doc/geoip_admin.xml
+++ b/modules/geoip/doc/geoip_admin.xml
@@ -18,7 +18,9 @@
 	<title>Overview</title>
 	<para>
 		This module allows real-time queries against the Max Mind GeoIP 
-		database to be performed from the config script.  
+		database to be performed from the config script. It uses the old
+		version of API, still very common on OS distributions. For using
+		the new version of GeoIP API, see geoip2 module.
 	</para>
 	<para>
 		The Max Mind GeoIP database is a map of IP network address assignments 
@@ -182,6 +184,9 @@ if(geoip_match("$si", "src"))
 				<listitem><para>
 					<emphasis>metro</emphasis> - metro code
 				</para></listitem>
+				<listitem><para>
+					<emphasis>contc</emphasis> - continent code
+				</para></listitem>
 			</itemizedlist>
 			</listitem>
 		</itemizedlist>
diff --git a/modules/geoip/geoip_pv.c b/modules/geoip/geoip_pv.c
index 60f37ca..46c4dff 100644
--- a/modules/geoip/geoip_pv.c
+++ b/modules/geoip/geoip_pv.c
@@ -210,6 +210,8 @@ int pv_parse_geoip_name(pv_spec_p sp, str *in)
 		case 5: 
 			if(strncmp(pvs.s, "metro", 5)==0)
 				gpv->type = 12;
+			else if(strncmp(pvs.s, "contc", 5)==0)
+				gpv->type = 13;
 			else goto error;
 		break;
 		default:
@@ -349,6 +351,11 @@ int pv_get_geoip(struct sip_msg *msg, pv_param_t *param,
 				return pv_get_null(msg, param, res);
 			return pv_get_sintval(msg, param, res,
 					gpv->item->r.record->metro_code);
+		case 13: /* contc */
+			if(gpv->item->r.record==NULL)
+				return pv_get_null(msg, param, res);
+			return pv_geoip_get_strzval(msg, param, res,
+					gpv->item->r.record->continent_code);
 		default: /* cc */
 			if(gpv->item->r.record==NULL)
 				return pv_get_null(msg, param, res);
diff --git a/modules/geoip2/Makefile b/modules/geoip2/Makefile
new file mode 100644
index 0000000..f4b26a4
--- /dev/null
+++ b/modules/geoip2/Makefile
@@ -0,0 +1,15 @@
+# $Id$
+#
+# WARNING: do not run this directly, it should be run by the master Makefile
+
+include ../../Makefile.defs
+auto_gen=
+NAME=geoip2.so
+LIBS= -lmaxminddb
+
+DEFS+=-DKAMAILIO_MOD_INTERFACE
+
+SERLIBPATH=../../lib
+SER_LIBS+=$(SERLIBPATH)/kmi/kmi
+
+include ../../Makefile.modules
diff --git a/modules/geoip2/README b/modules/geoip2/README
new file mode 100644
index 0000000..fd07cdd
--- /dev/null
+++ b/modules/geoip2/README
@@ -0,0 +1,147 @@
+geoip2 Module
+
+Sergey Okhapkin
+
+   callwithus.com
+
+Edited by
+
+Daniel-Constantin Mierla
+
+   <miconda at gmail.com>
+
+   Copyright © 2010 Daniel-Constantin Mierla (asipto.com)
+     __________________________________________________________________
+
+   Table of Contents
+
+   1. Admin Guide
+
+        1. Overview
+        2. Dependencies
+
+              2.1. Kamailio Modules
+              2.2. External Libraries or Applications
+
+        3. Parameters
+
+              3.1. path (string)
+
+        4. Functions
+
+              4.1. geoip2_match(ipaddr, pvc)
+
+        5. Exported pseudo-variables
+
+   List of Examples
+
+   1.1. Set path parameter
+   1.2. geoip2_match usage
+
+Chapter 1. Admin Guide
+
+   Table of Contents
+
+   1. Overview
+   2. Dependencies
+
+        2.1. Kamailio Modules
+        2.2. External Libraries or Applications
+
+   3. Parameters
+
+        3.1. path (string)
+
+   4. Functions
+
+        4.1. geoip2_match(ipaddr, pvc)
+
+   5. Exported pseudo-variables
+
+1. Overview
+
+   This module allows real-time queries against the Max Mind GeoIP2
+   database to be performed from the config script.
+
+   The Max Mind GeoIP2 database is a map of IP network address assignments
+   to geographical locales that can be useful -- though approximate -- in
+   identifying the physical location with which an IP host address is
+   associated on a relatively granular level.
+
+   This database itself can be obtained on a free or commercial basis from
+   http://dev.maxmind.com/geoip/. The library libmaxminddb that interfaces
+   with the Max Mind API, as well as scripts to automate downloading of
+   the on-disk version are available at
+   http://dev.maxmind.com/geoip/geoip2/downloadable/.
+
+   This module exports a new class of pseudo-variables - $gip2(pvc=>key) -
+   to enable access to the results of a query to the database.
+
+   Many queries can be done and store results in different containers to
+   be able to use in parallel. Database is loaded at startup in cache.
+
+2. Dependencies
+
+   2.1. Kamailio Modules
+   2.2. External Libraries or Applications
+
+2.1. Kamailio Modules
+
+   The following modules must be loaded before this module:
+     * none.
+
+2.2. External Libraries or Applications
+
+   The following libraries or applications must be installed before
+   running Kamailio with this module loaded:
+     * libmaxminddb - the GeoIP2 library.
+
+3. Parameters
+
+   3.1. path (string)
+
+3.1. path (string)
+
+   Path to the GeoIP2 database file.
+
+   Default value is “null”.
+
+   Example 1.1. Set path parameter
+...
+modparam("geoip2", "path", "/usr/local/share/GeoIP/GeoLite2-City.mmdb")
+...
+
+4. Functions
+
+   4.1. geoip2_match(ipaddr, pvc)
+
+4.1.  geoip2_match(ipaddr, pvc)
+
+   Match ipaddr against the GeoIP database and set the pvc container. The
+   function has to be called before accessing a key via: $gip2(pvc=>key).
+
+   Example 1.2. geoip2_match usage
+...
+if(geoip2_match("$si", "src"))
+    xlog("SIP message from: $gip2(src=>cc)\n");
+...
+
+5. Exported pseudo-variables
+
+     * $gip2(pvc=>key) - pvc is an identifier for this query result; it is
+       designated by the second parameter of geoip2_match(). The key can
+       be one of the following:
+          + cc - country code
+          + tz - time zone
+          + zip - postal code
+          + lat - latitude
+          + lon - longitude
+          + nmask - network mask (CIDR format)
+          + city - city
+          + regc - region
+          + regn - region name
+          + metro - metro code
+          + contc - continent code
+
+   Exported pseudo-variables are documented at
+   http://www.kamailio.org/wiki/.
diff --git a/modules/geoip2/doc/Makefile b/modules/geoip2/doc/Makefile
new file mode 100644
index 0000000..997a9b2
--- /dev/null
+++ b/modules/geoip2/doc/Makefile
@@ -0,0 +1,4 @@
+docs = geoip2.xml
+
+docbook_dir = ../../../docbook
+include $(docbook_dir)/Makefile.module
diff --git a/modules/geoip2/doc/geoip2.xml b/modules/geoip2/doc/geoip2.xml
new file mode 100644
index 0000000..d69b0ed
--- /dev/null
+++ b/modules/geoip2/doc/geoip2.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding='ISO-8859-1'?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+<!-- Include general documentation entities -->
+<!ENTITY % docentities SYSTEM "../../../docbook/entities.xml">
+%docentities;
+
+]>
+
+<book xmlns:xi="http://www.w3.org/2001/XInclude">
+    <bookinfo>
+	<title>geoip2 Module</title>
+	<productname class="trade">&kamailioname;</productname>
+	<authorgroup>
+	    <author>
+		<firstname>Sergey</firstname>
+		<surname>Okhapkin</surname>
+		<affiliation><orgname>callwithus.com</orgname></affiliation>
+	    </author>
+	    <editor>
+		<firstname>Daniel-Constantin</firstname>
+		<surname>Mierla</surname>
+		    <email>miconda at gmail.com</email>
+	    </editor>
+	</authorgroup>
+	<copyright>
+	    <year>2010</year>
+	    <holder>Daniel-Constantin Mierla (asipto.com)</holder>
+	</copyright>
+    </bookinfo>
+    <toc></toc>
+    
+	<xi:include href="geoip2_admin.xml"/>
+    
+</book>
diff --git a/modules/geoip2/doc/geoip2_admin.xml b/modules/geoip2/doc/geoip2_admin.xml
new file mode 100644
index 0000000..b944bb3
--- /dev/null
+++ b/modules/geoip2/doc/geoip2_admin.xml
@@ -0,0 +1,178 @@
+<?xml version="1.0" encoding='ISO-8859-1'?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+<!-- Include general documentation entities -->
+<!ENTITY % docentities SYSTEM "../../../docbook/entities.xml">
+%docentities;
+
+]>
+
+<!-- Module User's Guide -->
+
+<chapter>
+    
+    <title>&adminguide;</title>
+    
+    <section>
+	<title>Overview</title>
+	<para>
+		This module allows real-time queries against the Max Mind GeoIP2 
+		database to be performed from the config script.  
+	</para>
+	<para>
+		The Max Mind GeoIP2 database is a map of IP network address assignments 
+		to geographical locales that can be useful -- though approximate --
+		in identifying the physical location with which an IP host address
+		is associated on a relatively granular level.
+	</para>
+	<para>
+		This database itself can be obtained on a free or commercial basis 
+		from <ulink url="http://dev.maxmind.com/geoip/">
+		http://dev.maxmind.com/geoip/</ulink>. The 
+		library libmaxminddb
+		that interfaces with the Max Mind API, as well as scripts to
+		automate downloading of the on-disk version are available at
+		<ulink url="http://dev.maxmind.com/geoip/geoip2/downloadable/">
+		http://dev.maxmind.com/geoip/geoip2/downloadable/</ulink>.
+	</para>
+	<para>
+		This module exports a new class of pseudo-variables -
+		$gip2(pvc=>key) - to enable access to the results of a query to the
+		database.
+	</para>
+	<para>
+		Many queries can be done and store results in different containers to
+		be able to use in parallel. Database is loaded at startup in cache.
+	</para>
+    </section>
+    <section>
+	<title>Dependencies</title>
+	<section>
+	    <title>&kamailio; Modules</title>
+	    <para>
+		The following modules must be loaded before this module:
+	    	<itemizedlist>
+		    <listitem>
+			<para>
+			    <emphasis>none</emphasis>.
+			</para>
+		    </listitem>
+	    	</itemizedlist>
+	    </para>
+	</section>
+	<section>
+	    <title>External Libraries or Applications</title>
+	    <para>
+		The following libraries or applications must be installed before running
+		&kamailio; with this module loaded:
+	    	<itemizedlist>
+		    <listitem>
+			<para>
+			    <emphasis>libmaxminddb</emphasis> - the GeoIP2 library.
+			</para>
+		    </listitem>
+	    	</itemizedlist>
+	    </para>
+	</section>
+    </section>
+    <section>
+	<title>Parameters</title>
+	<section>
+	    <title><varname>path</varname> (string)</title>
+	    <para>
+		Path to the GeoIP2 database file.
+	    </para>
+	    <para>
+		<emphasis>
+		    Default value is <quote>null</quote>.
+		</emphasis>
+	    </para>
+	    <example>
+		<title>Set <varname>path</varname> parameter</title>
+		<programlisting format="linespecific">
+...
+modparam("geoip2", "path", "/usr/local/share/GeoIP/GeoLite2-City.mmdb")
+...
+</programlisting>
+	    </example>
+	</section>
+
+	</section>
+	
+    <section>
+	<title>Functions</title>
+ 	<section>
+	    <title>
+		<function moreinfo="none">geoip2_match(ipaddr, pvc)</function>
+	    </title>
+	    <para>
+			Match ipaddr against the GeoIP database and set the pvc container. The
+			function has to be called before accessing a key via: $gip2(pvc=>key).
+	    </para>
+		<example>
+		<title><function>geoip2_match</function> usage</title>
+		<programlisting format="linespecific">
+...
+if(geoip2_match("$si", "src"))
+    xlog("SIP message from: $gip2(src=>cc)\n");
+...
+</programlisting>
+	    </example>
+	</section>
+	
+    </section>
+	
+	<section>
+		<title>Exported pseudo-variables</title>
+		<itemizedlist>
+			<listitem><para>
+				<emphasis>$gip2(pvc=>key)</emphasis> - <emphasis>pvc</emphasis> is an 
+				identifier for this query result;  it is designated by the second 
+				parameter of geoip2_match(). The <emphasis>key</emphasis> can be one of
+				the following:
+				</para>
+			<itemizedlist>
+				<listitem><para>
+					<emphasis>cc</emphasis> - country code
+				</para></listitem>
+				<listitem><para>
+					<emphasis>tz</emphasis> - time zone
+				</para></listitem>
+				<listitem><para>
+					<emphasis>zip</emphasis> - postal code
+				</para></listitem>
+				<listitem><para>
+					<emphasis>lat</emphasis> - latitude
+				</para></listitem>
+				<listitem><para>
+					<emphasis>lon</emphasis> - longitude
+				</para></listitem>
+				<listitem><para>
+					<emphasis>nmask</emphasis> - network mask (CIDR format)
+				</para></listitem>
+				<listitem><para>
+					<emphasis>city</emphasis> - city
+				</para></listitem>
+				<listitem><para>
+					<emphasis>regc</emphasis> - region
+				</para></listitem>
+				<listitem><para>
+					<emphasis>regn</emphasis> - region name
+				</para></listitem>
+				<listitem><para>
+					<emphasis>metro</emphasis> - metro code
+				</para></listitem>
+				<listitem><para>
+					<emphasis>contc</emphasis> - continent code
+				</para></listitem>
+			</itemizedlist>
+			</listitem>
+		</itemizedlist>
+		<para>
+		Exported pseudo-variables are documented at &kamwikilink;.
+		</para>
+	</section>
+
+</chapter>
+
diff --git a/modules/geoip2/geoip2_mod.c b/modules/geoip2/geoip2_mod.c
new file mode 100644
index 0000000..d9b2314
--- /dev/null
+++ b/modules/geoip2/geoip2_mod.c
@@ -0,0 +1,139 @@
+/**
+ * $Id$
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../../sr_module.h"
+#include "../../dprint.h"
+#include "../../ut.h"
+#include "../../pvar.h"
+#include "../../mod_fix.h"
+
+#include "geoip2_pv.h"
+
+MODULE_VERSION
+
+static char *geoip2_path = NULL;
+
+static int  mod_init(void);
+static void mod_destroy(void);
+
+static int w_geoip2_match(struct sip_msg* msg, char* str1, char* str2);
+static int geoip2_match(struct sip_msg *msg, gparam_t *target, gparam_t *pvname);
+
+static pv_export_t mod_pvs[] = {
+	{ {"gip2", sizeof("gip2")-1}, PVT_OTHER, pv_get_geoip2, 0,
+		pv_parse_geoip2_name, 0, 0, 0 },
+	{ {0, 0}, 0, 0, 0, 0, 0, 0, 0 }
+};
+
+
+static cmd_export_t cmds[]={
+	{"geoip2_match", (cmd_function)w_geoip2_match, 2, fixup_spve_spve,
+		0, ANY_ROUTE},
+	{0, 0, 0, 0, 0, 0}
+};
+
+static param_export_t params[]={
+	{"path",     PARAM_STRING, &geoip2_path},
+	{0, 0, 0}
+};
+
+struct module_exports exports = {
+	"geoip2",
+	DEFAULT_DLFLAGS, /* dlopen flags */
+	cmds,
+	params,
+	0,
+	0,              /* exported MI functions */
+	mod_pvs,        /* exported pseudo-variables */
+	0,              /* extra processes */
+	mod_init,       /* module initialization function */
+	0,              /* response function */
+	mod_destroy,    /* destroy function */
+	0               /* per child init function */
+};
+
+
+
+/**
+ * init module function
+ */
+static int mod_init(void)
+{
+
+	if(geoip2_path==NULL || strlen(geoip2_path)==0)
+	{
+		LM_ERR("path to GeoIP database file not set\n");
+		return -1;
+	}
+
+	if(geoip2_init_pv(geoip2_path)!=0)
+	{
+		LM_ERR("cannot init for database file at: %s\n", geoip2_path);
+		return -1;
+	}
+	return 0;
+}
+
+/**
+ * destroy module function
+ */
+static void mod_destroy(void)
+{
+	geoip2_destroy_pv();
+}
+
+static int w_geoip2_match(struct sip_msg* msg, char* str1, char* str2)
+{
+	return geoip2_match(msg, (gparam_t*)str1, (gparam_t*)str2);
+}
+
+static int geoip2_match(struct sip_msg *msg, gparam_t *target, gparam_t *pvname)
+{
+	str tomatch;
+	str pvclass;
+	
+	if(msg==NULL)
+	{
+		LM_ERR("received null msg\n");
+		return -1;
+	}
+
+	if(fixup_get_svalue(msg, target, &tomatch)<0)
+	{
+		LM_ERR("cannot get the address\n");
+		return -1;
+	}
+	if(fixup_get_svalue(msg, pvname, &pvclass)<0)
+	{
+		LM_ERR("cannot get the pv class\n");
+		return -1;
+	}
+	geoip2_pv_reset(&pvclass);
+
+	return geoip2_update_pv(&tomatch, &pvclass);
+}
+
diff --git a/modules/geoip2/geoip2_pv.c b/modules/geoip2/geoip2_pv.c
new file mode 100644
index 0000000..69bd719
--- /dev/null
+++ b/modules/geoip2/geoip2_pv.c
@@ -0,0 +1,495 @@
+/**
+ * $Id$
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+
+#include <assert.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "../../dprint.h"
+#include "../../hashes.h"
+#include "../../pvar.h"
+
+#include "geoip2_pv.h"
+
+typedef struct _sr_geoip2_record {
+	MMDB_lookup_result_s record;
+	str time_zone;
+	str zip;
+	str city;
+	str region_code;
+	str region_name;
+	str country;
+	str cont_code;
+	char latitude[16];
+	char longitude[16];
+	char metro[16];
+	char nmask[8];
+	char tomatch[256];
+	int flags;
+} sr_geoip2_record_t;
+
+typedef struct _sr_geoip2_item {
+	str pvclass;
+	unsigned int hashid;
+	sr_geoip2_record_t r;
+	struct _sr_geoip2_item *next;
+} sr_geoip2_item_t;
+
+typedef struct _geoip2_pv {
+	sr_geoip2_item_t *item;
+	int type;
+} geoip2_pv_t;
+
+static MMDB_s _handle_GeoIP;
+
+static sr_geoip2_item_t *_sr_geoip2_list = NULL;
+
+sr_geoip2_record_t *sr_geoip2_get_record(str *name)
+{
+	sr_geoip2_item_t *it = NULL;
+	unsigned int hashid = 0;
+
+	hashid =  get_hash1_raw(name->s, name->len);
+
+	it = _sr_geoip2_list;
+	while(it!=NULL)
+	{
+		if(it->hashid==hashid && it->pvclass.len == name->len
+				&& strncmp(it->pvclass.s, name->s, name->len)==0)
+			return &it->r;
+		it = it->next;
+	}
+	return NULL;
+}
+
+sr_geoip2_item_t *sr_geoip2_add_item(str *name)
+{
+	sr_geoip2_item_t *it = NULL;
+	unsigned int hashid = 0;
+
+	hashid =  get_hash1_raw(name->s, name->len);
+
+	it = _sr_geoip2_list;
+	while(it!=NULL)
+	{
+		if(it->hashid==hashid && it->pvclass.len == name->len
+				&& strncmp(it->pvclass.s, name->s, name->len)==0)
+			return it;
+		it = it->next;
+	}
+	/* add new */
+	it = (sr_geoip2_item_t*)pkg_malloc(sizeof(sr_geoip2_item_t));
+	if(it==NULL)
+	{
+		LM_ERR("no more pkg\n");
+		return NULL;
+	}
+	memset(it, 0, sizeof(sr_geoip2_item_t));
+	it->pvclass.s = (char*)pkg_malloc(name->len+1);
+	if(it->pvclass.s==NULL)
+	{
+		LM_ERR("no more pkg.\n");
+		pkg_free(it);
+		return NULL;
+	}
+	memcpy(it->pvclass.s, name->s, name->len);
+	it->pvclass.s[name->len] = '\0';
+	it->pvclass.len = name->len;
+	it->hashid = hashid;
+	it->next = _sr_geoip2_list;
+	_sr_geoip2_list = it;
+	return it;
+}
+
+
+int pv_parse_geoip2_name(pv_spec_p sp, str *in)
+{
+	geoip2_pv_t *gpv=NULL;
+	char *p;
+	str pvc;
+	str pvs;
+	if(sp==NULL || in==NULL || in->len<=0)
+		return -1;
+
+	gpv = (geoip2_pv_t*)pkg_malloc(sizeof(geoip2_pv_t));
+	if(gpv==NULL)
+		return -1;
+
+	memset(gpv, 0, sizeof(geoip2_pv_t));
+
+	p = in->s;
+
+	while(p<in->s+in->len && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r'))
+		p++;
+	if(p>in->s+in->len || *p=='\0')
+		goto error;
+	pvc.s = p;
+	while(p < in->s + in->len)
+	{
+		if(*p=='=' || *p==' ' || *p=='\t' || *p=='\n' || *p=='\r')
+			break;
+		p++;
+	}
+	if(p>in->s+in->len || *p=='\0')
+		goto error;
+	pvc.len = p - pvc.s;
+	if(*p!='=')
+	{
+		while(p<in->s+in->len && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r'))
+			p++;
+		if(p>in->s+in->len || *p=='\0' || *p!='=')
+			goto error;
+	}
+	p++;
+	if(*p!='>')
+		goto error;
+	p++;
+
+	pvs.len = in->len - (int)(p - in->s);
+	pvs.s = p;
+	LM_DBG("geoip2 [%.*s] - key [%.*s]\n", pvc.len, pvc.s,
+			pvs.len, pvs.s);
+
+	gpv->item = sr_geoip2_add_item(&pvc);
+	if(gpv->item==NULL)
+		goto error;
+
+	switch(pvs.len)
+	{
+		case 2: 
+			if(strncmp(pvs.s, "cc", 2)==0)
+				gpv->type = 0;
+			else if(strncmp(pvs.s, "tz", 2)==0)
+				gpv->type = 1;
+			else goto error;
+		break;
+		case 3: 
+			if(strncmp(pvs.s, "zip", 3)==0)
+				gpv->type = 2;
+			else if(strncmp(pvs.s, "lat", 3)==0)
+				gpv->type = 3;
+			else if(strncmp(pvs.s, "lon", 3)==0)
+				gpv->type = 4;
+			else goto error;
+		break;
+		case 4: 
+			if(strncmp(pvs.s, "city", 4)==0)
+				gpv->type = 8;
+			else if(strncmp(pvs.s, "regc", 4)==0)
+				gpv->type = 10;
+			else if(strncmp(pvs.s, "regn", 4)==0)
+				gpv->type = 11;
+			else goto error;
+		break;
+		case 5: 
+			if(strncmp(pvs.s, "metro", 5)==0)
+				gpv->type = 12;
+			else if(strncmp(pvs.s, "nmask", 5)==0)
+				gpv->type = 13;
+			else if(strncmp(pvs.s, "contc", 5)==0)
+				gpv->type = 6;
+			else goto error;
+		break;
+		default:
+			goto error;
+	}
+	sp->pvp.pvn.u.dname = (void*)gpv;
+	sp->pvp.pvn.type = PV_NAME_OTHER;
+
+	return 0;
+
+error:
+	if(gpv!=NULL)
+		pkg_free(gpv);
+
+	LM_ERR("error at PV geoip2 name: %.*s\n", in->len, in->s);
+	return -1;
+}
+
+int pv_geoip2_get_strzval(struct sip_msg *msg, pv_param_t *param,
+		pv_value_t *res, char *sval)
+{
+	str s;
+	if(sval==NULL)
+		return pv_get_null(msg, param, res);
+
+	s.s = sval;
+	s.len = strlen(s.s);
+	return pv_get_strval(msg, param, res, &s);
+}
+
+int pv_get_geoip2(struct sip_msg *msg, pv_param_t *param,
+		pv_value_t *res)
+{
+	geoip2_pv_t *gpv;
+	MMDB_entry_data_s entry_data;
+
+	if(msg==NULL || param==NULL)
+		return -1;
+
+	gpv = (geoip2_pv_t*)param->pvn.u.dname;
+	if(gpv==NULL)
+		return -1;
+	if(gpv->item==NULL)
+		return pv_get_null(msg, param, res);
+
+	switch(gpv->type)
+	{
+		case 1: /* tz */
+			if(gpv->item->r.time_zone.s==NULL)
+			{
+				if(gpv->item->r.flags&1)
+					return pv_get_null(msg, param, res);
+				if(MMDB_get_value(&gpv->item->r.record.entry, &entry_data,
+					"location","time_zone", NULL
+					) != MMDB_SUCCESS)
+					return pv_get_null(msg, param, res);
+				if(entry_data.has_data && entry_data.type == MMDB_DATA_TYPE_UTF8_STRING) {
+					gpv->item->r.time_zone.s = (char *)entry_data.utf8_string;
+					gpv->item->r.time_zone.len = entry_data.data_size;
+				}
+				gpv->item->r.flags |= 1;
+			}
+			return pv_get_strval(msg, param, res, &gpv->item->r.time_zone);
+		case 2: /* zip */
+			if(gpv->item->r.zip.s==NULL)
+			{
+				if(gpv->item->r.flags&32)
+					return pv_get_null(msg, param, res);
+				if(MMDB_get_value(&gpv->item->r.record.entry, &entry_data,
+					"postal","code", NULL) != MMDB_SUCCESS)
+					return pv_get_null(msg, param, res);
+				if(entry_data.has_data && entry_data.type == MMDB_DATA_TYPE_UTF8_STRING) {
+					gpv->item->r.zip.s = (char *)entry_data.utf8_string;
+					gpv->item->r.zip.len = entry_data.data_size;
+				}
+				gpv->item->r.flags |= 32;
+			}
+			return pv_get_strval(msg, param, res, &gpv->item->r.zip);
+		case 3: /* lat */
+			if((gpv->item->r.flags&2)==0)
+			{
+				gpv->item->r.latitude[0] = '\0';
+				if(MMDB_get_value(&gpv->item->r.record.entry, &entry_data,
+					"location","latitude", NULL) != MMDB_SUCCESS)
+					return pv_get_null(msg, param, res);
+				if(entry_data.has_data && entry_data.type == MMDB_DATA_TYPE_DOUBLE)
+					snprintf(gpv->item->r.latitude, 15, "%f", entry_data.double_value);
+				gpv->item->r.flags |= 2;
+			}
+			return pv_geoip2_get_strzval(msg, param, res,
+					gpv->item->r.latitude);
+		case 4: /* lon */
+			if((gpv->item->r.flags&4)==0)
+			{
+				gpv->item->r.latitude[0] = '\0';
+				if(MMDB_get_value(&gpv->item->r.record.entry, &entry_data,
+					"location","longitude", NULL) != MMDB_SUCCESS)
+					return pv_get_null(msg, param, res);
+				if(entry_data.has_data && entry_data.type == MMDB_DATA_TYPE_DOUBLE)
+					snprintf(gpv->item->r.longitude, 15, "%f", entry_data.double_value);
+				gpv->item->r.flags |= 4;
+			}
+			return pv_geoip2_get_strzval(msg, param, res,
+					gpv->item->r.longitude);
+		case 6: /* contc */
+			if(gpv->item->r.cont_code.s==NULL)
+			{
+				if(gpv->item->r.flags&16)
+					return pv_get_null(msg, param, res);
+				if(MMDB_get_value(&gpv->item->r.record.entry, &entry_data,
+					"continent","code", NULL
+					) != MMDB_SUCCESS)
+					return pv_get_null(msg, param, res);
+				if(entry_data.has_data && entry_data.type == MMDB_DATA_TYPE_UTF8_STRING) {
+					gpv->item->r.cont_code.s = (char *)entry_data.utf8_string;
+					gpv->item->r.cont_code.len = entry_data.data_size;
+				}
+				gpv->item->r.flags |= 16;
+			}
+			return pv_get_strval(msg, param, res, &gpv->item->r.cont_code);
+		case 8: /* city */
+			if(gpv->item->r.city.s==NULL)
+			{
+				if(gpv->item->r.flags&64)
+					return pv_get_null(msg, param, res);
+				if(MMDB_get_value(&gpv->item->r.record.entry, &entry_data,
+					"city","names","en", NULL
+					) != MMDB_SUCCESS)
+					return pv_get_null(msg, param, res);
+				if(entry_data.has_data && entry_data.type == MMDB_DATA_TYPE_UTF8_STRING) {
+					gpv->item->r.city.s = (char *)entry_data.utf8_string;
+					gpv->item->r.city.len = entry_data.data_size;
+				}
+				gpv->item->r.flags |= 64;
+			}
+			return pv_get_strval(msg, param, res, &gpv->item->r.city);
+		case 10: /* regc */
+			if(gpv->item->r.region_code.s==NULL)
+			{
+				if(gpv->item->r.flags&128)
+					return pv_get_null(msg, param, res);
+				if(MMDB_get_value(&gpv->item->r.record.entry, &entry_data,
+					"subdivisions","0","iso_code", NULL
+					) != MMDB_SUCCESS)
+					return pv_get_null(msg, param, res);
+				if(entry_data.has_data && entry_data.type == MMDB_DATA_TYPE_UTF8_STRING) {
+					gpv->item->r.region_code.s = (char *)entry_data.utf8_string;
+					gpv->item->r.region_code.len = entry_data.data_size;
+				}
+				gpv->item->r.flags |= 128;
+			}
+			return pv_get_strval(msg, param, res, &gpv->item->r.region_code);
+		case 11: /* regn */
+			if(gpv->item->r.region_name.s==NULL)
+			{
+				if(gpv->item->r.flags&16)
+					return pv_get_null(msg, param, res);
+				if(MMDB_get_value(&gpv->item->r.record.entry, &entry_data,
+					"subdivisions","0","names","en", NULL
+					) != MMDB_SUCCESS)
+					return pv_get_null(msg, param, res);
+				if(entry_data.has_data && entry_data.type == MMDB_DATA_TYPE_UTF8_STRING) {
+					gpv->item->r.region_name.s = (char *)entry_data.utf8_string;
+					gpv->item->r.region_name.len = entry_data.data_size;
+				}
+				gpv->item->r.flags |= 16;
+			}
+			return pv_get_strval(msg, param, res, &gpv->item->r.region_name);
+		case 12: /* metro */
+			if((gpv->item->r.flags&256)==0)
+			{
+				gpv->item->r.metro[0] = '\0';
+				if(MMDB_get_value(&gpv->item->r.record.entry, &entry_data,
+					"location","metro_code", NULL) != MMDB_SUCCESS)
+					return pv_get_null(msg, param, res);
+				if(entry_data.has_data && entry_data.type == MMDB_DATA_TYPE_UINT16)
+					snprintf(gpv->item->r.metro, 15, "%hd", entry_data.uint16);
+				gpv->item->r.flags |= 256;
+			}
+			return pv_geoip2_get_strzval(msg, param, res,
+					gpv->item->r.metro);
+		case 13: /* nmask */
+			if((gpv->item->r.flags&1024)==0)
+			{
+				gpv->item->r.nmask[0] = '\0';
+				snprintf(gpv->item->r.nmask, 8, "%hd", gpv->item->r.record.netmask);
+				gpv->item->r.flags |= 1024;
+			}
+			return pv_geoip2_get_strzval(msg, param, res,
+					gpv->item->r.nmask);
+		default: /* cc */
+			if(gpv->item->r.country.s==NULL)
+			{
+				if(gpv->item->r.flags&512)
+					return pv_get_null(msg, param, res);
+				if(MMDB_get_value(&gpv->item->r.record.entry, &entry_data,
+					"country","iso_code", NULL
+					) != MMDB_SUCCESS)
+					return pv_get_null(msg, param, res);
+				if(entry_data.has_data && entry_data.type == MMDB_DATA_TYPE_UTF8_STRING) {
+					gpv->item->r.country.s = (char *)entry_data.utf8_string;
+					gpv->item->r.country.len = entry_data.data_size;
+				}
+				if(MMDB_get_value(&gpv->item->r.record.entry, &entry_data,
+					"traits","is_anonymous_proxy", NULL) == MMDB_SUCCESS
+					&& entry_data.has_data && entry_data.type == MMDB_DATA_TYPE_BOOLEAN
+					&& entry_data.boolean) {
+					gpv->item->r.country.s = "A1";
+					gpv->item->r.country.len = 2;
+				}
+				gpv->item->r.flags |= 512;
+			}
+			return pv_get_strval(msg, param, res, &gpv->item->r.country);
+	}
+}
+
+int geoip2_init_pv(char *path)
+{
+	int status = MMDB_open(path, MMDB_MODE_MMAP, &_handle_GeoIP);
+	
+	if(MMDB_SUCCESS != status)
+	{
+		LM_ERR("cannot open GeoIP database file at: %s\n", path);
+		return -1;
+	}
+	return 0;
+}
+
+void geoip2_destroy_list(void)
+{
+}
+
+void geoip2_destroy_pv(void)
+{
+	MMDB_close(&_handle_GeoIP);
+}
+
+void geoip2_pv_reset(str *name)
+{
+	sr_geoip2_record_t *gr = NULL;
+	
+	gr = sr_geoip2_get_record(name);
+
+	if(gr==NULL)
+		return;
+	memset(gr, 0, sizeof(struct _sr_geoip2_record));
+}
+
+int geoip2_update_pv(str *tomatch, str *name)
+{
+	sr_geoip2_record_t *gr = NULL;
+	int gai_error, mmdb_error;
+	
+	if(tomatch->len>255)
+	{
+		LM_DBG("target too long (max 255): %s\n", tomatch->s);
+		return -3;
+	}
+	
+	gr = sr_geoip2_get_record(name);
+	if(gr==NULL)
+	{
+		LM_DBG("container not found: %s\n", tomatch->s);
+		return - 4;
+	}
+
+	strncpy(gr->tomatch, tomatch->s, tomatch->len);
+	tomatch->s[tomatch->len] = '\0';
+	gr->record = MMDB_lookup_string(&_handle_GeoIP,
+			(const char*)gr->tomatch,
+			&gai_error, &mmdb_error
+			);
+	LM_DBG("attempt to match: %s\n", gr->tomatch);
+	if (gai_error || MMDB_SUCCESS != mmdb_error || !gr->record.found_entry)
+	{
+		LM_DBG("no match for: %s\n", gr->tomatch);
+		return -2;
+	}
+	LM_DBG("geoip2 PV updated for: %s\n", gr->tomatch);
+
+	return 1;
+}
+
diff --git a/modules/geoip2/geoip2_pv.h b/modules/geoip2/geoip2_pv.h
new file mode 100644
index 0000000..05ebf80
--- /dev/null
+++ b/modules/geoip2/geoip2_pv.h
@@ -0,0 +1,40 @@
+/**
+ * $Id$
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _GEOIP_PV_H_
+#define _GEOIP_PV_H_
+
+#include <maxminddb.h>
+
+#include "../../pvar.h"
+
+int pv_parse_geoip2_name(pv_spec_p sp, str *in);
+int pv_get_geoip2(struct sip_msg *msg, pv_param_t *param,
+		pv_value_t *res);
+
+int geoip2_init_pv(char *path);
+void geoip2_destroy_pv(void);
+void geoip2_pv_reset(str *pvclass);
+int geoip2_update_pv(str *tomatch, str *pvclass);
+
+#endif
+
diff --git a/modules/group/Makefile b/modules/group/Makefile
index 199b0a6..0000f10 100644
--- a/modules/group/Makefile
+++ b/modules/group/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # group example module makefile
 #
diff --git a/modules/group/group.c b/modules/group/group.c
index a765e73..59c5352 100644
--- a/modules/group/group.c
+++ b/modules/group/group.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,11 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2003-02-25 - created by janakj
- * 2004-06-07   updated to the new DB api, added group_db_{bind,init,close,ver}
- *               (andrei)
  */
 
 /**
diff --git a/modules/group/group.h b/modules/group/group.h
index a54d0cc..d254965 100644
--- a/modules/group/group.h
+++ b/modules/group/group.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,9 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2003-02-25 - created by janakj
  */
 
 /**
diff --git a/modules/group/group_mod.c b/modules/group/group_mod.c
index 91767f3..0d86b1e 100644
--- a/modules/group/group_mod.c
+++ b/modules/group/group_mod.c
@@ -1,6 +1,4 @@
 /*
- * $Id$ 
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,15 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2003-02-25 - created by janakj
- *  2003-03-11 - New module interface (janakj)
- *  2003-03-16 - flags export parameter added (janakj)
- *  2003-03-19  all mallocs/frees replaced w/ pkg_malloc/pkg_free
- *  2003-04-05  default_uri #define used (jiri)
- *  2004-06-07  updated to the new DB api: calls to group_db_* (andrei)
- *  2005-10-06 - added support for regexp-based groups (bogdan)
  */
 
 /**
diff --git a/modules/group/group_mod.h b/modules/group/group_mod.h
index 171e798..d63adcd 100644
--- a/modules/group/group_mod.h
+++ b/modules/group/group_mod.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,9 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2003-02-25 - created by janakj
  */
 
 /**
diff --git a/modules/group/re_group.c b/modules/group/re_group.c
index df877a0..329cd50 100644
--- a/modules/group/re_group.c
+++ b/modules/group/re_group.c
@@ -1,6 +1,4 @@
 /*
- * $Id$ 
- *
  * Copyright (C) 2005-2007 Voice Sistem SRL
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,9 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2005-10-06 - created by bogdan
  */
 
 /**
diff --git a/modules/group/re_group.h b/modules/group/re_group.h
index 5601278..91698d8 100644
--- a/modules/group/re_group.h
+++ b/modules/group/re_group.h
@@ -1,6 +1,4 @@
 /*
- * $Id$ 
- *
  * Copyright (C) 2005-2007 Voice Sistem SRL
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,9 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2005-10-06 - created by bogdan
  */
 
 /**
diff --git a/modules/h350/Makefile b/modules/h350/Makefile
index 8cdcae0..8b28356 100644
--- a/modules/h350/Makefile
+++ b/modules/h350/Makefile
@@ -1,4 +1,3 @@
-# $Id: $
 #
 # H350
 #
diff --git a/modules/h350/h350_exp_fn.c b/modules/h350/h350_exp_fn.c
index ddbed57..f92e210 100644
--- a/modules/h350/h350_exp_fn.c
+++ b/modules/h350/h350_exp_fn.c
@@ -1,13 +1,10 @@
 /*
- * $Id: $
- *
  * Kamailio H.350 Module
  *
  * Copyright (C) 2007 University of North Carolina
  *
  * Original author: Christian Schlatter, cs at unc.edu
  *
- *
  * This file is part of Kamailio, a free SIP server.
  *
  * Kamailio is free software; you can redistribute it and/or modify
@@ -24,9 +21,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2007-03-12: Initial version
  */
 
 #include <regex.h>
diff --git a/modules/h350/h350_exp_fn.h b/modules/h350/h350_exp_fn.h
index fc6bef9..283f4bc 100644
--- a/modules/h350/h350_exp_fn.h
+++ b/modules/h350/h350_exp_fn.h
@@ -1,13 +1,10 @@
 /*
- * $Id: $
- *
  * Kamailio H.350 Module
  *
  * Copyright (C) 2007 University of North Carolina
  *
  * Original author: Christian Schlatter, cs at unc.edu
  *
- *
  * This file is part of Kamailio, a free SIP server.
  *
  * Kamailio is free software; you can redistribute it and/or modify
@@ -24,9 +21,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2007-03-12: Initial version
  */
 
 #ifndef H350_EXP_FN_H
diff --git a/modules/h350/h350_mod.c b/modules/h350/h350_mod.c
index 2e49393..e2216d6 100644
--- a/modules/h350/h350_mod.c
+++ b/modules/h350/h350_mod.c
@@ -1,6 +1,4 @@
 /* 
- * $Id: $
- *
  * Kamailio H.350 Module
  *
  * Copyright (C) 2007 University of North Carolina
@@ -24,9 +22,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2007-03-12: Initial version
  */
 
 #include "../../ut.h"
diff --git a/modules/h350/h350_mod.h b/modules/h350/h350_mod.h
index a3d7e0c..b2b78f7 100644
--- a/modules/h350/h350_mod.h
+++ b/modules/h350/h350_mod.h
@@ -1,6 +1,4 @@
 /*
- * $Id: $
- *
  * Kamailio H.350 Module
  *
  * Copyright (C) 2007 University of North Carolina
@@ -24,9 +22,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2007-03-12: Initial version
  */
 
 
diff --git a/modules/htable/Makefile b/modules/htable/Makefile
index de7ea25..7adca5d 100644
--- a/modules/htable/Makefile
+++ b/modules/htable/Makefile
@@ -1,6 +1,5 @@
-# $Id$
 #
-# example module makefile
+# htable module makefile
 #
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
diff --git a/modules/htable/README b/modules/htable/README
index 322fac9..fc7054b 100644
--- a/modules/htable/README
+++ b/modules/htable/README
@@ -92,7 +92,7 @@ Ovidiu Sas
 
    1.1. Accessing $sht(htname=>key)
    1.2. Dictionary attack limitation
-   1.3. Storring array values
+   1.3. Storing array values
    1.4. Set hash_size parameter
    1.5. Set db_url parameter
    1.6. Set key_name_column parameter
@@ -180,9 +180,9 @@ Chapter 1. Admin Guide
 
 1. Overview
 
-   The module adds a hash table container to configuration language. The
-   hash table is stored in shared memory and the access to it can be done
-   via pseudo-variables: $sht(htname=>name). The module supports
+   The module adds a hash table container to the configuration language.
+   The hash table is stored in shared memory and the access to it can be
+   done via pseudo-variables: $sht(htname=>name). The module supports
    definition of many hash tables and can load values at startup from a
    database table.
 
@@ -191,7 +191,7 @@ Chapter 1. Admin Guide
    from database and store it in hash table so next time the access to it
    is very fast. In the definition of the table you can define the default
    expiration time of cached items. The expiration time can be adjusted
-   per itme via assignment operation at runtime.
+   per item via assignment operation at runtime.
 
    Replication between multiple servers is performed automatically (if
    enabled) via the DMQ module.
@@ -212,15 +212,15 @@ $sht(a=>$ci::srcip) = $si;
 
    Next example shows a way to protect against dictionary attacks. If
    someone fails to authenticate 3 times, it is forbidden for 15min.
-   Authenticatin against database is expensive as it does a select on
-   subscriber table. By disabling the DB auth for 15min, resources on
-   server as saved and time to discover the password is increased
-   substantially. Additional alerting can be done by writing a message to
-   syslog or sending email, etc.
+   Authenticatiion against database is expensive as it does a select on
+   the “subscriberthe” table. By disabling the DB auth for 15min,
+   resources on the server are saved and time to discover the password is
+   increased substantially. Additional alerting can be done by writing a
+   message to syslog or sending email, etc.
 
-   To implement the logic, two hash table variables are user: one counting
+   To implement the logic, two hash table variables are used: one counting
    the failed authentications per user and one for storing the time of
-   last authentication attempt. To ensure unique name per user, the hash
+   last authentication attempt. To ensure a unique name per user, the hash
    table uses a combination of authentication username and text
    “::auth_count” and “::last_auth”.
 
@@ -273,10 +273,10 @@ if(is_present_hf("Authorization"))
 
    The array is built when the table is loaded in memory and afterwards
    all the keys are treated as individual keys. If a particular entry in
-   the array is deleted, it is the administarator's responsability to
+   the array is deleted, it is the administrator's responsibility to
    update the size of the array and any other elements (if required).
 
-   Example 1.3. Storring array values
+   Example 1.3. Storing array values
 # Example of dbtext with multiple keys
 $ cat /usr/local/etc/kamailio/dbtext/htable
 1:key:1:0:value3:0
@@ -382,7 +382,7 @@ $ kamcmd htable.dump htable
 
 2.3. Loading from database
 
-   The module is able to load values in hash table at startup upon
+   The module is able to load values in a hash table at startup upon
    providing a DB URL and table name.
 
    The structure of the table must contain:
@@ -447,7 +447,7 @@ $ kamcmd htable.dump htable
        however, in which case this attribute can be set to 0.
      * dmqreplicate - if set to 1, any actions (set, update, delete etc.)
        performed upon entries in this table will be replicated to other
-       nodes (htable peers). Please note, module parameter "enable_dmq"
+       nodes (htable peers). Please note, module parameter “enable_dmq”
        must also be set in order for this to apply (see below). Default is
        0 (no replication).
 
@@ -475,7 +475,7 @@ modparam("htable", "db_url", "mysql://kamailio:kamailiorw@localhost/kamailio")
 
 3.3. key_name_column (str)
 
-   The name of the column containing hash table key name.
+   The name of the column containing the hash table key name.
 
    Default value is 'key_name'.
 
@@ -486,7 +486,7 @@ modparam("htable", "key_name_column", "kname")
 
 3.4. key_type_column (str)
 
-   The name of the column containing hash table key type.
+   The name of the column containing the hash table key type.
 
    Default value is 'key_type'.
 
@@ -497,7 +497,7 @@ modparam("htable", "key_type_column", "ktype")
 
 3.5. value_type_column (str)
 
-   The name of the column containing hash table value type.
+   The name of the column containing the hash table value type.
 
    Default value is 'value_type'.
 
@@ -519,7 +519,7 @@ modparam("htable", "key_value_column", "kvalue")
 
 3.7. expires_column (str)
 
-   The name of the column containing expires type.
+   The name of the column containing the expires value.
 
    Default value is 'expires'.
 
@@ -564,8 +564,8 @@ modparam("htable", "timer_interval", 10)
 
 3.11. timer_mode (integer)
 
-   If set to 1, will start a new timer process. If set to 0 will use
-   default timer process to check for expired htable values.
+   If set to 1, the module will start a new timer process. If set to 0
+   will use the default timer process to check for expired htable values.
 
    Default value is 0.
 
@@ -576,9 +576,9 @@ modparam("htable", "timer_mode", 1)
 
 3.12. db_expires (integer)
 
-   If set to 1, will load/save the expires values of the items in hash
-   table fromm/to database. It applies only to hash tables that have
-   auto-expires attribute defined.
+   If set to 1, the module will load/save the expires values of the items
+   in hash table from/to database. It applies only to hash tables that
+   have the auto-expires attribute defined.
 
    Default value is 0.
 
@@ -596,6 +596,9 @@ modparam("htable", "db_expires", 1)
    table definition (size, autoexpire etc.) is identical across all
    instances.
 
+   Important: If this parameter is enabled, the DMQ module must be loaded
+   first - otherwise, startup will fail.
+
    Currently, values are not replicated on load from DB as it is expected
    that in these cases, all servers will load their values from the same
    DB.
diff --git a/modules/htable/api.c b/modules/htable/api.c
index 34bfc6b..1116a0d 100644
--- a/modules/htable/api.c
+++ b/modules/htable/api.c
@@ -1,5 +1,4 @@
 /**
- * $Id$
  *
  * Copyright (C) 2008 Elena-Ramona Modroiu (asipto.com)
  *
diff --git a/modules/htable/api.h b/modules/htable/api.h
index 71502b2..4f12674 100644
--- a/modules/htable/api.h
+++ b/modules/htable/api.h
@@ -1,5 +1,4 @@
 /**
- * $Id$
  *
  * Copyright (C) 2008 Elena-Ramona Modroiu (asipto.com)
  *
diff --git a/modules/htable/doc/htable_admin.xml b/modules/htable/doc/htable_admin.xml
index 5281f74..9007813 100644
--- a/modules/htable/doc/htable_admin.xml
+++ b/modules/htable/doc/htable_admin.xml
@@ -16,7 +16,7 @@
 	<section>
 	<title>Overview</title>
 	<para>
-		The module adds a hash table container to configuration language. The
+		The module adds a hash table container to the configuration language. The
 		hash table is stored in shared memory and the access to it can be
 		done via pseudo-variables: $sht(htname=>name). The module supports
 		definition of many hash tables and can load values at startup from
@@ -28,7 +28,7 @@
 		it from database and store it in hash table so next time the access to
 		it is very fast. In the definition of the table you can define the
 		default expiration time of cached items. The expiration time can
-		be adjusted per itme via assignment operation at runtime.
+		be adjusted per item via assignment operation at runtime.
 	</para>
 	<para>
 		Replication between multiple servers is performed automatically (if 
@@ -56,16 +56,16 @@ $sht(a=>$ci::srcip) = $si;
 	<para>
 		Next example shows a way to protect against dictionary attacks. If
 		someone fails to authenticate 3 times, it is forbidden for 15min.
-		Authenticatin against database is expensive as it does a select
-		on subscriber table. By disabling the DB auth for 15min, resources
-		on server as saved and time to discover the password is increased
+		Authenticatiion against database is expensive as it does a select
+		on the <quote>subscriberthe</quote> table. By disabling the DB auth for 15min,
+		resources on the server are saved and time to discover the password is increased
 		substantially. Additional alerting can be done by writing a message
 		to syslog or sending email, etc.
 	</para>
 	<para>
-		To implement the logic, two hash table variables are user: one counting
+		To implement the logic, two hash table variables are used: one counting
 		the failed authentications per user and one for storing the time of 
-		last authentication attempt. To ensure unique name per user, the
+		last authentication attempt. To ensure a unique name per user, the
 		hash table uses a combination of authentication username and text
 		<quote>::auth_count</quote> and <quote>::last_auth</quote>.
 	</para>
@@ -117,18 +117,18 @@ if(is_present_hf("Authorization"))
 	<para>
 		The module also provides a way to store multiple values for a single key.
 		This is emulated by storing individual keys as 'key_name[n]', where n is
-		incremented for each key.  The total number of keys is stored in a
+		incremented for each key. The total number of keys is stored in a
 		dedicated key, by default: 'key_name::size'.
 	</para>
 	<para>
 		The array is built when the table is loaded in memory and afterwards all
 		the keys are treated as individual keys.
-		If a particular entry in the array is deleted, it is the administarator's
-		responsability to update the size of the array and any other elements
+		If a particular entry in the array is deleted, it is the administrator's
+		responsibility to update the size of the array and any other elements
 		(if required).
 	</para>
 	<example>
-	<title>Storring array values</title>
+	<title>Storing array values</title>
 	<programlisting format="linespecific">
 # Example of dbtext with multiple keys
 $ cat /usr/local/etc/kamailio/dbtext/htable
@@ -250,7 +250,7 @@ $ kamcmd htable.dump htable
 	<section>
 		<title>Loading from database</title>
 		<para>
-		The module is able to load values in hash table at startup upon
+		The module is able to load values in a hash table at startup upon
 		providing a DB URL and table name.
 		</para>
 		<para>
@@ -335,8 +335,8 @@ $ kamcmd htable.dump htable
 		<listitem>
 		<para>
 			<emphasis>htname</emphasis> - string specifying the name of
-			the hash table. This string is used by $sht(...) to refer to the
-			hash table.
+			the hash table. This string is used by <emphasis>$sht(...)</emphasis>
+			to refer to the hash table.
 		</para>
 		</listitem>
 		<listitem>
@@ -377,12 +377,18 @@ $ kamcmd htable.dump htable
 		</listitem>
 		<listitem>
 		<para>
-			<emphasis>updateexpire</emphasis> - if set to 1 (default), the time until expiration of an item is reset when that item is updated.  Certain uses of htable may dictate that updates should not reset the expiration timeout, however, in which case this attribute can be set to 0.
+			<emphasis>updateexpire</emphasis> - if set to 1 (default), the time until
+			expiration of an item is reset when that item is updated.  Certain uses of
+			htable may dictate that updates should not reset the expiration timeout, however,
+			in which case this attribute can be set to 0.
 		</para>
 		</listitem>
 		<listitem>
 		<para>
-			<emphasis>dmqreplicate</emphasis> - if set to 1, any actions (set, update, delete etc.) performed upon entries in this table will be replicated to other nodes (htable peers). Please note, module parameter "enable_dmq" must also be set in order for this to apply (see below). Default is 0 (no replication).
+			<emphasis>dmqreplicate</emphasis> - if set to 1, any actions (set, update, delete
+			etc.) performed upon entries in this table will be replicated to other nodes (htable
+			peers). Please note, module parameter <quote>enable_dmq</quote> must also be set in
+			order for this to apply (see below). Default is 0 (no replication).
 		</para>
 		</listitem>
 		</itemizedlist>
@@ -405,7 +411,7 @@ modparam("htable", "htable", "c=>size=4;autoexpire=7200;initval=1;dmqreplicat
 	<section id="htable.p.db_url">
 		<title><varname>db_url</varname> (str)</title>
 		<para>
-			The URL to connect to database for loading values in hash
+			The <acronym>URL</acronym> to connect to database for loading values in hash
 			table at start up.
 		</para>
 		<para>
@@ -425,7 +431,7 @@ modparam("htable", "db_url", "&defaultdb;")
 	<section id="htable.p.key_name_column">
 		<title><varname>key_name_column</varname> (str)</title>
 		<para>
-			The name of the column containing hash table key name.
+			The name of the column containing the hash table key name.
 		</para>
 		<para>
 		<emphasis>
@@ -444,7 +450,7 @@ modparam("htable", "key_name_column", "kname")
 	<section id="htable.p.key_type_column">
 		<title><varname>key_type_column</varname> (str)</title>
 		<para>
-			The name of the column containing hash table key type.
+			The name of the column containing the hash table key type.
 		</para>
 		<para>
 		<emphasis>
@@ -463,7 +469,7 @@ modparam("htable", "key_type_column", "ktype")
 	<section id="htable.p.value_type_column">
 		<title><varname>value_type_column</varname> (str)</title>
 		<para>
-			The name of the column containing hash table value type.
+			The name of the column containing the hash table value type.
 		</para>
 		<para>
 		<emphasis>
@@ -501,7 +507,7 @@ modparam("htable", "key_value_column", "kvalue")
 	<section id="htable.p.expires_column">
 		<title><varname>expires_column</varname> (str)</title>
 		<para>
-			The name of the column containing expires type.
+			The name of the column containing the expires value.
 		</para>
 		<para>
 		<emphasis>
@@ -578,8 +584,8 @@ modparam("htable", "timer_interval", 10)
 	<section id="htable.p.timer_mode">
 		<title><varname>timer_mode</varname> (integer)</title>
 		<para>
-		If set to 1, will start a new timer process. If set to 0
-		will use default timer process to check for expired htable
+		If set to 1, the module will start a new timer process. If set to 0
+		will use the default timer process to check for expired htable
 		values.
 		</para>
 		<para>
@@ -599,9 +605,9 @@ modparam("htable", "timer_mode", 1)
 	<section id="htable.p.db_expires">
 		<title><varname>db_expires</varname> (integer)</title>
 		<para>
-			If set to 1, will load/save the expires values of the items in
-			hash table fromm/to database. It applies only to hash tables that
-			have auto-expires attribute defined.
+			If set to 1, the module will load/save the expires values of the items in
+			hash table from/to database. It applies only to hash tables that
+			have the auto-expires attribute defined.
 		</para>
 		<para>
 		<emphasis>
@@ -627,6 +633,11 @@ modparam("htable", "db_expires", 1)
 			table definition (size, autoexpire etc.) is identical across all instances.
 		</para>
 		<para>
+		<emphasis>
+			Important: If this parameter is enabled, the DMQ module must be loaded first - otherwise, startup will fail.
+		</emphasis>
+		</para>
+		<para>
 			Currently, values are not replicated on load from DB as it is expected 
 			that in these cases, all servers will load their values from the same DB.
 		</para>
diff --git a/modules/htable/ht_api.c b/modules/htable/ht_api.c
index fc4c3f2..fb0b117 100644
--- a/modules/htable/ht_api.c
+++ b/modules/htable/ht_api.c
@@ -1,5 +1,4 @@
 /**
- * $Id$
  *
  * Copyright (C) 2008 Elena-Ramona Modroiu (asipto.com)
  *
diff --git a/modules/htable/ht_api.h b/modules/htable/ht_api.h
index f760bc6..e91db33 100644
--- a/modules/htable/ht_api.h
+++ b/modules/htable/ht_api.h
@@ -1,5 +1,4 @@
 /**
- * $Id$
  *
  * Copyright (C) 2008 Elena-Ramona Modroiu (asipto.com)
  *
diff --git a/modules/htable/ht_db.c b/modules/htable/ht_db.c
index 0231ece..06f3057 100644
--- a/modules/htable/ht_db.c
+++ b/modules/htable/ht_db.c
@@ -1,5 +1,4 @@
 /**
- * $Id$
  *
  * Copyright (C) 2008 Elena-Ramona Modroiu (asipto.com)
  *
diff --git a/modules/htable/ht_db.h b/modules/htable/ht_db.h
index 1551862..cffe534 100644
--- a/modules/htable/ht_db.h
+++ b/modules/htable/ht_db.h
@@ -1,5 +1,4 @@
 /**
- * $Id$
  *
  * Copyright (C) 2008 Elena-Ramona Modroiu (asipto.com)
  *
diff --git a/modules/htable/ht_dmq.c b/modules/htable/ht_dmq.c
index 284c3dc..7fa2959 100644
--- a/modules/htable/ht_dmq.c
+++ b/modules/htable/ht_dmq.c
@@ -59,6 +59,7 @@ int ht_dmq_initialize()
         }
 
 	not_peer.callback = ht_dmq_handle_msg;
+	not_peer.init_callback = NULL;
 	not_peer.description.s = "htable";
 	not_peer.description.len = 6;
 	not_peer.peer_id.s = "htable";
@@ -88,7 +89,7 @@ int ht_dmq_broadcast(str* body) {
 /**
  * @brief ht dmq callback
  */
-int ht_dmq_handle_msg(struct sip_msg* msg, peer_reponse_t* resp)
+int ht_dmq_handle_msg(struct sip_msg* msg, peer_reponse_t* resp, dmq_node_t* dmq_node)
 {
 	int content_length;
 	str body;
diff --git a/modules/htable/ht_dmq.h b/modules/htable/ht_dmq.h
index 7a0ca88..e9189ec 100644
--- a/modules/htable/ht_dmq.h
+++ b/modules/htable/ht_dmq.h
@@ -40,7 +40,7 @@ typedef enum {
 } ht_dmq_action_t;
 
 int ht_dmq_initialize();
-int ht_dmq_handle_msg(struct sip_msg* msg, peer_reponse_t* resp);
+int ht_dmq_handle_msg(struct sip_msg* msg, peer_reponse_t* resp, dmq_node_t* dmq_node);
 int ht_dmq_replicate_action(ht_dmq_action_t action, str* htname, str* cname, int type, int_str* val, int mode);
 int ht_dmq_replay_action(ht_dmq_action_t action, str* htname, str* cname, int type, int_str* val, int mode);
 int ht_dmq_resp_callback_f(struct sip_msg* msg, int code, dmq_node_t* node, void* param);
diff --git a/modules/htable/ht_var.c b/modules/htable/ht_var.c
index 5ac76cb..4bcc2b1 100644
--- a/modules/htable/ht_var.c
+++ b/modules/htable/ht_var.c
@@ -1,5 +1,4 @@
 /**
- * $Id$
  *
  * Copyright (C) 2008 Elena-Ramona Modroiu (asipto.com)
  *
diff --git a/modules/htable/ht_var.h b/modules/htable/ht_var.h
index 4ffe8c2..6c95e91 100644
--- a/modules/htable/ht_var.h
+++ b/modules/htable/ht_var.h
@@ -1,5 +1,4 @@
 /**
- * $Id$
  *
  * Copyright (C) 2008 Elena-Ramona Modroiu (asipto.com)
  *
diff --git a/modules/imc/Makefile b/modules/imc/Makefile
index f6a1df4..a6dc35d 100644
--- a/modules/imc/Makefile
+++ b/modules/imc/Makefile
@@ -1,6 +1,5 @@
-# $Id$
 #
-# example module makefile
+# imc  module makefile
 #
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
diff --git a/modules/ims_auth/Makefile b/modules/ims_auth/Makefile
index c3776e6..46c1331 100644
--- a/modules/ims_auth/Makefile
+++ b/modules/ims_auth/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # Digest Authentication - IMS support
 #
diff --git a/modules/ims_charging/Makefile b/modules/ims_charging/Makefile
index 0dbcd19..988e6d6 100644
--- a/modules/ims_charging/Makefile
+++ b/modules/ims_charging/Makefile
@@ -1,6 +1,5 @@
-# $Id$
 #
-# ims_ro make file
+# ims_charging make file
 #
 # 
 
@@ -14,6 +13,7 @@ DEFS+=-DOPENSER_MOD_INTERFACE
 SERLIBPATH=../../lib
 SER_LIBS+=$(SERLIBPATH)/kcore/kcore
 SER_LIBS+=$(SERLIBPATH)/ims/kamailio_ims
+SER_LIBS+=$(SERLIBPATH)/srdb1/srdb1
 
 ifneq ($(OS),darwin)
 	LIBS += -lrt
diff --git a/modules/ims_charging/Ro_data.c b/modules/ims_charging/Ro_data.c
index 6504c54..c15ba9f 100644
--- a/modules/ims_charging/Ro_data.c
+++ b/modules/ims_charging/Ro_data.c
@@ -86,7 +86,8 @@ out_of_memory:
     return 0;
 }
 
-ims_information_t * new_ims_information(event_type_t * event_type, time_stamps_t * time_stamps, str * user_session_id, str * outgoing_session_id, str * calling_party, str * called_party, str * icid, str * orig_ioi, str * term_ioi, int node_role) {
+ims_information_t * new_ims_information(event_type_t * event_type, time_stamps_t * time_stamps, str * user_session_id, str * outgoing_session_id, str * calling_party, 
+	str * called_party, str * icid, str * orig_ioi, str * term_ioi, int node_role, str *incoming_trunk_id, str *outgoing_trunk_id, str* pani) {
 
     str_list_slot_t *sl = 0;
     ims_information_t *x = 0;
@@ -116,6 +117,16 @@ ims_information_t * new_ims_information(event_type_t * event_type, time_stamps_t
 
     if (called_party && called_party->s)
         str_dup_ptr(x->called_party_address, *called_party, pkg);
+    
+    if (incoming_trunk_id && incoming_trunk_id->s)
+        str_dup_ptr(x->incoming_trunk_id, *incoming_trunk_id, pkg);
+    
+    if (outgoing_trunk_id && outgoing_trunk_id->s)
+        str_dup_ptr(x->outgoing_trunk_id, *outgoing_trunk_id, pkg);
+    
+    if (pani && pani->s) {
+	str_dup_ptr(x->access_network_info, *pani, pkg);
+    }
 
     //WL_FREE_ALL(&(x->called_asserted_identity),str_list_t,pkg);
     //str_free_ptr(x->requested_party_address,pkg);
@@ -229,6 +240,10 @@ void ims_information_free(ims_information_t *x) {
     str_free_ptr(x->called_party_address, pkg);
     WL_FREE_ALL(&(x->called_asserted_identity), str_list_t, pkg);
     str_free_ptr(x->requested_party_address, pkg);
+    
+    str_free_ptr(x->incoming_trunk_id, pkg);
+    str_free_ptr(x->outgoing_trunk_id, pkg);
+    str_free_ptr(x->access_network_info, pkg);
 
     time_stamps_free(x->time_stamps);
 
diff --git a/modules/ims_charging/Ro_data.h b/modules/ims_charging/Ro_data.h
index c469582..26dd0dc 100644
--- a/modules/ims_charging/Ro_data.h
+++ b/modules/ims_charging/Ro_data.h
@@ -271,7 +271,8 @@ typedef struct {
     str_list_t calling_party_address;
     str *called_party_address;
     str_list_t called_asserted_identity;
-    str * requested_party_address;
+    str *requested_party_address;
+    str *access_network_info;
 
     time_stamps_t *time_stamps;
 
@@ -281,6 +282,9 @@ typedef struct {
     str *icid;
 
     str *service_id;
+    
+    str *incoming_trunk_id;
+    str *outgoing_trunk_id;
 
     service_specific_info_list_t service_specific_info;
 
@@ -393,7 +397,10 @@ ims_information_t * new_ims_information(event_type_t * event_type,
         str * icid,
         str * orig_ioi,
         str * term_ioi,
-        int node_role);
+        int node_role,
+	str *incoming_trunk_id,
+	str *outgoing_trunk_id,
+        str *pani);
 
 void event_type_free(event_type_t *x);
 void time_stamps_free(time_stamps_t *x);
diff --git a/modules/ims_charging/ccr.c b/modules/ims_charging/ccr.c
index 3621a75..140d1c1 100644
--- a/modules/ims_charging/ccr.c
+++ b/modules/ims_charging/ccr.c
@@ -3,6 +3,7 @@
 #include "ccr.h"
 #include "Ro_data.h"
 #include "ro_avp.h"
+#include "mod.h"
 
 extern cdp_avp_bind_t *cdp_avp;
 extern struct cdp_binds cdpb;
@@ -94,6 +95,23 @@ int Ro_write_ims_information_avps(AAA_AVP_LIST * avp_list, ims_information_t* x)
     if (x->called_party_address)
         if (!cdp_avp->epcapp.add_Called_Party_Address(&aList2, *(x->called_party_address), 0))
             goto error;
+    
+    if (x->incoming_trunk_id && x->outgoing_trunk_id) {
+	if (!cdp_avp->epcapp.add_Outgoing_Trunk_Group_Id(&aList, *(x->outgoing_trunk_id), 0))
+	    goto error;
+	    
+	if (!cdp_avp->epcapp.add_Incoming_Trunk_Group_Id(&aList, *(x->incoming_trunk_id), 0))
+	    goto error;
+	    
+	if (!cdp_avp->epcapp.add_Trunk_Group_Id(&aList2, &aList, 0))
+            goto error;
+	cdp_avp->cdp->AAAFreeAVPList(&aList);
+        aList.head = aList.tail = 0;
+    }
+    
+    if (x->access_network_info) {
+		cdp_avp->imsapp.add_Access_Network_Information(&aList2, *(x->access_network_info), 0);
+    }
 
     for (sl = x->called_asserted_identity.head; sl; sl = sl->next) {
         if (!cdp_avp->epcapp.add_Called_Asserted_Identity(&aList2, sl->data, 0))
@@ -119,6 +137,7 @@ int Ro_write_ims_information_avps(AAA_AVP_LIST * avp_list, ims_information_t* x)
 
         if (!cdp_avp->epcapp.add_Inter_Operator_Identifier(&aList2, &aList, 0))
             goto error;
+	cdp_avp->cdp->AAAFreeAVPList(&aList);
         aList.head = aList.tail = 0;
     }
 
@@ -141,6 +160,7 @@ int Ro_write_ims_information_avps(AAA_AVP_LIST * avp_list, ims_information_t* x)
 
         if (!cdp_avp->epcapp.add_Service_Specific_Info(&aList2, &aList, 0))
             goto error;
+	cdp_avp->cdp->AAAFreeAVPList(&aList);
         aList.head = aList.tail = 0;
     }
 
diff --git a/modules/ims_charging/dialog.c b/modules/ims_charging/dialog.c
index 6d5596f..0548fee 100644
--- a/modules/ims_charging/dialog.c
+++ b/modules/ims_charging/dialog.c
@@ -1,11 +1,15 @@
+#include "mod.h"
 #include "dialog.h"
 #include "ro_session_hash.h"
 #include "../ims_usrloc_scscf/usrloc.h"
 #include "../ims_usrloc_scscf/udomain.h"
+#include "ro_db_handler.h"
 
 struct cdp_binds cdpb;
 
 extern usrloc_api_t ul;
+extern int ro_db_mode;
+extern char *domain;
 
 void dlg_reply(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params) {
 	struct sip_msg *reply;
@@ -23,26 +27,8 @@ void dlg_reply(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params) {
 	reply = _params->rpl;
 	if (!reply) {
 		LM_WARN("dlg_reply has no SIP reply associated.\n");
+		return;
 	}
-	
-//	if (reply != FAKED_REPLY && reply->REPLY_STATUS == 200) {
-//		//get CC session from callback param
-//		char* cdp_session_id = (char*)*_params->param;
-//		LM_INFO("Call answered\n");
-//		LM_DBG("Call answered and we have a session id of [%s]\n", cdp_session_id);
-//
-//		str session_id;
-//		session_id.s = cdp_session_id;
-//		session_id.len = strlen(cdp_session_id);
-//		AAASession* cdp_session = cdpb.AAAGetCCAccSession(session_id);
-//		if (!cdp_session) {
-//			LM_ERR("could not find find CC App CDP session\n");
-//			return;
-//		}
-//
-//		cdpb.AAAStartChargingCCAccSession(cdp_session);
-//		cdpb.AAASessionsUnlock(cdp_session->hash);
-//	}
 
 	if (reply != FAKED_REPLY && reply->REPLY_STATUS == 200) {
 		LM_DBG("Call answered on dlg [%p] - search for Ro Session and initialise timers.\n", dlg);
@@ -91,6 +77,13 @@ void dlg_reply(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params) {
 		} else {
 			ref_ro_session_unsafe(session, 1); // lock already acquired
 		}
+
+		if (ro_db_mode == DB_MODE_REALTIME) {
+		    session->flags |= RO_SESSION_FLAG_CHANGED;
+		    if (update_ro_dbinfo_unsafe(session) != 0) {
+			LM_ERR("Failed to update ro_session in database... continuing\n");
+		    };
+		}
 				
 		ro_session_unlock(ro_session_table, ro_session_entry);
 
@@ -148,14 +141,15 @@ void dlg_terminated(struct dlg_cell *dlg, int type, struct dlg_cb_params *_param
 				//if the Ro session is not active we don't need to do anything. This prevents
 				//double processing for various dialog_terminated callback events.
 				//If however, the call was never answered, then we can continue as normal
+				ro_session_lock(ro_session_table, ro_session_entry);
 				if (!ro_session->active && (ro_session->start_time != 0)) {
 					unref_ro_session(ro_session,1);
 					LM_ERR("Ro Session is not active, but may have been answered [%d]\n", (int)ro_session->start_time);
+					ro_session_unlock(ro_session_table, ro_session_entry);
 					return;
 				}
 			
 	
-				ro_session_lock(ro_session_table, ro_session_entry);
 
 				if (ro_session->active) { // if the call was never activated, there's no timer to remove
 					int ret = remove_ro_timer(&ro_session->ro_tl);
@@ -173,6 +167,14 @@ void dlg_terminated(struct dlg_cell *dlg, int type, struct dlg_cb_params *_param
 				LM_DBG("Sending CCR STOP on Ro_Session [%p]\n", ro_session);
 				send_ccr_stop(ro_session);
 				ro_session->active = 0;
+				
+				if (ro_db_mode == DB_MODE_REALTIME) {
+				    ro_session->flags |= RO_SESSION_FLAG_DELETED;
+				    if (update_ro_dbinfo_unsafe(ro_session) != 0) {
+					LM_ERR("Unable to update Ro session in DB...continuing\n");
+				    }
+				}
+				
 				//ro_session->start_time;
 				unref_ro_session_unsafe(ro_session, 1+unref, ro_session_entry); //lock already acquired
 				//unref_ro_session_unsafe(ro_session, 2+unref, ro_session_entry); //lock already acquired
@@ -189,9 +191,15 @@ void remove_dlg_data_from_contact(struct dlg_cell *dlg, int type, struct dlg_cb_
     struct ucontact* ucontact;
     str callid = {0, 0};
     str path = {0, 0};
+    udomain_t* domain_t;
     
     LM_DBG("dialog [%p] terminated, lets remove dlg data from contact\n", dlg);
     
+    if (ul.register_udomain(domain, &domain_t) < 0) {
+	    LM_ERR("Unable to register usrloc domain....aborting\n");
+	    return;
+    }
+    
     if(_params && _params->param){
 	impu_data = (struct impu_data*)*_params->param;
 	if (!impu_data) {
@@ -200,19 +208,20 @@ void remove_dlg_data_from_contact(struct dlg_cell *dlg, int type, struct dlg_cb_
 	}
 	
 	LM_DBG("IMPU data is present, contact: <%.*s> identity <%.*s>", impu_data->contact.len, impu_data->contact.s, impu_data->identity.len, impu_data->identity.s);
-	LM_DBG("IMPU data domain <%.*s>", impu_data->d->name->len, impu_data->d->name->s);
+	LM_DBG("IMPU data domain <%.*s>", domain_t->name->len, domain_t->name->s);
 	
-	ul.lock_udomain(impu_data->d, &impu_data->identity);
-	if (ul.get_impurecord(impu_data->d, &impu_data->identity, &implicit_impurecord) != 0) {
+	ul.lock_udomain(domain_t, &impu_data->identity);
+	if (ul.get_impurecord(domain_t, &impu_data->identity, &implicit_impurecord) != 0) {
 	    LM_DBG("usrloc does not have imprecord for implicity IMPU, ignore\n");
 	}else {
 	    if (ul.get_ucontact(implicit_impurecord, &impu_data->contact, &callid, &path, 0/*cseq*/,  &ucontact) != 0) { //contact does not exist
 		LM_DBG("This contact: <%.*s> is not in usrloc, ignore - NOTE: You need S-CSCF usrloc set to match_mode CONTACT_PORT_IP_ONLY\n", impu_data->contact.len, impu_data->contact.s);
 	    } else {//contact exists so add dialog data to it
 		ul.remove_dialog_data_from_contact(ucontact, dlg->h_entry, dlg->h_id);
+		ul.release_ucontact(ucontact);
 	    }
 	}
-	ul.unlock_udomain(impu_data->d, &impu_data->identity);
+	ul.unlock_udomain(domain_t, &impu_data->identity);
 	free_impu_data(impu_data);
     }
 }
@@ -224,9 +233,15 @@ void add_dlg_data_to_contact(struct dlg_cell *dlg, int type, struct dlg_cb_param
     struct ucontact* ucontact;
     str callid = {0, 0};
     str path = {0, 0};
+    udomain_t* domain_t;
     
     LM_DBG("dialog [%p] confirmed, lets add dlg data to contact\n", dlg);
     
+    if (ul.register_udomain(domain, &domain_t) < 0) {
+	    LM_ERR("Unable to register usrloc domain....aborting\n");
+	    return;
+    }
+    
     if(_params && _params->param){
 	impu_data = (struct impu_data*)*_params->param;
 	if (!impu_data) {
@@ -235,18 +250,19 @@ void add_dlg_data_to_contact(struct dlg_cell *dlg, int type, struct dlg_cb_param
 	}
 	
 	LM_DBG("IMPU data is present, contact: <%.*s> identity <%.*s>", impu_data->contact.len, impu_data->contact.s, impu_data->identity.len, impu_data->identity.s);
-	LM_DBG("IMPU data domain <%.*s>", impu_data->d->name->len, impu_data->d->name->s);
+	LM_DBG("IMPU data domain <%.*s>", domain_t->name->len, domain_t->name->s);
 	
-	ul.lock_udomain(impu_data->d, &impu_data->identity);
-	if (ul.get_impurecord(impu_data->d, &impu_data->identity, &implicit_impurecord) != 0) {
+	ul.lock_udomain(domain_t, &impu_data->identity);
+	if (ul.get_impurecord(domain_t, &impu_data->identity, &implicit_impurecord) != 0) {
 	    LM_DBG("usrloc does not have imprecord for implicity IMPU, ignore\n");
 	}else {
 	    if (ul.get_ucontact(implicit_impurecord, &impu_data->contact, &callid, &path, 0/*cseq*/,  &ucontact) != 0) { //contact does not exist
 		LM_DBG("This contact: <%.*s> is not in usrloc, ignore - NOTE: You need S-CSCF usrloc set to match_mode CONTACT_PORT_IP_ONLY\n", impu_data->contact.len, impu_data->contact.s);
 	    } else {//contact exists so add dialog data to it
 		ul.add_dialog_data_to_contact(ucontact, dlg->h_entry, dlg->h_id);
+		ul.release_ucontact(ucontact);
 	    }
 	}
-	ul.unlock_udomain(impu_data->d, &impu_data->identity);
+	ul.unlock_udomain(domain_t, &impu_data->identity);
     }
-} 
\ No newline at end of file
+} 
diff --git a/modules/ims_charging/doc/ims_charging_admin.xml b/modules/ims_charging/doc/ims_charging_admin.xml
index a77f03d..a00b126 100644
--- a/modules/ims_charging/doc/ims_charging_admin.xml
+++ b/modules/ims_charging/doc/ims_charging_admin.xml
@@ -737,7 +737,8 @@ modparam("ims_charging", "service_context_id_release", "262")
 
     <section>
       <title><function moreinfo="none">Ro_CCR(route_name, direction,
-      charge_type, unit_type, reservation_units, domain</function></title>
+      reservation_units, domain, incoming_trunk_id, outgoing_trunk_id</function>
+      </title>
 
       <para>Perform a CCR on Diameter Ro interface for Charging</para>
 
@@ -745,39 +746,34 @@ modparam("ims_charging", "service_context_id_release", "262")
 
       <itemizedlist>
         <listitem>
-          <para><emphasis>route_name</emphasis>route to be executed upon
+          <para><emphasis>route_name</emphasis> route to be executed upon
           reception of charging requests</para>
         </listitem>
 
         <listitem>
-          <para><emphasis>direction</emphasis>"orig"inating or
+          <para><emphasis>direction</emphasis> "orig"inating or
           "term"inating</para>
         </listitem>
 
         <listitem>
-          <para><emphasis>charge_type</emphasis>"IEC" = Immediate Event
-          Charging, "ECUR" - Event Charging with Unit Reservation or "SCUR" -
-          Session Charging with Unit Reservation.</para>
-
-          <emphasis>(Note: At the moment only SCUR is supported)</emphasis>
-        </listitem>
-
-        <listitem>
-          <para><emphasis>unit_type</emphasis>Types of the unit to be
-          requested</para>
-
-          <emphasis>(unused at the moment)</emphasis>
-        </listitem>
-
-        <listitem>
-          <para><emphasis>reservation_units</emphasis>how many units (at the
+          <para><emphasis>reservation_units</emphasis> how many units (at the
           moment seconds) should be reservated at the moment.</para>
         </listitem>
 
         <listitem>
-          <para><emphasis>domain</emphasis>- Logical domain within
+          <para><emphasis>domain</emphasis> Logical domain within
           registrar.</para>
         </listitem>
+	
+	<listitem>
+          <para><emphasis>incoming_trunk_id</emphasis> Identifies the trunk group 
+	  from which this originates.</para>
+        </listitem>
+	
+	<listitem>
+          <para><emphasis>outgoing_trunk_id</emphasis> Identifies the trunk 
+	  group where this will be terminated.</para>
+        </listitem>
       </itemizedlist>
 
       <para>This function can be used from REQUEST_ROUTE.</para>
@@ -791,7 +787,7 @@ modparam("ims_charging", "service_context_id_release", "262")
         <programlisting format="linespecific">
 ...
   xlog("L_DBG","Sending initial CCR Request for call\n");
-  Ro_CCR("CHARGING_CCR_REPLY", "orig", "SCUR", "", "30");
+    Ro_CCR("RO_ASYNC_TERM_REPLY", "term", 30, "1", "1");
 }
 
 route[CHARGING_CCR_REPLY] 
@@ -914,4 +910,4 @@ route[CHARGING_CCR_REPLY]
       <para>Number of calls that were killed due to lack of credit.</para>
     </section>
   </section>
-</chapter>
+</chapter>
\ No newline at end of file
diff --git a/modules/ims_charging/ims_charging_stats.c b/modules/ims_charging/ims_charging_stats.c
new file mode 100644
index 0000000..d62b4fc
--- /dev/null
+++ b/modules/ims_charging/ims_charging_stats.c
@@ -0,0 +1,67 @@
+#include "ims_charging_stats.h"
+
+struct ims_charging_counters_h ims_charging_cnts_h;
+enum sctp_info_req { IMS_CHARGING_AVG_RSP, IMS_CHARGING_FAILED_INITIAL, IMS_CHARGING_FAILED_FINAL, IMS_CHARGING_FAILED_INTERIM };
+
+static counter_val_t ims_charging_internal_stats(counter_handle_t h, void* what);
+
+counter_def_t ims_charging_cnt_defs[] = {
+    {&ims_charging_cnts_h.active_ro_sessions,	    "active_ro_sessions",	0, 0, 0,			    "number of currently active Ro sessions"},
+    {&ims_charging_cnts_h.billed_secs,		    "billed_secs",		0, 0, 0,			    "total number of seconds billed since start or reset"},
+    {&ims_charging_cnts_h.ccr_avg_response_time,    "ccr_avg_response_time",	0, ims_charging_internal_stats, (void*) (long) IMS_CHARGING_AVG_RSP,	"avg response time for CCRs"},
+    {&ims_charging_cnts_h.ccr_response_time,	    "ccr_response_time",	0, 0, 0,			    "total number of seconds waiting for CCR responses"},
+    {&ims_charging_cnts_h.ccr_timeouts,		    "ccr_timeouts",		0, 0, 0,			    "total number of CCR timeouts"},
+    {&ims_charging_cnts_h.failed_final_ccrs,	    "failed_final_ccrs",	0, 0, 0,			    "total number of failed final CCRs"},
+    {&ims_charging_cnts_h.failed_initial_ccrs,	    "failed_initial_ccrs",	0, 0, 0,			    "total number of failed initial CCRs"},
+    {&ims_charging_cnts_h.failed_interim_ccr,	    "failed_interim_ccrs",	0, 0, 0,			    "total number of failed interim CCRs"},
+    {&ims_charging_cnts_h.final_ccrs,		    "final_ccrs",		0, 0, 0,			    "total number of final (terminating) CCRs"},
+    {&ims_charging_cnts_h.initial_ccrs,		    "initial_ccrs",		0, 0, 0,			    "total number of initial CCRs"},
+    {&ims_charging_cnts_h.interim_ccrs,		    "interim_ccrs",		0, 0, 0,			    "total number of interim CCRs"},
+    {&ims_charging_cnts_h.killed_calls,		    "killed_calls",		0, 0, 0,			    "total number of killed calls"},
+    {&ims_charging_cnts_h.successful_final_ccrs,    "successful_final_ccrs",	0, 0, 0,			    "total number of successful final CCRs"},
+    {&ims_charging_cnts_h.successful_initial_ccrs,  "successful_initial_ccrs",	0, 0, 0,			    "total number of successful initial CCRs"},
+    {&ims_charging_cnts_h.successful_interim_ccrs,   "successful_interim_ccrs",	0, 0, 0,			    "total number of successful interim CCRs"},
+    {&ims_charging_cnts_h.ccr_replies_received,     "ccr_replies_received",     0, 0, 0,                            "total number of CCR replies received"},
+    {0, 0, 0, 0, 0, 0}
+};
+
+int ims_charging_init_counters() {
+    if (counter_register_array("ims_charging", ims_charging_cnt_defs) < 0)
+	goto error;
+    return 0;
+error:
+    return -1;
+}
+
+void ims_charging_destroy_counters() {
+    
+}
+
+/** helper function for some stats (which are kept internally).
+ */
+static counter_val_t ims_charging_internal_stats(counter_handle_t h, void* what) {
+    enum sctp_info_req w;
+
+    w = (int) (long) what;
+    switch (w) {
+	case IMS_CHARGING_AVG_RSP:
+	    if ((counter_get_val(ims_charging_cnts_h.initial_ccrs) + counter_get_val(ims_charging_cnts_h.interim_ccrs) + counter_get_val(ims_charging_cnts_h.final_ccrs)) == 0) 
+		return 0;
+	    else
+		return counter_get_val(ims_charging_cnts_h.ccr_response_time)/
+			(counter_get_val(ims_charging_cnts_h.initial_ccrs) + counter_get_val(ims_charging_cnts_h.interim_ccrs) + counter_get_val(ims_charging_cnts_h.final_ccrs));
+	    break;
+	case IMS_CHARGING_FAILED_INITIAL:
+	    return (counter_get_val(ims_charging_cnts_h.initial_ccrs) - counter_get_val(ims_charging_cnts_h.successful_initial_ccrs));
+	    break;
+	case IMS_CHARGING_FAILED_INTERIM:
+	    return (counter_get_val(ims_charging_cnts_h.interim_ccrs) - counter_get_val(ims_charging_cnts_h.successful_interim_ccrs));
+	    break;
+	case IMS_CHARGING_FAILED_FINAL:
+	    return (counter_get_val(ims_charging_cnts_h.final_ccrs) - counter_get_val(ims_charging_cnts_h.successful_final_ccrs));
+	    break;
+	default:
+	    return 0;
+    };
+    return 0;
+}
diff --git a/modules/ims_charging/ims_charging_stats.h b/modules/ims_charging/ims_charging_stats.h
new file mode 100644
index 0000000..14a8280
--- /dev/null
+++ b/modules/ims_charging/ims_charging_stats.h
@@ -0,0 +1,38 @@
+/* 
+ * File:   ims_charging_stats.h
+ * Author: jaybeepee
+ *
+ * Created on 24 February 2015, 11:15 AM
+ */
+
+#ifndef IMS_CHARGING_STATS_H
+#define	IMS_CHARGING_STATS_H
+
+#include "../../counters.h"
+
+struct ims_charging_counters_h {
+    counter_handle_t billed_secs;
+    counter_handle_t ccr_avg_response_time;
+    counter_handle_t ccr_response_time;
+    counter_handle_t ccr_timeouts;
+    counter_handle_t failed_final_ccrs;
+    counter_handle_t failed_initial_ccrs;
+    counter_handle_t failed_interim_ccr;
+    counter_handle_t final_ccrs;
+    counter_handle_t initial_ccrs;
+    counter_handle_t interim_ccrs;
+    counter_handle_t killed_calls;
+    counter_handle_t successful_final_ccrs;
+    counter_handle_t successful_initial_ccrs;
+    counter_handle_t successful_interim_ccrs;
+    counter_handle_t active_ro_sessions;
+    counter_handle_t ccr_replies_received;
+};
+
+int ims_charging_init_counters();
+void ims_charging_destroy_counters();
+
+#endif	/* IMS_CHARGING_STATS_H */
+
+
+
diff --git a/modules/ims_charging/ims_ro.c b/modules/ims_charging/ims_ro.c
index 7f0ece2..7215036 100644
--- a/modules/ims_charging/ims_ro.c
+++ b/modules/ims_charging/ims_ro.c
@@ -29,8 +29,9 @@
 #include "ccr.h"
 #include "config.h"
 #include "ro_session_hash.h"
-#include "stats.h"
 #include "ro_avp.h"
+#include "ro_db_handler.h"
+#include "ims_charging_stats.h"
 
 extern struct tm_binds tmb;
 extern struct cdp_binds cdpb;
@@ -38,13 +39,14 @@ extern client_ro_cfg cfg;
 extern struct dlg_binds dlgb;
 extern cdp_avp_bind_t *cdp_avp;
 extern str ro_forced_peer;
+extern int ro_db_mode;
+extern struct ims_charging_counters_h ims_charging_cnts_h;
 
 struct session_setup_data {
-	struct ro_session *ro_session;
-
-	cfg_action_t* action;
-	unsigned int tindex;
-	unsigned int tlabel;
+    struct ro_session *ro_session;
+    cfg_action_t* action;
+    unsigned int tindex;
+    unsigned int tlabel;
 };
 
 struct dlg_binds* dlgb_p;
@@ -56,8 +58,6 @@ extern int voice_service_identifier;
 extern int voice_rating_group;
 extern int video_service_identifier;
 extern int video_rating_group;
-extern int active_service_identifier;
-extern int active_rating_group;
 
 static int create_cca_return_code(int result);
 static void resume_on_initial_ccr(int is_timeout, void *param, AAAMessage *cca, long elapsed_msecs);
@@ -66,17 +66,15 @@ static void resume_on_termination_ccr(int is_timeout, void *param, AAAMessage *c
 static int get_mac_avp_value(struct sip_msg *msg, str *value);
 
 void credit_control_session_callback(int event, void* session) {
-	switch (event) {
-		case AUTH_EV_SESSION_DROP:
-			LM_DBG("Received notification of CC App session drop - we must free the generic data\n");
-			break;
-		default:
-			LM_DBG("Received unhandled event [%d] in credit control session callback from CDP\n", event);
-	}
+    switch (event) {
+	case AUTH_EV_SESSION_DROP:
+	    LM_DBG("Received notification of CC App session drop - we must free the generic data\n");
+	    break;
+	default:
+	    LM_DBG("Received unhandled event [%d] in credit control session callback from CDP\n", event);
+    }
 }
 
-
-
 /**
  * Retrieves the SIP request that generated a diameter transaction
  * @param hash - the tm hash value for this request
@@ -87,8 +85,8 @@ struct sip_msg * trans_get_request_from_current_reply() {
     struct cell *t;
     t = tmb.t_gett();
     if (!t || t == (void*) - 1) {
-        LM_ERR("trans_get_request_from_current_reply: Reply without transaction\n");
-        return 0;
+	LM_ERR("trans_get_request_from_current_reply: Reply without transaction\n");
+	return 0;
     }
     if (t) return t->uas.request;
     else return 0;
@@ -107,24 +105,24 @@ struct sip_msg * trans_get_request_from_current_reply() {
  * @returns 1 on success or 0 on failure
  */
 static inline int Ro_add_avp_list(AAA_AVP_LIST *list, char *d, int len, int avp_code,
-        int flags, int vendorid, int data_do, const char *func) {
+	int flags, int vendorid, int data_do, const char *func) {
     AAA_AVP *avp;
     if (vendorid != 0) flags |= AAA_AVP_FLAG_VENDOR_SPECIFIC;
     avp = cdpb.AAACreateAVP(avp_code, flags, vendorid, d, len, data_do);
     if (!avp) {
-        LM_ERR("%s: Failed creating avp\n", func);
-        return 0;
+	LM_ERR("%s: Failed creating avp\n", func);
+	return 0;
     }
     if (list->tail) {
-        avp->prev = list->tail;
-        avp->next = 0;
-        list->tail->next = avp;
-        list->tail = avp;
+	avp->prev = list->tail;
+	avp->next = 0;
+	list->tail->next = avp;
+	list->tail = avp;
     } else {
-        list->head = avp;
-        list->tail = avp;
-        avp->next = 0;
-        avp->prev = 0;
+	list->head = avp;
+	list->tail = avp;
+	avp->next = 0;
+	avp->prev = 0;
     }
 
     return 1;
@@ -182,13 +180,13 @@ inline int Ro_add_termination_cause(AAAMessage *msg, unsigned int term_code) {
 }
 
 /* called only when building stop record AVPS */
-inline int Ro_add_multiple_service_credit_Control_stop(AAAMessage *msg, int used_unit) {
+inline int Ro_add_multiple_service_credit_Control_stop(AAAMessage *msg, int used_unit, int active_rating_group, int active_service_identifier) {
     AAA_AVP_LIST used_list, mscc_list;
     str used_group;
     char x[4];
 
     //unsigned int service_id = 1000; //Removed these are now configurable config file params
-    
+
     //unsigned int rating_group = 500; //Removed these are now configurable config file params
 
     used_list.head = 0;
@@ -198,16 +196,16 @@ inline int Ro_add_multiple_service_credit_Control_stop(AAAMessage *msg, int used
 
     /* if we must Used-Service-Unit */
     if (used_unit >= 0) {
-        set_4bytes(x, used_unit);
-        Ro_add_avp_list(&used_list, x, 4, AVP_CC_Time, AAA_AVP_FLAG_MANDATORY, 0, AVP_DUPLICATE_DATA, __FUNCTION__);
-        used_group = cdpb.AAAGroupAVPS(used_list);
-        cdpb.AAAFreeAVPList(&used_list);
-        Ro_add_avp_list(&mscc_list, used_group.s, used_group.len, AVP_Used_Service_Unit, AAA_AVP_FLAG_MANDATORY, 0, AVP_FREE_DATA, __FUNCTION__);
+	set_4bytes(x, used_unit);
+	Ro_add_avp_list(&used_list, x, 4, AVP_CC_Time, AAA_AVP_FLAG_MANDATORY, 0, AVP_DUPLICATE_DATA, __FUNCTION__);
+	used_group = cdpb.AAAGroupAVPS(used_list);
+	cdpb.AAAFreeAVPList(&used_list);
+	Ro_add_avp_list(&mscc_list, used_group.s, used_group.len, AVP_Used_Service_Unit, AAA_AVP_FLAG_MANDATORY, 0, AVP_FREE_DATA, __FUNCTION__);
     }
 
     set_4bytes(x, active_service_identifier);
     Ro_add_avp_list(&mscc_list, x, 4, AVP_Service_Identifier, AAA_AVP_FLAG_MANDATORY, 0, AVP_DUPLICATE_DATA, __FUNCTION__);
-    
+
     set_4bytes(x, active_rating_group);
     Ro_add_avp_list(&mscc_list, x, 4, AVP_Rating_Group, AAA_AVP_FLAG_MANDATORY, 0, AVP_DUPLICATE_DATA, __FUNCTION__);
 
@@ -217,13 +215,10 @@ inline int Ro_add_multiple_service_credit_Control_stop(AAAMessage *msg, int used
     return Ro_add_avp(msg, used_group.s, used_group.len, AVP_Multiple_Services_Credit_Control, AAA_AVP_FLAG_MANDATORY, 0, AVP_FREE_DATA, __FUNCTION__);
 }
 
-inline int Ro_add_multiple_service_credit_Control(AAAMessage *msg, unsigned int requested_unit, int used_unit) {
+inline int Ro_add_multiple_service_credit_Control(AAAMessage *msg, unsigned int requested_unit, int used_unit, int active_rating_group, int active_service_identifier) {
     AAA_AVP_LIST list, used_list, mscc_list;
     str group, used_group;
-    //unsigned int service_id = 1000; //VOICE TODO FIX as config item - should be a MAP that can be identified based on SDP params
-    
-    //unsigned int rating_group = 500; //VOICE TODO FIX as config item - should be a MAP that can be identified based on SDP params
-    
+
     char x[4];
 
     list.head = 0;
@@ -242,17 +237,17 @@ inline int Ro_add_multiple_service_credit_Control(AAAMessage *msg, unsigned int
 
     set_4bytes(x, active_service_identifier);
     Ro_add_avp_list(&mscc_list, x, 4, AVP_Service_Identifier, AAA_AVP_FLAG_MANDATORY, 0, AVP_DUPLICATE_DATA, __FUNCTION__);
-    
+
     set_4bytes(x, active_rating_group);
     Ro_add_avp_list(&mscc_list, x, 4, AVP_Rating_Group, AAA_AVP_FLAG_MANDATORY, 0, AVP_DUPLICATE_DATA, __FUNCTION__);
 
     /* if we must Used-Service-Unit */
     if (used_unit >= 0) {
-        set_4bytes(x, used_unit);
-        Ro_add_avp_list(&used_list, x, 4, AVP_CC_Time, AAA_AVP_FLAG_MANDATORY, 0, AVP_DUPLICATE_DATA, __FUNCTION__);
-        used_group = cdpb.AAAGroupAVPS(used_list);
-        cdpb.AAAFreeAVPList(&used_list);
-        Ro_add_avp_list(&mscc_list, used_group.s, used_group.len, AVP_Used_Service_Unit, AAA_AVP_FLAG_MANDATORY, 0, AVP_FREE_DATA, __FUNCTION__);
+	set_4bytes(x, used_unit);
+	Ro_add_avp_list(&used_list, x, 4, AVP_CC_Time, AAA_AVP_FLAG_MANDATORY, 0, AVP_DUPLICATE_DATA, __FUNCTION__);
+	used_group = cdpb.AAAGroupAVPS(used_list);
+	cdpb.AAAFreeAVPList(&used_list);
+	Ro_add_avp_list(&mscc_list, used_group.s, used_group.len, AVP_Used_Service_Unit, AAA_AVP_FLAG_MANDATORY, 0, AVP_FREE_DATA, __FUNCTION__);
     }
 
     group = cdpb.AAAGroupAVPS(mscc_list);
@@ -302,12 +297,12 @@ inline int Ro_add_vendor_specific_appid(AAAMessage *msg, unsigned int vendor_id,
     Ro_add_avp_list(&list, x, 4, AVP_Vendor_Id, AAA_AVP_FLAG_MANDATORY, 0, AVP_DUPLICATE_DATA, __FUNCTION__);
 
     if (auth_id) {
-        set_4bytes(x, auth_id);
-        Ro_add_avp_list(&list, x, 4, AVP_Auth_Application_Id, AAA_AVP_FLAG_MANDATORY, 0, AVP_DUPLICATE_DATA, __FUNCTION__);
+	set_4bytes(x, auth_id);
+	Ro_add_avp_list(&list, x, 4, AVP_Auth_Application_Id, AAA_AVP_FLAG_MANDATORY, 0, AVP_DUPLICATE_DATA, __FUNCTION__);
     }
     if (acct_id) {
-        set_4bytes(x, acct_id);
-        Ro_add_avp_list(&list, x, 4, AVP_Acct_Application_Id, AAA_AVP_FLAG_MANDATORY, 0, AVP_DUPLICATE_DATA, __FUNCTION__);
+	set_4bytes(x, acct_id);
+	Ro_add_avp_list(&list, x, 4, AVP_Acct_Application_Id, AAA_AVP_FLAG_MANDATORY, 0, AVP_DUPLICATE_DATA, __FUNCTION__);
     }
 
     group = cdpb.AAAGroupAVPS(list);
@@ -318,41 +313,41 @@ inline int Ro_add_vendor_specific_appid(AAAMessage *msg, unsigned int vendor_id,
 }
 
 int get_sip_header_info(struct sip_msg * req,
-        struct sip_msg * reply,
-        int32_t * acc_record_type,
-        str * sip_method,
-        str * event, uint32_t * expires,
-        str * callid, str * asserted_id_uri, str * to_uri) {
+	struct sip_msg * reply,
+	int32_t * acc_record_type,
+	str * sip_method,
+	str * event, uint32_t * expires,
+	str * callid, str * asserted_id_uri, str * to_uri) {
 
     sip_method->s = req->first_line.u.request.method.s;
     sip_method->len = req->first_line.u.request.method.len;
 
     if (strncmp(sip_method->s, "INVITE", 6) == 0)
-        *acc_record_type = AAA_ACCT_START;
+	*acc_record_type = AAA_ACCT_START;
     else if (strncmp(sip_method->s, "BYE", 3) == 0)
-        *acc_record_type = AAA_ACCT_STOP;
+	*acc_record_type = AAA_ACCT_STOP;
     else
-        *acc_record_type = AAA_ACCT_EVENT;
+	*acc_record_type = AAA_ACCT_EVENT;
 
     *event = cscf_get_event(req);
     *expires = cscf_get_expires_hdr(req, 0);
     *callid = cscf_get_call_id(req, NULL);
 
     if ((*asserted_id_uri = cscf_get_asserted_identity(req, 0)).len == 0) {
-    	LM_DBG("No P-Asserted-Identity hdr found. Using From hdr");
+	LM_DBG("No P-Asserted-Identity hdr found. Using From hdr");
 
-    	if (!cscf_get_from_uri(req, asserted_id_uri)) {
-    		LM_ERR("Error assigning P-Asserted-Identity using From hdr");
-    		goto error;
-    	}
+	if (!cscf_get_from_uri(req, asserted_id_uri)) {
+	    LM_ERR("Error assigning P-Asserted-Identity using From hdr");
+	    goto error;
+	}
     }
 
-    *to_uri	= req->first_line.u.request.uri;
+    *to_uri = req->first_line.u.request.uri;
 
     LM_DBG("retrieved sip info : sip_method %.*s acc_record_type %i, event %.*s expires %u "
-            "call_id %.*s from_uri %.*s to_uri %.*s\n",
-            sip_method->len, sip_method->s, *acc_record_type, event->len, event->s, *expires,
-            callid->len, callid->s, asserted_id_uri->len, asserted_id_uri->s, to_uri->len, to_uri->s);
+	    "call_id %.*s from_uri %.*s to_uri %.*s\n",
+	    sip_method->len, sip_method->s, *acc_record_type, event->len, event->s, *expires,
+	    callid->len, callid->s, asserted_id_uri->len, asserted_id_uri->s, to_uri->len, to_uri->s);
 
     return 1;
 error:
@@ -363,9 +358,9 @@ int get_ims_charging_info(struct sip_msg *req, struct sip_msg * reply, str * ici
 
     LM_DBG("get ims charging info\n");
     if (req)
-        cscf_get_p_charging_vector(req, icid, orig_ioi, term_ioi);
+	cscf_get_p_charging_vector(req, icid, orig_ioi, term_ioi);
     if (reply)
-        cscf_get_p_charging_vector(reply, icid, orig_ioi, term_ioi);
+	cscf_get_p_charging_vector(reply, icid, orig_ioi, term_ioi);
 
     return 1;
 }
@@ -373,9 +368,9 @@ int get_ims_charging_info(struct sip_msg *req, struct sip_msg * reply, str * ici
 int get_timestamps(struct sip_msg * req, struct sip_msg * reply, time_t * req_timestamp, time_t * reply_timestamp) {
 
     if (reply)
-        *reply_timestamp = time(NULL);
+	*reply_timestamp = time(NULL);
     if (req)
-        *req_timestamp = time(NULL);
+	*req_timestamp = time(NULL);
     return 1;
 }
 
@@ -384,7 +379,8 @@ int get_timestamps(struct sip_msg * req, struct sip_msg * reply, time_t * req_ti
  *
  */
 
-Ro_CCR_t * dlg_create_ro_session(struct sip_msg * req, struct sip_msg * reply, AAASession ** authp, int dir, str asserted_identity, str called_asserted_identity, str subscription_id, int subscription_id_type) {
+Ro_CCR_t * dlg_create_ro_session(struct sip_msg * req, struct sip_msg * reply, AAASession ** authp, int dir, str asserted_identity,
+	str called_asserted_identity, str subscription_id, int subscription_id_type, str* incoming_trunk_id, str *outgoing_trunk_id, str* pani) {
 
     Ro_CCR_t * ro_ccr_data = 0;
     AAASession * auth = NULL;
@@ -403,65 +399,66 @@ Ro_CCR_t * dlg_create_ro_session(struct sip_msg * req, struct sip_msg * reply, A
     *authp = 0;
 
     if (!get_sip_header_info(req, reply, &acc_record_type, &sip_method, &event, &expires, &callid, &from_uri, &to_uri))
-        goto error;
+	goto error;
     user_name.s = subscription_id.s;
     user_name.len = subscription_id.len;
-	
+
     /*	if(!get_ims_charging_info(req, reply, &icid, &orig_ioi, &term_ioi))
-                    goto error;
+		    goto error;
      */
     LM_DBG("retrieved ims charging info icid:[%.*s] orig_ioi:[%.*s] term_ioi:[%.*s]\n",
-    		icid.len, icid.s, orig_ioi.len, orig_ioi.s, term_ioi.len, term_ioi.s);
+	    icid.len, icid.s, orig_ioi.len, orig_ioi.s, term_ioi.len, term_ioi.s);
 
     if (!get_timestamps(req, reply, &req_timestamp, &reply_timestamp))
-        goto error;
+	goto error;
 
     if (!(event_type = new_event_type(&sip_method, &event, &expires)))
-        goto error;
+	goto error;
 
     if (!(time_stamps = new_time_stamps(&req_timestamp, NULL, &reply_timestamp, NULL)))
-        goto error;
+	goto error;
 
-    if (!(ims_info = new_ims_information(event_type, time_stamps, &callid, &callid, &asserted_identity, &called_asserted_identity, &icid, &orig_ioi, &term_ioi, dir)))
-        goto error;
+    if (!(ims_info = new_ims_information(event_type, time_stamps, &callid, &callid, &asserted_identity, &called_asserted_identity, &icid,
+	    &orig_ioi, &term_ioi, dir, incoming_trunk_id, outgoing_trunk_id, pani)))
+	goto error;
     event_type = 0;
     time_stamps = 0;
 
-    
+
     subscr.id.s = subscription_id.s;
     subscr.id.len = subscription_id.len;
     subscr.type = subscription_id_type;
-    
+
     ro_ccr_data = new_Ro_CCR(acc_record_type, &user_name, ims_info, &subscr);
     if (!ro_ccr_data) {
-        LM_ERR("dlg_create_ro_session: no memory left for generic\n");
-        goto out_of_memory;
+	LM_ERR("dlg_create_ro_session: no memory left for generic\n");
+	goto out_of_memory;
     }
     ims_info = 0;
 
     if (strncmp(req->first_line.u.request.method.s, "INVITE", 6) == 0) {
-    	//create CDP CC Accounting session
-    	auth = cdpb.AAACreateCCAccSession(credit_control_session_callback, 1/*is_session*/, NULL ); //must unlock session hash when done
-    	LM_DBG("Created Ro Session with id Session ID [%.*s]\n", auth->id.len, auth->id.s);
-        //save_session = auth->id;
+	//create CDP CC Accounting session
+	auth = cdpb.AAACreateCCAccSession(credit_control_session_callback, 1/*is_session*/, NULL); //must unlock session hash when done
+	LM_DBG("Created Ro Session with id Session ID [%.*s]\n", auth->id.len, auth->id.s);
+	//save_session = auth->id;
 
     }
     /*if (strncmp(req->first_line.u.request.method.s, "BYE", 3) == 0) {
-        auth = cdp_avp->cdp->AAAGetAuthSession(save_session);
+	auth = cdp_avp->cdp->AAAGetAuthSession(save_session);
     }*/
 
 
     if (!auth) {
-        LM_ERR("unable to create the Ro Session\n");
-        goto error;
+	LM_ERR("unable to create the Ro Session\n");
+	goto error;
     }
 
     *authp = auth;
     return ro_ccr_data;
 
 out_of_memory:
-error :
-    time_stamps_free(time_stamps);
+    error :
+	    time_stamps_free(time_stamps);
     event_type_free(event_type);
     ims_information_free(ims_info);
     Ro_free_CCR(ro_ccr_data);
@@ -469,16 +466,18 @@ error :
     return NULL;
 }
 
-int sip_create_ro_ccr_data(struct sip_msg * msg, int dir, Ro_CCR_t ** ro_ccr_data, AAASession ** auth, str asserted_identity, str called_asserted_identity, str subscription_id, int subscription_id_type) {
+int sip_create_ro_ccr_data(struct sip_msg * msg, int dir, Ro_CCR_t ** ro_ccr_data, AAASession ** auth, str asserted_identity, str called_asserted_identity,
+	str subscription_id, int subscription_id_type, str* incoming_trunk_id, str* outgoing_trunk_id, str* pani) {
 
     if (msg->first_line.type == SIP_REQUEST) {
-        /*end of session*/
-        if (strncmp(msg->first_line.u.request.method.s, "INVITE", 6) == 0) {
-            if (!(*ro_ccr_data = dlg_create_ro_session(msg, NULL, auth, dir, asserted_identity, called_asserted_identity, subscription_id, subscription_id_type)))
-                goto error;
-        }
+	/*end of session*/
+	if (strncmp(msg->first_line.u.request.method.s, "INVITE", 6) == 0) {
+	    if (!(*ro_ccr_data = dlg_create_ro_session(msg, NULL, auth, dir, asserted_identity, called_asserted_identity, subscription_id,
+		    subscription_id_type, incoming_trunk_id, outgoing_trunk_id, pani)))
+		goto error;
+	}
     } else {
-        goto error; //We only support Request (INVITE) messages on this interface
+	goto error; //We only support Request (INVITE) messages on this interface
     }
 
     return 1;
@@ -486,6 +485,7 @@ error:
     return 0;
 }
 
+/* must be called with lock on ro_session */
 void send_ccr_interim(struct ro_session* ro_session, unsigned int used, unsigned int reserve) {
     AAASession * auth = 0;
 
@@ -495,59 +495,62 @@ void send_ccr_interim(struct ro_session* ro_session, unsigned int used, unsigned
     int32_t acc_record_type;
     subscription_id_t subscr;
     time_stamps_t *time_stamps;
-	struct interim_ccr *i_req = shm_malloc(sizeof(struct interim_ccr));
-	int ret = 0;
+    struct interim_ccr *i_req = shm_malloc(sizeof (struct interim_ccr));
+    int ret = 0;
     event_type_t *event_type;
-    int node_role = 0;
 
-	memset(i_req, 0, sizeof(sizeof(struct interim_ccr)));
-    i_req->ro_session	= ro_session;
+    memset(i_req, 0, sizeof (sizeof (struct interim_ccr)));
+    i_req->ro_session = ro_session;
 
     str sip_method = str_init("dummy");
     str sip_event = str_init("dummy");
-    
+
     str user_name = {0, 0};
 
     time_t req_timestamp;
 
     event_type = new_event_type(&sip_method, &sip_event, 0);
 
-    LM_DBG("Sending interim CCR request for (usage:new) [%i:%i] seconds for user [%.*s] using session id [%.*s]",
-    						used,
-    						reserve,
-    						ro_session->asserted_identity.len, ro_session->asserted_identity.s,
-    						ro_session->ro_session_id.len, ro_session->ro_session_id.s);
+    LM_DBG("Sending interim CCR request for (usage:new) [%i:%i] seconds for user [%.*s] using session id [%.*s] active rating group [%d] active service identifier [%d] incoming_trunk_id [%.*s] outgoing_trunk_id [%.*s]\n",
+	    used,
+	    reserve,
+	    ro_session->asserted_identity.len, ro_session->asserted_identity.s,
+	    ro_session->ro_session_id.len, ro_session->ro_session_id.s,
+	    ro_session->rating_group, ro_session->service_identifier,
+	    ro_session->incoming_trunk_id.len, ro_session->incoming_trunk_id.s,
+	    ro_session->outgoing_trunk_id.len, ro_session->outgoing_trunk_id.s);
 
     req_timestamp = time(0);
 
     if (!(time_stamps = new_time_stamps(&req_timestamp, NULL, NULL, NULL)))
-        goto error;
+	goto error;
 
-    if (!(ims_info = new_ims_information(event_type, time_stamps, &ro_session->callid, &ro_session->callid, &ro_session->asserted_identity, &ro_session->called_asserted_identity, 0, 0, 0, node_role)))
-        goto error;
+    if (!(ims_info = new_ims_information(event_type, time_stamps, &ro_session->callid, &ro_session->callid, &ro_session->asserted_identity,
+	    &ro_session->called_asserted_identity, 0, 0, 0, ro_session->direction, &ro_session->incoming_trunk_id, &ro_session->outgoing_trunk_id, &ro_session->pani)))
+	goto error;
 
     LM_DBG("Created IMS information\n");
 
     event_type = 0;
 
     if (ro_session->direction == RO_ORIG_DIRECTION) {
-        subscr.id = ro_session->asserted_identity;
-        
-	
-    } else if (ro_session->direction == RO_TERM_DIRECTION){
-        subscr.id = ro_session->called_asserted_identity;
+	subscr.id = ro_session->asserted_identity;
+
+
+    } else if (ro_session->direction == RO_TERM_DIRECTION) {
+	subscr.id = ro_session->called_asserted_identity;
     } else {
-    	LM_CRIT("don't know what to do in unknown mode - should we even get here\n");
-    	goto error;
+	LM_CRIT("don't know what to do in unknown mode - should we even get here\n");
+	goto error;
     }
-    
+
     //getting subscription id type
-    if (strncasecmp(subscr.id.s,"tel:",4)==0) {
+    if (strncasecmp(subscr.id.s, "tel:", 4) == 0) {
 	subscr.type = Subscription_Type_MSISDN;
-    }else{
+    } else {
 	subscr.type = Subscription_Type_IMPU; //default is END_USER_SIP_URI
     }
-    
+
     user_name.s = subscr.id.s;
     user_name.len = subscr.id.len;
 
@@ -555,53 +558,53 @@ void send_ccr_interim(struct ro_session* ro_session, unsigned int used, unsigned
 
     ro_ccr_data = new_Ro_CCR(acc_record_type, &user_name, ims_info, &subscr);
     if (!ro_ccr_data) {
-        LM_ERR("no memory left for generic\n");
-        goto error;
+	LM_ERR("no memory left for generic\n");
+	goto error;
     }
     ims_info = NULL;
 
     auth = cdpb.AAAGetCCAccSession(ro_session->ro_session_id);
     if (!auth) {
-        LM_DBG("Diameter Auth Session has timed out.... creating a new one.\n");
-        /* lets try and recreate this session */
-        //TODO: make a CC App session auth = cdpb.AAASession(ro_session->auth_appid, ro_session->auth_session_type, ro_session->ro_session_id); //TODO: would like this session to last longer (see session timeout in cdp
-        //BUG("Oh shit, session timed out and I don't know how to create a new one.");
+	LM_DBG("Diameter Auth Session has timed out.... creating a new one.\n");
+	/* lets try and recreate this session */
+	//TODO: make a CC App session auth = cdpb.AAASession(ro_session->auth_appid, ro_session->auth_session_type, ro_session->ro_session_id); //TODO: would like this session to last longer (see session timeout in cdp
+	//BUG("Oh shit, session timed out and I don't know how to create a new one.");
 
-        auth = cdpb.AAAMakeSession(ro_session->auth_appid, ro_session->auth_session_type, ro_session->ro_session_id); //TODO: would like this session to last longer (see session timeout in cdp
-        if (!auth)
-            goto error;
+	auth = cdpb.AAAMakeSession(ro_session->auth_appid, ro_session->auth_session_type, ro_session->ro_session_id); //TODO: would like this session to last longer (see session timeout in cdp
+	if (!auth)
+	    goto error;
     }
 
     //don't send INTERIM record if session is not in OPEN state (it could already be waiting for a previous response, etc)
     if (auth->u.cc_acc.state != ACC_CC_ST_OPEN) {
-	    LM_WARN("ignoring interim update on CC session not in correct state, currently in state [%d]\n", auth->u.cc_acc.state);
-	    goto error;
+	LM_WARN("ignoring interim update on CC session not in correct state, currently in state [%d]\n", auth->u.cc_acc.state);
+	goto error;
     }
 
     if (!(ccr = Ro_new_ccr(auth, ro_ccr_data)))
-        goto error;
+	goto error;
 
     if (!Ro_add_vendor_specific_appid(ccr, IMS_vendor_id_3GPP, IMS_Ro, 0/*acct id*/)) {
-        LM_ERR("Problem adding Vendor specific ID\n");
+	LM_ERR("Problem adding Vendor specific ID\n");
     }
     ro_session->hop_by_hop += 1;
     if (!Ro_add_cc_request(ccr, RO_CC_INTERIM, ro_session->hop_by_hop)) {
-        LM_ERR("Problem adding CC-Request data\n");
+	LM_ERR("Problem adding CC-Request data\n");
     }
     if (!Ro_add_event_timestamp(ccr, time(NULL))) {
-        LM_ERR("Problem adding Event-Timestamp data\n");
+	LM_ERR("Problem adding Event-Timestamp data\n");
     }
 
     if (!Ro_add_user_equipment_info(ccr, AVP_EPC_User_Equipment_Info_Type_MAC, ro_session->avp_value.mac)) {
-        LM_ERR("Problem adding User-Equipment data\n");
+	LM_ERR("Problem adding User-Equipment data\n");
     }
 
     if (!Ro_add_subscription_id(ccr, subscr.type, &(subscr.id))) {
-        LM_ERR("Problem adding Subscription ID data\n");
+	LM_ERR("Problem adding Subscription ID data\n");
     }
 
-    if (!Ro_add_multiple_service_credit_Control(ccr, interim_request_credits/*INTERIM_CREDIT_REQ_AMOUNT*/, used)) {
-        LM_ERR("Problem adding Multiple Service Credit Control data\n");
+    if (!Ro_add_multiple_service_credit_Control(ccr, interim_request_credits/*INTERIM_CREDIT_REQ_AMOUNT*/, used, ro_session->rating_group, ro_session->service_identifier)) {
+	LM_ERR("Problem adding Multiple Service Credit Control data\n");
     }
 
     LM_DBG("Sending CCR Diameter message.\n");
@@ -609,32 +612,32 @@ void send_ccr_interim(struct ro_session* ro_session, unsigned int used, unsigned
     cdpb.AAASessionsUnlock(auth->hash);
 
     if (ro_forced_peer.len > 0) {
-    	ret = cdpb.AAASendMessageToPeer(ccr, &ro_forced_peer, resume_on_interim_ccr, (void *) i_req);
+	ret = cdpb.AAASendMessageToPeer(ccr, &ro_forced_peer, resume_on_interim_ccr, (void *) i_req);
     } else {
-    	ret = cdpb.AAASendMessage(ccr, resume_on_interim_ccr, (void *) i_req);
+	ret = cdpb.AAASendMessage(ccr, resume_on_interim_ccr, (void *) i_req);
     }
 
     if (ret != 1) {
-    	goto error;
+	goto error;
     }
-//    cdpb.AAASessionsUnlock(auth->hash);
+    //    cdpb.AAASessionsUnlock(auth->hash);
 
     Ro_free_CCR(ro_ccr_data);
 
-    update_stat(interim_ccrs, 1);
+    counter_inc(ims_charging_cnts_h.interim_ccrs);
     return;
 error:
-	LM_ERR("error trying to reserve interim credit\n");
+    LM_ERR("error trying to reserve interim credit\n");
 
-	if (ro_ccr_data)
-		Ro_free_CCR(ro_ccr_data);
+    if (ro_ccr_data)
+	Ro_free_CCR(ro_ccr_data);
 
-	if (ccr)
-		cdpb.AAAFreeMessage(&ccr);
+    if (ccr)
+	cdpb.AAAFreeMessage(&ccr);
 
     if (auth) {
-    	cdpb.AAASessionsUnlock(auth->hash);
-    	cdpb.AAADropCCAccSession(auth);
+	cdpb.AAASessionsUnlock(auth->hash);
+	cdpb.AAADropCCAccSession(auth);
     }
 
     shm_free(i_req);
@@ -643,76 +646,78 @@ error:
     // to it can be reused later.
     //
     struct ro_session_entry *ro_session_entry = &(ro_session_table->entries[ro_session->h_entry]);
-    unref_ro_session_unsafe(ro_session, 1, ro_session_entry);//unref from the initial timer that fired this event.
+    ro_session_lock(ro_session_table, ro_session_entry);
+    unref_ro_session_unsafe(ro_session, 1, ro_session_entry); //unref from the initial timer that fired this event.
     ro_session_unlock(ro_session_table, ro_session_entry);
 
     return;
 }
 
 static void resume_on_interim_ccr(int is_timeout, void *param, AAAMessage *cca, long elapsed_msecs) {
-	struct interim_ccr *i_req	= (struct interim_ccr *) param;
-	Ro_CCA_t * ro_cca_data = NULL;
+    struct interim_ccr *i_req = (struct interim_ccr *) param;
+    Ro_CCA_t * ro_cca_data = NULL;
 
     if (is_timeout) {
-        update_stat(ccr_timeouts, 1);
-        LM_ERR("Transaction timeout - did not get CCA\n");
-        goto error;
+	counter_inc(ims_charging_cnts_h.ccr_timeouts);
+	LM_ERR("Transaction timeout - did not get CCA\n");
+	goto error;
     }
 
-    update_stat(ccr_responses_time, elapsed_msecs);
+    counter_add(ims_charging_cnts_h.ccr_response_time, elapsed_msecs);
+    counter_inc(ims_charging_cnts_h.ccr_replies_received);
 
-	if (!i_req) {
-		LM_ERR("This is so wrong: ro session is NULL\n");
-		goto error;
-	}
+    if (!i_req) {
+	LM_ERR("This is so wrong: ro session is NULL\n");
+	goto error;
+    }
 
-	if (cca == NULL) {
-		LM_ERR("Error reserving credit for CCA.\n");
-		goto error;
-	}
+    if (cca == NULL) {
+	LM_ERR("Error reserving credit for CCA.\n");
+	goto error;
+    }
 
-	ro_cca_data = Ro_parse_CCA_avps(cca);
+    ro_cca_data = Ro_parse_CCA_avps(cca);
 
-	if (ro_cca_data == NULL) {
-		LM_ERR("Could not parse CCA message response.\n");
-		goto error;
-	}
+    if (ro_cca_data == NULL) {
+	LM_ERR("Could not parse CCA message response.\n");
+	goto error;
+    }
 
-	if (ro_cca_data->resultcode != 2001) {
-		LM_ERR("Got bad CCA result code [%d] - reservation failed", ro_cca_data->resultcode);
-		goto error;
-	} else {
-		LM_DBG("Valid CCA response with time chunk of [%i] and validity [%i].\n", ro_cca_data->mscc->granted_service_unit->cc_time, ro_cca_data->mscc->validity_time);
-	}
+    if (ro_cca_data->resultcode != 2001) {
+	LM_ERR("Got bad CCA result code [%d] - reservation failed", ro_cca_data->resultcode);
+	goto error;
+    } else {
+	LM_DBG("Valid CCA response with time chunk of [%i] and validity [%i].\n", ro_cca_data->mscc->granted_service_unit->cc_time, ro_cca_data->mscc->validity_time);
+    }
 
-	i_req->new_credit = ro_cca_data->mscc->granted_service_unit->cc_time;
-	i_req->credit_valid_for = ro_cca_data->mscc->validity_time;
-	i_req->is_final_allocation	= 0;
+    i_req->new_credit = ro_cca_data->mscc->granted_service_unit->cc_time;
+    i_req->credit_valid_for = ro_cca_data->mscc->validity_time;
+    i_req->is_final_allocation = 0;
 
-	if (ro_cca_data->mscc->final_unit_action && (ro_cca_data->mscc->final_unit_action->action == 0))
-		i_req->is_final_allocation = 1;
+    if (ro_cca_data->mscc->final_unit_action && (ro_cca_data->mscc->final_unit_action->action == 0))
+	i_req->is_final_allocation = 1;
 
-	Ro_free_CCA(ro_cca_data);
-	cdpb.AAAFreeMessage(&cca);
+    Ro_free_CCA(ro_cca_data);
+    cdpb.AAAFreeMessage(&cca);
 
-	update_stat(successful_interim_ccrs, 1);
-	goto success;
+    counter_inc(ims_charging_cnts_h.successful_interim_ccrs);
+    goto success;
 
 error:
-	if (ro_cca_data)
-		Ro_free_CCA(ro_cca_data);
+    if (ro_cca_data)
+	Ro_free_CCA(ro_cca_data);
 
-	if (!is_timeout && cca) {
-		cdpb.AAAFreeMessage(&cca);
-	}
+    if (!is_timeout && cca) {
+	cdpb.AAAFreeMessage(&cca);
+    }
 
-	if (i_req) {
-		i_req->credit_valid_for = 0;
-		i_req->new_credit = 0;
-	}
+    if (i_req) {
+	i_req->credit_valid_for = 0;
+	i_req->new_credit = 0;
+    }
 
 success:
-	resume_ro_session_ontimeout(i_req);
+    resume_ro_session_ontimeout(i_req);
 }
 
 void send_ccr_stop(struct ro_session *ro_session) {
@@ -725,16 +730,15 @@ void send_ccr_stop(struct ro_session *ro_session) {
     time_stamps_t *time_stamps;
     unsigned int used = 0;
     str user_name = {0, 0};
-    int ret  = 0;
-    
+    int ret = 0;
+
     if (ro_session->event_type != pending) {
-        used = time(0) - ro_session->last_event_timestamp;
+	used = time(0) - ro_session->last_event_timestamp;
     }
 
-    update_stat(billed_secs, used);
+    counter_add(ims_charging_cnts_h.billed_secs, used);
 
     event_type_t *event_type;
-    int node_role = 0;
 
     str sip_method = str_init("dummy");
     str sip_event = str_init("dummy");
@@ -742,48 +746,54 @@ void send_ccr_stop(struct ro_session *ro_session) {
     time_t req_timestamp;
 
     event_type = new_event_type(&sip_method, &sip_event, 0);
-    
-    LM_DBG("Sending CCR STOP request for for user:[%.*s] using session id:[%.*s] and units:[%d]\n",
-    		ro_session->asserted_identity.len, ro_session->asserted_identity.s, ro_session->ro_session_id.len, ro_session->ro_session_id.s, used);
+
+    LM_DBG("Sending stop CCR request for (usage) [%i] seconds for user [%.*s] using session id [%.*s] active rating group [%d] active service identifier [%d] incoming_trunk_id [%.*s] outgoing_trunk_id [%.*s]\n",
+	    used,
+	    ro_session->asserted_identity.len, ro_session->asserted_identity.s,
+	    ro_session->ro_session_id.len, ro_session->ro_session_id.s,
+	    ro_session->rating_group, ro_session->service_identifier,
+	    ro_session->incoming_trunk_id.len, ro_session->incoming_trunk_id.s,
+	    ro_session->outgoing_trunk_id.len, ro_session->outgoing_trunk_id.s);
 
     req_timestamp = time(0);
 
     if (!(time_stamps = new_time_stamps(&req_timestamp, NULL, NULL, NULL)))
-        goto error0;
+	goto error0;
+
+    if (!(ims_info = new_ims_information(event_type, time_stamps, &ro_session->callid, &ro_session->callid, &ro_session->asserted_identity,
+	    &ro_session->called_asserted_identity, 0, 0, 0, ro_session->direction, &ro_session->incoming_trunk_id, &ro_session->outgoing_trunk_id, &ro_session->pani)))
+	goto error0;
 
-    if (!(ims_info = new_ims_information(event_type, time_stamps, &ro_session->callid, &ro_session->callid, &ro_session->asserted_identity, &ro_session->called_asserted_identity, 0, 0, 0, node_role)))
-        goto error0;
-    
     event_type = 0;
 
     if (ro_session->direction == RO_ORIG_DIRECTION) {
-        subscr.id = ro_session->asserted_identity;
-        
-	
-    } else if (ro_session->direction == RO_TERM_DIRECTION){
-        subscr.id = ro_session->called_asserted_identity;
+	subscr.id = ro_session->asserted_identity;
+
+
+    } else if (ro_session->direction == RO_TERM_DIRECTION) {
+	subscr.id = ro_session->called_asserted_identity;
     } else {
-    	LM_CRIT("don't know what to do in unknown mode - should we even get here\n");
-    	goto error0;
+	LM_CRIT("don't know what to do in unknown mode - should we even get here\n");
+	goto error0;
     }
-    
+
     //getting subscription id type
-    if (strncasecmp(subscr.id.s,"tel:",4)==0) {
+    if (strncasecmp(subscr.id.s, "tel:", 4) == 0) {
 	subscr.type = Subscription_Type_MSISDN;
-    }else{
+    } else {
 	subscr.type = Subscription_Type_IMPU; //default is END_USER_SIP_URI
     }
-    
+
     user_name.s = subscr.id.s;
     user_name.len = subscr.id.len;
-    
-    
+
+
     acc_record_type = AAA_ACCT_STOP;
 
     ro_ccr_data = new_Ro_CCR(acc_record_type, &user_name, ims_info, &subscr);
     if (!ro_ccr_data) {
-        LM_ERR("dlg_create_ro_session: no memory left for generic\n");
-        goto error0;
+	LM_ERR("send_ccr_stop: no memory left for generic\n");
+	goto error0;
     }
     ims_info = 0;
 
@@ -792,63 +802,64 @@ void send_ccr_stop(struct ro_session *ro_session) {
     auth = cdpb.AAAGetCCAccSession(ro_session->ro_session_id);
 
     if (!auth) {
-        LM_DBG("Diameter Auth Session has timed out.... creating a new one.\n");
-        /* lets try and recreate this session */
-        auth = cdpb.AAAMakeSession(ro_session->auth_appid, ro_session->auth_session_type, ro_session->ro_session_id); //TODO: would like this session to last longer (see session timeout in cdp
-        if (!auth)
-            goto error1;
+	LM_DBG("Diameter Auth Session has timed out.... creating a new one.\n");
+	/* lets try and recreate this session */
+	auth = cdpb.AAAMakeSession(ro_session->auth_appid, ro_session->auth_session_type, ro_session->ro_session_id); //TODO: would like this session to last longer (see session timeout in cdp
+	if (!auth)
+	    goto error1;
     }
 
 
     if (!(ccr = Ro_new_ccr(auth, ro_ccr_data)))
-        goto error1;
+	goto error1;
 
     LM_DBG("Created new CCR\n");
 
     if (!Ro_add_vendor_specific_appid(ccr, IMS_vendor_id_3GPP, IMS_Ro, 0)) {
-        LM_ERR("Problem adding Vendor specific ID\n");
+	LM_ERR("Problem adding Vendor specific ID\n");
     }
-   
+
     ro_session->hop_by_hop += 1;
     if (!Ro_add_cc_request(ccr, RO_CC_STOP, ro_session->hop_by_hop)) {
-        LM_ERR("Problem adding CC-Request data\n");
+	LM_ERR("Problem adding CC-Request data\n");
     }
-   
+
     if (!Ro_add_event_timestamp(ccr, time(NULL))) {
-        LM_ERR("Problem adding Event-Timestamp data\n");
+	LM_ERR("Problem adding Event-Timestamp data\n");
     }
 
     if (!Ro_add_user_equipment_info(ccr, AVP_EPC_User_Equipment_Info_Type_MAC, ro_session->avp_value.mac)) {
-        LM_ERR("Problem adding User-Equipment data\n");
+	LM_ERR("Problem adding User-Equipment data\n");
     }
-    
+
     if (!Ro_add_subscription_id(ccr, subscr.type, &subscr.id)) {
-        LM_ERR("Problem adding Subscription ID data\n");
+	LM_ERR("Problem adding Subscription ID data\n");
     }
-    
-    if (!Ro_add_multiple_service_credit_Control_stop(ccr, used)) {
-        LM_ERR("Problem adding Multiple Service Credit Control data\n");
+
+    if (!Ro_add_multiple_service_credit_Control_stop(ccr, used, ro_session->rating_group, ro_session->service_identifier)) {
+	LM_ERR("Problem adding Multiple Service Credit Control data\n");
     }
-    
+
     if (!Ro_add_termination_cause(ccr, TERM_CAUSE_LOGOUT)) {
-        LM_ERR("problem add Termination cause AVP to STOP record.\n");
+	LM_ERR("problem add Termination cause AVP to STOP record.\n");
     }
 
     cdpb.AAASessionsUnlock(auth->hash);
 
     if (ro_forced_peer.len > 0) {
-    	ret = cdpb.AAASendMessageToPeer(ccr, &ro_forced_peer, resume_on_termination_ccr, NULL);
+	ret = cdpb.AAASendMessageToPeer(ccr, &ro_forced_peer, resume_on_termination_ccr, NULL);
     } else {
-    	ret = cdpb.AAASendMessage(ccr, resume_on_termination_ccr, NULL);
+	ret = cdpb.AAASendMessage(ccr, resume_on_termination_ccr, NULL);
     }
 
     if (ret != 1) {
-    	goto error1;
+	goto error1;
     }
 
     Ro_free_CCR(ro_ccr_data);
 
-    update_stat(final_ccrs, 1);
+    counter_inc(ims_charging_cnts_h.final_ccrs);
+    counter_add(ims_charging_cnts_h.active_ro_sessions, -1);
     return;
 
 error1:
@@ -856,8 +867,8 @@ error1:
     Ro_free_CCR(ro_ccr_data);
 
     if (auth) {
-    	cdpb.AAASessionsUnlock(auth->hash);
-    	cdpb.AAADropCCAccSession(auth);
+	cdpb.AAASessionsUnlock(auth->hash);
+	cdpb.AAADropCCAccSession(auth);
     }
 
 error0:
@@ -869,50 +880,46 @@ static void resume_on_termination_ccr(int is_timeout, void *param, AAAMessage *c
     Ro_CCA_t *ro_cca_data = NULL;
 
     if (is_timeout) {
-        update_stat(ccr_timeouts, 1);
-        LM_ERR("Transaction timeout - did not get CCA\n");
-        goto error;
+	counter_inc(ims_charging_cnts_h.ccr_timeouts);
+	LM_ERR("Transaction timeout - did not get CCA\n");
+	goto error;
     }
 
-    update_stat(ccr_responses_time, elapsed_msecs);
+    counter_inc(ims_charging_cnts_h.ccr_replies_received);
+    counter_add(ims_charging_cnts_h.ccr_response_time, elapsed_msecs);
 
     if (!cca) {
-    	LM_ERR("Error in termination CCR.\n");
-        return;
+	LM_ERR("Error in termination CCR.\n");
+	return;
     }
 
     ro_cca_data = Ro_parse_CCA_avps(cca);
 
     if (ro_cca_data == NULL) {
-    	LM_DBG("Could not parse CCA message response.\n");
-    	return;
+	LM_DBG("Could not parse CCA message response.\n");
+	return;
     }
 
     if (ro_cca_data->resultcode != 2001) {
-    	LM_ERR("Got bad CCA result code for STOP record - [%d]\n", ro_cca_data->resultcode);
-        goto error;
-    }
-    else {
-    	LM_DBG("Valid CCA response for STOP record\n");
+	LM_ERR("Got bad CCA result code for STOP record - [%d]\n", ro_cca_data->resultcode);
+	goto error;
+    } else {
+	LM_DBG("Valid CCA response for STOP record\n");
     }
 
-    update_stat(successful_final_ccrs, 1);
+    counter_inc(ims_charging_cnts_h.successful_final_ccrs);
 
 error:
-	Ro_free_CCA(ro_cca_data);
-	if (!is_timeout && cca) {
-		cdpb.AAAFreeMessage(&cca);
-	}
+    Ro_free_CCA(ro_cca_data);
+    if (!is_timeout && cca) {
+	cdpb.AAAFreeMessage(&cca);
+    }
 }
 
-
-
 /**
  * Send a CCR to the OCS based on the SIP message (INVITE ONLY)
  * @param msg - SIP message
  * @param direction - orig|term
- * @param charge_type - IEC (Immediate Event Charging), ECUR (Event Charging with Unit Reservation), SCUR (Session Charging with Unit Reservation)
- * @param unit_type - unused
  * @param reservation_units - units to try to reserve
  * @param reservation_units - config route to call when receiving a CCA
  * @param tindex - transaction index
@@ -920,12 +927,12 @@ error:
  *
  * @returns #CSCF_RETURN_BREAK if OK, #CSCF_RETURN_ERROR on error
  */
-int Ro_Send_CCR(struct sip_msg *msg, struct dlg_cell *dlg, int dir, str* charge_type, str* unit_type, int reservation_units,
-						cfg_action_t* action, unsigned int tindex, unsigned int tlabel) {
-	str session_id = { 0, 0 },
-		called_asserted_identity = {0 , 0 },
-		subscription_id = {0 , 0 },
-	asserted_identity = {0 , 0 };
+int Ro_Send_CCR(struct sip_msg *msg, struct dlg_cell *dlg, int dir, int reservation_units, str* incoming_trunk_id, str* outgoing_trunk_id,
+	str* pani, cfg_action_t* action, unsigned int tindex, unsigned int tlabel) {
+    str session_id = {0, 0},
+    called_asserted_identity = {0, 0},
+    subscription_id = {0, 0},
+    asserted_identity = {0, 0};
     int subscription_id_type = AVP_EPC_Subscription_Id_Type_End_User_SIP_URI;
     AAASession* cc_acc_session = NULL;
     Ro_CCR_t * ro_ccr_data = 0;
@@ -933,210 +940,219 @@ int Ro_Send_CCR(struct sip_msg *msg, struct dlg_cell *dlg, int dir, str* charge_
     struct ro_session *new_session = 0;
     struct session_setup_data *ssd;
     int ret = 0;
-    struct hdr_field *h=0;
-    
-    int cc_event_number = 0;						//According to IOT tests this should start at 0
+    struct hdr_field *h = 0;
+
+    int cc_event_number = 0; //According to IOT tests this should start at 0
     int cc_event_type = RO_CC_START;
     int free_called_asserted_identity = 0;
-    
+
     sdp_session_cell_t* msg_sdp_session;
     sdp_stream_cell_t* msg_sdp_stream;
-    
+
+    int active_service_identifier;
+    int active_rating_group;
+
     int sdp_stream_num = 0;
 
-    ssd = shm_malloc(sizeof(struct session_setup_data)); // lookup structure used to load session info from cdp callback on CCA
+    LM_DBG("Sending initial CCR request for reservation_units [%d] incoming_trunk_id [%.*s] outgoing_trunk_id [%.*s]\n",
+	    reservation_units,
+	    incoming_trunk_id->len, incoming_trunk_id->s,
+	    outgoing_trunk_id->len, outgoing_trunk_id->s);
+
+
+
+    ssd = shm_malloc(sizeof (struct session_setup_data)); // lookup structure used to load session info from cdp callback on CCA
     if (!ssd) {
-    	LM_ERR("no more shm mem\n");
-    	goto error;
+	LM_ERR("no more shm mem\n");
+	goto error;
     }
 
     //getting asserted identity
     if ((asserted_identity = cscf_get_asserted_identity(msg, 0)).len == 0) {
-	    LM_DBG("No P-Asserted-Identity hdr found. Using From hdr for asserted_identity");
-	    asserted_identity	= dlg->from_uri;
+	LM_DBG("No P-Asserted-Identity hdr found. Using From hdr for asserted_identity");
+	asserted_identity = dlg->from_uri;
     }
-    
-    
+
+
     //getting called asserted identity
     if ((called_asserted_identity = cscf_get_public_identity_from_called_party_id(msg, &h)).len == 0) {
-	    LM_DBG("No P-Called-Identity hdr found. Using request URI for called_asserted_identity");
-	    called_asserted_identity = cscf_get_public_identity_from_requri(msg);
-	    free_called_asserted_identity = 1;
+	LM_DBG("No P-Called-Identity hdr found. Using request URI for called_asserted_identity");
+	called_asserted_identity = cscf_get_public_identity_from_requri(msg);
+	free_called_asserted_identity = 1;
     }
-    
+
     if (dir == RO_ORIG_DIRECTION) {
-        subscription_id.s = asserted_identity.s;
-        subscription_id.len = asserted_identity.len;
-	
-    } else if (dir == RO_TERM_DIRECTION){
-        subscription_id.s = called_asserted_identity.s;
-        subscription_id.len = called_asserted_identity.len;
+	subscription_id.s = asserted_identity.s;
+	subscription_id.len = asserted_identity.len;
+
+    } else if (dir == RO_TERM_DIRECTION) {
+	subscription_id.s = called_asserted_identity.s;
+	subscription_id.len = called_asserted_identity.len;
     } else {
-    	LM_CRIT("don't know what to do in unknown mode - should we even get here\n");
-    	goto error;
+	LM_CRIT("don't know what to do in unknown mode - should we even get here\n");
+	goto error;
     }
-    
+
     //getting subscription id type
-    if (strncasecmp(subscription_id.s,"tel:",4)==0) {
+    if (strncasecmp(subscription_id.s, "tel:", 4) == 0) {
 	subscription_id_type = Subscription_Type_MSISDN;
-    }else{
+    } else {
 	subscription_id_type = Subscription_Type_IMPU; //default is END_USER_SIP_URI
     }
 
-    str mac	= {0,0};
+    str mac = {0, 0};
     if (get_mac_avp_value(msg, &mac) != 0)
-    	LM_DBG(RO_MAC_AVP_NAME" was not set. Using default.");
+	LM_DBG(RO_MAC_AVP_NAME" was not set. Using default.");
 
-	//create a session object without auth and diameter session id - we will add this later.
-	new_session = build_new_ro_session(dir, 0, 0, &session_id, &dlg->callid,
-			&asserted_identity, &called_asserted_identity, &mac, dlg->h_entry, dlg->h_id,
-			reservation_units, 0);
+    //by default we use voice service id and rate group
+    //then we check SDP - if we find video then we use video service id and rate group
+    LM_DBG("Setting default SID to %d and RG to %d for voice",
+	    voice_service_identifier, voice_rating_group);
+    active_service_identifier = voice_service_identifier;
+    active_rating_group = voice_rating_group;
 
-	if (!new_session) {
-		LM_ERR("Couldn't create new Ro Session - this is BAD!\n");
-		goto error;
+    //check SDP - if there is video then set default to video, if not set it to audio
+    if (parse_sdp(msg) < 0) {
+	LM_ERR("Unable to parse req SDP\n");
+	goto error;
+    }
+
+    msg_sdp_session = get_sdp_session(msg, 0);
+    if (!msg_sdp_session) {
+	LM_ERR("Missing SDP session information from rpl\n");
+    } else {
+	for (;;) {
+	    msg_sdp_stream = get_sdp_stream(msg, 0, sdp_stream_num);
+	    if (!msg_sdp_stream) {
+		//LM_ERR("Missing SDP stream information\n");
+		break;
+	    }
+
+	    int intportA = atoi(msg_sdp_stream->port.s);
+	    if (intportA != 0 && strncasecmp(msg_sdp_stream->media.s, "video", 5) == 0) {
+		LM_DBG("This SDP has a video component and src ports not equal to 0 - so we set default SID to %d and RG to %d for video",
+			video_service_identifier, video_rating_group);
+		active_service_identifier = video_service_identifier;
+		active_rating_group = video_rating_group;
+		break;
+	    }
+
+	    sdp_stream_num++;
 	}
+    }
+
+    free_sdp((sdp_info_t**) (void*) &msg->body);
 
-	ssd->action	= action;
-	ssd->tindex	= tindex;
-	ssd->tlabel	= tlabel;
-	ssd->ro_session	= new_session;
+    //create a session object without auth and diameter session id - we will add this later.
+    new_session = build_new_ro_session(dir, 0, 0, &session_id, &dlg->callid,
+	    &asserted_identity, &called_asserted_identity, &mac, dlg->h_entry, dlg->h_id,
+	    reservation_units, 0, active_rating_group, active_service_identifier, incoming_trunk_id, outgoing_trunk_id, pani);
 
-    if (!sip_create_ro_ccr_data(msg, dir, &ro_ccr_data, &cc_acc_session, asserted_identity, called_asserted_identity, subscription_id, subscription_id_type))
-        goto error;
+    if (!new_session) {
+	LM_ERR("Couldn't create new Ro Session - this is BAD!\n");
+	goto error;
+    }
+
+    ssd->action = action;
+    ssd->tindex = tindex;
+    ssd->tlabel = tlabel;
+    ssd->ro_session = new_session;
+
+    if (!sip_create_ro_ccr_data(msg, dir, &ro_ccr_data, &cc_acc_session, asserted_identity, called_asserted_identity, subscription_id, subscription_id_type, incoming_trunk_id, outgoing_trunk_id, pani))
+	goto error;
 
     if (!ro_ccr_data)
-        goto error;
+	goto error;
 
     if (!cc_acc_session)
-    	goto error;
-
-	//by default we use voice service id and rate group
-	//then we check SDP - if we find video then we use video service id and rate group
-	LM_DBG("Setting default SID to %d and RG to %d for voice", 
-			    voice_service_identifier, voice_rating_group);
-	active_service_identifier = voice_service_identifier;
-	active_rating_group = voice_rating_group;
-	
-	//check SDP - if there is video then set default to video, if not set it to audio
-	if (parse_sdp(msg) < 0) {
-	    LM_ERR("Unable to parse req SDP\n");
-	    goto error;
-	}
-	
-	msg_sdp_session = get_sdp_session(msg, 0);
-	if (!msg_sdp_session ) {
-            LM_ERR("Missing SDP session information from rpl\n");
-        } else {
-	    for (;;) {
-		msg_sdp_stream = get_sdp_stream(msg, 0, sdp_stream_num);
-		if (!msg_sdp_stream) {
-		    //LM_ERR("Missing SDP stream information\n");
-		    break;
-		}
-
-		int intportA = atoi(msg_sdp_stream->port.s);
-		if(intportA != 0 && strncasecmp(msg_sdp_stream->media.s,"video",5)==0){
-		    LM_DBG("This SDP has a video component and src ports not equal to 0 - so we set default SID to %d and RG to %d for video", 
-			    video_service_identifier, video_rating_group);
-		    active_service_identifier = video_service_identifier;
-		    active_rating_group = video_rating_group;
-		    break;
-		}
-
-		sdp_stream_num++;
-	    }
-	}
-	
-	free_sdp((sdp_info_t**) (void*) &msg->body);
-	
-	
+	goto error;
+
     if (!(ccr = Ro_new_ccr(cc_acc_session, ro_ccr_data)))
-        goto error;
+	goto error;
 
     if (!Ro_add_vendor_specific_appid(ccr, IMS_vendor_id_3GPP, IMS_Ro, 0)) {
-        LM_ERR("Problem adding Vendor specific ID\n");
-        goto error;
+	LM_ERR("Problem adding Vendor specific ID\n");
+	goto error;
     }
 
     if (!Ro_add_cc_request(ccr, cc_event_type, cc_event_number)) {
-        LM_ERR("Problem adding CC-Request data\n");
-        goto error;
+	LM_ERR("Problem adding CC-Request data\n");
+	goto error;
     }
 
     if (!Ro_add_event_timestamp(ccr, time(NULL))) {
-        LM_ERR("Problem adding Event-Timestamp data\n");
-        goto error;
+	LM_ERR("Problem adding Event-Timestamp data\n");
+	goto error;
     }
 
     if (!Ro_add_user_equipment_info(ccr, AVP_EPC_User_Equipment_Info_Type_MAC, mac)) {
-        LM_ERR("Problem adding User-Equipment data\n");
-        goto error;
+	LM_ERR("Problem adding User-Equipment data\n");
+	goto error;
     }
 
     if (!Ro_add_subscription_id(ccr, subscription_id_type, &subscription_id)) {
-        LM_ERR("Problem adding Subscription ID data\n");
-        goto error;
+	LM_ERR("Problem adding Subscription ID data\n");
+	goto error;
     }
-    if (!Ro_add_multiple_service_credit_Control(ccr, reservation_units, -1)) {
-        LM_ERR("Problem adding Multiple Service Credit Control data\n");
-        goto error;
+    if (!Ro_add_multiple_service_credit_Control(ccr, reservation_units, -1, active_rating_group, active_service_identifier)) {
+	LM_ERR("Problem adding Multiple Service Credit Control data\n");
+	goto error;
     }
-
+    
     /* before we send, update our session object with CC App session ID and data */
     new_session->auth_appid = cc_acc_session->application_id;
     new_session->auth_session_type = cc_acc_session->type;
     new_session->ro_session_id.s = (char*) shm_malloc(cc_acc_session->id.len);
     new_session->ro_session_id.len = cc_acc_session->id.len;
     memcpy(new_session->ro_session_id.s, cc_acc_session->id.s, cc_acc_session->id.len);
-    
+
     LM_DBG("new CC Ro Session ID: [%.*s]\n", cc_acc_session->id.len, cc_acc_session->id.s);
 
     LM_DBG("Sending CCR Diameter message.\n");
     cdpb.AAASessionsUnlock(cc_acc_session->hash);
 
     if (ro_forced_peer.len > 0) {
-    	LM_DBG("Sending message with Peer\n");
-    	ret = cdpb.AAASendMessageToPeer(ccr, &ro_forced_peer, resume_on_initial_ccr, (void *) ssd);
+	LM_DBG("Sending message with Peer\n");
+	ret = cdpb.AAASendMessageToPeer(ccr, &ro_forced_peer, resume_on_initial_ccr, (void *) ssd);
     } else {
-    	LM_DBG("Sending message without Peer and realm is [%.*s]\n", ccr->dest_realm->data.len, ccr->dest_realm->data.s);
-    	ret = cdpb.AAASendMessage(ccr, resume_on_initial_ccr, (void *) ssd);
+	LM_DBG("Sending message without Peer and realm is [%.*s]\n", ccr->dest_realm->data.len, ccr->dest_realm->data.s);
+	ret = cdpb.AAASendMessage(ccr, resume_on_initial_ccr, (void *) ssd);
     }
 
     if (ret != 1) {
-    	LM_ERR("Failed to send Diameter CCR\n");
-    	goto error;
+	LM_ERR("Failed to send Diameter CCR\n");
+	goto error;
     }
 
     Ro_free_CCR(ro_ccr_data);
 
     //TODO: if the following fail, we should clean up the Ro session.......
-    if (dlgb.register_dlgcb(dlg, /* DLGCB_RESPONSE_FWDED */ DLGCB_CONFIRMED, dlg_reply, (void*)new_session ,NULL ) != 0) {
-    	LM_CRIT("cannot register callback for dialog confirmation\n");
-    	goto error;
+    if (dlgb.register_dlgcb(dlg, /* DLGCB_RESPONSE_FWDED */ DLGCB_CONFIRMED, dlg_reply, (void*) new_session, NULL) != 0) {
+	LM_CRIT("cannot register callback for dialog confirmation\n");
+	goto error;
     }
 
     if (dlgb.register_dlgcb(dlg, DLGCB_TERMINATED | DLGCB_FAILED | DLGCB_EXPIRED /*| DLGCB_DESTROY */
-    		, dlg_terminated, (void*)new_session, NULL ) != 0) {
-    	LM_CRIT("cannot register callback for dialog termination\n");
-    	goto error;
+	    , dlg_terminated, (void*) new_session, NULL) != 0) {
+	LM_CRIT("cannot register callback for dialog termination\n");
+	goto error;
     }
 
-    update_stat(initial_ccrs, 1);
+    counter_inc(ims_charging_cnts_h.initial_ccrs);
 
-    if(free_called_asserted_identity)  shm_free(called_asserted_identity.s);// shm_malloc in cscf_get_public_identity_from_requri	
+    if (free_called_asserted_identity) shm_free(called_asserted_identity.s); // shm_malloc in cscf_get_public_identity_from_requri	
     return RO_RETURN_BREAK;
 
 error:
-    if(free_called_asserted_identity)  shm_free(called_asserted_identity.s);// shm_malloc in cscf_get_public_identity_from_requri	
+    if (free_called_asserted_identity) shm_free(called_asserted_identity.s); // shm_malloc in cscf_get_public_identity_from_requri	
     Ro_free_CCR(ro_ccr_data);
     if (cc_acc_session) {
-        	cdpb.AAASessionsUnlock(cc_acc_session->hash);
-        	cdpb.AAADropSession(cc_acc_session);
+	cdpb.AAASessionsUnlock(cc_acc_session->hash);
+	cdpb.AAADropSession(cc_acc_session);
     }
 
     if (ssd)
-    	shm_free(ssd);
+	shm_free(ssd);
 
     LM_DBG("Trying to reserve credit on initial INVITE failed.\n");
     return RO_RETURN_ERROR;
@@ -1146,37 +1162,38 @@ static void resume_on_initial_ccr(int is_timeout, void *param, AAAMessage *cca,
     Ro_CCA_t *ro_cca_data = NULL;
     struct cell *t = NULL;
     struct session_setup_data *ssd = (struct session_setup_data *) param;
-    int error_code	= RO_RETURN_ERROR;
+    int error_code = RO_RETURN_ERROR;
 
     if (is_timeout) {
-        update_stat(ccr_timeouts, 1);
-        LM_ERR("Transaction timeout - did not get CCA\n");
-        error_code =  RO_RETURN_ERROR;
-        goto error0;
+	counter_inc(ims_charging_cnts_h.ccr_timeouts);
+	LM_ERR("Transaction timeout - did not get CCA\n");
+	error_code = RO_RETURN_ERROR;
+	goto error0;
     }
 
-    update_stat(ccr_responses_time, elapsed_msecs);
+    counter_inc(ims_charging_cnts_h.ccr_replies_received);
+    counter_add(ims_charging_cnts_h.ccr_response_time, elapsed_msecs);
 
     if (!cca) {
-    	LM_ERR("Error reserving credit for CCA.\n");
-    	error_code	= RO_RETURN_ERROR;
-        goto error0;
+	LM_ERR("Error reserving credit for CCA.\n");
+	error_code = RO_RETURN_ERROR;
+	goto error0;
     }
 
     if (!ssd) {
-    	LM_ERR("Session lookup data is NULL.\n");
-    	error_code	= RO_RETURN_ERROR;
-    	goto error0;
+	LM_ERR("Session lookup data is NULL.\n");
+	error_code = RO_RETURN_ERROR;
+	goto error0;
     }
 
     // we make sure the transaction exists
-	if (tmb.t_lookup_ident(&t, ssd->tindex, ssd->tlabel) < 0) {
-		LM_ERR("t_continue: transaction not found\n");
-		error_code	= RO_RETURN_ERROR;
-		goto error0;
-	}
+    if (tmb.t_lookup_ident(&t, ssd->tindex, ssd->tlabel) < 0) {
+	LM_ERR("t_continue: transaction not found\n");
+	error_code = RO_RETURN_ERROR;
+	goto error0;
+    }
 
-	// we bring the list of AVPs of the transaction to the current context
+    // we bring the list of AVPs of the transaction to the current context
     set_avp_list(AVP_TRACK_FROM | AVP_CLASS_URI, &t->uri_avps_from);
     set_avp_list(AVP_TRACK_TO | AVP_CLASS_URI, &t->uri_avps_to);
     set_avp_list(AVP_TRACK_FROM | AVP_CLASS_USER, &t->user_avps_from);
@@ -1187,20 +1204,26 @@ static void resume_on_initial_ccr(int is_timeout, void *param, AAAMessage *cca,
     ro_cca_data = Ro_parse_CCA_avps(cca);
 
     if (!ro_cca_data) {
-    	LM_ERR("Could not parse CCA message response.\n");
-    	error_code	= RO_RETURN_ERROR;
-        goto error0;
+	LM_ERR("Could not parse CCA message response.\n");
+	error_code = RO_RETURN_ERROR;
+	goto error0;
     }
 
     if (ro_cca_data->resultcode != 2001) {
-    	LM_ERR("Got bad CCA result code - reservation failed");
-    	error_code	= RO_RETURN_FALSE;
-        goto error1;
+	LM_ERR("Got bad CCA result code - reservation failed");
+	error_code = RO_RETURN_FALSE;
+	goto error1;
     }
 
     LM_DBG("Valid CCA response with time chunk of [%i] and validity [%i]\n",
-    			ro_cca_data->mscc->granted_service_unit->cc_time,
-    			ro_cca_data->mscc->validity_time);
+	    ro_cca_data->mscc->granted_service_unit->cc_time,
+	    ro_cca_data->mscc->validity_time);
+    
+    if (ro_cca_data->mscc->granted_service_unit->cc_time <=0 ) {
+        LM_DBG("got zero GSU.... reservation failed");
+	error_code = RO_RETURN_FALSE;
+	goto error1;
+    }
 
     ssd->ro_session->last_event_timestamp = time(0);
     ssd->ro_session->event_type = pending;
@@ -1212,33 +1235,43 @@ static void resume_on_initial_ccr(int is_timeout, void *param, AAAMessage *cca,
     LM_DBG("Freeing CCA message\n");
     cdpb.AAAFreeMessage(&cca);
 
-    link_ro_session(ssd->ro_session, 1);            //create extra ref for the fact that dialog has a handle in the callbacks
-    unref_ro_session(ssd->ro_session, 1);
+    link_ro_session(ssd->ro_session, 1); /* create extra ref for the fact that dialog has a handle in the callbacks */
+
+    if (ro_db_mode == DB_MODE_REALTIME) {
+	ssd->ro_session->flags |= RO_SESSION_FLAG_NEW;
+	if (update_ro_dbinfo(ssd->ro_session) != 0) {
+	    LM_ERR("Failed to update ro_session in database... continuing\n");
+	};
+    }
+
+    unref_ro_session(ssd->ro_session, 1); /* release our reference */
 
     create_cca_return_code(RO_RETURN_TRUE);
 
     if (t)
-    	tmb.unref_cell(t);
+	tmb.unref_cell(t);
 
     tmb.t_continue(ssd->tindex, ssd->tlabel, ssd->action);
     shm_free(ssd);
 
-    update_stat(successful_initial_ccrs, 1);
+    counter_inc(ims_charging_cnts_h.successful_initial_ccrs);
+    counter_inc(ims_charging_cnts_h.active_ro_sessions);
+
     return;
 
 error1:
-	Ro_free_CCA(ro_cca_data);
+    Ro_free_CCA(ro_cca_data);
 
 error0:
     LM_DBG("Trying to reserve credit on initial INVITE failed on cdp callback\n");
     create_cca_return_code(error_code);
 
     if (!is_timeout && cca) {
-    	cdpb.AAAFreeMessage(&cca);
+	cdpb.AAAFreeMessage(&cca);
     }
 
     if (t)
-    	tmb.unref_cell(t);
+	tmb.unref_cell(t);
 
     tmb.t_continue(ssd->tindex, ssd->tlabel, ssd->action);
     shm_free(ssd);
@@ -1248,23 +1281,23 @@ void remove_aaa_session(str *session_id) {
     AAASession *session;
 
     if ((session = cdpb.AAAGetCCAccSession(*session_id))) {
-        LM_DBG("Found AAA CC App Auth session to delete.\n");
-        cdpb.AAASessionsUnlock(session->hash);
-        cdpb.AAADropCCAccSession(session);
+	LM_DBG("Found AAA CC App Auth session to delete.\n");
+	cdpb.AAASessionsUnlock(session->hash);
+	cdpb.AAADropCCAccSession(session);
     }
 }
 
 int get_direction_as_int(str* direction) {
-	char* p = direction->s;
-
-	if (direction->len > 0 && p) {
-		if (p[0]=='O' || p[0]=='o'){
-			return RO_ORIG_DIRECTION;
-		} else if (p[0]=='T' || p[0]=='t') {
-			return RO_TERM_DIRECTION;
-		}
+    char* p = direction->s;
+
+    if (direction->len > 0 && p) {
+	if (p[0] == 'O' || p[0] == 'o') {
+	    return RO_ORIG_DIRECTION;
+	} else if (p[0] == 'T' || p[0] == 't') {
+	    return RO_TERM_DIRECTION;
 	}
-	return RO_UNKNOWN_DIRECTION;
+    }
+    return RO_UNKNOWN_DIRECTION;
 }
 
 static int create_cca_return_code(int result) {
@@ -1274,50 +1307,50 @@ static int create_cca_return_code(int result) {
     avp_name.s.len = RO_AVP_CCA_RETURN_CODE_LENGTH;
 
     avp_val.n = result;
-    avp_val.s.s = RO_RETURN_TRUE_STR;	//assume true
+    avp_val.s.s = RO_RETURN_TRUE_STR; //assume true
     avp_val.s.len = 1;
 
-    switch(result) {
-    case RO_RETURN_FALSE:
-    	avp_val.s.s = RO_RETURN_FALSE_STR;
-    	break;
-    case RO_RETURN_ERROR:
-    	avp_val.s.s = RO_RETURN_ERROR_STR;
-    	break;
-    default:
-    	if (result >= 0)
-    		break;
+    switch (result) {
+	case RO_RETURN_FALSE:
+	    avp_val.s.s = RO_RETURN_FALSE_STR;
+	    break;
+	case RO_RETURN_ERROR:
+	    avp_val.s.s = RO_RETURN_ERROR_STR;
+	    break;
+	default:
+	    if (result >= 0)
+		break;
 
-    	LM_ERR("Unknown result code: %d", result);
-    	avp_val.s.s = "??";
+	    LM_ERR("Unknown result code: %d", result);
+	    avp_val.s.s = "??";
     }
 
-    if (result < 0)	
-        avp_val.s.len = 2;
+    if (result < 0)
+	avp_val.s.len = 2;
 
-    rc = add_avp(AVP_NAME_STR|AVP_VAL_STR, avp_name, avp_val);
+    rc = add_avp(AVP_NAME_STR | AVP_VAL_STR, avp_name, avp_val);
 
     if (rc < 0)
-        LM_ERR("Couldn't create ["RO_AVP_CCA_RETURN_CODE"] AVP\n");
+	LM_ERR("Couldn't create ["RO_AVP_CCA_RETURN_CODE"] AVP\n");
     else
-    	LM_DBG("Created AVP ["RO_AVP_CCA_RETURN_CODE"] successfully: value=[%d]\n", result);
+	LM_DBG("Created AVP ["RO_AVP_CCA_RETURN_CODE"] successfully: value=[%d]\n", result);
 
     return 1;
 }
 
 static int get_mac_avp_value(struct sip_msg *msg, str *value) {
-	str mac_avp_name_str = str_init(RO_MAC_AVP_NAME);
-	pv_spec_t avp_spec;
-	pv_value_t val;
+    str mac_avp_name_str = str_init(RO_MAC_AVP_NAME);
+    pv_spec_t avp_spec;
+    pv_value_t val;
 
-	pv_parse_spec2(&mac_avp_name_str, &avp_spec, 1);
-	if (pv_get_spec_value(msg, &avp_spec, &val) != 0 || val.rs.len == 0) {
+    pv_parse_spec2(&mac_avp_name_str, &avp_spec, 1);
+    if (pv_get_spec_value(msg, &avp_spec, &val) != 0 || val.rs.len == 0) {
 
-		value->s	= "00:00:00:00:00:00";
-		value->len	= sizeof("00:00:00:00:00:00") - 1;
-		return -1;
-	}
+	value->s = "00:00:00:00:00:00";
+	value->len = sizeof ("00:00:00:00:00:00") - 1;
+	return -1;
+    }
 
-	*value = val.rs;
-	return 0;
+    *value = val.rs;
+    return 0;
 }
diff --git a/modules/ims_charging/ims_ro.h b/modules/ims_charging/ims_ro.h
index 353b610..b18d0f8 100644
--- a/modules/ims_charging/ims_ro.h
+++ b/modules/ims_charging/ims_ro.h
@@ -14,8 +14,8 @@ struct interim_ccr {
 
 void credit_control_session_callback(int event, void* session);
 void remove_aaa_session(str *session_id);
-int Ro_Send_CCR(struct sip_msg *msg, struct dlg_cell *dlg, int dir, str* charge_type, str* unit_type, int reservation_units, cfg_action_t* action, unsigned int tindex, unsigned int tlabel);
-//void send_ccr_interim(struct ro_session *ro_session, str* from_uri, str *to_uri, int *new_credit, int *credit_valid_for, unsigned int used, unsigned int reserve, unsigned int *is_final_allocation);
+int Ro_Send_CCR(struct sip_msg *msg, struct dlg_cell *dlg, int dir, int reservation_units, 
+	    str *incoming_trunk_id, str *outgoing_trunk_id, str *enb_cell_id, cfg_action_t* action, unsigned int tindex, unsigned int tlabel);
 void send_ccr_interim(struct ro_session* ro_session, unsigned int used, unsigned int reserve);
 void send_ccr_stop(struct ro_session *ro_session);
 int get_direction_as_int(str* direction);
diff --git a/modules/ims_charging/mod.c b/modules/ims_charging/mod.c
index 1a60ef9..2b45f72 100644
--- a/modules/ims_charging/mod.c
+++ b/modules/ims_charging/mod.c
@@ -12,7 +12,6 @@
 #include "../cdp/cdp_load.h"
 #include "../cdp_avp/mod_export.h"
 #include "../../parser/parse_to.h"
-#include "stats.h"
 #include "ro_timer.h"
 #include "ro_session_hash.h"
 #include "ims_ro.h"
@@ -20,6 +19,8 @@
 #include "dialog.h"
 #include "../ims_usrloc_scscf/usrloc.h"
 #include "../../lib/ims/ims_getters.h"
+#include "ro_db_handler.h"
+#include "ims_charging_stats.h"
 
 MODULE_VERSION
 
@@ -40,8 +41,15 @@ int voice_rating_group = 100;
 int video_service_identifier = 1001;
 int video_rating_group = 200;
 
-int active_service_identifier = 1000; //current SID to be used - will  be changed depending on SDP info
-int active_rating_group = 200; //current RG to be used - will  be changed depending on SDP info
+
+/* DB params */
+static str db_url = str_init(DEFAULT_DB_URL);
+static unsigned int db_update_period = DB_DEFAULT_UPDATE_PERIOD;
+int ro_db_mode_param = DB_MODE_NONE;
+static int db_fetch_rows = 200;
+int ro_db_mode = DB_MODE_NONE;
+
+char *domain = "location";
 
 client_ro_cfg cfg = { str_init("scscf.ims.smilecoms.com"),
     str_init("ims.smilecoms.com"),
@@ -67,30 +75,18 @@ int cdp_event_threshold = 500; /*time in ms above which we should report slow pr
 int cdp_event_latency_loglevel = 0; /*log-level to use to report slow processing of CDP callback event - default ERROR*/
 int single_ro_session_per_dialog = 0; /*whether to to have 1 ro_session per dialog or let user decide from config - default is an ro session every time Ro_CCR called from config file*/
 
-stat_var *initial_ccrs;
-stat_var *interim_ccrs;
-stat_var *final_ccrs;
-stat_var *successful_initial_ccrs;
-stat_var *successful_interim_ccrs;
-stat_var *successful_final_ccrs;
-stat_var *ccr_responses_time;
-stat_var *billed_secs;
-stat_var *killed_calls;
-stat_var *ccr_timeouts;
-
 /** module functions */
 static int mod_init(void);
 static int mod_child_init(int);
 static void mod_destroy(void);
 
-static int w_ro_ccr(struct sip_msg *msg, str* route_name, str* direction, str* charge_type, str* unit_type, int reservation_units, char *_d);
+static int w_ro_ccr(struct sip_msg *msg, char* route_name, char* direction, int reservation_units, char* incoming_trunk_id, char* outgoing_trunk_id);
 //void ro_session_ontimeout(struct ro_tl *tl);
 
-static int domain_fixup(void** param);
 static int ro_fixup(void **param, int param_no);
 
 static cmd_export_t cmds[] = {
-		{ "Ro_CCR", 	(cmd_function) w_ro_ccr, 6, ro_fixup, 0, REQUEST_ROUTE },
+		{ "Ro_CCR", 	(cmd_function) w_ro_ccr, 5, ro_fixup, 0, REQUEST_ROUTE },
 		{ 0, 0, 0, 0, 0, 0 }
 };
 
@@ -115,37 +111,22 @@ static param_export_t params[] = {
 		{ "service_context_id_ext", PARAM_STRING,			&ro_service_context_id_ext_s 	},
 		{ "service_context_id_mnc", PARAM_STRING,			&ro_service_context_id_mnc_s 	},
 		{ "service_context_id_mcc", PARAM_STRING,			&ro_service_context_id_mcc_s 	},
-		{ "service_context_id_release",	PARAM_STRING, 		&ro_service_context_id_release_s},
+		{ "service_context_id_release",	PARAM_STRING,			&ro_service_context_id_release_s},
 		{ "voice_service_identifier", 	INT_PARAM, 			&voice_service_identifier },/*service id for voice*/
 		{ "voice_rating_group", 	INT_PARAM, 			&voice_rating_group },/*rating group for voice*/
 		{ "video_service_identifier", 	INT_PARAM, 			&video_service_identifier },/*service id for voice*/
 		{ "video_rating_group", 	INT_PARAM, 			&video_rating_group },/*rating group for voice*/
+		{ "db_mode",			INT_PARAM,			&ro_db_mode_param		},
+		{ "db_url",			PARAM_STRING,			&db_url 			},
+		{ "db_update_period",		INT_PARAM,			&db_update_period		},
 		{ 0, 0, 0 }
 };
 
-stat_export_t charging_stats[] = {
-    {"initial_ccrs", STAT_NO_RESET, &initial_ccrs},
-    {"interim_ccrs", STAT_NO_RESET, &interim_ccrs},
-    {"final_ccrs", STAT_NO_RESET, &final_ccrs},
-    {"successful_initial_ccrs", STAT_NO_RESET, &successful_initial_ccrs},
-    {"successful_interim_ccr", STAT_NO_RESET, &successful_interim_ccrs},
-    {"successful_final_ccrs", STAT_NO_RESET, &successful_final_ccrs},
-    {"failed_initial_ccrs", STAT_IS_FUNC, (stat_var**) get_failed_initial_ccrs},
-    {"failed_interim_ccr", STAT_IS_FUNC, (stat_var**) get_failed_interim_ccrs},
-    {"failed_final_ccrs", STAT_IS_FUNC, (stat_var**) get_failed_final_ccrs},
-    {"ccr_avg_response_time", STAT_IS_FUNC, (stat_var**) get_ccr_avg_response_time},
-    {"ccr_responses_time", STAT_NO_RESET, &ccr_responses_time},
-    {"billed_secs", STAT_NO_RESET, &billed_secs},
-    {"killed_calls", STAT_NO_RESET, &killed_calls},
-    {"ccr_timeouts", 0, &ccr_timeouts},
-    {0, 0, 0}
-};
-
 /** module exports */
 struct module_exports exports = { MOD_NAME, DEFAULT_DLFLAGS, /* dlopen flags */
 		cmds, 		/* Exported functions */
 		params, 	/* Exported params */
-		charging_stats,	/* exported statistics */
+		0,		/* exported statistics */
 		0, 			/* exported MI functions */
 		0, 			/* exported pseudo-variables */
 		0, 			/* extra processes */
@@ -270,40 +251,70 @@ static int mod_init(void) {
 	    return -1;
 	}
 	
-	 /* register statistics */
-	if (register_module_stats(exports.name, charging_stats) != 0) {
-		LM_ERR("failed to register core statistics\n");
-		return -1;
+	if (ims_charging_init_counters() != 0) {
+	    LM_ERR("Failed to register counters for ims_charging module\n");
+	    return -1;
 	}
-
-	/*if (register_stat(MOD_NAME, "ccr_responses_time", &ccr_responses_time, 0)) {
-		LM_ERR("failed to register core statistics\n");
+	
+	/* if a database should be used to store the dialogs' information */
+	ro_db_mode = ro_db_mode_param;
+	if (ro_db_mode == DB_MODE_NONE) {
+	    db_url.s = 0;
+	    db_url.len = 0;
+	} else {
+	    if (ro_db_mode != DB_MODE_REALTIME && ro_db_mode != DB_MODE_SHUTDOWN) {
+		LM_ERR("unsupported db_mode %d\n", ro_db_mode);
+		return -1;
+	    }
+	    if (!db_url.s || db_url.len == 0) {
+		LM_ERR("db_url not configured for db_mode %d\n", ro_db_mode);
+		return -1;
+	    }
+	    if (init_ro_db(&db_url, ro_session_hash_size, db_update_period, db_fetch_rows) != 0) {
+		LM_ERR("failed to initialize the DB support\n");
 		return -1;
-	}*/
+	    }
+//	    run_load_callbacks();
+	}
 
 	return 0;
 
 error:
-	LM_ERR("Failed to initialise ims_qos module\n");
+	LM_ERR("Failed to initialise ims_charging module\n");
 	return RO_RETURN_FALSE;
 
 }
 
 static int mod_child_init(int rank) {
-	return 0;
+    ro_db_mode = ro_db_mode_param;
+
+    if (((ro_db_mode == DB_MODE_REALTIME) && (rank > 0 || rank == PROC_TIMER)) ||
+	    (ro_db_mode == DB_MODE_SHUTDOWN && (rank == PROC_MAIN))) {
+	if (ro_connect_db(&db_url)) {
+	    LM_ERR("failed to connect to database (rank=%d)\n", rank);
+	    return -1;
+	}
+    }
+
+    /* in DB_MODE_SHUTDOWN only PROC_MAIN will do a DB dump at the end, so
+     * for the rest of the processes will be the same as DB_MODE_NONE */
+    if (ro_db_mode == DB_MODE_SHUTDOWN && rank != PROC_MAIN)
+	ro_db_mode = DB_MODE_NONE;
+    /* in DB_MODE_REALTIME and DB_MODE_DELAYED the PROC_MAIN have no DB handle */
+    if ((ro_db_mode == DB_MODE_REALTIME) && rank == PROC_MAIN)
+	ro_db_mode = DB_MODE_NONE;
+    
+    return 0;
 }
 
 static void mod_destroy(void) {
 
 }
 
-static int w_ro_ccr(struct sip_msg *msg, str* route_name, str* direction, str* charge_type, str* unit_type, int reservation_units, char* _d) {
+static int w_ro_ccr(struct sip_msg *msg, char* c_route_name, char* c_direction, int reservation_units, char* c_incoming_trunk_id, char* c_outgoing_trunk_id) {
 	/* PSEUDOCODE/NOTES
 	 * 1. What mode are we in - terminating or originating
-	 * 2. check request type - 	IEC - Immediate Event Charging
-	 * 							ECUR - Event Charging with Unit Reservation
-	 * 							SCUR - Session Charging with Unit Reservation
-	 * 3. probably only do SCUR in this module for now - can see event based charging in another component instead (AS for SMS for example, etc)
+	 * 2. We assume this is SCUR in this module for now - can see event based charging in another component instead (AS for SMS for example, etc)
 	 * 4. Check a dialog exists for call, if not we fail
 	 * 5. make sure we dont already have an Ro Session for this dialog
 	 * 6. create new Ro Session
@@ -314,7 +325,8 @@ static int w_ro_ccr(struct sip_msg *msg, str* route_name, str* direction, str* c
 	int ret = RO_RETURN_TRUE;
 	int dir = 0;
 	str identity = {0, 0},
-		contact = {0, 0};
+	pani = {0,0},
+	contact = {0, 0};
 	struct hdr_field *h=0;
 	
 	cfg_action_t* cfg_action;
@@ -322,19 +334,38 @@ static int w_ro_ccr(struct sip_msg *msg, str* route_name, str* direction, str* c
 	unsigned int tindex = 0,
 				 tlabel = 0;
 	struct impu_data *impu_data;
-	udomain_t* domain_t = (udomain_t*) _d;
 	char *p;
 	struct dlg_cell* dlg;
 	unsigned int len;
 	struct ro_session *ro_session = 0;
 	int free_contact = 0;
 	
-	LM_DBG("Ro CCR initiated: direction:%.*s, charge_type:%.*s, unit_type:%.*s, reservation_units:%i, route_name:%.*s",
-			direction->len, direction->s,
-			charge_type->len, charge_type->s,
-			unit_type->len, unit_type->s,
+	str s_route_name, s_direction, s_incoming_trunk_id, s_outgoing_trunk_id;
+	
+	if (get_str_fparam(&s_route_name, msg, (fparam_t*) c_route_name) < 0) {
+	    LM_ERR("failed to get s_route_name\n");
+	    return RO_RETURN_ERROR;
+	}
+	if (get_str_fparam(&s_direction, msg, (fparam_t*) c_direction) < 0) {
+	    LM_ERR("failed to get s_direction\n");
+	    return RO_RETURN_ERROR;
+	}
+	if (get_str_fparam(&s_incoming_trunk_id, msg, (fparam_t*) c_incoming_trunk_id) < 0) {
+	    LM_ERR("failed to get s_incoming_trunk_id\n");
+	    return RO_RETURN_ERROR;
+	}
+	if (get_str_fparam(&s_outgoing_trunk_id, msg, (fparam_t*) c_outgoing_trunk_id) < 0) {
+	    LM_ERR("failed to get s_outgoing_trunk_id\n");
+	    return RO_RETURN_ERROR;
+	}
+	
+	LM_DBG("Ro CCR initiated: direction:%.*s, reservation_units:%i, route_name:%.*s, incoming_trunk_id:%.*s outgoing_trunk_id:%.*s\n",
+			s_direction.len, s_direction.s,
 			reservation_units,
-			route_name->len, route_name->s);
+			s_route_name.len, s_route_name.s,
+			s_incoming_trunk_id.len, s_incoming_trunk_id.s,
+			s_outgoing_trunk_id.len, s_outgoing_trunk_id.s);
+	
 
 	if (msg->first_line.type != SIP_REQUEST) {
 	    LM_ERR("Ro_CCR() called from SIP reply.");
@@ -349,7 +380,7 @@ static int w_ro_ccr(struct sip_msg *msg, str* route_name, str* direction, str* c
 		return RO_RETURN_ERROR;
 	}
 	
-	dir = get_direction_as_int(direction);
+	dir = get_direction_as_int(&s_direction);
 	
 	if (dir == RO_ORIG_DIRECTION) {
 		//get caller IMPU from asserted identity
@@ -363,6 +394,7 @@ static int w_ro_ccr(struct sip_msg *msg, str* route_name, str* direction, str* c
 			goto send_ccr;
 		}
 		
+		pani = cscf_get_access_network_info(msg, &h);
 	} else if (dir == RO_TERM_DIRECTION){
 		//get callee IMPU from called part id - if not present then skip this
 		if ((identity = cscf_get_public_identity_from_called_party_id(msg, &h)).len == 0) {
@@ -402,8 +434,6 @@ static int w_ro_ccr(struct sip_msg *msg, str* route_name, str* direction, str* c
 	memcpy(p, contact.s, contact.len);
 	p += contact.len;
 	
-	impu_data->d = domain_t;
-
 	if (p != (((char*) impu_data) + len)) {
 	    LM_ERR("buffer overflow creating impu data, trying to send CCR\n");
 	    shm_free(impu_data);
@@ -436,18 +466,18 @@ send_ccr:
 	    goto done;
 	}
 	
-	LM_DBG("Looking for route block [%.*s]\n", route_name->len, route_name->s);
+	LM_DBG("Looking for route block [%.*s]\n", s_route_name.len, s_route_name.s);
 
-	int ri = route_get(&main_rt, route_name->s);
+	int ri = route_get(&main_rt, s_route_name.s);
 	if (ri < 0) {
-		LM_ERR("unable to find route block [%.*s]\n", route_name->len, route_name->s);
+		LM_ERR("unable to find route block [%.*s]\n", s_route_name.len, s_route_name.s);
 		ret = RO_RETURN_ERROR;
 		goto done;
 	}
 	
 	cfg_action = main_rt.rlist[ri];
 	if (!cfg_action) {
-		LM_ERR("empty action lists in route block [%.*s]\n", route_name->len, route_name->s);
+		LM_ERR("empty action lists in route block [%.*s]\n", s_route_name.len, s_route_name.s);
 		ret = RO_RETURN_ERROR;
 		goto done;
 	}
@@ -475,7 +505,7 @@ send_ccr:
 		goto done;
 	}
 	
-	ret = Ro_Send_CCR(msg, dlg, dir, charge_type, unit_type, reservation_units, cfg_action, tindex, tlabel);
+	ret = Ro_Send_CCR(msg, dlg, dir, reservation_units, &s_incoming_trunk_id, &s_outgoing_trunk_id, &pani, cfg_action, tindex, tlabel);
 	
 	if(ret < 0){
 	    LM_ERR("Failed to send CCR\n");
@@ -487,26 +517,13 @@ done:
 	return ret;
 }
 
-///* fixups */
-static int domain_fixup(void** param)
-{
-	udomain_t* d;
-
-	if (ul.register_udomain((char*)*param, &d) < 0) {
-		LM_ERR("failed to register domain\n");
-		return E_UNSPEC;
-	}
-	*param = (void*)d;
-	return 0;
-}
-
 static int ro_fixup(void **param, int param_no) {
 	str s;
 	unsigned int num;
 
-	if (param_no > 0 && param_no <= 4) {
+	if ( (param_no > 0 && param_no <= 2) || (param_no >= 4 && param_no <= 6)) {
 		return fixup_var_str_12(param, param_no);
-	} else if (param_no == 5) {
+	} else if (param_no == 3) {
 		/*convert to int */
 		s.s = (char*)*param;
 		s.len = strlen(s.s);
@@ -517,9 +534,6 @@ static int ro_fixup(void **param, int param_no) {
 		}
 		LM_ERR("Bad reservation units: <%s>n", (char*)(*param));
 		return E_CFG;
-	} 
-	else if (param_no == 6) {
-		return domain_fixup(param);
 	}
 	
 	return 0;
diff --git a/modules/ims_charging/mod.h b/modules/ims_charging/mod.h
index 9c0bc82..a34c5a9 100644
--- a/modules/ims_charging/mod.h
+++ b/modules/ims_charging/mod.h
@@ -14,9 +14,9 @@
 #define RO_CC_INTERIM 	2
 #define RO_CC_STOP 		3
 
-#define RO_UNKNOWN_DIRECTION 0
-#define RO_ORIG_DIRECTION 1
-#define RO_TERM_DIRECTION 2
+#define RO_UNKNOWN_DIRECTION -1
+#define RO_ORIG_DIRECTION 0
+#define RO_TERM_DIRECTION 1
 
 /** Return and break the execution of routing script */
 #define RO_RETURN_BREAK	0
@@ -47,4 +47,10 @@
 
 #define RO_MAC_AVP_NAME	"$avp(ro_mac_value)"
 
+#define DB_DEFAULT_UPDATE_PERIOD	60
+
+#define DB_MODE_NONE				0
+#define DB_MODE_REALTIME			1
+#define DB_MODE_SHUTDOWN			2
+
 #endif /* MOD_H_ */
diff --git a/modules/ims_charging/ro_db_handler.c b/modules/ims_charging/ro_db_handler.c
new file mode 100644
index 0000000..f66292d
--- /dev/null
+++ b/modules/ims_charging/ro_db_handler.c
@@ -0,0 +1,269 @@
+#include "ro_db_handler.h"
+#include "../../lib/srdb1/db.h"
+
+static db1_con_t* ro_db_handle = 0; /* database connection handle */
+static db_func_t ro_dbf;
+
+str ro_session_table_name = str_init(RO_SESSION_TABLE_NAME);
+str id_column = str_init(ID_COL);
+str h_entry_column = str_init(HASH_ENTRY_COL);
+str h_id_column = str_init(HASH_ID_COL);
+str session_id_column = str_init(SESSION_ID_COL);
+str dlg_h_entry_column = str_init(DLG_HASH_ENTRY_COL);
+str dlg_h_id_column = str_init(DLG_HASH_ID_COL);
+str direction_column = str_init(DIRECTION_COL);
+str asserted_column = str_init(ASSERTED_ID_COL);
+str callee_column = str_init(CALLEE_COL);
+str start_time_col = str_init(START_TIME_COL);
+str last_event_ts_column = str_init(LAST_EVENT_TS_COL);
+str reserved_sec_column = str_init(RESERVED_SECS_COL);
+str valid_for_column = str_init(VALID_FOR_COL);
+str state_column = str_init(STATE_COL);
+str incoming_trunk_id_column = str_init(INCOMING_TRUNK_ID_COL);
+str outgoing_trunk_id_column = str_init(OUTGOING_TRUNK_ID_COL);
+str rating_group_column = str_init(RATING_GROUP_COL);
+str service_identifier_column = str_init(SERVICE_IDENTIFIER_COL);
+
+typedef enum ro_session_field_idx {
+    ID_COL_IDX = 0,
+    HASH_ENTRY_COL_IDX,
+    HASH_ID_COL_IDX,
+    SESSION_ID_COL_IDX,
+    DLG_HASH_ENTRY_COL_IDX,
+    DLG_HASH_ID_COL_IDX,
+    DIRECTION_COL_IDX,
+    ASSERTED_ID_COL_IDX,
+    CALLEE_COL_IDX,
+    START_TIME_COL_IDX,
+    LAST_EVENT_TS_COL_IDX,
+    RESERVED_SECS_COL_IDX,
+    VALID_FOR_COL_IDX,
+    STATE_COL_IDX,
+    INCOMING_TRUNK_ID_COL_IDX,
+    OUTGOING_TRUNK_ID_COL_IDX,
+    RATING_GROUP_COL_IDX,
+    SERVICE_IDENTIFIER_COL_IDX
+	    
+} ro_session_field_idx_t;
+
+#define GET_FIELD_IDX(_val, _idx)\
+		(_val + _idx)
+
+#define SET_STR_VALUE(_val, _str)\
+	do{\
+			VAL_STR((_val)).s = (_str).s;\
+			VAL_STR((_val)).len = (_str).len;\
+	}while(0);
+
+#define SET_NULL_FLAG(_vals, _i, _max, _flag)\
+	do{\
+		for((_i) = 0;(_i)<(_max); (_i)++)\
+			VAL_NULL((_vals)+(_i)) = (_flag);\
+	}while(0);
+
+#define SET_PROPER_NULL_FLAG(_str, _vals, _index)\
+	do{\
+		if( (_str).len == 0)\
+			VAL_NULL( (_vals)+(_index) ) = 1;\
+		else\
+			VAL_NULL( (_vals)+(_index) ) = 0;\
+	}while(0);
+
+#define GET_STR_VALUE(_res, _values, _index, _not_null, _unref)\
+	do{\
+		if (VAL_NULL((_values)+ (_index))) { \
+			if (_not_null) {\
+				if (_unref) unref_dlg(dlg,1);\
+				goto next_dialog; \
+			} else { \
+				(_res).s = 0; \
+				(_res).len = 0; \
+			}\
+		} else { \
+			(_res).s = VAL_STR((_values)+ (_index)).s;\
+			(_res).len = strlen(VAL_STR((_values)+ (_index)).s);\
+		} \
+	}while(0);
+
+int init_ro_db(const str *db_url, int dlg_hash_size, int db_update_period, int fetch_num_rows) {
+    /* Find a database module */
+    if (db_bind_mod(db_url, &ro_dbf) < 0) {
+	LM_ERR("Unable to bind to a database driver\n");
+	return -1;
+    }
+
+    if (ro_connect_db(db_url) != 0) {
+	LM_ERR("unable to connect to the database\n");
+	return -1;
+    }
+
+    if (db_check_table_version(&ro_dbf, ro_db_handle, &ro_session_table_name, RO_TABLE_VERSION) < 0) {
+	LM_ERR("error during dialog-table version check.\n");
+	return -1;
+    }
+
+    //	if( (dlg_db_mode==DB_MODE_DELAYED) && 
+    //	(register_timer( dialog_update_db, 0, db_update_period)<0 )) {
+    //		LM_ERR("failed to register update db\n");
+    //		return -1;
+    //	}
+
+    if ((load_ro_info_from_db(dlg_hash_size, fetch_num_rows)) != 0) {
+	LM_ERR("unable to load the dialog data\n");
+	return -1;
+    }
+
+    ro_dbf.close(ro_db_handle);
+    ro_db_handle = 0;
+
+    return 0;
+}
+
+int load_ro_info_from_db(int hash_size, int fetch_num_rows) {
+    LM_WARN("not supported yet");
+    return 0;
+}
+
+int ro_connect_db(const str *db_url) {
+    if (ro_db_handle) {
+	LM_CRIT("BUG - db connection found already open\n");
+	return -1;
+    }
+    if ((ro_db_handle = ro_dbf.init(db_url)) == 0)
+	return -1;
+
+    /* use default table */
+    if (ro_dbf.use_table(ro_db_handle, &ro_session_table_name) != 0) {
+	LM_ERR("Error in use table for table name [%.*s]\n", ro_session_table_name.len, ro_session_table_name.s);
+	return -1;
+    }
+
+    return 0;
+}
+
+void db_set_int_val(db_val_t* values, int index, int val) {
+    VAL_TYPE(GET_FIELD_IDX(values, index)) = DB1_INT;
+    VAL_NULL(GET_FIELD_IDX(values, index)) = 0;
+    VAL_INT(GET_FIELD_IDX(values, index)) = val;
+}
+
+void db_set_str_val(db_val_t* values, int index, str* val) {
+    VAL_TYPE(GET_FIELD_IDX(values, index)) = DB1_STR;
+    VAL_NULL(GET_FIELD_IDX(values, index)) = 0;
+    SET_STR_VALUE(GET_FIELD_IDX(values, index), *val);
+}
+
+void db_set_datetime_val(db_val_t* values, int index, time_t val) {
+    VAL_TYPE(GET_FIELD_IDX(values, index)) = DB1_DATETIME;
+    VAL_NULL(GET_FIELD_IDX(values, index)) = 0;
+    VAL_TIME(GET_FIELD_IDX(values, index)) = val;
+}
+
+int update_ro_dbinfo_unsafe(struct ro_session* ro_session) {
+    if ((ro_session->flags & RO_SESSION_FLAG_NEW) != 0 && (ro_session->flags & RO_SESSION_FLAG_INSERTED) == 0) {
+
+	db_val_t values[RO_SESSION_TABLE_COL_NUM];
+	db_key_t insert_keys[RO_SESSION_TABLE_COL_NUM] = {
+	    &id_column, &h_entry_column, &h_id_column, &session_id_column, &dlg_h_entry_column, &dlg_h_id_column,
+	    &direction_column, &asserted_column, &callee_column, &start_time_col, &last_event_ts_column,
+	    &reserved_sec_column, &valid_for_column, &state_column, &incoming_trunk_id_column, &outgoing_trunk_id_column, &rating_group_column, &service_identifier_column
+	};
+
+	VAL_TYPE(GET_FIELD_IDX(values, ID_COL_IDX)) = DB1_INT;
+	VAL_NULL(GET_FIELD_IDX(values, ID_COL_IDX)) = 1;
+
+	db_set_int_val(values, HASH_ENTRY_COL_IDX, ro_session->h_entry);
+	db_set_int_val(values, HASH_ID_COL_IDX, ro_session->h_id);
+	db_set_str_val(values, SESSION_ID_COL_IDX, &ro_session->ro_session_id);
+	db_set_int_val(values, DLG_HASH_ENTRY_COL_IDX, ro_session->dlg_h_entry);
+	db_set_int_val(values, DLG_HASH_ID_COL_IDX, ro_session->dlg_h_id);
+	db_set_int_val(values, DIRECTION_COL_IDX, ro_session->direction);
+	db_set_str_val(values, ASSERTED_ID_COL_IDX, &ro_session->asserted_identity);
+	db_set_str_val(values, CALLEE_COL_IDX, &ro_session->called_asserted_identity);
+	db_set_datetime_val(values, START_TIME_COL_IDX, ro_session->start_time);
+	db_set_datetime_val(values, LAST_EVENT_TS_COL_IDX, ro_session->last_event_timestamp);
+	db_set_int_val(values, RESERVED_SECS_COL_IDX, ro_session->reserved_secs);
+	db_set_int_val(values, VALID_FOR_COL_IDX, ro_session->valid_for);
+	db_set_int_val(values, STATE_COL_IDX, ro_session->active);
+	db_set_str_val(values, INCOMING_TRUNK_ID_COL_IDX, &ro_session->incoming_trunk_id);
+	db_set_str_val(values, OUTGOING_TRUNK_ID_COL_IDX, &ro_session->outgoing_trunk_id);
+	db_set_int_val(values, RATING_GROUP_COL_IDX, ro_session->rating_group);
+	db_set_int_val(values, SERVICE_IDENTIFIER_COL_IDX, ro_session->service_identifier);
+	
+
+	LM_DBG("Inserting ro_session into database\n");
+	if ((ro_dbf.insert(ro_db_handle, insert_keys, values, RO_SESSION_TABLE_COL_NUM)) != 0) {
+	    LM_ERR("could not add new Ro session into DB.... continuing\n");
+	    goto error;
+	}
+	ro_session->flags &= ~(RO_SESSION_FLAG_NEW | RO_SESSION_FLAG_CHANGED);
+	ro_session->flags |= RO_SESSION_FLAG_INSERTED;
+
+    } else if ((ro_session->flags & RO_SESSION_FLAG_CHANGED) != 0 && (ro_session->flags & RO_SESSION_FLAG_INSERTED) != 0) {
+
+	db_val_t values[RO_SESSION_TABLE_COL_NUM-1];
+	db_key_t update_keys[RO_SESSION_TABLE_COL_NUM-1] = {
+	    &h_entry_column, &h_id_column, &session_id_column, &dlg_h_entry_column, &dlg_h_id_column,
+	    &direction_column, &asserted_column, &callee_column, &start_time_col, &last_event_ts_column,
+	    &reserved_sec_column, &valid_for_column, &state_column, &incoming_trunk_id_column, &outgoing_trunk_id_column, &rating_group_column, &service_identifier_column
+	};
+
+	db_set_int_val(values, HASH_ENTRY_COL_IDX - 1, ro_session->h_entry);
+	db_set_int_val(values, HASH_ID_COL_IDX - 1, ro_session->h_id);
+	db_set_str_val(values, SESSION_ID_COL_IDX - 1, &ro_session->ro_session_id);
+	db_set_int_val(values, DLG_HASH_ENTRY_COL_IDX - 1, ro_session->dlg_h_entry);
+	db_set_int_val(values, DLG_HASH_ID_COL_IDX - 1, ro_session->dlg_h_id);
+	db_set_int_val(values, DIRECTION_COL_IDX - 1, ro_session->direction);
+	db_set_str_val(values, ASSERTED_ID_COL_IDX - 1, &ro_session->asserted_identity);
+	db_set_str_val(values, CALLEE_COL_IDX - 1, &ro_session->called_asserted_identity);
+	db_set_datetime_val(values, START_TIME_COL_IDX - 1, ro_session->start_time);
+	db_set_datetime_val(values, LAST_EVENT_TS_COL_IDX - 1, ro_session->last_event_timestamp);
+	db_set_int_val(values, RESERVED_SECS_COL_IDX - 1, ro_session->reserved_secs);
+	db_set_int_val(values, VALID_FOR_COL_IDX - 1, ro_session->valid_for);
+	db_set_int_val(values, STATE_COL_IDX - 1, ro_session->active);
+	db_set_str_val(values, INCOMING_TRUNK_ID_COL_IDX - 1, &ro_session->incoming_trunk_id);
+	db_set_str_val(values, OUTGOING_TRUNK_ID_COL_IDX - 1, &ro_session->outgoing_trunk_id);
+	db_set_int_val(values, RATING_GROUP_COL_IDX - 1, ro_session->rating_group);
+	db_set_int_val(values, SERVICE_IDENTIFIER_COL_IDX - 1, ro_session->service_identifier);
+
+	LM_DBG("Updating ro_session in database\n");
+	if ((ro_dbf.update(ro_db_handle, update_keys/*match*/, 0/*match*/, values/*match*/, update_keys/*update*/, values/*update*/, 3/*match*/, 13/*update*/)) != 0) {
+	    LM_ERR("could not update Ro session information in DB... continuing\n");
+	    goto error;
+	}
+	ro_session->flags &= ~RO_SESSION_FLAG_CHANGED;
+    } else if ((ro_session->flags & RO_SESSION_FLAG_DELETED) != 0) {
+	db_val_t values[3];
+	db_key_t match_keys[3] = {&h_entry_column, &h_id_column, &session_id_column};
+	
+	db_set_int_val(values, HASH_ENTRY_COL_IDX - 1, ro_session->h_entry);
+	db_set_int_val(values, HASH_ID_COL_IDX - 1, ro_session->h_id);
+	db_set_str_val(values, SESSION_ID_COL_IDX - 1, &ro_session->ro_session_id);
+	
+	if(ro_dbf.delete(ro_db_handle, match_keys, 0, values, 3) < 0) {
+		LM_ERR("failed to delete ro session database information... continuing\n");
+		return -1;
+	}
+    } else {
+	LM_WARN("Asked to update Ro session in strange state [%d]\n", ro_session->flags);
+    }
+
+    return 0;
+
+error:
+    return -1;
+}
+
+int update_ro_dbinfo(struct ro_session* ro_session) {
+    struct ro_session_entry entry;
+    /* lock the entry */
+    entry = (ro_session_table->entries)[ro_session->h_entry];
+    ro_session_lock(ro_session_table, &entry);
+    if (update_ro_dbinfo_unsafe(ro_session) != 0) {
+	LM_ERR("failed to update ro_session in DB\n");
+	ro_session_unlock(ro_session_table, &entry);
+	return -1;
+    }
+    ro_session_unlock(ro_session_table, &entry);
+    return 0;
+}
diff --git a/modules/ims_charging/ro_db_handler.h b/modules/ims_charging/ro_db_handler.h
new file mode 100644
index 0000000..cb5fdd9
--- /dev/null
+++ b/modules/ims_charging/ro_db_handler.h
@@ -0,0 +1,45 @@
+/* 
+ * File:   ro_db_handler.h
+ * Author: jaybeepee
+ *
+ * Created on 02 September 2014, 11:20 AM
+ */
+
+#ifndef RO_DB_HANDLER_H
+#define	RO_DB_HANDLER_H
+
+#include "../../str.h"
+#include "../../lib/srdb1/db.h"
+#include "ro_session_hash.h"
+
+#define RO_TABLE_VERSION            1
+#define RO_SESSION_TABLE_NAME       "ro_session"
+#define RO_SESSION_TABLE_COL_NUM    18
+
+#define ID_COL                      "id"
+#define HASH_ENTRY_COL              "hash_entry"
+#define HASH_ID_COL                 "hash_id"
+#define SESSION_ID_COL              "session_id"
+#define DLG_HASH_ENTRY_COL          "dlg_hash_entry"
+#define DLG_HASH_ID_COL             "dlg_hash_id"
+#define DIRECTION_COL               "direction"
+#define ASSERTED_ID_COL             "asserted_identity"
+#define CALLEE_COL                  "callee"
+#define START_TIME_COL              "start_time"
+#define LAST_EVENT_TS_COL           "last_event_timestamp"
+#define RESERVED_SECS_COL           "reserved_secs"
+#define VALID_FOR_COL               "valid_for"
+#define STATE_COL                   "state"
+#define RATING_GROUP_COL            "rating_group"
+#define SERVICE_IDENTIFIER_COL      "service_identifier"
+#define INCOMING_TRUNK_ID_COL	    "incoming_trunk_id"
+#define OUTGOING_TRUNK_ID_COL		    "outgoing_trunk_id"
+
+int init_ro_db(const str *db_url, int dlg_hash_size , int db_update_period, int fetch_num_rows);
+int load_ro_info_from_db(int hash_size, int fetch_num_rows);
+int ro_connect_db(const str *db_url);
+int update_ro_dbinfo_unsafe(struct ro_session* ro_session);
+int update_ro_dbinfo(struct ro_session* ro_session);
+
+#endif	/* RO_DB_HANDLER_H */
+
diff --git a/modules/ims_charging/ro_session_hash.c b/modules/ims_charging/ro_session_hash.c
index d236692..b78d827 100644
--- a/modules/ims_charging/ro_session_hash.c
+++ b/modules/ims_charging/ro_session_hash.c
@@ -7,8 +7,8 @@
 
 #include "ro_session_hash.h"
 
-#define MAX_LDG_LOCKS  2048
-#define MIN_LDG_LOCKS  2
+#define MAX_ROSESSION_LOCKS  2048
+#define MIN_ROSESSION_LOCKS  2
 
 /*! global ro_session table */
 struct ro_session_table *ro_session_table = 0;
@@ -82,7 +82,7 @@ int init_ro_session_table(unsigned int size) {
     unsigned int n;
     unsigned int i;
 
-    ro_session_table = (struct ro_session_table*) shm_malloc(sizeof (struct ro_session_table) +size * sizeof (struct ro_session_entry));
+    ro_session_table = (struct ro_session_table*) shm_malloc(sizeof (struct ro_session_table) + size * sizeof (struct ro_session_entry));
     if (ro_session_table == 0) {
         LM_ERR("no more shm mem (1)\n");
         goto error0;
@@ -92,8 +92,8 @@ int init_ro_session_table(unsigned int size) {
     ro_session_table->size = size;
     ro_session_table->entries = (struct ro_session_entry*) (ro_session_table + 1);
 
-    n = (size < MAX_LDG_LOCKS) ? size : MAX_LDG_LOCKS;
-    for (; n >= MIN_LDG_LOCKS; n--) {
+    n = (size < MAX_ROSESSION_LOCKS) ? size : MAX_ROSESSION_LOCKS;
+    for (; n >= MIN_ROSESSION_LOCKS; n--) {
         ro_session_table->locks = lock_set_alloc(n);
         if (ro_session_table->locks == 0)
             continue;
@@ -107,20 +107,21 @@ int init_ro_session_table(unsigned int size) {
     }
 
     if (ro_session_table->locks == 0) {
-        LM_ERR("unable to allocted at least %d locks for the hash table\n",
-                MIN_LDG_LOCKS);
+        LM_ERR("unable to allocate at least %d locks for the hash table\n",
+                MIN_ROSESSION_LOCKS);
         goto error1;
     }
 
     for (i = 0; i < size; i++) {
         memset(&(ro_session_table->entries[i]), 0, sizeof (struct ro_session_entry));
-        ro_session_table->entries[i].next_id = rand();
+        ro_session_table->entries[i].next_id = rand() % (3*size);
         ro_session_table->entries[i].lock_idx = i % ro_session_table->locks_no;
     }
 
     return 0;
 error1:
     shm_free(ro_session_table);
+    ro_session_table = NULL;
 error0:
     return -1;
 }
@@ -174,10 +175,13 @@ void destroy_dlg_table(void) {
     return;
 }
 
-struct ro_session* build_new_ro_session(int direction, int auth_appid, int auth_session_type, str *session_id, str *callid, str *asserted_identity, str* called_asserted_identity, str* mac, unsigned int dlg_h_entry, unsigned int dlg_h_id, unsigned int requested_secs, unsigned int validity_timeout){
+struct ro_session* build_new_ro_session(int direction, int auth_appid, int auth_session_type, str *session_id, str *callid, str *asserted_identity, 
+	str* called_asserted_identity, str* mac, unsigned int dlg_h_entry, unsigned int dlg_h_id, unsigned int requested_secs, unsigned int validity_timeout,
+	int active_rating_group, int active_service_identifier, str *incoming_trunk_id, str *outgoing_trunk_id, str *pani){
     LM_DBG("Building Ro Session **********");
     char *p;
-    unsigned int len = session_id->len + callid->len + asserted_identity->len + called_asserted_identity->len + mac->len + sizeof (struct ro_session);
+    unsigned int len = session_id->len + callid->len + asserted_identity->len + called_asserted_identity->len + mac->len + 
+        incoming_trunk_id->len + outgoing_trunk_id->len + pani->len + sizeof (struct ro_session);
     struct ro_session *new_ro_session = (struct ro_session*) shm_malloc(len);
 
     if (!new_ro_session) {
@@ -189,6 +193,11 @@ struct ro_session* build_new_ro_session(int direction, int auth_appid, int auth_
     LM_DBG("New Ro Session given memory at address [%p]\n", new_ro_session);
 
     memset(new_ro_session, 0, len);
+    
+//    if (pani->len < MAX_PANI_LEN) {
+//		p = new_ro_session->pani;
+//		memcpy(p, pani->s, pani->len);
+//    }
 
     new_ro_session->direction = direction;
     new_ro_session->auth_appid = auth_appid;
@@ -208,6 +217,9 @@ struct ro_session* build_new_ro_session(int direction, int auth_appid, int auth_
     new_ro_session->h_entry = dlg_h_entry; /* we will use the same entry ID as the dlg - saves us using our own hash function */
     new_ro_session->h_id = 0;
     new_ro_session->ref = 0;
+    
+    new_ro_session->rating_group = active_rating_group;
+    new_ro_session->service_identifier = active_service_identifier;
 
     p = (char*) (new_ro_session + 1);
     new_ro_session->callid.s = p;
@@ -230,11 +242,25 @@ struct ro_session* build_new_ro_session(int direction, int auth_appid, int auth_
     memcpy(p, called_asserted_identity->s, called_asserted_identity->len);
     p += called_asserted_identity->len;
     
-    new_ro_session->avp_value.mac.s		= p;
-    new_ro_session->avp_value.mac.len	= mac->len;
+    new_ro_session->incoming_trunk_id.s = p;
+    new_ro_session->incoming_trunk_id.len = incoming_trunk_id->len;
+    memcpy(p, incoming_trunk_id->s, incoming_trunk_id->len);
+    p += incoming_trunk_id->len;
+    
+    new_ro_session->outgoing_trunk_id.s = p;
+    new_ro_session->outgoing_trunk_id.len = outgoing_trunk_id->len;
+    memcpy(p, outgoing_trunk_id->s, outgoing_trunk_id->len);
+    p += outgoing_trunk_id->len;
+    
+    new_ro_session->avp_value.mac.s = p;
+    new_ro_session->avp_value.mac.len = mac->len;
     memcpy(p, mac->s, mac->len);
-
     p += mac->len;
+    
+    new_ro_session->pani.s = p;
+    memcpy(p, pani->s, pani->len);
+    new_ro_session->pani.len = pani->len;
+    p += pani->len;
 
     if (p != (((char*) new_ro_session) + len)) {
         LM_ERR("buffer overflow\n");
diff --git a/modules/ims_charging/ro_session_hash.h b/modules/ims_charging/ro_session_hash.h
index dc9d8df..4e7c9fe 100644
--- a/modules/ims_charging/ro_session_hash.h
+++ b/modules/ims_charging/ro_session_hash.h
@@ -13,6 +13,15 @@
 #include "../ims_usrloc_scscf/usrloc.h"
 #include <stdlib.h>
 
+
+/* ro session flags */
+#define RO_SESSION_FLAG_NEW          (1<<0) /*!< new ro session */
+#define RO_SESSION_FLAG_INSERTED     (1<<1) /*!< session has been written to DB */
+#define RO_SESSION_FLAG_CHANGED      (1<<2) /*!< ro session has been updated */
+#define RO_SESSION_FLAG_DELETED      (1<<3) /*!< ro session has been deleted */
+
+#define MAX_PANI_LEN 100
+
 enum ro_session_event_type {
     pending,
     answered,
@@ -28,12 +37,11 @@ struct diameter_avp_value {
 struct impu_data {
     str identity;
     str contact;
-    udomain_t* d;
 } impu_data_t;
 
 
 struct ro_session {
-	str cdp_session_id;
+    str cdp_session_id;
     volatile int ref;
     int direction;
     struct ro_session* next;
@@ -42,6 +50,9 @@ struct ro_session {
     str callid;
     str asserted_identity;
     str called_asserted_identity;
+    str incoming_trunk_id;
+    str outgoing_trunk_id;
+    str pani;
     unsigned int hop_by_hop;
     struct ro_tl ro_tl;
     unsigned int reserved_secs;
@@ -56,8 +67,10 @@ struct ro_session {
     int auth_appid;
     int auth_session_type;
     int active;
-
+    unsigned int flags;
     struct diameter_avp_value avp_value;
+    int rating_group;
+    int service_identifier;
 };
 
 /*! entries in the main ro_session table */
@@ -179,7 +192,9 @@ void link_ro_session(struct ro_session *ro_session, int n);
 
 void remove_aaa_session(str *session_id);
 
-struct ro_session* build_new_ro_session(int direction, int auth_appid, int auth_session_type, str *session_id, str *callid, str *asserted_identity, str* called_asserted_identity, str* mac, unsigned int dlg_h_entry, unsigned int dlg_h_id, unsigned int requested_secs, unsigned int validity_timeout);
+struct ro_session* build_new_ro_session(int direction, int auth_appid, int auth_session_type, str *session_id, str *callid, str *asserted_identity, str* called_asserted_identity, 
+	str* mac, unsigned int dlg_h_entry, unsigned int dlg_h_id, unsigned int requested_secs, unsigned int validity_timeout,
+	int active_rating_group, int active_service_identifier, str *incoming_trunk_id, str *outgoing_trunk_id, str *pani);
 
 /*!
  * \brief Refefence a ro_session with locking
diff --git a/modules/ims_charging/ro_timer.c b/modules/ims_charging/ro_timer.c
index 8467341..d1d036d 100644
--- a/modules/ims_charging/ro_timer.c
+++ b/modules/ims_charging/ro_timer.c
@@ -14,12 +14,16 @@
 #include "ro_timer.h"
 #include "ro_session_hash.h"
 #include "ims_ro.h"
-#include "stats.h"
+#include "ro_db_handler.h"
+#include "mod.h"
+#include "ims_charging_stats.h"
+#include "../../counters.h"
 
 extern int interim_request_credits;
 extern int ro_timer_buffer;
-
+extern int ro_db_mode;
 extern struct dlg_binds dlgb;
+extern struct ims_charging_counters_h ims_charging_cnts_h;
 
 /*! global dialog timer */
 struct ro_timer *roi_timer = 0;
@@ -264,7 +268,7 @@ void resume_ro_session_ontimeout(struct interim_ccr *i_req) {
 	}
 
 	ro_session_entry = &(ro_session_table->entries[i_req->ro_session->h_entry]);
-
+	ro_session_lock(ro_session_table, ro_session_entry);
 	LM_DBG("credit=%d credit_valid_for=%d", i_req->new_credit, i_req->credit_valid_for);
 
 	used_secs = now - i_req->ro_session->last_event_timestamp;
@@ -317,6 +321,13 @@ void resume_ro_session_ontimeout(struct interim_ccr *i_req) {
 		else {
 			ref_ro_session_unsafe(i_req->ro_session, 1);
 		}
+		
+		if (ro_db_mode == DB_MODE_REALTIME) {
+		    i_req->ro_session->flags |= RO_SESSION_FLAG_CHANGED;
+		    if (update_ro_dbinfo_unsafe(i_req->ro_session) != 0) {
+			LM_ERR("Failed to update Ro session in DB... continuing\n");
+		    }
+		}
 	}
 	else {
 		/* just put the timer back in with however many seconds are left (if any!!! in which case we need to kill */
@@ -374,7 +385,6 @@ void ro_session_ontimeout(struct ro_tl *tl) {
 	LM_DBG("We have a fired timer [p=%p] and tl=[%i].\n", tl, tl->timeout);
 
 	/* find the session id for this timer*/
-	struct ro_session_entry *ro_session_entry = NULL;
 	struct ro_session* ro_session = ((struct ro_session*) ((char *) (tl) - (unsigned long) (&((struct ro_session*) 0)->ro_tl)));
 
 	if (!ro_session) {
@@ -382,9 +392,6 @@ void ro_session_ontimeout(struct ro_tl *tl) {
 		return;
 	}
 
-	ro_session_entry = &(ro_session_table->entries[ro_session->h_entry]);
-	ro_session_lock(ro_session_table, ro_session_entry);
-	
 	LM_DBG("event-type=%d", ro_session->event_type);
 	
 //	if (!ro_session->active) {
@@ -399,7 +406,7 @@ void ro_session_ontimeout(struct ro_tl *tl) {
 		used_secs = now - ro_session->last_event_timestamp;
 		call_time = now - ro_session->start_time;
 
-		update_stat(billed_secs, used_secs);
+		counter_add(ims_charging_cnts_h.billed_secs, used_secs);
 
 		if (ro_session->callid.s != NULL
 				&& ro_session->dlg_h_entry	>= 0
@@ -455,10 +462,10 @@ void ro_session_ontimeout(struct ro_tl *tl) {
 	}
 
 
-	update_stat(killed_calls, 1);
+	counter_inc(ims_charging_cnts_h.killed_calls);
 
 	//unref_ro_session_unsafe(ro_session, 1, ro_session_entry); //unref from the initial timer that fired this event.
-	ro_session_unlock(ro_session_table, ro_session_entry);
+//	ro_session_unlock(ro_session_table, ro_session_entry);
 
 	dlgb.lookup_terminate_dlg(ro_session->dlg_h_entry, ro_session->dlg_h_id, NULL);
 	return;
diff --git a/modules/ims_charging/stats.c b/modules/ims_charging/stats.c
deleted file mode 100644
index 93627d8..0000000
--- a/modules/ims_charging/stats.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * stats.c
- *
- *  Created on: Sep 30, 2013
- *      Author: carlos
- */
-
-#include "stats.h"
-
-unsigned long get_failed_initial_ccrs() {
-
-	unsigned long success_number = get_stat_val(successful_initial_ccrs),
-		 total_number	= get_stat_val(initial_ccrs);
-
-	return total_number - success_number;
-}
-
-unsigned long get_failed_interim_ccrs() {
-
-	unsigned long success_number = get_stat_val(successful_interim_ccrs),
-		 total_number	= get_stat_val(interim_ccrs);
-
-	return total_number - success_number;
-}
-
-unsigned long get_failed_final_ccrs() {
-
-	unsigned long success_number = get_stat_val(successful_final_ccrs),
-		 total_number	= get_stat_val(final_ccrs);
-
-	return total_number - success_number;
-}
-
-unsigned long get_ccr_avg_response_time() {
-
-	unsigned long responses_time = get_stat_val(ccr_responses_time),
-				  ccrs	= get_stat_val(initial_ccrs)
-				  	  	  + get_stat_val(interim_ccrs)
-				  	  	  + get_stat_val(final_ccrs);
-
-	if (responses_time == 0 || ccrs == 0)
-		return 0;
-
-	return responses_time / ccrs;
-}
diff --git a/modules/ims_charging/stats.h b/modules/ims_charging/stats.h
deleted file mode 100644
index 9b0e3fc..0000000
--- a/modules/ims_charging/stats.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * stats.h
- *
- *  Created on: Sep 30, 2013
- *      Author: carlos
- */
-
-#ifndef STATS_H_
-#define STATS_H_
-
-#include "../../lib/kcore/statistics.h"
-
-extern stat_var *initial_ccrs;
-extern stat_var *interim_ccrs;
-extern stat_var *final_ccrs;
-extern stat_var *successful_initial_ccrs;
-extern stat_var *successful_interim_ccrs;
-extern stat_var *successful_final_ccrs;
-extern stat_var *ccr_responses_time;
-extern stat_var *billed_secs;
-extern stat_var *killed_calls;
-extern stat_var *ccr_timeouts;
-
-unsigned long get_failed_initial_ccrs();
-unsigned long get_failed_interim_ccrs();
-unsigned long get_failed_final_ccrs();
-unsigned long get_ccr_avg_response_time();
-
-#endif /* STATS_H_ */
diff --git a/modules/ims_icscf/Makefile b/modules/ims_icscf/Makefile
index 9e74f28..5f3ce6a 100644
--- a/modules/ims_icscf/Makefile
+++ b/modules/ims_icscf/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # IMS_ICSCF make file
 #
diff --git a/modules/ims_icscf/doc/ims_icscf_admin.xml b/modules/ims_icscf/doc/ims_icscf_admin.xml
index 4712bbb..dfd9a9c 100644
--- a/modules/ims_icscf/doc/ims_icscf_admin.xml
+++ b/modules/ims_icscf/doc/ims_icscf_admin.xml
@@ -140,7 +140,7 @@ modparam("ims_icscf", "cxdx_forced_peer", "hss.ims.smilecoms.com")
       <para><emphasis> Default value is "ims.smilecoms.com".</emphasis></para>
 
       <example>
-        <title><varname>version_table</varname> parameter usage</title>
+        <title><varname>cxdx_dest_realm</varname> parameter usage</title>
 
         <programlisting format="linespecific">
 ...
@@ -149,6 +149,47 @@ modparam("ims_icscf", "cxdx_dest_realm", "ims.smilecoms.com")
     </programlisting>
       </example>
     </section>
+    
+    <section>
+      <title><varname>use_preferred_scscf_uri</varname> (int)</title>
+
+      <para>Whether or not this ICSCF has a preferred S-CSCF to use when the
+      HSS returns a list of SCSCFs.  0 means this I-CSCF has no preferred
+      SCSCF.  1 means it has a preferred S-CSCF.</para>
+
+      <para><emphasis> Default value is 0.</emphasis></para>
+
+      <example>
+        <title><varname>use_preferred_scscf_uri</varname> parameter usage</title>
+
+        <programlisting format="linespecific">
+...
+modparam("ims_icscf", "use_preferred_scscf_uri", 1)
+...
+    </programlisting>
+      </example>
+    </section>
+    
+    <section>
+      <title><varname>preferred_scscf_uri</varname> (string)</title>
+
+      <para>If use_preferred_scscf_uri is set then this is the URI of the preferred
+	  SCSCF.</para>
+
+      <para><emphasis> Default value is "".</emphasis></para>
+
+      <example>
+        <title><varname>preferred_scscf_uri</varname> parameter usage</title>
+
+        <programlisting format="linespecific">
+...
+modparam("ims_icscf", "preferred_scscf_uri", "sip:scscf.ims.smilecoms.com:6060")
+...
+    </programlisting>
+      </example>
+    </section>
+    
+    
   </section>
 
   <section>
@@ -299,7 +340,7 @@ route[REG_UAR_REPLY]
       retrieve return value</para>
 
       <example>
-        <title>I_perform_location_information_request()</title>
+        <title>I_perform_location_information_request</title>
 
         <programlisting format="linespecific">
 ...
diff --git a/modules/ims_icscf/mod.c b/modules/ims_icscf/mod.c
index ce67903..04ccd19 100644
--- a/modules/ims_icscf/mod.c
+++ b/modules/ims_icscf/mod.c
@@ -76,6 +76,9 @@ int scscf_entry_expiry = 300;
 char* cxdx_dest_realm_s = "ims.smilecoms.com";
 str cxdx_dest_realm;
 
+str preferred_scscf_uri = str_init("sip:scscf.ims.smilecoms.com:4060");
+int use_preferred_scscf_uri = 0;
+
 //Only used if we want to force the Rx peer
 //Usually this is configured at a stack level and the first request uses realm routing
 char* cxdx_forced_peer_s = "";
@@ -123,6 +126,8 @@ static param_export_t params[] = {
     {"db_capabilities_table", 	PARAM_STRING, &ims_icscf_db_capabilities_table},
     {"cxdx_forced_peer", PARAM_STR, &cxdx_forced_peer},
     {"cxdx_dest_realm", PARAM_STR, &cxdx_dest_realm},
+    {"preferred_scscf_uri",	PARAM_STR, &preferred_scscf_uri},
+    {"use_preferred_scscf_uri", INT_PARAM, &use_preferred_scscf_uri},
     {0, 0, 0}
 };
 
diff --git a/modules/ims_icscf/registration.c b/modules/ims_icscf/registration.c
index 8940dc8..b9d1df5 100644
--- a/modules/ims_icscf/registration.c
+++ b/modules/ims_icscf/registration.c
@@ -127,22 +127,20 @@ int I_perform_user_authorization_request(struct sip_msg* msg, char* route, char*
     b = cscf_parse_contacts(msg);
 
     if (!b || (!b->contacts && !b->star)) {
-        LM_DBG("DBG:I_UAR: No contacts found\n");
-        return CSCF_RETURN_ERROR;
-    }
-
-    for (c = b->contacts; c; c = c->next) {
-
-        sos_reg = cscf_get_sos_uri_param(c->uri);
-        if (sos_reg == -1) {
-            //error case
-            LM_ERR("ERR:I_UAR: MSG_400_MALFORMED_CONTACT, responding with 400\n");
-            cscf_reply_transactional(msg, 400, MSG_400_MALFORMED_CONTACT);
-            return CSCF_RETURN_BREAK;
-        } else if (sos_reg == -2) {
-            LM_ERR("ERR:I_UAR: MSG_500_SERVER_ERROR_OUT_OF_MEMORY, responding with 500\n");
-            cscf_reply_transactional(msg, 500, MSG_500_SERVER_ERROR_OUT_OF_MEMORY);
-            return CSCF_RETURN_BREAK;
+        LM_DBG("DBG:I_UAR: No contacts found - just fetching bindings\n");
+    } else {
+        for (c = b->contacts; c; c = c->next) {
+            sos_reg = cscf_get_sos_uri_param(c->uri);
+            if (sos_reg == -1) {
+                //error case
+                LM_ERR("ERR:I_UAR: MSG_400_MALFORMED_CONTACT, responding with 400\n");
+                cscf_reply_transactional(msg, 400, MSG_400_MALFORMED_CONTACT);
+                return CSCF_RETURN_BREAK;
+            } else if (sos_reg == -2) {
+                LM_ERR("ERR:I_UAR: MSG_500_SERVER_ERROR_OUT_OF_MEMORY, responding with 500\n");
+                cscf_reply_transactional(msg, 500, MSG_500_SERVER_ERROR_OUT_OF_MEMORY);
+                return CSCF_RETURN_BREAK;
+            }
         }
     }
 
diff --git a/modules/ims_icscf/scscf_list.c b/modules/ims_icscf/scscf_list.c
index f5655c5..1d21ba3 100644
--- a/modules/ims_icscf/scscf_list.c
+++ b/modules/ims_icscf/scscf_list.c
@@ -56,6 +56,9 @@ extern int scscf_entry_expiry; //time for scscf entries to remain the scscf_list
 
 extern struct tm_binds tmb; //Structure with pointers to tm funcs
 
+extern int use_preferred_scscf_uri;
+extern str preferred_scscf_uri;
+
 int i_hash_size;
 i_hash_slot *i_hash_table = 0;
 
@@ -427,19 +430,51 @@ out_of_memory:
 str take_scscf_entry(str call_id) {
     str scscf = {0, 0};
     scscf_list *l = 0;
+    scscf_entry *scscf_entry = 0;
     unsigned int hash = get_call_id_hash(call_id, i_hash_size);
 
+    LM_DBG("Getting scscf entry from list\n");
+    
     i_lock(hash);
     l = i_hash_table[hash].head;
-    while (l) {
-        if (l->call_id.len == call_id.len &&
-                strncasecmp(l->call_id.s, call_id.s, call_id.len) == 0) {
-            if (l->list) {
-                scscf = l->list->scscf_name;
-            }
-            break;
-        }
-        l = l->next;
+    
+    //if use_preferred_scscf_uri then check the table for the preferred scscf set
+    if(use_preferred_scscf_uri) {
+	LM_DBG("use_preferred_scscf_uri is set so will check for preferred_scscf_uri first [%.*s]\n", preferred_scscf_uri.len, preferred_scscf_uri.s);
+	while (l) {
+	    if (l->call_id.len == call_id.len &&
+		    strncasecmp(l->call_id.s, call_id.s, call_id.len) == 0) {
+		scscf_entry = l->list;
+		while (scscf_entry) {
+		    LM_DBG("scscf_entry [%.*s]\n", scscf_entry->scscf_name.len, scscf_entry->scscf_name.s);
+		    if (strncasecmp(scscf_entry->scscf_name.s, preferred_scscf_uri.s, preferred_scscf_uri.len) == 0) {
+			LM_DBG("scscf_entry matches\n");
+			scscf = scscf_entry->scscf_name;
+			break;
+		    }
+		    scscf_entry = scscf_entry->next;
+		}
+		
+		break;
+	    }
+	    l = l->next;
+	}
+    }
+    
+    // if scscf has not yet been set then find the first scscf that matches
+    if(scscf.len <= 0 ) {
+	LM_DBG("scscf has not been set so we just look for first match\n");
+	while (l) {
+	    if (l->call_id.len == call_id.len &&
+		    strncasecmp(l->call_id.s, call_id.s, call_id.len) == 0) {
+		if (l->list) {
+		    LM_DBG("scscf_entry [%.*s]\n", l->list->scscf_name.len, l->list->scscf_name.s);
+		    scscf = l->list->scscf_name;
+		}
+		break;
+	    }
+	    l = l->next;
+	}
     }
     i_unlock(hash);
     return scscf;
diff --git a/modules/ims_isc/Makefile b/modules/ims_isc/Makefile
index 5690e5e..1fe2ee4 100644
--- a/modules/ims_isc/Makefile
+++ b/modules/ims_isc/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # ims_isc make file
 #
diff --git a/modules/ims_isc/checker.c b/modules/ims_isc/checker.c
index 10e27ff..bbf1b1b 100644
--- a/modules/ims_isc/checker.c
+++ b/modules/ims_isc/checker.c
@@ -397,7 +397,7 @@ isc_match* isc_checker_find(str uri, char direction, int skip,
 	//need to get the urecord
 	if ((ret = isc_ulb.get_impurecord(d, &uri, &p)) != 0) {
 		isc_ulb.unlock_udomain(d, &uri);
-		LM_ERR("Failure getting record");
+		LM_ERR("Failure getting IMPU record for [%.*s] - ISC checker find METHOD: [%.*s]\n", uri.len, uri.s, msg->first_line.u.request.method.len, msg->first_line.u.request.method.s);
 		return 0;
 	};
 
diff --git a/modules/ims_isc/mark.c b/modules/ims_isc/mark.c
index 99ef7de..167f3af 100644
--- a/modules/ims_isc/mark.c
+++ b/modules/ims_isc/mark.c
@@ -313,7 +313,7 @@ inline int isc_mark_write_route(struct sip_msg *msg, str *as, str *iscmark) {
  */
 int isc_mark_write_psu(struct sip_msg *msg, isc_mark *mark) {
     struct lump *l = msg->add_rm;
-    int hlen;
+    size_t hlen;
     char * hstr = NULL;
     const str *regstate, *sescase;
 
diff --git a/modules/ims_isc/mod.c b/modules/ims_isc/mod.c
index 888af13..a21e8ed 100644
--- a/modules/ims_isc/mod.c
+++ b/modules/ims_isc/mod.c
@@ -401,6 +401,13 @@ done:
     return ret;
 }
 
+void clean_impu_str(str* impu_s) {
+    char *p;
+    
+    if ((p = memchr(impu_s->s, ';', impu_s->len))) {
+	impu_s->len = p - impu_s->s;
+    }
+}
 /**
  * Checks if there is a match on REGISTER.
  * Inserts route headers and set the dst_uri
@@ -436,7 +443,10 @@ int isc_match_filter_reg(struct sip_msg *msg, char *str1, udomain_t* d) {
             else
                 k = 1;
 
-            LM_DBG("Orig User <%.*s> [%d]\n", s.len, s.s, k);
+	    LM_DBG("Orig User before clean: <%.*s> [%d]\n", s.len, s.s, k);
+	    clean_impu_str(&s);
+            LM_DBG("Orig User after clean: <%.*s> [%d]\n", s.len, s.s, k);
+	    
             m = isc_checker_find(s, old_mark.direction, old_mark.skip, msg, k, d);
             while (m) {
                 LM_DBG("REGISTER match found in filter criteria\n");
diff --git a/modules/ims_isc/third_party_reg.c b/modules/ims_isc/third_party_reg.c
index 4b30639..5de746d 100644
--- a/modules/ims_isc/third_party_reg.c
+++ b/modules/ims_isc/third_party_reg.c
@@ -45,6 +45,65 @@
 
 #include "third_party_reg.h"
 
+/*! \brief
+ * Combines all Path HF bodies into one string.
+ */
+int build_path_vector(struct sip_msg *_m, str *path, str *received) {
+    static char buf[MAX_PATH_SIZE];
+    char *p;
+    struct hdr_field *hdr;
+    struct sip_uri puri;
+
+    rr_t *route = 0;
+
+    path->len = 0;
+    path->s = 0;
+    received->s = 0;
+    received->len = 0;
+
+    if (parse_headers(_m, HDR_EOH_F, 0) < 0) {
+	LM_ERR("failed to parse the message\n");
+	goto error;
+    }
+
+    for (hdr = _m->path, p = buf; hdr; hdr = next_sibling_hdr(hdr)) {
+	/* check for max. Path length */
+	if (p - buf + hdr->body.len + 1 >= MAX_PATH_SIZE) {
+	    LM_ERR("Overall Path body exceeds max. length of %d\n",
+		    MAX_PATH_SIZE);
+	    goto error;
+	}
+	if (p != buf)
+	    *(p++) = ',';
+	memcpy(p, hdr->body.s, hdr->body.len);
+	p += hdr->body.len;
+    }
+
+    if (p != buf) {
+	/* check if next hop is a loose router */
+	if (parse_rr_body(buf, p - buf, &route) < 0) {
+	    LM_ERR("failed to parse Path body, no head found\n");
+	    goto error;
+	}
+	if (parse_uri(route->nameaddr.uri.s, route->nameaddr.uri.len, &puri) < 0) {
+	    LM_ERR("failed to parse the first Path URI\n");
+	    goto error;
+	}
+	if (!puri.lr.s) {
+	    LM_ERR("first Path URI is not a loose-router, not supported\n");
+	    goto error;
+	}
+	free_rr(&route);
+    }
+
+    path->s = buf;
+    path->len = p - buf;
+    return 0;
+error:
+    if (route) free_rr(&route);
+    return -1;
+}
+
 /**
  * Handle third party registration
  * @param msg - the SIP REGISTER message
@@ -53,81 +112,98 @@
  * @returns #ISC_RETURN_TRUE if allowed, #ISC_RETURN_FALSE if not
  */
 int isc_third_party_reg(struct sip_msg *msg, isc_match *m, isc_mark *mark) {
-	r_third_party_registration r;
-	int expires = 0;
-	str req_uri = { 0, 0 };
-	str to = { 0, 0 };
-	str pvni = { 0, 0 };
-	str pani = { 0, 0 };
-	str cv = { 0, 0 };
-
-	struct hdr_field *hdr;
-
-	LM_DBG("isc_third_party_reg: Enter\n");
-
-	/* Set Request Uri to IFC matching server name */
-	req_uri.len = m->server_name.len;
-	req_uri.s = m->server_name.s;
-
-	/* Get To header*/
-	to = cscf_get_public_identity(msg);
-
-	/*TODO - check if the min/max expires is in the acceptable limits
-	 * this does not work correctly if the user has multiple contacts
-	 * and register/deregisters them individually!!!
-	 */
-	expires = cscf_get_max_expires(msg, 0);
-
-	/* Get P-Visited-Network-Id header */
-	pvni = cscf_get_visited_network_id(msg, &hdr);
-	/* Get P-Access-Network-Info header */
-	pani = cscf_get_access_network_info(msg, &hdr);
-
-	/* Get P-Charging-Vector header */
-	/* Just forward the charging header received from P-CSCF */
-	/* Todo: implement also according to TS 24.229, chap 5.4.1.7 */
-	cv = cscf_get_charging_vector(msg, &hdr);
-
-	if (req_uri.s) {
-
-		memset(&r, 0, sizeof(r_third_party_registration));
-
-		r.req_uri = req_uri;
-		r.to = to;
-		r.from = isc_my_uri_sip;
-		r.pvni = pvni;
-		r.pani = pani;
-		r.cv = cv;
-		r.service_info = m->service_info;
-
-		if (expires <= 0)
-			r_send_third_party_reg(&r, 0);
-		else
-			r_send_third_party_reg(&r, expires + isc_expires_grace);
-		return ISC_RETURN_TRUE;
-	} else {
-		return ISC_RETURN_FALSE;
-	}
+    r_third_party_registration r;
+    str path, path_received;
+    int expires = 0;
+    str req_uri = {0, 0};
+    str to = {0, 0};
+    str pvni = {0, 0};
+    str pani = {0, 0};
+    str cv = {0, 0};
+
+    struct hdr_field *hdr;
+
+    LM_DBG("isc_third_party_reg: Enter\n");
+
+    /* Set Request Uri to IFC matching server name */
+    req_uri.len = m->server_name.len;
+    req_uri.s = m->server_name.s;
+
+    /* Get To header*/
+    to = cscf_get_public_identity(msg);
+
+    /*TODO - check if the min/max expires is in the acceptable limits
+     * this does not work correctly if the user has multiple contacts
+     * and register/deregisters them individually!!!
+     */
+    expires = cscf_get_max_expires(msg, 0);
+
+    /* Get P-Visited-Network-Id header */
+    pvni = cscf_get_visited_network_id(msg, &hdr);
+    /* Get P-Access-Network-Info header */
+    pani = cscf_get_access_network_info(msg, &hdr);
+
+    if (build_path_vector(msg, &path, &path_received) < 0) {
+	LM_ERR("Failed to parse PATH header for third-party reg\n");
+	return ISC_RETURN_FALSE;
+    }
+    LM_DBG("PATH header in REGISTER is [%.*s]\n", path.len, path.s);
+
+    /* Get P-Charging-Vector header */
+    /* Just forward the charging header received from P-CSCF */
+    /* Todo: implement also according to TS 24.229, chap 5.4.1.7 */
+    cv = cscf_get_charging_vector(msg, &hdr);
+
+    if (req_uri.s) {
+
+	memset(&r, 0, sizeof (r_third_party_registration));
+
+	r.req_uri = req_uri;
+	r.to = to;
+	r.from = isc_my_uri_sip;
+	r.pvni = pvni;
+	r.pani = pani;
+	r.cv = cv;
+	r.service_info = m->service_info;
+	r.path = path;
+
+	if (expires <= 0)
+	    r_send_third_party_reg(&r, 0);
+	else
+	    r_send_third_party_reg(&r, expires + isc_expires_grace);
+	return ISC_RETURN_TRUE;
+    } else {
+	return ISC_RETURN_FALSE;
+    }
 }
 
-static str method = { "REGISTER", 8 };
-static str event_hdr = { "Event: registration\r\n", 21 };
-static str max_fwds_hdr = { "Max-Forwards: 10\r\n", 18 };
-static str expires_s = { "Expires: ", 9 };
-static str expires_e = { "\r\n", 2 };
-static str contact_s = { "Contact: <", 10 };
-static str contact_e = { ">\r\n", 3 };
+static str method = {"REGISTER", 8};
+static str event_hdr = {"Event: registration\r\n", 21};
+static str max_fwds_hdr = {"Max-Forwards: 10\r\n", 18};
+static str expires_s = {"Expires: ", 9};
+static str expires_e = {"\r\n", 2};
+static str contact_s = {"Contact: <", 10};
+static str contact_e = {">\r\n", 3};
 
-static str p_visited_network_id_s = { "P-Visited-Network-ID: ", 22 };
-static str p_visited_network_id_e = { "\r\n", 2 };
+static str p_visited_network_id_s = {"P-Visited-Network-ID: ", 22};
+static str p_visited_network_id_e = {"\r\n", 2};
 
-static str p_access_network_info_s = { "P-Access-Network-Info: ", 23 };
-static str p_access_network_info_e = { "\r\n", 2 };
+static str p_access_network_info_s = {"P-Access-Network-Info: ", 23};
+static str p_access_network_info_e = {"\r\n", 2};
 
-static str p_charging_vector_s = { "P-Charging-Vector: ", 19 };
-static str p_charging_vector_e = { "\r\n", 2 };
-static str body_s = { "<ims-3gpp version=\"1\"><service-info>", 36 };
-static str body_e = { "</service-info></ims-3gpp>", 26 };
+static str p_charging_vector_s = {"P-Charging-Vector: ", 19};
+static str p_charging_vector_e = {"\r\n", 2};
+
+static str path_s = {"Path: ", 6};
+static str path_e = {"\r\n", 2};
+
+static str comma = {",", 1};
+
+static str path_mine_s = {"<", 1};
+static str path_mine_e = {";lr>", 4};
+
+static str body_s = {"<ims-3gpp version=\"1\"><service-info>", 36};
+static str body_e = {"</service-info></ims-3gpp>", 26};
 
 /**
  * Send a third party registration
@@ -137,117 +213,131 @@ static str body_e = { "</service-info></ims-3gpp>", 26 };
  */
 
 int r_send_third_party_reg(r_third_party_registration *r, int expires) {
-	str h = { 0, 0 };
-	str b = { 0, 0 };
-	uac_req_t req;
+    str h = {0, 0};
+    str b = {0, 0};
+    uac_req_t req;
 
-	LM_DBG("r_send_third_party_reg: REGISTER to <%.*s>\n",
-			r->req_uri.len, r->req_uri.s);
+    LM_DBG("r_send_third_party_reg: REGISTER to <%.*s>\n",
+	    r->req_uri.len, r->req_uri.s);
 
-	h.len = event_hdr.len + max_fwds_hdr.len;
-	h.len += expires_s.len + 12 + expires_e.len;
+    h.len = event_hdr.len + max_fwds_hdr.len;
+    h.len += expires_s.len + 12 + expires_e.len;
 
-	h.len += contact_s.len + isc_my_uri_sip.len + contact_e.len;
+    h.len += contact_s.len + isc_my_uri_sip.len + contact_e.len;
 
-	if (r->pvni.len)
-		h.len += p_visited_network_id_s.len + p_visited_network_id_e.len
-				+ r->pvni.len;
+    if (r->pvni.len)
+	h.len += p_visited_network_id_s.len + p_visited_network_id_e.len
+	    + r->pvni.len;
 
-	if (r->pani.len)
-		h.len += p_access_network_info_s.len + p_access_network_info_e.len
-				+ r->pani.len;
+    if (r->pani.len)
+	h.len += p_access_network_info_s.len + p_access_network_info_e.len
+	    + r->pani.len;
 
-	if (r->cv.len)
-		h.len += p_charging_vector_s.len + p_charging_vector_e.len + r->cv.len;
+    if (r->cv.len)
+	h.len += p_charging_vector_s.len + p_charging_vector_e.len + r->cv.len;
 
-	h.s = pkg_malloc(h.len);
-	if (!h.s) {
-		LM_ERR("r_send_third_party_reg: Error allocating %d bytes\n", h.len);
-		h.len = 0;
-		return 0;
-	}
+    if (r->path.len)
+	h.len += path_s.len + path_e.len + r->path.len + 6/*',' and ';lr' and '<' and '>'*/ + r->from.len /*adding our own address to path*/;
 
+    h.s = pkg_malloc(h.len);
+    if (!h.s) {
+	LM_ERR("r_send_third_party_reg: Error allocating %d bytes\n", h.len);
 	h.len = 0;
-	STR_APPEND(h, event_hdr);
-
-	STR_APPEND(h, max_fwds_hdr);
-
-	STR_APPEND(h, expires_s);
-	sprintf(h.s + h.len, "%d", expires);
-	h.len += strlen(h.s + h.len);
-	STR_APPEND(h, expires_e);
-
-	STR_APPEND(h, contact_s);
-	STR_APPEND(h, isc_my_uri_sip);
-	STR_APPEND(h, contact_e);
-
-	if (r->pvni.len) {
-		STR_APPEND(h, p_visited_network_id_s);
-		STR_APPEND(h, r->pvni);
-		STR_APPEND(h, p_visited_network_id_e);
-	}
-
-	if (r->pani.len) {
-		STR_APPEND(h, p_access_network_info_s);
-		STR_APPEND(h, r->pani);
-		STR_APPEND(h, p_access_network_info_e);
-	}
-
-	if (r->cv.len) {
-		STR_APPEND(h, p_charging_vector_s);
-		STR_APPEND(h, r->cv);
-		STR_APPEND(h, p_charging_vector_e);
-	}
-	LM_CRIT("SRV INFO:<%.*s>\n", r->service_info.len, r->service_info.s);
-	if (r->service_info.len) {
-		b.len = body_s.len + r->service_info.len + body_e.len;
-		b.s = pkg_malloc(b.len);
-		if (!b.s) {
-			LM_ERR("r_send_third_party_reg: Error allocating %d bytes\n", b.len);
-			b.len = 0;
-			return 0;
-		}
-
-		b.len = 0;
-		STR_APPEND(b, body_s);
-		STR_APPEND(b, r->service_info);
-		STR_APPEND(b, body_e);
-	}
-
-	set_uac_req(&req, &method, &h, &b, 0,
-			TMCB_RESPONSE_IN | TMCB_ON_FAILURE | TMCB_LOCAL_COMPLETED,
-			r_third_party_reg_response, &(r->req_uri));
-	if (isc_tmb.t_request(&req, &(r->req_uri), &(r->to), &(r->from), 0) < 0) {
-		LM_ERR("r_send_third_party_reg: Error sending in transaction\n");
-		goto error;
+	return 0;
+    }
+
+    h.len = 0;
+    STR_APPEND(h, event_hdr);
+
+    STR_APPEND(h, max_fwds_hdr);
+
+    STR_APPEND(h, expires_s);
+    sprintf(h.s + h.len, "%d", expires);
+    h.len += strlen(h.s + h.len);
+    STR_APPEND(h, expires_e);
+
+    if (r->path.len) {
+	STR_APPEND(h, path_s);
+	STR_APPEND(h, path_mine_s);
+	STR_APPEND(h, r->from);
+	STR_APPEND(h, path_mine_e);
+	STR_APPEND(h, comma);
+	STR_APPEND(h, r->path);
+	STR_APPEND(h, path_e);
+    }
+
+    STR_APPEND(h, contact_s);
+    STR_APPEND(h, isc_my_uri_sip);
+    STR_APPEND(h, contact_e);
+
+    if (r->pvni.len) {
+	STR_APPEND(h, p_visited_network_id_s);
+	STR_APPEND(h, r->pvni);
+	STR_APPEND(h, p_visited_network_id_e);
+    }
+
+    if (r->pani.len) {
+	STR_APPEND(h, p_access_network_info_s);
+	STR_APPEND(h, r->pani);
+	STR_APPEND(h, p_access_network_info_e);
+    }
+
+    if (r->cv.len) {
+	STR_APPEND(h, p_charging_vector_s);
+	STR_APPEND(h, r->cv);
+	STR_APPEND(h, p_charging_vector_e);
+    }
+    LM_DBG("SRV INFO:<%.*s>\n", r->service_info.len, r->service_info.s);
+    if (r->service_info.len) {
+	b.len = body_s.len + r->service_info.len + body_e.len;
+	b.s = pkg_malloc(b.len);
+	if (!b.s) {
+	    LM_ERR("r_send_third_party_reg: Error allocating %d bytes\n", b.len);
+	    b.len = 0;
+	    return 0;
 	}
-	if (h.s)
-		pkg_free(h.s);
-	return 1;
 
-	error: if (h.s)
-		pkg_free(h.s);
-	return 0;
+	b.len = 0;
+	STR_APPEND(b, body_s);
+	STR_APPEND(b, r->service_info);
+	STR_APPEND(b, body_e);
+    }
+
+    set_uac_req(&req, &method, &h, &b, 0,
+	    TMCB_RESPONSE_IN | TMCB_ON_FAILURE | TMCB_LOCAL_COMPLETED,
+	    r_third_party_reg_response, &(r->req_uri));
+    if (isc_tmb.t_request(&req, &(r->req_uri), &(r->to), &(r->from), 0) < 0) {
+	LM_ERR("r_send_third_party_reg: Error sending in transaction\n");
+	goto error;
+    }
+    if (h.s)
+	pkg_free(h.s);
+    return 1;
+
+error:
+    if (h.s)
+	pkg_free(h.s);
+    return 0;
 }
 
 /**
  * Response callback for third party register
  */
 void r_third_party_reg_response(struct cell *t, int type, struct tmcb_params *ps) {
+    LM_DBG("r_third_party_reg_response: code %d\n", ps->code);
+    if (!ps->rpl) {
+	LM_ERR("r_third_party_reg_response: No reply\n");
+	return;
+    }
+
+    if (ps->code >= 200 && ps->code < 300) {
+	if (ps->rpl)
+	    cscf_get_expires_hdr(ps->rpl, 0);
+	else
+	    return;
+    } else if (ps->code == 404) {
+    } else {
 	LM_DBG("r_third_party_reg_response: code %d\n", ps->code);
-	if (!ps->rpl) {
-		LM_ERR("r_third_party_reg_response: No reply\n");
-		return;
-	}
-
-	if (ps->code >= 200 && ps->code < 300) {
-		if (ps->rpl)
-			cscf_get_expires_hdr(ps->rpl, 0);
-		else
-			return;
-	} else if (ps->code == 404) {
-	} else {
-		LM_DBG("r_third_party_reg_response: code %d\n", ps->code);
-	}
+    }
 }
 
diff --git a/modules/ims_isc/third_party_reg.h b/modules/ims_isc/third_party_reg.h
index 2b687b0..a23cbce 100644
--- a/modules/ims_isc/third_party_reg.h
+++ b/modules/ims_isc/third_party_reg.h
@@ -65,13 +65,14 @@ extern struct tm_binds isc_tmb; 	/**< Structure with pointers to tm funcs 		*/
 
 /** reg event notification structure */
 typedef struct _r_third_party_reg {
-	str req_uri; 		/* AS sip uri:  	*/
+	str req_uri;                    /* AS sip uri:  	*/
 	str from; 			/* SCSCF uri            */
 	str to; 			/* Public user id       */
 	str pvni; 			/* Visited network id 	*/
 	str pani; 			/* Access Network info 	*/
 	str cv; 			/* Charging vector 	*/
-	str service_info; 	/* Service info body */
+	str service_info;               /* Service info body */
+    str path;                       /* Path header  */
 } r_third_party_registration;
 
 int isc_third_party_reg(struct sip_msg *msg, isc_match *m, isc_mark *mark);
diff --git a/modules/ims_qos/Makefile b/modules/ims_qos/Makefile
index d9a9926..5afc0ff 100644
--- a/modules/ims_qos/Makefile
+++ b/modules/ims_qos/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # ims_qos make file
 #
diff --git a/modules/ims_qos/README b/modules/ims_qos/README
index 0f8407a..8420696 100644
--- a/modules/ims_qos/README
+++ b/modules/ims_qos/README
@@ -15,9 +15,16 @@ Richard Good
    Smile Communications
    <richard.good at smilecoms.com>
 
+Carsten Bock
+
+   ng-voice GmbH
+   <carsten at ng-voice.com>
+
    Copyright © 2007 FhG FOKUS
 
    Copyright © 2012 Smile Communications
+
+   Copyright © 2015 ng-voice GmbH
      __________________________________________________________________
 
    Table of Contents
@@ -38,11 +45,16 @@ Richard Good
               3.4. cdp_event_latency (integer)
               3.5. cdp_event_threshold (integer)
               3.6. cdp_event_latency_log (integer)
+              3.7. authorize_video_flow (integer)
+              3.8. cdp_event_list_size_threshold (integer)
+              3.9. audio_default_bandwidth (integer)
+              3.10. video_default_bandwidth (integer)
 
         4. Functions
 
-              4.1. Rx_AAR_Register(domain)
-              4.2. Rx_AAR(domain)
+              4.1. Rx_AAR_Register(route_block, domain)
+              4.2. Rx_AAR(route_block, direction, subscription_id,
+                      subscription_id_type)
 
         5. Statistics
 
@@ -57,8 +69,12 @@ Richard Good
    1.4. cdp_event_latency parameter usage
    1.5. cdp_event_threshold parameter usage
    1.6. cdp_event_latency_log parameter usage
-   1.7. Rx_AAR_Register
-   1.8. Rx_AAR
+   1.7. authorize_video_flow parameter usage
+   1.8. cdp_event_list_size_threshold parameter usage
+   1.9. audio_default_bandwidth parameter usage
+   1.10. video_default_bandwidth parameter usage
+   1.11. Rx_AAR_Register
+   1.12. Rx_AAR
 
 Chapter 1. Admin Guide
 
@@ -78,11 +94,16 @@ Chapter 1. Admin Guide
         3.4. cdp_event_latency (integer)
         3.5. cdp_event_threshold (integer)
         3.6. cdp_event_latency_log (integer)
+        3.7. authorize_video_flow (integer)
+        3.8. cdp_event_list_size_threshold (integer)
+        3.9. audio_default_bandwidth (integer)
+        3.10. video_default_bandwidth (integer)
 
    4. Functions
 
-        4.1. Rx_AAR_Register(domain)
-        4.2. Rx_AAR(domain)
+        4.1. Rx_AAR_Register(route_block, domain)
+        4.2. Rx_AAR(route_block, direction, subscription_id,
+                subscription_id_type)
 
    5. Statistics
 
@@ -123,6 +144,10 @@ Chapter 1. Admin Guide
    3.4. cdp_event_latency (integer)
    3.5. cdp_event_threshold (integer)
    3.6. cdp_event_latency_log (integer)
+   3.7. authorize_video_flow (integer)
+   3.8. cdp_event_list_size_threshold (integer)
+   3.9. audio_default_bandwidth (integer)
+   3.10. video_default_bandwidth (integer)
 
 3.1. rx_dest_realm (string)
 
@@ -138,8 +163,11 @@ modparam("ims_qos", "rx_dest_realm", "ims.smilecoms.com")
 
 3.2. rx_forced_peer (string)
 
-   This is the optional name of the origin host of the Diameter server
-   (typically a PCRF). If not set then realm routing is used.
+   FQDN of the Diameter server (typically a PCRF) to communicate with. If
+   not set then realm routing is used. If you use this, the routing
+   defined in your diameter xml configuration file (CDP) will be ignored
+   and as a result you will lose the benefits of load balancing and
+   failover.
 
    Default value is ''.
 
@@ -199,12 +227,62 @@ modparam("ims_qos", "cdp_event_threshold", 500)
 modparam("ims_qos", "cdp_event_latency_log", 1)
 ...
 
+3.7. authorize_video_flow (integer)
+
+   This is a flag that specifies whether or not to authorize video flows.
+   1 means video flows will be authorized over Rx and 0 means video flows
+   will not be authorized over Rx
+
+   Default value is 1.
+
+   Example 1.7. authorize_video_flow parameter usage
+...
+modparam("ims_qos", "authorize_video_flow", 0)
+...
+
+3.8. cdp_event_list_size_threshold (integer)
+
+   This is a threshold on the size of the cdp event list. Once the queue
+   exceeds this length a warning is logged. 0 disables this feature
+
+   Default value is 0.
+
+   Example 1.8. cdp_event_list_size_threshold parameter usage
+...
+modparam("ims_qos", "cdp_event_list_size_threshold", 10)
+...
+
+3.9. audio_default_bandwidth (integer)
+
+   This parameters defines the default bandwidth for Audio, if no
+   "b=AS"-Parameter is found in the SDP.
+
+   Default value is 64 (64 kBit)
+
+   Example 1.9. audio_default_bandwidth parameter usage
+...
+modparam("ims_qos", "audio_default_bandwidth", 32)
+...
+
+3.10. video_default_bandwidth (integer)
+
+   This parameters defines the default bandwidth for Video, if no
+   "b=AS"-Parameter is found in the SDP.
+
+   Default value is 128 (128 kBit)
+
+   Example 1.10. video_default_bandwidth parameter usage
+...
+modparam("ims_qos", "video_default_bandwidth", 256)
+...
+
 4. Functions
 
-   4.1. Rx_AAR_Register(domain)
-   4.2. Rx_AAR(domain)
+   4.1. Rx_AAR_Register(route_block, domain)
+   4.2. Rx_AAR(route_block, direction, subscription_id,
+          subscription_id_type)
 
-4.1. Rx_AAR_Register(domain)
+4.1. Rx_AAR_Register(route_block, domain)
 
    Perform a AAR on Diameter RX interface to subscribe to signalling
    status. This purpose of this is tell a Diameter server (typically a
@@ -213,17 +291,29 @@ modparam("ims_qos", "cdp_event_latency_log", 1)
    see 3GGP TS 29.214.
 
    Meaning of the parameters is as follows:
+     * Route block to resume after async UAR Diameter reply.
      * domain that usrloc_pcscf uses to store user information.
 
+   Return codes:
+     * -1 - error: There was an error, so we must either ignore it (no
+       subscription) or send 403 (depends on behaviour you want)
+       0 - Success: AAR-Request sent, reply is processed asynchronously.
+       1 - Success: No need to send AAR-Request, as a subscription still
+       exists (continue as normal)
+
    This function can be used from REQUEST_ROUTE.
 
    p.s. this is executed asynchronously. See example on how to retrieve
    return value
 
-   Example 1.7. Rx_AAR_Register
+   Example 1.11. Rx_AAR_Register
 ...
-    Rx_AAR_Register("location");
-
+if(Rx_AAR_Register("REG_AAR_REPLY","location")==0){
+    exit;
+}
+...
+route[REG_AAR_REPLY]
+{
     switch ($avp(s:aar_return_code)) {
         case 1:
             xlog("L_DBG", "Diameter: AAR success on subscription to signalling\n
@@ -235,37 +325,44 @@ modparam("ims_qos", "cdp_event_latency_log", 1)
             t_reply("403", "Can't register to QoS for signalling");
             exit;
     }
-
 ...
 
-4.2. Rx_AAR(domain)
+4.2. Rx_AAR(route_block, direction, subscription_id, subscription_id_type)
 
    Perform a AAR on Diameter RX interface to request resource
    authorisation from a Diameter server (typically a PCRF). For more
    details see 3GGP TS 29.214.
 
    Meaning of the parameters is as follows:
-     * domain that usrloc_pcscf uses to store user information.
+     * Route block to resume after async UAR Diameter reply.
+     * direction of this message - orig, term, etc.
+     * subscription_id to hard code subscription ID for AAR. Used for some
+       broken PCRFs. Leave blank to use default
+     * subscription_id_type to hard code subscription ID type for AAR.
+       Only applicable if subscription_id is set. Set to -1 to use
+       default. This is as per RFC 4006: END_USER_E164 0, END_USER_IMSI 1,
+       END_USER_SIP_URI 2, END_USER_NAI 3, END_USER_PRIVATE 4
 
    This function can be used from REQUEST_ROUTE or ONREPLY_ROUTE.
 
    p.s. this is executed asynchronously. See example on how to retrieve
    return value
 
-   Example 1.8. Rx_AAR
+   Example 1.12. Rx_AAR
 ...
-    Rx_AAR("location");
-
-    switch ($avp(s:aar_return_code)) {
-        case 1:
-            xlog("L_DBG", "Diameter: AAR success\n");
-            break;
-        default:
-            xlog("L_ERR", "Diameter: AAR failed\n");
-            t_reply("403", "QoS not authorized");
-            exit;
+if(Rx_AAR("ORIG_SESSION_AAR_REPLY","orig","",-1)==0){
+    exit;
+}
+...
+route[ORIGN_SESSION_AAR_REPLY]
+{
+    if ($avp(s:aar_return_code) != 1) {
+        xlog("L_ERR", "IMS: AAR failed Orig\n");
+        dlg_terminate("all", "Sorry no QoS available");
+    } else {
+        xlog("L_DBG", "Diameter: Orig AAR success on media authorization\n");
     }
-
+}
 ...
 
 5. Statistics
diff --git a/modules/ims_qos/cdpeventprocessor.c b/modules/ims_qos/cdpeventprocessor.c
index 409009e..2b38050 100644
--- a/modules/ims_qos/cdpeventprocessor.c
+++ b/modules/ims_qos/cdpeventprocessor.c
@@ -51,6 +51,7 @@
 #include "mod.h"
 #include "cdpeventprocessor.h"
 #include "rx_str.h"
+#include "ims_qos_stats.h"
 
 cdp_cb_event_list_t *cdp_event_list = 0;
 extern usrloc_api_t ul;
@@ -58,6 +59,9 @@ extern struct dlg_binds dlgb;
 extern int cdp_event_latency;
 extern int cdp_event_threshold;
 extern int cdp_event_latency_loglevel;
+extern int cdp_event_list_size_threshold;
+
+extern struct ims_qos_counters_h ims_qos_cnts_h;
 
 int init_cdp_cb_event_list() {
     cdp_event_list = shm_malloc(sizeof (cdp_cb_event_list_t));
@@ -72,6 +76,7 @@ int init_cdp_cb_event_list() {
         return 0;
     }
     cdp_event_list->lock = lock_init(cdp_event_list->lock);
+    cdp_event_list->size = 0;
 
     sem_new(cdp_event_list->empty, 0); //pre-locked - as we assume list is empty at start
 
@@ -130,6 +135,10 @@ void push_cdp_cb_event(cdp_cb_event_t* event) {
         cdp_event_list->tail->next = event;
         cdp_event_list->tail = event;
     }
+    cdp_event_list->size++;
+    if(cdp_event_list_size_threshold > 0 && cdp_event_list->size > cdp_event_list_size_threshold) {
+	    LM_WARN("cdp_event_list is size [%d] and has exceed cdp_event_list_size_threshold of [%d]", cdp_event_list->size, cdp_event_list_size_threshold);
+    }
     sem_release(cdp_event_list->empty);
     lock_release(cdp_event_list->lock);
 }
@@ -153,6 +162,7 @@ cdp_cb_event_t* pop_cdp_cb_event() {
         cdp_event_list->tail = 0;
     }
     ev->next = 0; //make sure whoever gets this cant access our list
+    cdp_event_list->size--;
     lock_release(cdp_event_list->lock);
 
     return ev;
@@ -230,26 +240,30 @@ void cdp_cb_event_process() {
                     LM_DBG("This is a subscription to signalling bearer session");
                     //instead of removing the contact from usrloc_pcscf we just change the state of the contact to TERMINATE_PENDING_NOTIFY
                     //pcscf_registrar sees this, sends a SIP PUBLISH and on SIP NOTIFY the contact is deleted
-
-                    if (ul.register_udomain(p_session_data->domain.s, &domain)
-                            < 0) {
-                        LM_DBG("Unable to register usrloc domain....aborting\n");
-                        return;
-                    }
-                    ul.lock_udomain(domain, &p_session_data->registration_aor);
-                    if (ul.get_pcontact(domain, &p_session_data->registration_aor,
-                            &pcontact) != 0) {
-                        LM_DBG("no contact found for terminated Rx reg session..... ignoring\n");
-                    } else {
-                        LM_DBG("Updating contact [%.*s] after Rx reg session terminated, setting state to PCONTACT_DEREG_PENDING_PUBLISH\n", pcontact->aor.len, pcontact->aor.s);
-                        ci.reg_state = PCONTACT_DEREG_PENDING_PUBLISH;
-                        ci.num_service_routes = 0;
-                        ul.update_pcontact(domain, &ci, pcontact);
-                    }
-                    ul.unlock_udomain(domain, &p_session_data->registration_aor);
+		    //note we only send SIP PUBLISH if the session has been successfully opened
+		    
+		    if(p_session_data->session_has_been_opened) {
+			if (ul.register_udomain(p_session_data->domain.s, &domain)
+				< 0) {
+			    LM_DBG("Unable to register usrloc domain....aborting\n");
+			    return;
+			}
+			ul.lock_udomain(domain, &p_session_data->registration_aor, &p_session_data->ip, p_session_data->recv_port);
+			if (ul.get_pcontact(domain, &p_session_data->registration_aor, &p_session_data->ip, p_session_data->recv_port, &pcontact) != 0) {
+			    LM_DBG("no contact found for terminated Rx reg session..... ignoring\n");
+			} else {
+			    LM_DBG("Updating contact [%.*s] after Rx reg session terminated, setting state to PCONTACT_DEREG_PENDING_PUBLISH\n", pcontact->aor.len, pcontact->aor.s);
+			    ci.reg_state = PCONTACT_DEREG_PENDING_PUBLISH;
+			    ci.num_service_routes = 0;
+			    ul.update_pcontact(domain, &ci, pcontact);
+			}
+			ul.unlock_udomain(domain, &p_session_data->registration_aor, &p_session_data->ip, p_session_data->recv_port);
+			counter_add(ims_qos_cnts_h.active_registration_rx_sessions, -1);
+		    }
                 } else {
                     LM_DBG("This is a media bearer session session");
-                    
+		    
+		    counter_add(ims_qos_cnts_h.active_media_rx_sessions, -1);
                     //we only terminate the dialog if this was triggered from the transport plane or timeout - i.e. if must_terminate_dialog is set
                     //if this was triggered from the signalling plane (i.e. someone hanging up) then we don'y need to terminate the dialog
                     if (p_session_data->must_terminate_dialog) {
diff --git a/modules/ims_qos/cdpeventprocessor.h b/modules/ims_qos/cdpeventprocessor.h
index ecd78bb..f2f0884 100644
--- a/modules/ims_qos/cdpeventprocessor.h
+++ b/modules/ims_qos/cdpeventprocessor.h
@@ -63,6 +63,7 @@ typedef struct {
 	cdp_cb_event_t *head;
 	cdp_cb_event_t *tail;
 	gen_sem_t *empty;
+	int size;
 } cdp_cb_event_list_t;
 
 int init_cdp_cb_event_list();
diff --git a/modules/ims_qos/doc/ims_qos.xml b/modules/ims_qos/doc/ims_qos.xml
index 2395e52..1f0eb56 100644
--- a/modules/ims_qos/doc/ims_qos.xml
+++ b/modules/ims_qos/doc/ims_qos.xml
@@ -44,6 +44,17 @@
 
         <email>richard.good at smilecoms.com</email>
       </author>
+
+      <author>
+        <firstname>Carsten</firstname>
+
+        <surname>Bock</surname>
+        <affiliation>
+          <orgname>ng-voice GmbH</orgname>
+        </affiliation>
+
+        <email>carsten at ng-voice.com</email>
+      </author>
     </authorgroup>
 
     <copyright>
@@ -56,6 +67,10 @@
 
       <holder>Smile Communications</holder>
     </copyright>
+    <copyright>
+      <year>2015</year>
+      <holder>ng-voice GmbH</holder>
+    </copyright>
   </bookinfo>
 
   <toc/>
diff --git a/modules/ims_qos/doc/ims_qos_admin.xml b/modules/ims_qos/doc/ims_qos_admin.xml
index 726e441..1281d1f 100644
--- a/modules/ims_qos/doc/ims_qos_admin.xml
+++ b/modules/ims_qos/doc/ims_qos_admin.xml
@@ -201,6 +201,63 @@ modparam("ims_qos", "authorize_video_flow", 0)
         </programlisting>
       </example>
     </section>
+    <section>
+      <title><varname>cdp_event_list_size_threshold</varname> (integer)</title>
+
+      <para>This is a threshold on the size of the cdp event list.  Once the
+	queue exceeds this length a warning is logged.  0 disables this feature</para>
+
+      <para><emphasis> Default value is 0. </emphasis></para>
+
+      <example>
+        <title><varname>cdp_event_list_size_threshold</varname> parameter
+        usage</title>
+
+        <programlisting format="linespecific">
+...
+modparam("ims_qos", "cdp_event_list_size_threshold", 10)
+...
+        </programlisting>
+      </example>
+    </section>
+    <section>
+      <title><varname>audio_default_bandwidth</varname> (integer)</title>
+
+      <para>This parameters defines the default bandwidth for Audio,
+            if no "b=AS"-Parameter is found in the SDP.</para>
+
+      <para><emphasis> Default value is 64 (64 kBit)</emphasis></para>
+
+      <example>
+        <title><varname>audio_default_bandwidth</varname> parameter
+        usage</title>
+
+        <programlisting format="linespecific">
+...
+modparam("ims_qos", "audio_default_bandwidth", 32)
+...
+        </programlisting>
+      </example>
+    </section>
+    <section>
+      <title><varname>video_default_bandwidth</varname> (integer)</title>
+
+      <para>This parameters defines the default bandwidth for Video,
+            if no "b=AS"-Parameter is found in the SDP.</para>
+
+      <para><emphasis> Default value is 128 (128 kBit)</emphasis></para>
+
+      <example>
+        <title><varname>video_default_bandwidth</varname> parameter
+        usage</title>
+
+        <programlisting format="linespecific">
+...
+modparam("ims_qos", "video_default_bandwidth", 256)
+...
+        </programlisting>
+      </example>
+    </section>
   </section>
 
   <section>
@@ -229,6 +286,22 @@ modparam("ims_qos", "authorize_video_flow", 0)
         </listitem>
       </itemizedlist>
 
+	<para>Return codes:</para>
+		<itemizedlist>
+		<listitem>
+			<para>
+			<emphasis>-1</emphasis> - error: There was an error, so we must either ignore it (no subscription) or send 403 (depends on behaviour you want)
+			</para>
+			<para>
+			<emphasis>0</emphasis> - Success: AAR-Request sent, reply is processed asynchronously.
+			</para>
+			<para>
+			<emphasis>1</emphasis> - Success: No need to send AAR-Request, as a subscription still exists (continue as normal)
+			</para>
+		</listitem>
+		</itemizedlist>
+
+
       <para>This function can be used from REQUEST_ROUTE.</para>
 
       <para>p.s. this is executed asynchronously. See example on how to
@@ -261,7 +334,7 @@ route[REG_AAR_REPLY]
 
     <section>
       <title><function moreinfo="none">Rx_AAR(route_block,
-      direction)</function></title>
+      direction, subscription_id, subscription_id_type)</function></title>
 
       <para>Perform a AAR on Diameter RX interface to request resource
       authorisation from a Diameter server (typically a PCRF). For more
@@ -271,14 +344,27 @@ route[REG_AAR_REPLY]
 
       <itemizedlist>
         <listitem>
-          <para>Route block to resume after async UAR Diameter reply.</para>
+          <para><emphasis>Route block</emphasis> to resume after async UAR Diameter reply.</para>
         </listitem>
 
         <listitem>
-          <para><emphasis>direction</emphasis>the direction of this message -
+          <para><emphasis>direction</emphasis> of this message -
           orig, term, etc.</para>
         </listitem>
-      </itemizedlist>
+	
+	<listitem>
+          <para><emphasis>subscription_id</emphasis> to hard code subscription ID for AAR.
+	  Used for some broken PCRFs.  Leave blank to use default</para>
+        </listitem>
+	
+	<listitem>
+          <para><emphasis>subscription_id_type</emphasis> to hard code subscription ID type
+	  for AAR. Only applicable if subscription_id is set. Set to -1 to use default.
+	  This is as per RFC 4006: 
+	  END_USER_E164 0, END_USER_IMSI 1, END_USER_SIP_URI 2, END_USER_NAI 3,
+	  END_USER_PRIVATE 4</para>
+	</listitem>
+	</itemizedlist>
 
       <para>This function can be used from REQUEST_ROUTE or
       ONREPLY_ROUTE.</para>
@@ -291,7 +377,7 @@ route[REG_AAR_REPLY]
 
         <programlisting format="linespecific">
 ...
-if(Rx_AAR("ORIG_SESSION_AAR_REPLY","orig")==0){
+if(Rx_AAR("ORIG_SESSION_AAR_REPLY","orig","",-1)==0){
     exit;
 }
 ...
diff --git a/modules/ims_qos/ims_qos_stats.c b/modules/ims_qos/ims_qos_stats.c
new file mode 100644
index 0000000..280603d
--- /dev/null
+++ b/modules/ims_qos/ims_qos_stats.c
@@ -0,0 +1,118 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2012 Smile Communications, jason.penton at smilecoms.com
+ * Copyright (C) 2012 Smile Communications, richard.good at smilecoms.com
+ * 
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Fokus. 
+ * Copyright (C) 2004-2006 FhG Fokus
+ * Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ *
+ *
+ *
+ * History:
+ * --------
+ *  2011-02-02  initial version (jason.penton)
+ */
+
+
+#include "ims_qos_stats.h"
+
+struct ims_qos_counters_h ims_qos_cnts_h;
+enum sctp_info_req { IMS_QOS_REGISTRATION_AAR_AVG_RSP, IMS_QOS_MEDIA_AAR_AVG_RSP };
+
+static counter_val_t ims_qos_internal_stats(counter_handle_t h, void* what);
+
+counter_def_t ims_qos_cnt_defs[] = {
+    {&ims_qos_cnts_h.active_registration_rx_sessions,	    "active_registration_rx_sessions",		0, 0, 0,	    "number of currently active registration Rx sessions"},
+    {&ims_qos_cnts_h.registration_aar_avg_response_time,    "registration_aar_avg_response_time",	0, ims_qos_internal_stats, (void*) (long) IMS_QOS_REGISTRATION_AAR_AVG_RSP,	"avg response time for registration AARs"},
+    {&ims_qos_cnts_h.registration_aar_timeouts,		    "registration_aar_timeouts",		0, 0, 0,	    "total number of registration AAR timeouts"},
+    {&ims_qos_cnts_h.failed_registration_aars,		    "failed_registration_aars",			0, 0, 0,	    "total number of failed registration AARs"},
+    {&ims_qos_cnts_h.registration_aars,			    "registration_aars",			0, 0, 0,	    "total number of registration AARs"},
+    {&ims_qos_cnts_h.asrs,				    "asrs",					0, 0, 0,	    "total number of registration ASRs"},
+    {&ims_qos_cnts_h.successful_registration_aars,	    "successful_registration_aars",		0, 0, 0,	    "total number of successful registration AARs"},
+    {&ims_qos_cnts_h.registration_aar_response_time,	    "registration_aar_response_time",		0, 0, 0,	    "total number of seconds waiting for registration AAR responses"},
+    {&ims_qos_cnts_h.registration_aar_replies_received,	    "registration_aar_replies_received",	0, 0, 0,            "total number of registration AAR replies received"},
+
+    {&ims_qos_cnts_h.active_media_rx_sessions,		    "active_media_rx_sessions",		0, 0, 0,		    "number of currently active media Rx sessions"},
+    {&ims_qos_cnts_h.media_aar_avg_response_time,	    "media_aar_avg_response_time",	0, ims_qos_internal_stats, (void*) (long) IMS_QOS_MEDIA_AAR_AVG_RSP,	"avg response time for media AARs"},
+    {&ims_qos_cnts_h.media_aar_timeouts,		    "media_aar_timeouts",		0, 0, 0,		    "total number of media AAR timeouts"},
+    {&ims_qos_cnts_h.failed_media_aars,			    "failed_media_aars",		0, 0, 0,		    "total number of failed media AARs"},
+    {&ims_qos_cnts_h.media_aars,			    "media_aars",			0, 0, 0,		    "total number of media AARs"},
+    {&ims_qos_cnts_h.successful_media_aars,		    "successful_media_aars",		0, 0, 0,		    "total number of successful media AARs"},
+    {&ims_qos_cnts_h.media_aar_response_time,		    "media_aar_response_time",		0, 0, 0,		    "total number of seconds waiting for media AAR responses"},
+    {&ims_qos_cnts_h.media_aar_replies_received,	    "media_aar_replies_received",	0, 0, 0,                    "total number of media AAR replies received"},
+    {0, 0, 0, 0, 0, 0}
+};
+
+
+int ims_qos_init_counters() {
+    if (counter_register_array("ims_qos", ims_qos_cnt_defs) < 0)
+	goto error;
+    return 0;
+error:
+    return -1;
+}
+
+void ims_qos_destroy_counters() {
+    
+}
+
+/** helper function for some stats (which are kept internally).
+ */
+static counter_val_t ims_qos_internal_stats(counter_handle_t h, void* what) {
+    enum sctp_info_req w;
+
+    w = (int) (long) what;
+    switch (w) {
+	case IMS_QOS_REGISTRATION_AAR_AVG_RSP:
+	    if (counter_get_val(ims_qos_cnts_h.registration_aars) == 0) 
+		return 0;
+	    else
+		return counter_get_val(ims_qos_cnts_h.registration_aar_response_time)/counter_get_val(ims_qos_cnts_h.registration_aars);
+	    break;
+	case IMS_QOS_MEDIA_AAR_AVG_RSP:
+	    if (counter_get_val(ims_qos_cnts_h.media_aars) == 0) 
+		return 0;
+	    else
+		return counter_get_val(ims_qos_cnts_h.media_aar_response_time)/counter_get_val(ims_qos_cnts_h.media_aars);
+	    break;
+	default:
+	    return 0;
+    };
+    return 0;
+}
diff --git a/modules/ims_qos/ims_qos_stats.h b/modules/ims_qos/ims_qos_stats.h
new file mode 100644
index 0000000..20d3a8c
--- /dev/null
+++ b/modules/ims_qos/ims_qos_stats.h
@@ -0,0 +1,39 @@
+/* 
+ * File:   ims_qos_stats.h
+ * Author: jaybeepee
+ *
+ * Created on 24 February 2015, 11:15 AM
+ */
+
+#ifndef IMS_QOS_STATS_H
+#define	IMS_QOS_STATS_H
+
+#include "../../counters.h"
+
+struct ims_qos_counters_h {
+    counter_handle_t registration_aar_avg_response_time;
+    counter_handle_t registration_aar_response_time;
+    counter_handle_t registration_aar_timeouts;
+    counter_handle_t failed_registration_aars;
+    counter_handle_t registration_aars;
+    counter_handle_t asrs;
+    counter_handle_t successful_registration_aars;
+    counter_handle_t active_registration_rx_sessions;
+    counter_handle_t media_aar_avg_response_time;
+    counter_handle_t media_aar_response_time;
+    counter_handle_t media_aar_timeouts;
+    counter_handle_t failed_media_aars;
+    counter_handle_t media_aars;
+    counter_handle_t successful_media_aars;
+    counter_handle_t active_media_rx_sessions;
+    counter_handle_t media_aar_replies_received;
+    counter_handle_t registration_aar_replies_received;
+};
+
+int ims_qos_init_counters();
+void ims_qos_destroy_counters();
+
+#endif	/* IMS_QOS_STATS_H */
+
+
+
diff --git a/modules/ims_qos/mod.c b/modules/ims_qos/mod.c
index 3dc9496..78010cb 100644
--- a/modules/ims_qos/mod.c
+++ b/modules/ims_qos/mod.c
@@ -43,7 +43,6 @@
  * 
  */
 
-#include "stats.h"
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
@@ -72,7 +71,7 @@
 #include "../../parser/sdp/sdp.h"
 
 #include "../../lib/ims/useful_defs.h"
-
+#include "ims_qos_stats.h"
 
 MODULE_VERSION
 
@@ -98,6 +97,20 @@ int cdp_event_latency = 1; /*flag: report slow processing of CDP callback events
 int cdp_event_threshold = 500; /*time in ms above which we should report slow processing of CDP callback event - default 500ms*/
 int cdp_event_latency_loglevel = 0; /*log-level to use to report slow processing of CDP callback event - default ERROR*/
 
+int audio_default_bandwidth = 64;
+int video_default_bandwidth = 128;
+
+int cdp_event_list_size_threshold = 0;  /**Threshold for size of cdp event list after which a warning is logged */
+
+stat_var *aars;
+stat_var *strs;
+stat_var *asrs;
+stat_var *successful_aars;
+stat_var *successful_strs;
+
+static str identifier = {0,0};
+static int identifier_size = 0;
+
 /** module functions */
 static int mod_init(void);
 static int mod_child_init(int);
@@ -114,11 +127,11 @@ str rx_dest_realm = str_init("ims.smilecoms.com");
 str rx_forced_peer = str_init("");
 
 /* commands wrappers and fixups */
-static int w_rx_aar(struct sip_msg *msg, char *route, char* direction, char *bar);
+static int w_rx_aar(struct sip_msg *msg, char *route, char* dir, char *id, int id_type);
 static int w_rx_aar_register(struct sip_msg *msg, char *route, char* str1, char *bar);
 
 static cmd_export_t cmds[] = {
-    { "Rx_AAR", (cmd_function) w_rx_aar, 2, fixup_aar, 0, REQUEST_ROUTE | ONREPLY_ROUTE},
+    { "Rx_AAR", (cmd_function) w_rx_aar, 4, fixup_aar, 0, REQUEST_ROUTE | ONREPLY_ROUTE},
     { "Rx_AAR_Register", (cmd_function) w_rx_aar_register, 2, fixup_aar_register, 0, REQUEST_ROUTE},
     { 0, 0, 0, 0, 0, 0}
 };
@@ -131,14 +144,12 @@ static param_export_t params[] = {
     { "cdp_event_threshold", INT_PARAM, &cdp_event_threshold}, /*time in ms above which we should report slow processing of CDP callback event*/
     { "cdp_event_latency_log", INT_PARAM, &cdp_event_latency_loglevel}, /*log-level to use to report slow processing of CDP callback event*/
     { "authorize_video_flow", INT_PARAM, &authorize_video_flow}, /*whether or not we authorize resources for video flows*/
+    { "cdp_event_list_size_threshold", INT_PARAM, &cdp_event_list_size_threshold}, /**Threshold for size of cdp event list after which a warning is logged */
+    { "audio_default_bandwidth", INT_PARAM, &audio_default_bandwidth},
+    { "video_default_bandwidth", INT_PARAM, &video_default_bandwidth},
     { 0, 0, 0}
 };
 
-stat_export_t mod_stats[] = {
-    {"aar_avg_response_time", STAT_IS_FUNC, (stat_var**) get_avg_aar_response_time},
-    {"aar_timeouts", 0, (stat_var**) & stat_aar_timeouts},
-    {0, 0, 0}
-};
 
 /** module exports */
 struct module_exports exports = {"ims_qos", DEFAULT_DLFLAGS, /* dlopen flags */
@@ -154,18 +165,6 @@ struct module_exports exports = {"ims_qos", DEFAULT_DLFLAGS, /* dlopen flags */
  * init module function
  */
 static int mod_init(void) {
-#ifdef STATISTICS
-    /* register statistics */
-    if (register_module_stats(exports.name, mod_stats) != 0) {
-        LM_ERR("failed to register core statistics\n");
-        goto error;
-    }
-
-    if (!register_stats()) {
-        LM_ERR("Unable to register statistics\n");
-        goto error;
-    }
-#endif
 
     callback_singleton = shm_malloc(sizeof (int));
     *callback_singleton = 0;
@@ -218,6 +217,11 @@ static int mod_init(void) {
         LM_ERR("unable to initialise cdp callback event list\n");
         return -1;
     }
+    
+    if (ims_qos_init_counters() != 0) {
+	    LM_ERR("Failed to register counters for ims_qos module\n");
+	    return -1;
+	}
 
     return 0;
 error:
@@ -232,7 +236,7 @@ static int mod_child_init(int rank) {
     LM_DBG("Initialization of module in child [%d] \n", rank);
 
     if (rank == PROC_MAIN) {
-        int pid = fork_process(PROC_SIPINIT, "Rx Event Processor", 1);
+	int pid = fork_process(PROC_MIN, "Rx Event Processor", 1);
         if (pid < 0)
             return -1; //error
         if (pid == 0) {
@@ -257,6 +261,9 @@ static int mod_child_init(int rank) {
 }
 
 static void mod_destroy(void) {
+    if (identifier_size > 0 && identifier.s) {
+        pkg_free(identifier.s);
+    }
 }
 
 /*callback of CDP session*/
@@ -355,8 +362,8 @@ void callback_dialog(struct dlg_cell* dlg, int type, struct dlg_cb_params * para
     
     LM_DBG("Dialog callback of type %d received\n", type);
     
-    if(type == DLGCB_TERMINATED || type == DLGCB_DESTROY || type == DLGCB_EXPIRED){
-	   LM_DBG("Dialog has ended - we need to terminate Rx bearer session\n");
+    if(type == DLGCB_TERMINATED || type == DLGCB_DESTROY || type == DLGCB_EXPIRED || type == DLGCB_FAILED){
+	   LM_DBG("Dialog has ended or failed - we need to terminate Rx bearer session\n");
 
 	LM_DBG("Received notification of termination of dialog with Rx session ID: [%.*s]\n",
 		rx_session_id->len, rx_session_id->s);
@@ -374,7 +381,7 @@ void callback_dialog(struct dlg_cell* dlg, int type, struct dlg_cb_params * para
 	//getting auth session
 	auth = cdpb.AAAGetAuthSession(*rx_session_id);
 	if (!auth) {
-	    LM_DBG("Could not get Auth Session for session id: [%.*s] - this is fine as this might have been started by already sending an STR\n", rx_session_id->len, rx_session_id->s);
+	    LM_DBG("Could not get Auth Session for session id: [%.*s]\n", rx_session_id->len, rx_session_id->s);
 	    goto error;
 	}
 
@@ -414,7 +421,7 @@ void callback_dialog(struct dlg_cell* dlg, int type, struct dlg_cb_params * para
 	//getting auth session
 	auth = cdpb.AAAGetAuthSession(*rx_session_id);
 	if (!auth) {
-	    LM_DBG("Could not get Auth Session for session id: [%.*s] - this is fine as this might have been started by already sending an STR\n", rx_session_id->len, rx_session_id->s);
+	    LM_DBG("Could not get Auth Session for session id: [%.*s]\n", rx_session_id->len, rx_session_id->s);
 	    goto error;
 	}
 
@@ -519,36 +526,74 @@ void callback_pcscf_contact_cb(struct pcontact *c, int type, void *param) {
     }
 }
 
+static int get_identifier(str* src) {
+    char *sep;
+    
+    if (src == 0 || src->len == 0){
+        return -1;
+    }
+
+    if (identifier_size <= src->len) {
+        if (identifier.s) {
+            pkg_free(identifier.s);
+        }
+        identifier.s = (char*) pkg_malloc(src->len + 1);
+        if (!identifier.s) {
+            LM_ERR("no more pkg mem\n");
+            return -1;
+        }
+        memset(identifier.s, 0, src->len + 1);
+        identifier_size = src->len + 1;
+    }
+    
+    memcpy(identifier.s, src->s, src->len);
+    identifier.len = src->len;
+    sep = memchr(identifier.s, 59 /* ; */, identifier.len);
+
+    if (sep) identifier.len = (int) (sep - identifier.s);
+    
+    return 0;
+}
+
+
 /* Wrapper to send AAR from config file - this only allows for AAR for calls - not register, which uses r_rx_aar_register
  * return: 1 - success, <=0 failure. 2 - message not a AAR generating message (ie proceed without PCC if you wish)
  */
-static int w_rx_aar(struct sip_msg *msg, char *route, char* str1, char* bar) {
+static int w_rx_aar(struct sip_msg *msg, char *route, char* dir, char *c_id, int id_type) {
 
     int ret = CSCF_RETURN_ERROR;
     int result = CSCF_RETURN_ERROR;
     struct cell *t;
 
-    AAASession* auth_session;
+    AAASession* auth_session = 0;
     rx_authsessiondata_t* rx_authdata_p = 0;
-    str *rx_session_id;
+    str *rx_session_id = 0;
     str callid = {0, 0};
     str ftag = {0, 0};
     str ttag = {0, 0};
     
     str route_name;
-    str identifier, ip;
+    str ip, uri;
+    int identifier_type;
     int ip_version = 0;
-    int must_free_asserted_identity = 0;
     sdp_session_cell_t* sdp_session;
+    str s_id;
+    struct hdr_field *h=0;
+    struct dlg_cell* dlg = 0;
 
     cfg_action_t* cfg_action = 0;
     saved_transaction_t* saved_t_data = 0; //data specific to each contact's AAR async call
-    char* direction = str1;
+    char* direction = dir;
     if (fixup_get_svalue(msg, (gparam_t*) route, &route_name) != 0) {
         LM_ERR("no async route block for assign_server_unreg\n");
         return result;
     }
     
+    if (get_str_fparam(&s_id, msg, (fparam_t*) c_id) < 0) {
+	LM_ERR("failed to get s__id\n");
+	return result;
+    }
+    
     LM_DBG("Looking for route block [%.*s]\n", route_name.len, route_name.s);
     int ri = route_get(&main_rt, route_name.s);
     if (ri < 0) {
@@ -676,38 +721,99 @@ static int w_rx_aar(struct sip_msg *msg, char *route, char* str1, char* bar) {
         rx_session_id = dlgb.get_dlg_var(&callid, &ftag, &ttag,
                 &term_session_key);
     }
-
-    if (!rx_session_id || rx_session_id->len <= 0 || !rx_session_id->s) {
+    if (rx_session_id && rx_session_id->len > 0 && rx_session_id->s) {
+	auth_session = cdpb.AAAGetAuthSession(*rx_session_id);
+	if(auth_session && auth_session->u.auth.state != AUTH_ST_OPEN) {
+	    LM_DBG("This session is not state open - so we will create a new session");
+	    if (auth_session) cdpb.AAASessionsUnlock(auth_session->hash);
+	    auth_session = 0;
+	}
+    }
+	
+    if (!auth_session) {
         LM_DBG("New AAR session for this dialog in mode %s\n", direction);
         
 	
 	//get ip and subscription_id and store them in the call session data
 	
 	//SUBSCRIPTION-ID
+	
+	//if subscription-id and identifier_type is passed from config file we use them - if not we use default behaviour of
+	
 	//if its mo we use p_asserted_identity in request - if that not there we use from_uri
 	//if its mt we use p_asserted_identity in reply - if that not there we use to_uri
+	if(s_id.len > 0 && id_type > -1) {
+            get_identifier(&s_id);
+	    identifier_type = id_type;
+	    LM_DBG("Passed in subscription_id [%.*s] and subscription_id_type [%d]\n", identifier.len, identifier.s, identifier_type);
+	} else {
+	    if (dlg_direction == DLG_MOBILE_ORIGINATING) {
+		LM_DBG("originating direction\n");
+                uri = cscf_get_asserted_identity(t->uas.request, 1);
+		if (uri.len == 0) {
+		    LM_DBG("No P-Asserted-Identity hdr found in request. Using From hdr in req");
+
+		    if (!cscf_get_from_uri(t->uas.request, &uri)) {
+			    LM_ERR("Error assigning P-Asserted-Identity using From hdr in req");
+			    goto error;
+		    }
+		    LM_DBG("going to remove parameters if any from identity: [%.*s]\n", uri.len, uri.s);
+		    get_identifier(&uri);
+		    LM_DBG("identifier from uri : [%.*s]\n", identifier.len, identifier.s);
+		    
+		} else {
+                    get_identifier(&uri);
+                    //free this cscf_get_asserted_identity allocates it
+                    pkg_free(uri.s);
+		}
+	    } else {
+		LM_DBG("terminating direction\n");
+                uri = cscf_get_asserted_identity(msg, 0);
+		if (uri.len == 0) {
+		    LM_DBG("No P-Asserted-Identity hdr found in response. Using Called party id in resp");
+		    //get identity from called party id
+		    //getting called asserted identity
+                    uri = cscf_get_public_identity_from_called_party_id(t->uas.request, &h);
+		    if (uri.len == 0) {
+			LM_DBG("No P-Called-Party hdr found in response. Using req URI from dlg");
+			//get dialog and get the req URI from there
+			dlg = dlgb.get_dlg(msg);
+			if (!dlg) {
+			    LM_ERR("Unable to find dialog and cannot do Rx without it\n");
+			    goto error;
+			}
+			LM_DBG("dlg req uri : [%.*s] going to remove parameters if any\n", dlg->req_uri.len, dlg->req_uri.s);
+			
+                        if (get_identifier(&dlg->req_uri) !=0 ) {
+                            dlgb.release_dlg(dlg);
+                            goto error;
+                        }
+			dlgb.release_dlg(dlg);
+			LM_DBG("identifier from dlg req uri : [%.*s]\n", identifier.len, identifier.s);
+		    } else {
+                        get_identifier(&uri);
+                    }
+		} else {
+                    get_identifier(&uri);
+                }
+	    }
+	    if (strncasecmp(identifier.s,"tel:",4)==0) {
+		identifier_type = AVP_Subscription_Id_Type_E164; //
+	    }else{
+		identifier_type = AVP_Subscription_Id_Type_SIP_URI; //default is END_USER_SIP_URI
+	    }
+	}
 	//IP 
 	//if its mo we use request SDP
 	//if its mt we use reply SDP
 	if (dlg_direction == DLG_MOBILE_ORIGINATING) {
 	    LM_DBG("originating direction\n");
-	    if ((identifier = cscf_get_asserted_identity(t->uas.request, 1)).len == 0) {
-		LM_DBG("No P-Asserted-Identity hdr found in request. Using From hdr in req");
-
-		if (!cscf_get_from_uri(t->uas.request, &identifier)) {
-			LM_ERR("Error assigning P-Asserted-Identity using From hdr in req");
-			goto error;
-		}
-	    } else {
-		must_free_asserted_identity = 1;
-	    }
-	    
 	    //get ip from request sdp (we use first SDP session)
 	    if (parse_sdp(t->uas.request) < 0) {
 		LM_ERR("Unable to parse req SDP\n");
 		goto error;
 	    }
-	    
+
 	    sdp_session = get_sdp_session(t->uas.request, 0);
 	    if (!sdp_session) {
 		    LM_ERR("Missing SDP session information from req\n");
@@ -716,20 +822,15 @@ static int w_rx_aar(struct sip_msg *msg, char *route, char* str1, char* bar) {
 	    ip = sdp_session->ip_addr;
 	    ip_version = sdp_session->pf;
 	    free_sdp((sdp_info_t**) (void*) &t->uas.request->body);
-	    
+
 	} else {
 	    LM_DBG("terminating direction\n");
-	    if ((identifier = cscf_get_asserted_identity(msg, 0)).len == 0) {
-		LM_DBG("No P-Asserted-Identity hdr found in response. Using To hdr in resp");
-		identifier = cscf_get_public_identity(msg); //get public identity from to header
-	    }
-	    
 	    //get ip from reply sdp (we use first SDP session)
 	    if (parse_sdp(msg) < 0) {
 		LM_ERR("Unable to parse req SDP\n");
 		goto error;
 	    }
-	    
+
 	    sdp_session = get_sdp_session(msg, 0);
 	    if (!sdp_session) {
 		    LM_ERR("Missing SDP session information from reply\n");
@@ -738,21 +839,14 @@ static int w_rx_aar(struct sip_msg *msg, char *route, char* str1, char* bar) {
 	    ip = sdp_session->ip_addr;
 	    ip_version = sdp_session->pf;
 	    free_sdp((sdp_info_t**) (void*) &msg->body);
-	    
 	}
-
-        int ret = create_new_callsessiondata(&callid, &ftag, &ttag, &identifier, &ip, ip_version, &rx_authdata_p);
+	
+        int ret = create_new_callsessiondata(&callid, &ftag, &ttag, &identifier, identifier_type, &ip, ip_version, &rx_authdata_p);
         if (!ret) {
             LM_DBG("Unable to create new media session data parcel\n");
             goto error;
         }
 	
-	//free this cscf_get_asserted_identity allocates it
-	if (must_free_asserted_identity) {
-		pkg_free(identifier.s);
-		must_free_asserted_identity = 1;
-	}
-	
 	//create new diameter auth session
         auth_session = cdpb.AAACreateClientAuthSession(1, callback_for_cdp_session, rx_authdata_p); //returns with a lock
         if (!auth_session) {
@@ -775,21 +869,6 @@ static int w_rx_aar(struct sip_msg *msg, char *route, char* str1, char* bar) {
         LM_DBG("Attached CDP auth session [%.*s] for Rx to dialog in %s mode\n", auth_session->id.len, auth_session->id.s, direction);
     } else {
         LM_DBG("Update AAR session for this dialog in mode %s\n", direction);
-	auth_session = cdpb.AAAGetAuthSession(*rx_session_id);
-	
-	    if (!auth_session) {
-	    LM_ERR("Could not get Auth Session for session id: [%.*s] on AAR update\n", rx_session_id->len, rx_session_id->s);
-	    result = CSCF_RETURN_FALSE; //here we return FALSE this just drops the message in the config file
-	    goto error;
-	}
-	
-	if(auth_session->u.auth.state != AUTH_ST_OPEN)
-	{
-	    LM_DBG("This session is not state open, packet will be dropped");
-	    if (auth_session) cdpb.AAASessionsUnlock(auth_session->hash);
-	    result = CSCF_RETURN_FALSE; //here we return FALSE this just drops the message in the config file
-	    goto error;
-	}
 	saved_t_data->aar_update = 1;//this is an update aar - we set this so on async_aar we know this is an update and act accordingly
     }
 
@@ -820,13 +899,6 @@ error:
     if (saved_t_data)
         free_saved_transaction_global_data(saved_t_data); //only free global data if no AARs were sent. if one was sent we have to rely on the callback (CDP) to free
     //otherwise the callback will segfault
-
-    //free this cscf_get_asserted_identity allocates it
-    if (must_free_asserted_identity) {
-	    pkg_free(identifier.s);
-	    must_free_asserted_identity = 1;
-    }
-
     return result;
 }
 
@@ -848,6 +920,8 @@ static int w_rx_aar_register(struct sip_msg *msg, char* route, char* str1, char*
     int aar_sent = 0;
     saved_transaction_local_t* local_data = 0; //data to be shared across all async calls
     saved_transaction_t* saved_t_data = 0; //data specific to each contact's AAR async call
+    str recv_ip;
+    int recv_port;
     
     if (fixup_get_svalue(msg, (gparam_t*) route, &route_name) != 0) {
         LM_ERR("no async route block for assign_server_unreg\n");
@@ -961,15 +1035,22 @@ static int w_rx_aar_register(struct sip_msg *msg, char* route, char* str1, char*
         LM_DBG("No contact headers in Register message\n");
         goto error;
     }
+    
+    //we use the received IP address for the framed_ip_address 
+    recv_ip.s = ip_addr2a(&msg->rcv.src_ip);
+    recv_ip.len = strlen(ip_addr2a(&msg->rcv.src_ip));
+    recv_port = msg->rcv.src_port;
+    LM_DBG("Message received IP address is: [%.*s]\n", recv_ip.len, recv_ip.s);
+    uint16_t ip_version = AF_INET; //TODO IPv6!!!?
 
     lock_get(saved_t_data->lock); //we lock here to make sure we send all requests before processing replies asynchronously
     for (h = msg->contact; h; h = h->next) {
         if (h->type == HDR_CONTACT_T && h->parsed) {
             for (c = ((contact_body_t*) h->parsed)->contacts; c; c = c->next) {
-                ul.lock_udomain(domain_t, &c->uri);
-                if (ul.get_pcontact(domain_t, &c->uri, &pcontact) != 0) {
+                ul.lock_udomain(domain_t, &c->uri, &recv_ip, recv_port);
+                if (ul.get_pcontact(domain_t, &c->uri, &recv_ip, recv_port, &pcontact) != 0) {
                     LM_DBG("This contact does not exist in PCSCF usrloc - error in cfg file\n");
-                    ul.unlock_udomain(domain_t, &c->uri);
+                    ul.unlock_udomain(domain_t, &c->uri, &recv_ip, recv_port);
                     lock_release(saved_t_data->lock);
                     goto error;
                 } else if (pcontact->reg_state == PCONTACT_REG_PENDING
@@ -977,25 +1058,13 @@ static int w_rx_aar_register(struct sip_msg *msg, char* route, char* str1, char*
                     LM_DBG("Contact [%.*s] exists and is in state PCONTACT_REG_PENDING or PCONTACT_REGISTERED\n"
                             , pcontact->aor.len, pcontact->aor.s);
 
-                    //get IP address from contact
-                    struct sip_uri puri;
-                    if (parse_uri(c->uri.s, c->uri.len, &puri) < 0) {
-                        LM_ERR("failed to parse Contact\n");
-                        ul.unlock_udomain(domain_t, &c->uri);
-                        lock_release(saved_t_data->lock);
-                        goto error;
-
-                    }
-                    LM_DBG("Parsed URI of from host is [%.*s]\n", puri.host.len, puri.host.s);
-                    uint16_t ip_version = AF_INET; //TODO IPv6!!!?
-
-                    //check for existing Rx session
+		    //check for existing Rx session
                     if (pcontact->rx_session_id.len > 0
                             && pcontact->rx_session_id.s
                             && (auth = cdpb.AAAGetAuthSession(pcontact->rx_session_id))) {
                         LM_DBG("Rx session already exists for this user\n");
                         if (memcmp(pcontact->rx_session_id.s, auth->id.s, auth->id.len) != 0) {
-                            LM_ERR("Rx session mismatch when URI is [%.*s].......Aborting\n", puri.host.len, puri.host.s);
+                            LM_ERR("Rx session mismatch for rx_session_id [%.*s].......Aborting\n", pcontact->rx_session_id.len, pcontact->rx_session_id.s);
                             if (auth) cdpb.AAASessionsUnlock(auth->hash);
                             lock_release(saved_t_data->lock);
                             goto error;
@@ -1005,10 +1074,10 @@ static int w_rx_aar_register(struct sip_msg *msg, char* route, char* str1, char*
                         is_rereg = 1;
                     } else {
                         LM_DBG("Creating new Rx session for contact <%.*s>\n", pcontact->aor.len, pcontact->aor.s);
-                        int ret = create_new_regsessiondata(domain_t->name, &pcontact->aor, &rx_regsession_data_p);
+                        int ret = create_new_regsessiondata(domain_t->name, &pcontact->aor, &recv_ip, ip_version, recv_port, &rx_regsession_data_p);
                         if (!ret) {
-                            LM_ERR("Unable to create regsession data parcel when URI is [%.*s]...Aborting\n", puri.host.len, puri.host.s);
-                            ul.unlock_udomain(domain_t, &c->uri);
+                            LM_ERR("Unable to create regsession data parcel for rx_session_id [%.*s]...Aborting\n", pcontact->rx_session_id.len, pcontact->rx_session_id.s);
+                            ul.unlock_udomain(domain_t, &c->uri, &recv_ip, recv_port);
                             if (rx_regsession_data_p) {
                                 shm_free(rx_regsession_data_p);
                                 rx_regsession_data_p = 0;
@@ -1018,12 +1087,12 @@ static int w_rx_aar_register(struct sip_msg *msg, char* route, char* str1, char*
                         }
                         auth = cdpb.AAACreateClientAuthSession(1, callback_for_cdp_session, rx_regsession_data_p); //returns with a lock
                         if (!auth) {
-                            LM_ERR("Rx: unable to create new Rx Reg Session when URI is [%.*s]\n", puri.host.len, puri.host.s);
+                            LM_ERR("Rx: unable to create new Rx Reg Session for rx_session_id is [%.*s]\n", pcontact->rx_session_id.len, pcontact->rx_session_id.s);
                             if (rx_regsession_data_p) {
                                 shm_free(rx_regsession_data_p);
                                 rx_regsession_data_p = 0;
                             }
-                            ul.unlock_udomain(domain_t, &c->uri);
+                            ul.unlock_udomain(domain_t, &c->uri, &recv_ip, recv_port);
                             if (auth) cdpb.AAASessionsUnlock(auth->hash);
                             if (rx_regsession_data_p) {
                                 shm_free(rx_regsession_data_p);
@@ -1068,9 +1137,9 @@ static int w_rx_aar_register(struct sip_msg *msg, char* route, char* str1, char*
 
                     //TODOD remove - no longer user AOR parm
                     //ret = rx_send_aar_register(msg, auth, &puri.host, &ip_version, &c->uri, local_data); //returns a locked rx auth object
-                    ret = rx_send_aar_register(msg, auth, &puri.host, &ip_version, local_data); //returns a locked rx auth object
+                    ret = rx_send_aar_register(msg, auth, local_data); //returns a locked rx auth object
 
-                    ul.unlock_udomain(domain_t, &c->uri);
+                    ul.unlock_udomain(domain_t, &c->uri, &recv_ip, recv_port);
 
                     if (!ret) {
                         LM_ERR("Failed to send AAR\n");
@@ -1085,7 +1154,7 @@ static int w_rx_aar_register(struct sip_msg *msg, char* route, char* str1, char*
                 } else {
                     //contact exists - this is a re-registration, for now we just ignore this
                     LM_DBG("This contact exists and is not in state REGISTER PENDING - we assume re (or de) registration and ignore\n");
-                    ul.unlock_udomain(domain_t, &c->uri);
+                    ul.unlock_udomain(domain_t, &c->uri, &recv_ip, recv_port);
                     //now we loop for any other contacts.
                 }
             }
@@ -1174,7 +1243,11 @@ static int fixup_aar_register(void** param, int param_no) {
 }
 
 static int fixup_aar(void** param, int param_no) {
-    if (strlen((char*) *param) <= 0) {
+    str s;
+    int num;
+    
+    //param 3 can be empty
+    if (param_no != 3 && strlen((char*) *param) <= 0) {
         LM_ERR("empty parameter %d not allowed\n", param_no);
         return -1;
     }
@@ -1183,6 +1256,19 @@ static int fixup_aar(void** param, int param_no) {
         if (fixup_spve_null(param, param_no) < 0)
             return -1;
         return 0;
+    } else if (param_no == 3) {
+	return fixup_var_str_12(param, param_no);
+    } else if (param_no == 4) {
+	/*convert to int */
+	s.s = (char*)*param;
+	s.len = strlen(s.s);
+	if (str2sint(&s, &num)==0) {
+		pkg_free(*param);
+		*param = (void*)(unsigned long)num;
+		return 0;
+	}
+	LM_ERR("Bad subscription id: <%s>n", (char*)(*param));
+	return E_CFG;
     }
 
     return 0;
diff --git a/modules/ims_qos/rx_aar.c b/modules/ims_qos/rx_aar.c
index 028d6cd..fcc91de 100644
--- a/modules/ims_qos/rx_aar.c
+++ b/modules/ims_qos/rx_aar.c
@@ -48,7 +48,6 @@
  *  2011-02-02  initial version (jason.penton)
  */
 
-#include "stats.h"
 #include "../../mem/shm_mem.h"
 #include "../../parser/sdp/sdp.h"
 #include "../cdp_avp/mod_export.h"
@@ -66,11 +65,16 @@
 #include "mod.h"
 
 #include "../../lib/ims/useful_defs.h"
+#include "ims_qos_stats.h"
+
+
 #define macro_name(_rc)	#_rc
 
 //extern struct tm_binds tmb;
 usrloc_api_t ul;
 
+extern struct ims_qos_counters_h ims_qos_cnts_h;
+
 extern int authorize_video_flow;
 
 str IMS_Serv_AVP_val = {"IMS Services", 12};
@@ -94,7 +98,7 @@ void async_aar_callback(int is_timeout, void *param, AAAMessage *aaa, long elaps
     struct cell *t = 0;
     unsigned int cdp_result;
     int result = CSCF_RETURN_ERROR;
-
+    
     LM_DBG("Received AAR callback\n");
     saved_transaction_t* data = (saved_transaction_t*) param;
 
@@ -116,7 +120,7 @@ void async_aar_callback(int is_timeout, void *param, AAAMessage *aaa, long elaps
 
     if (is_timeout != 0) {
         LM_ERR("Error timeout when sending AAR message via CDP\n");
-        update_stat(stat_aar_timeouts, 1);
+        counter_inc(ims_qos_cnts_h.media_aar_timeouts);
         goto error;
     }
     if (!aaa) {
@@ -124,8 +128,9 @@ void async_aar_callback(int is_timeout, void *param, AAAMessage *aaa, long elaps
         goto error;
     }
 
-    update_stat(aar_replies_received, 1);
-    update_stat(aar_replies_response_time, elapsed_msecs);
+    counter_inc(ims_qos_cnts_h.media_aars);
+    counter_add(ims_qos_cnts_h.media_aar_response_time, elapsed_msecs);
+    counter_inc(ims_qos_cnts_h.media_aar_replies_received);
 
     /* Process the response to AAR, retrieving result code and associated Rx session ID */
     if (rx_process_aaa(aaa, &cdp_result) < 0) {
@@ -135,22 +140,26 @@ void async_aar_callback(int is_timeout, void *param, AAAMessage *aaa, long elaps
 
     if (cdp_result >= 2000 && cdp_result < 3000) {
         LM_DBG("Success, received code: [%i] from PCRF for AAR request\n", cdp_result);
-
-        LM_DBG("Auth session ID [%.*s]", aaa->sessionId->data.len, aaa->sessionId->data.s);
+	counter_inc(ims_qos_cnts_h.successful_media_aars);
 	
+	LM_DBG("Auth session ID [%.*s]", aaa->sessionId->data.len, aaa->sessionId->data.s);
+
 	if(!data->aar_update) {
 	    LM_DBG("This is an AAA response to an initial AAR");
+	    counter_inc(ims_qos_cnts_h.active_media_rx_sessions);
+	    
 	    str * passed_rx_session_id = shm_malloc(sizeof (struct _str));
 	    passed_rx_session_id->s = 0;
 	    passed_rx_session_id->len = 0;
 	    STR_SHM_DUP(*passed_rx_session_id, aaa->sessionId->data, "cb_passed_rx_session_id");
 	    LM_DBG("passed rx session id [%.*s]", passed_rx_session_id->len, passed_rx_session_id->s);
 
-	    dlgb.register_dlgcb_nodlg(&data->callid, &data->ftag, &data->ttag, DLGCB_TERMINATED | DLGCB_DESTROY | DLGCB_EXPIRED | DLGCB_RESPONSE_WITHIN | DLGCB_CONFIRMED, callback_dialog, (void*) (passed_rx_session_id), free_dialog_data);
+	    dlgb.register_dlgcb_nodlg(&data->callid, &data->ftag, &data->ttag, DLGCB_TERMINATED | DLGCB_DESTROY | DLGCB_EXPIRED | DLGCB_RESPONSE_WITHIN | DLGCB_CONFIRMED | DLGCB_FAILED, callback_dialog, (void*) (passed_rx_session_id), free_dialog_data);
 	} 
         result = CSCF_RETURN_TRUE;
     } else {
         LM_DBG("Received negative reply from PCRF for AAR Request\n");
+	counter_inc(ims_qos_cnts_h.failed_media_aars);
         //we don't free rx_authdata_p here - it is free-ed when the CDP session expires
         goto error; // if its not a success then that means i want to reject this call!
     }
@@ -181,6 +190,8 @@ void async_aar_reg_callback(int is_timeout, void *param, AAAMessage *aaa, long e
     struct pcontact_info ci;
     udomain_t* domain_t;
     int finalReply = 0;
+    AAASession *auth = 0;
+    rx_authsessiondata_t* p_session_data = 0;
     int result = CSCF_RETURN_ERROR;
 
     LM_DBG("Received AAR callback\n");
@@ -221,7 +232,7 @@ void async_aar_reg_callback(int is_timeout, void *param, AAAMessage *aaa, long e
 
     if (is_timeout != 0) {
         LM_ERR("Error timeout when sending AAR message via CDP\n");
-        update_stat(stat_aar_timeouts, 1);
+        counter_inc(ims_qos_cnts_h.registration_aar_timeouts);
         goto error;
     }
     if (!aaa) {
@@ -229,8 +240,9 @@ void async_aar_reg_callback(int is_timeout, void *param, AAAMessage *aaa, long e
         goto error;
     }
 
-    update_stat(aar_replies_received, 1);
-    update_stat(aar_replies_response_time, elapsed_msecs);
+    counter_inc(ims_qos_cnts_h.registration_aars);
+    counter_add(ims_qos_cnts_h.registration_aar_response_time, elapsed_msecs);
+    counter_inc(ims_qos_cnts_h.registration_aar_replies_received);
 
     /* Process the response to AAR, retrieving result code and associated Rx session ID */
     if (rx_process_aaa(aaa, &cdp_result) < 0) {
@@ -239,21 +251,43 @@ void async_aar_reg_callback(int is_timeout, void *param, AAAMessage *aaa, long e
     }
 
     if (cdp_result >= 2000 && cdp_result < 3000) {
-        if (is_rereg) {
+        counter_inc(ims_qos_cnts_h.successful_registration_aars);
+	if (is_rereg) {
             LM_DBG("this is a re-registration, therefore we don't need to do anything except know that the the subscription was successful\n");
             result = CSCF_RETURN_TRUE;
             create_return_code(result);
             goto done;
         }
+	//need to set Rx auth data to say this session has been successfully opened
+	//This is used elsewhere to prevent acting on termination events when the session has not been opened
+	//getting auth session
+	auth = cdpb.AAAGetAuthSession(aaa->sessionId->data);
+	if (!auth) {
+	    LM_DBG("Could not get Auth Session for session id: [%.*s]\n", aaa->sessionId->data.len, aaa->sessionId->data.s);
+	    goto error;
+	}
+	//getting session data
+	p_session_data = (rx_authsessiondata_t*) auth->u.auth.generic_data;
+	if (!p_session_data) {
+	    LM_DBG("Could not get session data on Auth Session for session id: [%.*s]\n", aaa->sessionId->data.len, aaa->sessionId->data.s);
+	    if (auth) cdpb.AAASessionsUnlock(auth->hash);
+	    goto error;
+	}
+	p_session_data->session_has_been_opened = 1;
+	counter_inc(ims_qos_cnts_h.active_registration_rx_sessions);
+	
+	if (auth) cdpb.AAASessionsUnlock(auth->hash);
+	
+	
         LM_DBG("Success, received code: [%i] from PCRF for AAR request (contact: [%.*s]), (auth session id: %.*s)\n",
                 cdp_result, local_data->contact.len, local_data->contact.s,
                 local_data->auth_session_id.len, local_data->auth_session_id.s);
         LM_DBG("Registering for Usrloc callbacks on DELETE\n");
 
-        ul.lock_udomain(domain_t, &local_data->contact);
-        if (ul.get_pcontact(domain_t, &local_data->contact, &pcontact) != 0) {
+        ul.lock_udomain(domain_t, &local_data->contact, &p_session_data->ip, p_session_data->recv_port);
+        if (ul.get_pcontact(domain_t, &local_data->contact, &p_session_data->ip, p_session_data->recv_port, &pcontact) != 0) {
             LM_ERR("Shouldn't get here, can find contact....\n");
-            ul.unlock_udomain(domain_t, &local_data->contact);
+            ul.unlock_udomain(domain_t, &local_data->contact, &p_session_data->ip, p_session_data->recv_port);
             goto error;
         }
 
@@ -263,7 +297,7 @@ void async_aar_reg_callback(int is_timeout, void *param, AAAMessage *aaa, long e
          * */
         if (ul.update_rx_regsession(domain_t, &local_data->auth_session_id, pcontact) != 0) {
             LM_ERR("unable to update pcontact......\n");
-            ul.unlock_udomain(domain_t, &local_data->contact);
+            ul.unlock_udomain(domain_t, &local_data->contact, &p_session_data->ip, p_session_data->recv_port);
             goto error;
         }
         memset(&ci, 0, sizeof (struct pcontact_info));
@@ -275,10 +309,11 @@ void async_aar_reg_callback(int is_timeout, void *param, AAAMessage *aaa, long e
         //register for callbacks on contact
         ul.register_ulcb(pcontact, PCSCF_CONTACT_DELETE | PCSCF_CONTACT_EXPIRE,
                 callback_pcscf_contact_cb, NULL);
-        ul.unlock_udomain(domain_t, &local_data->contact);
+        ul.unlock_udomain(domain_t, &local_data->contact, &p_session_data->ip, p_session_data->recv_port);
         result = CSCF_RETURN_TRUE;
     } else {
-        LM_ERR("Received negative reply from PCRF for AAR Request\n");
+        LM_DBG("Received negative reply from PCRF for AAR Request\n");
+	counter_inc(ims_qos_cnts_h.failed_registration_aars);
         result = CSCF_RETURN_FALSE;
         goto error;
     }
@@ -459,7 +494,6 @@ int add_media_components(AAAMessage* aar, struct sip_msg *req,
 int rx_send_aar_update_no_video(AAASession* auth) {
 
     AAAMessage* aar = 0;
-    int must_free_asserted_identity = 0;
     
     str identifier;
     int identifier_type;
@@ -476,6 +510,7 @@ int rx_send_aar_update_no_video(AAASession* auth) {
     rx_authsessiondata_t* p_session_data = 0;
     p_session_data = (rx_authsessiondata_t*) auth->u.auth.generic_data;
     identifier = p_session_data->identifier;
+    identifier_type = p_session_data->identifier_type;
     ip = p_session_data->ip;
     ip_version = p_session_data->ip_version;
     
@@ -537,17 +572,7 @@ int rx_send_aar_update_no_video(AAASession* auth) {
 
     LM_DBG("Adding subscription id...\n");
 
-    if (strncasecmp(identifier.s,"tel:",4)==0) {
-	identifier_type = AVP_Subscription_Id_Type_E164; //
-    }else{
-	identifier_type = AVP_Subscription_Id_Type_SIP_URI; //default is END_USER_SIP_URI
-    }
-    
-    
     rx_add_subscription_id_avp(aar, identifier, identifier_type);
-    if (must_free_asserted_identity) {
-            pkg_free(identifier.s);
-    }
 
 
     LM_DBG("Adding reservation priority...\n");
@@ -630,7 +655,6 @@ int rx_send_aar(struct sip_msg *req, struct sip_msg *res,
         AAASession* auth, char* direction, saved_transaction_t* saved_t_data) {
 
     AAAMessage* aar = 0;
-    int must_free_asserted_identity = 0;
     
     str identifier;
     int identifier_type;
@@ -647,6 +671,7 @@ int rx_send_aar(struct sip_msg *req, struct sip_msg *res,
     rx_authsessiondata_t* p_session_data = 0;
     p_session_data = (rx_authsessiondata_t*) auth->u.auth.generic_data;
     identifier = p_session_data->identifier;
+    identifier_type = p_session_data->identifier_type;
     ip = p_session_data->ip;
     ip_version = p_session_data->ip_version;
     
@@ -716,17 +741,7 @@ int rx_send_aar(struct sip_msg *req, struct sip_msg *res,
 
     LM_DBG("Adding subscription id...\n");
 
-    if (strncasecmp(identifier.s,"tel:",4)==0) {
-	identifier_type = AVP_Subscription_Id_Type_E164; //
-    }else{
-	identifier_type = AVP_Subscription_Id_Type_SIP_URI; //default is END_USER_SIP_URI
-    }
-    
-    
     rx_add_subscription_id_avp(aar, identifier, identifier_type);
-    if (must_free_asserted_identity) {
-            pkg_free(identifier.s);
-    }
 
 
     LM_DBG("Adding reservation priority...\n");
@@ -806,13 +821,22 @@ error:
  * @returns int >0 if sent AAR successfully, otherwise 0
  */
 
-int rx_send_aar_register(struct sip_msg *msg, AAASession* auth, str *ip,
-        uint16_t *ip_version, saved_transaction_local_t* saved_t_data) {
+int rx_send_aar_register(struct sip_msg *msg, AAASession* auth, saved_transaction_local_t* saved_t_data) {
     AAAMessage* aar = 0;
     int ret = 0;
     AAA_AVP* avp = 0;
     char x[4];
     str identifier;
+    
+    str ip;
+    uint16_t ip_version;
+
+    //we get ip and identifier for the auth session data 
+    rx_authsessiondata_t* p_session_data = 0;
+    p_session_data = (rx_authsessiondata_t*) auth->u.auth.generic_data;
+    identifier = p_session_data->identifier;
+    ip = p_session_data->ip;
+    ip_version = p_session_data->ip_version;
 
     LM_DBG("Send AAR register\n");
 
@@ -850,7 +874,7 @@ int rx_send_aar_register(struct sip_msg *msg, AAASession* auth, str *ip,
     rx_add_media_component_description_avp_register(aar);
 
     /* Add Framed IP address AVP*/
-    if (!rx_add_framed_ip_avp(&aar->avpList, *ip, *ip_version)) {
+    if (!rx_add_framed_ip_avp(&aar->avpList, ip, ip_version)) {
         LM_ERR("Unable to add framed IP AVP\n");
         goto error;
     }
diff --git a/modules/ims_qos/rx_aar.h b/modules/ims_qos/rx_aar.h
index 9bd782a..3fc1e92 100644
--- a/modules/ims_qos/rx_aar.h
+++ b/modules/ims_qos/rx_aar.h
@@ -104,7 +104,7 @@ int rx_send_aar_update_no_video(AAASession* auth);
 
 //TODOD remove - no longer user AOR parm
 //int rx_send_aar_register(struct sip_msg *msg, AAASession* auth, str *ip_address, uint16_t *ip_version, str *aor, saved_transaction_local_t* saved_t_data);
-int rx_send_aar_register(struct sip_msg *msg, AAASession* auth, str *ip_address, uint16_t *ip_version, saved_transaction_local_t* saved_t_data);
+int rx_send_aar_register(struct sip_msg *msg, AAASession* auth, saved_transaction_local_t* saved_t_data);
 
 int rx_process_aaa(AAAMessage *aaa, unsigned int * rc);
 enum dialog_direction get_dialog_direction(char *direction);
diff --git a/modules/ims_qos/rx_asr.c b/modules/ims_qos/rx_asr.c
index 523397b..4f34ac2 100644
--- a/modules/ims_qos/rx_asr.c
+++ b/modules/ims_qos/rx_asr.c
@@ -60,6 +60,9 @@
 #include "rx_asr.h"
 #include "rx_avp.h"
 #include "../../lib/ims/ims_getters.h"
+#include "ims_qos_stats.h"
+
+extern struct ims_qos_counters_h ims_qos_cnts_h;
 
 /*
  * Called upon receipt of an ASR. Terminates the user session and returns the ASA.
@@ -76,13 +79,15 @@ AAAMessage* rx_process_asr(AAAMessage *request) {
 
     if (!request || !request->sessionId) return 0;
 
+    counter_inc(ims_qos_cnts_h.asrs);
+    
     session = cdpb.AAAGetAuthSession(request->sessionId->data);
 
     if (!session) {
         LM_DBG("received an ASR but the session is already deleted\n");
         return 0;
     }
-
+    
     code = rx_get_abort_cause(request);
     LM_DBG("abort-cause code is %u\n", code);
 
diff --git a/modules/ims_qos/rx_authdata.c b/modules/ims_qos/rx_authdata.c
index 1de9b40..bc99492 100644
--- a/modules/ims_qos/rx_authdata.c
+++ b/modules/ims_qos/rx_authdata.c
@@ -68,9 +68,9 @@
 #include "../../lib/ims/ims_getters.h"
 #include "mod.h"
 
-int create_new_regsessiondata(str* domain, str* aor, rx_authsessiondata_t** session_data) {
+int create_new_regsessiondata(str* domain, str* aor, str *ip, int ip_version, int recv_port, rx_authsessiondata_t** session_data) {
 
-	int len = (domain->len + 1) + aor->len + sizeof(rx_authsessiondata_t);
+	int len = (domain->len + 1) + aor->len + ip->len + sizeof(rx_authsessiondata_t);
 	rx_authsessiondata_t* p_session_data = shm_malloc(len);
 	if (!p_session_data) {
 		LM_ERR("no more shm memory\n");
@@ -81,6 +81,10 @@ int create_new_regsessiondata(str* domain, str* aor, rx_authsessiondata_t** sess
 	p_session_data->subscribed_to_signaling_path_status = 1;
         p_session_data->must_terminate_dialog = 0; /*irrelevent for reg session data this will always be 0 */
 
+	p_session_data->session_has_been_opened = 0; /*0 has not been opened 1 has been opened*/
+	p_session_data->ip_version = ip_version;
+	p_session_data->recv_port = recv_port;
+	
 	char* p = (char*)(p_session_data + 1);
 	p_session_data->domain.s = p;
 	memcpy(p, domain->s, domain->len);
@@ -92,6 +96,12 @@ int create_new_regsessiondata(str* domain, str* aor, rx_authsessiondata_t** sess
 	memcpy(p, aor->s, aor->len);
 	p_session_data->registration_aor.len = aor->len;
 	p += aor->len;
+	
+	p_session_data->ip.s = p;
+	memcpy(p, ip->s, ip->len);
+	p_session_data->ip.len = ip->len;
+	p += ip->len;
+	
 	if (p != (((char*)p_session_data) + len)) {
 		LM_ERR("buffer over/underflow\n");
 		shm_free(p_session_data);
@@ -103,7 +113,7 @@ int create_new_regsessiondata(str* domain, str* aor, rx_authsessiondata_t** sess
 	return 1;
 }
 
-int create_new_callsessiondata(str* callid, str* ftag, str* ttag, str* identifier, str* ip, int ip_version, rx_authsessiondata_t** session_data) {
+int create_new_callsessiondata(str* callid, str* ftag, str* ttag, str* identifier, int identifier_type, str* ip, int ip_version, rx_authsessiondata_t** session_data) {
 
 	int len = callid->len + ftag->len + ttag->len + identifier->len + ip->len + sizeof(rx_authsessiondata_t);
 	rx_authsessiondata_t* call_session_data = shm_malloc(len);
@@ -118,6 +128,7 @@ int create_new_callsessiondata(str* callid, str* ftag, str* ttag, str* identifie
 	call_session_data->first_current_flow_description=0;
 	call_session_data->first_new_flow_description=0;
 	call_session_data->ip_version = ip_version;
+	call_session_data->identifier_type = identifier_type;
 	
 	char *p = (char*)(call_session_data + 1);
 
diff --git a/modules/ims_qos/rx_authdata.h b/modules/ims_qos/rx_authdata.h
index 3332997..8814167 100644
--- a/modules/ims_qos/rx_authdata.h
+++ b/modules/ims_qos/rx_authdata.h
@@ -80,10 +80,13 @@ typedef struct rx_authsessiondata {
     str ftag;
     str ttag;
     str identifier;
+    int identifier_type;
     str ip;
+    int recv_port;
     int ip_version;
     //for registration session
     int subscribed_to_signaling_path_status; // 0 not subscribed 1 is subscribed
+    int session_has_been_opened; // 0 has not been opened 1 has been opened
     str domain;				//the domain the registration aor belongs to (for registration)
     str registration_aor; //the aor if this rx session is a subscription to signalling status
     int must_terminate_dialog; //0 means when this session terminates it must not terminate the relevant dialog, 1 means it must terminate the dialog
@@ -91,8 +94,8 @@ typedef struct rx_authsessiondata {
     flow_description_t *first_new_flow_description;
 } rx_authsessiondata_t;
 
-int create_new_regsessiondata(str* domain, str* aor, rx_authsessiondata_t** session_data);
-int create_new_callsessiondata(str* callid, str* ftag, str* ttag, str* identifier, str *ip, int ip_version, rx_authsessiondata_t** session_data);
+int create_new_regsessiondata(str* domain, str* aor,  str *ip, int ip_version, int recv_port, rx_authsessiondata_t** session_data);
+int create_new_callsessiondata(str* callid, str* ftag, str* ttag, str* identifier, int identifier_type, str *ip, int ip_version, rx_authsessiondata_t** session_data);
 void free_callsessiondata(rx_authsessiondata_t* session_data);
 
 int add_flow_description(rx_authsessiondata_t* session_data, int stream_num, str *media, str *req_sdp_ip_addr, str *req_sdp_port,
diff --git a/modules/ims_qos/rx_avp.c b/modules/ims_qos/rx_avp.c
index 6d0867c..a0a79f9 100644
--- a/modules/ims_qos/rx_avp.c
+++ b/modules/ims_qos/rx_avp.c
@@ -55,6 +55,7 @@
 #include "rx_authdata.h"
 #include "rx_avp.h"
 #include "mod.h"
+#include "../../parser/sdp/sdp_helpr_funcs.h"
 
 #include "../../lib/ims/ims_getters.h"
 
@@ -343,6 +344,31 @@ int rx_add_subscription_id_avp(AAAMessage *msg, str identifier, int identifier_t
             __FUNCTION__);
 }
 
+inline unsigned int sdp_b_value(str * payload, char * subtype) {
+   char * line;
+   unsigned int i;
+   str s;
+   line = find_sdp_line(payload->s, payload->s + payload->len, 'b');
+   while (line != NULL) {
+      // b=AS:
+      if ((line[2] == subtype[0]) && (line[3] == subtype[1])) {
+        LM_DBG("SDP-Line: %.*s\n", 5, line);
+        line += 5;
+        i = 0;
+        while ((line[i] != '\r') && (line[i] != '\n') && ((line +i) <= (payload->s + payload->len))) {
+          i++;
+	}
+        s.s = line;
+        s.len = i;
+        LM_DBG("value: %.*s\n", s.len, s.s);
+        if (str2int(&s, &i) == 0) return i;
+        else return 0;
+      }
+      line = find_next_sdp_line(line, payload->s + payload->len, 'b', NULL);
+   }
+   return 0;
+}
+
 inline int rx_add_media_component_description_avp(AAAMessage *msg, int number, str *media_description, str *ipA, str *portA, str *ipB, str *portB, str *transport,
         str *req_raw_payload, str *rpl_raw_payload, enum dialog_direction dlg_direction) {
     str data;
@@ -351,8 +377,10 @@ inline int rx_add_media_component_description_avp(AAAMessage *msg, int number, s
     AAA_AVP *codec_data1, *codec_data2;
     AAA_AVP * media_sub_component[PCC_Media_Sub_Components];
     AAA_AVP *flow_status;
+    AAA_AVP *dl_bw, *ul_bw, *rs_bw, *rr_bw;
 
     int media_sub_component_number = 0;
+    unsigned int bandwidth = 0;
 
     int type;
     char x[4];
@@ -412,6 +440,72 @@ inline int rx_add_media_component_description_avp(AAAMessage *msg, int number, s
     cdpb.AAAAddAVPToList(&list, media_type);
 
     /*RR and RS*/
+    if ((type == AVP_IMS_Media_Type_Audio) || (type == AVP_IMS_Media_Type_Video)) {
+	// Get bandwidth from SDP:
+        bandwidth = sdp_b_value(req_raw_payload, "AS");
+        LM_DBG("Request: got bandwidth %i from b=AS-Line\n", bandwidth);
+        // Set default values:
+        if ((type == AVP_IMS_Media_Type_Audio) && (bandwidth <= 0))
+	  bandwidth = audio_default_bandwidth;
+        if ((type == AVP_IMS_Media_Type_Video) && (bandwidth <= 0))
+	  bandwidth = video_default_bandwidth;
+        
+        // According to 3GPP TS 29.213, Rel. 9+, this value is * 1000:
+        bandwidth *= 1000; 
+  
+        // Add AVP
+        set_4bytes(x,bandwidth);
+	ul_bw = cdpb.AAACreateAVP(AVP_EPC_Max_Requested_Bandwidth_UL,
+            AAA_AVP_FLAG_MANDATORY | AAA_AVP_FLAG_VENDOR_SPECIFIC,
+            IMS_vendor_id_3GPP, x, 4,
+            AVP_DUPLICATE_DATA);
+    	cdpb.AAAAddAVPToList(&list, ul_bw);
+
+	// Get bandwidth from SDP:
+        bandwidth = sdp_b_value(rpl_raw_payload, "AS");
+        LM_DBG("Answer: got bandwidth %i from b=AS-Line\n", bandwidth);
+        // Set default values:
+        if ((type == AVP_IMS_Media_Type_Audio) && (bandwidth <= 0))
+	  bandwidth = audio_default_bandwidth;
+        if ((type == AVP_IMS_Media_Type_Video) && (bandwidth <= 0))
+	  bandwidth = video_default_bandwidth;
+
+        // According to 3GPP TS 29.213, Rel. 9+, this value is * 1000:
+        bandwidth *= 1000; 
+        
+        // Add AVP
+        set_4bytes(x,bandwidth);
+	dl_bw = cdpb.AAACreateAVP(AVP_EPC_Max_Requested_Bandwidth_DL,
+            AAA_AVP_FLAG_MANDATORY | AAA_AVP_FLAG_VENDOR_SPECIFIC,
+            IMS_vendor_id_3GPP, x, 4,
+            AVP_DUPLICATE_DATA);
+    	cdpb.AAAAddAVPToList(&list, dl_bw);
+
+	// Get A=RS-bandwidth from SDP-Reply:
+        bandwidth = sdp_b_value(rpl_raw_payload, "RS");
+        LM_DBG("Answer: Got bandwidth %i from b=RS-Line\n", bandwidth);
+	if (bandwidth >= 0) {
+		// Add AVP
+		set_4bytes(x,bandwidth);
+		rs_bw = cdpb.AAACreateAVP(AVP_EPC_RS_Bandwidth,
+		    AAA_AVP_FLAG_MANDATORY | AAA_AVP_FLAG_VENDOR_SPECIFIC,
+		    IMS_vendor_id_3GPP, x, 4,
+		    AVP_DUPLICATE_DATA);
+		cdpb.AAAAddAVPToList(&list, rs_bw);
+	}
+	// Get A=RS-bandwidth from SDP-Reply:
+        bandwidth = sdp_b_value(rpl_raw_payload, "RR");
+        LM_DBG("Answer: Got bandwidth %i from b=RR-Line\n", bandwidth);
+	if (bandwidth >= 0) {
+		// Add AVP
+		set_4bytes(x,bandwidth);
+		rr_bw = cdpb.AAACreateAVP(AVP_EPC_RR_Bandwidth,
+		    AAA_AVP_FLAG_MANDATORY | AAA_AVP_FLAG_VENDOR_SPECIFIC,
+		    IMS_vendor_id_3GPP, x, 4,
+		    AVP_DUPLICATE_DATA);
+		cdpb.AAAAddAVPToList(&list, rr_bw);
+	}
+    }
 
     /*codec-data*/
 
@@ -683,45 +777,60 @@ AAA_AVP *rx_create_media_subcomponent_avp_register() {
  */
 
 AAA_AVP* rx_create_codec_data_avp(str *raw_sdp_stream, int number, int direction) {
-    char data[PCC_MAX_Char4];
-    char *p;
-    int l, len;
+    str data;
+    int l = 0;
+    AAA_AVP* result;
+    data.len = 0;
 
     switch (direction) {
-
-        case 0: sprintf(data, "uplink\noffer\n");
+        case 0: data.len = 13;
             break;
-        case 1: sprintf(data, "uplink\nanswer\n");
+        case 1: data.len = 14;
             break;
-        case 2: sprintf(data, "downlink\noffer\n");
+        case 2: data.len = 15;
             break;
-        case 3: sprintf(data, "downlink\nanswer\n");
+        case 3: data.len = 16;
             break;
         default:
             break;
-
     }
+    data.len += raw_sdp_stream->len + 1; // 0 Terminated.
+    LM_DBG("data.len is calculated %i, sdp-stream has a len of %i\n", data.len, raw_sdp_stream->len);
+    data.s = (char*)pkg_malloc(data.len);
+    memset(data.s, 0, data.len);
+    
+    switch (direction) {
+        case 0: memcpy(data.s, "uplink\noffer\n", 13);
+		l = 13;
+            break;
+        case 1: memcpy(data.s, "uplink\nanswer\n", 14);
+		l = 14;
+            break;
+        case 2: memcpy(data.s, "downlink\noffer\n", 15);
+		l = 15;
+            break;
+        case 3: memcpy(data.s, "downlink\nanswer\n", 16);
+		l = 16;
+            break;
+        default:
+            break;
 
-    l = strlen(data);
-
-    if ((l + raw_sdp_stream->len) >= PCC_MAX_Char4) {
-        len = PCC_MAX_Char4 - l - 1;
-    } else {
-        len = raw_sdp_stream->len;
     }
+    // LM_DBG("data.s = \"%.*s\"\n", l, data.s);
+    memcpy(data.s + l, raw_sdp_stream->s, raw_sdp_stream->len);
+    LM_DBG("data.s = \"%.*s\"\n", data.len, data.s);
 
-    memcpy(data + l, raw_sdp_stream->s, len);
-    p = data + l + len;
-    *p = '\0';
-
-    return (cdpb.AAACreateAVP(AVP_IMS_Codec_Data,
+    result = cdpb.AAACreateAVP(AVP_IMS_Codec_Data,
             AAA_AVP_FLAG_MANDATORY | AAA_AVP_FLAG_VENDOR_SPECIFIC,
-            IMS_vendor_id_3GPP, data, strlen(data),
-            AVP_DUPLICATE_DATA));
+            IMS_vendor_id_3GPP, data.s, data.len,
+            AVP_DUPLICATE_DATA);
+ 
+    // Free the buffer:
+    pkg_free(data.s);
 
+    return result;
 }
 
-
 /**
  * Creates and adds a Vendor Specific Application ID Group AVP.
  * @param msg - the Diameter message to add to.
diff --git a/modules/ims_qos/rx_avp.h b/modules/ims_qos/rx_avp.h
index 9447ef3..85c5cb3 100644
--- a/modules/ims_qos/rx_avp.h
+++ b/modules/ims_qos/rx_avp.h
@@ -64,6 +64,10 @@ struct AAA_AVP_List;
 struct AAAMessage;
 enum dialog_direction;
 
+int audio_default_bandwidth;
+int video_default_bandwidth;
+
+
 /*helper*/
 int rx_add_framed_ip_avp(AAA_AVP_LIST * list, str ip, uint16_t version);
 
diff --git a/modules/ims_registrar_pcscf/Makefile b/modules/ims_registrar_pcscf/Makefile
index 3ffdf6f..8ed9ec4 100644
--- a/modules/ims_registrar_pcscf/Makefile
+++ b/modules/ims_registrar_pcscf/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # registrar module makefile
 #
diff --git a/modules/ims_registrar_pcscf/async_reginfo.c b/modules/ims_registrar_pcscf/async_reginfo.c
index fe34164..c037f74 100644
--- a/modules/ims_registrar_pcscf/async_reginfo.c
+++ b/modules/ims_registrar_pcscf/async_reginfo.c
@@ -45,11 +45,20 @@
 
 #include <time.h>
 #include "async_reginfo.h"
+#include "../pua/pua.h"
+#include "../pua/send_publish.h"
 
+#include "../pua/pua_bind.h"
+
+extern pua_api_t pua;
+extern int reginfo_queue_size_threshold;
 reginfo_event_list_t *reginfo_event_list = 0;
 
 int init_reginfo_event_list()
 {
+	if (reginfo_event_list)
+		return 1;
+
 	reginfo_event_list = shm_malloc(sizeof(reginfo_event_list_t));
 	if (!reginfo_event_list) {
 		LM_ERR("No more SHM mem\n");
@@ -62,6 +71,7 @@ int init_reginfo_event_list()
 		return 0;
 	}
 	reginfo_event_list->lock = lock_init(reginfo_event_list->lock);
+	reginfo_event_list->size = 0;
 
 	sem_new(reginfo_event_list->empty, 0); //pre-locked - as we assume list is empty at start
 
@@ -83,17 +93,132 @@ void destroy_reginfo_event_list()
 	shm_free(reginfo_event_list);
 }
 
-reginfo_event_t* new_reginfo_event (int event)
+reginfo_event_t* new_reginfo_event (int event, str *publ_body, str *publ_id, str *publ_content_type, str *subs_remote_target, str *subs_watcher_uri,
+	str *subs_contact, str *subs_outbound_proxy, int expires, int flag, int source_flag, int reg_info_event, str *extra_headers, str *pres_uri)
 {
-	reginfo_event_t *new_event = shm_malloc(sizeof(reginfo_event_t));
+	char *p;
+	int len;
+	reginfo_event_t *new_event;
+    
+	len = sizeof(reginfo_event_t);
+	if(publ_body){
+	    len += publ_body->len;
+	}
+	if(publ_id){
+	    len += publ_id->len;
+	}
+	if(publ_content_type){
+	    len += publ_content_type->len;
+	}
+	if(subs_remote_target){
+	    len += subs_remote_target->len;
+	}
+	if(subs_watcher_uri){
+	    len += subs_watcher_uri->len;
+	}
+	if(subs_contact){
+	    len += subs_contact->len;
+	}
+	if(subs_outbound_proxy){
+	    len += subs_outbound_proxy->len;
+	}
+	if(extra_headers){
+	    len += extra_headers->len;
+	}
+	if(pres_uri){
+	    len += pres_uri->len;
+	}
+	
+	LM_DBG("Shm alloc'ing %d for new reg info event\n", len);
+	new_event = (reginfo_event_t*) shm_malloc(len);
+	
 	if (!new_event) {
 		LM_ERR("No more shm mem\n");
 		return NULL;
 	}
+	memset(new_event, 0, len);
+	
+	p = (char*) (new_event + 1);
+
+	if(publ_body) {
+	    LM_DBG("publ_body [%.*s]\n", publ_body->len, publ_body->s);
+	    new_event->publ_body.s = p;
+	    new_event->publ_body.len = publ_body->len;
+	    memcpy(p, publ_body->s, publ_body->len);
+	    p += publ_body->len;
+	}
+	if(publ_id) {
+	    LM_DBG("publ_id [%.*s]\n", publ_id->len, publ_id->s);
+	    new_event->publ_id.s = p;
+	    new_event->publ_id.len = publ_id->len;
+	    memcpy(p, publ_id->s, publ_id->len);
+	    p += publ_id->len;
+	}
+	if(publ_content_type) {
+	    LM_DBG("publ_content_type [%.*s]\n", publ_content_type->len, publ_content_type->s);
+	    new_event->publ_content_type.s = p;
+	    new_event->publ_content_type.len = publ_content_type->len;
+	    memcpy(p, publ_content_type->s, publ_content_type->len);
+	    p += publ_content_type->len;
+	}
+	if(subs_remote_target) {
+	    LM_DBG("subs_remote_target [%.*s]\n", subs_remote_target->len, subs_remote_target->s);
+	    new_event->subs_remote_target.s = p;
+	    new_event->subs_remote_target.len = subs_remote_target->len;
+	    memcpy(p, subs_remote_target->s, subs_remote_target->len);
+	    p += subs_remote_target->len;
+	}
+	if(subs_watcher_uri) {
+	    LM_DBG("subs_watcher_uri [%.*s]\n", subs_watcher_uri->len, subs_watcher_uri->s);
+	    new_event->subs_watcher_uri.s = p;
+	    new_event->subs_watcher_uri.len = subs_watcher_uri->len;
+	    memcpy(p, subs_watcher_uri->s, subs_watcher_uri->len);
+	    p += subs_watcher_uri->len;
+	}
+	if(subs_contact) {
+	    LM_DBG("subs_contact [%.*s]\n", subs_contact->len, subs_contact->s);
+	    new_event->subs_contact.s = p;
+	    new_event->subs_contact.len = subs_contact->len;
+	    memcpy(p, subs_contact->s, subs_contact->len);
+	    p += subs_contact->len;
+	}
+	if(subs_outbound_proxy) {
+	    LM_DBG("subs_outbound_proxy [%.*s]\n", subs_outbound_proxy->len, subs_outbound_proxy->s);
+	    new_event->subs_outbound_proxy.s = p;
+	    new_event->subs_outbound_proxy.len = subs_outbound_proxy->len;
+	    memcpy(p, subs_outbound_proxy->s, subs_outbound_proxy->len);
+	    p += subs_outbound_proxy->len;
+	}
+	if(extra_headers) {
+	    LM_DBG("extra_headers [%.*s]\n", extra_headers->len, extra_headers->s);
+	    new_event->extra_headers.s = p;
+	    new_event->extra_headers.len = extra_headers->len;
+	    memcpy(p, extra_headers->s, extra_headers->len);
+	    p += extra_headers->len;
+	}
+	if(pres_uri) {
+	    LM_DBG("pres_uri [%.*s]\n", pres_uri->len, pres_uri->s);
+	    new_event->pres_uri.s = p;
+	    new_event->pres_uri.len = pres_uri->len;
+	    memcpy(p, pres_uri->s, pres_uri->len);
+	    p += pres_uri->len;
+	}
+		
+	if (p != (((char*) new_event) + len)) {
+	    LM_CRIT("buffer overflow\n");
+	    shm_free(new_event);
+	    return 0;
+	}
+	
+	new_event->expires = expires;
+	new_event->flag = flag;
+	new_event->reg_info_event = reg_info_event;
+	new_event->sourge_flag = source_flag;
+	
 	new_event->registered = time(NULL);
 	new_event->event = event;
 	new_event->next = 0;
-
+	
 	return new_event;
 }
 
@@ -106,6 +231,12 @@ void push_reginfo_event(reginfo_event_t* event)
 		reginfo_event_list->tail->next = event;
 		reginfo_event_list->tail = event;
 	}
+	reginfo_event_list->size++;
+	
+	if(reginfo_queue_size_threshold > 0 && reginfo_event_list->size > reginfo_queue_size_threshold) {
+	    LM_WARN("Reginfo queue is size [%d] and has exceed reginfo_queue_size_threshold of [%d]", reginfo_event_list->size, reginfo_queue_size_threshold);
+	}
+	
 	sem_release(reginfo_event_list->empty);
 	lock_release(reginfo_event_list->lock);
 }
@@ -114,6 +245,9 @@ reginfo_event_t* pop_reginfo_event()
 {
 	reginfo_event_t *ev;
 
+	// Make sure, it's initialized:
+	init_reginfo_event_list();
+
 	lock_get(reginfo_event_list->lock);
 	while (reginfo_event_list->head == 0) {
 		lock_release(reginfo_event_list->lock);
@@ -128,6 +262,9 @@ reginfo_event_t* pop_reginfo_event()
 		reginfo_event_list->tail = 0;
 	}
 	ev->next = 0; //make sure whoever gets this cant access our list
+	
+	reginfo_event_list->size--;
+	
 	lock_release(reginfo_event_list->lock);
 
 	return ev;
@@ -143,18 +280,75 @@ void free_reginfo_event(reginfo_event_t* ev)
 
 void reginfo_event_process()
 {
+    	publ_info_t publ;
+	subs_info_t subs;
 	reginfo_event_t *ev;
 	for (;;) {
-			LM_DBG("POPPING REGINFO EVENT\n");
+		LM_DBG("POPPING REGINFO EVENT\n");
 	        ev = pop_reginfo_event();
 	        LM_DBG("PROCESSING REGINFO EVENT with event [%d]\n", ev->event);
 
 	        switch (ev->event) {
 	        case REG_EVENT_PUBLISH:
-	        	LM_DBG("Sending out-of-band publish\n");
+	        	LM_DBG("Sending out-of-band publish with pres_uri [%.*s] publ_id [%.*s] publ_content_type [%.*s] extra_headers [%.*s]"
+				"expires [%d] event [%d]\n",
+				ev->pres_uri.len, ev->pres_uri.s, ev->publ_id.len, ev->publ_id.s, ev->publ_content_type.len, ev->publ_content_type.s,
+				ev->extra_headers.len, ev->extra_headers.s, ev->expires, ev->reg_info_event);
+			LM_DBG("publ_body [%.*s] \n",
+				ev->publ_body.len, ev->publ_body.s);
+			
+			memset(&publ, 0, sizeof(publ_info_t));
+			publ.pres_uri = &ev->pres_uri;
+			publ.body = &ev->publ_body;
+			publ.id = ev->publ_id;
+			publ.content_type = ev->publ_content_type;
+			publ.expires = ev->expires;
+
+			/* make UPDATE_TYPE, as if this "publish dialog" is not found
+			 by pua it will fallback to INSERT_TYPE anyway */
+			publ.flag |= ev->flag;
+			publ.source_flag |= ev->sourge_flag;
+			publ.event |= ev->reg_info_event;
+			publ.extra_headers = &ev->extra_headers;
+
+			if (pua.send_publish(&publ) < 0) {
+				LM_ERR("Error while sending publish\n");
+			}
 	        	break;
 	        case REG_EVENT_SUBSCRIBE:
-	        	LM_DBG("Sending out-of-band subscribe\n");
+	        	memset(&subs, 0, sizeof(subs_info_t));
+
+			subs.remote_target = &ev->subs_remote_target;
+			subs.pres_uri= &ev->pres_uri;
+			subs.watcher_uri= &ev->subs_watcher_uri;
+			subs.expires = ev->expires;
+
+			subs.source_flag= ev->sourge_flag;
+			subs.event= ev->reg_info_event;
+			subs.contact= &ev->subs_contact;
+			subs.extra_headers = &ev->extra_headers;
+
+			if(ev->subs_outbound_proxy.s) {
+			    subs.outbound_proxy= &ev->subs_outbound_proxy;
+			}
+
+			subs.flag|= ev->flag;
+			
+			
+			LM_DBG("Sending out-of-band subscribe with remote_target [%.*s] pres_uri [%.*s] subs_watcher_uri [%.*s] subs_contact [%.*s] extra_headers [%.*s] "
+				"expires [%d] event [%d] flag [%d] source_flag [%d]\n",
+				subs.remote_target->len, subs.remote_target->s, subs.pres_uri->len, subs.pres_uri->s, subs.watcher_uri->len, subs.watcher_uri->s,
+				subs.contact->len, subs.contact->s, subs.extra_headers->len, subs.extra_headers->s, subs.expires, subs.event, subs.flag, subs.source_flag);
+			if(subs.outbound_proxy) {
+			    LM_DBG("subs_outbound_proxy [%.*s]\n",
+				subs.outbound_proxy->len, subs.outbound_proxy->s);
+			}
+			
+
+			if(pua.send_subscribe(&subs)< 0) {
+				LM_ERR("while sending subscribe\n");
+			}
+			
 	        	break;
 	        default:
 	        	LM_ERR("Unknown REG event.....ignoring\n");
diff --git a/modules/ims_registrar_pcscf/async_reginfo.h b/modules/ims_registrar_pcscf/async_reginfo.h
index 0db662c..dcae1b5 100644
--- a/modules/ims_registrar_pcscf/async_reginfo.h
+++ b/modules/ims_registrar_pcscf/async_reginfo.h
@@ -56,10 +56,24 @@
 typedef struct _reginfo_event{
 	int event;							/* event id */
 	time_t registered;					/* time event was added to list - useful if we want to report on things that have taken too long to process */
+	str publ_body;
+	str publ_id;
+	str publ_content_type;
+	str subs_remote_target;
+	str subs_watcher_uri;
+	str subs_contact;
+	str subs_outbound_proxy;
+	int expires;
+	int flag;
+	int sourge_flag;
+	int reg_info_event;
+	str extra_headers;
+	str pres_uri;
 	struct _reginfo_event *next;
 } reginfo_event_t;
 
 typedef struct {
+	int size;
 	gen_lock_t *lock;
 	reginfo_event_t *head;
 	reginfo_event_t *tail;
@@ -70,7 +84,8 @@ typedef struct {
 int init_reginfo_event_list();
 void destroy_reginfo_event_list();
 
-reginfo_event_t* new_reginfo_event (int event); 			/*create new event*/
+reginfo_event_t* new_reginfo_event (int event, str *publ_body, str *publ_id, str *publ_content_type, str *subs_remote_target, str *subs_watcher_uri,
+	str *subs_contact, str *subs_outbound_proxy, int expires, int flag, int source_flag, int reg_info_event, str *extra_headers, str *pres_uri);
 void push_reginfo_event(reginfo_event_t* event);	/*add event to stack*/
 reginfo_event_t* pop_reginfo_event();				/*pop next (head) event off list*/
 void free_reginfo_event(reginfo_event_t*);			/*free memory allocated for event*/
diff --git a/modules/ims_registrar_pcscf/lookup.c b/modules/ims_registrar_pcscf/lookup.c
index aefddda..b0f7ae2 100644
--- a/modules/ims_registrar_pcscf/lookup.c
+++ b/modules/ims_registrar_pcscf/lookup.c
@@ -59,6 +59,7 @@ int lookup_transport(struct sip_msg* _m, udomain_t* _d, str* _uri) {
     str uri;
     pcontact_t* pcontact;
     char tmp[MAX_URI_SIZE];
+    str received_host = {0,0};
     str tmp_s;
     int ret = 1;
 
@@ -66,8 +67,8 @@ int lookup_transport(struct sip_msg* _m, udomain_t* _d, str* _uri) {
     else uri = _m->first_line.u.request.uri;
 
     //now lookup in usrloc
-    ul.lock_udomain(_d, &uri);
-    if (ul.get_pcontact(_d, &uri, &pcontact) != 0) { //need to insert new contact
+    ul.lock_udomain(_d, &uri, &received_host, _m->rcv.src_port);
+    if (ul.get_pcontact(_d, &uri, &received_host, _m->rcv.src_port, &pcontact) != 0) { //need to insert new contact
 	LM_WARN("received request for contact that we don't know about\n");
 	ret = -1;
 	goto done;
@@ -100,7 +101,7 @@ int lookup_transport(struct sip_msg* _m, udomain_t* _d, str* _uri) {
     }
 	
 done:
-    ul.unlock_udomain(_d, &uri);
+    ul.unlock_udomain(_d, &uri, &received_host, _m->rcv.src_port);
     return ret;
 }
 
diff --git a/modules/ims_registrar_pcscf/notify.c b/modules/ims_registrar_pcscf/notify.c
index 50f781a..44089a9 100644
--- a/modules/ims_registrar_pcscf/notify.c
+++ b/modules/ims_registrar_pcscf/notify.c
@@ -76,7 +76,7 @@
 extern usrloc_api_t ul;
 extern time_t time_now;
 
-int process_contact(udomain_t * _d, int expires, str contact_uri, int contact_state) {
+int process_contact(udomain_t * _d, int expires, str contact_uri, str * received_host, int received_port, int contact_state) {
 	
 	pcontact_t* pcontact;
 	
@@ -102,9 +102,9 @@ int process_contact(udomain_t * _d, int expires, str contact_uri, int contact_st
 	ci.reg_state = PCONTACT_REGISTERED;
 	
 	
-	ul.lock_udomain(_d, &contact_uri);
+	ul.lock_udomain(_d, &contact_uri, received_host, received_port);
 	
-	if (ul.get_pcontact(_d, &contact_uri, &pcontact) != 0) { //contact does not exist
+	if (ul.get_pcontact(_d, &contact_uri, received_host, received_port, &pcontact) != 0) { //contact does not exist
 	    if (contact_state == STATE_TERMINATED) {
 		LM_DBG("This contact: <%.*s> is in state terminated and is not in usrloc, ignore\n", contact_uri.len, contact_uri.s);
 		ret = RESULT_CONTACTS_FOUND;
@@ -124,7 +124,7 @@ int process_contact(udomain_t * _d, int expires, str contact_uri, int contact_st
 		if (contact_state == STATE_TERMINATED) {
 			//delete contact
 			LM_DBG("This contact <%.*s> is in state terminated and is in usrloc so removing it from usrloc\n", contact_uri.len, contact_uri.s);
-			if (ul.delete_pcontact(_d, &contact_uri, pcontact) != 0) {
+			if (ul.delete_pcontact(_d, &contact_uri, received_host, received_port, pcontact) != 0) {
 				LM_DBG("failed to delete pcscf contact <%.*s> - not a problem this may have been removed by de registration", contact_uri.len, contact_uri.s);
 			}
 		}else {//state is active
@@ -143,7 +143,7 @@ int process_contact(udomain_t * _d, int expires, str contact_uri, int contact_st
 	}
 	
 done:	 
-	ul.unlock_udomain(_d, &contact_uri);
+	ul.unlock_udomain(_d, &contact_uri, received_host, received_port);
 	return ret;
 }
 
@@ -366,7 +366,7 @@ int process_body(struct sip_msg* msg, str notify_body, udomain_t * domain) {
 					contact_uri.len, contact_uri.s);
 
 				/* Add to Usrloc: */
-				result = process_contact(domain, expires, contact_uri, contact_state);
+				result = process_contact(domain, expires, contact_uri, 0/*we don't have the recv ip*/, 0 /*we don't have the recv port*/, contact_state);
 
 				/* Process the result */
 				if (final_result != RESULT_CONTACTS_FOUND) final_result = result;
diff --git a/modules/ims_registrar_pcscf/reg_mod.c b/modules/ims_registrar_pcscf/reg_mod.c
index a987a04..874dad0 100644
--- a/modules/ims_registrar_pcscf/reg_mod.c
+++ b/modules/ims_registrar_pcscf/reg_mod.c
@@ -58,16 +58,18 @@
 #include "../../lib/kcore/statistics.h"
 #include "../../modules/sl/sl.h"
 #include "../../mod_fix.h"
+#include "../../cfg/cfg_struct.h"
 
 /* Bindings to PUA */
 #include "../pua/pua_bind.h"
 #include "notify.h"
 
+#include "async_reginfo.h"
+
 #include "reg_mod.h"
 #include "save.h"
 #include "service_routes.h"
 #include "lookup.h"
-
 MODULE_VERSION
 
 usrloc_api_t ul;						/**!< Structure containing pointers to usrloc functions*/
@@ -92,6 +94,7 @@ unsigned int pending_reg_expires = 30;			/**!< parameter for expiry time of a pe
 
 int is_registered_fallback2ip = 0;
 
+int reginfo_queue_size_threshold = 0;    /**Threshold for size of reginfo queue after which a warning is logged */
 
 
 char* rcv_avp_param = 0;
@@ -119,11 +122,13 @@ static int w_lookup_transport(struct sip_msg* _m, char* _d, char* _uri);
 
 /*! \brief Fixup functions */
 static int domain_fixup(void** param, int param_no);
+static int domain_uri_fixup(void** param, int param_no);
 static int save_fixup2(void** param, int param_no);
 static int assert_identity_fixup(void ** param, int param_no);
 
 /* Pseudo-Variables */
 static int pv_get_asserted_identity_f(struct sip_msg *, pv_param_t *, pv_value_t *);
+static int pv_get_registration_contact_f(struct sip_msg *, pv_param_t *, pv_value_t *);
 
 /**
  * Update the time.
@@ -137,15 +142,16 @@ inline void pcscf_act_time()
  * Exported functions
  */
 static cmd_export_t cmds[] = {
-	{"pcscf_save",     		(cmd_function)w_save,                   1,  	save_fixup2,            0,		ONREPLY_ROUTE },
-	{"pcscf_save_pending",          (cmd_function)w_save_pending,       	1,  	save_fixup2,            0,		REQUEST_ROUTE },
-	{"pcscf_follows_service_routes",(cmd_function)w_follows_service_routes, 1,  	save_fixup2,            0,		REQUEST_ROUTE },
-	{"pcscf_force_service_routes",  (cmd_function)w_force_service_routes,   1,  	save_fixup2,            0,		REQUEST_ROUTE },
-	{"pcscf_is_registered",         (cmd_function)w_is_registered,          1,  	save_fixup2,            0,		REQUEST_ROUTE|ONREPLY_ROUTE },
-	{"pcscf_assert_identity",       (cmd_function)w_assert_identity,        2,  	assert_identity_fixup,  0,		REQUEST_ROUTE },
-	{"pcscf_assert_called_identity",(cmd_function)w_assert_called_identity, 1,  assert_identity_fixup,  0,		ONREPLY_ROUTE },
-	{"reginfo_handle_notify",       (cmd_function)w_reginfo_handle_notify,  1,      domain_fixup,           0,              REQUEST_ROUTE},
-        {"lookup_transport",		(cmd_function)w_lookup_transport,                 1,      domain_fixup,           0,              REQUEST_ROUTE|FAILURE_ROUTE},
+	{"pcscf_save",     		(cmd_function)w_save,                   1,  	save_fixup2,            0,ONREPLY_ROUTE },
+	{"pcscf_save_pending",          (cmd_function)w_save_pending,       	1,  	save_fixup2,            0,REQUEST_ROUTE },
+	{"pcscf_follows_service_routes",(cmd_function)w_follows_service_routes, 1,  	save_fixup2,            0,REQUEST_ROUTE },
+	{"pcscf_force_service_routes",  (cmd_function)w_force_service_routes,   1,  	save_fixup2,            0,REQUEST_ROUTE },
+	{"pcscf_is_registered",         (cmd_function)w_is_registered,          1,  	save_fixup2,            0,REQUEST_ROUTE|ONREPLY_ROUTE },
+	{"pcscf_assert_identity",       (cmd_function)w_assert_identity,        2,  	assert_identity_fixup,  0,REQUEST_ROUTE },
+	{"pcscf_assert_called_identity",(cmd_function)w_assert_called_identity, 1,      assert_identity_fixup,  0,ONREPLY_ROUTE },
+	{"reginfo_handle_notify",       (cmd_function)w_reginfo_handle_notify,  1,      domain_fixup,           0,REQUEST_ROUTE},
+        {"lookup_transport",		(cmd_function)w_lookup_transport,       1,      domain_fixup,           0,REQUEST_ROUTE|FAILURE_ROUTE},
+        {"lookup_transport",		(cmd_function)w_lookup_transport,       2,      domain_uri_fixup,        0,REQUEST_ROUTE|FAILURE_ROUTE},
 	
 	{0, 0, 0, 0, 0, 0}
 };
@@ -165,6 +171,7 @@ static param_export_t params[] = {
         {"ignore_contact_rxport_check", INT_PARAM, &ignore_contact_rxport_check         },
         {"ignore_reg_state",		INT_PARAM, &ignore_reg_state			},
 	{"force_icscf_uri",		PARAM_STR, &force_icscf_uri			},
+	{"reginfo_queue_size_threshold",	INT_PARAM, &reginfo_queue_size_threshold		},
 //	{"store_profile_dereg",	INT_PARAM, &store_data_on_dereg},
 	{0, 0, 0}
 };
@@ -179,6 +186,8 @@ stat_export_t mod_stats[] = {
 static pv_export_t mod_pvs[] = {
     {{"pcscf_asserted_identity", (sizeof("pcscf_asserted_identity")-1)}, /* The first identity of the contact. */
      PVT_OTHER, pv_get_asserted_identity_f, 0, 0, 0, 0, 0},
+    {{"pcscf_registration_contact", (sizeof("pcscf_registration_contact")-1)}, /* The contact used during REGISTER */
+     PVT_OTHER, pv_get_registration_contact_f, 0, 0, 0, 0, 0},
     {{0, 0}, 0, 0, 0, 0, 0, 0, 0}
 };
 
@@ -232,6 +241,9 @@ static int mod_init(void) {
 	bind_usrloc_t bind_usrloc;
 	bind_pua_t bind_pua;
 
+	/*register space for event processor*/
+	register_procs(1);
+	
 	if (!fix_parameters()) goto error;
 
 	/* bind the SL API */
@@ -284,6 +296,13 @@ static int mod_init(void) {
                        return -1;
                }
 	       LM_DBG("Successfully bound to PUA module\n");
+	       
+	       /*init cdb cb event list*/
+		if (!init_reginfo_event_list()) {
+		    LM_ERR("unable to initialise reginfo_event_list\n");
+		    return -1;
+		}
+	       LM_DBG("Successfully initialised reginfo_event_list\n");
        }
 
 	return 0;
@@ -299,6 +318,20 @@ static void mod_destroy(void)
 
 static int child_init(int rank)
 {
+    
+	LM_DBG("Initialization of module in child [%d] \n", rank);
+        if ((subscribe_to_reginfo == 1) && (rank == PROC_MAIN)) {
+	     LM_DBG("Creating RegInfo Event Processor process\n");
+	    int pid = fork_process(PROC_SIPINIT, "RegInfo Event Processor", 1);
+	    if (pid < 0)
+		return -1; //error
+	    if (pid == 0) {
+		if (cfg_child_init())
+		    return -1; //error
+		reginfo_event_process();
+	    }
+	}
+    
 	if (rank == PROC_MAIN || rank == PROC_TCP_MAIN)
 		return 0;
 	if (rank == 1) {
@@ -329,6 +362,23 @@ static int domain_fixup(void** param, int param_no)
 	return 0;
 }
 
+static int domain_uri_fixup(void** param, int param_no)
+{
+	udomain_t* d;
+
+	if (param_no == 1) {
+		if (ul.register_udomain((char*)*param, &d) < 0) {
+			LM_ERR("failed to register domain\n");
+			return E_UNSPEC;
+		}
+		*param = (void*)d;
+	} else {
+            fixup_var_pve_12(param, param_no);
+        }
+        
+	return 0;
+}
+
 /*! \brief
  * Fixup for "save" function - both domain and flags
  */
@@ -451,3 +501,16 @@ pv_get_asserted_identity_f(struct sip_msg *msg, pv_param_t *param,
 	if (ret_val != NULL) return pv_get_strval(msg, param, res, ret_val);
 	else return -1;
 }
+
+
+/*
+ * Get the asserted Identity for the current user
+ */
+static int
+pv_get_registration_contact_f(struct sip_msg *msg, pv_param_t *param,
+		  pv_value_t *res)
+{
+	str * ret_val = get_registration_contact(msg);
+	if (ret_val != NULL) return pv_get_strval(msg, param, res, ret_val);
+	else return -1;
+}
diff --git a/modules/ims_registrar_pcscf/save.c b/modules/ims_registrar_pcscf/save.c
index 311983e..6ee868e 100644
--- a/modules/ims_registrar_pcscf/save.c
+++ b/modules/ims_registrar_pcscf/save.c
@@ -179,8 +179,9 @@ static inline int update_contacts(struct sip_msg *req,struct sip_msg *rpl, udoma
 				// Set to default, if not set:
 				if (ci.received_port == 0) ci.received_port = 5060;
 
-				ul.lock_udomain(_d, &c->uri);
-				if (ul.get_pcontact(_d, &c->uri, &pcontact) != 0) { //need to insert new contact
+				
+				ul.lock_udomain(_d, &c->uri, &ci.received_host, ci.received_port);
+				if (ul.get_pcontact(_d, &c->uri, &ci.received_host, ci.received_port, &pcontact) != 0) { //need to insert new contact
 					if ((expires-local_time_now)<=0) { //remove contact - de-register
 						LM_DBG("This is a de-registration for contact <%.*s> but contact is not in usrloc - ignore\n", c->uri.len, c->uri.s);
 						goto next_contact;
@@ -200,7 +201,7 @@ static inline int update_contacts(struct sip_msg *req,struct sip_msg *rpl, udoma
 					LM_DBG("contact already exists and is in state (%d) : [%s]\n",pcontact->reg_state, reg_state_to_string(pcontact->reg_state));
 					if ((expires-local_time_now)<=0) { //remove contact - de-register
 						LM_DBG("This is a de-registration for contact <%.*s>\n", c->uri.len, c->uri.s);
-						if (ul.delete_pcontact(_d, &c->uri, pcontact) != 0) {
+						if (ul.delete_pcontact(_d, &c->uri, &ci.received_host, ci.received_port, pcontact) != 0) {
 							LM_ERR("failed to delete pcscf contact <%.*s>\n", c->uri.len, c->uri.s);
 						}
 					} else { //update contact
@@ -215,7 +216,7 @@ static inline int update_contacts(struct sip_msg *req,struct sip_msg *rpl, udoma
 					}
 				}
 next_contact:
-				ul.unlock_udomain(_d, &c->uri);
+				ul.unlock_udomain(_d, &c->uri, &ci.received_host, ci.received_port);
 			}
 	}
 	return 1;
@@ -304,8 +305,8 @@ int save_pending(struct sip_msg* _m, udomain_t* _d) {
 	if (ci.received_port == 0)
 		ci.received_port = 5060;
 
-	ul.lock_udomain(_d, &c->uri);
-	if (ul.get_pcontact(_d, &c->uri, &pcontact) != 0) { //need to insert new contact
+	ul.lock_udomain(_d, &c->uri, &ci.received_host, ci.received_port);
+	if (ul.get_pcontact(_d, &c->uri, &ci.received_host, ci.received_port, &pcontact) != 0) { //need to insert new contact
 		LM_DBG("Adding pending pcontact: <%.*s>\n", c->uri.len, c->uri.s);
 		if (ul.insert_pcontact(_d, &c->uri, &ci, &pcontact) != 0) {
 			LM_ERR("Failed inserting new pcontact\n");
@@ -316,7 +317,7 @@ int save_pending(struct sip_msg* _m, udomain_t* _d) {
 	} else { //contact already exists - update
 		LM_DBG("Contact already exists - not doing anything for now\n");
 	}
-	ul.unlock_udomain(_d, &c->uri);
+	ul.unlock_udomain(_d, &c->uri, &ci.received_host, ci.received_port);
 
 	return 1;
 
diff --git a/modules/ims_registrar_pcscf/service_routes.c b/modules/ims_registrar_pcscf/service_routes.c
index 1eef7f4..ca253ef 100644
--- a/modules/ims_registrar_pcscf/service_routes.c
+++ b/modules/ims_registrar_pcscf/service_routes.c
@@ -38,6 +38,7 @@ static pcontact_t * c = NULL;
 extern usrloc_api_t ul;
 extern int ignore_contact_rxport_check;
 static str * asserted_identity;
+static str * registration_contact;
 
 /*!
  * \brief Parse the message and find first occurrence of Route header field.
@@ -169,14 +170,14 @@ pcontact_t * getContactP(struct sip_msg* _m, udomain_t* _d) {
 	str received_host = {0, 0};
 	char srcip[50];	
 
+	received_host.len = ip_addr2sbuf(&_m->rcv.src_ip, srcip, sizeof(srcip));
+			received_host.s = srcip;
+			
 	if (_m->id != current_msg_id) {
 		current_msg_id = _m->id;
 		c = NULL;
 
 		if (is_registered_fallback2ip == 2) {
-			received_host.len = ip_addr2sbuf(&_m->rcv.src_ip, srcip, sizeof(srcip));
-			received_host.s = srcip;
-
 			LM_DBG("Searching in usrloc for %.*s:%i (Proto %i)\n",
 				received_host.len, received_host.s,
 				_m->rcv.src_port, _m->rcv.proto);
@@ -195,7 +196,7 @@ pcontact_t * getContactP(struct sip_msg* _m, udomain_t* _d) {
 
 			if (b && b->contacts) {
 				for (ct = b->contacts; ct; ct = ct->next) {
-					if (ul.get_pcontact(_d, &ct->uri, &c) == 0) {
+					if (ul.get_pcontact(_d, &ct->uri, &received_host, _m->rcv.src_port, &c) == 0) {
 						if (checkcontact(_m, c) != 0) {
 							c = NULL;
 						} else {
@@ -222,7 +223,9 @@ pcontact_t * getContactP(struct sip_msg* _m, udomain_t* _d) {
 		}
 	}
 	asserted_identity = NULL;
+	registration_contact = NULL;
 	if (c) {
+		registration_contact = &c->contact_user;
 		p = c->head;
 		while (p) {
 			if (p->is_default == 1)
@@ -276,6 +279,8 @@ int check_service_routes(struct sip_msg* _m, udomain_t* _d) {
 	int i;
 	struct hdr_field *hdr;
 	rr_t *r;
+	char srcip[20];
+	str received_host;
 	pcontact_t * c = getContactP(_m, _d);
 	/* Contact not found => not following service-routes */
 	if (c == NULL) return -1;
@@ -285,8 +290,11 @@ int check_service_routes(struct sip_msg* _m, udomain_t* _d) {
 
 	LM_DBG("Got %i Route-Headers.\n", c->num_service_routes);
 
+	received_host.len = ip_addr2sbuf(&_m->rcv.src_ip, srcip, sizeof(srcip));
+	received_host.s = srcip;
+	
 	/* Lock this record while working with the data: */
-	ul.lock_udomain(_d, &c->aor);
+	ul.lock_udomain(_d, &c->aor, &received_host, _m->rcv.src_port);
 
 	/* Check the route-set: */
 	if (_m->route) {
@@ -315,7 +323,7 @@ int check_service_routes(struct sip_msg* _m, udomain_t* _d) {
 				if (r)
 					LM_DBG("Next Route is %.*s\n", r->nameaddr.uri.len, r->nameaddr.uri.s);
 			}
-			LM_DBG("We have %d service-routes\n");
+			LM_DBG("We have %d service-routes\n", c->num_service_routes);
 			/* Then check the following headers: */
 			for (i=0; i< c->num_service_routes; i++) {
 				LM_DBG("Route must be: %.*s\n", c->service_routes[i].len, c->service_routes[i].s);
@@ -358,11 +366,11 @@ int check_service_routes(struct sip_msg* _m, udomain_t* _d) {
 		if (c->num_service_routes > 0) goto error;
 	}
 	/* Unlock domain */
-	ul.unlock_udomain(_d, &c->aor);
+	ul.unlock_udomain(_d, &c->aor, &received_host, _m->rcv.src_port);
 	return 1;
 error:
 	/* Unlock domain */
-	ul.unlock_udomain(_d, &c->aor);
+	ul.unlock_udomain(_d, &c->aor, &received_host, _m->rcv.src_port);
 	return -1;
 }
 
@@ -380,6 +388,8 @@ int force_service_routes(struct sip_msg* _m, udomain_t* _d) {
 	struct lump* lmp = NULL;
 	char * buf;
 	pcontact_t * c = getContactP(_m, _d);
+	char srcip[20];
+	str received_host;
 	
 	// Contact not found => not following service-routes
 	if (c == NULL) return -1;
@@ -408,9 +418,12 @@ int force_service_routes(struct sip_msg* _m, udomain_t* _d) {
 		_m->dst_uri.s = NULL;
 		_m->dst_uri.len = 0;
 	}
+	
+	received_host.len = ip_addr2sbuf(&_m->rcv.src_ip, srcip, sizeof(srcip));
+	received_host.s = srcip;
 
 	/* Lock this record while working with the data: */
-	ul.lock_udomain(_d, &c->aor);
+	ul.lock_udomain(_d, &c->aor, &received_host, _m->rcv.src_port);
 
 	if (c->num_service_routes > 0) {
 		/* Create anchor for new Route-Header: */
@@ -458,11 +471,11 @@ int force_service_routes(struct sip_msg* _m, udomain_t* _d) {
 		}
 	}
 	/* Unlock domain */
-	ul.unlock_udomain(_d, &c->aor);
+	ul.unlock_udomain(_d, &c->aor, &received_host, _m->rcv.src_port);
 	return 1;
 error:
 	/* Unlock domain */
-	ul.unlock_udomain(_d, &c->aor);
+	ul.unlock_udomain(_d, &c->aor, &received_host, _m->rcv.src_port);
 	return -1;
 	
 }
@@ -485,6 +498,18 @@ str * get_asserted_identity(struct sip_msg* _m) {
 	} else return asserted_identity;
 }
 
+
+/**
+ * Get the contact used during registration of this user
+ */
+str * get_registration_contact(struct sip_msg* _m) {
+	if (_m->id != current_msg_id) {
+		LM_ERR("Unable to get contact used during registration: Please call is_registered first!\n");
+		return NULL;
+	} else return registration_contact;
+}
+
+
 /**
  * checked if passed identity is an asserted identity
  */
@@ -511,7 +536,7 @@ int assert_identity(struct sip_msg* _m, udomain_t* _d, str identity) {
 			    } else LM_DBG("Length does not match.\n");
 			}
 		}
-	LM_WARN("Contact not found based on Contact, trying IP/Port/Proto\n");
+	LM_INFO("Contact not found based on Contact, trying IP/Port/Proto\n");
 	str received_host = {0, 0};
 	char srcip[50];	
 	
diff --git a/modules/ims_registrar_pcscf/service_routes.h b/modules/ims_registrar_pcscf/service_routes.h
index c7daf8f..c7887f5 100644
--- a/modules/ims_registrar_pcscf/service_routes.h
+++ b/modules/ims_registrar_pcscf/service_routes.h
@@ -47,6 +47,11 @@ int is_registered(struct sip_msg* _m, udomain_t* _d);
 str * get_asserted_identity(struct sip_msg* _m);
 
 /**
+ * Get the contact used during registration of this user
+ */
+str * get_registration_contact(struct sip_msg* _m);
+
+/**
  * Assert a given identity of a user
  */
 int assert_identity(struct sip_msg* _m, udomain_t* _d, str identity);
diff --git a/modules/ims_registrar_pcscf/subscribe.c b/modules/ims_registrar_pcscf/subscribe.c
index 9c859df..68f788f 100644
--- a/modules/ims_registrar_pcscf/subscribe.c
+++ b/modules/ims_registrar_pcscf/subscribe.c
@@ -32,6 +32,7 @@
 #include "../pua/pua.h"
 
 #include "../pua/pua_bind.h"
+#include "async_reginfo.h"
 
 
 extern pua_api_t pua;
@@ -44,14 +45,16 @@ int reginfo_subscribe_real(struct sip_msg* msg, pv_elem_t* uri, str* service_rou
 	str uri_str = {0, 0};
 	char uri_buf[512];
 	int uri_buf_len = 512;
-	subs_info_t subs;
+	//subs_info_t subs;
 	str p_asserted_identity_header;
+	reginfo_event_t *new_event;
+	str *subs_outbound_proxy = 0;
 	
 	int len = strlen(P_ASSERTED_IDENTITY_HDR_PREFIX) + pcscf_uri.len + 1 + CRLF_LEN;
 	p_asserted_identity_header.s = (char *)pkg_malloc( len );
 	if ( p_asserted_identity_header.s == NULL ) {
 	    LM_ERR( "insert_asserted_identity: pkg_malloc %d bytes failed", len );
-	    return -1;
+	    goto error;
 	}
 
 	memcpy(p_asserted_identity_header.s, P_ASSERTED_IDENTITY_HDR_PREFIX, strlen(P_ASSERTED_IDENTITY_HDR_PREFIX));
@@ -64,11 +67,8 @@ int reginfo_subscribe_real(struct sip_msg* msg, pv_elem_t* uri, str* service_rou
 	p_asserted_identity_header.len += CRLF_LEN;
 	
 	if (pv_printf(msg, uri, uri_buf, &uri_buf_len) < 0) {
-		LM_ERR("cannot print uri into the format\n");
-		if (p_asserted_identity_header.s) {
-                    pkg_free(p_asserted_identity_header.s);
-                }
-		return -1;
+	    LM_ERR("cannot print uri into the format\n");
+	    goto error;
 	}
 	uri_str.s = uri_buf;
 	uri_str.len = uri_buf_len;
@@ -77,34 +77,31 @@ int reginfo_subscribe_real(struct sip_msg* msg, pv_elem_t* uri, str* service_rou
 
 	LM_DBG("Subscribing to %.*s\n", uri_str.len, uri_str.s);
 
-	memset(&subs, 0, sizeof(subs_info_t));
-
-	subs.remote_target = &uri_str;
-	subs.pres_uri= &uri_str;
-	subs.watcher_uri= &pcscf_uri;
-	subs.expires = expires;
-
-	subs.source_flag= REGINFO_SUBSCRIBE;
-	subs.event= REGINFO_EVENT;
-	subs.contact= &pcscf_uri;
-	subs.extra_headers = &p_asserted_identity_header;
-	
 	if(force_icscf_uri.s && force_icscf_uri.len) {
-	    subs.outbound_proxy= &force_icscf_uri;
+	    subs_outbound_proxy= &force_icscf_uri;
 	}
 	
-	subs.flag|= UPDATE_TYPE;
+	new_event = new_reginfo_event(REG_EVENT_SUBSCRIBE, 0, 0, 0, &uri_str, &pcscf_uri, &pcscf_uri,
+	subs_outbound_proxy, expires, UPDATE_TYPE, REGINFO_SUBSCRIBE, REGINFO_EVENT, &p_asserted_identity_header, &uri_str);
 	
-	if(pua.send_subscribe(&subs)< 0) {
-		LM_ERR("while sending subscribe\n");
-	}	
+	if (!new_event) {
+            LM_ERR("Unable to create event for cdp callback\n");
+            goto error;
+        }
+        //push the new event onto the stack (FIFO)
+        push_reginfo_event(new_event);
 	
 	if (p_asserted_identity_header.s) {
 		pkg_free(p_asserted_identity_header.s);
 	}
 
 	return 1;
+	
+    error:
+    
+	if (p_asserted_identity_header.s) {
+		pkg_free(p_asserted_identity_header.s);
+	}
+	return -1;
+	
 }
-
-
-
diff --git a/modules/ims_registrar_pcscf/ul_callback.c b/modules/ims_registrar_pcscf/ul_callback.c
index 119f3c9..0691bf2 100644
--- a/modules/ims_registrar_pcscf/ul_callback.c
+++ b/modules/ims_registrar_pcscf/ul_callback.c
@@ -48,6 +48,7 @@
 #include "../pua/send_publish.h"
 
 #include "../pua/pua_bind.h"
+#include "async_reginfo.h"
 
 #include <libxml/parser.h>
 
@@ -185,12 +186,14 @@ error:
 #define P_ASSERTED_IDENTITY_HDR_PREFIX	"P-Asserted-Identity: <"
 int send_partial_publish(ppublic_t *impu, struct pcontact *c, int type)
 {
-	publ_info_t publ;
+	//publ_info_t publ;
 	str content_type;
 	int id_buf_len;
 	char id_buf[512];
 	str p_asserted_identity_header;
-
+	str publ_id;
+	reginfo_event_t *new_event;
+	
 	content_type.s = "application/reginfo+xml";
 	content_type.len = 23;
 	
@@ -220,30 +223,31 @@ int send_partial_publish(ppublic_t *impu, struct pcontact *c, int type)
 		goto error;
 	}
 	LM_DBG("XML-Body:\n%.*s\n", body->len, body->s);
-
-	memset(&publ, 0, sizeof(publ_info_t));
-	publ.pres_uri = &impu->public_identity;
-	publ.body = body;
+	
 	id_buf_len = snprintf(id_buf, sizeof(id_buf), "IMSPCSCF_PUBLISH.%.*s", c->aor.len, c->aor.s);
-	publ.id.s = id_buf;
-	publ.id.len = id_buf_len;
-	publ.content_type = content_type;
-	publ.expires = 3600;
-
-	/* make UPDATE_TYPE, as if this "publish dialog" is not found
-	 by pua it will fallback to INSERT_TYPE anyway */
-	publ.flag |= UPDATE_TYPE;
-	publ.source_flag |= REGINFO_PUBLISH;
-	publ.event |= REGINFO_EVENT;
-	publ.extra_headers = &p_asserted_identity_header;
-
-	if (pua.send_publish(&publ) < 0) {
-		LM_ERR("Error while sending publish\n");
-	}
+	publ_id.s = id_buf;
+	publ_id.len = id_buf_len;
+
+	new_event = new_reginfo_event(REG_EVENT_PUBLISH, body, &publ_id, &content_type, 0, 0,
+	0, 0, 3600, UPDATE_TYPE, REGINFO_PUBLISH, REGINFO_EVENT, &p_asserted_identity_header, &impu->public_identity);
+	
+	if (!new_event) {
+            LM_ERR("Unable to create event for cdp callback\n");
+            goto error;
+        }
+        //push the new event onto the stack (FIFO)
+        push_reginfo_event(new_event);
+	
 	if (p_asserted_identity_header.s) {
 		pkg_free(p_asserted_identity_header.s);
 	}
 	
+	if (body) {
+		if (body->s)
+			xmlFree(body->s);
+		pkg_free(body);
+	}
+	
 	return 1;
 
 error:
diff --git a/modules/ims_registrar_scscf/Makefile b/modules/ims_registrar_scscf/Makefile
index 0123c73..fc37819 100644
--- a/modules/ims_registrar_scscf/Makefile
+++ b/modules/ims_registrar_scscf/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # registrar module makefile
 #
@@ -27,4 +26,10 @@ DEFS+=-DOPENSER_MOD_INTERFACE
 SERLIBPATH=../../lib
 SER_LIBS+=$(SERLIBPATH)/kcore/kcore
 SER_LIBS+=$(SERLIBPATH)/ims/kamailio_ims
+
+ifneq ($(OS),darwin)
+	LIBS += -lrt
+	LIBS += -lpthread
+endif
+
 include ../../Makefile.modules
diff --git a/modules/ims_registrar_scscf/cxdx_avp.c b/modules/ims_registrar_scscf/cxdx_avp.c
index e4f912a..ab9490a 100644
--- a/modules/ims_registrar_scscf/cxdx_avp.c
+++ b/modules/ims_registrar_scscf/cxdx_avp.c
@@ -142,6 +142,17 @@ static inline str cxdx_get_avp(AAAMessage *msg,int avp_code,int vendor_id,
 		return avp->data;
 }
 
+inline int cxdx_add_call_id(AAAMessage *msg, str data) 
+{
+    return 
+	cxdx_add_avp(msg,data.s,data.len,
+		AVP_Call_Id,
+		AAA_AVP_FLAG_VENDOR_SPECIFIC,
+		50,
+		AVP_DUPLICATE_DATA,
+		__FUNCTION__);
+}
+
 /**
  * Creates and adds a Destination-Realm AVP.
  * @param msg - the Diameter message to add to.
diff --git a/modules/ims_registrar_scscf/cxdx_avp.h b/modules/ims_registrar_scscf/cxdx_avp.h
index d95bff4..842629b 100644
--- a/modules/ims_registrar_scscf/cxdx_avp.h
+++ b/modules/ims_registrar_scscf/cxdx_avp.h
@@ -53,6 +53,7 @@ struct AAAMessage;
 struct AAA_AVP;
 struct sip_msg;
 
+inline int cxdx_add_call_id(AAAMessage *msg, str data);
 /**
  * Creates and adds a Destination-Realm AVP.
  * @param msg - the Diameter message to add to.
diff --git a/modules/ims_registrar_scscf/cxdx_callbacks.c b/modules/ims_registrar_scscf/cxdx_callbacks.c
index f490524..7cfcbfa 100644
--- a/modules/ims_registrar_scscf/cxdx_callbacks.c
+++ b/modules/ims_registrar_scscf/cxdx_callbacks.c
@@ -23,6 +23,14 @@
 #include "cxdx_callbacks.h"
 #include "../../str.h"
 #include "../../dprint.h"
+#include "../ims_usrloc_scscf/usrloc.h"
+#include "cxdx_avp.h"
+
+
+extern struct cdp_binds cdpb;
+extern usrloc_api_t ul;
+
+extern char *domain;
 
 /*int PPR_RTR_Event(void *parsed_message, int type, void *param) {
 	if (type & CXDX_PPR_RECEIVED) {
@@ -35,3 +43,83 @@
 	}
 	return 0;
 }*/
+
+AAAMessage* cxdx_process_rtr(AAAMessage *rtr) {
+    LM_DBG("Processing RTR");
+    
+    AAAMessage *rta_msg;
+    AAA_AVP* avp;
+    str public_id;
+    impurecord_t* r;
+    int i = 0;
+    int res = 0;
+    udomain_t* udomain;
+    
+    rta_msg = cdpb.AAACreateResponse(rtr);//session ID?
+    if (!rta_msg) return 0;
+
+    avp = cxdx_get_next_public_identity(rtr,0,AVP_IMS_Public_Identity,IMS_vendor_id_3GPP,__FUNCTION__);	
+    if(avp==0){
+	    LM_WARN("RTR received with only IMPI (username AVP) - currently S-CSCF does not support this kind of RTR\n");
+	    return 0;
+	    //TODO add support for receiving RTR with IMPI
+	    //get all impus related to this impu
+	    //get all contacts related to each impu
+	    //set the contact expire for each contact to now
+    }else{
+	    public_id=avp->data;
+	    LM_DBG("RTR received with IMPU [%.*s] in public identity AVP - this is supported\n", public_id.len, public_id.s);
+
+	    //TODO this should be a configurable module param
+	    if (ul.register_udomain(domain, &udomain) < 0) {
+		LM_ERR("Unable to register usrloc domain....aborting\n");
+		return 0;
+	    }
+	    
+	    ul.lock_udomain(udomain, &public_id);
+            res = ul.get_impurecord(udomain, &public_id, &r);
+            if (res != 0) {
+                LM_WARN("Strange, '%.*s' Not found in usrloc\n", public_id.len, public_id.s);
+                ul.unlock_udomain(udomain, &public_id);
+                //no point in continuing
+                return 0;
+            }
+	    
+	    for(i = 0; i < r->num_contacts; i++) {
+		LM_DBG("Expiring contact with AOR [%.*s]\n", r->newcontacts[i]->aor.len, r->newcontacts[i]->aor.s);
+		ul.expire_ucontact(r, r->newcontacts[i]);
+	    }
+	    
+	    ul.unlock_udomain(udomain, &public_id);
+	    
+	    while(cdpb.AAAGetNextAVP(avp) && (avp=cxdx_get_next_public_identity(rtr,cdpb.AAAGetNextAVP(avp),AVP_IMS_Public_Identity,IMS_vendor_id_3GPP,__FUNCTION__))!=0){
+		    public_id=avp->data;
+		    LM_DBG("RTR also has public id [%.*s]\n", public_id.len, public_id.s);
+		    ul.lock_udomain(udomain, &public_id);
+		    res = ul.get_impurecord(udomain, &public_id, &r);
+		    if (res != 0) {
+			LM_WARN("Strange, '%.*s' Not found in usrloc\n", public_id.len, public_id.s);
+			ul.unlock_udomain(udomain, &public_id);
+			//no point in continuing
+			return 0;
+		    }
+
+		    for(i = 0; i < r->num_contacts; i++) {
+			LM_DBG("Expiring contact with AOR [%.*s]\n", r->newcontacts[i]->aor.len, r->newcontacts[i]->aor.s);
+			ul.expire_ucontact(r, r->newcontacts[i]);
+		    }
+
+		    ul.unlock_udomain(udomain, &public_id);
+		}		
+    }
+    cxdx_add_vendor_specific_appid(rta_msg,IMS_vendor_id_3GPP,IMS_Cx,0 /*IMS_Cx*/);
+    
+    cxdx_add_auth_session_state(rta_msg,1);		
+
+    /* send an RTA back to the HSS */
+    cxdx_add_result_code(rta_msg,DIAMETER_SUCCESS);
+    
+    return rta_msg;
+    
+    
+}
diff --git a/modules/ims_registrar_scscf/cxdx_callbacks.h b/modules/ims_registrar_scscf/cxdx_callbacks.h
index 6750a41..9b47976 100644
--- a/modules/ims_registrar_scscf/cxdx_callbacks.h
+++ b/modules/ims_registrar_scscf/cxdx_callbacks.h
@@ -23,9 +23,12 @@
 #ifndef CXDX_CALLBACKS_H
 #define CXDX_CALLBACKS_H
 
+#include "../cdp/cdp_load.h"
 /**
  * Check, if a user-agent follows the indicated service-routes
  */
 int PPR_RTR_Event(void *parsed_message, int type, void *param);
 
+AAAMessage* cxdx_process_rtr(AAAMessage *request);
+
 #endif /* CXDX_CALLBACKS_H */
diff --git a/modules/ims_registrar_scscf/cxdx_sar.c b/modules/ims_registrar_scscf/cxdx_sar.c
index 24991d2..4e97fe0 100644
--- a/modules/ims_registrar_scscf/cxdx_sar.c
+++ b/modules/ims_registrar_scscf/cxdx_sar.c
@@ -61,6 +61,10 @@
 #include "../../data_lump_rpl.h"
 #include "sip_msg.h"
 #include "regtime.h"
+#include "../../parser/hf.h"
+#include "../../lib/ims/ims_getters.h"
+
+extern struct cdp_binds cdpb;
 
 int create_return_code(int result) {
     int rc;
@@ -310,6 +314,7 @@ int cxdx_send_sar(struct sip_msg *msg, str public_identity, str private_identity
     AAAMessage *sar = 0;
     AAASession *session = 0;
     unsigned int hash = 0, label = 0;
+    struct hdr_field *hdr;
 
     session = cdpb.AAACreateSession(0);
 
@@ -320,6 +325,7 @@ int cxdx_send_sar(struct sip_msg *msg, str public_identity, str private_identity
     }
     if (!sar) goto error1;
 
+    if (!cxdx_add_call_id(sar, cscf_get_call_id(msg, &hdr)));
     if (!cxdx_add_destination_realm(sar, cxdx_dest_realm)) goto error1;
 
     if (!cxdx_add_vendor_specific_appid(sar, IMS_vendor_id_3GPP, IMS_Cx, 0 /*IMS_Cx*/)) goto error1;
diff --git a/modules/ims_registrar_scscf/doc/ims_registrar_scscf_admin.xml b/modules/ims_registrar_scscf/doc/ims_registrar_scscf_admin.xml
index d54561e..76a0f35 100644
--- a/modules/ims_registrar_scscf/doc/ims_registrar_scscf_admin.xml
+++ b/modules/ims_registrar_scscf/doc/ims_registrar_scscf_admin.xml
@@ -67,10 +67,9 @@
       contact parameters, this value will be used for newly created S-CSCF
       usrloc records. The parameter contains number of second to expire (for
       example use 3600 for one hour). If it is set to a lower value than the
-      “min_expires” parameter then it will be ignored. This
-      parameter can be modified via ser config framework. A random value in a
-      specific interval can be selected by using the default_expires_range
-      parameter</para>
+      min_expires parameter then it will be ignored. This parameter can be
+      modified via ser config framework. A random value in a specific interval
+      can be selected by using the default_expires_range parameter</para>
 
       <para><emphasis> Default value is 3600. </emphasis></para>
 
@@ -87,14 +86,13 @@
       <title>default_expires_range (int)</title>
 
       <para>This parameter specifies that the expiry used for newly created
-      S-CSCF usrloc records are not fixed(when “default_expires”
-      applies), but a random value in the interval
-      “[default_expires-default_expires_range%,
-      default_expires+default_expires_range%]”. The value is between 0
-      and 100 and represent the maximim percentage from default_expires that
-      will be substracted or added when computing the value. Default in 0,
-      meaning default_expires is left unmodified. This parameter can be
-      modified via ser config framework.</para>
+      S-CSCF usrloc records are not fixed(when default_expires applies), but a
+      random value in the intervalrdq [default_expires-default_expires_range%,
+      default_expires+default_expires_range%]. The value is between 0 and 100
+      and represent the maximim percentage from default_expires that will be
+      substracted or added when computing the value. Default in 0, meaning
+      default_expires is left unmodified. This parameter can be modified via
+      ser config framework.</para>
 
       <para><emphasis> Default value is 0. </emphasis></para>
 
@@ -146,6 +144,92 @@
     </section>
 
     <section>
+      <title>subscription_default_expires (int)</title>
+
+      <para>If the processed message contains neither Expires HFs nor expires
+      contact parameters, this value will be used for newly created
+      subscriptions. The parameter contains number of second to expire (for
+      example use 3600 for one hour). If it is set to a lower value than the
+      subscription_min_expires parameter then it will be ignored. A random
+      value in a specific interval can be selected by using the
+      subscription_expires_range parameter</para>
+
+      <para><emphasis> Default value is 3600. </emphasis></para>
+
+      <example>
+        <title>Set <varname>subscription_default_expires</varname>
+        parameter</title>
+
+        <programlisting format="linespecific">...
+        modparam("ims_registrar_scscf", "subscription_default_expires", 3600)
+...</programlisting>
+      </example>
+    </section>
+
+    <section>
+      <title>subscription_expires_range (int)</title>
+
+      <para>This parameter specifies that the expiry used for newly created
+      subscriptions are not fixed(when subscription_default_expires applies),
+      but a random value in the interval
+      [subscription_default_expires-subscription_expires_range%,
+      subscription_default_expires+subscription_expires_range%]. The value is
+      between 0 and 100 and represent the maximim percentage from
+      subscription_default_expires that will be substracted or added when
+      computing the value. Default in 0, meaning subscription_default_expires
+      is left unmodified.</para>
+
+      <para><emphasis> Default value is 0. </emphasis></para>
+
+      <example>
+        <title>Set <varname>subscription_expires_range
+        </varname>parameter</title>
+
+        <programlisting format="linespecific">...
+        modparam("ims_registrar_scscf", "subscription_expires_range", 30) # +- 30% from subscription_expires_range
+...</programlisting>
+      </example>
+    </section>
+
+    <section>
+      <title>subscription_min_expires (int)</title>
+
+      <para>The minimum expires value of a subscription, values lower than
+      this minimum will be automatically set to the minimum. Value 0 disables
+      the checking.</para>
+
+      <para><emphasis> Default value is 10. </emphasis></para>
+
+      <example>
+        <title>Set
+        <varname>subscription_min_expires</varname>parameter</title>
+
+        <programlisting format="linespecific">...
+        modparam("subscription_min_expires", "min_expires", 1800)
+...</programlisting>
+      </example>
+    </section>
+
+    <section>
+      <title>subscription_max_expires (int)</title>
+
+      <para>The maximum expires value of a subscription, values higher than
+      this maximum will be automatically set to the maximum. Value 0 disables
+      the checking.</para>
+
+      <para><emphasis> Default value is 1000000. </emphasis></para>
+
+      <example>
+        <title>Set
+        <varname>subscription_max_expires</varname>parameter</title>
+
+        <programlisting format="linespecific">...
+        modparam("ims_registrar_scscf", "subscription_max_expires", 3600)
+...</programlisting>
+      </example>
+    </section>
+
+    <section>
       <title>user_data_dtd (string)</title>
 
       <para>DTD to check the user data received in SAA (Server Assignment
@@ -305,6 +389,24 @@
 ...</programlisting>
       </example>
     </section>
+
+    <section>
+      <title>user_data_always (integer)</title>
+
+      <para>If specified this will make the S-CSCF always request user data
+      from HSS.</para>
+
+      <para><emphasis> Default value is 0 (disabled)</emphasis></para>
+
+      <example>
+        <title>Set <varname>user_data_always</varname>parameter</title>
+
+        <programlisting format="linespecific">...
+        modparam("ims_registrar_scscf", "user_data_always", 1)
+...
+	</programlisting>
+      </example>
+    </section>
   </section>
 
   <section>
@@ -414,6 +516,46 @@ switch ($retcode) {
     </section>
 
     <section>
+      <title><function
+      moreinfo="none">lookup_path_to_contact(uri)</function></title>
+
+      <para>This function take a URI and tries to find the contact in usrloc.
+      If the contact is found and has a path set, then a path header is added
+      to the SIP message so it can be loose routed.</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <para><itemizedlist>
+          <listitem>
+            <para>uri - URI of contact to lookup</para>
+          </listitem>
+        </itemizedlist></para>
+
+      <para>Return codes:</para>
+
+      <para><itemizedlist>
+          <listitem>
+            <para><emphasis>1</emphasis> - Success</para>
+          </listitem>
+
+          <listitem>
+            <para>-1 - Failure</para>
+          </listitem>
+        </itemizedlist></para>
+
+      <para>This function can be used from REQUEST_ROUTE, FAILURE_ROUTE</para>
+
+      <example>
+        <title><function>lookup</function> usage</title>
+
+        <programlisting format="linespecific">...
+lookup_path_to_contact($ruri);
+...
+</programlisting>
+      </example>
+    </section>
+
+    <section>
       <title><function moreinfo="none">unregister(domain)</function></title>
 
       <para>This function will remove all bindings for the IMPU found in the
diff --git a/modules/ims_registrar_scscf/lookup.c b/modules/ims_registrar_scscf/lookup.c
index 4da781d..a7075f7 100644
--- a/modules/ims_registrar_scscf/lookup.c
+++ b/modules/ims_registrar_scscf/lookup.c
@@ -52,129 +52,180 @@
 #define allowed_method(_msg, _c) \
 	( !method_filtering || ((_msg)->REQ_METHOD)&((_c)->methods) )
 
-
 /*! \brief
  * Lookup contact in the database and rewrite Request-URI
  * \return: -1 : not found
  *          -2 : found but method not allowed
  *          -3 : error
  */
-int lookup(struct sip_msg* _m, udomain_t* _d)
-{
-	impurecord_t* r;
-	str aor, uri;
-	ucontact_t* ptr;
-	int res;
-	int ret;
-	str path_dst;
-	flag_t old_bflags;
+int lookup(struct sip_msg* _m, udomain_t* _d) {
+    impurecord_t* r;
+    str aor;
+    ucontact_t* ptr;
+    int res;
+    int ret;
+    str path_dst;
+    flag_t old_bflags;
+    int i = 0;
+
+	if (!_m){
+		LM_ERR("NULL message!!!\n");
+		return -1;
+	}
 
+	if (_m->new_uri.s) aor = _m->new_uri;
+	else aor = _m->first_line.u.request.uri;
+	
+	for(i=0;i<aor.len;i++)
+		if (aor.s[i]==';' || aor.s[i]=='?') {
+			aor.len = i;
+			break;
+		}
 
-	if (_m->new_uri.s) uri = _m->new_uri;
-	else uri = _m->first_line.u.request.uri;
+	LM_DBG("Looking for <%.*s>\n",aor.len,aor.s);
+
+    get_act_time();
 
-	if (extract_aor(&uri, &aor) < 0) {
-		LM_ERR("failed to extract address of record\n");
-		return -3;
+    ul.lock_udomain(_d, &aor);
+    res = ul.get_impurecord(_d, &aor, &r);
+    if (res > 0) {
+	LM_DBG("'%.*s' Not found in usrloc\n", aor.len, ZSW(aor.s));
+	ul.unlock_udomain(_d, &aor);
+	return -1;
+    }
+    ret = -1;
+    i = 0;
+
+    while (i < MAX_CONTACTS_PER_IMPU && (ptr = r->newcontacts[i])) {
+	if (VALID_CONTACT(ptr, act_time) && allowed_method(_m, ptr)) {
+	    LM_DBG("Found a valid contact [%.*s]\n", ptr->c.len, ptr->c.s);
+	    i++;
+	    break;
+	}
+	i++;
+    }
+
+    /* look first for an un-expired and supported contact */
+    if (ptr == 0) {
+	LM_INFO("No contacts founds for IMPU <%.*s>\n",aor.len,aor.s);
+	/* nothing found */
+	goto done;
+    }
+
+    ret = 1;
+    if (ptr) {
+	if (rewrite_uri(_m, &ptr->c) < 0) {
+	    LM_ERR("unable to rewrite Request-URI\n");
+	    ret = -3;
+	    goto done;
 	}
 
-	get_act_time();
+	/* reset next hop address */
+	reset_dst_uri(_m);
 
-	ul.lock_udomain(_d, &aor);
-	res = ul.get_impurecord(_d, &aor, &r);
-	if (res > 0) {
-		LM_DBG("'%.*s' Not found in usrloc\n", aor.len, ZSW(aor.s));
-		ul.unlock_udomain(_d, &aor);
+	/* If a Path is present, use first path-uri in favour of
+	 * received-uri because in that case the last hop towards the uac
+	 * has to handle NAT. - agranig */
+	if (ptr->path.s && ptr->path.len) {
+	    if (get_path_dst_uri(&ptr->path, &path_dst) < 0) {
+		LM_ERR("failed to get dst_uri for Path\n");
+		ret = -3;
+		goto done;
+	    }
+	    if (set_path_vector(_m, &ptr->path) < 0) {
+		LM_ERR("failed to set path vector\n");
 		return -1;
-	}
-
-	ptr = r->contacts;
-	ret = -1;
-	/* look first for an un-expired and suported contact */
-	while ( (ptr) &&
-	!(VALID_CONTACT(ptr,act_time) && (ret=-2) && allowed_method(_m,ptr)))
-		ptr = ptr->next;
-	if (ptr==0) {
-		/* nothing found */
+	    }
+	    if (set_dst_uri(_m, &path_dst) < 0) {
+		LM_ERR("failed to set dst_uri of Path\n");
+		ret = -3;
+		goto done;
+	    }
+	} else if (ptr->received.s && ptr->received.len) {
+	    if (set_dst_uri(_m, &ptr->received) < 0) {
+		ret = -3;
 		goto done;
+	    }
 	}
 
-	ret = 1;
-	if (ptr) {
-		if (rewrite_uri(_m, &ptr->c) < 0) {
-			LM_ERR("unable to rewrite Request-URI\n");
-			ret = -3;
-			goto done;
-		}
-
-		/* reset next hop address */
-		reset_dst_uri(_m);
-
-		/* If a Path is present, use first path-uri in favour of
-		 * received-uri because in that case the last hop towards the uac
-		 * has to handle NAT. - agranig */
-		if (ptr->path.s && ptr->path.len) {
-			if (get_path_dst_uri(&ptr->path, &path_dst) < 0) {
-				LM_ERR("failed to get dst_uri for Path\n");
-				ret = -3;
-				goto done;
-			}
-			if (set_path_vector(_m, &ptr->path) < 0) {
-				LM_ERR("failed to set path vector\n");
-				ret = -3;
-				goto done;
-			}
-			if (set_dst_uri(_m, &path_dst) < 0) {
-				LM_ERR("failed to set dst_uri of Path\n");
-				ret = -3;
-				goto done;
-			}
-		} else if (ptr->received.s && ptr->received.len) {
-			if (set_dst_uri(_m, &ptr->received) < 0) {
-				ret = -3;
-				goto done;
-			}
-		}
-
-		set_ruri_q(ptr->q);
-
-		old_bflags = 0;
-		getbflagsval(0, &old_bflags);
-		setbflagsval(0, old_bflags|ptr->cflags);
+	set_ruri_q(ptr->q);
+
+	old_bflags = 0;
+	getbflagsval(0, &old_bflags);
+	setbflagsval(0, old_bflags | ptr->cflags);
+
+	if (ptr->sock)
+	    set_force_socket(_m, ptr->sock);
+
+	ptr = ptr->next;
+    }
+
+    /* Append branches if enabled */
+    if (!cfg_get(registrar, registrar_cfg, append_branches)) goto done;
+
+    //the last i was the first valid contact we found - let's go through the rest of valid contacts and append the branches.
+    while (i < MAX_CONTACTS_PER_IMPU && (ptr = r->newcontacts[i])) {
+	if (VALID_CONTACT(ptr, act_time) && allowed_method(_m, ptr)) {
+	    path_dst.len = 0;
+	    if (ptr->path.s && ptr->path.len
+		    && get_path_dst_uri(&ptr->path, &path_dst) < 0) {
+		LM_ERR("failed to get dst_uri for Path\n");
+		continue;
+	    }
+
+	    /* The same as for the first contact applies for branches
+	     * regarding path vs. received. */
+	    if (km_append_branch(_m, &ptr->c, path_dst.len ? &path_dst : &ptr->received,
+		    &ptr->path, ptr->q, ptr->cflags, ptr->sock) == -1) {
+		LM_ERR("failed to append a branch\n");
+		/* Also give a chance to the next branches*/
+		continue;
+	    }
+	}
+	i++;
+    }
 
-		if (ptr->sock)
-			set_force_socket(_m, ptr->sock);
+done:
+    ul.unlock_udomain(_d, &aor);
+    return ret;
+}
 
-		ptr = ptr->next;
+int lookup_path_to_contact(struct sip_msg* _m, char* contact_uri) {
+    ucontact_t* contact;
+    str s_contact_uri;
+    str path_dst;
+    
+    if (get_str_fparam(&s_contact_uri, _m, (fparam_t*) contact_uri) < 0) {
+	    LM_ERR("failed to get RURI\n");
+	    return -1;
+    }
+    LM_DBG("Looking up contact [%.*s]\n", s_contact_uri.len, s_contact_uri.s);
+
+    if (ul.get_ucontact(NULL, &s_contact_uri, 0, 0, 0, &contact) == 0) { //get_contact returns with lock
+	LM_DBG("CONTACT FOUND and path is [%.*s]\n", contact->path.len, contact->path.s);
+	
+	if (get_path_dst_uri(&contact->path, &path_dst) < 0) {
+	    LM_ERR("failed to get dst_uri for Path\n");
+	    ul.release_ucontact(contact);
+	    return -1;
 	}
-
-	/* Append branches if enabled */
-	if (!cfg_get(registrar, registrar_cfg, append_branches)) goto done;
-
-	for( ; ptr ; ptr = ptr->next ) {
-		if (VALID_CONTACT(ptr, act_time) && allowed_method(_m, ptr)) {
-			path_dst.len = 0;
-			if(ptr->path.s && ptr->path.len
-			&& get_path_dst_uri(&ptr->path, &path_dst) < 0) {
-				LM_ERR("failed to get dst_uri for Path\n");
-				continue;
-			}
-
-			/* The same as for the first contact applies for branches
-			 * regarding path vs. received. */
-			if (km_append_branch(_m,&ptr->c,path_dst.len?&path_dst:&ptr->received,
-			&ptr->path, ptr->q, ptr->cflags, ptr->sock) == -1) {
-				LM_ERR("failed to append a branch\n");
-				/* Also give a chance to the next branches*/
-				continue;
-			}
-		}
+	if (set_path_vector(_m, &contact->path) < 0) {
+	    LM_ERR("failed to set path vector\n");
+	    ul.release_ucontact(contact);
+	    return -1;
+	}
+	if (set_dst_uri(_m, &path_dst) < 0) {
+	    LM_ERR("failed to set dst_uri of Path\n");
+	    ul.release_ucontact(contact);
+	    return -1;
 	}
+	
+	ul.release_ucontact(contact);
+	return 1;
+    }
 
-done:
-	//ul.release_impurecord(r);
-	ul.unlock_udomain(_d, &aor);
-	return ret;
+    LM_DBG("no contact found for [%.*s]\n", s_contact_uri.len, s_contact_uri.s);
+    return -1;
 }
 
 /*! \brief the impu_registered() function
@@ -211,6 +262,60 @@ int impu_registered(struct sip_msg* _m, char* _t, char* _s)
 	return ret;
 }
 
+/**
+ * Check that the IMPU at the Term S has at least one valid contact...
+ * @param _m - msg
+ * @param _t - t
+ * @param _s - s
+ * @return true if there is at least one valid contact. false if not
+ */
+int term_impu_has_contact(struct sip_msg* _m, udomain_t* _d, char* _s) 
+{
+    impurecord_t* r;
+    str aor, uri;
+    ucontact_t* ptr;
+    int res;
+    int ret;
+    int i = 0;
+
+    if (_m->new_uri.s) uri = _m->new_uri;
+    else uri = _m->first_line.u.request.uri;
+
+    if (extract_aor(&uri, &aor) < 0) {
+	LM_ERR("failed to extract address of record\n");
+	return -3;
+    }
+
+    get_act_time();
+
+    ul.lock_udomain(_d, &aor);
+    res = ul.get_impurecord(_d, &aor, &r);
+    if (res > 0) {
+	LM_DBG("'%.*s' Not found in usrloc\n", aor.len, ZSW(aor.s));
+	ul.unlock_udomain(_d, &aor);
+	return -1;
+    }
+
+    while (i < MAX_CONTACTS_PER_IMPU && (ptr = r->newcontacts[i])) {
+	if (VALID_CONTACT(ptr, act_time) && allowed_method(_m, ptr)) {
+	    LM_DBG("Found a valid contact [%.*s]\n", ptr->c.len, ptr->c.s);
+	    i++;
+	    ret = 1;
+	    break;
+	}
+	i++;
+    }
+
+    /* look first for an un-expired and supported contact */
+    if (ptr == 0) {
+	/* nothing found */
+	ret = -1;
+    } 
+
+    ul.unlock_udomain(_d, &aor);
+
+    return ret;
+}
 /*! \brief the term_impu_registered() function
  * Return true if the AOR in the Request-URI  for the terminating user is registered
  */
@@ -244,11 +349,10 @@ int term_impu_registered(struct sip_msg* _m, char* _t, char* _s)
 	else uri = _m->first_line.u.request.uri;
 		
 	for(i=0;i<uri.len;i++)
-		if (uri.s[i]==';' || uri.s[i]=='?') {
+		if (uri.s[i]==';' || uri.s[i]=='?' || (i>3 /*sip:*/ && uri.s[i]==':' /*strip port*/)) {
 			uri.len = i;
 			break;
 		}
-	
 	LM_DBG("term_impu_registered: Looking for <%.*s>\n",uri.len,uri.s);
 
 	ul.lock_udomain((udomain_t*)_t, &uri);
diff --git a/modules/ims_registrar_scscf/lookup.h b/modules/ims_registrar_scscf/lookup.h
index 68a7e0e..791460d 100644
--- a/modules/ims_registrar_scscf/lookup.h
+++ b/modules/ims_registrar_scscf/lookup.h
@@ -40,7 +40,7 @@
  * Lookup a contact in usrloc and rewrite R-URI if found
  */
 int lookup(struct sip_msg* _m, udomain_t* _d);
-
+int lookup_path_to_contact(struct sip_msg* _m, char* contact_uri);
 
 /*! \brief
  * Return true if the AOR in the Request-URI is registered,
@@ -49,6 +49,7 @@ int lookup(struct sip_msg* _m, udomain_t* _d);
  */
 int impu_registered(struct sip_msg* _m, char* _t, char* _s);
 int term_impu_registered(struct sip_msg* _m, char* _t, char* _s);
+int term_impu_has_contact(struct sip_msg* _m, udomain_t* _d, char* _s);
 
 
 #endif /* LOOKUP_H */
diff --git a/modules/ims_registrar_scscf/reg_mod.c b/modules/ims_registrar_scscf/reg_mod.c
index a92ac97..2c72493 100644
--- a/modules/ims_registrar_scscf/reg_mod.c
+++ b/modules/ims_registrar_scscf/reg_mod.c
@@ -57,6 +57,7 @@
 #include "../../lib/kcore/statistics.h"
 #include "../../modules/sl/sl.h"
 #include "../../mod_fix.h"
+#include "../../cfg/cfg_struct.h"
 
 #include "save.h"
 #include "api.h"
@@ -69,11 +70,14 @@
 #include "usrloc_cb.h"
 #include "userdata_parser.h"
 #include "cxdx_sar.h"
+#include "cxdx_callbacks.h"
 #include "registrar_notify.h"
 #include "../cdp_avp/mod_export.h"
 
 MODULE_VERSION
 
+extern gen_lock_t* process_lock; /* lock on the process table */
+
 int * callback_singleton; /**< Cx callback singleton 								*/
 
 
@@ -93,6 +97,8 @@ int store_data_on_dereg = 0; /**< should we store SAR data on de-registration  *
 int ue_unsubscribe_on_dereg = 0;  /*many UEs do not unsubscribe on de reg - therefore we should remove their subscription and not send a notify
 				   Some UEs do unsubscribe then everything is fine*/
 
+int user_data_always = 0; /* Always Reports that user data is missing to HSS */
+
 /* parameters storage */
 str cxdx_dest_realm = str_init("ims.smilecoms.com");
 
@@ -103,6 +109,8 @@ str cxdx_forced_peer = {0,0};
 str scscf_name_str = str_init("sip:scscf2.ims.smilecoms.com:6060"); /* default scscf_name - actual should be set via parameter*/
 str scscf_serviceroute_uri_str; /* Service Route URI */
 
+char *domain = "location";  ///TODO should be configurable mod param
+
 /*! \brief Module init & destroy function */
 static int mod_init(void);
 static int child_init(int);
@@ -110,6 +118,7 @@ static void mod_destroy(void);
 static int w_save(struct sip_msg* _m, char * _route, char* _d, char* mode, char* _cflags);
 static int w_assign_server_unreg(struct sip_msg* _m, char* _route, char* _d, char* _direction);
 static int w_lookup(struct sip_msg* _m, char* _d, char* _p2);
+static int w_lookup_path_to_contact(struct sip_msg* _m, char* contact_uri);
 
 /*! \brief Fixup functions */
 static int domain_fixup(void** param, int param_no);
@@ -119,6 +128,8 @@ static int fetchc_fixup(void** param, int param_no);
 /*! \brief Functions */
 static int add_sock_hdr(struct sip_msg* msg, char *str, char *foo);
 
+AAAMessage* callback_cdp_request(AAAMessage *request, void *param);
+
 int tcp_persistent_flag = -1; /*!< if the TCP connection should be kept open */
 int method_filtering = 0; /*!< if the looked up contacts should be filtered based on supported methods */
 int path_enabled = 0; /*!< if the Path HF should be handled */
@@ -150,6 +161,9 @@ str sock_hdr_name = {0, 0};
 int subscription_default_expires = 3600; /**< the default value for expires if none found*/
 int subscription_min_expires = 10; /**< minimum subscription expiration time 		*/
 int subscription_max_expires = 1000000; /**< maximum subscription expiration time 		*/
+int subscription_expires_range = 0;
+
+int notification_list_size_threshold = 0; /**Threshold for size of notification list after which a warning is logged */
 
 
 extern reg_notification_list *notification_list; /**< list of notifications for reg to be sent			*/
@@ -186,7 +200,9 @@ static pv_export_t mod_pvs[] = {
 static cmd_export_t cmds[] = {
     {"save", (cmd_function) w_save, 2, assign_save_fixup3_async, 0, REQUEST_ROUTE | ONREPLY_ROUTE},
     {"lookup", (cmd_function) w_lookup, 1, domain_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE},
+    {"lookup_path_to_contact", (cmd_function) w_lookup_path_to_contact, 1, fixup_var_str_12, 0, REQUEST_ROUTE},
     {"term_impu_registered", (cmd_function) term_impu_registered, 1, domain_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE},
+    {"term_impu_has_contact", (cmd_function) term_impu_has_contact, 1, domain_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE},
     {"impu_registered", (cmd_function) impu_registered, 1, domain_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE},
     {"assign_server_unreg", (cmd_function) w_assign_server_unreg, 3, assign_save_fixup3_async, 0, REQUEST_ROUTE},
     {"add_sock_hdr", (cmd_function) add_sock_hdr, 1, fixup_str_null, 0, REQUEST_ROUTE},
@@ -243,6 +259,9 @@ static param_export_t params[] = {
     {"subscription_min_expires", INT_PARAM, &subscription_min_expires},
     {"subscription_max_expires", INT_PARAM, &subscription_max_expires},
     {"ue_unsubscribe_on_dereg", INT_PARAM, &ue_unsubscribe_on_dereg},
+    {"subscription_expires_range", INT_PARAM, &subscription_expires_range},
+    {"user_data_always", INT_PARAM, &user_data_always},
+    {"notification_list_size_threshold", INT_PARAM, &notification_list_size_threshold},
 
     {0, 0, 0}
 };
@@ -289,6 +308,9 @@ static int mod_init(void) {
     str s;
     bind_usrloc_t bind_usrloc;
     qvalue_t dq;
+    
+    callback_singleton = shm_malloc(sizeof (int));
+    *callback_singleton = 0;
 
     /*build the required strings */
     scscf_serviceroute_uri_str.s =
@@ -326,6 +348,9 @@ static int mod_init(void) {
     }
 #endif
 
+    /*register space for notification processor*/
+    register_procs(1);
+
     /* bind the SL API */
     if (sl_load_api(&slb) != 0) {
         LM_ERR("cannot bind to SL API\n");
@@ -471,6 +496,21 @@ static int mod_init(void) {
 }
 
 static int child_init(int rank) {
+    LM_DBG("Initialization of module in child [%d] \n", rank);
+    int pid;
+    
+    if (rank == PROC_MAIN) {
+        pid = fork_process(PROC_MIN, "sip_notification_event_process", 1);
+        if (pid < 0)
+            return -1; //error
+        if (pid == 0) {
+            if (cfg_child_init())
+                return -1; //error
+            notification_event_process();
+        }
+    }
+    
+    
     if (rank == PROC_MAIN || rank == PROC_TCP_MAIN)
         return 0;
     if (rank == 1) {
@@ -489,10 +529,52 @@ static int child_init(int rank) {
     /* Init the user data parser */
     if (!parser_init(scscf_user_data_dtd, scscf_user_data_xsd))
         return -1;
+    
+    
+    lock_get(process_lock);
+    if ((*callback_singleton) == 0) {
+        *callback_singleton = 1;
+        cdpb.AAAAddRequestHandler(callback_cdp_request, NULL);
+    }
+    lock_release(process_lock);
+
+    return 0;
+}
+
 
+/**
+ * Handler for incoming Diameter requests.
+ * @param request - the received request
+ * @param param - generic pointer
+ * @returns the answer to this request
+ */
+AAAMessage* callback_cdp_request(AAAMessage *request, void *param) {
+    if (is_req(request)) {
+
+        switch (request->applicationId) {
+            case IMS_Cx:
+            //case IMS_Dx:  IMS_Cx is same as IMS_Dx 16777216
+                switch (request->commandCode) {
+                    case IMS_RTR:
+                        LM_INFO("Cx/Dx request handler():- Received an IMS_RTR \n");
+                        return cxdx_process_rtr(request);
+                        break;
+                    default:
+                        LM_ERR("Cx/Dx request handler(): - Received unknown request for Cx/Dx command %d, flags %#1x endtoend %u hopbyhop %u\n", request->commandCode, request->flags, request->endtoendId, request->hopbyhopId);
+                        return 0;
+                        break;
+                }
+                break;
+            default:
+                LM_ERR("Cx/Dx request handler(): - Received unknown request for app %d command %d\n", request->applicationId, request->commandCode);
+                return 0;
+                break;
+        }
+    }
     return 0;
 }
 
+
 /*! \brief
  * Wrapper to save(location)
  */
@@ -509,6 +591,10 @@ static int w_assign_server_unreg(struct sip_msg* _m, char* _route, char* _d, cha
 
 }
 
+static int w_lookup_path_to_contact(struct sip_msg* _m, char* contact_uri) {
+    return lookup_path_to_contact(_m, contact_uri);
+}
+
 /*! \brief
  * Wrapper to lookup(location)
  */
diff --git a/modules/ims_registrar_scscf/registrar_notify.c b/modules/ims_registrar_scscf/registrar_notify.c
index 8e80bcf..2b33fd7 100644
--- a/modules/ims_registrar_scscf/registrar_notify.c
+++ b/modules/ims_registrar_scscf/registrar_notify.c
@@ -77,6 +77,8 @@ reg_notification_list *notification_list = 0; //< List of pending notifications
 
 extern struct tm_binds tmb;
 
+extern int notification_list_size_threshold;
+
 extern int subscription_default_expires;
 extern int subscription_min_expires;
 extern int subscription_max_expires;
@@ -91,14 +93,45 @@ static str ctype_hdr1 = {"Content-Type: ", 14};
 static str ctype_hdr2 = {"\r\n", 2};
 
 extern int ue_unsubscribe_on_dereg;
+extern int subscription_expires_range;
+
+extern char *domain;
+
+/* \brief
+ * Return randomized expires between expires-range% and expires.
+ * RFC allows only value less or equal to the one provided by UAC.
+ */
+
+static inline int randomize_expires( int expires, int range )
+{
+	/* if no range is given just return expires */
+	if(range == 0) return expires;
+
+	int range_min = expires - (float)range/100 * expires;
+
+	return range_min + (float)(rand()%100)/100 * ( expires - range_min );
+}
 
 int notify_init() {
     notification_list = shm_malloc(sizeof (reg_notification_list));
-    if (!notification_list) return 0;
+    if (!notification_list) {
+	LM_ERR("No more SHM mem\n");
+	return 0; 
+    }
     memset(notification_list, 0, sizeof (reg_notification_list));
     notification_list->lock = lock_alloc();
-    if (!notification_list->lock) return 0;
-    notification_list->lock = lock_init(notification_list->lock);
+    if (!notification_list->lock)  {
+	LM_ERR("failed to create cdp event list lock\n");
+	return 0;
+    }
+    if (lock_init(notification_list->lock)==0){
+       lock_dealloc(notification_list->lock);
+       notification_list->lock=0;
+       LM_ERR("failed to initialize cdp event list lock\n");
+       return 0;
+    }
+    notification_list->size = 0;
+    sem_new(notification_list->empty, 0); //pre-locked - as we assume list is empty at start
     return 1;
 }
 
@@ -119,127 +152,127 @@ void notify_destroy() {
     shm_free(notification_list);
 }
 
-
 int can_publish_reg(struct sip_msg *msg, char *_t, char *str2) {
-    
-	int ret = CSCF_RETURN_FALSE;
-	str presentity_uri = {0, 0};
-	str event;
-	str asserted_id;
-	ucontact_t* c = 0;
-	impurecord_t* r;
-	int res;
-	ims_public_identity *pi = 0;
-	int i, j;
 
-	LM_DBG("Checking if allowed to publish reg event\n");
+    int ret = CSCF_RETURN_FALSE;
+    str presentity_uri = {0, 0};
+    str event;
+    str asserted_id;
+    ucontact_t* c = 0;
+    impurecord_t* r;
+    int res;
+    ims_public_identity *pi = 0;
+    int i, j;
 
-	//check that this is a request
-	if (msg->first_line.type != SIP_REQUEST) {
-	    LM_ERR("This message is not a request\n");
-	    goto error;
-	}
+    LM_DBG("Checking if allowed to publish reg event\n");
 
-	//check that this is a subscribe request
-	if (msg->first_line.u.request.method.len != 7 ||
-		memcmp(msg->first_line.u.request.method.s, "PUBLISH", 7) != 0) {
-	    LM_ERR("This message is not a PUBLISH\n");
-	    goto error;
-	}
+    //check that this is a request
+    if (msg->first_line.type != SIP_REQUEST) {
+	LM_ERR("This message is not a request\n");
+	goto error;
+    }
 
-	//check that this is a reg event - currently we only support reg event!
-	event = cscf_get_event(msg);
-	if (event.len != 3 || strncasecmp(event.s, "reg", 3) != 0) {
-	    LM_ERR("Accepting only <Event: reg>. Found: <%.*s>\n",
-		    event.len, event.s);
-	    goto done;
-	}
+    //check that this is a subscribe request
+    if (msg->first_line.u.request.method.len != 7 ||
+	    memcmp(msg->first_line.u.request.method.s, "PUBLISH", 7) != 0) {
+	LM_ERR("This message is not a PUBLISH\n");
+	goto error;
+    }
 
-	asserted_id = cscf_get_asserted_identity(msg, 0);
-	if (!asserted_id.len) {
-	    LM_ERR("P-Asserted-Identity empty.\n");
-	    goto error;
-	}
-	LM_DBG("P-Asserted-Identity <%.*s>.\n", asserted_id.len, asserted_id.s);
+    //check that this is a reg event - currently we only support reg event!
+    event = cscf_get_event(msg);
+    if (event.len != 3 || strncasecmp(event.s, "reg", 3) != 0) {
+	LM_ERR("Accepting only <Event: reg>. Found: <%.*s>\n",
+		event.len, event.s);
+	goto done;
+    }
 
-	//get presentity URI
-	presentity_uri = cscf_get_public_identity_from_requri(msg);
-	
-	LM_DBG("Looking for IMPU in usrloc <%.*s>\n", presentity_uri.len, presentity_uri.s);
+    asserted_id = cscf_get_asserted_identity(msg, 0);
+    if (!asserted_id.len) {
+	LM_ERR("P-Asserted-Identity empty.\n");
+	goto error;
+    }
+    LM_DBG("P-Asserted-Identity <%.*s>.\n", asserted_id.len, asserted_id.s);
 
-	ul.lock_udomain((udomain_t*) _t, &presentity_uri);
-	res = ul.get_impurecord((udomain_t*) _t, &presentity_uri, &r);
+    //get presentity URI
+    presentity_uri = cscf_get_public_identity_from_requri(msg);
 
-	if (res > 0) {
-	    LM_DBG("'%.*s' Not found in usrloc\n", presentity_uri.len, presentity_uri.s);
-	    ul.unlock_udomain((udomain_t*) _t, &presentity_uri);
-	    goto done;
-	}
+    LM_DBG("Looking for IMPU in usrloc <%.*s>\n", presentity_uri.len, presentity_uri.s);
 
-	LM_DBG("<%.*s> found in usrloc\n", presentity_uri.len, presentity_uri.s);
+    ul.lock_udomain((udomain_t*) _t, &presentity_uri);
+    res = ul.get_impurecord((udomain_t*) _t, &presentity_uri, &r);
 
-	//check if the asserted identity is in the same group as that presentity uri
-	if (r->public_identity.len == asserted_id.len &&
-		strncasecmp(r->public_identity.s, asserted_id.s, asserted_id.len) == 0) {
-	    LM_DBG("Identity found as AOR <%.*s>\n",
-		    presentity_uri.len, presentity_uri.s);
-	    ul.unlock_udomain((udomain_t*) _t, &presentity_uri);
-	    ret = CSCF_RETURN_TRUE;
-	    goto done;
-	}
+    if (res > 0) {
+	LM_DBG("'%.*s' Not found in usrloc\n", presentity_uri.len, presentity_uri.s);
+	ul.unlock_udomain((udomain_t*) _t, &presentity_uri);
+	goto done;
+    }
 
-	//check if asserted identity is in service profile
-	lock_get(r->s->lock);
-	if (r->s) {
-	    for (i = 0; i < r->s->service_profiles_cnt; i++)
-		for (j = 0; j < r->s->service_profiles[i].public_identities_cnt; j++) {
-		    pi = &(r->s->service_profiles[i].public_identities[j]);
-		    if (!pi->barring &&
-			    pi->public_identity.len == asserted_id.len &&
-			    strncasecmp(pi->public_identity.s, asserted_id.s, asserted_id.len) == 0) {
-			LM_DBG("Identity found in SP[%d][%d]\n",
-				i, j);
-			ret = CSCF_RETURN_TRUE;
-			ul.unlock_udomain((udomain_t*) _t, &presentity_uri);
-			lock_release(r->s->lock);
-			goto done;
-		    }
+    LM_DBG("<%.*s> found in usrloc\n", presentity_uri.len, presentity_uri.s);
+
+    //check if the asserted identity is in the same group as that presentity uri
+    if (r->public_identity.len == asserted_id.len &&
+	    strncasecmp(r->public_identity.s, asserted_id.s, asserted_id.len) == 0) {
+	LM_DBG("Identity found as AOR <%.*s>\n",
+		presentity_uri.len, presentity_uri.s);
+	ul.unlock_udomain((udomain_t*) _t, &presentity_uri);
+	ret = CSCF_RETURN_TRUE;
+	goto done;
+    }
+
+    //check if asserted identity is in service profile
+    lock_get(r->s->lock);
+    if (r->s) {
+	for (i = 0; i < r->s->service_profiles_cnt; i++)
+	    for (j = 0; j < r->s->service_profiles[i].public_identities_cnt; j++) {
+		pi = &(r->s->service_profiles[i].public_identities[j]);
+		if (!pi->barring &&
+			pi->public_identity.len == asserted_id.len &&
+			strncasecmp(pi->public_identity.s, asserted_id.s, asserted_id.len) == 0) {
+		    LM_DBG("Identity found in SP[%d][%d]\n",
+			    i, j);
+		    ret = CSCF_RETURN_TRUE;
+		    ul.unlock_udomain((udomain_t*) _t, &presentity_uri);
+		    lock_release(r->s->lock);
+		    goto done;
 		}
-	}
-	lock_release(r->s->lock);
-	LM_DBG("Did not find p-asserted-identity <%.*s> in SP\n", asserted_id.len, asserted_id.s);
+	    }
+    }
+    lock_release(r->s->lock);
+    LM_DBG("Did not find p-asserted-identity <%.*s> in SP\n", asserted_id.len, asserted_id.s);
 
-	//check if asserted is present in any of the path headers
-	c = r->contacts;
+    //check if asserted is present in any of the path headers
+    j=0;
 
-	while (c) {
-	    if (c->path.len) {
-		for (i = 0; i < c->path.len - asserted_id.len; i++)
-		    LM_DBG("Path: <%.*s>.\n",
+    while (j<MAX_CONTACTS_PER_IMPU && (c=r->newcontacts[j])) {
+	if (c->path.len) {
+	    LM_DBG("Path: <%.*s>.\n",
 		    c->path.len, c->path.s);
-		    //we compare the asserted_id without "sip:" to the path 
-		    if (strncasecmp(c->path.s + i, asserted_id.s+4, asserted_id.len-4) == 0) {
-			LM_DBG("Identity found in Path <%.*s>\n",
-				c->path.len, c->path.s);
-			ret = CSCF_RETURN_TRUE;
-			ul.unlock_udomain((udomain_t*) _t, &presentity_uri);
-			goto done;
-		    }
+	    for (i = 0; i < c->path.len - (asserted_id.len - 4); i++){
+		//we compare the asserted_id without "sip:" to the path 
+		if (strncasecmp(c->path.s + i, asserted_id.s + 4, asserted_id.len - 4) == 0) {
+		    LM_DBG("Identity found in Path <%.*s>\n",
+			    c->path.len, c->path.s);
+		    ret = CSCF_RETURN_TRUE;
+		    ul.unlock_udomain((udomain_t*) _t, &presentity_uri);
+		    goto done;
+		}
 	    }
-	    c = c->next;
 	}
-	LM_DBG("Did not find p-asserted-identity <%.*s> on Path\n", asserted_id.len, asserted_id.s);
+	j++;
+    }
+    LM_DBG("Did not find p-asserted-identity <%.*s> on Path\n", asserted_id.len, asserted_id.s);
+
+    ul.unlock_udomain((udomain_t*) _t, &presentity_uri);
+    LM_DBG("Publish forbidden\n");
 
-	ul.unlock_udomain((udomain_t*) _t, &presentity_uri);
-	LM_DBG("Publish forbidden\n");
-    
 done:
-	if (presentity_uri.s) shm_free(presentity_uri.s); // shm_malloc in cscf_get_public_identity_from_requri
-	return ret;
+    if (presentity_uri.s) shm_free(presentity_uri.s); // shm_malloc in cscf_get_public_identity_from_requri
+    return ret;
 error:
-	if (presentity_uri.s) shm_free(presentity_uri.s); // shm_malloc in cscf_get_public_identity_from_requri
-	ret = CSCF_RETURN_ERROR;
-	return ret;
+    if (presentity_uri.s) shm_free(presentity_uri.s); // shm_malloc in cscf_get_public_identity_from_requri
+    ret = CSCF_RETURN_ERROR;
+    return ret;
 }
 
 int can_subscribe_to_reg(struct sip_msg *msg, char *_t, char *str2) {
@@ -367,24 +400,25 @@ int can_subscribe_to_reg(struct sip_msg *msg, char *_t, char *str2) {
     LM_DBG("Did not find p-asserted-identity <%.*s> in SP\n", asserted_id.len, asserted_id.s);
 
     //check if asserted is present in any of the path headers
-    c = r->contacts;
-
-    while (c) {
+    j = 0;
+    while (j < MAX_CONTACTS_PER_IMPU && (c = r->newcontacts[j])) {
 	if (c->path.len) {
-            for (i = 0; i < c->path.len - asserted_id.len; i++)
-		LM_DBG("Path: <%.*s>.\n",
-		c->path.len, c->path.s);
+	    LM_DBG("Path: <%.*s>.\n",
+		    c->path.len, c->path.s);
+	    for (i = 0; i < c->path.len - (asserted_id.len - 4); i++) {
 		//we compare the asserted_id without "sip:" to the path 
-                if (strncasecmp(c->path.s + i, asserted_id.s+4, asserted_id.len-4) == 0) {
-                    LM_DBG("Identity found in Path <%.*s>\n",
-                            c->path.len, c->path.s);
-                    ret = CSCF_RETURN_TRUE;
-                    ul.unlock_udomain((udomain_t*) _t, &presentity_uri);
-                    goto done;
-                }
-        }
-        c = c->next;
+		if (strncasecmp(c->path.s + i, asserted_id.s + 4, asserted_id.len - 4) == 0) {
+		    LM_DBG("Identity found in Path <%.*s>\n",
+			    c->path.len, c->path.s);
+		    ret = CSCF_RETURN_TRUE;
+		    ul.unlock_udomain((udomain_t*) _t, &presentity_uri);
+		    goto done;
+		}
+	    }
+	}
+	j++;
     }
+
     LM_DBG("Did not find p-asserted-identity <%.*s> on Path\n", asserted_id.len, asserted_id.s);
     
     ul.unlock_udomain((udomain_t*) _t, &presentity_uri);
@@ -409,7 +443,11 @@ int event_reg(udomain_t* _d, impurecord_t* r_passed, ucontact_t* c_passed, int e
     impurecord_t* r;
     int num_impus;
     str* impu_list;
+    int res = 0;
+    udomain_t* udomain;
 
+    get_act_time();
+    
     LM_DBG("Sending Reg event notifies\n");
     LM_DBG("Switching on event type: %d", event_type);
     switch (event_type) {
@@ -424,7 +462,7 @@ int event_reg(udomain_t* _d, impurecord_t* r_passed, ucontact_t* c_passed, int e
             //lets get IMPU list for presentity as well as register for callbacks (IFF its a new SUBSCRIBE)
 
             ul.lock_udomain(_d, presentity_uri);
-            int res = ul.get_impurecord(_d, presentity_uri, &r);
+            res = ul.get_impurecord(_d, presentity_uri, &r);
             if (res != 0) {
                 LM_WARN("Strange, '%.*s' Not found in usrloc\n", presentity_uri->len, presentity_uri->s);
                 ul.unlock_udomain(_d, presentity_uri);
@@ -446,7 +484,7 @@ int event_reg(udomain_t* _d, impurecord_t* r_passed, ucontact_t* c_passed, int e
             ul.unlock_udomain((udomain_t*) _d, presentity_uri);
 
             content = generate_reginfo_full(_d, impu_list,
-                    num_impus);
+                    num_impus, 0, 0);
 
             if (impu_list) {
                 pkg_free(impu_list);
@@ -470,7 +508,34 @@ int event_reg(udomain_t* _d, impurecord_t* r_passed, ucontact_t* c_passed, int e
                 return 0;
             }
 
-	    content = get_reginfo_partial(r_passed, c_passed, event_type);
+	    //content = get_reginfo_partial(r_passed, c_passed, event_type);
+	    
+	    //this is a ulcallback so r_passed domain is already locked
+	    res = ul.get_impus_from_subscription_as_string(_d, r_passed,
+                    0/*all unbarred impus*/, &impu_list, &num_impus);
+	    if (res != 0) {
+                LM_WARN("failed to get IMPUs from subscription\n");
+                if (impu_list) {
+                    pkg_free(impu_list);
+                }
+                return 1;
+            }
+	    
+	    //TODO this should be a configurable module param
+	    if (ul.register_udomain(domain, &udomain) < 0) {
+		LM_ERR("Unable to register usrloc domain....aborting\n");
+		return 0;
+	    }
+//	    
+	    content = generate_reginfo_full(udomain, impu_list,
+                    num_impus, &r_passed->public_identity, 1);
+//	    
+	    if (impu_list) {
+                pkg_free(impu_list);
+            }
+
+            LM_DBG("About to ceate notification");
+	    
             create_notifications(_d, r_passed, c_passed, presentity_uri, watcher_contact, content, event_type);
             if (content.s) pkg_free(content.s);
             //                        if (send_now) notification_timer(0, 0);
@@ -532,14 +597,20 @@ int process_contact(impurecord_t* presentity_impurecord, udomain_t * _d, int exp
 			if (contact_state == STATE_TERMINATED) {
 				//delete contact
 				LM_DBG("This contact <%.*s> is in state terminated and is in usrloc so removing it from usrloc\n", contact_uri.len, contact_uri.s);
-				if (ul.delete_ucontact(implicit_impurecord, ucontact) != 0) {
+				ul.lock_contact_slot(&contact_uri);
+				if (ul.unlink_contact_from_impu(implicit_impurecord, ucontact, 1) != 0) {
 				    LM_ERR("Failed to delete ucontact <%.*s> from implicit IMPU\n", contact_uri.len, contact_uri.s);
-				    goto next_implicit_impu;
+				    ul.unlock_contact_slot(&contact_uri);
+				    ul.release_ucontact(ucontact);
+				    goto next_implicit_impu;	//TODO: don't need to use goto here...
 				}
+				ul.unlock_contact_slot(&contact_uri);
 			}else {//state is active
 				LM_DBG("This contact: <%.*s> is not in state terminated and is in usrloc, ignore\n", contact_uri.len, contact_uri.s);
+				ul.release_ucontact(ucontact);
 				goto next_implicit_impu;
 			}
+			ul.release_ucontact(ucontact);
 		}
 next_implicit_impu:
 		ul.unlock_udomain(_d, &pi->public_identity);
@@ -561,15 +632,21 @@ next_implicit_impu:
 		if (contact_state == STATE_TERMINATED) {
 			//delete contact
 			LM_DBG("This contact <%.*s> is in state terminated and is in usrloc so removing it from usrloc\n", contact_uri.len, contact_uri.s);
-			if (ul.delete_ucontact(presentity_impurecord, ucontact) != 0) {
+			ul.lock_contact_slot(&contact_uri);
+			if (ul.unlink_contact_from_impu(presentity_impurecord, ucontact, 1) != 0) {
 			    LM_ERR("Failed to delete ucontact <%.*s>\n", contact_uri.len, contact_uri.s);
 			    ret = CSCF_RETURN_FALSE;
+    			    ul.unlock_contact_slot(&contact_uri);
+			    ul.release_ucontact(ucontact);
 			    goto done;
 			}
+			ul.unlock_contact_slot(&contact_uri);
 		}else {//state is active
 			LM_DBG("This contact: <%.*s> is not in state terminated and is in usrloc, ignore\n", contact_uri.len, contact_uri.s);
+			ul.release_ucontact(ucontact);
 			goto done;
 		}
+		ul.release_ucontact(ucontact);
 	}
 	
 done:
@@ -885,7 +962,6 @@ int subscribe_to_reg(struct sip_msg *msg, char *_t, char *str2) {
     reg_subscriber *reg_subscriber;
     subscriber_data_t subscriber_data;
 
-    int new_subscription = 1;
     int event_type = IMS_REGISTRAR_NONE;
 
     int rt = 0;
@@ -1031,13 +1107,18 @@ int subscribe_to_reg(struct sip_msg *msg, char *_t, char *str2) {
     subscriber_data.record_route = &record_route;
     subscriber_data.sockinfo_str = &sockinfo_str;
     subscriber_data.local_cseq = local_cseq;
-
+    subscriber_data.watcher_uri = &watcher_impu;
+    subscriber_data.watcher_contact = &watcher_contact;
+    subscriber_data.version = 1; /*default version starts at 1*/
+    
     if (expires > 0) {
         LM_DBG("expires is more than zero - SUBSCRIBE");
         event_type = IMS_REGISTRAR_SUBSCRIBE;
 
         if (expires < subscription_min_expires) expires = subscription_min_expires;
         if (expires > subscription_max_expires) expires = subscription_max_expires;
+	
+	expires = randomize_expires(expires, subscription_expires_range);
 
         get_act_time();
         expires_time = expires + act_time;
@@ -1059,32 +1140,49 @@ int subscribe_to_reg(struct sip_msg *msg, char *_t, char *str2) {
         }
 
         LM_DBG("Received impurecord for presentity being subscribed to [%.*s]\n", presentity_impurecord->public_identity.len, presentity_impurecord->public_identity.s);
-
+	
         res = ul.get_subscriber(presentity_impurecord, &presentity_uri, &watcher_contact, event_i, &reg_subscriber);
 	if (res != 0) {
             LM_DBG("this must be a new subscriber, lets add it\n");
-            res = ul.add_subscriber(presentity_impurecord, &watcher_impu, &watcher_contact, &subscriber_data, &reg_subscriber);
+	    subscriber_data.presentity_uri = &presentity_impurecord->public_identity;
+            res = ul.add_subscriber(presentity_impurecord, &subscriber_data, &reg_subscriber, 0 /*not a db_load*/);
             if (res != 0) {
                 LM_ERR("Failed to add new subscription\n");
                 ul.unlock_udomain(domain, &presentity_uri);
                 ret = CSCF_RETURN_FALSE;
                 goto error;
             }
-            //send full update on first registration
-
-            new_subscription = 1;
-
         } else {
 
-            LM_DBG("this must be a re subscribe, lets update it\n");
-            res = ul.update_subscriber(presentity_impurecord, &watcher_impu, &watcher_contact, &expires_time, &reg_subscriber);
-            if (res != 1) {
-                LM_ERR("Failed to update subscription - expires is %d\n", expires_time);
-                ul.unlock_udomain(domain, &presentity_uri);
-                ret = CSCF_RETURN_FALSE;
-                goto error;
-            }
-            new_subscription = 0;
+            if(memcmp(reg_subscriber->call_id.s, subscriber_data.callid->s, reg_subscriber->call_id.len) == 0 && 
+		    memcmp(reg_subscriber->from_tag.s, subscriber_data.ftag->s, reg_subscriber->from_tag.len) == 0 && 
+		    memcmp(reg_subscriber->to_tag.s, subscriber_data.ttag->s, reg_subscriber->to_tag.len) == 0) {
+		LM_DBG("This has same callid, fromtag and totag - must be a re subscribe, lets update it\n");
+		res = ul.update_subscriber(presentity_impurecord, &reg_subscriber, &expires_time, 0, 0);
+		if (res != 1) {
+		    LM_ERR("Failed to update subscription - expires is %d\n", expires_time);
+		    ul.unlock_udomain(domain, &presentity_uri);
+		    ret = CSCF_RETURN_FALSE;
+		    goto error;
+		}
+	    } else {
+		LM_ERR("Re-subscribe for same watcher_contact, presentity_uri, event but with different callid [%.*s], fromtag [%.*s] and totag [%.*s] for presentity [%.*s] and watcher contact [%.*s] - What happened?\n",
+			subscriber_data.callid->len, subscriber_data.callid->s,
+			subscriber_data.ftag->len, subscriber_data.ftag->s,
+			subscriber_data.ttag->len, subscriber_data.ttag->s,
+			presentity_impurecord->public_identity.len, presentity_impurecord->public_identity.s,
+			subscriber_data.watcher_contact->len, subscriber_data.watcher_contact->s);
+		LM_DBG("Removing old subscriber and adding new one\n");
+		subscriber_data.presentity_uri = &presentity_impurecord->public_identity;
+		ul.external_delete_subscriber(reg_subscriber, (udomain_t*) _t, 0 /*domain is already locked*/);
+		res = ul.add_subscriber(presentity_impurecord, &subscriber_data, &reg_subscriber, 0 /*not a db_load*/);
+		if (res != 0) {
+		    LM_ERR("Failed to add new subscription\n");
+		    ul.unlock_udomain(domain, &presentity_uri);
+		    ret = CSCF_RETURN_FALSE;
+		    goto error;
+		}
+	    }
         }
 
         ul.unlock_udomain(domain, &presentity_uri);
@@ -1093,16 +1191,14 @@ int subscribe_to_reg(struct sip_msg *msg, char *_t, char *str2) {
         LM_DBG("Sending 200 OK to subscribing user");
         subscribe_reply(msg, 200, MSG_REG_SUBSCRIBE_OK, &expires, &scscf_name_str);
 
-        //only do reg event on new subscriptions
-        if (new_subscription) {
-            if (event_reg(domain, 0, 0, event_type, &presentity_uri, &watcher_contact) != 0) {
-                LM_ERR("failed to send NOTIFYs for reg events\n");
-                ret = CSCF_RETURN_ERROR;
-                goto error;
-            } else {
-                LM_DBG("success sending NOTIFY\n");
-            }
-        }
+        //do reg event every time you get a subscribe
+	if (event_reg(domain, 0, 0, event_type, &presentity_uri, &watcher_contact) != 0) {
+	    LM_ERR("failed adding notification for reg events\n");
+	    ret = CSCF_RETURN_ERROR;
+	    goto error;
+	} else {
+	    LM_DBG("success adding notification for reg events\n");
+	}
     } else {
         event_type = IMS_REGISTRAR_UNSUBSCRIBE;
         LM_DBG("expires is zero or less - UNSUBSCRIBE");
@@ -1265,6 +1361,8 @@ void create_notifications(udomain_t* _t, impurecord_t* r_passed, ucontact_t* c_p
     reg_notification *n;
     reg_subscriber *s;
     impurecord_t* r;
+    int local_cseq = 0;
+    int version = 0;
 
     str subscription_state = {"active;expires=10000000000", 26},
     content_type = {"application/reginfo+xml", 23};
@@ -1322,18 +1420,17 @@ void create_notifications(udomain_t* _t, impurecord_t* r_passed, ucontact_t* c_p
                     (presentity_uri->len == s->presentity_uri.len) && (memcmp(s->presentity_uri.s, presentity_uri->s, presentity_uri->len) == 0)) {
                 LM_DBG("This is a fix to ensure that we only send full reg info XML to the UE that just subscribed");
                 LM_DBG("about to make new notification!");
-                n = new_notification(subscription_state, content_type, content,
-                        s->version++, s);
+		
+		LM_DBG("we always increment the local cseq and version before we send a new notification\n");
+		
+		local_cseq = s->local_cseq + 1;
+		version = s->version + 1;
+		ul.update_subscriber(r, &s, 0, &local_cseq, &version);
+		
+                n = new_notification(subscription_state, content_type, content, s);
                 if (n) {
-                    //LM_DBG("Notification exists - about to add it");
-                    //add_notification(n);
-
-                    //Richard just gonna send it - not bother queueing etc.
-                    //TODO look at impact of this - sending straight away vs queueing and getting another process to send
-                    LM_DBG("About to send notification");
-                    send_notification(n);
-                    LM_DBG("About to free notification");
-                    free_notification(n);
+                    LM_DBG("Notification exists - about to add it");
+                    add_notification(n);
                 } else {
                     LM_DBG("Notification does not exist");
                 }
@@ -1349,24 +1446,23 @@ void create_notifications(udomain_t* _t, impurecord_t* r_passed, ucontact_t* c_p
 	    }
 	    else{
 		LM_DBG("about to make new notification!");
-		n = new_notification(subscription_state, content_type, content,
-			s->version++, s);
+		
+		LM_DBG("we always increment the local cseq and version before we send a new notification\n");
+		
+		local_cseq = s->local_cseq + 1;
+		version = s->version + 1;
+		ul.update_subscriber(r, &s, 0, &local_cseq, &version);
+		
+		n = new_notification(subscription_state, content_type, content, s);
 		if (n) {
-		    //LM_DBG("Notification exists - about to add it");
-		    //add_notification(n);
-
-		    //Richard just gonna send it - not bother queueing etc.
-		    //TODO look at impact of this - sending straight away vs queueing and getting another process to send
-		    LM_DBG("About to send notification");
-		    send_notification(n);
-		    LM_DBG("About to free notification");
-		    free_notification(n);
+		    LM_DBG("Notification exists - about to add it");
+		    add_notification(n);
+
 		} else {
 		    LM_DBG("Notification does not exist");
 		}
 	    }
 	}
-        //}
         s = s->next;
 
         if (subscription_state.s) {
@@ -1383,6 +1479,35 @@ out_of_memory:
     return;
 }
 
+/*We currently only support certain unknown params to be sent in NOTIFY bodies
+ This prevents having compatability issues with UEs including non-standard params in contact header
+ Supported params:
+ */
+static str param_q = {"q", 1};
+static str param_video = {"video", 5};
+static str param_expires = {"expires", 7};
+static str param_sip_instance = {"+sip.instance", 13};
+static str param_3gpp_smsip = {"+g.3gpp.smsip", 13};
+static str param_3gpp_icsi_ref = {"+g.3gpp.icsi-ref", 16};
+int inline supported_param(str *param_name) {
+    
+    if(strncasecmp(param_name->s, param_q.s, param_name->len) == 0) {
+	return 0;
+    } else if (strncasecmp(param_name->s, param_video.s, param_name->len) == 0) {
+	return 0;
+    } else if (strncasecmp(param_name->s, param_expires.s, param_name->len) == 0) {
+	return 0;
+    } else if (strncasecmp(param_name->s, param_sip_instance.s, param_name->len) == 0) {
+	return 0;
+    } else if (strncasecmp(param_name->s, param_3gpp_smsip.s, param_name->len) == 0) {
+	return 0;
+    } else if (strncasecmp(param_name->s, param_3gpp_icsi_ref.s, param_name->len) == 0) {
+	return 0;
+    } else {
+	return -1;
+    }
+}
+
 /** Maximum reginfo XML size */
 #define MAX_REGINFO_SIZE 16384
 
@@ -1405,6 +1530,11 @@ static str r_expired = {"expired", 7};
 static str r_unregistered = {"unregistered", 12};
 static str contact_s = {"\t\t<contact id=\"%p\" state=\"%.*s\" event=\"%.*s\" expires=\"%d\">\n", 59};
 static str contact_s_q = {"\t\t<contact id=\"%p\" state=\"%.*s\" event=\"%.*s\" expires=\"%d\" q=\"%.3f\">\n", 69};
+static str contact_s_params_with_body = {"\t\t<unknown-param name=\"%.*s\">\"%.*s\"</unknown-param>\n", 1};
+/**NOTIFY XML needs < to be replaced by < and > to be replaced by >*/
+/*For params that need to be fixed we pass in str removing first and last character and replace them with < and >**/
+static str contact_s_params_with_body_fix = {"\t\t<unknown-param name=\"%.*s\">\"<%.*s>\"</unknown-param>\n", 1};
+static str contact_s_params_no_body = {"\t\t<unknown-param name=\"%.*s\"></unknown-param>\n", 1};
 static str contact_e = {"\t\t</contact>\n", 13};
 
 static str uri_s = {"\t\t\t<uri>", 8};
@@ -1418,18 +1548,24 @@ static str uri_e = {"</uri>\n", 7};
  * @returns the str with the XML content
  * if its a new subscription we do things like subscribe to updates on IMPU, etc
  */
-str generate_reginfo_full(udomain_t* _t, str* impu_list, int num_impus) {
+str generate_reginfo_full(udomain_t* _t, str* impu_list, int num_impus, str *primary_impu, int primary_locked) {
     str x = {0, 0};
     str buf, pad;
     char bufc[MAX_REGINFO_SIZE], padc[MAX_REGINFO_SIZE];
     impurecord_t *r;
-    ucontact_t *c;
-    int i, res;
+    int i, j, res;
+    ucontact_t* ptr;
+    param_t *param;
 
     buf.s = bufc;
     buf.len = 0;
     pad.s = padc;
     pad.len = 0;
+    
+    int domain_locked = 1;
+    int terminate_impu = 1;
+    
+    int expires;
 
     LM_DBG("Getting reginfo_full");
 
@@ -1439,58 +1575,132 @@ str generate_reginfo_full(udomain_t* _t, str* impu_list, int num_impus) {
     STR_APPEND(buf, pad);
 
     for (i = 0; i < num_impus; i++) {
-        ul.lock_udomain(_t, &impu_list[i]);
-        LM_DBG("Scrolling through public identities, current one <%.*s>", impu_list[i].len, impu_list[i].s);
-        res = ul.get_impurecord(_t, &(impu_list[i]), &r);
-        if (res != 0) {
-            LM_WARN("impu disappeared, ignoring it\n");
-	    ul.unlock_udomain(_t, &impu_list[i]);
-            continue;
-        }
+	LM_DBG("Scrolling through public identities, current one <%.*s>", impu_list[i].len, impu_list[i].s);
+	if(primary_locked && strncasecmp(impu_list[i].s, primary_impu->s, impu_list[i].len) == 0) {
+	    LM_DBG("Don't need to lock this impu [%.*s]  as its a ulcallback so already locked\n", impu_list[i].len, impu_list[i].s);
+	    domain_locked = 0;
+	} else {
+	    LM_DBG("Need to lock this impu\n");
+	    ul.lock_udomain(_t, &impu_list[i]);
+	    domain_locked = 1;
+	}
+	
+	res = ul.get_impurecord(_t, &(impu_list[i]), &r);
+	if (res != 0) {
+	    LM_WARN("impu disappeared, ignoring it\n");
+	    if(domain_locked) {
+		ul.unlock_udomain(_t, &impu_list[i]);
+	    }
+	    continue;
+	}
+	
         LM_DBG("Retrieved IMPU record");
-
-        if (r->reg_state == IMPU_REGISTERED) {
-            LM_DBG("IMPU reg state is IMPU REGISTERED so putting in status active");
-            sprintf(pad.s, registration_s.s, r->public_identity.len,
-                    r->public_identity.s, r, r_active.len, r_active.s);
-        } else {
-            LM_DBG("IMPU reg state is not IMPU REGISTERED so putting in status terminated");
+	
+	j=0;
+	terminate_impu = 1;
+	while (j<MAX_CONTACTS_PER_IMPU && (ptr=r->newcontacts[j])) {
+	    if (((ptr->expires - act_time) > 0)) {
+		LM_DBG("IMPU <%.*s> has another active contact <%.*s> so will set its state to active\n",
+			r->public_identity.len, r->public_identity.s, ptr->c.len, ptr->c.s);
+		terminate_impu = 0;
+		break;
+	    }
+	    j++;
+	}
+	if(terminate_impu) {
+	    LM_DBG("IMPU reg state has no active contacts so putting in status terminated");
             sprintf(pad.s, registration_s.s, r->public_identity.len,
                     r->public_identity.s, r, r_terminated.len,
                     r_terminated.s);
-        }
+	} else {
+	    LM_DBG("IMPU has active contacts so putting in status active");
+            sprintf(pad.s, registration_s.s, r->public_identity.len,
+                    r->public_identity.s, r, r_active.len, r_active.s);
+	}
+
         pad.len = strlen(pad.s);
         STR_APPEND(buf, pad);
-        c = r->contacts;
-        LM_DBG("Scrolling through contact for this IMPU");
-        while (c) {
-            if (c->q != -1) {
-                LM_DBG("q value not equal to -1");
-                float q = (float) c->q / 1000;
-                sprintf(pad.s, contact_s_q.s, c, r_active.len, r_active.s,
-                        r_registered.len, r_registered.s, c->expires - act_time,
-                        q);
-            } else {
-                LM_DBG("q value equal to -1");
-                sprintf(pad.s, contact_s.s, c, r_active.len, r_active.s,
-                        r_registered.len, r_registered.s,
-                        c->expires - act_time);
-            }
-            pad.len = strlen(pad.s);
-            STR_APPEND(buf, pad);
-            STR_APPEND(buf, uri_s);
-
-            LM_DBG("Appending contact address: <%.*s>", c->c.len, c->c.s);
-
-            STR_APPEND(buf, (c->c));
-            STR_APPEND(buf, uri_e);
+        
+	j=0;
+	LM_DBG("Scrolling through contact for this IMPU");
+	while (j < MAX_CONTACTS_PER_IMPU && (ptr = r->newcontacts[j])) {
+	    if (ptr->q != -1) {
+		LM_DBG("q value not equal to -1");
+		float q = (float) ptr->q / 1000;
+		expires = ptr->expires - act_time;
+		if(expires < 0) {
+		    LM_WARN("Contact expires is negative - setting to 0\n");
+		    expires = 0;
+		}
+		if(expires == 0) {
+		    sprintf(pad.s, contact_s_q.s, ptr, r_terminated.len, r_terminated.s,
+			r_expired.len, r_expired.s, expires,
+			q);
+		} else {
+		    sprintf(pad.s, contact_s_q.s, ptr, r_active.len, r_active.s,
+			r_registered.len, r_registered.s, expires,
+			q);
+		}
+		
+	    } else {
+		LM_DBG("q value equal to -1");
+		expires = ptr->expires - act_time;
+		if(expires < 0) {
+		    LM_WARN("Contact expires is negative - setting to 0\n");
+		    expires = 0;
+		}
+		if(expires == 0) {
+		    sprintf(pad.s, contact_s_q.s, ptr, r_terminated.len, r_terminated.s,
+			r_expired.len, r_expired.s, expires);
+		} else {
+		    sprintf(pad.s, contact_s_q.s, ptr, r_active.len, r_active.s,
+			r_registered.len, r_registered.s, expires);
+		}
+	    }
+	    pad.len = strlen(pad.s);
+	    STR_APPEND(buf, pad);
+	    STR_APPEND(buf, uri_s);
+	    
+	    LM_DBG("Appending contact address: <%.*s>", ptr->c.len, ptr->c.s);
 
-            STR_APPEND(buf, contact_e);
-            c = c->next;
-        }
+	    STR_APPEND(buf, (ptr->c));
+	    STR_APPEND(buf, uri_e);
+	    
+	    param = ptr->params;
+	    while (param) {
+			if (supported_param(&param->name) != 0) { 
+				param = param->next;
+				continue;
+			}
+		
+		if(param->body.len > 0) {
+		    LM_DBG("This contact has params name: [%.*s] body [%.*s]\n", param->name.len, param->name.s, param->body.len, param->body.s);
+		    if (param->body.s[0] == '<' && param->body.s[param->body.len -1] == '>') {
+			LM_DBG("This param body starts with '<' and ends with '>' we will clean these for the NOTIFY XML with < and >\n");
+			sprintf(pad.s, contact_s_params_with_body_fix.s, param->name.len, param->name.s, param->body.len - 2, param->body.s + 1);
+		    } else {
+			sprintf(pad.s, contact_s_params_with_body.s, param->name.len, param->name.s, param->body.len, param->body.s);
+		    }
+		    
+		    pad.len = strlen(pad.s);
+		    STR_APPEND(buf, pad);
+		} else {
+		    LM_DBG("This contact has params name: [%.*s] \n", param->name.len, param->name.s);
+		    sprintf(pad.s, contact_s_params_no_body.s, param->name.len, param->name.s);
+		    pad.len = strlen(pad.s);
+		    STR_APPEND(buf, pad);
+		}
+		param = param->next;
+	    }
+	    STR_APPEND(buf, contact_e);
+	    j++;
+	}
+	
         STR_APPEND(buf, registration_e);
 
-        ul.unlock_udomain(_t, &impu_list[i]);
+	if(domain_locked) {
+	    ul.unlock_udomain(_t, &impu_list[i]);
+	}
     }
 
     STR_APPEND(buf, r_reginfo_e);
@@ -1518,16 +1728,15 @@ str generate_reginfo_full(udomain_t* _t, str* impu_list, int num_impus) {
 
 str get_reginfo_partial(impurecord_t *r, ucontact_t *c, int event_type) {
     str x = {0, 0};
+    int i;
     str buf, pad;
     char bufc[MAX_REGINFO_SIZE], padc[MAX_REGINFO_SIZE];
     int expires = -1;
-    
     int terminate_impu = 1;
-    
     ucontact_t *c_tmp;
-
     str state, event;
-
+    param_t *param;
+    
     buf.s = bufc;
     buf.len = 0;
     pad.s = padc;
@@ -1541,31 +1750,33 @@ str get_reginfo_partial(impurecord_t *r, ucontact_t *c, int event_type) {
 
     if (r) {
         expires = c->expires - act_time;
-        if (r->contacts == c &&
-                //richard we only use expired and unregistered
+	if(expires < 0) {
+	    LM_WARN("Contact expires is negative - setting to 0\n");
+	    expires = 0;
+	}
+	
+        if (//richard we only use expired and unregistered
                 (event_type == IMS_REGISTRAR_CONTACT_EXPIRED ||
                 event_type == IMS_REGISTRAR_CONTACT_UNREGISTERED)
                 ){
 	    //check if impu record has any other active contacts - if not then set this to terminated - if so then keep this active
 	    //check if asserted is present in any of the path headers
-	    c_tmp = r->contacts;
-
-	    while (c_tmp) {
-		if ((strncasecmp(c_tmp->c.s, c->c.s, c_tmp->c.len) != 0)  && ((c_tmp->expires - act_time) > 0)) {
+	    
+	    
+	    i=0;
+	    while (i<MAX_CONTACTS_PER_IMPU && (c_tmp=r->newcontacts[i])) {
+		if ((strncasecmp(c_tmp->c.s, c->c.s, c_tmp->c.len) != 0) && ((c_tmp->expires - act_time) > 0)) {
 		    LM_DBG("IMPU <%.*s> has another active contact <%.*s> so will set its state to active\n",
-			r->public_identity.len, r->public_identity.s, c_tmp->c.len, c_tmp->c.s);
-			terminate_impu = 0;
-			break;
+			    r->public_identity.len, r->public_identity.s, c_tmp->c.len, c_tmp->c.s);
+		    terminate_impu = 0;
+		    break;
 		}
-		c_tmp = c_tmp->next;
+		i++;
 	    }
-	    
-	    if(terminate_impu){
+	    if(terminate_impu)
 		sprintf(pad.s, registration_s.s, r->public_identity.len, r->public_identity.s, r, r_terminated.len, r_terminated.s);
-	    }else
-	    {
+	    else
 		sprintf(pad.s, registration_s.s, r->public_identity.len, r->public_identity.s, r, r_active.len, r_active.s);
-	    }
 	}
         else{
 	    sprintf(pad.s, registration_s.s, r->public_identity.len, r->public_identity.s, r, r_active.len, r_active.s);
@@ -1609,7 +1820,30 @@ str get_reginfo_partial(impurecord_t *r, ucontact_t *c, int event_type) {
             STR_APPEND(buf, uri_s);
             STR_APPEND(buf, (c->c));
             STR_APPEND(buf, uri_e);
-
+	    
+	    param = c->params;
+	    while (param && supported_param(&param->name) == 0) {
+		
+		if(param->body.len > 0) {
+		    LM_DBG("This contact has params name: [%.*s] body [%.*s]\n", param->name.len, param->name.s, param->body.len, param->body.s);
+		    if (param->body.s[0] == '<' && param->body.s[param->body.len -1] == '>') {
+			LM_DBG("This param body starts with '<' and ends with '>' we will clean these for the NOTIFY XML with < and >\n");
+			sprintf(pad.s, contact_s_params_with_body_fix.s, param->name.len, param->name.s, param->body.len - 2, param->body.s + 1);
+		    } else {
+			sprintf(pad.s, contact_s_params_with_body.s, param->name.len, param->name.s, param->body.len, param->body.s);
+		    }
+		    
+		    pad.len = strlen(pad.s);
+		    STR_APPEND(buf, pad);
+		} else {
+		    LM_DBG("This contact has params name: [%.*s] \n", param->name.len, param->name.s);
+		    sprintf(pad.s, contact_s_params_no_body.s, param->name.len, param->name.s);
+		    pad.len = strlen(pad.s);
+		    STR_APPEND(buf, pad);
+		}
+		param = param->next;
+	    }
+	    
             STR_APPEND(buf, contact_e);
             STR_APPEND(buf, registration_e);
         }
@@ -1631,7 +1865,7 @@ str get_reginfo_partial(impurecord_t *r, ucontact_t *c, int event_type) {
  * Callback for the UAC response to NOTIFY
  */
 void uac_request_cb(struct cell *t, int type, struct tmcb_params * ps) {
-    LM_DBG("DBG:uac_request_cb: Type %d\n", type);
+    LM_DBG("received NOTIFY reply type [%d] and code [%d]\n", type, ps->code);
 }
 
 static int free_tm_dlg(dlg_t * td) {
@@ -1725,41 +1959,6 @@ void send_notification(reg_notification * n) {
 }
 
 /**
- * The Notification timer looks for unsent notifications and sends them.
- *  - because not all events should wait until the notifications for them are sent
- * @param ticks - the current time
- * @param param - pointer to the domain_list
- */
-void notification_timer(unsigned int ticks, void* param) {
-
-    LM_DBG("Running notification timer");
-
-    reg_notification *n = 0;
-    LM_DBG("Getting lock of notification list");
-    lock_get(notification_list->lock);
-    LM_DBG("Scrolling through list");
-    while (notification_list->head) {
-        n = notification_list->head;
-        LM_DBG("Taking notification out of list with watcher uri <%.*s> and presentity uri <%.*s>", n->watcher_uri.len, n->watcher_uri.s, n->presentity_uri.len, n->presentity_uri.s);
-        notification_list->head = n->next;
-        if (n->next) n->next->prev = 0;
-        else notification_list->tail = n->next;
-
-        LM_DBG("Releasing lock");
-        lock_release(notification_list->lock);
-
-        LM_DBG("About to send notification");
-        send_notification(n);
-        LM_DBG("About to free notification");
-        free_notification(n);
-        LM_DBG("Getting lock of notification list again");
-        lock_get(notification_list->lock);
-    }
-    LM_DBG("Releasing lock again");
-    lock_release(notification_list->lock);
-}
-
-/**
  * Creates a notification based on the given parameters
  * @param req_uri - the Request-URI for the NOTIFY
  * @param uri - uri to send to
@@ -1771,14 +1970,19 @@ void notification_timer(unsigned int ticks, void* param) {
  * @returns the r_notification or NULL on error
  */
 reg_notification * new_notification(str subscription_state,
-        str content_type, str content, int version, reg_subscriber * r) {
+        str content_type, str content, reg_subscriber * r) {
 
     reg_notification *n = 0;
 
     str buf;
     char bufc[MAX_REGINFO_SIZE];
 
-    sprintf(bufc, content.s, version);
+    if (content.len > MAX_REGINFO_SIZE) {
+        LM_ERR("content size (%d) exceeds MAX_REGINFO_SIZE (%d)!\n", content.len, MAX_REGINFO_SIZE);
+        return 0;
+    }
+
+    sprintf(bufc, content.s, r->version);
     buf.s = bufc;
     buf.len = strlen(bufc);
 
@@ -1799,6 +2003,8 @@ reg_notification * new_notification(str subscription_state,
     memset(n, 0, len);
 
     p = (char*) (n + 1);
+    
+    n->local_cseq = r->local_cseq;
 
     n->call_id.s = p;
     n->call_id.len = r->call_id.len;
@@ -1895,10 +2101,61 @@ void add_notification(reg_notification * n) {
     if (notification_list->tail) notification_list->tail->next = n;
     notification_list->tail = n;
     if (!notification_list->head) notification_list->head = n;
+    notification_list->size++;
+    if(notification_list_size_threshold > 0 && notification_list->size > notification_list_size_threshold) {
+	    LM_WARN("notification_list is size [%d] and has exceed notification_list_size_threshold of [%d]", notification_list->size, notification_list_size_threshold);
+    }
+    
+    sem_release(notification_list->empty);
     lock_release(notification_list->lock);
 }
 
 /**
+* Pop a notification to the list of notifications from the top
+*/
+reg_notification* get_notification() {
+    reg_notification * n;
+
+    lock_get(notification_list->lock);
+    while (notification_list->head == 0) {
+        lock_release(notification_list->lock);
+        sem_get(notification_list->empty);
+        lock_get(notification_list->lock);
+    }
+
+    n = notification_list->head;
+    notification_list->head = n->next;
+
+    if (n == notification_list->tail) { //list now empty
+        notification_list->tail = 0;
+    }
+    n->next = 0; //make sure whoever gets this cant access our list
+    notification_list->size--;
+    lock_release(notification_list->lock);
+
+    return n;
+}
+
+/**
+ * This is the main event process for notifications to be sent
+ */
+void notification_event_process() {
+
+    reg_notification *n = 0;
+    
+    LM_DBG("Running notification_event_process");
+    
+    for (;;) {
+        n = get_notification();
+	LM_DBG("About to send notification");
+        send_notification(n);
+        LM_DBG("About to free notification");
+        free_notification(n);
+    }
+}
+
+
+/**
  * Frees up space taken by a notification
  * @param n - the notification to be freed
  */
diff --git a/modules/ims_registrar_scscf/registrar_notify.h b/modules/ims_registrar_scscf/registrar_notify.h
index 1196cb7..5475a36 100644
--- a/modules/ims_registrar_scscf/registrar_notify.h
+++ b/modules/ims_registrar_scscf/registrar_notify.h
@@ -49,6 +49,7 @@
 
 #include "../ims_usrloc_scscf/usrloc.h"
 #include "../../locking.h"
+#include "sem.h"
 
 
 #define MSG_REG_SUBSCRIBE_OK "Subscription to REG saved"
@@ -86,6 +87,8 @@ typedef struct {
     gen_lock_t *lock; /**< lock for notifications ops		*/
     reg_notification *head; /**< first notification in the list	*/
     reg_notification *tail; /**< last notification in the list	*/
+    gen_sem_t *empty;
+    int size;
 } reg_notification_list;
 
 /** Events for subscriptions */
@@ -122,21 +125,22 @@ int subscribe_reply(struct sip_msg *msg, int code, char *text, int *expires, str
 int event_reg(udomain_t* _d, impurecord_t* r_passed, ucontact_t* c_passed, int event_type, str *presentity_uri, str *watcher_contact);
 
 
-str generate_reginfo_full(udomain_t* _t, str* impu_list, int new_subscription);
+str generate_reginfo_full(udomain_t* _t, str* impu_list, int new_subscription, str *primary_impu, int primary_locked);
 
 str get_reginfo_partial(impurecord_t *r, ucontact_t *c, int event_type);
 
 void create_notifications(udomain_t* _t, impurecord_t* r_passed, ucontact_t* c_passed, str *presentity_uri, str *watcher_contact, str content, int event_type);
 
-void notification_timer(unsigned int ticks, void* param);
+void notification_event_process();
 
 void free_notification(reg_notification *n);
 
 void send_notification(reg_notification * n);
 
 void add_notification(reg_notification *n);
+
 reg_notification* new_notification(str subscription_state,
-        str content_type, str content, int version, reg_subscriber* r);
+        str content_type, str content, reg_subscriber* r);
 
 dlg_t* build_dlg_t_from_notification(reg_notification* n);
 
diff --git a/modules/ims_registrar_scscf/regpv.c b/modules/ims_registrar_scscf/regpv.c
index f686be6..856577d 100644
--- a/modules/ims_registrar_scscf/regpv.c
+++ b/modules/ims_registrar_scscf/regpv.c
@@ -455,7 +455,7 @@ int pv_fetch_contacts(struct sip_msg* msg, char* table, char* uri,
 		return -1;
 	}
 
-	ptr = r->contacts;
+	ptr = 0;//r->contacts;TODO
 	ptr0 = NULL;
 	n = 0;
 	while(ptr)
@@ -470,8 +470,8 @@ int pv_fetch_contacts(struct sip_msg* msg, char* table, char* uri,
 			goto error;
 		}
 		memcpy(c0, ptr, ilen);
-		c0->domain = NULL;
-		c0->aor = NULL;
+		//c0->domain = {0,0};//NULL;TODO
+		//c0->aor = {0,0};//NULL;
 		c0->next = NULL;
 		c0->prev = NULL;
 
diff --git a/modules/ims_registrar_scscf/reply.c b/modules/ims_registrar_scscf/reply.c
index 320e5f6..17022da 100644
--- a/modules/ims_registrar_scscf/reply.c
+++ b/modules/ims_registrar_scscf/reply.c
@@ -88,12 +88,14 @@ static struct {
  * Calculate the length of buffer needed to
  * print contacts
  */
-static inline unsigned int calc_buf_len(ucontact_t* c) {
+static inline unsigned int calc_buf_len(impurecord_t* impurec) {
     unsigned int len;
     int qlen;
+    int i=0;
+    ucontact_t* c;
 
     len = 0;
-    while (c) {
+    while (i<MAX_CONTACTS_PER_IMPU && (c=impurec->newcontacts[i])) {
         if (VALID_CONTACT(c, act_time)) {
             if (len) len += CONTACT_SEP_LEN;
             len += 2 /* < > */ + c->c.len;
@@ -110,7 +112,7 @@ static inline unsigned int calc_buf_len(ucontact_t* c) {
                         ;
             }
         }
-        c = c->next;
+	i++;
     }
 
     if (len) len += CONTACT_BEGIN_LEN + CRLF_LEN;
@@ -395,12 +397,12 @@ int build_expired_contact(contact_t* chi, contact_for_header_t** contact_header)
 
 //We use shared memory for this so we can use it when we use async diameter
 
-int build_contact(ucontact_t* c, contact_for_header_t** contact_header) {
-
+int build_contact(impurecord_t* impurec, contact_for_header_t** contact_header) {
     char *p, *cp;
     int fl, len;
-
+    ucontact_t* c;
     *contact_header = 0;
+    int i=0;
 
     contact_for_header_t* tmp_contact_header = shm_malloc(sizeof (contact_for_header_t));
     if (!tmp_contact_header) {
@@ -409,7 +411,7 @@ int build_contact(ucontact_t* c, contact_for_header_t** contact_header) {
     }
     memset(tmp_contact_header, 0, sizeof (contact_for_header_t));
 
-    tmp_contact_header->data_len = calc_buf_len(c);
+    tmp_contact_header->data_len = calc_buf_len(impurec);
     tmp_contact_header->buf = (char*)shm_malloc(tmp_contact_header->data_len);
 
     if (tmp_contact_header->data_len) {
@@ -419,7 +421,8 @@ int build_contact(ucontact_t* c, contact_for_header_t** contact_header) {
         p += CONTACT_BEGIN_LEN;
 
         fl = 0;
-        while (c) {
+	    
+        while (i<MAX_CONTACTS_PER_IMPU && (c=impurec->newcontacts[i])) {
             if (VALID_CONTACT(c, act_time)) {
                 if (fl) {
                     memcpy(p, CONTACT_SEP, CONTACT_SEP_LEN);
@@ -458,8 +461,7 @@ int build_contact(ucontact_t* c, contact_for_header_t** contact_header) {
                     *p++ = '\"';
                 }
             }
-
-            c = c->next;
+	    i++;
         }
 
         memcpy(p, CRLF, CRLF_LEN);
@@ -666,7 +668,7 @@ int reg_send_reply(struct sip_msg* _m, contact_for_header_t* contact_header) {
     str msg = str_init(MSG_200); /* makes gcc shut up */
     char* buf;
 
-    if (contact_header && contact_header->buf && contact_header->data_len > 0) {
+    if (contact_header && contact_header->buf && (contact_header->buf_len > 0) && (contact_header->data_len > 0)) {
     	LM_DBG("Contacts: %.*s\n", contact_header->data_len, contact_header->buf);
         add_lump_rpl(_m, contact_header->buf, contact_header->data_len, LUMP_RPL_HDR | LUMP_RPL_NODUP | LUMP_RPL_NOFREE);
         contact_header->data_len = 0;
diff --git a/modules/ims_registrar_scscf/reply.h b/modules/ims_registrar_scscf/reply.h
index cba4057..f6f11c0 100644
--- a/modules/ims_registrar_scscf/reply.h
+++ b/modules/ims_registrar_scscf/reply.h
@@ -64,7 +64,7 @@ int reg_send_reply_transactional(struct sip_msg* _m, contact_for_header_t* conta
 /*! \brief
  * Build Contact HF for reply
  */
-int build_contact(ucontact_t* c, contact_for_header_t** contact_header);
+int build_contact(impurecord_t* impurec, contact_for_header_t** contact_header);
 int build_expired_contact(contact_t* chi, contact_for_header_t** contact_header); //this is for building the expired response - ie reply to dereg
 
 int build_p_associated_uri(ims_subscription* s);
diff --git a/modules/ims_registrar_scscf/save.c b/modules/ims_registrar_scscf/save.c
index 4061e6f..2638d3c 100644
--- a/modules/ims_registrar_scscf/save.c
+++ b/modules/ims_registrar_scscf/save.c
@@ -84,6 +84,23 @@ extern struct tm_binds tmb;
 extern int store_data_on_dereg; /**< should we store SAR user data on de-registration  */
 
 extern int ue_unsubscribe_on_dereg;
+extern int user_data_always;
+
+
+/* \brief
+ * Return randomized expires between expires-range% and expires.
+ * RFC allows only value less or equal to the one provided by UAC.
+ */
+static inline int randomize_expires( int expires, int range )
+{
+	/* if no range is given just return expires */
+	if(range == 0) return expires;
+
+	int range_min = expires - (float)range/100 * expires;
+
+	return range_min + (float)(rand()%100)/100 * ( expires - range_min );
+}
+
 
 /*! \brief
  * Calculate absolute expires value per contact as follows:
@@ -123,6 +140,9 @@ static inline int calc_contact_expires(contact_t *c, unsigned int expires_hdr, i
         r = default_registrar_cfg.em_min_expires;
 
 end:
+	    
+    r = randomize_expires(r, default_registrar_cfg.default_expires_range);
+	    
     LM_DBG("Calculated expires for contact is %d\n", r);
     return time(NULL) + r;
 }
@@ -134,16 +154,9 @@ end:
  */
 static inline int star(udomain_t* _d, str* _a) {
     impurecord_t* r;
-    ucontact_t* c = 0;
 
     ul.lock_udomain(_d, _a);
 
-    if (!ul.get_impurecord(_d, _a, &r)) {
-        c = r->contacts;
-    } else {
-        r = NULL;
-    }
-
     if (ul.delete_impurecord(_d, _a, r) < 0) {
         LM_ERR("failed to remove record from usrloc\n");
 
@@ -155,7 +168,7 @@ static inline int star(udomain_t* _d, str* _a) {
 
         if (!ul.get_impurecord(_d, _a, &r)) {
             contact_for_header_t** contact_header = 0;
-            build_contact(c, contact_header);
+            build_contact(r, contact_header);
             free_contact_buf(*contact_header);
         }
         ul.unlock_udomain(_d, _a);
@@ -285,8 +298,10 @@ static inline ucontact_info_t* pack_ci(struct sip_msg* _m, contact_t* _c, unsign
                 }
             }
         }
-
-        ci.last_modified = act_time;
+	
+	if(_c->params) {
+	    ci.params = _c->params;
+	}
 
         /* set flags */
         ci.flags = _f;
@@ -485,7 +500,7 @@ static inline int is_impu_registered(udomain_t* _d, str* public_identity) {
         }
 	
 	//check valid contacts
-        if(impu->contacts == 0)
+        if((impu->num_contacts <=0) || (impu->newcontacts[0]==0))
 	{
 	    LM_DBG("IMPU <%.*s> has no valid contacts\n", public_identity->len, public_identity->s);
             ret = 0;
@@ -553,7 +568,7 @@ static inline int update_contacts_helper(struct sip_msg* msg, impurecord_t* impu
                                 "sos: [%d],"
                                 "expires [%ld]\n", chi->uri.len, chi->uri.s, qvalue, sos, expires - time(NULL));
 
-                        LM_DBG("packing contact information\n");
+			LM_DBG("packing contact information\n");
                         if ((ci = pack_ci(msg, chi, expires, 0)) == 0) {
                             LM_ERR("Failed to extract contact info\n");
                             goto error;
@@ -561,22 +576,29 @@ static inline int update_contacts_helper(struct sip_msg* msg, impurecord_t* impu
 
                         LM_DBG("adding/updating contact based on prior existence\n");
                         //stick the contacts into usrloc
+//			ul.lock_contact_slot(&chi->uri);
                         if (ul.get_ucontact(impu_rec, &chi->uri, ci->callid,
-                                ci->path, ci->cseq, &ucontact) != 0) {
+                                ci->path, ci->cseq, &ucontact) != 0) {	//get_contact returns with lock
                             LM_DBG("inserting new contact\n");
                             if (ul.insert_ucontact(impu_rec, &chi->uri, ci,
                                     &ucontact) != 0) {
                                 LM_ERR("Error inserting contact <%.*s>\n", chi->uri.len, chi->uri.s);
+//				ul.unlock_contact_slot(&chi->uri);
                                 goto error;
                             }
                         } else {
                             LM_DBG("Contact already exists - updating\n");
                             if (ul.update_ucontact(impu_rec, ucontact, ci) != 0) {
                                 LM_ERR("Error updating contact <%.*s>\n", chi->uri.len, chi->uri.s);
+				ul.release_ucontact(ucontact);
+//				ul.unlock_contact_slot(&chi->uri);
                                 goto error;
                             }
+			    ul.release_ucontact(ucontact);
                         }
-
+			
+			
+//			ul.unlock_contact_slot(&chi->uri);
                     }
                 }
             }
@@ -628,10 +650,14 @@ static inline int unregister_contact(udomain_t* _d, str* public_identity, contac
 	}
     }
     
-    if (ul.delete_ucontact(impu_rec, ucontact) != 0) {
+//    if (ul.delete_ucontact(impu_rec, ucontact) != 0) {
+    ul.lock_contact_slot_i(ucontact->contact_hash);
+    if (ul.unlink_contact_from_impu(impu_rec, ucontact, 1) != 0) {
         LM_ERR("Failed to delete ucontact <%.*s>\n", chi->uri.len, chi->uri.s);
     }
-    LM_DBG("Contact deleted successfully <%.*s>\n", chi->uri.len, chi->uri.s);
+    ul.unlock_contact_slot_i(ucontact->contact_hash);
+    ul.release_ucontact(ucontact);
+    LM_DBG("Contact unlinked successfully <%.*s>\n", chi->uri.len, chi->uri.s);
     return 0;
 
 error:
@@ -705,7 +731,7 @@ int update_contacts_new(struct sip_msg* msg, udomain_t* _d,
                 goto error;
             }
             //now build the contact buffer to be include in the reply message and unlock
-            build_contact(impu_rec->contacts, contact_header);
+            build_contact(impu_rec, contact_header);
             ul.unlock_udomain(_d, public_identity);
             break;
         case AVP_IMS_SAR_RE_REGISTRATION:
@@ -727,7 +753,7 @@ int update_contacts_new(struct sip_msg* msg, udomain_t* _d,
                 goto error;
             }
             //build the contact buffer for all registered contacts on explicit IMPU
-            build_contact(impu_rec->contacts, contact_header);
+            build_contact(impu_rec, contact_header);
 
             subscription = impu_rec->s;
             if (!subscription) {
@@ -738,7 +764,7 @@ int update_contacts_new(struct sip_msg* msg, udomain_t* _d,
                     LM_ERR("Unable to update explicit impurecord for <%.*s>\n", public_identity->len, public_identity->s);
                 }
                 ul.unlock_udomain(_d, public_identity);
-                build_contact(impu_rec->contacts, contact_header);
+                build_contact(impu_rec, contact_header);
                 break;
             }
 
@@ -830,7 +856,7 @@ int update_contacts_new(struct sip_msg* msg, udomain_t* _d,
                 goto error;
             }
 
-            if (impu_rec->contacts) {
+            if (impu_rec->num_contacts>=0 && impu_rec->newcontacts[0]) {
                 LM_DBG("contacts still available\n");
                 //TODO: add all other remaining contacts to reply message (contacts still registered for this IMPU)
                 ret = 1;
@@ -858,7 +884,6 @@ int update_contacts_new(struct sip_msg* msg, udomain_t* _d,
                         pi = &(subscription->service_profiles[i].public_identities[j]);
                         if (memcmp(public_identity->s, pi->public_identity.s, public_identity->len) == 0) { //we don't need to update the explicit IMPU
                             LM_DBG("Ignoring explicit identity <%.*s>, already de-reg/updated\n", public_identity->len, public_identity->s);
-                            ul.unlock_udomain(_d, &pi->public_identity);
                             continue;
                         }
                         ul.lock_udomain(_d, &pi->public_identity);
@@ -898,7 +923,7 @@ int update_contacts_new(struct sip_msg* msg, udomain_t* _d,
                             continue;
                         }
 
-                        if (impu_rec->contacts)
+                        if (impu_rec->num_contacts && impu_rec->newcontacts[0])
                             LM_DBG("contacts still available after implicit dereg for IMPU: <%.*s>\n", pi->public_identity.len, pi->public_identity.s);
                         else {
                             LM_DBG("no contacts left after implicit dereg for IMPU: <%.*s>\n", pi->public_identity.len, pi->public_identity.s);
@@ -1220,11 +1245,16 @@ int save(struct sip_msg* msg, char* str1, char *route) {
             }
         }
     }
-    if (require_user_data)
-        data_available = AVP_IMS_SAR_USER_DATA_NOT_AVAILABLE;
-    else
-        data_available = AVP_IMS_SAR_USER_DATA_ALREADY_AVAILABLE;
-
+    
+    if (!user_data_always) {
+	if (require_user_data)
+	    data_available = AVP_IMS_SAR_USER_DATA_NOT_AVAILABLE;
+	else
+	    data_available = AVP_IMS_SAR_USER_DATA_ALREADY_AVAILABLE;
+    } else {
+	data_available = AVP_IMS_SAR_USER_DATA_NOT_AVAILABLE;
+    }
+    
     //before we send lets suspend the transaction
     t = tmb.t_gett();
     if (t == NULL || t == T_UNDEFINED) {
diff --git a/modules/ims_registrar_scscf/sem.h b/modules/ims_registrar_scscf/sem.h
new file mode 100644
index 0000000..48a2431
--- /dev/null
+++ b/modules/ims_registrar_scscf/sem.h
@@ -0,0 +1,90 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2012 Smile Communications, jason.penton at smilecoms.com
+ * Copyright (C) 2012 Smile Communications, richard.good at smilecoms.com
+ * 
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Fokus. 
+ * Copyright (C) 2004-2006 FhG Fokus
+ * Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ *
+ *
+ * History:
+ * --------
+ *  2011-02-02  initial version (jason.penton)
+ */
+
+#ifndef __SEM_H
+#define __SEM_H
+
+	#include <semaphore.h>
+
+	typedef sem_t gen_sem_t;
+
+	/**
+	 * Create a new unnamed semaphore and initialize it
+	 * @param value - 0 if it should be pre-locked, 1 if not, or how many locks until block
+	 * @return
+	 */
+    #define sem_new(sem_ptr,value)\
+	do {\
+		sem_ptr=shm_malloc(sizeof(gen_sem_t));\
+		if (!sem_ptr){\
+			LM_ERR("Error allocating %lx bytes of shm!\n",sizeof(gen_sem_t));\
+		}	\
+		if (sem_init(sem_ptr, 1, value)<0) {\
+			LM_ERR("Error > %s\n",strerror(errno));\
+		}\
+	} while(0)
+	
+    #define sem_free(sem)\
+	do {\
+		if (sem) {\
+			sem_destroy(sem);\
+			shm_free(sem);\
+			sem=0;\
+		}\
+	} while(0)
+	
+	
+	#define sem_get(sem) sem_wait(sem)
+	#define sem_tryget(sem) sem_trywait(sem)
+	#define sem_timedget(sem,abs_timeout) sem_trywait(sem,abs_timeout)
+	
+	#define sem_release(sem) sem_post(sem)
+
+#endif
diff --git a/modules/ims_registrar_scscf/userdata_parser.c b/modules/ims_registrar_scscf/userdata_parser.c
index 90e8976..8fc93b0 100644
--- a/modules/ims_registrar_scscf/userdata_parser.c
+++ b/modules/ims_registrar_scscf/userdata_parser.c
@@ -860,7 +860,18 @@ static ims_subscription* parse_ims_subscription(xmlDocPtr doc, xmlNodePtr root)
 					s->service_profiles_cnt++;
 			}				
 	s->lock = lock_alloc();
-	s->lock = lock_init(s->lock);
+	if (s->lock==0) {
+		LM_ERR("Failed to allocate Lock for IMS Subscription\n");
+		shm_free(s);
+		return 0;
+	}
+	if (lock_init(s->lock)==0){
+		LM_ERR("Failed to initialize Lock for IMS Subscription\n");
+		lock_dealloc(s->lock);
+		s->lock=0;
+		shm_free(s);
+		return 0;
+	}
 	return s;
 }
 
diff --git a/modules/ims_usrloc_pcscf/Makefile b/modules/ims_usrloc_pcscf/Makefile
index bdf7fac..cea1c11 100644
--- a/modules/ims_usrloc_pcscf/Makefile
+++ b/modules/ims_usrloc_pcscf/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # ims_usrloc_pcscf module Makefile
 #
diff --git a/modules/ims_usrloc_pcscf/doc/ims_usrloc_pcscf_admin.xml b/modules/ims_usrloc_pcscf/doc/ims_usrloc_pcscf_admin.xml
index c904b53..165ba41 100644
--- a/modules/ims_usrloc_pcscf/doc/ims_usrloc_pcscf_admin.xml
+++ b/modules/ims_usrloc_pcscf/doc/ims_usrloc_pcscf_admin.xml
@@ -235,6 +235,34 @@ modparam("ims_usrloc_pcscf", "lookup_check_received", 0)
 </programlisting>
       </example>
     </section>
+    <section>
+      <title>match_contact_host_port (int)</title>
+
+      <para>If set to 1 (default), the contact is matched using only host
+	  and port in the contact URI.</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>0 - When matching contact do full contact match procedure.</para>
+        </listitem>
+
+        <listitem>
+          <para>1 - When matching contact compare only host and port of the contact URI.</para>
+        </listitem>
+      </itemizedlist>
+
+      <para><emphasis>Default value is 1.</emphasis></para>
+
+      <example>
+        <title>Set match_contact_host_port parameter</title>
+
+        <programlisting format="linespecific">...
+modparam("ims_usrloc_pcscf", "match_contact_host_port", 0)
+...
+</programlisting>
+      </example>
+    </section>
+    
   </section>
 
   <section>
diff --git a/modules/ims_usrloc_pcscf/pcontact.c b/modules/ims_usrloc_pcscf/pcontact.c
index 907ac5f..eb83806 100644
--- a/modules/ims_usrloc_pcscf/pcontact.c
+++ b/modules/ims_usrloc_pcscf/pcontact.c
@@ -177,7 +177,12 @@ int new_pcontact(struct udomain* _d, str* _contact, struct pcontact_info* _ci, s
 	if (hashing_type==0) {
 		(*_c)->aorhash = core_hash(_contact, 0, 0);
 	} else if (hashing_type==1) {
-		(*_c)->aorhash = core_hash(&(*_c)->contact_host, 0, 0);
+		if ((*_c)->received_host.len > 0 && memcmp((*_c)->contact_host.s, (*_c)->received_host.s, (*_c)->contact_host.len) != 0) {
+		    LM_DBG("Looks like this contact is natted - contact URI: [%.*s] but came from [%.*s]\n", (*_c)->contact_host.len, 
+		    (*_c)->contact_host.s, (*_c)->received_host.len, (*_c)->received_host.s);
+		    (*_c)->aorhash = core_hash(&(*_c)->received_host, 0, 0);
+		} else 
+		    (*_c)->aorhash = core_hash(&(*_c)->contact_host, 0, 0);
 	} else {
 		if ((*_c)->received_host.len > 0) {
 			(*_c)->aorhash = core_hash(&(*_c)->received_host, 0, 0);	
diff --git a/modules/ims_usrloc_pcscf/pcontact.h b/modules/ims_usrloc_pcscf/pcontact.h
index ee2b345..9df0004 100644
--- a/modules/ims_usrloc_pcscf/pcontact.h
+++ b/modules/ims_usrloc_pcscf/pcontact.h
@@ -70,8 +70,8 @@ void timer_pcontact(pcontact_t* _r);
 int delete_ppublic(pcontact_t* _r/*, struct ucontact* _c*/);
 int get_ppublic(pcontact_t* _r);
 int aor_to_contact(str* aor, str* contact);
-unsigned int get_hash_slot(udomain_t* _d, str* _aor);
-unsigned int get_aor_hash(udomain_t* _d, str* _aor);
+unsigned int get_hash_slot(udomain_t* _d, str* _aor, str* received_host, int received_port);
+unsigned int get_aor_hash(udomain_t* _d, str* _aor, str* received_host, int received_port);
 
 
 #endif
diff --git a/modules/ims_usrloc_pcscf/udomain.c b/modules/ims_usrloc_pcscf/udomain.c
index 23e1213..94a72db 100644
--- a/modules/ims_usrloc_pcscf/udomain.c
+++ b/modules/ims_usrloc_pcscf/udomain.c
@@ -64,6 +64,7 @@
 extern int db_mode;
 extern unsigned int hashing_type;
 extern int lookup_check_received;
+extern int match_contact_host_port;
 
 #ifdef STATISTICS
 static char *build_stat_name( str* domain, char *var_name)
@@ -228,6 +229,7 @@ int mem_insert_pcontact(struct udomain* _d, str* _contact, struct pcontact_info*
 	}
 
 	sl = ((*_c)->aorhash) & (_d->size - 1);
+	(*_c)->sl = sl;
 	slot_add(&_d->table[sl], *_c);
 	update_stat(_d->contacts, 1);
 	return 0;
@@ -242,7 +244,7 @@ void mem_delete_pcontact(udomain_t* _d, struct pcontact* _c)
 
 void mem_timer_udomain(udomain_t* _d)
 {
-	struct pcontact* ptr;
+	struct pcontact* ptr, *tmp;
 	int i;
 
 	for(i=0; i<_d->size; i++)
@@ -252,26 +254,20 @@ void mem_timer_udomain(udomain_t* _d)
 		ptr = _d->table[i].first;
 
 		while(ptr) {
-			timer_pcontact(ptr);
-			/* Remove the entire record if it is empty */
-			//if (ptr->contacts == 0) {
-			//	t = ptr;
-			//	ptr = ptr->next;
-			//	mem_delete_pcontact(_d, t);
-			//}//// else {
-			//	ptr = ptr->next;
-			//}
+		    tmp = ptr;
 			ptr = ptr->next;
+		    timer_pcontact(tmp);
 		}
+		
 		unlock_ulslot(_d, i);
 	}
 }
 
-void lock_udomain(udomain_t* _d, str* _aor)
+void lock_udomain(udomain_t* _d, str* _aor, str* _received_host, unsigned short received_port)
 {
 	unsigned int sl;
-
-	sl = get_hash_slot(_d, _aor);
+	
+	sl = get_hash_slot(_d, _aor, _received_host, received_port);
 
 #ifdef GEN_LOCK_T_PREFERED
 	lock_get(_d->table[sl].lock);
@@ -280,10 +276,10 @@ void lock_udomain(udomain_t* _d, str* _aor)
 #endif
 }
 
-void unlock_udomain(udomain_t* _d, str* _aor)
+void unlock_udomain(udomain_t* _d, str* _aor, str* _received_host, unsigned short received_port)
 {
 	unsigned int sl;
-	sl = get_hash_slot(_d, _aor);
+	sl = get_hash_slot(_d, _aor, _received_host, received_port);
 #ifdef GEN_LOCK_T_PREFERED
 	lock_release(_d->table[sl].lock);
 #else
@@ -450,34 +446,51 @@ error:
  * @struct pontact** _c - contact to return to if found (null if not found)
  * @return 0 if found <>0 if not
  */
-int get_pcontact(udomain_t* _d, str* _contact, struct pcontact** _c) {
+int get_pcontact(udomain_t* _d, str* _contact, str* _received_host, int received_port, struct pcontact** _c) {
 	unsigned int sl, i, aorhash;
 	struct pcontact* c;
 	ppublic_t* impu;
 	struct sip_uri needle_uri, impu_uri;
 	int port_match = 0;
-
+	str alias_host = {0, 0};
+	struct sip_uri contact_uri;
+	
 	if (parse_uri(_contact->s, _contact->len, &needle_uri) != 0 ) {
 		LM_ERR("failed to parse search URI [%.*s]\n", _contact->len, _contact->s);
 		return 1;
 	}
 
+	LM_DBG("Searching for contact in P-CSCF usrloc [%.*s]\n",
+				_contact->len,
+				_contact->s);
+	
 	/* search in cache */
-	aorhash = get_aor_hash(_d, _contact);
+	aorhash = get_aor_hash(_d, _contact, _received_host, received_port);
 	sl = aorhash & (_d->size - 1);
 	c = _d->table[sl].first;
 
 	for (i = 0; i < _d->table[sl].n; i++) {
-		LM_DBG("Searching for contact in P-CSCF usrloc [%.*s]\n",
-				_contact->len,
-				_contact->s);
 
 		if ((c->aorhash == aorhash) && (c->aor.len == _contact->len)
 				&& !memcmp(c->aor.s, _contact->s, _contact->len)) {
 			*_c = c;
 			return 0;
 		}
-
+		
+		if(match_contact_host_port) {
+		    LM_DBG("Comparing needle user at host:port [%.*s@%.*s:%d] and contact_user at contact_host:port [%.*s@%.*s:%d]\n", needle_uri.user.len, needle_uri.user.s, 
+			    needle_uri.host.len, needle_uri.host.s, needle_uri.port_no,
+			    c->contact_user.len, c->contact_user.s, c->contact_host.len, c->contact_host.s, c->contact_port);
+
+		    if((needle_uri.user.len == c->contact_user.len && (memcmp(needle_uri.user.s, c->contact_user.s, needle_uri.user.len) ==0)) &&
+			    (needle_uri.host.len == c->contact_host.len && (memcmp(needle_uri.host.s, c->contact_host.s, needle_uri.host.len) ==0)) &&
+			    (needle_uri.port_no == c->contact_port)) {
+			LM_DBG("Match!!\n");
+			*_c = c;
+			return 0;
+		    }
+		}
+		
 		LM_DBG("Searching for [%.*s] and comparing to [%.*s]\n", _contact->len, _contact->s, c->aor.len, c->aor.s);
 
 		/* hosts HAVE to match */
@@ -543,13 +556,23 @@ int get_pcontact(udomain_t* _d, str* _contact, struct pcontact** _c) {
 		}
 
 		/* user parts must match (if not wildcarded) with either primary contact OR with any userpart in the implicit set (associated URIs).. */
-		if (((needle_uri.user.len == 1)
-				&& (memcmp(needle_uri.user.s, "*", 1) == 0))
-				|| ((needle_uri.user.len == c->contact_user.len)
-						&& (memcmp(needle_uri.user.s, c->contact_user.s,
-								needle_uri.user.len) == 0))) {
+		if((needle_uri.user.len == c->contact_user.len) && (memcmp(needle_uri.user.s, c->contact_user.s,needle_uri.user.len) == 0)) {
+		    LM_DBG("Needle user part matches contact user part therefore this is a match\n");
+		    *_c = c;
+		    return 0;
+		} else if ((needle_uri.user.len == 1) && (memcmp(needle_uri.user.s, "*", 1) == 0)) { /*wild card*/
+		    LM_DBG("This a wild card user part - we must check if hosts match or needle host matches alias\n");
+		    if(memcmp(needle_uri.host.s, c->contact_host.s, needle_uri.host.len) == 0) {
+			LM_DBG("Needle host matches contact host therefore this is a match\n");
 			*_c = c;
 			return 0;
+		    } else if ((parse_uri(c->aor.s, c->aor.len, &contact_uri) == 0) && ((get_alias_host_from_contact(&contact_uri.params, &alias_host)) == 0) &&
+			    (memcmp(needle_uri.host.s, alias_host.s, alias_host.len) == 0)) {
+			LM_DBG("Needle host matches contact alias therefore this is a match\n");
+			*_c = c;
+			return 0;
+			
+		    }
 		}
 
 		/* check impus user parts */
@@ -591,8 +614,9 @@ int get_pcontact_by_src(udomain_t* _d, str * _host, unsigned short _port, unsign
 	sprintf(p, "%d", _port);
 	s_contact.s = c_contact;
 	s_contact.len = strlen(c_contact);
-
-	ret = get_pcontact(_d, &s_contact, _c);
+	
+	LM_DBG("Trying to find contact by src with URI: [%.*s]\n", s_contact.len, s_contact.s);
+	ret = get_pcontact(_d, &s_contact, _host, _port, _c);
 
 	return ret;
 }
@@ -661,10 +685,10 @@ int assert_identity(udomain_t* _d, str * _host, unsigned short _port, unsigned s
 	return 0; /* Nothing found */
 }
 
-int delete_pcontact(udomain_t* _d, str* _aor, struct pcontact* _c)
+int delete_pcontact(udomain_t* _d, str* _aor, str* _received_host, int _received_port, struct pcontact* _c)
 {
 	if (_c==0) {
-		if (get_pcontact(_d, _aor, &_c) > 0) {
+		if (get_pcontact(_d, _aor, _received_host, _received_port, &_c) > 0) {
 			return 0;
 		}
 	}
@@ -902,14 +926,14 @@ int preload_udomain(db1_con_t* _c, udomain_t* _d)
 						aor.len, aor.s, _d->name->s);
 				continue;
 			}
-			lock_udomain(_d, &aor);
+			lock_udomain(_d, &aor, &ci->received_host, ci->received_port);
 
 			if ( (mem_insert_pcontact(_d, &aor, ci, &c)) != 0) {
 				LM_ERR("inserting contact failed\n");
-				unlock_udomain(_d, &aor);
+				unlock_udomain(_d, &aor, &ci->received_host, ci->received_port);
 				goto error1;
 			}
-			unlock_udomain(_d, &aor);
+			unlock_udomain(_d, &aor, &ci->received_host, ci->received_port);
 		}
 
 		if (DB_CAPABILITY(ul_dbf, DB_CAP_FETCH)) {
diff --git a/modules/ims_usrloc_pcscf/udomain.h b/modules/ims_usrloc_pcscf/udomain.h
index 34249e2..2446a9c 100644
--- a/modules/ims_usrloc_pcscf/udomain.h
+++ b/modules/ims_usrloc_pcscf/udomain.h
@@ -67,8 +67,8 @@ void mem_timer_udomain(udomain_t* _d);
 int mem_insert_pcontact(struct udomain* _d, str* _contact, struct pcontact_info* _ci, struct pcontact** _c);
 void mem_delete_pcontact(udomain_t* _d, struct pcontact* _r);
 
-void lock_udomain(udomain_t* _d, str *_aor);
-void unlock_udomain(udomain_t* _d, str *_aor);
+void lock_udomain(udomain_t* _d, str *_aor, str* _received_host, unsigned short int received_port);
+void unlock_udomain(udomain_t* _d, str *_aor, str* _received_host, unsigned short int received_port);
 
 void lock_ulslot(udomain_t* _d, int i);
 void unlock_ulslot(udomain_t* _d, int i);
@@ -76,10 +76,10 @@ void unlock_ulslot(udomain_t* _d, int i);
 int update_rx_regsession(struct udomain* _d, str* session_id, struct pcontact* _c);
 int update_pcontact(struct udomain* _d, struct pcontact_info* _ci, struct pcontact* _c);
 int insert_pcontact(struct udomain* _d, str* _contact, struct pcontact_info* _ci, struct pcontact** _r);
-int get_pcontact(udomain_t* _d, str* _aor, struct pcontact** _r);
+int get_pcontact(udomain_t* _d, str* _aor, str* _received_host, int received_port, struct pcontact** _r);
 int get_pcontact_by_src(udomain_t* _d, str * _host, unsigned short _port, unsigned short _proto, struct pcontact** _c);
 int assert_identity(udomain_t* _d, str * _host, unsigned short _port, unsigned short _proto, str * _identity);
-int delete_pcontact(udomain_t* _d, str* _aor, struct pcontact* _r);
+int delete_pcontact(udomain_t* _d, str* _aor, str* _received_host, int _received_port, struct pcontact* _r);
 int update_security(udomain_t* _d, security_type _t, security_t* _s, struct pcontact* _c);
 int update_temp_security(udomain_t* _d, security_type _t, security_t* _s, struct pcontact* _c);
 
diff --git a/modules/ims_usrloc_pcscf/ul_mod.c b/modules/ims_usrloc_pcscf/ul_mod.c
index 3fbab3c..11079da 100644
--- a/modules/ims_usrloc_pcscf/ul_mod.c
+++ b/modules/ims_usrloc_pcscf/ul_mod.c
@@ -86,6 +86,7 @@ int ul_fetch_rows 	= 2000;
 int hashing_type 	= 0;						/*!< has type for storing P-CSCF contacts - 0 - use full contact AOR, 1 - use IP:PORT only */
 
 int lookup_check_received = 1;						/*!< Should we check received on lookup? */
+int match_contact_host_port = 1;					/*!< Should we match contact just based on rui host and port*/
 
 db1_con_t* ul_dbh = 0;
 db_func_t ul_dbf; 
@@ -112,6 +113,7 @@ static param_export_t params[] = {
 	{"db_mode",             INT_PARAM, &db_mode         },
 	{"hashing_type",		INT_PARAM, &hashing_type	},
 	{"lookup_check_received",		INT_PARAM, &lookup_check_received	},
+	{"match_contact_host_port",		INT_PARAM, &match_contact_host_port	},
 
 	{0, 0, 0}
 };
diff --git a/modules/ims_usrloc_pcscf/usrloc.c b/modules/ims_usrloc_pcscf/usrloc.c
index b833eee..9de69b0 100644
--- a/modules/ims_usrloc_pcscf/usrloc.c
+++ b/modules/ims_usrloc_pcscf/usrloc.c
@@ -84,35 +84,106 @@ int bind_usrloc(usrloc_api_t* api) {
 	return 0;
 }
 
+#define ALIAS        "alias="
+#define ALIAS_LEN (sizeof(ALIAS) - 1)
+
+int get_alias_host_from_contact(str *contact_uri_params, str *alias_host) {
+    char *rest, *sep;
+    unsigned int rest_len;
+    
+    rest = contact_uri_params->s;
+    rest_len = contact_uri_params->len;
+    if (rest_len == 0) {
+        LM_DBG("no params\n");
+        return -1;
+    }
+
+    /*Get full alias parameter*/
+    while (rest_len >= ALIAS_LEN) {
+        if (strncmp(rest, ALIAS, ALIAS_LEN) == 0) break;
+        sep = memchr(rest, 59 /* ; */, rest_len);
+        if (sep == NULL) {
+            LM_DBG("no alias param\n");
+            return -1;
+        } else {
+            rest_len = rest_len - (sep - rest + 1);
+            rest = sep + 1;
+        }
+    }
+
+    if (rest_len < ALIAS_LEN) {
+        LM_DBG("no alias param\n");
+        return -1;
+    }
+
+    alias_host->s = rest + ALIAS_LEN;
+    alias_host->len = rest_len - ALIAS_LEN;
+
+    /*Get host from alias*/
+    rest = memchr(alias_host->s, 126 /* ~ */, alias_host->len);
+    if (rest == NULL) {
+        LM_ERR("no '~' in alias param value\n");
+        return -1;
+    }
+    alias_host->len = rest - alias_host->s;
+    LM_DBG("Alias host to return [%.*s]\n", alias_host->len, alias_host->s);
+    return 0;
+}
+
+
 /* return the slot id for inserting contacts in the hash */
-unsigned int get_hash_slot(udomain_t* _d, str* _aor){
-	struct sip_uri contact_uri;
-	unsigned int sl;
-
-	if ((hashing_type == 0) /*use full AOR for hash*/ || (parse_uri(_aor->s, _aor->len, &contact_uri) != 0)) {
-		if (hashing_type!=0) {
-			LM_DBG("Unable to get contact host:port from contact header [%.*s]... falling back to full AOR\n", _aor->len, _aor->s);
-		}
-		sl = core_hash(_aor, 0, _d->size);
-	} else {
-		sl = core_hash(&contact_uri.host, 0, _d->size);
-	}
+unsigned int get_hash_slot(udomain_t* _d, str* _aor, str* received_host, int received_port) {
+    struct sip_uri contact_uri;
+    unsigned int sl;
+    str alias_host = {0, 0};
 
-	return sl;
+    if ((hashing_type == 0) /*use full AOR for hash*/ || (parse_uri(_aor->s, _aor->len, &contact_uri) != 0)) {
+	if (hashing_type != 0) {
+	    LM_DBG("Unable to get contact host:port from contact header [%.*s]... falling back to full AOR\n", _aor->len, _aor->s);
+	}
+	sl = core_hash(_aor, 0, _d->size);
+    } else {
+	if ( received_host && (memcmp(contact_uri.host.s, received_host->s, received_host->len) != 0)) {
+	    LM_DBG("Looks like this contact is natted - contact URI: [%.*s] but came from received_host: [%.*s] so will use received_host for hash\n", contact_uri.host.len, contact_uri.host.s,
+		    received_host->len, received_host->s);
+	    sl = core_hash(received_host, 0, _d->size);
+	} else if (((get_alias_host_from_contact(&contact_uri.params, &alias_host)) == 0 && (memcmp(contact_uri.host.s, alias_host.s, alias_host.len) != 0))) {
+	    LM_DBG("Looks like this contact is natted - as it has alias [%.*s] different from contact URI [%.*s] so will use alias for hash\n", 
+		    alias_host.len, alias_host.s, contact_uri.host.len, contact_uri.host.s);
+	    sl = core_hash(&alias_host, 0, _d->size);
+	}else {
+	    LM_DBG("using host for hash [%.*s]\n", contact_uri.host.len, contact_uri.host.s);
+	    sl = core_hash(&contact_uri.host, 0, _d->size);
+	}
+    } 
+    LM_DBG("Returning hash slot: [%d]\n", sl);
+    return sl;
 }
 
-unsigned int get_aor_hash(udomain_t* _d, str* _aor) {
-	struct sip_uri contact_uri;
-	unsigned int aorhash;
-
-	if ((hashing_type == 0) || (parse_uri(_aor->s, _aor->len, &contact_uri) != 0)) {
-		if (hashing_type !=0) {
-			LM_DBG("Unable to get contact host:port from contact header [%.*s]... falling back to full AOR\n", _aor->len, _aor->s);
-		}
-		aorhash = core_hash(_aor, 0, 0);
-	} else {
-		LM_DBG("using host in lookup [%.*s]\n", contact_uri.host.len, contact_uri.host.s);
-		aorhash = core_hash(&contact_uri.host, 0, 0);
+unsigned int get_aor_hash(udomain_t* _d, str* _aor, str* received_host, int received_port) {
+    struct sip_uri contact_uri;
+    unsigned int aorhash;
+    str alias_host = {0, 0};
+
+    if ((hashing_type == 0) /*use full AOR for hash*/ || (parse_uri(_aor->s, _aor->len, &contact_uri) != 0)) {
+	if (hashing_type != 0) {
+	    LM_DBG("Unable to get contact host:port from contact header [%.*s]... falling back to full AOR\n", _aor->len, _aor->s);
+	}
+	aorhash = core_hash(_aor, 0, 0);
+    } else {
+	if ( received_host && (memcmp(contact_uri.host.s, received_host->s, received_host->len) != 0)) {
+	    LM_DBG("Looks like this contact is natted - contact URI: [%.*s] but came from received_host: [%.*s] so will use received_host for hash\n", contact_uri.host.len, contact_uri.host.s,
+		    received_host->len, received_host->s);
+	    aorhash = core_hash(received_host, 0, 0);
+	} else if (((get_alias_host_from_contact(&contact_uri.params, &alias_host)) == 0 && (memcmp(contact_uri.host.s, alias_host.s, alias_host.len) != 0))) {
+	    LM_DBG("Looks like this contact is natted - as it has alias [%.*s] different from contact URI [%.*s] so will use alias for hash\n", 
+		    alias_host.len, alias_host.s, contact_uri.host.len, contact_uri.host.s);
+	    aorhash = core_hash(&alias_host, 0, 0);
+	}else {
+	    LM_DBG("using host for hash [%.*s]\n", contact_uri.host.len, contact_uri.host.s);
+	    aorhash = core_hash(&contact_uri.host, 0, 0);
 	}
-	return aorhash;
+    } 
+    LM_DBG("Returning hash slot: [%d]\n", aorhash);
+    return aorhash;
 }
diff --git a/modules/ims_usrloc_pcscf/usrloc.h b/modules/ims_usrloc_pcscf/usrloc.h
index 30fe76a..11bcc9d 100644
--- a/modules/ims_usrloc_pcscf/usrloc.h
+++ b/modules/ims_usrloc_pcscf/usrloc.h
@@ -64,6 +64,8 @@
 struct hslot;		/*!< Hash table slot */
 struct socket_info;
 
+int get_alias_host_from_contact(str *contact_uri_params, str *alias_host);
+
 struct udomain {
 	str* name;                 /*!< Domain name (NULL terminated) */
 	int size;                  /*!< Hash table size */
@@ -183,6 +185,7 @@ typedef struct pcontact_info {
  */
 typedef struct pcontact {
 	unsigned int aorhash; 					/*!< Hash over address of record */
+	unsigned int sl;                                        /*!< slot number */
 	struct hslot* slot; 					/*!< Collision slot in the hash table array we belong to */
 	str* domain; 							/*!< Pointer to domain we belong to (null terminated string) */
 	str aor;			 					/*!< Address of record */
@@ -209,19 +212,19 @@ typedef struct pcontact {
 	struct pcontact* next; 					/*!< Previous item in the hash entry */
 } pcontact_t;
 
-typedef int (*get_pcontact_t)(struct udomain* _d, str* _contact, struct pcontact** _c);
+typedef int (*get_pcontact_t)(struct udomain* _d, str* _contact, str* _received_host, int received_port, struct pcontact** _c);
 
 typedef int (*get_pcontact_by_src_t)(struct udomain* _d, str * _host, unsigned short _port, unsigned short _proto, struct pcontact** _c);
 
 typedef int (*assert_identity_t)(struct udomain* _d, str * _host, unsigned short _port, unsigned short _proto, str * _identity);
 
 typedef int (*insert_pcontact_t)(struct udomain* _d, str* _aor, struct pcontact_info* ci, struct pcontact** _c);
-typedef int (*delete_pcontact_t)(struct udomain* _d, str* _aor, struct pcontact* _c);
+typedef int (*delete_pcontact_t)(struct udomain* _d, str* _aor, str* _received_host, int received_port, struct pcontact* _c);
 typedef int (*update_pcontact_t)(struct udomain* _d, struct pcontact_info* ci, struct pcontact* _c);
 typedef int (*update_rx_regsession_t)(struct udomain* _d, str* session_id, struct pcontact* _c);
 
-typedef void (*lock_udomain_t)(struct udomain* _d, str *_aor);
-typedef void (*unlock_udomain_t)(struct udomain* _d, str *_aor);
+typedef void (*lock_udomain_t)(struct udomain* _d, str *_aor, str* _received_host, unsigned short received_port);
+typedef void (*unlock_udomain_t)(struct udomain* _d, str *_aor, str* _received_host, unsigned short received_port);
 typedef int (*register_udomain_t)(const char* _n, struct udomain** _d);
 typedef int (*get_udomain_t)(const char* _n, udomain_t** _d);
 typedef int (*get_all_ucontacts_t)(void* buf, int len, unsigned int flags, unsigned int part_idx, unsigned int part_max);
diff --git a/modules/ims_usrloc_scscf/Makefile b/modules/ims_usrloc_scscf/Makefile
index 03e6b57..97859c8 100644
--- a/modules/ims_usrloc_scscf/Makefile
+++ b/modules/ims_usrloc_scscf/Makefile
@@ -1,6 +1,5 @@
-# $Id$
 #
-# Usrloc module Makefile
+# ims_Usrloc_scscf module Makefile
 #
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
diff --git a/modules/ims_usrloc_scscf/bin_utils.c b/modules/ims_usrloc_scscf/bin_utils.c
index 958dc26..0588380 100644
--- a/modules/ims_usrloc_scscf/bin_utils.c
+++ b/modules/ims_usrloc_scscf/bin_utils.c
@@ -898,7 +898,14 @@ ims_subscription *bin_decode_ims_subscription(bin_data *x)
 		if (!bin_decode_service_profile(x,imss->service_profiles+i)) goto error;
 
 	imss->lock = lock_alloc();
-	imss->lock = lock_init(imss->lock);
+	if (imss->lock==0){
+		goto error;
+	}
+	if (lock_init(imss->lock)==0){
+		lock_dealloc(imss->lock);
+		imss->lock=0;
+		goto error;
+	}
 	imss->ref_count = 1;
 
 	return imss;
diff --git a/modules/ims_usrloc_scscf/contact_hslot.c b/modules/ims_usrloc_scscf/contact_hslot.c
new file mode 100644
index 0000000..167894a
--- /dev/null
+++ b/modules/ims_usrloc_scscf/contact_hslot.c
@@ -0,0 +1,221 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2012 Smile Communications, jason.penton at smilecoms.com
+ * Copyright (C) 2012 Smile Communications, richard.good at smilecoms.com
+ * 
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Fokus. 
+ * Copyright (C) 2004-2006 FhG Fokus
+ * Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ */
+
+#include "contact_hslot.h"
+
+/*! number of locks */
+int contacts_locks_no=4;
+/*! global list of locks */
+gen_lock_set_t* contacts_locks=0;
+
+
+/*!
+ * \brief Initialize locks for the hash table
+ * \return 0 on success, -1 on failure
+ */
+int init_contacts_locks(void)
+{
+	int i;
+	i = contacts_locks_no;
+	do {
+		if ((( contacts_locks=lock_set_alloc(i))!=0)&&
+				(lock_set_init(contacts_locks)!=0))
+		{
+			contacts_locks_no = i;
+			LM_INFO("locks array size %d\n", contacts_locks_no);
+			return 0;
+
+		}
+		if (contacts_locks){
+			lock_set_dealloc(contacts_locks);
+			contacts_locks=0;
+		}
+		i--;
+		if(i==0)
+		{
+			LM_ERR("failed to allocate locks\n");
+			return -1;
+		}
+	} while (1);
+}
+
+
+/*!
+ * \brief Unlock all locks on the list
+ */
+void unlock_contacts_locks(void)
+{
+	unsigned int i;
+
+	if (contacts_locks==0)
+		return;
+
+	for (i=0;i<contacts_locks_no;i++) {
+#ifdef GEN_LOCK_T_PREFERED
+		lock_release(&contacts_locks->locks[i]);
+#else
+		ul_release_idx(i);
+#endif
+	};
+}
+
+
+/*!
+ * \brief Destroy all locks on the list
+ */
+void destroy_contacts_locks(void)
+{
+	if (contacts_locks !=0){
+		lock_set_destroy(contacts_locks);
+		lock_set_dealloc(contacts_locks);
+	};
+}
+
+#ifndef GEN_LOCK_T_PREFERED
+/*!
+ * \brief Lock a lock with a certain index
+ * \param idx lock index
+ */
+void lock_contacts_idx(int idx)
+{
+	lock_set_get(contacts_locks, idx);
+}
+
+
+/*!
+ * \brief Release a lock with a certain index
+ * \param idx lock index
+ */
+void release_contacts_idx(int idx)
+{
+	lock_set_release(contacts_locks, idx);
+}
+#endif
+
+/*!
+ * \brief Initialize cache slot structure
+ * \param _d domain for the hash slot
+ * \param _s hash slot
+ * \param n used to get the slot number (modulo number or locks)
+ */
+void init_contact_slot(contact_hslot_t* _s, int n)
+{
+	_s->n = 0;
+	_s->first = 0;
+	_s->last = 0;
+//	_s->d = _d;
+
+#ifdef GEN_LOCK_T_PREFERED
+	_s->lock = &contacts_locks->locks[n%contacts_locks_no];
+#else
+	_s->lockidx = n%contacts_locks_no;
+#endif
+}
+
+
+/*!
+ * \brief Deinitialize given slot structure
+ * \param _s hash slot
+ */
+void deinit_contact_slot(contact_hslot_t* _s)
+{
+	struct ucontact* ptr;
+	
+	     /* Remove all elements */
+	while(_s->first) {
+		ptr = _s->first;
+		_s->first = _s->first->next;
+		free_ucontact(ptr);
+	}
+	
+	_s->n = 0;
+	_s->last = 0;
+//    _s->d = 0;
+}
+
+
+/*!
+ * \brief Add an element to an slot's linked list
+ * \param _s hash slot
+ * \param _r added record
+ */
+void contact_slot_add(contact_hslot_t* _s, struct ucontact* _c)
+{
+	if (_s->n == 0) {
+		_s->first = _s->last = _c;
+	} else {
+		_c->prev = _s->last;
+		_s->last->next = _c;
+		_s->last = _c;
+	}
+	_s->n++;
+	_c->slot = _s;
+}
+
+
+/*!
+ * \brief Remove an element from slot linked list
+ * \param _s hash slot
+ * \param _r removed record
+ */
+void contact_slot_rem(contact_hslot_t* _s, struct ucontact* _c)
+{
+	if (_c->prev) {
+		_c->prev->next = _c->next;
+	} else {
+		_s->first = _c->next;
+	}
+
+	if (_c->next) {
+		_c->next->prev = _c->prev;
+	} else {
+		_s->last = _c->prev;
+	}
+
+	_c->prev = _c->next = 0;
+	_c->slot = 0;
+	_s->n--;
+}
+
diff --git a/modules/ims_usrloc_scscf/contact_hslot.h b/modules/ims_usrloc_scscf/contact_hslot.h
new file mode 100644
index 0000000..409bd9f
--- /dev/null
+++ b/modules/ims_usrloc_scscf/contact_hslot.h
@@ -0,0 +1,107 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2012 Smile Communications, jason.penton at smilecoms.com
+ * Copyright (C) 2012 Smile Communications, richard.good at smilecoms.com
+ * 
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Fokus. 
+ * Copyright (C) 2004-2006 FhG Fokus
+ * Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ */
+
+#ifndef CONTACT_HSLOT_H
+#define	CONTACT_HSLOT_H
+
+#include "../../locking.h"
+#include "ucontact.h"
+struct ucontact;
+
+typedef struct contact_hslot {
+	int n;                  /*!< Number of elements in the collision slot */
+	struct ucontact* first;  /*!< First element in the list */
+	struct ucontact* last;   /*!< Last element in the list */
+#ifdef GEN_LOCK_T_PREFERED
+	gen_lock_t *lock;       /*!< Lock for hash entry - fastlock */
+#else
+	int lockidx;            /*!< Lock index for hash entry - the rest*/
+#endif
+} contact_hslot_t;
+
+/*! \brief
+ * Initialize slot structure
+ */
+void init_contact_slot(contact_hslot_t* _s, int n);
+
+
+/*! \brief
+ * Deinitialize given slot structure
+ */
+void deinit_contact_slot(contact_hslot_t* _s);
+
+
+/*! \brief
+ * Add an element to slot linked list
+ */
+void contact_slot_add(contact_hslot_t* _s, struct ucontact* _c);
+
+
+/*! \brief
+ * Remove an element from slot linked list
+ */
+void contact_slot_rem(contact_hslot_t* _s, struct ucontact* _c);
+
+
+/*!
+ * \brief Initialize locks for the hash table
+ * \return 0 on success, -1 on failure
+ */
+int init_contacts_locks(void);
+
+
+/*!
+ * \brief Destroy all locks on the list
+ */
+void unlock_contacts_locks(void);
+void destroy_contacts_locks(void);
+
+#ifndef GEN_LOCK_T_PREFERED
+void lock_contacts_idx(int idx);
+void release_contacts_idx(int idx);
+#endif
+
+#endif	/* CONTACT_HSLOT_H */
+
diff --git a/modules/ims_usrloc_scscf/dlist.c b/modules/ims_usrloc_scscf/dlist.c
index 538684f..5c7b306 100644
--- a/modules/ims_usrloc_scscf/dlist.c
+++ b/modules/ims_usrloc_scscf/dlist.c
@@ -87,7 +87,6 @@ static inline int find_dlist(str* _n, dlist_t** _d)
 	return 1;
 }
 
-
 /*!
  * \brief Get all contacts from the memory, in partitions if wanted
  * \see get_all_ucontacts
@@ -99,104 +98,106 @@ static inline int find_dlist(str* _n, dlist_t** _d)
  * \return 0 on success, positive if buffer size was not sufficient, negative on failure
  */
 static inline int get_all_mem_ucontacts(void *buf, int len, unsigned int flags,
-								unsigned int part_idx, unsigned int part_max)
-{
-	dlist_t *p;
-	impurecord_t *r;
-	ucontact_t *c;
-	void *cp;
-	int shortage;
-	int needed;
-	int i = 0;
-	cp = buf;
-	shortage = 0;
-	/* Reserve space for terminating 0000 */
-	len -= sizeof(c->c.len);
-
-	for (p = root; p != NULL; p = p->next) {
-
-		for(i=0; i<p->d->size; i++) {
-
-			if ( (i % part_max) != part_idx )
-				continue;
-
-			lock_ulslot(p->d, i);
-			if(p->d->table[i].n<=0)
-			{
-				unlock_ulslot(p->d, i);
-				continue;
+	unsigned int part_idx, unsigned int part_max) {
+    dlist_t *p;
+    impurecord_t *r;
+    ucontact_t *c;
+    void *cp;
+    int shortage;
+    int needed;
+    int i,j;
+    cp = buf;
+    shortage = 0;
+    /* Reserve space for terminating 0000 */
+    len -= sizeof (c->c.len);
+
+    for (p = root; p != NULL; p = p->next) {
+
+	for (i = 0; i < p->d->size; i++) {
+
+	    if ((i % part_max) != part_idx)
+		continue;
+	    LM_DBG("LOCKING ULSLOT %d\n", i);
+	    lock_ulslot(p->d, i);
+	    if (p->d->table[i].n <= 0) {
+	    	LM_DBG("UNLOCKING ULSLOT %d\n", i);
+		unlock_ulslot(p->d, i);
+		continue;
+	    }
+	    for (r = p->d->table[i].first; r != NULL; r = r->next) {
+		while (j<MAX_CONTACTS_PER_IMPU && (c = r->newcontacts[j++])) {
+		    if (c->c.len <= 0)
+			continue;
+		    /*
+		     * List only contacts that have all requested
+		     * flags set
+		     */
+		    if ((c->cflags & flags) != flags)
+			continue;
+		    if (c->received.s) {
+			needed = (int) (sizeof (c->received.len)
+				+ c->received.len + sizeof (c->sock)
+				+ sizeof (c->cflags) + sizeof (c->path.len)
+				+ c->path.len);
+			if (len >= needed) {
+			    memcpy(cp, &c->received.len, sizeof (c->received.len));
+			    cp = (char*) cp + sizeof (c->received.len);
+			    memcpy(cp, c->received.s, c->received.len);
+			    cp = (char*) cp + c->received.len;
+			    memcpy(cp, &c->sock, sizeof (c->sock));
+			    cp = (char*) cp + sizeof (c->sock);
+			    memcpy(cp, &c->cflags, sizeof (c->cflags));
+			    cp = (char*) cp + sizeof (c->cflags);
+			    memcpy(cp, &c->path.len, sizeof (c->path.len));
+			    cp = (char*) cp + sizeof (c->path.len);
+			    memcpy(cp, c->path.s, c->path.len);
+			    cp = (char*) cp + c->path.len;
+			    len -= needed;
+			} else {
+			    shortage += needed;
 			}
-			for (r = p->d->table[i].first; r != NULL; r = r->next) {
-				for (c = r->contacts; c != NULL; c = c->next) {
-					if (c->c.len <= 0)
-						continue;
-					/*
-					 * List only contacts that have all requested
-					 * flags set
-					 */
-					if ((c->cflags & flags) != flags)
-						continue;
-					if (c->received.s) {
-						needed = (int)(sizeof(c->received.len)
-								+ c->received.len + sizeof(c->sock)
-								+ sizeof(c->cflags) + sizeof(c->path.len)
-								+ c->path.len);
-						if (len >= needed) {
-							memcpy(cp,&c->received.len,sizeof(c->received.len));
-							cp = (char*)cp + sizeof(c->received.len);
-							memcpy(cp, c->received.s, c->received.len);
-							cp = (char*)cp + c->received.len;
-							memcpy(cp, &c->sock, sizeof(c->sock));
-							cp = (char*)cp + sizeof(c->sock);
-							memcpy(cp, &c->cflags, sizeof(c->cflags));
-							cp = (char*)cp + sizeof(c->cflags);
-							memcpy(cp, &c->path.len, sizeof(c->path.len));
-							cp = (char*)cp + sizeof(c->path.len);
-							memcpy(cp, c->path.s, c->path.len);
-							cp = (char*)cp + c->path.len;
-							len -= needed;
-						} else {
-							shortage += needed;
-						}
-					} else {
-						needed = (int)(sizeof(c->c.len) + c->c.len +
-							sizeof(c->sock) + sizeof(c->cflags) +
-							sizeof(c->path.len) + c->path.len);
-						if (len >= needed) {
-							memcpy(cp, &c->c.len, sizeof(c->c.len));
-							cp = (char*)cp + sizeof(c->c.len);
-							memcpy(cp, c->c.s, c->c.len);
-							cp = (char*)cp + c->c.len;
-							memcpy(cp, &c->sock, sizeof(c->sock));
-							cp = (char*)cp + sizeof(c->sock);
-							memcpy(cp, &c->cflags, sizeof(c->cflags));
-							cp = (char*)cp + sizeof(c->cflags);
-							memcpy(cp, &c->path.len, sizeof(c->path.len));
-							cp = (char*)cp + sizeof(c->path.len);
-							memcpy(cp, c->path.s, c->path.len);
-							cp = (char*)cp + c->path.len;
-							len -= needed;
-						} else {
-							shortage += needed;
-						}
-					}
-				}
+		    } else {
+			needed = (int) (sizeof (c->c.len) + c->c.len +
+				sizeof (c->sock) + sizeof (c->cflags) +
+				sizeof (c->path.len) + c->path.len);
+			if (len >= needed) {
+			    memcpy(cp, &c->c.len, sizeof (c->c.len));
+			    cp = (char*) cp + sizeof (c->c.len);
+			    memcpy(cp, c->c.s, c->c.len);
+			    cp = (char*) cp + c->c.len;
+			    memcpy(cp, &c->sock, sizeof (c->sock));
+			    cp = (char*) cp + sizeof (c->sock);
+			    memcpy(cp, &c->cflags, sizeof (c->cflags));
+			    cp = (char*) cp + sizeof (c->cflags);
+			    memcpy(cp, &c->path.len, sizeof (c->path.len));
+			    cp = (char*) cp + sizeof (c->path.len);
+			    memcpy(cp, c->path.s, c->path.len);
+			    cp = (char*) cp + c->path.len;
+			    len -= needed;
+			} else {
+			    shortage += needed;
 			}
-			unlock_ulslot(p->d, i);
+		    }
 		}
+	    }
+#ifdef EXTRA_DEBUG
+	    LM_DBG("UN-LOCKING ULSLOT %d\n", i);
+#endif
+	    unlock_ulslot(p->d, i);
 	}
-	/* len < 0 is possible, if size of the buffer < sizeof(c->c.len) */
-	if (len >= 0)
-		memset(cp, 0, sizeof(c->c.len));
+    }
+    /* len < 0 is possible, if size of the buffer < sizeof(c->c.len) */
+    if (len >= 0)
+	memset(cp, 0, sizeof (c->c.len));
 
-	/* Shouldn't happen */
-	if (shortage > 0 && len > shortage) {
-		abort();
-	}
+    /* Shouldn't happen */
+    if (shortage > 0 && len > shortage) {
+	abort();
+    }
 
-	shortage -= len;
+    shortage -= len;
 
-	return shortage > 0 ? shortage : 0;
+    return shortage > 0 ? shortage : 0;
 }
 
 
diff --git a/modules/ims_usrloc_scscf/hslot_sp.h b/modules/ims_usrloc_scscf/hslot_sp.h
index 6450979..134953d 100644
--- a/modules/ims_usrloc_scscf/hslot_sp.h
+++ b/modules/ims_usrloc_scscf/hslot_sp.h
@@ -95,8 +95,8 @@ int subs_init_locks(void);
 /*!
  * \brief Destroy all locks on the list
  */
-void subs__unlock_locks(void);
-void subs__destroy_locks(void);
+void subs_unlock_locks(void);
+void subs_destroy_locks(void);
 
 #ifndef GEN_LOCK_T_PREFERED
 void subs__lock_idx(int idx);
diff --git a/modules/ims_usrloc_scscf/impurecord.c b/modules/ims_usrloc_scscf/impurecord.c
index fc4690f..9c5214b 100644
--- a/modules/ims_usrloc_scscf/impurecord.c
+++ b/modules/ims_usrloc_scscf/impurecord.c
@@ -60,6 +60,8 @@
 #include "../../lib/ims/useful_defs.h"
 #include "../../modules/dialog_ng/dlg_load.h"
 #include "../../modules/dialog_ng/dlg_hash.h"
+#include "contact_hslot.h"
+#include "dlist.h"
 
 /*! contact matching mode */
 int matching_mode = CONTACT_ONLY;
@@ -73,6 +75,7 @@ extern int db_mode;
 
 extern int sub_dialog_hash_size;
 extern shtable_t sub_dialog_table;
+extern struct contact_list* contact_list;
 
 extern struct dlg_binds dlgb;
 
@@ -147,16 +150,9 @@ out_of_memory:
  * \param _r freed record list
  */
 void free_impurecord(impurecord_t* _r) {
-    ucontact_t* ptr;
     struct ul_callback *cbp, *cbp_tmp;
     struct _reg_subscriber* subscriber, *s_tmp;
 
-    while (_r->contacts) {
-        ptr = _r->contacts;
-        _r->contacts = _r->contacts->next;
-        free_ucontact(ptr);
-    }
-
     //free IMS specific extensions
     if (_r->ccf1.s)
         shm_free(_r->ccf1.s);
@@ -211,7 +207,8 @@ void free_impurecord(impurecord_t* _r) {
  */
 void print_impurecord(FILE* _f, impurecord_t* _r) {
     ucontact_t* ptr;
-
+    int i;
+    
     fprintf(_f, "...Record(%p)...\n", _r);
     fprintf(_f, "domain : '%.*s'\n", _r->domain->len, ZSW(_r->domain->s));
     fprintf(_f, "public_identity    : '%.*s'\n", _r->public_identity.len, ZSW(_r->public_identity.s));
@@ -240,11 +237,9 @@ void print_impurecord(FILE* _f, impurecord_t* _r) {
         subscriber = subscriber->next;
     }
 
-    if (_r->contacts) {
-        ptr = _r->contacts;
-        while (ptr) {
+    if (_r->newcontacts[0]) {
+        while ((ptr=_r->newcontacts[i++])) {
             print_ucontact(_f, ptr);
-            ptr = ptr->next;
         }
     }
 
@@ -262,41 +257,21 @@ void print_impurecord(FILE* _f, impurecord_t* _r) {
  * \return pointer to new created contact on success, 0 on failure
  */
 ucontact_t* mem_insert_ucontact(impurecord_t* _r, str* _c, ucontact_info_t* _ci) {
-    ucontact_t* ptr, *prev = 0;
     ucontact_t* c;
-
+    int sl;
+    
     if ((c = new_ucontact(_r->domain, &_r->public_identity, _c, _ci)) == 0) {
         LM_ERR("failed to create new contact\n");
         return 0;
     }
     if_update_stat(_r->slot, _r->slot->d->contacts, 1);
-
-    ptr = _r->contacts;
-
-    while (ptr) {//make sure our contacts are ordered oldest(first) to newest(last)
-        if (ptr->expires > c->expires)
-            break;
-        prev = ptr;
-        ptr = ptr->next;
-    }
-
-    if (ptr) {
-        if (!ptr->prev) {
-            ptr->prev = c;
-            c->next = ptr;
-            _r->contacts = c;
-        } else {
-            c->next = ptr;
-            c->prev = ptr->prev;
-            ptr->prev->next = c;
-            ptr->prev = c;
-        }
-    } else if (prev) {
-        prev->next = c;
-        c->prev = prev;
-    } else {
-        _r->contacts = c;
-    }
+    
+    LM_DBG("Created new contact in memory with AOR: [%.*s] and hash [%d]\n", _c->len, _c->s, c->contact_hash);
+    
+    sl = (c->contact_hash);// & (contact_list->size - 1);
+    lock_contact_slot_i(sl);
+    contact_slot_add(&contact_list->slot[sl], c);
+    unlock_contact_slot_i(sl);
 
     return c;
 }
@@ -306,18 +281,9 @@ ucontact_t* mem_insert_ucontact(impurecord_t* _r, str* _c, ucontact_info_t* _ci)
  * \param _r record this contact belongs to
  * \param _c removed contact
  */
-void mem_remove_ucontact(impurecord_t* _r, ucontact_t* _c) {
-    if (_c->prev) {
-        _c->prev->next = _c->next;
-        if (_c->next) {
-            _c->next->prev = _c->prev;
-        }
-    } else {
-        _r->contacts = _c->next;
-        if (_c->next) {
-            _c->next->prev = 0;
-        }
-    }
+void mem_remove_ucontact(ucontact_t* _c) {
+    LM_DBG("removing contact [%.*s] from slot %d\n", _c->c.len, _c->c.s, _c->contact_hash);
+    contact_slot_rem(&contact_list->slot[_c->contact_hash], _c);
 }
 
 /*!
@@ -325,7 +291,7 @@ void mem_remove_ucontact(impurecord_t* _r, ucontact_t* _c) {
  * \param _r record this contact belongs to
  * \param _c deleted contact
  */
-void mem_delete_ucontact(impurecord_t* _r, ucontact_t* _c) {
+void mem_delete_ucontact(ucontact_t* _c) {
     
     struct contact_dialog_data *dialog_data;
     //tear down dialogs in dialog data list
@@ -334,8 +300,9 @@ void mem_delete_ucontact(impurecord_t* _r, ucontact_t* _c) {
         dialog_data = dialog_data->next;
     }
     
-    mem_remove_ucontact(_r, _c);
-    if_update_stat(_r->slot, _r->slot->d->contacts, -1);
+    mem_remove_ucontact(_c);
+    //TODO: fix stats
+//    if_update_stat(_r->slot, _r->slot->d->contacts, -1);
     free_ucontact(_c);
 }
 
@@ -347,23 +314,26 @@ void mem_delete_ucontact(impurecord_t* _r, ucontact_t* _c) {
  * \param _r processed record
  */
 static inline void nodb_timer(impurecord_t* _r) {
-    ucontact_t* ptr, *t;
-    
+    ucontact_t* ptr;
+    int i, flag, mustdeleteimpu=1, hascontacts=0;
+    udomain_t* udomain;
     unsigned int hash_code = 0;
+    impurecord_t* tmp_impu;
 
     reg_subscriber *s;
     subs_t* sub_dialog;
 
     get_act_time();
-
+    
     s = _r->shead;
     LM_DBG("Checking validity of IMPU: <%.*s> registration subscriptions\n", _r->public_identity.len, _r->public_identity.s);
     while (s) {
-        if (!valid_subscriber(s)) {
+        if (!valid_subscriber(s, act_time)) {
             LM_DBG("DBG:registrar_timer: Subscriber with watcher_contact <%.*s> and presentity uri <%.*s> expired and removed.\n",
                     s->watcher_contact.len, s->watcher_contact.s, s->presentity_uri.len, s->presentity_uri.s);
             delete_subscriber(_r, s);
         } else {
+	    mustdeleteimpu = 0;
             LM_DBG("DBG:registrar_timer: Subscriber with watcher_contact <%.*s> and presentity uri <%.*s> is valid and expires in %d seconds.\n",
                     s->watcher_contact.len, s->watcher_contact.s, s->presentity_uri.len, s->presentity_uri.s,
                     (unsigned int) (s->expires - time(NULL)));
@@ -385,38 +355,44 @@ static inline void nodb_timer(impurecord_t* _r) {
         s = s->next;
     }
 
-    ptr = _r->contacts;
-    LM_DBG("Checking validity of IMPU: <%.*s> contacts\n", _r->public_identity.len, _r->public_identity.s);
-
-    while (ptr) {
-        if (!VALID_CONTACT(ptr, act_time)) {
-            /* run callbacks for EXPIRE event */
-            if (exists_ulcb_type(ptr->cbs, UL_CONTACT_EXPIRE))
-                run_ul_callbacks(ptr->cbs, UL_CONTACT_EXPIRE, _r, ptr);
-
-            if (exists_ulcb_type(_r->cbs, UL_IMPU_EXPIRE_CONTACT)) {
-                run_ul_callbacks(_r->cbs, UL_IMPU_EXPIRE_CONTACT, _r, ptr);
-            }
-
-            LM_DBG("Binding '%.*s','%.*s' has expired\n",
-                    ptr->aor->len, ZSW(ptr->aor->s),
-                    ptr->c.len, ZSW(ptr->c.s));
-
-            t = ptr;
-            ptr = ptr->next;
-
-			if (db_mode == WRITE_THROUGH && db_delete_ucontact(_r, t) != 0) {
-				LM_ERR("error removing contact from DB [%.*s]... will still remove from memory\n", t->c.len, t->c.s);
-			}
-
-            mem_delete_ucontact(_r, t);
-            update_stat(_r->slot->d->expires, 1);
-        } else {
-            LM_DBG("IMPU:<%.*s> - contact:<%.*s> is valid and expires in %d seconds\n", _r->public_identity.len, _r->public_identity.s,
+    LM_DBG("Checking validity of IMPU: <%.*s> contacts (#%d contacts)\n", _r->public_identity.len, _r->public_identity.s, _r->num_contacts);
+    flag = 0;
+    
+    for (i=0; i<MAX_CONTACTS_PER_IMPU; i++) {
+	if ((ptr = _r->newcontacts[i])) {
+	    flag=1;
+	    if (!VALID_CONTACT(ptr, act_time)) {
+		LM_DBG("IMPU:<%.*s> - contact:<%.*s> has expired\n", _r->public_identity.len, _r->public_identity.s, ptr->c.len, ptr->c.s);
+		lock_contact_slot_i(ptr->contact_hash); //TODO, this maybe should be a lock on the strcuture itself and not the slot
+		unlink_contact_from_impu(_r, ptr, 1);
+		unlock_contact_slot_i(ptr->contact_hash);
+	    } else {
+		LM_DBG("IMPU:<%.*s> - contact:<%.*s> is valid and expires in %d seconds\n", _r->public_identity.len, _r->public_identity.s,
                     ptr->c.len, ptr->c.s,
                     (unsigned int) (ptr->expires - time(NULL)));
-            ptr = ptr->next;
-        }
+		mustdeleteimpu = 0;
+		hascontacts = 1;
+	    }
+	    
+	} else {
+	    break;
+	}
+    }
+    
+    if (!flag)
+        LM_DBG("no contacts\n");
+
+    register_udomain("location", &udomain);
+    if (mustdeleteimpu) {
+	delete_impurecord(udomain, &_r->public_identity, _r);
+    } else {
+	if (!hascontacts) {
+	    LM_DBG("This impu is not to be deleted but has no contacts - should change state to IMPU_UNREGISTERED\n");
+	    if (update_impurecord(udomain, &_r->public_identity, IMPU_UNREGISTERED,
+		    -1/*do not change*/, -1 /*do not change */, -1/*do not change*/, NULL, NULL, NULL, NULL, NULL, &tmp_impu) != 0) {
+		LM_ERR("Unable to update impurecord for <%.*s>\n", _r->public_identity.len, _r->public_identity.s);
+	    }
+	}
     }
 }
 
@@ -428,7 +404,18 @@ static inline void nodb_timer(impurecord_t* _r) {
  * \param _r processed record
  */
 void timer_impurecord(impurecord_t* _r) {
-    nodb_timer(_r);
+        nodb_timer(_r);
+}
+
+int get_contacts_count(impurecord_t* _r) {
+    ucontact_t* ptr;
+    int i = 0;
+    
+    while (i<MAX_CONTACTS_PER_IMPU && (ptr=_r->newcontacts[i])) {
+	i++;
+    }
+    
+    return i;
 }
 
 /*!
@@ -442,12 +429,7 @@ void timer_impurecord(impurecord_t* _r) {
 int insert_ucontact(impurecord_t* _r, str* _contact, ucontact_info_t* _ci, ucontact_t** _c) {
     //First check our constraints
     if (maxcontact > 0 && maxcontact_behaviour > 0) {
-        ucontact_t* contact = _r->contacts;
-        int numcontacts = 0;
-        while (contact) {
-            numcontacts++;
-            contact = contact->next;
-        }
+        int numcontacts = get_contacts_count(_r);
         if (numcontacts >= maxcontact) {
             switch (maxcontact_behaviour) {
                 case 1://reject
@@ -456,7 +438,7 @@ int insert_ucontact(impurecord_t* _r, str* _contact, ucontact_info_t* _ci, ucont
                 case 2://overwrite oldest
                     LM_DBG("Too many contacts already registered, overwriting oldest for IMPU <%.*s>\n", _r->public_identity.len, _r->public_identity.s);
                     //we can just remove the first one seeing the contacts are ordered on insertion with newest last and oldest first
-                    mem_delete_ucontact(_r, _r->contacts);
+                    //TODO:mem_delete_ucontact(_r, _r->contacts);
                     break;
                 default://unknown
                     LM_ERR("unknown maxcontact behaviour..... ignoring\n");
@@ -472,12 +454,19 @@ int insert_ucontact(impurecord_t* _r, str* _contact, ucontact_info_t* _ci, ucont
         return -1;
     }
 
-    /*DB?*/
+
+
+//    /*DB?*/
 	if (db_mode == WRITE_THROUGH && db_insert_ucontact(_r, *_c) != 0) {
 		LM_ERR("error inserting contact into db");
 		return -1;
 	}
 
+//make sure IMPU is linked to this contact
+    link_contact_to_impu(_r, *_c, 1);
+    
+    release_ucontact(*_c);
+
     if (exists_ulcb_type(NULL, UL_CONTACT_INSERT)) {
         run_ul_callbacks(NULL, UL_CONTACT_INSERT, _r, *_c);
     }
@@ -494,23 +483,27 @@ int insert_ucontact(impurecord_t* _r, str* _contact, ucontact_info_t* _ci, ucont
  * \param _c deleted contact
  * \return 0 on success, -1 on failure
  */
-int delete_ucontact(impurecord_t* _r, struct ucontact* _c) {
+int delete_ucontact(struct ucontact* _c) {
     int ret = 0;
     
-    if (exists_ulcb_type(_c->cbs, UL_CONTACT_DELETE)) {
-        run_ul_callbacks(_c->cbs, UL_CONTACT_DELETE, _r, _c);
-    }
-    if (exists_ulcb_type(_r->cbs, UL_IMPU_DELETE_CONTACT)) {
-        run_ul_callbacks(_r->cbs, UL_IMPU_DELETE_CONTACT, _r, _c);
-    }
+    LM_DBG("Deleting contact: [%.*s]\n", _c->c.len, _c->c.s);
+    //TODO: restore callbacks
+//    if (exists_ulcb_type(_c->cbs, UL_CONTACT_DELETE)) {
+//        run_ul_callbacks(_c->cbs, UL_CONTACT_DELETE, _r, _c);
+//    }
+    
+    //TODO: following callbacks need to move to unlink contact from impu functions
+//    if (exists_ulcb_type(_r->cbs, UL_IMPU_DELETE_CONTACT)) {
+//        run_ul_callbacks(_r->cbs, UL_IMPU_DELETE_CONTACT, _r, _c);
+//    }
 
 	/*DB?*/
-	if (db_mode == WRITE_THROUGH && db_delete_ucontact(_r, _c) != 0) {
+	if (db_mode == WRITE_THROUGH && db_delete_ucontact(_c) != 0) {
 		LM_ERR("error removing contact from DB [%.*s]... will still remove from memory\n", _c->c.len, _c->c.s);
 
 	}
 
-    mem_delete_ucontact(_r, _c);
+    mem_delete_ucontact(_c);
 
     return ret;
 }
@@ -550,12 +543,13 @@ inline int aor_to_contact(str* aor, str* contact) {
  * \param _c contact string
  * \return ptr on successfull match, 0 when they not match
  */
-static inline struct ucontact* contact_match(ucontact_t* ptr, str* _c) {
+static inline struct ucontact* contact_match(unsigned int slot, str* _c) {
+    ucontact_t* ptr = contact_list->slot[slot].first;
+    
     while (ptr) {
-        if ((_c->len == ptr->c.len) && !memcmp(_c->s, ptr->c.s, _c->len)) {
+        if ((_c->len == ptr->c.len) && !memcmp(_c->s, ptr->c.s, _c->len) && VALID_CONTACT(ptr, act_time)) {//check validity
             return ptr;
         }
-
         ptr = ptr->next;
     }
     return 0;
@@ -567,13 +561,14 @@ static inline struct ucontact* contact_match(ucontact_t* ptr, str* _c) {
  * \param _c contact string
  * \return ptr on successfull match, 0 when they not match
  */
-static inline struct ucontact* contact_port_ip_match(ucontact_t* ptr, str* _c) {
+static inline struct ucontact* contact_port_ip_match(unsigned int slot, str* _c) {
+    ucontact_t* ptr = contact_list->slot[slot].first;
     str string_ip_port, contact_ip_port;
     aor_to_contact(_c, &string_ip_port);//strip userpart from test contact
 
     while (ptr) {
 	aor_to_contact(&ptr->c, &contact_ip_port);//strip userpart from contact
-	if ((string_ip_port.len == contact_ip_port.len) && !memcmp(string_ip_port.s, contact_ip_port.s, string_ip_port.len)) {
+	if ((string_ip_port.len == contact_ip_port.len) && !memcmp(string_ip_port.s, contact_ip_port.s, string_ip_port.len) && VALID_CONTACT(ptr, act_time)) {
             return ptr;
         }
 
@@ -589,16 +584,17 @@ static inline struct ucontact* contact_port_ip_match(ucontact_t* ptr, str* _c) {
  * \param _callid callid
  * \return ptr on successfull match, 0 when they not match
  */
-static inline struct ucontact* contact_callid_match(ucontact_t* ptr,
+static inline struct ucontact* contact_callid_match(unsigned int slot,
         str* _c, str *_callid) {
+    ucontact_t* ptr = contact_list->slot[slot].first;
+    
     while (ptr) {
         if ((_c->len == ptr->c.len) && (_callid->len == ptr->callid.len)
                 && !memcmp(_c->s, ptr->c.s, _c->len)
                 && !memcmp(_callid->s, ptr->callid.s, _callid->len)
-                ) {
+                && VALID_CONTACT(ptr, act_time)) {
             return ptr;
         }
-
         ptr = ptr->next;
     }
     return 0;
@@ -611,16 +607,18 @@ static inline struct ucontact* contact_callid_match(ucontact_t* ptr,
 + * \param _path path
 + * \return ptr on successfull match, 0 when they not match
 + */
-static inline struct ucontact* contact_path_match(ucontact_t* ptr, str* _c, str *_path) {
+static inline struct ucontact* contact_path_match(unsigned int slot, str* _c, str *_path) {
+    ucontact_t* ptr = contact_list->slot[slot].first;
     /* if no path is preset (in REGISTER request) or use_path is not configured
        in registrar module, default to contact_match() */
-    if (_path == NULL) return contact_match(ptr, _c);
+    if (_path == NULL) return contact_match(slot, _c);
 
     while (ptr) {
         if ((_c->len == ptr->c.len) && (_path->len == ptr->path.len)
                 && !memcmp(_c->s, ptr->c.s, _c->len)
                 && !memcmp(_path->s, ptr->path.s, _path->len)
-                ) {
+                && VALID_CONTACT(ptr, act_time)
+		) {
             return ptr;
         }
 
@@ -638,47 +636,64 @@ static inline struct ucontact* contact_path_match(ucontact_t* ptr, str* _c, str
  * \param _cseq CSEQ number
  * \param _co found contact
  * \return 0 - found, 1 - not found, -1 - invalid found,
- * -2 - found, but to be skipped (same cseq)
+ * -2 - found, but to be skipped (same cseq) - don't forget to release_ucontact so dec. the ref counter
  */
 int get_ucontact(impurecord_t* _r, str* _c, str* _callid, str* _path, int _cseq, struct ucontact** _co) {
+    unsigned int sl;
     ucontact_t* ptr;
-    int no_callid;
-
+    int with_callid = 0;
     ptr = 0;
-    no_callid = 0;
     *_co = 0;
 
+    sl = core_hash(_c, 0, contact_list->size);
+    LM_DBG("looking for contact [%.*s] in slot %d\n", _c->len, _c->s, sl);
+    lock_contact_slot_i(sl);
+    
+    get_act_time();
+    
     switch (matching_mode) {
         case CONTACT_ONLY:
-            ptr = contact_match(_r->contacts, _c);
+            ptr = contact_match(sl, _c);
             break;
         case CONTACT_CALLID:
-            ptr = contact_callid_match(_r->contacts, _c, _callid);
-            no_callid = 1;
+            ptr = contact_callid_match(sl, _c, _callid);
+            with_callid = 1;
             break;
         case CONTACT_PATH:
-            ptr = contact_path_match(_r->contacts, _c, _path);
-            break;
+            ptr = contact_path_match(sl, _c, _path);
+	    break;
 	case CONTACT_PORT_IP_ONLY:
-	    ptr = contact_port_ip_match(_r->contacts, _c);
+	    ptr = contact_port_ip_match(sl, _c);
 	    break;
         default:
             LM_CRIT("unknown matching_mode %d\n", matching_mode);
-            return -1;
+            unlock_contact_slot_i(sl);
+	    return -1;
     }
+    
+    unlock_contact_slot_i(sl);	/*TODO: we probably need to ref count here..... */
 
     if (ptr) {
+	LM_DBG("have partially found a contact\n");
         /* found -> check callid and cseq */
-        if (no_callid || (ptr->callid.len == _callid->len
+        if (!with_callid || (_callid && ptr->callid.len == _callid->len
                 && memcmp(_callid->s, ptr->callid.s, _callid->len) == 0)) {
-            if (_cseq < ptr->cseq)
-                return -1;
-            if (_cseq == ptr->cseq) {
-                get_act_time();
-                return (ptr->last_modified + cseq_delay > act_time) ? -2 : -1;
-            }
+            if (_cseq < ptr->cseq) {
+		LM_DBG("cseq less than expected\n");
+//                return -1;
+	    }
+//            if (_cseq == ptr->cseq) {
+//                get_act_time();
+//                return (ptr->last_modified + cseq_delay > act_time) ? -2 : -1;
+//            }
+	    
+	    
         }
+	LM_DBG("contact found p=[%p], aor:[%.*s] and contact:[%.*s]\n", ptr, ptr->aor.len, ptr->aor.s, ptr->c.len, ptr->c.s);
+	
+	ptr->ref_count++;
         *_co = ptr;
+	
         return 0;
     }
 
@@ -849,9 +864,114 @@ int update_impurecord(struct udomain* _d, str* public_identity, int reg_state, i
     }
 
     run_ul_callbacks((*_r)->cbs, UL_IMPU_UPDATE, *_r, NULL);
+    
+    if (db_mode == WRITE_THROUGH && db_insert_impurecord(_d, &(*_r)->public_identity, (*_r)->reg_state, (*_r)->barring, &(*_r)->s, &(*_r)->ccf1, &(*_r)->ccf2, &(*_r)->ecf1, &(*_r)->ecf2, _r) != 0) {
+	LM_ERR("error inserting IMPU [%.*s] into db... continuing", (*_r)->public_identity.len, (*_r)->public_identity.s);
+    }
+    
     return 0;
 
 out_of_memory:
     unlock_udomain(_d, public_identity);
     return -1;
 }
+
+/* link contact to impu 
+    must be called with lock on domain (IMPU) as well as lock on contact_slot 
+ */
+int link_contact_to_impu(impurecord_t* impu, ucontact_t* contact, int write_to_db)
+{
+    ucontact_t* ptr;
+    int i;
+    i=0;
+    int overwrite=0;
+    ptr=impu->newcontacts[i];
+
+    
+    
+    while (i<MAX_CONTACTS_PER_IMPU && ptr) {
+	if (ptr == contact) {
+	    LM_DBG("contact [%.*s] already linked to impu [%.*s]\n", contact->c.len, contact->c.s, impu->public_identity.len, impu->public_identity.s);
+	    return 0;
+	}
+	i++;
+	ptr = impu->newcontacts[i];
+    }
+    
+    if ((maxcontact_behaviour>0) && (maxcontact>0) && (maxcontact < (i+1))) {
+	LM_DBG("Need to overwrite oldest contact at position %d\n", i);
+	i = maxcontact-1;
+	overwrite = 1;
+    }
+    
+    if (i<MAX_CONTACTS_PER_IMPU) {
+	LM_DBG("contact [%.*s] needs to be linked to impu [%.*s] at position %d\n", contact->c.len, contact->c.s, impu->public_identity.len, impu->public_identity.s, i);
+	if (overwrite)
+	    unlink_contact_from_impu(impu, impu->newcontacts[i], write_to_db);    //unlink the contact we are overwriting
+
+	impu->num_contacts = i+1;   //we always bump this - as unlink (in overwrite would have decremented)
+	
+	impu->newcontacts[i] = contact;
+	
+	contact->ref_count++;
+	LM_DBG("number of contacts for IMPU [%.*s] is %d\n", impu->public_identity.len, impu->public_identity.s, impu->num_contacts);
+	if (write_to_db && db_mode == WRITE_THROUGH && db_link_contact_to_impu(impu, contact) !=0) {
+	    LM_ERR("Failed to update DB linking contact [%.*s] to IMPU [%.*s]...continuing but db will be out of sync!\n", contact->c.len, contact->c.s, impu->public_identity.len, impu->public_identity.s);
+	};
+    } else {
+	LM_DBG("unable to link contact to impu as too many links already > %d\n", MAX_CONTACTS_PER_IMPU);
+	return -1;
+    }
+    
+    return 0;
+}
+
+/* link contact to impu 
+    must be called with lock on domain (IMPU) as well as lock on contact_slot 
+ */
+int unlink_contact_from_impu(impurecord_t* impu, ucontact_t* contact, int write_to_db)
+{
+    ucontact_t* ptr;
+    int i;
+    i=0;
+    int found=0;
+    ptr=impu->newcontacts[i];
+
+    LM_DBG("asked to unlink contact [%.*s] from impu [%.*s]\n", contact->c.len, contact->c.s, impu->public_identity.len, impu->public_identity.s);    
+    
+    while (i<MAX_CONTACTS_PER_IMPU && ptr) {
+	if (found) {
+	    //shift all later pointers forward by 1
+	    impu->newcontacts[i-1] = impu->newcontacts[i];
+	} else {
+	    if (ptr == contact) {
+		LM_DBG("unlinking contact [%.*s] from impu [%.*s]\n", contact->c.len, contact->c.s, impu->public_identity.len, impu->public_identity.s);
+		
+		if (exists_ulcb_type(impu->cbs, UL_IMPU_DELETE_CONTACT)) {
+		    LM_DBG("Running callback UL_IMPU_DELETE_CONTACT for contact [%.*s] and impu [%.*s]\n", impu->public_identity.len, impu->public_identity.s, ptr->c.len, ptr->c.s);
+		    run_ul_callbacks(impu->cbs, UL_IMPU_DELETE_CONTACT, impu, ptr);
+		}
+
+		found = 1;
+		impu->newcontacts[i]=0;
+		impu->num_contacts--;
+		LM_DBG("decrementing ref count on contact [%.*s] to %d\n", contact->c.len, contact->c.s, contact->ref_count);
+		contact->ref_count--;	//TODO - should we lock the actual ucontact struct?
+		if (write_to_db && db_mode == WRITE_THROUGH && db_unlink_contact_from_impu(impu, contact) != 0) {
+		    LM_ERR("Failed to un-link DB contact [%.*s] from IMPU [%.*s]...continuing but db will be out of sync!\n", contact->c.len, contact->c.s, impu->public_identity.len, impu->public_identity.s);
+		}
+	    }
+	}
+	i++;
+	ptr = impu->newcontacts[i];
+    }
+
+    if (found && i < MAX_CONTACTS_PER_IMPU) {
+	LM_DBG("zero'ing last pointer to contact in the list\n");
+	impu->newcontacts[i-1]=0;
+    } else {
+	LM_DBG("contact [%.*s] did not exist in IMPU list [%.*s] while trying to unlink\n", contact->c.len, contact->c.s, impu->public_identity.len, impu->public_identity.s);
+    }
+    
+    return 0;
+}
diff --git a/modules/ims_usrloc_scscf/impurecord.h b/modules/ims_usrloc_scscf/impurecord.h
index 78f1665..eb18911 100644
--- a/modules/ims_usrloc_scscf/impurecord.h
+++ b/modules/ims_usrloc_scscf/impurecord.h
@@ -102,18 +102,16 @@ ucontact_t* mem_insert_ucontact(impurecord_t* _r, str* _c, ucontact_info_t* _ci)
 
 /*!
  * \brief Remove the contact from lists in memory
- * \param _r record this contact belongs to
- * \param _c removed contact
+  * \param _c contact to remove
  */
-void mem_remove_ucontact(impurecord_t* _r, ucontact_t* _c);
+void mem_remove_ucontact(ucontact_t* _c);
 
 
 /*!
  * \brief Remove contact in memory from the list and delete it
- * \param _r record this contact belongs to
- * \param _c deleted contact
+ * \param _c contact to delete
  */
-void mem_delete_ucontact(impurecord_t* _r, ucontact_t* _c);
+void mem_delete_ucontact(ucontact_t* _c);
 
 
 /*!
@@ -154,7 +152,7 @@ int insert_ucontact(impurecord_t* _r, str* _contact,
  * \param _c deleted contact
  * \return 0 on success, -1 on failure
  */
-int delete_ucontact(impurecord_t* _r, struct ucontact* _c);
+int delete_ucontact(struct ucontact* _c);
 
 
 /*!
@@ -174,4 +172,8 @@ int get_ucontact(impurecord_t* _r, str* _c, str* _callid, str* _path,
 
 int update_impurecord(struct udomain* _d, str* public_identity, int reg_state, int send_sar_on_delete, int barring, int is_primary, ims_subscription** s, str* ccf1, str* ccf2, str* ecf1, str* ecf2, struct impurecord** _r);
 
+int link_contact_to_impu(impurecord_t* impu, ucontact_t* contact, int write_to_db);
+int unlink_contact_from_impu(impurecord_t* impu, ucontact_t* contact, int write_to_db);
+
 #endif
+
diff --git a/modules/ims_usrloc_scscf/subscribe.c b/modules/ims_usrloc_scscf/subscribe.c
index dbfe059..4209e7c 100644
--- a/modules/ims_usrloc_scscf/subscribe.c
+++ b/modules/ims_usrloc_scscf/subscribe.c
@@ -55,11 +55,14 @@
 #include "../../hashes.h"
 
 #include "ul_mod.h"
+#include "usrloc_db.h"
 
 
 extern int sub_dialog_hash_size;
 extern shtable_t sub_dialog_table;
 
+extern int db_mode;
+
 int get_subscriber(impurecord_t* urec, str *presentity_uri, str *watcher_contact, int event, reg_subscriber** r_subscriber) {
     
     reg_subscriber* s = NULL;
@@ -95,7 +98,7 @@ int get_subscriber(impurecord_t* urec, str *presentity_uri, str *watcher_contact
     return 1;
 }
 
-reg_subscriber* new_subscriber(str* presentity_uri, str* watcher_uri, str* watcher_contact, subscriber_data_t* subscriber_data) {
+reg_subscriber* new_subscriber(subscriber_data_t* subscriber_data) {
     subs_t subs;
     reg_subscriber *s;
 
@@ -107,7 +110,7 @@ reg_subscriber* new_subscriber(str* presentity_uri, str* watcher_uri, str* watch
     
     len = sizeof (reg_subscriber) + subscriber_data->callid->len
             + subscriber_data->ftag->len + subscriber_data->ttag->len
-            + watcher_contact->len + watcher_uri->len + presentity_uri->len
+            + subscriber_data->watcher_contact->len + subscriber_data->watcher_uri->len + subscriber_data->presentity_uri->len
             + subscriber_data->record_route->len + subscriber_data->sockinfo_str->len;
 
     LM_DBG("Creating new subscription to reg");
@@ -124,6 +127,8 @@ reg_subscriber* new_subscriber(str* presentity_uri, str* watcher_uri, str* watch
     s->event = subscriber_data->event;
 
     s->expires = subscriber_data->expires;
+    
+    s->version = subscriber_data->version;
 
     p = (char*) (s + 1);
 
@@ -143,14 +148,14 @@ reg_subscriber* new_subscriber(str* presentity_uri, str* watcher_uri, str* watch
     p += subscriber_data->ftag->len;
 
     s->watcher_uri.s = p;
-    s->watcher_uri.len = watcher_uri->len;
-    memcpy(p, watcher_uri->s, watcher_uri->len);
-    p += watcher_uri->len;
+    s->watcher_uri.len = subscriber_data->watcher_uri->len;
+    memcpy(p, subscriber_data->watcher_uri->s, subscriber_data->watcher_uri->len);
+    p += subscriber_data->watcher_uri->len;
 
     s->watcher_contact.s = p;
-    s->watcher_contact.len = watcher_contact->len;
-    memcpy(p, watcher_contact->s, watcher_contact->len);
-    p += watcher_contact->len;
+    s->watcher_contact.len = subscriber_data->watcher_contact->len;
+    memcpy(p, subscriber_data->watcher_contact->s, subscriber_data->watcher_contact->len);
+    p += subscriber_data->watcher_contact->len;
 
     s->record_route.s = p;
     s->record_route.len = subscriber_data->record_route->len;
@@ -163,9 +168,9 @@ reg_subscriber* new_subscriber(str* presentity_uri, str* watcher_uri, str* watch
     p += subscriber_data->sockinfo_str->len;
 
     s->presentity_uri.s = p;
-    s->presentity_uri.len = presentity_uri->len;
-    memcpy(p, presentity_uri->s, presentity_uri->len);
-    p += presentity_uri->len;
+    s->presentity_uri.len = subscriber_data->presentity_uri->len;
+    memcpy(p, subscriber_data->presentity_uri->s, subscriber_data->presentity_uri->len);
+    p += subscriber_data->presentity_uri->len;
 
     if (p != (((char*) s) + len)) {
         LM_CRIT("buffer overflow\n");
@@ -174,11 +179,14 @@ reg_subscriber* new_subscriber(str* presentity_uri, str* watcher_uri, str* watch
     }
     
     /*This lets us get presentity URI info for subsequent SUBSCRIBEs that don't have presentity URI as req URI*/
+    get_act_time();
     
     subs.pres_uri = s->presentity_uri;
     subs.from_tag = s->from_tag;
     subs.to_tag = s->to_tag;
     subs.callid = s->call_id;
+    subs.expires = s->expires - act_time;
+    subs.contact = s->watcher_contact;
     
     hash_code = core_hash(&subs.callid, &subs.to_tag, sub_dialog_hash_size);
     
@@ -214,7 +222,7 @@ str get_presentity_from_subscriber_dialog(str *callid, str *to_tag, str *from_ta
 	    LM_DBG("Subscriber dialog record not found in hash table\n");
 	    lock_release(&sub_dialog_table[hash_code].lock);
 	    return pres_uri;
-    }
+}
 
     //make copy of pres_uri
     pres_uri.s = (char*) shm_malloc(s->pres_uri.len);
@@ -231,19 +239,22 @@ str get_presentity_from_subscriber_dialog(str *callid, str *to_tag, str *from_ta
     return pres_uri;
 }
 
+/*db_load:  if this is a db_load then we don't write to db - as it will be an unecessary rewrite*/
 int add_subscriber(impurecord_t* urec,
-        str *watcher_uri, str *watcher_contact,
-        subscriber_data_t* subscriber_data, reg_subscriber** _reg_subscriber) {
+        subscriber_data_t* subscriber_data, reg_subscriber** _reg_subscriber, int db_load) {
 
+    reg_subscriber *s;
     LM_DBG("Adding reg subscription to IMPU record");
 
     if (!urec) {
         LM_ERR("no presentity impu record provided\n");
         return 0;
     }
-    reg_subscriber *s = new_subscriber(&urec->public_identity, watcher_uri, watcher_contact, subscriber_data);
+    
+    s = new_subscriber(subscriber_data);
+    
 
-    if (!s) return 1;
+    if (!s) return -1;
 
     LM_DBG("Adding new subscription to IMPU record list");
     s->next = 0;
@@ -253,23 +264,74 @@ int add_subscriber(impurecord_t* urec,
     if (!urec->shead) urec->shead = s;
 
     *_reg_subscriber = s;
+    
+    /*DB?*/
+    if(!db_load && db_mode == WRITE_THROUGH) {
+	if(db_insert_subscriber(urec, s) != 0) {
+	    LM_ERR("Failed to insert subscriber into DB subscriber [%.*s] to IMPU [%.*s]...continuing but db will be out of sync!\n", 
+		    s->presentity_uri.len, s->presentity_uri.s, urec->public_identity.len, urec->public_identity.s);
+	    goto done;
+	}
+	
+	if(db_link_subscriber_to_impu(urec, s) !=0) {
+	    LM_ERR("Failed to update DB linking subscriber [%.*s] to IMPU [%.*s]...continuing but db will be out of sync!\n", 
+		    s->presentity_uri.len, s->presentity_uri.s, urec->public_identity.len, urec->public_identity.s);
+	}
+    }
+    
+done:
     return 0;
 }
 
 
-int update_subscriber(impurecord_t* urec,
-        str *watcher_uri, str *watcher_contact,
-        int *expires, reg_subscriber** _reg_subscriber) {
-
+int update_subscriber(impurecord_t* urec, reg_subscriber** _reg_subscriber, int *expires, int *local_cseq, int *version) {
 
+    subs_t subs;
+    unsigned int hash_code = 0;
     reg_subscriber *rs = *_reg_subscriber;
     if (expires) {
         rs->expires = *expires;
-        return 1;
     } else {
-        LM_ERR("Failed to update subscriber as expires is expires is null");
-        return 0;
+        LM_DBG("No expires so will not update subscriber expires.\n");
+    }
+    if (local_cseq) {
+        rs->local_cseq = *local_cseq;
+    } else {
+        LM_DBG("No local cseq so will not update subscriber local cseq.\n");
+    }
+    if (version) {
+        rs->version = *version;
+    } else {
+        LM_DBG("No version so will not update subscriber version.\n");
+    }
+    
+    /*This lets us get presentity URI info for subsequent SUBSCRIBEs that don't have presentity URI as req URI*/
+    get_act_time();
+    
+    subs.pres_uri = rs->presentity_uri;
+    subs.from_tag = rs->from_tag;
+    subs.to_tag = rs->to_tag;
+    subs.callid = rs->call_id;
+    subs.expires = rs->expires - act_time;
+    subs.contact = rs->watcher_contact;
+    
+    hash_code = core_hash(&subs.callid, &subs.to_tag, sub_dialog_hash_size);
+    
+    LM_DBG("Updating sub dialog hash info with call_id: <%.*s> and ttag <%.*s> amd ftag <%.*s> and hash code <%d>", subs.callid.len, subs.callid.s, subs.to_tag.len, subs.to_tag.s, subs.from_tag.len,  subs.from_tag.s, hash_code);
+    
+    if (pres_update_shtable(sub_dialog_table, hash_code, &subs, REMOTE_TYPE))
+    {
+	LM_ERR("while updating new subscription\n");
+	return 0;
+    }
+        
+    /*DB?*/
+    if (db_mode == WRITE_THROUGH && db_insert_subscriber(urec, rs) != 0) {
+	    LM_ERR("Failed to insert subscriber into DB subscriber [%.*s] to IMPU [%.*s]...continuing but db will be out of sync!\n", 
+		    rs->presentity_uri.len, rs->presentity_uri.s, urec->public_identity.len, urec->public_identity.s);
     }
+
+    return 1;
 }
 
 
@@ -286,19 +348,24 @@ void external_delete_subscriber(reg_subscriber *s, udomain_t* _t, int lock_domai
         return;
     }
 
-    if (urec->shead == s) urec->shead = s->next;
-    else s->prev->next = s->next;
-    if (urec->stail == s) urec->stail = s->prev;
-    else s->next->prev = s->prev;
-    LM_DBG("About to free subscriber memory");
-    free_subscriber(s);
+    delete_subscriber(urec, s);
 
     if(lock_domain) unlock_udomain(_t, &s->presentity_uri);
 
 }
 
 void delete_subscriber(impurecord_t* urec, reg_subscriber *s) {
-    LM_DBG("Deleting subscriber");
+    LM_DBG("Deleting subscriber [%.*s] from IMPU: [%.*s]", s->watcher_uri.len, s->watcher_uri.s, urec->public_identity.len, urec->public_identity.s);
+    
+    if (db_mode == WRITE_THROUGH && db_unlink_subscriber_from_impu(urec, s) !=0) {
+	    LM_ERR("Failed to delete DB linking subscriber [%.*s] to IMPU [%.*s]...continuing but db will be out of sync!\n", 
+		    s->presentity_uri.len, s->presentity_uri.s, urec->public_identity.len, urec->public_identity.s);
+	    
+    }    
+    if (db_mode == WRITE_THROUGH && db_delete_subscriber(urec, s) != 0) {
+	    LM_ERR("error removing subscriber from DB [%.*s]... will still remove from memory\n", s->presentity_uri.len, s->presentity_uri.s);
+    }
+    
     if (urec->shead == s) urec->shead = s->next;
     else s->prev->next = s->next;
     if (urec->stail == s) urec->stail = s->prev;
@@ -337,6 +404,6 @@ void free_subscriber(reg_subscriber *s) {
 
 }
 
-int valid_subscriber(reg_subscriber *s) {
-    return (s->expires > act_time);
+int valid_subscriber(reg_subscriber *s, time_t time) {
+    return (s->expires > time);
 }
diff --git a/modules/ims_usrloc_scscf/subscribe.h b/modules/ims_usrloc_scscf/subscribe.h
index c42434d..1d6ea3d 100644
--- a/modules/ims_usrloc_scscf/subscribe.h
+++ b/modules/ims_usrloc_scscf/subscribe.h
@@ -48,24 +48,16 @@
 
 #include "usrloc.h"
 
-reg_subscriber* new_subscriber(str* presentity_uri, str* watcher_uri,
-		str* watcher_contact, subscriber_data_t* subscriber_data);
+reg_subscriber* new_subscriber(subscriber_data_t* subscriber_data);
 
 //API declarations
 int get_subscriber(impurecord_t* urec, str *watcher_uri,
 		str *watcher_contact, int event, reg_subscriber** r_subscriber);
 
-int add_subscriber(impurecord_t* urec, str *watcher_uri,
-		str *watcher_contact, subscriber_data_t* subscriber_data,
-		reg_subscriber** _reg_subscriber);
-
-
-int update_subscriber(impurecord_t* urec,
-        str *watcher_uri, str *watcher_contact,
-        int *expires, reg_subscriber** _reg_subscriber);
-
+int add_subscriber(impurecord_t* urec, subscriber_data_t* subscriber_data, reg_subscriber** _reg_subscriber, int db_load);
 
 
+int update_subscriber(impurecord_t* urec, reg_subscriber** _reg_subscriber, int *expires, int *local_cseq, int *version);
 
 void delete_subscriber(impurecord_t* urec, reg_subscriber *s);
 
@@ -73,7 +65,7 @@ void external_delete_subscriber(reg_subscriber *s, udomain_t* _t, int lock_domai
 
 void free_subscriber(reg_subscriber *s);
 
-int valid_subscriber(reg_subscriber *s);
+int valid_subscriber(reg_subscriber *s, time_t act_time);
 
 str get_presentity_from_subscriber_dialog(str *callid, str *to_tag, str *from_tag);
 
diff --git a/modules/ims_usrloc_scscf/ucontact.c b/modules/ims_usrloc_scscf/ucontact.c
index 30bdab6..c0a2ef5 100644
--- a/modules/ims_usrloc_scscf/ucontact.c
+++ b/modules/ims_usrloc_scscf/ucontact.c
@@ -64,6 +64,13 @@
 #include "impurecord.h"
 #include "ucontact.h"
 #include "usrloc.h"
+#include "usrloc_db.h"
+#include "../../hashes.h"
+#include "contact_hslot.h"
+#include "utime.h"
+
+extern struct contact_list* contact_list;
+extern int db_mode;
 
 /*!
  * \brief Create a new contact structure
@@ -75,6 +82,8 @@
  */
 ucontact_t* new_ucontact(str* _dom, str* _aor, str* _contact, ucontact_info_t* _ci) {
     ucontact_t *c;
+    param_t *prev, *curr, *param;
+    int first = 1;
 
     c = (ucontact_t*) shm_malloc(sizeof (ucontact_t));
     if (!c) {
@@ -82,6 +91,16 @@ ucontact_t* new_ucontact(str* _dom, str* _aor, str* _contact, ucontact_info_t* _
         return 0;
     }
     memset(c, 0, sizeof (ucontact_t));
+    
+    c->lock = lock_alloc();
+    if (c->lock==0){
+        goto error;
+    }
+    if (lock_init(c->lock)==0){
+	lock_dealloc(c->lock);
+	c->lock=0;
+	goto error;
+    }
 
     //setup callback list
     c->cbs = (struct ulcb_head_list*) shm_malloc(sizeof (struct ulcb_head_list));
@@ -91,25 +110,49 @@ ucontact_t* new_ucontact(str* _dom, str* _aor, str* _contact, ucontact_info_t* _
     }
     c->cbs->first = 0;
     c->cbs->reg_types = 0;
-
+    
+    /*Copy parameter list into shm**/
+    param = _ci->params;
+    while(param) {
+	/*Copy first param in curr*/
+	curr = shm_malloc(sizeof (param_t));
+	curr->len = param->len;
+	curr->type = param->type;
+	curr->next = 0;
+	if (shm_str_dup(&curr->body, &param->body) < 0) goto error;
+	if (shm_str_dup(&curr->name, &param->name) < 0) goto error;
+	
+	if(first) {
+	    c->params = curr;
+	    first = 0;
+	} else {
+	    prev->next = curr;
+	}
+	prev = curr;
+	param = param->next;
+	
+    }
+    
     if (shm_str_dup(&c->c, _contact) < 0) goto error;
     if (shm_str_dup(&c->callid, _ci->callid) < 0) goto error;
     if (shm_str_dup(&c->user_agent, _ci->user_agent) < 0) goto error;
-
+    if (shm_str_dup(&c->aor, _aor) < 0) goto error;
+    if (shm_str_dup(&c->domain, _dom) < 0) goto error;
+    
     if (_ci->received.s && _ci->received.len) {
         if (shm_str_dup(&c->received, &_ci->received) < 0) goto error;
     }
     if (_ci->path && _ci->path->len) {
         if (shm_str_dup(&c->path, _ci->path) < 0) goto error;
     }
-
-    c->domain = _dom;
-    c->aor = _aor;
+    
+    LM_DBG("generating hash based on [%.*s]\n", _contact->len, _contact->s);
+    c->contact_hash = core_hash(_contact, 0, contact_list->size);
+    c->ref_count = 1;
     c->expires = _ci->expires;
     c->q = _ci->q;
     c->sock = _ci->sock;
     c->cseq = _ci->cseq;
-    c->state = CS_NEW;
     c->flags = _ci->flags;
     c->cflags = _ci->cflags;
     c->methods = _ci->methods;
@@ -123,6 +166,8 @@ error:
     if (c->user_agent.s) shm_free(c->user_agent.s);
     if (c->callid.s) shm_free(c->callid.s);
     if (c->c.s) shm_free(c->c.s);
+    if (c->domain.s) shm_free(c->domain.s);
+    if (c->aor.s) shm_free(c->aor.s);
     shm_free(c);
     return 0;
 }
@@ -134,19 +179,33 @@ error:
 void free_ucontact(ucontact_t* _c) {
     struct ul_callback *cbp, *cbp_tmp;
     struct contact_dialog_data *dialog_data, *tmp_dialog_data; 
-
+    param_t * tmp, *tmp1;
+    
     if (!_c) return;
+    LM_DBG("Freeing ucontact [%.*s]\n", _c->aor.len, _c->aor.s);    
     if (_c->path.s) shm_free(_c->path.s);
     if (_c->received.s) shm_free(_c->received.s);
     if (_c->user_agent.s) shm_free(_c->user_agent.s);
     if (_c->callid.s) shm_free(_c->callid.s);
     if (_c->c.s) shm_free(_c->c.s);
+    
+    tmp = _c->params;
+    while(tmp){
+	tmp1 = tmp->next;
+	if (tmp->body.s) shm_free(tmp->body.s);
+	if (tmp->name.s) shm_free(tmp->name.s);
+	if(tmp) shm_free(tmp);
+	tmp = tmp1;
+    }
+    
+    if (_c->domain.s) shm_free(_c->domain.s);
+    if (_c->aor.s) shm_free(_c->aor.s);
 
     //free dialog data
     for (dialog_data = _c->first_dialog_data; dialog_data;) {
         tmp_dialog_data = dialog_data;
         dialog_data = dialog_data->next;
-	shm_free(tmp_dialog_data);
+		shm_free(tmp_dialog_data);
     }
     
     //free callback list
@@ -158,6 +217,8 @@ void free_ucontact(ucontact_t* _c) {
         shm_free(cbp_tmp);
     }
     shm_free(_c->cbs);
+    lock_dealloc(_c->lock);
+    lock_destroy(_c->lock);
     shm_free(_c);
 }
 
@@ -168,23 +229,22 @@ void free_ucontact(ucontact_t* _c) {
  */
 void print_ucontact(FILE* _f, ucontact_t* _c) {
     time_t t = time(0);
-    char* st;
-
-    switch (_c->state) {
-        case CS_NEW: st = "CS_NEW";
-            break;
-        case CS_SYNC: st = "CS_SYNC";
-            break;
-        case CS_DIRTY: st = "CS_DIRTY";
-            break;
-        default: st = "CS_UNKNOWN";
-            break;
-    }
-
+    char* st = "";
+    param_t * tmp;
+    
     fprintf(_f, "~~~Contact(%p)~~~\n", _c);
-    fprintf(_f, "domain    : '%.*s'\n", _c->domain->len, ZSW(_c->domain->s));
-    fprintf(_f, "aor       : '%.*s'\n", _c->aor->len, ZSW(_c->aor->s));
+    fprintf(_f, "domain    : '%.*s'\n", _c->domain.len, ZSW(_c->domain.s));
+    fprintf(_f, "aor       : '%.*s'\n", _c->aor.len, ZSW(_c->aor.s));
     fprintf(_f, "Contact   : '%.*s'\n", _c->c.len, ZSW(_c->c.s));
+    
+    fprintf(_f, "Params   :\n");
+    tmp = _c->params;
+    while (tmp) {
+	fprintf(_f, "Param Name: '%.*s' Param Body '%.*s'\n", tmp->name.len, ZSW(tmp->name.s), tmp->body.len, ZSW(tmp->body.s));
+	tmp = tmp->next;
+    }
+    
+    
     fprintf(_f, "Expires   : ");
     if (_c->expires == 0) {
         fprintf(_f, "Permanent\n");
@@ -264,7 +324,7 @@ int mem_update_ucontact(ucontact_t* _c, ucontact_info_t* _ci) {
         _c->path.s = 0;
         _c->path.len = 0;
     }
-
+    
     LM_DBG("Setting contact expires to %d which is in %d seconds time\n", (unsigned int) _ci->expires, (unsigned int) (_ci->expires - time(NULL)));
     _c->sock = _ci->sock;
     _c->expires = _ci->expires;
@@ -279,24 +339,19 @@ int mem_update_ucontact(ucontact_t* _c, ucontact_info_t* _ci) {
 }
 
 /*!
- * \brief Remove a contact from list belonging to a certain record
- * \param _r record the contact belongs
- * \param _c removed contact
+ * \brief Setting contact expires to now in memory
+ * \param _c contact
+  * \return 0 on success, -1 on failure
  */
-static inline void unlink_contact(struct impurecord* _r, ucontact_t* _c) {
-    if (_c->prev) {
-        _c->prev->next = _c->next;
-        if (_c->next) {
-            _c->next->prev = _c->prev;
-        }
-    } else {
-        _r->contacts = _c->next;
-        if (_c->next) {
-            _c->next->prev = 0;
-        }
-    }
+int mem_expire_ucontact(ucontact_t* _c) {
+    get_act_time();
+    _c->expires = act_time;
+
+    return 0;
 }
 
+
+
 /*!
  * \brief Insert a new contact into the list at the correct position
  * \param _r record that holds the sorted contacts
@@ -336,6 +391,43 @@ static inline void update_contact_pos(struct impurecord* _r, ucontact_t* _c) {
 }
 
 /*!
+ * \brief Setting ucontact expires to now
+ * \param _r record the contact belongs to
+ * \param _c updated contact
+ * \return 0 on success, -1 on failure
+ */
+int expire_ucontact(struct impurecord* _r, ucontact_t* _c) {
+    /* we have to update memory in any case, but database directly
+     * only in db_mode 1 */
+    LM_DBG("Expiring contact aor: [%.*s] and contact uri: [%.*s]\n", _c->aor.len, _c->aor.s, _c->c.len, _c->c.s);
+    if (mem_expire_ucontact(_c) < 0) {
+        LM_ERR("failed to update memory\n");
+        return -1;
+    }
+    
+    if (db_mode == WRITE_THROUGH && (db_insert_ucontact(_r, _c) != 0)) {  /* this is an insert/update */
+	LM_ERR("failed to update contact in DB [%.*s]\n", _c->aor.len, _c->aor.s);
+	return -1;
+    }
+    
+    //make sure IMPU is linked to this contact
+    link_contact_to_impu(_r, _c, 1);
+
+    /* run callbacks for UPDATE event */
+    if (exists_ulcb_type(_c->cbs, UL_CONTACT_EXPIRE)) {
+        LM_DBG("exists callback for type= UL_CONTACT_UPDATE\n");
+        run_ul_callbacks(_c->cbs, UL_CONTACT_EXPIRE, _r, _c);
+    }
+    if (exists_ulcb_type(_r->cbs, UL_IMPU_EXPIRE_CONTACT)) {
+        run_ul_callbacks(_r->cbs, UL_IMPU_EXPIRE_CONTACT, _r, _c);
+    }
+
+    return 0;
+}
+
+
+
+/*!
  * \brief Update ucontact with new values
  * \param _r record the contact belongs to
  * \param _c updated contact
@@ -345,10 +437,19 @@ static inline void update_contact_pos(struct impurecord* _r, ucontact_t* _c) {
 int update_ucontact(struct impurecord* _r, ucontact_t* _c, ucontact_info_t* _ci) {
     /* we have to update memory in any case, but database directly
      * only in db_mode 1 */
+    LM_DBG("Updating contact aor: [%.*s] and contact uri: [%.*s]\n", _c->aor.len, _c->aor.s, _c->c.len, _c->c.s);
     if (mem_update_ucontact(_c, _ci) < 0) {
         LM_ERR("failed to update memory\n");
         return -1;
     }
+    
+    if (db_mode == WRITE_THROUGH && (db_insert_ucontact(_r, _c) != 0)) {  /* this is an insert/update */
+	LM_ERR("failed to update contact in DB [%.*s]\n", _c->aor.len, _c->aor.s);
+	return -1;
+    }
+    
+    //make sure IMPU is linked to this contact
+    link_contact_to_impu(_r, _c, 1);
 
     /* run callbacks for UPDATE event */
     if (exists_ulcb_type(_c->cbs, UL_CONTACT_UPDATE)) {
@@ -359,7 +460,7 @@ int update_ucontact(struct impurecord* _r, ucontact_t* _c, ucontact_info_t* _ci)
         run_ul_callbacks(_r->cbs, UL_IMPU_UPDATE_CONTACT, _r, _c);
     }
 
-    update_contact_pos(_r, _c);
+//    update_contact_pos(_r, _c);
 
     return 0;
 }
@@ -428,3 +529,9 @@ int remove_dialog_data_from_contact(ucontact_t* _c, unsigned int h_entry, unsign
     LM_DBG("Did not find dialog data to remove from contact");
     return 0;
 }
+
+void release_ucontact(struct ucontact* _c) {
+    lock_contact_slot_i(_c->contact_hash);
+    _c->ref_count--;
+    unlock_contact_slot_i(_c->contact_hash);
+}
diff --git a/modules/ims_usrloc_scscf/ucontact.h b/modules/ims_usrloc_scscf/ucontact.h
index 98f0d8a..de45db7 100644
--- a/modules/ims_usrloc_scscf/ucontact.h
+++ b/modules/ims_usrloc_scscf/ucontact.h
@@ -107,8 +107,25 @@ int mem_update_ucontact(ucontact_t* _c, ucontact_info_t *_ci);
  */
 int update_ucontact(struct impurecord* _r, ucontact_t* _c, ucontact_info_t* _ci);
 
+/*!
+ * \brief Setting contact expires to now in memory
+ * \param _c contact
+  * \return 0 on success, -1 on failure
+ */
+int mem_expire_ucontact(ucontact_t* _c);
+
+/*!
+ * \brief Setting ucontact expires to now
+ * \param _r record the contact belongs to
+ * \param _c updated contact
+ * \return 0 on success, -1 on failure
+ */
+int expire_ucontact(struct impurecord* _r, ucontact_t* _c);
+
 int remove_dialog_data_from_contact(ucontact_t* _c, unsigned int h_entry, unsigned int h_id);
 
 int add_dialog_data_to_contact(ucontact_t* _c, unsigned int h_entry, unsigned int h_id);
 
+void release_ucontact(struct ucontact* _c);
+
 #endif
diff --git a/modules/ims_usrloc_scscf/udomain.c b/modules/ims_usrloc_scscf/udomain.c
index 5823148..15bf1c9 100644
--- a/modules/ims_usrloc_scscf/udomain.c
+++ b/modules/ims_usrloc_scscf/udomain.c
@@ -65,34 +65,35 @@
 #include "usrloc.h"
 #include "bin_utils.h"
 #include "usrloc_db.h"
+#include "contact_hslot.h"
 
 extern int unreg_validity;
 extern int db_mode;
+struct contact_list* contact_list;
 
 #ifdef STATISTICS
-static char *build_stat_name( str* domain, char *var_name)
-{
-	int n;
-	char *s;
-	char *p;
-
-	n = domain->len + 1 + strlen(var_name) + 1;
-	s = (char*)shm_malloc( n );
-	if (s==0) {
-		LM_ERR("no more shm mem\n");
-		return 0;
-	}
-	memcpy( s, domain->s, domain->len);
-	p = s + domain->len;
-	*(p++) = '-';
-	memcpy( p , var_name, strlen(var_name));
-	p += strlen(var_name);
-	*(p++) = 0;
-	return s;
+
+static char *build_stat_name(str* domain, char *var_name) {
+    int n;
+    char *s;
+    char *p;
+
+    n = domain->len + 1 + strlen(var_name) + 1;
+    s = (char*) shm_malloc(n);
+    if (s == 0) {
+	LM_ERR("no more shm mem\n");
+	return 0;
+    }
+    memcpy(s, domain->s, domain->len);
+    p = s + domain->len;
+    *(p++) = '-';
+    memcpy(p, var_name, strlen(var_name));
+    p += strlen(var_name);
+    *(p++) = 0;
+    return s;
 }
 #endif
 
-
 /*!
  * \brief Create a new domain structure
  * \param  _n is pointer to str representing name of the domain, the string is
@@ -101,166 +102,156 @@ static char *build_stat_name( str* domain, char *var_name)
  * \param _d new created domain
  * \return 0 on success, -1 on failure
  */
-int new_udomain(str* _n, int _s, udomain_t** _d)
-{
-	int i;
+int new_udomain(str* _n, int _s, udomain_t** _d) {
+    int i;
 #ifdef STATISTICS
-	char *name;
+    char *name;
 #endif
 
-	/* Must be always in shared memory, since
-	 * the cache is accessed from timer which
-	 * lives in a separate process
-	 */
-	*_d = (udomain_t*)shm_malloc(sizeof(udomain_t));
-	if (!(*_d)) {
-		LM_ERR("new_udomain(): No memory left\n");
-		goto error0;
-	}
-	memset(*_d, 0, sizeof(udomain_t));
+    /* Must be always in shared memory, since
+     * the cache is accessed from timer which
+     * lives in a separate process
+     */
+    *_d = (udomain_t*) shm_malloc(sizeof (udomain_t));
+    if (!(*_d)) {
+	LM_ERR("new_udomain(): No memory left\n");
+	goto error0;
+    }
+    memset(*_d, 0, sizeof (udomain_t));
 
-	(*_d)->table = (hslot_t*)shm_malloc(sizeof(hslot_t) * _s);
-	if (!(*_d)->table) {
-		LM_ERR("no memory left 2\n");
-		goto error1;
-	}
+    (*_d)->table = (hslot_t*) shm_malloc(sizeof (hslot_t) * _s);
+    if (!(*_d)->table) {
+	LM_ERR("no memory left 2\n");
+	goto error1;
+    }
 
-	(*_d)->name = _n;
+    (*_d)->name = _n;
 
-	for(i = 0; i < _s; i++) {
-		init_slot(*_d, &((*_d)->table[i]), i);
-	}
+    for (i = 0; i < _s; i++) {
+	init_slot(*_d, &((*_d)->table[i]), i);
+    }
 
-	(*_d)->size = _s;
+    (*_d)->size = _s;
 
 #ifdef STATISTICS
-	/* register the statistics */
-	if ( (name=build_stat_name(_n,"users"))==0 || register_stat("usrloc",
-	name, &(*_d)->users, STAT_NO_RESET|STAT_SHM_NAME)!=0 ) {
-		LM_ERR("failed to add stat variable\n");
-		goto error2;
-	}
-	if ( (name=build_stat_name(_n,"contacts"))==0 || register_stat("usrloc",
-	name, &(*_d)->contacts, STAT_NO_RESET|STAT_SHM_NAME)!=0 ) {
-		LM_ERR("failed to add stat variable\n");
-		goto error2;
-	}
-	if ( (name=build_stat_name(_n,"expires"))==0 || register_stat("usrloc",
-	name, &(*_d)->expires, STAT_SHM_NAME)!=0 ) {
-		LM_ERR("failed to add stat variable\n");
-		goto error2;
-	}
+    /* register the statistics */
+    if ((name = build_stat_name(_n, "users")) == 0 || register_stat("usrloc",
+	    name, &(*_d)->users, STAT_NO_RESET | STAT_SHM_NAME) != 0) {
+	LM_ERR("failed to add stat variable\n");
+	goto error2;
+    }
+    if ((name = build_stat_name(_n, "contacts")) == 0 || register_stat("usrloc",
+	    name, &(*_d)->contacts, STAT_NO_RESET | STAT_SHM_NAME) != 0) {
+	LM_ERR("failed to add stat variable\n");
+	goto error2;
+    }
+    if ((name = build_stat_name(_n, "expires")) == 0 || register_stat("usrloc",
+	    name, &(*_d)->expires, STAT_SHM_NAME) != 0) {
+	LM_ERR("failed to add stat variable\n");
+	goto error2;
+    }
 #endif
 
-	return 0;
+    return 0;
 #ifdef STATISTICS
 error2:
-	shm_free((*_d)->table);
+    shm_free((*_d)->table);
 #endif
 error1:
-	shm_free(*_d);
+    shm_free(*_d);
 error0:
-	return -1;
+    return -1;
 }
 
-
 /*!
  * \brief Free all memory allocated for the domain
  * \param _d freed domain
  */
-void free_udomain(udomain_t* _d)
-{
-	int i;
-
-	if (_d->table) {
-		for(i = 0; i < _d->size; i++) {
-			lock_ulslot(_d, i);
-			deinit_slot(_d->table + i);
-			unlock_ulslot(_d, i);
-		}
-		shm_free(_d->table);
+void free_udomain(udomain_t* _d) {
+    int i;
+
+    if (_d->table) {
+	for (i = 0; i < _d->size; i++) {
+	    lock_ulslot(_d, i);
+	    deinit_slot(_d->table + i);
+	    unlock_ulslot(_d, i);
 	}
-	shm_free(_d);
+	shm_free(_d->table);
+    }
+    shm_free(_d);
 }
 
-
 /*!
  * \brief Returns a static dummy impurecord for temporary usage
  * \param _d domain (needed for the name)
  * \param _aor address of record
  * \param _r new created urecord
  */
-static inline void get_static_impurecord(udomain_t* _d, str* _aor,	struct impurecord** _r)
-{
-	static struct impurecord r;
-
-	memset( &r, 0, sizeof(struct impurecord) );
-	r.public_identity = *_aor;
-	r.domain = _d->name;
-	*_r = &r;
-}
+static inline void get_static_impurecord(udomain_t* _d, str* _aor, struct impurecord** _r) {
+    static struct impurecord r;
 
+    memset(&r, 0, sizeof (struct impurecord));
+    r.public_identity = *_aor;
+    r.domain = _d->name;
+    *_r = &r;
+}
 
 /*!
  * \brief Debugging helper function
  */
-void print_udomain(FILE* _f, udomain_t* _d)
-{
-	int i;
-	int max=0, slot=0, n=0;
-	struct impurecord* r;
-	fprintf(_f, "---Domain---\n");
-	fprintf(_f, "name : '%.*s'\n", _d->name->len, ZSW(_d->name->s));
-	fprintf(_f, "size : %d\n", _d->size);
-	fprintf(_f, "table: %p\n", _d->table);
-	/*fprintf(_f, "lock : %d\n", _d->lock); -- can be a structure --andrei*/
-	fprintf(_f, "\n");
-	for(i=0; i<_d->size; i++)
-	{
-		r = _d->table[i].first;
-		n += _d->table[i].n;
-		if(max<_d->table[i].n){
-			max= _d->table[i].n;
-			slot = i;
-		}
-		while(r) {
-			print_impurecord(_f, r);
-			r = r->next;
-		}
+void print_udomain(FILE* _f, udomain_t* _d) {
+    int i;
+    int max = 0, slot = 0, n = 0;
+    struct impurecord* r;
+    fprintf(_f, "---Domain---\n");
+    fprintf(_f, "name : '%.*s'\n", _d->name->len, ZSW(_d->name->s));
+    fprintf(_f, "size : %d\n", _d->size);
+    fprintf(_f, "table: %p\n", _d->table);
+    /*fprintf(_f, "lock : %d\n", _d->lock); -- can be a structure --andrei*/
+    fprintf(_f, "\n");
+    for (i = 0; i < _d->size; i++) {
+	r = _d->table[i].first;
+	n += _d->table[i].n;
+	if (max < _d->table[i].n) {
+	    max = _d->table[i].n;
+	    slot = i;
+	}
+	while (r) {
+	    print_impurecord(_f, r);
+	    r = r->next;
 	}
-	fprintf(_f, "\nMax slot: %d (%d/%d)\n", max, slot, n);
-	fprintf(_f, "\n---/Domain---\n");
+    }
+    fprintf(_f, "\nMax slot: %d (%d/%d)\n", max, slot, n);
+    fprintf(_f, "\n---/Domain---\n");
 }
 
+inline int time2str(time_t _v, char* _s, int* _l) {
+    struct tm* t;
+    int l;
 
-inline int time2str(time_t _v, char* _s, int* _l)
-{
-	struct tm* t;
-	int l;
-
-	if ((!_s) || (!_l) || (*_l < 2)) {
-		LM_ERR("Invalid parameter value\n");
-		return -1;
-	}
+    if ((!_s) || (!_l) || (*_l < 2)) {
+	LM_ERR("Invalid parameter value\n");
+	return -1;
+    }
 
-	*_s++ = '\'';
+    *_s++ = '\'';
 
-	/* Convert time_t structure to format accepted by the database */
-	t = localtime(&_v);
-	l = strftime(_s, *_l -1, "%Y-%m-%d %H:%M:%S", t);
+    /* Convert time_t structure to format accepted by the database */
+    t = localtime(&_v);
+    l = strftime(_s, *_l - 1, "%Y-%m-%d %H:%M:%S", t);
 
-	if (l == 0) {
-		LM_ERR("Error during time conversion\n");
-		/* the value of _s is now unspecified */
-		_s = NULL;
-		_l = 0;
-		return -1;
-	}
-	*_l = l;
+    if (l == 0) {
+	LM_ERR("Error during time conversion\n");
+	/* the value of _s is now unspecified */
+	_s = NULL;
+	_l = 0;
+	return -1;
+    }
+    *_l = l;
 
-	*(_s + l) = '\'';
-	*_l = l + 2;
-	return 0;
+    *(_s + l) = '\'';
+    *_l = l + 2;
+    return 0;
 }
 
 /*!
@@ -271,159 +262,197 @@ inline int time2str(time_t _v, char* _s, int* _l)
  * \return 0 on success, -1 on failure
  */
 int mem_insert_impurecord(struct udomain* _d, str* public_identity, int reg_state, int barring,
-		ims_subscription** s, str* ccf1, str* ccf2, str* ecf1, str* ecf2,
-		struct impurecord** _r) {
-	int sl;
-
-	if (new_impurecord(_d->name, public_identity, reg_state, barring, s, ccf1, ccf2, ecf1,
-			ecf2, _r) < 0) {
-		LM_ERR("creating impurecord failed\n");
-		return -1;
-	}
-	LM_DBG("Successfully parsed user data\n");
+	ims_subscription** s, str* ccf1, str* ccf2, str* ecf1, str* ecf2,
+	struct impurecord** _r) {
+    int sl;
 
-	sl = ((*_r)->aorhash) & (_d->size - 1);
-	slot_add(&_d->table[sl], *_r);
-	update_stat( _d->users, 1);
-	return 0;
-}
+    if (new_impurecord(_d->name, public_identity, reg_state, barring, s, ccf1, ccf2, ecf1,
+	    ecf2, _r) < 0) {
+	LM_ERR("creating impurecord failed\n");
+	return -1;
+    }
+    LM_DBG("Successfully parsed user data\n");
 
+    sl = ((*_r)->aorhash) & (_d->size - 1);
+    slot_add(&_d->table[sl], *_r);
+    update_stat(_d->users, 1);
+
+    LM_DBG("inserted new impurecord into memory [%.*s]\n", (*_r)->public_identity.len, (*_r)->public_identity.s);
+    return 0;
+}
 
 /*!
  * \brief Remove a record from domain in memory
  * \param _d domain the record belongs to
  * \param _r deleted record
  */
-void mem_delete_impurecord(udomain_t* _d, struct impurecord* _r)
-{
-	slot_rem(_r->slot, _r);
-	free_impurecord(_r);
-	update_stat( _d->users, -1);
+void mem_delete_impurecord(udomain_t* _d, struct impurecord* _r) {
+    LM_DBG("deleting impurecord from memory [%.*s]\n", _r->public_identity.len, _r->public_identity.s);
+    slot_rem(_r->slot, _r);
+    free_impurecord(_r);
+    update_stat(_d->users, -1);
 }
 
-
 /*!
  * \brief Run timer handler for given domain
  * \param _d domain
  */
-void mem_timer_udomain(udomain_t* _d)
-{
-	struct impurecord* ptr, *t, *temp_impu;
-	int i, j, k;
-	ims_public_identity* impu;
-	unsigned int sl;
-
-	time_t time_now = time(NULL);
-
-	for(i=0; i<_d->size; i++)
-	{
-		lock_ulslot(_d, i);
-
-		ptr = _d->table[i].first;
-
-		while(ptr) {
-			timer_impurecord(ptr);
-			t = ptr;
-			ptr = ptr->next;
-
-			if (t->reg_state == IMPU_NOT_REGISTERED && t->shead == 0) {
-				//remove it - housekeeping - not sure why its still here...?
-				if (exists_ulcb_type(t->cbs, UL_IMPU_NR_DELETE))
-					run_ul_callbacks(t->cbs, UL_IMPU_NR_DELETE, t, NULL);
-					delete_impurecord(_d, &t->public_identity, t);
-			} else if (t->reg_state == IMPU_UNREGISTERED) {//Remove IMPU record if it is in state IMPU_UNREGISTERED and has expired
-			    
-				if (time_now >= t->expires) {//check here and only remove if no subscribes - if there is a subscribe then bump the validity by unreg_validity
-				    if(t->shead != 0){
-					LM_DBG("This impurecord still has subscriptions - extending the expiry");
-					t->expires = time(NULL) + unreg_validity;
-				    } else {
-					if (exists_ulcb_type(t->cbs, UL_IMPU_UNREG_EXPIRED))
-						run_ul_callbacks(t->cbs, UL_IMPU_UNREG_EXPIRED, t, NULL);
-					delete_impurecord(_d, &t->public_identity, t);
-				    }
-				}
-			//} else if (t->reg_state != IMPU_UNREGISTERED && t->contacts == 0) { /* Remove the entire record if it is empty IFF it is not an UNREGISTERED RECORD */
-			} else if (t->reg_state != IMPU_UNREGISTERED && t->contacts == 0 && t->shead == 0) { /* Remove the entire record if it is empty IFF it is not an UNREGISTERED RECORD */
-																								/* TS 23.228 5.3.2.1 (release 11) */
-				//need a way of distinguishing between deletes that need a SAR (expired) and deletes that do not need a SAR (explicit de reg)
-				//we only want to send one SAR for each implicit IMPU set
-				//make sure all IMPU's associated with this set are de-registered before calling the callbacks
-				int first=1;
-				int this_is_first = 0;
-
-				lock_get(t->s->lock);
-				for (k = 0; k < t->s->service_profiles_cnt; k++){
-					for (j = 0;j < t->s->service_profiles[k].public_identities_cnt;j++) {
-						impu = &(t->s->service_profiles[k].public_identities[j]);
-
-						sl = core_hash(&impu->public_identity, 0, _d->size);
-						if (sl != i)
-							lock_udomain(_d, &impu->public_identity);
-
-						if (first) {
-							first = 0; //dont do anything - we will leave this impu to be processed as normal
-							if (!strncmp(impu->public_identity.s, t->public_identity.s, t->public_identity.len)) {
-								//we are the first in the implicit set
-								this_is_first = 1;
-							}
-						} else {
-							//set all other implicits to not registered
-							if (update_impurecord(_d, &impu->public_identity, IMPU_NOT_REGISTERED,
-														-1/*barring*/, -1 /*do not change send sar on delete */, 0/*is_primary*/, NULL, NULL, NULL, NULL, NULL, &temp_impu) != 0) {
-								LM_ERR("Unable to update impurecord for <%.*s>\n", impu->public_identity.len, impu->public_identity.s);
-							}
-						}
-						if (sl != i)
-							unlock_udomain(_d, &impu->public_identity);
-					}
-				}
-				lock_release(t->s->lock);
-
-				if (this_is_first) {
-					//now run a normal callback on our
-					if (exists_ulcb_type(t->cbs, UL_IMPU_REG_NC_DELETE))
-						run_ul_callbacks(t->cbs, UL_IMPU_REG_NC_DELETE, t, NULL);
-						delete_impurecord(_d, &t->public_identity, t);
-				}
-			}
-		}
-		unlock_ulslot(_d, i);
+void mem_timer_udomain(udomain_t* _d) {
+    struct impurecord* ptr, *t;
+    struct ucontact* contact_ptr, *tmp_contact_ptr;
+    int i;
+
+    //go through contacts first
+    LM_DBG("*** mem_timer_udomain - checking contacts - START ***\n");
+    
+    for (i = 0; i < contact_list->size; i++) {
+#ifdef EXTRA_DEBUG
+	LM_DBG("looking for contacts in slot %d\n", i);
+#endif
+	lock_contact_slot_i(i);
+	contact_ptr = contact_list->slot[i].first;
+	while (contact_ptr) {
+	    LM_DBG("We have a contact in the new contact list in slot %d = [%.*s] (%.*s) which expires in %lf seconds and has a ref count of %d\n", i, contact_ptr->aor.len, contact_ptr->aor.s, contact_ptr->c.len, contact_ptr->c.s, (double) contact_ptr->expires - time(NULL), contact_ptr->ref_count);
+	    if (contact_ptr->ref_count <= 0) {
+		LM_DBG("Deleting contact [%.*s]\n", contact_ptr->c.len, contact_ptr->c.s);
+		tmp_contact_ptr = contact_ptr->next;
+		delete_ucontact(contact_ptr);
+		contact_ptr = tmp_contact_ptr;
+	    } else {
+		contact_ptr = contact_ptr->next;
+	    }
+	}
+	unlock_contact_slot_i(i);
+    }
+    
+    LM_DBG("*** mem_timer_udomain - checking contacts - FINISHED ***\n");
+
+    int temp = 0;
+
+    LM_DBG("*** mem_timer_udomain - checking IMPUs - START ***\n");
+    for (i = 0; i < _d->size; i++) {
+	lock_ulslot(_d, i);
+	ptr = _d->table[i].first;
+	temp = 0;
+	while (ptr) {
+	    temp = 1;
+#ifdef EXTRA_DEBUG
+	    LM_DBG("ULSLOT %d LOCKED\n", i);
+#endif
+	    t = ptr;
+	    ptr = ptr->next;
+	    timer_impurecord(t);
+
+//	    			if (t->reg_state == IMPU_NOT_REGISTERED && t->shead == 0) {
+//	    				//remove it - housekeeping - not sure why its still here...?
+//	    				if (exists_ulcb_type(t->cbs, UL_IMPU_NR_DELETE))
+//	    					run_ul_callbacks(t->cbs, UL_IMPU_NR_DELETE, t, NULL);
+//	    					    
+//	    				LM_DBG("about to delete impurecord\n");
+//	    				delete_impurecord(_d, &t->public_identity, t);
+//	    			} //else if (t->reg_state == IMPU_UNREGISTERED) {//Remove IMPU record if it is in state IMPU_UNREGISTERED and has expired
+	    //			    
+	    //				if (time_now >= t->expires) {//check here and only remove if no subscribes - if there is a subscribe then bump the validity by unreg_validity
+	    //				    if(t->shead != 0){
+	    //					LM_DBG("This impurecord still has subscriptions - extending the expiry");
+	    //					t->expires = time(NULL) + unreg_validity;
+	    //				    } else {
+	    //					if (exists_ulcb_type(t->cbs, UL_IMPU_UNREG_EXPIRED))
+	    //						run_ul_callbacks(t->cbs, UL_IMPU_UNREG_EXPIRED, t, NULL);
+	    //					LM_DBG("about to delete impurecord\n");
+	    //					delete_impurecord(_d, &t->public_identity, t);
+	    //				    }
+	    //				}
+	    //			//} else if (t->reg_state != IMPU_UNREGISTERED && t->contacts == 0) { /* Remove the entire record if it is empty IFF it is not an UNREGISTERED RECORD */
+	    //			} else if (t->reg_state != IMPU_UNREGISTERED && t->num_contacts == 0 && t->shead == 0) { /* Remove the entire record if it is empty IFF it is not an UNREGISTERED RECORD */
+	    //																								/* TS 23.228 5.3.2.1 (release 11) */
+	    //				//need a way of distinguishing between deletes that need a SAR (expired) and deletes that do not need a SAR (explicit de reg)
+	    //				//we only want to send one SAR for each implicit IMPU set
+	    //				//make sure all IMPU's associated with this set are de-registered before calling the callbacks
+	    //				int first=1;
+	    //				int this_is_first = 0;
+	    //
+	    //				lock_get(t->s->lock);
+	    //				for (k = 0; k < t->s->service_profiles_cnt; k++){
+	    //					for (j = 0;j < t->s->service_profiles[k].public_identities_cnt;j++) {
+	    //						impu = &(t->s->service_profiles[k].public_identities[j]);
+	    //
+	    //						sl = core_hash(&impu->public_identity, 0, _d->size);
+	    //						if (sl != i)
+	    //							lock_udomain(_d, &impu->public_identity);
+	    //
+	    //						if (first) {
+	    //							first = 0; //dont do anything - we will leave this impu to be processed as normal
+	    //							if (!strncmp(impu->public_identity.s, t->public_identity.s, t->public_identity.len)) {
+	    //								//we are the first in the implicit set
+	    //								this_is_first = 1;
+	    //							}
+	    //						} else {
+	    //							//set all other implicits to not registered
+	    //							if (update_impurecord(_d, &impu->public_identity, IMPU_NOT_REGISTERED,
+	    //														-1/*barring*/, -1 /*do not change send sar on delete */, 0/*is_primary*/, NULL, NULL, NULL, NULL, NULL, &temp_impu) != 0) {
+	    //								LM_ERR("Unable to update impurecord for <%.*s>\n", impu->public_identity.len, impu->public_identity.s);
+	    //							}
+	    //						}
+	    //						if (sl != i)
+	    //							unlock_udomain(_d, &impu->public_identity);
+	    //					}
+	    //				}
+	    //				lock_release(t->s->lock);
+	    //
+	    //				if (this_is_first) {
+	    //					//now run a normal callback on our
+	    //					if (exists_ulcb_type(t->cbs, UL_IMPU_REG_NC_DELETE))
+	    //						run_ul_callbacks(t->cbs, UL_IMPU_REG_NC_DELETE, t, NULL);
+	    //					LM_DBG("about to delete impurecord\n");
+	    //						delete_impurecord(_d, &t->public_identity, t);
+	    //				}
+	    //			}
+	}
+	if (temp) {
+#ifdef EXTRA_DEBUG
+	    LM_DBG("ULSLOT %d UN-LOCKED\n", i);
+#endif
 	}
+	unlock_ulslot(_d, i);
+    }
+    LM_DBG("*** mem_timer_udomain - checking IMPUs - FINISHED ***\n");
 }
 
-
 /*!
  * \brief Get lock for a domain
  * \param _d domain
  * \param _aor adress of record, used as hash source for the lock slot
  */
-void lock_udomain(udomain_t* _d, str* _aor)
-{
-	unsigned int sl;
-	sl = core_hash(_aor, 0, _d->size);
+void lock_udomain(udomain_t* _d, str* _aor) {
+    unsigned int sl;
+    sl = core_hash(_aor, 0, _d->size);
+#ifdef EXTRA_DEBUG
+    LM_DBG("LOCKING UDOMAIN SLOT [%d]\n", sl);
+#endif
 
 #ifdef GEN_LOCK_T_PREFERED
-	lock_get(_d->table[sl].lock);
+    lock_get(_d->table[sl].lock);
 #else
-	ul_lock_idx(_d->table[sl].lockidx);
+    ul_lock_idx(_d->table[sl].lockidx);
 #endif
 }
 
-
 /*!
  * \brief Release lock for a domain
  * \param _d domain
  * \param _aor address of record, uses as hash source for the lock slot
  */
-void unlock_udomain(udomain_t* _d, str* _aor)
-{
-	unsigned int sl;
-	sl = core_hash(_aor, 0, _d->size);
+void unlock_udomain(udomain_t* _d, str* _aor) {
+    unsigned int sl;
+    sl = core_hash(_aor, 0, _d->size);
+#ifdef EXTRA_DEBUG
+    LM_DBG("UN-LOCKING UDOMAIN SLOT [%d]\n", sl);
+#endif
 #ifdef GEN_LOCK_T_PREFERED
-	lock_release(_d->table[sl].lock);
+    lock_release(_d->table[sl].lock);
 #else
-	ul_release_idx(_d->table[sl].lockidx);
+    ul_release_idx(_d->table[sl].lockidx);
 #endif
 }
 
@@ -432,30 +461,61 @@ void unlock_udomain(udomain_t* _d, str* _aor)
  * \param _d domain
  * \param i slot number
  */
-void lock_ulslot(udomain_t* _d, int i)
-{
+void lock_ulslot(udomain_t* _d, int i) {
 #ifdef GEN_LOCK_T_PREFERED
-	lock_get(_d->table[i].lock);
+    lock_get(_d->table[i].lock);
 #else
-	ul_lock_idx(_d->table[i].lockidx);
+    ul_lock_idx(_d->table[i].lockidx);
 #endif
 }
 
-
 /*!
  * \brief Release lock for a slot
  * \param _d domain
  * \param i slot number
  */
-void unlock_ulslot(udomain_t* _d, int i)
-{
+void unlock_ulslot(udomain_t* _d, int i) {
+#ifdef GEN_LOCK_T_PREFERED
+    lock_release(_d->table[i].lock);
+#else
+    ul_release_idx(_d->table[i].lockidx);
+#endif
+}
+
+void lock_contact_slot(str* contact_uri) {
+    unsigned int sl;
+    sl = core_hash(contact_uri, 0, contact_list->size);
+    lock_contact_slot_i(sl);
+}
+
+void unlock_contact_slot(str* contact_uri) {
+    unsigned int sl;
+    sl = core_hash(contact_uri, 0, contact_list->size);
+
+    unlock_contact_slot_i(sl);
+}
+
+void lock_contact_slot_i(int i) {
+#ifdef EXTRA_DEBUG
+    LM_DBG("LOCKING CONTACT SLOT [%d]\n", i);
+#endif
 #ifdef GEN_LOCK_T_PREFERED
-	lock_release(_d->table[i].lock);
+    lock_get(contact_list->slot[i].lock);
 #else
-	ul_release_idx(_d->table[i].lockidx);
+    lock_contacts_idx(contact_list->slot[i].lockidx);
 #endif
 }
 
+void unlock_contact_slot_i(int i) {
+#ifdef EXTRA_DEBUG
+    LM_DBG("UN-LOCKING CONTACT SLOT [%d]\n", i);
+#endif
+#ifdef GEN_LOCK_T_PREFERED
+    lock_release(contact_list->slot[i].lock);
+#else
+    release_contact_idx(contact_list->slot[i].lockidx);
+#endif
+}
 
 /*!
  * \brief Create and insert a new record
@@ -465,39 +525,38 @@ void unlock_ulslot(udomain_t* _d, int i)
  * \return return 0 on success, -1 on failure
  */
 int insert_impurecord(struct udomain* _d, str* public_identity, int reg_state, int barring,
-		ims_subscription** s, str* ccf1, str* ccf2, str* ecf1, str* ecf2,
-		struct impurecord** _r) {
-
-//	ims_subscription* s = 0;
-//	/*check we can parse XML user data*/
-//	if (xml_data->s && xml_data->len > 0) {
-//		s = parse_user_data(*xml_data);
-//		if (!s) {
-//			LM_ERR("Unable to parse XML user data from SAA\n");
-//			goto error;
-//		}
-//	}
+	ims_subscription** s, str* ccf1, str* ccf2, str* ecf1, str* ecf2,
+	struct impurecord** _r) {
+
+    //	ims_subscription* s = 0;
+    //	/*check we can parse XML user data*/
+    //	if (xml_data->s && xml_data->len > 0) {
+    //		s = parse_user_data(*xml_data);
+    //		if (!s) {
+    //			LM_ERR("Unable to parse XML user data from SAA\n");
+    //			goto error;
+    //		}
+    //	}
     if (mem_insert_impurecord(_d, public_identity, reg_state, barring, s, ccf1, ccf2, ecf1, ecf2, _r) < 0) {
-        LM_ERR("inserting record failed\n");
-        goto error;
+	LM_ERR("inserting record failed\n");
+	goto error;
     }
 
     /*DB?*/
-	if (db_mode == WRITE_THROUGH && db_insert_impurecord(_d, public_identity, reg_state, barring, s, ccf1, ccf2, ecf1, ecf2, _r) != 0) {
-		LM_ERR("error inserting contact into db");
-		goto error;
-	}
+    if (db_mode == WRITE_THROUGH && db_insert_impurecord(_d, public_identity, reg_state, barring, s, ccf1, ccf2, ecf1, ecf2, _r) != 0) {
+	LM_ERR("error inserting contact into db");
+	goto error;
+    }
 
     return 0;
 
 error:
-//    if (s) {
-//    	free_ims_subscription_data(s);
-//    }
+    //    if (s) {
+    //    	free_ims_subscription_data(s);
+    //    }
     return -1;
 }
 
-
 /*!
  * \brief Obtain a impurecord pointer if the impurecord exists in domain
  * \param _d domain to search the record
@@ -506,24 +565,24 @@ error:
  * \return 0 if a record was found, 1 if nothing could be found
  */
 int get_impurecord(udomain_t* _d, str* public_identity, struct impurecord** _r) {
-	unsigned int sl, i, aorhash;
-	impurecord_t* r;
-
-	/* search in cache */
-	aorhash = core_hash(public_identity, 0, 0);
-	sl = aorhash & (_d->size - 1);
-	r = _d->table[sl].first;
-
-	for (i = 0; i < _d->table[sl].n; i++) {
-		if ((r->aorhash == aorhash) && (r->public_identity.len == public_identity->len)
-				&& !memcmp(r->public_identity.s, public_identity->s, public_identity->len)) {
-			*_r = r;
-			return 0;
-		}
-
-		r = r->next;
+    unsigned int sl, i, aorhash;
+    impurecord_t* r;
+
+    /* search in cache */
+    aorhash = core_hash(public_identity, 0, 0);
+    sl = aorhash & (_d->size - 1);
+    r = _d->table[sl].first;
+
+    for (i = 0; i < _d->table[sl].n; i++) {
+	if ((r->aorhash == aorhash) && (r->public_identity.len == public_identity->len)
+		&& !memcmp(r->public_identity.s, public_identity->s, public_identity->len)) {
+	    *_r = r;
+	    return 0;
 	}
-	return 1; /* Nothing found */
+
+	r = r->next;
+    }
+    return 1; /* Nothing found */
 }
 
 /*!
@@ -533,41 +592,41 @@ int get_impurecord(udomain_t* _d, str* public_identity, struct impurecord** _r)
  * \param _r deleted record
  * \return 0 on success, -1 if the record could not be deleted
  */
-int delete_impurecord(udomain_t* _d, str* _aor, struct impurecord* _r)
-{
-	struct ucontact* c, *t;
-
-    LM_DBG("Deleting IMPURECORD\n");
+int delete_impurecord(udomain_t* _d, str* _aor, struct impurecord* _r) {
+    //    struct ucontact* c;//, *t;
 
-	if (_r==0) {
-		if (get_impurecord(_d, _aor, &_r) > 0) {
-			return 0;
-		}
-	}
-
-    c = _r->contacts;
-	while(c) {
-		t = c;
-		c = c->next;
-		if (delete_ucontact(_r, t) < 0) {
-			LM_ERR("deleting contact failed\n");
-			return -1;
-		}
-	}
+    LM_DBG("Deleting IMPURECORD [%.*s]\n", _r->public_identity.len, _r->public_identity.s);
 
-	if (exists_ulcb_type(_r->cbs, UL_IMPU_DELETE)) {
-	        run_ul_callbacks(_r->cbs, UL_IMPU_DELETE, _r, 0);
+    if (_r == 0) {
+	if (get_impurecord(_d, _aor, &_r) > 0) {
+	    return 0;
 	}
+    }
 
-	/*DB?*/
-	if (db_mode == WRITE_THROUGH
-			&& db_delete_impurecord(_d, _r) != 0) {
-		LM_ERR("error inserting contact into db");
-		return 0;
-	}
+    //TODO: need to unref the contacts in the contact list (not delete them), the timer should delete all contacts that are unreffed
+    //    c = _r->contacts;
+    //    while (c) {
+    //	t = c;
+    //	c = c->next;
+    //	if (delete_ucontact(_r, t) < 0) {
+    //	    LM_ERR("deleting contact failed [%.*s]\n", c->aor.len, c->aor.s);
+    //	    return -1;
+    //	}
+    //    }
+
+    if (exists_ulcb_type(_r->cbs, UL_IMPU_DELETE)) {
+	run_ul_callbacks(_r->cbs, UL_IMPU_DELETE, _r, 0);
+    }
 
-	mem_delete_impurecord(_d, _r);
+    /*DB?*/
+    if (db_mode == WRITE_THROUGH
+	    && db_delete_impurecord(_d, _r) != 0) {
+	LM_ERR("error deleting IMPU record from db");
 	return 0;
+    }
+
+    mem_delete_impurecord(_d, _r);
+    return 0;
 }
 
 /*
@@ -577,82 +636,85 @@ int delete_impurecord(udomain_t* _d, str* _aor, struct impurecord* _r)
  * barring-(-1) get all records
  * NB. Remember to free the block of memory pointed to by impus (pkg_malloc)
  */
-int get_impus_from_subscription_as_string(udomain_t* _d, impurecord_t* impu_rec, int barring, str** impus, int* num_impus)
-{
-	int i, j, count;
-	*num_impus = 0;
-	*impus = 0;
-	ims_public_identity* impi;
-	int bytes_needed = 0;
-	int len = 0;
-
-	LM_DBG("getting IMPU subscription set\n");
-
-	if (!impu_rec){
-		LM_ERR("no impu record provided\n");
-		return 1;
-	}
+int get_impus_from_subscription_as_string(udomain_t* _d, impurecord_t* impu_rec, int barring, str** impus, int* num_impus) {
+    int i, j, count;
+    *num_impus = 0;
+    *impus = 0;
+    ims_public_identity* impi;
+    int bytes_needed = 0;
+    int len = 0;
+
+    LM_DBG("getting IMPU subscription set\n");
+
+    if (!impu_rec) {
+	LM_ERR("no impu record provided\n");
+	return 1;
+    }
 
-	if (!impu_rec->s) {
-		LM_DBG("no subscription associated with impu\n");
-		return 0;
-	}
+    if (!impu_rec->s) {
+	LM_DBG("no subscription associated with impu\n");
+	return 0;
+    }
 
-	lock_get(impu_rec->s->lock);
-	for (i = 0; i < impu_rec->s->service_profiles_cnt; i++) {
-		for (j = 0; j < impu_rec->s->service_profiles[i].public_identities_cnt; j++) {
-			impi = &(impu_rec->s->service_profiles[i].public_identities[j]);
-			if (barring<0) {
-				//get all records
-				bytes_needed += impi->public_identity.len;
-				(*num_impus)++;
-			} else {
-				if (impi->barring == barring) {
-					//add the record to the list
-					bytes_needed += impi->public_identity.len;
-					(*num_impus)++;
-				}
-			}
+    lock_get(impu_rec->s->lock);
+    for (i = 0; i < impu_rec->s->service_profiles_cnt; i++) {
+	for (j = 0; j < impu_rec->s->service_profiles[i].public_identities_cnt; j++) {
+	    impi = &(impu_rec->s->service_profiles[i].public_identities[j]);
+	    if (barring < 0) {
+		//get all records
+		bytes_needed += impi->public_identity.len;
+		(*num_impus)++;
+	    } else {
+		if (impi->barring == barring) {
+		    //add the record to the list
+		    bytes_needed += impi->public_identity.len;
+		    (*num_impus)++;
 		}
+	    }
 	}
-	LM_DBG("num of records returned is %d and we need %d bytes\n", *num_impus, bytes_needed);
-
-	len = (sizeof(str)*(*num_impus)) + bytes_needed;
-	*impus = (str*)pkg_malloc(len);
-	char* ptr = (char*)(*impus + *num_impus);
-
-	//now populate the data
-	count=0;
-	for (i = 0; i < impu_rec->s->service_profiles_cnt; i++) {
-		for (j = 0; j < impu_rec->s->service_profiles[i].public_identities_cnt; j++) {
-			impi = &(impu_rec->s->service_profiles[i].public_identities[j]);
-			if (barring < 0) {
-				//get all records
-				(*impus)[count].s = ptr;
-				memcpy(ptr, impi->public_identity.s, impi->public_identity.len);
-				(*impus)[count].len = impi->public_identity.len;
-				ptr += impi->public_identity.len;
-				count++;
-			} else {
-				if (impi->barring == barring) {
-					//add the record to the list
-					(*impus)[count].s = ptr;
-					memcpy(ptr, impi->public_identity.s, impi->public_identity.len);
-					(*impus)[count].len = impi->public_identity.len;
-					ptr += impi->public_identity.len;
-					count++;
-				}
-			}
+    }
+    LM_DBG("num of records returned is %d and we need %d bytes\n", *num_impus, bytes_needed);
+
+    len = (sizeof (str)*(*num_impus)) + bytes_needed;
+    *impus = (str*) pkg_malloc(len);
+    if (*impus == 0) {
+	LM_ERR("no more pkg_mem\n");
+	return 0;
+    }
+    char* ptr = (char*) (*impus + *num_impus);
+
+    //now populate the data
+    count = 0;
+    for (i = 0; i < impu_rec->s->service_profiles_cnt; i++) {
+	for (j = 0; j < impu_rec->s->service_profiles[i].public_identities_cnt; j++) {
+	    impi = &(impu_rec->s->service_profiles[i].public_identities[j]);
+	    if (barring < 0) {
+		//get all records
+		(*impus)[count].s = ptr;
+		memcpy(ptr, impi->public_identity.s, impi->public_identity.len);
+		(*impus)[count].len = impi->public_identity.len;
+		ptr += impi->public_identity.len;
+		count++;
+	    } else {
+		if (impi->barring == barring) {
+		    //add the record to the list
+		    (*impus)[count].s = ptr;
+		    memcpy(ptr, impi->public_identity.s, impi->public_identity.len);
+		    (*impus)[count].len = impi->public_identity.len;
+		    ptr += impi->public_identity.len;
+		    count++;
 		}
+	    }
 	}
+    }
 
-	if (ptr != ((char*)*impus + len)) {
-		LM_CRIT("buffer overflow\n");
-		return 1;
-	}
+    if (ptr != ((char*) *impus + len)) {
+	LM_CRIT("buffer overflow\n");
+	return 1;
+    }
 
-	lock_release(impu_rec->s->lock);
+    lock_release(impu_rec->s->lock);
 
-	return 0;
+    return 0;
 }
 
diff --git a/modules/ims_usrloc_scscf/udomain.h b/modules/ims_usrloc_scscf/udomain.h
index 22ef64d..cedc1f7 100644
--- a/modules/ims_usrloc_scscf/udomain.h
+++ b/modules/ims_usrloc_scscf/udomain.h
@@ -62,21 +62,20 @@
 #include "hslot.h"
 #include "usrloc.h"
 
-struct hslot;   /*!< Hash table slot */
+struct hslot; /*!< Hash table slot */
 struct impurecord; /*!< Usrloc record */
 
-
 /*! \brief
  * The structure represents a usrloc domain
  */
 struct udomain {
-	str* name;                 /*!< Domain name (NULL terminated) */
-	int size;                  /*!< Hash table size */
-	struct hslot* table;       /*!< Hash table - array of collision slots */
-	/* statistics */
-	stat_var *users;           /*!< no of registered users */
-	stat_var *contacts;        /*!< no of registered contacts */
-	stat_var *expires;         /*!< no of expires */
+    str* name; /*!< Domain name (NULL terminated) */
+    int size; /*!< Hash table size */
+    struct hslot* table; /*!< Hash table - array of collision slots */
+    /* statistics */
+    stat_var *users; /*!< no of registered users */
+    stat_var *contacts; /*!< no of registered contacts */
+    stat_var *expires; /*!< no of expires */
 };
 
 
@@ -159,6 +158,11 @@ void lock_ulslot(udomain_t* _d, int i);
  */
 void unlock_ulslot(udomain_t* _d, int i);
 
+void lock_contact_slot(str* contact_uri);
+void unlock_contact_slot(str* contact_uri);
+void lock_contact_slot_i(int i);
+void unlock_contact_slot_i(int i);
+
 /* ===== module interface ======= */
 
 
@@ -170,8 +174,8 @@ void unlock_ulslot(udomain_t* _d, int i);
  * \return return 0 on success, -1 on failure
  */
 int insert_impurecord(struct udomain* _d, str* public_identity, int reg_state, int barring,
-		ims_subscription** s, str* ccf1, str* ccf2, str* ecf1, str* ecf2,
-		struct impurecord** _r);
+        ims_subscription** s, str* ccf1, str* ccf2, str* ecf1, str* ecf2,
+        struct impurecord** _r);
 
 
 /*!
diff --git a/modules/ims_usrloc_scscf/ul_callback.h b/modules/ims_usrloc_scscf/ul_callback.h
index 6f66f88..50eedf5 100644
--- a/modules/ims_usrloc_scscf/ul_callback.h
+++ b/modules/ims_usrloc_scscf/ul_callback.h
@@ -82,15 +82,13 @@ struct ul_callback {
 	struct ul_callback* next;
 };
 
-struct ulcb_head_list {
+    struct ulcb_head_list {
 	struct ul_callback *first;
 	int reg_types;
 };
 
-
 extern struct ulcb_head_list*  ulcb_list;
 
-
 static inline int exists_ulcb_type(struct ulcb_head_list* list, int types) {
 	if (list==NULL)
 		return (ulcb_list->reg_types|types);
@@ -102,7 +100,6 @@ int init_ulcb_list(void);
 
 void destroy_ulcb_list(void);
 
-
 /*! \brief register a callback for several types of events */
 int register_ulcb( struct impurecord* r, struct ucontact* c, int types, ul_cb f, void *param );
 
diff --git a/modules/ims_usrloc_scscf/ul_mod.c b/modules/ims_usrloc_scscf/ul_mod.c
index a398ac1..d963c8d 100644
--- a/modules/ims_usrloc_scscf/ul_mod.c
+++ b/modules/ims_usrloc_scscf/ul_mod.c
@@ -60,10 +60,9 @@
 #include "usrloc.h"
 #include "hslot_sp.h"
 #include "usrloc_db.h"
-
+#include "contact_hslot.h"
 #include "../presence/bind_presence.h"
 #include "../presence/hash.h"
-
 #include "../../modules/dialog_ng/dlg_load.h"
 #include "../../modules/dialog_ng/dlg_hash.h"
 
@@ -81,6 +80,7 @@ static int child_init(int rank);                    /*!< Per-child init function
 extern int bind_usrloc(usrloc_api_t* api);
 extern int ul_locks_no;
 extern int subs_locks_no;
+extern int contacts_locks_no;
 /*
  * Module parameters and their default values
  */
@@ -98,6 +98,9 @@ int maxcontact_behaviour = 0;			/*!< max contact behaviour - 0-disabled(default)
 int ul_fetch_rows = 2000;				/*!< number of rows to fetch from result */
 int ul_hash_size = 9;
 int subs_hash_size = 9;					/*!<number of ims subscription slots*/
+int contacts_hash_size = 9;
+
+struct contact_list* contact_list;
 
 int db_mode = 0;						/*!<database mode*/
 db1_con_t* ul_dbh = 0;
@@ -188,7 +191,7 @@ struct module_exports exports = {
  * Module initialization function
  */
 static int mod_init(void) {
-
+	int i;
 	load_dlg_f load_dlg;
 	if (usrloc_debug){
 		LM_INFO("Logging usrloc records to %.*s\n", usrloc_debug_file.len, usrloc_debug_file.s);
@@ -221,12 +224,19 @@ static int mod_init(void) {
 	else
 		subs_hash_size = 1 << subs_hash_size;
 	subs_locks_no = subs_hash_size;
+	
+	if (contacts_hash_size <= 1)
+		contacts_hash_size = 512;
+	else
+		contacts_hash_size = 1 << contacts_hash_size;
+	contacts_locks_no = contacts_hash_size;
 
 	/* check matching mode */
 	switch (matching_mode) {
 		case CONTACT_ONLY:
 		case CONTACT_CALLID:
 		case CONTACT_PATH:
+		case CONTACT_PORT_IP_ONLY:
 			break;
 		default:
 			LM_ERR("invalid matching mode %d\n", matching_mode);
@@ -241,7 +251,27 @@ static int mod_init(void) {
 		LM_ERR("IMS Subscription locks array initialization failed\n");
 		return -1;
 	}
-
+	
+	/* create hash table for storing registered contacts */
+	if (init_contacts_locks() !=0) {
+	    LM_ERR("failed to initialise locks array for contacts\n");
+	    return -1;
+	}
+	contact_list = (struct contact_list*)shm_malloc(sizeof(struct contact_list));
+	if (!contact_list) {
+	    LM_ERR("no more memory to create contact list structure\n");
+	    return -1;
+	}
+	contact_list->slot = (struct contact_hslot*) shm_malloc(sizeof(struct contact_hslot) * contacts_hash_size);
+	if (!contact_list->slot) {
+	    LM_ERR("no more memory to create contact list structure\n");
+	    return -1;
+	}
+	for (i=0; i<contacts_hash_size;i++) {
+	    init_contact_slot(&contact_list->slot[i], i);
+	} 
+	contact_list->size = contacts_hash_size;
+	
 	/* presence binding for subscribe processing*/
 	presence_api_t pres;
 	bind_presence_t bind_presence;
@@ -394,6 +424,8 @@ static void destroy(void) {
 
 	free_all_udomains();
 	ul_destroy_locks();
+	subs_destroy_locks();
+	destroy_contacts_locks();
 
 	/* free callbacks list */
 	destroy_ulcb_list();
diff --git a/modules/ims_usrloc_scscf/ul_rpc.c b/modules/ims_usrloc_scscf/ul_rpc.c
index 9cd069e..b393254 100644
--- a/modules/ims_usrloc_scscf/ul_rpc.c
+++ b/modules/ims_usrloc_scscf/ul_rpc.c
@@ -32,146 +32,149 @@ static const char* ul_rpc_showimpu_doc[2] = {"Dump SCSCF IMPU information", 0 };
 static unsigned int contact_buflen = 0;
 static str contact_buf = {0,0};
 
-static void ul_rpc_show_impu(rpc_t* rpc, void* ctx)
-{
-	int i, j;
-	str impu;
-	int res;
-	udomain_t* domain;
-	struct impurecord* impu_rec;
-	ucontact_t* contact;
-	void *ah, *sh, *ch, *cdh, *sdh, *sph, *spi;
-	char numstr[21+16]; //enough for all numbers up to 64bits + longest length of field name (16)
-
-	if (rpc->scan(ctx, "S", &impu) < 1) {
-		rpc->fault(ctx, 400, "required IMPU argument");
-		return;
-	}
+static void ul_rpc_show_impu(rpc_t* rpc, void* ctx) {
+    int i, j;
+    str impu;
+    int res;
+    udomain_t* domain;
+    struct impurecord* impu_rec;
+    ucontact_t* contact;
+    void *ah, *sh, *ch, *cdh, *sdh, *sph, *spi;
+    char numstr[21 + 16]; //enough for all numbers up to 64bits + longest length of field name (16)
+
+    if (rpc->scan(ctx, "S", &impu) < 1) {
+	rpc->fault(ctx, 400, "required IMPU argument");
+	return;
+    }
+
+    LM_DBG("searching for impu <%.*s>\n", impu.len, impu.s);
+
+    res = get_udomain("location", &domain);
+    if (res != 0) {
+	LM_ERR("Failed to get domain\n");
+	return;
+    }
+
+    lock_udomain(domain, &impu);
+    res = get_impurecord(domain, &impu, &impu_rec);
+    if (res != 0) {
+	unlock_udomain(domain, &impu);
+	return;
+    }
 
-	LM_DBG("searching for impu <%.*s>\n", impu.len, impu.s);
+    //now print the data for this IMPU record
+    if (rpc->add(ctx, "{", &ah) < 0) {
+	rpc->fault(ctx, 500, "Internal error creating IMPU struct");
+	unlock_udomain(domain, &impu);
+	return;
+    }
+
+    if (rpc->struct_add(ah, "SsdSSSS",
+	    "impu", &impu,
+	    "state", get_impu_regstate_as_string(impu_rec->reg_state),
+	    "barring", impu_rec->barring,
+	    "ccf1", &impu_rec->ccf1,
+	    "ccf2", &impu_rec->ccf2,
+	    "ecf1", &impu_rec->ecf1,
+	    "ecf2", &impu_rec->ecf2
+	    ) < 0) {
+	rpc->fault(ctx, 500, "Internal error adding impu data");
+	unlock_udomain(domain, &impu);
+	return;
+    }
 
-	res = get_udomain("location", &domain);
-	if (res != 0) {
-		LM_ERR("Failed to get domain\n");
-		return;
+    if (rpc->struct_add(ah, "{", "subscription", &sh) < 0) {
+	rpc->fault(ctx, 500, "Internal error adding impu subscription data");
+	unlock_udomain(domain, &impu);
+	return;
+    }
+
+    ims_subscription* subscription = impu_rec->s;
+    lock_get(subscription->lock);
+    //add subscription data
+    if (rpc->struct_add(sh, "S{", "impi", &subscription->private_identity, "service profiles", &sph) < 0) {
+	rpc->fault(ctx, 500, "Internal error adding impu subscription data");
+	lock_release(subscription->lock);
+	unlock_udomain(domain, &impu);
+	return;
+    }
+
+    //add subscription detail information
+    for (i = 0; i < subscription->service_profiles_cnt; i++) {
+	sprintf(numstr, "%d", i + 1);
+	if (rpc->struct_add(sph, "{", numstr, &sdh) < 0) {
+	    rpc->fault(ctx, 500, "Internal error adding impu subscription detail data");
+	    lock_release(subscription->lock);
+	    unlock_udomain(domain, &impu);
+	    return;
 	}
-
-	lock_udomain(domain, &impu);
-	res = get_impurecord(domain, &impu, &impu_rec);
-	if (res != 0) {
-		unlock_udomain(domain, &impu);
-		return;
+	if (rpc->struct_add(sdh, "{", "impus", &spi) < 0) {
+	    rpc->fault(ctx, 500, "Internal error adding impu subscription data");
+	    lock_release(subscription->lock);
+	    unlock_udomain(domain, &impu);
+	    return;
 	}
 
-	//now print the data for this IMPU record
-	if (rpc->add(ctx, "{", &ah) < 0) {
-		rpc->fault(ctx, 500, "Internal error creating IMPU struct");
+	for (j = 0; j < subscription->service_profiles[i].public_identities_cnt; j++) {
+	    sprintf(numstr, "%d", j + 1);
+	    if (rpc->struct_add(spi, "S", numstr, &subscription->service_profiles[i].public_identities[j].public_identity) < 0) {
+		rpc->fault(ctx, 500, "Internal error adding impu subscription detail data");
+		lock_release(subscription->lock);
 		unlock_udomain(domain, &impu);
 		return;
+	    }
 	}
+    }
 
-	if (rpc->struct_add(ah, "SsdSSSS",
-			"impu", &impu,
-			"state", get_impu_regstate_as_string(impu_rec->reg_state),
-			"barring", impu_rec->barring,
-			"ccf1", &impu_rec->ccf1,
-			"ccf2", &impu_rec->ccf2,
-			"ecf1", &impu_rec->ecf1,
-			"ecf2", &impu_rec->ecf2
-			) < 0) {
-		rpc->fault(ctx, 500, "Internal error adding impu data");
-		unlock_udomain(domain, &impu);
-		return;
-	}
+    lock_release(subscription->lock);
 
-	if (rpc->struct_add(ah, "{", "subscription", &sh) < 0) {
-		rpc->fault(ctx, 500, "Internal error adding impu subscription data");
-		unlock_udomain(domain, &impu);
-		return;
-	}
+    //add contact data
+    if (rpc->struct_add(ah, "{", "contacts", &ch) < 0) {
+	rpc->fault(ctx, 500, "Internal error adding impu contact data");
+	unlock_udomain(domain, &impu);
+	return;
+    }
 
-	ims_subscription* subscription = impu_rec->s;
-	lock_get(subscription->lock);
-	//add subscription data
-	if (rpc->struct_add(sh, "S{", "impi", &subscription->private_identity, "service profiles", &sph) < 0) {
-		rpc->fault(ctx, 500, "Internal error adding impu subscription data");
-		lock_release(subscription->lock);
-		unlock_udomain(domain, &impu);
-		return;
-	}
+    i = 0;
 
-	//add subscription detail information
-	for (i=0; i<subscription->service_profiles_cnt; i++) {
-		sprintf(numstr, "%d", i+1);
-		if (rpc->struct_add(sph, "{", numstr, &sdh) < 0) {
-			rpc->fault(ctx, 500, "Internal error adding impu subscription detail data");
-			lock_release(subscription->lock);
-			unlock_udomain(domain, &impu);
-			return;
+    if (impu_rec->num_contacts > 0 && impu_rec->newcontacts[0]) {
+	while (i < MAX_CONTACTS_PER_IMPU && (contact = impu_rec->newcontacts[i++])) {
+	    //contact is not null terminated so we need to create a null terminated version
+	    if (!contact_buf.s || (contact_buf.len <= contact->c.len)) {
+		if (contact_buf.s && contact_buf.len <= contact->c.len) {
+		    pkg_free(contact_buf.s);
 		}
-		if (rpc->struct_add(sdh, "{", "impus", &spi) < 0) {
-				rpc->fault(ctx, 500, "Internal error adding impu subscription data");
-				lock_release(subscription->lock);
-				unlock_udomain(domain, &impu);
-				return;
+		contact_buflen = contact->c.len + 1;
+		contact_buf.s = (char*) pkg_malloc(contact_buflen);
+		if (!contact_buf.s) {
+		    LM_ERR("no more pkg memory");
+		    rpc->fault(ctx, 500, "Internal error adding impu contact header");
+		    unlock_udomain(domain, &impu);
+		    return;
 		}
-
-		for (j=0; j<subscription->service_profiles[i].public_identities_cnt; j++) {
-			sprintf(numstr, "%d", j+1);
-			if (rpc->struct_add(spi, "S", numstr, &subscription->service_profiles[i].public_identities[j].public_identity) < 0) {
-					rpc->fault(ctx, 500, "Internal error adding impu subscription detail data");
-					lock_release(subscription->lock);
-					unlock_udomain(domain, &impu);
-					return;
-			}
-		}
-	}
-
-	lock_release(subscription->lock);
-
-	//add contact data
-	if (rpc->struct_add(ah, "{", "contacts", &ch) < 0) {
+	    }
+	    memcpy(contact_buf.s, contact->c.s, contact->c.len);
+	    contact_buf.s[contact->c.len] = '\0';
+	    contact_buf.len = contact->c.len;
+
+	    LM_DBG("contact is %s\n", contact_buf.s);
+	    if (rpc->struct_add(ch, "{", contact_buf.s, &cdh) < 0) {
+		rpc->fault(ctx, 500, "Internal error adding impu contact header");
+		unlock_udomain(domain, &impu);
+		return;
+	    }
+	    if (rpc->struct_add(cdh, "dS",
+		    "expires", contact->expires - time(NULL),
+		    "client", &contact->user_agent) < 0) {
 		rpc->fault(ctx, 500, "Internal error adding impu contact data");
 		unlock_udomain(domain, &impu);
 		return;
+	    }
+	    contact = contact->next;
 	}
-	contact = impu_rec->contacts;
-	while (contact) {
-		//contact is not null terminated so we need to create a null terminated version
-		if (!contact_buf.s || (contact_buf.len <= contact->c.len)) {
-			if (contact_buf.s && contact_buf.len <= contact->c.len){
-				pkg_free(contact_buf.s);
-			}
-			contact_buflen = contact->c.len + 1;
-			contact_buf.s = (char*)pkg_malloc(contact_buflen);
-			if (!contact_buf.s) {
-				LM_ERR("no more pkg memory");
-				rpc->fault(ctx, 500, "Internal error adding impu contact header");
-				unlock_udomain(domain, &impu);
-				return;
-			}
-		}
-		memcpy(contact_buf.s, contact->c.s, contact->c.len);
-		contact_buf.s[contact->c.len] = '\0';
-		contact_buf.len = contact->c.len;
-
-		LM_DBG("contact is %s\n", contact_buf.s);
-		if (rpc->struct_add(ch, "{", contact_buf.s, &cdh) < 0) {
-			rpc->fault(ctx, 500, "Internal error adding impu contact header");
-			unlock_udomain(domain, &impu);
-			return;
-		}
-		if (rpc->struct_add(cdh, "dS",
-				"expires", contact->expires - time(NULL),
-				"client", &contact->user_agent) < 0) {
-			rpc->fault(ctx, 500, "Internal error adding impu contact data");
-			unlock_udomain(domain, &impu);
-			return;
-		}
-		contact = contact->next;
-	}
+    }
 
-	unlock_udomain(domain, &impu);
+    unlock_udomain(domain, &impu);
 
 }
 
diff --git a/modules/ims_usrloc_scscf/usrloc.c b/modules/ims_usrloc_scscf/usrloc.c
index 55fbd53..ae7518f 100644
--- a/modules/ims_usrloc_scscf/usrloc.c
+++ b/modules/ims_usrloc_scscf/usrloc.c
@@ -84,14 +84,21 @@ int bind_usrloc(usrloc_api_t* api) {
 	api->lock_udomain = lock_udomain;
 	api->unlock_udomain = unlock_udomain;
 
+	api->lock_contact_slot = lock_contact_slot;
+	api->unlock_contact_slot = unlock_contact_slot;
+	api->lock_contact_slot_i = lock_contact_slot_i;
+	api->unlock_contact_slot_i = unlock_contact_slot_i;	
 	api->get_all_ucontacts = get_all_ucontacts;
 	api->insert_ucontact = insert_ucontact;
 	api->delete_ucontact = delete_ucontact;
 	api->get_ucontact = get_ucontact;
+	api->release_ucontact = release_ucontact;
 	api->update_ucontact = update_ucontact;
+	api->expire_ucontact = expire_ucontact;
 	api->add_dialog_data_to_contact = add_dialog_data_to_contact;
 	api->remove_dialog_data_from_contact = remove_dialog_data_from_contact;
-
+	api->unlink_contact_from_impu = unlink_contact_from_impu;
+	api->link_contact_to_impu = link_contact_to_impu;
 	api->get_subscriber = get_subscriber;
 	api->add_subscriber = add_subscriber;
 	api->external_delete_subscriber = external_delete_subscriber;
@@ -101,7 +108,7 @@ int bind_usrloc(usrloc_api_t* api) {
 	
 	api->get_presentity_from_subscriber_dialog = get_presentity_from_subscriber_dialog;
         
-    api->register_ulcb = register_ulcb;
+	api->register_ulcb = register_ulcb;
 
 	//api->update_user_profile = update_user_profile;
 	api->nat_flag = nat_bflag;
diff --git a/modules/ims_usrloc_scscf/usrloc.h b/modules/ims_usrloc_scscf/usrloc.h
index 72a5ec2..104fd1c 100644
--- a/modules/ims_usrloc_scscf/usrloc.h
+++ b/modules/ims_usrloc_scscf/usrloc.h
@@ -54,6 +54,7 @@
 #include "../cdp/diameter_ims_code_avp.h"
 
 #define DEFAULT_DBG_FILE "/var/log/usrloc_debug"
+#define MAX_CONTACTS_PER_IMPU 100
 
 /* DB modes */
 #define NO_DB         0
@@ -99,16 +100,20 @@ typedef struct udomain udomain_t;
 typedef struct _subscriber_data {
 	int event;
 	int expires;
+	int version;
 	str* callid;
 	str* ftag;
 	str* ttag;
 	unsigned int local_cseq;
 	str* record_route;
 	str* sockinfo_str;
+	str* presentity_uri;
+	str *watcher_uri;
+	str* watcher_contact;
 } subscriber_data_t;
 
 typedef struct _reg_subscriber {
-    char event;
+    int event;
     time_t expires; /**< Time of expiration		 			*/
     int version; /**< Last version sent to this subs.	*/
 
@@ -136,6 +141,12 @@ typedef enum cstate {
     CS_DIRTY /*!< Update contact - not flushed yet */
 } cstate_t;
 
+typedef enum contact_state {
+    CONTACT_VALID,
+    CONTACT_EXPIRED,
+    CONTACT_DELETED
+} contact_state_t;
+
 /*! \brief Valid contact is a contact that either didn't expire yet or is permanent */
 #define VALID_CONTACT(c, t)   ((c->expires>t) || (c->expires==0))
 
@@ -282,16 +293,22 @@ typedef struct contact_dialog_data {
 
 /*! \brief Main structure for handling of registered Contact data */
 typedef struct ucontact {
-    str* domain; /*!< Pointer to domain name (NULL terminated) */
-    str* aor; /*!< Pointer to the AOR string in record structure*/
+    gen_lock_t *lock;           /**< we have to lock the contact as it is shared by many impu structs and has reference conting	*/
+    struct contact_hslot* slot; /*!< Collision slot in the hash table array we belong to */
+    unsigned int contact_hash; 			/*!< Hash over contact */
+    int ref_count;
+    contact_state_t state;
+    str domain; /*!< Pointer to domain name (NULL terminated) */
+    str aor; /*!< Pointer to the AOR string in record structure*/
     str c; /*!< Contact address */
+    param_t *params; /*!< Params header details> */
     str received; /*!< IP+port+protocol we received the REGISTER from */
     str path; /*!< Path header */
     time_t expires; /*!< Expires parameter */
     qvalue_t q; /*!< q parameter */
     str callid; /*!< Call-ID header field of registration */
     int cseq; /*!< CSeq value */
-    cstate_t state; /*!< State of the contact (\ref cstate) */
+//    cstate_t state; /*!< State of the contact (\ref cstate) */
     unsigned int flags; /*!< Various flags (NAT, ping type, etc) */
     unsigned int cflags; /*!< Custom contact flags (from script) */
     str user_agent; /*!< User-Agent header field */
@@ -320,6 +337,7 @@ typedef struct ucontact_info {
     time_t expires; /*!< Contact expires */
     qvalue_t q; /*!< Q-value */
     str* callid; /*!< call-ID */
+    param_t *params;
     int cseq; /*!< CSEQ number */
     unsigned int flags; /*!< message flags */
     unsigned int cflags; /*!< contact flags */
@@ -366,7 +384,8 @@ typedef struct impurecord {
     enum pi_reg_states reg_state;
     ims_subscription *s; 			/**< subscription to which it belongs 		*/
     str ccf1, ccf2, ecf1, ecf2; 	/**< charging functions						*/
-    ucontact_t* contacts; 			/*!< One or more contact fields */
+    ucontact_t* newcontacts[MAX_CONTACTS_PER_IMPU];
+    int num_contacts;
     reg_subscriber *shead, *stail; 	/**< list of subscribers attached			*/
     time_t expires; 				/*!< timer when this IMPU expires - currently only used for unreg IMPU */
     int send_sar_on_delete;			/* used to distinguish between explicit contact removal and contact expiry - SAR only sent on contact expiry*/
@@ -385,6 +404,11 @@ typedef struct impurecord_info {
     str *ccf1, *ccf2, *ecf1, *ecf2;
 } impurecord_info_t;
 
+typedef struct contact_list {
+    struct contact_hslot* slot;
+    int size;
+//    stat_var *contacts;        /*!< no of contacts in table */
+}contact_list_t;
 
 typedef int (*insert_impurecord_t)(struct udomain* _d, str* public_identity, int reg_state, int barring,
         ims_subscription** s, str* ccf1, str* ccf2, str* ecf1, str* ecf2,
@@ -396,14 +420,30 @@ typedef int (*delete_impurecord_t)(struct udomain* _d, str* _aor, struct impurec
 
 typedef int (*update_impurecord_t)(struct udomain* _d, str* public_identity, int reg_state, int send_sar_on_delete, int barring, int is_primary, ims_subscription** s, str* ccf1, str* ccf2, str* ecf1, str* ecf2, struct impurecord** _r);
 
+typedef void (*lock_contact_slot_t)(str* contact_uri);
+
+typedef void (*unlock_contact_slot_t)(str* contact_uri);
+
+typedef void (*lock_contact_slot_i_t)(int sl);
+
+typedef void (*unlock_contact_slot_i_t)(int sl);
+
 typedef int (*update_ucontact_t)(struct impurecord* _r, struct ucontact* _c, struct ucontact_info* _ci);
 
+typedef int (*expire_ucontact_t)(struct impurecord* _r, struct ucontact* _c);
+
+typedef int (*unlink_contact_from_impu_t)(struct impurecord* _r, struct ucontact* _c, int write_to_db);
+
+typedef int (*link_contact_to_impu_t)(struct impurecord* _r, struct ucontact* _c, int wirte_to_db);
+
 typedef int (*insert_ucontact_t)(struct impurecord* _r, str* _contact, struct ucontact_info* _ci, struct ucontact** _c);
 
-typedef int (*delete_ucontact_t)(struct impurecord* _r, struct ucontact* _c);
+typedef int (*delete_ucontact_t)(struct ucontact* _c);
 
 typedef int (*get_ucontact_t)(struct impurecord* _r, str* _c, str* _callid, str* _path, int _cseq, struct ucontact** _co);
 
+typedef void (*release_ucontact_t)(struct ucontact* _c);
+
 typedef int (*add_dialog_data_to_contact_t)(struct ucontact* _c, unsigned int h_entry, unsigned int h_id);
 
 typedef int (*remove_dialog_data_from_contact_t)(struct ucontact* _c, unsigned int h_entry, unsigned int h_id);
@@ -418,24 +458,15 @@ typedef int (*get_all_ucontacts_t)(void* buf, int len, unsigned int flags, unsig
 
 typedef int (*get_udomain_t)(const char* _n, udomain_t** _d);
 
-//typedef int (*update_subscriber_t)(udomain_t* _d, int event,int* expires, str *callid, str *ftag, str *ttag, unsigned int local_cseq, str *watcher_uri, str *watcher_contact, str *presentity_uri, str *record_route, str *sockinfo_str, reg_subscriber** reg_subscriber );
-
-typedef int (*update_subscriber_t)(impurecord_t* urec,
-        str *watcher_uri, str *watcher_contact,
-        int *expires, reg_subscriber** _reg_subscriber);
+typedef int (*update_subscriber_t)(impurecord_t* urec, reg_subscriber** _reg_subscriber,
+        int *expires, int *local_cseq, int *version);
 
 typedef void (*external_delete_subscriber_t)(reg_subscriber *s, udomain_t* _t, int lock_domain);
 
-//typedef int (*get_subscriber_t)(udomain_t* _d, impurecord_t* urec, str *watcher_contact, str *presentity_uri, int event, reg_subscriber** reg_subscriber);
 typedef int (*get_subscriber_t)(impurecord_t* urec, str *watcher_contact, str *presentity_uri, int event, reg_subscriber** reg_subscriber);
 
-//typedef int (*add_subscriber_t)(udomain_t* _d, impurecord_t* urec,
-//		str *watcher_uri, str *watcher_contact,
-//		subscriber_data_t* subscriber_data, reg_subscriber** _reg_subscriber);
-
 typedef int (*add_subscriber_t)(impurecord_t* urec,
-		str *watcher_uri, str *watcher_contact,
-		subscriber_data_t* subscriber_data, reg_subscriber** _reg_subscriber);
+		subscriber_data_t* subscriber_data, reg_subscriber** _reg_subscriber, int db_load);
 
 typedef int (*get_impus_from_subscription_as_string_t)(udomain_t* _d, impurecord_t* impu_rec, int barring, str** impus, int* num_impus);
 
@@ -457,11 +488,19 @@ typedef struct usrloc_api {
     get_impurecord_t get_impurecord;
     update_impurecord_t update_impurecord;
 
+    lock_contact_slot_t lock_contact_slot;
+    unlock_contact_slot_t unlock_contact_slot;
+    lock_contact_slot_i_t lock_contact_slot_i;
+    unlock_contact_slot_i_t unlock_contact_slot_i;
     insert_ucontact_t insert_ucontact;
     delete_ucontact_t delete_ucontact;
     get_ucontact_t get_ucontact;
+    release_ucontact_t release_ucontact;
     get_all_ucontacts_t get_all_ucontacts;
     update_ucontact_t update_ucontact;
+    expire_ucontact_t expire_ucontact;
+    unlink_contact_from_impu_t unlink_contact_from_impu;
+    link_contact_to_impu_t link_contact_to_impu;
     //update_user_profile_t update_user_profile;
     
     add_dialog_data_to_contact_t add_dialog_data_to_contact;
diff --git a/modules/ims_usrloc_scscf/usrloc_db.c b/modules/ims_usrloc_scscf/usrloc_db.c
index c25e89c..c639bd7 100644
--- a/modules/ims_usrloc_scscf/usrloc_db.c
+++ b/modules/ims_usrloc_scscf/usrloc_db.c
@@ -4,6 +4,9 @@
 #include "bin_utils.h"
 #include "udomain.h"
 #include "math.h"
+#include "subscribe.h"
+#include "../../lib/ims/useful_defs.h"
+#include "../../parser/parse_param.h"
 
 str id_col = str_init(ID_COL); /*!< Name of column containing ID (gen. auto_increment field */
 str impu_id_col = str_init(IMPU_ID_COL); /*!< Name of column containing impu ID in mapping table */
@@ -17,6 +20,7 @@ str ecf1_col = str_init(ECF1_COL); /*!< Name of column containing ecf1 */
 str ecf2_col = str_init(ECF2_COL); /*!< Name of column containing ecf2 */
 str ims_sub_data_col = str_init(IMS_SUB_COL); /*!< Name of column containing ims_subscription data */
 str contact_col = str_init(CONTACT_COL); /*!< Name of column containing contact addresses */
+str params_col = str_init(PARAMS_COL); /*!< Name of column containing contact addresses */
 str expires_col = str_init(EXPIRES_COL); /*!< Name of column containing expires values */
 str q_col = str_init(Q_COL); /*!< Name of column containing q values */
 str callid_col = str_init(CALLID_COL); /*!< Name of column containing callid string */
@@ -30,12 +34,48 @@ str sock_col = str_init(SOCK_COL); /*!< Name of column containing the received s
 str methods_col = str_init(METHODS_COL); /*!< Name of column containing the supported methods */
 str last_mod_col = str_init(LAST_MOD_COL); /*!< Name of column containing the last modified date */
 
-str id_column 			= { "id", 2 };
-str impu_table 			= { "impu", 4 };
-str contact_table 		= { "contact", 7 };
-str impu_contact_table 	= { "impu_contact", 12 };
+/*impu table*/
+str impu_table = str_init(IMPU_TABLE);
+
+/*contact table*/
+str contact_table = str_init(CONTACT_TABLE);
+
+/*impu contact table*/
+str impu_contact_table = str_init(IMPU_CONTACT_TABLE);
+
+/*subscriber table*/
+str subscriber_table = str_init(SUBSCRIBER_TABLE);
+str sub_event_col = str_init(SUB_EVENT_COL);
+str sub_expires_col = str_init(SUB_EXPIRES_COL);
+str sub_version_col = str_init(SUB_VERSION_COL);
+str sub_watcher_uri_col = str_init(SUB_WATCHER_URI_COL);
+str sub_watcher_contact_col = str_init(SUB_WATCHER_CONTACT_COL);
+str sub_presentity_uri_col = str_init(SUB_PRESENTITY_URI_COL);
+str sub_local_cseq_col = str_init(SUB_LOCAL_CSEQ_COL);
+str sub_call_id_col = str_init(SUB_CALL_ID_COL);
+str sub_from_tag_col = str_init(SUB_FROM_TAG_COL);
+str sub_to_tag_col = str_init(SUB_TO_TAG_COL);
+str sub_record_route_col = str_init(SUB_RECORD_ROUTE_COL);
+str sub_sockinfo_str_col = str_init(SUB_SOCKINFO_STR_COL);
+
+/*impu_subscriber table*/
+str impu_subscriber_table = str_init(IMPU_SUBSCRIBER_TABLE);
+str subscriber_id_col = str_init(SUBSCRIBER_ID_COL);
+
 str query_buffer 		= { 0, 0 };
-int query_buffer_len 	= 0;
+int query_buffer_len		= 0;
+
+char* impu_contact_insert_query = "INSERT INTO impu_contact (impu_id, contact_id) (SELECT I.id, C.id FROM impu I, contact C WHERE I.impu='%.*s' and C.contact='%.*s')";
+int impu_contact_insert_query_len;
+char* impu_contact_delete_query = "DELETE FROM impu_contact WHERE impu_id in (select impu.id from impu where impu.impu='%.*s') AND contact_id in (select contact.id from contact where contact.contact='%.*s')";
+int impu_contact_delete_query_len;
+
+char* impu_subscriber_insert_query = "INSERT INTO impu_subscriber (impu_id, subscriber_id) (SELECT I.id, S.id FROM impu I, subscriber S WHERE I.impu='%.*s' and S.event='%.*s' and S.watcher_contact='%.*s' and S.presentity_uri='%.*s')";
+int impu_subscriber_insert_query_len;
+char* impu_subscriber_delete_query = "DELETE FROM impu_subscriber WHERE impu_id in (select impu.id from impu where impu.impu='%.*s') AND subscriber_id in (select subscriber.id from subscriber where subscriber.event='%.*s' and subscriber.watcher_contact='%.*s' and subscriber.presentity_uri='%.*s')";
+int impu_subscriber_delete_query_len;
+
+
 
 extern db1_con_t* ul_dbh;
 extern db_func_t ul_dbf;
@@ -107,19 +147,23 @@ int db_insert_impurecord(struct udomain* _d, str* public_identity,
 	db_key_t key[8];
 	db_val_t val[8];
 	str bin_str;
+	
+	LM_DBG("DB: Inserting/Updating IMPU [%.*s]\n", public_identity->len, public_identity->s);
 
 	//serialise ims_subscription
-	if (!bin_alloc(&x, 256)) {
-		LM_DBG("unable to allocate buffer for binary serialisation\n");
-		return -1;
-	}
-	if (!bin_encode_ims_subscription(&x, (*s))) {
-		LM_DBG("Unable to serialise ims_subscription data\n");
-		bin_free(&x);
-		return -1;
+	if (s) {
+	    if (!bin_alloc(&x, 256)) {
+		    LM_DBG("unable to allocate buffer for binary serialisation\n");
+		    return -1;
+	    }
+	    if (!bin_encode_ims_subscription(&x, (*s))) {
+		    LM_DBG("Unable to serialise ims_subscription data\n");
+		    bin_free(&x);
+		    return -1;
+	    }
+	    bin_str.s = x.s;
+	    bin_str.len = x.len;
 	}
-	bin_str.s = x.s;
-	bin_str.len = x.len;
 
 	key[0] = &impu_col;
 	key[1] = &barring_col;
@@ -167,8 +211,13 @@ int db_insert_impurecord(struct udomain* _d, str* public_identity,
 	}
 	key[i] = &ims_sub_data_col;
 	val[i].type = DB1_BLOB;
-	val[i].nul = 0;
-	val[i].val.blob_val = bin_str;
+	if (s) {
+	    val[i].nul = 0;
+	    val[i].val.blob_val = bin_str;
+	} else {
+	    val[i].nul = 1;
+	}
+	
 	i++;
 
 	if (ul_dbf.use_table(ul_dbh, &impu_table) != 0) {
@@ -181,7 +230,9 @@ int db_insert_impurecord(struct udomain* _d, str* public_identity,
 		bin_free(&x);
 		return -1;
 	}
-	bin_free(&x);
+	
+	if (s)
+	    bin_free(&x);
 
 	return 0;
 }
@@ -189,35 +240,66 @@ int db_insert_impurecord(struct udomain* _d, str* public_identity,
 int db_delete_impurecord(udomain_t* _d, struct impurecord* _r) {
 	db_key_t key[1];
 	db_val_t val[1];
+	
+	LM_DBG("DB: deleting IMPU [%.*s]\n", _r->public_identity.len, _r->public_identity.s);
 
 	key[0] = &impu_col;
 	val[0].type = DB1_STR;
 	val[0].nul = 0;
 	val[0].val.str_val = _r->public_identity;
 
-	ul_dbf.use_table(ul_dbh, &impu_table);
-	ul_dbf.delete(ul_dbh, key, 0, val, 1);
-
+	if (ul_dbf.use_table(ul_dbh, &impu_table) != 0) {
+		LM_ERR("Unable to use table [%.*s]\n", impu_table.len, impu_table.s);
+		return -1;
+	}
+	if (ul_dbf.delete(ul_dbh, key, 0, val, 1) != 0) {
+		LM_ERR("Unable to delete impu [%.*s] from DB\n", _r->public_identity.len, _r->public_identity.s);
+		return -1;
+	}
+	
 	return 0;
 }
 
-int db_insert_ucontact(impurecord_t* _r, ucontact_t* _c) {
-	db1_res_t* _rs;
-	int contact_id;
-	int impu_id;
-	db_key_t key[6];
-	db_val_t val[6];
-	db_key_t key_return[1];
-	db_val_t* ret_val;
+static int MAX_PARAMS_SIZE = 1000;
+static str param_name_and_nody = {"%.*s=%.*s;", 1};
+static str param_name_no_body = {"%.*s;", 1};
 
-	key_return[0] = &id_column;
+int db_insert_ucontact(impurecord_t* _r, ucontact_t* _c) {
+	
+	str param_buf, param_pad;
+	param_t * tmp;
+	char param_bufc[MAX_PARAMS_SIZE], param_padc[MAX_PARAMS_SIZE];
+	param_buf.s = param_bufc;
+	param_buf.len = 0;
+	param_pad.s = param_padc;
+	param_pad.len = 0;
+	
+	db_key_t key[7];
+	db_val_t val[7];
+	
+	LM_DBG("DB: inserting ucontact [%.*s]\n", _c->c.len, _c->c.s);
+	
+	tmp = _c->params;
+	while (tmp) {
+	    if(tmp->body.len > 0) {
+		sprintf(param_pad.s, param_name_and_nody.s, tmp->name.len, tmp->name.s, tmp->body.len, tmp->body.s);
+	    } else {
+		sprintf(param_pad.s, param_name_no_body.s, tmp->name.len, tmp->name.s);
+	    }
+	    param_pad.len = strlen(param_pad.s);
+	    STR_APPEND(param_buf, param_pad);
+	    tmp = tmp->next;
+	}
+	LM_DBG("Converted params to string to insert into db: [%.*s]\n", param_buf.len, param_buf.s);
+	
 
 	key[0] = &contact_col;
-	key[1] = &path_col;
-	key[2] = &user_agent_col;
-	key[3] = &received_col;
-	key[4] = &expires_col;
-	key[5] = &callid_col;
+	key[1] = &params_col;
+	key[2] = &path_col;
+	key[3] = &user_agent_col;
+	key[4] = &received_col;
+	key[5] = &expires_col;
+	key[6] = &callid_col;
 
 	val[0].type = DB1_STR;
 	val[0].nul = 0;
@@ -225,232 +307,182 @@ int db_insert_ucontact(impurecord_t* _r, ucontact_t* _c) {
 
 	val[1].type = DB1_STR;
 	val[1].nul = 0;
-	val[1].val.str_val = _c->path;
-
+	val[1].val.str_val = param_buf;
+	
 	val[2].type = DB1_STR;
 	val[2].nul = 0;
-	val[2].val.str_val = _c->user_agent;
+	val[2].val.str_val = _c->path;
 
 	val[3].type = DB1_STR;
 	val[3].nul = 0;
-	val[3].val.str_val = _c->received;
+	val[3].val.str_val = _c->user_agent;
 
-	val[4].type = DB1_DATETIME;
+	val[4].type = DB1_STR;
 	val[4].nul = 0;
-	val[4].val.time_val = _c->expires;
+	val[4].val.str_val = _c->received;
 
-	val[5].type = DB1_STR;
+	val[5].type = DB1_DATETIME;
 	val[5].nul = 0;
-	val[5].val.str_val = _c->callid;
+	val[5].val.time_val = _c->expires;
+
+	val[6].type = DB1_STR;
+	val[6].nul = 0;
+	val[6].val.str_val = _c->callid;
 
 	if (ul_dbf.use_table(ul_dbh, &contact_table) != 0) {
 		LM_ERR("Unable to use table [%.*s]\n", contact_table.len, contact_table.s);
 		return -1;
 	}
-	if (ul_dbf.insert_update(ul_dbh, key, val, 6) != 0) {
+	if (ul_dbf.insert_update(ul_dbh, key, val, 7) != 0) {
 		LM_ERR("Failed to insert/update contact record for [%.*s]\n", _c->c.len, _c->c.s);
 		return -1;
 	}
-	contact_id = ul_dbf.last_inserted_id(ul_dbh);
-	if (contact_id <= 0) {
-		/* search for the ID if the contact just entered */
-		if (ul_dbf.query(ul_dbh, key, 0, val, key_return, 1, 1, NULL, &_rs) != 0) {
-			LM_ERR("Unable to find contact [%.*s] in DB to complete IMPU-contact mapping\n", _c->c.len, _c->c.s);
-			ul_dbf.free_result(ul_dbh, _rs);
-			return -1;
-		}
 
-		if (RES_ROW_N(_rs) == 0) {
-			LM_DBG("Contact %.*s not found in DB\n",_c->c.len, _c->c.s);
-			ul_dbf.free_result(ul_dbh, _rs);
-			return -1;
-		}
-
-		if (RES_ROW_N(_rs) > 1) {
-			LM_WARN("more than one contact found in DB for contact [%.*s] - this should not happen... proceeding with first entry\n",
-				_c->c.len, _c->c.s);
-		}
+	return 0;
+}
 
-		ret_val = ROW_VALUES(RES_ROWS(_rs));
-		contact_id = ret_val[0].val.int_val;
-		ul_dbf.free_result(ul_dbh, _rs);
-	}
-	LM_DBG("contact ID is %d\n", contact_id);
+int db_delete_ucontact(ucontact_t* _c) {
+	db_key_t key[1];
+	db_val_t val[1];
 
-	/* search for ID of the associated IMPU */
-	key[0] = &impu_col;
-	val[0].nul = 0;
-	val[0].type = DB1_STR;
-	val[0].val.str_val = _r->public_identity;
+	LM_DBG("Deleting ucontact [%.*s]\n",_c->c.len, _c->c.s);
 
-	if (ul_dbf.use_table(ul_dbh, &impu_table) != 0) {
-		LM_ERR("Unable to use table [%.*s]\n", impu_table.len, impu_table.s);
-		return -1;
-	}
-	if (ul_dbf.query(ul_dbh, key, 0, val, key_return, 1, 1, NULL, &_rs) != 0) {
-		LM_ERR("Unable to find IMPU [%.*s] in DB to complete IMPU-contact mapping\n", _r->public_identity.len, _r->public_identity.s);
-		return -1;
-	}
-	if (RES_ROW_N(_rs) == 0) {
-		LM_DBG("IMPU %.*s not found in DB\n", _r->public_identity.len, _r->public_identity.s);
-		ul_dbf.free_result(ul_dbh, _rs);
+	/* get contact id from DB */
+	if (ul_dbf.use_table(ul_dbh, &contact_table) != 0) {
+		LM_ERR("Unable to use table [%.*s]\n", contact_table.len, contact_table.s);
 		return -1;
 	}
-
-	if (RES_ROW_N(_rs) > 1) {
-		LM_WARN("more than one IMPU found in DB for contact [%.*s] - this should not happen... proceeding with first entry\n",
-				_r->public_identity.len, _r->public_identity.s);
-	}
-	ret_val = ROW_VALUES(RES_ROWS(_rs));
-	impu_id = ret_val[0].val.int_val;
-
-	ul_dbf.free_result(ul_dbh, _rs);
-	LM_DBG("IMPU ID is %d\n", impu_id);
-
-	/* update mapping table between contact and IMPU */
-	key[0] = &impu_id_col;
-	key[1] = &contact_id_col;
+	key[0] = &contact_col;
+	val[0].type = DB1_STR;
 	val[0].nul = 0;
-	val[0].type = DB1_INT;
-	val[0].val.int_val = impu_id;
-	val[1].nul = 0;
-	val[1].type = DB1_INT;
-	val[1].val.int_val = contact_id;
-
-	if (ul_dbf.use_table(ul_dbh, &impu_contact_table) != 0) {
-		LM_ERR("Unable to use table [%.*s]\n", impu_table.len, impu_table.s);
-		return -1;
-	}
-
-	if (ul_dbf.insert_update(ul_dbh, key, val, 2) != 0) {
-		LM_ERR("Failed to insert/update impu-contact mapping record for contact [%.*s] and impu [%.*s]\n",
-				_c->c.len, _c->c.s,
-				_r->public_identity.len, _r->public_identity.s);
+	val[0].val.str_val = _c->c;
+	if (ul_dbf.delete(ul_dbh, key, 0, val, 1) != 0) {
+		LM_ERR("Unable to delete contact [%.*s] from DB\n", _c->c.len, _c->c.s);
 		return -1;
 	}
 
 	return 0;
 }
 
-int db_delete_ucontact(impurecord_t* _r, ucontact_t* _c) {
-	db_key_t key[2];
-	db_val_t val[2];
-	db_key_t key_return[1];
-	db_val_t* ret_val;
-	db1_res_t* _rs;
-	int impu_id, contact_id;
-
-	LM_DBG("Deleting contact binding [%.*s] on impu [%.*s]\n",
-			_c->c.len, _c->c.s,
-			_r->public_identity.len, _r->public_identity.s);
+int db_insert_subscriber(impurecord_t* _r, reg_subscriber* _reg_subscriber) {
+	int col_num = 12;
+	db_key_t key[col_num];
+	db_val_t val[col_num];
+	
+	LM_DBG("DB: inserting subscriber [%.*s]\n", _reg_subscriber->presentity_uri.len, _reg_subscriber->presentity_uri.s);
+	
+	key[0] = &sub_watcher_uri_col;
+	key[1] = &sub_watcher_contact_col;
+	key[2] = &sub_presentity_uri_col;
+	key[3] = &sub_event_col;
+	key[4] = &sub_expires_col;
+	key[5] = &sub_version_col;
+	key[6] = &sub_local_cseq_col;
+	key[7] = &sub_call_id_col;
+	key[8] = &sub_from_tag_col;
+	key[9] = &sub_to_tag_col;
+	key[10] = &sub_record_route_col;
+	key[11] = &sub_sockinfo_str_col;
 
-	/* get id of IMPU entry */
-	key[0] = &impu_col;
 	val[0].type = DB1_STR;
 	val[0].nul = 0;
-	val[0].val.str_val = _r->public_identity;
-	key_return[0] = &id_column;
+	val[0].val.str_val = _reg_subscriber->watcher_uri;
 
-	if (ul_dbf.use_table(ul_dbh, &impu_table) != 0) {
-		LM_ERR("Unable to use table [%.*s]\n", impu_table.len, impu_table.s);
-		return -1;
-	}
-	if (ul_dbf.query(ul_dbh, key, 0, val, key_return, 1, 1, NULL, &_rs) != 0) {
-		LM_ERR("Unable to find IMPU [%.*s] in DB to complete IMPU-contact mapping\n", _r->public_identity.len, _r->public_identity.s);
-		return -1;
-	}
-	if (RES_ROW_N(_rs) == 0) {
-		LM_DBG("IMPU %.*s not found in DB\n", _r->public_identity.len, _r->public_identity.s);
-		ul_dbf.free_result(ul_dbh, _rs);
-		return -1;
-	}
-	if (RES_ROW_N(_rs) > 1) {
-		LM_WARN("more than one IMPU found in DB for contact [%.*s] - this should not happen... proceeding with first entry\n",
-				_r->public_identity.len, _r->public_identity.s);
-	}
-	ret_val = ROW_VALUES(RES_ROWS(_rs));
-	impu_id = ret_val[0].val.int_val;
+	val[1].type = DB1_STR;
+	val[1].nul = 0;
+	val[1].val.str_val = _reg_subscriber->watcher_contact;
 
-	ul_dbf.free_result(ul_dbh, _rs);
-	LM_DBG("IMPU ID is %d\n", impu_id);
+	val[2].type = DB1_STR;
+	val[2].nul = 0;
+	val[2].val.str_val = _reg_subscriber->presentity_uri;
 
-	/* get contact id from DB */
-	if (ul_dbf.use_table(ul_dbh, &contact_table) != 0) {
-		LM_ERR("Unable to use table [%.*s]\n", contact_table.len, contact_table.s);
-		return -1;
-	}
-	key[0] = &contact_col;
-	val[0].type = DB1_STR;
-	val[0].nul = 0;
-	val[0].val.str_val = _c->c;
-	if (ul_dbf.query(ul_dbh, key, 0, val, key_return, 1, 1, NULL, &_rs) != 0) {
-		LM_ERR("Unable to find contact [%.*s] in DB to complete IMPU-contact mapping removal\n", _c->c.len, _c->c.s);
+	val[3].type = DB1_INT;
+	val[3].nul = 0;
+	val[3].val.int_val = _reg_subscriber->event;
+
+	val[4].type = DB1_DATETIME;
+	val[4].nul = 0;
+	val[4].val.time_val = _reg_subscriber->expires;
+
+	val[5].type = DB1_INT;
+	val[5].nul = 0;
+	val[5].val.int_val = _reg_subscriber->version;
+	
+	val[6].type = DB1_INT;
+	val[6].nul = 0;
+	val[6].val.int_val = _reg_subscriber->local_cseq;
+	
+	val[7].type = DB1_STR;
+	val[7].nul = 0;
+	val[7].val.str_val = _reg_subscriber->call_id;
+	
+	val[8].type = DB1_STR;
+	val[8].nul = 0;
+	val[8].val.str_val = _reg_subscriber->from_tag;
+	
+	val[9].type = DB1_STR;
+	val[9].nul = 0;
+	val[9].val.str_val = _reg_subscriber->to_tag;
+	
+	val[10].type = DB1_STR;
+	val[10].nul = 0;
+	val[10].val.str_val = _reg_subscriber->record_route;
+	
+	val[11].type = DB1_STR;
+	val[11].nul = 0;
+	val[11].val.str_val = _reg_subscriber->sockinfo_str;
+	
+	if (ul_dbf.use_table(ul_dbh, &subscriber_table) != 0) {
+		LM_ERR("Unable to use table [%.*s]\n", subscriber_table.len, subscriber_table.s);
 		return -1;
 	}
-	if (RES_ROW_N(_rs) == 0) {
-		LM_DBG("Contact %.*s not found in DB\n",_c->c.len, _c->c.s);
-		ul_dbf.free_result(ul_dbh, _rs);
+	if (ul_dbf.insert_update(ul_dbh, key, val, col_num) != 0) {
+		LM_ERR("Failed to insert/update subscriber record for [%.*s]\n", _reg_subscriber->presentity_uri.len, _reg_subscriber->presentity_uri.s);
 		return -1;
 	}
-	if (RES_ROW_N(_rs) > 1) {
-		LM_WARN("more than one contact found in DB for contact [%.*s] - this should not happen... proceeding with first entry\n",
-				_c->c.len, _c->c.s);
-	}
-	ret_val = ROW_VALUES(RES_ROWS(_rs));
-	contact_id = ret_val[0].val.int_val;
-	ul_dbf.free_result(ul_dbh, _rs);
-	LM_DBG("contact ID is %d\n", contact_id);
+	
+	return 0;
+}
 
-	LM_DBG("need to remove contact-impu mapping %d:%d\n", impu_id, contact_id);
 
-	/* update impu-contact mapping table */
-	if (ul_dbf.use_table(ul_dbh, &impu_contact_table) != 0) {
-		LM_ERR("Unable to use table [%.*s]\n", impu_contact_table.len, impu_contact_table.s);
+int db_delete_subscriber(impurecord_t* _r, reg_subscriber* _reg_subscriber) {
+	db_key_t key[3];
+	db_val_t val[3];
+	
+	LM_DBG("Deleting subscriber binding [%.*s] on impu [%.*s]\n",
+			_reg_subscriber->presentity_uri.len, _reg_subscriber->presentity_uri.s,
+			_r->public_identity.len, _r->public_identity.s);
+
+	/* get subscriber id from DB */
+	if (ul_dbf.use_table(ul_dbh, &subscriber_table) != 0) {
+		LM_ERR("Unable to use table [%.*s]\n", subscriber_table.len, subscriber_table.s);
 		return -1;
 	}
-	key[0] = &contact_id_col;
-	key[1] = &impu_id_col;
+	key[0] = &sub_event_col;
 	val[0].type = DB1_INT;
 	val[0].nul = 0;
-	val[0].val.int_val = contact_id;
-	val[1].type = DB1_INT;
+	val[0].val.int_val = _reg_subscriber->event;
+		
+	key[1] = &sub_watcher_contact_col;
+	val[1].type = DB1_STR;
 	val[1].nul = 0;
-	val[1].val.int_val = impu_id;
-
-	if (ul_dbf.delete(ul_dbh, key, 0, val, 2) != 0) {
-		LM_ERR("unable to remove impu-contact mapping from DB for contact [%.*s], impu [%.*s]  ..... continuing\n",
-				_c->c.len, _c->c.s,
-				_r->public_identity.len, _r->public_identity.s);
-	}
-
-	/* delete contact from contact table - IFF there are no more mappings for it to impus */
-	if (ul_dbf.query(ul_dbh, key, 0, val, key_return, 1, 1, NULL, &_rs) != 0) {
-		LM_WARN("error searching for impu-contact mappings in DB\n");
-	}
-	if (RES_ROW_N(_rs) > 0) {
-		ul_dbf.free_result(ul_dbh, _rs);
-		LM_DBG("impu-contact mappings still exist, not removing contact from DB\n");
-		return 0;
-	}
-	ul_dbf.free_result(ul_dbh, _rs);
-
-	key[0] = &contact_col;
-	val[0].type = DB1_STR;
-	val[0].nul = 0;
-	val[0].val.str_val = _c->c;
-
-	if (ul_dbf.use_table(ul_dbh, &contact_table) != 0) {
-		LM_ERR("Unable to use table [%.*s]\n", contact_table.len, contact_table.s);
+	val[1].val.str_val = _reg_subscriber->watcher_contact;
+	
+	key[2] = &sub_presentity_uri_col;
+	val[2].type = DB1_STR;
+	val[2].nul = 0;
+	val[2].val.str_val = _reg_subscriber->presentity_uri;
+	
+	if (ul_dbf.delete(ul_dbh, key, 0, val, 3) != 0) {
+		LM_ERR("Unable to delete subscriber [%.*s] from DB\n", _reg_subscriber->presentity_uri.len, _reg_subscriber->presentity_uri.s);
 		return -1;
 	}
-
-	if (ul_dbf.delete(ul_dbh, key, 0, val, 1) != 0) {
-		LM_ERR("unable to remove contact from DB [%.*s]\n", _c->c.len, _c->c.s);
-	}
-
+	
 	return 0;
+	
 }
 
+
 int inline int_to_str_len(int i) {
 	if (i < 0)
 		i = -i;
@@ -476,35 +508,48 @@ int inline int_to_str_len(int i) {
 }
 
 static inline int dbrow2contact(db_val_t* val, ucontact_info_t* ci) {
-	static str path, user_agent, callid;
+	static str path, user_agent, callid, params;
+	param_hooks_t hooks;
+	
+	// Set ci to 0:
+	memset( ci, 0, sizeof(ucontact_info_t));
 
-	/* path */
+	/* params */
 	if (!VAL_NULL(val + 1)) {
-		path.s = (char*)VAL_STRING(val + 1);
+		params.s = (char*)VAL_STRING(val + 1);
+		params.len = strlen(params.s);
+		if (parse_params(&params, CLASS_CONTACT, &hooks, &ci->params) < 0) {
+			LM_WARN("Error while parsing parameters: %.*s\n", params.len, params.s);
+		}
+	}
+	
+	/* path */
+	if (!VAL_NULL(val + 2)) {
+		path.s = (char*)VAL_STRING(val + 2);
 		path.len = strlen(path.s);
 	}
 	ci->path = &path;
 
 	/* user-agent */
-	if (!VAL_NULL(val + 2)) {
-		user_agent.s = (char*)VAL_STRING(val + 2);
+	if (!VAL_NULL(val + 3)) {
+		user_agent.s = (char*)VAL_STRING(val + 3);
 		user_agent.len = strlen(user_agent.s);
 	}
 	ci->user_agent = &user_agent;
 
 	/* received */
-	if (!VAL_NULL(val + 3)) {
-		ci->received.s = (char*)VAL_STRING(val + 3);
+	if (!VAL_NULL(val + 4)) {
+		ci->received.s = (char*)VAL_STRING(val + 4);
 		ci->received.len = strlen(ci->received.s);
 	}
 
 	/* expires */
-	if (!VAL_NULL(val + 4)) {
-		ci->expires = VAL_TIME(val + 4);
+	if (!VAL_NULL(val + 5)) {
+		ci->expires = VAL_TIME(val + 5);
 	}
 	/* callid */
-	if (!VAL_NULL(val + 5)) {
-		callid.s = (char*) VAL_STRING(val + 5);
+	if (!VAL_NULL(val + 6)) {
+		callid.s = (char*) VAL_STRING(val + 6);
 		callid.len = strlen(callid.s);
 	}
 	ci->callid = &callid;
@@ -512,221 +557,561 @@ static inline int dbrow2contact(db_val_t* val, ucontact_info_t* ci) {
 	return 0;
 }
 
+static inline int dbrow2subscriber(db_val_t* val, subscriber_data_t* subscriber_data) {
+	static str presentity_uri, watcher_uri, watcher_contact, call_id, from_tag, to_tag, record_route, sockinfo_str;
+	
+	/*presentity uri*/
+	if (!VAL_NULL(val)) {
+	    presentity_uri.s = (char*) VAL_STRING(val);
+	    presentity_uri.len = strlen(presentity_uri.s);
+	}
+	subscriber_data->presentity_uri = &presentity_uri;
+	LM_DBG("presentity_uri: [%.*s]", subscriber_data->presentity_uri->len, subscriber_data->presentity_uri->s);
+	
+	/*watcher_uri*/
+	if (!VAL_NULL(val + 1)) {
+	    watcher_uri.s = (char*) VAL_STRING(val + 1);
+	    watcher_uri.len = strlen(watcher_uri.s);
+	}
+	subscriber_data->watcher_uri = &watcher_uri;
+	LM_DBG("watcher_uri: [%.*s]", subscriber_data->watcher_uri->len, subscriber_data->watcher_uri->s);
+	
+	/*watcher_contact*/
+	if (!VAL_NULL(val + 2)) {
+	    watcher_contact.s = (char*) VAL_STRING(val + 2);
+	    watcher_contact.len = strlen(watcher_contact.s);
+	}
+	subscriber_data->watcher_contact = &watcher_contact;
+	LM_DBG("watcher_contact: [%.*s]", subscriber_data->watcher_contact->len, subscriber_data->watcher_contact->s);
+	
+	/*event*/
+	if (!VAL_NULL(val + 3)) {
+	    subscriber_data->event = VAL_INT(val + 3);
+	}
+	LM_DBG("event: [%d]", subscriber_data->event);
+	
+	/* expires */
+	if (!VAL_NULL(val + 4)) {
+		subscriber_data->expires = VAL_TIME(val + 4);
+	}
+	LM_DBG("expires: [%d]", subscriber_data->expires);
+	
+	/*event*/
+	if (!VAL_NULL(val + 5)) {
+	    subscriber_data->version = VAL_INT(val + 5);
+	}
+	LM_DBG("version: [%d]", subscriber_data->version);
+	
+	/*local_cseq*/
+	if (!VAL_NULL(val + 6)) {
+	    subscriber_data->local_cseq = VAL_INT(val + 6);
+	}
+	LM_DBG("local_cseq: [%d]", subscriber_data->local_cseq);
+	
+	/* callid */
+	if (!VAL_NULL(val + 7)) {
+		call_id.s = (char*) VAL_STRING(val + 7);
+		call_id.len = strlen(call_id.s);
+	}
+	subscriber_data->callid = &call_id;
+	LM_DBG("callid: [%.*s]", subscriber_data->callid->len, subscriber_data->callid->s);
+	
+	/* ftag */
+	if (!VAL_NULL(val + 8)) {
+		from_tag.s = (char*) VAL_STRING(val + 8);
+		from_tag.len = strlen(from_tag.s);
+	}
+	subscriber_data->ftag = &from_tag;
+	LM_DBG("ftag: [%.*s]", subscriber_data->ftag->len, subscriber_data->ftag->s);
+	
+	/* ttag */
+	if (!VAL_NULL(val + 9)) {
+		to_tag.s = (char*) VAL_STRING(val + 9);
+		to_tag.len = strlen(to_tag.s);
+	}
+	subscriber_data->ttag = &to_tag;
+	LM_DBG("ttag: [%.*s]", subscriber_data->ttag->len, subscriber_data->ttag->s);
+	
+	/* record_route */
+	if (!VAL_NULL(val + 10)) {
+		record_route.s = (char*) VAL_STRING(val + 10);
+		record_route.len = strlen(record_route.s);
+	}
+	subscriber_data->record_route = &record_route;
+	LM_DBG("record_route: [%.*s]", subscriber_data->record_route->len, subscriber_data->record_route->s);
+	
+	/* sockinfo_str */
+	if (!VAL_NULL(val + 11)) {
+		sockinfo_str.s = (char*) VAL_STRING(val + 11);
+		sockinfo_str.len = strlen(sockinfo_str.s);
+	}
+	subscriber_data->sockinfo_str = &sockinfo_str;
+	LM_DBG("sockinfo_str: [%.*s]", subscriber_data->sockinfo_str->len, subscriber_data->sockinfo_str->s);
+	
+	return 0;
+}
+
 int preload_udomain(db1_con_t* _c, udomain_t* _d) {
-	db_key_t col[9];
-	db_row_t* row;
-	db_row_t* contact_row;
-	db1_res_t* rs;
-	db1_res_t* contact_rs;
-	db_val_t* vals;
-	db_val_t* contact_vals;
-	int barring = 0, reg_state = 0, impu_id, n, nn, i, j, len;
-	str query, impu, ccf1 = { 0, 0 }, ecf1 = { 0, 0 }, ccf2 = { 0, 0 }, ecf2 = {
-			0, 0 }, blob = { 0, 0 }, contact={0,0};
-	bin_data x;
-	ims_subscription* subscription = 0;
-	impurecord_t* impurecord;
-	int impu_id_len;
-	ucontact_t* c;
-	ucontact_info_t contact_data;
-
-	/*
-	 * the two queries - get the IMPUs, then get associated contacts for each IMPU:
-	 * SELECT impu.impu,impu.barring,impu.reg_state,impu.ccf1,impu.ccf2,impu.ecf1,impu.ecf2,impu.ims_subscription_data FROM impu;
-	 * SELECT c.contact,c.path,c.user_agent,c.received,c.expires FROM impu_contact m LEFT JOIN contact c ON c.id=m.contact_id WHERE m.impu_id=20;
-	 */
-
-	char *p =
-			"SELECT c.contact,c.path,c.user_agent,c.received,c.expires,c.callid FROM impu_contact m LEFT JOIN contact c ON c.id=m.contact_id WHERE m.impu_id=";
-
-	query.s = p;
-	query.len = strlen(query.s);
-
-	col[0] = &impu_col;
-	col[1] = &barring_col;
-	col[2] = &reg_state_col;
-	col[3] = &ccf1_col;
-	col[4] = &ecf1_col;
-	col[5] = &ccf2_col;
-	col[6] = &ecf2_col;
-	col[7] = &ims_sub_data_col;
-	col[8] = &id_col;
-
-	if (ul_dbf.use_table(_c, &impu_table) != 0) {
-		LM_ERR("SQL use table failed\n");
-		return -1;
+    db_key_t col[9];
+    db_row_t* row;
+    db_row_t* contact_row;
+    db_row_t* subscriber_row;
+    db1_res_t* rs;
+    db1_res_t* contact_rs;
+    db1_res_t* subscriber_rs;
+    db_val_t* vals;
+    db_val_t* contact_vals;
+    db_val_t* subscriber_vals;
+    int barring = 0, reg_state = 0, impu_id, n, nn, i, j, len;
+    str query_contact, query_subscriber, impu, ccf1 = {0, 0}, ecf1 = {0, 0}, ccf2 = {0, 0}, ecf2 = {
+	0, 0
+    }, blob = {0, 0}, contact = {0, 0}, presentity_uri = {0, 0};
+    bin_data x;
+    ims_subscription* subscription = 0;
+    impurecord_t* impurecord;
+    int impu_id_len;
+    ucontact_t* c;
+    ucontact_info_t contact_data;
+    subscriber_data_t subscriber_data;
+    reg_subscriber *reg_subscriber;
+
+    /*
+     * the two queries - get the IMPUs, then get associated contacts for each IMPU:
+     * SELECT impu.impu,impu.barring,impu.reg_state,impu.ccf1,impu.ccf2,impu.ecf1,impu.ecf2,impu.ims_subscription_data FROM impu;
+     * SELECT c.contact,c.path,c.user_agent,c.received,c.expires FROM impu_contact m LEFT JOIN contact c ON c.id=m.contact_id WHERE m.impu_id=20;
+     */
+
+    char *p_contact =
+	    "SELECT c.contact,c.params,c.path,c.user_agent,c.received,c.expires,c.callid FROM impu_contact m LEFT JOIN contact c ON c.id=m.contact_id WHERE m.impu_id=";
+
+    char *p_subscriber =
+	    "SELECT s.presentity_uri,s.watcher_uri,s.watcher_contact,s.event,s.expires,s.version,s.local_cseq,s.call_id,s.from_tag,"
+	    "s.to_tag,s.record_route,s.sockinfo_str FROM impu_subscriber m LEFT JOIN subscriber s ON s.id=m.subscriber_id WHERE m.impu_id=";
+
+    query_contact.s = p_contact;
+    query_contact.len = strlen(query_contact.s);
+
+    query_subscriber.s = p_subscriber;
+    query_subscriber.len = strlen(query_subscriber.s);
+
+
+    col[0] = &impu_col;
+    col[1] = &barring_col;
+    col[2] = &reg_state_col;
+    col[3] = &ccf1_col;
+    col[4] = &ecf1_col;
+    col[5] = &ccf2_col;
+    col[6] = &ecf2_col;
+    col[7] = &ims_sub_data_col;
+    col[8] = &id_col;
+
+    if (ul_dbf.use_table(_c, &impu_table) != 0) {
+	LM_ERR("SQL use table failed\n");
+	return -1;
+    }
+    if (ul_dbf.query(_c, NULL, 0, NULL, col, 0, 9, NULL, &rs) != 0) {
+	LM_ERR("Unable to query DB to preload S-CSCF usrloc\n");
+	return -1;
+    }
+
+    if (RES_ROW_N(rs) == 0) {
+	LM_DBG("table is empty\n");
+	ul_dbf.free_result(_c, rs);
+	return 0;
+    }
+
+    LM_DBG("preloading S-CSCF usrloc...\n");
+    LM_DBG("%d rows returned in preload\n", RES_ROW_N(rs));
+
+    n = 0;
+    do {
+	n++;
+	LM_DBG("loading S-CSCF usrloc records - cycle [%d]\n", n);
+	for (i = 0; i < RES_ROW_N(rs); i++) {
+	    impu_id = -1;
+
+	    row = RES_ROWS(rs) + i;
+	    LM_DBG("Fetching IMPU row %d\n", i + 1);
+	    vals = ROW_VALUES(row);
+
+	    impu.s = (char*) VAL_STRING(vals);
+	    if (VAL_NULL(vals) || !impu.s || !impu.s[0]) {
+		impu.len = 0;
+		impu.s = 0;
+	    } else {
+		impu.len = strlen(impu.s);
+	    }
+	    LM_DBG("IMPU from DB is [%.*s]\n", impu.len, impu.s);
+	    if (!VAL_NULL(vals + 1)) {
+		barring = VAL_INT(vals + 1);
+	    }
+	    if (!VAL_NULL(vals + 2)) {
+		reg_state = VAL_INT(vals + 2);
+	    }
+	    if (!VAL_NULL(vals + 3)) {
+		ccf1.s = (char*) VAL_STRING(vals + 3);
+		ccf1.len = strlen(ccf1.s);
+	    }
+	    LM_DBG("CCF1 from DB is [%.*s]\n", ccf1.len, ccf1.s);
+	    if (!VAL_NULL(vals + 4)) {
+		ecf1.s = (char*) VAL_STRING(vals + 3);
+		ecf1.len = strlen(ecf1.s);
+	    }
+	    LM_DBG("ECF1 from DB is [%.*s]\n", ecf1.len, ecf1.s);
+	    if (!VAL_NULL(vals + 5)) {
+		ccf2.s = (char*) VAL_STRING(vals + 5);
+		ccf2.len = strlen(ccf2.s);
+	    }
+	    LM_DBG("CCF2 from DB is [%.*s]\n", ccf2.len, ccf2.s);
+	    if (!VAL_NULL(vals + 6)) {
+		ecf2.s = (char*) VAL_STRING(vals + 6);
+		ecf2.len = strlen(ecf2.s);
+	    }
+	    LM_DBG("ECF2 from DB is [%.*s]\n", ecf2.len, ecf2.s);
+
+	    if (!VAL_NULL(vals + 7)) {
+		blob = VAL_BLOB(vals + 7);
+		bin_alloc(&x, blob.len);
+		memcpy(x.s, blob.s, blob.len);
+		x.len = blob.len;
+		x.max = 0;
+		subscription = bin_decode_ims_subscription(&x);
+		bin_free(&x);
+	    }
+	    if (!VAL_NULL(vals + 8)) {
+		impu_id = VAL_INT(vals + 8);
+	    }
+
+	    /* insert impu into memory */
+	    lock_udomain(_d, &impu);
+	    if (get_impurecord(_d, &impu, &impurecord) != 0) {
+		if (mem_insert_impurecord(_d, &impu, reg_state, barring,
+			&subscription, &ccf1, &ccf2, &ecf1, &ecf2, &impurecord)
+			!= 0) {
+		    LM_ERR("Unable to insert IMPU into memory [%.*s]\n", impu.len, impu.s);
+		}
+	    }
+
+	    /* add contacts */
+	    if (impu_id < 0) {
+		LM_ERR("impu_id has not been set [%.*s] - we cannot read contacts or subscribers from DB....aborting preload\n", impu.len, impu.s);
+		//TODO: check frees
+		unlock_udomain(_d, &impu);
+		continue;
+	    }
+	    impu_id_len = int_to_str_len(impu_id);
+	    len = query_contact.len + impu_id_len + 1/*nul*/;
+	    if (!query_buffer_len || query_buffer_len < len) {
+		if (query_buffer.s) {
+		    pkg_free(query_buffer.s);
+		}
+		query_buffer.s = (char*) pkg_malloc(len);
+		if (!query_buffer.s) {
+		    LM_ERR("mo more pkg mem\n");
+		    //TODO: check free
+		    unlock_udomain(_d, &impu);
+		    return -1;
+		}
+		query_buffer_len = len;
+	    }
+	    memcpy(query_buffer.s, query_contact.s, query_contact.len);
+	    p_contact = query_buffer.s + query_contact.len;
+	    snprintf(p_contact, impu_id_len + 1, "%d", impu_id);
+	    query_buffer.len = query_contact.len + impu_id_len;
+	    if (ul_dbf.raw_query(_c, &query_buffer, &contact_rs) != 0) {
+		LM_ERR("Unable to query DB for contacts associated with impu [%.*s]\n",
+			impu.len, impu.s);
+		ul_dbf.free_result(_c, contact_rs);
+	    } else {
+		if (RES_ROW_N(contact_rs) == 0) {
+		    LM_DBG("no contacts associated with impu [%.*s]\n", impu.len, impu.s);
+		    ul_dbf.free_result(_c, contact_rs);
+		} else {
+		    nn = 0;
+		    do {
+			nn++;
+			LM_DBG("loading S-CSCF contact - cycle [%d]\n", nn);
+			for (j = 0; j < RES_ROW_N(contact_rs); j++) {
+			    contact_row = RES_ROWS(contact_rs) + j;
+			    contact_vals = ROW_VALUES(contact_row);
+
+			    if (!VAL_NULL(contact_vals)) {
+				contact.s = (char*) VAL_STRING(contact_vals);
+				contact.len = strlen(contact.s);
+			    }
+			    if (dbrow2contact(contact_vals, &contact_data) != 0) {
+				LM_ERR("unable to convert contact row from DB into valid data... moving on\n");
+				continue;
+			    }
+
+			    if (get_ucontact(impurecord, &contact, contact_data.callid, contact_data.path, contact_data.cseq, &c) != 0) {
+				LM_DBG("Contact doesn't exist yet, creating new one [%.*s]\n", contact.len, contact.s);
+				if ((c = mem_insert_ucontact(impurecord, &contact, &contact_data)) == 0) {
+				    LM_ERR("Unable to insert contact [%.*s] for IMPU [%.*s] into memory... continuing...\n",
+					    contact.len, contact.s,
+					    impu.len, impu.s);
+				    continue;
+				}
+			    }
+			    link_contact_to_impu(impurecord, c, 0);
+			    release_ucontact(c);
+			}
+			if (DB_CAPABILITY(ul_dbf, DB_CAP_FETCH)) {
+			    if (ul_dbf.fetch_result(_c, &contact_rs, ul_fetch_rows) < 0) {
+				LM_ERR("fetching rows failed\n");
+				ul_dbf.free_result(_c, contact_rs);
+				unlock_udomain(_d, &impu);
+				return -1;
+			    }
+			} else {
+			    break;
+			}
+		    } while (RES_ROW_N(contact_rs) > 0);
+		    ul_dbf.free_result(_c, contact_rs);
+		}
+	    }
+
+	    /* add subscriber */
+	    impu_id_len = int_to_str_len(impu_id);
+	    len = query_subscriber.len + impu_id_len + 1/*nul*/;
+	    if (!query_buffer_len || query_buffer_len < len) {
+		if (query_buffer.s) {
+		    pkg_free(query_buffer.s);
+		}
+		query_buffer.s = (char*) pkg_malloc(len);
+		if (!query_buffer.s) {
+		    LM_ERR("mo more pkg mem\n");
+		    //TODO: check free
+		    unlock_udomain(_d, &impu);
+		    return -1;
+		}
+		query_buffer_len = len;
+	    }
+	    memcpy(query_buffer.s, query_subscriber.s, query_subscriber.len);
+	    p_subscriber = query_buffer.s + query_subscriber.len;
+	    snprintf(p_subscriber, impu_id_len + 1, "%d", impu_id);
+	    query_buffer.len = query_subscriber.len + impu_id_len;
+	    if (ul_dbf.raw_query(_c, &query_buffer, &subscriber_rs) != 0) {
+		LM_ERR("Unable to query DB for subscriber associated with impu [%.*s]\n",
+			impu.len, impu.s);
+		ul_dbf.free_result(_c, subscriber_rs);
+		unlock_udomain(_d, &impu);
+		continue;
+	    }
+	    if (RES_ROW_N(subscriber_rs) == 0) {
+		LM_DBG("no subscriber associated with impu [%.*s]\n", impu.len, impu.s);
+		ul_dbf.free_result(_c, subscriber_rs);
+		unlock_udomain(_d, &impu);
+		continue;
+	    }
+
+	    nn = 0;
+	    do {
+		nn++;
+		LM_DBG("loading S-CSCF subscriber - cycle [%d]\n", nn);
+		for (j = 0; j < RES_ROW_N(subscriber_rs); j++) {
+		    subscriber_row = RES_ROWS(subscriber_rs) + j;
+		    subscriber_vals = ROW_VALUES(subscriber_row);
+
+		    /*presentity uri*/
+		    if (!VAL_NULL(subscriber_vals)) {
+			presentity_uri.s = (char*) VAL_STRING(subscriber_vals);
+			presentity_uri.len = strlen(presentity_uri.s);
+		    }
+
+		    if (dbrow2subscriber(subscriber_vals, &subscriber_data) != 0) {
+			LM_ERR("unable to convert subscriber row from DB into valid subscriberdata... moving on\n");
+			continue;
+		    }
+
+		    if (add_subscriber(impurecord, &subscriber_data, &reg_subscriber, 1 /*db_load*/) != 0) {
+			LM_ERR("Unable to insert subscriber with presentity_uri [%.*s] for IMPU [%.*s] into memory... continuing...\n",
+				presentity_uri.len, presentity_uri.s,
+				impu.len, impu.s);
+		    }
+		}
+		if (DB_CAPABILITY(ul_dbf, DB_CAP_FETCH)) {
+		    if (ul_dbf.fetch_result(_c, &subscriber_rs, ul_fetch_rows) < 0) {
+			LM_ERR("fetching rows failed\n");
+			ul_dbf.free_result(_c, subscriber_rs);
+			unlock_udomain(_d, &impu);
+			return -1;
+		    }
+		} else {
+		    break;
+		}
+	    } while (RES_ROW_N(subscriber_rs) > 0);
+	    ul_dbf.free_result(_c, subscriber_rs);
+
+	    unlock_udomain(_d, &impu);
+
 	}
-	if (ul_dbf.query(_c, NULL, 0, NULL, col, 0, 9, NULL, &rs) != 0) {
-		LM_ERR("Unable to query DB to preload S-CSCF usrloc\n");
+
+	if (DB_CAPABILITY(ul_dbf, DB_CAP_FETCH)) {
+	    if (ul_dbf.fetch_result(_c, &rs, ul_fetch_rows) < 0) {
+		LM_ERR("fetching rows (1) failed\n");
+		ul_dbf.free_result(_c, rs);
 		return -1;
+	    }
+	} else {
+	    break;
 	}
+    } while (RES_ROW_N(rs) > 0);
 
-	if (RES_ROW_N(rs) == 0) {
-		LM_DBG("table is empty\n");
-		ul_dbf.free_result(_c, rs);
-		return 0;
+    ul_dbf.free_result(_c, rs);
+
+    LM_DBG("Completed preload_udomain");
+
+    return 0;
+}
+
+int db_link_contact_to_impu(impurecord_t* _r, ucontact_t* _c) {
+    int len;
+    db1_res_t* rs;
+
+    LM_DBG("DB: linking contact to IMPU\n");
+
+    len = strlen(impu_contact_insert_query) + _r->public_identity.len + _c->c.len + 1;
+
+    if (!query_buffer_len || query_buffer_len < len) {
+	if (query_buffer.s) {
+	    pkg_free(query_buffer.s);
+	}
+	query_buffer.s = (char*) pkg_malloc(len);
+	if (!query_buffer.s) {
+	    LM_ERR("no more pkg mem\n");
+	    return -1;
 	}
+	query_buffer_len = len;
+	
+    }
+
+    snprintf(query_buffer.s, query_buffer_len, impu_contact_insert_query, _r->public_identity.len, _r->public_identity.s, _c->c.len, _c->c.s);
+    query_buffer.len = strlen(query_buffer.s);//len;
+
+    LM_DBG("QUERY IS [%.*s] and len is %d\n", query_buffer.len, query_buffer.s, query_buffer.len);
+    if (ul_dbf.raw_query(ul_dbh, &query_buffer, &rs) != 0) {
+	LM_ERR("Unable to link impu-contact in DB - impu [%.*s], contact [%.*s]\n", _r->public_identity.len, _r->public_identity.s, _c->c.len, _c->c.s);
+	return -1;
+    }
+    ul_dbf.free_result(ul_dbh, rs);
+    LM_DBG("Query success\n");
+
+    return 0;
+}
 
-	LM_DBG("preloading S-CSCF usrloc...\n");
-	LM_DBG("%d rows returned in preload\n", RES_ROW_N(rs));
+int db_unlink_contact_from_impu(impurecord_t* _r, ucontact_t* _c) {
+    int len;
+    db1_res_t* rs;
 
-	n = 0;
-	do {
-		LM_DBG("loading S-CSCF usrloc records - cycle [%d]\n", ++n);
-		for (i = 0; i < RES_ROW_N(rs); i++) {
-			impu_id = -1;
+    LM_DBG("DB: un-linking contact to IMPU\n");
 
-			row = RES_ROWS(rs) + i;
-			LM_DBG("Fetching IMPU row %d\n", i+1);
-			vals = ROW_VALUES(row);
+    len = strlen(impu_contact_delete_query) + _r->public_identity.len + _c->c.len + 1;
 
-			impu.s = (char*) VAL_STRING(vals);
-			if (VAL_NULL(vals) || !impu.s || !impu.s[0]) {
-				impu.len = 0;
-				impu.s = 0;
-			} else {
-				impu.len = strlen(impu.s);
-			}
-			LM_DBG("IMPU from DB is [%.*s]\n", impu.len, impu.s);
-			if (!VAL_NULL(vals + 1)) {
-				barring = VAL_INT(vals + 1);
-			}
-			if (!VAL_NULL(vals + 2)) {
-				reg_state = VAL_INT(vals + 2);
-			}
-			if (!VAL_NULL(vals + 3)) {
-				ccf1.s = (char*) VAL_STRING(vals + 3);
-				ccf1.len = strlen(ccf1.s);
-			}
-			LM_DBG("CCF1 from DB is [%.*s]\n", ccf1.len, ccf1.s);
-			if (!VAL_NULL(vals + 4)) {
-				ecf1.s = (char*) VAL_STRING(vals + 3);
-				ecf1.len = strlen(ecf1.s);
-			}
-			LM_DBG("ECF1 from DB is [%.*s]\n", ecf1.len, ecf1.s);
-			if (!VAL_NULL(vals + 5)) {
-				ccf2.s = (char*) VAL_STRING(vals + 5);
-				ccf2.len = strlen(ccf2.s);
-			}
-			LM_DBG("CCF2 from DB is [%.*s]\n", ccf2.len, ccf2.s);
-			if (!VAL_NULL(vals + 6)) {
-				ecf2.s = (char*) VAL_STRING(vals + 6);
-				ecf2.len = strlen(ecf2.s);
-			}
-			LM_DBG("ECF2 from DB is [%.*s]\n", ecf2.len, ecf2.s);
-
-			if (!VAL_NULL(vals + 7)) {
-				blob = VAL_BLOB(vals + 7);
-				bin_alloc(&x, blob.len);
-				memcpy(x.s, blob.s, blob.len);
-				x.len = blob.len;
-				x.max = 0;
-				subscription = bin_decode_ims_subscription(&x);
-				bin_free(&x);
-			}
-			if (!VAL_NULL(vals + 8)) {
-				impu_id = VAL_INT(vals + 8);
-			}
+    if (!query_buffer_len || query_buffer_len < len) {
+	if (query_buffer.s) {
+	    pkg_free(query_buffer.s);
+	}
+	query_buffer.s = (char*) pkg_malloc(len);
+	if (!query_buffer.s) {
+	    LM_ERR("no more pkg mem\n");
+	    return -1;
+	}
+	query_buffer_len = len;
+	
+    }
 
-			/* insert impu into memory */
-			lock_udomain(_d, &impu);
-			if (mem_insert_impurecord(_d, &impu, reg_state, barring,
-					&subscription, &ccf1, &ccf2, &ecf1, &ecf2, &impurecord)
-					!= 0) {
-				LM_ERR("Unable to insert IMPU into memory [%.*s]\n", impu.len, impu.s);
-			}
+    snprintf(query_buffer.s, query_buffer_len, impu_contact_delete_query, _r->public_identity.len, _r->public_identity.s, _c->c.len, _c->c.s);
+    query_buffer.len = strlen(query_buffer.s);//len;
 
-			/* add contacts */
-			if (impu_id < 0) {
-				LM_ERR("impu_id has not been set [%.*s] - we cannot read contacts from DB....aborting preload\n", impu.len, impu.s);
-				//TODO: check frees
-				unlock_udomain(_d, &impu);
-				continue;
-			}
-			impu_id_len = int_to_str_len(impu_id);
-			len = query.len + impu_id_len + 1/*nul*/;
-			if (!query_buffer_len || query_buffer_len < len) {
-				if (query_buffer.s) {
-					pkg_free(query_buffer.s);
-				}
-				query_buffer.s = (char*) pkg_malloc(len);
-				if (!query_buffer.s) {
-					LM_ERR("mo more pkg mem\n");
-					//TODO: check free
-					unlock_udomain(_d, &impu);
-					return -1;
-				}
-				query_buffer_len = len;
-			}
-			memcpy(query_buffer.s, query.s, query.len);
-			p = query_buffer.s + query.len;
-			snprintf(p, impu_id_len + 1, "%d", impu_id);
-			query_buffer.len = query.len + impu_id_len;
-			if (ul_dbf.raw_query(_c, &query_buffer, &contact_rs) != 0) {
-				LM_ERR("Unable to query DB for contacts associated with impu [%.*s]\n",
-						impu.len, impu.s);
-				ul_dbf.free_result(_c, contact_rs);
-				unlock_udomain(_d, &impu);
-				continue;
-			}
-			if (RES_ROW_N(contact_rs) == 0) {
-				LM_DBG("no contacts associated with impu [%.*s]\n",impu.len, impu.s);
-				ul_dbf.free_result(_c, contact_rs);
-				unlock_udomain(_d, &impu);
-				continue;
-			}
+    if (ul_dbf.raw_query(ul_dbh, &query_buffer, &rs) != 0) {
+	LM_ERR("Unable to un-link impu-contact in DB - impu [%.*s], contact [%.*s]\n", _r->public_identity.len, _r->public_identity.s, _c->c.len, _c->c.s);
+	return -1;
+    }
+    ul_dbf.free_result(ul_dbh, rs);
+    LM_DBG("Delete query success\n");
 
-			nn = 0;
-			do {
-				LM_DBG("loading S-CSCF contact - cycle [%d]\n", ++nn);
-				for (j = 0; j < RES_ROW_N(contact_rs); j++) {
-					contact_row = RES_ROWS(contact_rs) + j;
-					contact_vals = ROW_VALUES(contact_row);
-
-					if (!VAL_NULL(contact_vals)) {
-						contact.s = (char*) VAL_STRING(contact_vals);
-						contact.len = strlen(contact.s);
-					}
-					if (dbrow2contact(contact_vals, &contact_data) != 0) {
-						LM_ERR("unable to convert contact row from DB into valid data... moving on\n");
-						unlock_udomain(_d, &impu);
-						continue;
-					}
-
-					if ((c = mem_insert_ucontact(impurecord, &contact, &contact_data)) == 0) {
-						LM_ERR("Unable to insert contact [%.*s] for IMPU [%.*s] into memory... continuing...\n",
-								contact.len, contact.s,
-								impu.len, impu.s);
-					}
-				}
-				if (DB_CAPABILITY(ul_dbf, DB_CAP_FETCH)) {
-					if (ul_dbf.fetch_result(_c, &contact_rs, ul_fetch_rows) < 0) {
-						LM_ERR("fetching rows failed\n");
-						ul_dbf.free_result(_c, contact_rs);
-						unlock_udomain(_d, &impu);
-						return -1;
-					}
-				} else {
-					break;
-				}
-			} while (RES_ROW_N(contact_rs) > 0);
+    return 0;
+}
 
-			unlock_udomain(_d, &impu);
-			ul_dbf.free_result(_c, contact_rs);
-		}
+int db_unlink_subscriber_from_impu(impurecord_t* _r, reg_subscriber* _reg_subscriber) {
+    int len;
+    db1_res_t* rs;
+    char event[11];
+    int event_len;
 
-		if (DB_CAPABILITY(ul_dbf, DB_CAP_FETCH)) {
-			if (ul_dbf.fetch_result(_c, &rs, ul_fetch_rows) < 0) {
-				LM_ERR("fetching rows (1) failed\n");
-				ul_dbf.free_result(_c, rs);
-				return -1;
-			}
-		} else {
-			break;
-		}
-	} while (RES_ROW_N(rs) > 0);
+    LM_DBG("DB: un-linking subscriber to IMPU\n");
+    
+    event_len = int_to_str_len(_reg_subscriber->event);
+    snprintf(event, event_len + 1, "%d", _reg_subscriber->event);
 
-	ul_dbf.free_result(_c, rs);
+    len = strlen(impu_subscriber_delete_query) + _r->public_identity.len + _reg_subscriber->watcher_contact.len + _reg_subscriber->presentity_uri.len + strlen(event) + 1;
 
-	return 0;
+    if (!query_buffer_len || query_buffer_len < len) {
+	if (query_buffer.s) {
+	    pkg_free(query_buffer.s);
+	}
+	query_buffer.s = (char*) pkg_malloc(len);
+	if (!query_buffer.s) {
+	    LM_ERR("no more pkg mem\n");
+	    return -1;
+	}
+	query_buffer_len = len;
+	
+    }
+
+    snprintf(query_buffer.s, query_buffer_len, impu_subscriber_delete_query, _r->public_identity.len, _r->public_identity.s, strlen(event), event, 
+	    _reg_subscriber->watcher_contact.len, _reg_subscriber->watcher_contact.s, _reg_subscriber->presentity_uri.len, _reg_subscriber->presentity_uri.s);
+    query_buffer.len = strlen(query_buffer.s);//len;
+
+    if (ul_dbf.raw_query(ul_dbh, &query_buffer, &rs) != 0) {
+	LM_ERR("Unable to un-link impu-subscriber in DB - impu [%.*s], subscriber [%.*s]\n", _r->public_identity.len, _r->public_identity.s, _reg_subscriber->presentity_uri.len, _reg_subscriber->presentity_uri.s);
+	return -1;
+    }
+    ul_dbf.free_result(ul_dbh, rs);
+    LM_DBG("Delete query success\n");
+
+    return 0;
 }
+
+int db_link_subscriber_to_impu(impurecord_t* _r, reg_subscriber* _reg_subscriber) {
+    int len;
+    db1_res_t* rs;
+    char event[11];
+    int event_len;
+    
+    LM_DBG("DB: linking subscriber to IMPU\n");
+    
+    event_len = int_to_str_len(_reg_subscriber->event);
+    snprintf(event, event_len + 1, "%d", _reg_subscriber->event);
+
+    len = strlen(impu_subscriber_insert_query) + _r->public_identity.len + _reg_subscriber->watcher_contact.len + _reg_subscriber->presentity_uri.len + strlen(event) + 1;
+
+    if (!query_buffer_len || query_buffer_len < len) {
+	if (query_buffer.s) {
+	    pkg_free(query_buffer.s);
+	}
+	query_buffer.s = (char*) pkg_malloc(len);
+	if (!query_buffer.s) {
+	    LM_ERR("no more pkg mem\n");
+	    return -1;
+	}
+	query_buffer_len = len;
+	
+    }
+
+    snprintf(query_buffer.s, query_buffer_len, impu_subscriber_insert_query, _r->public_identity.len, _r->public_identity.s, strlen(event), event, 
+	    _reg_subscriber->watcher_contact.len, _reg_subscriber->watcher_contact.s, _reg_subscriber->presentity_uri.len, _reg_subscriber->presentity_uri.s);
+    query_buffer.len = strlen(query_buffer.s);//len;
+
+    LM_DBG("QUERY IS [%.*s] and len is %d\n", query_buffer.len, query_buffer.s, query_buffer.len);
+    if (ul_dbf.raw_query(ul_dbh, &query_buffer, &rs) != 0) {
+	LM_ERR("Unable to link impu-subscriber in DB - impu [%.*s], subscriber [%.*s]\n", _r->public_identity.len, _r->public_identity.s, _reg_subscriber->presentity_uri.len, _reg_subscriber->presentity_uri.s);
+	return -1;
+    }
+    LM_DBG("Query success\n");
+    ul_dbf.free_result(ul_dbh, rs);
+
+    return 0;
+}
+
diff --git a/modules/ims_usrloc_scscf/usrloc_db.h b/modules/ims_usrloc_scscf/usrloc_db.h
index 40abe30..736d6fc 100644
--- a/modules/ims_usrloc_scscf/usrloc_db.h
+++ b/modules/ims_usrloc_scscf/usrloc_db.h
@@ -11,6 +11,7 @@ extern db_func_t ul_dbf;
 #define USER_COL       "username"
 #define DOMAIN_COL     "domain"
 #define CONTACT_COL    "contact"
+#define PARAMS_COL    "params"
 #define EXPIRES_COL    "expires"
 #define Q_COL          "q"
 #define CALLID_COL     "callid"
@@ -31,6 +32,29 @@ extern db_func_t ul_dbf;
 #define ECF2_COL       "ecf2"
 #define IMS_SUB_COL    "ims_subscription_data"
 
+#define IMPU_TABLE  "impu"
+#define CONTACT_TABLE  "contact"
+#define IMPU_CONTACT_TABLE  "impu_contact"
+
+/*subscriber table*/
+#define SUBSCRIBER_TABLE "subscriber"
+#define SUB_EVENT_COL "event"
+#define SUB_EXPIRES_COL "expires"
+#define SUB_VERSION_COL "version"
+#define SUB_WATCHER_URI_COL "watcher_uri"
+#define SUB_WATCHER_CONTACT_COL "watcher_contact"
+#define SUB_PRESENTITY_URI_COL "presentity_uri"
+#define SUB_LOCAL_CSEQ_COL "local_cseq"
+#define SUB_CALL_ID_COL "call_id"
+#define SUB_FROM_TAG_COL "from_tag"
+#define SUB_TO_TAG_COL "to_tag"
+#define SUB_RECORD_ROUTE_COL "record_route"
+#define SUB_SOCKINFO_STR_COL "sockinfo_str"
+
+/*impu subscriber table*/
+#define IMPU_SUBSCRIBER_TABLE "impu_subscriber"
+#define SUBSCRIBER_ID_COL "subscriber_id"
+
 int init_db(const str *db_url, int db_update_period, int fetch_num_rows);
 int connect_db(const str *db_url);
 void destroy_db();
@@ -41,7 +65,15 @@ int db_insert_impurecord(struct udomain* _d, str* public_identity, int reg_state
 		struct impurecord** _r);
 int db_delete_impurecord(udomain_t* _d, struct impurecord* _r);
 int db_insert_ucontact(impurecord_t* _r, ucontact_t* _c);
-int db_delete_ucontact(impurecord_t* _r, ucontact_t* _c);
+int db_update_ucontact(impurecord_t* _r, ucontact_t* _c);
+int db_delete_ucontact(ucontact_t* _c);
+int db_link_contact_to_impu(impurecord_t* _r, ucontact_t* _c);
+int db_unlink_contact_from_impu(impurecord_t* _r, ucontact_t* _c);
+int db_insert_subscriber(impurecord_t* _r, reg_subscriber* _reg_subscriber);
+int db_delete_subscriber(impurecord_t* _r, reg_subscriber* _reg_subscriber);
+
+int db_unlink_subscriber_from_impu(impurecord_t* _r, reg_subscriber* _reg_subscriber);
+int db_link_subscriber_to_impu(impurecord_t* _r, reg_subscriber* _reg_subscriber);
 
 int preload_udomain(db1_con_t* _c, udomain_t* _d);
 
diff --git a/modules/ipops/README b/modules/ipops/README
index 982db00..b213b03 100644
--- a/modules/ipops/README
+++ b/modules/ipops/README
@@ -39,6 +39,7 @@ I
               4.11. dns_sys_match_ip(hostname, ipaddr)
               4.12. dns_int_match_ip(hostname, ipaddr)
               4.13. dns_query(hostname, pvid)
+              4.14. srv_query(srvcname, pvid)
 
    List of Examples
 
@@ -55,6 +56,7 @@ I
    1.11. dns_sys_match_ip usage
    1.12. dns_int_match_ip usage
    1.13. dns_query usage
+   1.14. srv_query usage
 
 Chapter 1. Admin Guide
 
@@ -82,6 +84,7 @@ Chapter 1. Admin Guide
         4.11. dns_sys_match_ip(hostname, ipaddr)
         4.12. dns_int_match_ip(hostname, ipaddr)
         4.13. dns_query(hostname, pvid)
+        4.14. srv_query(srvcname, pvid)
 
 1. Overview
 
@@ -136,6 +139,7 @@ Chapter 1. Admin Guide
    4.11. dns_sys_match_ip(hostname, ipaddr)
    4.12. dns_int_match_ip(hostname, ipaddr)
    4.13. dns_query(hostname, pvid)
+   4.14. srv_query(srvcname, pvid)
 
 4.1. is_ip (ip)
 
@@ -416,3 +420,44 @@ if(dns_query("test.com", "xyz"))
     }
 }
 ...
+
+4.14. srv_query(srvcname, pvid)
+
+   Queries DNS SRV records to resolve a service/protocol name into a list
+   of priorities, weights, ports, and targets sorted by priority and
+   weight as outlined in RFC 2782.
+
+   Parameters:
+     * srvcname - string or pseudo-variable containing the
+       service/protocol. For example, "_sip._tcp.example.com".
+     * pvid - container id for script variable.
+
+   Output:
+
+   Returns a positive number indicating success or a negative number when
+   an error is encountered. It can be used from ANY_ROUTE.
+
+   The $srvquery pseudo-variable (PV) is loaded with the results of the
+   query. Multiple queries can be stored in the PV using the pvid key.
+   Each query contains zero-indexed arrays sorted by priority and weight
+   that contain:
+     * count - number of records found
+     * port [index] - port number
+     * priority [index] - priority number as defined by RFC 2782
+     * target [index] - target host name
+     * weight [index] - weight number as defined by RFC 2782
+
+   Example 1.14. srv_query usage
+...
+if (srv_query ("_sip._udp.example.com", "udp") > 0) {
+  $var(cnt) = $srvquery(udp=>count);
+  $var(i) = 0;
+  while ($var(i) < $var(cnt)) {
+    xlog ("port[$var(i)] $srvquery(udp=>port[$var(i)])\n)";
+    xlog ("priority[$var(i)] $srvquery(udp=>priority[$var(i)])\n)";
+    xlog ("target[$var(i)] $srvquery(udp=>target[$var(i)])\n)";
+    xlog ("weight[$var(i)] $srvquery(udp=>weight[$var(i)])\n)";
+    $var(i) = $var(i) + 1;
+  }
+}
+...
diff --git a/modules/ipops/doc/ipops_admin.xml b/modules/ipops/doc/ipops_admin.xml
index bbf68cf..90c4168 100644
--- a/modules/ipops/doc/ipops_admin.xml
+++ b/modules/ipops/doc/ipops_admin.xml
@@ -680,6 +680,91 @@ if(dns_query("test.com", "xyz"))
 
     </section>
 
+    <section id="ipops.f.srv_query">
+      <title>
+        <function moreinfo="none">srv_query(srvcname, pvid)</function>
+      </title>
+
+      <para>
+Queries DNS SRV records to resolve a service/protocol name into a list of priorities, weights, ports, and targets sorted by priority and weight as outlined in <ulink url="http://tools.ietf.org/html/rfc2782">RFC 2782</ulink>.
+      </para>
+
+      <para>Parameters:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>
+			  <emphasis>srvcname</emphasis> - string or pseudo-variable containing the service/protocol. For example, "_sip._tcp.example.com".
+          </para>
+        </listitem>
+        <listitem>
+          <para>
+            <emphasis>pvid</emphasis> - container id for script variable.
+          </para>
+        </listitem>
+      </itemizedlist>
+
+      <para>Output:</para>
+
+      <para>
+        Returns a positive number indicating success or a negative number when an error is encountered. It can be used from ANY_ROUTE.
+      </para>
+
+      <para>
+        The $srvquery pseudo-variable (PV) is loaded with the results of the query. Multiple queries can be stored in the PV using the pvid key. Each query contains zero-indexed arrays sorted by priority and weight that contain:
+      </para>
+
+      <itemizedlist>
+        <listitem>
+          <para>
+            <emphasis>count</emphasis> - number of records found
+          </para>
+        </listitem>
+        <listitem>
+          <para>
+            <emphasis>port [index]</emphasis> - port number
+          </para>
+        </listitem>
+        <listitem>
+          <para>
+            <emphasis>priority [index]</emphasis> - priority number as defined by <ulink url="http://tools.ietf.org/html/rfc2782">RFC 2782</ulink>
+          </para>
+        </listitem>
+        <listitem>
+          <para>
+            <emphasis>target [index]</emphasis> - target host name
+          </para>
+        </listitem>
+        <listitem>
+          <para>
+            <emphasis>weight [index]</emphasis> - weight number as defined by <ulink url="http://tools.ietf.org/html/rfc2782">RFC 2782</ulink>
+          </para>
+        </listitem>
+      </itemizedlist>
+
+      <example>
+        <title>
+          <function>srv_query</function> usage
+        </title>
+        <programlisting format="linespecific">
+...
+if (srv_query ("_sip._udp.example.com", "udp") > 0) {
+  $var(cnt) = $srvquery(udp=>count);
+  $var(i) = 0;
+  while ($var(i) < $var(cnt)) {
+    xlog ("port[$var(i)] $srvquery(udp=>port[$var(i)])\n)";
+    xlog ("priority[$var(i)] $srvquery(udp=>priority[$var(i)])\n)";
+    xlog ("target[$var(i)] $srvquery(udp=>target[$var(i)])\n)";
+    xlog ("weight[$var(i)] $srvquery(udp=>weight[$var(i)])\n)";
+    $var(i) = $var(i) + 1;
+  }
+}
+...
+        </programlisting>
+      </example>
+
+    </section>
+
   </section>
  
 </chapter>
diff --git a/modules/ipops/ipops_mod.c b/modules/ipops/ipops_mod.c
index d2a7673..916a713 100644
--- a/modules/ipops/ipops_mod.c
+++ b/modules/ipops/ipops_mod.c
@@ -21,6 +21,7 @@
  *
  * History:
  * -------
+ *  2015-03-31: Added srv_query function (rboisvert)
  *  2011-07-29: Added a function to detect RFC1918 private IPv4 addresses (ibc)
  *  2011-04-27: Initial version (ibc)
  */
@@ -92,10 +93,13 @@ static int w_dns_sys_match_ip(sip_msg_t*, char*, char*);
 static int w_dns_int_match_ip(sip_msg_t*, char*, char*);
 
 static int w_dns_query(struct sip_msg* msg, char* str1, char* str2);
+static int w_srv_query(struct sip_msg* msg, char* str1, char* str2);
 
 static pv_export_t mod_pvs[] = {
 	{ {"dns", sizeof("dns")-1}, PVT_OTHER, pv_get_dns, 0,
 		pv_parse_dns_name, 0, 0, 0 },
+	{ {"srvquery", sizeof("srvquery")-1}, PVT_OTHER, pv_get_srv, 0,
+		pv_parse_srv_name, 0, 0, 0 },
 	{ {"HN", sizeof("HN")-1}, PVT_OTHER, pv_get_hn, 0,
 		pv_parse_hn_name, 0, 0, 0 },
 	{ {0, 0}, 0, 0, 0, 0, 0, 0, 0 }
@@ -106,34 +110,36 @@ static pv_export_t mod_pvs[] = {
  */
 static cmd_export_t cmds[] =
 {
-  { "is_ip", (cmd_function)w_is_ip, 1, fixup_spve_null, 0,
-  REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE },
-  { "is_pure_ip", (cmd_function)w_is_pure_ip, 1, fixup_spve_null, 0,
-  REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE },
-  { "is_ipv4", (cmd_function)w_is_ipv4, 1, fixup_spve_null, 0,
-  REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE },
-  { "is_ipv6", (cmd_function)w_is_ipv6, 1, fixup_spve_null, 0,
-  REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE },
-  { "is_ipv6_reference", (cmd_function)w_is_ipv6_reference, 1, fixup_spve_null, 0,
-  REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE },
-  { "ip_type", (cmd_function)w_ip_type, 1, fixup_spve_null, 0,
-  REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE },
-  { "compare_ips", (cmd_function)w_compare_ips, 2, fixup_spve_spve, 0,
-  REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE },
-  { "compare_pure_ips", (cmd_function)w_compare_pure_ips, 2, fixup_spve_spve, 0,
-  REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE },
-  { "is_ip_rfc1918", (cmd_function)w_is_ip_rfc1918, 1, fixup_spve_null, 0,
-  REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE },
-  { "is_in_subnet", (cmd_function)w_ip_is_in_subnet, 2, fixup_spve_spve, 0,
-  REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE },
-  { "dns_sys_match_ip", (cmd_function)w_dns_sys_match_ip, 2, fixup_spve_spve, 0,
-  ANY_ROUTE },
-  { "dns_int_match_ip", (cmd_function)w_dns_int_match_ip, 2, fixup_spve_spve, 0,
-  ANY_ROUTE },
-  { "dns_query", (cmd_function)w_dns_query, 2, fixup_spve_spve, 0,
-  ANY_ROUTE },
-  { "bind_ipops", (cmd_function)bind_ipops, 0, 0, 0, 0},
-  { 0, 0, 0, 0, 0, 0 }
+	{ "is_ip", (cmd_function)w_is_ip, 1, fixup_spve_null, 0,
+		REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE },
+	{ "is_pure_ip", (cmd_function)w_is_pure_ip, 1, fixup_spve_null, 0,
+		REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE },
+	{ "is_ipv4", (cmd_function)w_is_ipv4, 1, fixup_spve_null, 0,
+		REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE },
+	{ "is_ipv6", (cmd_function)w_is_ipv6, 1, fixup_spve_null, 0,
+		REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE },
+	{ "is_ipv6_reference", (cmd_function)w_is_ipv6_reference, 1, fixup_spve_null, 0,
+		REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE },
+	{ "ip_type", (cmd_function)w_ip_type, 1, fixup_spve_null, 0,
+		REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE },
+	{ "compare_ips", (cmd_function)w_compare_ips, 2, fixup_spve_spve, 0,
+		REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE },
+	{ "compare_pure_ips", (cmd_function)w_compare_pure_ips, 2, fixup_spve_spve, 0,
+		REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE },
+	{ "is_ip_rfc1918", (cmd_function)w_is_ip_rfc1918, 1, fixup_spve_null, 0,
+		REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE },
+	{ "is_in_subnet", (cmd_function)w_ip_is_in_subnet, 2, fixup_spve_spve, 0,
+		REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE },
+	{ "dns_sys_match_ip", (cmd_function)w_dns_sys_match_ip, 2, fixup_spve_spve, 0,
+		ANY_ROUTE },
+	{ "dns_int_match_ip", (cmd_function)w_dns_int_match_ip, 2, fixup_spve_spve, 0,
+		ANY_ROUTE },
+	{ "dns_query", (cmd_function)w_dns_query, 2, fixup_spve_spve, 0,
+		ANY_ROUTE },
+	{ "srv_query", (cmd_function)w_srv_query, 2, fixup_spve_spve, 0,
+		ANY_ROUTE },
+	{ "bind_ipops", (cmd_function)bind_ipops, 0, 0, 0, 0},
+	{ 0, 0, 0, 0, 0, 0 }
 };
 
 
@@ -141,18 +147,18 @@ static cmd_export_t cmds[] =
  * Module interface
  */
 struct module_exports exports = {
-  "ipops",                   /*!< module name */
-  DEFAULT_DLFLAGS,           /*!< dlopen flags */
-  cmds,                      /*!< exported functions */
-  0,                         /*!< exported parameters */
-  0,                         /*!< exported statistics */
-  0,                         /*!< exported MI functions */
-  mod_pvs,                   /*!< exported pseudo-variables */
-  0,                         /*!< extra processes */
-  0,                         /*!< module initialization function */
-  (response_function) 0,     /*!< response handling function */
-  0,                         /*!< destroy function */
-  0                          /*!< per-child init function */
+	"ipops",                   /*!< module name */
+	DEFAULT_DLFLAGS,           /*!< dlopen flags */
+	cmds,                      /*!< exported functions */
+	0,                         /*!< exported parameters */
+	0,                         /*!< exported statistics */
+	0,                         /*!< exported MI functions */
+	mod_pvs,                   /*!< exported pseudo-variables */
+	0,                         /*!< extra processes */
+	0,                         /*!< module initialization function */
+	(response_function) 0,     /*!< response handling function */
+	0,                         /*!< destroy function */
+	0                          /*!< per-child init function */
 };
 
 
@@ -163,97 +169,97 @@ struct module_exports exports = {
 /*! \brief Return 1 if both pure IP's are equal, 0 otherwise. */
 int _compare_ips(char *ip1, size_t len1, enum enum_ip_type ip1_type, char *ip2, size_t len2, enum enum_ip_type ip2_type)
 {
-  struct in_addr in_addr1, in_addr2;
-  struct in6_addr in6_addr1, in6_addr2;
-  char _ip1[INET6_ADDRSTRLEN], _ip2[INET6_ADDRSTRLEN];
-  
-  // Not same IP type, return false.
-  if (ip1_type != ip2_type)
-    return 0;
-
-  memcpy(_ip1, ip1, len1);
-  _ip1[len1] = '\0';
-  memcpy(_ip2, ip2, len2);
-  _ip2[len2] = '\0';
-
-  switch(ip1_type) {
-    // Comparing IPv4 with IPv4.
-    case(ip_type_ipv4):
-      if (inet_pton(AF_INET, _ip1, &in_addr1) == 0)  return 0;
-      if (inet_pton(AF_INET, _ip2, &in_addr2) == 0)  return 0;
-      if (in_addr1.s_addr == in_addr2.s_addr)
-        return 1;
-      else
-        return 0;
-      break;
-    // Comparing IPv6 with IPv6.
-    case(ip_type_ipv6):
-      if (inet_pton(AF_INET6, _ip1, &in6_addr1) != 1)  return 0;
-      if (inet_pton(AF_INET6, _ip2, &in6_addr2) != 1)  return 0;
-      if (memcmp(in6_addr1.s6_addr, in6_addr2.s6_addr, sizeof(in6_addr1.s6_addr)) == 0)
-        return 1;
-      else
-        return 0;
-      break;
-    default:
-      return 0;
-      break;
-  }
+	struct in_addr in_addr1, in_addr2;
+	struct in6_addr in6_addr1, in6_addr2;
+	char _ip1[INET6_ADDRSTRLEN], _ip2[INET6_ADDRSTRLEN];
+
+	// Not same IP type, return false.
+	if (ip1_type != ip2_type)
+		return 0;
+
+	memcpy(_ip1, ip1, len1);
+	_ip1[len1] = '\0';
+	memcpy(_ip2, ip2, len2);
+	_ip2[len2] = '\0';
+
+	switch(ip1_type) {
+		// Comparing IPv4 with IPv4.
+		case(ip_type_ipv4):
+			if (inet_pton(AF_INET, _ip1, &in_addr1) == 0)  return 0;
+			if (inet_pton(AF_INET, _ip2, &in_addr2) == 0)  return 0;
+			if (in_addr1.s_addr == in_addr2.s_addr)
+				return 1;
+			else
+				return 0;
+			break;
+			// Comparing IPv6 with IPv6.
+		case(ip_type_ipv6):
+			if (inet_pton(AF_INET6, _ip1, &in6_addr1) != 1)  return 0;
+			if (inet_pton(AF_INET6, _ip2, &in6_addr2) != 1)  return 0;
+			if (memcmp(in6_addr1.s6_addr, in6_addr2.s6_addr, sizeof(in6_addr1.s6_addr)) == 0)
+				return 1;
+			else
+				return 0;
+			break;
+		default:
+			return 0;
+			break;
+	}
 }
 
 /*! \brief Return 1 if IP1 is in the subnet given by IP2 and the netmask, 0 otherwise. */
 int _ip_is_in_subnet(char *ip1, size_t len1, enum enum_ip_type ip1_type, char *ip2, size_t len2, enum enum_ip_type ip2_type, int netmask)
 {
-  struct in_addr in_addr1, in_addr2;
-  struct in6_addr in6_addr1, in6_addr2;
-  char _ip1[INET6_ADDRSTRLEN], _ip2[INET6_ADDRSTRLEN];
-  uint32_t ipv4_mask;
-  uint8_t ipv6_mask[16];
-  int i;
-  
-  // Not same IP type, return false.
-  if (ip1_type != ip2_type)
-    return 0;
-
-  memcpy(_ip1, ip1, len1);
-  _ip1[len1] = '\0';
-  memcpy(_ip2, ip2, len2);
-  _ip2[len2] = '\0';
-
-  switch(ip1_type) {
-    // Comparing IPv4 with IPv4.
-    case(ip_type_ipv4):
-      if (inet_pton(AF_INET, _ip1, &in_addr1) == 0)  return 0;
-      if (inet_pton(AF_INET, _ip2, &in_addr2) == 0)  return 0;
-      if (netmask <0 || netmask > 32)  return 0;
-      if (netmask == 32) ipv4_mask = 0xFFFFFFFF;
-      else ipv4_mask = htonl(~(0xFFFFFFFF >> netmask));
-      if ((in_addr1.s_addr & ipv4_mask) == in_addr2.s_addr)
-        return 1;
-      else
-        return 0;
-      break;
-    // Comparing IPv6 with IPv6.
-    case(ip_type_ipv6):
-      if (inet_pton(AF_INET6, _ip1, &in6_addr1) != 1)  return 0;
-      if (inet_pton(AF_INET6, _ip2, &in6_addr2) != 1)  return 0;
-      if (netmask <0 || netmask > 128)  return 0;
-      for (i=0; i<16; i++)
-      {
-        if (netmask > ((i+1)*8)) ipv6_mask[i] = 0xFF;
-        else if (netmask > (i*8))  ipv6_mask[i] = ~(0xFF >> (netmask-(i*8)));
-	else ipv6_mask[i] = 0x00;
-      }
-      for (i=0; i<16; i++)  in6_addr1.s6_addr[i] &= ipv6_mask[i];
-      if (memcmp(in6_addr1.s6_addr, in6_addr2.s6_addr, sizeof(in6_addr1.s6_addr)) == 0)
-        return 1;
-      else
-        return 0;
-      break;
-    default:
-      return 0;
-      break;
-  }
+	struct in_addr in_addr1, in_addr2;
+	struct in6_addr in6_addr1, in6_addr2;
+	char _ip1[INET6_ADDRSTRLEN], _ip2[INET6_ADDRSTRLEN];
+	uint32_t ipv4_mask;
+	uint8_t ipv6_mask[16];
+	int i;
+
+	// Not same IP type, return false.
+	if (ip1_type != ip2_type)
+		return 0;
+
+	memcpy(_ip1, ip1, len1);
+	_ip1[len1] = '\0';
+	memcpy(_ip2, ip2, len2);
+	_ip2[len2] = '\0';
+
+	switch(ip1_type) {
+		// Comparing IPv4 with IPv4.
+		case(ip_type_ipv4):
+			if (inet_pton(AF_INET, _ip1, &in_addr1) == 0)  return 0;
+			if (inet_pton(AF_INET, _ip2, &in_addr2) == 0)  return 0;
+			if (netmask <0 || netmask > 32)  return 0;
+			if (netmask == 32) ipv4_mask = 0xFFFFFFFF;
+			else ipv4_mask = htonl(~(0xFFFFFFFF >> netmask));
+			if ((in_addr1.s_addr & ipv4_mask) == in_addr2.s_addr)
+				return 1;
+			else
+				return 0;
+			break;
+			// Comparing IPv6 with IPv6.
+		case(ip_type_ipv6):
+			if (inet_pton(AF_INET6, _ip1, &in6_addr1) != 1)  return 0;
+			if (inet_pton(AF_INET6, _ip2, &in6_addr2) != 1)  return 0;
+			if (netmask <0 || netmask > 128)  return 0;
+			for (i=0; i<16; i++)
+			{
+				if (netmask > ((i+1)*8)) ipv6_mask[i] = 0xFF;
+				else if (netmask > (i*8))  ipv6_mask[i] = ~(0xFF >> (netmask-(i*8)));
+				else ipv6_mask[i] = 0x00;
+			}
+			for (i=0; i<16; i++)  in6_addr1.s6_addr[i] &= ipv6_mask[i];
+			if (memcmp(in6_addr1.s6_addr, in6_addr2.s6_addr, sizeof(in6_addr1.s6_addr)) == 0)
+				return 1;
+			else
+				return 0;
+			break;
+		default:
+			return 0;
+			break;
+	}
 }
 
 
@@ -265,358 +271,358 @@ int _ip_is_in_subnet(char *ip1, size_t len1, enum enum_ip_type ip1_type, char *i
 /*! \brief Return true if the given argument (string or pv) is a valid IPv4, IPv6 or IPv6 reference. */
 static int w_is_ip(struct sip_msg* _msg, char* _s)
 {
-  str string;
-  
-  if (_s == NULL) {
-    LM_ERR("bad parameter\n");
-    return -2;
-  }
-  
-  if (fixup_get_svalue(_msg, (gparam_p)_s, &string))
-  {
-    LM_ERR("cannot print the format for string\n");
-    return -3;
-  }
-  
-  if (ip_parser_execute(string.s, string.len) != ip_type_error)
-    return 1;
-  else
-    return -1;
+	str string;
+
+	if (_s == NULL) {
+		LM_ERR("bad parameter\n");
+		return -2;
+	}
+
+	if (fixup_get_svalue(_msg, (gparam_p)_s, &string))
+	{
+		LM_ERR("cannot print the format for string\n");
+		return -3;
+	}
+
+	if (ip_parser_execute(string.s, string.len) != ip_type_error)
+		return 1;
+	else
+		return -1;
 }
 
 
 /*! \brief Return true if the given argument (string or pv) is a valid IPv4 or IPv6. */
 static int w_is_pure_ip(struct sip_msg* _msg, char* _s)
 {
-  str string;
-  
-  if (_s == NULL) {
-    LM_ERR("bad parameter\n");
-    return -2;
-  }
-  
-  if (fixup_get_svalue(_msg, (gparam_p)_s, &string))
-  {
-    LM_ERR("cannot print the format for string\n");
-    return -3;
-  }
-
-  switch(ip_parser_execute(string.s, string.len)) {
-    case(ip_type_ipv4):
-      return 1;
-      break;
-    case(ip_type_ipv6):
-      return 1;
-      break;
-    default:
-      return -1;
-      break;
-  }
+	str string;
+
+	if (_s == NULL) {
+		LM_ERR("bad parameter\n");
+		return -2;
+	}
+
+	if (fixup_get_svalue(_msg, (gparam_p)_s, &string))
+	{
+		LM_ERR("cannot print the format for string\n");
+		return -3;
+	}
+
+	switch(ip_parser_execute(string.s, string.len)) {
+		case(ip_type_ipv4):
+			return 1;
+			break;
+		case(ip_type_ipv6):
+			return 1;
+			break;
+		default:
+			return -1;
+			break;
+	}
 }
 
 
 /*! \brief Return true if the given argument (string or pv) is a valid IPv4. */
 static int w_is_ipv4(struct sip_msg* _msg, char* _s)
 {
-  str string;
-  
-  if (_s == NULL) {
-    LM_ERR("bad parameter\n");
-    return -2;
-  }
-  
-  if (fixup_get_svalue(_msg, (gparam_p)_s, &string))
-  {
-    LM_ERR("cannot print the format for string\n");
-    return -3;
-  }
-
-  if (ip_parser_execute(string.s, string.len) == ip_type_ipv4)
-    return 1;
-  else
-    return -1;
+	str string;
+
+	if (_s == NULL) {
+		LM_ERR("bad parameter\n");
+		return -2;
+	}
+
+	if (fixup_get_svalue(_msg, (gparam_p)_s, &string))
+	{
+		LM_ERR("cannot print the format for string\n");
+		return -3;
+	}
+
+	if (ip_parser_execute(string.s, string.len) == ip_type_ipv4)
+		return 1;
+	else
+		return -1;
 }
 
 
 /*! \brief Return true if the given argument (string or pv) is a valid IPv6. */
 static int w_is_ipv6(struct sip_msg* _msg, char* _s)
 {
-  str string;
-  
-  if (_s == NULL) {
-    LM_ERR("bad parameter\n");
-    return -2;
-  }
-  
-  if (fixup_get_svalue(_msg, (gparam_p)_s, &string))
-  {
-    LM_ERR("cannot print the format for string\n");
-    return -3;
-  }
-  
-  if (ip_parser_execute(string.s, string.len) == ip_type_ipv6)
-    return 1;
-  else
-    return -1;
+	str string;
+
+	if (_s == NULL) {
+		LM_ERR("bad parameter\n");
+		return -2;
+	}
+
+	if (fixup_get_svalue(_msg, (gparam_p)_s, &string))
+	{
+		LM_ERR("cannot print the format for string\n");
+		return -3;
+	}
+
+	if (ip_parser_execute(string.s, string.len) == ip_type_ipv6)
+		return 1;
+	else
+		return -1;
 }
 
 
 /*! \brief Return true if the given argument (string or pv) is a valid IPv6 reference. */
 static int w_is_ipv6_reference(struct sip_msg* _msg, char* _s)
 {
-  str string;
-  
-  if (_s == NULL) {
-    LM_ERR("bad parameter\n");
-    return -2;
-  }
-  
-  if (fixup_get_svalue(_msg, (gparam_p)_s, &string))
-  {
-    LM_ERR("cannot print the format for string\n");
-    return -3;
-  }
-  
-  if (ip_parser_execute(string.s, string.len) == ip_type_ipv6_reference)
-    return 1;
-  else
-    return -1;
+	str string;
+
+	if (_s == NULL) {
+		LM_ERR("bad parameter\n");
+		return -2;
+	}
+
+	if (fixup_get_svalue(_msg, (gparam_p)_s, &string))
+	{
+		LM_ERR("cannot print the format for string\n");
+		return -3;
+	}
+
+	if (ip_parser_execute(string.s, string.len) == ip_type_ipv6_reference)
+		return 1;
+	else
+		return -1;
 }
 
 
 /*! \brief Return the IP type of the given argument (string or pv): 1 = IPv4, 2 = IPv6, 3 = IPv6 refenrece, -1 = invalid IP. */
 static int w_ip_type(struct sip_msg* _msg, char* _s)
 {
-  str string;
-  
-  if (_s == NULL) {
-    LM_ERR("bad parameter\n");
-    return -2;
-  }
-  
-  if (fixup_get_svalue(_msg, (gparam_p)_s, &string))
-  {
-    LM_ERR("cannot print the format for string\n");
-    return -3;
-  }
-  
-  switch (ip_parser_execute(string.s, string.len)) {
-    case(ip_type_ipv4):
-      return 1;
-      break;
-    case(ip_type_ipv6):
-      return 2;
-      break;
-    case(ip_type_ipv6_reference):
-      return 3;
-      break;
-    default:
-      return -1;
-      break;
-  }
+	str string;
+
+	if (_s == NULL) {
+		LM_ERR("bad parameter\n");
+		return -2;
+	}
+
+	if (fixup_get_svalue(_msg, (gparam_p)_s, &string))
+	{
+		LM_ERR("cannot print the format for string\n");
+		return -3;
+	}
+
+	switch (ip_parser_execute(string.s, string.len)) {
+		case(ip_type_ipv4):
+			return 1;
+			break;
+		case(ip_type_ipv6):
+			return 2;
+			break;
+		case(ip_type_ipv6_reference):
+			return 3;
+			break;
+		default:
+			return -1;
+			break;
+	}
 }
 
 
 /*! \brief Return true if both IP's (string or pv) are equal. This function also allows comparing an IPv6 with an IPv6 reference. */
 static int w_compare_ips(struct sip_msg* _msg, char* _s1, char* _s2)
 {
-  str string1, string2;
-  enum enum_ip_type ip1_type, ip2_type;
-  
-  if (_s1 == NULL || _s2 == NULL ) {
-    LM_ERR("bad parameters\n");
-    return -2;
-  }
-  
-  if (fixup_get_svalue(_msg, (gparam_p)_s1, &string1))
-  {
-    LM_ERR("cannot print the format for first string\n");
-    return -3;
-  }
-
-  if (fixup_get_svalue(_msg, (gparam_p)_s2, &string2))
-  {
-    LM_ERR("cannot print the format for second string\n");
-    return -3;
-  }
-
-  switch(ip1_type = ip_parser_execute(string1.s, string1.len)) {
-    case(ip_type_error):
-      return -1;
-      break;
-    case(ip_type_ipv6_reference):
-      string1.s += 1;
-      string1.len -= 2;
-      ip1_type = ip_type_ipv6;
-      break;
-    default:
-      break;
-  }
-  switch(ip2_type = ip_parser_execute(string2.s, string2.len)) {
-    case(ip_type_error):
-      return -1;
-      break;
-    case(ip_type_ipv6_reference):
-      string2.s += 1;
-      string2.len -= 2;
-      ip2_type = ip_type_ipv6;
-      break;
-    default:
-      break;
-  }
-
-  if (_compare_ips(string1.s, string1.len, ip1_type, string2.s, string2.len, ip2_type))
-    return 1;
-  else
-    return -1;
+	str string1, string2;
+	enum enum_ip_type ip1_type, ip2_type;
+
+	if (_s1 == NULL || _s2 == NULL ) {
+		LM_ERR("bad parameters\n");
+		return -2;
+	}
+
+	if (fixup_get_svalue(_msg, (gparam_p)_s1, &string1))
+	{
+		LM_ERR("cannot print the format for first string\n");
+		return -3;
+	}
+
+	if (fixup_get_svalue(_msg, (gparam_p)_s2, &string2))
+	{
+		LM_ERR("cannot print the format for second string\n");
+		return -3;
+	}
+
+	switch(ip1_type = ip_parser_execute(string1.s, string1.len)) {
+		case(ip_type_error):
+			return -1;
+			break;
+		case(ip_type_ipv6_reference):
+			string1.s += 1;
+			string1.len -= 2;
+			ip1_type = ip_type_ipv6;
+			break;
+		default:
+			break;
+	}
+	switch(ip2_type = ip_parser_execute(string2.s, string2.len)) {
+		case(ip_type_error):
+			return -1;
+			break;
+		case(ip_type_ipv6_reference):
+			string2.s += 1;
+			string2.len -= 2;
+			ip2_type = ip_type_ipv6;
+			break;
+		default:
+			break;
+	}
+
+	if (_compare_ips(string1.s, string1.len, ip1_type, string2.s, string2.len, ip2_type))
+		return 1;
+	else
+		return -1;
 }
 
 
 /*! \brief Return true if both pure IP's (string or pv) are equal. IPv6 references not allowed. */
 static int w_compare_pure_ips(struct sip_msg* _msg, char* _s1, char* _s2)
 {
-  str string1, string2;
-  enum enum_ip_type ip1_type, ip2_type;
-  
-  if (_s1 == NULL || _s2 == NULL ) {
-    LM_ERR("bad parameters\n");
-    return -2;
-  }
-  
-  if (fixup_get_svalue(_msg, (gparam_p)_s1, &string1))
-  {
-    LM_ERR("cannot print the format for first string\n");
-    return -3;
-  }
-  
-  if (fixup_get_svalue(_msg, (gparam_p)_s2, &string2))
-  {
-    LM_ERR("cannot print the format for second string\n");
-    return -3;
-  }
-
-  switch(ip1_type = ip_parser_execute(string1.s, string1.len)) {
-    case(ip_type_error):
-      return -1;
-      break;
-    case(ip_type_ipv6_reference):
-      return -1;
-      break;
-    default:
-      break;
-  }
-  switch(ip2_type = ip_parser_execute(string2.s, string2.len)) {
-    case(ip_type_error):
-      return -1;
-      break;
-    case(ip_type_ipv6_reference):
-      return -1;
-      break;
-    default:
-      break;
-  }
-  
-  if (_compare_ips(string1.s, string1.len, ip1_type, string2.s, string2.len, ip2_type))
-    return 1;
-  else
-    return -1;
+	str string1, string2;
+	enum enum_ip_type ip1_type, ip2_type;
+
+	if (_s1 == NULL || _s2 == NULL ) {
+		LM_ERR("bad parameters\n");
+		return -2;
+	}
+
+	if (fixup_get_svalue(_msg, (gparam_p)_s1, &string1))
+	{
+		LM_ERR("cannot print the format for first string\n");
+		return -3;
+	}
+
+	if (fixup_get_svalue(_msg, (gparam_p)_s2, &string2))
+	{
+		LM_ERR("cannot print the format for second string\n");
+		return -3;
+	}
+
+	switch(ip1_type = ip_parser_execute(string1.s, string1.len)) {
+		case(ip_type_error):
+			return -1;
+			break;
+		case(ip_type_ipv6_reference):
+			return -1;
+			break;
+		default:
+			break;
+	}
+	switch(ip2_type = ip_parser_execute(string2.s, string2.len)) {
+		case(ip_type_error):
+			return -1;
+			break;
+		case(ip_type_ipv6_reference):
+			return -1;
+			break;
+		default:
+			break;
+	}
+
+	if (_compare_ips(string1.s, string1.len, ip1_type, string2.s, string2.len, ip2_type))
+		return 1;
+	else
+		return -1;
 }
 
 
 /*! \brief Return true if the first IP (string or pv) is within the subnet defined by the second IP in CIDR notation. IPv6 references not allowed. */
 static int w_ip_is_in_subnet(struct sip_msg* _msg, char* _s1, char* _s2)
 {
-  str string1, string2;
-  enum enum_ip_type ip1_type, ip2_type;
-  char *cidr_pos = NULL;
-  int netmask = 0;
-  
-  if (_s1 == NULL || _s2 == NULL ) {
-    LM_ERR("bad parameters\n");
-    return -2;
-  }
-  
-  if (fixup_get_svalue(_msg, (gparam_p)_s1, &string1))
-  {
-    LM_ERR("cannot print the format for first string\n");
-    return -3;
-  }
-  
-  if (fixup_get_svalue(_msg, (gparam_p)_s2, &string2))
-  {
-    LM_ERR("cannot print the format for second string\n");
-    return -3;
-  }
-
-  switch(ip1_type = ip_parser_execute(string1.s, string1.len)) {
-    case(ip_type_error):
-      return -1;
-      break;
-    case(ip_type_ipv6_reference):
-      return -1;
-      break;
-    default:
-      break;
-  }
-  cidr_pos = string2.s + string2.len - 1;
-  while (cidr_pos > string2.s)
-  {
-    if (*cidr_pos == '/')
-    {
-      string2.len = (cidr_pos - string2.s);
-      netmask = atoi(cidr_pos+1);
-      break;
-    }
-    cidr_pos--;
-  }
-  switch(ip2_type = ip_parser_execute(string2.s, string2.len)) {
-    case(ip_type_error):
-      return -1;
-      break;
-    case(ip_type_ipv6_reference):
-      return -1;
-      break;
-    default:
-      break;
-  }
-
-  if (netmask == 0)
-  {
-    if (_compare_ips(string1.s, string1.len, ip1_type, string2.s, string2.len, ip2_type))
-      return 1;
-    else
-      return -1;
-  }
-  else
-  {
-    if (_ip_is_in_subnet(string1.s, string1.len, ip1_type, string2.s, string2.len, ip2_type, netmask))
-      return 1;
-    else
-      return -1;
-  }
+	str string1, string2;
+	enum enum_ip_type ip1_type, ip2_type;
+	char *cidr_pos = NULL;
+	int netmask = 0;
+
+	if (_s1 == NULL || _s2 == NULL ) {
+		LM_ERR("bad parameters\n");
+		return -2;
+	}
+
+	if (fixup_get_svalue(_msg, (gparam_p)_s1, &string1))
+	{
+		LM_ERR("cannot print the format for first string\n");
+		return -3;
+	}
+
+	if (fixup_get_svalue(_msg, (gparam_p)_s2, &string2))
+	{
+		LM_ERR("cannot print the format for second string\n");
+		return -3;
+	}
+
+	switch(ip1_type = ip_parser_execute(string1.s, string1.len)) {
+		case(ip_type_error):
+			return -1;
+			break;
+		case(ip_type_ipv6_reference):
+			return -1;
+			break;
+		default:
+			break;
+	}
+	cidr_pos = string2.s + string2.len - 1;
+	while (cidr_pos > string2.s)
+	{
+		if (*cidr_pos == '/')
+		{
+			string2.len = (cidr_pos - string2.s);
+			netmask = atoi(cidr_pos+1);
+			break;
+		}
+		cidr_pos--;
+	}
+	switch(ip2_type = ip_parser_execute(string2.s, string2.len)) {
+		case(ip_type_error):
+			return -1;
+			break;
+		case(ip_type_ipv6_reference):
+			return -1;
+			break;
+		default:
+			break;
+	}
+
+	if (netmask == 0)
+	{
+		if (_compare_ips(string1.s, string1.len, ip1_type, string2.s, string2.len, ip2_type))
+			return 1;
+		else
+			return -1;
+	}
+	else
+	{
+		if (_ip_is_in_subnet(string1.s, string1.len, ip1_type, string2.s, string2.len, ip2_type, netmask))
+			return 1;
+		else
+			return -1;
+	}
 }
 
 
 /*! \brief Return true if the given argument (string or pv) is a valid RFC 1918 IPv4 (private address). */
 static int w_is_ip_rfc1918(struct sip_msg* _msg, char* _s)
 {
-  str string;
-  
-  if (_s == NULL) {
-    LM_ERR("bad parameter\n");
-    return -2;
-  }
-  
-  if (fixup_get_svalue(_msg, (gparam_p)_s, &string))
-  {
-    LM_ERR("cannot print the format for string\n");
-    return -3;
-  }
-  
-  if (rfc1918_parser_execute(string.s, string.len) == 1)
-    return 1;
-  else
-    return -1;
+	str string;
+
+	if (_s == NULL) {
+		LM_ERR("bad parameter\n");
+		return -2;
+	}
+
+	if (fixup_get_svalue(_msg, (gparam_p)_s, &string))
+	{
+		LM_ERR("cannot print the format for string\n");
+		return -3;
+	}
+
+	if (rfc1918_parser_execute(string.s, string.len) == 1)
+		return 1;
+	else
+		return -1;
 }
 
 static inline ip_addr_t *strtoipX(str *ips)
@@ -669,9 +675,9 @@ static int w_dns_sys_match_ip(sip_msg_t *msg, char *hnp, char *ipp)
 
 	if ((status = getaddrinfo(hns.s, NULL, &hints, &res)) != 0)
 	{
-        LM_ERR("getaddrinfo: %s\n", gai_strerror(status));
-        return -4;
-    }
+		LM_ERR("getaddrinfo: %s\n", gai_strerror(status));
+		return -4;
+	}
 
 	for(p = res;p != NULL; p = p->ai_next)
 	{
@@ -692,7 +698,7 @@ static int w_dns_sys_match_ip(sip_msg_t *msg, char *hnp, char *ipp)
 				return 1;
 			}
 		}
-    }
+	}
 	freeaddrinfo(res);
 
 	return -1;
@@ -773,3 +779,31 @@ static int w_dns_query(struct sip_msg* msg, char* str1, char* str2)
 
 	return dns_update_pv(&hostname, &name);
 }
+
+/**
+ *
+ */
+static int w_srv_query(struct sip_msg* msg, char* str1, char* str2)
+{
+	str srvcname;
+	str name;
+
+	if(msg==NULL)
+	{
+		LM_ERR("received null msg\n");
+		return -1;
+	}
+
+	if(fixup_get_svalue(msg, (gparam_t*)str1, &srvcname)<0)
+	{
+		LM_ERR("cannot get the srvcname\n");
+		return -1;
+	}
+	if(fixup_get_svalue(msg, (gparam_t*)str2, &name)<0)
+	{
+		LM_ERR("cannot get the pvid name\n");
+		return -1;
+	}
+
+	return srv_update_pv(&srvcname, &name);
+}
diff --git a/modules/ipops/ipops_pv.c b/modules/ipops/ipops_pv.c
index 37f215c..ecd3ced 100644
--- a/modules/ipops/ipops_pv.c
+++ b/modules/ipops/ipops_pv.c
@@ -32,6 +32,7 @@
 #include <netinet/in.h>
 
 #include "../../dprint.h"
+#include "../../rand/fastrand.h"
 #include "../../hashes.h"
 #include "../../resolve.h"
 #include "../../pvar.h"
@@ -66,7 +67,6 @@ typedef struct _dns_pv {
 	int nidx;
 } dns_pv_t;
 
-
 static sr_dns_item_t *_sr_dns_list = NULL;
 
 /**
@@ -132,7 +132,6 @@ sr_dns_item_t *sr_dns_add_item(str *name)
 	return it;
 }
 
-
 /**
  *
  */
@@ -215,12 +214,12 @@ int pv_parse_dns_name(pv_spec_t *sp, str *in)
 			else if(strncmp(pvs.s, "ipv6", 4)==0)
 				dpv->type = 3;
 			else goto error;
-		break;
+			break;
 		case 5: 
 			if(strncmp(pvs.s, "count", 5)==0)
 				dpv->type = 4;
 			else goto error;
-		break;
+			break;
 		default:
 			goto error;
 	}
@@ -361,13 +360,13 @@ int dns_update_pv(str *hostname, str *name)
 	void *addr;
 	int status;
 	int i;
-	
+
 	if(hostname->len>255)
 	{
 		LM_DBG("target hostname too long (max 255): %s\n", hostname->s);
 		return -2;
 	}
-	
+
 	dr = sr_dns_get_item(name);
 	if(dr==NULL)
 	{
@@ -391,10 +390,10 @@ int dns_update_pv(str *hostname, str *name)
 
 	if ((status = getaddrinfo(dr->hostname, NULL, &hints, &res)) != 0)
 	{
-        LM_ERR("unable to resolve %s - getaddrinfo: %s\n",
+		LM_ERR("unable to resolve %s - getaddrinfo: %s\n",
 				dr->hostname, gai_strerror(status));
-        return -4;
-    }
+		return -4;
+	}
 
 	i=0;
 	for(p=res; p!=NULL; p=p->ai_next)
@@ -421,7 +420,7 @@ int dns_update_pv(str *hostname, str *name)
 					PV_DNS_RECS, dr->hostname);
 			break;
 		}
-    }
+	}
 	freeaddrinfo(res);
 
 	dr->count = i;
@@ -431,7 +430,6 @@ int dns_update_pv(str *hostname, str *name)
 	return 1;
 }
 
-
 struct _hn_pv_data {
 	str data;
 	str fullname;
@@ -487,7 +485,7 @@ int hn_pv_data_init(void)
 		_hn_data->hostname.len   = d - _hn_data->data.s;
 		_hn_data->hostname.s     = _hn_data->data.s;
 		_hn_data->domain.len     = _hn_data->fullname.len
-										- _hn_data->hostname.len-1;
+			- _hn_data->hostname.len-1;
 		_hn_data->domain.s       = d+1;
 	} else {
 		_hn_data->hostname       = _hn_data->fullname;
@@ -497,7 +495,7 @@ int hn_pv_data_init(void)
 	if (he) {
 		if ((strlen(he->h_name)!=_hn_data->fullname.len)
 				|| strncmp(he->h_name, _hn_data->fullname.s,
-									_hn_data->fullname.len)) {
+					_hn_data->fullname.len)) {
 			LM_WARN("hostname '%.*s' different than gethostbyname '%s'\n",
 					_hn_data->fullname.len, _hn_data->fullname.s, he->h_name);
 		}
@@ -549,7 +547,7 @@ int pv_parse_hn_name(pv_spec_p sp, str *in)
 			else if(strncmp(in->s, "i", 1)==0)
 				sp->pvp.pvn.u.isname.name.n = 3;
 			else goto error;
-		break;
+			break;
 		default:
 			goto error;
 	}
@@ -595,3 +593,543 @@ int pv_get_hn(struct sip_msg *msg, pv_param_t *param,
 			return pv_get_strval(msg, param, res, &_hn_data->hostname);
 	}
 }
+
+/**********
+ * srvquery PV
+ **********/
+
+static char *srvqrylst []
+= {"count", "port", "priority", "target", "weight", NULL};
+
+#define PV_SRV_MAXSTR 64
+#define PV_SRV_MAXRECS 32
+
+typedef struct _sr_srv_record {
+	unsigned short priority;
+	unsigned short weight;
+	unsigned short port;
+	char target [PV_SRV_MAXSTR + 1];
+} sr_srv_record_t;
+
+typedef struct _sr_srv_item {
+	str pvid;
+	unsigned int hashid;
+	int count;
+	sr_srv_record_t rr [PV_SRV_MAXRECS];
+	struct _sr_srv_item *next;
+} sr_srv_item_t;
+
+typedef struct _srv_pv {
+	sr_srv_item_t *item;
+	int type;
+	int flags;
+	pv_spec_t *pidx;
+	int nidx;
+} srv_pv_t;
+
+static sr_srv_item_t *_sr_srv_list = NULL;
+
+/**********
+ * Add srvquery Item
+ *
+ * INPUT:
+ *   Arg (1) = pvid string pointer
+ *   Arg (2) = find flag; <>0=search only
+ * OUTPUT: srv record pointer; NULL=not found
+ **********/
+
+sr_srv_item_t *sr_srv_add_item (str *pvid, int findflg)
+
+{
+	sr_srv_item_t *pitem;
+	unsigned int hashid;
+
+	/**********
+	 * o get hash
+	 * o already exists?
+	 **********/
+
+	hashid = get_hash1_raw (pvid->s, pvid->len);
+	for (pitem = _sr_srv_list; pitem; pitem = pitem->next) {
+		if (pitem->hashid == hashid
+				&& pitem->pvid.len == pvid->len
+				&& !strncmp (pitem->pvid.s, pvid->s, pvid->len))
+			return pitem;
+	}
+	if (findflg)
+		return NULL;
+
+	/**********
+	 * o alloc/init item structure
+	 * o link in new item
+	 **********/
+
+	pitem = (sr_srv_item_t *) pkg_malloc (sizeof (sr_srv_item_t));
+	if (!pitem) {
+		LM_ERR ("No more pkg memory!\n");
+		return NULL;
+	}
+	memset (pitem, 0, sizeof (sr_srv_item_t));
+	pitem->pvid.s = (char *) pkg_malloc (pvid->len + 1);
+	if (!pitem->pvid.s) {
+		LM_ERR ("No more pkg memory!\n");
+		pkg_free (pitem);
+		return NULL;
+	}
+	memcpy (pitem->pvid.s, pvid->s, pvid->len);
+	pitem->pvid.len = pvid->len;
+	pitem->hashid = hashid;
+	pitem->next = _sr_srv_list;
+	_sr_srv_list = pitem;
+	return pitem;
+}
+
+/**********
+ * Skip Over
+ *
+ * INPUT:
+ *   Arg (1) = string pointer
+ *   Arg (2) = starting position
+ *   Arg (3) = whitespace flag
+ * OUTPUT: position past skipped
+ **********/
+
+int skip_over (str *pstr, int pos, int bWS)
+
+{
+	char *pchar;
+
+	/**********
+	 * o string exists?
+	 * o skip over
+	 **********/
+
+	if (pos >= pstr->len)
+		return pstr->len;
+	for (pchar = &pstr->s [pos]; pos < pstr->len; pchar++, pos++) {
+		if (*pchar == ' ' || *pchar == '\t' || *pchar == '\n' || *pchar == '\r') {
+			if (bWS)
+				continue;
+		}
+		if ((*pchar>='A' && *pchar<='Z') || (*pchar>='a' && *pchar<='z')
+				|| (*pchar>='0' && *pchar<='9')) {
+			if (!bWS)
+				continue;
+		}
+		break;
+	}
+	return pos;
+}
+
+/**********
+ * Sort SRV Records by Weight (RFC 2782)
+ *
+ * INPUT:
+ *   Arg (1) = pointer to array of SRV records
+ *   Arg (2) = first record in range
+ *   Arg (3) = last record in range
+ * OUTPUT: position past skipped
+ **********/
+
+void sort_weights (struct srv_rdata **plist, int pos1, int pos2)
+
+{
+	int idx1, idx2, lastfound;
+	struct srv_rdata *wlist [PV_SRV_MAXRECS];
+	unsigned int rand, sum, sums [PV_SRV_MAXRECS];
+
+	/**********
+	 * place zero weights in the unordered list and then non-zero
+	 **********/
+
+	idx2 = 0;
+	for (idx1 = pos1; idx1 <= pos2; idx1++) {
+		if (!plist [idx1]->weight) {
+			wlist [idx2++] = plist [idx1];
+		}
+	}
+	for (idx1 = pos1; idx1 <= pos2; idx1++) {
+		if (plist [idx1]->weight) {
+			wlist [idx2++] = plist [idx1];
+		}
+	}
+
+	/**********
+	 * generate running sum list
+	 **********/
+
+	sum = 0;
+	for (idx1 = 0; idx1 < idx2; idx1++) {
+		sum += wlist [idx1]->weight;
+		sums [idx1] = sum;
+	}
+
+	/**********
+	 * resort randomly
+	 **********/
+
+	lastfound = 0;
+	for (idx1 = pos1; idx1 <= pos2; idx1++) {
+		/**********
+		 * o calculate a random number in range
+		 * o find first unsorted
+		 **********/
+
+		rand = fastrand_max (sum);
+		for (idx2 = 0; idx2 <= pos2 - pos1; idx2++) {
+			if (!wlist [idx2]) {
+				continue;
+			}
+			if (sums [idx2] >= rand) {
+				plist [idx1] = wlist [idx2];
+				wlist [idx2] = 0;
+				break;
+			}
+			lastfound = idx2;
+		}
+		if (idx2 > pos2 - pos1) {
+			plist [idx1] = wlist [lastfound];
+			wlist [lastfound] = 0;
+		}
+	}
+	return;
+}
+
+/**********
+ * Sort SRV Records by Priority/Weight
+ *
+ * INPUT:
+ *   Arg (1) = pointer to array of SRV records
+ *   Arg (2) = record count
+ * OUTPUT: position past skipped
+ **********/
+
+void sort_srv (struct srv_rdata **plist, int rcount)
+
+{
+	int idx1, idx2;
+	struct srv_rdata *pswap;
+
+	/**********
+	 * sort by priority
+	 **********/
+
+	for (idx1 = 1; idx1 < rcount; idx1++) {
+		pswap = plist [idx1];
+		for (idx2 = idx1;
+				idx2 && (plist [idx2 - 1]->priority > pswap->priority); --idx2) {
+			plist [idx2] = plist [idx2 - 1];
+		}
+		plist [idx2] = pswap;
+	}
+
+	/**********
+	 * check for multiple priority
+	 **********/
+
+	idx2 = 0;
+	pswap = plist [0];
+	for (idx1 = 1; idx1 <= rcount; idx1++) {
+		if ((idx1 == rcount) || (pswap->priority != plist [idx1]->priority)) {
+			/**********
+			 * o range has more than one element?
+			 * o restart range
+			 **********/
+
+			if (idx1 - idx2 - 1) {
+				sort_weights (plist, idx2, idx1 - 1);
+			}
+			idx2 = idx1;
+			pswap = plist [idx2];
+		}
+	}
+	return;
+}
+
+/**********
+ * Parse srvquery Name
+ *
+ * INPUT:
+ *   Arg (1) = pv spec pointer
+ *   Arg (2) = input string pointer
+ * OUTPUT: 0=success
+ **********/
+
+int pv_parse_srv_name (pv_spec_t *sp, str *in)
+
+{
+	char *pstr;
+	int i, pos, sign;
+	srv_pv_t *dpv;
+	str pvi = {0}, pvk = {0}, pvn = {0};
+
+	/**********
+	 * o alloc/init pvid structure
+	 * o extract pvid name
+	 * o check separator
+	 **********/
+
+	if (!sp || !in || in->len<=0)
+		return -1;
+	dpv = (srv_pv_t *) pkg_malloc (sizeof (srv_pv_t));
+	if (!dpv) {
+		LM_ERR ("No more pkg memory!\n");
+		return -1;
+	}
+	memset (dpv, 0, sizeof (srv_pv_t));
+	pos = skip_over (in, 0, 1);
+	if (pos == in->len)
+		goto error;
+	pvn.s = &in->s [pos];
+	pvn.len = pos;
+	pos = skip_over (in, pos, 0);
+	pvn.len = pos - pvn.len;
+	if (!pvn.len)
+		goto error;
+	pos = skip_over (in, pos, 1);
+	if ((pos + 2) > in->len)
+		goto error;
+	if (strncmp (&in->s [pos], "=>", 2))
+		goto error;
+
+	/**********
+	 * o extract key name
+	 * o check key name
+	 * o count?
+	 **********/
+
+	pos = skip_over (in, pos + 2, 1);
+	pvk.s = &in->s [pos];
+	pvk.len = pos;
+	pos = skip_over (in, pos, 0);
+	pvk.len = pos - pvk.len;
+	if (!pvk.len)
+		goto error;
+	for (i = 0; srvqrylst [i]; i++) {
+		if (strlen (srvqrylst [i]) != pvk.len)
+			continue;
+		if (!strncmp (pvk.s, srvqrylst [i], pvk.len)) {
+			dpv->type = i;
+			break;
+		}
+	}
+	if (!srvqrylst [i])
+		goto error;
+	if (!i)
+		goto noindex;
+
+	/**********
+	 * o check for array
+	 * o extract array index and check
+	 **********/
+
+	pos = skip_over (in, pos, 1);
+	if ((pos + 3) > in->len)
+		goto error;
+	if (in->s [pos] != '[')
+		goto error;
+	pos = skip_over (in, pos + 1, 1);
+	if ((pos + 2) > in->len)
+		goto error;
+	pvi.s = &in->s [pos];
+	pvi.len = pos;
+	if (in->s [pos] == PV_MARKER) {
+		/**********
+		 * o search from the end back to array close
+		 * o get PV value
+		 **********/
+
+		for (i = in->len - 1; i != pos; --i) {
+			if (in->s [i] == ']')
+				break;
+		}
+		if (i == pos)
+			goto error;
+		pvi.len = i - pvi.len;
+		pos = i + 1;
+		dpv->pidx = pv_cache_get (&pvi);
+		if (!dpv->pidx)
+			goto error;
+		dpv->flags |= SR_DNS_PVIDX;
+	} else {
+		/**********
+		 * o get index value
+		 * o check for reverse index
+		 * o convert string to number
+		 **********/
+
+		pos = skip_over (in, pos, 0);
+		pvi.len = pos - pvi.len;
+		sign = 1;
+		i = 0;
+		pstr = pvi.s;
+		if (*pstr == '-') {
+			sign = -1;
+			i++;
+			pstr++;
+		}
+		for (dpv->nidx = 0; i < pvi.len; i++) {
+			if (*pstr >= '0' && *pstr <= '9')
+				dpv->nidx = (dpv->nidx * 10) + *pstr++ - '0';
+		}
+		if (i != pvi.len)
+			goto error;
+		dpv->nidx *= sign;
+		pos = skip_over (in, pos, 1);
+		if (pos == in->len)
+			goto error;
+		if (in->s [pos++] != ']')
+			goto error;
+	}
+
+	/**********
+	 * o check for trailing whitespace
+	 * o add data to PV
+	 **********/
+
+noindex:
+	if (skip_over (in, pos, 1) != in->len)
+		goto error;
+	LM_DBG ("srvquery (%.*s => %.*s [%.*s])\n",
+			pvn.len, ZSW(pvn.s), pvk.len, ZSW(pvk.s), pvi.len, ZSW(pvi.s));
+	dpv->item = sr_srv_add_item (&pvn, 0);
+	if (!dpv->item)
+		goto error;
+	sp->pvp.pvn.u.dname = (void *)dpv;
+	sp->pvp.pvn.type = PV_NAME_OTHER;
+	return 0;
+
+error:
+	LM_ERR ("error at PV srvquery: %.*s@%d\n", in->len, in->s, pos);
+	pkg_free (dpv);
+	return -1;
+}
+
+int srv_update_pv (str *srvcname, str *pvid)
+
+{
+	int idx1, idx2, rcount;
+	struct rdata *phead, *psrv;
+	struct srv_rdata *plist [PV_SRV_MAXRECS];
+	sr_srv_item_t *pitem;
+	sr_srv_record_t *prec;
+
+	/**********
+	 * o service name missing?
+	 * o find pvid
+	 **********/
+
+	if (!srvcname->len) {
+		LM_DBG ("service name missing: %.*s\n", srvcname->len, srvcname->s);
+		return -2;
+	}
+	pitem = sr_srv_add_item (pvid, 1);
+	if (!pitem) {
+		LM_DBG ("pvid not found: %.*s\n", pvid->len, pvid->s);
+		return -3;
+	}
+
+	/**********
+	 * o get records
+	 * o sort by priority/weight
+	 * o save to PV
+	 **********/
+
+	LM_DBG ("attempting to query: %.*s\n", srvcname->len, srvcname->s);
+	phead = get_record (srvcname->s, T_SRV, RES_ONLY_TYPE);
+	rcount = 0;
+	for (psrv = phead; psrv; psrv = psrv->next) {
+		if (rcount < PV_SRV_MAXRECS) {
+			plist [rcount++] = (struct srv_rdata *) psrv->rdata;
+		} else {
+			LM_WARN ("truncating srv_query list to %d records!", PV_SRV_MAXRECS);
+			break;
+		}
+	}
+	pitem->count = rcount;
+	if (rcount)
+		sort_srv (plist, rcount);
+	for (idx1 = 0; idx1 < rcount; idx1++) {
+		prec = &pitem->rr [idx1];
+		prec->priority = plist [idx1]->priority;
+		prec->weight = plist [idx1]->weight;
+		prec->port = plist [idx1]->port;
+		idx2 = plist [idx1]->name_len;
+		if (idx2 > PV_SRV_MAXSTR) {
+			LM_WARN ("truncating srv_query target (%.*s)!", idx2, plist [idx1]->name);
+			idx2 = PV_SRV_MAXSTR;
+		}
+		strncpy (prec->target, plist [idx1]->name, idx2);
+		prec->target [idx2] = '\0';
+	}
+	if (phead)
+		free_rdata_list (phead);
+	LM_DBG ("srvquery PV updated for: %.*s (%d)\n",
+			srvcname->len, srvcname->s, rcount);
+	return 1;
+}
+
+/**********
+ * Get srvquery Values
+ *
+ * INPUT:
+ *   Arg (1) = SIP message pointer
+ *   Arg (2) = parameter pointer
+ *   Arg (3) = PV value pointer
+ * OUTPUT: 0=success
+ **********/
+
+int pv_get_srv (sip_msg_t *pmsg, pv_param_t *param, pv_value_t *res)
+
+{
+	pv_value_t val;
+	srv_pv_t *dpv;
+
+	/**********
+	 * o sipmsg and param exist?
+	 * o PV name exists?
+	 * o count?
+	 **********/
+
+	if(!pmsg || !param)
+		return -1;
+	dpv = (srv_pv_t *) param->pvn.u.dname;
+	if(!dpv || !dpv->item)
+		return -1;
+	if (!dpv->type)
+		return pv_get_sintval (pmsg, param, res, dpv->item->count);
+
+	/**********
+	 * o get index value
+	 * o reverse index?
+	 * o extract data
+	 **********/
+
+	if (!dpv->pidx) {
+		val.ri = dpv->nidx;
+	} else {
+		if (pv_get_spec_value (pmsg, dpv->pidx, &val) < 0
+				|| !(val.flags & PV_VAL_INT)) {
+			LM_ERR ("failed to evaluate index variable!\n");
+			return pv_get_null (pmsg, param, res);
+		}
+	}
+	if (val.ri < 0) {
+		if ((dpv->item->count + val.ri) < 0)
+			return pv_get_null (pmsg, param, res);
+		val.ri = dpv->item->count + val.ri;
+	}
+	if (val.ri >= dpv->item->count)
+		return pv_get_null(pmsg, param, res);
+	switch (dpv->type) {
+		case 1: /* port */
+			return pv_get_sintval (pmsg, param, res, dpv->item->rr [val.ri].port);
+		case 2: /* priority */
+			return pv_get_sintval (pmsg, param, res, dpv->item->rr [val.ri].priority);
+		case 3: /* target */
+			return pv_get_strzval (pmsg, param, res, dpv->item->rr [val.ri].target);
+		case 4: /* weight */
+			return pv_get_sintval (pmsg, param, res, dpv->item->rr [val.ri].weight);
+	}
+	return pv_get_null (pmsg, param, res);
+}
diff --git a/modules/ipops/ipops_pv.h b/modules/ipops/ipops_pv.h
index b4acab3..9a10124 100644
--- a/modules/ipops/ipops_pv.h
+++ b/modules/ipops/ipops_pv.h
@@ -39,5 +39,9 @@ int pv_parse_hn_name(pv_spec_p sp, str *in);
 int pv_get_hn(struct sip_msg *msg, pv_param_t *param,
 		pv_value_t *res);
 
+int pv_parse_srv_name(pv_spec_t *, str *);
+int pv_get_srv(sip_msg_t *, pv_param_t *, pv_value_t *);
+int srv_update_pv(str *, str *);
+
 #endif
 
diff --git a/modules/iptrtpproxy/Makefile b/modules/iptrtpproxy/Makefile
index ed9e915..59c9ddb 100644
--- a/modules/iptrtpproxy/Makefile
+++ b/modules/iptrtpproxy/Makefile
@@ -1,6 +1,5 @@
-# $Id$
 #
-# print example module makefile
+# iprtpproxy module makefile
 #
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
diff --git a/modules/iptrtpproxy/oob/sip-router-oob-RTPPROXY.cfg.patch b/modules/iptrtpproxy/oob/sip-router-oob-RTPPROXY.cfg.patch
new file mode 100644
index 0000000..6edcfe4
--- /dev/null
+++ b/modules/iptrtpproxy/oob/sip-router-oob-RTPPROXY.cfg.patch
@@ -0,0 +1,373 @@
+--- /root/sip-router/etc/sip-router-oob.cfg	2011-04-05 21:11:22.000000000 +0200
++++ sip-router-oob-RTPPROXY.cfg-pre_flexroute	2011-04-05 21:03:19.000000000 +0200
+@@ -283,23 +287,11 @@
+ #
+ session_timer.min_se = "90" desc "minimum session interval (in s)"
+ 
+-# RTP Proxy options
+-#
+-# Whether to enable or disable the rtp proxy. Possible values are:
+-# "0" -- always disable
+-# "1" -- always enable regardless of whether UAC or UAS is behind NAT
+-# "detect" -- detect whether the UAC or the UAS is behind NAT,
+-#             and enable the rtp proxy when necessary
+-#
+-#DEBCONF-RTP_ENABLE-START
+-rtp_proxy.enabled = "detect" desc "indicates whether the RTP Proxy is enabled or not (0/1/detect)"
+-#DEBCONF-RTP_ENABLE-END
+-
+ # ------------------ Module Loading -----------------------------------------
+ #!ifdef LOCAL_TEST_RUN
+ loadpath "modules:modules_s"
+ #!else
+-loadpath "/usr/lib/sip-router/modules:/usr/lib/sip-router/modules_s"
++loadpath "/usr/local/lib/ser/modules:/usr/local/lib/ser/modules_s"
+ #!endif
+ 
+ # load a SQL database for authentication, domains, user AVPs etc.
+@@ -457,7 +449,7 @@
+ modparam("rr", "enable_full_lr", 1)
+ 
+ # Limit the length of the AVP cookie to necessary attributes only
+-modparam("rr", "cookie_filter", "(account|rproxy|stimer|dialog_id)")
++modparam("rr", "cookie_filter", "(account|stimer|dialog_id)")
+ 
+ # You probably do not want that someone can simply read and change
+ # the AVP cookie in your Routes, thus should really change this
+@@ -467,7 +459,7 @@
+ # The ftag Route parameter may be used to easily determine if a BYE
+ # is coming from caller or callee, but we prefer shorter messages
+ # Enable when FLAG_REVERSE_DIR is to be used
+-modparam("rr", "append_fromtag", 0)
++modparam("rr", "append_fromtag", 1)
+ 
+ 
+ # -- gflags --
+@@ -529,7 +521,7 @@
+ 
+ # RTP Proxy address
+ #DEBCONF-RTTPPROXY-START
+-modparam("nathelper", "rtpproxy_sock", "udp:127.0.0.1:22222")
++#modparam("nathelper", "rtpproxy_sock", "udp:127.0.0.1:22222")
+ #DEBCONF-RTTPPROXY-END
+ 
+ # TCP keepalives as simple as CRLF
+@@ -649,7 +641,7 @@
+ 	route(PSTN);
+ 
+ 	# nothing matched
+-	sl_reply("404", "No route matched");
++	t_reply("404", "No route matched");
+ }
+ 
+ # Forward a request to the destination set.
+@@ -668,7 +660,8 @@
+ 	# If this is an initial INVITE (without a To-tag) we might try
+ 	# another target (call forwarding or voicemail) after receiving
+ 	# an error.
+-	if (isflagset(FLAG_INIT_DLG)) {
++	# and also for RTPPROXY processing
++	if (method=="INVITE" || method == "UPDATE") {
+ 		t_on_failure("FAILURE_ROUTE");
+ 	}
+ 
+@@ -682,7 +675,7 @@
+ 
+ 	# Activate the RTP proxy as the second last step because it modifies the
+ 	# body but also sets an dialog AVP cookie.
+-	route(RTPPROXY);
++	route(RTPPROXY_PROCESS_REQUEST);
+ 
+ 	# Insert a Record-Route header into all requests.
+ 	# This has to be done as one of the last steps to include all the
+@@ -742,10 +735,10 @@
+ 	# if needed then we MUST put after force_rport() which is located in NAT_DETECTION!!!
+ 	# also must be called after FLAG_ACC is set !!!
+ 	# Check t_reply() vs. sl_reply() usage in script
+-	#if (!t_newtran()) {
+-	#	sl_reply("500", "Internal tm error");
+-	#	drop;
+-	#}
++	if (!t_newtran()) {
++		sl_reply("500", "Internal tm error");
++		drop;
++	}
+ 														
+ 	# Set flag and use it instead of the attribute.
+ 	if ($replicate==1) {
+@@ -765,6 +758,7 @@
+ 		(uri == myself || $t.did != ""))
+ 	{
+ 		options_reply();
++		t_release();
+ 		drop;
+ 	}
+ }
+@@ -879,47 +873,7 @@
+ 	}
+ }
+ 
+-
+-# Activates RTP proxy if necessary.
+-#
+-route[RTPPROXY]
+-{
+-	if (@cfg_get.rtp_proxy.enabled == "0") {
+-		# RTP Proxy is disabled
+-		break;
+-	} else if (@cfg_get.rtp_proxy.enabled == "detect") {
+-		if (!isflagset(FLAG_NAT)) {
+-			# If no NAT is involved we don't have to do here anything.
+-			break;
+-		}
+-	} else if (@cfg_get.rtp_proxy.enabled != "1") {
+-		# This is not a valid setting
+-		xlog("L_ERR", "Unknown option for rtp_proxy.enabled: %@cfg_get.rtp_proxy.enabled\n");
+-		break;
+-	} # else rtp proxy is permanently enabled
+-
+-	# If the message terminates a dialog for which the RTP proxy 
+-	# was turned on, turn it off again.
+-	if ((method == "BYE" && isflagset(FLAG_RTP_PROXY)) ||
+-		(method == "CANCEL")) {
+-		unforce_rtp_proxy();
+-		append_hf("P-RTP-Proxy: Off\r\n");
+-		break;
+-	}
+-
+-	# Turn the RTP proxy on for INVITEs and UPDATEs, if they 
+-	# have a body
+-	if (((method=="INVITE" || method == "UPDATE") && @msg.body != "")
+-	    && !isflagset(FLAG_RTP_PROXY))
+-	{
+-		force_rtp_proxy('r');
+-		append_hf("P-RTP-Proxy: On\r\n");
+-		setflag(FLAG_RTP_PROXY);
+-		$rproxy = 1;
+-		setavpflag($rproxy, "dialog_cookie");
+-	}
+-}
+-
++include_file "sip-router-oob-RTPPROXY.cfg.inc"
+ 
+ # Handling of Route headers
+ #
+@@ -934,7 +888,7 @@
+ 		xlog("L_DEBUG", "\n%mb\n\ndialogid -/from/to=%$dialog_id/%$f.dialog_id/%$t.dialog_id");
+ 		if (method == "INVITE" || method == "UPDATE" || method == "ACK" || method == "BYE") {
+ 			if (!defined $dialog_id) {
+-				sl_reply("400", "Missing cookie");
++				t_reply("400", "Missing cookie");
+ 				drop;
+ 			}
+ 		}
+@@ -954,11 +908,6 @@
+ 			setflag(FLAG_ACC_MISSED);
+ 		}
+ 
+-		# Restore the RTP proxy flag if present
+-		if ($rproxy == "1") {
+-			setflag(FLAG_RTP_PROXY);
+-		}
+-
+ 		# Restore Session Timer flag and headers.
+ 		if ( defined $stimer && ($stimer != "0")) {
+ 			route(SESSION_TIMER);
+@@ -1039,7 +988,7 @@
+ 	# then From b at B and To a at A. There is no mentioning of c at C despite
+ 	# legitimate behaviour of c at C).
+ 	if (!isflagset(FLAG_TOTAG) && strempty($t.did) && strempty($f.did)) {
+-		sl_reply("403", "Relaying Forbidden");
++		t_reply("403", "Relaying Forbidden");
+ 		drop;
+ 	}
+ }
+@@ -1057,6 +1006,7 @@
+ 	# If this is a replica (sent to the multicast address), trust it to
+ 	# be secure and store it in usrloc
+ 	if (dst_ip==224.0.1.75) {
++		t_release();
+ 		if (!isflagset(FLAG_REPL_ENABLED)) {
+ 			# Multicast replication administratively disabled.
+ 			# Ignore.
+@@ -1097,13 +1047,13 @@
+ 
+ 	# Check if the REGISTER if for one of our local domains.
+ 	if (strempty($t.did)) {
+-		sl_reply("403", "Register Forwarding Forbidden");
++		t_reply("403", "Register Forwarding Forbidden");
+ 		drop;
+ 	}
+ 
+ 	# The REGISTER target is in the To header, so reload the domain.
+ 	if (!lookup_domain("$td", "@to.uri.host")) {
+-		sl_reply("404", "Unknown Domain");
++		t_reply("404", "Unknown Domain");
+ 		drop;
+ 	}
+ 
+@@ -1115,29 +1065,29 @@
+ 	# We want only authenticated users to be registered.
+ 	if (!www_authenticate("$fd.digest_realm", "credentials")) {
+ 		if ($? == -2) {
+-			sl_reply("500", "Internal Server Error");
++			t_reply("500", "Internal Server Error");
+ 		}
+ 		else if ($? == -3) {
+-			sl_reply("400", "Bad Request");
++			t_reply("400", "Bad Request");
+ 		}
+ 		else {
+ 			if ($digest_challenge != "") {
+ 				append_to_reply("%$digest_challenge");
+ 			}
+-			sl_reply("401", "Unauthorized");
++			t_reply("401", "Unauthorized");
+ 		}
+ 		drop;
+ 	}
+ 
+ 	# Check if the authenticated user is the same as the target user.
+ 	if (!lookup_user("$tu.uid", "@to.uri")) {
+-		sl_reply("404", "Unknown user in To");
++		t_reply("404", "Unknown user in To");
+ 		drop;
+ 	}
+ 
+ 	# the authentication ID does not match the ID in the To header
+ 	if ($f.uid != $t.uid) {
+-		sl_reply("403", "Authentication and To-Header mismatch");
++		t_reply("403", "Authentication and To-Header mismatch");
+ 		drop;
+ 	}
+ 
+@@ -1145,11 +1095,11 @@
+ 	# originator. You may uncomment it if you care, which URI is in
+ 	# the From header.
+ 	#if (!lookup_user("$fr.uid", "@from.uri")) {
+-	#	sl_reply("404", "Unknown user in From");
++	#	t_reply("404", "Unknown user in From");
+ 	#	drop;
+ 	#}
+ 	#if ($fu.uid != $fr.uid) {
+-	#	sl_reply("403", "Authentication and From-Header mismatch");
++	#	t_reply("403", "Authentication and From-Header mismatch");
+ 	#	drop;
+ 	#}
+ 
+@@ -1158,7 +1108,7 @@
+ 	}
+ 	# Everything is fine. Store the binding.
+ 	if (!save_contacts("location")) {
+-		sl_reply("400", "Invalid REGISTER Request");
++		t_reply("400", "Invalid REGISTER Request");
+ 		drop;
+ 	}
+ # do not delete the following 3 lines, they are used by debconf
+@@ -1190,7 +1140,7 @@
+ #DEBCONF-REPLICATION2-START
+ #
+ #DEBCONF-REPLICATION2-END
+-
++	t_release();
+ 	drop;
+ }
+ 
+@@ -1221,16 +1171,16 @@
+ 
+ 	if (!proxy_authenticate("$fd.digest_realm", "credentials")) {
+ 		if ($? == -2) {
+-			sl_reply("500", "Internal Server Error");
++			t_reply("500", "Internal Server Error");
+ 		}
+ 		else if ($? == -3) {
+-			sl_reply("400", "Bad Request");
++			t_reply("400", "Bad Request");
+ 		}
+ 		else {
+ 			if (defined $digest_challenge && $digest_challenge != "") {
+ 				append_to_reply("%$digest_challenge");
+ 			}
+-			sl_reply("407", "Proxy Authentication Required");
++			t_reply("407", "Proxy Authentication Required");
+ 		}
+ 		drop;
+ 	}
+@@ -1238,11 +1188,11 @@
+ 	# Check if the UID derived from authentication matches that from
+ 	# the From header.
+ 	if (!lookup_user("$fr.uid", "@from.uri")) {
+-		sl_reply("403", "Fake Identity");
++		t_reply("403", "Fake Identity");
+ 		drop;
+ 	}
+ 	if ($fu.uid != $fr.uid) {
+-		sl_reply("403", "Fake Identity");
++		t_reply("403", "Fake Identity");
+ 		drop;
+ 	}
+ 	setflag(FLAG_AUTH_OK);
+@@ -1274,10 +1224,10 @@
+ 	# UA to the real target.
+ 	if ($fd.did != "" && uri =~ "sip:[0-9][0-9]@") {
+ 		if (sd_lookup("speed_dial")) {
+-			sl_reply("302", "Speed Dial Redirect");
++			t_reply("302", "Speed Dial Redirect");
+ 		}
+ 		else {
+-			sl_reply("404", "Speed Dial Not Found");
++			t_reply("404", "Speed Dial Not Found");
+ 		}
+ 		drop;
+ 	}
+@@ -1392,7 +1342,7 @@
+ 	# Check permissions of the caller for initial INVITEs.
+ 	if (isflagset(FLAG_INIT_DLG)) {
+ 		if ($f.gw_acl != "1") {
+-			sl_reply("403", "PSTN Not Permitted");
++			t_reply("403", "PSTN Not Permitted");
+ 			drop;
+ 		}
+ 	}
+@@ -1431,7 +1381,7 @@
+ 		xlog("L_DEBUG", "catching cancel dialogid=%$dialog_id\n");
+ 		if (!t_relay_cancel()) {
+ 			# An INVITE was found but some error occurred.
+-			sl_reply("500", "Internal Server Error");
++			t_reply("500", "Internal Server Error");
+ 			drop;
+ 		}
+ 		# Bad luck, no corresponding INVITE was found, we have to
+@@ -1486,7 +1436,7 @@
+ 				# Session interval is lower than the
+ 				# configured Min-SE
+ 				append_to_reply("Min-SE: %@cfg_get.session_timer.min_se\r\n");
+-				sl_reply("422", "Session Interval Too Small");
++				t_reply("422", "Session Interval Too Small");
+ 				drop;
+ 			}
+ 
+@@ -1592,6 +1542,7 @@
+ 			}
+ 		}
+ 	} # if (isflagset...
++	route(RTPPROXY_PROCESS_FAILURE);
+ }
+ 
+ 
+@@ -1603,14 +1554,7 @@
+ 	# allow proper routing of in-dialog messages.
+ 	route(UAS_NAT_DETECTION);
+ 
+-	# If RTP proxy was activated and this is a 18x or 2xx reply with a
+-	# body, inform RTP proxy.
+-	if (isflagset(FLAG_RTP_PROXY)
+-	    && status=~"(18[03])|(2[0-9][0-9])"
+-	    && @msg.body != "")
+-	{
+-		force_rtp_proxy('r');
+-	}
++	route(RTPPROXY_PROCESS_REPLY);
+ 
+ 	# Let's check for session timer support.
+ 	if (isflagset(FLAG_SESSIONTIMER) && status =~ "2[0-9][0-9]") {
diff --git a/modules/jansson/Makefile b/modules/jansson/Makefile
new file mode 100644
index 0000000..2d033a4
--- /dev/null
+++ b/modules/jansson/Makefile
@@ -0,0 +1,22 @@
+#
+# jansson module makefile
+#
+# 
+# WARNING: do not run this directly, it should be run by the master Makefile
+
+include ../../Makefile.defs
+auto_gen=
+NAME=jansson.so
+
+BUILDER = $(shell which pkg-config)
+ifeq ($(BUILDER),)
+	DEFS+=-I$(LOCALBASE)/include \
+	LIBS+=-L$(SYSBASE)/include/lib -L$(LOCALBASE)/lib -ljansson
+else
+	DEFS+= $(shell pkg-config --cflags jansson)
+	LIBS+= $(shell pkg-config --libs jansson)
+endif
+DEFS+=-DOPENSER_MOD_INTERFACE
+
+SERLIBPATH=../../lib
+include ../../Makefile.modules
diff --git a/modules/jansson/README b/modules/jansson/README
new file mode 100644
index 0000000..c5be0a6
--- /dev/null
+++ b/modules/jansson/README
@@ -0,0 +1,236 @@
+JANSSON Module
+
+Joe Hillenbrand
+
+   <joe at flowroute.com>
+
+Edited by
+
+Matthew Williams
+
+   <matthew at flowroute.com>
+
+   Copyright � 2013 Flowroute LLC (flowroute.com)
+     __________________________________________________________________
+
+   Table of Contents
+
+   1. Admin Guide
+
+        1. Overview
+        2. Dependencies
+
+              2.1. Kamailio Modules
+              2.2. External Libraries or Applications
+
+        3. Parameters
+
+              3.1.
+
+        4. Functions
+
+              4.1. jansson_get(key/path, src, dst)
+              4.2. jansson_set(type, key/path, value, result)
+              4.3. jansson_append(type, key/path, value, result)
+              4.4. jansson_array_size(key/path, src, dst)
+              4.5. jansson_get_field(src, field_name, dst)
+
+   List of Examples
+
+   1.1. jansson_get usage
+   1.2. jansson_set usage
+   1.3. jansson_append usage
+   1.4. jansson_array_size usage
+   1.5. array concatination
+   1.6. jansson_get_field usage
+
+Chapter 1. Admin Guide
+
+   Table of Contents
+
+   1. Overview
+   2. Dependencies
+
+        2.1. Kamailio Modules
+        2.2. External Libraries or Applications
+
+   3. Parameters
+
+        3.1.
+
+   4. Functions
+
+        4.1. jansson_get(key/path, src, dst)
+        4.2. jansson_set(type, key/path, value, result)
+        4.3. jansson_append(type, key/path, value, result)
+        4.4. jansson_array_size(key/path, src, dst)
+        4.5. jansson_get_field(src, field_name, dst)
+
+1. Overview
+
+   This module provides operations on JSON strings using JANSSON library.
+   It has support for JSON-PATH operations.
+
+2. Dependencies
+
+   2.1. Kamailio Modules
+   2.2. External Libraries or Applications
+
+2.1. Kamailio Modules
+
+   The following modules must be loaded before this module:
+     * None
+
+2.2. External Libraries or Applications
+
+   The following libraries or applications must be installed before
+   running Kamailio with this module loaded:
+     * jansson (http://www.digip.org/jansson/), tested with: 2.2+
+
+3. Parameters
+
+   3.1.
+
+   None
+
+4. Functions
+
+   4.1. jansson_get(key/path, src, dst)
+   4.2. jansson_set(type, key/path, value, result)
+   4.3. jansson_append(type, key/path, value, result)
+   4.4. jansson_array_size(key/path, src, dst)
+   4.5. jansson_get_field(src, field_name, dst)
+
+4.1. jansson_get(key/path, src, dst)
+
+   Copy the value at the location 'path' from the json object 'src' and
+   store it in pvar 'dst'.
+
+   The path string supports dot delimited notation (e.g. foo.bar.baz),
+   array notation (e.g. [0]), or a combination of the two (e.g.
+   foo.bar[0][1].baz).
+
+   The function can put a string, integer, null, or new json string into
+   destination.
+
+   Example 1.1. jansson_get usage
+...
+jansson_get("inner.deep.list[3]", $var(myjson), "$var(n)");
+xlog("foo is $var(n)");
+...
+
+4.2. jansson_set(type, key/path, value, result)
+
+   Insert 'value' as 'type' at location 'path' into 'result'.
+
+   The path string works the same as in jansson_get.
+
+   Valid 'type' parameters are 'integer', 'real', 'string', 'object',
+   'array', 'true', 'false', and 'null' as well as abbriviated names such
+   as 'int', 'str', and 'obj'. 'value' is ignored when type is 'true',
+   'false', or 'null'.
+
+   Example 1.2. jansson_set usage
+...
+# create a new json object and put a string in it at key "mystr"
+jansson_set("string", "mystr", "my input string", "$var(myjson)");
+# $var(myjson) =='{"mystr":"my input string"}'
+
+# add other values
+jansson_set("integer", "count", 9000, "$var(myjson)");
+jansson_set("true", "mybool", 0, "$var(myjson)");
+jansson_set("real", "pi", "3.14159", "$var(myjson)");
+# $var(myjson) == '{"mystr":"my input string", "count":9000, "mybool":true, "pi"
+:3.14159}'
+
+# add a nested object
+jansson_set("obj", "myobj", '{"foo":"bar"}', "$var(myjson)");
+# $var(myjson) =='{"mystr":"my input string", "count":9000, "mybool":true, "pi":
+3.14159, "myobj":{"foo":"bar"}}'
+
+# change the nested object
+jansson_set("str", "myobj.foo", "baz", "$var(myjson)");
+# $var(myjson) == '{"mystr":"my input string", "count":9000, "mybool":true, "pi"
+:3.14159, "myobj":{"foo":"baz"}}'
+...
+
+4.3. jansson_append(type, key/path, value, result)
+
+   Like jansson_set but can be used to append to arrays. It can also be
+   used to combine two json objects.
+
+   Note that when appending a json object to another json object, if there
+   is a key that is shared between the two objects, that value will be
+   overwritten by the new object.
+
+   Example 1.3. jansson_append usage
+...
+# create a new json array and append values to it
+$var(myarray) = '[]';
+jansson_append("int", "", 0, "$var(myarray)");
+jansson_append("int", "", 1, "$var(myarray)");
+jansson_append("int", "", 2, "$var(myarray)");
+jansson_append("int", "", 3, "$var(myarray)");
+jansson_append("int", "", 4, "$var(myarray)");
+# $var(myarray) == '[0,1,2,3,4]'
+
+# add that array to an object
+jansson_set("array", "list", $var(myarray), "$var(myjson)");
+# $var(myjson) == '{"list":[0,1,2,3,4]}'
+
+# append another value to the list
+jansson_append("int", "list", 5, "$var(myjson)");
+# $var(myjson) == '{"list":[0,1,2,3,4,5]}'
+
+# combining two json objects
+$var(newobj) = '{"b":2, "c":3}';
+jansson_append('obj', "", '{"a":1, "b":100}', "$var(newobj)");
+# $var(newobj) == '{"a":1,"b":100","c":3}';
+...
+
+4.4. jansson_array_size(key/path, src, dst)
+
+   Puts the size of the array in 'src' at location 'path' into the pvar
+   'dst'.
+
+   This is particularly useful for looping through an array. See example.
+
+   Example 1.4. jansson_array_size usage
+...
+$var(array) = "{\"loopme\":[0,1,2,3,4,5]}";
+$var(count) = 0;
+jansson_array_size("loopme", $var(array), "$var(size)");
+while($var(count) < $var(size)) {
+    jansson_get("loopme[$var(count)]", $var(array), "$var(v)");
+    xlog("loopme[$var(count)] == $var(v)\n");
+    $var(count) = $var(count) + 1;
+}
+...
+
+   Example 1.5. array concatination
+...
+$var(count) = 0;
+$var(appendme) = '[0,1]';
+$var(mylist) = '[2,3,4,5]';
+jansson_array_size("", $var(mylist), "$var(appendme_size)");
+while($var(count) < $var(appendme_size)) {
+    jansson_get("[$var(count)]", $var(mylist), "$var(tmp)");
+    jansson_append('int', "", $var(tmp), "$var(appendme)");
+    $var(count) = $var(count) + 1;
+}
+...
+
+4.5. jansson_get_field(src, field_name, dst)
+
+   Copy field 'field_name' from json object 'src' and store it in pvar
+   'dst'.
+
+   This function is deprecated but kept for backwards compatibility. Right
+   now it is just a wrapper around jansson_get, and its functionality is
+   the same.
+
+   Example 1.6. jansson_get_field usage
+...
+jansson_get_field("{'foo':'bar'}", "foo", "$var(foo)");
+xlog("foo is $var(foo)");
+...
diff --git a/modules/jansson/doc/Makefile b/modules/jansson/doc/Makefile
new file mode 100644
index 0000000..2cafa1e
--- /dev/null
+++ b/modules/jansson/doc/Makefile
@@ -0,0 +1,4 @@
+docs = jansson.xml
+
+docbook_dir = ../../../docbook
+include $(docbook_dir)/Makefile.module
diff --git a/modules/jansson/doc/jansson.xml b/modules/jansson/doc/jansson.xml
new file mode 100644
index 0000000..4d05657
--- /dev/null
+++ b/modules/jansson/doc/jansson.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding='ISO-8859-1'?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+<!-- Include general documentation entities -->
+<!ENTITY % docentities SYSTEM "../../../docbook/entities.xml">
+%docentities;
+
+]>
+
+<book xmlns:xi="http://www.w3.org/2001/XInclude">
+    <bookinfo>
+	<title>JANSSON Module</title>
+	<productname class="trade">kamailio.org</productname>
+	<authorgroup>
+	    <author>
+		<firstname>Joe</firstname>
+		<surname>Hillenbrand</surname>
+		<email>joe at flowroute.com</email>
+	    </author>
+	    <editor>
+			<firstname>Matthew</firstname>
+			<surname>Williams</surname>
+			<email>matthew at flowroute.com</email>
+	    </editor>
+	</authorgroup>
+	<copyright>
+	    <year>2013</year>
+	    <holder>Flowroute LLC (flowroute.com)</holder>
+	</copyright>
+    </bookinfo>
+    <toc></toc>
+    
+    <xi:include href="jansson_admin.xml"/>
+    
+    
+</book>
diff --git a/modules/jansson/doc/jansson_admin.xml b/modules/jansson/doc/jansson_admin.xml
new file mode 100644
index 0000000..b1b0eab
--- /dev/null
+++ b/modules/jansson/doc/jansson_admin.xml
@@ -0,0 +1,230 @@
+<?xml version="1.0" encoding='ISO-8859-1'?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+<!-- Include general documentation entities -->
+<!ENTITY % docentities SYSTEM "../../../docbook/entities.xml">
+%docentities;
+
+]>
+<!-- Module User's Guide -->
+
+<chapter>
+
+    <title>&adminguide;</title>
+
+    <section>
+    <title>Overview</title>
+    <para>
+		This module provides operations on JSON strings using JANSSON
+		library. It has support for JSON-PATH operations.
+    </para>
+    </section>
+
+    <section>
+    <title>Dependencies</title>
+    <section>
+        <title>&kamailio; Modules</title>
+        <para>
+        The following modules must be loaded before this module:
+            <itemizedlist>
+            <listitem>
+            <para>
+                <emphasis>None</emphasis>
+            </para>
+            </listitem>
+            </itemizedlist>
+        </para>
+    </section>
+    <section>
+        <title>External Libraries or Applications</title>
+        <para>
+        The following libraries or applications must be installed before running
+        &kamailio; with this module loaded:
+            <itemizedlist>
+            <listitem>
+            <para>
+                <emphasis>jansson (http://www.digip.org/jansson/)</emphasis>, tested with: 2.2+
+            </para>
+            </listitem>
+            </itemizedlist>
+        </para>
+    </section>
+    </section>
+    <section>
+    <title>Parameters</title>
+    <section>
+        <para>
+            <emphasis>None</emphasis>
+        </para>
+    </section>
+    </section>
+
+    <section>
+    <title>Functions</title>
+    <section>
+        <title>
+            <function moreinfo="none">jansson_get(key/path, src, dst)</function>
+        </title>
+        <para>
+            Copy the value at the location 'path' from the json object 'src' and store it in pvar 'dst'.
+        </para>
+        <para>
+            The path string supports dot delimited notation (e.g. foo.bar.baz), array notation (e.g. [0]), or a combination of the two (e.g. foo.bar[0][1].baz).
+        </para>
+        <para>
+            The function can put a string, integer, null, or new json string into destination.
+        </para>
+        <example>
+        <title><function>jansson_get</function> usage</title>
+        <programlisting format="linespecific">
+...
+jansson_get("inner.deep.list[3]", $var(myjson), "$var(n)");
+xlog("foo is $var(n)");
+...
+        </programlisting>
+        </example>
+    </section>
+    <section>
+        <title>
+            <function moreinfo="none">jansson_set(type, key/path, value, result)</function>
+        </title>
+        <para>
+            Insert 'value' as 'type' at location 'path' into 'result'.
+        </para>
+        <para>
+            The path string works the same as in jansson_get.
+        </para>
+        <para>
+            Valid 'type' parameters are 'integer', 'real', 'string', 'object', 'array', 'true', 'false', and 'null'  as well as
+            abbriviated names such as 'int', 'str', and 'obj'. 'value' is ignored when type is 'true', 'false', or 'null'.
+        </para>
+        <example>
+        <title><function>jansson_set</function> usage</title>
+        <programlisting format="linespecific">
+...
+# create a new json object and put a string in it at key "mystr"
+jansson_set("string", "mystr", "my input string", "$var(myjson)");
+# $var(myjson) =='{"mystr":"my input string"}'
+
+# add other values
+jansson_set("integer", "count", 9000, "$var(myjson)");
+jansson_set("true", "mybool", 0, "$var(myjson)");
+jansson_set("real", "pi", "3.14159", "$var(myjson)");
+# $var(myjson) == '{"mystr":"my input string", "count":9000, "mybool":true, "pi":3.14159}'
+
+# add a nested object
+jansson_set("obj", "myobj", '{"foo":"bar"}', "$var(myjson)");
+# $var(myjson) =='{"mystr":"my input string", "count":9000, "mybool":true, "pi":3.14159, "myobj":{"foo":"bar"}}'
+
+# change the nested object
+jansson_set("str", "myobj.foo", "baz", "$var(myjson)");
+# $var(myjson) == '{"mystr":"my input string", "count":9000, "mybool":true, "pi":3.14159, "myobj":{"foo":"baz"}}'
+...
+        </programlisting>
+        </example>
+    </section>
+    <section>
+        <title>
+            <function moreinfo="none">jansson_append(type, key/path, value, result)</function>
+        </title>
+        <para>
+            Like jansson_set but can be used to append to arrays. It can also be used to combine two json objects.
+        </para>
+        <para>
+            Note that when appending a json object to another json object, if there is a key that is shared between the two objects, that value will be overwritten by the new object.
+        </para>
+        <example>
+        <title><function>jansson_append</function> usage</title>
+        <programlisting format="linespecific">
+...
+# create a new json array and append values to it
+$var(myarray) = '[]';
+jansson_append("int", "", 0, "$var(myarray)");
+jansson_append("int", "", 1, "$var(myarray)");
+jansson_append("int", "", 2, "$var(myarray)");
+jansson_append("int", "", 3, "$var(myarray)");
+jansson_append("int", "", 4, "$var(myarray)");
+# $var(myarray) == '[0,1,2,3,4]'
+
+# add that array to an object
+jansson_set("array", "list", $var(myarray), "$var(myjson)");
+# $var(myjson) == '{"list":[0,1,2,3,4]}'
+
+# append another value to the list
+jansson_append("int", "list", 5, "$var(myjson)");
+# $var(myjson) == '{"list":[0,1,2,3,4,5]}'
+
+# combining two json objects
+$var(newobj) = '{"b":2, "c":3}';
+jansson_append('obj', "", '{"a":1, "b":100}', "$var(newobj)");
+# $var(newobj) == '{"a":1,"b":100","c":3}';
+...
+        </programlisting>
+        </example>
+    </section>
+    <section>
+        <title>
+            <function moreinfo="none">jansson_array_size(key/path, src, dst)</function>
+        </title>
+        <para>
+            Puts the size of the array in 'src' at location 'path' into the pvar 'dst'.
+        </para>
+        <para>
+            This is particularly useful for looping through an array. See example.
+        </para>
+        <example>
+        <title><function>jansson_array_size</function> usage</title>
+        <programlisting format="linespecific">
+...
+$var(array) = "{\"loopme\":[0,1,2,3,4,5]}";
+$var(count) = 0;
+jansson_array_size("loopme", $var(array), "$var(size)");
+while($var(count) < $var(size)) {
+    jansson_get("loopme[$var(count)]", $var(array), "$var(v)");
+    xlog("loopme[$var(count)] == $var(v)\n");
+    $var(count) = $var(count) + 1;
+}
+...
+        </programlisting>
+        </example>
+        <example>
+        <title>array concatination</title>
+        <programlisting format="linespecific">
+...
+$var(count) = 0;
+$var(appendme) = '[0,1]';
+$var(mylist) = '[2,3,4,5]';
+jansson_array_size("", $var(mylist), "$var(appendme_size)");
+while($var(count) < $var(appendme_size)) {
+    jansson_get("[$var(count)]", $var(mylist), "$var(tmp)");
+    jansson_append('int', "", $var(tmp), "$var(appendme)");
+    $var(count) = $var(count) + 1;
+}
+...
+        </programlisting>
+        </example>
+    </section>
+    <section>
+        <title>
+            <function moreinfo="none">jansson_get_field(src, field_name, dst)</function>
+        </title>
+        <para>
+            Copy field 'field_name' from json object 'src' and store it in pvar 'dst'.
+        </para>
+        <para>
+            <emphasis>This function is deprecated</emphasis> but kept for backwards compatibility. Right now it is just a wrapper around <function>jansson_get</function>, and its functionality is the same.
+        </para>
+        <example>
+        <title><function>jansson_get_field</function> usage</title>
+        <programlisting format="linespecific">
+...
+jansson_get_field("{'foo':'bar'}", "foo", "$var(foo)");
+xlog("foo is $var(foo)");
+...
+        </programlisting>
+        </example>
+    </section>
+    </section>
+</chapter>
+
diff --git a/modules/jansson/jansson_funcs.c b/modules/jansson/jansson_funcs.c
new file mode 100644
index 0000000..fbae741
--- /dev/null
+++ b/modules/jansson/jansson_funcs.c
@@ -0,0 +1,293 @@
+/**
+ * Copyright (C) 2013 Flowroute LLC (flowroute.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <jansson.h>
+
+#include "../../mod_fix.h"
+#include "../../lvalue.h"
+
+#include "jansson_path.h"
+#include "jansson_funcs.h"
+#include "jansson_utils.h"
+
+int janssonmod_get(struct sip_msg* msg, char* path_in, char* src_in, char* dst)
+{
+	str src_s;
+	str path_s;
+	pv_spec_t *dst_pv;
+	pv_value_t dst_val;
+
+	if (fixup_get_svalue(msg, (gparam_p)src_in, &src_s) != 0) {
+		ERR("cannot get json string value\n");
+		return -1;
+	}
+
+	if (fixup_get_svalue(msg, (gparam_p)path_in, &path_s) != 0) {
+		ERR("cannot get path string value\n");
+		return -1;
+	}
+
+	dst_pv = (pv_spec_t *)dst;
+
+	json_t* json = NULL;
+	json_error_t parsing_error;
+
+	json = json_loads(src_s.s, JSON_REJECT_DUPLICATES, &parsing_error);
+
+	if(!json) {
+		ERR("failed to parse: %.*s\n", src_s.len, src_s.s);
+		ERR("json error at line %d: %s\n",
+				parsing_error.line, parsing_error.text);
+		goto fail;
+	}
+
+	char* path = path_s.s;
+
+	json_t* v = json_path_get(json, path);
+	if(!v) {
+		goto fail;
+	}
+
+	char* freeme = NULL;
+
+	if(jansson_to_val(&dst_val, &freeme, v)<0) goto fail;
+
+	dst_pv->setf(msg, &dst_pv->pvp, (int)EQ_T, &dst_val);
+
+	if(freeme!=NULL) {
+		free(freeme);
+	}
+
+	json_decref(json);
+	return 1;
+
+fail:
+	json_decref(json);
+	return -1;
+}
+
+#define STR_EQ_STATIC(a,b) ((a.len == sizeof(b)-1) && (strncmp(a.s, b, sizeof(b)-1)==0))
+
+int janssonmod_set(unsigned int append, struct sip_msg* msg, char* type_in,
+		 char* path_in, char* value_in, char* result_in)
+{
+	str type_s;
+	str value_s;
+	str path_s;
+
+	pv_spec_t* result_pv;
+	pv_value_t result_val;
+
+	if (fixup_get_svalue(msg, (gparam_p)type_in, &type_s) != 0){
+		ERR("cannot get type string value\n");
+		return -1;
+	}
+
+	if (fixup_get_svalue(msg, (gparam_p)value_in, &value_s) != 0){
+		ERR("cannot get value string\n");
+		return -1;
+	}
+
+	if (fixup_get_svalue(msg, (gparam_p)path_in, &path_s) != 0){
+		ERR("cannot get path string value\n");
+		return -1;
+	}
+
+	result_pv = (pv_spec_t *)result_in;
+
+	if(pv_get_spec_value(msg, result_pv, &result_val)!=0
+			|| result_val.flags != PV_VAL_STR) {
+		result_val.flags = PV_VAL_STR;
+		result_val.rs.s = "{}";
+		result_val.rs.len = strlen("{}");
+	}
+
+/*
+	ALERT("type is: %.*s\n", type_s.len, type_s.s);
+	ALERT("path is: %.*s\n", path_s.len, path_s.s);
+	ALERT("value is: %.*s\n", value_s.len, value_s.s);
+	ALERT("result is: %.*s\n", result_val.rs.len, result_val.rs.s);
+*/
+
+	char* result = result_val.rs.s;
+
+	json_t* result_json = NULL;
+	json_t* value = NULL;
+	char* freeme = NULL;
+	json_error_t parsing_error;
+	char* endptr;
+
+	/* check the type */
+	if(STR_EQ_STATIC(type_s, "object") || STR_EQ_STATIC(type_s, "obj")){
+		value = json_loads(value_s.s, JSON_REJECT_DUPLICATES, &parsing_error);
+		if(value && !json_is_object(value)) {
+			ERR("value to add is not an object\n");
+			goto fail;
+		}
+
+	}else if(STR_EQ_STATIC(type_s, "array")) {
+		value = json_loads(value_s.s, JSON_REJECT_DUPLICATES, &parsing_error);
+		if(value && !json_is_array(value)) {
+			ERR("value to add is not an array\n");
+			goto fail;
+		}
+
+	}else if(STR_EQ_STATIC(type_s, "string")
+				|| STR_EQ_STATIC(type_s, "str")) {
+		value = json_string(value_s.s);
+		if(!value || !json_is_string(value)) {
+			ERR("value to add is not a string\n");
+			goto fail;
+		}
+
+	}else if(STR_EQ_STATIC(type_s, "integer")
+				|| STR_EQ_STATIC(type_s, "int")) {
+		int i = strtol(value_s.s, &endptr, 10);
+		if(*endptr != '\0') {
+			ERR("parsing int failed for \"%s\"\n", value_s.s);
+			goto fail;
+		}
+		value = json_integer(i);
+		if(!value || !json_is_integer(value)) {
+			ERR("value to add is not an integer\n");
+			goto fail;
+		}
+
+	}else if(STR_EQ_STATIC(type_s, "real")) {
+		double d = strtod(value_s.s, &endptr);
+		if(*endptr != '\0') {
+			ERR("parsing real failed for \"%s\"\n", value_s.s);
+			goto fail;
+		}
+		value = json_real(d);
+		if(!value || !json_is_real(value)) {
+			ERR("value to add is not a real\n");
+			goto fail;
+		}
+
+	}else if(STR_EQ_STATIC(type_s, "true")) {
+		value = json_true();
+
+	}else if(STR_EQ_STATIC(type_s, "false")) {
+		value = json_false();
+
+	}else if(STR_EQ_STATIC(type_s, "null")) {
+		value = json_null();
+
+	} else {
+		ERR("unrecognized input type\n");
+		goto fail;
+	}
+
+	if(!value) {
+		ERR("parsing failed for \"%s\"\n", value_s.s);
+		ERR("value error at line %d: %s\n",
+				parsing_error.line, parsing_error.text);
+		goto fail;
+	}
+
+	char* path = path_s.s;
+
+	result_json = json_loads(result, JSON_REJECT_DUPLICATES, &parsing_error);
+
+	if(!result_json) {
+		ERR("result has json error at line %d: %s\n",
+				parsing_error.line, parsing_error.text);
+		goto fail;
+	}
+
+	if(json_path_set(result_json, path, value, append)<0) {
+		goto fail;
+	}
+
+	if(jansson_to_val(&result_val, &freeme, result_json)<0) goto fail;
+
+	result_pv->setf(msg, &result_pv->pvp, (int)EQ_T, &result_val);
+
+	if(freeme) free(freeme);
+	json_decref(result_json);
+	return 1;
+
+fail:
+	if(freeme) free(freeme);
+	json_decref(result_json);
+	return -1;
+}
+
+int janssonmod_array_size(struct sip_msg* msg, char* path_in, char* src_in, char* dst)
+{
+	str src_s;
+	str path_s;
+	pv_spec_t *dst_pv;
+	pv_value_t dst_val;
+
+	if (fixup_get_svalue(msg, (gparam_p)src_in, &src_s) != 0) {
+		ERR("cannot get json string value\n");
+		return -1;
+	}
+
+	if (fixup_get_svalue(msg, (gparam_p)path_in, &path_s) != 0) {
+		ERR("cannot get path string value\n");
+		return -1;
+	}
+
+	dst_pv = (pv_spec_t *)dst;
+
+	json_t* json = NULL;
+	json_error_t parsing_error;
+
+	json = json_loads(src_s.s, JSON_REJECT_DUPLICATES, &parsing_error);
+
+	if(!json) {
+		ERR("json error at line %d: %s\n",
+				parsing_error.line, parsing_error.text);
+		goto fail;
+	}
+
+	char* path = path_s.s;
+
+	json_t* v = json_path_get(json, path);
+	if(!v) {
+		ERR("failed to find %s in json\n", path);
+		goto fail;
+	}
+
+	if(!json_is_array(v)) {
+		ERR("value at %s is not an array\n", path);
+		goto fail;
+	}
+
+	int size = json_array_size(v);
+	dst_val.ri = size;
+	dst_val.flags = PV_TYPE_INT|PV_VAL_INT;
+
+	dst_pv->setf(msg, &dst_pv->pvp, (int)EQ_T, &dst_val);
+
+	json_decref(json);
+	return 1;
+
+fail:
+	json_decref(json);
+	return -1;
+}
diff --git a/modules/jansson/jansson_funcs.h b/modules/jansson/jansson_funcs.h
new file mode 100644
index 0000000..7babbc2
--- /dev/null
+++ b/modules/jansson/jansson_funcs.h
@@ -0,0 +1,35 @@
+/**
+ * Copyright (C) 2011 Flowroute LLC (flowroute.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef _JANSSON_FUNCS_H_
+#define _JANSSON_FUNCS_H_
+
+#include "../../parser/msg_parser.h"
+
+int janssonmod_get(struct sip_msg* msg, char* path_in, char* json_in,
+		char* result);
+int janssonmod_set(unsigned int append, struct sip_msg* msg, char* type_in,
+		char* path_in, char* value_in, char* result);
+int janssonmod_array_size(struct sip_msg* msg, char* json_in,
+		char* path_in, char* dst);
+
+#endif
diff --git a/modules/jansson/jansson_mod.c b/modules/jansson/jansson_mod.c
new file mode 100644
index 0000000..58f4904
--- /dev/null
+++ b/modules/jansson/jansson_mod.c
@@ -0,0 +1,149 @@
+/**
+ * Copyright (C) 2011 Flowroute LLC (flowroute.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "../../mod_fix.h"
+#include "../../sr_module.h"
+
+#include "jansson_funcs.h"
+#include "jansson_utils.h"
+
+MODULE_VERSION
+
+/* module functions */
+static int mod_init(void);
+static int fixup_get_params(void** param, int param_no);
+static int fixup_get_params_free(void** param, int param_no);
+static int fixup_set_params(void** param, int param_no);
+static int fixup_set_params_free(void** param, int param_no);
+
+
+int janssonmod_set_replace(struct sip_msg* msg, char* type_in, char* path_in,
+		char* value_in, char* result){
+	return janssonmod_set(0, msg, type_in, path_in, value_in, result);
+}
+
+int janssonmod_set_append(struct sip_msg* msg, char* type_in, char* path_in,
+		char* value_in, char* result) {
+	return janssonmod_set(1, msg, type_in, path_in, value_in, result);
+}
+int janssonmod_get_field(struct sip_msg* msg, char* jansson_in, char* path_in,
+		char* result) {
+	return janssonmod_get(msg, path_in, jansson_in, result);
+}
+
+/* Exported functions */
+static cmd_export_t cmds[]={
+	{"jansson_get", (cmd_function)janssonmod_get, 3,
+		fixup_get_params, fixup_get_params_free, ANY_ROUTE},
+	{"jansson_array_size", (cmd_function)janssonmod_array_size, 3,
+		fixup_get_params, fixup_get_params_free, ANY_ROUTE},
+	{"jansson_set", (cmd_function)janssonmod_set_replace, 4,
+		fixup_set_params, fixup_set_params_free, ANY_ROUTE},
+	{"jansson_append", (cmd_function)janssonmod_set_append, 4,
+		fixup_set_params, fixup_set_params_free, ANY_ROUTE},
+	/* for backwards compatibility */
+	{"jansson_get_field", (cmd_function)janssonmod_get_field, 3,
+		fixup_get_params, fixup_get_params_free, ANY_ROUTE},
+	/* non-script functions */
+	{"jansson_to_val", (cmd_function)jansson_to_val, 0, 0, 0, 0},
+	{0, 0, 0, 0, 0, 0}
+};
+
+struct module_exports exports = {
+		"jansson",
+		DEFAULT_DLFLAGS,	/* dlopen flags */
+		cmds,				/* Exported functions */
+		0,					/* Exported parameters */
+		0,					/* exported statistics */
+		0,					/* exported MI functions */
+		0,					/* exported pseudo-variables */
+		0,					/* extra processes */
+		mod_init,			/* module initialization function */
+		0,					/* response function*/
+		0,					/* destroy function */
+		0					/* per-child init function */
+};
+
+
+static int fixup_get_params(void** param, int param_no)
+{
+	if (param_no <= 2) {
+		return fixup_spve_null(param, 1);
+	}
+
+	if (param_no == 3) {
+		return fixup_pvar_null(param, 1);
+	}
+
+	ERR("invalid parameter number <%d>\n", param_no);
+	return -1;
+}
+
+static int fixup_get_params_free(void** param, int param_no)
+{
+	if (param_no <= 2) {
+		return fixup_free_spve_null(param, 1);
+	}
+
+	if (param_no == 3) {
+		return fixup_free_pvar_null(param, 1);
+	}
+
+	ERR("invalid parameter number <%d>\n", param_no);
+	return -1;
+}
+
+static int fixup_set_params(void** param, int param_no)
+{
+	if(param_no <= 3) {
+		return fixup_spve_null(param, 1);
+	}
+
+	if (param_no == 4) {
+		return fixup_pvar_null(param, 1);
+	}
+
+	ERR("invalid parameter number <%d>\n", param_no);
+	return -1;
+}
+
+static int fixup_set_params_free(void** param, int param_no)
+{
+	if (param_no <= 3) {
+		return fixup_free_spve_null(param, 1);
+	}
+
+	if (param_no == 4) {
+		return fixup_free_pvar_null(param, 1);
+	}
+
+	ERR("invalid parameter number <%d>\n", param_no);
+	return -1;
+}
+
+/* just used for unit testing */
+static int mod_init(void) {
+	return 0;
+}
diff --git a/modules/jansson/jansson_path.c b/modules/jansson/jansson_path.c
new file mode 100644
index 0000000..d7c4c83
--- /dev/null
+++ b/modules/jansson/jansson_path.c
@@ -0,0 +1,279 @@
+/*
+ * Copyright (c) 2009-2012 Petri Lehtinen <petri at digip.org>
+ * Copyright (c) 2011-2012 Basile Starynkevitch <basile at starynkevitch.net>
+ * Copyright (c) 2012 Rogerz Zhang <rogerz.zhang at gmail.com>
+ * Copyright (c) 2013 Flowroute LLC (flowroute.com)
+ *
+ * Jansson is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license.
+ *
+ * Pulled from https://github.com/rogerz/jansson/blob/json_path/src/path.c
+ */
+
+#include <string.h>
+#include <assert.h>
+
+#include <jansson.h>
+
+#include "../../mod_fix.h"
+
+/* jansson private helper functions */
+void *jsonp_malloc(size_t size);
+void jsonp_free(void *ptr);
+char *jsonp_strdup(const char *str);
+
+static json_malloc_t do_malloc = malloc;
+static json_free_t do_free = free;
+
+json_t *json_path_get(const json_t *json, const char *path)
+{
+	static const char array_open = '[';
+	static const char *path_delims = ".[", *array_close = "]";
+	const json_t *cursor;
+	char *token, *buf, *peek, *endptr, delim = '\0';
+	const char *expect;
+
+	if (!json || !path)
+		return NULL;
+	else
+		buf = jsonp_strdup(path);
+
+	peek = buf;
+	token = buf;
+	cursor = json;
+	expect = path_delims;
+
+	if (*token == array_open) {
+		expect = array_close;
+		token++;
+	}
+
+	while (peek && *peek && cursor)
+	{
+		char *last_peek = peek;
+		peek = strpbrk(peek, expect);
+		if (peek) {
+			if (!token && peek != last_peek)
+				goto fail;
+			delim = *peek;
+			*peek++ = '\0';
+		} else if (expect != path_delims || !token) {
+			goto fail;
+		}
+
+		if (expect == path_delims) {
+			if (token) {
+				cursor = json_object_get(cursor, token);
+			}
+			expect = (delim == array_open ? array_close : path_delims);
+			token = peek;
+		} else if (expect == array_close) {
+			size_t index = strtol(token, &endptr, 0);
+			if (*endptr)
+				goto fail;
+			cursor = json_array_get(cursor, index);
+			token = NULL;
+			expect = path_delims;
+		} else {
+			goto fail;
+		}
+	}
+
+	jsonp_free(buf);
+	return (json_t *)cursor;
+fail:
+	jsonp_free(buf);
+	return NULL;
+}
+
+int json_path_set(json_t *json, const char *path, json_t *value,
+		unsigned int append)
+{
+	static const char array_open = '[';
+	static const char object_delim = '.';
+	static const char *path_delims = ".[";
+	static const char *array_close = "]";
+
+	json_t *cursor, *parent = NULL;
+	char *token, *buf = NULL, *peek, delim = '\0';
+	const char *expect;
+	int index_saved = -1;
+
+	if (!json || !path || !value) {
+		ERR("invalid arguments\n");
+		goto fail;
+	} else {
+		buf = jsonp_strdup(path);
+	}
+
+	peek = buf;
+	token = buf;
+	cursor = json;
+	expect = path_delims;
+
+	if (*token == array_open) {
+		expect = array_close;
+		token++;
+	}
+
+	while (peek && *peek && cursor)
+	{
+		char *last_peek = peek;
+		peek = strpbrk(last_peek, expect);
+
+		if (peek) {
+			if (!token && peek != last_peek) {
+				ERR("unexpected trailing chars in JSON path at pos %zu\n",
+						last_peek - buf);
+				goto fail;
+			}
+			delim = *peek;
+			*peek++ = '\0';
+		} else { // end of path
+			if (expect == path_delims) {
+				break;
+			} else {
+				ERR("missing ']' at pos %zu\n", peek - buf);
+				goto fail;
+			}
+		}
+
+		if (expect == path_delims) {
+			if (token) {
+				if (token[0] == '\0') {
+					ERR("empty token at pos %zu\n", peek - buf);
+					goto fail;
+				}
+
+				parent = cursor;
+				cursor = json_object_get(parent, token);
+
+				if (!cursor) {
+					if (!json_is_object(parent)) {
+						ERR("object expected at pos %zu\n", peek - buf);
+						goto fail;
+					}
+					if (delim == object_delim) {
+						cursor = json_object();
+						json_object_set_new(parent, token, cursor);
+					} else {
+						ERR("new array is not allowed at pos %zu\n", peek - buf);
+						goto fail;
+					}
+				}
+			}
+			expect = (delim == array_open ? array_close : path_delims);
+			token = peek;
+		} else if (expect == array_close) {
+			char *endptr;
+			size_t index;
+
+			parent = cursor;
+			if (!json_is_array(parent)) {
+				ERR("array expected at pos %zu\n", peek - buf);
+				goto fail;
+			}
+
+			index = strtol(token, &endptr, 0);
+			if (*endptr) {
+				ERR("invalid array index at pos %zu\n", peek - buf);
+				goto fail;
+			}
+
+			cursor = json_array_get(parent, index);
+			if (!cursor) {
+				ERR("array index out of bound at pos %zu\n", peek - buf);
+				goto fail;
+			}
+
+			index_saved = index;
+			token = NULL;
+			expect = path_delims;
+
+		} else {
+			ERR("fatal JSON error at pos %zu\n", peek - buf);
+			goto fail;
+		}
+	}
+
+	if (token && append) {
+
+		if(strlen(token) > 0) {
+			json_t* tmp  = json_object_get(cursor, token);
+			if(json_is_array(tmp)) {
+				json_array_append(tmp, value);
+				json_object_set(cursor, token, tmp);
+			} else if(json_is_object(tmp) && json_is_object(value) ) {
+				json_object_update(tmp, value);
+				json_object_set(cursor, token, tmp);
+			} else {
+				ERR("JSON array or object expected at pos %zu\n", peek - buf);
+				goto fail;
+			}
+		} else if(json_is_array(cursor)) {
+			json_array_append(cursor, value);
+
+		} else if(json_is_object(cursor) && json_is_object(value)) {
+			json_object_update(cursor, value);
+
+		} else {
+			ERR("JSON array or object expected at pos %zu\n", peek - buf);
+			goto fail;
+		}
+
+	} else if (token && strlen(token) != 0 ) {
+
+		if (json_is_object(cursor)) {
+			json_object_set(cursor, token, value);
+
+		} else {
+			ERR("JSON object expected at pos %zu\n", peek - buf);
+			goto fail;
+		}
+
+		cursor = json_object_get(cursor, token);
+	} else if (index_saved != -1 && json_is_array(parent)) {
+		json_array_set(parent, index_saved, value);
+		cursor = json_array_get(parent, index_saved);
+
+	} else {
+		ERR("invalid JSON path at pos %zu\n", peek - buf);
+		goto fail;
+	}
+
+	json_decref(value);
+	jsonp_free(buf);
+	return 0;
+
+fail:
+	json_decref(value);
+	jsonp_free(buf);
+	return -1;
+}
+
+/* jansson private helper functions */
+void *jsonp_malloc(size_t size) {
+	if(!size)
+		return NULL;
+
+	return (*do_malloc)(size);
+}
+
+void jsonp_free(void *ptr) {
+	if(!ptr)
+		return;
+
+	(*do_free)(ptr);
+}
+
+char *jsonp_strdup(const char *str) {
+	char *new_str;
+
+	new_str = jsonp_malloc(strlen(str) + 1); 
+	if(!new_str)
+		return NULL;
+
+	strcpy(new_str, str);
+	return new_str;
+}
+/* end jansson private helpers */
diff --git a/modules/jansson/jansson_path.h b/modules/jansson/jansson_path.h
new file mode 100644
index 0000000..9aefb49
--- /dev/null
+++ b/modules/jansson/jansson_path.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2012 Rogerz Zhang <rogerz.zhang at gmail.com>
+ *
+ * Jansson is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. 
+ */
+
+
+#ifndef _JANSSON_FUNCS_H_
+#define _JANSSON_FUNCS_H_
+#include <jansson.h>
+
+json_t *json_path_get(const json_t *json, const char *path);
+int json_path_set(json_t *json, const char *path, json_t *value, unsigned int append);
+
+#endif
+
diff --git a/modules/jansson/jansson_utils.c b/modules/jansson/jansson_utils.c
new file mode 100644
index 0000000..85f87ad
--- /dev/null
+++ b/modules/jansson/jansson_utils.c
@@ -0,0 +1,70 @@
+/**
+ * Copyright (C) 2013 Flowroute LLC (flowroute.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <jansson.h>
+
+#include "../../lvalue.h"
+
+#include "jansson_utils.h"
+
+int jansson_to_val(pv_value_t* val, char** freeme, json_t* v) {
+
+	val->flags = 0;
+
+	if(json_is_object(v) || json_is_array(v)) {
+		const char* value = json_dumps(v, JSON_COMPACT);
+		*freeme = (char*)value;
+		val->rs.s = (char*)value;
+		val->rs.len = strlen(value);
+		val->flags = PV_VAL_STR;
+	}else if(json_is_string(v)) {
+		const char* value = json_string_value(v);
+		val->rs.s = (char*)value;
+		val->rs.len = strlen(value);
+		val->flags = PV_VAL_STR;
+	}else if(json_is_boolean(v)) {
+		val->ri = json_is_true(v) ? 0 : 1;
+		val->flags = PV_TYPE_INT|PV_VAL_INT;
+	}else if(json_is_real(v)) {
+		char* value = NULL;
+		if(asprintf(&value, "%.15g", json_real_value(v))<0) {
+			ERR("asprintf failed\n");
+			return -1;
+		}
+		*freeme = value;
+		val->rs.s = value;
+		val->rs.len = strlen(value);
+		val->flags = PV_VAL_STR;
+	}else if(json_is_integer(v)) {
+		int value = json_integer_value(v);
+		val->ri = value;
+		val->flags = PV_TYPE_INT|PV_VAL_INT;
+	}else if(json_is_null(v)) {
+		val->flags = PV_VAL_NULL;
+	}else {
+		ERR("unrecognized json type: %d\n", json_typeof(v));
+		return -1;
+	}
+	return 0;
+}
diff --git a/modules/jansson/jansson_utils.h b/modules/jansson/jansson_utils.h
new file mode 100644
index 0000000..5f57509
--- /dev/null
+++ b/modules/jansson/jansson_utils.h
@@ -0,0 +1,34 @@
+/**
+ * Copyright (C) 2013 Flowroute LLC (flowroute.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef _JANSSON_UTILS_H_
+#define _JANSSON_UTILS_H_
+
+#include <jansson.h>
+
+#include "../../sr_module.h"
+#include "../../lvalue.h"
+
+typedef int (*jansson_to_val_f)(pv_value_t* val, char** freeme, json_t* v);
+int jansson_to_val(pv_value_t* val, char** freeme, json_t* v);
+
+#endif
diff --git a/modules/janssonrpc-c/Makefile b/modules/janssonrpc-c/Makefile
new file mode 100644
index 0000000..21e4d4c
--- /dev/null
+++ b/modules/janssonrpc-c/Makefile
@@ -0,0 +1,26 @@
+#
+# janssonrpc-c module makefile
+#
+# 
+# WARNING: do not run this directly, it should be run by the master Makefile
+
+include ../../Makefile.defs
+auto_gen=
+NAME=janssonrpc-c.so
+LIBS=-lm
+
+BUILDER = $(shell which pkg-config)
+ifeq ($(BUILDER),)
+	DEFS+=-I$(LOCALBASE)/include
+	LIBS+=-L$(SYSBASE)/include/lib -L$(LOCALBASE)/lib -levent -ljansson
+else
+	DEFS+= $(shell pkg-config --cflags jansson)
+	LIBS+= $(shell pkg-config --libs jansson)
+	DEFS+= $(shell pkg-config --cflags libevent)
+	LIBS+= $(shell pkg-config --libs libevent)
+endif
+ 
+DEFS+=-DOPENSER_MOD_INTERFACE
+
+SERLIBPATH=../../lib
+include ../../Makefile.modules
diff --git a/modules/janssonrpc-c/README b/modules/janssonrpc-c/README
new file mode 100644
index 0000000..d585e05
--- /dev/null
+++ b/modules/janssonrpc-c/README
@@ -0,0 +1,355 @@
+janssonrpc-c Module
+
+Joe Hillenbrand
+
+   <joe at flowroute.com>
+
+Edited by
+
+Matthew Williams
+
+   <matthew at flowroute.com>
+
+   Copyright � 2013 Flowroute LLC (flowroute.com)
+     __________________________________________________________________
+
+   Table of Contents
+
+   1. Admin Guide
+
+        1. Overview
+        2. Dependencies
+
+              2.1. Kamailio Modules
+              2.2. External Libraries or Applications
+
+        3. Parameters
+
+              3.1. min_srv_ttl (integer)
+              3.2. result_pv (string)
+              3.3. server (string)
+              3.4. retry_codes (string)
+
+        4. Functions
+
+              4.1. janssonrpc_notification(conn, method, parameters)
+              4.2. janssonrpc_request(conn, method, params[, options]])
+              4.3. Error Handling
+
+   List of Examples
+
+   1.1. Set min_srv_ttl parameter
+   1.2. Set result_pv parameter
+   1.3. Set server parameter
+   1.4. Set retry_codes parameter
+   1.5. janssonrpc_notification usage
+   1.6. janssonrpc_request usage
+   1.7. route example with internal_error handling
+
+Chapter 1. Admin Guide
+
+   Table of Contents
+
+   1. Overview
+   2. Dependencies
+
+        2.1. Kamailio Modules
+        2.2. External Libraries or Applications
+
+   3. Parameters
+
+        3.1. min_srv_ttl (integer)
+        3.2. result_pv (string)
+        3.3. server (string)
+        3.4. retry_codes (string)
+
+   4. Functions
+
+        4.1. janssonrpc_notification(conn, method, parameters)
+        4.2. janssonrpc_request(conn, method, params[, options]])
+        4.3. Error Handling
+
+1. Overview
+
+   This module provides access to JSON-RPC 2.0 services (operating over
+   TCP/Netstrings) in accordance with
+   http://www.jsonrpc.org/specification. It uses JANSSON library for JSON
+   document management.
+
+   It uses t_suspend() and t_continue() from the TM module.
+
+   Note that after invoking an asyncronous operation, the processing will
+   continue later, in another application process. Therefore, do not rely
+   on variables stored in private memory, use shared memory if you want to
+   get values after the processing is resumend (e.g., $shv(...) or htable
+   $sht(...)).
+
+2. Dependencies
+
+   2.1. Kamailio Modules
+   2.2. External Libraries or Applications
+
+2.1. Kamailio Modules
+
+   The following modules must be loaded before this module:
+     * jansson - jansson json handling.
+     * tm - transaction management.
+
+2.2. External Libraries or Applications
+
+   The following libraries or applications must be installed before
+   running Kamailio with this module loaded:
+     * jansson (http://www.digip.org/jansson/), tested with: 2.2+
+     * libevent 2.0.5+ (http://libevent.org/), tested with: 2.0.16
+
+3. Parameters
+
+   3.1. min_srv_ttl (integer)
+   3.2. result_pv (string)
+   3.3. server (string)
+   3.4. retry_codes (string)
+
+3.1. min_srv_ttl (integer)
+
+   The minimum acceptable TTL in seconds for SRV DNS entries. This means
+   that TTLs from the DNS will be ignored if they are lower than this
+   value. It cannot be set lower than 1 second.
+
+   Default is 5 seconds.
+
+   Example 1.1. Set min_srv_ttl parameter
+...
+modparam("janssonrpc-c", "min_srv_ttl", 30)
+...
+
+   This will set any SRV TTL lower than 30 seconds to 30 seconds.
+
+3.2. result_pv (string)
+
+   The PV spec where to store the result of a call to
+   janssonrpc_request(). It can be any writtable PV.
+
+   Default value is "$var(jsrpc_result)".
+
+   Example 1.2. Set result_pv parameter
+...
+modparam("janssonrpc-c", "result_pv", "$var(result)")
+...
+
+3.3. server (string)
+
+   The server providing the remote jsonrpc service. Format can be
+   "conn=example;addr=localhost;port=9999;priority=10;weight=20" or
+   "conn=bar;srv=_sip._tcp.example.net".
+
+     * conn - name for a collection of servers (required).
+     * srv - DNS SRV domain name (optional).
+     * addr - host address (required, except when using srv).
+     * port - host port (required, except when using srv).
+     * priority - server are grouped by priority. Servers with higher
+       priority (lower number) are used first. Default is 0. (optional
+       when using addr, invalid otherwise).
+     * weight - functions the same as a DNS SRV weight. Requests are
+       distributed between servers of the same priority proportional to
+       their weight. Default is 1. (optional when using addr, invalid
+       otherwise).
+
+   Example 1.3. Set server parameter
+...
+modparam("janssonrpc-c", "server", "conn=tests;srv=_test1._tcp.example.net");
+modparam("janssonrpc-c", "server", "conn=tests;srv=_test2._tcp.example.net");
+modparam("janssonrpc-c", "server", "conn=local;addr=localhost;port=8080;priority
+=10;weight=10");
+modparam("janssonrpc-c", "server", "conn=user_db;addr=rpc.prod.exmaple.net;port=
+5060;priority=10;weight=10");
+...
+
+3.4. retry_codes (string)
+
+   A comma delimited list of error codes or error code ranges to
+   automatically schedule a request retry if received.
+
+   This will only be used if there is no route specified for the request.
+
+   An error code can be any interger, but is typically a negative number.
+
+   An error code range is delimited by ".." . For example,
+   "-32099..-32000".
+
+   Spaces are ignored.
+
+   Example 1.4. Set retry_codes parameter
+...
+modparam("janssonrpc-s", "retry_codes", "-32603, -32000..-32099");
+...
+
+4. Functions
+
+   4.1. janssonrpc_notification(conn, method, parameters)
+   4.2. janssonrpc_request(conn, method, params[, options]])
+   4.3. Error Handling
+
+4.1. janssonrpc_notification(conn, method, parameters)
+
+     * conn - name for a collection of servers (required)
+     * method - jsonrpc method (required)
+     * params - jsonrpc request params (required) Use $null or empty
+       string to not send any parameters in the jsonrpc notification.
+
+   Unlike janssonrpc_request (below), notifications do not receive a
+   response. Script processing continues in the usual fashion as soon as
+   the notification has been sent.
+
+   If no servers can be reached, a message is sent to the logs.
+
+   The 'method' and 'params' can be a static string or dynamic string
+   value with config variables.
+
+   Example 1.5. janssonrpc_notification usage
+...
+janssonrpc_notification("user_db", "update_user", '{"id": 1234, "name": "Daniel"
+}');
+...
+
+4.2. janssonrpc_request(conn, method, params[, options]])
+
+   The conn, method, params, and options can be a static string or a
+   dynamic string value with config variables.
+
+     * conn - name for a collection of servers (required)
+     * method - jsonrpc method (required)
+     * params - jsonrpc request params (required) Use $null or empty
+       string to not send any parameters in the jsonrpc request.
+     * options
+       Options for the janssonrpc_request function. Format can be
+       "route=RESPONSE;retry=2;timeout=100". All these parameters are
+       optional.
+          + retry - number of times you retry a failed request. -1 means
+            retry forever. Default is 0. Request will be retried if they
+            either timeout or fail to send. Retries untilize exponential
+            back off between successive retries, up to 60 seconds. The
+            equation for time between retries is:
+            time = n^2 * timeout (for time < 60 seconds)
+            where n is the number of times a request has been tried.
+          + timeout - request timeout in milliseconds. Default is 500.
+          + route - resume script execution at this route.
+
+   When a response is received, processing continues for the SIP request
+   in the route specified.
+
+   If no route is specified, then any errors are logged and successes are
+   ignored. The function will also not interupt script execution.
+
+   Since the SIP request handling is resumed in another process, the
+   config file execution is lost. Only shared variables ($shv, $avp, etc)
+   should be used for any value that will be needed when the script is
+   resumed.
+
+   The result is stored in the pseudo-variable specified in the module
+   parameter 'result_pv'. This pseudo-variable is set after the response
+   is received.
+
+   Example 1.6. janssonrpc_request usage
+...
+janssonrpc_request("user_db", "get_user", '{"id": 1234}', "route=RESPONSE;retry=
+1");
+        ...
+
+route[RESPONSE] {
+        xlog("Result received: $var(result)");
+        ...
+}
+...
+
+4.3. Error Handling
+
+   When a route is specified as part of the janssonrpc_request() function,
+   a JSON object is stored in the result pseudo-variable (see
+   'Parameters').
+
+   The JSON object can be accessed using the jansson_get() function from
+   the jansson module and is of the form:
+...
+{
+  "result" : {...},
+  "error": {...},
+  "internal_error": { "code": ..., "message": ..., "data": ... }
+}
+...
+
+   'result' or 'error' come from the server and should follow the JSONRPC
+   specification. Keep in mind a server's 'error' might not follow the
+   JSONRPC specification and not include a 'code' and/or 'message', so be
+   sure to check that they are there before trying to use them.
+
+   When 'internal_error' is present, that means there was a problem with
+   sending or receiving the request. 'internal_error' contains a 'code'
+   which is an integer representing the type of error, a 'message' which
+   is the error in string form, and possibly 'data' which is usually the
+   failed request, which is optional and can be useful for debugging.
+
+   Here are the possible values for internal error codes:
+     * -1: "Failed to build request"
+     * -5: "Failed to send request"
+     * -10: "JSON parse error"
+     * -11: "Failed to convert response to a pseudo-variable"
+     * -20: "Bad response from server"
+     * -50: "Request retry failed"
+     * -75: "Request dropped for server disconnection"
+     * -100: "Message timeout"
+     * -1000: "There is a bug". Please report these errors to the module
+       maintainers.
+
+   Example 1.7. route example with internal_error handling
+...
+route {
+        janssonrpc_request("user_db", "get_user", '{"id": 1234}', "route=RESPONS
+E;retry=1");
+}
+
+route[RESPONSE] {
+        if(jansson_get($var(jsrpc_result), "internal_error", "$var(internal)"))
+{
+                route(INTERNAL);
+        } else if(jansson_get($var(jsrpc_result), "error", "$var(error)")) {
+                route(ERROR);
+        } else if(jansson_get($var(jsrpc_result), "result", "$var(result)")) {
+                route(RESULT);
+        }
+    t_reply("200", "OK");
+}
+
+route[RESULT] {
+        xlog("result is $var(result)\n");
+        xlog("success\n");
+}
+
+route[ERROR] {
+        xlog("There was an error\n");
+        if(jansson_get($var(error), "code", "$var(c)")) {
+                xlog("code is $var(c)\n");
+        }
+
+        if(jansson_get($var(error), "message", "$var(r)")) {
+                xlog("error is $var(r)\n");
+        }
+
+        if(jansson_get($var(error), "data", "$var(d)")) {
+                xlog("data is $var(d)\n");
+        }
+}
+
+route[INTERNAL] {
+        xlog("There was an internal error\n");
+
+        jansson_get($var(internal), "code", "$var(c)");
+        xlog("code is $var(c)\n");
+
+        jansson_get($var(internal), "message", "$var(r)");
+        xlog("error is $var(r)\n");
+
+        if(jansson_get($var(internal), "data", "$var(d)")) {
+                xlog("request is $var(d)\n");
+        }
+}
+...
diff --git a/modules/janssonrpc-c/doc/Makefile b/modules/janssonrpc-c/doc/Makefile
new file mode 100644
index 0000000..d7e5694
--- /dev/null
+++ b/modules/janssonrpc-c/doc/Makefile
@@ -0,0 +1,4 @@
+docs = janssonrpc-c.xml
+
+docbook_dir = ../../../docbook
+include $(docbook_dir)/Makefile.module
diff --git a/modules/janssonrpc-c/doc/janssonrpc-c.xml b/modules/janssonrpc-c/doc/janssonrpc-c.xml
new file mode 100644
index 0000000..13db606
--- /dev/null
+++ b/modules/janssonrpc-c/doc/janssonrpc-c.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding='ISO-8859-1'?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+<!-- Include general documentation entities -->
+<!ENTITY % docentities SYSTEM "../../../docbook/entities.xml">
+%docentities;
+
+]>
+
+<book xmlns:xi="http://www.w3.org/2001/XInclude">
+	<bookinfo>
+	<title>janssonrpc-c Module</title>
+	<productname class="trade">sip-router.org</productname>
+	<authorgroup>
+		<author>
+			<firstname>Joe</firstname>
+			<surname>Hillenbrand</surname>
+			<email>joe at flowroute.com</email>
+		</author>
+		<editor>
+			<firstname>Matthew</firstname>
+			<surname>Williams</surname>
+			<email>matthew at flowroute.com</email>
+		</editor>
+	</authorgroup>
+	<copyright>
+		<year>2013</year>
+		<holder>Flowroute LLC (flowroute.com)</holder>
+	</copyright>
+	</bookinfo>
+	<toc></toc>
+
+	<xi:include href="janssonrpc-c_admin.xml"/>
+
+</book>
diff --git a/modules/janssonrpc-c/doc/janssonrpc-c_admin.xml b/modules/janssonrpc-c/doc/janssonrpc-c_admin.xml
new file mode 100644
index 0000000..27f0f45
--- /dev/null
+++ b/modules/janssonrpc-c/doc/janssonrpc-c_admin.xml
@@ -0,0 +1,408 @@
+<?xml version="1.0" encoding='ISO-8859-1'?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+<!-- Include general documentation entities -->
+<!ENTITY % docentities SYSTEM "../../../docbook/entities.xml">
+%docentities;
+
+]>
+<!-- Module User's Guide -->
+
+<chapter>
+
+	<title>&adminguide;</title>
+
+	<section>
+		<title>Overview</title>
+		<para>
+			This module provides access to JSON-RPC 2.0 services (operating over TCP/Netstrings)
+			in accordance with http://www.jsonrpc.org/specification. It uses JANSSON library for
+			JSON document management.
+		</para>
+		<para>
+			It uses t_suspend() and t_continue() from the TM module.
+		</para>
+		<para>
+			Note that after invoking an asyncronous operation, the processing
+			will continue later, in another application process. Therefore, do not
+			rely on variables stored in private memory, use shared memory if you
+			want to get values after the processing is resumend (e.g., $shv(...)
+			or htable $sht(...)).
+		</para>
+	</section>
+
+	<section>
+		<title>Dependencies</title>
+		<section>
+			<title>&kamailio; Modules</title>
+			<para>
+				The following modules must be loaded before this module:
+				<itemizedlist>
+					<listitem>
+						<emphasis>jansson</emphasis> - jansson json handling.
+					</listitem>
+					<listitem>
+						<emphasis>tm</emphasis> - transaction management.
+					</listitem>
+				</itemizedlist>
+			</para>
+		</section>
+		<section>
+			<title>External Libraries or Applications</title>
+			<para>
+				The following libraries or applications must be installed before running
+				&kamailio; with this module loaded:
+				<itemizedlist>
+					<listitem>
+						<emphasis>jansson (http://www.digip.org/jansson/)</emphasis>, tested with: 2.2+
+					</listitem>
+					<listitem>
+						<para>
+							<emphasis>libevent 2.0.5+ (http://libevent.org/)</emphasis>, tested with: 2.0.16
+						</para>
+					</listitem>
+				</itemizedlist>
+			</para>
+		</section>
+	</section>
+	<section>
+		<title>Parameters</title>
+		<section>
+			<title><varname>min_srv_ttl</varname> (integer)</title>
+			<para>
+				The minimum acceptable TTL in seconds for SRV DNS entries. This means that TTLs from the DNS will be ignored if they are lower than this value. It cannot be set lower than 1 second.
+			</para>
+			<para>
+			<emphasis>
+				Default is 5 seconds.
+			</emphasis>
+			</para>
+			<example>
+			<title>Set <varname>min_srv_ttl</varname> parameter</title>
+			<programlisting format="linespecific">
+...
+modparam("janssonrpc-c", "min_srv_ttl", 30)
+...
+			</programlisting>
+			<para>
+				This will set any SRV TTL lower than 30 seconds to 30 seconds.
+			</para>
+			</example>
+		</section>
+		<section>
+			<title><varname>result_pv</varname> (string)</title>
+			<para>
+				The PV spec where to store the result of a call to janssonrpc_request(). It can be any writtable PV.
+			</para>
+			<para>
+			<emphasis>
+				Default value is <quote>$var(jsrpc_result)</quote>.
+			</emphasis>
+			</para>
+			<example>
+			<title>Set <varname>result_pv</varname> parameter</title>
+			<programlisting format="linespecific">
+...
+modparam("janssonrpc-c", "result_pv", "$var(result)")
+...
+			</programlisting>
+		</example>
+		</section>
+		<section>
+			<title><varname>server</varname> (string)</title>
+			<para>
+				The server providing the remote jsonrpc service. Format can be "conn=example;addr=localhost;port=9999;priority=10;weight=20" or "conn=bar;srv=_sip._tcp.example.net".
+			</para>
+			<para>
+				<itemizedlist>
+					<listitem>
+						<emphasis>conn</emphasis> - name for a collection of servers (required).
+					</listitem>
+					<listitem>
+						<emphasis>srv</emphasis> - DNS SRV domain name (optional).
+					</listitem>
+					<listitem>
+						<emphasis>addr</emphasis> - host address (required, except when using srv).
+					</listitem>
+					<listitem>
+						<emphasis>port</emphasis> - host port (required, except when using srv).
+					</listitem>
+					<listitem>
+						<emphasis>priority</emphasis> - server are grouped by priority. Servers with higher priority (lower number) are used first. Default is 0. (optional when using addr, invalid otherwise).
+					</listitem>
+					<listitem>
+						<emphasis>weight</emphasis> - functions the same as a DNS SRV weight. Requests are distributed between servers of the same priority proportional to their weight. Default is 1. (optional when using addr, invalid otherwise).
+					</listitem>
+				</itemizedlist>
+			</para>
+			<example>
+				<title>Set <varname>server</varname> parameter</title>
+				<programlisting format="linespecific">
+...
+modparam("janssonrpc-c", "server", "conn=tests;srv=_test1._tcp.example.net");
+modparam("janssonrpc-c", "server", "conn=tests;srv=_test2._tcp.example.net");
+modparam("janssonrpc-c", "server", "conn=local;addr=localhost;port=8080;priority=10;weight=10");
+modparam("janssonrpc-c", "server", "conn=user_db;addr=rpc.prod.exmaple.net;port=5060;priority=10;weight=10");
+...
+				</programlisting>
+			</example>
+		</section>
+		<section>
+			<title><varname>retry_codes</varname> (string)</title>
+			<para>
+				A comma delimited list of error codes or error code ranges to automatically schedule a request retry if received.
+			</para>
+			<para>
+				This will only be used if there is no route specified for the request.
+			</para>
+			<para>
+				An error code can be any interger, but is typically a negative number.
+			</para>
+			<para>
+				An error code range is delimited by "<emphasis>..</emphasis>" . For example, "-32099..-32000".
+			</para>
+			<para>
+				Spaces are ignored.
+			</para>
+			<example>
+				<title>Set <varname>retry_codes</varname> parameter</title>
+				<programlisting format="linespecific">
+...
+modparam("janssonrpc-s", "retry_codes", "-32603, -32000..-32099");
+...
+				</programlisting>
+			</example>
+		</section>
+	</section>
+	<section>
+		<title>Functions</title>
+		<section>
+			<title>
+				<function moreinfo="none">janssonrpc_notification(conn, method, parameters)</function>
+			</title>
+			<para>
+				<itemizedlist>
+					<listitem>
+						<emphasis>conn</emphasis> - name for a collection of servers (required)
+					</listitem>
+					<listitem>
+						<emphasis>method</emphasis> - jsonrpc method (required)
+					</listitem>
+					<listitem>
+						<emphasis>params</emphasis> - jsonrpc request params (required)
+						Use $null or empty string to not send any parameters in the jsonrpc notification.
+					</listitem>
+				</itemizedlist>
+			</para>
+			<para>
+				Unlike janssonrpc_request (below), notifications do not receive a response.
+				Script processing continues in the usual fashion as soon as the notification
+				has been sent.
+			</para>
+			<para>
+				If no servers can be reached, a message is sent to the logs.
+			</para>
+			<para>
+				The 'method' and 'params' can be a static string or dynamic string value with
+				config variables.
+			</para>
+			<example>
+				<title><function>janssonrpc_notification</function> usage</title>
+				<programlisting format="linespecific">
+...
+janssonrpc_notification("user_db", "update_user", '{"id": 1234, "name": "Daniel"}');
+...
+				</programlisting>
+			</example>
+		</section>
+		<section>
+			<title>
+				<function moreinfo="none">janssonrpc_request(conn, method, params[, options]])</function>
+			</title>
+			<para>
+				The conn, method, params, and options can be a static string or
+				a dynamic string value with config variables.
+			</para>
+			<para>
+				<itemizedlist>
+					<listitem>
+						<emphasis>conn</emphasis> - name for a collection of servers (required)
+					</listitem>
+					<listitem>
+						<emphasis>method</emphasis> - jsonrpc method (required)
+					</listitem>
+					<listitem>
+						<emphasis>params</emphasis> - jsonrpc request params (required)
+						Use $null or empty string to not send any parameters in the jsonrpc request.
+					</listitem>
+					<listitem>
+						<para><emphasis>options</emphasis></para>
+						<para>
+							Options for the janssonrpc_request function. Format can be "route=RESPONSE;retry=2;timeout=100".
+							All these parameters are optional.
+						</para>
+						<para>
+							<itemizedlist>
+								<listitem>
+									<emphasis>retry</emphasis> - number of times you retry a failed request. 
+									-1 means retry forever. Default is 0.
+									Request will be retried if they either timeout or fail to send.
+									Retries untilize exponential back off between successive retries,
+									up to 60 seconds. The equation for time between retries is:
+									<para>
+									time = n^2 * timeout (for time < 60 seconds)
+									</para>
+									 where n is the number of times a request has been tried.
+								</listitem>
+								<listitem>
+									<emphasis>timeout</emphasis> - request timeout in milliseconds. Default is 500.
+								</listitem>
+								<listitem>
+									<emphasis>route</emphasis> - resume script execution at this route.
+								</listitem>
+							</itemizedlist>
+						</para>
+					</listitem>
+				</itemizedlist>
+			</para>
+			<para>
+				When a response is received, processing continues for the SIP request in the route specified.
+			</para>
+			<para>
+				If no route is specified, then any errors are logged and successes are ignored.
+				The function will also not interupt script execution.
+			</para>
+			<para>
+				Since the SIP request handling is resumed in another process,
+				the config file execution is lost. Only shared variables ($shv, $avp, etc)
+				should be used for any value that will be needed when the script is resumed.
+			</para>
+			<para>
+				The result is stored in the pseudo-variable specified in the module parameter 'result_pv'.
+				This pseudo-variable is set <emphasis>after</emphasis> the response is received.
+			</para>
+			<example>
+				<title><function>janssonrpc_request</function> usage</title>
+				<programlisting format="linespecific">
+...
+janssonrpc_request("user_db", "get_user", '{"id": 1234}', "route=RESPONSE;retry=1");
+	...
+
+route[RESPONSE] {
+	xlog("Result received: $var(result)");
+	...
+}
+...
+				</programlisting>
+			</example>
+		</section>
+		<section>
+			<title>
+				Error Handling
+			</title>
+			<para>
+				When a route is specified as part of the janssonrpc_request() function,
+				a JSON object is stored in the result pseudo-variable (see 'Parameters').
+			</para>
+			<para>
+				The JSON object can be accessed using the jansson_get() function
+				from the jansson module and is of the form:
+				<programlisting format="linespecific">
+...
+{
+  "result" : {...},
+  "error": {...},
+  "internal_error": { "code": ..., "message": ..., "data": ... }
+}
+...
+				</programlisting>
+			</para>
+			<para>
+				'result' or 'error' come from the server and should follow the
+				JSONRPC specification.  Keep in mind a server's 'error' might
+				not follow the JSONRPC specification and not include a 'code'
+				and/or 'message', so be sure to check that they are there
+				before trying to use them.
+			</para>
+			<para>
+				When 'internal_error' is present, that means there was a
+				problem with sending or receiving the request. 'internal_error'
+				contains a 'code' which is an integer representing the type of
+				error, a 'message' which is the error in string form, and
+				possibly 'data' which is usually the failed request, which is
+				optional and can be useful for debugging.
+			</para>
+			<para>
+				Here are the possible values for internal error codes:
+				<itemizedlist>
+					<listitem><emphasis>-1</emphasis>: "Failed to build request"</listitem>
+					<listitem><emphasis>-5</emphasis>: "Failed to send request"</listitem>
+					<listitem><emphasis>-10</emphasis>: "JSON parse error"</listitem>
+					<listitem><emphasis>-11</emphasis>: "Failed to convert response to a pseudo-variable"</listitem>
+					<listitem><emphasis>-20</emphasis>: "Bad response from server"</listitem>
+					<listitem><emphasis>-50</emphasis>: "Request retry failed"</listitem>
+					<listitem><emphasis>-75</emphasis>: "Request dropped for server disconnection"</listitem>
+					<listitem><emphasis>-100</emphasis>: "Message timeout"</listitem>
+					<listitem><emphasis>-1000</emphasis>: "There is a bug". Please report these errors to the module maintainers.</listitem>
+				</itemizedlist>
+			</para>
+			<example>
+				<title>route example with internal_error handling</title>
+				<programlisting format="linespecific">
+...
+route {
+	janssonrpc_request("user_db", "get_user", '{"id": 1234}', "route=RESPONSE;retry=1");
+}
+
+route[RESPONSE] {
+	if(jansson_get($var(jsrpc_result), "internal_error", "$var(internal)")) {
+		route(INTERNAL);
+	} else if(jansson_get($var(jsrpc_result), "error", "$var(error)")) {
+		route(ERROR);
+	} else if(jansson_get($var(jsrpc_result), "result", "$var(result)")) {
+		route(RESULT);
+	}
+    t_reply("200", "OK");
+}
+
+route[RESULT] {
+	xlog("result is $var(result)\n");
+	xlog("success\n");
+}
+
+route[ERROR] {
+	xlog("There was an error\n");
+	if(jansson_get($var(error), "code", "$var(c)")) {
+		xlog("code is $var(c)\n");
+	}
+
+	if(jansson_get($var(error), "message", "$var(r)")) {
+		xlog("error is $var(r)\n");
+	}
+
+	if(jansson_get($var(error), "data", "$var(d)")) {
+		xlog("data is $var(d)\n");
+	}
+}
+
+route[INTERNAL] {
+	xlog("There was an internal error\n");
+
+	jansson_get($var(internal), "code", "$var(c)");
+	xlog("code is $var(c)\n");
+
+	jansson_get($var(internal), "message", "$var(r)");
+	xlog("error is $var(r)\n");
+
+	if(jansson_get($var(internal), "data", "$var(d)")) {
+		xlog("request is $var(d)\n");
+	}
+}
+...
+				</programlisting>
+			</example>
+		</section>
+	</section>
+</chapter>
+
diff --git a/modules/janssonrpc-c/janssonrpc.h b/modules/janssonrpc-c/janssonrpc.h
new file mode 100644
index 0000000..cfdf5e3
--- /dev/null
+++ b/modules/janssonrpc-c/janssonrpc.h
@@ -0,0 +1,137 @@
+/**
+ * Copyright (C) 2013 Flowroute LLC (flowroute.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef _JANSSONRPC_H_
+#define _JANSSONRPC_H_
+
+#ifdef TEST
+
+#include "unit_tests/test.h"
+
+#else
+
+#include "../../sr_module.h"
+#include "../jansson/jansson_utils.h"
+jansson_to_val_f jsontoval;
+pv_spec_t jsonrpc_result_pv;
+
+#endif
+
+#define JSONRPC_VERSION "2.0"
+
+#define JSONRPC_INTERNAL_SERVER_ERROR -32603
+#define JSONRPC_ERROR_NO_MEMORY -1;
+
+/* DEFAULTS */
+/* time (in ms) after which the error route is called */
+#define JSONRPC_DEFAULT_TIMEOUT     500
+#define JSONRPC_RESULT_STR "$var(jsrpc_result)"
+#define JSONRPC_DEFAULT_RETRY       0
+
+/* helpful macros */
+#define CHECK_MALLOC_VOID(p)  if(!(p)) {ERR("Out of memory!\n"); return;}
+#define CHECK_MALLOC(p)  if(!(p)) {ERR("Out of memory!\n"); return JSONRPC_ERROR_NO_MEMORY;}
+#define CHECK_MALLOC_NULL(p)  if(!(p)) {ERR("Out of memory!\n"); return NULL;}
+#define CHECK_MALLOC_GOTO(p,loc)  if(!(p)) {ERR("Out of memory!\n"); goto loc;}
+#define CHECK_AND_FREE(p) if((p)!=NULL) shm_free(p)
+#define CHECK_AND_FREE_EV(p) \
+	if((p) && event_initialized((p))) {\
+		event_del(p); \
+		event_free(p); \
+		p = NULL; \
+	}
+
+#define STR(ss) (ss).len, (ss).s
+/* The lack of parens is intentional; this is intended to be used in a list
+ * of multiple arguments.
+ *
+ * Usage: printf("my str %.*s", STR(mystr))
+ *
+ * Expands to: printf("my str %.*s", (mystr).len, (mystr).s)
+ * */
+
+
+#define PIT_MATCHES(param) \
+	(pit->name.len == sizeof((param))-1 && \
+		strncmp(pit->name.s, (param), sizeof((param))-1)==0)
+
+#include <jansson.h>
+#include <event.h>
+
+typedef void (*libev_cb_f)(int sock, short flags, void *arg);
+
+typedef struct retry_range {
+	int start;
+	int end;
+	struct retry_range* next;
+} retry_range_t;
+
+/* globals */
+int cmd_pipe;
+extern const str null_str;
+str result_pv_str;
+retry_range_t* global_retry_ranges;
+
+static inline str pkg_strdup(str src)
+{
+	str res;
+
+	if (!src.s) {
+		res.s = NULL;
+		res.len = 0;
+	} else if (!(res.s = (char *) pkg_malloc(src.len + 1))) {
+		res.len = 0;
+	} else {
+		strncpy(res.s, src.s, src.len);
+		res.s[src.len] = 0;
+		res.len = src.len;
+	}
+	return res;
+}
+
+static inline str shm_strdup(str src)
+{
+	str res;
+
+	if (!src.s) {
+		res.s = NULL;
+		res.len = 0;
+	} else if (!(res.s = (char *) shm_malloc(src.len + 1))) {
+		res.len = 0;
+	} else {
+		strncpy(res.s, src.s, src.len);
+		res.s[src.len] = 0;
+		res.len = src.len;
+	}
+	return res;
+}
+
+static inline struct timeval ms_to_tv(unsigned int time)
+{
+	struct timeval tv = {0,0};
+	tv.tv_sec = time/1000;
+	tv.tv_usec = ((time % 1000) * 1000);
+	return tv;
+}
+
+
+#endif /* _JSONRPC_H_ */
diff --git a/modules/janssonrpc-c/janssonrpc_connect.c b/modules/janssonrpc-c/janssonrpc_connect.c
new file mode 100644
index 0000000..bfe66c9
--- /dev/null
+++ b/modules/janssonrpc-c/janssonrpc_connect.c
@@ -0,0 +1,317 @@
+/**
+ * Copyright (C) 2013 Flowroute LLC (flowroute.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <string.h>
+#include <fcntl.h>
+#include <event.h>
+
+#include "../../sr_module.h"
+#include "../../route.h"
+#include "../../route_struct.h"
+#include "../../resolve.h"
+#include "../../parser/parse_param.h"
+#include "../../mem/mem.h"
+#include "../../lvalue.h"
+
+#include "netstring.h"
+#include "janssonrpc.h"
+#include "janssonrpc_request.h"
+#include "janssonrpc_io.h"
+#include "janssonrpc_srv.h"
+#include "janssonrpc_server.h"
+#include "janssonrpc_connect.h"
+
+void wait_server_backoff(unsigned int timeout /* seconds */,
+		jsonrpc_server_t* server, bool delay);
+
+void bev_connect(jsonrpc_server_t* server);
+
+void bev_disconnect(struct bufferevent* bev)
+{
+	// close bufferevent
+	if(bev != NULL) {
+		short enabled = bufferevent_get_enabled(bev);
+		if(EV_READ & enabled)
+			bufferevent_disable(bev, EV_READ);
+		if(EV_WRITE & enabled)
+			bufferevent_disable(bev, EV_WRITE);
+		bufferevent_free(bev);
+		bev = NULL;
+	}
+}
+
+
+/* This will immediately close a server socket and clean out any pending
+ * requests that are waiting on that socket.
+ * */
+void force_disconnect(jsonrpc_server_t* server)
+{
+	if(!server) {
+		ERR("Trying to disconnect a NULL server.\n");
+		return;
+	}
+
+	// clear the netstring buffer when disconnecting
+	free_netstring(server->buffer);
+	server->buffer = NULL;
+
+	server->status = JSONRPC_SERVER_DISCONNECTED;
+
+	// close bufferevent
+	bev_disconnect(server->bev);
+	INFO("Disconnected from server %.*s:%d for conn %.*s.\n",
+			STR(server->addr), server->port, STR(server->conn));
+
+
+	/* clean out requests */
+	jsonrpc_request_t* req = NULL;
+	int key = 0;
+	for (key=0; key < JSONRPC_DEFAULT_HTABLE_SIZE; key++) {
+		for (req = request_table[key]; req != NULL; req = req->next) {
+			if(req->server != NULL && req->server == server) {
+				fail_request(JRPC_ERR_SERVER_DISCONNECT, req,
+						"Failing request for server shutdown");
+			}
+		}
+	}
+}
+
+typedef struct server_backoff_args {
+	struct event* ev;
+	jsonrpc_server_t* server;
+	unsigned int timeout;
+} server_backoff_args_t;
+
+void server_backoff_cb(int fd, short event, void *arg)
+{
+	if(!arg)
+		return;
+
+	server_backoff_args_t* a = (server_backoff_args_t*)arg;
+	if(!a)
+		return;
+
+	unsigned int timeout = a->timeout;
+
+	/* exponential backoff */
+	if(timeout < 1) {
+		timeout = 1;
+	} else {
+		timeout = timeout * 2;
+		if(timeout > 60) {
+			timeout = 60;
+		}
+	}
+
+	close(fd);
+	CHECK_AND_FREE_EV(a->ev);
+	pkg_free(arg);
+
+	wait_server_backoff(timeout, a->server, false);
+}
+
+void wait_server_backoff(unsigned int timeout /* seconds */,
+		jsonrpc_server_t* server, bool delay)
+{
+	if(!server) {
+		ERR("Trying to close/reconnect a NULL server\n");
+		return;
+	}
+
+	if(delay == false) {
+		if (requests_using_server(server) <= 0) {
+			if(server->status == JSONRPC_SERVER_RECONNECTING) {
+				bev_connect(server);
+			} else if(server->status == JSONRPC_SERVER_CLOSING) {
+				close_server(server);
+			}
+			return;
+		}
+	}
+
+	const struct timeval tv = {timeout, 0};
+
+	server_backoff_args_t* args = pkg_malloc(sizeof(server_backoff_args_t));
+	CHECK_MALLOC_VOID(args);
+	memset(args, 0, sizeof(server_backoff_args_t));
+
+	args->ev = evtimer_new(global_ev_base, server_backoff_cb, (void*)args);
+	CHECK_MALLOC_GOTO(args->ev, error);
+
+	args->server = server;
+	args->timeout = timeout;
+
+	if(evtimer_add(args->ev, &tv)<0) {
+		ERR("event_add failed while setting request timer (%s).", strerror(errno));
+		goto error;
+	}
+
+	return;
+
+error:
+	ERR("schedule_server failed.\n");
+
+	if(args) {
+		if(args->ev) {
+			evtimer_del(args->ev);
+		}
+		pkg_free(args);
+	}
+
+	if (server->status == JSONRPC_SERVER_CLOSING) {
+		ERR("Closing server now...\n");
+		close_server(server);
+	} else if (server->status == JSONRPC_SERVER_RECONNECTING) {
+		ERR("Reconnecting server now...\n");
+		force_reconnect(server);
+	}
+}
+
+void wait_close(jsonrpc_server_t* server)
+{
+	if(!server) {
+		ERR("Trying to close null server.\n");
+		return;
+	}
+
+	server->status = JSONRPC_SERVER_CLOSING;
+	wait_server_backoff(1, server, false);
+}
+
+void wait_reconnect(jsonrpc_server_t* server)
+{
+	if(!server) {
+		ERR("Trying to reconnect null server.\n");
+		return;
+	}
+
+	server->status = JSONRPC_SERVER_RECONNECTING;
+	wait_server_backoff(1, server, false);
+}
+
+void connect_servers(jsonrpc_server_group_t** group)
+{
+	INIT_SERVER_LOOP
+	FOREACH_SERVER_IN(group)
+		server = wgroup->server;
+		if(server->status != JSONRPC_SERVER_FAILURE
+				&& server->status != JSONRPC_SERVER_RECONNECTING)
+		{
+			bev_connect(server);
+		}
+	ENDFOR
+}
+
+void force_reconnect(jsonrpc_server_t* server)
+{
+	INFO("Reconnecting to server %.*s:%d for conn %.*s.\n",
+			STR(server->addr), server->port, STR(server->conn));
+	force_disconnect(server);
+	bev_connect(server);
+}
+
+/* helper for bev_connect_cb() and bev_connect() */
+void connect_failed(jsonrpc_server_t* server)
+{
+	bev_disconnect(server->bev);
+
+	server->status = JSONRPC_SERVER_RECONNECTING;
+	wait_server_backoff(JSONRPC_RECONNECT_INTERVAL, server, true);
+}
+
+void bev_connect_cb(struct bufferevent* bev, short events, void* arg)
+{
+	jsonrpc_server_t* server = (jsonrpc_server_t*)arg;
+	if(!arg) {
+		ERR("Trying to connect null server\n");
+		return;
+	}
+
+	if (events & (BEV_EVENT_ERROR|BEV_EVENT_EOF)) {
+		WARN("Connection error for %.*s:%d\n", STR(server->addr), server->port);
+		if (events & BEV_EVENT_ERROR) {
+			int err = bufferevent_socket_get_dns_error(bev);
+			if(err) {
+				ERR("DNS error for %.*s: %s\n",
+					STR(server->addr), evutil_gai_strerror(err));
+			}
+		}
+		goto failed;
+	} else if(events & BEV_EVENT_CONNECTED) {
+
+		if (server->status == JSONRPC_SERVER_CONNECTED) {
+			return;
+		}
+
+		server->status = JSONRPC_SERVER_CONNECTED;
+		INFO("Connected to host %.*s:%d\n",
+				STR(server->addr), server->port);
+	}
+
+	return;
+
+failed:
+	connect_failed(server);
+}
+
+void bev_connect(jsonrpc_server_t* server)
+{
+	if(!server) {
+		ERR("Trying to connect null server\n");
+		return;
+	}
+
+	INFO("Connecting to server %.*s:%d for conn %.*s.\n",
+			STR(server->addr), server->port, STR(server->conn));
+
+	server->bev = bufferevent_socket_new(
+			global_ev_base,
+			-1,
+			BEV_OPT_CLOSE_ON_FREE);
+	if(!(server->bev)) {
+		ERR("Could not create bufferevent for  %.*s:%d\n", STR(server->addr), server->port);
+		connect_failed(server);
+		return;
+	}
+
+	bufferevent_setcb(
+			server->bev,
+			bev_read_cb,
+			NULL,
+			bev_connect_cb,
+			server);
+	bufferevent_enable(server->bev, EV_READ|EV_WRITE);
+	if(bufferevent_socket_connect_hostname(
+			server->bev,
+			global_evdns_base,
+			AF_UNSPEC,
+			server->addr.s,
+			server->port)<0) {
+		WARN("Failed to connect to %.*s:%d\n", STR(server->addr), server->port);
+		connect_failed(server);
+	}
+}
+
diff --git a/modules/janssonrpc-c/janssonrpc_connect.h b/modules/janssonrpc-c/janssonrpc_connect.h
new file mode 100644
index 0000000..a9ce8e4
--- /dev/null
+++ b/modules/janssonrpc-c/janssonrpc_connect.h
@@ -0,0 +1,49 @@
+/**
+ * Copyright (C) 2013 Flowroute LLC (flowroute.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef _JANSSONRPC_CONNECT_H_
+#define _JANSSONRPC_CONNECT_H_
+
+enum
+{ JSONRPC_SERVER_DISCONNECTED = 0
+, JSONRPC_SERVER_CONNECTED
+, JSONRPC_SERVER_CONNECTING
+, JSONRPC_SERVER_FAILURE
+, JSONRPC_SERVER_CLOSING
+, JSONRPC_SERVER_RECONNECTING
+};
+
+/* interval (in seconds) at which failed servers are retried */
+#define JSONRPC_RECONNECT_INTERVAL  3
+
+void force_disconnect(jsonrpc_server_t* server);
+/* Do not call force_disconnect() from outside the IO process.
+ * Server's have a bufferevent that is part of local memory and free'd
+ * at disconnect */
+
+void wait_close(jsonrpc_server_t* server);
+void wait_reconnect(jsonrpc_server_t* server);
+void connect_servers(jsonrpc_server_group_t** group);
+void force_reconnect(jsonrpc_server_t* server);
+void bev_connect(jsonrpc_server_t* server);
+
+#endif /* _JSONRPC_CONNECT_H_ */
diff --git a/modules/janssonrpc-c/janssonrpc_funcs.c b/modules/janssonrpc-c/janssonrpc_funcs.c
new file mode 100644
index 0000000..65b9b77
--- /dev/null
+++ b/modules/janssonrpc-c/janssonrpc_funcs.c
@@ -0,0 +1,265 @@
+/**
+ * Copyright (C) 2013 Flowroute LLC (flowroute.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "../../mod_fix.h"
+#include "../../pvar.h"
+#include "../../lvalue.h"
+#include "../tm/tm_load.h"
+
+#include "janssonrpc.h"
+#include "janssonrpc_request.h"
+#include "janssonrpc_io.h"
+#include "janssonrpc_funcs.h"
+
+
+struct tm_binds tmb;
+
+int jsonrpc_request(struct sip_msg* _m,
+		char* _conn,
+		char* _method,
+		char* _params,
+		char* _options)
+{
+	str conn;
+	str method;
+	str params;
+	str options;
+	str route;
+	param_hooks_t phooks;
+	param_t* pit=NULL;
+	param_t* freeme=NULL;
+	int retry;
+	int timeout;
+	int retval = -1;
+
+	/* defaults */
+	options = null_str;
+	route = null_str;
+	timeout = JSONRPC_DEFAULT_TIMEOUT;
+	retry = JSONRPC_DEFAULT_RETRY;
+
+	if (get_str_fparam(&conn, _m, (fparam_t*)_conn) != 0) {
+		ERR("cannot get connection value\n");
+		return -1;
+	}
+
+	if (get_str_fparam(&method, _m, (fparam_t*)_method) != 0) {
+		ERR("cannot get method value\n");
+		return -1;
+	}
+
+	if (get_str_fparam(&params, _m, (fparam_t*)_params) != 0) {
+		ERR("cannot get params value\n");
+		return -1;
+	}
+
+	if(_options == NULL) {
+
+	} else if (get_str_fparam(&options, _m, (fparam_t*)_options) != 0) {
+		ERR("cannot get options value\n");
+		return -1;
+
+	} else {
+		if(options.len == 0) {
+			goto skip_parse;
+		}else if (options.len > 0 && options.s[options.len-1] == ';') {
+			options.len--;
+		}
+
+		if (parse_params(&options, CLASS_ANY, &phooks, &pit)<0) {
+			ERR("failed parsing params value\n");
+			return -1;
+		}
+
+		freeme = pit;
+
+		for (; pit;pit=pit->next)
+		{
+			if PIT_MATCHES("route") {
+				route = pkg_strdup(pit->body);
+				CHECK_MALLOC_GOTO(route.s, end);
+
+			} else if PIT_MATCHES("timeout") {
+				timeout = atoi(pit->body.s);
+
+			} else if PIT_MATCHES("retry") {
+				retry = atoi(pit->body.s);
+
+			} else {
+				ERR("Unrecognized option: %.*s\n", STR(pit->name));
+				goto end;
+			}
+		}
+	}
+skip_parse:
+
+	/* check options */
+	if(timeout < 1) {
+		ERR("invalid timeout option (%d). Must be > 0.\n", timeout);
+		goto end;
+	}
+
+	if(retry < -1) {
+		ERR("invalid retry option (%d). Must be > -2.\n", retry);
+		goto end;
+	}
+
+	retval = 0;
+
+	retval = mod_jsonrpc_request(
+		_m,                     /* sip_msg */
+		conn,                   /* connection group */
+		method,                 /* RPC method */
+		params,                 /* JSON param */
+		route,                  /* result route */
+		false,                  /* notify only */
+		retry,                  /* retry attempts */
+		(unsigned int)timeout   /* request timeout */
+		);
+
+end:
+	if(freeme) free_params(freeme);
+	if(route.s) pkg_free(route.s);
+	return retval;
+}
+
+int jsonrpc_notification(struct sip_msg* _m,
+		char* _conn,
+		char* _method,
+		char* _params)
+{
+	str conn;
+	str method;
+	str params;
+
+	if (get_str_fparam(&conn, _m, (fparam_t*)_conn) != 0) {
+		ERR("cannot get connection value\n");
+		return -1;
+	}
+
+	if (get_str_fparam(&method, _m, (fparam_t*)_method) != 0) {
+		ERR("cannot get method value\n");
+		return -1;
+	}
+
+	if (get_str_fparam(&params, _m, (fparam_t*)_params) != 0) {
+		ERR("cannot get params value\n");
+		return -1;
+	}
+
+	return mod_jsonrpc_request(
+		_m,          /* sip_msg */
+		conn,        /* connection group */
+		method,      /* RPC method */
+		params,      /* JSON param */
+		null_str,    /* result route */
+		true,        /* notify only */
+		0,           /* retry attempts */
+		0            /* request timeout */
+		);
+}
+
+int mod_jsonrpc_request(
+		struct sip_msg* msg,
+		str conn,
+		str method,
+		str params,
+		str route,
+		bool notify_only,
+		int retry,
+		unsigned int timeout
+	)
+{
+	unsigned int hash_index;
+	unsigned int label;
+
+	if(retry < -1) {
+		ERR("retry can't be less than -1\n");
+		return -1;
+	}
+
+
+
+	jsonrpc_req_cmd_t* req_cmd = create_req_cmd();
+	CHECK_MALLOC(req_cmd);
+
+	req_cmd->conn   = shm_strdup(conn);
+	CHECK_MALLOC_GOTO(req_cmd->conn.s, error);
+
+	req_cmd->method = shm_strdup(method);
+	CHECK_MALLOC_GOTO(req_cmd->conn.s, error);
+
+	if(params.s) {
+		req_cmd->params = shm_strdup(params);
+		CHECK_MALLOC_GOTO(req_cmd->params.s, error);
+	}
+
+	if(route.s) {
+		req_cmd->route = shm_strdup(route);
+		CHECK_MALLOC_GOTO(req_cmd->route.s, error);
+	}
+
+	req_cmd->msg = msg;
+	req_cmd->retry = retry;
+	req_cmd->notify_only = notify_only;
+	req_cmd->timeout = timeout;
+
+	if(notify_only || route.len <= 0) {
+		req_cmd->route = null_str;
+		if(send_pipe_cmd(CMD_SEND, req_cmd)<0) goto error;
+		return 1; /* continue script execution */
+	}
+
+	tm_cell_t *t = 0;
+	t = tmb.t_gett();
+	if (t==NULL || t==T_UNDEFINED)
+	{
+		if(tmb.t_newtran(msg)<0)
+		{
+			ERR("cannot create the transaction\n");
+			goto error;
+		}
+		t = tmb.t_gett();
+		if (t==NULL || t==T_UNDEFINED)
+		{
+			ERR("cannot look up the transaction\n");
+			goto error;
+		}
+	}
+
+	if (tmb.t_suspend(msg, &hash_index, &label) < 0) {
+		ERR("t_suspend() failed\n");
+		goto error;
+	}
+	req_cmd->t_hash = hash_index;
+	req_cmd->t_label = label;
+
+	if(send_pipe_cmd(CMD_SEND, req_cmd)<0) goto error;
+
+	return 0;
+
+error:
+	free_req_cmd(req_cmd);
+	ERR("failed to send request to io process\n");
+	return -1;
+}
+
diff --git a/modules/janssonrpc-c/janssonrpc_funcs.h b/modules/janssonrpc-c/janssonrpc_funcs.h
new file mode 100644
index 0000000..755ba4e
--- /dev/null
+++ b/modules/janssonrpc-c/janssonrpc_funcs.h
@@ -0,0 +1,62 @@
+/**
+ * Copyright (C) 2013 Flowroute LLC (flowroute.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef _JANSSONRPC_FUNCS_H_
+#define _JANSSONRPC_FUNCS_H_
+
+#include <stdbool.h>
+#include "../../parser/msg_parser.h"
+
+int jsonrpc_request(struct sip_msg* _m,
+		char* _conn,
+		char* _method,
+		char* _params,
+		char* _options);
+
+int jsonrpc_notification(struct sip_msg* msg,
+		char* conn,
+		char* method,
+		char* params);
+
+int mod_jsonrpc_request(
+		struct sip_msg* msg,
+		str conn,
+		str method,
+		str params,
+		str route,
+		bool notify_only,
+		int retry,
+		unsigned int timeout
+	);
+
+typedef int (*mod_jsonrpc_request_f)(
+		struct sip_msg* msg,
+		str conn,
+		str method,
+		str params,
+		str route,
+		bool notify_only,
+		unsigned int retry,
+		unsigned int timeout
+	);
+
+#endif /* _JSONRPC_FUNCS_H_ */
diff --git a/modules/janssonrpc-c/janssonrpc_global.c b/modules/janssonrpc-c/janssonrpc_global.c
new file mode 100644
index 0000000..83192ca
--- /dev/null
+++ b/modules/janssonrpc-c/janssonrpc_global.c
@@ -0,0 +1,29 @@
+/**
+ * Copyright (C) 2013 Flowroute LLC (flowroute.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef TEST
+#include "../../sr_module.h"
+#else
+#include "unit_tests/test.h"
+#endif
+
+const str null_str = {0,0};
diff --git a/modules/janssonrpc-c/janssonrpc_io.c b/modules/janssonrpc-c/janssonrpc_io.c
new file mode 100644
index 0000000..0a4ebd6
--- /dev/null
+++ b/modules/janssonrpc-c/janssonrpc_io.c
@@ -0,0 +1,854 @@
+/**
+ * Copyright (C) 2013 Flowroute LLC (flowroute.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <string.h>
+#include <fcntl.h>
+#include <jansson.h>
+#include <event.h>
+#include <event2/dns.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <signal.h>
+
+#include "../../sr_module.h"
+#include "../../route.h"
+#include "../../mem/mem.h"
+#include "../../action.h"
+#include "../../route_struct.h"
+#include "../../lvalue.h"
+#include "../../rand/fastrand.h"
+#include "../tm/tm_load.h"
+#include "../jansson/jansson_utils.h"
+
+#include "janssonrpc.h"
+#include "janssonrpc_request.h"
+#include "janssonrpc_server.h"
+#include "janssonrpc_io.h"
+#include "janssonrpc_connect.h"
+#include "netstring.h"
+
+struct tm_binds tmb;
+
+void cmd_pipe_cb(int fd, short event, void *arg);
+void io_shutdown(int sig);
+
+int jsonrpc_io_child_process(int cmd_pipe)
+{
+	global_ev_base = event_base_new();
+	global_evdns_base = evdns_base_new(global_ev_base, 1);
+
+	set_non_blocking(cmd_pipe);
+	struct event* pipe_ev = event_new(global_ev_base, cmd_pipe, EV_READ | EV_PERSIST, cmd_pipe_cb, NULL);
+	if(!pipe_ev) {
+		ERR("Failed to create pipe event\n");
+		return -1;
+	}
+
+	if(event_add(pipe_ev, NULL)<0) {
+		ERR("Failed to start pipe event\n");
+		return -1;
+	}
+
+	connect_servers(global_server_group);
+
+#if 0
+	/* attach shutdown signal handler */
+	/* The shutdown handler are intended to clean up the remaining memory
+	 * in the IO process. However, catching the signals causes unpreditable
+	 * behavior in the Kamailio shutdown process, so this should be disabled
+	 * except when doing memory debugging. */
+	struct sigaction sa;
+	sigemptyset(&sa.sa_mask);
+	sa.sa_flags = 0;
+	sa.sa_handler = io_shutdown;
+	if(sigaction(SIGTERM, &sa, NULL) == -1) {
+		ERR("Failed to attach IO shutdown handler to SIGTERM\n");
+	} else if(sigaction(SIGINT, NULL, &sa) == -1) {
+		ERR("Failed to attach IO shutdown handler to SIGINT\n");
+	}
+#endif
+
+	if(event_base_dispatch(global_ev_base)<0) {
+		ERR("IO couldn't start event loop\n");
+		return -1;
+	}
+	return 0;
+}
+
+void io_shutdown(int sig)
+{
+	INFO("Shutting down JSONRPC IO process...\n");
+	lock_get(jsonrpc_server_group_lock); /* blocking */
+
+	INIT_SERVER_LOOP
+	FOREACH_SERVER_IN(global_server_group)
+		close_server(server);
+	ENDFOR
+
+	evdns_base_free(global_evdns_base, 0);
+	event_base_loopexit(global_ev_base, NULL);
+	event_base_free(global_ev_base);
+
+	lock_release(jsonrpc_server_group_lock);
+}
+
+int send_to_script(pv_value_t* val, jsonrpc_req_cmd_t* req_cmd)
+{
+	if(!(req_cmd)) return -1;
+
+	if(req_cmd->route.len <= 0) return -1;
+
+	jsonrpc_result_pv.setf(req_cmd->msg, &jsonrpc_result_pv.pvp, (int)EQ_T, val);
+
+	int n = route_lookup(&main_rt, req_cmd->route.s);
+	if(n<0) {
+		ERR("no such route: %s\n", req_cmd->route.s);
+		return -1;
+	}
+
+	struct action* route = main_rt.rlist[n];
+
+	if(tmb.t_continue(req_cmd->t_hash, req_cmd->t_label, route)<0) {
+		ERR("Failed to resume transaction\n");
+		return -1;
+	}
+	return 0;
+}
+
+json_t* internal_error(int code, json_t* data)
+{
+	json_t* ret = json_object();
+	json_t* inner = json_object();
+	char* message;
+
+	switch(code){
+	case JRPC_ERR_REQ_BUILD:
+		message = "Failed to build request";
+		break;
+	case JRPC_ERR_SEND:
+		message = "Failed to send";
+		break;
+	case JRPC_ERR_BAD_RESP:
+		message = "Bad response result";
+		json_object_set(ret, "data", data);
+		break;
+	case JRPC_ERR_RETRY:
+		message = "Retry failed";
+		break;
+	case JRPC_ERR_SERVER_DISCONNECT:
+		message = "Server disconnected";
+		break;
+	case JRPC_ERR_TIMEOUT:
+		message = "Message timeout";
+		break;
+	case JRPC_ERR_PARSING:
+		message = "JSON parse error";
+		break;
+	case JRPC_ERR_BUG:
+		message = "There is a bug";
+		break;
+	default:
+		ERR("Unrecognized error code: %d\n", code);
+		message = "Unknown error";
+		break;
+	}
+
+	json_t* message_js = json_string(message);
+	json_object_set(inner, "message", message_js);
+	if(message_js) json_decref(message_js);
+
+	json_t* code_js = json_integer(code);
+	json_object_set(inner, "code", code_js);
+	if(code_js) json_decref(code_js);
+
+	if(data) {
+		json_object_set(inner, "data", data);
+	}
+
+	json_object_set(ret, "internal_error", inner);
+	if(inner) json_decref(inner);
+	return ret;
+}
+
+void fail_request(int code, jsonrpc_request_t* req, char* err_str)
+{
+	char* req_s;
+	char* freeme = NULL;
+	pv_value_t val;
+	json_t* error;
+
+	if(!req) {
+null_req:
+		WARN("%s: (null)\n", err_str);
+		goto end;
+	}
+
+	if(!(req->cmd) || (req->cmd->route.len <= 0)) {
+no_route:
+		req_s = json_dumps(req->payload, JSON_COMPACT);
+		if(req_s) {
+			WARN("%s: \n%s\n", err_str, req_s);
+			free(req_s);
+			goto end;
+		}
+		goto null_req;
+	}
+
+	error = internal_error(code, req->payload);
+	jsontoval(&val, &freeme, error);
+	if(error) json_decref(error);
+	if(send_to_script(&val, req->cmd)<0) {
+		goto no_route;
+	}
+
+end:
+	if(freeme) free(freeme);
+	free_req_cmd(req->cmd);
+	free_request(req);
+}
+
+void timeout_cb(int fd, short event, void *arg)
+{
+	jsonrpc_request_t* req = (jsonrpc_request_t*)arg;
+	if(!req)
+		return;
+
+	if(!(req->server)) {
+		ERR("No server defined for request\n");
+		return;
+	}
+
+	if(schedule_retry(req)<0) {
+		fail_request(JRPC_ERR_TIMEOUT, req, "Request timeout");
+	}
+}
+
+
+int server_tried(jsonrpc_server_t* server, server_list_t* tried)
+{
+	if(!server)
+		return 0;
+
+	int t = 0;
+	for(;tried!=NULL;tried=tried->next)
+	{
+		if(tried->server &&
+			server == tried->server)
+		{
+			t = 1;
+		}
+	}
+	return t;
+}
+
+/* loadbalance_by_weight() uses an algorithm to randomly pick a server out of
+ * a list based on its relative weight.
+ *
+ * It is loosely inspired by this:
+ * http://eli.thegreenplace.net/2010/01/22/weighted-random-generation-in-python/
+ *
+ * The insert_server_group() function provides the ability to get the combined
+ * weight of all the servers off the head of the list, making it possible to
+ * compute in O(n) in the worst case and O(1) in the best.
+ *
+ * A random number out of the total weight is chosen. Each node is inspected and
+ * its weight added to a recurring sum. Once the sum is larger than the random
+ * number the last server that was seen is chosen.
+ *
+ * A weight of 0 will almost never be chosen, unless if maybe all the other
+ * servers are offline.
+ *
+ * The exception is when all the servers in a group have a weight of 0. In
+ * this case, the load should be distributed evenly across each of them. This
+ * requires finding the size of the list beforehand.
+ * */
+void loadbalance_by_weight(jsonrpc_server_t** s,
+		jsonrpc_server_group_t* grp, server_list_t* tried)
+{
+	*s = NULL;
+
+	if(grp == NULL) {
+		ERR("Trying to pick from an empty group\n");
+		return;
+	}
+
+	if(grp->type != WEIGHT_GROUP) {
+		ERR("Trying to pick from a non weight group\n");
+		return;
+	}
+
+	jsonrpc_server_group_t* head = grp;
+	jsonrpc_server_group_t* cur = grp;
+
+	unsigned int pick = 0;
+	if(head->weight == 0) {
+		unsigned int size = 0;
+		size = server_group_size(cur);
+		if(size == 0) return;
+
+		pick = fastrand_max(size-1);
+
+		int i;
+		for(i=0;
+			(i <= pick || *s == NULL)
+				&& cur != NULL;
+			i++, cur=cur->next)
+		{
+			if(cur->server->status == JSONRPC_SERVER_CONNECTED) {
+				if(!server_tried(cur->server, tried)
+					&& (cur->server->hwm <= 0
+						|| cur->server->req_count < cur->server->hwm))
+				{
+					*s = cur->server;
+				}
+			}
+		}
+	} else {
+		pick = fastrand_max(head->weight - 1);
+
+		unsigned int sum = 0;
+		while(1) {
+			if(cur == NULL) break;
+			if(cur->server->status == JSONRPC_SERVER_CONNECTED) {
+				if(!server_tried(cur->server, tried)
+					&& (cur->server->hwm <= 0
+						|| cur->server->req_count < cur->server->hwm))
+				{
+					*s = cur->server;
+				}
+			}
+			sum += cur->server->weight;
+			if(sum > pick && *s != NULL) break;
+			cur = cur->next;
+		}
+	}
+}
+
+int jsonrpc_send(str conn, jsonrpc_request_t* req, bool notify_only)
+{
+	char* json = (char*)json_dumps(req->payload, JSON_COMPACT);
+
+	char* ns;
+	size_t bytes;
+	bytes = netstring_encode_new(&ns, json, (size_t)strlen(json));
+
+	bool sent = false;
+	jsonrpc_server_group_t* c_grp = NULL;
+	if(global_server_group != NULL)
+		c_grp = *global_server_group;
+	jsonrpc_server_group_t* p_grp = NULL;
+	jsonrpc_server_group_t* w_grp = NULL;
+	jsonrpc_server_t* s = NULL;
+	server_list_t* tried_servers = NULL;
+	DEBUG("SENDING DATA\n");
+	for(; c_grp != NULL; c_grp = c_grp->next) {
+
+		if(strncmp(conn.s, c_grp->conn.s, c_grp->conn.len) != 0) continue;
+
+		for(p_grp = c_grp->sub_group; p_grp != NULL; p_grp = p_grp->next)
+		{
+			w_grp = p_grp->sub_group;
+			while(!sent) {
+				loadbalance_by_weight(&s, w_grp, tried_servers);
+				if (s == NULL || s->status != JSONRPC_SERVER_CONNECTED) {
+					break;
+				}
+
+				if(bufferevent_write(s->bev, ns, bytes) == 0) {
+					sent = true;
+					if(!notify_only) {
+						s->req_count++;
+						if (s->hwm > 0 && s->req_count >= s->hwm) {
+							WARN("%.*s:%d in connection group %.*s has exceeded its high water mark (%d)\n",
+									STR(s->addr), s->port,
+									STR(s->conn), s->hwm);
+						}
+					}
+					req->server = s;
+					break;
+				} else {
+					addto_server_list(s, &tried_servers);
+				}
+			}
+
+			if (sent) {
+				break;
+			}
+
+			WARN("Failed to send to priority group, %d\n", p_grp->priority);
+			if(p_grp->next != NULL) {
+				INFO("Proceeding to next priority group, %d\n",
+						p_grp->next->priority);
+			}
+		}
+
+		if (sent) {
+			break;
+		}
+
+	}
+
+	if(!sent) {
+		WARN("Failed to send to connection group, \"%.*s\"\n",
+				STR(conn));
+		if(schedule_retry(req)<0) {
+			fail_request(JRPC_ERR_RETRY, req, "Failed to schedule retry");
+		}
+	}
+
+	free_server_list(tried_servers);
+	if(ns) pkg_free(ns);
+	if(json) free(json);
+
+	if (sent && notify_only == false) {
+
+		const struct timeval tv = ms_to_tv(req->timeout);
+
+		req->timeout_ev = evtimer_new(global_ev_base, timeout_cb, (void*)req);
+		if(event_add(req->timeout_ev, &tv)<0) {
+			ERR("event_add failed while setting request timer (%s).",
+					strerror(errno));
+			return -1;
+		}
+	}
+
+	return sent;
+}
+
+
+void cmd_pipe_cb(int fd, short event, void *arg)
+{
+	struct jsonrpc_pipe_cmd *cmd;
+
+	if (read(fd, &cmd, sizeof(cmd)) != sizeof(cmd)) {
+		ERR("FATAL ERROR: failed to read from command pipe: %s\n",
+				strerror(errno));
+		return;
+	}
+
+
+	switch(cmd->type) {
+	case CMD_CLOSE:
+		if(cmd->server) {
+			wait_close(cmd->server);
+		}
+		goto end;
+		break;
+	case CMD_RECONNECT:
+		if(cmd->server) {
+			wait_reconnect(cmd->server);
+		}
+		goto end;
+		break;
+	case CMD_CONNECT:
+		if(cmd->server) {
+			bev_connect(cmd->server);
+		}
+		goto end;
+		break;
+	case CMD_UPDATE_SERVER_GROUP:
+		if(cmd->new_grp) {
+			jsonrpc_server_group_t* old_grp = *global_server_group;
+			*global_server_group = cmd->new_grp;
+			free_server_group(&old_grp);
+		}
+		lock_release(jsonrpc_server_group_lock);
+		goto end;
+		break;
+
+	case CMD_SEND:
+		break;
+
+	default:
+		ERR("Unrecognized pipe command: %d\n", cmd->type);
+		goto end;
+		break;
+	}
+
+	/* command is SEND */
+
+	jsonrpc_req_cmd_t* req_cmd = cmd->req_cmd;
+	if(req_cmd == NULL) {
+		ERR("req_cmd is NULL. Invalid send command\n");
+		goto end;
+	}
+
+	jsonrpc_request_t* req = NULL;
+	req = create_request(req_cmd);
+	if (!req || !req->payload) {
+		json_t* error = internal_error(JRPC_ERR_REQ_BUILD, NULL);
+		pv_value_t val;
+		char* freeme = NULL;
+		jsontoval(&val, &freeme, error);
+		if(req_cmd->route.len <=0 && send_to_script(&val, req_cmd)<0) {
+			ERR("Failed to build request (method: %.*s, params: %.*s)\n",
+					STR(req_cmd->method), STR(req_cmd->params));
+		}
+		if(freeme) free(freeme);
+		if(error) json_decref(error);
+		free_req_cmd(req_cmd);
+		goto end;
+	}
+
+	int sent = jsonrpc_send(req_cmd->conn, req, req_cmd->notify_only);
+
+	char* type;
+	if (sent<0) {
+		if (req_cmd->notify_only == false) {
+			type = "Request";
+		} else {
+			type = "Notification";
+		}
+		WARN("%s could not be sent to connection group: %.*s\n",
+				type, STR(req_cmd->conn));
+		fail_request(JRPC_ERR_SEND, req, "Failed to send request");
+	}
+
+end:
+	free_pipe_cmd(cmd);
+}
+
+int handle_response(json_t* response)
+{
+	int retval = 0;
+	jsonrpc_request_t* req = NULL;
+	json_t* return_obj = NULL;
+	json_t* internal = NULL;
+	char* freeme = NULL;
+
+
+	/* check if json object */
+	if(!json_is_object(response)){
+		WARN("jsonrpc response is not an object\n");
+		return -1;
+	}
+
+	/* check version */
+	json_t* version = json_object_get(response, "jsonrpc");
+	if(!version) {
+		WARN("jsonrpc response does not have a version.\n");
+		retval = -1;
+		goto end;
+	}
+
+	const char* version_s = json_string_value(version);
+	if(!version_s){
+		WARN("jsonrpc response version is not a string.\n");
+		retval = -1;
+		goto end;
+	}
+
+	if (strlen(version_s) != (sizeof(JSONRPC_VERSION)-1)
+			|| strncmp(version_s, JSONRPC_VERSION, sizeof(JSONRPC_VERSION)-1) != 0) {
+		WARN("jsonrpc response version is not %s. version: %s\n",
+				JSONRPC_VERSION, version_s);
+		retval = -1;
+		goto end;
+	}
+
+	/* check for an id */
+	json_t* _id = json_object_get(response, "id");
+	if(!_id) {
+		WARN("jsonrpc response does not have an id.\n");
+		retval = -1;
+		goto end;
+	}
+
+	int id = json_integer_value(_id);
+	if (!(req = pop_request(id))) {
+		/* don't fail the server for an unrecognized id */
+		retval = 0;
+		goto end;
+	}
+
+	return_obj = json_object();
+
+	json_t* error = json_object_get(response, "error");
+	json_t* result = json_object_get(response, "result");
+
+	if(error) {
+		json_object_set(return_obj, "error", error);
+	}
+
+	if(result) {
+		json_object_set(return_obj, "result", result);
+	}
+
+	if ((!result && !error) || (result && error)) {
+		WARN("bad response\n");
+		internal = internal_error(JRPC_ERR_BAD_RESP, req->payload);
+		json_object_update(return_obj, internal);
+		if(internal) json_decref(internal);
+	}
+
+	pv_value_t val;
+
+	if(jsontoval(&val, &freeme, return_obj)<0) {
+		fail_request(
+				JRPC_ERR_TO_VAL,
+				req,
+				"Failed to convert response json to pv\n");
+		retval = -1;
+		goto end;
+	}
+
+	char* error_s = NULL;
+
+	if(send_to_script(&val, req->cmd)>=0) {
+		goto free_and_end;
+	}
+
+	if(error) {
+		// get code from error
+		json_t* _code = json_object_get(error, "code");
+		if(_code) {
+			int code = json_integer_value(_code);
+
+			// check if code is in global_retry_ranges
+			retry_range_t* tmpr;
+			for(tmpr = global_retry_ranges;
+					tmpr != NULL;
+					tmpr = tmpr->next) {
+				if((tmpr->start < tmpr->end
+						&& tmpr->start <= code && code <= tmpr->end)
+				|| (tmpr->end < tmpr->start
+						&& tmpr->end <= code && code <= tmpr->start)
+				|| (tmpr->start == tmpr->end && tmpr->start == code)) {
+					if(schedule_retry(req)==0) {
+						goto end;
+					}
+					break;
+				}
+			}
+
+		}
+		error_s = json_dumps(error, JSON_COMPACT);
+		if(error_s) {
+			WARN("Request recieved an error: \n%s\n", error_s);
+			free(error_s);
+		} else {
+			fail_request(
+					JRPC_ERR_BAD_RESP,
+					req,
+					"Could not convert 'error' response to string");
+			retval = -1;
+			goto end;
+		}
+	}
+
+
+free_and_end:
+	free_req_cmd(req->cmd);
+	free_request(req);
+
+end:
+	if(freeme) free(freeme);
+	if(return_obj) json_decref(return_obj);
+	return retval;
+}
+
+void handle_netstring(jsonrpc_server_t* server)
+{
+	unsigned int old_count = server->req_count;
+	server->req_count--;
+	if (server->hwm > 0
+			&& old_count >= server->hwm
+			&& server->req_count < server->hwm) {
+		INFO("%.*s:%d in connection group %.*s is back to normal\n",
+				STR(server->addr), server->port, STR(server->conn));
+	}
+
+	json_error_t error;
+
+	json_t* res = json_loads(server->buffer->string, 0, &error);
+
+	if (res) {
+		if(handle_response(res)<0){
+			ERR("Cannot handle jsonrpc response: %s\n", server->buffer->string);
+		}
+		json_decref(res);
+	} else {
+		ERR("Failed to parse json: %s\n", server->buffer->string);
+		ERR("PARSE ERROR: %s at %d,%d\n",
+				error.text, error.line, error.column);
+	}
+}
+
+void bev_read_cb(struct bufferevent* bev, void* arg)
+{
+	jsonrpc_server_t* server = (jsonrpc_server_t*)arg;
+	int retval = 0;
+	while (retval == 0) {
+		int retval = netstring_read_evbuffer(bev, &server->buffer);
+
+		if (retval == NETSTRING_INCOMPLETE) {
+			return;
+		} else if (retval < 0) {
+			char* msg = "";
+			switch(retval) {
+			case NETSTRING_ERROR_TOO_LONG:
+				msg = "too long";
+				break;
+			case NETSTRING_ERROR_NO_COLON:
+				msg = "no colon after length field";
+				break;
+			case NETSTRING_ERROR_TOO_SHORT:
+				msg = "too short";
+				break;
+			case NETSTRING_ERROR_NO_COMMA:
+				msg = "missing comma";
+				break;
+			case NETSTRING_ERROR_LEADING_ZERO:
+				msg = "length field has a leading zero";
+				break;
+			case NETSTRING_ERROR_NO_LENGTH:
+				msg = "missing length field";
+				break;
+			case NETSTRING_INCOMPLETE:
+				msg = "incomplete";
+				break;
+			default:
+				ERR("bad netstring: unknown error (%d)\n", retval);
+				goto reconnect;
+			}
+			ERR("bad netstring: %s\n", msg);
+reconnect:
+			force_reconnect(server);
+			return;
+		}
+
+		handle_netstring(server);
+		free_netstring(server->buffer);
+		server->buffer = NULL;
+	}
+}
+
+int set_non_blocking(int fd)
+{
+	int flags;
+
+	flags = fcntl(fd, F_GETFL);
+	if (flags < 0)
+		return flags;
+	flags |= O_NONBLOCK;
+	if (fcntl(fd, F_SETFL, flags) < 0)
+		return -1;
+
+	return 0;
+}
+
+jsonrpc_pipe_cmd_t* create_pipe_cmd()
+{
+	jsonrpc_pipe_cmd_t* cmd = NULL;
+	cmd = (jsonrpc_pipe_cmd_t*)shm_malloc(sizeof(jsonrpc_pipe_cmd_t));
+	if(!cmd) {
+		ERR("Failed to malloc pipe cmd.\n");
+		return NULL;
+	}
+	memset(cmd, 0, sizeof(jsonrpc_pipe_cmd_t));
+
+	return cmd;
+}
+
+void free_pipe_cmd(jsonrpc_pipe_cmd_t* cmd)
+{
+	if(!cmd) return;
+
+	shm_free(cmd);
+}
+
+jsonrpc_req_cmd_t* create_req_cmd()
+{
+	jsonrpc_req_cmd_t* req_cmd = NULL;
+	req_cmd = (jsonrpc_req_cmd_t*)shm_malloc(sizeof(jsonrpc_req_cmd_t));
+	CHECK_MALLOC_NULL(req_cmd);
+	memset(req_cmd, 0, sizeof(jsonrpc_req_cmd_t));
+
+	req_cmd->conn = null_str;
+	req_cmd->method = null_str;
+	req_cmd->params = null_str;
+	req_cmd->route = null_str;
+	return req_cmd;
+}
+
+void free_req_cmd(jsonrpc_req_cmd_t* req_cmd)
+{
+	if(req_cmd) {
+		CHECK_AND_FREE(req_cmd->conn.s);
+		CHECK_AND_FREE(req_cmd->method.s);
+		CHECK_AND_FREE(req_cmd->params.s);
+		CHECK_AND_FREE(req_cmd->route.s);
+		shm_free(req_cmd);
+	}
+}
+
+int send_pipe_cmd(cmd_type type, void* data)
+{
+	char* name = "";
+	jsonrpc_pipe_cmd_t* cmd = NULL;
+	cmd = create_pipe_cmd();
+	CHECK_MALLOC(cmd);
+
+	cmd->type = type;
+
+	switch(type) {
+	case CMD_CONNECT:
+		cmd->server = (jsonrpc_server_t*)data;
+		name = "connect";
+		break;
+	case CMD_RECONNECT:
+		cmd->server = (jsonrpc_server_t*)data;
+		name = "reconnect";
+		break;
+	case CMD_CLOSE:
+		cmd->server = (jsonrpc_server_t*)data;
+		name = "close";
+		break;
+	case CMD_UPDATE_SERVER_GROUP:
+		cmd->new_grp = (jsonrpc_server_group_t*)data;
+		name = "update";
+		break;
+	case CMD_SEND:
+		cmd->req_cmd = (jsonrpc_req_cmd_t*)data;
+		name = "send";
+		break;
+	default:
+		ERR("Unknown command type %d", type);
+		goto error;
+	}
+
+	DEBUG("sending %s command\n", name);
+
+	if (write(cmd_pipe, &cmd, sizeof(cmd)) != sizeof(cmd)) {
+		ERR("Failed to send '%s' cmd to io pipe: %s\n", name, strerror(errno));
+		goto error;
+	}
+
+	return 0;
+error:
+	free_pipe_cmd(cmd);
+	return -1;
+}
diff --git a/modules/janssonrpc-c/janssonrpc_io.h b/modules/janssonrpc-c/janssonrpc_io.h
new file mode 100644
index 0000000..5abb75e
--- /dev/null
+++ b/modules/janssonrpc-c/janssonrpc_io.h
@@ -0,0 +1,90 @@
+/**
+ * Copyright (C) 2013 Flowroute LLC (flowroute.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef _JANSSONRPC_IO_H_
+#define _JANSSONRPC_IO_H_
+
+#include <jansson.h>
+#include <event2/bufferevent.h>
+#include <stdbool.h>
+#include "../../route_struct.h"
+#include "../../pvar.h"
+#include "janssonrpc_server.h"
+#include "janssonrpc_request.h"
+#include "janssonrpc.h"
+
+/* event bases */
+struct event_base* global_ev_base;
+struct evdns_base* global_evdns_base;
+
+typedef enum
+{ CMD_CONNECT = 1000
+, CMD_RECONNECT
+, CMD_CLOSE
+, CMD_UPDATE_SERVER_GROUP
+, CMD_SEND
+} cmd_type;
+
+typedef struct jsonrpc_req_cmd {
+	str method, params, route, conn;
+	unsigned int t_hash, t_label, timeout;
+	bool notify_only;
+	int retry;
+	struct sip_msg *msg;
+} jsonrpc_req_cmd_t;
+
+typedef struct jsonrpc_pipe_cmd jsonrpc_pipe_cmd_t;
+struct jsonrpc_pipe_cmd
+{
+	cmd_type type;
+	union {
+		jsonrpc_server_t* server;
+		jsonrpc_req_cmd_t* req_cmd;
+		jsonrpc_server_group_t* new_grp;
+	};
+};
+
+int jsonrpc_io_child_process(int data_pipe);
+int send_pipe_cmd(cmd_type type, void* data);
+int handle_response(json_t *response);
+jsonrpc_pipe_cmd_t* create_pipe_cmd();
+void free_pipe_cmd(jsonrpc_pipe_cmd_t* cmd);
+jsonrpc_req_cmd_t* create_req_cmd();
+void free_req_cmd(jsonrpc_req_cmd_t* cmd);
+int  set_non_blocking(int fd);
+void bev_read_cb(struct bufferevent* bev, void* arg);
+
+/* Remember to update the docs if you add or change these */
+typedef enum
+{ JRPC_ERR_BUG       = -1000
+, JRPC_ERR_TIMEOUT   = -100
+, JRPC_ERR_SERVER_DISCONNECT = -75
+, JRPC_ERR_RETRY     = -50
+, JRPC_ERR_BAD_RESP  = -20
+, JRPC_ERR_TO_VAL    = -11
+, JRPC_ERR_PARSING   = -10
+, JRPC_ERR_SEND      = -5
+, JRPC_ERR_REQ_BUILD = -1
+} jsonrpc_error;
+
+
+#endif /* _JSONRPC_IO_H_ */
diff --git a/modules/janssonrpc-c/janssonrpc_mod.c b/modules/janssonrpc-c/janssonrpc_mod.c
new file mode 100644
index 0000000..7db22cc
--- /dev/null
+++ b/modules/janssonrpc-c/janssonrpc_mod.c
@@ -0,0 +1,362 @@
+/**
+ * Copyright (C) 2013 Flowroute LLC (flowroute.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <arpa/inet.h>
+#include <sys/types.h>
+#include <errno.h>
+
+#include "../../pvar.h"
+#include "../../mod_fix.h"
+#include "../../trim.h"
+#include "../../sr_module.h"
+#include "../../timer_proc.h"
+#include "../tm/tm_load.h"
+#include "../jansson/jansson_utils.h"
+
+#include "janssonrpc_funcs.h"
+#include "janssonrpc_request.h"
+#include "janssonrpc_io.h"
+#include "janssonrpc_connect.h"
+#include "janssonrpc_server.h"
+#include "janssonrpc_srv.h"
+#include "janssonrpc.h"
+
+
+MODULE_VERSION
+
+
+static int mod_init(void);
+static int child_init(int);
+void mod_destroy(void);
+int parse_server_param(modparam_t type, void* val);
+int parse_retry_codes_param(modparam_t type, void* val);
+int parse_min_ttl_param(modparam_t type, void* val);
+static int fixup_req(void** param, int param_no);
+static int fixup_req_free(void** param, int param_no);
+static int fixup_notify(void** param, int param_no);
+static int fixup_notify_free(void** param, int param_no);
+int		  fixup_pvar_shm(void** param, int param_no);
+
+int  pipe_fds[2] = {-1,-1};
+
+struct tm_binds tmb;
+
+/*
+ * Exported Functions
+ */
+int jsonrpc_request_no_options(struct sip_msg* msg,
+		char* conn,
+		char* method,
+		char* params) {
+	return jsonrpc_request(msg, conn, method, params, NULL);
+}
+
+static cmd_export_t cmds[]={
+	{"janssonrpc_request", (cmd_function)jsonrpc_request,
+		4, fixup_req, fixup_req_free, ANY_ROUTE},
+	{"jsansonrpc_request", (cmd_function)jsonrpc_request_no_options,
+		3, fixup_req, fixup_req_free, ANY_ROUTE},
+	{"janssonrpc_notification", (cmd_function)jsonrpc_notification,
+		3, fixup_notify, fixup_notify_free, ANY_ROUTE},
+	{"mod_janssonrpc_request", (cmd_function)mod_jsonrpc_request,
+		0, 0, 0, 0},
+	{0, 0, 0, 0, 0, 0}
+};
+
+/*
+ * Script Parameters
+ */
+static param_export_t mod_params[]={
+	{"server",      STR_PARAM|USE_FUNC_PARAM, (void*)parse_server_param},
+	{"retry_codes",  STR_PARAM|USE_FUNC_PARAM, (void*)parse_retry_codes_param},
+	{"min_srv_ttl", INT_PARAM|USE_FUNC_PARAM, (void*)parse_min_ttl_param},
+	{"result_pv",   STR_PARAM,                &result_pv_str.s},
+	{ 0,0,0 }
+};
+
+/*
+ * Exports
+ */
+struct module_exports exports = {
+		"janssonrpc-c",       /* module name */
+		DEFAULT_DLFLAGS, /* dlopen flags */
+		cmds,            /* Exported functions */
+		mod_params,      /* Exported parameters */
+		0,               /* exported statistics */
+		0,               /* exported MI functions */
+		0,               /* exported pseudo-variables */
+		0,               /* extra processes */
+		mod_init,        /* module initialization function */
+		0,               /* response function*/
+		mod_destroy,     /* destroy function */
+		child_init       /* per-child init function */
+};
+
+
+static int mod_init(void)
+{
+	/* load the tm functions  */
+	if(load_tm_api(&tmb)<0) return -1;
+
+	/* load json_to_val from json module */
+	jsontoval = (jansson_to_val_f)find_export("jansson_to_val", 0, 0);
+	if(jsontoval == 0) {
+		ERR("ERROR:jsonrpc:mod_init: cannot import json_to_val\n");
+		return -1;
+	}
+
+	/* setup result pvar */
+	if (result_pv_str.s == NULL)
+		result_pv_str.s = JSONRPC_RESULT_STR;
+	result_pv_str.len = strlen(result_pv_str.s);
+
+	if(pv_parse_spec(&result_pv_str, &jsonrpc_result_pv)<0) {
+		ERR("cannot parse result_pv: %.*s\n", STR(result_pv_str));
+		return -1;
+	}
+
+	if(!(pv_is_w(&jsonrpc_result_pv))) {
+		ERR("%.*s is read only\n", STR(result_pv_str));
+		return -1;
+	}
+
+	register_procs(1);
+	register_basic_timers(1);
+
+	if (pipe(pipe_fds) < 0) {
+		ERR("pipe() failed\n");
+		return -1;
+	}
+
+	if(jsonrpc_min_srv_ttl < ABSOLUTE_MIN_SRV_TTL) {
+		jsonrpc_min_srv_ttl = JSONRPC_DEFAULT_MIN_SRV_TTL; /* 5s */
+	}
+
+	return 0;
+}
+
+static int child_init(int rank)
+{
+	int pid;
+
+	if (rank>PROC_MAIN)
+		cmd_pipe = pipe_fds[1];
+
+	if (rank!=PROC_MAIN)
+		return 0;
+
+	jsonrpc_server_group_lock = lock_alloc();
+	if(jsonrpc_server_group_lock == NULL) {
+		ERR("cannot allocate the server_group_lock\n");
+		return -1;
+	}
+
+	if(lock_init(jsonrpc_server_group_lock) == 0) {
+		ERR("failed to initialized the server_group_lock\n");
+		lock_dealloc(jsonrpc_server_group_lock);
+		return -1;
+	}
+
+	srv_cb_params_t* params = (srv_cb_params_t*)shm_malloc(sizeof(srv_cb_params_t));
+	CHECK_MALLOC(params);
+	params->cmd_pipe = pipe_fds[1];
+	params->srv_ttl = jsonrpc_min_srv_ttl;
+
+	/* start timer to check SRV ttl every second */
+	if(fork_basic_timer(PROC_TIMER, "jsonrpc SRV timer", 1 /*socks flag*/,
+				refresh_srv_cb, (void*)params, ABSOLUTE_MIN_SRV_TTL)<0) {
+		ERR("Failed to start SRV timer\n");
+		return -1;
+	}
+
+	pid=fork_process(PROC_RPC, "jsonrpc io handler", 1);
+
+	if (pid<0)
+		return -1; /* error */
+	if(pid==0){
+		/* child */
+		close(pipe_fds[1]);
+		return jsonrpc_io_child_process(pipe_fds[0]);
+	}
+
+	return 0;
+}
+
+void mod_destroy(void)
+{
+	lock_get(jsonrpc_server_group_lock); /* blocking */
+	if(jsonrpc_server_group_lock) lock_dealloc(jsonrpc_server_group_lock);
+
+	free_server_group(global_server_group);
+	CHECK_AND_FREE(global_server_group);
+}
+
+int parse_server_param(modparam_t type, void* val)
+{
+	if(global_server_group == NULL) {
+		global_server_group = shm_malloc(sizeof(void*));
+		*global_server_group = NULL;
+	}
+	return jsonrpc_parse_server((char*)val, global_server_group);
+}
+
+/* helper function for parse_retry_codes_param */
+int s2i(char* str, int* result)
+{
+	char* endptr;
+	errno = 0;
+
+	long val = strtol(str, &endptr, 10);
+
+	if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN))
+			|| (errno != 0 && val == 0)) {
+		ERR("%s is not a number: %s\n", str, strerror(errno));
+		return -1;
+	}
+
+	if (endptr == str) {
+		ERR("failed to convert %s to integer\n", str);
+		return -1;
+	}
+
+	*result = (int)val;
+	return 0;
+}
+
+int parse_retry_codes_param(modparam_t type, void* val)
+{
+	if (val==NULL) {
+		ERR("retry_codes cannot be NULL!\n");
+		return -1;
+	}
+
+	if (PARAM_TYPE_MASK(type) != STR_PARAM) {
+		ERR("retry_codes must be a string\n");
+		return -1;
+	}
+
+	global_retry_ranges = NULL;
+
+	char* save_comma;
+	char* save_elipse;
+	char* token;
+	char* start_s;
+	int start;
+	char* end_s;
+	int end;
+	char* codes_s = (char*)val;
+
+	char* tmp;
+	retry_range_t** tmp_range;
+	tmp_range = &global_retry_ranges;
+	for (tmp = codes_s; ; tmp = NULL) {
+		token = strtok_r(tmp, ",", &save_comma);
+		if (token == NULL)
+			break;
+
+		start_s = strtok_r(token, ".", &save_elipse);
+		if (start_s == NULL) {
+			continue;
+		}
+
+		if(s2i(start_s, &start)<0) return -1;
+
+		*tmp_range = shm_malloc(sizeof(retry_range_t));
+		CHECK_MALLOC(*tmp_range);
+		memset(*tmp_range, 0, sizeof(retry_range_t));
+
+		(*tmp_range)->start = start;
+
+		end_s = strtok_r(NULL, ".", &save_elipse);
+		if (end_s == NULL) {
+			end_s = start_s;
+		}
+
+		if(s2i(end_s, &end)<0) return -1;
+		(*tmp_range)->end = end;
+
+		tmp_range = &((*tmp_range)->next);
+	}
+
+	return 0;
+}
+
+int parse_min_ttl_param(modparam_t type, void* val)
+{
+	if (val==0) {
+		ERR("min_srv_ttl cannot be NULL!\n");
+		return -1;
+	}
+
+	if (PARAM_TYPE_MASK(type) != INT_PARAM) {
+		ERR("min_srv_ttl must be of type %d, not %d!\n", INT_PARAM, type);
+		return -1;
+	}
+
+	jsonrpc_min_srv_ttl = (int)(long)val;
+	if(jsonrpc_min_srv_ttl < ABSOLUTE_MIN_SRV_TTL) {
+		ERR("Cannot set min_srv_ttl lower than %d", ABSOLUTE_MIN_SRV_TTL);
+		return -1;
+	}
+
+	INFO("min_srv_ttl set to %d\n", jsonrpc_min_srv_ttl);
+
+	return 0;
+}
+
+/* Fixup Functions */
+
+static int fixup_req(void** param, int param_no)
+{
+	if (param_no <= 4) {
+		return fixup_spve_null(param, 1);
+	}
+	ERR("function takes at most 4 parameters.\n");
+	return -1;
+}
+
+static int fixup_req_free(void** param, int param_no)
+{
+	if (param_no <= 4) {
+		return fixup_free_spve_null(param, 1);
+	}
+	ERR("function takes at most 4 parameters.\n");
+	return -1;
+}
+
+static int fixup_notify(void** param, int param_no)
+{
+	if (param_no <= 3) {
+		return fixup_spve_null(param, 1);
+	}
+	ERR("function takes at most 3 parameters.\n");
+	return -1;
+}
+
+static int fixup_notify_free(void** param, int param_no)
+{
+	if (param_no <= 3) {
+		return fixup_free_spve_null(param, 1);
+	}
+	ERR("function takes at most 3 parameters.\n");
+	return -1;
+}
diff --git a/modules/janssonrpc-c/janssonrpc_request.c b/modules/janssonrpc-c/janssonrpc_request.c
new file mode 100644
index 0000000..39c7f31
--- /dev/null
+++ b/modules/janssonrpc-c/janssonrpc_request.c
@@ -0,0 +1,340 @@
+/**
+ * Copyright (C) 2013 Flowroute LLC (flowroute.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+
+#include "../../sr_module.h"
+#include "../../mem/mem.h"
+
+#include "janssonrpc.h"
+#include "janssonrpc_request.h"
+#include "janssonrpc_io.h"
+
+int next_id = 1;
+
+int store_request(jsonrpc_request_t* req);
+
+/* for debugging only */
+void print_request(jsonrpc_request_t* req)
+{
+	if(!req) {
+		INFO("request is (null)\n");
+		return;
+	}
+
+	INFO("------request------\n");
+	INFO("| id: %d\n", req->id);
+
+	if(req->type == RPC_NOTIFICATION) {
+		INFO("| type: notification\n");
+	} else if(req->type == RPC_REQUEST) {
+		INFO("| type: request\n");
+	} else {
+		INFO("| type: unknown (%d)\n", (int)req->type);
+	}
+
+	if(!(req->server)) {
+		INFO("| server: (null)\n");
+	} else {
+		print_server(req->server);
+	}
+
+	if(!(req->cmd)) {
+		INFO("| cmd: (null)\n");
+	} else {
+		INFO("| cmd->route: %.*s\n", STR(req->cmd->route));
+	}
+
+	INFO("| payload: %s\n", json_dumps(req->payload, 0));
+	INFO("| retry: %d\n", req->retry);
+	INFO("| ntries: %d\n", req->ntries);
+	INFO("| timeout: %d\n", req->timeout);
+	INFO("\t-------------------\n");
+}
+
+void free_request(jsonrpc_request_t* req)
+{
+	if(!req)
+		return;
+
+	pop_request(req->id);
+
+	CHECK_AND_FREE_EV(req->retry_ev);
+	CHECK_AND_FREE_EV(req->timeout_ev);
+
+	if(req->payload) json_decref(req->payload);
+	pkg_free(req);
+}
+
+jsonrpc_request_t* create_request(jsonrpc_req_cmd_t* cmd)
+{
+	if (cmd == NULL) {
+		ERR("cmd is (null). Cannot build request.\n");
+		return NULL;
+	}
+
+	if (cmd->params.s == NULL) {
+		ERR("params is (null). Cannot build request.\n");
+		return NULL;
+	}
+
+	jsonrpc_request_t* req = (jsonrpc_request_t*)pkg_malloc(sizeof(jsonrpc_request_t));
+	if (!req) {
+		ERR("Out of memory!");
+		return NULL;
+	}
+	memset(req, 0, sizeof(jsonrpc_request_t));
+
+	if (cmd->notify_only) {
+		req->type = RPC_NOTIFICATION;
+	} else {
+		req->type = RPC_REQUEST;
+	}
+
+	/* settings for both notifications and requests */
+	req->ntries = 0;
+	req->next = NULL;
+
+	req->payload = json_object();
+	if(!(req->payload)) {
+		ERR("Failed to create request payload\n");
+		goto fail;
+	}
+
+	if(req->type == RPC_REQUEST) {
+		if (next_id>JSONRPC_MAX_ID) {
+			next_id = 1;
+		} else {
+			next_id++;
+		}
+		req->id = next_id;
+		req->timeout = cmd->timeout;
+
+		json_t* id_js = json_integer(next_id);
+		if(id_js) {
+			json_object_set(req->payload, "id", id_js);
+			json_decref(id_js);
+		} else {
+			ERR("Failed to create request id\n");
+			goto fail;
+		}
+
+		req->retry = cmd->retry;
+		req->timeout = cmd->timeout;
+		if (!store_request(req)) {
+			ERR("store_request failed\n");
+			goto fail;
+		}
+	} else if (req->type == RPC_NOTIFICATION) {
+		req->id = 0;
+		req->retry = 0;
+	} else {
+		ERR("Unknown RPC type: %d\n", (int)req->type);
+		goto fail;
+	}
+
+	json_t* version_js = json_string(JSONRPC_VERSION);
+	if(version_js) {
+		json_object_set(req->payload, "jsonrpc", version_js);
+		json_decref(version_js);
+	} else {
+		ERR("Failed to create request version\n");
+		goto fail;
+	}
+
+	json_t* method_js = json_string(cmd->method.s);
+	if(method_js) {
+		json_object_set(req->payload, "method", method_js);
+		json_decref(method_js);
+	} else {
+		ERR("Failed to create request method\n");
+		goto fail;
+	}
+
+	json_t* params = NULL;
+	json_error_t error;
+	if(cmd->params.len > 0) {
+		params = json_loads(cmd->params.s, 0, &error);
+		if(!params) {
+			ERR("Failed to parse json: %.*s\n", STR(cmd->params));
+			ERR("PARSE ERROR: %s at %d,%d\n",
+					error.text, error.line, error.column);
+			goto fail;
+		}
+	}
+
+	json_object_set(req->payload, "params", params);
+	if(!(req->payload)) {
+		ERR("Failed to add request payload params\n");
+		goto fail;
+	}
+
+	if(params) json_decref(params);
+
+	req->cmd = cmd;
+	return req;
+fail:
+	ERR("Failed to create request\n");
+	free_request(req);
+	return NULL;
+}
+
+void retry_cb(int fd, short event, void* arg)
+{
+	if(!arg)
+		return;
+
+	jsonrpc_request_t* req = (jsonrpc_request_t*)arg;
+
+	if(!(req->cmd)) {
+		ERR("request has no cmd\n");
+		goto error;
+	}
+
+	DEBUG("retrying request: id=%d\n", req->id);
+
+	if(jsonrpc_send(req->cmd->conn, req, 0)<0) {
+		goto error;
+	}
+
+	CHECK_AND_FREE_EV(req->retry_ev);
+	return;
+
+error:
+	fail_request(JRPC_ERR_SEND, req, "Retry failed to send request");
+}
+
+int schedule_retry(jsonrpc_request_t* req)
+{
+	if(!req) {
+		ERR("Trying to schedule retry for a null request.\n");
+		return -1;
+	}
+
+	if(req->retry == 0) {
+		return -1;
+	}
+
+	req->ntries++;
+	if(req->retry > 0 && req->ntries > req->retry) {
+		WARN("Number of retries exceeded. Failing request.\n");
+		return -1;
+	}
+
+	/* next retry in milliseconds */
+	unsigned int time = req->ntries * req->ntries * req->timeout;
+	if(time > RETRY_MAX_TIME) {
+		time = RETRY_MAX_TIME;
+	}
+
+	jsonrpc_request_t* new_req = create_request(req->cmd);
+
+	new_req->ntries = req->ntries;
+
+	free_request(req);
+
+	const struct timeval tv = ms_to_tv(time);
+
+	new_req->retry_ev = evtimer_new(global_ev_base, retry_cb, (void*)new_req);
+	if(evtimer_add(new_req->retry_ev, &tv)<0) {
+		ERR("event_add failed while setting request retry timer (%s).",
+				strerror(errno));
+		goto error;
+	}
+
+	return 0;
+error:
+	ERR("schedule_retry failed.\n");
+	return -1;
+}
+
+int id_hash(int id) {
+	return (id % JSONRPC_DEFAULT_HTABLE_SIZE);
+}
+
+jsonrpc_request_t* pop_request(int id)
+{
+	int key = id_hash(id);
+	jsonrpc_request_t* req = request_table[key];
+	jsonrpc_request_t* prev_req = NULL;
+
+	while (req && req->id != id) {
+		prev_req = req;
+		if (!(req = req->next)) {
+			break;
+		};
+	}
+
+	if (req && req->id == id) {
+		if (prev_req != NULL) {
+			prev_req->next = req->next;
+		} else {
+			request_table[key] = NULL;
+		}
+		return req;
+	}
+	return 0;
+}
+
+int store_request(jsonrpc_request_t* req)
+{
+	int key = id_hash(req->id);
+	jsonrpc_request_t* existing;
+
+	if ((existing = request_table[key])) { /* collision */
+		jsonrpc_request_t* i;
+		for(i=existing; i; i=i->next) {
+			if (i == NULL) {
+				i = req;
+				LM_ERR("!!!!!!!");
+				return 1;
+			}
+			if (i->next == NULL) {
+				i->next = req;
+				return 1;
+			}
+		}
+	} else {
+		request_table[key] = req;
+	}
+	return 1;
+}
+
+unsigned int requests_using_server(jsonrpc_server_t* server)
+{
+	unsigned int count = 0;
+	jsonrpc_request_t* req = NULL;
+	int key = 0;
+	for (key=0; key < JSONRPC_DEFAULT_HTABLE_SIZE; key++) {
+		for (req = request_table[key]; req != NULL; req = req->next) {
+			if(req->server
+					&& req->server == server) {
+				count++;
+			}
+		}
+	}
+	return count;
+}
+
diff --git a/modules/janssonrpc-c/janssonrpc_request.h b/modules/janssonrpc-c/janssonrpc_request.h
new file mode 100644
index 0000000..e38c08e
--- /dev/null
+++ b/modules/janssonrpc-c/janssonrpc_request.h
@@ -0,0 +1,65 @@
+/**
+ * Copyright (C) 2013 Flowroute LLC (flowroute.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef _JANSSONRPC_REQUEST_H_
+#define _JANSSONRPC_REQUEST_H_
+
+#include "janssonrpc_io.h"
+#include "janssonrpc_server.h"
+
+#define JSONRPC_DEFAULT_HTABLE_SIZE 500
+#define JSONRPC_MAX_ID 1000000
+#define RETRY_MAX_TIME 60000 /* milliseconds */
+
+typedef enum {
+	RPC_REQUEST,
+	RPC_NOTIFICATION
+} rpc_type;
+
+typedef struct jsonrpc_request jsonrpc_request_t;
+struct jsonrpc_request {
+	rpc_type type;
+	int id;
+	jsonrpc_request_t *next; /* pkg */
+	jsonrpc_server_t* server; /* shm */
+	jsonrpc_req_cmd_t* cmd; /* shm */
+	json_t* payload;
+	struct event* timeout_ev; /* pkg */
+	struct event* retry_ev; /* pkg */
+	int retry;
+	unsigned int ntries;
+	unsigned int timeout;
+};
+
+jsonrpc_request_t* request_table[JSONRPC_DEFAULT_HTABLE_SIZE];
+
+jsonrpc_request_t* create_request(jsonrpc_req_cmd_t* cmd);
+void print_request(jsonrpc_request_t* req);
+jsonrpc_request_t* pop_request(int id);
+unsigned int requests_using_server(jsonrpc_server_t* server);
+void free_request(jsonrpc_request_t* req);
+int schedule_retry(jsonrpc_request_t* req);
+
+int jsonrpc_send(str conn, jsonrpc_request_t* req, bool notify_only);
+void fail_request(int code, jsonrpc_request_t* req, char* error_str);
+
+#endif /* _JSONRPC_H_ */
diff --git a/modules/janssonrpc-c/janssonrpc_server.c b/modules/janssonrpc-c/janssonrpc_server.c
new file mode 100644
index 0000000..09286bc
--- /dev/null
+++ b/modules/janssonrpc-c/janssonrpc_server.c
@@ -0,0 +1,611 @@
+/**
+ * Copyright (C) 2013 Flowroute LLC (flowroute.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <fcntl.h>
+#include <event.h>
+
+#include "../../sr_module.h"
+#include "../../route.h"
+#include "../../route_struct.h"
+#include "../../resolve.h"
+#include "../../parser/parse_param.h"
+#include "../../mem/mem.h"
+#include "../../lvalue.h"
+
+#include "netstring.h"
+#include "janssonrpc.h"
+#include "janssonrpc_request.h"
+#include "janssonrpc_io.h"
+#include "janssonrpc_srv.h"
+#include "janssonrpc_server.h"
+#include "janssonrpc_connect.h"
+
+/* used for debugging only */
+void print_server(jsonrpc_server_t* server)
+{
+	INFO("\t----- server ------\n");
+	INFO("\t|pointer: %p\n", server);
+	INFO("\t|conn: %.*s\n", STR(server->conn));
+	INFO("\t|addr: %.*s\n", STR(server->addr));
+	switch (server->status) {
+	case JSONRPC_SERVER_CONNECTED:
+		INFO("\t|status: connected\n");
+		break;
+	case JSONRPC_SERVER_DISCONNECTED:
+		INFO("\t|status: disconnected\n");
+		break;
+	case JSONRPC_SERVER_FAILURE:
+		INFO("\t|status: failure\n");
+		break;
+	case JSONRPC_SERVER_CLOSING:
+		INFO("\t|status: closing\n");
+		break;
+	case JSONRPC_SERVER_RECONNECTING:
+		INFO("\t|status: reconnecting\n");
+		break;
+	default:
+		INFO("\t|status: invalid (%d)\n", server->status);
+		break;
+	}
+	INFO("\t|srv: %.*s\n", STR(server->srv));
+	INFO("\t|ttl: %d\n", server->ttl);
+	INFO("\t|port: %d\n", server->port);
+	INFO("\t|priority: %d\n", server->priority);
+	INFO("\t|weight: %d\n", server->weight);
+	INFO("\t|hwm: %d\n", server->hwm);
+	INFO("\t|req_count: %d\n", server->req_count);
+	if(server->added) {
+		INFO("\t|added: true\n");
+	} else {
+		INFO("\t|added: false\n");
+	}
+	INFO("\t-------------------\n");
+}
+
+/* used for debugging only */
+void print_group(jsonrpc_server_group_t** group)
+{
+	jsonrpc_server_group_t* grp = NULL;
+
+	INFO("group addr is %p\n", group);
+
+	if(group == NULL)
+		return;
+
+	for (grp=*group; grp != NULL; grp=grp->next) {
+		switch(grp->type) {
+		case CONN_GROUP:
+			INFO("Connection group: %.*s\n", STR(grp->conn));
+			print_group(&(grp->sub_group));
+			break;
+		case PRIORITY_GROUP:
+			INFO("Priority group: %d\n", grp->priority);
+			print_group(&(grp->sub_group));
+			break;
+		case WEIGHT_GROUP:
+			INFO("Weight group: %d\n", grp->weight);
+			print_server(grp->server);
+			break;
+		}
+	}
+}
+
+int jsonrpc_parse_server(char* server_s, jsonrpc_server_group_t **group_ptr)
+{
+	if(group_ptr == NULL) {
+		ERR("Trying to add server to null group ptr\n");
+		return -1;
+	}
+
+	str s;
+	param_hooks_t phooks;
+	param_t* pit=NULL;
+	param_t* freeme=NULL;
+	str conn;
+	str addr;
+	addr.s = NULL;
+	str srv;
+	srv.s = NULL;
+
+	unsigned int priority = JSONRPC_DEFAULT_PRIORITY;
+	unsigned int weight = JSONRPC_DEFAULT_WEIGHT;
+	unsigned int hwm = JSONRPC_DEFAULT_HWM;
+	unsigned int port = 0;
+
+	s.s = server_s;
+	s.len = strlen(server_s);
+	if (s.s[s.len-1] == ';')
+		s.len--;
+
+	if (parse_params(&s, CLASS_ANY, &phooks, &pit)<0) {
+		ERR("Failed parsing params value\n");
+		return -1;
+	}
+
+	freeme = pit;
+
+	for (; pit;pit=pit->next)
+	{
+		if PIT_MATCHES("conn") {
+			conn = shm_strdup(pit->body);
+			CHECK_MALLOC(conn.s);
+
+		} else if PIT_MATCHES("srv") {
+			srv = shm_strdup(pit->body);
+			CHECK_MALLOC(srv.s);
+
+		} else if PIT_MATCHES("addr") {
+			addr = shm_strdup(pit->body);
+			CHECK_MALLOC(addr.s);
+
+		} else if PIT_MATCHES("port") {
+			port = atoi(pit->body.s);
+
+		} else if PIT_MATCHES("priority") {
+			priority = atoi(pit->body.s);
+
+		} else if PIT_MATCHES("weight") {
+			weight = atoi(pit->body.s);
+
+		} else if PIT_MATCHES("hwm") {
+			hwm = atoi(pit->body.s);
+
+		} else if PIT_MATCHES("proto") {
+			if(strncmp(pit->body.s, "tcp", sizeof("tcp")-1) != 0) {
+				ERR("Unsupported proto=%.*s. Only tcp is supported.\n",
+						STR(pit->body));
+				goto error;
+			}
+		} else {
+			ERR("Unrecognized parameter: %.*s\n", STR(pit->name));
+			goto error;
+		}
+
+		DEBUG("%.*s = %.*s\n", STR(pit->name), STR(pit->body));
+	}
+
+	if(conn.s == NULL) {
+		ERR("No conn defined! conn parameter is required.\n");
+		goto error;
+	}
+
+	if (srv.s != NULL) {
+		if (addr.s != NULL
+			|| port != 0
+			|| weight != JSONRPC_DEFAULT_WEIGHT
+			|| priority != JSONRPC_DEFAULT_PRIORITY) {
+			ERR("addr, port, weight, and priority are not supported when using srv\n");
+			goto error;
+		}
+
+		if (jsonrpc_server_from_srv(conn, srv, hwm, group_ptr)<0) goto error;
+
+	} else {
+
+		if (addr.s == NULL || port == 0) {
+			ERR("no address/port defined\n");
+			goto error;
+		}
+
+		jsonrpc_server_t* server = create_server();
+		CHECK_MALLOC(server);
+
+		server->conn = conn;
+		server->addr = addr;
+		server->port = port;
+		server->priority = priority;
+		server->weight = weight;
+		server->hwm = hwm;
+
+		if(jsonrpc_add_server(server, group_ptr)<0) goto error;
+	}
+
+	//print_group(group_ptr); /* debug */
+
+	CHECK_AND_FREE(srv.s);
+	if (freeme) free_params(freeme);
+	return 0;
+
+error:
+	CHECK_AND_FREE(srv.s);
+	if (freeme) free_params(freeme);
+	return -1;
+}
+
+int jsonrpc_server_from_srv(str conn, str srv,
+		unsigned int hwm, jsonrpc_server_group_t** group_ptr)
+{
+	struct rdata *l, *head;
+	struct srv_rdata *srv_record;
+	str name;
+	unsigned int ttl = jsonrpc_min_srv_ttl;
+
+	jsonrpc_server_t* server = NULL;
+
+	resolv_init();
+
+	head = get_record(srv.s, T_SRV, RES_AR);
+	if (head == NULL) {
+		ERR("No SRV record returned for %.*s\n", STR(srv));
+		goto error;
+	}
+	for (l=head; l; l=l->next) {
+		if (l->type != T_SRV)
+			continue;
+		srv_record = (struct srv_rdata*)l->rdata;
+		if (srv_record == NULL) {
+			ERR("BUG: null rdata\n");
+			goto error;
+		}
+
+		if (l->ttl < jsonrpc_min_srv_ttl) {
+			ttl = jsonrpc_min_srv_ttl;
+		} else {
+			ttl = l->ttl;
+		}
+
+		name.s = srv_record->name;
+		name.len = srv_record->name_len;
+
+		DBG("server %s\n", srv_record->name);
+
+		server = create_server();
+		CHECK_MALLOC(server);
+
+		server->conn = shm_strdup(conn);
+		CHECK_MALLOC_GOTO(server->conn.s, error);
+
+		server->addr = shm_strdup(name);
+		CHECK_MALLOC_GOTO(server->addr.s, error);
+
+		server->srv = shm_strdup(srv);
+		CHECK_MALLOC_GOTO(server->srv.s, error);
+
+		server->port = srv_record->port;
+		server->priority = srv_record->priority;
+		server->weight = srv_record->weight;
+		server->ttl = ttl;
+		server->hwm = hwm;
+
+		if(jsonrpc_add_server(server, group_ptr)<0) goto error;
+	}
+
+	jsonrpc_srv_t* new_srv = create_srv(srv, conn, ttl);
+	addto_srv_list(new_srv, &global_srv_list);
+
+	free_rdata_list(head);
+
+	return 0;
+error:
+	CHECK_AND_FREE(server);
+	if (head) free_rdata_list(head);
+
+	return -1;
+}
+
+int create_server_group(server_group_t type, jsonrpc_server_group_t** grp)
+{
+	if(grp == NULL) {
+		ERR("Trying to dereference null group pointer\n");
+		return -1;
+	}
+
+	jsonrpc_server_group_t* new_grp =
+		shm_malloc(sizeof(jsonrpc_server_group_t));
+	CHECK_MALLOC(new_grp);
+
+	switch(type) {
+	case CONN_GROUP:
+		DEBUG("Creating new connection group\n");
+		new_grp->conn.s = NULL;
+		new_grp->conn.len = 0;
+		break;
+	case PRIORITY_GROUP:
+		DEBUG("Creating new priority group\n");
+		new_grp->priority = JSONRPC_DEFAULT_PRIORITY;
+		break;
+	case WEIGHT_GROUP:
+		DEBUG("Creating new weight group\n");
+		new_grp->server = NULL;
+		new_grp->weight = JSONRPC_DEFAULT_WEIGHT;
+		break;
+	}
+
+	new_grp->next = NULL;
+	new_grp->sub_group = NULL;
+	new_grp->type = type;
+	*grp = new_grp;
+	return 0;
+}
+
+void free_server_group(jsonrpc_server_group_t** grp)
+{
+	if(grp == NULL)
+		return;
+
+	jsonrpc_server_group_t* next = NULL;
+	jsonrpc_server_group_t* cgroup = NULL;
+	jsonrpc_server_group_t* pgroup = NULL;
+	jsonrpc_server_group_t* wgroup = NULL;
+
+	cgroup=*grp;
+	while(cgroup!=NULL) {
+		pgroup=cgroup->sub_group;
+		while(pgroup!=NULL) {
+			wgroup=pgroup->sub_group;
+			while(wgroup!=NULL) {
+				next = wgroup->next;
+				CHECK_AND_FREE(wgroup);
+				wgroup = next;
+			}
+			next = pgroup->next;
+			CHECK_AND_FREE(pgroup);
+			pgroup = next;
+		}
+		next = cgroup->next;
+		CHECK_AND_FREE(cgroup->conn.s);
+		CHECK_AND_FREE(cgroup);
+		cgroup = next;
+	}
+}
+
+int insert_server_group(jsonrpc_server_group_t* new_grp,
+		jsonrpc_server_group_t** parent)
+{
+	if(parent == NULL) {
+		ERR("Trying to insert into NULL group\n");
+		return -1;
+	}
+
+	jsonrpc_server_group_t* head = *parent;
+
+	if (head == NULL) {
+		*parent = new_grp;
+	} else {
+		if (new_grp->type != head->type) {
+			ERR("Inserting group (%d) into the wrong type of list (%d)\n",
+				new_grp->type, head->type);
+			return -1;
+		}
+
+		jsonrpc_server_group_t* current = head;
+		jsonrpc_server_group_t** prev = parent;
+
+		while (1) {
+			if(new_grp->type == PRIORITY_GROUP
+					&& new_grp->priority < current->priority) {
+			 /* Priority groups are organized in ascending order.*/
+				new_grp->next = current;
+				*prev = new_grp;
+				break;
+			} else if (new_grp->type == WEIGHT_GROUP ) {
+			/* Weight groups are special in how they are organized in order
+		     * to facilitate load balancing and weighted random selection.
+			 *
+			 * The weight in the head of a weight group list represents
+			 * the total weight of the list. Subsequent nodes represent the
+			 * remaining total.
+			 *
+			 * In order to achieve this, the weight to be inserted is added
+			 * to each node that is passed before insertion.
+			 *
+			 * Weight groups are organized in descending order.
+			 *
+			 * The actual weight of a node can be found in its server.
+			 * */
+				if(new_grp->server == NULL) {
+					ERR("Trying to insert an empty weight group.\n");
+					return -1;
+				}
+				if(new_grp->server->weight != new_grp->weight) {
+					ERR("Weight of the new node (%d) doesn't match its server (%d). This is a bug. Please report this to the maintainer.\n",
+							new_grp->server->weight, new_grp->weight);
+					return -1;
+				}
+				if(new_grp->weight > current->server->weight) {
+					new_grp->weight += current->weight;
+					new_grp->next = current;
+					*prev = new_grp;
+					break;
+				} else {
+					current->weight += new_grp->weight;
+				}
+			}
+
+			if(current->next == NULL) {
+				current->next = new_grp;
+				break;
+			}
+			prev = &((*prev)->next); // This is madness. Madness? THIS IS POINTERS!
+			current = current->next;
+		}
+	}
+	return 0;
+}
+
+unsigned int server_group_size(jsonrpc_server_group_t* grp)
+{
+	unsigned int size = 0;
+	for(;grp != NULL; grp=grp->next) {
+		size++;
+	}
+	return size;
+}
+
+jsonrpc_server_t* create_server()
+{
+	jsonrpc_server_t* server = shm_malloc(sizeof(jsonrpc_server_t));
+	CHECK_MALLOC_NULL(server);
+	memset(server, 0, sizeof(jsonrpc_server_t));
+
+	server->priority = JSONRPC_DEFAULT_PRIORITY;
+	server->weight = JSONRPC_DEFAULT_WEIGHT;
+	server->status = JSONRPC_SERVER_DISCONNECTED;
+
+	return server;
+}
+
+void free_server(jsonrpc_server_t* server)
+{
+	if(!server)
+		return;
+
+	CHECK_AND_FREE(server->conn.s);
+	CHECK_AND_FREE(server->addr.s);
+	CHECK_AND_FREE(server->srv.s);
+
+	if ((server->buffer)!=NULL) free_netstring(server->buffer);
+	memset(server, 0, sizeof(jsonrpc_server_t));
+	shm_free(server);
+	server = NULL;
+}
+
+int server_eq(jsonrpc_server_t* a, jsonrpc_server_t* b)
+{
+	if(!a || !b)
+		return 0;
+
+	if(!STR_EQ(a->conn, b->conn)) return 0;
+	if(!STR_EQ(a->srv, b->srv)) return 0;
+	if(!STR_EQ(a->addr, b->addr)) return 0;
+	if(a->port != b->port) return 0;
+	if(a->priority != b->priority) return 0;
+	if(a->weight != b->weight) return 0;
+
+	return 1;
+}
+
+int jsonrpc_add_server(jsonrpc_server_t* server, jsonrpc_server_group_t** group_ptr)
+{
+	jsonrpc_server_group_t* conn_grp = NULL;
+	jsonrpc_server_group_t* priority_grp = NULL;
+	jsonrpc_server_group_t* weight_grp = NULL;
+
+	if(group_ptr == NULL) {
+		ERR("Trying to add server to null group\n");
+		return -1;
+	}
+
+	if(create_server_group(WEIGHT_GROUP, &weight_grp) < 0) goto error;
+
+	weight_grp->weight = server->weight;
+	weight_grp->server = server;
+
+	/* find conn group */
+	for (conn_grp=*group_ptr; conn_grp != NULL; conn_grp=conn_grp->next) {
+		if (strncmp(conn_grp->conn.s, server->conn.s, server->conn.len) == 0)
+			break;
+	}
+
+	if (conn_grp == NULL) {
+		if(create_server_group(CONN_GROUP, &conn_grp) < 0) goto error;
+		if(create_server_group(PRIORITY_GROUP, &priority_grp) < 0) goto error;
+
+		priority_grp->priority = server->priority;
+		priority_grp->sub_group = weight_grp;
+
+		conn_grp->conn = shm_strdup(server->conn);
+		CHECK_MALLOC_GOTO(conn_grp->conn.s, error);
+
+		conn_grp->sub_group = priority_grp;
+		if(insert_server_group(conn_grp, group_ptr) < 0) goto error;
+		goto success;
+	}
+
+	/* find priority group */
+	for (priority_grp=conn_grp->sub_group;
+			priority_grp != NULL;
+			priority_grp=priority_grp->next) {
+		if (priority_grp->priority == server->priority) break;
+	}
+
+	if (priority_grp == NULL) {
+		if(create_server_group(PRIORITY_GROUP, &priority_grp) < 0) goto error;
+
+		priority_grp->priority = server->priority;
+		priority_grp->sub_group = weight_grp;
+
+		if(insert_server_group(priority_grp, &(conn_grp->sub_group)) < 0) goto error;
+		goto success;
+	}
+
+	if(insert_server_group(weight_grp, &(priority_grp->sub_group)) < 0) goto error;
+
+success:
+	return 0;
+error:
+	ERR("Failed to add server: %s, %s, %d\n",
+			server->conn.s, server->addr.s, server->port);
+	CHECK_AND_FREE(conn_grp);
+	CHECK_AND_FREE(priority_grp);
+	CHECK_AND_FREE(weight_grp);
+	CHECK_AND_FREE(server);
+	return -1;
+}
+
+void addto_server_list(jsonrpc_server_t* server, server_list_t** list)
+{
+	server_list_t* new_node = (server_list_t*)pkg_malloc(sizeof(server_list_t));
+	CHECK_MALLOC_VOID(new_node);
+
+	new_node->server = server;
+	new_node->next = NULL;
+
+	if (*list == NULL) {
+		*list = new_node;
+		return;
+	}
+
+	server_list_t* node = *list;
+	for(; node->next!=NULL; node=node->next);
+
+	node->next = new_node;
+}
+
+void free_server_list(server_list_t* list)
+{
+	if (!list)
+		return;
+
+	server_list_t* node = NULL;
+	for(node=list; node!=NULL; node=node->next)
+	{
+		pkg_free(node);
+	}
+}
+
+void close_server(jsonrpc_server_t* server)
+{
+	if(!server)
+		return;
+
+	INFO("Closing server %.*s:%d for conn %.*s.\n",
+			STR(server->addr), server->port, STR(server->conn));
+	force_disconnect(server);
+
+	free_server(server);
+}
+
diff --git a/modules/janssonrpc-c/janssonrpc_server.h b/modules/janssonrpc-c/janssonrpc_server.h
new file mode 100644
index 0000000..0c71630
--- /dev/null
+++ b/modules/janssonrpc-c/janssonrpc_server.h
@@ -0,0 +1,130 @@
+/**
+ * Copyright (C) 2013 Flowroute LLC (flowroute.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef _JANSSONRPC_SERVER_H_
+#define _JANSSONRPC_SERVER_H_
+
+#include <stdbool.h>
+#include <event.h>
+#include <event2/bufferevent.h>
+#include <event2/buffer.h>
+#include "../../locking.h"
+#include "netstring.h"
+
+/* interval (in seconds) at which failed servers are retried */
+#define JSONRPC_RECONNECT_INTERVAL  3
+
+/* default values */
+#define JSONRPC_DEFAULT_PRIORITY 0
+#define JSONRPC_DEFAULT_WEIGHT 1
+#define JSONRPC_DEFAULT_HWM 0 /* unlimited */
+
+typedef struct jsonrpc_server {
+	str conn, addr, srv; /* shared mem */
+	int port;
+	unsigned int  status, ttl, hwm;
+	unsigned int  req_count;
+	unsigned int priority, weight;
+	bool added;
+	struct bufferevent* bev; /* local mem */
+	netstring_t* buffer;
+} jsonrpc_server_t;
+
+typedef enum {
+	CONN_GROUP,
+	PRIORITY_GROUP,
+	WEIGHT_GROUP
+} server_group_t;
+
+/* servers are organized in the following order:
+ * 1) conn
+ * 2) priority
+ * 3) weight
+ ***/
+typedef struct jsonrpc_server_group {
+	server_group_t type;
+	struct jsonrpc_server_group* sub_group; // NULL when type is WEIGHT_GROUP
+	union {
+		str conn; // when type is CONN_GROUP
+		unsigned int priority; // when type is PRIORITY_GROUP
+		unsigned int weight; //when type is WEIGHT_GROUP
+	};
+	jsonrpc_server_t* server; // only when type is WEIGHT_GROUP
+	struct jsonrpc_server_group* next;
+} jsonrpc_server_group_t;
+
+gen_lock_t* jsonrpc_server_group_lock;
+
+typedef struct server_list {
+	jsonrpc_server_t* server;
+	struct server_list* next;
+} server_list_t;
+
+/* where all the servers are stored */
+jsonrpc_server_group_t** global_server_group;
+
+int  jsonrpc_parse_server(char *_server, jsonrpc_server_group_t** group_ptr);
+int jsonrpc_server_from_srv(str conn, str srv,
+		unsigned int hwm, jsonrpc_server_group_t** group_ptr);
+
+void close_server(jsonrpc_server_t* server);
+/* Do not call close_server() from outside the IO process.
+ * Server's have a bufferevent that is part of local memory and free'd
+ * at disconnect */
+
+jsonrpc_server_t* create_server();
+void free_server(jsonrpc_server_t* server);
+int create_server_group(server_group_t type, jsonrpc_server_group_t** new_grp);
+int jsonrpc_add_server(jsonrpc_server_t* server, jsonrpc_server_group_t** group);
+unsigned int  server_group_size(jsonrpc_server_group_t* group);
+void free_server_group(jsonrpc_server_group_t** grp);
+int server_eq(jsonrpc_server_t* a, jsonrpc_server_t* b);
+void addto_server_list(jsonrpc_server_t* server, server_list_t** list);
+void free_server_list(server_list_t* list);
+
+#define INIT_SERVER_LOOP  \
+	jsonrpc_server_group_t* cgroup = NULL; \
+	jsonrpc_server_group_t* pgroup = NULL; \
+	jsonrpc_server_group_t* wgroup = NULL; \
+	jsonrpc_server_t* server = NULL;
+
+#define FOREACH_SERVER_IN(ii) \
+	if(ii == NULL) { \
+		cgroup = NULL; \
+	} else { \
+		cgroup = *(ii); \
+	} \
+	pgroup = NULL; \
+	wgroup = NULL; \
+	server = NULL; \
+	for(; cgroup!=NULL; cgroup=cgroup->next) { \
+		for(pgroup=cgroup->sub_group; pgroup!=NULL; pgroup=pgroup->next) { \
+			for(wgroup=pgroup->sub_group; wgroup!=NULL; wgroup=wgroup->next) { \
+				server = wgroup->server;
+
+#define ENDFOR }}}
+
+/* debugging only */
+void print_server(jsonrpc_server_t* server);
+void print_group(jsonrpc_server_group_t** group);
+
+#endif /* _JSONRPC_SERVER_H_ */
diff --git a/modules/janssonrpc-c/janssonrpc_srv.c b/modules/janssonrpc-c/janssonrpc_srv.c
new file mode 100644
index 0000000..82d8298
--- /dev/null
+++ b/modules/janssonrpc-c/janssonrpc_srv.c
@@ -0,0 +1,315 @@
+/**
+ * Copyright (C) 2013 Flowroute LLC (flowroute.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <string.h>
+#include <fcntl.h>
+
+#include "../../sr_module.h"
+#include "../../route.h"
+#include "../../route_struct.h"
+#include "../../resolve.h"
+#include "../../parser/parse_param.h"
+#include "../../mem/mem.h"
+#include "../../lvalue.h"
+#include "../../str.h"
+
+#include "janssonrpc.h"
+#include "janssonrpc_srv.h"
+#include "janssonrpc_request.h"
+#include "janssonrpc_io.h"
+#include "janssonrpc_server.h"
+
+int refresh_srv(jsonrpc_srv_t* srv_obj)
+{
+	DEBUG("Refreshing SRV for %.*s\n", STR(srv_obj->srv));
+	int retval = 0;
+
+	if(!srv_obj) {
+		ERR("Trying to refresh NULL SRV\n");
+		return -1;
+	}
+
+	unsigned int ttl = ABSOLUTE_MIN_SRV_TTL;
+	str srv = srv_obj->srv;
+	jsonrpc_server_group_t* conn_group = srv_obj->cgroup;
+
+	if(!conn_group) {
+		ERR("SRV (%.*s) has no connections\n", STR(srv));
+		return -1;
+	}
+
+	struct rdata *l, *head;
+	struct srv_rdata *srv_record;
+	str name;
+
+	jsonrpc_server_group_t* new_grp = NULL;
+
+	// dns lookup
+	head = get_record(srv.s, T_SRV, RES_AR);
+	if (head == NULL) {
+		ERR("No SRV record returned for %.*s\n", STR(srv));
+		return -1;
+	}
+
+	// get all the servers from the srv record
+	server_list_t* new_servers = NULL;
+	jsonrpc_server_t* new_server = NULL;
+	server_list_t* rm_servers = NULL;
+	jsonrpc_server_t* rm_server = NULL;
+	int iter = 0;
+	for (l=head, iter=0; l; l=l->next, iter++) {
+		if (l->type != T_SRV)
+			continue;
+		srv_record = (struct srv_rdata*)l->rdata;
+		if (srv_record == NULL) {
+			ERR("BUG: null rdata\n");
+			return -1;
+		}
+
+		if (l->ttl < jsonrpc_min_srv_ttl) {
+			ttl = jsonrpc_min_srv_ttl;
+		} else {
+			ttl = l->ttl;
+		}
+
+		srv_obj->ttl = ttl;
+
+		name.s = srv_record->name;
+		name.len = srv_record->name_len;
+
+		DBG("server %s\n", srv_record->name);
+
+		jsonrpc_server_group_t* cgroup = NULL;
+		for(cgroup=conn_group; cgroup!=NULL; cgroup=cgroup->next) {
+			new_server = create_server();
+			CHECK_MALLOC(new_server);
+
+			new_server->conn = shm_strdup(cgroup->conn);
+			CHECK_MALLOC(new_server->conn.s);
+
+			new_server->addr = shm_strdup(name);
+			CHECK_MALLOC(new_server->addr.s);
+
+			new_server->srv = shm_strdup(srv);
+			CHECK_MALLOC(new_server->srv.s);
+
+			new_server->port = srv_record->port;
+			new_server->priority = srv_record->priority;
+			new_server->weight = srv_record->weight;
+			new_server->ttl = ttl;
+			new_server->added = false;
+
+			addto_server_list(new_server, &new_servers);
+		}
+	}
+
+	if(iter <= 0) goto end;
+
+	/* aquire global_server_group lock */
+	/* this lock is only released when the old global_server_group
+	 * is freed in the IO process */
+	lock_get(jsonrpc_server_group_lock); /* blocking */
+	//print_group(global_server_group); /* debug */
+
+
+	INIT_SERVER_LOOP
+
+	// copy existing servers
+	server_list_t* node;
+	FOREACH_SERVER_IN(global_server_group)
+		server->added = false;
+		if(STR_EQ(server->srv, srv)) {
+			for(node=new_servers; node!=NULL; node=node->next) {
+				new_server = node->server;
+				if(server_eq(new_server, server)) {
+					new_server->added = true;
+					server->added = true;
+					server->ttl = srv_obj->ttl;
+					jsonrpc_add_server(server, &new_grp);
+				}
+			}
+		} else {
+			server->added = true;
+			jsonrpc_add_server(server, &new_grp);
+		}
+	ENDFOR
+
+	FOREACH_SERVER_IN(global_server_group)
+		if(server->added == false) {
+			addto_server_list(server, &rm_servers);
+		}
+	ENDFOR
+
+	// add and connect new servers
+	for(node=new_servers; node!=NULL; node=node->next) {
+		new_server = node->server;
+		if(new_server->added == false) {
+
+			jsonrpc_add_server(new_server, &new_grp);
+
+			if(send_pipe_cmd(CMD_CONNECT, new_server) <0) {
+				print_server(new_server);
+			}
+
+		} else {
+			free_server(new_server);
+		}
+	}
+
+	// close old servers
+	for(node=rm_servers; node!=NULL; node=node->next) {
+
+		rm_server = node->server;
+
+		if(send_pipe_cmd(CMD_CLOSE, rm_server) <0) {
+			print_server(rm_server);
+		}
+	}
+
+	if(send_pipe_cmd(CMD_UPDATE_SERVER_GROUP, new_grp)<0) {
+		free_server_group(&new_grp);
+		lock_release(jsonrpc_server_group_lock);
+	}
+
+end:
+	// free server lists
+	free_server_list(new_servers);
+	free_server_list(rm_servers);
+
+	return retval;
+}
+
+void free_srv(jsonrpc_srv_t* srv)
+{
+	if(!srv)
+		return;
+
+	CHECK_AND_FREE(srv->srv.s);
+
+	free_server_group(&(srv->cgroup));
+}
+
+jsonrpc_srv_t* create_srv(str srv, str conn, unsigned int ttl)
+{
+	jsonrpc_srv_t* new_srv = shm_malloc(sizeof(jsonrpc_srv_t));
+	if(!new_srv) goto error;
+	new_srv->srv = shm_strdup(srv);
+
+	if (ttl < jsonrpc_min_srv_ttl) {
+		new_srv->ttl = jsonrpc_min_srv_ttl;
+	} else {
+		new_srv->ttl = ttl;
+	}
+
+	if(create_server_group(CONN_GROUP, &(new_srv->cgroup))<0) goto error;
+	new_srv->cgroup->conn = shm_strdup(conn);
+	if(!(new_srv->cgroup->conn.s)) return NULL;
+
+	return new_srv;
+error:
+	ERR("create_srv failed\n");
+	free_srv(new_srv);
+	return NULL;
+}
+
+void refresh_srv_cb(unsigned int ticks, void* params)
+{
+	if(!params) {
+		ERR("params is (null)\n");
+		return;
+	}
+
+	if(!global_srv_list) {
+		return;
+	}
+
+	srv_cb_params_t* p = (srv_cb_params_t*)params;
+
+	cmd_pipe = p->cmd_pipe;
+	jsonrpc_min_srv_ttl = p->srv_ttl;
+
+	if(cmd_pipe == 0) {
+		ERR("cmd_pipe is not set\n");
+		return;
+	}
+
+	jsonrpc_srv_t* srv;
+	for(srv=global_srv_list; srv!=NULL; srv=srv->next) {
+		if(ticks % srv->ttl == 0) {
+			refresh_srv(srv);
+		}
+	}
+
+}
+
+void addto_srv_list(jsonrpc_srv_t* srv, jsonrpc_srv_t** list)
+{
+	if (*list == NULL) {
+		*list = srv;
+		return;
+	}
+
+	jsonrpc_srv_t* node = *list;
+	jsonrpc_srv_t* prev = *list;
+	jsonrpc_server_group_t* cgroup;
+	jsonrpc_server_group_t* cprev;
+	for(node=*list; node!=NULL; prev=node, node=node->next) {
+		if(STR_EQ(srv->srv, node->srv)) {
+			for(cgroup=node->cgroup, cprev=node->cgroup;
+					cgroup!=NULL;
+					cprev=cgroup, cgroup=cgroup->next) {
+				if(STR_EQ(cgroup->conn, srv->cgroup->conn)) {
+					INFO("Trying to add identical srv\n");
+					goto clean;
+				}
+			}
+			if(create_server_group(CONN_GROUP, &(cprev->next))<0) goto clean;
+			cprev->next->conn = shm_strdup(srv->cgroup->conn);
+			CHECK_MALLOC_GOTO(cprev->next->conn.s, clean);
+			node->ttl = srv->ttl;
+			goto clean;
+		}
+	}
+
+	prev->next = srv;
+	return;
+clean:
+	free_srv(srv);
+}
+
+void print_srv(jsonrpc_srv_t* list)
+{
+	INFO("------SRV list------\n");
+	jsonrpc_srv_t* node = NULL;
+	for(node=list; node!=NULL; node=node->next) {
+		INFO("-----------------\n");
+		INFO("| srv: %.*s\n", STR(node->srv));
+		INFO("| ttl: %d\n", node->ttl);
+		print_group(&(node->cgroup));
+		INFO("-----------------\n");
+	}
+}
+
diff --git a/modules/janssonrpc-c/janssonrpc_srv.h b/modules/janssonrpc-c/janssonrpc_srv.h
new file mode 100644
index 0000000..c902183
--- /dev/null
+++ b/modules/janssonrpc-c/janssonrpc_srv.h
@@ -0,0 +1,53 @@
+/**
+ * Copyright (C) 2013 Flowroute LLC (flowroute.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef _JANSSONRPC_SRV_H_
+#define _JANSSONRPC_SRV_H_
+
+#include "janssonrpc_server.h"
+
+typedef struct jsonrpc_srv jsonrpc_srv_t;
+struct jsonrpc_srv {
+	str srv;
+	unsigned int ttl;
+	jsonrpc_server_group_t* cgroup;
+	jsonrpc_srv_t* next;
+};
+
+typedef struct srv_cb_params {
+	int cmd_pipe;
+	unsigned int srv_ttl;
+} srv_cb_params_t;
+
+jsonrpc_srv_t* global_srv_list;
+
+unsigned int jsonrpc_min_srv_ttl;
+
+jsonrpc_srv_t* create_srv(str srv, str conn, unsigned int ttl);
+void addto_srv_list(jsonrpc_srv_t* srv, jsonrpc_srv_t** list);
+void refresh_srv_cb(unsigned int ticks, void* params);
+void print_srv(jsonrpc_srv_t* list);
+
+#define JSONRPC_DEFAULT_MIN_SRV_TTL 5
+#define ABSOLUTE_MIN_SRV_TTL 1
+
+#endif /* _JSONRPC_SRV_H_ */
diff --git a/modules/janssonrpc-c/netstring.c b/modules/janssonrpc-c/netstring.c
new file mode 100644
index 0000000..a559224
--- /dev/null
+++ b/modules/janssonrpc-c/netstring.c
@@ -0,0 +1,323 @@
+/**
+ * Copyright (C) 2013 Flowroute LLC (flowroute.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <math.h>
+#include <sys/socket.h>
+#include "netstring.h"
+#include "janssonrpc.h"
+
+#ifdef TEST
+#include "unit_tests/test.h"
+#else
+#include "../../mem/mem.h"
+#endif
+
+
+void free_netstring(netstring_t* netstring) {
+	if(!netstring) return;
+	if(netstring->buffer) pkg_free(netstring->buffer);
+	pkg_free(netstring);
+}
+
+//TODO: refactor out common code in the following two functions
+
+int netstring_read_evbuffer(struct bufferevent *bev, netstring_t **netstring)
+{
+	int bytes, offset;
+	size_t read_len;
+	char *temp_buffer;
+	temp_buffer = NULL;
+	offset = 0;
+	struct evbuffer *ib = bufferevent_get_input(bev);
+
+	if (*netstring == NULL) {
+		/* No buffer yet. Peek at first 10 bytes, to get length and colon. */
+		unsigned char *lenstr;
+		int i, len;
+		struct evbuffer_ptr *search_end = pkg_malloc(sizeof(struct evbuffer_ptr));
+		CHECK_MALLOC(search_end);
+
+		i = evbuffer_get_length(ib);
+		len = ((NETSTRING_PEEKLEN <= i) ? (NETSTRING_PEEKLEN) : (i-1));
+		evbuffer_ptr_set(ib, search_end, len, EVBUFFER_PTR_SET);
+		struct evbuffer_ptr loc = evbuffer_search_range(ib, ":", 1, NULL, search_end);
+		pkg_free(search_end);
+		if (loc.pos < 0) {
+			// no colon found
+			if (i > NETSTRING_PEEKLEN)
+				return NETSTRING_ERROR_TOO_LONG;
+			// TODO: peek at what's available and return suitable errors
+			return NETSTRING_INCOMPLETE;
+		}
+
+
+		lenstr = pkg_malloc(loc.pos+1);
+		CHECK_MALLOC(lenstr);
+		bytes = evbuffer_remove(ib, lenstr, loc.pos+1);
+
+		/* First character must be a digit */
+		if (!isdigit(lenstr[0]))
+			return NETSTRING_ERROR_NO_LENGTH;
+
+		/* No leading zeros allowed! */
+		if (lenstr[0] == '0' && isdigit(lenstr[1]))
+			return NETSTRING_ERROR_LEADING_ZERO;
+		if (lenstr[loc.pos] != ':') {
+			return NETSTRING_ERROR_NO_COLON;
+		}
+		len = i = 0;
+
+		/* Read the number of bytes */
+		for (i = 0; i < loc.pos; i++) {
+			/* Accumulate each digit, assuming ASCII. */
+			len = len*10 + (lenstr[i] - '0');
+		}
+		pkg_free(lenstr);
+		/* alloc the memory needed for the whole netstring */
+		read_len = len+1;
+		temp_buffer = pkg_malloc(read_len);
+		CHECK_MALLOC(temp_buffer);
+
+		/* initialize the netstring struct */
+		*netstring = pkg_malloc(sizeof(netstring_t));
+		CHECK_MALLOC(netstring);
+		(*netstring)->read = 0;
+		(*netstring)->length = len;
+		(*netstring)->buffer = temp_buffer;
+		(*netstring)->string = NULL;
+	} else {
+		/* Continue reading into an existing buffer. */
+		offset = (*netstring)->read;
+		read_len = (*netstring)->length-offset+1;
+		temp_buffer = (*netstring)->buffer + offset;
+	}
+
+	/* Read from the evbuffer */
+	bytes = evbuffer_remove(ib, temp_buffer, read_len);
+	int total = (*netstring)->read += bytes;
+
+	/* See if we have the whole netstring yet */
+	if (read_len > bytes) {
+		return NETSTRING_INCOMPLETE;
+	}
+
+	/* Test for the trailing comma */
+	if (((*netstring)->buffer)[total-1] != ',') {
+		return NETSTRING_ERROR_NO_COMMA;
+	}
+
+	/* Replace the comma with \0 */
+	(*netstring)->buffer[total-1] = '\0';
+
+	/* Set the string pointer to the "body" of the netstring */
+	(*netstring)->string = (*netstring)->buffer;
+	return 0;
+}
+
+int netstring_read_fd(int fd, netstring_t **netstring)
+{
+	int bytes, offset;
+	size_t read_len;
+	char *temp_buffer;
+	temp_buffer = NULL;
+	offset = 0;
+
+	if (*netstring == NULL) {
+		/* No buffer yet. Peek at first 10 bytes, to get length and colon. */
+		char peek[10]={0};
+		bytes = recv(fd,peek,10,MSG_PEEK);
+
+		if (bytes < 3) return NETSTRING_INCOMPLETE;
+
+		/* No leading zeros allowed! */
+		if (peek[0] == '0' && isdigit(peek[1]))
+			return NETSTRING_ERROR_LEADING_ZERO;
+
+		/* The netstring must start with a number */
+		if (!isdigit(peek[0])) return NETSTRING_ERROR_NO_LENGTH;
+
+		int i, len;
+		len = i = 0;
+
+		/* Read the number of bytes */
+		for (i = 0; i < bytes && isdigit(peek[i]); i++) {
+			/* Error if more than 9 digits */
+			if (i >= 9) return NETSTRING_ERROR_TOO_LONG;
+			/* Accumulate each digit, assuming ASCII. */
+			len = len*10 + (peek[i] - '0');
+		}
+
+		/* Read the colon */
+		if (peek[i++] != ':') return NETSTRING_ERROR_NO_COLON;
+
+		/* alloc the memory needed for the whole netstring */
+		read_len = len+i+1;
+		temp_buffer = pkg_malloc(read_len);
+		CHECK_MALLOC(temp_buffer);
+
+		/* initialize the netstring struct */
+		*netstring = pkg_malloc(sizeof(netstring_t));
+		CHECK_MALLOC(netstring);
+		(*netstring)->start = i;
+		(*netstring)->read = 0;
+		(*netstring)->length = len;
+		(*netstring)->buffer = temp_buffer;
+		(*netstring)->string = NULL;
+	} else {
+		/* Continue reading into an existing buffer. */
+		offset = (*netstring)->read;
+		read_len = (*netstring)->start+(*netstring)->length-offset+1;
+		temp_buffer = (*netstring)->buffer + offset;
+	}
+
+	/* Read from the socket */
+	bytes = recv(fd, temp_buffer, read_len, 0);
+	int total = (*netstring)->read += bytes;
+
+	/* See if we have the whole netstring yet */
+	if (read_len > bytes) {
+		return NETSTRING_INCOMPLETE;
+	}
+
+	/* Test for the trailing comma */
+	if (((*netstring)->buffer)[total-1] != ',') {
+		return NETSTRING_ERROR_NO_COMMA;
+	}
+
+	/* Replace the comma with \0 */
+	(*netstring)->buffer[total-1] = '\0';
+
+	/* Set the string pointer to the "body" of the netstring */
+	(*netstring)->string = (*netstring)->buffer + (*netstring)->start;
+	return 0;
+}
+
+
+/* Reads a netstring from a `buffer` of length `buffer_length`. Writes
+   to `netstring_start` a pointer to the beginning of the string in
+   the buffer, and to `netstring_length` the length of the
+   string. Does not allocate any memory. If it reads successfully,
+   then it returns 0. If there is an error, then the return value will
+   be negative. The error values are:
+
+   NETSTRING_ERROR_TOO_LONG      More than 999999999 bytes in a field
+   NETSTRING_ERROR_NO_COLON      No colon was found after the number
+   NETSTRING_ERROR_TOO_SHORT     Number of bytes greater than buffer length
+   NETSTRING_ERROR_NO_COMMA      No comma was found at the end
+   NETSTRING_ERROR_LEADING_ZERO  Leading zeros are not allowed
+   NETSTRING_ERROR_NO_LENGTH     Length not given at start of netstring
+
+   If you're sending messages with more than 999999999 bytes -- about
+   1 GB -- then you probably should not be doing so in the form of a
+   single netstring. This restriction is in place partially to protect
+   from malicious or erroneous input, and partly to be compatible with
+   D. J. Bernstein's reference implementation.
+
+   Example:
+	if (netstring_read("3:foo,", 6, &str, &len) < 0) explode_and_die();
+*/
+
+int netstring_read(char *buffer, size_t buffer_length,
+			char **netstring_start, size_t *netstring_length)
+{
+	int i;
+	size_t len = 0;
+
+	/* Write default values for outputs */
+	*netstring_start = NULL; *netstring_length = 0;
+
+	/* Make sure buffer is big enough. Minimum size is 3. */
+	if (buffer_length < 3) return NETSTRING_ERROR_TOO_SHORT;
+
+	/* No leading zeros allowed! */
+	if (buffer[0] == '0' && isdigit(buffer[1]))
+		return NETSTRING_ERROR_LEADING_ZERO;
+
+	/* The netstring must start with a number */
+	if (!isdigit(buffer[0])) return NETSTRING_ERROR_NO_LENGTH;
+
+	/* Read the number of bytes */
+	for (i = 0; i < buffer_length && isdigit(buffer[i]); i++) {
+		/* Error if more than 9 digits */
+		if (i >= 9) return NETSTRING_ERROR_TOO_LONG;
+		/* Accumulate each digit, assuming ASCII. */
+		len = len*10 + (buffer[i] - '0');
+	}
+
+	/* Check buffer length once and for all. Specifically, we make sure
+		 that the buffer is longer than the number we've read, the length
+		 of the string itself, and the colon and comma. */
+	if (i + len + 1 >= buffer_length) return NETSTRING_ERROR_TOO_SHORT;
+
+	/* Read the colon */
+	if (buffer[i++] != ':') return NETSTRING_ERROR_NO_COLON;
+
+	/* Test for the trailing comma, and set the return values */
+	if (buffer[i + len] != ',') return NETSTRING_ERROR_NO_COMMA;
+	*netstring_start = &buffer[i]; *netstring_length = len;
+
+	return 0;
+}
+
+/* Return the length, in ASCII characters, of a netstring containing
+   `data_length` bytes. */
+size_t netstring_buffer_size(size_t data_length)
+{
+	if (data_length == 0) return 3;
+	return (size_t)ceil(log10((double)data_length + 1)) + data_length + 2;
+}
+
+/* Allocate and create a netstring containing the first `len` bytes of
+   `data`. This must be manually freed by the client. If `len` is 0
+   then no data will be read from `data`, and it may be NULL. */
+size_t netstring_encode_new(char **netstring, char *data, size_t len)
+{
+	char *ns;
+	size_t num_len = 1;
+
+	*netstring = NULL;
+
+	if (len == 0) {
+		ns = pkg_malloc(3);
+		if (!ns) {
+			return JSONRPC_ERROR_NO_MEMORY;
+		}
+		ns[0] = '0';
+		ns[1] = ':';
+		ns[2] = ',';
+	} else {
+		num_len = (size_t)ceil(log10((double)len + 1));
+		ns = pkg_malloc(num_len + len + 2);
+		if (!ns) {
+			return JSONRPC_ERROR_NO_MEMORY;
+		}
+		sprintf(ns, "%lu:", (unsigned long)len);
+		memcpy(ns + num_len + 1, data, len);
+		ns[num_len + len + 1] = ',';
+	}
+
+	*netstring = ns;
+	return num_len + len + 2;
+}
diff --git a/modules/janssonrpc-c/netstring.h b/modules/janssonrpc-c/netstring.h
new file mode 100644
index 0000000..edba4cc
--- /dev/null
+++ b/modules/janssonrpc-c/netstring.h
@@ -0,0 +1,62 @@
+/**
+ * Copyright (C) 2013 Flowroute LLC (flowroute.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __NETSTRING_STREAM_H
+#define __NETSTRING_STREAM_H
+
+#include <string.h>
+#include <event2/bufferevent.h>
+
+typedef struct {
+	char* buffer;
+	char* string;
+	unsigned int start, read, length;
+} netstring_t;
+
+void free_netstring(netstring_t* netstring);
+
+int netstring_read_evbuffer(struct bufferevent *bev, netstring_t **netstring);
+
+int netstring_read_fd(int fd, netstring_t **netstring);
+
+int netstring_read(char *buffer, size_t buffer_length,
+		   char **netstring_start, size_t *netstring_length);
+
+size_t netstring_buffer_size(size_t data_length);
+
+size_t netstring_encode_new(char **netstring, char *data, size_t len);
+
+/* Errors that can occur during netstring parsing */
+typedef enum {
+	NETSTRING_ERROR_TOO_LONG = -1000,
+	NETSTRING_ERROR_NO_COLON,
+	NETSTRING_ERROR_TOO_SHORT,
+	NETSTRING_ERROR_NO_COMMA,
+	NETSTRING_ERROR_LEADING_ZERO,
+	NETSTRING_ERROR_NO_LENGTH,
+	NETSTRING_ERROR_BAD_FD,
+	NETSTRING_INCOMPLETE
+} netstring_errors;
+
+#define NETSTRING_PEEKLEN 10
+
+#endif
diff --git a/modules/janssonrpc-c/test/mem-test.sh b/modules/janssonrpc-c/test/mem-test.sh
new file mode 100755
index 0000000..5405101
--- /dev/null
+++ b/modules/janssonrpc-c/test/mem-test.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+cd ../../../
+valgrind --leak-check=full ./kamailio -w . -E -f modules/jsonrpc-c/test/test.cfg -m 256 -M 256
diff --git a/modules/janssonrpc-c/test/run-tests.sh b/modules/janssonrpc-c/test/run-tests.sh
new file mode 100755
index 0000000..302b63b
--- /dev/null
+++ b/modules/janssonrpc-c/test/run-tests.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+cd ../../../
+./kamailio -w . -E -f modules/jsonrpc-c/test/test.cfg -m 256 -M 256
diff --git a/modules/janssonrpc-c/test/test.cfg b/modules/janssonrpc-c/test/test.cfg
new file mode 100644
index 0000000..6dd16cc
--- /dev/null
+++ b/modules/janssonrpc-c/test/test.cfg
@@ -0,0 +1,94 @@
+#
+# $Id$
+#
+# jsonrpc module testing script
+
+debug = 2
+memlog=1   # debug level is higher or equal memlog
+mem_summary=8
+log_stderror=yes
+fork=no
+children=1
+listen = 127.0.0.1:5060
+
+check_via=no    # (cmd. line: -v)
+dns=yes          # (cmd. line: -r)
+rev_dns=no      # (cmd. line: -R)
+sip_warning=yes
+
+# ------------------ module loading ----------------------------------
+
+loadpath "modules:modules_k"
+
+loadmodule "pv"
+loadmodule "tm"
+loadmodule "json"
+loadmodule "xlog"
+loadmodule "jsonrpc-c"
+
+#modparam("jsonrpc", "min_srv_ttl", 1);
+modparam("jsonrpc", "result_pv", "$var(foobar)");
+modparam("jsonrpc", "server", "conn=pingpong;addr=foobar;port=7080;priority=10;weight=0;hwm=1");
+#modparam("jsonrpc", "server", "conn=pingpong;addr=localhost;port=7081;priority=10;weight=0;hwm=10");
+#modparam("jsonrpc", "server", "conn=pingpong;addr=localhost;port=7082;priority=10;weight=0;hwm=10");
+#modparam("jsonrpc", "server", "conn=pingpong;addr=localhost;port=7083;priority=10;weight=0;hwm=10");
+#modparam("jsonrpc", "server", "conn=pingpong;addr=localhost;port=7084;priority=10;weight=0;hwm=1");
+#modparam("jsonrpc", "server", "conn=fail;addr=localhost;port=9999;priority=10;weight=0");
+#modparam("jsonrpc", "server", "conn=test0;srv=_test0._tcp.sandbox.internal");
+#modparam("jsonrpc", "server", "conn=test0;srv=_test1._tcp.sandbox.internal");
+#modparam("jsonrpc", "server", "conn=tests;srv=_test2._tcp.sandbox.internal");
+
+
+# ------------------- unit tests ------------------------------------
+
+route {
+
+    jsonrpc_request("test0", "echo", '[{"foo":"bar"}]', "route=RESPONSE;retry=10;timeout=30");
+
+    xlog("done\n");
+}
+
+route[RESPONSE] {
+    if(json_get($var(jsrpc_result), "internal_error", "$var(internal)")) {
+        route(INTERNAL);
+    } else if(json_get($var(jsrpc_result), "error", "$var(error)")) {
+        route(ERROR);
+    } else if(json_get($var(jsrpc_result), "result", "$var(result)")) {
+        route(RESULT);
+    }
+    t_reply("200", "OK");
+}
+
+route[RESULT] {
+    xlog("result is $var(result)\n");
+    xlog("success\n");
+}
+
+route[ERROR] {
+    xlog("There was an error\n");
+    if(json_get($var(error), "code", "$var(c)")) {
+        xlog("code is $var(c)\n");
+    }
+
+    if(json_get($var(error), "message", "$var(r)")) {
+        xlog("error is $var(r)\n");
+    }
+
+    if(json_get($var(error), "data", "$var(d)")) {
+        xlog("data is $var(d)\n");
+    }
+}
+
+route[INTERNAL] {
+    xlog("There was an internal error\n");
+
+    json_get($var(internal), "code", "$var(c)");
+    xlog("code is $var(c)\n");
+
+    json_get($var(internal), "message", "$var(r)");
+    xlog("error is $var(r)\n");
+
+    if(json_get($var(internal), "data", "$var(d)")) {
+        xlog("request is $var(d)\n");
+    }
+}
diff --git a/modules/janssonrpc-c/unit_tests/Makefile b/modules/janssonrpc-c/unit_tests/Makefile
new file mode 100644
index 0000000..5e6a937
--- /dev/null
+++ b/modules/janssonrpc-c/unit_tests/Makefile
@@ -0,0 +1,11 @@
+CC = gcc
+FILES = *.c ../netstring.c ../jsonrpc_global.c seatest/seatest.c
+OUT_EXE = test
+
+build: $(FILES)
+	$(CC) -std=gnu99 -pedantic -D TEST -o $(OUT_EXE) $(FILES) -lm -levent
+
+clean:
+	rm -f *.o core
+
+rebuild: clean build
diff --git a/modules/janssonrpc-c/unit_tests/netstring.c b/modules/janssonrpc-c/unit_tests/netstring.c
new file mode 100644
index 0000000..19a4589
--- /dev/null
+++ b/modules/janssonrpc-c/unit_tests/netstring.c
@@ -0,0 +1,351 @@
+/**
+ * $Id$
+ *
+ * Copyright (C) 2013 Flowroute LLC (flowroute.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h> //temp
+#include <sys/socket.h>
+#include <event2/event.h>
+#include <event2/buffer.h> //temp
+#include <event2/bufferevent.h>
+#include "test.h"
+#include "../netstring.h"
+
+
+int fd[2];
+const int writer = 0;
+const int reader = 1;
+struct event_base *evbase;
+struct bufferevent *bev;
+netstring_t* ns_buffer;
+char* ns;
+char* next;
+
+
+/* ***********************************************************************
+ *                  tests for netstring_read_evbuffer                    *
+ * ***********************************************************************/
+
+//
+// Test normal operation of netstring_read_fd, with data received in three chunks.
+//
+void ev_init(void (*cb)(struct bufferevent*, void*))
+{
+	ns_buffer = NULL;
+	evbase = event_base_new();
+	socketpair(PF_LOCAL, SOCK_STREAM, 0, fd);
+	evutil_make_socket_nonblocking(fd[reader]);
+	bev = bufferevent_socket_new(evbase, fd[reader], BEV_OPT_CLOSE_ON_FREE);
+	bufferevent_setcb(bev, cb, NULL, NULL, NULL);
+    bufferevent_enable(bev, EV_READ);
+}
+
+void read_evb_cb3(struct bufferevent *bev, void *ptr)
+{
+	int r = netstring_read_evbuffer(bev, &ns_buffer);
+	assert_int_equal(0, r);
+	if (r == 0)
+		assert_string_equal("foobar-bizbaz", ns_buffer->string);
+
+	int res = event_base_loopbreak(evbase);
+	return;
+}
+
+void read_evb_cb2(struct bufferevent *bev, void *ptr)
+{
+	assert_int_equal(NETSTRING_INCOMPLETE, netstring_read_evbuffer(bev, &ns_buffer));
+	send(fd[writer], next, 10, 0);
+	bufferevent_setcb(bev, read_evb_cb3, NULL, NULL, NULL);
+	return;
+}
+
+void read_evb_cb1(struct bufferevent *bev, void *ptr)
+{
+	assert_int_equal(NETSTRING_INCOMPLETE, netstring_read_evbuffer(bev, &ns_buffer));
+	send(fd[writer], next, 5, 0);
+	next = next+5;
+	bufferevent_setcb(bev, read_evb_cb2, NULL, NULL, NULL);
+	return;
+}
+
+void test_read_evbuffer()
+{
+	ns = "13:foobar-bizbaz,";
+	ev_init(read_evb_cb1);
+	send(fd[writer], ns, 2, 0);
+	next = ns+2;
+	event_base_dispatch(evbase);
+}
+
+void test_read_evbuffer_one_chunk()
+{
+	ns = "13:foobar-bizbaz,";
+	ev_init(read_evb_cb3);
+	send(fd[writer], ns, strlen(ns), 0);
+	event_base_dispatch(evbase);
+}
+
+//
+// Abnormal test scenarios for netstring_read_evbuffer
+//
+
+void read_evb_leading_zero_cb()
+{
+	assert_int_equal(NETSTRING_ERROR_LEADING_ZERO, netstring_read_evbuffer(bev, &ns_buffer));
+	int res = event_base_loopbreak(evbase);
+}
+
+void test_read_evbuffer_leading_zero()
+{
+	ns = "0001:abbbbbbb,";
+	ev_init(read_evb_leading_zero_cb);
+	send(fd[writer], ns, strlen(ns), 0);
+	event_base_dispatch(evbase);
+}
+
+void read_evb_no_length_cb()
+{
+	assert_int_equal(NETSTRING_ERROR_NO_LENGTH, netstring_read_evbuffer(bev, &ns_buffer));
+	int res = event_base_loopbreak(evbase);
+}
+
+void test_read_evbuffer_no_length()
+{
+	ns = "a:......................b,";
+	ev_init(read_evb_no_length_cb);
+	send(fd[writer], ns, strlen(ns), 0);
+	event_base_dispatch(evbase);
+}
+
+void read_evb_too_long_cb()
+{
+	assert_int_equal(NETSTRING_ERROR_TOO_LONG, netstring_read_evbuffer(bev, &ns_buffer));
+	int res = event_base_loopbreak(evbase);
+}
+
+void test_read_evbuffer_too_long()
+{
+	ns = "999999999999999999999:...,";
+	ev_init(read_evb_too_long_cb);
+	send(fd[writer], ns, strlen(ns), 0);
+	event_base_dispatch(evbase);
+}
+
+void read_evb_no_colon_cb()
+{
+	assert_int_equal(NETSTRING_ERROR_NO_COLON, netstring_read_evbuffer(bev, &ns_buffer));
+	int res = event_base_loopbreak(evbase);
+}
+
+void test_read_evbuffer_no_colon()
+{
+	ns = "999abcc,";
+	ev_init(read_evb_no_colon_cb);
+	send(fd[writer], ns, strlen(ns), 0);
+	event_base_dispatch(evbase);
+}
+
+void read_evb_no_comma_cb()
+{
+	assert_int_equal(NETSTRING_ERROR_NO_COMMA, netstring_read_evbuffer(bev, &ns_buffer));
+	int res = event_base_loopbreak(evbase);
+}
+
+void test_read_evbuffer_no_comma()
+{
+	ns = "2:ab.";
+	ev_init(read_evb_no_comma_cb);
+	send(fd[writer], ns, strlen(ns), 0);
+	event_base_dispatch(evbase);
+}
+
+/* ***********************************************************************
+ *                    tests for netstring_read_fd                        *
+ * ***********************************************************************/
+
+//
+// Test normal operation of netstring_read_fd, with data received in three chunks.
+//
+void test_read_fd()
+{
+	char* ns = "13:foobar-bizbaz,";
+	char* temp;
+	int fd[2];
+	const int writer = 0;
+	const int reader = 1;
+	socketpair(PF_LOCAL, SOCK_STREAM, 0, fd);
+    netstring_t* buffer = NULL;
+
+	send(fd[writer], ns, 4, 0);
+	assert_int_equal(NETSTRING_INCOMPLETE, netstring_read_fd(fd[reader], &buffer));
+	temp = ns+4;
+	send(fd[writer], temp, 3, 0);
+	assert_int_equal(NETSTRING_INCOMPLETE, netstring_read_fd(fd[reader], &buffer));
+	temp = temp+3;
+	send(fd[writer], temp, 10, 0);
+	int r = netstring_read_fd(fd[reader], &buffer);
+	assert_int_equal(0, r);
+	if (r == 0)
+		assert_string_equal("foobar-bizbaz", buffer->string);
+}
+
+
+//
+// Abnormal test scenarios for netstring_read_fd
+//
+void test_read_fd_leading_zero()
+{
+	char *ns = "0001:a,";
+	int fd[2];
+	const int writer = 0;
+	const int reader = 1;
+	socketpair(PF_LOCAL, SOCK_STREAM, 0, fd);
+    netstring_t* buffer = NULL;
+
+	send(fd[writer], ns, 7, 0);
+	assert_int_equal(NETSTRING_ERROR_LEADING_ZERO, netstring_read_fd(fd[reader], &buffer));
+}
+
+void test_read_fd_no_length()
+{
+	char *ns = "ab,";
+	int fd[2];
+	const int writer = 0;
+	const int reader = 1;
+	socketpair(PF_LOCAL, SOCK_STREAM, 0, fd);
+    netstring_t* buffer = NULL;
+
+	send(fd[writer], ns, 3, 0);
+	assert_int_equal(NETSTRING_ERROR_NO_LENGTH, netstring_read_fd(fd[reader], &buffer));
+}
+
+void test_read_fd_too_long()
+{
+	char *ns = "999999999999999999999:...,";
+	int fd[2];
+	const int writer = 0;
+	const int reader = 1;
+	socketpair(PF_LOCAL, SOCK_STREAM, 0, fd);
+    netstring_t* buffer = NULL;
+
+	send(fd[writer], ns, strlen(ns), 0);
+	assert_int_equal(NETSTRING_ERROR_TOO_LONG, netstring_read_fd(fd[reader], &buffer));
+}
+
+void test_read_fd_no_colon()
+{
+	char *ns = "999ab,";
+	int fd[2];
+	const int writer = 0;
+	const int reader = 1;
+	socketpair(PF_LOCAL, SOCK_STREAM, 0, fd);
+    netstring_t* buffer = NULL;
+
+	send(fd[writer], ns, strlen(ns), 0);
+	assert_int_equal(NETSTRING_ERROR_NO_COLON, netstring_read_fd(fd[reader], &buffer));
+}
+
+void test_read_fd_no_comma()
+{
+	char *ns = "5:......";
+	int fd[2];
+	const int writer = 0;
+	const int reader = 1;
+	socketpair(PF_LOCAL, SOCK_STREAM, 0, fd);
+    netstring_t* buffer = NULL;
+
+	send(fd[writer], ns, strlen(ns), 0);
+	assert_int_equal(NETSTRING_ERROR_NO_COMMA, netstring_read_fd(fd[reader], &buffer));
+}
+
+///
+// Test for netstring_encode_new
+//
+void test_encode_new()
+{
+	char *ns;
+	char *data = "foobar-bizbaz";
+	int len = netstring_encode_new(&ns, data, strlen(data));
+	assert_int_equal(17, len);
+	char *temp = malloc(len+1);
+	memcpy(temp, ns, len);
+	temp[len] = '\0';
+	assert_string_equal("13:foobar-bizbaz,", temp);
+}
+
+// put the tests into a fixture...
+//
+void test_fixture_read_fd(void)
+{
+	printf("Running read_fd tests...\n");
+	test_fixture_start();
+	run_test(test_read_fd);
+	run_test(test_read_fd_leading_zero);
+	run_test(test_read_fd_no_length);
+	run_test(test_read_fd_too_long);
+	run_test(test_read_fd_no_colon);
+	run_test(test_read_fd_no_comma);
+	test_fixture_end();
+}
+
+void test_fixture_read_evbuffer(void)
+{
+	printf("Running read_evbuffer tests...\n");
+	test_fixture_start();
+	run_test(test_read_evbuffer);
+	run_test(test_read_evbuffer_one_chunk);
+	run_test(test_read_evbuffer_leading_zero);
+	run_test(test_read_evbuffer_no_length);
+	run_test(test_read_evbuffer_too_long);
+//	run_test(test_read_evbuffer_no_colon);
+//	...skip due to TODO in netstring.c
+	run_test(test_read_evbuffer_no_comma);
+	test_fixture_end();
+}
+
+void test_fixture_encode(void)
+{
+	printf("Running encode_new tests...\n");
+	test_fixture_start();
+	run_test(test_encode_new);
+	test_fixture_end();
+}
+
+//
+// put the fixture into a suite...
+//
+void all_tests(void)
+{
+	test_fixture_read_fd();
+	test_fixture_read_evbuffer();
+	test_fixture_encode();
+}
+
+//
+// run the suite!
+//
+int main(int argc, char** argv)
+{
+	return run_tests(all_tests);
+}
+
diff --git a/modules/janssonrpc-c/unit_tests/seatest/license.txt b/modules/janssonrpc-c/unit_tests/seatest/license.txt
new file mode 100644
index 0000000..3fbf632
--- /dev/null
+++ b/modules/janssonrpc-c/unit_tests/seatest/license.txt
@@ -0,0 +1,19 @@
+ Copyright (c) 2010 Keith Nicholas
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
\ No newline at end of file
diff --git a/modules/janssonrpc-c/unit_tests/seatest/seatest.c b/modules/janssonrpc-c/unit_tests/seatest/seatest.c
new file mode 100644
index 0000000..cb68fb5
--- /dev/null
+++ b/modules/janssonrpc-c/unit_tests/seatest/seatest.c
@@ -0,0 +1,248 @@
+#include "seatest.h"
+#include <string.h>
+#ifdef WIN32
+#include <conio.h>
+#include "windows.h"
+#else
+unsigned int GetTickCount() { return 0;}
+void _getch( void ) { }
+#endif
+
+static int sea_tests_run = 0;
+static int sea_tests_passed = 0;
+static int sea_tests_failed = 0;
+static char* seatest_current_fixture;
+
+static void (*seatest_suite_setup_func)( void ) = 0;
+static void (*seatest_suite_teardown_func)( void ) = 0;
+static void (*seatest_fixture_setup)( void ) = 0;
+static void (*seatest_fixture_teardown)( void ) = 0;
+
+
+
+void suite_setup(void (*setup)( void ))
+{
+	seatest_suite_setup_func = setup;
+}
+void suite_teardown(void (*teardown)( void ))
+{
+	seatest_suite_teardown_func = teardown;
+}
+
+void seatest_suite_setup( void )
+{
+	if(seatest_suite_setup_func != 0) seatest_suite_setup_func();
+}
+
+void seatest_suite_teardown( void )
+{
+	if(seatest_suite_teardown_func != 0) seatest_suite_teardown_func();
+}
+
+void fixture_setup(void (*setup)( void ))
+{
+	seatest_fixture_setup = setup;
+}
+void fixture_teardown(void (*teardown)( void ))
+{
+	seatest_fixture_teardown = teardown;
+}
+
+void seatest_setup( void )
+{
+	if(seatest_fixture_setup != 0) seatest_fixture_setup();
+}
+
+void seatest_teardown( void )
+{
+	if(seatest_fixture_teardown != 0) seatest_fixture_teardown();
+}
+
+char* test_file_name(char* path)
+{
+	char* file = path + strlen(path);
+	while(file != path && *file!= '\\' ) file--;
+	if(*file == '\\') file++;
+	return file;
+}
+
+static int seatest_fixture_tests_run;
+static int seatest_fixture_tests_failed;
+
+void seatest_simple_test_result(int passed, char* reason, const char* function, unsigned int line)
+{
+	if (!passed)
+	{
+		printf("%-20s Line %-5d %s\r\n", function, line, reason );
+		sea_tests_failed++; 
+	}
+	else
+	{
+		sea_tests_passed++; 
+	}	
+}
+
+void seatest_assert_true(int test, const char* function, unsigned int line)
+{
+	seatest_simple_test_result(test, "Should of been true", function, line);
+
+}
+
+void seatest_assert_false(int test, const char* function, unsigned int line)
+{
+	seatest_simple_test_result(!test, "Should of been false", function, line);	
+}
+
+
+void seatest_assert_int_equal(int expected, int actual, const char* function, unsigned int line)
+{
+	char s[SEATEST_PRINT_BUFFER_SIZE];
+	sprintf(s, "Expected %d but was %d", expected, actual);
+	seatest_simple_test_result(expected==actual, s, function, line);	
+}
+
+void seatest_assert_ulong_equal(unsigned long expected, unsigned long actual, const char* function, unsigned int line)
+{
+	char s[SEATEST_PRINT_BUFFER_SIZE];
+	sprintf(s, "Expected %lu but was %lu", expected, actual);
+	seatest_simple_test_result(expected==actual, s, function, line);	
+}
+
+void seatest_assert_float_equal( float expected, float actual, float delta, const char* function, unsigned int line )
+{
+	char s[SEATEST_PRINT_BUFFER_SIZE];
+	float result = expected-actual;
+	sprintf(s, "Expected %f but was %f", expected, actual);
+	if(result < 0.0) result = 0.0f - result;
+	seatest_simple_test_result( result <= delta, s, function, line);	
+}
+
+void seatest_assert_double_equal( double expected, double actual, double delta, const char* function, unsigned int line )
+{
+	char s[SEATEST_PRINT_BUFFER_SIZE];
+	double result = expected-actual;
+	sprintf(s, "Expected %f but was %f", expected, actual);
+	if(result < 0.0) result = 0.0 - result;
+	seatest_simple_test_result( result <= delta, s, function, line);	
+}
+
+void seatest_assert_string_equal(char* expected, char* actual, const char* function, unsigned int line)
+{
+	char s[SEATEST_PRINT_BUFFER_SIZE];
+	sprintf(s, "Expected %s but was %s", expected, actual);
+	seatest_simple_test_result(strcmp(expected, actual)==0, s, function, line);	
+}
+
+void seatest_assert_string_ends_with(char* expected, char* actual, const char* function, unsigned int line)
+{
+	char s[SEATEST_PRINT_BUFFER_SIZE];
+	sprintf(s, "Expected %s to end with %s", actual, expected);
+	seatest_simple_test_result(strcmp(expected, actual+(strlen(actual)-strlen(expected)))==0, s, function, line);	
+}
+
+void seatest_assert_string_starts_with(char* expected, char* actual, const char* function, unsigned int line)
+{
+	char s[SEATEST_PRINT_BUFFER_SIZE];
+	sprintf(s, "Expected %s to start with %s", actual, expected);
+	seatest_simple_test_result(strncmp(expected, actual, strlen(expected))==0, s, function, line);	
+}
+
+void seatest_assert_string_contains(char* expected, char* actual, const char* function, unsigned int line)
+{
+	char s[SEATEST_PRINT_BUFFER_SIZE];
+	sprintf(s, "Expected %s to be in %s", expected, actual);
+	seatest_simple_test_result(strstr(actual, expected)!=0, s, function, line);	
+}
+
+void seatest_assert_string_doesnt_contain(char* expected, char* actual, const char* function, unsigned int line)
+{
+	char s[SEATEST_PRINT_BUFFER_SIZE];
+	sprintf(s, "Expected %s not to have %s in it", actual, expected);
+	seatest_simple_test_result(strstr(actual, expected)==0, s, function, line);	
+}
+
+void seatest_run_test(void)
+{
+	sea_tests_run++; 
+}
+
+void seatest_header_printer(char* s, int length, char f)
+{
+	int l = strlen(s);
+	int d = (length- (l + 2)) / 2;
+	int i;
+	for(i = 0; i<d; i++) printf("%c",f);
+	printf(" %s ", s);
+	for(i = (d+l+2); i<length; i++) printf("%c",f);
+	printf("\r\n");
+}
+
+
+void seatest_test_fixture_start(char* filepath)
+{
+	seatest_current_fixture = test_file_name(filepath);
+	seatest_header_printer(seatest_current_fixture, 50, '-');
+	seatest_fixture_tests_failed = sea_tests_failed;
+	seatest_fixture_tests_run = sea_tests_run;
+	seatest_fixture_teardown = 0;
+	seatest_fixture_setup = 0;
+}
+
+void seatest_test_fixture_end()
+{
+	char s[SEATEST_PRINT_BUFFER_SIZE];
+	sprintf(s, "%d run  %d failed", sea_tests_run-seatest_fixture_tests_run, sea_tests_failed-seatest_fixture_tests_failed);
+	seatest_header_printer(s, 50, ' ');
+	printf("\r\n");
+}
+
+static char* seatest_fixture_filter = 0;
+static char* seatest_test_filter = 0;
+
+void fixture_filter(char* filter)
+{
+	seatest_fixture_filter = filter;
+}
+
+
+void test_filter(char* filter)
+{
+	seatest_test_filter = filter;
+}
+
+
+int seatest_should_run( char* fixture, char* test)
+{
+	int run = 1;
+	if(seatest_fixture_filter) 
+	{
+		if(strncmp(seatest_fixture_filter, fixture, strlen(seatest_fixture_filter)) != 0) run = 0;
+	}
+	if(seatest_test_filter) 
+	{
+		if(strncmp(seatest_test_filter, test, strlen(seatest_test_filter)) != 0) run = 0;
+	}
+	return run;
+}
+
+int run_tests(void (*tests)(void))
+{
+	unsigned long end;
+	unsigned long start = GetTickCount();
+	tests();	 
+	end = GetTickCount();
+	printf("\r\n\r\n==================SEATEST v%s====================\r\n\r\n", SEATEST_VERSION);	 
+	if (sea_tests_failed > 0) {
+		printf("                      Failed\r\n");			
+	}
+	else {
+		printf("               ALL TESTS PASSED\r\n");
+	}
+	printf("                 %d tests run\r\n", sea_tests_run);
+	printf("                    in %lu ms\r\n",end - start);
+	printf("==================================================\r\n");
+
+	_getch();
+	return sea_tests_failed == 0;
+}
+
diff --git a/modules/janssonrpc-c/unit_tests/seatest/seatest.h b/modules/janssonrpc-c/unit_tests/seatest/seatest.h
new file mode 100644
index 0000000..964eaf9
--- /dev/null
+++ b/modules/janssonrpc-c/unit_tests/seatest/seatest.h
@@ -0,0 +1,74 @@
+#ifndef SEATEST_H
+#define SEATEST_H
+#include <stdio.h>
+
+/*
+Defines
+*/
+
+#define SEATEST_VERSION "0.5"
+#define SEATEST_PROJECT_HOME "http://code.google.com/p/seatest/"
+#define SEATEST_PRINT_BUFFER_SIZE 100000
+
+/*
+Declarations
+*/
+
+void seatest_test_fixture_start(char* filepath);
+void seatest_test_fixture_end( void );
+void seatest_simple_test_result(int passed, char* reason, const char* function, unsigned int line);
+void seatest_assert_true(int test, const char* function, unsigned int line);
+void seatest_assert_false(int test, const char* function, unsigned int line);
+void seatest_assert_int_equal(int expected, int actual, const char* function, unsigned int line);
+void seatest_assert_ulong_equal(unsigned long expected, unsigned long actual, const char* function, unsigned int line);
+void seatest_assert_float_equal(float expected, float actual, float delta, const char* function, unsigned int line);
+void seatest_assert_double_equal(double expected, double actual, double delta, const char* function, unsigned int line);
+void seatest_assert_string_equal(char* expected, char* actual, const char* function, unsigned int line);
+void seatest_assert_string_ends_with(char* expected, char* actual, const char* function, unsigned int line);
+void seatest_assert_string_starts_with(char* expected, char* actual, const char* function, unsigned int line);
+void seatest_assert_string_contains(char* expected, char* actual, const char* function, unsigned int line);
+void seatest_assert_string_doesnt_contain(char* expected, char* actual, const char* function, unsigned int line);
+int seatest_should_run( char* fixture, char* test);
+void seatest_run_test(void);
+void seatest_setup( void );
+void seatest_teardown( void );
+void seatest_suite_teardown( void );
+void seatest_suite_setup( void );
+
+/*
+Assert Macros
+*/
+
+#define assert_true(test) do { seatest_assert_true(test, __FUNCTION__, __LINE__); } while (0)
+#define assert_false(test) do {  seatest_assert_false(test, __FUNCTION__, __LINE__); } while (0)
+#define assert_int_equal(expected, actual) do {  seatest_assert_int_equal(expected, actual, __FUNCTION__, __LINE__); } while (0)
+#define assert_ulong_equal(expected, actual) do {  seatest_assert_ulong_equal(expected, actual, __FUNCTION__, __LINE__); } while (0)
+#define assert_string_equal(expected, actual) do {  seatest_assert_string_equal(expected, actual, __FUNCTION__, __LINE__); } while (0)
+#define assert_n_array_equal(expected, actual, n) do { int seatest_count; for(seatest_count=0; seatest_count<n; seatest_count++) { char s_seatest[SEATEST_PRINT_BUFFER_SIZE]; sprintf(s_seatest,"Expected %d to be %d at position %d", actual[seatest_count], expected[seatest_count], seatest_count); seatest_simple_test_result((expected[seatest_count] == actual[seatest_count]), s_seatest, __FUNCTION__, __LINE__);} } while (0)
+#define assert_bit_set(bit_number, value) { seatest_simple_test_result(((1 << bit_number) & value), " Expected bit to be set" ,  __FUNCTION__, __LINE__); } while (0)
+#define assert_bit_not_set(bit_number, value) { seatest_simple_test_result(!((1 << bit_number) & value), " Expected bit not to to be set" ,  __FUNCTION__, __LINE__); } while (0)
+#define assert_bit_mask_matches(value, mask) { seatest_simple_test_result(((value & mask) == mask), " Expected all bits of mask to be set" ,  __FUNCTION__, __LINE__); } while (0)
+#define assert_fail(message) { seatest_simple_test_result(0, message,  __FUNCTION__, __LINE__); } while (0)
+#define assert_float_equal(expected, actual, delta) do {  seatest_assert_float_equal(expected, actual, delta, __FUNCTION__, __LINE__); } while (0)
+#define assert_double_equal(expected, actual, delta) do {  seatest_assert_double_equal(expected, actual, delta, __FUNCTION__, __LINE__); } while (0)
+#define assert_string_contains(expected, actual) do {  seatest_assert_string_contains(expected, actual, __FUNCTION__, __LINE__); } while (0)
+#define assert_string_doesnt_contain(expected, actual) do {  seatest_assert_string_doesnt_contain(expected, actual, __FUNCTION__, __LINE__); } while (0)
+#define assert_string_starts_with(expected, actual) do {  seatest_assert_string_starts_with(expected, actual, __FUNCTION__, __LINE__); } while (0)
+#define assert_string_ends_with(expected, actual) do {  seatest_assert_string_ends_with(expected, actual, __FUNCTION__, __LINE__); } while (0)
+
+/*
+Fixture / Test Management
+*/
+
+void fixture_setup(void (*setup)( void ));
+void fixture_teardown(void (*teardown)( void ));
+#define run_test(test) do { if(seatest_should_run(__FILE__, #test)) {seatest_suite_setup(); seatest_setup(); test(); seatest_teardown(); seatest_suite_teardown(); seatest_run_test();  }} while (0)
+#define test_fixture_start() do { seatest_test_fixture_start(__FILE__); } while (0)
+#define test_fixture_end() do { seatest_test_fixture_end();} while (0)
+void fixture_filter(char* filter);
+void test_filter(char* filter);
+
+int run_tests(void (*tests)(void));
+void suite_teardown(void (*teardown)( void ));
+void suite_setup(void (*setup)( void ));
+#endif 
diff --git a/modules/janssonrpc-c/unit_tests/test.h b/modules/janssonrpc-c/unit_tests/test.h
new file mode 100644
index 0000000..edb0740
--- /dev/null
+++ b/modules/janssonrpc-c/unit_tests/test.h
@@ -0,0 +1,48 @@
+/**
+ * $Id$
+ *
+ * Copyright (C) 2013 Flowroute LLC (flowroute.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef _TEST_H_
+#define _TEST_H_
+
+#include <stdlib.h>
+#include <math.h>
+#include "seatest/seatest.h"
+
+struct _str{
+	char* s;
+	int len;
+};
+
+typedef struct _str str;
+
+#define pkg_malloc malloc
+#define shm_malloc malloc
+
+#define pkg_free free
+#define shm_free free
+
+#define ERR printf
+#define ALERT printf
+
+#endif /* _TEST_H_ */
diff --git a/modules/json/.gitignore b/modules/json/.gitignore
new file mode 100644
index 0000000..d31c081
--- /dev/null
+++ b/modules/json/.gitignore
@@ -0,0 +1,4 @@
+*.d
+*.o
+*.so
+*.lst
diff --git a/modules/jsonrpc-c/.gitignore b/modules/jsonrpc-c/.gitignore
new file mode 100644
index 0000000..88b08c7
--- /dev/null
+++ b/modules/jsonrpc-c/.gitignore
@@ -0,0 +1,10 @@
+*.d
+*.o
+*.so
+*.lst
+*.tar.gz
+*.swp
+*.swo
+tags
+TAGS
+doc/*.txt
diff --git a/modules/jsonrpc-c/TODO b/modules/jsonrpc-c/TODO
index 0c7cefe..f0e1915 100644
--- a/modules/jsonrpc-c/TODO
+++ b/modules/jsonrpc-c/TODO
@@ -1 +1,2 @@
 * "Reliable" Notifications (implement using requests, and failover on error; ignore non-error responses) ?
+* Implement timout for non-Linux systems
diff --git a/modules/jsonrpc-c/jsonrpc.c b/modules/jsonrpc-c/jsonrpc.c
index ce17f15..7baed54 100644
--- a/modules/jsonrpc-c/jsonrpc.c
+++ b/modules/jsonrpc-c/jsonrpc.c
@@ -1,5 +1,4 @@
-/**
- * $Id$
+/*
  *
  * Copyright (C) 2011 Flowroute LLC (flowroute.com)
  *
diff --git a/modules/jsonrpc-c/jsonrpc.h b/modules/jsonrpc-c/jsonrpc.h
index 7780034..9aa0aeb 100644
--- a/modules/jsonrpc-c/jsonrpc.h
+++ b/modules/jsonrpc-c/jsonrpc.h
@@ -1,5 +1,4 @@
-/**
- * $Id$
+/*
  *
  * Copyright (C) 2011 Flowroute LLC (flowroute.com)
  *
diff --git a/modules/jsonrpc-c/jsonrpc_io.c b/modules/jsonrpc-c/jsonrpc_io.c
index df61a31..188d2e6 100644
--- a/modules/jsonrpc-c/jsonrpc_io.c
+++ b/modules/jsonrpc-c/jsonrpc_io.c
@@ -1,5 +1,4 @@
-/**
- * $Id$
+/*
  *
  * Copyright (C) 2011 Flowroute LLC (flowroute.com)
  *
diff --git a/modules/jsonrpc-c/jsonrpc_io.h b/modules/jsonrpc-c/jsonrpc_io.h
index 774af91..d5dd1b0 100644
--- a/modules/jsonrpc-c/jsonrpc_io.h
+++ b/modules/jsonrpc-c/jsonrpc_io.h
@@ -1,5 +1,4 @@
-/**
- * $Id$
+/*
  *
  * Copyright (C) 2011 Flowroute LLC (flowroute.com)
  *
diff --git a/modules/jsonrpc-c/jsonrpc_mod.c b/modules/jsonrpc-c/jsonrpc_mod.c
index 0b27137..49c7162 100644
--- a/modules/jsonrpc-c/jsonrpc_mod.c
+++ b/modules/jsonrpc-c/jsonrpc_mod.c
@@ -1,5 +1,4 @@
-/**
- * $Id$
+/*
  *
  * Copyright (C) 2011 Flowroute LLC (flowroute.com)
  *
diff --git a/modules/jsonrpc-c/jsonrpc_request.c b/modules/jsonrpc-c/jsonrpc_request.c
index 6a1b5b8..19dade8 100644
--- a/modules/jsonrpc-c/jsonrpc_request.c
+++ b/modules/jsonrpc-c/jsonrpc_request.c
@@ -1,6 +1,4 @@
-/**
- * $Id$
-*
+/*
  * Copyright (C) 2011 Flowroute LLC (flowroute.com)
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/jsonrpc-c/jsonrpc_request.h b/modules/jsonrpc-c/jsonrpc_request.h
index 0aaacbc..4c77660 100644
--- a/modules/jsonrpc-c/jsonrpc_request.h
+++ b/modules/jsonrpc-c/jsonrpc_request.h
@@ -1,6 +1,4 @@
-/**
- * $Id$
- *
+/*
  * Copyright (C) 2011 Flowroute LLC (flowroute.com)
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/jsonrpc-c/netstring.c b/modules/jsonrpc-c/netstring.c
index e65d8a5..6c668e4 100644
--- a/modules/jsonrpc-c/netstring.c
+++ b/modules/jsonrpc-c/netstring.c
@@ -1,6 +1,4 @@
-/**
- * $Id$
- *
+/*
  * Copyright (C) 2011 Flowroute LLC (flowroute.com)
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/jsonrpc-c/netstring.h b/modules/jsonrpc-c/netstring.h
index 0c68fdf..9af5d3f 100644
--- a/modules/jsonrpc-c/netstring.h
+++ b/modules/jsonrpc-c/netstring.h
@@ -1,6 +1,4 @@
-/**
- * $Id$
- *
+/*
  * Copyright (C) 2011 Flowroute LLC (flowroute.com)
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/jsonrpc-s/Makefile b/modules/jsonrpc-s/Makefile
index 2248ef5..3ef462a 100644
--- a/modules/jsonrpc-s/Makefile
+++ b/modules/jsonrpc-s/Makefile
@@ -1,4 +1,5 @@
 # 
+# 
 # WARNING: do not run this directly, it should be run by the master Makefile
 
 include ../../Makefile.defs
diff --git a/modules/jsonrpc-s/README b/modules/jsonrpc-s/README
index bb92a7a..5d1e328 100644
--- a/modules/jsonrpc-s/README
+++ b/modules/jsonrpc-s/README
@@ -29,17 +29,36 @@ Daniel-Constantin Mierla
         3. Parameters
 
               3.1. pretty_format (int)
+              3.2. transport (int)
+              3.3. fifo_name (str)
+              3.4. fifo_mode (int)
+              3.5. fifo_group (int or str)
+              3.6. fifo_user (int or str)
+              3.7. fifo_reply_dir (str)
 
         4. Functions
 
               4.1. jsonrpc_dispatch()
               4.2. jsonrpc_exec(cmd)
 
+        5. JSONRPC Transports
+
+              5.1. JSONRPC Over HTTP
+              5.2. JSONRPC Over FIFO
+
    List of Examples
 
    1.1. Set pretty_format parameter
-   1.2. jsonrpc_dispatch usage
-   1.3. jsonrpc_exec usage
+   1.2. Set transport parameter
+   1.3. Set fifo_name parameter
+   1.4. Set fifo_mode parameter
+   1.5. Set fifo_group parameter
+   1.6. Set fifo_user parameter
+   1.7. Set fifo_reply_dir parameter
+   1.8. jsonrpc_dispatch usage
+   1.9. jsonrpc_exec usage
+   1.10. JSONRPC Over Fifo Command
+   1.11. JSONRPC Over Fifo Command From Termina
 
 Chapter 1. Admin Guide
 
@@ -57,21 +76,35 @@ Chapter 1. Admin Guide
    3. Parameters
 
         3.1. pretty_format (int)
+        3.2. transport (int)
+        3.3. fifo_name (str)
+        3.4. fifo_mode (int)
+        3.5. fifo_group (int or str)
+        3.6. fifo_user (int or str)
+        3.7. fifo_reply_dir (str)
 
    4. Functions
 
         4.1. jsonrpc_dispatch()
         4.2. jsonrpc_exec(cmd)
 
+   5. JSONRPC Transports
+
+        5.1. JSONRPC Over HTTP
+        5.2. JSONRPC Over FIFO
+
 1. Overview
 
    1.1. Limitations
 
-   This module provides a JSON-RPC server over HTTP implementation,
+   This module provides a JSON-RPC v2 server over HTTP implementation,
    tailored for the needs of Kamailio. It implements the Kamailio RPC
    interface over JSON-RPC.
 
-   The JSONRPC-S module uses the xHTTP module to handle HTTP requests.
+   The specification for JSON-RPC is available at:
+   http://www.jsonrpc.org/specification.
+
+   The JSONRPC-S module uses the xHTTP module to handle HTTP/S requests.
    Read the documentation of the xHTTP module for more details.
 
 1.1. Limitations
@@ -102,6 +135,12 @@ Chapter 1. Admin Guide
 3. Parameters
 
    3.1. pretty_format (int)
+   3.2. transport (int)
+   3.3. fifo_name (str)
+   3.4. fifo_mode (int)
+   3.5. fifo_group (int or str)
+   3.6. fifo_user (int or str)
+   3.7. fifo_reply_dir (str)
 
 3.1. pretty_format (int)
 
@@ -114,6 +153,81 @@ Chapter 1. Admin Guide
 modparam("jsonrpc-s", "pretty_format", 1)
 ...
 
+3.2. transport (int)
+
+   Control what transports are enabled. The value can be:
+     * 0 - all transports that can be enabled. For http, the xhttp module
+       must be loaded. For FIFO, the fifo_name parameter must be set.
+     * 1 - only HTTP transport
+     * 2 - only FIFO transport
+
+   Default value is '0'.
+
+   Example 1.2. Set transport parameter
+...
+modparam("jsonrpc-s", "transport", 1)
+...
+
+3.3. fifo_name (str)
+
+   The name of the FIFO file to be created for listening and reading
+   external commands. If the given path is not absolute, the fifo file is
+   created relative to run_dir (global parameter).
+
+   Default value is NONE.
+
+   Example 1.3. Set fifo_name parameter
+...
+modparam("jsonrpc-s", "fifo_name", "/tmp/kamailio_jsonrpc_fifo")
+...
+
+3.4. fifo_mode (int)
+
+   Permission to be used for creating the listening FIFO file. It follows
+   the UNIX conventions.
+
+   Default value is 0660 (rw-rw----).
+
+   Example 1.4. Set fifo_mode parameter
+...
+modparam("jsonrpc-s", "fifo_mode", 0600)
+...
+
+3.5. fifo_group (int or str)
+
+   System Group to be used for creating the listening FIFO file.
+
+   Default value is the inherited one (process group).
+
+   Example 1.5. Set fifo_group parameter
+...
+modparam("jsonrpc-s", "fifo_group", 0)
+modparam("jsonrpc-s", "fifo_group", "root")
+...
+
+3.6. fifo_user (int or str)
+
+   System User to be used for creating the listening FIFO file.
+
+   Default value is the inherited one (process user).
+
+   Example 1.6. Set fifo_user parameter
+...
+modparam("jsonrpc-s", "fifo_user", 0)
+modparam("jsonrpc-s", "fifo_user", "root")
+...
+
+3.7. fifo_reply_dir (str)
+
+   Directory to be used for creating the reply FIFO files.
+
+   Default value is "/tmp/"
+
+   Example 1.7. Set fifo_reply_dir parameter
+...
+modparam("jsonrpc-s", "fifo_reply_dir", "/home/kamailio/tmp/")
+...
+
 4. Functions
 
    4.1. jsonrpc_dispatch()
@@ -123,7 +237,7 @@ modparam("jsonrpc-s", "pretty_format", 1)
 
    Handle the JSONRPC request and generate a response.
 
-   Example 1.2. jsonrpc_dispatch usage
+   Example 1.8. jsonrpc_dispatch usage
 ...
 #!KAMAILIO
 
@@ -174,7 +288,62 @@ event_route[xhttp:request] {
    dynamic string with variables. The result of the command can be
    accessed via $jsonrpl(key) pseudo variables.
 
-   Example 1.3. jsonrpc_exec usage
+   Example 1.9. jsonrpc_exec usage
 ...
 jsonrpc_exec({"jsonrpc": "2.0", "method": "dispatcher.reload", "id": 1}');
 ...
+
+5. JSONRPC Transports
+
+   5.1. JSONRPC Over HTTP
+   5.2. JSONRPC Over FIFO
+
+   JSONRPC specifications do not enforce a specific transport to carry the
+   JSON documents. Very common is JSONRPC over HTTP or HTTPS, and they are
+   supported by Kamailio. In addition, Kamailio supports receiving JSON
+   documents via a local FIFO file.
+
+5.1. JSONRPC Over HTTP
+
+   It requires that XHTTP module is loaded. HTTPS can be used if you
+   enable TLS for Kamailio. The JSONRPC requests have to be sent to the
+   TCP or TLS ports of Kamailio.
+
+   The 'transport' parameter has to be 0 or 1.
+
+   The format of the JSON document must follow the JSONRPC specifications.
+
+5.2. JSONRPC Over FIFO
+
+   This module can retrive JSONRPC requests via a local FIFO file. To
+   enable this feature, 'fifo_name' parameter must be set and 'transport'
+   parameter has to be 0 or 2.
+
+   The format of the JSON document must follow the JSONRPC specifications
+   plus an additional field named 'reply_name'. The value for this field
+   must be the name of the FIFO file were to write the JSONRPC response.
+   The reply FIFO file is created in the folder specified by
+   'fifo_reply_dir'. Next is an example showing a JSONRPC command to be
+   sent via FIFO transport.
+
+   Example 1.10. JSONRPC Over Fifo Command
+...
+{
+ "jsonrpc": "2.0",
+  "method": "core.psx",
+  "reply_name": "kamailio_jsonrpc_reply_fifo",
+  "id": 1
+}
+...
+
+   Next is an example of how to test it from a terminal, assuming that the
+   parameter 'fifo_name' is set to '/tmp/kamailio_jsonrpc_fifo'.
+
+   Example 1.11. JSONRPC Over Fifo Command From Termina
+...
+mkfifo /tmp/kamailio_jsonrpc_reply_fifo
+cat /tmp/kamailio_jsonrpc_reply_fifo &
+echo '{"jsonrpc": "2.0", "method": "core.psx", \
+          "reply_name": "kamailio_jsonrpc_reply_fifo", "id": 1}' \
+     > /tmp/kamailio_jsonrpc_fifo
+rm /tmp/kamailio_jsonrpc_reply_fifo
diff --git a/modules/jsonrpc-s/doc/jsonrpc-s_admin.xml b/modules/jsonrpc-s/doc/jsonrpc-s_admin.xml
index a12b153..6c9ef1c 100644
--- a/modules/jsonrpc-s/doc/jsonrpc-s_admin.xml
+++ b/modules/jsonrpc-s/doc/jsonrpc-s_admin.xml
@@ -16,12 +16,16 @@
 	<section>
 	<title>Overview</title>
 	<para>
-		This module provides a JSON-RPC server over HTTP implementation,
+		This module provides a JSON-RPC v2 server over HTTP implementation,
 		tailored for the needs of &kamailio;. It implements the &kamailio;
 		RPC interface over JSON-RPC.
+	</para>
 	<para>
+		The specification for JSON-RPC is available at:
+		<ulink url="http://www.jsonrpc.org/specification">http://www.jsonrpc.org/specification</ulink>.
 	</para>
-		The JSONRPC-S module uses the xHTTP module to handle HTTP requests.
+	<para>
+		The JSONRPC-S module uses the xHTTP module to handle HTTP/S requests.
 		Read the documentation of the xHTTP module for more details.
 	</para>
 
@@ -78,7 +82,7 @@
 	</section>
 	<section>
 	<title>Parameters</title>
-	<section>
+	<section id="jsonrpc-s.p.pretty_format">
 		<title><varname>pretty_format</varname> (int)</title>
 		<para>
 			Pretty format for JSON-RPC response document. 
@@ -97,6 +101,144 @@ modparam("jsonrpc-s", "pretty_format", 1)
 </programlisting>
 		</example>
 	</section>
+	<section id="jsonrpc-s.p.transport">
+		<title><varname>transport</varname> (int)</title>
+		<para>
+			Control what transports are enabled. The value can be:
+		</para>
+		<itemizedlist>
+			<listitem><para>
+				<emphasis>0</emphasis> - all transports that can be enabled.
+				For http, the xhttp module must be loaded. For FIFO, the
+				fifo_name parameter must be set.
+			</para></listitem>
+			<listitem><para>
+				<emphasis>1</emphasis> - only HTTP transport
+			</para></listitem>
+			<listitem><para>
+				<emphasis>2</emphasis> - only FIFO transport
+			</para></listitem>
+		</itemizedlist>
+
+		<para>
+		<emphasis>
+			Default value is '0'.
+		</emphasis>
+		</para>
+		<example>
+		<title>Set <varname>transport</varname> parameter</title>
+		<programlisting format="linespecific">
+...
+modparam("jsonrpc-s", "transport", 1)
+...
+</programlisting>
+		</example>
+	</section>
+	<section id="jsonrpc-s.p.fifo_name">
+		<title><varname>fifo_name</varname> (str)</title>
+		<para>
+		The name of the FIFO file to be created for listening and 
+		reading external commands. If the given path is not absolute,
+		the fifo file is created relative to run_dir (global parameter).
+		</para>
+		<para>
+		<emphasis>
+			Default value is NONE.
+		</emphasis>
+		</para>
+		<example>
+		<title>Set <varname>fifo_name</varname> parameter</title>
+		<programlisting format="linespecific">
+...
+modparam("jsonrpc-s", "fifo_name", "/tmp/kamailio_jsonrpc_fifo")
+...
+</programlisting>
+		</example>
+	</section>
+
+	<section id="jsonrpc-s.p.fifo_mode">
+		<title><varname>fifo_mode</varname> (int)</title>
+		<para>
+		Permission to be used for creating the listening FIFO file. It 
+		follows the UNIX conventions.
+		</para>
+		<para>
+		<emphasis>
+			Default value is 0660 (rw-rw----).
+		</emphasis>
+		</para>
+		<example>
+		<title>Set <varname>fifo_mode</varname> parameter</title>
+		<programlisting format="linespecific">
+...
+modparam("jsonrpc-s", "fifo_mode", 0600)
+...
+</programlisting>
+		</example>
+	</section>
+
+	<section id="jsonrpc-s.p.fifo_group">
+		<title><varname>fifo_group</varname> (int or str)</title>
+		<para>
+		System Group to be used for creating the listening FIFO file.
+		</para>
+		<para>
+		<emphasis>
+			Default value is the inherited one (process group).
+		</emphasis>
+		</para>
+		<example>
+		<title>Set <varname>fifo_group</varname> parameter</title>
+		<programlisting format="linespecific">
+...
+modparam("jsonrpc-s", "fifo_group", 0)
+modparam("jsonrpc-s", "fifo_group", "root")
+...
+</programlisting>
+		</example>
+	</section>
+
+	<section id="jsonrpc-s.p.fifo_user">
+		<title><varname>fifo_user</varname> (int or str)</title>
+		<para>
+		System User to be used for creating the listening FIFO file.
+		</para>
+		<para>
+		<emphasis>
+			Default value is the inherited one (process user).
+		</emphasis>
+		</para>
+		<example>
+		<title>Set <varname>fifo_user</varname> parameter</title>
+		<programlisting format="linespecific">
+...
+modparam("jsonrpc-s", "fifo_user", 0)
+modparam("jsonrpc-s", "fifo_user", "root")
+...
+</programlisting>
+		</example>
+	</section>
+
+	<section id="jsonrpc-s.p.fifo_reply_dir">
+		<title><varname>fifo_reply_dir</varname> (str)</title>
+		<para>
+		Directory to be used for creating the reply FIFO files.
+		</para>
+		<para>
+		<emphasis>
+			Default value is <quote>/tmp/</quote>
+		</emphasis>
+		</para>
+		<example>
+		<title>Set <varname>fifo_reply_dir</varname> parameter</title>
+		<programlisting format="linespecific">
+...
+modparam("jsonrpc-s", "fifo_reply_dir", "/home/kamailio/tmp/")
+...
+</programlisting>
+		</example>
+	</section>
+
 	</section>
 
 	<section>
@@ -178,5 +320,77 @@ jsonrpc_exec({"jsonrpc": "2.0", "method": "dispatcher.reload", "id": 1}');
 	</section>
 
 	</section>
+
+	<section>
+	<title>JSONRPC Transports</title>
+	<para>
+	JSONRPC specifications do not enforce a specific transport to carry the
+	JSON documents. Very common is JSONRPC over HTTP or HTTPS, and they are
+	supported by &kamailio;. In addition, &kamailio; supports receiving JSON
+	documents via a local FIFO file. 
+	</para>
+ 	<section>
+	    <title>JSONRPC Over HTTP</title>
+	    <para>
+			It requires that XHTTP module is loaded. HTTPS can be used if
+			you enable TLS for &kamailio;. The JSONRPC requests have to be
+			sent to the TCP or TLS ports of &kamailio;.
+		</para>
+		<para>
+			The 'transport' parameter has to be 0 or 1.
+		</para>
+		<para>
+			The format of the JSON document must follow the JSONRPC
+			specifications.
+		</para>
+	</section>
+ 	<section>
+	    <title>JSONRPC Over FIFO</title>
+	    <para>
+			This module can retrive JSONRPC requests via a local FIFO file. To
+			enable this feature, 'fifo_name' parameter must be set and
+			'transport' parameter has to be 0 or 2.
+		</para>
+		<para>
+			The format of the JSON document must follow the JSONRPC
+			specifications plus an additional field named 'reply_name'. The
+			value for this field must be the name of the FIFO file were to
+			write the JSONRPC response. The reply FIFO file is created in the
+			folder specified by 'fifo_reply_dir'. Next is an example showing
+			a JSONRPC command to be sent via FIFO transport.
+		</para>
+		<example>
+		<title>JSONRPC Over Fifo Command</title>
+		<programlisting format="linespecific">
+...
+{
+ "jsonrpc": "2.0",
+  "method": "core.psx",
+  "reply_name": "kamailio_jsonrpc_reply_fifo",
+  "id": 1
+}
+...
+</programlisting>
+	    </example>
+		<para>
+			Next is an example of how to test it from a terminal, assuming that
+			the parameter 'fifo_name' is set to '/tmp/kamailio_jsonrpc_fifo'.
+		</para>
+		<example>
+		<title>JSONRPC Over Fifo Command From Termina</title>
+		<programlisting format="linespecific">
+...
+mkfifo /tmp/kamailio_jsonrpc_reply_fifo
+cat /tmp/kamailio_jsonrpc_reply_fifo &
+echo '{"jsonrpc": "2.0", "method": "core.psx", \
+          "reply_name": "kamailio_jsonrpc_reply_fifo", "id": 1}' \
+     > /tmp/kamailio_jsonrpc_fifo
+rm /tmp/kamailio_jsonrpc_reply_fifo
+</programlisting>
+	    </example>
+
+	</section>
+	</section>
+
 </chapter>
 
diff --git a/modules/jsonrpc-s/jsonrpc-s_mod.c b/modules/jsonrpc-s/jsonrpc-s_mod.c
index c1018c4..a5c877b 100644
--- a/modules/jsonrpc-s/jsonrpc-s_mod.c
+++ b/modules/jsonrpc-s/jsonrpc-s_mod.c
@@ -23,12 +23,19 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <stdarg.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
 
 #include "../../ver.h"
 #include "../../trim.h"
+#include "../../pt.h"
 #include "../../sr_module.h"
 #include "../../mod_fix.h"
 #include "../../nonsip_hooks.h"
+#include "../../cfg/cfg_struct.h"
 #include "../../modules/xhttp/api.h"
 
 #include "jsonrpc-s_mod.h"
@@ -53,8 +60,19 @@ MODULE_VERSION
 #define jsonrpc_malloc	pkg_malloc
 #define jsonrpc_free	pkg_free
 
-str JSONRPC_REASON_OK = str_init("OK");
-str JSONRPC_CONTENT_TYPE_HTML = str_init("application/json");
+static str JSONRPC_REASON_OK = str_init("OK");
+static str JSONRPC_CONTENT_TYPE_HTML = str_init("application/json");
+
+/* FIFO server vars */
+static char *jsonrpc_fifo = NULL;				/*!< FIFO file name */
+static char *jsonrpc_fifo_reply_dir = "/tmp/"; 	/*!< dir where reply fifos are allowed */
+static int  jsonrpc_fifo_uid = -1;				/*!< Fifo default UID */
+static char *jsonrpc_fifo_uid_s = 0;			/*!< Fifo default User ID name */
+static int  jsonrpc_fifo_gid = -1;				/*!< Fifo default Group ID */
+static char *jsonrpc_fifo_gid_s = 0;			/*!< Fifo default Group ID name */
+static int  jsonrpc_fifo_mode = S_IRUSR| S_IWUSR| S_IRGRP| S_IWGRP; /* Default file mode rw-rw---- */
+
+static int  jsonrpc_transport = 0;				/*!< 0 - all available; 1 - http; 2 - fifo */
 
 static int jsonrpc_pretty_format = 0;
 
@@ -62,9 +80,12 @@ static int jsonrpc_register_rpc(void);
 
 static int mod_init(void);
 static int child_init(int rank);
+static void mod_destroy(void);
 static int jsonrpc_dispatch(sip_msg_t* msg, char* s1, char* s2);
 static int jsonrpc_exec(sip_msg_t* msg, char* cmd, char* s2);
 
+static int jsonrpc_init_fifo_file(void);
+static void jsonrpc_fifo_process(int rank);
 
 /** The context of the jsonrpc request being processed.
  *
@@ -95,7 +116,15 @@ static cmd_export_t cmds[] = {
 };
 
 static param_export_t params[] = {
-	{"pretty_format",   PARAM_INT,    &jsonrpc_pretty_format},
+	{"pretty_format",    PARAM_INT,    &jsonrpc_pretty_format},
+	{"fifo_name",        PARAM_STRING, &jsonrpc_fifo},
+	{"fifo_mode",        PARAM_INT,	   &jsonrpc_fifo_mode},
+	{"fifo_group",       PARAM_STRING, &jsonrpc_fifo_gid_s},
+	{"fifo_group",       PARAM_INT,    &jsonrpc_fifo_gid},
+	{"fifo_user",        PARAM_STRING, &jsonrpc_fifo_uid_s},
+	{"fifo_user",        PARAM_INT,    &jsonrpc_fifo_uid},
+	{"fifo_reply_dir",   PARAM_STRING, &jsonrpc_fifo_reply_dir},
+	{"transport",        PARAM_INT,    &jsonrpc_transport},
 	{0, 0, 0}
 };
 
@@ -120,7 +149,7 @@ struct module_exports exports= {
 	0,			/* extra processes */
 	mod_init,	/* module initialization function */
 	0,
-	0,
+	mod_destroy,/* module destroy function */
 	child_init	/* per-child init function */
 };
 
@@ -317,7 +346,7 @@ static int jsonrpc_send(jsonrpc_ctx_t* ctx)
 		} else {
 			jsonrpc_set_plain_reply(ctx->http_code, &ctx->http_text, &rbuf,
 					ctx->jrpl->free_fn);
-			rbuf.s = NULL;
+			rbuf.s=NULL;
 		}
 	} else {
 		if(ctx->msg) {
@@ -864,10 +893,52 @@ static void jsonrpc_clean_context(jsonrpc_ctx_t* ctx)
 
 static int mod_init(void)
 {
+	int sep;
+	int len;
+	char *p;
+
 	/* bind the XHTTP API */
-	if (xhttp_load_api(&xhttp_api) < 0) {
-		LM_ERR("cannot bind to XHTTP API\n");
-		return -1;
+	if(jsonrpc_transport==0 || jsonrpc_transport==1) {
+		if (xhttp_load_api(&xhttp_api) < 0) {
+			if(jsonrpc_transport==1) {
+				LM_ERR("cannot bind to XHTTP API\n");
+				return -1;
+			} else {
+				memset(&xhttp_api, 0, sizeof(xhttp_api_t));
+			}
+		}
+	}
+	if(jsonrpc_transport==0 || jsonrpc_transport==2) {
+		if(jsonrpc_fifo != NULL && *jsonrpc_fifo!=0) {
+			if(*jsonrpc_fifo != '/') {
+				if(runtime_dir!=NULL && *runtime_dir!=0) {
+					len = strlen(runtime_dir);
+					sep = 0;
+					if(runtime_dir[len-1]!='/') {
+						sep = 1;
+					}
+					len += sep + strlen(jsonrpc_fifo);
+					p = pkg_malloc(len + 1);
+					if(p==NULL) {
+						LM_ERR("no more pkg\n");
+						return -1;
+					}
+					strcpy(p, runtime_dir);
+					if(sep) strcat(p, "/");
+					strcat(p, jsonrpc_fifo);
+					jsonrpc_fifo = p;
+					LM_DBG("fifo path is [%s]\n", jsonrpc_fifo);
+				}
+			}
+		}
+		if(jsonrpc_init_fifo_file()<0) {
+			if(jsonrpc_transport==2) {
+				LM_ERR("cannot initialize fifo transport\n");
+				return -1;
+			} else {
+				jsonrpc_fifo = NULL;
+			}
+		}
 	}
 
 	memset(&func_param, 0, sizeof(func_param));
@@ -893,12 +964,61 @@ static int mod_init(void)
 
 static int child_init(int rank)
 {
+	int pid;
+
+	if (rank==PROC_MAIN) {
+		if(jsonrpc_fifo != NULL) {
+			pid=fork_process(PROC_NOCHLDINIT, "JSONRPC-S FIFO", 1);
+			if (pid<0)
+				return -1; /* error */
+			if(pid==0) {
+				/* child */
+
+				/* initialize the config framework */
+				if (cfg_child_init())
+					return -1;
+
+				jsonrpc_fifo_process(1);
+			}
+		}
+	}
+
 	if(rank==PROC_MAIN || rank==PROC_TCP_MAIN)
+	{
 		return 0; /* do nothing for the main process */
+	}
 
 	return 0;
 }
 
+static void mod_destroy(void)
+{
+	int n;
+	struct stat filestat;
+
+	if(jsonrpc_fifo==NULL)
+		return;
+
+	/* destroying the fifo file */
+	n=stat(jsonrpc_fifo, &filestat);
+	if (n==0){
+		/* FIFO exist, delete it (safer) if not config check */
+		if(config_check==0) {
+			if (unlink(jsonrpc_fifo)<0){
+				LM_ERR("cannot delete the fifo (%s): %s\n",
+					jsonrpc_fifo, strerror(errno));
+				goto error;
+			}
+		}
+	} else if (n<0 && errno!=ENOENT) {
+		LM_ERR("FIFO stat failed: %s\n", strerror(errno));
+		goto error;
+	}
+
+	return;
+error:
+	return;
+}
 
 static int jsonrpc_dispatch(sip_msg_t* msg, char* s1, char* s2)
 {
@@ -980,7 +1100,7 @@ send_reply:
 }
 
 
-static int jsonrpc_exec(sip_msg_t* msg, char* cmd, char* s2)
+static int jsonrpc_exec_ex(str *cmd, str *rpath)
 {
 	rpc_export_t* rpce;
 	jsonrpc_ctx_t* ctx;
@@ -989,10 +1109,7 @@ static int jsonrpc_exec(sip_msg_t* msg, char* cmd, char* s2)
 	str val;
 	str scmd;
 
-	if(fixup_get_svalue(msg, (gparam_t*)cmd, &scmd)<0 || scmd.len<=0) {
-		LM_ERR("cannot get the rpc command parameter\n");
-		return -1;
-	}
+	scmd = *cmd;
 
 	/* initialize jsonrpc context */
 	ctx = &_jsonrpc_ctx;
@@ -1029,6 +1146,27 @@ static int jsonrpc_exec(sip_msg_t* msg, char* cmd, char* s2)
 		LM_ERR("unsupported jsonrpc version [%.*s]\n", val.len, val.s);
 		goto send_reply;
 	}
+	/* reply name */
+	if(rpath!=NULL) {
+		if(rpath->s==NULL || rpath->len<=0) {
+			LM_ERR("empty buffer to store the reply name\n");
+			goto send_reply;
+		}
+		nj = srjson_GetObjectItem(ctx->jreq, ctx->jreq->root, "reply_name");
+		if(nj==NULL) {
+			LM_ERR("missing reply_name field in request\n");
+			goto send_reply;
+		}
+		val.s = nj->valuestring;
+		val.len = strlen(val.s);
+		if(val.len>=rpath->len) {
+			LM_ERR("no space to store reply_name field\n");
+			goto send_reply;
+		}
+		strncpy(rpath->s, val.s, val.len);
+		rpath->s[val.len] = 0;
+		rpath->len = val.len;
+	}
 	/* run jsonrpc command */
 	nj = srjson_GetObjectItem(ctx->jreq, ctx->jreq->root, "method");
 	if(nj==NULL) {
@@ -1063,6 +1201,16 @@ send_reply:
 	return 1;
 }
 
+static int jsonrpc_exec(sip_msg_t* msg, char* cmd, char* s2)
+{
+	str scmd;
+
+	if(fixup_get_svalue(msg, (gparam_t*)cmd, &scmd)<0 || scmd.len<=0) {
+		LM_ERR("cannot get the rpc command parameter\n");
+		return -1;
+	}
+	return jsonrpc_exec_ex(&scmd, NULL);
+}
 /**
  *
  */
@@ -1154,3 +1302,446 @@ static int jsonrpc_pv_parse_jrpl_name(pv_spec_t *sp, str *in)
 	}
 	return 0;
 }
+
+/* FIFO TRANSPORT */
+
+/*! \brief Initialize fifo transport */
+static int jsonrpc_init_fifo_file(void)
+{
+	int n;
+	struct stat filestat;
+
+	/* checking the jsonrpc_fifo module param */
+	if (jsonrpc_fifo==NULL || *jsonrpc_fifo == 0) {
+		jsonrpc_fifo=NULL;
+		LM_DBG("No fifo configured\n");
+		return 0;
+	}
+
+	LM_DBG("testing if fifo file exists ...\n");
+	n=stat(jsonrpc_fifo, &filestat);
+	if (n==0) {
+		/* FIFO exist, delete it (safer) if no config check */
+		if(config_check==0) {
+			if (unlink(jsonrpc_fifo)<0){
+				LM_ERR("Cannot delete old fifo (%s): %s\n",
+					jsonrpc_fifo, strerror(errno));
+				return -1;
+			}
+		}
+	} else if (n<0 && errno!=ENOENT){
+		LM_ERR("MI FIFO stat failed: %s\n", strerror(errno));
+		return -1;
+	}
+
+	/* checking the fifo_reply_dir param */
+	if(!jsonrpc_fifo_reply_dir || *jsonrpc_fifo_reply_dir == 0) {
+		LM_ERR("fifo_reply_dir parameter is empty\n");
+		return -1;
+	}
+
+	/* Check if the directory for the reply fifo exists */
+	n = stat(jsonrpc_fifo_reply_dir, &filestat);
+	if(n < 0){
+		LM_ERR("Directory stat for MI Fifo reply failed: %s\n", strerror(errno));
+		return -1;
+	}
+
+	if(S_ISDIR(filestat.st_mode) == 0){
+		LM_ERR("fifo_reply_dir parameter is not a directory\n");
+		return -1;
+	}
+
+	/* check fifo_mode */
+	if(!jsonrpc_fifo_mode){
+		LM_WARN("cannot specify fifo_mode = 0, forcing it to rw-------\n");
+		jsonrpc_fifo_mode = S_IRUSR | S_IWUSR;
+	}
+
+	if (jsonrpc_fifo_uid_s){
+		if (user2uid(&jsonrpc_fifo_uid, &jsonrpc_fifo_gid, jsonrpc_fifo_uid_s)<0){
+			LM_ERR("Bad user name %s\n", jsonrpc_fifo_uid_s);
+			return -1;
+		}
+	}
+
+	if (jsonrpc_fifo_gid_s){
+		if (group2gid(&jsonrpc_fifo_gid, jsonrpc_fifo_gid_s)<0){
+			LM_ERR("Bad group name %s\n", jsonrpc_fifo_gid_s);
+			return -1;
+		}
+	}
+
+	/* add space for one extra process */
+	register_procs(1);
+
+	/* add child to update local config framework structures */
+	cfg_register_child(1);
+
+	return 0;
+}
+
+
+static int  jsonrpc_fifo_read = 0;
+static int  jsonrpc_fifo_write = 0;
+#define JSONRPC_MAX_FILENAME	128
+static char *jsonrpc_reply_fifo_s = NULL;
+static int jsonrpc_reply_fifo_len = 0;
+
+/*! \brief Initialize Fifo server */
+FILE *jsonrpc_init_fifo_server(char *fifo_name, int fifo_mode,
+						int fifo_uid, int fifo_gid, char* fifo_reply_dir)
+{
+	FILE *fifo_stream;
+	long opt;
+
+	/* create FIFO ... */
+	if ((mkfifo(fifo_name, fifo_mode)<0)) {
+		LM_ERR("Can't create FIFO: %s (mode=%d)\n", strerror(errno), fifo_mode);
+		return 0;
+	}
+
+	LM_DBG("FIFO created @ %s\n", fifo_name );
+
+	if ((chmod(fifo_name, fifo_mode)<0)) {
+		LM_ERR("Can't chmod FIFO: %s (mode=%d)\n", strerror(errno), fifo_mode);
+		return 0;
+	}
+
+	if ((fifo_uid!=-1) || (fifo_gid!=-1)){
+		if (chown(fifo_name, fifo_uid, fifo_gid)<0){
+			LM_ERR("Failed to change the owner/group for %s  to %d.%d; %s[%d]\n",
+				fifo_name, fifo_uid, fifo_gid, strerror(errno), errno);
+			return 0;
+		}
+	}
+
+	LM_DBG("fifo %s opened, mode=%o\n", fifo_name, fifo_mode );
+
+	/* open it non-blocking or else wait here until someone
+	 * opens it for writing */
+	jsonrpc_fifo_read=open(fifo_name, O_RDONLY|O_NONBLOCK, 0);
+	if (jsonrpc_fifo_read<0) {
+		LM_ERR("Can't open fifo %s for reading - fifo_read did not open: %s\n", fifo_name, strerror(errno));
+		return 0;
+	}
+
+	fifo_stream = fdopen(jsonrpc_fifo_read, "r");
+	if (fifo_stream==NULL) {
+		LM_ERR("fdopen failed on %s: %s\n", fifo_name, strerror(errno));
+		return 0;
+	}
+
+	/* make sure the read fifo will not close */
+	jsonrpc_fifo_write=open(fifo_name, O_WRONLY|O_NONBLOCK, 0);
+	if (jsonrpc_fifo_write<0) {
+		LM_ERR("fifo_write did not open: %s\n", strerror(errno));
+		return 0;
+	}
+	/* set read fifo blocking mode */
+	if ((opt=fcntl(jsonrpc_fifo_read, F_GETFL))==-1){
+		LM_ERR("fcntl(F_GETFL) failed: %s [%d]\n", strerror(errno), errno);
+		return 0;
+	}
+	if (fcntl(jsonrpc_fifo_read, F_SETFL, opt & (~O_NONBLOCK))==-1){
+		LM_ERR("cntl(F_SETFL) failed: %s [%d]\n", strerror(errno), errno);
+		return 0;
+	}
+
+	jsonrpc_reply_fifo_s = pkg_malloc(JSONRPC_MAX_FILENAME);
+	if (jsonrpc_reply_fifo_s==NULL) {
+		LM_ERR("no more private memory\n");
+		return 0;
+	}
+
+	/* init fifo reply dir buffer */
+	jsonrpc_reply_fifo_len = strlen(fifo_reply_dir);
+	memcpy( jsonrpc_reply_fifo_s, jsonrpc_fifo_reply_dir, jsonrpc_reply_fifo_len);
+
+	return fifo_stream;
+}
+
+/*! \brief Read input on fifo */
+int jsonrpc_read_stream(char *b, int max, FILE *stream, int *lread)
+{
+	int retry_cnt;
+	int len;
+	char *p;
+	int sstate;
+	int pcount;
+	int pfound;
+	int stype;
+
+	sstate = 0;
+	retry_cnt=0;
+
+	*lread = 0;
+	p = b;
+	pcount = 0;
+	pfound = 0;
+	stype = 0;
+
+	while(1) {
+		len = fread (p, 1, 1, stream);
+		if(len==0) {
+			LM_ERR("fifo server fread failed: %s\n", strerror(errno));
+			/* on Linux, sometimes returns ESPIPE -- give
+			   it few more chances
+			*/
+			if (errno==ESPIPE) {
+				retry_cnt++;
+				if (retry_cnt>4)
+					return -1;
+				continue;
+			}
+			/* interrupted by signal or ... */
+			if ((errno==EINTR)||(errno==EAGAIN))
+				continue;
+			return -1;
+		}
+		if(*p=='"' && (sstate==0 || stype==1)) {
+			if(*lread>0) {
+				if(*(p-1)!='\\') {
+					sstate = (sstate+1) % 2;
+					stype = 1;
+				}
+			} else {
+				sstate = (sstate+1) % 2;
+				stype = 1;
+			}
+		} else if(*p=='\'' && (sstate==0 || stype==2)) {
+			if(*lread>0) {
+				if(*(p-1)!='\\') {
+					sstate = (sstate+1) % 2;
+					stype = 2;
+				}
+			} else {
+				sstate = (sstate+1) % 2;
+				stype = 2;
+			}
+		} else if(*p=='{') {
+			if(sstate==0) {
+				pfound = 1;
+				pcount++;
+			}
+		} else if(*p=='}') {
+			if(sstate==0)
+				pcount--;
+		}
+		*lread = *lread + 1;
+		if(*lread>=max-1) {
+			LM_WARN("input data too large (%d)\n", *lread);
+			return -1;
+		}
+		p++;
+		if(pfound==1 && pcount==0) {
+			*p = 0;
+			return 0;
+		}
+	}
+
+	return -1;
+}
+
+/*! \brief reply fifo security checks:
+ *
+ * checks if fd is a fifo, is not hardlinked and it's not a softlink
+ * opened file descriptor + file name (for soft link check)
+ * \return 0 if ok, <0 if not */
+static int jsonrpc_fifo_check(int fd, char* fname)
+{
+	struct stat fst;
+	struct stat lst;
+	
+	if (fstat(fd, &fst)<0){
+		LM_ERR("security: fstat on %s failed: %s\n", fname, strerror(errno));
+		return -1;
+	}
+	/* check if fifo */
+	if (!S_ISFIFO(fst.st_mode)){
+		LM_ERR("security: %s is not a fifo\n", fname);
+		return -1;
+	}
+	/* check if hard-linked */
+	if (fst.st_nlink>1){
+		LM_ERR("security: fifo_check: %s is hard-linked %d times\n", fname, (unsigned)fst.st_nlink);
+		return -1;
+	}
+
+	/* lstat to check for soft links */
+	if (lstat(fname, &lst)<0){
+		LM_ERR("security: lstat on %s failed: %s\n", fname, strerror(errno));
+		return -1;
+	}
+	if (S_ISLNK(lst.st_mode)){
+		LM_ERR("security: fifo_check: %s is a soft link\n", fname);
+		return -1;
+	}
+	/* if this is not a symbolic link, check to see if the inode didn't
+	 * change to avoid possible sym.link, rm sym.link & replace w/ fifo race
+	 */
+	if ((lst.st_dev!=fst.st_dev)||(lst.st_ino!=fst.st_ino)){
+		LM_ERR("security: fifo_check: inode/dev number differ: %d %d (%s)\n",
+			(int)fst.st_ino, (int)lst.st_ino, fname);
+		return -1;
+	}
+	/* success */
+	return 0;
+}
+
+#define JSONRPC_REPLY_RETRIES 4
+FILE *jsonrpc_open_reply_fifo(str *srpath)
+{
+	int retries=JSONRPC_REPLY_RETRIES;
+	int fifofd;
+	FILE *file_handle;
+	int flags;
+
+	if ( memchr(srpath->s, '.', srpath->len)
+			|| memchr(srpath->s, '/', srpath->len)
+			|| memchr(srpath->s, '\\', srpath->len) ) {
+		LM_ERR("Forbidden reply fifo filename: %.*s\n",
+				srpath->len, srpath->s);
+		return 0;
+	}
+
+	if (jsonrpc_reply_fifo_len + srpath->len + 1 > JSONRPC_MAX_FILENAME) {
+		LM_ERR("Reply fifo filename too long %d\n",
+				jsonrpc_reply_fifo_len + srpath->len);
+		return 0;
+	}
+
+	memcpy(jsonrpc_reply_fifo_s + jsonrpc_reply_fifo_len, srpath->s, srpath->len);
+	jsonrpc_reply_fifo_s[jsonrpc_reply_fifo_len + srpath->len]=0;
+
+
+tryagain:
+	/* open non-blocking to make sure that a broken client will not 
+	 * block the FIFO server forever */
+	fifofd=open( jsonrpc_reply_fifo_s, O_WRONLY | O_NONBLOCK );
+	if (fifofd==-1) {
+		/* retry several times if client is not yet ready for getting
+		   feedback via a reply pipe
+		*/
+		if (errno==ENXIO) {
+			/* give up on the client - we can't afford server blocking */
+			if (retries==0) {
+				LM_ERR("no client at %s\n", jsonrpc_reply_fifo_s );
+				return 0;
+			}
+			/* don't be noisy on the very first try */
+			if (retries != JSONRPC_REPLY_RETRIES)
+				LM_DBG("mi_fifo retry countdown: %d\n", retries );
+			sleep_us( 80000 );
+			retries--;
+			goto tryagain;
+		}
+		/* some other opening error */
+		LM_ERR("open error (%s): %s\n", jsonrpc_reply_fifo_s, strerror(errno));
+		return 0;
+	}
+
+	/* security checks: is this really a fifo?, is 
+	 * it hardlinked? is it a soft link? */
+	if (jsonrpc_fifo_check(fifofd, jsonrpc_reply_fifo_s)<0)
+		goto error;
+
+	/* we want server blocking for big writes */
+	if ( (flags=fcntl(fifofd, F_GETFL, 0))<0) {
+		LM_ERR("pipe (%s): getfl failed: %s\n", jsonrpc_reply_fifo_s, strerror(errno));
+		goto error;
+	}
+	flags&=~O_NONBLOCK;
+	if (fcntl(fifofd, F_SETFL, flags)<0) {
+		LM_ERR("pipe (%s): setfl cntl failed: %s\n", jsonrpc_reply_fifo_s, strerror(errno));
+		goto error;
+	}
+
+	/* create an I/O stream */
+	file_handle=fdopen( fifofd, "w");
+	if (file_handle==NULL) {
+		LM_ERR("open error (%s): %s\n",
+			jsonrpc_reply_fifo_s, strerror(errno));
+		goto error;
+	}
+	return file_handle;
+error:
+	close(fifofd);
+	return 0;
+}
+
+#define JSONRPC_BUF_IN_SIZE	4096
+static void jsonrpc_run_fifo_server(FILE *fifo_stream)
+{
+	FILE *reply_stream;
+	char buf_in[JSONRPC_BUF_IN_SIZE];
+	char buf_rpath[128];
+	int lread;
+	str scmd;
+	str srpath;
+	int nw;
+
+	while(1) {
+		/* update the local config framework structures */
+		cfg_update();
+
+		reply_stream = NULL;
+		lread = 0;
+		if(jsonrpc_read_stream(buf_in, JSONRPC_BUF_IN_SIZE,
+					fifo_stream, &lread)<0 || lread<=0) {
+			LM_DBG("failed to get the json document from fifo stream\n");
+			continue;
+		}
+		scmd.s = buf_in;
+		scmd.len = lread;
+		trim(&scmd);
+		LM_DBG("preparing to execute fifo jsonrpc [%.*s]\n", scmd.len, scmd.s);
+		srpath.s = buf_rpath;
+		srpath.len = 128;
+		if(jsonrpc_exec_ex(&scmd, &srpath)<0) {
+			LM_ERR("failed to execute the json document from fifo stream\n");
+			continue;
+		}
+
+		LM_DBG("command executed - result: [%.*s] [%d] [%p] [%.*s]\n",
+				srpath.len, srpath.s,
+				_jsonrpc_plain_reply.rcode,
+				_jsonrpc_plain_reply.rbody.s,
+				_jsonrpc_plain_reply.rbody.len, _jsonrpc_plain_reply.rbody.s);
+		if(srpath.len>0) {
+			reply_stream = jsonrpc_open_reply_fifo(&srpath);
+			if (reply_stream==NULL) {
+				LM_ERR("cannot open reply fifo: %.*s\n", srpath.len, srpath.s);
+				continue;
+			}
+			nw = fwrite(_jsonrpc_plain_reply.rbody.s, 1,
+						_jsonrpc_plain_reply.rbody.len, reply_stream);
+			if(nw < _jsonrpc_plain_reply.rbody.len) {
+				LM_ERR("failed to write the reply to fifo: %d out of %d\n",
+						nw, _jsonrpc_plain_reply.rbody.len);
+			}
+			fclose(reply_stream);
+
+		}
+	}
+	return;
+}
+
+static void jsonrpc_fifo_process(int rank)
+{
+	FILE *fifo_stream;
+
+	LM_DBG("new process with pid = %d created\n",getpid());
+
+	fifo_stream = jsonrpc_init_fifo_server( jsonrpc_fifo, jsonrpc_fifo_mode,
+		jsonrpc_fifo_uid, jsonrpc_fifo_gid, jsonrpc_fifo_reply_dir);
+	if ( fifo_stream==NULL ) {
+		LM_CRIT("The function jsonrpc_init_fifo_server returned with error!!!\n");
+		exit(-1);
+	}
+
+	jsonrpc_run_fifo_server( fifo_stream );
+
+	LM_CRIT("the function jsonroc_fifo_server returned with error!!!\n");
+	exit(-1);
+}
diff --git a/modules/kazoo/Makefile b/modules/kazoo/Makefile
index 853566c..fe589ae 100644
--- a/modules/kazoo/Makefile
+++ b/modules/kazoo/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # WARNING: do not run this directly, it should be run by the master Makefile
 
diff --git a/modules/kazoo/kz_json.c b/modules/kazoo/kz_json.c
index 01cb6f5..daa07e1 100644
--- a/modules/kazoo/kz_json.c
+++ b/modules/kazoo/kz_json.c
@@ -122,7 +122,7 @@ int kz_json_get_field_ex(str* json, str* field, pv_value_p dst_val)
 				str field = str_init(*(tokens + i));
 				// check for idx []
 				int sresult = sscanf(field.s, "%[^[][%[^]]]", f1, f2); //, f3);
-				LM_DBG("CHECK IDX %d - %s , %s, %s\n", sresult, field.s, f1, f2);
+				LM_DBG("CHECK IDX %d - %s , %s, %s\n", sresult, field.s, f1, (sresult > 1? f2 : "(null)"));
 
 				jtree = kz_json_get_object(jtree, f1);
 				if(jtree != NULL) {
diff --git a/modules/kazoo/kz_trans.c b/modules/kazoo/kz_trans.c
index e041ab0..ef34a5a 100644
--- a/modules/kazoo/kz_trans.c
+++ b/modules/kazoo/kz_trans.c
@@ -46,6 +46,9 @@
 #include "../../parser/parse_nameaddr.h"
 
 #include "../../lib/kcore/strcommon.h"
+
+#include "../../mod_fix.h"
+
 #include "kz_trans.h"
 #include "kz_json.h"
 #include "kz_amqp.h"
@@ -191,6 +194,8 @@ int kz_tr_eval(struct sip_msg *msg, tr_param_t *tp, int subtype, pv_value_t *val
 	str sv;
 	pv_value_t* pv;
 	pv_value_t v;
+    str v2 = {0,0};
+	void* v1 = NULL;
 
 	if(val==NULL || (val->flags&PV_VAL_NULL))
 		return -1;
@@ -249,7 +254,18 @@ int kz_tr_eval(struct sip_msg *msg, tr_param_t *tp, int subtype, pv_value_t *val
 
 			if(tp->type == TR_PARAM_STRING)
 			{
-				sv = tp->v.s;
+				v1 = tp->v.s.s;
+				if(fixup_spve_null(&v1, 1) != 0) {
+					LM_ERR("cannot get spve_value from TR_PARAM_STRING : %.*s\n", tp->v.s.len, tp->v.s.s);
+					return -1;
+				}
+				if (fixup_get_svalue(msg, (gparam_p)v1, &v2) != 0) {
+					LM_ERR("cannot get value from TR_PARAM_STRING\n");
+					fixup_free_spve_null(&v1, 1);
+					return -1;
+				}
+				fixup_free_spve_null(&v1, 1);
+				sv = v2;
 			} else {
 				if(pv_get_spec_value(msg, (pv_spec_p)tp->v.data, &v)!=0
 						|| (!(v.flags&PV_VAL_STR)) || v.rs.len<=0)
@@ -337,8 +353,10 @@ int kz_tr_eval(struct sip_msg *msg, tr_param_t *tp, int subtype, pv_value_t *val
 		} \
 		memset(_tp, 0, sizeof(tr_param_t)); \
 		_tp->type = TR_PARAM_STRING; \
-		_tp->v.s.s = _ps; \
 		_tp->v.s.len = _p - _ps; \
+		_tp->v.s.s = (char*)malloc((tp->v.s.len+1)*sizeof(char)); \
+		strncpy(_tp->v.s.s, _ps, tp->v.s.len); \
+		_tp->v.s.s[tp->v.s.len] = '\0'; \
 		_kz_parse_params[_kz_tr_parse_params++] = _tp; \
 	}
 
diff --git a/modules/kex/Makefile b/modules/kex/Makefile
index b6652c6..bda6220 100644
--- a/modules/kex/Makefile
+++ b/modules/kex/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # example module makefile
 #
diff --git a/modules/ldap/Makefile b/modules/ldap/Makefile
index 8d75945..ad4cbe8 100644
--- a/modules/ldap/Makefile
+++ b/modules/ldap/Makefile
@@ -1,4 +1,3 @@
-# $Id: $
 #
 # LDAP_H350
 #
diff --git a/modules/ldap/api.h b/modules/ldap/api.h
index 0998649..1ad83da 100644
--- a/modules/ldap/api.h
+++ b/modules/ldap/api.h
@@ -1,6 +1,4 @@
 /*
-* $Id$
-*
 * Kamailio LDAP Module
 *
 * Copyright (C) 2007 University of North Carolina
@@ -24,9 +22,6 @@
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
-* History:
-* --------
-* 2007-02-18: Initial version
 */
 
 
diff --git a/modules/ldap/iniparser.c b/modules/ldap/iniparser.c
index e481af0..4dd6a36 100644
--- a/modules/ldap/iniparser.c
+++ b/modules/ldap/iniparser.c
@@ -1,6 +1,4 @@
 /*
-* $Id$
-*
 * Kamailio LDAP Module
 *
 * Copyright (C) 2007 University of North Carolina
@@ -24,9 +22,6 @@
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
-* History:
-* --------
-* 2007-02-18: Initial version
 */
 
 
diff --git a/modules/ldap/iniparser.h b/modules/ldap/iniparser.h
index 763e40f..06d8d2a 100644
--- a/modules/ldap/iniparser.h
+++ b/modules/ldap/iniparser.h
@@ -1,6 +1,4 @@
 /*
-* $Id$
-*
 * Kamailio LDAP Module
 *
 * Copyright (C) 2007 University of North Carolina
@@ -24,9 +22,6 @@
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
-* History:
-* --------
-* 2007-02-18: Initial version
 */
 
 
diff --git a/modules/ldap/ld_session.c b/modules/ldap/ld_session.c
index e62fedf..cad4698 100644
--- a/modules/ldap/ld_session.c
+++ b/modules/ldap/ld_session.c
@@ -1,6 +1,4 @@
 /*
-* $Id$
-*
 * Kamailio LDAP Module
 *
 * Copyright (C) 2007 University of North Carolina
@@ -24,9 +22,6 @@
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
-* History:
-* --------
-* 2007-02-18: Initial version
 */
 
 
diff --git a/modules/ldap/ld_session.h b/modules/ldap/ld_session.h
index 6d1d92f..08a752c 100644
--- a/modules/ldap/ld_session.h
+++ b/modules/ldap/ld_session.h
@@ -1,6 +1,4 @@
 /*
-* $Id$
-*
 * Kamailio LDAP Module
 *
 * Copyright (C) 2007 University of North Carolina
@@ -24,9 +22,6 @@
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
-* History:
-* --------
-* 2007-02-18: Initial version
 */
 
 
diff --git a/modules/ldap/ldap_api_fn.c b/modules/ldap/ldap_api_fn.c
index 6a3a55b..5039e18 100644
--- a/modules/ldap/ldap_api_fn.c
+++ b/modules/ldap/ldap_api_fn.c
@@ -1,6 +1,4 @@
 /*
-* $Id$
-*
 * Kamailio LDAP Module
 *
 * Copyright (C) 2007 University of North Carolina
@@ -24,9 +22,6 @@
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
-* History:
-* --------
-* 2007-02-18: Initial version
 */
 
 
diff --git a/modules/ldap/ldap_api_fn.h b/modules/ldap/ldap_api_fn.h
index 136ba8d..4f4bf17 100644
--- a/modules/ldap/ldap_api_fn.h
+++ b/modules/ldap/ldap_api_fn.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Kamailio LDAP Module
  *
  * Copyright (C) 2007 University of North Carolina
@@ -24,9 +22,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2007-02-18: Initial version
  */
 
 
diff --git a/modules/ldap/ldap_connect.c b/modules/ldap/ldap_connect.c
index c1c6a06..c21e445 100644
--- a/modules/ldap/ldap_connect.c
+++ b/modules/ldap/ldap_connect.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Kamailio LDAP Module
  *
  * Copyright (C) 2007 University of North Carolina
@@ -24,9 +22,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2007-02-18: Initial version
  */
 
 
diff --git a/modules/ldap/ldap_connect.h b/modules/ldap/ldap_connect.h
index 77959c9..6ce77a1 100644
--- a/modules/ldap/ldap_connect.h
+++ b/modules/ldap/ldap_connect.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Kamailio LDAP Module
  *
  * Copyright (C) 2007 University of North Carolina
@@ -24,9 +22,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2007-02-18: Initial version
  */
 
 
diff --git a/modules/ldap/ldap_escape.c b/modules/ldap/ldap_escape.c
index 0f94231..e6507f8 100644
--- a/modules/ldap/ldap_escape.c
+++ b/modules/ldap/ldap_escape.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Kamailio LDAP Module
  *
  * Copyright (C) 2007 University of North Carolina
@@ -24,9 +22,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2007-02-18: Initial version
  */
 
 
diff --git a/modules/ldap/ldap_escape.h b/modules/ldap/ldap_escape.h
index d941c2e..83635ed 100644
--- a/modules/ldap/ldap_escape.h
+++ b/modules/ldap/ldap_escape.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Kamailio LDAP Module
  *
  * Copyright (C) 2007 University of North Carolina
@@ -24,9 +22,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2007-02-18: Initial version
  */
 
 
diff --git a/modules/ldap/ldap_exp_fn.c b/modules/ldap/ldap_exp_fn.c
index 04f4aa3..8629c96 100644
--- a/modules/ldap/ldap_exp_fn.c
+++ b/modules/ldap/ldap_exp_fn.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Kamailio LDAP Module
  *
  * Copyright (C) 2007 University of North Carolina
@@ -24,9 +22,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2007-02-18: Initial version
  */
 
 
diff --git a/modules/ldap/ldap_exp_fn.h b/modules/ldap/ldap_exp_fn.h
index 33fdb0e..2bbc500 100644
--- a/modules/ldap/ldap_exp_fn.h
+++ b/modules/ldap/ldap_exp_fn.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Kamailio LDAP Module
  *
  * Copyright (C) 2007 University of North Carolina
@@ -24,9 +22,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2007-02-18: Initial version
  */
 
 
diff --git a/modules/ldap/ldap_mod.c b/modules/ldap/ldap_mod.c
index f170b0b..a95bec8 100644
--- a/modules/ldap/ldap_mod.c
+++ b/modules/ldap/ldap_mod.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Kamailio LDAP Module
  *
  * Copyright (C) 2007 University of North Carolina
@@ -24,9 +22,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2007-02-18: Initial version
  */
 
 
diff --git a/modules/malloc_test/Makefile b/modules/malloc_test/Makefile
index a83936d..02f185d 100644
--- a/modules/malloc_test/Makefile
+++ b/modules/malloc_test/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 #malloc_test module makefile
 #
diff --git a/modules/mangler/Makefile b/modules/mangler/Makefile
index ada06ef..70ee599 100644
--- a/modules/mangler/Makefile
+++ b/modules/mangler/Makefile
@@ -1,6 +1,5 @@
-# Makefile v 1.0 2002/12/27
 #
-# Enum module makefile
+# mangler module makefile
 #
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
diff --git a/modules/mangler/README b/modules/mangler/README
index a6761f7..5ec5622 100644
--- a/modules/mangler/README
+++ b/modules/mangler/README
@@ -1,4 +1,3 @@
-
 The Mangler Module - SDP mangling
 
 Gabriel Vasile
@@ -6,7 +5,7 @@ Gabriel Vasile
    FhG FOKUS
 
    Copyright � 2003 FhG FOKUS
-     _________________________________________________________________
+     __________________________________________________________________
 
    Table of Contents
 
@@ -19,11 +18,11 @@ Gabriel Vasile
 
         3. Functions
 
-              3.1. sdp_mangle_ip(pattern, newip) 
-              3.2. sdp_mangle_port(offset) 
-              3.3. encode_contact(encoding_prefix) 
-              3.4. decode_contact() 
-              3.5. decode_contact_header() 
+              3.1. sdp_mangle_ip(pattern, newip)
+              3.2. sdp_mangle_port(offset)
+              3.3. encode_contact(encoding_prefix)
+              3.4. decode_contact()
+              3.5. decode_contact_header()
 
    List of Examples
 
@@ -45,11 +44,11 @@ Chapter 1. Admin Guide
 
    3. Functions
 
-        3.1. sdp_mangle_ip(pattern, newip) 
-        3.2. sdp_mangle_port(offset) 
-        3.3. encode_contact(encoding_prefix) 
-        3.4. decode_contact() 
-        3.5. decode_contact_header() 
+        3.1. sdp_mangle_ip(pattern, newip)
+        3.2. sdp_mangle_port(offset)
+        3.3. encode_contact(encoding_prefix)
+        3.4. decode_contact()
+        3.5. decode_contact_header()
 
 1. Overview
 
@@ -61,16 +60,16 @@ Chapter 1. Admin Guide
 
 2.1. contact_flds_separator (string)
 
-   First   char   of   this   parameter   is   used   as   separator  for
-   encoding/decoding  Contact  header.  If you set this parameter to "-",
-   then an encoded uri might look
-   sip:user-password-ip-port-protocol at PublicIP
+   First char of this parameter is used as a separator for
+   encoding/decoding Contact headers. If you set this parameter to "-",
+   then an encoded URI will look like
+   "sip:user-password-ip-port-protocol at PublicIP"
 
 Warning
 
-   First  char  of  this  field  must be set to a value which is not used
-   inside  username,password  or  other fields of contact.Otherwise it is
-   possible for the decoding step to fail/produce wrong results.
+   The first character of this field must be set to a value which is not
+   used inside username, password or other fields of contact.Otherwise it
+   is possible for the decoding step to fail/produce wrong results.
 
    Default value is "*".
 
@@ -81,27 +80,26 @@ modparam("mangler", "contact_flds_separator", "-")
 
 3. Functions
 
-   3.1. sdp_mangle_ip(pattern, newip) 
-   3.2. sdp_mangle_port(offset) 
-   3.3. encode_contact(encoding_prefix) 
-   3.4. decode_contact() 
-   3.5. decode_contact_header() 
+   3.1. sdp_mangle_ip(pattern, newip)
+   3.2. sdp_mangle_port(offset)
+   3.3. encode_contact(encoding_prefix)
+   3.4. decode_contact()
+   3.5. decode_contact_header()
 
-3.1.  sdp_mangle_ip(pattern, newip)
+3.1. sdp_mangle_ip(pattern, newip)
 
-   Changes   IP   addresses   inside  SDP  package  in  lines  describing
-   connections  like  c=IN IP4 . Currently this function only changes IP4
+   Changes IP addresses inside SDP document in lines describing
+   connections like c=IN IP4 . Currently this function only changes IP4
    addresses since IP6 probably will not need to traverse NAT :)
 
    The function returns negative on error, or number of replacements + 1.
 
    Meaning of the parameters is as follows:
-     * pattern - A ip address/mask pair used to match IP's located inside
-       SDP  package  in lines c=IN IP4 ip. This line will only be changed
-       if  located  IP  is  in  the  network  described  by this pattern.
-       Examples   of   valid   patterns   are   "10.0.0.0/255.0.0.0"   or
-       "10.0.0.0/8" etc.
-     * newip  -  A  string  representing  the new IP to be put inside SDP
+     * pattern - An IP address/mask pair used to match IP's located inside
+       SDP package in lines c=IN IP4 ip. This line will only be changed if
+       located IP is in the network described by this pattern. Examples of
+       valid patterns are "10.0.0.0/255.0.0.0" or "10.0.0.0/8" etc.
+     * newip - A string representing the new IP to be put inside SDP
        package if old IP address matches pattern.
 
    Example 1.2. sdp_mangle_ip usage
@@ -109,15 +107,15 @@ modparam("mangler", "contact_flds_separator", "-")
 sdp_mangle_ip("10.0.0.0/8","193.175.135.38");
 ...
 
-3.2.  sdp_mangle_port(offset)
+3.2. sdp_mangle_port(offset)
 
-   Changes  ports  inside  SDP  package  in  lines  describing media like
-   m=audio 13451.
+   Changes ports in SDP document in lines starting a media section like
+   "m=audio 13451".
 
    The function returns negative on error, or number of replacements + 1.
 
    Meaning of the parameters is as follows:
-     * offset   -   A  string  representing  an  integer  which  will  be
+     * offset - A string representing an integer which will be
        added/subtracted from the located port.
 
    Example 1.3. sdp_mangle_port usage
@@ -125,36 +123,35 @@ sdp_mangle_ip("10.0.0.0/8","193.175.135.38");
 sdp_mangle_port("-12000");
 ...
 
-3.3.  encode_contact(encoding_prefix)
+3.3. encode_contact(encoding_prefix)
 
-   This function will encode uri-s inside Contact header in the following
-   manner      sip:username:password at ip:port;transport=protocol      goes
-   sip:enc_pref*username*ip*port*protocol at public_ip.  "*"  (asterisk)  is
-   the default separator.
+   This function will encode URIs inside the "Contact" header in the
+   following manner "sip:username:password at ip:port;transport=protocol"
+   goes sip:enc_pref*username*ip*port*protocol at public_ip. "*" (asterisk)
+   is the default separator.
 
    The function returns negative on error, 1 on success.
 
    Meaning of the parameters is as follows:
-     * encoding_prefix  -  Something  to  allow  us  to  determine that a
-       contact  is  encoded  public  ip--a routable IP, most probably you
-       should put your external IP of your NAT box.
+     * encoding_prefix - Something to allow us to determine that a contact
+       is encoded public IP--a routable IP, most probably you should put
+       your external IP of your NAT box.
 
    Example 1.4. encode_contact usage
 ...
 if (src_ip == 10.0.0.0/8) encode_contact("enc_prefix","193.175.135.38");
 ...
 
-3.4.  decode_contact()
+3.4. decode_contact()
 
-   This  function will decode the URI in first line in packets which come
+   This function will decode the URI in first line in packets which come
    with encoded URI in the following manner
-   sip:enc_pref*username*ip*port*protocol*src_ip*src_port*src_proto at publi
-   c_ip;parameters is converted to
-   sip:username:password at ip:port;parameters  and will set destination URI
-   to sip:src_ip:src_port;transport=src_proto (so that the next forward()
-   or  t_relay()  will  send  the  message  back to src_ip:src_port using
-   src_proto).  It  uses  the  default set parameter for contact encoding
-   separator.
+   sip:enc_pref*username*ip*port*protocol*src_ip*src_port*src_proto at public
+   _ip;parameters is converted to sip:username:password at ip:port;parameters
+   and will set destination URI to sip:src_ip:src_port;transport=src_proto
+   (so that the next forward() or t_relay() will send the message back to
+   src_ip:src_port using src_proto). It uses the default set parameter for
+   contact encoding separator.
 
    The function returns negative on error, 1 on success.
 
@@ -163,12 +160,12 @@ if (src_ip == 10.0.0.0/8) encode_contact("enc_prefix","193.175.135.38");
 if (uri =~ "^enc*") { decode_contact(); }
 ...
 
-3.5.  decode_contact_header()
+3.5. decode_contact_header()
 
-   This  function  will  decode  URIs  inside  Contact header in the same
-   manner  as  decode_contact(). The difference is that no dst_uri is set
-   (src_ip,  src_port  and src_proto are ignored) and instead of changing
-   the  request  uri,  the  Contact  header  URI is modified. It uses the
+   This function will decode URIs inside the "Contact" header in the same
+   manner as decode_contact(). The difference is that no dst_uri is set
+   (src_ip, src_port and src_proto are ignored) and instead of changing
+   the request URI, the Contact header URI is modified. It uses the
    default set parameter for contact encoding separator.
 
    The function returns negative on error, 1 on success.
diff --git a/modules/mangler/common.h b/modules/mangler/common.h
index 2fb6872..acf2aa5 100644
--- a/modules/mangler/common.h
+++ b/modules/mangler/common.h
@@ -1,23 +1,17 @@
 /*
  * mangler module
  *
- * $Id$
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -26,10 +20,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/* History:
- * --------
- *  2003-04-07 first version.  
- */
 
 #ifndef COMMON_H
 #define COMMON_H
diff --git a/modules/mangler/contact_ops.c b/modules/mangler/contact_ops.c
index 191d76e..90814dc 100644
--- a/modules/mangler/contact_ops.c
+++ b/modules/mangler/contact_ops.c
@@ -1,23 +1,16 @@
 /*
  * mangler module
  *
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -26,11 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/* History:
- * --------
- *  2003-04-07 first version.  
- */
-
 
 #include "contact_ops.h"
 #include "utils.h"
diff --git a/modules/mangler/contact_ops.h b/modules/mangler/contact_ops.h
index 100651b..059d680 100644
--- a/modules/mangler/contact_ops.h
+++ b/modules/mangler/contact_ops.h
@@ -1,23 +1,16 @@
 /*
  *  mangler module
  *
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -26,10 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/* History:
- * --------
- *  2003-04-07 first version.  
- */
 
 /* TODO :decode2format unpleasant */
 
diff --git a/modules/mangler/doc/mangler_functions.xml b/modules/mangler/doc/mangler_functions.xml
index abf71a9..63f3807 100644
--- a/modules/mangler/doc/mangler_functions.xml
+++ b/modules/mangler/doc/mangler_functions.xml
@@ -8,12 +8,12 @@
 
     <title>Functions</title>
 
-    <section id="sdp_mangle_ip">
+    <section id="mangler.f.sdp_mangle_ip">
 	<title>
 	    <function>sdp_mangle_ip(pattern, newip)</function>
 	</title>
 	<para>
-	    Changes IP addresses inside SDP package in lines describing
+	    Changes IP addresses inside SDP document in lines describing
 	    connections like c=IN IP4 . Currently this function only changes 
 	    IP4 addresses since IP6 probably will not need to traverse NAT :)
 	</para>
@@ -24,7 +24,7 @@
 	<itemizedlist>
 	    <listitem>
 		<para>
-		    <emphasis>pattern</emphasis> - A ip address/mask pair used to match
+		    <emphasis>pattern</emphasis> - An IP address/mask pair used to match
 		    IP's located inside SDP package in lines c=IN IP4 ip. This
 		    line will only be changed if located IP is in the network
 		    described by this pattern. Examples of valid patterns are
@@ -49,13 +49,13 @@ sdp_mangle_ip("10.0.0.0/8","193.175.135.38");
 	    </example>
     </section>
     
-    <section id="sdp_mangle_port">
+    <section id="mangler.f.sdp_mangle_port">
 	<title>
 	    <function>sdp_mangle_port(offset)</function>
 	</title>
 	<para>
-	    Changes ports inside SDP package in lines describing media like
-	    m=audio 13451.
+	    Changes ports in SDP document in lines starting a media section like
+	    "m=audio 13451".
 	</para>
 	<para>
 	    The function returns negative on error, or number of replacements + 1.
@@ -80,13 +80,13 @@ sdp_mangle_port("-12000");
 	</example>
     </section>
     
-    <section id="encode_contact">
+    <section id="mangler.f.encode_contact">
 	<title>
 	    <function>encode_contact(encoding_prefix)</function>
 	</title>
 	<para>
-	    This function will encode uri-s inside Contact header in the
-	    following manner sip:username:password at ip:port;transport=protocol
+	    This function will encode URIs inside the "Contact" header in the
+	    following manner "sip:username:password at ip:port;transport=protocol"
 	    goes <emphasis>sip:enc_pref*username*ip*port*protocol at public_ip</emphasis>.
 	    "*" (asterisk) is the default separator.
 	</para>
@@ -98,7 +98,7 @@ sdp_mangle_port("-12000");
 	    <listitem>
 		<para>
 		    <emphasis>encoding_prefix</emphasis> - Something to allow
-		    us to determine that a contact is encoded public ip--a
+		    us to determine that a contact is encoded public IP--a
 		    routable IP, most probably you should put your external IP
 		    of your NAT box.
 		</para>
@@ -114,7 +114,7 @@ if (src_ip == 10.0.0.0/8) encode_contact("enc_prefix","193.175.135.38");
 	</example>
     </section>
     
-    <section id="decode_contact">
+    <section id="mangler.f.decode_contact">
 	<title>
 	    <function>decode_contact()</function>
 	</title>
@@ -150,15 +150,15 @@ if (uri =~ "^enc*") { decode_contact(); }
 	</example>
     </section>
     
-    <section id="decode_contact_header">
+    <section id="mangler.f.decode_contact_header">
 	<title>
 	    <function>decode_contact_header()</function>
 	</title>
 	<para>
-	    This function will decode URIs inside Contact header in the
+	    This function will decode URIs inside the "Contact" header in the
 	    same manner as decode_contact(). The difference is that no dst_uri is set
 		 (src_ip, src_port and src_proto are ignored) and instead of changing
-		 the request uri, the Contact header URI is modified.
+		 the request URI, the Contact header URI is modified.
 		 It uses the default set parameter for contact encoding separator.
 	</para>
 	<para>
diff --git a/modules/mangler/doc/mangler_params.xml b/modules/mangler/doc/mangler_params.xml
index e72e28b..882ed5c 100644
--- a/modules/mangler/doc/mangler_params.xml
+++ b/modules/mangler/doc/mangler_params.xml
@@ -8,18 +8,18 @@
 
     <title>Parameters</title>
 
-    <section id="contact_flds_separator">
+    <section id="mangler.p.contact_flds_separator">
 	<title><varname>contact_flds_separator</varname> (string)</title>
 	<para>
-	    First char of this parameter is used as separator for
-	    encoding/decoding Contact header.
+	    First char of this parameter is used as a separator for
+	    encoding/decoding Contact headers.
 	    If you set this parameter to "-", 
-	    then an encoded uri might look sip:user-password-ip-port-protocol at PublicIP
+	    then an encoded URI will look like "sip:user-password-ip-port-protocol at PublicIP"
 	</para>
 	<warning>
 	    <para>
-		First char of this field must be set to a value which is not
-		used inside username,password or other fields of
+		The first character of this field must be set to a value which is not
+		used inside username, password or other fields of
 		contact.Otherwise it is possible for the decoding step to
 		fail/produce wrong results.
 	    </para>
diff --git a/modules/mangler/ip_helper.c b/modules/mangler/ip_helper.c
index 008a591..5dba117 100644
--- a/modules/mangler/ip_helper.c
+++ b/modules/mangler/ip_helper.c
@@ -1,23 +1,16 @@
 /*
  * Sdp mangler module
  *
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -26,10 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/* History:
- * --------
- *  2003-04-07 first version.  
- */
 
 #include "ip_helper.h"
 #include <stdlib.h>
diff --git a/modules/mangler/ip_helper.h b/modules/mangler/ip_helper.h
index 980331b..fb142a4 100644
--- a/modules/mangler/ip_helper.h
+++ b/modules/mangler/ip_helper.h
@@ -1,23 +1,16 @@
 /*
  * Sdp mangler module
  *
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -26,11 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/* History:
- * --------
- *  2003-04-07 first version.  
- */
-
 
 #ifndef IP_HELPER_H
 #define IP_HELPER_H
diff --git a/modules/mangler/mangler.c b/modules/mangler/mangler.c
index f3d3332..2da1cc7 100644
--- a/modules/mangler/mangler.c
+++ b/modules/mangler/mangler.c
@@ -1,23 +1,16 @@
 /*
  * mangler module
  *
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -26,13 +19,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/* History:
- * --------
- *  2003-04-07 first version.
- */
-
-
-
 
 #include <stdio.h>
 #include <string.h>
diff --git a/modules/mangler/mangler.h b/modules/mangler/mangler.h
index 85f0401..429db81 100644
--- a/modules/mangler/mangler.h
+++ b/modules/mangler/mangler.h
@@ -1,23 +1,16 @@
 /*
  * Sdp mangler module
  *
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -26,11 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/* History:
- * --------
- *  2003-04-07 first version.  
- */
-
 
 #ifndef MANGLER_MOD_H
 #define MANGLER_MOD_H
diff --git a/modules/mangler/sdp_mangler.c b/modules/mangler/sdp_mangler.c
index 6805702..aad5bf3 100644
--- a/modules/mangler/sdp_mangler.c
+++ b/modules/mangler/sdp_mangler.c
@@ -1,23 +1,16 @@
 /*
  * mangler module
  *
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -26,10 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/* History:
- * --------
- *  2003-04-07 first version.  
- */
 
 #include <stdio.h>
 #include <stdlib.h>
diff --git a/modules/mangler/sdp_mangler.h b/modules/mangler/sdp_mangler.h
index eb6bcf7..3837cb9 100644
--- a/modules/mangler/sdp_mangler.h
+++ b/modules/mangler/sdp_mangler.h
@@ -1,23 +1,16 @@
 /*
  * mangler module
  *
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -26,10 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/* History:
- * --------
- *  2003-04-07 first version.  
- */
 
 /* TO DO: precompiled expresions */
 
diff --git a/modules/mangler/utils.c b/modules/mangler/utils.c
index 5aead58..9cc1392 100644
--- a/modules/mangler/utils.c
+++ b/modules/mangler/utils.c
@@ -1,23 +1,16 @@
 /*
  * mangler module
  *
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -26,10 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/* History:
- * --------
- *  2003-04-07 first version.  
- */
 
 #include "utils.h"
 
diff --git a/modules/mangler/utils.h b/modules/mangler/utils.h
index eee07a2..98e01ea 100644
--- a/modules/mangler/utils.h
+++ b/modules/mangler/utils.h
@@ -1,23 +1,16 @@
 /*
  * Sdp mangler module
  *
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -26,10 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/* History:
- * --------
- *  2003-04-07 first version.  
- */
 
 #ifndef UTILS_H
 #define UTILS_H
diff --git a/modules/matrix/matrix.c b/modules/matrix/matrix.c
index a218f9f..1279a58 100644
--- a/modules/matrix/matrix.c
+++ b/modules/matrix/matrix.c
@@ -321,7 +321,7 @@ static int matrix_insert(int first, short int second, int res)
 		while (srcitem) {
 			if (srcitem->id == first) {
 				srcitem->second_list[second] = res;
-				LM_DBG("inserted (%d, %d, %d)", first, second, res);
+				LM_DBG("inserted (%d, %d, %d)\n", first, second, res);
 				return 0;
 			}
 			srcitem = srcitem->next;
@@ -329,7 +329,7 @@ static int matrix_insert(int first, short int second, int res)
 		/* not found */
 		srcitem = shm_malloc(sizeof(struct first_t));
 		if (srcitem == NULL) {
-			LM_ERR("out of shared memory.");
+			LM_ERR("out of shared memory.\n");
 			return -1;
 		}
 		memset(srcitem, 0, sizeof(struct first_t));
@@ -343,7 +343,7 @@ static int matrix_insert(int first, short int second, int res)
 		matrix->head = srcitem;
 	}
 
-	LM_DBG("inserted new row for (%d, %d, %d)", first, second, res);
+	LM_DBG("inserted new row for (%d, %d, %d)\n", first, second, res);
 	return 0;
 }
 
@@ -498,7 +498,7 @@ static int db_reload_matrix(void)
 
 	matrix_dbf.free_result(matrix_dbh, res);
 
-	LM_INFO("loaded %d matrix entries.", n);
+	LM_INFO("loaded %d matrix entries.\n", n);
 	return n;
 }
 
diff --git a/modules/maxfwd/Makefile b/modules/maxfwd/Makefile
index ea793b3..54eab05 100644
--- a/modules/maxfwd/Makefile
+++ b/modules/maxfwd/Makefile
@@ -1,6 +1,5 @@
-# $Id$
 #
-# example module makefile
+# maxfwd module makefile
 #
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
diff --git a/modules/mediaproxy/Makefile b/modules/mediaproxy/Makefile
index 8789f11..3d5d9f6 100644
--- a/modules/mediaproxy/Makefile
+++ b/modules/mediaproxy/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # mediaproxy module makefile
 #
diff --git a/modules/memcached/Makefile b/modules/memcached/Makefile
index 916b6c0..216a211 100644
--- a/modules/memcached/Makefile
+++ b/modules/memcached/Makefile
@@ -1,4 +1,3 @@
-# $Id: Makefile 3642 2008-02-06 15:46:09Z henningw $
 #
 # WARNING: do not run this directly, it should be run by the master Makefile
 
diff --git a/modules/mi_datagram/Makefile b/modules/mi_datagram/Makefile
index 8f3522d..22a0119 100644
--- a/modules/mi_datagram/Makefile
+++ b/modules/mi_datagram/Makefile
@@ -1,6 +1,5 @@
-# $Id: Makefile 1133 2006-10-02 17:31:13Z bogdan_iancu $
 #
-# example module makefile
+# mi_datagram module makefile
 #
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
diff --git a/modules/mi_datagram/datagram_fnc.c b/modules/mi_datagram/datagram_fnc.c
index 8470ddb..0309b73 100644
--- a/modules/mi_datagram/datagram_fnc.c
+++ b/modules/mi_datagram/datagram_fnc.c
@@ -331,9 +331,9 @@ static void datagram_close_async(struct mi_root *mi_rpl,struct mi_handler *hdl,
 
 	LM_DBG("the socket domain is %i and af_local is %i\n", p->domain, AF_LOCAL);
 
-	mi_create_dtgram_replysocket(reply_sock, p->domain, err);
+	memset(&dtgram, 0, sizeof(dtgram));
 
-        memset(&dtgram, 0, sizeof(dtgram));
+	mi_create_dtgram_replysocket(reply_sock, p->domain, err);
 
 	if (mi_rpl!=0) {
 		/*allocate the response datagram*/	
diff --git a/modules/mi_fifo/Makefile b/modules/mi_fifo/Makefile
index 95f2552..fc2af7b 100644
--- a/modules/mi_fifo/Makefile
+++ b/modules/mi_fifo/Makefile
@@ -1,6 +1,5 @@
-# $Id$
 #
-# example module makefile
+# mi_fifo module makefile
 #
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
diff --git a/modules/mi_fifo/README b/modules/mi_fifo/README
index ed42377..a9a8303 100644
--- a/modules/mi_fifo/README
+++ b/modules/mi_fifo/README
@@ -111,9 +111,15 @@ Chapter 1. Admin Guide
 4.1. fifo_name (string)
 
    The name of the FIFO file to be created for listening and reading
-   external commands.
+   external commands. If the value is a file name or does not start with
+   '/', the FIFO file is created in the 'run_dir'. The 'run_dir' is a core
+   parameter that can specify where to create runtime files, its default
+   value is '/var/run/kamailio/'.
 
-   Default value is NONE.
+   Default value is 'Kamailio_fifo'.
+
+   The full path used by default for FIFO file is
+   '/var/run/kamailio/Kamailio_fifo'
 
    Example 1.1. Set fifo_name parameter
 ...
diff --git a/modules/mi_fifo/doc/mi_fifo_admin.xml b/modules/mi_fifo/doc/mi_fifo_admin.xml
index 714772d..4b25035 100644
--- a/modules/mi_fifo/doc/mi_fifo_admin.xml
+++ b/modules/mi_fifo/doc/mi_fifo_admin.xml
@@ -86,13 +86,20 @@
 		<title><varname>fifo_name</varname> (string)</title>
 		<para>
 		The name of the FIFO file to be created for listening and 
-		reading external commands.
+		reading external commands. If the value is a file name or does
+		not start with '/', the FIFO file is created in the 'run_dir'. The
+		'run_dir' is a core parameter that can specify where to create
+		runtime files, its default value is '/var/run/kamailio/'.
 		</para>
 		<para>
 		<emphasis>
-			Default value is NONE.
+			Default value is '&kamailio;_fifo'.
 		</emphasis>
 		</para>
+		<para>
+			The full path used by default for FIFO file is
+			'/var/run/kamailio/&kamailio;_fifo'
+		</para>
 		<example>
 		<title>Set <varname>fifo_name</varname> parameter</title>
 		<programlisting format="linespecific">
diff --git a/modules/mi_fifo/mi_fifo.c b/modules/mi_fifo/mi_fifo.c
index 710eec1..b0046ef 100644
--- a/modules/mi_fifo/mi_fifo.c
+++ b/modules/mi_fifo/mi_fifo.c
@@ -60,7 +60,7 @@ static void fifo_process(int rank);
 static int mi_destroy(void);
 
 /* FIFO server vars */
-static char *mi_fifo = 0;		 		/*!< FIFO name */
+static char *mi_fifo = NAME "_fifo";		/*!< FIFO name */
 static char *mi_fifo_reply_dir = DEFAULT_MI_REPLY_DIR; 	/*!< dir where reply fifos are allowed */
 static char *mi_reply_indent = DEFAULT_MI_REPLY_IDENT;
 static int  mi_fifo_uid = -1;				/*!< Fifo default UID */
@@ -114,12 +114,35 @@ static int mi_mod_init(void)
 {
 	int n;
 	struct stat filestat;
+	int len;
+	int sep;
+	char *p;
 
 	/* checking the mi_fifo module param */
 	if (mi_fifo==NULL || *mi_fifo == 0) {
 		LM_ERR("No MI fifo configured\n");
 		return -1;
 	}
+	if(*mi_fifo != '/') {
+		if(runtime_dir!=NULL && *runtime_dir!=0) {
+			len = strlen(runtime_dir);
+			sep = 0;
+			if(runtime_dir[len-1]!='/') {
+				sep = 1;
+			}
+			len += sep + strlen(mi_fifo);
+			p = pkg_malloc(len + 1);
+			if(p==NULL) {
+				LM_ERR("no more pkg\n");
+				return -1;
+			}
+			strcpy(p, runtime_dir);
+			if(sep) strcat(p, "/");
+			strcat(p, mi_fifo);
+			mi_fifo = p;
+			LM_DBG("fifo path is [%s]\n", mi_fifo);
+		}
+	}
 
 	LM_DBG("testing mi_fifo existance ...\n");
 	n=stat(mi_fifo, &filestat);
diff --git a/modules/mi_rpc/Makefile b/modules/mi_rpc/Makefile
index 907ec89..05e46fc 100644
--- a/modules/mi_rpc/Makefile
+++ b/modules/mi_rpc/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # mi_rpc module makefile
 #
diff --git a/modules/mi_rpc/mi_rpc_mod.c b/modules/mi_rpc/mi_rpc_mod.c
index 2388bc9..32d444f 100644
--- a/modules/mi_rpc/mi_rpc_mod.c
+++ b/modules/mi_rpc/mi_rpc_mod.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * mi_rpc module
  *
  * Copyright (C) 2009 Daniel-Constantin Mierla (asipto.com).
diff --git a/modules/misc_radius/Makefile b/modules/misc_radius/Makefile
index 9814ebf..88f0be8 100644
--- a/modules/misc_radius/Makefile
+++ b/modules/misc_radius/Makefile
@@ -1,4 +1,3 @@
-# $Id: Makefile 1515 2007-01-16 21:25:55Z bogdan_iancu $
 #
 # WARNING: do not run this directly, it should be run by the master Makefile
 
diff --git a/modules/mohqueue/Makefile b/modules/mohqueue/Makefile
index f10bb40..8351c02 100644
--- a/modules/mohqueue/Makefile
+++ b/modules/mohqueue/Makefile
@@ -1,6 +1,5 @@
-# $Id$
 #
-# msgqueue module makefile
+# mohqueue module makefile
 #
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
diff --git a/modules/mohqueue/mohq.c b/modules/mohqueue/mohq.c
index 0a16606..711f3fe 100644
--- a/modules/mohqueue/mohq.c
+++ b/modules/mohqueue/mohq.c
@@ -1,9 +1,8 @@
 /*
- * $Id$
  *
  * Copyright (C) 2013 Robert Boisvert
  *
- * This file is part of the mohqueue module for sip-router, a free SIP server.
+ * This file is part of the mohqueue module for Kamailio, a free SIP server.
  *
  * The mohqueue module is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -134,52 +133,58 @@ return 0;
 static int init_cfg (void)
 
 {
-/**********
-* db_url, db_ctable, db_qtable exist?
-**********/
+  int error = 0;
+  int bfnd = 0;
+  struct stat psb [1];
 
+  /**********
+  * db_url, db_ctable, db_qtable exist?
+  **********/
+  
   if (!db_url.s || db_url.len<=0)
   {
-    LM_ERR ("db_url parameter not set!");
-    return 0;
+    LM_ERR ("db_url parameter not set!\n");
+    error = 1;
   }
-  pmod_data->pcfg->db_url = db_url;
 
   if (!db_ctable.s || db_ctable.len<=0)
   {
-    LM_ERR ("db_ctable parameter not set!");
-    return 0;
+    LM_ERR ("db_ctable parameter not set!\n");
+    error = 1;
   }
-  pmod_data->pcfg->db_ctable = db_ctable;
 
   if (!db_qtable.s || db_qtable.len<=0)
   {
-    LM_ERR ("db_qtable parameter not set!");
-    return 0;
+    LM_ERR ("db_qtable parameter not set!\n");
+    error = 1;
+  } 
+
+  /**********
+  * mohdir
+  * o exists?
+  * o directory?
+  **********/
+
+  if (!*mohdir) {
+    LM_ERR ("mohdir parameter not set!\n");
+    error = 1;
+  } else if (strlen(mohdir) > MOHDIRLEN) {
+    LM_ERR ("mohdir too long!");
+    error = 1;
   }
-  pmod_data->pcfg->db_qtable = db_qtable;
-
-
-/**********
-* mohdir
-* o exists?
-* o directory?
-**********/
-
-  if (!*mohdir)
+  if (moh_maxcalls < 1 || moh_maxcalls > 5000)
   {
-    LM_ERR ("mohdir parameter not set!");
-    return 0;
+    LM_ERR ("moh_maxcalls not in range of 1-5000!");
+    error = 1;
   }
-  if (strlen(mohdir) > MOHDIRLEN)
-  {
-    LM_ERR ("mohdir too long!");
-    return 0;
+  if (error == 1) {
+	return 0;
   }
+  pmod_data->pcfg->db_qtable = db_qtable;
+  pmod_data->pcfg->db_ctable = db_ctable;
+  pmod_data->pcfg->db_url = db_url;
   pmod_data->pcfg->mohdir = mohdir;
 
-  int bfnd = 0;
-  struct stat psb [1];
   if (!lstat (mohdir, psb))
   {
     if ((psb->st_mode & S_IFMT) == S_IFDIR)
@@ -187,31 +192,24 @@ static int init_cfg (void)
   }
   if (!bfnd)
   {
-    LM_ERR ("mohdir is not a directory!");
+    LM_ERR ("mohdir is not a directory!\n");
     return 0;
   }
 
-/**********
-* max calls
-* o valid count?
-* o alloc memory
-**********/
+  /**********
+  * max calls
+  * o valid count?
+  * o alloc memory
+  **********/
 
-if (moh_maxcalls < 1 || moh_maxcalls > 5000)
-  {
-  LM_ERR ("moh_maxcalls not in range of 1-5000!");
-  return 0;
+   pmod_data->pcall_lst = (call_lst *) shm_malloc (sizeof (call_lst) * moh_maxcalls);
+   if (!pmod_data->pcall_lst) {
+       LM_ERR ("Unable to allocate shared memory");
+       return -1;
   }
-pmod_data->pcall_lst =
-  (call_lst *) shm_malloc (sizeof (call_lst) * moh_maxcalls);
-if (!pmod_data->pcall_lst)
-  {
-  LM_ERR ("Unable to allocate shared memory");
+  memset (pmod_data->pcall_lst, 0, sizeof (call_lst) * moh_maxcalls);
+  pmod_data->call_cnt = moh_maxcalls;
   return -1;
-  }
-memset (pmod_data->pcall_lst, 0, sizeof (call_lst) * moh_maxcalls);
-pmod_data->call_cnt = moh_maxcalls;
-return -1;
 }
 
 /**********
@@ -373,47 +371,47 @@ if (!init_db ())
 
 if (sl_load_api (pmod_data->psl))
   {
-  LM_ERR ("Unable to load SL module");
+  LM_ERR ("Unable to load SL module\n");
   goto initerr;
   }
 if (load_tm_api (pmod_data->ptm))
   {
-  LM_ERR ("Unable to load TM module");
+  LM_ERR ("Unable to load TM module\n");
   goto initerr;
   }
 if (load_rr_api (pmod_data->prr))
   {
-  LM_ERR ("Unable to load RR module");
+  LM_ERR ("Unable to load RR module\n");
   goto initerr;
   }
 pmod_data->fn_rtp_answer = find_export ("rtpproxy_answer", 0, 0);
 if (!pmod_data->fn_rtp_answer)
   {
-  LM_ERR ("Unable to load rtpproxy_answer");
+  LM_ERR ("Unable to load rtpproxy_answer\n");
   goto initerr;
   }
 pmod_data->fn_rtp_offer = find_export ("rtpproxy_offer", 0, 0);
 if (!pmod_data->fn_rtp_offer)
   {
-  LM_ERR ("Unable to load rtpproxy_offer");
+  LM_ERR ("Unable to load rtpproxy_offer\n");
   goto initerr;
   }
 pmod_data->fn_rtp_stream_c = find_export ("rtpproxy_stream2uac", 2, 0);
 if (!pmod_data->fn_rtp_stream_c)
   {
-  LM_ERR ("Unable to load rtpproxy_stream2uac");
+  LM_ERR ("Unable to load rtpproxy_stream2uac\n");
   goto initerr;
   }
 pmod_data->fn_rtp_stream_s = find_export ("rtpproxy_stream2uas", 2, 0);
 if (!pmod_data->fn_rtp_stream_s)
   {
-  LM_ERR ("Unable to load rtpproxy_stream2uas");
+  LM_ERR ("Unable to load rtpproxy_stream2uas\n");
   goto initerr;
   }
 pmod_data->fn_rtp_destroy = find_export ("rtpproxy_destroy", 0, 0);
 if (!pmod_data->fn_rtp_destroy)
   {
-  LM_ERR ("Unable to load rtpproxy_destroy");
+  LM_ERR ("Unable to load rtpproxy_destroy\n");
   goto initerr;
   }
 
diff --git a/modules/mohqueue/mohq.h b/modules/mohqueue/mohq.h
index bc40432..b23e6a3 100644
--- a/modules/mohqueue/mohq.h
+++ b/modules/mohqueue/mohq.h
@@ -1,9 +1,7 @@
 /*
- * $Id$
- *
  * Copyright (C) 2013 Robert Boisvert
  *
- * This file is part of the mohqueue module for sip-router, a free SIP server.
+ * This file is part of the mohqueue module for Kamailio, a free SIP server.
  *
  * The mohqueue module is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -129,4 +127,4 @@ typedef struct
 extern mod_data *pmod_data;
 extern rtpmap prtpmap [];
 
-#endif /* MOHQ_H */
\ No newline at end of file
+#endif /* MOHQ_H */
diff --git a/modules/mohqueue/mohq_common.h b/modules/mohqueue/mohq_common.h
index 8cf4781..9103323 100644
--- a/modules/mohqueue/mohq_common.h
+++ b/modules/mohqueue/mohq_common.h
@@ -1,9 +1,8 @@
 /*
- * $Id$
  *
  * Copyright (C) 2013 Robert Boisvert
  *
- * This file is part of the mohqueue module for sip-router, a free SIP server.
+ * This file is part of the mohqueue module for Kamailio, a free SIP server.
  *
  * The mohqueue module is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -101,4 +100,4 @@
 #define MOHQ_HEADER_EMPTY( hdr1 ) \
 	((hdr1) == NULL || MOHQ_STR_EMPTY( &(hdr1)->body ))
 
-#endif /* MOHQ_COMMON_H */
\ No newline at end of file
+#endif /* MOHQ_COMMON_H */
diff --git a/modules/mohqueue/mohq_db.c b/modules/mohqueue/mohq_db.c
index b07985d..64ac90e 100644
--- a/modules/mohqueue/mohq_db.c
+++ b/modules/mohqueue/mohq_db.c
@@ -1,9 +1,7 @@
 /*
- * $Id$
- *
  * Copyright (C) 2013 Robert Boisvert
  *
- * This file is part of the mohqueue module for sip-router, a free SIP server.
+ * This file is part of the mohqueue module for Kamailio, a free SIP server.
  *
  * The mohqueue module is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -297,7 +295,7 @@ db1_con_t *mohq_dbconnect (void)
 str *pdb_url = &pmod_data->pcfg->db_url;
 db1_con_t *pconn = pmod_data->pdb->init (pdb_url);
 if (!pconn)
-  { LM_ERR ("Unable to connect to DB %s", pdb_url->s); }
+  { LM_ERR ("Unable to connect to DB %s\n", pdb_url->s); }
 return pconn;
 }
 
@@ -428,7 +426,7 @@ for (nidx = 0; nidx < MOHQ_COLCNT; nidx++)
 db1_res_t *presult = NULL;
 if (pdb->query (pconn, 0, 0, 0, prkeys, 0, MOHQ_COLCNT, 0, &presult))
   {
-  LM_ERR ("%stable query (%s) failed!", pfncname,
+  LM_ERR ("%stable query (%s) failed!\n", pfncname,
     pmod_data->pcfg->db_qtable.s);
   return;
   }
@@ -449,7 +447,7 @@ for (nidx = 0; nidx < nrows; nidx++)
   struct sip_uri puri_parsed [1];
   if (parse_uri (puri, strlen (puri), puri_parsed))
     {
-    LM_ERR ("Queue,Field (%s,%.*s): %s is not a valid URI!", pqname,
+    LM_ERR ("Queue,Field (%s,%.*s): %s is not a valid URI!\n", pqname,
       STR_FMT (&MOHQCSTR_URI), puri);
     continue;
     }
@@ -477,7 +475,7 @@ for (nidx = 0; nidx < nrows; nidx++)
       struct stat psb [1];
       if (lstat (pmohdir, psb))
         {
-        LM_ERR ("Queue,Field (%s,%.*s): Unable to find %s!", pqname,
+        LM_ERR ("Queue,Field (%s,%.*s): Unable to find %s!\n", pqname,
           STR_FMT (&MOHQCSTR_MDIR), pmohdir);
         continue;
         }
@@ -485,7 +483,7 @@ for (nidx = 0; nidx < nrows; nidx++)
         {
         if ((psb->st_mode & S_IFMT) != S_IFDIR)
           {
-          LM_ERR ("Queue,Field (%s,%.*s): %s is not a directory!", pqname,
+          LM_ERR ("Queue,Field (%s,%.*s): %s is not a directory!\n", pqname,
             STR_FMT (&MOHQCSTR_MDIR), pmohdir);
           continue;
           }
@@ -501,7 +499,7 @@ for (nidx = 0; nidx < nrows; nidx++)
     (char *)VAL_STRING (prowvals + MOHQCOL_MFILE));
   if (!pmohfiles [0])
     {
-    LM_ERR ("Queue,Field (%s,%.*s): Unable to find MOH files (%s/%s.*)!",
+    LM_ERR ("Queue,Field (%s,%.*s): Unable to find MOH files (%s/%s.*)!\n",
       pqname, STR_FMT (&MOHQCSTR_MDIR), pmohdir,
       (char *)VAL_STRING (prowvals + MOHQCOL_MFILE));
     continue;
@@ -576,7 +574,7 @@ for (nidx = 0; nidx < nrows; nidx++)
     pnewlst = (mohq_lst *) shm_malloc (sizeof (mohq_lst) * nsize);
     if (!pnewlst)
       {
-      LM_ERR ("%sUnable to allocate shared memory!", pfncname);
+      LM_ERR ("%sUnable to allocate shared memory!\n", pfncname);
       return;
       }
     pmod_data->mohq_cnt = nsize;
@@ -623,4 +621,4 @@ for (nidx = 0; nidx < pmod_data->mohq_cnt; nidx++)
   --nidx;
   }
 return;
-}
\ No newline at end of file
+}
diff --git a/modules/mohqueue/mohq_db.h b/modules/mohqueue/mohq_db.h
index f857214..611d455 100644
--- a/modules/mohqueue/mohq_db.h
+++ b/modules/mohqueue/mohq_db.h
@@ -1,9 +1,7 @@
 /*
- * $Id$
- *
  * Copyright (C) 2013 Robert Boisvert
  *
- * This file is part of the mohqueue module for sip-router, a free SIP server.
+ * This file is part of the mohqueue module for Kamailio, a free SIP server.
  *
  * The mohqueue module is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -63,4 +61,4 @@ void update_call_rec (call_lst *);
 void update_debug (mohq_lst *, int);
 void update_mohq_lst (db1_con_t *pconn);
 
-#endif /* MOHQ_DB_H */
\ No newline at end of file
+#endif /* MOHQ_DB_H */
diff --git a/modules/mohqueue/mohq_funcs.c b/modules/mohqueue/mohq_funcs.c
index 17316d3..1d023e6 100644
--- a/modules/mohqueue/mohq_funcs.c
+++ b/modules/mohqueue/mohq_funcs.c
@@ -1,9 +1,7 @@
 /*
- * $Id$
- *
  * Copyright (C) 2013 Robert Boisvert
  *
- * This file is part of the mohqueue module for sip-router, a free SIP server.
+ * This file is part of the mohqueue module for Kamailio, a free SIP server.
  *
  * The mohqueue module is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -195,10 +193,10 @@ if (pcall->call_state != CLSTA_INVITED)
   **********/
 
   if (pcall->call_state != CLSTA_INQUEUE)
-    { LM_ERR ("%sUnexpected ACK (%s)!", pfncname, pcall->call_from); }
+    { LM_ERR ("%sUnexpected ACK (%s)!\n", pfncname, pcall->call_from); }
   else
     {
-    mohq_debug (pcall->pmohq, "%sACK from refused re-INVITE (%s)!",
+    mohq_debug (pcall->pmohq, "%sACK from refused re-INVITE (%s)!\n",
       pfncname, pcall->call_from);
     }
   return 1;
@@ -212,7 +210,7 @@ if (pcall->call_state != CLSTA_INVITED)
 
 if (ptm->t_lookup_ident (&ptrans, pcall->call_hash, pcall->call_label) < 0)
   {
-  LM_ERR ("%sINVITE transaction missing for call (%s)!",
+  LM_ERR ("%sINVITE transaction missing for call (%s)!\n",
     pfncname, pcall->call_from);
   return 1;
   }
@@ -220,7 +218,7 @@ else
   {
   if (ptm->t_release (pcall->call_pmsg) < 0)
     {
-    LM_ERR ("%sRelease transaction failed for call (%s)!",
+    LM_ERR ("%sRelease transaction failed for call (%s)!\n",
       pfncname, pcall->call_from);
     return 1;
     }
@@ -261,7 +259,7 @@ char *pfncname = "bye_cb: ";
 call_lst *pcall = (call_lst *)*pcbp->param;
 if (ntype == TMCB_ON_FAILURE)
   {
-  LM_ERR ("%sCall (%s) did not respond to BYE", pfncname,
+  LM_ERR ("%sCall (%s) did not respond to BYE\n", pfncname,
     pcall->call_from);
   }
 else
@@ -269,7 +267,7 @@ else
   int nreply = pcbp->code;
   if ((nreply / 100) != 2)
     {
-    LM_ERR ("%sCall (%s) BYE error (%d)", pfncname,
+    LM_ERR ("%sCall (%s) BYE error (%d)\n", pfncname,
       pcall->call_from, nreply);
     }
   else
@@ -302,7 +300,7 @@ int bye_msg (sip_msg_t *pmsg, call_lst *pcall)
 char *pfncname = "bye_msg: ";
 if (pmod_data->psl->freply (pmsg, 200, presp_ok) < 0)
   {
-  LM_ERR ("%sUnable to create reply to call (%s)", pfncname,
+  LM_ERR ("%sUnable to create reply to call (%s)\n", pfncname,
     pcall->call_from);
   return 1;
   }
@@ -310,7 +308,7 @@ if (pcall->call_state >= CLSTA_INQUEUE)
   { drop_call (pmsg, pcall); }
 else
   {
-  LM_ERR ("%sEnding call (%s) before placed in queue!",
+  LM_ERR ("%sEnding call (%s) before placed in queue!\n",
     pfncname, pcall->call_from);
   delete_call (pcall);
   }
@@ -340,14 +338,14 @@ if (pcall->call_state < CLSTA_INQUEUE)
   mohq_debug (pcall->pmohq, "%sCANCELed call (%s)",
     pfncname, pcall->call_from);
   if (pmod_data->psl->freply (pmsg, 487, presp_reqterm) < 0)
-    { LM_ERR ("%sUnable to create reply!", pfncname); }
+    { LM_ERR ("%sUnable to create reply!\n", pfncname); }
   }
 else
   {
-  LM_ERR ("%sUnable to CANCEL because accepted INVITE for call (%s)!",
+  LM_ERR ("%sUnable to CANCEL because accepted INVITE for call (%s)!\n",
     pfncname, pcall->call_from);
   if (pmod_data->psl->freply (pmsg, 481, presp_nocall) < 0)
-    { LM_ERR ("%sUnable to create reply!", pfncname); }
+    { LM_ERR ("%sUnable to create reply!\n", pfncname); }
   }
 return 1;
 }
@@ -378,7 +376,7 @@ if (pmsg != FAKED_REPLY)
     pfncname, pcall->call_from);
   if (pmod_data->fn_rtp_destroy (pmsg, 0, 0) != 1)
     {
-    LM_ERR ("%srtpproxy_destroy refused for call (%s)!",
+    LM_ERR ("%srtpproxy_destroy refused for call (%s)!\n",
       pfncname, pcall->call_from);
     }
   }
@@ -402,7 +400,7 @@ int npos1 = sizeof (pbyemsg) // BYE template
 phdr = pkg_malloc (npos1);
 if (!phdr)
   {
-  LM_ERR ("%sNo more memory!", pfncname);
+  LM_ERR ("%sNo more memory!\n", pfncname);
   goto bye_err;
   }
 sprintf (phdr, pbyemsg,
@@ -422,11 +420,11 @@ set_uac_req (puac, pbye, phdrs, 0, pdlg,
 pcall->call_state = CLSTA_BYE;
 if (ptm->t_request_within (puac) < 0)
   {
-  LM_ERR ("%sUnable to create BYE request for call (%s)!",
+  LM_ERR ("%sUnable to create BYE request for call (%s)!\n",
     pfncname, pcall->call_from);
   goto bye_err;
   }
-mohq_debug (pcall->pmohq, "%sSent BYE request for call (%s)",
+mohq_debug (pcall->pmohq, "%sSent BYE request for call (%s)\n",
   pfncname, pcall->call_from);
 bsent = 1;
 
@@ -466,7 +464,7 @@ int create_call (int mohq_idx, sip_msg_t *pmsg)
 char *pfncname = "create_call: ";
 if (!mohq_lock_set (pmod_data->pcall_lock, 1, 2000))
   {
-  LM_ERR ("%sUnable to lock calls!", pfncname);
+  LM_ERR ("%sUnable to lock calls!\n", pfncname);
   return -1;
   }
 call_lst *pcall;
@@ -474,7 +472,7 @@ int ncall_idx = find_call (pmsg, &pcall);
 if (pcall)
   {
   mohq_lock_release (pmod_data->pcall_lock);
-  LM_ERR ("%sCall already in use (%s)!", pfncname, pcall->call_from);
+  LM_ERR ("%sCall already in use (%s)!\n", pfncname, pcall->call_from);
   return -1;
   }
 for (ncall_idx = 0; ncall_idx < pmod_data->call_cnt; ncall_idx++)
@@ -485,7 +483,7 @@ for (ncall_idx = 0; ncall_idx < pmod_data->call_cnt; ncall_idx++)
 if (ncall_idx == pmod_data->call_cnt)
   {
   mohq_lock_release (pmod_data->pcall_lock);
-  LM_ERR ("%sNo call slots available!", pfncname);
+  LM_ERR ("%sNo call slots available!\n", pfncname);
   return -1;
   }
 
@@ -605,14 +603,14 @@ if (pcall->call_hash || pcall->call_label)
   {
   if (ptm->t_lookup_ident (&ptrans, pcall->call_hash, pcall->call_label) < 0)
     {
-    LM_ERR ("%sLookup transaction failed for call (%s)!", pfncname,
+    LM_ERR ("%sLookup transaction failed for call (%s)!\n", pfncname,
       pcall->call_from);
     }
   else
     {
     if (ptm->t_release (pcall->call_pmsg) < 0)
       {
-      LM_ERR ("%sRelease transaction failed for call (%s)!",
+      LM_ERR ("%sRelease transaction failed for call (%s)!\n",
         pfncname, pcall->call_from);
       }
     }
@@ -655,21 +653,21 @@ char *pfncname = "deny_method: ";
 tm_api_t *ptm = pmod_data->ptm;
 if (ptm->t_newtran (pmsg) < 0)
   {
-  LM_ERR ("%sUnable to create new transaction!", pfncname);
+  LM_ERR ("%sUnable to create new transaction!\n", pfncname);
   if (pmod_data->psl->freply (pmsg, 500, presp_srverr) < 0)
     {
-    LM_ERR ("%sUnable to create reply to %.*s!", pfncname,
+    LM_ERR ("%sUnable to create reply to %.*s!\n", pfncname,
       STR_FMT (&REQ_LINE (pmsg).method));
     }
   return;
   }
 if (!add_lump_rpl2 (pmsg, pallowhdr->s, pallowhdr->len, LUMP_RPL_HDR))
-  { LM_ERR ("%sUnable to add Allow header!", pfncname); }
+  { LM_ERR ("%sUnable to add Allow header!\n", pfncname); }
 LM_ERR ("%sRefused %.*s for call (%s)!", pfncname,
   STR_FMT (&REQ_LINE (pmsg).method), pcall->call_from);
 if (ptm->t_reply (pmsg, 405, presp_noallow->s) < 0)
   {
-  LM_ERR ("%sUnable to create reply to %.*s!", pfncname,
+  LM_ERR ("%sUnable to create reply to %.*s!\n", pfncname,
     STR_FMT (&REQ_LINE (pmsg).method));
   }
 return;
@@ -699,7 +697,7 @@ if (pmsg != FAKED_REPLY)
     pfncname, pcall->call_from);
   if (pmod_data->fn_rtp_destroy (pmsg, 0, 0) != 1)
     {
-    LM_ERR ("%srtpproxy_destroy refused for call (%s)!",
+    LM_ERR ("%srtpproxy_destroy refused for call (%s)!\n",
       pfncname, pcall->call_from);
     }
   }
@@ -785,7 +783,7 @@ for (nidx = 0; nidx < pmod_data->call_cnt; nidx++)
     {
     if ((pcall->call_time + 32) < time (0))
       {
-      LM_ERR ("find_call: No ACK response for call (%s)", pcall->call_from);
+      LM_ERR ("find_call: No ACK response for call (%s)\n", pcall->call_from);
       delete_call (pcall);
       continue;
       }
@@ -831,7 +829,7 @@ int nidx;
 str tmpstr;
 if (!mohq_lock_set (pmod_data->pmohq_lock, 0, 500))
   {
-  LM_ERR ("%sUnable to lock queues!", pfncname);
+  LM_ERR ("%sUnable to lock queues!\n", pfncname);
   return -1;
   }
 for (nidx = 0; nidx < pmod_data->mohq_cnt; nidx++)
@@ -843,7 +841,7 @@ for (nidx = 0; nidx < pmod_data->mohq_cnt; nidx++)
   }
 if (nidx == pmod_data->mohq_cnt)
   {
-  LM_ERR ("%sUnable to find queue (%.*s)!", pfncname, STR_FMT (pqname));
+  LM_ERR ("%sUnable to find queue (%.*s)!\n", pfncname, STR_FMT (pqname));
   nidx = -1;
   }
 mohq_lock_release (pmod_data->pmohq_lock);
@@ -2662,4 +2660,4 @@ if (pmod_data->ptm->t_relay (pmsg, 0, 0) < 0)
   return -1;
   }
 return 1;
-}
\ No newline at end of file
+}
diff --git a/modules/mohqueue/mohq_funcs.h b/modules/mohqueue/mohq_funcs.h
index 25c06d7..dbe02c5 100644
--- a/modules/mohqueue/mohq_funcs.h
+++ b/modules/mohqueue/mohq_funcs.h
@@ -1,9 +1,7 @@
 /*
- * $Id$
- *
  * Copyright (C) 2013 Robert Boisvert
  *
- * This file is part of the mohqueue module for sip-router, a free SIP server.
+ * This file is part of the mohqueue module for Kamailio, a free SIP server.
  *
  * The mohqueue module is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -37,4 +35,4 @@ int mohq_process (sip_msg_t *);
 int mohq_retrieve (sip_msg_t *, char *, char *);
 int mohq_send (sip_msg_t *, char *);
 
-#endif /* MOHQ_FUNCS_H */
\ No newline at end of file
+#endif /* MOHQ_FUNCS_H */
diff --git a/modules/mohqueue/mohq_locks.c b/modules/mohqueue/mohq_locks.c
index 996ac52..7adb04b 100644
--- a/modules/mohqueue/mohq_locks.c
+++ b/modules/mohqueue/mohq_locks.c
@@ -1,9 +1,7 @@
 /*
- * $Id$
- *
  * Copyright (C) 2013 Robert Boisvert
  *
- * This file is part of the mohqueue module for sip-router, a free SIP server.
+ * This file is part of the mohqueue module for Kamailio, a free SIP server.
  *
  * The mohqueue module is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -196,4 +194,4 @@ do
   }
 while (!nret && --nms_cnt >= 0);
 return nret;
-}
\ No newline at end of file
+}
diff --git a/modules/mohqueue/mohq_locks.h b/modules/mohqueue/mohq_locks.h
index ddecff5..6f95c65 100644
--- a/modules/mohqueue/mohq_locks.h
+++ b/modules/mohqueue/mohq_locks.h
@@ -1,9 +1,7 @@
 /*
- * $Id$
- *
  * Copyright (C) 2013 Robert Boisvert
  *
- * This file is part of the mohqueue module for sip-router, a free SIP server.
+ * This file is part of the mohqueue module for Kamailio, a free SIP server.
  *
  * The mohqueue module is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -46,4 +44,4 @@ int mohq_lock_init (mohq_lock *);
 void mohq_lock_release (mohq_lock *);
 int mohq_lock_set (mohq_lock *, int, int);
 
-#endif /* MOHQ_LOCKS_H */
\ No newline at end of file
+#endif /* MOHQ_LOCKS_H */
diff --git a/modules/mqueue/Makefile b/modules/mqueue/Makefile
index 8305253..a31540e 100644
--- a/modules/mqueue/Makefile
+++ b/modules/mqueue/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # WARNING: do not run this directly, it should be run by the master Makefile
 
diff --git a/modules/msilo/Makefile b/modules/msilo/Makefile
index a644b8a..4aaebb2 100644
--- a/modules/msilo/Makefile
+++ b/modules/msilo/Makefile
@@ -1,6 +1,5 @@
-# $Id$
 #
-# example module makefile
+# msilo module makefile
 #
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
diff --git a/modules/msilo/README b/modules/msilo/README
index fee3574..310e8ec 100644
--- a/modules/msilo/README
+++ b/modules/msilo/README
@@ -66,6 +66,7 @@ Juha Heinanen
               3.27. max_messages (int)
               3.28. add_contact (int)
               3.29. extra_hdrs_avp (str)
+              3.30. skip_notification_flag (int)
 
         4. Functions
 
@@ -115,9 +116,10 @@ Juha Heinanen
    1.27. Set the "max_messages" parameter
    1.28. Set the "add_contact" parameter
    1.29. Set the "extra_hdrs_avp" parameter
-   1.30. m_store usage
-   1.31. m_dump usage
-   1.32. Kamailio config script - sample msilo usage
+   1.30. Set the "skip_notification_flag" parameter
+   1.31. m_store usage
+   1.32. m_dump usage
+   1.33. Kamailio config script - sample msilo usage
 
 Chapter 1. Admin Guide
 
@@ -160,6 +162,7 @@ Chapter 1. Admin Guide
         3.27. max_messages (int)
         3.28. add_contact (int)
         3.29. extra_hdrs_avp (str)
+        3.30. skip_notification_flag (int)
 
    4. Functions
 
@@ -258,6 +261,7 @@ Chapter 1. Admin Guide
    3.27. max_messages (int)
    3.28. add_contact (int)
    3.29. extra_hdrs_avp (str)
+   3.30. skip_notification_flag (int)
 
 3.1. db_url (string)
 
@@ -618,6 +622,21 @@ modparam("msilo", "add_contact", 1)
 modparam("msilo", "extra_hdrs_avp", "$avp(msilo_extra_hdrs)")
 ...
 
+3.30. skip_notification_flag (int)
+
+   Flag to mark the message for which no notification should be sent back
+   to sender when storing in msilo. Valid value is in between 0 and 31.
+
+   Default value is "-1" (feature disabled).
+
+   Example 1.30. Set the "skip_notification_flag" parameter
+...
+modparam("msilo", "skip_notification_flag", 18)
+...
+setflag(18);
+m_store(...);
+...
+
 4. Functions
 
    4.1. m_store([owner])
@@ -639,7 +658,7 @@ modparam("msilo", "extra_hdrs_avp", "$avp(msilo_extra_hdrs)")
 
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE.
 
-   Example 1.30. m_store usage
+   Example 1.31. m_store usage
 ...
 m_store();
 m_store("$tu");
@@ -659,7 +678,7 @@ m_store("$tu");
 
    This function can be used from REQUEST_ROUTE.
 
-   Example 1.31. m_dump usage
+   Example 1.32. m_dump usage
 ...
 m_dump();
 m_dump("$fu");
@@ -701,7 +720,7 @@ m_dump("$fu");
 
    Next picture displays a sample usage of msilo.
 
-   Example 1.32. Kamailio config script - sample msilo usage
+   Example 1.33. Kamailio config script - sample msilo usage
 ...
 # $Id$
 #
diff --git a/modules/msilo/api.h b/modules/msilo/api.h
index ac90912..c9d761b 100644
--- a/modules/msilo/api.h
+++ b/modules/msilo/api.h
@@ -1,5 +1,5 @@
-/**
- * $Id$
+/*! \file
+ * \brief MSILO API
  *
  */
 
diff --git a/modules/msilo/doc/msilo_admin.xml b/modules/msilo/doc/msilo_admin.xml
index 568a75c..dfb3829 100644
--- a/modules/msilo/doc/msilo_admin.xml
+++ b/modules/msilo/doc/msilo_admin.xml
@@ -655,6 +655,31 @@ modparam("msilo", "extra_hdrs_avp", "$avp(msilo_extra_hdrs)")
 		</example>
 	</section>
 
+	<section id="msilo.p.skip_notification_flag">
+		<title><varname>skip_notification_flag</varname> (int)</title>
+		<para>
+			Flag to mark the message for which no notification should be
+			sent back to sender when storing in msilo. Valid value is in
+			between 0 and 31.
+		</para>
+		<para>
+		<emphasis>
+			Default value is <quote>-1</quote> (feature disabled).
+		</emphasis>
+		</para>
+		<example>
+		<title>Set the <quote>skip_notification_flag</quote> parameter</title>
+		<programlisting format="linespecific">
+...
+modparam("msilo", "skip_notification_flag", 18)
+...
+setflag(18);
+m_store(...);
+...
+</programlisting>
+		</example>
+	</section>
+
 	</section>
 
 	<section>
diff --git a/modules/msilo/ms_msg_list.c b/modules/msilo/ms_msg_list.c
index 61ad66f..326aa30 100644
--- a/modules/msilo/ms_msg_list.c
+++ b/modules/msilo/ms_msg_list.c
@@ -1,6 +1,4 @@
 /**
- * $Id$
- *
  * MSILO module
  *
  * Copyright (C) 2001-2003 FhG Fokus
@@ -21,9 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2003-03-11  major locking changes: not it uses locking.h (andrei)
  */
 
 #include <string.h>
diff --git a/modules/msilo/ms_msg_list.h b/modules/msilo/ms_msg_list.h
index a9ce34d..e6e67e7 100644
--- a/modules/msilo/ms_msg_list.h
+++ b/modules/msilo/ms_msg_list.h
@@ -1,6 +1,4 @@
 /**
- * $Id$
- *
  * MSILO module
  *
  * Copyright (C) 2001-2003 FhG Fokus
@@ -21,9 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2003-03-11  major locking changes, now it uses locking.h (andrei)
  */
 
 #ifndef _MS_MSG_LIST_H_
diff --git a/modules/msilo/msfuncs.c b/modules/msilo/msfuncs.c
index 7784b13..32c8aa7 100644
--- a/modules/msilo/msfuncs.c
+++ b/modules/msilo/msfuncs.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/msilo/msfuncs.h b/modules/msilo/msfuncs.h
index cd1eb6b..80cc4b7 100644
--- a/modules/msilo/msfuncs.h
+++ b/modules/msilo/msfuncs.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/msilo/msilo.c b/modules/msilo/msilo.c
index cf68150..c93a35d 100644
--- a/modules/msilo/msilo.c
+++ b/modules/msilo/msilo.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * MSILO module
  *
  * Copyright (C) 2001-2003 FhG Fokus
@@ -21,25 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History
- * -------
- *
- * 2003-01-23: switched from t_uac to t_uac_dlg (dcm)
- * 2003-02-28: protocolization of t_uac_dlg completed (jiri)
- * 2003-03-11: updated to the new module interface (andrei)
- *             removed non-constant initializers to some strs (andrei)
- * 2003-03-16: flags parameter added (janakj)
- * 2003-04-05: default_uri #define used (jiri)
- * 2003-04-06: db_init removed from mod_init, will be called from child_init
- *             now (janakj)
- * 2003-04-07: m_dump takes a parameter which sets the way the outgoing URI
- *             is computed (dcm)
- * 2003-08-05 adapted to the new parse_content_type_hdr function (bogdan)
- * 2004-06-07 updated to the new DB api (andrei)
- * 2006-09-10 m_dump now checks if registering UA supports MESSAGE method (jh)
- * 2006-10-05 added max_messages module variable (jh)
- * 2011-10-19 added storage of extra SIP headers (hpw)
- * 2011-12-07 added storage of extra SIP headers from AVP (jh)
  */
 
 #include <stdio.h>
@@ -112,7 +91,7 @@ static str sc_stored_hdrs = str_init("extra_hdrs"); /* 10 */
 
 MODULE_VERSION
 
-#define S_TABLE_VERSION 7
+#define S_TABLE_VERSION 8
 
 /** database connection */
 static db1_con_t *db_con = NULL;
@@ -160,6 +139,7 @@ int_str ms_extra_hdrs_avp_name;
 unsigned short ms_extra_hdrs_avp_type;
 
 str msg_type = str_init("MESSAGE");
+static int ms_skip_notification_flag = -1;
 
 /** module functions */
 static int mod_init(void);
@@ -229,6 +209,7 @@ static param_export_t params[]={
 	{ "add_date",         INT_PARAM, &ms_add_date             },
 	{ "max_messages",     INT_PARAM, &ms_max_messages         },
 	{ "add_contact",      INT_PARAM, &ms_add_contact          },
+	{ "skip_notification_flag", PARAM_INT, &ms_skip_notification_flag },
 	{ 0,0,0 }
 };
 
@@ -296,6 +277,15 @@ static int mod_init(void)
 	}
 #endif
 
+	if(ms_skip_notification_flag!=-1) {
+		if(ms_skip_notification_flag<0 || ms_skip_notification_flag>31) {
+			LM_ERR("invalid skip notification flag value: %d\n",
+					ms_skip_notification_flag);
+			return -1;
+		}
+		ms_skip_notification_flag = 1 << ms_skip_notification_flag;
+	}
+
 	/* binding to mysql module  */
 	if (db_bind_mod(&ms_db_url, &msilo_dbf))
 	{
@@ -831,7 +821,9 @@ static int m_store(struct sip_msg* msg, str *owner_s)
 	update_stat(ms_stored_msgs, 1);
 #endif
 
-	if(ms_from==NULL || ms_offline_message == NULL)
+	if(ms_from==NULL || ms_offline_message == NULL
+			|| (ms_skip_notification_flag!=-1
+				&& (msg->flags & ms_skip_notification_flag)))
 		goto done;
 
 	LM_DBG("sending info message.\n");
diff --git a/modules/msrp/Makefile b/modules/msrp/Makefile
index 436f47f..bd855ea 100644
--- a/modules/msrp/Makefile
+++ b/modules/msrp/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # WARNING: do not run this directly, it should be run by the master Makefile
 
diff --git a/modules/msrp/msrp_cmap.c b/modules/msrp/msrp_cmap.c
index 557d1a4..6583e5a 100644
--- a/modules/msrp/msrp_cmap.c
+++ b/modules/msrp/msrp_cmap.c
@@ -1,6 +1,4 @@
 /**
- * $Id$
- *
  * Copyright (C) 2013 Daniel-Constantin Mierla (asipto.com)
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/msrp/msrp_cmap.h b/modules/msrp/msrp_cmap.h
index acb77fd..81dca07 100644
--- a/modules/msrp/msrp_cmap.h
+++ b/modules/msrp/msrp_cmap.h
@@ -1,6 +1,4 @@
 /**
- * $Id$
- *
  * Copyright (C) 2013 Daniel-Constantin Mierla (asipto.com)
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/msrp/msrp_env.c b/modules/msrp/msrp_env.c
index 5fdf36d..e2ccf47 100644
--- a/modules/msrp/msrp_env.c
+++ b/modules/msrp/msrp_env.c
@@ -1,6 +1,4 @@
 /**
- * $Id$
- *
  * Copyright (C) 2012 Daniel-Constantin Mierla (asipto.com)
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/msrp/msrp_env.h b/modules/msrp/msrp_env.h
index 17035b7..133950c 100644
--- a/modules/msrp/msrp_env.h
+++ b/modules/msrp/msrp_env.h
@@ -1,6 +1,4 @@
 /**
- * $Id$
- *
  * Copyright (C) 2012 Daniel-Constantin Mierla (asipto.com)
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/msrp/msrp_mod.c b/modules/msrp/msrp_mod.c
index e068e32..4e168ce 100644
--- a/modules/msrp/msrp_mod.c
+++ b/modules/msrp/msrp_mod.c
@@ -1,6 +1,4 @@
 /**
- * $Id$
- *
  * Copyright (C) 2012 Daniel-Constantin Mierla (asipto.com)
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/msrp/msrp_netio.c b/modules/msrp/msrp_netio.c
index 114ba64..1a169a7 100644
--- a/modules/msrp/msrp_netio.c
+++ b/modules/msrp/msrp_netio.c
@@ -1,6 +1,4 @@
 /**
- * $Id$
- *
  * Copyright (C) 2012 Daniel-Constantin Mierla (asipto.com)
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/msrp/msrp_netio.h b/modules/msrp/msrp_netio.h
index a593675..00df67a 100644
--- a/modules/msrp/msrp_netio.h
+++ b/modules/msrp/msrp_netio.h
@@ -1,6 +1,4 @@
 /**
- * $Id$
- *
  * Copyright (C) 2012 Daniel-Constantin Mierla (asipto.com)
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/msrp/msrp_parser.c b/modules/msrp/msrp_parser.c
index 0a6492c..e9cb11f 100644
--- a/modules/msrp/msrp_parser.c
+++ b/modules/msrp/msrp_parser.c
@@ -1,6 +1,4 @@
 /**
- * $Id$
- *
  * Copyright (C) 2012 Daniel-Constantin Mierla (asipto.com)
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/msrp/msrp_parser.h b/modules/msrp/msrp_parser.h
index 5977dc2..1ee9983 100644
--- a/modules/msrp/msrp_parser.h
+++ b/modules/msrp/msrp_parser.h
@@ -1,6 +1,4 @@
 /**
- * $Id$
- *
  * Copyright (C) 2012 Daniel-Constantin Mierla (asipto.com)
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/msrp/msrp_vars.c b/modules/msrp/msrp_vars.c
index 088e399..98452fe 100644
--- a/modules/msrp/msrp_vars.c
+++ b/modules/msrp/msrp_vars.c
@@ -1,6 +1,4 @@
 /**
- * $Id$
- *
  * Copyright (C) 2012 Daniel-Constantin Mierla (asipto.com)
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/msrp/msrp_vars.h b/modules/msrp/msrp_vars.h
index 566d1c7..34ca331 100644
--- a/modules/msrp/msrp_vars.h
+++ b/modules/msrp/msrp_vars.h
@@ -1,6 +1,4 @@
 /**
- * $Id$
- *
  * Copyright (C) 2012 Daniel-Constantin Mierla (asipto.com)
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/mtree/Makefile b/modules/mtree/Makefile
index 291d19c..b89770a 100644
--- a/modules/mtree/Makefile
+++ b/modules/mtree/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # WARNING: do not run this directly, it should be run by the master Makefile
 
diff --git a/modules/nat_traversal/Makefile b/modules/nat_traversal/Makefile
index 684fdf7..53846df 100644
--- a/modules/nat_traversal/Makefile
+++ b/modules/nat_traversal/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # nat_traversal module makefile
 #
diff --git a/modules/nat_traversal/nat_traversal.c b/modules/nat_traversal/nat_traversal.c
index 87aaf50..45fa5c0 100644
--- a/modules/nat_traversal/nat_traversal.c
+++ b/modules/nat_traversal/nat_traversal.c
@@ -1,5 +1,4 @@
-/* $Id$
- *
+/*
  * Copyright (C) 2007-2009 Dan Pascu
  *
  * This file is part of Kamailio, a free SIP server.
@@ -20,6 +19,21 @@
  *
  */
 
+/*!
+ * \file
+ * \brief Module interface and functions
+ * \ingroup nat_traversal
+ * Module: \ref nat_traversal
+ */
+
+/**
+ * @defgroup nat_traversal Nat
+ * @brief Kamailio nat_traversal module
+
+   The nat_traversal module provides support for handling far-end NAT
+   traversal for SIP signaling. 
+ */
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
diff --git a/modules/nathelper/Makefile b/modules/nathelper/Makefile
index b2a605a..f5b9f18 100644
--- a/modules/nathelper/Makefile
+++ b/modules/nathelper/Makefile
@@ -1,6 +1,5 @@
-# $Id$
 #
-# print example module makefile
+# nathelper module makefile
 #
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
diff --git a/modules/nathelper/README b/modules/nathelper/README
index a526fe7..39168be 100644
--- a/modules/nathelper/README
+++ b/modules/nathelper/README
@@ -59,6 +59,7 @@ Ovidiu Sas
               4.11. nortpproxy_str (string)
               4.12. keepalive_timeout (int)
               4.13. udpping_from_path (int)
+              4.14. append_sdp_oldmediaip (int)
 
         5. Functions
 
@@ -102,17 +103,18 @@ Ovidiu Sas
    1.11. Set nortpproxy_str parameter
    1.12. Set keepalive_timeout parameter
    1.13. Set udpping_from_path parameter
-   1.14. fix_nated_contact usage
-   1.15. fix_nated_sdp usage
-   1.16. add_rcv_paramer usage
-   1.17. fix_nated_register usage
-   1.18. add_contact_alias usage
-   1.19. handle_ruri_alias usage
-   1.20. set_contact_alias usage
-   1.21. $rr_count usage
-   1.22. $rr_top_count usage
-   1.23. nh_enable_ping usage
-   1.24. @nathelper.rewrite_contact usage
+   1.14. Set append_sdp_oldmediaip parameter
+   1.15. fix_nated_contact usage
+   1.16. fix_nated_sdp usage
+   1.17. add_rcv_paramer usage
+   1.18. fix_nated_register usage
+   1.19. add_contact_alias usage
+   1.20. handle_ruri_alias usage
+   1.21. set_contact_alias usage
+   1.22. $rr_count usage
+   1.23. $rr_top_count usage
+   1.24. nh_enable_ping usage
+   1.25. @nathelper.rewrite_contact usage
 
 Chapter 1. Admin Guide
 
@@ -140,6 +142,7 @@ Chapter 1. Admin Guide
         4.11. nortpproxy_str (string)
         4.12. keepalive_timeout (int)
         4.13. udpping_from_path (int)
+        4.14. append_sdp_oldmediaip (int)
 
    5. Functions
 
@@ -236,6 +239,7 @@ Chapter 1. Admin Guide
    4.11. nortpproxy_str (string)
    4.12. keepalive_timeout (int)
    4.13. udpping_from_path (int)
+   4.14. append_sdp_oldmediaip (int)
 
 4.1. force_socket (string)
 
@@ -426,6 +430,18 @@ modparam("nathelper", "keepalive_timeout", 120)
 modparam("nathelper", "udpping_from_path", 1)
 ...
 
+4.14. append_sdp_oldmediaip (int)
+
+   The parameter controls if oldmediaip field should be appended to the
+   SDP.
+
+   Default value is "1" (feature enabled).
+
+   Example 1.14. Set append_sdp_oldmediaip parameter
+...
+modparam("nathelper", "append_sdp_oldmediaip", 1)
+...
+
 5. Functions
 
    5.1. fix_nated_contact()
@@ -446,7 +462,7 @@ modparam("nathelper", "udpping_from_path", 1)
    This function can be used from REQUEST_ROUTE, ONREPLY_ROUTE,
    BRANCH_ROUTE.
 
-   Example 1.14. fix_nated_contact usage
+   Example 1.15. fix_nated_contact usage
 ...
 if (search("User-Agent: Cisco ATA.*") {fix_nated_contact();};
 ...
@@ -476,7 +492,7 @@ if (search("User-Agent: Cisco ATA.*") {fix_nated_contact();};
    This function can be used from REQUEST_ROUTE, ONREPLY_ROUTE,
    FAILURE_ROUTE, BRANCH_ROUTE.
 
-   Example 1.15. fix_nated_sdp usage
+   Example 1.16. fix_nated_sdp usage
 ...
 if (search("User-Agent: Cisco ATA.*") {fix_nated_sdp("3");};
 ...
@@ -498,7 +514,7 @@ if (search("User-Agent: Cisco ATA.*") {fix_nated_sdp("3");};
 
    This function can be used from REQUEST_ROUTE.
 
-   Example 1.16. add_rcv_paramer usage
+   Example 1.17. add_rcv_paramer usage
 ...
 add_rcv_param(); # add the parameter to the Contact header
 ....
@@ -518,7 +534,7 @@ add_rcv_param("1"); # add the parameter to the Contact URI
 
    This function can be used from REQUEST_ROUTE.
 
-   Example 1.17. fix_nated_register usage
+   Example 1.18. fix_nated_register usage
 ...
 fix_nated_register();
 ...
@@ -569,7 +585,7 @@ fix_nated_register();
    This function can be used from REQUEST_ROUTE, ONREPLY_ROUTE,
    BRANCH_ROUTE, and LOCAL_ROUTE.
 
-   Example 1.18. add_contact_alias usage
+   Example 1.19. add_contact_alias usage
 ...
     if (!is_present_hf("Record-Route")) {
         if (!add_contact_alias("$var(src_ip)", "$Rp", "tcp")) {
@@ -596,7 +612,7 @@ fix_nated_register();
    This function can be used from REQUEST_ROUTE, BRANCH_ROUTE, and
    LOCAL_ROUTE.
 
-   Example 1.19. handle_ruri_alias usage
+   Example 1.20. handle_ruri_alias usage
 ...
     if ($du == "") {
         handle_ruri_alias();
@@ -625,7 +641,7 @@ fix_nated_register();
    This function can be used from REQUEST_ROUTE, ONREPLY_ROUTE,
    BRANCH_ROUTE, and FAILURE_ROUTE.
 
-   Example 1.20. set_contact_alias usage
+   Example 1.21. set_contact_alias usage
 ...
     if (!is_present_hf("Record-Route")) {
         if (!set_contact_alias()) {
@@ -645,7 +661,7 @@ fix_nated_register();
 
    Number of Record Routes in received SIP request or reply.
 
-   Example 1.21. $rr_count usage
+   Example 1.22. $rr_count usage
 ...
     $avp(rr_count) = $rr_count;
 ...
@@ -657,7 +673,7 @@ fix_nated_register();
    value of $rr_top_count is 1. If there is no Record Route(s), value of
    $rr_top_count is 0.
 
-   Example 1.22. $rr_top_count usage
+   Example 1.23. $rr_top_count usage
 ...
     if ($rr_count == $avp(rr_count) + $rr_top_count) {
         route(ADD_CONTACT_ALIAS);
@@ -675,7 +691,7 @@ fix_nated_register();
 
    The function takes only one parameter - a number in decimal format.
 
-   Example 1.23. nh_enable_ping usage
+   Example 1.24. nh_enable_ping usage
 ...
 $ kamctl fifo nh_enable_ping 1
 ...
@@ -690,7 +706,7 @@ $ kamctl fifo nh_enable_ping 1
    counted from 1. Only IP:port is rewritten, remaining part are left
    unchanged. Full nameaddr is supported.
 
-   Example 1.24. @nathelper.rewrite_contact usage
+   Example 1.25. @nathelper.rewrite_contact usage
 ...
 $c = @nathelper.rewrite_contact[1];
 ...
diff --git a/modules/nathelper/doc/nathelper_admin.xml b/modules/nathelper/doc/nathelper_admin.xml
index 7283704..66101d5 100644
--- a/modules/nathelper/doc/nathelper_admin.xml
+++ b/modules/nathelper/doc/nathelper_admin.xml
@@ -420,6 +420,25 @@ modparam("nathelper", "udpping_from_path", 1)
 </programlisting>
 		</example>
 	</section>
+	<section id="nathelper.p.append_sdp_oldmediaip">
+		<title><varname>append_sdp_oldmediaip</varname> (int)</title>
+		<para>
+		The parameter controls if oldmediaip field should be appended to the SDP.
+		</para>
+		<para>
+		<emphasis>
+			Default value is <quote>1</quote> (feature enabled).
+		</emphasis>
+		</para>
+		<example>
+		<title>Set <varname>append_sdp_oldmediaip</varname> parameter</title>
+		<programlisting format="linespecific">
+...
+modparam("nathelper", "append_sdp_oldmediaip", 1)
+...
+</programlisting>
+		</example>
+	</section>
 	</section>
 
 
diff --git a/modules/nathelper/nathelper.c b/modules/nathelper/nathelper.c
index 58f56b4..f6791db 100644
--- a/modules/nathelper/nathelper.c
+++ b/modules/nathelper/nathelper.c
@@ -352,6 +352,7 @@ static int_str rcv_avp_name;
 
 static char *natping_socket = 0;
 static int udpping_from_path = 0;
+static int sdp_oldmediaip = 1;
 static int raw_sock = -1;
 static unsigned int raw_ip = 0;
 static unsigned short raw_port = 0;
@@ -424,6 +425,7 @@ static param_export_t params[] = {
 	{"natping_socket",        PARAM_STRING, &natping_socket        },
 	{"keepalive_timeout",     INT_PARAM, &nh_keepalive_timeout  },
 	{"udpping_from_path",     INT_PARAM, &udpping_from_path     },
+	{"append_sdp_oldmediaip", INT_PARAM, &sdp_oldmediaip        },
 
 	{0, 0, 0}
 };
@@ -673,6 +675,7 @@ mod_init(void)
 			LM_ERR("bad config - natping_processes must be >= 0\n");
 			return -1;
 		}
+		ul.set_max_partition(natping_processes*natping_interval);
 
 		sipping_flag = (sipping_flag==-1)?0:(1<<sipping_flag);
 		natping_disable_flag = (natping_disable_flag==-1)?0:(1<<natping_disable_flag);
@@ -1682,7 +1685,7 @@ replace_sdp_ip(struct sip_msg* msg, str *org_body, char *line, str *ip)
 		}
 		body2.s = oldip.s + oldip.len;
 		body2.len = bodylimit - body2.s;
-		ret = alter_mediaip(msg, &body1, &oldip, pf, &newip, pf,1);
+		ret = alter_mediaip(msg, &body1, &oldip, pf, &newip, pf, sdp_oldmediaip);
 		if (ret == -1) {
 			LM_ERR("can't alter '%s' IP\n",line);
 			return -1;
@@ -2049,6 +2052,8 @@ nh_timer(unsigned int ticks, void *timer_idx)
 	int rval;
 	void *buf, *cp;
 	str c;
+	str recv;
+	str *dst_uri;
 	str opt;
 	str path;
 	str ruid;
@@ -2109,6 +2114,9 @@ nh_timer(unsigned int ticks, void *timer_idx)
 			break;
 		c.s = (char*)cp + sizeof(c.len);
 		cp =  (char*)cp + sizeof(c.len) + c.len;
+		memcpy(&(recv.len), cp, sizeof(recv.len));
+		recv.s = (char*)cp + sizeof(recv.len);
+		cp =  (char*)cp + sizeof(recv.len) + recv.len;
 		memcpy( &send_sock, cp, sizeof(send_sock));
 		cp = (char*)cp + sizeof(send_sock);
 		memcpy( &flags, cp, sizeof(flags));
@@ -2125,6 +2133,9 @@ nh_timer(unsigned int ticks, void *timer_idx)
 		if ((flags & natping_disable_flag)) /* always 0 if natping_disable_flag not set */
 			continue;
 
+		if(recv.len>0) dst_uri = &recv;
+		else dst_uri = &c;
+
 		/* determin the destination */
 		if ( path.len && (flags&sipping_flag)!=0 ) {
 			/* send to first URI in path */
@@ -2147,14 +2158,14 @@ nh_timer(unsigned int ticks, void *timer_idx)
 				LM_ERR("could not parse path host for udpping_from_path\n");
 				continue;
 			}
-			if (parse_uri(c.s, c.len, &curi) < 0) {
-				LM_ERR("can't parse contact uri\n");
+			if (parse_uri(dst_uri->s, dst_uri->len, &curi) < 0) {
+				LM_ERR("can't parse contact/received uri\n");
 				continue;
 			}
 		} else {
 			/* send to the contact/received */
-			if (parse_uri(c.s, c.len, &curi) < 0) {
-				LM_ERR("can't parse contact uri\n");
+			if (parse_uri(dst_uri->s, dst_uri->len, &curi) < 0) {
+				LM_ERR("can't parse contact/received uri\n");
 				continue;
 			}
 		}
@@ -2221,94 +2232,7 @@ done:
 static int
 create_rcv_uri(str* uri, struct sip_msg* m)
 {
-	static char buf[MAX_URI_SIZE];
-	char* p;
-	str ip, port;
-	int len;
-	str proto;
-
-	if (!uri || !m) {
-		LM_ERR("invalid parameter value\n");
-		return -1;
-	}
-
-	ip.s = ip_addr2a(&m->rcv.src_ip);
-	ip.len = strlen(ip.s);
-
-	port.s = int2str(m->rcv.src_port, &port.len);
-
-	switch(m->rcv.proto) {
-	case PROTO_NONE:
-	case PROTO_UDP:
-		proto.s = 0; /* Do not add transport parameter, UDP is default */
-		proto.len = 0;
-		break;
-
-	case PROTO_TCP:
-		proto.s = "TCP";
-		proto.len = 3;
-		break;
-
-	case PROTO_TLS:
-		proto.s = "TLS";
-		proto.len = 3;
-		break;
-
-	case PROTO_SCTP:
-		proto.s = "SCTP";
-		proto.len = 4;
-		break;
-
-	case PROTO_WS:
-	case PROTO_WSS:
-		proto.s = "WS";
-		proto.len = 2;
-		break;
-
-	default:
-		LM_ERR("unknown transport protocol\n");
-		return -1;
-	}
-
-	len = 4 + ip.len + 2*(m->rcv.src_ip.af==AF_INET6)+ 1 + port.len;
-	if (proto.s) {
-		len += TRANSPORT_PARAM_LEN;
-		len += proto.len;
-	}
-
-	if (len > MAX_URI_SIZE) {
-		LM_ERR("buffer too small\n");
-		return -1;
-	}
-
-	p = buf;
-	memcpy(p, "sip:", 4);
-	p += 4;
-	
-	if (m->rcv.src_ip.af==AF_INET6)
-		*p++ = '[';
-	memcpy(p, ip.s, ip.len);
-	p += ip.len;
-	if (m->rcv.src_ip.af==AF_INET6)
-		*p++ = ']';
-
-	*p++ = ':';
-	
-	memcpy(p, port.s, port.len);
-	p += port.len;
-
-	if (proto.s) {
-		memcpy(p, TRANSPORT_PARAM, TRANSPORT_PARAM_LEN);
-		p += TRANSPORT_PARAM_LEN;
-
-		memcpy(p, proto.s, proto.len);
-		p += proto.len;
-	}
-
-	uri->s = buf;
-	uri->len = len;
-
-	return 0;
+	return get_src_uri(m, 0, uri);
 }
 
 
diff --git a/modules/ndb_cassandra/.gitignore b/modules/ndb_cassandra/.gitignore
new file mode 100644
index 0000000..e4e5f6c
--- /dev/null
+++ b/modules/ndb_cassandra/.gitignore
@@ -0,0 +1 @@
+*~
\ No newline at end of file
diff --git a/modules/ndb_mongodb/README b/modules/ndb_mongodb/README
index cef2482..0c655e5 100644
--- a/modules/ndb_mongodb/README
+++ b/modules/ndb_mongodb/README
@@ -10,7 +10,7 @@ Daniel-Constantin Mierla
 
    <miconda at gmail.com>
 
-   Copyright � 2014 asipto.com
+   Copyright © 2014 asipto.com
      __________________________________________________________________
 
    Table of Contents
@@ -34,8 +34,11 @@ Daniel-Constantin Mierla
                       replyid)
 
               4.3. mongodb_find(srvname, dbname, cname, command, replyid)
-              4.4. mongodb_next(replyid)
-              4.5. mongodb_free(replyid)
+              4.4. mongodb_find_one(srvname, dbname, cname, command,
+                      replyid)
+
+              4.5. mongodb_next(replyid)
+              4.6. mongodb_free(replyid)
 
    List of Examples
 
@@ -43,8 +46,9 @@ Daniel-Constantin Mierla
    1.2. mongodb_cmd usage
    1.3. mongodb_cmd_simple usage
    1.4. mongodb_find usage
-   1.5. mongodb_next usage
-   1.6. mongodb_free usage
+   1.5. mongodb_find_one usage
+   1.6. mongodb_next usage
+   1.7. mongodb_free usage
 
 Chapter 1. Admin Guide
 
@@ -65,8 +69,9 @@ Chapter 1. Admin Guide
         4.1. mongodb_cmd(srvname, dbname, cname, command, replyid)
         4.2. mongodb_cmd_simple(srvname, dbname, cname, command, replyid)
         4.3. mongodb_find(srvname, dbname, cname, command, replyid)
-        4.4. mongodb_next(replyid)
-        4.5. mongodb_free(replyid)
+        4.4. mongodb_find_one(srvname, dbname, cname, command, replyid)
+        4.5. mongodb_next(replyid)
+        4.6. mongodb_free(replyid)
 
 1. Overview
 
@@ -124,10 +129,11 @@ modparam("ndb_mongodb", "server", "name=mgs2;uri='mongodb://127.0.0.2/kamailio'"
    4.1. mongodb_cmd(srvname, dbname, cname, command, replyid)
    4.2. mongodb_cmd_simple(srvname, dbname, cname, command, replyid)
    4.3. mongodb_find(srvname, dbname, cname, command, replyid)
-   4.4. mongodb_next(replyid)
-   4.5. mongodb_free(replyid)
+   4.4. mongodb_find_one(srvname, dbname, cname, command, replyid)
+   4.5. mongodb_next(replyid)
+   4.6. mongodb_free(replyid)
 
-4.1. mongodb_cmd(srvname, dbname, cname, command, replyid)
+4.1.  mongodb_cmd(srvname, dbname, cname, command, replyid)
 
    Send a valid command to MongoDB server identified by srvname. The reply
    will be stored in a local container identified by replyid. All the
@@ -159,7 +165,7 @@ if(mongodb_cmd("mgs1", "kamailio", "acc", "{ \"collStats\": \"acc\" }", "mgr1"))
 }
 ...
 
-4.2. mongodb_cmd_simple(srvname, dbname, cname, command, replyid)
+4.2.  mongodb_cmd_simple(srvname, dbname, cname, command, replyid)
 
    Send a valid command to MongoDB server identified by srvname. The reply
    will be stored in a local container identified by replyid. All the
@@ -185,7 +191,7 @@ mgr1")) {
 }
 ...
 
-4.3. mongodb_find(srvname, dbname, cname, command, replyid)
+4.3.  mongodb_find(srvname, dbname, cname, command, replyid)
 
    Send a find command to MongoDB server identified by srvname. The reply
    will be stored in a local container identified by replyid. All the
@@ -214,14 +220,31 @@ if(mongodb_find("mgs1", "kamailio", "acc", "{ \"src_user\" : \"111\" }", "mgr1")
 }
 ...
 
-4.4. mongodb_next(replyid)
+4.4.  mongodb_find_one(srvname, dbname, cname, command, replyid)
+
+   Similar to mongodb_find(...), but it stops searching after first match,
+   returning the result with one object - faster when expecting to have a
+   single match. Parameters and behaviour are the same as for
+   mongodb_find(...).
+
+   The function can be used from ANY_ROUTE.
+
+   Example 1.5. mongodb_find_one usage
+...
+if(mongodb_find_one("mgs1", "kamailio", "subscriber", "{ \"username\" : \"111\"
+}", "mgr1")) {
+        xlog("response from mongodb is [[$mongodb(mgr1=>value)]]\n");
+}
+...
+
+4.5.  mongodb_next(replyid)
 
    Moves to next document in a MongoDB reply. This function can be used
    after a succesful mongodb_cmd() or mongodb_find(). It returns true if
    there is a shift to document. The current document becomes available
    via $mongodb(key) variable.
 
-   Example 1.5. mongodb_next usage
+   Example 1.6. mongodb_next usage
 ...
 if(mongodb_find("mgs1", "kamailio", "acc", "{ \"src_user\" : \"111\" }", "mgr1")
 ) {
@@ -233,7 +256,7 @@ if(mongodb_find("mgs1", "kamailio", "acc", "{ \"src_user\" : \"111\" }", "mgr1")
 mongodb_free("mgr1");
 ...
 
-4.5. mongodb_free(replyid)
+4.6.  mongodb_free(replyid)
 
    Frees data in a previous reply from memory. After this function call,
    accessing to a freed replyid returns null value.
@@ -243,7 +266,7 @@ mongodb_free("mgr1");
    execution, but for freeing used resources (e.g., memory), it is
    recommended to do it.
 
-   Example 1.6. mongodb_free usage
+   Example 1.7. mongodb_free usage
 ...
 if(mongodb_cmd_simple("mgs1", "kamailio", "acc", "{ \"collStats\": \"acc\" }", "
 mgr1")) {
diff --git a/modules/ndb_mongodb/api.h b/modules/ndb_mongodb/api.h
new file mode 100644
index 0000000..4ffd43f
--- /dev/null
+++ b/modules/ndb_mongodb/api.h
@@ -0,0 +1,69 @@
+/**
+ * ndb_mongodb module
+ * 
+ * Copyright (C) 2015 Daniel-Constantin Mierla (asipto.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _NDB_MONGODB_API_H_
+#define _NDB_MONGODB_API_H_
+
+#include "../../sr_module.h"
+
+typedef int (*mongodbc_exec_simple_f)(str *srv, str *dname, str *cname, str *cmd, str *res);
+typedef int (*mongodbc_exec_f)(str *srv, str *dname, str *cname, str *cmd, str *res);
+typedef int (*mongodbc_find_f)(str *srv, str *dname, str *cname, str *cmd, str *res);
+typedef int (*mongodbc_find_one_f)(str *srv, str *dname, str *cname, str *cmd, str *res);
+typedef int (*mongodbc_next_reply_f)(str *name);
+typedef int (*mongodbc_free_reply_f)(str *name);
+
+
+typedef struct ndb_mongodb_api {
+	mongodbc_exec_simple_f cmd_simple;
+	mongodbc_exec_f	cmd;
+	mongodbc_find_f	find;
+	mongodbc_find_one_f	find_one;
+	mongodbc_next_reply_f next_reply;
+	mongodbc_next_reply_f free_reply;
+} ndb_mongodb_api_t;
+
+typedef int (*bind_ndb_mongodb_f)(ndb_mongodb_api_t* api);
+int bind_ndb_mongodb(ndb_mongodb_api_t* api);
+
+/**
+ * @brief Load the dispatcher API
+ */
+static inline int ndb_mongodb_load_api(ndb_mongodb_api_t *api)
+{
+	bind_ndb_mongodb_f bindndbmongodb;
+
+	bindndbmongodb = (bind_ndb_mongodb_f)find_export("bind_ndb_mongodb", 0, 0);
+	if(bindndbmongodb == 0) {
+		LM_ERR("cannot find bind_ndb_mongodb\n");
+		return -1;
+	}
+	if(bindndbmongodb(api)<0)
+	{
+		LM_ERR("cannot bind ndb mongodb api\n");
+		return -1;
+	}
+	return 0;
+}
+
+#endif
diff --git a/modules/ndb_mongodb/doc/ndb_mongodb_admin.xml b/modules/ndb_mongodb/doc/ndb_mongodb_admin.xml
index 1927197..5df4660 100644
--- a/modules/ndb_mongodb/doc/ndb_mongodb_admin.xml
+++ b/modules/ndb_mongodb/doc/ndb_mongodb_admin.xml
@@ -233,6 +233,30 @@ if(mongodb_find("mgs1", "kamailio", "acc", "{ \"src_user\" : \"111\" }", "mgr1")
 </programlisting>
 	    </example>
 	</section>
+	<section id="ndb_mongodb.f.mongodb_find_one">
+	    <title>
+		<function moreinfo="none">mongodb_find_one(srvname, dbname, cname, command, replyid)</function>
+	    </title>
+	    <para>
+			Similar to mongodb_find(...), but it stops searching after first
+			match, returning the result with one object - faster when expecting
+			to have a single match. Parameters and behaviour are the same
+			as for mongodb_find(...).
+		</para>
+		<para>
+			The function can be used from ANY_ROUTE.
+		</para>
+		<example>
+		<title><function>mongodb_find_one</function> usage</title>
+		<programlisting format="linespecific">
+...
+if(mongodb_find_one("mgs1", "kamailio", "subscriber", "{ \"username\" : \"111\" }", "mgr1")) {
+	xlog("response from mongodb is [[$mongodb(mgr1=>value)]]\n");
+}
+...
+</programlisting>
+	    </example>
+	</section>
 	<section id="ndb_mongodb.f.mongodb_next">
 	<title>
 		<function moreinfo="none">mongodb_next(replyid)</function>
diff --git a/modules/ndb_mongodb/mongodb_client.c b/modules/ndb_mongodb/mongodb_client.c
index 7202e6c..5765a1a 100644
--- a/modules/ndb_mongodb/mongodb_client.c
+++ b/modules/ndb_mongodb/mongodb_client.c
@@ -32,6 +32,7 @@
 #include "../../ut.h"
 
 #include "mongodb_client.h"
+#include "api.h"
 
 static mongodbc_server_t *_mongodbc_srv_list=NULL;
 
@@ -217,6 +218,7 @@ int mongodbc_exec_cmd(str *srv, str *dname, str *cname, str *cmd, str *res, int
 	bson_t reply;
 	const bson_t *cdoc;
 	char c;
+	int nres;
 	int ret;
 
 	if(srv==NULL || cmd==NULL || res==NULL)
@@ -283,10 +285,12 @@ int mongodbc_exec_cmd(str *srv, str *dname, str *cname, str *cmd, str *res, int
 					NULL,
 					0);
 		} else {
+			nres = 0;
+			if(emode==3) nres = 1; /* return one result */
 			rpl->cursor = mongoc_collection_find (rpl->collection,
 					MONGOC_QUERY_NONE,
 					0,
-					0,
+					nres,
 					0,
 					&command,
 					NULL,
@@ -343,6 +347,14 @@ int mongodbc_find(str *srv, str *dname, str *cname, str *cmd, str *res)
 /**
  *
  */
+int mongodbc_find_one(str *srv, str *dname, str *cname, str *cmd, str *res)
+{
+	return mongodbc_exec_cmd(srv, dname, cname, cmd, res, 3);
+}
+
+/**
+ *
+ */
 mongodbc_reply_t *mongodbc_get_reply(str *name)
 {
 	mongodbc_reply_t *rpl;
@@ -478,3 +490,25 @@ int mongodbc_next_reply(str *name)
 	LM_DBG("next cursor result: [[%s]]\n", (rpl->jsonrpl.s)?rpl->jsonrpl.s:"<null>");
 	return 0;
 }
+
+/**
+ *
+ */
+int bind_ndb_mongodb(ndb_mongodb_api_t* api)
+{
+	if (!api) {
+		ERR("Invalid parameter value\n");
+		return -1;
+	}
+
+	memset(api, 0, sizeof(ndb_mongodb_api_t));
+	api->cmd		= mongodbc_exec;
+	api->cmd_simple	= mongodbc_exec_simple;
+	api->find		= mongodbc_find;
+	api->find_one	= mongodbc_find_one;
+	api->next_reply	= mongodbc_next_reply;
+	api->free_reply	= mongodbc_free_reply;
+
+	return 0;
+}
+
diff --git a/modules/ndb_mongodb/mongodb_client.h b/modules/ndb_mongodb/mongodb_client.h
index 1583db9..b0892e9 100644
--- a/modules/ndb_mongodb/mongodb_client.h
+++ b/modules/ndb_mongodb/mongodb_client.h
@@ -35,6 +35,7 @@ int mongodbc_add_server(char *spec);
 int mongodbc_exec_simple(str *srv, str *dname, str *cname, str *cmd, str *res);
 int mongodbc_exec(str *srv, str *dname, str *cname, str *cmd, str *res);
 int mongodbc_find(str *srv, str *dname, str *cname, str *cmd, str *res);
+int mongodbc_find_one(str *srv, str *dname, str *cname, str *cmd, str *res);
 
 typedef struct mongodbc_server {
 	str *sname;
diff --git a/modules/ndb_mongodb/ndb_mongodb_mod.c b/modules/ndb_mongodb/ndb_mongodb_mod.c
index 75bee9f..775ff6f 100644
--- a/modules/ndb_mongodb/ndb_mongodb_mod.c
+++ b/modules/ndb_mongodb/ndb_mongodb_mod.c
@@ -31,6 +31,7 @@
 #include "../../trim.h"
 
 #include "mongodb_client.h"
+#include "api.h"
 
 MODULE_VERSION
 
@@ -39,6 +40,8 @@ MODULE_VERSION
 int mongodb_srv_param(modparam_t type, void *val);
 static int w_mongodb_find(sip_msg_t* msg, char* ssrv, char *sdname, char *scname,
 		char* scmd, char* sres);
+static int w_mongodb_find_one(sip_msg_t* msg, char* ssrv, char *sdname, char *scname,
+		char* scmd, char* sres);
 static int w_mongodb_cmd_simple(sip_msg_t* msg, char* ssrv, char *sdname, char *scname,
 		char* scmd, char* sres);
 static int w_mongodb_cmd(sip_msg_t* msg, char* ssrv, char *sdname, char *scname,
@@ -64,6 +67,8 @@ static pv_export_t mod_pvs[] = {
 static cmd_export_t cmds[]={
 	{"mongodb_find", (cmd_function)w_mongodb_find, 5, fixup_mongodb_cmd,
 		0, ANY_ROUTE},
+	{"mongodb_find_one", (cmd_function)w_mongodb_find_one, 5, fixup_mongodb_cmd,
+		0, ANY_ROUTE},
 	{"mongodb_cmd_simple", (cmd_function)w_mongodb_cmd_simple, 5, fixup_mongodb_cmd,
 		0, ANY_ROUTE},
 	{"mongodb_cmd", (cmd_function)w_mongodb_cmd, 5, fixup_mongodb_cmd,
@@ -72,6 +77,8 @@ static cmd_export_t cmds[]={
 		0, ANY_ROUTE},
 	{"mongodb_next", (cmd_function)w_mongodb_next_reply, 1, fixup_spve_null,
 		0, ANY_ROUTE},
+	{"bind_ndb_mongodb",   (cmd_function)bind_ndb_mongodb,  0,
+		0, 0, 0},
 	{0, 0, 0, 0, 0, 0}
 };
 
@@ -155,12 +162,15 @@ static int w_mongodb_do_cmd(sip_msg_t* msg, char* ssrv, char *sdname, char *scna
 		LM_ERR("no mongodb reply name\n");
 		return -1;
 	}
+	ret = -1;
 	if(ctype==0) {
 		ret = mongodbc_exec_simple(&s[0], &s[1], &s[2], &s[3], &s[4]);
 	} else if(ctype==1) {
 		ret = mongodbc_exec(&s[0], &s[1], &s[2], &s[3], &s[4]);
-	} else {
+	} else if(ctype==2) {
 		ret = mongodbc_find(&s[0], &s[1], &s[2], &s[3], &s[4]);
+	} else if(ctype==3) {
+		ret = mongodbc_find_one(&s[0], &s[1], &s[2], &s[3], &s[4]);
 	}
 	if(ret<0)
 		return -1;
@@ -197,6 +207,15 @@ static int w_mongodb_find(sip_msg_t* msg, char* ssrv, char *sdname, char *scname
 /**
  *
  */
+static int w_mongodb_find_one(sip_msg_t* msg, char* ssrv, char *sdname, char *scname,
+		char* scmd, char* sres)
+{
+	return w_mongodb_do_cmd(msg, ssrv, sdname, scname, scmd, sres, 3);
+}
+
+/**
+ *
+ */
 static int fixup_mongodb_cmd(void** param, int param_no)
 {
 	return fixup_spve_null(param, 1);
diff --git a/modules/ndb_redis/README b/modules/ndb_redis/README
index 03c5cc9..96a3363 100644
--- a/modules/ndb_redis/README
+++ b/modules/ndb_redis/README
@@ -32,6 +32,7 @@ Vicente Hernando
         3. Parameters
 
               3.1. server (str)
+              3.2. init_without_redis (integer)
 
         4. Functions
 
@@ -41,8 +42,9 @@ Vicente Hernando
    List of Examples
 
    1.1. Set server parameter
-   1.2. redis_cmd usage
-   1.3. redis_free usage
+   1.2. Set init_without_redis parameter
+   1.3. redis_cmd usage
+   1.4. redis_free usage
 
 Chapter 1. Admin Guide
 
@@ -57,6 +59,7 @@ Chapter 1. Admin Guide
    3. Parameters
 
         3.1. server (str)
+        3.2. init_without_redis (integer)
 
    4. Functions
 
@@ -91,18 +94,19 @@ Chapter 1. Admin Guide
 3. Parameters
 
    3.1. server (str)
+   3.2. init_without_redis (integer)
 
 3.1. server (str)
 
    Specify the details to connect to REDIS server. It takes a list of
    attribute=value separated by semicolon, the attributes can be name,
-   unix, addr, port and db. Name is a generic identifier to be used with
-   module functions. unix is the path to the unix domain socket provided
-   by redis server. addr and port are the IP address and the port to
-   connect to REDIS server. unix and (addr, port) are mutually exclusive.
-   If both appear in same server settings unix domain socket is
-   configured. db is the DB number to use (defaults to 0 if not
-   specified).
+   unix, addr, port, db and pass. Name is a generic identifier to be used
+   with module functions. unix is the path to the unix domain socket
+   provided by redis server. addr and port are the IP address and the port
+   to connect to REDIS server. pass is the server password. unix and
+   (addr, port) are mutually exclusive. If both appear in same server
+   settings unix domain socket is configured. db is the DB number to use
+   (defaults to 0 if not specified).
 
    You can set this parameter many times, in case you want to connect to
    many REDIS servers, just give different attributes and use the specific
@@ -113,12 +117,25 @@ Chapter 1. Admin Guide
    Example 1.1. Set server parameter
 ...
 modparam("ndb_redis", "server", "name=srvN;addr=127.0.0.1;port=6379;db=1")
-modparam("ndb_redis", "server", "name=srvX;addr=127.0.0.2;port=6379;db=4")
+modparam("ndb_redis", "server", "name=srvX;addr=127.0.0.2;port=6379;db=4;pass=m
+ypassword")
 
 # Unix domain socket
 modparam("ndb_redis", "server", "name=srvY;unix=/tmp/redis.sock;db=3")
 ...
 
+3.2. init_without_redis (integer)
+
+   If set to 1, the module will correctly initialize even if redis is not
+   available at start up.
+
+   Default value is “0”.
+
+   Example 1.2. Set init_without_redis parameter
+...
+modparam("ndb_redis", "init_without_redis", 1)
+...
+
 4. Functions
 
    4.1. redis_cmd(srvname, command, ..., replyid)
@@ -147,7 +164,7 @@ modparam("ndb_redis", "server", "name=srvY;unix=/tmp/redis.sock;db=3")
      * value[n] - returns value of the nth element. value - returns null
        for an array. You need to get each element by index.
 
-   Example 1.2. redis_cmd usage
+   Example 1.3. redis_cmd usage
 ...
 if(redis_cmd("srvN", "INCR cnt", "r")) {
     # success - the incremented value is in $redis(r=>value)
@@ -188,7 +205,7 @@ if(redis_cmd("srvN", "HMGET foo_key field1 field3", "r")) {
    function. When ndb_redis module closes, all pending replies are freed
    automatically.
 
-   Example 1.3. redis_free usage
+   Example 1.4. redis_free usage
 ...
 After a redis command call:
         redis_cmd("srvN", "INCR cnt", "r");
diff --git a/modules/ndb_redis/doc/ndb_redis_admin.xml b/modules/ndb_redis/doc/ndb_redis_admin.xml
index 1f4d6dd..b5e47d9 100644
--- a/modules/ndb_redis/doc/ndb_redis_admin.xml
+++ b/modules/ndb_redis/doc/ndb_redis_admin.xml
@@ -62,14 +62,13 @@
 	<section id="ndb_redis.p.server">
 		<title><varname>server</varname> (str)</title>
 		<para>
-			Specify the details to connect to REDIS server. It takes a list of
-			attribute=value separated by semicolon, the attributes can be
-			name, unix, addr, port and db. Name is a generic identifier to be used
-			with module functions. unix is the path to the unix domain socket provided
-			by redis server. addr and port are the IP address and the port to
-			connect to REDIS server. unix and (addr, port) are mutually exclusive.
-			If both appear in same server settings unix domain socket is configured.
-			db is the DB number to use (defaults to 0 if not specified).
+			Specify the details to connect to REDIS server. It takes a list of attribute=value
+			separated by semicolon, the attributes can be name, unix, addr, port, db and pass. Name
+			is a generic identifier to be used with module functions. unix is the path to the unix
+			domain socket provided by redis server. addr and port are the IP address and the port to
+			connect to REDIS server. pass is the server password. unix and (addr, port) are mutually
+			exclusive.  If both appear in same server settings unix domain socket is configured.  db
+			is the DB number to use (defaults to 0 if not specified).
 		</para>
 		<para>
 			You can set this parameter many times, in case you want to connect to
@@ -86,7 +85,7 @@
 		<programlisting format="linespecific">
 ...
 modparam("ndb_redis", "server", "name=srvN;addr=127.0.0.1;port=6379;db=1")
-modparam("ndb_redis", "server", "name=srvX;addr=127.0.0.2;port=6379;db=4")
+modparam("ndb_redis", "server", "name=srvX;addr=127.0.0.2;port=6379;db=4;pass=mypassword")
 
 # Unix domain socket
 modparam("ndb_redis", "server", "name=srvY;unix=/tmp/redis.sock;db=3")
@@ -94,6 +93,25 @@ modparam("ndb_redis", "server", "name=srvY;unix=/tmp/redis.sock;db=3")
 </programlisting>
 		</example>
 	</section>
+	<section id="ndb_redis.p.init_without_redis">
+		<title><varname>init_without_redis</varname> (integer)</title>
+		<para>
+			If set to 1, the module will correctly initialize even if redis is not available at start up.
+		</para>
+		<para>
+		<emphasis>
+			Default value is <quote>0</quote>.
+		</emphasis>
+		</para>
+		<example>
+			<title>Set <varname>init_without_redis</varname> parameter</title>
+			<programlisting format="linespecific">
+...
+modparam("ndb_redis", "init_without_redis", 1)
+...
+			</programlisting>
+		</example>
+	</section>
 	</section>
 
 	<section>
diff --git a/modules/ndb_redis/ndb_redis_mod.c b/modules/ndb_redis/ndb_redis_mod.c
index a24ada3..c3c71f6 100644
--- a/modules/ndb_redis/ndb_redis_mod.c
+++ b/modules/ndb_redis/ndb_redis_mod.c
@@ -42,6 +42,8 @@ MODULE_VERSION
 /** parameters */
 
 int redis_srv_param(modparam_t type, void *val);
+int init_without_redis = 0;
+
 static int w_redis_cmd3(struct sip_msg* msg, char* ssrv, char* scmd,
 		char* sres);
 static int w_redis_cmd4(struct sip_msg* msg, char* ssrv, char* scmd,
@@ -84,6 +86,7 @@ static cmd_export_t cmds[]={
 
 static param_export_t params[]={
 	{"server",         PARAM_STRING|USE_FUNC_PARAM, (void*)redis_srv_param},
+	{"init_without_redis", INT_PARAM, &init_without_redis},
 	{0, 0, 0}
 };
 
@@ -113,8 +116,8 @@ static int child_init(int rank)
 
 	if(redisc_init()<0)
 	{
-		LM_ERR("failed to initialize redis connections\n");
-		return -1;
+	  LM_ERR("failed to initialize redis connections\n");
+	  return -1;
 	}
 	return 0;
 }
diff --git a/modules/ndb_redis/redis_client.c b/modules/ndb_redis/redis_client.c
index 2108386..02aa7b8 100644
--- a/modules/ndb_redis/redis_client.c
+++ b/modules/ndb_redis/redis_client.c
@@ -41,12 +41,14 @@ static redisc_server_t *_redisc_srv_list=NULL;
 
 static redisc_reply_t *_redisc_rpl_list=NULL;
 
+extern int init_without_redis;
+
 /**
  *
  */
 int redisc_init(void)
 {
-	char *addr, *unix_sock_path = NULL;
+	char *addr, *pass, *unix_sock_path = NULL;
 	unsigned int port, db;
 	redisc_server_t *rsrv=NULL;
 	param_t *pit = NULL;
@@ -66,6 +68,8 @@ int redisc_init(void)
 		addr = "127.0.0.1";
 		port = 6379;
 		db = 0;
+		pass = NULL;
+
 		for (pit = rsrv->attrs; pit; pit=pit->next)
 		{
 			if(pit->name.len==4 && strncmp(pit->name.s, "unix", 4)==0) {
@@ -80,6 +84,9 @@ int redisc_init(void)
 			} else if(pit->name.len==2 && strncmp(pit->name.s, "db", 2)==0) {
 				if(str2int(&pit->body, &db) < 0)
 					db = 0;
+			} else if(pit->name.len==4 && strncmp(pit->name.s, "pass", 4)==0) {
+				pass = pit->body.s;
+				pass[pit->body.len] = '\0';
 			}
 		}
 
@@ -94,6 +101,8 @@ int redisc_init(void)
 			goto err;
 		if (rsrv->ctxRedis->err)
 			goto err2;
+		if ((pass != NULL) && redisc_check_auth(rsrv, pass))
+			goto err2;
 		if (redisCommandNR(rsrv->ctxRedis, "PING"))
 			goto err2;
 		if (redisCommandNR(rsrv->ctxRedis, "SELECT %i", db))
@@ -111,6 +120,12 @@ err2:
 		LM_ERR("error communicating with redis server [%.*s] (%s:%d/%d): %s\n",
 			   rsrv->sname->len, rsrv->sname->s, addr, port, db, rsrv->ctxRedis->errstr);
 	}
+	if (init_without_redis==1)
+	{
+		LM_WARN("failed to initialize redis connections, but initializing module anyway.\n");
+		return 0;
+	}
+
 	return -1;
 err:
 	if (unix_sock_path != NULL) {
@@ -120,6 +135,12 @@ err:
 		LM_ERR("failed to connect to redis server [%.*s] (%s:%d/%d)\n",
 			   rsrv->sname->len, rsrv->sname->s, addr, port, db);
 	}
+	if (init_without_redis==1)
+	{
+		LM_WARN("failed to initialize redis connections, but initializing module anyway.\n");
+		return 0;
+	}
+
 	return -1;
 }
 
@@ -242,7 +263,7 @@ redisc_server_t *redisc_get_server(str *name)
  */
 int redisc_reconnect_server(redisc_server_t *rsrv)
 {
-	char *addr, *unix_sock_path = NULL;
+	char *addr, *pass, *unix_sock_path = NULL;
 	unsigned int port, db;
 	param_t *pit = NULL;
 	struct timeval tv;
@@ -252,6 +273,7 @@ int redisc_reconnect_server(redisc_server_t *rsrv)
 	addr = "127.0.0.1";
 	port = 6379;
 	db = 0;
+	pass = NULL;
 	for (pit = rsrv->attrs; pit; pit=pit->next)
 	{
 		if(pit->name.len==4 && strncmp(pit->name.s, "unix", 4)==0) {
@@ -266,6 +288,9 @@ int redisc_reconnect_server(redisc_server_t *rsrv)
 		} else if(pit->name.len==2 && strncmp(pit->name.s, "db", 2)==0) {
 			if(str2int(&pit->body, &db) < 0)
 				db = 0;
+		} else if(pit->name.len==4 && strncmp(pit->name.s, "pass", 4)==0) {
+			pass = pit->body.s;
+			pass[pit->body.len] = '\0';
 		}
 	}
 	if(rsrv->ctxRedis!=NULL) {
@@ -282,6 +307,8 @@ int redisc_reconnect_server(redisc_server_t *rsrv)
 		goto err;
 	if (rsrv->ctxRedis->err)
 		goto err2;
+	if ((pass != NULL) && redisc_check_auth(rsrv, pass))
+		goto err2;
 	if (redisCommandNR(rsrv->ctxRedis, "PING"))
 		goto err2;
 	if (redisCommandNR(rsrv->ctxRedis, "SELECT %i", db))
@@ -515,3 +542,17 @@ int redisc_free_reply(str *name)
 	/* reply entry not found. */
 	return -1;
 }
+
+int redisc_check_auth(redisc_server_t *rsrv, char *pass)
+{
+	redisReply *reply;
+	int retval = 0;
+
+	reply = redisCommand(rsrv->ctxRedis, "AUTH %s", pass);
+	if (reply->type == REDIS_REPLY_ERROR) {
+		LM_ERR("Redis authentication error\n");
+		retval = -1;
+	}
+	freeReplyObject(reply);
+	return retval;
+}
diff --git a/modules/ndb_redis/redis_client.h b/modules/ndb_redis/redis_client.h
index 73a3f1d..a86acaf 100644
--- a/modules/ndb_redis/redis_client.h
+++ b/modules/ndb_redis/redis_client.h
@@ -67,4 +67,5 @@ int redisc_exec(str *srv, str *res, str *cmd, ...);
 void* redisc_exec_argv(redisc_server_t *rsrv, int argc, const char **argv, const size_t *argvlen);
 redisc_reply_t *redisc_get_reply(str *name);
 int redisc_free_reply(str *name);
+int redisc_check_auth(redisc_server_t *rsrv, char *pass);
 #endif
diff --git a/modules/outbound/Makefile b/modules/outbound/Makefile
index a4c7a73..df43360 100644
--- a/modules/outbound/Makefile
+++ b/modules/outbound/Makefile
@@ -1,5 +1,3 @@
-# $Id$
-#
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
 
diff --git a/modules/p_usrloc/Makefile b/modules/p_usrloc/Makefile
index f2f4042..e4cc5a3 100644
--- a/modules/p_usrloc/Makefile
+++ b/modules/p_usrloc/Makefile
@@ -1,6 +1,5 @@
-# $Id: Makefile,v 1.1.1.1 2005/06/13 16:47:47 bogdan_iancu Exp $
 #
-# sp-ul_db module Makefile
+# p_userloc module Makefile
 #
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
diff --git a/modules/p_usrloc/dlist.c b/modules/p_usrloc/dlist.c
index 64989a0..9a6f806 100644
--- a/modules/p_usrloc/dlist.c
+++ b/modules/p_usrloc/dlist.c
@@ -1,6 +1,4 @@
 /*
- * $Id: dlist.c 5160 2008-11-03 17:51:22Z henningw $
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,11 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * ========
- * 2006-11-28 added get_number_of_users() (Jeffrey Magder - SOMA Networks)
- * 2007-09-12 added partitioning support for fetching all ul contacts
- *            (bogdan)
  */
 
 /*! \file
diff --git a/modules/p_usrloc/dlist.h b/modules/p_usrloc/dlist.h
index de22a04..2114ac6 100644
--- a/modules/p_usrloc/dlist.h
+++ b/modules/p_usrloc/dlist.h
@@ -1,6 +1,4 @@
 /*
- * $Id: dlist.h 5160 2008-11-03 17:51:22Z henningw $
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,11 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * ========
- * 2006-11-28 Added get_number_of_users() (Jeffrey Magder - SOMA Networks)
- * 2007-09-12 added partitioning support for fetching all ul contacts
- *            (bogdan)
  */
 
 /*! \file
diff --git a/modules/p_usrloc/hslot.c b/modules/p_usrloc/hslot.c
index 388b37f..592ec7e 100644
--- a/modules/p_usrloc/hslot.c
+++ b/modules/p_usrloc/hslot.c
@@ -1,6 +1,4 @@
 /*
- * $Id: hslot.c 5241 2008-11-21 12:52:25Z henningw $ 
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/p_usrloc/hslot.h b/modules/p_usrloc/hslot.h
index 04b3007..ec1ddb0 100644
--- a/modules/p_usrloc/hslot.h
+++ b/modules/p_usrloc/hslot.h
@@ -1,6 +1,4 @@
 /*
- * $Id: hslot.h 5241 2008-11-21 12:52:25Z henningw $ 
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/p_usrloc/p_usrloc_mod.c b/modules/p_usrloc/p_usrloc_mod.c
index f050c76..77bfb24 100644
--- a/modules/p_usrloc/p_usrloc_mod.c
+++ b/modules/p_usrloc/p_usrloc_mod.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Usrloc module interface
  *
  * Copyright (C) 2001-2003 FhG Fokus
@@ -21,17 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * ---------
- * 2003-01-27 timer activity printing #ifdef-ed to EXTRA_DEBUG (jiri)
- * 2003-03-11 New module interface (janakj)
- * 2003-03-12 added replication and state columns (nils)
- * 2003-03-16 flags export parameter added (janakj)
- * 2003-04-05: default_uri #define used (jiri)
- * 2003-04-21 failed fifo init stops init process (jiri)
- * 2004-03-17 generic callbacks added (bogdan)
- * 2004-06-07 updated to the new DB api (andrei)
- * 2011-01-03 extended module definition for partitioned userlocking (marius)
  */
 
 /*! \file
diff --git a/modules/p_usrloc/p_usrloc_mod.h b/modules/p_usrloc/p_usrloc_mod.h
index 8ae6f59..cce5bfd 100644
--- a/modules/p_usrloc/p_usrloc_mod.h
+++ b/modules/p_usrloc/p_usrloc_mod.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * User location module interface
  *
  * Copyright (C) 2001-2003 FhG Fokus
@@ -21,8 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * ---------
  */
 
 /*! \file
diff --git a/modules/p_usrloc/ucontact.c b/modules/p_usrloc/ucontact.c
index a29fccc..cdce6dd 100644
--- a/modules/p_usrloc/ucontact.c
+++ b/modules/p_usrloc/ucontact.c
@@ -1,6 +1,4 @@
 /*
- * $Id: ucontact.c 5272 2008-11-27 12:32:26Z henningw $ 
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,11 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * ---------
- * 2003-03-12 added replication mark and three zombie states (nils)
- * 2004-03-17 generic callbacks added (bogdan)
- * 2004-06-07 updated to the new DB api (andrei)
  */
 
 /*! \file
diff --git a/modules/p_usrloc/ucontact.h b/modules/p_usrloc/ucontact.h
index 587395f..07216f4 100644
--- a/modules/p_usrloc/ucontact.h
+++ b/modules/p_usrloc/ucontact.h
@@ -1,6 +1,4 @@
 /*
- * $Id: ucontact.h 5272 2008-11-27 12:32:26Z henningw $ 
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,11 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * ---------
- * 2003-03-12 added replication mark and three zombie states (nils)
- * 2005-07-11 added FL_NAT_SIPPING for nat pinging with SIP method
- *             instead of UDP package (bogdan)
  */
 
 /*! \file
diff --git a/modules/p_usrloc/udomain.c b/modules/p_usrloc/udomain.c
index c537955..8cb93e9 100644
--- a/modules/p_usrloc/udomain.c
+++ b/modules/p_usrloc/udomain.c
@@ -1,6 +1,4 @@
 /*
- * $Id: udomain.c 5272 2008-11-27 12:32:26Z henningw $ 
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,13 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * ---------
- * 2003-03-11 changed to the new locking scheme: locking.h (andrei)
- * 2003-03-12 added replication mark and zombie state (nils)
- * 2004-06-07 updated to the new DB api (andrei)
- * 2004-08-23  hash function changed to process characters as unsigned
- *             -> no negative results occur (jku)
  */
 
 /*! \file
diff --git a/modules/p_usrloc/udomain.h b/modules/p_usrloc/udomain.h
index e1f7998..b377b01 100644
--- a/modules/p_usrloc/udomain.h
+++ b/modules/p_usrloc/udomain.h
@@ -1,6 +1,4 @@
 /*
- * $Id: udomain.h 5272 2008-11-27 12:32:26Z henningw $ 
-
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,12 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/*
- * History:
- * --------
- *  2003-03-11  changed to new locking scheme: locking.h (andrei)
- */
-
 
 /*! \file
  *  \brief USRLOC - Usrloc domain structure
diff --git a/modules/p_usrloc/ul_callback.c b/modules/p_usrloc/ul_callback.c
index 50673b8..7d3ccf3 100644
--- a/modules/p_usrloc/ul_callback.c
+++ b/modules/p_usrloc/ul_callback.c
@@ -1,6 +1,4 @@
 /*
- * $Id: ul_callback.c 4518 2008-07-28 15:39:28Z henningw $
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,9 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2004-03-16  created (bogdan)
  */
 
 /*! \file
diff --git a/modules/p_usrloc/ul_mi.c b/modules/p_usrloc/ul_mi.c
index a96a04b..65a0c72 100644
--- a/modules/p_usrloc/ul_mi.c
+++ b/modules/p_usrloc/ul_mi.c
@@ -1,6 +1,4 @@
 /*
- * $Id: ul_mi.c 5194 2008-11-13 10:38:11Z henningw $
- *
  * Copyright (C) 2006 Voice Sistem SRL
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,10 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * ---------
- *
- * 2006-12-01  created (bogdan)
  */
 
 /*! \file
diff --git a/modules/p_usrloc/ul_mi.h b/modules/p_usrloc/ul_mi.h
index 98fd2b0..ca4ce01 100644
--- a/modules/p_usrloc/ul_mi.h
+++ b/modules/p_usrloc/ul_mi.h
@@ -1,6 +1,4 @@
 /*
- * $Id: ul_mi.h 5194 2008-11-13 10:38:11Z henningw $
- *
  * Copyright (C) 2006 Voice Sistem SRL
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/p_usrloc/urecord.c b/modules/p_usrloc/urecord.c
index b2879d6..16414f0 100644
--- a/modules/p_usrloc/urecord.c
+++ b/modules/p_usrloc/urecord.c
@@ -1,6 +1,4 @@
 /*
- * $Id: urecord.c 5241 2008-11-21 12:52:25Z henningw $ 
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,11 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * ---------
- * 2003-03-12 added replication mark and zombie state support (nils)
- * 2004-03-17 generic callbacks added (bogdan)
- * 2004-06-07 updated to the new DB api (andrei)
  */
 
 /*! \file
diff --git a/modules/p_usrloc/urecord.h b/modules/p_usrloc/urecord.h
index 516fad0..3d851f9 100644
--- a/modules/p_usrloc/urecord.h
+++ b/modules/p_usrloc/urecord.h
@@ -1,6 +1,4 @@
 /*
- * $Id: urecord.h 5241 2008-11-21 12:52:25Z henningw $ 
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/p_usrloc/usrloc.c b/modules/p_usrloc/usrloc.c
index 6017e73..c4305cd 100644
--- a/modules/p_usrloc/usrloc.c
+++ b/modules/p_usrloc/usrloc.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,11 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * ========
- *
- * 2006-11-28 Added a new function to the usrloc_api, to retrieve the number
- *            of registered users.  (Jeffrey Magder - SOMA Networks)
  */
 
 /*! \file
diff --git a/modules/p_usrloc/utime.c b/modules/p_usrloc/utime.c
index ddcc611..d3069c9 100644
--- a/modules/p_usrloc/utime.c
+++ b/modules/p_usrloc/utime.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Usrloc time related functions
  *
  * Copyright (C) 2001-2003 FhG Fokus
diff --git a/modules/p_usrloc/utime.h b/modules/p_usrloc/utime.h
index 7e061f4..128fca2 100644
--- a/modules/p_usrloc/utime.h
+++ b/modules/p_usrloc/utime.h
@@ -1,6 +1,4 @@
 /*
- * $Id: utime.h 4518 2008-07-28 15:39:28Z henningw $
- *
  * Usrloc time related functions
  *
  * Copyright (C) 2001-2003 FhG Fokus
diff --git a/modules/path/Makefile b/modules/path/Makefile
index 26d784f..1cc4116 100644
--- a/modules/path/Makefile
+++ b/modules/path/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # path module makefile
 #
diff --git a/modules/pdt/Makefile b/modules/pdt/Makefile
index 7e8a184..21996ab 100644
--- a/modules/pdt/Makefile
+++ b/modules/pdt/Makefile
@@ -1,6 +1,5 @@
-# $Id$
 #
-# print example module makefile
+# pdt example module makefile
 #
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
diff --git a/modules/permissions/Makefile b/modules/permissions/Makefile
index ad81664..a6cdf5b 100644
--- a/modules/permissions/Makefile
+++ b/modules/permissions/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # PERMISSIONS module makefile
 # 
diff --git a/modules/pike/Makefile b/modules/pike/Makefile
index ec9f085..f417449 100644
--- a/modules/pike/Makefile
+++ b/modules/pike/Makefile
@@ -1,6 +1,5 @@
-# $Id$
 #
-# example module makefile
+# pike module makefile
 #
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
diff --git a/modules/pike/ip_tree.c b/modules/pike/ip_tree.c
index b0e8a57..0994332 100644
--- a/modules/pike/ip_tree.c
+++ b/modules/pike/ip_tree.c
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,11 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2004-11-05: adaptiv init lock (bogdan)
- *  2008-04-17  the leaf nodes memorize (via flags) if they are in RED state
- *               (detected) or not -> better logging and MI (bogdan)
  */
 
 
diff --git a/modules/pike/ip_tree.h b/modules/pike/ip_tree.h
index a082707..7ccc1b8 100644
--- a/modules/pike/ip_tree.h
+++ b/modules/pike/ip_tree.h
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,14 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2004-07-28  s/lock_set_t/gen_lock_set_t/ because of a type conflict
- *              on darwin (andrei)
- *  2004-11-05  adaptiv init lock (bogdan)
- *  2005-06-02  flags added to ip_node structure (bogdan)
- *  2008-04-17  the leaf nodes memorize (via flags) if they are in RED state
- *               (detected) or not -> better logging and MI (bogdan)
  */
 
 #ifndef _IP_TREE_H
diff --git a/modules/pike/pike.c b/modules/pike/pike.c
index 036614a..6aee8fd 100644
--- a/modules/pike/pike.c
+++ b/modules/pike/pike.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * PIKE module
  *
  * Copyright (C) 2001-2003 FhG Fokus
@@ -21,14 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2003-03-11  updated to the new module exports interface (andrei)
- *  2003-03-11  converted to the new locking interface: locking.h --
- *               major changes (andrei)
- *  2003-03-16  flags export parameter added (janakj)
- *  2008-04-17  new parameter to control the module's log regarding the
- *               blocking/unblocking of IPs (bogdan)
  */
 
 
diff --git a/modules/pike/pike_funcs.c b/modules/pike/pike_funcs.c
index 0e1a9e1..a0b964f 100644
--- a/modules/pike/pike_funcs.c
+++ b/modules/pike/pike_funcs.c
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,16 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2003-03-11  converted to the new locking interface: locking.h --
- *               major changes (andrei)
- *  2005-05-02  flags field added to node stucture -better sync between timer
- *              and worker processes; some races eliminated (bogdan)
- *  2008-04-17  new parameter to control the module's log regarding the
- *               blocking/unblocking of IPs (bogdan)
- *  2008-04-17  the leaf nodes memorize (via flags) if they are in RED state
- *               (detected) or not -> better logging and MI (bogdan)
  */
 
 
diff --git a/modules/pike/pike_funcs.h b/modules/pike/pike_funcs.h
index df21c8e..483d704 100644
--- a/modules/pike/pike_funcs.h
+++ b/modules/pike/pike_funcs.h
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/pike/pike_mi.c b/modules/pike/pike_mi.c
index adce231..b169acf 100644
--- a/modules/pike/pike_mi.c
+++ b/modules/pike/pike_mi.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Header file for PIKE MI functions
  *
  * Copyright (C) 2006 Voice Sistem SRL
@@ -21,9 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2006-12-05  created (bogdan)
  */
 
 #include "ip_tree.h"
diff --git a/modules/pike/pike_mi.h b/modules/pike/pike_mi.h
index cca17c5..23e8116 100644
--- a/modules/pike/pike_mi.h
+++ b/modules/pike/pike_mi.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Header file for PIKE MI functions
  *
  * Copyright (C) 2006 Voice Sistem SRL
@@ -21,9 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2006-12-05  created (bogdan)
  */
 
 
diff --git a/modules/pike/pike_rpc.c b/modules/pike/pike_rpc.c
index b93dcc1..ee29ef4 100644
--- a/modules/pike/pike_rpc.c
+++ b/modules/pike/pike_rpc.c
@@ -1,3 +1,24 @@
+/*
+ * PIKE module
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
 #include "ip_tree.h"
 #include "../../rpc_lookup.h"
 /*??? #include "rpc.h" */
diff --git a/modules/pike/pike_rpc.h b/modules/pike/pike_rpc.h
index c70e9ce..51ac2f8 100644
--- a/modules/pike/pike_rpc.h
+++ b/modules/pike/pike_rpc.h
@@ -1,3 +1,23 @@
+/*
+ * PIKE module
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
 #ifndef __PIKE_RPC_H
 #define __PIKE_RPC_H
 
diff --git a/modules/pike/pike_top.c b/modules/pike/pike_top.c
index 8399602..97af823 100644
--- a/modules/pike/pike_top.c
+++ b/modules/pike/pike_top.c
@@ -1,3 +1,23 @@
+/*
+ * PIKE module
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
 #include "pike_top.h"
 
 #include "../../dprint.h"
diff --git a/modules/pike/pike_top.h b/modules/pike/pike_top.h
index c18c152..0cdec86 100644
--- a/modules/pike/pike_top.h
+++ b/modules/pike/pike_top.h
@@ -1,3 +1,23 @@
+/*
+ * PIKE module
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
 #ifndef __PIKE_TOP_H
 #define __PIKE_TOP_H
 
diff --git a/modules/pike/timer.c b/modules/pike/timer.c
index ec0eff1..23f554c 100644
--- a/modules/pike/timer.c
+++ b/modules/pike/timer.c
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,10 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2005-05-02  flags field added to node stucture -better sync between timer
- *              and worker processes; some races eliminated (bogdan)
  */
 
 
diff --git a/modules/pike/timer.h b/modules/pike/timer.h
index b57acde..bc3bfdb 100644
--- a/modules/pike/timer.h
+++ b/modules/pike/timer.h
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,8 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
  *
  */
 
diff --git a/modules/pipelimit/Makefile b/modules/pipelimit/Makefile
index 4742afa..4095fa3 100644
--- a/modules/pipelimit/Makefile
+++ b/modules/pipelimit/Makefile
@@ -1,5 +1,5 @@
 #
-# ratelimit module makefile
+# pipelimit module makefile
 #
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
diff --git a/modules/pipelimit/README b/modules/pipelimit/README
index 9f4caf1..52d844c 100644
--- a/modules/pipelimit/README
+++ b/modules/pipelimit/README
@@ -150,6 +150,7 @@ Chapter 1. Admin Guide
 
    The following modules must be loaded before this module:
      * database connection module.
+     * sl: Stateless Request Handling.
 
 2.2. External Libraries or Applications
 
diff --git a/modules/pipelimit/doc/pipelimit_admin.xml b/modules/pipelimit/doc/pipelimit_admin.xml
index 0983f60..bf23c1b 100644
--- a/modules/pipelimit/doc/pipelimit_admin.xml
+++ b/modules/pipelimit/doc/pipelimit_admin.xml
@@ -45,6 +45,11 @@
 				<emphasis>database connection module</emphasis>.
 			</para>
 			</listitem>
+			<listitem>
+			<para>
+				<emphasis>sl: Stateless Request Handling</emphasis>.
+			</para>
+			</listitem>
 			</itemizedlist>
 		</para>
 	</section>
diff --git a/modules/pipelimit/pipelimit.c b/modules/pipelimit/pipelimit.c
index 882c205..5ed5c13 100644
--- a/modules/pipelimit/pipelimit.c
+++ b/modules/pipelimit/pipelimit.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * pipelimit module
  *
  * Copyright (C) 2010 Daniel-Constantin Mierla (asipto.com)
@@ -23,11 +21,14 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * ---------
+ */
+ 
+/*! \file
+ * \ingroup pipelimit
+ * \brief pipelimit :: pl_db
  *
- * 2008-01-10 ported from SER project (osas)
- * 2008-01-16 ported enhancements from openims project (osas) 
+ */
+/*! \defgroup pipelimit Pipelimit - rate limiting using BSD pipe model
  */
 
 #include <stdio.h>
@@ -222,9 +223,15 @@ static int get_cpuload(double * load)
 	FILE * f = fopen("/proc/stat", "r");
 	double vload;
 	int ncpu;
+	static int errormsg = 0;
 
 	if (! f) {
-		LM_ERR("could not open /proc/stat\n");
+		/* Only write this error message five times. Otherwise you will annoy
+		   BSD-ish system administrators. */
+		if (errormsg < 5) {
+			LM_ERR("could not open /proc/stat\n");
+			errormsg++;
+		}
 		return -1;
 	}
 	if (fscanf(f, "cpu  %lld%lld%lld%lld%lld%lld%lld%lld",
diff --git a/modules/pipelimit/pl_db.c b/modules/pipelimit/pl_db.c
index 7292450..08dd2e0 100644
--- a/modules/pipelimit/pl_db.c
+++ b/modules/pipelimit/pl_db.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * pipelimit module
  *
  * Copyright (C) 2009 Daniel-Constantin Mierla (asipto.com)
diff --git a/modules/pipelimit/pl_db.h b/modules/pipelimit/pl_db.h
index 823f3be..8b6fe12 100644
--- a/modules/pipelimit/pl_db.h
+++ b/modules/pipelimit/pl_db.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * pipelimit module
  *
  * Copyright (C) 2009 Daniel-Constantin Mierla (asipto.com)
@@ -21,6 +19,11 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
+ 
+/*! \file
+ * \ingroup pipelimit
+ * \brief pipelimit :: pl_db
+ */
 
 #ifndef _RL_DB_H_
 #define _RL_DB_H_
diff --git a/modules/pipelimit/pl_ht.c b/modules/pipelimit/pl_ht.c
index 6e48bb4..a79ccce 100644
--- a/modules/pipelimit/pl_ht.c
+++ b/modules/pipelimit/pl_ht.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * pipelimit module
  *
  * Copyright (C) 2006 Hendrik Scholz <hscholz at raisdorf.net>
diff --git a/modules/pipelimit/pl_ht.h b/modules/pipelimit/pl_ht.h
index 38c7a43..ecdefaf 100644
--- a/modules/pipelimit/pl_ht.h
+++ b/modules/pipelimit/pl_ht.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * pipelimit module
  *
  * Copyright (C) 2006 Hendrik Scholz <hscholz at raisdorf.net>
@@ -23,6 +21,11 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
+ 
+/*! \file
+ * \ingroup pipelimit
+ * \brief pipelimit :: pl_ht
+ */
 
 #ifndef _RL_HT_H_
 #define _RL_HT_H_
diff --git a/modules/prefix_route/Makefile b/modules/prefix_route/Makefile
index 7facf65..ba083da 100644
--- a/modules/prefix_route/Makefile
+++ b/modules/prefix_route/Makefile
@@ -1,3 +1,5 @@
+# prefix_route
+#
 include ../../Makefile.defs
 
 auto_gen=
diff --git a/modules/prefix_route/pr.h b/modules/prefix_route/pr.h
index cd81250..a7c4d0a 100644
--- a/modules/prefix_route/pr.h
+++ b/modules/prefix_route/pr.h
@@ -4,19 +4,14 @@
  * Copyright (C) 2007 Alfred E. Heggestad
  * Copyright (C) 2008 Telio Telecom AS
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -25,6 +20,10 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
+/*! \file
+ * \brief Prefix Route Module - Internal module interface
+ * \ingroup prefix_route
+ */
 
 
 extern rpc_export_t pr_rpc[];
diff --git a/modules/prefix_route/pr_rpc.c b/modules/prefix_route/pr_rpc.c
index 5546bec..caf4a8e 100644
--- a/modules/prefix_route/pr_rpc.c
+++ b/modules/prefix_route/pr_rpc.c
@@ -4,19 +4,14 @@
  * Copyright (C) 2007 Alfred E. Heggestad
  * Copyright (C) 2008 Telio Telecom AS
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -25,6 +20,10 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
+/*! \file
+ * \brief Prefix Route Module - RPC Commands
+ * \ingroup prefix_route
+ */
 
 #include <stdio.h>
 #include <stdlib.h>
diff --git a/modules/prefix_route/prefix_route.c b/modules/prefix_route/prefix_route.c
index 45c2438..c60ce8b 100644
--- a/modules/prefix_route/prefix_route.c
+++ b/modules/prefix_route/prefix_route.c
@@ -4,19 +4,14 @@
  * Copyright (C) 2007 Alfred E. Heggestad
  * Copyright (C) 2008 Telio Telecom AS
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -26,6 +21,15 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
+/*! \file
+ * \brief Prefix Route Module - module interface
+ * \ingroup prefix_route
+ */
+
+/*! \defgroup prefix_route
+ * The prefix_route module does routing based on a set of prefixes from the database.
+ */
+
 
 #include <stdio.h>
 #include <stdlib.h>
diff --git a/modules/prefix_route/tree.c b/modules/prefix_route/tree.c
index c65e044..bbca7e0 100644
--- a/modules/prefix_route/tree.c
+++ b/modules/prefix_route/tree.c
@@ -4,19 +4,14 @@
  * Copyright (C) 2007 Alfred E. Heggestad
  * Copyright (C) 2008 Telio Telecom AS
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -25,7 +20,10 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-
+/*! \file
+ * \brief Prefix Route Module - tree search implementation
+ * \ingroup prefix_route
+ */
 
 #include <stdio.h>
 #include <string.h>
diff --git a/modules/prefix_route/tree.h b/modules/prefix_route/tree.h
index 1221650..674f49c 100644
--- a/modules/prefix_route/tree.h
+++ b/modules/prefix_route/tree.h
@@ -4,19 +4,14 @@
  * Copyright (C) 2007 Alfred E. Heggestad
  * Copyright (C) 2008 Telio Telecom AS
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -25,6 +20,10 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
+/*! \file
+ * \brief Prefix Route Module - tree search interface
+ * \ingroup prefix_route
+ */
 
 
 struct tree_item;
diff --git a/modules/presence/README b/modules/presence/README
index 6395628..d2be1dc 100644
--- a/modules/presence/README
+++ b/modules/presence/README
@@ -45,21 +45,26 @@ Juha Heinanen
               3.10. to_tag_pref (str)
               3.11. expires_offset (int)
               3.12. max_expires (int)
-              3.13. server_address (str)
-              3.14. subs_db_mode (int)
-              3.15. publ_cache (int)
-              3.16. subs_htable_size (int)
-              3.17. pres_htable_size (int)
-              3.18. send_fast_notify (int)
-              3.19. enable_sphere_check (int)
-              3.20. timeout_rm_subs (int)
-              3.21. fetch_rows (integer)
-              3.22. db_table_lock_type (integer)
-              3.23. local_log_level (int)
+              3.13. min_expires (int)
+              3.14. min_expires_action (int)
+              3.15. server_address (str)
+              3.16. subs_db_mode (int)
+              3.17. publ_cache (int)
+              3.18. subs_htable_size (int)
+              3.19. pres_htable_size (int)
+              3.20. send_fast_notify (int)
+              3.21. enable_sphere_check (int)
+              3.22. timeout_rm_subs (int)
+              3.23. fetch_rows (integer)
+              3.24. db_table_lock_type (integer)
+              3.25. local_log_level (int)
+              3.26. subs_remove_match (int)
+              3.27. xavp_cfg (str)
+              3.28. retrieve_order (int)
 
         4. Functions
 
-              4.1. handle_publish(char* sender_uri)
+              4.1. handle_publish([sender_uri])
               4.2. handle_subscribe([watcher_uri])
               4.3. pres_auth_status(watcher_uri, presentity_uri)
               4.4. pres_refresh_watchers(uri, event, type[, file_uri,
@@ -112,22 +117,27 @@ Juha Heinanen
    1.10. Set to_tag_pref parameter
    1.11. Set expires_offset parameter
    1.12. Set max_expires parameter
-   1.13. Set server_address parameter
-   1.14. Set subs_db_mode parameter
-   1.15. Set publ_cache parameter
-   1.16. Set subs_htable_size parameter
-   1.17. Set pres_htable_size parameter
-   1.18. Set send_fast_notify parameter
-   1.19. Set enable_sphere_check parameter
-   1.20. Set timeout_rm_subs parameter
-   1.21. Set fetch_rows parameter
-   1.22. Set db_table_lock_type parameter
-   1.23. Set local_log_level parameter
-   1.24. handle_publish usage
-   1.25. handle_subscribe usage
-   1.26. pres_auth_status usage
-   1.27. pres_refresh_watchers usage
-   1.28. pres_update_watchers usage
+   1.13. Set min_expires parameter
+   1.14. Set min_expires parameter
+   1.15. Set server_address parameter
+   1.16. Set subs_db_mode parameter
+   1.17. Set publ_cache parameter
+   1.18. Set subs_htable_size parameter
+   1.19. Set pres_htable_size parameter
+   1.20. Set send_fast_notify parameter
+   1.21. Set enable_sphere_check parameter
+   1.22. Set timeout_rm_subs parameter
+   1.23. Set fetch_rows parameter
+   1.24. Set db_table_lock_type parameter
+   1.25. Set local_log_level parameter
+   1.26. Set subs_remove_match parameter
+   1.27. Set xavp_cfg parameter
+   1.28. Set retrieve_order parameter
+   1.29. handle_publish usage
+   1.30. handle_subscribe usage
+   1.31. pres_auth_status usage
+   1.32. pres_refresh_watchers usage
+   1.33. pres_update_watchers usage
    2.1. presence_api_t structure
 
 Chapter 1. Admin Guide
@@ -154,21 +164,26 @@ Chapter 1. Admin Guide
         3.10. to_tag_pref (str)
         3.11. expires_offset (int)
         3.12. max_expires (int)
-        3.13. server_address (str)
-        3.14. subs_db_mode (int)
-        3.15. publ_cache (int)
-        3.16. subs_htable_size (int)
-        3.17. pres_htable_size (int)
-        3.18. send_fast_notify (int)
-        3.19. enable_sphere_check (int)
-        3.20. timeout_rm_subs (int)
-        3.21. fetch_rows (integer)
-        3.22. db_table_lock_type (integer)
-        3.23. local_log_level (int)
+        3.13. min_expires (int)
+        3.14. min_expires_action (int)
+        3.15. server_address (str)
+        3.16. subs_db_mode (int)
+        3.17. publ_cache (int)
+        3.18. subs_htable_size (int)
+        3.19. pres_htable_size (int)
+        3.20. send_fast_notify (int)
+        3.21. enable_sphere_check (int)
+        3.22. timeout_rm_subs (int)
+        3.23. fetch_rows (integer)
+        3.24. db_table_lock_type (integer)
+        3.25. local_log_level (int)
+        3.26. subs_remove_match (int)
+        3.27. xavp_cfg (str)
+        3.28. retrieve_order (int)
 
    4. Functions
 
-        4.1. handle_publish(char* sender_uri)
+        4.1. handle_publish([sender_uri])
         4.2. handle_subscribe([watcher_uri])
         4.3. pres_auth_status(watcher_uri, presentity_uri)
         4.4. pres_refresh_watchers(uri, event, type[, file_uri, filename])
@@ -242,17 +257,22 @@ Chapter 1. Admin Guide
    3.10. to_tag_pref (str)
    3.11. expires_offset (int)
    3.12. max_expires (int)
-   3.13. server_address (str)
-   3.14. subs_db_mode (int)
-   3.15. publ_cache (int)
-   3.16. subs_htable_size (int)
-   3.17. pres_htable_size (int)
-   3.18. send_fast_notify (int)
-   3.19. enable_sphere_check (int)
-   3.20. timeout_rm_subs (int)
-   3.21. fetch_rows (integer)
-   3.22. db_table_lock_type (integer)
-   3.23. local_log_level (int)
+   3.13. min_expires (int)
+   3.14. min_expires_action (int)
+   3.15. server_address (str)
+   3.16. subs_db_mode (int)
+   3.17. publ_cache (int)
+   3.18. subs_htable_size (int)
+   3.19. pres_htable_size (int)
+   3.20. send_fast_notify (int)
+   3.21. enable_sphere_check (int)
+   3.22. timeout_rm_subs (int)
+   3.23. fetch_rows (integer)
+   3.24. db_table_lock_type (integer)
+   3.25. local_log_level (int)
+   3.26. subs_remove_match (int)
+   3.27. xavp_cfg (str)
+   3.28. retrieve_order (int)
 
 3.1. db_url(str)
 
@@ -410,8 +430,8 @@ modparam("presence", "expires_offset", 10)
 
 3.12. max_expires (int)
 
-   The the maximum admissible expires value for PUBLISH/SUBSCRIBE message
-   (in seconds).
+   The maximum admissible expires value for PUBLISH/SUBSCRIBE message (in
+   seconds).
 
    Default value is "3600".
 
@@ -420,18 +440,49 @@ modparam("presence", "expires_offset", 10)
 modparam("presence", "max_expires", 3600)
 ...
 
-3.13. server_address (str)
+3.13. min_expires (int)
+
+   The minimum admissible expires value for PUBLISH/SUBSCRIBE message (in
+   seconds).
+
+   If > 0 then min_expires_action parameter determines the response.
+
+   Default value is "0".
+
+   Example 1.13. Set min_expires parameter
+            ...
+            modparam("presence", "min_expires", 1800)
+            ...
+
+3.14. min_expires_action (int)
+
+   The action to take when UA sends a expires value less then min_expires.
+
+   Possible Values
+     * 1 : RFC Compliant, returns "423 Interval Too Brief"
+     * 2 : forces the min_expires value in the subscription
+
+   If > 0 then min_expires_action parameter determines the response.
+
+   Default value is "1".
+
+   Example 1.14. Set min_expires parameter
+            ...
+            modparam("presence", "min_expires", 1800)
+            ...
+
+3.15. server_address (str)
 
    The presence server address which will become the value of Contact
    header filed for 200 OK replies to SUBSCRIBE and PUBLISH and in NOTIFY
    messages.
 
-   Example 1.13. Set server_address parameter
+   Example 1.15. Set server_address parameter
 ...
 modparam("presence", "server_address", "sip:10.10.10.10:5060")
 ...
 
-3.14. subs_db_mode (int)
+3.16. subs_db_mode (int)
 
    The presence module can utilize database for persistent subscription
    storage. If you use database, your subscriptions will survive machine
@@ -465,12 +516,12 @@ modparam("presence", "server_address", "sip:10.10.10.10:5060")
 
    Default value is 2 (Write-Back scheme).
 
-   Example 1.14. Set subs_db_mode parameter
+   Example 1.16. Set subs_db_mode parameter
 ...
 modparam("presence", "subs_db_mode", 1)
 ...
 
-3.15. publ_cache (int)
+3.17. publ_cache (int)
 
    To improve performance, the presence module holds by default a publish
    cache that says if a certain publication exists in database. This is
@@ -486,12 +537,12 @@ modparam("presence", "subs_db_mode", 1)
 
    Default value is "1".
 
-   Example 1.15. Set publ_cache parameter
+   Example 1.17. Set publ_cache parameter
 ...
 modparam("presence", "publ_cache", 0)
 ...
 
-3.16. subs_htable_size (int)
+3.18. subs_htable_size (int)
 
    The size of the in-memory hash table to store subscription dialogs.
    This parameter will be used as the power of 2 when computing table
@@ -499,24 +550,24 @@ modparam("presence", "publ_cache", 0)
 
    Default value is "9 (512)".
 
-   Example 1.16. Set subs_htable_size parameter
+   Example 1.18. Set subs_htable_size parameter
 ...
 modparam("presence", "subs_htable_size", 11)
 ...
 
-3.17. pres_htable_size (int)
+3.19. pres_htable_size (int)
 
    The size of the in-memory hash table to store publish records. This
    parameter will be used as the power of 2 when computing table size.
 
    Default value is "9 (512)".
 
-   Example 1.17. Set pres_htable_size parameter
+   Example 1.19. Set pres_htable_size parameter
 ...
 modparam("presence", "pres_htable_size", 11)
 ...
 
-3.18. send_fast_notify (int)
+3.20. send_fast_notify (int)
 
    This parameter enables or disables the sending of an initial empty
    NOTIFY after a SUBSCRIBE/reSUBSCRIBE. This caused problems for MWI
@@ -526,12 +577,12 @@ modparam("presence", "pres_htable_size", 11)
 
    Default value is "1 ".
 
-   Example 1.18. Set send_fast_notify parameter
+   Example 1.20. Set send_fast_notify parameter
 ...
 modparam("presence", "send_fast_notify", 0)
 ...
 
-3.19. enable_sphere_check (int)
+3.21. enable_sphere_check (int)
 
    This parameter is a flag that should be set if permission rules include
    sphere checking. The sphere information is expected to be present in
@@ -541,12 +592,12 @@ modparam("presence", "send_fast_notify", 0)
 
    Default value is "0 ".
 
-   Example 1.19. Set enable_sphere_check parameter
+   Example 1.21. Set enable_sphere_check parameter
 ...
 modparam("presence", "enable_sphere_check", 1)
 ...
 
-3.20. timeout_rm_subs (int)
+3.22. timeout_rm_subs (int)
 
    This parameter is a flag that should be set if subscriptions should be
    removed from the active_watchers when a NOTIFY times out. RFC3265
@@ -556,23 +607,23 @@ modparam("presence", "enable_sphere_check", 1)
 
    Default value is "1".
 
-   Example 1.20. Set timeout_rm_subs parameter
+   Example 1.22. Set timeout_rm_subs parameter
 ...
 modparam("presence", "timeout_rm_subs", 0)
 ...
 
-3.21. fetch_rows (integer)
+3.23. fetch_rows (integer)
 
    Number of rows to be loaded in one step from database.
 
    Default value is 500.
 
-   Example 1.21. Set fetch_rows parameter
+   Example 1.23. Set fetch_rows parameter
 ...
 modparam("presence", "fetch_rows", 1000)
 ...
 
-3.22. db_table_lock_type (integer)
+3.24. db_table_lock_type (integer)
 
    Enable (=1) or disable (=0) the Locks for table during an transaction.
    Locking only the "current" table causes problems with a MySQL-Databases
@@ -585,31 +636,82 @@ modparam("presence", "fetch_rows", 1000)
 
    Default value is 1 (Write Lock for the Tables).
 
-   Example 1.22. Set db_table_lock_type parameter
+   Example 1.24. Set db_table_lock_type parameter
 ...
 modparam("presence", "db_table_lock_type", 0)
 ...
 
-3.23. local_log_level (int)
+3.25. local_log_level (int)
 
    Control log level for some debug messages inside the module.
 
    Default value is 2 (L_INFO).
 
-   Example 1.23. Set local_log_level parameter
+   Example 1.25. Set local_log_level parameter
 ...
 modparam("presence", "local_log_level", 3)
 ...
 
+3.26. subs_remove_match (int)
+
+   Control how to match the subscriptions to remove from memory. If set to
+   0, then the match is done on To-Tag (local generated), if set to 1,
+   then the match is done on all dialog attributes (Call-Id, From-Tag,
+   To-Tag).
+
+   Default value is 0.
+
+   Example 1.26. Set subs_remove_match parameter
+...
+modparam("presence", "subs_remove_match", 1)
+...
+
+3.27. xavp_cfg (str)
+
+   The name of the xavp to be used to specify attributes for internal
+   processing of presence module.
+
+   Inner attributes inside xavp can be:
+     * priority - integer value to set the priority of the presence
+       document (higher value, higher priority). It can set the order of
+       the aggregated presence documents sent by NOTIFY (first the
+       document with higher priority). If xavp_cfg parameter is set but
+       this attribute is not in the avp, the priority of the presence
+       document is based on timestamp, so newer documents have higher
+       priority.
+
+   Default value is empty (not set).
+
+   Example 1.27. Set xavp_cfg parameter
+...
+modparam("presence", "xavp_cfg", "pres")
+...
+if(is_method("PUBLISH")) {
+    $xavp(pres=>priority) = 100;
+}
+...
+
+3.28. retrieve_order (int)
+
+   If set to 0, presentity records are retrieve by received_time order. if
+   set to 1, presentity records are retrieve by priority order.
+
+   Default value is 0.
+
+   Example 1.28. Set retrieve_order parameter
+...
+modparam("presence", "retrieve_order", 1)
+...
+
 4. Functions
 
-   4.1. handle_publish(char* sender_uri)
+   4.1. handle_publish([sender_uri])
    4.2. handle_subscribe([watcher_uri])
    4.3. pres_auth_status(watcher_uri, presentity_uri)
    4.4. pres_refresh_watchers(uri, event, type[, file_uri, filename])
    4.5. pres_update_watchers(uri, event)
 
-4.1. handle_publish(char* sender_uri)
+4.1. handle_publish([sender_uri])
 
    Handles PUBLISH requests by storing and updating published information
    in memory cache and database, then calls functions to send NOTIFY
@@ -629,7 +731,7 @@ modparam("presence", "local_log_level", 3)
 
    The module sends an appropriate stateless reply in all cases.
 
-   Example 1.24. handle_publish usage
+   Example 1.29. handle_publish usage
 ...
         if(is_method("PUBLISH"))
         {
@@ -660,7 +762,7 @@ modparam("presence", "local_log_level", 3)
 
    The module sends an appropriate stateless reply in all cases.
 
-   Example 1.25. handle_subscribe usage
+   Example 1.30. handle_subscribe usage
 ...
 if(method=="SUBSCRIBE")
     handle_subscribe();
@@ -677,7 +779,7 @@ if(method=="SUBSCRIBE")
 
    This function can be used from REQUEST_ROUTE.
 
-   Example 1.26. pres_auth_status usage
+   Example 1.31. pres_auth_status usage
 ...
 if (method=="MESSAGE") {
     pres_auth_status("$fu", $ru");
@@ -713,7 +815,7 @@ if (method=="MESSAGE") {
 
    This function can be used from ANY_ROUTE.
 
-   Example 1.27. pres_refresh_watchers usage
+   Example 1.32. pres_refresh_watchers usage
 ...
 pres_refresh_watchers("sip:test at kamailio.org", "presence", 1);
 ...
@@ -731,7 +833,7 @@ pres_refresh_watchers("sip:test at kamailio.org", "presence", 1);
 
    This function can be used from ANY_ROUTE.
 
-   Example 1.28. pres_update_watchers usage
+   Example 1.33. pres_update_watchers usage
 ...
 pres_update_watchers("sip:test at kamailio.org", "presence");
 ...
diff --git a/modules/presence/bind_presence.c b/modules/presence/bind_presence.c
index 5cbcfc1..98645bd 100644
--- a/modules/presence/bind_presence.c
+++ b/modules/presence/bind_presence.c
@@ -1,5 +1,4 @@
 /*
- * $Id: bind_presence.c 1979 2007-04-06 13:24:12Z anca_vamanu $
  *
  * presence module - presence server implementation
  *
@@ -21,13 +20,10 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2007-04-17  initial version (Anca Vamanu)
  */
 
 /*! \file
- * \brief SIP-Router Presence :: Kamailio generic presence module
+ * \brief Kamailio Presence :: Kamailio generic presence module
  *
  * This is the core presence module, used in combination with other modules.
  *
diff --git a/modules/presence/bind_presence.h b/modules/presence/bind_presence.h
index d96f400..2c512cb 100644
--- a/modules/presence/bind_presence.h
+++ b/modules/presence/bind_presence.h
@@ -1,6 +1,4 @@
 /*
- * $Id: bind_presence.h 1979 2007-04-06 13:24:12Z anca_vamanu $
- *
  * presence module - presence server implementation
  *
  * Copyright (C) 2007 Voice Sistem S.R.L.
@@ -21,12 +19,9 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2007-04-17  initial version (Anca Vamanu)
  */
 /*! \file
- * \brief SIP-Router Presence :: Kamailio generic presence module
+ * \brief Kamailio Presence :: Kamailio generic presence module
  *
  * \ingroup presence
  */
diff --git a/modules/presence/doc/presence_admin.xml b/modules/presence/doc/presence_admin.xml
index e37ddc9..7909260 100644
--- a/modules/presence/doc/presence_admin.xml
+++ b/modules/presence/doc/presence_admin.xml
@@ -81,7 +81,7 @@
 	
 	<section>
 	<title>Parameters</title>
-	<section>
+	<section id="presence.p.db_url">
 		<title><varname>db_url</varname>(str)</title>
 		<para>
 		The database url.
@@ -103,7 +103,7 @@ modparam("presence", "db_url",
 </programlisting>
 		</example>
 	</section>
-	<section>
+	<section id="presence.p.presentity_table">
 		<title><varname>presentity_table</varname>(str)</title>
 		<para>
 		The name of the db table where PUBLISH presence information is stored.
@@ -121,7 +121,7 @@ modparam("presence", "presentity_table", "presentity")
 </programlisting>
 		</example>
 	</section>
-	<section>
+	<section id="presence.p.active_watchers_table">
 		<title><varname>active_watchers_table</varname>(str)</title>
 		<para>
 		The name of the db table where active subscription information is stored. 
@@ -139,7 +139,7 @@ modparam("presence", "active_watchers_table", "active_watchers")
 </programlisting>
 		</example>
 	</section>
-	<section>
+	<section id="presence.p.watchers_table">
 		<title><varname>watchers_table</varname>(str)</title>
 		<para>
 		The name of the db table where subscription states are stored.
@@ -157,7 +157,7 @@ modparam("presence", "watchers_table", "watchers")
 </programlisting>
 		</example>
 	</section>
-	<section>
+	<section id="presence.p.clean_period">
 		<title><varname>clean_period</varname> (int)</title>
 		<para>
 		The period in seconds between checks if there are expired messages stored in database.
@@ -175,7 +175,7 @@ modparam("presence", "clean_period", 100)
 </programlisting>
 		</example>
 	</section>
-	<section>
+	<section id="presence.p.db_update_period">
 		<title><varname>db_update_period</varname> (int)</title>
 		<para>
 		The period at which to synchronize cached subscriber info with the
@@ -195,7 +195,7 @@ modparam("presence", "db_update_period", 100)
 		</example>
 	</section>
 
-	<section>
+	<section id="presence.p.waitn_time">
 		<title><varname>waitn_time</varname> (int)</title>
 		<para>
 		The maximum time period that NOTIFY requests will
@@ -221,7 +221,7 @@ modparam("presence", "waitn_time", 10)
 		</example>
 	</section>
 
-	<section>
+	<section id="presence.p.notifier_poll_rate">
 		<title><varname>notifier_poll_rate</varname> (int)</title>
 		<para>
 		The number of times per second that the notifier processes
@@ -247,7 +247,7 @@ modparam("presence", "notifier_poll_rate", 20)
 		</example>
 	</section>
 
-	<section>
+	<section id="presence.p.notifier_processes">
 		<title><varname>notifier_processes</varname> (int)</title>
 		<para>
 		The number of notifier processes that should be started.
@@ -278,7 +278,7 @@ modparam("presence", "notifier_processes", 2)
 		</example>
 	</section>
 
-	<section>
+	<section id="presence.p.to_tag_pref">
 		<title><varname>to_tag_pref</varname> (str)</title>
 		<para>
 		The prefix used when generating to_tag when sending replies for
@@ -298,7 +298,7 @@ modparam("presence", "to_tag_pref", 'pres')
 		</example>
 	</section>
 
-	<section>
+	<section id="presence.p.expires_offset">
 		<title><varname>expires_offset</varname> (int)</title>
 		<para>
 		The value in seconds that should be subtracted from the expires value when
@@ -319,10 +319,10 @@ modparam("presence", "expires_offset", 10)
 		</example>
 
 </section>
-       <section>
+       <section id="presence.p.max_expires">
                <title><varname>max_expires</varname> (int)</title>
                <para>
-               The the maximum admissible expires value for PUBLISH/SUBSCRIBE
+               The maximum admissible expires value for PUBLISH/SUBSCRIBE
                message (in seconds).
                </para>
                <para>
@@ -339,7 +339,62 @@ modparam("presence", "max_expires", 3600)
 	</example>
 </section>
 
-<section>
+<section id="presence.p.min_expires">
+    <title><varname>min_expires</varname> (int)</title>
+    <para>
+        The minimum admissible expires value for PUBLISH/SUBSCRIBE
+        message (in seconds).
+    </para>
+    <para>
+        If > 0 then min_expires_action parameter determines the response.
+    </para>
+    <para>
+        <emphasis>Default value is <quote>0</quote>.
+        </emphasis>
+    </para>
+    <example>
+        <title>Set <varname>min_expires</varname> parameter</title>
+        <programlisting format="linespecific">
+            ...
+            modparam("presence", "min_expires", 1800)
+            ...
+        </programlisting>
+    </example>
+</section>
+
+<section id="presence.p.min_expires_action">
+    <title><varname>min_expires_action</varname> (int)</title>
+    <para>
+        The action to take when UA sends a expires value less then min_expires.
+    </para>
+    <para>
+        <itemizedlist>
+            <title>Possible Values</title>
+            <listitem>
+                <para> 1 : RFC Compliant, returns <quote>423 Interval Too Brief</quote></para>
+            </listitem>
+            <listitem>
+                <para> 2 : forces the min_expires value in the subscription</para>
+            </listitem>
+        </itemizedlist>
+    </para>
+    <para>
+        If > 0 then min_expires_action parameter determines the response.
+    </para>
+    <para>
+        <emphasis>Default value is <quote>1</quote>.</emphasis>
+    </para>
+    <example>
+        <title>Set <varname>min_expires</varname> parameter</title>
+        <programlisting format="linespecific">
+            ...
+            modparam("presence", "min_expires", 1800)
+            ...
+        </programlisting>
+    </example>
+</section>
+
+<section id="presence.p.server_address">
 		<title><varname>server_address</varname> (str)</title>
 		<para>
 		The presence server address which will become the value of Contact header filed 
@@ -355,7 +410,7 @@ modparam("presence", "server_address", "sip:10.10.10.10:5060")
 		</example>
 	</section>
 
-<section>
+<section id="presence.p.subs_db_mode">
 		<title><varname>subs_db_mode</varname> (int)</title>
 		<para>
 		The presence module can utilize database for persistent subscription storage.
@@ -420,7 +475,7 @@ modparam("presence", "subs_db_mode", 1)
 		</example>
 	</section>
 
-	<section>
+	<section id="presence.p.publ_cache">
 		<title><varname>publ_cache</varname> (int)</title>
 		<para>
 		To improve performance, the presence module holds by default a
@@ -450,7 +505,7 @@ modparam("presence", "publ_cache", 0)
 		</example>
 	</section>
 
-	<section>
+	<section id="presence.p.subs_htable_size">
 		<title><varname>subs_htable_size</varname> (int)</title>
 		<para>
 		The size of the in-memory hash table to store subscription dialogs.
@@ -470,7 +525,7 @@ modparam("presence", "subs_htable_size", 11)
 		</example>
 	</section>
 
-	<section>
+	<section id="presence.p.pres_htable_size">
 		<title><varname>pres_htable_size</varname> (int)</title>
 		<para>
         	The size of the in-memory hash table to store publish records.
@@ -489,7 +544,7 @@ modparam("presence", "pres_htable_size", 11)
 	</programlisting>
 		</example>
 	</section>
-	<section>
+	<section id="presence.p.send_fast_notify">
 		<title><varname>send_fast_notify</varname> (int)</title>
 		<para>
 		This parameter enables or disables the sending of an initial empty NOTIFY after a SUBSCRIBE/reSUBSCRIBE. 
@@ -510,7 +565,7 @@ modparam("presence", "send_fast_notify", 0)
 		</example>
 	</section>
 
-	<section>
+	<section id="presence.p.enable_sphere_check">
 		<title><varname>enable_sphere_check</varname> (int)</title>
 		<para>
 		This parameter is a flag that should be set if permission rules include
@@ -534,7 +589,7 @@ modparam("presence", "enable_sphere_check", 1)
 		</example>
 	</section>
 
-	<section>
+	<section id="presence.p.timeout_rm_subs">
 		<title><varname>timeout_rm_subs</varname> (int)</title>
 		<para>
 		This parameter is a flag that should be set if subscriptions should be
@@ -556,7 +611,7 @@ modparam("presence", "timeout_rm_subs", 0)
 	</programlisting>
 		</example>
 	</section>
-	<section>
+	<section id="presence.p.fetch_rows">
 	    <title><varname>fetch_rows</varname> (integer)</title>
 	    <para>
 		Number of rows to be loaded in one step from database.
@@ -575,7 +630,7 @@ modparam("presence", "fetch_rows", 1000)
 </programlisting>
 	    </example>
 	</section>
-	<section>
+	<section id="presence.p.db_table_lock_type">
 	    <title><varname>db_table_lock_type</varname> (integer)</title>
 	    <para>
 		Enable (=1) or disable (=0) the Locks for table during an
@@ -621,14 +676,122 @@ modparam("presence", "local_log_level", 3)
 </programlisting>
 	    </example>
 	</section>
+	<section id="presence.p.subs_remove_match">
+	    <title><varname>subs_remove_match</varname> (int)</title>
+	    <para>
+		Control how to match the subscriptions to remove from memory.
+		If set to 0, then the match is done on To-Tag (local generated),
+		if set to 1, then the match is done on all dialog attributes
+		(Call-Id, From-Tag, To-Tag).
+	    </para>
+	    <para>
+		<emphasis>
+		    Default value is 0.
+		</emphasis>
+	    </para>
+	    <example>
+		<title>Set <varname>subs_remove_match</varname> parameter</title>
+		<programlisting format="linespecific">
+...
+modparam("presence", "subs_remove_match", 1)
+...
+</programlisting>
+	    </example>
+	</section>
+	<section id="presence.p.xavp_cfg">
+    <title><varname>xavp_cfg</varname> (str)</title>
+    <para>
+		The name of the xavp to be used to specify attributes for internal
+		processing of presence module.
+    </para>
+    <para>
+		Inner attributes inside xavp can be:
+    </para>
+    <itemizedlist>
+        <listitem>
+			<para><emphasis>priority</emphasis> - integer value to set the
+			priority of the presence document (higher value, higher priority).
+			It can set the order of the aggregated presence documents sent by
+			NOTIFY (first the document with higher priority). If xavp_cfg
+			parameter is set but this attribute is not in the avp,
+			the priority of the presence document is based on timestamp,
+			so newer documents have higher priority.</para>
+        </listitem>
+     </itemizedlist>
+    <para>
+        Default value is <emphasis>empty</emphasis> (not set).
+    </para>
+    <example>
+        <title>Set <varname>xavp_cfg</varname> parameter</title>
+        <programlisting format="linespecific">
+...
+modparam("presence", "xavp_cfg", "pres")
+...
+if(is_method("PUBLISH")) {
+    $xavp(pres=>priority) = 100;
+}
+...
+</programlisting>
+    </example>
+	</section>
+
+	<section id="presence.p.retrieve_order">
+	    <title><varname>retrieve_order</varname> (int)</title>
+	    <para>
+		If set to 0, presentity records are retrieve by received_time order.
+		if set to 1, presentity records are retrieve by priority order.
+	    </para>
+	    <para>
+		<emphasis>
+		    Default value is 0.
+		</emphasis>
+	    </para>
+	    <example>
+		<title>Set <varname>retrieve_order</varname> parameter</title>
+		<programlisting format="linespecific">
+...
+modparam("presence", "retrieve_order", 1)
+...
+</programlisting>
+	    </example>
+	</section>
+
+<section id="presence.p.sip_uri_match">
+    <title><varname>sip_uri_match</varname> (int)</title>
+    <para>
+        The mode used when comparing uris.
+    </para>
+    <para>
+        <itemizedlist>
+            <title>Possible Values</title>
+            <listitem>
+                <para> 0 : case sensitive</para>
+            </listitem>
+            <listitem>
+                <para> 1 : case insensitive</para>
+            </listitem>
+        </itemizedlist>
+    </para>
+    <para>
+        <emphasis>Default value is <quote>0</quote>.</emphasis>
+    </para>
+    <example>
+        <title>Set <varname>sip_uri_match</varname> parameter</title>
+        <programlisting format="linespecific">
+            ...
+            modparam("presence", "sip_uri_match", 1)
+            ...
+        </programlisting>
+    </example>
+</section>
 
 </section>
 
 <section>
 	<title>Functions</title>
-	<section>
+	<section id="presence.f.handle_publish">
 		<title>
-		<function moreinfo="none">handle_publish(char* sender_uri)</function>
+		<function moreinfo="none">handle_publish([sender_uri])</function>
 		</title>
 		<para>
 		Handles PUBLISH requests by storing and updating 
@@ -683,7 +846,7 @@ modparam("presence", "local_log_level", 3)
 		</example>
 	</section>
 
-	<section>
+	<section id="presence.f.handle_subscribe">
 		<title>
 		<function moreinfo="none">handle_subscribe([watcher_uri])</function>
 		</title>
@@ -732,7 +895,7 @@ if(method=="SUBSCRIBE")
 		</example>
 	</section>
 
-	<section>
+	<section id="presence.f.pres_auth_status">
 		<title>
 		<function moreinfo="none">pres_auth_status(watcher_uri, presentity_uri)</function>
 		</title>
@@ -767,7 +930,7 @@ if (method=="MESSAGE") {
 		</example>
 	</section>
 
-	<section>
+	<section id="presence.f.pres_refresh_watchers">
 		<title>
 		<function moreinfo="none">pres_refresh_watchers(uri, event, type[, file_uri, filename])</function>
 		</title>
@@ -827,7 +990,7 @@ pres_refresh_watchers("sip:test at kamailio.org", "presence", 1);
 		</example>
 	</section>
 
-	<section>
+	<section id="presence.f.pres_update_whatchers">
 		<title>
 		<function moreinfo="none">pres_update_watchers(uri, event)</function>
 		</title>
@@ -967,6 +1130,40 @@ pres_update_watchers("sip:test at kamailio.org", "presence");
 </section>
 
 <section>
+	<title>Pseudo Variables</title>
+		
+		<section>
+			<title><varname>$subs(attr)</varname></title>
+			<para>
+				Access the attributes of handled subscription. 
+				It must be used after a call of
+				<quote>handle_subscription())</quote>.
+			</para>
+			<para>
+			The <quote>attr</quote> can be:
+			</para>
+			<itemizedlist>
+				<listitem>
+				<para><emphasis>uri</emphasis> - subscription presentity uri
+				</para>
+				</listitem>	  
+			</itemizedlist>
+
+			<example>
+			<title><function moreinfo="none">$subs(name)</function> usage</title>
+<programlisting format="linespecific">
+...
+if(handle_subscription())
+{
+  xlog("presentity=$subs(uri)\n");
+}
+...
+				 </programlisting>
+			</example>
+		</section>
+</section>
+
+<section>
 	<title>Installation</title>
 	<para>
 	The module requires 3 tables in the &kamailio; database: "presentity",
diff --git a/modules/presence/event_list.c b/modules/presence/event_list.c
index 238eeba..e814db3 100644
--- a/modules/presence/event_list.c
+++ b/modules/presence/event_list.c
@@ -17,9 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2007-04-04  initial version (Anca Vamanu)
  */
 
 /*!
diff --git a/modules/presence/event_list.h b/modules/presence/event_list.h
index 29511cb..640e6d5 100644
--- a/modules/presence/event_list.h
+++ b/modules/presence/event_list.h
@@ -17,9 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2007-04-05  initial version (Anca Vamanu)
  */
 
 /*!
diff --git a/modules/presence/hash.c b/modules/presence/hash.c
index 08a3461..49e5a91 100644
--- a/modules/presence/hash.c
+++ b/modules/presence/hash.c
@@ -1,6 +1,4 @@
 /*
- * $Id: hash.c 2583 2007-08-08 11:33:25Z anca_vamanu $
- *
  * presence module - presence server implementation
  *
  * Copyright (C) 2007 Voice Sistem S.R.L.
@@ -21,9 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2007-08-20  initial version (Anca Vamanu)
  */
 
 /*! \file
@@ -42,6 +37,13 @@
 #include "hash.h"
 #include "notify.h"
 
+/* matching mode when removing subscriptions from memory */
+extern int pres_subs_remove_match;
+
+/**
+ * create the subscription hash table in shared memory
+ * - hash_size: number of slots
+ */
 shtable_t new_shtable(int hash_size)
 {
 	shtable_t htable= NULL;
@@ -287,12 +289,26 @@ int delete_shtable(shtable_t htable,unsigned int hash_code,subs_t* subs)
 		
 	while(s)
 	{
-		if(s->callid.len==subs->callid.len
+		if(pres_subs_remove_match==0) {
+			/* match on to-tag only (unique, local generated - faster) */
+			if(s->to_tag.len==subs->to_tag.len
+				&& strncmp(s->to_tag.s,subs->to_tag.s,subs->to_tag.len)==0)
+			{
+				found = 0;
+			}
+		} else {
+			/* match on all dialog attributes (distributed systems) */
+			if(s->callid.len==subs->callid.len
 				&& s->to_tag.len==subs->to_tag.len
 				&& s->from_tag.len==subs->from_tag.len
 				&& strncmp(s->callid.s,subs->callid.s,subs->callid.len)==0
 				&& strncmp(s->to_tag.s,subs->to_tag.s,subs->to_tag.len)==0
 				&& strncmp(s->from_tag.s,subs->from_tag.s,subs->from_tag.len)==0)
+			{
+				found = 0;
+			}
+		}
+		if(found==0)
 		{
 			found= s->local_cseq +1;
 			ps->next= s->next;
@@ -359,7 +375,7 @@ int update_shtable(shtable_t htable,unsigned int hash_code,
 		subs->version = ++s->version;
 	}
 	
-	if(strncmp(s->contact.s, subs->contact.s, subs->contact.len))
+	if(presence_sip_uri_match(&s->contact, &subs->contact))
 	{
 		shm_free(s->contact.s);
 		s->contact.s= (char*)shm_malloc(subs->contact.len* sizeof(char));
@@ -467,7 +483,7 @@ pres_entry_t* search_phtable(str* pres_uri,int event, unsigned int hash_code)
 	while(p)
 	{
 		if(p->event== event && p->pres_uri.len== pres_uri->len &&
-				strncmp(p->pres_uri.s, pres_uri->s, pres_uri->len)== 0 )
+				presence_sip_uri_match(&p->pres_uri, pres_uri)== 0 )
 			return p;
 		p= p->next;
 	}
@@ -480,7 +496,7 @@ int insert_phtable(str* pres_uri, int event, char* sphere)
 	pres_entry_t* p= NULL;
 	int size;
 
-	hash_code= core_hash(pres_uri, NULL, phtable_size);
+	hash_code= core_case_hash(pres_uri, NULL, phtable_size);
 
 	lock_get(&pres_htable[hash_code].lock);
 	
@@ -538,7 +554,7 @@ int delete_phtable(str* pres_uri, int event)
 	unsigned int hash_code;
 	pres_entry_t* p= NULL, *prev_p= NULL;
 
-	hash_code= core_hash(pres_uri, NULL, phtable_size);
+	hash_code= core_case_hash(pres_uri, NULL, phtable_size);
 
 	lock_get(&pres_htable[hash_code].lock);
 	
@@ -595,7 +611,7 @@ int update_phtable(presentity_t* presentity, str pres_uri, str body)
 	}
 
 	/* search for record in hash table */
-	hash_code= core_hash(&pres_uri, NULL, phtable_size);
+	hash_code= core_case_hash(&pres_uri, NULL, phtable_size);
 	
 	lock_get(&pres_htable[hash_code].lock);
 
diff --git a/modules/presence/hash.h b/modules/presence/hash.h
index 065fd20..87e01af 100644
--- a/modules/presence/hash.h
+++ b/modules/presence/hash.h
@@ -1,6 +1,4 @@
 /*
- * $Id: hash.h 2583 2007-08-08 11:33:25Z anca_vamanu $
- *
  * presence module - presence server implementation
  *
  * Copyright (C) 2007 Voice Sistem S.R.L.
@@ -21,9 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2007-08-20  initial version (Anca Vamanu)
  */
 
 /*! \file
diff --git a/modules/presence/notify.c b/modules/presence/notify.c
index bc4c442..6466fc1 100644
--- a/modules/presence/notify.c
+++ b/modules/presence/notify.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * presence module- presence server implementation
  *
  * Copyright (C) 2006 Voice Sistem S.R.L.
@@ -21,9 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2006-08-15  initial version (Anca Vamanu)
  */
 
 /*! \file
@@ -99,6 +94,7 @@ str str_id_col = str_init("id");
 str str_sender_col = str_init("sender");
 str str_updated_col = str_init("updated");
 str str_updated_winfo_col = str_init("updated_winfo");
+str str_priority_col = str_init("priority");
 
 int subset=0;
 
@@ -375,7 +371,7 @@ str* get_wi_notify_body(subs_t* subs, subs_t* watcher_subs)
 			goto error;
 		}
 	} else {
-		hash_code= core_hash(&subs->pres_uri, &subs->event->wipeer->name,
+		hash_code= core_case_hash(&subs->pres_uri, &subs->event->wipeer->name,
 				shtable_size);
 		lock_get(&subs_htable[hash_code].lock);
 		s= subs_htable[hash_code].entries;
@@ -391,7 +387,7 @@ str* get_wi_notify_body(subs_t* subs, subs_t* watcher_subs)
 
 			if(s->event== subs->event->wipeer &&
 				s->pres_uri.len== subs->pres_uri.len &&
-				strncmp(s->pres_uri.s, subs->pres_uri.s,subs->pres_uri.len)== 0)
+				presence_sip_uri_match(&s->pres_uri, &subs->pres_uri)== 0)
 			{
 				if(add_watcher_list(s, watchers)< 0)
 				{
@@ -613,7 +609,7 @@ str* get_p_notify_body(str pres_uri, pres_ev_t* event, str* etag,
 	if( publ_cache_enabled )
 	{
 		/* search in hash table if any record exists */
-		hash_code= core_hash(&pres_uri, NULL, phtable_size);
+		hash_code= core_case_hash(&pres_uri, NULL, phtable_size);
 		if(search_phtable(&pres_uri, event->evp->type, hash_code)== NULL)
 		{
 			LM_DBG("No record exists in hash_table\n");
@@ -657,7 +653,11 @@ str* get_p_notify_body(str pres_uri, pres_ev_t* event, str* etag,
 		return NULL;
 	}
 
-	query_str = str_received_time_col;
+	if(pres_retrieve_order==1) {
+		query_str = str_priority_col;
+	} else {
+		query_str = str_received_time_col;
+	}
 	if (pa_dbf.query (pa_db, query_cols, 0, query_vals,
 		 result_cols, n_query_cols, n_result_cols, &query_str ,  &result) < 0) 
 	{
@@ -705,7 +705,7 @@ str* get_p_notify_body(str pres_uri, pres_ev_t* event, str* etag,
 				sender.len= strlen(sender.s);
 			
 				if(sender.len== contact->len &&
-						strncmp(sender.s, contact->s, sender.len)== 0)
+						presence_sip_uri_match(&sender, contact)== 0)
 				{
 					notify_body= build_empty_bla_body(pres_uri);
 					pa_dbf.free_result(pa_db, result);
@@ -1192,7 +1192,7 @@ subs_t* get_subs_dialog(str* pres_uri, pres_ev_t* event, str* sender)
 			goto error;
 		}
 	}else {
-		hash_code= core_hash(pres_uri, &event->name, shtable_size);
+		hash_code= core_case_hash(pres_uri, &event->name, shtable_size);
 		
 		lock_get(&subs_htable[hash_code].lock);
 
@@ -1213,9 +1213,9 @@ subs_t* get_subs_dialog(str* pres_uri, pres_ev_t* event, str* sender)
 			if((!(s->status== ACTIVE_STATUS &&
 		    s->reason.len== 0 &&
 				s->event== event && s->pres_uri.len== pres_uri->len &&
-				strncmp(s->pres_uri.s, pres_uri->s, pres_uri->len)== 0)) || 
+				presence_sip_uri_match(&s->pres_uri, pres_uri)== 0)) || 
 				(sender && sender->len== s->contact.len && 
-				strncmp(sender->s, s->contact.s, sender->len)== 0))
+				presence_sip_uri_match(sender, &s->contact)== 0))
 				continue;
 
 			s_new= mem_copy_subs(s, PKG_MEM_TYPE);
@@ -1654,7 +1654,7 @@ int notify(subs_t* subs, subs_t * watcher_subs,str* n_body,int force_null_body)
 	if(subs->expires!= 0 && subs->status != TERMINATED_STATUS)
 	{
 		unsigned int hash_code;
-		hash_code= core_hash(&subs->pres_uri, &subs->event->name, shtable_size);
+		hash_code= core_case_hash(&subs->pres_uri, &subs->event->name, shtable_size);
 
 		/* if subscriptions are held also in memory, update the subscription hashtable */
 		if(subs_dbmode != DB_ONLY)
@@ -1889,7 +1889,7 @@ int watcher_found_in_list(watcher_t * watchers, str wuri)
 
 	while(w)
 	{
-		if(w->uri.len == wuri.len && strncmp(w->uri.s, wuri.s, wuri.len)== 0)
+		if(w->uri.len == wuri.len && presence_sip_uri_match(&w->uri, &wuri)== 0)
 			return 1;
 		w= w->next;
 	}
@@ -2266,7 +2266,7 @@ int set_wipeer_subs_updated(str *pres_uri, pres_ev_t *event, int full)
 		update_vals[n_update_cols].type = DB1_INT;
 		update_vals[n_update_cols].nul = 0;
 		update_vals[n_update_cols].val.int_val =
-			core_hash(&callid, &from_tag, 0) % (pres_waitn_time *
+			core_case_hash(&callid, &from_tag, 0) % (pres_waitn_time *
  			 pres_notifier_poll_rate * pres_notifier_processes);
 		n_update_cols++;
 
@@ -2327,7 +2327,7 @@ int set_updated(subs_t *sub)
 	update_vals[0].type = DB1_INT;
 	update_vals[0].nul = 0;
 	update_vals[0].val.int_val =
-		core_hash(&sub->callid, &sub->from_tag, 0) %
+		core_case_hash(&sub->callid, &sub->from_tag, 0) %
 			(pres_waitn_time * pres_notifier_poll_rate
 						* pres_notifier_processes);
 
diff --git a/modules/presence/notify.h b/modules/presence/notify.h
index 1ce747b..4f8276c 100644
--- a/modules/presence/notify.h
+++ b/modules/presence/notify.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * presence module -presence server implementation
  *
  * Copyright (C) 2006 Voice Sistem S.R.L.
@@ -21,9 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2006-08-15  initial version (Anca Vamanu)
  */
 
 /*! \file
@@ -101,6 +96,7 @@ extern str str_id_col;
 extern str str_sender_col;
 extern str str_updated_col;
 extern str str_updated_winfo_col;
+extern str str_priority_col;
 
 void PRINT_DLG(FILE* out, dlg_t* _d);
 
diff --git a/modules/presence/presence.c b/modules/presence/presence.c
index 03eeb56..0668bd2 100644
--- a/modules/presence/presence.c
+++ b/modules/presence/presence.c
@@ -17,9 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2006-08-15  initial version (Anca Vamanu)
  */
 
 /*!
@@ -79,7 +76,7 @@
 MODULE_VERSION
 
 #define S_TABLE_VERSION  3
-#define P_TABLE_VERSION  3
+#define P_TABLE_VERSION  4
 #define ACTWATCH_TABLE_VERSION 11
 
 char *log_buf = NULL;
@@ -98,6 +95,13 @@ int pres_fetch_rows = 500;
 int library_mode= 0;
 str server_address= {0, 0};
 evlist_t* EvList= NULL;
+int pres_subs_remove_match = 0;
+
+/* sip uri match */
+sip_uri_match_f presence_sip_uri_match;
+static int sip_uri_case_sensitive_match(str* s1, str* s2);
+static int sip_uri_case_insensitive_match(str* s1, str* s2);
+int pres_uri_match = 0;
 
 /* to tag prefix */
 char* to_tag_pref = "10";
@@ -138,6 +142,8 @@ char prefix='a';
 int startup_time=0;
 str db_url = {0, 0};
 int expires_offset = 0;
+int min_expires= 0;
+int min_expires_action= 1;
 int max_expires= 3600;
 int shtable_size= 9;
 shtable_t subs_htable= NULL;
@@ -149,6 +155,8 @@ int publ_cache_enabled = 1;
 int pres_waitn_time = 5;
 int pres_notifier_poll_rate = 10;
 int pres_notifier_processes = 1;
+str pres_xavp_cfg = {0};
+int pres_retrieve_order = 0;
 
 int db_table_lock_type = 1;
 db_locking_t db_table_lock = DB_LOCKING_WRITE;
@@ -194,6 +202,8 @@ static param_export_t params[]={
 	{ "to_tag_pref",            PARAM_STRING, &to_tag_pref },
 	{ "expires_offset",         INT_PARAM, &expires_offset },
 	{ "max_expires",            INT_PARAM, &max_expires },
+	{ "min_expires",            INT_PARAM, &min_expires },
+    { "min_expires_action",     INT_PARAM, &min_expires_action },
 	{ "server_address",         PARAM_STR, &server_address},
 	{ "subs_htable_size",       INT_PARAM, &shtable_size},
 	{ "pres_htable_size",       INT_PARAM, &phtable_size},
@@ -205,6 +215,10 @@ static param_export_t params[]={
 	{ "fetch_rows",             INT_PARAM, &pres_fetch_rows},
 	{ "db_table_lock_type",     INT_PARAM, &db_table_lock_type},
 	{ "local_log_level",        PARAM_INT, &pres_local_log_level},
+	{ "subs_remove_match",      PARAM_INT, &pres_subs_remove_match},
+	{ "xavp_cfg",               PARAM_STR, &pres_xavp_cfg},
+	{ "retrieve_order",         PARAM_INT, &pres_retrieve_order},
+	{ "sip_uri_match",          PARAM_INT, &pres_uri_match},
     {0,0,0}
 };
 
@@ -214,6 +228,11 @@ static mi_export_t mi_cmds[] = {
 	{  0,                0,                     0,  0,  0}
 };
 
+static pv_export_t pres_mod_pvs[] = {
+	{{"subs", (sizeof("subs")-1)}, PVT_OTHER, pv_get_subscription, 0, pv_parse_subscription_name, 0, 0, 0},
+	{ {0, 0}, 0, 0, 0, 0, 0, 0, 0 }
+};
+
 /** module exports */
 struct module_exports exports= {
 	"presence",			/* module name */
@@ -222,7 +241,7 @@ struct module_exports exports= {
 	params,				/* exported parameters */
 	0,					/* exported statistics */
 	mi_cmds,   			/* exported MI functions */
-	0,					/* exported pseudo-variables */
+	pres_mod_pvs,		/* exported pseudo-variables */
 	0,					/* extra processes */
 	mod_init,			/* module initialization function */
 	0,   				/* response handling function */
@@ -235,6 +254,12 @@ struct module_exports exports= {
  */
 static int mod_init(void)
 {
+	if(pres_uri_match == 1) {
+		presence_sip_uri_match = sip_uri_case_insensitive_match;
+	} else {
+		presence_sip_uri_match = sip_uri_case_sensitive_match;
+	}
+
 	if(register_mi_mod(exports.name, mi_cmds)!=0)
 	{
 		LM_ERR("failed to register MI commands\n");
@@ -272,6 +297,17 @@ static int mod_init(void)
 	if(max_expires<= 0)
 		max_expires = 3600;
 
+	if(min_expires < 0)
+		min_expires = 0;
+
+	if(min_expires > max_expires)
+		min_expires = max_expires;
+
+    if(min_expires_action < 1 || min_expires_action > 2) {
+        LM_ERR("min_expires_action must be 1 = RFC 6665/3261 Reply 423, 2 = force min_expires value\n");
+        return -1;
+    }
+    
 	if(server_address.s== NULL)
 		LM_DBG("server_address parameter not set in configuration file\n");
 
@@ -994,7 +1030,7 @@ int update_watchers_status(str pres_uri, pres_ev_t* ev, str* rules_doc)
 	}
 
 	LM_DBG("found %d record-uri in watchers_table\n", result->n);
-	hash_code= core_hash(&pres_uri, &ev->name, shtable_size);
+	hash_code= core_case_hash(&pres_uri, &ev->name, shtable_size);
 	subs.db_flag= hash_code;
 
 	/*must do a copy as sphere_check requires database queries */
@@ -1415,7 +1451,7 @@ static int update_pw_dialogs_dbonlymode(subs_t* subs, subs_t** subs_array)
 					* pres_notifier_processes));
 	} else {
 		db_vals[n_update_cols].val.int_val = 
-			core_hash(&subs->callid, &subs->from_tag, 0) %
+			core_case_hash(&subs->callid, &subs->from_tag, 0) %
 				  (pres_waitn_time * pres_notifier_poll_rate
 					* pres_notifier_processes);
 	}
@@ -1454,9 +1490,9 @@ static int update_pw_dialogs(subs_t* subs, unsigned int hash_code, subs_t** subs
 		if(s->event== subs->event && s->pres_uri.len== subs->pres_uri.len &&
 			s->watcher_user.len== subs->watcher_user.len && 
 			s->watcher_domain.len==subs->watcher_domain.len &&
-			strncmp(s->pres_uri.s, subs->pres_uri.s, subs->pres_uri.len)== 0 &&
-			strncmp(s->watcher_user.s, subs->watcher_user.s, s->watcher_user.len)== 0 &&
-			strncmp(s->watcher_domain.s,subs->watcher_domain.s,s->watcher_domain.len)==0)
+			presence_sip_uri_match(&s->pres_uri, &subs->pres_uri)== 0 &&
+			presence_sip_uri_match(&s->watcher_user, &subs->watcher_user)== 0 &&
+			presence_sip_uri_match(&s->watcher_domain, &subs->watcher_domain)==0)
 		{
 			i++;
 			s->status= subs->status;
@@ -1822,3 +1858,29 @@ static int presence_init_rpc(void)
 	}
 	return 0;
 }
+
+static int sip_uri_case_sensitive_match(str* s1, str* s2)
+{
+	if(!s1) {
+		LM_ERR("null pointer (s1) in sip_uri_match\n");
+		return -1;
+	}
+	if(!s2) {
+		LM_ERR("null pointer (s2) in sip_uri_match\n");
+		return -1;
+	}
+	return strncmp(s1->s, s2->s, s2->len);
+}
+
+static int sip_uri_case_insensitive_match(str* s1, str* s2)
+{
+	if(!s1) {
+		LM_ERR("null pointer (s1) in sip_uri_match\n");
+		return -1;
+	}
+	if(!s2) {
+		LM_ERR("null pointer (s2) in sip_uri_match\n");
+		return -1;
+	}
+	return strncasecmp(s1->s, s2->s, s2->len);
+}
diff --git a/modules/presence/presence.h b/modules/presence/presence.h
index c1bd288..92c9ecc 100644
--- a/modules/presence/presence.h
+++ b/modules/presence/presence.h
@@ -17,10 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  *
- *
- * History:
- * ---------
- *  2006-10-09  first version (Anca Vamanu)
  */
 
 /*!
@@ -76,6 +72,8 @@ extern int startup_time;
 extern char *to_tag_pref;
 extern int expires_offset;
 extern str server_address;
+extern int min_expires;
+extern int min_expires_action;
 extern int max_expires;
 extern int subs_dbmode;
 extern int publ_cache_enabled;
@@ -90,6 +88,8 @@ extern int pres_fetch_rows;
 extern int pres_waitn_time;
 extern int pres_notifier_poll_rate;
 extern int pres_notifier_processes;
+extern str pres_xavp_cfg;
+extern int pres_retrieve_order;
 
 extern int phtable_size;
 extern phtable_t* pres_htable;
@@ -99,4 +99,10 @@ extern db_locking_t db_table_lock;
 int update_watchers_status(str pres_uri, pres_ev_t* ev, str* rules_doc);
 int pres_auth_status(struct sip_msg* msg, str watcher_uri, str presentity_uri);
 
+typedef int (*sip_uri_match_f) (str* s1, str* s2);
+extern sip_uri_match_f presence_sip_uri_match;
+
+int pv_get_subscription(struct sip_msg *msg, pv_param_t *param,	pv_value_t *res);
+int pv_parse_subscription_name(pv_spec_p sp, str *in);
+
 #endif /* PA_MOD_H */
diff --git a/modules/presence/presentity.c b/modules/presence/presentity.c
index cd0b9a3..0f3c3e5 100644
--- a/modules/presence/presentity.c
+++ b/modules/presence/presentity.c
@@ -17,9 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2006-08-15  initial version (Anca Vamanu)
  */
 
 /*!
@@ -38,8 +35,8 @@
 #include "../../hashes.h"
 #include "../../dprint.h"
 #include "../../mem/shm_mem.h"
+#include "../../xavp.h"
 #include "../../str.h"
-#include "../alias_db/alias_db.h"
 #include "../../data_lump_rpl.h"
 #include "presentity.h"
 #include "presence.h" 
@@ -49,6 +46,9 @@
 #include "utils_func.h"
 
 
+/* base priority value (20150101T000000) */
+#define PRES_PRIORITY_TBASE	1420070400
+
 xmlNodePtr xmlNodeGetNodeByName(xmlNodePtr node, const char *name,
 													const char *ns);
 static str pu_200_rpl  = str_init("OK");
@@ -167,7 +167,31 @@ error:
 		pkg_free(hdr_append2.s);
 
 	return -1;
-}	
+}
+
+/**
+ * get priority value for presence document
+ */
+unsigned int pres_get_priority(void)
+{
+	sr_xavp_t *vavp = NULL;
+	str vname = str_init("priority");
+
+	if(pres_xavp_cfg.s==NULL || pres_xavp_cfg.len<=0) {
+		return 0;
+	}
+
+	vavp = xavp_get_child_with_ival(&pres_xavp_cfg, &vname);
+	if(vavp!=NULL) {
+		return (unsigned int)vavp->val.v.i;
+	}
+
+	return (unsigned int)(time(NULL) - PRES_PRIORITY_TBASE);
+}
+
+/**
+ * create new presentity record
+ */
 presentity_t* new_presentity( str* domain,str* user,int expires, 
 		pres_ev_t* event, str* etag, str* sender)
 {
@@ -224,6 +248,7 @@ presentity_t* new_presentity( str* domain,str* user,int expires,
 	presentity->event= event;
 	presentity->expires = expires;
 	presentity->received_time= (int)time(NULL);
+	presentity->priority = pres_get_priority();
 	return presentity;
     
 error:
@@ -271,9 +296,9 @@ int check_if_dialog(str body, int *is_dialog)
 int update_presentity(struct sip_msg* msg, presentity_t* presentity, str* body,
 		int new_t, int* sent_reply, char* sphere)
 {
-	db_key_t query_cols[12], update_keys[8], result_cols[5];
-	db_op_t  query_ops[12];
-	db_val_t query_vals[12], update_vals[8];
+	db_key_t query_cols[13], update_keys[9], result_cols[6];
+	db_op_t  query_ops[13];
+	db_val_t query_vals[13], update_vals[9];
 	db1_res_t *result= NULL;
 	int n_query_cols = 0;
 	int n_update_cols = 0;
@@ -378,6 +403,12 @@ int update_presentity(struct sip_msg* msg, presentity_t* presentity, str* body,
 		query_vals[n_query_cols].nul = 0;
 		query_vals[n_query_cols].val.int_val = presentity->received_time;
 		n_query_cols++;
+
+		query_cols[n_query_cols] = &str_priority_col;
+		query_vals[n_query_cols].type = DB1_INT;
+		query_vals[n_query_cols].nul = 0;
+		query_vals[n_query_cols].val.int_val = presentity->priority;
+		n_query_cols++;
 		
 		if (presentity->expires != -1)
 		{
@@ -519,7 +550,7 @@ int update_presentity(struct sip_msg* msg, presentity_t* presentity, str* body,
 			if(presentity->sender)
 			{
 				if(!(presentity->sender->len == sender.len && 
-				strncmp(presentity->sender->s, sender.s, sender.len)== 0))
+				presence_sip_uri_match(presentity->sender, &sender)== 0))
 					 bla_update_publish= 0;
 			}
 after_dialog_check:
@@ -680,6 +711,12 @@ after_dialog_check:
 		update_vals[n_update_cols].val.int_val= presentity->received_time;
 		n_update_cols++;
 
+		update_keys[n_update_cols] = &str_priority_col;
+		update_vals[n_update_cols].type = DB1_INT;
+		update_vals[n_update_cols].nul = 0;
+		update_vals[n_update_cols].val.int_val= presentity->priority;
+		n_update_cols++;
+
 		if(body && body->s)
 		{
 			update_keys[n_update_cols] = &str_body_col;
@@ -1035,7 +1072,7 @@ char* get_sphere(str* pres_uri)
 	if ( publ_cache_enabled )
 	{
 		/* search in hash table*/
-		hash_code= core_hash(pres_uri, NULL, phtable_size);
+		hash_code= core_case_hash(pres_uri, NULL, phtable_size);
 
 		lock_get(&pres_htable[hash_code].lock);
 
@@ -1092,7 +1129,11 @@ char* get_sphere(str* pres_uri)
 		return NULL;
 	}
 
-	query_str = str_received_time_col;
+	if(pres_retrieve_order==1) {
+		query_str = str_priority_col;
+	} else {
+		query_str = str_received_time_col;
+	}
 	if (pa_dbf.query (pa_db, query_cols, 0, query_vals,
 		 result_cols, n_query_cols, n_result_cols, &query_str ,  &result) < 0) 
 	{
diff --git a/modules/presence/presentity.h b/modules/presence/presentity.h
index 55e433a..a925830 100644
--- a/modules/presence/presentity.h
+++ b/modules/presence/presentity.h
@@ -17,9 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2006-08-15  initial version (Anca Vamanu)
  */
 
 /*!
@@ -49,6 +46,7 @@ typedef struct presentity
 	str* sender;
 	time_t expires;
 	time_t received_time;
+	unsigned int priority;
 } presentity_t;
 
 /* create new presentity */
diff --git a/modules/presence/publish.c b/modules/presence/publish.c
index a95d805..5a48f77 100644
--- a/modules/presence/publish.c
+++ b/modules/presence/publish.c
@@ -17,9 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2006-08-15  initial version (Anca Vamanu)
  */
 
 /*!
diff --git a/modules/presence/publish.h b/modules/presence/publish.h
index 6c2e9d8..09be0fc 100644
--- a/modules/presence/publish.h
+++ b/modules/presence/publish.h
@@ -17,9 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2006-08-15  initial version (Anca Vamanu)
  */
 
 /*!
diff --git a/modules/presence/subscribe.c b/modules/presence/subscribe.c
index ce09e2f..1268243 100644
--- a/modules/presence/subscribe.c
+++ b/modules/presence/subscribe.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * presence module - presence server implementation
  *
  * Copyright (C) 2006 Voice Sistem S.R.L.
@@ -21,9 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2006-08-15  initial version (Anca Vamanu)
  */
 
 /*! \file
@@ -58,6 +53,7 @@ static str pu_481_rpl  = str_init("Subscription does not exist");
 static str pu_400_rpl  = str_init("Bad request");
 static str pu_500_rpl  = str_init("Server Internal Error");
 static str pu_489_rpl  = str_init("Bad Event");
+static str pu_423_rpl  = str_init("Interval Too Brief");
 
 int send_2XX_reply(struct sip_msg * msg, int reply_code, int lexpire,
 		str* local_contact)
@@ -467,7 +463,7 @@ void delete_subs(str* pres_uri, str* ev_name, str* to_tag,
 	/* delete record from hash table also if not in dbonly mode */
 	if(subs_dbmode != DB_ONLY)
 	{
-		unsigned int hash_code= core_hash(pres_uri, ev_name, shtable_size);
+		unsigned int hash_code= core_case_hash(pres_uri, ev_name, shtable_size);
 		if(delete_shtable(subs_htable, hash_code, &subs) < 0) {
 			LM_ERR("Failed to delete subscription from memory"
 					" [slot: %u ev: %.*s pu: %.*s ci: %.*s ft: %.*s tt: %.*s]\n",
@@ -490,7 +486,7 @@ int update_subscription_notifier(struct sip_msg* msg, subs_t* subs,
 	*sent_reply= 0;
 
 	/* Set the notifier/update fields for the subscription */
-	subs->updated = core_hash(&subs->callid, &subs->from_tag, 0) %
+	subs->updated = core_case_hash(&subs->callid, &subs->from_tag, 0) %
 				(pres_waitn_time * pres_notifier_poll_rate
 					* pres_notifier_processes);
 	if (subs->event->type & WINFO_TYPE)
@@ -610,7 +606,7 @@ int update_subscription(struct sip_msg* msg, subs_t* subs, int to_tag_gen,
 		/* if subscriptions are stored in memory, update them */
 		if(subs_dbmode != DB_ONLY)
 		{
-			hash_code= core_hash(&subs->pres_uri, &subs->event->name, shtable_size);
+			hash_code= core_case_hash(&subs->pres_uri, &subs->event->name, shtable_size);
 			if(update_shtable(subs_htable, hash_code, subs, REMOTE_TYPE)< 0)
 			{
 				LM_ERR("failed to update subscription in memory\n");
@@ -637,7 +633,7 @@ int update_subscription(struct sip_msg* msg, subs_t* subs, int to_tag_gen,
 			{
 				LM_DBG("inserting in shtable\n");
 				subs->db_flag = (subs_dbmode==WRITE_THROUGH)?WTHROUGHDB_FLAG:INSERTDB_FLAG;
-				hash_code= core_hash(&subs->pres_uri, &subs->event->name, shtable_size);
+				hash_code= core_case_hash(&subs->pres_uri, &subs->event->name, shtable_size);
 				subs->version = 0;
 				if(insert_shtable(subs_htable,hash_code,subs)< 0)
 				{
@@ -759,6 +755,46 @@ void msg_watchers_clean(unsigned int ticks,void *param)
 		LM_ERR("cleaning pending subscriptions\n");
 }
 
+static char* _pres_subs_last_presentity = NULL;
+
+int pv_parse_subscription_name(pv_spec_p sp, str *in)
+{
+	if(sp==NULL || in==NULL || in->len<=0)
+		return -1;
+
+	switch(in->len)
+	{
+		case 3:
+			if(strncmp(in->s, "uri", 3)==0) {
+				sp->pvp.pvn.u.isname.name.n = 1;
+			} else {
+				goto error;
+			};
+			break;
+		default:
+			goto error;
+	}
+	sp->pvp.pvn.type = PV_NAME_INTSTR;
+	sp->pvp.pvn.u.isname.type = 0;
+
+	return 0;
+
+error:
+	LM_ERR("unknown PV subscription name %.*s\n", in->len, in->s);
+	return -1;
+}
+
+int pv_get_subscription(struct sip_msg *msg, pv_param_t *param,	pv_value_t *res)
+{
+	if(param->pvn.u.isname.name.n==1) /* presentity */
+		return (_pres_subs_last_presentity == NULL) ? pv_get_null(msg, param, res)
+						: pv_get_strzval(msg, param, res, _pres_subs_last_presentity);
+
+	LM_ERR("unknown specifier\n");
+	return pv_get_null(msg, param, res);
+
+}
+
 int handle_subscribe0(struct sip_msg* msg)
 {
 	struct to_body *pfrom;
@@ -813,6 +849,11 @@ int handle_subscribe(struct sip_msg* msg, str watcher_user, str watcher_domain)
 	str reply_str;
 	int sent_reply= 0;
 
+	if(_pres_subs_last_presentity) {
+		pkg_free(_pres_subs_last_presentity);
+		_pres_subs_last_presentity = NULL;
+	}
+
 	/* ??? rename to avoid collisions with other symbols */
 	counter++;
 
@@ -863,11 +904,10 @@ int handle_subscribe(struct sip_msg* msg, str watcher_user, str watcher_domain)
 		ev_param= ev_param->next;
 	}
 	
-	if(extract_sdialog_info(&subs, msg, max_expires, &to_tag_gen,
-				server_address, watcher_user, watcher_domain)< 0)
+	if(extract_sdialog_info_ex(&subs, msg, min_expires, max_expires, &to_tag_gen,
+				server_address, watcher_user, watcher_domain, &reply_code, &reply_str)< 0)
 	{
-		LM_ERR("failed to extract dialog information\n");
-		goto error;
+            goto error;
 	}
 
 	if (pres_notifier_processes > 0 && pa_dbf.start_transaction)
@@ -911,6 +951,14 @@ int handle_subscribe(struct sip_msg* msg, str watcher_user, str watcher_domain)
 		}
 		reason= subs.reason;
 	}
+
+	if(subs.pres_uri.len > 0 && subs.pres_uri.s) {
+		_pres_subs_last_presentity =
+				(char*)pkg_malloc((subs.pres_uri.len+1) * sizeof(char));
+		strncpy(_pres_subs_last_presentity, subs.pres_uri.s, subs.pres_uri.len);
+		_pres_subs_last_presentity[subs.pres_uri.len] = '\0';
+	}
+		
 	/* mark that the received event is a SUBSCRIBE message */
 	subs.recv_event = PRES_SUBSCRIBE_RECV;
 
@@ -1088,9 +1136,10 @@ error:
 }
 
 
-int extract_sdialog_info(subs_t* subs,struct sip_msg* msg, int mexp,
-		int* to_tag_gen, str scontact, str watcher_user,
-		str watcher_domain)
+int extract_sdialog_info_ex(subs_t* subs,struct sip_msg* msg, int miexp,
+		int mexp, int* to_tag_gen, str scontact,
+		str watcher_user, str watcher_domain,
+        int* reply_code, str* reply_str)
 {
 	str rec_route= {0, 0};
 	int rt  = 0;
@@ -1120,6 +1169,18 @@ int extract_sdialog_info(subs_t* subs,struct sip_msg* msg, int mexp,
 	if(lexpire > mexp)
 		lexpire = mexp;
 
+    if (lexpire && miexp && lexpire < miexp) {
+        if(min_expires_action == 1) {
+            LM_DBG("subscription expiration invalid , requested=%d, minimum=%d, returning error \"423 Interval Too brief\"\n", lexpire, miexp);
+            *reply_code = INTERVAL_TOO_BRIEF;
+            *reply_str = pu_423_rpl;
+            goto error;
+        } else {
+            LM_DBG("subscription expiration set to minimum (%d) for requested (%d)\n", lexpire, miexp);
+            lexpire = miexp;
+        }
+    }
+    
 	subs->expires = lexpire;
 
 	if( msg->to==NULL || msg->to->body.s==NULL)
@@ -1325,6 +1386,15 @@ error:
 	return -1;
 }
 
+int extract_sdialog_info(subs_t* subs,struct sip_msg* msg, int mexp,
+                         int* to_tag_gen, str scontact,
+                         str watcher_user, str watcher_domain)
+{
+    int reply_code = 500;
+    str reply_str = pu_500_rpl;
+    return extract_sdialog_info_ex(subs, msg, min_expires, mexp, to_tag_gen,
+        scontact, watcher_user, watcher_domain, &reply_code, &reply_str);
+}
 
 int get_stored_info(struct sip_msg* msg, subs_t* subs, int* reply_code,
 		str* reply_str)
@@ -1350,7 +1420,7 @@ int get_stored_info(struct sip_msg* msg, subs_t* subs, int* reply_code,
 	else
 		pres_uri = subs->pres_uri;
 
-	hash_code= core_hash(&pres_uri, &subs->event->name, shtable_size);
+	hash_code= core_case_hash(&pres_uri, &subs->event->name, shtable_size);
 	lock_get(&subs_htable[hash_code].lock);
 	s= search_shtable(subs_htable, subs->callid, subs->to_tag,
 		subs->from_tag, hash_code);
@@ -2459,7 +2529,7 @@ int restore_db_subs(void)
 			s.sockinfo_str.s=(char*)row_vals[sockinfo_col].val.string_val;
 			s.sockinfo_str.len= strlen(s.sockinfo_str.s);
 			s.db_flag = (subs_dbmode==WRITE_THROUGH)?WTHROUGHDB_FLAG:NO_UPDATEDB_FLAG;
-			hash_code= core_hash(&s.pres_uri, &s.event->name, shtable_size);
+			hash_code= core_case_hash(&s.pres_uri, &s.event->name, shtable_size);
 			if(insert_shtable(subs_htable, hash_code, &s)< 0)
 			{
 				LM_ERR("adding new record in hash table\n");
diff --git a/modules/presence/subscribe.h b/modules/presence/subscribe.h
index 00c02a3..955e46a 100644
--- a/modules/presence/subscribe.h
+++ b/modules/presence/subscribe.h
@@ -19,9 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2006-08-15  initial version (Anca Vamanu)
  */
 
 /*! \file
@@ -113,11 +110,14 @@ void update_db_subs_timer(db1_con_t *db,db_func_t dbf, shtable_t hash_table,
 typedef void (*update_db_subs_t)(db1_con_t * ,db_func_t ,shtable_t ,int ,int ,
 		handle_expired_func_t);
 
+int extract_sdialog_info_ex(subs_t* subs,struct sip_msg* msg, int min_expire,
+        int max_expire, int* to_tag_gen, str scontact, str watcher_user,
+        str watcher_domain, int* reply_code,str* reply_txt);
 int extract_sdialog_info(subs_t* subs,struct sip_msg* msg, int max_expire,
 		int* to_tag_gen, str scontact, str watcher_user, str watcher_domain);
 typedef int (*extract_sdialog_info_t)(subs_t* subs, struct sip_msg* msg,
-		int max_expire, int* to_tag_gen, str scontact, str watcher_user,
-		str watcher_domain);
+        int max_expire, int* to_tag_gen, str scontact, str watcher_user,
+        str watcher_domain);
 void delete_subs(str* pres_uri, str* ev_name, str* to_tag, str* from_tag, str* callid);
 
 #endif
diff --git a/modules/presence/utils_func.c b/modules/presence/utils_func.c
index e7dbd06..c56c6cb 100644
--- a/modules/presence/utils_func.c
+++ b/modules/presence/utils_func.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * presence module - presence server implementation
  *
  * Copyright (C) 2006 Voice Sistem S.R.L.
@@ -21,9 +19,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2006-08-15  initial version (Anca Vamanu)
  */
 
 /*! \file
@@ -102,13 +97,13 @@ int a_to_i (char *s,int len)
 
 int send_error_reply(struct sip_msg* msg, int reply_code, str reply_str)
 {
-	if(reply_code== BAD_EVENT_CODE)
-	{
-		str hdr_append;
-		char buffer[256];
-		int i;
-		pres_ev_t* ev= EvList->events;
+    str hdr_append;
+    char buffer[256];
+    int i;
+    pres_ev_t* ev= EvList->events;
 
+    if(reply_code== BAD_EVENT_CODE)
+	{
 		hdr_append.s = buffer;
 		hdr_append.s[0]='\0';
 		hdr_append.len = sprintf(hdr_append.s, "Allow-Events: ");
@@ -138,7 +133,26 @@ int send_error_reply(struct sip_msg* msg, int reply_code, str reply_str)
 			LM_ERR("unable to add lump_rl\n");
 			return -1;
 		}
-	}
+    } else if(reply_code== INTERVAL_TOO_BRIEF) {
+        
+        hdr_append.s = buffer;
+        hdr_append.s[0]='\0';
+        hdr_append.len = sprintf(hdr_append.s, "Min-Expires: %d", min_expires);
+        if(hdr_append.len < 0)
+        {
+            LM_ERR("unsuccessful sprintf\n");
+            return -1;
+        }
+        memcpy(hdr_append.s+ hdr_append.len, CRLF, CRLF_LEN);
+        hdr_append.len+=  CRLF_LEN;
+        hdr_append.s[hdr_append.len]= '\0';
+        
+        if (add_lump_rpl( msg, hdr_append.s, hdr_append.len, LUMP_RPL_HDR)==0 )
+        {
+            LM_ERR("unable to add lump_rl\n");
+            return -1;
+        }
+    }
 
 	if (slb.freply(msg, reply_code, &reply_str) < 0)
 	{
diff --git a/modules/presence/utils_func.h b/modules/presence/utils_func.h
index bb3a181..866df1b 100644
--- a/modules/presence/utils_func.h
+++ b/modules/presence/utils_func.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * presence module - presence server implementation
  *
  * Copyright (C) 2006 Voice Sistem S.R.L.
@@ -21,9 +19,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2006-08-15  initial version (Anca Vamanu)
  */
 
 /*! \file
@@ -47,6 +42,7 @@
 
 #define LCONTACT_BUF_SIZE 1024
 #define BAD_EVENT_CODE 489
+#define INTERVAL_TOO_BRIEF 423
 
 
 #define EVENT_DIALOG_SLA(ev) \
diff --git a/modules/presence_dialoginfo/notify_body.c b/modules/presence_dialoginfo/notify_body.c
index b7cad27..5db2a98 100644
--- a/modules/presence_dialoginfo/notify_body.c
+++ b/modules/presence_dialoginfo/notify_body.c
@@ -68,7 +68,7 @@ void free_xml_body(char* body)
 }
 
 #define DIALOGINFO_EMPTY_BODY "<dialog-info>\
-<dialog direction=\"recipient\">\
+<dialog id=\"615293b33c62dec073e05d9421e9f48b\" direction=\"recipient\">\
 <state>terminated</state>\
 </dialog>\
 </dialog-info>"
diff --git a/modules/presence_reginfo/Makefile b/modules/presence_reginfo/Makefile
index 6b508a7..b4b94f0 100644
--- a/modules/presence_reginfo/Makefile
+++ b/modules/presence_reginfo/Makefile
@@ -1,5 +1,5 @@
 #
-# Presence_MWI Makefile
+# Presence_reginfo Makefile
 # 
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
diff --git a/modules/print/Makefile b/modules/print/Makefile
index a871df8..af48fdc 100644
--- a/modules/print/Makefile
+++ b/modules/print/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # print example module makefile
 #
diff --git a/modules/print_lib/Makefile b/modules/print_lib/Makefile
index 47abe45..3c93ddc 100644
--- a/modules/print_lib/Makefile
+++ b/modules/print_lib/Makefile
@@ -1,6 +1,5 @@
-# $Id$
 #
-# print example module makefile
+# print_lib example module makefile
 #
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
diff --git a/modules/pua/README b/modules/pua/README
index c8c7d8a..ed64a3b 100644
--- a/modules/pua/README
+++ b/modules/pua/README
@@ -8,7 +8,7 @@ Edited by
 
 Anca-Maria Vamanu
 
-   Copyright � 2006 Voice Sistem SRL
+   Copyright (c) 2006 Voice Sistem SRL
      __________________________________________________________________
 
    Table of Contents
@@ -186,7 +186,7 @@ modparam("pua", "hash_size", 11)
 
    Database url.
 
-   Default value is ">mysql://openser:openserrw@localhost/openser".
+   Default value is ">mysql://kamailio:kamailiorw@localhost/kamailio".
 
    Example 1.2. Set db_url parameter
 ...
@@ -243,7 +243,8 @@ modparam("pua", "update_period", 100)
 
 3.7. outbound_proxy (str)
 
-   SIP URI of outbound proxy to be used when sending PUBLISH requests.
+   SIP URI of outbound proxy to be used when sending PUBLISH requests if
+   no outbound proxy is given in outbound_proxy field of struct publ_info.
 
    By default, no outbound proxy has been defined.
 
@@ -334,7 +335,7 @@ modparam("pua", "fetch_rows", 1000)
 
    4.1. pua_update_contact()
 
-4.1. pua_update_contact()
+4.1.  pua_update_contact()
 
    The remote target can be updated by the Contact of a subsequent in
    dialog request. In the PUA watcher case (sending a SUBSCRIBE messages),
@@ -359,7 +360,7 @@ if(method=="NOTIFY")
 
    5.1. pua_cleanup
 
-5.1. pua_cleanup
+5.1.  pua_cleanup
 
    Manually triggers the cleanup functions for the pua table. Useful if
    you have set update_period to zero or less.
@@ -394,7 +395,7 @@ Chapter 2. Developer Guide
    The module provides the following functions that can be used by other
    Kamailio modules.
 
-1. bind_pua(pua_api_t* api)
+1.  bind_pua(pua_api_t* api)
 
    This function binds the pua modules and fills the structure with the
    two exported functions.
@@ -410,7 +411,7 @@ typedef struct pua_api {
 } pua_api_t;
 ...
 
-2. send_publish
+2.  send_publish
 
    Field type:
 ...
@@ -445,12 +446,14 @@ typedef struct publ_info
                           for that event)*/
   str* etag;          /*  (optional) the value of the etag the request
                           should match */
+  str* outbound_proxy;/*  outbound_proxy to use when sending the
+                          Publish request */
   str* extra_headers  /*  (optional) extra_headers that should be added
                           to Publish msg*/
 }publ_info_t;
 ...
 
-3. send_subscribe
+3.  send_subscribe
 
    Field type:
 ...
@@ -489,7 +492,7 @@ typedef struct subs_info
 }subs_info_t;
 ...
 
-4. is_dialog
+4.  is_dialog
 
    Field type:
 ...
@@ -508,7 +511,7 @@ typedef int  (*query_dialog_t)(ua_pres_t* presentity);
         }
 ...
 
-5. register_puacb
+5.  register_puacb
 
    Field type:
 ...
@@ -537,7 +540,7 @@ typedef int (*register_puacb_t)(int types, pua_cb f, void* param );
 typedef int (pua_cb)(ua_pres_t* hentity, struct sip_msg*);
 ...
 
-6. add_event
+6.  add_event
 
    Field type:
 ...
diff --git a/modules/pua/add_events.c b/modules/pua/add_events.c
index d48ea5f..f4a9c8e 100644
--- a/modules/pua/add_events.c
+++ b/modules/pua/add_events.c
@@ -1,6 +1,4 @@
 /*
- * $Id: add_events.c  2007-05-03 15:05:20Z anca_vamanu $
- *
  * pua module - presence user agent module
  *
  * Copyright (C) 2007 Voice Sistem S.R.L.
@@ -21,7 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- *	initial version 2007-05-03 (anca)
  */
 #include <stdio.h>
 #include <stdlib.h>
diff --git a/modules/pua/add_events.h b/modules/pua/add_events.h
index 4d1b226..b802d67 100644
--- a/modules/pua/add_events.h
+++ b/modules/pua/add_events.h
@@ -1,6 +1,4 @@
 /*
- * $Id: add_events.h  2007-05-03 15:05:20Z anca_vamanu $
- *
  * pua module - presence user agent module
  *
  * Copyright (C) 2007 Voice Sistem S.R.L.
@@ -21,7 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- *	initial version 2007-05-03 (anca)
  */
 #ifndef _PUA_ADD_EV_H_
 #define _PUA_ADD_EV_H_
diff --git a/modules/pua/doc/pua_admin.xml b/modules/pua/doc/pua_admin.xml
index f692786..7bb9cbb 100644
--- a/modules/pua/doc/pua_admin.xml
+++ b/modules/pua/doc/pua_admin.xml
@@ -197,7 +197,8 @@ modparam("pua", "update_period", 100)
 		<title><varname>outbound_proxy</varname> (str)</title>
 		<para>
 		SIP URI of outbound proxy to be used when sending
-		PUBLISH requests.
+		PUBLISH requests if no outbound proxy is given in
+                outbound_proxy field of struct publ_info.
 		</para>
 		<para>
 		<emphasis>By default, no outbound proxy has been defined.
@@ -286,6 +287,28 @@ modparam("pua", "db_mode", 0)
 		</example>
 	</section>
 	<section>
+	    <title><varname>db_table_lock_write</varname> (integer)</title>
+	    <para>
+		Enable (=1) or disable (=0) the Locks for table during an transaction.
+		Locking only the "current" table causes problems with a MySQL-Databases
+		in "DB-Only" mode.
+	    </para>
+	    <para>
+		<emphasis>
+		    Default value is 1 (Write Lock for the Tables).
+		</emphasis>
+	    </para>
+	    <example>
+		<title>Set <varname>db_table_lock_write</varname> parameter</title>
+		<programlisting format="linespecific">
+...
+modparam("pua", "db_table_lock_write", 0)
+...
+</programlisting>
+	    </example>
+	</section>
+	
+	<section>
 		<title><varname>check_remote_contact</varname> (int)</title>
 		<para>
 		When sending a SUBSCRIBE check that the remote contact matches the
diff --git a/modules/pua/doc/pua_devel.xml b/modules/pua/doc/pua_devel.xml
index 75014b4..d36c8d1 100644
--- a/modules/pua/doc/pua_devel.xml
+++ b/modules/pua/doc/pua_devel.xml
@@ -86,6 +86,8 @@ typedef struct publ_info
                           for that event)*/
   str* etag;          /*  (optional) the value of the etag the request
                           should match */
+  str* outbound_proxy;/*  outbound_proxy to use when sending the 
+                          Publish request */
   str* extra_headers  /*  (optional) extra_headers that should be added
                           to Publish msg*/
 }publ_info_t;
diff --git a/modules/pua/event_list.c b/modules/pua/event_list.c
index 91a513b..1bdf52e 100644
--- a/modules/pua/event_list.c
+++ b/modules/pua/event_list.c
@@ -1,6 +1,4 @@
 /*
- * $Id: event_list.c  2007-05-03 15:05:20Z anca_vamanu $
- *
  * pua module - presence user agent module
  *
  * Copyright (C) 2007 Voice Sistem S.R.L.
@@ -21,7 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- *	initial version 2007-05-03 (anca)
  */
 #include <stdio.h>
 #include <stdlib.h>
diff --git a/modules/pua/event_list.h b/modules/pua/event_list.h
index 6670e16..6df5df3 100644
--- a/modules/pua/event_list.h
+++ b/modules/pua/event_list.h
@@ -1,6 +1,4 @@
 /*
- * $Id: event_list.h  2007-05-03 15:05:20Z anca_vamanu $
- *
  * pua module - presence user agent module
  *
  * Copyright (C) 2007 Voice Sistem S.R.L.
@@ -21,7 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- *	initial version  2007-05-03 (anca)
  */
 
 #ifndef _PUA_EVLIST_H_
diff --git a/modules/pua/hash.c b/modules/pua/hash.c
index 93b9a89..2af436f 100644
--- a/modules/pua/hash.c
+++ b/modules/pua/hash.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * pua module - presence user agent module
  *
  * Copyright (C) 2006 Voice Sistem S.R.L.
diff --git a/modules/pua/hash.h b/modules/pua/hash.h
index af32d13..3da0894 100644
--- a/modules/pua/hash.h
+++ b/modules/pua/hash.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * pua module - presence user agent module
  *
  * Copyright (C) 2006 Voice Sistem S.R.L.
@@ -81,6 +79,7 @@ typedef struct ua_pres{
 	void* cb_param;
 	struct ua_pres* next;
 	int ua_flag;
+	str* outbound_proxy; /* croc-not sored in db_only mode */
 	
 	/* publish */
 	str etag;
@@ -96,7 +95,6 @@ typedef struct ua_pres{
 	int cseq;
 	int version;
 /*  int watcher_count; croc-nolonger used!! */
-	str* outbound_proxy; /* croc-not sored in db_only mode */
 	str* extra_headers;
 	str record_route;
 	str remote_contact;
diff --git a/modules/pua/pidf.c b/modules/pua/pidf.c
index 83b337a..6c3c288 100644
--- a/modules/pua/pidf.c
+++ b/modules/pua/pidf.c
@@ -1,6 +1,4 @@
 /*
- * $Id: pidf.c 1953 2007-04-04 08:50:33Z anca_vamanu $
- *
  * pua module
  *
  * Copyright (C) 2007 Voice Sistem S.R.L.
@@ -21,9 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2007-07-03  initial version (anca)
  */
 
 #include <string.h>
diff --git a/modules/pua/pidf.h b/modules/pua/pidf.h
index 54bdd80..63ccf35 100644
--- a/modules/pua/pidf.h
+++ b/modules/pua/pidf.h
@@ -1,6 +1,4 @@
 /*
- * $Id: pidf.h 1401 2006-12-14 11:12:42Z anca_vamanu $
- *
  * pua module
  *
  * Copyright (C) 2006 Voice Sistem S.R.L.
@@ -21,9 +19,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2007-07-03  initial version (anca)
  */
 
 #ifndef PUA_PIDF_H
diff --git a/modules/pua/pua.c b/modules/pua/pua.c
index e44a38d..06b3077 100644
--- a/modules/pua/pua.c
+++ b/modules/pua/pua.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * pua module - presence user agent module
  *
  * Copyright (C) 2006 Voice Sistem S.R.L.
@@ -21,9 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2006-11-29  initial version (anca)
  */
 
 
@@ -73,6 +68,9 @@ int reginfo_increase_version = 0;
 pua_event_t* pua_evlist= NULL;
 int dbmode = 0;
 
+int db_table_lock_write = 1;
+db_locking_t db_table_lock = DB_LOCKING_WRITE;
+
 int pua_fetch_rows = 500;
 
 /* database connection */
@@ -134,6 +132,7 @@ static param_export_t params[]={
 	{"check_remote_contact",     INT_PARAM, &check_remote_contact},
 	{"db_mode",                  INT_PARAM, &dbmode},
 	{"fetch_rows",               INT_PARAM, &pua_fetch_rows},
+	{"db_table_lock_write",     INT_PARAM, &db_table_lock_write},
 	{0,                          0,         0}
 };
 
@@ -280,10 +279,13 @@ static int mod_init(void)
 			register_timer(db_update, 0, update_period);
 	}
 
+	if (db_table_lock_write != 1)
+		db_table_lock = DB_LOCKING_NONE;
+	
 	if(pua_db)
 		pua_dbf.close(pua_db);
 	pua_db = NULL;
-
+	
 	return 0;
 }
 
diff --git a/modules/pua/pua.h b/modules/pua/pua.h
index 695f3fd..2295c29 100644
--- a/modules/pua/pua.h
+++ b/modules/pua/pua.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * pua module - presence user agent module
  *
  * Copyright (C) 2006 Voice Sistem S.R.L.
diff --git a/modules/pua/pua_bind.c b/modules/pua/pua_bind.c
index e8f80ef..80d5c9c 100644
--- a/modules/pua/pua_bind.c
+++ b/modules/pua/pua_bind.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * pua module - presence user agent module
  *
  * Copyright (C) 2006 Voice Sistem S.R.L.
diff --git a/modules/pua/pua_bind.h b/modules/pua/pua_bind.h
index ea8933f..35c208e 100644
--- a/modules/pua/pua_bind.h
+++ b/modules/pua/pua_bind.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * pua module - presence user agent module
  *
  * Copyright (C) 2006 Voice Sistem S.R.L.
diff --git a/modules/pua/pua_callback.c b/modules/pua/pua_callback.c
index 9741270..c231c1d 100644
--- a/modules/pua/pua_callback.c
+++ b/modules/pua/pua_callback.c
@@ -1,6 +1,4 @@
 /*
- * $Id: pua_callback.c,v 1.2 2007/02/20 13:40:09 anca_vamanu Exp $
- *
  * pua module - presence user agent module
  *
  * Copyright (C) 2007 Voice Sistem S.R.L.
diff --git a/modules/pua/pua_callback.h b/modules/pua/pua_callback.h
index 4b88598..68ee36f 100644
--- a/modules/pua/pua_callback.h
+++ b/modules/pua/pua_callback.h
@@ -1,6 +1,4 @@
 /*
- * $Id: pua_callback.c,v 1.2 2007/02/20 13:40:09 anca_vamanu Exp $
- *
  * pua module - presence user agent module
  *
  * Copyright (C) 2007 Voice Sistem S.R.L.
diff --git a/modules/pua/pua_db.c b/modules/pua/pua_db.c
index 4a10fff..7297d4a 100644
--- a/modules/pua/pua_db.c
+++ b/modules/pua/pua_db.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * pua db - presence user agent database support 
  *
  * Copyright (C) 2011 Crocodile RCS Ltd
diff --git a/modules/pua/pua_db.h b/modules/pua/pua_db.h
index 02f0a10..c5e7a0b 100644
--- a/modules/pua/pua_db.h
+++ b/modules/pua/pua_db.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * pua_db headers - presence user agent db headers
  *
  * Copyright (C) 2011 Crocodile RCS Ltd
diff --git a/modules/pua/send_publish.c b/modules/pua/send_publish.c
index b0d540c..a7bb09e 100644
--- a/modules/pua/send_publish.c
+++ b/modules/pua/send_publish.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * pua module - presence user agent module
  *
  * Copyright (C) 2006 Voice Sistem S.R.L.
@@ -21,9 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2006-11-29  initial version (anca)
  */
 
 
@@ -49,6 +44,8 @@
 #include "event_list.h"
 #include "pua_db.h"
 
+extern db_locking_t db_table_lock;
+
 str* publ_build_hdr(int expires, pua_event_t* ev, str* content_type, str* etag,
 		str* extra_headers, int is_body)
 {
@@ -216,7 +213,7 @@ void publ_cback_func(struct cell *t, int type, struct tmcb_params *ps)
 
 	if (dbmode == PUA_DB_ONLY && pua_dbf.start_transaction)
 	{
-		if (pua_dbf.start_transaction(pua_db, DB_LOCKING_WRITE) < 0)
+		if (pua_dbf.start_transaction(pua_db, db_table_lock) < 0)
 		{
 			LM_ERR("in start_transaction\n");
 			goto error;
@@ -274,6 +271,7 @@ void publ_cback_func(struct cell *t, int type, struct tmcb_params *ps)
 			publ.content_type= hentity->content_type;	
 			publ.id= hentity->id;
 			publ.extra_headers= hentity->extra_headers;
+			publ.outbound_proxy = hentity->outbound_proxy;
 			publ.cb_param= hentity->cb_param;
 
 			if (dbmode == PUA_DB_ONLY && pua_dbf.end_transaction)
@@ -501,7 +499,7 @@ int send_publish( publ_info_t* publ )
 	
 	if (dbmode == PUA_DB_ONLY && pua_dbf.start_transaction)
 	{
-		if (pua_dbf.start_transaction(pua_db, DB_LOCKING_WRITE) < 0)
+		if (pua_dbf.start_transaction(pua_db, db_table_lock) < 0)
 		{
 			LM_ERR("in start_transaction\n");
 			goto error;
@@ -692,8 +690,9 @@ send_publish:
 	result= tmb.t_request(&uac_r,
 			publ->pres_uri,			/*! Request-URI */
 			publ->pres_uri,			/*! To */
-			publ->pres_uri,			/*! From */
-			&outbound_proxy		/*! Outbound proxy*/
+ 		        publ->pres_uri,			/*! From */
+		        publ->outbound_proxy?
+			      publ->outbound_proxy:&outbound_proxy /*! Outbound proxy*/
 			);
 
 	if(result< 0)
@@ -756,6 +755,9 @@ ua_pres_t* publish_cbparam(publ_info_t* publ,str* body,str* tuple_id,
 
 	size= sizeof(ua_pres_t)+ sizeof(str)+ (publ->pres_uri->len+ 
 		+ publ->content_type.len+ publ->id.len+ 1)*sizeof(char);
+
+	if(publ->outbound_proxy)
+		size+= sizeof(str)+ publ->outbound_proxy->len* sizeof(char);
 	if(body && body->s && body->len)
 		size+= sizeof(str)+ body->len* sizeof(char);
 	if(publ->etag)
@@ -821,6 +823,16 @@ ua_pres_t* publish_cbparam(publ_info_t* publ,str* body,str* tuple_id,
 		cb_param->extra_headers->len= publ->extra_headers->len;
 		size+= publ->extra_headers->len;
 	}	
+	if(publ->outbound_proxy)
+	{
+		cb_param->outbound_proxy = (str*)((char*)cb_param + size);
+		size += sizeof(str);
+		cb_param->outbound_proxy->s = (char*)cb_param + size;
+		memcpy(cb_param->outbound_proxy->s, publ->outbound_proxy->s,
+		       publ->outbound_proxy->len);
+		cb_param->outbound_proxy->len = publ->outbound_proxy->len;
+		size+= publ->outbound_proxy->len;
+	}	
 
 	if(publ->content_type.s && publ->content_type.len)
 	{
@@ -836,6 +848,7 @@ ua_pres_t* publish_cbparam(publ_info_t* publ,str* body,str* tuple_id,
 		cb_param->tuple_id.len= tuple_id->len;
 		size+= tuple_id->len;
 	}
+
 	cb_param->event= publ->event;
 	cb_param->flag|= publ->source_flag;
 	cb_param->cb_param= publ->cb_param;
diff --git a/modules/pua/send_publish.h b/modules/pua/send_publish.h
index ef81ee9..426c6d7 100644
--- a/modules/pua/send_publish.h
+++ b/modules/pua/send_publish.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * pua module - presence user agent module
  *
  * Copyright (C) 2006 Voice Sistem S.R.L.
@@ -44,6 +42,7 @@ typedef struct publ_info
 	str content_type;  /*! the content_type of the body if present(optional if the
 				same as the default value for that event) */
 	str* etag;
+	str* outbound_proxy;
 	str* extra_headers;
 	void* cb_param;   /*! the parameter for the function to be called on the callback 
 				for the received reply; it must be allocated in share memory;
diff --git a/modules/pua/send_subscribe.c b/modules/pua/send_subscribe.c
index 5f4b0b8..84b69f8 100644
--- a/modules/pua/send_subscribe.c
+++ b/modules/pua/send_subscribe.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * pua module - presence user agent module
  *
  * Copyright (C) 2006 Voice Sistem S.R.L.
@@ -48,6 +46,7 @@
 #include "pua_db.h"
 #include "../presence/subscribe.h"
 
+extern db_locking_t db_table_lock;
 
 void print_subs(subs_info_t* subs)
 {
@@ -301,7 +300,7 @@ void subs_cback_func(struct cell *t, int cb_type, struct tmcb_params *ps)
 
 	if (dbmode == PUA_DB_ONLY && pua_dbf.start_transaction)
 	{
-		if (pua_dbf.start_transaction(pua_db, DB_LOCKING_WRITE) < 0)
+		if (pua_dbf.start_transaction(pua_db, db_table_lock) < 0)
 		{
 			LM_ERR("in start_transaction\n");
 			goto error;
@@ -687,7 +686,7 @@ faked_error:
 
 		if (pua_dbf.start_transaction)
 		{
-			if (pua_dbf.start_transaction(pua_db, DB_LOCKING_WRITE) < 0)
+			if (pua_dbf.start_transaction(pua_db, db_table_lock) < 0)
 			{
 				LM_ERR("in start_transaction\n");
 				goto error;
@@ -986,7 +985,7 @@ int send_subscribe(subs_info_t* subs)
 
 	if (dbmode == PUA_DB_ONLY && pua_dbf.start_transaction)
 	{
-		if (pua_dbf.start_transaction(pua_db, DB_LOCKING_WRITE) < 0)
+		if (pua_dbf.start_transaction(pua_db, db_table_lock) < 0)
 		{
 			LM_ERR("in start_transaction\n");
 			goto error;
diff --git a/modules/pua/send_subscribe.h b/modules/pua/send_subscribe.h
index 6c7e721..2cd8e28 100644
--- a/modules/pua/send_subscribe.h
+++ b/modules/pua/send_subscribe.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * pua module - presence user agent module
  *
  * Copyright (C) 2006 Voice Sistem S.R.L.
diff --git a/modules/pua_dialoginfo/README b/modules/pua_dialoginfo/README
index 4f685fc..9a674aa 100644
--- a/modules/pua_dialoginfo/README
+++ b/modules/pua_dialoginfo/README
@@ -47,6 +47,8 @@ Klaus Darilion
               5.7. use_pubruri_avps (int)
               5.8. pubruri_caller_avp (int)
               5.9. pubruri_callee_avp (int)
+              5.10. pubruri_caller_dlg_var (str)
+              5.11. pubruri_callee_dlg_var (int)
 
         6. Functions
 
@@ -61,6 +63,8 @@ Klaus Darilion
    1.7. Set use_pubruri_avps parameter
    1.8. Set pubruri_caller_avp parameter
    1.9. Set pubruri_callee_avp parameter
+   1.10. Set pubruri_caller_avp parameter
+   1.11. Set pubruri_callee_dlg_var parameter
 
 Chapter 1. Admin Guide
 
@@ -85,6 +89,8 @@ Chapter 1. Admin Guide
         5.7. use_pubruri_avps (int)
         5.8. pubruri_caller_avp (int)
         5.9. pubruri_callee_avp (int)
+        5.10. pubruri_caller_dlg_var (str)
+        5.11. pubruri_callee_dlg_var (int)
 
    6. Functions
 
@@ -262,6 +268,8 @@ Chapter 1. Admin Guide
    5.7. use_pubruri_avps (int)
    5.8. pubruri_caller_avp (int)
    5.9. pubruri_callee_avp (int)
+   5.10. pubruri_caller_dlg_var (str)
+   5.11. pubruri_callee_dlg_var (int)
 
 5.1. include_callid (int)
 
@@ -392,4 +400,32 @@ modparam("pua_dialoginfo", "pubruri_caller_avp", "$avp(s:puburis_caller)")
 modparam("pua_dialoginfo", "pubruri_callee_avp", "$avp(s:puburis_callee)")
 ...
 
+5.10. pubruri_caller_dlg_var (str)
+
+   Must be set to the name of dialog variable where to store the URI for
+   caller, used to send the notifications. This is needed to restored the
+   value after Kamailio restart. If not set, loaded dialogs at restart are
+   no longer sending notifications. New dialogs are working fine.
+
+   Default value is "NULL".
+
+   Example 1.10. Set pubruri_caller_avp parameter
+...
+modparam("pua_dialoginfo", "pubruri_caller_dlg_var", "pubruri_caller")
+...
+
+5.11. pubruri_callee_dlg_var (int)
+
+   Must be set to the name of dialog variable where to store the URI for
+   callee, used to send the notifications. This is needed to restored the
+   value after Kamailio restart. If not set, loaded dialogs at restart are
+   no longer sending notifications. New dialogs are working fine.
+
+   Default value is "NULL".
+
+   Example 1.11. Set pubruri_callee_dlg_var parameter
+...
+modparam("pua_dialoginfo", "pubruri_callee_dlg_var", "pubruri_callee")
+...
+
 6. Functions
diff --git a/modules/pua_dialoginfo/doc/pua_dialoginfo_admin.xml b/modules/pua_dialoginfo/doc/pua_dialoginfo_admin.xml
index 6864a00..e08402d 100644
--- a/modules/pua_dialoginfo/doc/pua_dialoginfo_admin.xml
+++ b/modules/pua_dialoginfo/doc/pua_dialoginfo_admin.xml
@@ -416,7 +416,51 @@ modparam("pua_dialoginfo", "pubruri_callee_avp", "$avp(s:puburis_callee)")
 </programlisting>
 		</example>
 		</section>
+
+		<section id="pua_dialoginfo.p.pubruri_caller_dlg_var">
+		<title><varname>pubruri_caller_dlg_var</varname> (str)</title>
+		<para>
+			Must be set to the name of dialog variable where to store
+			the URI for caller, used to send the notifications. This is needed
+			to restored the value after &kamailio; restart. If not set, loaded
+			dialogs at restart are no longer sending notifications. New dialogs
+			are working fine.
+		</para>
+		<para>
+			<emphasis>Default value is <quote>NULL</quote>.</emphasis>
+		</para>
+		<example>
+			<title>Set <varname>pubruri_caller_avp</varname> parameter</title>
+			<programlisting format="linespecific">
+...
+modparam("pua_dialoginfo", "pubruri_caller_dlg_var", "pubruri_caller")
+...
+</programlisting>
+		</example>
+		</section>
 		
+		<section id="pua_dialoginfo.p.pubruri_callee_dlg_var">
+		<title><varname>pubruri_callee_dlg_var</varname> (int)</title>
+		<para>
+			Must be set to the name of dialog variable where to store
+			the URI for callee, used to send the notifications. This is needed
+			to restored the value after &kamailio; restart. If not set, loaded
+			dialogs at restart are no longer sending notifications. New dialogs
+			are working fine.
+		</para>
+		<para>
+			<emphasis>Default value is <quote>NULL</quote>.</emphasis>
+		</para>
+		<example>
+			<title>Set <varname>pubruri_callee_dlg_var</varname> parameter</title>
+			<programlisting format="linespecific">
+...
+modparam("pua_dialoginfo", "pubruri_callee_dlg_var", "pubruri_callee")
+...
+</programlisting>
+		</example>
+		</section>
+
 	</section>
 
 	<section>
diff --git a/modules/pua_dialoginfo/pua_dialoginfo.c b/modules/pua_dialoginfo/pua_dialoginfo.c
index 0665cdc..de53e0f 100644
--- a/modules/pua_dialoginfo/pua_dialoginfo.c
+++ b/modules/pua_dialoginfo/pua_dialoginfo.c
@@ -1,6 +1,4 @@
 /*
- * $Id: pua_usrloc.c 4657 2008-08-10 22:51:44Z henningw $
- *
  * pua_dialoginfo module - publish dialog-info from dialo module
  *
  * Copyright (C) 2006 Voice Sistem S.R.L.
@@ -81,6 +79,9 @@ int_str pubruri_caller_avp_name;
 unsigned short pubruri_callee_avp_type;
 int_str pubruri_callee_avp_name;
 
+static str caller_dlg_var = {0, 0}; /* pubruri_caller */
+static str callee_dlg_var = {0, 0}; /* pubruri_callee */
+
 /* Module parameter variables */
 int include_callid         = DEF_INCLUDE_CALLID;
 int include_localremote    = DEF_INCLUDE_LOCALREMOTE;
@@ -116,6 +117,8 @@ static param_export_t params[]={
 	{"use_pubruri_avps",    INT_PARAM, &use_pubruri_avps },
 	{"pubruri_caller_avp",  PARAM_STRING, &pubruri_caller_avp },
 	{"pubruri_callee_avp",  PARAM_STRING, &pubruri_callee_avp },
+	{"pubruri_caller_dlg_var",  PARAM_STR, &caller_dlg_var },
+	{"pubruri_callee_dlg_var",  PARAM_STR, &callee_dlg_var },
 	{0, 0, 0 }
 };
 
@@ -141,12 +144,16 @@ __dialog_cbtest(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params)
 {
 	str tag;
 	struct sip_msg *msg;
-	LM_ERR("dialog callback received, from=%.*s, to=%.*s\n", dlg->from_uri.len, dlg->from_uri.s, dlg->to_uri.len, dlg->to_uri.s);
+	LM_ERR("dialog callback received, from=%.*s, to=%.*s\n",
+			dlg->from_uri.len, dlg->from_uri.s, dlg->to_uri.len,
+			dlg->to_uri.s);
 	if (dlg->tag[0].len && dlg->tag[0].s ) {
-		LM_ERR("dialog callback: tag[0] = %.*s", dlg->tag[0].len, dlg->tag[0].s);
+		LM_ERR("dialog callback: tag[0] = %.*s",
+				dlg->tag[0].len, dlg->tag[0].s);
 	}
 	if (dlg->tag[0].len && dlg->tag[1].s ) {
-		LM_ERR("dialog callback: tag[1] = %.*s", dlg->tag[1].len, dlg->tag[1].s);
+		LM_ERR("dialog callback: tag[1] = %.*s",
+				dlg->tag[1].len, dlg->tag[1].s);
 	}
 
 	if (type != DLGCB_DESTROY) {
@@ -167,7 +174,7 @@ __dialog_cbtest(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params)
 				tag.len = 0;
 			} else if (!msg->to) {
 				// to header still not defined
-				LM_ERR("no to although to-header is parsed: bad reply or missing TO hdr :-/\n");
+				LM_ERR("bad reply or missing TO header\n");
 				tag.s = 0;
 				tag.len = 0;
 			} else 
@@ -181,46 +188,59 @@ __dialog_cbtest(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params)
 			}
 		}
 		if (tag.s) {
-			LM_ERR("dialog callback: msg->to->parsed->tag_value = %.*s", tag.len, tag.s);
+			LM_ERR("dialog callback: msg->to->parsed->tag_value = %.*s",
+					tag.len, tag.s);
 		}
 	}
 
 	switch (type) {
-	case DLGCB_FAILED:
-		LM_ERR("dialog callback type 'DLGCB_FAILED' received, from=%.*s\n", dlg->from_uri.len, dlg->from_uri.s);
-		break;
-	case DLGCB_CONFIRMED_NA:
-		LM_ERR("dialog callback type 'DLGCB_CONFIRMED_NA' received, from=%.*s\n", dlg->from_uri.len, dlg->from_uri.s);
-		break;
-	case DLGCB_CONFIRMED:
-		LM_ERR("dialog callback type 'DLGCB_CONFIRMED' received, from=%.*s\n", dlg->from_uri.len, dlg->from_uri.s);
-		break;
-	case DLGCB_REQ_WITHIN:
-		LM_ERR("dialog callback type 'DLGCB_REQ_WITHIN' received, from=%.*s\n", dlg->from_uri.len, dlg->from_uri.s);
-		break;
-	case DLGCB_TERMINATED:
-		LM_ERR("dialog callback type 'DLGCB_TERMINATED' received, from=%.*s\n", dlg->from_uri.len, dlg->from_uri.s);
-		break;
-	case DLGCB_EXPIRED:
-		LM_ERR("dialog callback type 'DLGCB_EXPIRED' received, from=%.*s\n", dlg->from_uri.len, dlg->from_uri.s);
-		break;
-	case DLGCB_EARLY:
-		LM_ERR("dialog callback type 'DLGCB_EARLY' received, from=%.*s\n", dlg->from_uri.len, dlg->from_uri.s);
-		break;
-	case DLGCB_RESPONSE_FWDED:
-		LM_ERR("dialog callback type 'DLGCB_RESPONSE_FWDED' received, from=%.*s\n", dlg->from_uri.len, dlg->from_uri.s);
-		break;
-	case DLGCB_RESPONSE_WITHIN:
-		LM_ERR("dialog callback type 'DLGCB_RESPONSE_WITHIN' received, from=%.*s\n", dlg->from_uri.len, dlg->from_uri.s);
-		break;
-	case DLGCB_MI_CONTEXT:
-		LM_ERR("dialog callback type 'DLGCB_MI_CONTEXT' received, from=%.*s\n", dlg->from_uri.len, dlg->from_uri.s);
-		break;
-	case DLGCB_DESTROY:
-		LM_ERR("dialog callback type 'DLGCB_DESTROY' received, from=%.*s\n", dlg->from_uri.len, dlg->from_uri.s);
-		break;
-	default:
-		LM_ERR("dialog callback type 'unknown' received, from=%.*s\n", dlg->from_uri.len, dlg->from_uri.s);
+		case DLGCB_FAILED:
+			LM_ERR("dialog callback type 'DLGCB_FAILED' received, from=%.*s\n",
+					dlg->from_uri.len, dlg->from_uri.s);
+			break;
+		case DLGCB_CONFIRMED_NA:
+			LM_ERR("dialog callback type 'DLGCB_CONFIRMED_NA' received, from=%.*s\n",
+					dlg->from_uri.len, dlg->from_uri.s);
+			break;
+		case DLGCB_CONFIRMED:
+			LM_ERR("dialog callback type 'DLGCB_CONFIRMED' received, from=%.*s\n",
+					dlg->from_uri.len, dlg->from_uri.s);
+			break;
+		case DLGCB_REQ_WITHIN:
+			LM_ERR("dialog callback type 'DLGCB_REQ_WITHIN' received, from=%.*s\n",
+					dlg->from_uri.len, dlg->from_uri.s);
+			break;
+		case DLGCB_TERMINATED:
+			LM_ERR("dialog callback type 'DLGCB_TERMINATED' received, from=%.*s\n",
+					dlg->from_uri.len, dlg->from_uri.s);
+			break;
+		case DLGCB_EXPIRED:
+			LM_ERR("dialog callback type 'DLGCB_EXPIRED' received, from=%.*s\n",
+					dlg->from_uri.len, dlg->from_uri.s);
+			break;
+		case DLGCB_EARLY:
+			LM_ERR("dialog callback type 'DLGCB_EARLY' received, from=%.*s\n",
+					dlg->from_uri.len, dlg->from_uri.s);
+			break;
+		case DLGCB_RESPONSE_FWDED:
+			LM_ERR("dialog callback type 'DLGCB_RESPONSE_FWDED' received, from=%.*s\n",
+					dlg->from_uri.len, dlg->from_uri.s);
+			break;
+		case DLGCB_RESPONSE_WITHIN:
+			LM_ERR("dialog callback type 'DLGCB_RESPONSE_WITHIN' received, from=%.*s\n",
+					dlg->from_uri.len, dlg->from_uri.s);
+			break;
+		case DLGCB_MI_CONTEXT:
+			LM_ERR("dialog callback type 'DLGCB_MI_CONTEXT' received, from=%.*s\n",
+					dlg->from_uri.len, dlg->from_uri.s);
+			break;
+		case DLGCB_DESTROY:
+			LM_ERR("dialog callback type 'DLGCB_DESTROY' received, from=%.*s\n",
+					dlg->from_uri.len, dlg->from_uri.s);
+			break;
+		default:
+			LM_ERR("dialog callback type 'unknown' received, from=%.*s\n",
+					dlg->from_uri.len, dlg->from_uri.s);
 	}
 }
 #endif
@@ -242,70 +262,114 @@ __dialog_sendpublish(struct dlg_cell *dlg, int type, struct dlg_cb_params *_para
 	}
 
 	switch (type) {
-	case DLGCB_FAILED:
-	case DLGCB_TERMINATED:
-	case DLGCB_EXPIRED:
-		LM_DBG("dialog over, from=%.*s\n", dlginfo->from_uri.len, dlginfo->from_uri.s);
-		dialog_publish_multi("terminated", dlginfo->pubruris_caller, &(dlginfo->from_uri), &uri, &(dlginfo->callid), 1, dlginfo->lifetime, 0, 0, &(dlginfo->from_contact), &target, send_publish_flag==-1?1:0);
-		dialog_publish_multi("terminated", dlginfo->pubruris_callee, &uri, &(dlginfo->from_uri), &(dlginfo->callid), 0, dlginfo->lifetime, 0, 0, &target, &(dlginfo->from_contact), send_publish_flag==-1?1:0);
-		break;
-	case DLGCB_CONFIRMED:
-	case DLGCB_REQ_WITHIN:
-	case DLGCB_CONFIRMED_NA:
-		LM_DBG("dialog confirmed, from=%.*s\n", dlginfo->from_uri.len, dlginfo->from_uri.s);
-		dialog_publish_multi("confirmed", dlginfo->pubruris_caller, &(dlginfo->from_uri), &uri, &(dlginfo->callid), 1, dlginfo->lifetime, 0, 0, &(dlginfo->from_contact), &target, send_publish_flag==-1?1:0);
-		dialog_publish_multi("confirmed", dlginfo->pubruris_callee, &uri, &(dlginfo->from_uri), &(dlginfo->callid), 0, dlginfo->lifetime, 0, 0, &target, &(dlginfo->from_contact), send_publish_flag==-1?1:0);
-		break;
-	case DLGCB_EARLY:
-		LM_DBG("dialog is early, from=%.*s\n", dlginfo->from_uri.len, dlginfo->from_uri.s);
-		if (include_tags) {
-			/* get remotetarget */
-			if ( !_params->rpl->contact && ((parse_headers(_params->rpl, HDR_CONTACT_F,0)<0) || !_params->rpl->contact) ) {
-				LM_ERR("bad reply or missing CONTACT hdr\n");
-			} else {
-				if ( parse_contact(_params->rpl->contact)<0 ||
-						((contact_body_t *)_params->rpl->contact->parsed)->contacts==NULL ||
-						((contact_body_t *)_params->rpl->contact->parsed)->contacts->next!=NULL ) {
-					LM_ERR("Malformed CONTACT hdr\n");
+		case DLGCB_FAILED:
+		case DLGCB_TERMINATED:
+		case DLGCB_EXPIRED:
+			LM_DBG("dialog over, from=%.*s\n", dlginfo->from_uri.len,
+					dlginfo->from_uri.s);
+			dialog_publish_multi("terminated", dlginfo->pubruris_caller,
+					&(dlginfo->from_uri), &uri, &(dlginfo->callid), 1,
+					10, 0, 0, &(dlginfo->from_contact),
+					&target, send_publish_flag==-1?1:0);
+			dialog_publish_multi("terminated", dlginfo->pubruris_callee,
+					&uri, &(dlginfo->from_uri), &(dlginfo->callid), 0,
+					10, 0, 0, &target, &(dlginfo->from_contact),
+					send_publish_flag==-1?1:0);
+			break;
+		case DLGCB_CONFIRMED:
+		case DLGCB_REQ_WITHIN:
+		case DLGCB_CONFIRMED_NA:
+			LM_DBG("dialog confirmed, from=%.*s\n", dlginfo->from_uri.len,
+					dlginfo->from_uri.s);
+			dialog_publish_multi("confirmed", dlginfo->pubruris_caller,
+					&(dlginfo->from_uri), &uri, &(dlginfo->callid), 1,
+					dlginfo->lifetime, 0, 0, &(dlginfo->from_contact), &target,
+					send_publish_flag==-1?1:0);
+			dialog_publish_multi("confirmed", dlginfo->pubruris_callee, &uri,
+					&(dlginfo->from_uri), &(dlginfo->callid), 0,
+					dlginfo->lifetime, 0, 0, &target, &(dlginfo->from_contact),
+					send_publish_flag==-1?1:0);
+			break;
+		case DLGCB_EARLY:
+			LM_DBG("dialog is early, from=%.*s\n", dlginfo->from_uri.len,
+					dlginfo->from_uri.s);
+			if (include_tags) {
+				/* get remotetarget */
+				if ( !_params->rpl->contact && ((parse_headers(_params->rpl,
+									HDR_CONTACT_F,0)<0) || !_params->rpl->contact) ) {
+					LM_ERR("bad reply or missing CONTACT hdr\n");
 				} else {
-					target = ((contact_body_t *)_params->rpl->contact->parsed)->contacts->uri;
+					if ( parse_contact(_params->rpl->contact)<0 ||
+							((contact_body_t *)_params->rpl->contact->parsed)->contacts==NULL ||
+							((contact_body_t *)_params->rpl->contact->parsed)->contacts->next!=NULL ) {
+						LM_ERR("Malformed CONTACT hdr\n");
+					} else {
+						target = ((contact_body_t *)_params->rpl->contact->parsed)->contacts->uri;
+					}
 				}
-			}
-			/* get to tag*/
-			if ( !_params->rpl->to && ((parse_headers(_params->rpl, HDR_TO_F,0)<0) || !_params->rpl->to) ) {
-				LM_ERR("bad reply or missing TO hdr :-/\n");
-				tag.s = 0;
-				tag.len = 0;
-			} else {
-				tag = get_to(_params->rpl)->tag_value;
-				if (tag.s==0 || tag.len==0) {
-					LM_ERR("missing TAG param in TO hdr :-/\n");
+				/* get to tag*/
+				if ( !_params->rpl->to && ((parse_headers(_params->rpl, HDR_TO_F,0)<0)
+							|| !_params->rpl->to) ) {
+					LM_ERR("bad reply or missing TO hdr :-/\n");
 					tag.s = 0;
 					tag.len = 0;
+				} else {
+					tag = get_to(_params->rpl)->tag_value;
+					if (tag.s==0 || tag.len==0) {
+						LM_ERR("missing TAG param in TO hdr :-/\n");
+						tag.s = 0;
+						tag.len = 0;
+					}
 				}
-			}
-			if (caller_confirmed) {
-				dialog_publish_multi("confirmed", dlginfo->pubruris_caller, &(dlginfo->from_uri), &uri, &(dlginfo->callid), 1, dlginfo->lifetime, &(dlginfo->from_tag), &tag, &(dlginfo->from_contact), &target, send_publish_flag==-1?1:0);
+				if (caller_confirmed) {
+					dialog_publish_multi("confirmed", dlginfo->pubruris_caller,
+							&(dlginfo->from_uri), &uri, &(dlginfo->callid), 1,
+							dlginfo->lifetime, &(dlginfo->from_tag), &tag,
+							&(dlginfo->from_contact), &target,
+							send_publish_flag==-1?1:0);
+				} else {
+					dialog_publish_multi("early", dlginfo->pubruris_caller,
+							&(dlginfo->from_uri), &uri, &(dlginfo->callid), 1,
+							dlginfo->lifetime, &(dlginfo->from_tag), &tag,
+							&(dlginfo->from_contact), &target,
+							send_publish_flag==-1?1:0);
+				}
+				dialog_publish_multi("early", dlginfo->pubruris_callee, &uri,
+						&(dlginfo->from_uri), &(dlginfo->callid), 0,
+						dlginfo->lifetime, &tag, &(dlginfo->from_tag), &target,
+						&(dlginfo->from_contact), send_publish_flag==-1?1:0);
+
 			} else {
-				dialog_publish_multi("early", dlginfo->pubruris_caller, &(dlginfo->from_uri), &uri, &(dlginfo->callid), 1, dlginfo->lifetime, &(dlginfo->from_tag), &tag, &(dlginfo->from_contact), &target, send_publish_flag==-1?1:0);
-			}
-			dialog_publish_multi("early", dlginfo->pubruris_callee, &uri, &(dlginfo->from_uri), &(dlginfo->callid), 0, dlginfo->lifetime, &tag, &(dlginfo->from_tag), &target, &(dlginfo->from_contact), send_publish_flag==-1?1:0);
+				if (caller_confirmed) {
+					dialog_publish_multi("confirmed", dlginfo->pubruris_caller,
+							&(dlginfo->from_uri), &uri, &(dlginfo->callid), 1,
+							dlginfo->lifetime, 0, 0, &(dlginfo->from_contact),
+							&target, send_publish_flag==-1?1:0);
 
-		} else {
-			if (caller_confirmed) {
-				dialog_publish_multi("confirmed", dlginfo->pubruris_caller, &(dlginfo->from_uri), &uri, &(dlginfo->callid), 1, dlginfo->lifetime, 0, 0, &(dlginfo->from_contact), &target, send_publish_flag==-1?1:0);
+				} else {
+					dialog_publish_multi("early", dlginfo->pubruris_caller,
+							&(dlginfo->from_uri), &uri, &(dlginfo->callid), 1,
+							dlginfo->lifetime, 0, 0, &(dlginfo->from_contact),
+							&target, send_publish_flag==-1?1:0);
+				}
+				dialog_publish_multi("early", dlginfo->pubruris_callee, &uri,
+						&(dlginfo->from_uri), &(dlginfo->callid), 0,
+						dlginfo->lifetime, 0, 0, &target,
+						&(dlginfo->from_contact), send_publish_flag==-1?1:0);
 
-			} else {
-				dialog_publish_multi("early", dlginfo->pubruris_caller, &(dlginfo->from_uri), &uri, &(dlginfo->callid), 1, dlginfo->lifetime, 0, 0, &(dlginfo->from_contact), &target, send_publish_flag==-1?1:0);
 			}
-			dialog_publish_multi("early", dlginfo->pubruris_callee, &uri, &(dlginfo->from_uri), &(dlginfo->callid), 0, dlginfo->lifetime, 0, 0, &target, &(dlginfo->from_contact), send_publish_flag==-1?1:0);
-
-		}
-		break;
-	default:
-		LM_ERR("unhandled dialog callback type %d received, from=%.*s\n", type, dlginfo->from_uri.len, dlginfo->from_uri.s);
-		dialog_publish_multi("terminated", dlginfo->pubruris_caller, &(dlginfo->from_uri), &uri, &(dlginfo->callid), 1, dlginfo->lifetime, 0, 0, &(dlginfo->from_contact), &target, send_publish_flag==-1?1:0);
-		dialog_publish_multi("terminated", dlginfo->pubruris_callee, &uri, &(dlginfo->from_uri), &(dlginfo->callid), 0, dlginfo->lifetime, 0, 0, &target, &(dlginfo->from_contact), send_publish_flag==-1?1:0);
+			break;
+		default:
+			LM_ERR("unhandled dialog callback type %d received, from=%.*s\n",
+					type, dlginfo->from_uri.len, dlginfo->from_uri.s);
+			dialog_publish_multi("terminated", dlginfo->pubruris_caller,
+					&(dlginfo->from_uri), &uri, &(dlginfo->callid), 1,
+					10, 0, 0, &(dlginfo->from_contact), &target,
+					send_publish_flag==-1?1:0);
+			dialog_publish_multi("terminated", dlginfo->pubruris_callee, &uri,
+					&(dlginfo->from_uri), &(dlginfo->callid), 0,
+					10, 0, 0, &target, &(dlginfo->from_contact),
+					send_publish_flag==-1?1:0);
 
 	}
 }
@@ -359,34 +423,25 @@ struct str_list* get_str_list(unsigned short avp_flags, int_str avp_name) {
 
 }
 
-static void
-__dialog_created(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params)
+struct dlginfo_cell* get_dialog_data(struct dlg_cell *dlg, int type)
 {
-	struct sip_msg *request = _params->req;
 	struct dlginfo_cell *dlginfo;
 	int len;
-
-	if (request->REQ_METHOD != METHOD_INVITE)
-		return;
-
-	if(send_publish_flag > -1 && !(request->flags & (1<<send_publish_flag)))
-		return;
-
-	LM_DBG("new INVITE dialog created: from=%.*s\n", dlg->from_uri.len, dlg->from_uri.s);
+	str* s=NULL;
 
 	/* create dlginfo structure to store important data inside the module*/
-	len = sizeof(struct dlginfo_cell) + 
-			dlg->from_uri.len + 
-			dlg->to_uri.len + 
-			dlg->callid.len + 
-			dlg->tag[0].len +
-			dlg->req_uri.len +
-			dlg->contact[0].len;
+	len = sizeof(struct dlginfo_cell)
+		+ dlg->from_uri.len
+		+ dlg->to_uri.len
+		+ dlg->callid.len
+		+ dlg->tag[0].len
+		+ dlg->req_uri.len
+		+ dlg->contact[0].len;
 
 	dlginfo = (struct dlginfo_cell*)shm_malloc( len );
 	if (dlginfo==0) {
 		LM_ERR("no more shm mem (%d)\n",len);
-		return;
+		return NULL;
 	}
 	memset( dlginfo, 0, len);
 
@@ -413,28 +468,75 @@ __dialog_created(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params)
 	memcpy(dlginfo->from_contact.s, dlg->contact[0].s, dlg->contact[0].len);
 
 	if (use_pubruri_avps) {
+		if(type==DLGCB_CREATED) {
+			dlginfo->pubruris_caller = get_str_list(pubruri_caller_avp_type,
+					pubruri_caller_avp_name);
+			dlginfo->pubruris_callee = get_str_list(pubruri_callee_avp_type,
+					pubruri_callee_avp_name);
 
-		dlginfo->pubruris_caller = get_str_list(pubruri_caller_avp_type,pubruri_caller_avp_name);
-		dlginfo->pubruris_callee = get_str_list(pubruri_callee_avp_type,pubruri_callee_avp_name);
+			if(dlginfo->pubruris_callee!=NULL && callee_dlg_var.len>0)
+				dlg_api.set_dlg_var(dlg, &callee_dlg_var,
+						&dlginfo->pubruris_callee->s);
 
-	} else {
+			if(dlginfo->pubruris_caller!=NULL && caller_dlg_var.len>0)
+				dlg_api.set_dlg_var(dlg, &caller_dlg_var,
+						&dlginfo->pubruris_caller->s);
+
+		} else {
+			if(caller_dlg_var.len>0
+					&& (s = dlg_api.get_dlg_var(dlg, &caller_dlg_var))!=0) {
+				dlginfo->pubruris_caller =
+					(struct str_list*)shm_malloc( sizeof(struct str_list) );
+				if (dlginfo->pubruris_caller==0) {
+					LM_ERR("no more shm mem (%d)\n", (int) sizeof(struct str_list));
+					free_dlginfo_cell(dlginfo);
+					return NULL;
+				}
+				memset( dlginfo->pubruris_caller, 0, sizeof(struct str_list));
+				dlginfo->pubruris_caller->s=*s;
+				LM_DBG("Found pubruris_caller in dialog '%.*s'\n",
+						dlginfo->pubruris_caller->s.len, dlginfo->pubruris_caller->s.s);
+			}
 
-		dlginfo->pubruris_caller = (struct str_list*)shm_malloc( sizeof(struct str_list) );
+			if(callee_dlg_var.len>0
+					&& (s = dlg_api.get_dlg_var(dlg, &callee_dlg_var))!=0) {
+				dlginfo->pubruris_callee =
+					(struct str_list*)shm_malloc( sizeof(struct str_list) );
+				if (dlginfo->pubruris_callee==0) {
+					LM_ERR("no more shm mem (%d)\n", (int) sizeof(struct str_list));
+					free_dlginfo_cell(dlginfo);
+					return NULL;
+				}
+				memset( dlginfo->pubruris_callee, 0, sizeof(struct str_list));
+				dlginfo->pubruris_callee->s=*s;
+				LM_DBG("Found pubruris_callee in dialog '%.*s'\n",
+						dlginfo->pubruris_callee->s.len, dlginfo->pubruris_callee->s.s);
+			}
+		}
 
+		if(dlginfo->pubruris_caller == 0 && dlginfo->pubruris_callee == 0 ) {
+			/* No reason to save dlginfo, we have nobody to publish to */
+			LM_DBG("Neither pubruris_caller nor pubruris_callee found.\n");
+			free_dlginfo_cell(dlginfo);
+			return NULL;
+		}
+	} else {
+		dlginfo->pubruris_caller =
+			(struct str_list*)shm_malloc( sizeof(struct str_list) );
 		if (dlginfo->pubruris_caller==0) {
 			LM_ERR("no more shm mem (%d)\n", (int) sizeof(struct str_list));
-			return;
+			free_dlginfo_cell(dlginfo);
+			return NULL;
 		}
 		memset( dlginfo->pubruris_caller, 0, sizeof(struct str_list));
-
 		dlginfo->pubruris_caller->s=dlginfo->from_uri;
 
-
-		dlginfo->pubruris_callee = (struct str_list*)shm_malloc( sizeof(struct str_list) );
-
+		dlginfo->pubruris_callee =
+			(struct str_list*)shm_malloc( sizeof(struct str_list) );
 		if (dlginfo->pubruris_callee==0) {
 			LM_ERR("no more shm mem (%d)\n", (int) sizeof(struct str_list));
-			return;
+			free_dlginfo_cell(dlginfo);
+			return NULL;
 		}
 		memset( dlginfo->pubruris_callee, 0, sizeof(struct str_list));
 
@@ -443,34 +545,72 @@ __dialog_created(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params)
 		} else {
 			dlginfo->pubruris_callee->s = dlginfo->to_uri;
 		}
-
 	}
 
 	/* register dialog callbacks which triggers sending PUBLISH */
-	if (dlg_api.register_dlgcb(dlg, 
-		DLGCB_FAILED| DLGCB_CONFIRMED_NA | DLGCB_TERMINATED | DLGCB_EXPIRED |
-		DLGCB_REQ_WITHIN | DLGCB_EARLY,
-		__dialog_sendpublish, dlginfo, free_dlginfo_cell) != 0) {
+	if (dlg_api.register_dlgcb(dlg,
+				DLGCB_FAILED| DLGCB_CONFIRMED_NA | DLGCB_TERMINATED
+				| DLGCB_EXPIRED | DLGCB_REQ_WITHIN | DLGCB_EARLY,
+				__dialog_sendpublish, dlginfo, free_dlginfo_cell) != 0) {
 		LM_ERR("cannot register callback for interesting dialog types\n");
-		return;
+		free_dlginfo_cell(dlginfo);
+		return NULL;
 	}
 
 #ifdef PUA_DIALOGINFO_DEBUG
 	/* dialog callback testing (registered last to be executed frist) */
 	if (dlg_api.register_dlgcb(dlg, 
-		DLGCB_FAILED| DLGCB_CONFIRMED_NA | DLGCB_CONFIRMED | DLGCB_REQ_WITHIN | DLGCB_TERMINATED |
-		DLGCB_EXPIRED | DLGCB_EARLY | DLGCB_RESPONSE_FWDED | DLGCB_RESPONSE_WITHIN  |
-		DLGCB_MI_CONTEXT | DLGCB_DESTROY,
-		__dialog_cbtest, NULL, NULL) != 0) {
+				DLGCB_FAILED| DLGCB_CONFIRMED_NA | DLGCB_CONFIRMED
+				| DLGCB_REQ_WITHIN | DLGCB_TERMINATED | DLGCB_EXPIRED
+				| DLGCB_EARLY | DLGCB_RESPONSE_FWDED | DLGCB_RESPONSE_WITHIN
+				| DLGCB_MI_CONTEXT | DLGCB_DESTROY,
+				__dialog_cbtest, NULL, NULL) != 0) {
 		LM_ERR("cannot register callback for all dialog types\n");
-		return;
+		free_dlginfo_cell(dlginfo);
+		return NULL;
 	}
 #endif
 
-	dialog_publish_multi("Trying", dlginfo->pubruris_caller, &(dlg->from_uri), (include_req_uri)?&(dlg->req_uri):&(dlg->to_uri), &(dlg->callid), 1, dlginfo->lifetime, 0, 0, 0, 0, send_publish_flag==-1?1:0);
+	return(dlginfo);
+}
+
+	static void
+__dialog_created(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params)
+{
+	struct sip_msg *request = _params->req;
+	struct dlginfo_cell *dlginfo;
+
+	if (request->REQ_METHOD != METHOD_INVITE)
+		return;
+
+	if(send_publish_flag > -1 && !(request->flags & (1<<send_publish_flag)))
+		return;
+
+	LM_DBG("new INVITE dialog created: from=%.*s\n",
+			dlg->from_uri.len, dlg->from_uri.s);
+
+	dlginfo=get_dialog_data(dlg, type);
+	if(dlginfo==NULL)
+		return;
+
+	dialog_publish_multi("Trying", dlginfo->pubruris_caller,
+			&(dlg->from_uri),
+			(include_req_uri)?&(dlg->req_uri):&(dlg->to_uri),
+			&(dlg->callid), 1, dlginfo->lifetime,
+			0, 0, 0, 0, (send_publish_flag==-1)?1:0);
+
 }
 
+	static void
+__dialog_loaded(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params)
+{
+	struct dlginfo_cell *dlginfo;
+
+	LM_DBG("INVITE dialog loaded: from=%.*s\n", dlg->from_uri.len, dlg->from_uri.s);
 
+	dlginfo=get_dialog_data(dlg, type);
+	if(dlginfo!=NULL) free_dlginfo_cell(dlginfo);
+}
 
 
 /**
@@ -482,14 +622,20 @@ static int mod_init(void)
 
 	str s;
 	pv_spec_t avp_spec;
-	
+
+	if(caller_dlg_var.len<=0)
+		LM_WARN("pubruri_caller_dlg_var is not set - restore on restart disabled\n");
+
+	if(callee_dlg_var.len<=0)
+		LM_WARN("pubruri_callee_dlg_var is not set - restore on restart disabled\n");
+
 	bind_pua= (bind_pua_t)find_export("bind_pua", 1,0);
 	if (!bind_pua)
 	{
 		LM_ERR("Can't bind pua\n");
 		return -1;
 	}
-	
+
 	if (bind_pua(&pua) < 0)
 	{
 		LM_ERR("Can't bind pua\n");
@@ -512,11 +658,18 @@ static int mod_init(void)
 		LM_ERR("cannot register callback for dialog creation\n");
 		return -1;
 	}
+	/* register dialog loaded callback */
+	if (dlg_api.register_dlgcb(NULL, DLGCB_LOADED, __dialog_loaded, NULL, NULL) != 0) {
+		LM_ERR("cannot register callback for dialog loaded\n");
+		return -1;
+	}
 
 	if(use_pubruri_avps) {
 
-		if(!(pubruri_caller_avp && *pubruri_caller_avp) && (pubruri_callee_avp && *pubruri_callee_avp)) {
-			LM_ERR("pubruri_caller_avp and pubruri_callee_avp must be set, if use_pubruri_avps is enabled\n");
+		if(!(pubruri_caller_avp && *pubruri_caller_avp)
+				&& (pubruri_callee_avp && *pubruri_callee_avp)) {
+			LM_ERR("pubruri_caller_avp and pubruri_callee_avp must be set,"
+					" if use_pubruri_avps is enabled\n");
 			return -1;
 		}
 
@@ -525,7 +678,8 @@ static int mod_init(void)
 			LM_ERR("malformed or non AVP %s AVP definition\n", pubruri_caller_avp);
 			return -1;
 		}
-		if(pv_get_avp_name(0, &avp_spec.pvp, &pubruri_caller_avp_name, &pubruri_caller_avp_type)!=0) {
+		if(pv_get_avp_name(0, &avp_spec.pvp, &pubruri_caller_avp_name,
+					&pubruri_caller_avp_type)!=0) {
 			LM_ERR("[%s]- invalid AVP definition\n", pubruri_caller_avp);
 			return -1;
 		}
@@ -535,7 +689,8 @@ static int mod_init(void)
 			LM_ERR("malformed or non AVP %s AVP definition\n", pubruri_callee_avp);
 			return -1;
 		}
-		if(pv_get_avp_name(0, &avp_spec.pvp, &pubruri_callee_avp_name, &pubruri_callee_avp_type)!=0) {
+		if(pv_get_avp_name(0, &avp_spec.pvp, &pubruri_callee_avp_name,
+					&pubruri_callee_avp_type)!=0) {
 			LM_ERR("[%s]- invalid AVP definition\n", pubruri_callee_avp);
 			return -1;
 		}
@@ -547,8 +702,12 @@ static int mod_init(void)
 
 void free_dlginfo_cell(void *param) {
 
-	struct dlginfo_cell *cell = param;
+	struct dlginfo_cell *cell = NULL;
+
+	if(param==NULL)
+		return;
 
+	cell = param;
 	free_str_list_all(cell->pubruris_caller);
 	free_str_list_all(cell->pubruris_callee);
 
diff --git a/modules/pua_mi/README b/modules/pua_mi/README
index bfeaccf..6218ac4 100644
--- a/modules/pua_mi/README
+++ b/modules/pua_mi/README
@@ -12,7 +12,7 @@ Edited by
 
 Juha Heinanen
 
-   Copyright � 2006 Voice Sistem SRL
+   Copyright (c) 2006 Voice Sistem SRL
      __________________________________________________________________
 
    Table of Contents
@@ -25,14 +25,19 @@ Juha Heinanen
               2.1. Kamailio Modules
               2.2. External Libraries or Applications
 
-        3. MI Commands
+        3. Parameters
 
-              3.1. pua_publish
-              3.2. pua_subscribe
+              3.1. publish_with_ob_proxy (int)
+
+        4. MI Commands
+
+              4.1. pua_publish
+              4.2. pua_subscribe
 
    List of Examples
 
-   1.1. pua_publish FIFO example
+   1.1. Set publish_with_ob_proxy parameter
+   1.2. pua_publish FIFO example
 
 Chapter 1. Admin Guide
 
@@ -44,10 +49,14 @@ Chapter 1. Admin Guide
         2.1. Kamailio Modules
         2.2. External Libraries or Applications
 
-   3. MI Commands
+   3. Parameters
+
+        3.1. publish_with_ob_proxy (int)
 
-        3.1. pua_publish
-        3.2. pua_subscribe
+   4. MI Commands
+
+        4.1. pua_publish
+        4.2. pua_subscribe
 
 1. Overview
 
@@ -76,12 +85,27 @@ Chapter 1. Admin Guide
    running Kamailio with this module loaded:
      * none
 
-3. MI Commands
+3. Parameters
+
+   3.1. publish_with_ob_proxy (int)
+
+3.1. publish_with_ob_proxy (int)
+
+   If 1, pua_publish MI command has outbound proxy parameter.
+
+   Default value is "0".
+
+   Example 1.1. Set publish_with_ob_proxy parameter
+...
+modparam("pua_mi", "publish_with_ob_proxy", 1)
+...
+
+4. MI Commands
 
-   3.1. pua_publish
-   3.2. pua_subscribe
+   4.1. pua_publish
+   4.2. pua_subscribe
 
-3.1. pua_publish
+4.1.  pua_publish
 
    Command parameters:
      * presentity_uri - e.g. sip:system at kamailio.org
@@ -97,13 +121,17 @@ Chapter 1. Admin Guide
        user take place. The dialog-id from the dialog-info body qualifies
        as a suitable id here.
      * ETag - ETag that publish should match or . if no ETag is given.
+     * outbound proxy - SIP URI of outbound proxy to be used when sending
+       PUBLISH request or . if no outbound proxy is given. This parameter
+       is present only when publish_with_ob_proxy module parameter has
+       value 1.
      * extra_headers - Extra headers added to PUBLISH request or . if no
        extra headers.
      * body - The body of the publish request containing published
        information or missing if no published information. It has to be a
        single line for FIFO transport.
 
-   Example 1.1. pua_publish FIFO example
+   Example 1.2. pua_publish FIFO example
 ...
 
 :pua_publish:fifo_test_reply
@@ -121,7 +149,7 @@ le id='0x81475a0'><status><basic>open</basic></status></tuple><dm:person id='pdd
 748945'><rpid:activities><rpid:away/>away</rpid:activities><dm:note>CPU:16 MEM:4
 76</dm:note></dm:person></presence>
 
-3.2. pua_subscribe
+4.2.  pua_subscribe
 
    Command parameters:
      * presentity_uri - e.g. sip:presentity at kamailio.org
diff --git a/modules/pua_mi/doc/pua_mi_admin.xml b/modules/pua_mi/doc/pua_mi_admin.xml
index f10c42f..7d4385f 100644
--- a/modules/pua_mi/doc/pua_mi_admin.xml
+++ b/modules/pua_mi/doc/pua_mi_admin.xml
@@ -63,6 +63,28 @@
 			</itemizedlist>
 	</section>
 	</section>
+
+	<section>
+	<title>Parameters</title>
+	<section>
+		<title><varname>publish_with_ob_proxy</varname> (int)</title>
+		<para>
+		If 1, pua_publish MI command has outbound proxy parameter.
+        	</para>
+		<para>
+		<emphasis>Default value is <quote>0</quote>.	
+		</emphasis>
+		</para>
+		<example>
+		<title>Set <varname>publish_with_ob_proxy</varname> parameter</title>
+		<programlisting format="linespecific">
+...
+modparam("pua_mi", "publish_with_ob_proxy", 1)
+...
+</programlisting>
+		</example>
+	</section>
+	</section>
 	
 	<section>
 		<title>MI Commands</title>
@@ -123,6 +145,15 @@
 			</listitem>
 			<listitem>
 				<para>
+				  <emphasis>outbound proxy</emphasis>
+				  - SIP URI of outbound proxy to be used when
+       sending PUBLISH request or . if no outbound proxy is given.  This
+       parameter is present only when publish_with_ob_proxy module
+       parameter has value 1. 
+		                </para> 
+			</listitem>
+			<listitem>
+				<para>
 					<emphasis>extra_headers</emphasis>
 					- Extra headers added to PUBLISH
 		request or . if no extra headers.
diff --git a/modules/pua_mi/mi_func.c b/modules/pua_mi/mi_func.c
index ae6d8e2..f92c9ff 100644
--- a/modules/pua_mi/mi_func.c
+++ b/modules/pua_mi/mi_func.c
@@ -33,7 +33,6 @@
 #include "../../lib/kcore/cmpapi.h"
 
 #include "../pua/pua_bind.h"
-#include "../pua/pua.h"
 #include "pua_mi.h"
 
 /*
@@ -46,6 +45,7 @@
  *		<id>               - id for a series of related PUBLISHes to the same
  *		                     presentity-uri or .
  *		<ETag>             - ETag that publish should match or . if no ETag
+ *		<outbound_proxy>   - outbound proxy or .
  *		<extra_headers>    - extra headers to be added to the request or .
  *		<publish_body>     - may not be present in case of update for expire
  */
@@ -62,6 +62,7 @@ struct mi_root* mi_pua_publish(struct mi_root* cmd, void* param)
 	str content_type;
 	str id;
 	str etag;
+	str outbound_proxy;
 	str extra_headers;
 	int result;
 	int sign= 1;
@@ -171,6 +172,21 @@ struct mi_root* mi_pua_publish(struct mi_root* cmd, void* param)
 	if(node == NULL)
 		return 0;
 
+	/* Get outbound_proxy */
+	if (publish_with_ob_proxy) {
+
+		outbound_proxy = node->value;
+		if(outbound_proxy.s== NULL || outbound_proxy.len== 0) {
+			LM_ERR("empty outbound proxy parameter\n");
+			return init_mi_tree(400, "Empty outbound proxy", 20);
+		}
+		LM_DBG("outbound_proxy '%.*s'\n",
+		       outbound_proxy.len, outbound_proxy.s);
+	
+		node = node->next;
+		if(node == NULL) return 0;
+	}
+
 	/* Get extra_headers */
 	extra_headers = node->value;
 	if(extra_headers.s== NULL || extra_headers.len== 0)
@@ -241,10 +257,22 @@ struct mi_root* mi_pua_publish(struct mi_root* cmd, void* param)
 	}	
 	publ.expires= exp;
 
+	if (publish_with_ob_proxy) {
+		if (!((outbound_proxy.len == 1) &&
+		      (outbound_proxy.s[0] == '.')))
+			publ.outbound_proxy = &outbound_proxy;
+	}
+
 	if (!(extra_headers.len == 1 && extra_headers.s[0] == '.')) {
 	    publ.extra_headers = &extra_headers;
 	}
 
+	if (!(etag.len== 1 && etag.s[0]== '.'))
+	{
+		publ.etag= &etag;
+	}	
+	publ.expires= exp;
+
 	if (cmd->async_hdl!=NULL)
 	{
 		publ.source_flag= MI_ASYN_PUBLISH;
diff --git a/modules/pua_mi/pua_mi.c b/modules/pua_mi/pua_mi.c
index 1e6bf2c..ec5cfa7 100644
--- a/modules/pua_mi/pua_mi.c
+++ b/modules/pua_mi/pua_mi.c
@@ -48,6 +48,9 @@ MODULE_VERSION
 
 pua_api_t pua;
 
+/** module params */
+int publish_with_ob_proxy = 0;
+
 /** module functions */
 
 static int mod_init(void);
@@ -56,6 +59,14 @@ send_publish_t pua_send_publish;
 send_subscribe_t pua_send_subscribe;
 
 /*
+ * Exported params
+ */
+static param_export_t params[]={
+	{"publish_with_ob_proxy",    INT_PARAM, &publish_with_ob_proxy},
+	{0,                          0,         0}
+};
+
+/*
  * Exported MI functions
  */
 static mi_export_t mi_cmds[] = {
@@ -69,7 +80,7 @@ struct module_exports exports= {
 	"pua_mi",					/* module name */
 	DEFAULT_DLFLAGS,			/* dlopen flags */
 	0,							/* exported functions */
-	0,							/* exported parameters */
+	params,							/* exported parameters */
 	0,							/* exported statistics */
 	mi_cmds,					/* exported MI functions */
 	0,							/* exported pseudo-variables */
diff --git a/modules/pua_mi/pua_mi.h b/modules/pua_mi/pua_mi.h
index c1eadbc..74af4e1 100644
--- a/modules/pua_mi/pua_mi.h
+++ b/modules/pua_mi/pua_mi.h
@@ -27,6 +27,8 @@
 
 #include "../pua/pua_bind.h"
 
+extern int publish_with_ob_proxy;
+
 extern send_publish_t pua_send_publish;
 extern send_subscribe_t pua_send_subscribe;
 
diff --git a/modules/pua_reginfo/Makefile b/modules/pua_reginfo/Makefile
index 532f159..1f08c33 100644
--- a/modules/pua_reginfo/Makefile
+++ b/modules/pua_reginfo/Makefile
@@ -1,6 +1,4 @@
-# $Id: Makefile 1856 2007-03-15 21:06:00Z jblache $
-#
-# PUBLISH
+# PUA_REGINFO
 #
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
diff --git a/modules/pua_reginfo/usrloc_cb.c b/modules/pua_reginfo/usrloc_cb.c
index 0164a67..6b8cd68 100644
--- a/modules/pua_reginfo/usrloc_cb.c
+++ b/modules/pua_reginfo/usrloc_cb.c
@@ -65,7 +65,6 @@ str* build_reginfo_full(urecord_t * record, str uri, ucontact_t* c, int type) {
 	str * body= NULL;
 	ucontact_t * ptr;
 	char buf[512];
-	int buf_len;
 	int reg_active = 0;
 	time_t cur_time = time(0);
 
@@ -99,7 +98,7 @@ str* build_reginfo_full(urecord_t * record, str uri, ucontact_t* c, int type) {
 
 	/* Add the properties to this Node for AOR and ID: */
 	xmlNewProp(registration_node, BAD_CAST "aor", BAD_CAST uri.s);
-	buf_len = snprintf(buf, sizeof(buf), "%p", record);
+	snprintf(buf, sizeof(buf), "%p", record);
 	xmlNewProp(registration_node, BAD_CAST "id", BAD_CAST buf);
 
 	ptr = record->contacts;
@@ -113,7 +112,7 @@ str* build_reginfo_full(urecord_t * record, str uri, ucontact_t* c, int type) {
 				goto error;
 			}
 			memset(buf, 0, sizeof(buf));
-			buf_len = snprintf(buf, sizeof(buf), "%p", ptr);
+			snprintf(buf, sizeof(buf), "%p", ptr);
 			xmlNewProp(contact_node, BAD_CAST "id", BAD_CAST buf);
 			/* Check, if this is the modified contact: */
 			if (ptr == c) {
@@ -128,50 +127,50 @@ str* build_reginfo_full(urecord_t * record, str uri, ucontact_t* c, int type) {
 				else if (type & UL_CONTACT_DELETE) xmlNewProp(contact_node, BAD_CAST "event", BAD_CAST "unregistered");
 				else xmlNewProp(contact_node, BAD_CAST "event", BAD_CAST "unknown");
 				memset(buf, 0, sizeof(buf));
-				buf_len = snprintf(buf, sizeof(buf), "%i", (int)(ptr->expires-cur_time));
+				snprintf(buf, sizeof(buf), "%i", (int)(ptr->expires-cur_time));
 				xmlNewProp(contact_node, BAD_CAST "expires", BAD_CAST buf);
 			} else {
 				reg_active = 1;
 				xmlNewProp(contact_node, BAD_CAST "state", BAD_CAST "active");
 				xmlNewProp(contact_node, BAD_CAST "event", BAD_CAST "registered");
 				memset(buf, 0, sizeof(buf));
-				buf_len = snprintf(buf, sizeof(buf), "%i", (int)(ptr->expires-cur_time));
+				snprintf(buf, sizeof(buf), "%i", (int)(ptr->expires-cur_time));
 				xmlNewProp(contact_node, BAD_CAST "expires", BAD_CAST buf);
 			}
 			if (ptr->q != Q_UNSPECIFIED) {
 				float q = (float)ptr->q/1000;
 				memset(buf, 0, sizeof(buf));
-				buf_len = snprintf(buf, sizeof(buf), "%.3f", q);
+				snprintf(buf, sizeof(buf), "%.3f", q);
 				xmlNewProp(contact_node, BAD_CAST "q", BAD_CAST buf);
 			}
 			/* CallID Attribute */
 			memset(buf, 0, sizeof(buf));
-			buf_len = snprintf(buf, sizeof(buf), "%.*s", ptr->callid.len, ptr->callid.s);
+			snprintf(buf, sizeof(buf), "%.*s", ptr->callid.len, ptr->callid.s);
 			xmlNewProp(contact_node, BAD_CAST "callid", BAD_CAST buf);
 
 			/* CSeq Attribute */
 			memset(buf, 0, sizeof(buf));
-			buf_len = snprintf(buf, sizeof(buf), "%d", ptr->cseq);
+			snprintf(buf, sizeof(buf), "%d", ptr->cseq);
 			xmlNewProp(contact_node, BAD_CAST "cseq", BAD_CAST buf);
 
 			/* received Attribute */
 			memset(buf, 0, sizeof(buf));
-	                buf_len = snprintf(buf, sizeof(buf), "%.*s", ptr->received.len, ptr->received.s);
+	                snprintf(buf, sizeof(buf), "%.*s", ptr->received.len, ptr->received.s);
          	       	xmlNewProp(contact_node, BAD_CAST "received", BAD_CAST buf);
 			
 			/* path Attribute */
 			memset(buf, 0, sizeof(buf));
-			buf_len = snprintf(buf, sizeof(buf), "%.*s", ptr->path.len, ptr->path.s);
+			snprintf(buf, sizeof(buf), "%.*s", ptr->path.len, ptr->path.s);
 			xmlNewProp(contact_node, BAD_CAST "path", BAD_CAST buf);
 
 			/* user_agent Attribute */
 			memset(buf, 0, sizeof(buf));
-			buf_len = snprintf(buf, sizeof(buf), "%.*s", ptr->user_agent.len, ptr->user_agent.s);
+			snprintf(buf, sizeof(buf), "%.*s", ptr->user_agent.len, ptr->user_agent.s);
 			xmlNewProp(contact_node, BAD_CAST "user_agent", BAD_CAST buf);
 
 			/* URI-Node */
 			memset(buf, 0, sizeof(buf));
-			buf_len = snprintf(buf, sizeof(buf), "%.*s", ptr->c.len, ptr->c.s);
+			snprintf(buf, sizeof(buf), "%.*s", ptr->c.len, ptr->c.s);
 			uri_node = xmlNewChild(contact_node, NULL, BAD_CAST "uri", BAD_CAST buf) ;
 			if(uri_node == NULL) {
 				LM_ERR("while adding child\n");
diff --git a/modules/purple/hashtable.c b/modules/purple/hashtable.c
index 1c5d02a..5d6159d 100644
--- a/modules/purple/hashtable.c
+++ b/modules/purple/hashtable.c
@@ -36,11 +36,11 @@ static int *get_counter(char *key) {
 	if (d == NULL) {
 		gchar *k = g_strdup(key);
 		d = (int*) pkg_malloc(sizeof(int));
-		LM_DBG("counter created @0x%08x\n", (unsigned int)d);
+		LM_DBG("counter created @0x%p\n", d);
 		*d = 0;
 		g_hash_table_insert(hash, k, d);
 	}
-	LM_DBG("counter at 0x%08x: key: %s ; value: %d\n", (unsigned int)d, key, *d);
+	LM_DBG("counter at 0x%p: key: %s ; value: %d\n", d, key, *d);
 	return d;
 }
 
diff --git a/modules/purple/purple_sip.c b/modules/purple/purple_sip.c
index 4f5f2c2..88f95dd 100644
--- a/modules/purple/purple_sip.c
+++ b/modules/purple/purple_sip.c
@@ -74,7 +74,7 @@ static str* build_pidf(char *uri, char *id, enum purple_publish_basic basic, enu
 	xmlNodePtr root_node = NULL, status_node = NULL;
 	xmlNodePtr tuple_node = NULL, basic_node = NULL;
 	xmlNodePtr person_node = NULL, activities_node = NULL;
-	xmlNsPtr pidf_ns, dm_ns, rpid_ns, cipid_ns;
+	xmlNsPtr pidf_ns, dm_ns, rpid_ns;
 	char* entity = NULL;
 
 	entity = (char*)pkg_malloc(7+ strlen(uri)*sizeof(char));
@@ -104,7 +104,7 @@ static str* build_pidf(char *uri, char *id, enum purple_publish_basic basic, enu
 	pidf_ns = xmlNewNs(root_node, BAD_CAST "urn:ietf:params:xml:ns:pidf", NULL);
 	dm_ns = xmlNewNs(root_node, BAD_CAST "urn:ietf:params:xml:ns:pidf:data-model", BAD_CAST "dm");
 	rpid_ns = xmlNewNs(root_node, BAD_CAST "urn:ietf:params:xml:ns:pidf:rpid", BAD_CAST "rpid");
-	cipid_ns = xmlNewNs(root_node, BAD_CAST "urn:ietf:params:xml:ns:pidf:cipid", BAD_CAST "c");
+	xmlNewNs(root_node, BAD_CAST "urn:ietf:params:xml:ns:pidf:cipid", BAD_CAST "c");
 	
 	tuple_node = xmlNewChild(root_node, NULL, BAD_CAST "tuple", NULL);
 	if( tuple_node == NULL) {
diff --git a/modules/pv/Makefile b/modules/pv/Makefile
index 1a199ff..8ebaf13 100644
--- a/modules/pv/Makefile
+++ b/modules/pv/Makefile
@@ -1,6 +1,5 @@
-# $Id$
 #
-# example module makefile
+# pv module makefile
 #
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
diff --git a/modules/pv/README b/modules/pv/README
index fafee35..9cab590 100644
--- a/modules/pv/README
+++ b/modules/pv/README
@@ -41,6 +41,10 @@ Daniel-Constantin Mierla
               4.3. is_int(pvar)
               4.4. typeof(pvar, vtype)
               4.5. not_empty(pvar)
+              4.6. xavp_params_explode(sparams, xname)
+              4.7. sbranch_set_ruri()
+              4.8. sbranch_append()
+              4.9. sbranch_reset()
 
         5. MI Commands
 
@@ -62,8 +66,12 @@ Daniel-Constantin Mierla
    1.6. is_int() usage
    1.7. typeof() usage
    1.8. not_empty() usage
-   1.9. shv_set usage
-   1.10. shv_get usage
+   1.9. xavp_params_explode usage
+   1.10. sbranch_set_ruri() usage
+   1.11. sbranch_append() usage
+   1.12. sbranch_append() usage
+   1.13. shv_set usage
+   1.14. shv_get usage
 
 Chapter 1. Admin Guide
 
@@ -88,6 +96,10 @@ Chapter 1. Admin Guide
         4.3. is_int(pvar)
         4.4. typeof(pvar, vtype)
         4.5. not_empty(pvar)
+        4.6. xavp_params_explode(sparams, xname)
+        4.7. sbranch_set_ruri()
+        4.8. sbranch_append()
+        4.9. sbranch_reset()
 
    5. MI Commands
 
@@ -187,6 +199,10 @@ modparam("pv","avp_aliases","email=s:email_addr;tmp=i:100")
    4.3. is_int(pvar)
    4.4. typeof(pvar, vtype)
    4.5. not_empty(pvar)
+   4.6. xavp_params_explode(sparams, xname)
+   4.7. sbranch_set_ruri()
+   4.8. sbranch_append()
+   4.9. sbranch_reset()
 
 4.1. pv_isset(pvar)
 
@@ -262,6 +278,80 @@ if (not_empty("$var(foo)")) {
 }
 ...
 
+4.6. xavp_params_explode(sparams, xname)
+
+   Convert a parameters string in xavp atributes.
+
+   The first parameter has to be a string in the format of SIP header
+   parameters (name1=value1;...;nameN=valueN). The second parameter is the
+   name of the root xavp to hold the pairs (nameX,valueX).
+
+   The values are stored as string type.
+
+   Function can be used from ANY ROUTE.
+
+   Example 1.9. xavp_params_explode usage
+...
+xavp_params_explode("a=b;c=d;e=d", "x");
+# results in:
+#    $xavp(x=>a) = "b";
+#    $xavp(x=>c) = "d";
+#    $xavp(x=>e) = "f";
+...
+
+4.7. sbranch_set_ruri()
+
+   Use the attributes from static branch ($sbranch(key) variable) to set
+   request URI and the other fields of the branch associated with request
+   URI (destination URI, path, ...).
+
+   Content of the static branch is not reset after this function is
+   executed. It has to be done explicitely with sbranch_reset().
+
+   Function can be used from REQUEST_ROUTE, BRANCH_ROUTE or FAILURE_ROUTE.
+
+   Example 1.10. sbranch_set_ruri() usage
+...
+sbranch_reset();
+$sbranch(uri) = "sip:127.0.0.1:5080";
+$sbranch(dst_uri) =  "sip:127.0.0.1:5090";
+$sbranch(path) =  "sip:127.0.0.1:5090, sip:127.0.0.1:5094";
+$sbranch(send_socket) =  "udp:127.0.0.1:5060";
+sbranch_set_ruri();
+...
+
+4.8. sbranch_append()
+
+   Use the attributes from static branch ($sbranch(key) variable) to
+   append a new branch to destination set. It is an alternative to
+   append_branch() that allows setting each attribute specific to the
+   branch.
+
+   Content of the static branch is not reset after this function is
+   executed. It has to be done explicitely with sbranch_reset().
+
+   Function can be used from REQUEST_ROUTE, BRANCH_ROUTE or FAILURE_ROUTE.
+
+   Example 1.11. sbranch_append() usage
+...
+sbranch_reset();
+$sbranch(uri) = "sip:127.0.0.1:5080";
+$sbranch(dst_uri) =  "sip:127.0.0.1:5090";
+$sbranch(send_socket) =  "udp:127.0.0.1:5060";
+sbranch_append();
+...
+
+4.9. sbranch_reset()
+
+   Reset the content of static branch ($sbranch(key) variable.
+
+   Function can be used from REQUEST_ROUTE, BRANCH_ROUTE or FAILURE_ROUTE.
+
+   Example 1.12. sbranch_append() usage
+...
+sbranch_reset();
+...
+
 5. MI Commands
 
    5.1. shv_set
@@ -285,7 +375,7 @@ if (not_empty("$var(foo)")) {
                 _value_
                 _empty_line_
 
-   Example 1.9. shv_set usage
+   Example 1.13. shv_set usage
 ...
 $ kamctl fifo shv_set debug int 0
 ...
@@ -303,7 +393,7 @@ $ kamctl fifo shv_set debug int 0
                 _name_
                 _empty_line_
 
-   Example 1.10. shv_get usage
+   Example 1.14. shv_get usage
 ...
 $ kamctl fifo shv_get debug
 $ kamctl fifo shv_get
diff --git a/modules/pv/doc/pv_admin.xml b/modules/pv/doc/pv_admin.xml
index 739ccbb..a630b29 100644
--- a/modules/pv/doc/pv_admin.xml
+++ b/modules/pv/doc/pv_admin.xml
@@ -266,6 +266,116 @@ if (not_empty("$var(foo)")) {
 				</programlisting>
 			</example>
 		</section>
+		<section id="pv.f.xavp_params_explode">
+			<title>
+				<function moreinfo="none">xavp_params_explode(sparams, xname)</function>
+			</title>
+			<para>
+				Convert a parameters string in xavp atributes.
+			</para>
+			<para>
+				The first parameter has to be a string in the format of SIP header
+				parameters (name1=value1;...;nameN=valueN). The second parameter
+				is the name of the root xavp to hold the pairs (nameX,valueX).
+			</para>
+			<para>
+				The values are stored as string type.
+			</para>
+			<para>
+			Function can be used from ANY ROUTE.
+			</para>
+			<example>
+				<title><function>xavp_params_explode</function> usage</title>
+				<programlisting format="linespecific">
+...
+xavp_params_explode("a=b;c=d;e=d", "x");
+# results in:
+#    $xavp(x=>a) = "b";
+#    $xavp(x=>c) = "d";
+#    $xavp(x=>e) = "f";
+...
+				</programlisting>
+			</example>
+		</section>
+		<section id="pv.f.sbranch_set_ruri">
+			<title>
+				<function moreinfo="none">sbranch_set_ruri()</function>
+			</title>
+			<para>
+				Use the attributes from static branch ($sbranch(key) variable) to
+				set request URI and the other fields of the branch associated with
+				request URI (destination URI, path, ...).
+			</para>
+			<para>
+				Content of the static branch is not reset after this function is
+				executed. It has to be done explicitely with sbranch_reset().
+			</para>
+			<para>
+			Function can be used from REQUEST_ROUTE, BRANCH_ROUTE or FAILURE_ROUTE.
+			</para>
+			<example>
+				<title><function>sbranch_set_ruri()</function> usage</title>
+				<programlisting format="linespecific">
+...
+sbranch_reset();
+$sbranch(uri) = "sip:127.0.0.1:5080";
+$sbranch(dst_uri) =  "sip:127.0.0.1:5090";
+$sbranch(path) =  "sip:127.0.0.1:5090, sip:127.0.0.1:5094";
+$sbranch(send_socket) =  "udp:127.0.0.1:5060";
+sbranch_set_ruri();
+...
+				</programlisting>
+			</example>
+		</section>
+		<section id="pv.f.sbranch_append">
+			<title>
+				<function moreinfo="none">sbranch_append()</function>
+			</title>
+			<para>
+				Use the attributes from static branch ($sbranch(key) variable) to
+				append a new branch to destination set. It is an alternative to
+				append_branch() that allows setting each attribute specific to
+				the branch.
+			</para>
+			<para>
+				Content of the static branch is not reset after this function is
+				executed. It has to be done explicitely with sbranch_reset().
+			</para>
+			<para>
+			Function can be used from REQUEST_ROUTE, BRANCH_ROUTE or FAILURE_ROUTE.
+			</para>
+			<example>
+				<title><function>sbranch_append()</function> usage</title>
+				<programlisting format="linespecific">
+...
+sbranch_reset();
+$sbranch(uri) = "sip:127.0.0.1:5080";
+$sbranch(dst_uri) =  "sip:127.0.0.1:5090";
+$sbranch(send_socket) =  "udp:127.0.0.1:5060";
+sbranch_append();
+...
+				</programlisting>
+			</example>
+		</section>
+		<section id="pv.f.sbranch_reset">
+			<title>
+				<function moreinfo="none">sbranch_reset()</function>
+			</title>
+			<para>
+				Reset the content of static branch ($sbranch(key) variable.
+			</para>
+			<para>
+			Function can be used from REQUEST_ROUTE, BRANCH_ROUTE or FAILURE_ROUTE.
+			</para>
+			<example>
+				<title><function>sbranch_append()</function> usage</title>
+				<programlisting format="linespecific">
+...
+sbranch_reset();
+...
+				</programlisting>
+			</example>
+		</section>
 	</section>
 
 	<section>
diff --git a/modules/pv/pv.c b/modules/pv/pv.c
index 53edc38..11d899a 100644
--- a/modules/pv/pv.c
+++ b/modules/pv/pv.c
@@ -1,6 +1,4 @@
-/**
- * $Id$
- *
+/*
  * Copyright (C) 2008 Daniel-Constantin Mierla (asipto.com)
  *
  * This file is part of Kamailio, a free SIP server.
@@ -70,6 +68,9 @@ static pv_export_t mod_pvs[] = {
 	{ {"branch", sizeof("branch")-1}, /* branch attributes */
 		PVT_CONTEXT, pv_get_branchx, pv_set_branchx,
 		pv_parse_branchx_name, pv_parse_index, 0, 0 },
+	{ {"sbranch", sizeof("sbranch")-1}, /* static branch attributes */
+		PVT_CONTEXT, pv_get_sbranch, pv_set_sbranch,
+		pv_parse_branchx_name, 0, 0, 0 },
 	{ {"mi", (sizeof("mi")-1)}, /* message id */
 		PVT_OTHER, pv_get_msgid, 0,
 		0, 0, 0, 0},
@@ -97,6 +98,10 @@ static pv_export_t mod_pvs[] = {
 		pv_parse_index, 0, 0},
 	{{"var", (sizeof("var")-1)}, PVT_SCRIPTVAR, pv_get_scriptvar,
 		pv_set_scriptvar, pv_parse_scriptvar_name, 0, 0, 0},
+	{{"vz", (sizeof("vz")-1)}, PVT_SCRIPTVAR, pv_get_scriptvar,
+		pv_set_scriptvar, pv_parse_scriptvar_name, 0, 0, 0},
+	{{"vn", (sizeof("vn")-1)}, PVT_SCRIPTVAR, pv_get_scriptvar,
+		pv_set_scriptvar, pv_parse_scriptvarnull_name, 0, 0, 0},
 	{{"ai", (sizeof("ai")-1)}, /* */
 		PVT_OTHER, pv_get_pai, 0,
 		0, pv_parse_index, 0, 0},
@@ -379,6 +384,9 @@ static pv_export_t mod_pvs[] = {
 	{{"td", (sizeof("td")-1)}, /* */
 		PVT_OTHER, pv_get_to_attr, pv_set_to_domain,
 		0, 0, pv_init_iname, 3},
+	{{"sut", (sizeof("sut")-1)}, /* */
+		PVT_OTHER, pv_get_srcaddr_uri_full, 0,
+		0, 0, 0, 0},
 	{{"to.domain", (sizeof("to.domain")-1)}, /* */
 		PVT_OTHER, pv_get_to_attr, pv_set_to_domain,
 		0, 0, pv_init_iname, 3},
@@ -470,6 +478,11 @@ static int pv_unset(struct sip_msg* msg, char* pvid, char *foo);
 static int is_int(struct sip_msg* msg, char* pvar, char* s2);
 static int pv_typeof(sip_msg_t *msg, char *pv, char *t);
 static int pv_not_empty(sip_msg_t *msg, char *pv, char *s2);
+static int w_xavp_params_explode(sip_msg_t *msg, char *pparams, char *pxname);
+static int w_sbranch_set_ruri(sip_msg_t *msg, char p1, char *p2);
+static int w_sbranch_append(sip_msg_t *msg, char p1, char *p2);
+static int w_sbranch_reset(sip_msg_t *msg, char p1, char *p2);
+
 static int pv_init_rpc(void);
 
 static cmd_export_t cmds[]={
@@ -489,6 +502,15 @@ static cmd_export_t cmds[]={
 	{"not_empty", (cmd_function)pv_not_empty, 1, fixup_pvar_null,
 		fixup_free_pvar_null,
 		ANY_ROUTE},
+	{"xavp_params_explode", (cmd_function)w_xavp_params_explode,
+		2, fixup_spve_spve, fixup_free_spve_spve,
+		ANY_ROUTE},
+	{"sbranch_set_ruri",  (cmd_function)w_sbranch_set_ruri,  0, 0, 0,
+		ANY_ROUTE },
+	{"sbranch_append",    (cmd_function)w_sbranch_append,    0, 0, 0,
+		ANY_ROUTE },
+	{"sbranch_reset",     (cmd_function)w_sbranch_reset,     0, 0, 0,
+		ANY_ROUTE },
 
 	{0,0,0,0,0,0}
 };
@@ -519,10 +541,11 @@ static int mod_init(void)
 		return -1;
 	}
 	if(pv_init_rpc()!=0)
-        {
-                LM_ERR("failed to register RPC commands\n");
-                return -1;
-        }
+	{
+		LM_ERR("failed to register RPC commands\n");
+		return -1;
+    }
+	pv_init_sbranch();
 
 	return 0;
 }
@@ -658,6 +681,59 @@ static int is_int(struct sip_msg* msg, char* pvar, char* s2)
 	return -1;
 }
 
+/**
+ *
+ */
+static int w_xavp_params_explode(sip_msg_t *msg, char *pparams, char *pxname)
+{
+	str sparams;
+	str sxname;
+
+	if(fixup_get_svalue(msg, (gparam_t*)pparams, &sparams)!=0) {
+		LM_ERR("cannot get the params\n");
+		return -1;
+	}
+	if(fixup_get_svalue(msg, (gparam_t*)pxname, &sxname)!=0) {
+		LM_ERR("cannot get the xavp name\n");
+		return -1;
+	}
+
+	if(xavp_params_explode(&sparams, &sxname)<0)
+		return -1;
+
+	return 1;
+}
+
+/**
+ *
+ */
+static int w_sbranch_set_ruri(sip_msg_t *msg, char p1, char *p2)
+{
+	if(sbranch_set_ruri(msg)<0)
+		return -1;
+	return 1;
+}
+
+/**
+ *
+ */
+static int w_sbranch_append(sip_msg_t *msg, char p1, char *p2)
+{
+	if(sbranch_append(msg)<0)
+		return -1;
+	return 1;
+}
+
+/**
+ *
+ */
+static int w_sbranch_reset(sip_msg_t *msg, char p1, char *p2)
+{
+	if(sbranch_reset()<0)
+		return -1;
+	return 1;
+}
+
 static const char* rpc_shv_set_doc[2] = {
 	"Set a shared variable (args: name type value)",
 	0
diff --git a/modules/pv/pv_branch.c b/modules/pv/pv_branch.c
index 4cc5f0b..e35330a 100644
--- a/modules/pv/pv_branch.c
+++ b/modules/pv/pv_branch.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2008 Daniel-Constantin Mierla (asipto.com)
  *
  * This file is part of Kamailio, a free SIP server.
@@ -29,31 +27,37 @@
 #include "pv_core.h"
 #include "pv_branch.h"
 
-int pv_get_branchx(struct sip_msg *msg, pv_param_t *param,
-		pv_value_t *res)
+static branch_t _pv_sbranch;
+
+void pv_init_sbranch(void)
+{
+	memset(&_pv_sbranch, 0, sizeof(branch_t));
+}
+
+int pv_get_branchx_helper(sip_msg_t *msg, pv_param_t *param,
+		pv_value_t *res, int btype)
 {
 	int idx = 0;
 	int idxf = 0;
-	str uri;
-	str duri;
-	int lq = 0;
-	str path;
-	unsigned int fl = 0;
-	struct socket_info* fsocket = NULL;
-	str ruid;
-	str location_ua;
-
-	/* get the index */
-	if(pv_get_spec_index(msg, param, &idx, &idxf)!=0)
-	{
-		LM_ERR("invalid index\n");
-		return pv_get_null(msg, param, res);
-	}
+	branch_t *br;
 
-	uri.s = get_branch(idx, &uri.len, &lq, &duri, &path, &fl, &fsocket, &ruid, 0, &location_ua);
+	if(btype==1) {
+		br = &_pv_sbranch;
+	} else {
+		/* get the index */
+		if(pv_get_spec_index(msg, param, &idx, &idxf)!=0)
+		{
+			LM_ERR("invalid index\n");
+			return pv_get_null(msg, param, res);
+		}
+		br = get_sip_branch(idx);
+		if(br==NULL) {
+			return pv_get_null(msg, param, res);
+		}
+	}
 
 	/* branch(count) doesn't need a valid branch, everything else does */
-	if(uri.s == 0 && ( param->pvn.u.isname.name.n != 5/* count*/ ))
+	if(br->len == 0 && ( param->pvn.u.isname.name.n != 5/* count*/ ))
 	{
 		LM_ERR("error accessing branch [%d]\n", idx);
 		return pv_get_null(msg, param, res);
@@ -62,43 +66,49 @@ int pv_get_branchx(struct sip_msg *msg, pv_param_t *param,
 	switch(param->pvn.u.isname.name.n)
 	{
 		case 1: /* dst uri */
-			if(duri.len==0)
+			if(br->dst_uri_len==0)
 				return pv_get_null(msg, param, res);
-			return pv_get_strval(msg, param, res, &duri);
+			return pv_get_strlval(msg, param, res, br->dst_uri, br->dst_uri_len);
 		case 2: /* path */
-			if(path.len==0)
+			if(br->path_len==0)
 				return pv_get_null(msg, param, res);
-			return pv_get_strval(msg, param, res, &path);
+			return pv_get_strlval(msg, param, res, br->path, br->path_len);
 		case 3: /* Q */
-			if(lq == Q_UNSPECIFIED)
+			if(br->q == Q_UNSPECIFIED)
 				return pv_get_null(msg, param, res);
-			return pv_get_sintval(msg, param, res, lq);
+			return pv_get_sintval(msg, param, res, br->q);
 		case 4: /* send socket */
-			if(fsocket!=0)
-				return pv_get_strval(msg, param, res, &fsocket->sock_str);
+			if(br->force_send_socket!=0)
+				return pv_get_strval(msg, param, res, &br->force_send_socket->sock_str);
 			return pv_get_null(msg, param, res);
 		case 5: /* count */
 			return pv_get_uintval(msg, param, res, nr_branches);
 		case 6: /* flags */
-			return pv_get_uintval(msg, param, res, fl);
+			return pv_get_uintval(msg, param, res, br->flags);
 		case 7: /* ruid */
-			if(ruid.len==0)
+			if(br->ruid_len==0)
 				return pv_get_null(msg, param, res);
-			return pv_get_strval(msg, param, res, &ruid);
+			return pv_get_strlval(msg, param, res, br->ruid, br->ruid_len);
 		case 8: /* location_ua */
-			if(location_ua.len==0)
+			if(br->location_ua_len==0)
 				return pv_get_null(msg, param, res);
-			return pv_get_strval(msg, param, res, &location_ua);
+			return pv_get_strlval(msg, param, res, br->location_ua, br->location_ua_len);
 		default:
 			/* 0 - uri */
-			return pv_get_strval(msg, param, res, &uri);
+			return pv_get_strlval(msg, param, res, br->uri, br->len);
 	}
 
 	return 0;
 }
 
-int pv_set_branchx(struct sip_msg* msg, pv_param_t *param,
-		int op, pv_value_t *val)
+int pv_get_branchx(sip_msg_t *msg, pv_param_t *param,
+		pv_value_t *res)
+{
+	return pv_get_branchx_helper(msg, param, res, 0);
+}
+
+int pv_set_branchx_helper(sip_msg_t *msg, pv_param_t *param,
+		int op, pv_value_t *val, int btype)
 {
 	int idx = 0;
 	int idxf = 0;
@@ -114,15 +124,18 @@ int pv_set_branchx(struct sip_msg* msg, pv_param_t *param,
 		return -1;
 	}
 
-	/* get the index */
-	if(pv_get_spec_index(msg, param, &idx, &idxf)!=0)
-	{
-		LM_ERR("invalid index\n");
-		return -1;
+	if(btype==1) {
+		br = &_pv_sbranch;
+	} else {
+		/* get the index */
+		if(pv_get_spec_index(msg, param, &idx, &idxf)!=0)
+		{
+			LM_ERR("invalid index\n");
+			return -1;
+		}
+		br = get_sip_branch(idx);
 	}
 
-	br = get_sip_branch(idx);
-
 	if(br==NULL)
 	{
 		LM_DBG("no branch to operate on\n");
@@ -265,7 +278,11 @@ int pv_set_branchx(struct sip_msg* msg, pv_param_t *param,
 			/* 0 - uri */
 			if(val==NULL || (val->flags&PV_VAL_NULL))
 			{
-				drop_sip_branch(idx);
+				if(btype==1) {
+					memset(br, 0, sizeof(branch_t));
+				} else {
+					drop_sip_branch(idx);
+				}
 			} else {
 				if(!(val->flags&PV_VAL_STR))
 				{
@@ -274,7 +291,11 @@ int pv_set_branchx(struct sip_msg* msg, pv_param_t *param,
 				}
 				if(val->rs.len<=0)
 				{
-					drop_sip_branch(idx);
+					if(btype==1) {
+						memset(br, 0, sizeof(branch_t));
+					} else {
+						drop_sip_branch(idx);
+					}
 				} else {
 					if (unlikely(val->rs.len > MAX_URI_SIZE - 1))
 					{
@@ -292,6 +313,12 @@ int pv_set_branchx(struct sip_msg* msg, pv_param_t *param,
 	return 0;
 }
 
+int pv_set_branchx(sip_msg_t *msg, pv_param_t *param,
+		int op, pv_value_t *val)
+{
+	return pv_set_branchx_helper(msg, param, op, val, 0);
+}
+
 int pv_parse_branchx_name(pv_spec_p sp, str *in)
 {
 	if(sp==NULL || in==NULL || in->len<=0)
@@ -348,6 +375,18 @@ error:
 	return -1;
 }
 
+int pv_get_sbranch(sip_msg_t *msg, pv_param_t *param,
+		pv_value_t *res)
+{
+	return pv_get_branchx_helper(msg, param, res, 1);
+}
+
+int pv_set_sbranch(sip_msg_t *msg, pv_param_t *param,
+		int op, pv_value_t *val)
+{
+	return pv_set_branchx_helper(msg, param, op, val, 1);
+}
+
 int pv_get_sndfrom(struct sip_msg *msg, pv_param_t *param,
 		pv_value_t *res)
 {
@@ -558,3 +597,146 @@ error:
 	return -1;
 }
 
+/**
+ *
+ */
+int sbranch_set_ruri(sip_msg_t *msg)
+{
+	str sv;
+	flag_t old_bflags;
+	branch_t *br;
+	int ret;
+
+	ret = 0;
+	br = &_pv_sbranch;
+	if(br->len==0)
+		return -1;
+
+	sv.s = br->uri;
+	sv.len = br->len;
+
+	if (rewrite_uri(msg, &sv) < 0) {
+		LM_ERR("unable to rewrite Request-URI\n");
+		ret = -3;
+		goto error;
+	}
+
+	/* reset next hop address */
+	reset_dst_uri(msg);
+	if(br->dst_uri_len>0) {
+		sv.s = br->dst_uri;
+		sv.len = br->dst_uri_len;
+		if (set_dst_uri(msg, &sv) < 0) {
+			ret = -3;
+			goto error;
+		}
+	}
+
+	reset_path_vector(msg);
+	if(br->path_len==0) {
+		sv.s = br->path;
+		sv.len = br->path_len;
+		if(set_path_vector(msg, &sv) < 0) {
+			ret = -4;
+			goto error;
+		}
+	}
+
+	reset_instance(msg);
+	if (br->instance_len) {
+		sv.s = br->instance;
+		sv.len = br->instance_len;
+	    if (set_instance(msg, &sv) < 0) {
+			ret = -5;
+			goto error;
+	    }
+	}
+
+	reset_ruid(msg);
+	if (br->ruid_len) {
+		sv.s = br->ruid;
+		sv.len = br->ruid_len;
+	    if (set_ruid(msg, &sv) < 0) {
+			ret = -6;
+			goto error;
+	    }
+	}
+
+	reset_ua(msg);
+	if (br->location_ua_len) {
+		sv.s = br->location_ua;
+		sv.len = br->location_ua_len;
+	    if (set_ua(msg, &sv) < 0) {
+			ret = -7;
+			goto error;
+	    }
+	}
+
+	if (br->force_send_socket)
+		set_force_socket(msg, br->force_send_socket);
+
+	msg->reg_id = br->reg_id;
+	set_ruri_q(br->q);
+	old_bflags = 0;
+	getbflagsval(0, &old_bflags);
+	setbflagsval(0, old_bflags|br->flags);
+
+	return 0;
+error:
+	return ret;
+}
+
+/**
+ *
+ */
+int sbranch_append(sip_msg_t *msg)
+{
+	str uri = {0};
+	str duri = {0};
+	str path = {0};
+	str ruid = {0};
+	str location_ua = {0};
+	branch_t *br;
+
+	br = &_pv_sbranch;
+	if(br->len==0)
+		return -1;
+
+	uri.s = br->uri;
+	uri.len = br->len;
+
+	if(br->dst_uri_len==0) {
+		duri.s = br->dst_uri;
+		duri.len = br->dst_uri_len;
+	}
+	if(br->path_len==0) {
+		path.s = br->path;
+		path.len = br->path_len;
+	}
+	if(br->ruid_len==0) {
+		ruid.s = br->ruid;
+		ruid.len = br->ruid_len;
+	}
+	if(br->location_ua_len==0) {
+		location_ua.s = br->location_ua;
+		location_ua.len = br->location_ua_len;
+	}
+
+	if (append_branch(msg, &uri, &duri, &path, br->q, br->flags,
+					  br->force_send_socket, 0 /*instance*/, br->reg_id,
+					  &ruid, &location_ua)
+			    == -1) {
+		LM_ERR("failed to append static branch\n");
+		return -1;
+	}
+	return 0;
+}
+
+/**
+ *
+ */
+int sbranch_reset(void)
+{
+	memset(&_pv_sbranch, 0, sizeof(branch_t));
+	return 0;
+}
diff --git a/modules/pv/pv_branch.h b/modules/pv/pv_branch.h
index 56982cb..84b7972 100644
--- a/modules/pv/pv_branch.h
+++ b/modules/pv/pv_branch.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2008 Daniel-Constantin Mierla (asipto.com)
  *
  * This file is part of Kamailio, a free SIP server.
@@ -31,6 +29,11 @@ int pv_set_branchx(struct sip_msg* msg, pv_param_t *param,
 		int op, pv_value_t *val);
 int pv_parse_branchx_name(pv_spec_p sp, str *in);
 
+int pv_get_sbranch(sip_msg_t *msg, pv_param_t *param,
+		pv_value_t *res);
+int pv_set_sbranch(sip_msg_t *msg, pv_param_t *param,
+		int op, pv_value_t *val);
+
 int pv_get_sndto(struct sip_msg *msg, pv_param_t *param,
 		pv_value_t *res);
 int pv_get_sndfrom(struct sip_msg *msg, pv_param_t *param,
@@ -41,5 +44,10 @@ int pv_get_nh(struct sip_msg *msg, pv_param_t *param,
 		pv_value_t *res);
 int pv_parse_nh_name(pv_spec_p sp, str *in);
 
+int sbranch_set_ruri(sip_msg_t *msg);
+int sbranch_append(sip_msg_t *msg);
+void pv_init_sbranch(void);
+int sbranch_reset(void);
+
 #endif
 
diff --git a/modules/pv/pv_core.c b/modules/pv/pv_core.c
index 56253b8..9cbad39 100644
--- a/modules/pv/pv_core.c
+++ b/modules/pv/pv_core.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2005 FhG Fokus
  * Copyright (C) 2005 Voice Sistem SRL
  * Copyright (C) 2010 Daniel-Constantin Mierla (asipto.com)
@@ -112,36 +110,6 @@ int pv_get_return_code(struct sip_msg *msg, pv_param_t *param,
 }
 */
 
-int pv_get_known_proto_string(int proto, str *sproto)
-{
-	switch(proto) {
-		case PROTO_UDP:
-			sproto->s = "udp";
-			sproto->len = 3;
-		return 0;
-		case PROTO_TCP:
-			sproto->s = "tcp";
-			sproto->len = 3;
-		return 0;
-		case PROTO_TLS:
-			sproto->s = "tls";
-			sproto->len = 3;
-		return 0;
-		case PROTO_SCTP:
-			sproto->s = "sctp";
-			sproto->len = 4;
-		return 0;
-		case PROTO_WS:
-			sproto->s = "ws";
-			sproto->len = 2;
-		return 0;
-		case PROTO_WSS:
-			sproto->s = "wss";
-			sproto->len = 3;
-		return 0;
-	}
-	return -1;
-}
 
 int pv_get_pid(struct sip_msg *msg, pv_param_t *param,
 		pv_value_t *res)
@@ -691,35 +659,44 @@ int pv_get_srcport(struct sip_msg *msg, pv_param_t *param,
 	return pv_get_uintval(msg, param, res, msg->rcv.src_port);
 }
 
-int pv_get_srcaddr_uri(struct sip_msg *msg, pv_param_t *param,
-		pv_value_t *res)
+int pv_get_srcaddr_uri_helper(struct sip_msg *msg, pv_param_t *param,
+		int tmode, pv_value_t *res)
 {
-	str sip;
-	str sproto;
+	str uri;
 	str sr;
 
 	if(msg==NULL)
 		return -1;
 
-	if(pv_get_known_proto_string(msg->rcv.proto, &sproto)<0)
+	if(get_src_uri(msg, tmode, &uri)<0)
 		return pv_get_null(msg, param, res);
 
-	sip.s = ip_addr2a(&msg->rcv.src_ip);
-	sip.len = strlen(sip.s);
-	if (sip.len + sproto.len + 32 >= pv_get_buffer_size())
+	if (uri.len + 1 >= pv_get_buffer_size())
 	{
 		LM_ERR("local buffer size exceeded\n");
 		return pv_get_null(msg, param, res);
 	}
 
 	sr.s = pv_get_buffer();
-	sr.len = snprintf(sr.s, pv_get_buffer_size(),
-			"sip:%.*s:%d;transport=%.*s", sip.len, sip.s,
-			msg->rcv.src_port, sproto.len, sproto.s);
+	strncpy(sr.s, uri.s, uri.len);
+	sr.len = uri.len;
+	sr.s[sr.len] = '\0';
 
 	return pv_get_strval(msg, param, res, &sr);
 }
 
+int pv_get_srcaddr_uri(struct sip_msg *msg, pv_param_t *param,
+		pv_value_t *res)
+{
+	return pv_get_srcaddr_uri_helper(msg, param, 0, res);
+}
+
+int pv_get_srcaddr_uri_full(struct sip_msg *msg, pv_param_t *param,
+		pv_value_t *res)
+{
+	return pv_get_srcaddr_uri_helper(msg, param, 1, res);
+}
+
 int pv_get_rcvip(struct sip_msg *msg, pv_param_t *param,
 		pv_value_t *res)
 {
@@ -1100,9 +1077,9 @@ int pv_get_proto(struct sip_msg *msg, pv_param_t *param,
 	if(msg==NULL)
 		return -1;
 
-	if(pv_get_known_proto_string(msg->rcv.proto, &s)<0)
+	if(get_valid_proto_string(msg->rcv.proto, 0, 0, &s)<0)
 	{
-		s.s = "NONE";
+		s.s = "none";
 		s.len = 4;
 	}
 
@@ -1804,6 +1781,9 @@ int pv_get_scriptvar(struct sip_msg *msg,  pv_param_t *param,
 	
 	sv= (script_var_t*)param->pvn.u.dname;
 
+	if((sv->v.flags&VAR_TYPE_NULL) && (sv->v.flags&VAR_VAL_NULL))
+			return pv_get_null(msg, param, res);
+
 	if(sv->v.flags&VAR_VAL_STR)
 	{
 		res->rs = sv->v.value.s;
@@ -1988,8 +1968,13 @@ int pv_set_scriptvar(struct sip_msg* msg, pv_param_t *param,
 	}
 	if((val==NULL) || (val->flags&PV_VAL_NULL))
 	{
-		avp_val.n = 0;
-		set_var_value((script_var_t*)param->pvn.u.dname, &avp_val, 0);
+		if(((script_var_t*)param->pvn.u.dname)->v.flags&VAR_TYPE_NULL)
+		{
+			set_var_value((script_var_t*)param->pvn.u.dname, NULL, 0);
+		} else {
+			avp_val.n = 0;
+			set_var_value((script_var_t*)param->pvn.u.dname, &avp_val, 0);
+		}
 		return 0;
 	}
 	flags = 0;
@@ -2752,9 +2737,24 @@ int pv_parse_scriptvar_name(pv_spec_p sp, str *in)
 {
 	if(in==NULL || in->s==NULL || sp==NULL)
 		return -1;
-	
+
+	sp->pvp.pvn.type = PV_NAME_PVAR;
+	sp->pvp.pvn.u.dname = (void*)add_var(in, VAR_TYPE_ZERO);
+	if(sp->pvp.pvn.u.dname==NULL)
+	{
+		LM_ERR("cannot register var [%.*s]\n", in->len, in->s);
+		return -1;
+	}
+	return 0;
+}
+
+int pv_parse_scriptvarnull_name(pv_spec_p sp, str *in)
+{
+	if(in==NULL || in->s==NULL || sp==NULL)
+		return -1;
+
 	sp->pvp.pvn.type = PV_NAME_PVAR;
-	sp->pvp.pvn.u.dname = (void*)add_var(in);
+	sp->pvp.pvn.u.dname = (void*)add_var(in, VAR_TYPE_NULL);
 	if(sp->pvp.pvn.u.dname==NULL)
 	{
 		LM_ERR("cannot register var [%.*s]\n", in->len, in->s);
@@ -2907,8 +2907,7 @@ int pv_parse_flag_param(pv_spec_p sp, str *in)
 			LM_ERR("flag not declared: [%.*s]\n", in->len, in->s);
 			return -1;
 		}
-	}
-	if (check_flag(n) < 0)
+	} else if (check_flag(n) < 0)
 	{
 		LM_ERR("bad flag value: [%.*s]\n", in->len, in->s);
 		return -1;
diff --git a/modules/pv/pv_core.h b/modules/pv/pv_core.h
index 9f2c6fc..6d6c1a5 100644
--- a/modules/pv/pv_core.h
+++ b/modules/pv/pv_core.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2005 FhG Fokus
  * Copyright (C) 2008 Daniel-Constantin Mierla (asipto.com)
  *
@@ -135,6 +133,9 @@ int pv_get_srcport(struct sip_msg *msg, pv_param_t *param,
 int pv_get_srcaddr_uri(struct sip_msg *msg, pv_param_t *param,
 		pv_value_t *res);
 
+int pv_get_srcaddr_uri_full(struct sip_msg *msg, pv_param_t *param,
+		pv_value_t *res);
+
 int pv_get_rcvip(struct sip_msg *msg, pv_param_t *param,
 		pv_value_t *res);
 
@@ -301,6 +302,7 @@ int pv_set_from_display(struct sip_msg* msg, pv_param_t *param,
 /********* end PV set functions *********/
 
 int pv_parse_scriptvar_name(pv_spec_p sp, str *in);
+int pv_parse_scriptvarnull_name(pv_spec_p sp, str *in);
 
 int pv_parse_hdr_name(pv_spec_p sp, str *in);
 
diff --git a/modules/pv/pv_select.c b/modules/pv/pv_select.c
index 41f60f7..a4b0efd 100644
--- a/modules/pv/pv_select.c
+++ b/modules/pv/pv_select.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/pv/pv_select.h b/modules/pv/pv_select.h
index b7574d9..d328885 100644
--- a/modules/pv/pv_select.h
+++ b/modules/pv/pv_select.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/pv/pv_shv.c b/modules/pv/pv_shv.c
index 128f5b7..67f03ac 100644
--- a/modules/pv/pv_shv.c
+++ b/modules/pv/pv_shv.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2007 Elena-Ramona Modroiu
  * Copyright (C) 2013 Olle E. Johansson
  *
@@ -810,7 +808,7 @@ int param_set_xvar( modparam_t type, void* val, int mode)
 		isv.n = ival;
 	}
 	if(mode==0) {
-		pkv = add_var(&s);
+		pkv = add_var(&s, VAR_TYPE_ZERO);
 		if(pkv==NULL)
 			goto error;
 		if(set_var_value(pkv, &isv, flags)==NULL)
diff --git a/modules/pv/pv_shv.h b/modules/pv/pv_shv.h
index 951328e..c9c31a9 100644
--- a/modules/pv/pv_shv.h
+++ b/modules/pv/pv_shv.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2007 Elena-Ramona Modroiu
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/pv/pv_stats.c b/modules/pv/pv_stats.c
index c60ed27..0038fba 100644
--- a/modules/pv/pv_stats.c
+++ b/modules/pv/pv_stats.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/pv/pv_stats.h b/modules/pv/pv_stats.h
index a71314b..4be01ca 100644
--- a/modules/pv/pv_stats.h
+++ b/modules/pv/pv_stats.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/pv/pv_svar.c b/modules/pv/pv_svar.c
index 6f8e3c8..2e50643 100644
--- a/modules/pv/pv_svar.c
+++ b/modules/pv/pv_svar.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2006 voice-system.ro
  *
  * This file is part of Kamailio, a free SIP server.
@@ -37,15 +35,21 @@
 #include "pv_svar.h"
 
 static script_var_t *script_vars = 0;
+static script_var_t *script_vars_null = 0;
 
-script_var_t* add_var(str *name)
+script_var_t* add_var(str *name, int vtype)
 {
 	script_var_t *it;
 
 	if(name==0 || name->s==0 || name->len<=0)
 		return 0;
 
-	for(it=script_vars; it; it=it->next)
+	if(vtype==VAR_TYPE_NULL) {
+		it=script_vars_null;
+	} else {
+		it=script_vars;
+	}
+	for(; it; it=it->next)
 	{
 		if(it->name.len==name->len
 				&& strncmp(name->s, it->name.s, name->len)==0)
@@ -69,9 +73,14 @@ script_var_t* add_var(str *name)
 	strncpy(it->name.s, name->s, name->len);
 	it->name.s[it->name.len] = '\0';
 
-	it->next = script_vars;
-
-	script_vars = it;
+	if(vtype==VAR_TYPE_NULL) {
+		it->v.flags = VAR_VAL_NULL|VAR_TYPE_NULL;
+		it->next = script_vars_null;
+		script_vars_null = it;
+	} else {
+		it->next = script_vars;
+		script_vars = it;
+	}
 
 	return it;
 }
@@ -87,11 +96,16 @@ script_var_t* set_var_value(script_var_t* var, int_str *value, int flags)
 			pkg_free(var->v.value.s.s);
 			var->v.flags &= ~VAR_VAL_STR;
 		}
+
+		if(var->v.flags&VAR_TYPE_NULL)
+			var->v.flags |= VAR_VAL_NULL;
+
 		memset(&var->v.value, 0, sizeof(int_str));
 
 		return var;
 	}
 
+	var->v.flags &= ~VAR_VAL_NULL;
 	if(flags&VAR_VAL_STR)
 	{
 		if(var->v.flags&VAR_VAL_STR)
@@ -156,6 +170,22 @@ script_var_t* get_var_by_name(str *name)
 	return 0;
 }
 
+script_var_t* get_varnull_by_name(str *name)
+{
+	script_var_t *it;
+
+	if(name==0 || name->s==0 || name->len<=0)
+		return 0;
+
+	for(it=script_vars_null; it; it=it->next)
+	{
+		if(it->name.len==name->len
+				&& strncmp(name->s, it->name.s, name->len)==0)
+			return it;
+	}
+	return 0;
+}
+
 void reset_vars(void)
 {
 	script_var_t *it;
@@ -168,6 +198,16 @@ void reset_vars(void)
 		}
 		memset(&it->v.value, 0, sizeof(int_str));
 	}
+	for(it=script_vars_null; it; it=it->next)
+	{
+		if(it->v.flags&VAR_VAL_STR)
+		{
+			pkg_free(it->v.value.s.s);
+			it->v.flags &= ~VAR_VAL_STR;
+		}
+		it->v.flags |= VAR_VAL_NULL;
+		memset(&it->v.value, 0, sizeof(int_str));
+	}
 }
 
 void destroy_vars_list(script_var_t *svl)
@@ -192,4 +232,5 @@ void destroy_vars_list(script_var_t *svl)
 void destroy_vars(void)
 {
 	destroy_vars_list(script_vars);
+	destroy_vars_list(script_vars_null);
 }
diff --git a/modules/pv/pv_svar.h b/modules/pv/pv_svar.h
index 6656c18..6c503a5 100644
--- a/modules/pv/pv_svar.h
+++ b/modules/pv/pv_svar.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2006 voice-system.ro
  *
  * This file is part of Kamailio, a free SIP server.
@@ -31,7 +29,12 @@
 
 #include "../../usr_avp.h"
 
-#define VAR_VAL_STR	(1<<0)
+#define VAR_VAL_INT		(0)		/* value is INT (other flags not set) */
+#define VAR_VAL_STR		(1<<0)  /* value is STR */
+#define VAR_VAL_NULL	(1<<1)	/* value is NULL */
+
+#define VAR_TYPE_ZERO	(0)		/* default value is 0 (type NULL not set) */
+#define VAR_TYPE_NULL	(1<<15) /* default value is NULL */
 
 typedef struct script_val {
 	int flags;
@@ -44,9 +47,10 @@ typedef struct script_var {
 	struct script_var *next;
 } script_var_t, *script_var_p;
 
-script_var_t* add_var(str *name);
+script_var_t* add_var(str *name, int vtype);
 script_var_t* set_var_value(script_var_t *var, int_str *value, int flags);
 script_var_t* get_var_by_name(str *name);
+script_var_t* get_varnull_by_name(str *name);
 
 void reset_vars(void);
 void destroy_vars(void);
diff --git a/modules/pv/pv_time.c b/modules/pv/pv_time.c
index 0e5c20b..a51d644 100644
--- a/modules/pv/pv_time.c
+++ b/modules/pv/pv_time.c
@@ -1,6 +1,4 @@
 /*
- * $Id: pv_shv.c 5291 2008-12-03 16:47:50Z miconda $
- *
  * Copyright (C) 2007 Elena-Ramona Modroiu
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/pv/pv_time.h b/modules/pv/pv_time.h
index 2806fe1..1bbfe02 100644
--- a/modules/pv/pv_time.h
+++ b/modules/pv/pv_time.h
@@ -1,6 +1,4 @@
 /*
- * $Id: pv_shv.h 5291 2008-12-03 16:47:50Z miconda $
- *
  * Copyright (C) 2007 Elena-Ramona Modroiu
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/pv/pv_trans.c b/modules/pv/pv_trans.c
index 96516f5..42798d8 100644
--- a/modules/pv/pv_trans.c
+++ b/modules/pv/pv_trans.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2007 voice-system.ro
  * Copyright (C) 2009 asipto.com
  *
@@ -179,6 +177,62 @@ static int urldecode_param(str *sin, str *sout) {
 	return 0;
 }
 
+/* Encode 7BIT PDU */
+static int pdu_7bit_encode(str sin) {
+	int i, j;
+	unsigned char hex;
+	unsigned char nleft;
+	unsigned char fill;
+	char HexTbl[] = {"0123456789ABCDEF"};
+
+	nleft = 1;
+	j = 0;
+	for(i = 0; i < sin.len; i++) {
+		hex = *(sin.s) >> (nleft - 1);
+		fill = *(sin.s+1) << (8-nleft);
+		hex = hex | fill;
+		_tr_buffer[j++] = HexTbl[hex >> 4];
+		_tr_buffer[j++] = HexTbl[hex & 0x0F];
+		nleft++;
+		if(nleft == 8) {
+			sin.s++;
+			i++;
+			nleft = 1;
+		}	   										 	
+		sin.s++;
+	}
+	_tr_buffer[j] = '\0';
+	return j;
+}
+
+/* Decode 7BIT PDU */
+static int pdu_7bit_decode(str sin) {
+	int i, j;
+	unsigned char nleft = 1;
+	unsigned char fill = 0;
+	unsigned char oldfill = 0;
+	j = 0;
+	for(i = 0; i < sin.len; i += 2) {
+		_tr_buffer[j] = (unsigned char)pv_from_hex(sin.s[i]) << 4;
+		_tr_buffer[j] |= (unsigned char)pv_from_hex(sin.s[i+1]);
+		fill = (unsigned char)_tr_buffer[j];
+		fill >>= (8 - nleft);
+		_tr_buffer[j] <<= (nleft -1 );
+		_tr_buffer[j] &= 0x7F;
+		_tr_buffer[j] |= oldfill;
+		oldfill = fill;
+		j++;
+		nleft++;
+		if(nleft == 8) {
+			_tr_buffer[j++] = oldfill;
+			nleft = 1;
+			oldfill = 0;
+		}
+	}
+	_tr_buffer[j] = '\0';
+	return j;	
+}
+
 /* -- transformations functions */
 
 /*!
@@ -312,6 +366,28 @@ int tr_eval_string(struct sip_msg *msg, tr_param_t *tp, int subtype,
 			val->rs.s = _tr_buffer;
 			val->rs.len = i;
 			break;
+		case TR_S_ENCODE7BIT:
+			if(!(val->flags&PV_VAL_STR))
+				val->rs.s = int2str(val->ri, &val->rs.len);
+			if(val->rs.len > (TR_BUFFER_SIZE*7/8) -1)
+				return -1;
+			i = pdu_7bit_encode(val->rs);
+			memset(val, 0, sizeof(pv_value_t));
+			val->flags = PV_VAL_STR;
+			val->rs.s = _tr_buffer;
+			val->rs.len = i;
+			break;
+		case TR_S_DECODE7BIT:
+			if(!(val->flags&PV_VAL_STR))
+				val->rs.s = int2str(val->ri, &val->rs.len);
+			if(val->rs.len>TR_BUFFER_SIZE/2-1)
+				return -1;
+			i = pdu_7bit_decode(val->rs);
+			memset(val, 0, sizeof(pv_value_t));
+			val->flags = PV_VAL_STR;
+			val->rs.s = _tr_buffer;
+			val->rs.len = i;
+			break;
 		case TR_S_ENCODEBASE64:
 			if(!(val->flags&PV_VAL_STR))
 				val->rs.s = int2str(val->ri, &val->rs.len);
@@ -1960,6 +2036,12 @@ char* tr_parse_string(str* in, trans_t *t)
 	} else if(name.len==11 && strncasecmp(name.s, "decode.hexa", 11)==0) {
 		t->subtype = TR_S_DECODEHEXA;
 		goto done;
+	} else if(name.len==11 && strncasecmp(name.s, "encode.7bit", 11)==0) {
+		t->subtype = TR_S_ENCODE7BIT;
+		goto done;
+	} else if(name.len==11 && strncasecmp(name.s, "decode.7bit", 11)==0) {
+		t->subtype = TR_S_DECODE7BIT;
+		goto done;
 	} else if(name.len==13 && strncasecmp(name.s, "encode.base64", 13)==0) {
 		t->subtype = TR_S_ENCODEBASE64;
 		goto done;
diff --git a/modules/pv/pv_trans.h b/modules/pv/pv_trans.h
index 346fd32..a49ad53 100644
--- a/modules/pv/pv_trans.h
+++ b/modules/pv/pv_trans.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2007 voice-system.ro
  *
  * This file is part of Kamailio, a free SIP server.
@@ -37,7 +35,7 @@ enum _tr_type { TR_NONE=0, TR_STRING, TR_URI, TR_PARAMLIST, TR_NAMEADDR,
 enum _tr_s_subtype { 
 	TR_S_NONE=0, TR_S_LEN, TR_S_INT, TR_S_MD5, TR_S_SHA256, TR_S_SHA384,
 	TR_S_SHA512, TR_S_SUBSTR, TR_S_SELECT, TR_S_ENCODEHEXA, TR_S_DECODEHEXA,
-	TR_S_ENCODEBASE64, TR_S_DECODEBASE64,
+	TR_S_ENCODE7BIT, TR_S_DECODE7BIT, TR_S_ENCODEBASE64, TR_S_DECODEBASE64,
 	TR_S_ESCAPECOMMON, TR_S_UNESCAPECOMMON, TR_S_ESCAPEUSER, TR_S_UNESCAPEUSER,
 	TR_S_ESCAPEPARAM, TR_S_UNESCAPEPARAM, TR_S_TOLOWER, TR_S_TOUPPER,
 	TR_S_STRIP, TR_S_STRIPTAIL, TR_S_PREFIXES, TR_S_PREFIXES_QUOT, TR_S_REPLACE,
diff --git a/modules/pv/pv_xavp.c b/modules/pv/pv_xavp.c
index 3ba737b..53fd99a 100644
--- a/modules/pv/pv_xavp.c
+++ b/modules/pv/pv_xavp.c
@@ -1,6 +1,4 @@
-/**
- * $Id$
- *
+/*
  * Copyright (C) 2009 Daniel-Constantin Mierla (asipto.com) 
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -23,6 +21,7 @@
 #include "../../dprint.h"
 #include "../../xavp.h"
 #include "../../pvapi.h"
+#include "../../parser/parse_param.h"
 
 #include "pv_xavp.h"
 
@@ -557,4 +556,61 @@ int pv_xavp_print(struct sip_msg* msg, char* s1, char *s2)
 	return 1;
 }
 
+/**
+ *
+ */
+int xavp_params_explode(str *params, str *xname)
+{
+	param_t* params_list = NULL;
+	param_hooks_t phooks;
+	param_t *pit=NULL;
+	str s;
+	sr_xavp_t *xavp=NULL;
+	sr_xval_t xval;
+
+	if(params==NULL || xname==NULL || params->s==NULL || xname->s==NULL
+			|| params->len<=0 || xname->len<=0)
+	{
+		LM_ERR("invalid parameters\n");
+		return -1;
+	}
+
+	s.s = params->s;
+	s.len = params->len;
+	if(s.s[s.len-1]==';')
+		s.len--;
+	if (parse_params(&s, CLASS_ANY, &phooks, &params_list)<0) {
+		LM_DBG("invalid formatted values [%.*s]\n", params->len, params->s);
+		return -1;
+	}
+
+	if(params_list==NULL) {
+		return -1;
+	}
+
+
+	for (pit = params_list; pit; pit=pit->next)
+	{
+		memset(&xval, 0, sizeof(sr_xval_t));
+		xval.type = SR_XTYPE_STR;
+		xval.v.s = pit->body;
+		if(xavp_add_value(&pit->name, &xval, &xavp)==NULL) {
+			free_params(params_list);
+			xavp_destroy_list(&xavp);
+			return -1;
+		}
+	}
+	free_params(params_list);
+
+	/* add main xavp in root list */
+	memset(&xval, 0, sizeof(sr_xval_t));
+	xval.type = SR_XTYPE_XAVP;
+	xval.v.xavp = xavp;
+	if(xavp_add_value(xname, &xval, NULL)==NULL) {
+		xavp_destroy_list(&xavp);
+		return -1;
+	}
+
+	return 0;
+}
 #endif
diff --git a/modules/pv/pv_xavp.h b/modules/pv/pv_xavp.h
index 4851b3f..3c8238e 100644
--- a/modules/pv/pv_xavp.h
+++ b/modules/pv/pv_xavp.h
@@ -1,6 +1,4 @@
-/**
- * $Id$
- *
+/*
  * Copyright (C) 2009 Daniel-Constantin Mierla (asipto.com) 
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -31,5 +29,7 @@ int pv_parse_xavp_name(pv_spec_p sp, str *in);
 
 int pv_xavp_print(struct sip_msg* msg, char* s1, char *s2);
 
+int xavp_params_explode(str *params, str *xname);
+
 #endif
 #endif
diff --git a/modules/qos/Makefile b/modules/qos/Makefile
index 50a2694..c1c54c7 100644
--- a/modules/qos/Makefile
+++ b/modules/qos/Makefile
@@ -1,6 +1,4 @@
 #
-# $Id$
-#
 # WARNING: do not run this directly, it should be run by the master Makefile
 #
 # Copyright (C) 2006 SOMA Networks, Inc.
@@ -23,9 +21,6 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
 # USA
 #
-# History:
-# --------
-#  2007-07-16  initial version (osas)
 #
 
 include ../../Makefile.defs
diff --git a/modules/qos/qos.c b/modules/qos/qos.c
index 09338e0..c6a5109 100644
--- a/modules/qos/qos.c
+++ b/modules/qos/qos.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * QoS module - support for tracking dialogs and SDP
  *
  * Copyright (C) 2007 SOMA Networks, Inc.
@@ -23,9 +21,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
  * USA
  *
- * History:
- * --------
- * 2007-07-16 initial version (osas)
  */
 
 #include <stdio.h>
@@ -115,7 +110,7 @@ static int mod_init(void)
 
 	/* Register the main (static) dialog call back.  */
 	if (load_dlg_api(&dialog_st) != 0) {
-		LM_ERR("Can't load dialog hooks");
+		LM_ERR("Can't load dialog hooks\n");
 		return(-1);
 	}
 
diff --git a/modules/qos/qos_cb.c b/modules/qos/qos_cb.c
index 6ba051e..3c0014e 100644
--- a/modules/qos/qos_cb.c
+++ b/modules/qos/qos_cb.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2007 SOMA Networks, Inc.
  * Written by Ovidiu Sas (osas)
  *
@@ -20,9 +18,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2007-07-14  initial version (osas)
  */
 
 
diff --git a/modules/qos/qos_cb.h b/modules/qos/qos_cb.h
index ec38877..3db4b66 100644
--- a/modules/qos/qos_cb.h
+++ b/modules/qos/qos_cb.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2007 SOMA Networks, Inc.
  * Written by Ovidiu Sas (osas)
  *
@@ -20,9 +18,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2007-07-11  initial version (osas)
  */
 
 #ifndef _QOS_QOS_CB_H_
diff --git a/modules/qos/qos_ctx_helpers.c b/modules/qos/qos_ctx_helpers.c
index 1fa555e..9aba8ea 100644
--- a/modules/qos/qos_ctx_helpers.c
+++ b/modules/qos/qos_ctx_helpers.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2007 SOMA Networks, Inc.
  * Written by Ovidiu Sas (osas)
  *
@@ -20,9 +18,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * -------
- * 2007-07-16 initial version (osas)
  */
 
 #include "../../mem/mem.h"
diff --git a/modules/qos/qos_ctx_helpers.h b/modules/qos/qos_ctx_helpers.h
index 650903f..96782a9 100644
--- a/modules/qos/qos_ctx_helpers.h
+++ b/modules/qos/qos_ctx_helpers.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2007 SOMA Networks, INC.
  * Written By Ovidiu Sas
  *
@@ -21,9 +19,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
  * USA
  *
- * History:
- * --------
- * 2007-07-16 initial version (osas)
  */
 
 #ifndef _QOS_CTX_HELPERS_H_
diff --git a/modules/qos/qos_handlers.c b/modules/qos/qos_handlers.c
index d5d950c..a3b5e98 100644
--- a/modules/qos/qos_handlers.c
+++ b/modules/qos/qos_handlers.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2007 SOMA Networks, Inc.
  * Written by Ovidiu Sas (osas)
  *
@@ -21,9 +19,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
  * USA
  *
- * History:
- * --------
- * 2007-07-16 initial version (osas)
  */
 
 
diff --git a/modules/qos/qos_handlers.h b/modules/qos/qos_handlers.h
index 0afc417..f5cb7e7 100644
--- a/modules/qos/qos_handlers.h
+++ b/modules/qos/qos_handlers.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2007 SOMA Networks, Inc.
  * Written By Ovidiu Sas (osas)
  *
@@ -21,9 +19,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
  * USA
  *
- * History:
- * --------
- * 2007-07-16 initial version (osas)
  */
 
 #ifndef _QOS_HANDLERS_H_
diff --git a/modules/qos/qos_load.h b/modules/qos/qos_load.h
index 68208ea..ed5b042 100644
--- a/modules/qos/qos_load.h
+++ b/modules/qos/qos_load.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2007 SOMA Networks, Inc.
  * Written by Ovidiu Sas (osas)
  *
@@ -20,9 +18,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2007-07-14  initial version (osas)
  */
 
 #ifndef _QOS_QOS_LOAD_H_
diff --git a/modules/qos/qos_mi.c b/modules/qos/qos_mi.c
index b1ab3fc..707ab91 100644
--- a/modules/qos/qos_mi.c
+++ b/modules/qos/qos_mi.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2007 SOMA Networks, Inc.
  * Written by Ovidiu Sas (osas)
  *
@@ -21,9 +19,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
  * USA
  *
- * History:
- * --------
- * 2007-07-16 initial version (osas)
  */
 
 
diff --git a/modules/qos/qos_mi.h b/modules/qos/qos_mi.h
index a539c63..ba20fed 100644
--- a/modules/qos/qos_mi.h
+++ b/modules/qos/qos_mi.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2007 SOMA Networks, Inc.
  * Written By Ovidiu Sas (osas)
  *
@@ -21,9 +19,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
  * USA
  *
- * History:
- * --------
- * 2007-07-16 initial version (osas)
  */
 
 #ifndef _QOS_MI_H_
diff --git a/modules/ratelimit/README b/modules/ratelimit/README
index 3051560..fe4ee88 100644
--- a/modules/ratelimit/README
+++ b/modules/ratelimit/README
@@ -245,7 +245,7 @@ Chapter 1. Admin Guide
 4.1. Kamailio Modules
 
    The following modules must be loaded before this module:
-     * No dependencies on other Kamailio modules.
+     * SL: Stateless request handling.
 
 4.2. External Libraries or Applications
 
@@ -327,7 +327,7 @@ modparam("ratelimit", "pipe", "4:NETWORK:10000")
    6.1. rl_check([pvar])
    6.2. rl_check_pipe([pipe_no])
 
-6.1.  rl_check([pvar])
+6.1. rl_check([pvar])
 
    Check the current request against the matched ratelimit algorithm. If
    no parameter is provided, the queue will be matched based on method
@@ -374,7 +374,7 @@ modparam("ratelimit", "pipe", "4:NETWORK:10000")
         };
 ...
 
-6.2.  rl_check_pipe([pipe_no])
+6.2. rl_check_pipe([pipe_no])
 
    Check the current request against the matched ratelimit algorithm. If
    no parameter is provided, the queue will be matched based on method
@@ -419,7 +419,7 @@ modparam("ratelimit", "pipe", "4:NETWORK:10000")
    7.8. rl.push_load
    7.9. rl.set_dbg
 
-7.1.  rl.stats
+7.1. rl.stats
 
    Lists the parameters and variables in the ratelimit module.
 
@@ -430,7 +430,7 @@ modparam("ratelimit", "pipe", "4:NETWORK:10000")
    RPC Command Format:
                 kamcmd rl.stats
 
-7.2.  rl.set_pipe
+7.2. rl.set_pipe
 
    Sets the pipe parameters for the given pipe id.
 
@@ -444,7 +444,7 @@ modparam("ratelimit", "pipe", "4:NETWORK:10000")
    RPC Command Format:
                 kamcmd rl.set_pipe 2 RED 10
 
-7.3.  rl.get_pipes
+7.3. rl.get_pipes
 
    Gets the list of in use pipes.
 
@@ -455,7 +455,7 @@ modparam("ratelimit", "pipe", "4:NETWORK:10000")
    RPC Command Format:
                 kamcmd rl.get_pipes
 
-7.4.  rl.set_queue
+7.4. rl.set_queue
 
    Sets the queue parameters for the given queue id.
 
@@ -469,7 +469,7 @@ modparam("ratelimit", "pipe", "4:NETWORK:10000")
    RPC Command Format:
                 kamcmd rl.set_queue 3 INVITE 2
 
-7.5.  rl.get_queues
+7.5. rl.get_queues
 
    Gets the list of in use queues.
 
@@ -480,7 +480,7 @@ modparam("ratelimit", "pipe", "4:NETWORK:10000")
    RPC Command Format:
                 kamcmd rl.get_queues
 
-7.6.  rl.set_pid
+7.6. rl.set_pid
 
    Sets the PID Controller parameters for the Feedback Algorithm.
 
@@ -494,7 +494,7 @@ modparam("ratelimit", "pipe", "4:NETWORK:10000")
    RPC Command Format:
                 kamcmd rl.set_pid 0.5 0.5 0.5
 
-7.7.  rl.get_pid
+7.7. rl.get_pid
 
    Gets the list of in use PID Controller parameters.
 
@@ -505,7 +505,7 @@ modparam("ratelimit", "pipe", "4:NETWORK:10000")
    RPC Command Format:
                 kamcmd rl.get_pid
 
-7.8.  rl.push_load
+7.8. rl.push_load
 
    Force the value of the load parameter. This method is useful for
    testing the Feedback algorithm.
@@ -519,7 +519,7 @@ modparam("ratelimit", "pipe", "4:NETWORK:10000")
    RPC Command Format:
                 kamcmd rl.push_load 0.85
 
-7.9.  rl.set_dbg
+7.9. rl.set_dbg
 
    This function will enable/disable a WARNING debug log exposing the
    internal counters for each pipe (useful in monitoring the ratelimit
diff --git a/modules/ratelimit/doc/ratelimit_admin.xml b/modules/ratelimit/doc/ratelimit_admin.xml
index 52843a6..865fc16 100644
--- a/modules/ratelimit/doc/ratelimit_admin.xml
+++ b/modules/ratelimit/doc/ratelimit_admin.xml
@@ -163,7 +163,7 @@
 			<itemizedlist>
 			<listitem>
 			<para>
-				<emphasis>No dependencies on other &kamailio; modules</emphasis>.
+				<emphasis>SL: Stateless request handling</emphasis>.
 			</para>
 			</listitem>
 			</itemizedlist>
diff --git a/modules/ratelimit/ratelimit.c b/modules/ratelimit/ratelimit.c
index 2770822..dc5748f 100644
--- a/modules/ratelimit/ratelimit.c
+++ b/modules/ratelimit/ratelimit.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * ratelimit module
  *
  * Copyright (C) 2006 Hendrik Scholz <hscholz at raisdorf.net>
@@ -22,12 +20,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * ---------
- *
- * 2008-01-10 ported from SER project (osas)
- * 2008-01-16 ported enhancements from openims project (osas)
- * 2020-04-28 add sip-router rpc interface (osas)
  */
 
 #include <stdio.h>
@@ -333,9 +325,14 @@ static int get_cpuload(double * load)
 	FILE * f = fopen("/proc/stat", "r");
 	double vload;
 	int ncpu;
+	static int errormsg = 0;
 
 	if (! f) {
-		LM_ERR("could not open /proc/stat\n");
+		/* Only output this error message five times */
+		if (errormsg < 5) {
+			LM_ERR("could not open /proc/stat\n");
+			errormsg++;
+		}
 		return -1;
 	}
 	if (fscanf(f, "cpu  %lld%lld%lld%lld%lld%lld%lld%lld",
diff --git a/modules/regex/regex_mod.c b/modules/regex/regex_mod.c
index adc0de9..71acfc9 100644
--- a/modules/regex/regex_mod.c
+++ b/modules/regex/regex_mod.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * regex module - pcre operations
  *
  * Copyright (C) 2008 Iñaki Baz Castillo
@@ -21,13 +19,8 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2011-02-22  pcre_match_group() allows now pseudo-variable as group argument.
- *  2009-01-14  initial version (Iñaki Baz Castillo).
  */
 
-
 /*!
  * \file
  * \brief REGEX :: Perl-compatible regular expressions using PCRE library
diff --git a/modules/registrar/Makefile b/modules/registrar/Makefile
index 32cc78b..ac6a2f4 100644
--- a/modules/registrar/Makefile
+++ b/modules/registrar/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # registrar module makefile
 #
diff --git a/modules/registrar/README b/modules/registrar/README
index 059a210..e3f5a7f 100644
--- a/modules/registrar/README
+++ b/modules/registrar/README
@@ -8,6 +8,10 @@ Daniel-Constantin Mierla
 
    <miconda at gmail.com>
 
+Juha Heinanen
+
+   <jh at tutpro.com>
+
 Edited by
 
 Jan Janak
@@ -55,20 +59,23 @@ Bogdan-Andre Iancu
               3.18. use_path (integer)
               3.19. path_mode (integer)
               3.20. path_use_received (integer)
-              3.21. reg_callid_avp (string)
-              3.22. xavp_cfg (string)
-              3.23. xavp_rcd (string)
-              3.24. gruu_enabled (integer)
-              3.25. outbound_mode (integer)
-              3.26. regid_mode (integer)
-              3.27. flow_timer (integer)
+              3.21. path_check_local (integer)
+              3.22. reg_callid_avp (string)
+              3.23. xavp_cfg (string)
+              3.24. xavp_rcd (string)
+              3.25. gruu_enabled (integer)
+              3.26. outbound_mode (integer)
+              3.27. regid_mode (integer)
+              3.28. flow_timer (integer)
 
         4. Functions
 
               4.1. save(domain, [, flags [, uri]])
               4.2. lookup(domain [, uri])
               4.3. lookup_branches(domain)
-              4.4. registered(domain [, uri])
+              4.4. registered(domain [, uri [, match_option [,
+                      match_action]]])
+
               4.5. add_sock_hdr(hdr_name)
               4.6. unregister(domain, uri[, ruid])
               4.7. reg_fetch_contacts(domain, uri, profile)
@@ -113,23 +120,24 @@ Bogdan-Andre Iancu
    1.17. Set use_path parameter
    1.18. Set path_mode parameter
    1.19. Set path_use_received parameter
-   1.20. Set reg_callid_avp parameter
-   1.21. Set xavp_cfg parameter
-   1.22. Set xavp_rcd parameter
-   1.23. Set gruu_enabled parameter
-   1.24. Set outbound_mode parameter
-   1.25. Set regid_mode parameter
-   1.26. Set flow_timer parameter
-   1.27. save usage
-   1.28. lookup usage
-   1.29. lookup_branches usage
-   1.30. registered usage
-   1.31. add_sock_hdr usage
-   1.32. unregister usage
-   1.33. reg_fetch_contacts usage
-   1.34. reg_free_contacts usage
-   1.35. event_route[usrloc:contact-expired] usage
-   1.36. $ulc(name) usage
+   1.20. Set path_check_local parameter
+   1.21. Set reg_callid_avp parameter
+   1.22. Set xavp_cfg parameter
+   1.23. Set xavp_rcd parameter
+   1.24. Set gruu_enabled parameter
+   1.25. Set outbound_mode parameter
+   1.26. Set regid_mode parameter
+   1.27. Set flow_timer parameter
+   1.28. save usage
+   1.29. lookup usage
+   1.30. lookup_branches usage
+   1.31. registered usage
+   1.32. add_sock_hdr usage
+   1.33. unregister usage
+   1.34. reg_fetch_contacts usage
+   1.35. reg_free_contacts usage
+   1.36. event_route[usrloc:contact-expired] usage
+   1.37. $ulc(name) usage
 
 Chapter 1. Admin Guide
 
@@ -167,20 +175,21 @@ Chapter 1. Admin Guide
         3.18. use_path (integer)
         3.19. path_mode (integer)
         3.20. path_use_received (integer)
-        3.21. reg_callid_avp (string)
-        3.22. xavp_cfg (string)
-        3.23. xavp_rcd (string)
-        3.24. gruu_enabled (integer)
-        3.25. outbound_mode (integer)
-        3.26. regid_mode (integer)
-        3.27. flow_timer (integer)
+        3.21. path_check_local (integer)
+        3.22. reg_callid_avp (string)
+        3.23. xavp_cfg (string)
+        3.24. xavp_rcd (string)
+        3.25. gruu_enabled (integer)
+        3.26. outbound_mode (integer)
+        3.27. regid_mode (integer)
+        3.28. flow_timer (integer)
 
    4. Functions
 
         4.1. save(domain, [, flags [, uri]])
         4.2. lookup(domain [, uri])
         4.3. lookup_branches(domain)
-        4.4. registered(domain [, uri])
+        4.4. registered(domain [, uri [, match_option [, match_action]]])
         4.5. add_sock_hdr(hdr_name)
         4.6. unregister(domain, uri[, ruid])
         4.7. reg_fetch_contacts(domain, uri, profile)
@@ -288,13 +297,14 @@ Chapter 1. Admin Guide
    3.18. use_path (integer)
    3.19. path_mode (integer)
    3.20. path_use_received (integer)
-   3.21. reg_callid_avp (string)
-   3.22. xavp_cfg (string)
-   3.23. xavp_rcd (string)
-   3.24. gruu_enabled (integer)
-   3.25. outbound_mode (integer)
-   3.26. regid_mode (integer)
-   3.27. flow_timer (integer)
+   3.21. path_check_local (integer)
+   3.22. reg_callid_avp (string)
+   3.23. xavp_cfg (string)
+   3.24. xavp_rcd (string)
+   3.25. gruu_enabled (integer)
+   3.26. outbound_mode (integer)
+   3.27. regid_mode (integer)
+   3.28. flow_timer (integer)
 
 3.1. default_expires (integer)
 
@@ -477,9 +487,12 @@ modparam("registrar", "received_param", "rcv")
 3.13. max_contacts (integer)
 
    The parameter can be used to limit the number of contacts per AOR
-   (Address of Record) in the user location database. Value 0 disables the
-   check. This parameter can be modified via the Kamailio config
-   framework.
+   (Address of Record) in the user location database. If the maximum
+   number of contacts is exceeded, Kamailio will not accept the
+   registration and send an error response. Value 0 disables the check.
+   This parameter can be modified via the Kamailio config framework.
+   (Please also check the flag for save() if you only want only one active
+   registration).
 
    Default value is 0.
 
@@ -605,7 +618,25 @@ modparam("registrar", "path_mode", 0)
 modparam("registrar", "path_use_received", 1)
 ...
 
-3.21. reg_callid_avp (string)
+3.21. path_check_local (integer)
+
+   If set to 1, when performing a lookup the Path (if present) is
+   evaluated and if the first hop is local (according to "myself" test),
+   we skip it to avoid unnecessary looping.
+
+   This is useful if multiple servers are sharing a common location
+   database, each saving contacts with their local address as the Path.
+
+   Default value is 0 (disabled).
+
+   Example 1.20. Set path_check_local parameter
+...
+modparam("registrar", "path_check_local", 1)
+...
+
+3.22. reg_callid_avp (string)
+
+   obsolete. use match_option in registered function
 
    If reg_callid_avp is defined and populated when the registered() is
    invoked, the result is TRUE only if an active registration with the
@@ -613,12 +644,12 @@ modparam("registrar", "path_use_received", 1)
 
    Default value is NULL (disabled).
 
-   Example 1.20. Set reg_callid_avp parameter
+   Example 1.21. Set reg_callid_avp parameter
 ...
 modparam("registrar", "reg_callid_avp", "$avp(s:avp)")
 ...
 
-3.22. xavp_cfg (string)
+3.23. xavp_cfg (string)
 
    Defines the name of XAVP class to store runtime module config values.
    The values are stored as inner XAVPs, like $xavp(class=>attribute).
@@ -628,18 +659,20 @@ modparam("registrar", "reg_callid_avp", "$avp(s:avp)")
        parameter value.
      * socket - the string representing the socket on which the register
        rquest was received, as alternative to using the sock_hdr.
+     * q - q value of contact (integer 0-1000). It overrides q value given
+       in contact header and default_q parameter.
 
    For example. if this parameter is set to 'reg', then the number of
    maximum contacts can be set in $xavp(reg=>max_contacts).
 
    Default value is NULL (disabled).
 
-   Example 1.21. Set xavp_cfg parameter
+   Example 1.22. Set xavp_cfg parameter
 ...
 modparam("registrar", "xavp_cfg", "reg")
 ...
 
-3.23. xavp_rcd (string)
+3.24. xavp_rcd (string)
 
    Defines the name of XAVP class to store details from the location
    records. The values are stored as inner XAVPs, like
@@ -651,12 +684,12 @@ modparam("registrar", "xavp_cfg", "reg")
 
    Default value is NULL (disabled).
 
-   Example 1.22. Set xavp_rcd parameter
+   Example 1.23. Set xavp_rcd parameter
 ...
 modparam("registrar", "xavp_rcd", "ulrcd")
 ...
 
-3.24. gruu_enabled (integer)
+3.25. gruu_enabled (integer)
 
    If set to 1 and the "+sip.instance" parameter to Contact header of
    REGISTER is present, then the value of the parameter is saved to
@@ -666,12 +699,12 @@ modparam("registrar", "xavp_rcd", "ulrcd")
 
    Default value is 1 (enabled).
 
-   Example 1.23. Set gruu_enabled parameter
+   Example 1.24. Set gruu_enabled parameter
 ...
 modparam("registrar", "gruu_enabled", 0)
 ...
 
-3.25. outbound_mode (integer)
+3.26. outbound_mode (integer)
 
    If set to 0 this module will accept REGISTER requests that do not
    contain a "Supported:" header with the outbound options-tag. The 200 OK
@@ -694,12 +727,12 @@ modparam("registrar", "gruu_enabled", 0)
 
    Default value is 0.
 
-   Example 1.24. Set outbound_mode parameter
+   Example 1.25. Set outbound_mode parameter
 ...
 modparam("registrar", "outbound_mode", 2)
 ...
 
-3.26. regid_mode (integer)
+3.27. regid_mode (integer)
 
    If set to 0 this module will ignore the "regid" contact param when
    saving REGISTER request if the request does not indicate support for
@@ -711,12 +744,12 @@ modparam("registrar", "outbound_mode", 2)
 
    Default value is 0.
 
-   Example 1.25. Set regid_mode parameter
+   Example 1.26. Set regid_mode parameter
 ...
 modparam("registrar", "regid_mode", 1)
 ...
 
-3.27. flow_timer (integer)
+3.28. flow_timer (integer)
 
    If set to 0 then this module will not add a "Flow-Timer:" header to 200
    OK responses to REGISTER requests.
@@ -738,7 +771,7 @@ modparam("registrar", "regid_mode", 1)
 
    Default value is 0.
 
-   Example 1.26. Set flow_timer parameter
+   Example 1.27. Set flow_timer parameter
 ...
 modparam("registrar", "flow_timer", 25)
 ...
@@ -748,7 +781,7 @@ modparam("registrar", "flow_timer", 25)
    4.1. save(domain, [, flags [, uri]])
    4.2. lookup(domain [, uri])
    4.3. lookup_branches(domain)
-   4.4. registered(domain [, uri])
+   4.4. registered(domain [, uri [, match_option [, match_action]]])
    4.5. add_sock_hdr(hdr_name)
    4.6. unregister(domain, uri[, ruid])
    4.7. reg_fetch_contacts(domain, uri, profile)
@@ -792,7 +825,7 @@ modparam("registrar", "flow_timer", 25)
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE and
    REPLY_ROUTE.
 
-   Example 1.27. save usage
+   Example 1.28. save usage
 ...
 save("location");
 save("location", "0x01");
@@ -825,7 +858,7 @@ save("location", "0x00", "sip:test at kamailio.org");
 
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE.
 
-   Example 1.28. lookup usage
+   Example 1.29. lookup usage
 ...
 lookup("location");
 switch ($retcode) {
@@ -851,12 +884,12 @@ switch ($retcode) {
 
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE.
 
-   Example 1.29. lookup_branches usage
+   Example 1.30. lookup_branches usage
 ...
 lookup_branches("location");
 ...
 
-4.4. registered(domain [, uri])
+4.4. registered(domain [, uri [, match_option [, match_action]]])
 
    The function returns true if the AOR in the Request-URI is registered,
    false otherwise. The function does not modify the message being
@@ -867,16 +900,32 @@ lookup_branches("location");
      * domain - Name of table that should be used for the lookup.
      * uri (optional) - SIP URI to do be used instead of R-URI. It can be
        a dynamic string with pseudo-variables.
+     * match_option (optional) - flag parameter to restrict contact
+       search. use reg_xavp_cfg to set the values to compare to.
+       flag values is as follows:
+          + 1 - match_callid
+          + 2 - match_received
+          + 4 - match_contact
+     * match_action (optional) - actions to perform when match is
+       positive.
+       flag values is as follows:
+          + 1 - set xavp_rcd with value from matched contact
 
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE.
 
-   Example 1.30. registered usage
+   Example 1.31. registered usage
 ...
 if (registered("location")) {
         sl_send_reply("100", "Trying");
         ...
 };
 ...
+$xavp(regcfg=>match_received) = $su;
+if (registered("location","$rz:$Au", 2)) {
+        sl_send_reply("100", "Trying");
+        ...
+};
+...
 
 4.5. add_sock_hdr(hdr_name)
 
@@ -890,7 +939,7 @@ if (registered("location")) {
 
    This function can be used from REQUEST_ROUTE.
 
-   Example 1.31. add_sock_hdr usage
+   Example 1.32. add_sock_hdr usage
 ...
 add_sock_hdr("Sock-Info");
 ...
@@ -914,7 +963,7 @@ add_sock_hdr("Sock-Info");
 
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE.
 
-   Example 1.32. unregister usage
+   Example 1.33. unregister usage
 ...
 unregister("location", "$ru");
 unregister("location", "sip:user at kamailio.org");
@@ -938,7 +987,7 @@ unregister("location", "", "$ruid");
 
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE.
 
-   Example 1.33. reg_fetch_contacts usage
+   Example 1.34. reg_fetch_contacts usage
 ...
 reg_fetch_contacts("location", "$ru", "callee");
 reg_fetch_contacts("location", "sip:user at kamailio.org", "caller");
@@ -957,7 +1006,7 @@ reg_fetch_contacts("location", "sip:user at kamailio.org", "caller");
 
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE.
 
-   Example 1.34. reg_free_contacts usage
+   Example 1.35. reg_free_contacts usage
 ...
 reg_free_contacts("callee");
 ...
@@ -971,7 +1020,7 @@ reg_free_contacts("callee");
    Executed when a contact in location table has expired. The variable
    $ulc(exp=>...) is filled with the attributes of the expired contact.
 
-   Example 1.35. event_route[usrloc:contact-expired] usage
+   Example 1.36. event_route[usrloc:contact-expired] usage
 ...
 event_route[usrloc:contact-expired] {
     xlog("expired contact for $ulc(exp=>aor)\n");
@@ -1039,11 +1088,12 @@ event_route[usrloc:contact-expired] {
      * ruid - record unique ID
      * reg-id - reg-id value
      * instance - instance value
+     * conid - TCP socket internal connection ID ($null if UDP)
 
    The pseudo-variable accepts positive index value to access a specific
    contact record.
 
-   Example 1.36. $ulc(name) usage
+   Example 1.37. $ulc(name) usage
 ...
 if(reg_fetch_contacts("location", "$fu", "caller"))
 {
diff --git a/modules/registrar/api.c b/modules/registrar/api.c
index 564b252..cf8f37a 100644
--- a/modules/registrar/api.c
+++ b/modules/registrar/api.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Functions that process REGISTER message 
  * and store data in usrloc
  *
diff --git a/modules/registrar/api.h b/modules/registrar/api.h
index 11d8b15..0fabb3a 100644
--- a/modules/registrar/api.h
+++ b/modules/registrar/api.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Functions that process REGISTER message 
  * and store data in usrloc
  *
diff --git a/modules/registrar/common.c b/modules/registrar/common.c
index f81f69b..53d8cc1 100644
--- a/modules/registrar/common.c
+++ b/modules/registrar/common.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Common stuff
  *
  * Copyright (C) 2001-2003 FhG Fokus
@@ -21,12 +19,7 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *	
- * History
- * ------
- * 2003-02-14 un-escaping added (janakj)
- * 2006-09-19 AOR may be provided via an AVP instead of being fetched
- *            from URI (bogdan)
-*/
+ */
 
 /*!
  * \file
diff --git a/modules/registrar/common.h b/modules/registrar/common.h
index cf44eee..5f3f66d 100644
--- a/modules/registrar/common.h
+++ b/modules/registrar/common.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Common stuff
  *
  * Copyright (C) 2001-2003 FhG Fokus
diff --git a/modules/registrar/config.c b/modules/registrar/config.c
index b0e580d..0f628dc 100644
--- a/modules/registrar/config.c
+++ b/modules/registrar/config.c
@@ -1,13 +1,12 @@
 /*
- * $Id$
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/modules/registrar/config.h b/modules/registrar/config.h
index 249e895..f82ba63 100644
--- a/modules/registrar/config.h
+++ b/modules/registrar/config.h
@@ -1,7 +1,5 @@
 /*
- * $Id$
- *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/modules/registrar/doc/registrar.xml b/modules/registrar/doc/registrar.xml
index 4328ccf..8e8143c 100644
--- a/modules/registrar/doc/registrar.xml
+++ b/modules/registrar/doc/registrar.xml
@@ -26,6 +26,11 @@
 		<surname>Mierla</surname>
 		<email>miconda at gmail.com</email>
 		</author>
+		<author>
+		<firstname>Juha</firstname>
+		<surname>Heinanen</surname>
+		<email>jh at tutpro.com</email>
+		</author>
 		<editor>
 		<firstname>Jan</firstname>
 		<surname>Janak</surname>
diff --git a/modules/registrar/doc/registrar_admin.xml b/modules/registrar/doc/registrar_admin.xml
index 5530e15..672cee8 100644
--- a/modules/registrar/doc/registrar_admin.xml
+++ b/modules/registrar/doc/registrar_admin.xml
@@ -406,9 +406,13 @@ modparam("registrar", "received_param", "rcv")
 		<title><varname>max_contacts</varname> (integer)</title>
 		<para>
 		The parameter can be used to limit the number of contacts per 
-		AOR (Address of Record) in the user location database. Value 0 
-		disables the check. This parameter can be modified via the &kamailio;
-		config framework.
+		AOR (Address of Record) in the user location database.
+		If the maximum number of contacts is exceeded, &kamailio; will not
+		accept the registration and send an error response. 
+		Value 0 disables the check. This parameter can be modified via 
+		the &kamailio; config framework.
+		(Please also check the flag for <function>save()</function> if you only want
+		only one active registration).
 		</para>
 		<para>
 		<emphasis>
@@ -626,9 +630,40 @@ modparam("registrar", "path_use_received", 1)
 		</example>
 	</section>
 
+	<section id="registrar.p.path_check_local">
+		<title><varname>path_check_local</varname> (integer)</title>
+		<para>
+		If set to 1, when performing a lookup the Path (if present) is evaluated
+		and if the first hop is local (according to <quote>myself</quote> test), we
+		skip it	to avoid unnecessary looping.
+		</para>
+		<para>
+		This is useful if multiple servers are sharing a common location database,
+		each saving contacts with their local address as the Path.
+		</para>
+		<para>
+		<emphasis>
+		Default value is 0 (disabled).
+		</emphasis>
+		</para>
+		<example>
+		<title>Set <varname>path_check_local</varname> parameter</title>
+		<programlisting format="linespecific">
+...
+modparam("registrar", "path_check_local", 1)
+...
+		</programlisting>
+		</example>
+	</section>
+
 	<section id="registrar.p.reg_callid_avp">
 		<title><varname>reg_callid_avp</varname> (string)</title>
 		<para>
+			<emphasis>
+				obsolete. use match_option in registered function
+			</emphasis>
+		</para>
+		<para>
 		If reg_callid_avp is defined and populated when the
 		<function>registered()</function> is invoked, the result is 
 		TRUE only if an active registration with
@@ -671,6 +706,14 @@ modparam("registrar", "reg_callid_avp", "$avp(s:avp)")
 				to using the sock_hdr.
 			</para>
 		</listitem>
+		<listitem>
+			<para>
+				<emphasis>q</emphasis> - q value of contact
+				(integer 0-1000). It
+				overrides q value given in contact header and
+				default_q parameter.
+			</para>
+		</listitem>
 		</itemizedlist>
 		<para>
 			For example. if this parameter is set to 'reg', then the number
@@ -1064,7 +1107,7 @@ lookup_branches("location");
 
 	<section id="registrar.f.registered">
 		<title>
-		<function moreinfo="none">registered(domain [, uri])</function>
+		<function moreinfo="none">registered(domain [, uri [, match_option [, match_action]]])</function>
 		</title>
 		<para>
 		The function returns true if the AOR in the Request-URI is 
@@ -1086,6 +1129,35 @@ lookup_branches("location");
 			of R-URI. It can be a dynamic string with pseudo-variables.
 			</para>
 		</listitem>
+		<listitem>
+			<para>
+			<emphasis>match_option</emphasis> (optional) - flag parameter to restrict
+			contact search. use reg_xavp_cfg to set the values to compare to.
+			</para>
+            <para>flag values is as follows:</para>
+			<itemizedlist>
+				<listitem>
+					<para>1 - match_callid</para>
+				</listitem>
+				<listitem>
+					<para>2 - match_received</para>
+				</listitem>
+				<listitem>
+					<para>4 - match_contact</para>
+				</listitem>
+			</itemizedlist>			
+		</listitem>
+		<listitem>
+			<para>
+			<emphasis>match_action</emphasis> (optional) - actions to perform when match is positive.
+			</para>
+            <para>flag values is as follows:</para>
+			<itemizedlist>
+				<listitem>
+					<para>1 - set xavp_rcd with value from matched contact</para>
+				</listitem>
+			</itemizedlist>						
+		</listitem>
 		</itemizedlist>
 		<para>
 		This function can be used from REQUEST_ROUTE, FAILURE_ROUTE.
@@ -1099,6 +1171,13 @@ if (registered("location")) {
 	...
 };
 ...
+$xavp(regcfg=>match_received) = $su;
+if (registered("location","$rz:$Au", 2)) {
+	sl_send_reply("100", "Trying");
+	...
+};
+...
+
 </programlisting>
 		</example>
 	</section>
@@ -1417,6 +1496,10 @@ event_route[usrloc:contact-expired] {
 				<para><emphasis>instance</emphasis> - instance value
 				</para>
 				</listitem>	  
+				<listitem>
+				<para><emphasis>conid</emphasis> - TCP socket internal connection ID ($null if UDP)
+				</para>
+				</listitem>	  
 			</itemizedlist>
 			<para>
 				The pseudo-variable accepts positive index value to access
diff --git a/modules/registrar/lookup.c b/modules/registrar/lookup.c
index 1d25acd..efbe39c 100644
--- a/modules/registrar/lookup.c
+++ b/modules/registrar/lookup.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Lookup contacts in usrloc
  *
  * Copyright (C) 2001-2003 FhG Fokus
@@ -21,9 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * ---------
- * 2003-03-12 added support for zombie state (nils)
  */
 /*!
  * \file
@@ -41,6 +36,7 @@
 #include "../../action.h"
 #include "../../mod_fix.h"
 #include "../../parser/parse_rr.h"
+#include "../../forward.h"
 #include "../usrloc/usrloc.h"
 #include "common.h"
 #include "regtime.h"
@@ -121,6 +117,8 @@ int lookup_helper(struct sip_msg* _m, udomain_t* _d, str* _uri, int _mode)
 	sr_xavp_t *list=NULL;
 	str xname = {"ruid", 4};
 	sr_xval_t xval;
+	sip_uri_t path_uri;
+	str path_str;
 
 	ret = -1;
 
@@ -256,16 +254,47 @@ int lookup_helper(struct sip_msg* _m, udomain_t* _d, str* _uri, int _mode)
 				xavp_add_value(&reg_xavp_rcd, &xval, NULL);
 			}
 		}
+
 		/* If a Path is present, use first path-uri in favour of
 		 * received-uri because in that case the last hop towards the uac
 		 * has to handle NAT. - agranig */
 		if (ptr->path.s && ptr->path.len) {
-			if (get_path_dst_uri(&ptr->path, &path_dst) < 0) {
+			/* make a copy, so any change we need to make here does not mess up the structure in usrloc */
+			path_str = ptr->path;
+			if (get_path_dst_uri(&path_str, &path_dst) < 0) {
 				LM_ERR("failed to get dst_uri for Path\n");
 				ret = -3;
 				goto done;
 			}
-			if (set_path_vector(_m, &ptr->path) < 0) {
+			if (path_check_local > 0) {
+				if (parse_uri(path_dst.s, path_dst.len, &path_uri) < 0){
+					LM_ERR("failed to parse the Path URI\n");
+					ret = -3;
+					goto done;
+				}
+				if (check_self(&(path_uri.host), 0, 0)) {
+					/* first hop in path vector is local - check for additional hops and if present, point to next one */
+					if (path_str.len > (path_dst.len + 3)) {
+						path_str.s = path_str.s + path_dst.len + 3;
+						path_str.len = path_str.len - path_dst.len - 3;
+						if (get_path_dst_uri(&path_str, &path_dst) < 0) {
+							LM_ERR("failed to get second dst_uri for Path\n");
+							ret = -3;
+							goto done;
+						}
+					} else {
+						/* no more hops */
+						path_dst.s = NULL;
+						path_dst.len = 0;
+					}
+				}
+			}
+		} else {
+			path_dst.s = NULL;
+			path_dst.len = 0;
+		}
+		if (path_dst.s && path_dst.len) {
+			if (set_path_vector(_m, &path_str) < 0) {
 				LM_ERR("failed to set path vector\n");
 				ret = -3;
 				goto done;
@@ -316,7 +345,7 @@ int lookup_helper(struct sip_msg* _m, udomain_t* _d, str* _uri, int _mode)
 
 		if(ptr->xavp!=NULL) {
 			xavp = xavp_clone_level_nodata(ptr->xavp);
-			if(xavp_add(xavp, NULL)<0) {
+			if(xavp_insert(xavp, 0, NULL)<0) {
 				ret = -3;
 				goto done;
 			}
@@ -333,10 +362,36 @@ int lookup_helper(struct sip_msg* _m, udomain_t* _d, str* _uri, int _mode)
 	for( ; ptr ; ptr = ptr->next ) {
 		if (VALID_CONTACT(ptr, act_time) && allowed_method(_m, ptr)) {
 			path_dst.len = 0;
-			if(ptr->path.s && ptr->path.len 
-			&& get_path_dst_uri(&ptr->path, &path_dst) < 0) {
-				LM_ERR("failed to get dst_uri for Path\n");
-				continue;
+			if(ptr->path.s && ptr->path.len) {
+				path_str = ptr->path;
+				if (get_path_dst_uri(&path_str, &path_dst) < 0) {
+					LM_ERR("failed to get dst_uri for Path\n");
+					continue;
+				}
+				if (path_check_local > 0) {
+					if (parse_uri(path_dst.s, path_dst.len, &path_uri) < 0) {
+						LM_ERR("failed to parse the Path URI\n");
+						continue;
+					}
+					if (check_self(&(path_uri.host), 0, 0)) {
+						/* first hop in path vector is local - check for additional hops and if present, point to next one */
+						if (path_str.len > (path_dst.len + 3)) {
+							path_str.s = path_str.s + path_dst.len + 3;
+							path_str.len = path_str.len - path_dst.len - 3;
+							if (get_path_dst_uri(&path_str, &path_dst) < 0) {
+								LM_ERR("failed to get second dst_uri for Path\n");
+								continue;
+							}
+						} else {
+							/* no more hops */
+							path_dst.s = NULL;
+							path_dst.len = 0;
+						}
+					}
+				}
+			} else {
+				path_dst.s = NULL;
+				path_dst.len = 0;
 			}
 
 			/* The same as for the first contact applies for branches 
@@ -345,7 +400,7 @@ int lookup_helper(struct sip_msg* _m, udomain_t* _d, str* _uri, int _mode)
 			       ptr->instance.len, ptr->instance.s);
 			if (append_branch(_m, &ptr->c,
 					  path_dst.len?&path_dst:&ptr->received,
-					  &ptr->path, ptr->q, ptr->cflags,
+					  path_dst.len?&path_str:0, ptr->q, ptr->cflags,
 					  ptr->sock,
 					  ptr->instance.len?&(ptr->instance):0,
 				          ptr->instance.len?ptr->reg_id:0,
@@ -564,13 +619,24 @@ done:
  * it is similar to lookup but registered neither rewrites
  * the Request-URI nor appends branches
  */
-int registered(struct sip_msg* _m, udomain_t* _d, str* _uri)
+int registered(struct sip_msg* _m, udomain_t* _d, str* _uri) {
+	return registered4(_m, _d, _uri, 0, 0);
+}
+
+int registered3(struct sip_msg* _m, udomain_t* _d, str* _uri, int match_flag) {
+	return registered4(_m, _d, _uri, match_flag, 0);
+}
+
+int registered4(struct sip_msg* _m, udomain_t* _d, str* _uri, int match_flag, int match_action_flag)
 {
 	str uri, aor;
 	urecord_t* r;
 	ucontact_t* ptr;
 	int res;
-	int_str match_callid=(int_str)0;
+	str match_callid = {0,0};
+	str match_received = {0,0};
+	str match_contact = {0,0};
+	sr_xavp_t *vavp = NULL;
 
 	if(_uri!=NULL)
 	{
@@ -595,26 +661,61 @@ int registered(struct sip_msg* _m, udomain_t* _d, str* _uri)
 	}
 
 	if (res == 0) {
-		
-		if (reg_callid_avp_name.n) {
-			struct usr_avp *avp =
-				search_first_avp( reg_callid_avp_type, reg_callid_avp_name, &match_callid, 0);
-			if (!(avp && is_avp_str_val(avp)))
-				match_callid.n = 0;
-				match_callid.s.s = NULL;
-		} else {
-			match_callid.n = 0;
-			match_callid.s.s = NULL;
+		LM_DBG("searching with match flags (%d,%d)\n", match_flag, match_action_flag);
+		if(reg_xavp_cfg.s!=NULL) {
+
+			if((match_flag & 1)
+					&& (vavp = xavp_get_child_with_sval(&reg_xavp_cfg, &match_callid_name)) != NULL
+					&& vavp->val.v.s.len > 0) {
+				match_callid = vavp->val.v.s;
+				LM_DBG("matching with callid %.*s\n", match_callid.len, match_callid.s);
+			}
+
+			if((match_flag & 2)
+					&& (vavp = xavp_get_child_with_sval(&reg_xavp_cfg, &match_received_name)) != NULL
+					&& vavp->val.v.s.len > 0) {
+				match_received = vavp->val.v.s;
+				LM_DBG("matching with received %.*s\n", match_received.len, match_received.s);
+			}
+
+			if((match_flag & 4)
+					&& (vavp = xavp_get_child_with_sval(&reg_xavp_cfg, &match_contact_name)) != NULL
+					&& vavp->val.v.s.len > 0) {
+				match_contact = vavp->val.v.s;
+				LM_DBG("matching with contact %.*s\n", match_contact.len, match_contact.s);
+			}
 		}
 
 		for (ptr = r->contacts; ptr; ptr = ptr->next) {
 			if(!VALID_CONTACT(ptr, act_time)) continue;
-			if (match_callid.s.s && /* optionally enforce tighter matching w/ Call-ID */
-				memcmp(match_callid.s.s,ptr->callid.s,match_callid.s.len))
+			if (match_callid.s && /* optionally enforce tighter matching w/ Call-ID */
+				match_callid.len > 0 &&
+				(match_callid.len != ptr->callid.len || 
+				memcmp(match_callid.s, ptr->callid.s, match_callid.len)))
+				continue;
+			if (match_received.s && /* optionally enforce tighter matching w/ ip:port */
+				match_received.len > 0 &&
+				(match_received.len != ptr->received.len || 
+				memcmp(match_received.s, ptr->received.s, match_received.len)))
 				continue;
+			if (match_contact.s && /* optionally enforce tighter matching w/ Contact */
+				match_contact.len > 0 &&
+				(match_contact.len != ptr->c.len || 
+				memcmp(match_contact.s, ptr->c.s, match_contact.len)))
+				continue;
+
+			if(ptr->xavp!=NULL && match_action_flag == 1) {
+				sr_xavp_t *xavp = xavp_clone_level_nodata(ptr->xavp);
+				if(xavp_add(xavp, NULL)<0) {
+					LM_ERR("error adding xavp for %.*s after successful match\n", aor.len, ZSW(aor.s));
+					xavp_destroy_list(&xavp);
+				}
+			}
+
 			ul.release_urecord(r);
 			ul.unlock_udomain(_d, &aor);
 			LM_DBG("'%.*s' found in usrloc\n", aor.len, ZSW(aor.s));
+
 			return 1;
 		}
 	}
diff --git a/modules/registrar/lookup.h b/modules/registrar/lookup.h
index 1a88c94..035b818 100644
--- a/modules/registrar/lookup.h
+++ b/modules/registrar/lookup.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Lookup contacts in usrloc
  *
  * Copyright (C) 2001-2003 FhG Fokus
@@ -69,6 +67,7 @@ int lookup_branches(sip_msg_t *msg, udomain_t *d);
  * the Request-URI nor appends branches
  */
 int registered(struct sip_msg* _m, udomain_t* _d, str* _uri);
-
+int registered3(struct sip_msg* _m, udomain_t* _d, str* _uri, int match_flag);
+int registered4(struct sip_msg* _m, udomain_t* _d, str* _uri, int match_flag, int match_action_flag);
 
 #endif /* LOOKUP_H */
diff --git a/modules/registrar/path.c b/modules/registrar/path.c
index 0e242e3..8571eea 100644
--- a/modules/registrar/path.c
+++ b/modules/registrar/path.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Helper functions for Path support.
  *
  * Copyright (C) 2006 Andreas Granig <agranig at linguin.org>
diff --git a/modules/registrar/path.h b/modules/registrar/path.h
index 12c94d9..1914bf4 100644
--- a/modules/registrar/path.h
+++ b/modules/registrar/path.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Helper functions for Path support.
  *
  * Copyright (C) 2006 Andreas Granig <agranig at linguin.org>
diff --git a/modules/registrar/reg_mod.c b/modules/registrar/reg_mod.c
index f187fb3..d767834 100644
--- a/modules/registrar/reg_mod.c
+++ b/modules/registrar/reg_mod.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Registrar module interface
  *
  * Copyright (C) 2001-2003 FhG Fokus
@@ -21,29 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2003-03-11  updated to the new module exports interface (andrei)
- *  2003-03-16  flags export parameter added (janakj)
- *  2003-03-21  save_noreply added, provided by Maxim Sobolev
- *              <sobomax at portaone.com> (janakj)
- *  2005-07-11  added sip_natping_flag for nat pinging with SIP method
- *              instead of UDP package (bogdan)
- *  2006-09-19  AOR may be provided via an AVP instead of being fetched
- *              from URI (bogdan)
- *  2006-10-04  removed the "desc_time_order" parameter, as its functionality
- *              was moved to usrloc (Carsten Bock, BASIS AudioNet GmbH)
- *  2006-11-22  save_noreply and save_memory merged into save();
- *              removed the module parameter "use_domain" - now it is
- *              imported from usrloc module (bogdan)
- *  2006-11-28  Added statistics tracking for the number of accepted/rejected
- *              registrations, as well as for the max expiry time, max 
- *              contacts and default expiry time(Jeffrey Magder-SOMA Networks)
- *  2007-02-24  sip_natping_flag moved into branch flags, so migrated to 
- *              nathelper module (bogdan)
- *  2009-12-09  Commented out tcp_persistent_flag param, because sr_3.0 tm
- *              does not support it (Juha)
- *
  */
 
 /*!
@@ -96,6 +71,8 @@ static int w_lookup_branches(struct sip_msg* _m, char* _d, char* _p2);
 static int w_registered(struct sip_msg* _m, char* _d, char* _uri);
 static int w_unregister(struct sip_msg* _m, char* _d, char* _uri);
 static int w_unregister2(struct sip_msg* _m, char* _d, char* _uri, char *_ruid);
+static int w_registered3(struct sip_msg* _m, char* _d, char* _uri, char* _flags);
+static int w_registered4(struct sip_msg* _m, char* _d, char* _uri, char* _flags, char* _actionflags);
 
 /*! \brief Fixup functions */
 static int domain_fixup(void** param, int param_no);
@@ -103,6 +80,7 @@ static int domain_uri_fixup(void** param, int param_no);
 static int save_fixup(void** param, int param_no);
 static int unreg_fixup(void** param, int param_no);
 static int fetchc_fixup(void** param, int param_no);
+static int registered_fixup(void** param, int param_no);
 /*! \brief Functions */
 static int add_sock_hdr(struct sip_msg* msg, char *str, char *foo);
 
@@ -116,6 +94,7 @@ int path_mode = PATH_MODE_STRICT;		/*!< if the Path HF should be inserted in the
 
 int path_use_params = 0;			/*!< if the received- and nat-parameters of last Path uri should be used
  						 * to determine if UAC is nat'ed */
+int path_check_local = 0;
 
 /* sruid to get internal uid */
 sruid_t _reg_sruid;
@@ -125,10 +104,9 @@ int reg_outbound_mode = 0;
 int reg_regid_mode = 0;
 int reg_flow_timer = 0;
 
-/* Populate this AVP if testing for specific registration instance. */
-char *reg_callid_avp_param = 0;
-unsigned short reg_callid_avp_type = 0;
-int_str reg_callid_avp_name;
+str match_callid_name = str_init("match_callid");
+str match_received_name = str_init("match_received");
+str match_contact_name = str_init("match_contact");
 
 char* rcv_avp_param = 0;
 unsigned short rcv_avp_type = 0;
@@ -188,6 +166,10 @@ static cmd_export_t cmds[] = {
 			REQUEST_ROUTE | FAILURE_ROUTE },
 	{"registered",   (cmd_function)w_registered,  2,  domain_uri_fixup, 0,
 			REQUEST_ROUTE | FAILURE_ROUTE },
+	{"registered",   (cmd_function)w_registered3, 3,  registered_fixup, 0,
+			REQUEST_ROUTE | FAILURE_ROUTE },
+	{"registered",   (cmd_function)w_registered4, 4,  registered_fixup, 0,
+			REQUEST_ROUTE | FAILURE_ROUTE },
 	{"add_sock_hdr", (cmd_function)add_sock_hdr,  1,  fixup_str_null, 0,
 			REQUEST_ROUTE },
 	{"unregister",   (cmd_function)w_unregister,  2,  unreg_fixup, 0,
@@ -224,7 +206,6 @@ static param_export_t params[] = {
 	{"max_expires",        INT_PARAM, &default_registrar_cfg.max_expires			},
 	{"received_param",     PARAM_STR, &rcv_param           					},
 	{"received_avp",       PARAM_STRING, &rcv_avp_param       					},
-	{"reg_callid_avp",     PARAM_STRING, &reg_callid_avp_param					},
 	{"max_contacts",       INT_PARAM, &default_registrar_cfg.max_contacts			},
 	{"retry_after",        INT_PARAM, &default_registrar_cfg.retry_after			},
 	{"sock_flag",          INT_PARAM, &sock_flag           					},
@@ -233,6 +214,7 @@ static param_export_t params[] = {
 	{"use_path",           INT_PARAM, &path_enabled        					},
 	{"path_mode",          INT_PARAM, &path_mode           					},
 	{"path_use_received",  INT_PARAM, &path_use_params     					},
+	{"path_check_local",   INT_PARAM, &path_check_local                                     },
 	{"xavp_cfg",           PARAM_STR, &reg_xavp_cfg     					},
 	{"xavp_rcd",           PARAM_STR, &reg_xavp_rcd     					},
 	{"gruu_enabled",       INT_PARAM, &reg_gruu_enabled    					},
@@ -329,24 +311,6 @@ static int mod_init(void)
 		rcv_avp_type = 0;
 	}
 
-	if (reg_callid_avp_param && *reg_callid_avp_param) {
-		s.s = reg_callid_avp_param; s.len = strlen(s.s);
-		if (pv_parse_spec(&s, &avp_spec)==0
-			|| avp_spec.type!=PVT_AVP) {
-			LM_ERR("malformed or non AVP %s AVP definition\n", reg_callid_avp_param);
-			return -1;
-		}
-
-		if(pv_get_avp_name(0, &avp_spec.pvp, &reg_callid_avp_name, &reg_callid_avp_type)!=0)
-		{
-			LM_ERR("[%s]- invalid AVP definition\n", reg_callid_avp_param);
-			return -1;
-		}
-	} else {
-		reg_callid_avp_name.n = 0;
-		reg_callid_avp_type = 0;
-	}
-
 	bind_usrloc = (bind_usrloc_t)find_export("ul_bind_usrloc", 1, 0);
 	if (!bind_usrloc) {
 		LM_ERR("can't bind usrloc\n");
@@ -511,6 +475,46 @@ static int w_registered(struct sip_msg* _m, char* _d, char* _uri)
 	return registered(_m, (udomain_t*)_d, (uri.len>0)?&uri:NULL);
 }
 
+static int w_registered3(struct sip_msg* _m, char* _d, char* _uri, char* _flags)
+{
+	str uri = {0};
+	int flags = 0;
+	if(_uri!=NULL && (fixup_get_svalue(_m, (gparam_p)_uri, &uri)!=0 || uri.len<=0))
+	{
+		LM_ERR("invalid uri parameter\n");
+		return -1;
+	}
+	if(_flags!=NULL && (fixup_get_ivalue(_m, (fparam_t*)_flags, &flags)) < 0)
+	{
+		LM_ERR("invalid flags parameter\n");
+		return -1;
+	}
+	return registered3(_m, (udomain_t*)_d, (uri.len>0)?&uri:NULL, flags);
+}
+
+static int w_registered4(struct sip_msg* _m, char* _d, char* _uri, char* _flags, char* _actionflags)
+{
+	str uri = {0};
+	int flags = 0;
+	int actionflags = 0;
+	if(_uri!=NULL && (fixup_get_svalue(_m, (gparam_p)_uri, &uri)!=0 || uri.len<=0))
+	{
+		LM_ERR("invalid uri parameter\n");
+		return -1;
+	}
+	if(_flags!=NULL && (fixup_get_ivalue(_m, (fparam_t*)_flags, &flags)) < 0)
+	{
+		LM_ERR("invalid flags parameter\n");
+		return -1;
+	}
+	if(_actionflags!=NULL && (fixup_get_ivalue(_m, (fparam_t*)_actionflags, &actionflags)) < 0)
+	{
+		LM_ERR("invalid action flag parameter\n");
+		return -1;
+	}
+	return registered4(_m, (udomain_t*)_d, (uri.len>0)?&uri:NULL, flags, actionflags);
+}
+
 static int w_unregister(struct sip_msg* _m, char* _d, char* _uri)
 {
 	str uri = {0};
@@ -573,6 +577,19 @@ static int domain_uri_fixup(void** param, int param_no)
 	return 0;
 }
 
+static int registered_fixup(void** param, int param_no)
+{
+	if (param_no == 1) {
+		return domain_fixup(param, 1);
+	} else if (param_no == 2) {
+		return fixup_spve_null(param, 1);
+	} else if (param_no == 3) {
+		return fixup_igp_null(param, 1);
+	} else if (param_no == 4) {
+		return fixup_igp_null(param, 1);
+	}
+	return 0;
+}
 
 /*! \brief
  * Convert char* parameter to udomain_t* pointer
diff --git a/modules/registrar/reg_mod.h b/modules/registrar/reg_mod.h
index 96def72..8fd0ccb 100644
--- a/modules/registrar/reg_mod.h
+++ b/modules/registrar/reg_mod.h
@@ -1,6 +1,4 @@
 /* 
- * $Id$ 
- *
  * registrar module interface
  *
  * Copyright (C) 2001-2003 FhG Fokus
@@ -21,16 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *
- * 2005-07-11  added sip_natping_flag for nat pinging with SIP method
- *             instead of UDP package (bogdan)
- * 2006-11-28  Added statistics tracking for the number of accepted/rejected
- *             registrations, as well as for the max expiry time, max contacts,
- *             and default expiry time. (Jeffrey Magder - SOMA Networks)
- * 2007-02-24  sip_natping_flag moved into branch flags, so migrated to 
- *             nathelper module (bogdan)
  */
 
 /*!
@@ -86,14 +74,17 @@ extern float def_q;
 
 extern unsigned short rcv_avp_type;
 extern int_str rcv_avp_name;
-extern unsigned short reg_callid_avp_type;
-extern int_str reg_callid_avp_name;
+
+extern str match_callid_name;
+extern str match_received_name;
+extern str match_contact_name;
 
 extern str rcv_param;
 extern int method_filtering;
 extern int path_enabled;
 extern int path_mode;
 extern int path_use_params;
+extern int path_check_local;
 extern int reg_gruu_enabled;
 extern int reg_outbound_mode;
 extern int reg_regid_mode;
diff --git a/modules/registrar/regpv.c b/modules/registrar/regpv.c
index 227562a..8574e92 100644
--- a/modules/registrar/regpv.c
+++ b/modules/registrar/regpv.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Export vontact attrs as PV
  *
  * Copyright (C) 2008 Daniel-Constantin Mierla (asipto.com)
@@ -271,6 +269,10 @@ int pv_get_ulc(struct sip_msg *msg,  pv_param_t *param,
 			if(c->instance.len>0)
 				return  pv_get_strval(msg, param, res, &c->instance);
 		break;
+		case 21: /* conid */
+			if (c->sock && (c->sock->proto == PROTO_TCP || c->sock->proto == PROTO_TLS || c->sock->proto == PROTO_WS || c->sock->proto == PROTO_WSS))
+				return pv_get_sintval(msg, param, res, c->tcpconn_id);
+		break;
 	}
 
 	return pv_get_null(msg, param, res);
@@ -365,6 +367,8 @@ int pv_parse_ulc_name(pv_spec_p sp, str *in)
 				rp->attr = 17;
 			else if(strncmp(pa.s, "regid", 5)==0)
 				rp->attr = 19;
+			else if(strncmp(pa.s, "conid", 5)==0)
+				rp->attr = 21;
 			else goto error;
 		break;
 		case 6: 
@@ -540,6 +544,10 @@ int pv_fetch_contacts(struct sip_msg* msg, char* table, char* uri,
 			c0->instance.len = ptr->instance.len;
 			p += c0->instance.len;
 		}
+		if (ptr->sock->proto == PROTO_TCP || ptr->sock->proto == PROTO_TLS || ptr->sock->proto == PROTO_WS || ptr->sock->proto == PROTO_WSS)
+		{
+			c0->tcpconn_id = ptr->tcpconn_id;
+		}
 
 		if(ptr0==NULL)
 		{
diff --git a/modules/registrar/regpv.h b/modules/registrar/regpv.h
index de986ae..1926d64 100644
--- a/modules/registrar/regpv.h
+++ b/modules/registrar/regpv.h
@@ -1,7 +1,5 @@
 /*
- * $Id$
- *
- * Export vontact attrs as PV
+ * Export contact attrs as PV
  *
  * Copyright (C) 2008 Daniel-Constantin Mierla (asipto.com)
  *
diff --git a/modules/registrar/regtime.c b/modules/registrar/regtime.c
index cc38366..2e9ed87 100644
--- a/modules/registrar/regtime.c
+++ b/modules/registrar/regtime.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Registrar time related functions
  *
  * Copyright (C) 2001-2003 FhG Fokus
diff --git a/modules/registrar/regtime.h b/modules/registrar/regtime.h
index cf2d6e0..0815da5 100644
--- a/modules/registrar/regtime.h
+++ b/modules/registrar/regtime.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Registrar time related functions
  *
  * Copyright (C) 2001-2003 FhG Fokus
diff --git a/modules/registrar/reply.c b/modules/registrar/reply.c
index b5a67c0..ef5b601 100644
--- a/modules/registrar/reply.c
+++ b/modules/registrar/reply.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Send a reply
  *
  * Copyright (C) 2001-2003 FhG Fokus
@@ -21,12 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2003-01-18: buffer overflow patch committed (Jan on behalf of Maxim)
- * 2003-01-21: Errors reported via Error-Info header field - janakj
- * 2003-09-11: updated to new build_lump_rpl() interface (bogdan)
- * 2003-11-11: build_lump_rpl() removed, add_lump_rpl() has flags (bogdan)
  */
 
 /*!
diff --git a/modules/registrar/reply.h b/modules/registrar/reply.h
index 1fda991..f10840e 100644
--- a/modules/registrar/reply.h
+++ b/modules/registrar/reply.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Send a reply
  *
  * Copyright (C) 2001-2003 FhG Fokus
diff --git a/modules/registrar/rerrno.c b/modules/registrar/rerrno.c
index 227aaf0..8650fce 100644
--- a/modules/registrar/rerrno.c
+++ b/modules/registrar/rerrno.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Registrar errno
  *
  * Copyright (C) 2001-2003 FhG Fokus
diff --git a/modules/registrar/rerrno.h b/modules/registrar/rerrno.h
index c7624b0..694f682 100644
--- a/modules/registrar/rerrno.h
+++ b/modules/registrar/rerrno.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Registrar errno
  *
  * Copyright (C) 2001-2003 FhG Fokus
diff --git a/modules/registrar/save.c b/modules/registrar/save.c
index a3a5b29..ae311e8 100644
--- a/modules/registrar/save.c
+++ b/modules/registrar/save.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Process REGISTER request and send reply
  *
  * Copyright (C) 2001-2003 FhG Fokus
@@ -22,21 +20,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * ----------
- * 2003-01-27 next baby-step to removing ZT - PRESERVE_ZT (jiri)
- * 2003-02-28 scrathcpad compatibility abandoned (jiri)
- * 2003-03-21 save_noreply added, patch provided by Maxim Sobolev 
- *            <sobomax at portaone.com> (janakj)
- * 2005-07-11 added sip_natping_flag for nat pinging with SIP method
- *            instead of UDP package (bogdan)
- * 2006-04-13 added tcp_persistent_flag for keeping the TCP connection as long
- *            as a TCP contact is registered (bogdan)
- * 2006-11-22 save_noreply and save_memory merged into save() (bogdan)
- * 2006-11-28 Added statistic support for the number of accepted/rejected 
- *            registrations. (Jeffrey Magder - SOMA Networks) 
- * 2007-02-24  sip_natping_flag moved into branch flags, so migrated to 
- *             nathelper module (bogdan)
  */
 /*!
  * \file
@@ -234,7 +217,8 @@ static inline int no_contacts(sip_msg_t *_m, udomain_t* _d, str* _a, str* _h)
 /*! \brief
  * Fills the common part (for all contacts) of the info structure
  */
-static inline ucontact_info_t* pack_ci( struct sip_msg* _m, contact_t* _c, unsigned int _e, unsigned int _f, int _use_regid)
+static inline ucontact_info_t* pack_ci( struct sip_msg* _m, contact_t* _c,
+		unsigned int _e, unsigned int _f, int _use_regid)
 {
 	static ucontact_info_t ci;
 	static str no_ua = str_init("n/a");
@@ -322,6 +306,8 @@ static inline ucontact_info_t* pack_ci( struct sip_msg* _m, contact_t* _c, unsig
 			ci.received = path_received;
 		}
 
+		ci.server_id = server_id;
+
 		allow_parsed = 0; /* not parsed yet */
 		received_found = 0; /* not found yet */
 		m = _m; /* remember the message */
diff --git a/modules/registrar/save.h b/modules/registrar/save.h
index 6240c4d..f8fc094 100644
--- a/modules/registrar/save.h
+++ b/modules/registrar/save.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Functions that process REGISTER message 
  * and store data in usrloc
  *
@@ -22,11 +20,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * -------
- * 2003-03-21  save_noreply added, provided by Maxim Sobolev 
- *             <sobomax at portaone.com> (janakj)
- * 2006-11-22  save_noreply and save_memory merged into save() (bogdan)
  */
 /*!
  * \file
diff --git a/modules/registrar/sip_msg.c b/modules/registrar/sip_msg.c
index 6ccfd5b..5ca83eb 100644
--- a/modules/registrar/sip_msg.c
+++ b/modules/registrar/sip_msg.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * SIP message related functions
  *
  * Copyright (C) 2001-2003 FhG Fokus
@@ -283,11 +281,29 @@ void calc_contact_expires(struct sip_msg* _m, param_t* _ep, int* _e)
 
 /*! \brief
  * Calculate contact q value as follows:
- * 1) If q parameter exists, use it
- * 2) If the parameter doesn't exist, use the default value
+ * 1) If xavp_cfg q has been defined, use it
+ * 2) If q parameter exists in contact, use it
+ * 3) If the parameter doesn't exist in contact, use the default value
  */
 int calc_contact_q(param_t* _q, qvalue_t* _r)
 {
+	sr_xavp_t *vavp = NULL;
+	str xqname = str_init("q");
+
+	if (reg_xavp_cfg.s != NULL)
+		vavp = xavp_get_child_with_ival(&reg_xavp_cfg, &xqname);
+
+	if (vavp != NULL) {
+		if ((vavp->val.v.i >= 0) && (vavp->val.v.i <= 1000)) {
+			*_r = vavp->val.v.i;
+			return 0;
+		} else {
+			rerrno = R_INV_Q; /* Invalid q parameter */
+			LM_ERR("invalid q parameter\n");
+			return -1;
+		}
+	}
+
 	if (!_q || (_q->body.len == 0)) {
 		*_r = cfg_get(registrar, registrar_cfg, default_q);
 	} else {
@@ -297,5 +313,6 @@ int calc_contact_q(param_t* _q, qvalue_t* _r)
 			return -1;
 		}
 	}
+
 	return 0;
 }
diff --git a/modules/registrar/sip_msg.h b/modules/registrar/sip_msg.h
index ef247bf..c405b9f 100644
--- a/modules/registrar/sip_msg.h
+++ b/modules/registrar/sip_msg.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * SIP message related functions
  *
  * Copyright (C) 2001-2003 FhG Fokus
diff --git a/modules/rls/Makefile b/modules/rls/Makefile
index 726c9c5..927c0cb 100644
--- a/modules/rls/Makefile
+++ b/modules/rls/Makefile
@@ -1,6 +1,5 @@
-# $Id: Makefile 1856 2007-03-15 21:06:00Z  $
 #
-# Resource List Server
+# rls: Resource List Server
 #
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
diff --git a/modules/rls/notify.c b/modules/rls/notify.c
index fb9d7f3..cda3da1 100644
--- a/modules/rls/notify.c
+++ b/modules/rls/notify.c
@@ -1,6 +1,4 @@
 /*
- * $Id: notify.c 2230 2007-06-06 07:13:20Z anca_vamanu $
- *
  * rls module - resource list server
  *
  * Copyright (C) 2007 Voice Sistem S.R.L.
@@ -21,9 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2007-09-11  initial version (anca)
  */
 
 #include <stdlib.h>
diff --git a/modules/rls/notify.h b/modules/rls/notify.h
index 5223887..bb18e10 100644
--- a/modules/rls/notify.h
+++ b/modules/rls/notify.h
@@ -1,6 +1,4 @@
 /*
- * $Id: notify.c 2230 2007-06-06 07:13:20Z anca_vamanu $
- *
  * rls module - resource list server
  *
  * Copyright (C) 2007 Voice Sistem S.R.L.
@@ -21,10 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2007-09-11  initial version (anca)
- *
  */
 
 #ifndef _RLS_NOTIFY_H
diff --git a/modules/rls/resource_notify.c b/modules/rls/resource_notify.c
index 01c8dd8..d17445c 100644
--- a/modules/rls/resource_notify.c
+++ b/modules/rls/resource_notify.c
@@ -1,6 +1,4 @@
 /*
- * $Id: resource_notify.c 2230 2007-06-06 07:13:20Z anca_vamanu $
- *
  * rls module - resource list server
  *
  * Copyright (C) 2007 Voice Sistem S.R.L.
@@ -21,9 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2007-09-11  initial version (anca)
  */
 
 #include <stdio.h>
diff --git a/modules/rls/resource_notify.h b/modules/rls/resource_notify.h
index 86f65f6..72fa7f4 100644
--- a/modules/rls/resource_notify.h
+++ b/modules/rls/resource_notify.h
@@ -1,6 +1,4 @@
 /*
- * $Id: resource_notify.h 2230 2007-06-06 07:13:20Z anca_vamanu $
- *
  * rls module - resource list server
  *
  * Copyright (C) 2007 Voice Sistem S.R.L.
@@ -21,9 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2007-09-11  initial version (anca)
  */
 
 #ifndef RLS_RES_NOT_H
diff --git a/modules/rls/rls.c b/modules/rls/rls.c
index c87e91e..23c6a7c 100644
--- a/modules/rls/rls.c
+++ b/modules/rls/rls.c
@@ -1,6 +1,4 @@
 /*
- * $Id: rls.c 2230 2007-06-06 07:13:20Z anca_vamanu $
- *
  * rls module - resource list server
  *
  * Copyright (C) 2007 Voice Sistem S.R.L.
@@ -21,9 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2007-09-11  initial version (anca)
  */
 
 #include <stdio.h>
diff --git a/modules/rls/rls.h b/modules/rls/rls.h
index 8b55cf9..ac11efa 100644
--- a/modules/rls/rls.h
+++ b/modules/rls/rls.h
@@ -1,6 +1,4 @@
 /*
- * $Id: rls.h 2230 2007-06-06 07:13:20Z anca_vamanu $
- *
  * rls module - resource list server
  *
  * Copyright (C) 2007 Voice Sistem S.R.L.
@@ -21,9 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2007-09-11  initial version (anca)
  */
 
 #ifndef _RLS_H_
diff --git a/modules/rls/rls_db.c b/modules/rls/rls_db.c
index 463b5bc..5dbbca9 100644
--- a/modules/rls/rls_db.c
+++ b/modules/rls/rls_db.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * rls db - RLS database support 
  *
  * Copyright (C) 2011 Crocodile RCS Ltd
diff --git a/modules/rls/subscribe.c b/modules/rls/subscribe.c
index 801d5e4..09d988b 100644
--- a/modules/rls/subscribe.c
+++ b/modules/rls/subscribe.c
@@ -1,6 +1,4 @@
 /*
- * $Id: subscribe.c 2230 2007-06-06 07:13:20Z anca_vamanu $
- *
  * rls module - resource list server
  *
  * Copyright (C) 2007 Voice Sistem S.R.L.
@@ -21,9 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2007-09-11  initial version (anca)
  */
 #include <stdlib.h>
 #include <stdio.h>
diff --git a/modules/rls/subscribe.h b/modules/rls/subscribe.h
index c82df74..04fc117 100644
--- a/modules/rls/subscribe.h
+++ b/modules/rls/subscribe.h
@@ -1,6 +1,4 @@
 /*
- * $Id: subscribe.c 2230 2007-06-06 07:13:20Z anca_vamanu $
- *
  * rls module - resource list server
  *
  * Copyright (C) 2007 Voice Sistem S.R.L.
@@ -21,9 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2007-09-11  initial version (anca)
  */
 
 #ifndef RLS_SUBSCRIBE_H
diff --git a/modules/rr/Makefile b/modules/rr/Makefile
index 0360020..4dccf3a 100644
--- a/modules/rr/Makefile
+++ b/modules/rr/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # rr module makefile
 #
diff --git a/modules/rr/api.c b/modules/rr/api.c
index a4bd949..1b7c420 100644
--- a/modules/rr/api.c
+++ b/modules/rr/api.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2005 Voice Sistem SRL
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/rr/api.h b/modules/rr/api.h
index abe50de..e2b7340 100644
--- a/modules/rr/api.h
+++ b/modules/rr/api.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2005 Voice Sistem SRL
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/rr/loose.c b/modules/rr/loose.c
index f537a8d..de06bb3 100644
--- a/modules/rr/loose.c
+++ b/modules/rr/loose.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2004 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/rr/loose.h b/modules/rr/loose.h
index a4f4252..9064a6f 100644
--- a/modules/rr/loose.h
+++ b/modules/rr/loose.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/rr/record.c b/modules/rr/record.c
index a521092..d335748 100644
--- a/modules/rr/record.c
+++ b/modules/rr/record.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/rr/record.h b/modules/rr/record.h
index 5cf0272..8e30fb1 100644
--- a/modules/rr/record.h
+++ b/modules/rr/record.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/rr/rr_cb.c b/modules/rr/rr_cb.c
index cebb0a4..d9c3149 100644
--- a/modules/rr/rr_cb.c
+++ b/modules/rr/rr_cb.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2005 Voice Sistem SRL
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/rr/rr_cb.h b/modules/rr/rr_cb.h
index 63acc1d..6224f88 100644
--- a/modules/rr/rr_cb.h
+++ b/modules/rr/rr_cb.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2005 Voice Sistem SRL
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/rr/rr_mod.c b/modules/rr/rr_mod.c
index c01de65..9eb29d6 100644
--- a/modules/rr/rr_mod.c
+++ b/modules/rr/rr_mod.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  * Copyright (C) 2011 Carsten Bock, carsten at ng-voice.com
  *
@@ -40,6 +38,8 @@
 #include "../../mem/mem.h"
 #include "../../mod_fix.h"
 #include "../../parser/parse_rr.h"
+#include "../../parser/parse_from.h"
+#include "../../parser/parse_to.h"
 #include "../outbound/api.h"
 #include "loose.h"
 #include "record.h"
@@ -79,6 +79,13 @@ static int w_is_direction(struct sip_msg *,char *, char *);
 static int remove_record_route(sip_msg_t*, char*, char*);
 /* PV functions */
 static int pv_get_route_uri_f(struct sip_msg *, pv_param_t *, pv_value_t *);
+static int pv_get_from_tag_initial(sip_msg_t *msg, pv_param_t *param,
+		pv_value_t *res);
+static int pv_get_to_tag_initial(sip_msg_t *msg, pv_param_t *param,
+		pv_value_t *res);
+static int pv_get_rdir(sip_msg_t *msg, pv_param_t *param, pv_value_t *res);
+static int pv_parse_rdir_name(pv_spec_p sp, str *in);
+
 /*!
  * \brief Exported functions
  */
@@ -129,7 +136,14 @@ static param_export_t params[] ={
  */
 static pv_export_t mod_pvs[] = {
     {{"route_uri", (sizeof("route_uri")-1)}, /* URI of the first Route-Header */
-     PVT_OTHER, pv_get_route_uri_f, 0, 0, 0, 0, 0},
+		PVT_OTHER, pv_get_route_uri_f, 0, 0, 0, 0, 0},
+    {{"fti", (sizeof("fti")-1)}, /* From-Tag as for initial request */
+		PVT_OTHER, pv_get_from_tag_initial, 0, 0, 0, 0, 0},
+    {{"tti", (sizeof("tti")-1)}, /* To-Tag as for response to initial request */
+		PVT_OTHER, pv_get_to_tag_initial, 0, 0, 0, 0, 0},
+	{ {"rdir", (sizeof("rdir")-1)}, PVT_OTHER, pv_get_rdir, 0,
+		pv_parse_rdir_name, 0, 0, 0 },
+
     {{0, 0}, 0, 0, 0, 0, 0, 0, 0}
 };
 
@@ -480,3 +494,141 @@ static int remove_record_route(sip_msg_t* _m, char* _s1, char* _s2)
 	free_rr_lump(&(_m->add_rm));
 	return 1;
 }
+
+/**
+ *
+ */
+static int pv_get_to_tag_initial(sip_msg_t *msg, pv_param_t *param,
+		pv_value_t *res)
+{
+	struct to_body *xto;
+	if(msg==NULL)
+		return -1;
+
+	if(msg->to==NULL && parse_headers(msg, HDR_TO_F, 0)==-1) {
+		LM_ERR("cannot parse To header\n");
+		return pv_get_null(msg, param, res);
+	}
+	if(msg->to==NULL || get_to(msg)==NULL) {
+		LM_DBG("no To header\n");
+		return pv_get_null(msg, param, res);
+	}
+	xto = get_to(msg);
+
+	if(is_direction(msg, RR_FLOW_UPSTREAM)==0) {
+		if(parse_from_header(msg)<0) {
+			LM_ERR("cannot parse From header\n");
+			return pv_get_null(msg, param, res);
+		}
+		if(msg->from==NULL || get_from(msg)==NULL) {
+			LM_DBG("no From header\n");
+			return pv_get_null(msg, param, res);
+		}
+		xto = get_from(msg);
+	}
+
+	if (xto->tag_value.s==NULL || xto->tag_value.len<=0) {
+		LM_DBG("no Tag parameter\n");
+		return pv_get_null(msg, param, res);
+	}
+	return pv_get_strval(msg, param, res, &xto->tag_value);
+}
+
+/**
+ *
+ */
+static int pv_get_from_tag_initial(sip_msg_t *msg, pv_param_t *param,
+		pv_value_t *res)
+{
+	struct to_body *xto;
+	if(msg==NULL)
+		return -1;
+
+	if(parse_from_header(msg)<0) {
+		LM_ERR("cannot parse From header\n");
+		return pv_get_null(msg, param, res);
+	}
+	if(msg->from==NULL || get_from(msg)==NULL) {
+		LM_DBG("no From header\n");
+		return pv_get_null(msg, param, res);
+	}
+	xto = get_from(msg);
+
+	if(is_direction(msg, RR_FLOW_UPSTREAM)==0) {
+		if(msg->to==NULL && parse_headers(msg, HDR_TO_F, 0)==-1) {
+			LM_ERR("cannot parse To header\n");
+			return pv_get_null(msg, param, res);
+		}
+		if(msg->to==NULL || get_to(msg)==NULL) {
+			LM_DBG("no To header\n");
+			return pv_get_null(msg, param, res);
+		}
+		xto = get_to(msg);
+	}
+
+	if (xto->tag_value.s==NULL || xto->tag_value.len<=0) {
+		LM_DBG("no Tag parameter\n");
+		return pv_get_null(msg, param, res);
+	}
+	return pv_get_strval(msg, param, res, &xto->tag_value);
+}
+
+/**
+ *
+ */
+static int pv_parse_rdir_name(pv_spec_p sp, str *in)
+{
+	if(sp==NULL || in==NULL || in->len<=0)
+		return -1;
+
+	switch(in->len)
+	{
+		case 2:
+			if(strncmp(in->s, "id", 2)==0)
+				sp->pvp.pvn.u.isname.name.n = 0;
+			else goto error;
+		break;
+		case 4:
+			if(strncmp(in->s, "name", 4)==0)
+				sp->pvp.pvn.u.isname.name.n = 1;
+			else goto error;
+		break;
+		default:
+			goto error;
+	}
+	sp->pvp.pvn.type = PV_NAME_INTSTR;
+	sp->pvp.pvn.u.isname.type = 0;
+
+	return 0;
+
+error:
+	LM_ERR("unknown PV af key: %.*s\n", in->len, in->s);
+	return -1;
+}
+
+static str pv_rr_flow_list[] = {
+		{ "downstream",  10 },
+		{ "upstream",    8  },
+		{ 0, 0 }
+	};
+
+/**
+ *
+ */
+static int pv_get_rdir(sip_msg_t *msg, pv_param_t *param, pv_value_t *res)
+{
+	if(msg==NULL || param==NULL)
+		return -1;
+
+	switch(param->pvn.u.isname.name.n)
+	{
+		case 1:
+			if(is_direction(msg, RR_FLOW_UPSTREAM)==0)
+				return pv_get_strval(msg, param, res, &pv_rr_flow_list[1]);
+			return pv_get_strval(msg, param, res, &pv_rr_flow_list[0]);
+		default:
+			if(is_direction(msg, RR_FLOW_UPSTREAM)==0)
+				return pv_get_uintval(msg, param, res, RR_FLOW_UPSTREAM);
+			return pv_get_uintval(msg, param, res, RR_FLOW_DOWNSTREAM);
+	}
+}
diff --git a/modules/rr/rr_mod.h b/modules/rr/rr_mod.h
index 2b55003..566f280 100644
--- a/modules/rr/rr_mod.h
+++ b/modules/rr/rr_mod.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/rtimer/Makefile b/modules/rtimer/Makefile
index 8912e21..a5b22b1 100644
--- a/modules/rtimer/Makefile
+++ b/modules/rtimer/Makefile
@@ -1,6 +1,5 @@
-# $Id: Makefile 2 2005-06-13 16:47:24Z bogdan_iancu $
 #
-# example module makefile
+# rtimer module makefile
 #
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
diff --git a/modules/rtjson/Makefile b/modules/rtjson/Makefile
new file mode 100644
index 0000000..a87979d
--- /dev/null
+++ b/modules/rtjson/Makefile
@@ -0,0 +1,15 @@
+# 
+# 
+# WARNING: do not run this directly, it should be run by the master Makefile
+
+include ../../Makefile.defs
+auto_gen=
+NAME=rtjson.so
+DEFS +=
+LIBS +=
+
+DEFS+=-DKAMAILIO_MOD_INTERFACE
+SERLIBPATH=../../lib
+SER_LIBS+=$(SERLIBPATH)/srutils/srutils
+
+include ../../Makefile.modules
diff --git a/modules/rtjson/README b/modules/rtjson/README
new file mode 100644
index 0000000..b1cc61d
--- /dev/null
+++ b/modules/rtjson/README
@@ -0,0 +1,235 @@
+RTJSON Module
+
+Daniel-Constantin Mierla
+
+   <miconda at gmail.com>
+
+Edited by
+
+Daniel-Constantin Mierla
+
+   <miconda at gmail.com>
+
+   Copyright � 2015 asipto.com
+     __________________________________________________________________
+
+   Table of Contents
+
+   1. Admin Guide
+
+        1. Overview
+        2. Dependencies
+
+              2.1. Kamailio Modules
+              2.2. External Libraries or Applications
+
+        3. Parameters
+
+              3.1. xavp_cfg (str)
+
+        4. Functions
+
+              4.1. rtjson_init_routes(rtdoc)
+              4.2. rtjson_push_routes()
+              4.3. rtjson_next_route()
+              4.4. rtjson_update_branch()
+
+        5. JSON Routing Structure
+
+   List of Examples
+
+   1.1. Set xavp_cfg parameter
+   1.2. rtjson_init_routes usage
+   1.3. rtjson_push_routes usage
+   1.4. rtjson_next_route usage
+   1.5. rtjson_update_branch usage
+   1.6. JSON Routing Structure
+
+Chapter 1. Admin Guide
+
+   Table of Contents
+
+   1. Overview
+   2. Dependencies
+
+        2.1. Kamailio Modules
+        2.2. External Libraries or Applications
+
+   3. Parameters
+
+        3.1. xavp_cfg (str)
+
+   4. Functions
+
+        4.1. rtjson_init_routes(rtdoc)
+        4.2. rtjson_push_routes()
+        4.3. rtjson_next_route()
+        4.4. rtjson_update_branch()
+
+   5. JSON Routing Structure
+
+1. Overview
+
+   This module facilitates SIP routing based on JSON specifications.
+
+   The values for R-URI ($ru), outbound proxy ($du) and other attributes
+   used for SIP routing can be retrieved in a JSON document. It is able to
+   process attributes for more than one destination and prepare for
+   routing in serial or parallel fashion.
+
+2. Dependencies
+
+   2.1. Kamailio Modules
+   2.2. External Libraries or Applications
+
+2.1. Kamailio Modules
+
+   The following modules must be loaded before this module:
+     * tm - (optional) transaction management.
+       uac - (optional) user agent operations.
+
+2.2. External Libraries or Applications
+
+   The following libraries or applications must be installed before
+   running Kamailio with this module loaded:
+     * None
+
+3. Parameters
+
+   3.1. xavp_cfg (str)
+
+3.1. xavp_cfg (str)
+
+   The name of the xavp to be used internally by the module.
+
+   Default value is "rtjson".
+
+   Example 1.1. Set xavp_cfg parameter
+...
+modparam("rtjson", "xavp_cfg", "myxavp")
+...
+
+4. Functions
+
+   4.1. rtjson_init_routes(rtdoc)
+   4.2. rtjson_push_routes()
+   4.3. rtjson_next_route()
+   4.4. rtjson_update_branch()
+
+4.1. rtjson_init_routes(rtdoc)
+
+   Initialize routing based on JSON document stored in rtdoc parameter.
+
+   The rtdoc parameter can be a static string or a dynamic string value
+   with config variables. It has to result in a valid JSON document with
+   the structure specified in chapter 'JSON Routing Structure'.
+
+   This function can be used from REQUEST_ROUTE.
+
+   Example 1.2. rtjson_init_routes usage
+...
+rtjson_init_routes("$var(json)");
+...
+
+4.2. rtjson_push_routes()
+
+   Push the routes given in JSON document to rtjson_init_routes(rtdoc) to
+   the internal fields used by Kamailio for routing.
+
+   This function can be used from REQUEST_ROUTE.
+
+   Example 1.3. rtjson_push_routes usage
+...
+rtjson_init_routes("$var(json)");
+rtjson_push_routes();
+...
+
+4.3. rtjson_next_route()
+
+   To be used in failure_route for serial forking, to push the next route
+   to the internal fields used by Kamailio for routing.
+
+   This function can be used from FAILURE_ROUTE.
+
+   Example 1.4. rtjson_next_route usage
+...
+rtjson_init_routes("$var(json)");
+rtjson_push_routes();
+...
+failure_route[REROUTE] {
+        rtjson_next_route();
+}
+...
+
+4.4. rtjson_update_branch()
+
+   To be used in branch_route if the JSON document had attributes that
+   needs to be set for each branch.
+
+   This function can be used from BRANCH_ROUTE.
+
+   Example 1.5. rtjson_update_branch usage
+...
+rtjson_init_routes("$var(json)");
+rtjson_push_routes();
+...
+branch_route[OUTGOING] {
+        rtjson_update_branch();
+}
+...
+
+5. JSON Routing Structure
+
+   The format of the JSON document containing routing information.
+
+   Description of the fields: TBA.
+
+   Example 1.6. JSON Routing Structure
+...
+{
+        "version": "1.0",
+        "routing": "parallel",
+        "routes": [
+                {
+                        "uri": "sip:127.0.0.1:5080",
+                        "dst_uri": "sip:127.0.0.1:5082",
+                        "path": "<sip:127.0.0.1:5084>, <sip:127.0.0.1:5086>",
+                        "socket": "udp:127.0.0.1:5060",
+                        "headers": {
+                                "from": {
+                                        "display": "Alice",
+                                        "uri": "sip:alice at 127.0.0.1"
+                                },
+                                "to": {
+                                        "display": "Alice",
+                                        "uri": "sip:alice at 127.0.0.1"
+                                },
+                                "extra": "X-Hdr-A: abc\r\nX-Hdr-B: bcd\r\n"
+                        },
+                        "branch_flags": 8,
+                        "fr_timer": 5000,
+                        "fr_inv_timer": 30000
+                },
+                {
+                        "uri": "sip:127.0.0.1:5080",
+                        "dst_uri": "sip:127.0.0.1:5082",
+                        "path": "<sip:127.0.0.1:5084>, <sip:127.0.0.1:5086>",
+                        "socket": "udp:127.0.0.1:5060",
+                        "headers": {
+                                "from": {
+                                        "display": "Alice",
+                                        "uri": "sip:alice at 127.0.0.1"
+                                },
+                                "to": {
+                                        "display": "Alice",
+                                        "uri": "sip:alice at 127.0.0.1"
+                                },
+                                "extra": "X-Hdr-A: abc\r\nX-Hdr-B: bcd\r\n"
+                        },
+                        "branch_flags": 8,
+                        "fr_timer": 5000,
+                        "fr_inv_timer": 30000
+                }
+        ]
+}
+...
diff --git a/modules/rtjson/doc/Makefile b/modules/rtjson/doc/Makefile
new file mode 100644
index 0000000..9e93bed
--- /dev/null
+++ b/modules/rtjson/doc/Makefile
@@ -0,0 +1,4 @@
+docs = rtjson.xml
+
+docbook_dir = ../../../docbook
+include $(docbook_dir)/Makefile.module
diff --git a/modules/rtjson/doc/rtjson.xml b/modules/rtjson/doc/rtjson.xml
new file mode 100644
index 0000000..8479f31
--- /dev/null
+++ b/modules/rtjson/doc/rtjson.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding='ISO-8859-1'?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+<!-- Include general documentation entities -->
+<!ENTITY % docentities SYSTEM "../../../docbook/entities.xml">
+%docentities;
+
+]>
+
+<book xmlns:xi="http://www.w3.org/2001/XInclude">
+    <bookinfo>
+	<title>RTJSON Module</title>
+	<productname class="trade">kamailio.org</productname>
+	<authorgroup>
+	    <author>
+		<firstname>Daniel-Constantin</firstname>
+		<surname>Mierla</surname>
+		<email>miconda at gmail.com</email>
+	    </author>
+	    <editor>
+		<firstname>Daniel-Constantin</firstname>
+		<surname>Mierla</surname>
+		<email>miconda at gmail.com</email>
+	    </editor>
+	</authorgroup>
+	<copyright>
+	    <year>2015</year>
+	    <holder>asipto.com</holder>
+	</copyright>
+    </bookinfo>
+    <toc></toc>
+    
+    <xi:include href="rtjson_admin.xml"/>
+    
+    
+</book>
diff --git a/modules/rtjson/doc/rtjson_admin.xml b/modules/rtjson/doc/rtjson_admin.xml
new file mode 100644
index 0000000..4218e73
--- /dev/null
+++ b/modules/rtjson/doc/rtjson_admin.xml
@@ -0,0 +1,252 @@
+<?xml version="1.0" encoding='ISO-8859-1'?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+<!-- Include general documentation entities -->
+<!ENTITY % docentities SYSTEM "../../../docbook/entities.xml">
+%docentities;
+
+]>
+<!-- Module User's Guide -->
+
+<chapter>
+	
+	<title>&adminguide;</title>
+	
+	<section>
+	<title>Overview</title>
+	<para>
+		This module facilitates SIP routing based on JSON specifications.
+	</para>
+	<para>
+		The values for R-URI ($ru), outbound proxy ($du) and other attributes
+		used for SIP routing can be retrieved in a JSON document. It is able
+		to process attributes for more than one destination and prepare for
+		routing in serial or parallel fashion.
+	</para>
+	</section>
+
+	<section>
+	<title>Dependencies</title>
+	<section>
+		<title>&kamailio; Modules</title>
+		<para>
+		The following modules must be loaded before this module:
+			<itemizedlist>
+			<listitem>
+			<para>
+				<emphasis>tm</emphasis> - (optional) transaction management.
+			</para>
+			<para>
+				<emphasis>uac</emphasis> - (optional) user agent operations.
+			</para>
+			</listitem>
+			</itemizedlist>
+		</para>
+	</section>
+	<section>
+		<title>External Libraries or Applications</title>
+		<para>
+		The following libraries or applications must be installed before running
+		&kamailio; with this module loaded:
+			<itemizedlist>
+			<listitem>
+			<para>
+				<emphasis>None</emphasis>
+			</para>
+			</listitem>
+			</itemizedlist>
+		</para>
+	</section>
+	</section>
+	<section>
+	<title>Parameters</title>
+	<section id="rtjson.p.xavp_cfg">
+		<title><varname>xavp_cfg</varname> (str)</title>
+		<para>
+			The name of the xavp to be used internally by the module. 
+		</para>
+		<para>
+		<emphasis>
+			Default value is "rtjson".
+		</emphasis>
+		</para>
+		<example>
+		<title>Set <varname>xavp_cfg</varname> parameter</title>
+		<programlisting format="linespecific">
+...
+modparam("rtjson", "xavp_cfg", "myxavp")
+...
+</programlisting>
+		</example>
+	</section>
+	</section>
+
+	<section>
+	<title>Functions</title>
+	<section id="rtjson.f.rtjson_init_routes">
+	    <title>
+		<function moreinfo="none">rtjson_init_routes(rtdoc)</function>
+	    </title>
+	    <para>
+		Initialize routing based on JSON document stored in rtdoc parameter.
+		</para>
+		<para>
+		The rtdoc parameter can be a static string or a dynamic string
+		value with config variables. It has to result in a valid JSON document
+		with the structure specified in chapter 'JSON Routing Structure'.
+		</para>
+			<para>
+		This function can be used from REQUEST_ROUTE.
+		</para>
+		<example>
+		<title><function>rtjson_init_routes</function> usage</title>
+		<programlisting format="linespecific">
+...
+rtjson_init_routes("$var(json)");
+...
+</programlisting>
+	    </example>
+	</section>
+
+	<section id="rtjson.f.rtjson_push_routes">
+	    <title>
+		<function moreinfo="none">rtjson_push_routes()</function>
+	    </title>
+	    <para>
+		Push the routes given in JSON document to rtjson_init_routes(rtdoc) to
+		the internal fields used by &kamailio; for routing.
+		</para>
+		<para>
+		This function can be used from REQUEST_ROUTE.
+		</para>
+		<example>
+		<title><function>rtjson_push_routes</function> usage</title>
+		<programlisting format="linespecific">
+...
+rtjson_init_routes("$var(json)");
+rtjson_push_routes();
+...
+</programlisting>
+	    </example>
+	</section>
+
+	<section id="rtjson.f.rtjson_next_route">
+	    <title>
+		<function moreinfo="none">rtjson_next_route()</function>
+	    </title>
+	    <para>
+		To be used in failure_route for serial forking, to push the next route
+		to the internal fields used by &kamailio; for routing.
+		</para>
+		<para>
+		This function can be used from FAILURE_ROUTE.
+		</para>
+		<example>
+		<title><function>rtjson_next_route</function> usage</title>
+		<programlisting format="linespecific">
+...
+rtjson_init_routes("$var(json)");
+rtjson_push_routes();
+...
+failure_route[REROUTE] {
+	rtjson_next_route();
+}
+...
+</programlisting>
+	    </example>
+	</section>
+
+	<section id="rtjson.f.rtjson_update_branch">
+	    <title>
+		<function moreinfo="none">rtjson_update_branch()</function>
+	    </title>
+	    <para>
+		To be used in branch_route if the JSON document had attributes
+		that needs to be set for each branch.
+		</para>
+		<para>
+		This function can be used from BRANCH_ROUTE.
+		</para>
+		<example>
+		<title><function>rtjson_update_branch</function> usage</title>
+		<programlisting format="linespecific">
+...
+rtjson_init_routes("$var(json)");
+rtjson_push_routes();
+...
+branch_route[OUTGOING] {
+	rtjson_update_branch();
+}
+...
+</programlisting>
+	    </example>
+	</section>
+
+	</section>
+
+	<section id="rtjson.json-routing-structure">
+	<title>JSON Routing Structure</title>
+	<para>
+		The format of the JSON document containing routing information.
+	</para>
+	<para>
+		Description of the fields: TBA.
+	</para>
+	<example>
+		<title>JSON Routing Structure</title>
+		<programlisting format="linespecific">
+...
+{
+	"version": "1.0",
+	"routing": "parallel",
+	"routes": [
+		{
+			"uri": "sip:127.0.0.1:5080",
+			"dst_uri": "sip:127.0.0.1:5082",
+			"path": "<sip:127.0.0.1:5084>, <sip:127.0.0.1:5086>",
+			"socket": "udp:127.0.0.1:5060",
+			"headers": {
+				"from": {
+					"display": "Alice",
+					"uri": "sip:alice at 127.0.0.1"
+				},
+				"to": {
+					"display": "Alice",
+					"uri": "sip:alice at 127.0.0.1"
+				},
+				"extra": "X-Hdr-A: abc\r\nX-Hdr-B: bcd\r\n"
+			},
+			"branch_flags": 8,
+			"fr_timer": 5000,
+			"fr_inv_timer": 30000
+		},
+		{
+			"uri": "sip:127.0.0.1:5080",
+			"dst_uri": "sip:127.0.0.1:5082",
+			"path": "<sip:127.0.0.1:5084>, <sip:127.0.0.1:5086>",
+			"socket": "udp:127.0.0.1:5060",
+			"headers": {
+				"from": {
+					"display": "Alice",
+					"uri": "sip:alice at 127.0.0.1"
+				},
+				"to": {
+					"display": "Alice",
+					"uri": "sip:alice at 127.0.0.1"
+				},
+				"extra": "X-Hdr-A: abc\r\nX-Hdr-B: bcd\r\n"
+			},
+			"branch_flags": 8,
+			"fr_timer": 5000,
+			"fr_inv_timer": 30000
+		}
+	]
+}
+...
+</programlisting>
+	   </example>
+
+	</section>
+</chapter>
+
diff --git a/modules/rtjson/rtjson_mod.c b/modules/rtjson/rtjson_mod.c
new file mode 100644
index 0000000..963ae34
--- /dev/null
+++ b/modules/rtjson/rtjson_mod.c
@@ -0,0 +1,170 @@
+/**
+ * Copyright (C) 2015 Daniel-Constantin Mierla (asipto.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../../sr_module.h"
+#include "../../dprint.h"
+#include "../../mod_fix.h"
+
+#include "rtjson_routing.h"
+
+MODULE_VERSION
+
+
+str _rtjson_xavp_name = str_init("rtjson");
+
+static int  mod_init(void);
+static int  child_init(int);
+static void mod_destroy(void);
+
+static int w_rtjson_init_routes(sip_msg_t *msg, char *rdoc, char *rflags);
+static int w_rtjson_push_routes(sip_msg_t *msg, char *p1, char *p2);
+static int w_rtjson_next_route(sip_msg_t *msg, char *p1, char *p2);
+static int w_rtjson_update_branch(sip_msg_t *msg, char *p1, char *p2);
+
+static cmd_export_t cmds[]={
+	{"rtjson_init_routes", (cmd_function)w_rtjson_init_routes, 1, fixup_spve_null,
+		0, REQUEST_ROUTE},
+	{"rtjson_push_routes", (cmd_function)w_rtjson_push_routes,     0, 0,
+		0, REQUEST_ROUTE},
+	{"rtjson_next_route", (cmd_function)w_rtjson_next_route,       0, 0,
+		0, REQUEST_ROUTE|FAILURE_ROUTE},
+	{"rtjson_update_branch", (cmd_function)w_rtjson_update_branch, 0, 0,
+		0, BRANCH_ROUTE},
+	{0, 0, 0, 0, 0, 0}
+};
+
+static param_export_t params[]={
+	{"xavp_cfg", PARAM_STR, &_rtjson_xavp_name},
+	{0, 0, 0}
+};
+
+struct module_exports exports = {
+	"rtjson",
+	DEFAULT_DLFLAGS, /* dlopen flags */
+	cmds,
+	params,
+	0,
+	0,              /* exported MI functions */
+	0,              /* exported pseudo-variables */
+	0,              /* extra processes */
+	mod_init,       /* module initialization function */
+	0,              /* response function */
+	mod_destroy,    /* destroy function */
+	child_init      /* per child init function */
+};
+
+/**
+ * init module function
+ */
+static int mod_init(void)
+{
+	if(_rtjson_xavp_name.s==NULL || _rtjson_xavp_name.len<=0) {
+		LM_ERR("invalid xavp name\n");
+		return -1;
+	}
+	if(rtjson_init()<0) {
+		LM_ERR("failed to initialize\n");
+		return -1;
+	}
+	return 0;
+}
+
+/**
+ * @brief Initialize async module children
+ */
+static int child_init(int rank)
+{
+	return 0;
+}
+/**
+ * destroy module function
+ */
+static void mod_destroy(void)
+{
+}
+
+/**
+ *
+ */
+static int w_rtjson_init_routes(sip_msg_t *msg, char *rdoc, char *rflags)
+{
+	str srdoc = {0};
+
+	if(msg==NULL)
+		return -1;
+
+	if(fixup_get_svalue(msg, (gparam_t*)rdoc, &srdoc)!=0 || srdoc.len<=0) {
+		LM_ERR("no routing information\n");
+		return -1;
+	}
+	if(rtjson_init_routes(msg, &srdoc)<0)
+		return -1;
+
+	return 1;
+}
+
+/**
+ *
+ */
+static int w_rtjson_push_routes(sip_msg_t *msg, char *p1, char *p2)
+{
+	if(msg==NULL)
+		return -1;
+
+	if(rtjson_push_routes(msg)<0)
+		return -1;
+
+	return 1;
+}
+
+/**
+ *
+ */
+static int w_rtjson_next_route(sip_msg_t *msg, char *p1, char *p2)
+{
+	if(msg==NULL)
+		return -1;
+
+	if(rtjson_next_route(msg)<0)
+		return -1;
+
+	return 1;
+}
+
+/**
+ *
+ */
+static int w_rtjson_update_branch(sip_msg_t *msg, char *p1, char *p2)
+{
+	if(msg==NULL)
+		return -1;
+
+	if(rtjson_update_branch(msg)<0)
+		return -1;
+
+	return 1;
+}
diff --git a/modules/rtjson/rtjson_routing.c b/modules/rtjson/rtjson_routing.c
new file mode 100644
index 0000000..71ac2e6
--- /dev/null
+++ b/modules/rtjson/rtjson_routing.c
@@ -0,0 +1,717 @@
+/**
+ * Copyright (C) 2015 Daniel-Constantin Mierla (asipto.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../../dprint.h"
+#include "../../xavp.h"
+#include "../../dset.h"
+#include "../../mem/shm_mem.h"
+#include "../../data_lump.h"
+#include "../../lib/srutils/srjson.h"
+#include "../../modules/tm/tm_load.h"
+#include "../../modules/uac/api.h"
+
+#include "rtjson_routing.h"
+
+typedef struct rtjson_data {
+	srjson_doc_t *jdoc;
+	int idx;
+} rtjson_data_t;
+
+extern str _rtjson_xavp_name;
+
+int rtjson_init_serial(sip_msg_t *msg, srjson_doc_t *jdoc, sr_xavp_t *iavp);
+int rtjson_init_parallel(sip_msg_t *msg, srjson_doc_t *jdoc, sr_xavp_t *iavp);
+
+/* tm */
+static struct tm_binds tmb;
+/* uac */
+static uac_api_t uacb;
+
+int rtjson_init(void)
+{
+	if (load_tm_api( &tmb ) == -1) {
+		LM_NOTICE("cannot load the TM API - some features are diabled\n");
+		memset(&tmb, 0, sizeof(struct tm_binds));
+	}
+	if (load_uac_api(&uacb) < 0) {
+		LM_ERR("cannot bind to UAC API - some features are diabled\n");
+		memset(&uacb, 0, sizeof(uac_api_t));
+	}
+	return 0;
+}
+
+#ifdef RTJSON_STORE_SHM
+/**
+ *
+ */
+void rtjson_data_free(void *ptr, sr_xavp_sfree_f sfree)
+{
+	rtjson_data_t *rdata;
+
+	rdata = (rtjson_data_t*)ptr;
+
+	if(rdata->jdoc) {
+		rdata->jdoc->free_fn = sfree;
+		srjson_DeleteDoc(rdata->jdoc);
+	}
+	sfree(ptr);
+}
+
+/**
+ *
+ */
+void *rtjson_malloc(size_t sz)
+{
+	return shm_malloc(sz);
+}
+
+/**
+ *
+ */
+void rtjson_free(void *ptr)
+{
+	shm_free(ptr);
+}
+
+/**
+ *
+ */
+int rtjson_init_routes(sip_msg_t *msg, str *rdoc)
+{
+	srjson_Hooks jhooks;
+	srjson_doc_t *tdoc = NULL;
+	sr_data_t *xdata = NULL;
+	rtjson_data_t *rdata = NULL;
+	sr_xavp_t *xavp=NULL;
+	str xname;
+	sr_xval_t xval;
+
+
+	memset(&jhooks, 0, sizeof(srjson_Hooks));
+	jhooks.malloc_fn = rtjson_malloc;
+	jhooks.free_fn = rtjson_free;
+
+	tdoc = srjson_NewDoc(&jhooks);
+
+	if(tdoc==NULL) {
+		LM_ERR("no more shm\n");
+		return -1;
+	}
+	tdoc->root = srjson_Parse(tdoc, rdoc->s);
+	if(tdoc->root == NULL) {
+		LM_ERR("invalid json doc [[%s]]\n", rdoc->s);
+		srjson_DeleteDoc(tdoc);
+		return -1;
+	}
+	xdata = shm_malloc(sizeof(sr_data_t));
+	if(xdata==NULL) {
+		LM_ERR("no more shm\n");
+		srjson_DeleteDoc(tdoc);
+		return -1;
+	}
+	memset(xdata, 0, sizeof(sr_data_t));
+	rdata = shm_malloc(sizeof(rtjson_data_t));
+	if(rdata==NULL) {
+		LM_ERR("no more shm\n");
+		srjson_DeleteDoc(tdoc);
+		shm_free(xdata);
+		return -1;
+	}
+	memset(rdata, 0, sizeof(rtjson_data_t));
+
+	rdata->jdoc = tdoc;
+	xdata->p = rdata;
+	xdata->pfree = rtjson_data_free;
+
+	memset(&xval, 0, sizeof(sr_xval_t));
+	xval.type = SR_XTYPE_STR;
+	xval.v.s = *rdoc;
+	xname.s = "json";
+	xname.len = 4;
+	if(xavp_add_value(&xname, &xval, &xavp)==NULL) {
+		goto error;
+	}
+
+	memset(&xval, 0, sizeof(sr_xval_t));
+	xval.type = SR_XTYPE_DATA;
+	xval.v.data = xdata;
+	xname.s = "data";
+	xname.len = 4;
+	if(xavp_add_value(&xname, &xval, &xavp)==NULL) {
+		goto error;
+	}
+	/* reset pointers - they are linked inside xavp now */
+	tdoc = NULL;
+	xdata = NULL;
+	rdata = NULL;
+
+	memset(&xval, 0, sizeof(sr_xval_t));
+	xval.type = SR_XTYPE_XAVP;
+	xval.v.xavp = xavp;
+	if(xavp_add_value(&_rtjson_xavp_name, &xval, NULL)==NULL) {
+		goto error;
+	}
+
+	return 0;
+error:
+	if(xavp) xavp_destroy_list(&xavp);
+	if(rdata) shm_free(rdata);
+	if(xdata) shm_free(xdata);
+	if(tdoc) srjson_DeleteDoc(tdoc);
+	return -1;
+}
+#else
+
+/**
+ *
+ */
+int rtjson_init_routes(sip_msg_t *msg, str *rdoc)
+{
+	sr_xavp_t *xavp=NULL;
+	str xname;
+	sr_xval_t xval;
+	srjson_doc_t tdoc;
+
+	srjson_InitDoc(&tdoc, NULL);
+
+	tdoc.root = srjson_Parse(&tdoc, rdoc->s);
+	if(tdoc.root == NULL) {
+		LM_ERR("invalid json doc [[%s]]\n", rdoc->s);
+		srjson_DestroyDoc(&tdoc);
+		return -1;
+	}
+
+	/* basic validation */
+
+	srjson_DestroyDoc(&tdoc);
+
+	memset(&xval, 0, sizeof(sr_xval_t));
+	xval.type = SR_XTYPE_INT;
+	xval.v.i = 0;
+	xname.s = "idx";
+	xname.len = 3;
+	if(xavp_add_value(&xname, &xval, &xavp)==NULL) {
+		goto error;
+	}
+
+	memset(&xval, 0, sizeof(sr_xval_t));
+	xval.type = SR_XTYPE_STR;
+	xval.v.s = *rdoc;
+	xname.s = "json";
+	xname.len = 4;
+	if(xavp_add_value(&xname, &xval, &xavp)==NULL) {
+		goto error;
+	}
+
+	memset(&xval, 0, sizeof(sr_xval_t));
+	xval.type = SR_XTYPE_XAVP;
+	xval.v.xavp = xavp;
+	if(xavp_add_value(&_rtjson_xavp_name, &xval, NULL)==NULL) {
+		goto error;
+	}
+
+	return 0;
+
+error:
+	if(xavp) xavp_destroy_list(&xavp);
+	return -1;
+}
+#endif
+
+/**
+ *
+ */
+int rtjson_push_routes(sip_msg_t *msg)
+{
+	sr_xavp_t *javp = NULL;
+	sr_xavp_t *iavp = NULL;
+	srjson_doc_t tdoc;
+	srjson_t *nj = NULL;
+	str val;
+	str xname;
+	int ret;
+
+	xname.s = "json";
+	xname.len = 4;
+	javp = xavp_get_child_with_sval(&_rtjson_xavp_name, &xname);
+	if(javp==NULL || javp->val.v.s.len<=0) {
+		LM_WARN("no json for routing\n");
+		return -1;
+	}
+
+	xname.s = "idx";
+	xname.len = 3;
+	iavp = xavp_get_child_with_ival(&_rtjson_xavp_name, &xname);
+	if(iavp==NULL) {
+		LM_WARN("no idx for routing\n");
+		return -1;
+	}
+
+	srjson_InitDoc(&tdoc, NULL);
+
+	tdoc.root = srjson_Parse(&tdoc, javp->val.v.s.s);
+	if(tdoc.root == NULL) {
+		LM_ERR("invalid json doc [[%s]]\n", javp->val.v.s.s);
+		srjson_DestroyDoc(&tdoc);
+		return -1;
+	}
+
+	nj = srjson_GetObjectItem(&tdoc, tdoc.root, "routing");
+	if(nj==NULL || nj->valuestring==NULL) {
+		LM_ERR("missing or invalid routing field\n");
+		goto error;
+	}
+	val.s = nj->valuestring;
+	val.len = strlen(val.s);
+
+	if(val.len==6 && strncmp(val.s, "serial", 6)==0) {
+		LM_DBG("supported routing [%.*s]\n", val.len, val.s);
+		ret = rtjson_init_serial(msg, &tdoc, iavp);
+	} else if(val.len==8 && strncmp(val.s, "parallel", 8)==0) {
+		LM_DBG("supported routing [%.*s]\n", val.len, val.s);
+		ret = rtjson_init_parallel(msg, &tdoc, iavp);
+	} else {
+		LM_ERR("unsupported routing [%.*s]\n", val.len, val.s);
+		goto error;
+	}
+
+	srjson_DestroyDoc(&tdoc);
+	return ret;
+
+error:
+	srjson_DestroyDoc(&tdoc);
+	return -1;
+}
+
+/**
+ *
+ */
+int rtjson_init_serial(sip_msg_t *msg, srjson_doc_t *jdoc, sr_xavp_t *iavp)
+{
+	srjson_t *nj = NULL;
+	srjson_t *rj = NULL;
+	str val;
+	unsigned int bflags = 0;
+	unsigned int old_bflags = 0;
+
+	nj = srjson_GetObjectItem(jdoc, jdoc->root, "routes");
+	if(nj==NULL || nj->type!=srjson_Array || nj->child==NULL) {
+		LM_ERR("missing or invalid routes field\n");
+		goto error;
+	}
+
+	clear_branches();
+
+	rj = srjson_GetObjectItem(jdoc, nj, "uri");
+	if(rj!=NULL && rj->type==srjson_String && rj->valuestring!=NULL) {
+		val.s = rj->valuestring;
+		val.len = strlen(val.s);
+		if (rewrite_uri(msg, &val) < 0) {
+			LM_ERR("unable to rewrite Request-URI\n");
+			goto error;
+		}
+	}
+
+	reset_dst_uri(msg);
+	reset_path_vector(msg);
+	reset_instance(msg);
+	reset_ruid(msg);
+	reset_ua(msg);
+	reset_force_socket(msg);
+	msg->reg_id = 0;
+	set_ruri_q(0);
+
+	rj = srjson_GetObjectItem(jdoc, nj, "dst_uri");
+	if(rj!=NULL && rj->type==srjson_String && rj->valuestring!=NULL) {
+		val.s = rj->valuestring;
+		val.len = strlen(val.s);
+		if (set_dst_uri(msg, &val) < 0) {
+			LM_ERR("unable to set destination uri\n");
+			goto error;
+		}
+	}
+
+	rj = srjson_GetObjectItem(jdoc, nj, "path");
+	if(rj!=NULL && rj->type==srjson_String && rj->valuestring!=NULL) {
+		val.s = rj->valuestring;
+		val.len = strlen(val.s);
+		if (set_path_vector(msg, &val) < 0) {
+			LM_ERR("unable to set path\n");
+			goto error;
+		}
+	}
+
+	rj = srjson_GetObjectItem(jdoc, nj, "branch_flags");
+	if(rj!=NULL && rj->type==srjson_Number && rj->valueint!=0) {
+		bflags = rj->valueint;
+
+		old_bflags = 0;
+		getbflagsval(0, &old_bflags);
+		setbflagsval(0, old_bflags|bflags);
+	}
+
+	iavp->val.v.i++;
+
+	return 0;
+
+error:
+	return -1;
+}
+
+/**
+ *
+ */
+int rtjson_prepare_branch(sip_msg_t *msg, srjson_doc_t *jdoc, srjson_t *nj)
+{
+	srjson_t *rj = NULL;
+	srjson_t *tj = NULL;
+	srjson_t *vj = NULL;
+	str xdsp = {0};
+	str xuri = {0};
+	str xhdr = {0};
+	unsigned int fr = 0;
+	unsigned int fr_inv = 0;
+	struct lump *anchor = NULL;
+	char *s;
+
+
+	if(tmb.set_fr!=NULL) {
+		rj = srjson_GetObjectItem(jdoc, nj, "fr_timer");
+		if(rj!=NULL && rj->type==srjson_Number && rj->valueint!=0) {
+			fr = rj->valueint;
+		}
+		rj = srjson_GetObjectItem(jdoc, nj, "fr_inv_timer");
+		if(rj!=NULL && rj->type==srjson_Number && rj->valueint!=0) {
+			fr_inv = rj->valueint;
+		}
+		if(fr || fr_inv) tmb.set_fr(msg, fr_inv, fr);
+	}
+	rj = srjson_GetObjectItem(jdoc, nj, "headers");
+	if(rj==NULL || rj->type!=srjson_Object || rj->child==NULL) {
+		LM_DBG("no header operations - done\n");
+		return 0;
+	}
+
+	tj = srjson_GetObjectItem(jdoc, rj, "extra");
+	if(tj!=NULL && tj->type==srjson_String && tj->valuestring!=0) {
+		xhdr.s =  tj->valuestring;
+		xhdr.len = strlen(xhdr.s);
+	}
+
+	if(xhdr.len>4) {
+		anchor = anchor_lump(msg, msg->unparsed - msg->buf, 0, 0);
+		if(anchor == 0) {
+			LM_ERR("can't get anchor\n");
+			return -1;
+		}
+		s = pkg_malloc(xhdr.len+1);
+		if(s==NULL) {
+			LM_ERR("no more pkg\n");
+			return -1;
+		}
+		strncpy(s, xhdr.s, xhdr.len);
+		s[xhdr.len] = '\0';
+		if (insert_new_lump_before(anchor, s, xhdr.len, 0) == 0) {
+			LM_ERR("can't insert lump\n");
+			pkg_free(s);
+			return -1;
+		}
+	}
+
+	if(uacb.replace_from!=NULL) {
+		tj = srjson_GetObjectItem(jdoc, rj, "from");
+		if(tj!=NULL && tj->type==srjson_Object && rj->child!=NULL) {
+			vj = srjson_GetObjectItem(jdoc, tj, "display");
+			if(vj!=NULL && vj->type==srjson_String && vj->valuestring!=0) {
+				xdsp.s =  vj->valuestring;
+				xdsp.len = strlen(xdsp.s);
+			}
+			vj = srjson_GetObjectItem(jdoc, tj, "uri");
+			if(vj!=NULL && vj->type==srjson_String && vj->valuestring!=0) {
+				xuri.s =  vj->valuestring;
+				xuri.len = strlen(xuri.s);
+			}
+			if(xdsp.len>0 || xuri.len>0) {
+				uacb.replace_from(msg, &xdsp, &xuri);
+			}
+		}
+	}
+
+	if(uacb.replace_to!=NULL) {
+		tj = srjson_GetObjectItem(jdoc, rj, "to");
+		if(tj!=NULL && tj->type==srjson_Object && rj->child!=NULL) {
+			vj = srjson_GetObjectItem(jdoc, tj, "display");
+			if(vj!=NULL && vj->type==srjson_String && vj->valuestring!=0) {
+				xdsp.s =  vj->valuestring;
+				xdsp.len = strlen(xdsp.s);
+			}
+			vj = srjson_GetObjectItem(jdoc, tj, "uri");
+			if(vj!=NULL && vj->type==srjson_String && vj->valuestring!=0) {
+				xuri.s =  vj->valuestring;
+				xuri.len = strlen(xuri.s);
+			}
+			if(xdsp.len>0 || xuri.len>0) {
+				uacb.replace_from(msg, &xdsp, &xuri);
+			}
+		}
+	}
+
+	return 0;
+}
+
+/**
+ *
+ */
+int rtjson_append_branch(sip_msg_t *msg, srjson_doc_t *jdoc, srjson_t *nj)
+{
+	srjson_t *rj = NULL;
+	str uri = {0};
+	str duri = {0};
+	str path = {0};
+	struct socket_info* fsocket = NULL;
+	unsigned int bflags = 0;
+
+	rj = srjson_GetObjectItem(jdoc, nj, "uri");
+	if(rj==NULL || rj->type!=srjson_String || rj->valuestring==NULL) {
+		return -1;
+	}
+
+	uri.s = rj->valuestring;
+	uri.len = strlen(uri.s);
+
+	rj = srjson_GetObjectItem(jdoc, nj, "dst_uri");
+	if(rj!=NULL && rj->type==srjson_String && rj->valuestring!=NULL) {
+		duri.s = rj->valuestring;
+		duri.len = strlen(duri.s);
+	}
+	rj = srjson_GetObjectItem(jdoc, nj, "path");
+	if(rj!=NULL && rj->type==srjson_String && rj->valuestring!=NULL) {
+		path.s = rj->valuestring;
+		path.len = strlen(path.s);
+	}
+	
+	if (append_branch(msg, &uri, &duri, &path, 0, bflags,
+					  fsocket, 0 /*instance*/, 0,
+					  0, 0) <0) {
+		LM_ERR("failed to append branch\n");
+		goto error;
+	}
+
+	return 0;
+
+error:
+	return -1;
+}
+
+/**
+ *
+ */
+int rtjson_init_parallel(sip_msg_t *msg, srjson_doc_t *jdoc, sr_xavp_t *iavp)
+{
+	srjson_t *nj = NULL;
+	int ret;
+
+	nj = srjson_GetObjectItem(jdoc, jdoc->root, "routes");
+	if(nj==NULL || nj->type!=srjson_Array || nj->child==NULL) {
+		LM_ERR("missing or invalid routes field\n");
+		goto error;
+	}
+
+	ret = rtjson_init_serial(msg, jdoc, iavp);
+	if(ret<0)
+		return ret;
+
+	/* skip first - used for r-uri */
+	nj = nj->next;
+
+	while(nj) {
+		rtjson_append_branch(msg, jdoc, nj);
+
+		iavp->val.v.i++;
+		nj = nj->next;
+	}
+
+	return 0;
+
+error:
+	return -1;
+}
+
+/**
+ *
+ */
+int rtjson_next_route(sip_msg_t *msg)
+{
+	sr_xavp_t *javp = NULL;
+	sr_xavp_t *iavp = NULL;
+	srjson_doc_t tdoc;
+	srjson_t *nj = NULL;
+	str val;
+	str xname;
+	int i;
+
+	xname.s = "json";
+	xname.len = 4;
+	javp = xavp_get_child_with_sval(&_rtjson_xavp_name, &xname);
+	if(javp==NULL || javp->val.v.s.len<=0) {
+		LM_WARN("no json for routing\n");
+		return -1;
+	}
+
+	xname.s = "idx";
+	xname.len = 3;
+	iavp = xavp_get_child_with_ival(&_rtjson_xavp_name, &xname);
+	if(iavp==NULL) {
+		LM_WARN("no idx for routing\n");
+		return -1;
+	}
+
+	srjson_InitDoc(&tdoc, NULL);
+
+	tdoc.root = srjson_Parse(&tdoc, javp->val.v.s.s);
+	if(tdoc.root == NULL) {
+		LM_ERR("invalid json doc [[%s]]\n", javp->val.v.s.s);
+		srjson_DestroyDoc(&tdoc);
+		return -1;
+	}
+
+	nj = srjson_GetObjectItem(&tdoc, tdoc.root, "routing");
+	if(nj==NULL || nj->valuestring==NULL) {
+		LM_ERR("missing or invalid routing field\n");
+		goto error;
+	}
+	val.s = nj->valuestring;
+	val.len = strlen(val.s);
+
+	if(val.len!=6 || strncmp(val.s, "serial", 6)!=0) {
+		LM_DBG("not serial routing [%.*s]\n", val.len, val.s);
+		goto error;
+	}
+
+	nj = srjson_GetObjectItem(&tdoc, tdoc.root, "routes");
+	if(nj==NULL || nj->type!=srjson_Array || nj->child==NULL) {
+		LM_ERR("missing or invalid routes field\n");
+		goto error;
+	}
+
+	i = 0;
+	while(nj && i<iavp->val.v.i) {
+		nj = nj->next;
+		i++;
+	}
+	if(nj==NULL)
+		goto error;
+
+	iavp->val.v.i++;
+	if(rtjson_append_branch(msg, &tdoc, nj)<0)
+		goto error;
+
+	srjson_DestroyDoc(&tdoc);
+	return 0;
+
+error:
+	srjson_DestroyDoc(&tdoc);
+	return -1;
+}
+
+/**
+ *
+ */
+int rtjson_update_branch(sip_msg_t *msg)
+{
+	sr_xavp_t *javp = NULL;
+	sr_xavp_t *iavp = NULL;
+	srjson_doc_t tdoc;
+	srjson_t *nj = NULL;
+	str val;
+	str xname;
+	int i;
+
+	xname.s = "json";
+	xname.len = 4;
+	javp = xavp_get_child_with_sval(&_rtjson_xavp_name, &xname);
+	if(javp==NULL || javp->val.v.s.len<=0) {
+		LM_WARN("no json for routing\n");
+		return -1;
+	}
+
+	xname.s = "idx";
+	xname.len = 3;
+	iavp = xavp_get_child_with_ival(&_rtjson_xavp_name, &xname);
+	if(iavp==NULL) {
+		LM_WARN("no idx for routing\n");
+		return -1;
+	}
+
+	srjson_InitDoc(&tdoc, NULL);
+
+	tdoc.root = srjson_Parse(&tdoc, javp->val.v.s.s);
+	if(tdoc.root == NULL) {
+		LM_ERR("invalid json doc [[%s]]\n", javp->val.v.s.s);
+		srjson_DestroyDoc(&tdoc);
+		return -1;
+	}
+
+	nj = srjson_GetObjectItem(&tdoc, tdoc.root, "routing");
+	if(nj==NULL || nj->valuestring==NULL) {
+		LM_ERR("missing or invalid routing field\n");
+		goto error;
+	}
+	val.s = nj->valuestring;
+	val.len = strlen(val.s);
+
+	if(val.len!=6 || strncmp(val.s, "serial", 6)!=0) {
+		LM_DBG("not serial routing [%.*s]\n", val.len, val.s);
+		goto error;
+	}
+
+	nj = srjson_GetObjectItem(&tdoc, tdoc.root, "routes");
+	if(nj==NULL || nj->type!=srjson_Array || nj->child==NULL) {
+		LM_ERR("missing or invalid routes field\n");
+		goto error;
+	}
+
+	i = 0;
+	while(nj && i<iavp->val.v.i) {
+		nj = nj->next;
+		i++;
+	}
+	if(nj==NULL)
+		goto error;
+
+	if(rtjson_prepare_branch(msg, &tdoc, nj)<0)
+		goto error;
+
+	srjson_DestroyDoc(&tdoc);
+	return 0;
+
+error:
+	srjson_DestroyDoc(&tdoc);
+	return -1;
+
+}
+
diff --git a/modules/rtjson/rtjson_routing.h b/modules/rtjson/rtjson_routing.h
new file mode 100644
index 0000000..33d03eb
--- /dev/null
+++ b/modules/rtjson/rtjson_routing.h
@@ -0,0 +1,34 @@
+/**
+ * Copyright (C) 2015 Daniel-Constantin Mierla (asipto.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _RTJSON_ROUTING_H_
+#define _RTJSON_ROUTING_H_
+
+#include "../../parser/msg_parser.h"
+
+int rtjson_init_routes(sip_msg_t *msg, str *rdoc);
+int rtjson_push_routes(sip_msg_t *msg);
+int rtjson_next_route(sip_msg_t *msg);
+int rtjson_update_branch(sip_msg_t *msg);
+int rtjson_init(void);
+
+#endif
diff --git a/modules/rtpengine/Makefile b/modules/rtpengine/Makefile
index 3d3425b..3287ee0 100644
--- a/modules/rtpengine/Makefile
+++ b/modules/rtpengine/Makefile
@@ -1,8 +1,3 @@
-# $Id$
-#
-# print example module makefile
-#
-#
 # WARNING: do not run this directly, it should be run by the master Makefile
 
 include ../../Makefile.defs
diff --git a/modules/rtpengine/README b/modules/rtpengine/README
index b38d92c..ae5870f 100644
--- a/modules/rtpengine/README
+++ b/modules/rtpengine/README
@@ -62,10 +62,14 @@ Richard Fuchs
 
               4.1. rtpengine_sock (string)
               4.2. rtpengine_disable_tout (integer)
-              4.3. rtpengine_tout (integer)
-              4.4. rtpengine_retr (integer)
-              4.5. extra_id_pv (string)
-              4.6. setid_avp (string)
+              4.3. rtpengine_tout_ms (integer)
+              4.4. queried_nodes_limit (integer)
+              4.5. rtpengine_retr (integer)
+              4.6. extra_id_pv (string)
+              4.7. setid_avp (string)
+              4.8. force_send_interface (string)
+              4.9. write_sdp_pv (string)
+              4.10. rtp_inst_pvar (string)
 
         5. Functions
 
@@ -91,19 +95,23 @@ Richard Fuchs
 
    1.1. Set rtpengine_sock parameter
    1.2. Set rtpengine_disable_tout parameter
-   1.3. Set rtpengine_tout parameter
-   1.4. Set rtpengine_retr parameter
-   1.5. Set extra_id_pv parameter
-   1.6. Set setid_avp parameter
-   1.7. set_rtpengine_set usage
-   1.8. rtpengine_offer usage
-   1.9. rtpengine_answer usage
-   1.10. rtpengine_delete usage
-   1.11. rtpengine_manage usage
-   1.12. start_recording usage
-   1.13. $rtpstat Usage
-   1.14. nh_enable_rtpp usage
-   1.15. nh_show_rtpp usage
+   1.3. Set rtpengine_tout_ms parameter
+   1.4. Set queried_nodes_limit parameter
+   1.5. Set rtpengine_retr parameter
+   1.6. Set extra_id_pv parameter
+   1.7. Set setid_avp parameter
+   1.8. Set force_send_interface parameter
+   1.9. Set write_sdp_avp parameter
+   1.10. Set rtp_inst_pvar parameter
+   1.11. set_rtpengine_set usage
+   1.12. rtpengine_offer usage
+   1.13. rtpengine_answer usage
+   1.14. rtpengine_delete usage
+   1.15. rtpengine_manage usage
+   1.16. start_recording usage
+   1.17. $rtpstat Usage
+   1.18. nh_enable_rtpp usage
+   1.19. nh_show_rtpp usage
 
 Chapter 1. Admin Guide
 
@@ -120,10 +128,14 @@ Chapter 1. Admin Guide
 
         4.1. rtpengine_sock (string)
         4.2. rtpengine_disable_tout (integer)
-        4.3. rtpengine_tout (integer)
-        4.4. rtpengine_retr (integer)
-        4.5. extra_id_pv (string)
-        4.6. setid_avp (string)
+        4.3. rtpengine_tout_ms (integer)
+        4.4. queried_nodes_limit (integer)
+        4.5. rtpengine_retr (integer)
+        4.6. extra_id_pv (string)
+        4.7. setid_avp (string)
+        4.8. force_send_interface (string)
+        4.9. write_sdp_pv (string)
+        4.10. rtp_inst_pvar (string)
 
    5. Functions
 
@@ -208,10 +220,14 @@ Chapter 1. Admin Guide
 
    4.1. rtpengine_sock (string)
    4.2. rtpengine_disable_tout (integer)
-   4.3. rtpengine_tout (integer)
-   4.4. rtpengine_retr (integer)
-   4.5. extra_id_pv (string)
-   4.6. setid_avp (string)
+   4.3. rtpengine_tout_ms (integer)
+   4.4. queried_nodes_limit (integer)
+   4.5. rtpengine_retr (integer)
+   4.6. extra_id_pv (string)
+   4.7. setid_avp (string)
+   4.8. force_send_interface (string)
+   4.9. write_sdp_pv (string)
+   4.10. rtp_inst_pvar (string)
 
 4.1. rtpengine_sock (string)
 
@@ -224,9 +240,9 @@ Chapter 1. Admin Guide
 ...
 # single rtproxy
 modparam("rtpengine", "rtpengine_sock", "udp:localhost:12221")
-# multiple rtproxies for LB
+# multiple rtproxies for LB with weights (missing weight defaults to 1)
 modparam("rtpengine", "rtpengine_sock",
-        "udp:localhost:12221 udp:localhost:12222")
+        "udp:localhost:12221=2 udp:localhost:12222=1")
 # multiple sets of multiple rtproxies
 modparam("rtpengine", "rtpengine_sock",
         "1 == udp:localhost:12221 udp:localhost:12222")
@@ -247,30 +263,46 @@ modparam("rtpengine", "rtpengine_sock",
 modparam("rtpengine", "rtpengine_disable_tout", 20)
 ...
 
-4.3. rtpengine_tout (integer)
+4.3. rtpengine_tout_ms (integer)
 
-   Timeout value in waiting for reply from RTP proxy.
+   Timeout value expressed in milliseconds in waiting for reply from RTP
+   proxy.
 
-   Default value is "1".
+   Default value is "1000".
 
-   Example 1.3. Set rtpengine_tout parameter
+   Example 1.3. Set rtpengine_tout_ms parameter
 ...
-modparam("rtpengine", "rtpengine_tout", 2)
+modparam("rtpengine", "rtpengine_tout_ms", 2000)
 ...
 
-4.4. rtpengine_retr (integer)
+4.4. queried_nodes_limit (integer)
+
+   The total number of nodes inside a set (sets are configurable via
+   rtpengine_sock function) to be queried before giving up establishing a
+   session. This brings more flexibility in case checking all rtpengines
+   would take too long. Max limit is 50.
+
+   By default all nodes in a set are tried before giving up communicating
+   with the rtpengines.
+
+   Example 1.4. Set queried_nodes_limit parameter
+...
+modparam("rtpengine", "queried_nodes_limit", 5)
+...
+
+4.5. rtpengine_retr (integer)
 
    How many times the module should retry to send and receive after
    timeout was generated.
 
    Default value is "5".
 
-   Example 1.4. Set rtpengine_retr parameter
+   Example 1.5. Set rtpengine_retr parameter
 ...
 modparam("rtpengine", "rtpengine_retr", 2)
 ...
 
-4.5. extra_id_pv (string)
+4.6. extra_id_pv (string)
 
    The parameter sets the PV defination to use when the "b" parameter is
    used on rtpengine_delete(), rtpengine_offer(), rtpengine_answer() or
@@ -278,12 +310,12 @@ modparam("rtpengine", "rtpengine_retr", 2)
 
    Default is empty, the "b" parameter may not be used then.
 
-   Example 1.5. Set extra_id_pv parameter
+   Example 1.6. Set extra_id_pv parameter
 ...
 modparam("rtpengine", "extra_id_pv", "$avp(extra_id)")
 ...
 
-4.6. setid_avp (string)
+4.7. setid_avp (string)
 
    The parameter defines an AVP that, if set, determines which RTP proxy
    set rtpengine_offer(), rtpengine_answer(), rtpengine_delete(), and
@@ -291,11 +323,51 @@ modparam("rtpengine", "extra_id_pv", "$avp(extra_id)")
 
    There is no default value.
 
-   Example 1.6. Set setid_avp parameter
+   Example 1.7. Set setid_avp parameter
 ...
 modparam("rtpengine", "setid_avp", "$avp(setid)")
 ...
 
+4.8. force_send_interface (string)
+
+   Forces all control messages between the SIP proxy and the RTP proxy to
+   be sent from the specified local interface. Only IPv4 addresses are
+   supported so far. If not specified, the default interface selected by
+   the operating system will be used.
+
+   There is no default value.
+
+   Example 1.8. Set force_send_interface parameter
+...
+modparam("rtpengine", "force_send_interface", "10.3.7.123")
+...
+
+4.9. write_sdp_pv (string)
+
+   If this parameter is set to a valid AVP or script var specifier, the
+   SDP returned by rtpengine in the offer/answer operations is returned in
+   the specified variable instead of the message body.
+
+   There is no default value.
+
+   Example 1.9. Set write_sdp_avp parameter
+...
+modparam("rtpengine", "write_sdp_avp", "$avp(sdp)")
+...
+
+4.10. rtp_inst_pvar (string)
+
+   A pseudo variable to store the chosen RTP Engine IP address. If this
+   parameter is set, the IP address and port of the instance chosen will
+   be stored in the given variable.
+
+   By default, this parameter is not set.
+
+   Example 1.10. Set rtp_inst_pvar parameter
+...
+modparam("rtpproxy", "rtp_inst_pvar", "$avp(RTP_INSTANCE)")
+...
+
 5. Functions
 
    5.1. set_rtpengine_set(setid[, setid])
@@ -327,7 +399,7 @@ modparam("rtpengine", "setid_avp", "$avp(setid)")
    This function can be used from REQUEST_ROUTE, ONREPLY_ROUTE,
    BRANCH_ROUTE.
 
-   Example 1.7. set_rtpengine_set usage
+   Example 1.11. set_rtpengine_set usage
 ...
 set_rtpengine_set("2");
 rtpengine_offer();
@@ -497,7 +569,7 @@ rtpengine_offer();
 
    This function can be used from ANY_ROUTE.
 
-   Example 1.8. rtpengine_offer usage
+   Example 1.12. rtpengine_offer usage
 route {
 ...
     if (is_method("INVITE")) {
@@ -541,7 +613,7 @@ onreply_route[2]
    This function can be used from REQUEST_ROUTE, ONREPLY_ROUTE,
    FAILURE_ROUTE, BRANCH_ROUTE.
 
-   Example 1.9. rtpengine_answer usage
+   Example 1.13. rtpengine_answer usage
 
    See rtpengine_offer() function example above for example.
 
@@ -554,7 +626,7 @@ onreply_route[2]
 
    This function can be used from ANY_ROUTE.
 
-   Example 1.10. rtpengine_delete usage
+   Example 1.14. rtpengine_delete usage
 ...
 rtpengine_delete();
 ...
@@ -584,7 +656,7 @@ rtpengine_delete();
 
    This function can be used from ANY_ROUTE.
 
-   Example 1.11. rtpengine_manage usage
+   Example 1.15. rtpengine_manage usage
 ...
 rtpengine_manage();
 ...
@@ -597,7 +669,7 @@ rtpengine_manage();
 
    This function can be used from REQUEST_ROUTE and ONREPLY_ROUTE.
 
-   Example 1.12. start_recording usage
+   Example 1.16. start_recording usage
 ...
 start_recording();
 ...
@@ -613,7 +685,7 @@ start_recording();
    packet counters. The statistics must be retrieved before the session is
    deleted (before rtpengine_delete()).
 
-   Example 1.13. $rtpstat Usage
+   Example 1.17. $rtpstat Usage
 ...
     append_hf("X-RTP-Statistics: $rtpstat\r\n");
 ...
@@ -636,7 +708,7 @@ start_recording();
    NOTE: if a RTP proxy is defined multiple times (in the same or
    diferente sete), all of its instances will be enables/disabled.
 
-   Example 1.14.  nh_enable_rtpp usage
+   Example 1.18.  nh_enable_rtpp usage
 ...
 $ kamctl fifo nh_enable_rtpp udp:192.168.2.133:8081 0
 ...
@@ -644,11 +716,14 @@ $ kamctl fifo nh_enable_rtpp udp:192.168.2.133:8081 0
 7.2. nh_show_rtpp
 
    Displays all the RTP proxies and their information: set and status
-   (disabled or not, weight and recheck_ticks).
+   (disabled or not, weight and recheck_ticks). If a RTP proxy has been
+   disabled by a mi command a "(permanent)" quote will appear when
+   printing the disabled status. This is to differentiate from a temporary
+   disable due to the proxy being not found responsive by kamailio.
 
    No parameter.
 
-   Example 1.15.  nh_show_rtpp usage
+   Example 1.19.  nh_show_rtpp usage
 ...
 $ kamctl fifo nh_show_rtpp
 ...
diff --git a/modules/rtpengine/doc/rtpengine_admin.xml b/modules/rtpengine/doc/rtpengine_admin.xml
index fdc9a2d..6be5386 100644
--- a/modules/rtpengine/doc/rtpengine_admin.xml
+++ b/modules/rtpengine/doc/rtpengine_admin.xml
@@ -126,9 +126,9 @@
 ...
 # single rtproxy
 modparam("rtpengine", "rtpengine_sock", "udp:localhost:12221")
-# multiple rtproxies for LB
+# multiple rtproxies for LB with weights (missing weight defaults to 1)
 modparam("rtpengine", "rtpengine_sock",
-	"udp:localhost:12221 udp:localhost:12222")
+	"udp:localhost:12221=2 udp:localhost:12222=1")
 # multiple sets of multiple rtproxies
 modparam("rtpengine", "rtpengine_sock",
 	"1 == udp:localhost:12221 udp:localhost:12222")
@@ -159,21 +159,42 @@ modparam("rtpengine", "rtpengine_disable_tout", 20)
 </programlisting>
 		</example>
 	</section>
-	<section id="rtpengine.p.rtpengine_tout">
-		<title><varname>rtpengine_tout</varname> (integer)</title>
+	<section id="rtpengine.p.rtpengine_tout_ms">
+		<title><varname>rtpengine_tout_ms</varname> (integer)</title>
 		<para>
-		Timeout value in waiting for reply from &rtp; proxy.
+		Timeout value expressed in milliseconds in waiting for reply from &rtp; proxy.
 		</para>
 		<para>
 		<emphasis>
-			Default value is <quote>1</quote>.
+			Default value is <quote>1000</quote>.
 		</emphasis>
 		</para>
 		<example>
-		<title>Set <varname>rtpengine_tout</varname> parameter</title>
+		<title>Set <varname>rtpengine_tout_ms</varname> parameter</title>
 		<programlisting format="linespecific">
 ...
-modparam("rtpengine", "rtpengine_tout", 2)
+modparam("rtpengine", "rtpengine_tout_ms", 2000)
+...
+</programlisting>
+		</example>
+	</section>
+	<section id="rtpengine.p.queried_nodes_limit">
+		<title><varname>queried_nodes_limit</varname> (integer)</title>
+		<para>
+		The total number of nodes inside a set (sets are configurable via rtpengine_sock function) to be queried 
+		before giving up establishing a session. This brings more flexibility in case checking all rtpengines
+		would take too long. Max limit is 50.
+		</para>
+		<para>
+		<emphasis>
+			By default all nodes in a set are tried before giving up communicating with the rtpengines.
+		</emphasis>
+		</para>
+		<example>
+		<title>Set <varname>queried_nodes_limit</varname> parameter</title>
+		<programlisting format="linespecific">
+...
+modparam("rtpengine", "queried_nodes_limit", 5)
 ...
 </programlisting>
 		</example>
@@ -239,6 +260,72 @@ modparam("rtpengine", "setid_avp", "$avp(setid)")
 		</example>
 	</section>
 
+	<section id="rtpengine.p.force_send_interface">
+		<title><varname>force_send_interface</varname> (string)</title>
+		<para>
+			Forces all control messages between the &sip; proxy and
+			the &rtp; proxy to be sent from the specified local
+			interface. Both IPv4 and IPv6 addresses are supported. If
+			not specified, the default interface selected by the
+			operating system will be used.
+			Note: when rtpengine_sock is a IPv6 link-local address,
+			one _must_ set this parameter in order to successfully connect to RTP engine.
+			This is necessarely because OS needs additional scope_id hint to communicate
+			over IPv6 link locals. The scope_id is resolved based on the given IPv6.
+		</para>
+		<para>
+			There is no default value.
+		</para>
+		<example>
+		<title>Set <varname>force_send_interface</varname> parameter</title>
+<programlisting format="linespecific">
+...
+modparam("rtpengine", "force_send_interface", "10.3.7.123")
+modparam("rtpengine", "force_send_interface", "2001:8d8:1ff:10c0:9a90:96ff:fea8:fd99")
+...
+</programlisting>
+		</example>
+	</section>
+	<section id="rtpengine.p.write_sdp_pv">
+		<title><varname>write_sdp_pv</varname> (string)</title>
+		<para>
+			If this parameter is set to a valid AVP or script var specifier, the
+            SDP returned by rtpengine in the offer/answer operations
+            is returned in the specified variable instead of the
+            message body.
+		</para>
+		<para>
+			There is no default value.
+		</para>
+		<example>
+		<title>Set <varname>write_sdp_avp</varname> parameter</title>
+<programlisting format="linespecific">
+...
+modparam("rtpengine", "write_sdp_avp", "$avp(sdp)")
+...
+</programlisting>
+		</example>
+	</section>
+
+	<section id="rtpengine.p.rtp_inst_pvar">
+		<title><varname>rtp_inst_pvar</varname> (string)</title>
+		<para>
+			A pseudo variable to store the chosen RTP Engine IP address.
+			If this parameter is set, the IP address and port of the instance chosen will be stored in the given variable.
+		</para>
+		<para>
+			By default, this parameter is not set.
+		</para>
+		<example>
+		<title>Set <varname>rtp_inst_pvar</varname> parameter</title>
+<programlisting format="linespecific">
+...
+modparam("rtpproxy", "rtp_inst_pvar", "$avp(RTP_INSTANCE)")
+...
+</programlisting>
+		</example>
+	</section>
+
 	</section>
 
 	<section>
@@ -736,7 +823,9 @@ $ &ctltool; fifo nh_enable_rtpp udp:192.168.2.133:8081 0
 			<title><function moreinfo="none">nh_show_rtpp</function></title>
 			<para>
 			Displays all the &rtp; proxies and their information: set and
-			status (disabled or not, weight and recheck_ticks).
+			status (disabled or not, weight and recheck_ticks). If a RTP proxy has been disabled by a mi command
+			a "(permanent)" quote will appear when printing the disabled status. This is to differentiate from
+			a temporary disable due to the proxy being not found responsive by kamailio.
 			</para>
 			<para>
 			No parameter.
diff --git a/modules/rtpengine/rtpengine.c b/modules/rtpengine/rtpengine.c
index b5960b2..609ebc5 100644
--- a/modules/rtpengine/rtpengine.c
+++ b/modules/rtpengine/rtpengine.c
@@ -1,6 +1,6 @@
-/* $Id$
- *
+/*
  * Copyright (C) 2003-2008 Sippy Software, Inc., http://www.sippysoft.com
+ * Copyright (C) 2014-2015 Sipwise GmbH, http://www.sipwise.com
  *
  * This file is part of Kamailio, a free SIP server.
  *
@@ -17,152 +17,6 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- *
- * History:
- * ---------
- * 2003-10-09	nat_uac_test introduced (jiri)
- *
- * 2003-11-06   nat_uac_test permitted from onreply_route (jiri)
- *
- * 2003-12-01   unforce_rtp_proxy introduced (sobomax)
- *
- * 2004-01-07	RTP proxy support updated to support new version of the
- *		RTP proxy (20040107).
- *
- *		force_rtp_proxy() now inserts a special flag
- *		into the SDP body to indicate that this session already
- *		proxied and ignores sessions with such flag.
- *
- *		Added run-time check for version of command protocol
- *		supported by the RTP proxy.
- *
- * 2004-01-16   Integrated slightly modified patch from Tristan Colgate,
- *		force_rtp_proxy function with IP as a parameter (janakj)
- *
- * 2004-01-28	nat_uac_test extended to allow testing SDP body (sobomax)
- *
- *		nat_uac_test extended to allow testing top Via (sobomax)
- *
- * 2004-02-21	force_rtp_proxy now accepts option argument, which
- *		consists of string of chars, each of them turns "on"
- *		some feature, currently supported ones are:
- *
- *		 `a' - flags that UA from which message is received
- *		       doesn't support symmetric RTP;
- *		 `l' - force "lookup", that is, only rewrite SDP when
- *		       corresponding session is already exists in the
- *		       RTP proxy. Only makes sense for SIP requests,
- *		       replies are always processed in "lookup" mode;
- *		 `i' - flags that message is received from UA in the
- *		       LAN. Only makes sense when RTP proxy is running
- *		       in the bridge mode.
- *
- *		force_rtp_proxy can now be invoked without any arguments,
- *		as previously, with one argument - in this case argument
- *		is treated as option string and with two arguments, in
- *		which case 1st argument is option string and the 2nd
- *		one is IP address which have to be inserted into
- *		SDP (IP address on which RTP proxy listens).
- *
- * 2004-03-12	Added support for IPv6 addresses in SDPs. Particularly,
- *		force_rtp_proxy now can work with IPv6-aware RTP proxy,
- *		replacing IPv4 address in SDP with IPv6 one and vice versa.
- *		This allows creating full-fledged IPv4<->IPv6 gateway.
- *		See 4to6.cfg file for example.
- *
- *		Two new options added into force_rtp_proxy:
- *
- *		 `f' - instructs nathelper to ignore marks inserted
- *		       by another nathelper in transit to indicate
- *		       that the session is already goes through another
- *		       proxy. Allows creating chain of proxies.
- *		 `r' - flags that IP address in SDP should be trusted.
- *		       Without this flag, nathelper ignores address in the
- *		       SDP and uses source address of the SIP message
- *		       as media address which is passed to the RTP proxy.
- *
- *		Protocol between nathelper and RTP proxy in bridge
- *		mode has been slightly changed. Now RTP proxy expects SER
- *		to provide 2 flags when creating or updating session
- *		to indicate direction of this session. Each of those
- *		flags can be either `e' or `i'. For example `ei' means
- *		that we received INVITE from UA on the "external" network
- *		network and will send it to the UA on "internal" one.
- *		Also possible `ie' (internal->external), `ii'
- *		(internal->internal) and `ee' (external->external). See
- *		example file alg.cfg for details.
- *
- * 2004-03-15	If the rtp proxy test failed (wrong version or not started)
- *		retry test from time to time, when some *rtpproxy* function
- *		is invoked. Minimum interval between retries can be
- *		configured via rtpproxy_disable_tout module parameter (default
- *		is 60 seconds). Setting it to -1 will disable periodic
- *		rechecks completely, setting it to 0 will force checks
- *		for each *rtpproxy* function call. (andrei)
- *
- * 2004-03-22	Fix assignment of rtpproxy_retr and rtpproxy_tout module
- *		parameters.
- *
- * 2004-03-22	Fix get_body position (should be called before get_callid)
- * 				(andrei)
- *
- * 2004-03-24	Fix newport for null ip address case (e.g onhold re-INVITE)
- * 				(andrei)
- *
- * 2004-09-30	added received port != via port test (andrei)
- *
- * 2004-10-10   force_socket option introduced (jiri)
- *
- * 2005-02-24	Added support for using more than one rtp proxy, in which
- *		case traffic will be distributed evenly among them. In addition,
- *		each such proxy can be assigned a weight, which will specify
- *		which share of the traffic should be placed to this particular
- *		proxy.
- *
- *		Introduce failover mechanism, so that if SER detects that one
- *		of many proxies is no longer available it temporarily decreases
- *		its weight to 0, so that no traffic will be assigned to it.
- *		Such "disabled" proxies are periodically checked to see if they
- *		are back to normal in which case respective weight is restored
- *		resulting in traffic being sent to that proxy again.
- *
- *		Those features can be enabled by specifying more than one "URI"
- *		in the rtpproxy_sock parameter, optionally followed by the weight,
- *		which if absent is assumed to be 1, for example:
- *
- *		rtpproxy_sock="unix:/foo/bar=4 udp:1.2.3.4:3456=3 udp:5.6.7.8:5432=1"
- *
- * 2005-02-25	Force for pinging the socket returned by USRLOC (bogdan)
- *
- * 2005-03-22	support for multiple media streams added (netch)
- *
- * 2005-07-11  SIP ping support added (bogdan)
- *
- * 2005-07-14  SDP origin (o=) IP may be also changed (bogdan)
- *
- * 2006-03-08  fix_nated_sdp() may take one more param to force a specific IP;
- *             force_rtp_proxy() accepts a new flag 's' to swap creation/
- *              confirmation between requests/replies;
- *             add_rcv_param() may take as parameter a flag telling if the
- *              parameter should go to the contact URI or contact header;
- *             (bogdan)
- * 2006-03-28 Support for changing session-level SDP connection (c=) IP when
- *            media-description also includes connection information (bayan)
- * 2007-04-13 Support multiple sets of rtpproxies and set selection added
- *            (ancuta)
- * 2007-04-26 Added some MI commands:
- *             nh_enable_ping used to enable or disable natping
- *             nh_enable_rtpp used to enable or disable a specific rtp proxy
- *             nh_show_rtpp   used to display information for all rtp proxies
- *             (ancuta)
- * 2007-05-09 New function start_recording() allowing to start recording RTP
- *             session in the RTP proxy (Carsten Bock - ported from SER)
- * 2007-09-11 Separate timer process and support for multiple timer processes
- *             (bogdan)
- * 2008-12-12 Support for RTCP attribute in the SDP
- *              (Min Wang/BASIS AudioNet - ported from SER)
- * 2010-08-05 Core SDP parser integrated into nathelper (osas)
- * 2010-10-08 Removal of deprecated force_rtp_proxy and swap flag (osas)
  */
 
 #include <sys/types.h>
@@ -189,6 +43,9 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <ifaddrs.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
 
 #include "../../flags.h"
 #include "../../sr_module.h"
@@ -241,7 +98,7 @@ MODULE_VERSION
 
 
 #define DEFAULT_RTPP_SET_ID		0
-
+#define MAX_RTPP_TRIED_NODES    50
 #define MI_SET_NATPING_STATE		"nh_enable_ping"
 #define MI_DEFAULT_NATPING_STATE	1
 
@@ -255,6 +112,8 @@ MODULE_VERSION
 #define MI_RTP_PROXY_NOT_FOUND_LEN	(sizeof(MI_RTP_PROXY_NOT_FOUND)-1)
 #define MI_PING_DISABLED			"NATping disabled from script"
 #define MI_PING_DISABLED_LEN		(sizeof(MI_PING_DISABLED)-1)
+#define MI_DISABLED_PERMANENT        "1 (permanent)"
+#define MI_DISABLED_PERMANENT_LEN    (sizeof(MI_DISABLED_PERMANENT)-1)
 #define MI_SET						"set"
 #define MI_SET_LEN					(sizeof(MI_SET)-1)
 #define MI_INDEX					"index"
@@ -316,6 +175,10 @@ static int mod_init(void);
 static int child_init(int);
 static void mod_destroy(void);
 
+static int get_ip_type(char *str_addr);
+static int get_ip_scope(char *str_addr); // useful for link-local ipv6
+static int bind_force_send_ip(int sock_idx);
+
 /* Pseudo-Variables */
 static int pv_get_rtpstat_f(struct sip_msg *, pv_param_t *, pv_value_t *);
 
@@ -328,7 +191,8 @@ static struct mi_root* mi_show_rtpproxies(struct mi_root* cmd_tree,
 
 static int rtpengine_disable_tout = 60;
 static int rtpengine_retr = 5;
-static int rtpengine_tout = 1;
+static int rtpengine_tout_ms = 1000;
+static int queried_nodes_limit = MAX_RTPP_TRIED_NODES;
 static pid_t mypid;
 static unsigned int myseqn = 0;
 static str extra_id_pv_param = {NULL, 0};
@@ -347,6 +211,9 @@ static struct rtpp_set * default_rtpp_set=0;
 
 static str body_intermediate;
 
+static str rtp_inst_pv_param = {NULL, 0};
+static pv_spec_t *rtp_inst_pvar = NULL;
+
 /* array with the sockets used by rtpporxy (per process)*/
 static unsigned int rtpp_no = 0;
 static int *rtpp_socks = 0;
@@ -354,6 +221,13 @@ static int *rtpp_socks = 0;
 static int     setid_avp_type;
 static int_str setid_avp;
 
+static str            write_sdp_pvar_str = {NULL, 0};
+static pv_spec_t*     write_sdp_pvar = NULL;
+
+
+char* force_send_ip_str="";
+int force_send_ip_af = AF_UNSPEC;
+
 typedef struct rtpp_set_link {
 	struct rtpp_set *rset;
 	pv_spec_t *rpv;
@@ -415,12 +289,16 @@ static param_export_t params[] = {
 	                         (void*)rtpengine_set_store          },
 	{"rtpengine_disable_tout",INT_PARAM, &rtpengine_disable_tout },
 	{"rtpengine_retr",        INT_PARAM, &rtpengine_retr         },
-	{"rtpengine_tout",        INT_PARAM, &rtpengine_tout         },
+	{"rtpengine_tout_ms",     INT_PARAM, &rtpengine_tout_ms      },
+	{"queried_nodes_limit",   INT_PARAM, &queried_nodes_limit    },
 	{"db_url",                PARAM_STR, &rtpp_db_url },
 	{"table_name",            PARAM_STR, &rtpp_table_name },
 	{"url_col",               PARAM_STR, &rtpp_url_col },
 	{"extra_id_pv",           PARAM_STR, &extra_id_pv_param },
 	{"setid_avp",             PARAM_STRING, &setid_avp_param },
+	{"force_send_interface",  PARAM_STRING, &force_send_ip_str	},
+	{"rtp_inst_pvar",         PARAM_STR, &rtp_inst_pv_param },
+	{"write_sdp_pv",          PARAM_STR, &write_sdp_pvar_str          },
 	{0, 0, 0}
 };
 
@@ -447,6 +325,140 @@ struct module_exports exports = {
 };
 
 
+static int get_ip_type(char *str_addr)
+{
+	struct addrinfo hint, *info = NULL;
+	int ret;
+
+	memset(&hint, '\0', sizeof hint);
+	hint.ai_family = PF_UNSPEC;
+	hint.ai_flags = AI_NUMERICHOST;
+
+	ret = getaddrinfo(str_addr, NULL, &hint, &info);
+	if (ret) {
+		/* Invalid ip addinfos */
+		return -1;
+	}
+
+	if(info->ai_family == AF_INET) {
+		LM_DBG("%s is an ipv4 addinfos\n", str_addr);
+	} else if (info->ai_family == AF_INET6) {
+		LM_DBG("%s is an ipv6 addinfos\n", str_addr);
+	} else {
+		LM_DBG("%s is an unknown addinfos format AF=%d\n",str_addr, info->ai_family);
+		return -1;
+	}
+
+	ret = info->ai_family;
+
+	freeaddrinfo(info);
+
+	return ret;
+}
+
+
+static int get_ip_scope(char *str_addr)
+{
+	struct ifaddrs *ifaddr, *ifa;
+	struct sockaddr_in6 *in6;
+	char str_if_ip[NI_MAXHOST];
+	int ret = -1;
+
+	if (getifaddrs(&ifaddr) == -1) {
+		LM_ERR("getifaddrs() failed: %s\n", gai_strerror(ret));
+		return -1;
+	}
+
+	for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
+		in6 = (struct sockaddr_in6 *)ifa->ifa_addr;
+
+		if (ifa->ifa_addr == NULL)
+			continue;
+
+		if (ifa->ifa_addr->sa_family != AF_INET6)
+			continue;
+
+		ret = getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in6),
+		str_if_ip, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
+		if (ret != 0) {
+			LM_ERR("getnameinfo() failed: %s\n", gai_strerror(ret));
+			return -1;
+		}
+
+		if (strstr(str_if_ip, str_addr)) {
+			LM_INFO("dev: %-8s address: <%s> scope %d\n",
+			ifa->ifa_name, str_if_ip, in6->sin6_scope_id);
+			ret = in6->sin6_scope_id;
+			break;
+		}
+	}
+
+	freeifaddrs(ifaddr);
+
+	return ret;
+}
+
+
+static int bind_force_send_ip(int sock_idx)
+{
+	struct sockaddr_in tmp, ip4addr;
+	struct sockaddr_in6 tmp6, ip6addr;
+	char str_addr[INET_ADDRSTRLEN];
+	char str_addr6[INET6_ADDRSTRLEN];
+	socklen_t sock_len = sizeof(struct sockaddr);
+	int ret, scope;
+
+	switch (force_send_ip_af) {
+		case AF_INET:
+			memset(&ip4addr, 0, sizeof(ip4addr));
+			ip4addr.sin_family = AF_INET;
+			ip4addr.sin_port = htons(0);
+			inet_pton(AF_INET, force_send_ip_str, &ip4addr.sin_addr);
+
+			if (bind(rtpp_socks[sock_idx], (struct sockaddr*)&ip4addr, sizeof(ip4addr)) < 0) {
+				LM_ERR("can't bind socket to required ipv4 interface\n");
+				return -1;
+			}
+
+			memset(&tmp, 0, sizeof(tmp));
+			getsockname(rtpp_socks[sock_idx], (struct sockaddr *) &tmp, &sock_len);
+			inet_ntop(AF_INET, &tmp.sin_addr, str_addr, INET_ADDRSTRLEN);
+			LM_INFO("Binding on %s:%d\n", str_addr, ntohs(tmp.sin_port));
+
+			break;
+
+		case AF_INET6:
+			if ((scope = get_ip_scope(force_send_ip_str)) < 0) {
+				LM_ERR("can't get the ipv6 interface scope\n");
+				return -1;
+			}
+			memset(&ip6addr, 0, sizeof(ip6addr));
+			ip6addr.sin6_family = AF_INET6;
+			ip6addr.sin6_port = htons(0);
+			ip6addr.sin6_scope_id = scope;
+			inet_pton(AF_INET6, force_send_ip_str, &ip6addr.sin6_addr);
+
+			if ((ret = bind(rtpp_socks[sock_idx], (struct sockaddr*)&ip6addr, sizeof(ip6addr))) < 0) {
+				LM_ERR("can't bind socket to required ipv6 interface\n");
+				LM_ERR("ret=%d errno=%d\n", ret, errno);
+				return -1;
+			}
+
+			memset(&tmp6, 0, sizeof(tmp6));
+			getsockname(rtpp_socks[sock_idx], (struct sockaddr *) &tmp6, &sock_len);
+			inet_ntop(AF_INET6, &tmp6.sin6_addr, str_addr6, INET6_ADDRSTRLEN);
+			LM_INFO("Binding on ipv6 %s:%d\n", str_addr6, ntohs(tmp6.sin6_port));
+
+			break;
+
+		default:
+			LM_DBG("force_send_ip_str not specified in .cfg file!\n");
+			break;
+	}
+
+	return 0;
+}
+
 
 static inline int str_eq(const str *p, const char *q) {
 	int l = strlen(q);
@@ -629,7 +641,6 @@ int add_rtpengine_socks(struct rtpp_set * rtpp_list, char * rtpproxy)
 		pnode->rn_url.s[p2 - p1] 	= 0;
 		pnode->rn_url.len 			= p2-p1;
 
-		LM_DBG("url is %s, len is %i\n", pnode->rn_url.s, pnode->rn_url.len);
 		/* Leave only address in rn_address */
 		pnode->rn_address = pnode->rn_url.s;
 		if (strncasecmp(pnode->rn_address, "udp:", 4) == 0) {
@@ -894,8 +905,19 @@ static struct mi_root* mi_show_rtpproxies(struct mi_root* cmd_tree,
 
 			add_rtpp_node_int_info(crt_node, MI_INDEX, MI_INDEX_LEN,
 				crt_rtpp->idx, child, len,string,error);
-			add_rtpp_node_int_info(crt_node, MI_DISABLED, MI_DISABLED_LEN,
-				crt_rtpp->rn_disabled, child, len,string,error);
+			
+			if (( 1 == crt_rtpp->rn_disabled ) && ( crt_rtpp->rn_recheck_ticks == MI_MAX_RECHECK_TICKS)) {
+				if( !(child = add_mi_node_child(crt_node, MI_DUP_VALUE, MI_DISABLED, MI_DISABLED_LEN,
+								MI_DISABLED_PERMANENT, MI_DISABLED_PERMANENT_LEN))) {
+					LM_ERR("cannot add disabled (permanent) message\n");
+					goto error;
+				}
+			}
+			else {
+				add_rtpp_node_int_info(crt_node, MI_DISABLED, MI_DISABLED_LEN,
+					crt_rtpp->rn_disabled, child, len,string,error);
+			}
+
 			add_rtpp_node_int_info(crt_node, MI_WEIGHT, MI_WEIGHT_LEN,
 				crt_rtpp->rn_weight,  child, len, string,error);
 			add_rtpp_node_int_info(crt_node, MI_RECHECK_TICKS,MI_RECHECK_T_LEN,
@@ -954,6 +976,18 @@ mod_init(void)
 		}
 	}
 
+	if (rtp_inst_pv_param.s) {
+		rtp_inst_pv_param.len = strlen(rtp_inst_pv_param.s);
+		rtp_inst_pvar = pv_cache_get(&rtp_inst_pv_param);
+		if ((rtp_inst_pvar == NULL) ||
+			((rtp_inst_pvar->type != PVT_AVP) &&
+	     	 (rtp_inst_pvar->type != PVT_XAVP) &&
+			 (rtp_inst_pvar->type != PVT_SCRIPTVAR))) {
+		LM_ERR("Invalid pvar name <%.*s>\n", rtp_inst_pv_param.len, rtp_inst_pv_param.s);
+		return -1;
+		}
+	}
+
 	if (extra_id_pv_param.s && *extra_id_pv_param.s) {
 		extra_id_pv_param.len = strlen(extra_id_pv_param.s);
 		if(pv_parse_format(&extra_id_pv_param, &extra_id_pv) < 0) {
@@ -980,9 +1014,24 @@ mod_init(void)
 	    setid_avp_type = avp_flags;
 	}
 
+	if (write_sdp_pvar_str.len > 0) {
+		write_sdp_pvar = pv_cache_get(&write_sdp_pvar_str);
+		if (write_sdp_pvar == NULL
+		    || (write_sdp_pvar->type != PVT_AVP &&  write_sdp_pvar->type != PVT_SCRIPTVAR) ) {
+			LM_ERR("write_sdp_pv: not a valid AVP or VAR definition <%.*s>\n",
+		       write_sdp_pvar_str.len, write_sdp_pvar_str.s);
+			return -1;
+		}
+	}
+
 	if (rtpp_strings)
 		pkg_free(rtpp_strings);
 
+	if ((queried_nodes_limit < 1) || (queried_nodes_limit > MAX_RTPP_TRIED_NODES)) {
+		LM_ERR("queried_nodes_limit must be a number in the range 1..50 \n");
+		return -1;
+	}
+
 	if (load_tm_api( &tmb ) < 0)
 	{
 		LM_DBG("could not load the TM-functions - answer-offer model"
@@ -990,6 +1039,14 @@ mod_init(void)
 		memset(&tmb, 0, sizeof(struct tm_binds));
 	}
 
+	/* Determine IP addr type (IPv4 or IPv6 allowed) */
+	force_send_ip_af = get_ip_type(force_send_ip_str);
+	if (force_send_ip_af != AF_INET && force_send_ip_af != AF_INET6 &&
+			strlen(force_send_ip_str) > 0) {
+		LM_ERR("%s is an unknown address\n", force_send_ip_str);
+		return -1;
+	}
+
 	return 0;
 }
 
@@ -1058,19 +1115,28 @@ child_init(int rank)
 
 			rtpp_socks[pnode->idx] = socket((pnode->rn_umode == 6)
 			    ? AF_INET6 : AF_INET, SOCK_DGRAM, 0);
-			if ( rtpp_socks[pnode->idx] == -1) {
+			if (rtpp_socks[pnode->idx] == -1) {
 				LM_ERR("can't create socket\n");
 				freeaddrinfo(res);
 				return -1;
 			}
 
-			if (connect( rtpp_socks[pnode->idx], res->ai_addr, res->ai_addrlen) == -1) {
+			if (bind_force_send_ip(pnode->idx) == -1) {
+				LM_ERR("can't bind socket\n");
+				close(rtpp_socks[pnode->idx]);
+				rtpp_socks[pnode->idx] = -1;
+				freeaddrinfo(res);
+				return -1;
+			}
+
+			if (connect(rtpp_socks[pnode->idx], res->ai_addr, res->ai_addrlen) == -1) {
 				LM_ERR("can't connect to a RTP proxy\n");
-				close( rtpp_socks[pnode->idx] );
+				close(rtpp_socks[pnode->idx]);
 				rtpp_socks[pnode->idx] = -1;
 				freeaddrinfo(res);
 				return -1;
 			}
+
 			freeaddrinfo(res);
 rptest:
 			pnode->rn_disabled = rtpp_test(pnode, 0, 1);
@@ -1321,7 +1387,7 @@ static bencode_item_t *rtpp_function_call(bencode_buffer_t *bencbuf, struct sip_
 	struct ng_flags_parse ng_flags;
 	bencode_item_t *item, *resp;
 	str callid, from_tag, to_tag, body, viabranch, error;
-	int ret;
+	int ret, queried_nodes;
 	struct rtpp_node *node;
 	char *cp;
 
@@ -1436,17 +1502,22 @@ static bencode_item_t *rtpp_function_call(bencode_buffer_t *bencbuf, struct sip_
 	if(msg->id != current_msg_id)
 		active_rtpp_set = default_rtpp_set;
 
+	queried_nodes = 0;
 	do {
+		if (++queried_nodes > queried_nodes_limit) {
+			LM_ERR("queried nodes limit reached\n");
+			goto error;
+		}
 		node = select_rtpp_node(callid, 1);
 		if (!node) {
 			LM_ERR("no available proxies\n");
 			goto error;
 		}
-
 		cp = send_rtpp_command(node, ng_flags.dict, &ret);
 	} while (cp == NULL);
 	LM_DBG("proxy reply: %.*s\n", ret, cp);
 
+	set_rtp_inst_pvar(msg, &node->rn_url);
 	/*** process reply ***/
 
 	resp = bencode_decode_expect(bencbuf, cp, ret, BENCODE_DICTIONARY);
@@ -1630,7 +1701,7 @@ send_rtpp_command(struct rtpp_node *node, bencode_item_t *dict, int *outlen)
 				LM_ERR("can't send command to a RTP proxy\n");
 				goto badproxy;
 			}
-			while ((poll(fds, 1, rtpengine_tout * 1000) == 1) &&
+			while ((poll(fds, 1, rtpengine_tout_ms) == 1) &&
 			    (fds[0].revents & POLLIN) != 0) {
 				do {
 					len = recv(rtpp_socks[node->idx], buf, sizeof(buf)-1, 0);
@@ -2062,6 +2133,7 @@ rtpengine_offer_answer(struct sip_msg *msg, const char *flags, int op, int more)
 	bencode_item_t *dict;
 	str body, newbody;
 	struct lump *anchor;
+	pv_value_t pv_val;
 
 	dict = rtpp_function_call_ok(&bencbuf, msg, op, flags, &body);
 	if (!dict)
@@ -2078,14 +2150,28 @@ rtpengine_offer_answer(struct sip_msg *msg, const char *flags, int op, int more)
 	if (more)
 		body_intermediate = newbody;
 	else {
-		anchor = del_lump(msg, body.s - msg->buf, body.len, 0);
-		if (!anchor) {
-			LM_ERR("del_lump failed\n");
-			goto error_free;
-		}
-		if (!insert_new_lump_after(anchor, newbody.s, newbody.len, 0)) {
-			LM_ERR("insert_new_lump_after failed\n");
-			goto error_free;
+		if (write_sdp_pvar!= NULL) {
+			pv_val.rs = newbody;
+			pv_val.flags = PV_VAL_STR;
+
+			if (write_sdp_pvar->setf(msg,&write_sdp_pvar->pvp, (int)EQ_T, &pv_val) < 0)
+			{
+				LM_ERR("error setting pvar <%.*s>\n", write_sdp_pvar_str.len, write_sdp_pvar_str.s);
+				goto error_free;
+			}
+
+			pkg_free(newbody.s);
+
+		} else {
+			anchor = del_lump(msg, body.s - msg->buf, body.len, 0);
+			if (!anchor) {
+				LM_ERR("del_lump failed\n");
+				goto error_free;
+			}
+			if (!insert_new_lump_after(anchor, newbody.s, newbody.len, 0)) {
+				LM_ERR("insert_new_lump_after failed\n");
+				goto error_free;
+			}
 		}
 	}
 
@@ -2110,41 +2196,40 @@ start_recording_f(struct sip_msg* msg, char *foo, char *bar)
 	return rtpengine_rtpp_set_wrap(msg, rtpengine_start_recording_wrap, NULL, 1);
 }
 
-/*
- * Returns the current RTP-Statistics from the RTP-Proxy
- */
-static int
-pv_get_rtpstat_f(struct sip_msg *msg, pv_param_t *param,
-		  pv_value_t *res)
-{
+static int rtpengine_rtpstat_wrap(struct sip_msg *msg, void *d, int more) {
+	void **parms;
+	pv_param_t *param;
+	pv_value_t *res;
 	bencode_buffer_t bencbuf;
-	bencode_item_t *dict, *tot, *in, *out;
+	bencode_item_t *dict, *tot, *rtp, *rtcp;
 	static char buf[256];
 	str ret;
 
+	parms = d;
+	param = parms[0];
+	res = parms[1];
+
 	dict = rtpp_function_call_ok(&bencbuf, msg, OP_QUERY, NULL, NULL);
 	if (!dict)
 		return -1;
 
 	tot = bencode_dictionary_get_expect(dict, "totals", BENCODE_DICTIONARY);
-	in = bencode_dictionary_get_expect(tot, "input", BENCODE_DICTIONARY);
-	in = bencode_dictionary_get_expect(in, "rtp", BENCODE_DICTIONARY);
-	out = bencode_dictionary_get_expect(tot, "output", BENCODE_DICTIONARY);
-	out = bencode_dictionary_get_expect(out, "rtp", BENCODE_DICTIONARY);
+	rtp = bencode_dictionary_get_expect(tot, "RTP", BENCODE_DICTIONARY);
+	rtcp = bencode_dictionary_get_expect(tot, "RTCP", BENCODE_DICTIONARY);
 
-	if (!in || !out)
+	if (!rtp || !rtcp)
 		goto error;
 
 	ret.s = buf;
 	ret.len = snprintf(buf, sizeof(buf),
-			"Input: %lli bytes, %lli packets, %lli errors; "
-			"Output: %lli bytes, %lli packets, %lli errors",
-			bencode_dictionary_get_integer(in, "bytes", -1),
-			bencode_dictionary_get_integer(in, "packets", -1),
-			bencode_dictionary_get_integer(in, "errors", -1),
-			bencode_dictionary_get_integer(out, "bytes", -1),
-			bencode_dictionary_get_integer(out, "packets", -1),
-			bencode_dictionary_get_integer(out, "errors", -1));
+			"RTP: %lli bytes, %lli packets, %lli errors; "
+			"RTCP: %lli bytes, %lli packets, %lli errors",
+			bencode_dictionary_get_integer(rtp, "bytes", -1),
+			bencode_dictionary_get_integer(rtp, "packets", -1),
+			bencode_dictionary_get_integer(rtp, "errors", -1),
+			bencode_dictionary_get_integer(rtcp, "bytes", -1),
+			bencode_dictionary_get_integer(rtcp, "packets", -1),
+			bencode_dictionary_get_integer(rtcp, "errors", -1));
 
 	bencode_buffer_free(&bencbuf);
 	return pv_get_strval(msg, param, res, &ret);
@@ -2154,3 +2239,35 @@ error:
 	return -1;
 }
 
+/*
+ * Returns the current RTP-Statistics from the RTP-Proxy
+ */
+static int
+pv_get_rtpstat_f(struct sip_msg *msg, pv_param_t *param,
+		  pv_value_t *res)
+{
+	void *parms[2];
+
+	parms[0] = param;
+	parms[1] = res;
+
+	return rtpengine_rtpp_set_wrap(msg, rtpengine_rtpstat_wrap, parms, 1);
+}
+
+int set_rtp_inst_pvar(struct sip_msg *msg, const str * const uri) {
+	pv_value_t val;
+
+	if (rtp_inst_pvar == NULL)
+		return 0;
+
+	memset(&val, 0, sizeof(pv_value_t));
+	val.flags = PV_VAL_STR;
+	val.rs = *uri;
+
+	if (rtp_inst_pvar->setf(msg, &rtp_inst_pvar->pvp, (int)EQ_T, &val) < 0)
+	{
+		LM_ERR("Failed to add RTP Engine URI to pvar\n");
+		return -1;
+	}
+	return 0;
+}
diff --git a/modules/rtpengine/rtpengine.h b/modules/rtpengine/rtpengine.h
index 5abd1f8..af61701 100644
--- a/modules/rtpengine/rtpengine.h
+++ b/modules/rtpengine/rtpengine.h
@@ -1,6 +1,6 @@
-/* $Id: nathelper.c 1808 2007-03-10 17:36:19Z bogdan_iancu $
- *
+/*
  * Copyright (C) 2003 Porta Software Ltd
+ * Copyright (C) 2014-2015 Sipwise GmbH, http://www.sipwise.com
  *
  * This file is part of Kamailio, a free SIP server.
  *
@@ -17,10 +17,6 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- *
- * History:
- * ---------
- * 2007-04-13   splitted from nathelper.c (ancuta)
 */
 
 
@@ -65,6 +61,8 @@ struct rtpp_set_head{
 struct rtpp_set *get_rtpp_set(int set_id);
 int add_rtpengine_socks(struct rtpp_set * rtpp_list, char * rtpproxy);
 
+int set_rtp_inst_pvar(struct sip_msg *msg, const str * const uri);
+
 int init_rtpproxy_db(void);
 
 extern str rtpp_db_url;
diff --git a/modules/rtpengine/rtpengine_db.c b/modules/rtpengine/rtpengine_db.c
index bf5558e..82c64bb 100644
--- a/modules/rtpengine/rtpengine_db.c
+++ b/modules/rtpengine/rtpengine_db.c
@@ -1,7 +1,6 @@
 /*
- * rtpproxy module
- *
  * Copyright (c) 2013 Crocodile RCS Ltd
+ * Copyright (C) 2014-2015 Sipwise GmbH, http://www.sipwise.com
  *
  * This file is part of Kamailio, a free SIP server.
  *
@@ -18,12 +17,12 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- *
  */
 
 #include "../../lib/srdb1/db.h"
 #include "../../lib/srdb1/db_res.h"
 
+#include "../../parser/msg_parser.h"
 #include "rtpengine.h"
 
 #define RTPP_TABLE_VERSION 1
diff --git a/modules/rtpengine/rtpengine_funcs.c b/modules/rtpengine/rtpengine_funcs.c
index 565ebfb..78159f3 100644
--- a/modules/rtpengine/rtpengine_funcs.c
+++ b/modules/rtpengine/rtpengine_funcs.c
@@ -1,7 +1,6 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
+ * Copyright (C) 2014-2015 Sipwise GmbH, http://www.sipwise.com
  *
  * This file is part of Kamailio, a free SIP server.
  *
@@ -18,13 +17,6 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- *
- * History:
- * --------
- *  2003-11-06  body len is computed using the message len (it's
- *               not taken any more from the msg. content-length) (andrei)
- *  2008-08-30  body len is taken from Conent-length header as it is more
- *               reliable (UDP packages may contain garbage at the end)(bogdan)
  */
 
 #include <stdio.h>
diff --git a/modules/rtpengine/rtpengine_funcs.h b/modules/rtpengine/rtpengine_funcs.h
index 04e2bf8..79ae121 100644
--- a/modules/rtpengine/rtpengine_funcs.h
+++ b/modules/rtpengine/rtpengine_funcs.h
@@ -1,7 +1,6 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
+ * Copyright (C) 2014-2015 Sipwise GmbH, http://www.sipwise.com
  *
  * This file is part of Kamailio, a free SIP server.
  *
diff --git a/modules/rtpproxy/Makefile b/modules/rtpproxy/Makefile
index e0d53f4..7b5dcc7 100644
--- a/modules/rtpproxy/Makefile
+++ b/modules/rtpproxy/Makefile
@@ -1,6 +1,5 @@
-# $Id$
 #
-# print example module makefile
+# rtpproxy example module makefile
 #
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
diff --git a/modules/rtpproxy/test/rtpproxy.patch b/modules/rtpproxy/test/rtpproxy.patch
new file mode 100644
index 0000000..e427c72
--- /dev/null
+++ b/modules/rtpproxy/test/rtpproxy.patch
@@ -0,0 +1,374 @@
+diff --git a/Makefile.am b/Makefile.am
+index 258de5e..a61bc57 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -5,7 +5,7 @@ rtpproxy_SOURCES=main.c rtp.h rtp_server.c rtp_server.h \
+   rtpp_command.c rtpp_command.h rtpp_log.c rtpp_network.h rtpp_network.c \
+   rtpp_syslog_async.c rtpp_syslog_async.h rtpp_notify.c rtpp_notify.h \
+   rtpp_command_async.h rtpp_command_async.c
+-rtpproxy_LDADD=-lm -lpthread
++rtpproxy_LDADD=-lm -lpthread @LIBS_XMLRPC@
+ dist_man_MANS=rtpproxy.8
+ makeann_SOURCES=makeann.c rtp.h g711.h
+ makeann_LDADD=@LIBS_G729@ @LIBS_GSM@
+diff --git a/Makefile.in b/Makefile.in
+index 47c14fd..cdb5e43 100644
+--- a/Makefile.in
++++ b/Makefile.in
+@@ -217,7 +217,7 @@ rtpproxy_SOURCES = main.c rtp.h rtp_server.c rtp_server.h \
+   rtpp_syslog_async.c rtpp_syslog_async.h rtpp_notify.c rtpp_notify.h \
+   rtpp_command_async.h rtpp_command_async.c
+ 
+-rtpproxy_LDADD = -lm -lpthread
++rtpproxy_LDADD = -lm -lpthread @LIBS_XMLRPC@
+ dist_man_MANS = rtpproxy.8
+ makeann_SOURCES = makeann.c rtp.h g711.h
+ makeann_LDADD = @LIBS_G729@ @LIBS_GSM@
+diff --git a/aclocal.m4 b/aclocal.m4
+index b36bc80..0970c41 100644
+--- a/aclocal.m4
++++ b/aclocal.m4
+@@ -13,8 +13,8 @@
+ 
+ m4_ifndef([AC_AUTOCONF_VERSION],
+   [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+-m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.68],,
+-[m4_warning([this file was generated for autoconf 2.68.
++m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.67],,
++[m4_warning([this file was generated for autoconf 2.67.
+ You have another version of autoconf.  It may work, but is not guaranteed to.
+ If you have problems, you may need to regenerate the build system entirely.
+ To do so, use the procedure documented by the package, typically `autoreconf'.])])
+diff --git a/config.h.in b/config.h.in
+index cd0c23a..87491e3 100644
+--- a/config.h.in
++++ b/config.h.in
+@@ -14,6 +14,9 @@
+ /* Define if you have libgsm library installed */
+ #undef ENABLE_GSM
+ 
++/* Define if you have xmlrpc library installed */
++#undef ENABLE_XMLRPC
++
+ /* Define to 1 if you have `alloca', as a function or macro. */
+ #undef HAVE_ALLOCA
+ 
+diff --git a/configure.ac b/configure.ac
+index 54c1a60..1c88b99 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -53,6 +53,17 @@ then
+    AC_DEFINE([ENABLE_G729], 1, [Define if you have libg729 library installed])
+   )
+ fi
++
++# XML-RPC-Libs:
++AC_CHECK_HEADERS(xmlrpc_client.h xmlrpc.h, found_xmlrpc=yes)
++if test "$found_xmlrpc" = yes
++then
++  AC_CHECK_LIB(curl, curl_version,
++   LIBS_XMLRPC="-lcurl -lxmlrpc_client -lxmlrpc -lxmlrpc_util -lxmlrpc_xmlparse -lxmlrpc_xmltok"
++   AC_DEFINE([ENABLE_XMLRPC], 1, [Define if you have XML-RPC-Client library installed])
++  )
++fi
++
+ ##if test -z "$G729_SUPPORT"
+ ##then
+ ##  echo "*************************************************************************** $ECHO_C" 1>&6
+@@ -94,4 +105,5 @@ AC_CONFIG_FILES([Makefile])
+ AC_SUBST(AM_CFLAGS)
+ AC_SUBST(LIBS_GSM)
+ AC_SUBST(LIBS_G729)
++AC_SUBST(LIBS_XMLRPC)
+ AC_OUTPUT
+diff --git a/rtpp_command.c b/rtpp_command.c
+index c5734ae..d6072de 100644
+--- a/rtpp_command.c
++++ b/rtpp_command.c
+@@ -69,6 +69,9 @@ struct proto_cap proto_caps[] = {
+     { "20081102", "Support for setting codecs in the update/lookup command" },
+     { "20081224", "Support for session timeout notifications" },
+     { "20090810", "Support for automatic bridging" },
++#ifdef ENABLE_XMLRPC
++    { "20100819", "Support for timeout notifications using XML-RPC towards Kamailio/sip-router.org" },
++#endif
+     { NULL, NULL }
+ };
+ 
+@@ -269,6 +272,7 @@ handle_command(struct cfg *cf, int controlfd, double dtime)
+     char *socket_name_u, *notify_tag;
+     struct sockaddr *local_addr;
+     char c;
++    struct rtpp_timeout_handler * my_timeout_h;
+ 
+     requested_nsamples = -1;
+     ia[0] = ia[1] = NULL;
+@@ -468,7 +472,7 @@ handle_command(struct cfg *cf, int controlfd, double dtime)
+     }
+     call_id = argv[1];
+     if (op == UPDATE || op == LOOKUP || op == PLAY) {
+-	max_argc = (op == UPDATE ? 8 : 6);
++	max_argc = (op == PLAY ? 6 : 8);
+ 	if (argc < 5 || argc > max_argc) {
+ 	    rtpp_log_write(RTPP_LOG_ERR, cf->stable.glog, "command syntax error");
+ 	    reply_error(&cf->stable, controlfd, &raddr, rlen, cookie, 4);
+@@ -478,7 +482,7 @@ handle_command(struct cfg *cf, int controlfd, double dtime)
+ 	to_tag = argv[5];
+ 	if (op == PLAY && argv[0][1] != '\0')
+ 	    playcount = atoi(argv[0] + 1);
+-	if (op == UPDATE && argc > 6) {
++	if (op != PLAY && argc > 6) {
+ 	    socket_name_u = argv[6];
+ 	    if (strncmp("unix:", socket_name_u, 5) == 0)
+ 		socket_name_u += 5;
+@@ -965,25 +969,39 @@ handle_command(struct cfg *cf, int controlfd, double dtime)
+     }
+ 
+     pthread_mutex_lock(&cf->glock);
+-    if (op == UPDATE) {
+-	if (cf->timeout_handler->socket_name == NULL && socket_name_u != NULL)
+-	    rtpp_log_write(RTPP_LOG_ERR, spa->log, "must permit notification socket with -n");
++
++    if ((op == UPDATE) || (op == LOOKUP)){
+ 	if (spa->timeout_data.notify_tag != NULL) {
+ 	    free(spa->timeout_data.notify_tag);
+ 	    spa->timeout_data.notify_tag = NULL;
+ 	}
+-	if (cf->timeout_handler->socket_name != NULL && socket_name_u != NULL) {
+-	    if (strcmp(cf->timeout_handler->socket_name, socket_name_u) != 0) {
+-		rtpp_log_write(RTPP_LOG_ERR, spa->log, "invalid socket name %s", socket_name_u);
+-		socket_name_u = NULL;
+-	    } else {
++        spa->timeout_data.handler = NULL;
++	if (socket_name_u != NULL) {
++	    if (cf->timeout_handler != NULL && cf->timeout_handler->socket_name != NULL 
++		&& strlen(cf->timeout_handler->socket_name) == strlen(socket_name_u)
++		&& strcmp(cf->timeout_handler->socket_name, socket_name_u) != 0) {
+ 		rtpp_log_write(RTPP_LOG_INFO, spa->log, "setting timeout handler");
+ 		spa->timeout_data.handler = cf->timeout_handler;
+ 		spa->timeout_data.notify_tag = strdup(notify_tag);
++	    } else {
++		rtpp_log_write(RTPP_LOG_INFO, spa->log, "setting custom timeout handler (%s)", socket_name_u);
++		my_timeout_h = malloc(sizeof(struct rtpp_timeout_handler));
++		if (my_timeout_h == NULL) {
++			rtpp_log_write(RTPP_LOG_ERR, spa->log, "Unable to allocate memory");
++		} else {
++			memset(my_timeout_h, 0, sizeof(struct rtpp_timeout_handler));
++	    		my_timeout_h->socket_name = (char *)malloc(strlen(socket_name_u) + 1);
++	    		if(my_timeout_h->socket_name != NULL) {
++				strcpy(my_timeout_h->socket_name, socket_name_u);
++				spa->timeout_data.handler = my_timeout_h;
++				if (notify_tag != NULL) spa->timeout_data.notify_tag = strdup(notify_tag);
++				else spa->timeout_data.notify_tag = NULL;
++			} else {
++				rtpp_log_write(RTPP_LOG_ERR, spa->log, "Unable to allocate memory");
++				free(my_timeout_h);
++			}
++		}
+ 	    }
+-	} else if (socket_name_u == NULL && spa->timeout_data.handler != NULL) {
+-	    spa->timeout_data.handler = NULL;
+-	    rtpp_log_write(RTPP_LOG_INFO, spa->log, "disabling timeout handler");
+ 	}
+     }
+ 
+diff --git a/rtpp_notify.c b/rtpp_notify.c
+index e92c9ec..e6b30e4 100644
+--- a/rtpp_notify.c
++++ b/rtpp_notify.c
+@@ -42,10 +42,24 @@
+ #include "rtpp_session.h"
+ #include "rtpp_util.h"
+ 
++#ifdef ENABLE_XMLRPC
++#include <xmlrpc.h>
++#include <xmlrpc_client.h>
++#define XMLRPC_CLIENT_NAME       "XML-RPC RTPProxy Client"
++#define XMLRPC_CLIENT_VERSION    "0.2"
++#endif
++
+ struct rtpp_notify_wi
+ {
+     char *notify_buf;
+     int len;
++#ifdef ENABLE_XMLRPC
++    char *call_id;
++    int call_id_len;
++    char *param;
++    int param_len;
++    int custom_handler;
++#endif
+     struct rtpp_timeout_handler *th;
+     rtpp_log_t glog;
+     struct rtpp_notify_wi *next;
+@@ -258,6 +272,13 @@ rtpp_notify_schedule(struct cfg *cf, struct rtpp_session *sp)
+     if (wi == NULL)
+         return -1;
+ 
++#ifdef ENABLE_XMLRPC
++    if (th != cf->timeout_handler)
++	wi->custom_handler = 1;
++    else 
++	wi->custom_handler = 0;
++#endif
++
+     wi->th = th;
+     if (sp->timeout_data.notify_tag == NULL) {
+         /* two 5-digit numbers, space, \0 and \n */
+@@ -289,6 +310,59 @@ rtpp_notify_schedule(struct cfg *cf, struct rtpp_session *sp)
+         len = snprintf(wi->notify_buf, len, "%s\n",
+           sp->timeout_data.notify_tag);
+     }
++#ifdef ENABLE_XMLRPC
++
++    // rtpp_log_write(RTPP_LOG_ERR, wi->glog, "Timeout socket is: %s (%p)\n", wi->th->socket_name, wi->th->socket_name);
++
++    if (strncmp("xmlrpc:", wi->th->socket_name, 7) == 0) {
++	    // Copy the Socket-Name
++	    len = strlen(wi->th->socket_name)+1;
++	    if (wi->param == NULL) {
++		wi->param = malloc(len);
++		if (wi->param == NULL) {
++		    rtpp_notify_queue_return_free_item(wi);
++		    return -1;
++		}
++	    } else {
++		notify_buf = realloc(wi->param, len);
++		if (notify_buf == NULL) {
++		    rtpp_notify_queue_return_free_item(wi);
++		    return -1;
++		}
++		wi->param = notify_buf;
++	    }
++	    memset(wi->param, '\0', len);
++	    len = snprintf(wi->param, len, "%s",
++		  wi->th->socket_name);
++	    wi->param_len = len;
++
++	   // rtpp_log_write(RTPP_LOG_ERR, wi->glog, "wi->param %s (%p)\n", wi->param, wi->param);
++
++	    // Copy the Call-ID:
++	    len = strlen(sp->call_id)+1;
++	    if (wi->call_id == NULL) {
++		wi->call_id = malloc(len);
++		if (wi->call_id == NULL) {
++		    rtpp_notify_queue_return_free_item(wi);
++		    return -1;
++		}
++	    } else {
++		notify_buf = realloc(wi->call_id, len);
++		if (notify_buf == NULL) {
++		    rtpp_notify_queue_return_free_item(wi);
++		    return -1;
++		}
++		wi->call_id = notify_buf;
++	    }
++	    memset(wi->call_id, '\0', len);
++	    len = snprintf(wi->call_id, len, "%s",
++		  sp->call_id);
++	    wi->call_id_len = len;
++
++	  // rtpp_log_write(RTPP_LOG_ERR, wi->glog, "wi->call_id %s (%p)\n", wi->call_id, wi->call_id);
++
++    }
++#endif
+ 
+     wi->glog = cf->stable.glog;
+ 
+@@ -345,29 +419,72 @@ reconnect_timeout_handler(rtpp_log_t log, struct rtpp_timeout_handler *th)
+     }
+ }
+ 
++#ifdef ENABLE_XMLRPC
++static int
++do_xmlrpc_timeout_notification(rtpp_log_t log, struct rtpp_notify_wi *wi) {
++    xmlrpc_env env;
++    xmlrpc_value *result;
++    
++    /* Start up our XML-RPC client library. */
++    xmlrpc_client_init(XMLRPC_CLIENT_NO_FLAGS, XMLRPC_CLIENT_NAME, XMLRPC_CLIENT_VERSION);
++    xmlrpc_env_init(&env);
++
++    /* Get the dialog-Info: */
++    result = xmlrpc_client_call(&env, wi->param+7,
++                                "dlg_terminate_dlg", "(s)",
++                                wi->call_id);
++    if (env.fault_occurred) {
++        rtpp_log_write(RTPP_LOG_ERR, wi->glog, "%s: XML-RPC Fault: %s (%d)\n", wi->call_id, env.fault_string, env.fault_code);
++        return -1;
++    }
++    
++    /* Dispose of our result value. */
++    xmlrpc_DECREF(result);
++
++    /* Shutdown our XML-RPC client library. */
++    xmlrpc_env_clean(&env);
++    xmlrpc_client_cleanup();
++
++    return 0;
++}
++#endif
++
+ static void
+ do_timeout_notification(struct rtpp_notify_wi *wi, int retries)
+ {
+     int result;
+ 
+-    if (wi->th->connected == 0) {
+-        reconnect_timeout_handler(wi->glog, wi->th);
+-
+-        /* If connect fails, no notification will be sent */
+-        if (wi->th->connected == 0) {
+-            rtpp_log_write(RTPP_LOG_ERR, wi->glog, "unable to send timeout notification");
+-            return;
+-        }
++    if (strncmp("xmlrpc:", wi->th->socket_name, 7) == 0) {
++	result = do_xmlrpc_timeout_notification(wi->glog, wi);
++    } else {
++	    if (wi->th->connected == 0) {
++		reconnect_timeout_handler(wi->glog, wi->th);
++
++		/* If connect fails, no notification will be sent */
++		if (wi->th->connected == 0) {
++		    rtpp_log_write(RTPP_LOG_ERR, wi->glog, "unable to send timeout notification");
++		    return;
++		}
++	    }
++
++	    do {
++		result = send(wi->th->fd, wi->notify_buf, wi->len - 1, 0);
++	    } while (result == -1 && errno == EINTR);
+     }
+ 
+-    do {
+-        result = send(wi->th->fd, wi->notify_buf, wi->len - 1, 0);
+-    } while (result == -1 && errno == EINTR);
+-
+     if (result < 0) {
+         wi->th->connected = 0;
+         rtpp_log_ewrite(RTPP_LOG_ERR, wi->glog, "failed to send timeout notification");
+         if (retries > 0)
+             do_timeout_notification(wi, retries - 1);
+     }
++#ifdef ENABLE_XMLRPC
++    // In case we use a custom timeout handler, we have to free it.
++    if (wi->th && (wi->custom_handler == 1)) {
++ 	free(wi->th->socket_name);
++	free(wi->th);
++	wi->th = 0;
++    }
++#endif
++
+ }
+diff --git a/rtpp_session.c b/rtpp_session.c
+index 03e3d8a..51b3319 100644
+--- a/rtpp_session.c
++++ b/rtpp_session.c
+@@ -41,6 +41,7 @@
+ #include "rtpp_record.h"
+ #include "rtpp_session.h"
+ #include "rtpp_util.h"
++#include "rtpp_notify.h"
+ 
+ void
+ init_hash_table(struct cfg_stable *cf)
diff --git a/modules/sanity/Makefile b/modules/sanity/Makefile
index 75fbaf3..8fe5144 100755
--- a/modules/sanity/Makefile
+++ b/modules/sanity/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # sanity check module makefile
 #
diff --git a/modules/sanity/api.h b/modules/sanity/api.h
index c7ddb18..01666b5 100644
--- a/modules/sanity/api.h
+++ b/modules/sanity/api.h
@@ -1,23 +1,16 @@
 /*
- * $Id$
- *
  * Sanity Checks Module
  *
  * Copyright (C) 2006 iptelorg GbmH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/modules/sanity/mod_sanity.c b/modules/sanity/mod_sanity.c
index 310be09..1e10189 100644
--- a/modules/sanity/mod_sanity.c
+++ b/modules/sanity/mod_sanity.c
@@ -1,23 +1,16 @@
 /*
- * $Id$
- *
  * Sanity Checks Module
  *
  * Copyright (C) 2006 iptelorg GbmH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/modules/sanity/mod_sanity.h b/modules/sanity/mod_sanity.h
index fb27b40..f946a01 100644
--- a/modules/sanity/mod_sanity.h
+++ b/modules/sanity/mod_sanity.h
@@ -1,23 +1,16 @@
 /*
- * $Id$
- *
  * Sanity Checks Module
  *
  * Copyright (C) 2006 iptelorg GbmH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/modules/sanity/sanity.c b/modules/sanity/sanity.c
index 58522d4..7e1842e 100644
--- a/modules/sanity/sanity.c
+++ b/modules/sanity/sanity.c
@@ -1,23 +1,16 @@
 /*
- * $Id$
- *
  * Sanity Checks Module
  *
  * Copyright (C) 2006 iptelorg GbmH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/modules/sanity/sanity.h b/modules/sanity/sanity.h
index 8ea9d78..934acb5 100644
--- a/modules/sanity/sanity.h
+++ b/modules/sanity/sanity.h
@@ -1,23 +1,16 @@
 /*
- * $Id$
- *
  * Sanity Checks Module
  *
  * Copyright (C) 2006 iptelorg GbmH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/modules/sca/Makefile b/modules/sca/Makefile
index fb9a363..808f16f 100644
--- a/modules/sca/Makefile
+++ b/modules/sca/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # sca module makefile
 #
diff --git a/modules/sca/sca.c b/modules/sca/sca.c
index 920024b..4c73c0f 100644
--- a/modules/sca/sca.c
+++ b/modules/sca/sca.c
@@ -1,9 +1,7 @@
 /*
- * $Id$
- *
  * Copyright (C) 2012 Andrew Mortensen
  *
- * This file is part of the sca module for sip-router, a free SIP server.
+ * This file is part of the sca module for Kamailio, a free SIP server.
  *
  * The sca module is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/modules/sca/sca.h b/modules/sca/sca.h
index 1ded694..83a1c08 100644
--- a/modules/sca/sca.h
+++ b/modules/sca/sca.h
@@ -1,9 +1,7 @@
 /*
- * $Id$
- *
  * Copyright (C) 2012 Andrew Mortensen
  *
- * This file is part of the sca module for sip-router, a free SIP server.
+ * This file is part of the sca module for Kamailio, a free SIP server.
  *
  * The sca module is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/modules/sca/sca_appearance.c b/modules/sca/sca_appearance.c
index 43c5445..e0ba91e 100644
--- a/modules/sca/sca_appearance.c
+++ b/modules/sca/sca_appearance.c
@@ -1,9 +1,7 @@
 /*
- * $Id$
- *
  * Copyright (C) 2012 Andrew Mortensen
  *
- * This file is part of the sca module for sip-router, a free SIP server.
+ * This file is part of the sca module for Kamailio, a free SIP server.
  *
  * The sca module is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/modules/sca/sca_appearance.h b/modules/sca/sca_appearance.h
index 45a77fe..3445183 100644
--- a/modules/sca/sca_appearance.h
+++ b/modules/sca/sca_appearance.h
@@ -1,9 +1,7 @@
 /*
- * $Id$
- *
  * Copyright (C) 2012 Andrew Mortensen
  *
- * This file is part of the sca module for sip-router, a free SIP server.
+ * This file is part of the sca module for Kamailio, a free SIP server.
  *
  * The sca module is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -18,8 +16,6 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- *
- *
  */
 #include "../../str.h"
 
diff --git a/modules/sca/sca_call_info.c b/modules/sca/sca_call_info.c
index 066834c..1f36777 100644
--- a/modules/sca/sca_call_info.c
+++ b/modules/sca/sca_call_info.c
@@ -1,9 +1,7 @@
 /*
- * $Id$
- *
  * Copyright (C) 2012 Andrew Mortensen
  *
- * This file is part of the sca module for sip-router, a free SIP server.
+ * This file is part of the sca module for Kamailio, a free SIP server.
  *
  * The sca module is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/modules/sca/sca_call_info.h b/modules/sca/sca_call_info.h
index c769d7d..a0a2b1e 100644
--- a/modules/sca/sca_call_info.h
+++ b/modules/sca/sca_call_info.h
@@ -1,9 +1,7 @@
 /*
- * $Id$
- *
  * Copyright (C) 2012 Andrew Mortensen
  *
- * This file is part of the sca module for sip-router, a free SIP server.
+ * This file is part of the sca module for Kamailio, a free SIP server.
  *
  * The sca module is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -19,7 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- *
  */
 #ifndef SCA_CALL_INFO_H
 #define SCA_CALL_INFO_H
diff --git a/modules/sca/sca_common.h b/modules/sca/sca_common.h
index 2b15886..8b9db4a 100644
--- a/modules/sca/sca_common.h
+++ b/modules/sca/sca_common.h
@@ -1,9 +1,7 @@
 /*
- * $Id$
- *
  * Copyright (C) 2012 Andrew Mortensen
  *
- * This file is part of the sca module for sip-router, a free SIP server.
+ * This file is part of the sca module for Kamailio, a free SIP server.
  *
  * The sca module is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/modules/sca/sca_db.c b/modules/sca/sca_db.c
index 0bdfa85..dbd3460 100644
--- a/modules/sca/sca_db.c
+++ b/modules/sca/sca_db.c
@@ -1,9 +1,7 @@
 /*
- * $Id$
- *
  * Copyright (C) 2012 Andrew Mortensen
  *
- * This file is part of the sca module for sip-router, a free SIP server.
+ * This file is part of the sca module for Kamailio, a free SIP server.
  *
  * The sca module is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -18,8 +16,6 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- *
- *
  */
 #include "sca_common.h"
 
diff --git a/modules/sca/sca_db.h b/modules/sca/sca_db.h
index b89bae1..f48934b 100644
--- a/modules/sca/sca_db.h
+++ b/modules/sca/sca_db.h
@@ -1,9 +1,7 @@
 /*
- * $Id$
- *
  * Copyright (C) 2012 Andrew Mortensen
  *
- * This file is part of the sca module for sip-router, a free SIP server.
+ * This file is part of the sca module for Kamailio, a free SIP server.
  *
  * The sca module is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/modules/sca/sca_dialog.c b/modules/sca/sca_dialog.c
index 7975ad7..9faf9e7 100644
--- a/modules/sca/sca_dialog.c
+++ b/modules/sca/sca_dialog.c
@@ -1,9 +1,7 @@
 /*
- * $Id$
- *
  * Copyright (C) 2012 Andrew Mortensen
  *
- * This file is part of the sca module for sip-router, a free SIP server.
+ * This file is part of the sca module for Kamailio, a free SIP server.
  *
  * The sca module is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -18,8 +16,6 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- *
- *
  */
 #include "sca_common.h"
 
diff --git a/modules/sca/sca_dialog.h b/modules/sca/sca_dialog.h
index 0015db0..9f7a250 100644
--- a/modules/sca/sca_dialog.h
+++ b/modules/sca/sca_dialog.h
@@ -1,9 +1,7 @@
 /*
- * $Id$
- *
  * Copyright (C) 2012 Andrew Mortensen
  *
- * This file is part of the sca module for sip-router, a free SIP server.
+ * This file is part of the sca module for Kamailio, a free SIP server.
  *
  * The sca module is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/modules/sca/sca_event.c b/modules/sca/sca_event.c
index ad99ae9..ddd9c78 100644
--- a/modules/sca/sca_event.c
+++ b/modules/sca/sca_event.c
@@ -1,9 +1,7 @@
 /*
- * $Id$
- *
  * Copyright (C) 2012 Andrew Mortensen
  *
- * This file is part of the sca module for sip-router, a free SIP server.
+ * This file is part of the sca module for Kamailio, a free SIP server.
  *
  * The sca module is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/modules/sca/sca_event.h b/modules/sca/sca_event.h
index 3cf5db1..a592282 100644
--- a/modules/sca/sca_event.h
+++ b/modules/sca/sca_event.h
@@ -1,9 +1,7 @@
 /*
- * $Id$
- *
  * Copyright (C) 2012 Andrew Mortensen
  *
- * This file is part of the sca module for sip-router, a free SIP server.
+ * This file is part of the sca module for Kamailio, a free SIP server.
  *
  * The sca module is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/modules/sca/sca_hash.c b/modules/sca/sca_hash.c
index f8fa178..fa469c1 100644
--- a/modules/sca/sca_hash.c
+++ b/modules/sca/sca_hash.c
@@ -1,9 +1,7 @@
 /*
- * $Id$
- *
  * Copyright (C) 2012 Andrew Mortensen
  *
- * This file is part of the sca module for sip-router, a free SIP server.
+ * This file is part of the sca module for Kamailio, a free SIP server.
  *
  * The sca module is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/modules/sca/sca_hash.h b/modules/sca/sca_hash.h
index 206eafc..c833c5e 100644
--- a/modules/sca/sca_hash.h
+++ b/modules/sca/sca_hash.h
@@ -1,9 +1,7 @@
 /*
- * $Id$
- *
  * Copyright (C) 2012 Andrew Mortensen
  *
- * This file is part of the sca module for sip-router, a free SIP server.
+ * This file is part of the sca module for Kamailio, a free SIP server.
  *
  * The sca module is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/modules/sca/sca_notify.c b/modules/sca/sca_notify.c
index 0cc0f66..e8cbdba 100644
--- a/modules/sca/sca_notify.c
+++ b/modules/sca/sca_notify.c
@@ -1,9 +1,7 @@
 /*
- * $Id$
- *
  * Copyright (C) 2012 Andrew Mortensen
  *
- * This file is part of the sca module for sip-router, a free SIP server.
+ * This file is part of the sca module for Kamailio, a free SIP server.
  *
  * The sca module is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/modules/sca/sca_notify.h b/modules/sca/sca_notify.h
index acca3ca..1cfe40b 100644
--- a/modules/sca/sca_notify.h
+++ b/modules/sca/sca_notify.h
@@ -1,9 +1,7 @@
 /*
- * $Id$
- *
  * Copyright (C) 2012 Andrew Mortensen
  *
- * This file is part of the sca module for sip-router, a free SIP server.
+ * This file is part of the sca module for Kamailio, a free SIP server.
  *
  * The sca module is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/modules/sca/sca_reply.c b/modules/sca/sca_reply.c
index e84b8ca..3f44317 100644
--- a/modules/sca/sca_reply.c
+++ b/modules/sca/sca_reply.c
@@ -1,9 +1,7 @@
 /*
- * $Id$
- *
  * Copyright (C) 2012 Andrew Mortensen
  *
- * This file is part of the sca module for sip-router, a free SIP server.
+ * This file is part of the sca module for Kamailio, a free SIP server.
  *
  * The sca module is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -18,8 +16,6 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- *
- *
  */
 #include "sca_common.h"
 
diff --git a/modules/sca/sca_reply.h b/modules/sca/sca_reply.h
index dfd59b9..15785bf 100644
--- a/modules/sca/sca_reply.h
+++ b/modules/sca/sca_reply.h
@@ -1,9 +1,7 @@
 /*
- * $Id$
- *
  * Copyright (C) 2012 Andrew Mortensen
  *
- * This file is part of the sca module for sip-router, a free SIP server.
+ * This file is part of the sca module for Kamailio, a free SIP server.
  *
  * The sca module is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -18,8 +16,6 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- *
- *
  */
 #ifndef SCA_REPLY_H
 #define SCA_REPLY_H
diff --git a/modules/sca/sca_rpc.c b/modules/sca/sca_rpc.c
index d1c9f87..5e6873b 100644
--- a/modules/sca/sca_rpc.c
+++ b/modules/sca/sca_rpc.c
@@ -1,9 +1,7 @@
 /*
- * $Id$
- *
  * Copyright (C) 2012 Andrew Mortensen
  *
- * This file is part of the sca module for sip-router, a free SIP server.
+ * This file is part of the sca module for Kamailio, a free SIP server.
  *
  * The sca module is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/modules/sca/sca_rpc.h b/modules/sca/sca_rpc.h
index d323b9b..ff3db39 100644
--- a/modules/sca/sca_rpc.h
+++ b/modules/sca/sca_rpc.h
@@ -1,9 +1,7 @@
 /*
- * $Id$
- *
  * Copyright (C) 2012 Andrew Mortensen
  *
- * This file is part of the sca module for sip-router, a free SIP server.
+ * This file is part of the sca module for Kamailio, a free SIP server.
  *
  * The sca module is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/modules/sca/sca_subscribe.c b/modules/sca/sca_subscribe.c
index b5401a8..9dfb5ce 100644
--- a/modules/sca/sca_subscribe.c
+++ b/modules/sca/sca_subscribe.c
@@ -1,9 +1,7 @@
 /*
- * $Id$
- *
  * Copyright (C) 2012 Andrew Mortensen
  *
- * This file is part of the sca module for sip-router, a free SIP server.
+ * This file is part of the sca module for Kamailio, a free SIP server.
  *
  * The sca module is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -18,8 +16,6 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- *
- *
  */
 #include "sca_common.h"
 
diff --git a/modules/sca/sca_subscribe.h b/modules/sca/sca_subscribe.h
index fc85b49..6fbf7b9 100644
--- a/modules/sca/sca_subscribe.h
+++ b/modules/sca/sca_subscribe.h
@@ -1,9 +1,7 @@
 /*
- * $Id$
- *
  * Copyright (C) 2012 Andrew Mortensen
  *
- * This file is part of the sca module for sip-router, a free SIP server.
+ * This file is part of the sca module for Kamailio, a free SIP server.
  *
  * The sca module is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -18,8 +16,6 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- *
- *
  */
 #ifndef SCA_SUBSCRIBE_H
 #define SCA_SUBSCRIBE_H
diff --git a/modules/sca/sca_util.c b/modules/sca/sca_util.c
index 0b70abe..1a5643e 100644
--- a/modules/sca/sca_util.c
+++ b/modules/sca/sca_util.c
@@ -1,9 +1,7 @@
 /*
- * $Id$
- *
  * Copyright (C) 2012 Andrew Mortensen
  *
- * This file is part of the sca module for sip-router, a free SIP server.
+ * This file is part of the sca module for Kamailio, a free SIP server.
  *
  * The sca module is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -18,8 +16,6 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- *
- *
  */
 #include "sca_common.h"
 
diff --git a/modules/sca/sca_util.h b/modules/sca/sca_util.h
index 985c9bc..eb1664d 100644
--- a/modules/sca/sca_util.h
+++ b/modules/sca/sca_util.h
@@ -1,9 +1,7 @@
 /*
- * $Id$
- *
  * Copyright (C) 2012 Andrew Mortensen
  *
- * This file is part of the sca module for sip-router, a free SIP server.
+ * This file is part of the sca module for Kamailio, a free SIP server.
  *
  * The sca module is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -18,8 +16,6 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- *
- *
  */
 #ifndef SCA_UTIL_H
 #define SCA_UTIL_H
diff --git a/modules/sctp/Makefile b/modules/sctp/Makefile
index a328f77..b813380 100644
--- a/modules/sctp/Makefile
+++ b/modules/sctp/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # WARNING: do not run this directly, it should be run by the master Makefile
 
diff --git a/modules/sdpops/Makefile b/modules/sdpops/Makefile
index 1a9412f..b8e89f1 100644
--- a/modules/sdpops/Makefile
+++ b/modules/sdpops/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
diff --git a/modules/sdpops/README b/modules/sdpops/README
index 74b049d..8558a6f 100644
--- a/modules/sdpops/README
+++ b/modules/sdpops/README
@@ -10,7 +10,7 @@ Daniel-Constantin Mierla
 
    <miconda at gmail.com>
 
-   Copyright � 2011 asipto.com
+   Copyright © 2011 asipto.com
      __________________________________________________________________
 
    Table of Contents
@@ -32,18 +32,19 @@ Daniel-Constantin Mierla
               4.4. sdp_keep_codecs_by_id(list [, mtype])
               4.5. sdp_keep_codecs_by_name(list [, mtype])
               4.6. sdp_with_media(type)
-              4.7. sdp_remove_media(type)
-              4.8. sdp_with_transport(type)
-              4.9. sdp_with_transport_like(string)
-              4.10. sdp_transport(pv)
-              4.11. sdp_remove_transport(type)
-              4.12. sdp_with_codecs_by_id(list)
-              4.13. sdp_with_codecs_by_name(list)
-              4.14. sdp_print(level)
-              4.15. sdp_get(avpvar)
-              4.16. sdp_content()
-              4.17. sdp_with_ice()
-              4.18. sdp_get_line_startswith(avpvar, string)
+              4.7. sdp_with_active_media(type)
+              4.8. sdp_remove_media(type)
+              4.9. sdp_with_transport(type)
+              4.10. sdp_with_transport_like(string)
+              4.11. sdp_transport(pv)
+              4.12. sdp_remove_transport(type)
+              4.13. sdp_with_codecs_by_id(list)
+              4.14. sdp_with_codecs_by_name(list)
+              4.15. sdp_print(level)
+              4.16. sdp_get(avpvar)
+              4.17. sdp_content()
+              4.18. sdp_with_ice()
+              4.19. sdp_get_line_startswith(avpvar, string)
 
    List of Examples
 
@@ -53,18 +54,19 @@ Daniel-Constantin Mierla
    1.4. sdp_keep_codecs_by_id usage
    1.5. sdp_keep_codecs_by_name usage
    1.6. sdp_with_media usage
-   1.7. sdp_remove_media usage
-   1.8. sdp_with_transport usage
-   1.9. sdp_with_transport_like usage
-   1.10. sdp_transport usage
-   1.11. sdp_remove_transport usage
-   1.12. sdp_with_codecs_by_id usage
-   1.13. sdp_with_codecs_by_name usage
-   1.14. sdp_print usage
-   1.15. sdp_get usage
-   1.16. sdp_content usage
-   1.17. sdp_with_ice usage
-   1.18. sdp_get_line_startswith usage
+   1.7. sdp_with_active_media usage
+   1.8. sdp_remove_media usage
+   1.9. sdp_with_transport usage
+   1.10. sdp_with_transport_like usage
+   1.11. sdp_transport usage
+   1.12. sdp_remove_transport usage
+   1.13. sdp_with_codecs_by_id usage
+   1.14. sdp_with_codecs_by_name usage
+   1.15. sdp_print usage
+   1.16. sdp_get usage
+   1.17. sdp_content usage
+   1.18. sdp_with_ice usage
+   1.19. sdp_get_line_startswith usage
 
 Chapter 1. Admin Guide
 
@@ -85,18 +87,19 @@ Chapter 1. Admin Guide
         4.4. sdp_keep_codecs_by_id(list [, mtype])
         4.5. sdp_keep_codecs_by_name(list [, mtype])
         4.6. sdp_with_media(type)
-        4.7. sdp_remove_media(type)
-        4.8. sdp_with_transport(type)
-        4.9. sdp_with_transport_like(string)
-        4.10. sdp_transport(pv)
-        4.11. sdp_remove_transport(type)
-        4.12. sdp_with_codecs_by_id(list)
-        4.13. sdp_with_codecs_by_name(list)
-        4.14. sdp_print(level)
-        4.15. sdp_get(avpvar)
-        4.16. sdp_content()
-        4.17. sdp_with_ice()
-        4.18. sdp_get_line_startswith(avpvar, string)
+        4.7. sdp_with_active_media(type)
+        4.8. sdp_remove_media(type)
+        4.9. sdp_with_transport(type)
+        4.10. sdp_with_transport_like(string)
+        4.11. sdp_transport(pv)
+        4.12. sdp_remove_transport(type)
+        4.13. sdp_with_codecs_by_id(list)
+        4.14. sdp_with_codecs_by_name(list)
+        4.15. sdp_print(level)
+        4.16. sdp_get(avpvar)
+        4.17. sdp_content()
+        4.18. sdp_with_ice()
+        4.19. sdp_get_line_startswith(avpvar, string)
 
 1. Overview
 
@@ -126,7 +129,7 @@ Chapter 1. Admin Guide
 
 3. Parameters
 
-   The module does not export any config parameter yet.
+   The module does not export any config parameters yet.
 
 4. Functions
 
@@ -136,20 +139,21 @@ Chapter 1. Admin Guide
    4.4. sdp_keep_codecs_by_id(list [, mtype])
    4.5. sdp_keep_codecs_by_name(list [, mtype])
    4.6. sdp_with_media(type)
-   4.7. sdp_remove_media(type)
-   4.8. sdp_with_transport(type)
-   4.9. sdp_with_transport_like(string)
-   4.10. sdp_transport(pv)
-   4.11. sdp_remove_transport(type)
-   4.12. sdp_with_codecs_by_id(list)
-   4.13. sdp_with_codecs_by_name(list)
-   4.14. sdp_print(level)
-   4.15. sdp_get(avpvar)
-   4.16. sdp_content()
-   4.17. sdp_with_ice()
-   4.18. sdp_get_line_startswith(avpvar, string)
-
-4.1. sdp_remove_codecs_by_id(list)
+   4.7. sdp_with_active_media(type)
+   4.8. sdp_remove_media(type)
+   4.9. sdp_with_transport(type)
+   4.10. sdp_with_transport_like(string)
+   4.11. sdp_transport(pv)
+   4.12. sdp_remove_transport(type)
+   4.13. sdp_with_codecs_by_id(list)
+   4.14. sdp_with_codecs_by_name(list)
+   4.15. sdp_print(level)
+   4.16. sdp_get(avpvar)
+   4.17. sdp_content()
+   4.18. sdp_with_ice()
+   4.19. sdp_get_line_startswith(avpvar, string)
+
+4.1.  sdp_remove_codecs_by_id(list)
 
    Remove the codecs provided in the parameter 'list' from all media
    streams found in SDP payload. The parameter 'list' must be one item or
@@ -166,7 +170,7 @@ sdp_remove_codecs_by_id("0");
 sdp_remove_codecs_by_id("0,8,3");
 ...
 
-4.2. sdp_remove_codecs_by_name(list)
+4.2.  sdp_remove_codecs_by_name(list)
 
    Remove the codecs provided in the parameter 'list' from all media
    streams found in SDP payload. The parameter 'list' must be one item or
@@ -183,7 +187,7 @@ sdp_remove_codecs_by_name("PCMU");
 sdp_remove_codecs_by_name("PCMU,PCMA,GSM");
 ...
 
-4.3. sdp_remove_line_by_prefix(string)
+4.3.  sdp_remove_line_by_prefix(string)
 
    Remove all SDP attribute lines beginning with 'string' in all media
    streams.
@@ -202,7 +206,7 @@ if ($si == "2001:DB8::8:800:200C:417A"
 
 ...
 
-4.4. sdp_keep_codecs_by_id(list [, mtype])
+4.4.  sdp_keep_codecs_by_id(list [, mtype])
 
    Keep only the codecs provided in the parameter 'list' from all media
    streams found in SDP payload. The parameter 'list' must be one item or
@@ -222,7 +226,7 @@ sdp_keep_codecs_by_id("0");
 sdp_keep_codecs_by_id("0,8,3", "audio");
 ...
 
-4.5. sdp_keep_codecs_by_name(list [, mtype])
+4.5.  sdp_keep_codecs_by_name(list [, mtype])
 
    Keep only the codecs provided in the parameter 'list' from all media
    streams found in SDP payload. The parameter 'list' must be one or a
@@ -245,7 +249,7 @@ sdp_keep_codecs_by_name("PCMU");
 sdp_keep_codecs_by_name("PCMU,PCMA,GSM");
 ...
 
-4.6. sdp_with_media(type)
+4.6.  sdp_with_media(type)
 
    Return true of the SDP has 'media=type ...' line. Useful to check the
    content of the RTP sessions, such as 'audio' or 'video'. The parameter
@@ -262,20 +266,39 @@ if(sdp_with_media("video"))
 }
 ...
 
-4.7. sdp_remove_media(type)
+4.7.  sdp_with_active_media(type)
+
+   Return true of the SDP has 'media=type ...' line and the media is
+   active. Useful to check the content of the RTP sessions, such as
+   'audio' or 'video'. Active media means the port is non-zero and the
+   direction is not "inactive" The parameter can be static string or
+   variable holding the media type.
+
+   This function can be used from ANY_ROUTE.
+
+   Example 1.7. sdp_with_active_media usage
+...
+# check for active video stream
+if(sdp_with_active_media("video"))
+{
+    # the session has an active video stream
+}
+...
+
+4.8.  sdp_remove_media(type)
 
    Remove the streams that match on 'm=type ...' line. The parameter can
    be static string or variable holding the media type.
 
    This function can be used from ANY_ROUTE.
 
-   Example 1.7. sdp_remove_media usage
+   Example 1.8. sdp_remove_media usage
 ...
 # remove video stream
 sdp_remove_media("video");
 ...
 
-4.8. sdp_with_transport(type)
+4.9.  sdp_with_transport(type)
 
    Return true of the SDP has 'media=media port type ...' line. Useful to
    check the transport of the RTP sessions, such as 'RTP/AVP', 'RTP/SAVP'
@@ -284,7 +307,7 @@ sdp_remove_media("video");
 
    This function can be used from ANY_ROUTE.
 
-   Example 1.8. sdp_with_transport usage
+   Example 1.9. sdp_with_transport usage
 ...
 # check for RTP/SAVP stream
 if(sdp_with_transport("RTP/SAVP"))
@@ -293,7 +316,7 @@ if(sdp_with_transport("RTP/SAVP"))
 }
 ...
 
-4.9. sdp_with_transport_like(string)
+4.10.  sdp_with_transport_like(string)
 
    Returns true if the SDP has 'media=media port type ...' line, where
    type contains string. The parameter can be static string or variable
@@ -301,7 +324,7 @@ if(sdp_with_transport("RTP/SAVP"))
 
    This function can be used from ANY_ROUTE.
 
-   Example 1.9. sdp_with_transport_like usage
+   Example 1.10. sdp_with_transport_like usage
 ...
 # check for SAVPF stream
 if(sdp_with_transport_like("SAVPF"))
@@ -310,7 +333,7 @@ if(sdp_with_transport_like("SAVPF"))
 }
 ...
 
-4.10. sdp_transport(pv)
+4.11.  sdp_transport(pv)
 
    Assigns common media transport (if any) of 'm' lines to pv argument.
    Returns 1 if common media transport was found, -2 if there was no
@@ -318,25 +341,25 @@ if(sdp_with_transport_like("SAVPF"))
 
    This function can be used from ANY_ROUTE.
 
-   Example 1.10. sdp_transport usage
+   Example 1.11. sdp_transport usage
 ...
 sdp_transport("$avp(caller_rtp_transport)");
 ...
 
-4.11. sdp_remove_transport(type)
+4.12.  sdp_remove_transport(type)
 
    Remove the streams that match on 'm=media port type ...' line. The
    parameter can be static string or variable holding the transport type.
 
    This function can be used from ANY_ROUTE.
 
-   Example 1.11. sdp_remove_transport usage
+   Example 1.12. sdp_remove_transport usage
 ...
 # remove stream with transport RTP/AVP
 sdp_remove_transport("RTP/AVP");
 ...
 
-4.12. sdp_with_codecs_by_id(list)
+4.13.  sdp_with_codecs_by_id(list)
 
    Returns true if any of the codecs provided in the parameter 'list' from
    all media streams is found in SDP payload. The parameter 'list' must be
@@ -345,7 +368,7 @@ sdp_remove_transport("RTP/AVP");
 
    This function can be used from ANY_ROUTE.
 
-   Example 1.12. sdp_with_codecs_by_id usage
+   Example 1.13. sdp_with_codecs_by_id usage
 ...
 # test for PCMU
 if(sdp_with_codecs_by_id("0")) { ... }
@@ -353,7 +376,7 @@ if(sdp_with_codecs_by_id("0")) { ... }
 if(sdp_with_codecs_by_id("0,8,3")) { ... }
 ...
 
-4.13. sdp_with_codecs_by_name(list)
+4.14.  sdp_with_codecs_by_name(list)
 
    Returns true if any of the codecs provided in the parameter 'list' from
    all media streams is found in SDP payload. The parameter 'list' must be
@@ -362,7 +385,7 @@ if(sdp_with_codecs_by_id("0,8,3")) { ... }
 
    This function can be used from ANY_ROUTE.
 
-   Example 1.13. sdp_with_codecs_by_name usage
+   Example 1.14. sdp_with_codecs_by_name usage
 ...
 # test for PCMU
 if(sdp_with_codecs_by_name("PCMU")) { ... }
@@ -370,59 +393,59 @@ if(sdp_with_codecs_by_name("PCMU")) { ... }
 if(sdp_with_codecs_by_name("PCMU,PCMA,GSM")) { ... }
 ...
 
-4.14. sdp_print(level)
+4.15.  sdp_print(level)
 
    Print the SDP internal structure to log 'level'. The parameter can be
    static integer or variable holding the integer value of the log level.
 
    This function can be used from ANY_ROUTE.
 
-   Example 1.14. sdp_print usage
+   Example 1.15. sdp_print usage
 ...
 # print the SDP
 sdp_print("1");
 ...
 
-4.15. sdp_get(avpvar)
+4.16.  sdp_get(avpvar)
 
    Store the SDP part of message body in an AVP. Return 1 if SDP is found,
    -1 on error and -2 if there is no SDP part in the message body.
 
    This function can be used from ANY_ROUTE.
 
-   Example 1.15. sdp_get usage
+   Example 1.16. sdp_get usage
 ...
 sdp_get("$avp(sdp)");
 ...
 
-4.16. sdp_content()
+4.17.  sdp_content()
 
    Return true if the SIP message has SDP body or a SDP part in body.
 
    This function can be used from ANY_ROUTE.
 
-   Example 1.16. sdp_content usage
+   Example 1.17. sdp_content usage
 ...
 if(sdp_content()) {
     ...
 }
 ...
 
-4.17. sdp_with_ice()
+4.18.  sdp_with_ice()
 
    Return true if the SIP message has SDP body that contains ICE candidate
    attribute(s).
 
    This function can be used from ANY_ROUTE.
 
-   Example 1.17. sdp_with_ice usage
+   Example 1.18. sdp_with_ice usage
 ...
 if(sdp_with_ice()) {
     ...
 }
 ...
 
-4.18. sdp_get_line_startswith(avpvar, string)
+4.19.  sdp_get_line_startswith(avpvar, string)
 
    Store the search part of SDP body message with line beginning with
    'string' in an AVP. Return 1 if 'string' is found in SDP, -1 on error
@@ -430,7 +453,7 @@ if(sdp_with_ice()) {
 
    This function can be used from ANY_ROUTE.
 
-   Example 1.18. sdp_get_line_startswith usage
+   Example 1.19. sdp_get_line_startswith usage
 ...
 if(sdp_get_line_startswith("$avp(mline)", "m=")) {
         xlog("m-line: $avp(mline)\n");
diff --git a/modules/sdpops/doc/sdpops_admin.xml b/modules/sdpops/doc/sdpops_admin.xml
index 8d10f06..e93ea6b 100644
--- a/modules/sdpops/doc/sdpops_admin.xml
+++ b/modules/sdpops/doc/sdpops_admin.xml
@@ -234,6 +234,32 @@ if(sdp_with_media("video"))
 </programlisting>
 	    </example>
 	</section>
+	<section id="sdpops.f.sdp_with_active_media">
+	    <title>
+		<function moreinfo="none">sdp_with_active_media(type)</function>
+	    </title>
+	    <para>
+		Return true of the SDP has 'media=type ...' line and the media is active.
+		Useful to check	the content of the RTP sessions, such as 'audio' or 'video'.
+		Active media means the port is non-zero and the direction is not "inactive"
+		The parameter can be static string or variable holding the media type.
+	    </para>
+		<para>
+			This function can be used from ANY_ROUTE.
+	    </para>
+		<example>
+		<title><function>sdp_with_active_media</function> usage</title>
+		<programlisting format="linespecific">
+...
+# check for active video stream
+if(sdp_with_active_media("video"))
+{
+    # the session has an active video stream
+}
+...
+</programlisting>
+	    </example>
+	</section>
 	<section id="sdpops.f.sdp_remove_media">
 	    <title>
 		<function moreinfo="none">sdp_remove_media(type)</function>
diff --git a/modules/sdpops/sdpops_mod.c b/modules/sdpops/sdpops_mod.c
index 98c2f84..2a4aa6b 100644
--- a/modules/sdpops/sdpops_mod.c
+++ b/modules/sdpops/sdpops_mod.c
@@ -48,6 +48,7 @@ static int w_sdp_remove_codecs_by_name(sip_msg_t* msg, char* codecs, char *bar);
 static int w_sdp_keep_codecs_by_id(sip_msg_t* msg, char* codecs, char *bar);
 static int w_sdp_keep_codecs_by_name(sip_msg_t* msg, char* codecs, char *bar);
 static int w_sdp_with_media(sip_msg_t* msg, char* media, char *bar);
+static int w_sdp_with_active_media(sip_msg_t* msg, char* media, char *bar);
 static int w_sdp_with_transport(sip_msg_t* msg, char* transport, char *bar);
 static int w_sdp_with_transport_like(sip_msg_t* msg, char* transport, char *bar);
 static int w_sdp_transport(sip_msg_t* msg, char *bar);
@@ -81,6 +82,8 @@ static cmd_export_t cmds[] = {
 		2, fixup_spve_spve,  0, ANY_ROUTE},
 	{"sdp_with_media",             (cmd_function)w_sdp_with_media,
 		1, fixup_spve_null,  0, ANY_ROUTE},
+	{"sdp_with_active_media",       (cmd_function)w_sdp_with_active_media,
+		1, fixup_spve_null,  0, ANY_ROUTE},
 	{"sdp_remove_media",             (cmd_function)w_sdp_remove_media,
 		1, fixup_spve_null,  0, ANY_ROUTE},
 	{"sdp_with_transport",         (cmd_function)w_sdp_with_transport,
@@ -815,6 +818,86 @@ static int w_sdp_with_media(sip_msg_t* msg, char* media, char *bar)
 }
 
 /**
+ * @brief check 'media' matches the value of any 'm=value ...' lines, and that line is active
+ * @return -1 - error; 0 - not found or inactive; 1 - at least one sendrecv, recvonly or sendonly stream
+ */
+static int sdp_with_active_media(sip_msg_t *msg, str *media)
+{
+	int sdp_session_num;
+	int sdp_stream_num;
+	int port_num;
+	sdp_session_cell_t* sdp_session;
+	sdp_stream_cell_t* sdp_stream;
+
+	if(parse_sdp(msg) < 0) {
+		LM_ERR("Unable to parse sdp\n");
+		return -1;
+	}
+
+	LM_DBG("attempting to search for media type: [%.*s]\n",
+			media->len, media->s);
+
+	sdp_session_num = 0;
+	for(;;)
+	{
+		sdp_session = get_sdp_session(msg, sdp_session_num);
+		if(!sdp_session) break;
+		sdp_stream_num = 0;
+		for(;;)
+		{
+			sdp_stream = get_sdp_stream(msg, sdp_session_num, sdp_stream_num);
+			if(!sdp_stream) break;
+
+			LM_DBG("stream %d of %d - media [%.*s]\n",
+					sdp_stream_num, sdp_session_num,
+					sdp_stream->media.len, sdp_stream->media.s);
+			if(media->len==sdp_stream->media.len
+					&& strncasecmp(sdp_stream->media.s, media->s,
+						media->len)==0) {
+				port_num = atoi(sdp_stream->port.s);
+				LM_DBG("Port number is %d\n", port_num);
+				if (port_num != 0) {  /* Zero port number => inactive */
+					LM_DBG("sendrecv_mode %.*s\n", sdp_stream->sendrecv_mode.len, sdp_stream->sendrecv_mode.s);
+					if ((sdp_stream->sendrecv_mode.len == 0) || /* No send/recv mode given => sendrecv */
+						(strncasecmp(sdp_stream->sendrecv_mode.s, "inactive", 8) != 0)) { /* Explicit mode is not inactive */
+						/* Found an active stream for the correct media type */
+						return 1;
+					}
+				}
+			}
+			sdp_stream_num++;
+		}
+		sdp_session_num++;
+	}
+
+	return 0;
+}
+
+/**
+ *
+ */
+static int w_sdp_with_active_media(sip_msg_t* msg, char* media, char *bar)
+{
+	str lmedia = {0, 0};
+
+	if(media==0)
+	{
+		LM_ERR("invalid parameters\n");
+		return -1;
+	}
+
+	if(fixup_get_svalue(msg, (gparam_p)media, &lmedia)!=0)
+	{
+		LM_ERR("unable to get the media value\n");
+		return -1;
+	}
+
+	if(sdp_with_active_media(msg, &lmedia)<=0)
+		return -1;
+	return 1;
+}
+
+/**
  * @brief remove streams matching the m='media'
  * @return -1 - error; 0 - not found; >=1 - found
  */
diff --git a/modules/seas/Makefile b/modules/seas/Makefile
index 20d9394..11b937b 100644
--- a/modules/seas/Makefile
+++ b/modules/seas/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # example module makefile
 #
diff --git a/modules/sipcapture/Makefile b/modules/sipcapture/Makefile
index f5a37f4..f9b3e9a 100644
--- a/modules/sipcapture/Makefile
+++ b/modules/sipcapture/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # sipcapture module makefile
 #
diff --git a/modules/sipcapture/hash_mode.h b/modules/sipcapture/hash_mode.h
index 9969f42..933ee81 100644
--- a/modules/sipcapture/hash_mode.h
+++ b/modules/sipcapture/hash_mode.h
@@ -1,16 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2012 dragos.dinu at 1and1.ro, 1&1 Internet AG
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/modules/sipcapture/hep.c b/modules/sipcapture/hep.c
index a14fcd9..c0a1791 100644
--- a/modules/sipcapture/hep.c
+++ b/modules/sipcapture/hep.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * hep related functions
  *
  * Copyright (C) 2011-14 Alexandr Dubovikov <alexandr.dubovikov at gmail.com>
diff --git a/modules/sipcapture/hep.h b/modules/sipcapture/hep.h
index aad0b79..c2433db 100644
--- a/modules/sipcapture/hep.h
+++ b/modules/sipcapture/hep.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * hep related structure
  *
  * Copyright (C) 2011-14 Alexandr Dubovikov <alexandr.dubovikov at gmail.com>
diff --git a/modules/sipcapture/sipcapture.c b/modules/sipcapture/sipcapture.c
index 804436e..bef1305 100644
--- a/modules/sipcapture/sipcapture.c
+++ b/modules/sipcapture/sipcapture.c
@@ -1,6 +1,4 @@
 /* 
- * $Id$ 
- *
  * sipcapture module - helper module to capture sip messages
  *
  * Copyright (C) 2011-2014 Alexandr Dubovikov (QSC AG) (alexandr.dubovikov at gmail.com)
diff --git a/modules/sipcapture/sipcapture.h b/modules/sipcapture/sipcapture.h
index cd85c84..8d912fe 100644
--- a/modules/sipcapture/sipcapture.h
+++ b/modules/sipcapture/sipcapture.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * hep related structure
  *
  * Copyright (C) 2011-2014 Alexandr Dubovikov (QSC AG) (alexandr.dubovikov at gmail.com)
diff --git a/modules/sipt/Makefile b/modules/sipt/Makefile
index d3342fe..93defc7 100644
--- a/modules/sipt/Makefile
+++ b/modules/sipt/Makefile
@@ -1,4 +1,3 @@
-# $Id: $
 #
 # sipt module makefile
 #
diff --git a/modules/sipt/README b/modules/sipt/README
index a129e6f..5e33c7c 100644
--- a/modules/sipt/README
+++ b/modules/sipt/README
@@ -17,7 +17,10 @@ Torrey Searle
         3. Functions
 
               3.1. sipt_destination(destination, hops, nai)
-              3.2. sipt_set_calling(origin, nai, presentation, screening)
+              3.2. sipt_set_bci_1(charge_indicator, called_status,
+                      called_category, e2e_indicator)
+
+              3.3. sipt_set_calling(origin, nai, presentation, screening)
 
         4. Exported pseudo-variables
 
@@ -48,13 +51,14 @@ Torrey Searle
    List of Examples
 
    1.1. sipt_destination(destination, hops, nai) usage
-   1.2. sipt_set_calling(origin, nai, presentation, screening) usage
-   1.3. sipt_presentation pseudo-variable usage
-   1.4. sipt_screening pseudo-variable usage
-   1.5. sipt_hop_counter pseudo-variable usage
-   1.6. sipt_cpc pseudo-variable usage
-   1.7. sipt_calling_party_nai pseudo-variable usage
-   1.8. sipt_called_party_nai pseudo-variable usage
+   1.2. sipt_destination(destination, hops, nai) usage
+   1.3. sipt_set_calling(origin, nai, presentation, screening) usage
+   1.4. sipt_presentation pseudo-variable usage
+   1.5. sipt_screening pseudo-variable usage
+   1.6. sipt_hop_counter pseudo-variable usage
+   1.7. sipt_cpc pseudo-variable usage
+   1.8. sipt_calling_party_nai pseudo-variable usage
+   1.9. sipt_called_party_nai pseudo-variable usage
 
 Chapter 1. Admin Guide
 
@@ -65,7 +69,10 @@ Chapter 1. Admin Guide
    3. Functions
 
         3.1. sipt_destination(destination, hops, nai)
-        3.2. sipt_set_calling(origin, nai, presentation, screening)
+        3.2. sipt_set_bci_1(charge_indicator, called_status,
+                called_category, e2e_indicator)
+
+        3.3. sipt_set_calling(origin, nai, presentation, screening)
 
    4. Exported pseudo-variables
 
@@ -97,7 +104,10 @@ Chapter 1. Admin Guide
 3. Functions
 
    3.1. sipt_destination(destination, hops, nai)
-   3.2. sipt_set_calling(origin, nai, presentation, screening)
+   3.2. sipt_set_bci_1(charge_indicator, called_status, called_category,
+          e2e_indicator)
+
+   3.3. sipt_set_calling(origin, nai, presentation, screening)
 
 3.1. sipt_destination(destination, hops, nai)
 
@@ -114,14 +124,29 @@ $rU = "19495551234";
 sipt_destination($rU, 31, 4);
 ...
 
-3.2. sipt_set_calling(origin, nai, presentation, screening)
+3.2. sipt_set_bci_1(charge_indicator, called_status, called_category,
+e2e_indicator)
+
+   updates the first byte of the backward call indicator in the ACM or COT
+   in the body if setting the Charge Indicator to “charge_indicator”, the
+   Called party's status indicator in “called_status”, the Called party's
+   category indicator in “called_category” and the End to End Method
+   Indicator with the value of the value of “e2e_indicator”.
+
+   Example 1.2. sipt_destination(destination, hops, nai) usage
+...
+# set bci for charging, subscriber free, ordinary, no e2e available
+sipt_set_bci_1("2", "1", "1", "0");
+...
+
+3.3. sipt_set_calling(origin, nai, presentation, screening)
 
    updates the IAM in the body if it exists, setting (or adding) the
    calling party number to “origin” with the nature address specified in
    “nai” and setting the presentation and screening values to
    “presentation” and “screening”.
 
-   Example 1.2. sipt_set_calling(origin, nai, presentation, screening)
+   Example 1.3. sipt_set_calling(origin, nai, presentation, screening)
    usage
 ...
 # update the calling party to the value in the from header
@@ -154,7 +179,7 @@ sipt_set_calling($fU, 4, 0, 3);
    2 address not avail (national use)
    3 spare
 
-   Example 1.3. sipt_presentation pseudo-variable usage
+   Example 1.4. sipt_presentation pseudo-variable usage
 ...
 # add privacy header if restriction is requested
 if($sipt(calling_party_number.presentation) == 1)
@@ -177,7 +202,7 @@ if($sipt(calling_party_number.presentation) == 1)
    2 Reserved (user provided, verified and failed)
    3 Network provided
 
-   Example 1.4. sipt_screening pseudo-variable usage
+   Example 1.5. sipt_screening pseudo-variable usage
 ...
 
 # remove P-Asserted-Identity header if the screening isn't verified
@@ -195,7 +220,7 @@ if($avp(s:screening) != 1 && $avp(s:screening) != 3)
    Returns the value of the Hop Counter for the IAM message if it exists.
    Returns -1 if there isn't a hop counter.
 
-   Example 1.5. sipt_hop_counter pseudo-variable usage
+   Example 1.6. sipt_hop_counter pseudo-variable usage
 ...
 # get the hop counter and update the Max-Forwards header if it exists
 $avp(s:hop) = $sipt(hop_counter);
@@ -212,7 +237,7 @@ if($avp(s:hop) > 0)
    Returns the value of the Calling Party Category for the IAM message.
    Returns -1 if there is a parsing error.
 
-   Example 1.6. sipt_cpc pseudo-variable usage
+   Example 1.7. sipt_cpc pseudo-variable usage
 ...
 # get the Cpc code and set put it in a custom sip header
 append_hf("X-CPC: $sipt(cpc)\r\n");
@@ -233,7 +258,7 @@ $sipt.(calling_party_number.nai) / $sipt_calling_party_nai
    3 National (significant) number (national use)
    4 International use
 
-   Example 1.7. sipt_calling_party_nai pseudo-variable usage
+   Example 1.8. sipt_calling_party_nai pseudo-variable usage
 ...
 # get the Calling Nai and add country code if national
 if($sipt(calling_party_number.nai) == 3)
@@ -257,7 +282,7 @@ $sipt(called_party_number.nai) / $sipt_called_party_nai
    4 International use
    5 Network-specific number (national use)
 
-   Example 1.8. sipt_called_party_nai pseudo-variable usage
+   Example 1.9. sipt_called_party_nai pseudo-variable usage
 ...
 # get the Called Nai and add country code if national
 if($sipt(called_party_number.nai) == 3)
diff --git a/modules/sipt/doc/sipt_admin.xml b/modules/sipt/doc/sipt_admin.xml
index 8b7889f..42e329c 100644
--- a/modules/sipt/doc/sipt_admin.xml
+++ b/modules/sipt/doc/sipt_admin.xml
@@ -56,6 +56,24 @@ sipt_destination($rU, 31, 4);
 </programlisting>
 		</example>
 	</section>
+	<section id="sipt.f.sipt_set_bci_1">
+		<title><function moreinfo="none">sipt_set_bci_1(charge_indicator, called_status, called_category, e2e_indicator)</function></title>
+		<para>
+			updates the first byte of the backward call indicator in the ACM or COT in the body if setting the 
+			Charge Indicator to <quote>charge_indicator</quote>, the Called party's status indicator in <quote>called_status</quote>, 
+			the Called party's category indicator in <quote>called_category</quote> and the End to End Method Indicator
+			with the value of the value of <quote>e2e_indicator</quote>.
+		</para>
+		<example>
+			<title><function moreinfo="none">sipt_destination(destination, hops, nai)</function> usage</title>
+			<programlisting format="linespecific">
+...
+# set bci for charging, subscriber free, ordinary, no e2e available
+sipt_set_bci_1("2", "1", "1", "0");
+...
+</programlisting>
+		</example>
+	</section>
 	<section id="sipt.f.sipt_set_calling">
 		<title><function moreinfo="none">sipt_set_calling(origin, nai, presentation, screening)</function></title>
 		<para>
diff --git a/modules/sipt/sipt.c b/modules/sipt/sipt.c
index cca358a..343d729 100644
--- a/modules/sipt/sipt.c
+++ b/modules/sipt/sipt.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright (C) 2013 Voxbone SA
+ * Copyright (C) 2015 Voxbone SA
  *
  * This file is part of SIP-Router, a free SIP server.
  *
@@ -39,6 +39,7 @@
 
 MODULE_VERSION
 
+static int sipt_set_bci_1(struct sip_msg *msg, char *_charge_indicator, char *_called_status, char * _called_category, char * _e2e_indicator);
 static int sipt_destination(struct sip_msg *msg, char *_destination, char *_hops, char * _nai);
 static int sipt_set_calling(struct sip_msg *msg, char *_origin, char *_nai, char *_pres, char * _screen);
 static int sipt_get_hop_counter(struct sip_msg *msg, pv_param_t *param, pv_value_t *res);
@@ -133,6 +134,12 @@ static cmd_export_t cmds[]={
 		fixup_str_str_str, fixup_free_str_str_str,         /* */
 		/* can be applied to original requests */
 		REQUEST_ROUTE|BRANCH_ROUTE}, 
+	{"sipt_set_bci_1", /* action name as in scripts */
+		(cmd_function)sipt_set_bci_1,  /* C function name */
+		4,          /* number of parameters */
+		fixup_str_str_str, fixup_free_str_str_str,         /* */
+		/* can be applied to original requests */
+		ONREPLY_ROUTE}, 
 	{0, 0, 0, 0, 0, 0}
 };
 
@@ -469,6 +476,67 @@ static int sipt_get_pv(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
 	return -1;
 }
 
+static int sipt_set_bci_1(struct sip_msg *msg, char *_charge_indicator, char *_called_status, char * _called_category, char * _e2e_indicator)
+{
+	str * str_charge_indicator = (str*)_charge_indicator;
+	unsigned int charge_indicator = 0;
+	str2int(str_charge_indicator, &charge_indicator);
+	str * str_called_status = (str*)_called_status;
+	unsigned int called_status = 0;
+	str2int(str_called_status, &called_status);
+	str * str_called_category = (str*)_called_category;
+	unsigned int called_category = 0;
+	str2int(str_called_category, &called_category);
+	str * str_e2e_indicator = (str*)_e2e_indicator;
+	unsigned int e2e_indicator = 0;
+	str2int(str_e2e_indicator, &e2e_indicator);
+	struct sdp_mangler mangle;
+
+	// update forwarded iam
+	str body;
+	body.s = get_body_part(msg, TYPE_APPLICATION,SUBTYPE_ISUP,&body.len);
+
+	if(body.s == NULL)
+	{
+		LM_INFO("No ISUP Message Found");
+		return -1;
+	}
+	str sdp;
+	sdp.s = get_body_part(msg, TYPE_APPLICATION, SUBTYPE_SDP, &sdp.len);
+	
+	unsigned char newbuf[1024];
+	memset(newbuf, 0, 1024);
+	if (body.s==0) {
+		LM_ERR("failed to get the message body\n");
+		return -1;
+	}
+	body.len = msg->len -(int)(body.s-msg->buf);
+	if (body.len==0) {
+		LM_DBG("message body has zero length\n");
+		return -1;
+	}
+
+	if(body.s[0] != ISUP_ACM && body.s[0] != ISUP_COT)
+	{
+		LM_DBG("message not an ACM or COT\n");
+		return -1;
+	}
+
+	mangle.msg = msg;
+	mangle.body_offset = (int)(body.s - msg->buf);
+
+
+
+	int res = isup_update_bci_1(&mangle, charge_indicator, called_status, called_category, e2e_indicator, (unsigned char*)body.s, body.len);
+	if(res < 0)
+	{
+		LM_DBG("error updating ACM\n");
+		return -1;
+	}
+
+	return 1;
+}
+
 static int sipt_destination(struct sip_msg *msg, char *_destination, char *_hops, char * _nai)
 {
 	str * str_hops = (str*)_hops;
diff --git a/modules/sipt/ss7.h b/modules/sipt/ss7.h
index bba47a3..e58303d 100644
--- a/modules/sipt/ss7.h
+++ b/modules/sipt/ss7.h
@@ -203,6 +203,7 @@ int isup_get_called_party_nai(unsigned char *buf, int len);
 int isup_get_screening(unsigned char *buf, int len);
 int isup_get_presentation(unsigned char *buf, int len);
 int isup_update_destination(struct sdp_mangler * mangle, char * dest, int hops, int nai, unsigned char *buf, int len);
+int isup_update_bci_1(struct sdp_mangler * mangle, int charge_indicator, int called_status, int called_category, int e2e_indicator, unsigned char *buf, int len);
 int isup_update_calling(struct sdp_mangler * mangle, char * origin, int nai, int presentation, int screening, unsigned char * buf, int len);
 
 
diff --git a/modules/sipt/ss7_parser.c b/modules/sipt/ss7_parser.c
index 1263fa0..e7554f8 100644
--- a/modules/sipt/ss7_parser.c
+++ b/modules/sipt/ss7_parser.c
@@ -158,7 +158,7 @@ static int get_optional_header(unsigned char header, unsigned char *buf, int len
 		offset += offsetof(struct isup_iam_fixed, optional_pointer);
 		optional_pointer = message->iam.optional_pointer;
 	}
-	else if(message->type == ISUP_ACM)
+	else if(message->type == ISUP_ACM || message->type == ISUP_COT)
 	{
 		len -= offsetof(struct isup_acm_fixed, optional_pointer);
 		offset += offsetof(struct isup_acm_fixed, optional_pointer);
@@ -305,6 +305,29 @@ int isup_get_called_party_nai(unsigned char *buf, int len)
 	return message->called_party_number[1]&0x7F;
 }
 
+int isup_update_bci_1(struct sdp_mangler * mangle, int charge_indicator, int called_status, int called_category, int e2e_indicator, unsigned char *buf, int len)
+{
+	struct isup_acm_fixed * orig_message = (struct isup_acm_fixed*)buf;
+	unsigned char bci;
+
+	// not an acm or cot? do nothing
+	if(orig_message->type != ISUP_ACM && orig_message->type != ISUP_COT)
+	{
+		return 1;
+	}
+
+	// add minus 1 because the optinal pointer is optional
+	if (len < sizeof(struct isup_acm_fixed) -1 )
+		return -1;
+
+	bci = (charge_indicator & 0x3) | ((called_status & 0x3)<<2) |
+		((called_category & 0x3)<<4) | ((e2e_indicator & 0x3)<<6);
+
+	replace_body_segment(mangle, offsetof(struct isup_acm_fixed, backwards_call_ind), 1, &bci, 1);
+
+	return sizeof(struct isup_acm_fixed);
+}
+
 int isup_update_destination(struct sdp_mangler * mangle, char * dest, int hops, int nai, unsigned char *buf, int len)
 {
 	int offset = 0;
diff --git a/modules/siptrace/Makefile b/modules/siptrace/Makefile
index d200908..85c283c 100644
--- a/modules/siptrace/Makefile
+++ b/modules/siptrace/Makefile
@@ -1,6 +1,5 @@
-# $Id$
 #
-# example module makefile
+# siptrace module makefile
 #
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
diff --git a/modules/siptrace/siptrace.c b/modules/siptrace/siptrace.c
index 0ccef7d..07e3a1a 100644
--- a/modules/siptrace/siptrace.c
+++ b/modules/siptrace/siptrace.c
@@ -1,6 +1,4 @@
 /* 
- * $Id$ 
- *
  * siptrace module - helper module to trace sip messages
  *
  * Copyright (C) 2006 Voice Sistem S.R.L.
@@ -72,6 +70,7 @@ struct _siptrace_data {
 	char *dir;
 	str fromtag;
 	str fromip;
+	str totag;
 	str toip;
 	char toip_buff[IP_ADDR_MAX_STR_SIZE+12];
 	char fromip_buff[IP_ADDR_MAX_STR_SIZE+12];
@@ -123,8 +122,10 @@ static str toip_column        = str_init("toip");        /* 07 */
 static str fromtag_column     = str_init("fromtag");     /* 08 */
 static str direction_column   = str_init("direction");   /* 09 */
 static str time_us_column     = str_init("time_us");     /* 10 */
+static str totag_column       = str_init("totag");       /* 11 */
 
-#define NR_KEYS 11
+#define NR_KEYS 12
+#define SIP_TRACE_TABLE_VERSION 4
 
 #define XHEADERS_BUFSIZE 512
 
@@ -193,6 +194,7 @@ static param_export_t params[] = {
 	{"fromip_column",      PARAM_STR, &fromip_column      },
 	{"toip_column",        PARAM_STR, &toip_column        },
 	{"fromtag_column",     PARAM_STR, &fromtag_column     },
+	{"totag_column",       PARAM_STR, &totag_column       },
 	{"direction_column",   PARAM_STR, &direction_column   },
 	{"trace_flag",         INT_PARAM, &trace_flag           },
 	{"trace_on",           INT_PARAM, &trace_on             },
@@ -463,6 +465,12 @@ static int child_init(int rank)
 			LM_ERR("unable to connect to database. Please check configuration.\n");
 			return -1;
 		}
+		if (db_check_table_version(&db_funcs, db_con, &siptrace_table,
+					   SIP_TRACE_TABLE_VERSION) < 0) {
+			LM_ERR("error during table version check\n");
+			db_funcs.close(db_con);		
+			return -1;
+		}
 	}
 
 	return 0;
@@ -809,6 +817,11 @@ static int sip_trace_store_db(struct _siptrace_data *sto)
 	db_vals[10].nul = 0;
 	db_vals[10].val.int_val = sto->tv.tv_usec;
 
+	db_keys[11] = &totag_column;
+	db_vals[11].type = DB1_STR;
+	db_vals[11].nul = 0;
+	db_vals[11].val.str_val = sto->totag;
+
 	db_funcs.use_table(db_con, siptrace_get_table());
 
 	if(trace_on_flag!=NULL && *trace_on_flag!=0) {
@@ -1025,6 +1038,7 @@ static int sip_trace(struct sip_msg *msg, struct dest_info * dst, char *dir)
 	}
 
 	sto.fromtag = get_from(msg)->tag_value;
+	sto.totag = get_to(msg)->tag_value;
 
 #ifdef STATISTICS
 	if(msg->first_line.type==SIP_REPLY) {
@@ -1210,6 +1224,7 @@ static void trace_onreq_out(struct cell* t, int type, struct tmcb_params *ps)
 	sto.dir = "out";
 
 	sto.fromtag = get_from(msg)->tag_value;
+	sto.totag = get_to(msg)->tag_value;
 
 #ifdef STATISTICS
 	sto.stat = siptrace_req;
@@ -1282,6 +1297,7 @@ static void trace_onreply_in(struct cell* t, int type, struct tmcb_params *ps)
 	sto.dir = "in";
 
 	sto.fromtag = get_from(msg)->tag_value;
+	sto.totag = get_to(msg)->tag_value;
 #ifdef STATISTICS
 	sto.stat = siptrace_rpl;
 #endif
@@ -1390,6 +1406,7 @@ static void trace_onreply_out(struct cell* t, int type, struct tmcb_params *ps)
 
 	sto.dir = "out";
 	sto.fromtag = get_from(msg)->tag_value;
+	sto.totag = get_to(msg)->tag_value;
 
 #ifdef STATISTICS
 	sto.stat = siptrace_rpl;
@@ -1476,6 +1493,7 @@ static void trace_sl_onreply_out(sl_cbp_t *slcbp)
 
 	sto.dir = "out";
 	sto.fromtag = get_from(msg)->tag_value;
+	sto.totag = get_to(msg)->tag_value;
 
 #ifdef STATISTICS
 	sto.stat = siptrace_rpl;
diff --git a/modules/siputils/README b/modules/siputils/README
index 978d0c4..e7caca1 100644
--- a/modules/siputils/README
+++ b/modules/siputils/README
@@ -40,7 +40,7 @@ Edited by
 
 Gabriel Vasile
 
-   Copyright � 2008, 2005, 2003 1&1 Internet AG, FhG Fokus, Voice Sistem
+   Copyright (c) 2008, 2005, 2003 1&1 Internet AG, FhG Fokus, Voice Sistem
    SRL
      __________________________________________________________________
 
@@ -79,21 +79,23 @@ Gabriel Vasile
               4.9. tel2sip(uri, hostpart, result)
               4.10. is_e164(pseudo-variable)
               4.11. is_uri_user_e164(pseudo-variable)
-              4.12. encode_contact(encoding_prefix,hostpart)
-              4.13. decode_contact()
-              4.14. decode_contact_header()
-              4.15. cmp_uri(str1, str2)
-              4.16. cmp_aor(str1, str2)
-              4.17. append_rpid_hf()
-              4.18. append_rpid_hf(prefix, suffix)
-              4.19. is_rpid_user_e164()
-              4.20. set_uri_user(uri, user)
-              4.21. set_uri_host(uri, host)
-              4.22. is_request()
-              4.23. is_reply()
-              4.24. is_gruu([uri])
-              4.25. is_supported(option)
-              4.26. is_first_hop()
+              4.12. is_tel_number(tval)
+              4.13. is_numeric(tval)
+              4.14. encode_contact(encoding_prefix,hostpart)
+              4.15. decode_contact()
+              4.16. decode_contact_header()
+              4.17. cmp_uri(str1, str2)
+              4.18. cmp_aor(str1, str2)
+              4.19. append_rpid_hf()
+              4.20. append_rpid_hf(prefix, suffix)
+              4.21. is_rpid_user_e164()
+              4.22. set_uri_user(uri, user)
+              4.23. set_uri_host(uri, host)
+              4.24. is_request()
+              4.25. is_reply()
+              4.26. is_gruu([uri])
+              4.27. is_supported(option)
+              4.28. is_first_hop()
 
    List of Examples
 
@@ -117,21 +119,23 @@ Gabriel Vasile
    1.18. tel2sip usage
    1.19. is_e164 usage
    1.20. is_uri_user_e164 usage
-   1.21. encode_contact usage
-   1.22. decode_contact usage
-   1.23. decode_contact_header usage
-   1.24. cmp_uri usage
-   1.25. cmp_aor usage
-   1.26. append_rpid_hf usage
-   1.27. append_rpid_hf(prefix, suffix) usage
-   1.28. is_rpid_user_e164 usage
-   1.29. set_uri_user usage
-   1.30. set_uri_host usage
-   1.31. is_request usage
-   1.32. is_reply usage
-   1.33. is_gruu() usage
-   1.34. is_supported() usage
-   1.35. is_first_hop() usage
+   1.21. is_tel_number usage
+   1.22. is_numeric usage
+   1.23. encode_contact usage
+   1.24. decode_contact usage
+   1.25. decode_contact_header usage
+   1.26. cmp_uri usage
+   1.27. cmp_aor usage
+   1.28. append_rpid_hf usage
+   1.29. append_rpid_hf(prefix, suffix) usage
+   1.30. is_rpid_user_e164 usage
+   1.31. set_uri_user usage
+   1.32. set_uri_host usage
+   1.33. is_request usage
+   1.34. is_reply usage
+   1.35. is_gruu() usage
+   1.36. is_supported() usage
+   1.37. is_first_hop() usage
 
 Chapter 1. Admin Guide
 
@@ -168,21 +172,23 @@ Chapter 1. Admin Guide
         4.9. tel2sip(uri, hostpart, result)
         4.10. is_e164(pseudo-variable)
         4.11. is_uri_user_e164(pseudo-variable)
-        4.12. encode_contact(encoding_prefix,hostpart)
-        4.13. decode_contact()
-        4.14. decode_contact_header()
-        4.15. cmp_uri(str1, str2)
-        4.16. cmp_aor(str1, str2)
-        4.17. append_rpid_hf()
-        4.18. append_rpid_hf(prefix, suffix)
-        4.19. is_rpid_user_e164()
-        4.20. set_uri_user(uri, user)
-        4.21. set_uri_host(uri, host)
-        4.22. is_request()
-        4.23. is_reply()
-        4.24. is_gruu([uri])
-        4.25. is_supported(option)
-        4.26. is_first_hop()
+        4.12. is_tel_number(tval)
+        4.13. is_numeric(tval)
+        4.14. encode_contact(encoding_prefix,hostpart)
+        4.15. decode_contact()
+        4.16. decode_contact_header()
+        4.17. cmp_uri(str1, str2)
+        4.18. cmp_aor(str1, str2)
+        4.19. append_rpid_hf()
+        4.20. append_rpid_hf(prefix, suffix)
+        4.21. is_rpid_user_e164()
+        4.22. set_uri_user(uri, user)
+        4.23. set_uri_host(uri, host)
+        4.24. is_request()
+        4.25. is_reply()
+        4.26. is_gruu([uri])
+        4.27. is_supported(option)
+        4.28. is_first_hop()
 
 1. Overview
 
@@ -369,23 +375,25 @@ modparam("auth", "rpid_avp", "$avp(myrpid)")
    4.9. tel2sip(uri, hostpart, result)
    4.10. is_e164(pseudo-variable)
    4.11. is_uri_user_e164(pseudo-variable)
-   4.12. encode_contact(encoding_prefix,hostpart)
-   4.13. decode_contact()
-   4.14. decode_contact_header()
-   4.15. cmp_uri(str1, str2)
-   4.16. cmp_aor(str1, str2)
-   4.17. append_rpid_hf()
-   4.18. append_rpid_hf(prefix, suffix)
-   4.19. is_rpid_user_e164()
-   4.20. set_uri_user(uri, user)
-   4.21. set_uri_host(uri, host)
-   4.22. is_request()
-   4.23. is_reply()
-   4.24. is_gruu([uri])
-   4.25. is_supported(option)
-   4.26. is_first_hop()
-
-4.1. ring_insert_callid()
+   4.12. is_tel_number(tval)
+   4.13. is_numeric(tval)
+   4.14. encode_contact(encoding_prefix,hostpart)
+   4.15. decode_contact()
+   4.16. decode_contact_header()
+   4.17. cmp_uri(str1, str2)
+   4.18. cmp_aor(str1, str2)
+   4.19. append_rpid_hf()
+   4.20. append_rpid_hf(prefix, suffix)
+   4.21. is_rpid_user_e164()
+   4.22. set_uri_user(uri, user)
+   4.23. set_uri_host(uri, host)
+   4.24. is_request()
+   4.25. is_reply()
+   4.26. is_gruu([uri])
+   4.27. is_supported(option)
+   4.28. is_first_hop()
+
+4.1.  ring_insert_callid()
 
    Inserting the call-id in the internal list, which is checked when
    further replies arrive. Any 183 reply that is received during the
@@ -402,7 +410,7 @@ modparam("auth", "rpid_avp", "$avp(myrpid)")
 ring_insert_callid();
 ...
 
-4.2. options_reply()
+4.2.  options_reply()
 
    This function checks if the request method is OPTIONS and if the
    request URI does not contain an username. If both is true the request
@@ -430,7 +438,7 @@ if (uri==myself) {
 }
 ...
 
-4.3. is_user(username)
+4.3.  is_user(username)
 
    Check if the username in credentials matches the given username.
 
@@ -446,7 +454,7 @@ if (is_user("john")) {
 };
 ...
 
-4.4. has_totag()
+4.4.  has_totag()
 
    Check if To header field uri contains tag parameter.
 
@@ -459,7 +467,7 @@ if (has_totag()) {
 };
 ...
 
-4.5. uri_param(param)
+4.5.  uri_param(param)
 
    Find if Request URI has a given parameter with no value
 
@@ -475,7 +483,7 @@ if (uri_param("param1")) {
 };
 ...
 
-4.6. uri_param(param,value)
+4.6.  uri_param(param,value)
 
    Find if Request URI has a given parameter with matching value
 
@@ -492,7 +500,7 @@ if (uri_param("param1","value1")) {
 };
 ...
 
-4.7. add_uri_param(param)
+4.7.  add_uri_param(param)
 
    Add to RURI a parameter (name=value);
 
@@ -506,7 +514,7 @@ if (uri_param("param1","value1")) {
 add_uri_param("nat=yes");
 ...
 
-4.8. get_uri_param(name, var)
+4.8.  get_uri_param(name, var)
 
    Get the value of RURI parameter.
 
@@ -521,7 +529,7 @@ add_uri_param("nat=yes");
 get_uri_param("nat", "$var(nat)");
 ...
 
-4.9. tel2sip(uri, hostpart, result)
+4.9.  tel2sip(uri, hostpart, result)
 
    Converts URI in first param (pseudo variable or string) to SIP URI, if
    it is a tel URI. If conversion was done, writes resulting SIP URI to
@@ -553,7 +561,7 @@ tel2sip("$ru", $fd", "$ru");
 # $ru:  sip:+12345678;ext=200;isub=+123-456 at foo.com;user=phone
 ...
 
-4.10. is_e164(pseudo-variable)
+4.10.  is_e164(pseudo-variable)
 
    Checks if string value of pseudo variable argument is an E164 number.
 
@@ -571,7 +579,7 @@ if (is_e164("$avp(i:705)") {
 };
 ...
 
-4.11. is_uri_user_e164(pseudo-variable)
+4.11.  is_uri_user_e164(pseudo-variable)
 
    Checks if userpart of URI stored in pseudo variable is E164 number.
 
@@ -588,7 +596,38 @@ if (is_uri_user_e164("$avp(i:705)") {
 };
 ...
 
-4.12. encode_contact(encoding_prefix,hostpart)
+4.12.  is_tel_number(tval)
+
+   Checks if the parameter value is a telephone number: starting with one
+   optional +, followed by digits. The parameter can include variables.
+
+   This function can be used from ANY_ROUTE.
+
+   Example 1.21. is_tel_number usage
+...
+if (is_tel_number("$rU")) {  # Test if R-URI user is telephone number
+   ...
+}
+if (is_tel_number("+24242424") {
+   ...
+}
+...
+
+4.13.  is_numeric(tval)
+
+   Checks if the parameter value consists solely of decimal digits. The
+   parameter can include variables.
+
+   This function can be used from ANY_ROUTE.
+
+   Example 1.22. is_numeric usage
+...
+if (is_numeric($rU)) {  # Test if R-URI user consists of decimal digits
+   ...
+}
+...
+
+4.14.  encode_contact(encoding_prefix,hostpart)
 
    This function will encode uri-s inside Contact header in the following
    manner sip:username:password at ip:port;transport=protocol goes
@@ -610,12 +649,12 @@ if (is_uri_user_e164("$avp(i:705)") {
 
    This function can be used from REQUEST_ROUTE, ONREPLY_ROUTE.
 
-   Example 1.21. encode_contact usage
+   Example 1.23. encode_contact usage
 ...
 if (src_ip == 10.0.0.0/8) encode_contact("natted_client","1.2.3.4");
 ...
 
-4.13. decode_contact()
+4.15.  decode_contact()
 
    This function will decode the request URI. If the RURI is in the format
    sip:encoding_prefix*username*ip*port*protocol at hostpart it will be
@@ -628,12 +667,12 @@ if (src_ip == 10.0.0.0/8) encode_contact("natted_client","1.2.3.4");
 
    This function can be used from REQUEST_ROUTE.
 
-   Example 1.22. decode_contact usage
+   Example 1.24. decode_contact usage
 ...
 if (uri =~ "^sip:natted_client") { decode_contact(); }
 ...
 
-4.14. decode_contact_header()
+4.16.  decode_contact_header()
 
    This function will decode URIs inside Contact header. If the URI in the
    format sip:encoding_prefix*username*ip*port*protocol at hostpart it will
@@ -646,7 +685,7 @@ if (uri =~ "^sip:natted_client") { decode_contact(); }
 
    This function can be used from REQUEST_ROUTE, ONREPLY_ROUTE.
 
-   Example 1.23. decode_contact_header usage
+   Example 1.25. decode_contact_header usage
 ...
 reply_route[2] {
         ...
@@ -655,13 +694,13 @@ reply_route[2] {
 }
 ...
 
-4.15. cmp_uri(str1, str2)
+4.17.  cmp_uri(str1, str2)
 
    The function returns true if the two parameters matches as SIP URI.
 
    This function can be used from ANY_ROUTE.
 
-   Example 1.24. cmp_uri usage
+   Example 1.26. cmp_uri usage
 ...
 if(cmp_uri("$ru", "sip:kamailio at kamailio.org"))
 {
@@ -669,14 +708,14 @@ if(cmp_uri("$ru", "sip:kamailio at kamailio.org"))
 }
 ...
 
-4.16. cmp_aor(str1, str2)
+4.18.  cmp_aor(str1, str2)
 
    The function returns true if the two parameters matches as AoR. The
    parameters have to be SIP URIs.
 
    This function can be used from ANY_ROUTE.
 
-   Example 1.25. cmp_aor usage
+   Example 1.27. cmp_aor usage
 ...
 if(cmp_aor("$rU at KaMaIlIo.org", "sip:kamailio@$fd"))
 {
@@ -684,7 +723,7 @@ if(cmp_aor("$rU at KaMaIlIo.org", "sip:kamailio@$fd"))
 }
 ...
 
-4.17. append_rpid_hf()
+4.19.  append_rpid_hf()
 
    Appends to the message a Remote-Party-ID header that contains header
    'Remote-Party-ID: ' followed by the saved value of the SIP URI received
@@ -695,14 +734,14 @@ if(cmp_aor("$rU at KaMaIlIo.org", "sip:kamailio@$fd"))
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE,
    BRANCH_ROUTE.
 
-   Example 1.26. append_rpid_hf usage
+   Example 1.28. append_rpid_hf usage
 ...
 append_rpid_hf();  # Append Remote-Party-ID header field
 ...
 
-4.18. append_rpid_hf(prefix, suffix)
+4.20.  append_rpid_hf(prefix, suffix)
 
-   This function is the same as Section 4.17, " append_rpid_hf()". The
+   This function is the same as Section 4.19, " append_rpid_hf()". The
    only difference is that it accepts two parameters--prefix and suffix to
    be added to Remote-Party-ID header field. This function ignores
    rpid_prefix and rpid_suffix parameters, instead of that allows to set
@@ -719,13 +758,13 @@ append_rpid_hf();  # Append Remote-Party-ID header field
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE,
    BRANCH_ROUTE.
 
-   Example 1.27. append_rpid_hf(prefix, suffix) usage
+   Example 1.29. append_rpid_hf(prefix, suffix) usage
 ...
 # Append Remote-Party-ID header field
 append_rpid_hf("", ";party=calling;id-type=subscriber;screen=yes");
 ...
 
-4.19. is_rpid_user_e164()
+4.21.  is_rpid_user_e164()
 
    The function checks if the SIP URI received from the database or radius
    server and will potentially be used in Remote-Party-ID header field
@@ -735,68 +774,68 @@ append_rpid_hf("", ";party=calling;id-type=subscriber;screen=yes");
 
    This function can be used from REQUEST_ROUTE.
 
-   Example 1.28. is_rpid_user_e164 usage
+   Example 1.30. is_rpid_user_e164 usage
 ...
 if (is_rpid_user_e164()) {
     # do something here
 };
 ...
 
-4.20. set_uri_user(uri, user)
+4.22.  set_uri_user(uri, user)
 
    Sets userpart of SIP URI stored in writable pseudo variable 'uri' to
    value of pseudo variable 'user'.
 
    This function can be used from ANY_ROUTE.
 
-   Example 1.29. set_uri_user usage
+   Example 1.31. set_uri_user usage
 ...
 $var(uri) = "sip:user at host";
 $var(user) = "new_user";
 set_uri_user("$var(uri)", "$var(user)");
 ...
 
-4.21. set_uri_host(uri, host)
+4.23.  set_uri_host(uri, host)
 
    Sets hostpart of SIP URI stored in writable pseudo variable 'uri' to
    value of pseudo variable 'host'.
 
    This function can be used from ANY_ROUTE.
 
-   Example 1.30. set_uri_host usage
+   Example 1.32. set_uri_host usage
 ...
 $var(uri) = "sip:user at host";
 $var(host) = "new_host";
 set_uri_host("$var(uri)", "$var(host)");
 ...
 
-4.22. is_request()
+4.24.  is_request()
 
    Return true if the SIP message is a request.
 
    This function can be used from ANY_ROUTE.
 
-   Example 1.31. is_request usage
+   Example 1.33. is_request usage
 ...
 if (is_request()) {
         ...
 }
 ...
 
-4.23. is_reply()
+4.25.  is_reply()
 
    Return true if the SIP message is a reply.
 
    This function can be used from ANY_ROUTE.
 
-   Example 1.32. is_reply usage
+   Example 1.34. is_reply usage
 ...
 if (is_reply()) {
         ...
 }
 ...
 
-4.24. is_gruu([uri])
+4.26.  is_gruu([uri])
 
    The function returns true if the uri is GRUU ('gr' parameter is
    present): 1 - pub-gruu; 2 - temp-gruu.
@@ -807,12 +846,12 @@ if (is_reply()) {
 
    This function can be used from ANY_ROUTE.
 
-   Example 1.33. is_gruu() usage
+   Example 1.35. is_gruu() usage
 ...
 if(is_gruu()) { ... }
 ...
 
-4.25. is_supported(option)
+4.27.  is_supported(option)
 
    Function returns true if given option is listed in Supported header(s)
    (if any) of the request. Currently the following options are known:
@@ -820,12 +859,12 @@ if(is_gruu()) { ... }
 
    This function can be used from ANY_ROUTE.
 
-   Example 1.34. is_supported() usage
+   Example 1.36. is_supported() usage
 ...
 if (is_supported("outbound")) { ... }
 ...
 
-4.26. is_first_hop()
+4.28.  is_first_hop()
 
    The function returns true if the proxy is first hop after the original
    sender. For incoming SIP requests, it means there is only one Via
@@ -837,7 +876,7 @@ if (is_supported("outbound")) { ... }
 
    This function can be used from ANY_ROUTE.
 
-   Example 1.35. is_first_hop() usage
+   Example 1.37. is_first_hop() usage
 ...
 if(is_first_hop()) { ... }
 ...
diff --git a/modules/siputils/checks.c b/modules/siputils/checks.c
index f265c38..9a53010 100644
--- a/modules/siputils/checks.c
+++ b/modules/siputils/checks.c
@@ -1,20 +1,18 @@
 /*
- * $Id$
- *
  * Various URI checks and URI manipulation
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * Copyright (C) 2004-2010 Juha Heinanen
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -23,11 +21,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2003-02-26: Created by janakj
- * 2004-03-20: has_totag introduced (jiri)
- * 2004-04-14: uri_param and add_uri_param introduced (jih)
  */
 
 /*!
@@ -52,6 +45,7 @@
 #include "../../pvar.h"
 #include "../../lvalue.h"
 #include "../../sr_module.h"
+#include "../../mod_fix.h"
 #include "checks.h"
 
 /**
@@ -725,3 +719,63 @@ found:
 	return 1;
 }
 
+
+/*
+ * Check if the parameter is a valid telephone number
+ * - optional leading + followed by digits only
+ */
+int is_tel_number(sip_msg_t *msg, char *_sp, char* _s2)
+{
+    str tval = {0, 0};
+    int i;
+
+    if(fixup_get_svalue(msg, (gparam_t*)_sp, &tval)!=0)
+	{
+		LM_ERR("cannot get parameter value\n");
+		return -1;
+	}
+	if(tval.len<1)
+		return -2;
+
+	i = 0;
+	if(tval.s[0]=='+') {
+		if(tval.len<2)
+			return -2;
+		if(tval.s[1]<'1' || tval.s[1]>'9')
+			return -2;
+		i = 2;
+	}
+
+	for(; i<tval.len; i++) {
+		if(tval.s[i]<'0' || tval.s[i]>'9')
+			return -2;
+	}
+
+	return 1;
+}
+
+
+/*
+ * Check if the parameter contains decimal digits only
+ */
+int is_numeric(sip_msg_t *msg, char *_sp, char* _s2)
+{
+    str tval = {0, 0};
+    int i;
+
+    if(fixup_get_svalue(msg, (gparam_t*)_sp, &tval)!=0)
+	{
+		LM_ERR("cannot get parameter value\n");
+		return -1;
+	}
+	if(tval.len<=0)
+		return -2;
+
+	i = 0;
+	for(; i<tval.len; i++) {
+		if(tval.s[i]<'0' || tval.s[i]>'9')
+			return -2;
+	}
+
+	return 1;
+}
diff --git a/modules/siputils/checks.h b/modules/siputils/checks.h
index bc1a99a..f4c9c64 100644
--- a/modules/siputils/checks.h
+++ b/modules/siputils/checks.h
@@ -1,18 +1,16 @@
 /*
- * $Id$
- *
  * Various URI checks
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -21,10 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2003-03-26 created by janakj
- * 2004-04-14 uri_param and add_uri_param introduced (jih)
  */
 
 /*!
@@ -117,4 +111,14 @@ int w_is_reply(struct sip_msg* msg, char *foo, char *bar);
  */
 int get_uri_param(struct sip_msg* _msg, char* _param, char* _value);
 
+/*
+ * Check if parameter value has a telephone number format
+ */
+int is_tel_number(sip_msg_t *msg, char *_sp, char* _s2);
+
+/*
+ * Check if parameter value consists solely of decimal digits
+ */
+int is_numeric(sip_msg_t *msg, char *_sp, char* _s2);
+
 #endif /* CHECKS_H */
diff --git a/modules/siputils/config.c b/modules/siputils/config.c
index df837b6..0c68dcf 100644
--- a/modules/siputils/config.c
+++ b/modules/siputils/config.c
@@ -1,13 +1,12 @@
 /*
- * $Id$
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -16,9 +15,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History
- * -------
- *  2008-02-05	adapting tm module for the configuration framework (Miklos)
  */
 
 /*!
diff --git a/modules/siputils/config.h b/modules/siputils/config.h
index 7635ac7..2bc4050 100644
--- a/modules/siputils/config.h
+++ b/modules/siputils/config.h
@@ -1,14 +1,19 @@
-/*
- * $Id$
+/* This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
  */
 
 /*!
diff --git a/modules/siputils/contact_ops.c b/modules/siputils/contact_ops.c
index 232e752..6039785 100644
--- a/modules/siputils/contact_ops.c
+++ b/modules/siputils/contact_ops.c
@@ -1,29 +1,24 @@
 /*
- * $Id$
- *
  * mangler module
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2003-04-07 first version.  
  */
 
 /*!
diff --git a/modules/siputils/contact_ops.h b/modules/siputils/contact_ops.h
index 4648e0d..48a9405 100644
--- a/modules/siputils/contact_ops.h
+++ b/modules/siputils/contact_ops.h
@@ -1,29 +1,24 @@
 /*
- * $Id$
- *
  *  mangler module
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2003-04-07 first version.  
  */
 
 /*!
diff --git a/modules/siputils/doc/siputils_admin.xml b/modules/siputils/doc/siputils_admin.xml
index eefb56c..fea60a2 100644
--- a/modules/siputils/doc/siputils_admin.xml
+++ b/modules/siputils/doc/siputils_admin.xml
@@ -608,6 +608,55 @@ if (is_uri_user_e164("$avp(i:705)") {
 		</example>
 	</section>
 
+	<section id="siputils.f.is_tel_number">
+		<title>
+		<function moreinfo="none">is_tel_number(tval)</function>
+		</title>
+		<para>
+			Checks if the parameter value is a telephone number: starting with
+			one optional +, followed by digits. The parameter can include
+			variables.
+		</para>
+		<para>
+		This function can be used from ANY_ROUTE.
+		</para>
+		<example>
+		<title><function>is_tel_number</function> usage</title>
+		<programlisting format="linespecific">
+...
+if (is_tel_number("$rU")) {  # Test if R-URI user is telephone number
+   ...
+}
+if (is_tel_number("+24242424") {
+   ...
+}
+...
+</programlisting>
+		</example>
+	</section>
+
+	<section id="siputils.f.is_numeric">
+		<title>
+		<function moreinfo="none">is_numeric(tval)</function>
+		</title>
+		<para>
+		  Checks if the parameter value consists solely of decimal digits. The parameter can include variables.
+		</para>
+		<para>
+		This function can be used from ANY_ROUTE.
+		</para>
+		<example>
+		<title><function>is_numeric</function> usage</title>
+		<programlisting format="linespecific">
+...
+if (is_numeric($rU)) {  # Test if R-URI user consists of decimal digits
+   ...
+}
+...
+</programlisting>
+		</example>
+	</section>
+
 	<section id="siputils.f.encode_contact">
 		<title>
 		<function moreinfo="none">encode_contact(encoding_prefix,hostpart)</function>
diff --git a/modules/siputils/options.c b/modules/siputils/options.c
index 9467d7e..b7b7e29 100644
--- a/modules/siputils/options.c
+++ b/modules/siputils/options.c
@@ -1,18 +1,16 @@
 /*
- * $Id$
- *
  * Options Reply Module
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -21,9 +19,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * -------
- * 2003-11-11: build_lump_rpl() removed, add_lump_rpl() has flags (bogdan)
  */
 
 /*!
diff --git a/modules/siputils/options.h b/modules/siputils/options.h
index 3b22674..9fe0c63 100644
--- a/modules/siputils/options.h
+++ b/modules/siputils/options.h
@@ -1,18 +1,16 @@
 /*
- * $Id$
- *
  * Options Reply Module
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -20,8 +18,10 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
  */
 
+
 /*!
  * \file siputils/options.c
  * \brief SIP-utils :: Options reply modules
diff --git a/modules/siputils/ring.c b/modules/siputils/ring.c
index aac80d4..a6b6919 100644
--- a/modules/siputils/ring.c
+++ b/modules/siputils/ring.c
@@ -1,25 +1,25 @@
 /*
- * $Id$
- *
  * Copyright (C) 2008-2009 1&1 Internet AG
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
  */
 
+
 /**
  * \file
  * \brief SIP-utils :: Only allow one 183 message per call-id
diff --git a/modules/siputils/ring.h b/modules/siputils/ring.h
index 92d84d3..18fa628 100644
--- a/modules/siputils/ring.h
+++ b/modules/siputils/ring.h
@@ -1,23 +1,22 @@
 /*
- * $Id$
- *
  * Copyright (C) 2008-2009 1&1 Internet AG
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
  */
 
 /**
diff --git a/modules/siputils/rpid.c b/modules/siputils/rpid.c
index 98cd1d2..3d5259b 100644
--- a/modules/siputils/rpid.c
+++ b/modules/siputils/rpid.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,10 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2003-04-28 rpid contributed by Juha Heinanen added (janakj)
- * 2005-05-31 general avp specification added for rpid (bogdan)
  */
 
 /*!
diff --git a/modules/siputils/rpid.h b/modules/siputils/rpid.h
index 3f1f43b..77f726f 100644
--- a/modules/siputils/rpid.h
+++ b/modules/siputils/rpid.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,10 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2003-04-28 rpid contributed by Juha Heinanen added (janakj)
- * 2005-05-31 general avp specification added for rpid (bogdan)
  */
 
 /*!
diff --git a/modules/siputils/sipops.c b/modules/siputils/sipops.c
index f5517ab..9750f71 100644
--- a/modules/siputils/sipops.c
+++ b/modules/siputils/sipops.c
@@ -1,24 +1,22 @@
 /*
- * $Id: utils.h 5318 2008-12-08 16:38:47Z henningw $
- *
  * SIPUTILS mangler module
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
  */
diff --git a/modules/siputils/sipops.h b/modules/siputils/sipops.h
index a936ea8..ac7b9f8 100644
--- a/modules/siputils/sipops.h
+++ b/modules/siputils/sipops.h
@@ -1,24 +1,22 @@
 /*
- * $Id: utils.h 5318 2008-12-08 16:38:47Z henningw $
- *
  * SIPUTILS mangler module
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
  */
diff --git a/modules/siputils/siputils.c b/modules/siputils/siputils.c
index 4ae73b0..b6358ad 100644
--- a/modules/siputils/siputils.c
+++ b/modules/siputils/siputils.c
@@ -1,24 +1,23 @@
 /*
- * $Id$
- *
  * Copyright (C) 2008-2009 1&1 Internet AG
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
  */
 
 /*!
@@ -31,7 +30,6 @@
 /*!
  * \defgroup siputils SIPUTILS :: Various SIP message handling functions
  *
- * \note A Kamailio module (modules_k)
  *
    This module implement various functions and checks related to
    SIP message handling and URI handling.
@@ -175,6 +173,10 @@ static cmd_export_t cmds[]={
 		0, ANY_ROUTE},
 	{"is_first_hop",  (cmd_function)w_is_first_hop,                    0, 0,
 		0, ANY_ROUTE},
+	{"is_tel_number", (cmd_function)is_tel_number,           1, fixup_spve_null,
+		0, ANY_ROUTE},
+	{"is_numeric", (cmd_function)is_numeric,                 1, fixup_spve_null,
+		0, ANY_ROUTE},
 	{0,0,0,0,0,0}
 };
 
diff --git a/modules/siputils/siputils.h b/modules/siputils/siputils.h
index f2628e3..f8b9d79 100644
--- a/modules/siputils/siputils.h
+++ b/modules/siputils/siputils.h
@@ -1,23 +1,22 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
  */
 
 
diff --git a/modules/siputils/utils.c b/modules/siputils/utils.c
index 8a2bd7c..8b39ae5 100644
--- a/modules/siputils/utils.c
+++ b/modules/siputils/utils.c
@@ -1,31 +1,27 @@
 /*
- * $Id$
- *
  * mangler module
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2003-04-07 first version.  
  */
 
+
 /*!
  * \file
  * \brief SIP-utils :: Mangler
diff --git a/modules/siputils/utils.h b/modules/siputils/utils.h
index c965860..1f99ed9 100644
--- a/modules/siputils/utils.h
+++ b/modules/siputils/utils.h
@@ -1,29 +1,24 @@
 /*
- * $Id$
- *
  * Sdp mangler module
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2003-04-07 first version.  
  */
 
 /*!
diff --git a/modules/sl/Makefile b/modules/sl/Makefile
index 65109c5..4af62f6 100644
--- a/modules/sl/Makefile
+++ b/modules/sl/Makefile
@@ -1,6 +1,5 @@
-# $Id$
 #
-# example module makefile
+# sl module makefile
 #
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
diff --git a/modules/sl/sl.c b/modules/sl/sl.c
index 27c30e8..12db27c 100644
--- a/modules/sl/sl.c
+++ b/modules/sl/sl.c
@@ -1,23 +1,16 @@
 /*
- * $Id$
- *
  * sl module - stateless reply
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -26,15 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/*
- * History:
- * --------
- *  2003-03-11  updated to the new module exports interface (andrei)
- *  2003-03-16  flags export parameter added (janakj)
- *  2003-03-19  all mallocs/frees replaced w/ pkg_malloc/pkg_free
- *  2005-03-01  force for stateless replies the incoming interface of
- *              the request (bogdan)
- */
 
 /**
  * @file
diff --git a/modules/sl/sl.h b/modules/sl/sl.h
index e4a7c02..063c32f 100644
--- a/modules/sl/sl.h
+++ b/modules/sl/sl.h
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2006 FhG FOKUS
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/modules/sl/sl_funcs.c b/modules/sl/sl_funcs.c
index bfaa76f..a65a7b8 100644
--- a/modules/sl/sl_funcs.c
+++ b/modules/sl/sl_funcs.c
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,23 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
- /*
-  * History:
-  * -------
-  * 2003-02-11  modified sl_send_reply to use the transport independent
-  *              msg_send  (andrei)
-  * 2003-02-18  replaced TOTAG_LEN w/ TOTAG_VALUE_LEN (it was defined twice
-  *              w/ different values!)  (andrei)
-  * 2003-03-06  aligned to request2response use of tag bookmarks (jiri)
-  * 2003-04-04  modified sl_send_reply to use src_port if rport is present
-  *              in the topmost via (andrei)
-  * 2003-09-11: updated to new build_lump_rpl() interface (bogdan)
-  * 2003-09-11: sl_tag converted to str to fit to the new
-  *               build_res_buf_from_sip_req() interface (bogdan)
-  * 2003-11-11: build_lump_rpl() removed, add_lump_rpl() has flags (bogdan)
-  * 2004-10-10: use of mhomed disabled for replies (jiri)
-  */
-
 
 #include "../../globals.h"
 #include "../../forward.h"
diff --git a/modules/sl/sl_funcs.h b/modules/sl/sl_funcs.h
index 7dc5b65..4928fc9 100644
--- a/modules/sl/sl_funcs.h
+++ b/modules/sl/sl_funcs.h
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/modules/sl/sl_stats.c b/modules/sl/sl_stats.c
index f76211f..df4edd2 100644
--- a/modules/sl/sl_stats.c
+++ b/modules/sl/sl_stats.c
@@ -1,23 +1,14 @@
 /*
- *
- * $Id$
- *
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/modules/sl/sl_stats.h b/modules/sl/sl_stats.h
index 32ea552..a5983e2 100644
--- a/modules/sl/sl_stats.h
+++ b/modules/sl/sl_stats.h
@@ -1,24 +1,14 @@
 /*
- *
- * $Id$
- *
- *
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/modules/sms/Makefile b/modules/sms/Makefile
index 775e73c..97da1d0 100644
--- a/modules/sms/Makefile
+++ b/modules/sms/Makefile
@@ -1,6 +1,5 @@
-# $Id$
 #
-# example module makefile
+# sms module makefile
 #
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
diff --git a/modules/sms/libsms_sms.h b/modules/sms/libsms_sms.h
index 3582c7c..2d4c5b6 100644
--- a/modules/sms/libsms_sms.h
+++ b/modules/sms/libsms_sms.h
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/modules/sms/sms.c b/modules/sms/sms.c
index d31aeb4..f2b1566 100644
--- a/modules/sms/sms.c
+++ b/modules/sms/sms.c
@@ -1,22 +1,14 @@
 /*
- * $Id$
- *
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -25,17 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/*
- * History:
- * --------
- *  2003-03-11  updated to the new module exports interface (andrei)
- *  2003-03-16  flags export parameter added (janakj)
- *  2003-03-19  all mallocs/frees replaced w/ pkg_malloc/pkg_free (andrei)
- *  2003-04-02  port_no_str does not contain a leading ':' anymore (andrei)
- *  2003-04-06  Only child 1 will execute child init (janakj)
- *  2003-10-24  updated to the new socket_info lists (andrei)
- */
-
 
 #include <stdio.h>
 #include <string.h>
diff --git a/modules/sms/sms_funcs.c b/modules/sms/sms_funcs.c
index 5a2548b..8f25136 100644
--- a/modules/sms/sms_funcs.c
+++ b/modules/sms/sms_funcs.c
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -25,17 +18,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-/*
- * History:
- * --------
- * 2003-01-23: switched from t_uac to t_uac_dlg, adapted to new way of
- *              parsing for Content-Type (bogdan)
- * 2003-02-28: protocolization of t_uac_dlg completed (jiri)
- * 2003-08-05: adapted to the new parse_content_type_hdr function (bogdan)
- * 2003-09-11: updated to new build_lump_rpl() interface (bogdan)
- * 2003-09-11: force parsing to hdr when extracting destination user (bogdan)
- */
-
 #include <unistd.h>
 #include <errno.h>
 #include <stdlib.h>
diff --git a/modules/sms/sms_funcs.h b/modules/sms/sms_funcs.h
index 86fe69f..abf65e7 100644
--- a/modules/sms/sms_funcs.h
+++ b/modules/sms/sms_funcs.h
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/modules/sms/sms_report.c b/modules/sms/sms_report.c
index 4cf9ca3..0aeb1a5 100644
--- a/modules/sms/sms_report.c
+++ b/modules/sms/sms_report.c
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/modules/sms/sms_report.h b/modules/sms/sms_report.h
index 0ca2dbc..3160c13 100644
--- a/modules/sms/sms_report.h
+++ b/modules/sms/sms_report.h
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/modules/snmpstats/Makefile b/modules/snmpstats/Makefile
index ea986ac..48463a0 100644
--- a/modules/snmpstats/Makefile
+++ b/modules/snmpstats/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # WARNING: do not run this directly, it should be run by the master Makefile
 
diff --git a/modules/snmpstats/alarm_checks.c b/modules/snmpstats/alarm_checks.c
index 8a5e94d..9002cea 100644
--- a/modules/snmpstats/alarm_checks.c
+++ b/modules/snmpstats/alarm_checks.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * SNMPStats Module 
  * Copyright (C) 2006 SOMA Networks, INC.
  * Written by: Jeffrey Magder (jmagder at somanetworks.com)
@@ -22,18 +20,15 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
  * USA
  *
- * History:
- * --------
- * 2006-11-23 initial version (jmagder)
- * 
- * This file groups together alarm checking and handling
  */
 
 /*!
  *\file
  * \brief SNMP statistic module
+ * This file groups together alarm checking and handling
  * \ingroup snmpstats
  * - Module: \ref snmpstats
+ * \author jmagder
  */
 
 #include <signal.h>
diff --git a/modules/snmpstats/alarm_checks.h b/modules/snmpstats/alarm_checks.h
index 645e5be..fa69292 100644
--- a/modules/snmpstats/alarm_checks.h
+++ b/modules/snmpstats/alarm_checks.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * SNMPStats Module 
  * Copyright (C) 2006 SOMA Networks, INC.
  * Written by: Jeffrey Magder (jmagder at somanetworks.com)
@@ -22,10 +20,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
  * USA
  *
- * History:
- * --------
- * 2006-11-23 initial version (jmagder)
- *
  * This file groups together alarm checking and handling
  */
 
diff --git a/modules/snmpstats/hashTable.c b/modules/snmpstats/hashTable.c
index 24ec242..69caf34 100644
--- a/modules/snmpstats/hashTable.c
+++ b/modules/snmpstats/hashTable.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * SNMPStats Module 
  * Copyright (C) 2006 SOMA Networks, INC.
  * Written by: Jeffrey Magder (jmagder at somanetworks.com)
@@ -22,16 +20,13 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
  * USA
  *
- * History:
- * --------
- * 2006-11-23 initial version (jmagder)
- *
- * Hash Stuff;
  */
 
 /*!
  * \file
  * \brief SNMP statistic module, hash table
+ * Hash Stuff;
+ * \author jmagder
  *
  * For an overview of its structures, please see hashTable.h
  *
@@ -170,7 +165,6 @@ void deleteUser(hashSlot_t *theTable, char *aor, int hashTableSize)
 	int hashIndex = calculateHashSlot(aor, hashTableSize);
 	int searchStringLength = strlen(aor);
 
-	aorToIndexStruct_t *previousRecord = theTable[hashIndex].first;
 	aorToIndexStruct_t *currentRecord  = theTable[hashIndex].first;
 
 	while (currentRecord != NULL) {
@@ -232,7 +226,6 @@ void deleteUser(hashSlot_t *theTable, char *aor, int hashTableSize)
 		}
 
 		/* Advance to the next records. */
-		previousRecord = currentRecord;
 		currentRecord = currentRecord->next;
 	}
 
diff --git a/modules/snmpstats/hashTable.h b/modules/snmpstats/hashTable.h
index 94cce2c..0389c4c 100644
--- a/modules/snmpstats/hashTable.h
+++ b/modules/snmpstats/hashTable.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * SNMPStats Module 
  * Copyright (C) 2006 SOMA Networks, INC.
  * Written by: Jeffrey Magder (jmagder at somanetworks.com)
@@ -22,9 +20,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
  * USA
  *
- * History:
- * --------
- * 2006-11-23 initial version (jmagder)
  */
 
 /*!
diff --git a/modules/snmpstats/interprocess_buffer.c b/modules/snmpstats/interprocess_buffer.c
index 8f513c0..3f00978 100644
--- a/modules/snmpstats/interprocess_buffer.c
+++ b/modules/snmpstats/interprocess_buffer.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * SNMPStats Module 
  * Copyright (C) 2006 SOMA Networks, INC.
  * Written by: Jeffrey Magder (jmagder at somanetworks.com)
@@ -22,14 +20,12 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
  * USA
  *
- * History:
- * --------
- * 2006-11-23 initial version (jmagder)
  */
 
 /*!
  * \file
  * \brief SNMP statistic module, interprocess buffer
+ * \author jmagder
  *
  * This file implements the interprocess buffer, used for marshalling data
  * exchange from the usrloc module to the kamailioSIPRegUserTable,
diff --git a/modules/snmpstats/interprocess_buffer.h b/modules/snmpstats/interprocess_buffer.h
index 90cba58..12ad49a 100644
--- a/modules/snmpstats/interprocess_buffer.h
+++ b/modules/snmpstats/interprocess_buffer.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * SNMPStats Module 
  * Copyright (C) 2006 SOMA Networks, INC.
  * Written by: Jeffrey Magder (jmagder at somanetworks.com)
@@ -22,9 +20,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
  * USA
  *
- * History:
- * --------
- * 2006-11-23 initial version (jmagder)
  */
 
 /*!
diff --git a/modules/snmpstats/kamailioNet.c b/modules/snmpstats/kamailioNet.c
index f977da9..3c2097b 100644
--- a/modules/snmpstats/kamailioNet.c
+++ b/modules/snmpstats/kamailioNet.c
@@ -22,13 +22,16 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
  * USA
  *
- * History:
- * --------
- * 2013-03-24 initial version (oej)
- * 
  * Note: this file originally auto-generated by mib2c 
  *
  */
+/*!
+ *\file
+ * \brief Network statistics
+ * \ingroup snmpstats
+ * - Module: \ref snmpstats
+ * \author oej
+ */
 
 #include <net-snmp/net-snmp-config.h>
 #include <net-snmp/net-snmp-includes.h>
@@ -974,11 +977,6 @@ handle_kamailioNetTcpKeepIdle(netsnmp_mib_handler *handler,
     
     switch(reqinfo->mode) {
 
-    struct cfg_group_tcp t;
-    unsigned int value;
-
-    tcp_options_get(&t);
-    value = t.con_lifetime;
         case MODE_GET:
             snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER,
 			 (u_char *) &value, sizeof(int));
diff --git a/modules/snmpstats/kamailioNet.h b/modules/snmpstats/kamailioNet.h
index 1315fee..562090d 100644
--- a/modules/snmpstats/kamailioNet.h
+++ b/modules/snmpstats/kamailioNet.h
@@ -22,10 +22,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
  * USA
  *
- * History:
- * --------
- * 2013-04-01 initial version (oej)
- * 
  * Note: this file originally auto-generated by mib2c 
  *
  */
diff --git a/modules/snmpstats/kamailioNetConfig.c b/modules/snmpstats/kamailioNetConfig.c
index 309d7b9..bb56361 100644
--- a/modules/snmpstats/kamailioNetConfig.c
+++ b/modules/snmpstats/kamailioNetConfig.c
@@ -22,13 +22,17 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
  * USA
  *
- * History:
- * --------
- * 2013-04-01 initial version (oej)
- * 
  * Note: this file originally auto-generated by mib2c 
  *
  */
+/*!
+ *\file
+ * \brief SNMP network statistics
+ * This file groups together alarm checking and handling
+ * \ingroup snmpstats
+ * - Module: \ref snmpstats
+ * \author oej
+ */
 
 #include <net-snmp/net-snmp-config.h>
 #include <net-snmp/net-snmp-includes.h>
diff --git a/modules/snmpstats/kamailioServer.c b/modules/snmpstats/kamailioServer.c
index 2c21ffc..0e55db6 100644
--- a/modules/snmpstats/kamailioServer.c
+++ b/modules/snmpstats/kamailioServer.c
@@ -1,5 +1,4 @@
 /*
- *
  * SNMPStats Module 
  * Copyright (C) 2006 SOMA Networks, INC.
  * Written by: Jeffrey Magder (jmagder at somanetworks.com)
@@ -25,13 +24,18 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
  * USA
  *
- * History:
- * --------
- * 2013-03-24 initial version (oej)
- * 
  * Note: this file originally auto-generated by mib2c 
  *
  */
+/*!
+ *\file
+ * \brief SNMP statistic module
+ * This file groups together alarm checking and handling
+ * \ingroup snmpstats
+ * - Module: \ref snmpstats
+ * \author jmagder
+ * \author Olle E. Johansson (oej at edvina.net)
+ */
 
 #include <net-snmp/net-snmp-config.h>
 #include <net-snmp/net-snmp-includes.h>
diff --git a/modules/snmpstats/kamailioServer.h b/modules/snmpstats/kamailioServer.h
index b516f37..83d1798 100644
--- a/modules/snmpstats/kamailioServer.h
+++ b/modules/snmpstats/kamailioServer.h
@@ -24,10 +24,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
  * USA
  *
- * History:
- * --------
- * 2013-03-24 initial version (oej)
- * 
  * Note: this file originally auto-generated by mib2c 
  *
  */
diff --git a/modules/snmpstats/snmpMIBNotifications.c b/modules/snmpstats/snmpMIBNotifications.c
index 971b7db..ddde88b 100644
--- a/modules/snmpstats/snmpMIBNotifications.c
+++ b/modules/snmpstats/snmpMIBNotifications.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * SNMPStats Module 
  * Copyright (C) 2006 SOMA Networks, INC.
  * Written by: Jeffrey Magder (jmagder at somanetworks.com)
@@ -22,12 +20,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
  * USA
  *
- * History:
- * --------
- * 2006-11-23 initial version (jmagder)
- * 2007-02-16 Moved all OID registrations from the experimental branch to 
- *            Kamailio's IANA assigned enterprise branch. (jmagder)
- * 
  * Note: this file originally auto-generated by mib2c using
  *        : mib2c.notify.conf,v 5.3 2004/04/15 12:29:19 dts12 Exp $
  *
diff --git a/modules/snmpstats/snmpMIBNotifications.h b/modules/snmpstats/snmpMIBNotifications.h
index 6b1b6d7..bbe0838 100644
--- a/modules/snmpstats/snmpMIBNotifications.h
+++ b/modules/snmpstats/snmpMIBNotifications.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * SNMPStats Module 
  * Copyright (C) 2006 SOMA Networks, INC.
  * Written by: Jeffrey Magder (jmagder at somanetworks.com)
@@ -22,9 +20,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
  * USA
  *
- * History:
- * --------
- * 2006-11-23 initial version (jmagder)
  * 
  * Note: this file originally auto-generated by mib2c using
  *        : mib2c.notify.conf,v 5.3 2004/04/15 12:29:19 dts12 Exp $
diff --git a/modules/snmpstats/snmpObjects.c b/modules/snmpstats/snmpObjects.c
index 942264c..6223609 100644
--- a/modules/snmpstats/snmpObjects.c
+++ b/modules/snmpstats/snmpObjects.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * SNMPStats Module 
  * Copyright (C) 2006 SOMA Networks, INC.
  * Written by: Jeffrey Magder (jmagder at somanetworks.com)
diff --git a/modules/snmpstats/snmpObjects.h b/modules/snmpstats/snmpObjects.h
index 33c8077..f896ecc 100644
--- a/modules/snmpstats/snmpObjects.h
+++ b/modules/snmpstats/snmpObjects.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * SNMPStats Module 
  * Copyright (C) 2006 SOMA Networks, INC.
  * Written by: Jeffrey Magder (jmagder at somanetworks.com)
@@ -22,10 +20,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
  * USA
  *
- * History:
- * --------
- * 2006-11-23 initial version (jmagder)
- * 
  * Note: this file originally auto-generated by mib2c using
  *        : mib2c.scalar.conf,v 1.9 2005/01/07 09:37:18 dts12 Exp $
  *
diff --git a/modules/snmpstats/snmpSIPCommonObjects.c b/modules/snmpstats/snmpSIPCommonObjects.c
index 4cc00fc..2a57eec 100644
--- a/modules/snmpstats/snmpSIPCommonObjects.c
+++ b/modules/snmpstats/snmpSIPCommonObjects.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * SNMPStats Module 
  * Copyright (C) 2006 SOMA Networks, INC.
  * Written by: Jeffrey Magder (jmagder at somanetworks.com)
@@ -22,15 +20,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
  * USA
  *
- * History:
- * --------
- * 2006-11-23 initial version (jmagder)
- * 2007-02-16 Moved all OID registrations from the experimental branch to 
- *            Kamailio's IANA assigned enterprise branch. (jmagder)
- * 
- * Note: this file originally auto-generated by mib2c using
- *        : mib2c.scalar.conf,v 1.9 2005/01/07 09:37:18 dts12 Exp $
- *
  * This file defines all registration and handling of all scalars defined in the
  * KAMAILIO-SIP-COMMON-MIB.  Please see KAMAILIO-SIP-COMMON-MIB for the complete
  * descriptions of the individual scalars.
diff --git a/modules/snmpstats/snmpSIPCommonObjects.h b/modules/snmpstats/snmpSIPCommonObjects.h
index 9046d1d..8779c8a 100644
--- a/modules/snmpstats/snmpSIPCommonObjects.h
+++ b/modules/snmpstats/snmpSIPCommonObjects.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * SNMPStats Module 
  * Copyright (C) 2006 SOMA Networks, INC.
  * Written by: Jeffrey Magder (jmagder at somanetworks.com)
@@ -22,10 +20,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
  * USA
  *
- * History:
- * --------
- * 2006-11-23 initial version (jmagder)
- * 
  * Note: this file originally auto-generated by mib2c using
  *        : mib2c.scalar.conf,v 1.9 2005/01/07 09:37:18 dts12 Exp $
  *
diff --git a/modules/snmpstats/snmpSIPContactTable.c b/modules/snmpstats/snmpSIPContactTable.c
index 1c168da..d518fa1 100644
--- a/modules/snmpstats/snmpSIPContactTable.c
+++ b/modules/snmpstats/snmpSIPContactTable.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * SNMPStats Module 
  * Copyright (C) 2006 SOMA Networks, INC.
  * Written by: Jeffrey Magder (jmagder at somanetworks.com)
diff --git a/modules/snmpstats/snmpSIPContactTable.h b/modules/snmpstats/snmpSIPContactTable.h
index 9542e06..ff0d3bc 100644
--- a/modules/snmpstats/snmpSIPContactTable.h
+++ b/modules/snmpstats/snmpSIPContactTable.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * SNMPStats Module 
  * Copyright (C) 2006 SOMA Networks, INC.
  * Written by: Jeffrey Magder (jmagder at somanetworks.com)
@@ -22,14 +20,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
  * USA
  *
- * History:
- * --------
- * 2006-11-23 initial version (jmagder)
- * 2007-02-16 Moved all OID registrations from the experimental branch to 
- *            Kamailio's IANA assigned enterprise branch. (jmagder)
- * 
- * Note: this file was originally auto-generated by mib2c using
- * mib2c.array-user.conf
  *
  * This file contains the implementation of the kamailioSIPContact Table.  For a
  * full description of this structure, please see the KAMAILIO-SIP-SERVER-MIB.
diff --git a/modules/snmpstats/snmpSIPMethodSupportedTable.c b/modules/snmpstats/snmpSIPMethodSupportedTable.c
index 4645e5c..4acc598 100644
--- a/modules/snmpstats/snmpSIPMethodSupportedTable.c
+++ b/modules/snmpstats/snmpSIPMethodSupportedTable.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * SNMPStats Module 
  * Copyright (C) 2006 SOMA Networks, INC.
  * Written by: Jeffrey Magder (jmagder at somanetworks.com)
@@ -22,12 +20,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
  * USA
  *
- * History:
- * --------
- * 2006-11-23 initial version (jmagder)
- * 
- * Originally Generated with mib2c using mib2c.array-user.conf
- *
  * The file implements the kamailioSIPMethodSupportedTable.  The table is
  * populated by looking to see which modules are loaded, and guessing what SIP
  * Methods they  provide.  It is quite possible that this initial implementation
diff --git a/modules/snmpstats/snmpSIPMethodSupportedTable.h b/modules/snmpstats/snmpSIPMethodSupportedTable.h
index b2db4b8..468289d 100644
--- a/modules/snmpstats/snmpSIPMethodSupportedTable.h
+++ b/modules/snmpstats/snmpSIPMethodSupportedTable.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * SNMPStats Module 
  * Copyright (C) 2006 SOMA Networks, INC.
  * Written by: Jeffrey Magder (jmagder at somanetworks.com)
@@ -22,14 +20,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
  * USA
  *
- * History:
- * --------
- * 2006-11-23 initial version (jmagder)
- * 2007-02-16 Moved all OID registrations from the experimental branch to 
- *            Kamailio's IANA assigned enterprise branch. (jmagder)
- * 
- * Originally Generated with Mib2c using mib2c.array-user.conf.
- * 
  * This file defines the prototypes used to define the
  * kamailioSIPMethodSupportedTable.  For full details, please see the
  * KAMAILIO-SIP-COMMON-MIB.
diff --git a/modules/snmpstats/snmpSIPPortTable.c b/modules/snmpstats/snmpSIPPortTable.c
index 0513f79..ae2669a 100644
--- a/modules/snmpstats/snmpSIPPortTable.c
+++ b/modules/snmpstats/snmpSIPPortTable.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * SNMPStats Module 
  * Copyright (C) 2006 SOMA Networks, INC.
  * Written by: Jeffrey Magder (jmagder at somanetworks.com)
@@ -25,12 +23,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
  * USA
  *
- * History:
- * --------
- * 2006-11-23 initial version (jmagder)
- * 2013-02-24 Added SCTP support (oej)
- * 2013-04-07 Added IPv6 support (oej)
- * 
  * Originally Generated with mib2c using mib2c.array-user.conf
  *
  * This file implements the kamailioSIPPortTable.  For a full description of the table,
diff --git a/modules/snmpstats/snmpSIPPortTable.h b/modules/snmpstats/snmpSIPPortTable.h
index 2954555..f05ea55 100644
--- a/modules/snmpstats/snmpSIPPortTable.h
+++ b/modules/snmpstats/snmpSIPPortTable.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * SNMPStats Module 
  * Copyright (C) 2006 SOMA Networks, INC.
  * Written by: Jeffrey Magder (jmagder at somanetworks.com)
@@ -22,12 +20,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
  * USA
  *
- * History:
- * --------
- * 2006-11-23 initial version (jmagder)
- * 2007-02-16 Moved all OID registrations from the experimental branch to 
- *            Kamailio's IANA assigned enterprise branch. (jmagder)
- * 
  * Originally Generated with Mib2c using mib2c.array-user.conf.
  *
  * This file defines the kamailioSIPPortTable prototypes.  For a full description
diff --git a/modules/snmpstats/snmpSIPRegUserLookupTable.c b/modules/snmpstats/snmpSIPRegUserLookupTable.c
index f36b3d0..1f0281d 100644
--- a/modules/snmpstats/snmpSIPRegUserLookupTable.c
+++ b/modules/snmpstats/snmpSIPRegUserLookupTable.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * SNMPStats Module 
  * Copyright (C) 2006 SOMA Networks, INC.
  * Written by: Jeffrey Magder (jmagder at somanetworks.com)
@@ -22,10 +20,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
  * USA
  *
- * History:
- * --------
- * 2006-11-23 initial version (jmagder)
- * 
  * Note: this file originally auto-generated by mib2c using 
  * mib2c.array-user.conf
  *
@@ -465,15 +459,12 @@ void kamailioSIPRegUserLookupTable_set_reserve2( netsnmp_request_group *rg )
 
 	netsnmp_request_group_item *current;
 
-	netsnmp_variable_list *var;
-
 	int rc;
 
 	rg->rg_void = rg->list->ri;
 
 	for( current = rg->list; current; current = current->next ) {
 
-		var = current->ri->requestvb;
 		rc = SNMP_ERR_NOERROR;
 
 		switch(current->tri->colnum) 
diff --git a/modules/snmpstats/snmpSIPRegUserLookupTable.h b/modules/snmpstats/snmpSIPRegUserLookupTable.h
index c1ca833..7be2fd8 100644
--- a/modules/snmpstats/snmpSIPRegUserLookupTable.h
+++ b/modules/snmpstats/snmpSIPRegUserLookupTable.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * SNMPStats Module 
  * Copyright (C) 2006 SOMA Networks, INC.
  * Written by: Jeffrey Magder (jmagder at somanetworks.com)
@@ -22,15 +20,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
  * USA
  *
- * History:
- * --------
- * 2006-11-23 initial version (jmagder)
- * 2007-02-16 Moved all OID registrations from the experimental branch to 
- *            Kamailio's IANA assigned enterprise branch. (jmagder)
- * 
- * Note: this file originally auto-generated by mib2c using 
- * mib2c.array-user.conf,
- *
  * This file implements the kamailioSIPRegUserLookupTable.  For a full
  * description of the table, please see the KAMAILIO-SIP-SERVER-MIB.
  *
diff --git a/modules/snmpstats/snmpSIPRegUserTable.c b/modules/snmpstats/snmpSIPRegUserTable.c
index 4d719f9..878ce17 100644
--- a/modules/snmpstats/snmpSIPRegUserTable.c
+++ b/modules/snmpstats/snmpSIPRegUserTable.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * SNMPStats Module 
  * Copyright (C) 2006 SOMA Networks, INC.
  * Written by: Jeffrey Magder (jmagder at somanetworks.com)
@@ -22,10 +20,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
  * USA
  *
- * History:
- * --------
- * 2006-11-23 initial version (jmagder)
- *
  * Note: this file originally auto-generated by mib2c using
  * mib2c.array-user.conf
  *
diff --git a/modules/snmpstats/snmpSIPRegUserTable.h b/modules/snmpstats/snmpSIPRegUserTable.h
index 8206069..f99924f 100644
--- a/modules/snmpstats/snmpSIPRegUserTable.h
+++ b/modules/snmpstats/snmpSIPRegUserTable.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * SNMPStats Module 
  * Copyright (C) 2006 SOMA Networks, INC.
  * Written by: Jeffrey Magder (jmagder at somanetworks.com)
@@ -22,15 +20,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
  * USA
  *
- * History:
- * --------
- * 2006-11-23 initial version (jmagder)
- * 2007-02-16 Moved all OID registrations from the experimental branch to 
- *            Kamailio's IANA assigned enterprise branch. (jmagder)
- * 
- * Note: this file originally auto-generated by mib2c using
- * mib2c.array-user.conf
- *
  * This file defines the prototypes that implement the kamailioSIPRegUserTable.
  * For a full description of the table, please see the KAMAILIO-SIP-SERVER-MIB.
  *
diff --git a/modules/snmpstats/snmpSIPServerObjects.c b/modules/snmpstats/snmpSIPServerObjects.c
index f65d73b..d81a242 100644
--- a/modules/snmpstats/snmpSIPServerObjects.c
+++ b/modules/snmpstats/snmpSIPServerObjects.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * SNMPStats Module 
  * Copyright (C) 2006 SOMA Networks, INC.
  * Written by: Jeffrey Magder (jmagder at somanetworks.com)
@@ -22,15 +20,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
  * USA
  *
- * History:
- * --------
- * 2006-11-23 initial version (jmagder)
- * 2007-02-16 Moved all OID registrations from the experimental branch to 
- *            Kamailio's IANA assigned enterprise branch. (jmagder)
- * 
- * Note: this file originally auto-generated by mib2c using
- *        : mib2c.scalar.conf,v 1.9 2005/01/07 09:37:18 dts12 Exp $
- *
  * This file implements all scalares defines in the KAMAILIO-SIP-SERVER-MIB.  For
  * a full description of the scalars, please see KAMAILIO-SIP-SERVER-MIB.
  *
diff --git a/modules/snmpstats/snmpSIPServerObjects.h b/modules/snmpstats/snmpSIPServerObjects.h
index 2c29003..5b8a0ee 100644
--- a/modules/snmpstats/snmpSIPServerObjects.h
+++ b/modules/snmpstats/snmpSIPServerObjects.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * SNMPStats Module 
  * Copyright (C) 2006 SOMA Networks, INC.
  * Written by: Jeffrey Magder (jmagder at somanetworks.com)
@@ -22,13 +20,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
  * USA
  *
- * History:
- * --------
- * 2006-11-23 initial version (jmagder)
- * 
- * Note: this file originally auto-generated by mib2c using
- *        : mib2c.scalar.conf,v 1.9 2005/01/07 09:37:18 dts12 Exp $
- *
  * This file implements all scalars defined in the KAMAILIO-SIP-SERVER-MIB.  
  * For a full description of the scalars, please see KAMAILIO-SIP-SERVER-MIB.
  *
diff --git a/modules/snmpstats/snmpSIPStatusCodesTable.c b/modules/snmpstats/snmpSIPStatusCodesTable.c
index 2c7da81..0ff74ad 100644
--- a/modules/snmpstats/snmpSIPStatusCodesTable.c
+++ b/modules/snmpstats/snmpSIPStatusCodesTable.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * SNMPStats Module 
  * Copyright (C) 2006 SOMA Networks, INC.
  * Written by: Jeffrey Magder (jmagder at somanetworks.com)
@@ -22,13 +20,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
  * USA
  *
- * History:
- * --------
- * 2006-11-23 initial version (jmagder)
- *
- * Note: this file originally auto-generated by mib2c using
- * mib2c.array-user.conf
- *
  * The file implements the kamailioSIPStatusCodesTable.  For a full description
  * of the table, please see the KAMAILIO-SIP-COMMON-MIB.
  * 
@@ -499,7 +490,6 @@ void kamailioSIPStatusCodesTable_set_reserve2( netsnmp_request_group *rg )
 		(kamailioSIPStatusCodesTable_context *)rg->undo_info;
 
 	netsnmp_request_group_item *current;
-	netsnmp_variable_list      *var;
 
 	int rc;
 
@@ -507,7 +497,6 @@ void kamailioSIPStatusCodesTable_set_reserve2( netsnmp_request_group *rg )
 
 	for( current = rg->list; current; current = current->next ) {
 
-		var = current->ri->requestvb;
 		rc = SNMP_ERR_NOERROR;
 
 		switch(current->tri->colnum) 
diff --git a/modules/snmpstats/snmpSIPStatusCodesTable.h b/modules/snmpstats/snmpSIPStatusCodesTable.h
index dc292a4..089c1b9 100644
--- a/modules/snmpstats/snmpSIPStatusCodesTable.h
+++ b/modules/snmpstats/snmpSIPStatusCodesTable.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * SNMPStats Module 
  * Copyright (C) 2006 SOMA Networks, INC.
  * Written by: Jeffrey Magder (jmagder at somanetworks.com)
@@ -22,12 +20,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
  * USA
  *
- * History:
- * --------
- * 2006-11-23 initial version (jmagder)
- * 2007-02-16 Moved all OID registrations from the experimental branch to 
- *            Kamailio's IANA assigned enterprise branch. (jmagder)
- * 
  * Note: this file originally auto-generated by mib2c using
  * mib2c.array-user.conf
  *
diff --git a/modules/snmpstats/snmpstats.c b/modules/snmpstats/snmpstats.c
index 328e57a..cf2961c 100644
--- a/modules/snmpstats/snmpstats.c
+++ b/modules/snmpstats/snmpstats.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * SNMPStats Module 
  * Copyright (C) 2006 SOMA Networks, INC.
  * Written by: Jeffrey Magder (jmagder at somanetworks.com)
@@ -24,11 +22,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
  * USA
  *
- * History:
- * --------
- * 2006-11-23 initial version (jmagder)
- * 2013-04-01 updates of the MIB with core memory, tcp stats and much more (oej)
- * 
  * There are some important points to understanding the SNMPStat modules
  * architecture.
  *
@@ -60,6 +53,8 @@
  * \brief SNMP statistic module
  * \ingroup snmpstats
  * - Module: \ref snmpstats
+ * \author Jeffrey Magder (jmagder at somanetworks.com)
+ * \author Olle E. Johansson (oej at edvina.net)
  */
 
 /*!
diff --git a/modules/snmpstats/snmpstats.h b/modules/snmpstats/snmpstats.h
index b7811c4..ff9fbb2 100644
--- a/modules/snmpstats/snmpstats.h
+++ b/modules/snmpstats/snmpstats.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * SNMPStats Module 
  * Copyright (C) 2006 SOMA Networks, INC.
  * Written by: Jeffrey Magder (jmagder at somanetworks.com)
@@ -21,10 +19,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
  * USA
- *
- * History:
- * --------
- * 2006-11-23 initial version (jmagder)
  * 
  * Structure and prototype definitions for the SNMPStats module.
  *
diff --git a/modules/snmpstats/snmpstats_globals.h b/modules/snmpstats/snmpstats_globals.h
index 43a3dc5..7d6d75f 100644
--- a/modules/snmpstats/snmpstats_globals.h
+++ b/modules/snmpstats/snmpstats_globals.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * SNMPStats Module 
  * Copyright (C) 2006 SOMA Networks, INC.
  * Written by: Jeffrey Magder (jmagder at somanetworks.com)
@@ -22,10 +20,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
  * USA
  *
- * History:
- * --------
- * 2006-11-23 initial version (jmagder)
- *
  */
 
 /*!
diff --git a/modules/snmpstats/sub_agent.c b/modules/snmpstats/sub_agent.c
index 2223e91..f102ff8 100644
--- a/modules/snmpstats/sub_agent.c
+++ b/modules/snmpstats/sub_agent.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * SNMPStats Module 
  * Copyright (C) 2006 SOMA Networks, INC.
  * Written by: Jeffrey Magder (jmagder at somanetworks.com)
@@ -22,9 +20,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
  * USA
  *
- * History:
- * --------
- * 2006-11-23 initial version (jmagder)
  */
 
 /*!
@@ -35,6 +30,7 @@
  * master agent.
  * \ingroup snmpstats
  * - Module: \ref snmpstats
+ * \author jmagder
  */
 
 
diff --git a/modules/snmpstats/sub_agent.h b/modules/snmpstats/sub_agent.h
index 2700736..f93ac44 100644
--- a/modules/snmpstats/sub_agent.h
+++ b/modules/snmpstats/sub_agent.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * SNMPStats Module 
  * Copyright (C) 2006 SOMA Networks, INC.
  * Written by: Jeffrey Magder (jmagder at somanetworks.com)
@@ -22,9 +20,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
  * USA
  *
- * History:
- * --------
- * 2006-11-23 initial version (jmagder)
  */
 
 /*!
diff --git a/modules/snmpstats/utilities.c b/modules/snmpstats/utilities.c
index a401279..cefbef7 100644
--- a/modules/snmpstats/utilities.c
+++ b/modules/snmpstats/utilities.c
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- *
  * SNMPStats Module 
  * Copyright (C) 2006 SOMA Networks, INC.
  * Written by: Jeffrey Magder (jmagder at somanetworks.com)
@@ -22,9 +20,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
  * USA
  *
- * History:
- * --------
- * 2006-11-23 initial version (jmagder)
  */
 
 /*!
@@ -35,6 +30,7 @@
  * throughout the SNMPStats module, without belonging to any file in particular.
  * \ingroup snmpstats
  * - Module: \ref snmpstats
+ * \author jmagder
  */
 
 #include <stdlib.h>
diff --git a/modules/snmpstats/utilities.h b/modules/snmpstats/utilities.h
index 4f73ac6..0069758 100644
--- a/modules/snmpstats/utilities.h
+++ b/modules/snmpstats/utilities.h
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- *
  * SNMPStats Module 
  * Copyright (C) 2006 SOMA Networks, INC.
  * Written by: Jeffrey Magder (jmagder at somanetworks.com)
@@ -22,9 +20,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
  * USA
  *
- * History:
- * --------
- * 2006-11-23 initial version (jmagder)
  */
 
 /*!
diff --git a/modules/speeddial/Makefile b/modules/speeddial/Makefile
index f7bb222..a241447 100644
--- a/modules/speeddial/Makefile
+++ b/modules/speeddial/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # SPEEDDIAL Module
 #
diff --git a/modules/speeddial/sdlookup.c b/modules/speeddial/sdlookup.c
index 17277c4..ff67f3c 100644
--- a/modules/speeddial/sdlookup.c
+++ b/modules/speeddial/sdlookup.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2004-2006 Voice Sistem SRL
  *
  * This file is part of Kamailio.
@@ -19,8 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  *
- * History:
- * ---------
  * 
  */
 
diff --git a/modules/speeddial/sdlookup.h b/modules/speeddial/sdlookup.h
index 85e90f4..1724362 100644
--- a/modules/speeddial/sdlookup.h
+++ b/modules/speeddial/sdlookup.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2004-2006 Voice Sistem SRL
  *
  * This file is part of Kamailio.
@@ -19,8 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  *
- * History:
- * ---------
  * 
  */
 
diff --git a/modules/speeddial/speeddial.c b/modules/speeddial/speeddial.c
index ce7e051..f0ac752 100644
--- a/modules/speeddial/speeddial.c
+++ b/modules/speeddial/speeddial.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2004-2006 Voice Sistem SRL
  *
  * This file is part of Kamailio.
@@ -19,8 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  *
- * History:
- * ---------
  * 
  */
 
diff --git a/modules/speeddial/speeddial.h b/modules/speeddial/speeddial.h
index b5fbf2b..bd4a483 100644
--- a/modules/speeddial/speeddial.h
+++ b/modules/speeddial/speeddial.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2004-2006 Voice Sistem SRL
  *
  * This file is part of Kamailio.
@@ -19,8 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  *
- * History:
- * ---------
  * 
  */
 
diff --git a/modules/sqlops/Makefile b/modules/sqlops/Makefile
index 66a0b94..489d884 100644
--- a/modules/sqlops/Makefile
+++ b/modules/sqlops/Makefile
@@ -1,6 +1,5 @@
-# $Id$
 #
-# example module makefile
+# sqlops module makefile
 #
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
diff --git a/modules/sqlops/sql_api.c b/modules/sqlops/sql_api.c
index e11ae29..db87fbf 100644
--- a/modules/sqlops/sql_api.c
+++ b/modules/sqlops/sql_api.c
@@ -1,6 +1,4 @@
-/**
- * $Id$
- *
+/*
  * Copyright (C) 2008 Elena-Ramona Modroiu (asipto.com)
  *
  * This file is part of kamailio, a free SIP server.
@@ -22,7 +20,7 @@
 
 /*! \file
  * \ingroup sqlops
- * \brief SIP-router SQL-operations :: API
+ * \brief Kamailio SQL-operations :: API
  *
  * - Module: \ref sqlops
  */
diff --git a/modules/sqlops/sql_api.h b/modules/sqlops/sql_api.h
index 15c5813..4083370 100644
--- a/modules/sqlops/sql_api.h
+++ b/modules/sqlops/sql_api.h
@@ -1,6 +1,4 @@
 /**
- * $Id$
- *
  * Copyright (C) 2008 Elena-Ramona Modroiu (asipto.com)
  *
  * This file is part of kamailio, a free SIP server.
@@ -22,7 +20,7 @@
 
 /*! \file
  * \ingroup sqlops
- * \brief SIP-router SQL-operations :: API
+ * \brief Kamailio SQL-operations :: API
  *
  * - Module: \ref sqlops
  */
diff --git a/modules/sqlops/sql_trans.c b/modules/sqlops/sql_trans.c
index ba5a230..d0701a6 100644
--- a/modules/sqlops/sql_trans.c
+++ b/modules/sqlops/sql_trans.c
@@ -1,6 +1,4 @@
 /**
- * $Id$
- *
  * Copyright (C) 2011 SpeakUp B.V. (alex at speakup.nl)
  *
  * This file is part of kamailio, a free SIP server.
diff --git a/modules/sqlops/sql_trans.h b/modules/sqlops/sql_trans.h
index 5a1104f..945028e 100644
--- a/modules/sqlops/sql_trans.h
+++ b/modules/sqlops/sql_trans.h
@@ -1,6 +1,4 @@
 /**
- * $Id$
- *
  * Copyright (C) 2011 SpeakUp B.V. (alex at speakup.nl)
  *
  * This file is part of kamailio, a free SIP server.
diff --git a/modules/sqlops/sql_var.c b/modules/sqlops/sql_var.c
index c68c44a..940ec5a 100644
--- a/modules/sqlops/sql_var.c
+++ b/modules/sqlops/sql_var.c
@@ -1,6 +1,4 @@
 /**
- * $Id$
- *
  * Copyright (C) 2008 Elena-Ramona Modroiu (asipto.com)
  *
  * This file is part of kamailio, a free SIP server.
@@ -22,7 +20,7 @@
 
 /*! \file
  * \ingroup sqlops
- * \brief SIP-router SQL-operations :: Variables
+ * \brief Kamailio SQL-operations :: Variables
  *
  * - Module: \ref sqlops
  */
diff --git a/modules/sqlops/sql_var.h b/modules/sqlops/sql_var.h
index ebd9632..37dec27 100644
--- a/modules/sqlops/sql_var.h
+++ b/modules/sqlops/sql_var.h
@@ -1,6 +1,4 @@
 /**
- * $Id$
- *
  * Copyright (C) 2008 Elena-Ramona Modroiu (asipto.com)
  *
  * This file is part of kamailio, a free SIP server.
@@ -22,7 +20,7 @@
 
 /*! \file
  * \ingroup sqlops
- * \brief SIP-router SQL-operations :: Variables
+ * \brief Kamailio SQL-operations :: Variables
  *
  * - Module: \ref sqlops
  */
diff --git a/modules/sqlops/sqlops.c b/modules/sqlops/sqlops.c
index 1760c3c..3ca3509 100644
--- a/modules/sqlops/sqlops.c
+++ b/modules/sqlops/sqlops.c
@@ -1,6 +1,4 @@
 /**
- * $Id$
- *
  * Copyright (C) 2008 Elena-Ramona Modroiu (asipto.com)
  *
  * This file is part of Kamailio, a free SIP server.
@@ -22,12 +20,12 @@
 
 /*! \file
  * \ingroup sqlops
- * \brief SIP-router SQL-operations :: Module interface
+ * \brief Kamailio SQL-operations :: Module interface
  *
  * - Module: \ref sqlops
  */
 
-/*! \defgroup sqlops SIP-Router :: SQL Operations
+/*! \defgroup sqlops Kamailio :: SQL Operations
  *  \note Kamailio module - part of modules_k
 
  * The module adds support for raw SQL queries in the configuration file.
diff --git a/modules/sst/Makefile b/modules/sst/Makefile
index 82c7e01..f46ab01 100644
--- a/modules/sst/Makefile
+++ b/modules/sst/Makefile
@@ -1,19 +1,18 @@
 #
-# $Id$
 #
 # WARNING: do not run this directly, it should be run by the master Makefile
 #
 # Copyright (C) 2006 SOMA Networks, INC.
 # Written by: Ron Winacott
 #
-# This file is part of openser, a free SIP server.
+# This file is part of Kamailio, a free SIP server.
 #
 # Kamailio is free software; you can redistribute it and/or modify it
 # under the terms of the GNU General Public License as published by
 # the Free Software Foundation; either version 2 of the License, or
 # (at your option) any later version
 #
-# openser is distributed in the hope that it will be useful, but
+# Kamailio is distributed in the hope that it will be useful, but
 # WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 # General Public License for more details.
@@ -23,9 +22,6 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
 # USA
 #
-# History:
-# --------
-#  2006-05-11  initial version (ronw)
 #
 
 include ../../Makefile.defs
diff --git a/modules/sst/sst.c b/modules/sst/sst.c
index 50b3ccc..6b1eb41 100644
--- a/modules/sst/sst.c
+++ b/modules/sst/sst.c
@@ -1,20 +1,18 @@
 /*
- * $Id$
- *
  * SIP Session Timer (sst) module - support for tracking dialogs and
  * SIP Session Timers.
  *
  * Copyright (C) 2006 SOMA Networks, INC.
  * Written by: Ron Winacott (karwin)
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify it
+ * Kamailio is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful, but
+ * Kamailio is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
@@ -24,10 +22,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
  * USA
  *
- * History:
- * --------
- * 2006-05-11 initial version (karwin)
- * 2006-10-10 RFC compilent changes. Added the other flags (karwin)
  */
 
 /*! \file sst/sst.c
diff --git a/modules/sst/sst_handlers.c b/modules/sst/sst_handlers.c
index 48b9339..1cacb29 100644
--- a/modules/sst/sst_handlers.c
+++ b/modules/sst/sst_handlers.c
@@ -1,17 +1,15 @@
 /*
- * $Id$
- *
  * Copyright (C) 2006 SOMA Networks, Inc.
  * Written by Ron Winacott (karwin)
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify it
+ * Kamailio is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful, but
+ * Kamailio is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
diff --git a/modules/sst/sst_handlers.h b/modules/sst/sst_handlers.h
index c0f707d..a33f281 100644
--- a/modules/sst/sst_handlers.h
+++ b/modules/sst/sst_handlers.h
@@ -1,17 +1,15 @@
 /*
- * $Id$
- *
  * Copyright (C) 2006 SOMA Networks, Inc.
  * Written By Ron Winacott (karwin)
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify it
+ * Kamailio is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful, but
+ * Kamailio is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
@@ -21,10 +19,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
  * USA
  *
- * History:
- * --------
- * 2006-05-11 initial version (karwin)
- * 2006-10-10 Code cleanup of this header file. (karwin)
  */
 
 /*! \file sst/sst_handlers.h
diff --git a/modules/sst/sst_mi.c b/modules/sst/sst_mi.c
index 72c79f0..e1547bf 100644
--- a/modules/sst/sst_mi.c
+++ b/modules/sst/sst_mi.c
@@ -1,17 +1,15 @@
 /*
- * $Id$
- *
  * Copyright (C) 2008 SOMA Networks, Inc.
  * Written By Ovidiu Sas (osas)
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify it
+ * Kamailio is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful, but
+ * Kamailio is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
@@ -21,9 +19,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
  * USA
  *
- * History:
- * --------
- * 2008-04-11 initial version (osas)
  */
 
 /*! 
diff --git a/modules/sst/sst_mi.h b/modules/sst/sst_mi.h
index 30fafdb..c991286 100644
--- a/modules/sst/sst_mi.h
+++ b/modules/sst/sst_mi.h
@@ -1,17 +1,15 @@
 /*
- * $Id$
- *
  * Copyright (C) 2008 SOMA Networks, Inc.
  * Written By Ovidiu Sas (osas)
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify it
+ * Kamailio is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful, but
+ * Kamailio is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
@@ -21,9 +19,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
  * USA
  *
- * History:
- * --------
- * 2008-04-11 initial version (osas)
  */
 
 /*!
diff --git a/modules/statistics/Makefile b/modules/statistics/Makefile
index abd7e7e..65554b4 100644
--- a/modules/statistics/Makefile
+++ b/modules/statistics/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # WARNING: do not run this directly, it should be run by the master Makefile
 
diff --git a/modules/statistics/statistics.c b/modules/statistics/statistics.c
index 477b60e..2baf759 100644
--- a/modules/statistics/statistics.c
+++ b/modules/statistics/statistics.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * statistics module - script interface to internal statistics manager
  *
  * Copyright (C) 2006 Voice Sistem S.R.L.
@@ -21,9 +19,15 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2006-03-14  initial version (bogdan)
+ */
+
+/*!
+ * \defgroup statistics The statistics module
+ */
+/*!
+ * \brief Script interface
+ * \ingroup statistics
+ * \author bogdan
  */
 
 
diff --git a/modules/statistics/stats_funcs.c b/modules/statistics/stats_funcs.c
index e039a5f..6acc793 100644
--- a/modules/statistics/stats_funcs.c
+++ b/modules/statistics/stats_funcs.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * statistics module - script interface to internal statistics manager
  *
  * Copyright (C) 2006 Voice Sistem S.R.L.
@@ -21,10 +19,13 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2006-03-14  initial version (bogdan)
  */
+/*!
+ * \brief Script interface
+ * \ingroup statistics
+ * \author bogdan
+ */
+
 
 
 #include <string.h>
diff --git a/modules/statistics/stats_funcs.h b/modules/statistics/stats_funcs.h
index 251dbb1..ec8036d 100644
--- a/modules/statistics/stats_funcs.h
+++ b/modules/statistics/stats_funcs.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * statistics module - script interface to internal statistics manager
  *
  * Copyright (C) 2006 Voice Sistem S.R.L.
@@ -21,10 +19,13 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2006-03-14  initial version (bogdan)
  */
+/*!
+ * \brief Script interface
+ * \ingroup statistics
+ * \author bogdan
+ */
+
 
 
 #ifndef _STATISTICS_STATS_FUNCS_
diff --git a/modules/statsd/Makefile b/modules/statsd/Makefile
new file mode 100644
index 0000000..209ed2c
--- /dev/null
+++ b/modules/statsd/Makefile
@@ -0,0 +1,14 @@
+#
+# statsd module makefile
+#
+#
+# WARNING: do not run this directly, it should be run by the master Makefile
+
+include ../../Makefile.defs
+auto_gen=
+NAME=statsd.so
+LIBS=
+
+DEFS+=-DKAMAILIO_MOD_INTERFACE
+
+include ../../Makefile.modules
diff --git a/modules/statsd/README b/modules/statsd/README
new file mode 100644
index 0000000..689c15a
--- /dev/null
+++ b/modules/statsd/README
@@ -0,0 +1,205 @@
+Statsd Module
+
+Eloy Coto Pereiro
+
+   <eloy.coto at gmail.com>
+
+Edited by
+
+Eloy Coto Pereiro
+
+   <eloy.coto at gmail.com>
+
+   Copyright � 2014 Eloy Coto
+     __________________________________________________________________
+
+   Table of Contents
+
+   1. Admin Guide
+
+        1. Overview
+        2. Parameters
+
+              2.1. ip(string)
+              2.2. port(int)
+
+        3. Functions
+
+              3.1. statsd_set(key, value)
+              3.2. statsd_gauge(key, value)
+              3.3. statsd_start(key)
+              3.4. statsd_stop(key)
+              3.5. statsd_incr(key)
+              3.6. statsd_decr(key)
+
+   List of Examples
+
+   1.1. Set ip parameter
+   1.2. Set ip parameter
+   1.3. statsd_set usage
+   1.4. statsd_set usage
+   1.5. statsd_start usage
+   1.6. statsd_stop usage
+   1.7. statsd_incr usage
+   1.8. statsd_decr usage
+
+Chapter 1. Admin Guide
+
+   Table of Contents
+
+   1. Overview
+   2. Parameters
+
+        2.1. ip(string)
+        2.2. port(int)
+
+   3. Functions
+
+        3.1. statsd_set(key, value)
+        3.2. statsd_gauge(key, value)
+        3.3. statsd_start(key)
+        3.4. statsd_stop(key)
+        3.5. statsd_incr(key)
+        3.6. statsd_decr(key)
+
+1. Overview
+
+   The module provides the ability to send commands to statsd (you can use
+   InfluxDB too) with different kind of information. It provides native
+   integration with statsd (https://github.com/etsy/statsd/) and graphite
+   (http://graphite.wikidot.com/).
+
+   The module does not have any special dependency, it does a direct
+   socket connection to Graphite.
+
+2. Parameters
+
+   2.1. ip(string)
+   2.2. port(int)
+
+2.1. ip(string)
+
+   Statsd server ip
+
+   Example 1.1. Set ip parameter
+...
+modparam("statsd", "ip", "127.0.0.1")
+...
+
+2.2. port(int)
+
+   Statsd server ip
+
+   Example 1.2. Set ip parameter
+...
+modparam("statsd", "port", "8125")
+...
+
+3. Functions
+
+   3.1. statsd_set(key, value)
+   3.2. statsd_gauge(key, value)
+   3.3. statsd_start(key)
+   3.4. statsd_stop(key)
+   3.5. statsd_incr(key)
+   3.6. statsd_decr(key)
+
+3.1. statsd_set(key, value)
+
+   Sets count the number of unique values passed to a key.
+
+   If that method is called multiple times with the same userid in the
+   same sample period, that userid will only be counted once.
+
+   This function can be used in ALL ROUTES.
+
+   Example 1.3. statsd_set usage
+...
+failure_route[tryagain] {
+...
+    statsd_set("customerFailure", 1);
+...
+}
+...
+
+3.2. statsd_gauge(key, value)
+
+   Gauges are a constant data type. They are not subject to averaging, and
+   they don�t change unless you change them. That is, once you set a gauge
+   value, it will be a flat line on the graph until you change it again.
+
+   Gauges are useful for things that are already averaged, or don�t need
+   to reset periodically
+
+   This function can be used in ALL ROUTES.
+
+   The statsd server collects gauges under the stats.gauges prefix.
+
+   Example 1.4. statsd_set usage
+route [gauge_method]{
+    statsd_gauge("method"+$rm, "+1");
+    statsd_gauge("customer_credit"+$var(customer),"$var(customer_credit)");
+}
+
+3.3. statsd_start(key)
+
+   statsd start set a avp with the key name, and when you use
+   statsd_stop(key), module will send to statsd the difference in
+   milliseconds. this is useful to know the time of a sql query, or how
+   many time take your replies.
+
+   this function can be used in all routes.
+
+   the statsd server collects all timers under the stats.timers prefix,
+   and will calculate the lower bound, mean, 90th percentile, upper bound,
+   and count of each timer for each period (by the time you see it in
+   graphite, that�s usually per minute).
+
+   Example 1.5. statsd_start usage
+...
+statsd_start("long_mysql_query");
+sql_query("ca", "select sleep(0.2)", "ra");
+statsd_stop("long_mysql_query");
+...
+
+3.4. statsd_stop(key)
+
+   statsd_stop(key) get the avp string with the key and calculate the
+   difference from the start time. When finish app send the milliseconds
+   to statsd.
+
+   This function can be used in all routes.
+
+   Example 1.6. statsd_stop usage
+...
+statsd_start("long_mysql_query");
+sql_query("ca", "select sleep(0.2)", "ra");
+statsd_stop("long_mysql_query");
+...
+
+3.5. statsd_incr(key)
+
+   Increment a counter
+
+   This function can be used in all routes.
+
+   Example 1.7. statsd_incr usage
+...
+if(geoip_match("$si", "src")){
+    statsd_incr("country."+$(gip(src=>cc)));
+}
+...
+
+3.6. statsd_decr(key)
+
+   Decrement a counter
+
+   This function can be used in all routes.
+
+   Example 1.8. statsd_decr usage
+...
+if (t_check_status("408")) {
+    statsd_decr("kamailio.successfulCalls");
+    statsd_incr("kamailio.reply.busy");
+}
+...
diff --git a/modules/statsd/doc/Makefile b/modules/statsd/doc/Makefile
new file mode 100644
index 0000000..998b6c2
--- /dev/null
+++ b/modules/statsd/doc/Makefile
@@ -0,0 +1,6 @@
+docs = statsd.xml
+
+
+docbook_dir = ../../../docbook
+include $(docbook_dir)/Makefile.module
+
diff --git a/modules/statsd/doc/statsd.xml b/modules/statsd/doc/statsd.xml
new file mode 100644
index 0000000..e7b9255
--- /dev/null
+++ b/modules/statsd/doc/statsd.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding='ISO-8859-1'?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+<!-- Include general documentation entities -->
+<!ENTITY % docentities SYSTEM "../../../docbook/entities.xml">
+%docentities;
+
+]>
+
+<book xmlns:xi="http://www.w3.org/2001/XInclude">
+    <bookinfo>
+    <title>Statsd Module</title>
+    <productname class="trade"></productname>
+    <authorgroup>
+        <author>
+        <firstname>Eloy</firstname>
+        <surname>Coto Pereiro</surname>
+        <email>eloy.coto at gmail.com</email>
+        </author>
+        <editor>
+        <firstname>Eloy</firstname>
+        <surname>Coto Pereiro</surname>
+        <email>eloy.coto at gmail.com</email>
+        </editor>
+    </authorgroup>
+    <copyright>
+        <year>2014</year>
+        <holder>Eloy Coto</holder>
+    </copyright>
+   </bookinfo>
+   <toc></toc>
+
+    <xi:include href="statsd_admin.xml"/>
+</book>
+
diff --git a/modules/statsd/doc/statsd_admin.xml b/modules/statsd/doc/statsd_admin.xml
new file mode 100644
index 0000000..4e299d2
--- /dev/null
+++ b/modules/statsd/doc/statsd_admin.xml
@@ -0,0 +1,213 @@
+<?xml version="1.0" encoding='ISO-8859-1'?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+<!-- Include general documentation entities -->
+<!ENTITY % docentities SYSTEM "../../../docbook/entities.xml">
+%docentities;
+
+]>
+<!-- Module User's Guide -->
+
+<chapter xmlns:xi="http://www.w3.org/2001/XInclude">
+
+    <title>&adminguide;</title>
+
+    <section>
+        <title>Overview</title>
+		<para>
+			The module provides the ability to send commands to statsd
+			(you can use InfluxDB too) with different kind of information.
+			It provides native integration with statsd (https://github.com/etsy/statsd/)
+			and graphite (http://graphite.wikidot.com/).
+		</para>
+		<para>
+			The module does not have any special dependency, it does a direct
+			socket connection to Graphite.
+		</para>
+    </section>
+
+    <section>
+        <title>Parameters</title>
+        <section id="statsd.p.serverIP">
+            <title><varname>ip</varname>(string)</title>
+            <para>
+            Statsd server ip
+            </para>
+            <example>
+                <title>Set ip parameter</title>
+                <programlisting format="linespecific">
+...
+modparam("statsd", "ip", "127.0.0.1")
+...
+                </programlisting>
+            </example>
+        </section>
+
+        <section id="statsd.p.serverPort">
+            <title><varname>port</varname>(int)</title>
+            <para>
+            Statsd server ip
+            </para>
+            <example>
+                <title>Set ip parameter</title>
+                <programlisting format="linespecific">
+...
+modparam("statsd", "port", "8125")
+...
+                </programlisting>
+            </example>
+        </section>
+    </section>
+
+    <section>
+        <title>Functions</title>
+        <section id="statsd.f.statsd_set">
+            <title>
+                <function moreinfo="none">statsd_set(key, value)</function>
+            </title>
+            <para>
+                Sets count the number of unique values passed to a key.
+            </para>
+            <para>
+                If that method is called multiple times with the same userid in the same sample period, that userid will only be counted once.
+            </para>
+            <para>
+                This function can be used in ALL ROUTES.
+            </para>
+            <example>
+                <title><function>statsd_set</function> usage</title>
+                <programlisting format="linespecific">
+...
+failure_route[tryagain] {
+...
+    statsd_set("customerFailure", 1);
+...
+}
+...
+                </programlisting>
+            </example>
+        </section>
+
+        <section id="statsd.f.statsd_gauge">
+            <title>
+                <function moreinfo="none">statsd_gauge(key, value)</function>
+            </title>
+            <para>
+                Gauges are a constant data type. They are not subject to averaging, and they don’t change unless you change them. That is, once you set a gauge value, it will be a flat line on the graph until you change it again.
+            </para>
+            <para>
+                Gauges are useful for things that are already averaged, or don’t need to reset periodically
+            </para>
+            <para>
+                This function can be used in ALL ROUTES.
+            </para>
+            <para>
+                The statsd server collects gauges under the stats.gauges prefix.
+            </para>
+            <example>
+                <title><function>statsd_set</function> usage</title>
+                <programlisting format="linespecific">
+route [gauge_method]{
+    statsd_gauge("method"+$rm, "+1");
+    statsd_gauge("customer_credit"+$var(customer),"$var(customer_credit)");
+}
+                </programlisting>
+            </example>
+        </section>
+
+        <section id="statsd.f.statsd_start">
+            <title>
+                <function moreinfo="none">statsd_start(key)</function>
+            </title>
+            <para>
+statsd start set a avp with the key name, and when you use statsd_stop(key), module will send to statsd the difference in milliseconds. this is useful to know the time of a sql query, or how many time take your replies.
+            </para>
+            <para>
+                this function can be used in all routes.
+            </para>
+            <para>
+                the statsd server collects all timers under the stats.timers prefix, and will calculate the lower bound, mean, 90th percentile, upper bound, and count of each timer for each period (by the time you see it in graphite, that’s usually per minute).
+            </para>
+            <example>
+                <title><function>statsd_start</function> usage</title>
+                <programlisting format="linespecific">
+...
+statsd_start("long_mysql_query");
+sql_query("ca", "select sleep(0.2)", "ra");
+statsd_stop("long_mysql_query");
+...
+                </programlisting>
+            </example>
+        </section>
+
+
+        <section id="statsd.f.statsd_stop">
+            <title>
+                <function moreinfo="none">statsd_stop(key)</function>
+            </title>
+            <para>
+                statsd_stop(key) get the avp string with the key and calculate the difference from the start time. When finish app send the milliseconds to statsd.
+            </para>
+            <para>
+                This function can be used in all routes.
+            </para>
+            <example>
+                <title><function>statsd_stop</function> usage</title>
+                <programlisting format="linespecific">
+...
+statsd_start("long_mysql_query");
+sql_query("ca", "select sleep(0.2)", "ra");
+statsd_stop("long_mysql_query");
+...
+                </programlisting>
+            </example>
+        </section>
+
+        <section id="statsd.f.statsd_incr">
+            <title>
+                <function moreinfo="none">statsd_incr(key)</function>
+            </title>
+            <para>
+            Increment a counter
+            </para>
+            <para>
+                This function can be used in all routes.
+            </para>
+            <example>
+                <title><function>statsd_incr</function> usage</title>
+                <programlisting format="linespecific">
+...
+if(geoip_match("$si", "src")){
+    statsd_incr("country."+$(gip(src=>cc)));
+}
+...
+                </programlisting>
+            </example>
+        </section>
+
+        <section id="statsd.f.statsd_decr">
+            <title>
+                <function moreinfo="none">statsd_decr(key)</function>
+            </title>
+            <para>
+                Decrement a counter
+            </para>
+            <para>
+                This function can be used in all routes.
+            </para>
+            <example>
+                <title><function>statsd_decr</function> usage</title>
+                <programlisting format="linespecific">
+...
+if (t_check_status("408")) {
+    statsd_decr("kamailio.successfulCalls");
+    statsd_incr("kamailio.reply.busy");
+}
+...
+                </programlisting>
+            </example>
+        </section>
+    </section>
+</chapter>
+
diff --git a/modules/statsd/lib_statsd.c b/modules/statsd/lib_statsd.c
new file mode 100644
index 0000000..52820e5
--- /dev/null
+++ b/modules/statsd/lib_statsd.c
@@ -0,0 +1,133 @@
+#include <stdio.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <netdb.h>
+#include <math.h>
+#include <errno.h>
+
+#include "../../sr_module.h"
+#include "lib_statsd.h"
+
+static StatsdSocket statsd_socket = {
+    "/var/run/statsd/statsd.sock",
+    -1,
+    500, // timeout 500ms if no answer
+    0,
+    ""
+};
+
+static StatsConnection statsd_connection = {
+    "127.0.0.1",
+    "8125"
+};
+
+int statsd_connect(void){
+
+    struct addrinfo *serverAddr;
+    int rc, error;
+
+    if (statsd_socket.sock > 0){
+        return True;
+    }
+
+    error = getaddrinfo(
+        statsd_connection.ip, statsd_connection.port,
+        NULL, &serverAddr);
+    if (error != 0)
+    {
+        LM_ERR(
+            "Statsd: could not initiate server information (%s)\n",
+            gai_strerror(error));
+        return False;
+    }
+
+    statsd_socket.sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+    if (statsd_socket.sock == 0 ){
+        LM_ERR("Statsd: could not initiate a connect to statsd\n");
+        return False;
+    }
+
+    rc = connect(
+        statsd_socket.sock, serverAddr->ai_addr, serverAddr->ai_addrlen);
+    if (rc < 0){
+        LM_ERR("Statsd: could not initiate a connect to statsd\n");
+        return False;
+    }
+    return True;
+}
+
+int send_command(char *command){
+    int send_result;
+
+    if (!statsd_connect()){
+        return False;
+    }
+
+    send_result = send(statsd_socket.sock, command, strlen(command), 0);
+    if ( send_result < 0){
+        LM_ERR("could not send the correct info to statsd (%i| %s)\n",
+            send_result, strerror(errno));
+        return True;
+    }
+    LM_DBG("Sent to statsd (%s)", command);
+    return True;
+}
+
+int statsd_set(char *key, char *value){
+   char* end = 0;
+   char command[254];
+   int val;
+   val = strtol(value, &end, 0);
+   if (*end){
+       LM_ERR("statsd_count could not  use the provide value(%s)\n", value);
+       return False;
+   }
+   snprintf(command, sizeof command, "%s:%i|s\n", key, val);
+   return send_command(command);
+}
+
+
+int statsd_gauge(char *key, char *value){
+   char command[254];
+   snprintf(command, sizeof command, "%s:%s|g\n", key, value);
+   return send_command(command);
+}
+
+int statsd_count(char *key, char *value){
+   char* end = 0;
+   char command[254];
+   int val;
+
+   val = strtol(value, &end, 0);
+   if (*end){
+       LM_ERR("statsd_count could not  use the provide value(%s)\n", value);
+       return False;
+   }
+   snprintf(command, sizeof command, "%s:%i|c\n", key, val);
+   return send_command(command);
+}
+
+int statsd_timing(char *key, int value){
+   char command[254];
+   snprintf(command, sizeof command, "%s:%i|ms\n", key, value);
+   return send_command(command);
+}
+
+int statsd_init(char *ip, char *port){
+
+    if (ip != NULL){
+        statsd_connection.ip = ip;
+    }
+    if (port != NULL ){
+       statsd_connection.port = port;
+    }
+    return statsd_connect();
+}
+
+int statsd_destroy(void){
+    statsd_socket.sock = 0;
+    return True;
+}
diff --git a/modules/statsd/lib_statsd.h b/modules/statsd/lib_statsd.h
new file mode 100644
index 0000000..b7d178e
--- /dev/null
+++ b/modules/statsd/lib_statsd.h
@@ -0,0 +1,27 @@
+
+#define BUFFER_SIZE 8192
+typedef int Bool;
+#define True 1
+#define False 0
+
+typedef struct StatsConnection{
+    char *ip;
+    char *port;
+} StatsConnection;
+
+typedef struct StatsdSocket {
+    char *name; // name
+    int sock; // socket
+    int timeout; // how many miliseconds to wait for an answer
+    time_t last_failure; // time of the last failure
+    char data[BUFFER_SIZE]; // buffer for the answer data
+} StatsdSocket;
+
+int statsd_connect(void);
+int send_command(char *command);
+int statsd_set(char *key, char *value);
+int statsd_gauge(char *key, char *value);
+int statsd_count(char *key, char *value);
+int statsd_timing(char *key, int value);
+int statsd_init(char *ip, char *port);
+int statsd_destroy(void);
diff --git a/modules/statsd/statsd.c b/modules/statsd/statsd.c
new file mode 100644
index 0000000..daae358
--- /dev/null
+++ b/modules/statsd/statsd.c
@@ -0,0 +1,187 @@
+
+#include <sys/time.h>
+#include <stdlib.h>
+
+#include "../../sr_module.h"
+#include "../../usr_avp.c"
+#include "../../pvar.h"
+#include "../../lvalue.h"
+#include "lib_statsd.h"
+
+
+MODULE_VERSION
+
+static int mod_init(void);
+static int mod_destroy(void);
+static int func_gauge(struct sip_msg *msg, char *key, char* val);
+static int func_set(struct sip_msg *msg, char *key, char* val);
+static int func_time_start(struct sip_msg *msg, char *key);
+static int func_time_end(struct sip_msg *msg, char *key);
+static int func_incr(struct sip_msg *msg, char *key);
+static int func_decr(struct sip_msg *msg, char *key);
+static char* get_milliseconds(char *dst);
+
+typedef struct StatsdParams{
+    char *ip;
+    char *port;
+} StatsdParams;
+
+static StatsdParams statsd_params= {};
+
+static cmd_export_t commands[] = {
+	{"statsd_gauge", (cmd_function)func_gauge, 2, 0, 0, ANY_ROUTE},
+	{"statsd_start", (cmd_function)func_time_start, 1, 0, 0, ANY_ROUTE},
+	{"statsd_stop", (cmd_function)func_time_end, 1, 0, 0, ANY_ROUTE},
+	{"statsd_incr", (cmd_function)func_incr, 1, 0, 0, ANY_ROUTE},
+	{"statsd_decr", (cmd_function)func_decr, 1, 0, 0, ANY_ROUTE},
+	{"statsd_set", (cmd_function)func_set, 2, 0, 0, ANY_ROUTE},
+    {0, 0, 0, 0, 0, 0}
+};
+
+static param_export_t parameters[] = {
+    {"ip", STR_PARAM, &(statsd_params.ip)},
+    {"port", STR_PARAM, &(statsd_params.port)},
+    {0, 0, 0}
+};
+
+struct module_exports exports = {
+    "statsd",    // module name
+    DEFAULT_DLFLAGS, // dlopen flags
+    commands,        // exported functions
+    parameters,      // exported parameters
+    NULL,            // exported statistics
+    NULL,            // exported MI functions
+    NULL,            // exported seudo-variables
+    NULL,            // extra processes
+    mod_init,        // module init function (before fork. kids will inherit)
+    NULL,            // reply processing function
+    (destroy_function) mod_destroy,     // destroy function
+    NULL       // child init function
+};
+
+
+static int mod_init(void)
+{
+    int rc = 0;
+    if(!statsd_params.ip){
+        LM_INFO("Statsd init ip value is null. use default 127.0.0.1\r\n");
+    }else{
+        LM_INFO("Statsd init ip value %s \r\n", statsd_params.ip);
+    }
+
+    if(!statsd_params.port){
+        LM_INFO("Statsd init port value is null. use default 8125\r\n");
+    } else {
+        LM_INFO("Statsd init port value %s\r\n", statsd_params.port);
+    }
+
+    rc = statsd_init(statsd_params.ip, statsd_params.port);
+    if (rc < 0){
+        LM_ERR("Statsd connection failed (ERROR_CODE: %i) \n",rc);
+        return -1;
+    }else{
+        LM_INFO("Statsd: sucess connection to statsd server\n");
+    }
+    return 0;
+}
+
+/**
+* destroy module function
+*/
+static int mod_destroy(void)
+{
+    statsd_destroy();
+    return 0;
+}
+
+static int func_gauge(struct sip_msg* msg, char* key, char* val)
+{
+    return statsd_gauge(key, val);
+}
+
+static int func_set(struct sip_msg* msg, char* key, char* val)
+{
+    return statsd_set(key, val);
+}
+
+static int func_time_start(struct sip_msg *msg, char *key)
+{
+    int_str avp_key, avp_val;
+    char unix_time[20];
+    get_milliseconds(unix_time);
+    avp_key.s.s = key;
+    avp_key.s.len = strlen(avp_key.s.s);
+
+    avp_val.s.s = unix_time;
+    avp_val.s.len = strlen(avp_val.s.s);
+
+	if (add_avp(AVP_NAME_STR|AVP_VAL_STR, avp_key, avp_val) < 0) {
+        LM_ERR("Statsd: time start failed to create AVP\n");
+        return -1;
+    }
+    return 1;
+}
+
+
+static int func_time_end(struct sip_msg *msg, char *key)
+{
+    char unix_time[20];
+    char *endptr;
+    long int start_time;
+    int result;
+
+    struct search_state st;
+
+    get_milliseconds(unix_time);
+    LM_DBG("Statsd: statsd_stop at %s\n",unix_time);
+    avp_t* prev_avp;
+
+    int_str avp_value, avp_name;
+    avp_name.s.s = key;
+    avp_name.s.len = strlen(avp_name.s.s);
+
+    prev_avp = search_first_avp(
+        AVP_NAME_STR|AVP_VAL_STR, avp_name, &avp_value, &st);
+    if(avp_value.s.len == 0){
+        LM_ERR("Statsd: statsd_stop not valid key(%s)\n",key);
+        return 1;
+    }
+
+    start_time = strtol(avp_value.s.s, &endptr,10);
+    if(strlen(endptr) >0){
+      LM_DBG(
+          "Statsd:statsd_stop not valid key(%s) it's not a number value=%s\n",
+          key, avp_value.s.s);
+      return 0;
+    }
+
+    result = atol(unix_time) - start_time;
+    LM_DBG(
+        "Statsd: statsd_stop Start_time=%ld unix_time=%ld (%i)\n",
+        start_time, atol(unix_time), result);
+    destroy_avp(prev_avp);
+    return statsd_timing(key, result);
+}
+
+
+static int func_incr(struct sip_msg *msg, char *key)
+{
+    return statsd_count(key, "+1");
+}
+
+
+static int func_decr(struct sip_msg *msg, char *key)
+{
+    return statsd_count(key, "-1");
+}
+
+
+char* get_milliseconds(char *dst){
+    struct timeval tv;
+    long int millis;
+
+    gettimeofday(&tv, NULL);
+    millis = (tv.tv_sec * (int)1000) + (tv.tv_usec / 1000);
+    snprintf(dst, 21, "%ld", millis);
+    return dst;
+}
diff --git a/modules/stun/Makefile b/modules/stun/Makefile
index beced1f..3402c9f 100644
--- a/modules/stun/Makefile
+++ b/modules/stun/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
diff --git a/modules/stun/config.c b/modules/stun/config.c
index 9afb388..bd04af7 100644
--- a/modules/stun/config.c
+++ b/modules/stun/config.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2013 Crocodile RCS Ltd
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/stun/config.h b/modules/stun/config.h
index 1be1fa6..de7d9ca 100644
--- a/modules/stun/config.h
+++ b/modules/stun/config.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2013 Crocodile RCS Ltd
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/stun/kam_stun.c b/modules/stun/kam_stun.c
index c17e57c..7859757 100644
--- a/modules/stun/kam_stun.c
+++ b/modules/stun/kam_stun.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Portions Copyright (C) 2013 Crocodile RCS Ltd
  *
  * Based on "ser_stun.c". Copyright (C) 2001-2003 FhG Fokus
@@ -22,6 +20,15 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
  */
+/*!
+ * \file
+ * \brief STUN :: Configuration
+ * \ingroup stun
+ */
+/*!
+ * \defgroup stun STUN Nat traversal support
+ * 
+ */
 
 #include <arpa/inet.h>
 #include "kam_stun.h"
diff --git a/modules/stun/kam_stun.h b/modules/stun/kam_stun.h
index 3cf85ef..0b1fb29 100644
--- a/modules/stun/kam_stun.h
+++ b/modules/stun/kam_stun.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Portions Copyright (C) 2013 Crocodile RCS Ltd
  *
  * Based on "ser_stun.h". Copyright (C) 2001-2003 FhG Fokus
@@ -22,6 +20,11 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
  */
+/*!
+ * \file
+ * \brief STUN :: Configuration
+ * \ingroup stun
+ */
 
 #ifndef _kam_stun_h
 #define _kam_stun_h
diff --git a/modules/stun/stun_mod.c b/modules/stun/stun_mod.c
index 69f3e59..adfa078 100644
--- a/modules/stun/stun_mod.c
+++ b/modules/stun/stun_mod.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2013 Crocodile RCS Ltd
  *
  * This file is part of Kamailio, a free SIP server.
@@ -20,6 +18,11 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
  */
+/*!
+ * \file
+ * \brief STUN :: Module interface
+ * \ingroup stun
+ */
 
 #include "../../dprint.h"
 #include "../../events.h"
diff --git a/modules/tcpops/Makefile b/modules/tcpops/Makefile
new file mode 100644
index 0000000..40fbcf6
--- /dev/null
+++ b/modules/tcpops/Makefile
@@ -0,0 +1,14 @@
+#
+# TCP keepelive module
+#
+# 
+# WARNING: do not run this directly, it should be run by the master Makefile
+
+include ../../Makefile.defs
+auto_gen=
+NAME=tcpops.so
+LIBS=
+
+DEFS+=-DKAMAILIO_MOD_INTERFACE
+
+include ../../Makefile.modules
diff --git a/modules/tcpops/README b/modules/tcpops/README
new file mode 100644
index 0000000..d05b800
--- /dev/null
+++ b/modules/tcpops/README
@@ -0,0 +1,148 @@
+TCP Ops module
+
+Camille Oudot
+
+   Orange
+
+   Copyright © 2015 Orange
+     __________________________________________________________________
+
+   Table of Contents
+
+   1. Admin Guide
+
+        1. Overview
+        2. Parameters
+        3. Functions
+
+              3.1. tcp_keepalive_enable([conid], idle, count, interval)
+              3.2. tcp_keepalive_disable([conid])
+              3.3. tcp_set_connection_lifetime([conid], lifetime)
+
+   List of Examples
+
+   1.1. tcp_keepalive_enable usage
+   1.2. tcp_keepalive_disable usage
+   1.3. tcp_set_connection_lifetime usage
+
+Chapter 1. Admin Guide
+
+   Table of Contents
+
+   1. Overview
+   2. Parameters
+   3. Functions
+
+        3.1. tcp_keepalive_enable([conid], idle, count, interval)
+        3.2. tcp_keepalive_disable([conid])
+        3.3. tcp_set_connection_lifetime([conid], lifetime)
+
+1. Overview
+
+   This modules allows kamailio to control the TCP options (such as the
+   keepalive mechanism), on demand, and on a per-socket basis.
+
+   Note: the keepalive functions only work on systems with the
+   HAVE_TCP_KEEPIDLE, HAVE_TCP_KEEPCNT and HAVE_TCP_KEEPINTVL macros
+   defined (currently only Linux).
+
+2. Parameters
+
+3. Functions
+
+   3.1. tcp_keepalive_enable([conid], idle, count, interval)
+   3.2. tcp_keepalive_disable([conid])
+   3.3. tcp_set_connection_lifetime([conid], lifetime)
+
+3.1.  tcp_keepalive_enable([conid], idle, count, interval)
+
+   Enables keepalive on a TCP connection.
+
+   Meaning of the parameters is as follows:
+     * conid (optionnal): the kamailio internal connection id on which TCP
+       keepalive will be enabled. If no parameter is given, the keepalive
+       mechanism will be enabled on the current message source connection.
+     * idle (seconds): the time before the first keepalive packet is sent
+       out.
+     * count: number of non-acked keepalive before reseting the
+       connection.
+     * interval (seconds): time between two keepalive probes.
+
+   Retuns 1 on success, -1 on failure.
+
+   Example 1.1. tcp_keepalive_enable usage
+request_route {
+        if (is_method("INVITE")) {
+                $avp(caller_conid) = $conid;
+                t_on_reply("foo");
+        }
+        ...
+}
+
+onreply_route[foo] {
+        if (is_method("INVITE") && status == 200) {
+                # enable on callee's connection
+                tcp_keepalive_enable("60", "5", "5");
+                # enable on caller's connection
+                tcp_keepalive_enable("$avp(caller_conid)", "60", "5", "2");
+        }
+        ...
+}
+
+3.2.  tcp_keepalive_disable([conid])
+
+   Disables keepalive on a TCP connection.
+
+   Meaning of the parameters is as follows:
+     * conid (optionnal): the kamailio internal connection id on which TCP
+       keepalive will be disabled. If no parameter is given, the keepalive
+       mechanism will be disabled on the current message source
+       connection.
+
+   Retuns 1 on success, -1 on failure.
+
+   Example 1.2. tcp_keepalive_disable usage
+request_route {
+        ...
+        if (is_method("BYE")) {
+                $avp(bye_conid) = $conid;
+                t_on_reply("foo");
+        }
+        ...
+}
+
+onreply_route[foo] {
+        ...
+        if (is_method("BYE") && status == 200) {
+                tcp_keepalive_disable();
+                tcp_keepalive_disable("$avp(bye_conid)");
+        }
+        ...
+}
+
+3.3.  tcp_set_connection_lifetime([conid], lifetime)
+
+   Sets the connection lifetime of a connection (TCP).
+
+   Meaning of the parameters is as follows:
+     * conid (optionnal): the kamailio internal connection id on which to
+       set the new lifetime. If no parameter is given, it will be set on
+       the current message source connection.
+     * lifetime (seconds): the new connection lifetime.
+
+   Retuns 1 on success, -1 on failure.
+
+   Example 1.3. tcp_set_connection_lifetime usage
+...
+# use 10s as default lifetime
+tcp_connection_lifetime=10
+...
+
+request_route {
+        ...
+        if (is_method("REGISTER") && pv_www_authenticate("$td", "xxx", "0")) {
+                # raise the TCP lifetime to a bigger value
+                tcp_set_connection_lifetime("3605");
+        }
+        ...
+}
diff --git a/modules/tcpops/doc/Makefile b/modules/tcpops/doc/Makefile
new file mode 100644
index 0000000..21a618d
--- /dev/null
+++ b/modules/tcpops/doc/Makefile
@@ -0,0 +1,4 @@
+docs = tcpops.xml
+
+docbook_dir=../../../docbook
+include $(docbook_dir)/Makefile.module
diff --git a/modules/tcpops/doc/functions.xml b/modules/tcpops/doc/functions.xml
new file mode 100644
index 0000000..16f1b86
--- /dev/null
+++ b/modules/tcpops/doc/functions.xml
@@ -0,0 +1,149 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<section id="print.functions" xmlns:xi="http://www.w3.org/2001/XInclude">
+	<sectioninfo>
+	</sectioninfo>
+
+	<title>Functions</title>
+
+	<section id="tcpops.f.tcp_keepalive_enable">
+		<title>
+			<function>tcp_keepalive_enable([conid], idle, count, interval)</function>
+		</title>
+		<para>
+				Enables keepalive on a TCP connection.
+		</para>
+		<para>Meaning of the parameters is as follows:</para>
+		<itemizedlist>
+			<listitem>
+				<para><emphasis>conid</emphasis> (optionnal): the kamailio internal
+				connection id on which TCP keepalive will be enabled. If no parameter
+				is given, the keepalive mechanism will be enabled on the current message
+				source connection.
+				</para>
+			</listitem>
+			<listitem>
+				<para><emphasis>idle</emphasis> (seconds): the time before the first
+				keepalive packet is sent out.
+				</para>
+			</listitem>
+			<listitem>
+				<para><emphasis>count</emphasis>: number of non-acked keepalive before
+				reseting the connection. 
+				</para>
+			</listitem>
+			<listitem>
+				<para><emphasis>interval</emphasis> (seconds): time between two keepalive
+				probes. 
+				</para>
+			</listitem>
+		</itemizedlist>
+		<para>Retuns 1 on success, -1 on failure.</para>
+		<example>
+			<title><function>tcp_keepalive_enable</function> usage</title>
+			<programlisting><![CDATA[
+request_route {
+	if (is_method("INVITE")) {
+		$avp(caller_conid) = $conid;
+		t_on_reply("foo");
+	}
+	...
+}
+
+onreply_route[foo] {
+	if (is_method("INVITE") && status == 200) {
+		# enable on callee's connection
+		tcp_keepalive_enable("60", "5", "5");
+		# enable on caller's connection
+		tcp_keepalive_enable("$avp(caller_conid)", "60", "5", "2");
+	}
+	...
+}
+			]]></programlisting>
+		</example>
+	</section>
+	
+	 <section id="tcpops.f.tcp_keepalive_disable">
+		<title>
+			<function>tcp_keepalive_disable([conid])</function>
+		</title>
+		<para>
+				Disables keepalive on a TCP connection.
+		</para>
+		<para>Meaning of the parameters is as follows:</para>
+		<itemizedlist>
+			<listitem>
+				<para><emphasis>conid</emphasis> (optionnal): the kamailio internal
+				connection id on which TCP keepalive will be disabled. If no parameter
+				is given, the keepalive mechanism will be disabled on the current message
+				source connection.
+				</para>
+			</listitem>
+		</itemizedlist>
+		<para>Retuns 1 on success, -1 on failure.</para>
+		<example>
+			<title><function>tcp_keepalive_disable</function> usage</title>
+			<programlisting><![CDATA[
+request_route {
+	...
+	if (is_method("BYE")) {
+		$avp(bye_conid) = $conid;
+		t_on_reply("foo");
+	}
+	...
+}
+
+onreply_route[foo] {
+	...
+	if (is_method("BYE") && status == 200) {
+		tcp_keepalive_disable();
+		tcp_keepalive_disable("$avp(bye_conid)");
+	}
+	...
+}
+			]]></programlisting>
+		</example>
+	</section>
+	<section id="tcpops.f.tcp_set_connection_lifetime">
+                <title>
+                        <function>tcp_set_connection_lifetime([conid], lifetime)</function>
+                </title>
+                <para>
+                                Sets the connection lifetime of a connection (TCP).
+                </para>
+                <para>Meaning of the parameters is as follows:</para>
+                <itemizedlist>
+                        <listitem>
+                                <para><emphasis>conid</emphasis> (optionnal): the kamailio internal
+                                connection id on which to set the new lifetime. If no parameter
+                                is given, it will be set on the current message source connection.
+                                </para>
+                        </listitem>
+                        <listitem>
+                                <para><emphasis>lifetime</emphasis> (seconds): the new connection lifetime.
+                                </para>
+                        </listitem>
+                </itemizedlist>
+                <para>Retuns 1 on success, -1 on failure.</para>
+                <example>
+                        <title><function>tcp_set_connection_lifetime</function> usage</title>
+                        <programlisting><![CDATA[
+...
+# use 10s as default lifetime
+tcp_connection_lifetime=10 
+...
+
+request_route {
+        ...
+        if (is_method("REGISTER") && pv_www_authenticate("$td", "xxx", "0")) {
+                # raise the TCP lifetime to a bigger value
+                tcp_set_connection_lifetime("3605");
+        }
+        ...
+}
+                        ]]></programlisting>
+                </example>
+        </section>
+</section>
diff --git a/modules/tcpops/doc/params.xml b/modules/tcpops/doc/params.xml
new file mode 100644
index 0000000..eb6af5b
--- /dev/null
+++ b/modules/tcpops/doc/params.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<section id="print.parameters" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <sectioninfo>
+    </sectioninfo>
+
+    <title>Parameters</title>
+
+
+
+</section>
diff --git a/modules/tcpops/doc/tcpops.xml b/modules/tcpops/doc/tcpops.xml
new file mode 100644
index 0000000..1c3a305
--- /dev/null
+++ b/modules/tcpops/doc/tcpops.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<book id="print" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <bookinfo>
+        <title>TCP Ops module</title>
+	<authorgroup>
+	    <author>
+		<firstname>Camille</firstname>
+		<surname>Oudot</surname>
+		<affiliation><orgname>Orange</orgname></affiliation>
+		<address>
+		    <email>camille.oudot at orange.com</email>
+		</address>
+	    </author>
+	</authorgroup>
+	<copyright>
+	    <year>2015</year>
+	    <holder>Orange</holder>
+	</copyright>
+    </bookinfo>
+    <toc></toc>
+
+    <chapter>
+	<title>Admin Guide</title>
+    <section id="tcpops.overview">
+	<title>Overview</title>
+	<para>
+	    This modules allows kamailio to control the TCP options (such as the keepalive
+	    mechanism), on demand, and on a per-socket basis.
+	</para>
+	<para>
+	<emphasis>Note</emphasis>: the keepalive functions only work on systems with the
+	HAVE_TCP_KEEPIDLE, HAVE_TCP_KEEPCNT and HAVE_TCP_KEEPINTVL macros defined
+	(currently only Linux).
+	</para>
+    </section>
+    
+    <xi:include href="params.xml"/>
+    <xi:include href="functions.xml"/>
+    </chapter>
+</book>
+
diff --git a/modules/tcpops/tcpops.c b/modules/tcpops/tcpops.c
new file mode 100644
index 0000000..037a8cb
--- /dev/null
+++ b/modules/tcpops/tcpops.c
@@ -0,0 +1,187 @@
+/**
+ * Copyright 2015 (C) Orange
+ * <camille.oudot at orange.com>
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/tcp.h>
+#include <errno.h>
+
+#include "../../dprint.h"
+#include "../../tcp_options.h"
+#include "../../tcp_conn.h"
+#include "../../globals.h"
+#include "../../pass_fd.h"
+#include "../../timer.h"
+
+/**
+ * gets the fd of the current message source connection
+ *
+ * @param conid - connection id
+ * @param fd - placeholder to return the fd
+ * @return 1 on success, 0 on failure
+ *
+ */
+int tcpops_get_current_fd(int conid, int *fd)
+{
+	struct tcp_connection *s_con;
+	if (unlikely((s_con = tcpconn_get(conid, 0, 0, 0, 0)) == NULL)) {
+		LM_ERR("invalid connection id %d, (must be a TCP connid)\n", conid);
+		return 0;
+	}
+	LM_DBG("got fd=%d from id=%d\n", s_con->fd, conid);
+
+	*fd = s_con->fd;
+	tcpconn_put(s_con);
+	return 1;
+}
+
+/**
+ * Request the fd corresponding to the given connection id to the TCP main process.
+ * You may want to close() the fd after use.
+ *
+ * @param conid - connection id
+ * @param fd - placeholder to return the fd
+ * @return 1 on success, 0 on failure
+ *
+ */
+int tcpops_acquire_fd_from_tcpmain(int conid, int *fd)
+{
+	struct tcp_connection *s_con, *tmp;
+	long msg[2];
+	int n;
+
+	if (unlikely((s_con = tcpconn_get(conid, 0, 0, 0, 0)) == NULL)) {
+		LM_ERR("invalid connection id %d, (must be a TCP connid)\n", conid);
+		return 0;
+	}
+
+	msg[0] = (long)s_con;
+	msg[1] = CONN_GET_FD;
+
+	n = send_all(unix_tcp_sock, msg, sizeof(msg));
+	if (unlikely(n <= 0)){
+		LM_ERR("failed to send fd request: %s (%d)\n", strerror(errno), errno);
+		goto error_release;
+	}
+
+	n = receive_fd(unix_tcp_sock, &tmp, sizeof(tmp), fd, MSG_WAITALL);
+	if (unlikely(n <= 0)){
+		LM_ERR("failed to get fd (receive_fd): %s (%d)\n", strerror(errno), errno);
+		goto error_release;
+	}
+	tcpconn_put(s_con);
+	return 1;
+
+error_release:
+	tcpconn_put(s_con);
+	return 0;
+}
+
+#if !defined(HAVE_SO_KEEPALIVE) || !defined(HAVE_TCP_KEEPIDLE) || !defined(HAVE_TCP_KEEPCNT) || !defined(HAVE_TCP_KEEPINTVL)
+	#warning "TCP keepalive is not fully supported by your platform"
+
+int tcpops_keepalive_enable(int fd, int idle, int count, int interval, int closefd)
+{
+	LM_ERR("tcp_keepalive_enable() failed: this module does not support your platform\n");
+	return -1;
+}
+
+int tcpops_keepalive_disable(int fd, int closefd)
+{
+	LM_ERR("tcp_keepalive_disable() failed: this module does not support your platform\n");
+	return -1;
+}
+#else
+
+int tcpops_keepalive_enable(int fd, int idle, int count, int interval, int closefd)
+{
+	static const int enable = 1;
+	int ret = -1;
+
+	if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &enable,
+					sizeof(enable))<0){
+		LM_ERR("failed to enable SO_KEEPALIVE: %s\n", strerror(errno));
+		return -1;
+	} else {
+
+		if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &idle,
+						sizeof(idle))<0){
+			LM_ERR("failed to set keepalive idle interval: %s\n", strerror(errno));
+		}
+
+		if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &count,
+						sizeof(count))<0){
+			LM_ERR("failed to set maximum keepalive count: %s\n", strerror(errno));
+		}
+
+		if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &interval,
+						sizeof(interval))<0){
+			LM_ERR("failed to set keepalive probes interval: %s\n", strerror(errno));
+		}
+
+		ret = 1;
+		LM_DBG("keepalive enabled for fd=%d, idle=%d, cnt=%d, intvl=%d\n", fd, idle, count, interval);
+	}
+
+	if (closefd)
+	{
+		close(fd);
+	}
+	return ret;
+}
+
+int tcpops_keepalive_disable(int fd, int closefd)
+{
+	static const int disable = 0;
+	int ret = -1;
+
+	if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &disable,
+					sizeof(disable))<0){
+		LM_WARN("failed to disable SO_KEEPALIVE: %s\n", strerror(errno));
+	} else {
+		ret = 1;
+		LM_DBG("keepalive disabled for fd=%d\n", fd);
+	}
+
+	if (closefd)
+	{
+		close(fd);
+	}
+	return ret;
+}
+
+#endif
+
+int tcpops_set_connection_lifetime(struct tcp_connection* con, int time) {
+	if (unlikely(con == NULL)) {
+		LM_CRIT("BUG: con == NULL");
+		return -1;
+	}
+	if (unlikely(time < 0)) {
+		LM_ERR("Invalid timeout value, %d, must be >= 0\n", time);
+		return -1;
+	}
+	con->lifetime = S_TO_TICKS(time);
+	con->timeout = get_ticks_raw() + con->lifetime;
+	LM_DBG("new connection lifetime for conid=%d: %d\n", con->id, con->timeout);
+	return 1;
+}
diff --git a/modules/tcpops/tcpops.h b/modules/tcpops/tcpops.h
new file mode 100644
index 0000000..c9a0771
--- /dev/null
+++ b/modules/tcpops/tcpops.h
@@ -0,0 +1,35 @@
+/**
+ * Copyright 2015 (C) Orange
+ * <camille.oudot at orange.com>
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef TCP_KEEPALIVE_H_
+#define TCP_KEEPALIVE_H_
+
+#include "../../tcp_conn.h"
+
+int tcpops_get_current_fd(int conid, int *fd);
+int tcpops_acquire_fd_from_tcpmain(int conid, int *fd);
+int tcpops_keepalive_enable(int fd, int idle, int count, int interval, int closefd);
+int tcpops_keepalive_disable(int fd, int closefd);
+int tcpops_set_connection_lifetime(struct tcp_connection* con, int time);
+
+#endif /* TCP_KEEPALIVE_H_ */
diff --git a/modules/tcpops/tcpops_mod.c b/modules/tcpops/tcpops_mod.c
new file mode 100644
index 0000000..fb565de
--- /dev/null
+++ b/modules/tcpops/tcpops_mod.c
@@ -0,0 +1,269 @@
+/**
+ * Copyright 2015 (C) Orange
+ * <camille.oudot at orange.com>
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../../globals.h"
+#include "../../sr_module.h"
+#include "../../tcp_options.h"
+#include "../../dprint.h"
+#include "../../mod_fix.h"
+
+#include "tcpops.h"
+
+MODULE_VERSION
+
+static int  mod_init(void);
+static int  child_init(int);
+static void mod_destroy(void);
+static int w_tcp_keepalive_enable4(sip_msg_t* msg, char* con, char* idle, char *cnt, char *intvl);
+static int w_tcp_keepalive_enable3(sip_msg_t* msg, char* idle, char *cnt, char *intvl);
+static int w_tcp_keepalive_disable1(sip_msg_t* msg, char* con);
+static int w_tcp_keepalive_disable0(sip_msg_t* msg);
+static int w_tcpops_set_connection_lifetime2(sip_msg_t* msg, char* con, char* time);
+static int w_tcpops_set_connection_lifetime1(sip_msg_t* msg, char* time);
+
+static int fixup_numpv(void** param, int param_no);
+
+
+static cmd_export_t cmds[]={
+	{"tcp_keepalive_enable", (cmd_function)w_tcp_keepalive_enable4, 4, fixup_numpv,
+		0, ANY_ROUTE},
+	{"tcp_keepalive_enable", (cmd_function)w_tcp_keepalive_enable3, 3, fixup_numpv,
+		0, REQUEST_ROUTE|ONREPLY_ROUTE},
+	{"tcp_keepalive_disable", (cmd_function)w_tcp_keepalive_disable1, 1, fixup_numpv,
+		0, ANY_ROUTE},
+	{"tcp_keepalive_disable", (cmd_function)w_tcp_keepalive_disable0, 0, 0,
+		0, REQUEST_ROUTE|ONREPLY_ROUTE},
+	{"tcp_set_connection_lifetime", (cmd_function)w_tcpops_set_connection_lifetime2, 2, fixup_numpv,
+		0, ANY_ROUTE},
+	{"tcp_set_connection_lifetime", (cmd_function)w_tcpops_set_connection_lifetime1, 1, fixup_numpv,
+		0, REQUEST_ROUTE|ONREPLY_ROUTE},
+	{0, 0, 0, 0, 0, 0}
+};
+
+
+
+struct module_exports exports = {
+	"tcpops",
+	DEFAULT_DLFLAGS, /* dlopen flags */
+	cmds,            /* exported functions to config */
+	0,          /* exported parameters to config */
+	0,               /* exported statistics */
+	0,              /* exported MI functions */
+	0,        /* exported pseudo-variables */
+	0,              /* extra processes */
+	mod_init,       /* module initialization function */
+	0,              /* response function */
+	mod_destroy,    /* destroy function */
+	child_init      /* per child init function */
+};
+
+
+
+/**
+ * init module function
+ */
+static int mod_init(void)
+{
+	LM_DBG("TCP keepalive module loaded.\n");
+
+	return 0;
+}
+
+/**
+ * @brief Initialize async module children
+ */
+static int child_init(int rank)
+{
+
+	return 0;
+}
+/**
+ * destroy module function
+ */
+static void mod_destroy(void)
+{
+	LM_DBG("TCP keepalive module unloaded.\n");
+}
+
+#define _IVALUE_ERROR(NAME) LM_ERR("invalid parameter '" #NAME "' (must be a number)\n")
+#define _IVALUE(NAME)\
+int i_##NAME ;\
+if(fixup_get_ivalue(msg, (gparam_t*)NAME, &( i_##NAME))!=0)\
+{ \
+	_IVALUE_ERROR(NAME);\
+	return -1;\
+}
+
+
+/**
+ *
+ */
+static int w_tcp_keepalive_enable4(sip_msg_t* msg, char* con, char* idle, char *cnt, char *intvl)
+{
+	int fd;
+	int closefd = 0;
+
+	_IVALUE (con)
+
+	if (msg != NULL && msg->rcv.proto_reserved1 == i_con) {
+		if (!tcpops_get_current_fd(msg->rcv.proto_reserved1, &fd)) {
+			return -1;
+		}
+	} else {
+		if (!tcpops_acquire_fd_from_tcpmain(i_con, &fd)) {
+			return -1;
+		}
+		closefd = 1;
+	}
+
+	_IVALUE (idle)
+	_IVALUE (cnt)
+	_IVALUE (intvl)
+
+	return tcpops_keepalive_enable(fd, i_idle, i_cnt, i_intvl, closefd);
+
+}
+
+static int w_tcp_keepalive_enable3(sip_msg_t* msg, char* idle, char *cnt, char *intvl)
+{
+	int fd;
+
+	if (unlikely(msg == NULL)) {
+		return -1;
+	}
+
+	if(unlikely(msg->rcv.proto != PROTO_TCP && msg->rcv.proto != PROTO_TLS && msg->rcv.proto != PROTO_WS && msg->rcv.proto != PROTO_WSS))
+	{
+		LM_ERR("the current message does not come from a TCP connection\n");
+		return -1;
+	}
+
+	if (!tcpops_get_current_fd(msg->rcv.proto_reserved1, &fd)) {
+		return -1;
+	}
+
+	_IVALUE (idle)
+	_IVALUE (cnt)
+	_IVALUE (intvl)
+
+	return tcpops_keepalive_enable(fd, i_idle, i_cnt, i_intvl, 0);
+}
+
+static int w_tcp_keepalive_disable1(sip_msg_t* msg, char* con)
+{
+	int fd;
+	int closefd = 0;
+
+	_IVALUE (con)
+
+	if (msg != NULL && msg->rcv.proto_reserved1 == i_con) {
+		if (!tcpops_get_current_fd(msg->rcv.proto_reserved1, &fd)) {
+			return -1;
+		}
+	} else {
+		if (!tcpops_acquire_fd_from_tcpmain(i_con, &fd)) {
+			return -1;
+		}
+		closefd = 1;
+	}
+
+	return tcpops_keepalive_disable(fd, closefd);
+}
+
+static int w_tcp_keepalive_disable0(sip_msg_t* msg)
+{
+	int fd;
+
+	if (unlikely(msg == NULL))
+		return -1;
+
+	if(unlikely(msg->rcv.proto != PROTO_TCP && msg->rcv.proto != PROTO_TLS && msg->rcv.proto != PROTO_WS && msg->rcv.proto != PROTO_WSS))
+	{
+		LM_ERR("the current message does not come from a TCP connection\n");
+		return -1;
+	}
+
+	if (!tcpops_get_current_fd(msg->rcv.proto_reserved1, &fd)) {
+		return -1;
+	}
+
+	return tcpops_keepalive_disable(fd, 0);
+}
+
+
+static int w_tcpops_set_connection_lifetime2(sip_msg_t* msg, char* conid, char* time)
+{
+	struct tcp_connection *s_con;
+	int ret = -1;
+
+	_IVALUE (conid)
+	_IVALUE (time)
+
+	if (unlikely((s_con = tcpconn_get(i_conid, 0, 0, 0, 0)) == NULL)) {
+		LM_ERR("invalid connection id %d, (must be a TCP connid)\n", i_conid);
+		return 0;
+	} else {
+		ret = tcpops_set_connection_lifetime(s_con, i_time);
+		tcpconn_put(s_con);
+	}
+	return ret;
+}
+
+
+static int w_tcpops_set_connection_lifetime1(sip_msg_t* msg, char* time)
+{
+	struct tcp_connection *s_con;
+	int ret = -1;
+
+	_IVALUE (time)
+
+	if(unlikely(msg->rcv.proto != PROTO_TCP && msg->rcv.proto != PROTO_TLS && msg->rcv.proto != PROTO_WS && msg->rcv.proto != PROTO_WSS))
+	{
+		LM_ERR("the current message does not come from a TCP connection\n");
+		return -1;
+	}
+
+	if (unlikely((s_con = tcpconn_get(msg->rcv.proto_reserved1, 0, 0, 0, 0)) == NULL)) {
+		return -1;
+	} else {
+		ret = tcpops_set_connection_lifetime(s_con, i_time);
+		tcpconn_put(s_con);
+	}
+	return ret;
+}
+
+/**
+ *
+ */
+static int fixup_numpv(void** param, int param_no)
+{
+	return fixup_igp_null(param, 1);
+}
+
+
diff --git a/modules/textops/Makefile b/modules/textops/Makefile
index ab954e1..6cb97fb 100644
--- a/modules/textops/Makefile
+++ b/modules/textops/Makefile
@@ -1,6 +1,5 @@
-# $Id$
 #
-# print example module makefile
+# textops example module makefile
 #
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
diff --git a/modules/textops/api.c b/modules/textops/api.c
index fbf86ff..4515201 100644
--- a/modules/textops/api.c
+++ b/modules/textops/api.c
@@ -17,9 +17,13 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  *
  *
- * History:
- * ---------
- *  2008-07-14 first version (Ardjan Zwartjes)
+ */
+
+/*!
+ * \file
+ * \brief API integration
+ * \ingroup textops
+ * Module: \ref textops
  */
 
 
diff --git a/modules/textops/api.h b/modules/textops/api.h
index 042aa7e..10474b5 100644
--- a/modules/textops/api.h
+++ b/modules/textops/api.h
@@ -16,12 +16,16 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  *
- *
- * History:
- * ---------
- *  2008-07-14 first version (Ardjan Zwartjes)
  */
 
+/*!
+ * \file
+ * \brief API
+ * \ingroup textops
+ * Module: \ref textops
+ */
+
+
 
 #ifndef TEXTOPS_API_H_
 #define TEXTOPS_API_H_
diff --git a/modules/textops/textops.c b/modules/textops/textops.c
index fa8874f..7c5e2af 100644
--- a/modules/textops/textops.c
+++ b/modules/textops/textops.c
@@ -1,5 +1,4 @@
-/*$Id$
- *
+/*
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,35 +18,21 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
  *
- * History:
- * -------
- *  2003-02-28  scratchpad compatibility abandoned (jiri)
- *  2003-01-29: - rewriting actions (replace, search_append) now begin
- *                at the second line -- previously, they could affect
- *                first line too, which resulted in wrong calculation of
- *                forwarded requests and an error consequently
- *              - replace_all introduced
- *  2003-01-28  scratchpad removed (jiri)
- *  2003-01-18  append_urihf introduced (jiri)
- *  2003-03-10  module export interface updated to the new format (andrei)
- *  2003-03-16  flags export parameter added (janakj)
- *  2003-03-19  replaced all mallocs/frees w/ pkg_malloc/pkg_free (andrei)
- *  2003-04-97  actions permitted to be used from failure/reply routes (jiri)
- *  2003-04-21  remove_hf and is_present_hf introduced (jiri)
- *  2003-08-19  subst added (support for sed like res:s/re/repl/flags) (andrei)
- *  2003-08-20  subst_uri added (like above for uris) (andrei)
- *  2003-09-11  updated to new build_lump_rpl() interface (bogdan)
- *  2003-11-11: build_lump_rpl() removed, add_lump_rpl() has flags (bogdan)
- *  2004-05-09: append_time introduced (jiri)
- *  2004-07-06  subst_user added (like subst_uri but only for user) (sobomax)
- *  2004-11-12  subst_user changes (old serdev mails) (andrei)
- *  2005-07-05  is_method("name") to check method using id (ramona)
- *  2006-03-17  applied patch from Marc Haisenko <haisenko at comdasys.com> 
- *              for adding has_body() function (bogdan)
- *  2008-07-14  Moved some function declarations to a separate file (Ardjan Zwartjes) 
- *
  */
 
+/*!
+ * \file
+ * \brief Module interface
+ * \ingroup textops
+ * Module: \ref textops
+ */
+
+/**
+ * @defgroup Textops Various text operatoins on messages
+ * @brief Kamailio textops module
+ */
+
+
 
 #include "../../action.h"
 #include "../../sr_module.h"
diff --git a/modules/textops/textops.h b/modules/textops/textops.h
index 0226f14..50a0cc3 100644
--- a/modules/textops/textops.h
+++ b/modules/textops/textops.h
@@ -17,11 +17,16 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  *
  *
- * History:
- * ---------
- *  2008-07-14 first version, function definitions copied from textops.c (Ardjan Zwartjes)
  */
 
+/*!
+ * \file
+ * \brief Module interface
+ * \ingroup textops
+ * Module: \ref textops
+ */
+
+
 #ifndef TEXTOPS_H_
 #define TEXTOPS_H_
 #include "../../mod_fix.h"
diff --git a/modules/textops/txt_var.c b/modules/textops/txt_var.c
index 884ed95..0f704e3 100644
--- a/modules/textops/txt_var.c
+++ b/modules/textops/txt_var.c
@@ -1,6 +1,4 @@
-/**
- * $Id$
- *
+/*
  * Copyright (C) 2008 Elena-Ramona Modroiu (asipto.com)
  *
  * This file is part of kamailio, a free SIP server.
@@ -20,6 +18,14 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
+/*!
+ * \file
+ * \brief Regular expressions
+ * \ingroup textops
+ * Module: \ref textops
+ */
+
+
 #include <stdio.h>
 #include <string.h>
 #include <sys/types.h>
diff --git a/modules/textops/txt_var.h b/modules/textops/txt_var.h
index 024df10..22edc4c 100644
--- a/modules/textops/txt_var.h
+++ b/modules/textops/txt_var.h
@@ -1,6 +1,4 @@
-/**
- * $Id$
- *
+/*
  * Copyright (C) 2008 Elena-Ramona Modroiu (asipto.com)
  *
  * This file is part of kamailio, a free SIP server.
@@ -19,6 +17,14 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
+
+/*!
+ * \file
+ * \brief Regular expressions
+ * \ingroup textops
+ * Module: \ref textops
+ */
+
 		       
 #ifndef _TXT_VAR_H_
 #define _TXT_VAR_H_
diff --git a/modules/textopsx/Makefile b/modules/textopsx/Makefile
index acb320c..e86dd56 100644
--- a/modules/textopsx/Makefile
+++ b/modules/textopsx/Makefile
@@ -1,6 +1,5 @@
-# $Id$
 #
-# print example module makefile
+# textopsx example module makefile
 #
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
diff --git a/modules/textopsx/README b/modules/textopsx/README
index 3ff68fe..5239885 100644
--- a/modules/textopsx/README
+++ b/modules/textopsx/README
@@ -33,11 +33,12 @@ Daniel-Constantin Mierla
               2.12. include_hf_value(hf, hvalue)
               2.13. exclude_hf_value(hf, hvalue)
               2.14. hf_value_exists(hf, hvalue)
-              2.15. Selects
 
-                    2.15.1. @hf_value
-                    2.15.2. @hf_value2
-                    2.15.3. @hf_value_exists
+        3. Selects
+
+              3.1. @hf_value
+              3.2. @hf_value2
+              3.3. @hf_value_exists
 
    List of Examples
 
@@ -78,11 +79,12 @@ Chapter 1. Admin Guide
         2.12. include_hf_value(hf, hvalue)
         2.13. exclude_hf_value(hf, hvalue)
         2.14. hf_value_exists(hf, hvalue)
-        2.15. Selects
 
-              2.15.1. @hf_value
-              2.15.2. @hf_value2
-              2.15.3. @hf_value_exists
+   3. Selects
+
+        3.1. @hf_value
+        3.2. @hf_value2
+        3.3. @hf_value_exists
 
 1. Overview
 
@@ -106,11 +108,6 @@ Chapter 1. Admin Guide
    2.12. include_hf_value(hf, hvalue)
    2.13. exclude_hf_value(hf, hvalue)
    2.14. hf_value_exists(hf, hvalue)
-   2.15. Selects
-
-        2.15.1. @hf_value
-        2.15.2. @hf_value2
-        2.15.3. @hf_value_exists
 
 2.1. msg_apply_changes()
 
@@ -375,9 +372,13 @@ if (@hf_value_exists.supported.path == "1") {
 }
 ...
 
-2.15. Selects
+3. Selects
+
+   3.1. @hf_value
+   3.2. @hf_value2
+   3.3. @hf_value_exists
 
-2.15.1. @hf_value
+3.1. @hf_value
 
    Get value of required header-value or param. Note that functions called
    'value2' works with Authorization-like headers where comma is not
@@ -418,10 +419,10 @@ $rr = @hf_value.route.uri;
 $prt = @hf_value2.authorization.integrity_protected;
 ...
 
-2.15.2. @hf_value2
+3.2. @hf_value2
 
    TBA.
 
-2.15.3. @hf_value_exists
+3.3. @hf_value_exists
 
    TBA.
diff --git a/modules/textopsx/doc/functions.xml b/modules/textopsx/doc/functions.xml
index 53fd113..204c227 100644
--- a/modules/textopsx/doc/functions.xml
+++ b/modules/textopsx/doc/functions.xml
@@ -438,81 +438,4 @@ if (@hf_value_exists.supported.path == "1") {
 	</example>
     </section>
 
-	<section>
-	<title>Selects</title>
-    <section id="textopsx.sel.hf_value">
-	<title>@hf_value</title>
-	<para>
-		Get value of required header-value or param. Note that functions called 'value2'
-		works with Authorization-like headers where comma is not treated as value delimiter. Formats:
-		@hf_value.HFNAME[IDX]    # idx value, negative value counts from bottom
-		@hf_value.HFNAME.PARAM_NAME
-		@hf_value.HFNAME[IDX].PARAM_NAME
-		@hf_value.HFNAME.p.PARAM_NAME  # or .param., useful if requred called "uri", "p", "param"
-		@hf_value.HFNAME[IDX].p.PARAM_NAME # dtto
-		@hf_value.HFNAME[IDX].uri # (< & > excluded)
-		@hf_value.HFNAME[*]     # return comma delimited list of all values (combines headers)
-		@hf_value.HFNAME        # the same as above [*] but may be parsed by cfg.y
-		@hf_value.HFNAME[*].uri # return comma delimited list of uris (< & > excluded)
-		@hf_value.HFNAME.uri    # the same as above [*] but may be parsed by cfg.y
-		@hf_value.HFNAME[IDX].name  # returns name part, quotes excluded
-		@hf_value.HFNAME.name   # returns name part of the first value
-
-		@hf_value2.HFNAME        # returns value of first header
-		@hf_value2.HFNAME[IDX]   # returns value of idx's header
-		@hf_value2.HFNAME.PARAM_NAME
-		@hf_value2.HFNAME[IDX].PARAM_NAME
-
-		@hf_value.HFNAME[IDX].uri  # return URI, quotes excluded
-		@hf_value.HFNAME.p.uri  # returns param named uri, not URI itself
-		@hf_value.HFNAME.p.name # returns param named name, not name itself
-		@hf_value.HFNAME[IDX].uri.name #  any sel_any_uri nested features may be used
-		@hf_value.HFNAME[IDX].nameaddr.name # select_any_nameaddr
-	</para>
-	<para>Meaning of the parameters is as follows:</para>
-	<itemizedlist>
-	    <listitem>
-		<para><emphasis>HFNAME</emphasis> - Header field name. Underscores are treated as dashes.
-		</para>
-	    </listitem>
-	    <listitem>
-		<para><emphasis>IDX</emphasis> - Value index, negative value counts from bottom
-		</para>
-	    </listitem>
-	    <listitem>
-		<para><emphasis>PARAM_NAME</emphasis> - name of parameter
-		</para>
-	    </listitem>
-	</itemizedlist>
-	<example>
-	    <title><function>@hf_value select</function> usage</title>
-	    <programlisting>
-...
-$a = @hf_value.my_header[1].my_param;
-xplog("L_ERR", "$sel(@hf_value.via[-1]), $sel(@hf_value.from.tag)\n");
-$b = @hf_value.p_associated_uri;
-
-xplog("L_ERR", "Route uris: '$sel(@hf_value.route[*].uri)'\n");
-$rr = @hf_value.route.uri;
-
-$prt = @hf_value2.authorization.integrity_protected;
-...
-	    </programlisting>
-	</example>
-    </section>
-    <section id="textopsx.sel.hf_value2">
-	<title>@hf_value2</title>
-	<para>
-		TBA.
-	</para>
-    </section>
-    <section id="textopsx.sel.hf_value_exists">
-	<title>@hf_value_exists</title>
-	<para>
-		TBA.
-	</para>
-    </section>
-
-    </section>
-
 </section>
diff --git a/modules/textopsx/doc/selects.xml b/modules/textopsx/doc/selects.xml
new file mode 100644
index 0000000..1b3a443
--- /dev/null
+++ b/modules/textopsx/doc/selects.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<section id="textopsx.selects" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <title>Selects</title>
+
+    <section id="textopsx.sel.hf_value">
+	<title>@hf_value</title>
+	<para>
+		Get value of required header-value or param. Note that functions called 'value2'
+		works with Authorization-like headers where comma is not treated as value delimiter. Formats:
+		@hf_value.HFNAME[IDX]    # idx value, negative value counts from bottom
+		@hf_value.HFNAME.PARAM_NAME
+		@hf_value.HFNAME[IDX].PARAM_NAME
+		@hf_value.HFNAME.p.PARAM_NAME  # or .param., useful if requred called "uri", "p", "param"
+		@hf_value.HFNAME[IDX].p.PARAM_NAME # dtto
+		@hf_value.HFNAME[IDX].uri # (< & > excluded)
+		@hf_value.HFNAME[*]     # return comma delimited list of all values (combines headers)
+		@hf_value.HFNAME        # the same as above [*] but may be parsed by cfg.y
+		@hf_value.HFNAME[*].uri # return comma delimited list of uris (< & > excluded)
+		@hf_value.HFNAME.uri    # the same as above [*] but may be parsed by cfg.y
+		@hf_value.HFNAME[IDX].name  # returns name part, quotes excluded
+		@hf_value.HFNAME.name   # returns name part of the first value
+
+		@hf_value2.HFNAME        # returns value of first header
+		@hf_value2.HFNAME[IDX]   # returns value of idx's header
+		@hf_value2.HFNAME.PARAM_NAME
+		@hf_value2.HFNAME[IDX].PARAM_NAME
+
+		@hf_value.HFNAME[IDX].uri  # return URI, quotes excluded
+		@hf_value.HFNAME.p.uri  # returns param named uri, not URI itself
+		@hf_value.HFNAME.p.name # returns param named name, not name itself
+		@hf_value.HFNAME[IDX].uri.name #  any sel_any_uri nested features may be used
+		@hf_value.HFNAME[IDX].nameaddr.name # select_any_nameaddr
+	</para>
+	<para>Meaning of the parameters is as follows:</para>
+	<itemizedlist>
+	    <listitem>
+		<para><emphasis>HFNAME</emphasis> - Header field name. Underscores are treated as dashes.
+		</para>
+	    </listitem>
+	    <listitem>
+		<para><emphasis>IDX</emphasis> - Value index, negative value counts from bottom
+		</para>
+	    </listitem>
+	    <listitem>
+		<para><emphasis>PARAM_NAME</emphasis> - name of parameter
+		</para>
+	    </listitem>
+	</itemizedlist>
+	<example>
+	    <title><function>@hf_value select</function> usage</title>
+	    <programlisting>
+...
+$a = @hf_value.my_header[1].my_param;
+xplog("L_ERR", "$sel(@hf_value.via[-1]), $sel(@hf_value.from.tag)\n");
+$b = @hf_value.p_associated_uri;
+
+xplog("L_ERR", "Route uris: '$sel(@hf_value.route[*].uri)'\n");
+$rr = @hf_value.route.uri;
+
+$prt = @hf_value2.authorization.integrity_protected;
+...
+	    </programlisting>
+	</example>
+    </section>
+    <section id="textopsx.sel.hf_value2">
+	<title>@hf_value2</title>
+	<para>
+		TBA.
+	</para>
+    </section>
+    <section id="textopsx.sel.hf_value_exists">
+	<title>@hf_value_exists</title>
+	<para>
+		TBA.
+	</para>
+    </section>
+
+</section>
diff --git a/modules/textopsx/doc/textopsx.xml b/modules/textopsx/doc/textopsx.xml
index d8f923b..b7fe0d1 100644
--- a/modules/textopsx/doc/textopsx.xml
+++ b/modules/textopsx/doc/textopsx.xml
@@ -40,6 +40,7 @@
     </section>
 
     <xi:include href="functions.xml"/>
+    <xi:include href="selects.xml"/>
     </chapter>
 </book>
 
diff --git a/modules/timer/Makefile b/modules/timer/Makefile
index c1a1614..f19f1eb 100644
--- a/modules/timer/Makefile
+++ b/modules/timer/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # timer module makefile
 #
diff --git a/modules/timer/README b/modules/timer/README
index 22dade4..e6af28c 100644
--- a/modules/timer/README
+++ b/modules/timer/README
@@ -1,4 +1,3 @@
-
 timer module
 
 Tomas Mandys
@@ -6,7 +5,7 @@ Tomas Mandys
    Iptel.org
 
    Copyright � 2007 iptelorg GmbH
-     _________________________________________________________________
+     __________________________________________________________________
 
    Table of Contents
 
@@ -21,9 +20,9 @@ Tomas Mandys
 
         5. Functions
 
-              5.1. timer_enable(timer_id, enable_disable) 
-              5.2. @timer.timer.timer_id.enabled 
-              5.3. @timer.executed 
+              5.1. timer_enable(timer_id, enable_disable)
+              5.2. @timer.timer.timer_id.enabled
+              5.3. @timer.executed
 
         6. Examples
 
@@ -49,9 +48,9 @@ Chapter 1. Admin Guide
 
    5. Functions
 
-        5.1. timer_enable(timer_id, enable_disable) 
-        5.2. @timer.timer.timer_id.enabled 
-        5.3. @timer.executed 
+        5.1. timer_enable(timer_id, enable_disable)
+        5.2. @timer.timer.timer_id.enabled
+        5.3. @timer.executed
 
    6. Examples
 
@@ -67,8 +66,8 @@ Chapter 1. Admin Guide
 
         timer_id = alphanum
         slow_fast = "slow" | "fast"
-        declare_timer_syntax = timer_id "=" (route#|route_name) "," interval ",
-" slow_fast "," ["enable"]
+        declare_timer_syntax = timer_id "=" (route#|route_name) "," interval ","
+ slow_fast "," ["enable"]
         enable_disable = "0" | "1"
 
 4. Parameters
@@ -83,31 +82,31 @@ Chapter 1. Admin Guide
                         declare_timer = declare_timer_syntax
 
    timer_id is timer identifier, route is handler to be called when timer
-   is  triggered,  interval  is timer interval in milliseconds, slow_fast
+   is triggered, interval is timer interval in milliseconds, slow_fast
    determines if handler will be hooked in slow or fast timer queue, fast
-   timer  handler  returns as quickly as possible, slow timer handler may
-   spend longer time, see ser/doc/timers.txt documentation. Use enable to
-   enable timer when ser is starting, otherwise use timer_enable to start
-   it later.
+   timer handler returns as quickly as possible, slow timer handler may
+   spend longer time, see kamailio/doc/timers.txt documentation. Use
+   enable to enable timer when Kamailio is starting, otherwise use
+   timer_enable to start it later.
 
    Example 1.1. Example declare_timer
         ...
-        modparam("timer", "declare_timer", "MY_TIMER=MY_TIMER_ROUTE,10,slow,ena
-ble");
+        modparam("timer", "declare_timer", "MY_TIMER=MY_TIMER_ROUTE,10,slow,enab
+le");
         ...
 
 5. Functions
 
-   5.1. timer_enable(timer_id, enable_disable) 
-   5.2. @timer.timer.timer_id.enabled 
-   5.3. @timer.executed 
+   5.1. timer_enable(timer_id, enable_disable)
+   5.2. @timer.timer.timer_id.enabled
+   5.3. @timer.executed
 
-5.1.  timer_enable(timer_id, enable_disable)
+5.1. timer_enable(timer_id, enable_disable)
 
-   Enable/disable  timer  route  specified  by timer_id. Because of timer
-   core  API the callback is not disabled immediately but is removed from
-   handler  by itself not to decrease performance. Disabling and enabling
-   in  sequence  may  be tricky. timer_id references to timer declared by
+   Enable/disable timer route specified by timer_id. Because of timer core
+   API the callback is not disabled immediately but is removed from
+   handler by itself not to decrease performance. Disabling and enabling
+   in sequence may be tricky. timer_id references to timer declared by
    declare_timer.
 
    Example 1.2. timer_enable usage
@@ -115,7 +114,7 @@ ble");
         timer_enable("MY_TIMER", 1);
         ...
 
-5.2.  @timer.timer.timer_id.enabled
+5.2. @timer.timer.timer_id.enabled
 
    Return true ("1") if timer specified by timer_id is enabled, otherwise
    returns false ("0").
@@ -125,7 +124,7 @@ ble");
         ....
         }
 
-5.3.  @timer.executed
+5.3. @timer.executed
 
    Returns name of timer which has been executed, i.e. non empty value is
    returned only when handler is being processed.
@@ -162,9 +161,9 @@ route["ONTIMER2"] {
 
    Example 1.6. Using timer module for testing a functionality
 
-   The  timer  module may be used to test a functionality being developed
-   and  not  requiring  real  request.A  developer may put tested code in
-   route section which is called once after ser starts.
+   The timer module may be used to test a functionality being developed
+   and not requiring real request.A developer may put tested code in route
+   section which is called once after Kamailio starts.
 loadmodule "timer";
 loadmodule "xprint";
 
diff --git a/modules/timer/doc/timer.xml b/modules/timer/doc/timer.xml
index 0385bad..3b98f55 100644
--- a/modules/timer/doc/timer.xml
+++ b/modules/timer/doc/timer.xml
@@ -1,6 +1,12 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
-   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+<?xml version="1.0" encoding='ISO-8859-1'?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+<!-- Include general documentation entities -->
+<!ENTITY % docentities SYSTEM "../../../docbook/entities.xml">
+%docentities;
+
+]>
 
 <book id="timer" xmlns:xi="http://www.w3.org/2001/XInclude">
     <bookinfo>
@@ -70,8 +76,8 @@
 			<emphasis>timer_id</emphasis> is timer identifier, <emphasis>route</emphasis> is handler to be called when
 			timer is triggered, <emphasis>interval</emphasis> is timer interval in milliseconds, <emphasis>slow_fast</emphasis>
 			determines if handler will be hooked in slow or fast timer queue, fast timer handler returns
-			as quickly as possible, slow timer handler may spend longer time, see ser/doc/timers.txt documentation. Use <emphasis>enable</emphasis>
-			to enable timer when ser is starting, otherwise use <function>timer_enable</function> to start it later.		
+			as quickly as possible, slow timer handler may spend longer time, see kamailio/doc/timers.txt documentation. Use <emphasis>enable</emphasis>
+			to enable timer when &kamailio; is starting, otherwise use <function>timer_enable</function> to start it later.		
 			</para>
 			<example>
 				<title>Example <varname>declare_timer</varname></title>
@@ -188,7 +194,7 @@ route["ONTIMER2"] {
 			<para>
 				The timer module may be used to test a functionality being developed and 
 				not requiring real request.A developer may put tested code in route section
-				which is called once after ser starts.
+				which is called once after &kamailio; starts.
 			</para>
 			<programlisting>
 			
diff --git a/modules/timer/timer.c b/modules/timer/timer.c
index 1986f26..abfbb70 100644
--- a/modules/timer/timer.c
+++ b/modules/timer/timer.c
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2006 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/modules/tls/Makefile b/modules/tls/Makefile
index f9d4c39..167863d 100644
--- a/modules/tls/Makefile
+++ b/modules/tls/Makefile
@@ -1,4 +1,3 @@
-# Makefile v 1.0 2002/12/27
 #
 # TLS module makefile
 #
diff --git a/modules/tls/README b/modules/tls/README
index aaa7b0b..d01a43b 100644
--- a/modules/tls/README
+++ b/modules/tls/README
@@ -36,27 +36,29 @@ Carsten Bock
               9.7. verify_depth (integer)
               9.8. require_certificate (boolean)
               9.9. cipher_list (string)
-              9.10. send_timeout (int)
-              9.11. handshake_timeout (int)
-              9.12. connection_timeout (int)
-              9.13. tls_disable_compression (boolean)
-              9.14. ssl_release_buffers (integer)
-              9.15. ssl_free_list_max_len (integer)
-              9.16. ssl_max_send_fragment (integer)
-              9.17. ssl_read_ahead (boolean)
-              9.18. send_close_notify (boolean)
-              9.19. con_ct_wq_max (integer)
-              9.20. ct_wq_max (integer)
-              9.21. ct_wq_blk_size (integer)
-              9.22. tls_log (int)
-              9.23. tls_debug (int)
-              9.24. low_mem_threshold1 (integer)
-              9.25. low_mem_threshold2 (integer)
-              9.26. tls_force_run (boolean)
-              9.27. session_cache (boolean)
-              9.28. session_id (str)
-              9.29. renegotiation (boolean)
-              9.30. config (string)
+              9.10. server_name (string)
+              9.11. send_timeout (int)
+              9.12. handshake_timeout (int)
+              9.13. connection_timeout (int)
+              9.14. tls_disable_compression (boolean)
+              9.15. ssl_release_buffers (integer)
+              9.16. ssl_free_list_max_len (integer)
+              9.17. ssl_max_send_fragment (integer)
+              9.18. ssl_read_ahead (boolean)
+              9.19. send_close_notify (boolean)
+              9.20. con_ct_wq_max (integer)
+              9.21. ct_wq_max (integer)
+              9.22. ct_wq_blk_size (integer)
+              9.23. tls_log (int)
+              9.24. tls_debug (int)
+              9.25. low_mem_threshold1 (integer)
+              9.26. low_mem_threshold2 (integer)
+              9.27. tls_force_run (boolean)
+              9.28. session_cache (boolean)
+              9.29. session_id (str)
+              9.30. renegotiation (boolean)
+              9.31. config (string)
+              9.32. xavp_cfg (string)
 
         10. Functions
 
@@ -87,37 +89,39 @@ Carsten Bock
    1.9. Set verify_depth parameter
    1.10. Set require_certificate parameter
    1.11. Set cipher_list parameter
-   1.12. Set connection_timeout parameter
-   1.13. Set tls.connection_timeout at runtime
-   1.14. Set tls_disable_compression parameter
-   1.15. Set ssl_release_buffers parameter
-   1.16. Set ssl_freelist_max_len parameter
-   1.17. Set ssl_max_send_fragment parameter
-   1.18. Set ssl_read_ahead parameter
-   1.19. Set send_close_notify parameter
-   1.20. Set tls.send_close_notify at runtime
-   1.21. Set con_ct_wq_max parameter
-   1.22. Set tls.con_ct_wq_max at runtime
-   1.23. Set ct_wq_max parameter
-   1.24. Set tls.ct_wq_max at runtime
-   1.25. Set ct_wq_blk_size parameter
-   1.26. Set tls.ct_wq_max at runtime
-   1.27. Set tls_log parameter
-   1.28. Set tls.log at runtime
-   1.29. Set tls_debug parameter
-   1.30. Set tls.debug at runtime
-   1.31. Set low_mem_threshold1 parameter
-   1.32. Set tls.low_mem_threshold1 at runtime
-   1.33. Set low_mem_threshold2 parameter
-   1.34. Set tls.low_mem_threshold2 at runtime
-   1.35. Set tls_force_run parameter
-   1.36. Set session_cache parameter
-   1.37. Set session_id parameter
-   1.38. Set renegotiation parameter
-   1.39. Short config file
-   1.40. Set config parameter
-   1.41. Change and reload tls config at runtime
-   1.42. is_peer_verified usage
+   1.12. Set server_name parameter
+   1.13. Set connection_timeout parameter
+   1.14. Set tls.connection_timeout at runtime
+   1.15. Set tls_disable_compression parameter
+   1.16. Set ssl_release_buffers parameter
+   1.17. Set ssl_freelist_max_len parameter
+   1.18. Set ssl_max_send_fragment parameter
+   1.19. Set ssl_read_ahead parameter
+   1.20. Set send_close_notify parameter
+   1.21. Set tls.send_close_notify at runtime
+   1.22. Set con_ct_wq_max parameter
+   1.23. Set tls.con_ct_wq_max at runtime
+   1.24. Set ct_wq_max parameter
+   1.25. Set tls.ct_wq_max at runtime
+   1.26. Set ct_wq_blk_size parameter
+   1.27. Set tls.ct_wq_max at runtime
+   1.28. Set tls_log parameter
+   1.29. Set tls.log at runtime
+   1.30. Set tls_debug parameter
+   1.31. Set tls.debug at runtime
+   1.32. Set low_mem_threshold1 parameter
+   1.33. Set tls.low_mem_threshold1 at runtime
+   1.34. Set low_mem_threshold2 parameter
+   1.35. Set tls.low_mem_threshold2 at runtime
+   1.36. Set tls_force_run parameter
+   1.37. Set session_cache parameter
+   1.38. Set session_id parameter
+   1.39. Set renegotiation parameter
+   1.40. Short config file
+   1.41. Set config parameter
+   1.42. Change and reload tls config at runtime
+   1.43. Set xavp_cfg parameter
+   1.44. is_peer_verified usage
 
 Chapter 1. Admin Guide
 
@@ -142,27 +146,29 @@ Chapter 1. Admin Guide
         9.7. verify_depth (integer)
         9.8. require_certificate (boolean)
         9.9. cipher_list (string)
-        9.10. send_timeout (int)
-        9.11. handshake_timeout (int)
-        9.12. connection_timeout (int)
-        9.13. tls_disable_compression (boolean)
-        9.14. ssl_release_buffers (integer)
-        9.15. ssl_free_list_max_len (integer)
-        9.16. ssl_max_send_fragment (integer)
-        9.17. ssl_read_ahead (boolean)
-        9.18. send_close_notify (boolean)
-        9.19. con_ct_wq_max (integer)
-        9.20. ct_wq_max (integer)
-        9.21. ct_wq_blk_size (integer)
-        9.22. tls_log (int)
-        9.23. tls_debug (int)
-        9.24. low_mem_threshold1 (integer)
-        9.25. low_mem_threshold2 (integer)
-        9.26. tls_force_run (boolean)
-        9.27. session_cache (boolean)
-        9.28. session_id (str)
-        9.29. renegotiation (boolean)
-        9.30. config (string)
+        9.10. server_name (string)
+        9.11. send_timeout (int)
+        9.12. handshake_timeout (int)
+        9.13. connection_timeout (int)
+        9.14. tls_disable_compression (boolean)
+        9.15. ssl_release_buffers (integer)
+        9.16. ssl_free_list_max_len (integer)
+        9.17. ssl_max_send_fragment (integer)
+        9.18. ssl_read_ahead (boolean)
+        9.19. send_close_notify (boolean)
+        9.20. con_ct_wq_max (integer)
+        9.21. ct_wq_max (integer)
+        9.22. ct_wq_blk_size (integer)
+        9.23. tls_log (int)
+        9.24. tls_debug (int)
+        9.25. low_mem_threshold1 (integer)
+        9.26. low_mem_threshold2 (integer)
+        9.27. tls_force_run (boolean)
+        9.28. session_cache (boolean)
+        9.29. session_id (str)
+        9.30. renegotiation (boolean)
+        9.31. config (string)
+        9.32. xavp_cfg (string)
 
    10. Functions
 
@@ -477,27 +483,29 @@ Revoking a certificate and using a CRL
    9.7. verify_depth (integer)
    9.8. require_certificate (boolean)
    9.9. cipher_list (string)
-   9.10. send_timeout (int)
-   9.11. handshake_timeout (int)
-   9.12. connection_timeout (int)
-   9.13. tls_disable_compression (boolean)
-   9.14. ssl_release_buffers (integer)
-   9.15. ssl_free_list_max_len (integer)
-   9.16. ssl_max_send_fragment (integer)
-   9.17. ssl_read_ahead (boolean)
-   9.18. send_close_notify (boolean)
-   9.19. con_ct_wq_max (integer)
-   9.20. ct_wq_max (integer)
-   9.21. ct_wq_blk_size (integer)
-   9.22. tls_log (int)
-   9.23. tls_debug (int)
-   9.24. low_mem_threshold1 (integer)
-   9.25. low_mem_threshold2 (integer)
-   9.26. tls_force_run (boolean)
-   9.27. session_cache (boolean)
-   9.28. session_id (str)
-   9.29. renegotiation (boolean)
-   9.30. config (string)
+   9.10. server_name (string)
+   9.11. send_timeout (int)
+   9.12. handshake_timeout (int)
+   9.13. connection_timeout (int)
+   9.14. tls_disable_compression (boolean)
+   9.15. ssl_release_buffers (integer)
+   9.16. ssl_free_list_max_len (integer)
+   9.17. ssl_max_send_fragment (integer)
+   9.18. ssl_read_ahead (boolean)
+   9.19. send_close_notify (boolean)
+   9.20. con_ct_wq_max (integer)
+   9.21. ct_wq_max (integer)
+   9.22. ct_wq_blk_size (integer)
+   9.23. tls_log (int)
+   9.24. tls_debug (int)
+   9.25. low_mem_threshold1 (integer)
+   9.26. low_mem_threshold2 (integer)
+   9.27. tls_force_run (boolean)
+   9.28. session_cache (boolean)
+   9.29. session_id (str)
+   9.30. renegotiation (boolean)
+   9.31. config (string)
+   9.32. xavp_cfg (string)
 
 9.1. tls_method (string)
 
@@ -714,19 +722,33 @@ modparam("tls", "require_certificate", 1)
 modparam("tls", "cipher_list", "HIGH")
 ...
 
-9.10. send_timeout (int)
+9.10. server_name (string)
+
+   Sets the Server Name Indication (SNI) value.
+
+   This is a TLS extension and is not working for old and obsoleted SSL
+   versions.
+
+   The default value is empty (not set).
+
+   Example 1.12. Set server_name parameter
+...
+modparam("tls", "server_name", "kamailio.org")
+...
+
+9.11. send_timeout (int)
 
    This parameter is obsolete and cannot be used in newer TLS versions (>
    Kamailio 3.0). In these versions the send_timeout is replaced by
    tcp_send_timeout (common with all the tcp connections).
 
-9.11. handshake_timeout (int)
+9.12. handshake_timeout (int)
 
    This parameter is obsolete and cannot be used in newer TLS versions (>
    Kamailio 3.0). In these versions the handshake_timeout is replaced by
    tcp_connect_timeout (common with all the tcp connections).
 
-9.12. connection_timeout (int)
+9.13. connection_timeout (int)
 
    Sets the amount of time after which an idle TLS connection will be
    closed, if no I/O ever occured after the initial open. If an I/O event
@@ -740,15 +762,15 @@ modparam("tls", "cipher_list", "HIGH")
    It can be changed also at runtime, via the RPC interface and config
    framework. The config variable name is tls.connection_timeout.
 
-   Example 1.12. Set connection_timeout parameter
+   Example 1.13. Set connection_timeout parameter
 ...
 modparam("tls", "connection_timeout", 60)
 ...
 
-   Example 1.13. Set tls.connection_timeout at runtime
+   Example 1.14. Set tls.connection_timeout at runtime
  $ kamcmd cfg.set_now_int tls connection_timeout 180
 
-9.13. tls_disable_compression (boolean)
+9.14. tls_disable_compression (boolean)
 
    If set compression over SSL/TLS will be disabled. Note that compression
    uses a lot of memory (about 10x more then with the compression
@@ -757,12 +779,12 @@ modparam("tls", "connection_timeout", 60)
 
    By default compression is disabled.
 
-   Example 1.14. Set tls_disable_compression parameter
+   Example 1.15. Set tls_disable_compression parameter
 ...
 modparam("tls", "tls_disable_compression", 0) # enable
 ...
 
-9.14. ssl_release_buffers (integer)
+9.15. ssl_release_buffers (integer)
 
    Release internal OpenSSL read or write buffers as soon as they are no
    longer needed. Combined with ssl_free_list_max_len has the potential of
@@ -781,10 +803,10 @@ Note
    This option is supported only for OpenSSL versions >= 1.0.0. On all the
    other versions attempting to change the default will trigger an error.
 
-   Example 1.15. Set ssl_release_buffers parameter
+   Example 1.16. Set ssl_release_buffers parameter
 modparam("tls", "ssl_release_buffers", 1)
 
-9.15. ssl_free_list_max_len (integer)
+9.16. ssl_free_list_max_len (integer)
 
    Sets the maximum number of free memory chunks, that OpenSSL will keep
    per connection. Setting it to 0 would cause any unused memory chunk to
@@ -804,10 +826,10 @@ Note
    This option is supported only for OpenSSL versions >= 1.0.0. On all the
    other versions attempting to change the default will trigger an error.
 
-   Example 1.16. Set ssl_freelist_max_len parameter
+   Example 1.17. Set ssl_freelist_max_len parameter
 modparam("tls", "ssl_freelist_max_len", 0)
 
-9.16. ssl_max_send_fragment (integer)
+9.17. ssl_max_send_fragment (integer)
 
    Sets the maximum number of bytes (from the clear text) sent into one
    TLS or SSL record. Valid values are between 512 and 16384. Note however
@@ -839,10 +861,10 @@ Note
    This option is supported only for OpenSSL versions >= 0.9.9. On all the
    other versions attempting to change the default will trigger an error.
 
-   Example 1.17. Set ssl_max_send_fragment parameter
+   Example 1.18. Set ssl_max_send_fragment parameter
 modparam("tls", "ssl_max_send_fragment", 4096)
 
-9.17. ssl_read_ahead (boolean)
+9.18. ssl_read_ahead (boolean)
 
    Enables read ahead, reducing the number of internal OpenSSL BIO read()
    calls. This option has only debugging value, in normal circumstances it
@@ -861,10 +883,10 @@ modparam("tls", "ssl_max_send_fragment", 4096)
 
    By default the value is 0 (disabled).
 
-   Example 1.18. Set ssl_read_ahead parameter
+   Example 1.19. Set ssl_read_ahead parameter
 modparam("tls", "ssl_read_ahead", 1)
 
-9.18. send_close_notify (boolean)
+9.19. send_close_notify (boolean)
 
    Enables/disables sending close notify alerts prior to closing the
    corresponding TCP connection. Sending the close notify prior to tcp
@@ -877,15 +899,15 @@ modparam("tls", "ssl_read_ahead", 1)
    It can be changed also at runtime, via the RPC interface and config
    framework. The config variable name is tls.send_close_notify.
 
-   Example 1.19. Set send_close_notify parameter
+   Example 1.20. Set send_close_notify parameter
 ...
 modparam("tls", "send_close_notify", 1)
 ...
 
-   Example 1.20. Set tls.send_close_notify at runtime
+   Example 1.21. Set tls.send_close_notify at runtime
  $ kamcmd cfg.set_now_int tls send_close_notify 1
 
-9.19. con_ct_wq_max (integer)
+9.20. con_ct_wq_max (integer)
 
    Sets the maximum allowed per connection clear-text send queue size in
    bytes. This queue is used when data cannot be encrypted and sent
@@ -896,15 +918,15 @@ modparam("tls", "send_close_notify", 1)
    It can be changed also at runtime, via the RPC interface and config
    framework. The config variable name is tls.con_ct_wq_max.
 
-   Example 1.21. Set con_ct_wq_max parameter
+   Example 1.22. Set con_ct_wq_max parameter
 ...
 modparam("tls", "con_ct_wq_max", 1048576)
 ...
 
-   Example 1.22. Set tls.con_ct_wq_max at runtime
+   Example 1.23. Set tls.con_ct_wq_max at runtime
  $ kamcmd cfg.set_now_int tls con_ct_wq_max 1048576
 
-9.20. ct_wq_max (integer)
+9.21. ct_wq_max (integer)
 
    Sets the maximum total number of bytes queued in all the clear-text
    send queues. These queues are used when data cannot be encrypted and
@@ -915,15 +937,15 @@ modparam("tls", "con_ct_wq_max", 1048576)
    It can be changed also at runtime, via the RPC interface and config
    framework. The config variable name is tls.ct_wq_max.
 
-   Example 1.23. Set ct_wq_max parameter
+   Example 1.24. Set ct_wq_max parameter
 ...
 modparam("tls", "ct_wq_max", 4194304)
 ...
 
-   Example 1.24. Set tls.ct_wq_max at runtime
+   Example 1.25. Set tls.ct_wq_max at runtime
  $ kamcmd cfg.set_now_int tls ct_wq_max 4194304
 
-9.21. ct_wq_blk_size (integer)
+9.22. ct_wq_blk_size (integer)
 
    Minimum block size for the internal clear-text send queues (debugging /
    advanced tunning). Good values are multiple of typical datagram sizes.
@@ -933,15 +955,15 @@ modparam("tls", "ct_wq_max", 4194304)
    It can be changed also at runtime, via the RPC interface and config
    framework. The config variable name is tls.ct_wq_blk_size.
 
-   Example 1.25. Set ct_wq_blk_size parameter
+   Example 1.26. Set ct_wq_blk_size parameter
 ...
 modparam("tls", "ct_wq_blk_size", 2048)
 ...
 
-   Example 1.26. Set tls.ct_wq_max at runtime
+   Example 1.27. Set tls.ct_wq_max at runtime
  $ kamcmd cfg.set_now_int tls ct_wq_blk_size 2048
 
-9.22. tls_log (int)
+9.23. tls_log (int)
 
    Sets the log level at which TLS related messages will be logged.
 
@@ -950,16 +972,16 @@ modparam("tls", "ct_wq_blk_size", 2048)
    It can be changed also at runtime, via the RPC interface and config
    framework. The config variable name is tls.log.
 
-   Example 1.27. Set tls_log parameter
+   Example 1.28. Set tls_log parameter
 ...
 # ignore TLS messages if Kamailio is started with debug less than 10
 modparam("tls", "tls_log", 10)
 ...
 
-   Example 1.28. Set tls.log at runtime
+   Example 1.29. Set tls.log at runtime
  $ kamcmd cfg.set_now_int tls log 10
 
-9.23. tls_debug (int)
+9.24. tls_debug (int)
 
    Sets the log level at which TLS debug messages will be logged. Note
    that TLS debug messages are enabled only if the TLS module is compiled
@@ -971,16 +993,16 @@ modparam("tls", "tls_log", 10)
    It can be changed also at runtime, via the RPC interface and config
    framework. The config variable name is tls.debug.
 
-   Example 1.29. Set tls_debug parameter
+   Example 1.30. Set tls_debug parameter
 ...
 # ignore TLS debug messages if Kamailio is started with debug less than 10
 modparam("tls", "tls_debug", 10)
 ...
 
-   Example 1.30. Set tls.debug at runtime
+   Example 1.31. Set tls.debug at runtime
  $ kamcmd cfg.set_now_int tls debug 10
 
-9.24. low_mem_threshold1 (integer)
+9.25. low_mem_threshold1 (integer)
 
    Sets the minimal free memory from which attempts to open or accept new
    TLS connections will start to fail. The value is expressed in KB.
@@ -1003,15 +1025,15 @@ modparam("tls", "tls_debug", 10)
 
    See also low_mem_threshold2.
 
-   Example 1.31. Set low_mem_threshold1 parameter
+   Example 1.32. Set low_mem_threshold1 parameter
 ...
 modparam("tls", "low_mem_threshold1", -1)
 ...
 
-   Example 1.32. Set tls.low_mem_threshold1 at runtime
+   Example 1.33. Set tls.low_mem_threshold1 at runtime
  $ kamcmd cfg.set_now_int tls low_mem_threshold1 2048
 
-9.25. low_mem_threshold2 (integer)
+9.26. low_mem_threshold2 (integer)
 
    Sets the minimal free memory from which TLS operations on already
    established TLS connections will start to fail preemptively. The value
@@ -1035,15 +1057,15 @@ modparam("tls", "low_mem_threshold1", -1)
 
    See also low_mem_threshold1.
 
-   Example 1.33. Set low_mem_threshold2 parameter
+   Example 1.34. Set low_mem_threshold2 parameter
 ...
 modparam("tls", "low_mem_threshold2", -1)
 ...
 
-   Example 1.34. Set tls.low_mem_threshold2 at runtime
+   Example 1.35. Set tls.low_mem_threshold2 at runtime
  $ kamcmd cfg.set_now_int tls low_mem_threshold2 1024
 
-9.26. tls_force_run (boolean)
+9.27. tls_force_run (boolean)
 
    If enabled Kamailio will start even if some of the openssl sanity
    checks fail (turn it on at your own risk).
@@ -1059,36 +1081,36 @@ modparam("tls", "low_mem_threshold2", -1)
 
    By default tls_force_run is disabled.
 
-   Example 1.35. Set tls_force_run parameter
+   Example 1.36. Set tls_force_run parameter
 ...
 modparam("tls", "tls_force_run", 11)
 ...
 
-9.27. session_cache (boolean)
+9.28. session_cache (boolean)
 
    If enabled Kamailio will do caching of the TLS sessions data,
    generation a session_id and sending it back to client.
 
    By default TLS session caching is disabled (0).
 
-   Example 1.36. Set session_cache parameter
+   Example 1.37. Set session_cache parameter
 ...
 modparam("tls", "session_cache", 1)
 ...
 
-9.28. session_id (str)
+9.29. session_id (str)
 
    The value for session ID context, making sense when session caching is
    enabled.
 
    By default TLS session_id is "sip-router-tls-3.1".
 
-   Example 1.37. Set session_id parameter
+   Example 1.38. Set session_id parameter
 ...
 modparam("tls", "session_id", "my-session-id-context")
 ...
 
-9.29. renegotiation (boolean)
+9.30. renegotiation (boolean)
 
    If enabled Kamailio will allow renegotiations of TLS connection
    initiated by the client. This may expose to a security risk if the
@@ -1097,12 +1119,12 @@ modparam("tls", "session_id", "my-session-id-context")
 
    By default TLS renegotiation is disabled (0).
 
-   Example 1.38. Set renegotiation parameter
+   Example 1.39. Set renegotiation parameter
 ...
 modparam("tls", "renegotiation", 1)
 ...
 
-9.30. config (string)
+9.31. config (string)
 
    Sets the name of the TLS specific config file or config directory.
 
@@ -1131,6 +1153,7 @@ modparam("tls", "renegotiation", 1)
      * ca_list
      * crl
      * cipher_list
+     * server_name
 
    All the parameters that take filenames as values will be resolved using
    the same rules as for the tls config filename itself: starting with a
@@ -1142,7 +1165,7 @@ modparam("tls", "renegotiation", 1)
    when it initiates a new connection by itself (it connects to
    something).
 
-   Example 1.39. Short config file
+   Example 1.40. Short config file
 [server:default]
 method = TLSv1
 verify_certificate = yes
@@ -1165,11 +1188,12 @@ private_key = local_key.pem
 certificate = local_cert.pem
 verify_depth = 3
 ca_list = local_ca.pem
+server_name = kamailio.org
 
    For a more complete example check the tls.cfg distributed with the
    Kamailio source (kamailio/modules/tls/tls.cfg).
 
-   Example 1.40. Set config parameter
+   Example 1.41. Set config parameter
 ...
 modparam("tls", "config", "/usr/local/etc/kamailio/tls.cfg")
 ...
@@ -1177,10 +1201,28 @@ modparam("tls", "config", "/usr/local/etc/kamailio/tls.cfg")
    It can be changed also at runtime. The new config will not be loaded
    immediately, but after the first tls.reload RPC call.
 
-   Example 1.41. Change and reload tls config at runtime
+   Example 1.42. Change and reload tls config at runtime
  $ kamcmd cfg.set_now_string tls config "/usr/local/etc/kamailio/new_tls.cfg"
  $ kamcmd tls.reload
 
+9.32. xavp_cfg (string)
+
+   Sets the name of XAVP that stored attributes for TLS connections.
+
+   The following (inner) attributes can be set:
+     * server_name - SNI to be used for outbound connections
+
+   The default value is empty (not set).
+
+   Example 1.43. Set xavp_cfg parameter
+...
+  modparam("tls", "xavp_cfg", "tls")
+ ...
+  $xavp(tls=>server_name) = "kamailio.org";
+  $du = "sip:kamailio.org:5061;transport=tls";
+  route(RELAY);
+...
+
 10. Functions
 
    10.1. is_peer_verified()
@@ -1191,7 +1233,7 @@ modparam("tls", "config", "/usr/local/etc/kamailio/tls.cfg")
    , the peer presented an X509 certificate and the certificate chain
    verified ok. It can be used only in a request route.
 
-   Example 1.42. is_peer_verified usage
+   Example 1.44. is_peer_verified usage
         if (proto==TLS && !is_peer_verified()){
                 sl_send_reply("400", "No certificate or verification failed");
                 drop;
diff --git a/modules/tls/doc/params.xml b/modules/tls/doc/params.xml
index ecd5802..60d62fc 100644
--- a/modules/tls/doc/params.xml
+++ b/modules/tls/doc/params.xml
@@ -350,6 +350,28 @@ modparam("tls", "cipher_list", "HIGH")
 	</example>
 	</section>
 
+	<section id="tls.p.server_name">
+	<title><varname>server_name</varname> (string)</title>
+	<para>
+		Sets the Server Name Indication (SNI) value.
+	</para>
+	<para>
+		This is a TLS extension and is not working for old and obsoleted
+		SSL versions.
+	</para>
+	<para>
+		The default value is empty (not set).
+	</para>
+	<example>
+	    <title>Set <varname>server_name</varname> parameter</title>
+	    <programlisting>
+...
+modparam("tls", "server_name", "kamailio.org")
+...
+	    </programlisting>
+	</example>
+	</section>
+
 	<section id="tls.p.send_timeout">
 	<title><varname>send_timeout</varname> (int)</title>
 	<para>
@@ -993,6 +1015,7 @@ modparam("tls", "renegotiation", 1)
 			<listitem><para>ca_list</para></listitem>
 			<listitem><para>crl</para></listitem>
 			<listitem><para>cipher_list</para></listitem>
+			<listitem><para>server_name</para></listitem>
 	</itemizedlist>
 	<para>
 		All the parameters that take filenames as values will be resolved
@@ -1031,6 +1054,7 @@ private_key = local_key.pem
 certificate = local_cert.pem
 verify_depth = 3
 ca_list = local_ca.pem
+server_name = kamailio.org
 
 	</programlisting>
 	</example>
@@ -1058,4 +1082,32 @@ modparam("tls", "config", "/usr/local/etc/kamailio/tls.cfg")
 	</para>
 	</section>
 
+	<section id="tls.p.xavp_cfg">
+	<title><varname>xavp_cfg</varname> (string)</title>
+	<para>
+		Sets the name of XAVP that stored attributes for TLS connections.
+	</para>
+	<para>
+		The following (inner) attributes can be set:
+	</para>
+	<itemizedlist>
+		<listitem><para>server_name - SNI to be used for outbound connections</para></listitem>
+	</itemizedlist>
+	<para>
+		The default value is empty (not set).
+	</para>
+	<example>
+	    <title>Set <varname>xavp_cfg</varname> parameter</title>
+	    <programlisting>
+...
+  modparam("tls", "xavp_cfg", "tls")
+ ...
+  $xavp(tls=>server_name) = "kamailio.org";
+  $du = "sip:kamailio.org:5061;transport=tls";
+  route(RELAY);
+...
+	    </programlisting>
+	</example>
+	</section>
+
 </section>
diff --git a/modules/tls/fixed_c_zlib.h b/modules/tls/fixed_c_zlib.h
index e35bd45..8a2eefc 100644
--- a/modules/tls/fixed_c_zlib.h
+++ b/modules/tls/fixed_c_zlib.h
@@ -8,7 +8,16 @@
  *
  * Copyright (c) 1998-2005 The OpenSSL Project.  All rights reserved.
  */
-/*
+/*!
+ * \file
+ * \brief Kamailio TLS support :: Zlib functions
+ * \ingroup tls
+ * Module: \ref tls
+ *
+ * This file contains modified zlib compression functions
+ * originally part of crypto/comp/c_zlib.c from the openssl library 
+ * (version 0.9.8a).
+ *
  * The changes are: 
  *   - proper zalloc and zfree initialization for the zlib compression
  *     methods (use OPENSSL_malloc & OPENSSL_free to construct zalloc/zfree)
@@ -19,13 +28,6 @@
  *    version).
  *  -- andrei
  */
-/*!
- * \file
- * \brief SIP-router TLS support :: Zlib functions
- * \ingroup tls
- * Module: \ref tls
- */
-
 
 
 #ifdef TLS_FIX_ZLIB_COMPRESSION
diff --git a/modules/tls/sbufq.h b/modules/tls/sbufq.h
index 35c2f33..fdc9947 100644
--- a/modules/tls/sbufq.h
+++ b/modules/tls/sbufq.h
@@ -1,5 +1,5 @@
 /* 
- * TLS module
+ * Kamailio TLS module
  *
  * Copyright (C) 2010 iptelorg GmbH
  *
@@ -20,11 +20,6 @@
  * @ingroup: tls
  * Module: @ref tls
  */
-/*
- * History:
- * --------
- *  2010-03-31  initial version, based on tcp_conn.h tcp_wbuffer_queue (andrei)
-*/
 
 #ifndef __sbufq_h
 #define __sbufq_h
diff --git a/modules/tls/tls.cfg b/modules/tls/tls.cfg
index cdb1e03..102990b 100644
--- a/modules/tls/tls.cfg
+++ b/modules/tls/tls.cfg
@@ -1,6 +1,4 @@
 #
-# $Id$
-#
 # Example Kamailio TLS Configuration File
 #
 
diff --git a/modules/tls/tls_bio.c b/modules/tls/tls_bio.c
index dc8ceba..aee1953 100644
--- a/modules/tls/tls_bio.c
+++ b/modules/tls/tls_bio.c
@@ -1,5 +1,5 @@
 /* 
- * TLS module
+ * Kamailio TLS module
  *
  * Copyright (C) 2010 iptelorg GmbH
  *
@@ -22,14 +22,6 @@
  * @ingroup tls
  */
 
-/*
- * History:
- * --------
- *  2010-03-25  initial version (andrei)
- *  2010-05-20  emulate EAGAIN on null rd/wr memory buffer; handle some
- *              needed commands in ctrl; debug support (TLS_BIO_DBG) (andrei)
-*/
-
 #include "tls_bio.h"
 #include "../../compiler_opt.h"
 #include "../../dprint.h"
diff --git a/modules/tls/tls_bio.h b/modules/tls/tls_bio.h
index 9d9bdcf..f2859a1 100644
--- a/modules/tls/tls_bio.h
+++ b/modules/tls/tls_bio.h
@@ -1,5 +1,5 @@
 /* 
- * TLS module
+ * Kamailio TLS module
  *
  * Copyright (C) 2010 iptelorg GmbH
  *
@@ -21,12 +21,6 @@
  * @ingroup tls
  */
  
-/*
- * History:
- * --------
- *  2010-03-25  initial version (andrei)
-*/
-
 #ifndef __tls_bio_h
 #define __tls_bio_h
 
diff --git a/modules/tls/tls_cfg.c b/modules/tls/tls_cfg.c
index f928c10..fd3b950 100644
--- a/modules/tls/tls_cfg.c
+++ b/modules/tls/tls_cfg.c
@@ -1,5 +1,5 @@
 /* 
- * TLS module
+ * Kamailio TLS module
  *
  * Copyright (C) 2010 iptelorg GmbH
  * Copyright (C) 2013 Motorola Solutions, Inc.
@@ -18,18 +18,12 @@
  */
 
 /**
- * SIP-router TLS support :: tls runtime configuration
+ * Kamailio TLS support :: tls runtime configuration
  * @file tls_cfg.c
  * @ingroup tls
  * Module: @ref tls
  */
 
-/*
- * History:
- * --------
- *  2010-05-27  initial version (andrei)
-*/
-
 #include "tls_cfg.h"
 #include "../../config.h"
 #include "../../str.h"
@@ -41,6 +35,7 @@
 struct cfg_group_tls default_tls_cfg = {
 	0, /* tls_force_run */
 	STR_STATIC_INIT("TLSv1"), /* method */
+	STR_NULL, /* server name (sni) */
 	0, /* verify_certificate */
 	9, /* verify_depth */
 	0, /* require_certificate */
@@ -144,7 +139,9 @@ cfg_def_t	tls_cfg_def[] = {
 	{"force_run", CFG_VAR_INT | CFG_READONLY, 0, 1, 0, 0,
 		"force loading the tls module even when initial sanity checks fail"},
 	{"method",   CFG_VAR_STR | CFG_READONLY, 0, 0, 0, 0,
-		"TLS method used (TLSv1, SSLv3, SSLv2, SSLv23)"},
+		"TLS method used (TLSv1.2, TLSv1.1, TLSv1, SSLv3, SSLv2, SSLv23)"},
+	{"server_name",   CFG_VAR_STR | CFG_READONLY, 0, 0, 0, 0,
+		"Server name (SNI)"},
 	{"verify_certificate", CFG_VAR_INT | CFG_READONLY, 0, 1, 0, 0,
 		"if enabled the certificates will be verified" },
 	{"verify_depth", CFG_VAR_INT | CFG_READONLY, 0, 100, 0, 0,
diff --git a/modules/tls/tls_cfg.h b/modules/tls/tls_cfg.h
index 4aeb5f5..36cb662 100644
--- a/modules/tls/tls_cfg.h
+++ b/modules/tls/tls_cfg.h
@@ -24,12 +24,6 @@
  * Module: @ref tls
  */
 
-/*
- * History:
- * --------
- *  2010-05-27  initial version (andrei)
-*/
-
 #ifndef __tls_cfg_h
 #define __tls_cfg_h
 
@@ -47,6 +41,7 @@
 struct cfg_group_tls {
 	int force_run;
 	str method;
+	str server_name;
 	int verify_cert;
 	int verify_depth;
 	int require_cert;
diff --git a/modules/tls/tls_config.c b/modules/tls/tls_config.c
index 96bdfff..e1dca1b 100644
--- a/modules/tls/tls_config.c
+++ b/modules/tls/tls_config.c
@@ -17,7 +17,7 @@
  */
 /*!
  * \file
- * \brief SIP-router TLS support :: Configuration file parser
+ * \brief Kamailio TLS support :: Configuration file parser
  * \ingroup tls
  * Module: \ref tls
  */
@@ -51,16 +51,19 @@ static int parse_ipv6(struct ip_addr* ip, cfg_token_t* token,
 	cfg_token_t t;
 	struct ip_addr* ipv6;
 	str ip6_str;
+	char ip6_buff[IP_ADDR_MAX_STR_SIZE+3];
 
+	ip6_buff[0] = '\0';
 	while(1) {
 		ret = cfg_get_token(&t, st, 0);
 		if (ret != 0) goto err;
 		if (t.type == ']') break;
 		if (t.type != CFG_TOKEN_ALPHA && t.type != ':') goto err;
+		strncat(ip6_buff, t.val.s, t.val.len);
 	}
-	ip6_str.s = t.val.s;
-	ip6_str.len = (int)(long)(t.val.s - ip6_str.s);
-
+	ip6_str.s = ip6_buff;
+	ip6_str.len = strlen(ip6_buff);
+	LM_DBG("found IPv6 address [%.*s]\n", ip6_str.len, ip6_str.s);
 	ipv6 = str2ip6(&ip6_str);
 	if (ipv6 == 0) goto err;
 	*ip = *ipv6;
@@ -160,6 +163,7 @@ static cfg_option_t options[] = {
 	{"cipher_list",         .f = cfg_parse_str_opt, .flags = CFG_STR_SHMMEM},
 	{"ca_list",             .f = cfg_parse_str_opt, .flags = CFG_STR_SHMMEM},
 	{"crl",                 .f = cfg_parse_str_opt, .flags = CFG_STR_SHMMEM},
+	{"server_name",         .f = cfg_parse_str_opt, .flags = CFG_STR_SHMMEM},
 	{0}
 };
 
@@ -183,6 +187,7 @@ static void update_opt_variables(void)
 	options[12].param = &domain->cipher_list;
 	options[13].param = &domain->ca_file;
 	options[14].param = &domain->crl_file;
+	options[15].param = &domain->server_name;
 }
 
 
diff --git a/modules/tls/tls_config.h b/modules/tls/tls_config.h
index 709e4e9..86efe0b 100644
--- a/modules/tls/tls_config.h
+++ b/modules/tls/tls_config.h
@@ -17,7 +17,7 @@
  */
 /*!
  * \file
- * \brief SIP-router TLS support :: Configuration file parser
+ * \brief Kamailio TLS support :: Configuration file parser
  * \ingroup tls
  * Module: \ref tls
  */
@@ -29,6 +29,14 @@
 #include "../../str.h"
 #include "tls_domain.h"
 
+#include <openssl/ssl.h>
+
+#ifndef OPENSSL_NO_TLSEXT
+#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
+#define OPENSSL_NO_TLSEXT
+#endif
+#endif
+
 tls_domains_cfg_t* tls_load_config(str* filename);
 
 /*
diff --git a/modules/tls/tls_ct_q.h b/modules/tls/tls_ct_q.h
index 183c2f7..236c529 100644
--- a/modules/tls/tls_ct_q.h
+++ b/modules/tls/tls_ct_q.h
@@ -25,12 +25,6 @@
  * Module: @ref tls
  */
 
-/*
- * History:
- * --------
- *  2010-03-31  initial version (andrei)
-*/
-
 #ifndef __tls_ct_q_h
 #define __tls_ct_q_h
 
diff --git a/modules/tls/tls_ct_wrq.c b/modules/tls/tls_ct_wrq.c
index f5b7d2f..badb411 100644
--- a/modules/tls/tls_ct_wrq.c
+++ b/modules/tls/tls_ct_wrq.c
@@ -25,12 +25,6 @@
  * Module: @ref tls
  */
 
-/*
- * History:
- * --------
- *  2010-03-31  initial version (andrei)
-*/
-
 #include "tls_ct_wrq.h"
 #include "tls_cfg.h"
 #include "tls_server.h"
diff --git a/modules/tls/tls_ct_wrq.h b/modules/tls/tls_ct_wrq.h
index fa679f7..cb02dcc 100644
--- a/modules/tls/tls_ct_wrq.h
+++ b/modules/tls/tls_ct_wrq.h
@@ -25,12 +25,6 @@
  * Module: @ref tls
  */
 
-/*
- * History:
- * --------
- *  2010-03-31  initial version (andrei)
-*/
-
 #ifndef __tls_ct_wrq_h
 #define __tls_ct_wrq_h
 
diff --git a/modules/tls/tls_domain.c b/modules/tls/tls_domain.c
index 395fd4e..97b6356 100644
--- a/modules/tls/tls_domain.c
+++ b/modules/tls/tls_domain.c
@@ -18,7 +18,7 @@
  */
 
 /**
- * SIP-router TLS support :: Virtual domain configuration support
+ * Kamailio TLS support :: Virtual domain configuration support
  * @file
  * @ingroup tls
  * Module: @ref tls
@@ -35,6 +35,7 @@
 #include "../../pt.h"
 #include "../../cfg/cfg.h"
 #include "../../dprint.h"
+#include "tls_config.h"
 #include "tls_server.h"
 #include "tls_util.h"
 #include "tls_mod.h"
@@ -878,6 +879,71 @@ static int tls_ssl_ctx_set_read_ahead(SSL_CTX* ctx, long val, void* unused)
 	return 0;
 }
 
+
+#ifndef OPENSSL_NO_TLSEXT
+
+/**
+ * @brief SNI callback function
+ *
+ * callback on server_name -> trigger context switch if a TLS domain
+ * for the server_name is found (checks socket too) */
+static int tls_server_name_cb(SSL *ssl, int *ad, void *private)
+{
+    tls_domain_t *orig_domain, *new_domain;
+	str server_name;
+
+	orig_domain = (tls_domain_t*)private;
+	server_name.s = (char*)SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
+	if (server_name.s)  {
+		LM_DBG("received server_name (TLS extension): '%s'\n", server_name.s);
+	} else {
+		LM_DBG("SSL_get_servername returned NULL: return SSL_TLSEXT_ERR_NOACK\n");
+		return SSL_TLSEXT_ERR_NOACK;
+	}
+
+	server_name.len = strlen(server_name.s);
+
+	new_domain = tls_lookup_cfg(*tls_domains_cfg, TLS_DOMAIN_SRV,
+			&orig_domain->ip, orig_domain->port, &server_name);
+	if (new_domain==NULL) {
+		LM_DBG("TLS domain for socket [%s:%d] and server_name='%s' "
+			"not found\n", ip_addr2a(&orig_domain->ip),
+			orig_domain->port, server_name.s);
+		/* we do not perform SSL_CTX switching, thus the default server domain
+		   for this socket (or the default server domain) will be used. */
+		return SSL_TLSEXT_ERR_ALERT_WARNING;
+	}
+
+	LM_DBG("TLS cfg domain selected for received server name [%s]:"
+		" socket [%s:%d] server name='%s' -"
+		" switching SSL CTX to %p dom %p%s\n",
+		server_name.s, ip_addr2a(&new_domain->ip),
+		new_domain->port, ZSW(new_domain->server_name.s),
+		new_domain->ctx[process_no], new_domain,
+		(new_domain->type & TLS_DOMAIN_DEF)?" (default)":"");
+	SSL_set_SSL_CTX(ssl, new_domain->ctx[process_no]);
+	/* SSL_set_SSL_CTX only sets the correct certificate parameters, but does
+	   set the proper verify options. Thus this will be done manually! */
+
+	SSL_set_options(ssl, SSL_CTX_get_options(ssl->ctx));
+	if ((SSL_get_verify_mode(ssl) == SSL_VERIFY_NONE) ||
+				(SSL_num_renegotiations(ssl) == 0)) {
+		/*
+		 * Only initialize the verification settings from the ctx
+		 * if they are not yet set, or if we're called when a new
+		 * SSL connection is set up (num_renegotiations == 0).
+		 * Otherwise, we would possibly reset a per-directory
+		 * configuration which was put into effect by ssl_hook_access.
+		 */
+		SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ssl->ctx),
+			SSL_CTX_get_verify_callback(ssl->ctx));
+	}
+
+	return SSL_TLSEXT_ERR_OK;
+}
+#endif
+
+
 /**
  * @brief Initialize all domain attributes from default domains if necessary
  * @param d initialized TLS domain
@@ -915,8 +981,36 @@ static int fix_domain(tls_domain_t* d, tls_domain_t* def)
 		if(d->method>TLS_USE_TLSvRANGE) {
 			SSL_CTX_set_options(d->ctx[i], (long)ssl_methods[d->method - 1]);
 		}
+#ifndef OPENSSL_NO_TLSEXT
+		/*
+		* check server domains for server_name extension and register
+		* callback function
+		*/
+		if ((d->type & TLS_DOMAIN_SRV) && d->server_name.len>0) {
+			if (!SSL_CTX_set_tlsext_servername_callback(d->ctx[i], tls_server_name_cb)) {
+				LM_ERR("register server_name callback handler for socket "
+					"[%s:%d], server_name='%s' failed for proc %d\n",
+					ip_addr2a(&d->ip), d->port, d->server_name.s, i);
+				return -1;
+			}
+			if (!SSL_CTX_set_tlsext_servername_arg(d->ctx[i], d)) {
+				LM_ERR("register server_name callback handler data for socket "
+					"[%s:%d], server_name='%s' failed for proc %d\n",
+					ip_addr2a(&d->ip), d->port, d->server_name.s, i);
+				return -1;
+			}
+		}
+#endif
 	}
-	
+
+#ifndef OPENSSL_NO_TLSEXT
+	if ((d->type & TLS_DOMAIN_SRV) && d->server_name.len>0) {
+		LM_NOTICE("registered server_name callback handler for socket "
+			"[%s:%d], server_name='%s' ...\n", ip_addr2a(&d->ip), d->port,
+			d->server_name.s);
+	}
+#endif
+
 	if (load_cert(d) < 0) return -1;
 	if (load_ca_list(d) < 0) return -1;
 	if (load_crl(d) < 0) return -1;
@@ -1195,7 +1289,7 @@ tls_domains_cfg_t* tls_new_cfg(void)
  * @return found configuration or default, if not found
  */
 tls_domain_t* tls_lookup_cfg(tls_domains_cfg_t* cfg, int type,
-								struct ip_addr* ip, unsigned short port)
+		struct ip_addr* ip, unsigned short port, str *sname)
 {
 	tls_domain_t *p;
 
@@ -1208,8 +1302,23 @@ tls_domain_t* tls_lookup_cfg(tls_domains_cfg_t* cfg, int type,
 	}
 
 	while (p) {
-		if ((p->port == port) && ip_addr_cmp(&p->ip, ip))
-			return p;
+		if(sname) {
+			LM_DBG("comparing addr: [%s:%d]  [%s:%d] -- sni: [%.*s] [%.*s]\n",
+				ip_addr2a(&p->ip), p->port, ip_addr2a(ip), port,
+				p->server_name.len, ZSW(p->server_name.s),
+				sname->len, ZSW(sname->s));
+		}
+		if ((p->port==0 || p->port == port) && ip_addr_cmp(&p->ip, ip)) {
+			if(sname && sname->len>0) {
+				if(p->server_name.s && p->server_name.len==sname->len
+					&& strncasecmp(p->server_name.s, sname->s, sname->len)==0) {
+					LM_DBG("socket+server_name based TLS server domain found\n");
+					return p;
+				}
+			} else {
+				return p;
+			}
+		}
 		p = p->next;
 	}
 
@@ -1238,8 +1347,13 @@ static int domain_exists(tls_domains_cfg_t* cfg, tls_domain_t* d)
 	}
 
 	while (p) {
-		if ((p->port == d->port) && ip_addr_cmp(&p->ip, &d->ip))
-			return 1;
+		if ((p->port == d->port) && ip_addr_cmp(&p->ip, &d->ip)) {
+			if(p->server_name.len==0) {
+				LM_WARN("another tls domain with same address was defined"
+						" and no server name provided\n");
+				return 1;
+			}
+		}
 		p = p->next;
 	}
 
diff --git a/modules/tls/tls_domain.h b/modules/tls/tls_domain.h
index dce7850..d10c97a 100644
--- a/modules/tls/tls_domain.h
+++ b/modules/tls/tls_domain.h
@@ -18,7 +18,7 @@
  */
 
 /**
- * SIP-router TLS support :: virtual domain configuration support
+ * Kamailio TLS support :: virtual domain configuration support
  * @file
  * @ingroup tls
  * Module: @ref tls
@@ -105,6 +105,7 @@ typedef struct tls_domain {
 	str cipher_list;
 	enum tls_method method;
 	str crl_file;
+	str server_name;
 	struct tls_domain* next;
 } tls_domain_t;
 
@@ -189,10 +190,11 @@ int tls_fix_domains_cfg(tls_domains_cfg_t* cfg, tls_domain_t* srv_defaults,
  * @param type type of configuration
  * @param ip IP for configuration
  * @param port port for configuration
+ * @param sname server name
  * @return found configuration or default, if not found
  */
 tls_domain_t* tls_lookup_cfg(tls_domains_cfg_t* cfg, int type,
-								struct ip_addr* ip, unsigned short port);
+				struct ip_addr* ip, unsigned short port, str *sname);
 
 
 /**
diff --git a/modules/tls/tls_dump_vf.c b/modules/tls/tls_dump_vf.c
index 942ea7a..e507646 100644
--- a/modules/tls/tls_dump_vf.c
+++ b/modules/tls/tls_dump_vf.c
@@ -3,14 +3,14 @@
  *
  * Copyright (C) 2006 enum.at
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,16 +24,12 @@
  * such as linking with software components and libraries released under
  * OpenSSL project license.
  */
+
 /** log the verification failure reason.
  * @file tls_dump_vf.c
  * @ingroup: tls
  * Module: @ref tls
  */
-/*
- * History:
- * --------
- *  2010-05-20  split from tls_server.c
-*/
 
 #include "tls_dump_vf.h"
 
diff --git a/modules/tls/tls_dump_vf.h b/modules/tls/tls_dump_vf.h
index fe5b64a..aa2a836 100644
--- a/modules/tls/tls_dump_vf.h
+++ b/modules/tls/tls_dump_vf.h
@@ -3,14 +3,14 @@
  *
  * Copyright (C) 2006 enum.at
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -29,11 +29,6 @@
  * @ingroup: tls
  * Module: @ref tls
  */
-/*
- * History:
- * --------
- *  2010-05-20  split from tls_server.c
-*/
 
 #ifndef __tls_dump_vf_h
 #define __tls_dump_vf_h
diff --git a/modules/tls/tls_init.c b/modules/tls/tls_init.c
index 0c03d56..bd14647 100644
--- a/modules/tls/tls_init.c
+++ b/modules/tls/tls_init.c
@@ -16,7 +16,7 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/*! \defgroup tls SIP-router TLS support
+/*! \defgroup tls Kamailio TLS support
  *
  * This modules implements SIP over TCP with TLS encryption.
  * Make sure you read the README file that describes configuration
@@ -27,7 +27,7 @@
  */
 /*!
  * \file
- * \brief SIP-router TLS support :: Initialization
+ * \brief Kamailio TLS support :: Initialization
  * \ingroup tls
  * Module: \ref tls
  */
@@ -138,6 +138,8 @@ const SSL_METHOD* ssl_methods[TLS_METHOD_MAX];
 #define NULL_GRACE_PERIOD 10U
 */
 
+
+
 inline static char* buf_append(char* buf, char* end, char* str, int str_len)
 {
 	if ( (buf+str_len)<end){
@@ -544,11 +546,11 @@ int init_tls_h(void)
 	 * (e.g. 0.9.8a & 0.9.8c are ok, but 0.9.8 and 0.9.9x are not) */
 	if ((ssl_version>>8)!=(OPENSSL_VERSION_NUMBER>>8)){
 		LOG(L_CRIT, "ERROR: tls: init_tls_h: installed openssl library "
-				"version is too different from the library the ser tls module "
+				"version is too different from the library the Kamailio tls module "
 				"was compiled with: installed \"%s\" (0x%08lx), compiled "
 				"\"%s\" (0x%08lx).\n"
 				" Please make sure a compatible version is used"
-				" (tls_force_run in ser.cfg will override this check)\n",
+				" (tls_force_run in kamailio.cfg will override this check)\n",
 				SSLeay_version(SSLEAY_VERSION), ssl_version,
 				OPENSSL_VERSION_TEXT, (long)OPENSSL_VERSION_NUMBER);
 		if (cfg_get(tls, tls_cfg, force_run))
@@ -597,8 +599,8 @@ int init_tls_h(void)
 		if (lib_kerberos!=-1){
 			LOG(L_CRIT, "ERROR: tls: init_tls_h: openssl compile options"
 						" mismatch: library has kerberos support"
-						" %s and ser tls %s (unstable configuration)\n"
-						" (tls_force_run in ser.cfg will override this"
+						" %s and Kamailio tls %s (unstable configuration)\n"
+						" (tls_force_run in kamailio.cfg will override this"
 						" check)\n",
 						lib_kerberos?"enabled":"disabled",
 						kerberos_support?"enabled":"disabled"
@@ -649,7 +651,7 @@ int init_tls_h(void)
 				low_mem_threshold1, low_mem_threshold2);
 	
 	if (shm_available()==(unsigned long)(-1)){
-		LOG(L_WARN, "tls: ser compiled without MALLOC_STATS support:"
+		LOG(L_WARN, "tls: Kamailio is compiled without MALLOC_STATS support:"
 				" the workaround for low mem. openssl bugs will _not_ "
 				"work\n");
 		low_mem_threshold1=0;
diff --git a/modules/tls/tls_init.h b/modules/tls/tls_init.h
index 78390bf..eb28398 100644
--- a/modules/tls/tls_init.h
+++ b/modules/tls/tls_init.h
@@ -15,9 +15,10 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
+
 /*!
  * \file
- * \brief SIP-router TLS support :: OpenSSL initialization funtions
+ * \brief Kamailio TLS support :: OpenSSL initialization funtions
  * \ingroup tls
  * Module: \ref tls
  */
diff --git a/modules/tls/tls_locking.c b/modules/tls/tls_locking.c
index d35de8f..46a8387 100644
--- a/modules/tls/tls_locking.c
+++ b/modules/tls/tls_locking.c
@@ -18,7 +18,7 @@
 
 /*!
  * \file
- * \brief SIP-router TLS support :: Locking
+ * \brief Kamailio TLS support :: Locking
  * \ingroup tls
  * Module: \ref tls
  */
diff --git a/modules/tls/tls_locking.h b/modules/tls/tls_locking.h
index 056efcd..ee94709 100644
--- a/modules/tls/tls_locking.h
+++ b/modules/tls/tls_locking.h
@@ -15,16 +15,10 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/*
- * tls locking and atomic ops related init functions
- *
- * History:
- * --------
- *  2007-01-22  created by andrei
- */
+
 /*!
  * \file
- * \brief SIP-router TLS support ::  tls locking and atomic ops related init functions
+ * \brief Kamailio  TLS support ::  tls locking and atomic ops related init functions
  * \ingroup tls
  * Module: \ref tls
  */
diff --git a/modules/tls/tls_mod.c b/modules/tls/tls_mod.c
index 4c767dc..2d085d0 100644
--- a/modules/tls/tls_mod.c
+++ b/modules/tls/tls_mod.c
@@ -17,7 +17,7 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/** SIP-router TLS support :: Module interface.
+/** Kamailio TLS support :: Module interface.
  * @file
  * @ingroup tls
  * Module: @ref tls
@@ -82,6 +82,7 @@ static int is_peer_verified(struct sip_msg* msg, char* foo, char* foo2);
 MODULE_VERSION
 
 
+str sr_tls_xavp_cfg = {0, 0};
 /*
  * Default settings when modparams are used 
  */
@@ -99,6 +100,7 @@ static tls_domain_t mod_params = {
 	{0, },                /* Cipher list */
 	TLS_USE_TLSv1,    /* TLS method */
 	STR_STATIC_INIT(TLS_CRL_FILE), /* Certificate revocation list */
+	{0, 0},           /* Server name (SNI) */
 	0                 /* next */
 };
 
@@ -120,6 +122,7 @@ tls_domain_t srv_defaults = {
 	{0, 0},                /* Cipher list */
 	TLS_USE_TLSv1,    /* TLS method */
 	STR_STATIC_INIT(TLS_CRL_FILE), /* Certificate revocation list */
+	{0, 0},           /* Server name (SNI) */
 	0                 /* next */
 };
 
@@ -141,6 +144,7 @@ tls_domain_t cli_defaults = {
 	{0, 0},                /* Cipher list */
 	TLS_USE_TLSv1,    /* TLS method */
 	{0, 0}, /* Certificate revocation list */
+	{0, 0},           /* Server name (SNI) */
 	0                 /* next */
 };
 
@@ -170,6 +174,7 @@ static cmd_export_t cmds[] = {
  */
 static param_export_t params[] = {
 	{"tls_method",          PARAM_STR,    &default_tls_cfg.method       },
+	{"server_name",         PARAM_STR,    &default_tls_cfg.server_name  },
 	{"verify_certificate",  PARAM_INT,    &default_tls_cfg.verify_cert  },
 	{"verify_depth",        PARAM_INT,    &default_tls_cfg.verify_depth },
 	{"require_certificate", PARAM_INT,    &default_tls_cfg.require_cert },
@@ -199,6 +204,7 @@ static param_export_t params[] = {
 	{"low_mem_threshold1",  PARAM_INT,    &default_tls_cfg.low_mem_threshold1},
 	{"low_mem_threshold2",  PARAM_INT,    &default_tls_cfg.low_mem_threshold2},
 	{"renegotiation",       PARAM_INT,    &sr_tls_renegotiation},
+	{"xavp_cfg",            PARAM_STR,    &sr_tls_xavp_cfg},
 	{0, 0, 0}
 };
 
@@ -307,6 +313,7 @@ static int mod_init(void)
 	mod_params.crl_file = cfg_get(tls, tls_cfg, crl);
 	mod_params.cert_file = cfg_get(tls, tls_cfg, certificate);
 	mod_params.cipher_list = cfg_get(tls, tls_cfg, cipher_list);
+	mod_params.server_name = cfg_get(tls, tls_cfg, server_name);
 
 	tls_domains_cfg =
 			(tls_domains_cfg_t**)shm_malloc(sizeof(tls_domains_cfg_t*));
diff --git a/modules/tls/tls_mod.h b/modules/tls/tls_mod.h
index d72f357..288df20 100644
--- a/modules/tls/tls_mod.h
+++ b/modules/tls/tls_mod.h
@@ -15,7 +15,7 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/** SIP-router TLS support :: module interface.
+/** Kamailio TLS support :: module interface.
  * @file
  * @ingroup tls
  * Module: @ref tls
diff --git a/modules/tls/tls_rpc.c b/modules/tls/tls_rpc.c
index c7c994d..67b9649 100644
--- a/modules/tls/tls_rpc.c
+++ b/modules/tls/tls_rpc.c
@@ -4,7 +4,7 @@
  * Copyright (C) 2005 iptelorg GmbH
  * Copyright (C) 2013 Motorola Solutions, Inc.
  *
- * This file is part of sip-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
diff --git a/modules/tls/tls_rpc.h b/modules/tls/tls_rpc.h
index 0d8e958..9a9106f 100644
--- a/modules/tls/tls_rpc.h
+++ b/modules/tls/tls_rpc.h
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2005 iptelorg GmbH
  *
- * This file is part of sip-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
diff --git a/modules/tls/tls_select.c b/modules/tls/tls_select.c
index d4be3d8..b5f6986 100644
--- a/modules/tls/tls_select.c
+++ b/modules/tls/tls_select.c
@@ -4,14 +4,14 @@
  * Copyright (C) 2005 iptelorg GmbH
  * Copyright (C) 2006 enum.at
  *
- * This file is part of sip-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * sip-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * sip-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -25,7 +25,8 @@
  * such as linking with software components and libraries released under
  * OpenSSL project license.
  */
-/** SIP-router TLS support :: Select interface.
+
+/** Kamailio TLS support :: Select interface.
  * @file
  * @ingroup tls
  * Module: @ref tls
diff --git a/modules/tls/tls_select.h b/modules/tls/tls_select.h
index 71f8371..179c7bf 100644
--- a/modules/tls/tls_select.h
+++ b/modules/tls/tls_select.h
@@ -4,19 +4,14 @@
  * Copyright (C) 2005,2006 iptelorg GmbH
  * Copyright (C) 2006 enum.at
  *
- * This file is part of sip-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * sip-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the sip-router software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * sip-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -32,7 +27,7 @@
  */
 /*!
  * \file
- * \brief SIP-router TLS support :: select interface
+ * \brief Kamailio TLS support :: select interface
  * \ingroup tls
  * Module: \ref tls
  */
diff --git a/modules/tls/tls_server.c b/modules/tls/tls_server.c
index eceb78e..3f87fc8 100644
--- a/modules/tls/tls_server.c
+++ b/modules/tls/tls_server.c
@@ -4,7 +4,7 @@
  * Copyright (C) 2005-2010 iptelorg GmbH
  * Copyright (C) 2013 Motorola Solutions, Inc.
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -18,14 +18,7 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/*
- * History:
- * --------
- *  2007-01-26  openssl kerberos malloc bug detection/workaround (andrei)
- *  2007-02-23  openssl low memory bugs workaround (andrei)
- *  2009-09-21  tls connection state is now kept in c->extra_data (no
- *               longer shared with tcp state) (andrei)
- */
+
 /** main tls part (implements the tls hooks that are called from the tcp code).
  * @file tls_server.c
  * @ingroup tls
@@ -49,6 +42,7 @@
 #include "../../route.h"
 #include "../../forward.h"
 #include "../../onsend.h"
+#include "../../xavp.h"
 
 #include "tls_init.h"
 #include "tls_domain.h"
@@ -134,6 +128,30 @@ int tls_run_event_routes(struct tcp_connection *c);
 #endif /* TLS_RD_DEBUG */
 
 
+extern str sr_tls_xavp_cfg;
+
+/**
+ * get the server name (sni) for outbound connections from xavp
+ */
+static str *tls_get_connect_server_name(void)
+{
+#ifndef OPENSSL_NO_TLSEXT
+	sr_xavp_t *vavp = NULL;
+	str sname = {"server_name", 11};
+
+	if(sr_tls_xavp_cfg.s!=NULL)
+		vavp = xavp_get_child_with_sval(&sr_tls_xavp_cfg, &sname);
+	if(vavp==NULL || vavp->val.v.s.len<=0) {
+		LM_DBG("xavp with outbound server name not found\n");
+		return NULL;
+	}
+	LM_DBG("found xavp with outbound server name: %s\n", vavp->val.v.s.s);
+	return &vavp->val.v.s;
+#else
+	return NULL;
+#endif
+}
+
 /** finish the ssl init.
  * Creates the SSL context + internal tls_extra_data and sets
  * extra_data to it.
@@ -148,6 +166,7 @@ static int tls_complete_init(struct tcp_connection* c)
 	struct tls_extra_data* data = 0;
 	tls_domains_cfg_t* cfg;
 	enum tls_conn_states state;
+	str *sname = NULL;
 
 	if (LOW_MEM_NEW_CONNECTION_TEST()){
 		ERR("tls: ssl bug #1491 workaround: not enough memory for safe"
@@ -158,6 +177,8 @@ static int tls_complete_init(struct tcp_connection* c)
 	      * count immediately.
 	      */
 
+	LM_DBG("completing tls connection initialization\n");
+
 	lock_get(tls_domains_cfg_lock);
 	cfg = *tls_domains_cfg;
 
@@ -171,17 +192,20 @@ static int tls_complete_init(struct tcp_connection* c)
 	if (c->flags & F_CONN_PASSIVE) {
 		state=S_TLS_ACCEPTING;
 		dom = tls_lookup_cfg(cfg, TLS_DOMAIN_SRV,
-								&c->rcv.dst_ip, c->rcv.dst_port);
+								&c->rcv.dst_ip, c->rcv.dst_port, 0);
 	} else {
 		state=S_TLS_CONNECTING;
+		sname = tls_get_connect_server_name();
 		dom = tls_lookup_cfg(cfg, TLS_DOMAIN_CLI,
-								&c->rcv.dst_ip, c->rcv.dst_port);
+						&c->rcv.dst_ip, c->rcv.dst_port, sname);
 	}
 	if (unlikely(c->state<0)) {
 		BUG("Invalid connection (state %d)\n", c->state);
 		goto error;
 	}
-	DBG("Using TLS domain %s\n", tls_domain_str(dom));
+	DBG("Using initial TLS domain %s (dom %p ctx %p sn [%s])\n",
+			tls_domain_str(dom), dom, dom->ctx[process_no],
+			ZSW(dom->server_name.s));
 
 	data = (struct tls_extra_data*)shm_malloc(sizeof(struct tls_extra_data));
 	if (!data) {
@@ -202,6 +226,20 @@ static int tls_complete_init(struct tcp_connection* c)
 			BIO_free(data->rwbio);
 		goto error;
 	}
+
+#ifndef OPENSSL_NO_TLSEXT
+	if (sname!=NULL) {
+		if(!SSL_set_tlsext_host_name(data->ssl, sname->s)) {
+			if (data->ssl)
+				SSL_free(data->ssl);
+			if (data->rwbio)
+				BIO_free(data->rwbio);
+			goto error;
+		}
+		LM_DBG("outbound TLS server name set to: %s\n", sname->s);
+	}
+#endif
+
 #ifdef TLS_KSSL_WORKARROUND
 	 /* if needed apply workaround for openssl bug #1467 */
 	if (data->ssl->kssl_ctx && openssl_kssl_malloc_bug){
@@ -214,7 +252,6 @@ static int tls_complete_init(struct tcp_connection* c)
 
 	/* link the extra data struct inside ssl connection*/
 	SSL_set_app_data(data->ssl, data);
-
 	return 0;
 
  error:
@@ -554,6 +591,7 @@ int tls_h_tcpconn_init(struct tcp_connection *c, int sock)
 	c->type = PROTO_TLS;
 	c->rcv.proto = PROTO_TLS;
 	c->timeout = get_ticks_raw() + cfg_get(tls, tls_cfg, con_lifetime);
+	c->lifetime = cfg_get(tls, tls_cfg, con_lifetime);
 	c->extra_data = 0;
 	return 0;
 }
diff --git a/modules/tls/tls_server.h b/modules/tls/tls_server.h
index abb3b13..0197b8d 100644
--- a/modules/tls/tls_server.h
+++ b/modules/tls/tls_server.h
@@ -3,7 +3,7 @@
  * 
  * Copyright (C) 2005-2010 iptelorg GmbH
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -17,6 +17,7 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
+
 /** main tls part (implements the tls hooks that are called from the tcp code).
  * @file tls_server.h
  * @ingroup tls
diff --git a/modules/tls/tls_util.c b/modules/tls/tls_util.c
index 4889eb3..5d61087 100644
--- a/modules/tls/tls_util.c
+++ b/modules/tls/tls_util.c
@@ -17,6 +17,13 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+/*!
+ * \file
+ * \brief Kamailio TLS support :: Common functions
+ * \ingroup tls
+ * Module: \ref tls
+ */
+
 
 #define _GNU_SOURCE 1 /* Needed for strndup */
 
@@ -27,13 +34,6 @@
 #include "../../dprint.h"
 #include "tls_mod.h"
 #include "tls_util.h"
-/*!
- * \file
- * \brief SIP-router TLS support :: Common functions
- * \ingroup tls
- * Module: \ref tls
- */
-
 
 
 /*
diff --git a/modules/tls/tls_util.h b/modules/tls/tls_util.h
index c345024..efbd842 100644
--- a/modules/tls/tls_util.h
+++ b/modules/tls/tls_util.h
@@ -17,7 +17,7 @@
  */
 /*!
  * \file
- * \brief SIP-router TLS support :: Common functions
+ * \brief Kamailio TLS support :: Common functions
  * \ingroup tls
  * Module: \ref tls
  */
diff --git a/modules/tls/tls_verify.c b/modules/tls/tls_verify.c
index 4751555..728006d 100644
--- a/modules/tls/tls_verify.c
+++ b/modules/tls/tls_verify.c
@@ -21,7 +21,7 @@
 
 /*!
  * \file
- * \brief SIP-router TLS support :: Certificate verification
+ * \brief Kamailio TLS support :: Certificate verification
  * \ingroup tls
  * Module: \ref tls
  */
diff --git a/modules/tls/tls_verify.h b/modules/tls/tls_verify.h
index 68b0662..017ad44 100644
--- a/modules/tls/tls_verify.h
+++ b/modules/tls/tls_verify.h
@@ -17,7 +17,7 @@
  */
 /*!
  * \file
- * \brief SIP-router TLS support :: Certificate verification function
+ * \brief Kamailio TLS support :: Certificate verification function
  * \ingroup tls
  * Module: \ref tls
  */
diff --git a/modules/tm/Makefile b/modules/tm/Makefile
index 93807ca..6cfe647 100644
--- a/modules/tm/Makefile
+++ b/modules/tm/Makefile
@@ -1,6 +1,5 @@
-# $Id$
 #
-# example module makefile
+# tm module makefile
 #
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
diff --git a/modules/tm/README b/modules/tm/README
index 892f778..01ec6ac 100644
--- a/modules/tm/README
+++ b/modules/tm/README
@@ -120,6 +120,7 @@ Juha Heinanen
               5.48. t_set_no_e2e_cancel_reason(0|1)
               5.49. t_is_set(target)
               5.50. t_use_uac_headers()
+              5.51. t_is_retr_async_reply()
 
         6. TM Module API
 
@@ -231,7 +232,8 @@ Juha Heinanen
    1.86. t_set_no_e2e_cancel_reason usage
    1.87. t_replicate usage
    1.88. t_use_uac_headers usage
-   1.89. event_route[tm:branch-failure] usage
+   1.89. t_is_retr_async_reply usage
+   1.90. event_route[tm:branch-failure] usage
 
 Chapter 1. Admin Guide
 
@@ -340,6 +342,7 @@ Chapter 1. Admin Guide
         5.48. t_set_no_e2e_cancel_reason(0|1)
         5.49. t_is_set(target)
         5.50. t_use_uac_headers()
+        5.51. t_is_retr_async_reply()
 
    6. TM Module API
 
@@ -672,7 +675,7 @@ modparam("tm", "fr_timer", 10000)
    Timer which hits if no final reply for an INVITE arrives after a
    provisional message was received (in milliseconds).
 
-   Note: this timer can be restarted when a provisional response is
+   Note: This timer can be restarted when a provisional response is
    received. For more details see restart_fr_on_each_reply.
 
    Default value is 120000 ms (120 seconds).
@@ -693,7 +696,7 @@ modparam("tm", "fr_inv_timer", 180000)
    transaction fr_inv_timer and fr_timer values.
 
    An INVITE transaction will be kept in memory for maximum:
-   max_inv_lifetime+fr_timer(from the ack to the final reply
+   max_inv_lifetime+fr_timer(from the ACK to the final reply
    wait)+wt_timer.
 
    The main difference between this timer and fr_inv_timer is that the
@@ -704,8 +707,8 @@ modparam("tm", "fr_inv_timer", 180000)
    provisional reply. Even if restart_fr_on_each_reply is not set the
    fr_inv_timer will still be restarted for each increasing reply (e.g.
    180, 181, 182, ...). Another example when a transaction can live
-   substantially more then its fr_inv_timer and where max_inv_lifetime
-   will help is when dns failover is used (each failed dns destination can
+   substantially more than its fr_inv_timer and where max_inv_lifetime
+   will help is when DNS failover is used (each failed DNS destination can
    introduce a new branch).
 
    The default value is 180000 ms (180 seconds - the rfc3261 timer C
@@ -729,17 +732,17 @@ modparam("tm", "max_inv_lifetime", 150000)
    transaction fr_timer value. It's the same as max_inv_lifetime, but for
    non-INVITEs.
 
-   A non-INVITE transaction will be kept in memory for maximum:
+   A non-INVITE transaction will be kept in memory for a maximum of:
    max_noninv_lifetime+wt_timer.
 
    The main difference between this timer and fr_timer is that the
    fr_timer is per branch, while max_noninv_lifetime is per the whole
    transaction. An example when a transaction can live substantially more
-   then its fr_timer and where max_noninv_lifetime will help is when dns
-   failover is used (each failed dns destination can introduce a new
+   then its fr_timer and where max_noninv_lifetime will help is when DNS
+   failover is used (each failed DNS SRV destination can introduce a new
    branch).
 
-   The default value is 32000 ms (32 seconds - the rfc3261 timer F value).
+   The default value is 32000 ms (32 seconds - the RFC3261 timer F value).
 
    See also: max_inv_lifetime, t_set_max_lifetime() (allows changing
    max_noninv_lifetime on a per transaction basis), t_reset_max_lifetime
@@ -754,9 +757,9 @@ modparam("tm", "max_noninv_lifetime", 30000)
 
    Time for which a transaction stays in memory to absorb delayed messages
    after it completed (in milliseconds); also, when this timer hits,
-   retransmission of local cancels is stopped (a puristic but complex
-   behavior would be not to enter wait state until local branches are
-   finished by a final reply or FR timer--we simplified).
+   retransmission of local CANCEL requests is stopped (a puristic but
+   complex behavior would be not to enter wait state until local branches
+   are finished by a final reply or FR timer--we simplified).
 
    Default value is 5000 ms (5 seconds).
 
@@ -770,7 +773,7 @@ modparam("tm", "wt_timer", 1000)
    Time after which a to-be-deleted transaction currently ref-ed by a
    process will be tried to be deleted again (in milliseconds).
 
-   Note: this parameter is obsolete for ser 2.1 (in 2.1 the transaction is
+   Note: this parameter is obsolete for SER 2.1 (in 2.1 the transaction is
    deleted the moment it's not referenced anymore).
 
    Default value is 200 milliseconds.
@@ -811,10 +814,11 @@ modparam("tm", "retr_timer2", 2000)
    response was ever received on this branch, it will be silently dropped
    (no 408 reply will be generated) This behavior is overridden if a
    request is forked, the transaction has a failure route or callback, or
-   some functionality explicitly turned it on for a transaction (like acc
-   does to avoid unaccounted transactions due to expired timer). Turn this
-   off only if you know the client UACs will timeout and their timeout
-   interval for INVITEs is lower or equal than tm's fr_inv_timer.
+   some functionality explicitly turned it on for a transaction (like the
+   ACC module does to avoid unaccounted transactions due to expired
+   timer). Turn this off only if you know the client UACs will timeout and
+   their timeout interval for INVITEs is lower or equal than tm's
+   fr_inv_timer.
 
    Default value is 1 (on).
 
@@ -849,7 +853,7 @@ modparam("tm", "restart_fr_on_each_reply", 0)
 
    If set (default) tm will automatically send and 100 reply to INVITEs.
 
-   Setting it to 0 one can be used to enable doing first some tests or
+   Setting it to 0 can be used to enable first running some tests or
    pre-processing on the INVITE and only if some conditions are met
    manually send a 100 (using t_reply()). Note however that in this case
    all the 100s have to be sent "by hand". t_set_auto_inv_100() might help
@@ -867,7 +871,7 @@ modparam("tm", "auto_inv_100", 0)
 
 4.12. auto_inv_100_reason (string)
 
-   Set reason text of the automatically send 100 to an INVITE.
+   Set reason text of the automatically sent 100 to an INVITE.
 
    Default value is "trying -- your call is important to us".
 
@@ -882,8 +886,8 @@ modparam("tm", "auto_inv_100_reason", "Trying")
 
    Unix socket transmission timeout, in milliseconds.
 
-   If unix sockets are used (e.g.: to communicate with sems) and sending a
-   message on a unix socket takes longer then unix_tx_timeout, the send
+   If UNIX sockets are used (e.g.: to communicate with sems) and sending a
+   message on a UNIX socket takes longer than unix_tx_timeout, the send
    will fail.
 
    The default value is 500 milliseconds.
@@ -895,15 +899,17 @@ modparam("tm", "unix_tx_timeout", 250)
 
 4.14. aggregate_challenges (integer)
 
-   If set (default), the final reply is a 401 or a 407 and more then one
-   branch received a 401 or 407, then all the WWW-Authenticate and
+   If set (default) and the final response is a 401 or a 407 and more than
+   one branch received a 401 or 407, then all the WWW-Authenticate and
    Proxy-Authenticate headers from all the 401 and 407 replies will be
-   aggregated in a new final reply. If only one branch received the
+   aggregated in a new final response. If only one branch received the
    winning 401 or 407 then this reply will be forwarded (no new one will
-   be built). If 0 only the first 401, or if no 401 was received the first
-   407, will be forwarded (no header aggregation).
+   be built).
 
-   Default value is 1 (required by rfc3261).
+   If disabled (set to 0) only the first 401, or if no 401 was received
+   the first 407, will be forwarded (no header aggregation).
+
+   Default value is 1 (required by RFC 3261).
 
    Example 1.14. Set aggregate_challenges parameter
 ...
@@ -920,13 +926,13 @@ modparam("tm", "aggregate_challenges", 0)
    INVITE message. Do not disable the INVITE re-parsing for example in the
    following cases:
 
-   - The INVITE contains a preloaded route-set, and SER forwards the
-   message to the next hop according to the Route header. The Route header
-   is not removed in the CANCEL without reparse_invite=1.
+   - The INVITE contains a preloaded route-set, and Kamailio forwards the
+   message to the next hop according to the "Route" header. The "Route"
+   header is not removed in the CANCEL without reparse_invite=1.
 
-   - SER record-routes, thus an in-dialog INVITE contains a Route header
-   which is removed during loose routing. If the in-dialog INVITE is
-   rejected, the negative ACK still contains the Route header without
+   - Kamailio record-routes, thus an in-dialog INVITE contains a "Route"
+   header which is removed during loose routing. If the in-dialog INVITE
+   is rejected, the negative ACK still contains the "Route" header without
    reparse_invite=1.
 
    Default value is 1.
@@ -943,7 +949,7 @@ modparam("tm", "reparse_invite", 0)
    INVITE.
 
    Note, that the parameter value effects only those headers which are not
-   covered by RFC-3261 (which are neither mandatory nor prohibited in
+   covered by RFC 3261 (which are neither mandatory nor prohibited in
    CANCEL and ACK), and the parameter can be used only together with
    reparse_invite=1.
 
@@ -956,11 +962,11 @@ modparam("tm", "ac_extra_hdrs", "myfavoriteheaders-")
 
 4.17. blst_503 (integer)
 
-   If set and the blacklist support is enabled, every 503 reply source is
-   added to the blacklist. The initial blacklist timeout (or ttl) depends
-   on the presence of a Retry-After header in the reply and the values of
-   the following tm parameters: blst_503_def_timeout, blst_503_min_timeout
-   and blst_503_max_timeout.
+   If set and the Kamailio blacklist support is enabled, every 503 reply
+   source is added to the blacklist. The initial blacklist timeout (or
+   ttl) depends on the presence of a "Retry-After" header in the reply and
+   the values of the following tm parameters: blst_503_def_timeout,
+   blst_503_min_timeout and blst_503_max_timeout.
 
    WARNING:blindly allowing 503 blacklisting could be very easily
    exploited for DOS attacks in most network setups.
@@ -974,13 +980,13 @@ modparam("tm", "blst_503", 1)
 
 4.18. blst_503_def_timeout (integer)
 
-   Blacklist interval in seconds for a 503 reply with no Retry-After
+   Blacklist interval in seconds for a 503 reply with no "Retry-After"
    header. See also blst_503, blst_503_min_timeout and
    blst_503_max_timeout.
 
-   The default value is 0, which means that if no Retry-After header is
-   present, the 503 reply source will not be blacklisted (rfc conformant
-   behaviour).
+   The default value is 0, which means that if no "Retry-After" header is
+   present, the 503 reply source will not be blacklisted (RFC 3261
+   conformant behaviour).
 
    Example 1.18. Set blst_503_def_timeout parameter
 ...
@@ -990,9 +996,10 @@ modparam("tm", "blst_503_def_timeout", 120)
 4.19. blst_503_min_timeout (integer)
 
    Minimum blacklist interval in seconds for a 503 reply with a
-   Retry-After header. It will be used if the Retry-After value is
-   smaller. See also blst_503, blst_503_def_timeout and
-   blst_503_max_timeout.
+   "Retry-After" header. It will be used if the "Retry-After" value is
+   smaller than this value.
+
+   See also blst_503, blst_503_def_timeout and blst_503_max_timeout.
 
    The default value is 0
 
@@ -1004,9 +1011,10 @@ modparam("tm", "blst_503_min_timeout", 30)
 4.20. blst_503_max_timeout (integer)
 
    Maximum blacklist interval in seconds for a 503 reply with a
-   Retry-After header. It will be used if the Retry-After value is
-   greater. See also blst_503, blst_503_def_timeout and
-   blst_503_min_timeout.
+   "Retry-After header". It will be used if the "Retry-After" value is
+   greater than this limit.
+
+   See also blst_503, blst_503_def_timeout and blst_503_min_timeout.
 
    The default value is 3600
 
@@ -1026,11 +1034,11 @@ modparam("tm", "blst_503_max_timeout", 604800)
    INFO=16, REGISTER=32, SUBSCRIBE=64, NOTIFY=126, OTHER=256 (all the
    unknown types). Check parser/msg_parser.h for farther details.
 
-   Change the value carefully, because requests not having provisional
-   response (everything but INVITE) can easily cause the next hop to be
-   inserted into the blacklist by mistake. For exmaple the next hop is a
-   proxy, it is alive, but waiting for the response of the UAS, and has
-   higher fr_timer value.
+   Change the value carefully, because requests that doesn't get a
+   provisional response (everything but INVITE) can easily cause the next
+   hop to be inserted into the blacklist by mistake. For exmaple the next
+   hop is a proxy, it is alive, but waiting for the response of the UAS,
+   and has higher fr_timer value.
 
    The default value is 1, only INVITEs trigger blacklisting
 
@@ -1042,8 +1050,8 @@ modparam("tm", "blst_methods_add", 33)
 
 4.22. blst_methods_lookup (unsigned integer)
 
-   Bitmap of method types that are looked-up in the blacklist before
-   statefull forwarding. See also blst_methods_add
+   Bitmap of method types that are looked-up in the blacklist before being
+   forwarded statefully. See also blst_methods_add
 
    The default value is 4294967287, every method type except BYE. (We try
    to deliver BYEs no matter what)
@@ -1057,10 +1065,10 @@ modparam("tm", "blst_methods_lookup", 1)
 4.23. cancel_b_method (integer)
 
    Method used when attempting to CANCEL an unreplied transaction branch
-   (a branch where no reply greater the 99 was received). The possible
-   values are 0, 1, and 2.
+   (a branch where no response was received). The possible values are 0,
+   1, and 2.
 
-   0 will immediately stop the request (INVITE) retransmission on the
+   - 0 will immediately stop the request (INVITE) retransmission on the
    branch and it will behave as if the branch was immediately replied with
    a 487 (a fake internal 487 reply). The advantage is the unreplied
    branches will be terminated immediately. However it introduces a race
@@ -1068,22 +1076,22 @@ modparam("tm", "blst_methods_lookup", 1)
    have an UA receiving a 2xx after a 487. Moreover this risk is greatly
    amplified by packet loss (e.g. if an 180 is lost the branch will look
    as unreplied and a CANCEL will silently drop the branch, but a 2xx can
-   still come at a later time). This is the behaviour for ser versions
-   older then 2.1.
+   still come at a later time). This is the behaviour for SER versions
+   older than 2.1.
 
-   1 will keep retransmitting the request on unreplied branches. If a
-   provisional answer is later received a CANCEL will be immediately sent
-   back (attempting to quickly trigger a 487). This approach is race free
-   and avoids the 2xx after 487 problem, but it's more resource intensive:
+   - 1 will keep retransmitting the request on unreplied branches. If a
+   provisional answer is received a CANCEL will be immediately sent back
+   (attempting to quickly trigger a 487). This approach is race free and
+   avoids the 2xx after 487 problem, but it's more resource intensive:
    faced with a branch towards and UA that doesn't answer, a CANCEL
    attempt will keep the transaction alive for the whole timeout interval
    (fr_timer).
 
-   2 will send and retransmit CANCEL even on unreplied branches, stopping
-   the request retransmissions. This has the same advantages as 1 and also
-   avoids the extra roundtrip in the case of the provisional reply, but
-   it's not RFC 3261 conforming (the RFC allows sending CANCELs only on
-   pending branches).
+   - 2 will send and retransmit CANCEL even on unreplied branches,
+   stopping the request retransmissions. This has the same advantages as 1
+   and also avoids the extra roundtrip in the case of the provisional
+   reply, but it's not RFC 3261 conforming (the RFC allows sending CANCELs
+   only on pending branches).
 
    The default value is 1.
 
@@ -1110,8 +1118,8 @@ modparam("tm", "cancel_b_method", 1)
    the outgoing socket address is not corrected in any other part of the
    message. It is dangerous on multihomed hosts: when the new SIP request
    after the DNS failover is sent via different interface than the first
-   request, the message can contain incorrect ip address in the
-   Record-Route header for instance.
+   request, the message can contain incorrect IP address in the
+   Record-Route header.
 
    Default value is 1.
 
@@ -1139,7 +1147,7 @@ onreply_route["stateless_replies"] {
 
 4.26. contacts_avp (string)
 
-   This is the name of an XAVP that t_load_contacts() function uses to
+   This is the name of an XAVP that the t_load_contacts() function uses to
    store contacts of the destination set and that t_next_contacts()
    function uses to restore those contacts.
 
@@ -1153,7 +1161,7 @@ modparam("tm", "contacts_avp", "tm_contacts")
 
 4.27. contact_flows_avp (string)
 
-   This is the name of an XAVP that t_next_contacts() function uses to
+   This is the name of an XAVP that the t_next_contacts() function uses to
    store contacts (if any) that it skipped, because they contained same
    +sip.instance value than some other contact, and that
    t_next_contact_flows() function uses to restore those contacts.
@@ -1175,9 +1183,6 @@ modparam("tm", "contact_flows_avp", "tm_contact_flows")
    fr_timer timer, effectively overriding the value configured in fr_timer
    parameter for the current transaction.
 
-   The value of this parameter is the the name of the AVP to be checked,
-   without the $ character or "$avp" prefix.
-
 Note
 
    The value of the AVP is expected to be expressed in seconds and not
@@ -1192,13 +1197,14 @@ Note
 
    In Kamailio compatibility mode (defined by #!KAMAILIO), the value of
    the parameter must be the name of an AVP in pseudo-variable format:
-   $avp(name). In SER compatibility mode it must by just AVP name.
+   $avp(name). In SER compatibility mode it must be just AVP name.
 
    Example 1.28. Set fr_timer_avp parameter
 ...
-modparam("tm", "fr_timer_avp", "i:708")
-# K mode
+# Kamailio mode
 modparam("tm", "fr_timer_avp", "$avp(i:708)")
+# Old SER mode
+modparam("tm", "fr_timer_avp", "i:708")
 ...
 
 4.29. fr_inv_timer_avp (string)
@@ -1211,9 +1217,6 @@ modparam("tm", "fr_timer_avp", "$avp(i:708)")
    effectively overriding the value configured in fr_inv_timer parameter
    for the current transaction.
 
-   The value of this parameter is the the name of the AVP to be checked,
-   without the $ character or "$avp" prefix.
-
 Note
 
    The value of the AVP is expected to be expressed in seconds and not
@@ -1232,22 +1235,24 @@ Note
 
    Example 1.29. Set fr_inv_timer_avp parameter
 ...
-modparam("tm", "fr_inv_timer_avp", "my_fr_inv_timer")
-# K mode
+# Kamailio mode
 modparam("tm", "fr_inv_timer_avp", "$avp(my_fr_inv_timer)")
+# Old SER mode
+modparam("tm", "fr_inv_timer_avp", "my_fr_inv_timer")
 ...
 
 4.30. unmatched_cancel (string)
 
    This parameter selects between forwarding CANCELs that do not match any
    transaction statefully (0, default value), statelessly (1) or dropping
-   them (2). Note that the statefull forwarding has an additional hidden
-   advantage: tm will be able to recognize INVITEs that arrive after their
-   CANCEL. Note also that this feature could be used to try a memory
-   exhaustion DOS attack against a proxy that authenticates all requests,
-   by continuously flooding the victim with CANCELs to random destinations
-   (since the CANCEL cannot be authenticated, each received bogus CANCEL
-   will create a new transaction that will live by default 30s).
+   them (2). Note that the stateful forwarding has an additional hidden
+   advantage: the tm module will be able to recognize INVITEs that arrive
+   after their CANCEL. Note also that this feature could be used to try a
+   memory exhaustion DOS attack against a proxy that authenticates all
+   requests, by continuously flooding the victim with CANCELs to random
+   destinations (since the CANCEL cannot be authenticated, each received
+   bogus CANCEL will create a new transaction that will live by default
+   30s).
 
    Default value is 0.
 
@@ -1258,9 +1263,9 @@ modparam("tm", "unmatched_cancel", "2")
 
 4.31. ruri_matching (integer)
 
-   If set it will also try to match the request uri when doing pre-3261
-   transaction matching (the via branch parameter does not contain the
-   3261 cookie).
+   If set the TM module will try to match the request URI when doing SIP
+   1.0 (pre-RFC 3261) transaction matching (the "Via" header branch
+   parameter does not contain the 3261 cookie).
 
    The only reason to have it not set is for interoperability with old,
    broken implementations.
@@ -1277,9 +1282,9 @@ modparam("tm", "ruri_matching", 1)
 
 4.32. via1_matching (integer)
 
-   If set it will also try to match the topmost via when doing pre-3261
-   transaction matching (the via branch parameter does not contain the
-   3261 cookie).
+   If set the TM module will try to match the topmost "Via" header when
+   doing SIP 1.0 (pre-RFC 3261) transaction matching (the "Via" header
+   branch parameter does not contain the 3261 cookie).
 
    The only reason to have it not set is for interoperability with old,
    broken implementations.
@@ -1296,12 +1301,12 @@ modparam("tm", "via1_matching", 1)
 
 4.33. callid_matching (integer)
 
-   If set it will also try to match the callid when doing transaction
-   matching.
+   If set the TM module will try to match the callid when doing
+   transaction matching.
 
    Turn on if you don't want replies/requests from broken clients who send
    a mangled Call-ID to match the transaction. For example when the other
-   side won't recognise the response anyway because of changed Call-ID,
+   side won't recognise the response anyway because of a changed Call-ID,
    this setting will prevent accounting records to be created or
    failure_route to be skipped.
 
@@ -1362,11 +1367,11 @@ modparam("tm", "default_reason", "Unknown reason")
 
 4.37. disable_6xx_block (integer)
 
-   If set tm will treat all the 6xx replies like normal replies (warning:
-   this would be non-rfc conformant behaviour).
+   If set the TM module will treat all the 6xx replies like normal replies
+   (warning: this would be non-RFC conformant behaviour).
 
    If not set (default) receiving a 6xx will cancel all the running
-   parallel branches, will stop dns failover and forking. However serial
+   parallel branches, will stop DNS failover and forking. However serial
    forking using append_branch() in the failure_route will still work.
 
    It can be overwritten on a per transaction basis using
@@ -1386,12 +1391,12 @@ modparam("tm", "disable_6xx_block", 1)
 
 4.38. local_ack_mode (integer)
 
-   It controls where locally generated ACKs for 2xx replies to local
-   transactions (transactions created via t_uac*() either thorugh the tm
-   api or via RPC/mi/fifo) are sent.
+   This setting controls where locally generated ACKs for 2xx replies to
+   local transactions (transactions created via t_uac*() either through
+   the TM api or via RPC/mi/fifo) are sent.
 
    It has 3 possible values:
-     * 0 - the ACK destination is choosen according to the rfc: the next
+     * 0 - the ACK destination is choosen according to the RFC: the next
        hop is found using the contact and the route set and then DNS
        resolution is used on it.
      * 1 - the ACK is sent to the same address as the corresponding INVITE
@@ -1400,11 +1405,11 @@ modparam("tm", "disable_6xx_block", 1)
 
 Note
 
-   Mode 1 and 2 break the rfc, but are useful to deal with some simple UAs
-   behind the NAT cases (no different routing for the ACK and the contact
-   contains an address behind the NAT).
+   Mode 1 and 2 does not follow RFC 3261, but are useful to deal with some
+   simple UAs behind a NAT (no different routing for the ACK and the
+   contact contains an address behind the NAT).
 
-   The default value is 0 (rfc conformant behaviour).
+   The default value is 0 (RFC conformant behaviour).
 
    Can be set at runtime, e.g.:
         $ kamcmd cfg.set_now_int tm local_ack_mode 0
@@ -1416,9 +1421,9 @@ modparam("tm", "local_ack_mode", 1)
 
 4.39. failure_reply_mode (integer)
 
-   It controls how branches are managed and replies are selected for
-   failure_route handling: keep all, drop all, drop last branches in SIP
-   serial forking handling.
+   This parameter controls how branches are managed and replies are
+   selected for failure_route handling: keep all, drop all, drop last
+   branches in SIP serial forking handling.
 
    To control per transaction see t_drop_replies().
 
@@ -1430,7 +1435,7 @@ modparam("tm", "local_ack_mode", 1)
        redirection in failure route, sent to a new destination and this
        one timeout, you will get again the 3xx). Use t_drop_replies() on
        per transaction fashion to control the behavior you want. It is the
-       default behaviour comming from SER 2.1.x.
+       default behaviour coming from SER 2.1.x.
      * 1 - all branches are discarded by default. You can still overwrite
        the behaviour via t_drop_replies()
      * 2 - by default only the branches of previous leg of serial forking
@@ -1527,7 +1532,7 @@ modparam("tm", "remap_503_500", 0)
 
 4.44. failure_exec_mode (boolean)
 
-   Add local failed branches in timer to be cosidered for failure routing
+   Add local failed branches in timer to be considered for failure routing
    blocks. If disabled, relay functions will return false in case the
    branch could not be forwarded (default behaviour before v4.1.0).
 
@@ -1541,15 +1546,16 @@ modparam("tm", "failure_exec_mode", 1)
 4.45. dns_reuse_rcv_socket (boolean)
 
    Control reuse of the receive socket for additional branches added by
-   dns failover. If set to 1, the receive socket is used for sending out
+   DNS failover. If set to 1, the receive socket is used for sending out
    the new branches, unless the socket is forced explicitely in
    configuration file. If set to 0, selected socket is done depending on
-   value of global parameter mhomed (if mhomed=0, then the first listen
+   value of global parameter "mhomed" (if mhomed=0, then the first listen
    socket is used, otherwise the socket is selected based on routing
    rules).
 
-   Do enable it with caution, it might create troubles on dns results with
-   different transport layer. Better let it disabled and enable mhomed.
+   Do enable it with caution, it might create troubles on DNS results with
+   different transport layer. Better let it be disabled and enable
+   "mhomed".
 
    Default value is 0 (disabled).
 
@@ -1610,6 +1616,7 @@ modparam("tm", "dns_reuse_rcv_socket", 1)
    5.48. t_set_no_e2e_cancel_reason(0|1)
    5.49. t_is_set(target)
    5.50. t_use_uac_headers()
+   5.51. t_is_retr_async_reply()
 
 5.1. t_relay([host, port])
 
@@ -2671,6 +2678,29 @@ if(!t_is_set("failure_route"))
 t_use_uac_headers();
 ...
 
+5.51. t_is_retr_async_reply()
+
+   Check to see if the reply is a retransmitted reply on a transaction
+   that is currently suspended asynchronously (suspended during reply
+   processing). Right now the check is only on the transaction, we don't
+   actually check to see if the reply message is an actual retransmission
+   of the suspended reply. This is expected as you should not process
+   another reply until the suspended reply processing has been completed.
+   The trick here is to make sure you don't suspend for too long or even
+   worse, indefinitely.
+
+   returns true if the transaction is currently reply suspended or false
+   if not.
+
+   Example 1.89. t_is_retr_async_reply usage
+...
+if (t_is_retr_async_reply()) {
+        xlog("L_DBG", "Dropping retransmitted reply which is still currently sus
+pended\n");
+        drop();
+}
+...
+
 6. TM Module API
 
    6.1. Defines
@@ -2852,7 +2882,7 @@ action *route)
    enabled with the t_on_branch_failure function. This event_route uses
    the BRANCH_FAILURE_ROUTE route type.
 
-   Example 1.89. event_route[tm:branch-failure] usage
+   Example 1.90. event_route[tm:branch-failure] usage
 ...
 route {
     t_on_branch_failure("myroute");
diff --git a/modules/tm/callid.c b/modules/tm/callid.c
index 0688d88..560af33 100644
--- a/modules/tm/callid.c
+++ b/modules/tm/callid.c
@@ -1,14 +1,14 @@
 /*
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -17,10 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * ----------
- *  2003-04-09  Created by janakj
- *  2003-10-24  updated to the new socket_info lists (andrei)
  */
 
 /*!
diff --git a/modules/tm/callid.h b/modules/tm/callid.h
index 541942f..3a829f1 100644
--- a/modules/tm/callid.h
+++ b/modules/tm/callid.h
@@ -1,14 +1,14 @@
 /*
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/modules/tm/config.c b/modules/tm/config.c
index d53a5a1..ee290ae 100644
--- a/modules/tm/config.c
+++ b/modules/tm/config.c
@@ -1,16 +1,15 @@
 /*
- * $Id$
  *
  * Copyright (C) 2008 iptelorg GmbH
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -19,9 +18,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History
- * -------
- *  2008-02-05	adapting tm module for the configuration framework (Miklos)
  */
 
 /** TM :: Runtime configuration variables.
diff --git a/modules/tm/config.h b/modules/tm/config.h
index 8b2853d..7081dd3 100644
--- a/modules/tm/config.h
+++ b/modules/tm/config.h
@@ -1,17 +1,14 @@
 /*
- * $Id$
- *
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/modules/tm/defs.h b/modules/tm/defs.h
index 1645023..b712b1d 100644
--- a/modules/tm/defs.h
+++ b/modules/tm/defs.h
@@ -1,17 +1,15 @@
 /*
- * $Id$
- *
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -20,9 +18,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * ---------
- * 2003-01-27 t_uac deprecated (jiri)
  */
 
 /*!
diff --git a/modules/tm/dlg.c b/modules/tm/dlg.c
index 31748a3..d78e170 100644
--- a/modules/tm/dlg.c
+++ b/modules/tm/dlg.c
@@ -1,16 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -19,12 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * -------
- * 2003-03-29 Created by janakj
- * 2003-07-08 added wrapper to calculate_hooks, needed by b2bua (dcm)
- * 2007-04-13 added dialog callbacks (andrei)
- * 2007-05-16 added dialog callbacks destroy (andrei)
  */
 
 /*!
diff --git a/modules/tm/dlg.h b/modules/tm/dlg.h
index e260db0..ed5529c 100644
--- a/modules/tm/dlg.h
+++ b/modules/tm/dlg.h
@@ -1,15 +1,14 @@
 /*
- * $Id$
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -18,10 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * -------
- * 2003-03-29 Created by janakj
- * 2007-04-13 added dialog callbacks (andrei)
  */
 
 /*!
diff --git a/modules/tm/doc/functions.xml b/modules/tm/doc/functions.xml
index af7d11d..d93d181 100644
--- a/modules/tm/doc/functions.xml
+++ b/modules/tm/doc/functions.xml
@@ -1723,5 +1723,29 @@ t_use_uac_headers();
 	    </programlisting>
 	</example>
     </section>
-
-</section>
+	<section id="tm.f.t_is_retr_async_reply">
+	<title>
+	    <function>t_is_retr_async_reply()</function>
+	</title>
+	<para>
+	Check to see if the reply is a retransmitted reply on a transaction that is 
+	currently suspended asynchronously (suspended during reply processing). Right now the check is only on the 
+	transaction, we don't actually check to see if the reply message is an actual 
+	retransmission of the suspended reply. This is expected as you should not process 
+	another reply until the suspended reply processing has been completed. The trick here 
+	is to make sure you don't suspend for too long or even worse, indefinitely.
+	</para>
+	<para>returns true if the transaction is currently reply suspended or false if not.</para>
+	<example>
+	    <title><function>t_is_retr_async_reply</function> usage</title>
+	    <programlisting>
+...
+if (t_is_retr_async_reply()) {
+	xlog("L_DBG", "Dropping retransmitted reply which is still currently suspended\n");
+        drop();
+}
+...
+	    </programlisting>
+	</example>
+    </section>
+    </section>
diff --git a/modules/tm/doc/params.xml b/modules/tm/doc/params.xml
index 6711916..c0cdf16 100644
--- a/modules/tm/doc/params.xml
+++ b/modules/tm/doc/params.xml
@@ -15,7 +15,7 @@
 
     <title>Parameters</title>
 
-    <section id="fr_timer">
+    <section id="tm.p.fr_timer">
 	<title><varname>fr_timer</varname> (integer)</title>
 	<para>
 	    Timer which hits if no final reply for a request or ACK for a
@@ -38,7 +38,7 @@ modparam("tm", "fr_timer", 10000)
 	</example>
     </section>
 
-    <section id="fr_inv_timer">
+    <section id="tmp.p.fr_inv_timer">
 	<title><varname>fr_inv_timer</varname> (integer)</title>
 	<para>
 	    Timer which hits if no final reply for an INVITE arrives after a
@@ -47,7 +47,7 @@ modparam("tm", "fr_timer", 10000)
 	<para>
 	</para>
 	<para>
-		Note: this timer can be restarted when a provisional response is
+		Note: This timer can be restarted when a provisional response is
 		received. For more details see
 		<varname>restart_fr_on_each_reply</varname>.
 	</para>
@@ -68,7 +68,7 @@ modparam("tm", "fr_inv_timer", 180000)
 	</example>
     </section>
 
-	<section id="max_inv_lifetime">
+	<section id="tm.p.max_inv_lifetime">
 	<title><varname>max_inv_lifetime</varname> (integer)</title>
 	<para>
 		Maximum time an INVITE transaction is allowed to be active (in 
@@ -81,7 +81,7 @@ modparam("tm", "fr_inv_timer", 180000)
 	<para>
 		An INVITE transaction will be kept in memory for maximum:
 		<varname>max_inv_lifetime</varname>+<varname>fr_timer</varname>(from 
-		the ack to the final reply wait)+<varname>wt_timer</varname>.
+		the ACK to the final reply wait)+<varname>wt_timer</varname>.
 	</para>
 	<para>
 		The main difference between this timer and 
@@ -95,10 +95,10 @@ modparam("tm", "fr_inv_timer", 180000)
 		provisional reply. Even if <varname>restart_fr_on_each_reply</varname>
 		is not set the <varname>fr_inv_timer</varname> will still be restarted
 		for each increasing reply (e.g. 180, 181, 182, ...). 
-		Another example when a transaction can live substantially more then its
+		Another example when a transaction can live substantially more than its
 		<varname>fr_inv_timer</varname> and where
-		<varname>max_inv_lifetime</varname> will help is when dns failover is 
-		used (each failed dns destination can introduce a new branch).
+		<varname>max_inv_lifetime</varname> will help is when DNS failover is 
+		used (each failed DNS destination can introduce a new branch).
 	</para>
 	<para>
 		The default value is 180000 ms (180 seconds - the rfc3261 
@@ -136,7 +136,7 @@ modparam("tm", "max_inv_lifetime", 150000)
 		non-INVITEs.
 	</para>
 	<para>
-		A non-INVITE transaction will be kept in memory for maximum:
+		A non-INVITE transaction will be kept in memory for a maximum of:
 		<varname>max_noninv_lifetime</varname>+<varname>wt_timer</varname>.
 	</para>
 	<para>
@@ -146,11 +146,11 @@ modparam("tm", "max_inv_lifetime", 150000)
 		<varname>max_noninv_lifetime</varname> is per the whole transaction.
 		An example when a transaction can live substantially more then its
 		<varname>fr_timer</varname> and where
-		<varname>max_noninv_lifetime</varname> will help is when dns failover
-		is used (each failed dns destination can introduce a new branch).
+		<varname>max_noninv_lifetime</varname> will help is when DNS failover
+		is used (each failed DNS SRV destination can introduce a new branch).
 	</para>
 	<para>
-		The default value is 32000 ms (32 seconds - the rfc3261 timer F value).
+		The default value is 32000 ms (32 seconds - the RFC3261 timer F value).
 	</para>
 	<para>
 		See also: <varname>max_inv_lifetime</varname>,
@@ -171,13 +171,13 @@ modparam("tm", "max_noninv_lifetime", 30000)
 	</example>
     </section>
 
-    <section id="wt_timer">
+    <section id="tm.p.wt_timer">
 	<title><varname>wt_timer</varname> (integer)</title>
 	<para>
 	    Time for which a transaction stays in memory to absorb delayed
 	    messages after it completed (in milliseconds); also, when this 
 	    timer hits,
-	    retransmission of local cancels is stopped (a puristic but complex
+	    retransmission of local CANCEL requests is stopped (a puristic but complex
 	    behavior would be not to enter wait state until local branches are
 	    finished by a final reply or FR timer--we simplified).
 	</para>
@@ -194,14 +194,14 @@ modparam("tm", "wt_timer", 1000)
 	</example>
     </section>
 
-    <section id="delete_timer">
+    <section id="tm.p.delete_timer">
 	<title><varname>delete_timer</varname> (integer)</title>
 	<para>
 	    Time after which a to-be-deleted transaction currently ref-ed by a
 	    process will be tried to be deleted again (in milliseconds).
 	</para>
 	<para>
-	    Note: this parameter is obsolete for ser 2.1 (in 2.1 the transaction
+	    Note: this parameter is obsolete for SER 2.1 (in 2.1 the transaction
 		 is deleted the moment it's not referenced anymore).
 	</para>
 	<para>
@@ -217,7 +217,7 @@ modparam("tm", "delete_timer", 100)
 	</example>
     </section>
     
-    <section id="retr_timer1">
+    <section id="tm.p.retr_timer1">
 	<title><varname>retr_timer1</varname> (integer)</title>
 	<para>
 	    Initial retransmission period (in milliseconds).
@@ -235,7 +235,7 @@ modparam("tm", "retr_timer1", 1000)
 	</example>
     </section>
 
-    <section id="retr_timer2">
+    <section id="tm.p.retr_timer2">
 	<title><varname>retr_timer2</varname> (integer)</title>
 	<para>
 	    Maximum retransmission period (in milliseconds). The retransmission
@@ -256,7 +256,7 @@ modparam("tm", "retr_timer2", 2000)
 	</example>
     </section>
 
-    <section id="noisy_ctimer">
+    <section id="tm.p.noisy_ctimer">
 	<title><varname>noisy_ctimer</varname> (integer)</title>
 	<para>
 	    If set, INVITE transactions that time-out (FR INV timer) will be 
@@ -265,7 +265,7 @@ modparam("tm", "retr_timer2", 2000)
 		will be silently dropped (no 408 reply will be generated)
 		This behavior is overridden if a request is forked, the transaction
 		 has a failure route or callback, or some functionality explicitly 
-		 turned it on  for a transaction (like acc does to avoid unaccounted
+		 turned it on  for a transaction (like the ACC module does to avoid unaccounted
 		 transactions due to expired timer).
 		Turn this off only if you know the client UACs will timeout and their
 		timeout interval for INVITEs is lower or equal than tm's
@@ -284,7 +284,7 @@ modparam("tm", "noisy_ctimer", 1)
 	</example>
     </section>
 
-	<section id="restart_fr_on_each_reply">
+	<section id="tm.p.restart_fr_on_each_reply">
 	<title><varname>restart_fr_on_each_reply</varname> (integer)</title>
 	<para>
 		If set (default), the <varname>fr_inv_timer</varname> for an INVITE
@@ -318,17 +318,17 @@ modparam("tm", "restart_fr_on_each_reply", 0)
 	</example>
 	</section>
 
-	<section id="auto_inv_100">
+	<section id="tm.p.auto_inv_100">
 	<title><varname>auto_inv_100</varname> (integer)</title>
 	<para>
 		If set (default) tm will automatically send and 100 reply to INVITEs.
 	</para>
 	<para>
-		Setting it to 0 one can be used to enable doing first some tests or
+		Setting it to 0 can be used to enable first running some tests or
 		pre-processing on the INVITE and only if some conditions are met
 		manually send a 100 (using <function>t_reply()</function>). Note 
 		however that in this case all the 100s have to be sent "by hand".
-		<function>t_set_auto_inv_100()</function> might  help to selectively
+		<function>t_set_auto_inv_100()</function> might help to selectively
 		turn off this feature only for some specific transactions.
 	</para>
 	<para>
@@ -348,10 +348,10 @@ modparam("tm", "auto_inv_100", 0)
 	</example>
 	</section>
 
-	<section id="auto_inv_100_reason">
+	<section id="tm.p.auto_inv_100_reason">
 	<title><varname>auto_inv_100_reason</varname> (string)</title>
 	<para>
-		Set reason text of the automatically send 100 to an INVITE.
+		Set reason text of the automatically sent 100 to an INVITE.
 	</para>
 	<para>
 		Default value is "trying -- your call is important to us".
@@ -369,14 +369,14 @@ modparam("tm", "auto_inv_100_reason", "Trying")
 	</example>
 	</section>
 
-	<section id="unix_tx_timeout">
+	<section id="tm.p.unix_tx_timeout">
 	<title><varname>unix_tx_timeout</varname> (integer)</title>
 	<para>
 		Unix socket transmission timeout, in milliseconds.
 	</para>
 	<para>
-		If unix sockets are used (e.g.: to communicate with sems) and sending
-		a message on a unix socket takes longer then 
+		If UNIX sockets are used (e.g.: to communicate with sems) and sending
+		a message on a UNIX socket takes longer than 
 		<varname>unix_tx_timeout</varname>, the send will fail.
 	</para>
 	<para>
@@ -392,20 +392,22 @@ modparam("tm", "unix_tx_timeout", 250)
 	</example>
 	</section>
 
-    <section id="aggregate_challenges">
+        <section id="tm.p.aggregate_challenges">
 	<title><varname>aggregate_challenges</varname> (integer)</title>
 	<para>
-		If set (default), the final reply is a 401 or a 407 and more then
+		If set (default) and the final response is a 401 or a 407 and more than
 		one branch received a 401 or 407, then all the WWW-Authenticate and 
 		Proxy-Authenticate headers from all the 401 and 407 replies will 
-		be aggregated in a new final reply. If only one branch received the
+		be aggregated in a new final response. If only one branch received the
 		 winning 401 or 407 then this reply will be forwarded (no new one
 		 will be built).
-		If 0 only the first 401, or if no 401 was received the first 407,  will
+	</para>
+	<para>
+		If disabled (set to 0) only the first 401, or if no 401 was received the first 407,  will
 		be forwarded (no header aggregation).
 	</para>
 	<para>
-	    Default value is 1 (required by rfc3261).
+	    	Default value is 1 (required by RFC 3261).
 	</para>
 	<example>
 	    <title>Set <varname>aggregate_challenges</varname> parameter</title>
@@ -417,7 +419,7 @@ modparam("tm", "aggregate_challenges", 0)
 	</example>
     </section>
 
-    <section id="reparse_invite">
+    <section id="tm.p.reparse_invite">
 	<title><varname>reparse_invite</varname> (integer)</title>
 	<para>
 		If set (default), the CANCEL and negative ACK requests are
@@ -429,15 +431,15 @@ modparam("tm", "aggregate_challenges", 0)
 		the INVITE re-parsing for example in the following cases:
 	</para>
 	<para>
-		- The INVITE contains a preloaded route-set, and SER forwards
-		the message to the next hop according to the Route header. The
-		Route header is not removed in the CANCEL without
+		- The INVITE contains a preloaded route-set, and &kamailio; forwards
+		the message to the next hop according to the "Route" header. The
+		"Route" header is not removed in the CANCEL without
 		<varname>reparse_invite</varname>=1.
 	</para>
 	<para>
-		- SER record-routes, thus an in-dialog INVITE contains a Route
+		- &kamailio; record-routes, thus an in-dialog INVITE contains a "Route"
 		header which is removed during loose routing. If the in-dialog
-		INVITE is rejected, the negative ACK still contains the Route
+		INVITE is rejected, the negative ACK still contains the "Route"
 		header without <varname>reparse_invite</varname>=1.
 	</para>
 	<para>
@@ -453,7 +455,7 @@ modparam("tm", "reparse_invite", 0)
 	</example>
     </section>
 
-    <section id="ac_extra_hdrs">
+    <section id="tm.p.ac_extra_hdrs">
 	<title><varname>ac_extra_hdrs</varname> (string)</title>
 	<para>
 		Header fields prefixed by this parameter value are included
@@ -462,12 +464,12 @@ modparam("tm", "reparse_invite", 0)
 	</para>
 	<para>
 		Note, that the parameter value effects only those headers
-		which are not covered by RFC-3261 (which are neither mandatory
+		which are not covered by RFC 3261 (which are neither mandatory
 		nor prohibited in CANCEL and ACK), and the parameter can be used
 		only together with <varname>reparse_invite</varname>=1.
 	</para>
 	<para>
-	    Default value is "".
+	    	Default value is "".
 	</para>
 	<example>
 	    <title>Set <varname>ac_extra_hdrs</varname> parameter</title>
@@ -479,12 +481,12 @@ modparam("tm", "ac_extra_hdrs", "myfavoriteheaders-")
 	</example>
     </section>
 
-    <section id="blst_503">
+    <section id="tm.p.blst_503">
 	<title><varname>blst_503</varname> (integer)</title>
 	<para>
-		If set and the blacklist support is enabled, every 503 reply source is
+		If set and the &kamailio; blacklist support is enabled, every 503 reply source is
 		added to the blacklist. The initial blacklist timeout (or ttl) depends
-		on the presence of a Retry-After header in the reply and the values of
+		on the presence of a "Retry-After" header in the reply and the values of
 		the following tm parameters: <varname>blst_503_def_timeout</varname>, 
 		<varname>blst_503_min_timeout</varname> and 
 		<varname>blst_503_max_timeout</varname>.
@@ -506,19 +508,19 @@ modparam("tm", "blst_503", 1)
 	</example>
     </section>
 
-    <section id="blst_503_def_timeout">
+    <section id="tm.p.blst_503_def_timeout">
 	<title><varname>blst_503_def_timeout</varname> (integer)</title>
 	<para>
 		
-		Blacklist interval in seconds for a 503 reply with no Retry-After 
+		Blacklist interval in seconds for a 503 reply with no "Retry-After"
 		header.
 		See also <varname>blst_503</varname>, 
 		<varname>blst_503_min_timeout</varname> and 
 		<varname>blst_503_max_timeout</varname>.
 	</para>
 	<para>
-		The default value is 0, which means that if no Retry-After header is
-		present, the 503 reply source will not be blacklisted (rfc conformant
+		The default value is 0, which means that if no "Retry-After" header is
+		present, the 503 reply source will not be blacklisted (RFC 3261 conformant
 		 behaviour).
 	</para>
 	<example>
@@ -531,13 +533,15 @@ modparam("tm", "blst_503_def_timeout", 120)
 	</example>
     </section>
 
-    <section id="blst_503_min_timeout">
+    <section id="tm.p.blst_503_min_timeout">
 	<title><varname>blst_503_min_timeout</varname> (integer)</title>
 	<para>
 		
 		Minimum blacklist interval in seconds for a 503 reply with a 
-		Retry-After header. It will be used if the Retry-After value is 
-		smaller.
+		"Retry-After" header. It will be used if the "Retry-After" value is 
+		smaller than this value.
+	</para>
+	<para>
 		See also <varname>blst_503</varname>, 
 		<varname>blst_503_def_timeout</varname> and 
 		<varname>blst_503_max_timeout</varname>.
@@ -555,13 +559,15 @@ modparam("tm", "blst_503_min_timeout", 30)
 	</example>
     </section>
 
-    <section id="blst_503_max_timeout">
+    <section id="tm.p.blst_503_max_timeout">
 	<title><varname>blst_503_max_timeout</varname> (integer)</title>
 	<para>
 		
 		Maximum blacklist interval in seconds for a 503 reply with a 
-		Retry-After header. It will be used if the Retry-After value is 
-		greater.
+		"Retry-After header". It will be used if the "Retry-After" value is 
+		greater than this limit.
+	</para>
+	<para>
 		See also <varname>blst_503</varname>, 
 		<varname>blst_503_def_timeout</varname> and 
 		<varname>blst_503_min_timeout</varname>.
@@ -579,7 +585,7 @@ modparam("tm", "blst_503_max_timeout", 604800)
 	</example>
     </section>
 
-    <section id="blst_methods_add">
+    <section id="tm.p.blst_methods_add">
 	<title><varname>blst_methods_add</varname> (unsigned integer)</title>
 	<para>
 		Bitmap of method types that trigger blacklisting on
@@ -594,8 +600,8 @@ modparam("tm", "blst_503_max_timeout", 604800)
 		Check parser/msg_parser.h for farther details.
 	</para>
 	<para>
-		Change the value carefully, because requests not having
-		provisional response (everything but INVITE) can easily
+		Change the value carefully, because requests that doesn't get
+		a provisional response (everything but INVITE) can easily
 		cause the next hop to be inserted into the blacklist
 		by mistake. For exmaple the next hop is a proxy, it is alive,
 		but waiting for the response of the UAS, and has higher
@@ -615,11 +621,11 @@ modparam("tm", "blst_methods_add", 33)
 	</example>
     </section>
 
-    <section id="blst_methods_lookup">
+    <section id="tm.p.blst_methods_lookup">
 	<title><varname>blst_methods_lookup</varname> (unsigned integer)</title>
 	<para>
 		Bitmap of method types that are looked-up in the blacklist
-		before statefull forwarding.
+		before being forwarded statefully.
 		See also <varname>blst_methods_add</varname>
 	</para>
 	<para>
@@ -637,15 +643,15 @@ modparam("tm", "blst_methods_lookup", 1)
 	</example>
     </section>
 
-    <section id="cancel_b_method">
+    <section id="tm.p.cancel_b_method">
 	<title><varname>cancel_b_method</varname> (integer)</title>
 	<para>
 		Method used when attempting to CANCEL an unreplied transaction branch
-		(a branch where no reply greater the 99 was received).
+		(a branch where no response was received).
 		The possible values are 0, 1, and 2.
 	</para>
 	<para>
-		<emphasis>0</emphasis> will immediately stop the request (INVITE) 
+		- <emphasis>0</emphasis> will immediately stop the request (INVITE) 
 		retransmission on the branch and it will behave as if the branch was 
 		immediately replied with a 487 (a fake internal 487 reply). The 
 		advantage is the unreplied branches will be terminated immediately.
@@ -654,11 +660,11 @@ modparam("tm", "blst_methods_lookup", 1)
 		 487. Moreover this risk is greatly amplified by packet loss
 		(e.g. if an 180 is lost the branch will look as unreplied and
 		 a CANCEL will silently drop the branch, but a 2xx can still come at
-		 a later time). This is the behaviour for ser versions older then 2.1.
+		 a later time). This is the behaviour for SER versions older than 2.1.
 	</para>
 	<para>
-		<emphasis>1</emphasis> will keep retransmitting the request on 
-		unreplied branches. If a provisional answer is later received a CANCEL
+		- <emphasis>1</emphasis> will keep retransmitting the request on 
+		unreplied branches. If a provisional answer is received a CANCEL
 		will be immediately sent back (attempting to quickly trigger a 487). 
 		This approach is race free and avoids the 2xx after 487 problem, but
 		 it's more resource intensive: faced with a branch towards and UA that
@@ -666,7 +672,7 @@ modparam("tm", "blst_methods_lookup", 1)
 		 the whole timeout interval (<varname>fr_timer</varname>).
 	</para>
 	<para>
-		<emphasis>2</emphasis> will send and retransmit CANCEL even on 
+		- <emphasis>2</emphasis> will send and retransmit CANCEL even on 
 		unreplied branches, stopping the request retransmissions. This has the
 		same advantages as <emphasis>1</emphasis> and also avoids the extra 
 		roundtrip in the case of the provisional reply, but it's not RFC 3261 
@@ -685,7 +691,7 @@ modparam("tm", "cancel_b_method", 1)
 	</example>
     </section>
 
-    <section id="reparse_on_dns_failover">
+    <section id="tm.p.reparse_on_dns_failover">
 	<title><varname>reparse_on_dns_failover</varname> (integer)</title>
 	<para>
 		If set to 1, the SIP message after a DNS failover is constructed
@@ -707,8 +713,7 @@ modparam("tm", "cancel_b_method", 1)
 		the outgoing socket address is not corrected in any other part of the message.
 		It is dangerous on multihomed hosts: when the new SIP request after
 		the DNS failover is sent via different interface than the first request,
-		the message can contain incorrect ip address in the Record-Route header
-		for instance.
+		the message can contain incorrect IP address in the Record-Route header.
 	</para>
 	<para>
 		Default value is 1.
@@ -723,7 +728,7 @@ modparam("tm", "reparse_on_dns_failover", 0)
 	</example>
     </section>
 
-    <section id="on_sl_reply">
+    <section id="tm.p.on_sl_reply">
 	<title><varname>on_sl_reply</varname> (string)</title>
 	<para>
 		Sets reply route block, to which control is passed when a
@@ -746,11 +751,11 @@ onreply_route["stateless_replies"] {
 	</example>
     </section>
 	
-	<section>
+	<section id ="tm.p.contacts_avp">
 		<title><varname>contacts_avp</varname> (string)</title>
 		<para>
-		This is the name of an XAVP
-                that <function>t_load_contacts()</function> function uses to
+		This is the name of an XAVP that the 
+		<function>t_load_contacts()</function> function uses to
                 store contacts of the destination set and that
                 <function>t_next_contacts()</function> function uses to
                 restore those contacts.
@@ -772,11 +777,11 @@ modparam("tm", "contacts_avp", "tm_contacts")
 		</example>
 	</section>
 	
-	<section>
+	<section id="tm.p.contact_flows_avp">
 		<title><varname>contact_flows_avp</varname> (string)</title>
 		<para>
 		This is the name of an XAVP
-                that <function>t_next_contacts()</function> function uses to
+                that the <function>t_next_contacts()</function> function uses to
                 store contacts (if any) that it skipped, because they
 		contained same +sip.instance value than some other contact,
                 and that <function>t_next_contact_flows()</function>
@@ -798,7 +803,7 @@ modparam("tm", "contact_flows_avp", "tm_contact_flows")
 		</example>
 	</section>
 
-	<section id="fr_timer_avp">
+	<section id="tm.p.fr_timer_avp" >
 		<title><varname>fr_timer_avp</varname> (string)</title>
 		<para>
 			The value of fr_timer timer can be overriden on per-transaction
@@ -809,10 +814,6 @@ modparam("tm", "contact_flows_avp", "tm_contact_flows")
 			value configured in <varname>fr_timer</varname> parameter for the
 			current transaction.
 		</para>
-		<para>
-			The value of this parameter is the the name of the AVP to be
-			checked, without the $ character or "$avp" prefix.
-		</para>
 		<note><para>
 			The value of the AVP is expected to be expressed in 
 			<emphasis>seconds</emphasis> and not milliseconds (unlike the rest
@@ -831,22 +832,23 @@ modparam("tm", "contact_flows_avp", "tm_contact_flows")
 		<para>
 			In Kamailio compatibility mode (defined by #!KAMAILIO), the value
 			of the parameter must be the name of an AVP in pseudo-variable
-			format: $avp(name). In SER compatibility mode it must by just
+			format: $avp(name). In SER compatibility mode it must be just
 			AVP name.
 		</para>
 		<example>
 			<title>Set <varname>fr_timer_avp</varname> parameter</title>
 			<programlisting>
 ...
-modparam("tm", "fr_timer_avp", "i:708")
-# K mode
+# Kamailio mode
 modparam("tm", "fr_timer_avp", "$avp(i:708)")
+# Old SER mode
+modparam("tm", "fr_timer_avp", "i:708")
 ...
 			</programlisting>
 		</example>
 	</section>
 	
-	<section id="fr_inv_timer_avp">
+	<section id="tm.p.fr_inv_timer_avp">
 		<title><varname>fr_inv_timer_avp</varname> (string)</title>
 		<para>
 			The value of fr_inv_timer timer can be overriden on
@@ -858,10 +860,6 @@ modparam("tm", "fr_timer_avp", "$avp(i:708)")
 			configured in <varname>fr_inv_timer</varname> parameter for the
 			current transaction.
 		</para>
-		<para>
-			The value of this parameter is the the name of the AVP to be
-			checked, without the $ character or "$avp" prefix.
-		</para>
 		<note><para>
 			The value of the AVP is expected to be expressed in
 			<emphasis>seconds</emphasis> and not milliseconds (unlike the rest
@@ -887,22 +885,23 @@ modparam("tm", "fr_timer_avp", "$avp(i:708)")
 			<title>Set <varname>fr_inv_timer_avp</varname> parameter</title>
 			<programlisting>
 ...
-modparam("tm", "fr_inv_timer_avp", "my_fr_inv_timer")
-# K mode
+# Kamailio mode
 modparam("tm", "fr_inv_timer_avp", "$avp(my_fr_inv_timer)")
+# Old SER mode
+modparam("tm", "fr_inv_timer_avp", "my_fr_inv_timer")
 ...
 			</programlisting>
 		</example>
 	</section>
 
-	<section id="unmatched_cancel">
+	<section id="tm.p.unmatched_cancel">
 		<title><varname>unmatched_cancel</varname> (string)</title>
 		<para>
 			This parameter selects between forwarding CANCELs
 			that do not match any transaction statefully (0,
 			default value), statelessly (1) or dropping them
-			(2). Note that the statefull forwarding has an
-			additional hidden advantage: tm will be able to
+			(2). Note that the stateful forwarding has an
+			additional hidden advantage: the tm module will be able to
 			recognize INVITEs that arrive after their CANCEL.
 			Note also that this feature could be used to try
 			a memory exhaustion DOS attack against a proxy that
@@ -925,11 +924,11 @@ modparam("tm", "unmatched_cancel", "2")
 		</example>
 	</section>
 
-	<section id="ruri_matching">
+	<section id="tm.p.ruri_matching">
 	<title><varname>ruri_matching</varname> (integer)</title>
 	<para>
-		If set it will also try to match the request uri  when doing
-		pre-3261 transaction matching (the via branch parameter does
+		If set the TM module will try to match the request URI when doing
+		SIP 1.0 (pre-RFC 3261) transaction matching (the "Via" header branch parameter does
 		not contain the 3261 cookie).
 	</para>
 	<para>
@@ -955,11 +954,11 @@ modparam("tm", "ruri_matching", 1)
 	</example>
 	</section>
 
-	<section id="via1_matching">
+	<section id="tm.p.via1_matching">
 	<title><varname>via1_matching</varname> (integer)</title>
 	<para>
-		If set it will also try to match the topmost via when doing
-		pre-3261 transaction matching (the via branch parameter does
+		If set the TM module will try to match the topmost "Via" header when doing
+		SIP 1.0 (pre-RFC 3261) transaction matching (the "Via" header branch parameter does
 		not contain the 3261 cookie).
 	</para>
 	<para>
@@ -985,16 +984,16 @@ modparam("tm", "via1_matching", 1)
 	</example>
 	</section>
 
-	<section id="callid_matching">
+	<section id="tm.p.callid_matching">
 	<title><varname>callid_matching</varname> (integer)</title>
 	<para>
-		If set it will also try to match the callid when doing
+		If set the TM module will try to match the callid when doing
 		transaction matching.
 	</para>
 	<para>
 		Turn on if you don't want replies/requests from broken clients who
 		send a mangled Call-ID to match the transaction. For example when
-		the other side won't recognise the response anyway because of changed
+		the other side won't recognise the response anyway because of a changed
 		Call-ID, this setting will prevent accounting records to be created
 		or failure_route to be skipped.
 	</para>
@@ -1017,7 +1016,7 @@ modparam("tm", "callid_matching", 1)
 	</example>
 	</section>
 
-	<section id="pass_provisional_replies">
+	<section id="tm.p.pass_provisional_replies">
 	<title><varname>pass_provisional_replies</varname> (integer)</title>
 	<para>
 		If set, TMCB_LOCAL_REPONSE_OUT tm registered callbacks will be called
@@ -1043,7 +1042,7 @@ modparam("tm", "pass_provisional_replies", 1)
 	</example>
 	</section>
 
-	<section id="default_code">
+	<section id="tm.p.default_code">
 	<title><varname>default_code</varname> (integer)</title>
 	<para>
 		Default response code sent by <function>t_reply()</function> if it
@@ -1069,7 +1068,7 @@ modparam("tm", "default_code", 501)
 	</example>
 	</section>
 
-	<section id="default_reason">
+	<section id="tm.p.default_reason">
 	<title><varname>default_reason</varname> (string)</title>
 	<para>
 		Default SIP reason phrase sent by <function>t_reply()</function> if it
@@ -1094,15 +1093,15 @@ modparam("tm", "default_reason", "Unknown reason")
 	</example>
 	</section>
 
-	<section id="disable_6xx_block">
+	<section id="tm.p.disable_6xx_block">
 	<title><varname>disable_6xx_block</varname> (integer)</title>
 	<para>
-		If set tm will treat all the 6xx replies like normal replies 
-		(warning: this would be non-rfc conformant behaviour).
+		If set the TM module will treat all the 6xx replies like normal replies 
+		(warning: this would be non-RFC conformant behaviour).
 	</para>
 	<para>
 		If not set (default) receiving a 6xx will cancel all the running
-		parallel branches, will stop dns failover and forking. However
+		parallel branches, will stop DNS failover and forking. However
 		serial forking using <function>append_branch()</function> in the
 		<function>failure_route</function> will still work.
 	</para>
@@ -1132,18 +1131,18 @@ modparam("tm", "disable_6xx_block", 1)
 	</example>
 	</section>
 
-<section id="local_ack_mode">
+	<section id="tm.p.local_ack_mode">
 	<title><varname>local_ack_mode</varname> (integer)</title>
 	<para>
-		It controls where locally generated ACKs for 2xx replies to local
+		This setting controls where locally generated ACKs for 2xx replies to local
 		transactions (transactions created via <function>t_uac*()</function>
-		either thorugh the tm api or via RPC/mi/fifo) are sent.
+		either through the TM api or via RPC/mi/fifo) are sent.
 	</para>
 	<para> It has 3 possible values:</para>
 	<itemizedlist>
 		<listitem><para>
 		<emphasis>0</emphasis> - the ACK destination is choosen according to
-		the rfc: the next hop is found using the contact and the route set and
+		the RFC: the next hop is found using the contact and the route set and
 		then DNS resolution is used on it.
 		</para></listitem>
 		<listitem><para>
@@ -1156,12 +1155,12 @@ modparam("tm", "disable_6xx_block", 1)
 		</para></listitem>
 	</itemizedlist>
 	<note><para>
-	Mode 1 and 2 break the rfc, but are useful to deal with some simple UAs
-	behind the NAT cases (no different routing for the ACK and the contact 
+	Mode 1 and 2 does not follow RFC 3261, but are useful to deal with some simple UAs
+	behind a NAT (no different routing for the ACK and the contact 
 	contains an address behind the NAT).
 	</para></note>
 	<para>
-		The default value is 0 (rfc conformant behaviour).
+		The default value is 0 (RFC conformant behaviour).
 	</para>
 	<para>
 		Can be set at runtime, e.g.:
@@ -1179,10 +1178,10 @@ modparam("tm", "local_ack_mode", 1)
 	</example>
 	</section>
 	
-	<section id="failure_reply_mode">
+	<section id="tm.p.failure_reply_mode">
 	<title><varname>failure_reply_mode</varname> (integer)</title>
 	<para>
-		It controls how branches are managed and replies are selected for
+		This parameter controls how branches are managed and replies are selected for
 		failure_route handling: keep all, drop all, drop last branches in
 		SIP serial forking handling.
 	</para>
@@ -1199,7 +1198,7 @@ modparam("tm", "local_ack_mode", 1)
 		the redirection in failure route, sent to a new destination and this
 		one timeout, you will get again the 3xx). Use t_drop_replies() on per
 		transaction fashion to control the behavior you want. It is the
-		default behaviour comming from SER 2.1.x.
+		default behaviour coming from SER 2.1.x.
 		</para></listitem>
 		<listitem><para>
 		<emphasis>1</emphasis> - all branches are discarded by default. You
@@ -1360,7 +1359,7 @@ modparam("tm", "remap_503_500", 0)
 	<section id="tm.p.failure_exec_mode">
 		<title><varname>failure_exec_mode</varname> (boolean)</title>
 		<para>
-			Add local failed branches in timer to be cosidered for failure
+			Add local failed branches in timer to be considered for failure
 			routing blocks. If disabled, relay functions will return false
 			in case the branch could not be forwarded (default behaviour
 			before v4.1.0).
@@ -1383,17 +1382,17 @@ modparam("tm", "failure_exec_mode", 1)
 		<title><varname>dns_reuse_rcv_socket</varname> (boolean)</title>
 		<para>
 			Control reuse of the receive socket for additional branches added
-			by dns failover. If set to 1, the receive socket is used for
+			by <acronym>DNS</acronym> failover. If set to 1, the receive socket is used for
 			sending out the new branches, unless the socket is forced
 			explicitely in configuration file. If set to 0, selected socket
-			is done depending on value of global parameter mhomed (if mhomed=0,
+			is done depending on value of global parameter "mhomed" (if mhomed=0,
 			then the first listen socket is used, otherwise the socket is
 			selected based on routing rules).
 		</para>
 		<para>
-			Do enable it with caution, it might create troubles on dns results
-			with different transport layer. Better let it disabled and enable
-			mhomed.
+			Do enable it with caution, it might create troubles on DNS results
+			with different transport layer. Better let it be disabled and enable
+			"mhomed".
 		</para>
 		<para>
 			Default value is 0 (disabled).
diff --git a/modules/tm/h_table.c b/modules/tm/h_table.c
index 051c326..e3bc1b4 100644
--- a/modules/tm/h_table.c
+++ b/modules/tm/h_table.c
@@ -1,16 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -19,28 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History
- * -------
- * 2003-03-06  200/INV to-tag list deallocation added;
- *             setting "kill_reason" moved in here -- it is moved
- *             from transaction state to a static var(jiri)
- * 2003-03-16  removed _TOTAG (jiri)
- * 2003-03-30  set_kr for requests only (jiri)
- * 2003-04-04  bug_fix: REQ_IN callback not called for local 
- *             UAC transactions (jiri)
- * 2003-09-12  timer_link->tg will be set only if EXTRA_DEBUG (andrei)
- * 2003-12-04  global callbacks replaceed with callbacks per transaction;
- *             completion callback merged into them as LOCAL_COMPETED (bogdan)
- * 2004-02-11  FIFO/CANCEL + alignments (hash=f(callid,cseq)) (uli+jiri)
- * 2004-02-13  t->is_invite and t->local replaced with flags;
- *             timer_link.payload removed (bogdan)
- * 2004-08-23  avp support added - move and remove avp list to/from
- *             transactions (bogdan)
- * 2006-08-11  dns failover support (andrei)
- * 2007-05-16  callbacks called on destroy (andrei)
- * 2007-06-06  don't allocate extra space for md5 if not used: syn_branch==1 
- *              (andrei)
- * 2007-06-06  switched tm bucket list to a simpler and faster clist (andrei)
  */
 
 /*!
@@ -290,7 +266,7 @@ static void inline init_branches(struct cell *t)
 	unsigned int i;
 	struct ua_client *uac;
 
-	for(i=0;i<MAX_BRANCHES;i++)
+	for(i=0;i<sr_dst_max_branches;i++)
 	{
 		uac=&t->uac[i];
 		uac->request.my_T = t;
@@ -313,21 +289,29 @@ struct cell*  build_cell( struct sip_msg* p_msg )
 #ifdef WITH_XAVP
 	sr_xavp_t** xold;
 #endif
+	unsigned int cell_size;
+
+	/* allocs a new cell, add space for:
+	 * md5 (MD5_LEN - sizeof(struct cell.md5))
+	 * uac (sr_dst_max_banches * sizeof(struct ua_client) ) */
+	cell_size = sizeof( struct cell ) + MD5_LEN - sizeof(((struct cell*)0)->md5)
+				+ (sr_dst_max_branches * sizeof(struct ua_client));
 
-	/* allocs a new cell, add space for md5 (MD5_LEN - sizeof(struct cell.md5)) */
-	new_cell = (struct cell*)shm_malloc( sizeof( struct cell )+
-			MD5_LEN-sizeof(((struct cell*)0)->md5) );
+	new_cell = (struct cell*)shm_malloc( cell_size );
 	if  ( !new_cell ) {
 		ser_error=E_OUT_OF_MEM;
 		return NULL;
 	}
 
 	/* filling with 0 */
-	memset( new_cell, 0, sizeof( struct cell ) );
+	memset( new_cell, 0, cell_size );
 
 	/* UAS */
 	new_cell->uas.response.my_T=new_cell;
 	init_rb_timers(&new_cell->uas.response);
+	/* UAC */
+	new_cell->uac = (struct ua_client*)((char*)new_cell + sizeof(struct cell)
+							+ MD5_LEN - sizeof(((struct cell*)0)->md5));
 	/* timers */
 	init_cell_timers(new_cell);
 
diff --git a/modules/tm/h_table.h b/modules/tm/h_table.h
index a145812..db35212 100644
--- a/modules/tm/h_table.h
+++ b/modules/tm/h_table.h
@@ -1,16 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -19,25 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2003-03-16  removed _TOTAG (jiri)
- * 2003-03-06  we keep a list of 200/INV to-tags now (jiri)
- * 2003-03-01  kr set through a function now (jiri)
- * 2003-12-04  callbacks per transaction added; completion callback
- *             merge into them as LOCAL_COMPETED (bogdan)
- * 2004-02-11  FIFO/CANCEL + alignments (hash=f(callid,cseq)) (uli+jiri)
- * 2004-02-13  t->is_invite, t->local, t->noisy_ctimer replaced
- *             with flags (bogdan)
- * 2004-08-23  avp support added - avp list linked in transaction (bogdan)
- * 2005-11-03  updated to the new timer interface (dropped tm timers) (andrei)
- * 2006-08-11  dns failover support (andrei)
- * 2007-05-29  switch ref_count to atomic and delete a cell automatically on
- *             UNREF if the ref_count reaches 0 (andrei)
- * 2007-06-01  support for different retransmissions intervals per transaction;
- *             added maximum inv. and non-inv. transaction life time (andrei)
- * 2007-06-06  switched tm bucket list to a simpler and faster clist;
- *              inlined often used functions (andrei)
  */
 
 /**  TM :: hash table, flags and other general defines.
@@ -321,6 +300,7 @@ typedef struct async_state {
 
 #define T_DISABLE_INTERNAL_REPLY (1<<13) /* don't send internal negative reply */
 #define T_ADMIN_REPLY (1<<14) /* t reply sent by admin (e.g., from cfg script) */
+#define T_ASYNC_SUSPENDED (1<<15)
 
 /* unsigned short should be enough for a retr. timer: max. 65535 ms =>
  * max retr. = 65 s which should be enough and saves us 2*2 bytes */
@@ -425,7 +405,7 @@ typedef struct cell
 	/* UA Server */
 	struct ua_server  uas;
 	/* UA Clients */
-	struct ua_client  uac[ MAX_BRANCHES ];
+	struct ua_client  *uac;
 	
 	/* store transaction state to be used for async transactions */
 	struct async_state async_backup;
@@ -466,7 +446,7 @@ typedef struct cell
 #endif
 	ticks_t end_of_life; /* maximum lifetime */
 
-	/* nr of replied branch; 0..MAX_BRANCHES=branch value,
+	/* nr of replied branch; 0..sr_dst_max_branches=branch value,
 	 * -1 no reply, -2 local reply */
 	short relayed_reply_branch;
 
diff --git a/modules/tm/lock.c b/modules/tm/lock.c
index cb24985..53c65b0 100644
--- a/modules/tm/lock.c
+++ b/modules/tm/lock.c
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,15 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/*
- * History:
- * --------
- *  2003-03-17  converted to locking.h (andrei)
- *  2004-07-28  s/lock_set_t/gen_lock_set_t/ because of a type conflict
- *              on darwin (andrei)
- *  2006-03-07  removed timer_semaphore, timer_group_lock and related functions
- *              since timers are now handled outside tm (andrei)
- */
 
 
 #include "defs.h"
diff --git a/modules/tm/lock.h b/modules/tm/lock.h
index 41ae7ed..d20965b 100644
--- a/modules/tm/lock.h
+++ b/modules/tm/lock.h
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,15 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/*
- * History:
- * --------
- *  2003-03-17  converted to locking.h (andrei)
- *  2004-07-28  s/lock_set_t/gen_lock_set_t/ because of a type conflict
- *              on darwin (andrei)
- *  2007-03-07  timer locks cleanup: timers are now handled outside tm => no
- *              need for timer locks in tm (andrei)
- */
 
 #include "defs.h"
 
diff --git a/modules/tm/lw_parser.c b/modules/tm/lw_parser.c
index 008e498..a26b63a 100644
--- a/modules/tm/lw_parser.c
+++ b/modules/tm/lw_parser.c
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2007 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/modules/tm/lw_parser.h b/modules/tm/lw_parser.h
index 916a2c9..45dc065 100644
--- a/modules/tm/lw_parser.h
+++ b/modules/tm/lw_parser.h
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2007 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/modules/tm/rpc_uac.c b/modules/tm/rpc_uac.c
index db692ef..d223fd2 100644
--- a/modules/tm/rpc_uac.c
+++ b/modules/tm/rpc_uac.c
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- * 
  * Copyright (C) 2009 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -18,11 +16,6 @@
 /*
  * modules/tm/rpc_uac.c
  */
-/*
- * History:
- * --------
- *  2009-07-20  initial version (andrei)
-*/
 
 #include "rpc_uac.h"
 #include "../../rpc.h"
diff --git a/modules/tm/rpc_uac.h b/modules/tm/rpc_uac.h
index 0aa5c00..06fa312 100644
--- a/modules/tm/rpc_uac.h
+++ b/modules/tm/rpc_uac.h
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- * 
  * Copyright (C) 2009 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -15,14 +13,6 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/*
- * modules/tm/rpc_uac.h
- */
-/*
- * History:
- * --------
- *  2009-07-20  initial version (andrei)
-*/
 
 #ifndef __rpc_uac_h
 #define __rpc_uac_h
diff --git a/modules/tm/select.c b/modules/tm/select.c
index bc784cf..f753e4e 100644
--- a/modules/tm/select.c
+++ b/modules/tm/select.c
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/modules/tm/select.h b/modules/tm/select.h
index d0c28df..0831ffe 100644
--- a/modules/tm/select.h
+++ b/modules/tm/select.h
@@ -1,22 +1,14 @@
 /*
- * $Id$
- *
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/modules/tm/sip_msg.c b/modules/tm/sip_msg.c
index 73c4b44..128d834 100644
--- a/modules/tm/sip_msg.c
+++ b/modules/tm/sip_msg.c
@@ -1,19 +1,14 @@
 /*
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -22,24 +17,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2003-01-23 - msg_cloner clones msg->from->parsed too (janakj)
- *  2003-01-29 - scratchpad removed (jiri)
- *  2003-02-25 - auth_body cloner added (janakj)
- *  2003-02-28  scratchpad compatibility abandoned (jiri)
- *  2003-03-31  removed msg->repl_add_rm (andrei)
- *  2003-04-04  parsed uris are recalculated on cloning (jiri)
- *  2003-05-07  received, rport & i via shortcuts are also translated (andrei)
- *  2003-11-11  updated cloning of lump_rpl (bogdan)
- *  2004-03-31  alias shortcuts are also translated (andrei)
- *  2006-04-20  via->comp is also translated (andrei)
- *  2006-10-16  HDR_{PROXY,WWW}_AUTHENTICATE_T cloned (andrei)
- *  2007-01-26  HDR_DATE_T, HDR_IDENTITY_T, HDR_IDENTITY_INFO_T added (gergo)
- *  2007-09-05  A separate memory block is allocated for the lumps
- *              in case of requests in order to allow cloning them
- *              later than the SIP msg. (Miklos)
- * 2009-07-22  moved most of the functions to core sip_msg_clone.c  (andrei)*/
+ */
 
 /**
  * @file
diff --git a/modules/tm/sip_msg.h b/modules/tm/sip_msg.h
index 1227fe1..4c1f0cb 100644
--- a/modules/tm/sip_msg.h
+++ b/modules/tm/sip_msg.h
@@ -1,19 +1,14 @@
 /*
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/modules/tm/t_append_branches.c b/modules/tm/t_append_branches.c
index 384c301..b276d9e 100644
--- a/modules/tm/t_append_branches.c
+++ b/modules/tm/t_append_branches.c
@@ -23,9 +23,6 @@
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * History:
- * -------
- *  2014-09-09  first release of t_append_branches
  *
  */
 
diff --git a/modules/tm/t_append_branches.h b/modules/tm/t_append_branches.h
index 886eaed..c942080 100644
--- a/modules/tm/t_append_branches.h
+++ b/modules/tm/t_append_branches.h
@@ -23,10 +23,6 @@
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * History:
- * -------
- *  2014-09-09  first release of t_append_branches
- *
  */
 
 #ifndef _T_APPEND_BRANCHES_H
diff --git a/modules/tm/t_cancel.c b/modules/tm/t_cancel.c
index b9b814b..69c5525 100644
--- a/modules/tm/t_cancel.c
+++ b/modules/tm/t_cancel.c
@@ -1,22 +1,14 @@
 /*
- * $Id$
- *
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -25,28 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * ----------
- * 2003-04-14  checking if a reply sent before cancel is initiated
- *             moved here (jiri)
- * 2004-02-11  FIFO/CANCEL + alignments (hash=f(callid,cseq)) (uli+jiri)
- * 2004-02-13  timer_link.payload removed (bogdan)
- * 2006-10-10  cancel_uacs  & cancel_branch take more options now (andrei)
- * 2007-03-15  TMCB_ONSEND hooks added (andrei)
- * 2007-05-28: cancel_branch() constructs the CANCEL from the
- *             outgoing INVITE instead of the incomming one.
- *             (it can be disabled with reparse_invite=0) (Miklos)
- * 2007-06-04  cancel_branch() can operate in lockless mode (with a lockless
- *              should_cancel()) (andrei)
- * 2008-03-07  cancel_branch() takes a new flag: F_CANCEL_B_FORCE_RETR (andrei)
- * 2008-03-08  e2e_cancel handles non replied branches in 3 different ways,
- *              selectable by the tm cancel_b_method parameter: fake reply,
- *              retransmit request and send cancel on branch (andrei)
- * 2009-07-14  renamed which_cancel() to prepare_to_cancel() for better
- *              reflecting its purpose
- *             prepare_to_cancel() takes now an additional skip_branches
- *              bitmap parameter (andrei)
- * 2010-02-26  cancel reason (rfc3326) basic support (andrei)
  */
 
 #include <stdio.h> /* for FILE* in fifo_uac_cancel */
diff --git a/modules/tm/t_cancel.h b/modules/tm/t_cancel.h
index ab04c77..f8fe118 100644
--- a/modules/tm/t_cancel.h
+++ b/modules/tm/t_cancel.h
@@ -1,22 +1,14 @@
 /*
- * $Id$
- *
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -25,17 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * ---------
- *  2004-02-11  FIFO/CANCEL + alignments (hash=f(callid,cseq)) (uli+jiri)
- *  2006-10-10  should_cancel_branch() returns true even for branches with
- *               no response or with response <100 (andrei)
- *  2007-06-04  should_cancel_branch() takes another parameter and it is safe
- *               to be called w/o REPLY_LOCK held (andrei)
- *  2009-07-14  should_cancel_branch() renamed to prepare_cancel_branch() to
- *               better reflect its purpose
- *              which_cancel() renamed to prepare_to_cancel() (andrei)
- * 2010-02-26  cancel reason (rfc3326) basic support (andrei)
  */
 
 
diff --git a/modules/tm/t_fifo.c b/modules/tm/t_fifo.c
index f7d4e97..db7e447 100644
--- a/modules/tm/t_fifo.c
+++ b/modules/tm/t_fifo.c
@@ -1,23 +1,16 @@
 /*
- * $Id$
- *
  * transaction maintenance functions
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -26,10 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * -------
- *  2004-02-23  created by splitting it from t_funcs (bogdan)
- *  2004-11-15  t_write_xxx can print whatever avp/hdr
  */
 
 
diff --git a/modules/tm/t_fifo.h b/modules/tm/t_fifo.h
index e0035e7..515c188 100644
--- a/modules/tm/t_fifo.h
+++ b/modules/tm/t_fifo.h
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,10 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2003-03-31  200 for INVITE/UAS resent even for UDP (jiri) 
- *  2004-11-15  t_write_xxx can print whatever avp/hdr
  */
 
 
diff --git a/modules/tm/t_funcs.c b/modules/tm/t_funcs.c
index f5cf233..cec58e0 100644
--- a/modules/tm/t_funcs.c
+++ b/modules/tm/t_funcs.c
@@ -1,23 +1,16 @@
 /*
- * $Id$
- *
  * transaction maintenance functions
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -26,32 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/*
- * History:
- * -------
- *  2003-03-31  200 for INVITE/UAS resent even for UDP (jiri)
- *               info only if compiling w/ -DEXTRA_DEBUG (andrei)
- *  2003-03-19  replaced all mallocs/frees w/ pkg_malloc/pkg_free (andrei)
- *  2003-03-13  send_pr_buffer is called w/ file/function/line debugging
- *  2003-03-01  start_retr changed to retransmit only for UDP
- *  2003-02-13  modified send_pr_buffer to use msg_send & rb->dst (andrei)
- *  2003-04-14  use protocol from uri (jiri)
- *  2003-04-25  do it (^) really everywhere (jiri)
- *  2003-04-26  do it (^) really really really everywhere (jiri)
- *  2003-07-07  added get_proto calls when proxy!=0 (andrei)
- *  2004-02-13  t->is_invite and t->local replaced with flags (bogdan)
- *  2005-02-16  fr_*_timer acceps full AVP specifications; empty AVP
- *              desable variable timer feature (bogdan)
- *  2005-12-11  t_relay doesn't return 0 (stop script) on send error 
- *              anymore (andrei)
- *  2006-08-11  updated forward_request usage (andrei)
- *              t_relay_to releases the transaction if t_forward_non_ack
- *              fails and t_kill fails or this is a failed replication (andrei)
- *  2007-05-02  t_relay_to() uses now t_forward_cancel for cancels (andrei)
- *  2007-06-05  delay t_relay() replies till script end so that they can be
- *               overwritten by the script user; generate 100 automatically
- *               only if T_NO_100 is not set (andrei)
- */
 
 #include <limits.h>
 #include <string.h>
diff --git a/modules/tm/t_funcs.h b/modules/tm/t_funcs.h
index c7f6bc5..173851b 100644
--- a/modules/tm/t_funcs.h
+++ b/modules/tm/t_funcs.h
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,17 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
- /* History:
-  * --------
-  *  2003-02-18  updated various function prototypes (andrei)
-  *  2003-03-10  removed ifdef _OBSO & made redefined all the *UNREF* macros
-  *               in a non-gcc specific way (andrei)
-  *  2003-03-13  now send_pr_buffer will be called w/ function/line info
-  *               only when compiling w/ -DEXTRA_DEBUG (andrei)
-  *  2003-03-31  200 for INVITE/UAS resent even for UDP (jiri) 
-  *  2005-11-09  added stop_rb_timers, updated to the new timer interface 
-  *               (andrei)
-  */
 
 
 
diff --git a/modules/tm/t_fwd.c b/modules/tm/t_fwd.c
index 734eb16..9cd002f 100644
--- a/modules/tm/t_fwd.c
+++ b/modules/tm/t_fwd.c
@@ -1,22 +1,14 @@
 /*
- * $Id$
- *
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -25,66 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/*
- * History:
- * -------
- *  2003-02-13  proto support added (andrei)
- *  2003-02-24  s/T_NULL/T_NULL_CELL/ to avoid redefinition conflict w/
- *              nameser_compat.h (andrei)
- *  2003-03-01  kr set through a function now (jiri)
- *  2003-03-06  callbacks renamed; "blind UAC" introduced, which makes
- *              transaction behave as if it was forwarded even if it was
- *              not -- good for local UAS, like VM (jiri)
- *  2003-03-19  replaced all the mallocs/frees w/ pkg_malloc/pkg_free (andrei)
- *  2003-03-30  we now watch downstream delivery and if it fails, send an
- *              error message upstream (jiri)
- *  2003-04-14  use protocol from uri (jiri)
- *  2003-12-04  global TM callbacks switched to per transaction callbacks
- *              (bogdan)
- *  2004-02-13: t->is_invite and t->local replaced with flags (bogdan)
- *  2005-08-04  msg->parsed_uri and parsed_uri_ok are no saved & restored
- *               before & after handling the branches (andrei)
- *  2005-12-11  onsend_route support added for forwarding (andrei)
- *  2006-01-27  t_forward_no_ack will return error if a forward on an 
- *              already canceled transaction is attempted (andrei)
- *  2006-02-07  named routes support (andrei)
- *  2006-04-18  add_uac simplified + switched to struct dest_info (andrei)
- *  2006-04-20  pint_uac_request uses now struct dest_info (andrei)
- *  2006-08-11  dns failover support (andrei)
- *              t_forward_non_ack won't start retransmission on send errors
- *               anymore (WARNING: callers should release/kill the transaction
- *               if error is returned) (andrei)
- *  2006-09-15  e2e_cancel uses t_reply_unsafe when called from the 
- *               failure_route and replying to a cancel (andrei)
- *  2006-10-10  e2e_cancel update for the new/modified 
- *               which_cancel()/should_cancel() (andrei)
- *  2006-10-11  don't fork a new branch if the transaction or branch was
- *               canceled, or a 6xx was received
- *              stop retr. timers fix on cancel for non-invites     (andrei)
- *  2006-11-20  new_uri is no longer saved/restore across add_uac calls, since
- *              print_uac_request is now uri safe (andrei)
- *  2007-03-15  TMCB_ONSEND hooks added (andrei)
- *  2007-05-02  added t_forward_cancel(unmatched_cancel) (andrei)
- *  2007-05-24  added TMCB_E2ECANCEL_IN hook support (andrei)
- *  2007-05-28: e2e_cancel_branch() constructs the CANCEL from the
- *              outgoing INVITE instead of applying the lumps to the
- *              incomming one. (it can be disabled with reparse_invite=0) (Miklos)
- *              t_relay_cancel() introduced -- can be used to relay CANCELs
- *              at the beginning of the script. (Miklos)
- * 2007-06-04  running transaction are canceled hop by hop (andrei)
- * 2007-08-37  In case of DNS failover the new SIP message is constructed
- *              from the message buffer of the failed branch instead of
- *              applying the lumps again, because the per-branch lumps are no
- *              t saved, thus, are not available. Set reparse_on_dns_failover
- *              to 0 to revert the change. (Miklos)
- * 2008-06-04  T_CANCELED is now set each time a CANCEL is received (andrei)
- * 2009-06-01  Pre- and post-script callbacks of branch route are 
- *             executed (Miklos)
- * 2009-10-26  support for changing dst_uri in branch routes,
- *             s/print_uac_request/prepare_new_uac/ (andrei)
- * 2009-10-28  support for changing r-uris and path in branch routes; more of
- *             add_uac() functionality moved into prepare_new_uac()  (andrei)
- */
 
 #include "defs.h"
 
@@ -757,7 +689,7 @@ int add_blind_uac( /*struct cell *t*/ )
 	}
 
 	branch=t->nr_of_outgoings;	
-	if (branch==MAX_BRANCHES) {
+	if (branch==sr_dst_max_branches) {
 		LOG(L_ERR, "ERROR: add_blind_uac: "
 			"maximum number of branches exceeded\n");
 		return -1;
@@ -819,7 +751,7 @@ int add_uac( struct cell *t, struct sip_msg *request, str *uri,
 	unsigned short branch;
 
 	branch=t->nr_of_outgoings;
-	if (branch==MAX_BRANCHES) {
+	if (branch==sr_dst_max_branches) {
 		LOG(L_ERR, "ERROR: add_uac: maximum number of branches exceeded\n");
 		ret=ser_error=E_TOO_MANY_BRANCHES;
 		goto error;
@@ -899,7 +831,7 @@ static int add_uac_from_buf( struct cell *t, struct sip_msg *request,
 	unsigned int len;
 
 	branch=t->nr_of_outgoings;
-	if (branch==MAX_BRANCHES) {
+	if (branch==sr_dst_max_branches) {
 		LOG(L_ERR, "ERROR: add_uac_from_buf: maximum number of branches"
 					" exceeded\n");
 		ret=ser_error=E_TOO_MANY_BRANCHES;
@@ -1061,7 +993,7 @@ int add_uac_dns_fallback(struct cell *t, struct sip_msg* msg,
 					return ret;
 				}
 			}
-			if (t->nr_of_outgoings >= MAX_BRANCHES){
+			if (t->nr_of_outgoings >= sr_dst_max_branches){
 				LOG(L_ERR, "ERROR: add_uac_dns_fallback: maximum number of "
 							"branches exceeded\n");
 				if (lock_replies)
diff --git a/modules/tm/t_fwd.h b/modules/tm/t_fwd.h
index 8a6d859..4a133e6 100644
--- a/modules/tm/t_fwd.h
+++ b/modules/tm/t_fwd.h
@@ -1,22 +1,14 @@
 /*
- * $Id$
- *
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -25,13 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/*
- * History:
- * --------
- *  2003-02-18  added proto to various function prototypes (andrei)
- *  2007-05-02  added unmatched_cancel & t_forward_cancel (andrei)
- */
-
 
 #ifndef _T_FWD_H
 #define _T_FWD_H
diff --git a/modules/tm/t_hooks.c b/modules/tm/t_hooks.c
index 500a2f6..334ebc4 100644
--- a/modules/tm/t_hooks.c
+++ b/modules/tm/t_hooks.c
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,21 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/*
- * History:
- * --------
- *  2003-03-19  replaced all the mallocs/frees w/ pkg_malloc/pkg_free (andrei)
- *  2003-12-04  global callbacks moved into transaction callbacks;
- *              multiple events per callback added; single list per
- *              transaction for all its callbacks (bogdan)
- *  2004-08-23  user avp(attribute value pair) added -> making avp list
- *              available in callbacks (bogdan)
- * 2007-03-08  membar_write() used in insert_tmcb(...) (andrei)
- * 2007-03-14  added *_SENT callbacks (andrei)
- * 2007-03-23  added local_req_in callbacks support (andrei)
- * 2007-05-17  insert_tmcb is now safe: it loops arround a mb_atomic_cmpxchg
- *              for a safe lockless list insert (andrei)
- */
 
 #include "defs.h"
 
diff --git a/modules/tm/t_hooks.h b/modules/tm/t_hooks.h
index 0777657..d642d3d 100644
--- a/modules/tm/t_hooks.h
+++ b/modules/tm/t_hooks.h
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,20 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2003-03-16 : backwards-compatibility callback names introduced (jiri)
- * 2003-03-06 : old callbacks renamed, new one introduced (jiri)
- * 2003-12-04 : global callbacks moved into transaction callbacks;
- *              multiple events per callback added; single list per
- *              transaction for all its callbacks (bogdan)
- * 2007-03-14   added *_SENT callbacks (andrei)
- * 2007-03-17   added TMCB_NEG_ACK_IN, TMCB_REQ_RETR_IN & 
- *               TMCB_LOCAL_RESPONSE_IN (andrei)
- * 2007-03-23   added TMCB_LOCAL_REQUEST_IN (andrei)
- * 2007-05-16   added TMCB_DESTROY (andrei)
- * 2007-05-24   fixed has_tran_tmcbs() & added TMCB_E2ECANCEL_IN (andrei)
- * 2007-11-12   added TMCB_E2EACK_RETR_IN (andrei)
  */
 
 
diff --git a/modules/tm/t_lookup.c b/modules/tm/t_lookup.c
index cb3a720..fb197c8 100644
--- a/modules/tm/t_lookup.c
+++ b/modules/tm/t_lookup.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * This C-file takes care of matching requests and replies with
  * existing transactions. Note that we do not do SIP-compliant
  * request matching as asked by SIP spec. We do bitwise matching of 
@@ -21,19 +19,14 @@
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -42,60 +35,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * ----------
- * 2003-01-23  options for disabling r-uri matching introduced (jiri)
- *              nameser_compat.h (andrei)
- * 2003-01-27  next baby-step to removing ZT - PRESERVE_ZT (jiri)
- * 2003-01-28  scratchpad removed (jiri)
- * 2003-02-13  init_rb() is proto indep. & it uses struct dest_info (andrei)
- * 2003-02-24  s/T_NULL/T_NULL_CELL/ to avoid redefinition conflict w/
- * 2003-02-27  3261 ACK/200 consumption bug removed (jiri)
- * 2003-02-28 scratchpad compatibility abandoned (jiri)
- * 2003-03-01  kr set through a function now (jiri)
- * 2003-03-06  dialog matching introduced for ACKs -- that's important for 
- *             INVITE UAS (like INVITE) and 200/ACK proxy matching (jiri)
- * 2003-03-29  optimization: e2e ACK matching only if callback installed
- *             (jiri)
- * 2003-03-30  set_kr for requests only (jiri)
- * 2003-04-04  bug_fix: RESPONSE_IN callback not called for local
- *             UAC transactions (jiri)
- * 2003-04-07  new transactions inherit on_failure and on_relpy from script
- *             variables on instantiation (jiri)
- * 2003-04-30  t_newtran clean up (jiri)
- * 2003-08-21  request lookups fixed to skip UAC transactions, 
- *             thanks Ed (jiri)
- * 2003-12-04  global TM callbacks switched to per transaction callbacks
- *             (bogdan)
- * 2004-02-11  FIFO/CANCEL + alignments (hash=f(callid,cseq)) (uli+jiri)
- * 2004-02-13: t->is_invite and t->local replaced with flags (bogdan)
- * 2004-10-10: use of mhomed disabled for replies (jiri)
- * 2005-02-01: use the incoming request interface for sending the replies
- *             - changes in init_rb() (bogdan)
- * 2005-12-09  added t_set_fr()  (andrei)
- * 2006-01-27  transaction lookup function will set up a cancel flag
- *             if the searched transaction was pre-canceled (andrei)
- * 2006-10-16  401 & 407 replies are completely parsed if tm_aggregate_auth is
- *              set (andrei)
- * 2006-11-10  a valid msg->hash_index is now marked by FL_HASH_INDEX in 
- *              msg_flags
- *             t_lookupOriginalT computes the hash_index by itself  if 
- *               needed (andrei)
- * 2007-03-17  added callbacks for retransmitted request, ack to negative 
- *              replies and replies to local transactions (andrei)
- * 2007-06-01  support for different retransmissions intervals per transaction;
- *             added maximum inv. and non-inv. transaction life time (andrei)
- * 2007-06-05  added delayed error reply support in t_unref;
-*              added support for turning off 100 repl. sending on inv. (andrei)
- * 2007-06-01  support for different retransmissions intervals per transaction;
- *             added maximum inv. and non-inv. transaction life time (andrei)
- * 2007-06-06  switched tm bucket list to a simpler and faster clist;
- * 2008-02-28  try matching e2e acks in t_lookup() only for transactions
- *               which have E2EACK callbacks registered (andrei)
- * 2008-03-31  message flags are updated in shared memory even if they are set
- *             after t_newtran() (Miklos)
- * 2009-06-24  added T_branch and changed set_t() to take also a branch
- *              parameter (andrei)
  */
 
 #include "defs.h"
@@ -936,7 +875,7 @@ int t_reply_matching( struct sip_msg *p_msg , int *p_branch )
 	if (unlikely(reverse_hex2int(hashi, hashl, &hash_index)<0
 		||hash_index>=TABLE_ENTRIES
 		|| reverse_hex2int(branchi, branchl, &branch_id)<0
-		||branch_id>=MAX_BRANCHES
+		|| branch_id>=sr_dst_max_branches
 		|| loopl!=MD5_LEN)
 	) {
 		DBG("DEBUG: t_reply_matching: poor reply labels %d label %d "
diff --git a/modules/tm/t_lookup.h b/modules/tm/t_lookup.h
index 2c15f00..7dd5a1f 100644
--- a/modules/tm/t_lookup.h
+++ b/modules/tm/t_lookup.h
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,15 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/*
- * History:
- * --------
- *  2003-02-24  s/T_NULL/T_NULL_CELL/ to avoid redefinition conflict w/
- *               nameser_compat.h (andrei)
- *  2004-02-11  FIFO/CANCEL + alignments (hash=f(callid,cseq)) (uli+jiri)
- *  2005-12-09  added t_set_fr()  (andrei)
- * 2009-06-24  changed set_t() to take also a branch parameter (andrei)
- */
 
 
 
@@ -106,6 +90,7 @@ typedef int (*tget_ti_f)(struct sip_msg*, unsigned int*, unsigned int*);
 typedef int (*tlookup_ident_f)(struct cell**, unsigned int, unsigned int);
 typedef int (*trelease_f)(struct sip_msg*);
 typedef int (*tlookup_callid_f)(struct cell **, str, str);
+typedef int (*tset_fr_f)(struct sip_msg*, unsigned int, unsigned int);
 
 int t_is_local(struct sip_msg*);
 int t_get_trans_ident(struct sip_msg* p_msg, unsigned int* hash_index, unsigned int* label);
diff --git a/modules/tm/t_msgbuilder.c b/modules/tm/t_msgbuilder.c
index 0102e19..ded1b47 100644
--- a/modules/tm/t_msgbuilder.c
+++ b/modules/tm/t_msgbuilder.c
@@ -1,23 +1,16 @@
 /*
- * $Id$
- *
  * message printing
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -26,27 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- *
- * History:
- * ----------
- * 2003-01-27  next baby-step to removing ZT - PRESERVE_ZT (jiri)
- * 2003-02-13  build_uac_request uses proto (andrei)
- * 2003-02-28  scratchpad compatibility abandoned (jiri)
- * 2003-04-14  build_local no longer checks reply status as it
- *             is now called before reply status is updated to
- *             avoid late ACK sending (jiri)
- * 2003-10-02  added via_builder set host/port support (andrei)
- * 2004-02-11  FIFO/CANCEL + alignments (hash=f(callid,cseq)) (uli+jiri)
- * 2004-02-13: t->is_invite and t->local replaced with flags (bogdan)
- * 2006-04-21  build_uac_req, assemble_via use struct dest_info now;
- *              uri2sock replaced with uri2dst (andrei)
- * 2006-08-11  build_dlg_ack: use the first dns ip for which a send_sock
- *              is found (andrei)
- * 2007-03-15  build_dls_ack: removed next_hop and replaced by dst to avoid
- *               resolving nexthop twice (andrei)
- * 2007-05-28: build_local_reparse() is introdued: it uses the outgoing
- *             INVITE as a source to construct a CANCEL or ACK (Miklos)
- * 2010-02-26  cancel reason (rfc3326) basic support (andrei)
  */
 
 #include "defs.h"
diff --git a/modules/tm/t_msgbuilder.h b/modules/tm/t_msgbuilder.h
index 8245e70..4ede95b 100644
--- a/modules/tm/t_msgbuilder.h
+++ b/modules/tm/t_msgbuilder.h
@@ -1,22 +1,14 @@
 /*
- * $Id$
- *
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -25,9 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2004-02-11  FIFO/CANCEL + alignments (hash=f(callid,cseq)) (uli+jiri)
  */
 
 
diff --git a/modules/tm/t_reply.c b/modules/tm/t_reply.c
index e23325b..d14ed1c 100644
--- a/modules/tm/t_reply.c
+++ b/modules/tm/t_reply.c
@@ -1,22 +1,14 @@
 /*
- * $Id$
- *
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -25,82 +17,9 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2003-01-19  faked lump list created in on_reply handlers
- *  2003-01-27  next baby-step to removing ZT - PRESERVE_ZT (jiri)
- *  2003-02-13  updated to use rb->dst (andrei)
- *  2003-02-18  replaced TOTAG_LEN w/ TOTAG_VALUE_LEN (TOTAG_LEN was defined
- *               twice with different values!)  (andrei)
- *  2003-02-28  scratchpad compatibility abandoned (jiri)
- *  2003-03-01  kr set through a function now (jiri)
- *  2003-03-06  saving of to-tags for ACK/200 matching introduced,
- *              voicemail changes accepted, updated to new callback
- *              names (jiri)
- *  2003-03-10  fixed new to tag bug/typo (if w/o {})  (andrei)
- *  2003-03-16  removed _TOTAG (jiri)
- *  2003-03-31  200 for INVITE/UAS resent even for UDP (jiri)
- *  2003-03-31  removed msg->repl_add_rm (andrei)
- *  2003-04-05  s/reply_route/failure_route, onreply_route introduced (jiri)
- *  2003-04-14  local acks generated before reply processing to avoid
- *              delays in length reply processing (like opening TCP
- *              connection to an unavailable destination) (jiri)
- *  2003-09-11  updates to new build_res_buf_from_sip_req() interface (bogdan)
- *  2003-09-11  t_reply_with_body() reshaped to use reply_lumps +
- *              build_res_buf_from_sip_req() instead of
- *              build_res_buf_with_body_from_sip_req() (bogdan)
- *  2003-11-05  flag context updated from failure/reply handlers back
- *              to transaction context (jiri)
- *  2003-11-11: build_lump_rpl() removed, add_lump_rpl() has flags (bogdan)
- *  2003-12-04  global TM callbacks switched to per transaction callbacks
- *              (bogdan)
- *  2004-02-06: support for user pref. added - destroy_avps (bogdan)
- *  2003-11-05  flag context updated from failure/reply handlers back
- *              to transaction context (jiri)
- *  2003-11-11: build_lump_rpl() removed, add_lump_rpl() has flags (bogdan)
- *  2004-02-13: t->is_invite and t->local replaced with flags (bogdan)
- *  2004-02-18  fifo_t_reply imported from vm module (bogdan)
- *  2004-08-23  avp list is available from failure/on_reply routes (bogdan)
- *  2004-10-01  added a new param.: restart_fr_on_each_reply (andrei)
- *  2005-03-01  force for statefull replies the incoming interface of
- *              the request (bogdan)
- *  2005-09-01  reverted to the old way of checking response.dst.send_sock
- *               in t_retransmit_reply & reply_light (andrei)
- *  2005-11-09  updated to the new timers interface (andrei)
- *  2006-02-07  named routes support (andrei)
- *  2006-09-13  t_pick_branch will skip also over branches with empty reply 
- *              t_should_relay_response will re-pick the branch if failure 
- *               route /handlers added new branches (andrei)
- * 2006-10-05  better final reply selection: t_pick_branch will prefer 6xx,
- *              if no 6xx reply => lowest class/code; if class==4xx =>
- *              prefer 401, 407, 415, 420 and 484   (andrei)
- * 2006-10-12  dns failover when a 503 is received
- *              replace a 503 final relayed reply by a 500 (andrei)
- * 2006-10-16  aggregate all the authorization headers/challenges when
- *               the final response is 401 or 407 (andrei)
- * 2007-03-08  membar_write() used in update_totag_set(...)(andrei)
- * 2007-03-15  build_local_ack: removed next_hop and replaced with dst to 
- *              avoid resolving next_hop twice
- *              added TMCB_ONSEND callbacks support for replies & ACKs (andrei)
- * 2007-05-28: build_ack() constructs the ACK from the
- *             outgoing INVITE instead of the incomming one.
- *             (it can be disabled with reparse_invite=0) (Miklos)
- * 2007-09-03: drop_replies() has been introduced (Miklos)
- * 2008-03-12  use cancel_b_method on 6xx (andrei)
- * 2008-05-30  make sure the wait timer is started after we don't need t
- *             anymore to allow safe calls from fr_timer (andrei)
- * 2009-06-01  Pre- and post-script callbacks of branch route are 
- *             executed (Miklos)
- * 2009-12-10  reply route is executed under lock to protect the avps (andrei)
- * 2010-02-22  _reply() will cleanup any reply lumps that it might have added
- *             (andrei)
- * 2010-02-26  added experimental support for final reply dropping, not
- *             enabled by default (performance hit) (andrei)
- * 2010-02-26  cancel reason (rfc3326) basic support (andrei)
- *
  */
 
- /* Defines:
+ /** Defines:
   *           TM_ONREPLY_FINAL_DROP_OK - allows dropping the final reply
   *            from the tm onreply_routes, but comes with a small performance
   *            hit (extra unlock()/lock() for each final reply when a onreply
diff --git a/modules/tm/t_reply.h b/modules/tm/t_reply.h
index 5a1b341..91b2ac8 100644
--- a/modules/tm/t_reply.h
+++ b/modules/tm/t_reply.h
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/modules/tm/t_serial.c b/modules/tm/t_serial.c
index 63d3bb7..b320759 100644
--- a/modules/tm/t_serial.c
+++ b/modules/tm/t_serial.c
@@ -23,9 +23,6 @@
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * History:
- * -------
- *  2008-10-22: Moved functions from lcr module to tm module (jh)
  */
 
 #include "../../qvalue.h"
diff --git a/modules/tm/t_serial.h b/modules/tm/t_serial.h
index 0794e31..f373441 100644
--- a/modules/tm/t_serial.h
+++ b/modules/tm/t_serial.h
@@ -23,9 +23,6 @@
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * History:
- * -------
- *  2008-10-22: Moved functions from lcr module to tm module (jh)
  */
 
 extern int fr_inv_timer_next;
diff --git a/modules/tm/t_stats.c b/modules/tm/t_stats.c
index 262d8e2..f0c3ba0 100644
--- a/modules/tm/t_stats.c
+++ b/modules/tm/t_stats.c
@@ -1,23 +1,15 @@
 /*
  *
- * $Id$
- *
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -26,11 +18,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/*
- * History:
- * --------
- *  2003-06-27  tm_stats & friends freed on exit only if non-null (andrei)
- */
 
 
 #include "defs.h"
diff --git a/modules/tm/t_stats.h b/modules/tm/t_stats.h
index bbea74c..2cbeeb7 100644
--- a/modules/tm/t_stats.h
+++ b/modules/tm/t_stats.h
@@ -1,23 +1,14 @@
 /*
- *
- * $Id$
- *
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/modules/tm/t_suspend.c b/modules/tm/t_suspend.c
index 45b194a..86fb3be 100644
--- a/modules/tm/t_suspend.c
+++ b/modules/tm/t_suspend.c
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2008 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,11 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2008-11-10	Initial version (Miklos)
- *  2009-06-01  Pre- and post-script callbacks of failure route are executed (Miklos)
- *
  */
 
 #include "../../action.h"
@@ -121,6 +109,7 @@ int t_suspend(struct sip_msg *msg,
 	} else {
 		LM_DBG("this is a suspend on reply - setting msg flag to SUSPEND\n");
 		msg->msg_flags |= FL_RPL_SUSPENDED;
+                t->flags |= T_ASYNC_SUSPENDED;
 		/* this is a reply suspend find which branch */
 
 		if (t_check( msg  , &branch )==-1){
@@ -200,9 +189,9 @@ int t_continue(unsigned int hash_index, unsigned int label,
 	 * form calling t_continue() multiple times simultaneously */
 	LOCK_ASYNC_CONTINUE(t);
 
-	t->flags |= T_ASYNC_CONTINUE;   /* we can now know anywhere in kamailio 
+	t->flags |= T_ASYNC_CONTINUE;   /* we can now know anywhere in kamailio
 					 * that we are executing post a suspend */
-	
+
 	/* which route block type were we in when we were suspended */
 	cb_type =  FAILURE_CB_TYPE;;
 	switch (t->async_backup.backup_route) {
@@ -250,7 +239,12 @@ int t_continue(unsigned int hash_index, unsigned int label,
 			Not a huge problem, fr timer will fire, but CANCEL
 			will not be sent. last_received will be set to 408. */
 
-		reset_kr();
+		/* We should not reset kr here to 0 as it's quite possible before continuing the dev. has correctly set the
+		 * kr by, for example, sending a transactional reply in code - resetting here will cause a dirty log message
+		 * "WARNING: script writer didn't release transaction" to appear in log files. TODO: maybe we need to add 
+		 * a special kr for async?
+		 * reset_kr();
+		 */
 
 		/* fake the request and the environment, like in failure_route */
 		if (!fake_req(&faked_req, t->uas.request, 0 /* extra flags */, uac)) {
diff --git a/modules/tm/t_suspend.h b/modules/tm/t_suspend.h
index ff21b49..df19f22 100644
--- a/modules/tm/t_suspend.h
+++ b/modules/tm/t_suspend.h
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2008 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/modules/tm/test.c b/modules/tm/test.c
index 403b0d0..7f95535 100644
--- a/modules/tm/test.c
+++ b/modules/tm/test.c
@@ -1,22 +1,14 @@
 /* 
- * $Id$
- *
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/modules/tm/timer.c b/modules/tm/timer.c
index 6f1a597..8a7d0d5 100644
--- a/modules/tm/timer.c
+++ b/modules/tm/timer.c
@@ -1,19 +1,14 @@
 /*
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -23,28 +18,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-/*
- * History:
- * --------
- *  2003-06-27  timers are not unlinked if timerlist is 0 (andrei)
- *  2004-02-13  t->is_invite, t->local, t->noisy_ctimer replaced;
- *              timer_link.payload removed (bogdan)
- *  2005-10-03  almost completely rewritten to use the new timers (andrei)
- *  2005-12-12  on final response marked the rb as removed to avoid deleting
- *              it from the timer handle; timer_allow_del()  (andrei)
- *  2006-08-11  final_response_handler dns failover support for timeout-ed
- *              invites (andrei)
- *  2006-09-28  removed the 480 on fr_inv_timeout reply: on timeout always 
- *               return a 408
- *              set the corresponding "faked" failure route sip_msg->msg_flags 
- *               on timeout or if the branch received a reply (andrei)
- *  2007-03-15  TMCB_ONSEND callbacks support (andrei)
- *  2007-05-29  delete on transaction ref_count==0 : removed the delete timer
- *               (andrei)
- * 2007-06-01  support for different retransmissions intervals per transaction;
- *             added maximum inv. and non-inv. transaction life time (andrei)
- */
-
 /**
  * \file
  * \brief TM :: timer support
@@ -491,7 +464,7 @@ inline static void final_response_handler(	struct retr_buf* r_buf,
 #ifdef EXTRA_DEBUG
 	DBG("DEBUG: final_response_handler:stop retr. and send CANCEL (%p)\n", t);
 #endif
-	if ((r_buf->branch < MAX_BRANCHES) && /* r_buf->branch is always >=0 */
+	if ((r_buf->branch < sr_dst_max_branches) && /* r_buf->branch is always >=0 */
 			(t->uac[r_buf->branch].last_received==0) &&
 			(t->uac[r_buf->branch].request.buffer!=NULL) /* not a blind UAC */
 	){
diff --git a/modules/tm/timer.h b/modules/tm/timer.h
index 5973b2e..776368e 100644
--- a/modules/tm/timer.h
+++ b/modules/tm/timer.h
@@ -1,19 +1,14 @@
 /*
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -23,19 +18,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-/*
- * History:
- * --------
- *  2003-09-12  timer_link.tg exists only if EXTRA_DEBUG (andrei)
- *  2004-02-13  timer_link.payload removed (bogdan)
- *  2005-11-03  rewritten to use the new timers (andrei)
- *  2007-06-01  support for different retr. intervals per transaction;
- *              added maximum inv. and non-inv. transaction life time (andrei)
- *  2007-06-09  wait timers and retr. timers (if TM_FAST_RETR_TIMER is defined)
- *               are run in a fast timer context switching to SLOW timer
- *               automatically for FR (andrei)
- */
-
 /**
  * \file
  * \brief TM :: timer support
diff --git a/modules/tm/tm.c b/modules/tm/tm.c
index 80476e0..b82775e 100644
--- a/modules/tm/tm.c
+++ b/modules/tm/tm.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * TM module
  *
  *
@@ -30,14 +28,14 @@
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -46,50 +44,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/*
- * History:
- * --------
- *  2003-02-18  added t_forward_nonack_{udp, tcp}, t_relay_to_{udp,tcp},
- *               t_replicate_{udp, tcp} (andrei)
- *  2003-02-19  added t_rely_{udp, tcp} (andrei)
- *  2003-03-06  voicemail changes accepted (jiri)
- *  2003-03-10  module export interface updated to the new format (andrei)
- *  2003-03-16  flags export parameter added (janakj)
- *  2003-03-19  replaced all mallocs/frees w/ pkg_malloc/pkg_free (andrei)
- *  2003-03-30  set_kr for requests only (jiri)
- *  2003-04-05  s/reply_route/failure_route, onreply_route introduced (jiri)
- *  2003-04-14  use protocol from uri (jiri)
- *  2003-07-07  added t_relay_to_tls, t_replicate_tls, t_forward_nonack_tls
- *              added #ifdef USE_TCP, USE_TLS
- *              removed t_relay_{udp,tcp,tls} (andrei)
- *  2003-09-26  added t_forward_nonack_uri() - same as t_forward_nonack() but
- *              takes no parameters -> forwards to uri (bogdan)
- *  2004-02-11  FIFO/CANCEL + alignments (hash=f(callid,cseq)) (uli+jiri)
- *  2004-02-18  t_reply exported via FIFO - imported from VM (bogdan)
- *  2004-10-01  added a new param.: restart_fr_on_each_reply (andrei)
- *  2005-11-14  new timer support, changed timer related module params (andrei)
- *  2005-12-09  fixup_hostport2proxy uses route_struct to access param #1
- *              when fixing param #2
- *  2005-12-09  added t_set_fr() (andrei)
- *  2006-02-07  named routes support (andrei)
- *  2006-09-28  added t_branch_replied, t_branch_timeout, t_any_replied, 
- *               t_any_timeout, t_is_canceled (andrei)
- *  2006-10-16  added a new param.: aggregate challenges (andrei)
- *  2007-05-28  two new params: reparse_invite, ac_extra_hdrs
- *              added w_t_relay_cancel() (Miklos)
- *  2007-06-05  added t_set_auto_inv_100() and auto_inv_100 (param);
- *               t_set_max_lifetime(), max_{non}inv_lifetime  (andrei)
- *  2008-02-05	module config parameters use the configuration framework (Miklos)
- *  2008-02-29  added t_grep_status(code) (andrei)
- *  2008-05-15  added t_relay(host, port) (similar to forward(host, port)) &
- *               t_relay_to_{udp,tcp,tls}(<no param>) (force protocol, but 
- *               forward to uri)  (andrei)
- *  2008-08-11  sctp support: t_relay_to_sctp, t_replicate_sctp,
- *               t_forward_nonack_sctp (andrei)
- *  2009-03-18  added a new param: auto_inv_100_reason (aheise) 
- *  2010-03-03  added new params: local_cancel_reason and e2e_cancel_reason
- *              (andrei)
- */
 
 /** TM :: Module API (core).
  * @file 
@@ -298,6 +252,7 @@ static int t_any_timeout(struct sip_msg* msg, char*, char*);
 static int t_any_replied(struct sip_msg* msg, char*, char*);
 static int w_t_is_canceled(struct sip_msg* msg, char*, char*);
 static int t_is_expired(struct sip_msg* msg, char*, char*);
+static int w_t_is_retr_async_reply(struct sip_msg* msg, char*, char*);
 static int t_grep_status(struct sip_msg* msg, char*, char*);
 static int w_t_drop_replies(struct sip_msg* msg, char* foo, char* bar);
 static int w_t_save_lumps(struct sip_msg* msg, char* foo, char* bar);
@@ -472,6 +427,8 @@ static cmd_export_t cmds[]={
 			REQUEST_ROUTE|TM_ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE },
 	{"t_is_canceled",     w_t_is_canceled,          0, 0,
 			REQUEST_ROUTE|TM_ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE },
+        {"t_is_retr_async_reply",     w_t_is_retr_async_reply,          0, 0,
+			TM_ONREPLY_ROUTE},                
 	{"t_is_expired",      t_is_expired,             0, 0,
 			REQUEST_ROUTE|TM_ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE },
 	{"t_grep_status",     t_grep_status,            1, fixup_var_int_1, 
@@ -798,9 +755,9 @@ static int mod_init(void)
 
 	/* checking if we have sufficient bitmap capacity for given
 	   maximum number of  branches */
-	if (MAX_BRANCHES+1>31) {
+	if (sr_dst_max_branches+1>31) {
 		LOG(L_CRIT, "Too many max UACs for UAC branch_bm_t bitmap: %d\n",
-			MAX_BRANCHES );
+			sr_dst_max_branches );
 		return -1;
 	}
 
@@ -1950,6 +1907,29 @@ static int w_t_is_canceled(struct sip_msg* msg, char* foo, char* bar)
 	return t_is_canceled(msg);
 }
 
+/* script function, returns: 1 if the transaction is currently suspended, -1 if not */
+int t_is_retr_async_reply(struct sip_msg* msg)
+{
+	struct cell *t;
+	int ret;	
+	
+	if (t_check( msg , 0 )==-1) return -1;
+	t=get_t();
+	if ((t==0) || (t==T_UNDEFINED)){
+		LOG(L_ERR, "ERROR: t_is_retr_async_reply: cannot check a message "
+			"for which no T-state has been established\n");
+		ret=-1;
+	}else{
+        LOG(L_DBG, "TRANSACTION FLAGS IS %d\n", t->flags);
+		ret=(t->flags & T_ASYNC_SUSPENDED)?1:-1;
+	}
+	return ret;
+}
+static int w_t_is_retr_async_reply(struct sip_msg* msg, char* foo, char* bar)
+{
+	return t_is_retr_async_reply(msg);
+}
+
 /* script function, returns: 1 if the transaction lifetime interval has already elapsed, -1 if not */
 int t_is_expired(struct sip_msg* msg, char* foo, char* bar)
 {
diff --git a/modules/tm/tm_load.c b/modules/tm/tm_load.c
index e95d618..5100271 100644
--- a/modules/tm/tm_load.c
+++ b/modules/tm/tm_load.c
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,10 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2003-03-06  voicemail changes accepted (jiri)
- * 2003-04-14  t_relay_to split in udp and tcp (jiri)
  */
 
 #include "defs.h"
@@ -148,6 +137,9 @@ int load_tm( struct tm_binds *tmb)
 	tmb->tm_ctx_get = tm_ctx_get;
 #endif
 	tmb->t_append_branches = t_append_branches;
+	tmb->t_load_contacts = t_load_contacts;
+	tmb->t_next_contacts = t_next_contacts;
+	tmb->set_fr = t_set_fr;
 	return 1;
 }
 
@@ -166,6 +158,7 @@ int load_xtm(tm_xapi_t *xapi)
 	xapi->t_on_reply      = t_on_reply;
 	xapi->t_check_trans   = t_check_trans;
 	xapi->t_is_canceled   = t_is_canceled;
+	xapi->t_on_branch_failure = t_on_branch_failure;
 
 	return 0;
 }
diff --git a/modules/tm/tm_load.h b/modules/tm/tm_load.h
index 06905c2..7d07568 100644
--- a/modules/tm/tm_load.h
+++ b/modules/tm/tm_load.h
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -25,11 +18,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
  *
- * History:
- * --------
- * 2003-03-06  voicemail changes accepted
- * 2009-07-14  renamed which_cancel* to prepare_to_cancel* (andrei)
- *
  */
 
 
@@ -51,6 +39,7 @@
 #include "t_suspend.h"
 #include "t_append_branches.h"
 #include "t_stats.h"
+#include "t_serial.h"
 
 /* export not usable from scripts */
 #define NO_SCRIPT	-1
@@ -135,6 +124,9 @@ struct tm_binds {
 	void* reserved5;
 #endif
 	t_append_branches_f	t_append_branches;
+	cmd_function	t_load_contacts;
+	cmd_function	t_next_contacts;
+	tset_fr_f set_fr;
 };
 
 typedef struct tm_binds tm_api_t;
@@ -182,6 +174,7 @@ int t_is_canceled(struct sip_msg* msg);
 typedef struct tm_xbinds {
 	t_on_route_f t_on_failure;
 	t_on_route_f t_on_branch;
+	t_on_route_f t_on_branch_failure;
 	t_on_route_f t_on_reply;
 	t_no_param_f t_check_trans;
 	t_no_param_f t_is_canceled;
diff --git a/modules/tm/uac.c b/modules/tm/uac.c
index 10e7a59..8c3a485 100644
--- a/modules/tm/uac.c
+++ b/modules/tm/uac.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * simple UAC for things such as SUBSCRIBE or SMS gateway;
  * no authentication and other UAC features -- just send
  * a message, retransmit and await a reply; forking is not
@@ -9,19 +7,14 @@
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -30,34 +23,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2003-01-23  t_uac_dlg now uses get_out_socket (jiri)
- *  2003-01-27  fifo:t_uac_dlg completed (jiri)
- *  2003-01-29  scratchpad removed (jiri)
- *  2003-02-13  t_uac, t _uac_dlg, gethfblock, uri2proxy changed to use 
- *               proto & rb->dst (andrei)
- *  2003-02-27  FIFO/UAC now dumps reply -- good for CTD (jiri)
- *  2003-02-28  scratchpad compatibility abandoned (jiri)
- *  2003-03-01  kr set through a function now (jiri)
- *  2003-03-19  replaced all mallocs/frees w/ pkg_malloc/pkg_free (andrei)
- *  2003-04-02  port_no_str does not contain a leading ':' anymore (andrei)
- *  2003-07-08  appropriate log messages in check_params(...), 
- *               call calculate_hooks if next_hop==NULL in t_uac (dcm) 
- *  2003-10-24  updated to the new socket_info lists (andrei)
- *  2003-12-03  completion filed removed from transaction and uac callbacks
- *              merged in transaction callbacks as LOCAL_COMPLETED (bogdan)
- *  2004-02-11  FIFO/CANCEL + alignments (hash=f(callid,cseq)) (uli+jiri)
- *  2004-02-13  t->is_invite, t->local, t->noisy_ctimer replaced (bogdan)
- *  2004-08-23  avp support in t_uac (bogdan)
- *  2005-12-16  t_uac will set the new_cell timers to the default values,
- *               fixes 0 fr_timer bug (andrei)
- *  2006-08-11  t_uac uses dns failover until it finds a send socket (andrei)
- *  2007-03-15  TMCB_ONSEND callbacks support added (andrei)
- *  2007-03-23  TMCB_LOCAL_REQUEST_IN callbacks support (andrei)
- *  2007-04-23  per dialog callbacks support (andrei)
- *  2007-06-01  support for per transaction different retransmissions intervals
- *              (andrei)
  */
 
 #include <string.h>
diff --git a/modules/tm/uac.h b/modules/tm/uac.h
index 66232c9..0c4ff9b 100644
--- a/modules/tm/uac.h
+++ b/modules/tm/uac.h
@@ -1,22 +1,14 @@
 /*
- * $Id$
- *
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -25,9 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * ----------
- * 2003-02-28 protocolization of t_uac_dlg completed (jiri)
  */
 
 #ifndef _UAC_H
diff --git a/modules/tm/ut.h b/modules/tm/ut.h
index ea98a8f..956b329 100644
--- a/modules/tm/ut.h
+++ b/modules/tm/ut.h
@@ -1,24 +1,17 @@
 /*
- * $Id$
- *
  * utilities
  *
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -27,17 +20,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * -------
- *  2003-02-13  added proto to uri2proxy (andrei)
- *  2003-04-09  uri2sock moved from uac.c (janakj)
- *  2003-04-14  added get_proto to determine protocol from uri unless
- *              specified explicitly (jiri)
- *  2003-07-07  get_proto takes now two protos as arguments (andrei)
- *              tls/sips support for get_proto & uri2proxy (andrei)
- *  2006-04-13  added uri2dst(), simplified uri2sock() (andrei)
- *  2006-08-11  dns failover support: uri2dst uses the dns cache and tries to 
- *               get the first ip for which there is a send sock. (andrei)
  */
 
 
diff --git a/modules/tmrec/Makefile b/modules/tmrec/Makefile
index 8e0ffe1..9f04f41 100644
--- a/modules/tmrec/Makefile
+++ b/modules/tmrec/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
diff --git a/modules/tmrec/doc/tmrec_admin.xml b/modules/tmrec/doc/tmrec_admin.xml
index 7a429eb..c70bdb2 100644
--- a/modules/tmrec/doc/tmrec_admin.xml
+++ b/modules/tmrec/doc/tmrec_admin.xml
@@ -80,7 +80,7 @@ modparam("tmrec", "separator", ";")
 
 	<section>
 	<title>Functions</title>
-	<section>
+	<section id="tmrec.f.tmrec_match">
 	    <title>
 		<function moreinfo="none">tmrec_match(timerec [, timestamp])</function>
 	    </title>
@@ -284,7 +284,7 @@ modparam("tmrec", "separator", ";")
 	    </example>
 	</section>
 
-	<section>
+	<section id="tmrec.f.is_leap_year">
 	    <title>
 		<function moreinfo="none">is_leap_year([year])</function>
 	    </title>
@@ -308,7 +308,7 @@ if(is_leap_year("2010"))
 	    </example>
 	</section>
 
-	<section>
+	<section id="tmrec.f.time_period_match">
 	    <title>
 		<function moreinfo="none">time_period_match(period [, timestamp])</function>
 	    </title>
diff --git a/modules/tmrec/tmrec_mod.c b/modules/tmrec/tmrec_mod.c
index e0ae5cd..2d856f1 100644
--- a/modules/tmrec/tmrec_mod.c
+++ b/modules/tmrec/tmrec_mod.c
@@ -1,6 +1,4 @@
-/**
- * $Id$
- *
+/*
  * Copyright (C) 2012 Daniel-Constantin Mierla (asipto.com)
  *
  * This file is part of Kamailio, a free SIP server.
@@ -21,6 +19,14 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
  */
+/*! \file
+ * \brief The TMREC module
+ * \ingroup tmrec
+ */
+
+/*! \defgroup tmrec TMREC
+ * This module provides time recurrence matching functions.
+ */
 
 #include <stdio.h>
 #include <unistd.h>
diff --git a/modules/tmx/Makefile b/modules/tmx/Makefile
index 6e27638..f71eb75 100644
--- a/modules/tmx/Makefile
+++ b/modules/tmx/Makefile
@@ -1,6 +1,5 @@
-# $Id$
 #
-# example module makefile
+# tmx module makefile
 #
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
diff --git a/modules/tmx/README b/modules/tmx/README
index bb3254e..1ad67a4 100644
--- a/modules/tmx/README
+++ b/modules/tmx/README
@@ -412,6 +412,8 @@ event_route [tm:branch-failure:contact] {
      * $T_rpl(pv)
      * $T_reply_ruid
      * $T_branch(name)
+     * $T_inv(pv)
+     * $T(name)
 
    Exported pseudo-variables are documented at
    http://www.kamailio.org/wiki/.
diff --git a/modules/tmx/doc/tmx_admin.xml b/modules/tmx/doc/tmx_admin.xml
index 9958185..65de597 100644
--- a/modules/tmx/doc/tmx_admin.xml
+++ b/modules/tmx/doc/tmx_admin.xml
@@ -172,7 +172,7 @@ if (t_cancel_callid("123qaz", "5", "22", "200")) {
 			</function>
 		</title>
 		<para>
-		Send reply to first INVITE transaction identified by callid and cseq.
+		Send reply to first transaction identified by callid and cseq.
 		</para>
 		<para>
 		Parameters:.
@@ -455,6 +455,12 @@ event_route [tm:branch-failure:contact] {
 			<listitem><para>
 				<emphasis>$T_branch(name)</emphasis>
 			</para></listitem>
+			<listitem><para>
+				<emphasis>$T_inv(pv)</emphasis>
+			</para></listitem>
+			<listitem><para>
+				<emphasis>$T(name)</emphasis>
+			</para></listitem>
 		</itemizedlist>
 		<para>
 		Exported pseudo-variables are documented at &kamwikilink;.
diff --git a/modules/tmx/t_mi.c b/modules/tmx/t_mi.c
index e3bff25..485b160 100644
--- a/modules/tmx/t_mi.c
+++ b/modules/tmx/t_mi.c
@@ -1,6 +1,4 @@
 /*
- * $Id: mi.c 5299 2008-12-04 18:12:33Z henningw $
- *
  * Header file for TM MI functions
  *
  * Copyright (C) 2001-2003 FhG Fokus
@@ -22,13 +20,10 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2006-12-04  created (bogdan)
  */
 
 /*! \file
- * \brief TM :: MI functions
+ * \brief TMX :: MI functions
  *
  * \ingroup tm
  * - Module: \ref tm
diff --git a/modules/tmx/t_mi.h b/modules/tmx/t_mi.h
index 42a22df..58287da 100644
--- a/modules/tmx/t_mi.h
+++ b/modules/tmx/t_mi.h
@@ -19,13 +19,10 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2006-12-04  created (bogdan)
  */
 
 /*! \file
- * \brief TM :: MI functions
+ * \brief TMX :: MI functions
  *
  * \ingroup tm
  * - Module: \ref tm
diff --git a/modules/tmx/t_var.c b/modules/tmx/t_var.c
index 55919c5..0338233 100644
--- a/modules/tmx/t_var.c
+++ b/modules/tmx/t_var.c
@@ -1,5 +1,4 @@
-/**
- * $Id$
+/*
  *
  * Copyright (C) 2008 Elena-Ramona Modroiu (asipto.com)
  *
@@ -19,6 +18,12 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
+/*! \file
+ * \brief TMX :: var functions
+ *
+ * \ingroup tm
+ * - Module: \ref tm
+ */
 
 #include "../../mem/mem.h"
 #include "../../dset.h"
@@ -631,6 +636,11 @@ int pv_parse_t_name(pv_spec_p sp, str *in)
 
 	switch(in->len)
 	{
+		case 3:
+			if(strncmp(in->s, "uri", 3) == 0)
+				sp->pvp.pvn.u.isname.name.n = 6;
+			else goto error;
+			break;
 		case 5:
 			if(strncmp(in->s, "flags", 5) == 0)
 				sp->pvp.pvn.u.isname.name.n = 5;
@@ -711,6 +721,7 @@ int pv_get_t(struct sip_msg *msg,  pv_param_t *param,
 int pv_get_t_branch(struct sip_msg *msg,  pv_param_t *param,
 		pv_value_t *res)
 {
+	tm_ctx_t *tcx = 0;
 	tm_cell_t *t;
 	int branch;
 
@@ -723,7 +734,7 @@ int pv_get_t_branch(struct sip_msg *msg,  pv_param_t *param,
 	}
 
 	switch(param->pvn.u.isname.name.n) {
-		case 5:
+		case 5: /* $T_branch(flags) */
 			switch (get_route_type()) {
 				case FAILURE_ROUTE:
 				case BRANCH_FAILURE_ROUTE:
@@ -731,7 +742,7 @@ int pv_get_t_branch(struct sip_msg *msg,  pv_param_t *param,
 					if ((branch=_tmx_tmb.t_get_picked_branch()) < 0) {
 						LM_CRIT("no picked branch (%d) for a final response"
 								" in MODE_ONFAILURE\n", branch);
-						return -1;
+						return pv_get_null(msg, param, res);
 					}
 					res->ri = t->uac[branch].branch_flags;
 					res->flags = PV_VAL_INT;
@@ -739,8 +750,24 @@ int pv_get_t_branch(struct sip_msg *msg,  pv_param_t *param,
 					break;
 				default:
 					LM_ERR("unsupported route_type %d\n", get_route_type());
-					return -1;
+					return pv_get_null(msg, param, res);
+			}
+			break;
+		case 6: /* $T_branch(uri) */
+			if (get_route_type() != TM_ONREPLY_ROUTE) {
+				LM_ERR("$T_branch(uri) - unsupported route_type %d\n",
+						get_route_type());
+				return pv_get_null(msg, param, res);
+			}
+			tcx = _tmx_tmb.tm_ctx_get();
+			if(tcx == NULL) {
+				return pv_get_null(msg, param, res);
+			}
+			branch = tcx->branch_index;
+			if(branch<0 || branch>=t->nr_of_outgoings) {
+				return pv_get_null(msg, param, res);
 			}
+			return pv_get_strval(msg, param, res, &t->uac[branch].uri);
 	}
 	return 0;
 }
diff --git a/modules/tmx/t_var.h b/modules/tmx/t_var.h
index 07ea9dd..2b454fd 100644
--- a/modules/tmx/t_var.h
+++ b/modules/tmx/t_var.h
@@ -1,6 +1,4 @@
-/**
- * $Id$
- *
+/*
  * Copyright (C) 2008 Elena-Ramona Modroiu (asipto.com)
  *
  * This file is part of kamailio, a free SIP server.
@@ -19,6 +17,12 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
+/*! \file
+ * \brief TMX :: var functions
+ *
+ * \ingroup tm
+ * - Module: \ref tm
+ */
 		       
 #ifndef _T_VAR_H_
 #define _T_VAR_H_
diff --git a/modules/tmx/tmx_mod.c b/modules/tmx/tmx_mod.c
index 3af01f5..28dbcd7 100644
--- a/modules/tmx/tmx_mod.c
+++ b/modules/tmx/tmx_mod.c
@@ -1,11 +1,9 @@
 /**
- * $Id$
- *
  * Copyright (C) 2009
  *
- * This file is part of SIP-Router.org, a free SIP server.
+ * This file is part of Kamailio.org, a free SIP server.
  *
- * SIP-Router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
@@ -19,6 +17,12 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
+/*! \file
+ * \brief TMX :: Module interface
+ *
+ * \ingroup tm
+ * - Module: \ref tm
+ */
 
 #include <stdio.h>
 #include <string.h>
diff --git a/modules/tmx/tmx_mod.h b/modules/tmx/tmx_mod.h
index dfffe63..dd3892f 100644
--- a/modules/tmx/tmx_mod.h
+++ b/modules/tmx/tmx_mod.h
@@ -1,11 +1,9 @@
-/**
- * $Id$
- *
+/*
  * Copyright (C) 2009
  *
- * This file is part of SIP-Router.org, a free SIP server.
+ * This file is part of Kamailio.org, a free SIP server.
  *
- * SIP-Router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
@@ -20,6 +18,13 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
+/*! \file
+ * \brief TMX :: Module interface
+ *
+ * \ingroup tm
+ * - Module: \ref tm
+ */
+
 #ifndef _TMX_MOD_H_
 #define _TMX_MOD_H_
 
diff --git a/modules/tmx/tmx_pretran.c b/modules/tmx/tmx_pretran.c
index 1e0f50f..1691432 100644
--- a/modules/tmx/tmx_pretran.c
+++ b/modules/tmx/tmx_pretran.c
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (C) 2014 Daniel-Constantin Mierla (asipto.com)
  *
  * This file is part of kamailio, a free SIP server.
@@ -17,6 +17,12 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
+/*! \file
+ * \brief TMX :: Pretran
+ *
+ * \ingroup tm
+ * - Module: \ref tm
+ */
 
 #include <stdio.h>
 #include <string.h>
diff --git a/modules/tmx/tmx_pretran.h b/modules/tmx/tmx_pretran.h
index 22cdaff..02e5a2e 100644
--- a/modules/tmx/tmx_pretran.h
+++ b/modules/tmx/tmx_pretran.h
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (C) 2014 Daniel-Constantin Mierla (asipto.com)
  *
  * This file is part of kamailio, a free SIP server.
@@ -17,6 +17,12 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
+/*! \file
+ * \brief TMX :: pretran
+ *
+ * \ingroup tm
+ * - Module: \ref tm
+ */
 		       
 #ifndef _TMX_PRETRANS_H_
 #define _TMX_PRETRANS_H_
diff --git a/modules/topoh/Makefile b/modules/topoh/Makefile
index 2cc4400..f995b5c 100644
--- a/modules/topoh/Makefile
+++ b/modules/topoh/Makefile
@@ -1,6 +1,5 @@
-# $Id$
 #
-# example module makefile
+# topoh module makefile
 #
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
diff --git a/modules/topoh/README b/modules/topoh/README
index 6895a33..8812b7b 100644
--- a/modules/topoh/README
+++ b/modules/topoh/README
@@ -147,6 +147,10 @@ modparam("topoh", "mask_ip", "192.168.0.1")
    encode Call-id in such cases. Well-known extensions such as call
    transfer or conference join will be added to work with encoded Call-id.
 
+   NOTE: if you are using dialog module to terminate calls and this
+   parameter is enabled, you must set the dialog module parameter
+   'lreq_callee_headers' to include the header: 'TH: dlh\r\n'.
+
    Default value is 0 (do not mask).
 
    Example 1.3. Set mask_callid parameter
diff --git a/modules/topoh/doc/topoh_admin.xml b/modules/topoh/doc/topoh_admin.xml
index f932b3e..fd588cd 100644
--- a/modules/topoh/doc/topoh_admin.xml
+++ b/modules/topoh/doc/topoh_admin.xml
@@ -118,6 +118,11 @@ modparam("topoh", "mask_ip", "192.168.0.1")
 			Call-id.
 		</para>
 		<para>
+			NOTE: if you are using dialog module to terminate calls and this
+			parameter is enabled, you must set the dialog module parameter
+			'lreq_callee_headers' to include the header: 'TH: dlh\r\n'.
+		</para>
+		<para>
 		<emphasis>
 			Default value is 0 (do not mask).
 		</emphasis>
diff --git a/modules/topoh/th_mask.c b/modules/topoh/th_mask.c
index f69a400..dfbc168 100644
--- a/modules/topoh/th_mask.c
+++ b/modules/topoh/th_mask.c
@@ -1,9 +1,8 @@
 /**
- * $Id$
  *
  * Copyright (C) 2009 SIP-Router.org
  *
- * This file is part of Extensible SIP Router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -19,7 +18,7 @@
  */
 /*!
  * \file
- * \brief SIP-router topoh :: 
+ * \brief Kamailio topoh :: 
  * \ingroup topoh
  * Module: \ref topoh
  */
diff --git a/modules/topoh/th_mask.h b/modules/topoh/th_mask.h
index 3061dc9..735d8bc 100644
--- a/modules/topoh/th_mask.h
+++ b/modules/topoh/th_mask.h
@@ -1,5 +1,4 @@
 /**
- * $Id$
  *
  * Copyright (C) 2009 SIP-Router.org
  *
diff --git a/modules/topoh/th_msg.c b/modules/topoh/th_msg.c
index 3a68f3f..4fd6070 100644
--- a/modules/topoh/th_msg.c
+++ b/modules/topoh/th_msg.c
@@ -1,9 +1,8 @@
 /**
- * $Id$
  *
  * Copyright (C) 2009 SIP-Router.org
  *
- * This file is part of Extensible SIP Router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -1002,6 +1001,15 @@ int th_del_cookie(sip_msg_t *msg)
 }
 
 
+/**
+ * return the special topoh cookie
+ * - TH header of TH Via parame
+ * - value is 3 chars
+ *   [0] - direction:    d - downstream; u - upstream
+ *   [1] - request type: i - initial; c - in-dialog; l - local in-dialog
+ *   [2] - location:     h - header; v - via param
+ * - if not found, returns 'xxx'
+ */
 char* th_get_cookie(sip_msg_t *msg, int *clen)
 {
 	hdr_field_t *hf;
diff --git a/modules/topoh/th_msg.h b/modules/topoh/th_msg.h
index d74ec65..314e026 100644
--- a/modules/topoh/th_msg.h
+++ b/modules/topoh/th_msg.h
@@ -1,9 +1,8 @@
 /**
- * $Id$
  *
  * Copyright (C) 2009 SIP-Router.org
  *
- * This file is part of Extensible SIP Router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -20,7 +19,7 @@
 
 /*!
  * \file
- * \brief SIP-router topoh ::
+ * \brief Kamailio topoh ::
  * \ingroup topoh
  * Module: \ref topoh
  */
diff --git a/modules/topoh/topoh_mod.c b/modules/topoh/topoh_mod.c
index ff64b6c..d3f347e 100644
--- a/modules/topoh/topoh_mod.c
+++ b/modules/topoh/topoh_mod.c
@@ -1,7 +1,7 @@
-/**
+/*
  * Copyright (C) 2009 SIP-Router.org
  *
- * This file is part of Extensible SIP Router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -18,12 +18,12 @@
 
 /*!
  * \file
- * \brief SIP-router topoh :: Module interface
+ * \brief Kamailio topoh :: Module interface
  * \ingroup topoh
  * Module: \ref topoh
  */
 
-/*! \defgroup topoh SIP-router :: Topology hiding
+/*! \defgroup topoh Kamailio :: Topology hiding
  *
  * This module hides the SIP routing headers that show topology details.
  * It it is not affected by the server being transaction stateless or
@@ -401,13 +401,24 @@ int th_msg_sent(void *data)
 	{
 		direction = (th_cookie_value.s[0]=='u')?1:0; /* upstream/downstram */
 		dialog = (get_to(&msg)->tag_value.len>0)?1:0;
-		local = (th_cookie_value.s[0]!='d'&&th_cookie_value.s[0]!='u')?1:0;
+
+		if(msg.via2==0) {
+			local = 1;
+			if(direction==0 && th_cookie_value.s[1]=='l') {
+				/* downstream local request (e.g., dlg bye) */
+				local = 2;
+			}
+		} else {
+			/* more than one Via, but no received th cookie */
+			local = (th_cookie_value.s[0]!='d' && th_cookie_value.s[0]!='u')?1:0;
+		}
 		/* local generated requests */
 		if(local)
 		{
 			/* ACK and CANCEL go downstream */
 			if(get_cseq(&msg)->method_id==METHOD_ACK
-					|| get_cseq(&msg)->method_id==METHOD_CANCEL)
+					|| get_cseq(&msg)->method_id==METHOD_CANCEL
+					|| local==2)
 			{
 				th_mask_callid(&msg);
 				goto ready;
diff --git a/modules/tsilo/Makefile b/modules/tsilo/Makefile
index 40b04cb..a520fde 100644
--- a/modules/tsilo/Makefile
+++ b/modules/tsilo/Makefile
@@ -1,6 +1,5 @@
-# $Id$
 #
-# example module makefile
+# tsilo module makefile
 #
 #
 # WARNING: do not run this directly, it should be run by the master Makefile
@@ -9,7 +8,7 @@ include ../../Makefile.defs
 auto_gen=
 NAME=tsilo.so
 LIBS=
-DEFS+= -DSER_MOD_INTERFACE
+DEFS+=-DKAMAILIO_MOD_INTERFACE
 
 ifeq ($(INSTALL_FLAVOUR),kamailio)
 DEFS+= -DWITH_EVENT_LOCAL_REQUEST
diff --git a/modules/tsilo/README b/modules/tsilo/README
index 4790ad1..5baafd8 100644
--- a/modules/tsilo/README
+++ b/modules/tsilo/README
@@ -10,7 +10,7 @@ Federico Cabiddu
 
    <federico.cabiddu at gmail.com>
 
-   Copyright � 2014 Federico Cabiddu
+   Copyright © 2015 Federico Cabiddu
      __________________________________________________________________
 
    Table of Contents
@@ -33,7 +33,10 @@ Federico Cabiddu
               4.2. ts_append(domain, ruri)
               4.3. ts_append_to(tindex, tlabel, domain)
 
-        5. Statistics
+        5. Exported RPC Functions
+
+              5.1. ts.dump
+              5.2. ts.lookup
 
    List of Examples
 
@@ -62,19 +65,28 @@ Chapter 1. Admin Guide
         4.2. ts_append(domain, ruri)
         4.3. ts_append_to(tindex, tlabel, domain)
 
-   5. Statistics
+   5. Exported RPC Functions
+
+        5.1. ts.dump
+        5.2. ts.lookup
 
 1. Overview
 
-   This modules provides transaction storage for the Kamailio SIP Server
-   Platform. It stores in an internal table transactions for an user and
-   add branches to them if new contacts are added.
+   This module provides transaction storage for the Kamailio SIP Server
+   Platform. It stores in an internal table transactions for a Request-URI
+   (R-URI) and add branches to them later if new contacts for the AOR are
+   added.
 
-   For each message, the modules stores "Request-URI" ("R-URI"), URI and
-   the internal transaction index and label.
+   When the ts_store function is called, the module stores the current
+   transaction R-URI URI, index and label. Two functions (ts_append and
+   ts_append_to) provide the ability to add new branches either to a
+   specific transaction or to all of the transactions stored for a given
+   R-URI. If USRLOC's use_domain option is true, the domain part of the
+   R-URI is used to store the transaction, otherwise only the username
+   part is used.
 
-   When the transaction is destroyed (by the TM module, the transaction is
-   removed from the module table.
+   When a transaction is destroyed by the TM module, it is removed from
+   the module's table too.
 
 2. Dependencies
 
@@ -87,6 +99,10 @@ Chapter 1. Admin Guide
      * REGISTRAR--registrar module-- used to lookup for new contacts and
        update the dset for the r-uri.
      * TM--transaction module-- used to send SIP requests.
+     * USRLOC--usrloc module-- according to the value of use_domain
+       option, domain part of the r-uri will be used to store the
+       transaction.
+     * SL
 
 2.2. External libraries or applications
 
@@ -105,7 +121,7 @@ Chapter 1. Admin Guide
    must be a power of two, otherwise it will be rounded down to the
    nearest power of two.
 
-   Default value is "2048".
+   Default value is “2048”.
 
    Example 1.1. Set hash_size parameter
 ...
@@ -152,7 +168,7 @@ if (is_method("INVITE")) {
    Example 1.3. ts_append usage
 ...
 if (is_method("REGISTER")) {
-        ts_append("location", "$tu");
+        ts_append("location", "$tU");
 }
 ...
 
@@ -182,4 +198,25 @@ if (is_method("REGISTER")) {
 }
 ...
 
-5. Statistics
+5. Exported RPC Functions
+
+   5.1. ts.dump
+   5.2. ts.lookup
+
+5.1. ts.dump
+
+   Dumps the content of the TSILO table
+
+   Name: ts.dump
+
+   RPC Command Format:
+                        kamcmd ts.dump
+
+5.2. ts.lookup
+
+   Dumps the transactions stored for the given RURI
+
+   Name: ts.lookup
+
+   RPC Command Format:
+                        kamcmd ts.lookup sip:abcd at example.com
diff --git a/modules/tsilo/doc/tsilo.xml b/modules/tsilo/doc/tsilo.xml
index 4feb719..4a5a00e 100644
--- a/modules/tsilo/doc/tsilo.xml
+++ b/modules/tsilo/doc/tsilo.xml
@@ -25,7 +25,7 @@
 	    </editor>
 	</authorgroup>
 	<copyright>
-	    <year>2014</year>
+	    <year>2015</year>
 	    <holder>Federico Cabiddu</holder>
 	</copyright>
     </bookinfo>
diff --git a/modules/tsilo/doc/tsilo_admin.xml b/modules/tsilo/doc/tsilo_admin.xml
index 4c35e69..7625059 100644
--- a/modules/tsilo/doc/tsilo_admin.xml
+++ b/modules/tsilo/doc/tsilo_admin.xml
@@ -16,18 +16,16 @@
 	<section>
 	<title>Overview</title>
 	<para>
-		This modules provides transaction storage for the &kamailioname;. It
-		stores in an internal table transactions for an user and add branches
-		to them if new contacts are added.
+		This module provides transaction storage for the &kamailioname;. It
+		stores in an internal table transactions for a Request-URI (R-URI) and add branches
+		to them later if new contacts for the AOR are added.
 	</para>
 	<para>
-		For each message, the modules stores <quote>Request-URI</quote>
-		(<quote>R-URI</quote>), &uri; and the internal transaction index
-		and label.
+		When the <emphasis>ts_store</emphasis> function is called, the module stores the current transaction R-URI &uri;, index and label. Two functions (<emphasis>ts_append</emphasis> and <emphasis>ts_append_to</emphasis>) provide the ability to add new branches either to a specific transaction or to all of the transactions stored for a given R-URI. If USRLOC's <emphasis>use_domain</emphasis> option is true, the domain part of the R-URI is used to store the transaction, otherwise only the use [...]
 	</para>
 	<para>
-		When the transaction is destroyed (by the <emphasis>TM</emphasis> module,
-		the transaction is removed from the module table.
+		When a transaction is destroyed by the <emphasis>TM</emphasis> module,
+		it is removed from the module's table too.
 	</para>
 	</section>
 	<section>
@@ -49,6 +47,16 @@
 				send &sip; requests.
 			</para>
 			</listitem>
+			<listitem>
+			<para>
+				<emphasis>USRLOC</emphasis>--usrloc module-- according to the value of <emphasis>use_domain</emphasis> option, domain part of the r-uri will be used to store the transaction.
+			</para>
+			</listitem>
+			<listitem>
+			<para>
+				<emphasis>SL</emphasis>
+			</para>
+			</listitem>
 			</itemizedlist>
 		</para>
 	</section>
@@ -148,7 +156,7 @@ if (is_method("INVITE")) {
 		<programlisting format="linespecific">
 ...
 if (is_method("REGISTER")) {
-	ts_append("location", "$tu");
+	ts_append("location", "$tU");
 }
 ...
 </programlisting>
@@ -201,6 +209,24 @@ if (is_method("REGISTER")) {
 	</section>
 
 	<section>
-	<title>Statistics</title>
+	<title>Exported RPC Functions</title>
+		<section>
+			<title><varname>ts.dump</varname></title>
+			<para>Dumps the content of the TSILO table</para>
+			<para>Name: <emphasis>ts.dump</emphasis></para>
+			<para>RPC Command Format:</para>
+			<programlisting  format="linespecific">
+			kamcmd ts.dump
+			</programlisting>
+		</section>
+		<section>
+			<title><varname>ts.lookup</varname></title>
+			<para>Dumps the transactions stored for the given RURI</para>
+			<para>Name: <emphasis>ts.lookup</emphasis></para>
+			<para>RPC Command Format:</para>
+			<programlisting  format="linespecific">
+			kamcmd ts.lookup sip:abcd at example.com
+			</programlisting>
+		</section>
 	</section>
 </chapter>
diff --git a/modules/tsilo/ts_hash.c b/modules/tsilo/ts_hash.c
index 31e1dcf..cf529ee 100644
--- a/modules/tsilo/ts_hash.c
+++ b/modules/tsilo/ts_hash.c
@@ -162,7 +162,7 @@ void unlock_entry(ts_entry_t *entry) {
 
 void lock_entry_by_ruri(str* ruri)
 {
-        unsigned int sl;
+	unsigned int sl;
 
 	sl = core_hash(ruri, 0, 0) & (t_table->size-1);
 	ts_lock(t_table, &t_table->entries[sl]);
diff --git a/modules/tsilo/ts_hash.h b/modules/tsilo/ts_hash.h
index b895c26..bc7adf1 100644
--- a/modules/tsilo/ts_hash.h
+++ b/modules/tsilo/ts_hash.h
@@ -26,8 +26,8 @@
  * Module: \ref tsilo
  */
 
-#ifndef _DIALOG_TS_HASH_H_
-#define _DIALOG_TS_HASH_H_
+#ifndef _TS_HASH_H_
+#define _TS_HASH_H_
 
 #include "../../locking.h"
 #include "../../lib/kmi/mi.h"
@@ -64,10 +64,10 @@ typedef struct ts_urecord
 /*! entries in the main transaction table */
 typedef struct ts_entry
 {
-	int n;                  	/*!< Number of elements in the collision slot */
+	int n;                  	    /*!< Number of elements in the collision slot */
 	struct ts_urecord    *first;	/*!< urecord list */
-	struct ts_urecord    *last;	/*!< optimisation, end of the urecord list */
-	unsigned int       next_id;	/*!< next id */
+	struct ts_urecord    *last;	    /*!< optimisation, end of the urecord list */
+	unsigned int       next_id;	    /*!< next id */
 	unsigned int       lock_idx;	/*!< lock index */
 } ts_entry_t;
 
@@ -75,13 +75,13 @@ typedef struct ts_entry
 /*! main transaction table */
 typedef struct ts_table
 {
-	unsigned int       size;	/*!< size of the dialog table */
+	unsigned int       size;	    /*!< size of the tsilo table */
 	struct ts_entry    *entries;	/*!< urecord hash table */
 	unsigned int       locks_no;	/*!< number of locks */
-	gen_lock_set_t     *locks;	/*!< lock table */
+	gen_lock_set_t     *locks;	    /*!< lock table */
 } ts_table_t;
 
-/*! global dialog table */
+/*! global transactions table */
 extern ts_table_t *t_table;
 
 /*!
diff --git a/modules/tsilo/ts_rpc.c b/modules/tsilo/ts_rpc.c
new file mode 100644
index 0000000..20783f4
--- /dev/null
+++ b/modules/tsilo/ts_rpc.c
@@ -0,0 +1,219 @@
+/**
+ * Copyright (C) 2014 Federico Cabiddu (federico.cabiddu at gmail.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+
+#include <string.h>
+#include <stdio.h>
+#include "ts_hash.h"
+#include "ts_rpc.h"
+
+
+static const char* rpc_tsilo_dump_doc[2] = {
+	"Dump tsilo transactions table",
+	0
+};
+
+
+static const char* rpc_tsilo_lookup_doc[2] = {
+	"Lookup one R-URI in the tsilo transactions table",
+	0
+};
+
+/************************ helper functions ****************************/
+
+/*!
+ * \brief Add a node for a transaction
+ */
+static inline int rpc_dump_transaction(rpc_t* rpc, void* ctx, void *ih, ts_transaction_t* t)
+{
+	void* vh;
+
+	if(rpc->struct_add(ih, "{", "Transaction", &vh)<0)
+	{
+		rpc->fault(ctx, 500, "Internal error creating transaction struct");
+		return -1;
+	}
+	if(rpc->struct_add(vh, "d", "Tindex", t->tindex)<0) {
+		rpc->fault(ctx, 500, "Internal error adding tindex");
+		return -1;
+	}
+
+	if(rpc->struct_add(vh, "d", "Tlabel", t->tlabel)<0) {
+		rpc->fault(ctx, 500, "Internal error adding tlabel");
+		return -1;
+	}
+	return 0;
+}
+
+
+/*************************** RPC functions *****************************/
+
+
+/*!
+ * \brief Dump the content of the tsilo table
+ * \param rpc RPC node that should be filled
+ * \param c RPC void pointer
+ */
+static void rpc_tsilo_dump(rpc_t *rpc, void *c)
+{
+	ts_transaction_t* trans;
+	struct ts_urecord* record;
+	struct ts_entry* entry;
+
+	str brief = {0, 0};
+
+	int max, res, n, ntrans, i;
+	int short_dump = 0;
+
+	void* th;
+	void* ah;
+	void* ih;
+	void* sh;
+
+	rpc->scan(c, "*S", &brief);
+
+	if(brief.len==5 && (strncmp(brief.s, "brief", 5)==0))
+		/* short version */
+		short_dump = 1;
+
+	if (rpc->add(c, "{", &th) < 0)
+	{
+		rpc->fault(c, 500, "Internal error creating top rpc");
+		return;
+	}
+
+	if (short_dump==0) {
+		res = rpc->struct_add(th, "d{",
+			"Size",		t_table->size,
+			"R-URIs",	&ah);
+	} else {
+		res = rpc->struct_add(th, "d",
+			"Size",		t_table->size);
+	}
+	if (res<0)
+	{
+		rpc->fault(c, 500, "Internal error creating inner struct");
+		return;
+	}
+
+	/* add the entries per hash */
+	for(i=0,n=0,max=0,ntrans=0; i<t_table->size; i++) {
+		entry = &t_table->entries[i];
+		lock_entry(entry);
+
+		n += entry->n;
+		if(max<entry->n)
+			max= entry->n;
+		for( record = entry->first ; record ; record=record->next ) {
+			/* add entry */
+			if(short_dump==0)
+			{
+				if(rpc->struct_add(ah, "Sd{",
+					"R-URI", &record->ruri,
+					"Hash", record->rurihash,
+					"Transactions", &ih)<0)
+				{
+					unlock_entry(entry);
+					rpc->fault(c, 500, "Internal error creating ruri struct");
+					return;
+				}
+			}
+			for( trans=record->transactions ; trans ; trans=trans->next) {
+				ntrans += 1;
+				if (short_dump==0) {
+					if (rpc_dump_transaction(rpc, c, ih, trans) == -1) {
+						unlock_entry(entry);
+						return;
+					}
+				}
+			}
+		}
+		unlock_entry(entry);
+	}
+
+	/* extra attributes node */
+	if(rpc->struct_add(th, "{", "Stats",    &sh)<0)	{
+		rpc->fault(c, 500, "Internal error creating stats struct");
+		return;
+	}
+	if(rpc->struct_add(sh, "ddd",
+		"RURIs", n,
+		"Max-Slots", max,
+		"Transactions", ntrans)<0)
+	{
+		rpc->fault(c, 500, "Internal error adding stats");
+		return;
+	}
+}
+/*!
+ * \brief Show the transactions for a given R-URI
+ * \param rpc RPC node that should be filled
+ * \param c RPC void pointer
+ */
+static void rpc_tsilo_lookup(rpc_t *rpc, void *c)
+{
+	ts_transaction_t* trans;
+	struct ts_urecord* record;
+
+	str ruri = {0, 0};
+
+	int res;
+
+	void* th;
+
+	if (rpc->scan(c, "S", &ruri) != 1) {
+		rpc->fault(c, 500, "No RURI to lookup specified");
+		return;
+	}
+
+	lock_entry_by_ruri(&ruri);
+
+	/* look for urecord */
+	res = get_ts_urecord(&ruri, &record);
+	if (res) {
+		unlock_entry_by_ruri(&ruri);
+		rpc->fault(c, 404, "RURI not found in tsilo table");
+		return;
+	}
+
+	if (rpc->add(c, "{", &th) < 0)
+	{
+		unlock_entry_by_ruri(&ruri);
+		rpc->fault(c, 500, "Internal error creating top rpc");
+		return;
+	}
+
+	/* add the transactions */
+	for( trans=record->transactions ; trans ; trans=trans->next) {
+		if (rpc_dump_transaction(rpc, c, th, trans) == -1) {
+			unlock_entry_by_ruri(&ruri);
+			return;
+		}
+	}
+	unlock_entry_by_ruri(&ruri);
+	return;
+}
+
+rpc_export_t rpc_methods[] = {
+	{ "ts.dump",	rpc_tsilo_dump,		rpc_tsilo_dump_doc,		0 },
+	{ "ts.lookup",	rpc_tsilo_lookup,	rpc_tsilo_lookup_doc,	0 },
+    { 0, 0, 0, 0}
+};
+
diff --git a/modules/tsilo/ts_rpc.h b/modules/tsilo/ts_rpc.h
new file mode 100644
index 0000000..f85798f
--- /dev/null
+++ b/modules/tsilo/ts_rpc.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2014 Federico Cabiddu, federico.cabiddu at gmail.com
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+/*!
+ * \file
+ * \brief Functions and definitions related to per user transaction indexing and searching
+ * \ingroup tsilo
+ * Module: \ref tsilo
+ */
+
+#ifndef _TS_RPC_H_
+#define _TS_RPC_H_
+
+#include "../../rpc.h"
+
+extern rpc_export_t rpc_methods[];
+#endif
diff --git a/modules/tsilo/ts_store.c b/modules/tsilo/ts_store.c
index 48d1441..67dc2d6 100644
--- a/modules/tsilo/ts_store.c
+++ b/modules/tsilo/ts_store.c
@@ -37,44 +37,62 @@
 #include "ts_hash.h"
 #include "ts_store.h"
 
+extern int use_domain;
+
 int ts_store(struct sip_msg* msg) {
-	struct cell     *t;
-	str ruri;
+	struct cell		*t;
+	str aor;
+	struct sip_uri ruri;
+
 	ts_urecord_t* r;
 	int res;
 
-	t = _tmb.t_gett();
-	ruri = msg->first_line.u.request.uri;
 
+
+	if (use_domain) {
+		aor = msg->first_line.u.request.uri;
+	}
+	else {
+		if (parse_uri(msg->first_line.u.request.uri.s, msg->first_line.u.request.uri.len, &ruri)!=0)
+		{
+			LM_ERR("bad uri [%.*s]\n",
+					msg->first_line.u.request.uri.len,
+					msg->first_line.u.request.uri.s);
+			return -1;
+		}
+		aor = ruri.user;
+	}
+
+	t = _tmb.t_gett();
 	if (!t || t==T_UNDEFINED) {
-		LM_ERR("no transaction defined for %.*s\n", ruri.len, ruri.s);
+		LM_ERR("no transaction defined for %.*s\n", aor.len, aor.s);
 		return -1;
 	}
-	
-	LM_DBG("storing transaction %u:%u for r-uri: %.*s\n", t->hash_index, t->label, ruri.len, ruri.s);
 
-	lock_entry_by_ruri(&ruri);
+	LM_DBG("storing transaction %u:%u for r-uri: %.*s\n", t->hash_index, t->label, aor.len, aor.s);
+
+	lock_entry_by_ruri(&aor);
 
-	res = get_ts_urecord(&ruri, &r);
+	res = get_ts_urecord(&aor, &r);
 
 	if (res < 0) {
-		LM_ERR("failed to retrieve record for %.*s\n", ruri.len, ruri.s);
-		unlock_entry_by_ruri(&ruri);
+		LM_ERR("failed to retrieve record for %.*s\n", aor.len, aor.s);
+		unlock_entry_by_ruri(&aor);
 		return -1;
 	}
 
 	if (res != 0) { /* entry not found for the ruri */
-		if (insert_ts_urecord(&ruri, &r) < 0) {
+		if (insert_ts_urecord(&aor, &r) < 0) {
 			LM_ERR("failed to insert new record structure\n");
-			unlock_entry_by_ruri(&ruri);
+			unlock_entry_by_ruri(&aor);
 			return -1;
 		}
 	}
 
 	insert_ts_transaction(t, msg, r);
-	unlock_entry_by_ruri(&ruri);
+	unlock_entry_by_ruri(&aor);
 
-	LM_DBG("transaction %u:%u (ruri: %.*s) inserted\n", t->hash_index, t->label, ruri.len, ruri.s);
+	LM_DBG("transaction %u:%u (ruri: %.*s) inserted\n", t->hash_index, t->label, aor.len, aor.s);
 
 	return 1;
 }
diff --git a/modules/tsilo/tsilo.c b/modules/tsilo/tsilo.c
index 90eb292..7dbce56 100644
--- a/modules/tsilo/tsilo.c
+++ b/modules/tsilo/tsilo.c
@@ -1,11 +1,10 @@
 /**
- * $Id$
  *
  * Copyright (C) 2014 Federico Cabiddu (federico.cabiddu at gmail.com)
  *
- * This file is part of SIP-Router.org, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-Router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
@@ -31,12 +30,15 @@
 #include "../../script_cb.h"
 #include "../../modules/tm/tm_load.h"
 #include "../../modules/registrar/api.h"
+#include "../../modules/usrloc/usrloc.h"
 #include "../../dset.h"
+#include "../../rpc_lookup.h"
 
 #include "ts_hash.h"
 #include "ts_handlers.h"
 #include "ts_append.h"
 #include "ts_store.h"
+#include "ts_rpc.h"
 
 MODULE_VERSION
 
@@ -45,6 +47,10 @@ MODULE_VERSION
 struct tm_binds _tmb;
 /** REGISTRAR bind **/
 registrar_api_t _regapi;
+/** USRLOC BIND **/
+usrloc_api_t _ul;
+
+int use_domain = 0;
 
 /** parameters */
 static int hash_size = 2048;
@@ -57,17 +63,15 @@ static int w_ts_append_to(struct sip_msg* msg, char *idx, char *lbl, char *d);
 static int fixup_ts_append_to(void** param, int param_no);
 static int w_ts_append(struct sip_msg* _msg, char *_table, char *_ruri);
 static int fixup_ts_append(void** param, int param_no);
-
 static int w_ts_store(struct sip_msg* msg);
 
-
 static cmd_export_t cmds[]={
 	{"ts_append_to", (cmd_function)w_ts_append_to,  3,
-		fixup_ts_append_to, REQUEST_ROUTE | FAILURE_ROUTE },
+		fixup_ts_append_to, 0, REQUEST_ROUTE | FAILURE_ROUTE },
 	{"ts_append", (cmd_function)w_ts_append,  2,
-		fixup_ts_append, REQUEST_ROUTE | FAILURE_ROUTE },
+		fixup_ts_append, 0, REQUEST_ROUTE | FAILURE_ROUTE },
 	{"ts_store", (cmd_function)w_ts_store,  0,
-		0 , REQUEST_ROUTE | FAILURE_ROUTE },
+		0 , 0, REQUEST_ROUTE | FAILURE_ROUTE },
 	{0,0,0,0,0}
 };
 
@@ -80,13 +84,16 @@ static param_export_t params[]={
 /** module exports */
 struct module_exports exports= {
 	"tsilo",
+    DEFAULT_DLFLAGS,
 	cmds,
-	0, /* RPC methods */
 	params,
+	0, /* exported statistics */
+    0,    /* exported MI functions */
+    0,
+    0,
 	mod_init,   /* module initialization function */
 	0,
 	(destroy_function) destroy,  /* destroy function */
-	0,
 	0
 };
 
@@ -96,7 +103,14 @@ struct module_exports exports= {
 static int mod_init(void)
 {
 	unsigned int n;
+	bind_usrloc_t bind_usrloc;
 
+	/* register the RPC methods */
+	if(rpc_register_array(rpc_methods)!=0)
+    {
+        LM_ERR("failed to register RPC commands\n");
+        return -1;
+    }
 	/* load the TM API */
 	if (load_tm_api(&_tmb)!=0) {
 		LM_ERR("can't load TM API\n");
@@ -108,6 +122,20 @@ static int mod_init(void)
 		LM_ERR("cannot load REGISTRAR API\n");
 		return -1;
 	}
+	/* load UL-Bindings */
+	bind_usrloc = (bind_usrloc_t)find_export("ul_bind_usrloc", 1, 0);
+
+	if (!bind_usrloc) {
+		LM_ERR("could not load the USRLOC API\n");
+		return -1;
+	}
+
+	if (bind_usrloc(&_ul) < 0) {
+		LM_ERR("could not load the USRLOC API\n");
+		return -1;
+	}
+
+	use_domain = _ul.use_domain;
 	/* sanitize hash_size */
     if (hash_size < 1){
         LM_WARN("hash_size is smaller "
diff --git a/modules/tsilo/tsilo.h b/modules/tsilo/tsilo.h
index 58699ae..90c965c 100644
--- a/modules/tsilo/tsilo.h
+++ b/modules/tsilo/tsilo.h
@@ -1,11 +1,9 @@
 /**
- * $Id$
- *
  * Copyright (C) 2014 Federico Cabiddu (federico.cabiddu at gmail.com)
  *
- * This file is part of SIP-Router.org, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-Router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
@@ -25,10 +23,15 @@
 
 #include "../../modules/tm/tm_load.h"
 #include "../../modules/registrar/api.h"
+#include "../../modules/usrloc/usrloc.h"
 
 /** TM bind */
 extern struct tm_binds _tmb;
 /** REGISTRAR bind */
 extern registrar_api_t _regapi;
+/** USRLOC BIND **/
+extern usrloc_api_t _ul;
+
+extern int use_domain;
 
 #endif
diff --git a/modules/uac/Makefile b/modules/uac/Makefile
index 9d28730..2be7006 100644
--- a/modules/uac/Makefile
+++ b/modules/uac/Makefile
@@ -1,6 +1,5 @@
-# $Id$
 #
-# example module makefile
+# uac module makefile
 #
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
diff --git a/modules/uac/README b/modules/uac/README
index 79070c0..ef1a218 100644
--- a/modules/uac/README
+++ b/modules/uac/README
@@ -14,9 +14,9 @@ Ramona-Elena Modroiu
 
    <ramona at rosdev.ro>
 
-   Copyright � 2009-2010 asipto.com
+   Copyright © 2009-2010 asipto.com
 
-   Copyright � 2005 Voice Sistem
+   Copyright © 2005 Voice Sistem
      __________________________________________________________________
 
    Table of Contents
@@ -62,16 +62,21 @@ Ramona-Elena Modroiu
               4.10. uac_reg_request_to(user, mode)
 
         5. Pseudo Variables
-        6. RPC Commands
+        6. Event Routes
 
-              6.1. uac.reg_dump
-              6.2. uac.reg_info
-              6.3. uac.reg_enable
-              6.4. uac.reg_disable
-              6.5. uac.reg_reload
-              6.6. uac.reg_refresh
+              6.1. event_route[uac:reply]
 
-        7. Remote Registration
+        7. Counters
+        8. RPC Commands
+
+              8.1. uac.reg_dump
+              8.2. uac.reg_info
+              8.3. uac.reg_enable
+              8.4. uac.reg_disable
+              8.5. uac.reg_reload
+              8.6. uac.reg_refresh
+
+        9. Remote Registration
 
    List of Examples
 
@@ -101,13 +106,14 @@ Ramona-Elena Modroiu
    1.24. uac_req_send usage
    1.25. uac_reg_lookup usage
    1.26. uac_reg_request_to usage
-   1.27. uac.reg_dump usage
-   1.28. uac.reg_info usage
-   1.29. uac.reg_enable usage
-   1.30. uac.reg_disable usage
-   1.31. uac.reg_reload usage
-   1.32. uac.reg_refresh usage
-   1.33. lookup remote registrations usage
+   1.27. event_route[uac:reply] usage
+   1.28. uac.reg_dump usage
+   1.29. uac.reg_info usage
+   1.30. uac.reg_enable usage
+   1.31. uac.reg_disable usage
+   1.32. uac.reg_reload usage
+   1.33. uac.reg_refresh usage
+   1.34. lookup remote registrations usage
 
 Chapter 1. Admin Guide
 
@@ -152,16 +158,21 @@ Chapter 1. Admin Guide
         4.10. uac_reg_request_to(user, mode)
 
    5. Pseudo Variables
-   6. RPC Commands
+   6. Event Routes
+
+        6.1. event_route[uac:reply]
 
-        6.1. uac.reg_dump
-        6.2. uac.reg_info
-        6.3. uac.reg_enable
-        6.4. uac.reg_disable
-        6.5. uac.reg_reload
-        6.6. uac.reg_refresh
+   7. Counters
+   8. RPC Commands
 
-   7. Remote Registration
+        8.1. uac.reg_dump
+        8.2. uac.reg_info
+        8.3. uac.reg_enable
+        8.4. uac.reg_disable
+        8.5. uac.reg_reload
+        8.6. uac.reg_refresh
+
+   9. Remote Registration
 
 1. Overview
 
@@ -182,7 +193,7 @@ Chapter 1. Admin Guide
      * Authentication does not support qop auth-int, just qop auth;
      * CSeq is not increased during authentication - the response may be
        rejected.
-     * The "uac_replace_*" functions can only be run once on the same SIP
+     * The “uac_replace_*” functions can only be run once on the same SIP
        request. Try to save needed changes in a pseudovariable and apply
        them once.
 
@@ -196,9 +207,9 @@ Chapter 1. Admin Guide
    The following modules must be loaded before this module:
      * TM - Transaction Module
      * RR - Record-Route Module, but only if restore mode for From: URI is
-       set to "auto".
+       set to “auto”.
      * Dialog Module, but only if restore mode for From: URI is set to
-       "auto" and you want uac_replace_from or uac_replace_to to store the
+       “auto” and you want uac_replace_from or uac_replace_to to store the
        values of the URIs as dialog variables.
 
 2.2. External Libraries or Applications
@@ -231,7 +242,7 @@ Chapter 1. Admin Guide
    Name of Record-Route header parameter that will be used to store an
    encoded version of the original FROM URI.
 
-   This parameter is optional, it's default value being "vsf".
+   This parameter is optional, it's default value being “vsf”.
 
    Example 1.1. Set rr_from_store_param parameter
 ...
@@ -243,7 +254,7 @@ modparam("uac","rr_from_store_param","my_param")
    Name of Record-Route header parameter that will be used to store
    (encoded) the original TO URI.
 
-   This parameter is optional, it's default value being "vst".
+   This parameter is optional, it's default value being “vst”.
 
    Example 1.2. Set rr_to_store_param parameter
 ...
@@ -254,16 +265,16 @@ modparam("uac","rr_to_store_param","my_param")
 
    There are 3 modes of restoring the original FROM URI and the original
    TO URI:
-     * "none" - no information about original URI is stored; restoration
+     * “none” - no information about original URI is stored; restoration
        is not possible.
-     * "manual" - all following replies will be restored, but not also the
+     * “manual” - all following replies will be restored, but not also the
        sequential requests - this must be manually updated based on
        original URI.
-     * "auto" - all sequential requests and replies will be automatically
+     * “auto” - all sequential requests and replies will be automatically
        updated based on stored original URI. For this option you have to
-       set "modparam("rr", "append_fromtag", 1)".
+       set “modparam("rr", "append_fromtag", 1)”.
 
-   This parameter is optional, it's default value being "auto".
+   This parameter is optional, it's default value being “auto”.
 
    Example 1.3. Set restore_mode parameter
 ...
@@ -355,9 +366,9 @@ modparam("uac","credential","username:domain:password")
    This can be used if the realm upstream will be using is not known in
    advance.
 
-   If you define it, you also need to define "auth_username_avp"
-   (Section 3.10, "auth_username_avp (string)") and "auth_username_avp"
-   (Section 3.11, "auth_password_avp (string)").
+   If you define it, you also need to define “auth_username_avp”
+   (Section 3.10, “auth_username_avp (string)”) and “auth_username_avp”
+   (Section 3.11, “auth_password_avp (string)”).
 
    Example 1.9. Set auth_realm_avp parameter
 ...
@@ -369,9 +380,9 @@ modparam("uac","auth_realm_avp","$avp(i:10)")
    The definition of an AVP that might contain the username to be used to
    perform authentication.
 
-   If you define it, you also need to define "auth_realm_avp"
-   (Section 3.9, "auth_realm_avp (string)") and "auth_username_avp"
-   (Section 3.11, "auth_password_avp (string)").
+   If you define it, you also need to define “auth_realm_avp”
+   (Section 3.9, “auth_realm_avp (string)”) and “auth_username_avp”
+   (Section 3.11, “auth_password_avp (string)”).
 
    Example 1.10. Set auth_username_avp parameter
 ...
@@ -383,9 +394,9 @@ modparam("uac","auth_username_avp","$avp(i:11)")
    The definition of an AVP that might contain the password to be used to
    perform authentication.
 
-   If you define it, you also need to define "auth_password_avp"
-   (Section 3.11, "auth_password_avp (string)") and "auth_username_avp"
-   (Section 3.11, "auth_password_avp (string)").
+   If you define it, you also need to define “auth_password_avp”
+   (Section 3.11, “auth_password_avp (string)”) and “auth_username_avp”
+   (Section 3.11, “auth_password_avp (string)”).
 
    Example 1.11. Set auth_password_avp parameter
 ...
@@ -432,7 +443,7 @@ modparam("uac", "reg_retry_interval", 300)
 
    DB table name to fetch user profiles for registration.
 
-   This parameter is optional, it's default value being "uacreg".
+   This parameter is optional, it's default value being “uacreg”.
 
    Example 1.15. Set reg_db_table parameter
 ...
@@ -464,7 +475,7 @@ modparam("uac", "reg_contact_addr", "192.168.1.2:5080")
    4.9. uac_reg_lookup(uuid, dst)
    4.10. uac_reg_request_to(user, mode)
 
-4.1. uac_replace_from(display,uri)
+4.1.  uac_replace_from(display,uri)
 
    Replace in FROM header the display name and the URI part.
 
@@ -507,7 +518,7 @@ uac_replace_from("","sip:robin at gotham.org");
 uac_replace_from("","");
 ...
 
-4.2. uac_replace_from(uri)
+4.2.  uac_replace_from(uri)
 
    Replace in FROM header the URI part without altering the display name.
 
@@ -520,7 +531,7 @@ uac_replace_from("","");
 uac_replace_from("sip:batman at gotham.org");
 ...
 
-4.3. uac_restore_from()
+4.3.  uac_restore_from()
 
    This function will check if the FROM URI was modified and will use the
    information stored in header parameter to restore the original FROM URI
@@ -533,7 +544,7 @@ uac_replace_from("sip:batman at gotham.org");
 uac_restore_from();
 ...
 
-4.4. uac_replace_to(display,uri)
+4.4.  uac_replace_to(display,uri)
 
    Replace in TO header the display name and the URI part.
 
@@ -558,7 +569,7 @@ uac_replace_to("","sip:robin at gotham.org");
 uac_replace_to("","");
 ...
 
-4.5. uac_replace_to(uri)
+4.5.  uac_replace_to(uri)
 
    Replace in TO header the URI part without altering the display name.
 
@@ -589,7 +600,7 @@ uac_replace_to("","");
 uac_replace_to("sip:batman at gotham.org");
 ...
 
-4.6. uac_restore_to()
+4.6.  uac_restore_to()
 
    This function will check if the TO URI was modified and will use the
    information stored in header parameter to restore the original TO URI
@@ -602,7 +613,7 @@ uac_replace_to("sip:batman at gotham.org");
 uac_restore_to();
 ...
 
-4.7. uac_auth()
+4.7.  uac_auth()
 
    This function can be called only from failure route and will build the
    authentication response header and insert it into the request without
@@ -615,7 +626,7 @@ uac_restore_to();
 uac_auth();
 ...
 
-4.8. uac_req_send()
+4.8.  uac_req_send()
 
    This function sends a SIP message from the configuration file. The
    message is built out of $uac_req(...) pseudo-variable.
@@ -633,7 +644,7 @@ $uac_req(callid)=$(mb{s.md5});
 uac_req_send();
 ...
 
-4.9. uac_reg_lookup(uuid, dst)
+4.9.  uac_reg_lookup(uuid, dst)
 
    This function sets the PV dst to SIP URI that correspond to uuid in uac
    registations table. uuid and dst must be pseudo-variables.
@@ -649,7 +660,7 @@ if(uac_reg_lookup("$rU", "$ru"))
 }
 ...
 
-4.10. uac_reg_request_to(user, mode)
+4.10.  uac_reg_request_to(user, mode)
 
    This function can be used to send an authenticated request to a remote
    user in the uac registrations table. It sets the request-uri, dst-uri
@@ -689,25 +700,57 @@ failure_route[REMOTE_AUTH] {
    Exported pseudo-variables are documented at
    http://www.kamailio.org/wiki/.
 
-6. RPC Commands
+6. Event Routes
+
+   6.1. event_route[uac:reply]
+
+6.1.  event_route[uac:reply]
+
+   Event route executed for the final reply to the request set with
+   uac_req_send(). The associated $uac_req(evroute) has to be set to 1.
+
+   Example 1.27. event_route[uac:reply] usage
+...
+$uac_req(method)="OPTIONS";
+$uac_req(ruri)="sip:kamailio.org";
+$uac_req(furi)="sip:kamailio.org";
+$uac_req(turi)="sip:kamailio.org";
+$uac_req(callid)=$(mb{s.md5});
+$uac_req(evroute)=1;
+uac_req_send();
+...
+event_route[uac:reply] {
+    xlog("received reply code is: $uac_req(evcode)\n");
+}
+...
+
+7. Counters
+
+     * regtotal: Total number of registrations
+     * regactive: Total number of active registrations (successfully
+       registred with service)
+     * regdisabled: Total number of disabled registrations (no longer
+       active)
+
+8. RPC Commands
 
-   6.1. uac.reg_dump
-   6.2. uac.reg_info
-   6.3. uac.reg_enable
-   6.4. uac.reg_disable
-   6.5. uac.reg_reload
-   6.6. uac.reg_refresh
+   8.1. uac.reg_dump
+   8.2. uac.reg_info
+   8.3. uac.reg_enable
+   8.4. uac.reg_disable
+   8.5. uac.reg_reload
+   8.6. uac.reg_refresh
 
-6.1. uac.reg_dump
+8.1.  uac.reg_dump
 
    Dump the content of remote registration table from memory.
 
-   Example 1.27. uac.reg_dump usage
+   Example 1.28. uac.reg_dump usage
 ...
    kamcmd uac.reg_dump
 ...
 
-6.2. uac.reg_info
+8.2.  uac.reg_info
 
    Return the details of a remote registration record based on a filter.
    The command has two parameter: attribute and value. The attribute can
@@ -715,12 +758,12 @@ failure_route[REMOTE_AUTH] {
    should be matcheg against the value of the attribute in the remote
    registration record.
 
-   Example 1.28. uac.reg_info usage
+   Example 1.29. uac.reg_info usage
 ...
    kamcmd uac.reg_info l_uuid account123
 ...
 
-6.3. uac.reg_enable
+8.3.  uac.reg_enable
 
    Enable a remote registration record based on a filter. The command has
    two parameter: attribute and value. The attribute can be: l_uuid,
@@ -728,12 +771,12 @@ failure_route[REMOTE_AUTH] {
    matcheg against the value of the attribute in the remote registration
    record.
 
-   Example 1.29. uac.reg_enable usage
+   Example 1.30. uac.reg_enable usage
 ...
    kamcmd uac.reg_enable l_uuid account123
 ...
 
-6.4. uac.reg_disable
+8.4.  uac.reg_disable
 
    Disable a remote registration record based on a filter. The command has
    two parameter: attribute and value. The attribute can be: l_uuid,
@@ -741,33 +784,33 @@ failure_route[REMOTE_AUTH] {
    matcheg against the value of the attribute in the remote registration
    record.
 
-   Example 1.30. uac.reg_disable usage
+   Example 1.31. uac.reg_disable usage
 ...
    kamcmd uac.reg_disable l_uuid account123
 ...
 
-6.5. uac.reg_reload
+8.5.  uac.reg_reload
 
    Reload the records from database for remote registrations.
 
-   Example 1.31. uac.reg_reload usage
+   Example 1.32. uac.reg_reload usage
 ...
    kamcmd uac.reg_reload
 ...
 
-6.6. uac.reg_refresh
+8.6.  uac.reg_refresh
 
    Load one record by l_uuid from database for remote registrations. If
    the record exists in memory, its authentication password is updated,
    otherwise a new record is added. The command has a parameter, which is
    the value of l_uuid field.
 
-   Example 1.32. uac.reg_refresh usage
+   Example 1.33. uac.reg_refresh usage
 ...
    kamcmd uac.reg_refresh account123
 ...
 
-7. Remote Registration
+9. Remote Registration
 
    The module can register contact addresses to remote REGISTRAR servers.
    You have to add records to uacreg table. The table stores following
@@ -800,7 +843,7 @@ failure_route[REMOTE_AUTH] {
    if the call is coming from a remote SIP provider and can change the
    R-URI to local username at domain. Afterwards you can run location lookup.
 
-   Example 1.33. lookup remote registrations usage
+   Example 1.34. lookup remote registrations usage
 ...
     if(uac_reg_lookup("$rU", "$ru")) {
         xlog("request from a remote SIP provider [$ou => $ru]\n");
diff --git a/modules/uac/api.h b/modules/uac/api.h
index 2d8e3b6..403a303 100644
--- a/modules/uac/api.h
+++ b/modules/uac/api.h
@@ -4,9 +4,13 @@
 
 
 typedef int (*uac_replace_from_t)(sip_msg_t *, str *, str *);
+typedef int (*uac_replace_to_t)(sip_msg_t *, str *, str *);
+typedef int (*uac_req_send_t)(void);
 
 typedef struct uac_binds {
 	uac_replace_from_t	replace_from;
+	uac_replace_to_t	replace_to;
+	uac_req_send_t      req_send;
 } uac_api_t;
 
 typedef int (*bind_uac_f)(uac_api_t*);
diff --git a/modules/uac/auth.c b/modules/uac/auth.c
index 3bdee90..7b8e6ed 100644
--- a/modules/uac/auth.c
+++ b/modules/uac/auth.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2005 Voice Sistem SRL
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,11 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  *
- *
- * History:
- * ---------
- *  2005-01-31  first version (ramona)
- *  2006-03-02  UAC authentication looks first in AVPs for credential (bogdan)
  */
 
 
diff --git a/modules/uac/auth.h b/modules/uac/auth.h
index a8b8cb6..0423456 100644
--- a/modules/uac/auth.h
+++ b/modules/uac/auth.h
@@ -1,16 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2005 Voice Sistem SRL
  *
- * This file is part of opnser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * UAC SER-module is free software; you can redistribute it and/or
+ * Kamailio is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
  * of the License, or (at your option) any later version.
  *
- * UAC SER-module is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -20,9 +18,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  *
  *
- * History:
- * ---------
- *  2005-01-31  first version (ramona)
  */
 
 
diff --git a/modules/uac/auth_alg.c b/modules/uac/auth_alg.c
index e16697a..608ac64 100644
--- a/modules/uac/auth_alg.c
+++ b/modules/uac/auth_alg.c
@@ -1,16 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2005 Voice Sistem SRL
  *
  * This file is part of Kamailio, a free SIP server.
  *
- * UAC Kamailio-module is free software; you can redistribute it and/or
+ * Kamailio is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
  * of the License, or (at your option) any later version.
  *
- * UAC Kamailio-module is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -19,9 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  *
- * History:
- * ---------
- *  2005-01-31  first version (ramona)
  */
 
 
diff --git a/modules/uac/auth_alg.h b/modules/uac/auth_alg.h
index 4239641..5ee6a85 100644
--- a/modules/uac/auth_alg.h
+++ b/modules/uac/auth_alg.h
@@ -1,16 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2005 Voice Sistem SRL
  *
  * This file is part of Kamailio, a free SIP server.
  *
- * UAC Kamailio-module is free software; you can redistribute it and/or
+ * Kamailio is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
  * of the License, or (at your option) any later version.
  *
- * UAC Kamailio-module is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -19,10 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  *
- *
- * History:
- * ---------
- *  2005-01-31  first version (ramona)
  */
 
 
diff --git a/modules/uac/auth_hdr.c b/modules/uac/auth_hdr.c
index 18a716c..62d204d 100644
--- a/modules/uac/auth_hdr.c
+++ b/modules/uac/auth_hdr.c
@@ -1,16 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2005 Voice Sistem SRL
  *
  * This file is part of Kamailio, a free SIP server.
  *
- * UAC Kamailio-module is free software; you can redistribute it and/or
+ * Kamailio is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
  * of the License, or (at your option) any later version.
  *
- * UAC Kamailio-module is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -18,11 +16,6 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- *
- *
- * History:
- * ---------
- *  2005-01-31  first version (ramona)
  */
 
 
diff --git a/modules/uac/auth_hdr.h b/modules/uac/auth_hdr.h
index 031fa31..4f0278e 100644
--- a/modules/uac/auth_hdr.h
+++ b/modules/uac/auth_hdr.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2005 Voice Sistem SRL
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,10 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  *
- *
- * History:
- * ---------
- *  2005-01-31  first version (ramona)
  */
 
 
diff --git a/modules/uac/doc/uac_admin.xml b/modules/uac/doc/uac_admin.xml
index f4c5580..0a154d9 100644
--- a/modules/uac/doc/uac_admin.xml
+++ b/modules/uac/doc/uac_admin.xml
@@ -796,6 +796,53 @@ failure_route[REMOTE_AUTH] {
 		Exported pseudo-variables are documented at &kamwikilink;.
 		</para>
 	</section>
+
+	<section>
+		<title>Event Routes</title>
+		<section id="uac.ert.uac_reply">
+			<title>
+				<function moreinfo="none">event_route[uac:reply]</function>
+			</title>
+		<para>
+			Event route executed for the final reply to the request set with
+			uac_req_send(). The associated $uac_req(evroute) has to be set to
+			1.
+		</para>
+		<example>
+		<title><function>event_route[uac:reply]</function> usage</title>
+			<programlisting format="linespecific">
+...
+$uac_req(method)="OPTIONS";
+$uac_req(ruri)="sip:kamailio.org";
+$uac_req(furi)="sip:kamailio.org";
+$uac_req(turi)="sip:kamailio.org";
+$uac_req(callid)=$(mb{s.md5});
+$uac_req(evroute)=1;
+uac_req_send();
+...
+event_route[uac:reply] {
+    xlog("received reply code is: $uac_req(evcode)\n");
+}
+...
+			</programlisting>
+		</example>
+		</section>
+	</section>
+
+	<section>
+		<title>Counters</title>
+		<itemizedlist>
+			<listitem><para>
+				<emphasis>regtotal</emphasis>: Total number of registrations
+			</para></listitem>
+			<listitem><para>
+				<emphasis>regactive</emphasis>: Total number of active registrations (successfully registred with service)
+			</para></listitem>
+			<listitem><para>
+				<emphasis>regdisabled</emphasis>: Total number of disabled registrations (no longer active)
+			</para></listitem>
+		</itemizedlist>
+	</section>
 	<section>
 		<title>RPC Commands</title>
 		<section id="uac.r.uac.reg_dump">
diff --git a/modules/uac/replace.c b/modules/uac/replace.c
index ccb2d46..1c30fe2 100644
--- a/modules/uac/replace.c
+++ b/modules/uac/replace.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2005 Voice Sistem SRL
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,18 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  *
- *
- * History:
- * ---------
- *  2005-01-31  first version (ramona)
- *  2005-08-12  encoded old FROM URI stored in RR hdr and not in FROM anymore;
- *              some TM callbacks replaced with RR callback - more efficient;
- *              XOR used to mix together old and new URI
- *              (bogdan)
- *  2006-03-03  new display name is added even if there is no previous one
- *              (bogdan)
- *  2006-03-03  the RR parameter is encrypted via XOR with a password
- *              (bogdan)
  */
 
 
diff --git a/modules/uac/replace.h b/modules/uac/replace.h
index 0b97053..6e9db0b 100644
--- a/modules/uac/replace.h
+++ b/modules/uac/replace.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2005 Voice Sistem SRL
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,10 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  *
- *
- * History:
- * ---------
- *  2005-01-31  first version (ramona)
  */
 
 
diff --git a/modules/uac/uac.c b/modules/uac/uac.c
index 3bfe356..125b08b 100644
--- a/modules/uac/uac.c
+++ b/modules/uac/uac.c
@@ -1,16 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2005 Voice Sistem SRL
  *
  * This file is part of Kamailio, a free SIP server.
  *
- * UAC Kamailio-module is free software; you can redistribute it and/or
+ * Kamailio is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
  * of the License, or (at your option) any later version.
  *
- * UAC Kamailio-module is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -19,16 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  *
- *
- * History:
- * ---------
- *  2005-01-31  first version (ramona)
- *  2005-08-12  some TM callbacks replaced with RR callback - more efficient;
- *              (bogdan)
- *  2006-03-02  UAC authentication looks first in AVPs for credential (bogdan)
- *  2006-03-03  the RR parameter is encrypted via XOR with a password
- *              (bogdan)
-
  */
 
 
@@ -127,9 +115,8 @@ static cmd_export_t cmds[]={
 			REQUEST_ROUTE },
 	{"uac_auth",          (cmd_function)w_uac_auth,       0,                  0, 0,
 			FAILURE_ROUTE },
-	{"uac_req_send",  (cmd_function)uac_req_send,         0,                  0, 0, 
-		REQUEST_ROUTE | FAILURE_ROUTE |
-		ONREPLY_ROUTE | BRANCH_ROUTE | ERROR_ROUTE | LOCAL_ROUTE},
+	{"uac_req_send",  (cmd_function)w_uac_req_send,       0,                  0, 0,
+			ANY_ROUTE},
 	{"uac_reg_lookup",  (cmd_function)w_uac_reg_lookup,  2, fixup_pvar_pvar,
 		fixup_free_pvar_pvar, ANY_ROUTE },
 	{"uac_reg_request_to",  (cmd_function)w_uac_reg_request_to,  2, fixup_pvar_uint, fixup_free_pvar_uint,
@@ -525,6 +512,24 @@ static int w_replace_to(struct sip_msg* msg, char* p1, char* p2)
 
 }
 
+int replace_to_api(sip_msg_t *msg, str* pd, str* pu)
+{
+	str *uri;
+	str *dsp;
+	if ( msg->to==0 && (parse_headers(msg,HDR_TO_F,0)!=0 || msg->to==0) ) {
+		LM_ERR("failed to find/parse TO hdr\n");
+		return -1;
+	}
+
+	uri = (pu!=NULL && pu->len>0)?pu:NULL;
+	dsp = (pd!=NULL && pd->len>0)?pd:NULL;
+
+	LM_DBG("dsp=%p (len=%d) , uri=%p (len=%d)\n", dsp, dsp?dsp->len:0,
+			uri, uri?uri->len:0);
+
+	return replace_uri(msg, dsp, uri, msg->to, &rr_to_param, &restore_to_avp, 0);
+}
+
 
 static int w_uac_auth(struct sip_msg* msg, char* str, char* str2)
 {
@@ -586,14 +591,16 @@ static int w_uac_reg_request_to(struct sip_msg* msg, char* src, char* mode_s)
 }
 
 
-int bind_uac(struct uac_binds *uacb)
+int bind_uac(uac_api_t *uacb)
 {
-	if (uacb == NULL)
-        {
-                LM_WARN("bind_uac: Cannot load uac API into a NULL pointer\n");
-                return -1;
-        }
-
-        uacb->replace_from = replace_from_api;
-        return 0;
+	if (uacb == NULL) {
+		LM_WARN("bind_uac: Cannot load uac API into a NULL pointer\n");
+		return -1;
+	}
+
+	memset(uacb, 0, sizeof(uac_api_t));
+	uacb->replace_from = replace_from_api;
+	uacb->replace_to = replace_to_api;
+	uacb->req_send = uac_req_send;
+	return 0;
 }
diff --git a/modules/uac/uac_reg.c b/modules/uac/uac_reg.c
index d295dbb..c56afef 100644
--- a/modules/uac/uac_reg.c
+++ b/modules/uac/uac_reg.c
@@ -1,6 +1,4 @@
 /**
- * $Id$
- *
  * Copyright (C) 2010 Daniel-Constantin Mierla (asipto.com)
  *
  * This file is part of kamailio, a free SIP server.
@@ -118,6 +116,7 @@ str auth_password_column = str_init("auth_password");
 str auth_proxy_column = str_init("auth_proxy");
 str expires_column = str_init("expires");
 
+
 #if 0
 INSERT INTO version (table_name, table_version) values ('uacreg','1');
 CREATE TABLE uacreg (
@@ -142,9 +141,22 @@ extern pv_spec_t auth_username_spec;
 extern pv_spec_t auth_realm_spec;
 extern pv_spec_t auth_password_spec;
 
+counter_handle_t regtotal;         /* Total number of registrations in memory */
+counter_handle_t regactive;        /* Active registrations - 200 OK */
+counter_handle_t regdisabled;      /* Disabled registrations */
+
+/* Init counters */
+static void uac_reg_counter_init()
+{
+	LM_DBG("*** Initializing UAC reg counters\n");
+        counter_register(&regtotal, "uac", "regtotal", 0, 0, 0, "Total number of registration accounts in memory", 0);
+        counter_register(&regactive, "uac", "regactive", 0, 0, 0, "Number of successfully registred accounts (200 OK)", 0);
+        counter_register(&regdisabled, "uac", "regdisabled", 0, 0, 0, "Counter of failed registrations (not 200 OK)", 0);
+}
+
 
 /**
- *
+ * Init the in-memory registration database in hash table
  */
 int uac_reg_init_ht(unsigned int sz)
 {
@@ -233,6 +245,9 @@ int uac_reg_init_ht(unsigned int sz)
 		}
 	}
 
+	/* Initialize uac reg counters */
+	uac_reg_counter_init();
+
 	return 0;
 }
 
@@ -345,6 +360,10 @@ int uac_reg_reset_ht_gc(void)
 		_reg_htable_gc->entries[i].byuser = NULL;
 		_reg_htable_gc->entries[i].usize = 0;
 	}
+	/* Reset all counters */
+	counter_reset(regtotal);
+	counter_reset(regactive);
+	counter_reset(regdisabled);
 	return 0;
 }
 
@@ -366,7 +385,7 @@ int uac_reg_ht_shift(void)
 	lock_get(_reg_htable_gc_lock);
 	if(_reg_htable_gc->stime > tn-UAC_REG_GC_INTERVAL) {
 		lock_release(_reg_htable_gc_lock);
-		LM_ERR("shifting the memory table is not possible in less than %d\n", UAC_REG_GC_INTERVAL);
+		LM_ERR("shifting the memory table is not possible in less than %d secs\n", UAC_REG_GC_INTERVAL);
 		return -1;
 	}
 	uac_reg_reset_ht_gc();
@@ -518,6 +537,7 @@ int reg_ht_add(reg_uac_t *reg)
 
 	reg_ht_add_byuser(nr);
 	reg_ht_add_byuuid(nr);
+	counter_inc(regtotal);
 
 	return 0;
 }
@@ -878,15 +898,17 @@ void uac_reg_tm_callback( struct cell *t, int type, struct tmcb_params *ps)
 	}
 
 error:
-	ri->flags &= ~(UAC_REG_ONGOING|UAC_REG_AUTHSENT);
-	if(reg_retry_interval)
+	if(reg_retry_interval) {
 		ri->timer_expires = time(NULL) + reg_retry_interval;
-	else
+	} else {
 		ri->flags |= UAC_REG_DISABLED;
+		counter_inc(regdisabled);
+	}
 done:
 	if(ri)
 		ri->flags &= ~(UAC_REG_ONGOING|UAC_REG_AUTHSENT);
 	shm_free(uuid);
+	counter_inc(regactive);
 }
 
 int uac_reg_update(reg_uac_t *reg, time_t tn)
@@ -912,15 +934,16 @@ int uac_reg_update(reg_uac_t *reg, time_t tn)
 		return 4;
 	if(reg->timer_expires > tn + reg_timer_interval + 3)
 		return 3;
-	reg->timer_expires = tn;
-	reg->flags |= UAC_REG_ONGOING;
-	reg->flags &= ~UAC_REG_ONLINE;
 	uuid = (char*)shm_malloc(reg->l_uuid.len+1);
 	if(uuid==NULL)
 	{
 		LM_ERR("no more shm\n");
 		return -1;
 	}
+	reg->timer_expires = tn;
+	reg->flags |= UAC_REG_ONGOING;
+	reg->flags &= ~UAC_REG_ONLINE;
+	counter_add(regactive, -1);		/* Take it out of the active pool while re-registering */
 	memcpy(uuid, reg->l_uuid.s, reg->l_uuid.len);
 	uuid[reg->l_uuid.len] = '\0';
 
@@ -962,8 +985,10 @@ int uac_reg_update(reg_uac_t *reg, time_t tn)
 		shm_free(uuid);
 		if (reg_retry_interval)
 			reg->timer_expires = (tn ? tn : time(NULL)) + reg_retry_interval;
-		else
+		else {
 			reg->flags |= UAC_REG_DISABLED;
+			counter_inc(regdisabled);
+		}
 		reg->flags &= ~UAC_REG_ONGOING;
 		return -1;
 	}
@@ -1658,6 +1683,7 @@ static const char* rpc_uac_reg_enable_doc[2] = {
 static void rpc_uac_reg_enable(rpc_t* rpc, void* ctx)
 {
 	rpc_uac_reg_update_flag(rpc, ctx, 0, UAC_REG_DISABLED);
+	counter_add(regdisabled, -1);
 }
 
 static const char* rpc_uac_reg_disable_doc[2] = {
@@ -1668,6 +1694,7 @@ static const char* rpc_uac_reg_disable_doc[2] = {
 static void rpc_uac_reg_disable(rpc_t* rpc, void* ctx)
 {
 	rpc_uac_reg_update_flag(rpc, ctx, 1, UAC_REG_DISABLED);
+	counter_inc(regdisabled);
 }
 
 static const char* rpc_uac_reg_reload_doc[2] = {
diff --git a/modules/uac/uac_reg.h b/modules/uac/uac_reg.h
index 9ca8f71..c5b3700 100644
--- a/modules/uac/uac_reg.h
+++ b/modules/uac/uac_reg.h
@@ -1,9 +1,7 @@
 /**
- * $Id$
- *
  * Copyright (C) 2010 Daniel-Constantin Mierla (asipto.com)
  *
- * This file is part of kamailio, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
  * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/modules/uac/uac_send.c b/modules/uac/uac_send.c
index 7718265..a429bdc 100644
--- a/modules/uac/uac_send.c
+++ b/modules/uac/uac_send.c
@@ -1,9 +1,7 @@
 /**
- * $Id$
- *
  * Copyright (C) 2009 Daniel-Constantin Mierla (asipto.com)
  *
- * This file is part of kamailio, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
  * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -22,6 +20,7 @@
 
 #include "../../dprint.h"
 #include "../../trim.h"
+#include "../../route.h"
 
 #include "../../modules/tm/tm_load.h"
 
@@ -29,6 +28,7 @@
 #include "../../parser/parse_from.h"
 #include "../../parser/parse_to.h"
 #include "../../parser/contact/parse_contact.h"
+#include "../../lib/kcore/faked_msg.h"
 
 #include "auth.h"
 #include "auth_hdr.h"
@@ -36,6 +36,7 @@
 
 #define MAX_UACH_SIZE 2048
 #define MAX_UACB_SIZE 4086
+#define MAX_UACD_SIZE 128
 
 /** TM bind */
 struct tm_binds tmb;
@@ -64,11 +65,32 @@ typedef struct _uac_send_info {
 	str   s_auser;
 	char  b_apasswd[64];
 	str   s_apasswd;
-	unsigned int onreply;
+	char  b_evparam[MAX_UACD_SIZE];
+	str   s_evparam;
+	unsigned int evroute;
+	unsigned int evcode;
+	unsigned int evtype;
 } uac_send_info_t;
 
 static struct _uac_send_info _uac_req;
 
+void uac_send_info_copy(uac_send_info_t *src, uac_send_info_t *dst)
+{
+	memcpy(dst, src, sizeof(uac_send_info_t));
+	dst->s_method.s  = dst->b_method;
+	dst->s_ruri.s    = dst->b_ruri;
+	dst->s_turi.s    = dst->b_turi;
+	dst->s_furi.s    = dst->b_furi;
+	dst->s_hdrs.s    = dst->b_hdrs;
+	dst->s_body.s    = dst->b_body;
+	dst->s_ouri.s    = dst->b_ouri;
+	dst->s_auser.s   = dst->b_auser;
+	dst->s_apasswd.s = dst->b_apasswd;
+	dst->s_callid.s  = dst->b_callid;
+	dst->s_sock.s    = dst->b_sock;
+	dst->s_evparam.s = dst->b_evparam;
+}
+
 uac_send_info_t *uac_send_info_clone(uac_send_info_t *ur)
 {
 	uac_send_info_t *tp = NULL;
@@ -78,18 +100,7 @@ uac_send_info_t *uac_send_info_clone(uac_send_info_t *ur)
 		LM_ERR("no more shm memory\n");
 		return NULL;
 	}
-	memcpy(tp, ur, sizeof(uac_send_info_t));
-	tp->s_method.s  = tp->b_method;
-	tp->s_ruri.s    = tp->b_ruri;
-	tp->s_turi.s    = tp->b_turi;
-	tp->s_furi.s    = tp->b_furi;
-	tp->s_hdrs.s    = tp->b_hdrs;
-	tp->s_body.s    = tp->b_body;
-	tp->s_ouri.s    = tp->b_ouri;
-	tp->s_auser.s   = tp->b_auser;
-	tp->s_apasswd.s = tp->b_apasswd;
-	tp->s_callid.s  = tp->b_callid;
-	tp->s_sock.s    = tp->b_sock;
+	uac_send_info_copy(ur, tp);
 
 	return tp;
 }
@@ -132,6 +143,8 @@ int pv_get_uac_req(struct sip_msg *msg, pv_param_t *param,
 			if(_uac_req.s_method.len<=0)
 				return pv_get_null(msg, param, res);
 			return pv_get_strval(msg, param, res, &_uac_req.s_method);
+		case 8:
+			return pv_get_uintval(msg, param, res, _uac_req.evroute);
 		case 9:
 			if(_uac_req.s_auser.len<=0)
 				return pv_get_null(msg, param, res);
@@ -148,6 +161,14 @@ int pv_get_uac_req(struct sip_msg *msg, pv_param_t *param,
 			if(_uac_req.s_sock.len<=0)
 				return pv_get_null(msg, param, res);
 			return pv_get_strval(msg, param, res, &_uac_req.s_sock);
+		case 14:
+			if(_uac_req.s_evparam.len<=0)
+				return pv_get_null(msg, param, res);
+			return pv_get_strval(msg, param, res, &_uac_req.s_evparam);
+		case 15:
+			return pv_get_uintval(msg, param, res, _uac_req.evcode);
+		case 16:
+			return pv_get_uintval(msg, param, res, _uac_req.evtype);
 		default:
 			return pv_get_uintval(msg, param, res, _uac_req.flags);
 	}
@@ -173,8 +194,11 @@ int pv_set_uac_req(struct sip_msg* msg, pv_param_t *param,
 				_uac_req.s_hdrs.len = 0;
 				_uac_req.s_body.len = 0;
 				_uac_req.s_method.len = 0;
-				_uac_req.onreply = 0;
 				_uac_req.s_callid.len = 0;
+				_uac_req.evroute = 0;
+				_uac_req.evtype = 0;
+				_uac_req.evcode = 0;
+				_uac_req.s_evparam.len = 0;
 			}
 			break;
 		case 1:
@@ -320,7 +344,7 @@ int pv_set_uac_req(struct sip_msg* msg, pv_param_t *param,
 		case 8:
 			if(val==NULL)
 			{
-				_uac_req.onreply = 0;
+				_uac_req.evroute = 0;
 				return 0;
 			}
 			if(!(val->flags&PV_VAL_INT))
@@ -328,12 +352,7 @@ int pv_set_uac_req(struct sip_msg* msg, pv_param_t *param,
 				LM_ERR("Invalid value type\n");
 				return -1;
 			}
-			if(val->ri>=ONREPLY_RT_NO)
-			{
-				LM_ERR("Value too big\n");
-				return -1;
-			}
-			_uac_req.onreply = val->ri;
+			_uac_req.evroute = val->ri;
 			break;
 		case 9:
 			if(val==NULL)
@@ -410,6 +429,52 @@ int pv_set_uac_req(struct sip_msg* msg, pv_param_t *param,
 			_uac_req.s_sock.s[val->rs.len] = '\0';
 			_uac_req.s_sock.len = val->rs.len;
 			break;
+		case 14:
+			if(val==NULL)
+			{
+				_uac_req.s_evparam.len = 0;
+				return 0;
+			}
+			if(!(val->flags&PV_VAL_STR))
+			{
+				LM_ERR("Invalid value type\n");
+				return -1;
+			}
+			if(val->rs.len>=MAX_UACD_SIZE)
+			{
+				LM_ERR("Value size too big\n");
+				return -1;
+			}
+			memcpy(_uac_req.s_evparam.s, val->rs.s, val->rs.len);
+			_uac_req.s_evparam.s[val->rs.len] = '\0';
+			_uac_req.s_evparam.len = val->rs.len;
+			break;
+		case 15:
+			if(val==NULL)
+			{
+				_uac_req.evcode = 0;
+				return 0;
+			}
+			if(!(val->flags&PV_VAL_INT))
+			{
+				LM_ERR("Invalid value type\n");
+				return -1;
+			}
+			_uac_req.evcode = val->ri;
+			break;
+		case 16:
+			if(val==NULL)
+			{
+				_uac_req.evtype = 0;
+				return 0;
+			}
+			if(!(val->flags&PV_VAL_INT))
+			{
+				LM_ERR("Invalid value type\n");
+				return -1;
+			}
+			_uac_req.evtype = val->ri;
+			break;
 	}
 	return 0;
 }
@@ -453,13 +518,19 @@ int pv_parse_uac_req_name(pv_spec_p sp, str *in)
 				sp->pvp.pvn.u.isname.name.n = 7;
 			else if(strncmp(in->s, "callid", 6)==0)
 				sp->pvp.pvn.u.isname.name.n = 11;
+			else if(strncmp(in->s, "evcode", 6)==0)
+				sp->pvp.pvn.u.isname.name.n = 15;
+			else if(strncmp(in->s, "evtype", 6)==0)
+				sp->pvp.pvn.u.isname.name.n = 16;
 			else goto error;
 		break;
 		case 7: 
-			if(strncmp(in->s, "onreply", 7)==0)
+			if(strncmp(in->s, "evroute", 7)==0)
 				sp->pvp.pvn.u.isname.name.n = 8;
 			else if(strncmp(in->s, "apasswd", 7)==0)
 				sp->pvp.pvn.u.isname.name.n = 10;
+			else if(strncmp(in->s, "evparam", 7)==0)
+				sp->pvp.pvn.u.isname.name.n = 14;
 			else goto error;
 		break;
 		default:
@@ -495,6 +566,7 @@ void uac_req_init(void)
 	_uac_req.s_apasswd.s  = _uac_req.b_apasswd;
 	_uac_req.s_callid.s   = _uac_req.b_callid;
 	_uac_req.s_sock.s     = _uac_req.b_sock;
+	_uac_req.s_evparam.s  = _uac_req.b_evparam;
 	return;
 }
 
@@ -535,6 +607,41 @@ int uac_send_tmdlg(dlg_t *tmdlg, sip_msg_t *rpl)
 
 #define MAX_UACH_SIZE 2048
 
+/**
+ *
+ */
+void uac_req_run_event_route(sip_msg_t *msg, uac_send_info_t *tp, int rcode)
+{
+	char *evrtname = "uac:reply";
+	int rt, backup_rt;
+	struct run_act_ctx ctx;
+	sip_msg_t *fmsg;
+
+	rt = route_get(&event_rt, evrtname);
+	if (rt < 0 || event_rt.rlist[rt] == NULL)
+	{
+		LM_DBG("event_route[uac:reply] does not exist\n");
+		return;
+	}
+
+	uac_send_info_copy(tp, &_uac_req);
+	_uac_req.evcode = rcode;
+	if(msg==NULL)
+	{
+		_uac_req.evtype = 2;
+		fmsg = faked_msg_get_next();
+	} else {
+		_uac_req.evtype = 1;
+		fmsg = msg;
+	}
+
+	backup_rt = get_route_type();
+	set_route_type(REQUEST_ROUTE);
+	init_run_actions_ctx(&ctx);
+	run_top_route(event_rt.rlist[rt], fmsg, 0);
+	set_route_type(backup_rt);
+}
+
 /** 
  * TM callback function
  */
@@ -552,13 +659,21 @@ void uac_send_tm_callback(struct cell *t, int type, struct tmcb_params *ps)
 	dlg_t tmdlg;
 	uac_send_info_t *tp = NULL;
 
+	LM_DBG("tm callback with status %d\n", ps->code);
+
 	if(ps->param==NULL || *ps->param==0)
 	{
-		LM_DBG("message id not received\n");
+		LM_DBG("callback param with message id not received\n");
 		goto done;
 	}
 	tp = (uac_send_info_t*)(*ps->param);
-	if(ps->code != 401 && ps->code != 407)
+
+	if(tp->evroute!=0) {
+		uac_req_run_event_route((ps->rpl==FAKED_REPLY)?NULL:ps->rpl,
+				tp, ps->code);
+	}
+
+	if((ps->code != 401 && ps->code != 407) || tp->s_apasswd.len<=0)
 	{
 		LM_DBG("completed with status %d\n", ps->code);
 		goto done;
@@ -640,7 +755,7 @@ error:
 }
 
 
-int uac_req_send(struct sip_msg *msg, char *s1, char *s2)
+int uac_req_send(void)
 {
 	int ret;
 	uac_req_t uac_r;
@@ -686,3 +801,7 @@ int uac_req_send(struct sip_msg *msg, char *s1, char *s2)
 	return 1;
 }
 
+int w_uac_req_send(struct sip_msg *msg, char *s1, char *s2)
+{
+	return uac_req_send();
+}
diff --git a/modules/uac/uac_send.h b/modules/uac/uac_send.h
index 6965ea1..2d43657 100644
--- a/modules/uac/uac_send.h
+++ b/modules/uac/uac_send.h
@@ -1,6 +1,4 @@
-/**
- * $Id$
- *
+/*
  * Copyright (C) 2009 Daniel-Constantin Mierla (asipto.com)
  *
  * This file is part of kamailio, a free SIP server.
@@ -31,6 +29,7 @@ int pv_set_uac_req(struct sip_msg* msg, pv_param_t *param,
 		int op, pv_value_t *val);
 int pv_parse_uac_req_name(pv_spec_p sp, str *in);
 void uac_req_init(void);
-int uac_req_send(struct sip_msg *msg, char *s1, char *s2);
+int uac_req_send(void);
+int w_uac_req_send(struct sip_msg *msg, char *s1, char *s2);
 
 #endif
diff --git a/modules/uac_redirect/Makefile b/modules/uac_redirect/Makefile
index 0b7e22d..27cfdd2 100644
--- a/modules/uac_redirect/Makefile
+++ b/modules/uac_redirect/Makefile
@@ -1,4 +1,4 @@
-# example module makefile
+# uac_redirect module makefile
 #
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
diff --git a/modules/uac_redirect/rd_filter.c b/modules/uac_redirect/rd_filter.c
index a4a169a..647cd4e 100644
--- a/modules/uac_redirect/rd_filter.c
+++ b/modules/uac_redirect/rd_filter.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2005 Voice Sistem SRL
  *
  * This file is part of Kamailio, a free SIP server.
@@ -20,9 +18,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  *
  *
- * History:
- * ---------
- *  2005-06-22  first version (bogdan)
  */
 
 
diff --git a/modules/uac_redirect/rd_filter.h b/modules/uac_redirect/rd_filter.h
index a446963..027708c 100644
--- a/modules/uac_redirect/rd_filter.h
+++ b/modules/uac_redirect/rd_filter.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2005 Voice Sistem SRL
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,10 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  *
- *
- * History:
- * ---------
- *  2005-06-22  first version (bogdan)
  */
 
 
diff --git a/modules/uac_redirect/rd_funcs.c b/modules/uac_redirect/rd_funcs.c
index a96ec31..6be86bd 100644
--- a/modules/uac_redirect/rd_funcs.c
+++ b/modules/uac_redirect/rd_funcs.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2005 Voice Sistem SRL
  *
  * This file is part of Kamailio, a free SIP server.
@@ -20,10 +18,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  *
  *
- * History:
- * ---------
- *  2005-06-22  first version (bogdan)
- *  2006-05-23  push also q value into branches (bogdan)
  */
 
 
diff --git a/modules/uac_redirect/rd_funcs.h b/modules/uac_redirect/rd_funcs.h
index 97764ca..b20aad0 100644
--- a/modules/uac_redirect/rd_funcs.h
+++ b/modules/uac_redirect/rd_funcs.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2005 Voice Sistem SRL
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,10 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  *
- *
- * History:
- * ---------
- *  2005-06-22  first version (bogdan)
  */
 
 
diff --git a/modules/uac_redirect/redirect.c b/modules/uac_redirect/redirect.c
deleted file mode 100644
index d8cecae..0000000
--- a/modules/uac_redirect/redirect.c
+++ /dev/null
@@ -1,382 +0,0 @@
-/*
- * $Id$
- *
- * Copyright (C) 2005 Voice Sistem SRL
- *
- * This file is part of Kamailio, a free SIP server.
- *
- * Kamailio is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * Kamailio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- *
- *
- * History:
- * ---------
- *  2005-06-22  first version (bogdan)
- */
-
-#include <sys/types.h> /* for regex */
-#include <regex.h>
-
-#include "../../sr_module.h"
-#include "../../str.h"
-#include "../../dprint.h"
-#include "../../mem/mem.h"
-#include "../../lib/srutils/sruid.h"
-#include "../../modules/tm/tm_load.h"
-#include "rd_funcs.h"
-#include "rd_filter.h"
-
-MODULE_VERSION
-
-/* internal global variables */
-struct tm_binds rd_tmb;           /*imported functions from tm */
-cmd_function    rd_acc_fct = 0;   /*imported function from acc */
-
-/* global parameter variables */
-char *acc_db_table = "acc";
-char *acc_fct_s    = "acc_log_request";
-
-/* private parameter variables */
-char *deny_filter_s = 0;
-char *accept_filter_s = 0;
-char *def_filter_s = 0;
-
-unsigned int bflags = 0;
-
-#define ACCEPT_RULE_STR "accept"
-#define DENY_RULE_STR   "deny"
-
-/* sruid to get internal uid */
-sruid_t _redirect_sruid;
-
-
-static int redirect_init(void);
-static int child_init(int rank);
-static int w_set_deny(struct sip_msg* msg, char *dir, char *foo);
-static int w_set_accept(struct sip_msg* msg, char *dir, char *foo);
-static int w_get_redirect1(struct sip_msg* msg, char *dir, char *foo);
-static int w_get_redirect2(struct sip_msg* msg, char *dir, char *foo);
-static int regexp_compile(char *re_s, regex_t **re);
-static int get_redirect_fixup(void** param, int param_no);
-static int setf_fixup(void** param, int param_no);
-
-
-static cmd_export_t cmds[] = {
-	{"set_deny_filter",   (cmd_function)w_set_deny,      2,  setf_fixup, 0,
-			FAILURE_ROUTE },
-	{"set_accept_filter", (cmd_function)w_set_accept,    2,  setf_fixup, 0,
-			FAILURE_ROUTE },
-	{"get_redirects",     (cmd_function)w_get_redirect2,  2,  get_redirect_fixup, 0,
-			FAILURE_ROUTE },
-	{"get_redirects",     (cmd_function)w_get_redirect1,  1,  get_redirect_fixup, 0,
-			FAILURE_ROUTE },
-	{0, 0, 0, 0, 0, 0}
-};
-
-static param_export_t params[] = {
-	{"deny_filter",     PARAM_STRING,  &deny_filter_s    },
-	{"accept_filter",   PARAM_STRING,  &accept_filter_s  },
-	{"default_filter",  PARAM_STRING,  &def_filter_s     },
-	{"acc_function",    PARAM_STRING,  &acc_fct_s        },
-	{"acc_db_table",    PARAM_STRING,  &acc_db_table     },
-	{"bflags",    		INT_PARAM,  &bflags			  },
-	{0, 0, 0}
-};
-
-
-struct module_exports exports = {
-	"uac_redirect",
-	DEFAULT_DLFLAGS, /* dlopen flags */
-	cmds,     /* Exported functions */
-	params,   /* Exported parameters */
-	0,        /* exported statistics */
-	0,        /* exported MI functions */
-	0,        /* exported pseudo-variables */
-	0,        /* extra processes */
-	redirect_init, /* Module initialization function */
-	0,
-	0,
-	child_init /* per-child init function */
-};
-
-
-
-int get_nr_max(char *s, unsigned char *max)
-{
-	unsigned short nr;
-	int err;
-
-	if ( s[0]=='*' && s[1]==0 ) {
-		/* is '*' -> infinit ;-) */
-		*max = 0;
-		return 0;
-	} else {
-		/* must be a positive number less than 255 */
-		nr = str2s(s, strlen(s), &err);
-		if (err==0){
-			if (nr>255){
-				LM_ERR("number too big <%d> (max=255)\n",nr);
-				return -1;
-			}
-			*max = (unsigned char)nr;
-			return 0;
-		}else{
-			LM_ERR("bad  number <%s>\n",s);
-			return -1;
-		}
-	}
-}
-
-
-static int get_redirect_fixup(void** param, int param_no)
-{
-	unsigned char maxb,maxt;
-	struct acc_param *accp;
-	cmd_function fct;
-	char *p;
-	char *s;
-
-	s = (char*)*param;
-	if (param_no==1) {
-		if ( (p=strchr(s,':'))!=0 ) {
-			/* have max branch also */
-			*p = 0;
-			if (get_nr_max(p+1, &maxb)!=0)
-				return E_UNSPEC;
-		} else {
-			maxb = 0; /* infinit */
-		}
-
-		/* get max total */
-		if (get_nr_max(s, &maxt)!=0)
-			return E_UNSPEC;
-
-		pkg_free(*param);
-		*param=(void*)(long)( (((unsigned short)maxt)<<8) | maxb);
-	} else if (param_no==2) {
-		/* acc function loaded? */
-		if (rd_acc_fct==0) {
-			/* must import the acc stuff */
-			if (acc_fct_s==0 || acc_fct_s[0]==0) {
-				LM_ERR("acc support enabled, but no acc function defined\n");
-				return E_UNSPEC;
-			}
-			fct = find_export(acc_fct_s, 2, REQUEST_ROUTE);
-			if ( fct==0 )
-				fct = find_export(acc_fct_s, 1, REQUEST_ROUTE);
-			if ( fct==0 ) {
-				LM_ERR("cannot import %s function; is acc loaded and proper "
-					"compiled?\n", acc_fct_s);
-				return E_UNSPEC;
-			}
-			rd_acc_fct = fct;
-		}
-		/* set the reason str */
-		accp = (struct acc_param*)pkg_malloc(sizeof(struct acc_param));
-		if (accp==0) {
-			LM_ERR("no more pkg mem\n");
-			return E_UNSPEC;
-		}
-		memset( accp, 0, sizeof(struct acc_param));
-		if (s!=0 && *s!=0) {
-			accp->reason.s = s;
-			accp->reason.len = strlen(s);
-		} else {
-			accp->reason.s = "n/a";
-			accp->reason.len = 3;
-		}
-		*param=(void*)accp;
-	}
-
-	return 0;
-}
-
-
-static int setf_fixup(void** param, int param_no)
-{
-	unsigned short nr;
-	regex_t *filter;
-	char *s;
-
-	s = (char*)*param;
-	if (param_no==1) {
-		/* compile the filter */
-		if (regexp_compile( s, &filter)<0) {
-			LM_ERR("cannot init filter <%s>\n", s);
-			return E_BAD_RE;
-		}
-		pkg_free(*param);
-		*param = (void*)filter;
-	} else if (param_no==2) {
-		if (s==0 || s[0]==0) {
-			nr = 0;
-		} else if (strcasecmp(s,"reset_all")==0) {
-			nr = RESET_ADDED|RESET_DEFAULT;
-		} else if (strcasecmp(s,"reset_default")==0) {
-			nr = RESET_DEFAULT;
-		} else if (strcasecmp(s,"reset_added")==0) {
-			nr = RESET_ADDED;
-		} else {
-			LM_ERR("unknown reset type <%s>\n",s);
-			return E_UNSPEC;
-		}
-		pkg_free(*param);
-		*param = (void*)(long)nr;
-	}
-
-	return 0;
-}
-
-
-
-static int regexp_compile(char *re_s, regex_t **re)
-{
-	*re = 0;
-	if (re_s==0 || strlen(re_s)==0 ) {
-		return 0;
-	} else {
-		if ((*re=pkg_malloc(sizeof(regex_t)))==0)
-			return E_OUT_OF_MEM;
-		if (regcomp(*re, re_s, REG_EXTENDED|REG_ICASE|REG_NEWLINE) ){
-			pkg_free(*re);
-			*re = 0;
-			LM_ERR("regexp_compile:bad regexp <%s>\n", re_s);
-			return E_BAD_RE;
-		}
-	}
-	return 0;
-}
-
-
-
-static int redirect_init(void)
-{
-	regex_t *filter;
-	void *p;
-
-	/* load the TM API */
-	if (load_tm_api(&rd_tmb)!=0) {
-		LM_ERR("failed to load TM API\n");
-		goto error;
-	}
-
-	p = (void*)acc_db_table;
-	/* fixup table name */
-	if(fixup_var_pve_str_12(&p, 1)<0) {
-		LM_ERR("failed to fixup acc db table\n");
-		goto error;
-	}
-	acc_db_table = p;
-
-	/* init filter */
-	init_filters();
-
-	/* what's the default rule? */
-	if (def_filter_s) {
-		if ( !strcasecmp(def_filter_s,ACCEPT_RULE_STR) ) {
-			set_default_rule( ACCEPT_RULE );
-		} else if ( !strcasecmp(def_filter_s,DENY_RULE_STR) ) {
-			set_default_rule( DENY_RULE );
-		} else {
-			LM_ERR("unknown default filter <%s>\n",def_filter_s);
-		}
-	}
-
-	/* if accept filter specify, compile it */
-	if (regexp_compile(accept_filter_s, &filter)<0) {
-		LM_ERR("failed to init accept filter\n");
-		goto error;
-	}
-	add_default_filter( ACCEPT_FILTER, filter);
-
-	/* if deny filter specify, compile it */
-	if (regexp_compile(deny_filter_s, &filter)<0) {
-		LM_ERR("failed to init deny filter\n");
-		goto error;
-	}
-	add_default_filter( DENY_FILTER, filter);
-
-	if(sruid_init(&_redirect_sruid, '-', "rdir", SRUID_INC)<0)
-		return -1;
-
-	return 0;
-error:
-	return -1;
-}
-
-static int child_init(int rank)
-{
-	if(sruid_init(&_redirect_sruid, '-', "rdir", SRUID_INC)<0)
-		return -1;
-	return 0;
-}
-
-static inline void msg_tracer(struct sip_msg* msg, int reset)
-{
-	static unsigned int id  = 0;
-	static unsigned int set = 0;
-
-	if (reset) {
-		set = 0;
-	} else {
-		if (set) {
-			if (id!=msg->id) {
-				LM_WARN("filters set but not used -> reseting to default\n");
-				reset_filters();
-				id = msg->id;
-			}
-		} else {
-			id = msg->id;
-			set = 1;
-		}
-	}
-}
-
-
-static int w_set_deny(struct sip_msg* msg, char *re, char *flags)
-{
-	msg_tracer( msg, 0);
-	return (add_filter( DENY_FILTER, (regex_t*)re, (int)(long)flags)==0)?1:-1;
-}
-
-
-static int w_set_accept(struct sip_msg* msg, char *re, char *flags)
-{
-	msg_tracer( msg, 0);
-	return (add_filter( ACCEPT_FILTER, (regex_t*)re, (int)(long)flags)==0)?1:-1;
-}
-
-
-static int w_get_redirect2(struct sip_msg* msg, char *max_c, char *reason)
-{
-	int n;
-	unsigned short max;
-
-	msg_tracer( msg, 0);
-	/* get the contacts */
-	max = (unsigned short)(long)max_c;
-	n = get_redirect(msg , (max>>8)&0xff, max&0xff, (struct acc_param*)reason, bflags);
-	reset_filters();
-	/* reset the tracer */
-	msg_tracer( msg, 1);
-
-	return n;
-}
-
-
-static int w_get_redirect1(struct sip_msg* msg, char *max_c, char *foo)
-{
-	return w_get_redirect2(msg, max_c, 0);
-}
-
diff --git a/modules/uac_redirect/uac_redirect.c b/modules/uac_redirect/uac_redirect.c
new file mode 100644
index 0000000..096ac0f
--- /dev/null
+++ b/modules/uac_redirect/uac_redirect.c
@@ -0,0 +1,376 @@
+/*
+ * Copyright (C) 2005 Voice Sistem SRL
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ */
+
+#include <sys/types.h> /* for regex */
+#include <regex.h>
+
+#include "../../sr_module.h"
+#include "../../str.h"
+#include "../../dprint.h"
+#include "../../mem/mem.h"
+#include "../../lib/srutils/sruid.h"
+#include "../../modules/tm/tm_load.h"
+#include "rd_funcs.h"
+#include "rd_filter.h"
+
+MODULE_VERSION
+
+/* internal global variables */
+struct tm_binds rd_tmb;           /*imported functions from tm */
+cmd_function    rd_acc_fct = 0;   /*imported function from acc */
+
+/* global parameter variables */
+char *acc_db_table = "acc";
+char *acc_fct_s    = "acc_log_request";
+
+/* private parameter variables */
+char *deny_filter_s = 0;
+char *accept_filter_s = 0;
+char *def_filter_s = 0;
+
+unsigned int bflags = 0;
+
+#define ACCEPT_RULE_STR "accept"
+#define DENY_RULE_STR   "deny"
+
+/* sruid to get internal uid */
+sruid_t _redirect_sruid;
+
+
+static int redirect_init(void);
+static int child_init(int rank);
+static int w_set_deny(struct sip_msg* msg, char *dir, char *foo);
+static int w_set_accept(struct sip_msg* msg, char *dir, char *foo);
+static int w_get_redirect1(struct sip_msg* msg, char *dir, char *foo);
+static int w_get_redirect2(struct sip_msg* msg, char *dir, char *foo);
+static int regexp_compile(char *re_s, regex_t **re);
+static int get_redirect_fixup(void** param, int param_no);
+static int setf_fixup(void** param, int param_no);
+
+
+static cmd_export_t cmds[] = {
+	{"set_deny_filter",   (cmd_function)w_set_deny,      2,  setf_fixup, 0,
+			FAILURE_ROUTE },
+	{"set_accept_filter", (cmd_function)w_set_accept,    2,  setf_fixup, 0,
+			FAILURE_ROUTE },
+	{"get_redirects",     (cmd_function)w_get_redirect2,  2,  get_redirect_fixup, 0,
+			FAILURE_ROUTE },
+	{"get_redirects",     (cmd_function)w_get_redirect1,  1,  get_redirect_fixup, 0,
+			FAILURE_ROUTE },
+	{0, 0, 0, 0, 0, 0}
+};
+
+static param_export_t params[] = {
+	{"deny_filter",     PARAM_STRING,  &deny_filter_s    },
+	{"accept_filter",   PARAM_STRING,  &accept_filter_s  },
+	{"default_filter",  PARAM_STRING,  &def_filter_s     },
+	{"acc_function",    PARAM_STRING,  &acc_fct_s        },
+	{"acc_db_table",    PARAM_STRING,  &acc_db_table     },
+	{"bflags",    		INT_PARAM,  &bflags			  },
+	{0, 0, 0}
+};
+
+
+struct module_exports exports = {
+	"uac_redirect",
+	DEFAULT_DLFLAGS, /* dlopen flags */
+	cmds,     /* Exported functions */
+	params,   /* Exported parameters */
+	0,        /* exported statistics */
+	0,        /* exported MI functions */
+	0,        /* exported pseudo-variables */
+	0,        /* extra processes */
+	redirect_init, /* Module initialization function */
+	0,
+	0,
+	child_init /* per-child init function */
+};
+
+
+
+int get_nr_max(char *s, unsigned char *max)
+{
+	unsigned short nr;
+	int err;
+
+	if ( s[0]=='*' && s[1]==0 ) {
+		/* is '*' -> infinit ;-) */
+		*max = 0;
+		return 0;
+	} else {
+		/* must be a positive number less than 255 */
+		nr = str2s(s, strlen(s), &err);
+		if (err==0){
+			if (nr>255){
+				LM_ERR("number too big <%d> (max=255)\n",nr);
+				return -1;
+			}
+			*max = (unsigned char)nr;
+			return 0;
+		}else{
+			LM_ERR("bad  number <%s>\n",s);
+			return -1;
+		}
+	}
+}
+
+
+static int get_redirect_fixup(void** param, int param_no)
+{
+	unsigned char maxb,maxt;
+	struct acc_param *accp;
+	cmd_function fct;
+	char *p;
+	char *s;
+
+	s = (char*)*param;
+	if (param_no==1) {
+		if ( (p=strchr(s,':'))!=0 ) {
+			/* have max branch also */
+			*p = 0;
+			if (get_nr_max(p+1, &maxb)!=0)
+				return E_UNSPEC;
+		} else {
+			maxb = 0; /* infinit */
+		}
+
+		/* get max total */
+		if (get_nr_max(s, &maxt)!=0)
+			return E_UNSPEC;
+
+		pkg_free(*param);
+		*param=(void*)(long)( (((unsigned short)maxt)<<8) | maxb);
+	} else if (param_no==2) {
+		/* acc function loaded? */
+		if (rd_acc_fct==0) {
+			/* must import the acc stuff */
+			if (acc_fct_s==0 || acc_fct_s[0]==0) {
+				LM_ERR("acc support enabled, but no acc function defined\n");
+				return E_UNSPEC;
+			}
+			fct = find_export(acc_fct_s, 2, REQUEST_ROUTE);
+			if ( fct==0 )
+				fct = find_export(acc_fct_s, 1, REQUEST_ROUTE);
+			if ( fct==0 ) {
+				LM_ERR("cannot import %s function; is acc loaded and proper "
+					"compiled?\n", acc_fct_s);
+				return E_UNSPEC;
+			}
+			rd_acc_fct = fct;
+		}
+		/* set the reason str */
+		accp = (struct acc_param*)pkg_malloc(sizeof(struct acc_param));
+		if (accp==0) {
+			LM_ERR("no more pkg mem\n");
+			return E_UNSPEC;
+		}
+		memset( accp, 0, sizeof(struct acc_param));
+		if (s!=0 && *s!=0) {
+			accp->reason.s = s;
+			accp->reason.len = strlen(s);
+		} else {
+			accp->reason.s = "n/a";
+			accp->reason.len = 3;
+		}
+		*param=(void*)accp;
+	}
+
+	return 0;
+}
+
+
+static int setf_fixup(void** param, int param_no)
+{
+	unsigned short nr;
+	regex_t *filter;
+	char *s;
+
+	s = (char*)*param;
+	if (param_no==1) {
+		/* compile the filter */
+		if (regexp_compile( s, &filter)<0) {
+			LM_ERR("cannot init filter <%s>\n", s);
+			return E_BAD_RE;
+		}
+		pkg_free(*param);
+		*param = (void*)filter;
+	} else if (param_no==2) {
+		if (s==0 || s[0]==0) {
+			nr = 0;
+		} else if (strcasecmp(s,"reset_all")==0) {
+			nr = RESET_ADDED|RESET_DEFAULT;
+		} else if (strcasecmp(s,"reset_default")==0) {
+			nr = RESET_DEFAULT;
+		} else if (strcasecmp(s,"reset_added")==0) {
+			nr = RESET_ADDED;
+		} else {
+			LM_ERR("unknown reset type <%s>\n",s);
+			return E_UNSPEC;
+		}
+		pkg_free(*param);
+		*param = (void*)(long)nr;
+	}
+
+	return 0;
+}
+
+
+
+static int regexp_compile(char *re_s, regex_t **re)
+{
+	*re = 0;
+	if (re_s==0 || strlen(re_s)==0 ) {
+		return 0;
+	} else {
+		if ((*re=pkg_malloc(sizeof(regex_t)))==0)
+			return E_OUT_OF_MEM;
+		if (regcomp(*re, re_s, REG_EXTENDED|REG_ICASE|REG_NEWLINE) ){
+			pkg_free(*re);
+			*re = 0;
+			LM_ERR("regexp_compile:bad regexp <%s>\n", re_s);
+			return E_BAD_RE;
+		}
+	}
+	return 0;
+}
+
+
+
+static int redirect_init(void)
+{
+	regex_t *filter;
+	void *p;
+
+	/* load the TM API */
+	if (load_tm_api(&rd_tmb)!=0) {
+		LM_ERR("failed to load TM API\n");
+		goto error;
+	}
+
+	p = (void*)acc_db_table;
+	/* fixup table name */
+	if(fixup_var_pve_str_12(&p, 1)<0) {
+		LM_ERR("failed to fixup acc db table\n");
+		goto error;
+	}
+	acc_db_table = p;
+
+	/* init filter */
+	init_filters();
+
+	/* what's the default rule? */
+	if (def_filter_s) {
+		if ( !strcasecmp(def_filter_s,ACCEPT_RULE_STR) ) {
+			set_default_rule( ACCEPT_RULE );
+		} else if ( !strcasecmp(def_filter_s,DENY_RULE_STR) ) {
+			set_default_rule( DENY_RULE );
+		} else {
+			LM_ERR("unknown default filter <%s>\n",def_filter_s);
+		}
+	}
+
+	/* if accept filter specify, compile it */
+	if (regexp_compile(accept_filter_s, &filter)<0) {
+		LM_ERR("failed to init accept filter\n");
+		goto error;
+	}
+	add_default_filter( ACCEPT_FILTER, filter);
+
+	/* if deny filter specify, compile it */
+	if (regexp_compile(deny_filter_s, &filter)<0) {
+		LM_ERR("failed to init deny filter\n");
+		goto error;
+	}
+	add_default_filter( DENY_FILTER, filter);
+
+	if(sruid_init(&_redirect_sruid, '-', "rdir", SRUID_INC)<0)
+		return -1;
+
+	return 0;
+error:
+	return -1;
+}
+
+static int child_init(int rank)
+{
+	if(sruid_init(&_redirect_sruid, '-', "rdir", SRUID_INC)<0)
+		return -1;
+	return 0;
+}
+
+static inline void msg_tracer(struct sip_msg* msg, int reset)
+{
+	static unsigned int id  = 0;
+	static unsigned int set = 0;
+
+	if (reset) {
+		set = 0;
+	} else {
+		if (set) {
+			if (id!=msg->id) {
+				LM_WARN("filters set but not used -> reseting to default\n");
+				reset_filters();
+				id = msg->id;
+			}
+		} else {
+			id = msg->id;
+			set = 1;
+		}
+	}
+}
+
+
+static int w_set_deny(struct sip_msg* msg, char *re, char *flags)
+{
+	msg_tracer( msg, 0);
+	return (add_filter( DENY_FILTER, (regex_t*)re, (int)(long)flags)==0)?1:-1;
+}
+
+
+static int w_set_accept(struct sip_msg* msg, char *re, char *flags)
+{
+	msg_tracer( msg, 0);
+	return (add_filter( ACCEPT_FILTER, (regex_t*)re, (int)(long)flags)==0)?1:-1;
+}
+
+
+static int w_get_redirect2(struct sip_msg* msg, char *max_c, char *reason)
+{
+	int n;
+	unsigned short max;
+
+	msg_tracer( msg, 0);
+	/* get the contacts */
+	max = (unsigned short)(long)max_c;
+	n = get_redirect(msg , (max>>8)&0xff, max&0xff, (struct acc_param*)reason, bflags);
+	reset_filters();
+	/* reset the tracer */
+	msg_tracer( msg, 1);
+
+	return n;
+}
+
+
+static int w_get_redirect1(struct sip_msg* msg, char *max_c, char *foo)
+{
+	return w_get_redirect2(msg, max_c, 0);
+}
+
diff --git a/modules/uid_auth_db/.cvsignore b/modules/uid_auth_db/.cvsignore
new file mode 100644
index 0000000..5f7969d
--- /dev/null
+++ b/modules/uid_auth_db/.cvsignore
@@ -0,0 +1 @@
+auth_db.7
diff --git a/modules/uid_auth_db/Makefile b/modules/uid_auth_db/Makefile
index 5efab20..3e94f9b 100644
--- a/modules/uid_auth_db/Makefile
+++ b/modules/uid_auth_db/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # Digest Authentication - Database support
 #
diff --git a/modules/uid_avp_db/Makefile b/modules/uid_avp_db/Makefile
index 8a5267f..0b9a74c 100644
--- a/modules/uid_avp_db/Makefile
+++ b/modules/uid_avp_db/Makefile
@@ -1,6 +1,5 @@
-# $Id$
 #
-# Digest Authentication - Database support
+# uid_avp_db
 #
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
diff --git a/modules/uid_domain/Makefile b/modules/uid_domain/Makefile
index f730b73..e1420ae 100644
--- a/modules/uid_domain/Makefile
+++ b/modules/uid_domain/Makefile
@@ -1,6 +1,5 @@
-# Makefile v 1.0 2002/12/27
 #
-# Domain module makefile
+# uid-Domain module makefile
 #
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
diff --git a/modules/uid_gflags/Makefile b/modules/uid_gflags/Makefile
index b536858..139ce7f 100644
--- a/modules/uid_gflags/Makefile
+++ b/modules/uid_gflags/Makefile
@@ -1,6 +1,5 @@
-# $Id$
 #
-# print example module makefile
+# uid-gflags module makefile
 #
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
diff --git a/modules/uid_gflags/README b/modules/uid_gflags/README
index 4997b42..4679fb7 100644
--- a/modules/uid_gflags/README
+++ b/modules/uid_gflags/README
@@ -1,4 +1,3 @@
-
 UID Gflags Module
 
 Jiri Kuthan
@@ -6,7 +5,7 @@ Jiri Kuthan
    <jiri at iptel.org>
 
    Copyright � 2004 FhG FOKUS
-     _________________________________________________________________
+     __________________________________________________________________
 
    Table of Contents
 
@@ -24,7 +23,7 @@ Jiri Kuthan
               3.3. is_ugflag(flag_num)
 
         4. FIFO Interface
-        5. XMLRPC Interface
+        5. RPC Interface
 
    List of Examples
 
@@ -47,18 +46,18 @@ Chapter 1. Admin Guide
         3.3. is_ugflag(flag_num)
 
    4. FIFO Interface
-   5. XMLRPC Interface
+   5. RPC Interface
 
 1. Overview
 
-   The  module implements global flags. The difference between the global
-   flags  and flags that can be used in the configuration file or AVPs is
-   that  they  the  scope  of  the global flags is not limited to the SIP
-   message  or  transaction  being  processed.  Global  flags  are always
+   The module implements global flags. The difference between the global
+   flags and flags that can be used in the configuration file or AVPs is
+   that they the scope of the global flags is not limited to the SIP
+   message or transaction being processed. Global flags are always
    available, their contents is not forgotten when a SIP transaction gets
-   destroyed in SER.
+   destroyed in Kamailio.
 
-   Global  flags  can  be  accessed  from  the  configuration script, for
+   Global flags can be accessed from the configuration script, for
    example:
 if (is_ugflag("1")) {
     t_relay_to_udp("10.0.0.1", "5060");
@@ -66,10 +65,10 @@ if (is_ugflag("1")) {
     t_relay_to_udp("10.0.0.2", "5060");
 };
 
-   The  value  of  the  global flags can be manipulated by external tools
-   such as the web interface of SER or cmd line administration tools. One
-   particular  application of global flags could be runtime configuration
-   changes without the need to restart SER.
+   The value of the global flags can be manipulated by external tools such
+   as the web interface of Kamailio or cmd line administration tools. One
+   particular application of global flags could be runtime configuration
+   changes without the need to restart Kamailio.
 
 2. Parameters
 
@@ -77,7 +76,7 @@ if (is_ugflag("1")) {
 
 2.1. initial (integer)
 
-   The  initial value of global flags. Each bit in the integer represents
+   The initial value of global flags. Each bit in the integer represents
    one flag.
 
    Default value is 0.
@@ -90,8 +89,8 @@ if (is_ugflag("1")) {
 
 3.1. set_gflag(flag_num)
 
-   Set  the  flag identified by flag_num to 1. The range of flag_num is 0
-   to 31.
+   Set the flag identified by flag_num to 1. The range of flag_num is 0 to
+   31.
 
    Example 1.1. set_ugflag usage
 ...
@@ -100,8 +99,8 @@ set_ugflag("2");
 
 3.2. reset_ugflag(flag_num)
 
-   Set  the  flag identified by flag_num to 0. The range of flag_num is 0
-   to 31.
+   Set the flag identified by flag_num to 0. The range of flag_num is 0 to
+   31.
 
    Example 1.2. reset_ugflag usage
 ...
@@ -110,38 +109,37 @@ reset_ugflag("2");
 
 3.3. is_ugflag(flag_num)
 
-   Returns  1  when  flag identified by flag_num is set, 0 otherwise. The
+   Returns 1 when flag identified by flag_num is set, 0 otherwise. The
    range of flag_num parameter is 0 to 31.
 
 4. FIFO Interface
 
-   The  state  of the global flags can be read and modified over the FIFO
-   interface  of SER. This module implements the following FIFO interface
-   functions:
+   The state of the global flags can be read and modified over the FIFO
+   interface of Kamailio. This module implements the following FIFO
+   interface functions:
      * set_gflag - Set the value of a flag to 1. The function accepts one
        parameter which is the number of the flag to be set.
      * reset_gflag - Reset the value of a flag to 0. The function accepts
        one parameter which is the number of the flag to be reset.
-     * is_gflag  -  Return  the status of a flag. The FIFO function would
-       return  TRUE  if  the  flag is set and FALSE if it is not set. The
-       only parameter of this function is the number of the flag.
-
-5. XMLRPC Interface
-
-   The state of the global flags can be read and modified over the XMLRPC
-   interface.  This  module  implements  the  following  XMLRPC interface
-   commands:
-     * gflags.set  -  Set  the value of a flag to 1. The function accepts
-       one parameter which is the number of the flag to be set.
-     * gflags.reset  -  Reset  the  value  of  a  flag to 0. The function
-       accepts one parameter which is the number of the flag to be reset.
-     * gflags.is_set  -  Return  the  status of a flag. The FIFO function
-       would  return  TRUE if the flag is set and FALSE if it is not set.
+     * is_gflag - Return the status of a flag. The FIFO function would
+       return TRUE if the flag is set and FALSE if it is not set. The only
+       parameter of this function is the number of the flag.
+
+5. RPC Interface
+
+   The state of the global flags can be read and modified over the RPC
+   interface. This module implements the following RPC interface commands:
+     * gflags.set - Set the value of a flag to 1. The function accepts one
+       parameter which is the number of the flag to be set.
+     * gflags.reset - Reset the value of a flag to 0. The function accepts
+       one parameter which is the number of the flag to be reset.
+     * gflags.is_set - Return the status of a flag. The FIFO function
+       would return TRUE if the flag is set and FALSE if it is not set.
        The only parameter of this function is the number of the flag.
      * gflags.flush - Flush the state of global flags into database.
      * gflags.dump - Return the status of all flags. The value is TRUE if
        the flag is set and FALSE if the flag is not set. The function has
        no parameters.
-     * global.reload  -  Reload  values  from global_attrs DB table. This
+     * global.reload - Reload values from global_attrs DB table. This
        function does not have any parameters. There is no return value on
        success.
diff --git a/modules/uid_gflags/doc/fifo.xml b/modules/uid_gflags/doc/fifo.xml
index 2116699..18d9b9b 100644
--- a/modules/uid_gflags/doc/fifo.xml
+++ b/modules/uid_gflags/doc/fifo.xml
@@ -1,6 +1,12 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
-   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+<!-- Include general documentation entities -->
+<!ENTITY % docentities SYSTEM "../../../docbook/entities.xml">
+%docentities;
+
+]>
 
 <section id="gflags.fifo" xmlns:xi="http://www.w3.org/2001/XInclude">
     <sectioninfo>
@@ -10,7 +16,7 @@
 
     <para>
 	The state of the global flags can be read and modified over the FIFO
-	interface of SER. This module implements the following FIFO interface
+	interface of &kamailio;. This module implements the following FIFO interface
 	functions:
     </para>
     <itemizedlist>
diff --git a/modules/uid_gflags/doc/functions.xml b/modules/uid_gflags/doc/functions.xml
index 912ea4c..1833fad 100644
--- a/modules/uid_gflags/doc/functions.xml
+++ b/modules/uid_gflags/doc/functions.xml
@@ -1,6 +1,12 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
-   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+<!-- Include general documentation entities -->
+<!ENTITY % docentities SYSTEM "../../../docbook/entities.xml">
+%docentities;
+
+]>
 
 <section id="uid_gflags.functions" xmlns:xi="http://www.w3.org/2001/XInclude">
     <sectioninfo>
diff --git a/modules/uid_gflags/doc/params.xml b/modules/uid_gflags/doc/params.xml
index 95bdb46..ccf651d 100644
--- a/modules/uid_gflags/doc/params.xml
+++ b/modules/uid_gflags/doc/params.xml
@@ -1,6 +1,12 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
-   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+<!-- Include general documentation entities -->
+<!ENTITY % docentities SYSTEM "../../../docbook/entities.xml">
+%docentities;
+
+]>
 
 <section id="gflags.parameters" xmlns:xi="http://www.w3.org/2001/XInclude">
     <sectioninfo>
@@ -8,7 +14,7 @@
 
     <title>Parameters</title>
 
-    <section id="initial">
+    <section id="gflags.p.initial">
 	<title><varname>initial</varname> (integer)</title>
 	<para>
 	    The initial value of global flags. Each bit in the integer
diff --git a/modules/uid_gflags/doc/uid_gflags.xml b/modules/uid_gflags/doc/uid_gflags.xml
index 0925619..5365e39 100644
--- a/modules/uid_gflags/doc/uid_gflags.xml
+++ b/modules/uid_gflags/doc/uid_gflags.xml
@@ -1,6 +1,12 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
-   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+<!-- Include general documentation entities -->
+<!ENTITY % docentities SYSTEM "../../../docbook/entities.xml">
+%docentities;
+
+]>
 
 <book id="gflags" xmlns:xi="http://www.w3.org/2001/XInclude">
     <bookinfo>
@@ -29,7 +35,7 @@
 	    or AVPs is that they the scope of the global flags is not limited
 	    to the SIP message or transaction being processed. Global flags are
 	    always available, their contents is not forgotten when a SIP
-	    transaction gets destroyed in SER.
+	    transaction gets destroyed in &kamailio;.
 	</para>
 	<para>
 	    Global flags can be accessed from the configuration script, for example:
@@ -43,9 +49,9 @@ if (is_ugflag("1")) {
 	</programlisting>
 	<para>
 	    The value of the global flags can be manipulated by external tools
-	    such as the web interface of SER or cmd line administration
+	    such as the web interface of &kamailio; or cmd line administration
 	    tools. One particular application of global flags could be runtime
-	    configuration changes without the need to restart SER.
+	    configuration changes without the need to restart &kamailio;.
 	</para>
     </section>
 
diff --git a/modules/uid_gflags/doc/xmlrpc.xml b/modules/uid_gflags/doc/xmlrpc.xml
index 8d78b91..3bd9bc6 100644
--- a/modules/uid_gflags/doc/xmlrpc.xml
+++ b/modules/uid_gflags/doc/xmlrpc.xml
@@ -1,16 +1,22 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
-   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+<!-- Include general documentation entities -->
+<!ENTITY % docentities SYSTEM "../../../docbook/entities.xml">
+%docentities;
+
+]>
 
 <section id="gflags.xmlrpc" xmlns:xi="http://www.w3.org/2001/XInclude">
     <sectioninfo>
     </sectioninfo>
 
-    <title>XMLRPC Interface</title>
+    <title>RPC Interface</title>
 
     <para>
-	The state of the global flags can be read and modified over the XMLRPC
-	interface. This module implements the following XMLRPC interface commands:
+	The state of the global flags can be read and modified over the RPC
+	interface. This module implements the following RPC interface commands:
     </para>
     <itemizedlist>
 	<listitem>
diff --git a/modules/uid_gflags/uid_gflags.c b/modules/uid_gflags/uid_gflags.c
index 21bf4a9..e639fd1 100644
--- a/modules/uid_gflags/uid_gflags.c
+++ b/modules/uid_gflags/uid_gflags.c
@@ -1,4 +1,4 @@
-/*$Id$
+/*
  *
  * gflags module: global flags; it keeps a bitmap of flags
  * in shared memory and may be used to change behaviour
@@ -12,19 +12,14 @@
  *
  * Copyright (C) 2004 FhG FOKUS
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -34,12 +29,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
 /*
- * History:
- * --------
- *  2004-09-09  initial module created (jiri)
- *  2006-12-04  added xmlrpc command global.reload for reloading of global_attrs
- *              db table (vlada)
- *
  * TODO
  * - flag range checking
  * - named flags (takes a protected name list)
diff --git a/modules/uid_uri_db/Makefile b/modules/uid_uri_db/Makefile
index 36f9659..37ff1cf 100644
--- a/modules/uid_uri_db/Makefile
+++ b/modules/uid_uri_db/Makefile
@@ -1,6 +1,5 @@
-# $Id$
 #
-# Various URI checks
+# uid-uri-db :: Various URI checks
 #
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
diff --git a/modules/uri_db/Makefile b/modules/uri_db/Makefile
index b22f6ab..b77e998 100644
--- a/modules/uri_db/Makefile
+++ b/modules/uri_db/Makefile
@@ -1,6 +1,5 @@
-# $Id$
 #
-# Various URI checks
+# uri-db Various URI checks
 #
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
diff --git a/modules/userblacklist/README b/modules/userblacklist/README
index cbedc95..affcbe9 100644
--- a/modules/userblacklist/README
+++ b/modules/userblacklist/README
@@ -14,7 +14,7 @@ Pawel Kuzak
    1&1 Internet AG
    <pawel.kuzak at 1und1.de>
 
-   Copyright © 2008 1&1 Internet AG
+   Copyright � 2008 1&1 Internet AG
      __________________________________________________________________
 
    Table of Contents
@@ -31,6 +31,18 @@ Pawel Kuzak
 
               3.1. use_domain (integer)
               3.2. match_mode (integer)
+              3.3. db_url (String)
+              3.4. userblacklist_table (String)
+              3.5. userblacklist_id_col (string)
+              3.6. userblacklist_username_col (string)
+              3.7. userblacklist_domain_col (string)
+              3.8. userblacklist_prefix_col (string)
+              3.9. userblacklist_whitelist_col (string)
+              3.10. globalblacklist_table (String)
+              3.11. globalblacklist_id_col (string)
+              3.12. globalblacklist_prefix_col (string)
+              3.13. globalblacklist_whitelist_col (string)
+              3.14. globalblacklist_description_col (string)
 
         4. Functions
 
@@ -51,44 +63,29 @@ Pawel Kuzak
 
               6.1. Database setup
 
-   2. Module parameter for database access.
-
-        1. db_url (String)
-        2. userblacklist_table (String)
-        3. userblacklist_id_col (string)
-        4. userblacklist_username_col (string)
-        5. userblacklist_domain_col (string)
-        6. userblacklist_prefix_col (string)
-        7. userblacklist_whitelist_col (string)
-        8. globalblacklist_table (String)
-        9. globalblacklist_id_col (string)
-        10. globalblacklist_prefix_col (string)
-        11. globalblacklist_whitelist_col (string)
-        12. globalblacklist_description_col (string)
-
    List of Examples
 
    1.1. Set use_domain parameter
    1.2. Set match_mode parameter
-   1.3. check_user_blacklist usage
-   1.4. check_user_blacklist usage
-   1.5. check_blacklist usage
-   1.6. check_whitelist usage
-   1.7. reload_blacklists usage
-   1.8. Example database content - globalblacklist table
-   1.9. Example database content - userblacklist table
-   2.1. Set db_url parameter
-   2.2. Set userblacklist_table parameter
-   2.3. Set userblacklist_id_col parameter
-   2.4. Set userblacklist_username_col parameter
-   2.5. Set userblacklist_domain_col parameter
-   2.6. Set userblacklist_prefix_col parameter
-   2.7. Set userblacklist_whitelist_col parameter
-   2.8. Set globalblacklist_table parameter
-   2.9. Set globalblacklist_id_col parameter
-   2.10. Set globalblacklist_prefix_col parameter
-   2.11. Set globalblacklist_whitelist_col parameter
-   2.12. Set globalblacklist_description_col parameter
+   1.3. Set db_url parameter
+   1.4. Set userblacklist_table parameter
+   1.5. Set userblacklist_id_col parameter
+   1.6. Set userblacklist_username_col parameter
+   1.7. Set userblacklist_domain_col parameter
+   1.8. Set userblacklist_prefix_col parameter
+   1.9. Set userblacklist_whitelist_col parameter
+   1.10. Set globalblacklist_table parameter
+   1.11. Set globalblacklist_id_col parameter
+   1.12. Set globalblacklist_prefix_col parameter
+   1.13. Set globalblacklist_whitelist_col parameter
+   1.14. Set globalblacklist_description_col parameter
+   1.15. check_user_blacklist usage
+   1.16. check_user_blacklist usage
+   1.17. check_blacklist usage
+   1.18. check_whitelist usage
+   1.19. reload_blacklist usage
+   1.20. Example database content - globalblacklist table
+   1.21. Example database content - userblacklist table
 
 Chapter 1. Admin Guide
 
@@ -104,6 +101,18 @@ Chapter 1. Admin Guide
 
         3.1. use_domain (integer)
         3.2. match_mode (integer)
+        3.3. db_url (String)
+        3.4. userblacklist_table (String)
+        3.5. userblacklist_id_col (string)
+        3.6. userblacklist_username_col (string)
+        3.7. userblacklist_domain_col (string)
+        3.8. userblacklist_prefix_col (string)
+        3.9. userblacklist_whitelist_col (string)
+        3.10. globalblacklist_table (String)
+        3.11. globalblacklist_id_col (string)
+        3.12. globalblacklist_prefix_col (string)
+        3.13. globalblacklist_whitelist_col (string)
+        3.14. globalblacklist_description_col (string)
 
    4. Functions
 
@@ -133,17 +142,18 @@ Chapter 1. Admin Guide
 
    An additional functionality that this module provides is the ability to
    handle global blacklists. This lists are loaded on startup into memory,
-   thus providing a better performance then in the userblacklist case.
-   This global blacklists are useful to only allow calls to certain
+   thus providing a better performance than the userblacklist case. These
+   global blacklists are useful to allow only calls to certain
    international destinations, i.e. block all not whitelisted numbers.
-   They could also used to prevent the blacklisting of important numbers,
-   as whitelisting is supported too. This is useful for example to prevent
-   the customer from blocking emergency call number or service hotlines.
+   They could also be used to prevent the blacklisting of important
+   numbers, as whitelisting is supported too. This is useful for example
+   to prevent the customer from blocking emergency call number or service
+   hotlines.
 
-   The module exports three functions, check_blacklist
-   check_user_blacklist and check_user_whitelist for usage in the config
-   file. Furthermore its provide a FIFO function to reload the global
-   blacklist cache.
+   The module exports four functions, check_blacklist, check_whitelist,
+   check_user_blacklist and check_user_whitelist for usage in the
+   configuration file. Furthermore it provides a MI function to reload the
+   global blacklist cache.
 
    Please note that only numerical strings for matching are supported at
    the moment (the used library supports this already, but its not yet
@@ -160,7 +170,7 @@ Chapter 1. Admin Guide
 
    The module depends on the following modules (in the other words the
    listed modules must be loaded before this module):
-     * database -- Any database module
+     * database -- Any db_* database module
 
 2.2. External Libraries or Applications
 
@@ -172,17 +182,29 @@ Chapter 1. Admin Guide
 
    3.1. use_domain (integer)
    3.2. match_mode (integer)
+   3.3. db_url (String)
+   3.4. userblacklist_table (String)
+   3.5. userblacklist_id_col (string)
+   3.6. userblacklist_username_col (string)
+   3.7. userblacklist_domain_col (string)
+   3.8. userblacklist_prefix_col (string)
+   3.9. userblacklist_whitelist_col (string)
+   3.10. globalblacklist_table (String)
+   3.11. globalblacklist_id_col (string)
+   3.12. globalblacklist_prefix_col (string)
+   3.13. globalblacklist_whitelist_col (string)
+   3.14. globalblacklist_description_col (string)
 
 3.1. use_domain (integer)
 
-   If set to non-zero value, the domain column in the userblacklist is
-   used.
+   If set to non-zero value, the domain column in the userblacklist table
+   is used.
 
-   Default value is “0”.
+   Default value is "0".
 
    Example 1.1. Set use_domain parameter
 ...
-modparam("userblacklist", "use_domain", 0)
+modparam("userblacklist", "use_domain", 1)
 ...
 
 3.2. match_mode (integer)
@@ -190,17 +212,134 @@ modparam("userblacklist", "use_domain", 0)
    The number of individual characters that are used for matching. Valid
    values are 10 or 128. When you specifiy 10, only digits will be used
    for matching, this operation mode is equivalent to the old behaviour.
-   When configured with 128, all standard ascii chars are available for
+   When configured with 128, all standard ASCII chars are available for
    matching. Please be aware that memory requirements for storing the
    routing tree in shared memory will also increase by a factor of 12.8.
 
-   Default value is “10”.
+   Default value is "10".
 
    Example 1.2. Set match_mode parameter
 ...
 modparam("userblacklist", "match_mode", 128)
 ...
 
+3.3. db_url (String)
+
+   URL to the database containing the data.
+
+   Default value is "mysql://kamailioro:kamailioro@localhost/kamailio".
+
+   Example 1.3. Set db_url parameter
+...
+modparam("userblacklist", "db_url", "dbdriver://username:password@dbhost/dbname"
+)
+...
+
+3.4. userblacklist_table (String)
+
+   Name of the userblacklist table for the userblacklist module.
+
+   Default value is "userblacklist".
+
+   Example 1.4. Set userblacklist_table parameter
+...
+modparam("userblacklist", "userblacklist_table", "userblacklist")
+...
+
+3.5. userblacklist_id_col (string)
+
+   unique ID
+
+   Example 1.5. Set userblacklist_id_col parameter
+...
+modparam("userblacklist", "userblacklist_id_col", "id")
+...
+
+3.6. userblacklist_username_col (string)
+
+   The user that is used for the blacklist lookup.
+
+   Example 1.6. Set userblacklist_username_col parameter
+...
+modparam("userblacklist", "userblacklist_username_col", "username")
+...
+
+3.7. userblacklist_domain_col (string)
+
+   The domain that is used for the blacklist lookup.
+
+   Example 1.7. Set userblacklist_domain_col parameter
+...
+modparam("userblacklist", "userblacklist_domain_col", "domain")
+...
+
+3.8. userblacklist_prefix_col (string)
+
+   The prefix that is matched for the blacklist.
+
+   Example 1.8. Set userblacklist_prefix_col parameter
+...
+modparam("userblacklist", "userblacklist_prefix_col", "prefix")
+...
+
+3.9. userblacklist_whitelist_col (string)
+
+   Specify if this a blacklist (0) or a whitelist (1) entry.
+
+   Example 1.9. Set userblacklist_whitelist_col parameter
+...
+modparam("userblacklist", "userblacklist_whitelist_col", "whitelist")
+...
+
+3.10. globalblacklist_table (String)
+
+   Name of the globalblacklist table for the userblacklist module. Please
+   note that this table is used when the check_blacklist function is
+   called with no parameters.
+
+   Default value is "globalblacklist".
+
+   Example 1.10. Set globalblacklist_table parameter
+...
+modparam("userblacklist", "globalblacklist_table", "globalblacklist")
+...
+
+3.11. globalblacklist_id_col (string)
+
+   unique ID
+
+   Example 1.11. Set globalblacklist_id_col parameter
+...
+modparam("userblacklist", "globalblacklist_id_col", "id")
+...
+
+3.12. globalblacklist_prefix_col (string)
+
+   The prefix that is matched for the blacklist.
+
+   Example 1.12. Set globalblacklist_prefix_col parameter
+...
+modparam("userblacklist", "globalblacklist_prefix_col", "prefix")
+...
+
+3.13. globalblacklist_whitelist_col (string)
+
+   Specify if this a blacklist (0) or a whitelist (1) entry.
+
+   Example 1.13. Set globalblacklist_whitelist_col parameter
+...
+modparam("userblacklist", "globalblacklist_whitelist_col", "whitelist")
+...
+
+3.14. globalblacklist_description_col (string)
+
+   A comment for the entry.
+
+   Example 1.14. Set globalblacklist_description_col parameter
+...
+modparam("userblacklist", "globalblacklist_description_col", "description")
+...
+
 4. Functions
 
    4.1. check_user_blacklist (string user, string domain, string number,
@@ -212,7 +351,7 @@ modparam("userblacklist", "match_mode", 128)
    4.3. check_blacklist ([string table])
    4.4. check_whitelist (string table)
 
-4.1.  check_user_blacklist (string user, string domain, string number, string
+4.1. check_user_blacklist (string user, string domain, string number, string
 table)
 
    Finds the longest prefix that matches the request URI user (or the
@@ -220,10 +359,10 @@ table)
    If a match is found and it is not set to whitelist, false is returned.
    Otherwise, true is returned. Pseudo-variables or AVPs can be used for
    the user, domain and number parameters. The number and table variables
-   are optional, the defaults are used if they are ommited. The number
+   are optional, the defaults are used if they are omitted. The number
    parameter can be used to check for example against the from URI user.
 
-   Example 1.3. check_user_blacklist usage
+   Example 1.15. check_user_blacklist usage
 ...
 $avp(i:80) = $rU;
 # rewrite the R-URI
@@ -233,7 +372,7 @@ if (!check_user_blacklist("$avp(i:80)", "$avp(i:82)")) {
 }
 ...
 
-4.2.  check_user_whitelist (string user, string domain, string number, string
+4.2. check_user_whitelist (string user, string domain, string number, string
 table)
 
    Finds the longest prefix that matches the request URI user (or the
@@ -241,10 +380,10 @@ table)
    If a match is found and it is set to whitelist, true is returned.
    Otherwise, false is returned. Pseudo-variables or AVPs can be used for
    the user, domain and number parameters. The number and table variables
-   are optional, the defaults are used if they are ommited. The number
+   are optional, the defaults are used if they are omitted. The number
    parameter can be used to check for example against the from URI user.
 
-   Example 1.4. check_user_blacklist usage
+   Example 1.16. check_user_blacklist usage
 ...
 $avp(i:80) = $rU;
 # rewrite the R-URI
@@ -254,14 +393,14 @@ if (!check_user_whitelist("$avp(i:80)", "$avp(i:82)")) {
 }
 ...
 
-4.3.  check_blacklist ([string table])
+4.3. check_blacklist ([string table])
 
    Finds the longest prefix that matches the request URI for the given
    table. If a match is found and it is not set to whitelist, false is
    returned. Otherwise, true is returned. If no table is given, then
    globalblacklist_table is used.
 
-   Example 1.5. check_blacklist usage
+   Example 1.17. check_blacklist usage
 ...
 if (!check_blacklist("globalblacklist")) {
         sl_send_reply("403", "Forbidden");
@@ -269,13 +408,13 @@ if (!check_blacklist("globalblacklist")) {
 }
 ...
 
-4.4.  check_whitelist (string table)
+4.4. check_whitelist (string table)
 
    Finds the longest prefix that matches the request URI for the given
    table. If a match is found and it is set to whitelist, true is
    returned. Otherwise, false is returned.
 
-   Example 1.6. check_whitelist usage
+   Example 1.18. check_whitelist usage
 ...
 if (!check_whitelist("globalblacklist")) {
         sl_send_reply("403", "Forbidden");
@@ -287,12 +426,12 @@ if (!check_whitelist("globalblacklist")) {
 
    5.1. reload_blacklist
 
-5.1.  reload_blacklist
+5.1. reload_blacklist
 
    Reload the internal global blacklist cache. This is necessary after the
    database tables for the global blacklist have been changed.
 
-   Example 1.7. reload_blacklists usage
+   Example 1.19. reload_blacklist usage
 ...
 kamctl fifo reload_blacklist
 ...
@@ -303,10 +442,10 @@ kamctl fifo reload_blacklist
 
 6.1. Database setup
 
-   Before running Kamailio with userblacklist, you have to setup the
-   database table where the module will read the blacklist data. For that,
-   if the table was not created by the installation script or you choose
-   to install everything by yourself you can use the
+   Before running Kamailio with the userblacklist module, you have to
+   setup the database table where the module will read the blacklist data.
+   For that, if the table was not created by the installation script or
+   you choose to install everything by yourself you can use the
    userblacklist-create.sql SQL script in the database directories in the
    kamailio/scripts folder as template. Database and table name can be set
    with module parameters so they can be changed, but the name of the
@@ -314,7 +453,7 @@ kamctl fifo reload_blacklist
    complete database documentation on the project webpage,
    http://www.kamailio.org/docs/db-tables/kamailio-db-devel.html.
 
-   Example 1.8. Example database content - globalblacklist table
+   Example 1.20. Example database content - globalblacklist table
 ...
 +----+-----------+-----------+
 | id | prefix    | whitelist |
@@ -327,11 +466,11 @@ kamctl fifo reload_blacklist
 ...
 
    This table will setup a global blacklist for all numbers, only allowing
-   calls starting with “1”. Numbers that starting with “123456” and
-   “123455787” are also blacklisted, because the longest prefix will be
+   calls starting with "1". Numbers that starts with "123456" and
+   "123455787" are also blacklisted, because the longest prefix will be
    matched.
 
-   Example 1.9. Example database content - userblacklist table
+   Example 1.21. Example database content - userblacklist table
 ...
 +----+----------------+-------------+-----------+-----------+
 | id | username       | domain      | prefix    | whitelist |
@@ -347,141 +486,7 @@ kamctl fifo reload_blacklist
 ...
 
    This table will setup user specific blacklists for certain usernames.
-   For example for user “49721123456788” the prefix “1234” will be not
-   allowed, but the number “123456788” is allowed. Additionally a domain
+   For example for user "49721123456788" the prefix "1234" will be not
+   allowed, but the number "123456788" is allowed. Additionally a domain
    could be specified that is used for username matching if the
-   “use_domain” parameter is set.
-
-Chapter 2. Module parameter for database access.
-
-   Table of Contents
-
-   1. db_url (String)
-   2. userblacklist_table (String)
-   3. userblacklist_id_col (string)
-   4. userblacklist_username_col (string)
-   5. userblacklist_domain_col (string)
-   6. userblacklist_prefix_col (string)
-   7. userblacklist_whitelist_col (string)
-   8. globalblacklist_table (String)
-   9. globalblacklist_id_col (string)
-   10. globalblacklist_prefix_col (string)
-   11. globalblacklist_whitelist_col (string)
-   12. globalblacklist_description_col (string)
-
-1. db_url (String)
-
-   URL to the database containing the data.
-
-   Default value is “mysql://kamailioro:kamailioro@localhost/kamailio”.
-
-   Example 2.1. Set db_url parameter
-...
-modparam("userblacklist", "db_url", "dbdriver://username:password@dbhost/dbname"
-)
-...
-
-2. userblacklist_table (String)
-
-   Name of the userblacklist table for the userblacklist module.
-
-   Default value is “userblacklist”.
-
-   Example 2.2. Set userblacklist_table parameter
-...
-modparam("userblacklist", "userblacklist_table", "userblacklist")
-...
-
-3. userblacklist_id_col (string)
-
-   unique ID
-
-   Example 2.3. Set userblacklist_id_col parameter
-...
-modparam("userblacklist", "userblacklist_id_col", "id")
-...
-
-4. userblacklist_username_col (string)
-
-   The user that is used for the blacklist lookup.
-
-   Example 2.4. Set userblacklist_username_col parameter
-...
-modparam("userblacklist", "userblacklist_username_col", "username")
-...
-
-5. userblacklist_domain_col (string)
-
-   The domain that is used for the blacklist lookup.
-
-   Example 2.5. Set userblacklist_domain_col parameter
-...
-modparam("userblacklist", "userblacklist_domain_col", "domain")
-...
-
-6. userblacklist_prefix_col (string)
-
-   The prefix that is matched for the blacklist.
-
-   Example 2.6. Set userblacklist_prefix_col parameter
-...
-modparam("userblacklist", "userblacklist_prefix_col", "prefix")
-...
-
-7. userblacklist_whitelist_col (string)
-
-   Specify if this a blacklist (0) or a whitelist (1) entry.
-
-   Example 2.7. Set userblacklist_whitelist_col parameter
-...
-modparam("userblacklist", "userblacklist_whitelist_col", "whitelist")
-...
-
-8. globalblacklist_table (String)
-
-   Name of the globalblacklist table for the userblacklist module. Please
-   note that this table is used when the check_blacklist function is
-   called with no parameters.
-
-   Default value is “globalblacklist”.
-
-   Example 2.8. Set globalblacklist_table parameter
-...
-modparam("userblacklist", "globalblacklist_table", "globalblacklist")
-...
-
-9. globalblacklist_id_col (string)
-
-   unique ID
-
-   Example 2.9. Set globalblacklist_id_col parameter
-...
-modparam("userblacklist", "globalblacklist_id_col", "id")
-...
-
-10. globalblacklist_prefix_col (string)
-
-   The prefix that is matched for the blacklist.
-
-   Example 2.10. Set globalblacklist_prefix_col parameter
-...
-modparam("userblacklist", "globalblacklist_prefix_col", "prefix")
-...
-
-11. globalblacklist_whitelist_col (string)
-
-   Specify if this a blacklist (0) or a whitelist (1) entry.
-
-   Example 2.11. Set globalblacklist_whitelist_col parameter
-...
-modparam("userblacklist", "globalblacklist_whitelist_col", "whitelist")
-...
-
-12. globalblacklist_description_col (string)
-
-   A comment for the entry.
-
-   Example 2.12. Set globalblacklist_description_col parameter
-...
-modparam("userblacklist", "globalblacklist_description_col", "description")
-...
+   "use_domain" parameter is set.
diff --git a/modules/userblacklist/db.c b/modules/userblacklist/db.c
index b4d8d42..bebb574 100644
--- a/modules/userblacklist/db.c
+++ b/modules/userblacklist/db.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2007 1&1 Internet AG
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/userblacklist/db.h b/modules/userblacklist/db.h
index 26a3ab7..bc463e3 100644
--- a/modules/userblacklist/db.h
+++ b/modules/userblacklist/db.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2007 1&1 Internet AG
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/userblacklist/db_userblacklist.c b/modules/userblacklist/db_userblacklist.c
index 09f5143..cb8fcd5 100644
--- a/modules/userblacklist/db_userblacklist.c
+++ b/modules/userblacklist/db_userblacklist.c
@@ -1,4 +1,3 @@
-
 /*!
  * \file
  * \ingroup db
diff --git a/modules/userblacklist/db_userblacklist.h b/modules/userblacklist/db_userblacklist.h
index ccf1475..87b31c9 100644
--- a/modules/userblacklist/db_userblacklist.h
+++ b/modules/userblacklist/db_userblacklist.h
@@ -1,4 +1,3 @@
-
 /*!
  * \file
  * \ingroup db
diff --git a/modules/userblacklist/doc/userblacklist.xml b/modules/userblacklist/doc/userblacklist.xml
index bfb652f..ef62472 100644
--- a/modules/userblacklist/doc/userblacklist.xml
+++ b/modules/userblacklist/doc/userblacklist.xml
@@ -32,6 +32,5 @@
 	</bookinfo>
 	<toc></toc>
 	<xi:include href="userblacklist_admin.xml"/>
-	<xi:include href="userblacklist_db.xml"/>
 	
 </book>
diff --git a/modules/userblacklist/doc/userblacklist_admin.xml b/modules/userblacklist/doc/userblacklist_admin.xml
index 6116670..649e2ab 100644
--- a/modules/userblacklist/doc/userblacklist_admin.xml
+++ b/modules/userblacklist/doc/userblacklist_admin.xml
@@ -21,18 +21,19 @@
 	<para>
 	An additional functionality that this module provides is the ability
 	to handle global blacklists. This lists are loaded on startup into
-	memory, thus providing a better performance then in the userblacklist
-	case. This global blacklists are useful to only allow calls to certain 
+	memory, thus providing a better performance than the userblacklist
+	case. These global blacklists are useful to allow only calls to certain 
 	international destinations, i.e. block all not whitelisted numbers.
-	They could also used to prevent the blacklisting of important	
+	They could also be used to prevent the blacklisting of important	
 	numbers, as whitelisting is supported too. This is useful for example
 	to prevent the customer from blocking emergency call number or service
 	hotlines.
 	</para>
 	<para>
-	The module exports three functions, <emphasis>check_blacklist</emphasis>
-	<emphasis>check_user_blacklist</emphasis> and <emphasis>check_user_whitelist</emphasis>
-	for usage in the config file. Furthermore its provide a FIFO function to
+	The module exports four functions, <function>check_blacklist</function>,
+	<function>check_whitelist</function>,
+	<function>check_user_blacklist</function> and <function>check_user_whitelist</function>
+	for usage in the configuration file. Furthermore it provides a MI function to
 	reload the global blacklist cache.
 	</para>
 	<para>
@@ -53,7 +54,8 @@
 			</para>
 			<itemizedlist>
 			<listitem>
-				<para><emphasis>database</emphasis> -- Any database module</para>
+				<para><emphasis>database</emphasis> 
+				-- Any db_* database module</para>
 			</listitem>
 			</itemizedlist>
 		</section>
@@ -72,12 +74,13 @@
 	</section>
 
 
-	<section>
+	<section  xmlns:xi="http://www.w3.org/2001/XInclude">
 	<title>Parameters</title>
-    <section>
+    	<section id="userblacklist.p.use_domain">
 	    <title><varname>use_domain</varname> (integer)</title>
 	    <para>
-			If set to non-zero value, the domain column in the userblacklist is used.
+			If set to non-zero value, the domain column in the
+			userblacklist table is used.
 	    </para>
 	    <para>
 		    <emphasis>
@@ -88,19 +91,20 @@
 		    <title>Set <varname>use_domain</varname> parameter</title>
 		    <programlisting format="linespecific">
 ...
-modparam("userblacklist", "use_domain", 0)
+modparam("userblacklist", "use_domain", 1)
 ...
 		    </programlisting>
 	    </example>
     </section>
-    <section>
+    <section id="userblacklist.p.match_mode">
     	    <title><varname>match_mode</varname> (integer)</title>
 	    <para>
-The number of individual characters that are used for matching. 
-Valid values are 10 or 128. When you specifiy 10, only digits will be used for matching, 
-this operation mode is equivalent to the old behaviour. When configured with 128, 
-all standard ascii chars are available for matching. Please be aware that memory 
-requirements for storing the routing tree in shared memory will also increase by a factor of 12.8.
+		The number of individual characters that are used for matching. 
+		Valid values are 10 or 128. When you specifiy 10, only digits will be used for matching, 
+		this operation mode is equivalent to the old behaviour. When configured with 128, 
+		all standard ASCII chars are available for matching. Please be aware that memory 
+		requirements for storing the routing tree in shared memory will also
+		increase by a factor of 12.8.
 	    </para>
 	    <para>
 		    <emphasis>
@@ -117,13 +121,170 @@ modparam("userblacklist", "match_mode", 128)
 	    </example>
     </section>
     
+  <section id="userblacklist.p.db_url">
+    <title><varname>db_url</varname> (String)</title>
+    <para>URL to the database containing the data.</para>
+    <para>
+      <emphasis>Default value is <quote>&defaultrodb;</quote>.</emphasis>
+    </para>
+    <example>
+      <title>Set <varname>db_url</varname> parameter</title>
+      <programlisting format="linespecific">
+...
+modparam("userblacklist", "db_url", "dbdriver://username:password@dbhost/dbname")
+...
+</programlisting>
+    </example>
+  </section>
+  <section>
+    <title><varname>userblacklist_table</varname> (String)</title>
+    <para>Name of the userblacklist table for the userblacklist module.</para>
+    <para>
+      <emphasis>Default value is <quote>userblacklist</quote>.</emphasis>
+    </para>
+    <example>
+      <title>Set <varname>userblacklist_table</varname> parameter</title>
+      <programlisting format="linespecific">
+...
+modparam("userblacklist", "userblacklist_table", "userblacklist")
+...
+</programlisting>
+    </example>
+  </section>
+  <section>
+    <title><varname>userblacklist_id_col</varname> (string)</title>
+    <para>unique ID</para>
+    <example>
+      <title>Set <varname>userblacklist_id_col</varname> parameter</title>
+      <programlisting format="linespecific">
+...
+modparam("userblacklist", "userblacklist_id_col", "id")
+...
+</programlisting>
+    </example>
+  </section>
+  <section>
+    <title><varname>userblacklist_username_col</varname> (string)</title>
+    <para>The user that is used for the blacklist lookup.</para>
+    <example>
+      <title>Set <varname>userblacklist_username_col</varname> parameter</title>
+      <programlisting format="linespecific">
+...
+modparam("userblacklist", "userblacklist_username_col", "username")
+...
+</programlisting>
+    </example>
+  </section>
+  <section>
+    <title><varname>userblacklist_domain_col</varname> (string)</title>
+    <para>The domain that is used for the blacklist lookup.</para>
+    <example>
+      <title>Set <varname>userblacklist_domain_col</varname> parameter</title>
+      <programlisting format="linespecific">
+...
+modparam("userblacklist", "userblacklist_domain_col", "domain")
+...
+</programlisting>
+    </example>
+  </section>
+  <section>
+    <title><varname>userblacklist_prefix_col</varname> (string)</title>
+    <para>The prefix that is matched for the blacklist.</para>
+    <example>
+      <title>Set <varname>userblacklist_prefix_col</varname> parameter</title>
+      <programlisting format="linespecific">
+...
+modparam("userblacklist", "userblacklist_prefix_col", "prefix")
+...
+</programlisting>
+    </example>
+  </section>
+  <section>
+    <title><varname>userblacklist_whitelist_col</varname> (string)</title>
+    <para>Specify if this a blacklist (0) or a whitelist (1) entry.</para>
+    <example>
+      <title>Set <varname>userblacklist_whitelist_col</varname> parameter</title>
+      <programlisting format="linespecific">
+...
+modparam("userblacklist", "userblacklist_whitelist_col", "whitelist")
+...
+</programlisting>
+    </example>
+  </section>
+  <section>
+    <title><varname>globalblacklist_table</varname> (String)</title>
+    <para>Name of the globalblacklist table for the userblacklist module.
+    Please note that this table is used when the check_blacklist
+	function is called with no parameters.</para>
+    <para>
+      <emphasis>Default value is <quote>globalblacklist</quote>.</emphasis>
+    </para>
+    <example>
+      <title>Set <varname>globalblacklist_table</varname> parameter</title>
+      <programlisting format="linespecific">
+...
+modparam("userblacklist", "globalblacklist_table", "globalblacklist")
+...
+</programlisting>
+    </example>
+  </section>
+  <section>
+    <title><varname>globalblacklist_id_col</varname> (string)</title>
+    <para>unique ID</para>
+    <example>
+      <title>Set <varname>globalblacklist_id_col</varname> parameter</title>
+      <programlisting format="linespecific">
+...
+modparam("userblacklist", "globalblacklist_id_col", "id")
+...
+</programlisting>
+    </example>
+  </section>
+  <section>
+    <title><varname>globalblacklist_prefix_col</varname> (string)</title>
+    <para>The prefix that is matched for the blacklist.</para>
+    <example>
+      <title>Set <varname>globalblacklist_prefix_col</varname> parameter</title>
+      <programlisting format="linespecific">
+...
+modparam("userblacklist", "globalblacklist_prefix_col", "prefix")
+...
+</programlisting>
+    </example>
+  </section>
+  <section>
+    <title><varname>globalblacklist_whitelist_col</varname> (string)</title>
+    <para>Specify if this a blacklist (0) or a whitelist (1) entry.</para>
+    <example>
+      <title>Set <varname>globalblacklist_whitelist_col</varname> parameter</title>
+      <programlisting format="linespecific">
+...
+modparam("userblacklist", "globalblacklist_whitelist_col", "whitelist")
+...
+</programlisting>
+    </example>
+  </section>
+
+  <section>
+    <title><varname>globalblacklist_description_col</varname> (string)</title>
+    <para>A comment for the entry.</para>
+    <example>
+      <title>Set <varname>globalblacklist_description_col</varname> parameter</title>
+      <programlisting format="linespecific">
+...
+modparam("userblacklist", "globalblacklist_description_col", "description")
+...
+</programlisting>
+    </example>
+  </section>
 
 </section>
 <section>
 	<title>Functions</title>
-	<section>
+    	<section id="userblacklist.f.check_user_blacklist">
 	    <title>
-		<function moreinfo="none">check_user_blacklist (string user, string domain, string number, string table)</function>
+		<function moreinfo="none">check_user_blacklist
+		(string user, string domain, string number, string table)</function>
 	    </title>
 	    <para>
 		Finds the longest prefix that matches the request URI user (or the number
@@ -131,7 +292,7 @@ modparam("userblacklist", "match_mode", 128)
 		If a match is found and it is not set to whitelist, false is returned.
 		Otherwise, true is returned. Pseudo-variables or AVPs can be used for
 		the user, domain and number parameters. The number and table variables
-		are optional, the defaults are used if they are ommited. The number
+		are optional, the defaults are used if they are omitted. The number
 		parameter can be used to check for example against the from URI user.
 	    </para>
 	<example>
@@ -148,9 +309,10 @@ if (!check_user_blacklist("$avp(i:80)", "$avp(i:82)")) {
 		</programlisting>
 	    </example>
 	</section>
-	<section>
+    	<section id="userblacklist.f.check_user_whitelist">
 	    <title>
-		<function moreinfo="none">check_user_whitelist (string user, string domain, string number, string table)</function>
+		<function moreinfo="none">check_user_whitelist
+		(string user, string domain, string number, string table)</function>
 	    </title>
 	    <para>
 		Finds the longest prefix that matches the request URI user (or the number
@@ -158,7 +320,7 @@ if (!check_user_blacklist("$avp(i:80)", "$avp(i:82)")) {
 		If a match is found and it is set to whitelist, true is returned.
 		Otherwise, false is returned. Pseudo-variables or AVPs can be used for
 		the user, domain and number parameters. The number and table variables
-		are optional, the defaults are used if they are ommited. The number
+		are optional, the defaults are used if they are omitted. The number
 		parameter can be used to check for example against the from URI user.
 	    </para>
 	<example>
@@ -175,7 +337,7 @@ if (!check_user_whitelist("$avp(i:80)", "$avp(i:82)")) {
 		</programlisting>
 	    </example>
 	</section>
-	<section>
+    	<section id="userblacklist.f.check_blacklist">
 	    <title>
 		<function moreinfo="none">check_blacklist ([string table])</function>
 	    </title>
@@ -197,7 +359,7 @@ if (!check_blacklist("globalblacklist")) {
 		</programlisting>
 	    </example>
 	</section>
-	<section>
+    	<section id="userblacklist.f.check_whitelist">
 	    <title>
 		<function moreinfo="none">check_whitelist (string table)</function>
 	    </title>
@@ -221,34 +383,148 @@ if (!check_whitelist("globalblacklist")) {
 </section>
 
 <section>
-	    <title><acronym>MI</acronym> Commands</title>
+	<title><acronym>MI</acronym> Commands</title>
 		<section>
-	    <title>
-		<function moreinfo="none">reload_blacklist</function>
-	    </title>
-	    <para>
-		Reload the internal global blacklist cache. This is necessary after
-		the database tables for the global blacklist have been changed.
-	    </para>
-	<example>
-		<title><function>reload_blacklists</function> usage</title>
-		<programlisting format="linespecific">
-...
-&ctltool; fifo reload_blacklist
-...
-		</programlisting>
-	    </example>
-	</section>
+			<title>
+				<function moreinfo="none">reload_blacklist</function>
+			</title>
+			<para>
+				Reload the internal global blacklist cache. This is necessary after
+				the database tables for the global blacklist have been changed.
+			</para>
+			<example>
+				<title><function>reload_blacklist</function> usage</title>
+				<programlisting format="linespecific">
+					...
+					&ctltool; fifo reload_blacklist
+					...
+				</programlisting>
+	    		</example>
+		</section>
+
+		<section>
+			<title>
+				<function moreinfo="none">dump_blacklist</function>
+			</title>
+			<para>
+				Dumps the default, in memory, global_blacklist content to stdout.
+				Note that a reload_blacklist should be issued before, 
+				in order to see the latest content of the database.
+			</para>
+			<example>
+				<title><function>dump_blacklist</function> usage</title>
+				<programlisting format="linespecific">
+					...
+					&ctltool; fifo reload_blacklist
+					&ctltool; fifo dump_blacklist
+					...
+				</programlisting>
+	    		</example>
+		</section>
+
+		<section>
+			<title>
+				<function moreinfo="none">check_blacklist prefix</function>
+			</title>
+			<para>
+				Searches in the default, in memory, global list. 
+				Finds the longest prefix that matches the given prefix parameter. 
+				Returns true if the prefix is found and the whitelist is <emphasis>not</emphasis> set. 
+				Returns false otherwise - either prefix found and whitelist set or prefix not found. 
+				Note that a reload_blacklist should be issued before, 
+				in order to check through the latest content of the database.
+			</para>
+			<example>
+				<title><function>check_blacklist</function> usage</title>
+				<programlisting format="linespecific">
+					...
+					&ctltool; fifo reload_blacklist
+					&ctltool; fifo check_blacklist prefix
+					...
+				</programlisting>
+	    		</example>
+		</section>
+
+		<section>
+			<title>
+				<function moreinfo="none">check_whitelist prefix</function>
+			</title>
+			<para>
+				Searches in the default, in memory, global list. 
+				Finds the longest prefix that matches the given prefix parameter. 
+				Returns true if the prefix is found and the whitelist is set. 
+				Returns false otherwise - either prefix found and whitelist 
+				<emphasis>not</emphasis> set or prefix not found. 
+				Note that a reload_blacklist should be issued before, 
+				in order to check through the latest content of the database.
+			</para>
+			<example>
+				<title><function>check_whitelist</function> usage</title>
+				<programlisting format="linespecific">
+					...
+					&ctltool; fifo reload_blacklist
+					&ctltool; fifo check_whitelist prefix
+					...
+				</programlisting>
+	    		</example>
+		</section>
+
+		<section>
+			<title>
+				<function moreinfo="none">check_userblacklist user [domain] prefix</function>
+			</title>
+			<para>
+				Searches in the default user list table.
+				Finds the longest prefix for the given user at domain that matches the given prefix parameter. 
+				Returns true if the prefix is found and the whitelist is <emphasis>not</emphasis> set. 
+				Returns false otherwise - either prefix found and whitelist set or prefix not found. 
+				Note that the domain parameter is optional. 
+				If not given, the second parameter is the considered to be the prefix. 
+			</para>
+			<example>
+				<title><function>check_userblacklist</function> usage</title>
+				<programlisting format="linespecific">
+					...
+					&ctltool; fifo check_userblacklist user [domain] prefix
+					...
+				</programlisting>
+	    		</example>
+		</section>
+
+		<section>
+			<title>
+				<function moreinfo="none">check_userwhitelist user [domain] prefix</function>
+			</title>
+			<para>
+				Searches in the default user list table.
+				Finds the longest prefix for the given user at domain that matches the given prefix parameter. 
+				Returns true if the prefix is found and the whitelist is set. 
+				Returns false otherwise - either prefix found and whitelist 
+				<emphasis>not</emphasis> set or prefix not found. 
+				Note that the domain parameter is optional. 
+				If not given, the second parameter is the considered to be the prefix. 
+			</para>
+			<example>
+				<title><function>check_userwhitelist</function> usage</title>
+				<programlisting format="linespecific">
+					...
+					&ctltool; fifo check_userwhitelist user [domain] prefix
+					...
+				</programlisting>
+	    		</example>
+		</section>
 </section>
+
     <section>
 	<title>Installation and Running</title>
 	<section>
 		<title>Database setup</title>
 		<para>
-			Before running &kamailio; with userblacklist, you have to setup the database 
-			table where the module will read the blacklist data. For that, if 
-			the table was not created by the installation script or you choose
-			to install everything by yourself you can use the userblacklist-create.sql
+			Before running &kamailio; with the userblacklist module,
+			you have to setup the database table where the module will
+			read the blacklist data. For that, if the table was not created
+			by the installation script or you choose to install everything
+			by yourself you can use the <emphasis>userblacklist-create.sql</emphasis>
 			<acronym>SQL</acronym> script in the database directories in the 
 			kamailio/scripts folder as template. 
 			Database and table name can be set with module parameters so they 
@@ -275,7 +551,7 @@ if (!check_whitelist("globalblacklist")) {
 	</example>
 	<para>
 		This table will setup a global blacklist for all numbers, only allowing calls
-		starting with <quote>1</quote>. Numbers that starting with <quote>123456</quote>
+		starting with <quote>1</quote>. Numbers that starts with <quote>123456</quote>
 		and <quote>123455787</quote> are also blacklisted, because the longest prefix
 		will be matched.
 	</para>
diff --git a/modules/userblacklist/doc/userblacklist_db.xml b/modules/userblacklist/doc/userblacklist_db.xml
deleted file mode 100644
index 987bedf..0000000
--- a/modules/userblacklist/doc/userblacklist_db.xml
+++ /dev/null
@@ -1,176 +0,0 @@
-<?xml version="1.0" encoding='ISO-8859-1'?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
-"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
-
-<!-- Include general documentation entities -->
-<!ENTITY % docentities SYSTEM "../../../docbook/entities.xml">
-%docentities;
-
-]>
-<!--
-WARNING:
-This file was autogenerated from the XML source file
-../../modules/userblacklist/doc/kamailio-userblacklist.xml.
-It can be regenerated by running 'make dbdoc' in the db/schema
-directory of the source code. You need to have xsltproc and
-docbook-xsl stylesheets installed.
-ALL CHANGES DONE HERE WILL BE LOST IF THE FILE IS REGENERATED
--->
-
-<chapter>
-  <title>Module parameter for database access.</title>
-  <section>
-    <title><varname>db_url</varname> (String)</title>
-    <para>URL to the database containing the data.</para>
-    <para>
-      <emphasis>Default value is <quote>&defaultrodb;</quote>.</emphasis>
-    </para>
-    <example>
-      <title>Set <varname>db_url</varname> parameter</title>
-      <programlisting format="linespecific">
-...
-modparam("userblacklist", "db_url", "dbdriver://username:password@dbhost/dbname")
-...
-</programlisting>
-    </example>
-  </section>
-  <section>
-    <title><varname>userblacklist_table</varname> (String)</title>
-    <para>Name of the userblacklist table for the userblacklist module.</para>
-    <para>
-      <emphasis>Default value is <quote>userblacklist</quote>.</emphasis>
-    </para>
-    <example>
-      <title>Set <varname>userblacklist_table</varname> parameter</title>
-      <programlisting format="linespecific">
-...
-modparam("userblacklist", "userblacklist_table", "userblacklist")
-...
-</programlisting>
-    </example>
-  </section>
-  <section>
-    <title><varname>userblacklist_id_col</varname> (string)</title>
-    <para>unique ID</para>
-    <example>
-      <title>Set <varname>userblacklist_id_col</varname> parameter</title>
-      <programlisting format="linespecific">
-...
-modparam("userblacklist", "userblacklist_id_col", "id")
-...
-</programlisting>
-    </example>
-  </section>
-  <section>
-    <title><varname>userblacklist_username_col</varname> (string)</title>
-    <para>The user that is used for the blacklist lookup.</para>
-    <example>
-      <title>Set <varname>userblacklist_username_col</varname> parameter</title>
-      <programlisting format="linespecific">
-...
-modparam("userblacklist", "userblacklist_username_col", "username")
-...
-</programlisting>
-    </example>
-  </section>
-  <section>
-    <title><varname>userblacklist_domain_col</varname> (string)</title>
-    <para>The domain that is used for the blacklist lookup.</para>
-    <example>
-      <title>Set <varname>userblacklist_domain_col</varname> parameter</title>
-      <programlisting format="linespecific">
-...
-modparam("userblacklist", "userblacklist_domain_col", "domain")
-...
-</programlisting>
-    </example>
-  </section>
-  <section>
-    <title><varname>userblacklist_prefix_col</varname> (string)</title>
-    <para>The prefix that is matched for the blacklist.</para>
-    <example>
-      <title>Set <varname>userblacklist_prefix_col</varname> parameter</title>
-      <programlisting format="linespecific">
-...
-modparam("userblacklist", "userblacklist_prefix_col", "prefix")
-...
-</programlisting>
-    </example>
-  </section>
-  <section>
-    <title><varname>userblacklist_whitelist_col</varname> (string)</title>
-    <para>Specify if this a blacklist (0) or a whitelist (1) entry.</para>
-    <example>
-      <title>Set <varname>userblacklist_whitelist_col</varname> parameter</title>
-      <programlisting format="linespecific">
-...
-modparam("userblacklist", "userblacklist_whitelist_col", "whitelist")
-...
-</programlisting>
-    </example>
-  </section>
-  <section>
-    <title><varname>globalblacklist_table</varname> (String)</title>
-    <para>Name of the globalblacklist table for the userblacklist module.
-    Please note that this table is used when the check_blacklist function is called with no parameters.</para>
-    <para>
-      <emphasis>Default value is <quote>globalblacklist</quote>.</emphasis>
-    </para>
-    <example>
-      <title>Set <varname>globalblacklist_table</varname> parameter</title>
-      <programlisting format="linespecific">
-...
-modparam("userblacklist", "globalblacklist_table", "globalblacklist")
-...
-</programlisting>
-    </example>
-  </section>
-  <section>
-    <title><varname>globalblacklist_id_col</varname> (string)</title>
-    <para>unique ID</para>
-    <example>
-      <title>Set <varname>globalblacklist_id_col</varname> parameter</title>
-      <programlisting format="linespecific">
-...
-modparam("userblacklist", "globalblacklist_id_col", "id")
-...
-</programlisting>
-    </example>
-  </section>
-  <section>
-    <title><varname>globalblacklist_prefix_col</varname> (string)</title>
-    <para>The prefix that is matched for the blacklist.</para>
-    <example>
-      <title>Set <varname>globalblacklist_prefix_col</varname> parameter</title>
-      <programlisting format="linespecific">
-...
-modparam("userblacklist", "globalblacklist_prefix_col", "prefix")
-...
-</programlisting>
-    </example>
-  </section>
-  <section>
-    <title><varname>globalblacklist_whitelist_col</varname> (string)</title>
-    <para>Specify if this a blacklist (0) or a whitelist (1) entry.</para>
-    <example>
-      <title>Set <varname>globalblacklist_whitelist_col</varname> parameter</title>
-      <programlisting format="linespecific">
-...
-modparam("userblacklist", "globalblacklist_whitelist_col", "whitelist")
-...
-</programlisting>
-    </example>
-  </section>
-  <section>
-    <title><varname>globalblacklist_description_col</varname> (string)</title>
-    <para>A comment for the entry.</para>
-    <example>
-      <title>Set <varname>globalblacklist_description_col</varname> parameter</title>
-      <programlisting format="linespecific">
-...
-modparam("userblacklist", "globalblacklist_description_col", "description")
-...
-</programlisting>
-    </example>
-  </section>
-</chapter>
diff --git a/modules/userblacklist/userblacklist.c b/modules/userblacklist/userblacklist.c
index 73bcd0c..17aebc2 100644
--- a/modules/userblacklist/userblacklist.c
+++ b/modules/userblacklist/userblacklist.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2007 1&1 Internet AG
  *
  * This file is part of Kamailio, a free SIP server.
@@ -60,6 +58,14 @@ MODULE_VERSION
 
 #define MAXNUMBERLEN 31
 
+#define BLACKLISTED_S		"blacklisted"
+#define BLACKLISTED_LEN		(sizeof(BLACKLISTED_S)-1)
+#define WHITELISTED_S		"whitelisted"
+#define WHITELISTED_LEN		(sizeof(WHITELISTED_S)-1)
+#define TRUE_S			"true"
+#define TRUE_LEN		(sizeof(TRUE_S)-1)
+#define FALSE_S			"false"
+#define FALSE_LEN		(sizeof(FALSE_S)-1)
 
 typedef struct _avp_check
 {
@@ -73,7 +79,7 @@ struct check_blacklist_fs_t {
 };
 
 str userblacklist_db_url = str_init(DEFAULT_RODB_URL);
-int use_domain   = 0;
+int use_domain = 0;
 int match_mode = 10; /* numeric */
 static struct dtrie_node_t *gnode = NULL;
 
@@ -102,6 +108,11 @@ static void mod_destroy(void);
 
 /* --- fifo functions */
 struct mi_root * mi_reload_blacklist(struct mi_root* cmd, void* param);  /* usage: kamctl fifo reload_blacklist */
+struct mi_root * mi_dump_blacklist(struct mi_root* cmd, void* param);  /* usage: kamctl fifo dump_blacklist */
+struct mi_root * mi_check_blacklist(struct mi_root* cmd, void* param);  /* usage: kamctl fifo check_blacklist prefix */
+struct mi_root * mi_check_whitelist(struct mi_root* cmd, void* param);  /* usage: kamctl fifo check_whitelist prefix */
+struct mi_root * mi_check_userblacklist(struct mi_root* cmd, void* param);  /* usage: kamctl fifo check_userblacklist */
+struct mi_root * mi_check_userwhitelist(struct mi_root* cmd, void* param);  /* usage: kamctl fifo check_userwhitelist */
 
 
 static cmd_export_t cmds[]={
@@ -125,15 +136,20 @@ static param_export_t params[] = {
 	userblacklist_DB_COLS
 	globalblacklist_DB_COLS
 	{ "use_domain",      INT_PARAM, &use_domain },
-	{ "match_mode",	     INT_PARAM, &match_mode},
-	{ 0, 0, 0}
+	{ "match_mode",	     INT_PARAM, &match_mode },
+	{ 0, 0, 0 }
 };
 
 
 /* Exported MI functions */
 static mi_export_t mi_cmds[] = {
 	{ "reload_blacklist", mi_reload_blacklist, MI_NO_INPUT_FLAG, 0, mi_child_init },
-	{ 0, 0, 0, 0, 0}
+	{ "dump_blacklist", mi_dump_blacklist, MI_NO_INPUT_FLAG, 0, 0},
+	{ "check_blacklist", mi_check_blacklist, 0, 0, 0 },
+	{ "check_whitelist", mi_check_whitelist, 0, 0, 0 },
+	{ "check_userblacklist", mi_check_userblacklist, 0, 0, 0 },
+	{ "check_userwhitelist", mi_check_userwhitelist, 0, 0, 0 },
+	{ 0, 0, 0, 0, 0 }
 };
 
 
@@ -675,6 +691,332 @@ static void destroy_shmlock(void)
 	}
 }
 
+static void dump_dtrie_mi(const struct dtrie_node_t *root,
+	const unsigned int branches, char *prefix, int *length, struct mi_root *reply)
+{
+	struct mi_node *crt_node;
+	unsigned int i;
+	char digit, *val = NULL;
+	int val_len = 0;
+
+	/* Sanity check - should not reach here anyway */
+	if (NULL == root) {
+		LM_ERR("root dtrie is NULL\n");
+		return ;
+	}
+
+        /* If data found, add a new node to the reply tree */
+        if (root->data) {
+		/* Create new node and add it to the roots's kids */
+		if(!(crt_node = add_mi_node_child(&reply->node, MI_DUP_NAME, prefix,
+				*length, 0, 0)) ) {
+			LM_ERR("cannot add the child node to the tree\n");
+			return ;
+		}
+
+		/* Resolve the value of the whitelist attribute */
+		if (root->data == (void *)MARK_BLACKLIST) {
+			val = int2str(0, &val_len);
+		} else if (root->data == (void *)MARK_WHITELIST) {
+			val = int2str(1, &val_len);
+		}
+
+		/* Add the attribute to the current node */
+		if((add_mi_attr(crt_node, MI_DUP_VALUE,
+				userblacklist_whitelist_col.s,
+				userblacklist_whitelist_col.len,
+				val, val_len)) == 0) {
+			LM_ERR("cannot add attributes to the node\n");
+			return ;
+		}
+        }
+
+	/* Perform a DFS search */
+        for (i = 0; i < branches; i++) {
+                /* If child branch found, traverse it */
+                if (root->child[i]) {
+                        if (branches == 10) {
+                                digit = i + '0';
+                        } else {
+                                digit = i;
+                        }
+
+                        /* Push digit in prefix stack */
+			if (*length >= MAXNUMBERLEN + 1) {
+				LM_ERR("prefix length exceeds %d\n", MAXNUMBERLEN + 1);
+				return ;
+			}
+                        prefix[(*length)++] = digit;
+
+                        /* Recursive DFS call */
+	                dump_dtrie_mi(root->child[i], branches, prefix, length, reply);
+
+                        /* Pop digit from prefix stack */
+                        (*length)--;
+                }
+        }
+
+        return ;
+}
+
+
+static struct mi_root * check_list_mi(struct mi_root* cmd, int list_type)
+{
+	struct mi_root *tmp = NULL;
+	struct mi_node *crt_node, *node;
+	struct mi_attr *crt_attr;
+	void **nodeflags;
+	int ret = -1;
+	char *ptr;
+	char req_prefix[MAXNUMBERLEN + 1];
+	str prefix, val, attr;
+
+	node = cmd->node.kids;
+
+	/* Get the prefix number */
+	if (NULL == node)
+		return init_mi_tree(400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
+
+	if (NULL == node->value.s || node->value.len == 0)
+		return init_mi_tree(400, MI_BAD_PARM_S, MI_BAD_PARM_LEN);
+	prefix = node->value;
+	strncpy(req_prefix, prefix.s, prefix.len);
+	req_prefix[prefix.len] = '\0';
+
+	/* Check that just 1 argument is given */
+	node = node->next;
+	if (node)
+		return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
+
+	/* Check that global blacklist exists */
+	if (!gnode) {
+		LM_ERR("the global blacklist is NULL\n");
+		return init_mi_tree(500, MI_INTERNAL_ERR_S, MI_INTERNAL_ERR_LEN);
+	}
+
+	/* Check that reply tree is successfully initialized */
+	tmp = init_mi_tree(200, MI_OK_S, MI_OK_LEN);
+	if (!tmp) {
+		LM_ERR("the MI tree cannot be initialized!\n");
+		return init_mi_tree(500, MI_INTERNAL_ERR_S, MI_INTERNAL_ERR_LEN);
+	}
+
+	/* Skip over non-digits. */
+	ptr = req_prefix;
+	while (match_mode == 10 && strlen(ptr) > 0 && !isdigit(*ptr)) {
+		ptr = ptr + 1;
+	}
+
+	/* Avoids dirty reads when updating d-tree */
+	lock_get(lock);
+	nodeflags = dtrie_longest_match(gnode, ptr, strlen(ptr), NULL, match_mode);
+	if (nodeflags) {
+		if (*nodeflags == (void *)MARK_WHITELIST) {
+			LM_DBG("prefix %.*s is whitelisted in table %.*s\n",
+				prefix.len, prefix.s, globalblacklist_table.len, globalblacklist_table.s);
+			ret = MARK_WHITELIST;
+		} else if (*nodeflags == (void *)MARK_BLACKLIST) {
+			LM_DBG("prefix %.*s is blacklisted in table %.*s\n",
+				prefix.len, prefix.s, globalblacklist_table.len, globalblacklist_table.s);
+			ret = MARK_BLACKLIST;
+		}
+	}
+	else {
+		LM_DBG("prefix %.*s not found in table %.*s\n",
+			prefix.len, prefix.s, globalblacklist_table.len, globalblacklist_table.s);
+	}
+	lock_release(lock);
+
+	/* Create new node and add it to the reply roots's kids */
+	if(!(crt_node = add_mi_node_child(&tmp->node, MI_DUP_NAME,
+			prefix.s, prefix.len, 0, 0)) ) {
+		LM_ERR("cannot add the child node to the tree\n");
+		return init_mi_tree(500, MI_INTERNAL_ERR_S, MI_INTERNAL_ERR_LEN);
+	}
+
+	/* Resolve the value of the attribute to be returned */
+	val.s = FALSE_S;
+	val.len = FALSE_LEN;
+
+	switch (list_type) {
+		case MARK_WHITELIST:
+                        attr.s = WHITELISTED_S;
+                        attr.len = WHITELISTED_LEN;
+
+			if (ret == MARK_WHITELIST) {
+				val.s = TRUE_S;
+				val.len = TRUE_LEN;
+			}
+
+			break;
+		case MARK_BLACKLIST:
+                        attr.s = BLACKLISTED_S;
+                        attr.len = BLACKLISTED_LEN;
+
+			if (ret == MARK_BLACKLIST) {
+				val.s = TRUE_S;
+				val.len = TRUE_LEN;
+			}
+
+			break;
+		default:
+			LM_ERR("list_type not found\n");
+			return init_mi_tree(500, MI_INTERNAL_ERR_S, MI_INTERNAL_ERR_LEN);
+	}
+
+	/* Add the attribute to the current node */
+	if (!(crt_attr = add_mi_attr(crt_node, MI_DUP_VALUE,
+			attr.s, attr.len, val.s, val.len))) {
+		LM_ERR("cannot add attribute to the node\n");
+		return init_mi_tree(500, MI_INTERNAL_ERR_S, MI_INTERNAL_ERR_LEN);
+	}
+
+	return tmp;
+}
+
+
+static struct mi_root * check_userlist_mi(struct mi_root* cmd, int list_type)
+{
+	struct mi_root *tmp = NULL;
+	struct mi_node *crt_node, *node;
+	struct mi_attr *crt_attr;
+	void **nodeflags;
+	int ret = -1;
+	int local_use_domain = 0;
+	char *ptr;
+	char req_prefix[MAXNUMBERLEN + 1];
+	str user, prefix, table, val, attr, domain;
+
+	node = cmd->node.kids;
+
+	/* Get the user number */
+	if (NULL == node)
+		return init_mi_tree(400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
+
+	if (NULL == node->value.s || node->value.len == 0)
+		return init_mi_tree(400, MI_BAD_PARM_S, MI_BAD_PARM_LEN);
+	user = node->value;
+
+	/* Get the domain name */
+	node = node->next;
+	if (NULL == node)
+		return init_mi_tree(400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
+
+	if (NULL == node->value.s || node->value.len == 0)
+		return init_mi_tree(400, MI_BAD_PARM_S, MI_BAD_PARM_LEN);
+	domain = node->value;
+
+	/* Get the prefix number */
+	node = node->next;
+	if (node) {
+		/* Got 3 params, the third one is the prefix */
+		if (NULL == node->value.s || node->value.len == 0)
+			return init_mi_tree(400, MI_BAD_PARM_S, MI_BAD_PARM_LEN);
+		prefix = node->value;
+		local_use_domain = 1;
+	} else {
+		/* Got 2 params, the second one is the prefix */
+		prefix = domain;
+		local_use_domain = 0;
+	}
+
+	strncpy(req_prefix, prefix.s, prefix.len);
+	req_prefix[prefix.len] = '\0';
+
+	/* Check that a maximum of 3 arguments are given */
+	if (node)
+		node = node->next;
+	if (node)
+		return init_mi_tree(400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
+
+	/* Build userblacklist dtrie */
+	table = userblacklist_table;
+	LM_DBG("check entry %s for user %.*s@%.*s in table %.*s, use domain=%d\n",
+		req_prefix, user.len, user.s, domain.len, domain.s,
+		table.len, table.s, local_use_domain);
+	if (db_build_userbl_tree(&user, &domain, &table, dtrie_root, local_use_domain) < 0) {
+		LM_ERR("cannot build d-tree\n");
+		return init_mi_tree(500, MI_INTERNAL_ERR_S, MI_INTERNAL_ERR_LEN);
+	}
+
+	/* Check that reply tree is successfully initialized */
+	tmp = init_mi_tree(200, MI_OK_S, MI_OK_LEN);
+	if (!tmp) {
+		LM_ERR("the MI tree cannot be initialized!\n");
+		return init_mi_tree(500, MI_INTERNAL_ERR_S, MI_INTERNAL_ERR_LEN);
+	}
+
+	/* Skip over non-digits. */
+	ptr = req_prefix;
+	while (match_mode == 10 && strlen(ptr) > 0 && !isdigit(*ptr)) {
+		ptr = ptr + 1;
+	}
+
+	/* Search for a match in dtrie */
+	nodeflags = dtrie_longest_match(dtrie_root, ptr, strlen(ptr), NULL, match_mode);
+	if (nodeflags) {
+		if (*nodeflags == (void *)MARK_WHITELIST) {
+			LM_DBG("user %.*s is whitelisted for prefix %.*s in table %.*s\n",
+				user.len, user.s, prefix.len, prefix.s, table.len, table.s);
+			ret = MARK_WHITELIST;
+		} else if (*nodeflags == (void *)MARK_BLACKLIST) {
+			LM_DBG("user %.*s is blacklisted for prefix %.*s in table %.*s\n",
+				user.len, user.s, prefix.len, prefix.s, table.len, table.s);
+			ret = MARK_BLACKLIST;
+		}
+	} else {
+		LM_DBG("user %.*s, prefix %.*s not found in table %.*s\n",
+			user.len, user.s, prefix.len, prefix.s, table.len, table.s);
+	}
+
+
+	/* Create new node and add it to the reply roots's kids */
+	if(!(crt_node = add_mi_node_child(&tmp->node, MI_DUP_NAME,
+			prefix.s, prefix.len, 0, 0)) ) {
+		LM_ERR("cannot add the child node to the tree\n");
+		return init_mi_tree(500, MI_INTERNAL_ERR_S, MI_INTERNAL_ERR_LEN);
+	}
+
+	/* Resolve the value of the attribute to be returned */
+	val.s = FALSE_S;
+	val.len = FALSE_LEN;
+
+	switch (list_type) {
+		case MARK_WHITELIST:
+                        attr.s = WHITELISTED_S;
+                        attr.len = WHITELISTED_LEN;
+
+			if (ret == MARK_WHITELIST) {
+				val.s = TRUE_S;
+				val.len = TRUE_LEN;
+			}
+
+			break;
+		case MARK_BLACKLIST:
+                        attr.s = BLACKLISTED_S;
+                        attr.len = BLACKLISTED_LEN;
+
+			if (ret == MARK_BLACKLIST) {
+				val.s = TRUE_S;
+				val.len = TRUE_LEN;
+			}
+
+			break;
+		default:
+			LM_ERR("list_type not found\n");
+			return init_mi_tree(500, MI_INTERNAL_ERR_S, MI_INTERNAL_ERR_LEN);
+	}
+
+	/* Add the attribute to the current node */
+	if (!(crt_attr = add_mi_attr(crt_node, MI_DUP_VALUE,
+			attr.s, attr.len, val.s, val.len))) {
+		LM_ERR("cannot add attribute to the node\n");
+		return init_mi_tree(500, MI_INTERNAL_ERR_S, MI_INTERNAL_ERR_LEN);
+	}
+
+	return tmp;
+}
+
 
 struct mi_root * mi_reload_blacklist(struct mi_root* cmd, void* param)
 {
@@ -689,6 +1031,54 @@ struct mi_root * mi_reload_blacklist(struct mi_root* cmd, void* param)
 }
 
 
+struct mi_root * mi_dump_blacklist(struct mi_root* cmd, void* param)
+{
+	char prefix_buff[MAXNUMBERLEN + 1];
+	int length = 0;
+	struct mi_root *tmp = NULL;
+
+	/* Check that global blacklist exists */
+	if (!gnode) {
+		LM_ERR("the global blacklist is NULL\n");
+		return init_mi_tree(500, MI_INTERNAL_ERR_S, MI_INTERNAL_ERR_LEN);
+	}
+
+	tmp = init_mi_tree(200, MI_OK_S, MI_OK_LEN);
+	if (!tmp) {
+		LM_ERR("the MI tree cannot be initialized!\n");
+		return init_mi_tree(500, MI_INTERNAL_ERR_S, MI_INTERNAL_ERR_LEN);
+	}
+
+	dump_dtrie_mi(gnode, match_mode, prefix_buff, &length, tmp);
+
+	return tmp;
+}
+
+
+struct mi_root * mi_check_blacklist(struct mi_root* cmd, void* param)
+{
+	return check_list_mi(cmd, MARK_BLACKLIST);
+}
+
+
+struct mi_root * mi_check_whitelist(struct mi_root* cmd, void* param)
+{
+	return check_list_mi(cmd, MARK_WHITELIST);
+}
+
+
+struct mi_root * mi_check_userblacklist(struct mi_root* cmd, void* param)
+{
+	return check_userlist_mi(cmd, MARK_BLACKLIST);
+}
+
+
+struct mi_root * mi_check_userwhitelist(struct mi_root* cmd, void* param)
+{
+	return check_userlist_mi(cmd, MARK_WHITELIST);
+}
+
+
 static int mod_init(void)
 {
 	if(register_mi_mod(exports.name, mi_cmds)!=0)
@@ -712,11 +1102,17 @@ static int child_init(int rank)
 	return mi_child_init();
 }
 
-
 static int userblacklist_child_initialized = 0;
+static int blacklist_child_initialized = 0;
 
 static int mi_child_init(void)
 {
+	/* global blacklist init */
+	if (check_globalblacklist_fixup(NULL, 0) != 0) {
+		LM_ERR("could not add global table when init the module");
+	}
+
+	/* user blacklist init */
 	if(userblacklist_child_initialized)
 		return 0;
 	if (userblacklist_db_open() != 0) return -1;
@@ -725,10 +1121,12 @@ static int mi_child_init(void)
 		LM_ERR("could not initialize data");
 		return -1;
 	}
+
 	/* because we've added new sources during the fixup */
 	if (reload_sources() != 0) return -1;
 
 	userblacklist_child_initialized = 1;
+	blacklist_child_initialized = 1;
 
 	return 0;
 }
diff --git a/modules/usrloc/Makefile b/modules/usrloc/Makefile
index 0026ae8..da2303d 100644
--- a/modules/usrloc/Makefile
+++ b/modules/usrloc/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # Usrloc module Makefile
 #
diff --git a/modules/usrloc/README b/modules/usrloc/README
index f480ad9..bd5daaa 100644
--- a/modules/usrloc/README
+++ b/modules/usrloc/README
@@ -53,25 +53,29 @@ Bogdan-Andrei Iancu
               3.15. path_column (string)
               3.16. ruid_column (string)
               3.17. instance_column (string)
-              3.18. use_domain (integer)
-              3.19. desc_time_order (integer)
-              3.20. timer_interval (integer)
-              3.21. db_url (string)
-              3.22. db_mode (integer)
-              3.23. matching_mode (integer)
-              3.24. cseq_delay (integer)
-              3.25. fetch_rows (integer)
-              3.26. hash_size (integer)
-              3.27. preload (string)
-              3.28. db_update_as_insert (string)
-              3.29. db_check_update (string)
-              3.30. timer_procs (string)
-              3.31. xavp_contact (string)
-              3.32. db_ops_ruid (int)
-              3.33. handle_lost_tcp (int)
-              3.34. expires_type (int)
-              3.35. db_raw_fetch_type (int)
-              3.36. db_insert_null (int)
+              3.18. server_id_column (string)
+              3.19. connection_id_column (string)
+              3.20. keepalive_column (string)
+              3.21. use_domain (integer)
+              3.22. desc_time_order (integer)
+              3.23. timer_interval (integer)
+              3.24. db_url (string)
+              3.25. db_mode (integer)
+              3.26. matching_mode (integer)
+              3.27. cseq_delay (integer)
+              3.28. fetch_rows (integer)
+              3.29. hash_size (integer)
+              3.30. preload (string)
+              3.31. db_update_as_insert (string)
+              3.32. db_check_update (string)
+              3.33. timer_procs (string)
+              3.34. xavp_contact (string)
+              3.35. db_ops_ruid (int)
+              3.36. handle_lost_tcp (int)
+              3.37. close_expired_tcp (int)
+              3.38. expires_type (int)
+              3.39. db_raw_fetch_type (int)
+              3.40. db_insert_null (int)
 
         4. Functions
         5. MI Commands
@@ -146,25 +150,29 @@ Bogdan-Andrei Iancu
    1.15. Set path_column parameter
    1.16. Set ruid_column parameter
    1.17. Set instance_column parameter
-   1.18. Set use_domain parameter
-   1.19. Set desc_time_order parameter
-   1.20. Set timer_interval parameter
-   1.21. Set db_url parameter
-   1.22. Set db_mode parameter
-   1.23. Set matching_mode parameter
-   1.24. Set cseq_delay parameter
-   1.25. Set fetch_rows parameter
-   1.26. Set hash_size parameter
-   1.27. Set preload parameter
-   1.28. Set db_update_as_insert parameter
-   1.29. Set db_check_update parameter
-   1.30. Set timer_procs parameter
-   1.31. Set xavp_contact parameter
-   1.32. Set db_ops_ruid parameter
-   1.33. Set handle_lost_tcp parameter
-   1.34. Set expires_type parameter
-   1.35. Set db_raw_fetch_type parameter
-   1.36. Set db_insert_null parameter
+   1.18. Set server_id_column parameter
+   1.19. Set connection_id_column parameter
+   1.20. Set keepalive_column parameter
+   1.21. Set use_domain parameter
+   1.22. Set desc_time_order parameter
+   1.23. Set timer_interval parameter
+   1.24. Set db_url parameter
+   1.25. Set db_mode parameter
+   1.26. Set matching_mode parameter
+   1.27. Set cseq_delay parameter
+   1.28. Set fetch_rows parameter
+   1.29. Set hash_size parameter
+   1.30. Set preload parameter
+   1.31. Set db_update_as_insert parameter
+   1.32. Set db_check_update parameter
+   1.33. Set timer_procs parameter
+   1.34. Set xavp_contact parameter
+   1.35. Set db_ops_ruid parameter
+   1.36. Set handle_lost_tcp parameter
+   1.37. Set close_expired_tcp parameter
+   1.38. Set expires_type parameter
+   1.39. Set db_raw_fetch_type parameter
+   1.40. Set db_insert_null parameter
 
 Chapter 1. Admin Guide
 
@@ -198,25 +206,29 @@ Chapter 1. Admin Guide
         3.15. path_column (string)
         3.16. ruid_column (string)
         3.17. instance_column (string)
-        3.18. use_domain (integer)
-        3.19. desc_time_order (integer)
-        3.20. timer_interval (integer)
-        3.21. db_url (string)
-        3.22. db_mode (integer)
-        3.23. matching_mode (integer)
-        3.24. cseq_delay (integer)
-        3.25. fetch_rows (integer)
-        3.26. hash_size (integer)
-        3.27. preload (string)
-        3.28. db_update_as_insert (string)
-        3.29. db_check_update (string)
-        3.30. timer_procs (string)
-        3.31. xavp_contact (string)
-        3.32. db_ops_ruid (int)
-        3.33. handle_lost_tcp (int)
-        3.34. expires_type (int)
-        3.35. db_raw_fetch_type (int)
-        3.36. db_insert_null (int)
+        3.18. server_id_column (string)
+        3.19. connection_id_column (string)
+        3.20. keepalive_column (string)
+        3.21. use_domain (integer)
+        3.22. desc_time_order (integer)
+        3.23. timer_interval (integer)
+        3.24. db_url (string)
+        3.25. db_mode (integer)
+        3.26. matching_mode (integer)
+        3.27. cseq_delay (integer)
+        3.28. fetch_rows (integer)
+        3.29. hash_size (integer)
+        3.30. preload (string)
+        3.31. db_update_as_insert (string)
+        3.32. db_check_update (string)
+        3.33. timer_procs (string)
+        3.34. xavp_contact (string)
+        3.35. db_ops_ruid (int)
+        3.36. handle_lost_tcp (int)
+        3.37. close_expired_tcp (int)
+        3.38. expires_type (int)
+        3.39. db_raw_fetch_type (int)
+        3.40. db_insert_null (int)
 
    4. Functions
    5. MI Commands
@@ -284,7 +296,7 @@ Chapter 1. Admin Guide
        retransmissions in this case.
 
    To find out how to control/select the contact maching algorithm, please
-   see the module parameter matching_mode - Section 3.23, "matching_mode
+   see the module parameter matching_mode - Section 3.26, "matching_mode
    (integer)".
 
 2. Dependencies
@@ -322,25 +334,29 @@ Chapter 1. Admin Guide
    3.15. path_column (string)
    3.16. ruid_column (string)
    3.17. instance_column (string)
-   3.18. use_domain (integer)
-   3.19. desc_time_order (integer)
-   3.20. timer_interval (integer)
-   3.21. db_url (string)
-   3.22. db_mode (integer)
-   3.23. matching_mode (integer)
-   3.24. cseq_delay (integer)
-   3.25. fetch_rows (integer)
-   3.26. hash_size (integer)
-   3.27. preload (string)
-   3.28. db_update_as_insert (string)
-   3.29. db_check_update (string)
-   3.30. timer_procs (string)
-   3.31. xavp_contact (string)
-   3.32. db_ops_ruid (int)
-   3.33. handle_lost_tcp (int)
-   3.34. expires_type (int)
-   3.35. db_raw_fetch_type (int)
-   3.36. db_insert_null (int)
+   3.18. server_id_column (string)
+   3.19. connection_id_column (string)
+   3.20. keepalive_column (string)
+   3.21. use_domain (integer)
+   3.22. desc_time_order (integer)
+   3.23. timer_interval (integer)
+   3.24. db_url (string)
+   3.25. db_mode (integer)
+   3.26. matching_mode (integer)
+   3.27. cseq_delay (integer)
+   3.28. fetch_rows (integer)
+   3.29. hash_size (integer)
+   3.30. preload (string)
+   3.31. db_update_as_insert (string)
+   3.32. db_check_update (string)
+   3.33. timer_procs (string)
+   3.34. xavp_contact (string)
+   3.35. db_ops_ruid (int)
+   3.36. handle_lost_tcp (int)
+   3.37. close_expired_tcp (int)
+   3.38. expires_type (int)
+   3.39. db_raw_fetch_type (int)
+   3.40. db_insert_null (int)
 
 3.1. nat_bflag (integer)
 
@@ -534,7 +550,41 @@ modparam("usrloc", "ruid_column", "myruid")
 modparam("usrloc", "instance_column", "myinstance")
 ...
 
-3.18. use_domain (integer)
+3.18. server_id_column (string)
+
+   Name of database table column containing the value for server id.
+
+   Default value is "server_id".
+
+   Example 1.18. Set server_id_column parameter
+...
+modparam("usrloc", "server_id_column", "srv_id")
+...
+
+3.19. connection_id_column (string)
+
+   Name of database table column containing the value for connection id.
+
+   Default value is "connection_id".
+
+   Example 1.19. Set connection_id_column parameter
+...
+modparam("usrloc", "connection_id_column", "con_id")
+...
+
+3.20. keepalive_column (string)
+
+   Name of database table column containing the value for keepalive
+   status.
+
+   Default value is "keepalive".
+
+   Example 1.20. Set keepalive_column parameter
+...
+modparam("usrloc", "keepalive_column", "kalive")
+...
+
+3.21. use_domain (integer)
 
    If the domain part of the user should be also saved and used for
    identifing the user (along with the username part). Useful in multi
@@ -542,24 +592,24 @@ modparam("usrloc", "instance_column", "myinstance")
 
    Default value is "0 (false)".
 
-   Example 1.18. Set use_domain parameter
+   Example 1.21. Set use_domain parameter
 ...
 modparam("usrloc", "use_domain", 1)
 ...
 
-3.19. desc_time_order (integer)
+3.22. desc_time_order (integer)
 
    If the user's contacts should be kept timestamp ordered; otherwise the
    contact will be ordered based on q value. Non 0 value means true.
 
    Default value is "0 (false)".
 
-   Example 1.19. Set desc_time_order parameter
+   Example 1.22. Set desc_time_order parameter
 ...
 modparam("usrloc", "desc_time_order", 1)
 ...
 
-3.20. timer_interval (integer)
+3.23. timer_interval (integer)
 
    Number of seconds between two timer runs. The module uses a timer to
    delete expired contacts, synchronize with database and other tasks,
@@ -567,23 +617,23 @@ modparam("usrloc", "desc_time_order", 1)
 
    Default value is 60.
 
-   Example 1.20. Set timer_interval parameter
+   Example 1.23. Set timer_interval parameter
 ...
 modparam("usrloc", "timer_interval", 120)
 ...
 
-3.21. db_url (string)
+3.24. db_url (string)
 
    URL of the database that should be used.
 
    Default value is "mysql://kamailio:kamailiorw@localhost/kamailio".
 
-   Example 1.21. Set db_url parameter
+   Example 1.24. Set db_url parameter
 ...
 modparam("usrloc", "db_url", "dbdriver://username:password@dbhost/dbname")
 ...
 
-3.22. db_mode (integer)
+3.25. db_mode (integer)
 
    The usrloc module can utilize a database for persistent contact
    storage. If a database is used, the location database (contacts) will
@@ -629,12 +679,12 @@ Warning
 
    Default value is 0.
 
-   Example 1.22. Set db_mode parameter
+   Example 1.25. Set db_mode parameter
 ...
 modparam("usrloc", "db_mode", 2)
 ...
 
-3.23. matching_mode (integer)
+3.26. matching_mode (integer)
 
    What contact matching algorithm to be used. Refer to section
    Section 1.1, "Contact matching" for the description of the algorithms.
@@ -648,12 +698,12 @@ modparam("usrloc", "db_mode", 2)
 
    Default value is 0 (CONTACT_ONLY).
 
-   Example 1.23. Set matching_mode parameter
+   Example 1.26. Set matching_mode parameter
 ...
 modparam("usrloc", "matching_mode", 1)
 ...
 
-3.24. cseq_delay (integer)
+3.27. cseq_delay (integer)
 
    Delay (in seconds) for accepting as retransmissions register requests
    with same Call-ID and Cseq. The delay is calculated starting from the
@@ -667,12 +717,12 @@ modparam("usrloc", "matching_mode", 1)
 
    Default value is "20 seconds".
 
-   Example 1.24. Set cseq_delay parameter
+   Example 1.27. Set cseq_delay parameter
 ...
 modparam("usrloc", "cseq_delay", 5)
 ...
 
-3.25. fetch_rows (integer)
+3.28. fetch_rows (integer)
 
    The number of the rows to be fetched at once from database when loading
    the location records. This value can be used to tune the load time at
@@ -681,12 +731,12 @@ modparam("usrloc", "cseq_delay", 5)
 
    Default value is "2000".
 
-   Example 1.25. Set fetch_rows parameter
+   Example 1.28. Set fetch_rows parameter
 ...
 modparam("usrloc", "fetch_rows", 3000)
 ...
 
-3.26. hash_size (integer)
+3.29. hash_size (integer)
 
    The number of entries of the hash table used by usrloc to store the
    location records is 2^hash_size. For hash_size=4, the number of slots
@@ -694,12 +744,12 @@ modparam("usrloc", "fetch_rows", 3000)
 
    Default value is "10" (1024 slots).
 
-   Example 1.26. Set hash_size parameter
+   Example 1.29. Set hash_size parameter
 ...
 modparam("usrloc", "hash_size", 12)
 ...
 
-3.27. preload (string)
+3.30. preload (string)
 
    Preload location table given as value. A location table is loaded based
    on fixup of registrar functions, therefore you need to use this
@@ -708,12 +758,12 @@ modparam("usrloc", "hash_size", 12)
 
    Default value is "NULL".
 
-   Example 1.27. Set preload parameter
+   Example 1.30. Set preload parameter
 ...
 modparam("usrloc", "preload", "location")
 ...
 
-3.28. db_update_as_insert (string)
+3.31. db_update_as_insert (string)
 
    Set this parameter if you want to do INSERT DB operations instead of
    UPDATE DB operations. It is recommended to set this parameter if you
@@ -721,12 +771,12 @@ modparam("usrloc", "preload", "location")
 
    Default value is "0".
 
-   Example 1.28. Set db_update_as_insert parameter
+   Example 1.31. Set db_update_as_insert parameter
 ...
 modparam("usrloc", "db_update_as_insert", 1)
 ...
 
-3.29. db_check_update (string)
+3.32. db_check_update (string)
 
    Set this parameter to 1 if you want to do DB INSERT if the number of
    affected rows by contact DB UPDATE operation is 0. The database module
@@ -736,12 +786,12 @@ modparam("usrloc", "db_update_as_insert", 1)
 
    Default value is "0" (no DB INSERT).
 
-   Example 1.29. Set db_check_update parameter
+   Example 1.32. Set db_check_update parameter
 ...
 modparam("usrloc", "db_check_update", 1)
 ...
 
-3.30. timer_procs (string)
+3.33. timer_procs (string)
 
    Number of timer processes to be started by module. Timer processes take
    care of checking expired records and syncronization with database. If
@@ -750,24 +800,24 @@ modparam("usrloc", "db_check_update", 1)
 
    Default value is "0".
 
-   Example 1.30. Set timer_procs parameter
+   Example 1.33. Set timer_procs parameter
 ...
 modparam("usrloc", "timer_procs", 4)
 ...
 
-3.31. xavp_contact (string)
+3.34. xavp_contact (string)
 
    The name of XAVP storring the attributes per contact. They are saved in
    location record and restored at lookup.
 
    Default value is "NULL".
 
-   Example 1.31. Set xavp_contact parameter
+   Example 1.34. Set xavp_contact parameter
 ...
 modparam("usrloc", "xavp_contact", "ulattrs")
 ...
 
-3.32. db_ops_ruid (int)
+3.35. db_ops_ruid (int)
 
    If set to 1, database queries for update or delete are done using ruid
    value. If it is set to 0, the old style using aor, contact and call-id
@@ -775,24 +825,37 @@ modparam("usrloc", "xavp_contact", "ulattrs")
 
    Default value is "1".
 
-   Example 1.32. Set db_ops_ruid parameter
+   Example 1.35. Set db_ops_ruid parameter
 ...
 modparam("usrloc", "db_ops_ruid", 0)
 ...
 
-3.33. handle_lost_tcp (int)
+3.36. handle_lost_tcp (int)
 
    If set to 1, Kamailio will remove location records made via
    TCP/TLS/WS/WSS transports when it looses corresponding tcp connections.
+   Does not currently work in DB-Only scheme.
 
    Default value is "0".
 
-   Example 1.33. Set handle_lost_tcp parameter
+   Example 1.36. Set handle_lost_tcp parameter
 ...
 modparam("usrloc", "handle_lost_tcp", 1)
 ...
 
-3.34. expires_type (int)
+3.37. close_expired_tcp (int)
+
+   If set to 1, Kamailio will close the TCP connection when a contact has
+   expired, if the corresponding transport is TCP/TLS/WS/WSS.
+
+   Default value is "0".
+
+   Example 1.37. Set close_expired_tcp parameter
+...
+modparam("usrloc", "close_expired_tcp", 1)
+...
+
+3.38. expires_type (int)
 
    If set to 1, Kamailio expects to deal with BIGINT type on database
    columns for expires and last modified values. It allows to handle
@@ -802,12 +865,12 @@ modparam("usrloc", "handle_lost_tcp", 1)
 
    Default value is "0".
 
-   Example 1.34. Set expires_type parameter
+   Example 1.38. Set expires_type parameter
 ...
 modparam("usrloc", "expires_type", 1)
 ...
 
-3.35. db_raw_fetch_type (int)
+3.39. db_raw_fetch_type (int)
 
    This affect DB-only mode and controls what kind of raw query is used to
    fetch the contacts from database for specific needs (e.g., sending NAT
@@ -817,19 +880,19 @@ modparam("usrloc", "expires_type", 1)
 
    Default value is "0".
 
-   Example 1.35. Set db_raw_fetch_type parameter
+   Example 1.39. Set db_raw_fetch_type parameter
 ...
 modparam("usrloc", "db_raw_fetch_type", 1)
 ...
 
-3.36. db_insert_null (int)
+3.40. db_insert_null (int)
 
    If set to 1, the insert operation to database will add null values in
    the sql statement.
 
    Default value is "0" (don't add null fields in insert statement).
 
-   Example 1.36. Set db_insert_null parameter
+   Example 1.40. Set db_insert_null parameter
 ...
 modparam("usrloc", "db_insert_null", 1)
 ...
@@ -847,7 +910,7 @@ modparam("usrloc", "db_insert_null", 1)
    5.5. ul_add
    5.6. ul_show_contact
 
-5.1. ul_rm
+5.1.  ul_rm
 
    Deletes an entire AOR record (including its contacts).
 
@@ -856,7 +919,7 @@ modparam("usrloc", "db_insert_null", 1)
      * AOR - user AOR in username[@domain] format (domain must be supplied
        only if use_domain option is on).
 
-5.2. ul_rm_contact
+5.2.  ul_rm_contact
 
    Deletes a contact from an AOR record.
 
@@ -866,7 +929,7 @@ modparam("usrloc", "db_insert_null", 1)
        only if use_domain option is on).
      * contact - exact contact to be removed
 
-5.3. ul_dump
+5.3.  ul_dump
 
    Dumps the entire content of the USRLOC in memory cache
 
@@ -875,11 +938,11 @@ modparam("usrloc", "db_insert_null", 1)
        "brief", a brief dump will be done (only AOR and contacts, with no
        other details)
 
-5.4. ul_flush
+5.4.  ul_flush
 
    Triggers the flush of USRLOC memory cache into DB.
 
-5.5. ul_add
+5.5.  ul_add
 
    Adds a new contact for an user AOR.
 
@@ -895,7 +958,7 @@ modparam("usrloc", "db_insert_null", 1)
      * cflags - per branch flags of the contact
      * methods - mask with supported requests of the contact
 
-5.6. ul_show_contact
+5.6.  ul_show_contact
 
    Dumps the contacts of an user AOR.
 
@@ -916,14 +979,14 @@ modparam("usrloc", "db_insert_null", 1)
    6.8. ul.db_contacts
    6.9. ul.db_expired_contacts
 
-6.1. ul.dump
+6.1.  ul.dump
 
    Dumps the content of the location table
 
    Parameters:
      * None.
 
-6.2. ul.lookup table AOR
+6.2.  ul.lookup table AOR
 
    Looks up the contents of an AOR entry in the location table
 
@@ -932,7 +995,7 @@ modparam("usrloc", "db_insert_null", 1)
      * AOR - user AOR in username[@domain] format (domain must be supplied
        only if use_domain option is on).
 
-6.3. ul.rm table AOR
+6.3.  ul.rm table AOR
 
    Deletes an entire AOR record (including its contacts).
 
@@ -941,7 +1004,7 @@ modparam("usrloc", "db_insert_null", 1)
      * AOR - user AOR in username[@domain] format (domain must be supplied
        only if use_domain option is on).
 
-6.4. ul.rm_contact table AOR contact
+6.4.  ul.rm_contact table AOR contact
 
    Deletes a contact from an AOR record.
 
@@ -951,11 +1014,11 @@ modparam("usrloc", "db_insert_null", 1)
        only if use_domain option is on).
      * contact - exact contact to be removed
 
-6.5. ul.flush
+6.5.  ul.flush
 
    Triggers the flush of USRLOC memory cache into DB.
 
-6.6. ul.add
+6.6.  ul.add
 
    Adds a new contact for an user AOR.
 
@@ -971,7 +1034,7 @@ modparam("usrloc", "db_insert_null", 1)
      * cflags - per branch flags of the contact
      * methods - mask with supported requests of the contact
 
-6.7. ul.db_users
+6.7.  ul.db_users
 
    Tell number of different users (AoRs) in a location table that have
    unexpired contacts.
@@ -980,7 +1043,7 @@ modparam("usrloc", "db_insert_null", 1)
      * table name - location table where the users are looked for, for
        example, location.
 
-6.8. ul.db_contacts
+6.8.  ul.db_contacts
 
    Tell number of unexpired contacts in a location table.
 
@@ -988,7 +1051,7 @@ modparam("usrloc", "db_insert_null", 1)
      * table name - location table where the contacts are looked for, for
        example, location.
 
-6.9. ul.db_expired_contacts
+6.9.  ul.db_expired_contacts
 
    Tell number of expired contacts in a location table.
 
@@ -1077,7 +1140,7 @@ Chapter 2. Developer Guide
    1.15. ul_register_ulcb(type ,callback, param)
    1.16. ul_get_num_users()
 
-1.1. ul_register_domain(name)
+1.1.  ul_register_domain(name)
 
    The function registers a new domain. Domain is just another name for
    table used in registrar. The function is called from fixups in
@@ -1092,7 +1155,7 @@ Chapter 2. Developer Guide
      * const char* name - Name of the domain (also called table) to be
        registered.
 
-1.2. ul_insert_urecord(domain, aor, rec)
+1.2.  ul_insert_urecord(domain, aor, rec)
 
    The function creates a new record structure and inserts it in the
    specified domain. The record is structure that contains all the
@@ -1107,7 +1170,7 @@ Chapter 2. Developer Guide
 
      * urecord_t** rec - The newly created record structure.
 
-1.3. ul_delete_urecord(domain, aor)
+1.3.  ul_delete_urecord(domain, aor)
 
    The function deletes all the contacts bound with the given Address Of
    Record.
@@ -1119,7 +1182,7 @@ Chapter 2. Developer Guide
      * str* aor - Address of record (aka username) of the record, that
        should be deleted.
 
-1.4. ul_delete_urecord_by_ruid(domain, ruid)
+1.4.  ul_delete_urecord_by_ruid(domain, ruid)
 
    The function deletes from given domain a contact with given ruid.
 
@@ -1129,7 +1192,7 @@ Chapter 2. Developer Guide
 
      * str* ruid - ruid of contact that should be deleted.
 
-1.5. ul_get_urecord(domain, aor)
+1.5.  ul_get_urecord(domain, aor)
 
    The function returns pointer to record with given Address of Record.
 
@@ -1139,7 +1202,7 @@ Chapter 2. Developer Guide
 
      * str* aor - Address of Record of request record.
 
-1.6. ul_lock_udomain(domain)
+1.6.  ul_lock_udomain(domain)
 
    The function lock the specified domain, it means, that no other
    processes will be able to access during the time. This prevents race
@@ -1150,14 +1213,14 @@ Chapter 2. Developer Guide
    Meaning of the parameters is as follows:
      * udomain_t* domain - Domain to be locked.
 
-1.7. ul_unlock_udomain(domain)
+1.7.  ul_unlock_udomain(domain)
 
    Unlock the specified domain previously locked by ul_lock_udomain.
 
    Meaning of the parameters is as follows:
      * udomain_t* domain - Domain to be unlocked.
 
-1.8. ul_release_urecord(record)
+1.8.  ul_release_urecord(record)
 
    Do some sanity checks - if all contacts have been removed, delete the
    entire record structure.
@@ -1165,7 +1228,7 @@ Chapter 2. Developer Guide
    Meaning of the parameters is as follows:
      * urecord_t* record - Record to be released.
 
-1.9. ul_insert_ucontact(record, contact, expires, q, callid, cseq, flags,
+1.9.  ul_insert_ucontact(record, contact, expires, q, callid, cseq, flags,
 cont, ua, sock)
 
    The function inserts a new contact in the given record with specified
@@ -1186,7 +1249,7 @@ cont, ua, sock)
      * struct socket_info *sock - socket on which the REGISTER message was
        received on.
 
-1.10. ul_delete_ucontact (record, contact)
+1.10.  ul_delete_ucontact (record, contact)
 
    The function deletes given contact from record.
 
@@ -1196,7 +1259,7 @@ cont, ua, sock)
 
      * ucontact_t* contact - Contact to be deleted.
 
-1.11. ul_get_ucontact(record, contact)
+1.11.  ul_get_ucontact(record, contact)
 
    The function tries to find contact with given Contact URI and returns
    pointer to structure representing the contact.
@@ -1206,7 +1269,7 @@ cont, ua, sock)
 
      * str_t* contact - URI of the request contact.
 
-1.12. ul_get_all_ucontacts (buf, len, flags)
+1.12.  ul_get_all_ucontacts (buf, len, flags)
 
    The function retrieves all contacts of all registered users and returns
    them in the caller-supplied buffer. If the buffer is too small, the
@@ -1227,7 +1290,7 @@ cont, ua, sock)
 
      * unsigned int flags - Flags that must be set.
 
-1.13. ul_update_ucontact(contact, expires, q, callid, cseq, set, res, ua,
+1.13.  ul_update_ucontact(contact, expires, q, callid, cseq, set, res, ua,
 sock)
 
    The function updates contact with new values.
@@ -1246,7 +1309,7 @@ sock)
      * struct socket_info *sock - socket on which the REGISTER message was
        received on.
 
-1.14. ul_bind_ursloc( api )
+1.14.  ul_bind_ursloc( api )
 
    The function imports all functions that are exported by the USRLOC
    module. Overs for other modules which want to user the internal USRLOC
@@ -1255,7 +1318,7 @@ sock)
    Meaning of the parameters is as follows:
      * usrloc_api_t* api - USRLOC API
 
-1.15. ul_register_ulcb(type ,callback, param)
+1.15.  ul_register_ulcb(type ,callback, param)
 
    The function register with USRLOC a callback function to be called when
    some event occures inside USRLOC.
@@ -1268,6 +1331,6 @@ sock)
      * void *param - some parameter to be passed to the callback each time
        when it is called.
 
-1.16. ul_get_num_users()
+1.16.  ul_get_num_users()
 
    The function loops through all domains summing up the number of users.
diff --git a/modules/usrloc/dlist.c b/modules/usrloc/dlist.c
index 8ac272a..1a95cc6 100644
--- a/modules/usrloc/dlist.c
+++ b/modules/usrloc/dlist.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,12 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * ========
- * 2005-07-11 get_all_ucontacts returns also the contact's flags (bogdan)
- * 2006-11-28 added get_number_of_users() (Jeffrey Magder - SOMA Networks)
- * 2007-09-12 added partitioning support for fetching all ul contacts
- *            (bogdan)
  */
 
 /*! \file
@@ -54,6 +46,12 @@
 /*! \brief Global list of all registered domains */
 dlist_t* root = 0;
 
+unsigned int _ul_max_partition = 0;
+
+void ul_set_max_partition(unsigned int m)
+{
+	_ul_max_partition = m;
+}
 
 /*!
  * \brief Find domain with the given name
@@ -79,12 +77,6 @@ static inline int find_dlist(str* _n, dlist_t** _d)
 	return 1;
 }
 
-extern int ul_db_raw_fetch_type;
-
-#define UL_DB_RAW_FETCH_COMMON	 "select %.*s, %.*s, %.*s, %.*s, %.*s, %.*s from %s where %.*s > %.*s and %.*s & %d = %d and id %% %u = %u"
-
-#define UL_DB_RAW_FETCH_ORACLE   "select %.*s, %.*s, %.*s, %.*s, %.*s, %.*s from %s where %.*s > %.*s and  bitand(%.*s, %d) = %d and mod(id, %u) = %u"
-
 /*!
  * \brief Get all contacts from the database, in partitions if wanted
  * \see get_all_ucontacts
@@ -98,19 +90,17 @@ extern int ul_db_raw_fetch_type;
 static inline int get_all_db_ucontacts(void *buf, int len, unsigned int flags,
 								unsigned int part_idx, unsigned int part_max)
 {
-	static char query_buf[512];
-	static str query_str;
-
 	struct socket_info *sock;
 	unsigned int dbflags;
 	db1_res_t* res = NULL;
 	db_row_t *row;
 	dlist_t *dom;
+	str now;
 	char now_s[25];
-	int now_len;
 	int port, proto;
 	char *p;
 	str addr;
+	str recv;
 	str path;
 	str ruid;
 	str host;
@@ -118,11 +108,11 @@ static inline int get_all_db_ucontacts(void *buf, int len, unsigned int flags,
 	int i;
 	void *cp;
 	int shortage, needed;
-
-	if(ul_dbf.raw_query==NULL) {
-		LM_WARN("DB raw query support is required, but not implemented\n");
-		return -1;
-	}
+	db_key_t keys1[3]; /* where */
+	db_val_t vals1[3];
+	db_op_t  ops1[3];
+	db_key_t keys2[6]; /* select */
+	int n[2] = {2,6}; /* number of dynamic values used on key1/key2 */
 
 	cp = buf;
 	shortage = 0;
@@ -130,37 +120,57 @@ static inline int get_all_db_ucontacts(void *buf, int len, unsigned int flags,
 	len -= sizeof(addr.len);
 
 	/* get the current time in DB format */
-	now_len = 25;
-	if (db_time2str( time(0), now_s, &now_len)!=0) {
+	now.len = 25;
+	now.s = now_s;
+	if (db_time2str( time(0), now.s, &now.len)!=0) {
 		LM_ERR("failed to print now time\n");
 		return -1;
 	}
 	aorhash = 0;
 
+	/* select fields */
+	keys2[0] = &received_col;
+	keys2[1] = &contact_col;
+	keys2[2] = &sock_col;
+	keys2[3] = &cflags_col;
+	keys2[4] = &path_col;
+	keys2[5] = &ruid_col;
+
+	/* where fields */
+	keys1[0] = &expires_col;
+	ops1[0] = OP_GT;
+	vals1[0].type = DB1_STR;
+	vals1[0].nul = 0;
+	vals1[0].val.str_val = now;
+
+	keys1[1] = &partition_col;
+	ops1[1] = OP_EQ;
+	vals1[1].type = DB1_INT;
+	vals1[1].nul = 0;
+	if(_ul_max_partition>0)
+		vals1[1].val.int_val = part_idx;
+	else
+		vals1[1].val.int_val = 0;
+
+	if (flags & nat_bflag) {
+		keys1[n[0]] = &keepalive_col;
+		ops1[n[0]] = OP_EQ;
+		vals1[n[0]].type = DB1_INT;
+		vals1[n[0]].nul = 0;
+		vals1[n[0]].val.int_val = 1;
+		n[0]++;
+	}
+
+	/* TODO: use part_idx and part_max on keys1 */
+
 	for (dom = root; dom!=NULL ; dom=dom->next) {
-		/* build query */
-		i = snprintf( query_buf, sizeof(query_buf),
-			(ul_db_raw_fetch_type==1)?
-					UL_DB_RAW_FETCH_ORACLE:UL_DB_RAW_FETCH_COMMON,
-			received_col.len, received_col.s,
-			contact_col.len, contact_col.s,
-			sock_col.len, sock_col.s,
-			cflags_col.len, cflags_col.s,
-			path_col.len, path_col.s,
-			ruid_col.len, ruid_col.s,
-			dom->d->name->s,
-			expires_col.len, expires_col.s,
-			now_len, now_s,
-			cflags_col.len, cflags_col.s,
-			flags, flags, part_max, part_idx);
-		if ( i>=sizeof(query_buf) ) {
-			LM_ERR("DB query too long\n");
+		if (ul_dbf.use_table(ul_dbh, dom->d->name) < 0) {
+			LM_ERR("sql use_table failed\n");
 			return -1;
 		}
-		query_str.s = query_buf;
-		query_str.len = i;
-		if ( ul_dbf.raw_query( ul_dbh, &query_str, &res)<0 ) {
-			LM_ERR("raw_query failed\n");
+		if (ul_dbf.query(ul_dbh, keys1, ops1, vals1, keys2,
+							n[0], n[1], NULL, &res) <0 ) {
+			LM_ERR("query error\n");
 			return -1;
 		}
 		if( RES_ROW_N(res)==0 ) {
@@ -171,17 +181,26 @@ static inline int get_all_db_ucontacts(void *buf, int len, unsigned int flags,
 		for(i = 0; i < RES_ROW_N(res); i++) {
 			row = RES_ROWS(res) + i;
 
+
 			/* received */
-			addr.s = (char*)VAL_STRING(ROW_VALUES(row));
-			if ( VAL_NULL(ROW_VALUES(row)) || addr.s==0 || addr.s[0]==0 ) {
-				/* contact */
-				addr.s = (char*)VAL_STRING(ROW_VALUES(row)+1);
-				if (VAL_NULL(ROW_VALUES(row)+1) || addr.s==0 || addr.s[0]==0) {
-					LM_ERR("empty contact -> skipping\n");
-					continue;
-				}
+			recv.s = (char*)VAL_STRING(ROW_VALUES(row));
+			if ( VAL_NULL(ROW_VALUES(row)) || recv.s==0 || recv.s[0]==0 ) {
+				recv.s = NULL;
+				recv.len = 0;
+			}
+			else {
+				recv.len = strlen(recv.s);
+			}
+
+			/* contact */
+			addr.s = (char*)VAL_STRING(ROW_VALUES(row)+1);
+			if (VAL_NULL(ROW_VALUES(row)+1) || addr.s==0 || addr.s[0]==0) {
+				LM_ERR("empty contact -> skipping\n");
+				continue;
+			}
+			else {
+				addr.len = strlen(addr.s);
 			}
-			addr.len = strlen(addr.s);
 
 			/* path */
 			path.s = (char*)VAL_STRING(ROW_VALUES(row)+4);
@@ -202,6 +221,7 @@ static inline int get_all_db_ucontacts(void *buf, int len, unsigned int flags,
 			}
 
 			needed = (int)(sizeof(addr.len) + addr.len
+					+ sizeof(recv.len) + recv.len
 					+ sizeof(sock) + sizeof(dbflags)
 					+ sizeof(path.len) + path.len
 					+ sizeof(ruid.len) + ruid.len
@@ -211,12 +231,21 @@ static inline int get_all_db_ucontacts(void *buf, int len, unsigned int flags,
 				continue;
 			}
 
-			/* write received/contact */
+			/* write contact */
 			memcpy(cp, &addr.len, sizeof(addr.len));
 			cp = (char*)cp + sizeof(addr.len);
 			memcpy(cp, addr.s, addr.len);
 			cp = (char*)cp + addr.len;
 
+			/* write received */
+			memcpy(cp, &recv.len, sizeof(recv.len));
+			cp = (char*)cp + sizeof(recv.len);
+			/* copy received only if exist */
+			if(recv.len){
+				memcpy(cp, recv.s, recv.len);
+				cp = (char*)cp + recv.len;
+			}
+
 			/* sock */
 			p  = (char*)VAL_STRING(ROW_VALUES(row) + 2);
 			if (VAL_NULL(ROW_VALUES(row)+2) || p==0 || p[0]==0){
@@ -355,65 +384,38 @@ static inline int get_all_mem_ucontacts(void *buf, int len, unsigned int flags,
 						}
 					}
 
-					if (c->received.s) {
-						needed = (int)(sizeof(c->received.len)
-								+ c->received.len
-								+ sizeof(c->sock) + sizeof(c->cflags)
-								+ sizeof(c->path.len) + c->path.len
-								+ sizeof(c->ruid.len) + c->ruid.len
-								+ sizeof(r->aorhash));
-						if (len >= needed) {
-							memcpy(cp,&c->received.len,sizeof(c->received.len));
-							cp = (char*)cp + sizeof(c->received.len);
-							memcpy(cp, c->received.s, c->received.len);
-							cp = (char*)cp + c->received.len;
-							memcpy(cp, &c->sock, sizeof(c->sock));
-							cp = (char*)cp + sizeof(c->sock);
-							memcpy(cp, &c->cflags, sizeof(c->cflags));
-							cp = (char*)cp + sizeof(c->cflags);
-							memcpy(cp, &c->path.len, sizeof(c->path.len));
-							cp = (char*)cp + sizeof(c->path.len);
-							memcpy(cp, c->path.s, c->path.len);
-							cp = (char*)cp + c->path.len;
-							memcpy(cp, &c->ruid.len, sizeof(c->ruid.len));
-							cp = (char*)cp + sizeof(c->ruid.len);
-							memcpy(cp, c->ruid.s, c->ruid.len);
-							cp = (char*)cp + c->ruid.len;
-							memcpy(cp, &r->aorhash, sizeof(r->aorhash));
-							cp = (char*)cp + sizeof(r->aorhash);
-							len -= needed;
-						} else {
-							shortage += needed;
-						}
-					} else {
-						needed = (int)(sizeof(c->c.len) + c->c.len
+					needed = (int)(sizeof(c->c.len) + c->c.len
+							+ sizeof(c->received.len) + c->received.len
 							+ sizeof(c->sock) + sizeof(c->cflags)
 							+ sizeof(c->path.len) + c->path.len
 							+ sizeof(c->ruid.len) + c->ruid.len
 							+ sizeof(r->aorhash));
-						if (len >= needed) {
-							memcpy(cp, &c->c.len, sizeof(c->c.len));
-							cp = (char*)cp + sizeof(c->c.len);
-							memcpy(cp, c->c.s, c->c.len);
-							cp = (char*)cp + c->c.len;
-							memcpy(cp, &c->sock, sizeof(c->sock));
-							cp = (char*)cp + sizeof(c->sock);
-							memcpy(cp, &c->cflags, sizeof(c->cflags));
-							cp = (char*)cp + sizeof(c->cflags);
-							memcpy(cp, &c->path.len, sizeof(c->path.len));
-							cp = (char*)cp + sizeof(c->path.len);
-							memcpy(cp, c->path.s, c->path.len);
-							cp = (char*)cp + c->path.len;
-							memcpy(cp, &c->ruid.len, sizeof(c->ruid.len));
-							cp = (char*)cp + sizeof(c->ruid.len);
-							memcpy(cp, c->ruid.s, c->ruid.len);
-							cp = (char*)cp + c->ruid.len;
-							memcpy(cp, &r->aorhash, sizeof(r->aorhash));
-							cp = (char*)cp + sizeof(r->aorhash);
-							len -= needed;
-						} else {
-							shortage += needed;
-						}
+					if (len >= needed) {
+						memcpy(cp, &c->c.len, sizeof(c->c.len));
+						cp = (char*)cp + sizeof(c->c.len);
+						memcpy(cp, c->c.s, c->c.len);
+						cp = (char*)cp + c->c.len;
+						memcpy(cp,&c->received.len,sizeof(c->received.len));
+						cp = (char*)cp + sizeof(c->received.len);
+						memcpy(cp, c->received.s, c->received.len);
+						cp = (char*)cp + c->received.len;
+						memcpy(cp, &c->sock, sizeof(c->sock));
+						cp = (char*)cp + sizeof(c->sock);
+						memcpy(cp, &c->cflags, sizeof(c->cflags));
+						cp = (char*)cp + sizeof(c->cflags);
+						memcpy(cp, &c->path.len, sizeof(c->path.len));
+						cp = (char*)cp + sizeof(c->path.len);
+						memcpy(cp, c->path.s, c->path.len);
+						cp = (char*)cp + c->path.len;
+						memcpy(cp, &c->ruid.len, sizeof(c->ruid.len));
+						cp = (char*)cp + sizeof(c->ruid.len);
+						memcpy(cp, c->ruid.s, c->ruid.len);
+						cp = (char*)cp + c->ruid.len;
+						memcpy(cp, &r->aorhash, sizeof(r->aorhash));
+						cp = (char*)cp + sizeof(r->aorhash);
+						len -= needed;
+					} else {
+						shortage += needed;
 					}
 				}
 			}
diff --git a/modules/usrloc/dlist.h b/modules/usrloc/dlist.h
index 76f1c15..9b8b84c 100644
--- a/modules/usrloc/dlist.h
+++ b/modules/usrloc/dlist.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,11 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * ========
- * 2006-11-28 Added get_number_of_users() (Jeffrey Magder - SOMA Networks)
- * 2007-09-12 added partitioning support for fetching all ul contacts
- *            (bogdan)
  */
 
 /*! \file
@@ -147,4 +140,9 @@ unsigned long get_number_of_users(void);
 int find_domain(str* _d, udomain_t** _p);
 
 
+/*!
+ * \brief Set the value for max partition
+ */
+void ul_set_max_partition(unsigned int m);
+
 #endif
diff --git a/modules/usrloc/doc/usrloc_admin.xml b/modules/usrloc/doc/usrloc_admin.xml
index 0f99681..ee569a4 100644
--- a/modules/usrloc/doc/usrloc_admin.xml
+++ b/modules/usrloc/doc/usrloc_admin.xml
@@ -449,6 +449,66 @@ modparam("usrloc", "instance_column", "myinstance")
 		</example>
 	</section>
 
+	<section id="usrloc.p.server_id_column">
+		<title><varname>server_id_column</varname> (string)</title>
+		<para>
+		Name of database table column containing the value for server id.
+		</para>
+		<para>
+		<emphasis>
+			Default value is <quote>server_id</quote>.
+		</emphasis>
+		</para>
+		<example>
+		<title>Set <varname>server_id_column</varname> parameter</title>
+		<programlisting format="linespecific">
+...
+modparam("usrloc", "server_id_column", "srv_id")
+...
+</programlisting>
+		</example>
+	</section>
+
+	<section id="usrloc.p.connection_id_column">
+		<title><varname>connection_id_column</varname> (string)</title>
+		<para>
+		Name of database table column containing the value for connection id.
+		</para>
+		<para>
+		<emphasis>
+			Default value is <quote>connection_id</quote>.
+		</emphasis>
+		</para>
+		<example>
+		<title>Set <varname>connection_id_column</varname> parameter</title>
+		<programlisting format="linespecific">
+...
+modparam("usrloc", "connection_id_column", "con_id")
+...
+</programlisting>
+		</example>
+	</section>
+
+	<section id="usrloc.p.keepalive_column">
+		<title><varname>keepalive_column</varname> (string)</title>
+		<para>
+		Name of database table column containing the value for keepalive status.
+		</para>
+		<para>
+		<emphasis>
+			Default value is <quote>keepalive</quote>.
+		</emphasis>
+		</para>
+		<example>
+		<title>Set <varname>keepalive_column</varname> parameter</title>
+		<programlisting format="linespecific">
+...
+modparam("usrloc", "keepalive_column", "kalive")
+...
+</programlisting>
+		</example>
+	</section>
+
 	<section id="usrloc.p.use_domain">
 		<title><varname>use_domain</varname> (integer)</title>
 		<para>
@@ -879,7 +939,8 @@ modparam("usrloc", "db_ops_ruid", 0)
 		<title><varname>handle_lost_tcp</varname> (int)</title>
 		<para>
 			If set to 1, Kamailio will remove location records made via
-			TCP/TLS/WS/WSS transports when it looses corresponding tcp connections.
+			TCP/TLS/WS/WSS transports when it looses corresponding tcp
+            connections.  Does not currently work in DB-Only scheme.
 		</para>
 		<para>
 		<emphasis>
@@ -896,6 +957,27 @@ modparam("usrloc", "handle_lost_tcp", 1)
 		</example>
 	</section>
 
+	<section id="usrloc.p.close_expired_tcp">
+		<title><varname>close_expired_tcp</varname> (int)</title>
+		<para>
+            If set to 1, Kamailio will close the TCP connection when a contact
+            has expired, if the corresponding transport is TCP/TLS/WS/WSS.
+        </para>
+		<para>
+		<emphasis>
+			Default value is <quote>0</quote>.
+		</emphasis>
+		</para>
+		<example>
+		<title>Set <varname>close_expired_tcp</varname> parameter</title>
+		<programlisting format="linespecific">
+...
+modparam("usrloc", "close_expired_tcp", 1)
+...
+</programlisting>
+		</example>
+	</section>
+
 	<section id="usrloc.p.expires_type">
 		<title><varname>expires_type</varname> (int)</title>
 		<para>
diff --git a/modules/usrloc/hslot.c b/modules/usrloc/hslot.c
index 6305916..592ec7e 100644
--- a/modules/usrloc/hslot.c
+++ b/modules/usrloc/hslot.c
@@ -1,6 +1,4 @@
 /*
- * $Id$ 
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/usrloc/hslot.h b/modules/usrloc/hslot.h
index 9dc190a..ec1ddb0 100644
--- a/modules/usrloc/hslot.h
+++ b/modules/usrloc/hslot.h
@@ -1,6 +1,4 @@
 /*
- * $Id$ 
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/usrloc/ucontact.c b/modules/usrloc/ucontact.c
index 45bcea8..a645e42 100644
--- a/modules/usrloc/ucontact.c
+++ b/modules/usrloc/ucontact.c
@@ -1,6 +1,4 @@
 /*
- * $Id$ 
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,11 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * ---------
- * 2003-03-12 added replication mark and three zombie states (nils)
- * 2004-03-17 generic callbacks added (bogdan)
- * 2004-06-07 updated to the new DB api (andrei)
  */
 
 /*! \file
@@ -140,6 +133,8 @@ ucontact_t* new_ucontact(str* _dom, str* _aor, str* _contact, ucontact_info_t* _
 	c->last_modified = _ci->last_modified;
 	c->last_keepalive = _ci->last_modified;
 	c->tcpconn_id = _ci->tcpconn_id;
+	c->server_id = _ci->server_id;
+	c->keepalive = (_ci->cflags & nat_bflag)?1:0;
 #ifdef WITH_XAVP
 	ucontact_xavp_store(c);
 #endif
@@ -463,6 +458,9 @@ int st_flush_ucontact(ucontact_t* _c)
 
 /* ============== Database related functions ================ */
 
+extern unsigned int _ul_max_partition;
+static unsigned int _ul_partition_counter = 0;
+
 /*!
  * \brief Insert contact into the database
  * \param _c inserted contact
@@ -471,8 +469,8 @@ int st_flush_ucontact(ucontact_t* _c)
 int db_insert_ucontact(ucontact_t* _c)
 {
 	char* dom;
-	db_key_t keys[18];
-	db_val_t vals[18];
+	db_key_t keys[22];
+	db_val_t vals[22];
 	int nr_cols;
 	
 	if (_c->flags & FL_MEM) {
@@ -629,6 +627,36 @@ int db_insert_ucontact(ucontact_t* _c)
 	vals[nr_cols].val.int_val = (int)_c->reg_id;
 	nr_cols++;
 
+	keys[nr_cols] = &srv_id_col;
+	vals[nr_cols].type = DB1_INT;
+	vals[nr_cols].nul = 0;
+	vals[nr_cols].val.int_val = (int)_c->server_id;
+	nr_cols++;
+
+	keys[nr_cols] = &con_id_col;
+	vals[nr_cols].type = DB1_INT;
+	vals[nr_cols].nul = 0;
+	vals[nr_cols].val.int_val = (int)_c->tcpconn_id;
+	nr_cols++;
+
+	keys[nr_cols] = &keepalive_col;
+	vals[nr_cols].type = DB1_INT;
+	vals[nr_cols].nul = 0;
+	vals[nr_cols].val.int_val = (int)_c->keepalive;
+	nr_cols++;
+
+	keys[nr_cols] = &partition_col;
+	vals[nr_cols].type = DB1_INT;
+	vals[nr_cols].nul = 0;
+	if(_ul_max_partition>0) {
+		vals[nr_cols].val.int_val = ((_ul_partition_counter++) + my_pid())
+										% _ul_max_partition;
+	} else {
+		vals[nr_cols].val.int_val = 0;
+	}
+	nr_cols++;
+
+
 	if (use_domain) {
 		keys[nr_cols] = &domain_col;
 		vals[nr_cols].type = DB1_STR;
@@ -678,8 +706,8 @@ int db_update_ucontact_addr(ucontact_t* _c)
 	db_val_t vals1[4];
 	int n1 = 0;
 
-	db_key_t keys2[16];
-	db_val_t vals2[16];
+	db_key_t keys2[19];
+	db_val_t vals2[19];
 	int nr_cols2 = 0;
 
 
@@ -860,6 +888,24 @@ int db_update_ucontact_addr(ucontact_t* _c)
 	vals2[nr_cols2].val.int_val = (int)_c->reg_id;
 	nr_cols2++;
 
+	keys2[nr_cols2] = &srv_id_col;
+	vals2[nr_cols2].type = DB1_INT;
+	vals2[nr_cols2].nul = 0;
+	vals2[nr_cols2].val.int_val = (int)_c->server_id;
+	nr_cols2++;
+
+	keys2[nr_cols2] = &con_id_col;
+	vals2[nr_cols2].type = DB1_INT;
+	vals2[nr_cols2].nul = 0;
+	vals2[nr_cols2].val.int_val = (int)_c->tcpconn_id;
+	nr_cols2++;
+
+	keys2[nr_cols2] = &keepalive_col;
+	vals2[nr_cols2].type = DB1_INT;
+	vals2[nr_cols2].nul = 0;
+	vals2[nr_cols2].val.int_val = (int)_c->keepalive;
+	nr_cols2++;
+
 	keys2[nr_cols2] = &contact_col;
 	vals2[nr_cols2].type = DB1_STR;
 	vals2[nr_cols2].nul = 0;
@@ -935,8 +981,8 @@ int db_update_ucontact_ruid(ucontact_t* _c)
 	db_val_t vals1[1];
 	int n1;
 
-	db_key_t keys2[15];
-	db_val_t vals2[15];
+	db_key_t keys2[18];
+	db_val_t vals2[18];
 	int n2;
 
 
@@ -1061,6 +1107,24 @@ int db_update_ucontact_ruid(ucontact_t* _c)
 	vals2[n2].val.int_val = (int)_c->reg_id;
 	n2++;
 
+	keys2[n2] = &srv_id_col;
+	vals2[n2].type = DB1_INT;
+	vals2[n2].nul = 0;
+	vals2[n2].val.int_val = (int)_c->server_id;
+	n2++;
+
+	keys2[n2] = &con_id_col;
+	vals2[n2].type = DB1_INT;
+	vals2[n2].nul = 0;
+	vals2[n2].val.int_val = (int)_c->tcpconn_id;
+	n2++;
+
+	keys2[n2] = &keepalive_col;
+	vals2[n2].type = DB1_INT;
+	vals2[n2].nul = 0;
+	vals2[n2].val.int_val = (int)_c->keepalive;
+	n2++;
+
 	keys2[n2] = &contact_col;
 	vals2[n2].type = DB1_STR;
 	vals2[n2].nul = 0;
@@ -1131,8 +1195,8 @@ int db_update_ucontact_instance(ucontact_t* _c)
 	db_val_t vals1[4];
 	int n1;
 
-	db_key_t keys2[13];
-	db_val_t vals2[13];
+	db_key_t keys2[16];
+	db_val_t vals2[16];
 	int n2;
 
 
@@ -1254,6 +1318,24 @@ int db_update_ucontact_instance(ucontact_t* _c)
 	vals2[n2].val.str_val = _c->callid;
 	n2++;
 
+	keys2[n2] = &srv_id_col;
+	vals2[n2].type = DB1_INT;
+	vals2[n2].nul = 0;
+	vals2[n2].val.bitmap_val = _c->server_id;
+	n2++;
+
+	keys2[n2] = &con_id_col;
+	vals2[n2].type = DB1_INT;
+	vals2[n2].nul = 0;
+	vals2[n2].val.bitmap_val = _c->tcpconn_id;
+	n2++;
+
+	keys2[n2] = &keepalive_col;
+	vals2[n2].type = DB1_INT;
+	vals2[n2].nul = 0;
+	vals2[n2].val.bitmap_val = _c->keepalive;
+	n2++;
+
 	keys2[n2] = &contact_col;
 	vals2[n2].type = DB1_STR;
 	vals2[n2].nul = 0;
@@ -1557,6 +1639,28 @@ static inline void update_contact_pos(struct urecord* _r, ucontact_t* _c)
 	}
 }
 
+/*!
+ * \brief helper function for update_ucontact
+ * \param _c contact
+ * \return 0 on success, -1 on failure
+ */
+static inline int update_contact_db(ucontact_t* _c)
+{
+	int res;
+
+	if (ul_db_update_as_insert)
+		res = db_insert_ucontact(_c);
+	else
+		res = db_update_ucontact(_c);
+
+	if (res < 0) {
+		LM_ERR("failed to update database\n");
+		return -1;
+	} else {
+		_c->state = CS_SYNC;
+	}
+	return 0;
+}
 
 /*!
  * \brief Update ucontact with new values
@@ -1567,8 +1671,6 @@ static inline void update_contact_pos(struct urecord* _r, ucontact_t* _c)
  */
 int update_ucontact(struct urecord* _r, ucontact_t* _c, ucontact_info_t* _ci)
 {
-	int res;
-
 	/* we have to update memory in any case, but database directly
 	 * only in db_mode 1 */
 	if (mem_update_ucontact( _c, _ci) < 0) {
@@ -1576,6 +1678,10 @@ int update_ucontact(struct urecord* _r, ucontact_t* _c, ucontact_info_t* _ci)
 		return -1;
 	}
 
+	if (db_mode==DB_ONLY) {
+		if (update_contact_db(_c) < 0) return -1;
+	}
+
 	/* run callbacks for UPDATE event */
 	if (exists_ulcb_type(UL_CONTACT_UPDATE))
 	{
@@ -1588,18 +1694,8 @@ int update_ucontact(struct urecord* _r, ucontact_t* _c, ucontact_info_t* _ci)
 
 	st_update_ucontact(_c);
 
-	if (db_mode == WRITE_THROUGH || db_mode==DB_ONLY) {
-		if (ul_db_update_as_insert)
-			res = db_insert_ucontact(_c);
-		else
-			res = db_update_ucontact(_c);
-
-		if (res < 0) {
-			LM_ERR("failed to update database\n");
-			return -1;
-		} else {
-			_c->state = CS_SYNC;
-		}
+	if (db_mode == WRITE_THROUGH) {
+		if (update_contact_db(_c) < 0) return -1;
 	}
 	return 0;
 }
diff --git a/modules/usrloc/ucontact.h b/modules/usrloc/ucontact.h
index 1ec9113..ebe4708 100644
--- a/modules/usrloc/ucontact.h
+++ b/modules/usrloc/ucontact.h
@@ -1,6 +1,4 @@
 /*
- * $Id$ 
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,11 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * ---------
- * 2003-03-12 added replication mark and three zombie states (nils)
- * 2005-07-11 added FL_NAT_SIPPING for nat pinging with SIP method
- *             instead of UDP package (bogdan)
  */
 
 /*! \file
diff --git a/modules/usrloc/udomain.c b/modules/usrloc/udomain.c
index dca72cd..2bb1707 100644
--- a/modules/usrloc/udomain.c
+++ b/modules/usrloc/udomain.c
@@ -1,6 +1,4 @@
 /*
- * $Id$ 
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,13 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * ---------
- * 2003-03-11 changed to the new locking scheme: locking.h (andrei)
- * 2003-03-12 added replication mark and zombie state (nils)
- * 2004-06-07 updated to the new DB api (andrei)
- * 2004-08-23  hash function changed to process characters as unsigned
- *             -> no negative results occur (jku)
  */
 
 /*! \file
@@ -223,9 +214,10 @@ void print_udomain(FILE* _f, udomain_t* _d)
  * ua, received, path, socket, methods, last_modified)
  * \param vals database values
  * \param contact contact
+ * \param rcon restore connection id
  * \return pointer to the ucontact_info on success, 0 on failure
  */
-static inline ucontact_info_t* dbrow2info( db_val_t *vals, str *contact)
+static inline ucontact_info_t* dbrow2info(db_val_t *vals, str *contact, int rcon)
 {
 	static ucontact_info_t ci;
 	static str callid, ua, received, host, path;
@@ -351,8 +343,21 @@ static inline ucontact_info_t* dbrow2info( db_val_t *vals, str *contact)
 		ci.reg_id = VAL_UINT(vals+15);
 	}
 
-	/* tcp connection id */
+	/* server_id */
+	if (!VAL_NULL(vals+16)) {
+		ci.server_id = VAL_UINT(vals+16);
+	}
+
+	/* tcp connection id (not restored always) */
 	ci.tcpconn_id = -1;
+	if(rcon==1 && !VAL_NULL(vals+17)) {
+		ci.tcpconn_id = VAL_UINT(vals+17);
+	}
+
+	/* keepalive */
+	if (!VAL_NULL(vals+18)) {
+		ci.keepalive = VAL_UINT(vals+18);
+	}
 
 	return &ci;
 }
@@ -372,7 +377,7 @@ int preload_udomain(db1_con_t* _c, udomain_t* _d)
 	char uri[MAX_URI_SIZE];
 	ucontact_info_t *ci;
 	db_row_t *row;
-	db_key_t columns[18];
+	db_key_t columns[21];
 	db1_res_t* res = NULL;
 	str user, contact;
 	char* domain;
@@ -399,7 +404,10 @@ int preload_udomain(db1_con_t* _c, udomain_t* _d)
 	columns[14] = &ruid_col;
 	columns[15] = &instance_col;
 	columns[16] = &reg_id_col;
-	columns[17] = &domain_col;
+	columns[17] = &srv_id_col;
+	columns[18] = &con_id_col;
+	columns[19] = &keepalive_col;
+	columns[20] = &domain_col;
 
 	if (ul_dbf.use_table(_c, _d->name) < 0) {
 		LM_ERR("sql use_table failed\n");
@@ -411,7 +419,7 @@ int preload_udomain(db1_con_t* _c, udomain_t* _d)
 #endif
 
 	if (DB_CAPABILITY(ul_dbf, DB_CAP_FETCH)) {
-		if (ul_dbf.query(_c, 0, 0, 0, columns, 0, (use_domain)?(18):(17), 0,
+		if (ul_dbf.query(_c, 0, 0, 0, columns, 0, (use_domain)?(21):(20), 0,
 		0) < 0) {
 			LM_ERR("db_query (1) failed\n");
 			return -1;
@@ -421,7 +429,7 @@ int preload_udomain(db1_con_t* _c, udomain_t* _d)
 			return -1;
 		}
 	} else {
-		if (ul_dbf.query(_c, 0, 0, 0, columns, 0, (use_domain)?(18):(17), 0,
+		if (ul_dbf.query(_c, 0, 0, 0, columns, 0, (use_domain)?(21):(20), 0,
 		&res) < 0) {
 			LM_ERR("db_query failed\n");
 			return -1;
@@ -449,7 +457,7 @@ int preload_udomain(db1_con_t* _c, udomain_t* _d)
 			}
 			user.len = strlen(user.s);
 
-			ci = dbrow2info( ROW_VALUES(row)+1, &contact);
+			ci = dbrow2info(ROW_VALUES(row)+1, &contact, 0);
 			if (ci==0) {
 				LM_ERR("sipping record for %.*s in table %s\n",
 						user.len, user.s, _d->name->s);
@@ -457,7 +465,7 @@ int preload_udomain(db1_con_t* _c, udomain_t* _d)
 			}
 
 			if (use_domain) {
-				domain = (char*)VAL_STRING(ROW_VALUES(row) + 17);
+				domain = (char*)VAL_STRING(ROW_VALUES(row) + 20);
 				if (VAL_NULL(ROW_VALUES(row)+17) || domain==0 || domain[0]==0){
 					LM_CRIT("empty domain record for user %.*s...skipping\n",
 							user.len, user.s);
@@ -534,7 +542,7 @@ urecord_t* db_load_urecord(db1_con_t* _c, udomain_t* _d, str *_aor)
 	char tname_buf[64];
 	str tname;
 	ucontact_info_t *ci;
-	db_key_t columns[16];
+	db_key_t columns[19];
 	db_key_t keys[2];
 	db_key_t order;
 	db_val_t vals[2];
@@ -587,6 +595,9 @@ urecord_t* db_load_urecord(db1_con_t* _c, udomain_t* _d, str *_aor)
 	columns[13] = &ruid_col;
 	columns[14] = &instance_col;
 	columns[15] = &reg_id_col;
+	columns[16] = &srv_id_col;
+	columns[17] = &con_id_col;
+	columns[18] = &keepalive_col;
 
 	if (desc_time_order)
 		order = &last_mod_col;
@@ -613,7 +624,7 @@ urecord_t* db_load_urecord(db1_con_t* _c, udomain_t* _d, str *_aor)
 	r = 0;
 
 	for(i = 0; i < RES_ROW_N(res); i++) {
-		ci = dbrow2info(  ROW_VALUES(RES_ROWS(res) + i), &contact);
+		ci = dbrow2info(ROW_VALUES(RES_ROWS(res) + i), &contact, 1);
 		if (ci==0) {
 			LM_ERR("skipping record for %.*s in table %s\n",
 					_aor->len, _aor->s, _d->name->s);
@@ -731,7 +742,7 @@ done:
 urecord_t* db_load_urecord_by_ruid(db1_con_t* _c, udomain_t* _d, str *_ruid)
 {
 	ucontact_info_t *ci;
-	db_key_t columns[18];
+	db_key_t columns[21];
 	db_key_t keys[1];
 	db_key_t order;
 	db_val_t vals[1];
@@ -766,8 +777,11 @@ urecord_t* db_load_urecord_by_ruid(db1_con_t* _c, udomain_t* _d, str *_ruid)
 	columns[13] = &ruid_col;
 	columns[14] = &instance_col;
 	columns[15] = &reg_id_col;
-	columns[16] = &user_col;
-	columns[17] = &domain_col;
+	columns[16] = &srv_id_col;
+	columns[17] = &con_id_col;
+	columns[18] = &keepalive_col;
+	columns[19] = &user_col;
+	columns[20] = &domain_col;
 
 	if (desc_time_order)
 		order = &last_mod_col;
@@ -797,19 +811,19 @@ urecord_t* db_load_urecord_by_ruid(db1_con_t* _c, udomain_t* _d, str *_ruid)
 	/* use first row - shouldn't be more */
 	row = RES_ROWS(res);
 
-	ci = dbrow2info(ROW_VALUES(RES_ROWS(res)), &contact);
+	ci = dbrow2info(ROW_VALUES(RES_ROWS(res)), &contact, 1);
 	if (ci==0) {
 		LM_ERR("skipping record for %.*s in table %s\n",
 				_ruid->len, _ruid->s, _d->name->s);
 		goto done;
 	}
 
-	aor.s = (char*)VAL_STRING(ROW_VALUES(row) + 16);
+	aor.s = (char*)VAL_STRING(ROW_VALUES(row) + 19);
 	aor.len = strlen(aor.s);
 
 	if (use_domain) {
-		domain.s = (char*)VAL_STRING(ROW_VALUES(row) + 17);
-		if (VAL_NULL(ROW_VALUES(row)+17) || domain.s==0 || domain.s[0]==0){
+		domain.s = (char*)VAL_STRING(ROW_VALUES(row) + 20);
+		if (VAL_NULL(ROW_VALUES(row)+20) || domain.s==0 || domain.s[0]==0){
 			LM_CRIT("empty domain record for user %.*s...skipping\n",
 					aor.len, aor.s);
 			goto done;
@@ -862,7 +876,7 @@ int db_timer_udomain(udomain_t* _d)
 	UL_DB_EXPIRES_SET(&vals[0], act_time + 1);
 
 	keys[1] = &expires_col;
-	ops[1] = "!=";
+	ops[1] = OP_NEQ;
 	vals[1].nul = 0;
 	UL_DB_EXPIRES_SET(&vals[1], 0);
 
@@ -887,23 +901,30 @@ int db_timer_udomain(udomain_t* _d)
  */
 int testdb_udomain(db1_con_t* con, udomain_t* d)
 {
-	db_key_t key[1], col[1];
-	db_val_t val[1];
+	db_key_t key[2], col[1];
+	db_val_t val[2];
 	db1_res_t* res = NULL;
 
-	if (ul_dbf.use_table(con, d->name) < 0) {
+	if(ul_dbf.use_table(con, d->name) < 0) {
 		LM_ERR("failed to change table\n");
 		return -1;
 	}
 
 	key[0] = &user_col;
+	key[1] = &domain_col;
 
 	col[0] = &user_col;
+
 	VAL_TYPE(val) = DB1_STRING;
 	VAL_NULL(val) = 0;
 	VAL_STRING(val) = "dummy_user";
 	
-	if (ul_dbf.query( con, key, 0, val, col, 1, 1, 0, &res) < 0) {
+	VAL_TYPE(val+1) = DB1_STRING;
+	VAL_NULL(val+1) = 0;
+	VAL_STRING(val+1) = "dummy_domain";
+
+	if(ul_dbf.query(con, key, 0, val, col, (use_domain)?2:1, 1, 0, &res)<0) {
+		if(res) ul_dbf.free_result( con, res);
 		LM_ERR("failure in db_query\n");
 		return -1;
 	}
diff --git a/modules/usrloc/udomain.h b/modules/usrloc/udomain.h
index 6f2d295..b6c71b0 100644
--- a/modules/usrloc/udomain.h
+++ b/modules/usrloc/udomain.h
@@ -1,6 +1,4 @@
 /*
- * $Id$ 
-
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,11 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/*
- * History:
- * --------
- *  2003-03-11  changed to new locking scheme: locking.h (andrei)
- */
 
 
 /*! \file
diff --git a/modules/usrloc/ul_callback.c b/modules/usrloc/ul_callback.c
index 43f6b5b..2768c9e 100644
--- a/modules/usrloc/ul_callback.c
+++ b/modules/usrloc/ul_callback.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,9 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2004-03-16  created (bogdan)
  */
 
 /*! \file
diff --git a/modules/usrloc/ul_callback.h b/modules/usrloc/ul_callback.h
index 167cfad..0899780 100644
--- a/modules/usrloc/ul_callback.h
+++ b/modules/usrloc/ul_callback.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,9 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2004-03-16  created (bogdan)
  */
 
 /*! \file
diff --git a/modules/usrloc/ul_mi.c b/modules/usrloc/ul_mi.c
index 6ec82a5..561b387 100644
--- a/modules/usrloc/ul_mi.c
+++ b/modules/usrloc/ul_mi.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2006 Voice Sistem SRL
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,10 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * ---------
- *
- * 2006-12-01  created (bogdan)
  */
 
 /*! \file
diff --git a/modules/usrloc/ul_mi.h b/modules/usrloc/ul_mi.h
index 7f10ab3..ca4ce01 100644
--- a/modules/usrloc/ul_mi.h
+++ b/modules/usrloc/ul_mi.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2006 Voice Sistem SRL
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/usrloc/ul_mod.c b/modules/usrloc/ul_mod.c
index 5992258..1ad69e3 100644
--- a/modules/usrloc/ul_mod.c
+++ b/modules/usrloc/ul_mod.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Usrloc module interface
  *
  * Copyright (C) 2001-2003 FhG Fokus
@@ -21,16 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * ---------
- * 2003-01-27 timer activity printing #ifdef-ed to EXTRA_DEBUG (jiri)
- * 2003-03-11 New module interface (janakj)
- * 2003-03-12 added replication and state columns (nils)
- * 2003-03-16 flags export parameter added (janakj)
- * 2003-04-05: default_uri #define used (jiri)
- * 2003-04-21 failed fifo init stops init process (jiri)
- * 2004-03-17 generic callbacks added (bogdan)
- * 2004-06-07 updated to the new DB api (andrei)
  */
 
 /*! \file
@@ -90,6 +78,10 @@ MODULE_VERSION
 #define INSTANCE_COL   "instance"
 #define REG_ID_COL     "reg_id"
 #define LAST_MOD_COL   "last_modified"
+#define SRV_ID_COL     "server_id"
+#define CON_ID_COL     "connection_id"
+#define KEEPALIVE_COL  "keepalive"
+#define PARTITION_COL  "partition"
 
 #define ULATTRS_USER_COL       "username"
 #define ULATTRS_DOMAIN_COL     "domain"
@@ -149,6 +141,10 @@ str methods_col     = str_init(METHODS_COL);	/*!< Name of column containing the
 str instance_col    = str_init(INSTANCE_COL);	/*!< Name of column containing the SIP instance value */
 str reg_id_col      = str_init(REG_ID_COL);		/*!< Name of column containing the reg-id value */
 str last_mod_col    = str_init(LAST_MOD_COL);	/*!< Name of column containing the last modified date */
+str srv_id_col      = str_init(SRV_ID_COL);		/*!< Name of column containing the server id value */
+str con_id_col      = str_init(CON_ID_COL);		/*!< Name of column containing the connection id value */
+str keepalive_col   = str_init(KEEPALIVE_COL);	/*!< Name of column containing the keepalive value */
+str partition_col   = str_init(PARTITION_COL);	/*!< Name of column containing the partition value */
 
 str ulattrs_user_col   = str_init(ULATTRS_USER_COL);   /*!< Name of column containing username */
 str ulattrs_domain_col = str_init(ULATTRS_DOMAIN_COL); /*!< Name of column containing domain */
@@ -164,6 +160,7 @@ int db_mode         = 0;				/*!< Database sync scheme: 0-no db, 1-write through,
 int use_domain      = 0;				/*!< Whether usrloc should use domain part of aor */
 int desc_time_order = 0;				/*!< By default do not enable timestamp ordering */
 int handle_lost_tcp = 0;				/*!< By default do not remove contacts before expiration time */
+int close_expired_tcp = 0;				/*!< By default do not close TCP connections for expired contacts */
 
 int ul_fetch_rows = 2000;				/*!< number of rows to fetch from result */
 int ul_hash_size = 10;
@@ -213,12 +210,16 @@ static param_export_t params[] = {
 	{"methods_column",      PARAM_STR, &methods_col   },
 	{"instance_column",     PARAM_STR, &instance_col  },
 	{"reg_id_column",       PARAM_STR, &reg_id_col    },
+	{"server_id_column",    PARAM_STR, &srv_id_col    },
+	{"connection_id_column",PARAM_STR, &con_id_col    },
+	{"keepalive_column",    PARAM_STR, &keepalive_col },
 	{"matching_mode",       INT_PARAM, &matching_mode   },
 	{"cseq_delay",          INT_PARAM, &cseq_delay      },
 	{"fetch_rows",          INT_PARAM, &ul_fetch_rows   },
 	{"hash_size",           INT_PARAM, &ul_hash_size    },
 	{"nat_bflag",           INT_PARAM, &nat_bflag       },
 	{"handle_lost_tcp",     INT_PARAM, &handle_lost_tcp },
+	{"close_expired_tcp",   INT_PARAM, &close_expired_tcp },
 	{"preload",             PARAM_STRING|USE_FUNC_PARAM, (void*)ul_preload_param},
 	{"db_update_as_insert", INT_PARAM, &ul_db_update_as_insert},
 	{"timer_procs",         INT_PARAM, &ul_timer_procs},
diff --git a/modules/usrloc/ul_mod.h b/modules/usrloc/ul_mod.h
index 9064cfc..1e3b08d 100644
--- a/modules/usrloc/ul_mod.h
+++ b/modules/usrloc/ul_mod.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * User location module interface
  *
  * Copyright (C) 2001-2003 FhG Fokus
@@ -21,8 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * ---------
  */
 
 /*! \file
@@ -43,7 +39,7 @@
  */
 
 
-#define UL_TABLE_VERSION 6
+#define UL_TABLE_VERSION 8
 
 extern str ruid_col;
 extern str user_col;
@@ -62,6 +58,10 @@ extern str sock_col;
 extern str methods_col;
 extern str instance_col;
 extern str reg_id_col;
+extern str srv_id_col;
+extern str con_id_col;
+extern str keepalive_col;
+extern str partition_col;
 extern str last_mod_col;
 
 extern str ulattrs_user_col;
@@ -85,6 +85,8 @@ extern int ul_db_update_as_insert;
 extern int ul_db_check_update;
 extern int ul_keepalive_timeout;
 extern int handle_lost_tcp;
+extern int close_expired_tcp;
+
 
 /*! nat branch flag */
 extern unsigned int nat_bflag;
diff --git a/modules/usrloc/ul_rpc.c b/modules/usrloc/ul_rpc.c
index 938328e..c4e234e 100644
--- a/modules/usrloc/ul_rpc.c
+++ b/modules/usrloc/ul_rpc.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * usrloc module
  *
  * Copyright (C) 2009 Daniel-Constantin Mierla (asipto.com).
diff --git a/modules/usrloc/ul_rpc.h b/modules/usrloc/ul_rpc.h
index b0a8c9a..c710765 100644
--- a/modules/usrloc/ul_rpc.h
+++ b/modules/usrloc/ul_rpc.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * usrloc module
  *
  * Copyright (C) 2009 Daniel-Constantin Mierla (asipto.com).
diff --git a/modules/usrloc/urecord.c b/modules/usrloc/urecord.c
index abdc152..36f747b 100644
--- a/modules/usrloc/urecord.c
+++ b/modules/usrloc/urecord.c
@@ -1,6 +1,4 @@
 /*
- * $Id$ 
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,11 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * ---------
- * 2003-03-12 added replication mark and zombie state support (nils)
- * 2004-03-17 generic callbacks added (bogdan)
- * 2004-06-07 updated to the new DB api (andrei)
  */
 
 /*! \file
@@ -41,6 +34,7 @@
 #include "../../ut.h"
 #include "../../hashes.h"
 #include "../../tcp_conn.h"
+#include "../../pass_fd.h"
 #include "ul_mod.h"
 #include "usrloc.h"
 #include "utime.h"
@@ -244,6 +238,31 @@ static inline int is_tcp_alive(ucontact_t *c)
 }
 
 /*!
+ * \brief Close a TCP connection
+ *
+ * Requests the TCP main process to close the specified TCP connection
+ * \param conid the internal connection ID
+ */
+static inline int close_connection(int conid) {
+	struct tcp_connection *con;
+	long msg[2];
+	int n;
+	if ((con = tcpconn_get(conid, 0, 0, 0, 0))) {
+		msg[0] = (long)con;
+		msg[1] = CONN_EOF;
+
+		n = send_all(unix_tcp_sock, msg, sizeof(msg));
+		tcpconn_put(con);
+		if (unlikely(n <= 0)){
+			LM_ERR("failed to send close request: %s (%d)\n", strerror(errno), errno);
+			return 0;
+		}
+		return 1;
+	}
+	return 0;
+}
+
+/*!
  * \brief Expires timer for NO_DB db_mode
  *
  * Expires timer for NO_DB db_mode, process all contacts from
@@ -254,6 +273,7 @@ static inline void nodb_timer(urecord_t* _r)
 {
 	ucontact_t* ptr, *t;
 
+
 	ptr = _r->contacts;
 
 	while(ptr) {
@@ -271,6 +291,10 @@ static inline void nodb_timer(urecord_t* _r)
 				ptr->aor->len, ZSW(ptr->aor->s),
 				ptr->c.len, ZSW(ptr->c.s));
 
+			if (close_expired_tcp && is_valid_tcpconn(ptr)) {
+				close_connection(ptr->tcpconn_id);
+			}
+
 			t = ptr;
 			ptr = ptr->next;
 
@@ -308,6 +332,10 @@ static inline void wt_timer(urecord_t* _r)
 				ptr->aor->len, ZSW(ptr->aor->s),
 				ptr->c.len, ZSW(ptr->c.s));
 
+			if (close_expired_tcp && is_valid_tcpconn(ptr)) {
+				close_connection(ptr->tcpconn_id);
+			}
+
 			t = ptr;
 			ptr = ptr->next;
 
@@ -357,6 +385,10 @@ static inline void wb_timer(urecord_t* _r)
 				ptr->c.len, ZSW(ptr->c.s));
 			update_stat( _r->slot->d->expires, 1);
 
+			if (close_expired_tcp && is_valid_tcpconn(ptr)) {
+				close_connection(ptr->tcpconn_id);
+			}
+
 			t = ptr;
 			ptr = ptr->next;
 
@@ -539,11 +571,20 @@ int insert_ucontact(urecord_t* _r, str* _contact, ucontact_info_t* _ci,
 		return -1;
 	}
 
+	if (db_mode==DB_ONLY) {
+		if (db_insert_ucontact(*_c) < 0) {
+			LM_ERR("failed to insert in database\n");
+			return -1;
+		} else {
+			(*_c)->state = CS_SYNC;
+		}
+	}
+
 	if (exists_ulcb_type(UL_CONTACT_INSERT)) {
 		run_ul_callbacks( UL_CONTACT_INSERT, *_c);
 	}
 
-	if (db_mode == WRITE_THROUGH || db_mode==DB_ONLY) {
+	if (db_mode == WRITE_THROUGH) {
 		if (db_insert_ucontact(*_c) < 0) {
 			LM_ERR("failed to insert in database\n");
 			return -1;
diff --git a/modules/usrloc/urecord.h b/modules/usrloc/urecord.h
index 64eb507..54ad5b4 100644
--- a/modules/usrloc/urecord.h
+++ b/modules/usrloc/urecord.h
@@ -1,6 +1,4 @@
 /*
- * $Id$ 
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/usrloc/usrloc.c b/modules/usrloc/usrloc.c
index 1399bd5..0ac3d73 100644
--- a/modules/usrloc/usrloc.c
+++ b/modules/usrloc/usrloc.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,11 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * ========
- *
- * 2006-11-28 Added a new function to the usrloc_api, to retrieve the number
- *            of registered users.  (Jeffrey Magder - SOMA Networks)
  */
 
 /*! \file
@@ -81,6 +74,7 @@ int bind_usrloc(usrloc_api_t* api)
 
 	api->set_keepalive_timeout    = ul_set_keepalive_timeout;
 	api->refresh_keepalive        = ul_refresh_keepalive;
+	api->set_max_partition        = ul_set_max_partition;
 
 	api->use_domain = use_domain;
 	api->db_mode    = db_mode;
diff --git a/modules/usrloc/usrloc.h b/modules/usrloc/usrloc.h
index 82490ae..5688e8c 100644
--- a/modules/usrloc/usrloc.h
+++ b/modules/usrloc/usrloc.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
@@ -61,6 +59,7 @@ typedef enum cstate {
 typedef enum flags {
 	FL_NONE        = 0,          /*!< No flags set */
 	FL_MEM         = 1 << 0,     /*!< Update memory only */
+	FL_RPL         = 1 << 1,     /*!< DMQ replication */
 	FL_ALL         = (int)0xFFFFFFFF  /*!< All flags set */
 } flags_t;
 
@@ -91,7 +90,9 @@ typedef struct ucontact {
 	unsigned int methods;   /*!< Supported methods */
 	str instance;           /*!< SIP instance value - gruu */
 	unsigned int reg_id;    /*!< reg-id parameters */
-	int tcpconn_id;          /* unique tcp connection id */
+	int server_id;          /*!< server id */
+	int tcpconn_id;         /*!< unique tcp connection id */
+	int keepalive;          /*!< keepalive */
 #ifdef WITH_XAVP
 	sr_xavp_t * xavp;       /*!< per contact xavps */
 #endif
@@ -117,7 +118,9 @@ typedef struct ucontact_info {
 	unsigned int methods;     /*!< supported methods */
 	str instance;             /*!< SIP instance value - gruu */
 	unsigned int reg_id;      /*!< reg-id parameters */
-	int tcpconn_id;
+	int server_id;            /*!< server id */
+	int tcpconn_id;           /*!< connection id */
+	int keepalive;            /*!< keepalive */
 #ifdef WITH_XAVP
 	sr_xavp_t * xavp;         /*!< per contact xavps */
 #endif
@@ -191,6 +194,9 @@ int ul_set_keepalive_timeout(int _to);
 typedef int (*ul_refresh_keepalive_t)(unsigned int _aorhash, str *_ruid);
 int ul_refresh_keepalive(unsigned int _aorhash, str *_ruid);
 
+
+typedef void (*ul_set_max_partition_t)(unsigned int m);
+
 /*! usrloc API export structure */
 typedef struct usrloc_api {
 	int           use_domain; /*! use_domain module parameter */
@@ -223,6 +229,7 @@ typedef struct usrloc_api {
 
 	ul_set_keepalive_timeout_t set_keepalive_timeout;
 	ul_refresh_keepalive_t     refresh_keepalive;
+	ul_set_max_partition_t     set_max_partition;
 } usrloc_api_t;
 
 
diff --git a/modules/usrloc/utime.c b/modules/usrloc/utime.c
index ddcc611..d3069c9 100644
--- a/modules/usrloc/utime.c
+++ b/modules/usrloc/utime.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Usrloc time related functions
  *
  * Copyright (C) 2001-2003 FhG Fokus
diff --git a/modules/usrloc/utime.h b/modules/usrloc/utime.h
index 5543b6a..128fca2 100644
--- a/modules/usrloc/utime.h
+++ b/modules/usrloc/utime.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Usrloc time related functions
  *
  * Copyright (C) 2001-2003 FhG Fokus
diff --git a/modules/utils/conf.c b/modules/utils/conf.c
index d0bcc3d..a29b76f 100644
--- a/modules/utils/conf.c
+++ b/modules/utils/conf.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2009 1&1 Internet AG
  *
  * This file is part of Kamailio, a free SIP server.
@@ -22,7 +20,7 @@
 
 /*!
  * \file
- * \brief SIP-router utils :: 
+ * \brief Kamailio utils :: 
  * \ingroup utils
  * Module: \ref utils
  */
diff --git a/modules/utils/conf.h b/modules/utils/conf.h
index c08cc03..193ce6b 100644
--- a/modules/utils/conf.h
+++ b/modules/utils/conf.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2009 1&1 Internet AG
  *
  * This file is part of Kamailio, a free SIP server.
@@ -22,7 +20,7 @@
 
 /*!
  * \file
- * \brief SIP-router utils :: 
+ * \brief Kamailio utils :: 
  * \ingroup utils
  * Module: \ref utils
  */
diff --git a/modules/utils/functions.c b/modules/utils/functions.c
index 2b252e9..3bfcb26 100644
--- a/modules/utils/functions.c
+++ b/modules/utils/functions.c
@@ -24,7 +24,7 @@
 
 /*!
  * \file
- * \brief SIP-router utils :: 
+ * \brief Kamailio utils :: 
  * \ingroup utils
  * Module: \ref utils
  */
@@ -46,24 +46,30 @@
 /* 
  * curl write function that saves received data as zero terminated
  * to stream. Returns the amount of data taken care of.
+ *
+ * This function may be called multiple times for larger responses, 
+ * so it reallocs + concatenates the buffer as needed.
  */
-size_t write_function( void *ptr, size_t size, size_t nmemb, void *stream)
+size_t write_function( void *ptr, size_t size, size_t nmemb, void *stream_ptr)
 {
-    /* Allocate memory and copy */
-    char* data;
+    http_res_stream_t *stream = (http_res_stream_t *) stream_ptr;
+
+    stream->buf = (char *) pkg_realloc(stream->buf, stream->curr_size + 
+				(size * nmemb) + 1);
 
-    data = (char*)pkg_malloc((size* nmemb) + 1);
-    if (data == NULL) {
+    if (stream->buf == NULL) {
 	LM_ERR("cannot allocate memory for stream\n");
 	return CURLE_WRITE_ERROR;
     }
 
-    memcpy(data, (char*)ptr, size* nmemb);
-    data[nmemb] = '\0';
-        
-    *((char**) stream) = data;
-    
-    return size* nmemb;
+    memcpy(&stream->buf[stream->pos], (char *) ptr, (size * nmemb));
+
+    stream->curr_size += ((size * nmemb) + 1);
+    stream->pos += (size * nmemb);
+
+    stream->buf[stream->pos + 1] = '\0';
+
+    return size * nmemb;
  }
 
 
@@ -77,12 +83,14 @@ int http_query(struct sip_msg* _m, char* _url, char* _dst, char* _post)
     CURLcode res;  
     str value, post_value;
     char *url, *at, *post;
-    char* stream;
+    http_res_stream_t stream;
     long stat;
     pv_spec_t *dst;
     pv_value_t val;
     double download_size;
 
+    memset(&stream, 0, sizeof(http_res_stream_t));
+
     if (fixup_get_svalue(_m, (gparam_p)_url, &value) != 0) {
 	LM_ERR("cannot get page value\n");
 	return -1;
@@ -130,7 +138,6 @@ int http_query(struct sip_msg* _m, char* _url, char* _dst, char* _post)
     curl_easy_setopt(curl, CURLOPT_NOSIGNAL, (long)1);
     curl_easy_setopt(curl, CURLOPT_TIMEOUT, (long)http_query_timeout);
 
-    stream = NULL;
     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_function);
     curl_easy_setopt(curl, CURLOPT_WRITEDATA, &stream);
 
@@ -151,8 +158,8 @@ int http_query(struct sip_msg* _m, char* _url, char* _dst, char* _post)
 		}
 	
 		curl_easy_cleanup(curl);
-		if(stream)
-			pkg_free(stream);
+		if(stream.buf)
+			pkg_free(stream.buf);
 		return -1;
     }
 
@@ -160,14 +167,15 @@ int http_query(struct sip_msg* _m, char* _url, char* _dst, char* _post)
     if ((stat >= 200) && (stat < 500)) {
 	curl_easy_getinfo(curl, CURLINFO_SIZE_DOWNLOAD, &download_size);
 	LM_DBG("http_query download size: %u\n", (unsigned int)download_size);
+
 	/* search for line feed */
-	at = memchr(stream, (char)10, download_size);
+	at = memchr(stream.buf, (char)10, download_size);
 	if (at == NULL) {
 	    /* not found: use whole stream */
-	    at = stream + (unsigned int)download_size;
+	    at = stream.buf + (unsigned int)download_size;
 	}
-	val.rs.s = stream;
-	val.rs.len = at - stream;
+	val.rs.s = stream.buf;
+	val.rs.len = at - stream.buf;
 	LM_DBG("http_query result: %.*s\n", val.rs.len, val.rs.s);
 	val.flags = PV_VAL_STR;
 	dst = (pv_spec_t *)_dst;
@@ -175,6 +183,6 @@ int http_query(struct sip_msg* _m, char* _url, char* _dst, char* _post)
     }
 	
     curl_easy_cleanup(curl);
-    pkg_free(stream);
+    pkg_free(stream.buf);
     return stat;
 }
diff --git a/modules/utils/functions.h b/modules/utils/functions.h
index 95b422a..230d119 100644
--- a/modules/utils/functions.h
+++ b/modules/utils/functions.h
@@ -24,7 +24,7 @@
 
 /*!
  * \file
- * \brief SIP-router utils :: 
+ * \brief Kamailio utils :: 
  * \ingroup utils
  * Module: \ref utils
  */
diff --git a/modules/utils/pidf.c b/modules/utils/pidf.c
index 352a8f8..358ad42 100644
--- a/modules/utils/pidf.c
+++ b/modules/utils/pidf.c
@@ -1,6 +1,4 @@
 /*
- * $Id: pidf.c 1953 2007-04-04 08:50:33Z anca_vamanu $
- *
  * presence module - presence server implementation
  *
  * Copyright (C) 2006 Voice Sistem S.R.L.
@@ -21,13 +19,10 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2007-04-14  initial version (anca)
  */
 
 /*! \file
- * \brief SIP-router ::  PIDF handling
+ * \brief Kamailio ::  PIDF handling
  * \ingroup utils
  */
 
diff --git a/modules/utils/pidf.h b/modules/utils/pidf.h
index 9d307f3..fa9ad5b 100644
--- a/modules/utils/pidf.h
+++ b/modules/utils/pidf.h
@@ -1,6 +1,4 @@
 /*
- * $Id: pidf.h 1401 2006-12-14 11:12:42Z anca_vamanu $
- *
  * presence module - presence server implementation
  *
  * Copyright (C) 2006 Voice Sistem S.R.L.
@@ -21,13 +19,10 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2006-08-15  initial version (anca)
  */
 
 /*! \file
- * \brief SIP-router utils :: PIDF handling
+ * \brief Kamailio utils :: PIDF handling
  * \ingroup utils
  */
 
diff --git a/modules/utils/utils.c b/modules/utils/utils.c
index f94bf3b..f506fa5 100644
--- a/modules/utils/utils.c
+++ b/modules/utils/utils.c
@@ -21,18 +21,14 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * -------
- * 2008-11-24: Introduced utils module and its first function: http_query.
- *
  */
 
 /*! \file
- * \brief SIP-router utils :: Module core
+ * \brief Kamailio utils :: Module core
  * \ingroup utils
  */
 
-/*! \defgroup Utils SIP-router :: Various utilities
+/*! \defgroup Utils Kamailio :: Various utilities
  *
  */
 
diff --git a/modules/utils/utils.h b/modules/utils/utils.h
index a601b51..66063f5 100644
--- a/modules/utils/utils.h
+++ b/modules/utils/utils.h
@@ -23,7 +23,7 @@
 
 /*!
  * \file
- * \brief SIP-router utils :: Core
+ * \brief Kamailio utils :: Core
  * \ingroup utils
  * Module: \ref utils
  */
@@ -40,4 +40,10 @@ extern int http_query_timeout;
 extern db1_con_t *pres_dbh;
 extern db_func_t pres_dbf;
 
+typedef struct {
+	char		*buf;
+	size_t		curr_size;
+	size_t		pos;
+} http_res_stream_t;
+
 #endif /* UTILS_H */
diff --git a/modules/utils/xcap_auth.c b/modules/utils/xcap_auth.c
index eb8064b..35ef6b0 100644
--- a/modules/utils/xcap_auth.c
+++ b/modules/utils/xcap_auth.c
@@ -21,15 +21,11 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2007-04-11  initial version (anca)
- *  2009-06-03  util version (jh)
  */
 
 /*!
  * \file
- * \brief SIP-router utils :: 
+ * \brief Kamailio utils :: 
  * \ingroup utils
  * Module: \ref utils
  */
diff --git a/modules/utils/xcap_auth.h b/modules/utils/xcap_auth.h
index 6dd93a4..0ce6997 100644
--- a/modules/utils/xcap_auth.h
+++ b/modules/utils/xcap_auth.h
@@ -24,7 +24,7 @@
 
 /*!
  * \file
- * \brief SIP-router utils :: 
+ * \brief Kamailio utils :: 
  * \ingroup utils
  * Module: \ref utils
  */
diff --git a/modules/websocket/Makefile b/modules/websocket/Makefile
index b28f0ab..915c81a 100644
--- a/modules/websocket/Makefile
+++ b/modules/websocket/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
diff --git a/modules/websocket/README b/modules/websocket/README
index 49d8693..270b5e2 100644
--- a/modules/websocket/README
+++ b/modules/websocket/README
@@ -4,7 +4,7 @@ Peter Dunkley
 
    Crocodile RCS Ltd
 
-   Copyright © 2012-2013 Crocodile RCS Ltd
+   Copyright � 2012-2013 Crocodile RCS Ltd
      __________________________________________________________________
 
    Table of Contents
@@ -129,11 +129,11 @@ Chapter 1. Admin Guide
 2.1. Initiating a connection
 
    A WebSocket connection is initiated with an HTTP GET. The xhttp module
-   is used to handle this GET and call the Section 5.1, “
-   ws_handle_handshake() ” exported function.
+   is used to handle this GET and call the Section 5.1, "
+   ws_handle_handshake() " exported function.
 
    event_route[xhttp:request] should perform some validation of the HTTP
-   headers before calling Section 5.1, “ ws_handle_handshake() ”. The
+   headers before calling Section 5.1, " ws_handle_handshake() ". The
    event_route can also be used to make sure the HTTP GET has the correct
    URI, perform HTTP authentication on the WebSocket connection, and check
    the Origin header (RFC 6454) to ensure a browser-based SIP UA or MSRP
@@ -299,6 +299,7 @@ onreply_route[WS_REPLY] {
 
    The following module must be loaded before this module:
      * sl.
+     * tm.
 
    The following modules are required to make proper use of this module:
      * nathelper or outbound.
@@ -436,7 +437,7 @@ modparam("websocket", "cors_mode", 2)
    5.1. ws_handle_handshake()
    5.2. ws_close([status, reason[, connection_id]])
 
-5.1.  ws_handle_handshake()
+5.1. ws_handle_handshake()
 
    This function checks an HTTP GET request for the required headers and
    values, and (if successful) upgrades the connection from HTTP to
@@ -455,7 +456,7 @@ Note
 ws_handle_handshake();
 ...
 
-5.2.  ws_close([status, reason[, connection_id]])
+5.2. ws_close([status, reason[, connection_id]])
 
    This function closes a WebSocket connection.
 
@@ -496,7 +497,7 @@ ws_close(4000, "Because I say so");
    Name: ws.dump
 
    Parameters:
-     * order (optional) - “id_hash”, “used_desc”, or “used_asc”.
+     * order (optional) - "id_hash", "used_desc", or "used_asc".
 
 Note
 
@@ -581,7 +582,7 @@ Note
 
    7.1. websocket:closed
 
-7.1.  websocket:closed
+7.1. websocket:closed
 
    When defined, the module calls event_route[websocket:closed] when a
    connection closes. The connection may be identified using the the $si
diff --git a/modules/websocket/config.c b/modules/websocket/config.c
index 4fc73e0..0747d88 100644
--- a/modules/websocket/config.c
+++ b/modules/websocket/config.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2012-2013 Crocodile RCS Ltd
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/websocket/config.h b/modules/websocket/config.h
index bf70f0c..a866f15 100644
--- a/modules/websocket/config.h
+++ b/modules/websocket/config.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2012-2013 Crocodile RCS Ltd
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/websocket/doc/websocket_admin.xml b/modules/websocket/doc/websocket_admin.xml
index fa7d300..a46b7e1 100644
--- a/modules/websocket/doc/websocket_admin.xml
+++ b/modules/websocket/doc/websocket_admin.xml
@@ -218,6 +218,9 @@ onreply_route[WS_REPLY] {
 		<listitem>
 		<para><emphasis>sl</emphasis>.</para>
 		</listitem>
+		<listitem>
+		<para><emphasis>tm</emphasis>.</para>
+		</listitem>
 		</itemizedlist>
 		</para>
 		<para>
diff --git a/modules/websocket/utf8_decode.h b/modules/websocket/utf8_decode.h
index bb2d4bf..4853d41 100644
--- a/modules/websocket/utf8_decode.h
+++ b/modules/websocket/utf8_decode.h
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (c) 2008-2010 Bjoern Hoehrmann <bjoern at hoehrmann.de>
  *
  * MIT License
diff --git a/modules/websocket/ws_conn.c b/modules/websocket/ws_conn.c
index 06f7b13..87d593d 100644
--- a/modules/websocket/ws_conn.c
+++ b/modules/websocket/ws_conn.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2012-2013 Crocodile RCS Ltd
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/websocket/ws_conn.h b/modules/websocket/ws_conn.h
index ef4635e..029d570 100644
--- a/modules/websocket/ws_conn.h
+++ b/modules/websocket/ws_conn.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2012-2013 Crocodile RCS Ltd
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/websocket/ws_frame.c b/modules/websocket/ws_frame.c
index a6b4f90..e890770 100644
--- a/modules/websocket/ws_frame.c
+++ b/modules/websocket/ws_frame.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2012-2013 Crocodile RCS Ltd
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/websocket/ws_frame.h b/modules/websocket/ws_frame.h
index 7479605..8e45a1e 100644
--- a/modules/websocket/ws_frame.h
+++ b/modules/websocket/ws_frame.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2012-2013 Crocodile RCS Ltd
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/websocket/ws_handshake.c b/modules/websocket/ws_handshake.c
index 37c61bb..f8dae83 100644
--- a/modules/websocket/ws_handshake.c
+++ b/modules/websocket/ws_handshake.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2012-2013 Crocodile RCS Ltd
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/websocket/ws_handshake.h b/modules/websocket/ws_handshake.h
index 9d46b1d..eb110d5 100644
--- a/modules/websocket/ws_handshake.h
+++ b/modules/websocket/ws_handshake.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2012-2013 Crocodile RCS Ltd
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/websocket/ws_mod.c b/modules/websocket/ws_mod.c
index ecebca3..827dd61 100644
--- a/modules/websocket/ws_mod.c
+++ b/modules/websocket/ws_mod.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2012-2013 Crocodile RCS Ltd
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/websocket/ws_mod.h b/modules/websocket/ws_mod.h
index f9ce213..b267cf9 100644
--- a/modules/websocket/ws_mod.h
+++ b/modules/websocket/ws_mod.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2012-2013 Crocodile RCS Ltd
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/xcap_client/Makefile b/modules/xcap_client/Makefile
index 89b3563..9921313 100644
--- a/modules/xcap_client/Makefile
+++ b/modules/xcap_client/Makefile
@@ -1,4 +1,3 @@
-# $Id: Makefile $
 #
 # XCAP client for Kamailio
 #
diff --git a/modules/xcap_client/xcap_callbacks.c b/modules/xcap_client/xcap_callbacks.c
index ef4f0ce..45e4d20 100644
--- a/modules/xcap_client/xcap_callbacks.c
+++ b/modules/xcap_client/xcap_callbacks.c
@@ -1,6 +1,4 @@
 /*
- * $Id: xcap_callback.c,v 1.2 2007/02/20 13:40:09 anca_vamanu Exp $
- *
  * xcap_client module - Kamailio xcap client module
  *
  * Copyright (C) 2007 Voice Sistem S.R.L.
@@ -21,9 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *	
- *History:
- *--------
- *  2007-08-30  initial version (anca)
  */
 
 #include <stdio.h>
diff --git a/modules/xcap_client/xcap_callbacks.h b/modules/xcap_client/xcap_callbacks.h
index ff5789c..f9d357b 100644
--- a/modules/xcap_client/xcap_callbacks.h
+++ b/modules/xcap_client/xcap_callbacks.h
@@ -1,6 +1,4 @@
 /*
- * $Id: xcap_callback.h,v 1.2 2007/02/20 13:40:09 anca_vamanu Exp $
- *
  * xcap_client module - Kamailio xcap client module
  *
  * Copyright (C) 2007 Voice Sistem S.R.L.
@@ -21,9 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *	
- *History:
- *--------
- *  2007-08-30  initial version (anca)
  */
 
 #ifndef XCAP_CBACK
diff --git a/modules/xcap_client/xcap_client.c b/modules/xcap_client/xcap_client.c
index d5818aa..aa78996 100644
--- a/modules/xcap_client/xcap_client.c
+++ b/modules/xcap_client/xcap_client.c
@@ -1,6 +1,4 @@
 /*
- * $Id: xcap_client.c 2230 2007-06-06 07:13:20Z anca_vamanu $
- *
  * xcap_client module - XCAP client for Kamailio
  *
  * Copyright (C) 2007 Voice Sistem S.R.L.
@@ -21,9 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2007-08-20  initial version (anca)
  */
 
 #include <stdio.h>
diff --git a/modules/xcap_client/xcap_client.h b/modules/xcap_client/xcap_client.h
index 2f3e24a..df8735b 100644
--- a/modules/xcap_client/xcap_client.h
+++ b/modules/xcap_client/xcap_client.h
@@ -1,6 +1,4 @@
 /*
- * $Id: xcap_client.h 2230 2007-06-06 07:13:20Z anca_vamanu $
- *
  * xcap_client module - XCAP client for Kamailio
  *
  * Copyright (C) 2007 Voice Sistem S.R.L.
@@ -21,9 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2007-08-20  initial version (anca)
  */
 
 #ifndef XCAP_CL_H
diff --git a/modules/xcap_client/xcap_functions.c b/modules/xcap_client/xcap_functions.c
index 3a2c3bb..c29d08e 100644
--- a/modules/xcap_client/xcap_functions.c
+++ b/modules/xcap_client/xcap_functions.c
@@ -1,6 +1,4 @@
 /*
- * $Id: xcap_functions.c 2230 2007-06-06 07:13:20Z anca_vamanu $
- *
  * xcap_client module - XCAP client for Kamailio
  *
  * Copyright (C) 2007 Voice Sistem S.R.L.
@@ -21,9 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2007-08-20  initial version (anca)
  */
 
 #include <stdio.h>
diff --git a/modules/xcap_client/xcap_functions.h b/modules/xcap_client/xcap_functions.h
index 09507bb..5756cde 100644
--- a/modules/xcap_client/xcap_functions.h
+++ b/modules/xcap_client/xcap_functions.h
@@ -1,6 +1,4 @@
 /*
- * $Id: xcap_functions.h 2230 2007-06-06 07:13:20Z anca_vamanu $
- *
  * xcap_client module - XCAP client for Kamailio
  *
  * Copyright (C) 2007 Voice Sistem S.R.L.
@@ -21,9 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2007-08-20  initial version (anca)
  */
 
 #ifndef XCAP_FUNC_H
diff --git a/modules/xcap_server/Makefile b/modules/xcap_server/Makefile
index 62e3404..f185454 100644
--- a/modules/xcap_server/Makefile
+++ b/modules/xcap_server/Makefile
@@ -1,4 +1,3 @@
-# $Id: Makefile $
 #
 # XCAP server for Kamailio
 #
diff --git a/modules/xhttp/Makefile b/modules/xhttp/Makefile
index 86634cb..ad71332 100644
--- a/modules/xhttp/Makefile
+++ b/modules/xhttp/Makefile
@@ -1,5 +1,4 @@
-# $Id$
-#
+# xhttp - Web server for Kamailio
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
 
diff --git a/modules/xhttp/README b/modules/xhttp/README
index 92ec726..c40302b 100644
--- a/modules/xhttp/README
+++ b/modules/xhttp/README
@@ -69,16 +69,17 @@ Chapter 1. Admin Guide
 
 1. Overview
 
-   This module provides basic HTTP/1.0 server functionality inside SIP
-   Router. SIP and HTTP are very similar protocols, so, practically, the
+   This module provides basic HTTP/1.0 server functionality inside
+   Kamailio. SIP and HTTP are very similar protocols, so, practically, the
    SIP parser can easily handle HTTP requests just by adding a fake Via
    header.
 
-   The xmlrpc module uses the same concept. xHTTP module offers a generic
-   HTTP handling way, by calling event_route[xhttp:request] in your
-   config. You can check the HTTP URL via config variable $hu. Note that
-   use of $ru will raise errors since the structure of an HTTP URL is not
-   compatible with that of a SIP URI.
+   The <module>xmlrpc</module> module uses the same concept. The xHTTP
+   module offers a generic way of handling the HTTP protocol, by calling
+   event_route[xhttp:request] in your config. You can check the HTTP URL
+   via the config variable $hu. Note that use of $ru will raise errors
+   since the structure of an HTTP URL is not compatible with that of a SIP
+   URI.
 
 2. Note on Latency
 
@@ -140,7 +141,7 @@ Chapter 1. Admin Guide
 
 4.1. url_skip (str)
 
-   Regular expression to match the HTTP URL. If there is a match, then
+   Regular expression to match the HTTP URL. If there is a match, the
    event route is not executed.
 
    Default value is null (don't skip).
@@ -152,7 +153,7 @@ modparam("xhttp", "url_skip", "^/RPC2")
 
 4.2. url_match (str)
 
-   Regular expression to match the HTTP URL. If there is no match, then
+   Regular expression to match the HTTP URL. If there is no match, the
    event route is not executed. This check is done after url_skip, so if
    both url_skip and url_match would match then the event route is not
    executed (url_skip has higher priority).
diff --git a/modules/xhttp/api.h b/modules/xhttp/api.h
index b62f901..674f453 100644
--- a/modules/xhttp/api.h
+++ b/modules/xhttp/api.h
@@ -1,5 +1,4 @@
 /**
- * $Id$
  *
  * Copyright (C) 2010 Daniel-Constantin Mierla (asipto.com)
  *
diff --git a/modules/xhttp/doc/xhttp_admin.xml b/modules/xhttp/doc/xhttp_admin.xml
index 05981b4..248975b 100644
--- a/modules/xhttp/doc/xhttp_admin.xml
+++ b/modules/xhttp/doc/xhttp_admin.xml
@@ -16,17 +16,19 @@
 	<section>
 	<title>Overview</title>
 	<para>
-		This module provides basic HTTP/1.0 server functionality inside SIP
-		Router. SIP and HTTP are very similar protocols, so, practically, the
+		This module provides basic HTTP/1.0 server functionality inside 
+		&kamailio;. SIP and HTTP are very similar protocols, so, practically, the
 		SIP parser can easily handle HTTP requests just by adding a fake
 		Via header.
 	</para>
 	<para>
-		The xmlrpc module uses the same concept. xHTTP module offers a
-		generic HTTP handling way, by calling event_route[xhttp:request]
-		in your config. You can check the HTTP URL via config variable
-		$hu. Note that use of $ru will raise errors since the structure 
-		of an HTTP URL is not compatible with that of a SIP URI.
+		The <module>xmlrpc</module> module uses the same concept.
+		The xHTTP module offers a generic way of handling the <acronym>HTTP</acronym>
+		protocol, by calling <emphasis>event_route[xhttp:request]</emphasis>
+		in your config. You can check the HTTP URL via the config variable
+		<acronym>$hu</acronym>. Note that use of <acronym>$ru</acronym> will
+		raise errors since the structure of an HTTP URL is not compatible with
+		that of a SIP URI.
 	</para>
 	</section>
 
@@ -54,7 +56,8 @@
 		SIP processing.  SIP worker threads will block, pending the outcome of the 
 		event route just like any other config script route.  
 	</para>
-	<para>  This is no more or less true for <emphasis>xhttp</emphasis> than it is for 
+	<para>
+		This is no more or less true for <emphasis>xhttp</emphasis> than it is for 
 		any other block of script in any other scenario, and does not warrant any 
 		extraordinary concern.  It nevertheless bears mention here because some 
 		processes with embedded HTTP servers have the request processing take place 
@@ -115,7 +118,7 @@
 		<title><varname>url_skip</varname> (str)</title>
 		<para>
 			Regular expression to match the HTTP URL. If there is a match,
-			then event route is not executed.
+			the event route is not executed.
 		</para>
 		<para>
 		<emphasis>
@@ -135,7 +138,7 @@ modparam("xhttp", "url_skip", "^/RPC2")
 		<title><varname>url_match</varname> (str)</title>
 		<para>
 			Regular expression to match the HTTP URL. If there is no match,
-			then event route is not executed. This check is done after
+			the event route is not executed. This check is done after
 			url_skip, so if both url_skip and url_match would match then
 			the event route is not executed (url_skip has higher priority).
 		</para>
diff --git a/modules/xhttp/xhttp_mod.c b/modules/xhttp/xhttp_mod.c
index 9085af3..912d75c 100644
--- a/modules/xhttp/xhttp_mod.c
+++ b/modules/xhttp/xhttp_mod.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2010 Daniel-Constantin Mierla (asipto.com)
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/modules/xhttp/xhttp_trans.c b/modules/xhttp/xhttp_trans.c
index 6b207d9..03e4ea8 100644
--- a/modules/xhttp/xhttp_trans.c
+++ b/modules/xhttp/xhttp_trans.c
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- *
  * Copyright (C) 2013 Crocodile RCS Ltd
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,6 +17,7 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
+
 #include "../../pvar.h"
 #include "../../str.h"
 #include "../../trim.h"
diff --git a/modules/xhttp/xhttp_trans.h b/modules/xhttp/xhttp_trans.h
index cb4ca61..18e19c8 100644
--- a/modules/xhttp/xhttp_trans.h
+++ b/modules/xhttp/xhttp_trans.h
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- *
  * Copyright (C) 2013 Crocodile RCS Ltd
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,6 +17,7 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
+
 #ifndef XHTTP_TRANS_H_
 #define XHTTP_TRANS_H_
 
diff --git a/modules/xhttp_pi/Makefile b/modules/xhttp_pi/Makefile
index 1400bfd..a7c2e5b 100644
--- a/modules/xhttp_pi/Makefile
+++ b/modules/xhttp_pi/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
diff --git a/modules/xhttp_pi/http_db_handler.c b/modules/xhttp_pi/http_db_handler.c
index c762382..cb8b5bc 100644
--- a/modules/xhttp_pi/http_db_handler.c
+++ b/modules/xhttp_pi/http_db_handler.c
@@ -17,9 +17,13 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * 2012-10-18  initial version (osas)
  */
-
+/*!
+ * \file
+ * \brief XHTTP_PI :: 
+ * \ingroup xhttp_pi
+ * Module: \ref xhttp_pi
+ */
 
 #include <stdio.h>
 #include <stdlib.h>
diff --git a/modules/xhttp_pi/http_db_handler.h b/modules/xhttp_pi/http_db_handler.h
index 1e80890..3fef42e 100644
--- a/modules/xhttp_pi/http_db_handler.h
+++ b/modules/xhttp_pi/http_db_handler.h
@@ -17,7 +17,13 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * 2012-10-18  initial version (osas)
+ */
+
+/*!
+ * \file
+ * \brief XHTTP_PI ::  DB handler
+ * \ingroup xhttp_pi
+ * Module: \ref xhttp_pi
  */
 
 
diff --git a/modules/xhttp_pi/xhttp_pi.c b/modules/xhttp_pi/xhttp_pi.c
index 4fbe5d7..511ebc5 100644
--- a/modules/xhttp_pi/xhttp_pi.c
+++ b/modules/xhttp_pi/xhttp_pi.c
@@ -17,7 +17,16 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * 2012-10-18  initial version (osas)
+ */
+
+/*!
+ * \file
+ * \brief XHTTP_PI :: Module interface (main file)
+ * \ingroup xhttp_pi
+ * Module: \ref xhttp_pi
+ *
+ * This is the main file of xhttp_pi module which contains all the functions
+ * related to http processing, as well as the module interface.
  */
 
 #include <string.h>
@@ -43,11 +52,6 @@
  * It is built on top of the xhttp API module.
  */
 
-/** @file
- *
- * This is the main file of xhttp_pi module which contains all the functions
- * related to http processing, as well as the module interface.
- */
 
 MODULE_VERSION
 
diff --git a/modules/xhttp_pi/xhttp_pi.h b/modules/xhttp_pi/xhttp_pi.h
index 5d44e69..eeef37b 100644
--- a/modules/xhttp_pi/xhttp_pi.h
+++ b/modules/xhttp_pi/xhttp_pi.h
@@ -17,9 +17,14 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * 2012-10-18  initial version (osas)
  */
 
+/*!
+ * \file
+ * \brief XHTTP_PI :: 
+ * \ingroup xhttp_pi
+ * Module: \ref xhttp_pi
+ */
 
 #ifndef _XHTTP_PI_H
 #define _XHTTP_PI_H
diff --git a/modules/xhttp_pi/xhttp_pi_fnc.c b/modules/xhttp_pi/xhttp_pi_fnc.c
index a51e692..9bacee5 100644
--- a/modules/xhttp_pi/xhttp_pi_fnc.c
+++ b/modules/xhttp_pi/xhttp_pi_fnc.c
@@ -17,7 +17,13 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * 2012-10-18  initial version (osas)
+ */
+
+/*!
+ * \file
+ * \brief XHTTP_PI :: 
+ * \ingroup xhttp_pi
+ * Module: \ref xhttp_pi
  */
 
 #include <libxml/parser.h>
diff --git a/modules/xhttp_pi/xhttp_pi_fnc.h b/modules/xhttp_pi/xhttp_pi_fnc.h
index 980c8ed..b324635 100644
--- a/modules/xhttp_pi/xhttp_pi_fnc.h
+++ b/modules/xhttp_pi/xhttp_pi_fnc.h
@@ -17,9 +17,14 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * 2012-10-18  initial version (osas)
  */
 
+/*!
+ * \file
+ * \brief XHTTP_PI :: 
+ * \ingroup xhttp_pi
+ * Module: \ref xhttp_pi
+ */
 
 #ifndef _XHTTP_PI_FNC_H
 #define _XHTTP_PI_FNC_H
diff --git a/modules/xhttp_rpc/Makefile b/modules/xhttp_rpc/Makefile
index c829b7a..8e99e09 100644
--- a/modules/xhttp_rpc/Makefile
+++ b/modules/xhttp_rpc/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
diff --git a/modules/xhttp_rpc/xhttp_rpc.c b/modules/xhttp_rpc/xhttp_rpc.c
index 4e0bef2..7f6f791 100644
--- a/modules/xhttp_rpc/xhttp_rpc.c
+++ b/modules/xhttp_rpc/xhttp_rpc.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2011 VoIP Embedded, Inc.
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,7 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * 2011-11-11  initial version (osas)
  */
 
 #include <string.h>
diff --git a/modules/xhttp_rpc/xhttp_rpc.h b/modules/xhttp_rpc/xhttp_rpc.h
index 2cb423c..74662de 100644
--- a/modules/xhttp_rpc/xhttp_rpc.h
+++ b/modules/xhttp_rpc/xhttp_rpc.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2011 VoIP Embedded, Inc.
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,7 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * 2011-11-11  initial version (osas)
  */
 
 
diff --git a/modules/xhttp_rpc/xhttp_rpc_fnc.c b/modules/xhttp_rpc/xhttp_rpc_fnc.c
index da4c0c9..6975d1f 100644
--- a/modules/xhttp_rpc/xhttp_rpc_fnc.c
+++ b/modules/xhttp_rpc/xhttp_rpc_fnc.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2011 VoIP Embedded, Inc.
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,7 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * 2011-11-11  initial version (osas)
  */
 
 #include <string.h>
diff --git a/modules/xhttp_rpc/xhttp_rpc_fnc.h b/modules/xhttp_rpc/xhttp_rpc_fnc.h
index db1ba79..980fa4a 100644
--- a/modules/xhttp_rpc/xhttp_rpc_fnc.h
+++ b/modules/xhttp_rpc/xhttp_rpc_fnc.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2011 VoIP Embedded, Inc.
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,7 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * 2011-11-11  initial version (osas)
  */
 
 
diff --git a/modules/xlog/Makefile b/modules/xlog/Makefile
index 74bccc6..9f03ca4 100644
--- a/modules/xlog/Makefile
+++ b/modules/xlog/Makefile
@@ -1,6 +1,5 @@
-# $Id$
 #
-# example module makefile
+# xlog module makefile
 #
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
diff --git a/modules/xlog/README b/modules/xlog/README
index c770cf6..219734b 100644
--- a/modules/xlog/README
+++ b/modules/xlog/README
@@ -35,6 +35,7 @@ Elena-Ramona Modroiu
               4.4. prefix (str)
               4.5. log_facility (string)
               4.6. log_colors (string)
+              4.7. methods_filter (int)
 
         5. Functions
 
@@ -42,6 +43,7 @@ Elena-Ramona Modroiu
               5.2. xdbg(format)
               5.3. xlogl([ [facility,] level,] format)
               5.4. xdbgl(format)
+              5.5. xlogm(level, format)
 
    List of Examples
 
@@ -51,8 +53,9 @@ Elena-Ramona Modroiu
    1.4. Set prefix parameter
    1.5. log_facility example
    1.6. log_colors example
-   1.7. xlog usage
-   1.8. xdbg usage
+   1.7. Set methods_filter parameter
+   1.8. xlog usage
+   1.9. xdbg usage
 
 Chapter 1. Admin Guide
 
@@ -73,6 +76,7 @@ Chapter 1. Admin Guide
         4.4. prefix (str)
         4.5. log_facility (string)
         4.6. log_colors (string)
+        4.7. methods_filter (int)
 
    5. Functions
 
@@ -80,14 +84,14 @@ Chapter 1. Admin Guide
         5.2. xdbg(format)
         5.3. xlogl([ [facility,] level,] format)
         5.4. xdbgl(format)
+        5.5. xlogm(level, format)
 
 1. Overview
 
    This module provides the possibility to print user formatted log or
    debug messages from Kamailio scripts, similar to the printf function. A
    C-style printf specifier is replaced with a part of the SIP request or
-   other variables from system. Section 2, "Implemented Specifiers" shows
-   what can be printed out.
+   other variables from system.
 
 2. Implemented Specifiers
 
@@ -97,7 +101,7 @@ Chapter 1. Admin Guide
 
    The most important changes from earlier versions of Kamailio are:
      * - '%' has been replaced by '$'
-     * - to print a header, use now $hdr(header_name[index]) instead of
+     * - to print a header, use $hdr(header_name[index]) instead of
        %{header_name[index]}
      * - to print an AVP, use now $avp([si]:avp_id[index]) instead of
        %{[si]:avp_id[index]} or $avp([$avp_alias[index]) instead of
@@ -114,7 +118,9 @@ Chapter 1. Admin Guide
 3.1. Kamailio Modules
 
    The following modules must be loaded before this module:
-     * No dependencies on other Kamailio modules.
+     * No dependencies on other Kamailio modules. Note that many modules
+       publish pseudovariables that you can use in this module. The core
+       module for this is the pv module.
 
 3.2. External Libraries or Applications
 
@@ -130,6 +136,7 @@ Chapter 1. Admin Guide
    4.4. prefix (str)
    4.5. log_facility (string)
    4.6. log_colors (string)
+   4.7. methods_filter (int)
 
 4.1. buf_size (integer)
 
@@ -144,7 +151,8 @@ modparam("xlog", "buf_size", 8192)
 
 4.2. force_color (integer)
 
-   When set to 1, forces color printing even if log_stderror=0.
+   When set to 1, forces color codes in log messages even if log_stderror
+   is set to 0.
 
    Default value is 0.
 
@@ -155,8 +163,8 @@ modparam("xlog", "force_color", 0)
 
 4.3. long_format (integer)
 
-   When set to 1, prints config file name in xlogl() and xdbgl() before
-   line number.
+   When set to 1, outputs the configuration file name in xlogl() and
+   xdbgl() before the line number.
 
    Default value is 0.
 
@@ -167,7 +175,7 @@ modparam("xlog", "long_format", 1)
 
 4.4. prefix (str)
 
-   Prefix to be printed before the log message.
+   Prefix to be output before the log message.
 
    Default value is "<script>: ".
 
@@ -178,9 +186,9 @@ modparam("xlog", "prefix", "-xlog: ")
 
 4.5. log_facility (string)
 
-   Syslog facility to be used when printing xlog messages. In this way you
-   can get the xlog messages in a separate syslog file than the debug
-   messages issued from source code.
+   Syslog facility to be used for the xlog output. By setting this, and
+   configuring syslog, you can get the xlog messages in a separate syslog
+   file than the debug messages issued from the source code.
 
    Default value is NULL (unset - use same facility as source code debug
    messages).
@@ -190,13 +198,13 @@ modparam("xlog", "log_facility", "LOG_DAEMON")
 
 4.6. log_colors (string)
 
-   Update terminal colors used by core for log levels (when log_stderr=1
-   and log_color=1). The value has to be 'logname=colors', where colors is
-   two characters specifying foreground and background in the same format
-   as $C(xy) variable.
+   Update terminal colors used by the Kamailio core for log levels (when
+   log_stderr=1 and log_color=1). The value has to be 'logname=colors',
+   where colors is two characters specifying foreground and background in
+   the same format as $C(xy) variable.
 
-   The parameter can be set many times, its value can also be a
-   ';'-separated list of color specs.
+   The parameter can be set many times. The value can also be a
+   ';'-separated list of color specifications.
 
    Default value is NULL.
 
@@ -204,20 +212,39 @@ modparam("xlog", "log_facility", "LOG_DAEMON")
 modparam("xlog", "log_colors", "L_ERR=cr")
 modparam("xlog", "log_colors", "L_ERR=cr;L_WARN=px")
 
+4.7. methods_filter (int)
+
+   The bitmask with internal SIP method ids to be ignored by xlogm()
+   function. The value can be changed at runtime via cfg reload framework:
+...
+kamcmd cfg.set_now_int xlog methods_filter 15
+...
+
+   To see the associated internal ids for SIP requests, look in source
+   tree inside parser/msg_parser.h for enum request_method.
+
+   Default value is -1 (all SIP methods are ignored).
+
+   Example 1.7. Set methods_filter parameter
+...
+modparam("xlog", "long_format", 1)
+...
+
 5. Functions
 
    5.1. xlog([ [facility,] level,] format)
    5.2. xdbg(format)
    5.3. xlogl([ [facility,] level,] format)
    5.4. xdbgl(format)
+   5.5. xlogm(level, format)
 
 5.1. xlog([ [facility,] level,] format)
 
-   Print a formated message using LOG function.
+   Output a formated log message.
 
    Meaning of the parameters are as follows:
-     * facility - The log facility that will be used for this single log
-       message.
+     * facility - The syslog facility that will be used for this single
+       log message.
        If this parameter is missing, the implicit facility is either the
        facility set with the 'log_facility' module parameter or the core's
        log facility.
@@ -240,7 +267,7 @@ modparam("xlog", "log_colors", "L_ERR=cr;L_WARN=px")
 
    This function can be used from ANY_ROUTE.
 
-   Example 1.7. xlog usage
+   Example 1.8. xlog usage
 ...
 xlog("L_ERR", "time [$Tf] method ($rm) r-uri ($ru) 2nd via ($hdr(via[1]))\n");
 ...
@@ -262,7 +289,7 @@ CAL3\n");
 
    This function can be used from ANY_ROUTE.
 
-   Example 1.8. xdbg usage
+   Example 1.9. xdbg usage
 ...
 xdbg("time $Cbx[$Tf]$Cxx method ($rm) r-uri ($ru)\n");
 ...
@@ -276,3 +303,9 @@ xdbg("time $Cbx[$Tf]$Cxx method ($rm) r-uri ($ru)\n");
 
    Similar to xdbg(), in addition prints configuration file line number at
    the beginning of message.
+
+5.5. xlogm(level, format)
+
+   Similar to xlog(level, format), but skips writing the log messages for
+   SIP requests and responses that match the SIP method id with
+   methods_filter parameter value.
diff --git a/modules/xlog/doc/xlog_admin.xml b/modules/xlog/doc/xlog_admin.xml
index dad27a6..d800941 100644
--- a/modules/xlog/doc/xlog_admin.xml
+++ b/modules/xlog/doc/xlog_admin.xml
@@ -13,15 +13,13 @@
 	
 	<title>&adminguide;</title>
 	
-	<section>
+	<section id="xlog.overview">
 	<title>Overview</title>
 	<para>
 		This module provides the possibility to print user formatted log or
 		debug messages from &kamailio; scripts, similar to the printf function. 
 		A C-style printf specifier is replaced with a part of the &sip; request or other
 		variables from system.
-		<xref linkend="sec-implemented-specifiers"/> shows what can be printed
-		out.
 	</para>
 	</section>
 	<section id="sec-implemented-specifiers">
@@ -42,7 +40,7 @@
 		</listitem>
 		<listitem>
 		<para>
-		- to print a header, use now $hdr(header_name[index]) instead of
+		- to print a header, use $hdr(header_name[index]) instead of
 		%{header_name[index]}
 		</para>
 		</listitem>
@@ -71,6 +69,8 @@
 			<listitem>
 			<para>
 				<emphasis>No dependencies on other &kamailio; modules</emphasis>.
+				Note that many modules publish pseudovariables that you can use
+				in this module. The core module for this is the <emphasis>pv</emphasis> module.
 			</para>
 			</listitem>
 			</itemizedlist>
@@ -115,7 +115,7 @@ modparam("xlog", "buf_size", 8192)
 	<section id="xlog.p.force_color">
 		<title><varname>force_color</varname> (integer)</title>
 		<para>
-		When set to 1, forces color printing even if log_stderror=0.
+		When set to 1, forces color codes in log messages even if <varname>log_stderror</varname> is set to 0.
 		</para>
 		<para>
 		<emphasis>
@@ -134,8 +134,8 @@ modparam("xlog", "force_color", 0)
 	<section id="xlog.p.long_format">
 		<title><varname>long_format</varname> (integer)</title>
 		<para>
-		When set to 1, prints config file name in xlogl() and xdbgl()
-		before line number.
+		When set to 1, outputs the configuration file name in xlogl() and xdbgl()
+		before the line number.
 		</para>
 		<para>
 		<emphasis>
@@ -154,7 +154,7 @@ modparam("xlog", "long_format", 1)
 	<section id="xlog.p.varname">
 		<title><varname>prefix</varname> (str)</title>
 		<para>
-		Prefix to be printed before the log message.
+		Prefix to be output before the log message.
 		</para>
 		<para>
 		<emphasis>
@@ -173,9 +173,9 @@ modparam("xlog", "prefix", "-xlog: ")
 	<section id="xlog.p.log_facility">
 		<title><varname>log_facility</varname> (string)</title>
 		<para>
-		Syslog facility to be used when printing xlog messages.
-		In this way you can get the xlog messages in a separate syslog file
-		than the debug messages issued from source code.
+		Syslog facility to be used for the xlog output.
+		By setting this, and configuring syslog, you can get the xlog messages 
+		in a separate syslog file than the debug messages issued from the source code.
 		</para>
 		<para>
 		Default value is NULL (unset - use same facility as source code debug
@@ -191,14 +191,14 @@ modparam("xlog", "log_facility", "LOG_DAEMON")
 	<section id="xlog.p.log_colors">
 		<title><varname>log_colors</varname> (string)</title>
 		<para>
-		Update terminal colors used by core for log levels (when log_stderr=1
+		Update terminal colors used by the &kamailio; core for log levels (when log_stderr=1
 		and log_color=1). The value has to be 'logname=colors', where colors
 		is two characters specifying foreground and background in the same
 		format as $C(xy) variable.
 		</para>
 		<para>
-		The parameter can be set many times, its value can also be a
-		';'-separated list of color specs.
+		The parameter can be set many times. The value can also be a
+		';'-separated list of color specifications.
 		</para>
 		<para>
 		Default value is NULL.
@@ -211,6 +211,36 @@ modparam("xlog", "log_colors", "L_ERR=cr;L_WARN=px")
 </programlisting>
 		</example>
 	</section>
+	<section id="xlog.p.methods_filter">
+		<title><varname>methods_filter</varname> (int)</title>
+		<para>
+		The bitmask with internal SIP method ids to be ignored by
+		xlogm() function. The value can be changed at runtime via
+		cfg reload framework:
+		</para>
+		<programlisting format="linespecific">
+...
+kamcmd cfg.set_now_int xlog methods_filter 15
+...
+</programlisting>
+		<para>
+		To see the associated internal ids for SIP requests, look
+		in source tree inside parser/msg_parser.h for enum request_method.
+		</para>
+		<para>
+		<emphasis>
+			Default value is -1 (all SIP methods are ignored).
+		</emphasis>
+		</para>
+		<example>
+		<title>Set <varname>methods_filter</varname> parameter</title>
+		<programlisting format="linespecific">
+...
+modparam("xlog", "long_format", 1)
+...
+</programlisting>
+		</example>
+	</section>
 
 	</section>
 	<section>
@@ -220,12 +250,12 @@ modparam("xlog", "log_colors", "L_ERR=cr;L_WARN=px")
 		<function moreinfo="none">xlog([ [facility,] level,] format)</function>
 		</title>
 		<para>
-		Print a formated message using LOG function.
+		Output a formated log message.
 		</para>
 		<para>Meaning of the parameters are as follows:</para>
 		<itemizedlist>
 		<listitem>
-			<para><emphasis>facility</emphasis> - The log facility that will be used for this single log message.
+			<para><emphasis>facility</emphasis> - The syslog facility that will be used for this single log message.
 			</para>
 			<para>
 			If this parameter is missing, the implicit facility is either the facility set with
@@ -363,6 +393,16 @@ xdbg("time $Cbx[$Tf]$Cxx method ($rm) r-uri ($ru)\n");
 		at the beginning of message.
 		</para>
 	</section>
+	<section id="xlog.f.xlogm">
+		<title>
+		<function moreinfo="none">xlogm(level, format)</function>
+		</title>
+		<para>
+			Similar to xlog(level, format), but skips writing the log messages
+			for SIP requests and responses that match the SIP method id with
+			methods_filter parameter value.
+		</para>
+	</section>
 	</section>
 </chapter>
 
diff --git a/modules/xlog/xl_lib.c b/modules/xlog/xl_lib.c
index 3e95068..24798f3 100644
--- a/modules/xlog/xl_lib.c
+++ b/modules/xlog/xl_lib.c
@@ -1,6 +1,4 @@
-/**
- * $Id$
- *
+/*
  * XLOG module
  *
  * Copyright (C) 2001-2003 FhG Fokus
@@ -22,15 +20,16 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
  * History:
- * --------
- * 2004-10-20 - added header name specifier (ramona)
- * 2005-06-14 - added avp name specifier (ramona)
- * 2005-06-18 - added color printing support via escape sequesnces
- *              contributed by Ingo Flaschberger (daniel)
- * 2005-06-22 - moved item methods to "items.{c,h}" (daniel)
  * 
  */
 
+/*!
+ * \file
+ * \brief Library
+ * \ingroup xlog
+ * Module: \ref xlog
+ */
+
 #include "xl_lib.h"
 
 int xl_print_log(struct sip_msg* msg, pv_elem_p list, char *buf, int *len)
diff --git a/modules/xlog/xl_lib.h b/modules/xlog/xl_lib.h
index 23065af..742885a 100644
--- a/modules/xlog/xl_lib.h
+++ b/modules/xlog/xl_lib.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,6 +17,12 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
+/*!
+ * \file
+ * \brief Library
+ * \ingroup xlog
+ * Module: \ref xlog
+ */
 
 #ifndef _XL_LIB_H_
 #define _XL_LIB_H_
diff --git a/modules/xlog/xlog.c b/modules/xlog/xlog.c
index 9855261..61947af 100644
--- a/modules/xlog/xlog.c
+++ b/modules/xlog/xlog.c
@@ -1,6 +1,4 @@
 /**
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,6 +17,20 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
+/*!
+ * \file
+ * \brief Module interface
+ * \ingroup xlog
+ * Module: \ref xlog
+ */
+
+/**
+ * @defgroup xlog xlog :: Kamailio xlog module
+ * @brief Kamailio xlog module
+ * Extended logging from the configuration script using pv:s.
+ * Can log to multiple channels as well as standard out.
+ *
+ */
 
 #include <stdio.h>
 #include <string.h>
@@ -33,6 +45,7 @@
 #include "../../sr_module.h"
 #include "../../dprint.h"
 #include "../../error.h"
+#include "../../cfg/cfg.h"
 #include "../../mem/mem.h"
 #include "../../parser/parse_param.h"
 
@@ -54,6 +67,20 @@ static int long_format=0;
 static int xlog_facility = DEFAULT_FACILITY;
 static char *xlog_facility_name = NULL;
 
+/** cfg dynamic parameters */
+struct cfg_group_xlog {
+	int methods_filter;
+};
+static struct cfg_group_xlog xlog_default_cfg = {
+	-1	/* methods filter */
+};
+static void *xlog_cfg = &xlog_default_cfg;
+static cfg_def_t xlog_cfg_def[] = {
+	{"methods_filter",		CFG_VAR_INT | CFG_ATOMIC, 	0, 0, 0, 0,
+		"Methods filter value for xlogm(...)."},
+	{0, 0, 0, 0, 0, 0}
+};
+
 /** module functions */
 static int mod_init(void);
 
@@ -67,6 +94,8 @@ static int xlogl_2(struct sip_msg*, char*, char*);
 static int xlogl_3(struct sip_msg*, char*, char*, char*);
 static int xdbgl(struct sip_msg*, char*, char*);
 
+static int xlogm_2(struct sip_msg*, char*, char*);
+
 static int xlog_fixup(void** param, int param_no);
 static int xlog3_fixup(void** param, int param_no);
 static int xdbg_fixup(void** param, int param_no);
@@ -113,6 +142,7 @@ static cmd_export_t cmds[]={
 	{"xlogl",  (cmd_function)xlogl_2,  2, xlogl_fixup, 0, ANY_ROUTE},
 	{"xlogl",  (cmd_function)xlogl_3,  3, xlogl3_fixup,0, ANY_ROUTE},
 	{"xdbgl",  (cmd_function)xdbgl,    1, xdbgl_fixup, 0, ANY_ROUTE},
+	{"xlogm",  (cmd_function)xlogm_2,  2, xlog_fixup,  0, ANY_ROUTE},
 	{0,0,0,0,0,0}
 };
 
@@ -124,6 +154,7 @@ static param_export_t params[]={
 	{"prefix",       PARAM_STRING, &_xlog_prefix},
 	{"log_facility", PARAM_STRING, &xlog_facility_name},
 	{"log_colors",   PARAM_STRING|USE_FUNC_PARAM, (void*)xlog_log_colors_param},
+	{"methods_filter",  PARAM_INT, &xlog_default_cfg.methods_filter},
 	{0,0,0}
 };
 
@@ -150,6 +181,11 @@ struct module_exports exports= {
 static int mod_init(void)
 {
 	int lf;
+	if(cfg_declare("xlog", xlog_cfg_def, &xlog_default_cfg,
+				cfg_sizeof(xlog), &xlog_cfg)){
+		LM_ERR("Fail to declare the xlog cfg framework structure\n");
+		return -1;
+	}
 	if (xlog_facility_name!=NULL) {
 		lf = str2facility(xlog_facility_name);
 		if (lf != -1) {
@@ -264,6 +300,35 @@ static int xlogl_2(struct sip_msg* msg, char* lev, char* frm)
 	return xlog_2_helper(msg, lev, frm, 1, NOFACILITY);
 }
 
+/**
+ * print log message to level given in parameter applying methods filter
+ */
+static int xlogm_2(struct sip_msg* msg, char* lev, char* frm)
+{
+	int mfilter;
+
+	mfilter = cfg_get(xlog, xlog_cfg, methods_filter);
+
+	if(mfilter==-1)
+		return 1;
+
+	if(msg->first_line.type==SIP_REQUEST) {
+		if (msg->first_line.u.request.method_value & mfilter) {
+			return 1;
+		}
+	} else {
+		if (parse_headers(msg, HDR_CSEQ_F, 0) != 0 || msg->cseq==NULL) {
+			LM_ERR("cannot parse cseq header\n");
+			return -1;
+		}
+		if (get_cseq(msg)->method_id & mfilter) {
+			return 1;
+		}
+	}
+
+	return xlog_2_helper(msg, lev, frm, 0, NOFACILITY);
+}
+
 static int xlog_3_helper(struct sip_msg* msg, char* fac, char* lev, char* frm, int mode)
 {
 	long level;
diff --git a/modules/xmlops/Makefile b/modules/xmlops/Makefile
index a55c4a1..7622dc9 100644
--- a/modules/xmlops/Makefile
+++ b/modules/xmlops/Makefile
@@ -1,5 +1,5 @@
 #
-# XML operations 
+# XMLOPS: XML operations 
 # 
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
diff --git a/modules/xmlops/pv_xml.c b/modules/xmlops/pv_xml.c
index f41d1aa..dbaed90 100644
--- a/modules/xmlops/pv_xml.c
+++ b/modules/xmlops/pv_xml.c
@@ -1,5 +1,4 @@
 /**
- * $Id$
  *
  * Copyright (C) 2009 Daniel-Constantin Mierla (asipto.com)
  *
diff --git a/modules/xmlops/pv_xml.h b/modules/xmlops/pv_xml.h
index af3f6cb..fe73f43 100644
--- a/modules/xmlops/pv_xml.h
+++ b/modules/xmlops/pv_xml.h
@@ -1,5 +1,4 @@
 /**
- * $Id$
  *
  * Copyright (C) 2009 Daniel-Constantin Mierla (asipto.com)
  *
diff --git a/modules/xmlops/xmlops_mod.c b/modules/xmlops/xmlops_mod.c
index d0f842b..47bd387 100644
--- a/modules/xmlops/xmlops_mod.c
+++ b/modules/xmlops/xmlops_mod.c
@@ -1,5 +1,4 @@
 /**
- * $Id$
  *
  * Copyright (C) 2009 Daniel-Constantin Mierla (asipto.com)
  *
diff --git a/modules/xmlrpc/README b/modules/xmlrpc/README
index 8bc7a51..1baff31 100644
--- a/modules/xmlrpc/README
+++ b/modules/xmlrpc/README
@@ -11,20 +11,24 @@ Jan Janak
 
    1. Admin Guide
 
-        1. Parameters
+        1. Dependencies
 
-              1.1. route (string)
-              1.2. autoconversion (string)
-              1.3. escape_cr (integer)
-              1.4. double_lf_to_crlf (integer)
-              1.5. mode (integer)
-              1.6. url_skip (str)
-              1.7. url_match (str)
+              1.1. Kamailio modules
 
-        2. Functions
+        2. Parameters
 
-              2.1. dispatch_rpc()
-              2.2. xmlrpc_reply(code, reason)
+              2.1. route (string)
+              2.2. autoconversion (string)
+              2.3. escape_cr (integer)
+              2.4. double_lf_to_crlf (integer)
+              2.5. mode (integer)
+              2.6. url_skip (str)
+              2.7. url_match (str)
+
+        3. Functions
+
+              3.1. dispatch_rpc()
+              3.2. xmlrpc_reply(code, reason)
 
    List of Tables
 
@@ -517,32 +521,45 @@ Chapter 1. Admin Guide
 
    Table of Contents
 
-   1. Parameters
+   1. Dependencies
+
+        1.1. Kamailio modules
+
+   2. Parameters
+
+        2.1. route (string)
+        2.2. autoconversion (string)
+        2.3. escape_cr (integer)
+        2.4. double_lf_to_crlf (integer)
+        2.5. mode (integer)
+        2.6. url_skip (str)
+        2.7. url_match (str)
+
+   3. Functions
+
+        3.1. dispatch_rpc()
+        3.2. xmlrpc_reply(code, reason)
+
+1. Dependencies
 
-        1.1. route (string)
-        1.2. autoconversion (string)
-        1.3. escape_cr (integer)
-        1.4. double_lf_to_crlf (integer)
-        1.5. mode (integer)
-        1.6. url_skip (str)
-        1.7. url_match (str)
+   1.1. Kamailio modules
 
-   2. Functions
+1.1. Kamailio modules
 
-        2.1. dispatch_rpc()
-        2.2. xmlrpc_reply(code, reason)
+   The following modules must be loaded before this module:
+     * SL - Stateless request handling
 
-1. Parameters
+2. Parameters
 
-   1.1. route (string)
-   1.2. autoconversion (string)
-   1.3. escape_cr (integer)
-   1.4. double_lf_to_crlf (integer)
-   1.5. mode (integer)
-   1.6. url_skip (str)
-   1.7. url_match (str)
+   2.1. route (string)
+   2.2. autoconversion (string)
+   2.3. escape_cr (integer)
+   2.4. double_lf_to_crlf (integer)
+   2.5. mode (integer)
+   2.6. url_skip (str)
+   2.7. url_match (str)
 
-1.1. route (string)
+2.1. route (string)
 
    Name of the route called for XMLRPC messages.
 
@@ -560,7 +577,7 @@ Chapter 1. Admin Guide
    Example 1.1. Set route parameter
 modparam("xmlrpc", "route", "route_for_xmlrpcs")
 
-1.2. autoconversion (string)
+2.2. autoconversion (string)
 
    Enable or disable automatic parameter type conversion globally, for all
    the methods parameters. If on, a type mismatch in a method parameter
@@ -577,7 +594,7 @@ modparam("xmlrpc", "route", "route_for_xmlrpcs")
    Example 1.2. Set the autoconversion parameter
 modparam("xmlrpc", "autoconversion", 1)
 
-1.3. escape_cr (integer)
+2.3. escape_cr (integer)
 
    Enable CR ('\r') escaping in replies. If enabled each '\r' in the
    xmlrpc reply will be replaced with "&#xD;", according to the xml spec.
@@ -590,7 +607,7 @@ modparam("xmlrpc", "autoconversion", 1)
    Example 1.3. Set the escape_cr parameter
 modparam("xmlrpc", "escape_cr", 1)
 
-1.4. double_lf_to_crlf (integer)
+2.4. double_lf_to_crlf (integer)
 
    When enabled double LFs ('\n\n') in the input xmlrpc strings will be
    replaced with CR LF ('\r\n'). This makes LF LF behave like an escape
@@ -608,7 +625,7 @@ modparam("xmlrpc", "escape_cr", 1)
    Example 1.4. Set the double_lf_to_crlf parameter
 modparam("xmlrpc", "double_lf_to_crlf", 1)
 
-1.5. mode (integer)
+2.5. mode (integer)
 
    When set to 1, the xmlrpc module does not register to core the callback
    functions for non-SIP messages. Useful when another module register a
@@ -620,7 +637,7 @@ modparam("xmlrpc", "double_lf_to_crlf", 1)
    Example 1.5. Set the mode parameter
 modparam("xmlrpc", "mode", 1)
 
-1.6. url_skip (str)
+2.6. url_skip (str)
 
    Regular expression to match the HTTP URL. If there is a match, then the
    xmlrpc route is not executed.
@@ -632,7 +649,7 @@ modparam("xmlrpc", "mode", 1)
 modparam("xmlrpc", "url_skip", "^/sip")
 ...
 
-1.7. url_match (str)
+2.7. url_match (str)
 
    Regular expression to match the HTTP URL. If there is no match, then
    xmlrpc route is not executed. This check is done after url_skip, so if
@@ -646,12 +663,12 @@ modparam("xmlrpc", "url_skip", "^/sip")
 modparam("xmlrpc", "url_match", "^/RPC2")
 ...
 
-2. Functions
+3. Functions
 
-   2.1. dispatch_rpc()
-   2.2. xmlrpc_reply(code, reason)
+   3.1. dispatch_rpc()
+   3.2. xmlrpc_reply(code, reason)
 
-2.1. dispatch_rpc()
+3.1. dispatch_rpc()
 
    This function processes an XMLRPC request, found in the body of the
    request.
@@ -678,7 +695,7 @@ route[XMLRPC]{
         dispatch_rpc();
 }
 
-2.2. xmlrpc_reply(code, reason)
+3.2. xmlrpc_reply(code, reason)
 
    This function can be called from the config script to directly generate
    an XML-RPC reply.
diff --git a/modules/xmlrpc/doc/xmlrpc.xml b/modules/xmlrpc/doc/xmlrpc.xml
index c975128..1e2dce1 100644
--- a/modules/xmlrpc/doc/xmlrpc.xml
+++ b/modules/xmlrpc/doc/xmlrpc.xml
@@ -31,7 +31,7 @@
 	<section id="xmlrpc.design">
 	<title>Design Goals</title>
 	<para>
-	    
+
 	</para>
 	<itemizedlist>
 	    <listitem>
@@ -99,7 +99,7 @@ User-Agent: Radio UserLand/7.1b7 (WinNT)
 Host: time.xmlrpc.com
 Content-Type: text/xml
 Content-length: 131
-	    
+
 <?xml version="1.0"?>
 <methodCall>
 <methodName>currentTime.getCurrentTime</methodName>
@@ -307,7 +307,7 @@ if (method == "POST" || method == "GET") {
 	    <function>dispatch_rpc</function> scans through the list of all
 	    exported RPC functions searching for the
 	    <function>statistics</function> function of the usrloc module. The
-		<ulink url='http://sip-router.org/docbook/sip-router/branch/master/rpc/ser_rpc.html'>
+		<ulink url='http://rpm.kamailio.org/docbook/sip-router/branch/master/rpc/kamailio_rpc.html'>
 		&kamailio; RPC Module API</ulink>
 		describes in detail how modules export RPC functions.
 	</para>
@@ -367,7 +367,7 @@ Warning: 392 127.0.0.1:5060 "Noisy feedback tells:  pid=9975 req_src_ip=127.0.0
 		HTTP requests from one SIP server to another and use standard
 		SIP routing mechanisms to decide which SIP server should
 		process the request. There is no need to have multiple SIP
-		servers in simple setups, because one SIP server can both add 
+		servers in simple setups, because one SIP server can both add
 		fake Via header field and process the RPC at the same
 		time. Modified configuration file snipped could then look like
 		this:
@@ -659,8 +659,8 @@ Content-Length: 276
 	<section id="xmlrpc.interoperability_problems">
 	    <title>Interoperability Problems</title>
 	    <para>
-		Due to a bug in Python xmlrpclib there is an interoperability 
-		problem with basic clients using it: by default an xmlrpclib client 
+		Due to a bug in Python xmlrpclib there is an interoperability
+		problem with basic clients using it: by default an xmlrpclib client
 		expects the server to immediately close the connection after answering
 		and if the server does not close the connections the xmlrpclib client
 		will wait forever.
@@ -671,7 +671,7 @@ Content-Length: 276
 		make ser close the tcp connection after each request.
 		</para>
 		<para>
-		The <ulink url='http://git.sip-router.org/cgi-bin/gitweb.cgi?p=sip-router;a=blob;f=modules/xmlrpc/examples/xmlrpc_test.py'>
+		The <ulink url='https://github.com/kamailio/kamailio/blob/master/modules/xmlrpc/examples/xmlrpc_test.py'>
 		examples/xmlrpc_test.py
 		</ulink> provides a very simple example of using xmlrpclib with a
 		Transport class that works.
@@ -683,7 +683,7 @@ Content-Length: 276
 		<function>set_reply_no_connect()</function> is also recommended
 		(avoid trying to open tcp connection to xmlrpc clients that closed it).
 		Alternatively ending the XMLRPC route with return -1, exit -1 or
-		drop -1 can also be used, but note that this will not work for 
+		drop -1 can also be used, but note that this will not work for
 		async rpcs (it will close the connection immeidately and not on the
 		async response).
 		<example>
@@ -716,37 +716,44 @@ route[XMLRPC]{
 	<section id="xmlrpc.client_examples">
 	<title>Client Examples</title>
 	<!-- TODO:
-	    implement clients in various languages 
-	- pros, cons 
+	    implement clients in various languages
+	- pros, cons
 	- How failures
-	    are mapped to XMLRPC 
-	- How success replies are mapped 
+	    are mapped to XMLRPC
+	- How success replies are mapped
 	- How data
-	    types of the API are mapped to XMLRPC elements 
+	    types of the API are mapped to XMLRPC elements
 	- 200 OK with no
 	    data transformed to one value - True
 	-->
 	<para>
 	<itemizedlist>
 		<listitem><para>
-			<ulink url='http://git.sip-router.org/cgi-bin/gitweb.cgi?p=sip-router;a=blob;f=modules/xmlrpc/examples/xmlrpc_test.pl'>
+			<ulink url='https://github.com/kamailio/kamailio/blob/master/modules/xmlrpc/examples/xmlrpc_test.pl'>
 			<emphasis>examples/xmlrpc_test.pl</emphasis>
 			</ulink> (basic perl application that builds and sends an
 			<emphasis>XMLRPC</emphasis> request from its commandline
 			parameters).
 		</para></listitem>
 		<listitem><para>
-			<ulink url='http://git.sip-router.org/cgi-bin/gitweb.cgi?p=sip-router;a=blob;f=modules/xmlrpc/examples/xmlrpc_test.py'>
+			<ulink url='https://github.com/kamailio/kamailio/blob/master/modules/xmlrpc/examples/xmlrpc_test.py'>
 			<emphasis>examples/xmlrpc_test.py</emphasis>
 			</ulink> (basic python application that builds and sends an
 			<emphasis>XMLRPC</emphasis> request from its commandline
 			parameters).
 		</para></listitem>
 		<listitem><para>
+			<ulink url='https://github.com/kamailio/kamailio/blob/master/modules/xmlrpc/examples/xmlrpc_test2.py'>
+			<emphasis>examples/xmlrpc_test2.py</emphasis>
+			</ulink> (basic python application that builds and sends an
+			<emphasis>XMLRPC</emphasis> request from its commandline
+			parameters).
+		</para></listitem>
+		<listitem><para>
 			<ulink url='http://git.sip-router.org/cgi-bin/gitweb.cgi?p=ser;a=tree;f=ser_ctl'>
 			<emphasis>ser_ctl</emphasis>
 			</ulink>
-			(complex python application that 
+			(complex python application that
 			uses the <emphasis>XML-RPC</emphasis> interface implemented by the
 			<emphasis>xmlrpc</emphasis> module).
 		</para></listitem>
@@ -755,7 +762,7 @@ route[XMLRPC]{
 			<emphasis>serweb</emphasis>
 			</ulink>
 			(php application that can use
-			the <emphasis>XML-RPC</emphasis> interface to call ser 
+			the <emphasis>XML-RPC</emphasis> interface to call ser
 			functions).
 		</para></listitem>
 	</itemizedlist>
diff --git a/modules/xmlrpc/doc/xmlrpc_admin.xml b/modules/xmlrpc/doc/xmlrpc_admin.xml
index b78f92b..20fe4ce 100644
--- a/modules/xmlrpc/doc/xmlrpc_admin.xml
+++ b/modules/xmlrpc/doc/xmlrpc_admin.xml
@@ -10,6 +10,22 @@
 
 <chapter>
 	<title>&adminguide;</title>
+	<section>
+	<title>Dependencies</title>
+	<section>
+		<title>&kamailio; modules</title>
+		<para>
+		The following modules must be loaded before this module:
+			<itemizedlist>
+			<listitem>
+			<para>
+				<emphasis>SL</emphasis> - Stateless request handling
+			</para>
+			</listitem>
+			</itemizedlist>
+		</para>
+	</section>
+	</section>
 
 	<section>
 	<title>Parameters</title>
diff --git a/modules/xmlrpc/examples/xmlrpc_test2.py b/modules/xmlrpc/examples/xmlrpc_test2.py
index 0fdee1e..b6c02fd 100644
--- a/modules/xmlrpc/examples/xmlrpc_test2.py
+++ b/modules/xmlrpc/examples/xmlrpc_test2.py
@@ -1,10 +1,11 @@
-import xmlrpclib, httplib, sys
+import sys
+import xmlrpclib
 
 # Usage:  python xmlrpc_test2.py command [params...]
 #
 # python script for sending an xmlrpc command to ser's xmlrpc module.
 # This script uses python xmlrpclib directly and expects the remote side to
-# immediately close the connection after answering (broken xmlrpclib 
+# immediately close the connection after answering (broken xmlrpclib
 # behaviour).
 # There are 2 way to make it work with ser xmlrpc module: define a
 # better transport class (that's what the xmlrpc_test.py script is doing) or
@@ -23,7 +24,15 @@ XMLRPC_PORT = 5060
 
 
 if len(sys.argv) < 2:
-	sys.exit("Usage: "+sys.argv[0]+" rpc_command [args...]");
-c=xmlrpclib.ServerProxy("http://" + XMLRPC_SERVER+ ":" + str(XMLRPC_PORT))
-res=getattr(c, sys.argv[1])(*sys.argv[2:])
-print res;
+    sys.exit("Usage: " + sys.argv[0] + " rpc_command [args...]")
+
+client = xmlrpclib.ServerProxy(
+    "http://{0}:{1}".format(XMLRPC_SERVER, XMLRPC_PORT))
+res = getattr(client, sys.argv[1])(*sys.argv[2:])
+print res
+
+#####
+# You can use this simple way.
+#client =xmlrpclib.ServerProxy("http://127.0.0.1:5060")
+#res = client.htable.listTables()
+#print res
diff --git a/modules/xmlrpc/http.c b/modules/xmlrpc/http.c
index b15b0f5..760b70a 100644
--- a/modules/xmlrpc/http.c
+++ b/modules/xmlrpc/http.c
@@ -1,21 +1,15 @@
 /*
- * $Id$
- *
  * Copyright (C) 2005 iptelorg GmbH
  * Written by Jan Janak <jan at iptel.org>
  *
- * This file is part of SER, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SER is free software; you can redistribute it and/or modify it under the
+ * Kamailio is free software; you can redistribute it and/or modify it under the
  * terms of the GNU General Public License as published by the Free Software
  * Foundation; either version 2 of the License, or (at your option) any later
  * version
  *
- * For a license to use the SER software under conditions other than those
- * described here, or to purchase support for this software, please contact
- * iptel.org by e-mail at the following addresses: info at iptel.org
- *
- * SER is distributed in the hope that it will be useful, but WITHOUT ANY
+ * Kamailio is distributed in the hope that it will be useful, but WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
  * details.
diff --git a/modules/xmlrpc/http.h b/modules/xmlrpc/http.h
index 6bc6276..5a4ae84 100644
--- a/modules/xmlrpc/http.h
+++ b/modules/xmlrpc/http.h
@@ -1,21 +1,15 @@
 /*
- * $Id$
- *
  * Copyright (C) 2005 iptelorg GmbH
  * Written by Jan Janak <jan at iptel.org>
  *
- * This file is part of SER, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SER is free software; you can redistribute it and/or modify it under the
+ * Kamailio is free software; you can redistribute it and/or modify it under the
  * terms of the GNU General Public License as published by the Free Software
  * Foundation; either version 2 of the License, or (at your option) any later
  * version
  *
- * For a license to use the SER software under conditions other than those
- * described here, or to purchase support for this software, please contact
- * iptel.org by e-mail at the following addresses: info at iptel.org
- *
- * SER is distributed in the hope that it will be useful, but WITHOUT ANY
+ * Kamailio is distributed in the hope that it will be useful, but WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
  * details.
diff --git a/modules/xmlrpc/xmlrpc.c b/modules/xmlrpc/xmlrpc.c
index e97a3f3..8761c02 100644
--- a/modules/xmlrpc/xmlrpc.c
+++ b/modules/xmlrpc/xmlrpc.c
@@ -2,18 +2,14 @@
  * Copyright (C) 2005 iptelorg GmbH
  * Written by Jan Janak <jan at iptel.org>
  *
- * This file is part of SER, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SER is free software; you can redistribute it and/or modify it under the
+ * Kamailio is free software; you can redistribute it and/or modify it under the
  * terms of the GNU General Public License as published by the Free Software
  * Foundation; either version 2 of the License, or (at your option) any later
  * version
  *
- * For a license to use the SER software under conditions other than those
- * described here, or to purchase support for this software, please contact
- * iptel.org by e-mail at the following addresses: info at iptel.org
- *
- * SER is distributed in the hope that it will be useful, but WITHOUT ANY
+ * Kamailio is distributed in the hope that it will be useful, but WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
  * details.
diff --git a/modules/xmlrpc/xmlrpc.h b/modules/xmlrpc/xmlrpc.h
index 1b6cb17..cb92e42 100644
--- a/modules/xmlrpc/xmlrpc.h
+++ b/modules/xmlrpc/xmlrpc.h
@@ -1,21 +1,15 @@
 /*
- * $Id$
- *
  * Copyright (C) 2005 iptelorg GmbH
  * Written by Jan Janak <jan at iptel.org>
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify it under the
+ * Kamailio is free software; you can redistribute it and/or modify it under the
  * terms of the GNU General Public License as published by the Free Software
  * Foundation; either version 2 of the License, or (at your option) any later
  * version
  *
- * For a license to use the ser software under conditions other than those
- * described here, or to purchase support for this software, please contact
- * iptel.org by e-mail at the following addresses: info at iptel.org
- *
- * ser is distributed in the hope that it will be useful, but WITHOUT ANY
+ * Kamailio is distributed in the hope that it will be useful, but WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
  * details.
diff --git a/modules/xmpp/Makefile b/modules/xmpp/Makefile
index 2cf78f3..cb611fe 100644
--- a/modules/xmpp/Makefile
+++ b/modules/xmpp/Makefile
@@ -1,4 +1,3 @@
-# $Id$
 #
 # xmpp module makefile
 #
diff --git a/modules/xmpp/network.c b/modules/xmpp/network.c
index d748a25..0de7f25 100644
--- a/modules/xmpp/network.c
+++ b/modules/xmpp/network.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * XMPP Module
  * This file is part of Kamailio, a free SIP server.
  *
diff --git a/modules/xmpp/network.h b/modules/xmpp/network.h
index e9500f8..589c247 100644
--- a/modules/xmpp/network.h
+++ b/modules/xmpp/network.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * XMPP Module
  * This file is part of Kamailio, a free SIP server.
  *
@@ -19,13 +17,11 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- *
- * Author: Andreea Spirea
- *
  */
 
 /*! \file
  * \ingroup xmpp
+ * \author Andreea Spirea
  */
 
 
diff --git a/modules/xmpp/sha.c b/modules/xmpp/sha.c
index ec2a295..e1ca80f 100644
--- a/modules/xmpp/sha.c
+++ b/modules/xmpp/sha.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
  *  the Free Software Foundation; either version 2 of the License, or
diff --git a/modules/xmpp/util.c b/modules/xmpp/util.c
index abeafb1..d991014 100644
--- a/modules/xmpp/util.c
+++ b/modules/xmpp/util.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * XMPP Module
  * This file is part of Kamailio, a free SIP server.
  *
diff --git a/modules/xmpp/xmpp.c b/modules/xmpp/xmpp.c
index 1ce590b..2972e84 100644
--- a/modules/xmpp/xmpp.c
+++ b/modules/xmpp/xmpp.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * XMPP Module
  * This file is part of Kamailio, a free SIP server.
  *
diff --git a/modules/xmpp/xmpp.h b/modules/xmpp/xmpp.h
index d1be933..34f290d 100644
--- a/modules/xmpp/xmpp.h
+++ b/modules/xmpp/xmpp.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * XMPP Module
  * This file is part of Kamailio, a free SIP server.
  *
diff --git a/modules/xmpp/xmpp_api.c b/modules/xmpp/xmpp_api.c
index 3f8babd..796b312 100644
--- a/modules/xmpp/xmpp_api.c
+++ b/modules/xmpp/xmpp_api.c
@@ -1,7 +1,5 @@
 
 /*
- * $Id$
- *
  * XMPP Module
  * This file is part of Kamailio, a free SIP server.
  *
diff --git a/modules/xmpp/xmpp_api.h b/modules/xmpp/xmpp_api.h
index aae67d7..0e1a2db 100644
--- a/modules/xmpp/xmpp_api.h
+++ b/modules/xmpp/xmpp_api.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * XMPP Module
  * This file is part of Kamailio, a free SIP server.
  *
diff --git a/modules/xmpp/xmpp_component.c b/modules/xmpp/xmpp_component.c
index 03af940..b84d996 100644
--- a/modules/xmpp/xmpp_component.c
+++ b/modules/xmpp/xmpp_component.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * XMPP Module
  * This file is part of Kamailio, a free SIP server.
  *
@@ -26,9 +24,7 @@
 /*! \file
  * \brief Kamailio XMPP :: XMPP Component interface support
  *  \ingroup xmpp
- */
-
-/*
+ *
  * An inbound SIP message:
  *   from sip:user1 at domain1 to sip:user2*domain2 at gateway_domain
  * is translated to an XMPP message:
diff --git a/modules/xmpp/xmpp_server.c b/modules/xmpp/xmpp_server.c
index 897275f..380dd64 100644
--- a/modules/xmpp/xmpp_server.c
+++ b/modules/xmpp/xmpp_server.c
@@ -1,7 +1,4 @@
 /*
- * $Id$
- *
- * XMPP Module
  * This file is part of Kamailio, a free SIP server.
  *
  * Copyright (C) 2006 Voice Sistem S.R.L.
diff --git a/modules/xmpp/xode.c b/modules/xmpp/xode.c
index 74e9c35..4909f63 100644
--- a/modules/xmpp/xode.c
+++ b/modules/xmpp/xode.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
  *  the Free Software Foundation; either version 2 of the License, or
diff --git a/modules/xmpp/xode.h b/modules/xmpp/xode.h
index 0e04cc0..b4d2513 100644
--- a/modules/xmpp/xode.h
+++ b/modules/xmpp/xode.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
  *  the Free Software Foundation; either version 2 of the License, or
diff --git a/modules/xmpp/xode_from.c b/modules/xmpp/xode_from.c
index 50662cb..f2d9b54 100644
--- a/modules/xmpp/xode_from.c
+++ b/modules/xmpp/xode_from.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
  *  the Free Software Foundation; either version 2 of the License, or
diff --git a/modules/xmpp/xode_str.c b/modules/xmpp/xode_str.c
index ca83e1f..ee8df6a 100644
--- a/modules/xmpp/xode_str.c
+++ b/modules/xmpp/xode_str.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
  *  the Free Software Foundation; either version 2 of the License, or
diff --git a/modules/xmpp/xpool.c b/modules/xmpp/xpool.c
index cc460f8..5a53f0c 100644
--- a/modules/xmpp/xpool.c
+++ b/modules/xmpp/xpool.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
  *  the Free Software Foundation; either version 2 of the License, or
diff --git a/modules/xmpp/xsnprintf.c b/modules/xmpp/xsnprintf.c
index 581bf0d..83b71f1 100644
--- a/modules/xmpp/xsnprintf.c
+++ b/modules/xmpp/xsnprintf.c
@@ -1,6 +1,4 @@
-/* ====================================================================
- * $Id$
- *
+/* 
  * Copyright (c) 1995-1998 The Apache Group.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/modules/xmpp/xstream.c b/modules/xmpp/xstream.c
index 89f3780..b4367b3 100644
--- a/modules/xmpp/xstream.c
+++ b/modules/xmpp/xstream.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
  *  the Free Software Foundation; either version 2 of the License, or
diff --git a/modules/xprint/Makefile b/modules/xprint/Makefile
index cc216d1..bd9fd7e 100644
--- a/modules/xprint/Makefile
+++ b/modules/xprint/Makefile
@@ -1,6 +1,5 @@
-# $Id$
 #
-# example module makefile
+# xprint module makefile
 #
 # 
 # WARNING: do not run this directly, it should be run by the master Makefile
diff --git a/msg_translator.c b/msg_translator.c
index dc2370e..d9c6f45 100644
--- a/msg_translator.c
+++ b/msg_translator.c
@@ -1,22 +1,14 @@
 /*
- * $Id$
- *
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -26,48 +18,9 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
  *
- * History:
- * --------
- * 2003-01-20  bug_fix: use of return value of snprintf aligned to C99 (jiri)
- * 2003-01-23  added rport patches, contributed by
- *              Maxim Sobolev <sobomax at FreeBSD.org> and heavily modified by me
- *              (andrei)
- * 2003-01-24  added i param to via of outgoing requests (used by tcp),
- *              modified via_builder params (andrei)
- * 2003-01-27  more rport fixes (make use of new via_param->start)  (andrei)
- * 2003-01-27  next baby-step to removing ZT - PRESERVE_ZT (jiri)
- * 2003-01-29  scratchpad removed (jiri)
- * 2003-02-28  scratchpad compatibility abandoned (jiri)
- * 2003-03-01  VOICE_MAIL defs removed (jiri)
- * 2003-03-06  totags in outgoing replies bookmarked to enable
- *             ACK/200 tag matching (andrei)
- * 2003-03-18  killed the build_warning snprintf (andrei)
- * 2003-03-31  added subst lump support (andrei)
- * 2003-04-01  added opt (conditional) lump support (andrei)
- * 2003-04-02  added more subst lumps: SUBST_{SND,RCV}_ALL
- *              => ip:port;transport=proto (andrei)
- * 2003-04-12  added FL_FORCE_RPORT support (andrei)
- * 2003-04-13  updated warning builder -- fixed (andrei)
- * 2003-07-10  check_via_address knows now how to compare with ipv6 address
- *              references (e.g [::1]) (andrei)
- *             build_req_fomr_sip_req no longer adds 1 for ipv6 via parameter
- *              position calculations ([] are part of host.s now) (andrei)
- * 2003-10-02  via+lump dst address/port can be set to preset values (andrei)
- * 2003-10-08  receive_test function-alized (jiri)
- * 2003-10-20  added body_lump list (sip_msg), adjust_clen (andrei & jan)
- * 2003-11-11  type of rpl_lumps replaced by flags (bogdan)
- * 2006-04-20  build_req_from_sip_req, via_builder and lump_* functions
- *              use now struct dest_info; lumps & via comp param support
- *              (rfc3486) (andrei)
- * 2007-08-31  id_builder() and via_builder() are grouped into one function:
- *             create_via_hf() -- tm module needs them as well (Miklos)
- * 2008-12-17  build_req_from_sip_req() will now fallback to tcp, tls or sctp
- *              if packet size > udp_mtu and fallback is enabled 
- *             build_req_from_sip_req() uses now global_req_flags along
- *               msg->msg_flags  (andrei)
  *
  */
-/* Via special params:
+/** Via special params:
  * requests:
  * - if the address in via is different from the src_ip or an existing
  *   received=something is found, received=src_ip is added (and any preexisting
@@ -119,7 +72,7 @@
 
 /*!
  * \file
- * \brief SIP-router core :: 
+ * \brief Kamailio core :: Message translations
  * \ingroup core
  * Module: \ref core
  */
@@ -202,8 +155,7 @@ static int check_via_address(struct ip_addr* ip, str *name,
 	/* maybe we are lucky and name it's an ip */
 	s=ip_addr2a(ip);
 	if (s){
-		DBG("check_via_address(%s, %.*s, %d)\n",
-			s, name->len, name->s, resolver);
+		LM_DBG("(%s, %.*s, %d)\n", s, name->len, name->s, resolver);
 
 		len=strlen(s);
 
@@ -228,7 +180,7 @@ static int check_via_address(struct ip_addr* ip, str *name,
 
 	if (port==0) port=SIP_PORT;
 	if (resolver&DO_DNS){
-		DBG("check_via_address: doing dns lookup\n");
+		LM_DBG("doing dns lookup\n");
 		/* try all names ips */
 		lproto = PROTO_NONE;
 		he=sip_resolvehost(name, &port, &lproto); /* don't use naptr */
@@ -240,7 +192,7 @@ static int check_via_address(struct ip_addr* ip, str *name,
 		}
 	}
 	if (resolver&DO_REV_DNS){
-		DBG("check_via_address: doing rev. dns lookup\n");
+		LM_DBG("doing rev. dns lookup\n");
 		/* try reverse dns */
 		he=rev_resolvehost(ip);
 		if (he && (strncmp(he->h_name, name->s, name->len)==0))
@@ -467,7 +419,7 @@ char* clen_builder(	struct sip_msg* msg, int *clen_len, int diff,
 	}
 	value=msg->len-(int)(body-msg->buf)+diff;
 	value_s=int2str(value, &value_len);
-	DBG("clen_builder: content-length: %d (%s)\n", value, value_s);
+	LM_DBG("content-length: %d (%s)\n", value, value_s);
 
 	if (body_only) {
 		len=value_len;
@@ -1397,7 +1349,7 @@ skip_after:
 			case LUMP_DEL:
 				/* copy till offset */
 				if (s_offset>t->u.offset){
-					DBG("Warning: (%d) overlapped lumps offsets,"
+					LM_DBG("WARNING: (%d) overlapped lumps offsets,"
 						" ignoring(%x, %x)\n", t->op, s_offset,t->u.offset);
 					/* this should've been fixed above (when computing len) */
 					/* just ignore it*/
@@ -1570,8 +1522,7 @@ static inline int adjust_clen(struct sip_msg* msg, int body_delta, int proto)
 				}
 				body_only=0;
 			} /* else
-				DBG("adjust_clen: UDP packet with no clen => "
-						"not adding one \n"); */
+				LM_DBG("UDP packet with no clen => not adding one \n"); */
 		}else{
 			/* Content-Length has been found, remove it */
 			anchor = del_lump(	msg, msg->content_length->body.s - msg->buf,
@@ -2275,7 +2226,7 @@ char * generate_res_buf_from_sip_res( struct sip_msg* msg,
 	new_len=len+body_delta+lumps_len(msg, msg->add_rm, 0); /*FIXME: we don't
 														know the send sock */
 
-	DBG(" old size: %d, new size: %d\n", len, new_len);
+	LM_DBG("old size: %d, new size: %d\n", len, new_len);
 	new_buf=(char*)pkg_malloc(new_len+1); /* +1 is for debugging
 											 (\0 to print it )*/
 	if (new_buf==0){
@@ -2292,8 +2243,8 @@ char * generate_res_buf_from_sip_res( struct sip_msg* msg,
 		buf+s_offset,
 		len-s_offset);
 	 /* send it! */
-	DBG("copied size: orig:%d, new: %d, rest: %d"
-			" msg=\n%s\n", s_offset, offset, len-s_offset, new_buf);
+	LM_DBG("copied size: orig:%d, new: %d, rest: %d msg=\n%s\n",
+			s_offset, offset, len-s_offset, new_buf);
 
 	*returned_len=new_len;
 	return new_buf;
@@ -2889,7 +2840,7 @@ char* create_via_hf( unsigned int *len,
 			return 0; /* we don't need to free anything,
 			                 nothing alloc'ed yet*/
 		}
-		DBG("create_via_hf: id added: <%.*s>, rcv proto=%d\n",
+		LM_DBG("id added: <%.*s>, rcv proto=%d\n",
 				(int)id_len, id_buf, msg->rcv.proto);
 		extra_params.s=id_buf;
 		extra_params.len=id_len;
diff --git a/msg_translator.h b/msg_translator.h
index 01b5619..5fa02cf 100644
--- a/msg_translator.h
+++ b/msg_translator.h
@@ -1,21 +1,14 @@
-/*$Id$
- * 
- *
+/*
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,15 +17,16 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2003-03-06  totags in outgoing replies bookmarked to enable
- *             ACK/200 tag matching
- *
- * 2003-03-01 VOICE_MAIL defs removed (jiri)
- * 2003-10-08 receive_test function-alized (jiri)
  */
 
+/*!
+* \file
+* \brief Kamailio core :: Message translations
+* \author jiri
+* \ingroup core
+* Module: \ref core
+*/
+
 
 #ifndef  _MSG_TRANSLATOR_H
 #define _MSG_TRANSLATOR_H
diff --git a/name_alias.h b/name_alias.h
index 3493024..bfc15c8 100644
--- a/name_alias.h
+++ b/name_alias.h
@@ -1,22 +1,15 @@
 /*
- * $Id$
- *
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -25,12 +18,13 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/*
- * History:
- * --------
- *  2003-03-19  replaced all mallocs/frees w/ pkg_malloc/pkg_free (andrei)
- *  2003-10-21  support for proto added: proto:host:port (andrei)
- */
+/*!
+* \file
+* \brief Kamailio core :: Name/alias handling
+* \author andrei
+* \ingroup core
+* Module: \ref core
+*/
 
 
 
@@ -52,7 +46,7 @@ extern struct host_alias* aliases;
 
 
 
-/* returns 1 if  name is in the alias list; if port=0, port no is ignored
+/** returns 1 if  name is in the alias list; if port=0, port no is ignored
  * if proto=0, proto is ignored*/
 static inline int grep_aliases(char* name, int len, unsigned short port,
 								unsigned short proto)
@@ -74,7 +68,7 @@ static inline int grep_aliases(char* name, int len, unsigned short port,
 
 
 
-/* adds an alias to the list (only if it isn't already there)
+/** adds an alias to the list (only if it isn't already there)
  * if port==0, the alias will match all the ports
  * if proto==0, the alias will match all the protocols
  * returns 1 if a new alias was added, 0 if a matching alias was already on
diff --git a/nonsip_hooks.c b/nonsip_hooks.c
index 4690f8c..16b00ff 100644
--- a/nonsip_hooks.c
+++ b/nonsip_hooks.c
@@ -1,21 +1,14 @@
 /* 
- * $Id$
- * 
  * Copyright (C) 2006 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,20 +17,13 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/*
- * non-sip callbacks, called whenever a message with protocol != SIP/2.0
- * is received (the message must have at least a sip like first line or
- * else they will be dropped before this callbacks are called
- */
-/* 
- * History:
- * --------
- *  2006-11-29  created by andrei
- */
 
 /*!
  * \file
- * \brief SIP-router core :: 
+ * \brief Kamailio core :: non-sip callbacks, called whenever a message with protocol != SIP/2.0
+ * is received (the message must have at least a sip like first line or
+ * else they will be dropped before this callbacks are called
+ *
  * \ingroup core
  * Module: \ref core
  */
diff --git a/nonsip_hooks.h b/nonsip_hooks.h
index 70480e4..42ca35d 100644
--- a/nonsip_hooks.h
+++ b/nonsip_hooks.h
@@ -1,21 +1,14 @@
 /* 
- * $Id$
- * 
  * Copyright (C) 2006 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,15 +17,15 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/*
+/*!
+ * \file
+ * \brief Kamailio core :: Non-sip callbacks
  * non-sip callbacks, called whenever a message with protocol != SIP/2.0
  * is received (the message must have at least a sip like first line or
  * else they will be dropped before this callbacks are called
- */
-/* 
- * History:
- * --------
- *  2006-11-29  created by andrei
+ * \ingroup core
+ * \author andrei
+ * Module: \ref core
  */
 
 
diff --git a/obsolete/acc_db/.cvsignore b/obsolete/acc_db/.cvsignore
new file mode 100644
index 0000000..ffc5f76
--- /dev/null
+++ b/obsolete/acc_db/.cvsignore
@@ -0,0 +1,2 @@
+acc_db.7
+
diff --git a/obsolete/acc_syslog/.cvsignore b/obsolete/acc_syslog/.cvsignore
new file mode 100644
index 0000000..938b803
--- /dev/null
+++ b/obsolete/acc_syslog/.cvsignore
@@ -0,0 +1,2 @@
+acc_syslog.7
+
diff --git a/obsolete/uac/doc/replace_from.patch b/obsolete/uac/doc/replace_from.patch
new file mode 100644
index 0000000..3ea81eb
--- /dev/null
+++ b/obsolete/uac/doc/replace_from.patch
@@ -0,0 +1,150 @@
+Index: modules/uac/from.c
+===================================================================
+diff -u -r1.3 modules/uac/from.c
+--- modules/uac/from.c      26 Feb 2005 18:04:20 -0000      1.3
++++ modules/uac/from.c      24 Mar 2005 16:29:27 -0000
+@@ -39,7 +39,6 @@
+ #include "../tm/tm_load.h"
+ 
+ #include "from.h"
+-#define  FL_FROM_ALTERED  (1<<31)
+ 
+ extern str from_param;
+ extern int from_restore_mode;
+Index: parser/msg_parser.h
+===================================================================
+RCS file: /cvsroot/ser/sip_router/parser/msg_parser.h,v
+retrieving revision 1.56
+diff -u -r1.56 msg_parser.h
+--- parser/msg_parser.h	28 Feb 2005 15:28:24 -0000	1.56
++++ parser/msg_parser.h	24 Mar 2005 22:13:04 -0000
+@@ -73,8 +73,8 @@
+ #define FL_FORCE_ACTIVE 2  /* force active SDP */
+ #define FL_SDP_IP_AFS 4    /* SDP IP rewritten */
+ #define FL_SDP_PORT_AFS 8  /* SDP port rewritten */
+-#define FL_SHM_CLONE   16  /* msg cloned in SHM as a single chunk */
+-
++#define FL_SHM_CLONE    16 /* msg cloned in SHM as a single chunk */
++#define FL_FROM_ALTERED 32 /* from is altered */
+ 
+ #define IFISMETHOD(methodname,firstchar)                                  \
+ if (  (*tmp==(firstchar) || *tmp==((firstchar) | 32)) &&                  \
+Index: modules/tm/t_msgbuilder.c
+===================================================================
+RCS file: /cvsroot/ser/sip_router/modules/tm/t_msgbuilder.c,v
+retrieving revision 1.41
+diff -u -r1.41 t_msgbuilder.c
+--- modules/tm/t_msgbuilder.c	23 Feb 2005 17:16:06 -0000	1.41
++++ modules/tm/t_msgbuilder.c	24 Mar 2005 22:13:04 -0000
+@@ -75,6 +75,72 @@
+ 		(_p)+=(_str).len;  \
+  	} while(0);
+ 
++#define LC(_cp) ((*(_cp))|0x20)
++static int extract_from( char *buf, int len, str *from)
++{
++	char *end, *p;
++	char *b;
++	int state;
++
++	p = buf;
++	end = buf+len;
++	state = 1;
++	b = 0;
++
++	while(p<end) {
++		switch (*p) {
++			case '\n':
++			case '\r':
++				switch (state) {
++					case 4: state=5;break;
++					case 5: case 6: state=6;break;
++					default : state=2;break;
++				}
++				break;
++			case ' ':
++			case '\t':
++				switch (state) {
++					case 4: case 6: state=5; break;
++					case 2: state=1; break;/*folded line*/
++				}
++				break;
++			case ':':
++				switch (state) {
++					case 4: state=5;break;
++					case 6: goto found;
++					case 2: state=1;break;
++				}
++				break;
++			case 'f':
++			case 'F':
++				if (state==5) break;
++				if (state==6) goto found;
++				if (state!=2) {state = 1;break;}
++				/* hdr starting with 'f' */
++				b = p;
++				if (p+3<end && LC(p+1)=='r' && LC(p+2)=='o' && LC(p+3)=='m')
++					p+=3;
++				state = 4; /* "f" or "from" found */
++				break;
++			default:
++				switch (state) {
++					case 2:case 4: state=1; break;
++					case 6: ;goto found;
++				}
++		}
++		p++;
++	}
++
++	LOG(L_CRIT,"BUG:tm:extract_from: no from found in outgoing buffer\n");
++	return -1;
++found:
++	from->s = b;
++	from->len = p-b;
++	DBG("-----from= <%.*s>\n",from->len,from->s);
++	return 0;
++}
++
++
+ /* Build a local request based on a previous request; main
+    customers of this function are local ACK and local CANCEL
+  */
+@@ -88,6 +154,7 @@
+ 	int branch_len;
+ 	str branch_str;
+ 	struct hostport hp;
++	str from;
+ 
+ #ifdef _OBSO
+ 	if ( Trans->uac[branch].last_received<100)
+@@ -98,6 +165,12 @@
+ 	}
+ #endif
+ 
++	if (!Trans->uas.request || !(Trans->uas.request->msg_flags&FL_FROM_ALTERED)
++	|| extract_from( Trans->uac[branch].request.buffer,
++	Trans->uac[branch].request.buffer_len, &from)!=0) {
++		from = Trans->from;
++	}
++
+ 	/* method, separators, version: "CANCEL sip:p2 at iptel.org SIP/2.0" */
+ 	*len=SIP_VERSION_LEN + method_len + 2 /* spaces */ + CRLF_LEN;
+ 	*len+=Trans->uac[branch].uri.len;
+@@ -119,7 +192,7 @@
+ 	}
+ 	*len+= via_len;
+ 	/*headers*/
+-	*len+=Trans->from.len+Trans->callid.len+to->len+
++	*len+=from.len+Trans->callid.len+to->len+
+ 		+Trans->cseq_n.len+1+method_len+CRLF_LEN; 
+ 
+ 
+@@ -154,7 +227,7 @@
+ 	append_mem_block(p,via,via_len);
+ 
+ 	/*other headers*/
+-	append_str( p, Trans->from );
++	append_str( p, from );
+ 	append_str( p, Trans->callid );
+ 	append_str( p, *to );
+ 
diff --git a/onsend.h b/onsend.h
index a8a4e6e..2ed68be 100644
--- a/onsend.h
+++ b/onsend.h
@@ -1,21 +1,14 @@
 /*
- *  $Id$
- *
  * Copyright (C) 2005 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,14 +17,14 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/*
- * History:
- * -------
- *  2005-12-11 created by andrei
- *  2009-06-01 Pre- and post-script callbacks of onsend route are executed (Miklos)
+/*!
+ * \file
+ * \brief Kamailio core :: IP address handling
+ * \author andrei
+ * \ingroup core
+ * Module: \ref core
  */
 
-
 #ifndef onsend_h
 #define onsend_h
 
diff --git a/parser/case_acce.h b/parser/case_acce.h
index f78deae..a4b63b5 100644
--- a/parser/case_acce.h
+++ b/parser/case_acce.h
@@ -3,14 +3,14 @@
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/case_allo.h b/parser/case_allo.h
index 4943b6a..ed745dc 100644
--- a/parser/case_allo.h
+++ b/parser/case_allo.h
@@ -3,14 +3,14 @@
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/case_auth.h b/parser/case_auth.h
index ac3cd62..62faefb 100644
--- a/parser/case_auth.h
+++ b/parser/case_auth.h
@@ -3,14 +3,14 @@
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/case_call.h b/parser/case_call.h
index d02766b..fee2257 100644
--- a/parser/case_call.h
+++ b/parser/case_call.h
@@ -3,14 +3,14 @@
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -19,10 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * ----------
- * 2003-02-28 scratchpad compatibility abandoned (jiri)
- * 2003-01-27 next baby-step to removing ZT - PRESERVE_ZT (jiri)
  */
 
 /*! \file 
diff --git a/parser/case_cont.h b/parser/case_cont.h
index 0adb4ab..9aa2665 100644
--- a/parser/case_cont.h
+++ b/parser/case_cont.h
@@ -4,14 +4,14 @@
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -20,10 +20,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * ----------
- * 2003-02-28 scratchpad compatibility abandoned (jiri)
- * 2003-01-27 next baby-step to removing ZT - PRESERVE_ZT (jiri)
  */
 
 /*! \file 
diff --git a/parser/case_cseq.h b/parser/case_cseq.h
index 37218d1..2da9343 100644
--- a/parser/case_cseq.h
+++ b/parser/case_cseq.h
@@ -3,14 +3,14 @@
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/case_date.h b/parser/case_date.h
index 9334b48..4d17c65 100644
--- a/parser/case_date.h
+++ b/parser/case_date.h
@@ -3,14 +3,14 @@
  *
  * Copyright (c) 2007 iptelorg GmbH
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/case_dive.h b/parser/case_dive.h
index 7c8d598..30ce04f 100644
--- a/parser/case_dive.h
+++ b/parser/case_dive.h
@@ -3,19 +3,14 @@
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/case_even.h b/parser/case_even.h
index 20ec8aa..e418aa2 100644
--- a/parser/case_even.h
+++ b/parser/case_even.h
@@ -3,19 +3,14 @@
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/case_expi.h b/parser/case_expi.h
index 141b38c..9dc7b21 100644
--- a/parser/case_expi.h
+++ b/parser/case_expi.h
@@ -3,19 +3,14 @@
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,10 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * ---------
- * 2003-02-28 scratchpad compatibility abandoned (jiri)
- * 2003-01-27 next baby-step to removing ZT - PRESERVE_ZT (jiri)
  */
 
 /*! \file 
diff --git a/parser/case_from.h b/parser/case_from.h
index 451e2b2..6925a8c 100644
--- a/parser/case_from.h
+++ b/parser/case_from.h
@@ -3,19 +3,14 @@
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/case_iden.h b/parser/case_iden.h
index 0816a40..46e034d 100644
--- a/parser/case_iden.h
+++ b/parser/case_iden.h
@@ -3,19 +3,14 @@
  *
  * Copyright (c) 2007 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,8 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
  */
 
 /*! \file 
diff --git a/parser/case_max.h b/parser/case_max.h
index 215a24e..055ed19 100644
--- a/parser/case_max.h
+++ b/parser/case_max.h
@@ -3,19 +3,14 @@
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/case_min.h b/parser/case_min.h
index b1a0e43..56231c3 100644
--- a/parser/case_min.h
+++ b/parser/case_min.h
@@ -3,19 +3,14 @@
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/case_orga.h b/parser/case_orga.h
index e3c1416..80fc63c 100644
--- a/parser/case_orga.h
+++ b/parser/case_orga.h
@@ -3,19 +3,14 @@
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/case_p_as.h b/parser/case_p_as.h
index 9f6e40f..331b1ab 100644
--- a/parser/case_p_as.h
+++ b/parser/case_p_as.h
@@ -13,14 +13,6 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/*
- * parser/case_p_as.h
- */
-/*
- * History:
- * --------
- *  2010-02-19  initial version (andrei)
-*/
 
 /** Parser :: Reason Header Name Parsing Macros.
  * @file 
diff --git a/parser/case_p_pr.h b/parser/case_p_pr.h
index d0371fb..d8bbaba 100644
--- a/parser/case_p_pr.h
+++ b/parser/case_p_pr.h
@@ -13,14 +13,6 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/*
- * parser/case_p_pr.h
- */
-/*
- * History:
- * --------
- *  2010-02-19  initial version (andrei)
-*/
 
 /** Parser :: Reason Header Name Parsing Macros.
  * @file 
diff --git a/parser/case_path.h b/parser/case_path.h
index 96350a5..1112157 100644
--- a/parser/case_path.h
+++ b/parser/case_path.h
@@ -3,19 +3,14 @@
  *
  * Copyright (C) 2009 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/case_prio.h b/parser/case_prio.h
index 28024f7..6e410b0 100644
--- a/parser/case_prio.h
+++ b/parser/case_prio.h
@@ -3,19 +3,14 @@
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/case_priv.h b/parser/case_priv.h
index f3f8d98..152dec6 100644
--- a/parser/case_priv.h
+++ b/parser/case_priv.h
@@ -3,14 +3,14 @@
  *
  * Copyright (C) 2001-2003 FhG FOKUS
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/case_prox.h b/parser/case_prox.h
index 7afba66..b8c69cd 100644
--- a/parser/case_prox.h
+++ b/parser/case_prox.h
@@ -3,19 +3,14 @@
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,10 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2003-02-28 scratchpad compatibility abandoned (jiri)
- * 2003-01-27 next baby-step to removing ZT - PRESERVE_ZT (jiri)
  */
 
 /*! \file 
diff --git a/parser/case_reas.h b/parser/case_reas.h
index 8db456b..e6b8d97 100644
--- a/parser/case_reas.h
+++ b/parser/case_reas.h
@@ -13,14 +13,6 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/*
- * parser/case_reas.h
- */
-/*
- * History:
- * --------
- *  2010-02-18  initial version (andrei)
-*/
 
 /** Parser :: Reason Header Name Parsing Macros.
  * @file 
diff --git a/parser/case_reco.h b/parser/case_reco.h
index 0a665e4..7f8f26e 100644
--- a/parser/case_reco.h
+++ b/parser/case_reco.h
@@ -3,19 +3,14 @@
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/case_refe.h b/parser/case_refe.h
index 5edc33b..5196092 100644
--- a/parser/case_refe.h
+++ b/parser/case_refe.h
@@ -3,19 +3,14 @@
  *
  * Copyright (C) 2005 Juha Heinanen
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/case_reje.h b/parser/case_reje.h
index 3a5d137..239b25e 100644
--- a/parser/case_reje.h
+++ b/parser/case_reje.h
@@ -3,19 +3,14 @@
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/case_remo.h b/parser/case_remo.h
index 5e07aee..dabed4f 100644
--- a/parser/case_remo.h
+++ b/parser/case_remo.h
@@ -3,19 +3,14 @@
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/case_requ.h b/parser/case_requ.h
index 75a4cc1..a0887b5 100644
--- a/parser/case_requ.h
+++ b/parser/case_requ.h
@@ -3,19 +3,14 @@
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,10 +19,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * -------------
- * 2003-02-28 scratchpad compatibility abandoned (jiri)
- * 2003-01-27 next baby-step to removing ZT - PRESERVE_ZT (jiri)
  */
 
 /*! \file 
diff --git a/parser/case_retr.h b/parser/case_retr.h
index 7548858..34ac3f5 100644
--- a/parser/case_retr.h
+++ b/parser/case_retr.h
@@ -3,19 +3,14 @@
  *
  * Copyright (C) 2007 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,9 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * ---------
- *  2007-07-27  created by andrei
  */
 
 /*! \file 
diff --git a/parser/case_rout.h b/parser/case_rout.h
index d805495..d78a29f 100644
--- a/parser/case_rout.h
+++ b/parser/case_rout.h
@@ -3,19 +3,14 @@
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/case_serv.h b/parser/case_serv.h
index 63bddba..f47bee0 100644
--- a/parser/case_serv.h
+++ b/parser/case_serv.h
@@ -3,19 +3,14 @@
  *
  * Copyright (C) 2001-2003 Fhg Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/case_sess.h b/parser/case_sess.h
index 2942e0a..6bbefa4 100644
--- a/parser/case_sess.h
+++ b/parser/case_sess.h
@@ -3,19 +3,14 @@
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/case_sip.h b/parser/case_sip.h
index 3ac6183..f48b396 100644
--- a/parser/case_sip.h
+++ b/parser/case_sip.h
@@ -1,14 +1,14 @@
 /*
  * Copyright (C) 2004 Jamey Hicks, jamey dot hicks at hp dot com
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/case_subj.h b/parser/case_subj.h
index f3e00c2..6989919 100644
--- a/parser/case_subj.h
+++ b/parser/case_subj.h
@@ -3,19 +3,14 @@
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/case_subs.h b/parser/case_subs.h
index e59f640..f3367a3 100644
--- a/parser/case_subs.h
+++ b/parser/case_subs.h
@@ -3,19 +3,14 @@
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/case_supp.h b/parser/case_supp.h
index bb32743..91364e0 100644
--- a/parser/case_supp.h
+++ b/parser/case_supp.h
@@ -3,19 +3,14 @@
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/case_to.h b/parser/case_to.h
index 4520d31..9de8c4a 100644
--- a/parser/case_to.h
+++ b/parser/case_to.h
@@ -3,19 +3,14 @@
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,10 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * ---------
- * 2003-02-28 scratchpad compatibility abandoned (jiri)
- * 2003-01-27 next baby-step to removing ZT - PRESERVE_ZT (jiri)
  */
 
 /*! \file 
diff --git a/parser/case_unsu.h b/parser/case_unsu.h
index e1929e9..a7df99a 100644
--- a/parser/case_unsu.h
+++ b/parser/case_unsu.h
@@ -3,19 +3,14 @@
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,10 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2003-02-28 scratchpad compatibility abandoned (jiri)
- * 2003-01-27 next baby-step to removing ZT - PRESERVE_ZT (jiri)
  */
 
 /*! \file 
diff --git a/parser/case_user.h b/parser/case_user.h
index 534614e..03f0922 100644
--- a/parser/case_user.h
+++ b/parser/case_user.h
@@ -3,19 +3,14 @@
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/case_via.h b/parser/case_via.h
index 480f16e..1b9607b 100644
--- a/parser/case_via.h
+++ b/parser/case_via.h
@@ -3,19 +3,14 @@
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,9 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2003-02-28 scratchpad compatibility abandoned (jiri)
  */
 
 /*! \file 
diff --git a/parser/case_www.h b/parser/case_www.h
index 77e5509..af98697 100644
--- a/parser/case_www.h
+++ b/parser/case_www.h
@@ -3,19 +3,14 @@
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/hf.c b/parser/hf.c
index 912dd51..3f2f879 100644
--- a/parser/hf.c
+++ b/parser/hf.c
@@ -1,19 +1,14 @@
 /*
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -22,13 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * -------
- * 2003-03-26 Frees also hdr->parsed for Route & Record-Route (janakj)
- * 2003-04-26 ZSW (jiri)
- * 2003-08-05 free the parsed part of Accept header (bogdan)
- * 2007-01-26 HDR_DATE_T, HDR_IDENTITY_T, HDR_IDENTITY_INFO_T added (gergo)
- * 2007-07-27 added HDR_RETRY_AFTER_T (andrei)
  */
 
 /** Parser :: parse header files
diff --git a/parser/hf.h b/parser/hf.h
index fe3dbc7..03b1ec7 100644
--- a/parser/hf.h
+++ b/parser/hf.h
@@ -1,19 +1,14 @@
 /*
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -22,15 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * ---------
- * 2003-02-28 scratchpad compatibility abandoned (jiri)
- * 2003-01-27 next baby-step to removing ZT - PRESERVE_ZT (jiri)
- * 2003-05-01 HDR_ACCEPT added (janakj)
- * 2005-02-14 hdr_flags_t && hdr_flags_f defined, split HDR_xxx into
- *             HDR_xxx_F & HDR_xxx_T [WARNING: don't mix them!] (andrei)
- * 2007-01-26 HDR_DATE_T, HDR_IDENTITY_T, HDR_IDENTITY_INFO_T added (gergo)
- * 2007-07-27 HDR_RETRY_AFTER_[TF] added (andrei)
  */
 
 /** Parser :: parse headers.
diff --git a/parser/keys.h b/parser/keys.h
index da72450..6a93d5d 100644
--- a/parser/keys.h
+++ b/parser/keys.h
@@ -3,14 +3,14 @@
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -19,12 +19,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2003-05-01 _acce_ macro added (janakj)
- * 2003-05-01 Macros for Accept-Disposition added (janakj)
- * 2003-11-02 Macros for Diversion added (jh)
- * 2007-01-26 Macros for Identity, Identity-info, Date added (gergo)
  */
 
 /** Parser :: Fast 32-bit Header Field Name Parser -- keys .
diff --git a/parser/msg_parser.c b/parser/msg_parser.c
index 3af3c43..b907772 100644
--- a/parser/msg_parser.c
+++ b/parser/msg_parser.c
@@ -3,19 +3,14 @@
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,18 +19,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * ---------
- *  2003-02-28  scratchpad compatibility abandoned (jiri)
- *  2003-01-29  scrathcpad removed (jiri)
- *  2003-01-27  next baby-step to removing ZT - PRESERVE_ZT (jiri)
- *  2003-03-31  removed msg->repl_add_rm (andrei)
- *  2003-04-26 ZSW (jiri)
- *  2003-05-01  parser extended to support Accept header field (janakj)
- *  2005-02-23  parse_headers uses hdr_flags_t now (andrei)
- *  2005-03-02  free_via_list(vb) on via parse error (andrei)
- *  2007-01-26  parser extended to support Identity, Identity-info and Date
- *		header fields (gergo)
  */
 
 /** Parser :: SIP Message header proxy parser.
@@ -1050,3 +1033,86 @@ int msg_set_time(sip_msg_t* const msg)
 		return 0;
 	return gettimeofday(&msg->tval, NULL);
 }
+
+/**
+ * get source ip, port and protocol in SIP URI format
+ * - tmode - 0: short format (transport=udp is not added, being default)
+ */
+int get_src_uri(sip_msg_t *m, int tmode, str *uri)
+{
+	static char buf[MAX_URI_SIZE];
+	char* p;
+	str ip, port;
+	int len;
+	str proto;
+
+	if (!uri || !m) {
+		LM_ERR("invalid parameter value\n");
+		return -1;
+	}
+
+	if(tmode==0) {
+		switch(m->rcv.proto) {
+			case PROTO_NONE:
+			case PROTO_UDP:
+				proto.s = 0; /* Do not add transport parameter, UDP is default */
+				proto.len = 0;
+			break;
+			default:
+				if(get_valid_proto_string(m->rcv.proto, 1, 0, &proto)<0) {
+					LM_ERR("unknown transport protocol\n");
+					return -1;
+				}
+		}
+	} else {
+		if(get_valid_proto_string(m->rcv.proto, 1, 0, &proto)<0) {
+			LM_ERR("unknown transport protocol\n");
+			return -1;
+		}
+	}
+
+	ip.s = ip_addr2a(&m->rcv.src_ip);
+	ip.len = strlen(ip.s);
+
+	port.s = int2str(m->rcv.src_port, &port.len);
+
+	len = 4 + ip.len + 2*(m->rcv.src_ip.af==AF_INET6)+ 1 + port.len;
+	if (proto.s) {
+		len += TRANSPORT_PARAM_LEN;
+		len += proto.len;
+	}
+
+	if (len > MAX_URI_SIZE) {
+		LM_ERR("buffer too small\n");
+		return -1;
+	}
+
+	p = buf;
+	memcpy(p, "sip:", 4);
+	p += 4;
+
+	if (m->rcv.src_ip.af==AF_INET6)
+		*p++ = '[';
+	memcpy(p, ip.s, ip.len);
+	p += ip.len;
+	if (m->rcv.src_ip.af==AF_INET6)
+		*p++ = ']';
+
+	*p++ = ':';
+
+	memcpy(p, port.s, port.len);
+	p += port.len;
+
+	if (proto.s) {
+		memcpy(p, TRANSPORT_PARAM, TRANSPORT_PARAM_LEN);
+		p += TRANSPORT_PARAM_LEN;
+
+		memcpy(p, proto.s, proto.len);
+		p += proto.len;
+	}
+
+	uri->s = buf;
+	uri->len = len;
+
+	return 0;
+}
diff --git a/parser/msg_parser.h b/parser/msg_parser.h
index 27177b5..c4e426a 100644
--- a/parser/msg_parser.h
+++ b/parser/msg_parser.h
@@ -1,19 +1,14 @@
 /*
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -22,25 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History
- * -------
- *  2003-01-28  removed scratchpad (jiri)
- *  2003-02-28  scratchpad compatibility abandoned (jiri)
- *  2003-03-06  enum_request_method changed to begin with 1;
- *               0 reserved for invalid values; (jiri)
- *  2003-03-31  removed sip_msg->repl_add_rm (andrei)
- *  2003-04-01  2 macros added: GET_NEXT_HOP and GET_RURI (janakj)
- *  2003-04-04  structure for parsed inbound uri added (jiri)
- *  2003-04-11  updated the  sip_uri structure (lots of fields added) (andrei)
- *  2003-04-12  added msg_flags to sip_msg (andrei)
- *  2003-11-02  added diversion header field to sip_msg (jh)
- *  2004-11-08  added force_send_socket (andrei)
- *  2005-02-25  uri types added (sip, sips & tel)  (andrei)
- *  2006-04-20  uri comp member (only if USE_COMP is defined) (andrei)
- *  2006-11-10  check_transaction_quadruple inlined (andrei)
- *  2007-01-26  added date, identity, identity_info header fields
- *		to sip_msg (gergo)
- *  2007-03-14  added SIP_MSG_START(msg) macro
  */
 
 /*! \file 
@@ -545,4 +521,9 @@ int msg_set_time(sip_msg_t* const msg);
  */
 void msg_ldata_reset(sip_msg_t*);
 
+/**
+ * get source ip, port and protocol in SIP URI format
+ */
+int get_src_uri(sip_msg_t *m, int tmode, str *uri);
+
 #endif
diff --git a/parser/parse_addr_spec.c b/parser/parse_addr_spec.c
index c943bf9..15d15cc 100644
--- a/parser/parse_addr_spec.c
+++ b/parser/parse_addr_spec.c
@@ -1,14 +1,14 @@
 /*
  * Copyright (C) 2001-2003 Fhg Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -17,10 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * ---------
- * 2003-04-26 ZSW (jiri)
- * 2010-03-03  fix multi-token no-quotes display name (andrei)
  */
 
 /** Parser :: Parse To: header.
diff --git a/parser/parse_allow.c b/parser/parse_allow.c
index 953a42d..cbe5a1c 100644
--- a/parser/parse_allow.c
+++ b/parser/parse_allow.c
@@ -1,14 +1,14 @@
 /*
  * Copyright (c) 2004 Juha Heinanen
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/parse_allow.h b/parser/parse_allow.h
index f1604e9..26d6035 100644
--- a/parser/parse_allow.h
+++ b/parser/parse_allow.h
@@ -1,14 +1,14 @@
 /*
  * Copyright (c) 2004 Juha Heinanen
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/parse_body.c b/parser/parse_body.c
index 985f7bf..9333114 100644
--- a/parser/parse_body.c
+++ b/parser/parse_body.c
@@ -1,19 +1,14 @@
 /*
  * Copyright (C) 2008 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -22,9 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2008-05-22  Initial version, get_body_part() is introduced (Miklos)
  */
 
 /*! \file
diff --git a/parser/parse_body.h b/parser/parse_body.h
index 984a468..1b5afde 100644
--- a/parser/parse_body.h
+++ b/parser/parse_body.h
@@ -1,19 +1,14 @@
 /*
  * Copyright (C) 2008 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -23,6 +18,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
  */
+
 /*! \file
  * \brief Parser :: Body handling
  *
diff --git a/parser/parse_content.c b/parser/parse_content.c
index 0341369..3c10a5e 100644
--- a/parser/parse_content.c
+++ b/parser/parse_content.c
@@ -1,14 +1,14 @@
 /*
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -17,14 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * 2003-08-04 parse_content_type_hdr separates type from subtype inside
- * the mime type (bogdan)
- * 2003-08-04 CPL subtype added (bogdan)
- * 2003-08-05 parse_accept_hdr function added (bogdan)
- * 2008-05-23 reset the type/subtype to unknown, if the end of
- *		tree has reached, but the type/subtype has still
- *		some remaining characters (Miklos)
  */
 
 /*! \file
diff --git a/parser/parse_content.h b/parser/parse_content.h
index ddbcd0e..16fb79a 100644
--- a/parser/parse_content.h
+++ b/parser/parse_content.h
@@ -1,14 +1,14 @@
 /*
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/parse_cseq.c b/parser/parse_cseq.c
index 2eac66a..01d4b57 100644
--- a/parser/parse_cseq.c
+++ b/parser/parse_cseq.c
@@ -1,14 +1,14 @@
 /* 
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -17,10 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  * 
- * History:
- * --------
- * 2003-02-28 scratchpad compatibility abandoned (jiri)
- * 2003-01-22 zero-termination in CSeq eliminated (jiri)
  */
 
 /*! \file
diff --git a/parser/parse_cseq.h b/parser/parse_cseq.h
index fb6ca5e..766e5c6 100644
--- a/parser/parse_cseq.h
+++ b/parser/parse_cseq.h
@@ -1,19 +1,14 @@
 /*
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/parse_date.c b/parser/parse_date.c
index 08f6708..f4da798 100644
--- a/parser/parse_date.c
+++ b/parser/parse_date.c
@@ -1,14 +1,14 @@
 /*
  * Copyright (c) 2007 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/parse_date.h b/parser/parse_date.h
index 2151285..cc852db 100644
--- a/parser/parse_date.h
+++ b/parser/parse_date.h
@@ -1,14 +1,14 @@
 /*
  * Copyright (c) 2007 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/parse_def.h b/parser/parse_def.h
index 9255290..d250d28 100644
--- a/parser/parse_def.h
+++ b/parser/parse_def.h
@@ -1,14 +1,14 @@
 /*
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/parse_disposition.c b/parser/parse_disposition.c
index 2d5e748..3a39c42 100644
--- a/parser/parse_disposition.c
+++ b/parser/parse_disposition.c
@@ -1,14 +1,14 @@
 /*
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -17,8 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * 2003-09-09 created (bogdan)
  */
 
 /*! \file
diff --git a/parser/parse_disposition.h b/parser/parse_disposition.h
index 3a4c053..8f0f604 100644
--- a/parser/parse_disposition.h
+++ b/parser/parse_disposition.h
@@ -1,14 +1,14 @@
 /*
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -17,8 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * 2003-09-09 created (bogdan)
  */
 
 /*! \file
diff --git a/parser/parse_diversion.c b/parser/parse_diversion.c
index 40f80e2..cc60600 100644
--- a/parser/parse_diversion.c
+++ b/parser/parse_diversion.c
@@ -1,14 +1,14 @@
 /*
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/parse_diversion.h b/parser/parse_diversion.h
index 36e86b4..526006c 100644
--- a/parser/parse_diversion.h
+++ b/parser/parse_diversion.h
@@ -1,14 +1,14 @@
 /*
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/parse_event.c b/parser/parse_event.c
index 8934be5..fbaf670 100644
--- a/parser/parse_event.c
+++ b/parser/parse_event.c
@@ -3,14 +3,14 @@
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -19,9 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2003-04-26 ZSW (jiri)
  */
 
 /*! \file
diff --git a/parser/parse_event.h b/parser/parse_event.h
index a830e5e..b5069ca 100644
--- a/parser/parse_event.h
+++ b/parser/parse_event.h
@@ -1,14 +1,14 @@
 /*
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/parse_expires.c b/parser/parse_expires.c
index 8090efe..1dcef71 100644
--- a/parser/parse_expires.c
+++ b/parser/parse_expires.c
@@ -3,19 +3,14 @@
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,9 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2003-04-26 ZSW (jiri)
  */
 
 /*! \file
diff --git a/parser/parse_expires.h b/parser/parse_expires.h
index 66bdda6..14f4be4 100644
--- a/parser/parse_expires.h
+++ b/parser/parse_expires.h
@@ -3,14 +3,14 @@
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/parse_fline.c b/parser/parse_fline.c
index dbbe4de..ac0b461 100644
--- a/parser/parse_fline.c
+++ b/parser/parse_fline.c
@@ -3,19 +3,14 @@
  * 
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,11 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * ---------
- * 2003-02-28 scratchpad compatibility abandoned (jiri)
- * 2003-01-28: removed 0-terminators from first line (jiri)
- * 2003-04-26 ZSW (jiri)
  */
 
 /*! \file
@@ -45,6 +35,11 @@
 #include "../mem/mem.h"
 #include "../ut.h"
 
+/* flags for first line
+ * - stored on a short field (16 flags) */
+#define FLINE_FLAG_PROTO_SIP	(1<<0)
+#define FLINE_FLAG_PROTO_HTTP	(1<<1)
+
 int http_reply_parse = 0;
 
 /* grammar:
@@ -56,7 +51,7 @@ int http_reply_parse = 0;
 
 /* parses the first line, returns pointer to  next line  & fills fl;
    also  modifies buffer (to avoid extra copy ops) */
-char* parse_first_line(char* buffer, unsigned int len, struct msg_start * fl)
+char* parse_first_line(char* buffer, unsigned int len, struct msg_start* fl)
 {
 	
 	char *tmp;
@@ -77,6 +72,7 @@ char* parse_first_line(char* buffer, unsigned int len, struct msg_start * fl)
 	*/
 	
 
+	memset(fl, 0, sizeof(struct msg_start));
 	offset = 0;
 	end=buffer+len;
 	/* see if it's a reply (status) */
@@ -97,6 +93,7 @@ char* parse_first_line(char* buffer, unsigned int len, struct msg_start * fl)
 		strncasecmp( tmp+1, SIP_VERSION+1, SIP_VERSION_LEN-1)==0 &&
 		(*(tmp+SIP_VERSION_LEN)==' ')) {
 			fl->type=SIP_REPLY;
+			fl->flags|=FLINE_FLAG_PROTO_SIP;
 			fl->u.reply.version.len=SIP_VERSION_LEN;
 			tmp=buffer+SIP_VERSION_LEN;
 	} else if (http_reply_parse != 0 &&
@@ -111,6 +108,7 @@ char* parse_first_line(char* buffer, unsigned int len, struct msg_start * fl)
 			 *       - the message is marked as SIP_REPLY (ugly)
 			 */
 				fl->type=SIP_REPLY;
+				fl->flags|=FLINE_FLAG_PROTO_HTTP;
 				fl->u.reply.version.len=HTTP_VERSION_LEN+1 /*include last digit*/;
 				tmp=buffer+HTTP_VERSION_LEN+1 /* last digit */;
 	} else IFISMETHOD( INVITE, 'I' )
@@ -223,6 +221,22 @@ char* parse_first_line(char* buffer, unsigned int len, struct msg_start * fl)
 	fl->u.request.version.len=tmp-third;
 	fl->len=nl-buffer;
 
+	if (fl->type==SIP_REQUEST) {
+		if(fl->u.request.version.len >= SIP_VERSION_LEN
+				&& (fl->u.request.version.s[0]=='S'
+					|| fl->u.request.version.s[0]=='s')
+				&& !strncasecmp(fl->u.request.version.s+1,
+					SIP_VERSION+1, SIP_VERSION_LEN-1)) {
+			fl->flags|=FLINE_FLAG_PROTO_SIP;
+		} else if(fl->u.request.version.len >= HTTP_VERSION_LEN
+				&& (fl->u.request.version.s[0]=='H'
+					|| fl->u.request.version.s[0]=='h')
+				&& !strncasecmp(fl->u.request.version.s+1,
+					HTTP_VERSION+1, HTTP_VERSION_LEN-1)) {
+			fl->flags|=FLINE_FLAG_PROTO_HTTP;
+		}
+	}
+
 	return nl;
 
 error:
@@ -245,3 +259,12 @@ error1:
 	nl=eat_line(buffer,len);
 	return nl;
 }
+
+char* parse_fline(char* buffer, char* end, struct msg_start* fl)
+{
+	if(end<=buffer) {
+		/* make it throw error via parse_first_line() for consistency */
+		return parse_first_line(buffer, 0, fl);
+	}
+	return parse_first_line(buffer, (unsigned int)(end-buffer), fl);
+}
diff --git a/parser/parse_fline.h b/parser/parse_fline.h
index 7564b9f..04f96b6 100644
--- a/parser/parse_fline.h
+++ b/parser/parse_fline.h
@@ -1,19 +1,19 @@
 /*
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
+ * For a license to use the Kamailio software under conditions
  * other than those described here, or to purchase support for this
  * software, please contact iptel.org by e-mail at the following addresses:
  *    info at iptel.org
  *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -69,7 +69,8 @@
 #define PUBLISH_LEN 7
 
 struct msg_start {
-	int type;					/*!< Type of the Message - Request/Response */
+	short type;					/*!< Type of the message - request/response */
+	short flags;				/*!< First line flags */
 	int len; 					/*!< length including delimiter */
 	union {
 		struct {
diff --git a/parser/parse_from.c b/parser/parse_from.c
index b1b49e8..dcee554 100644
--- a/parser/parse_from.c
+++ b/parser/parse_from.c
@@ -1,19 +1,14 @@
 /*
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/parse_from.h b/parser/parse_from.h
index 602b2d8..5f641ea 100644
--- a/parser/parse_from.h
+++ b/parser/parse_from.h
@@ -1,14 +1,14 @@
 /*
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/parse_hname2.c b/parser/parse_hname2.c
index 718f53b..c90d3e5 100644
--- a/parser/parse_hname2.c
+++ b/parser/parse_hname2.c
@@ -3,19 +3,14 @@
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,13 +19,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2003-02-28 scratchpad compatibility abandoned (jiri)
- * 2003-01-27 next baby-step to removing ZT - PRESERVE_ZT (jiri)
- * 2003-05-01 added support for Accept HF (janakj)
- * 2007-01-26 Date, Identity, Identity_info HF support added (gergo)
- * 2007-07-27 added support for Retry-After (andrei)
  */
 
 /** Parser :: Fast 32-bit Header Field Name Parser.
diff --git a/parser/parse_hname2.h b/parser/parse_hname2.h
index 2b97c12..6f5b76b 100644
--- a/parser/parse_hname2.h
+++ b/parser/parse_hname2.h
@@ -3,14 +3,14 @@
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/parse_hostport.c b/parser/parse_hostport.c
index 72507af..4fbd1a4 100644
--- a/parser/parse_hostport.c
+++ b/parser/parse_hostport.c
@@ -1,14 +1,14 @@
 /*
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/parse_hostport.h b/parser/parse_hostport.h
index c8e32b2..10f5f0c 100644
--- a/parser/parse_hostport.h
+++ b/parser/parse_hostport.h
@@ -1,19 +1,14 @@
 /*
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/parse_identity.c b/parser/parse_identity.c
index d0ca87b..f92dc46 100644
--- a/parser/parse_identity.c
+++ b/parser/parse_identity.c
@@ -1,19 +1,14 @@
 /*
  * Copyright (c) 2007 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/parse_identity.h b/parser/parse_identity.h
index 21faf68..134ce45 100644
--- a/parser/parse_identity.h
+++ b/parser/parse_identity.h
@@ -1,14 +1,14 @@
 /*
  * Copyright (c) 2007 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/parse_identityinfo.c b/parser/parse_identityinfo.c
index 3b718a8..f8ec22d 100644
--- a/parser/parse_identityinfo.c
+++ b/parser/parse_identityinfo.c
@@ -1,14 +1,14 @@
 /*
  * Copyright (c) 2007 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/parse_identityinfo.h b/parser/parse_identityinfo.h
index b05e02f..e4f3190 100644
--- a/parser/parse_identityinfo.h
+++ b/parser/parse_identityinfo.h
@@ -1,14 +1,14 @@
 /*
  * Copyright (c) 2007 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/parse_methods.c b/parser/parse_methods.c
index 718d088..8f23e6b 100644
--- a/parser/parse_methods.c
+++ b/parser/parse_methods.c
@@ -1,14 +1,14 @@
 /*
  * Copyright (c) 2004 Juha Heinanen
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/parse_methods.h b/parser/parse_methods.h
index 6c5c96b..75207d3 100644
--- a/parser/parse_methods.h
+++ b/parser/parse_methods.h
@@ -1,19 +1,14 @@
 /*
  * Copyright (c) 2004 Juha Heinanen
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/parse_nameaddr.c b/parser/parse_nameaddr.c
index c422cbe..d44c927 100644
--- a/parser/parse_nameaddr.c
+++ b/parser/parse_nameaddr.c
@@ -1,14 +1,14 @@
 /* 
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -17,10 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History
- * --------
- * 2003-03-24 Created by janakj
- * 2003-04-26 ZSW (jiri)
  */
 
 /*! \file
diff --git a/parser/parse_nameaddr.h b/parser/parse_nameaddr.h
index 719e20c..0c566e9 100644
--- a/parser/parse_nameaddr.h
+++ b/parser/parse_nameaddr.h
@@ -1,14 +1,14 @@
 /* 
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -17,9 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History
- * --------
- * 2003-03-24 Created by janakj
  */
 
 /*! \file
diff --git a/parser/parse_option_tags.c b/parser/parse_option_tags.c
index 2f410fd..6fedcef 100644
--- a/parser/parse_option_tags.c
+++ b/parser/parse_option_tags.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2006 Andreas Granig <agranig at linguin.org>
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/parser/parse_option_tags.h b/parser/parse_option_tags.h
index 1d53298..5a19ca6 100644
--- a/parser/parse_option_tags.h
+++ b/parser/parse_option_tags.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2006 Andreas Granig <agranig at linguin.org>
  * 
  * This file is part of Kamailio, a free SIP server.
diff --git a/parser/parse_param.c b/parser/parse_param.c
index 04d20c6..79e65e9 100644
--- a/parser/parse_param.c
+++ b/parser/parse_param.c
@@ -3,14 +3,14 @@
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -19,11 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * -------
- * 2003-03-24 Created by janakj
- * 2003-04-07 shm duplication added (janakj)
- * 2003-04-07 URI class added (janakj)
  */
 
 /*! \file
diff --git a/parser/parse_param.h b/parser/parse_param.h
index adbee0d..98a1bd1 100644
--- a/parser/parse_param.h
+++ b/parser/parse_param.h
@@ -3,19 +3,14 @@
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,11 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * -------
- * 2003-03-24 Created by janakj
- * 2003-04-07 shm duplication support (janakj)
- * 2003-04-07 URI class added (janakj)
  */
 
 /*! \file
diff --git a/parser/parse_ppi_pai.c b/parser/parse_ppi_pai.c
index a82b50e..c337169 100644
--- a/parser/parse_ppi_pai.c
+++ b/parser/parse_ppi_pai.c
@@ -17,9 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * ---------
- * 2013-03-06 Created (hpw)
  */
 
 /** Parser :: Parse P-Asserted-Identity: header.
diff --git a/parser/parse_refer_to.c b/parser/parse_refer_to.c
index 30b5fb0..1be4e14 100644
--- a/parser/parse_refer_to.c
+++ b/parser/parse_refer_to.c
@@ -1,14 +1,14 @@
 /*
  * Copyright (C) 2005 Juha Heinanen
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/parse_refer_to.h b/parser/parse_refer_to.h
index e78c8b8..ad1cd14 100644
--- a/parser/parse_refer_to.h
+++ b/parser/parse_refer_to.h
@@ -1,14 +1,14 @@
 /*
  * Copyright (C) 2005 Juha Heinanen
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/parse_require.c b/parser/parse_require.c
index ab82eb2..a520318 100644
--- a/parser/parse_require.c
+++ b/parser/parse_require.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2006 Andreas Granig <agranig at linguin.org>
  * 
  * This file is part of Kamailio, a free SIP server.
diff --git a/parser/parse_require.h b/parser/parse_require.h
index 3926015..d9bc507 100644
--- a/parser/parse_require.h
+++ b/parser/parse_require.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2006 Andreas Granig <agranig at linguin.org>
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/parser/parse_retry_after.c b/parser/parse_retry_after.c
index 5c30830..a467cf2 100644
--- a/parser/parse_retry_after.c
+++ b/parser/parse_retry_after.c
@@ -1,14 +1,14 @@
 /* 
  * Copyright (C) 2007 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -17,9 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  * 
- * History:
- * --------
- *  2007-07-27  created by andrei
  */
 
 /*! \file
diff --git a/parser/parse_retry_after.h b/parser/parse_retry_after.h
index e030302..58d764e 100644
--- a/parser/parse_retry_after.h
+++ b/parser/parse_retry_after.h
@@ -1,14 +1,14 @@
 /*
  * Copyright (C) 2007 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/parse_rpid.c b/parser/parse_rpid.c
index 7578ebf..6dbb8ae 100644
--- a/parser/parse_rpid.c
+++ b/parser/parse_rpid.c
@@ -1,14 +1,14 @@
 /*
  * Copyright (C) 2001-2003 Juha Heinanen
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/parse_rpid.h b/parser/parse_rpid.h
index bbadc0e..16d25ee 100644
--- a/parser/parse_rpid.h
+++ b/parser/parse_rpid.h
@@ -1,19 +1,14 @@
 /*
  * Copyright (C) 2001-2003 Juha Heinanen
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/parse_rr.c b/parser/parse_rr.c
index a6b59dd..bcc518f 100644
--- a/parser/parse_rr.c
+++ b/parser/parse_rr.c
@@ -3,19 +3,14 @@
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -31,12 +26,6 @@
  * \ingroup parser
  */
 
-/**
- * History:
- * --------
- * 2003-10-07  parse_rr() split and added parse_rr_body()
- * 2003-10-21  duplicate_rr() duplicate the whole linked list of RR
- */
 #include <string.h>
 #include "parse_rr.h"
 #include "../mem/mem.h"
diff --git a/parser/parse_rr.h b/parser/parse_rr.h
index e85ed7b..f7379a6 100644
--- a/parser/parse_rr.h
+++ b/parser/parse_rr.h
@@ -3,19 +3,14 @@
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/parse_sipifmatch.c b/parser/parse_sipifmatch.c
index b375b54..8009e1b 100644
--- a/parser/parse_sipifmatch.c
+++ b/parser/parse_sipifmatch.c
@@ -1,14 +1,14 @@
 /*
  * Copyright (C) 2004 Jamey Hicks, jamey dot hicks at hp dot com
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/parse_sipifmatch.h b/parser/parse_sipifmatch.h
index 9376e38..dff6416 100644
--- a/parser/parse_sipifmatch.h
+++ b/parser/parse_sipifmatch.h
@@ -1,14 +1,14 @@
 /*
  * Copyright (C) 2004 Jamey Hicks, jamey dot hicks at hp dot com
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/parse_subscription_state.c b/parser/parse_subscription_state.c
index 65653dc..bc7e42e 100644
--- a/parser/parse_subscription_state.c
+++ b/parser/parse_subscription_state.c
@@ -1,14 +1,14 @@
 /*
  * Copyright (C) 2006 Vaclav Kubart, vaclav dot kubart at iptel dot org
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/parse_subscription_state.h b/parser/parse_subscription_state.h
index b7646fd..742d349 100644
--- a/parser/parse_subscription_state.h
+++ b/parser/parse_subscription_state.h
@@ -1,14 +1,14 @@
 /*
  * Copyright (C) 2006 Vaclav Kubart, vaclav dot kubart at iptel dot org
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/parse_supported.c b/parser/parse_supported.c
index d247eb8..a08c37d 100644
--- a/parser/parse_supported.c
+++ b/parser/parse_supported.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2006 Andreas Granig <agranig at linguin.org>
  *
  * This file is part of Kamailio, a free SIP server.
diff --git a/parser/parse_supported.h b/parser/parse_supported.h
index fc547b6..1a55827 100644
--- a/parser/parse_supported.h
+++ b/parser/parse_supported.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2006 Andreas Granig <agranig at linguin.org>
  *
  * This file is part of Kamailio, a free SIP server.
@@ -19,11 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- *
- * History:
- * -------
- * 2006-03-02  parse_supported() parses and cumulates all SUPPORTED 
- *             headers (bogdan)
  */
 
 /*!
diff --git a/parser/parse_to.c b/parser/parse_to.c
index d655de8..6858d4b 100644
--- a/parser/parse_to.c
+++ b/parser/parse_to.c
@@ -1,14 +1,14 @@
 /*
  * Copyright (C) 2001-2003 Fhg Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -17,10 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * ---------
- * 2003-04-26 ZSW (jiri)
- * 2010-03-03  fix multi-token no-quotes display name (andrei)
  */
 
 /** Parser :: Parse To: header.
diff --git a/parser/parse_to.h b/parser/parse_to.h
index 9a4d9c6..7ffe12d 100644
--- a/parser/parse_to.h
+++ b/parser/parse_to.h
@@ -1,14 +1,14 @@
 /*
  * Copyright (C) 2001-2003 Fhg Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/parse_uri.c b/parser/parse_uri.c
index 9c0d5db..4e0be0f 100644
--- a/parser/parse_uri.c
+++ b/parser/parse_uri.c
@@ -1,19 +1,14 @@
 /*
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -22,21 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- * 2003-04-04  convenience inbound-uri parser parse_orig_ruri
- *             introduced (jiri)
- * 2003-04-11  new parse_uri introduced (better, parses also some parameters,
- *              works in one pass) (andrei)
- * 2003-04-11  ser_error is now set in parse_uri (andrei)
- * 2003-04-26  ZSW (jiri)
- * 2003-07-03  sips:, r2, lr=on support added (andrei)
- * 2005-02-25  preliminary tel uri support (andrei)
- * 2005-03-03  more tel uri fixes (andrei)
- * 2006-04-20  comp uri param. support (rfc3486) if defined USE_COMP  (andrei)
- * 2007-09-10  introduced phone2tel option which allows NOT to consider
- *             user=phone URIs as TEL URIs
- *
  */
 
 /** @file
diff --git a/parser/parse_uri.h b/parser/parse_uri.h
index 86f9e06..1638e26 100644
--- a/parser/parse_uri.h
+++ b/parser/parse_uri.h
@@ -1,14 +1,14 @@
 /*
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/parser/parse_via.c b/parser/parse_via.c
index e16ac3d..d99d031 100644
--- a/parser/parse_via.c
+++ b/parser/parse_via.c
@@ -3,19 +3,14 @@
  * 
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -31,31 +26,6 @@
  * @ingroup parser
  */
 
-/* 
- *  2003-01-21  added rport parsing code, contributed by
- *               Maxim Sobolev  <sobomax at FreeBSD.org>
- *  2003-01-23  added extra via param parsing code (i=...), used
- *               by tcp to identify the sending socket, by andrei
- *  2003-01-23  fixed rport parsing code to accept rport w/o any value,
- *               by andrei
- *  2003-01-27  modified parse_via to set new via_param->start member and
- *               via->params.s (andrei)
- *  2003-01-28  zero-terminations replaced with VIA_ZT (jiri)
- *  2003-02-28  scratchpad compatibility abandoned (jiri)
- *  2003-04-26  ZSW (jiri)
- *  2003-06-23  fixed  parse_via_param [op].* param. parsing bug (andrei)
- *  2003-07-02  added support for TLS parsing in via (andrei)
- *  2003-10-27  added support for alias via param parsing [see
- *               draft-ietf-sip-connect-reuse-00.txt.]  (andrei)
- *  2004-03-31  fixed rport set instead of i bug (andrei)
- *  2005-03-02  if via has multiple bodies, and one of them is bad set
- *               also the first one as bad (andrei)
- *  2006-02-24  added support for comp parameter parsing, see rfc3486 (andrei)
- *  2008-08-08  SCTP support (andrei)
- */
-
-
-
 #include "../comp_defs.h"
 #include <stdlib.h>
 #include <string.h>
diff --git a/parser/parse_via.h b/parser/parse_via.h
index 6b73dcd..684be32 100644
--- a/parser/parse_via.h
+++ b/parser/parse_via.h
@@ -1,19 +1,14 @@
 /*
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -29,18 +24,6 @@
  * @ingroup parser
  */
 
-/* 
- *  2003-01-21  added rport parsing code, contributed by
- *               Maxim Sobolev  <sobomax at FreeBSD.org>
- *  2003-01-21  added extra via param parsing code (i=...), used
- *               by tcp to identify the sending socket, by andrei
- *  2003-01-27  added a new member (start) to via_param, by andrei
- *  2003-10-27  added alias to via && PARAM_ALIAS (andrei)
- *  2006-02-24  added comp/PARAM_COMP support (andrei)
- */
-
-
-
 #ifndef PARSE_VIA_H
 #define PARSE_VIA_H
 
diff --git a/parser/parser_f.c b/parser/parser_f.c
index ba9de45..f1a532f 100644
--- a/parser/parser_f.c
+++ b/parser/parser_f.c
@@ -3,19 +3,14 @@
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,9 +19,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * ---------
- * 2003-01-27 next baby-step to removing ZT - PRESERVE_ZT (jiri)
  */
 
 /** @file
diff --git a/parser/parser_f.h b/parser/parser_f.h
index 749c16c..043c653 100644
--- a/parser/parser_f.h
+++ b/parser/parser_f.h
@@ -1,19 +1,14 @@
 /* 
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -22,10 +17,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History
- * --------
- * 2003-02-28 scratchpad compatibility abandoned (jiri)
- * 2003-03-24 find_not_quoted function added (janakj)
  */
 
 /*! \file
diff --git a/pass_fd.c b/pass_fd.c
index 461bd7f..edb1480 100644
--- a/pass_fd.c
+++ b/pass_fd.c
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,21 +17,10 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
- /*
-  * History:
-  * --------
-  *  2002-11-29  created by andrei
-  *  2003-02-20  added solaris support (! HAVE_MSGHDR_MSG_CONTROL) (andrei)
-  *  2003-11-03  added send_all, recv_all  and updated send/get_fd
-  *               to handle signals  (andrei)
-  *  2005-06-13  added flags to recv_all & receive_fd, to allow full blocking
-  *              or semi-nonblocking mode (andrei)
-  *  2008-04-30  added MSG_WAITALL emulation for cygwin (andrei)
-  */
 
 /*!
  * \file
- * \brief SIP-router core :: 
+ * \brief Kamailio core :: 
  * \ingroup core
  * Module: \ref core
  */
@@ -61,7 +43,7 @@
 
 
 
-/* receive all the data or returns error (handles EINTR etc.)
+/** receive all the data or returns error (handles EINTR etc.)
  * params: socket
  *         data     - buffer for the results
  *         data_len - 
@@ -141,7 +123,7 @@ poll_retry:
 
 
 
-/* sends all data (takes care of signals) (assumes blocking fd)
+/** sends all data (takes care of signals) (assumes blocking fd)
  * returns number of bytes sent or < 0 for an error */
 int send_all(int socket, void* data, int data_len)
 {
@@ -160,7 +142,7 @@ again:
 }
 
 
-/* at least 1 byte must be sent! */
+/** at least 1 byte must be sent! */
 int send_fd(int unix_socket, void* data, int data_len, int fd)
 {
 	struct msghdr msg;
@@ -214,7 +196,7 @@ again:
 
 
 
-/* receives a fd and data_len data
+/** receives a fd and data_len data
  * params: unix_socket 
  *         data
  *         data_len
diff --git a/pass_fd.h b/pass_fd.h
index 76d76f9..e02087e 100644
--- a/pass_fd.h
+++ b/pass_fd.h
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,6 +17,12 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
+/*!
+* \file
+* \brief Kamailio core :: File descriptor handling
+* \ingroup core
+* Module: \ref core
+*/
 
 #ifndef _pass_fd_h
 #define _pass_fd_h
diff --git a/pkg/kamailio/centos/6/kamailio.spec b/pkg/kamailio/centos/6/kamailio.spec
index ffb3839..fa3039a 100644
--- a/pkg/kamailio/centos/6/kamailio.spec
+++ b/pkg/kamailio/centos/6/kamailio.spec
@@ -1,6 +1,6 @@
 %define name	kamailio
-%define ver	4.2.5
-%define rel	0%{dist}
+%define ver	4.2.0
+%define rel	dev0.0%{dist}
 
 
 
diff --git a/pkg/kamailio/deb/debian/backports/precise b/pkg/kamailio/deb/debian/backports/precise
index 9f631f3..ca062a9 100755
--- a/pkg/kamailio/deb/debian/backports/precise
+++ b/pkg/kamailio/deb/debian/backports/precise
@@ -33,6 +33,11 @@ sed -i -e '/librabbitmq-dev/d' -e '/^Package: kamailio-kazoo-modules/,/^$/d' \
 sed -i -e 's/ kazoo[ ,$]*/ /' ${DIST}/rules
 sed -i -e '/^EXTRA_EXCLUDED_MODULES=/s/$/ kazoo/' ${DIST}/rules
 
+# no cnxcc module
+sed -i -e '/^Package: kamailio-cnxcc-modules/,/^$/d' ${DIST}/control
+sed -i -e 's/ cnxcc[ ,$]*/ /' ${DIST}/rules
+sed -i -e '/^EXTRA_EXCLUDED_MODULES=/s/$/ cnxcc/' ${DIST}/rules
+
 # clean backports scripts
 rm -rf ${DIST}/backports
 exit 0
diff --git a/pkg/kamailio/deb/debian/backports/squeeze b/pkg/kamailio/deb/debian/backports/squeeze
index 21aac4a..9fed142 100755
--- a/pkg/kamailio/deb/debian/backports/squeeze
+++ b/pkg/kamailio/deb/debian/backports/squeeze
@@ -79,6 +79,17 @@ sed -i -e '/librabbitmq-dev/d' -e '/^Package: kamailio-kazoo-modules/,/^$/d' \
 sed -i -e 's/ kazoo[ ,$]*/ /' ${DIST}/rules
 sed -i -e '/^EXTRA_EXCLUDED_MODULES=/s/$/ kazoo/' ${DIST}/rules
 
+# no cnxcc module
+sed -i -e '/^Package: kamailio-cnxcc-modules/,/^$/d' ${DIST}/control
+sed -i -e 's/ cnxcc[ ,$]*/ /' ${DIST}/rules
+sed -i -e '/^EXTRA_EXCLUDED_MODULES=/s/$/ cnxcc/' ${DIST}/rules
+
+# no jansson module
+sed -i -e '/libjansson-dev/d' ${DIST}/control
+sed -i -e 's/ jansson[ ,$]*/ /' ${DIST}/rules
+sed -i -e '/^EXTRA_EXCLUDED_MODULES=/s/$/ jansson/' ${DIST}/rules
+sed -i -e 's/ jansson[ ,$]*//' ${DIST}/control
+
 # clean backports scripts
 rm -rf ${DIST}/backports
 exit 0
diff --git a/pkg/kamailio/deb/debian/backports/wheezy b/pkg/kamailio/deb/debian/backports/wheezy
index 24c4c17..e0f7391 100755
--- a/pkg/kamailio/deb/debian/backports/wheezy
+++ b/pkg/kamailio/deb/debian/backports/wheezy
@@ -39,6 +39,11 @@ sed -i -e '/librabbitmq-dev/d' -e '/^Package: kamailio-kazoo-modules/,/^$/d' \
 sed -i -e 's/ kazoo[ ,$]*/ /' ${DIST}/rules
 sed -i -e '/^EXTRA_EXCLUDED_MODULES=/s/$/ kazoo/' ${DIST}/rules
 
+# no cnxcc module
+sed -i -e '/^Package: kamailio-cnxcc-modules/,/^$/d' ${DIST}/control
+sed -i -e 's/ cnxcc[ ,$]*/ /' ${DIST}/rules
+sed -i -e '/^EXTRA_EXCLUDED_MODULES=/s/$/ cnxcc/' ${DIST}/rules
+
 # clean backports scripts
 rm -rf ${DIST}/backports
 exit 0
diff --git a/pkg/kamailio/deb/debian/changelog b/pkg/kamailio/deb/debian/changelog
index 7d568dc..3a1bbe4 100644
--- a/pkg/kamailio/deb/debian/changelog
+++ b/pkg/kamailio/deb/debian/changelog
@@ -1,50 +1,56 @@
-kamailio (4.2.5) unstable; urgency=medium
+kamailio (4.3.0~rc0) unstable; urgency=medium
 
-  * update versionto 4.2.5
+  * update version to 4.3.0~rc0
 
- -- Daniel-Constantin Mierla <miconda at gmail.com>  Tue, 19 May 2015 12:10:55 +0100
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Tue, 26 May 2015 20:55:14 +0200
 
-kamailio (4.2.4) unstable; urgency=medium
+kamailio (4.3.0~pre2) unstable; urgency=medium
 
-  * update versionto 4.2.4
+  * update version to 4.3.0~pre2
 
- -- Daniel-Constantin Mierla <miconda at gmail.com>  Thu, 02 Apr 2015 14:20:05 +0100
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Mon, 18 May 2015 11:18:45 +0200
 
-kamailio (4.2.3) unstable; urgency=medium
+kamailio (4.3.0~pre1) unstable; urgency=medium
 
-  * update versionto 4.2.3
+  * update version to 4.3.0~pre1
 
- -- Daniel-Constantin Mierla <miconda at gmail.com>  Tue, 10 Feb 2015 15:30:45 +0100
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Tue, 05 May 2015 10:52:12 +0200
 
-kamailio (4.2.2) unstable; urgency=medium
+kamailio (4.3.0~pre0) unstable; urgency=medium
 
-  * update versionto 4.2.2
+  * update version to 4.3.0~pre0
 
- -- Daniel-Constantin Mierla <miconda at gmail.com>  Thu, 08 Jan 2015 14:25:40 +0100
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Thu, 23 Apr 2015 09:58:06 +0200
 
-kamailio (4.2.1) unstable; urgency=medium
+kamailio (4.3.0~dev5) unstable; urgency=medium
 
-  * update versionto 4.2.1
+  * update version to 4.3.0~dev5
 
- -- Daniel-Constantin Mierla <miconda at gmail.com>  Tue, 11 Nov 2014 11:55:40 +0100
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Thu, 12 Mar 2015 15:20:01 +0100
 
-kamailio (4.2.0) unstable; urgency=medium
+kamailio (4.3.0~dev4) unstable; urgency=medium
 
-  * update versionto 4.2.0
+  * update version to 4.3.0~dev4
 
- -- Daniel-Constantin Mierla <miconda at gmail.com>  Thu, 16 Oct 2014 14:25:30 +0100
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Sat, 07 Feb 2015 09:53:08 +0100
 
-kamailio (4.2.0~rc1) unstable; urgency=medium
+kamailio (4.3.0~dev3) unstable; urgency=medium
 
-  * update version to 4.2.0~rc1
+  * update version to 4.3.0~dev3
 
- -- Victor Seva <linuxmaniac at torreviejawireless.org>  Mon, 13 Oct 2014 23:39:26 +0200
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Sat, 03 Jan 2015 23:21:53 +0100
 
-kamailio (4.2.0~rc0) unstable; urgency=medium
+kamailio (4.3.0~dev1) unstable; urgency=medium
 
-  * update version to 4.2.0~rc0
+  * update version to 4.3.0~dev1
 
- -- Victor Seva <linuxmaniac at torreviejawireless.org>  Thu, 09 Oct 2014 09:55:52 +0200
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Mon, 13 Oct 2014 14:33:16 +0200
+
+kamailio (4.3.0~dev0) unstable; urgency=medium
+
+  * update version to 4.3.0~dev0
+
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Thu, 09 Oct 2014 09:49:13 +0200
 
 kamailio (4.2.0~pre1) UNRELEASED; urgency=medium
 
diff --git a/pkg/kamailio/deb/debian/control b/pkg/kamailio/deb/debian/control
index 2aeac33..f0b4739 100644
--- a/pkg/kamailio/deb/debian/control
+++ b/pkg/kamailio/deb/debian/control
@@ -19,6 +19,7 @@ Build-Depends: bison,
                libfreeradius-client-dev,
                libgeoip-dev (>= 1.4.5),
                libhiredis-dev (>= 0.10.0),
+               libjansson-dev,
                libjson-c-dev,
                libldap2-dev,
                liblua5.1-0-dev,
@@ -607,6 +608,20 @@ Description: kazoo modules for Kamailio
  .
  This package provides the kazoo module for Kamailio.
 
+Package: kamailio-cnxcc-modules
+Architecture: linux-any
+Multi-Arch: same
+Pre-Depends: ${misc:Pre-Depends}
+Depends: kamailio (= ${binary:Version}),
+         ${misc:Depends},
+         ${shlibs:Depends}
+Description: cnxcc modules for Kamailio
+ Kamailio is a very fast and flexible SIP (RFC3261)
+ proxy server. Written entirely in C, Kamailio can handle thousands calls
+ per second even on low-budget hardware.
+ .
+ This package provides the cnxcc module for Kamailio.
+
 Package: kamailio-extra-modules
 Architecture: linux-any
 Multi-Arch: same
@@ -619,7 +634,7 @@ Description: extra modules for Kamailio
  proxy server. Written entirely in C, Kamailio can handle thousands calls
  per second even on low-budget hardware.
  .
- This package provides: gzcompress uuid ev
+ This package provides: gzcompress uuid ev jansson
 
 Package: kamailio-nth
 Architecture: any
diff --git a/pkg/kamailio/deb/debian/rules b/pkg/kamailio/deb/debian/rules
index 39c3660..b4d1983 100755
--- a/pkg/kamailio/deb/debian/rules
+++ b/pkg/kamailio/deb/debian/rules
@@ -39,10 +39,10 @@ PACKAGE_GROUPS=mysql postgres berkeley unixodbc radius presence \
 			   ldap xml perl utils lua memcached \
 			   snmpstats carrierroute xmpp cpl redis python geoip\
 			   sqlite json mono ims sctp java \
-			   purple tls outbound websocket autheph dnssec kazoo
+			   purple tls outbound websocket autheph dnssec kazoo cnxcc
 
 # module groups to be packaged onto kamailio-extra-modules
-EXTRA_GROUPS=gzcompress uuid ev
+EXTRA_GROUPS=gzcompress uuid ev jansson
 
 # name of libdir in the path for libraries (e.g., lib for 32b, lib64 for 64b)
 LIBDIR ?= lib/$(DEB_HOST_MULTIARCH)
@@ -67,7 +67,7 @@ endef
 define PACKAGE_GRP_INSTALL_template
 	$(foreach grp,$(PACKAGE_GROUPS),\
 		$(MAKE) install-modules-all LIBDIR=$(LIBDIR) group_include="k$(grp)" \
-		basedir=$(CURDIR)/debian/kamailio-$(grp)-modules \
+		BASEDIR=$(CURDIR)/debian/kamailio-$(grp)-modules \
 		cfg_prefix=$(CURDIR)/debian/kamailio-$(grp)-modules \
 		doc-dir=share/doc/kamailio-$(grp)-modules
 		# eliminate duplicate libs
@@ -85,7 +85,7 @@ endef
 define PACKAGE_EXTRA_INSTALL_template
 	$(foreach grp,$(EXTRA_GROUPS),\
 		$(MAKE) install-modules-all LIBDIR=$(LIBDIR) group_include="k$(grp)" \
-		basedir=$(CURDIR)/debian/kamailio-extra-modules \
+		BASEDIR=$(CURDIR)/debian/kamailio-extra-modules \
 		cfg_prefix=$(CURDIR)/debian/kamailio-extra-modules \
 		doc-dir=share/doc/kamailio-extra-modules
 	)
@@ -100,17 +100,15 @@ define PACKAGE_EXTRA_INSTALL_template
 	find $(CURDIR)/debian/kamailio-extra-modules -depth -empty -type d -exec rmdir {} \;
 endef
 
-ifneq (,$(findstring debug,$(DEB_BUILD_OPTIONS)))
-	CFLAGS += -g
-endif
-ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
-	INSTALL_PROGRAM += -s
-endif
-
 # CFLAGS + CPPFLAGS -> CC_EXTRA_OPTS
+CC_EXTRA_OPTS := $(shell dpkg-buildflags --get CPPFLAGS)
+CC_EXTRA_OPTS += $(shell dpkg-buildflags --get CFLAGS)
+CXXFLAGS := $(shell dpkg-buildflags --get CXXFLAGS)
 # LDFLAGS -> LD_EXTRA_OPTS
-CUSTOM_BUILDFLAGS:=$(shell dpkg-buildflags --export=configure| \
-sed -e 's/" CPPFLAGS="/ /' -e 's/CFLAGS/CC_EXTRA_OPTS/g' -e 's/LDFLAGS/LD_EXTRA_OPTS/g')
+LD_EXTRA_OPTS := $(shell dpkg-buildflags --get LDFLAGS)
+
+# https://wiki.debian.org/ReproducibleBuilds/
+CC_EXTRA_OPTS += -DVERSION_NODATE
 
 configure: configure-stamp
 configure-stamp:
@@ -118,9 +116,10 @@ configure-stamp:
 	# Add here commands to configure the package.
 	$(MAKE) FLAVOUR=kamailio cfg prefix=/usr cfg_prefix=$(CURDIR)/debian/kamailio \
 			cfg_target=/etc/kamailio/ \
-			basedir=$(CURDIR)/debian/kamailio \
+			BASEDIR=$(CURDIR)/debian/kamailio \
 			skip_modules="$(EXCLUDED_MODULES) $(EXTRA_EXCLUDED_MODULES)" \
-			$(CUSTOM_BUILDFLAGS) \
+			CC_EXTRA_OPTS="$(CC_EXTRA_OPTS)" \
+			LD_EXTRA_OPTS="$(LD_EXTRA_OPTS)" \
 			group_include="kstandard"
 
 	touch configure-stamp
@@ -160,6 +159,8 @@ install: build
 	# install /etc/default/kamailio file
 	mkdir -p $(CURDIR)/debian/kamailio/etc/default
 	cp -f debian/kamailio.default $(CURDIR)/debian/kamailio/etc/default/kamailio
+	# delete /var/run/kamailio dir
+	rm -rf $(CURDIR)/debian/kamailio/usr/local
 
 
 # This single target is used to build all the packages, all at once, or
@@ -171,7 +172,7 @@ binary-common:
 	dh_testroot
 	dh_installdebconf
 	dh_installdocs
-	dh_installexamples
+	dh_installexamples -Xobsoleted -Xsr
 	dh_installmenu
 	dh_installinit -pkamailio -- defaults 23
 	dh_installcron
diff --git a/pkg/kamailio/deb/jessie/changelog b/pkg/kamailio/deb/jessie/changelog
index 7d568dc..3a1bbe4 100644
--- a/pkg/kamailio/deb/jessie/changelog
+++ b/pkg/kamailio/deb/jessie/changelog
@@ -1,50 +1,56 @@
-kamailio (4.2.5) unstable; urgency=medium
+kamailio (4.3.0~rc0) unstable; urgency=medium
 
-  * update versionto 4.2.5
+  * update version to 4.3.0~rc0
 
- -- Daniel-Constantin Mierla <miconda at gmail.com>  Tue, 19 May 2015 12:10:55 +0100
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Tue, 26 May 2015 20:55:14 +0200
 
-kamailio (4.2.4) unstable; urgency=medium
+kamailio (4.3.0~pre2) unstable; urgency=medium
 
-  * update versionto 4.2.4
+  * update version to 4.3.0~pre2
 
- -- Daniel-Constantin Mierla <miconda at gmail.com>  Thu, 02 Apr 2015 14:20:05 +0100
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Mon, 18 May 2015 11:18:45 +0200
 
-kamailio (4.2.3) unstable; urgency=medium
+kamailio (4.3.0~pre1) unstable; urgency=medium
 
-  * update versionto 4.2.3
+  * update version to 4.3.0~pre1
 
- -- Daniel-Constantin Mierla <miconda at gmail.com>  Tue, 10 Feb 2015 15:30:45 +0100
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Tue, 05 May 2015 10:52:12 +0200
 
-kamailio (4.2.2) unstable; urgency=medium
+kamailio (4.3.0~pre0) unstable; urgency=medium
 
-  * update versionto 4.2.2
+  * update version to 4.3.0~pre0
 
- -- Daniel-Constantin Mierla <miconda at gmail.com>  Thu, 08 Jan 2015 14:25:40 +0100
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Thu, 23 Apr 2015 09:58:06 +0200
 
-kamailio (4.2.1) unstable; urgency=medium
+kamailio (4.3.0~dev5) unstable; urgency=medium
 
-  * update versionto 4.2.1
+  * update version to 4.3.0~dev5
 
- -- Daniel-Constantin Mierla <miconda at gmail.com>  Tue, 11 Nov 2014 11:55:40 +0100
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Thu, 12 Mar 2015 15:20:01 +0100
 
-kamailio (4.2.0) unstable; urgency=medium
+kamailio (4.3.0~dev4) unstable; urgency=medium
 
-  * update versionto 4.2.0
+  * update version to 4.3.0~dev4
 
- -- Daniel-Constantin Mierla <miconda at gmail.com>  Thu, 16 Oct 2014 14:25:30 +0100
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Sat, 07 Feb 2015 09:53:08 +0100
 
-kamailio (4.2.0~rc1) unstable; urgency=medium
+kamailio (4.3.0~dev3) unstable; urgency=medium
 
-  * update version to 4.2.0~rc1
+  * update version to 4.3.0~dev3
 
- -- Victor Seva <linuxmaniac at torreviejawireless.org>  Mon, 13 Oct 2014 23:39:26 +0200
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Sat, 03 Jan 2015 23:21:53 +0100
 
-kamailio (4.2.0~rc0) unstable; urgency=medium
+kamailio (4.3.0~dev1) unstable; urgency=medium
 
-  * update version to 4.2.0~rc0
+  * update version to 4.3.0~dev1
 
- -- Victor Seva <linuxmaniac at torreviejawireless.org>  Thu, 09 Oct 2014 09:55:52 +0200
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Mon, 13 Oct 2014 14:33:16 +0200
+
+kamailio (4.3.0~dev0) unstable; urgency=medium
+
+  * update version to 4.3.0~dev0
+
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Thu, 09 Oct 2014 09:49:13 +0200
 
 kamailio (4.2.0~pre1) UNRELEASED; urgency=medium
 
diff --git a/pkg/kamailio/deb/jessie/control b/pkg/kamailio/deb/jessie/control
index b992303..940afbe 100644
--- a/pkg/kamailio/deb/jessie/control
+++ b/pkg/kamailio/deb/jessie/control
@@ -19,6 +19,7 @@ Build-Depends: bison,
                libfreeradius-client-dev,
                libgeoip-dev (>= 1.4.5),
                libhiredis-dev (>= 0.10.0),
+               libjansson-dev,
                libjson-c-dev,
                libldap2-dev,
                liblua5.1-0-dev,
@@ -606,6 +607,20 @@ Description: kazoo modules for Kamailio
  .
  This package provides the kazoo module for Kamailio.
 
+Package: kamailio-cnxcc-modules
+Architecture: linux-any
+Multi-Arch: same
+Pre-Depends: ${misc:Pre-Depends}
+Depends: kamailio (= ${binary:Version}),
+         ${misc:Depends},
+         ${shlibs:Depends}
+Description: cnxcc modules for Kamailio
+ Kamailio is a very fast and flexible SIP (RFC3261)
+ proxy server. Written entirely in C, Kamailio can handle thousands calls
+ per second even on low-budget hardware.
+ .
+ This package provides the cnxcc module for Kamailio.
+
 Package: kamailio-extra-modules
 Architecture: linux-any
 Multi-Arch: same
@@ -618,7 +633,7 @@ Description: extra modules for Kamailio
  proxy server. Written entirely in C, Kamailio can handle thousands calls
  per second even on low-budget hardware.
  .
- This package provides: gzcompress uuid ev
+ This package provides: gzcompress uuid ev jansson
 
 Package: kamailio-nth
 Architecture: any
diff --git a/pkg/kamailio/deb/jessie/rules b/pkg/kamailio/deb/jessie/rules
index 8cbe6bb..fb20807 100755
--- a/pkg/kamailio/deb/jessie/rules
+++ b/pkg/kamailio/deb/jessie/rules
@@ -39,10 +39,10 @@ PACKAGE_GROUPS=mysql postgres berkeley unixodbc radius presence \
 			   ldap xml perl utils lua memcached \
 			   snmpstats carrierroute xmpp cpl redis python geoip\
 			   sqlite json mono ims sctp java \
-			   purple tls outbound websocket autheph dnssec kazoo
+			   purple tls outbound websocket autheph dnssec kazoo cnxcc
 
 # module groups to be packaged onto kamailio-extra-modules
-EXTRA_GROUPS=gzcompress uuid ev
+EXTRA_GROUPS=gzcompress uuid ev jansson
 
 # name of libdir in the path for libraries (e.g., lib for 32b, lib64 for 64b)
 LIBDIR ?= lib/$(DEB_HOST_MULTIARCH)
@@ -67,7 +67,7 @@ endef
 define PACKAGE_GRP_INSTALL_template
 	$(foreach grp,$(PACKAGE_GROUPS),\
 		$(MAKE) install-modules-all LIBDIR=$(LIBDIR) group_include="k$(grp)" \
-		basedir=$(CURDIR)/debian/kamailio-$(grp)-modules \
+		BASEDIR=$(CURDIR)/debian/kamailio-$(grp)-modules \
 		cfg_prefix=$(CURDIR)/debian/kamailio-$(grp)-modules \
 		doc-dir=share/doc/kamailio-$(grp)-modules
 		# eliminate duplicate libs
@@ -85,7 +85,7 @@ endef
 define PACKAGE_EXTRA_INSTALL_template
 	$(foreach grp,$(EXTRA_GROUPS),\
 		$(MAKE) install-modules-all LIBDIR=$(LIBDIR) group_include="k$(grp)" \
-		basedir=$(CURDIR)/debian/kamailio-extra-modules \
+		BASEDIR=$(CURDIR)/debian/kamailio-extra-modules \
 		cfg_prefix=$(CURDIR)/debian/kamailio-extra-modules \
 		doc-dir=share/doc/kamailio-extra-modules
 	)
@@ -100,17 +100,15 @@ define PACKAGE_EXTRA_INSTALL_template
 	find $(CURDIR)/debian/kamailio-extra-modules -depth -empty -type d -exec rmdir {} \;
 endef
 
-ifneq (,$(findstring debug,$(DEB_BUILD_OPTIONS)))
-	CFLAGS += -g
-endif
-ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
-	INSTALL_PROGRAM += -s
-endif
-
 # CFLAGS + CPPFLAGS -> CC_EXTRA_OPTS
+CC_EXTRA_OPTS := $(shell dpkg-buildflags --get CPPFLAGS)
+CC_EXTRA_OPTS += $(shell dpkg-buildflags --get CFLAGS)
+CXXFLAGS := $(shell dpkg-buildflags --get CXXFLAGS)
 # LDFLAGS -> LD_EXTRA_OPTS
-CUSTOM_BUILDFLAGS:=$(shell dpkg-buildflags --export=configure| \
-sed -e 's/" CPPFLAGS="/ /' -e 's/CFLAGS/CC_EXTRA_OPTS/g' -e 's/LDFLAGS/LD_EXTRA_OPTS/g')
+LD_EXTRA_OPTS := $(shell dpkg-buildflags --get LDFLAGS)
+
+# https://wiki.debian.org/ReproducibleBuilds/
+CC_EXTRA_OPTS += -DVERSION_NODATE
 
 configure: configure-stamp
 configure-stamp:
@@ -118,9 +116,10 @@ configure-stamp:
 	# Add here commands to configure the package.
 	$(MAKE) FLAVOUR=kamailio cfg prefix=/usr cfg_prefix=$(CURDIR)/debian/kamailio \
 			cfg_target=/etc/kamailio/ \
-			basedir=$(CURDIR)/debian/kamailio \
+			BASEDIR=$(CURDIR)/debian/kamailio \
 			skip_modules="$(EXCLUDED_MODULES) $(EXTRA_EXCLUDED_MODULES)" \
-			$(CUSTOM_BUILDFLAGS) \
+			CC_EXTRA_OPTS="$(CC_EXTRA_OPTS)" \
+			LD_EXTRA_OPTS="$(LD_EXTRA_OPTS)" \
 			group_include="kstandard"
 
 	touch configure-stamp
@@ -160,6 +159,8 @@ install: build
 	# install /etc/default/kamailio file
 	mkdir -p $(CURDIR)/debian/kamailio/etc/default
 	cp -f debian/kamailio.default $(CURDIR)/debian/kamailio/etc/default/kamailio
+	# delete /var/run/kamailio dir
+	rm -rf $(CURDIR)/debian/kamailio/usr/local
 
 
 # This single target is used to build all the packages, all at once, or
@@ -171,7 +172,7 @@ binary-common:
 	dh_testroot
 	dh_installdebconf
 	dh_installdocs
-	dh_installexamples
+	dh_installexamples -Xobsoleted -Xsr
 	dh_installmenu
 	dh_installinit -pkamailio -- defaults 23
 	dh_installcron
diff --git a/pkg/kamailio/deb/precise/changelog b/pkg/kamailio/deb/precise/changelog
index 7d568dc..3a1bbe4 100644
--- a/pkg/kamailio/deb/precise/changelog
+++ b/pkg/kamailio/deb/precise/changelog
@@ -1,50 +1,56 @@
-kamailio (4.2.5) unstable; urgency=medium
+kamailio (4.3.0~rc0) unstable; urgency=medium
 
-  * update versionto 4.2.5
+  * update version to 4.3.0~rc0
 
- -- Daniel-Constantin Mierla <miconda at gmail.com>  Tue, 19 May 2015 12:10:55 +0100
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Tue, 26 May 2015 20:55:14 +0200
 
-kamailio (4.2.4) unstable; urgency=medium
+kamailio (4.3.0~pre2) unstable; urgency=medium
 
-  * update versionto 4.2.4
+  * update version to 4.3.0~pre2
 
- -- Daniel-Constantin Mierla <miconda at gmail.com>  Thu, 02 Apr 2015 14:20:05 +0100
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Mon, 18 May 2015 11:18:45 +0200
 
-kamailio (4.2.3) unstable; urgency=medium
+kamailio (4.3.0~pre1) unstable; urgency=medium
 
-  * update versionto 4.2.3
+  * update version to 4.3.0~pre1
 
- -- Daniel-Constantin Mierla <miconda at gmail.com>  Tue, 10 Feb 2015 15:30:45 +0100
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Tue, 05 May 2015 10:52:12 +0200
 
-kamailio (4.2.2) unstable; urgency=medium
+kamailio (4.3.0~pre0) unstable; urgency=medium
 
-  * update versionto 4.2.2
+  * update version to 4.3.0~pre0
 
- -- Daniel-Constantin Mierla <miconda at gmail.com>  Thu, 08 Jan 2015 14:25:40 +0100
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Thu, 23 Apr 2015 09:58:06 +0200
 
-kamailio (4.2.1) unstable; urgency=medium
+kamailio (4.3.0~dev5) unstable; urgency=medium
 
-  * update versionto 4.2.1
+  * update version to 4.3.0~dev5
 
- -- Daniel-Constantin Mierla <miconda at gmail.com>  Tue, 11 Nov 2014 11:55:40 +0100
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Thu, 12 Mar 2015 15:20:01 +0100
 
-kamailio (4.2.0) unstable; urgency=medium
+kamailio (4.3.0~dev4) unstable; urgency=medium
 
-  * update versionto 4.2.0
+  * update version to 4.3.0~dev4
 
- -- Daniel-Constantin Mierla <miconda at gmail.com>  Thu, 16 Oct 2014 14:25:30 +0100
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Sat, 07 Feb 2015 09:53:08 +0100
 
-kamailio (4.2.0~rc1) unstable; urgency=medium
+kamailio (4.3.0~dev3) unstable; urgency=medium
 
-  * update version to 4.2.0~rc1
+  * update version to 4.3.0~dev3
 
- -- Victor Seva <linuxmaniac at torreviejawireless.org>  Mon, 13 Oct 2014 23:39:26 +0200
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Sat, 03 Jan 2015 23:21:53 +0100
 
-kamailio (4.2.0~rc0) unstable; urgency=medium
+kamailio (4.3.0~dev1) unstable; urgency=medium
 
-  * update version to 4.2.0~rc0
+  * update version to 4.3.0~dev1
 
- -- Victor Seva <linuxmaniac at torreviejawireless.org>  Thu, 09 Oct 2014 09:55:52 +0200
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Mon, 13 Oct 2014 14:33:16 +0200
+
+kamailio (4.3.0~dev0) unstable; urgency=medium
+
+  * update version to 4.3.0~dev0
+
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Thu, 09 Oct 2014 09:49:13 +0200
 
 kamailio (4.2.0~pre1) UNRELEASED; urgency=medium
 
diff --git a/pkg/kamailio/deb/precise/control b/pkg/kamailio/deb/precise/control
index 5d790c0..869d349 100644
--- a/pkg/kamailio/deb/precise/control
+++ b/pkg/kamailio/deb/precise/control
@@ -19,6 +19,7 @@ Build-Depends: bison,
                libradiusclient-ng-dev,
                libgeoip-dev (>= 1.4.5),
                libhiredis-dev (>= 0.10.0),
+               libjansson-dev,
                libjson0-dev,
                libldap2-dev,
                liblua5.1-0-dev,
@@ -588,7 +589,7 @@ Description: extra modules for Kamailio
  proxy server. Written entirely in C, Kamailio can handle thousands calls
  per second even on low-budget hardware.
  .
- This package provides: gzcompress uuid ev
+ This package provides: gzcompress uuid ev jansson
 
 Package: kamailio-nth
 Architecture: any
diff --git a/pkg/kamailio/deb/precise/rules b/pkg/kamailio/deb/precise/rules
index f4367c6..1f449b9 100755
--- a/pkg/kamailio/deb/precise/rules
+++ b/pkg/kamailio/deb/precise/rules
@@ -28,7 +28,7 @@ EXCLUDED_MODULES=
 # extra modules to skip, because they are not compilable now
 # - regardless if they go to the main kamailio package or to some module package,
 # they will be excluded from compile and install of all
-EXTRA_EXCLUDED_MODULES=bdb dbtext oracle pa iptrtpproxy mi_xmlrpc dnssec kazoo
+EXTRA_EXCLUDED_MODULES=bdb dbtext oracle pa iptrtpproxy mi_xmlrpc dnssec kazoo cnxcc
 
 # module groups that are packaged in seperate packages
 # (with the name kamailio-$(group_name)-modules)
@@ -41,7 +41,7 @@ PACKAGE_GROUPS=mysql postgres berkeley unixodbc radius presence \
 			   purple tls outbound websocket autheph 
 
 # module groups to be packaged onto kamailio-extra-modules
-EXTRA_GROUPS=gzcompress uuid ev
+EXTRA_GROUPS=gzcompress uuid ev jansson
 
 # name of libdir in the path for libraries (e.g., lib for 32b, lib64 for 64b)
 LIBDIR ?= lib/$(DEB_HOST_MULTIARCH)
@@ -66,7 +66,7 @@ endef
 define PACKAGE_GRP_INSTALL_template
 	$(foreach grp,$(PACKAGE_GROUPS),\
 		$(MAKE) install-modules-all LIBDIR=$(LIBDIR) group_include="k$(grp)" \
-		basedir=$(CURDIR)/debian/kamailio-$(grp)-modules \
+		BASEDIR=$(CURDIR)/debian/kamailio-$(grp)-modules \
 		cfg_prefix=$(CURDIR)/debian/kamailio-$(grp)-modules \
 		doc-dir=share/doc/kamailio-$(grp)-modules
 		# eliminate duplicate libs
@@ -84,7 +84,7 @@ endef
 define PACKAGE_EXTRA_INSTALL_template
 	$(foreach grp,$(EXTRA_GROUPS),\
 		$(MAKE) install-modules-all LIBDIR=$(LIBDIR) group_include="k$(grp)" \
-		basedir=$(CURDIR)/debian/kamailio-extra-modules \
+		BASEDIR=$(CURDIR)/debian/kamailio-extra-modules \
 		cfg_prefix=$(CURDIR)/debian/kamailio-extra-modules \
 		doc-dir=share/doc/kamailio-extra-modules
 	)
@@ -99,17 +99,15 @@ define PACKAGE_EXTRA_INSTALL_template
 	find $(CURDIR)/debian/kamailio-extra-modules -depth -empty -type d -exec rmdir {} \;
 endef
 
-ifneq (,$(findstring debug,$(DEB_BUILD_OPTIONS)))
-	CFLAGS += -g
-endif
-ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
-	INSTALL_PROGRAM += -s
-endif
-
 # CFLAGS + CPPFLAGS -> CC_EXTRA_OPTS
+CC_EXTRA_OPTS := $(shell dpkg-buildflags --get CPPFLAGS)
+CC_EXTRA_OPTS += $(shell dpkg-buildflags --get CFLAGS)
+CXXFLAGS := $(shell dpkg-buildflags --get CXXFLAGS)
 # LDFLAGS -> LD_EXTRA_OPTS
-CUSTOM_BUILDFLAGS:=$(shell dpkg-buildflags --export=configure| \
-sed -e 's/" CPPFLAGS="/ /' -e 's/CFLAGS/CC_EXTRA_OPTS/g' -e 's/LDFLAGS/LD_EXTRA_OPTS/g')
+LD_EXTRA_OPTS := $(shell dpkg-buildflags --get LDFLAGS)
+
+# https://wiki.debian.org/ReproducibleBuilds/
+CC_EXTRA_OPTS += -DVERSION_NODATE
 
 configure: configure-stamp
 configure-stamp:
@@ -117,9 +115,10 @@ configure-stamp:
 	# Add here commands to configure the package.
 	$(MAKE) FLAVOUR=kamailio cfg prefix=/usr cfg_prefix=$(CURDIR)/debian/kamailio \
 			cfg_target=/etc/kamailio/ \
-			basedir=$(CURDIR)/debian/kamailio \
+			BASEDIR=$(CURDIR)/debian/kamailio \
 			skip_modules="$(EXCLUDED_MODULES) $(EXTRA_EXCLUDED_MODULES)" \
-			$(CUSTOM_BUILDFLAGS) \
+			CC_EXTRA_OPTS="$(CC_EXTRA_OPTS)" \
+			LD_EXTRA_OPTS="$(LD_EXTRA_OPTS)" \
 			group_include="kstandard"
 
 	touch configure-stamp
@@ -159,6 +158,8 @@ install: build
 	# install /etc/default/kamailio file
 	mkdir -p $(CURDIR)/debian/kamailio/etc/default
 	cp -f debian/kamailio.default $(CURDIR)/debian/kamailio/etc/default/kamailio
+	# delete /var/run/kamailio dir
+	rm -rf $(CURDIR)/debian/kamailio/usr/local
 
 
 # This single target is used to build all the packages, all at once, or
@@ -170,7 +171,7 @@ binary-common:
 	dh_testroot
 	dh_installdebconf
 	dh_installdocs
-	dh_installexamples
+	dh_installexamples -Xobsoleted -Xsr
 	dh_installmenu
 	dh_installinit -pkamailio -- defaults 23
 	dh_installcron
diff --git a/pkg/kamailio/deb/squeeze/changelog b/pkg/kamailio/deb/squeeze/changelog
index 7d568dc..3a1bbe4 100644
--- a/pkg/kamailio/deb/squeeze/changelog
+++ b/pkg/kamailio/deb/squeeze/changelog
@@ -1,50 +1,56 @@
-kamailio (4.2.5) unstable; urgency=medium
+kamailio (4.3.0~rc0) unstable; urgency=medium
 
-  * update versionto 4.2.5
+  * update version to 4.3.0~rc0
 
- -- Daniel-Constantin Mierla <miconda at gmail.com>  Tue, 19 May 2015 12:10:55 +0100
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Tue, 26 May 2015 20:55:14 +0200
 
-kamailio (4.2.4) unstable; urgency=medium
+kamailio (4.3.0~pre2) unstable; urgency=medium
 
-  * update versionto 4.2.4
+  * update version to 4.3.0~pre2
 
- -- Daniel-Constantin Mierla <miconda at gmail.com>  Thu, 02 Apr 2015 14:20:05 +0100
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Mon, 18 May 2015 11:18:45 +0200
 
-kamailio (4.2.3) unstable; urgency=medium
+kamailio (4.3.0~pre1) unstable; urgency=medium
 
-  * update versionto 4.2.3
+  * update version to 4.3.0~pre1
 
- -- Daniel-Constantin Mierla <miconda at gmail.com>  Tue, 10 Feb 2015 15:30:45 +0100
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Tue, 05 May 2015 10:52:12 +0200
 
-kamailio (4.2.2) unstable; urgency=medium
+kamailio (4.3.0~pre0) unstable; urgency=medium
 
-  * update versionto 4.2.2
+  * update version to 4.3.0~pre0
 
- -- Daniel-Constantin Mierla <miconda at gmail.com>  Thu, 08 Jan 2015 14:25:40 +0100
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Thu, 23 Apr 2015 09:58:06 +0200
 
-kamailio (4.2.1) unstable; urgency=medium
+kamailio (4.3.0~dev5) unstable; urgency=medium
 
-  * update versionto 4.2.1
+  * update version to 4.3.0~dev5
 
- -- Daniel-Constantin Mierla <miconda at gmail.com>  Tue, 11 Nov 2014 11:55:40 +0100
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Thu, 12 Mar 2015 15:20:01 +0100
 
-kamailio (4.2.0) unstable; urgency=medium
+kamailio (4.3.0~dev4) unstable; urgency=medium
 
-  * update versionto 4.2.0
+  * update version to 4.3.0~dev4
 
- -- Daniel-Constantin Mierla <miconda at gmail.com>  Thu, 16 Oct 2014 14:25:30 +0100
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Sat, 07 Feb 2015 09:53:08 +0100
 
-kamailio (4.2.0~rc1) unstable; urgency=medium
+kamailio (4.3.0~dev3) unstable; urgency=medium
 
-  * update version to 4.2.0~rc1
+  * update version to 4.3.0~dev3
 
- -- Victor Seva <linuxmaniac at torreviejawireless.org>  Mon, 13 Oct 2014 23:39:26 +0200
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Sat, 03 Jan 2015 23:21:53 +0100
 
-kamailio (4.2.0~rc0) unstable; urgency=medium
+kamailio (4.3.0~dev1) unstable; urgency=medium
 
-  * update version to 4.2.0~rc0
+  * update version to 4.3.0~dev1
 
- -- Victor Seva <linuxmaniac at torreviejawireless.org>  Thu, 09 Oct 2014 09:55:52 +0200
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Mon, 13 Oct 2014 14:33:16 +0200
+
+kamailio (4.3.0~dev0) unstable; urgency=medium
+
+  * update version to 4.3.0~dev0
+
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Thu, 09 Oct 2014 09:49:13 +0200
 
 kamailio (4.2.0~pre1) UNRELEASED; urgency=medium
 
diff --git a/pkg/kamailio/deb/squeeze/rules b/pkg/kamailio/deb/squeeze/rules
index 067c534..5337ef6 100755
--- a/pkg/kamailio/deb/squeeze/rules
+++ b/pkg/kamailio/deb/squeeze/rules
@@ -26,7 +26,7 @@ EXCLUDED_MODULES=
 # extra modules to skip, because they are not compilable now
 # - regardless if they go to the main kamailio package or to some module package,
 # they will be excluded from compile and install of all
-EXTRA_EXCLUDED_MODULES=bdb dbtext oracle pa iptrtpproxy java dnssec sctp purple redis mono kazoo
+EXTRA_EXCLUDED_MODULES=bdb dbtext oracle pa iptrtpproxy java dnssec sctp purple redis mono kazoo cnxcc jansson
 
 # module groups that are packaged in seperate packages
 # (with the name kamailio-$(group_name)-modules)
@@ -39,7 +39,7 @@ PACKAGE_GROUPS=mysql postgres berkeley unixodbc radius presence \
 			   tls outbound websocket autheph 
 
 # module groups to be packaged onto kamailio-extra-modules
-EXTRA_GROUPS=gzcompress uuid ev
+EXTRA_GROUPS=gzcompress uuid ev 
 
 # name of libdir in the path for libraries (e.g., lib for 32b, lib64 for 64b)
 LIBDIR ?= lib
@@ -64,7 +64,7 @@ endef
 define PACKAGE_GRP_INSTALL_template
 	$(foreach grp,$(PACKAGE_GROUPS),\
 		$(MAKE) install-modules-all LIBDIR=$(LIBDIR) group_include="k$(grp)" \
-		basedir=$(CURDIR)/debian/kamailio-$(grp)-modules \
+		BASEDIR=$(CURDIR)/debian/kamailio-$(grp)-modules \
 		cfg_prefix=$(CURDIR)/debian/kamailio-$(grp)-modules \
 		doc-dir=share/doc/kamailio-$(grp)-modules
 		# eliminate duplicate libs
@@ -82,7 +82,7 @@ endef
 define PACKAGE_EXTRA_INSTALL_template
 	$(foreach grp,$(EXTRA_GROUPS),\
 		$(MAKE) install-modules-all LIBDIR=$(LIBDIR) group_include="k$(grp)" \
-		basedir=$(CURDIR)/debian/kamailio-extra-modules \
+		BASEDIR=$(CURDIR)/debian/kamailio-extra-modules \
 		cfg_prefix=$(CURDIR)/debian/kamailio-extra-modules \
 		doc-dir=share/doc/kamailio-extra-modules
 	)
@@ -97,16 +97,15 @@ define PACKAGE_EXTRA_INSTALL_template
 	find $(CURDIR)/debian/kamailio-extra-modules -depth -empty -type d -exec rmdir {} \;
 endef
 
-ifneq (,$(findstring debug,$(DEB_BUILD_OPTIONS)))
-	CFLAGS += -g
-endif
-ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
-	INSTALL_PROGRAM += -s
-endif
-
 # CFLAGS + CPPFLAGS -> CC_EXTRA_OPTS
+CC_EXTRA_OPTS := $(shell dpkg-buildflags --get CPPFLAGS)
+CC_EXTRA_OPTS += $(shell dpkg-buildflags --get CFLAGS)
+CXXFLAGS := $(shell dpkg-buildflags --get CXXFLAGS)
 # LDFLAGS -> LD_EXTRA_OPTS
-sed -e 's/" CPPFLAGS="/ /' -e 's/CFLAGS/CC_EXTRA_OPTS/g' -e 's/LDFLAGS/LD_EXTRA_OPTS/g')
+LD_EXTRA_OPTS := $(shell dpkg-buildflags --get LDFLAGS)
+
+# https://wiki.debian.org/ReproducibleBuilds/
+CC_EXTRA_OPTS += -DVERSION_NODATE
 
 configure: configure-stamp
 configure-stamp:
@@ -114,9 +113,10 @@ configure-stamp:
 	# Add here commands to configure the package.
 	$(MAKE) FLAVOUR=kamailio cfg prefix=/usr cfg_prefix=$(CURDIR)/debian/kamailio \
 			cfg_target=/etc/kamailio/ \
-			basedir=$(CURDIR)/debian/kamailio \
+			BASEDIR=$(CURDIR)/debian/kamailio \
 			skip_modules="$(EXCLUDED_MODULES) $(EXTRA_EXCLUDED_MODULES)" \
-			$(CUSTOM_BUILDFLAGS) \
+			CC_EXTRA_OPTS="$(CC_EXTRA_OPTS)" \
+			LD_EXTRA_OPTS="$(LD_EXTRA_OPTS)" \
 			group_include="kstandard"
 
 	touch configure-stamp
@@ -156,6 +156,8 @@ install: build
 	# install /etc/default/kamailio file
 	mkdir -p $(CURDIR)/debian/kamailio/etc/default
 	cp -f debian/kamailio.default $(CURDIR)/debian/kamailio/etc/default/kamailio
+	# delete /var/run/kamailio dir
+	rm -rf $(CURDIR)/debian/kamailio/usr/local
 
 
 # This single target is used to build all the packages, all at once, or
@@ -167,7 +169,7 @@ binary-common:
 	dh_testroot
 	dh_installdebconf
 	dh_installdocs
-	dh_installexamples
+	dh_installexamples -Xobsoleted -Xsr
 	dh_installmenu
 	dh_installinit -pkamailio -- defaults 23
 	dh_installcron
diff --git a/pkg/kamailio/deb/trusty/changelog b/pkg/kamailio/deb/trusty/changelog
index 7d568dc..3a1bbe4 100644
--- a/pkg/kamailio/deb/trusty/changelog
+++ b/pkg/kamailio/deb/trusty/changelog
@@ -1,50 +1,56 @@
-kamailio (4.2.5) unstable; urgency=medium
+kamailio (4.3.0~rc0) unstable; urgency=medium
 
-  * update versionto 4.2.5
+  * update version to 4.3.0~rc0
 
- -- Daniel-Constantin Mierla <miconda at gmail.com>  Tue, 19 May 2015 12:10:55 +0100
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Tue, 26 May 2015 20:55:14 +0200
 
-kamailio (4.2.4) unstable; urgency=medium
+kamailio (4.3.0~pre2) unstable; urgency=medium
 
-  * update versionto 4.2.4
+  * update version to 4.3.0~pre2
 
- -- Daniel-Constantin Mierla <miconda at gmail.com>  Thu, 02 Apr 2015 14:20:05 +0100
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Mon, 18 May 2015 11:18:45 +0200
 
-kamailio (4.2.3) unstable; urgency=medium
+kamailio (4.3.0~pre1) unstable; urgency=medium
 
-  * update versionto 4.2.3
+  * update version to 4.3.0~pre1
 
- -- Daniel-Constantin Mierla <miconda at gmail.com>  Tue, 10 Feb 2015 15:30:45 +0100
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Tue, 05 May 2015 10:52:12 +0200
 
-kamailio (4.2.2) unstable; urgency=medium
+kamailio (4.3.0~pre0) unstable; urgency=medium
 
-  * update versionto 4.2.2
+  * update version to 4.3.0~pre0
 
- -- Daniel-Constantin Mierla <miconda at gmail.com>  Thu, 08 Jan 2015 14:25:40 +0100
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Thu, 23 Apr 2015 09:58:06 +0200
 
-kamailio (4.2.1) unstable; urgency=medium
+kamailio (4.3.0~dev5) unstable; urgency=medium
 
-  * update versionto 4.2.1
+  * update version to 4.3.0~dev5
 
- -- Daniel-Constantin Mierla <miconda at gmail.com>  Tue, 11 Nov 2014 11:55:40 +0100
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Thu, 12 Mar 2015 15:20:01 +0100
 
-kamailio (4.2.0) unstable; urgency=medium
+kamailio (4.3.0~dev4) unstable; urgency=medium
 
-  * update versionto 4.2.0
+  * update version to 4.3.0~dev4
 
- -- Daniel-Constantin Mierla <miconda at gmail.com>  Thu, 16 Oct 2014 14:25:30 +0100
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Sat, 07 Feb 2015 09:53:08 +0100
 
-kamailio (4.2.0~rc1) unstable; urgency=medium
+kamailio (4.3.0~dev3) unstable; urgency=medium
 
-  * update version to 4.2.0~rc1
+  * update version to 4.3.0~dev3
 
- -- Victor Seva <linuxmaniac at torreviejawireless.org>  Mon, 13 Oct 2014 23:39:26 +0200
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Sat, 03 Jan 2015 23:21:53 +0100
 
-kamailio (4.2.0~rc0) unstable; urgency=medium
+kamailio (4.3.0~dev1) unstable; urgency=medium
 
-  * update version to 4.2.0~rc0
+  * update version to 4.3.0~dev1
 
- -- Victor Seva <linuxmaniac at torreviejawireless.org>  Thu, 09 Oct 2014 09:55:52 +0200
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Mon, 13 Oct 2014 14:33:16 +0200
+
+kamailio (4.3.0~dev0) unstable; urgency=medium
+
+  * update version to 4.3.0~dev0
+
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Thu, 09 Oct 2014 09:49:13 +0200
 
 kamailio (4.2.0~pre1) UNRELEASED; urgency=medium
 
diff --git a/pkg/kamailio/deb/trusty/control b/pkg/kamailio/deb/trusty/control
index b992303..940afbe 100644
--- a/pkg/kamailio/deb/trusty/control
+++ b/pkg/kamailio/deb/trusty/control
@@ -19,6 +19,7 @@ Build-Depends: bison,
                libfreeradius-client-dev,
                libgeoip-dev (>= 1.4.5),
                libhiredis-dev (>= 0.10.0),
+               libjansson-dev,
                libjson-c-dev,
                libldap2-dev,
                liblua5.1-0-dev,
@@ -606,6 +607,20 @@ Description: kazoo modules for Kamailio
  .
  This package provides the kazoo module for Kamailio.
 
+Package: kamailio-cnxcc-modules
+Architecture: linux-any
+Multi-Arch: same
+Pre-Depends: ${misc:Pre-Depends}
+Depends: kamailio (= ${binary:Version}),
+         ${misc:Depends},
+         ${shlibs:Depends}
+Description: cnxcc modules for Kamailio
+ Kamailio is a very fast and flexible SIP (RFC3261)
+ proxy server. Written entirely in C, Kamailio can handle thousands calls
+ per second even on low-budget hardware.
+ .
+ This package provides the cnxcc module for Kamailio.
+
 Package: kamailio-extra-modules
 Architecture: linux-any
 Multi-Arch: same
@@ -618,7 +633,7 @@ Description: extra modules for Kamailio
  proxy server. Written entirely in C, Kamailio can handle thousands calls
  per second even on low-budget hardware.
  .
- This package provides: gzcompress uuid ev
+ This package provides: gzcompress uuid ev jansson
 
 Package: kamailio-nth
 Architecture: any
diff --git a/pkg/kamailio/deb/trusty/rules b/pkg/kamailio/deb/trusty/rules
index 8cbe6bb..fb20807 100755
--- a/pkg/kamailio/deb/trusty/rules
+++ b/pkg/kamailio/deb/trusty/rules
@@ -39,10 +39,10 @@ PACKAGE_GROUPS=mysql postgres berkeley unixodbc radius presence \
 			   ldap xml perl utils lua memcached \
 			   snmpstats carrierroute xmpp cpl redis python geoip\
 			   sqlite json mono ims sctp java \
-			   purple tls outbound websocket autheph dnssec kazoo
+			   purple tls outbound websocket autheph dnssec kazoo cnxcc
 
 # module groups to be packaged onto kamailio-extra-modules
-EXTRA_GROUPS=gzcompress uuid ev
+EXTRA_GROUPS=gzcompress uuid ev jansson
 
 # name of libdir in the path for libraries (e.g., lib for 32b, lib64 for 64b)
 LIBDIR ?= lib/$(DEB_HOST_MULTIARCH)
@@ -67,7 +67,7 @@ endef
 define PACKAGE_GRP_INSTALL_template
 	$(foreach grp,$(PACKAGE_GROUPS),\
 		$(MAKE) install-modules-all LIBDIR=$(LIBDIR) group_include="k$(grp)" \
-		basedir=$(CURDIR)/debian/kamailio-$(grp)-modules \
+		BASEDIR=$(CURDIR)/debian/kamailio-$(grp)-modules \
 		cfg_prefix=$(CURDIR)/debian/kamailio-$(grp)-modules \
 		doc-dir=share/doc/kamailio-$(grp)-modules
 		# eliminate duplicate libs
@@ -85,7 +85,7 @@ endef
 define PACKAGE_EXTRA_INSTALL_template
 	$(foreach grp,$(EXTRA_GROUPS),\
 		$(MAKE) install-modules-all LIBDIR=$(LIBDIR) group_include="k$(grp)" \
-		basedir=$(CURDIR)/debian/kamailio-extra-modules \
+		BASEDIR=$(CURDIR)/debian/kamailio-extra-modules \
 		cfg_prefix=$(CURDIR)/debian/kamailio-extra-modules \
 		doc-dir=share/doc/kamailio-extra-modules
 	)
@@ -100,17 +100,15 @@ define PACKAGE_EXTRA_INSTALL_template
 	find $(CURDIR)/debian/kamailio-extra-modules -depth -empty -type d -exec rmdir {} \;
 endef
 
-ifneq (,$(findstring debug,$(DEB_BUILD_OPTIONS)))
-	CFLAGS += -g
-endif
-ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
-	INSTALL_PROGRAM += -s
-endif
-
 # CFLAGS + CPPFLAGS -> CC_EXTRA_OPTS
+CC_EXTRA_OPTS := $(shell dpkg-buildflags --get CPPFLAGS)
+CC_EXTRA_OPTS += $(shell dpkg-buildflags --get CFLAGS)
+CXXFLAGS := $(shell dpkg-buildflags --get CXXFLAGS)
 # LDFLAGS -> LD_EXTRA_OPTS
-CUSTOM_BUILDFLAGS:=$(shell dpkg-buildflags --export=configure| \
-sed -e 's/" CPPFLAGS="/ /' -e 's/CFLAGS/CC_EXTRA_OPTS/g' -e 's/LDFLAGS/LD_EXTRA_OPTS/g')
+LD_EXTRA_OPTS := $(shell dpkg-buildflags --get LDFLAGS)
+
+# https://wiki.debian.org/ReproducibleBuilds/
+CC_EXTRA_OPTS += -DVERSION_NODATE
 
 configure: configure-stamp
 configure-stamp:
@@ -118,9 +116,10 @@ configure-stamp:
 	# Add here commands to configure the package.
 	$(MAKE) FLAVOUR=kamailio cfg prefix=/usr cfg_prefix=$(CURDIR)/debian/kamailio \
 			cfg_target=/etc/kamailio/ \
-			basedir=$(CURDIR)/debian/kamailio \
+			BASEDIR=$(CURDIR)/debian/kamailio \
 			skip_modules="$(EXCLUDED_MODULES) $(EXTRA_EXCLUDED_MODULES)" \
-			$(CUSTOM_BUILDFLAGS) \
+			CC_EXTRA_OPTS="$(CC_EXTRA_OPTS)" \
+			LD_EXTRA_OPTS="$(LD_EXTRA_OPTS)" \
 			group_include="kstandard"
 
 	touch configure-stamp
@@ -160,6 +159,8 @@ install: build
 	# install /etc/default/kamailio file
 	mkdir -p $(CURDIR)/debian/kamailio/etc/default
 	cp -f debian/kamailio.default $(CURDIR)/debian/kamailio/etc/default/kamailio
+	# delete /var/run/kamailio dir
+	rm -rf $(CURDIR)/debian/kamailio/usr/local
 
 
 # This single target is used to build all the packages, all at once, or
@@ -171,7 +172,7 @@ binary-common:
 	dh_testroot
 	dh_installdebconf
 	dh_installdocs
-	dh_installexamples
+	dh_installexamples -Xobsoleted -Xsr
 	dh_installmenu
 	dh_installinit -pkamailio -- defaults 23
 	dh_installcron
diff --git a/pkg/kamailio/deb/wheezy/changelog b/pkg/kamailio/deb/wheezy/changelog
index 7d568dc..3a1bbe4 100644
--- a/pkg/kamailio/deb/wheezy/changelog
+++ b/pkg/kamailio/deb/wheezy/changelog
@@ -1,50 +1,56 @@
-kamailio (4.2.5) unstable; urgency=medium
+kamailio (4.3.0~rc0) unstable; urgency=medium
 
-  * update versionto 4.2.5
+  * update version to 4.3.0~rc0
 
- -- Daniel-Constantin Mierla <miconda at gmail.com>  Tue, 19 May 2015 12:10:55 +0100
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Tue, 26 May 2015 20:55:14 +0200
 
-kamailio (4.2.4) unstable; urgency=medium
+kamailio (4.3.0~pre2) unstable; urgency=medium
 
-  * update versionto 4.2.4
+  * update version to 4.3.0~pre2
 
- -- Daniel-Constantin Mierla <miconda at gmail.com>  Thu, 02 Apr 2015 14:20:05 +0100
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Mon, 18 May 2015 11:18:45 +0200
 
-kamailio (4.2.3) unstable; urgency=medium
+kamailio (4.3.0~pre1) unstable; urgency=medium
 
-  * update versionto 4.2.3
+  * update version to 4.3.0~pre1
 
- -- Daniel-Constantin Mierla <miconda at gmail.com>  Tue, 10 Feb 2015 15:30:45 +0100
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Tue, 05 May 2015 10:52:12 +0200
 
-kamailio (4.2.2) unstable; urgency=medium
+kamailio (4.3.0~pre0) unstable; urgency=medium
 
-  * update versionto 4.2.2
+  * update version to 4.3.0~pre0
 
- -- Daniel-Constantin Mierla <miconda at gmail.com>  Thu, 08 Jan 2015 14:25:40 +0100
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Thu, 23 Apr 2015 09:58:06 +0200
 
-kamailio (4.2.1) unstable; urgency=medium
+kamailio (4.3.0~dev5) unstable; urgency=medium
 
-  * update versionto 4.2.1
+  * update version to 4.3.0~dev5
 
- -- Daniel-Constantin Mierla <miconda at gmail.com>  Tue, 11 Nov 2014 11:55:40 +0100
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Thu, 12 Mar 2015 15:20:01 +0100
 
-kamailio (4.2.0) unstable; urgency=medium
+kamailio (4.3.0~dev4) unstable; urgency=medium
 
-  * update versionto 4.2.0
+  * update version to 4.3.0~dev4
 
- -- Daniel-Constantin Mierla <miconda at gmail.com>  Thu, 16 Oct 2014 14:25:30 +0100
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Sat, 07 Feb 2015 09:53:08 +0100
 
-kamailio (4.2.0~rc1) unstable; urgency=medium
+kamailio (4.3.0~dev3) unstable; urgency=medium
 
-  * update version to 4.2.0~rc1
+  * update version to 4.3.0~dev3
 
- -- Victor Seva <linuxmaniac at torreviejawireless.org>  Mon, 13 Oct 2014 23:39:26 +0200
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Sat, 03 Jan 2015 23:21:53 +0100
 
-kamailio (4.2.0~rc0) unstable; urgency=medium
+kamailio (4.3.0~dev1) unstable; urgency=medium
 
-  * update version to 4.2.0~rc0
+  * update version to 4.3.0~dev1
 
- -- Victor Seva <linuxmaniac at torreviejawireless.org>  Thu, 09 Oct 2014 09:55:52 +0200
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Mon, 13 Oct 2014 14:33:16 +0200
+
+kamailio (4.3.0~dev0) unstable; urgency=medium
+
+  * update version to 4.3.0~dev0
+
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Thu, 09 Oct 2014 09:49:13 +0200
 
 kamailio (4.2.0~pre1) UNRELEASED; urgency=medium
 
diff --git a/pkg/kamailio/deb/wheezy/control b/pkg/kamailio/deb/wheezy/control
index 16d1f8d..26181d5 100644
--- a/pkg/kamailio/deb/wheezy/control
+++ b/pkg/kamailio/deb/wheezy/control
@@ -19,6 +19,7 @@ Build-Depends: bison,
                libradiusclient-ng-dev,
                libgeoip-dev (>= 1.4.5),
                libhiredis-dev (>= 0.10.0),
+               libjansson-dev,
                libjson0-dev,
                libldap2-dev,
                liblua5.1-0-dev,
@@ -572,7 +573,7 @@ Description: extra modules for Kamailio
  proxy server. Written entirely in C, Kamailio can handle thousands calls
  per second even on low-budget hardware.
  .
- This package provides: gzcompress uuid ev
+ This package provides: gzcompress uuid ev jansson
 
 Package: kamailio-nth
 Architecture: any
diff --git a/pkg/kamailio/deb/wheezy/rules b/pkg/kamailio/deb/wheezy/rules
index 22cd9e2..11a2b4e 100755
--- a/pkg/kamailio/deb/wheezy/rules
+++ b/pkg/kamailio/deb/wheezy/rules
@@ -28,7 +28,7 @@ EXCLUDED_MODULES=
 # extra modules to skip, because they are not compilable now
 # - regardless if they go to the main kamailio package or to some module package,
 # they will be excluded from compile and install of all
-EXTRA_EXCLUDED_MODULES=bdb dbtext oracle pa iptrtpproxy purple mi_xmlrpc dnssec kazoo
+EXTRA_EXCLUDED_MODULES=bdb dbtext oracle pa iptrtpproxy purple mi_xmlrpc dnssec kazoo cnxcc
 
 # module groups that are packaged in seperate packages
 # (with the name kamailio-$(group_name)-modules)
@@ -41,7 +41,7 @@ PACKAGE_GROUPS=mysql postgres berkeley unixodbc radius presence \
 			   tls outbound websocket autheph 
 
 # module groups to be packaged onto kamailio-extra-modules
-EXTRA_GROUPS=gzcompress uuid ev
+EXTRA_GROUPS=gzcompress uuid ev jansson
 
 # name of libdir in the path for libraries (e.g., lib for 32b, lib64 for 64b)
 LIBDIR ?= lib/$(DEB_HOST_MULTIARCH)
@@ -66,7 +66,7 @@ endef
 define PACKAGE_GRP_INSTALL_template
 	$(foreach grp,$(PACKAGE_GROUPS),\
 		$(MAKE) install-modules-all LIBDIR=$(LIBDIR) group_include="k$(grp)" \
-		basedir=$(CURDIR)/debian/kamailio-$(grp)-modules \
+		BASEDIR=$(CURDIR)/debian/kamailio-$(grp)-modules \
 		cfg_prefix=$(CURDIR)/debian/kamailio-$(grp)-modules \
 		doc-dir=share/doc/kamailio-$(grp)-modules
 		# eliminate duplicate libs
@@ -84,7 +84,7 @@ endef
 define PACKAGE_EXTRA_INSTALL_template
 	$(foreach grp,$(EXTRA_GROUPS),\
 		$(MAKE) install-modules-all LIBDIR=$(LIBDIR) group_include="k$(grp)" \
-		basedir=$(CURDIR)/debian/kamailio-extra-modules \
+		BASEDIR=$(CURDIR)/debian/kamailio-extra-modules \
 		cfg_prefix=$(CURDIR)/debian/kamailio-extra-modules \
 		doc-dir=share/doc/kamailio-extra-modules
 	)
@@ -99,17 +99,15 @@ define PACKAGE_EXTRA_INSTALL_template
 	find $(CURDIR)/debian/kamailio-extra-modules -depth -empty -type d -exec rmdir {} \;
 endef
 
-ifneq (,$(findstring debug,$(DEB_BUILD_OPTIONS)))
-	CFLAGS += -g
-endif
-ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
-	INSTALL_PROGRAM += -s
-endif
-
 # CFLAGS + CPPFLAGS -> CC_EXTRA_OPTS
+CC_EXTRA_OPTS := $(shell dpkg-buildflags --get CPPFLAGS)
+CC_EXTRA_OPTS += $(shell dpkg-buildflags --get CFLAGS)
+CXXFLAGS := $(shell dpkg-buildflags --get CXXFLAGS)
 # LDFLAGS -> LD_EXTRA_OPTS
-CUSTOM_BUILDFLAGS:=$(shell dpkg-buildflags --export=configure| \
-sed -e 's/" CPPFLAGS="/ /' -e 's/CFLAGS/CC_EXTRA_OPTS/g' -e 's/LDFLAGS/LD_EXTRA_OPTS/g')
+LD_EXTRA_OPTS := $(shell dpkg-buildflags --get LDFLAGS)
+
+# https://wiki.debian.org/ReproducibleBuilds/
+CC_EXTRA_OPTS += -DVERSION_NODATE
 
 configure: configure-stamp
 configure-stamp:
@@ -117,9 +115,10 @@ configure-stamp:
 	# Add here commands to configure the package.
 	$(MAKE) FLAVOUR=kamailio cfg prefix=/usr cfg_prefix=$(CURDIR)/debian/kamailio \
 			cfg_target=/etc/kamailio/ \
-			basedir=$(CURDIR)/debian/kamailio \
+			BASEDIR=$(CURDIR)/debian/kamailio \
 			skip_modules="$(EXCLUDED_MODULES) $(EXTRA_EXCLUDED_MODULES)" \
-			$(CUSTOM_BUILDFLAGS) \
+			CC_EXTRA_OPTS="$(CC_EXTRA_OPTS)" \
+			LD_EXTRA_OPTS="$(LD_EXTRA_OPTS)" \
 			group_include="kstandard"
 
 	touch configure-stamp
@@ -159,6 +158,8 @@ install: build
 	# install /etc/default/kamailio file
 	mkdir -p $(CURDIR)/debian/kamailio/etc/default
 	cp -f debian/kamailio.default $(CURDIR)/debian/kamailio/etc/default/kamailio
+	# delete /var/run/kamailio dir
+	rm -rf $(CURDIR)/debian/kamailio/usr/local
 
 
 # This single target is used to build all the packages, all at once, or
@@ -170,7 +171,7 @@ binary-common:
 	dh_testroot
 	dh_installdebconf
 	dh_installdocs
-	dh_installexamples
+	dh_installexamples -Xobsoleted -Xsr
 	dh_installmenu
 	dh_installinit -pkamailio -- defaults 23
 	dh_installcron
diff --git a/pkg/kamailio/fedora/17/kamailio.spec b/pkg/kamailio/fedora/17/kamailio.spec
index 63ec0af..2ceb8ea 100644
--- a/pkg/kamailio/fedora/17/kamailio.spec
+++ b/pkg/kamailio/fedora/17/kamailio.spec
@@ -1,6 +1,6 @@
 %define name	kamailio
-%define ver	4.2.5
-%define rel	0%{dist}
+%define ver	4.1.0
+%define rel	dev7.2%{dist}
 
 
 
diff --git a/pkg/kamailio/rpm/kamailio.spec-4.1 b/pkg/kamailio/rpm/kamailio.spec-4.1
index 8cd9e02..12b02f0 100644
--- a/pkg/kamailio/rpm/kamailio.spec-4.1
+++ b/pkg/kamailio/rpm/kamailio.spec-4.1
@@ -1,5 +1,5 @@
 %define name    kamailio
-%define ver     4.2.5
+%define ver     1.2.0
 %define rel     0
 
 %define EXCLUDED_MODULES	mysql jabber cpl-c avp_radius auth_radius group_radius uri_radius pa postgres osp tlsops unixodbc
diff --git a/pkg/kamailio/rpm/kamailio.spec.CenOS b/pkg/kamailio/rpm/kamailio.spec.CenOS
index e8186bf..6b396c7 100644
--- a/pkg/kamailio/rpm/kamailio.spec.CenOS
+++ b/pkg/kamailio/rpm/kamailio.spec.CenOS
@@ -1,5 +1,5 @@
 %define name    kamailio
-%define ver     4.2.5
+%define ver     3.2.0
 %define rel     0
 %define _sharedir %{_prefix}/share
 
diff --git a/pkg/kamailio/rpm/kamailio.spec.SuSE b/pkg/kamailio/rpm/kamailio.spec.SuSE
index 3b4b1d6..77af948 100644
--- a/pkg/kamailio/rpm/kamailio.spec.SuSE
+++ b/pkg/kamailio/rpm/kamailio.spec.SuSE
@@ -1,5 +1,5 @@
 %define name    kamailio
-%define ver     4.2.5
+%define ver     1.2.0
 %define rel     0
 
 %define EXCLUDED_MODULES	mysql jabber cpl-c auth_radius misc_radius peering postgress pa unixodbc osp tlsops
diff --git a/poll_types.h b/poll_types.h
index 7440c88..fd6767f 100644
--- a/poll_types.h
+++ b/poll_types.h
@@ -1,21 +1,14 @@
 /* 
- * $Id$
- * 
  * Copyright (C) 2005 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,18 +17,14 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/* 
- * io wait poll methods (enum, strings, related function)
- * see io_wait.h for more details
- * 
- *  
+/*!
+ * \file
+ * \brief Kamailio core :: I/O wait poll methods (enum, strings, related function)
+ * see \ref io_wait.h for more details
+ * \ingroup core
+ * \author andrei
+ * Module: \ref core
  */
-/* 
- * History:
- * --------
- *  2005-06-15  created by andrei
- */
-
 
 #ifndef _poll_types_h
 #define _poll_types_h
diff --git a/ppcfg.c b/ppcfg.c
index 63549ac..5d98fc0 100644
--- a/ppcfg.c
+++ b/ppcfg.c
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- * 
  * Copyright (C) 2010 Daniel-Constantin Mierla (asipto.com)
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -15,8 +13,12 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/*
- * ppcfg.c - config preprocessor directives
+
+/*!
+ * \file
+ * \brief Kamailio core :: ppcfg.c - config preprocessor directives
+ * \ingroup core
+ * Module: \ref core
  */
 
 #include <stdio.h>
diff --git a/ppcfg.h b/ppcfg.h
index d940f86..69f41d2 100644
--- a/ppcfg.h
+++ b/ppcfg.h
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- * 
  * Copyright (C) 2010 Daniel-Constantin Mierla (asipto.com)
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -15,8 +13,11 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/*
- * ppcfg.h - config preprocessor directives
+/*!
+ * \file
+ * \brief Kamailio core :: Config preprocessor directives
+ * \ingroup core
+ * Module: \ref core
  */
 
 #ifndef _PPCFG_H_
diff --git a/proxy.c b/proxy.c
index 98343c8..589d1ad 100644
--- a/proxy.c
+++ b/proxy.c
@@ -1,24 +1,17 @@
 /*
- * $Id$
- *
  * proxy list & assoc. functions
  *
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -27,16 +20,10 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
- /*
-  * History:
-  * -------
-  *  2003-02-13  all *proxy functions are now proto aware (andrei)
-  *  2003-03-19  replaced all mallocs/frees w/ pkg_malloc/pkg_free (andrei)
-  */
 
 /*!
  * \file
- * \brief SIP-router core :: 
+ * \brief Kamailio core :: proxy list & assoc. functions
  * \ingroup core
  * Module: \ref core
  */
@@ -241,19 +228,19 @@ error:
 		p=(struct proxy_l*) p_malloc(sizeof(struct proxy_l));			\
 		if (p==0){														\
 			ser_error=E_OUT_OF_MEM;										\
-			LM_ERR("memory allocation failure\n");		\
+			LM_ERR("memory allocation failure\n");						\
 			goto error;													\
 		}																\
 		memset(p,0,sizeof(struct proxy_l));								\
 		p->name=*name;													\
 		p->port=port;													\
 																		\
-		DBG("DEBUG: mk_proxy: doing DNS lookup...\n");					\
+		LM_DBG("doing DNS lookup...\n");								\
 		proto=protocol;													\
 		he=sip_resolvehost(name, &(p->port), &proto);					\
 		if (he==0){														\
 			ser_error=E_BAD_ADDRESS;									\
-			LM_CRIT("could not resolve hostname:"	\
+			LM_CRIT("could not resolve hostname:"						\
 				" \"%.*s\"\n", name->len, name->s);						\
 			p_free(p);													\
 			goto error;													\
diff --git a/proxy.h b/proxy.h
index 59f3a3e..e087240 100644
--- a/proxy.h
+++ b/proxy.h
@@ -1,22 +1,14 @@
 /*
- * $Id$
- *
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -25,12 +17,13 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
- /*
-  * History:
-  * -------
-  *  2003-02-13  added proto to struct proxy_l & to *_proxy functions (andrei)
-  */
-
+/*!
+ * \file
+ * \brief Kamailio core :: Proxy 
+ * \ingroup core
+ * \author andrei
+ * Module: \ref core
+ */
 
 #ifndef proxy_h
 #define proxy_h
@@ -70,7 +63,7 @@ void free_shm_proxy(struct proxy_l* p);
 
 
 
-/* returns 0 on success, -1 on error (unknown af/bug) */
+/** returns 0 on success, -1 on error (unknown af/bug) */
 inline static int proxy2su(union sockaddr_union* su, struct proxy_l* p)
 {
 	/* if error try next ip address if possible */
@@ -87,7 +80,7 @@ inline static int proxy2su(union sockaddr_union* su, struct proxy_l* p)
 
 
 
-/* mark as proxy either as ok (err>=0) or as bad (err<0) */
+/** mark proxy either as ok (err>=0) or as bad (err<0) */
 inline static void proxy_mark(struct proxy_l* p, int err)
 {
 	if (err<0){
diff --git a/pt.c b/pt.c
index bec1c4e..2c65250 100644
--- a/pt.c
+++ b/pt.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Process Table
  *
  * Copyright (C) 2001-2003 FhG Fokus
@@ -17,17 +15,7 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/*
- * History:
- * --------
- *  2006-06-14	added process table in shared mem (dragos)
- *  2006-09-20	added profile support (-DPROFILING) (hscholz)
- *  2006-10-25	sanity check before allowing forking w/ tcp support (is_main
- *               & tcp not started yet); set is_main=0 in childs (andrei)
- *  2007-07-04	added register_fds() and get_max_open_fds(() (andrei)
- *  2010-08-19	use daemon_status_on_fork_cleanup() (andrei)
- */
-/** internal fork functions and process table.
+/** Kamailio Core :: internal fork functions and process table.
  * @file: pt.c
  * @ingroup core
  */
diff --git a/pt.h b/pt.h
index b52be56..ed351a7 100644
--- a/pt.h
+++ b/pt.h
@@ -1,10 +1,6 @@
 /*
- * $Id$
- *
  * Process Table
  *
- *
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -19,19 +15,11 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/*
- * History:
- * --------
- *  2003-04-15  added tcp_disable support (andrei)
- *  2006-06-14	added process table in shared mem (dragos)
- *  2007-07-04	added register_fds() and get_max_open_fds(() (andrei)
- */
-/** internal fork functions and process table.
+/** Kamailio core :: internal fork functions and process table.
  * @file: pt.h
  * @ingroup core
  */
 
-
 #ifndef _PT_H
 #define _PT_H
 
diff --git a/pv_core.c b/pv_core.c
index 80020ab..c50de35 100644
--- a/pv_core.c
+++ b/pv_core.c
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- * 
  * Copyright (C) 2009 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -15,16 +13,13 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/*
- * pv_core.c - pvars needed in the core, e.g. $?, $retcode
- *
- * Note: in general please avoid adding pvars directly to the core, unless
- * absolutely necessary (use/create a new module instead).
- */
 
 /*!
  * \file
- * \brief SIP-router core :: 
+ * \brief Kamailio core ::  pv_core.c - pvars needed in the core, e.g. $?, $retcode
+ *
+ * \note Note: in general please avoid adding pvars directly to the core, unless
+ * absolutely necessary (use/create a new module instead).
  * \ingroup core
  * Module: \ref core
  */
@@ -45,7 +40,7 @@ static pv_export_t core_pvs[] = {
 };
 
 
-/* ugly hack to get the return code, needed because the PVs do not know (yet)
+/** ugly hack to get the return code, needed because the PVs do not know (yet)
    about the script context */
 extern int _last_returned_code;
 
diff --git a/pv_core.h b/pv_core.h
index e98480b..5f80556 100644
--- a/pv_core.h
+++ b/pv_core.h
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- * 
  * Copyright (C) 2009 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -15,9 +13,12 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/*
- * pv_core.h
- */
+/*!
+* \file
+* \brief Kamailio core :: Pseudovariable handling core
+* \ingroup core
+* Module: \ref core
+*/
 
 #ifndef __pv_core_h
 #define __pv_core_h
diff --git a/pvapi.c b/pvapi.c
index 981d85c..d60aebc 100644
--- a/pvapi.c
+++ b/pvapi.c
@@ -1,14 +1,14 @@
 /*
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of SIP-Router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-Router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-Router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -20,7 +20,7 @@
 
 /*!
  * \file
- * \brief SIP-router core :: PV API specification
+ * \brief Kamailio core :: PV API specification
  * \ingroup core
  * Module: \ref core
  */
@@ -539,6 +539,21 @@ int pv_get_strzval(struct sip_msg *msg, pv_param_t *param,
 }
 
 /**
+ * convert char* with len to pv_value_t
+ */
+int pv_get_strlval(struct sip_msg *msg, pv_param_t *param,
+		pv_value_t *res, char *sval, int slen)
+{
+	if(res==NULL)
+		return -1;
+
+	res->rs.s = sval;
+	res->rs.len = slen;
+	res->flags = PV_VAL_STR;
+	return 0;
+}
+
+/**
  * convert str-int to pv_value_t (type is str)
  */
 int pv_get_strintval(struct sip_msg *msg, pv_param_t *param,
@@ -667,6 +682,11 @@ int pv_parse_index(pv_spec_p sp, str *in)
 		sp->pvp.pvi.type = PV_IDX_ALL;
 		return 0;
 	}
+	if(*p=='+' && in->len==1)
+	{
+		sp->pvp.pvi.type = PV_IDX_ITR;
+		return 0;
+	}
 	sign = 1;
 	if(*p=='-')
 	{
@@ -1225,7 +1245,10 @@ int pv_get_spec_index(struct sip_msg* msg, pv_param_p ip, int *idx, int *flags)
 		*flags = PV_IDX_ALL;
 		return 0;
 	}
-	
+	if(ip->pvi.type == PV_IDX_ITR) {
+		*flags = PV_IDX_ITR;
+		return 0;
+	}
 	if(ip->pvi.type == PV_IDX_INT)
 	{
 		*idx = ip->pvi.u.ival;
diff --git a/pvapi.h b/pvapi.h
index 855e92b..1f2366e 100644
--- a/pvapi.h
+++ b/pvapi.h
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- * 
  * Copyright (C) 2009 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -15,8 +13,11 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/*
- * pvapi.h - pvapi init and destroy functions.
+/*!
+ * \file
+ * \brief Kamailio core :: pvapi init and destroy functions.
+ * \ingroup core
+ * Module: \ref core
  */
 
 #ifndef __pvapi_h__
diff --git a/pvar.h b/pvar.h
index 4aa04dc..3bdfe17 100644
--- a/pvar.h
+++ b/pvar.h
@@ -1,16 +1,14 @@
 /*
- * $Id: items.h 2111 2007-05-01 11:18:08Z juhe $
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of SIP-Router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-Router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-Router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -22,7 +20,7 @@
 
 /*!
  * \file
- * \brief Definitions for Pseudo-variable support
+ * \brief Kamailio core :: Definitions for Pseudo-variable support
  */
 
 
@@ -62,6 +60,7 @@
 #define PV_IDX_INT	0
 #define PV_IDX_PVAR	1
 #define PV_IDX_ALL	2
+#define PV_IDX_ITR	3
 
 /*! if PV name is dynamic, integer, or str */
 #define pv_has_dname(pv) ((pv)->pvp.pvn.type==PV_NAME_PVAR)
@@ -220,6 +219,8 @@ int pv_get_strval(struct sip_msg *msg, pv_param_t *param,
 		pv_value_t *res, str *sval);
 int pv_get_strzval(struct sip_msg *msg, pv_param_t *param,
 		pv_value_t *res, char *sval);
+int pv_get_strlval(struct sip_msg *msg, pv_param_t *param,
+		pv_value_t *res, char *sval, int slen);
 int pv_get_strintval(struct sip_msg *msg, pv_param_t *param,
 		pv_value_t *res, str *sval, int ival);
 int pv_get_intstrval(struct sip_msg *msg, pv_param_t *param,
diff --git a/qvalue.c b/qvalue.c
index 25460ac..e1dd5f9 100644
--- a/qvalue.c
+++ b/qvalue.c
@@ -1,23 +1,16 @@
 /*
- * $Id$
- *
  * Handling of the q value
  *
  * Copyright (C) 2004 FhG FOKUS
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -26,14 +19,11 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History
- * ------
- * 2004-04-25 created (janakj)
  */
 
 /*!
  * \file
- * \brief SIP-router core ::  Handling of the q value
+ * \brief Kamailio core ::  Handling of the q value
  * \ingroup core
  * Module: \ref core
  */
diff --git a/qvalue.h b/qvalue.h
index 231416d..4e2444b 100644
--- a/qvalue.h
+++ b/qvalue.h
@@ -1,23 +1,16 @@
 /*
- * $Id$
- *
  * Handling of the q value
  *
  * Copyright (C) 2004 FhG FOKUS
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -26,9 +19,13 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History
- * ------
- * 2004-04-25 created (janakj)
+ */
+/*!
+ * \file
+ * \brief Kamailio core :: Handling of the Q value
+ * \author janakj
+ * \ingroup core
+ * Module: \ref core
  */
 
 #ifndef _QVALUE_H
diff --git a/rad_dict.h b/rad_dict.h
index 5354ca9..3f0c260 100644
--- a/rad_dict.h
+++ b/rad_dict.h
@@ -3,19 +3,14 @@
  *
  * Copyright (C) 2001-2003 FhG FOKUS
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,9 +19,13 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-
-/*
- * WARNING: Don't forget to update sip_router/etc/dictionary.sip-router if you 
+/*!
+ * \file
+ * \brief Kamailio core :: Radius include file
+ * \ingroup core
+ * Module: \ref core
+ *
+ * \note WARNING: Don't forget to update sip_router/etc/dictionary.sip-router if you 
  * update this file !
  */
 
diff --git a/rand/fastrand.c b/rand/fastrand.c
index 94bd3c7..757e08d 100644
--- a/rand/fastrand.c
+++ b/rand/fastrand.c
@@ -1,8 +1,6 @@
 /*
  * fast pseudo random generation 
  *
- * $Id$
- *
  * Copyright (C) 2007 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
diff --git a/rand/fastrand.h b/rand/fastrand.h
index ab4fb74..c97232e 100644
--- a/rand/fastrand.h
+++ b/rand/fastrand.h
@@ -1,8 +1,6 @@
 /*
  * fast pseudo random generation 
  *
- * $Id$
- *
  * Copyright (C) 2007 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -16,10 +14,7 @@
  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-/*
- *History:
- *--------
+ *
  *  2007-06-15  wrapper around isaac (see 
  *              http://www.burtleburtle.net/bob/rand/isaacafa.html) (andrei)
  */
diff --git a/raw_listener.c b/raw_listener.c
index 5ff9e31..ab096f3 100644
--- a/raw_listener.c
+++ b/raw_listener.c
@@ -13,16 +13,12 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/** raw socket udp listen functions.
+
+/** Kamailio core :: raw socket udp listen functions.
  *  @file raw_listener.c
  *  @ingroup core
  *  Module: @ref core
  */
-/*
- * History:
- * --------
- *  2010-06-09  intial version (from older code) andrei
- */
 
 #ifdef USE_RAW_SOCKS
 
@@ -101,13 +97,13 @@ int raw_udp4_rcv_loop(int rsock, int port1, int port2)
 		len=raw_udp4_recv(rsock, &p, BUF_SIZE, &from, &to, &rf);
 		if (len<0){
 			if (len==-1){
-				LM_ERR("raw_udp4_recv: %s [%d]\n", strerror(errno), errno);
+				LM_ERR("%s [%d]\n", strerror(errno), errno);
 				if ((errno==EINTR)||(errno==EWOULDBLOCK))
 					continue;
 				else
 					goto error;
 			}else{
-				DBG("raw_udp4_rcv_loop: raw_udp4_recv error: %d\n", len);
+				LM_DBG("error len: %d\n", len);
 				continue;
 			}
 		}
@@ -121,7 +117,7 @@ int raw_udp4_rcv_loop(int rsock, int port1, int port2)
 		/* sanity checks */
 		if (len<MIN_UDP_PACKET){
 			tmp=ip_addr2a(&ri.src_ip);
-			DBG("raw_udp4_rcv_loop: probing packet received from %s %d\n",
+			LM_DBG("probing packet received from %s %d\n",
 					tmp, htons(ri.src_port));
 			continue;
 		}
@@ -131,7 +127,7 @@ int raw_udp4_rcv_loop(int rsock, int port1, int port2)
 			continue;
 		}
 		tmp=ip_addr2a(&ri.src_ip);
-		DBG("raw_udp4_rcv_loop: received from %s:\n[%.*s]\n", tmp, len, p);
+		LM_DBG("received from %s:\n[%.*s]\n", tmp, len, p);
 		receive_msg(p, len, &ri);
 	}
 error:
diff --git a/raw_listener.h b/raw_listener.h
index 3ac7d84..a171070 100644
--- a/raw_listener.h
+++ b/raw_listener.h
@@ -13,16 +13,12 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/** raw socket udp listen functions.
+/** Kamailio core :: raw socket udp listen functions.
  *  @file raw_listener.h
  *  @ingroup core
+ *  @author andrei
  *  Module: @ref core
  */
-/*
- * History:
- * --------
- *  2010-06-09  initial version (from older code) andrei
- */
 
 #ifndef _raw_listener_h
 #define _raw_listener_h
diff --git a/raw_sock.c b/raw_sock.c
index 1d18e5a..397f3fb 100644
--- a/raw_sock.c
+++ b/raw_sock.c
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- *
  * Copyright (C) 2010 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -15,18 +13,12 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/** raw socket functions.
+
+/** Kamailio core :: raw socket functions.
  *  @file raw_sock.c
  *  @ingroup core
  *  Module: @ref core
  */
-/* 
- * History:
- * --------
- *  2010-06-07  initial version (from older code) andrei
- *  2010-06-15  IP_HDRINCL raw socket support, including on-send
- *               fragmentation (andrei)
- */
 
 #ifdef USE_RAW_SOCKS
 
diff --git a/raw_sock.h b/raw_sock.h
index 868399f..fbb21bf 100644
--- a/raw_sock.h
+++ b/raw_sock.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2010 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -15,16 +13,13 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/** raw socket functions.
+
+/** Kamailio core :: raw socket functions.
  *  @file raw_sock.c
  *  @ingroup core
+ *  @author andrei
  *  Module: @ref core
  */
-/* 
- * History:
- * --------
- *  2010-06-07  initial version (from older code) andrei
- */
 
 #ifndef _raw_sock_h
 #define _raw_sock_h
diff --git a/re.c b/re.c
index e1fe37d..81583b4 100644
--- a/re.c
+++ b/re.c
@@ -1,23 +1,16 @@
 /* 
- * $Id$
- *
  * regexp and regexp substitutions implementations
  * 
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -26,16 +19,11 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- *
- * History:
- * --------
- *   2003-08-04  created by andrei
- *   2004-11-12  minor api extension, added *count (andrei)
  */
 
 /*!
  * \file
- * \brief SIP-router core ::  regexp and regexp substitutions implementations
+ * \brief Kamailio core ::  regexp and regexp substitutions implementations
  * \ingroup core
  * Module: \ref core
  */
@@ -322,7 +310,7 @@ found_re:
 	se->n_escapes=rw_no;
 	se->max_pmatch=max_pmatch;
 	for (r=0; r<rw_no; r++) se->replace[r]=rw[r];
-	DBG("subst_parser: ok, se is %p\n", se);
+	LM_DBG("ok, se is %p\n", se);
 	return se;
 	
 error:
@@ -445,7 +433,7 @@ struct replace_lst* subst_run(struct subst_expr* se, const char* input,
 	eflags=0;
 	do{
 		r=regexec(se->re, p, nmatch, pmatch, eflags);
-		DBG("subst_run: running. r=%d\n", r);
+		LM_DBG("running. r=%d\n", r);
 		/* subst */
 		if (r==0){ /* != REG_NOMATCH */
 			if (pmatch[0].rm_so==-1) {
@@ -464,7 +452,7 @@ struct replace_lst* subst_run(struct subst_expr* se, const char* input,
 			memset(*crt, 0, sizeof(struct replace_lst));
 			(*crt)->offset=pmatch[0].rm_so+(int)(p-input);
 			(*crt)->size=pmatch[0].rm_eo-pmatch[0].rm_so;
-			DBG("subst_run: matched (%d, %d): [%.*s]\n",
+			LM_DBG("matched (%d, %d): [%.*s]\n",
 					(*crt)->offset, (*crt)->size, 
 					(*crt)->size, input+(*crt)->offset);
 			/* create subst. string */
@@ -514,7 +502,7 @@ str* subst_str(const char *input, struct sip_msg* msg, struct subst_expr* se,
 	end=input+len;
 	lst=subst_run(se, input, msg, count);
 	if (lst==0){
-		DBG("subst_str: no match\n");
+		LM_DBG("no match\n");
 		return 0;
 	}
 	for (l=lst; l; l=l->next)
diff --git a/re.h b/re.h
index 1d6ea34..30d5ff6 100644
--- a/re.h
+++ b/re.h
@@ -1,23 +1,16 @@
 /*
- * $Id$
- *
  * regexp and regexp substitutions implementations
  * 
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -27,10 +20,13 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
  *
- * History:
- * --------
- *   2003-08-04  created by andrei
- *   2004-11-12  minor api extension, added *count (andrei)
+ */
+/*!
+ * \file
+ * \brief Kamailio core :: regexp and regexp substitutions implementations
+ * \author andrei
+ * \ingroup core
+ * Module: \ref core
  */
 
 #ifndef _re_h
diff --git a/receive.c b/receive.c
index 05a23e2..8a633cd 100644
--- a/receive.c
+++ b/receive.c
@@ -1,21 +1,14 @@
 /* 
- *$Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,25 +17,11 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * ---------
- * 2003-02-28 scratchpad compatibility abandoned (jiri)
- * 2003-01-29 transport-independent message zero-termination in
- *            receive_msg (jiri)
- * 2003-02-07 undoed jiri's zero term. changes (they break tcp) (andrei)
- * 2003-02-10 moved zero-term in the calling functions (udp_receive &
- *            tcp_read_req)
- * 2003-08-13 fixed exec_pre_cb returning 0 (backported from stable) (andrei)
- * 2004-02-06 added user preferences support - destroy_avps() (bogdan)
- * 2004-04-30 exec_pre_cb is called after basic sanity checks (at least one
- *            via present & parsed ok)  (andrei)
- * 2004-08-23 avp core changed - destroy_avp-> reset_avps (bogdan)
- * 2006-11-29 nonsip_msg hooks called for non-sip msg (e.g HTTP) (andrei)
  */
 
 /*!
  * \file
- * \brief SIP-router core :: 
+ * \brief Kamailio core :: 
  * \ingroup core
  * Module: \ref core
  */
@@ -96,7 +75,8 @@ unsigned int inc_msg_no(void)
 }
 
 
-/* WARNING: buf must be 0 terminated (buf[len]=0) or some things might 
+/** Receive message
+ *  WARNING: buf must be 0 terminated (buf[len]=0) or some things might 
  * break (e.g.: modules/textops)
  */
 int receive_msg(char* buf, unsigned int len, struct receive_info* rcv_info) 
@@ -151,7 +131,7 @@ int receive_msg(char* buf, unsigned int len, struct receive_info* rcv_info)
 		}
 		goto error02;
 	}
-	DBG("After parse_msg...\n");
+	LM_DBG("After parse_msg...\n");
 
 	/* set log prefix */
 	log_prefix_set(msg);
@@ -194,7 +174,7 @@ int receive_msg(char* buf, unsigned int len, struct receive_info* rcv_info)
 #endif
 
 	/*	skip: */
-		DBG("preparing to run routing scripts...\n");
+		LM_DBG("preparing to run routing scripts...\n");
 #ifdef  STATS
 		gettimeofday( & tvb, &tz );
 #endif
@@ -223,7 +203,7 @@ int receive_msg(char* buf, unsigned int len, struct receive_info* rcv_info)
 		diff = (tve.tv_sec-tvb.tv_sec)*1000000+(tve.tv_usec-tvb.tv_usec);
 		stats->processed_requests++;
 		stats->acc_req_time += diff;
-		DBG("successfully ran routing scripts...(%d usec)\n", diff);
+		LM_DBG("successfully ran routing scripts...(%d usec)\n", diff);
 		STATS_RX_REQUEST( msg->first_line.u.request.method_value );
 #endif
 
@@ -279,7 +259,7 @@ int receive_msg(char* buf, unsigned int len, struct receive_info* rcv_info)
 		diff = (tve.tv_sec-tvb.tv_sec)*1000000+(tve.tv_usec-tvb.tv_usec);
 		stats->processed_responses++;
 		stats->acc_res_time+=diff;
-		DBG("successfully ran reply processing...(%d usec)\n", diff);
+		LM_DBG("successfully ran reply processing...(%d usec)\n", diff);
 #endif
 
 		/* execute post reply-script callbacks */
@@ -295,7 +275,7 @@ end:
 #ifdef WITH_XAVP
 	xavp_reset_list();
 #endif
-	DBG("receive_msg: cleaning up\n");
+	LM_DBG("cleaning up\n");
 	free_sip_msg(msg);
 	pkg_free(msg);
 #ifdef STATS
@@ -316,7 +296,7 @@ error_rpl:
 	goto error02;
 #endif /* NO_ONREPLY_ROUTE_ERROR */
 error_req:
-	DBG("receive_msg: error:...\n");
+	LM_DBG("error:...\n");
 	/* execute post request-script callbacks */
 	exec_post_script_cb(msg, REQUEST_CB_TYPE);
 error03:
diff --git a/receive.h b/receive.h
index a40fdc2..4e6a13d 100644
--- a/receive.h
+++ b/receive.h
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,6 +17,12 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
+/*!
+* \file
+* \brief Kamailio core :: Receive msg function
+* \ingroup core
+* Module: \ref core
+*/
 
 
 
diff --git a/resolve.c b/resolve.c
index c9f0977..0af1be3 100644
--- a/resolve.c
+++ b/resolve.c
@@ -1,21 +1,14 @@
-/* $Id$*/
 /*
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,34 +17,10 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/*
- * History:
- * -------
- *  2003-02-13  added proto to sip_resolvehost, for SRV lookups (andrei)
- *  2003-07-03  default port value set according to proto (andrei)
- *  2005-07-11  added resolv_init (timeouts a.s.o) (andrei)
- *  2006-04-13  added sip_hostport2su()  (andrei)
- *  2006-07-13  rdata structures put on diet (andrei)
- *  2006-07-17  rdata contains now also the record name (andrei)
- *  2006-08-18  get_record can append also the additional records to the
- *               returned list (andrei)
- *  2007-06-15  naptr support (andrei)
- *  2007-10-10  short name resolution using search list supported (mma)
- *              set dns_use_search_list=1 (default on)
- *              new option dns_search_full_match (default on) controls
- *              whether rest of the name is matched against search list
- *              or blindly accepted (better performance but exploitable)
- *  2008-01-31  resolver options use the configuration framework, and the
- *               resolver is reinitialized when the options change (Miklos)
- *  2008-08-12  sctp preference support for NAPTR queries (andrei)
- *  2009-03-30  TXT record support (andrei)
- *  2009-03-31  EBL record support (andrei)
- *  2009-04-01  PTR record support (andrei)
- */ 
 
 /*!
  * \file
- * \brief SIP-router core :: 
+ * \brief Kamailio core :: DNS resolver
  * \ingroup core
  * Module: \ref core
  */
@@ -171,7 +140,7 @@ error:
 	return -1;
 }
 
-/* init. the resolver
+/** init. the resolver
  * params: retr_time  - time before retransmitting (must be >0)
  *         retr_no    - retransmissions number
  *         servers_no - how many dns servers will be used
@@ -205,7 +174,7 @@ static int _resolv_init(void)
 	return 0;
 }
 
-/* wrapper function to initialize the resolver at startup */
+/** wrapper function to initialize the resolver at startup */
 int resolv_init(void)
 {
 	int res = -1;
@@ -219,7 +188,7 @@ int resolv_init(void)
 	return res;
 }
 
-/* wrapper function to reinitialize the resolver
+/** wrapper function to reinitialize the resolver
  * This function must be called by each child process whenever
  * a resolver option changes
  */
@@ -233,7 +202,7 @@ void resolv_reinit(str *gname, str *name)
 	LM_DBG("DNS resolver has been reinitialized\n");
 }
 
-/* fixup function for dns_reinit variable
+/** fixup function for dns_reinit variable
  * (resets the variable to 0)
  */
 int dns_reinit_fixup(void *handle, str *gname, str *name, void **val)
@@ -242,7 +211,7 @@ int dns_reinit_fixup(void *handle, str *gname, str *name, void **val)
 	return 0;
 }
 
-/* wrapper function to recalculate the naptr and srv protocol preferences */
+/** wrapper function to recalculate the naptr and srv protocol preferences */
 void reinit_proto_prefs(str *gname, str *name)
 {
 #ifdef USE_NAPTR
@@ -251,8 +220,8 @@ void reinit_proto_prefs(str *gname, str *name)
 	init_srv_proto_prefs();
 }
 
-/* fixup function for dns_try_ipv6
- * verifies that SER really listens on an ipv6 interface
+/** fixup function for dns_try_ipv6
+ * verifies that Kamailio really listens on an ipv6 interface
  */
 int dns_try_ipv6_fixup(void *handle, str *gname, str *name, void **val)
 {
@@ -264,7 +233,7 @@ int dns_try_ipv6_fixup(void *handle, str *gname, str *name, void **val)
 	return 0;
 }
 
- /*  skips over a domain name in a dns message
+/**  skips over a domain name in a dns message
  *  (it can be  a sequence of labels ending in \0, a pointer or
  *   a sequence of labels ending in a pointer -- see rfc1035
  *   returns pointer after the domain name or null on error*/
@@ -290,13 +259,14 @@ unsigned char* dns_skipname(unsigned char* p, unsigned char* end)
 
 
 
-/* parses the srv record into a srv_rdata structure
+/** parses the srv record into a srv_rdata structure
  *   msg   - pointer to the dns message
  *   end   - pointer to the end of the message
  *   eor   - pointer to the end of the record/rdata
  *   rdata - pointer  to the rdata part of the srv answer
- * returns 0 on error, or a dyn. alloc'ed srv_rdata structure */
-/* SRV rdata format:
+ * returns 0 on error, or a dyn. alloc'ed srv_rdata structure 
+ *
+ * SRV rdata format:
  *            111111
  *  0123456789012345
  * +----------------+
@@ -354,12 +324,13 @@ error:
 }
 
 
-/* parses the naptr record into a naptr_rdata structure
+/** parses the naptr record into a naptr_rdata structure
  *   msg   - pointer to the dns message
  *   end   - pointer to the end of the message
  *   eor   - pointer to the end of the record/rdata
  *   rdata - pointer  to the rdata part of the naptr answer
  * returns 0 on error, or a dyn. alloc'ed naptr_rdata structure */
+
 /* NAPTR rdata format:
  *            111111
  *  0123456789012345
@@ -451,7 +422,7 @@ error:
 
 
 
-/* parses a CNAME record into a cname_rdata structure */
+/** parses a CNAME record into a cname_rdata structure */
 struct cname_rdata* dns_cname_parser( unsigned char* msg, unsigned char* end,
 									  unsigned char* rdata)
 {
@@ -482,7 +453,7 @@ error:
 
 
 
-/* parses an A record rdata into an a_rdata structure
+/** parses an A record rdata into an a_rdata structure
  * returns 0 on error or a dyn. alloc'ed a_rdata struct
  */
 struct a_rdata* dns_a_parser(unsigned char* rdata, unsigned char* eor)
@@ -503,7 +474,7 @@ error:
 
 
 
-/* parses an AAAA (ipv6) record rdata into an aaaa_rdata structure
+/** parses an AAAA (ipv6) record rdata into an aaaa_rdata structure
  * returns 0 on error or a dyn. alloc'ed aaaa_rdata struct */
 struct aaaa_rdata* dns_aaaa_parser(unsigned char* rdata, unsigned char* eor)
 {
@@ -654,7 +625,7 @@ error:
 
 
 
-/* parses a PTR record into a ptr_rdata structure */
+/** parses a PTR record into a ptr_rdata structure */
 struct ptr_rdata* dns_ptr_parser( unsigned char* msg, unsigned char* end,
 									  unsigned char* rdata)
 {
@@ -685,7 +656,7 @@ error:
 
 
 
-/* frees completely a struct rdata list */
+/** frees completely a struct rdata list */
 void free_rdata_list(struct rdata* head)
 {
 	struct rdata* l;
@@ -701,7 +672,7 @@ void free_rdata_list(struct rdata* head)
 }
 
 #ifdef HAVE_RESOLV_RES
-/* checks whether supplied name exists in the resolver search list
+/** checks whether supplied name exists in the resolver search list
  * returns 1 if found
  *         0 if not found
  */
@@ -715,7 +686,7 @@ int match_search_list(const struct __res_state* res, char* name) {
 }
 #endif
 
-/* gets the DNS records for name:type
+/** gets the DNS records for name:type
  * returns a dyn. alloc'ed struct rdata linked list with the parsed responses
  * or 0 on error
  * see rfc1035 for the query/response format */
@@ -767,7 +738,7 @@ struct rdata* get_record(char* name, int type, int flags)
 	size=dns_func.sr_res_search(name, C_IN, type, buff.buff, sizeof(buff));
 
 	if (unlikely(size<0)) {
-		DBG("get_record: lookup(%s, %d) failed\n", name, type);
+		LM_DBG("lookup(%s, %d) failed\n", name, type);
 		goto not_found;
 	}
 	else if (unlikely(size > sizeof(buff))) size=sizeof(buff);
@@ -963,8 +934,7 @@ again:
 		flags&=~RES_AR;
 		answers_no=ntohs((unsigned short)buff.hdr.nscount);
 #ifdef RESOLVE_DBG
-		DBG("get_record: skipping %d NS (p=%p, end=%p)\n", answers_no, p,
-				end);
+		LM_DBG("skipping %d NS (p=%p, end=%p)\n", answers_no, p, end);
 #endif
 		for (r=0; (r<answers_no) && (p<end); r++){
 			/* skip over the ns records */
@@ -979,8 +949,7 @@ again:
 		}
 		answers_no=ntohs((unsigned short)buff.hdr.arcount);
 #ifdef RESOLVE_DBG
-		DBG("get_record: parsing %d ARs (p=%p, end=%p)\n", answers_no, p,
-				end);
+		LM_DBG("parsing %d ARs (p=%p, end=%p)\n", answers_no, p, end);
 #endif
 		goto again; /* add also the additional records */
 	}
@@ -1049,7 +1018,7 @@ not_found:
 #define SIPS_D2T	0x7432642b
 
 
-/* get protocol from a naptr rdata and check for validity
+/** get protocol from a naptr rdata and check for validity
  * returns > 0 (PROTO_UDP, PROTO_TCP, PROTO_SCTP or PROTO_TLS)
  *         <=0  on error 
  */
@@ -1126,7 +1095,7 @@ inline static int srv_proto_pref_score(char proto)
 
 
 
-/* returns true if we support the protocol */
+/** returns true if we support the protocol */
 int naptr_proto_supported(char proto)
 {
 	if (naptr_proto_pref_score(proto)<0)
@@ -1153,21 +1122,21 @@ int naptr_proto_supported(char proto)
 
 
 
-/* returns true if new_proto is preferred over old_proto */
+/** returns true if new_proto is preferred over old_proto */
 int naptr_proto_preferred(char new_proto, char old_proto)
 {
 	return naptr_proto_pref_score(new_proto)>naptr_proto_pref_score(old_proto);
 }
 
 
-/* choose between 2 naptr records, should take into account local
+/** choose between 2 naptr records, should take into account local
  * preferences too
  * returns 1 if the new record was selected, 0 otherwise */
 int naptr_choose (struct naptr_rdata** crt, char* crt_proto,
 									struct naptr_rdata* n , char n_proto)
 {
 #ifdef NAPTR_DBG
-	DBG("naptr_choose(o: %d w: %d p:%d , o: %d w:%d p:%d)\n",
+	LM_DBG("o:%d w:%d p:%d, o:%d w:%d p:%d\n",
 			*crt?(int)(*crt)->order:-1, *crt?(int)(*crt)->pref:-1,
 			(int)*crt_proto,
 			(int)n->order, (int)n->pref, (int)n_proto);
@@ -1181,12 +1150,12 @@ int naptr_choose (struct naptr_rdata** crt, char* crt_proto,
 			goto change;
 	}
 #ifdef NAPTR_DBG
-	DBG("naptr_choose: no change\n");
+	LM_DBG("no change\n");
 #endif
 	return 0;
 change:
 #ifdef NAPTR_DBG
-	DBG("naptr_choose: changed\n");
+	LM_DBG("changed\n");
 #endif
 	*crt_proto=n_proto;
 	*crt=n;
@@ -1196,7 +1165,7 @@ change:
 
 
 
-/* internal sip srv resolver: resolves a host name trying:
+/** internal sip srv resolver: resolves a host name trying:
  * - SRV lookup if the address is not an ip *port==0. The result of the SRV
  *   query will be used for an A/AAAA lookup.
  *  - normal A/AAAA lookup (either fallback from the above or if *port!=0
@@ -1214,7 +1183,7 @@ change:
  *  0 on error
  */
 struct hostent* srv_sip_resolvehost(str* name, int zt, unsigned short* port,
-									char* proto, int is_srv, struct rdata* ars)
+	char* proto, int is_srv, struct rdata* ars)
 {
 	struct hostent* he;
 	struct ip_addr* ip;
@@ -1235,7 +1204,7 @@ struct hostent* srv_sip_resolvehost(str* name, int zt, unsigned short* port,
 		goto end;
 	}
 #ifdef RESOLVE_DBG
-	DBG("srv_sip_resolvehost: %.*s:%d proto=%d\n", name->len, name->s,
+	LM_DBG("%.*s:%d proto=%d\n", name->len, name->s,
 			port?(int)*port:-1, proto?(int)*proto:-1);
 #endif
 	if (is_srv){
@@ -1304,7 +1273,7 @@ do_srv:
 				if (he!=0){
 					/* we found it*/
 #ifdef RESOLVE_DBG
-					DBG("srv_sip_resolvehost: found SRV(%s) = %s:%d in AR\n",
+					LM_DBG("found SRV(%s) = %s:%d in AR\n",
 							srv_target, srv->name, srv->port);
 #endif
 					*port=srv->port;
@@ -1325,7 +1294,7 @@ do_srv:
 				if (he!=0){
 					/* we found it*/
 #ifdef RESOLVE_DBG
-					DBG("srv_sip_resolvehost: SRV(%s) = %s:%d\n",
+					LM_DBG("SRV(%s) = %s:%d\n",
 							srv_target, srv->name, srv->port);
 #endif
 					*port=srv->port;
@@ -1341,7 +1310,7 @@ do_srv:
 			}
 			/* cleanup on exit */
 #ifdef RESOLVE_DBG
-			DBG("srv_sip_resolvehost: no SRV record found for %.*s," 
+			LM_DBG("no SRV record found for %.*s," 
 					" trying 'normal' lookup...\n", name->len, name->s);
 #endif
 		}
@@ -1355,7 +1324,7 @@ do_srv:
 	}
 end:
 #ifdef RESOLVE_DBG
-	DBG("srv_sip_resolvehost: returning %p (%.*s:%d proto=%d)\n",
+	LM_DBG("returning %p (%.*s:%d proto=%d)\n",
 			he, name->len, name->s,
 			port?(int)*port:-1, proto?(int)*proto:-1);
 #endif
@@ -1369,7 +1338,7 @@ end:
 #ifdef USE_NAPTR 
 
 
-/* iterates over a naptr rr list, returning each time a "good" naptr record
+/** iterates over a naptr rr list, returning each time a "good" naptr record
  * is found.( srv type, no regex and a supported protocol)
  * params:
  *         naptr_head - naptr rr list head
@@ -1417,9 +1386,8 @@ struct rdata* naptr_sip_iterate(struct rdata* naptr_head,
 			continue; /* already tried */
 		}
 #ifdef NAPTR_DBG
-		DBG("naptr_iterate: found a valid sip NAPTR rr %.*s,"
-					" proto %d\n", naptr->repl_len, naptr->repl, 
-					(int)naptr_proto);
+		LM_DBG("found a valid sip NAPTR rr %.*s, proto %d\n",
+					naptr->repl_len, naptr->repl, (int)naptr_proto);
 #endif
 		if ((naptr_proto_supported(naptr_proto))){
 			if (naptr_choose(&naptr_saved, &saved_proto,
@@ -1432,8 +1400,8 @@ struct rdata* naptr_sip_iterate(struct rdata* naptr_head,
 	if (naptr_saved){
 		/* found something */
 #ifdef NAPTR_DBG
-		DBG("naptr_iterate: choosed NAPTR rr %.*s, proto %d"
-					" tried: 0x%x\n", naptr_saved->repl_len, 
+		LM_DBG("choosed NAPTR rr %.*s, proto %d tried: 0x%x\n",
+					naptr_saved->repl_len, 
 					naptr_saved->repl, (int)saved_proto, *tried);
 #endif
 		*tried|=1<<idx;
@@ -1446,7 +1414,7 @@ end:
 	return 0;
 }
 
-/* Prepend srv prefix according to the proto. */
+/** Prepend srv prefix according to the proto. */
 void create_srv_name(char proto, str *name, char *srv) {
 	switch (proto) {
 		case PROTO_UDP:
@@ -1529,13 +1497,12 @@ size_t create_srv_pref_list(char *proto, struct dns_srv_proto *list) {
 	return list_len;
 }
 
-/* Resolves SRV if no naptr found. 
+/** Resolves SRV if no naptr found. 
  * It reuse dns_pref values and according that resolves supported protocols. 
  * If dns_pref are equal then it use udp,tcp,tls,sctp order.
  * returns: hostent struct & *port filled with the port from the SRV record;
  *  0 on error
  */
-
 struct hostent* no_naptr_srv_sip_resolvehost(str* name, unsigned short* port, char* proto)
 {
 	struct dns_srv_proto srv_proto_list[PROTO_LAST];
@@ -1603,7 +1570,7 @@ struct hostent* no_naptr_srv_sip_resolvehost(str* name, unsigned short* port, ch
 
 } 
 
-/* internal sip naptr resolver function: resolves a host name trying:
+/** internal sip naptr resolver function: resolves a host name trying:
  * - NAPTR lookup if the address is not an ip and *proto==0 and *port==0.
  *   The result of the NAPTR query will be used for a SRV lookup
  * - SRV lookup if the address is not an ip *port==0. The result of the SRV
@@ -1661,8 +1628,8 @@ struct hostent* naptr_sip_resolvehost(str* name,  unsigned short* port,
 		}
 		/*clean up on exit*/
 #ifdef RESOLVE_DBG
-		DBG("naptr_sip_resolvehost: no NAPTR record found for %.*s," 
-				" trying SRV lookup...\n", name->len, name->s);
+		LM_DBG("no NAPTR record found for %.*s, trying SRV lookup...\n",
+					name->len, name->s);
 #endif
 	}
 	/* fallback to srv lookup */
@@ -1681,7 +1648,7 @@ end:
 
 
 
-/* resolves a host name trying:
+/** resolves a host name trying:
  * - NAPTR lookup if enabled, the address is not an ip and *proto==0 and 
  *   *port==0. The result of the NAPTR query will be used for a SRV lookup
  * - SRV lookup if the address is not an ip *port==0. The result of the SRV
@@ -1711,7 +1678,7 @@ struct hostent* _sip_resolvehost(str* name, unsigned short* port, char* proto)
 }
 
 
-/* resolve host, port, proto using sip rules (e.g. use SRV if port=0 a.s.o)
+/** resolve host, port, proto using sip rules (e.g. use SRV if port=0 a.s.o)
  *  and write the result in the sockaddr_union to
  *  returns -1 on error (resolve failed), 0 on success */
 int sip_hostport2su(union sockaddr_union* su, str* name, unsigned short port,
diff --git a/resolve.h b/resolve.h
index 3aa690a..fad783e 100644
--- a/resolve.h
+++ b/resolve.h
@@ -1,23 +1,16 @@
 /*
- * $Id$
- *
  * resolver related functions
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -26,17 +19,14 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/* History:
- * --------
- *  2003-04-12  support for resolving ipv6 address references added (andrei)
- *  2004-07-28  darwin needs nameser_compat.h (andrei)
- *  2006-07-13  rdata structures put on diet (andrei)
- *  2006-07-17  rdata contains now also the record name (andrei)
- *  2006-08-18  get_record uses flags (andrei)
- *  2006-06-16  naptr support (andrei)
- */
-
 
+/*!
+ * \file
+ * \brief Kamailio core :: DNS resolver
+ * \author andrei
+ * \ingroup core
+ * Module: \ref core
+ */
 
 #ifndef __resolve_h
 #define __resolve_h
diff --git a/route.c b/route.c
index 35c099f..97df31e 100644
--- a/route.c
+++ b/route.c
@@ -1,24 +1,16 @@
 /*
- * $Id$
- *
  * SIP routing engine
  *
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -27,37 +19,10 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2003-01-28  scratchpad removed, src_port introduced (jiri)
- *  2003-02-28  scratchpad compatibility abandoned (jiri)
- *  2003-03-10  updated to the new module exports format (andrei)
- *  2003-03-19  replaced all mallocs/frees w/ pkg_malloc/pkg_free (andrei)
- *  2003-04-01  added dst_port, proto, af; renamed comp_port to comp_no,
- *               inlined all the comp_* functions (andrei)
- *  2003-04-05  s/reply_route/failure_route, onreply_route introduced (jiri)
- *  2003-05-23  comp_ip fixed, now it will resolve its operand and compare
- *              the ip with all the addresses (andrei)
- *  2003-10-10  added more operators support to comp_* (<,>,<=,>=,!=) (andrei)
- *  2004-10-19  added from_uri & to_uri (andrei)
- *  2005-12-12  added retcode support (anrei)
- *  2005-12-19  select framework (mma)
- *  2006-01-30  removed rec. protection from eval_expr (andrei)
- *  2006-02-06  added named route tables (andrei)
- *  2008-04-14  (expr1 != expr2) is evaluated true if at least one of
- *		the expressions does not exist (Miklos)
- *  2008-04-23  errors are treated as false during expression evaluation
- *  		unless the operator is DIFF_OP (Miklos)
- *  2008-12-03  fixups for rvalues in assignments (andrei)
- *  2009-05-04  switched IF_T to rval_expr (andrei)
- *  2010-06-01  special hack/support for fparam fixups so that they can handle
- *               variable RVEs (andrei)
- *  2010-06-18  ip comparison (comp_ip()) normalizes strings to
- *              ip/netmask  (andrei)
  */
 
 
-/** expression evaluation, route fixups and routing lists.
+/** Kamailio core :: expression evaluation, route fixups and routing lists.
  * @file route.c
  * @ingroup core
  * Module: @ref core
@@ -405,7 +370,7 @@ static int exp_optimize_left(struct expr* exp)
 		}
 	}
 	if (ret>0)
-		DBG("left EXP optimized: op%d(_O%d_, ST%d) => op%d(_O%d_, ST%d)\n",
+		LM_DBG("op%d(_O%d_, ST%d) => op%d(_O%d_, ST%d)\n",
 			old_op, old_ltype, old_rtype, exp->op, exp->l_type, exp->r_type);
 	return ret;
 }
@@ -503,7 +468,7 @@ static int exp_optimize_right(struct expr* exp)
 		}
 	}
 	if (ret>0)
-		DBG("right EXP optimized: op%d(O%d, _ST%d_) => op%d(O%d, _ST%d_)\n",
+		LM_DBG("op%d(O%d, _ST%d_) => op%d(O%d, _ST%d_)\n",
 			old_op, old_ltype, old_rtype, exp->op, exp->l_type, exp->r_type);
 	return ret;
 }
@@ -904,7 +869,7 @@ int fix_actions(struct action* a)
 				cmd = t->val[0].u.data;
 				rve_param_no = 0;
 				if (cmd) {
-					DBG("fixing %s()\n", cmd->name);
+					LM_DBG("fixing %s()\n", cmd->name);
 					if (t->val[1].u.number==0) {
 						ret = call_fixup(cmd->fixup, 0, 0);
 						if (ret < 0)
@@ -1735,7 +1700,7 @@ inline static int comp_ip(int op, struct ip_addr* ip, int rtype,
 			/* 2: resolve (name) & compare w/ all the ips */
 			he=resolvehost(right->s);
 			if (he==0){
-				DBG("comp_ip: could not resolve %s\n", r->str.s);
+				LM_DBG("could not resolve %s\n", r->str.s);
 			}else if (he->h_addrtype==ip->af){
 				for(h=he->h_addr_list;(ret!=1)&& (*h); h++){
 					ret=(memcmp(ip->u.addr, *h, ip->len)==0);
@@ -1770,7 +1735,7 @@ inline static int comp_ip(int op, struct ip_addr* ip, int rtype,
 			/* 2: resolve (name) & compare w/ all the ips */
 			he=resolvehost(right->s);
 			if (he==0){
-				DBG("comp_ip: could not resolve %s\n", r->str.s);
+				LM_DBG("could not resolve %s\n", r->str.s);
 			}else if (he->h_addrtype==ip->af){
 				for(h=he->h_addr_list;(ret!=1)&& (*h); h++){
 					ret=(memcmp(ip->u.addr, *h, ip->len)==0);
@@ -2161,10 +2126,10 @@ static void print_rl(struct route_list* rt, char* name)
 	for(j=0; j<rt->entries; j++){
 		if (rt->rlist[j]==0){
 			if ((j==0) && (rt==&main_rt))
-				DBG("WARNING: the main routing table is empty\n");
+				LM_DBG("WARNING: the main routing table is empty\n");
 			continue;
 		}
-		DBG("%s routing table %d:\n", name, j);
+		LM_DBG("%s routing table %d:\n", name, j);
 		print_actions(rt->rlist[j]);
 		DBG("\n");
 	}
diff --git a/route.h b/route.h
index 4e3aca6..b711c2a 100644
--- a/route.h
+++ b/route.h
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,6 +17,12 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
+/*!
+* \file
+* \brief Kamailio core :: Message routing
+* \ingroup core
+* Module: \ref core
+*/
 
 
 #ifndef route_h
diff --git a/route_struct.c b/route_struct.c
index b5b702e..0bc677d 100644
--- a/route_struct.c
+++ b/route_struct.c
@@ -1,23 +1,16 @@
 /*
- * $Id$
- *
  * route structures helping functions
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -26,19 +19,10 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/* History:
- * --------
- *  2003-01-29  src_port introduced (jiri)
- *  2003-03-19  replaced all mallocs/frees w/ pkg_malloc/pkg_free (andrei)
- *  2003-04-12  FORCE_RPORT_T added (andrei)
- *  2003-10-02  added SET_ADV_ADDRESS & SET_ADV_PORT (andrei)
- *  2004-02-24  added LOAD_AVP_T and AVP_TO_URI_T (bogdan)
- *  2005-12-19  select framework added SELECT_O and SELECT_ST (mma)
- */
 
 /*!
  * \file
- * \brief SIP-router core :: 
+ * \brief Kamailio core :: route structures helping functions
  * \ingroup core
  * Module: \ref core
  */
diff --git a/route_struct.h b/route_struct.h
index 5d1aa15..f1aaac4 100644
--- a/route_struct.h
+++ b/route_struct.h
@@ -1,22 +1,14 @@
 /*
- * $Id$
- *
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -25,20 +17,14 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/* History:
- * --------
- *
- *  2003-04-12  FORCE_RPORT_T added (andrei)
- *  2003-04-22  strip_tail added (jiri)
- *  2003-10-10  >,<,>=,<=, != and MSGLEN_O added (andrei)
- *  2003-10-28  FORCE_TCP_ALIAS added (andrei)
- *  2004-02-24  added LOAD_AVP_T and AVP_TO_URI_T (bogdan)
- *  2005-12-11  added SND{IP,PORT,PROTO,AF}_O & TO{IP,PORT}_O (andrei)
- *  2005-12-19  select framework added SELECT_O and SELECT_ST (mma)
- *  2008-12-17  added UDP_MTU_TRY_PROTO_T (andrei)
+/*!
+ * \file
+ * \brief Kamailio core :: Route structure
+ * \ingroup core
+ * Module: \ref core
+ * \author andrei, bogdan
  */
 
-
 #ifndef route_struct_h
 #define route_struct_h
 
diff --git a/rpc.h b/rpc.h
index 91c1463..0eefc99 100644
--- a/rpc.h
+++ b/rpc.h
@@ -1,22 +1,16 @@
-/* $Id$
- *
- * SER Remote Procedure Call Interface
+/* 
+ * Kamailio Remote Procedure Call Interface
  *
  * Copyright (C) 2005 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -26,6 +20,13 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
+/*!
+* \file
+* \brief Kamailio core :: RPC, Remote procedure call interface
+* \ingroup core
+* Module: \ref core
+*/
+
 #ifndef _RPC_H
 #define _RPC_H
 
@@ -46,15 +47,15 @@ struct rpc_delayed_ctx;
 
 
 /* Send the result to the caller */
-typedef int (*rpc_send_f)(void* ctx);                                      /* Send the reply to the client */
-typedef void (*rpc_fault_f)(void* ctx, int code, char* fmt, ...);          /* Signal a failure to the client */
-typedef int (*rpc_add_f)(void* ctx, char* fmt, ...);                       /* Add a new piece of data to the result */
-typedef int (*rpc_scan_f)(void* ctx, char* fmt, ...);                      /* Retrieve request parameters */
-typedef int (*rpc_rpl_printf_f)(void* ctx, char* fmt, ...);                /* Add printf-like formated data to the result set */
-typedef int (*rpc_struct_add_f)(void* ctx, char* fmt, ...);                /* Add fields in a structure */
-typedef int (*rpc_array_add_f)(void* ctx, char* fmt, ...);                 /* Add values in an array */
-typedef int (*rpc_struct_scan_f)(void* ctx, char* fmt, ...);               /* Scan attributes of a structure */
-typedef int (*rpc_struct_printf_f)(void* ctx, char* name, char* fmt, ...); /* Struct version of rpc_printf */
+typedef int (*rpc_send_f)(void* ctx);                                      /*!< Send the reply to the client */
+typedef void (*rpc_fault_f)(void* ctx, int code, char* fmt, ...);          /*!< Signal a failure to the client */
+typedef int (*rpc_add_f)(void* ctx, char* fmt, ...);                       /*!< Add a new piece of data to the result */
+typedef int (*rpc_scan_f)(void* ctx, char* fmt, ...);                      /*!< Retrieve request parameters */
+typedef int (*rpc_rpl_printf_f)(void* ctx, char* fmt, ...);                /*!< Add printf-like formated data to the result set */
+typedef int (*rpc_struct_add_f)(void* ctx, char* fmt, ...);                /*!< Add fields in a structure */
+typedef int (*rpc_array_add_f)(void* ctx, char* fmt, ...);                 /*!< Add values in an array */
+typedef int (*rpc_struct_scan_f)(void* ctx, char* fmt, ...);               /*!< Scan attributes of a structure */
+typedef int (*rpc_struct_printf_f)(void* ctx, char* name, char* fmt, ...); /*!< Struct version of rpc_printf */
 
 /* returns the supported capabilities */
 typedef rpc_capabilities_t (*rpc_capabilities_f)(void* ctx);
@@ -91,13 +92,12 @@ typedef struct rpc_delayed_ctx{
 } rpc_delayed_ctx_t;
 
 
-/*
+/**
  * RPC Function Prototype
  */
-
 typedef void (*rpc_function_t)(rpc_t* rpc, void* ctx);
 
-/*
+/**
  * RPC callback context.
  *
  * Defines a convenient way of packing an rpc callback
@@ -110,14 +110,14 @@ typedef struct rpc_cb_ctx {
 } rpc_cb_ctx_t;
 
 
-/*
+/**
  * Remote Procedure Call Export
  */
 typedef struct rpc_export {
-	const char* name;        /* Name of the RPC function (null terminated) */
-	rpc_function_t function; /* Pointer to the function */
-	const char** doc_str;  /* Documentation strings, method signature and description */
-	unsigned int flags;      /* Various flags, reserved for future use */
+	const char* name;        /*!< Name of the RPC function (null terminated) */
+	rpc_function_t function; /*!< Pointer to the function */
+	const char** doc_str;  /*!< Documentation strings, method signature and description */
+	unsigned int flags;      /*!< Various flags, reserved for future use */
 } rpc_export_t;
 
 
diff --git a/rpc_lookup.c b/rpc_lookup.c
index bbe551c..cbcd2a9 100644
--- a/rpc_lookup.c
+++ b/rpc_lookup.c
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- * 
  * Copyright (C) 2009 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -15,18 +13,10 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/*
- * SER RPC lookup and register functions
- */
-/*
- * History:
- * --------
- *  2009-05-11  initial version (andrei)
-*/
 
 /*!
  * \file
- * \brief SIP-router core :: 
+ * \brief Kamailio core ::  RPC lookup and register functions
  * \ingroup core
  * Module: \ref core
  */
diff --git a/rpc_lookup.h b/rpc_lookup.h
index 53d40b6..fb199af 100644
--- a/rpc_lookup.h
+++ b/rpc_lookup.h
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- * 
  * Copyright (C) 2009 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -15,14 +13,13 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/*
- * SER RPC lookup and register functions
+/*!
+ * \file
+ * \brief Kamailio core :: Kamailio RPC lookup and register functions
+ * \ingroup core
+ * Module: \ref core
+ * \author andrei
  */
-/*
- * History:
- * --------
- *  2009-05-11  initial version (andrei)
-*/
 
 #ifndef __rpc_lookup_h
 #define __rpc_lookup_h
diff --git a/rvalue.c b/rvalue.c
index 8e5ba20..52c12ed 100644
--- a/rvalue.c
+++ b/rvalue.c
@@ -16,24 +16,12 @@
 
 /**
  * @file 
- * @brief SIP-router core :: rvalue expressions
+ * @brief Kamailio core :: rvalue expressions
  * @ingroup core
  * Module: \ref core
  */
 
-/* 
- * History:
- * --------
- *  2008-12-01  initial version (andrei)
- *  2009-04-24  added support for defined, strempty, strlen (andrei)
- *  2009-04-28  int and str automatic conversions: (int)undef=0,
- *               (str)undef="", (int)""=0, (int)"123"=123, (int)"abc"=0
- *              handle undef == expr, in function of the UNDEF_EQ_* defines.
- *              (andrei)
- *  2009-05-05  casts operator for int & string (andrei)
- */
-
-/* special defines:
+/** special defines:
  *
  *  UNDEF_EQ_* - how to behave when undef is on the right side of a generic
  *               compare operator
@@ -2829,7 +2817,7 @@ static int rve_can_optimize_int(struct rval_expr* rve)
 		if (rve->right.rve->left.rval.type!=RV_INT)
 			return 0;
 	}
-	DBG("rve_can_optimize_int: left %d, right %d\n", 
+	LM_DBG("left %d, right %d\n", 
 			rve->left.rve->op, rve->right.rve?rve->right.rve->op:0);
 	return 1;
 }
@@ -2847,7 +2835,7 @@ static int rve_can_optimize_str(struct rval_expr* rve)
 		return 0;
 	if (rve->op == RVE_RVAL_OP)
 		return 0;
-	DBG("rve_can_optimize_str: left %d, right %d\n", 
+	LM_DBG("left %d, right %d\n", 
 			rve->left.rve->op, rve->right.rve?rve->right.rve->op:0);
 	if (rve->left.rve->op != RVE_RVAL_OP)
 		return 0;
@@ -2868,15 +2856,15 @@ static int rve_can_optimize_str(struct rval_expr* rve)
 
 static int fix_rval(struct rvalue* rv)
 {
-	DBG("RV fixing type %d\n", rv->type);
+	LM_DBG("RV fixing type %d\n", rv->type);
 	switch(rv->type){
 		case RV_INT:
 			/*nothing to do*/
-			DBG("RV is int: %d\n", (int)rv->v.l);
+			LM_DBG("RV is int: %d\n", (int)rv->v.l);
 			return 0;
 		case RV_STR:
 			/*nothing to do*/
-			DBG("RV is str: \"%s\"\n", rv->v.s.s);
+			LM_DBG("RV is str: \"%s\"\n", rv->v.s.s);
 			return 0;
 		case RV_BEXPR:
 			return fix_expr(rv->v.bexpr);
@@ -3275,13 +3263,13 @@ static int rve_opt_01(struct rval_expr* rve, enum rval_type rve_type)
 			if (right){
 				if (rve->op==RVE_RVAL_OP){
 					if (rve->left.rval.type==RV_INT)
-						DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
+						LM_DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
 								" op%d($v, %d) -> %d\n", 
 								rve->fpos.s_line, rve->fpos.s_col,
 								rve->fpos.e_line, rve->fpos.e_col,
 								op, i, (int)rve->left.rval.v.l);
 					else
-						DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
+						LM_DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
 								" op%d($v, %d) -> $v (rval)\n",
 								rve->fpos.s_line, rve->fpos.s_col,
 								rve->fpos.e_line, rve->fpos.e_col,
@@ -3289,19 +3277,19 @@ static int rve_opt_01(struct rval_expr* rve, enum rval_type rve_type)
 				}else if (rve->op==RVE_INT_OP){
 					if (rve->left.rve->op==RVE_RVAL_OP &&
 							rve->left.rve->left.rval.type==RV_INT)
-						DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
+						LM_DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
 								" op%d($v, %d) -> (int)%d\n", 
 								rve->fpos.s_line, rve->fpos.s_col,
 								rve->fpos.e_line, rve->fpos.e_col,
 								op, i, (int)rve->left.rve->left.rval.v.l);
 					else
-						DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
+						LM_DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
 								" op%d($v, %d) -> (int)$v\n",
 								rve->fpos.s_line, rve->fpos.s_col,
 								rve->fpos.e_line, rve->fpos.e_col,
 								op, i);
 				}else{
-					DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
+					LM_DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
 							" op%d($v, %d) -> $v\n",
 							rve->fpos.s_line, rve->fpos.s_col,
 							rve->fpos.e_line, rve->fpos.e_col,
@@ -3310,13 +3298,13 @@ static int rve_opt_01(struct rval_expr* rve, enum rval_type rve_type)
 			}else{
 				if (rve->op==RVE_RVAL_OP){
 					if (rve->left.rval.type==RV_INT)
-						DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
+						LM_DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
 								" op%d(%d, $v) -> %d\n", 
 								rve->fpos.s_line, rve->fpos.s_col,
 								rve->fpos.e_line, rve->fpos.e_col,
 								op, i, (int)rve->left.rval.v.l);
 					else
-						DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
+						LM_DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
 								" op%d(%d, $v) -> $v (rval)\n",
 								rve->fpos.s_line, rve->fpos.s_col,
 								rve->fpos.e_line, rve->fpos.e_col,
@@ -3324,19 +3312,19 @@ static int rve_opt_01(struct rval_expr* rve, enum rval_type rve_type)
 				}else if (rve->op==RVE_INT_OP){
 					if (rve->left.rve->op==RVE_RVAL_OP &&
 							rve->left.rve->left.rval.type==RV_INT)
-						DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
+						LM_DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
 								" op%d(%d, $v) -> (int)%d\n", 
 								rve->fpos.s_line, rve->fpos.s_col,
 								rve->fpos.e_line, rve->fpos.e_col,
 								op, i, (int)rve->left.rve->left.rval.v.l);
 					else
-						DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
+						LM_DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
 								" op%d(%d, $v) -> (int)$v\n",
 								rve->fpos.s_line, rve->fpos.s_col,
 								rve->fpos.e_line, rve->fpos.e_col,
 								op, i);
 				}else{
-					DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
+					LM_DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
 							" op%d(%d, $v) -> $v\n",
 							rve->fpos.s_line, rve->fpos.s_col,
 							rve->fpos.e_line, rve->fpos.e_col,
@@ -3367,7 +3355,7 @@ static int rve_opt_01(struct rval_expr* rve, enum rval_type rve_type)
 					rve->right.rve=0;
 					ret=1;
 					if (dbg)
-						DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
+						LM_DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
 								" op%d($v, \"\") -> strempty($v)\n", 
 								rve->fpos.s_line, rve->fpos.s_col,
 								rve->fpos.e_line, rve->fpos.e_col,
@@ -3388,31 +3376,31 @@ static int rve_opt_01(struct rval_expr* rve, enum rval_type rve_type)
 			if (right){
 				if (rve->op==RVE_RVAL_OP){
 					if (rve->left.rval.type==RV_STR)
-						DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
+						LM_DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
 								" op%d($v, <string>) -> \"%s\"\n", 
 								rve->fpos.s_line, rve->fpos.s_col,
 								rve->fpos.e_line, rve->fpos.e_col,
 								op, rve->left.rval.v.s.s);
 					else
-						DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
+						LM_DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
 								" op%d($v, <string>) -> $v (rval)\n",
 								rve->fpos.s_line, rve->fpos.s_col,
 								rve->fpos.e_line, rve->fpos.e_col, op);
 				}else if (rve->op==RVE_STR_OP){
 					if (rve->left.rve->op==RVE_RVAL_OP &&
 							rve->left.rve->left.rval.type==RV_STR)
-						DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
+						LM_DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
 								" op%d($v, <string>) -> (str)\"%s\"\n", 
 								rve->fpos.s_line, rve->fpos.s_col,
 								rve->fpos.e_line, rve->fpos.e_col,
 								op, rve->left.rve->left.rval.v.s.s);
 					else
-						DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
+						LM_DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
 								" op%d($v, <string>) -> (str)$v\n",
 								rve->fpos.s_line, rve->fpos.s_col,
 								rve->fpos.e_line, rve->fpos.e_col, op);
 				}else{
-					DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
+					LM_DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
 							" op%d($v, <string>) -> $v\n",
 							rve->fpos.s_line, rve->fpos.s_col,
 							rve->fpos.e_line, rve->fpos.e_col, op);
@@ -3420,31 +3408,31 @@ static int rve_opt_01(struct rval_expr* rve, enum rval_type rve_type)
 			}else{
 				if (rve->op==RVE_RVAL_OP){
 					if (rve->left.rval.type==RV_STR)
-						DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
+						LM_DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
 								" op%d(<string>, $v) -> \"%s\"\n", 
 								rve->fpos.s_line, rve->fpos.s_col,
 								rve->fpos.e_line, rve->fpos.e_col,
 								op, rve->left.rval.v.s.s);
 					else
-						DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
+						LM_DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
 								" op%d(<string>, $v) -> $v (rval)\n",
 								rve->fpos.s_line, rve->fpos.s_col,
 								rve->fpos.e_line, rve->fpos.e_col, op);
 				}else if (rve->op==RVE_STR_OP){
 					if (rve->left.rve->op==RVE_RVAL_OP &&
 							rve->left.rve->left.rval.type==RV_STR)
-						DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
+						LM_DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
 								" op%d(<string>, $v) -> (str)\"%s\"\n", 
 								rve->fpos.s_line, rve->fpos.s_col,
 								rve->fpos.e_line, rve->fpos.e_col,
 								op, rve->left.rve->left.rval.v.s.s);
 					else
-						DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
+						LM_DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
 								" op%d(<string>, $v) -> (str)$v\n",
 								rve->fpos.s_line, rve->fpos.s_col,
 								rve->fpos.e_line, rve->fpos.e_col, op);
 				}else{
-					DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
+					LM_DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
 							" op%d(<string>, $v) -> $v\n",
 							rve->fpos.s_line, rve->fpos.s_col,
 							rve->fpos.e_line, rve->fpos.e_col, op);
@@ -3493,13 +3481,13 @@ static int rve_optimize(struct rval_expr* rve)
 		rv=0;
 		trv=&rve->left.rval;
 		if (trv->type==RV_INT)
-			DBG("FIXUP RVE (%d,%d-%d,%d): optimized constant int rve "
+			LM_DBG("FIXUP RVE (%d,%d-%d,%d): optimized constant int rve "
 					"(old op %d) to %d\n",
 					rve->fpos.s_line, rve->fpos.s_col,
 					rve->fpos.e_line, rve->fpos.e_col,
 					op, (int)trv->v.l);
 		else if (trv->type==RV_STR)
-			DBG("FIXUP RVE (%d,%d-%d,%d): optimized constant str rve "
+			LM_DBG("FIXUP RVE (%d,%d-%d,%d): optimized constant str rve "
 					"(old op %d) to \"%.*s\"\n",
 					rve->fpos.s_line, rve->fpos.s_col,
 					rve->fpos.e_line, rve->fpos.e_col,
@@ -3538,7 +3526,7 @@ static int rve_optimize(struct rval_expr* rve)
 				if (rve_replace_with_ct_rv(rve->right.rve, rv)<0)
 					goto error;
 				rve->op=RVE_IPLUS_OP;
-				DBG("FIXUP RVE (%d,%d-%d,%d): optimized $v - a into "
+				LM_DBG("FIXUP RVE (%d,%d-%d,%d): optimized $v - a into "
 						"$v + (%d)\n",
 						rve->fpos.s_line, rve->fpos.s_col,
 						rve->fpos.e_line, rve->fpos.e_col,
@@ -3553,12 +3541,12 @@ static int rve_optimize(struct rval_expr* rve)
 			l_type=rve_guess_type(rve->left.rve);
 			if (l_type==RV_INT){
 				rve->op=RVE_IPLUS_OP;
-				DBG("FIXUP RVE (%d,%d-%d,%d): changed + into integer plus\n",
+				LM_DBG("FIXUP RVE (%d,%d-%d,%d): changed + into integer plus\n",
 						rve->fpos.s_line, rve->fpos.s_col,
 						rve->fpos.e_line, rve->fpos.e_col);
 			}else if (l_type==RV_STR){
 				rve->op=RVE_CONCAT_OP;
-				DBG("FIXUP RVE (%d,%d-%d,%d): changed + into string concat\n",
+				LM_DBG("FIXUP RVE (%d,%d-%d,%d): changed + into string concat\n",
 						rve->fpos.s_line, rve->fpos.s_col,
 						rve->fpos.e_line, rve->fpos.e_col);
 			}
@@ -3569,13 +3557,13 @@ static int rve_optimize(struct rval_expr* rve)
 			l_type=rve_guess_type(rve->left.rve);
 			if (l_type==RV_INT){
 				rve->op=(rve->op==RVE_EQ_OP)?RVE_IEQ_OP:RVE_IDIFF_OP;
-				DBG("FIXUP RVE (%d,%d-%d,%d): changed ==/!= into integer"
+				LM_DBG("FIXUP RVE (%d,%d-%d,%d): changed ==/!= into integer"
 						" ==/!=\n",
 						rve->fpos.s_line, rve->fpos.s_col,
 						rve->fpos.e_line, rve->fpos.e_col);
 			}else if (l_type==RV_STR){
 				rve->op=(rve->op==RVE_EQ_OP)?RVE_STREQ_OP:RVE_STRDIFF_OP;
-				DBG("FIXUP RVE (%d,%d-%d,%d): changed ==/!= into string"
+				LM_DBG("FIXUP RVE (%d,%d-%d,%d): changed ==/!= into string"
 						" ==/!=\n",
 						rve->fpos.s_line, rve->fpos.s_col,
 						rve->fpos.e_line, rve->fpos.e_col);
@@ -3606,7 +3594,7 @@ static int rve_optimize(struct rval_expr* rve)
 					   or a combination of them */
 					if ((rve->op==RVE_PLUS_OP) &&
 						(rve_guess_type(tmp_rve.left.rve)!=RV_STR)){
-						DBG("RVE optimization failed (%d,%d-%d,%d): cannot "
+						LM_DBG("RVE optimization failed (%d,%d-%d,%d): cannot "
 							"optimize +(+($v, a), b) when typeof(a)==INT\n",
 							rve->fpos.s_line, rve->fpos.s_col,
 							rve->fpos.e_line, rve->fpos.e_col);
@@ -3625,13 +3613,13 @@ static int rve_optimize(struct rval_expr* rve)
 					rve->left.rve=rve->left.rve->left.rve;
 					trv=&rve->right.rve->left.rval;
 					if (trv->type==RV_INT)
-						DBG("FIXUP RVE (%d,%d-%d,%d): optimized int rve: "
+						LM_DBG("FIXUP RVE (%d,%d-%d,%d): optimized int rve: "
 								"op(op($v, a), b) with op($v, %d); op=%d\n",
 								rve->fpos.s_line, rve->fpos.s_col,
 								rve->fpos.e_line, rve->fpos.e_col,
 								(int)trv->v.l, rve->op);
 					else if (trv->type==RV_STR)
-						DBG("FIXUP RVE (%d,%d-%d,%d): optimized str rve "
+						LM_DBG("FIXUP RVE (%d,%d-%d,%d): optimized str rve "
 								"op(op($v, a), b) with op($v, \"%.*s\");"
 								" op=%d\n",
 								rve->fpos.s_line, rve->fpos.s_col,
@@ -3663,13 +3651,13 @@ static int rve_optimize(struct rval_expr* rve)
 					rv=0;
 					trv=&rve->left.rve->left.rval;
 					if (trv->type==RV_INT)
-						DBG("FIXUP RVE (%d,%d-%d,%d): optimized int rve: "
+						LM_DBG("FIXUP RVE (%d,%d-%d,%d): optimized int rve: "
 								"op(op(a, $v), b) with op(%d, $v); op=%d\n",
 								rve->fpos.s_line, rve->fpos.s_col,
 								rve->fpos.e_line, rve->fpos.e_col,
 								(int)trv->v.l, rve->op);
 					else if (trv->type==RV_STR)
-						DBG("FIXUP RVE (%d,%d-%d,%d): optimized str rve "
+						LM_DBG("FIXUP RVE (%d,%d-%d,%d): optimized str rve "
 								"op(op(a, $v), b) with op(\"%.*s\", $v);"
 								" op=%d\n",
 								rve->fpos.s_line, rve->fpos.s_col,
@@ -3709,13 +3697,13 @@ static int rve_optimize(struct rval_expr* rve)
 					rve->right.rve=rve->right.rve->left.rve;
 					trv=&rve->left.rve->left.rval;
 					if (trv->type==RV_INT)
-						DBG("FIXUP RVE (%d,%d-%d,%d): optimized int rve: "
+						LM_DBG("FIXUP RVE (%d,%d-%d,%d): optimized int rve: "
 								"op(a, op($v, b)) with op(%d, $v); op=%d\n",
 								rve->fpos.s_line, rve->fpos.s_col,
 								rve->fpos.e_line, rve->fpos.e_col,
 								(int)trv->v.l, rve->op);
 					else if (trv->type==RV_STR)
-						DBG("FIXUP RVE (%d,%d-%d,%d): optimized str rve "
+						LM_DBG("FIXUP RVE (%d,%d-%d,%d): optimized str rve "
 								"op(a, op($v, b)) with op(\"%.*s\", $v);"
 								" op=%d\n",
 								rve->fpos.s_line, rve->fpos.s_col,
@@ -3733,7 +3721,7 @@ static int rve_optimize(struct rval_expr* rve)
 					if ((rve->op==RVE_PLUS_OP) &&
 						(rve_guess_type(tmp_rve.left.rve) != 
 						 	rve_guess_type(tmp_rve.right.rve))){
-						DBG("RVE optimization failed (%d,%d-%d,%d): cannot "
+						LM_DBG("RVE optimization failed (%d,%d-%d,%d): cannot "
 								"optimize +(a, +(b, $v)) when "
 								"typeof(a)!=typeof(b)\n",
 								rve->fpos.s_line, rve->fpos.s_col,
@@ -3753,13 +3741,13 @@ static int rve_optimize(struct rval_expr* rve)
 					rve->right.rve=rve->right.rve->right.rve;
 					trv=&rve->left.rve->left.rval;
 					if (trv->type==RV_INT)
-						DBG("FIXUP RVE (%d,%d-%d,%d): optimized int rve: "
+						LM_DBG("FIXUP RVE (%d,%d-%d,%d): optimized int rve: "
 								"op(a, op(b, $v)) with op(%d, $v); op=%d\n",
 								rve->fpos.s_line, rve->fpos.s_col,
 								rve->fpos.e_line, rve->fpos.e_col,
 								(int)trv->v.l, rve->op);
 					else if (trv->type==RV_STR)
-						DBG("FIXUP RVE (%d,%d-%d,%d): optimized str rve "
+						LM_DBG("FIXUP RVE (%d,%d-%d,%d): optimized str rve "
 								"op(a, op(b, $v)) with op(\"%.*s\", $v);"
 								" op=%d\n",
 								rve->fpos.s_line, rve->fpos.s_col,
diff --git a/rvalue.h b/rvalue.h
index c0c2e0e..b8e8315 100644
--- a/rvalue.h
+++ b/rvalue.h
@@ -16,21 +16,12 @@
  
 /**
  * @file 
- * @brief SIP-router core :: rvalue expressions
+ * @brief Kamailio core :: rvalue expressions
  * @ingroup core
  * Module: \ref core
+ * @author andrei
  */
  
-/* 
- * History:
- * --------
- *  2008-11-30  initial version (andrei)
- *  2009-04-28  added string and interger versions for the EQ and DIFF
- *              operators (andrei)
- *  2009-05-05  casts operator for int & string (andrei)
- *  2010-03-16  space for an int2str result inside rval_cache (andrei)
- */
-
 #ifndef _rvalue_h_
 #define _rvalue_h_
 
diff --git a/sched_yield.h b/sched_yield.h
index 45030c5..1f8546d 100644
--- a/sched_yield.h
+++ b/sched_yield.h
@@ -1,10 +1,6 @@
 /*
  * sched_yield wrapper
  *
- * $Id$
- *
- * 
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -19,14 +15,14 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/*
- *
- *History:
- *--------
- *  2007-07-13  splitted from fastlock.h (andrei)
+/*!
+ * \file
+ * \brief Kamailio core :: Sched_yield wrapper
+ * \ingroup core
+ * Module: \ref core
+ * \author andrei
  */
 
-
 #ifndef _sched_yield_h
 #define _sched_yield_h
 
diff --git a/script_cb.c b/script_cb.c
index bf2af24..5e1547e 100644
--- a/script_cb.c
+++ b/script_cb.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Script callbacks -- they add the ability to register callback
  * functions which are always called when script for request
  * processing is entered or left
@@ -8,19 +6,14 @@
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -29,18 +22,15 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2003-03-29  cleaning pkg allocation introduced (jiri)
- *  2003-03-19  replaced all mallocs/frees w/ pkg_malloc/pkg_free (andrei)
- *  2005-02-13  script callbacks devided into request and reply types (bogdan)
- *  2009-06-01  Added pre- and post-script callback support for all types
- *		of route blocks. (Miklos)
  */
 
 /*!
  * \file
- * \brief SIP-router core :: 
+ * \brief Kamailio core :: Script callbacks 
+ *
+ * Script callbacks adds the ability to register callback
+ * functions which are always called when script for request
+ * processing is entered or left
  * \ingroup core
  * Module: \ref core
  */
diff --git a/script_cb.h b/script_cb.h
index 65361a0..ece69b8 100644
--- a/script_cb.h
+++ b/script_cb.h
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,11 +17,12 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2005-02-13  script callbacks devided into request and reply types (bogdan)
- *  2009-06-01  Added pre- and post-script callback support for all types
- *		of route blocks. (Miklos)
+ */
+/*!
+ * \file
+ * \brief Kamailio core :: Script callbacks
+ * \ingroup core
+ * Module: \ref core
  */
 
 #ifndef _SCRIPT_CB_H_
diff --git a/sctp_core.c b/sctp_core.c
index a27f603..b529e83 100644
--- a/sctp_core.c
+++ b/sctp_core.c
@@ -1,6 +1,4 @@
-/**
- * $Id$
- *
+/*
  * Copyright (C) 2013 Daniel-Constantin Mierla (asipto.com)
  *
  * This file is part of Kamailio, a free SIP server.
@@ -18,6 +16,13 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+/*!
+ * \file
+ * \brief Kamailio core :: SCTP support
+ * \ingroup core
+ * Module: \ref core
+ */
+
 #include "sctp_core.h"
 
 /**
diff --git a/sctp_core.h b/sctp_core.h
index 88e0470..c6b65b0 100644
--- a/sctp_core.h
+++ b/sctp_core.h
@@ -1,6 +1,4 @@
 /**
- * $Id$
- *
  * Copyright (C) 2013 Daniel-Constantin Mierla (asipto.com)
  *
  * This file is part of Kamailio, a free SIP server.
@@ -17,6 +15,13 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
+/*!
+ * \file
+ * \brief Kamailio core :: SCTP support
+ * \ingroup core
+ * Module: \ref core
+ * Copyright (C) 2013 Daniel-Constantin Mierla (asipto.com)
+ */
 
 #ifndef __sctp_core_h__
 #define __sctp_core_h__
diff --git a/select.c b/select.c
index 3b605d5..1bf1e6a 100644
--- a/select.c
+++ b/select.c
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2005-2006 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,21 +17,11 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2005-12-19  select framework (mma)
- *  2006-01-19  multiple nested calls, IS_ALIAS -> NESTED flag renamed (mma)
- *              DIVERSION flag checked
- *  2006-02-26  don't free str when changing type STR -> DIVERSION (mma)
- *				it can't be freeable sometimes (e.g. xlog's select)
- *	2006-05-30  parse_select (mma)
- *	2006-06-02  shm_parse_select (mma)
- *
  */
 
 /*!
  * \file
- * \brief SIP-router core :: 
+ * \brief Kamailio core :: The Select framework
  * \ingroup core
  * Module: \ref core
  */
@@ -55,19 +38,19 @@
 #include "mem/mem.h"
 #include "mem/shm_mem.h"
 
-/*
+/**
  * The main parser table list placeholder
  * at startup use core table, modules can
  * add their own via register_select_table call
  */
 static select_table_t *select_list = &select_core_table;
 
-/* the level of the select call that is beeing evaluated
+/** the level of the select call that is beeing evaluated
  * by the child process
  */
 int select_level = 0;
 
-/* pointer to the SIP uri beeing processed.
+/** pointer to the SIP uri beeing processed.
  * Nested function calls can pass information to each
  * other using this pointer. Only for performace reasons.
  * (Miklos)
@@ -116,7 +99,7 @@ int w_parse_select(char**p, select_t* sel)
 	sel->n=0;
 	while (isalpha((unsigned char)*(*p))) {
 		if (sel->n > MAX_SELECT_PARAMS -2) {
-			ERR("parse_select: select depth exceeds max\n");
+			LM_ERR("select depth exceeds max\n");
 			goto error;
 		}
 		name.s=(*p);
@@ -125,7 +108,7 @@ int w_parse_select(char**p, select_t* sel)
 		name.len=(*p)-name.s;
 		sel->params[sel->n].type=SEL_PARAM_STR;
 		sel->params[sel->n].v.s=name;
-		DBG("parse_select: part %d: %.*s\n", sel->n, sel->params[sel->n].v.s.len, sel->params[sel->n].v.s.s);
+		LM_DBG("part %d: %.*s\n", sel->n, sel->params[sel->n].v.s.len, sel->params[sel->n].v.s.s);
 		sel->n++;
 		if (*(*p)=='[') {
 			(*p)++; 
@@ -135,33 +118,33 @@ int w_parse_select(char**p, select_t* sel)
 				name.s=(*p);
 				while ((*(*p)!='\0') && (*(*p)!='"')) (*p)++;
 				if (*(*p)!='"') {
-					ERR("parse_select: end of string is missing\n");
+					LM_ERR("end of string is missing\n");
 					goto error;
 				}
 				name.len=(*p)-name.s;
 				if (*((*p)-1)=='\\') name.len--;
 				(*p)++;
 				if (*(*p)!=']') {
-					ERR("parse_select: invalid string index, no closing ]\n");
+					LM_ERR("invalid string index, no closing ]\n");
 					goto error;
 				};
 				(*p)++;
 				sel->params[sel->n].type=SEL_PARAM_STR;
 				sel->params[sel->n].v.s=name;
-				DBG("parse_select: part %d: [\"%.*s\"]\n", sel->n, sel->params[sel->n].v.s.len, sel->params[sel->n].v.s.s);
+				LM_DBG("part %d: [\"%.*s\"]\n", sel->n, sel->params[sel->n].v.s.len, sel->params[sel->n].v.s.s);
 			} else {
 				name.s=(*p);
 				if (*(*p)=='-') (*p)++;
 				while (isdigit((unsigned char)*(*p))) (*p)++;
 				name.len=(*p)-name.s;
 				if (*(*p)!=']') {
-					ERR("parse_select: invalid index, no closing ]\n");
+					LM_ERR("invalid index, no closing ]\n");
 					goto error;
 				};
 				(*p)++;
 				sel->params[sel->n].type=SEL_PARAM_INT;
 				sel->params[sel->n].v.i=atoi(name.s);
-				DBG("parse_select: part %d: [%d]\n", sel->n, sel->params[sel->n].v.i);
+				LM_DBG("part %d: [%d]\n", sel->n, sel->params[sel->n].v.i);
 			}
 			sel->n++;
 		}
@@ -169,12 +152,12 @@ int w_parse_select(char**p, select_t* sel)
 		(*p)++;
 	};
 	if (sel->n==0) {
-		ERR("parse_select: invalid select '%.*s'\n", (int)(*p - select_name), select_name);
+		LM_ERR("invalid select '%.*s'\n", (int)(*p - select_name), select_name);
 		goto error;
 	};
-	DBG("parse_select: end, total elements: %d, calling resolve_select\n", sel->n);
+	LM_DBG("end, total elements: %d, calling resolve_select\n", sel->n);
 	if (resolve_select(sel)<0) {
-		ERR("parse_select: error while resolve_select '%.*s'\n", (int)(*p - select_name), select_name);
+		LM_ERR("error while resolve_select '%.*s'\n", (int)(*p - select_name), select_name);
 		goto error;
 	}
 	return 0;
@@ -220,7 +203,7 @@ int parse_select (char** p, select_t** s)
 	
 	sel=(select_t*)pkg_malloc(sizeof(select_t));
 	if (!sel) {
-		ERR("parse_select: no free memory\n");
+		LM_ERR("no free memory\n");
 		return -1;
 	}
 	memset(sel, 0, sizeof(select_t));
@@ -250,7 +233,7 @@ int shm_parse_select (char** p, select_t** s)
 	
 	sel=(select_t*)shm_malloc(sizeof(select_t));
 	if (!sel) {
-		ERR("parse_select: no free shared memory\n");
+		LM_ERR("no free shared memory\n");
 		return -1;
 	}
 	if (w_parse_select(p, sel)<0) {
@@ -277,10 +260,10 @@ int resolve_select(select_t* s)
 		accept = 0;
 		switch (s->params[param_idx].type) {
 		case SEL_PARAM_STR:
-			DBG("resolve_select: '%.*s'\n", s->params[param_idx].v.s.len, s->params[param_idx].v.s.s);
+			LM_DBG("'%.*s'\n", s->params[param_idx].v.s.len, s->params[param_idx].v.s.s);
 			break;
 		case SEL_PARAM_INT:
-			DBG("resolve_select: [%d]\n", s->params[param_idx].v.i);
+			LM_DBG("[%d]\n", s->params[param_idx].v.i);
 			break;
 		default:
 			/* just to avoid the warning */
@@ -426,7 +409,7 @@ int run_select(str* res, select_t* s, struct sip_msg* msg)
 		BUG("Select structure has not been resolved\n");
 		return -1;
 	}
-	DBG("Calling SELECT %p \n", s->f);
+	LM_DBG("Calling SELECT %p\n", s->f);
 
 	/* reset the uri pointer */
 	select_uri_p = NULL;
@@ -464,7 +447,7 @@ int register_select_table(select_row_t* mod_tab)
 	select_table_t* t;
 	t=(select_table_t*)pkg_malloc(sizeof(select_table_t));
 	if (!t) {
-		ERR("No memory for new select_table structure\n");
+		LM_ERR("No memory for new select_table structure\n");
 		return -1;
 	}
 
diff --git a/select.h b/select.h
index 3ed5c5b..5d639d6 100644
--- a/select.h
+++ b/select.h
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2005-2006 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,10 +17,13 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2005-12-19  select framework (mma)
- *  2006-01-19  multiple nested calls, IS_ALIAS -> NESTED flag renamed (mma)
+ */
+/*!
+ * \file
+ * \brief Kamailio core :: Selcct Framework
+ * \author mma
+ * \ingroup core
+ * Module: \ref core
  */
 
  
diff --git a/select_buf.c b/select_buf.c
index 87fc73b..481c80c 100644
--- a/select_buf.c
+++ b/select_buf.c
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2005-2006 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,17 +17,13 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *	2006-06-16  static buffer for select results (mma)
- *	            each process owns a separate space
- *	            each request starts using the buffer from the start
- *
  */
 
 /*!
  * \file
- * \brief SIP-router core :: 
+ * \brief Kamailio core :: static buffer for select results (mma)
+ *	            each process owns a separate space
+ *	            each request starts using the buffer from the start
  * \ingroup core
  * Module: \ref core
  */
diff --git a/select_buf.h b/select_buf.h
index 6543fbf..d8b7c54 100644
--- a/select_buf.h
+++ b/select_buf.h
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2005-2006 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,12 +17,14 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *	2006-06-16  static buffer for select results (mma)
- *	            each process owns a separate space
- *	            each request starts using the buffer from the start
- *
+ */
+
+/*!
+ * \file
+ * \brief Kamailio core :: Select result buffers
+ * \author mma
+ * \ingroup core
+ * Module: \ref core
  */
 
 #ifndef SELECT_BUFFER_H
@@ -37,7 +32,7 @@
 
 #include "str.h"
 
-/*
+/**
  * Request for space from buffer
  *
  * Returns:  NULL  memory allocation failure (no more space)
@@ -46,11 +41,10 @@
 
 char* get_static_buffer(int req_size);
 
-/* Internal function - called before request is going to be processed
+/** Internal function - called before request is going to be processed
  *
  * Reset offset to unused space
  */
-
 int reset_static_buffer(void);
 
 int str_to_static_buffer(str* res, str* s);
diff --git a/select_core.c b/select_core.c
index 7a869d0..d16f59d 100644
--- a/select_core.c
+++ b/select_core.c
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2005-2006 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,17 +17,11 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2005-12-19  select framework, basic core functions (mma)
- *  2006-01-19  multiple nested calls, IS_ALIAS -> NESTED flag renamed (mma)
- *  2006-02-17  fixup call for select_anyhdr (mma)
- *  2007-01-26  date, identity, identity_info support added (gergo)
  */
 
 /*!
  * \file
- * \brief SIP-router core :: 
+ * \brief Kamailio core :: select framework, basic core functions (mma)
  * \ingroup core
  * Module: \ref core
  */
@@ -234,7 +221,7 @@ SELECT_uri_header(rpid)
 int parse_contact_header( struct sip_msg *msg)
 {
         if ( !msg->contact && ( parse_headers(msg,HDR_CONTACT_F,0)==-1 || !msg->contact)) {
-                DBG("bad msg or missing CONTACT header\n");
+                LM_DBG("bad msg or missing CONTACT header\n");
                 return -1;
         }
 
@@ -539,14 +526,14 @@ int select_sdp_line(str* res, select_t* sel, struct sip_msg* msg)
 		if (sel->n < 5) return -1;
 
 		if (sel->params[4].type != SEL_PARAM_STR) {
-			ERR("wrong parameter type");
+			LM_ERR("wrong parameter type");
 			return -1;
 		}
 		if ((sel->params[4].v.s.len < 1) ||
 			(sel->params[4].v.s.len > 2) ||
 			((sel->params[4].v.s.len == 2) && (sel->params[4].v.s.s[1] != '='))
 		) {
-			ERR("wrong sdp line format: %.*s\n",
+			LM_ERR("wrong sdp line format: %.*s\n",
 				sel->params[4].v.s.len, sel->params[4].v.s.s);
 			return -1;
 		}
@@ -568,7 +555,7 @@ int select_sdp_line(str* res, select_t* sel, struct sip_msg* msg)
 			/* the requested SDP line is found, return its value */
 			buf++;
 			if ((buf >= buf_end) || (*buf != '=')) {
-				ERR("wrong SDP line format\n");
+				LM_ERR("wrong SDP line format\n");
 				return -1;
 			}
 			buf++;
@@ -578,14 +565,14 @@ int select_sdp_line(str* res, select_t* sel, struct sip_msg* msg)
 				line_end++;
 
 			if (line_end >= buf_end) {
-				ERR("wrong SDP line format\n");
+				LM_ERR("wrong SDP line format\n");
 				return -1;
 			}
 			line_end--;
 			if (*line_end == '\r') line_end--;
 
 			if (line_end < buf) {
-				ERR("wrong SDP line format\n");
+				LM_ERR("wrong SDP line format\n");
 				return -1;
 			}
 
@@ -634,7 +621,7 @@ int select_anyheader(str* res, select_t* s, struct sip_msg* msg)
 			s->params[2].v.s.s[s->params[2].v.s.len]=':';
 			if (parse_hname2(s->params[2].v.s.s,s->params[2].v.s.s+(s->params[2].v.s.len<3?4:s->params[2].v.s.len+1),
 						&hdr)==0) {
-				ERR("select_anyhdr:fixup_call:parse error\n");
+				LM_ERR("fixup_call:parse error\n");
 				return -1;
 			}
 			s->params[2].v.s.s[s->params[2].v.s.len]=c;
@@ -667,7 +654,7 @@ int select_anyheader(str* res, select_t* s, struct sip_msg* msg)
 
 	/* we need to be sure we have parsed all headers */
 	if (!msg->eoh && (parse_headers(msg,HDR_EOH_F,0)==-1 || !msg->eoh)) {
-		ERR("bad msg while parsing to EOH \n");
+		LM_ERR("bad msg while parsing to EOH \n");
 		return -1;
 	}
 	for (hf=msg->headers; hf; hf=hf->next) {
@@ -965,7 +952,7 @@ int select_any_params(str* res, select_t* s, struct sip_msg* msg)
 	if (!res->len) return -1;
 
 	if (search_param(*res, wanted->s, wanted->len, res) <= 0) {
-		DBG("SELECT ...uri.params.%s NOT FOUND !\n", wanted->s);
+		LM_DBG("uri.params.%s NOT FOUND !\n", wanted->s);
 		return -1;
 	} else {
 		return (res->len) ? 0 : 1;
@@ -975,17 +962,17 @@ int select_any_params(str* res, select_t* s, struct sip_msg* msg)
 int select_event(str* res, select_t* s, struct sip_msg* msg)
 {
 	if (!msg->event && parse_headers(msg, HDR_EVENT_F, 0) == -1) {
-		ERR("Error while searching Event header field\n");
+		LM_ERR("Error while searching Event header field\n");
 		return -1;
 	}
 
 	if (!msg->event) {
-		DBG("Event header field not found\n");
+		LM_DBG("Event header field not found\n");
 		return -1;
 	}
 
 	if (parse_event(msg->event) < 0) {
-		ERR("Error while parsing Event header field\n");
+		LM_ERR("Error while parsing Event header field\n");
 		return -1;
 	}
 
@@ -998,12 +985,12 @@ int select_event(str* res, select_t* s, struct sip_msg* msg)
 static int parse_rr_header(struct sip_msg *msg)
 {
         if ( !msg->record_route && ( parse_headers(msg,HDR_RECORDROUTE_F,0) == -1)) {
-                ERR("bad msg or missing Record-Route header\n");
+                LM_ERR("bad msg or missing Record-Route header\n");
                 return -1;
         }
 
 	if (!msg->record_route) {
-		DBG("No Record-Route header field found\n");
+		LM_DBG("No Record-Route header field found\n");
 		return -1;
 	}
 
@@ -1069,12 +1056,12 @@ int select_rr_params(str* res, select_t* s, struct sip_msg* msg)
 static inline struct cseq_body* sel_parse_cseq(struct sip_msg* msg)
 {
         if (!msg->cseq && (parse_headers(msg, HDR_CSEQ_F, 0) == -1)) {
-                ERR("Unable to parse CSeq header\n");
+                LM_ERR("Unable to parse CSeq header\n");
                 return 0;
         }
 
 	if (!msg->cseq) {
-		DBG("No CSeqheader field found\n");
+		LM_DBG("No CSeq header field found\n");
 		return 0;
 	}
 
@@ -1235,7 +1222,7 @@ int select_nameaddr_name(str* res, select_t* s, struct sip_msg* msg)
 	
 	p=find_not_quoted(res, '<');
 	if (!p) {
-		DBG("select_nameaddr_name: no < found, whole string is uri\n");
+		LM_DBG("no < found, whole string is uri\n");
 		res->len=0;
 		return 1;
 	}
@@ -1251,7 +1238,7 @@ int select_nameaddr_uri(str* res, select_t* s, struct sip_msg* msg)
 	
 	p=find_not_quoted(res, '<');
 	if (!p) {
-		DBG("select_nameaddr_uri: no < found, string up to first semicolon is uri\n");
+		LM_DBG("no < found, string up to first semicolon is uri\n");
 		p = q_memchr(res->s, ';', res->len);
 		if (p)
 			res->len = p-res->s;
@@ -1263,7 +1250,7 @@ int select_nameaddr_uri(str* res, select_t* s, struct sip_msg* msg)
 	
 	p=find_not_quoted(res, '>');
 	if (!p) {
-		ERR("select_nameaddr_uri: no > found, invalid nameaddr value\n");
+		LM_ERR("no > found, invalid nameaddr value\n");
 		return -1;
 	}
 
@@ -1283,7 +1270,7 @@ int select_nameaddr_params(str* res, select_t* s, struct sip_msg* msg)
 		res->s=p +1;
 		p=find_not_quoted(res, '>');
 		if (!p) {
-			ERR("select_nameaddr_params: no > found, invalid nameaddr value\n");
+			LM_ERR("no > found, invalid nameaddr value\n");
 			return -1;
 		}
 		res->len=res->len - (p-res->s) -1;
@@ -1365,7 +1352,7 @@ int select_ip_port(str* res, select_t* s, struct sip_msg* msg)
 				break;
 
 			default:
-				ERR("BUG: select_ip_port: Unknown transport protocol\n");
+				LM_ERR("Unknown transport protocol\n");
 				return -1;
 			}
 		}
diff --git a/select_core.h b/select_core.h
index a3192e4..7f03a92 100644
--- a/select_core.h
+++ b/select_core.h
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2005-2006 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,13 +17,16 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * --------
- *  2005-12-19  select framework, basic core functions (mma)
- *  2006-01-19  multiple nested calls, IS_ALIAS -> NESTED flag renamed (mma)
- *  2007-01-26  date, identity, identity_info support added (gergo)
  */
 
+/*!
+* \file
+* \brief Kamailio core :: Select framework, basic core functions
+* \author mma
+* \ingroup core
+* Module: \ref core
+*/
+
  
 #ifndef _SELECT_CORE_H
 #define _SELECT_CORE_H
diff --git a/ser_time.h b/ser_time.h
index 70da002..e4a0000 100644
--- a/ser_time.h
+++ b/ser_time.h
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- * 
  * time related functions
  *
  * Copyright (C) 2006 iptelorg GmbH
@@ -17,9 +15,13 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/* History:
- * --------
- *  2008-07-16  initial version (andrei)
+
+/*!
+ * \file
+ * \brief Kamailio core :: Time related functions
+ * \author andrei
+ * \ingroup core
+ * Module: \ref core
  */
 #ifndef _ser_time_h
 #define _ser_time_h
diff --git a/shm_init.c b/shm_init.c
index d981ae5..19e6117 100644
--- a/shm_init.c
+++ b/shm_init.c
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- * 
  * Copyright (C) 2010 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -15,14 +13,13 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/*
- * shm_init.c
+
+/*!
+ * \file
+ * \brief Kamailio core :: Shared memory initialization
+ * \ingroup core
+ * Module: \ref core
  */
-/*
- * History:
- * --------
- *  2010-01-10  initial version (andrei)
-*/
 
 #include "shm_init.h"
 #include "mem/mem.h"
diff --git a/shm_init.h b/shm_init.h
index 1e0d76f..60b233f 100644
--- a/shm_init.h
+++ b/shm_init.h
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- * 
  * Copyright (C) 2010 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -15,13 +13,12 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/*
- * shm_init.h
- */
-/*
- * History:
- * --------
- *  2010-01-10  initial version (andrei)
+/*!
+* \file
+* \brief Kamailio core :: Shared memory initialization
+* \ingroup core
+* \author andrei
+* Module: \ref core
 */
 
 #ifndef __shm_init_h
diff --git a/signals.c b/signals.c
index edeef00..374a3dd 100644
--- a/signals.c
+++ b/signals.c
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
-  * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,17 +17,10 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/*
- * Handle the signals
- *
- * History:
- * --------
- *  2005-10-05  split from main.c  (andrei)
- */
 
 /*!
  * \file
- * \brief SIP-router core :: 
+ * \brief Kamailio core :: Handle the signals
  * \ingroup core
  * Module: \ref core
  */
diff --git a/signals.h b/signals.h
index 70681a0..88025b4 100644
--- a/signals.h
+++ b/signals.h
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,12 +17,9 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/*
- * Handle the signals
- *
- * History:
- * --------
- *  2005-10-05  split from main.c  (andrei)
+/*! \file
+ * \brief Kamailio core :: Handle the signals
+ * \ingroup core
  */
 
 
diff --git a/sip-router.8 b/sip-router.8
index 3bc247d..8dd5399 100644
--- a/sip-router.8
+++ b/sip-router.8
@@ -71,19 +71,19 @@ Turns on via host checking when forwarding replies.
 .TP
 .BI \-d
 Turns on debugging, multiple
-.B -d
+.B \-d
 increase the debug level.
 .TP
 .BI \-D
 Control how daemonize is done:
 .br
-.B -D
+.B \-D
 - do not fork (almost) anyway (run in foreground, doesn't fork into daemon mode);
 .br
-.B -DD
+.B \-DD
 - do not daemonize creator (main process is not daemonized);
 .br
-.B -DDD
+.B \-DDD
 - daemonize (default)
 .TP
 .BI \-E
diff --git a/sip_msg_clone.c b/sip_msg_clone.c
index b9c413c..e736b7b 100644
--- a/sip_msg_clone.c
+++ b/sip_msg_clone.c
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- * 
  * Copyright (C) 2009 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -15,16 +13,8 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/*
- * sip_msg_clone.c - moved sip msg clone-in-shm functions from tm
- */
-/*
- * History:
- * --------
- *  2009-07-22  initial version: functions moved from tm/sip_msg.c (andrei)
-*/
 
-/** SIP-router core :: sip message shared memory cloner.
+/** Kamailio core :: sip message shared memory cloner.
  * @file
  * @ingroup core
  * Module: @ref core
diff --git a/sip_msg_clone.h b/sip_msg_clone.h
index e823af6..7995e4f 100644
--- a/sip_msg_clone.h
+++ b/sip_msg_clone.h
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- * 
  * Copyright (C) 2009 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -15,14 +13,6 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/*
- * /home/andrei/sr.git/sip_msg_clone.h
- */
-/*
- * History:
- * --------
- *  2009-07-22  initial version (andrei)
-*/
 
 #ifndef __sip_msg_clone_h
 #define __sip_msg_clone_h
diff --git a/sock_ut.c b/sock_ut.c
index da46750..b1da20d 100644
--- a/sock_ut.c
+++ b/sock_ut.c
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- * 
  * Copyright (C) 2010 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -15,15 +13,11 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/** various socket related functions.
+
+/** Kamailio core :: various socket related functions.
  * @file sock_ut.c
  * @ingroup: core 
  */
-/*
- * History:
- * --------
- *  2010-08-09  initial version (andrei)
-*/
 
 #include "sock_ut.h"
 
diff --git a/sock_ut.h b/sock_ut.h
index e9613d1..ec2d24c 100644
--- a/sock_ut.h
+++ b/sock_ut.h
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- * 
  * Copyright (C) 2010 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -15,7 +13,7 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/** various socket related functions.
+/*! \brief Kamailio core :: various socket related functions.
  * @file sock_ut.h
  * @ingroup: core 
  */
diff --git a/socket_info.c b/socket_info.c
index 443e0a4..75d09da 100644
--- a/socket_info.c
+++ b/socket_info.c
@@ -1,23 +1,17 @@
 
-/* $Id$
- *
+/* 
  * find & manage listen addresses 
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -26,26 +20,13 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/*
- * This file contains code that initializes and handles ser listen addresses
- * lists (struct socket_info). It is used mainly on startup.
- * 
- * History:
- * --------
- *  2003-10-22  created by andrei
- *  2004-10-10  added grep_sock_info (andrei)
- *  2004-11-08  added find_si (andrei)
- *  2007-08-23  added detection for INADDR_ANY types of sockets (andrei)
- *  2008-08-08  sctp support (andrei)
- *  2008-08-15  support for handling sctp multihomed sockets (andrei)
- *  2008-10-15  fixed protocol list iteration when some protocols are
- *               compile time disabled (andrei)
- */
-
 
 /*!
  * \file
- * \brief SIP-router core :: 
+ * \brief Kamailio core :: find & manage listen addresses 
+ *
+ * This file contains code that initializes and handles Kamailio listen addresses
+ * lists (struct socket_info). It is used mainly on startup.
  * \ingroup core
  * Module: \ref core
  */
@@ -574,16 +555,14 @@ retry:
 		if (list==0) /* disabled or unknown protocol */
 			continue;
 		for (si=*list; si; si=si->next){
-			DBG("grep_sock_info - checking if host==us: %d==%d &&"
-					" [%.*s] == [%.*s]\n",
+			LM_DBG("checking if host==us: %d==%d && [%.*s] == [%.*s]\n",
 						hname.len,
 						si->name.len,
 						hname.len, hname.s,
 						si->name.len, si->name.s
 				);
 			if (port) {
-				DBG("grep_sock_info - checking if port %d (advertise %d)"
-						" matches port %d\n",
+				LM_DBG("checking if port %d (advertise %d) matches port %d\n",
 						si->port_no, si->useinfo.port_no, port);
 				if (si->port_no!=port && si->useinfo.port_no!=port) {
 					continue;
@@ -594,7 +573,7 @@ retry:
 				goto found;
 			if(si->useinfo.name.s!=NULL)
 			{
-				DBG("grep_sock_info - checking advertise if host==us:"
+				LM_DBG("checking advertise if host==us:"
 						" %d==%d && [%.*s] == [%.*s]\n",
 						hname.len,
 						si->useinfo.name.len,
@@ -651,8 +630,7 @@ struct socket_info* grep_sock_info_by_port(unsigned short port,
 			continue;
 		
 		for (si=*list; si; si=si->next){
-			DBG("grep_sock_info_by_port - checking if port %d matches"
-					" port %d\n", si->port_no, port);
+			LM_DBG("checking if port %d matches port %d\n", si->port_no, port);
 			if (si->port_no==port) {
 				goto found;
 			}
@@ -1179,9 +1157,10 @@ int add_interfaces_via_netlink(char* if_name, int family, unsigned short port,
 			//if(! (ifaces[i].flags & IFF_UP) ) continue;
 
 			for(tmp = ifaces[i].addresses; tmp; tmp = tmp->next){
-				LM_DBG("\t in add_iface_via_netlink Name %s Address %s\n", ifaces[i].name, tmp->addr);
-		                /* match family */
-                                if (family == tmp->family){
+				LM_DBG("in add_iface_via_netlink Name %s Address %s\n",
+							ifaces[i].name, tmp->addr);
+					/* match family */
+					if (family == tmp->family){
 					/* check if loopback */
 					if (ifaces[i].flags & IFF_LOOPBACK){
 						LM_DBG("INTERFACE %s is loopback", ifaces[i].name);
@@ -1561,7 +1540,7 @@ static int fix_socket_list(struct socket_info **list, int* type_flags)
 	}
 	/* get ips & fill the port numbers*/
 #ifdef EXTRA_DEBUG
-	DBG("Listening on \n");
+	LM_DBG("Listening on\n");
 #endif
 	for (si=*list;si;si=si->next){
 		/* fix port number, port_no should be !=0 here */
diff --git a/socket_info.h b/socket_info.h
index 7ac4260..eec9dd4 100644
--- a/socket_info.h
+++ b/socket_info.h
@@ -1,22 +1,16 @@
-/* $Id$
- *
+/*
  * find & manage listen addresses 
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -25,14 +19,12 @@
  * along with this program; if not, write to" the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/*
- * This file contains code that initializes and handles ser listen addresses
+
+/*! \file
+ * \brief Kamailio core :: listen address
+ * This file contains code that initializes and handles Kamailio listen addresses
  * lists (struct socket_info). It is used mainly on startup.
  * 
- * History:
- * --------
- *  2003-10-22  created by andrei
- *  2008-08-08  sctp support (andrei)
  */
 
 
diff --git a/sr_compat.c b/sr_compat.c
index 02e0527..ced1aab 100644
--- a/sr_compat.c
+++ b/sr_compat.c
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- * 
  * Copyright (C) 2008 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -15,9 +13,10 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
+
 /*!
  * \file
- * \brief SIP-router core :: ser/kamailio/openser compatibility macros & vars.
+ * \brief Kamailio core :: ser/kamailio/openser compatibility macros & vars.
  * \ingroup core
  * Module: \ref core
  */
diff --git a/sr_compat.h b/sr_compat.h
index ba46bde..5d50b02 100644
--- a/sr_compat.h
+++ b/sr_compat.h
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- * 
  * Copyright (C) 2008 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
diff --git a/sr_module.c b/sr_module.c
index c7f7833..216c953 100644
--- a/sr_module.c
+++ b/sr_module.c
@@ -1,19 +1,14 @@
 /*
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -23,27 +18,9 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-/*
- * History:
- * --------
- *  2003-03-10  switched to new module_exports format: updated find_export,
- *               find_export_param, find_module (andrei)
- *  2003-03-19  replaced all mallocs/frees w/ pkg_malloc/pkg_free (andrei)
- *  2003-03-19  Support for flags in find_export (janakj)
- *  2003-03-29  cleaning pkg_mallocs introduced (jiri)
- *  2003-04-24  module version checking introduced (jiri)
- *  2004-09-19  compile flags are checked too (andrei)
- *  2005-01-07  removed find_module-overloading problems, added
- *               find_export_record
- *  2006-02-07  added fix_flag (andrei)
- *  2008-02-29  store all the reponse callbacks in their own array (andrei)
- *  2008-11-17  support dual module interface: ser & kamailio (andrei)
- *  2008-11-26  added fparam_free_contents() and fix_param_types (andrei)
- */
-
 /**
  * @file
- * @brief SIP-Router core :: modules loading, structures declarations and utilities
+ * @brief Kamailio core :: modules loading, structures declarations and utilities
  * @ingroup core
  * Module: \ref core
  */
@@ -522,7 +499,7 @@ int load_module(char* mod_path)
 					strcat(path, ".so");
 
 				if (stat(path, &stat_buf) == -1) {
-					DBG("load_module: module file not found <%s>\n", path);
+					LM_DBG("module file not found <%s>\n", path);
 					pkg_free(path);
 
 					/* try path <MODS_DIR>/<modname>/<modname>.so */
@@ -545,7 +522,7 @@ int load_module(char* mod_path)
 						strcat(path, ".so");
 
 					if (stat(path, &stat_buf) == -1) {
-						DBG("load_module: module file not found <%s>\n", path);
+						LM_DBG("module file not found <%s>\n", path);
 						pkg_free(path);
 						path=0;
 					}
@@ -554,7 +531,7 @@ int load_module(char* mod_path)
 				/* try mod_path - S compat */
 				if(path==mod_path) {
 					if (stat(path, &stat_buf) == -1) {
-						DBG("load_module: module file not found <%s>\n", path);
+						LM_DBG("module file not found <%s>\n", path);
 						path=0;
 					}
 				}
@@ -573,7 +550,7 @@ int load_module(char* mod_path)
 					strcat(path, mod_path);
 
 					if (stat(path, &stat_buf) == -1) {
-						DBG("load_module: module file not found <%s>\n", path);
+						LM_DBG("module file not found <%s>\n", path);
 						pkg_free(path);
 						path=0;
 					}
@@ -587,7 +564,7 @@ int load_module(char* mod_path)
 			goto error;
 		}
 	}
-	DBG("load_module: trying to load <%s>\n", path);
+	LM_DBG("trying to load <%s>\n", path);
 
 	retries=2;
 	dlflags=RTLD_NOW;
@@ -691,14 +668,14 @@ sr31_cmd_export_t* find_mod_export_record(char* mod, char* name,
 					 (cmd->param_no==VAR_PARAM_NO)) &&
 					((cmd->flags & flags) == flags)
 				){
-					DBG("find_export_record: found <%s> in module %s [%s]\n",
+					LM_DBG("find_export_record: found <%s> in module %s [%s]\n",
 						name, t->exports.name, t->path);
 					*mod_if_ver=t->orig_mod_interface_ver;
 					return cmd;
 				}
 			}
 	}
-	DBG("find_export_record: <%s> not found \n", name);
+	LM_DBG("find_export_record: <%s> not found \n", name);
 	return 0;
 }
 
@@ -751,7 +728,7 @@ cmd_function find_mod_export(char* mod, char* name, int param_no, int flags)
 	if (cmd)
 		return cmd->function;
 	
-	DBG("find_mod_export: <%s> in module <%s> not found\n", name, mod);
+	LM_DBG("<%s> in module <%s> not found\n", name, mod);
 	return 0;
 }
 
@@ -764,7 +741,7 @@ struct sr_module* find_module_by_name(char* mod) {
 			return t;
 		}
 	}
-	DBG("find_module_by_name: module <%s> not found\n", mod);
+	LM_DBG("module <%s> not found\n", mod);
 	return 0;
 }
 
@@ -787,13 +764,13 @@ void* find_param_export(struct sr_module* mod, char* name,
 	for(param = mod->exports.params ;param && param->name ; param++) {
 		if ((strcmp(name, param->name) == 0) &&
 			((param->type & PARAM_TYPE_MASK(type_mask)) != 0)) {
-			DBG("find_param_export: found <%s> in module %s [%s]\n",
+			LM_DBG("found <%s> in module %s [%s]\n",
 				name, mod->exports.name, mod->path);
 			*param_type = param->type;
 			return param->param_pointer;
 		}
 	}
-	DBG("find_param_export: parameter <%s> not found in module <%s>\n",
+	LM_DBG("parameter <%s> not found in module <%s>\n",
 			name, mod->exports.name);
 	return 0;
 }
@@ -885,7 +862,7 @@ int init_child(int rank)
 	case PROC_TCP_MAIN: type = "PROC_TCP_MAIN"; break;
 	default:            type = "CHILD";         break;
 	}
-	DBG("init_child: initializing %s with rank %d\n", type, rank);
+	LM_DBG("initializing %s with rank %d\n", type, rank);
 
 	if(async_task_child_init(rank)<0)
 		return -1;
@@ -917,7 +894,7 @@ static int init_mod_child( struct sr_module* m, int rank )
 		 */
 		if (init_mod_child(m->next, rank)!=0) return -1;
 		if (m->exports.init_child_f) {
-			DBG("DEBUG: init_mod_child (%d): %s\n", rank, m->exports.name);
+			LM_DBG("rank %d: %s\n", rank, m->exports.name);
 			if (m->exports.init_child_f(rank)<0) {
 				LM_ERR("Error while initializing module %s (%s)\n",
 							m->exports.name, m->path);
@@ -962,7 +939,7 @@ static int init_mod( struct sr_module* m )
 		 */
 		if (init_mod(m->next)!=0) return -1;
 			if (m->exports.init_f) {
-				DBG("DEBUG: init_mod: %s\n", m->exports.name);
+				LM_DBG("%s\n", m->exports.name);
 				if (m->exports.init_f()!=0) {
 					LM_ERR("Error while initializing module %s (%s)\n",
 								m->exports.name, m->path);
@@ -1663,7 +1640,7 @@ int get_str_fparam(str* dst, struct sip_msg* msg, fparam_t* param)
 			avp = search_first_avp(param->v.avp.flags, param->v.avp.name,
 									&val, 0);
 			if (unlikely(!avp)) {
-				DBG("Could not find AVP from function parameter '%s'\n",
+				LM_DBG("Could not find AVP from function parameter '%s'\n",
 						param->orig);
 				return -1;
 			}
@@ -1728,7 +1705,7 @@ int get_int_fparam(int* dst, struct sip_msg* msg, fparam_t* param)
 			avp = search_first_avp(param->v.avp.flags, param->v.avp.name,
 									&val, 0);
 			if (unlikely(!avp)) {
-				DBG("Could not find AVP from function parameter '%s'\n",
+				LM_DBG("Could not find AVP from function parameter '%s'\n",
 						param->orig);
 				return -1;
 			}
@@ -1797,7 +1774,7 @@ int get_is_fparam(int* i_dst, str* s_dst, struct sip_msg* msg, fparam_t* param,
 			avp = search_first_avp(param->v.avp.flags, param->v.avp.name,
 									&val, 0);
 			if (unlikely(!avp)) {
-				DBG("Could not find AVP from function parameter '%s'\n",
+				LM_DBG("Could not find AVP from function parameter '%s'\n",
 						param->orig);
 				return -1;
 			}
diff --git a/sr_module.h b/sr_module.h
index c251982..b20cd63 100644
--- a/sr_module.h
+++ b/sr_module.h
@@ -1,19 +1,14 @@
 /*
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -23,32 +18,9 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-/*
- * History:
- * --------
- *  2003-03-10  changed module exports interface: added struct cmd_export
- *               and param_export (andrei)
- *  2003-03-16  Added flags field to cmd_export_ (janakj)
- *  2003-04-05  s/reply_route/failure_route, onreply_route introduced (jiri)
- *  2004-03-12  extra flag USE_FUNC_PARAM added to modparam type -
- *              instead of copying the param value, a func is called (bogdan)
- *  2004-09-19  switched to version.h for the module versions checks (andrei)
- *  2004-12-03  changed param_func_t to (modparam_t, void*), killed
- *               param_func_param_t   (andrei)
- *  2007-06-07  added PROC_INIT, called in the main process context
- *               (same as PROC_MAIN), buf guaranteed to be called before
- *               any other process is forked (andrei)
- *  2008-11-17  sip-router version: includes some of the openser/kamailio
- *               changes: f(void) instead of f(), free_fixup_function()
- *              dual module interface support: ser & kamailio (andrei)
- *  2008-11-18  prototypes for various fixed parameters numbers module
- *               functions (3, 4, 5 & 6) and variable parameters (andrei)
- *  2008-11-26  added fparam_free_contents() and fix_param_types (andrei)
- */
-
 /**
  * @file
- * @brief SIP-Router core :: modules loading, structures declarations and utilities
+ * @brief Kamailio core :: modules loading, structures declarations and utilities
  * @ingroup core
  * Module: \ref core
  */
diff --git a/stats.c b/stats.c
index 60de5e5..aeba97e 100644
--- a/stats.c
+++ b/stats.c
@@ -1,24 +1,17 @@
 /* 
- * $Id$
- *
  * Stats reporting code. It reports through SIG_USR1 and if loaded
  * through the SNMP module
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -27,14 +20,13 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * -------
- * 2003-03-19: added support for route type in find_export (janakj)
  */
 
 /*!
  * \file
- * \brief SIP-router core :: Stats reporting code
+ * \brief Kamailio core :: Stats reporting code
+ * Stats reporting code. It reports through SIG_USR1 and if loaded
+ * through the SNMP module
  * \ingroup core
  * Module: \ref core
  */
diff --git a/stats.h b/stats.h
index 4159184..18558fc 100644
--- a/stats.h
+++ b/stats.h
@@ -1,22 +1,15 @@
 /*
- * $Id$
- *
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/str.c b/str.c
index a7fcf93..c9c4d33 100644
--- a/str.c
+++ b/str.c
@@ -1,5 +1,4 @@
-/**
- * $Id$
+/*
  *
  * Copyright (C) 2014 Victor Seva <vseva at sipwise.com>
  *
@@ -17,6 +16,12 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
+/*!
+ * \file
+ * \brief Kamailio core :: Append to str data
+ * \ingroup core
+ * Module: \ref core
+ */
 
 #include <string.h>
 #include "str.h"
diff --git a/str.h b/str.h
index 5c7b715..9ef8809 100644
--- a/str.h
+++ b/str.h
@@ -1,19 +1,14 @@
 /*
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/str_hash.h b/str_hash.h
index 62423f1..982593f 100644
--- a/str_hash.h
+++ b/str_hash.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2006 iptelorg GmbH 
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -15,14 +13,6 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/*
- * History:
- * --------
- *  2006-02-02  created by andrei
- *  2006-11-24  added numeric string optimized hash function (andrei)
- *  2006-12-13  split into hashes.h (more generic) and str_hash.h (andrei)
- */
-
 
 #ifndef _str_hashs_h
 #define _str_hashs_h
diff --git a/str_list.c b/str_list.c
index 3fc6428..f63b4c9 100644
--- a/str_list.c
+++ b/str_list.c
@@ -1,14 +1,14 @@
 /*
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of sip-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * sip-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * sip-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -20,10 +20,11 @@
 
 /**
  * @file 
- * @brief Simple str type list and helper functions
+ * @brief Kamailio core :: Simple str type list and helper functions
+ * @ingroup core
+ * Module: @ref core
  */
 
-
 #include "str.h"
 #include "mem/mem.h"
 #include "str_list.h"
diff --git a/str_list.h b/str_list.h
index 1e35d7f..fe1e534 100644
--- a/str_list.h
+++ b/str_list.h
@@ -2,14 +2,14 @@
  * Copyright (C) 2001-2003 FhG Fokus
  * Copyright (C) 2006 Voice Sistem SRL
  *
- * This file is part of sip-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * sip-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * sip-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -21,7 +21,7 @@
 
 /**
  * @file 
- * @brief Simple str type list and helper functions
+ * @brief Kamailio core :: Simple str type list and helper functions
  */
 
 
diff --git a/stun.c b/stun.c
index 15f3c6c..9061e17 100644
--- a/stun.c
+++ b/stun.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2013 Crocodile RCS Ltd
  *
  * This file is part of Kamailio, a free SIP server.
@@ -20,6 +18,13 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
  */
+/*!
+ * \file
+ * \brief Kamailio core :: STUN support
+ * STUN support callback, used by the STUN module
+ * \ingroup core
+ * Module: \ref core
+ */
 
 #include "events.h"
 #include "ip_addr.h"
diff --git a/stun.h b/stun.h
index d3e7357..a245157 100644
--- a/stun.h
+++ b/stun.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Portions Copyright (C) 2013 Crocodile RCS Ltd
  *
  * Based on "ser_stun.h". Copyright (C) 2001-2003 FhG Fokus
diff --git a/switch.c b/switch.c
index 2958a75..6aeffc2 100644
--- a/switch.c
+++ b/switch.c
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- * 
  * Copyright (C) 2009 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -15,19 +13,10 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/*
- * switch.c
- */
-/*
- * History:
- * --------
- *  2009-02-02  initial version (andrei)
- *  2009-02-19  string and RE switch support added (andrei)
-*/
 
 /*!
  * \file
- * \brief SIP-router core :: 
+ * \brief Kamailio core :: 
  * \ingroup core
  * Module: \ref core
  */
@@ -184,11 +173,11 @@ int fix_switch(struct action* t)
 			rve_destroy(sw_rve);
 			t->val[0].type=BLOCK_ST;
 			t->val[0].u.data=0;
-			DBG("SWITCH: null switch optimized away\n");
+			LM_DBG("null switch optimized away\n");
 		}else{
 			t->type=EVAL_T;
 			t->val[0].type=RVE_ST;
-			DBG("SWITCH: null switch turned to EVAL_T\n");
+			LM_DBG("null switch turned to EVAL_T\n");
 		}
 		return 0;
 	}
@@ -226,7 +215,7 @@ int fix_switch(struct action* t)
 		if ( c->actions && ((ret=fix_actions(c->actions))<0))
 			goto error;
 	}
-	DBG("SWITCH: %d cases, %d default\n", n, default_found);
+	LM_DBG("%d cases, %d default\n", n, default_found);
 	/*: handle n==0 (no case only a default:) */
 	if (n==0){
 		if (default_found){
@@ -238,10 +227,12 @@ int fix_switch(struct action* t)
 				t->val[0].u.data=def_a;
 				t->val[1].type=0;
 				t->val[1].u.data=0;
-				DBG("SWITCH: default only switch optimized away (BLOCK_T)\n");
+				LM_DBG("default only switch optimized away (BLOCK_T)\n");
 				return 0;
 			}
-			DBG("SWITCH: default only switch with side-effect...\n");
+			LM_CRIT("default only switch with side-effect not expected at this point\n");
+			ret=E_BUG;
+			goto error;
 		}else{
 			LM_CRIT("empty switch not expected at this point\n");
 			ret=E_BUG;
@@ -315,7 +306,7 @@ int fix_switch(struct action* t)
 		t->val[1].type=0;
 		t->val[1].u.data=0;
 		ret=0;
-		DBG("SWITCH: constant switch(%d) with %d cases optimized away to case "
+		LM_DBG("constant switch(%d) with %d cases optimized away to case"
 				" %d \n", val, n, i);
 		goto end;
 	}
@@ -374,8 +365,8 @@ int fix_switch(struct action* t)
 		t->val[1].type=JUMPTABLE_ST;
 		t->val[1].u.data=jmp;
 		ret=0;
-		DBG("SWITCH: optimized to jumptable [%d, %d] and %d condtable,"
-				"default: %s\n ",
+		LM_DBG("optimized to jumptable [%d, %d] and %d condtable,"
+				" default: %s\n ",
 				jmp->first, jmp->last, jmp->rest.n, jmp->rest.def?"yes":"no");
 	}else{
 		sct=mk_switch_cond_table(n);
@@ -393,7 +384,7 @@ int fix_switch(struct action* t)
 		t->type=SWITCH_COND_T;
 		t->val[1].type=CONDTABLE_ST;
 		t->val[1].u.data=sct;
-		DBG("SWITCH: optimized to condtable (%d) default: %s\n ",
+		LM_DBG("optimized to condtable (%d) default: %s\n",
 				sct->n, sct->def?"yes":"no");
 		ret=0;
 	}
@@ -450,11 +441,11 @@ static int fix_match(struct action* t)
 			rve_destroy(m_rve);
 			t->val[0].type=BLOCK_ST;
 			t->val[0].u.data=0;
-			DBG("MATCH: null switch optimized away\n");
+			LM_DBG("null switch optimized away\n");
 		}else{
 			t->type=EVAL_T;
 			t->val[0].type=RVE_ST;
-			DBG("MATCH: null switch turned to EVAL_T\n");
+			LM_DBG("null switch turned to EVAL_T\n");
 		}
 		return 0;
 	}
@@ -541,7 +532,7 @@ static int fix_match(struct action* t)
 		if ( c->actions && ((ret=fix_actions(c->actions))<0))
 			goto error;
 	}
-	DBG("MATCH: %d cases, %d default\n", n, default_found);
+	LM_DBG("%d cases, %d default\n", n, default_found);
 	/*: handle n==0 (no case only a default:) */
 	if (n==0){
 		if (default_found){
@@ -553,10 +544,12 @@ static int fix_match(struct action* t)
 				t->val[0].u.data=def_a;
 				t->val[1].type=0;
 				t->val[1].u.data=0;
-				DBG("MATCH: default only switch optimized away (BLOCK_T)\n");
+				LM_DBG("default only switch optimized away (BLOCK_T)\n");
 				return 0;
 			}
-			DBG("MATCH: default only switch with side-effect...\n");
+			LM_CRIT("default only switch with side-effect not expected at this point\n");
+			ret=E_BUG;
+			goto error;
 		}else{
 			LM_CRIT("empty switch not expected at this point\n");
 			ret=E_BUG;
@@ -647,7 +640,7 @@ static int fix_match(struct action* t)
 				break;
 			}
 		}
-		DBG("MATCH: constant switch(\"%.*s\") with %d cases optimized away"
+		LM_DBG("constant switch(\"%.*s\") with %d cases optimized away"
 				" to case no. %d\n", s.len, ZSW(s.s), n, i);
 		/* cleanup */
 		rval_destroy(rv);
@@ -681,7 +674,7 @@ static int fix_match(struct action* t)
 	t->type=MATCH_COND_T;
 	t->val[1].type=MATCH_CONDTABLE_ST;
 	t->val[1].u.data=mct;
-	DBG("MATCH: optimized to match condtable (%d) default: %s\n ",
+	LM_DBG("optimized to match condtable (%d) default: %s\n",
 				mct->n, mct->def?"yes":"no");
 		ret=0;
 end:
diff --git a/switch.h b/switch.h
index bebe17a..acc1109 100644
--- a/switch.h
+++ b/switch.h
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- * 
  * Copyright (C) 2009 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -15,14 +13,6 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/*
- * /home/andrei/sr.git/switch.h
- */
-/*
- * History:
- * --------
- *  2009-02-02  initial version (andrei)
-*/
 
 #ifndef __switch_h
 #define __switch_h
diff --git a/tags.h b/tags.h
index 45c95db..192fdc3 100644
--- a/tags.h
+++ b/tags.h
@@ -1,8 +1,6 @@
 /*
- * $Id$
- *
  * - utility for generating to-tags
- *   in SER, to-tags consist of two parts: a fixed part
+ *   in Kamailio, to-tags consist of two parts: a fixed part
  *   which is bound to server instance and variable part
  *   which is bound to request -- that helps to recognize,
  *   who generated the to-tag in loops through the same
@@ -12,19 +10,14 @@
  *   
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -33,13 +26,6 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/*
- * History:
- * --------
- *  2003-02-18  changed TOTAG_LEN into TOTAG_VALUE_LEN, to solve
- *               redefinition conflict with tm/t_msgbuilder.h (andrei)
- */
-
 
 #ifndef _TAGS_H
 #define _TAGS_H
@@ -52,7 +38,7 @@
 
 #define TOTAG_VALUE_LEN (MD5_LEN+CRC16_LEN+1)
 
-/* generate variable part of to-tag for a request;
+/*! generate variable part of to-tag for a request;
  * it will have length of CRC16_LEN, sufficiently
  * long buffer must be passed to the function */
 static inline void calc_crc_suffix( struct sip_msg *msg, char *tag_suffix)
diff --git a/tcp_conn.h b/tcp_conn.h
index 7c9eecb..e1c31cd 100644
--- a/tcp_conn.h
+++ b/tcp_conn.h
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,21 +17,8 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- *
- * History:
- * --------
- *  2003-01-29  tcp buffer size ++-ed to allow for 0-terminator
- *  2003-06-30  added tcp_connection flags & state (andrei) 
- *  2003-10-27  tcp port aliases support added (andrei)
- *  2006-10-13  added tcp_req_states for STUN (vlada)
- *  2007-07-26  improved tcp connection hash function; increased aliases
- *               hash size (andrei)
- *  2007-11-26  switched to local_timer (andrei)
- *  2007-11-30  buffered write support (andrei)
  */
 
-
-
 #ifndef _tcp_conn_h
 #define _tcp_conn_h
 
@@ -224,6 +204,7 @@ struct tcp_connection{
 	void* extra_data; /* extra data associated to the connection, 0 for tcp*/
 	struct timer_ln timer;
 	ticks_t timeout;/* connection timeout, after this it will be removed*/
+	ticks_t lifetime;/* connection lifetime */
 	unsigned id_hash; /* hash index in the id_hash */
 	struct tcp_connection* id_next; /* next, prev in id hash table */
 	struct tcp_connection* id_prev;
diff --git a/tcp_ev.h b/tcp_ev.h
index a25d59f..9cac081 100644
--- a/tcp_ev.h
+++ b/tcp_ev.h
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- * 
  * Copyright (C) 2009 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -15,14 +13,10 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/*
- * tcp_ev.h - tcp events
+/*!
+ * \brief Kamailio core :: tcp_ev.h - tcp events
+ * \ingroup core
  */
-/*
- * History:
- * --------
- *  2009-04-09  initial version (andrei)
-*/
 
 #ifndef __tcp_ev_h
 #define __tcp_ev_h
diff --git a/tcp_info.h b/tcp_info.h
index bc493a1..ba7eb7c 100644
--- a/tcp_info.h
+++ b/tcp_info.h
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2006 iptelorg GmbH
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,8 +17,8 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/*
- * tcp various information
+/*! \brief Kamailio core :: tcp various information
+ * \ingroup core
  */
 
 #ifndef _tcp_info_h
diff --git a/tcp_init.h b/tcp_init.h
index 3d111a2..ddabbc5 100644
--- a/tcp_init.h
+++ b/tcp_init.h
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/tcp_int_send.h b/tcp_int_send.h
index b33e9b0..1828969 100644
--- a/tcp_int_send.h
+++ b/tcp_int_send.h
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- * 
  * Copyright (C) 2010 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -15,8 +13,9 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/** internal tcp send functions (use with care).
+/** internal Kamailio core :: tcp send functions (use with care).
  * @file tcp_int_send.h
+ * @ingroup core
  */
 /*
  * History:
diff --git a/tcp_main.c b/tcp_main.c
index 5830c8e..df778ba 100644
--- a/tcp_main.c
+++ b/tcp_main.c
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,89 +17,8 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/*
- * History:
- * --------
- *  2002-11-29  created by andrei
- *  2002-12-11  added tcp_send (andrei)
- *  2003-01-20  locking fixes, hashtables (andrei)
- *  2003-02-20  s/lock_t/gen_lock_t/ to avoid a conflict on solaris (andrei)
- *  2003-02-25  Nagle is disabled if -DDISABLE_NAGLE (andrei)
- *  2003-03-29  SO_REUSEADDR before calling bind to allow
- *              server restart, Nagle set on the (hopefuly) 
- *              correct socket (jiri)
- *  2003-03-31  always try to find the corresponding tcp listen socket for
- *               a temp. socket and store in in *->bind_address: added
- *               find_tcp_si, modified tcpconn_connect (andrei)
- *  2003-04-14  set sockopts to TOS low delay (andrei)
- *  2003-06-30  moved tcp new connect checking & handling to
- *               handle_new_connect (andrei)
- *  2003-07-09  tls_close called before closing the tcp connection (andrei)
- *  2003-10-24  converted to the new socket_info lists (andrei)
- *  2003-10-27  tcp port aliases support added (andrei)
- *  2003-11-04  always lock before manipulating refcnt; sendchild
- *              does not inc refcnt by itself anymore (andrei)
- *  2003-11-07  different unix sockets are used for fd passing
- *              to/from readers/writers (andrei)
- *  2003-11-17  handle_new_connect & tcp_connect will close the 
- *              new socket if tcpconn_new return 0 (e.g. out of mem) (andrei)
- *  2003-11-28  tcp_blocking_write & tcp_blocking_connect added (andrei)
- *  2004-11-08  dropped find_tcp_si and replaced with find_si (andrei)
- *  2005-06-07  new tcp optimized code, supports epoll (LT), sigio + real time
- *               signals, poll & select (andrei)
- *  2005-06-26  *bsd kqueue support (andrei)
- *  2005-07-04  solaris /dev/poll support (andrei)
- *  2005-07-08  tcp_max_connections, tcp_connection_lifetime, don't accept
- *               more connections if tcp_max_connections is exceeded (andrei)
- *  2005-10-21  cleanup all the open connections on exit
- *              decrement the no. of open connections on timeout too    (andrei) *  2006-01-30  queue send_fd request and execute them at the end of the
- *              poll loop  (#ifdef) (andrei)
- *              process all children requests, before attempting to send
- *              them new stuff (fixes some deadlocks) (andrei)
- *  2006-02-03  timers are run only once per s (andrei)
- *              tcp children fds can be non-blocking; send fds are queued on
- *              EAGAIN; lots of bug fixes (andrei)
- *  2006-02-06  better tcp_max_connections checks, tcp_connections_no moved to
- *              shm (andrei)
- *  2006-04-12  tcp_send() changed to use struct dest_info (andrei)
- *  2006-11-02  switched to atomic ops for refcnt, locking improvements 
- *               (andrei)
- *  2006-11-04  switched to raw ticks (to fix conversion errors which could
- *               result in inf. lifetime) (andrei)
- *  2007-07-25  tcpconn_connect can now bind the socket on a specified
- *                source addr/port (andrei)
- *  2007-07-26   tcp_send() and tcpconn_get() can now use a specified source
- *                addr./port (andrei)
- *  2007-08-23   getsockname() for INADDR_ANY(SI_IS_ANY) sockets (andrei)
- *  2007-08-27   split init_sock_opt into a lightweight init_sock_opt_accept() 
- *               used when accepting connections and init_sock_opt used for 
- *               connect/ new sockets (andrei)
- *  2007-11-22  always add the connection & clear the coresponding flags before
- *               io_watch_add-ing its fd - it's safer this way (andrei)
- *  2007-11-26  improved tcp timers: switched to local_timer (andrei)
- *  2007-11-27  added send fd cache and reader fd reuse (andrei)
- *  2007-11-28  added support for TCP_DEFER_ACCEPT, KEEPALIVE, KEEPINTVL,
- *               KEEPCNT, QUICKACK, SYNCNT, LINGER2 (andrei)
- *  2007-12-04  support for queueing write requests (andrei)
- *  2007-12-12  destroy connection asap on wbuf. timeout (andrei)
- *  2007-12-13  changed the refcnt and destroy scheme, now refcnt is 1 if
- *                linked into the hash tables (was 0) (andrei)
- *  2007-12-21  support for pending connects (connections are added to the
- *               hash immediately and writes on them are buffered) (andrei)
- *  2008-02-05  handle POLLRDHUP (if supported), POLLERR and
- *               POLLHUP (andrei)
- *              on write error check if there's still data in the socket 
- *               read buffer and process it first (andrei)
- *  2009-02-26  direct blacklist support (andrei)
- *  2009-03-20  s/wq_timeout/send_timeout ; send_timeout is now in ticks
- *              (andrei)
- *  2009-04-09  tcp ev and tcp stats macros added (andrei)
- *  2009-09-15  support for force connection reuse and close after send
- *               send flags (andrei)
- *  2010-03-23  tcp_send() split in 3 smaller functions (andrei)
- */
 
-/** tcp main/dispatcher and tcp send functions.
+/** Kamailio core: tcp main/dispatcher and tcp send functions.
  * @file tcp_main.c
  * @ingroup core
  * Module: @ref core
@@ -1070,7 +982,7 @@ struct tcp_connection* tcpconn_new(int sock, union sockaddr_union* su,
 		c->rcv.dst_port=ba->port_no;
 	}
 	print_ip("tcpconn_new: new tcp connection: ", &c->rcv.src_ip, "\n");
-	DBG(     "tcpconn_new: on port %d, type %d\n", c->rcv.src_port, type);
+	LM_DBG("on port %d, type %d\n", c->rcv.src_port, type);
 	init_tcp_req(&c->req, (char*)c+sizeof(struct tcp_connection), rd_b_size);
 	c->id=(*connection_id)++;
 	c->rcv.proto_reserved1=0; /* this will be filled before receive_message*/
@@ -1086,6 +998,7 @@ struct tcp_connection* tcpconn_new(int sock, union sockaddr_union* su,
 		c->type=PROTO_TCP;
 		c->rcv.proto=PROTO_TCP;
 		c->timeout=get_ticks_raw()+cfg_get(tcp, tcp_cfg, con_lifetime);
+		c->lifetime = cfg_get(tcp, tcp_cfg, con_lifetime);
 	}
 	
 	return c;
@@ -1375,7 +1288,7 @@ inline static struct tcp_connection*  tcpconn_add(struct tcp_connection *c)
 		 *  of the add_alias would fail (e.g. first add_alias for 2 connections
 		 *   with the same destination but different src. ip*/
 		TCPCONN_UNLOCK;
-		DBG("tcpconn_add: hashes: %d:%d:%d, %d\n",
+		LM_DBG("hashes: %d:%d:%d, %d\n",
 												c->con_aliases[0].hash,
 												c->con_aliases[1].hash,
 												c->con_aliases[2].hash,
@@ -1460,14 +1373,14 @@ struct tcp_connection* _tcpconn_find(int id, struct ip_addr* ip, int port,
 	int is_local_ip_any;
 	
 #ifdef EXTRA_DEBUG
-	DBG("tcpconn_find: %d  port %d\n",id, port);
+	LM_DBG("%d  port %d\n",id, port);
 	if (ip) print_ip("tcpconn_find: ip ", ip, "\n");
 #endif
 	if (likely(id)){
 		hash=tcp_id_hash(id);
 		for (c=tcpconn_id_hash[hash]; c; c=c->id_next){
 #ifdef EXTRA_DEBUG
-			DBG("c=%p, c->id=%d, port=%d\n",c, c->id, c->rcv.src_port);
+			LM_DBG("c=%p, c->id=%d, port=%d\n", c, c->id, c->rcv.src_port);
 			print_ip("ip=", &c->rcv.src_ip, "\n");
 #endif
 			if ((id==c->id)&&(c->state!=S_CONN_BAD)) return c;
@@ -1477,7 +1390,7 @@ struct tcp_connection* _tcpconn_find(int id, struct ip_addr* ip, int port,
 		is_local_ip_any=ip_addr_any(l_ip);
 		for (a=tcpconn_aliases_hash[hash]; a; a=a->next){
 #ifdef EXTRA_DEBUG
-			DBG("a=%p, c=%p, c->id=%d, alias port= %d port=%d\n", a, a->parent,
+			LM_DBG("a=%p, c=%p, c->id=%d, alias port= %d port=%d\n", a, a->parent,
 					a->parent->id, a->port, a->parent->rcv.src_port);
 			print_ip("ip=",&a->parent->rcv.src_ip,"\n");
 #endif
@@ -1621,8 +1534,8 @@ inline static int _tcpconn_add_alias_unsafe(struct tcp_connection* c, int port,
 	}else goto error_not_found;
 ok:
 #ifdef EXTRA_DEBUG
-	if (a) DBG("_tcpconn_add_alias_unsafe: alias already present\n");
-	else   DBG("_tcpconn_add_alias_unsafe: alias port %d for hash %d, id %d\n",
+	if (a) LM_DBG("alias already present\n");
+	else   LM_DBG("alias port %d for hash %d, id %d\n",
 			port, hash, c->id);
 #endif
 	return 0;
@@ -1817,7 +1730,7 @@ int tcp_send(struct dest_info* dst, union sockaddr_union* from,
 		if (unlikely((dst->send_flags.f & SND_F_FORCE_CON_REUSE) ||
 						cfg_get(tcp, tcp_cfg, no_connect)))
 			return -1;
-		DBG("tcp_send: no open tcp connection found, opening new one\n");
+		LM_DBG("no open tcp connection found, opening new one\n");
 		/* create tcp connection */
 		if (likely(from==0)){
 			/* check to see if we have to use a specific source addr. */
@@ -2279,7 +2192,7 @@ static int tcpconn_send_put(struct tcp_connection* c, const char* buf,
 		/* check if this is not the same reader process holding
 		 *  c  and if so send directly on c->fd */
 		if (c->reader_pid==my_pid()){
-			DBG("tcp_send: send from reader (%d (%d)), reusing fd\n",
+			LM_DBG("send from reader (%d (%d)), reusing fd\n",
 					my_pid(), process_no);
 			fd=c->fd;
 			do_close_fd=0; /* don't close the fd on exit, it's in use */
@@ -2292,11 +2205,10 @@ static int tcpconn_send_put(struct tcp_connection* c, const char* buf,
 							((fd_cache_e=tcp_fd_cache_get(c))!=0))){
 			fd=fd_cache_e->fd;
 			do_close_fd=0;
-			DBG("tcp_send: found fd in cache ( %d, %p, %d)\n",
-					fd, c, fd_cache_e->id);
+			LM_DBG("found fd in cache (%d, %p, %d)\n", fd, c, fd_cache_e->id);
 #endif /* TCP_FD_CACHE */
 		}else{
-			DBG("tcp_send: tcp connection found (%p), acquiring fd\n", c);
+			LM_DBG("tcp connection found (%p), acquiring fd\n", c);
 			/* get the fd */
 			response[0]=(long)c;
 			response[1]=CONN_GET_FD;
@@ -2306,7 +2218,7 @@ static int tcpconn_send_put(struct tcp_connection* c, const char* buf,
 				n=-1;
 				goto release_c;
 			}
-			DBG("tcp_send, c= %p, n=%d\n", c, n);
+			LM_DBG("c=%p, n=%d\n", c, n);
 			n=receive_fd(unix_tcp_sock, &tmp, sizeof(tmp), &fd, MSG_WAITALL);
 			if (unlikely(n<=0)){
 				LM_ERR("failed to get fd(receive_fd): %s (%d)\n",
@@ -2336,7 +2248,7 @@ static int tcpconn_send_put(struct tcp_connection* c, const char* buf,
 #endif /* TCP_FD_CACHE */
 				goto end;
 			}
-			DBG("tcp_send: after receive_fd: c= %p n=%d fd=%d\n",c, n, fd);
+			LM_DBG("after receive_fd: c= %p n=%d fd=%d\n",c, n, fd);
 		}
 	
 #ifdef USE_TLS
@@ -2515,7 +2427,7 @@ static int tcpconn_do_send(int fd, struct tcp_connection* c,
 	int enable_write_watch;
 #endif /* TCP_ASYNC */
 
-	DBG("tcp_send: sending...\n");
+	LM_DBG("sending...\n");
 	*resp = CONN_NOP;
 	if (likely(!locked)) lock_get(&c->write_lock);
 	/* update connection send flags with the current ones */
@@ -2549,8 +2461,8 @@ static int tcpconn_do_send(int fd, struct tcp_connection* c,
 	if (likely(!locked)) lock_release(&c->write_lock);
 #endif /* TCP_ASYNC */
 	
-	DBG("tcp_send: after real write: c= %p n=%d fd=%d\n",c, n, fd);
-	DBG("tcp_send: buf=\n%.*s\n", (int)len, buf);
+	LM_DBG("after real write: c= %p n=%d fd=%d\n",c, n, fd);
+	LM_DBG("buf=\n%.*s\n", (int)len, buf);
 	if (unlikely(n<(int)len)){
 #ifdef TCP_ASYNC
 		if (cfg_get(tcp, tcp_cfg, async) &&
@@ -2695,8 +2607,8 @@ static int tcpconn_1st_send(int fd, struct tcp_connection* c,
 		   ENOTCONN appears on newer FreeBSD versions (non-blocking socket,
 		   connect() & send immediately) */
 		if ((n>=0) || errno==EAGAIN || errno==EWOULDBLOCK || errno==ENOTCONN){
-			DBG("pending write on new connection %p "
-				" (%d/%d bytes written)\n", c, n, len);
+			LM_DBG("pending write on new connection %p "
+				"(%d/%d bytes written)\n", c, n, len);
 			if (unlikely(n<0)) n=0;
 			else{
 				if (likely(c->state == S_CONN_CONNECT))
@@ -2802,7 +2714,7 @@ int tcp_init(struct socket_info* sock_info)
 		LM_ERR("could no init sockaddr_union\n");
 		goto error;
 	}
-	DBG("tcp_init: added %s\n", su2a(addr, sizeof(*addr)));
+	LM_DBG("added %s\n", su2a(addr, sizeof(*addr)));
 	sock_info->socket=socket(AF2PF(addr->s.sa_family), SOCK_STREAM, 0);
 	if (sock_info->socket==-1){
 		LM_ERR("tcp_init: socket: %s\n", strerror(errno));
@@ -2942,9 +2854,8 @@ inline static void tcpconn_close_main_fd(struct tcp_connection* tcpconn)
 inline static int tcpconn_chld_put(struct tcp_connection* tcpconn)
 {
 	if (unlikely(atomic_dec_and_test(&tcpconn->refcnt))){
-		DBG("tcpconn_chld_put: destroying connection %p (%d, %d) "
-				"flags %04x\n", tcpconn, tcpconn->id,
-				tcpconn->s, tcpconn->flags);
+		LM_DBG("destroying connection %p (%d, %d) flags %04x\n",
+				tcpconn, tcpconn->id, tcpconn->s, tcpconn->flags);
 		/* sanity checks */
 		membar_read_atomic_op(); /* make sure we see the current flags */
 		if (unlikely(!(tcpconn->flags & F_CONN_FD_CLOSED) ||
@@ -2967,9 +2878,8 @@ inline static int tcpconn_chld_put(struct tcp_connection* tcpconn)
  */
 inline static void tcpconn_destroy(struct tcp_connection* tcpconn)
 {
-		DBG("tcpconn_destroy: destroying connection %p (%d, %d) "
-				"flags %04x\n", tcpconn, tcpconn->id,
-				tcpconn->s, tcpconn->flags);
+		LM_DBG("destroying connection %p (%d, %d) flags %04x\n",
+				tcpconn, tcpconn->id, tcpconn->s, tcpconn->flags);
 		if (unlikely(tcpconn->flags & F_CONN_HASHED)){
 			LM_CRIT("called with hashed connection (%p)\n", tcpconn);
 			/* try to continue */
@@ -3301,8 +3211,8 @@ inline static int handle_tcp_child(struct tcp_child* tcp_c, int fd_i)
 	if (unlikely(bytes<(int)sizeof(response))){
 		if (bytes==0){
 			/* EOF -> bad, child has died */
-			DBG("DBG: handle_tcp_child: dead tcp child %d (pid %ld, no %d)"
-					" (shutting down?)\n", (int)(tcp_c-&tcp_children[0]), 
+			LM_DBG("dead tcp child %d (pid %ld, no %d) (shutting down?)\n",
+					(int)(tcp_c-&tcp_children[0]), 
 					(long)tcp_c->pid, tcp_c->proc_no );
 			/* don't listen on it any more */
 			io_watch_del(&io_h, tcp_c->unix_sock, fd_i, 0); 
@@ -3329,7 +3239,7 @@ inline static int handle_tcp_child(struct tcp_child* tcp_c, int fd_i)
 		}
 	}
 	
-	DBG("handle_tcp_child: reader response= %lx, %ld from %d \n",
+	LM_DBG("reader response= %lx, %ld from %d \n",
 					response[0], response[1], (int)(tcp_c-&tcp_children[0]));
 	cmd=response[1];
 	tcpconn=(struct tcp_connection*)response[0];
@@ -3373,16 +3283,15 @@ inline static int handle_tcp_child(struct tcp_child* tcp_c, int fd_i)
 			}
 			/* update the timeout*/
 			t=get_ticks_raw();
-			con_lifetime=cfg_get(tcp, tcp_cfg, con_lifetime);
+			con_lifetime=tcpconn->lifetime;
 			tcpconn->timeout=t+con_lifetime;
 			crt_timeout=con_lifetime;
 #ifdef TCP_ASYNC
 			if (unlikely(cfg_get(tcp, tcp_cfg, async) && 
 							_wbufq_non_empty(tcpconn) )){
 				if (unlikely(TICKS_GE(t, tcpconn->wbuf_q.wr_timeout))){
-					DBG("handle_tcp_child: wr. timeout on CONN_RELEASE for %p "
-							"refcnt= %d\n", tcpconn,
-							atomic_get(&tcpconn->refcnt));
+					LM_DBG("wr. timeout on CONN_RELEASE for %p refcnt= %d\n",
+							tcpconn, atomic_get(&tcpconn->refcnt));
 					/* timeout */
 					if (unlikely(tcpconn->state==S_CONN_CONNECT)){
 #ifdef USE_DST_BLACKLIST
@@ -3457,7 +3366,7 @@ inline static int handle_tcp_child(struct tcp_child* tcp_c, int fd_i)
 #endif /* TCP_ASYNC */
 				break;
 			}
-			DBG("handle_tcp_child: CONN_RELEASE  %p refcnt= %d\n", 
+			LM_DBG("CONN_RELEASE  %p refcnt= %d\n", 
 							tcpconn, atomic_get(&tcpconn->refcnt));
 			break;
 		case CONN_ERROR:
@@ -3535,8 +3444,8 @@ inline static int handle_ser_child(struct process_table* p, int fd_i)
 		/* too few bytes read */
 		if (bytes==0){
 			/* EOF -> bad, child has died */
-			DBG("DBG: handle_ser_child: dead child %d, pid %d"
-					" (shutting down?)\n", (int)(p-&pt[0]), p->pid);
+			LM_DBG("dead child %d, pid %d (shutting down?)\n",
+					(int)(p-&pt[0]), p->pid);
 			/* don't listen on it any more */
 			io_watch_del(&io_h, p->unix_sock, fd_i, 0);
 			goto error; /* child dead => no further io events from it */
@@ -3563,7 +3472,7 @@ inline static int handle_ser_child(struct process_table* p, int fd_i)
 		}
 	}
 	ret=1; /* something was received, there might be more queued */
-	DBG("handle_ser_child: read response= %lx, %ld, fd %d from %d (%d)\n",
+	LM_DBG("read response= %lx, %ld, fd %d from %d (%d)\n",
 					response[0], response[1], fd, (int)(p-&pt[0]), p->pid);
 	cmd=response[1];
 	tcpconn=(struct tcp_connection*)response[0];
@@ -3707,9 +3616,8 @@ inline static int handle_ser_child(struct process_table* p, int fd_i)
 					local_timer_reinit(&tcpconn->timer);
 					local_timer_add(&tcp_main_ltimer, &tcpconn->timer,
 										tcpconn->wbuf_q.wr_timeout-t, t);
-					DBG("tcp_main: handle_ser_child: CONN_QUEUED_WRITE; %p "
-							"timeout adjusted to %d s\n", tcpconn, 
-							TICKS_TO_S(tcpconn->wbuf_q.wr_timeout-t));
+					LM_DBG("CONN_QUEUED_WRITE; %p timeout adjusted to %d s\n",
+							tcpconn, TICKS_TO_S(tcpconn->wbuf_q.wr_timeout-t));
 				}
 				if (!(tcpconn->flags & F_CONN_WRITE_W)){
 					tcpconn->flags|=F_CONN_WRITE_W;
@@ -3895,8 +3803,8 @@ inline static int send2child(struct tcp_connection* tcpconn)
 	tcp_children[idx].busy++;
 	tcp_children[idx].n_reqs++;
 	if (unlikely(min_busy)){
-		DBG("WARNING: send2child: no free tcp receiver, "
-				" connection passed to the least busy one (%d)\n",
+		LM_DBG("WARNING: no free tcp receiver, "
+				"connection passed to the least busy one (%d)\n",
 				min_busy);
 	}
 	LM_DBG("selected tcp worker %d %d(%ld) for activity on [%s], %p\n",
@@ -4056,7 +3964,7 @@ static inline int handle_new_connect(struct socket_info* si)
 		/* prepare it for passing to a child */
 		tcpconn->flags|=F_CONN_READER;
 		tcpconn_add(tcpconn);
-		DBG("handle_new_connect: new connection from %s: %p %d flags: %04x\n",
+		LM_DBG("new connection from %s: %p %d flags: %04x\n",
 			su2a(&su, sizeof(su)), tcpconn, tcpconn->s, tcpconn->flags);
 		if(unlikely(send2child(tcpconn)<0)){
 			tcpconn->flags&=~F_CONN_READER;
@@ -4219,7 +4127,7 @@ inline static int handle_tcpconn_ev(struct tcp_connection* tcpconn, short ev,
 #ifdef TCP_ASYNC
 send_to_child:
 #endif
-		DBG("tcp: DBG: sending to child, events %x\n", ev);
+		LM_DBG("sending to child, events %x\n", ev);
 #ifdef POLLRDHUP
 		tcpconn->flags|=((int)!(ev & (POLLRDHUP|POLLHUP|POLLERR)) -1) &
 							F_CONN_EOF_SEEN;
@@ -4316,7 +4224,7 @@ static ticks_t tcpconn_main_timeout(ticks_t t, struct timer_ln* tl, void* data)
 	/* or (struct tcp...*)(tl-offset(c->timer)) */
 	
 #ifdef TCP_ASYNC
-	DBG( "tcp_main: entering timer for %p (ticks=%d, timeout=%d (%d s), "
+	LM_DBG("entering timer for %p (ticks=%d, timeout=%d (%d s), "
 			"wr_timeout=%d (%d s)), write queue: %d bytes\n",
 			c, t, c->timeout, TICKS_TO_S(c->timeout-t),
 			c->wbuf_q.wr_timeout, TICKS_TO_S(c->wbuf_q.wr_timeout-t),
@@ -4362,7 +4270,7 @@ static ticks_t tcpconn_main_timeout(ticks_t t, struct timer_ln* tl, void* data)
 	TCP_EV_IDLE_CONN_CLOSED(0, &c->rcv);
 	TCP_STATS_CON_TIMEOUT();
 #endif /* TCP_ASYNC */
-	DBG("tcp_main: timeout for %p\n", c);
+	LM_DBG("timeout for %p\n", c);
 	if (likely(c->flags & F_CONN_HASHED)){
 		c->flags&=~(F_CONN_HASHED|F_CONN_MAIN_TIMER);
 		c->state=S_CONN_BAD;
diff --git a/tcp_options.c b/tcp_options.c
index 5069948..60eb2b3 100644
--- a/tcp_options.c
+++ b/tcp_options.c
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- * 
  * Copyright (C) 2007 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -15,18 +13,10 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/*
- * tcp options
- *
- * History:
- * --------
- *  2007-11-28  created by andrei
- *  2009-03-05  use cfg framework (andrei)
- */
 
 /*!
  * \file
- * \brief SIP-router core :: 
+ * \brief Kamailio core :: tcp options
  * \ingroup core
  * Module: \ref core
  */
diff --git a/tcp_options.h b/tcp_options.h
index ba9dd4b..f3b181d 100644
--- a/tcp_options.h
+++ b/tcp_options.h
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- * 
  * Copyright (C) 2007 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -15,12 +13,9 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/*
- * tcp options
+/*! \file
+ * \brief tcp options
  *
- * History:
- * --------
- *  2007-11-28  created by andrei
  */
 
 #ifndef tcp_options_h
diff --git a/tcp_read.c b/tcp_read.c
index 3d5fb19..2e1d3f2 100644
--- a/tcp_read.c
+++ b/tcp_read.c
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,29 +17,8 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/*
- * History:
- * --------
- * 2002-12-??  created by andrei.
- * 2003-02-10  zero term before calling receive_msg & undo afterward (andrei)
- * 2003-05-13  l: (short form of Content-Length) is now recognized (andrei)
- * 2003-07-01  tcp_read & friends take no a single tcp_connection 
- *              parameter & they set c->state to S_CONN_EOF on eof (andrei)
- * 2003-07-04  fixed tcp EOF handling (possible infinite loop) (andrei)
- * 2005-07-05  migrated to the new io_wait code (andrei)
- * 2006-02-03  use tsend_stream instead of send_all (andrei)
- * 2006-10-13  added STUN support - state machine for TCP (vlada)
- * 2007-02-20  fixed timeout calc. bug (andrei)
- * 2007-11-26  improved tcp timers: switched to local_timer (andrei)
- * 2008-02-04  optimizations: handle POLLRDHUP (if supported), detect short
- *              reads (sock. buffer empty) (andrei)
- * 2009-02-26  direct blacklist support (andrei)
- * 2009-04-09  tcp ev and tcp stats macros added (andrei)
- * 2010-05-14  split tcp_read() into tcp_read() and tcp_read_data() (andrei)
- * 2010-05-17  new RD_CONN_REPEAT_READ flag, used by the tls hooks (andrei)
- */
 
-/** tcp readers processes, tcp read and pre-parse msg. functions.
+/** Kamailio core :: tcp readers processes, tcp read and pre-parse msg. functions.
  * @file tcp_read.c
  * @ingroup core
  * Module: @ref core
@@ -303,7 +275,7 @@ again:
 					(*flags & RD_CONN_FORCE_EOF))){
 			c->state=S_CONN_EOF;
 			*flags|=RD_CONN_EOF;
-			DBG("EOF on %p, FD %d\n", c, fd);
+			LM_DBG("EOF on %p, FD %d\n", c, fd);
 		}else{
 			if (unlikely(c->state==S_CONN_CONNECT || c->state==S_CONN_ACCEPT)){
 				TCP_STATS_ESTABLISHED(c->state);
@@ -357,7 +329,7 @@ int tcp_read(struct tcp_connection *c, int* flags)
 		return -1;
 	}
 #ifdef EXTRA_DEBUG
-	DBG("tcp_read: read %d bytes:\n%.*s\n", bytes_read, bytes_read, r->pos);
+	LM_DBG("read %d bytes:\n%.*s\n", bytes_read, bytes_read, r->pos);
 #endif
 	r->pos+=bytes_read;
 	return bytes_read;
@@ -535,8 +507,7 @@ int tcp_read_headers(struct tcp_connection *c, int* read_flags)
 								p++;
 								goto skip;
 							} else {
-								DBG("tcp_read_headers: ERROR: no clen, p=%X\n",
-										*p);
+								LM_DBG("ERROR: no clen, p=%X\n", *p);
 								r->error=TCP_REQ_BAD_LEN;
 							}
 						}
@@ -608,8 +579,7 @@ int tcp_read_headers(struct tcp_connection *c, int* read_flags)
 							p++;
 							goto skip;
 						} else {
-							DBG("tcp_read_headers: ERROR: no clen, p=%X\n",
-									*p);
+							LM_DBG("ERROR: no clen, p=%X\n", *p);
 							r->error=TCP_REQ_BAD_LEN;
 						}
 					}
@@ -656,7 +626,7 @@ int tcp_read_headers(struct tcp_connection *c, int* read_flags)
 						/* body will used as pointer to the last used byte */
 							r->body=p;
 							r->content_len = 0;
-							DBG("stun msg detected\n");
+							LM_DBG("stun msg detected\n");
 						} else {
 							r->state=H_SKIP;
 						}
@@ -1314,10 +1284,10 @@ again:
 				bytes=tcp_read_headers(con, read_flags);
 #ifdef EXTRA_DEBUG
 						/* if timeout state=0; goto end__req; */
-			DBG("read= %d bytes, parsed=%d, state=%d, error=%d\n",
+			LM_DBG("read= %d bytes, parsed=%d, state=%d, error=%d\n",
 					bytes, (int)(req->parsed-req->start), req->state,
 					req->error );
-			DBG("tcp_read_req: last char=0x%02X, parsed msg=\n%.*s\n",
+			LM_DBG("last char=0x%02X, parsed msg=\n%.*s\n",
 					*(req->parsed-1), (int)(req->parsed-req->start),
 					req->start);
 #endif
@@ -1335,7 +1305,7 @@ again:
 			 */
 			if (unlikely((con->state==S_CONN_EOF) && 
 						(! TCP_REQ_COMPLETE(req)))) {
-				DBG( "tcp_read_req: EOF\n");
+				LM_DBG("EOF\n");
 				resp=CONN_EOF;
 				goto end_req;
 			}
@@ -1345,23 +1315,23 @@ again:
 					req->state, req->error,
 					(int)(req->pos-req->buf), req->buf,
 					(int)(req->parsed-req->start), req->start);
-			DBG("- received from: port %d\n", con->rcv.src_port);
-			print_ip("- received from: ip ",&con->rcv.src_ip, "\n");
+			LM_DBG("received from: port %d\n", con->rcv.src_port);
+			print_ip("received from: ip", &con->rcv.src_ip, "\n");
 			resp=CONN_ERROR;
 			goto end_req;
 		}
 		if (likely(TCP_REQ_COMPLETE(req))){
 #ifdef EXTRA_DEBUG
-			DBG("tcp_read_req: end of header part\n");
-			DBG("- received from: port %d\n", con->rcv.src_port);
-			print_ip("- received from: ip ", &con->rcv.src_ip, "\n");
-			DBG("tcp_read_req: headers:\n%.*s.\n",
+			LM_DBG("end of header part\n");
+			LM_DBG("received from: port %d\n", con->rcv.src_port);
+			print_ip("received from: ip", &con->rcv.src_ip, "\n");
+			LM_DBG("headers:\n%.*s.\n",
 					(int)(req->body-req->start), req->start);
 #endif
 			if (likely(TCP_REQ_HAS_CLEN(req))){
-				DBG("tcp_read_req: content-length= %d\n", req->content_len);
+				LM_DBG("content-length=%d\n", req->content_len);
 #ifdef EXTRA_DEBUG
-				DBG("tcp_read_req: body:\n%.*s\n", req->content_len,req->body);
+				LM_DBG("body:\n%.*s\n", req->content_len,req->body);
 #endif
 			}else{
 				if (cfg_get(tcp, tcp_cfg, accept_no_cl)==0) {
@@ -1374,7 +1344,7 @@ again:
 			/* if we are here everything is nice and ok*/
 			resp=CONN_RELEASE;
 #ifdef EXTRA_DEBUG
-			DBG("receiving msg(%p, %d, )\n",
+			LM_DBG("receiving msg(%p, %d)\n",
 					req->start, (int)(req->parsed-req->start));
 #endif
 			/* rcv.bind_address should always be !=0 */
@@ -1453,13 +1423,12 @@ again:
 				memmove(req->buf, req->parsed, size);
 				req->parsed=req->buf; /* fix req->parsed after using it */
 #ifdef EXTRA_DEBUG
-				DBG("tcp_read_req: preparing for new request, kept %ld"
-						" bytes\n", size);
+				LM_DBG("preparing for new request, kept %ld bytes\n", size);
 #endif
 				/*if we still have some unparsed bytes, try to parse them too*/
 				goto again;
 			} else if (unlikely(con->state==S_CONN_EOF)){
-				DBG( "tcp_read_req: EOF after reading complete request\n");
+				LM_DBG("EOF after reading complete request\n");
 				resp=CONN_EOF;
 			}
 			req->parsed=req->buf; /* fix req->parsed */
@@ -1477,9 +1446,9 @@ void release_tcpconn(struct tcp_connection* c, long state, int unix_sock)
 {
 	long response[2];
 	
-		DBG( "releasing con %p, state %ld, fd=%d, id=%d\n",
+		LM_DBG("releasing con %p, state %ld, fd=%d, id=%d\n",
 				c, state, c->fd, c->id);
-		DBG(" extra_data %p\n", c->extra_data);
+		LM_DBG("extra_data %p\n", c->extra_data);
 		/* release req & signal the parent */
 		c->reader_pid=0; /* reset it */
 		if (c->fd!=-1){
@@ -1551,7 +1520,7 @@ inline static int handle_io(struct fd_map* fm, short events, int idx)
 		case F_TCPMAIN:
 again:
 			ret=n=receive_fd(fm->fd, &con, sizeof(con), &s, 0);
-			DBG("received n=%d con=%p, fd=%d\n", n, con, s);
+			LM_DBG("received n=%d con=%p, fd=%d\n", n, con, s);
 			if (unlikely(n<0)){
 				if (errno == EWOULDBLOCK || errno == EAGAIN){
 					ret=0;
diff --git a/tcp_read.h b/tcp_read.h
index 581899b..23c39eb 100644
--- a/tcp_read.h
+++ b/tcp_read.h
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- * 
  * Copyright (C) 2010 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -15,16 +13,12 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/** tcp internal read functions.
+
+/** Kamailio core :: tcp internal read functions.
  * @file tcp_read.h
  * @ingroup: core
  * Module: @ref core
  */
-/*
- * History:
- * --------
- *  2010-05-18  initial version (andrei)
-*/
 
 #ifndef __tcp_read_h
 #define __tcp_read_h
diff --git a/tcp_server.h b/tcp_server.h
index 39de44b..0566c50 100644
--- a/tcp_server.h
+++ b/tcp_server.h
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/tcp_stats.c b/tcp_stats.c
index dc2dd61..3dac067 100644
--- a/tcp_stats.c
+++ b/tcp_stats.c
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- * 
  * Copyright (C) 2010 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -15,15 +13,12 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/** tcp statistics.
+
+/** Kamailio core :: TCP statistics.
  * @file tcp_stats.c
  * @ingroup:  core
+ * Module: \ref core
  */
-/*
- * History:
- * --------
- *  2010-08-08  initial version (andrei)
-*/
 
 #ifdef USE_TCP
 #include "tcp_stats.h"
diff --git a/tcp_stats.h b/tcp_stats.h
index 8465b29..c693d94 100644
--- a/tcp_stats.h
+++ b/tcp_stats.h
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- * 
  * Copyright (C) 2009 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -15,14 +13,10 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/*
- * tcp_stats.h - tcp statistics macros
+/*! \file
+ * \brief Kamailio core :: tcp_stats.h - tcp statistics macros
+ * \ingroup core
  */
-/*
- * History:
- * --------
- *  2009-04-08  initial version (andrei)
-*/
 
 #ifndef __tcp_stats_h
 #define __tcp_stats_h
diff --git a/test/acc-test.cfg b/test/acc-test.cfg
new file mode 100644
index 0000000..ad7c185
--- /dev/null
+++ b/test/acc-test.cfg
@@ -0,0 +1,170 @@
+#
+# iptel.org real world configuration
+#
+
+# ----------- global configuration parameters ------------------------
+
+# we're debugging now
+
+debug=9          # debug level (cmd line: -dddddddddd)
+fork=no
+log_stderror=yes	# (cmd line: -E)
+
+#fork=yes
+#children=16
+#log_stderror=no	# (cmd line: -E)
+
+check_via=yes     # (cmd. line: -v)
+dns=on           # (cmd. line: -r)
+rev_dns=yes      # (cmd. line: -R)
+
+# experimental usage at port 5060
+#port=9060
+#port=8060
+port=5060
+# advertise IP address in Via (as opposed to advertising DNS name
+# which is annoying for downstream servers and some phones can
+# not handle DNS at all)
+#listen=195.37.77.101
+#listen=193.175.135.170
+# ------------------ module loading ----------------------------------
+
+loadmodule "../sip_router/modules/sl/sl.so"
+loadmodule "../sip_router/modules/print/print.so"
+loadmodule "../sip_router/modules/tm/tm_mod.so"
+#loadmodule "../sip_router/modules/acc/acc.so"
+loadmodule "../sip_router/modules/rr/rr.so"
+loadmodule "../sip_router/modules/maxfwd/maxfwd.so"
+#loadmodule "../sip_router/modules/mysql/mysql.so"
+loadmodule "../sip_router/modules/usrloc/usrloc.so"
+#loadmodule "../sip_router/modules/auth/auth.so"
+#loadmodule "../sip_router/modules/cpl/cpl.so"
+loadmodule "../sip_router/modules/radius_acc/radius_acc.so"
+loadmodule "../sip_router/modules/registrar/registrar.so"
+
+
+# ----------------- setting module-specific parameters ---------------
+
+# -- usrloc params --
+
+# use in-RAM usrloc
+#modparam("usrloc", "use_db", 0)
+
+# -- acc params --
+# report ACKs too for sake of completeness -- as we account PSTN
+# destinations which are RR, ACKs should show up
+#modparam("acc", "report_ack", 1)
+# don't bother me with early media reports (I don't like 183 
+# too much anyway...ever thought of timer C hitting after
+# listening to music-on-hold for five minutes?)
+#modparam("acc", "early_media", 0)
+#modparam("acc", "log_level", 1)
+# that is the flag for which we will account -- don't forget to
+# set the same one :-)
+#modparam("acc", "acc_flag", 1 )
+# we are interested only in succesful transactions
+#modparam("acc", "failed_transactions", 0 )
+
+
+# -- acc params --
+# report ACKs too for sake of completeness -- as we account PSTN
+# destinations which are RR, ACKs should show up
+modparam("radius_acc", "report_ack", 1)
+# don't bother me with early media reports (I don't like 183
+# too much anyway...ever thought of timer C hitting after
+# listening to music-on-hold for five minutes?)
+modparam("radius_acc", "early_media", 0)
+modparam("radius_acc", "log_level", 1)
+# that is the flag for which we will account -- don't forget to
+# set the same one :-)
+modparam("radius_acc", "acc_flag", 1 )
+# we are interested only in succesful transactions
+modparam("radius_acc", "failed_transactions", 0 )
+
+# -- tm params --
+modparam("tm", "fr_timer", 30 )
+modparam("tm", "fr_inv_timer", 60 )
+
+# -------------------------  request routing logic -------------------
+
+# main routing logic
+
+route{
+
+	# filter local stateless ACK generated by authentication of mf replies
+	sl_filter_ACK();
+
+	# filter too old messages
+	log("LOG: Checking maxfwd\n");
+	if (!mf_process_maxfwd_header("10")) {
+		log("LOG: Too many hops\n");
+		sl_send_reply("483","Too Many Hops");
+		break;
+	};
+
+	# len_gt *after* max_fwd, otherwise an "INVITE sip:sos at 0.0.0.0"
+	# will cause "message too big" for a short message
+
+	if (len_gt( max_len )) {
+		sl_send_reply("513", "Riesengross -- Message too large");
+		break;
+	};
+
+	# Do strict routing if route headers present
+	if (method=="INVITE") {
+		addRecordRoute();
+	} else {
+		rewriteFromRoute();
+	};
+
+
+	# that is outbound request...
+
+	if (!(uri=~"fox\.iptel\.org([;:].*)*" 
+		| uri=~"[@:\.]195\.37\.77\.101([;:].*)*"  )) {
+		route(2);
+		# break from route (2) return -- stop then !
+		break;
+	};
+	# here we continue with requests for our domain...
+
+	if (method=="REGISTER") {
+		# update Contact database
+       	log("LOG: REGISTER is authorized, saving location\n");
+		save("location");
+		break;
+	};
+
+	# native SIP destinations are handled using our USRLOC DB
+	if (!lookup("location")) {
+		if (method=="ACK") {
+			log("Ooops -- an ACK made it here -- probably UAC screwed up to-tags\n");
+			break;
+		};
+		log("LOG: Unable to lookup contact, sending 404\n");
+		sl_send_reply("404", "Not Found");
+		break;
+	};
+
+	# label for accounting
+	setflag(1);
+	# we now know we may, we know where, let it go out now!
+	if (!t_relay()) {
+		sl_reply_error();
+		break;
+	};
+}
+#---------------------------------------------------------------------
+
+# routing logic for outbound requests targeted out of our domain
+# -- use outbound proxy iptel.org (note that except to FOKUS/PBX,
+# or itpel.org users, requests will be challenged)
+route[2] {
+		log("LOG: that's a request to outside");
+		# label for accounting
+		setflag(1);
+		if (!t_relay_to("fox.iptel.org", "5060")) {
+			sl_reply_error();
+			break;
+		};
+}
diff --git a/test/atomic_test.c b/test/atomic_test.c
new file mode 100644
index 0000000..a013a0c
--- /dev/null
+++ b/test/atomic_test.c
@@ -0,0 +1,102 @@
+/*
+ *
+ *  simple atomic ops testing program
+ *  (no paralel stuff, just see if the opcodes are "legal")
+ * 
+ *  Compile with: gcc -Wall -O3 -D__CPU_i386  on x86 machines
+ *                gcc -Wall -O3 -D__CPU_x86_64 on amd64 machines
+ *                gcc -mips2 -Wall -O2 -D__CPU_mips2  on mips machines
+ *                gcc -m64 -Wall -O2 -D__CPU_mips64 on mips64 machines
+ *                gcc -O3 -Wall -D__CPU_ppc on powerpc machines
+ *                gcc -m64 -O3 -Wall -D__CPU_ppc64 on powerpc machines
+ *                gcc -m64 -O3 -Wall -D__CPU_sparc64 -DSPARC64_MODE on 
+ *                                                   ultrasparc machines
+ *  -- andrei
+ *
+ *  
+ */
+
+#include <stdio.h>
+
+#define CC_GCC_LIKE_ASM
+
+#include "../atomic_ops.h"
+
+#ifdef ATOMIC_OPS_USE_LOCK 
+/* hack to make lock work */
+#include "../lock_ops.h"
+
+gen_lock_t* _atomic_lock;
+
+gen_lock_t dummy_lock;
+
+#endif
+
+int main(int argc, char** argv)
+{
+	int r;
+	atomic_t v;
+#ifdef ATOMIC_OPS_USE_LOCK
+	/* init the lock (emulate atomic_ops.c) */
+	_atomic_lock=&dummy_lock;
+	if (lock_init(_atomic_lock)==0){
+		fprintf(stderr, "ERROR: failed to initialize the lock\n");
+		goto error;
+	}
+#endif
+	
+#ifdef NOSMP
+	printf("no-smp mode\n");
+#else
+	printf("smp mode\n");
+#endif
+	
+	printf("starting memory barrier opcode tests...\n");
+	membar();
+	printf(" membar() .............................. ok\n");
+	membar_write();
+	printf(" membar_write() ........................ ok\n");
+	membar_read();
+	printf(" membar_read() ......................... ok\n");
+	
+	printf("\nstarting atomic ops basic tests...\n");
+	
+	mb_atomic_set(&v, 1);
+	printf(" atomic_set, v should be 1 ............. %2d\n", mb_atomic_get(&v));
+	mb_atomic_inc(&v);
+	printf(" atomic_inc, v should be 2 ............. %2d\n", mb_atomic_get(&v));
+	r=mb_atomic_inc_and_test(&v);
+	printf(" atomic_inc_and_test, v should be  3 ... %2d\n", mb_atomic_get(&v));
+	printf("                      r should be  0 ... %2d\n", r);
+	
+	mb_atomic_dec(&v);
+	printf(" atomic_dec, v should be 2 ............. %2d\n", mb_atomic_get(&v));
+	r=mb_atomic_dec_and_test(&v);
+	printf(" atomic_dec_and_test, v should be  1 ... %2d\n", mb_atomic_get(&v));
+	printf("                      r should be  0 ... %2d\n", r);
+	r=mb_atomic_dec_and_test(&v);
+	printf(" atomic_dec_and_test, v should be  0 ... %2d\n", mb_atomic_get(&v));
+	printf("                      r should be  1 ... %2d\n", r);
+	r=mb_atomic_dec_and_test(&v);
+	printf(" atomic_dec_and_test, v should be -1 ... %2d\n", mb_atomic_get(&v));
+	printf("                      r should be  0 ... %2d\n", r);
+	
+	mb_atomic_and(&v, 2);
+	printf(" atomic_and, v should be 2 ............. %2d\n", mb_atomic_get(&v));
+	
+	mb_atomic_or(&v, 5);
+	r=mb_atomic_get_and_set(&v, 0);
+	printf(" atomic_or,  v should be 7 ............. %2d\n", r);
+	printf(" atomic_get_and_set, v should be 0 ..... %2d\n", mb_atomic_get(&v));
+
+	
+	printf("\ndone.\n");
+#ifdef ATOMIC_OPS_USE_LOCK
+	lock_destroy(_atomic_lock);
+#endif
+	return 0;
+#ifdef ATOMIC_OPS_USE_LOCK
+error:
+	return -1;
+#endif
+}
diff --git a/test/atomic_test2.c b/test/atomic_test2.c
new file mode 100644
index 0000000..9048c3c
--- /dev/null
+++ b/test/atomic_test2.c
@@ -0,0 +1,301 @@
+/*
+ *
+ *  simple atomic ops testing program
+ *  (no paralel stuff, just see if the opcodes are "legal")
+ *
+ *  Defines: TYPE - not defined => use atomic_t and the corresponding
+ *                  atomic functions
+ *                - long => use volatile long* and  the atomic_*_long functions
+ *                - int  => use volatile int* and the atomic_*_int functions
+ *           MEMBAR - if defined use mb_atomic_* instead of atomic_*
+ *           NOSMP - use non smp versions
+ *           NOASM - don't use asm inline version
+ *           __CPU_xxx - use __CPU_xxx code
+ *           SPARC64_MODE - compile for a sparc 64 in 64 bit mode (gcc -m64
+ *                          must be used on solaris in this case)
+ *  Example:  
+ *    gcc -Wall -O3 -D__CPU_i386 -DNOSMP -DMEMBAR -DTYPE=long atomic_test2.c
+ * 
+ *  Compile with: gcc -Wall -O3 -D__CPU_i386  ... on x86 machines
+ *                gcc -Wall -O3 -D__CPU_x86_64 ... on amd64 machines
+ *                gcc -mips2 -Wall -O2 -D__CPU_mips2  ... on mips machines
+ *                gcc -m64 -Wall -O2 -D__CPU_mips64 ... on mips64 machines
+ *                gcc -O3 -Wall -D__CPU_ppc ... on powerpc machines
+ *                gcc -m64 -O3 -Wall -D__CPU_ppc64 ... on powerpc machines
+ *                gcc -m64 -O3 -Wall -D__CPU_sparc64 -DSPARC64_MODE ... on 
+ *                                                   ultrasparc machines
+ *                gcc -mcpu=v9 -O3 -Wall -D__CPU_sparc64  ... for 32 bit code 
+ *                                                   (sparc32plus) on 
+ *                                                   ultrasparc machines
+ *                gcc -O3 -Wall -D__CPU_sparc ... on sparc v8 machines
+ *  -- andrei
+ *
+ *  
+ */
+
+#include <stdio.h>
+
+#ifndef NOASM
+#define CC_GCC_LIKE_ASM
+#endif
+
+#include "../atomic_ops.h"
+
+#if defined ATOMIC_OPS_USE_LOCK  || defined MEMBAR_USES_LOCK || \
+	defined ATOMIC_OPS_USE_LOCK_SET
+/* hack to make lock work */
+#include "../lock_ops.h"
+#endif
+
+#ifdef MEMBAR_USES_LOCK
+gen_lock_t* __membar_lock=0; /* init in atomic_ops.c */
+gen_lock_t dummy_membar_lock;
+#endif
+
+#ifdef ATOMIC_OPS_USE_LOCK_SET
+gen_lock_set_t* _atomic_lock_set=0;
+gen_lock_set_t dummy_atomic_lock_set;
+gen_lock_t locks_array[_ATOMIC_LS_SIZE];
+#elif defined ATOMIC_OPS_USE_LOCK
+gen_lock_t* _atomic_lock=0;
+gen_lock_t dummy_atomic_lock;
+#endif /* ATOMIC_OPS_USE_LOCK / _SET */
+
+
+
+
+#if defined MB || defined MEMBAR
+#undef MB
+#define MB mb_
+#define MEMBAR_STR "membar "
+#else
+#define MB  /* empty */
+#define MEMBAR_STR ""
+#endif
+
+#ifndef TYPE
+#define SUF
+#define ATOMIC_TYPE atomic_t
+#define VALUE_TYPE volatile int
+#define get_val(v)	(v->val)
+#else
+#define _SUF(T) _##T
+#define _SUF1(T) _SUF(T)
+#define SUF _SUF1(TYPE)
+#define ATOMIC_TYPE volatile TYPE
+#define VALUE_TYPE ATOMIC_TYPE
+#define get_val(v)	(*v)
+#endif
+
+
+#define _STR(S) #S
+#define STR(S) _STR(S)
+
+static char* flags=
+#ifdef NOASM
+	"no_inline_asm "
+#endif
+#ifdef NOSMP
+	"nosmp "
+#else
+	"smp "
+#endif
+	MEMBAR_STR
+#ifndef HAVE_ASM_INLINE_MEMBAR
+	"no_asm_membar(slow) "
+#endif
+#ifndef HAVE_ASM_INLINE_ATOMIC_OPS
+	"no_asm_atomic_ops"
+#ifdef ATOMIC_OPS_USE_LOCK_SET
+	":use_lock_set"
+#elif defined ATOMIC_OPS_USE_LOCK
+	":use_lock"
+#endif
+	" "
+#endif
+#ifdef TYPE
+	STR(TYPE) " "
+#else
+	"atomic_t "
+#endif
+;
+
+
+
+/* macros for atomic_* functions */
+
+#define _AT_DECL(OP, P, S) \
+	P##atomic_##OP##S
+
+
+/* to make sure all the macro passed as params are expanded,
+ *  go through a 2 level deep macro decl. */
+#define _AT_DECL1(OP, P, S) _AT_DECL(OP, P, S)
+#define AT_DECL(OP) _AT_DECL1(OP, MB, SUF)
+
+
+#define at_set	AT_DECL(set)
+#define at_get	AT_DECL(get)
+
+#define at_inc	AT_DECL(inc)
+#define at_dec	AT_DECL(dec)
+#define at_inc_and_test	AT_DECL(inc_and_test)
+#define at_dec_and_test	AT_DECL(dec_and_test)
+#define at_and	AT_DECL(and)
+#define at_or	AT_DECL(or)
+#define at_get_and_set	AT_DECL(get_and_set)
+#define at_cmpxchg	AT_DECL(cmpxchg)
+#define at_add	AT_DECL(add)
+
+
+#define CHECK_ERR(txt, x, y) \
+	if (x!=y) { \
+		fprintf(stderr, "ERROR: line %d: %s failed: expected 0x%02x but got "\
+						"0x%02x.\n", \
+						__LINE__, #txt, (unsigned) x, (unsigned) y);\
+		goto error; \
+	}
+
+#define VERIFY(ops, y) \
+	ops ; \
+	CHECK_ERR( ops, y, get_val(v))
+
+
+int main(int argc, char** argv)
+{
+	ATOMIC_TYPE var;
+	VALUE_TYPE r;
+	
+	ATOMIC_TYPE* v;
+	
+	v=&var;
+	
+	
+#ifdef MEMBAR_USES_LOCK
+	__membar_lock=&dummy_membar_lock;
+	if (lock_init(__membar_lock)==0){
+		fprintf(stderr, "ERROR: failed to initialize membar_lock\n");
+		__membar_lock=0;
+		goto error;
+	}
+	_membar_lock; /* start with the lock "taken" so that we can safely use
+					 unlock/lock sequences on it later */
+#endif
+#ifdef ATOMIC_OPS_USE_LOCK_SET
+	/* init the lock (emulate atomic_ops.c) */
+	dummy_atomic_lock_set.locks=&locks_array[0];
+	_atomic_lock_set=&dummy_atomic_lock_set;
+	if (lock_set_init(_atomic_lock_set)==0){
+		fprintf(stderr, "ERROR: failed to initialize atomic_lock\n");
+		_atomic_lock_set=0;
+		goto error;
+	}
+#elif defined ATOMIC_OPS_USE_LOCK
+	/* init the lock (emulate atomic_ops.c) */
+	_atomic_lock=&dummy_atomic_lock;
+	if (lock_init(_atomic_lock)==0){
+		fprintf(stderr, "ERROR: failed to initialize atomic_lock\n");
+		_atomic_lock=0;
+		goto error;
+	}
+#endif
+	
+	printf("%s\n", flags);
+	
+	printf("starting memory barrier opcode tests...\n");
+	membar();
+	printf(" membar() .............................. ok\n");
+	membar_write();
+	printf(" membar_write() ........................ ok\n");
+	membar_read();
+	printf(" membar_read() ......................... ok\n");
+	membar_depends();
+	printf(" membar_depends() ...................... ok\n");
+	membar_enter_lock();
+	printf(" membar_enter_lock() ................... ok\n");
+	membar_leave_lock();
+	printf(" membar_leave_lock() ................... ok\n");
+	membar_atomic_op();
+	printf(" membar_atomic_op() .................... ok\n");
+	membar_atomic_setget();
+	printf(" membar_atomic_setget() ................ ok\n");
+	membar_read_atomic_op();
+	printf(" membar_read_atomic_op() ............... ok\n");
+	membar_read_atomic_setget();
+	printf(" membar_read_atomic_setget() ........... ok\n");
+	membar_write_atomic_op();
+	printf(" membar_write_atomic_op() .............. ok\n");
+	membar_write_atomic_setget();
+	printf(" membar_write_atomic_setget() .......... ok\n");
+	
+	printf("\nstarting atomic ops basic tests...\n");
+	
+	VERIFY(at_set(v, 1), 1);
+	printf(" atomic_set, v should be 1 ............. %2d\n", (int)at_get(v));
+	VERIFY(at_inc(v), 2);
+	printf(" atomic_inc, v should be 2 ............. %2d\n", (int)at_get(v));
+	VERIFY(r=at_inc_and_test(v), 3);
+	printf(" atomic_inc_and_test, v should be  3 ... %2d\n", (int)at_get(v));
+	printf("                      r should be  0 ... %2d\n", (int)r);
+	
+	VERIFY(at_dec(v), 2);
+	printf(" atomic_dec, v should be 2 ............. %2d\n", (int)at_get(v));
+	VERIFY(r=at_dec_and_test(v), 1);
+	printf(" atomic_dec_and_test, v should be  1 ... %2d\n", (int)at_get(v));
+	printf("                      r should be  0 ... %2d\n", (int)r);
+	VERIFY(r=at_dec_and_test(v), 0);
+	printf(" atomic_dec_and_test, v should be  0 ... %2d\n", (int)at_get(v));
+	printf("                      r should be  1 ... %2d\n", (int)r);
+	VERIFY(r=at_dec_and_test(v), -1);
+	printf(" atomic_dec_and_test, v should be -1 ... %2d\n", (int)at_get(v));
+	printf("                      r should be  0 ... %2d\n", (int)r);
+	
+	VERIFY(at_and(v, 2), 2);
+	printf(" atomic_and, v should be 2 ............. %2d\n", (int)at_get(v));
+	
+	VERIFY(at_or(v, 5), 7);
+	printf(" atomic_or,  v should be 7 ............. %2d\n", (int)at_get(v));
+	VERIFY(r=at_get_and_set(v, 0), 0);
+	printf(" atomic_get_and_set, v should be 0 ..... %2d\n", (int)at_get(v));
+	VERIFY(r=at_cmpxchg(v, 0, 7), 7);
+	CHECK_ERR(cmpxchg, r, 0);
+	printf(" atomic_cmpxchg, v should be 7 ......... %2d\n", (int)at_get(v));
+	printf("                 r should be 0 ......... %2d\n", (int)r);
+	VERIFY(r=at_cmpxchg(v, 2, 3), 7);
+	CHECK_ERR(cmpxchg, r, 7);
+	printf(" atomic_cmpxchg (fail), v should be 7 .. %2d\n", (int)at_get(v));
+	printf("                        r should be 7 .. %2d\n", (int)r);
+	VERIFY(r=at_add(v, 2), 9);
+	CHECK_ERR(atomic_add, r, 9);
+	printf(" atomic_add, v should be 9 ............. %2d\n", (int)at_get(v));
+	printf("             r should be 9 ............. %2d\n", (int)r);
+	VERIFY(r=at_add(v, -10), -1);
+	CHECK_ERR(atomic_add, r, -1);
+	printf(" atomic_add, v should be -1 ............ %2d\n", (int)at_get(v));
+	printf("             r should be -1 ............ %2d\n", (int)r);
+
+	
+	printf("\ndone.\n");
+#ifdef MEMBAR_USES_LOCK
+	lock_destroy(__membar_lock);
+#endif
+#ifdef ATOMIC_OPS_USE_LOCK_SET
+	lock_set_destroy(_atomic_lock_set);
+#elif defined ATOMIC_OPS_USE_LOCK
+	lock_destroy(_atomic_lock);
+#endif
+	return 0;
+error:
+#ifdef MEMBAR_USES_LOCK
+	if (__membar_lock)
+		lock_destroy(__membar_lock);
+#endif
+#ifdef ATOMIC_OPS_USE_LOCK_SET
+	if (_atomic_lock_set)
+		lock_set_destroy(_atomic_lock_set);
+#elif defined ATOMIC_OPS_USE_LOCK
+	if (_atomic_lock)
+		lock_destroy(_atomic_lock);
+#endif
+	return -1;
+}
diff --git a/test/auto.c b/test/auto.c
new file mode 100644
index 0000000..b7bcdd4
--- /dev/null
+++ b/test/auto.c
@@ -0,0 +1,439 @@
+
+/* test program -> switch speed */
+/*
+ *
+ * Copyright (C) 2001-2003 FhG Fokus
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+
+
+/* parsing:           compact form:
+ * Via:               v:
+ * From:              f:
+ * To:                t:
+ * Cseq:              n/a
+ * Call-ID:           i:
+ * Contact:           m:
+ * Max-Forwards:      n/a
+ * Route:             n/a
+ */
+
+enum { INITIAL=0,
+		VIA1, VIA2,
+		FROM1, FROM2, FROM3,
+		TO1,
+		C_START, CSEQ2, CSEQ3,
+		         CALLID2, CALLID3, CALLID4, CALLID5, CALLID6,
+		         CONTACT2, CONTACT3, CONTACT4, CONTACT5, CONTACT6,
+		M_START,      MAXFORWARDS2, MAXFORWARDS3, MAXFORWARDS4, MAXFORWARDS5,
+		MAXFORWARDS6, MAXFORWARDS7, MAXFORWARDS8, MAXFORWARDS9, MAXFORWARDS10,
+		MAXFORWARDS11,
+		ROUTE1, ROUTE2, ROUTE3, ROUTE4,
+		/* final states*/
+		F_VIA=1000, F_FROM, F_TO, F_CSEQ, F_CALLID, F_CONTACT, F_MAXFORWARDS,
+		F_ROUTE,
+		I_START,
+
+		UNKNOWN_HEADER=200,
+		BODY=220,
+		LF=25000,
+	};
+
+#include <stdio.h>
+
+int main(int argc, char** argv)
+{
+
+	char* t;
+	register int state;
+	int i;
+	int err;
+	err=0;
+
+	state=INITIAL;
+	printf(" %s (%d)\n", argv[0], argc);
+	if (argc<2){
+			fprintf(stderr, " no parameters\n");
+			exit(-1);
+	}
+	
+	for (i=0;i<10000000;i++){
+		
+	for(t=argv[1];*t;t++){
+		switch(*t){
+			case 'V':
+			case 'v':
+					switch(state){
+						case INITIAL:
+							state=VIA1;
+							break;
+						case UNKNOWN_HEADER: break;
+						default:
+							state=UNKNOWN_HEADER;
+					}
+					break;
+			case 'I':
+			case 'i':
+					switch(state){
+						case VIA1:
+							state=VIA2;
+							break;
+						case CALLID5:
+							state=CALLID6;
+							break;
+						case INITIAL:
+							state=I_START;
+							break;
+						case UNKNOWN_HEADER: break;
+						default:
+							state=UNKNOWN_HEADER;
+					}
+					break;
+			case 'A':
+			case 'a':
+					switch(state){
+						case VIA2:
+								state=F_VIA;
+								break;
+						case C_START:  /*CALLID1*/
+								state=CALLID2;
+								break;
+						case CONTACT4:
+								state=CONTACT5;
+								break;
+						case M_START:
+								state=MAXFORWARDS2;
+								break;
+						case MAXFORWARDS8:
+								state=MAXFORWARDS9;
+								break;
+						case UNKNOWN_HEADER: break;
+						default:
+								state=UNKNOWN_HEADER;
+					}
+					break;
+			case 'F':
+			case 'f':
+					switch(state){
+						case INITIAL:
+								state=FROM1;
+								break;
+						case MAXFORWARDS4:
+								state=MAXFORWARDS5;
+								break;
+						case UNKNOWN_HEADER: break;
+						default:
+								state=UNKNOWN_HEADER;
+					}
+					break;
+			case 'R':
+			case 'r':
+					switch(state){
+						case INITIAL:
+							state=ROUTE1;
+							break;
+						case FROM1:
+							state=FROM2;
+							break;
+						case MAXFORWARDS6:
+							state=MAXFORWARDS7;
+							break;
+						case MAXFORWARDS9:
+							state=MAXFORWARDS10;
+							break;
+						case UNKNOWN_HEADER: break;
+						default:
+							state=UNKNOWN_HEADER;
+					}
+					break;
+			case 'O':
+			case 'o':
+					switch(state){
+						case FROM2:
+							state=FROM3;
+							break;
+						case TO1:
+							state=F_TO;
+							break;
+						case C_START: /*CONTACT1 */
+							state=CONTACT2;
+							break;
+						case ROUTE1:
+							state=ROUTE2;
+							break;
+						case MAXFORWARDS5:
+							state=MAXFORWARDS6;
+							break;
+						case UNKNOWN_HEADER: break;
+						default:
+							state=UNKNOWN_HEADER;
+					}
+					break;
+			case 'M':
+			case 'm':
+						switch(state){
+							case INITIAL:
+								state=M_START;
+								break;
+							case FROM3:
+								state=F_FROM;
+								break;
+							case UNKNOWN_HEADER: break;
+							default:
+								state=UNKNOWN_HEADER;
+						}
+						break;
+			case 'T':
+			case 't':
+						switch(state){
+							case INITIAL:
+								state=TO1;
+								break;
+							case CONTACT3:
+								state=CONTACT4;
+								break;
+							case CONTACT6:
+								state=F_CONTACT;
+								break;
+							case ROUTE3:
+								state=ROUTE4;
+								break;
+							case UNKNOWN_HEADER: break;
+							default:
+								state=UNKNOWN_HEADER;
+						}
+						break;
+			case 'C':
+			case 'c':
+						switch(state){
+							case INITIAL:
+								state=C_START;
+								break;
+							case CONTACT5:
+								state=CONTACT6;
+								break;
+							case UNKNOWN_HEADER: break;
+							default:
+								state=UNKNOWN_HEADER;
+						}
+						break;
+			case 'S':
+			case 's':
+						switch(state){
+							case C_START:
+								state=CSEQ2;
+								break;
+							case MAXFORWARDS11:
+								state=F_MAXFORWARDS;
+								break;
+							case UNKNOWN_HEADER: break;
+							default:
+								state=UNKNOWN_HEADER;
+						}
+						break;
+			case 'E':
+			case 'e':
+						switch(state){
+							case CSEQ2:
+								state=CSEQ3;
+								break;
+							case ROUTE4:
+								state=F_ROUTE;
+								break;
+							case UNKNOWN_HEADER: break;
+							default:
+								state=UNKNOWN_HEADER;
+						}
+						break;
+			case 'Q':
+			case 'q':
+						switch(state){
+							case CSEQ3:
+								state=F_CSEQ;
+								break;
+							case UNKNOWN_HEADER: break;
+							default:
+								state=UNKNOWN_HEADER;
+						}
+						break;
+			case 'L':
+			case 'l':
+						switch(state){
+							case CALLID2:
+								state=CALLID3;
+								break;
+							case CALLID3:
+								state=CALLID4;
+								break;
+							case UNKNOWN_HEADER: break;
+							default:
+								state=UNKNOWN_HEADER;
+						}
+						break;
+			case 'D':
+			case 'd':
+						switch(state){
+							case CALLID6:
+								state=F_CALLID;
+								break;
+							case MAXFORWARDS10:
+								state=MAXFORWARDS11;
+								break;
+							case UNKNOWN_HEADER: break;
+							default:
+								state=UNKNOWN_HEADER;
+						}
+						break;
+			case 'N':
+			case 'n':
+						switch(state){
+							case CONTACT2:
+								state=CONTACT3;
+								break;
+							case UNKNOWN_HEADER: break;
+							default:
+								state=UNKNOWN_HEADER;
+						}
+						break;
+			case 'X':
+			case 'x':
+						switch(state){
+							case MAXFORWARDS2:
+								state=MAXFORWARDS3;
+								break;
+							case UNKNOWN_HEADER: break;
+							default:
+								state=UNKNOWN_HEADER;
+						}
+						break;
+			case '-':
+						switch(state){
+							case CALLID4:
+								state=CALLID5;
+								break;
+							case MAXFORWARDS3:
+								state=MAXFORWARDS4;
+								break;
+							case UNKNOWN_HEADER: break;
+							default:
+								state=UNKNOWN_HEADER;
+						}
+						break;
+			case 'W':
+			case 'w':
+						switch(state){
+							case MAXFORWARDS7:
+								state=MAXFORWARDS8;
+								break;
+							case UNKNOWN_HEADER: break;
+							default:
+								state=UNKNOWN_HEADER;
+						}
+						break;
+			case 'U':
+			case 'u':
+						switch(state){
+							case ROUTE2:
+								state=ROUTE3;
+								break;
+							case UNKNOWN_HEADER: break;
+							default:
+								state=UNKNOWN_HEADER;
+						}
+						break;
+			case ' ':
+						switch(state){
+							case INITIAL:
+								break; /*eat space */
+							case F_VIA:
+							case F_FROM:
+							case F_TO:
+							case F_CSEQ:
+							case F_CALLID:
+							case F_CONTACT:
+							case F_MAXFORWARDS:
+							case F_ROUTE:
+								break; /* eat trailing space*/
+							case VIA1:
+								/*compact form: v: */
+								state=F_VIA;
+								break;
+							case FROM1:
+								/*compact form f:*/
+								state=F_FROM;
+								break;
+							case TO1:
+								/*compact form t:*/
+								state=F_TO;
+								break;
+							case I_START:
+								/*compact form i: (Call-ID)*/
+								state=F_CALLID;
+								break;
+							case M_START:
+								/*compact form m: (Contact)*/
+								state=F_CONTACT;
+								break;
+							case UNKNOWN_HEADER: break;
+							default:
+								state=UNKNOWN_HEADER;
+						}
+						break;
+			case ':':
+						switch(state){
+							case F_VIA:
+							case VIA1: /* compact form*/
+							case F_FROM:
+							case FROM1: /*compact form*/
+							case F_TO:
+							case TO1: /*compact form*/
+							case F_CSEQ:
+							case F_CALLID:
+							case I_START: /*compact form*/
+							case F_CONTACT:
+							case M_START: /*compact form*/
+							case F_MAXFORWARDS:
+							case F_ROUTE:
+							//	printf("found header, state=%d\n", state);
+								state=INITIAL; /* reset to test*/
+								break;
+							case UNKNOWN_HEADER:
+							default:
+								/*printf("found unknown header, state=%d\n", 
+											state);*/
+								err=1;
+								state=INITIAL;
+						}
+						break;
+			default:
+					/*fprintf(stderr, "Unexpected char <%c> encountered"
+										" state=%d\n", *t, state);
+						exit(-1);*/
+					state=UNKNOWN_HEADER;
+		}
+	}
+
+	} //for i
+	if (err) printf("Error unknown header\n");
+	printf("final state=%d\n", state);
+
+	exit(0);
+
+}
+
diff --git a/test/bad_eof.cfg b/test/bad_eof.cfg
new file mode 100644
index 0000000..0d523a7
--- /dev/null
+++ b/test/bad_eof.cfg
@@ -0,0 +1 @@
+" unterminated string
diff --git a/test/bad_uri.sip b/test/bad_uri.sip
new file mode 100644
index 0000000..91be90d
--- /dev/null
+++ b/test/bad_uri.sip
@@ -0,0 +1,32 @@
+INVITE sip:jiri at bat.iptel.org SIP/2.0
+Max-Forwards: 10
+From: "jiri" <sip:jiri at iptel.org>;tag=76ff7a07-c091-4192-84a0-d56e91fe104f
+To: <sip:jiri at bat.iptel.org>
+Call-ID: d10815e0-bf17-4afa-8412-d9130a793d96 at 213.20.128.35
+CSeq: 2 INVITE
+Contact: <sip:213.20.128.35:9315>
+User-Agent: Windows RTC/1.0
+Proxy-Authorization: Digest username="jiri", realm="iptel.org", algorithm="MD5", uri="sip:jiri at bat.iptel.org", nonce="3cef753900000001771328f5ae1b8b7f0d742da1feb5753c", response="53fe98db10e1074b03b3e06438bda70f"
+Content-Type: application/sdp
+Content-Length: 451
+
+v=0
+o=jku2 0 0 IN IP4 213.20.128.35
+s=session
+c=IN IP4 213.20.128.35
+b=CT:1000
+t=0 0
+m=audio 54742 RTP/AVP 97 111 112 6 0 8 4 5 3 101
+a=rtpmap:97 red/8000
+a=rtpmap:111 SIREN/16000
+a=fmtp:111 bitrate=16000
+a=rtpmap:112 G7221/16000
+a=fmtp:112 bitrate=24000
+a=rtpmap:6 DVI4/16000
+a=rtpmap:0 PCMU/8000
+a=rtpmap:8 PCMA/8000
+a=rtpmap:4 G723/8000
+a=rtpmap:5 DVI4/8000
+a=rtpmap: 3 GSM/8000
+a=rtpmap:101 telephone-event/8000
+a=fmtp:101 0-16
diff --git a/test/bad_via1.sip b/test/bad_via1.sip
new file mode 100644
index 0000000..fbb81af
--- /dev/null
+++ b/test/bad_via1.sip
@@ -0,0 +1,6 @@
+INVITE sip:x at y.z SIP/2.0
+Via : SIP  /   2.0
+ /UDP
+    193.175.133.193
+
+
diff --git a/test/bad_via2.sip b/test/bad_via2.sip
new file mode 100644
index 0000000..f96d1fa
--- /dev/null
+++ b/test/bad_via2.sip
@@ -0,0 +1,4 @@
+INVITE sip:x at y.z SIP/2.0/UDP
+V: SIP/2.0/UDP 193.175.133.193
+
+
diff --git a/test/bad_via3.sip b/test/bad_via3.sip
new file mode 100644
index 0000000..3f48c8d
--- /dev/null
+++ b/test/bad_via3.sip
@@ -0,0 +1,3 @@
+INVITE sip:x at y.z SIP/2.0/UDP
+
+
diff --git a/test/basex.c b/test/basex.c
new file mode 100644
index 0000000..3033a8b
--- /dev/null
+++ b/test/basex.c
@@ -0,0 +1,399 @@
+/*
+ * Tests for basex.h
+ *
+ * Copyright (C) 2008 iptelorg GmbH
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+
+/*#define NO_BASE64_LOOKUP_TABLE
+ #define SINGLE_REG */
+
+#include "../basex.h"
+#include "profile.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <time.h>
+#include <ctype.h>
+
+
+#ifndef MIN
+#define MIN(a,b) (((a)<(b))?(a):(b))
+#endif
+
+#define BASE64 64
+#define Q_BASE64 640
+#define BASE16 16
+
+#ifndef BASEX
+#define BASEX BASE16
+#endif
+
+#if BASEX == Q_BASE64
+
+#warning Q_BASE64
+#define B_ENC	q_base64_enc
+#define B_DEC	q_base64_dec
+#define B_ENC_LEN(l)	(((l)+2)/3*4)
+
+#elif BASEX == BASE16
+
+#warning BASE16
+#define B_ENC	base16_enc
+#define B_DEC	base16_dec
+#define B_ENC_LEN(l)	((l)*2)
+
+#else
+
+#warning BASE64
+#define B_ENC	base64_enc
+#define B_DEC	base64_dec
+#define B_ENC_LEN(l)	(((l)+2)/3*4)
+
+
+#endif
+
+
+#define QUOTE_MACRO(x) QUOTEME(x)
+#define QUOTEME(x) #x
+
+static char* id="$Id$";
+static char* version="basex test 0.1 " 
+"BASE" QUOTE_MACRO(BASEX)  ": " QUOTE_MACRO(B_ENC) ", " QUOTE_MACRO(B_DEC) ""
+#if defined BASE64_LOOKUP_TABLE 
+#ifdef BASE64_LOOKUP_LARGE
+" (large b64 lookup table)"
+#else
+" (lookup b64 table)"
+#endif
+#else
+" (no b64 lookup table)"
+#endif
+#if defined BASE16_LOOKUP_TABLE
+#ifdef BASE16_LOOKUP_LARGE
+" (large b16 lookup table)"
+#else
+" (lookup b16 table)"
+#endif
+#else
+" (no b16 lookup table)"
+#endif
+#if defined BASE64_READ_WHOLE_INTS || defined BASE16_READ_WHOLE_INTS
+" (read 4 bytes at a time)"
+#else
+" (read 1 byte at a time)"
+#endif
+;
+
+static char* help_msg="\
+Usage: basex  [-hv] ... [options]\n\
+Options:\n\
+    -m min        minimum length\n\
+    -M max        maximum length\n\
+    -o offset     offset from the start of the buffer (alignment tests)\n\
+    -e offset     offset from the start of the dst. buf. (alignment tests)\n\
+    -n no.        number of test loops\n\
+    -v            increase verbosity\n\
+    -V            version number\n\
+    -h            this help message\n\
+";
+
+
+/* profiling */
+struct profile_data pf1, pf2, pf3, pf4, pf5, pf6;
+
+
+void dump_profile_info(struct profile_data* pd)
+{
+	printf("profiling for %s (%ld/%ld):  %lld/%lld/%lld (max/avg/last),"
+			" total %lld\n",
+			pd->name, pd->entries, pd->exits, pd->max_cycles, 
+			pd->entries?pd->total_cycles/pd->entries:0, pd->cycles,
+			pd->total_cycles);
+}
+
+
+
+int seed_prng()
+{
+	int seed, rfd;
+	
+	if ((rfd=open("/dev/urandom", O_RDONLY))!=-1){
+try_again:
+		if (read(rfd, (void*)&seed, sizeof(seed))==-1){
+			if (errno==EINTR) goto try_again; /* interrupted by signal */
+				fprintf(stderr, "WARNING: could not read from /dev/urandom: "
+								" %s (%d)\n", strerror(errno), errno);
+		}
+		close(rfd);
+	}else{
+		fprintf(stderr, "WARNING: could not open /dev/urandom: %s (%d)\n",
+						strerror(errno), errno);
+	}
+	seed+=getpid()+time(0);
+	srand(seed);
+	return 0;
+}
+
+
+/* fill buf with random data*/
+void fill_rand(unsigned char* buf, int len)
+{
+	unsigned char* end;
+	int v;
+
+/* find out how many random bytes we can get from rand() */
+#if RAND_MAX >= 0xffffffff
+#define RAND_BYTES 4
+#warning RAND_BYTES is 4
+#elif RAND_MAX >= 0xffffff
+#define RAND_BYTES 3
+#warning RAND_BYTES is 3
+#elif RAND_MAX >= 0xffff
+#define RAND_BYTES 2
+#warning RAND_BYTES is 2
+#else
+#define RAND_BYTES 1
+#endif
+
+	end=buf+len/RAND_BYTES*RAND_BYTES;
+	for(;buf<end;buf+=RAND_BYTES){
+		v=rand();
+		buf[0]=v;
+#if RAND_BYTES > 1
+		buf[1]=v>>8;
+#endif
+#if RAND_BYTES > 2
+		buf[2]=v>>16;
+#endif
+#if RAND_BYTES > 4
+		buf[3]=v>>24;
+#endif
+	}
+	v=rand();
+	switch(end-buf){
+		case 3:
+#if RAND_BYTES > 2
+			buf[2]=v>>16;
+#else
+			buf[2]=rand();
+#endif
+		case 2:
+#if RAND_BYTES > 1
+			buf[1]=v>>8;
+#else
+			buf[1]=rand();
+#endif
+		case 1:
+			buf[0]=v;
+		case 0:
+			break;
+	}
+}
+
+
+
+int main(int argc, char** argv)
+{
+
+	int loops, min_len, max_len, offset, e_offset;
+	unsigned char* ibuf;
+	unsigned char* enc_buf;
+	unsigned char* dec_buf;
+	int ibuf_len, enc_buf_len, dec_buf_len;
+	int offs, c_len, e_len, l;
+	int r;
+	int verbose;
+	int c;
+	char* tmp;
+
+	verbose=0;
+	min_len=max_len=offset=-1;
+	e_offset=0;
+	loops=1024;
+	opterr=0;
+	while ((c=getopt(argc, argv, "n:m:M:o:e:vhV"))!=-1){
+		switch(c){
+			case 'n':
+				loops=strtol(optarg, &tmp, 0);
+				if ((tmp==0)||(*tmp)||(loops<0)){
+					fprintf(stderr, "bad number: -%c %s\n", c, optarg);
+					goto error;
+				}
+				break;
+			case 'm':
+				min_len=strtol(optarg, &tmp, 0);
+				if ((tmp==0)||(*tmp)||(min_len<0)){
+					fprintf(stderr, "bad number: -%c %s\n", c, optarg);
+					goto error;
+				}
+				break;
+			case 'M':
+				max_len=strtol(optarg, &tmp, 0);
+				if ((tmp==0)||(*tmp)||(max_len<0)){
+					fprintf(stderr, "bad number: -%c %s\n", c, optarg);
+					goto error;
+				}
+				break;
+			case 'o':
+				offset=strtol(optarg, &tmp, 0);
+				if ((tmp==0)||(*tmp)||(offset<0)){
+					fprintf(stderr, "bad number: -%c %s\n", c, optarg);
+					goto error;
+				}
+				break;
+			case 'e':
+				e_offset=strtol(optarg, &tmp, 0);
+				if ((tmp==0)||(*tmp)||(e_offset<0)){
+					fprintf(stderr, "bad number: -%c %s\n", c, optarg);
+					goto error;
+				}
+				break;
+			case 'v':
+				verbose++;
+				break;
+			case 'V':
+				printf("version: %s\n", version);
+				printf("%s\n", id);
+				exit(0);
+				break;
+			case 'h':
+				printf("version: %s\n", version);
+				printf("%s", help_msg);
+				exit(0);
+				break;
+			case '?':
+				if (isprint(optopt))
+					fprintf(stderr, "Unknown option `-%c\n", optopt);
+				else
+					fprintf(stderr, "Unknown character `\\x%x\n", optopt);
+				goto error;
+			case ':':
+				fprintf(stderr, "Option `-%c requires an argument.\n",
+						optopt);
+				goto error;
+				break;
+			default:
+				abort();
+		}
+	}
+	if (min_len==-1 && max_len==-1){
+		min_len=0;
+		max_len=4*1024*1024;
+	}else if (min_len==-1)
+		min_len=0;
+	else if (max_len==-1)
+		max_len=min_len;
+	/* init */
+	ibuf_len=max_len;
+	ibuf=malloc(ibuf_len);
+	if (ibuf==0){
+		fprintf(stderr, "ERROR: 1. memory allocation error (%d bytes)\n",
+						ibuf_len);
+		exit(-1);
+	}
+	enc_buf_len=B_ENC_LEN(ibuf_len);
+	enc_buf=malloc(enc_buf_len+e_offset);
+	if (enc_buf==0){
+		fprintf(stderr, "ERROR: 2. memory allocation error (%d bytes)\n",
+						enc_buf_len);
+		exit(-1);
+	}
+	enc_buf+=e_offset; /* make sure it's off by e_offset bytes from the
+						 aligned stuff malloc returns */
+	dec_buf_len=ibuf_len;
+	dec_buf=malloc(dec_buf_len+e_offset);
+	if (dec_buf==0){
+		fprintf(stderr, "ERROR: 3. memory allocation error (%d bytes)\n",
+						dec_buf_len+e_offset);
+		exit(-1);
+	}
+	dec_buf+=e_offset; /* make sure it's off by e_offset bytes from the
+						  aligned stuff malloc returns */
+	
+	
+	seed_prng();
+	/* profile */
+	profile_init(&pf1, "encode");
+	profile_init(&pf2, "decode");
+	
+	init_basex();
+	if (verbose)
+		printf("starting (loops %d, min size %d, max size %d, offset %d,"
+				", e_offset %d, buffer sizes %d %d %d)\n",
+				loops, min_len, max_len, offset, e_offset, ibuf_len,
+				enc_buf_len, dec_buf_len);
+		
+		for (r=0; r<loops; r++){
+			if (min_len!=max_len)
+				/* test encode/decode random data w/ random length*/
+				c_len= min_len+(int)((float)(max_len-min_len+1)*
+											(rand()/(RAND_MAX+1.0)));
+			else 
+				/* test encode /decode random data w/ fixed lenght*/
+				c_len=max_len;
+			if (offset==-1)
+				/* offset between 0 & MIN(clen,3) */
+				offs= (int)((float)(MIN(c_len,3)+1)*(rand()/(RAND_MAX+1.0)));
+			else if (offset>c_len)
+				offs=0;
+			else
+				offs=offset;
+			if (verbose>2)
+				printf("loop %d, current len %d, offset %d, start %p\n",
+							r, c_len-offs, offs, &ibuf[offs]);
+			else if ((verbose >1) && (r %10==0)) putchar('.');
+			
+			fill_rand(ibuf, c_len);
+			
+			c_len-=offs;
+			e_len=B_ENC_LEN(c_len);
+			profile_start(&pf1);
+			l=B_ENC(&ibuf[offs], c_len, enc_buf, e_len);
+			profile_end(&pf1);
+			if (l != e_len){
+				fprintf(stderr, "ERROR: invalid length for encoding: %d "
+								"instead of %d (loops=%d)\n", l, e_len, r);
+				exit(-1);
+			}
+			profile_start(&pf2);
+			l=B_DEC(enc_buf, e_len, dec_buf, c_len);
+			profile_end(&pf2);
+			if (l != c_len){
+				fprintf(stderr, "ERROR: invalid length for decoding: %d "
+								"instead of %d (loops=%d)\n", l, c_len, r);
+				exit(-1);
+			}
+			if (memcmp(&ibuf[offs], dec_buf, c_len)!=0){
+				fprintf(stderr, "ERROR: decoding mismatch "
+								"(loops=%d, c_len=%d)\n", r, c_len);
+				abort();
+				exit(-1);
+			}
+		}
+	 if (verbose >1) putchar('\n');
+	/* encode len data and decode it, print profiling info*/
+	 dump_profile_info(&pf1);
+	 dump_profile_info(&pf2);
+	 return 0;
+error:
+		 exit(-1);
+}
diff --git a/test/basex.txt b/test/basex.txt
new file mode 100644
index 0000000..3686e65
--- /dev/null
+++ b/test/basex.txt
@@ -0,0 +1,60 @@
+# test results for basex.c
+
+
+pentium-m (core2): 
+gcc -g  -Wall -O9 -mtune=pentium-m -mcpu=pentium-m -D__CPU_x86  ${DEFS} \
+        ../basex.c basex.c -o basex
+
+               4		  8		 16		 32		 40		 64		 80		128
+lookup:
+base16_enc4   83		 96		125		177		205		291		345		509
+base16_dec4
+base16_enc    79		 97		150		208		240		326		390		559
+base16_dec    76		 96		152		217		249		350		402		588
+
+lookup(DEFS=-DBASEX=BASE64)::
+base16_enc4										211
+base16_dec4										252
+base16_enc										231
+base16_dec										251
+lookup_Large (DEFS=-DBASE16_LOOKUP_LARGE -DBASEX=BASE64):
+base16_enc4										218
+base16_dec4										236
+base16_enc										199
+base16_dec										236
+
+no lookup (DEFS=NO_BASE64_LOOKUP_TABLE -DBASEX=BASE64):
+base64_enc  156									1005						
+            181									1242
+lookup (DEFS=-DBASEX=BASE64):
+base64_enc   82			101		120		185		209		302		335		521
+base64_dec   89			103		140		198		208		289		359		546
+lookup_large (DEFS=-DBASE64_LOOKUP_LARGE -DBASEX=BASE64):
+base64_enc   79			 85		103		157		186		268		276		421
+base64_dec   93			103		126		188		207		281		348		510
+
+lookup_8k (DEFS=-DBASE64_LOOKUP_8K -DBASEX=BASE64), -e 1
+base64_enc   77			 94						177						422
+lookup_8k words (like above but -e 0)
+base64_enc   77									156						329
+
+
+ultrasparc:
+gcc -g  -Wall -O9 -mtune=ultrasparc -mcpu=ultrasparc -D__CPU_sparc64 ${DEFS} \
+     ../basex.c basex.c -o basex
+
+no lookup (DEFS=-DNO_BASE64_LOOKUP_TABLE -DBASEX=BASE64):
+base64_enc     			   						 728						  
+              									1425
+lookup (DEFS=-DBASEX=BASE64):
+base64_enc     			   						314						   
+              									260
+lookup_large (DEFS=-DBASE64_LOOKUP_LARGE -DBASEX=BASE64):
+base64_enc     			   						295						   
+
+lookup_8k (DEFS=-DBASE64_LOOKUP_8K -DBASEX=BASE64), -e 1
+base64_enc     			   						323						   
+               									250
+lookup_8k words (like above but -e 0)
+base64_enc   91			118						296						
+            101			117						249
diff --git a/test/bc2.sip b/test/bc2.sip
new file mode 100644
index 0000000..c48eed2
--- /dev/null
+++ b/test/bc2.sip
@@ -0,0 +1,10 @@
+BYE sip:211111948 at 195.37.77.101;transport=tcp;r2=on;ftag=e495220a31344eb39a6bf44ee3b01303;lr=on SIP/2.0
+Max-Forwards: 10
+Via: SIP/2.0/UDP 192.246.69.223;branch=z9hG4bK1ac2.64b19ee4.0
+From: <sip:xxx at iptel.org>;tag=as38468f70
+To: "christian at iptel.org" <sip:christian at iptel.org>;tag=e495220a31344eb39a6bf44ee3b01303;epid=f15c896fef
+Contact: <sip:404 at 65.39.205.112:5028>
+Call-ID: axxxxxef5cec10dd5f4dca871b764cb83ee73c at 192.168.1.100
+CSeq: 102 BYE
+Content-Length: 0
+
diff --git a/test/bit_scan_test.c b/test/bit_scan_test.c
new file mode 100644
index 0000000..0d85879
--- /dev/null
+++ b/test/bit_scan_test.c
@@ -0,0 +1,206 @@
+/*
+ * test bit_scan operations from bit_scan.h
+ *  (both for correctness  and speed)
+ * 
+ * Copyright (C) 2007 iptelorg GmbH
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* 
+ * Example gcc command line:
+ *  gcc -O9 -Wall -DCC_GCC_LIKE_ASM  -D__CPU_x86 bit_scan_test.c ../bit_scan.c
+ *      -o bit_scan_test
+ *
+ * History:
+ * --------
+ *  2007-06-23  created by andrei
+ */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+
+
+#define BIT_SCAN_DEBRUIJN
+#define BIT_SCAN_BRANCH
+#define BIT_SCAN_SLOW
+
+#include "../bit_scan.h"
+#ifdef NO_PROFILE
+#define profile_init(x,y)  do{}while(0)
+#define profile_start(x)  do{}while(0)
+#define profile_end(x)  do{}while(0)
+#define PROFILE_PRINT(x) do{}while(0)
+#else
+#include "profile.h"
+#endif
+
+#define CHECK(txt, v1, val, f, pd) \
+	do{ \
+		unsigned long long ret; \
+		profile_start(pd); \
+		ret=(unsigned long long)f(val); \
+		profile_end(pd); \
+		if ((unsigned long long)v1!=ret){ \
+			fprintf(stderr, "ERROR:" #f ": %s, expected %llx (%llx), got"\
+					" %llx\n", \
+					(txt), (unsigned long long)v1, \
+					(unsigned long long)val, ret); \
+			exit(-1); \
+		} \
+	}while(0)
+
+#ifndef PROFILE_PRINT
+#define PROFILE_PRINT(pd) \
+	do{ \
+		printf("profile: %s (%ld/%ld) total %llu max %llu average %llu\n", \
+				(pd)->name,  (pd)->entries, (pd)->exits, \
+				(pd)->total_cycles,  (pd)->max_cycles, \
+				(pd)->entries? \
+				(pd)->total_cycles/(unsigned long long)(pd)->entries:0ULL ); \
+	}while(0)
+#endif
+
+int main(int argc, char** argv)
+{
+	int r;
+	unsigned int v;
+	unsigned long long ll;
+	int i;
+#ifndef NO_PROFILE
+	struct profile_data pdf1, pdf2, pdf4, pdf5, pdf6, pdf8;
+	struct profile_data pdl1, pdl2, pdl4, pdl5, pdl6, pdl8;
+#ifdef HAS_BIT_SCAN_ASM
+	struct profile_data pdf3, pdf7, pdl3, pdl7;
+#endif
+	struct profile_data pdf_32, pdf_64, pdl_32, pdl_64;
+	struct profile_data pdf_long, pdl_long;
+#endif /* NO_PROFILE */
+	
+	profile_init(&pdf1, "first_debruijn32");
+	profile_init(&pdf2, "first_slow32");
+#ifdef HAS_BIT_SCAN_ASM
+	profile_init(&pdf3, "first_asm32");
+#endif
+	profile_init(&pdf4, "first_br32");
+	profile_init(&pdf5, "first_debruijn64");
+	profile_init(&pdf6, "first_slow64");
+#ifdef HAS_BIT_SCAN_ASM
+	profile_init(&pdf7, "first_asm64");
+#endif
+	profile_init(&pdf8, "first_br64");
+	profile_init(&pdl1, "last_debruijn32");
+	profile_init(&pdl2, "last_slow32");
+#ifdef HAS_BIT_SCAN_ASM
+	profile_init(&pdl3, "last_asm32");
+#endif
+	profile_init(&pdl4, "last_br32");
+	profile_init(&pdl5, "last_debruijn64");
+	profile_init(&pdl6, "last_slow64");
+#ifdef HAS_BIT_SCAN_ASM
+	profile_init(&pdl7, "last_asm64");
+#endif
+	profile_init(&pdl8, "last_br64");
+	
+	profile_init(&pdf_32, "scan_forward32");
+	profile_init(&pdf_64, "scan_forward64");
+	profile_init(&pdl_32, "scan_reverse32");
+	profile_init(&pdl_64, "scan_reverse64");
+	profile_init(&pdf_long, "scan_forward_l");
+	profile_init(&pdl_long, "scan_reverse_l");
+
+
+	for (i=0; i<100; i++){
+	for (r=0; r<32; r++){
+		v=(1U<<r);
+		CHECK("first debruijn 32bit", r, v, bit_scan_forward_debruijn32, &pdf1);
+		CHECK("first slow 32bit", r, v, bit_scan_forward_slow32, &pdf2);
+#ifdef HAS_BIT_SCAN_ASM
+		CHECK("first asm 32bit", r, v, bit_scan_forward_asm32, &pdf3);
+#endif
+		CHECK("first br 32bit", r, v, bit_scan_forward_br32, &pdf4);
+		CHECK("scan_forward32", r, v, bit_scan_forward32, &pdf_32);
+		if (sizeof(long)<=4){
+			CHECK("scan_forward_l", r, v, bit_scan_forward, &pdf_long);
+		}
+		v+=(v-1);
+		CHECK("last debruijn 32bit", r, v, bit_scan_reverse_debruijn32, &pdl1);
+		CHECK("last slow 32bit", r, v, bit_scan_reverse_slow32, &pdl2);
+#ifdef HAS_BIT_SCAN_ASM
+		CHECK("last asm 32bit", r, v, bit_scan_reverse_asm32, &pdl3);
+#endif
+		CHECK("last br 32bit", r, v, bit_scan_reverse_br32, &pdl4);
+		CHECK("scan_reverse32", r, v, bit_scan_reverse32, &pdl_32);
+		if (sizeof(long)<=4){
+			CHECK("scan_reverse_l", r, v, bit_scan_reverse, &pdl_long);
+		}
+	}
+	for (r=0; r<64; r++){
+		ll=(1ULL<<r);
+		CHECK("first debruijn 64bit", r, ll, bit_scan_forward_debruijn64, &pdf5);
+		CHECK("first slow 64bit", r, ll, bit_scan_forward_slow64, &pdf6);
+#ifdef HAS_BIT_SCAN_ASM
+		CHECK("first asm 64bit", r, ll, bit_scan_forward_asm64, &pdf7);
+#endif
+		CHECK("first br 64bit", r, ll, bit_scan_forward_br64, &pdf8);
+		CHECK("scan_forward64", r, ll, bit_scan_forward64, &pdf_64);
+		if (sizeof(long)>4){
+			CHECK("scan_forward_l", r, ll, bit_scan_forward, &pdf_long);
+		}
+		ll+=ll-1;
+		CHECK("last debruijn 64bit", r, ll, bit_scan_reverse_debruijn64, &pdl5);
+		CHECK("last slow 64bit", r, ll, bit_scan_reverse_slow64, &pdl6);
+#ifdef HAS_BIT_SCAN_ASM
+		CHECK("last asm 64bit", r, ll, bit_scan_reverse_asm64, &pdl7);
+#endif
+		CHECK("last br 64bit", r, ll, bit_scan_reverse_br64, &pdl8);
+		CHECK("scan_reverse64", r, ll, bit_scan_reverse64, &pdl_64);
+		if (sizeof(long)>4){
+			CHECK("scan_reverse_l", r, ll, bit_scan_reverse, &pdl_long);
+		}
+	}
+	}
+
+	PROFILE_PRINT(&pdf1);
+	PROFILE_PRINT(&pdf2);
+#ifdef HAS_BIT_SCAN_ASM
+	PROFILE_PRINT(&pdf3);
+#endif
+	PROFILE_PRINT(&pdf4);
+	PROFILE_PRINT(&pdl1);
+	PROFILE_PRINT(&pdl2);
+#ifdef HAS_BIT_SCAN_ASM
+	PROFILE_PRINT(&pdl3);
+#endif
+	PROFILE_PRINT(&pdl4);
+	PROFILE_PRINT(&pdf5);
+	PROFILE_PRINT(&pdf6);
+#ifdef HAS_BIT_SCAN_ASM
+	PROFILE_PRINT(&pdf7);
+#endif
+	PROFILE_PRINT(&pdf8);
+	PROFILE_PRINT(&pdl5);
+	PROFILE_PRINT(&pdl6);
+#ifdef HAS_BIT_SCAN_ASM
+	PROFILE_PRINT(&pdl7);
+#endif
+	PROFILE_PRINT(&pdl8);
+	
+	PROFILE_PRINT(&pdf_32);
+	PROFILE_PRINT(&pdf_64);
+	PROFILE_PRINT(&pdf_long);
+	PROFILE_PRINT(&pdl_32);
+	PROFILE_PRINT(&pdl_64);
+	PROFILE_PRINT(&pdl_long);
+	return 0;
+}
diff --git a/test/bt.gdb b/test/bt.gdb
new file mode 100644
index 0000000..0b36015
--- /dev/null
+++ b/test/bt.gdb
@@ -0,0 +1,2 @@
+
+backtrace
diff --git a/test/bye00.sip b/test/bye00.sip
new file mode 100644
index 0000000..7e044ac
--- /dev/null
+++ b/test/bye00.sip
@@ -0,0 +1,14 @@
+BYE sip:jiri at bat.iptel.org SIP/2.0
+Max-Forwards: 0
+Via: SIP/2.0/UDP 195.37.77.100;branch=df6250bb14ccda4a69dc0502173d02b2.e0e.0
+Via: SIP/2.0/UDP 213.20.228.21:13671
+From: "jiri" <sip:jiri at iptel.org>;tag=9c77afe9-71ec-4c52-a009-f2869fba848b
+To: <sip:jiri at bat.iptel.org>;tag=9c77afe9-71ec-4c52-a009-f2869fba848b
+Call-ID: bcd1134d-a36f-4647-ae9f-124c157d2db1 at 213.20.228.21
+CSeq: 4 BYE
+Contact: <sip:213.20.228.21:13671>
+User-Agent: Windows RTC/10
+Proxy-Authorization: Digest username="jiri", realm="iptel.org", algorithm="MD5", uri="sip:jiri at bat.iptel.org", nonce="3ceffa4400000001d587052d1c8c510923023da8846e64fa", response="daaa8ef489b5ac91420b8a818bf5581d"
+Content-Length: 0
+
+
diff --git a/test/bye_chris.sip b/test/bye_chris.sip
new file mode 100644
index 0000000..a656eb9
--- /dev/null
+++ b/test/bye_chris.sip
@@ -0,0 +1,14 @@
+BYE sip:christian at iptel.org SIP/2.0
+Max-Forwards: 10
+Record-Route: <sip:christian at 192.246.69.223;ftag=as38468f70;lr=on>
+Via: SIP/2.0/UDP 192.246.69.223;branch=z9hG4bK1ac2.64b19ee4.0
+Via: SIP/2.0/UDP 65.39.205.112:5028;branch=z9hG4bK28091bb9
+Route: <sip:211111948 at 195.37.77.101;r2=on;ftag=e495220a31344eb39a6bf44ee3b01303;lr=on>,<sip:211111948 at 195.37.77.101;transport=tcp;r2=on;ftag=e495220a31344eb39a6bf44ee3b01303;lr=on>
+From: <sip:xxx at iptel.org>;tag=as38468f70
+To: "christian at iptel.org" <sip:christian at iptel.org>;tag=e495220a31344eb39a6bf44ee3b01303;epid=f15c896fef
+Contact: <sip:404 at 65.39.205.112:5028>
+Call-ID: xxxef5cec10dd5f4dca871b764cb83ee73c at 192.168.1.100
+CSeq: 102 BYE
+User-Agent: Asterisk PBX
+Content-Length: 0
+
diff --git a/test/centauri.cfg b/test/centauri.cfg
new file mode 100644
index 0000000..c1487ce
--- /dev/null
+++ b/test/centauri.cfg
@@ -0,0 +1,14 @@
+# config file for centauri
+
+route{
+ src_ip=~"testing" log("packet from fokus\n"); route(1);
+/* drop all others */
+
+}
+
+
+route[1]{
+	(src_ip==192.168.46.0/24 or src_ip=~"^dorian") forward("fox.iptel.org");
+	src_ip=="centauri.fokus.gmd.de" log("Possible loop, dropping\n"); drop
+	src_ip==0.0.0.0/0 log("forwarding denied\n"); drop
+}
diff --git a/test/dns.sip b/test/dns.sip
new file mode 100644
index 0000000..4e69bee
--- /dev/null
+++ b/test/dns.sip
@@ -0,0 +1,24 @@
+OPTIONS sip:henrxx at iptel.com SIP/2.0
+Via: SIP/2.0/UDP 195.37.77.101:9
+From: "GMD FOKUS iptlab" <sip:jiri at iptel.org>;tag=b96b0300ed30f1286-2f5d
+Call-ID: b96b0300-88d30f-66da-63aa at 195.37.78.190
+CSeq: 101 OPTIONS
+To: sip:tester at iptel.org
+Expires: 180
+Max-Forwards:  9
+User-Agent: Cisco-SIP-IP-Phone/2
+Accept: application/sdp
+Contact: sip:jiri at 195.37.78.190:5060
+Content-Type: application/sdp
+Content-Length: 225
+
+
+v=0
+o=CiscoSystemsSIP-IPPhone-UserAgent 14474 8233 IN IP4 195.37.78.190
+s=SIP Call
+c=IN IP4 195.37.78.190
+t=0 0
+m=audio 18456 RTP/AVP 0 8 18 101
+a=rtpmap:0 pcmu/8000
+a=rtpmap:101 telephone-event/8000
+a=fmtp:101 0-11 
diff --git a/test/dns_query.c b/test/dns_query.c
new file mode 100644
index 0000000..e3d727a
--- /dev/null
+++ b/test/dns_query.c
@@ -0,0 +1,215 @@
+/*
+ *
+ * tests for ../resolver.c
+ *
+ * Compile with:
+ *  gcc -o dns_query2 dns_query.c ../resolve.o ../dprint.o ../mem/ *.o -lresolv
+ *  (and first compile Kamailio with qm_malloc)
+ * 
+ *
+ * Copyright (C) 2001-2003 FhG Fokus
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+/*
+ * tester for ser resolver  (andrei) */
+
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../resolve.h"
+#include "../mem/q_malloc.h"
+
+/* symbols needed by dprint */
+int log_stderr=1;
+int debug=0;
+int pids[1];
+int process_no=0;
+long shm_mem_size=0;
+char mem_pool[1024*1024];
+struct qm_block* mem_block;
+int log_facility=0;
+int memlog=0;
+int memdbg=0;
+int ser_error=0;
+struct process_table* pt=0;
+
+
+static char* id="$Id$";
+static char* version="dns_query 0.1";
+static char* help_msg="\
+Usage: dns_query  [-t type] [-hV] -n host\n\
+Options:\n\
+    -n host       host name\n\
+    -t type       query type (default A)\n\
+    -V            version number\n\
+    -h            this help message\n\
+";
+
+
+int main(int argc, char** argv)
+{
+	char c;
+	char* name;
+	char* type_str;
+	int type;
+	int r;
+	struct rdata* head;
+	struct rdata* l;
+	struct srv_rdata* srv;
+	struct naptr_rdata* naptr;
+	struct a_rdata* ip;
+
+	name=type_str=0;
+	
+	opterr=0;
+	while ((c=getopt(argc, argv, "n:t:hV"))!=-1){
+		switch(c){
+			case 'n':
+				name=optarg;
+				break;
+			case 't':
+				type_str=optarg;
+				break;
+			case 'V':
+				printf("version: %s\n", version);
+				printf("%s\n", id);
+				exit(0);
+				break;
+			case 'h':
+				printf("version: %s\n", version);
+				printf("%s", help_msg);
+				exit(0);
+				break;
+			case '?':
+				if (isprint(optopt))
+					fprintf(stderr, "Unknown option `-%c�\n", optopt);
+				else
+					fprintf(stderr, "Unknown character `\\x%x�\n", optopt);
+				goto error;
+			case ':':
+				fprintf(stderr, "Option `-%c� requires an argument.\n",
+						optopt);
+				goto error;
+				break;
+			default:
+				abort();
+		}
+	}
+	
+	if (name==0){
+		fprintf(stderr, "Missing domain name (-n name)\n");
+		goto error;
+	}
+	type=T_A;
+	if (type_str){
+		if (strcasecmp(type_str, "A")==0) type=T_A;
+		else if (strcasecmp(type_str, "NS")==0) type=T_NS;
+		else if (strcasecmp(type_str, "MD")==0) type=T_MD;
+		else if (strcasecmp(type_str, "MF")==0) type=T_MF;
+		else if (strcasecmp(type_str, "CNAME")==0) type=T_CNAME;
+		else if (strcasecmp(type_str, "SOA")==0) type=T_SOA;
+		else if (strcasecmp(type_str, "PTR")==0) type=T_PTR;
+		else if (strcasecmp(type_str, "HINFO")==0) type=T_HINFO;
+		else if (strcasecmp(type_str, "MINFO")==0) type=T_MINFO;
+		else if (strcasecmp(type_str, "MX")==0) type=T_MX;
+		else if (strcasecmp(type_str, "TXT")==0) type=T_TXT;
+		else if (strcasecmp(type_str, "AAAA")==0) type=T_AAAA;
+		else if (strcasecmp(type_str, "SRV")==0) type=T_SRV;
+		else if (strcasecmp(type_str, "NAPTR")==0) type=T_NAPTR;
+		else if (strcasecmp(type_str, "AXFR")==0) type=T_AXFR;
+		else{
+			fprintf(stderr, "Unknown query type %s\n", type_str);
+			goto error;
+		}
+	}
+	/* init mallocs*/
+	mem_block=qm_malloc_init(mem_pool, 1024*1024);
+	printf("calling get_record...\n");
+	head=get_record(name, type);
+	if (head==0) printf("no answer\n");
+	else{
+		printf("records:\n");
+		for(l=head; l; l=l->next){
+			switch(l->type){
+				case T_SRV:
+					srv=(struct srv_rdata*)l->rdata;
+					printf("SRV    type= %d class=%d  ttl=%d\n",
+							l->type, l->class, l->ttl);
+					printf("       prio= %d weight=%d port=%d\n",
+								srv->priority, srv->weight, srv->port);
+					printf("       name_len= %d (%d), name= [%.*s]\n",
+									srv->name_len, strlen(srv->name),
+									srv->name_len, srv->name);
+					break;
+				case T_CNAME:
+					printf("CNAME  type= %d class=%d  ttl=%d\n",
+							l->type, l->class, l->ttl);
+					printf("       name=[%s]\n", 
+								((struct cname_rdata*)l->rdata)->name);
+					break;
+				case T_A:
+					ip=(struct a_rdata*)l->rdata;
+					printf("A      type= %d class=%d  ttl=%d\n",
+								l->type, l->class, l->ttl);
+					printf("       ip= %d.%d.%d.%d\n",
+								ip->ip[0], ip->ip[1], ip->ip[2], ip->ip[3]);
+					break;
+				case T_AAAA:
+					printf("AAAA   type= %d class=%d  ttl=%d\n",
+							l->type, l->class, l->ttl);
+					printf("        ip6= ");
+					for(r=0;r<16;r++) 
+						printf("%x ", ((struct aaaa_rdata*)l->rdata)->ip6[r]);
+					printf("\n");
+					break;
+				case T_NAPTR:
+					naptr=(struct naptr_rdata*)l->rdata;
+					printf("NAPTR  type= %d class=%d  ttl=%d\n",
+							l->type, l->class, l->ttl);
+					printf("       order= %d pref=%d\n",
+								naptr->order, naptr->pref);
+					printf("       flags_len= %d,     flags= [%.*s]\n",
+									naptr->flags_len, 
+									naptr->flags_len, naptr->flags);
+					printf("       services_len= %d,  services= [%.*s]\n",
+									naptr->services_len, 
+									naptr->services_len, naptr->services);
+					printf("       regexp_len= %d,    regexp= [%.*s]\n",
+									naptr->regexp_len, 
+									naptr->regexp_len, naptr->regexp);
+					printf("       repl_len= %d,      repl= [%s]\n",
+									naptr->repl_len, naptr->repl);
+					break;
+
+				default:
+					printf("UNKN    type= %d class=%d  ttl=%d\n",
+								l->type, l->class, l->ttl);
+					printf("       rdata=%p\n", l->rdata);
+			}
+		}
+	}
+	printf("done\n");
+	exit(0);
+error:
+	exit(-1);
+}
diff --git a/test/echo.cfg b/test/echo.cfg
new file mode 100644
index 0000000..1e2cdba
--- /dev/null
+++ b/test/echo.cfg
@@ -0,0 +1,51 @@
+#
+# echo: rewrite userpart or r-uri to value from From header field
+#
+
+debug=3         # debug level (cmd line: -dddddddddd)
+fork=no
+log_stderror=yes
+
+memlog=4
+
+check_via=no    # (cmd. line: -v)
+dns=no           # (cmd. line: -r)
+rev_dns=no      # (cmd. line: -R)
+port=5060
+children=4
+fifo="/tmp/ser_fifo"
+
+listen=192.168.2.16
+
+# ------------------ module loading ----------------------------------
+
+# Uncomment this if you want to use SQL database
+#loadmodule "/usr/local/lib/ser/modules/mysql.so"
+
+loadmodule "modules/sl/sl.so"
+loadmodule "modules/exec/exec.so"
+
+route {
+
+		log(1, "request received\n");
+
+		if (method=="REGISTER") {
+			log(1, "register received\n");
+			sl_send_reply("200", "ok happy registratiion");
+			break;
+		};
+
+        if (exec_dset('
+			set -x
+			SIP_UID_FROM=`echo $SIP_HF_FROM | sed -e "s/^.*sip:\([a-zA-Z0-9_\.]*\)@.*$/\1/g"`
+			echo sip:$SIP_UID_FROM at vm04.foobar.com
+			echo sip:$SIP_UID_FROM at proxy01.foobar.com
+			echo>/dev/null ')) {
+                log(1, "trying to rewrite\n");
+				sl_send_reply("300", "redirect");
+        } else {
+                sl_send_reply("500", "exec error");
+                log(1, "alas, rewriting failed\n");
+        };
+}
+
diff --git a/test/endian_test.c b/test/endian_test.c
new file mode 100644
index 0000000..7c2ca11
--- /dev/null
+++ b/test/endian_test.c
@@ -0,0 +1,171 @@
+/* 
+ * Copyright (C) 2008 iptelorg GmbH
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ *  endianness.h tests
+ *  compile/run with:
+ *  gcc  -Wall endian_test.c ../endianness.c  -o endian_test; ./endian_test
+ */
+/* 
+ * History:
+ * --------
+ *  2008-06-13  created by andrei
+ */
+
+/*
+ *
+ * Macro names:
+ * linux:  __BYTE_ORDER == __LITTLE_ENDIAN | __BIG_ENDIAN
+ *           BYTE_ORDER == LITTLE_ENDIAN | BIG_ENDIAN
+ * bsd:     _BYTE_ORDER == _LITTLE_ENDIAN | _BIG_ENDIAN
+ *           BYTE_ORDER == LITTLE_ENDIAN | BIG_ENDIAN
+ * solaris: _LITTLE_ENDIAN | _BIG_ENDIAN
+ *
+ * Note: BIG_ENDIAN, LITTLE_ENDIAN, _BIG_ENDIAN, _LITTLE_ENDIAN cannot be 
+ *       used always,  some OSes define both of them for BYTE_ORDER use
+ *       (e.g. linux defines both BIG_ENDIAN & LITTLE_ENDIAN, bsds define
+ *          _BIG_ENDIAN, _LITTLE_ENDIAN, BIG_ENDIAN, LITTLE_ENDIAN)
+ *
+ * is sys/param.h universal ?
+ */
+
+#include <stdio.h>
+#include "../endianness.h"
+/* 
+ * Tested:
+ * linux:   y
+ * freebsd: y
+ * openbsd:
+ * netbsd:
+ * solaris: y
+ * darwin: 
+ * cygwin:
+ *
+ * Header files:
+ * linux:  <endian.h> , <sys/param.h>
+ * bsd:    <sys/param.h> or <sys/endian.h>
+ * solaris: <sys/param.h>
+ * openbsd
+ * netbsd
+ * solaris
+ * cywin
+ */
+
+/*
+ *
+ * Macro names:
+ * linux:  __BYTE_ORDER == __LITTLE_ENDIAN | __BIG_ENDIAN
+ *           BYTE_ORDER == LITTLE_ENDIAN | BIG_ENDIAN
+ * bsd:     _BYTE_ORDER == _LITTLE_ENDIAN | _BIG_ENDIAN
+ *           BYTE_ORDER == LITTLE_ENDIAN | BIG_ENDIAN
+ * solaris: _LITTLE_ENDIAN | _BIG_ENDIAN
+ *
+ * Note: BIG_ENDIAN, LITTLE_ENDIAN, _BIG_ENDIAN, _LITTLE_ENDIAN cannot be 
+ *       used always,  some OSes define both of them for BYTE_ORDER use
+ *       (e.g. linux defines both BIG_ENDIAN & LITTLE_ENDIAN, bsds define
+ *          _BIG_ENDIAN, _LITTLE_ENDIAN, BIG_ENDIAN, LITTLE_ENDIAN)
+ *
+ * is sys/param.h universal ?
+ */
+
+/* test only */
+#if defined __BYTE_ORDER && defined __LITTLE_ENDIAN 
+#if	__BYTE_ORDER == __LITTLE_ENDIAN
+#warning little endian (via __BYTE_ORDER)
+#define __BYTE_ORDER_FOUND
+#endif
+#endif
+#if defined __BYTE_ORDER && defined __BIG_ENDIAN
+#if	__BYTE_ORDER == __BIG_ENDIAN
+#warning big endian (via __BYTE_ORDER)
+#define __BYTE_ORDER_FOUND
+#endif
+#endif
+#if defined __BYTE_ORDER && !defined __BYTE_ORDER_FOUND
+#error __BYTE_ORDER defined, but w/ a strange value
+#endif
+
+#if defined _BYTE_ORDER && defined _LITTLE_ENDIAN
+#if _BYTE_ORDER == _LITTLE_ENDIAN
+#warning little endian (via _BYTE_ORDER)
+#define _BYTE_ORDER_FOUND
+#endif
+#endif
+#if defined _BYTE_ORDER && defined _BIG_ENDIAN 
+#if _BYTE_ORDER == _BIG_ENDIAN
+#warning big endian (via _BYTE_ORDER)
+#define _BYTE_ORDER_FOUND
+#endif
+#endif
+#if defined _BYTE_ORDER && !defined _BYTE_ORDER_FOUND
+#error _BYTE_ORDER defined, but w/ a strange value
+#endif
+
+#if defined BYTE_ORDER && defined LITTLE_ENDIAN 
+#if BYTE_ORDER == LITTLE_ENDIAN
+#warning little endian (via BYTE_ORDER)
+#define BYTE_ORDER_FOUND
+#endif
+#endif
+#if defined BYTE_ORDER && defined BIG_ENDIAN 
+#if BYTE_ORDER == BIG_ENDIAN
+#warning big endian (via BYTE_ORDER)
+#define BYTE_ORDER_FOUND
+#endif
+#endif
+#if defined BYTE_ORDER && !defined BYTE_ORDER_FOUND
+#error BYTE_ORDER defined, but w/ a strange value
+#endif
+
+#if defined _LITTLE_ENDIAN
+#warning _LITTLE_ENDIAN defined
+#endif
+#if defined _BIG_ENDIAN
+#warning _BIG_ENDIAN defined
+#endif
+#if defined LITTLE_ENDIAN
+#warning LITTLE_ENDIAN defined
+#endif
+#if defined BIG_ENDIAN
+#warning BIG_ENDIAN defined
+#endif
+
+
+int main(int argc, char** argv)
+{
+	int ret;
+	
+	ret=0;
+	if (endianness_sanity_check()!=0){
+		printf("ERROR: sanity checks failed\n");
+		ret=-1;
+	}
+	if (is_little_endian()){
+#ifdef __IS_LITTLE_ENDIAN
+		printf("OK: little endian confirmed\n");
+#else 
+		printf("ERROR: macro claims BIG ENDIAN, but it's little\n");
+		return -1;
+#endif
+	}else{
+#ifdef __IS_BIG_ENDIAN
+		printf("OK: big endian confirmed\n");
+#else 
+		printf("ERROR: macro claims LITTLE ENDIAN, but it's big\n");
+		return -1;
+#endif
+	}
+	return ret;
+}
diff --git a/test/file_copyright.txt b/test/file_copyright.txt
new file mode 100644
index 0000000..2df52e4
--- /dev/null
+++ b/test/file_copyright.txt
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2001-2004 FhG Fokus 
+ *
+ * This file is part of ser, a free SIP server.
+ *
+ * ser is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ *  For a license to use the ser software under conditions
+ *  other than those described here, or to purchase support for this
+ *  software, please contact iptel.org by e-mail at the following addresses:
+ *     info at iptel.org
+ *
+ * ser is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
diff --git a/test/flood.cfg b/test/flood.cfg
new file mode 100644
index 0000000..5d34983
--- /dev/null
+++ b/test/flood.cfg
@@ -0,0 +1,32 @@
+#
+# configuration for Stress testing
+#
+#
+
+
+debug=3          # debug level (cmd line: -dddddddddd)
+#fork=yes          # (cmd. line: -D)
+fork=yes
+fork=no
+log_stderror=yes # (cmd line: -E)
+#log_stderror=no	# (cmd line: -E)
+
+
+children=4
+check_via=no     # (cmd. line: -v)
+dns=off           # (cmd. line: -r)
+rev_dns=off      # (cmd. line: -R)
+#port=5070
+listen=10.0.0.179
+#listen=127.0.0.1
+#listen=192.168.57.33
+loop_checks=0
+# for more info: sip_router -h
+
+#modules
+
+
+route{
+	#forward(uri:host, uri:port);
+	forward(127.0.0.1, 5090);
+}
diff --git a/test/gcc_version.sh b/test/gcc_version.sh
new file mode 100755
index 0000000..078b852
--- /dev/null
+++ b/test/gcc_version.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+#
+# wrapper arroung gcc, that intercepts --version and reports instead
+# $GCC_VERSION
+#
+
+if [ -n "$GCC_VERSION" ]; then
+	for o in $@; do
+		if [ "$o" = "--version" ] ; then
+			echo $GCC_VERSION
+			exit 0
+		fi
+	done
+fi
+
+gcc $@
diff --git a/test/gcc_version_test.sh b/test/gcc_version_test.sh
new file mode 100755
index 0000000..4a6912b
--- /dev/null
+++ b/test/gcc_version_test.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+# test make cfg with all the gcc versions in gcc_versions.txt
+# should be run from the main sip-router directory
+# Depends on: test/gcc_version.sh and test/gcc_versions.txt
+
+if [ ! -e test/gcc_version.sh -o ! -r test/gcc_versions.txt -o ! -r Makefile ]
+then
+	echo "ERROR: wrong path, this test must be run from the main"\
+		" sip-router directory"
+	exit 1
+fi
+
+while read v ; do
+	GCC_VERSION=$v make CC=test/gcc_version.sh cfg-defs >/dev/null
+	if [ $? -ne 0 -o ! -r config.mak ]; then
+		echo "ERROR: make cfg failed for version \"$v\""
+		exit 1
+	fi
+	COMPILER=`egrep -o -- "-DCOMPILER='\"[^\"' ]+ [2-9]\.[0-9]{1,2}(\.[0-9]{1,2})?\"'" config.mak`
+	if [ $? -ne 0 -o -z "$COMPILER" ]; then
+		echo "ERROR: bad ver: \"$v\" => `egrep -o -- "-DCOMPILER='[^']*'" config.mak`"
+		exit 1
+	fi
+	echo "ok: \"$v\" => $COMPILER"
+done < test/gcc_versions.txt
diff --git a/test/gcc_versions.txt b/test/gcc_versions.txt
new file mode 100644
index 0000000..2b8f23c
--- /dev/null
+++ b/test/gcc_versions.txt
@@ -0,0 +1,25 @@
+2.7.1
+2.8.1
+egcs-2.91.66
+2.95.3
+2.95.4
+3.0.4
+gcc (GCC) 3.2
+gcc-3.2 (GCC) 3.2.3 (Debian)
+gcc (GCC) 3.3 20030304 (Apple Computer, Inc. build 1809)
+gcc (GCC) 3.3.3 (NetBSD nb3 20040520)
+gcc (GCC) 3.3.5 (propolice)
+gcc-3.3 (GCC) 3.3.5 (Debian 1:3.3.5-6)
+gcc-3.3 (GCC) 3.3.5 (Debian 1:3.3.5-13)
+gcc (GCC) 3.4.2 [FreeBSD] 20040728
+gcc (GCC) 3.4.3 (csl-sol210-3_4-branch+sol_rpath)
+gcc-3.4 (GCC) 3.4.4 20041218 (prerelease) (Debian 3.4.3-7)
+powerpc-apple-darwin8-gcc-3.5.0 (GCC) 3.5.0 20041026 (Apple Computer, Inc. build 4059)
+powerpc-apple-darwin8-gcc-4.0.0 (GCC) 4.0.0 20041026 (Apple Computer, Inc. build 4061)
+gcc-4.0 (GCC) 4.0.2 20050821 (prerelease) (Debian 4.0.1-6)
+gcc-4.0 (GCC) 4.0.4 20060904 (prerelease) (Debian 4.0.3-7)
+gcc-4.0.1 (GCC) 3.3.6 (Gentoo 3.3.6, ssp-3.3.6-1.0, pie-8.7.8)
+gcc-4.1 (GCC) 4.1.3 20080704 (prerelease) (Debian 4.1.2-25)
+gcc-4.2 (GCC) 4.2.4 (Debian 4.2.4-6)
+gcc-4.3 (Debian 4.3.3-8) 4.3.3
+gcc (SUSE Linux) 4.3.2 [gcc-4_3-branch revision 141291]
diff --git a/test/gen.cfg b/test/gen.cfg
new file mode 100644
index 0000000..e99afc4
--- /dev/null
+++ b/test/gen.cfg
@@ -0,0 +1,41 @@
+#
+# configuration for Stress testing
+#
+
+
+debug=9          # debug level (cmd line: -dddddddddd)
+#fork=yes          # (cmd. line: -D)
+fork=no
+log_stderror=yes  # (cmd line: -E)
+#log_stderror=no   # (cmd line: -E)
+
+
+children=4
+check_via=no      # (cmd. line: -v)
+dns=off           # (cmd. line: -r)
+rev_dns=off       # (cmd. line: -R)
+#port=5070
+#listen=10.0.0.179
+#listen=192.168.57.33
+loop_checks=0
+# for more info: sip_router -h
+
+#modules
+#loadmodule "modules/print/print.so"
+loadmodule "modules/textops/textops.so"
+loadmodule "modules/tm/tm.so"
+loadmodule "modules/maxfwd/maxfwd.so"
+loadmodule "modules/sl/sl.so"
+
+
+route{
+	sl_filter_ACK();
+
+	if ( !mf_process_maxfwd_header("10") )
+	{
+		sl_send_reply("483","To Many Hops");
+		drop();
+	};
+
+	t_relay();
+}
diff --git a/test/gethostbyaddr.c b/test/gethostbyaddr.c
new file mode 100644
index 0000000..2393680
--- /dev/null
+++ b/test/gethostbyaddr.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2001-2003 FhG Fokus
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <netdb.h>
+
+
+
+
+static char* id="$Id$";
+static char* version="gethostbyaddr 0.1";
+static char* help_msg="\
+Usage: gethostbyaddr   [-hV] -n host\n\
+Options:\n\
+    -n host       host name\n\
+    -V            version number\n\
+    -h            this help message\n\
+";
+
+
+int main(int argc, char** argv)
+{
+	char c;
+	char* name;
+	struct hostent* he;
+	unsigned char** h;
+
+	name=0;
+	
+	opterr=0;
+	while ((c=getopt(argc, argv, "n:hV"))!=-1){
+		switch(c){
+			case 'n':
+				name=optarg;
+				break;
+			case 'V':
+				printf("version: %s\n", version);
+				printf("%s\n", id);
+				exit(0);
+				break;
+			case 'h':
+				printf("version: %s\n", version);
+				printf("%s", help_msg);
+				exit(0);
+				break;
+			case '?':
+				if (isprint(optopt))
+					fprintf(stderr, "Unknown option `-%c�\n", optopt);
+				else
+					fprintf(stderr, "Unknown character `\\x%x�\n", optopt);
+				goto error;
+			case ':':
+				fprintf(stderr, "Option `-%c� requires an argument.\n",
+						optopt);
+				goto error;
+				break;
+			default:
+				abort();
+		}
+	}
+	
+	if (name==0){
+		fprintf(stderr, "Missing domain name (-n name)\n");
+		goto error;
+	}
+	
+	he=gethostbyname(name);
+	if (he==0){
+			printf("bad address <%s>\n", name);
+			goto error;
+	}
+	he=gethostbyaddr(he->h_addr_list[0], he->h_length, he->h_addrtype); 
+	if (he==0) printf("no answer\n");
+	else{
+		printf("h_name=%s\n", he->h_name);
+		for(h=he->h_aliases;*h;h++)
+			printf("   alias=%s\n", *h);
+		for(h=he->h_addr_list;*h;h++)
+			printf("   ip=%d.%d.%d.%d\n", (*h)[0],(*h)[1],(*h)[2],(*h)[3] );
+	}
+	printf("done\n");
+	exit(0);
+error:
+	exit(-1);
+}
diff --git a/test/gethostbyname.c b/test/gethostbyname.c
new file mode 100644
index 0000000..2d57917
--- /dev/null
+++ b/test/gethostbyname.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2001-2003 FhG Fokus
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <netdb.h>
+
+
+
+
+static char* id="$Id$";
+static char* version="gethostbyname 0.1";
+static char* help_msg="\
+Usage: gethostbyname   [-hV] -n host\n\
+Options:\n\
+    -n host       host name\n\
+    -V            version number\n\
+    -h            this help message\n\
+";
+
+
+int main(int argc, char** argv)
+{
+	char c;
+	char* name;
+	struct hostent* he;
+	unsigned char** h;
+
+	name=0;
+	
+	opterr=0;
+	while ((c=getopt(argc, argv, "n:hV"))!=-1){
+		switch(c){
+			case 'n':
+				name=optarg;
+				break;
+			case 'V':
+				printf("version: %s\n", version);
+				printf("%s\n", id);
+				exit(0);
+				break;
+			case 'h':
+				printf("version: %s\n", version);
+				printf("%s", help_msg);
+				exit(0);
+				break;
+			case '?':
+				if (isprint(optopt))
+					fprintf(stderr, "Unknown option `-%c�\n", optopt);
+				else
+					fprintf(stderr, "Unknown character `\\x%x�\n", optopt);
+				goto error;
+			case ':':
+				fprintf(stderr, "Option `-%c� requires an argument.\n",
+						optopt);
+				goto error;
+				break;
+			default:
+				abort();
+		}
+	}
+	
+	if (name==0){
+		fprintf(stderr, "Missing domain name (-n name)\n");
+		goto error;
+	}
+	
+	he=gethostbyname(name);
+	if (he==0) printf("no answer\n");
+	else{
+		printf("h_name=%s\n", he->h_name);
+		for(h=he->h_aliases;*h;h++)
+			printf("   alias=%s\n", *h);
+		for(h=he->h_addr_list;*h;h++)
+			printf("   ip=%d.%d.%d.%d\n", (*h)[0],(*h)[1],(*h)[2],(*h)[3] );
+	}
+	printf("done\n");
+	exit(0);
+error:
+	exit(-1);
+}
diff --git a/test/gplall.sh b/test/gplall.sh
new file mode 100755
index 0000000..6c549ce
--- /dev/null
+++ b/test/gplall.sh
@@ -0,0 +1,6 @@
+#!/bin/sh 
+
+for i in `find . -name '*.[hc]'` ; do
+	mv $i $i.pregpl
+	awk -f test/gplize.awk $i.pregpl > $i
+done
diff --git a/test/gplize.awk b/test/gplize.awk
new file mode 100644
index 0000000..859fc4d
--- /dev/null
+++ b/test/gplize.awk
@@ -0,0 +1,62 @@
+# add copyright banner after the first comment
+#
+# text taken from file_copyright.txt
+
+BEGIN {
+	status=0;
+}
+
+
+status==1 {
+	print 
+	next
+}
+
+# end of comment not encountered yet
+
+{ comment_begin=0 }
+
+/\/\*/ { comment_begin=1; }
+
+
+/\*\// {
+	status=1
+	# if it was a one-line comment print it and start a new comment
+	if (comment_begin==1) {
+		print
+		print "/*"
+	}
+
+	print " *"
+	print " * Copyright (C) 2001-2004 FhG Fokus"
+	print " *"
+	print " * This file is part of ser, a free SIP server."
+	print " *"
+	print " * ser is free software; you can redistribute it and/or modify"
+	print " * it under the terms of the GNU General Public License as published by"
+	print " * the Free Software Foundation; either version 2 of the License, or"
+	print " * (at your option) any later version"
+	print " *"
+	print " * For a license to use the ser software under conditions"
+	print " * other than those described here, or to purchase support for this"
+	print " * software, please contact iptel.org by e-mail at the following addresses:"
+	print " *    info at iptel.org"
+	print " *"
+	print " * ser is distributed in the hope that it will be useful,"
+	print " * but WITHOUT ANY WARRANTY; without even the implied warranty of"
+	print " * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the"
+	print " * GNU General Public License for more details."
+	print " *"
+	print " * You should have received a copy of the GNU General Public License "
+	print " * along with this program; if not, write to the Free Software "
+	print " * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA"
+	print " */"
+	print ""
+
+	# don't print the original end of comment
+	next
+}
+
+# end of comment not encountered yet -- print the line
+
+{ print }
diff --git a/test/ifls.c b/test/ifls.c
new file mode 100644
index 0000000..25a1aa5
--- /dev/null
+++ b/test/ifls.c
@@ -0,0 +1,343 @@
+/*
+ * test programs, list all interfaces and their ip address
+ *
+ * Copyright (C) 2001-2003 FhG Fokus
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+ /*
+  * History:
+  * --------
+  *  2002-09-09  created by andrei
+  */
+
+
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#ifdef __sun__
+#include <sys/sockio.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+#define FLAGS 1
+#define IF_DOWN 2
+#define IF_UP   4
+
+
+static char* version="ifls 0.1";
+static char* id="$Id$";
+static char* help_msg="\
+Usage: ifls [-6hV} [interface...]\n\
+(if no interface name is specified it will list all the interfaces)\n\
+Options:\n\
+    -a      list both ipv4 and ipv6 interfaces (default)\n\
+    -4      list only ipv4 interfaces\n\
+    -6      list only ipv6 interfaces\n\
+    -f      show also the interface flags\n\
+    -U      brings all the matching interfaces up\n\
+    -D      brings all the matching interfaces down\n\
+    -V      version number\n\
+    -h      this help message\n\
+";
+
+
+#define MAX(a,b) ( ((a)>(b))?(a):(b))
+
+
+
+void print_sockaddr(struct sockaddr* sa)
+{
+	unsigned char* buf;
+	int r;
+	
+	switch(sa->sa_family){
+	case AF_INET:
+		buf=(char*)&(((struct sockaddr_in*)sa)->sin_addr).s_addr;
+		printf("%d.%d.%d.%d\n", buf[0], buf[1], buf[2], buf[3]);
+		break;
+	case AF_INET6:
+		buf=(((struct sockaddr_in6*)sa)->sin6_addr).s6_addr;
+		for(r=0; r<16; r++) 
+			printf("%02x%s", buf[r], ((r%2)&&(r!=15))?":":"" );
+		printf("\n");
+		break;
+	default:
+		printf("unknown af %d\n", sa->sa_family);
+#ifdef __FreeBSD__
+		for (r=0; r<sa->sa_len; r++) 
+			printf("%02x ", ((unsigned char*)sa)[r]);
+		printf("\n");
+#endif
+	}
+}
+
+
+
+int ls_ifflags(char* name, int family , int options)
+{
+	struct ifreq ifr;
+	int s;
+	
+	memset(&ifr, 0, sizeof(ifr)); /* init to 0 (check if filled)*/
+	s=socket(family, SOCK_DGRAM, 0);
+	strncpy(ifr.ifr_name, name, IFNAMSIZ);
+#if 0	
+	if (ioctl(s, SIOCGIFADDR, &ifr)==-1){
+		if(errno==EBADF) return 0; /* invalid descriptor => no address*/
+		fprintf(stderr, "ls_if: ioctl for %s failed: %s\n", name, 
+					strerror(errno));
+		goto error;
+	};
+	
+	printf("%s:\n", ifr.ifr_name);
+	printf("        dbg: family=%d", ifr.ifr_addr.sa_family);
+#ifdef __FreeBSD__
+	printf(", len=%d\n", ifr.ifr_addr.sa_len);
+#else
+	printf("\n");
+#endif
+	if (ifr.ifr_addr.sa_family==0){
+		printf("ls_if: OS BUG: SIOCGIFADDR doesn't work!\n");
+		goto error;
+	}
+	
+	printf("        ");
+	print_sockaddr(&ifr.ifr_addr);
+
+	if (ifr.ifr_addr.sa_family!=family){
+		printf("ls_if: strange family %d\n", ifr.ifr_addr.sa_family);
+		/*goto error;*/
+	}
+#endif
+	if (options & (FLAGS|IF_DOWN|IF_UP)){
+		if (ioctl(s, SIOCGIFFLAGS, &ifr)==-1){
+			fprintf(stderr, "ls_if: flags ioctl for %s  failed: %s\n",
+					name, strerror(errno));
+			goto error;
+		}
+		if (ifr.ifr_flags & IFF_UP) printf ("UP ");
+		if (ifr.ifr_flags & IFF_BROADCAST) printf ("BROADCAST ");
+		if (ifr.ifr_flags & IFF_DEBUG) printf ("DEBUG ");
+		if (ifr.ifr_flags & IFF_LOOPBACK) printf ("LOOPBACK ");
+		if (ifr.ifr_flags & IFF_POINTOPOINT) printf ("POINTOPOINT ");
+		if (ifr.ifr_flags & IFF_RUNNING) printf ("RUNNING ");
+		if (ifr.ifr_flags & IFF_NOARP) printf ("NOARP ");
+		if (ifr.ifr_flags & IFF_PROMISC) printf ("PROMISC ");
+		/*if (ifr.ifr_flags & IFF_NOTRAILERS) printf ("NOTRAILERS ");*/
+		if (ifr.ifr_flags & IFF_ALLMULTI) printf ("ALLMULTI ");
+		/*if (ifr.ifr_flags & IFF_MASTER) printf ("MASTER ");*/
+		/*if (ifr.ifr_flags & IFF_SLAVE) printf ("SLAVE ");*/
+		if (ifr.ifr_flags & IFF_MULTICAST) printf ("MULTICAST ");
+		/*if (ifr.ifr_flags & IFF_PORTSEL) printf ("PORTSEL ");*/
+		/*if (ifr.ifr_flags & IFF_AUTOMEDIA) printf ("AUTOMEDIA ");*/
+		/*if (ifr.ifr_flags & IFF_DYNAMIC ) printf ("DYNAMIC ");*/
+		printf ("\n");
+		if (options & IF_DOWN){
+			ifr.ifr_flags &= ~IFF_UP;
+		}
+		if (options & IF_UP){
+			ifr.ifr_flags |= IFF_UP;
+		}
+		if (options & (IF_UP|IF_DOWN)){
+			if (ioctl(s, SIOCSIFFLAGS, &ifr)==-1){
+				fprintf(stderr, "ls_if: set flags ioctl for %s  failed: %s\n",
+						name, strerror(errno));
+				goto error;
+			}
+		}
+	};
+		
+	close(s);
+	return 0;
+error:
+	close(s);
+	return -1;
+}
+
+
+
+int ls_ifs(char* name, int family, int options)
+{
+	struct ifconf ifc;
+	struct ifreq* ifr;
+	char*  last;
+	int size;
+	int lastlen;
+	int s;
+	
+	/* ipv4 or ipv6 only*/
+	s=socket(family, SOCK_DGRAM, 0);
+	lastlen=0;
+	for (size=2; ; size*=2){
+		ifc.ifc_len=size*sizeof(struct ifreq);
+		ifc.ifc_req=(struct ifreq*) malloc(size*sizeof(struct ifreq));
+		if (ifc.ifc_req==0){
+			fprintf(stderr, "memory allocation failure\n");
+			goto error;
+		}
+		if (ioctl(s, SIOCGIFCONF, &ifc)==-1){
+			if(errno==EBADF) return 0; /* invalid descriptor => no such ifs*/
+			fprintf(stderr, "ioctl failed: %s\n", strerror(errno));
+			goto error;
+		}
+		if  ((lastlen) && (ifc.ifc_len==lastlen)) break; /*success,
+														   len not changed*/
+		lastlen=ifc.ifc_len;
+		/* try a bigger array*/
+		free(ifc.ifc_req);
+	}
+	
+	last=(char*)ifc.ifc_req+ifc.ifc_len;
+	for(ifr=ifc.ifc_req; (char*)ifr<last;
+			ifr=(struct ifreq*)((char*)ifr+sizeof(ifr->ifr_name)+
+			#ifdef  __FreeBSD__
+				MAX(ifr->ifr_addr.sa_len, sizeof(struct sockaddr))
+			#else
+				( (ifr->ifr_addr.sa_family==AF_INET)?
+					sizeof(struct sockaddr_in):
+					((ifr->ifr_addr.sa_family==AF_INET6)?
+						sizeof(struct sockaddr_in6):sizeof(struct sockaddr)) )
+			#endif
+				)
+		)
+	{
+/*
+		printf("\nls_all dbg: %s family=%d", ifr->ifr_name,
+				 						ifr->ifr_addr.sa_family);
+#ifdef __FreeBSD__
+		printf(", len=%d\n", ifr->ifr_addr.sa_len);
+#else
+		printf("\n");
+#endif
+*/
+		if (ifr->ifr_addr.sa_family!=family){
+			/*printf("strange family %d skipping...\n",
+					ifr->ifr_addr.sa_family);*/
+			continue;
+		}
+		if ((name==0)||
+			(strncmp(name, ifr->ifr_name, sizeof(ifr->ifr_name))==0)){
+			printf("%s:\n", ifr->ifr_name);
+			printf("        ");
+			print_sockaddr(&(ifr->ifr_addr));
+			printf("        ");
+			ls_ifflags(ifr->ifr_name, family, options);
+			printf("\n");
+		}
+	}
+	free(ifc.ifc_req); /*clean up*/
+	close(s);
+	return  0;
+error:
+	close(s);
+	return -1;
+}
+
+
+int main(int argc, char**argv)
+{
+	char** name;
+	int no;
+	int options;
+	int ipv6, ipv4;
+	int r;
+	char c;
+	
+	
+	options=0;
+	ipv6=ipv4=1;
+	name=0;
+	no=0;
+	opterr=0;
+	while((c=getopt(argc, argv, "a46fhVUD"))!=-1){
+		switch(c){
+			case 'a':
+				ipv6=ipv4=1;
+				break;
+			case '4':
+				ipv6=0;
+				ipv4=1;
+				break;
+			case '6':
+				ipv4=0;
+				ipv6=1;
+				break;
+			case 'f':
+				options|=FLAGS;
+				break;
+			case 'V':
+				printf("version: %s\n", version);
+				printf("%s\n", id);
+				exit(0);
+				break;
+			case 'D':
+				options|=IF_DOWN;
+				break;
+			case 'U':
+				options|=IF_UP;
+				break;
+			case 'h':
+				printf("version: %s\n", version);
+				printf("%s", help_msg);
+				exit(0);
+				break;
+			case '?':
+				if (isprint(optopt))
+					fprintf(stderr, "Unknown option `-%c�\n", optopt);
+				else
+					fprintf(stderr, "Unknown character `\\x%x�\n", optopt);
+				goto error;
+			case ':':
+				fprintf(stderr, "Option `-%c� requires an argument\n",
+						optopt);
+				goto error;
+			default:
+				abort();
+		};
+	};
+	/* check if we have non-options */
+	if( optind < argc){
+		no=argc-optind;
+		name=&argv[optind];
+	}
+	
+	if (no==0){
+		/* list all interfaces */
+		if (ipv4) ls_ifs(0, AF_INET, options);
+		if (ipv6) ls_ifs(0, AF_INET6, options);
+	}else{
+		for(r=0; r<no; r++){
+			if (ipv4) ls_ifs(name[r], AF_INET, options);
+			if (ipv6) ls_ifs(name[r], AF_INET6, options);
+		}
+	};
+	
+	
+	exit(0);
+error:
+	exit(-1);
+};
diff --git a/test/inv_srv.sip b/test/inv_srv.sip
new file mode 100644
index 0000000..400bc3b
--- /dev/null
+++ b/test/inv_srv.sip
@@ -0,0 +1,21 @@
+INVITE sip:andrei at mobile69 SIP/2.0
+Via: SIP/2.0/UDP dorian.fokus.gmd.de 
+From: "test" <sip:andrei at iptel.org>;tag=b96b0300ed30f1286-2f5d
+Call-ID: b96b0300-88d30f-66da-63aa at 195.37.78.190
+CSeq: 101 INVITE
+Expires: 180
+Max-Forwards:  0
+User-Agent: testing lookups
+Accept: application/sdp
+Content-Length: 225
+
+
+v=0
+o=CiscoSystemsSIP-IPPhone-UserAgent 14474 8233 IN IP4 195.37.78.190
+s=SIP Call
+c=IN IP4 195.37.78.190
+t=0 0
+m=audio 18456 RTP/AVP 0 8 18 101
+a=rtpmap:0 pcmu/8000
+a=rtpmap:101 telephone-event/8000
+a=fmtp:101 0-11 
diff --git a/test/invite00.sip b/test/invite00.sip
new file mode 100644
index 0000000..2ee3c4a
--- /dev/null
+++ b/test/invite00.sip
@@ -0,0 +1,33 @@
+INVITE sip:7170 at iptel.org SIP/2.0
+Via: SIP/2.0/UDP 195.37.77.100:5040;  rport
+Max-Forwards: 10
+From: "jiri" <sip:jiri at iptel.org>;tag=76ff7a07-c091-4192-84a0-d56e91fe104f
+To: <sip:jiri at bat.iptel.org>
+Call-ID: d10815e0-bf17-4afa-8412-d9130a793d96 at 213.20.128.35
+CSeq: 2 INVITE
+Contact: <sip:213.20.128.35:9315>
+User-Agent: Windows RTC/1.0
+Proxy-Authorization: Digest username="jiri", realm="iptel.org", algorithm="MD5", uri="sip:jiri at bat.iptel.org", nonce="3cef753900000001771328f5ae1b8b7f0d742da1feb5753c", response="53fe98db10e1074b03b3e06438bda70f"
+Content-Type: application/sdp
+Content-Length: 451
+
+v=0
+o=jku2 0 0 IN IP4 213.20.128.35
+s=session
+c=IN IP4 213.20.128.35
+b=CT:1000
+t=0 0
+m=audio 54742 RTP/AVP 97 111 112 6 0 8 4 5 3 101
+a=rtpmap:97 red/8000
+a=rtpmap:111 SIREN/16000
+a=fmtp:111 bitrate=16000
+a=rtpmap:112 G7221/16000
+a=fmtp:112 bitrate=24000
+a=rtpmap:6 DVI4/16000
+a=rtpmap:0 PCMU/8000
+a=rtpmap:8 PCMA/8000
+a=rtpmap:4 G723/8000
+a=rtpmap:5 DVI4/8000
+a=rtpmap: 3 GSM/8000
+a=rtpmap:101 telephone-event/8000
+a=fmtp:101 0-16
diff --git a/test/invite01.sip b/test/invite01.sip
new file mode 100644
index 0000000..78d3e4f
--- /dev/null
+++ b/test/invite01.sip
@@ -0,0 +1,33 @@
+INVITE sip:7271 at iptel.org SIP/2.0
+Via: SIP/2.0/UDP 195.37.77.100:5040
+Max-Forwards: 10
+From: "jiri" <sip:jiri at iptel.org>;tag=76ff7a07-c091-4192-84a0-d56e91fe104f
+To: <sip:jiri at bat.iptel.org>
+Call-ID: d10815e0-bf17-4afa-8412-d9130a793d96 at 213.20.128.35
+CSeq: 2 INVITE
+Contact: <sip:213.20.128.35:9315>
+User-Agent: Windows RTC/1.0
+Proxy-Authorization: Digest username="jiri", realm="iptel.org", algorithm="MD5", uri="sip:jiri at bat.iptel.org", nonce="3cef753900000001771328f5ae1b8b7f0d742da1feb5753c", response="53fe98db10e1074b03b3e06438bda70f"
+Content-Type: application/sdp
+Content-Length: 452
+
+v=0
+o=jku2 0 0 IN IP4 213.20.128.35
+s=session
+c=IN IP4 213.20.128.35
+b=CT:1000
+t=0 0
+m=audio 54742 RTP/AVP 97 111 112 6 0 8 4 5 3 101
+a=rtpmap:97 red/8000
+a=rtpmap:111 SIREN/16000
+a=fmtp:111 bitrate=16000
+a=rtpmap:112 G7221/16000
+a=fmtp:112 bitrate=24000
+a=rtpmap:6 DVI4/16000
+a=rtpmap:0 PCMU/8000
+a=rtpmap:8 PCMA/8000
+a=rtpmap:4 G723/8000
+a=rtpmap:5 DVI4/8000
+a=rtpmap: 3 GSM/8000
+a=rtpmap:101 telephone-event/8000
+a=fmtp:101 0-16
diff --git a/test/invite02.sip b/test/invite02.sip
new file mode 100644
index 0000000..69abd27
--- /dev/null
+++ b/test/invite02.sip
@@ -0,0 +1,33 @@
+INVITE sip:7271 at iptel.org SIP/2.0
+Via: SIP/2.0/UDP 195.37.77.99:5040
+Max-Forwards: 1
+From: "jiri" <sip:jiri at iptel.org>;tag=76ff7a07-c091-4192-84a0-d56e91fe104f
+To: <sip:jiri at bat.iptel.org>
+Call-ID: r10815e0-bf17-4afa-8412-d9130a793d96 at 213.20.128.35
+CSeq: 2 INVITE
+Contact: <sip:213.20.128.35:9315>
+User-Agent: Windows RTC/1.0
+Proxy-Authorization: Digest username="jiri", realm="iptel.org", algorithm="MD5", uri="sip:jiri at bat.iptel.org", nonce="3cef753900000001771328f5ae1b8b7f0d742da1feb5753c", response="53fe98db10e1074b03b3e06438bda70f"
+Content-Type: application/sdp
+Content-Length: 451
+
+v=0
+o=jku2 0 0 IN IP4 213.20.128.35
+s=session
+c=IN IP4 213.20.128.35
+b=CT:1000
+t=0 0
+m=audio 54742 RTP/AVP 97 111 112 6 0 8 4 5 3 101
+a=rtpmap:97 red/8000
+a=rtpmap:111 SIREN/16000
+a=fmtp:111 bitrate=16000
+a=rtpmap:112 G7221/16000
+a=fmtp:112 bitrate=24000
+a=rtpmap:6 DVI4/16000
+a=rtpmap:0 PCMU/8000
+a=rtpmap:8 PCMA/8000
+a=rtpmap:4 G723/8000
+a=rtpmap:5 DVI4/8000
+a=rtpmap: 3 GSM/8000
+a=rtpmap:101 telephone-event/8000
+a=fmtp:101 0-16
diff --git a/test/invite03.sip b/test/invite03.sip
new file mode 100644
index 0000000..47f7d97
--- /dev/null
+++ b/test/invite03.sip
@@ -0,0 +1,33 @@
+INVITE sip:7271 at iptel.org SIP/2.0
+Via: SIP/2.0/UDP 195.37.77.100:5040
+Max-Forwards: 3
+From: "jiri" <sip:jiri at iptel.org>;tag=76ff7a07-c091-4192-84a0-d56e91fe104f
+To: <sip:jiri at bat.iptel.org>
+Call-ID: r10815e0-bf17-4afa-8412-d9130a793d96 at 213.20.128.35
+CSeq: 2 INVITE
+Contact: <sip:213.20.128.35:9315>
+User-Agent: Windows RTC/1.0
+Proxy-Authorization: Digest username="jiri", realm="iptel.org", algorithm="MD5", uri="sip:jiri at bat.iptel.org", nonce="3cef753900000001771328f5ae1b8b7f0d742da1feb5753c", response="53fe98db10e1074b03b3e06438bda70f"
+Content-Type: application/sdp
+Content-Length: 451
+
+v=0
+o=jku2 0 0 IN IP4 213.20.128.35
+s=session
+c=IN IP4 213.20.128.35
+b=CT:1000
+t=0 0
+m=audio 54742 RTP/AVP 97 111 112 6 0 8 4 5 3 101
+a=rtpmap:97 red/8000
+a=rtpmap:111 SIREN/16000
+a=fmtp:111 bitrate=16000
+a=rtpmap:112 G7221/16000
+a=fmtp:112 bitrate=24000
+a=rtpmap:6 DVI4/16000
+a=rtpmap:0 PCMU/8000
+a=rtpmap:8 PCMA/8000
+a=rtpmap:4 G723/8000
+a=rtpmap:5 DVI4/8000
+a=rtpmap: 3 GSM/8000
+a=rtpmap:101 telephone-event/8000
+a=fmtp:101 0-16
diff --git a/test/invite04.sip b/test/invite04.sip
new file mode 100644
index 0000000..71308c2
--- /dev/null
+++ b/test/invite04.sip
@@ -0,0 +1,33 @@
+INVITE sip:7170 at bat.iptel.org:9 SIP/2.0
+Via: SIP/2.0/UDP 195.37.77.100:5040
+Max-Forwards: 1
+From: "jiri" <sip:jiri at iptel.org>;tag=76ff7a07-c091-4192-84a0-d56e91fe104f
+To: <sip:jiri at bat.iptel.org>
+Call-ID: r10815e0-bf17-4afa-8412-d9130a793d96 at 213.20.128.35
+CSeq: 2 INVITE
+Contact: <sip:213.20.128.35:9315>
+User-Agent: Windows RTC/1.0
+Proxy-Authorization: Digest username="jiri", realm="iptel.org", algorithm="MD5", uri="sip:jiri at bat.iptel.org", nonce="3cef753900000001771328f5ae1b8b7f0d742da1feb5753c", response="53fe98db10e1074b03b3e06438bda70f"
+Content-Type: application/sdp
+Content-Length: 451
+
+v=0
+o=jku2 0 0 IN IP4 213.20.128.35
+s=session
+c=IN IP4 213.20.128.35
+b=CT:1000
+t=0 0
+m=audio 54742 RTP/AVP 97 111 112 6 0 8 4 5 3 101
+a=rtpmap:97 red/8000
+a=rtpmap:111 SIREN/16000
+a=fmtp:111 bitrate=16000
+a=rtpmap:112 G7221/16000
+a=fmtp:112 bitrate=24000
+a=rtpmap:6 DVI4/16000
+a=rtpmap:0 PCMU/8000
+a=rtpmap:8 PCMA/8000
+a=rtpmap:4 G723/8000
+a=rtpmap:5 DVI4/8000
+a=rtpmap: 3 GSM/8000
+a=rtpmap:101 telephone-event/8000
+a=fmtp:101 0-16
diff --git a/test/invite05.sip b/test/invite05.sip
new file mode 100644
index 0000000..71308c2
--- /dev/null
+++ b/test/invite05.sip
@@ -0,0 +1,33 @@
+INVITE sip:7170 at bat.iptel.org:9 SIP/2.0
+Via: SIP/2.0/UDP 195.37.77.100:5040
+Max-Forwards: 1
+From: "jiri" <sip:jiri at iptel.org>;tag=76ff7a07-c091-4192-84a0-d56e91fe104f
+To: <sip:jiri at bat.iptel.org>
+Call-ID: r10815e0-bf17-4afa-8412-d9130a793d96 at 213.20.128.35
+CSeq: 2 INVITE
+Contact: <sip:213.20.128.35:9315>
+User-Agent: Windows RTC/1.0
+Proxy-Authorization: Digest username="jiri", realm="iptel.org", algorithm="MD5", uri="sip:jiri at bat.iptel.org", nonce="3cef753900000001771328f5ae1b8b7f0d742da1feb5753c", response="53fe98db10e1074b03b3e06438bda70f"
+Content-Type: application/sdp
+Content-Length: 451
+
+v=0
+o=jku2 0 0 IN IP4 213.20.128.35
+s=session
+c=IN IP4 213.20.128.35
+b=CT:1000
+t=0 0
+m=audio 54742 RTP/AVP 97 111 112 6 0 8 4 5 3 101
+a=rtpmap:97 red/8000
+a=rtpmap:111 SIREN/16000
+a=fmtp:111 bitrate=16000
+a=rtpmap:112 G7221/16000
+a=fmtp:112 bitrate=24000
+a=rtpmap:6 DVI4/16000
+a=rtpmap:0 PCMU/8000
+a=rtpmap:8 PCMA/8000
+a=rtpmap:4 G723/8000
+a=rtpmap:5 DVI4/8000
+a=rtpmap: 3 GSM/8000
+a=rtpmap:101 telephone-event/8000
+a=fmtp:101 0-16
diff --git a/test/invite1.sip b/test/invite1.sip
new file mode 100644
index 0000000..661019a
--- /dev/null
+++ b/test/invite1.sip
@@ -0,0 +1,23 @@
+INVITE sip:p2 at iptel.org SIP/2.0
+Via: SIP/2.0/UDP 192.168.99.100:5040
+From: "GMD FOKUS iptlab" <sip:jiri at iptel.org>;tag=b96b0300ed30f1286-2f5d
+Call-ID: b96b0300-88d30f-66da-63aa at 195.37.78.190
+CSeq: 101 INVITE
+Expires: 180
+Max-Forwards:  0
+User-Agent: Cisco-SIP-IP-Phone/2
+Accept: application/sdp
+Contact: sip:jiri at 195.37.78.190:5060
+Content-Type: application/sdp
+Content-Length: 218
+
+
+v=0
+o=CiscoSystemsSIP-IPPhone-UserAgent 14474 8233 IN IP4 195.37.78.190
+s=SIP Call
+c=IN IP4 195.37.78.190
+t=0 0
+m=audio 18456 RTP/AVP 0 8 18 101
+a=rtpmap:0 pcmu/8000
+a=rtpmap:101 telephone-event/8000
+a=fmtp:101 0-11 
diff --git a/test/invite3-callid.sip b/test/invite3-callid.sip
new file mode 100644
index 0000000..d33ab91
--- /dev/null
+++ b/test/invite3-callid.sip
@@ -0,0 +1,23 @@
+INVITE sip:p2 at iptel.org SIP/2.0
+Via: SIP/2.0/UDP 193.175.133.193
+From: "GMD FOKUS iptlab" <sip:jiri at iptel.org>;tag=b96b0300ed30f1286-2f5d
+To: <sip:p2 at iptel.org>
+ Call-ID: b96b0300-88d30f-66da-63aa at 195.37.78.190
+CSeq: 101 INVITE
+Expires: 180
+User-Agent: Cisco-SIP-IP-Phone/2
+Accept: application/sdp
+Contact: sip:jiri at 195.37.78.190:5060
+Content-Type: application/sdp
+Content-Length: 225
+
+
+v=0
+o=CiscoSystemsSIP-IPPhone-UserAgent 14474 8233 IN IP4 195.37.78.190
+s=SIP Call
+c=IN IP4 195.37.78.190
+t=0 0
+m=audio 18456 RTP/AVP 0 8 18 101
+a=rtpmap:0 pcmu/8000
+a=rtpmap:101 telephone-event/8000
+a=fmtp:101 0-11 
diff --git a/test/invite4-cseq.sip b/test/invite4-cseq.sip
new file mode 100644
index 0000000..88c6809
--- /dev/null
+++ b/test/invite4-cseq.sip
@@ -0,0 +1,23 @@
+INVITE sip:p2 at iptel.org SIP/2.0
+Via: SIP/2.0/UDP 193.175.133.193
+From: "GMD FOKUS iptlab" <sip:jiri at iptel.org>;tag=b96b0300ed30f1286-2f5d
+To: <sip:p2 at iptel.org>
+Call-ID: b96b0300-88d30f-66da-63aa at 195.37.78.190
+CSeq:101
+Expires: 180
+User-Agent: Cisco-SIP-IP-Phone/2
+Accept: application/sdp
+Contact: sip:jiri at 195.37.78.190:5060
+Content-Type: application/sdp
+Content-Length: 225
+
+
+v=0
+o=CiscoSystemsSIP-IPPhone-UserAgent 14474 8233 IN IP4 195.37.78.190
+s=SIP Call
+c=IN IP4 195.37.78.190
+t=0 0
+m=audio 18456 RTP/AVP 0 8 18 101
+a=rtpmap:0 pcmu/8000
+a=rtpmap:101 telephone-event/8000
+a=fmtp:101 0-11 
diff --git a/test/invite5-callid.sip b/test/invite5-callid.sip
new file mode 100644
index 0000000..44d89d4
--- /dev/null
+++ b/test/invite5-callid.sip
@@ -0,0 +1,23 @@
+INVITE sip:p2 at iptel.org SIP/2.0
+Via: SIP/2.0/UDP 193.175.133.193
+From: "GMD FOKUS iptlab" <sip:jiri at iptel.org>;tag=b96b0300ed30f1286-2f5d
+To: <sip:p2 at iptel.org>
+Call-ID; b96b0300-88d30f-66da-63aa at 195.37.78.190
+CSeq: 101 INVITE
+Expires: 180
+User-Agent: Cisco-SIP-IP-Phone/2
+Accept: application/sdp
+Contact: sip:jiri at 195.37.78.190:5060
+Content-Type: application/sdp
+Content-Length: 225
+
+
+v=0
+o=CiscoSystemsSIP-IPPhone-UserAgent 14474 8233 IN IP4 195.37.78.190
+s=SIP Call
+c=IN IP4 195.37.78.190
+t=0 0
+m=audio 18456 RTP/AVP 0 8 18 101
+a=rtpmap:0 pcmu/8000
+a=rtpmap:101 telephone-event/8000
+a=fmtp:101 0-11 
diff --git a/test/invite6-badbranch-via.sip b/test/invite6-badbranch-via.sip
new file mode 100644
index 0000000..36be42f
--- /dev/null
+++ b/test/invite6-badbranch-via.sip
@@ -0,0 +1,23 @@
+INVITE sip:p2 at iptel.org SIP/2.0
+Via: SIP/2.0/UDP 193.175.133.193;branch=
+From: "GMD FOKUS iptlab" <sip:jiri at iptel.org>;tag=b96b0300ed30f1286-2f5d
+To: <sip:p2 at iptel.org>
+Call-ID: b96b0300-88d30f-66da-63aa at 195.37.78.190
+CSeq: 101 INVITE
+Expires: 180
+User-Agent: Cisco-SIP-IP-Phone/2
+Accept: application/sdp
+Contact: sip:jiri at 195.37.78.190:5060
+Content-Type: application/sdp
+Content-Length: 225
+
+
+v=0
+o=CiscoSystemsSIP-IPPhone-UserAgent 14474 8233 IN IP4 195.37.78.190
+s=SIP Call
+c=IN IP4 195.37.78.190
+t=0 0
+m=audio 18456 RTP/AVP 0 8 18 101
+a=rtpmap:0 pcmu/8000
+a=rtpmap:101 telephone-event/8000
+a=fmtp:101 0-11 
diff --git a/test/lock_test.c b/test/lock_test.c
new file mode 100644
index 0000000..22c8c34
--- /dev/null
+++ b/test/lock_test.c
@@ -0,0 +1,43 @@
+/*
+ * 
+ *  simple locking test program
+ *  (no paralles stuff)
+ * 
+ *  Compile with: gcc -D__CPU_i386 -O3 on x86 machines and
+ *                gcc -mips2 -O2 -D__CPU_mips2  on mips machines.
+ *  -- andrei
+ *
+ *  
+ */
+
+#include <stdio.h>
+#include "../fastlock.h"
+
+
+
+int main(int argc, char** argv)
+{
+	fl_lock_t lock;
+	int r;
+	
+	lock=0;
+	printf("starting locking basic tests...\n");
+	
+	r=try_lock(&lock);
+	printf(" try_lock should return 0            ... %d\n", r);
+	printf("     lock should be 1 now            ... %d\n", lock);
+	r=try_lock(&lock);
+	printf(" tsl should return -1                ... %d\n", r);
+	printf("     lock should still be 1 now      ... %d\n", lock);
+	release_lock(&lock);
+	printf(" release_lock: lock should be 0 now  ... %d\n", lock);
+	printf("try_lock once more...\n");
+	r=try_lock(&lock);
+	printf(" try_lock should return 0            ... %d\n", r);
+	printf("     lock should be 1 now            ... %d\n", lock);
+	release_lock(&lock);
+	get_lock(&lock);
+	printf(" get_lock, lock should be 1 now      ... %d\n", lock);
+	printf("\ndone.\n");
+	return 0;
+}
diff --git a/test/locking/Makefile b/test/locking/Makefile
new file mode 100644
index 0000000..a99c679
--- /dev/null
+++ b/test/locking/Makefile
@@ -0,0 +1,63 @@
+#
+# $Id$
+#
+
+
+NAME=locking_test
+
+CC=gcc
+CFLAGS= -O2 -Wall
+DEFS=
+LIBS=
+INCLUDE=
+PTHREAD_LIBS= -lpthread
+
+OS = $(shell uname -s)
+
+
+ifeq ($(OS), SunOS)
+LIBS+= -lrt
+CFLAGS+=-mv8 -Wa,-xarch=v8plus
+PTHREAD_LIBS= -lpthread
+endif
+ifeq ($(OS), FreeBSD)
+PTHREAD_LIBS= -lc_r
+endif
+
+$(NAME): $(NAME).c
+	gcc $(CFLAGS) $(DEFS) -DNO_LOCK -o $@ $< $(LIBS)
+
+
+$(NAME)_sysv: $(NAME).c
+	gcc $(CFLAGS) $(DEFS) -DSYSV_SEM -o $@ $(INCLUDE) $< $(LIBS)
+
+
+$(NAME)_flock: $(NAME).c
+	gcc $(CFLAGS) $(DEFS) -DFLOCK -o $@ $(INCLUDE) $< $(LIBS)
+
+$(NAME)_posix: $(NAME).c
+	gcc $(CFLAGS) $(DEFS) -DPOSIX_SEM -o $@ $(INCLUDE) $< $(LIBS) \
+		$(PTHREAD_LIBS) 
+
+$(NAME)_pmutex: $(NAME).c
+	gcc $(CFLAGS) $(DEFS) -DPTHREAD_MUTEX -o $@ $(INCLUDE) $< $(LIBS) \
+		$(PTHREAD_LIBS)
+
+$(NAME)_fastlock: $(NAME).c
+	gcc $(CFLAGS) $(DEFS) -DFAST_LOCK -o $@ $(INCLUDE) $< $(LIBS) 
+
+$(NAME)_futex: $(NAME).c
+	gcc $(CFLAGS) $(DEFS) -DFUTEX -o $@ $(INCLUDE) $< $(LIBS) 
+
+all: $(NAME) $(NAME)_sysv  $(NAME)_posix $(NAME)_pmutex \
+		$(NAME)_fastlock
+
+ifneq ($(OS), SunOS)
+
+all: $(NAME)_flock
+
+endif
+
+clean:
+	- at rm $(NAME) $(NAME)_sysv $(NAME)_flock $(NAME)_posix \
+		$(NAME)_pmutex $(NAME)_fastlock
diff --git a/test/locking/locking_test.c b/test/locking/locking_test.c
new file mode 100644
index 0000000..549c1dc
--- /dev/null
+++ b/test/locking/locking_test.c
@@ -0,0 +1,304 @@
+/* $Id$ */
+/*
+ *
+ * Copyright (C) 2001-2003 FhG Fokus
+ *
+ * This file is part of ser, a free SIP server.
+ *
+ * ser is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * For a license to use the ser software under conditions
+ * other than those described here, or to purchase support for this
+ * software, please contact iptel.org by e-mail at the following addresses:
+ *    info at iptel.org
+ *
+ * ser is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <fcntl.h>
+
+#ifdef FLOCK
+#include <sys/file.h>
+
+static int lock_fd;
+#endif
+
+#ifdef POSIX_SEM
+#include <semaphore.h>
+
+static sem_t sem;
+#endif
+
+#ifdef PTHREAD_MUTEX
+#include <pthread.h>
+pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+#endif
+
+#ifdef FAST_LOCK
+#include "../../fastlock.h"
+fl_lock_t lock;
+#endif
+
+#ifdef FUTEX
+#define USE_FUTEX
+#include "../../futexlock.h"
+futex_lock_t lock;
+#endif
+
+#ifdef SYSV_SEM
+#include <sys/ipc.h>
+#include <sys/sem.h>
+
+
+#if (defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)) || \
+	defined(__FreeBSD__)
+	/* union semun is defined by including <sys/sem.h> */
+#else
+	/* according to X/OPEN we have to define it ourselves */
+	union semun {
+		int val;                    /* value for SETVAL */
+		struct semid_ds *buf;       /* buffer for IPC_STAT, IPC_SET */
+		unsigned short int *array;  /* array for GETALL, SETALL */
+		struct seminfo *__buf;      /* buffer for IPC_INFO */
+	};
+#endif
+
+static int semid=-1;
+
+#endif
+
+
+#ifdef NO_LOCK
+	#define LOCK()
+	#define UNLOCK()
+#elif defined SYSV_SEM
+	#define LOCK() \
+	{\
+		struct sembuf sop; \
+		sop.sem_num=0; \
+		sop.sem_op=-1; /*down*/ \
+		sop.sem_flg=0 /*SEM_UNDO*/; \
+		semop(semid, &sop, 1); \
+	}
+
+	#define UNLOCK()	\
+	{\
+		struct sembuf sop;\
+		sop.sem_num=0;\
+		sop.sem_op=1; /*up*/\
+		sop.sem_flg=0 /*SEM_UNDO*/;\
+		semop(semid, &sop, 1);\
+	}
+#elif defined FLOCK
+
+	#define LOCK() \
+		flock(lock_fd, LOCK_EX)
+	#define  UNLOCK() \
+		flock(lock_fd, LOCK_UN)
+#elif defined POSIX_SEM
+	#define LOCK() \
+		sem_wait(&sem)
+	#define UNLOCK() \
+		sem_post(&sem);
+#elif defined PTHREAD_MUTEX
+	#define LOCK() \
+		pthread_mutex_lock(&mutex)
+	#define UNLOCK() \
+		pthread_mutex_unlock(&mutex)
+#elif defined FAST_LOCK
+	#define LOCK() \
+		get_lock(&lock)
+	#define UNLOCK() \
+		release_lock(&lock)
+#elif defined FUTEX
+	#define LOCK() \
+		futex_get(&lock)
+	#define UNLOCK() \
+		futex_release(&lock)
+#endif
+
+
+
+
+static char *id="$Id$";
+static char *version="locking_test 0.1-"
+#ifdef NO_LOCK
+ "nolock"
+#elif defined SYSV_SEM
+ "sysv_sem"
+#elif defined FLOCK
+ "flock"
+#elif defined POSIX_SEM
+ "posix_sem"
+#elif defined PTHREAD_MUTEX
+ "pthread_mutex"
+#elif defined FAST_LOCK
+ "fast_lock"
+#elif defined FUTEX
+ "futex"
+#endif
+;
+
+static char* help_msg="\
+Usage: locking_test -n address [-c count] [-v]\n\
+Options:\n\
+    -c count      how many times to try lock/unlock \n\
+    -v            increase verbosity level\n\
+    -V            version number\n\
+    -h            this help message\n\
+";
+
+
+
+int main (int argc, char** argv)
+{
+	int c;
+	int r;
+	char *tmp;
+	
+	int count;
+	int verbose;
+	char *address;
+#ifdef SYSV_SEM
+	union semun su;
+#endif
+	
+	/* init */
+	count=0;
+	verbose=0;
+	address=0;
+
+
+
+	opterr=0;
+	while ((c=getopt(argc,argv, "c:vhV"))!=-1){
+		switch(c){
+			case 'v':
+				verbose++;
+				break;
+			case 'c':
+				count=strtol(optarg, &tmp, 10);
+				if ((tmp==0)||(*tmp)){
+					fprintf(stderr, "bad count: -c %s\n", optarg);
+					goto error;
+				}
+				break;
+			case 'V':
+				printf("version: %s\n", version);
+				printf("%s\n",id);
+				exit(0);
+				break;
+			case 'h':
+				printf("version: %s\n", version);
+				printf("%s", help_msg);
+				exit(0);
+				break;
+			case '?':
+				if (isprint(optopt))
+					fprintf(stderr, "Unknown option `-%c�\n", optopt);
+				else
+					fprintf(stderr, "Unknown character `\\x%x�\n", optopt);
+				goto error;
+			case ':':
+				fprintf(stderr, "Option `-%c� requires an argument.\n",
+						optopt);
+				goto error;
+				break;
+			default:
+					abort();
+		}
+	}
+
+	
+	/* check if all the required params are present */
+	if(count==0){
+		fprintf(stderr, "Missing count (-c number)\n");
+		exit(-1);
+	}else if(count<0){
+		fprintf(stderr, "Invalid count (-c %d)\n", count);
+		exit(-1);
+	}
+
+
+#ifdef SYSV_SEM
+	/*init*/
+	puts("Initializing SYS V semaphores\n");
+	semid=semget(IPC_PRIVATE,1,0700);
+	if(semid==-1){
+		fprintf(stderr, "ERROR: could not init semaphore: %s\n",
+				strerror(errno));
+		goto error;
+	}
+	/*set init value to 1 (mutex)*/
+	su.val=1;
+	if (semctl(semid, 0, SETVAL, su)==-1){
+		fprintf(stderr, "ERROR: could not set initial semaphore value: %s\n",
+				strerror(errno));
+		semctl(semid, 0, IPC_RMID, (union semun)0);
+		goto error;
+	}
+#elif defined FLOCK
+	puts("Initializing flock\n");
+	lock_fd=open("/dev/zero", O_RDONLY);
+	if (lock_fd==-1){
+		fprintf(stderr, "ERROR: could not open file: %s\n", strerror(errno));
+		goto error;
+	}
+#elif defined POSIX_SEM
+	puts("Initializing semaphores\n");
+	if (sem_init(&sem, 0, 1)<0){
+		fprintf(stderr, "ERROR: could not initialize semaphore: %s\n",
+				strerror(errno));
+		goto error;
+	}
+#elif defined PTHREAD_MUTEX
+	puts("Initializing mutex -already initialized (statically)\n");
+	/*pthread_mutext_init(&mutex, 0 );*/
+#elif defined FAST_LOCK
+	puts("Initializing fast lock\n");
+	init_lock(lock);
+#elif defined FUTEX
+	puts("Initializing futex lock\n");
+	futex_init(&lock);
+#endif
+
+
+	/*  loop */
+	for (r=0; r<count; r++){
+		LOCK();
+		if ((verbose>1)&&(r%1000))  putchar('.');
+		UNLOCK();
+	}
+
+	printf("%d loops\n", count);
+
+#ifdef SYSV_SEM
+	semctl(semid, 0, IPC_RMID, (union semun)0);
+#elif defined LIN_SEM
+	sem_destroy(&sem);
+#endif
+
+	exit(0);
+
+error:
+	exit(-1);
+}
diff --git a/test/locking/test_results.txt b/test/locking/test_results.txt
new file mode 100644
index 0000000..2b9f257
--- /dev/null
+++ b/test/locking/test_results.txt
@@ -0,0 +1,40 @@
+
+
+			nolock		flock		sysv		posix		pmutex		fastl
+
+Linux 2* Athlon 1200, 2.4.16:
+real		0.044/		 14.713		  9.330		  2.670		  1.730		 0.400
+user		0.040		  2.610		  2.950		  2.670		  1.720		 0.400
+sys			0.000		 12.110		  6.370		  0.000		  0.010		 0.000
+*			1			334.386		212.045		 60.681		 39.318		 9.090
+
+Linux 2*PIII, 2.4.17:
+real		0.056		 17.771		 14.476		  3.099		  1.902		 0.603
+user		0.050		  4.130		  5.120		  3.100		  1.900		 0.600
+sys			0.000		 13.650		  9.350		  0.000		  0.000		 0.000
+*			1			317.339		258.500		 55.339		 33.964		10.767
+
+Solaris 8:
+real		0.105		n/a			 48.490		 27.492		  3.602		 1.284
+user		0.090		n/a			 29.330		 27.410		  3.590		 1.270
+sys			0.010		n/a			 19.110		 0.010		  0.010		 0.020
+*			1			n/a			461.809		257.142		 34.304		12.228
+
+FreeBSD, PII 333:
+real:		0.147		 43.952		  54.428	 37.385		 15.706		 1.863
+user:		0.121		 12.761		  13.131	 31.958		 13.402		 1.606
+sys:		0.001		 25.149		  33.732	  0.017		  0.017		 0.001
+*			1  			299.061		 370.258	254.319		106.843		12.673
+
+
+nolock= no locking, just a loop
+flock= using flock
+sysv = using SYSV semaphores
+posix = using POSIX1003.1b semaphores (sem_wait, sem_post)
+pmutex = using pthread_mutex*
+fastl = using fastlock.h from ser (hand made assembler locks)
+
+Test: time ./locking_test* -c 10000000
+(sip_router/test/locking/*)
+
+
diff --git a/test/long.sip b/test/long.sip
new file mode 100644
index 0000000..250cf80
--- /dev/null
+++ b/test/long.sip
@@ -0,0 +1,66 @@
+INVITE sip:jiri at bat.iptel.org SIP/2.0
+Max-Forwards: 10
+Via: SIP/2.0/UDP 195.37.77.100;branch=4848eaf6f622ebaf1762f34e5d08ec2e.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=4848eaf6f622ebaf1762f34e5d08ec2e.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=4848eaf6f622ebaf1762f34e5d08ec2e.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=4848eaf6f622ebaf1762f34e5d08ec2e.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=4848eaf6f622ebaf1762f34e5d08ec2e.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=4848eaf6f622ebaf1762f34e5d08ec2e.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=4848eaf6f622ebaf1762f34e5d08ec2e.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=1848eaf6f622ebaf1762f34e5d08ec2e.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=2848eaf6f622ebaf1762f34e5d08ec2e.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=3848eaf6f622ebaf1762f34e5d08ec2e.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=4848eaf6f622ebaf1762f34e5d08ec2e.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=8848eaf6f622ebaf1762f34e5d08ec2e.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=9848eaf6f622ebaf1762f34e5d08ec2e.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=5848eaf6f622ebaf1762f34e5d08ec2e.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=6848eaf6f622ebaf1762f34e5d08ec2e.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=7848eaf6f622ebaf1762f34e5d08ec2e.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=b03d645a795fe2572631dbe15438fabd.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=59c7c421d731de1ce1e1e4c6e83150f2.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=3b33b0d029964ec5330922ff50b34c79.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=781aa36a12b7b99b2316a8ed32123fc9.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=a93680d322702022416a5a661aaf573d.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=5a94858405aeaae679632efed7e1ff0b.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=70509dba8d202a0116d2e51cd474a1d4.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=7056d40a2cfa30ff299705fc791f4303.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=ac7cf460ba831233121eead26af76d5a.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=2c4d2ac0b10115c704d28c2b360bcb6f.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=e0282bc88aed37191911cbb5ded27379.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=c7d6a97d4b6762877410653db5643775.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=a0c4944760b9f9693209f719e7aa177c.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=4147b5297bc5a8e0c3ec58fe6fd9bf6c.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=557cfe12fa9372a0a309ffebcdef3110.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=ce741cd8b427d1722d4f746922a9d3a2.836.0
+Via: SIP/2.0/UDP 195.37.77.101;branch=838cccacb7d33e12c5e097f9090adfe1.836.0
+Via: SIP/2.0/UDP 213.20.128.35:9315
+From: "jiri" <sip:jiri at iptel.org>;tag=76ff7a07-c091-4192-84a0-d56e91fe104f
+To: <sip:jiri at bat.iptel.org>
+Call-ID: d10815e0-bf17-4afa-8412-d9130a793d96 at 213.20.128.35
+CSeq: 2 INVITE
+Contact: <sip:213.20.128.35:9315>
+User-Agent: Windows RTC/1.0
+Proxy-Authorization: Digest username="jiri", realm="iptel.org", algorithm="MD5", uri="sip:jiri at bat.iptel.org", nonce="3cef753900000001771328f5ae1b8b7f0d742da1feb5753c", response="53fe98db10e1074b03b3e06438bda70f"
+Content-Type: application/sdp
+Content-Length: 451
+
+v=0
+o=jku2 0 0 IN IP4 213.20.128.35
+s=session
+c=IN IP4 213.20.128.35
+b=CT:1000
+t=0 0
+m=audio 54742 RTP/AVP 97 111 112 6 0 8 4 5 3 101
+a=rtpmap:97 red/8000
+a=rtpmap:111 SIREN/16000
+a=fmtp:111 bitrate=16000
+a=rtpmap:112 G7221/16000
+a=fmtp:112 bitrate=24000
+a=rtpmap:6 DVI4/16000
+a=rtpmap:0 PCMU/8000
+a=rtpmap:8 PCMA/8000
+a=rtpmap:4 G723/8000
+a=rtpmap:5 DVI4/8000
+a=rtpmap: 3 GSM/8000
+a=rtpmap:101 telephone-event/8000
+a=fmtp:101 0-16
diff --git a/test/message.sip b/test/message.sip
new file mode 100644
index 0000000..2708b58
--- /dev/null
+++ b/test/message.sip
@@ -0,0 +1,11 @@
+MESSAGE sip:01756843 at sms.iptel.org SIP/2.0
+Via: SIP/2.0/UDP fesarius.fokus.gmd.de:5000
+From: "bogdan" <sip:bogdan at iptel.org>;tag=0e99b1e7-ff50-4875-94ef-4ca5c27e2705
+To: sip:cucu at sms.iptel.org;cucu=bau;tag=xyz
+Call-ID: 02b1191c-447e-4bd0-b771-c039fc0d9d84 at 195.37.78.169
+CSeq: 7 MESSAGE
+Contact: <sip:195.37.78.169:11457>
+User-Agent: Windows RTC/1.0
+Content-Type: text/plain
+Content-Length: 4
+
diff --git a/test/message02.sip b/test/message02.sip
new file mode 100644
index 0000000..512806b
--- /dev/null
+++ b/test/message02.sip
@@ -0,0 +1,10 @@
+MESSAGE sip:756843 at iptel.org SIP/2.0
+Via: SIP/2.0/UDP bat.iptel.org:9
+From: "bogdan" <sip:bogdan at iptel.org>;tag=0e99b1e7-ff50-4875-94ef-4ca5c27e2705
+xCall-ID: 02b1191c-447e-4bd0-b771-c039fc0d9d84 at 195.37.78.169
+CSeq: 7 MESSAGE
+Contact: <sip:195.37.78.169:11457>
+User-Agent: Windows RTC/1.0
+text/plain
+Content-Length: 4
+
diff --git a/test/message03.sip b/test/message03.sip
new file mode 100644
index 0000000..ae8255f
--- /dev/null
+++ b/test/message03.sip
@@ -0,0 +1,14 @@
+MESSAGE sip:+49160567535 at fesarius.fokus.gmd.de SIP/2.0
+Via: SIP/2.0/UDP fesarius.fokus.gmde.de:9
+From: sip:bogdan at fesarius.fokus.gmd.de;tag=16df4fe56e8782ecaa5d53ae36fb9240
+To: sip:dcm at fesarius.fokus.gmd.de
+Call-ID: 02b1191c-447e-4bd0-b771-c039fc0d9d84 at 195.37.78.169
+CSeq: 7 MESSAGE
+Contact: <sip:195.37.78.169:11457>
+User-Agent: Windows RTC/1.0
+Content-Type: text/plain
+Content-Length: 13
+
+cucu
+bau
+miau
diff --git a/test/mips_lock.c b/test/mips_lock.c
new file mode 100644
index 0000000..af8f85a
--- /dev/null
+++ b/test/mips_lock.c
@@ -0,0 +1,97 @@
+/*
+ *
+ *  simple locking test program
+ *  (no paralles stuff)
+ * 
+ *  Compile with: gcc -D__CPU_i386 -O3 on x86 machines and
+ *                gcc -mips2 -O2 -D__CPU_mips  on mips machines.
+ *  -- andrei
+ *
+ *  
+ */
+
+#include <stdio.h>
+
+typedef volatile int fl_lock_t;
+
+
+
+int tsl(fl_lock_t* lock)
+{
+	long val;
+	
+#ifdef __CPU_mips
+	long tmp=0;
+	
+	asm volatile(
+		".set noreorder\n\t"
+		"1:  ll %1, %2   \n\t"
+		"    li %0, 1 \n\t"
+		"    sc %0, %2  \n\t"
+		"    beqz %0, 1b \n\t"
+		"    nop \n\t"
+		".set reorder\n\t"
+		: "=&r" (tmp), "=&r" (val), "=m" (*lock) 
+		: "0" (tmp), "m" (*lock) 
+		: "cc"
+	);
+#elif defined __CPU_i386
+	val=1;
+	asm volatile( 
+		" xchg %b1, %0" : "=q" (val), "=m" (*lock) : "0" (val) 
+	);
+#else
+#error "cpu type not defined, add -D__CPU_<type> when compiling"
+#endif
+	
+	return val;
+}
+
+
+
+void release_lock(fl_lock_t* lock)
+{
+#ifdef __CPU_mips
+	int tmp;
+	tmp=0;
+	asm volatile(
+		".set noreorder \n\t"
+		"    sync \n\t"
+		"    sw $0, %0 \n\t"
+		".set reorder \n\t"
+		: /*no output*/  : "m" (*lock) : "memory"
+	);
+#elif defined __CPU_i386
+	asm volatile(
+		" movb $0, (%0)" : /*no output*/ : "r"(lock): "memory"
+	); 
+#else
+#error "cpu type not defined, add -D__CPU_<type> when compiling"
+#endif
+}
+
+
+
+int main(int argc, char** argv)
+{
+	fl_lock_t lock;
+	int r;
+	
+	lock=0;
+	printf("starting locking basic tests...\n");
+	
+	r=tsl(&lock);
+	printf(" tsl should return 0                 ... %d\n", r);
+	printf("     lock should be 1 now            ... %d\n", lock);
+	r=tsl(&lock);
+	printf(" tsl should return 1                 ... %d\n", r);
+	printf("     lock should still be 1 now      ... %d\n", lock);
+	release_lock(&lock);
+	printf(" release_lock: lock should be 0 now  ... %d\n", lock);
+	printf("trying tsl once more...\n");
+	r=tsl(&lock);
+	printf(" tsl should return 0                 ... %d\n", r);
+	printf("     lock should be 1 now            ... %d\n", lock);
+	printf("\ndone.\n");
+	return 0;
+}
diff --git a/test/mobile61.cfg b/test/mobile61.cfg
new file mode 100644
index 0000000..6d9f84e
--- /dev/null
+++ b/test/mobile61.cfg
@@ -0,0 +1,23 @@
+
+
+route{
+
+	(src_ip=~'(dorian)|(ekina)|(terix)' & method=~'^inv') \
+				forward(centauri.fokus.gmd.de);
+	src_ip=~"^192\.168\.[0-9]{1,3}\.[0-9]{1,3}$"  \
+				log(1,"msg. from a private network\n"); route(1);
+	src_ip==0.0.0.0/0   log(1, " droping msg\n"); drop;
+}
+
+route[1]{
+	src_ip==192.168.46.61  log("possible loop, dropping\n"); drop;
+	(src_ip==192.168.46.0/24) log("routing with rt2\n");route(2); log("we're back\n");
+	src_ip==0.0.0.0/0 log(1, "we'll drop this one too\n"); drop;
+}
+
+route[2]{
+	(method=~'^ACK' and uri=~'.*fokus') forward("fox.iptel.org");
+	! method=~'^INV' forward(193.175.135.179); /* dorian */
+	method=~'.' log("spying...\n"); send(dorian,8000); \
+						forward("fox.iptel.org");
+}
diff --git a/test/module_compile_status.txt b/test/module_compile_status.txt
new file mode 100644
index 0000000..64262fa
--- /dev/null
+++ b/test/module_compile_status.txt
@@ -0,0 +1,74 @@
+
+
+1 linux-i386/gcc2.95
+2 linux-i386/gcc3.3
+3 linux-i386/icc
+4 freebsd_4.5-i386/gcc
+5 freebsd_5.0-i386/gcc3.2
+6 openbsd_3.1-i386/gcc
+7 netbsd_1.6-ultrasparc/gcc
+8 solaris_8.0-ultrasparc/gcc
+9 solaris_8.0-ultrasparc/sun cc 5.3
+
+W - warnings
+E - errors
+I - could not compile due to missing includes
+L - could not compile due to missing libraries
+l - locking problems
+o - ok
+
+P - possible proto problems (tcp)
+D - dead/not finished
+
+checked: 
+7 - 2003-05-06
+8 - 2003-05-09
+1-4 2003-05-23
+6 - 2003-05-23
+5 - 2003-05-26
+
+
+module_name       1  2  3  4  5  6  7  8  9
+core                 o  o  o  o  o  o  o  o
+acc               o  I  I  I  o* o* I  I  I
+auth              o  o  o  o  o  o  o  o  o
+auth_db           o  o  o  o  o  o  o  o  o
+auth_radius       o  I  I  I  I  I  I  I  I
+cpl             P o  o  o  o  o  o  o  o  o
+cpl-c           D I  I  I  I  I  I  I  I  I
+dbtext            o  o  o  o  o  o  o  o  o
+domain            o  o  o  o  o  o  o  o  o
+enum              o  o  o  o  o  o  o  o  o
+exec              o  o  o  o  o  o  o  o  o
+ext               o  o  o  o  o  o  o  o  o
+extcmd            o  o  o  o  o  o  o  o  o
+group             o  o  o  o  o  o  o  o  o
+group_radius      W  I  I  I  I  I  I  I  I
+jabber            o  o  o  o  o  o  o  W+ W
+mangler           o  o  o  o  o  o  o  o  o
+maxfwd            o  o  o  o  o  o  o  o  o
+msilo             o  o  o  o  o  o  o  o  o
+mysql             o  o  o  o  I  o  o  o  o
+nathelper         o  o  o  o  o  o  o  o  o
+pa                o  o  o  o  o  o  o  o  o
+pdt               o  o  o  o  o  o  o  o  o
+persmissions      o  o  o  o  o  o  o  o  o
+pike              o  o  o  o  o  o  o  o  o
+postgress         I  I  I  I  I  I  I  I  I
+print             o  o  o  o  o  o  o  o  o
+registrar         o  o  o  o  o  o  o  o  o
+rr                o  o  o  o  o  o  o  o  o
+sl                o  o  o  o  o  o  o  o  o
+sms               o  o  o  o  o  o  o  o  o
+snmp      D       I  I  I  I  I  I  I  I  I
+textops           o  o  o  o  o  o  o  o  o
+tm                o  o  o  o  o  o  o  o  o
+uri               o  o  o  o  o  o  o  o  o
+uri_radius        o  I  I  I  I  I  I  I  I
+usrloc            o  o  o  o  o  o  o  o  o
+vm                o  o  o  o  o  o  o  o  o
+
+
+[*] - w/o radius & mysql
+[+] - -I warning (bad cpp?)
+
diff --git a/test/ms-invite-00-rpl.sip b/test/ms-invite-00-rpl.sip
new file mode 100644
index 0000000..e2337a0
--- /dev/null
+++ b/test/ms-invite-00-rpl.sip
@@ -0,0 +1,8 @@
+SIP/2.0 180 Ringing
+From: "jiri" <sip:jiri at iptel.org>;tag=ae2c8aec-fd00-4f0c-98b9-6d40b72c950c
+To: <sip:jirim at bat.iptel.org>
+Call-ID: 83cd6524-386b-4e78-8975-ab96a0f78590 at 212.202.173.36
+CSeq: 2 OPTIONS
+Content-Length: 0
+Via: SIP/2.0/UDP 195.37.77.100;branch=902932441872fa3682b9de564b113050.e1.0
+Via: SIP/2.0/UDP pig.iptel.org
\ No newline at end of file
diff --git a/test/ms-invite-00.sip b/test/ms-invite-00.sip
new file mode 100644
index 0000000..787e277
--- /dev/null
+++ b/test/ms-invite-00.sip
@@ -0,0 +1,32 @@
+OPTIONS sip:jirim at bat.iptel.org SIP/2.0
+Max-Forwards: 10
+Via: SIP/2.0/UDP 195.37.77.100:9;branch=0e413351aee2246f9f1edac77ccd39bc.e1.0
+From: "jiri" <sip:jiri at iptel.org>;tag=ae2c8aec-fd00-4f0c-98b9-6d40b72c950c
+To: <sip:jirim at bat.iptel.org>
+Call-ID: 83cd6524-386b-4e78-8975-ab96a0f78590 at 212.202.173.36
+CSeq: 2 OPTIONS
+Contact: <sip:212.202.173.36:9310>
+User-Agent: Windows RTC/1.0
+Content-Type: application/sdp
+Content-Length: 453
+
+v=0
+o=jku2 0 0 IN IP4 212.202.173.36
+s=session
+c=IN IP4 212.202.173.36
+b=CT:1000
+t=0 0
+m=audio 16090 RTP/AVP 97 111 112 6 0 8 4 5 3 101
+a=rtpmap:97 red/8000
+a=rtpmap:111 SIREN/16000
+a=fmtp:111 bitrate=16000
+a=rtpmap:112 G7221/16000
+a=fmtp:112 bitrate=24000
+a=rtpmap:6 DVI4/16000
+a=rtpmap:0 PCMU/8000
+a=rtpmap:8 PCMA/8000
+a=rtpmap:4 G723/8000
+a=rtpmap:5 DVI4/8000
+a=rtpmap:3 GSM/8000
+a=rtpmap:101 telephone-event/8000
+a=fmtp:101 0-16
diff --git a/test/ms-invite-01-rpl.sip b/test/ms-invite-01-rpl.sip
new file mode 100644
index 0000000..c080a41
--- /dev/null
+++ b/test/ms-invite-01-rpl.sip
@@ -0,0 +1,10 @@
+SIP/2.0 180 Ringing
+From: "jiri" <sip:jiri at iptel.org>;tag=ae2c8aec-fd00-4f0c-98b9-6d40b72c950c
+To: <sip:jirim at bat.iptel.org>
+Call-ID: 83cd6524-386b-4e78-8975-ab96a0f78590 at 212.202.173.36
+CSeq: 2 OPTIONS
+Content-Length: 0
+Via: SIP/2.0/UDP 195.37.77.100;branch=902932441872fa3682b9de564b113050.e1.0
+Via: SIP/2.0/UDP pig.iptel.org
+foo: bar
+
diff --git a/test/msbye.sip b/test/msbye.sip
new file mode 100644
index 0000000..fc61251
--- /dev/null
+++ b/test/msbye.sip
@@ -0,0 +1,10 @@
+BYE sip:131.107.155.12:7210 SIP/2.0
+Via: SIP/2.0/UDP 195.37.77.100:5090;branch=z9hG4bK62b7.43cbeb64.0
+To: "qhuai" <sip:QHUAI-LAP>;tag=754bc9430a0145d09e5821109b5e171c
+From: <sip:mstest at iptel.org>;tag=00005CC80F31CECC
+CSeq: 2 BYE
+Call-ID: ef4832152f944621847e3bf729fd4c27 at 131.107.155.12
+Content-Length: 0
+User-Agent: Sip EXpress router(0.8.11pre28 (i386/linux))
+Route: <sip:mstest at 195.37.77.101;ftag=754bc9430a0145d09e5821109b5e171c;lr=on>
+
diff --git a/test/nc.cfg b/test/nc.cfg
new file mode 100644
index 0000000..4047bc3
--- /dev/null
+++ b/test/nc.cfg
@@ -0,0 +1,24 @@
+/*
+ * test along with nmr.sip
+ *
+ */
+
+listen=127.0.0.1
+port=6060
+fork=no
+log_stderror=yes
+
+loadmodule "/home/srouter/sip_router/modules/sl/sl.so"
+loadmodule "/home/srouter/sip_router/modules/textops/textops.so"
+
+
+route {
+	if (!search("^(From|f)\:.*sip\:[0-9]+@")) {
+		  log(1," From non-nummerical\n");
+          sl_send_reply("400", "entry nummerical from check failed\n");
+          break;
+    };
+    log(1," From nummerical\n");
+    sl_send_reply("200", "entry nummerical from check ok\n");
+}
+
diff --git a/test/nmr.sip b/test/nmr.sip
new file mode 100644
index 0000000..c463e6d
--- /dev/null
+++ b/test/nmr.sip
@@ -0,0 +1,30 @@
+INVITE sip:**@backup01.sipphone.com SIP/2.0
+Record-Route: <sip:**@195.37.77.101;ftag=2726874358;lr=on>
+Via: SIP/2.0/UDP 195.37.77.101;branch=z9hG4bK2e69.ceb85f87.0
+Via: SIP/2.0/UDP 192.168.0.177:5060;received=66.27.63.253;rport=10344;branch=z9hG4bK98761FBE466C4882B9A816285384E1EA
+From: 8..123 <sip:876543210123 at iptel.org>;tag=2726874358
+To: <sip:**@backup01.sipphone.com>
+Contact: <sip:876543210123 at 66.27.63.253:10344>
+Call-ID: 7937AAC5-AE9E-41BA-9918-EF0C9DD96B37 at 192.168.0.177
+CSeq: 38975 INVITE
+Proxy-Authorization: Digest username="876543210123",realm="iptel.org",nonce="3fb9dd3e335d491d6d08f57b8b1a0a0bb83443a4",response="87da01419bc07a9ba1a76d63b993ae5d",uri="sip:**@backup01.sipphone.com"
+Max-Forwards: 69
+Content-Type: application/sdp
+User-Agent: X-Lite build 1084
+Content-Length: 301
+P-hint: OUTBOUND
+P-Behind-NAT: Yes
+
+v=0
+o=876543210123 1531591932 1531591932 IN IP4 192.168.0.177
+s=X-Lite
+c=IN IP4 195.37.77.101
+t=0 0
+m=audio 35274 RTP/AVP 0 8 3 98 101
+a=rtpmap:0 pcmu/8000
+a=rtpmap:8 pcma/8000
+a=rtpmap:3 gsm/8000
+a=rtpmap:98 iLBC/8000
+a=rtpmap:101 telephone-event/8000
+a=fmtp:101 0-15
+a=direction:active
diff --git a/test/no_eom_reply.sip b/test/no_eom_reply.sip
new file mode 100644
index 0000000..8d05037
--- /dev/null
+++ b/test/no_eom_reply.sip
@@ -0,0 +1,3 @@
+SIP/2.0 183 Session Progress
+Via: SIP/2.0/UDP 195.37.77.100;branch=b7a102045e84a2d128c3e173680de665.531.0
+Via: SIP/2.0/UDP pig.iptel.org
\ No newline at end of file
diff --git a/test/p_uri.c b/test/p_uri.c
new file mode 100644
index 0000000..e59135e
--- /dev/null
+++ b/test/p_uri.c
@@ -0,0 +1,98 @@
+/** uri parser test program. */
+/* compile with:
+    gcc -Wall p_uri.c   -o p_uri -DFAST_LOCK -D__CPU_i386 */
+#include <stdio.h>
+#include <stdlib.h> /* exit() */
+#include <string.h>
+#include <stdarg.h>
+#include "../str.h"
+
+/* ser compat defs */
+#define EXTRA_DEBUG
+#include "../parser/parse_uri.c"
+#include "../dprint.c"
+
+
+int ser_error=0;
+int log_stderr=1;
+int process_no=0;
+struct process_table* pt=0;
+int phone2tel=1;
+/*volatile int dprint_crit=0; */
+int my_pid() {return 0; };
+
+struct cfg_group_core default_core_cfg = {
+	L_DBG, /*  print only msg. < L_WARN */
+	LOG_DAEMON,	/* log_facility -- see syslog(3) */
+#ifdef USE_DST_BLACKLIST
+	/* blacklist */
+	0, /* dst blacklist is disabled by default */
+	DEFAULT_BLST_TIMEOUT,
+	DEFAULT_BLST_MAX_MEM,
+#endif
+	/* resolver */
+	1,  /* dns_try_ipv6 -- on by default */
+	0,  /* dns_try_naptr -- off by default */
+	30,  /* udp transport preference (for naptr) */
+	20,  /* tcp transport preference (for naptr) */
+	10,  /* tls transport preference (for naptr) */
+	20,  /* sctp transport preference (for naptr) */
+	-1, /* dns_retr_time */
+	-1, /* dns_retr_no */
+	-1, /* dns_servers_no */
+	1,  /* dns_search_list */
+	1,  /* dns_search_fmatch */
+	0,  /* dns_reinit */
+	/* DNS cache */
+#ifdef USE_DNS_CACHE
+	1,  /* use_dns_cache -- on by default */
+	0,  /* dns_cache_flags */
+	0,  /* use_dns_failover -- off by default */
+	0,  /* dns_srv_lb -- off by default */
+	DEFAULT_DNS_NEG_CACHE_TTL, /* neg. cache ttl */
+	DEFAULT_DNS_CACHE_MIN_TTL, /* minimum ttl */
+	DEFAULT_DNS_CACHE_MAX_TTL, /* maximum ttl */
+	DEFAULT_DNS_MAX_MEM, /* dns_cache_max_mem */
+	0, /* dns_cache_del_nonexp -- delete only expired entries by default */
+#endif
+#ifdef PKG_MALLOC
+	0, /* mem_dump_pkg */
+#endif
+#ifdef SHM_MEM
+	0, /* mem_dump_shm */
+#endif
+};
+
+void	*core_cfg = &default_core_cfg;
+
+void dprint(char * format, ...)
+{
+	va_list ap;
+
+	fprintf(stderr, "%2d(%d) ", process_no, my_pid());
+	va_start(ap, format);
+	vfprintf(stderr,format,ap);
+	fflush(stderr);
+	va_end(ap);
+}
+
+
+
+int main (int argc, char** argv)
+{
+
+	int r;
+	struct sip_uri uri;
+
+	if (argc<2){
+		printf("usage:    %s  uri [, uri...]\n", argv[0]);
+		exit(1);
+	}
+	
+	for (r=1; r<argc; r++){
+		if (parse_uri(argv[r], strlen(argv[r]), &uri)<0){
+			printf("error: parsing %s\n", argv[r]);
+		}
+	}
+	return 0;
+}
diff --git a/test/parse_to_body.c b/test/parse_to_body.c
new file mode 100644
index 0000000..c8f8720
--- /dev/null
+++ b/test/parse_to_body.c
@@ -0,0 +1,112 @@
+/** to/from body parser test program. */
+/* compile with:
+    gcc -Wall parse_to_body.c -o parse_to_body -DFAST_LOCK -D__CPU_i386 */
+#include <stdio.h>
+#include <stdlib.h> /* exit() */
+#include <string.h>
+#include <stdarg.h>
+#include "../str.h"
+
+/* ser compat defs */
+#define EXTRA_DEBUG
+#include "../parser/parse_to.c"
+#include "../dprint.c"
+
+
+int ser_error=0;
+int log_stderr=1;
+int process_no=0;
+struct process_table* pt=0;
+int phone2tel=1;
+/*volatile int dprint_crit=0; */
+int my_pid() {return 0; };
+
+struct cfg_group_core default_core_cfg = {
+	L_DBG, /*  print only msg. < L_WARN */
+	LOG_DAEMON,	/* log_facility -- see syslog(3) */
+#ifdef USE_DST_BLACKLIST
+	/* blacklist */
+	0, /* dst blacklist is disabled by default */
+	DEFAULT_BLST_TIMEOUT,
+	DEFAULT_BLST_MAX_MEM,
+#endif
+	/* resolver */
+	1,  /* dns_try_ipv6 -- on by default */
+	0,  /* dns_try_naptr -- off by default */
+	30,  /* udp transport preference (for naptr) */
+	20,  /* tcp transport preference (for naptr) */
+	10,  /* tls transport preference (for naptr) */
+	20,  /* sctp transport preference (for naptr) */
+	-1, /* dns_retr_time */
+	-1, /* dns_retr_no */
+	-1, /* dns_servers_no */
+	1,  /* dns_search_list */
+	1,  /* dns_search_fmatch */
+	0,  /* dns_reinit */
+	/* DNS cache */
+#ifdef USE_DNS_CACHE
+	1,  /* use_dns_cache -- on by default */
+	0,  /* dns_cache_flags */
+	0,  /* use_dns_failover -- off by default */
+	0,  /* dns_srv_lb -- off by default */
+	DEFAULT_DNS_NEG_CACHE_TTL, /* neg. cache ttl */
+	DEFAULT_DNS_CACHE_MIN_TTL, /* minimum ttl */
+	DEFAULT_DNS_CACHE_MAX_TTL, /* maximum ttl */
+	DEFAULT_DNS_MAX_MEM, /* dns_cache_max_mem */
+	0, /* dns_cache_del_nonexp -- delete only expired entries by default */
+#endif
+#ifdef PKG_MALLOC
+	0, /* mem_dump_pkg */
+#endif
+#ifdef SHM_MEM
+	0, /* mem_dump_shm */
+#endif
+};
+
+void	*core_cfg = &default_core_cfg;
+
+void dprint(char * format, ...)
+{
+	va_list ap;
+
+	fprintf(stderr, "%2d(%d) ", process_no, my_pid());
+	va_start(ap, format);
+	vfprintf(stderr,format,ap);
+	fflush(stderr);
+	va_end(ap);
+}
+
+
+
+int main (int argc, char** argv)
+{
+
+	int r;
+	struct to_body to_b;
+	struct to_param *p;
+
+	if (argc<2){
+		printf("usage:    %s  to_body [, to_body...]\n", argv[0]);
+		exit(1);
+	}
+	
+	for (r=1; r<argc; r++){
+		/*memset(&to_b, 0, sizeof(to_b));*/
+		if (parse_to(argv[r], argv[r]+strlen(argv[r]), &to_b)==0 ||
+				to_b.error!=1){
+			printf("error: parsing %s\n", argv[r]);
+			continue;
+		}
+		printf("body:    [%.*s]\n", to_b.body.len, to_b.body.s);
+		printf("uri:     [%.*s]\n", to_b.uri.len, to_b.uri.s);
+		printf("display: [%.*s]\n", to_b.display.len, to_b.display.s);
+		printf("tag:     [%.*s]\n\n", to_b.tag_value.len, to_b.tag_value.s);
+		for (p=to_b.param_lst; p; p=p->next){
+			printf("	param type: %d\n", p->type);
+			printf("	param name: [%.*s]\n", p->name.len, p->name.s);
+			printf("	param value: [%.*s]\n\n", p->value.len, p->value.s);
+		}
+		printf("\n");
+	}
+	return 0;
+}
diff --git a/test/perf.txt b/test/perf.txt
new file mode 100644
index 0000000..5a034f6
--- /dev/null
+++ b/test/perf.txt
@@ -0,0 +1,278 @@
+#$Id$
+#
+# ser measurements
+
+date: 20.09.2002
+
+hardware: dorian 2*Athlon 1200 (ser) <=gigabit=> mobile34 2*PIII 900 (stress)
+
+version: ser 0.8.7-14-gpl (i386/Linux)
+flags: STATS:Off, USE_IPV6, NO_DEBUG, SHM_MEM, SHM_MMAP, PKG_MALLOC, F_MALLOC,
+FAST_LOCK-ADAPTIVE_WAIT ADAPTIVE_WAIT_LOOPS=1024, MAX_RECV_BUFFER_SIZE 262144,
+MAX_LISTEN 16, MAX_URI_SIZE 1024, BUF_SIZE 3040
+
+ser command: ./ser -f test/test-throughput.cfg -l 10.0.0.179 -n 1 -D 
+ser command: ./ser -f test/th-uri-fast.cfg     -l 10.0.0.179 -n 1 -D -m 256
+
+test calls: 100000 
+
+stateless:
+
+                  throttle      1 proc (cps)   2 procs (cps)   4 procs (cps) 
+ser   gcc-3.2      20            3093  2967     3267  3398       3536  3549
+                  100            4587  4669     5011  5181       4872  4985 
+                  150            4920  4836     5161  5127       5122  5134
+
+tm:
+
+ser  gcc-3.2      20             2456  2448     3158  3147       3137  3179
+                 100             2535  2535     3429  3445       3399  3365
+                 150             2537* 2542*    3448  3473       3359  3407*
+                 200             2546* 2560*    3434* 2948+      3365* 3425*
+
+(*) - retransmissions ( 500ms)
+(+) - retransmissions (2000ms)
+------------------------------------------------------------------------------
+
+
+
+date: 23.09.2002
+
+hardware: alioth UltraSparc-IIi (ser) <=fasteth=> mobile34 2*PIII 900 (stress)
+
+version: ser 0.8.7-15-tests (sparc64/SunOS)
+flags: STATS:Off, USE_IPV6, SHM_MEM, SHM_MMAP, PKG_MALLOC, F_MALLOC,
+FAST_LOCK-ADAPTIVE_WAIT ADAPTIVE_WAIT_LOOPS=1024, MAX_RECV_BUFFER_SIZE 262144,
+MAX_LISTEN 16, MAX_URI_SIZE 1024, BUF_SIZE 3040 
+
+ser command: ./ser -f test/test-throughput.cfg -l 192.168.57.33 -n 1 -D -m 256
+ser command: ./ser -f test/th-uri-fast.cfg     -l 192.168.57.33 -n 1 -D -m 256
+
+test calls: 10000 
+
+
+stateless:
+                  throttle      1 proc (cps)   2 procs (cps)   4 procs (cps) 
+ser gcc 3.0        20             666   665      672   673
+                  100             666*  658*     675*  656*
+                  200             671   660*
+
+ser gcc 3.0        20             805   807
+-DDNS_IP_HACK     100             802*  804*
+                  200             783*  775*
+
+tm:
+ser gcc 3.0        20             542   551
+-DDND_IP_HACK     100             550   553*
+                  200             523*  530*
+
+-------------------------------------------------------------------------------
+
+
+
+date: 23.09.2002
+
+hardware: balrog 4*UltraSparc-II 296 Mhz (ser) <=fasteth=> mobile34 2*PIII 900 
+(stress)
+
+version: ser 0.8.7-15-tests (sparc64/SunOS)
+flags: STATS:Off, USE_IPV6, NO_DEBUG, DNS_IP_HACK, SHM_MEM, SHM_MMAP,
+PKG_MALLOC, F_MALLOC, FAST_LOCK-ADAPTIVE_WAIT ADAPTIVE_WAIT_LOOPS=1024,
+MAX_RECV_BUFFER_SIZE 262144, MAX_LISTEN 16, MAX_URI_SIZE 1024, BUF_SIZE 3040
+
+ser command: ./ser -f test/test-throughput.cfg -l 192.168.46.35 -D -n 1 -m 256
+ser command: /ser -f test/th-uri-fast.cfg      -l 192.168.46.35    -n 4 -m 256 
+
+test calls: 10000 
+
+
+stateless:
+                  throttle      1 proc (cps)   2 procs (cps)   4 procs (cps) 
+ser gcc3.2         20             924   923      1591  1602      1624  1670
+(DNS_IP_HACK)     100             932*  906*     1486* 1420*     1517  1495
+                  200             939*  917*     1300* 1386*     1157* 1275*
+
+tm:
+                  throttle      1 proc (cps)   2 procs (cps)   4 procs (cps) 
+ser gcc3.2         20             704  725       1137  1202      1460  1575
+(DNS_IP_HACK)     100             703* 683*      1150*           1398* 1451*
+                  200             723* 723*      1207* 1277*     1176* 1369*
+
+stress:
+test calls: 1000000
+                  100          100 procs (cps)
+                                   107* - out of mem
+
+------------------------------------------------------------------------------
+
+
+
+date: 09.10.2002
+
+hardware: dorian 2*Athlon MP2000 (ser) <=gigabit=> mobile34 2*PIII 900
+
+version: udp_test_proxy (compiled w/ gcc-3.2 -O9 -march=athlon)
+
+command line: ./udp_test_proxy -l 10.0.0.179 -s 5060 -d 10.0.0.34 -p 5090 -n 2;
+              ./udp_test_proxy -l 10.0.0.179 -s 5070 -d 10.0.0.34 -p 5000 -n 2
+
+
+test calls: 100000
+                  throttle      1 proc (cps)   2 procs (cps)   4 procs (cps) 
+udp_test_proxy    20                           3984  4015
+                 100                           5140* 5104*
+                 200                           5451* 5529* 
+
+------------------------------------------------------------------------------
+
+
+
+date: 09.10.2002
+
+hardware: dorian 2*Athlon MP2000 (ser) <=gigabit=> mobile34 2*PIII 900
+
+version: ser 0.8.7-14-gpl (i386/Linux)
+flags: STATS:Off, USE_IPV6, NO_DEBUG, DNS_IP_HACK, SHM_MEM, SHM_MMAP,
+PKG_MALLOC, F_MALLOC, FAST_LOCK-ADAPTIVE_WAIT ADAPTIVE_WAIT_LOOPS=1024,
+MAX_RECV_BUFFER_SIZE 262144, MAX_LISTEN 16, MAX_URI_SIZE 1024, BUF_SIZE 3040 
+
+
+ser command: ./ser -f test/test-throughput.cfg -l 10.0.0.179 -n 2 -m 256
+ser command: ./ser -f test/th-uri-fast.cfg     -l 10.0.0.179 -n 2 -m 256
+
+test calls: 100000
+
+stateless:
+                  throttle      1 proc (cps)   2 procs (cps)   4 procs (cps) 
+ser 0.8.7-gpl     20                           3969  4013
+                 100                           5115  5023*
+                 200                           5064* 5065* 
+
+statefull(tm):
+                  throttle      1 proc (cps)   2 procs (cps)   4 procs (cps) 
+ser 0.8.7-gpl     20                           3388
+                 100                           3513+ 3509+
+                 200                           3583+ 3409+
+
+------------------------------------------------------------------------------
+
+
+
+date: 09.10.2002
+
+hardware: dorian 2*Athlon MP2000 (ser) <=gigabit=> mobile34 2*PIII 900
+
+version: ser 0.8.9 (i386/linux)
+flags: STATS:Off, USE_IPV6, NO_DEBUG, SHM_MEM, SHM_MMAP, PKG_MALLOC, F_MALLOC,
+FAST_LOCK-ADAPTIVE_WAIT ADAPTIVE_WAIT_LOOPS=1024, MAX_RECV_BUFFER_SIZE 262144,
+MAX_LISTEN 16, MAX_URI_SIZE 1024, BUF_SIZE 3040
+
+ser command: ./ser -f test/test-throughput.cfg -l 10.0.0.179 -n 2 -m 256
+ser command: ./ser -f test/th-uri-fast.cfg     -l 10.0.0.179 -n 2 -m 256
+
+test calls: 100000
+
+statefull(tm):
+                  throttle      1 proc (cps)   2 procs (cps)   4 procs (cps) 
+ser 0.8.9         20                           3420
+                 100                           3415+ 3557+
+                 200                           3401+ 3374++
++NOLOG
++HASH_POWER 10   100                           3661+
+(24kb)           200                           3606+
++HASH_POWER 12   100                           4221
+(96kb)           200                           4295
+
+                  20            3728 3787
++HASH_POWER 16   100                           4319
+(1.5Mb)          200            3788           4447  
+
++HASH_POWER 20   100                           4467+             4740+
+(24Mb)           200                           4595+             4525+
++HASH_POWER 22   100                           4627*             4636*
+(96Mb)           200                                             4664*
+
+
+new_hash2:
+
++HASH_POWER 16   20            3931            4045 4053
+                100                            4148 4618
+                200                                              4923   4931!!
++HASH_POWER 20  200                                              4853+  4987*
++HASH_POWER 22  100                                              4857*
+                200                                              4754*  4811+
+
+
+(!!) - bye retrans?
+
+------------------------------------------------------------------------------
+
+hash dist: ( min/max/diff/nonzero)
+                2^10            2^12                2^14            2^16
+new_hash   98/168/70/1023    13/60/47/4095     1/21/20/16377    1/15/14/55963
+new_hash2  96/166/70/1024    16/53/37/4096     1/21/20/16377    1/11/10/57213
+
+
+hash test results:
+
+                     gcc 2.95   gcc2.95 -O9      gcc3.2 -O9    gcc3.2 athlon
+new_hash             17.6        11.3             11.1
+new_hash2_old        16.6        12.6             10.9
+new_hash2            12           7.1              7.2         7.18
+-------------------------------------------------------------------------------
+date: 04.09.2002
+
+hardware: dorian 2*Athlon MP2000 (ser) <=gigabit=> mobile34 2*PIII 900
+
+version: ser 0.8.11 (i386/linux)
+flags: STATS:Off, USE_IPV6, USE_TCP, DISABLE_NAGLE, DNS_IP_HACK, SHM_MEM, SHM_MMAP, PKG_MALLOC, F_MALLOC, FAST_LOCK-ADAPTIVE_WAIT
+ADAPTIVE_WAIT_LOOPS=1024, MAX_RECV_BUFFER_SIZE 262144, MAX_LISTEN 16, MAX_URI_SIZE 1024, BUF_SIZE 65535
+@(#) $Id$
+main.c compiled on 14:34:25 Sep  4 2003 with gcc 3.3
+
+(standard release flags)
+
+ser command: ./ser -f test/test-throughput.cfg -l 10.0.0.179 -n 2 -m 256
+ser command: ./ser -f test/th-uri-fast.cfg     -l 10.0.0.179 -n 2 -m 256
+
+test calls: 100000
+
+stateless:
+                  throttle      1 proc (cps)   2 procs (cps)   4 procs (cps) 
+ser 0.8.11        20                           3951  3975
+                 100                           5032* 5057
+                 200                           5306  5360     5291 5321 5319
+statefull (tm):
+                  throttle      1 proc (cps)   2 procs (cps)   4 procs (cps) 
+ser 0.8.11        20                           
+                 100                                           4155 4429 4510
+                 200                                           4450 4349
+
+
+ w/ NO_DEBUG && CPU=athlon-mp CC_EXTRA_OPTIONS=-march=athlon-mp
+stateless:
+                  throttle      1 proc (cps)   2 procs (cps)   4 procs (cps) 
+ser 0.8.11        20                           
+                 100                                           5202 5224
+                 200                                           5384 5370
+statefull (tm):
+                  throttle      1 proc (cps)   2 procs (cps)   4 procs (cps) 
+ser 0.8.11        20                           
+                 100                                           4411 4549
+                 200                                           4602 4493
+statefull(tm)
+0.8.11+
+F_MALLOC_OPTIMIZE 12  100                                      4723 4660 4740
+                      200                                      4804 4879 4849
+(4857 cps, 1000000 calls, throttle=200)
+
+as above + std. cfg   100                                      4496 4453
+ (etc/ser.cfg)        200                                      4441 4445
+ (3 ifs, 5 aliases)
+
+ w/ usrloc lookups   100                                       4371 4475
+                     200                                       4381 4390
+
+(*)  - inv. retr
+(!!) - bye retrans?
+
diff --git a/test/pingtel.sip b/test/pingtel.sip
new file mode 100644
index 0000000..26e2f0b
--- /dev/null
+++ b/test/pingtel.sip
@@ -0,0 +1,15 @@
+REGISTER sip:iptel.org SIP/2.0
+Via: SIP/2.0/UDP 195.37.77.103:9
+From: sip:shawn.lipman at iptel.org;tag=7618c7618^
+To: sip:blb at iptel.org;tag=
+Call-Id: 1023638012-reg at 24.114.138.250
+Cseq: 61 REGISTER
+Contact: <sip:shawn.lipman at 24.114.138.250:5061;LINEID=bf07b2caa09525f72d4364642a0e287d>
+Expires: 3
+Authorization: Digest realm="iptel.org", nonce="3d6f6863000000005b60307d4fa699b2fa22957393754da0", uri="sip:iptel.org", response="82a055bbfe0aeec5f5f882e5a66a90eb", algorithm="MD5"
+Content-Length: 0
+Accept-Language: en
+Supported: sip-cc, sip-cc-01, timer
+User-Agent: Pingtel/2.0.0 (WinNT)
+Date: Sun, 09 Jul 2002 16:22:37 GMT
+
diff --git a/test/profile.h b/test/profile.h
new file mode 100644
index 0000000..d543191
--- /dev/null
+++ b/test/profile.h
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2007 iptelorg GmbH
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * Basic profile using the cpu cycle counter
+ *
+ * cycles_t - an unsigned interger type used for storing the cpu cycles
+ *            (unsigned long long for now)
+ *
+ * cycles_t get_cpu_cycles() - returns the current cpu cycles counter
+ *
+ * void     get_cpu_cycles_uint(unsigned* u1, unsigned* u2) 
+ *                            - sets u1 and u2 to the least significant, 
+ *                              respective most significant 32 bit word of
+ *                              the cpu cycles counter
+ * struct profile_data;            - holds all the profile results
+ *                               (last call cycles, max cycles, total cycles,
+ *                                no. of profile_start calls, no. of 
+ *                                profile_end calls, name use in profile_init)
+ * void     profile_init(pd, name) - intialize a profile structure
+ * void     profile_start(pd)      - starts profiling (call before calling
+ *                               the target function)
+ * void     profile_end(pd)        - stops profiling (call after the target
+ *                               function returns)
+ * 
+ */
+ /*
+ * Config defines:   CC_GCC_LIKE_ASM  - the compiler support gcc style
+ *                     inline asm,
+ *                  __CPU_x86, __CPU_x86_64, __CPU_sparc64
+ */
+/* 
+ * History:
+ * --------
+ *  2007-06-23  created by andrei
+ */
+
+
+
+
+#ifndef _profile_h
+#define _profile_h
+
+#include <string.h>
+
+/*
+ * cycles_t - an unsigned interger type used for storing the cpu cycles
+ *            (unsigned long long for now)
+ *
+ * cycles_t get_cpu_cycles() - returns the current cpu cycles counter
+ * void     get_cpu_cycles_uint(unsigned* u1, unsigned* u2) 
+ *                            - sets u1 and u2 to the least significant, 
+ *                              respective most significant 32 bit word of
+ *                              the cpu cycles counter
+ */
+
+#if defined __CPU_i386 && ! defined __CPU_x86
+#define __CPU_x86
+#endif
+
+#ifdef __CPU_x86
+typedef unsigned long long cycles_t;
+
+inline static cycles_t get_cpu_cycles()
+{
+	cycles_t r;
+	asm volatile( "rdtsc \n\t" : "=A"(r));
+	return r;
+}
+
+#define get_cpu_cycles_uint(u1, u2) \
+	do{ \
+		/* result in edx:eax */ \
+		asm volatile( "rdtsc \n\t" : "=a"(*(u1)), "=d"(*(u2))); \
+	}while(0)
+
+#elif defined __CPU_x86_64
+typedef unsigned long long cycles_t;
+
+inline static cycles_t get_cpu_cycles()
+{
+	unsigned int u1, u2;
+	asm volatile( "rdtsc \n\t" : "=a"(u1), "=d"(u2));
+	return ((cycles_t)u2<<32ULL)|u1;
+}
+
+
+#define get_cpu_cycles_uint(u1, u2) \
+	do{ \
+		/* result in edx:eax */ \
+		asm volatile( "rdtsc \n\t" : "=a"(*(u1)), "=d"(*(u2))); \
+	}while(0)
+
+#elif defined __CPU_sparc64
+
+typedef unsigned long long cycles_t;
+
+inline static cycles_t get_cpu_cycles()
+{
+#if ! defined(_LP64)
+#warning "ilp32 mode "
+	struct uint_64{
+		unsigned int u2;
+		unsigned int u1;
+	};
+	union{
+		cycles_t c;
+		struct uint_64 u;
+	}r;
+	
+	asm volatile("rd %%tick, %0 \n\t"
+				 "srlx %0, 32, %1 \n\t"
+				: "=r"(r.u.u1), "=r"(r.u.u2));
+	return r.c;
+#else
+	cycles_t r;
+	/* normal 64 bit mode (e.g. gcc -m64) */
+	asm volatile("rd %%tick, %0" : "=r"(r));
+	return r;
+#endif
+}
+inline static void  get_cpu_cycles_uint(unsigned int* u1, unsigned int* u2)
+{
+	cycles_t r;
+	asm volatile("rd %%tick, %0" : "=r"(r));
+	*u1=(unsigned int)r;
+	*u2=(unsigned int)(r>>32);
+}
+
+#else /* __CPU_xxx */
+#error "no get_cycles support for this CPU"
+#endif /* __CPU_xxx */
+
+
+union profile_cycles{
+	cycles_t c;
+	struct{
+		unsigned int u1;
+		unsigned int u2;
+	}uint;
+};
+
+struct profile_data{
+	cycles_t cycles;  /* last call */
+	cycles_t total_cycles;
+	cycles_t max_cycles;
+	unsigned long entries; /* no. profile_start calls */
+	unsigned long exits;   /* no. profile_end calls */
+	char * name;
+	
+	/* private stuff */
+	union profile_cycles init_rdtsc;
+};
+
+inline static void profile_init(struct profile_data* pd, char *name)
+{
+	memset(pd, 0, sizeof(*pd));
+	pd->name=name;
+}
+
+
+inline static void profile_start(struct profile_data* pd)
+{
+	pd->entries++;
+	pd->init_rdtsc.c=get_cpu_cycles();
+}
+
+
+inline static void profile_end(struct profile_data* pd)
+{
+	pd->cycles=get_cpu_cycles()-pd->init_rdtsc.c;
+	if (pd->max_cycles<pd->cycles) pd->max_cycles=pd->cycles;
+	pd->total_cycles+=pd->cycles;
+	pd->exits++;
+}
+
+
+#endif
diff --git a/test/re_test.c b/test/re_test.c
new file mode 100644
index 0000000..0c5a175
--- /dev/null
+++ b/test/re_test.c
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2001-2003 FhG Fokus
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+/*
+ * regexec test program (good to find re lib. bugs)
+ * uses the same flags as ser/textops for re-matching
+ */
+
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <regex.h>
+
+
+static char *id="$Id$";
+static char *version="re_test 0.1";
+static char* help_msg="\
+Usage: re_test [-f file] regular_expression \n\
+Options:\n\
+    -f file       file with the content of a sip packet (max 65k)\n\
+    -h            this help message\n\
+    -n            non matching list ([^...]) will match newlines\n\
+    -s            case sensitive\n\
+    -v            increase verbosity\n\
+";
+
+#define BUF_SIZE 65535
+
+
+int main (int argc, char** argv)
+{
+	int fd;
+	char c;
+	int n;
+	char* re_str;
+	char buffer[BUF_SIZE+1]; /* space for null-term. */
+	char* buf;
+	regex_t re;
+	int flags;
+	regmatch_t pmatch;
+	int match;
+	int eflags;
+	
+	int verbose;
+	char *fname;
+	
+	/* init */
+	verbose=0;
+	fname=0;
+	re_str=0;
+	flags=REG_EXTENDED|REG_ICASE|REG_NEWLINE;
+	match=0;
+	buf=buffer;
+	eflags=0;
+
+	opterr=0;
+	while ((c=getopt(argc,argv, "f:nsvhV"))!=-1){
+		switch(c){
+			case 'f':
+				fname=optarg;
+				break;
+			case 'v':
+				verbose++;
+				break;
+			case 'V':
+				printf("version: %s\n", version);
+				printf("%s\n",id);
+				exit(0);
+				break;
+			case 'h':
+				printf("version: %s\n", version);
+				printf("%s", help_msg);
+				exit(0);
+				break;
+			case 's':
+				flags&=~REG_ICASE;
+				break;
+			case 'n':
+				flags&=~REG_NEWLINE;
+				break;
+			case '?':
+				if (isprint(optopt))
+					fprintf(stderr, "Unknown option `-%c�\n", optopt);
+				else
+					fprintf(stderr, "Unknown character `\\x%x�\n", optopt);
+				goto error;
+			case ':':
+				fprintf(stderr, "Option `-%c� requires an argument.\n",
+						optopt);
+				goto error;
+				break;
+			default:
+					abort();
+		}
+	}
+	/* check if we have non-options */
+	if (optind < argc){
+		re_str=argv[optind];
+	}
+	
+	/* check if all the required params are present */
+	if (re_str==0){
+		fprintf(stderr, "ERROR: no regular expression specified\n");
+		goto error;
+	}else{
+		if (regcomp(&re, re_str, flags)){
+			fprintf(stderr, "ERROR: bad regular expression <%s>\n", re_str);
+			goto error;
+		}
+	}
+		
+	if ((fname!=0 ) &&(strcmp(fname, "-")!=0)){
+		/* open packet file */
+		fd=open(fname, O_RDONLY);
+		if (fd<0){
+			fprintf(stderr, "ERROR: loading packet-file(%s): %s\n", fname,
+					strerror(errno));
+			goto error;
+		}
+	}else fd=0;
+	n=read(fd, buf, BUF_SIZE);
+	if (n<0){
+		fprintf(stderr, "ERROR: reading file(%s): %s\n", fname,
+				strerror(errno));
+		goto error;
+	}
+	buf[n]=0; /* null terminate it */
+	if (verbose) printf("read %d bytes from file %s\n", n, fname);
+	if (fd!=0) close(fd); /* we don't want to close stdin */
+	
+	while (regexec(&re, buf, 1, &pmatch, eflags)==0){
+		eflags|=REG_NOTBOL;
+		match++;
+		if (pmatch.rm_so==-1){
+			fprintf(stderr, "ERROR: unknown match offset\n");
+			goto error;
+		}else{
+			if (verbose){
+				printf("%4d -%4d: ", (int)pmatch.rm_so+buf-buffer,
+						(int)pmatch.rm_eo+buf-buffer);
+			}
+			printf("%.*s\n", (int)(pmatch.rm_eo-pmatch.rm_so),
+								buf+pmatch.rm_so);
+		}
+		buf+=pmatch.rm_eo;
+	}
+	if (verbose) printf("\n%d matches\n", match);
+	if (match) exit(0);
+	else exit(1);
+	
+error:
+	exit(-1);
+}
diff --git a/test/register.sip b/test/register.sip
new file mode 100644
index 0000000..26be195
--- /dev/null
+++ b/test/register.sip
@@ -0,0 +1,11 @@
+REGISTER sip:voip.net:5060 SIP/2.0
+From: "Jan Janak" <sip:janakj at dhcp246.fokus.gmd.de>
+To: "Jan_Janak" <sip:janakj at dhcp246.fokus.gmd.de>
+Call-ID: aa at 195.37.78.208
+User-Agent: snom100_1.9b
+CSeq: 2 REGISTER
+Via: SIP/2.0/UDP 195.37.78.177:5060
+Contact: <sip:janakj at sdfd.df>
+Content-Length: 0
+
+
diff --git a/test/register02.sip b/test/register02.sip
new file mode 100644
index 0000000..08f08fa
--- /dev/null
+++ b/test/register02.sip
@@ -0,0 +1,12 @@
+REGISTER sip:iptel.org:5060 SIP/2.0
+Via: SIP/2.0/UDP 195.37.77.181:9
+From: "Jan Janak" <sip:blb at iptel.org>
+To: "Jan_Janak" <sip:blb at iptel.org>
+Call-ID: aa at 195.37.78.208
+User-Agent: snom100_1.9b
+CSeq: 2 REGISTER
+Expires: 0
+Contact: <sip:janakj at sdfd.df>;expires=2
+Content-Length: 0
+
+
diff --git a/test/register03.sip b/test/register03.sip
new file mode 100644
index 0000000..1cd00d0
--- /dev/null
+++ b/test/register03.sip
@@ -0,0 +1,11 @@
+REGISTER sip:iptel.org:5060 SIP/2.0
+To: <sip:jiri at iptel.org>
+From: <sip:jiri at iptel.org>
+Call-ID: 7138115741688223740 at 195.37.78.226
+CSeq: 4 REGISTER
+Via: SIP/2.0/UDP bat.iptel.org:5060
+User-Agent:  UbiquityUserAgent/4
+Expires: 0
+Content-Length: 0
+
+
diff --git a/test/register04.sip b/test/register04.sip
new file mode 100644
index 0000000..9471826
--- /dev/null
+++ b/test/register04.sip
@@ -0,0 +1,11 @@
+REGISTER sip:iptel.org:5060 SIP/2.0
+To:poo <bear at iptel.org>
+From: <sip:jiri at iptel.org>
+Call-ID: 7138115741688223740 at 195.37.78.226
+CSeq: 4 REGISTER
+Via: SIP/2.0/UDP bat.iptel.org:5060
+User-Agent:  UbiquityUserAgent/4
+Expires: 0
+Content-Length: 0
+
+
diff --git a/test/repl1.sip b/test/repl1.sip
new file mode 100644
index 0000000..7b82c4f
--- /dev/null
+++ b/test/repl1.sip
@@ -0,0 +1,10 @@
+SIP/2.0 200 Ok
+Via: SIP/2.0/UDP foo.bar.com
+Via: SIP/2.0/UDP mobile55
+From: <sip:x at foo.bar>
+To: <sip:y at bar.foo>
+Call-ID:9437892232b at foo.bar
+CSeq: 143 INVITE
+Contact: <sip:x at foo.bar>
+
+
diff --git a/test/req-test1.sip b/test/req-test1.sip
new file mode 100644
index 0000000..824cbe3
--- /dev/null
+++ b/test/req-test1.sip
@@ -0,0 +1,10 @@
+INVITE sip:foo at 127.0.0.1:5061  SIP/2.0
+Via: SIP/2.0/UDP 127.0.0.1
+Via: SIP/2.0/UDP 127.0.0.1:5061
+From:  <sip:x at foo.bar>
+To: <sip:y at bar.foo>
+Call-ID: 9437892232b at foo.bar
+CSeq: 143 INVITE
+Contact:<sip:x at foo.bar>
+
+
diff --git a/test/req-tm1.sip b/test/req-tm1.sip
new file mode 100644
index 0000000..e461078
--- /dev/null
+++ b/test/req-tm1.sip
@@ -0,0 +1,9 @@
+INVITE sip:foo at 127.0.0.1:5061  SIP/2.0
+Via: SIP/2.0/UDP 127.0.0.1:5062
+From:  <sip:x at foo.bar>
+To: <sip:y at bar.foo>
+Call-ID: 9437892232b at foo.bar
+CSeq: 143 INVITE
+Contact:<sip:x at foo.bar>
+
+
diff --git a/test/req1.sip b/test/req1.sip
new file mode 100644
index 0000000..c92085c
--- /dev/null
+++ b/test/req1.sip
@@ -0,0 +1,5 @@
+INVITE sip:andrei at localhost:5061;a=b?c=d SIP/2.0
+Via: SIP/2.0/UDP localhost
+
+
+
diff --git a/test/req2.sip b/test/req2.sip
new file mode 100644
index 0000000..328e869
--- /dev/null
+++ b/test/req2.sip
@@ -0,0 +1,5 @@
+INVITE sip:andrei at localhost:5061;a=b?c=d SIP/2.0
+Via: SIP/2.0/UDP localhost, SIP/2.0/UDP 127.0.0.1:5061
+
+
+
diff --git a/test/resolver.txt b/test/resolver.txt
new file mode 100644
index 0000000..2d95abe
--- /dev/null
+++ b/test/resolver.txt
@@ -0,0 +1,84 @@
+
+
+
+				 Linux		FreeBSD		Solaris		Cygwin
+gethostbyname		y			y			y			y
+gethostbyname_r		n			n			y			-
+gethostbyname2		y			y			y(*)		-
+getaddrinfo			y			y			y			-
+res_search (res_*)	y			y			y			-
+
+Linux, Solaris, Cygwin:
+
+struct sockaddr_in{
+	sa_family_t     sin_family;
+	in_port_t       sin_port;
+	struct  in_addr sin_addr;
+	/* ...*/
+}; 
+
+FreeBSD:
+struct sockaddr_in {
+        u_char  sin_len;
+        u_char  sin_family;
+        u_short sin_port;
+        struct  in_addr sin_addr;
+        char    sin_zero[8];
+};
+
+
+Linux, Solaris, Cygwin:
+struct sockaddr_in6 {
+        sa_family_t     sin6_family;
+        in_port_t       sin6_port;
+        uint32_t        sin6_flowinfo;
+        struct in6_addr sin6_addr;
+		/*...*/
+};
+
+
+FreeBSD:
+struct sockaddr_in6 {
+        u_int8_t        sin6_len;       /* length of this struct(sa_family_t)*/
+        u_int8_t        sin6_family;    /* AF_INET6 (sa_family_t) */
+        u_int16_t       sin6_port;      /* Transport layer port # (in_port_t)*/
+        u_int32_t       sin6_flowinfo;  /* IP6 flow information */
+        struct in6_addr sin6_addr;      /* IP6 address */
+        u_int32_t       sin6_scope_id;  /* intface scope id */
+};
+
+
+
+				sockaddr_in					sockaddr_in6
+Linux	<netinet/in.h> or <linux/in.h>	<netinet/in.h> or <linux/in6.h> (*)
+FreeBSD			<netinet/in.h>				<netinet6/in6.h>
+Solaris			<netinet/in.h>				<netinet/in.h>
+Cygwin	<netinet/in.h> or <cywin/in.h>	<netinet/in.h> or <cygwin/in.h>
+
+(*) - on linux netinet/in.h -> from GNU libc, linux/in*.h from the kernel.
+
+
+
+
+struct sockaddr:
+
+Linux:
+(sa_family_t= unsigned short)
+
+struct sockaddr {
+        sa_family_t     sa_family;      /* address family, AF_xxx       */
+        char            sa_data[14];    /* 14 bytes of protocol address */
+};
+
+
+
+FreeBSD:
+
+(sa_family_t = u_char)
+
+struct sockaddr {
+        u_char          sa_len;         /* total length */
+        sa_family_t     sa_family;      /* address family */
+        char            sa_data[14];    /* actually longer; address value */
+};
+
diff --git a/test/resolver_test.c b/test/resolver_test.c
new file mode 100644
index 0000000..a824aa5
--- /dev/null
+++ b/test/resolver_test.c
@@ -0,0 +1,147 @@
+/*
+ *
+ * Copyright (C) 2001-2003 FhG Fokus
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <ctype.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+
+static char *id="$Id$";
+static char *version="resolver_test 0.1";
+static char* help_msg="\
+Usage: resolver -n address [-c count] [-v]\n\
+Options:\n\
+    -n address    address to be resolved\n\
+    -c count      how many times to resolve it\n\
+    -v            increase verbosity level\n\
+    -V            version number\n\
+    -h            this help message\n\
+";
+
+
+
+int main (int argc, char** argv)
+{
+	char c;
+	struct hostent* he;
+	int ok;
+	int errors;
+	int r;
+	char *tmp;
+	
+	int count;
+	int verbose;
+	char *address;
+	
+	/* init */
+	count=0;
+	verbose=0;
+	address=0;
+
+	ok=errors=0;
+
+	opterr=0;
+	while ((c=getopt(argc,argv, "n:c:vhV"))!=-1){
+		switch(c){
+			case 'n':
+				address=optarg;
+				break;
+			case 'v':
+				verbose++;
+				break;
+			case 'c':
+				count=strtol(optarg, &tmp, 10);
+				if ((tmp==0)||(*tmp)){
+					fprintf(stderr, "bad count: -c %s\n", optarg);
+					goto error;
+				}
+				break;
+			case 'V':
+				printf("version: %s\n", version);
+				printf("%s\n",id);
+				exit(0);
+				break;
+			case 'h':
+				printf("version: %s\n", version);
+				printf("%s", help_msg);
+				exit(0);
+				break;
+			case '?':
+				if (isprint(optopt))
+					fprintf(stderr, "Unknown option `-%c�\n", optopt);
+				else
+					fprintf(stderr, "Unknown character `\\x%x�\n", optopt);
+				goto error;
+			case ':':
+				fprintf(stderr, "Option `-%c� requires an argument.\n",
+						optopt);
+				goto error;
+				break;
+			default:
+					abort();
+		}
+	}
+	
+	/* check if all the required params are present */
+	if (address==0){
+		fprintf(stderr, "Missing -a address\n");
+		exit(-1);
+	}
+	if(count==0){
+		fprintf(stderr, "Missing count (-c number)\n");
+		exit(-1);
+	}else if(count<0){
+		fprintf(stderr, "Invalid count (-c %d)\n", count);
+		exit(-1);
+	}
+	
+
+
+	/* flood loop */
+	for (r=0; r<count; r++){
+		if ((verbose>1)&&(r%1000))  putchar('.');
+		/* resolve destination loop */
+		he=gethostbyname(address);
+		if (he==0){
+			errors++;
+			if (verbose>1) 
+				putchar('?');
+		}else ok++;
+	}
+
+	printf("\n%d requests, %d succeeded, %d errors\n", count, ok, errors);
+
+	exit(0);
+
+error:
+	exit(-1);
+}
diff --git a/test/route.sip b/test/route.sip
new file mode 100644
index 0000000..1cb4646
--- /dev/null
+++ b/test/route.sip
@@ -0,0 +1,25 @@
+INVITE sip:janakj at megalith.sh.cvut.cz SIP/2.0
+Via: SIP/2.0/UDP 147.32.119.187:5040
+From: "Jan Janak" <sip:janakj at megalith.sh.cvut.cz>;tag=b96b0300ed30f1286-2f5d
+To: <sip:janakj2 at megalith.sh.cvut.cz>
+Call-ID: b96b0300-88d30f-66da-63aa at 195.37.78.190
+CSeq: 101 INVITE
+Expires: 180
+Route: <sip:aa at mail.ok2rab.nextra.cz:5061>,
+       <sip:bb at mail.ok2rab.nextra.cz:5062>
+User-Agent: Cisco-SIP-IP-Phone/2
+Accept: application/sdp
+Contact: sip:jiri at 195.37.78.190:5060
+Content-Type: application/sdp
+Content-Length: 225
+
+
+v=0
+o=CiscoSystemsSIP-IPPhone-UserAgent 14474 8233 IN IP4 195.37.78.190
+s=SIP Call
+c=IN IP4 195.37.78.190
+t=0 0
+m=audio 18456 RTP/AVP 0 8 18 101
+a=rtpmap:0 pcmu/8000
+a=rtpmap:101 telephone-event/8000
+a=fmtp:101 0-11 
diff --git a/test/rport.sip b/test/rport.sip
new file mode 100644
index 0000000..17b1882
--- /dev/null
+++ b/test/rport.sip
@@ -0,0 +1,10 @@
+MESSAGE sip:756843 at iptel.org SIP/2.0
+Via: SIP/2.0/UDP bat.iptel.org:9;rport=
+From: "bogdan" <sip:bogdan at iptel.org>;tag=0e99b1e7-ff50-4875-94ef-4ca5c27e2705
+xCall-ID: 02b1191c-447e-4bd0-b771-c039fc0d9d84 at 195.37.78.169
+CSeq: 7 MESSAGE
+Contact: <sip:195.37.78.169:11457>
+User-Agent: Windows RTC/1.0
+text/plain
+Content-Length: 4
+
diff --git a/test/ser.cfg b/test/ser.cfg
new file mode 100644
index 0000000..db7f415
--- /dev/null
+++ b/test/ser.cfg
@@ -0,0 +1,56 @@
+debug=9          # debug level (cmd line: -dddddddddd)
+check_via=1      # (cmd. line: -v)
+dns=on           # (cmd. line: -r)
+rev_dns=yes      # (cmd. line: -R)
+fork=no          # (cmd. line: -D)
+fork=yes
+log_stderror=yes # (cmd line: -E)
+fifo=/tmp/ser_fifo
+# for more info: sip_router -h
+
+
+route{
+
+	if false and forward("mobile69") { log("forwarded ok\n"); break; }
+	else log("error forwarding\n");
+	
+	if false log("if\n")
+	else log("else\n");
+	
+	if { log("test\n"); break; log("test2\n"); } log ("if {}");
+	
+	if (src_ip=~'(dorian)|(ekina)|(terix)' & method=~'^inv')
+				forward(centauri.fokus.gmd.de);
+	if src_ip=~"^192\.168\.[0-9]{1,3}\.[0-9]{1,3}$" {
+			log(1,"msg. from a private network\n");
+			route(1);
+			log(1, "after route(1)\n");
+			break;
+	};
+	if src_ip==0.0.0.0/0 {
+		setuserpass("andrei:test");
+		log(1, " test msg\n"); forward(192.168.46.55);
+		setuser("foo");sethostport("bar.com:6000");
+		forward(192.168.46.69);drop;
+	};
+	log("default route[0]\n");
+}
+
+route[1]{
+	if src_ip==192.168.46.61 { log("possible loop, dropping\n"); drop; };
+	if (src_ip==192.168.46.0/24) { 
+			log("routing with rt2\n");route(2); log("we're back\n");
+			break;
+	};
+	if src_ip==0.0.0.0/0 { log(1, "we'll drop this one too\n"); drop; };
+	log("default route[1]\n");
+}
+
+route[2]{
+	if (method=~'^ACK' and uri=~'.*fokus') forward("fox.iptel.org");
+	if ! method=~'^INV' forward(193.175.135.179); /* dorian */
+	if method=~'.' { log("spying...\n"); send(dorian,8000);/* raw sip packet */
+						forward("fox.iptel.org");
+					};
+	log("default route[2]\n");
+}
diff --git a/test/sf.cfg b/test/sf.cfg
new file mode 100644
index 0000000..61c3bb2
--- /dev/null
+++ b/test/sf.cfg
@@ -0,0 +1,127 @@
+#
+# iptel.org real world configuration
+#
+
+# ----------- global configuration parameters ------------------------
+
+#debug=8          # debug level (cmd line: -dddddddddd)
+debug=3
+fork=no
+children=2
+#log_stderror=no	# (cmd line: -E)
+log_stderror=yes	# (cmd line: -E)
+check_via=yes     # (cmd. line: -v)
+dns=no           # (cmd. line: -r)
+rev_dns=no	# (cmd. line: -R)
+port=5060
+#port=8060
+
+fifo="/tmp/ser_fifo"
+
+# advertise IP address in Via (as opposed to advertising DNS name
+# which is annoying for downstream servers and some phones can
+# not handle DNS at all)
+#listen=195.37.77.100
+#listen=127.0.0.1
+
+# ------------------ module loading ----------------------------------
+
+loadmodule "../sip_router/modules/sl/sl.so"
+loadmodule "../sip_router/modules/print/print.so"
+loadmodule "../sip_router/modules/tm/tm.so"
+loadmodule "../sip_router/modules/acc/acc.so"
+loadmodule "../sip_router/modules/rr/rr.so"
+loadmodule "../sip_router/modules/maxfwd/maxfwd.so"
+loadmodule "../sip_router/modules/usrloc/usrloc.so"
+loadmodule "../sip_router/modules/registrar/registrar.so"
+
+# ----------------- setting module-specific parameters ---------------
+
+# -- usrloc params --
+
+
+# -- acc params --
+# report ACKs too for sake of completeness -- as we account PSTN
+# destinations which are RR, ACKs should show up
+modparam("acc", "report_ack", 1)
+# don't bother me with early media reports (I don't like 183 
+# too much anyway...ever thought of timer C hitting after
+# listening to music-on-hold for five minutes?)
+modparam("acc", "early_media", 0)
+modparam("acc", "log_level", 1)
+# that is the flag for which we will account -- don't forget to
+# set the same one :-)
+modparam("acc", "acc_flag", 3 )
+# we are interested only in succesful transactions
+modparam("acc", "failed_transactions", 0 )
+modparam("acc", "missed_flag", 2 )
+
+# -- tm params --
+modparam("tm", "fr_timer", 103 )
+modparam("tm", "retr_timer1p1", 4 )
+modparam("tm", "fr_inv_timer", 4 )
+modparam("tm", "wt_timer", 8 )
+modparam("tm", "noisy_ctimer", 0 )
+
+# -------------------------  request routing logic -------------------
+
+# main routing logic
+
+route{
+	# for testing purposes, simply okay all REGISTERs
+	if (method=="REGISTER") {
+		log("REGISTER");
+		sl_send_reply("200", "ok");
+		#t_replicate("localhost", "9");
+		break;
+	};
+
+	if (!t_relay_to("fox.iptel.org", "12345" )) {
+		sl_reply_error();
+	};
+	/* t_reply("100", "trying"); */
+	break;
+
+	#rewritehost("iptel.org");
+	if (!t_relay()) {
+		sl_reply_error();
+	};
+	break;
+
+	# print a message if a call was missed
+	setflag(2);
+
+	rewriteuri("a at blb.com");
+	append_branch("b at blb.com");
+	append_branch("c at blb.com");
+
+#	forward( "fox.iptel.org", 9 );
+	t_relay_to("bat.iptel.org", "5088");
+#	t_relay();
+}
+
+route[3] {
+	lookup("location");
+}
+
+reply_route[1] {
+	# revert to original inbound uri -- good if we want
+	# to modify it; if we rewrite it completely as in the 
+	# line after it, it is actually useless
+	revert_uri();
+	# this one will return 404 too
+	rewriteuri("sip:nonsense at iptel.org");
+	append_branch();
+	# and if we don't yet get a positive reply (we won't --
+	# we will receive 404", try another forking destination
+	t_on_negative("2");
+}
+
+reply_route[2] {
+	revert_uri();
+	rewriteuri("sip:foo at iptel.org");
+	# give it one more try; if it fails too (it will, there
+	# is no foo), a lowest-code message will be relayed
+	# upstream
+	append_branch();
+}
diff --git a/test/sg.sip b/test/sg.sip
new file mode 100644
index 0000000..c5b430d
--- /dev/null
+++ b/test/sg.sip
@@ -0,0 +1,18 @@
+INVITE sip:theCallee at iptel.org SIP/2.0
+Via: SIP/2.0/UDP sipproxy.icr.a-star.edu.sg:5060;branch=QdqKUsYZOGRR+j*P
+Via: SIP/2.0/UDP 137.132.31.151:58072;branch=NTg2NTIwNzUw
+Max-Forwards: 68
+From: sip:Acaller at icr.a-star.edu.sg:6060;tag=MTU3MT

+To: sip:theCallee at iptel.org

+Call-ID: 1953014-jQ4MzYwNzUw-2137014
+CSeq: 123456 INVITE
+Contact: <sip:Acaller at 137.132.31.151:58072>
+Content-Type: application/sdp
+Content-Length: 153
+
+v=0
+o=User 1589702922991241424 1420814338471844940 IN IP4 137.132.31.151
+s=
+c=IN IP4 137.132.31.151 UNHOLD UNHOLD
+m=audio 58074 RTP/AVP 0 
+a=rtpmap:0 PCMU/8000
diff --git a/test/shoot.c b/test/shoot.c
new file mode 100644
index 0000000..fef3b65
--- /dev/null
+++ b/test/shoot.c
@@ -0,0 +1,325 @@
+/*
+shot written by ashhar farhan, is not bound by any licensing at all.
+you are free to use this code as you deem fit. just dont blame the author
+for any problems you may have using it.
+bouquets and brickbats to farhan at hotfoon.com
+ */
+
+
+/* changes by jiri at iptel.org; now messages can be really received;
+   status code returned is 2 for some local errors , 0 for success
+   and 1 for remote error -- ICMP/timeout; can be used to test if
+   a server is alive; 1xx messages are now ignored; windows support
+   dropped
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <string.h>
+#include <ctype.h>
+#include <time.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <sys/socket.h>
+
+#include <regex.h>
+regex_t* regexp;
+
+#define RESIZE		1024
+
+/* take either a dot.decimal string of ip address or a 
+domain name and returns a NETWORK ordered long int containing
+the address. i chose to internally represent the address as long for speedier
+comparisons.
+
+any changes to getaddress have to be patched back to the net library.
+contact: farhan at hotfoon.com
+
+  returns zero if there is an error.
+  this is convenient as 0 means 'this' host and the traffic of
+  a badly behaving dns system remains inside (you send to 0.0.0.0)
+*/
+
+long getaddress(char *host)
+{
+	int i, dotcount=0;
+	char *p = host;
+	struct hostent* pent;
+	long l, *lp;
+
+	/*try understanding if this is a valid ip address
+	we are skipping the values of the octets specified here.
+	for instance, this code will allow 952.0.320.567 through*/
+	while (*p)
+	{
+		for (i = 0; i < 3; i++, p++)
+			if (!isdigit(*p))
+				break;
+		if (*p != '.')
+			break;
+		p++;
+		dotcount++;
+	}
+
+	/* three dots with up to three digits in before, between and after ? */
+	if (dotcount == 3 && i > 0 && i <= 3)
+		return inet_addr(host);
+
+	/* try the system's own resolution mechanism for dns lookup:
+	 required only for domain names.
+	 inspite of what the rfc2543 :D Using SRV DNS Records recommends,
+	 we are leaving it to the operating system to do the name caching.
+
+	 this is an important implementation issue especially in the light
+	 dynamic dns servers like dynip.com or dyndns.com where a dial
+	 ip address is dynamically assigned a sub domain like farhan.dynip.com
+
+	 although expensive, this is a must to allow OS to take
+	 the decision to expire the DNS records as it deems fit.
+	*/
+	pent = gethostbyname(host);
+	if (!pent) {
+		perror("no gethostbyname");
+		exit(2);
+	}
+
+	lp = (long *) (pent->h_addr);
+	l = *lp;
+	return l;
+}
+
+
+/*
+shoot:
+takes:
+	1. the text message of buff to 
+	2. the address (network ordered byte order)
+	3. and port (not network byte ordered).
+
+starting from half a second, times-out on replies and
+keeps retrying with exponential back-off that flattens out
+at 5 seconds (5000 milliseconds).
+
+* Does not stop sending unless a final response is received.
+we are detecting the final response without a '1' as the first
+letter.
+*/
+void shoot(char *buff, long address, int lport, int rport )
+{
+	struct sockaddr_in	addr;
+	/* jku - b  server structures */
+	struct sockaddr_in	sockname;
+	int ssock;
+	/*
+	char compiledre[ RESIZE ];
+	*/
+	/* jku - e */
+	int retryAfter = 500, i, len, ret;
+	int	nretries = 10;
+	int	sock;
+	struct timeval	tv;
+	fd_set	fd;
+	char	reply[1600];
+
+	/* create a socket */
+	sock = (int)socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
+	if (sock==-1) {
+		perror("no client socket");
+		exit(2);
+	}
+
+	/* jku - b */
+	ssock = (int)socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
+	if (sock==-1) {
+		perror("no server socket");
+		exit(2);
+	}
+
+	sockname.sin_family=AF_INET;
+	sockname.sin_addr.s_addr = htonl( INADDR_ANY );
+	sockname.sin_port = htons((short)lport);
+	if (bind( ssock, (struct sockaddr *) &sockname, sizeof(sockname) )==-1) {
+		perror("no bind");
+		exit(2);
+	}
+
+	/* should capture: SIP/2.0 100 Trying */
+	/* compile("^SIP/[0-9]\\.[0-9] 1[0-9][0-9] ", compiledre, &compiledre[RESIZE], '\0'); */
+	regexp=(regex_t*)malloc(sizeof(regex_t));
+	regcomp(regexp, "^SIP/[0-9]\\.[0-9] 1[0-9][0-9] ", REG_EXTENDED|REG_NOSUB|REG_ICASE); 
+	
+
+	/* jku - e */
+
+	addr.sin_addr.s_addr = address;
+	addr.sin_port = htons((short)rport);
+	addr.sin_family = AF_INET;
+	
+	/* we connect as per the RFC 2543 recommendations
+	modified from sendto/recvfrom */
+
+	ret = connect(sock, (struct sockaddr *)&addr, sizeof(addr));
+	if (ret==-1) {
+		perror("no connect");
+		exit(2);
+	}
+	/* jku - e */
+
+	for (i = 0; i < nretries; i++)
+	{
+		puts("/* request */");
+		puts(buff);
+		putchar('\n');
+
+		ret = send(sock, buff, strlen(buff), 0);
+		if (ret==-1) {
+			perror("send failure");
+			exit( 1 );
+		}
+		
+
+		tv.tv_sec = retryAfter/1000;
+		tv.tv_usec = (retryAfter % 1000) * 1000;
+
+		FD_ZERO(&fd);
+		FD_SET(ssock, &fd); 
+
+		/* TO-DO: there does appear to be a problem with this select returning a zero
+		even when there is data pending in the recv queue. 
+		please help, someone! */
+
+		ret = select(6, &fd, NULL, NULL, &tv);
+		if (ret == 0)
+		{
+			puts("\n/* timeout */\n");
+			retryAfter = retryAfter * 2;
+			if (retryAfter > 5000)
+				retryAfter = 5000;
+			/* we should have retrieved the error code and displayed
+			we are not doing that because there is a great variation
+			in the process of retrieving error codes between
+			micro$oft and *nix world*/
+			continue;
+		} else if ( ret == -1 ) {
+			perror("select error");
+			exit(2);
+		} /* no timeout, no error ... something has happened :-) */
+                 else if (FD_ISSET(ssock, &fd)) {
+			puts ("\nmessage received\n");
+		} else {
+			puts("\nselect returned successfully, nothing received\n");
+			continue;
+		}
+
+		/* we are retrieving only the extend of a decent MSS = 1500 bytes */
+		len = sizeof(addr);
+		ret = recv(ssock, reply, 1500, 0);
+		if(ret > 0)
+		{
+			reply[ret] = 0;
+			puts("/* reply */");
+			puts(reply);
+			putchar('\n');
+			/* if (step( reply, compiledre )) { */
+			if (regexec((regex_t*)regexp, reply, 0, 0, 0)==0) {
+				puts(" provisional received; still waiting for a final response\n ");
+				continue;
+			} else {
+				puts(" final received; congratulations!\n ");
+				exit(0);
+			}
+		
+		} 
+		else	{
+			perror("recv error");
+			exit(2);
+			}
+	}
+	/* after all the retries, nothing has come back :-( */
+	puts("/* I give up retransmission....");
+	exit(1);
+}
+
+int main(int argc, char *argv[])
+{
+	long	address;
+	FILE	*pf;
+	char	buff[1600];
+	int		length;
+	int	lport=0;
+	int	rport=5060;
+
+	if (! (argc >= 3 && argc <= 5))
+	{
+		puts("usage: shoot file host [rport] [lport]");
+		exit(2);
+	}
+
+	address = getaddress(argv[2]);
+	if (!address)
+	{
+		puts("error:unable to determine the remote host address.");
+		exit(2);
+	}
+
+	/* take the port as 5060 even if it is incorrectly specified */
+	if (argc >= 4)
+	{
+		rport = atoi(argv[3]);
+		if (!rport) {
+			puts("error: non-numerical remote port number");
+			exit(1);
+		}
+		if (argc==5) {
+			lport=atoi(argv[4]);
+			if (!lport) {
+				puts("error: non-numerical local port number");
+				exit(1);
+			}
+		}
+	}
+
+	/* file is opened in binary mode so that the cr-lf is preserved */
+	pf = fopen(argv[1], "rb");
+	if (!pf)
+	{
+		puts("unable to open the file.\n");
+		return 1;
+	}
+	length  = fread(buff, 1, sizeof(buff), pf);
+	if (length >= sizeof(buff))
+	{
+		puts("error:the file is too big. try files of less than 1500 bytes.");
+		return 1;
+	}
+	fclose(pf);
+	buff[length] = 0;
+
+	shoot(buff, address, lport, rport );
+
+	/* visual studio closes the debug console as soon as the 
+	program terminates. this is to hold the window from collapsing
+	Uncomment it if needed.
+	getchar();*/
+	
+
+	return 0;
+}
+
+
+/*
+shoot will exercise the all types of sip servers.
+it is not to be used to measure round-trips and general connectivity.
+use ping for that. 
+written by farhan on 10th august, 2000.
+
+TO-DO:
+1. replace the command line arguments with just a sip url like this:
+	shoot invite.txt sip:farhan at sip.hotfoon.com:5060
+
+2. understand redirect response and retransmit to the redirected server.
+
+*/
+
diff --git a/test/shoot2.c b/test/shoot2.c
new file mode 100644
index 0000000..099207e
--- /dev/null
+++ b/test/shoot2.c
@@ -0,0 +1,409 @@
+/*
+shot written by ashhar farhan, is not bound by any licensing at all.
+you are free to use this code as you deem fit. just dont blame the author
+for any problems you may have using it.
+bouquets and brickbats to farhan at hotfoon.com
+ */
+
+
+/* changes by jiri at iptel.org; now messages can be really received;
+   status code returned is 2 for some local errors , 0 for success
+   and 1 for remote error -- ICMP/timeout; can be used to test if
+   a server is alive; 1xx messages are now ignored; windows support
+   dropped
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <string.h>
+#include <ctype.h>
+#include <time.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <sys/socket.h>
+
+#include <sys/utsname.h>
+
+#include <regex.h>
+regex_t* regexp;
+
+#define RESIZE		1024
+#define BUFSIZE		1600
+#define VIA_BEGIN_STR "Via: SIP/2.0/UDP "
+#define VIA_BEGIN_STR_LEN 17
+
+/* take either a dot.decimal string of ip address or a 
+domain name and returns a NETWORK ordered long int containing
+the address. i chose to internally represent the address as long for speedier
+comparisons.
+
+any changes to getaddress have to be patched back to the net library.
+contact: farhan at hotfoon.com
+
+  returns zero if there is an error.
+  this is convenient as 0 means 'this' host and the traffic of
+  a badly behaving dns system remains inside (you send to 0.0.0.0)
+*/
+
+long getaddress(char *host)
+{
+	int i, dotcount=0;
+	char *p = host;
+	struct hostent* pent;
+	long l, *lp;
+
+	/*try understanding if this is a valid ip address
+	we are skipping the values of the octets specified here.
+	for instance, this code will allow 952.0.320.567 through*/
+	while (*p)
+	{
+		for (i = 0; i < 3; i++, p++)
+			if (!isdigit(*p))
+				break;
+		if (*p != '.')
+			break;
+		p++;
+		dotcount++;
+	}
+
+	/* three dots with up to three digits in before, between and after ? */
+	if (dotcount == 3 && i > 0 && i <= 3)
+		return inet_addr(host);
+
+	/* try the system's own resolution mechanism for dns lookup:
+	 required only for domain names.
+	 inspite of what the rfc2543 :D Using SRV DNS Records recommends,
+	 we are leaving it to the operating system to do the name caching.
+
+	 this is an important implementation issue especially in the light
+	 dynamic dns servers like dynip.com or dyndns.com where a dial
+	 ip address is dynamically assigned a sub domain like farhan.dynip.com
+
+	 although expensive, this is a must to allow OS to take
+	 the decision to expire the DNS records as it deems fit.
+	*/
+	pent = gethostbyname(host);
+	if (!pent) {
+		perror("no gethostbyname");
+		exit(2);
+	}
+
+	lp = (long *) (pent->h_addr);
+	l = *lp;
+	return l;
+}
+
+/* This function tries to add a Via Header Field in the message. */
+add_via(char *mes)
+{
+	struct utsname myname;
+	char *via_line, *via, *backup;
+
+	/* get our address, only the first one */
+	if (uname (&myname) <0){
+		printf("cannot determine hostname\n");
+		exit(2);
+	}
+#ifdef DEBUG
+	printf("determined hostname: %s\n", myname.nodename);
+#endif
+
+	via_line = malloc(VIA_BEGIN_STR_LEN + strlen(myname.nodename) + 3);
+	strcat(via_line, VIA_BEGIN_STR);
+	strcat(via_line, myname.nodename);
+	strcat(via_line, "\r\n");
+#ifdef DEBUG
+	printf("our Via-Line: %s\n", via_line);
+#endif
+
+	if (strlen(mes)+strlen(via_line)>= BUFSIZE){
+		printf("can't add our Via Header Line because file is too big\n");
+		exit(2);
+	}
+	if ((via=strstr(mes,"Via:"))==NULL){
+		/* We doesn't find a Via so we insert our via
+		   direct after the first line. */
+		via=strchr(mes,'\n');
+		via++;
+	}
+	backup=malloc(strlen(via));
+	strncpy(backup, via, strlen(via));
+	strncpy(via, via_line, strlen(via_line));
+	strncpy(via+strlen(via_line), backup, strlen(backup));
+#ifdef DEBUG
+	printf("New message:\n%s", mes);
+#endif
+}
+
+
+/*
+shoot:
+takes:
+	1. the text message of buff to 
+	2. the address (network ordered byte order)
+	3. and port (not network byte ordered).
+
+starting from half a second, times-out on replies and
+keeps retrying with exponential back-off that flattens out
+at 5 seconds (5000 milliseconds).
+
+* Does not stop sending unless a final response is received.
+we are detecting the final response without a '1' as the first
+letter.
+*/
+void shoot(char *buff, long address, int lport, int rport )
+{
+	struct sockaddr_in	addr;
+	/* jku - b  server structures */
+	struct sockaddr_in	sockname;
+	int ssock;
+	/*
+	char compiledre[ RESIZE ];
+	*/
+	/* jku - e */
+	int retryAfter = 500;
+	int	nretries = 10;
+	int sock, i, len, ret;
+	struct timeval	tv;
+	fd_set	fd;
+	char	reply[1600];
+
+	/* create a socket */
+	sock = (int)socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
+	if (sock==-1) {
+		perror("no client socket");
+		exit(2);
+	}
+
+	/* jku - b */
+	ssock = (int)socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
+	if (ssock==-1) {
+		perror("no server socket");
+		exit(2);
+	}
+
+	sockname.sin_family=AF_INET;
+	sockname.sin_addr.s_addr = htonl( INADDR_ANY );
+	sockname.sin_port = htons((short)lport);
+	if (bind( ssock, (struct sockaddr *) &sockname, sizeof(sockname) )==-1) {
+		perror("no bind");
+		exit(2);
+	}
+
+	/* should capture: SIP/2.0 100 Trying */
+	/* compile("^SIP/[0-9]\\.[0-9] 1[0-9][0-9] ", compiledre, &compiledre[RESIZE], '\0'); */
+	regexp=(regex_t*)malloc(sizeof(regex_t));
+	regcomp(regexp, "^SIP/[0-9]\\.[0-9] 1[0-9][0-9] ", REG_EXTENDED|REG_NOSUB|REG_ICASE); 
+	
+
+	/* jku - e */
+
+	addr.sin_addr.s_addr = address;
+	addr.sin_port = htons((short)rport);
+	addr.sin_family = AF_INET;
+	
+	/* we connect as per the RFC 2543 recommendations
+	modified from sendto/recvfrom */
+
+	ret = connect(sock, (struct sockaddr *)&addr, sizeof(addr));
+	if (ret==-1) {
+		perror("no connect");
+		exit(2);
+	}
+	/* jku - e */
+
+	add_via(buff);
+	
+	for (i = 0; i < nretries; i++)
+	{
+		puts("/* request */");
+		puts(buff);
+		putchar('\n');
+
+		ret = send(sock, buff, strlen(buff), 0);
+		if (ret==-1) {
+			perror("send failure");
+			exit( 1 );
+		}
+		
+
+		tv.tv_sec = retryAfter/1000;
+		tv.tv_usec = (retryAfter % 1000) * 1000;
+
+		FD_ZERO(&fd);
+		FD_SET(ssock, &fd); 
+
+		/* TO-DO: there does appear to be a problem with this select returning a zero
+		even when there is data pending in the recv queue. 
+		please help, someone! */
+
+		ret = select(6, &fd, NULL, NULL, &tv);
+		if (ret == 0)
+		{
+			puts("\n/* timeout */\n");
+			retryAfter = retryAfter * 2;
+			if (retryAfter > 5000)
+				retryAfter = 5000;
+			/* we should have retrieved the error code and displayed
+			we are not doing that because there is a great variation
+			in the process of retrieving error codes between
+			micro$oft and *nix world*/
+			continue;
+		} else if ( ret == -1 ) {
+			perror("select error");
+			exit(2);
+		} /* no timeout, no error ... something has happened :-) */
+                 else if (FD_ISSET(ssock, &fd)) {
+			puts ("\nmessage received\n");
+		} else {
+			puts("\nselect returned successfully, nothing received\n");
+			continue;
+		}
+
+		/* we are retrieving only the extend of a decent MSS = 1500 bytes */
+		len = sizeof(addr);
+		ret = recv(ssock, reply, 1500, 0);
+		if(ret > 0)
+		{
+			reply[ret] = 0;
+			puts("/* reply */");
+			puts(reply);
+			putchar('\n');
+			/* if (step( reply, compiledre )) { */
+			if (regexec((regex_t*)regexp, reply, 0, 0, 0)==0) {
+				puts(" provisional received; still waiting for a final response\n ");
+				continue;
+			} else {
+				puts(" final received; congratulations!\n ");
+				exit(0);
+			}
+		
+		} 
+		else	{
+			perror("recv error");
+			exit(2);
+			}
+	}
+	/* after all the retries, nothing has come back :-( */
+	puts("/* I give up retransmission....");
+	exit(1);
+}
+
+int main(int argc, char *argv[])
+{
+	long	address;
+	FILE	*pf;
+	char	buff[BUFSIZE];
+	int		length;
+	int		lport=0;
+	int		rport=5060;
+	char	*delim, *delim2;
+
+	if (! (argc >= 3 && argc <= 5))
+	{
+		puts("usage: shoot file host rport [lport]");
+		puts("usage: shoot file sip:[user@]hostname[:rport]");
+		exit(2);
+	}
+
+	/* support for sip:uri added by noh */
+	if (argc==3){
+		if ((delim=strchr(argv[2],':'))!=NULL){
+			delim++;
+			if (!strncmp(argv[2],"sip",3)){
+				if ((delim2=strchr(delim,'@'))!=NULL){
+					/* we don't need the username */
+					delim2++;
+					delim=delim2;
+				}
+				if ((delim2=strchr(delim,':'))!=NULL){
+					*delim2 = '\0';
+					delim2++;
+					rport = atoi(delim2);
+					if (!rport) {
+						puts("error: non-numerical remote port number");
+						exit(2);
+					}
+				}
+				address = getaddress(delim);
+				if (!address){
+					puts("error:unable to determine the remote host address.");
+					exit(2);
+				}
+			}
+			else{
+				puts("sip:uri doesn't not begin with sip");
+				exit(2);
+			}
+		}
+		else{
+			puts("sip:uri doesn't contain a : ?!");
+			exit(2);
+		}
+	}
+	else{
+		address = getaddress(argv[2]);
+		if (!address){
+			puts("error:unable to determine the remote host address.");
+			exit(2);
+		}
+
+		/* take the port as 5060 even if it is incorrectly specified */
+		if (argc >= 4){
+			rport = atoi(argv[3]);
+			if (!rport) {
+				puts("error: non-numerical remote port number");
+				exit(2);
+			}
+			if (argc==5) {
+				lport=atoi(argv[4]);
+				if (!lport) {
+					puts("error: non-numerical local port number");
+					exit(2);
+				}
+			}
+		}
+	}
+
+	/* file is opened in binary mode so that the cr-lf is preserved */
+	pf = fopen(argv[1], "rb");
+	if (!pf)
+	{
+		puts("unable to open the file.\n");
+		return 1;
+	}
+	length  = fread(buff, 1, sizeof(buff), pf);
+	if (length >= sizeof(buff))
+	{
+		printf("error:the file is too big. try files of less than %i bytes.\n", BUFSIZE);
+		puts("      or recompile the program with bigger BUFSIZE defined.");
+		return 1;
+	}
+	fclose(pf);
+	buff[length] = 0;
+
+	shoot(buff, address, lport, rport );
+
+	/* visual studio closes the debug console as soon as the 
+	program terminates. this is to hold the window from collapsing
+	Uncomment it if needed.
+	getchar();*/
+	
+
+	return 0;
+}
+
+
+/*
+shoot will exercise the all types of sip servers.
+it is not to be used to measure round-trips and general connectivity.
+use ping for that. 
+written by farhan on 10th august, 2000.
+
+TO-DO:
+2. understand redirect response and retransmit to the redirected server.
+
+*/
+
diff --git a/test/short_nonce.sip b/test/short_nonce.sip
new file mode 100644
index 0000000..b4d8ee1
--- /dev/null
+++ b/test/short_nonce.sip
@@ -0,0 +1,11 @@
+REGISTER sip:iptel.org SIP/2.0
+Via: SIP/2.0/UDP 213.20.132.141:16449
+From: <sip:jiri at iptel.org>;tag=5df69a49-de80-436e-82eb-d0a991cbf744
+To: <sip:jiri at iptel.org>
+Call-ID: f3969dea-6401-427c-bdaf-ec92beedf8e7 at 213.20.132.141
+CSeq: 18 REGISTER
+Contact: <sip:213.20.132.141:16449>;methods="INVITE, MESSAGE, INFO, SUBSCRIBE, OPTIONS, BYE, CANCEL, NOTIFY, ACK"
+User-Agent: Windows RTC/1.0
+Expires: 0
+Content-Length: 0
+Authorization: Digest username="jiri", realm="iptel.org", algorithm="MD5", uri="sip:iptel.org", response="8791571e2a65e8e1d5ac17cc49f8a16d", nonce="3
diff --git a/test/short_reply.sip b/test/short_reply.sip
new file mode 100644
index 0000000..9ab6472
--- /dev/null
+++ b/test/short_reply.sip
@@ -0,0 +1,4 @@
+SIP/2.0 183 Session Progress
+Via: SIP/2.0/UDP 195.37.77.100;branch=b7a102045e84a2d128c3e173680de665.531.0
+Via: SIP/2.0/UDP pig.iptel.org
+
diff --git a/test/sock_conn.c b/test/sock_conn.c
new file mode 100644
index 0000000..b060be1
--- /dev/null
+++ b/test/sock_conn.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2001-2003 FhG Fokus
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <errno.h>
+#include <arpa/inet.h>
+
+/* results:
+
+
+real    0m23.332s
+user    0m0.410s
+sys     0m15.710s
+
+*/
+
+
+
+
+/* which socket to use? main socket or new one? */
+int udp_send()
+{
+
+	register int i;
+	 int n;
+	char buffer;
+	int sock;
+	struct sockaddr_in addr;
+
+	if ((sock=socket(PF_INET, SOCK_DGRAM, 0))<0) {
+		fprintf( stderr, "socket error\n");
+		exit(1);
+	}
+
+
+	memset( &addr, 0, sizeof(struct sockaddr_in));
+	addr.sin_family=AF_INET;
+	addr.sin_port=htons(9);
+	addr.sin_addr.s_addr= inet_addr("127.0.0.1");
+
+	if (connect(sock, (struct sockaddr *) &addr, sizeof(addr))==-1) {
+		fprintf( stderr, "connect failed\n");
+		exit(1);
+	}
+
+	for (i=0; i<1024*1024*16; i++) 
+		write( sock, &buffer, 1 );
+/*		sendto(sock, &buffer, 1, 0, (struct sockaddr *) &addr, sizeof(addr)); */
+
+}
+
+main() {
+
+	udp_send();
+}
diff --git a/test/sock_disc.c b/test/sock_disc.c
new file mode 100644
index 0000000..a9a0966
--- /dev/null
+++ b/test/sock_disc.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2001-2003 FhG Fokus
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <errno.h>
+#include <arpa/inet.h>
+
+/* results:
+
+
+real    0m23.332s
+user    0m0.410s
+sys     0m15.710s
+
+*/
+
+
+
+
+/* which socket to use? main socket or new one? */
+int udp_send()
+{
+
+	register int i;
+	 int n;
+	char buffer;
+	int sock;
+	struct sockaddr_in addr;
+
+	if ((sock=socket(PF_INET, SOCK_DGRAM, 0))<0) {
+		fprintf( stderr, "socket error\n");
+		exit(1);
+	}
+
+	memset( &addr, 0, sizeof(struct sockaddr_in));
+	addr.sin_family=AF_INET;
+	addr.sin_port=htons(9);
+	addr.sin_addr.s_addr= inet_addr("127.0.0.1");
+
+	for (i=0; i<1024*1024*16; i++) 
+		sendto(sock, &buffer, 1, 0, (struct sockaddr *) &addr, sizeof(addr));
+
+}
+
+main() {
+
+	udp_send();
+}
diff --git a/test/stateless.cfg b/test/stateless.cfg
new file mode 100644
index 0000000..1971833
--- /dev/null
+++ b/test/stateless.cfg
@@ -0,0 +1,38 @@
+#
+# configuration for stress testing
+#
+#
+
+
+#debug=9          # debug level (cmd line: -dddddddddd)
+#fork=yes          # (cmd. line: -D)
+#log_stderror=yes # (cmd line: -E)
+#log_stderror=no	# (cmd line: -E)
+
+
+#children=2
+check_via=no     # (cmd. line: -v)
+dns=off           # (cmd. line: -r)
+rev_dns=off      # (cmd. line: -R)
+#port=5070
+#listen=10.0.0.179 lo	dorian
+#listen=eth0
+#listen=127.0.0.1
+#listen=192.168.57.33
+#listen=192.168.57.72
+#loop_checks=0
+# for more info: sip_router -h
+alias=iptel.org
+alias="foo.bar"
+fifo="/tmp/ser_fifo"
+
+#modules
+
+
+route{
+	if (myself==uri){
+		log("\n\nfrom myself\n\n");
+	};
+	log(" continue \n\n");
+	forward(uri:host, uri:port);
+}
diff --git a/test/stress.cfg b/test/stress.cfg
new file mode 100644
index 0000000..855b795
--- /dev/null
+++ b/test/stress.cfg
@@ -0,0 +1,54 @@
+#
+#
+# iptel.org real world configuration
+#
+
+# ----------- global configuration parameters ------------------------
+
+debug=0
+fork=1
+log_stderror=yes	# (cmd line: -E)
+check_via=no # (cmd. line: -v)
+dns=no # (cmd. line: -r)
+reply_to_via=0
+fifo="/tmp/ser_fifo"
+
+# advertise IP address in Via (as opposed to advertising DNS name
+# which is annoying for downstream servers and some phones can
+# not handle DNS at all)
+listen=195.37.77.100
+
+# ------------------ module loading ----------------------------------
+
+loadmodule "../sip_router/modules/sl/sl.so"
+loadmodule "../sip_router/modules/print/print.so"
+#loadmodule "../sip_router/modules/tm/tm_mod.so"
+loadmodule "../sip_router/modules/usrloc/usrloc.so"
+
+# ----------------- setting module-specific parameters ---------------
+
+# -- usrloc params --
+
+modparam("usrloc", "use_database",   0)
+modparam("usrloc", "flush_interval", 3600)
+
+# -- tm params --
+modparam("tm", "fr_timer", 5 )
+modparam("tm", "fr_inv_timer", 5 )
+modparam("tm", "wt_timer", 5 )
+
+# -------------------------  request routing logic -------------------
+
+# main routing logic
+
+route{
+	append_branch("sip:bla at bat.iptel.org:5088");
+	append_branch("sip:blb at bat.iptel.org:5088");
+	t_on_negative("1");
+	t_relay_to("bat.iptel.org","5088");
+}
+
+reply_route[1] {
+	append_branch("sip:mrx at bat.iptel.org:5088");
+}
+
diff --git a/test/struas.cfg b/test/struas.cfg
new file mode 100644
index 0000000..9efcc18
--- /dev/null
+++ b/test/struas.cfg
@@ -0,0 +1,41 @@
+#
+# iptel.org real world configuration
+#
+
+# ----------- global configuration parameters ------------------------
+
+debug=3
+fork=no
+#children=2
+log_stderror=yes	# (cmd line: -E)
+check_via=yes     # (cmd. line: -v)
+dns=0           # (cmd. line: -r)
+rev_dns=0      # (cmd. line: -R)
+port=5088
+reply_to_via=no
+
+# advertise IP address in Via (as opposed to advertising DNS name
+# which is annoying for downstream servers and some phones can
+# not handle DNS at all)
+listen=195.37.77.100
+
+# ------------------ module loading ----------------------------------
+
+loadmodule "../sip_router/modules/sl/sl.so"
+loadmodule "../sip_router/modules/print/print.so"
+
+# ----------------- setting module-specific parameters ---------------
+
+
+# -------------------------  request routing logic -------------------
+
+# main routing logic
+
+route{
+	if (method=="CANCEL") {
+		sl_send_reply("200", "glad to cancel");
+		break;
+	};
+	sl_send_reply("180", "Jinggle Bells");
+}
+
diff --git a/test/t_debug2.cfg b/test/t_debug2.cfg
new file mode 100644
index 0000000..0eb8283
--- /dev/null
+++ b/test/t_debug2.cfg
@@ -0,0 +1,58 @@
+debug=9          # debug level (cmd line: -dddddddddd)
+check_via=yes     # (cmd. line: -v)
+dns=on           # (cmd. line: -r)
+rev_dns=yes      # (cmd. line: -R)
+fork=no          # (cmd. line: -D)
+#children=5
+log_stderror=yes # (cmd line: -E)
+#port=5080
+#listen=192.168.99.100
+loop_checks=1
+# for more info: sip_router -h
+
+#modules
+loadmodule "modules/print/print.so"
+loadmodule "modules/tm/tm.so"
+
+route{
+	#rewritehost("iptel.org");
+	log("trying forward to uri");
+#	forward(uri:host,uri:port);
+#	forward(127.0.0.1, 5090);
+	log("after forward");
+
+	if ( t_lookup_request()) {
+		print("\nFOUND REQUEST\n");
+		if ( method=="ACK" )	{
+			log("SER: ACK received -> t_release\n");
+			t_release();
+		} else {
+			t_retransmit_reply();
+			log("SER: yet another annoying retranmission\n");
+		};
+	} else {
+		print("\nbefore add transaction\n");
+		t_add_transaction();
+		print("\nafter add transaction\n");
+		if (method=="CANCEL") {
+			log("SER: new CANCEL\n");
+			# XXX ... it wants me to put status code in ""
+			t_send_reply( "200", "glad to cancel");
+		} else {
+		print("\nELSE if method\n");
+			log("SER: new transaction\n");
+			t_send_reply("100", "trying -- your call is important to us");
+		};
+		print("\nbefore rewrite host\n");
+		rewritehost("iptel.org");
+		# XXX ... it wants me to put port nr in ""
+		#t_forward("benetnash.fokus.gmd.de", "5080" );
+		#t_forward("iptel.org", "5060" );
+		print("\nbefore forward uri\n");
+		t_forward_uri();
+		# XXX ... it doesn't like default port numbers
+		# t_forward("fox.iptel.org" );
+		# XXX t_forward_uri ... not done yet
+	};
+		
+}
diff --git a/test/t_debug3.cfg b/test/t_debug3.cfg
new file mode 100644
index 0000000..2713194
--- /dev/null
+++ b/test/t_debug3.cfg
@@ -0,0 +1,50 @@
+debug=9          # debug level (cmd line: -dddddddddd)
+check_via=yes     # (cmd. line: -v)
+dns=on           # (cmd. line: -r)
+rev_dns=yes      # (cmd. line: -R)
+fork=no          # (cmd. line: -D)
+children=8
+log_stderror=yes # (cmd line: -E)
+#port=5080
+#listen=192.168.99.100
+loop_checks=1
+# for more info: sip_router -h
+
+#modules
+loadmodule "modules/print/print.so"
+loadmodule "modules/tm/tm.so"
+
+route{
+	#rewritehost("iptel.org");
+#	forward(uri:host,uri:port);
+#	forward(127.0.0.1, 5090);
+
+	if ( t_lookup_request()) {
+		if ( method=="ACK" )	{
+			log("SER: ACK received -> t_release\n");
+			t_release();
+		} else {
+			t_retransmit_reply();
+#			log("SER: yet another annoying retranmission\n");
+		};
+	} else {
+		t_add_transaction();
+		if (method=="CANCEL") {
+			log("SER: new CANCEL\n");
+			# XXX ... it wants me to put status code in ""
+			t_send_reply( "200", "glad to cancel");
+		} else {
+			log("SER: new transaction\n");
+			t_send_reply("100", "trying -- your call is important to us");
+		};
+#		rewritehost("iptel.org");
+		# XXX ... it wants me to put port nr in ""
+		#t_forward("benetnash.fokus.gmd.de", "5080" );
+		#t_forward("iptel.org", "5060" );
+		t_forward_uri();
+		# XXX ... it doesn't like default port numbers
+		# t_forward("fox.iptel.org" );
+		# XXX t_forward_uri ... not done yet
+	};
+		
+}
diff --git a/test/tcp.cfg b/test/tcp.cfg
new file mode 100644
index 0000000..4d83498
--- /dev/null
+++ b/test/tcp.cfg
@@ -0,0 +1,38 @@
+#
+# configuration for stress testing
+#
+
+
+#debug=9          # debug level (cmd line: -dddddddddd)
+#fork=yes          # (cmd. line: -D)
+#log_stderror=yes # (cmd line: -E)
+#log_stderror=no	# (cmd line: -E)
+
+
+#children=2
+check_via=no     # (cmd. line: -v)
+dns=off           # (cmd. line: -r)
+rev_dns=off      # (cmd. line: -R)
+#port=5070
+#listen=10.0.0.179 lo	dorian
+#listen=eth0
+#listen=127.0.0.1
+#listen=192.168.57.33
+#listen=192.168.57.72
+#loop_checks=0
+# for more info: sip_router -h
+alias=iptel.org
+alias="foo.bar"
+fifo="/tmp/ser_fifo"
+
+#modules
+
+route{
+	if (myself==uri){
+		log("\n\nfrom myself\n\n");
+	};
+	log(" continue \n\n");
+	#send_tcp("127.0.0.1", 6050);
+	forward_udp(fox.iptel.org, 5060);
+	#forward(uri:host, uri:port);
+}
diff --git a/test/tcp_tunnel1.cfg b/test/tcp_tunnel1.cfg
new file mode 100644
index 0000000..b5c11a0
--- /dev/null
+++ b/test/tcp_tunnel1.cfg
@@ -0,0 +1,33 @@
+#
+# configuration for stress testing
+#
+#
+
+
+#debug=9          # debug level (cmd line: -dddddddddd)
+#fork=yes          # (cmd. line: -D)
+#log_stderror=yes # (cmd line: -E)
+#log_stderror=no	# (cmd line: -E)
+
+
+#children=2
+check_via=no     # (cmd. line: -v)
+dns=off           # (cmd. line: -r)
+rev_dns=off      # (cmd. line: -R)
+#port=5070
+#listen=10.0.0.179 lo	dorian
+#listen=eth0
+#listen=127.0.0.1
+#listen=192.168.57.33
+#listen=192.168.57.72
+#loop_checks=0
+# for more info: sip_router -h
+alias="foo.bar"
+fifo="/tmp/ser_fifo"
+
+#modules
+#loadmodule "modules/tm/tm.so"
+
+route{
+	forward_tcp(mobile55, 5060);
+}
diff --git a/test/tcp_tunnel2.cfg b/test/tcp_tunnel2.cfg
new file mode 100644
index 0000000..8b79e01
--- /dev/null
+++ b/test/tcp_tunnel2.cfg
@@ -0,0 +1,35 @@
+#
+# configuration for stress testing
+#
+#
+
+
+#debug=9          # debug level (cmd line: -dddddddddd)
+#fork=yes          # (cmd. line: -D)
+#log_stderror=yes # (cmd line: -E)
+#log_stderror=no	# (cmd line: -E)
+
+
+#children=2
+check_via=no     # (cmd. line: -v)
+dns=off           # (cmd. line: -r)
+rev_dns=off      # (cmd. line: -R)
+#port=5070
+#listen=10.0.0.179 lo	dorian
+#listen=eth0
+#listen=127.0.0.1
+#listen=192.168.57.33
+#listen=192.168.57.72
+#loop_checks=0
+# for more info: sip_router -h
+alias="foo.bar"
+fifo="/tmp/ser_fifo"
+
+#modules
+loadmodule "modules/tm/tm.so"
+
+route{
+#	forward_udp(uri:host, uri:port);
+	t_relay_udp();
+	#forward_udp(uri:host, uri:port);
+}
diff --git a/test/td.cfg b/test/td.cfg
new file mode 100644
index 0000000..69e7a4a
--- /dev/null
+++ b/test/td.cfg
@@ -0,0 +1,52 @@
+debug=9          # debug level (cmd line: -dddddddddd)
+check_via=yes     # (cmd. line: -v)
+dns=on           # (cmd. line: -r)
+rev_dns=yes      # (cmd. line: -R)
+fork=no          # (cmd. line: -D)
+log_stderror=yes # (cmd line: -E)
+port=5080
+listen=192.168.99.100
+loop_checks=1
+# for more info: sip_router -h
+
+#modules
+loadmodule "modules/print/print.so"
+loadmodule "modules/tm/tm.so"
+
+route{
+	log("trying forward to uri");
+#	setuser("jiri");
+#	forward(uri:host,uri:port);
+#	forward(127.0.0.1, 5090);
+	log("after forward");
+
+	if ( t_lookup_request()) {
+		if ( method=="ACK" )	{
+			log("SER: ACK received -> t_release\n");
+			t_release();
+		} else {
+			t_retransmit_reply();
+			log("SER: yet another annoying retranmission\n");
+		};
+	} else {
+		t_add_transaction();
+		if (method=="CANCEL") {
+			log("SER: new CANCEL\n");
+			# XXX ... it wants me to put status code in ""
+			t_send_reply( "200", "glad to cancel");
+		} else {
+			log("SER: new transaction\n");
+			t_send_reply("100", "trying -- your call is important to us");
+		};
+		#rewritehost("xy.com");
+		# XXX ... it wants me to put port nr in ""
+		#t_forward("benetnash.fokus.gmd.de", "5080" );
+
+		t_forward("iptel.org", "5060" );
+#		t_forward("195.37.78.146", "5060" );
+		# XXX ... it doesn't like default port numbers
+		# t_forward("fox.iptel.org" );
+		# XXX t_forward_uri ... not done yet
+	};
+		
+}
diff --git a/test/test-throughput.cfg b/test/test-throughput.cfg
new file mode 100644
index 0000000..022faab
--- /dev/null
+++ b/test/test-throughput.cfg
@@ -0,0 +1,16 @@
+#debug=9			# for speed
+check_via=0
+dns=off
+rev_dns=off
+#fork=yes
+log_stderror=yes
+#children=8
+fifo=""
+alias=foo.bar
+alias=testing
+
+route{
+
+forward(uri:host, uri:port);
+}
+
diff --git a/test/test.c b/test/test.c
new file mode 100644
index 0000000..e52f9c7
--- /dev/null
+++ b/test/test.c
@@ -0,0 +1,78 @@
+/* 
+ * Copyright (C) 2001-2003 FhG Fokus
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <errno.h>
+#include <arpa/inet.h>
+
+
+#define LOOP_COUNT 100
+#define PORT 5060
+#define SEND_PORT 5090
+#define SEND_ADDR 0x0a000022 /*10.0.0.34*/   /*   0x7f000001 127.0.0.1*/
+#define BUF_SIZE 65535
+static char buf[BUF_SIZE];
+
+int main(char** argv, int argn)
+{
+	int sock;
+	struct sockaddr_in addr;
+	struct sockaddr_in to;
+	int r, len;
+
+	printf("starting\n");
+	
+	addr.sin_family=AF_INET;
+	addr.sin_port=htons(PORT);
+	addr.sin_addr.s_addr=INADDR_ANY;
+	to.sin_family=AF_INET;
+	to.sin_port=htons(SEND_PORT);
+	to.sin_addr.s_addr=htonl(SEND_ADDR);
+		
+
+	sock=socket(PF_INET, SOCK_DGRAM,0);
+	if (bind(sock, (struct sockaddr*) &addr, sizeof(struct sockaddr_in))==-1){
+		fprintf(stderr, "ERROR: udp_init: bind: %s\n", strerror(errno));
+		exit(1);
+	}
+
+	//if (fork())
+		if (fork()){
+			close(sock);
+			for(;;) sleep(100);
+			exit(1);
+		}
+	/*children*/
+	printf("child\n");
+	for(;;){
+		len=read(sock, buf, BUF_SIZE);
+		/*for (r=0;r < LOOP_COUNT; r++);*/
+		/* send it back*/
+		sendto(sock, buf, len, 0, (struct sockaddr*) &to,
+				sizeof(struct sockaddr_in));
+	}
+}
diff --git a/test/test.cfg b/test/test.cfg
new file mode 100644
index 0000000..4092dc9
--- /dev/null
+++ b/test/test.cfg
@@ -0,0 +1,43 @@
+#
+# configuration for stress testing
+#
+#
+
+
+#debug=9          # debug level (cmd line: -dddddddddd)
+#fork=yes          # (cmd. line: -D)
+#log_stderror=yes # (cmd line: -E)
+#log_stderror=no	# (cmd line: -E)
+
+
+#children=2
+check_via=no     # (cmd. line: -v)
+dns=off           # (cmd. line: -r)
+rev_dns=off      # (cmd. line: -R)
+#port=5070
+#listen=10.0.0.179 lo	dorian
+#listen=eth0
+#listen=127.0.0.1
+#listen=192.168.57.33
+#listen=192.168.57.72
+#loop_checks=0
+# for more info: sip_router -h
+alias=iptel.org
+alias="foo.bar"
+fifo="/tmp/ser_fifo"
+#listen= tcp:10.0.0.179:5065
+alias=  tcp:all:5065
+tcp_accept_aliases=yes
+
+
+#modules
+
+
+route{
+	if (myself==uri){
+		log("\n\nfrom myself\n\n");
+	};
+	log(" continue \n\n");
+	#force_tcp_alias();
+	forward(uri:host, uri:port);
+}
diff --git a/test/test1.cfg b/test/test1.cfg
new file mode 100644
index 0000000..24a617b
--- /dev/null
+++ b/test/test1.cfg
@@ -0,0 +1,34 @@
+# test config file
+
+/* C style comment */
+
+/*
+ * same thing but on multiple lines
+ */
+
+/*
+  /* Nested
+    comment */
+*/
+
+
+debug=1
+dns=true #comment on the same line
+
+route{
+	(method==invite and src_ip==1.2.3.4/32 or (src_ip==4.3.2.1 and src_ip==11.12.13.14/24) ) log("test log\n"); forward("ape");
+	( uri=~"test\n" &  ! src_ip=~"dorian") forward(dorian.fokus.gmd.de);
+
+	(src_ip==192.168.0.0/255.255.0.0 or dst_ip==127.0.0.1 and uri=~"s$") \
+		error("440","not forwarding"); log(2,"droping..."); drop;
+
+	src_ip==127.0.0.1 route(3); drop;
+}
+
+fork=no
+
+route[3]{
+	(src_ip==0.0.0.0/0) exec('/bin/ls >/tmp/x'); send(4.3.2.1,8000); /* catch all */
+}
+
+/* eof */
diff --git a/test/test2.cfg b/test/test2.cfg
new file mode 100644
index 0000000..48581c2
--- /dev/null
+++ b/test/test2.cfg
@@ -0,0 +1,20 @@
+debug=9          # debug level (cmd line: -dddddddddd)
+check_via=yes     # (cmd. line: -v)
+dns=on           # (cmd. line: -r)
+rev_dns=yes      # (cmd. line: -R)
+#fork=no          # (cmd. line: -D)
+#log_stderror=yes # (cmd line: -E)
+# for more info: sip_router -h
+
+#modules
+loadmodule "modules/print/print.so"
+loadmodule "modules/textops/textops.so"
+
+route{
+	print("before insert");
+	replace('^User-Agent:.*$', "User-Agent: ser 0.8.x");
+	print("after insert");
+	search_append('To:.*$', "Foo Bar");
+	forward(127.0.0.1,5061);
+	print("after forward");
+}
diff --git a/test/test3.cfg b/test/test3.cfg
new file mode 100644
index 0000000..97af49b
--- /dev/null
+++ b/test/test3.cfg
@@ -0,0 +1,17 @@
+debug=9          # debug level (cmd line: -dddddddddd)
+check_via=yes     # (cmd. line: -v)
+dns=on           # (cmd. line: -r)
+rev_dns=yes      # (cmd. line: -R)
+fork=no          # (cmd. line: -D)
+log_stderror=yes # (cmd line: -E)
+# for more info: sip_router -h
+
+#modules
+loadmodule "modules/print/print.so"
+
+route{
+	#rewritehost("127.0.0.1");
+	print("trying forward to uri");
+	forward(uri:host,uri:port);
+	print("after forward");
+}
diff --git a/test/th-uri-2.cfg b/test/th-uri-2.cfg
new file mode 100644
index 0000000..05b27b6
--- /dev/null
+++ b/test/th-uri-2.cfg
@@ -0,0 +1,53 @@
+#
+# tm test configuration, please don't touch
+# - andrei
+#
+#
+#
+
+
+
+debug=3          # debug level (cmd line: -dddddddddd)
+fork=yes          # (cmd. line: -D)
+#fork=no
+log_stderror=yes # (cmd line: -E)
+#log_stderror=no	# (cmd line: -E)
+
+
+children=4
+check_via=no     # (cmd. line: -v)
+dns=on           # (cmd. line: -r)
+rev_dns=yes      # (cmd. line: -R)
+#port=5070
+#listen=127.0.0.1
+#listen=192.168.57.33
+#listen=192.168.57.72
+#listen=10.0.0.179
+loop_checks=0
+# for more info: sip_router -h
+
+#modules
+#loadmodule "modules/print/print.so"
+loadmodule "modules/tm/tm.so"
+#loadmodule "modules/rr/rr.so"
+loadmodule "modules/maxfwd/maxfwd.so"
+
+
+route{
+             if ( mf_is_maxfwd_present() )
+             {
+                   if ( !mf_decrement_maxfwd() )
+                   {
+                     log("SER : unable to decrement MAX_FORWARD!\n");
+                   };
+                   if ( mf_is_maxfwd_zero() )
+                   {
+                     log("SER: MAX FORWARD header is zero\n");
+                     drop();
+                   };
+             }else{
+                   mf_add_maxfwd_header( "10" );
+             };
+
+             t_relay();
+}
diff --git a/test/th-uri-8.cfg b/test/th-uri-8.cfg
new file mode 100644
index 0000000..87dd5ae
--- /dev/null
+++ b/test/th-uri-8.cfg
@@ -0,0 +1,62 @@
+#
+# configuration for Stress testing
+#
+#
+
+
+debug=3          # debug level (cmd line: -dddddddddd)
+#fork=yes          # (cmd. line: -D)
+fork=yes
+log_stderror=yes # (cmd line: -E)
+#log_stderror=no	# (cmd line: -E)
+
+
+children=8
+check_via=no     # (cmd. line: -v)
+dns=on           # (cmd. line: -r)
+rev_dns=yes      # (cmd. line: -R)
+#port=5070
+#listen=127.0.0.1
+listen=192.168.57.33
+loop_checks=0
+# for more info: sip_router -h
+
+#modules
+#loadmodule "modules/print/print.so"
+loadmodule "modules/tm/tm.so"
+loadmodule "modules/rr/rr.so"
+loadmodule "modules/maxfwd/maxfwd.so"
+
+
+route{
+             if ( mf_is_maxfwd_present() )
+             {
+                   if ( !mf_decrement_maxfwd() )
+                   {
+                     log("SER : unable to decrement MAX_FORWARD!\n");
+                   };
+                   if ( mf_is_maxfwd_zero() )
+                   {
+                     log("SER: MAX FORWARD header is zero\n");
+                     drop();
+                   };
+             }else{
+                   mf_add_maxfwd_header( "10" );
+             };
+
+             #if ( !rewriteFromRoute() )
+             #{
+                log( " SER : no route found!\n");
+               # if ( method=="INVITE" )
+               # {
+                   #log ("SER : INVITE found - > adding RecordRoute!\n");
+                   #addRecordRoute();
+                #};
+             #}
+             #else
+             #{
+             #   log( "SER : ROUTE found! \n");
+             #};
+
+             t_relay();
+}
diff --git a/test/th-uri-fast.cfg b/test/th-uri-fast.cfg
new file mode 100644
index 0000000..a7da60c
--- /dev/null
+++ b/test/th-uri-fast.cfg
@@ -0,0 +1,33 @@
+#
+# configuration for stress testing
+#
+#
+
+
+#debug=3          # debug level (cmd line: -dddddddddd)
+#fork=yes          # (cmd. line: -D)
+#fork=no
+#log_stderror=yes # (cmd line: -E)
+#log_stderror=no	# (cmd line: -E)
+
+
+#children=8
+check_via=no     # (cmd. line: -v)
+dns=no          # (cmd. line: -r)
+rev_dns=no      # (cmd. line: -R)
+mem_log=0
+#port=5070
+#listen=127.0.0.1
+#listen=195.37.77.101
+# for more info: sip_router -h
+
+#modules
+#loadmodule "modules/print/print.so"
+loadmodule "modules/tm/tm.so"
+#loadmodule "modules/rr/rr.so"
+#loadmodule "modules/maxfwd/maxfwd.so"
+
+
+route{
+             t_relay();
+}
diff --git a/test/th-uri.cfg b/test/th-uri.cfg
new file mode 100644
index 0000000..e2fe25c
--- /dev/null
+++ b/test/th-uri.cfg
@@ -0,0 +1,64 @@
+
+debug=9          # debug level (cmd line: -dddddddddd)
+#fork=yes          # (cmd. line: -D)
+fork=no
+log_stderror=yes  # (cmd line: -E)
+#log_stderror=no   # (cmd line: -E)
+
+
+children=2
+check_via=no      # (cmd. line: -v)
+dns=off           # (cmd. line: -r)
+rev_dns=off       # (cmd. line: -R)
+port=5070
+listen=193.175.132.142
+# for more info: sip_router -h
+
+#modules
+loadmodule "modules/print/print.so"
+loadmodule "modules/textops/textops.so"
+loadmodule "modules/maxfwd/maxfwd.so"
+loadmodule "modules/sl/sl.so"
+loadmodule "modules/tm/tm.so"
+loadmodule "modules/im/im.so"
+loadmodule "modules/sms/sms.so"
+
+
+modparam("sms","modems","Falcom [d=/dev/ttyS1;b=9600;p=9254;m=new;l=2;r=1] ")
+modparam("sms","networks","D1[c=491710765000;m=10]")
+modparam("sms","links","Falcom[D1] ")
+#modparam("sms","domain","hope.fokus.gmd.de")
+modparam("sms","max_sms_parts",3)
+modparam("sms","use_contact",1)
+modparam("sms","sms_report_type",2)
+
+route{
+	if ( !mf_process_maxfwd_header("10") )
+	{
+		sl_send_reply("483","To Many Hops");
+		drop();
+	};
+
+	if (uri=~"sip:(\+[0-9]+@)?fesarius\.fokus\.gmd\.de"
+	  | uri=~"sip:(\+[0-9]+@)?193\.175\.132\.142")
+	{
+		if (method=="MESSAGE")
+		{
+			log("MESSAGE received -> sending as sms\n");
+			if (sms_send_msg_to_net("D1"))
+			{
+				sl_send_reply("200","Accepted");
+			}else{
+				sl_send_reply("502","Bad gateway");
+			};
+		}else{
+			log("NON_Message request received for sms gateway->dropt!\n");
+			sl_send_reply("501","Not implemented");
+		};
+		break;
+	};
+
+
+	sl_send_reply("502","Not Implemented");
+	#forward(uri:host,uri:port);
+}
diff --git a/test/tp.cfg b/test/tp.cfg
new file mode 100644
index 0000000..ee6098b
--- /dev/null
+++ b/test/tp.cfg
@@ -0,0 +1,40 @@
+debug=9          # debug level (cmd line: -dddddddddd)
+log_stderror=yes # (cmd line: -E)
+check_via=yes     # (cmd. line: -v)
+dns=on           # (cmd. line: -r)
+rev_dns=yes      # (cmd. line: -R)
+fork=no          # (cmd. line: -D)
+port=5080
+listen=192.168.99.100
+loop_checks=1
+# for more info: sip_router -h
+
+#modules
+loadmodule "modules/print/print.so"
+#loadmodule "modules/tm/tm.so"
+
+route{
+	if ( t_lookup_request()) {
+		if ( method=="ACK" )	{
+			t_release();
+			forward(195.37.77.100, 5090 );
+# once it supports ACK too
+#			t_forward(195.37.77.100, 5090 );
+		} else {
+			t_retransmit_reply();
+		};
+	} else {
+		if (method=="ACK") {
+			forward(195.37.77.100, 5090 );
+		} else {
+			t_add_transaction();
+			if (method=="CANCEL") {
+				t_send_reply( "200", "glad to cancel");
+			} else {
+				t_send_reply("100", "trying -- your call is important to us");
+			};
+			t_forward("195.37.77.100", "5090" );
+		};
+	};
+		
+}
diff --git a/test/transaction.fifo b/test/transaction.fifo
new file mode 100644
index 0000000..a555f9e
--- /dev/null
+++ b/test/transaction.fifo
@@ -0,0 +1,13 @@
+:t_uac_from:hh
+MESSAGE
+sip:faker at foo.bar
+sip:gh at iptel.org
+foo: bar
+x: y
+p_header: p_value
+Contact: <sip:195.37.77.100:9>
+Content-Type: text/plain; charset=UTF-8
+
+I love you man!!!!
+.
+
diff --git a/test/travis/build_deps.sh b/test/travis/build_deps.sh
new file mode 100755
index 0000000..10387b2
--- /dev/null
+++ b/test/travis/build_deps.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+#
+# build_deps script for travis CI
+# installs the build_deps packages needed to build Kamailio
+# environment based on Ubuntu 12.04 LTS (precise)
+#
+DIST=${1:-precise}
+BASE_DIR=${2:-$(pwd)}
+CONTROL_FILE="${BASE_DIR}/pkg/kamailio/deb/${DIST}/control"
+if ! [ -f "${CONTROL_FILE}" ]; then
+	echo "Error: No ${CONTROL_FILE} found"
+	exit 1
+fi
+
+BUILD_DEPS=$(/usr/bin/gdebi --quiet --non-interactive \
+	--option=APT::Install-Recommends=false \
+	--apt-line ${CONTROL_FILE})
+if [ -z "${BUILD_DEPS}" ]; then
+	echo "Error: no build deps packages resolved"
+	exit 2
+fi
+
+apt-get install -y $BUILD_DEPS
diff --git a/test/travis/build_travis.sh b/test/travis/build_travis.sh
new file mode 100755
index 0000000..04b4b2c
--- /dev/null
+++ b/test/travis/build_travis.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+#
+# build script for travis CI
+# environment based on Ubuntu 12.04 LTS (precise)
+#
+export JAVA_HOME="/usr/lib/jvm/java-gcj"
+EXCLUDED_MODULES=""
+EXTRA_EXCLUDED_MODULES="bdb dbtext oracle pa iptrtpproxy mi_xmlrpc dnssec kazoo cnxcc"
+PACKAGE_GROUPS="mysql postgres berkeley unixodbc radius presence ldap xml perl utils lua memcached \
+	snmpstats carrierroute xmpp cpl redis python geoip\
+	sqlite json mono ims sctp java \
+	purple tls outbound websocket autheph"
+export TESTS_EXCLUDE="3 12 17 19 20 23 25 26 30 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 50"
+echo "make cfg"
+make FLAVOUR=kamailio cfg \
+	skip_modules="${EXCLUDED_MODULES} ${EXTRA_EXCLUDED_MODULES}" \
+	group_include="kstandard"
+echo "make all"
+make all
+echo "make groups"
+for grp in ${PACKAGE_GROUPS}; do
+	make every-module group_include="k${grp}"
+done
+#echo "unit tests"
+#make -C test/unit
+if [[ "$CC" =~ "gcc" ]] ; then
+	echo "make install"
+	sudo make install
+else
+	echo "skip make install step"
+fi
diff --git a/test/travis/databases_travis.sh b/test/travis/databases_travis.sh
new file mode 100755
index 0000000..0ee7213
--- /dev/null
+++ b/test/travis/databases_travis.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+# create MySQL and PostgreSQL kamailio databases
+
+cd utils/kamctl
+PWSKIP=yes CHARSET=latin1 DBENGINE=MYSQL DBNAME=kamailio INSTALL_EXTRA_TABLES=yes \
+  INSTALL_PRESENCE_TABLES=yes INSTALL_DBUID_TABLES=yes \
+  ./kamdbctl create
+touch ~/.pgpass; chmod 600 ~/.pgpass
+PWSKIP=yes DBENGINE=PGSQL DBNAME=kamailio INSTALL_EXTRA_TABLES=yes \
+  INSTALL_PRESENCE_TABLES=yes INSTALL_DBUID_TABLES=yes \
+  ./kamdbctl create
diff --git a/test/tx.cfg b/test/tx.cfg
new file mode 100644
index 0000000..a2ac819
--- /dev/null
+++ b/test/tx.cfg
@@ -0,0 +1,44 @@
+#
+# configuration for stress testing
+#
+#
+
+debug=3          # debug level (cmd line: -dddddddddd)
+fork=yes          # (cmd. line: -D)
+#fork=no
+#log_stderror=yes # (cmd line: -E)
+log_stderror=yes	# (cmd line: -E)
+
+
+children=8
+check_via=no     # (cmd. line: -v)
+#dns=on           # (cmd. line: -r)
+#rev_dns=yes      # (cmd. line: -R)
+port=5080
+#listen=127.0.0.1
+listen=195.37.77.101
+loop_checks=0
+# for more info: sip_router -h
+
+#modules
+loadmodule "modules/print/print.so"
+loadmodule "modules/tm/tm.so"
+
+#route[0]{
+#	if (method=="BYE") { forward("bat.iptel.org", 5000); }
+#	else forward("bat.iptel.org", 5090);
+#	else t_forward("bat.iptel.org", "9" );
+#	break;
+#}
+
+route[0]{
+	log("SER: new request reveived\n");
+	if (method=="BYE") {
+		t_relay_to( "bat.iptel.org", "5000" );
+	}
+	else {
+		t_relay_to( "bat.iptel.org", "5090" );
+	};
+#	break;
+}
+
diff --git a/test/udp.c b/test/udp.c
new file mode 100644
index 0000000..9c33322
--- /dev/null
+++ b/test/udp.c
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2002-2003 FhG Fokus
+ *
+ * This file is sipsak, a free sip testing tool.
+ *
+ * sipsak is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * sipsak is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * Copyright (C) 2001-2003 FhG Fokus
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+
+/* sipsak written by nils ohlmeier (develop at ohlmeier.de).
+   based up on a modified version of shoot.
+   set DEBUG on compile will produce much more output. primarily
+   it will print out the sent and received messages before or after
+   every network action.
+*/
+
+/* changes by jiri at iptel.org; now messages can be really received;
+   status code returned is 2 for some local errors , 0 for success
+   and 1 for remote error -- ICMP/timeout; can be used to test if
+   a server is alive; 1xx messages are now ignored; windows support
+   dropped
+*/
+
+/*
+shot written by ashhar farhan, is not bound by any licensing at all.
+you are free to use this code as you deem fit. just dont blame the author
+for any problems you may have using it.
+bouquets and brickbats to farhan at hotfoon.com
+*/
+
+/* TO-DO:
+   - support for short notation
+   - support for IPv6
+*/
+
+//set ts=4 :-)
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <string.h>
+#include <ctype.h>
+#include <time.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <sys/socket.h>
+#include <sys/utsname.h>
+
+#include <regex.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/poll.h>
+
+#include <errno.h>
+
+/* this is the main function with the loops and modes */
+void shoot()
+{
+	struct sockaddr_in	addr, sockname;
+	struct timeval	tv, sendtime, recvtime, firstsendt;
+	struct timezone tz;
+	struct pollfd sockerr;
+	int ssock, redirected, retryAfter;
+	int sock, i, len, ret, usrlocstep, randretrys;
+	int dontsend, cseqcmp, cseqtmp;
+	int rem_rand, rem_namebeg;
+	char *contact, *crlf, *foo, *bar;
+	fd_set	fd;
+	socklen_t slen;
+	regex_t redexp, proexp, okexp, tmhexp, errexp;
+	int bsd_compat, opt_size;
+
+	int nretries=3;
+	char *buff="MiniTest";
+
+
+	/* create a sending socket */
+	sock = (int)socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
+	if (sock==-1) {
+		perror("no client socket");
+		exit(2);
+	}
+
+
+#ifndef _NO_LISTENER
+    /* create a listening socket */
+    ssock = (int)socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
+    if (ssock==-1) {
+        perror("no server socket");
+        exit(2);
+    }
+
+    sockname.sin_family=AF_INET;
+    sockname.sin_addr.s_addr = htonl( INADDR_ANY );
+    sockname.sin_port = htons((short)47437);
+    if (bind( ssock, (struct sockaddr *) &sockname, sizeof(sockname) )==-1) {
+        perror("no bind");
+        exit(2);
+    }
+#endif
+
+
+	/* destination socket init here because it could be changed in a 
+	   case of a redirect */
+	addr.sin_addr.s_addr = inet_addr("192.168.99.100");
+	addr.sin_port = htons((short)888);
+	addr.sin_family = AF_INET;
+
+	/* if we dont connect, even on Linux, nothing will happen */
+
+#ifdef CONNECTED	
+	/* we connect as per the RFC 2543 recommendations
+	   modified from sendto/recvfrom */
+	ret = connect(sock, (struct sockaddr *)&addr, sizeof(addr));
+	if (ret==-1) {
+		perror("no connect");
+		exit(2);
+	}
+#endif
+
+	if (getsockopt( sock, SOL_SOCKET, SO_BSDCOMPAT, &bsd_compat, &opt_size )==-1) {
+		perror("ERROR");
+		exit(1);
+	}
+	printf("BSD compat: %d\n", bsd_compat);
+
+	/* here we go for the number of nretries which heavily depends on the 
+	   mode */
+	for (i = 0; i <= nretries; i++)
+	{
+		/* lets fire the request to the server and store when we did */
+
+		/* if we send too fast, ICMP will arrive back when we are already
+		   done and we wont be able to recognize an error
+		*/
+#ifdef CONNECTED
+		ret = send(sock, buff, strlen(buff), 0);
+#else
+		ret=sendto(sock, buff, strlen(buff), 0, (struct sockaddr *)&addr, sizeof(addr));
+#endif
+		/* wait 1/10 sec to be safe we receive ICMP */
+		usleep(100000);
+		if (ret==-1) {
+			perror("send failure");
+			exit( 1 );
+		}
+	}
+
+	exit(0);
+}
+
+int main(int argc, char *argv[])
+{
+	shoot();
+}
+
diff --git a/test/udp_flood_disc.c b/test/udp_flood_disc.c
new file mode 100644
index 0000000..ea13275
--- /dev/null
+++ b/test/udp_flood_disc.c
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2001-2003 FhG Fokus
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <ctype.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#ifdef __linux__
+#include <linux/types.h>
+#include <linux/errqueue.h>
+#endif
+
+
+static char *id="$Id$";
+static char *version="udp_flood_disc 0.1";
+static char* help_msg="\
+Usage: udp_flood -f file -d address -p port -c count [-v]\n\
+Options:\n\
+    -f file       file with the content of the udp packet (max 65k)\n\
+    -d address    destination address\n\
+    -p port       destination port\n\
+    -c count      number of packets to be sent\n\
+    -v            increase verbosity level\n\
+    -V            version number\n\
+    -h            this help message\n\
+";
+
+#define BUF_SIZE 65535
+
+
+int main (int argc, char** argv)
+{
+	int fd;
+	int sock;
+	char c;
+	int n,r;
+	char* tmp;
+	char* buf[BUF_SIZE];
+	struct hostent* he;
+	struct sockaddr_in addr;
+	
+	int count;
+	int verbose;
+	char *fname;
+	char *dst;
+	int port;
+#ifdef __linux__
+	int optval;
+#endif
+	
+	/* init */
+	count=0;
+	verbose=0;
+	fname=0;
+	dst=0;
+	port=0;
+
+	opterr=0;
+	while ((c=getopt(argc,argv, "f:c:d:p:vhV"))!=-1){
+		switch(c){
+			case 'f':
+				fname=optarg;
+				break;
+			case 'v':
+				verbose++;
+				break;
+			case 'd':
+				dst=optarg;
+				break;
+			case 'p':
+				port=strtol(optarg, &tmp, 10);
+				if ((tmp==0)||(*tmp)){
+					fprintf(stderr, "bad port number: -p %s\n", optarg);
+					goto error;
+				}
+				break;
+			case 'c':
+				count=strtol(optarg, &tmp, 10);
+				if ((tmp==0)||(*tmp)){
+					fprintf(stderr, "bad count: -c %s\n", optarg);
+					goto error;
+				}
+				break;
+			case 'V':
+				printf("version: %s\n", version);
+				printf("%s\n",id);
+				exit(0);
+				break;
+			case 'h':
+				printf("version: %s\n", version);
+				printf("%s", help_msg);
+				exit(0);
+				break;
+			case '?':
+				if (isprint(optopt))
+					fprintf(stderr, "Unknown option `-%c�\n", optopt);
+				else
+					fprintf(stderr, "Unknown character `\\x%x�\n", optopt);
+				goto error;
+			case ':':
+				fprintf(stderr, "Option `-%c� requires an argument.\n",
+						optopt);
+				goto error;
+				break;
+			default:
+					abort();
+		}
+	}
+	
+	/* check if all the required params are present */
+	if (fname==0){
+		fprintf(stderr, "Missing -f file\n");
+		exit(-1);
+	}
+	if (dst==0){
+		fprintf(stderr, "Missing destination (-d ...)\n");
+		exit(-1);
+	}
+	if(port==0){
+		fprintf(stderr, "Missing port number (-p port)\n");
+		exit(-1);
+	}else if(port<0){
+		fprintf(stderr, "Invalid port number (-p %d)\n", port);
+		exit(-1);
+	}
+	if(count==0){
+		fprintf(stderr, "Missing packet count (-c number)\n");
+		exit(-1);
+	}else if(count<0){
+		fprintf(stderr, "Invalid packet count (-c %d)\n", count);
+		exit(-1);
+	}
+	
+	/* open packet file */
+	fd=open(fname, O_RDONLY);
+	if (fd<0){
+		fprintf(stderr, "ERROR: loading packet-file(%s): %s\n", fname,
+				strerror(errno));
+		goto error;
+	}
+	n=read(fd, buf, BUF_SIZE);
+	if (n<0){
+		fprintf(stderr, "ERROR: reading file(%s): %s\n", fname,
+				strerror(errno));
+		goto error;
+	}
+	if (verbose) printf("read %d bytes from file %s\n", n, fname);
+	close(fd);
+
+	/* resolve destination */
+	he=gethostbyname(dst);
+	if (he==0){
+		fprintf(stderr, "ERROR: could not resolve %s\n", dst);
+		goto error;
+	}
+	/* open socket*/
+	addr.sin_family=he->h_addrtype;
+	addr.sin_port=htons(port);
+	memcpy(&addr.sin_addr.s_addr, he->h_addr_list[0], he->h_length);
+	
+	sock = socket(he->h_addrtype, SOCK_DGRAM, 0);
+	if (sock==-1){
+		fprintf(stderr, "ERROR: socket: %s\n", strerror(errno));
+		goto error;
+	}
+#ifdef __linux__
+	/* enable error receiving on unconnected sockets*/
+	optval=1;
+	if(setsockopt(sock,SOL_IP,IP_RECVERR,(void*)&optval,sizeof(optval))==-1){
+		fprintf(stderr, "Error: setsockopt: %s\n", strerror(errno));
+		exit(1);
+	}
+#endif
+
+
+	/* flood loop */
+	for (r=0; r<count; r++){
+		if ((verbose>1)&&(r%1000))  putchar('.');
+		if (sendto(sock,buf, n, 0, (struct sockaddr*) &addr, sizeof(addr))==-1)
+		{
+			fprintf(stderr, "Error: send: %s\n",  strerror(errno));
+			exit(1);
+		}
+	}
+	printf("\n%d packets sent, %d bytes each => total %d bytes\n",
+			count, n, n*count);
+
+	close(sock);
+	exit(0);
+
+error:
+	exit(-1);
+}
diff --git a/test/udp_test_proxy.c b/test/udp_test_proxy.c
new file mode 100644
index 0000000..23a65fe
--- /dev/null
+++ b/test/udp_test_proxy.c
@@ -0,0 +1,247 @@
+/* 
+ * Copyright (C) 2001-2003 FhG Fokus
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <ctype.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+
+
+static char *id="$Id$";
+static char *version="udp_test_proxy 0.1";
+static char* help_msg="\
+Usage: udp_test_proxy  -l address -s port -d address -p port [-n no] [-v]\n\
+Options:\n\
+    -l address    listen address\n\
+    -s port       listen(source) port\n\
+    -d address    destination address\n\
+    -p port       destination port\n\
+    -n no         number of processes\n\
+    -2            use a different socket for sending\n\
+    -v            increase verbosity level\n\
+    -V            version number\n\
+    -h            this help message\n\
+";
+#define BUF_SIZE 65535
+static char buf[BUF_SIZE];
+
+int main(int argc, char** argv)
+{
+	int sock;
+	int s_sock;
+	pid_t pid;
+	struct sockaddr_in addr;
+	struct sockaddr_in to;
+	int r, n, len;
+	char c;
+	struct hostent* he;
+	int verbose;
+	int sport, dport;
+	char *dst;
+	char *src;
+	char* tmp;
+	int use_diff_ssock;
+
+
+	/* init */
+	verbose=0;
+	dst=0;
+	sport=dport=0;
+	src=dst=0;
+	n=0;
+	use_diff_ssock=0;
+	
+	opterr=0;
+	while ((c=getopt(argc,argv, "l:p:d:s:n:2vhV"))!=-1){
+		switch(c){
+			case '2':
+				use_diff_ssock=1;
+				break;
+			case 'v':
+				verbose++;
+				break;
+			case 'd':
+				dst=optarg;
+				break;
+			case 'l':
+				src=optarg;
+				break;
+			case 'p':
+				dport=strtol(optarg, &tmp, 10);
+				if ((tmp==0)||(*tmp)){
+					fprintf(stderr, "bad port number: -p %s\n", optarg);
+					goto error;
+				}
+				break;
+			case 's':
+				sport=strtol(optarg, &tmp, 10);
+				if ((tmp==0)||(*tmp)){
+					fprintf(stderr, "bad port number: -s %s\n", optarg);
+					goto error;
+				}
+				break;
+			case 'n':
+				n=strtol(optarg, &tmp, 10);
+				if ((tmp==0)||(*tmp)){
+					fprintf(stderr, "bad process number: -n %s\n", optarg);
+					goto error;
+				}
+				break;
+			case 'V':
+				printf("version: %s\n", version);
+				printf("%s\n",id);
+				exit(0);
+				break;
+			case 'h':
+				printf("version: %s\n", version);
+				printf("%s", help_msg);
+				exit(0);
+				break;
+			case '?':
+				if (isprint(optopt))
+					fprintf(stderr, "Unknown option `-%c�\n", optopt);
+				else
+					fprintf(stderr, "Unknown character `\\x%x�\n", optopt);
+				goto error;
+			case ':':
+				fprintf(stderr, "Option `-%c� requires an argument.\n",
+						optopt);
+				goto error;
+				break;
+			default:
+					abort();
+		}
+	}
+
+	/* check if all the required params are present */
+	if (dst==0){
+		fprintf(stderr, "Missing destination (-d ...)\n");
+		exit(-1);
+	}
+	if (src==0){
+		fprintf(stderr, "Missing listen address (-l ...)\n");
+		exit(-1);
+	}
+	if(sport==0){
+		fprintf(stderr, "Missing source port number (-s port)\n");
+		exit(-1);
+	}else if(sport<0){
+		fprintf(stderr, "Invalid source port number (-s %d)\n", sport);
+		exit(-1);
+	}
+	if(dport==0){
+		fprintf(stderr, "Missing destination port number (-p port)\n");
+		exit(-1);
+	}else if(dport<0){
+		fprintf(stderr, "Invalid destination port number (-p %d)\n", dport);
+		exit(-1);
+	}
+	if(n<0){
+		fprintf(stderr, "Invalid process no (-n %d)\n", n);
+		exit(-1);
+	}
+
+
+	/* resolve destination */
+	he=gethostbyname(dst);
+	if (he==0){
+		fprintf(stderr, "ERROR: could not resolve %s\n", dst);
+		goto error;
+	}
+
+	/* set to*/
+	to.sin_family=he->h_addrtype;
+	to.sin_port=htons(dport);
+	memcpy(&to.sin_addr.s_addr, he->h_addr_list[0], he->h_length);
+
+	/* resolve source/listen */
+	he=gethostbyname(src);
+	if (he==0){
+		fprintf(stderr, "ERROR: could not resolve %s\n", dst);
+		goto error;
+	}
+	/* open socket*/
+	addr.sin_family=he->h_addrtype;
+	addr.sin_port=htons(sport);
+	memcpy(&addr.sin_addr.s_addr, he->h_addr_list[0], he->h_length);
+
+	s_sock=-1;
+	sock = socket(he->h_addrtype, SOCK_DGRAM, 0);
+	if (use_diff_ssock && (sock!=-1))
+		s_sock = socket(he->h_addrtype, SOCK_DGRAM, 0);
+	else
+		s_sock=sock;
+	
+	if ((sock==-1)||(s_sock==-1)){
+		fprintf(stderr, "ERROR: socket: %s\n", strerror(errno));
+		goto error;
+	}
+	if (bind(sock, (struct sockaddr*) &addr, sizeof(struct sockaddr_in))==-1){
+		fprintf(stderr, "ERROR: bind: %s\n", strerror(errno));
+		goto error;
+	}
+	if (use_diff_ssock){
+		if (connect(s_sock, (struct sockaddr*) &to,
+					sizeof(struct sockaddr_in))==-1){
+			fprintf(stderr, "ERROR: connect: %s\n", strerror(errno));
+			goto error;
+		}
+	}
+
+	for(r=1; r<n; r++){
+		if ((pid=fork())==-1){
+			fprintf(stderr, "ERROR: fork: %s\n", strerror(errno));
+			goto error;
+		}
+		if (pid==0) break; /* child, skip */
+	}
+
+	if (verbose>3) printf("process starting\n");
+	for(;;){
+		len=read(sock, buf, BUF_SIZE);
+		if (len==-1){
+			fprintf(stderr, "ERROR: read: %s\n", strerror(errno));
+			continue;
+		}
+		if (verbose>2) putchar('r');
+		/* send it back*/
+		if (use_diff_ssock)
+			len=send(s_sock, buf, len, 0);
+		else
+			len=sendto(s_sock, buf, len, 0,
+					(struct sockaddr*) &to, sizeof(struct sockaddr_in));
+		if (len==-1){
+			fprintf(stderr, "ERROR: send: %s\n", strerror(errno));
+			continue;
+		}
+		if (verbose>1) putchar('.');
+	}
+error:
+	exit(-1);
+}
diff --git a/test/unit/1.sh b/test/unit/1.sh
new file mode 100755
index 0000000..3556392
--- /dev/null
+++ b/test/unit/1.sh
@@ -0,0 +1,37 @@
+#!/bin/bash
+# load a minimal config
+
+# Copyright (C) 2007 1&1 Internet AG
+#
+# This file is part of Kamailio, a free SIP server.
+#
+# Kamailio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version
+#
+# Kamailio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+source include/common
+
+CFG=1.cfg
+
+# setup config
+echo -e "debug=2\nrequest_route {\n ; \n}" > $CFG
+
+$BIN -w . -f $CFG > /dev/null
+ret=$?
+
+sleep 1
+$KILL
+
+rm -f $CFG
+
+exit $ret
diff --git a/test/unit/10.sh b/test/unit/10.sh
new file mode 100755
index 0000000..47bbc9d
--- /dev/null
+++ b/test/unit/10.sh
@@ -0,0 +1,50 @@
+#!/bin/bash
+# test basic db related kamailioctl functionality for dbtext
+
+# Copyright (C) 2007 1&1 Internet AG
+#
+# This file is part of Kamailio, a free SIP server.
+#
+# Kamailio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version
+#
+# Kamailio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+source include/common
+
+cd $CTL_DIR
+
+# setup config file
+cp $CTLRC $CTLRC.bak
+cp $CTL $CTL.bak
+sed -i'' -e "s/# DBENGINE=MYSQL/DBENGINE=DBTEXT/g" $CTLRC
+sed -i'' -e "s/TEST=\"false\"/TEST=\"true\"/g" $CTL
+
+./$CTL avp list > /dev/null
+
+ret=$?
+
+if [ "$ret" -eq 0 ] ; then
+	./$CTL domain showdb > /dev/null
+	ret=$?
+fi ;
+
+if [ "$ret" -eq 0 ] ; then
+	./$CTL dispatcher show > /dev/null
+	ret=$?
+fi ;
+
+# cleanup
+mv $CTLRC.bak $CTLRC
+mv $CTL.bak $CTL
+
+exit $ret
diff --git a/test/unit/11.cfg b/test/unit/11.cfg
new file mode 100644
index 0000000..fc3bc39
--- /dev/null
+++ b/test/unit/11.cfg
@@ -0,0 +1,82 @@
+# ----------- global configuration parameters ------------------------
+debug=2
+fork=yes
+log_stderror=no
+children=1
+disable_tcp=yes
+
+alias=localhost
+
+# ------------------ module loading ----------------------------------
+loadpath "../../modules/"
+
+#!trydef DBMOD	"db_mysql"
+loadmodule DBMOD
+
+loadmodule "tm"
+loadmodule "sl"
+loadmodule "rr"
+loadmodule "maxfwd"
+loadmodule "textops"
+loadmodule "xlog"
+loadmodule "pv"
+loadmodule "mi_fifo"
+modparam("mi_fifo", "fifo_name", "/tmp/kamailio_fifo")
+
+loadmodule "usrloc"
+modparam("usrloc", "db_mode", 1)
+
+loadmodule "registrar"
+modparam("registrar", "min_expires", 5)
+modparam("usrloc", "timer_interval", 1)
+
+#!trydef FETCHROWS	2000
+modparam("usrloc", "fetch_rows", FETCHROWS)
+
+#!trydef DBURL "mysql://kamailio:kamailiorw@localhost/kamailio"
+modparam("usrloc", "db_url", DBURL)
+
+#-------------------------  request routing logic -------------------
+request_route {
+
+	if (!mf_process_maxfwd_header("10")) {
+		sl_send_reply("483","Too Many Hops");
+		exit;
+	}
+
+	if (!method=="REGISTER")
+		record_route();
+
+	if (loose_route()) {
+		# mark routing logic in request
+		append_hf("P-hint: rr-enforced\r\n");
+		route(1);
+	}
+
+	if (!uri==myself) {
+		append_hf("P-hint: outbound\r\n");
+		route(1);
+	}
+
+	if (uri==myself) {
+		if (method=="REGISTER") {
+			save("location");
+			exit;
+		}
+		if (!lookup("location")) {
+			sl_send_reply("404", "Not Found");
+			exit;
+		}
+		append_hf("P-hint: usrloc applied\r\n");
+	}
+
+	route(1);
+}
+
+route[1] {
+	if (!t_relay()) {
+		sl_reply_error();
+	}
+	exit;
+}
+
diff --git a/test/unit/11.sh b/test/unit/11.sh
new file mode 100755
index 0000000..a220bc5
--- /dev/null
+++ b/test/unit/11.sh
@@ -0,0 +1,183 @@
+#!/bin/bash
+# database access and persistent storage for registrar on mysql
+
+# Copyright (C) 2007 1&1 Internet AG
+#
+# This file is part of Kamailio, a free SIP server.
+#
+# Kamailio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version
+#
+# Kamailio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+source include/common
+source include/require
+source include/database
+
+CFG=11.cfg
+
+if ! (check_sipsak && check_kamailio && check_module "db_mysql" && check_mysql); then
+	exit 0
+fi ;
+
+SIPDOMAIN=127.0.0.1
+
+$BIN -w . -f $CFG -a no > /dev/null
+ret=$?
+
+sleep 1
+
+# register two contacts
+sipsak -U -C sip:foobar at 127.0.0.1 -s sip:49721123456789@$SIPDOMAIN -H $SIPDOMAIN > /dev/null 2>&1
+sipsak -U -C sip:foobar1 at 127.0.0.1 -s sip:49721123456789@$SIPDOMAIN -H $SIPDOMAIN > /dev/null 2>&1
+ret=$?
+
+if [ "$ret" -eq 0 ]; then
+	$CTL ul show | grep "AOR:: 49721123456789" > /dev/null
+	ret=$?
+fi;
+
+if [ "$ret" -eq 0 ]; then
+	TMP=`$MYSQL "select COUNT(*) from location where username='49721123456789';" | tail -n 1`
+	if [ "$TMP" -eq 0 ] ; then
+		ret=1
+	fi;
+fi;
+
+if [ "$ret" -eq 0 ]; then
+	# check if the contact is registered
+	sipsak -U -C empty -s sip:49721123456789@$SIPDOMAIN -H $SIPDOMAIN -q "Contact: <sip:foobar at 127.0.0.1>" > /dev/null 2>&1
+	ret=$?
+fi;
+
+if [ "$ret" -eq 0 ]; then
+	# update the registration
+	sipsak -U -C sip:foobar at 127.0.0.1 -s sip:49721123456789@$SIPDOMAIN -H $SIPDOMAIN > /dev/null 2>&1
+	ret=$?
+fi;
+
+if [ "$ret" -eq 0 ]; then
+	# check if we get a hint when we try to unregister a non-existent conctact
+	sipsak -U -C "sip:foobar2 at 127.0.0.1" -s sip:49721123456789@$SIPDOMAIN -H $SIPDOMAIN -x 0 -q "Contact: <sip:foobar at 127.0.0.1>" > /dev/null 2>&1
+	ret=$?
+fi;
+
+if [ "$ret" -eq 0 ]; then
+	# unregister the contact
+	sipsak -U -C "sip:foobar at 127.0.0.1" -s sip:49721123456789@$SIPDOMAIN -H $SIPDOMAIN -x 0 > /dev/null 2>&1
+	ret=$?
+fi;
+
+if [ "$ret" -eq 0 ]; then
+	# unregister the user again should not fail
+	sipsak -U -C "sip:foobar at 127.0.0.1" -s sip:49721123456789@$SIPDOMAIN -H $SIPDOMAIN -x 0 > /dev/null 2>&1
+	ret=$?
+fi;
+
+if [ "$ret" -eq 0 ]; then
+	# check if the other contact is still registered
+	sipsak -U -C empty -s sip:49721123456789@$SIPDOMAIN -H $SIPDOMAIN -q "Contact: <sip:foobar1 at 127.0.0.1>" > /dev/null 2>&1
+	ret=$?
+fi;
+
+if [ "$ret" -eq 0 ]; then
+	# register the other again
+	sipsak -U -C sip:foobar at 127.0.0.1 -s sip:49721123456789@$SIPDOMAIN -H $SIPDOMAIN > /dev/null 2>&1
+	ret=$?
+fi;
+
+if [ "$ret" -eq 0 ]; then
+	# unregister all contacts
+	sipsak -U -C "*" -s sip:49721123456789@$SIPDOMAIN -H $SIPDOMAIN -x 0 > /dev/null 2>&1
+	ret=$?
+fi;
+
+if [ "$ret" -eq 0 ]; then
+	# let the timer cleanup the previous registrations
+	sleep 2
+	$CTL ul show | grep "AOR:: 49721123456789" > /dev/null
+	ret=$?
+	if [ "$ret" -eq 0 ]; then
+		ret=1
+	else
+		ret=0
+	fi;
+fi ;
+
+if [ "$ret" -eq 0 ]; then
+	ret=`$MYSQL "select COUNT(*) from location where username='49721123456789';" | tail -n 1`
+fi;
+
+if [ "$ret" -eq 0 ]; then
+	# test min_expires functionality
+	sipsak -U -C sip:foobar at 127.0.0.1 -s sip:49721123456789@$SIPDOMAIN -H $SIPDOMAIN -x 2 > /dev/null 2>&1
+	ret=$?
+fi;
+
+if [ "$ret" -eq 0 ]; then
+	sleep 3
+	# check if the contact is still registered
+	sipsak -U -C empty -s sip:49721123456789@$SIPDOMAIN -H $SIPDOMAIN -q "Contact: <sip:foobar at 127.0.0.1>" > /dev/null 2>&1
+	ret=$?
+fi;
+
+if [ "$ret" -eq 0 ]; then
+	# register a few more contacts
+	sipsak -U -e 9 -s sip:49721123456789@$SIPDOMAIN -H $SIPDOMAIN > /dev/null 2>&1
+fi;
+
+if [ "$ret" -eq 0 ]; then
+	# let the timer cleanup the previous registrations
+	sleep 3
+	# and check
+	TMP=`$MYSQL "select COUNT(*) from location where username like '49721123456789%';" | tail -n 1`
+	if [ "$TMP" -eq 10 ] ; then
+		ret=0
+	else
+		ret=1
+	fi;
+fi;
+
+$MYSQL "delete from location where username like '49721123456789%';"
+
+if [ "$ret" -eq 0 ]; then
+	# register again
+	sipsak -U -C sip:foobar at 127.0.0.1 -s sip:49721123456789@$SIPDOMAIN -H $SIPDOMAIN > /dev/null 2>&1
+	ret=$?
+fi;
+
+$KILL
+
+# restart to test preload_udomain functionality
+$BIN -w . -f $CFG -a no> /dev/null
+ret=$?
+
+sleep 1
+
+if [ "$ret" -eq 0 ]; then
+	# check if the contact is still registered
+	sipsak -U -C empty -s sip:49721123456789@$SIPDOMAIN -H $SIPDOMAIN -q "Contact: <sip:foobar at 127.0.0.1>" > /dev/null 2>&1
+	ret=$?
+fi;
+
+# check if the methods value is correct
+if [ "$ret" -eq 0 ]; then
+	$CTL ul show | grep "Methods:: 4294967295" > /dev/null
+	ret=$?
+fi;
+
+# cleanup
+$MYSQL "delete from location where username like '49721123456789%';"
+
+$KILL
+
+exit $ret
diff --git a/test/unit/12.cfg b/test/unit/12.cfg
new file mode 100644
index 0000000..5a4b6d8
--- /dev/null
+++ b/test/unit/12.cfg
@@ -0,0 +1,108 @@
+log_stderror=yes
+listen=127.0.0.1
+loadpath "../../modules/"
+loadmodule "../../modules/db_mysql/db_mysql.so"
+loadmodule "../../modules/tm/tm.so"
+loadmodule "sl"
+loadmodule "rr"
+loadmodule "maxfwd"
+loadmodule "textops"
+loadmodule "xlog"
+loadmodule "usrloc"
+loadmodule "registrar"
+loadmodule "pv"
+loadmodule "mi_fifo"
+modparam("mi_fifo", "fifo_name", "/tmp/kamailio_fifo")
+
+request_route {
+	xlog("received by kamailio[$pp] at '$Tf' from $si:$sp, method: $(rm{s.tolower}), transport: $rP:$Ri:$rp, user agent: $ua\n");
+
+	if !(route(39)) {
+		xlog("L_ERR", "Error getting identity\n");
+		exit;
+	}
+	xlog("L_ERR", "My identity: $avp(i:83)\n");
+	$var(x) = "sip:" + $fU +"@" + $td;
+	xlog("var(x): $var(x), MD5 var(x): $(var(x){s.md5})\n");
+
+	if (!method=="REGISTER")
+		record_route();
+
+	if (loose_route()) {
+		# mark routing logic in request
+		append_hf("P-hint: rr-enforced\r\n");
+		route(1);
+	}
+
+	if (!uri==myself) {
+		append_hf("P-hint: outbound\r\n");
+		route(1);
+	}
+	xlog("From header tag: $(hdr(From){param.value,tag})\n");
+	
+	if(is_method("REGISTER")) {
+		if(is_present_hf("Expires")) {
+			xlog("Expires header field present\n");
+			if($(hdr(Expires){s.int}) > 0) {
+				xlog("this is an registration\n");
+			}
+			if($(hdr(Expires){s.int}) == 0) {
+				xlog("this is an unregistration\n");
+			}
+		}
+		if(is_present_hf("Contact")) {
+			xlog("Contact header field present\n");
+			if ($(hdr(Contact){param.value,expires}{s.int}) > 0) {
+				xlog("this is an registration\n");
+			}
+			if ($(ct{param.value,expires}{s.int}) == 0) {
+				xlog("this is an unregistration\n");
+			}
+		}
+	}
+
+	if (uri==myself) {
+		if (method=="REGISTER") {
+			save("location");
+			exit;
+		}
+		if (!lookup("location")) {
+			sl_send_reply("404", "Not Found");
+			exit;
+		}
+		append_hf("P-hint: usrloc applied\r\n");
+	}
+
+	route(1);
+}
+
+route[1] {
+	if (!t_relay()) {
+		sl_reply_error();
+	}
+	exit;
+}
+
+route[39] {
+	if ($ai) {
+		$avp(i:81)=$(ai{uri.user});
+		$avp(i:82)=$(ai{uri.domain});
+		$avp(i:83)=$ai;
+		xlog("L_ERR", "Getting identity from P-Asserted-Identity header\n");
+	} else if ($pu) {
+		$avp(i:81)=$(pu{uri.user});
+		$avp(i:82)=$(pu{uri.domain});
+		$avp(i:83)=$pu;
+		xlog("L_ERR", "Getting identity from P-Preferred-Identity header\n");
+	} else if ($fU) {
+		$avp(i:81)=$(fu{uri.user});
+		$avp(i:82)=$(fu{uri.domain});
+		$avp(i:83)=$fu;
+		xlog("L_ERR", "Getting identity from FROM URI\n");
+	} else {
+		xlog("L_ERR", "No identity for $rm: $fu -> $ru\n");
+		return;# -1;
+	}
+
+	return; #1;
+}
diff --git a/test/unit/12.sh b/test/unit/12.sh
new file mode 100755
index 0000000..b3438b8
--- /dev/null
+++ b/test/unit/12.sh
@@ -0,0 +1,90 @@
+#!/bin/bash
+# configuration with pseudo-variables, transformations and xlog output
+
+# Copyright (C) 2007 1&1 Internet AG
+#
+# This file is part of Kamailio, a free SIP server.
+#
+# Kamailio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version
+#
+# Kamailio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+source include/common
+source include/require
+
+CFG=12.cfg
+TMPFILE=`mktemp -t kamailio-test.XXXXXXXXXX`
+
+if ! (check_netcat && check_kamailio); then
+	exit 0
+fi ;
+
+$BIN -w . -f $CFG &> $TMPFILE
+ret=$?
+
+sleep 1
+
+
+if [ "$ret" -eq 0 ] ; then
+	# register a user
+	cat register.sip | nc -q 1 -u localhost 5060 > /dev/null
+	$CTL ul show | grep "AOR:: 1000" > /dev/null
+	ret=$?
+	# unregister the user
+	cat unregister.sip | nc -q 1 -u localhost 5060 > /dev/null
+fi ;
+
+
+if [ "$ret" -eq 0 ] ; then
+	$CTL ul show | grep "AOR:: 1000" > /dev/null
+	ret=$?
+	if [ "$ret" -eq 0 ] ; then
+		ret=1
+	else
+		ret=0
+	fi ;
+fi ;
+
+if [ "$ret" -eq 0 ] ; then
+	grep "method: register, transport: UDP:127.0.0.1:5060, user agent: Twinkle/1.0"  $TMPFILE > /dev/null
+	ret=$?
+	if [ "$ret" -eq 0 ] ; then
+		grep "Getting identity from FROM URI" $TMPFILE > /dev/null
+		ret=$?
+		if [ "$ret" -eq 0 ] ; then
+			grep "My identity: sip:1000 at 127.0.0.1" $TMPFILE > /dev/null
+			ret=$?
+			if [ "$ret" -eq 0 ] ; then
+				grep "var(x): sip:1000 at 127.0.0.1, MD5 var(x): b6c3d120cfd9e85addf64ee8943f4eec" $TMPFILE > /dev/null
+				ret=$?
+				if [ "$ret" -eq 0 ] ; then
+					grep "Contact header field present" $TMPFILE > /dev/null
+					ret=$?
+					if [ "$ret" -eq 0 ] ; then
+						grep "this is an registration" $TMPFILE > /dev/null
+						ret=$?
+						if [ "$ret" -eq 0 ] ; then
+							grep "this is an unregistration" $TMPFILE > /dev/null
+							ret=$?
+						fi;
+					fi ;
+				fi ;
+			fi ;
+		fi ;
+	fi ;
+fi ;
+cat $TMPFILE
+$KILL
+rm $TMPFILE
+
+exit $ret
\ No newline at end of file
diff --git a/test/unit/13.cfg b/test/unit/13.cfg
new file mode 100644
index 0000000..ae2a69c
--- /dev/null
+++ b/test/unit/13.cfg
@@ -0,0 +1,52 @@
+debug=2
+loadpath "../../modules/"
+loadmodule "db_mysql"
+loadmodule "corex"
+loadmodule "tm"
+loadmodule "sl"
+loadmodule "xlog"
+loadmodule "maxfwd"
+loadmodule "carrierroute"
+loadmodule "pv"
+loadmodule "tmx"
+loadmodule "mi_fifo"
+
+modparam("carrierroute", "config_source", "db")
+
+modparam("mi_fifo", "fifo_name", "/tmp/kamailio_fifo")
+
+request_route {
+	# initial sanity checks
+	if (!mf_process_maxfwd_header("10")) {
+		sl_send_reply("483","Too Many Hops");
+		return;
+	};
+	cr_user_carrier("$fU", "$fd", "$avp(s:11)");
+	$avp(s:10)="start";
+	if (!cr_route("$avp(s:11)", "$avp(s:10)", "$rU", "$rU", "call_id", "$avp(s:12)")) {
+		xlog("L_ERR", "cr_route failed\n");
+		exit;
+	}
+	t_on_failure("1");
+	if (!t_relay()) {
+		sl_reply_error();
+	}
+}
+
+failure_route[1] {
+	revert_uri();
+	if (!cr_next_domain("$avp(s:11)", "$avp(s:10)", "$rU", "$avp(s:12)", "$T_reply_code", "$avp(s:10)")) {
+		xlog("L_ERR", "cr_next_domain failed\n");
+		exit;
+	}
+	if (!cr_route("$avp(s:11)", "$avp(s:10)", "$rU", "$rU", "call_id", "$avp(s:12)")) {
+		xlog("L_ERR", "cr_route failed\n");
+		exit;
+	}
+	t_on_failure("1");
+	append_branch();
+	if (!t_relay()) {
+		xlog("L_ERR", "t_relay failed\n");
+		exit;
+	}
+}
diff --git a/test/unit/13.sh b/test/unit/13.sh
new file mode 100755
index 0000000..25797a7
--- /dev/null
+++ b/test/unit/13.sh
@@ -0,0 +1,127 @@
+#!/bin/bash
+# loads a carrierroute config for loadbalancing from mysql database
+
+# Copyright (C) 2007 1&1 Internet AG
+#
+# This file is part of Kamailio, a free SIP server.
+#
+# Kamailio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version
+#
+# Kamailio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+source include/common
+source include/require
+source include/database
+
+CFG=13.cfg
+
+if ! (check_kamailio && check_module "carrierroute" && check_module "db_mysql" && check_mysql); then
+	exit 0
+fi ;
+
+cp $CFG $CFG.bak
+
+# setup database
+$MYSQL "insert into carrier_name (id, carrier) values ('1', 'carrier1');"
+$MYSQL "insert into carrier_name (id, carrier) values ('2', 'default');"
+$MYSQL "insert into carrier_name (id, carrier) values ('3', 'carrier2');"
+
+$MYSQL "insert into domain_name (id, domain) values ('10', 'domain1');"
+$MYSQL "insert into domain_name (id, domain) values ('1', 'domain2');"
+$MYSQL "insert into domain_name (id, domain) values ('2', 'domain3');"
+
+$MYSQL "insert into carrierroute (id, carrier, domain, scan_prefix, prob, strip, rewrite_host) values ('1','1','10','49','0.5','0','host1.local');"
+$MYSQL "insert into carrierroute (id, carrier, domain, scan_prefix, prob, strip, rewrite_host) values ('2','1','10','49','0.5','0','host2.local');"
+$MYSQL "insert into carrierroute (id, carrier, domain, scan_prefix, prob, strip, rewrite_host) values ('3','1','10','42','0.3','0','host3.local');"
+$MYSQL "insert into carrierroute (id, carrier, domain, scan_prefix, prob, strip, rewrite_host) values ('4','1','10','42','0.7','0','host4.local');"
+$MYSQL "insert into carrierroute (id, carrier, domain, scan_prefix, prob, strip, rewrite_host) values ('5','1','10','','0.1','0','host5.local');"
+$MYSQL "insert into carrierroute (id, carrier, domain, scan_prefix, prob, strip, rewrite_host) values ('6','1','1','','0.1','0','host5.local');"
+$MYSQL "insert into carrierroute (id, carrier, domain, scan_prefix, prob, strip, rewrite_host) values ('7','1','2','','0.1','0','host5.local');"
+$MYSQL "insert into carrierroute (id, carrier, domain, scan_prefix, prob, strip, rewrite_host) values ('8','2','10','','1','0','host6.local');"
+$MYSQL "insert into carrierroute (id, carrier, domain, scan_prefix, prob, strip, rewrite_host) values ('9','2','1','','1','0','host6.local');"
+$MYSQL "insert into carrierroute (id, carrier, domain, scan_prefix, prob, strip, rewrite_host) values ('10','2','2','','1','0','host6.local');"
+$MYSQL "insert into carrierroute (id, carrier, domain, scan_prefix, prob, strip, rewrite_host) values ('11','3','10','','1','0','host1.local');"
+
+$MYSQL "insert into carrierfailureroute(id, carrier, domain, scan_prefix, host_name, reply_code, flags,
+mask, next_domain) values ('1', '1', '1', '49', 'host1.local', '404', '0', '0', '2');"
+$MYSQL "insert into carrierfailureroute(id, carrier, domain, scan_prefix, host_name, reply_code, flags,
+mask, next_domain) values ('2', '1', '1', '49', 'host1.local', '4..', '0', '0', '3');"
+$MYSQL "insert into carrierfailureroute(id, carrier, domain, scan_prefix, host_name, reply_code, flags,
+mask, next_domain) values ('3', '2', '1', '49', 'host1.local', '503', '0', '0', '2');"
+$MYSQL "insert into carrierfailureroute(id, carrier, domain, scan_prefix, host_name, reply_code, flags,
+mask, next_domain) values ('4', '2', '2', '49', 'host1.local', '5..', '0', '0', '3');"
+
+$BIN -w . -f $CFG -a no > /dev/null
+
+ret=$?
+
+sleep 1
+
+TMPFILE=`mktemp -t kamailio-test.XXXXXXXXXX`
+
+if [ "$ret" -eq 0 ] ; then
+	$CTL fifo cr_dump_routes > $TMPFILE
+	# cat $TMPFILE
+	ret=$?
+fi ;
+
+if [ "$ret" -eq 0 ] ; then
+	tmp=`grep -v "Printing routing information:
+Printing tree for carrier 'carrier1' (1)
+Printing tree for domain 'domain2' (1)
+      NULL: 100.000 %, 'host5.local': ON, '0', '', '', ''
+Printing tree for domain 'domain3' (2)
+      NULL: 100.000 %, 'host5.local': ON, '0', '', '', ''
+Printing tree for domain 'domain1' (10)
+        42: 70.000 %, 'host4.local': ON, '0', '', '', ''
+        42: 30.000 %, 'host3.local': ON, '0', '', '', ''
+        49: 50.000 %, 'host2.local': ON, '0', '', '', ''
+        49: 50.000 %, 'host1.local': ON, '0', '', '', ''
+      NULL: 100.000 %, 'host5.local': ON, '0', '', '', ''
+Printing tree for carrier 'default' (2)
+Printing tree for domain 'domain2' (1)
+      NULL: 100.000 %, 'host6.local': ON, '0', '', '', ''
+Printing tree for domain 'domain3' (2)
+      NULL: 100.000 %, 'host6.local': ON, '0', '', '', ''
+Printing tree for domain 'domain1' (10)
+      NULL: 100.000 %, 'host6.local': ON, '0', '', '', ''
+Printing tree for carrier 'carrier2' (3)
+Printing tree for domain 'domain1' (10)
+      NULL: 100.000 %, 'host1.local': ON, '0', '', '', ''" $TMPFILE`
+	if [ "$tmp" = "" ] ; then
+		ret=0
+	else
+		ret=1
+	fi ;
+fi ;
+
+$KILL
+
+# cleanup database
+$MYSQL "delete from carrier_name where id = 1;"
+$MYSQL "delete from carrier_name where id = 2;"
+$MYSQL "delete from carrier_name where id = 3;"
+$MYSQL "delete from domain_name where id = 10;"
+$MYSQL "delete from domain_name where id = 1;"
+$MYSQL "delete from domain_name where id = 2;"
+$MYSQL "delete from carrierroute where carrier=1;"
+$MYSQL "delete from carrierroute where carrier=2;"
+$MYSQL "delete from carrierroute where carrier=3;"
+$MYSQL "delete from carrierfailureroute where carrier=1;"
+$MYSQL "delete from carrierfailureroute where carrier=2;"
+$MYSQL "delete from carrierfailureroute where carrier=3;"
+
+mv $CFG.bak $CFG
+rm $TMPFILE
+
+exit $ret
diff --git a/test/unit/14.cfg b/test/unit/14.cfg
new file mode 100644
index 0000000..98ed15a
--- /dev/null
+++ b/test/unit/14.cfg
@@ -0,0 +1,33 @@
+loadpath "../../modules/"
+loadmodule "sl"
+loadmodule "xlog"
+loadmodule "maxfwd"
+loadmodule "carrierroute"
+loadmodule "pv"
+loadmodule "mi_fifo"
+
+modparam("mi_fifo", "fifo_name", "/tmp/kamailio_fifo")
+
+modparam("carrierroute", "config_file", "carrierroute.cfg")
+
+request_route {
+	# initial sanity checks
+	if (!mf_process_maxfwd_header("10")) {
+		sl_send_reply("483","Too Many Hops");
+		return;
+	};
+	if (method == "REGISTER") {
+		if(!cr_route("default", "register", "$rU", "$rU", "call_id", "$avp(s:30)")) {
+			sl_send_reply("403", "Not allowed");
+		}
+		sl_send_reply("200", "OK");
+		return;
+	}
+	if (method == "INVITE") {
+		if(!cr_route("default", "proxy", "$rU", "$rU", "call_id")) {
+			sl_send_reply("403", "Not allowed");
+		}
+		sl_send_reply("100", "Trying");
+		return;
+	}
+}
diff --git a/test/unit/14.sh b/test/unit/14.sh
new file mode 100755
index 0000000..91b90d7
--- /dev/null
+++ b/test/unit/14.sh
@@ -0,0 +1,79 @@
+#!/bin/bash
+# loads a carrierroute config for loadbalancing from config file
+
+# Copyright (C) 2007 1&1 Internet AG
+#
+# This file is part of Kamailio, a free SIP server.
+#
+# Kamailio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version
+#
+# Kamailio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+source include/common
+source include/require
+
+CFG=14.cfg
+
+if ! (check_kamailio && check_module "carrierroute" ); then
+	exit 0
+fi ;
+
+cp $CFG $CFG.bak
+
+$BIN -w . -f $CFG -a no > /dev/null
+ret=$?
+
+sleep 1
+
+TMPFILE=`mktemp -t kamailio-test.XXXXXXXXXX`
+
+if [ "$ret" -eq 0 ] ; then
+	$CTL fifo cr_dump_routes > $TMPFILE
+	ret=$?
+fi ;
+
+if [ "$ret" -eq 0 ] ; then
+	tmp=`grep -v "Printing routing information:
+Printing tree for carrier 'default' (1)
+Printing tree for domain 'register' (1)
+      NULL: 0.000 %, 'test1': OFF, '0', '', '', ''
+      NULL: 50.000 %, 'test2.localdomain': ON, '0', '', '', ''
+      NULL: 50.000 %, 'test3.localdomain': ON, '0', '', '', ''
+Printing tree for domain 'proxy' (2)
+         2: 87.610 %, 'test7.localdomain': ON, '0', '', '', ''
+         2: 12.516 %, 'test8.localdomain': ON, '0', '', '', ''
+        42: 70.070 %, 'test4': ON, '0', '', '', ''
+        42: 20.020 %, 'test5.localdomain': ON, '0', '', '', ''
+        42: 10.010 %, 'test6.localdomain': ON, '0', '', '', ''
+        49: 0.000 %, 'test5.localdomain': OFF, '0', '', '', ''
+        49: 44.444 %, 'test4': ON, '0', '', '', ''
+        49: 55.556 %, 'test6.localdomain': ON, '0', '', '', ''
+Printing tree for domain 'other' (3)
+      NULL: 0.000 %, 'test1': OFF, '0', '', '', ''
+      NULL: 50.000 %, 'test2.localdomain': OFF, '0', '', '', ''
+            Rule is backed up by: test3.localdomain
+      NULL: 50.000 %, 'test3.localdomain': ON, '0', '', '', ''
+            Rule is backup for: test2.localdomain" $TMPFILE`
+	if [ "$tmp" = "" ] ; then
+		ret=0
+	else
+		ret=1
+	fi ;
+fi ;
+
+$KILL
+
+mv $CFG.bak $CFG
+rm -f $TMPFILE
+
+exit $ret
diff --git a/test/unit/15.sh b/test/unit/15.sh
new file mode 100755
index 0000000..04a7a92
--- /dev/null
+++ b/test/unit/15.sh
@@ -0,0 +1,44 @@
+#!/bin/bash
+# load all modules without external dependencies with dbtext
+
+# Copyright (C) 2007 1&1 Internet AG
+#
+# This file is part of Kamailio, a free SIP server.
+#
+# Kamailio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version
+#
+# Kamailio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+source include/common
+source include/require
+
+CFG=15.cfg
+
+if ! (check_kamailio); then
+	exit 0
+fi ;
+
+echo "loadmodule \"../../modules/db_text/db_text.so\"" > $CFG
+cat 2.cfg >> $CFG
+echo "modparam(\"$DB_ALL_MOD\", \"db_url\", \"text://`pwd`/../../utils/kamctl/dbtext/kamailio\")" >> $CFG
+echo -e "\nrequest_route {\n ;\n}" >> $CFG
+
+$BIN -w . -f $CFG -a no > /dev/null
+ret=$?
+
+sleep 1
+$KILL
+
+rm $CFG
+
+exit $ret
diff --git a/test/unit/16.sh b/test/unit/16.sh
new file mode 100755
index 0000000..b239adf
--- /dev/null
+++ b/test/unit/16.sh
@@ -0,0 +1,47 @@
+#!/bin/bash
+# load all modules without external dependencies with postgres
+
+# Copyright (C) 2007 1&1 Internet AG
+#
+# This file is part of Kamailio, a free SIP server.
+#
+# Kamailio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version
+#
+# Kamailio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+source include/common
+source include/require
+
+# Needs a default kamailio database setup for postgres
+
+if ! (check_kamailio && check_module "db_postgres" ); then
+	exit 0
+fi ;
+
+CFG=16.cfg
+
+cp 2.cfg $CFG
+echo "loadmodule \"../../modules/db_postgres/db_postgres.so\"" >> $CFG
+echo "modparam(\"$DB_ALL_MOD\", \"db_url\", \"postgres://kamailioro:kamailioro@localhost/kamailio\")" >> $CFG
+echo -e "\nrequest_route {\n ;\n}" >> $CFG
+
+# start
+$BIN -w . -f $CFG > /dev/null
+ret=$?
+
+sleep 1
+$KILL
+
+rm $CFG
+
+exit $ret
diff --git a/test/unit/17.sh b/test/unit/17.sh
new file mode 100755
index 0000000..c8e1661
--- /dev/null
+++ b/test/unit/17.sh
@@ -0,0 +1,72 @@
+#!/bin/bash
+# load all modules without external dependencies with db_berkeley
+
+# Copyright (C) 2007 1&1 Internet AG
+#
+# This file is part of Kamailio, a free SIP server.
+#
+# Kamailio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version
+#
+# Kamailio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+source include/common
+source include/require
+
+if ! (check_kamailio && check_module "db_berkeley" ); then
+	exit 0
+fi ;
+
+CFG=17.cfg
+
+tmp_name=""$RANDOM"_kamailiodb_tmp"
+
+echo "loadmodule \"../../modules/db_berkeley/db_berkeley.so\"" > $CFG
+cat 2.cfg >> $CFG
+echo "modparam(\"$DB_ALL_MOD\", \"db_url\", \"berkeley://`pwd`/$CTL_DIR/$tmp_name\")" >> $CFG
+echo -e "\nrequest_route {\n ;\n}" >> $CFG
+
+# setup config file
+cp $CTLRC $CTLRC.bak
+
+sed -i'' -e "s/# DBENGINE=MYSQL/DBENGINE=DB_BERKELEY/g" $CTLRC
+sed -i'' -e "s/# INSTALL_EXTRA_TABLES=ask/INSTALL_EXTRA_TABLES=yes/g" $CTLRC
+sed -i'' -e "s/# INSTALL_PRESENCE_TABLES=ask/INSTALL_PRESENCE_TABLES=yes/g" $CTLRC
+sed -i'' -e "s/# INSTALL_DBUID_TABLES=ask/INSTALL_DBUID_TABLES=yes/g" $CTLRC
+
+cp $DBCTL $DBCTL.bak
+sed -i'' -e "s/TEST=\"false\"/TEST=\"true\"/g" $DBCTL
+
+CRT_DIR=`pwd`
+cd $CTL_DIR
+$DBCTL create $tmp_name > /dev/null
+ret=$?
+cd $CRT_DIR
+
+if [ "$ret" -eq 0 ] ; then
+	$BIN -w . -f $CFG -a no > /dev/null
+	ret=$?
+fi ;
+
+sleep 1
+$KILL
+
+# cleanup
+cd $CTL_DIR
+$DBCTL drop $tmp_name > /dev/null
+cd $CRT_DIR
+mv $CTLRC.bak $CTLRC
+mv $DBCTL.bak $DBCTL
+
+rm $CFG
+
+exit $ret
diff --git a/test/unit/18.sh b/test/unit/18.sh
new file mode 100755
index 0000000..0489e14
--- /dev/null
+++ b/test/unit/18.sh
@@ -0,0 +1,50 @@
+#!/bin/bash
+# runs ../kamailio with all command line arguments.
+# ommited options are -h -v -I -c -D -V
+
+# Copyright (C) 2007 1&1 Internet AG
+#
+# This file is part of Kamailio, a free SIP server.
+#
+# Kamailio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version
+#
+# Kamailio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+source include/common
+source include/require
+
+if ! (check_kamailio); then
+	exit 0
+fi ;
+
+# the config file
+CFG=18.cfg
+
+# setup config
+echo -e "debug=3\nrequest_route {\n ;\n}" > $CFG
+
+# start:
+$BIN -f ./$CFG -l 127.0.0.1 -n 0 -r -R -E -d -e -K -T -N 0 -b 23 -m 42 -w . -u $(id -u) -g $(id -g) -P ./pid.out -G ./pgid.out -a no -A TESTDEF > /dev/null 2>&1
+
+ret=$?
+
+sleep 1
+
+# clean up:
+$KILL
+
+rm $CFG
+rm -f ./pid.out
+rm -f ./pgid.out 
+
+exit $ret
diff --git a/test/unit/19.cfg b/test/unit/19.cfg
new file mode 100644
index 0000000..3ee5a85
--- /dev/null
+++ b/test/unit/19.cfg
@@ -0,0 +1,52 @@
+# Kamailio config for lookup / registrar testing
+
+#------------------------Global configuration----------------------------------
+debug=2
+fork=yes
+log_stderror=no
+listen=127.0.0.1
+port=5060
+dns=no
+rev_dns=no
+
+#-----------------------Loading Modules-------------------------------------
+loadpath "../../modules/:../../modules_k/"
+loadmodule "tm"
+loadmodule "db_mysql"
+loadmodule "usrloc"
+loadmodule "registrar/registrar.so"
+loadmodule "sl/sl.so"
+loadmodule "maxfwd/maxfwd.so"
+loadmodule "pv/pv.so"
+#for debugging purposes only
+loadmodule "mi_fifo/mi_fifo.so"
+loadmodule "xlog/xlog.so"
+
+
+#-----------------------Module parameters-------------------------------------
+modparam("mi_fifo", "fifo_name", "/tmp/kamailio_fifo")
+modparam("usrloc", "db_mode", 3)
+modparam("usrloc", "db_url", "mysql://kamailio:kamailiorw@localhost/kamailio")
+
+#-----------------------Routing configuration---------------------------------#
+request_route{
+	if (!mf_process_maxfwd_header("10")) {
+		sl_send_reply("483","Too Many Hops");
+		exit();
+	}
+
+	if (registered("location")) {
+		xlog("contact registered");
+	}
+
+
+	if(!lookup ("location")){
+		sl_send_reply("404", "Not Found");
+		exit;
+	}
+
+	if (!t_relay()) {
+		sl_reply_error();
+	}
+}
+
diff --git a/test/unit/19.sh b/test/unit/19.sh
new file mode 100755
index 0000000..80c2ebd
--- /dev/null
+++ b/test/unit/19.sh
@@ -0,0 +1,50 @@
+#!/bin/bash
+# check user lookup for proxy functionality with usrloc and registrar for mysql
+
+# Copyright (C) 2007 1&1 Internet AG
+#
+# This file is part of Kamailio, a free SIP server.
+#
+# Kamailio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version
+#
+# Kamailio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+source include/common
+source include/require
+source include/database
+
+if ! (check_sipp && check_kamailio && check_module "db_mysql" && check_mysql); then
+	exit 0
+fi ;
+
+CFG=19.cfg
+SRV=5060
+UAS=5070
+UAC=5080
+
+
+# add an registrar entry to the db;
+$MYSQL "INSERT INTO location (ruid,username,contact,socket,user_agent,cseq,q) VALUES (\"kamailio-unit-uid\", \"foo\",\"sip:foo at localhost:$UAS\",\"udp:127.0.0.1:$UAS\",\"kamailio_test\",1,-1);"
+
+$BIN -w . -f $CFG > /dev/null
+sipp -sn uas -bg -i localhost -m 10 -f 2 -p $UAS &> /dev/null
+sipp -sn uac -s foo 127.0.0.1:$SRV -i localhost -m 10 -f 2 -p $UAC &> /dev/null
+
+ret=$?
+
+# cleanup
+killall -9 sipp > /dev/null 2>&1
+$KILL > /dev/null 2>&1
+
+$MYSQL "DELETE FROM location WHERE ((contact = \"sip:foo at localhost:$UAS\") and (user_agent = \"kamailio_test\"));"
+exit $ret;
diff --git a/test/unit/2.cfg b/test/unit/2.cfg
new file mode 100644
index 0000000..d2d7d8a
--- /dev/null
+++ b/test/unit/2.cfg
@@ -0,0 +1,68 @@
+debug=2
+mpath="../../modules/"
+loadmodule "../../modules/tm/tm.so"
+loadmodule "tmx"
+loadmodule "acc"
+loadmodule "alias_db"
+loadmodule "auth"
+loadmodule "auth_db"
+loadmodule "../../modules/avpops/avpops.so"
+loadmodule "benchmark"
+loadmodule "cfgutils"
+loadmodule "dialog"
+loadmodule "dispatcher"
+loadmodule "diversion"
+loadmodule "domain"
+loadmodule "domainpolicy"
+loadmodule "../../modules/enum/enum.so"
+loadmodule "exec"
+loadmodule "../../modules/db_flatstore/db_flatstore.so"
+loadmodule "group"
+loadmodule "htable"
+loadmodule "imc"
+loadmodule "maxfwd"
+loadmodule "mi_datagram"
+loadmodule "mi_fifo"
+loadmodule "msilo"
+loadmodule "nathelper"
+##loadmodule "nat_traversal"
+loadmodule "path"
+loadmodule "pike"
+loadmodule "ratelimit"
+loadmodule "rr"
+##loadmodule "seas"
+##loadmodule "siptrace"
+loadmodule "siputils"
+loadmodule "sl"
+loadmodule "sms"
+loadmodule "speeddial"
+###loadmodule "sst"
+loadmodule "statistics"
+loadmodule "textops"
+loadmodule "uac"
+##loadmodule "uac_redirect"
+loadmodule "uri_db"
+loadmodule "usrloc"
+loadmodule "userblacklist"
+loadmodule "registrar"
+loadmodule "permissions"
+loadmodule "pdt"
+loadmodule "pv"
+loadmodule "../../modules/rtpproxy/rtpproxy.so"
+loadmodule "xlog"
+loadmodule "../../modules/pdb/pdb.so"
+
+modparam("mi_fifo", "fifo_name", "/tmp/kamailio_fifo")
+modparam("mi_datagram", "socket_name", "/tmp/kamailio.sock")
+modparam("dialog", "dlg_flag", 10)
+modparam("dialog", "db_mode", 2)
+##modparam("tm", "fr_inv_timer_avp", "$avp(i:704)")
+modparam("sms", "modems", "Nokia [d=/dev/ttyS1;b=9600;m=new;l=30] ")
+modparam("sms", "networks", "D1 [m=10] ;d2[ m=20]")
+modparam("sms", "links", "NOKIA[D1;d2]")
+###modparam("sst", "sst_flag", 6)
+modparam("usrloc", "nat_bflag", 15)
+modparam("uri_db", "use_uri_table", 1)
+modparam("uri_db", "db_table", "uri")
+modparam("avpops", "avp_table", "usr_preferences")
+modparam("pdb", "server", "localhost:10001")
diff --git a/test/unit/2.sh b/test/unit/2.sh
new file mode 100755
index 0000000..71ba85d
--- /dev/null
+++ b/test/unit/2.sh
@@ -0,0 +1,52 @@
+#!/bin/bash
+# load all modules without external dependencies with mysql
+
+# Copyright (C) 2007 1&1 Internet AG
+#
+# This file is part of Kamailio, a free SIP server.
+#
+# Kamailio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version
+#
+# Kamailio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+# Needs a default kamailio database setup for mysql
+
+source include/common
+source include/require
+source include/database
+
+CFG=2.cfg
+
+if ! (check_kamailio && check_module "db_mysql" && check_mysql); then
+	exit 0
+fi ;
+
+cp $CFG $CFG.bak
+
+touch dispatcher.list
+
+echo "loadmodule \"$SRC_DIR/modules/db_mysql/db_mysql.so\"" >> $CFG
+echo "modparam(\"dispatcher\", \"list_file\", \"$SRC_DIR/$TEST_DIR/dispatcher.list\")" >> $CFG
+echo -e "\nrequest_route {\n ;\n}" >> $CFG
+
+# start
+$BIN -w . -f $CFG > /dev/null
+ret=$?
+
+sleep 1
+$KILL
+
+mv $CFG.bak $CFG
+rm -f dispatcher.list
+
+exit $ret
diff --git a/test/unit/20.cfg b/test/unit/20.cfg
new file mode 100644
index 0000000..8ef225f
--- /dev/null
+++ b/test/unit/20.cfg
@@ -0,0 +1,54 @@
+# Kamailio config for lookup / registrar testing
+
+#------------------------Global configuration----------------------------------
+debug=3
+fork=yes
+log_stderror=yes
+listen=127.0.0.1
+port=5059
+dns=yes
+rev_dns=no
+
+#-----------------------Loading Modiules-------------------------------------
+loadpath "../../modules/"
+loadmodule "tm"
+loadmodule "db_mysql"
+loadmodule "usrloc/usrloc.so"
+loadmodule "registrar"
+loadmodule "sl/sl.so"
+loadmodule "maxfwd/maxfwd.so"
+loadmodule "acc/acc.so"
+#for debugging purposes only
+loadmodule "mi_fifo/mi_fifo.so"
+loadmodule "xlog/xlog.so"
+
+
+#-----------------------Module parameters-------------------------------------
+modparam("mi_fifo", "fifo_name", "/tmp/kamailio_fifo")
+modparam("usrloc", "db_mode", 3)
+modparam("usrloc", "db_url", "mysql://kamailio:kamailiorw@127.0.0.1/kamailio")
+modparam("acc", "log_flag", 1)
+modparam("db_mysql", "timeout_interval", 2)
+
+
+#-----------------------Routing configuration---------------------------------#
+
+request_route {
+	if (!mf_process_maxfwd_header("10")) {
+		sl_send_reply("483","Too Many Hops");
+		exit;
+	}
+
+	if(!lookup ("location")) {
+		sl_send_reply("404", "Not Found");
+		exit;
+	}
+
+	if(method=="INVITE") {
+		setflag(1);
+	}
+
+	if (!t_relay()) {
+			sl_reply_error();
+	}
+}
diff --git a/test/unit/20.sh b/test/unit/20.sh
new file mode 100755
index 0000000..ad48b9d
--- /dev/null
+++ b/test/unit/20.sh
@@ -0,0 +1,54 @@
+#! /bin/bash
+# test basic accounting functionality
+
+# Copyright (C) 2007 1&1 Internet AG
+#
+# This file is part of Kamailio, a free SIP server.
+#
+# Kamailio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version
+#
+# Kamailio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+source include/common
+source include/require
+source include/database
+
+if ! (check_sipp && check_kamailio && check_module "db_mysql" && check_mysql); then
+	exit 0
+fi ;
+
+CFG="20.cfg"
+TMPFILE=`mktemp -t kamailio-test.XXXXXXXXXX`
+
+# add an registrar entry to the db;
+$MYSQL "INSERT INTO location (ruid, username,contact,socket,user_agent,cseq,q) VALUES (\"kamailio-test-uid\",\"foo\",\"sip:foo at 127.0.0.1\",\"udp:127.0.0.1:5060\",\"kamailio_test\",1,-1);"
+
+sipp -sn uas -bg -i 127.0.0.1 -m 1 -f 10 -p 5060 &> /dev/null
+
+$BIN -w . -f $CFG > $TMPFILE 2>&1
+
+sipp -sn uac -s foo 127.0.0.1:5059 -i 127.0.0.1 -m 1 -f 10 -p 5061 &> /dev/null
+
+egrep 'ACC:[[:space:]]+transaction[[:space:]]+answered:[[:print:]]*code=200;reason=OK$' $TMPFILE > /dev/null
+ret=$?
+
+sleep 1
+
+# cleanup
+killall -9 sipp &> /dev/null
+$KILL &> /dev/null
+rm $TMPFILE
+
+$MYSQL "DELETE FROM location WHERE ((contact = \"sip:foo at 127.0.0.1\") and (user_agent = \"kamailio_test\"));"
+
+exit $ret;
diff --git a/test/unit/21.cfg b/test/unit/21.cfg
new file mode 100644
index 0000000..74b237b
--- /dev/null
+++ b/test/unit/21.cfg
@@ -0,0 +1,100 @@
+#
+# simple quick-start config script
+# Please refer to the Core CookBook at http://www.kamailio.org/wiki/
+# for a explanation of possible statements, functions and parameters.
+#
+
+# ----------- global configuration parameters ------------------------
+
+debug=3      # debug level (cmd line: -dddddddddd)
+fork=yes
+log_stderror=no    # (cmd line: -E)
+children=4
+
+listen=127.0.0.1 
+port=5059
+
+dns=no
+rev_dns=no
+
+# ------------------ module loading ----------------------------------
+
+#set module path
+loadpath "../../modules/"
+
+# Uncomment this if you want to use SQL database
+loadmodule "db_mysql/db_mysql.so"
+
+loadmodule "sl/sl.so"
+loadmodule "rr/rr.so"
+loadmodule "maxfwd/maxfwd.so"
+loadmodule "usrloc/usrloc.so"
+loadmodule "pv/pv.so"
+loadmodule "registrar/registrar.so"
+loadmodule "textops/textops.so"
+loadmodule "auth/auth.so"
+loadmodule "auth_db/auth_db.so"
+loadmodule "uri_db/uri_db.so"
+loadmodule "xlog/xlog.so"
+
+# ----------------- setting module-specific parameters ---------------
+# -- usrloc params --
+
+# Uncomment this if you want to use SQL database 
+# for persistent storage and comment the previous line
+modparam("usrloc", "db_mode", 3)
+modparam("usrloc", "db_url", "mysql://kamailio:kamailiorw@localhost/kamailio")
+
+# -- auth params --
+# Uncomment if you are using auth module
+#
+modparam("auth_db", "calculate_ha1", 1)
+
+# If you set "calculate_ha1" parameter to 1 (which true in this config), 
+# uncomment also the following parameter)
+#
+modparam("auth_db", "password_column", "password")
+
+# -- rr params --
+# add value to ;lr param to make some broken UAs happy
+modparam("rr", "enable_full_lr", 1)
+
+
+# -------------------------  request routing logic -------------------
+
+# main routing logic
+
+route{
+
+	if (!mf_process_maxfwd_header("10")) {
+		sl_send_reply("483", "Too Many Hops");
+		exit;
+	}
+
+	if (is_method("ACK")) {
+		xlog("ACK\n");
+		sl_send_reply("200","OK");
+		exit;
+	}
+
+	if (uri == myself) {
+		if(method==REGISTER) {
+			if (!www_authorize("localhost", "subscriber")) {
+				www_challenge("localhost", "0");
+			} else {
+				if(check_to() && check_from()) {
+					sl_send_reply("200","OK");
+				}
+			}
+		} else {
+			if (!proxy_authorize("localhost", "subscriber")) {
+				proxy_challenge("localhost", "0");
+			} else {
+				if(check_to() && check_from() && does_uri_exist()) {
+					sl_send_reply("200","OK");
+				}
+			}
+		}
+		exit;
+	}
+}
diff --git a/test/unit/21.sh b/test/unit/21.sh
new file mode 100755
index 0000000..bd445b2
--- /dev/null
+++ b/test/unit/21.sh
@@ -0,0 +1,58 @@
+#!/bin/bash
+# tests the authentification via auth_db
+
+# Copyright (C) 2007 1&1 Internet AG
+#
+# This file is part of Kamailio, a free SIP server.
+#
+# Kamailio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version
+#
+# Kamailio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+source include/common
+source include/require
+source include/database
+
+if ! (check_sipp && check_kamailio && check_module "db_mysql" && check_mysql); then
+	exit 0
+fi ;
+
+
+CFG=21.cfg
+
+# add an registrar entry to the db;
+$MYSQL "INSERT INTO subscriber (username, domain, password) VALUES (\"alice\",\"localhost\",\"alice\");"
+
+$BIN -w . -f $CFG -E -e -dd > /dev/null 2>&1
+ret=$?
+
+sleep 1
+
+if [ "$ret" -eq 0 ] ; then
+	sipp -s alice 127.0.0.1:5059 -i 127.0.0.1 -m 1 -f 1 -auth_uri alice at localhost -p 5061 -sf reg_auth.xml -ap alice > /dev/null 2>&1 &
+	ret=$?
+fi
+
+if [ "$ret" -eq 0 ] ; then
+	sipp -s alice 127.0.0.1:5059 -i 127.0.0.1 -m 1 -f 1 -auth_uri alice at localhost -p 5061 -sf inv_auth.xml -ap alice > /dev/null 2>&1 &
+	ret=$?
+fi
+
+sleep 1
+
+#cleanup
+$KILL > /dev/null
+killall -9 sipp > /dev/null 2>&1
+$MYSQL "DELETE FROM subscriber WHERE((username = \"alice\") and (domain = \"localhost\"));"
+
+exit $ret;
diff --git a/test/unit/22.cfg b/test/unit/22.cfg
new file mode 100644
index 0000000..692ca15
--- /dev/null
+++ b/test/unit/22.cfg
@@ -0,0 +1,74 @@
+# ----------- global configuration parameters ------------------------
+debug=2
+fork=yes
+log_stderror=no
+children=1
+disable_tcp=yes
+
+alias=localhost
+
+# ------------------ module loading ----------------------------------
+loadpath "../../modules/"
+loadmodule "db_postgres"
+loadmodule "tm"
+loadmodule "sl"
+loadmodule "rr"
+loadmodule "maxfwd"
+loadmodule "textops"
+loadmodule "xlog"
+loadmodule "pv"
+loadmodule "mi_fifo"
+modparam("mi_fifo", "fifo_name", "/tmp/kamailio_fifo")
+
+loadmodule "usrloc"
+modparam("usrloc", "db_mode", 1)
+
+loadmodule "registrar"
+modparam("registrar", "min_expires", 5)
+modparam("usrloc", "timer_interval", 1)
+modparam("usrloc", "db_url", "postgres://kamailio:kamailiorw@localhost/kamailio")
+
+#-------------------------  request routing logic -------------------
+request_route {
+
+	if (!mf_process_maxfwd_header("10")) {
+		sl_send_reply("483","Too Many Hops");
+		exit;
+	}
+
+	if (!method=="REGISTER")
+		record_route();
+
+	if (loose_route()) {
+		# mark routing logic in request
+		append_hf("P-hint: rr-enforced\r\n");
+		route(1);
+	}
+
+	if (!uri==myself) {
+		append_hf("P-hint: outbound\r\n");
+		route(1);
+	}
+
+	if (uri==myself) {
+		if (method=="REGISTER") {
+			save("location");
+			exit;
+		}
+		if (!lookup("location")) {
+			sl_send_reply("404", "Not Found");
+			exit;
+		}
+		append_hf("P-hint: usrloc applied\r\n");
+	}
+
+	route(1);
+}
+
+route[1] {
+	if (!t_relay()) {
+		sl_reply_error();
+	}
+	exit;
+}
+
diff --git a/test/unit/22.sh b/test/unit/22.sh
new file mode 100755
index 0000000..78014cd
--- /dev/null
+++ b/test/unit/22.sh
@@ -0,0 +1,104 @@
+#!/bin/bash
+# database access and persistent storage for registrar on postgres
+
+# Copyright (C) 2007 1&1 Internet AG
+#
+# This file is part of Kamailio, a free SIP server.
+#
+# Kamailio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version
+#
+# Kamailio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+source include/common
+source include/require
+source include/database
+
+if ! (check_sipsak && check_kamailio && check_module "db_postgres" && check_postgres); then
+	exit 0
+fi ;
+
+SIPDOMAIN=127.0.0.1
+CFG=22.cfg
+
+$BIN -w . -f $CFG > /dev/null
+ret=$?
+
+sleep 1
+# register a user
+sipsak -U -C sip:foobar at 127.0.0.1 -s sip:49721123456789@$SIPDOMAIN -H $SIPDOMAIN &> /dev/null
+ret=$?
+
+if [ "$ret" -eq 0 ]; then
+	$CTL ul show | grep "AOR:: 49721123456789" > /dev/null
+	ret=$?
+fi;
+
+if [ "$ret" -eq 0 ]; then
+	TMP=`${PSQL} "select COUNT(*) from location where username='49721123456789';"`
+	if [ "$TMP" -eq 0 ] ; then
+		ret=1
+	fi;
+fi;
+
+if [ "$ret" -eq 0 ]; then
+	# unregister the user
+	sipsak -U -C "*" -s sip:49721123456789@$SIPDOMAIN -H $SIPDOMAIN -x 0 &> /dev/null
+fi;
+
+if [ "$ret" -eq 0 ]; then
+	$CTL ul show | grep "AOR:: 49721123456789" > /dev/null
+	ret=$?
+	if [ "$ret" -eq 0 ]; then
+		ret=1
+	else
+		ret=0
+	fi;
+fi;
+
+if [ "$ret" -eq 0 ]; then
+	ret=`$PSQL "select COUNT(*) from location where username='49721123456789';" | tail -n 1`
+fi;
+
+$PSQL "delete from location where username like '49721123456789%';"
+
+if [ "$ret" -eq 0 ]; then
+	# register again
+	sipsak -U -C sip:foobar at 127.0.0.1 -s sip:49721123456789@$SIPDOMAIN -H $SIPDOMAIN &> /dev/null
+	ret=$?
+fi;
+
+$KILL
+
+# restart to test preload_udomain functionality
+$BIN -w . -f $CFG > /dev/null
+ret=$?
+
+sleep 1
+
+if [ "$ret" -eq 0 ]; then
+	# check if the contact is still registered
+	sipsak -U -C empty -s sip:49721123456789@$SIPDOMAIN -H $SIPDOMAIN -q "Contact: <sip:foobar at 127.0.0.1>" &> /dev/null
+	ret=$?
+fi;
+
+# check if the methods value is correct
+if [ "$ret" -eq 0 ]; then
+	$CTL ul show | grep "Methods:: 4294967295" &> /dev/null
+	ret=$?
+fi;
+
+$KILL
+
+$PSQL "delete from location where username like '49721123456789%';"
+
+exit $ret
diff --git a/test/unit/23.sh b/test/unit/23.sh
new file mode 100755
index 0000000..f1bee63
--- /dev/null
+++ b/test/unit/23.sh
@@ -0,0 +1,104 @@
+#!/bin/bash
+# loads a carrierroute config for loadbalancing from postgres database
+
+# Copyright (C) 2007 1&1 Internet AG
+#
+# This file is part of Kamailio, a free SIP server.
+#
+# Kamailio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version
+#
+# Kamailio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+source include/common
+source include/require
+source include/database
+
+if ! (check_kamailio && check_module "carrierroute" && check_module "db_postgres" && check_postgres); then
+	exit 0
+fi ;
+
+CFG=13.cfg
+
+cp $CFG $CFG.bak
+
+# setup config
+echo "loadmodule \"../../modules/db_postgres/db_postgres.so\"" >> $CFG
+echo "modparam(\"carrierroute\", \"config_source\", \"db\")" >> $CFG
+echo "modparam(\"carrierroute\", \"db_url\", \"postgres://kamailioro:kamailioro@localhost/kamailio\")" >> $CFG
+
+# setup database
+$PSQL "insert into carrier_name (id, carrier) values ('1', 'carrier1');
+insert into carrier_name (id, carrier) values ('2', 'default');
+insert into carrier_name (id, carrier) values ('3', 'premium');
+insert into domain_name (id, domain) values ('10', 'domain1');
+insert into carrierroute (id, carrier, scan_prefix, domain, prob, strip, rewrite_host) values ('1','1','49','10','0.5','0','host1.local.domain');
+insert into carrierroute (id, carrier, scan_prefix, domain, prob, strip, rewrite_host) values ('2','1','49','10','0.5','0','host2.local.domain');
+insert into carrierroute (id, carrier, scan_prefix, domain, prob, strip, rewrite_host) values ('3','1','42','10','0.3','0','host3.local');
+insert into carrierroute (id, carrier, scan_prefix, domain, prob, strip, rewrite_host) values ('4','1','42','10','0.7','0','host4.local');
+insert into carrierroute (id, carrier, scan_prefix, domain, prob, strip, rewrite_host) values ('5','1','1','10','0.5','0','host1-ca.local:5060');
+insert into carrierroute (id, carrier, scan_prefix, domain, prob, strip, rewrite_host) values ('6','1','1','10','0.5','0','host2-ca.local.domain:5060');
+insert into carrierroute (id, carrier, scan_prefix, domain, prob, strip, rewrite_host) values ('10','1','','10','0.1','0','host5.local');
+insert into carrierroute (id, carrier, scan_prefix, domain, prob, strip, rewrite_host) values ('20','2','','10','1','0','host6');
+insert into carrierroute (id, carrier, scan_prefix, domain, prob, strip, rewrite_host) values ('21','3','','10','1','0','premium.host.local');"
+
+$BIN -w . -f $CFG > /dev/null
+ret=$?
+
+sleep 1
+
+TMPFILE=`mktemp -t kamailio-test.XXXXXXXXXX`
+
+if [ "$ret" -eq 0 ] ; then
+	$CTL fifo cr_dump_routes > $TMPFILE
+	ret=$?
+fi ;
+
+if [ "$ret" -eq 0 ] ; then
+	tmp=`grep -v "Printing routing information:
+Printing tree for carrier 'carrier1' (1)
+Printing tree for domain 'domain1' (10)
+         1: 50.000 %, 'host2-ca.local.domain:5060': ON, '0', '', '', ''
+         1: 50.000 %, 'host1-ca.local:5060': ON, '0', '', '', ''
+        42: 70.140 %, 'host4.local': ON, '0', '', '', ''
+        42: 30.060 %, 'host3.local': ON, '0', '', '', ''
+        49: 50.000 %, 'host2.local.domain': ON, '0', '', '', ''
+        49: 50.000 %, 'host1.local.domain': ON, '0', '', '', ''
+      NULL: 100.000 %, 'host5.local': ON, '0', '', '', ''
+Printing tree for carrier 'default' (2)
+Printing tree for domain 'domain1' (10)
+      NULL: 100.000 %, 'host6': ON, '0', '', '', ''
+Printing tree for carrier 'premium' (3)
+Printing tree for domain 'domain1' (10)
+      NULL: 100.000 %, 'premium.host.local': ON, '0', '', '', ''" $TMPFILE`
+	if [ "$tmp" = "" ] ; then
+		ret=0
+	else
+		ret=1
+	fi ;
+fi ;
+
+$KILL
+
+# cleanup database
+$PSQL "delete from carrier_name where id = 1;
+delete from carrier_name where id = 2;
+delete from carrier_name where id = 3;
+delete from domain_name where id = 10;
+delete from carrierroute where carrier=1;
+delete from carrierroute where carrier=2;
+delete from carrierroute where carrier=3;"
+
+mv $CFG.bak $CFG
+rm $TMPFILE
+
+exit $ret
\ No newline at end of file
diff --git a/test/unit/24.sh b/test/unit/24.sh
new file mode 100755
index 0000000..325c3df
--- /dev/null
+++ b/test/unit/24.sh
@@ -0,0 +1,58 @@
+#!/bin/bash
+# creates a postgres database with kamailiodbctl and deletes it again
+
+# Copyright (C) 2007 1&1 Internet AG
+#
+# This file is part of Kamailio, a free SIP server.
+#
+# Kamailio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version
+#
+# Kamailio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+# Needs a mysql database, the root user password must be given
+# in the file 'dbrootpw' in the test directory
+
+source include/common
+
+if [ ! -f ~/.pgpass ] ; then
+       echo "no .pgpass file, not run"
+       exit 0
+fi ;
+
+tmp_name=""$RANDOM"_kamailiodb_tmp"
+
+cd ../../utils/kamctl/
+
+# setup config file
+cp $CTLRC $CTLRC.bak
+sed -i "s/# DBENGINE=MYSQL/DBENGINE=PGSQL/g" $CTLRC
+sed -i "s/# INSTALL_EXTRA_TABLES=ask/INSTALL_EXTRA_TABLES=yes/g" $CTLRC
+sed -i "s/# INSTALL_PRESENCE_TABLES=ask/INSTALL_PRESENCE_TABLES=yes/g" $CTLRC
+
+cp $DBCTL $DBCTL.bak
+sed -i "s/TEST=\"false\"/TEST=\"true\"/g" $DBCTL
+
+./$DBCTL create $tmp_name &> /dev/null
+ret=$?
+
+if [ "$ret" -eq 0 ] ; then
+	./$DBCTL drop $tmp_name &> /dev/null
+	ret=$?
+fi ;
+
+# cleanup
+mv $CTLRC.bak $CTLRC
+mv $DBCTL.bak $DBCTL
+
+cd -
+exit $ret
\ No newline at end of file
diff --git a/test/unit/25.cfg b/test/unit/25.cfg
new file mode 100644
index 0000000..a7ceac0
--- /dev/null
+++ b/test/unit/25.cfg
@@ -0,0 +1,51 @@
+debug=0
+listen=127.0.0.1
+port=5059
+
+loadpath "../../modules_k/:../../modules/"
+loadmodule "tm/tm.so"
+loadmodule "sl/sl.so"
+loadmodule "usrloc/usrloc.so"
+loadmodule "registrar/registrar.so"
+loadmodule "xlog/xlog.so"
+loadmodule "db_mysql/db_mysql.so"
+loadmodule "pv/pv.so"
+loadmodule "userblacklist/userblacklist.so"
+loadmodule "maxfwd/maxfwd.so"
+loadmodule "mi_fifo/mi_fifo.so"
+
+modparam("usrloc", "db_mode", 3)
+modparam("mi_fifo", "fifo_name", "/tmp/kamailio_fifo")
+modparam("userblacklist", "match_mode", 128)
+
+request_route {
+	#xlog("user: $rU\n");
+
+	if (!mf_process_maxfwd_header("10")) {
+		sl_send_reply("483","Too Many Hops");
+		exit;
+	}
+
+	$avp(i:80) = $rU;
+	$avp(i:81) = $rd;
+
+	if(!lookup ("location")){
+		sl_send_reply("404", "Not Found");
+		exit;
+	}
+
+	if (!check_user_blacklist("$avp(i:80)", "$avp(i:81)")) {
+		xlog("$rU user blacklisted\n");
+		sl_send_reply("403", "Forbidden");
+		exit;
+	}
+
+	if (!check_blacklist("globalblacklist")) {
+		xlog("$rU globally blacklisted\n");
+		sl_send_reply("403", "Forbidden");
+		exit;
+	}
+	xlog("$rU not blacklisted\n");
+
+	t_relay();
+}
diff --git a/test/unit/25.sh b/test/unit/25.sh
new file mode 100755
index 0000000..f25a462
--- /dev/null
+++ b/test/unit/25.sh
@@ -0,0 +1,160 @@
+#!/bin/bash
+# loads a userblacklist config from mysql database and test some lists
+
+# Copyright (C) 2007 1&1 Internet AG
+#
+# This file is part of Kamailio, a free SIP server.
+#
+# Kamailio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version
+#
+# Kamailio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+source include/common
+source include/require
+source include/database
+
+function cleanup() {
+	killall -9 sipp > /dev/null 2>&1
+	$KILL > /dev/null 2>&1
+
+	$MYSQL "delete from location where (user_agent = \"kamailio_test\");"
+	$MYSQL "delete from userblacklist where username='49721123456786';"
+	$MYSQL "delete from userblacklist where username='49721123456788';"
+	$MYSQL "delete from userblacklist where username='49721123456789';"
+	$MYSQL "delete from userblacklist where username='494675231';"
+	$MYSQL "delete from userblacklist where username='494675453';"
+	$MYSQL "delete from userblacklist where username='494675454';"
+	$MYSQL "delete from userblacklist where username='user4946';"
+	$MYSQL "delete from globalblacklist where description='_test_';"
+	exit $1;
+}
+
+
+if ! (check_sipp && check_kamailio && check_module "db_mysql" && check_mysql); then
+	exit 0
+fi ;
+
+CFG=25.cfg
+
+# add an registrar entry to the db;
+$MYSQL "insert into location (ruid,username,contact,socket,user_agent,cseq,q) values (\"ul-ruid-aa\",\"49721123456789\",\"sip:123456789 at 127.0.0.1\",\"udp:127.0.0.1:5060\",\"kamailio_test\",1,-1);"
+
+$MYSQL "insert into location (ruid,username,contact,socket,user_agent,cseq,q) values (\"ul-ruid-bb\",\"49721123456788\",\"sip:123456788 at 127.0.0.1\",\"udp:127.0.0.1:5060\",\"kamailio_test\",1,-1);"
+
+$MYSQL "insert into location (ruid,username,contact,socket,user_agent,cseq,q) values (\"ul-ruid-cc\",\"49721123456787\",\"sip:123456787 at 127.0.0.1\",\"udp:127.0.0.1:5060\",\"kamailio_test\",1,-1);"
+
+$MYSQL "insert into location (ruid,username,contact,socket,user_agent,cseq,q) values (\"ul-ruid-dd\",\"49721123456786\",\"sip:123456786 at 127.0.0.1\",\"udp:127.0.0.1:5060\",\"kamailio_test\",1,-1);"
+
+$MYSQL "insert into location (ruid,username,contact,socket,user_agent,cseq,q) values (\"ul-ruid-ee\",\"49721123456785\",\"sip:223456789 at 127.0.0.1\",\"udp:127.0.0.1:5060\",\"kamailio_test\",1,-1);"
+
+$MYSQL "insert into location (ruid,username,contact,socket,user_agent,cseq,q) values (\"ul-ruid-ff\",\"49721123456784\",\"sip:2.23456789 at 127.0.0.1\",\"udp:127.0.0.1:5060\",\"kamailio_test\",1,-1);"
+
+$MYSQL "insert into location (ruid,username,contact,socket,user_agent,cseq,q) values (\"ul-ruid-gg\",\"user4946\",\"sip:user4946 at 127.0.0.1\",\"udp:127.0.0.1:5060\",\"kamailio_test\",1,-1);"
+
+# setup userblacklist, first some dummy data
+$MYSQL "insert into userblacklist (username, domain, prefix, whitelist) values ('494675454','','49900','0');"
+$MYSQL "insert into userblacklist (username, domain, prefix, whitelist) values ('494675453','test.domain','49901','0');"
+$MYSQL "insert into userblacklist (username, domain, prefix, whitelist) values ('494675231','test','499034132','0');"
+$MYSQL "insert into userblacklist (username, domain, prefix, whitelist) values ('494675231','','499034133','1');"
+# some actual data
+$MYSQL "insert into userblacklist (username, domain, prefix, whitelist) values ('49721123456789','','12345','0');"
+$MYSQL "insert into userblacklist (username, domain, prefix, whitelist) values ('49721123456788','','123456788','1');"
+$MYSQL "insert into userblacklist (username, domain, prefix, whitelist) values ('49721123456788','','1234','0');"
+# and the global ones
+$MYSQL "insert into globalblacklist (prefix, whitelist, description) values ('123456787','0','_test_');"
+$MYSQL "insert into globalblacklist (prefix, whitelist, description) values ('123456','0','_test_');"
+$MYSQL "insert into globalblacklist (prefix, whitelist, description) values ('1','1','_test_');"
+$MYSQL "insert into globalblacklist (prefix, whitelist, description) values ('','0','_test_');"
+
+
+$BIN -w . -f $CFG > /dev/null 2>&1
+sleep 1
+
+sipp -sn uas -bg -i 127.0.0.1 -p 5060 #&> /dev/null
+
+sipp -sn uac -s 49721123456789 127.0.0.1:5059 -i 127.0.0.1 -m 1 -f 2 -p 5061 &> /dev/null
+ret=$?
+
+if [ "$ret" -ne 1 ] ; then
+	cleanup 1
+fi;
+
+sipp -sn uac -s 49721123456788 127.0.0.1:5059 -i 127.0.0.1 -m 1 -f 2 -p 5061 &> /dev/null
+ret=$?
+
+if [ "$ret" -ne 1 ] ; then
+	cleanup 1
+fi;
+sipp -sn uac -s 49721123456787 127.0.0.1:5059 -i 127.0.0.1 -m 1 -f 2 -p 5061 &> /dev/null
+ret=$?
+
+if [ "$ret" -ne 1 ] ; then
+	cleanup 1
+fi;
+
+sipp -sn uac -s 49721123456786 127.0.0.1:5059 -i 127.0.0.1 -m 1 -f 2 -p 5061 &> /dev/null
+ret=$?
+
+if [ "$ret" -ne 1 ] ; then
+	cleanup 1
+fi;
+
+$MYSQL "insert into globalblacklist (prefix, whitelist, description) values ('123456786','1','_test_');"
+$CTL mi reload_blacklist
+
+sipp -sn uac -s 49721123456786 127.0.0.1:5059 -i 127.0.0.1 -m 1 -f 2 -p 5061 &> /dev/null
+ret=$?
+
+if [ "$ret" -ne 0 ] ; then
+	cleanup 1
+fi;
+
+$MYSQL "insert into userblacklist (username, domain, prefix, whitelist) values ('49721123456786','','12345','0');"
+
+sipp -sn uac -s 49721123456786 127.0.0.1:5059 -i 127.0.0.1 -m 1 -f 2 -p 5061 &> /dev/null
+ret=$?
+
+if [ "$ret" -ne 1 ] ; then
+	cleanup 1
+fi;
+
+sipp -sn uac -s 49721123456785 127.0.0.1:5059 -i 127.0.0.1 -m 1 -f 2 -p 5061 &> /dev/null
+ret=$?
+
+$MYSQL "insert into globalblacklist (prefix, whitelist, description) values ('2','1','_test_');"
+
+$CTL mi reload_blacklist
+
+sipp -sn uac -s 49721123456785 127.0.0.1:5059 -i 127.0.0.1 -m 1 -f 2 -p 5061 &> /dev/null
+ret=$?
+
+if [ "$ret" -ne 0 ] ; then
+	cleanup 1
+fi;
+
+$MYSQL "insert into globalblacklist (prefix, whitelist, description) values ('user4946','0','_test_');"
+
+sipp -sn uac -s user4946 127.0.0.1:5059 -i 127.0.0.1 -m 1 -f 2 -p 5061 &> /dev/null
+ret=$?
+
+if [ "$ret" -ne 1 ] ; then
+	cleanup 1
+fi;
+
+
+sipp -sn uac -s 49721123456784 127.0.0.1:5059 -i 127.0.0.1 -m 1 -f 2 -p 5061 &> /dev/null
+ret=$?
+
+sleep 1
+# cleanup:
+cleanup $ret
diff --git a/test/unit/26.cfg b/test/unit/26.cfg
new file mode 100644
index 0000000..52d8da9
--- /dev/null
+++ b/test/unit/26.cfg
@@ -0,0 +1,72 @@
+debug=3
+memdbg=6
+memlog=6
+loadpath "../../modules/:../../modules_k/"
+loadmodule "sl"
+loadmodule "tm"
+loadmodule "tmx"
+loadmodule "xlog"
+loadmodule "maxfwd"
+loadmodule "pv"
+loadmodule "kex"
+loadmodule "carrierroute"
+loadmodule "mi_fifo"
+
+modparam("mi_fifo", "fifo_name", "/tmp/kamailio_fifo")
+
+route{
+	# initial sanity checks
+	if (!mf_process_maxfwd_header("10")) {
+		sl_send_reply("483","Too Many Hops");
+		return;
+	}
+	if (msg:len > 4096) {
+		sl_send_reply("513", "Message too big");
+		return;
+	}
+	# set flag for later test
+	setflag(0);
+	resetflag(1);
+	setflag(2);
+
+	# user route
+	if(cr_user_carrier("$rU", "$rd", "$avp(s:11)")) {
+		$avp(s:10)="domain0";
+		if (!cr_route("$avp(s:11)", "$avp(s:10)", "$rU", "$rU", "call_id", "$avp(s:13)")) {
+			xlog("L_ERR", "cr_route failed\n");
+			exit;
+		}
+		t_on_failure("1");
+		$avp(s:12) = $rd+":"+$rp;
+		#xlog("host: $avp(s:12), comment: $avp(s:13)");
+	} else {
+	# default route
+		if (!cr_route("default", "domain0", "$rU", "$rU", "call_id")) {
+			xlog("L_ERR", "cr_route failed\n");
+			exit;
+		}
+	}
+	if (!t_relay()) {
+		sl_reply_error();
+	}
+}
+
+failure_route[1] {
+	xlog("entered failure route with result $T_reply_code");
+	revert_uri();
+	if (!cr_next_domain("$avp(s:11)", "$avp(s:10)", "$rU", "$avp(s:12)", "$T_reply_code", "$avp(s:10)")) {
+		xlog("L_ERR", "cr_next_domain failed\n");
+		exit;
+	}
+	if (!cr_route("$avp(s:11)", "$avp(s:10)", "$rU", "$rU", "call_id")) {
+		xlog("L_ERR", "cr_route failed\n");
+		exit;
+	}
+	$avp(s:12) = $rd+":"+$rp;
+	t_on_failure("1");
+	km_append_branch();
+	if (!t_relay()) {
+		xlog("L_ERR", "t_relay failed\n");
+		exit;
+	}
+}
diff --git a/test/unit/26.sh b/test/unit/26.sh
new file mode 100755
index 0000000..5f253ad
--- /dev/null
+++ b/test/unit/26.sh
@@ -0,0 +1,150 @@
+#!/bin/bash
+# do some routing with carrierroute route sets from mysql database
+
+# Copyright (C) 2007 1&1 Internet AG
+#
+# This file is part of Kamailio, a free SIP server.
+#
+# Kamailio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version
+#
+# Kamailio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+source include/common
+source include/require
+source include/database
+
+if ! (check_kamailio && check_module "carrierroute" && check_module "db_mysql" && check_mysql); then
+	exit 0
+fi ;
+
+CFG=26.cfg
+
+cp $CFG $CFG.bak
+
+# setup config
+echo "loadmodule \"../../modules/db_mysql/db_mysql.so\"" >> $CFG
+echo "modparam(\"carrierroute\", \"config_source\", \"db\")" >> $CFG
+
+# setup database
+$MYSQL "insert into carrier_name (id, carrier) values ('1', 'default');"
+$MYSQL "insert into carrier_name (id, carrier) values ('2', 'carrier1');"
+$MYSQL "insert into carrier_name (id, carrier) values ('3', 'carrier2');"
+
+$MYSQL "insert into domain_name (id, domain) values ('10', 'domain0');"
+$MYSQL "insert into domain_name (id, domain) values ('1', 'fallback');"
+$MYSQL "insert into domain_name (id, domain) values ('2', 'domain2');"
+
+$MYSQL "insert into carrierroute (id, carrier, domain, scan_prefix, flags, mask, prob, strip, rewrite_host)
+values ('1','1','10','49','0','0','0.5','0','127.0.0.1:7000');"
+$MYSQL "insert into carrierroute (id, carrier, domain, scan_prefix, flags, mask, prob, strip, rewrite_host, description)
+values ('2','1','10','49','0','0','0.5','0','127.0.0.1:8000', 'foobar');"
+$MYSQL "insert into carrierroute (id, carrier, domain, scan_prefix, flags, mask, prob, strip, rewrite_host)
+values ('3','2','10','49','0','0','1','0','127.0.0.1:9000');"
+$MYSQL "insert into carrierroute (id, carrier, domain, scan_prefix, flags, mask, prob, strip, rewrite_host)
+values ('4','3','10','49','0','3','1','0','127.0.0.1:10001');"
+$MYSQL "insert into carrierroute (id, carrier, domain, scan_prefix, flags, mask, prob, strip, rewrite_host)
+values ('5','3','10','49','1','3','1','0','127.0.0.1:10000');"
+$MYSQL "insert into carrierroute (id, carrier, domain, scan_prefix, flags, mask, prob, strip, rewrite_host)
+values ('6','3','10','49','2','3','1','0','127.0.0.1:10002');"
+$MYSQL "insert into carrierroute (id, carrier, domain, scan_prefix, flags, mask, prob, strip, rewrite_host)
+values ('7','3','1','49','0','0','1','0','127.0.0.1:10000');"
+$MYSQL "insert into carrierroute (id, carrier, domain, scan_prefix, flags, mask, prob, strip, rewrite_host)
+values ('8','3','2','49','0','0','1','0','127.0.0.1:10000');"
+
+$MYSQL "insert into carrierfailureroute(id, carrier, domain, scan_prefix, host_name, reply_code,
+flags, mask, next_domain) values ('1', '3', '10', '49', '127.0.0.1:10000', '5..', '0', '0', '1');"
+$MYSQL "insert into carrierfailureroute(id, carrier, domain, scan_prefix, host_name, reply_code,
+flags, mask, next_domain) values ('2', '3', '1', '49', '127.0.0.1:10000', '483', '0', '0', '2');"
+$MYSQL "insert into carrierfailureroute(id, carrier, domain, scan_prefix, host_name, reply_code,
+flags, mask, next_domain) values ('3', '3', '1', '49', '127.0.0.1:9000', '4..', '0', '0', '2');"
+
+$MYSQL "alter table subscriber add cr_preferred_carrier int(10) default NULL;"
+
+$MYSQL "insert into subscriber (username, cr_preferred_carrier) values ('49721123456786', 2);"
+$MYSQL "insert into subscriber (username, cr_preferred_carrier) values ('49721123456785', 3);"
+
+
+$BIN -w . -f $CFG > /dev/null
+
+ret=$?
+
+sleep 1
+
+if [ "$ret" -eq 0 ] ; then
+	sipp -sn uas -bg -i localhost -m 12 -p 7000 &> /dev/null
+	sipp -sn uas -bg -i localhost -m 12 -p 8000 &> /dev/null
+	sipp -sn uac -s 49721123456787 127.0.0.1:5060 -i 127.0.0.1 -m 20 -p 5061 &> /dev/null
+	ret=$?
+	killall sipp &> /dev/null
+fi;
+
+
+if [ "$ret" -eq 0 ] ; then
+	sipp -sn uas -bg -i localhost -m 10 -p 9000 &> /dev/null
+	sipp -sn uac -s 49721123456786 127.0.0.1:5060 -i 127.0.0.1 -m 10 -p 5061 &> /dev/null
+	ret=$?
+fi;
+sleep 1
+
+if [ "$ret" -eq 0 ] ; then
+	sipp -sn uas -bg -i localhost -m 10 -p 10000 &> /dev/null
+	sipp -sn uac -s 49721123456785 127.0.0.1:5060 -i 127.0.0.1 -m 10 -p 5061 &> /dev/null
+	ret=$?
+fi;
+sleep 2
+
+if [ "$ret" -eq 0 ] ; then
+	killall sipp &> /dev/null
+	sipp -sf failure_route.xml -bg -i localhost -m 1 -p 10000 &> /dev/null
+	sipp -sn uac -s 49721123456785 127.0.0.1:5060 -i 127.0.0.1 -m 1 -p 5061 #&> /dev/null
+	ret=$?
+fi;
+
+$MYSQL "insert into carrierfailureroute(id, carrier, domain, scan_prefix, host_name, reply_code,
+flags, mask, next_domain) values ('4', '3', '1', '49', '127.0.0.1:10000', '4..', '0', '0', '4');"
+$MYSQL "insert into carrierfailureroute(id, carrier, domain, scan_prefix, host_name, reply_code,
+flags, mask, next_domain) values ('5', '3', '1', '49', '127.0.0.1:10000', '486', '0', '0', '2');"
+
+if [ ! "$ret" -eq 0 ] ; then
+	$CTL fifo cr_reload_routes
+	killall sipp &> /dev/null
+	sipp -sf failure_route.xml -bg -i localhost -m 10 -p 10000 &> /dev/null
+	sipp -sn uac -s 49721123456785 127.0.0.1:5060 -i 127.0.0.1 -m 10 -p 5061 &> /dev/null
+	ret=$?
+fi;
+
+
+$KILL
+killall -9 sipp
+
+# cleanup database
+$MYSQL "delete from carrier_name where id = 1;"
+$MYSQL "delete from carrier_name where id = 2;"
+$MYSQL "delete from carrier_name where id = 3;"
+$MYSQL "delete from domain_name where id = 10;"
+$MYSQL "delete from domain_name where id = 1;"
+$MYSQL "delete from domain_name where id = 2;"
+$MYSQL "delete from carrierroute where carrier=1;"
+$MYSQL "delete from carrierroute where carrier=2;"
+$MYSQL "delete from carrierroute where carrier=3;"
+$MYSQL "delete from carrierfailureroute where carrier=1;"
+$MYSQL "delete from carrierfailureroute where carrier=2;"
+$MYSQL "delete from carrierfailureroute where carrier=3;"
+
+$MYSQL "delete from subscriber where username='49721123456786';"
+$MYSQL "delete from subscriber where username='49721123456785';"
+$MYSQL "alter table subscriber drop cr_preferred_carrier;"
+
+mv $CFG.bak $CFG
+
+exit $ret
\ No newline at end of file
diff --git a/test/unit/27.sh b/test/unit/27.sh
new file mode 100755
index 0000000..772321d
--- /dev/null
+++ b/test/unit/27.sh
@@ -0,0 +1,54 @@
+#!/bin/bash
+# test publish and subscribe for presence
+
+# Copyright (C) 2007 1&1 Internet AG
+#
+# This file is part of Kamailio, a free SIP server.
+#
+# Kamailio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version
+#
+# Kamailio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+source include/common
+source include/require
+source include/database
+
+if ! (check_sipp && check_kamailio && check_module "db_mysql" \
+	&& check_module "presence" && check_module "presence_xml" \
+	&& check_mysql); then
+	exit 0
+fi ;
+
+CFG=presence.cfg
+
+$BIN -w . -f $CFG -a no >/dev/null
+ret=$?
+sleep 1
+
+if [ "$ret" -eq 0 ] ; then
+    sipp -sf publish_scenario.xml -i 127.0.0.1 -p 5061 -inf publish.csv 127.0.0.1:5059 -recv_timeout 500000 -m 1 >/dev/null 2>&1 &
+    ret=$?
+fi
+
+if [ "$ret" -eq 0 ] ; then
+    sipp -sf subscribe_notify_scenario.xml -i 127.0.0.1 -p 5061 -inf subscribe_notify.csv 127.0.0.1:5059 -recv_timeout 500000 -m 1 >/dev/null 2>&1 &
+    ret=$?
+fi
+
+sleep 1
+
+#cleanup:
+$KILL >/dev/null
+killall -9 sipp >/dev/null 2>&1
+
+exit $ret
diff --git a/test/unit/28.cfg b/test/unit/28.cfg
new file mode 100644
index 0000000..ef034a8
--- /dev/null
+++ b/test/unit/28.cfg
@@ -0,0 +1,23 @@
+debug=3
+
+loadpath "../../modules/"
+loadmodule "sl.so"
+loadmodule "tm/tm.so"
+loadmodule "db_mysql/db_mysql.so"
+loadmodule "cpl-c/cpl-c.so"
+loadmodule "mi_fifo/mi_fifo.so"
+loadmodule "textops/textops.so"
+
+modparam("mi_fifo", "fifo_name", "/tmp/kamailio_fifo")
+modparam("cpl-c", "cpl_dtd_file", "../../modules/cpl-c/cpl-06.dtd")
+
+request_route {
+	if (is_method("INVITE")) {
+		# run incoming script
+		if ( !cpl_run_script("incoming", "force_stateful") ) {
+			# script execution failed
+			sl_send_reply("500","CPL script execution failed");
+			exit;
+		}
+	}
+}
diff --git a/test/unit/28.sh b/test/unit/28.sh
new file mode 100755
index 0000000..0547894
--- /dev/null
+++ b/test/unit/28.sh
@@ -0,0 +1,71 @@
+#!/bin/bash
+# tests simple cpl-c script operations with mysql
+
+# Copyright (C) 2008 1&1 Internet AG
+#
+# This file is part of Kamailio, a free SIP server.
+#
+# Kamailio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version
+#
+# Kamailio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+source include/common
+source include/require
+source include/database
+
+if ! (check_sipp && check_kamailio && check_module "db_mysql" && check_module "cpl-c" && check_mysql); then
+	exit 0
+fi ;
+
+CFG=28.cfg
+CPL=cpl_ignore.xml
+TMPFILE=`mktemp -t kamailio-test.XXXXXXXXXX`
+
+
+$BIN -w . -f $CFG -a no >/dev/null
+ret=$?
+sleep 1
+
+$CTL mi LOAD_CPL sip:alice at 127.0.0.1 $CPL
+
+if [ "$ret" -eq 0 ] ; then
+	sipp -m 1 -f 1 127.0.0.1:5060 -sf cpl_test.xml >/dev/null 2>&1 &
+	ret=$?
+fi
+
+if [ "$ret" -eq 0 ] ; then
+  $CTL fifo GET_CPL sip:alice at 127.0.0.1 > $TMPFILE 
+  diff $TMPFILE $CPL 
+  ret=$?
+fi 
+
+if [ "$ret" -eq 0 ] ; then
+  $CTL fifo REMOVE_CPL sip:alice at 127.0.0.1
+  $CTL fifo GET_CPL sip:alice at 127.0.0.1 > $TMPFILE
+fi
+
+diff $TMPFILE $CPL >/dev/null
+ret=$?
+
+if [ ! "$ret" -eq 0 ] ; then
+  ret=0
+fi;
+
+sleep 1
+
+#cleanup:
+$KILL >/dev/null
+killall -9 sipp >/dev/null 2>&1
+rm $TMPFILE
+
+exit $ret
diff --git a/test/unit/29.sh b/test/unit/29.sh
new file mode 100755
index 0000000..7925c94
--- /dev/null
+++ b/test/unit/29.sh
@@ -0,0 +1,73 @@
+#!/bin/bash
+# tests simple cpl-c script operations with postgres
+
+# Copyright (C) 2008 1&1 Internet AG
+#
+# This file is part of Kamailio, a free SIP server.
+#
+# Kamailio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version
+#
+# Kamailio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+source include/common
+source include/require
+
+if ! (check_sipp && check_kamailio && check_module "db_postgres" && check_module "cpl-c"); then
+	exit 0
+fi ;
+
+CFG=28.cfg
+CPL=cpl_ignore.xml
+TMPFILE=`mktemp -t kamailio-test.XXXXXXXXXX`
+
+cp $CFG $CFG.tmp
+echo "loadmodule \"../../modules/db_postgres/db_postgres.so\"" >> $CFG
+echo "modparam(\"cpl-c\", \"db_url\", \"postgres://kamailio:kamailiorw@localhost/kamailio\")" >> $CFG
+
+
+$BIN -w . -f $CFG >/dev/null
+ret=$?
+sleep 1
+
+$CTL fifo LOAD_CPL sip:alice at 127.0.0.1 $CPL
+
+if [ "$ret" -eq 0 ] ; then
+	sipp -m 1 -f 1 127.0.0.1:5060 -sf cpl_test.xml >/dev/null 2>&1 &
+	ret=$?
+fi
+
+if [ "$ret" -eq 0 ] ; then
+  $CTL fifo GET_CPL sip:alice at 127.0.0.1 > $TMPFILE 
+  diff $TMPFILE $CPL 
+  ret=$?
+fi 
+
+if [ "$ret" -eq 0 ] ; then
+  $CTL fifo REMOVE_CPL sip:alice at 127.0.0.1
+  $CTL fifo GET_CPL sip:alice at 127.0.0.1 > $TMPFILE
+fi
+
+diff $TMPFILE $CPL >/dev/null
+ret=$?
+
+if [ ! "$ret" -eq 0 ] ; then
+  ret=0
+fi;
+
+#cleanup:
+$KILL >/dev/null
+killall -9 sipp >/dev/null 2>&1
+rm $TMPFILE
+mv $CFG.tmp $CFG
+
+exit $ret
diff --git a/test/unit/3.sh b/test/unit/3.sh
new file mode 100755
index 0000000..9578c01
--- /dev/null
+++ b/test/unit/3.sh
@@ -0,0 +1,68 @@
+#!/bin/bash
+# creates a mysql database with kamailiodbctl and deletes it again
+
+# Copyright (C) 2007 1&1 Internet AG
+#
+# This file is part of Kamailio, a free SIP server.
+#
+# Kamailio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version
+#
+# Kamailio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+# Needs a mysql database, the root user password must be assigned to
+# the 'PW' variable in the file 'dbrootpw' in the test directory, e.g.:
+# PW=sql_root_passwd
+# If MySQL root password is empty, add in the file the line:
+# PWSKIP=yes
+
+source include/common
+
+if [ ! -f dbrootpw ] ; then
+	echo "no root password, not run"
+	exit 0
+fi ;
+
+source dbrootpw
+
+tmp_name=""$RANDOM"_kamailiodb_tmp"
+
+cd $CTL_DIR
+
+# setup config file
+cp $CTLRC $CTLRC.bak
+sed -i '' -e "s/# DBENGINE=MYSQL/DBENGINE=MYSQL/g" $CTLRC
+sed -i '' -e "s/# INSTALL_EXTRA_TABLES=ask/INSTALL_EXTRA_TABLES=yes/g" $CTLRC
+sed -i '' -e "s/# INSTALL_PRESENCE_TABLES=ask/INSTALL_PRESENCE_TABLES=yes/g" $CTLRC
+sed -i '' -e "s/# INSTALL_DBUID_TABLES=ask/INSTALL_DBUID_TABLES=yes/g" $CTLRC
+
+cp $DBCTL $DBCTL.bak
+sed -i '' -e "s/TEST=\"false\"/TEST=\"true\"/g" $DBCTL
+
+# set the mysql root password
+cp $DBCTL.mysql $DBCTL.mysql.bak
+sed -i '' -e "s/#PW=\"\"/PW=\"$PW\"/g" $DBCTL.mysql
+
+PWSKIP="$PWSKIP" CHARSET="latin1" ./$DBCTL create $tmp_name > /dev/null
+ret=$?
+
+if [ "$ret" -eq 0 ] ; then
+	PWSKIP="$PWSKIP" ./$DBCTL drop $tmp_name > /dev/null
+	ret=$?
+fi ;
+
+# cleanup
+mv $CTLRC.bak $CTLRC
+mv $DBCTL.mysql.bak $DBCTL.mysql
+mv $DBCTL.bak $DBCTL
+
+exit $ret
diff --git a/test/unit/30.cfg b/test/unit/30.cfg
new file mode 100644
index 0000000..c2f006b
--- /dev/null
+++ b/test/unit/30.cfg
@@ -0,0 +1,30 @@
+debug=2
+loadpath "../../modules/:../../modules_k/"
+loadmodule "sl"
+loadmodule "../../modules/tm/tm.so"
+loadmodule "xlog"
+loadmodule "maxfwd"
+loadmodule "pv"
+loadmodule "../../modules/carrierroute/carrierroute.so"
+
+route{
+	# initial sanity checks
+	if (!mf_process_maxfwd_header("10")) {
+		sl_send_reply("483","Too Many Hops");
+		return;
+	}
+
+	if (msg:len > 4096) {
+		sl_send_reply("513", "Message too big");
+		return;
+	}
+
+	# default route
+ 	if (!cr_route("default", "proxy", "$rU", "$rU", "call_id")) {
+		xlog("L_ERR", "cr_route failed\n");
+		exit;
+	}
+	if (!t_relay()) {
+		sl_reply_error();
+	}
+}
diff --git a/test/unit/30.sh b/test/unit/30.sh
new file mode 100755
index 0000000..8379777
--- /dev/null
+++ b/test/unit/30.sh
@@ -0,0 +1,70 @@
+#!/bin/bash
+# do some routing with carrierroute route sets from a config file
+
+# Copyright (C) 2007 1&1 Internet AG
+#
+# This file is part of Kamailio, a free SIP server.
+#
+# Kamailio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version
+#
+# Kamailio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+source include/common
+source include/require
+
+if ! (check_sipp && check_kamailio && check_module "carrierroute"); then
+	exit 0
+fi ;
+
+CFG=30.cfg
+
+
+cp $CFG $CFG.bak
+
+# setup config
+echo "modparam(\"carrierroute\", \"config_file\", \"carrierroute-2.cfg\")" >> $CFG
+
+
+$BIN -w . -f $CFG > /dev/null
+
+ret=$?
+
+sleep 1
+
+if [ "$ret" -eq 0 ] ; then
+	# the distribution is not perfect
+	sipp -sn uas -bg -i localhost -m 12 -p 7000 &> /dev/null
+	sipp -sn uas -bg -i localhost -m 12 -p 8000 &> /dev/null
+	sipp -sn uac -s 49721123456787 127.0.0.1:5060 -i 127.0.0.1 -m 20 -p 5061 &> /dev/null
+	ret=$?
+	killall sipp &> /dev/null
+fi;
+
+if [ "$ret" -eq 0 ] ; then
+	sipp -sn uas -bg -i localhost -m 10 -p 9000 &> /dev/null
+	sipp -sn uac -s 49721123456786 127.0.0.1:5060 -i 127.0.0.1 -m 10 -p 5061 &> /dev/null
+	ret=$?
+fi;
+
+if [ "$ret" -eq 0 ] ; then
+	sipp -sn uas -bg -i localhost -m 10 -p 10000 &> /dev/null
+	sipp -sn uac -s 49721123456785 127.0.0.1:5060 -i 127.0.0.1 -m 10 -p 5061 &> /dev/null
+	ret=$?
+fi;
+
+$KILL
+killall -9 sipp
+
+mv $CFG.bak $CFG
+
+exit $ret
\ No newline at end of file
diff --git a/test/unit/31.sh b/test/unit/31.sh
new file mode 100755
index 0000000..4e40f9f
--- /dev/null
+++ b/test/unit/31.sh
@@ -0,0 +1,50 @@
+#!/bin/bash
+# database access with fetch_result for usrloc on mysql
+
+# Copyright (C) 2008 1&1 Internet AG
+#
+# This file is part of Kamailio, a free SIP server.
+#
+# Kamailio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version
+#
+# Kamailio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+source include/common
+source include/require
+source include/database
+
+if ! (check_kamailio && check_module "db_mysql" && check_mysql); then
+	exit 0
+fi ;
+
+CFG=11.cfg
+
+DOMAIN="local"
+# setup 500 contacts
+NR=500
+
+COUNTER=0
+while [  $COUNTER -lt $NR ]; do
+	COUNTER=$(($COUNTER+1))
+	$MYSQL "insert into location (ruid, username, domain, contact, user_agent) values ('ul-ruid-$COUNTER', 'foobar-$RANDOM', '$DOMAIN', 'sip:foobar-$RANDOM@$DOMAIN', '___test___');"
+done
+
+$BIN -w . -f $CFG -A FETCHROWS=17 -a no >/dev/null
+ret=$?
+
+sleep 1
+$KILL >/dev/null
+
+$MYSQL "delete from location where user_agent = '___test___'"
+
+exit $ret
diff --git a/test/unit/32.sh b/test/unit/32.sh
new file mode 100755
index 0000000..e6d6533
--- /dev/null
+++ b/test/unit/32.sh
@@ -0,0 +1,59 @@
+#!/bin/bash
+# database access with fetch_result for usrloc on postgres
+
+# Copyright (C) 2008 1&1 Internet AG
+#
+# This file is part of Kamailio, a free SIP server.
+#
+# Kamailio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version
+#
+# Kamailio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+source include/common
+source include/require
+source include/database
+
+if ! (check_sipp && check_kamailio && check_module "db_postgres" && check_postgres); then
+	exit 0
+fi ;
+
+CFG=11.cfg
+
+DOMAIN="local"
+# setup 250 contacts
+NR=25
+
+cp $CFG $CFG.bak
+
+echo "loadmodule \"../../modules/db_postgres/db_postgres.so\"" >> $CFG
+echo "modparam(\"usrloc\", \"db_url\", \"postgres://kamailio:kamailiorw@localhost/kamailio\")" >> $CFG
+echo "modparam(\"usrloc\", \"fetch_rows\", 13)" >> $CFG
+
+
+COUNTER=0
+while [  $COUNTER -lt $NR ]; do
+	COUNTER=$(($COUNTER+1))
+	$PSQL "insert into location (username, domain, contact, user_agent) values ('foobar-$RANDOM', '$DOMAIN', 'foobar-$RANDOM@$DOMAIN', '___test___'); insert into location (username, domain, contact, user_agent) values ('foobar-$RANDOM', '$DOMAIN', 'foobar-$RANDOM@$DOMAIN', '___test___'); insert into location (username, domain, contact, user_agent) values ('foobar-$RANDOM', '$DOMAIN', 'foobar-$RANDOM@$DOMAIN', '___test___'); insert into location (username, domain, contact, user_agent) values [...]
+done
+
+$BIN -w . -f $CFG > /dev/null
+ret=$?
+
+sleep 1
+$KILL
+
+$PSQL "delete from location where user_agent = '___test___'"
+
+mv $CFG.bak $CFG
+
+exit $ret
diff --git a/test/unit/33.cfg b/test/unit/33.cfg
new file mode 100644
index 0000000..95dee89
--- /dev/null
+++ b/test/unit/33.cfg
@@ -0,0 +1,28 @@
+debug=3
+memlog=2
+loadpath "../../modules/"
+loadmodule "cfgutils.so"
+loadmodule "pv.so"
+loadmodule "xlog.so"
+loadmodule "mi_fifo/mi_fifo.so"
+
+modparam("mi_fifo", "fifo_name", "/tmp/kamailio_fifo")
+
+modparam("cfgutils", "initial_probability", 15)
+modparam("cfgutils", "hash_file", "33.cfg")
+
+modparam("pv", "shvset", "debug=i:1")
+modparam("pv", "shvset", "pstngw=s:sip:10.10.10.10")
+modparam("pv", "varset", "init=i:1")
+modparam("pv", "varset", "gw=s:sip:11.11.11.11;transport=tcp")
+
+request_route{
+	xlog("PGK status:");
+	usleep("100");
+	pkg_status();
+	sleep("1");
+	xlog("SHM status:");
+	shm_status();
+	abort();
+	xlog("end");
+}
diff --git a/test/unit/33.sh b/test/unit/33.sh
new file mode 100755
index 0000000..fcfcdc4
--- /dev/null
+++ b/test/unit/33.sh
@@ -0,0 +1,77 @@
+#!/bin/bash
+# test cfgutils and pv module
+
+# Copyright (C) 2008 1&1 Internet AG
+#
+# This file is part of Kamailio, a free SIP server.
+#
+# Kamailio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version
+#
+# Kamailio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+source include/common
+source include/require
+
+if ! (check_netcat && check_kamailio); then
+	exit 0
+fi;
+
+if [ -e core ] ; then
+	echo "core file found, not run"
+	exit 0
+fi;
+
+CFG=33.cfg
+
+cp $CFG $CFG.bak
+
+ulimit -c unlimited
+
+$BIN -w . -f $CFG -a no > /dev/null
+ret=$?
+
+sleep 1
+
+if [ $ret -eq 0 ] ; then
+	$CTL mi check_config_hash | grep "The actual config file hash is identical to the stored one." >/dev/null
+	ret=$?
+fi;
+
+echo " " >> $CFG
+if [ $ret -eq 0 ] ; then
+	$CTL mi check_config_hash | grep "The actual config file hash is identical to the stored one." >/dev/null
+	ret=$?
+fi
+
+if [ ! $ret -eq 0 ] ; then
+	# send a message
+	cat register.sip | nc -q 1 -u 127.0.0.1 5060 > /dev/null
+fi
+
+sleep 1
+$KILL >/dev/null 2>&1
+ret=$?
+
+if [ $ret -eq 0 ] ; then
+	ret=1
+else
+	ret=0
+fi
+
+if [ ! -e core ] ; then
+	ret=1
+fi
+rm -f core
+mv $CFG.bak $CFG
+
+exit $ret
diff --git a/test/unit/34.cfg b/test/unit/34.cfg
new file mode 100644
index 0000000..6f158a5
--- /dev/null
+++ b/test/unit/34.cfg
@@ -0,0 +1,26 @@
+loadpath "../../modules_k:../../modules"
+loadmodule "tm/tm.so"
+loadmodule "sl.so"
+loadmodule "usrloc.so"
+loadmodule "presence.so"
+loadmodule "presence_xml.so"
+loadmodule "presence_mwi.so"
+loadmodule "pua.so"
+loadmodule "pua_bla.so"
+loadmodule "pua_mi.so"
+loadmodule "pua_usrloc.so"
+loadmodule "xmpp.so"
+loadmodule "pua_xmpp.so"
+loadmodule "xcap_client.so"
+loadmodule "rls.so"
+loadmodule "presence_dialoginfo.so"
+loadmodule "rr.so"
+loadmodule "dialog.so"
+loadmodule "pua_dialoginfo.so"
+
+modparam("rls", "xcap_root", "http://localhost/xcap-root:8000")
+modparam("presence_xml", "integrated_xcap_server", 1)
+modparam("pua_bla|pua_usrloc", "default_domain", "localhost")
+modparam("pua_bla", "header_name", "Sender")
+modparam("pua_bla|pua_xmpp", "server_address", "sip:bla at 127.0.0.1")
+modparam("dialog", "dlg_flag", 10)
diff --git a/test/unit/34.sh b/test/unit/34.sh
new file mode 100755
index 0000000..1fd42d4
--- /dev/null
+++ b/test/unit/34.sh
@@ -0,0 +1,54 @@
+#!/bin/bash
+# load all presence related modules with mysql
+
+# Copyright (C) 2008 1&1 Internet AG
+#
+# This file is part of Kamailio, a free SIP server.
+#
+# Kamailio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version
+#
+# Kamailio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+# Needs a default kamailio database setup for mysql
+
+source include/common
+source include/require
+source include/database
+
+CFG=34.cfg
+
+if ! (check_kamailio && check_module "db_mysql" && check_module "presence" \
+		&& check_module "presence_xml" && check_module "pua" \
+		&& check_module "xcap_client" && check_module "rls" \
+		&& check_module "presence_mwi" && check_module "pua_bla" \
+		&& check_module "pua_mi" && check_module "pua_usrloc" \
+		&& check_module "pua_xmpp" && check_module "xmpp" \
+		&& check_module "presence_dialoginfo" && check_module "pua_dialoginfo" \
+		&& check_mysql); then
+	exit 0
+fi ;
+
+cp $CFG $CFG.bak
+
+echo "loadmodule \"../../modules/db_mysql/db_mysql.so\"" >> $CFG
+
+# start
+$BIN -w . -f $CFG > /dev/null
+ret=$?
+
+sleep 1
+$KILL
+
+mv $CFG.bak $CFG
+
+exit $ret
\ No newline at end of file
diff --git a/test/unit/35.cfg b/test/unit/35.cfg
new file mode 100644
index 0000000..1c436da
--- /dev/null
+++ b/test/unit/35.cfg
@@ -0,0 +1,56 @@
+# Kamailio config for lookup / registrar testing
+
+#------------------------Global configuration----------------------------------
+debug=3
+fork=yes
+log_stderror=no
+listen=127.0.0.1
+port=5060
+dns=no
+rev_dns=no
+
+#-----------------------Loading Modules-------------------------------------
+mpath="../modules/"
+loadmodule "db_mysql/db_mysql.so"
+loadmodule "usrloc/usrloc.so"
+loadmodule "registrar/registrar.so"
+loadmodule "sl/sl.so"
+loadmodule "tm/tm.so"
+loadmodule "pv/pv.so"
+loadmodule "permissions/permissions.so"
+loadmodule "maxfwd/maxfwd.so"
+loadmodule "mi_fifo/mi_fifo.so"
+loadmodule "xlog/xlog.so"
+
+
+#-----------------------Module parameters-------------------------------------
+modparam("mi_fifo", "fifo_name", "/tmp/kamailio_fifo")
+modparam("usrloc", "db_mode", 3)
+modparam("usrloc|permissions", "db_url", "mysql://kamailio:kamailiorw@localhost/kamailio")
+
+#-----------------------Routing configuration---------------------------------#
+route{
+if (!mf_process_maxfwd_header("10")) {
+	sl_send_reply("483","Too Many Hops");
+	exit();
+}
+
+if (!allow_address("0", "$si", "$sp") || !allow_source_address("0")) {
+	#xlog("permissions allow_address");
+	sl_send_reply("403", "Forbidden");
+}
+
+if (!allow_trusted())  {
+	xlog("permissions allow_trusted");
+	sl_send_reply("403", "Forbidden");
+}
+
+if(!lookup ("location")){
+	sl_send_reply("404", "Not Found");
+}
+
+if (!t_relay()) {
+	sl_reply_error();
+	}
+}
+
diff --git a/test/unit/35.sh b/test/unit/35.sh
new file mode 100755
index 0000000..c16ad0b
--- /dev/null
+++ b/test/unit/35.sh
@@ -0,0 +1,72 @@
+#!/bin/bash
+# check permissions module functionality
+
+# Copyright (C) 2008 1&1 Internet AG
+#
+# This file is part of Kamailio, a free SIP server.
+#
+# Kamailio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version
+#
+# Kamailio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+source include/common
+source include/require
+source include/database
+
+if ! (check_sipp && check_kamailio && check_module "db_mysql" && check_mysql); then
+	exit 0
+fi ;
+
+CFG=35.cfg
+SRV=5060
+UAS=5070
+UAC=5080
+IP="127.0.0.31"
+MASK=27
+
+# add an registrar entry to the db;
+$MYSQL "INSERT INTO location (username,contact,socket,user_agent,cseq,q) VALUES (\"foo\",\"sip:foo at localhost:$UAS\",\"udp:127.0.0.1:$UAS\",\"ser_test\",1,-1);"
+$MYSQL "INSERT INTO trusted (src_ip, proto) VALUES (\"127.0.0.1\",\"any\");"
+
+$MYSQL "INSERT INTO address (ip_addr, mask) VALUES ('$IP', '$MASK');"
+
+../$BIN -w . -f $CFG &> /dev/null
+sipp -sn uas -bg -i localhost -m 10 -f 2 -p $UAS &> /dev/null
+sipp -sn uac -s foo 127.0.0.1:$SRV -i localhost -m 10 -f 2 -p $UAC &> /dev/null
+ret=$?
+$MYSQL "DELETE FROM address WHERE (ip_addr='$IP' AND mask='$MASK');"
+
+if [ "$ret" -eq 0 ] ; then
+	killall sipp
+	IP="127.47.6.254"
+	MASK=10
+	$MYSQL "INSERT INTO address (ip_addr, mask) VALUES ('$IP', '$MASK');"
+	
+	$CTL fifo address_reload
+	#$CTL fifo address_dump
+
+	sipp -sn uas -bg -i localhost -m 10 -f 2 -p $UAS &> /dev/null
+	sipp -sn uac -s foo 127.0.0.1:$SRV -i localhost -m 10 -f 2 -p $UAC &> /dev/null
+	ret=$?
+	$MYSQL "DELETE FROM address WHERE (ip_addr='$IP' AND mask='$MASK');"
+fi;
+
+
+# cleanup
+killall -9 sipp > /dev/null 2>&1
+$KILL > /dev/null 2>&1
+
+$MYSQL "DELETE FROM location WHERE ((contact = \"sip:foo at localhost:$UAS\") and (user_agent = \"ser_test\"));"
+$MYSQL "DELETE FROM trusted WHERE (src_ip=\"127.0.0.1\");"
+
+exit $ret;
diff --git a/test/unit/36.sh b/test/unit/36.sh
new file mode 100755
index 0000000..da63623
--- /dev/null
+++ b/test/unit/36.sh
@@ -0,0 +1,81 @@
+#!/bin/bash
+# private memory effiency and fragmentation with ul_dump w/ or w/o PKG_MALLOC
+
+# Copyright (C) 2008 1&1 Internet AG
+#
+# This file is part of Kamailio, a free SIP server.
+#
+# Kamailio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version
+#
+# Kamailio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+source include/common
+source include/require
+source include/database
+
+if ! (check_kamailio && check_module "db_mysql" && check_mysql); then
+	exit 0
+fi ;
+
+CFG=11.cfg
+
+cp $CFG $CFG.bak
+
+echo "loadmodule \"../../modules/db_mysql/db_mysql.so\"" >> $CFG
+
+# 1768 contacts should fit into 1 MB of PKG memory
+$BIN -V | grep "PKG_MALLOC" > /dev/null
+if [ $? -eq 0 ]; then
+	NR=176
+else
+	NR=277
+fi;
+
+COUNTER=0
+while [  $COUNTER -lt $NR ]; do
+	COUNTER=$(($COUNTER+1))
+	$MYSQL "insert into location (username, domain, contact, user_agent) values ('foobar-$COUNTER-$RANDOM', 'local', 'foobar-$COUNTER-$RANDOM@$DOMAIN', '___test___'); \
+	insert into location (username, domain, contact, user_agent) values ('foobar-$COUNTER-$RANDOM', 'local', 'foobar-$COUNTER-$RANDOM@$DOMAIN', '___test___'); \
+	insert into location (username, domain, contact, user_agent) values ('foobar-$COUNTER-$RANDOM', 'local', 'foobar-$COUNTER-$RANDOM@$DOMAIN', '___test___'); \
+	insert into location (username, domain, contact, user_agent) values ('foobar-$COUNTER-$RANDOM', 'local', 'foobar-$COUNTER-$RANDOM@$DOMAIN', '___test___'); \
+	insert into location (username, domain, contact, user_agent) values ('foobar-$COUNTER-$RANDOM', 'local', 'foobar-$COUNTER-$RANDOM@$DOMAIN', '___test___'); \
+	insert into location (username, domain, contact, user_agent) values ('foobar-$COUNTER-$RANDOM', 'local', 'foobar-$COUNTER-$RANDOM@$DOMAIN', '___test___'); \
+	insert into location (username, domain, contact, user_agent) values ('foobar-$COUNTER-$RANDOM', 'local', 'foobar-$COUNTER-$RANDOM@$DOMAIN', '___test___'); \
+	insert into location (username, domain, contact, user_agent) values ('foobar-$COUNTER-$RANDOM', 'local', 'foobar-$COUNTER-$RANDOM@$DOMAIN', '___test___'); \
+	insert into location (username, domain, contact, user_agent) values ('foobar-$COUNTER-$RANDOM', 'local', 'foobar-$COUNTER-$RANDOM@$DOMAIN', '___test___'); \
+	insert into location (username, domain, contact, user_agent) values ('foobar-$COUNTER-$RANDOM', 'local', 'foobar-$COUNTER-$RANDOM@$DOMAIN', '___test___');"
+done
+
+$BIN -w . -f $CFG > /dev/null
+ret=$?
+
+if [ $ret -eq 0 ]; then
+	sleep 1
+	for ((i=1;i<=100;i+=1)); do
+		tmp=$($CTL fifo ul_dump | grep "User-agent:: ___test___" | wc -l)
+		NR_=$(($NR * 10))
+		if ! [ $tmp -eq $NR_ ]; then
+			ret=1
+			break;
+		fi;
+	done
+fi;
+
+sleep 1
+$KILL
+
+$MYSQL "delete from location where user_agent = '___test___'"
+
+mv $CFG.bak $CFG
+
+exit $ret
diff --git a/test/unit/37.sh b/test/unit/37.sh
new file mode 100755
index 0000000..9f7007e
--- /dev/null
+++ b/test/unit/37.sh
@@ -0,0 +1,114 @@
+#!/bin/bash
+# loading times for bigger carrierroute config from mysql database
+
+# Copyright (C) 2007 1&1 Internet AG
+#
+# This file is part of Kamailio, a free SIP server.
+#
+# Kamailio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version
+#
+# Kamailio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+source include/common
+source include/require
+source include/database
+
+CFG=13.cfg
+# number of routes, multiplied with 10
+# if you want to increase this above 4500, comment the fifo command below,
+# otherwise this will fails with memory allocation errors (with 1MB PKG mem)
+NR=450
+
+if ! (check_kamailio && check_module "carrierroute" && check_module "db_mysql" && check_mysql); then
+	exit 0
+fi ;
+
+cp $CFG $CFG.bak
+
+# setup config
+echo "loadmodule \"../../modules/db_mysql/db_mysql.so\"" >> $CFG
+echo "modparam(\"carrierroute\", \"config_source\", \"db\")" >> $CFG
+
+# setup database
+$MYSQL "insert into carrier_name (id, carrier) values ('1', 'default');"
+$MYSQL "insert into carrier_name (id, carrier) values ('2', 'carrier2');"
+$MYSQL "insert into carrier_name (id, carrier) values ('3', 'carrier3');"
+$MYSQL "insert into carrier_name (id, carrier) values ('4', 'carrier4');"
+$MYSQL "insert into carrier_name (id, carrier) values ('5', 'carrier5');"
+$MYSQL "insert into carrier_name (id, carrier) values ('6', 'carrier6');"
+$MYSQL "insert into carrier_name (id, carrier) values ('7', 'carrier7');"
+$MYSQL "insert into carrier_name (id, carrier) values ('8', 'carrier8');"
+$MYSQL "insert into carrier_name (id, carrier) values ('9', 'carrier9');"
+$MYSQL "insert into carrier_name (id, carrier) values ('10', 'carrier10');"
+$MYSQL "insert into carrier_name (id, carrier) values ('11', 'carrier11');"
+
+
+COUNTER=0
+while [  $COUNTER -lt $NR ]; do
+	COUNTER=$(($COUNTER+1))
+	domain=`expr $COUNTER % 9`
+	$MYSQL "insert into domain_name (id, domain) values ('$COUNTER', '$domain');"
+	$MYSQL "insert into carrierroute (carrier, domain, scan_prefix, prob, strip, rewrite_host) values ('2','$COUNTER','$RANDOM','0.5','0','host-$RANDOM'); insert into carrierroute (carrier, domain, scan_prefix, prob, strip, rewrite_host) values ('3','$COUNTER','$RANDOM','0.5','0','host-$RANDOM'); insert into carrierroute (carrier, domain, scan_prefix, prob, strip, rewrite_host) values ('4','$COUNTER','$RANDOM','0.5','0','host-$RANDOM'); insert into carrierroute (carrier, domain, scan_prefix [...]
+
+done
+
+$BIN -m 128 -w . -f $CFG > /dev/null
+ret=$?
+
+# adjust if you have bigger rule sets
+sleep 20
+
+if [ $ret -eq 0 ] ; then
+	tmp=`$CTL fifo cr_dump_routes | grep "host-" | wc -l`
+	let "TMPNR = $NR * 10"
+	if ! [ $tmp -eq $TMPNR ]; then
+		ret=1
+	fi;
+fi ;
+
+$KILL
+
+# cleanup database
+$MYSQL "delete from carrier_name where id = 1;"
+$MYSQL "delete from carrier_name where id = 2;"
+$MYSQL "delete from carrier_name where id = 3;"
+$MYSQL "delete from carrier_name where id = 4;"
+$MYSQL "delete from carrier_name where id = 5;"
+$MYSQL "delete from carrier_name where id = 6;"
+$MYSQL "delete from carrier_name where id = 7;"
+$MYSQL "delete from carrier_name where id = 8;"
+$MYSQL "delete from carrier_name where id = 9;"
+$MYSQL "delete from carrier_name where id = 10;"
+$MYSQL "delete from carrier_name where id = 11;"
+
+COUNTER=0
+while [  $COUNTER -lt $NR ]; do
+	COUNTER=$(($COUNTER+1))
+	$MYSQL "delete from domain_name where id = $COUNTER;"
+done
+
+$MYSQL "delete from carrierroute where carrier=1;"
+$MYSQL "delete from carrierroute where carrier=2;"
+$MYSQL "delete from carrierroute where carrier=3;"
+$MYSQL "delete from carrierroute where carrier=4;"
+$MYSQL "delete from carrierroute where carrier=5;"
+$MYSQL "delete from carrierroute where carrier=6;"
+$MYSQL "delete from carrierroute where carrier=7;"
+$MYSQL "delete from carrierroute where carrier=8;"
+$MYSQL "delete from carrierroute where carrier=9;"
+$MYSQL "delete from carrierroute where carrier=10;"
+$MYSQL "delete from carrierroute where carrier=11;"
+
+mv $CFG.bak $CFG
+
+exit $ret
diff --git a/test/unit/38.sh b/test/unit/38.sh
new file mode 100755
index 0000000..65e8d3c
--- /dev/null
+++ b/test/unit/38.sh
@@ -0,0 +1,48 @@
+#!/bin/bash
+# load all modules without external dependencies with unixodbc
+
+# Copyright (C) 2008 1&1 Internet AG
+#
+# This file is part of Kamailio, a free SIP server.
+#
+# Kamailio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version
+#
+# Kamailio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+source include/common
+source include/require
+source include/database
+
+# Needs a default kamailio database setup for unixodbc
+
+if ! (check_kamailio && check_module "db_unixodbc" && check_unixodbc); then
+	exit 0
+fi ;
+
+CFG=2.cfg
+cp $CFG $CFG.bak
+
+echo "loadmodule \"db_unixodbc/db_unixodbc.so\"" >> $CFG
+echo "modparam(\"$DB_ALL_MOD\", \"db_url\", \"unixodbc://kamailioro:kamailioro@localhost/kamailio\")" >> $CFG
+
+# start
+$BIN -w . -f $CFG > /dev/null
+ret=$?
+
+sleep 1
+$KILL
+
+mv $CFG.bak $CFG
+rm -f dispatcher.list
+
+exit $ret
diff --git a/test/unit/39.sh b/test/unit/39.sh
new file mode 100755
index 0000000..9a3757a
--- /dev/null
+++ b/test/unit/39.sh
@@ -0,0 +1,62 @@
+#!/bin/bash
+# database access with fetch_result for usrloc on unixodbc
+
+# Copyright (C) 2008 1&1 Internet AG
+#
+# This file is part of Kamailio, a free SIP server.
+#
+# Kamailio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version
+#
+# Kamailio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+source include/common
+source include/require
+source include/database
+
+if ! (check_sipp && check_kamailio && check_module "db_unixodbc" && check_unixodbc); then
+	exit 0
+fi ;
+
+
+CFG=11.cfg
+
+DOMAIN="local"
+# setup 250 contacts
+NR=25
+
+cp $CFG $CFG.bak
+
+echo "loadmodule \"$SRC_DIR/modules/db_unixodbc/db_unixodbc.so\"" >> $CFG
+echo "modparam(\"usrloc\", \"db_url\", \"unixodbc://kamailio:kamailiorw@localhost/kamailio\")" >> $CFG
+echo "modparam(\"usrloc\", \"fetch_rows\", 13)" >> $CFG
+
+# isql unfortunally only allow one statement per line
+COUNTER=0
+CNT=0
+while [  $COUNTER -lt $NR ]; do
+	COUNTER=$(($COUNTER+1))
+	echo -e "insert into location (id, username, domain, contact, user_agent) values ('$CNT', 'foobar-$RANDOM', '$DOMAIN', 'foobar-$RANDOM@$DOMAIN', '___test___'); \n insert into location (id, username, domain, contact, user_agent) values ('$(($CNT+1))', 'foobar-$RANDOM', '$DOMAIN', 'foobar-$RANDOM@$DOMAIN', '___test___'); \n insert into location (id, username, domain, contact, user_agent) values ('$(($CNT+2))', 'foobar-$RANDOM', '$DOMAIN', 'foobar-$RANDOM@$DOMAIN', '___test___'); \n insert [...]
+	CNT=$(($CNT+10))
+done
+
+$BIN -w . -f $CFG > /dev/null
+ret=$?
+
+sleep 2
+$KILL
+
+echo "delete from location where user_agent = '___test___'" | $ISQL > /dev/null
+
+mv $CFG.bak $CFG
+
+exit $ret
diff --git a/test/unit/4.sh b/test/unit/4.sh
new file mode 100755
index 0000000..452249e
--- /dev/null
+++ b/test/unit/4.sh
@@ -0,0 +1,51 @@
+#!/bin/bash
+# test basic fifo functionality
+
+# Copyright (C) 2007 1&1 Internet AG
+#
+# This file is part of Kamailio, a free SIP server.
+#
+# Kamailio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version
+#
+# Kamailio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+source include/common
+source include/require
+
+CFG=4.cfg
+
+if ! (check_kamailio); then
+	exit 0
+fi ;
+
+# setup config
+echo -e "loadmodule \"$SRC_DIR/modules/mi_fifo/mi_fifo.so\"" > $CFG
+echo -e "loadmodule \"$SRC_DIR/modules/kex/kex.so\"" >> $CFG
+echo -e "modparam(\"mi_fifo\", \"fifo_name\", \"/tmp/kamailio_fifo\")" >> $CFG
+echo -e "\nrequest_route {\n ;\n}" >> $CFG
+
+        
+$BIN -w . -f $CFG > /dev/null
+ret=$?
+
+if [ "$ret" -eq 0 ] ; then
+	sleep 1
+	$CTL version > /dev/null
+	ret=$?
+fi ;
+
+$KILL
+
+rm -f $CFG
+
+exit $ret
diff --git a/test/unit/40.cfg b/test/unit/40.cfg
new file mode 100644
index 0000000..9b4ed86
--- /dev/null
+++ b/test/unit/40.cfg
@@ -0,0 +1,33 @@
+
+loadpath "../../modules_k:../../modules/"
+
+loadmodule "tm/tm.so"
+loadmodule "sl/sl.so"
+loadmodule "db_mysql/db_mysql.so"
+loadmodule "usrloc/usrloc.so"
+loadmodule "registrar/registrar.so"
+loadmodule "pike/pike.so"
+loadmodule "xlog/xlog.so"
+
+modparam("usrloc", "db_mode", 3)
+modparam("usrloc", "db_url", "mysql://kamailio:kamailiorw@localhost/kamailio")
+
+modparam("pike", "sampling_time_unit", 5)
+modparam("pike", "reqs_density_per_unit", 25)
+modparam("pike", "remove_latency", 5)
+modparam("pike", "pike_log_level", 2)
+ 
+route{
+	if (!pike_check_req()) {
+		xlog("drop request");
+		sl_send_reply("500", "overloaded");
+	}
+
+	if(!lookup ("location")){
+		sl_send_reply("404", "Not Found");
+	}
+
+	if (!t_relay()) {
+		sl_reply_error();
+	}
+}
diff --git a/test/unit/40.sh b/test/unit/40.sh
new file mode 100755
index 0000000..6e2b298
--- /dev/null
+++ b/test/unit/40.sh
@@ -0,0 +1,73 @@
+#!/bin/bash
+# check pike module
+
+# Copyright (C) 2008 1&1 Internet AG
+#
+# This file is part of Kamailio, a free SIP server.
+#
+# Kamailio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version
+#
+# Kamailio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+# Needs a default kamailio database setup for mysql
+
+source include/common
+source include/require
+source include/database
+
+CFG=40.cfg
+SRV=5060
+UAS=5070
+UAC=5080
+
+if ! (check_sipp && check_kamailio && check_module "db_mysql" && check_mysql); then
+	exit 0
+fi ;
+
+# add an registrar entry to the db;
+$MYSQL "INSERT INTO location (username,contact,socket,user_agent,cseq,q) VALUES (\"foo\",\"sip:foo at 127.0.0.1:$UAS\",\"udp:127.0.0.1:$UAS\",\"ser_test\",1,-1);"
+
+# start
+$BIN -w . -f $CFG &> /dev/null
+ret=$?
+
+# this should work
+if [ "$ret" -eq 0 ]; then
+	sipp -sn uas -bg -i 127.0.0.1 -m 10 -p $UAS &> /dev/null
+	sipp -sn uac -s foo 127.0.0.1:$SRV -i 127.0.0.1 -m 10 -p $UAC &> /dev/null
+	ret=$?
+fi;
+
+# this should be trigger the blocking
+if [ "$ret" -eq 0 ]; then
+	killall -9 sipp > /dev/null 2>&1
+	sipp -sn uas -bg -i 127.0.0.1 -m 11 -p $UAS &> /dev/null
+	sipp -sn uac -s foo 127.0.0.1:$SRV -i 127.0.0.1 -m 11 -p $UAC &> /dev/null
+	ret=$?
+fi;
+
+# this should work again after the timeout
+if [ "$ret" -eq 1 ]; then
+	sleep 7
+	killall -9 sipp > /dev/null 2>&1
+	sipp -sn uas -bg -i 127.0.0.1 -m 15 -p $UAS &> /dev/null
+	sipp -sn uac -s foo 127.0.0.1:$SRV -i 127.0.0.1 -m 15 -p $UAC &> /dev/null
+	ret=$?
+fi;
+
+sleep 1
+$KILL
+killall -9 sipp > /dev/null 2>&1
+
+$MYSQL "DELETE FROM location WHERE ((contact = \"sip:foo at 127.0.0.1:$UAS\") and (user_agent = \"ser_test\"));"
+exit $ret
\ No newline at end of file
diff --git a/test/unit/41.cfg b/test/unit/41.cfg
new file mode 100644
index 0000000..0000364
--- /dev/null
+++ b/test/unit/41.cfg
@@ -0,0 +1,44 @@
+#memlog=1
+debug=1
+children=1
+loadpath "../../modules_k:../../modules/"
+
+loadmodule "tm/tm.so"
+loadmodule "sl/sl.so"
+loadmodule "db_mysql/db_mysql.so"
+loadmodule "usrloc/usrloc.so"
+loadmodule "registrar/registrar.so"
+loadmodule "pv/pv.so"
+loadmodule "avpops/avpops.so"
+loadmodule "mi_fifo/mi_fifo.so"
+loadmodule "xlog/xlog.so"
+
+modparam("usrloc", "db_mode", 3)
+modparam("usrloc|avpops", "db_url", "mysql://kamailio:kamailiorw@localhost/kamailio")
+
+modparam("avpops","avp_table","usr_preferences")
+modparam("mi_fifo", "fifo_name", "/tmp/kamailio_fifo")
+
+route{
+	$avp(s:10) = "foobar";
+	if (!avp_db_load("$avp(s:10)", "$avp(s:679)")) {
+		xlog("avp_db_load failed");
+		sl_reply_error();
+		exit;
+	}
+	
+	$avp(s:679) = "blafasel";
+	if (!avp_db_store("$avp(s:10)", "$avp(s:679)")) {
+		xlog("avp_db_store failed");
+		sl_reply_error();
+		exit;
+	}
+
+	if(!lookup ("location")){
+		sl_send_reply("404", "Not Found");
+	}
+
+	if (!t_relay()) {
+		sl_reply_error();
+	}
+}
diff --git a/test/unit/41.sh b/test/unit/41.sh
new file mode 100755
index 0000000..7e2be14
--- /dev/null
+++ b/test/unit/41.sh
@@ -0,0 +1,63 @@
+#!/bin/bash
+# test one out of PKG_MEM condition with avpops module
+
+# Copyright (C) 2008 1&1 Internet AG
+#
+# This file is part of Kamailio, a free SIP server.
+#
+# Kamailio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version
+#
+# Kamailio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+# Needs a default kamailio database setup for mysql
+
+source include/common
+source include/require
+source include/database
+
+CFG=41.cfg
+SRV=5060
+UAS=5070
+UAC=5080
+
+NR=200
+RT=50
+
+if ! (check_sipp && check_kamailio && check_module "db_mysql" && check_mysql); then
+	exit 0
+fi ;
+
+# add an registrar entry to the db;
+$MYSQL "INSERT INTO location (username,contact,socket,user_agent,cseq,q) VALUES (\"foo\",\"sip:foo at 127.0.0.1:$UAS\",\"udp:127.0.0.1:$UAS\",\"ser_test\",1,-1);"
+
+$MYSQL "INSERT INTO usr_preferences (uuid, attribute, type, value) VALUES (\"foobar\", \"679\", 0, \"foobar!!!!!\");"
+
+# start
+
+$BIN -w . -f $CFG &> /dev/null
+ret=$?
+
+if [ "$ret" -eq 0 ]; then
+	sipp -sn uas -bg  -i 127.0.0.1 -m $NR -r $RT -p $UAS &> /dev/null
+	sipp -sn uac -s foo 127.0.0.1:$SRV -r $RT -i 127.0.0.1 -m $NR -p $UAC &> /dev/null
+	ret=$?
+fi;
+
+sleep 1
+$KILL
+killall -9 sipp > /dev/null 2>&1
+
+$MYSQL "DELETE FROM location WHERE ((contact = \"sip:foo at 127.0.0.1:$UAS\") and (user_agent = \"ser_test\"));"
+$MYSQL "DELETE FROM usr_preferences;"
+exit $ret
+
diff --git a/test/unit/42.sh b/test/unit/42.sh
new file mode 100755
index 0000000..8a30d2f
--- /dev/null
+++ b/test/unit/42.sh
@@ -0,0 +1,148 @@
+#!/bin/bash
+# do some (non numerical) routing with carrierroute route sets from mysql database
+
+# Copyright (C) 2007 1&1 Internet AG
+#
+# This file is part of Kamailio, a free SIP server.
+#
+# Kamailio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version
+#
+# Kamailio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+source include/common
+source include/require
+source include/database
+
+if ! (check_kamailio && check_module "carrierroute" && check_module "db_mysql" && check_mysql); then
+	exit 0
+fi ;
+
+CFG=26.cfg
+
+cp $CFG $CFG.bak
+
+# setup config
+echo "loadmodule \"../../modules/db_mysql/db_mysql.so\"" >> $CFG
+echo "modparam(\"carrierroute\", \"config_source\", \"db\")" >> $CFG
+echo "modparam(\"carrierroute\", \"match_mode\", 128)" >> $CFG
+
+# setup database
+$MYSQL "insert into carrier_name (id, carrier) values ('1', 'default');"
+$MYSQL "insert into carrier_name (id, carrier) values ('2', 'carrier1');"
+$MYSQL "insert into carrier_name (id, carrier) values ('3', 'carrier2');"
+
+$MYSQL "insert into domain_name (id, domain) values ('10', 'domain0');"
+$MYSQL "insert into domain_name (id, domain) values ('1', 'fallback');"
+$MYSQL "insert into domain_name (id, domain) values ('2', 'domain2');"
+
+$MYSQL "insert into carrierroute (id, carrier, domain, scan_prefix, flags, prob, strip, rewrite_host)
+values ('1','1','10','ab4-','0','0.5','0','127.0.0.1:7000');"
+$MYSQL "insert into carrierroute (id, carrier, domain, scan_prefix, flags, prob, strip, rewrite_host)
+values ('2','1','10','ab4-','0','0.5','0','127.0.0.1:8000');"
+$MYSQL "insert into carrierroute (id, carrier, domain, scan_prefix, flags, prob, strip, rewrite_host)
+values ('3','2','10','ab4-','0','1','0','127.0.0.1:9000');"
+$MYSQL "insert into carrierroute (id, carrier, domain, scan_prefix, flags, mask,prob, strip, rewrite_host)
+values ('4','3','10','ab4-','0', '3', '1','0','127.0.0.1:10001');"
+$MYSQL "insert into carrierroute (id, carrier, domain, scan_prefix, flags, mask,prob, strip, rewrite_host)
+values ('5','3','10','ab4-','1', '3', '1','0','127.0.0.1:10000');"
+$MYSQL "insert into carrierroute (id, carrier, domain, scan_prefix, flags, mask, prob, strip, rewrite_host)
+values ('6','3','10','ab4-','2', '3', '1','0','127.0.0.1:10002');"
+$MYSQL "insert into carrierroute (id, carrier, domain, scan_prefix, flags, prob, strip, rewrite_host)
+values ('7','3','1','ab4-','0','1','0','127.0.0.1:10000');"
+$MYSQL "insert into carrierroute (id, carrier, domain, scan_prefix, flags, prob, strip, rewrite_host)
+values ('8','3','2','ab4-','0','1','0','127.0.0.1:10000');"
+
+$MYSQL "insert into carrierfailureroute(id, carrier, domain, scan_prefix, host_name, reply_code,
+flags, mask, next_domain) values ('1', '3', '10', 'ab4-', '127.0.0.1:10000', '5..', '0', '0', '1');"
+$MYSQL "insert into carrierfailureroute(id, carrier, domain, scan_prefix, host_name, reply_code,
+flags, mask, next_domain) values ('2', '3', '1', 'ab4-', '127.0.0.1:10000', '483', '0', '0', '2');"
+$MYSQL "insert into carrierfailureroute(id, carrier, domain, scan_prefix, host_name, reply_code,
+flags, mask, next_domain) values ('3', '3', '1', 'ab4-', '127.0.0.1:9000', '4..', '0', '0', '2');"
+
+$MYSQL "alter table subscriber add cr_preferred_carrier int(10) default NULL;"
+
+$MYSQL "insert into subscriber (username, cr_preferred_carrier) values ('ab4-123456786', 2);"
+$MYSQL "insert into subscriber (username, cr_preferred_carrier) values ('ab4-123456785', 3);"
+
+
+$BIN -w . -f $CFG > /dev/null
+
+ret=$?
+
+sleep 1
+
+if [ "$ret" -eq 0 ] ; then
+	sipp -sn uas -bg -i 127.0.0.1 -m 12 -p 7000 &> /dev/null
+	sipp -sn uas -bg -i 127.0.0.1 -m 12 -p 8000 &> /dev/null
+	sipp -sn uac -s ab4-123456787 127.0.0.1:5060 -i 127.0.0.1 -m 20 -p 5061 &> /dev/null
+	ret=$?
+	killall sipp &> /dev/null
+fi;
+
+if [ "$ret" -eq 0 ] ; then
+	sipp -sn uas -bg -i 127.0.0.1 -m 10 -p 9000 &> /dev/null
+	sipp -sn uac -s ab4-123456786 127.0.0.1:5060 -i 127.0.0.1 -m 10 -p 5061 &> /dev/null
+	ret=$?
+fi;
+
+if [ "$ret" -eq 0 ] ; then
+	sipp -sn uas -bg -i 127.0.0.1 -m 10 -p 10000 &> /dev/null
+	sipp -sn uac -s ab4-123456785 127.0.0.1:5060 -i 127.0.0.1 -m 10 -p 5061 &> /dev/null
+	ret=$?
+fi;
+
+if [ "$ret" -eq 0 ] ; then
+	killall sipp &> /dev/null
+	sipp -sf failure_route.xml -bg -i 127.0.0.1 -m 10 -p 10000 &> /dev/null
+	sipp -sn uac -s ab4-123456785 127.0.0.1:5060 -i 127.0.0.1 -m 10 -p 5061 &> /dev/null
+	ret=$?
+fi;
+
+$MYSQL "insert into carrierfailureroute(id, carrier, domain, scan_prefix, host_name, reply_code,
+flags, mask, next_domain) values ('4', '3', '1', 'ab4-', '127.0.0.1:10000', '4..', '0', '0', '4');"
+$MYSQL "insert into carrierfailureroute(id, carrier, domain, scan_prefix, host_name, reply_code,
+flags, mask, next_domain) values ('5', '3', '1', 'ab4-', '127.0.0.1:10000', '486', '0', '0', '2');"
+
+if [ ! "$ret" -eq 0 ] ; then
+	$CTL fifo cr_reload_routes
+	killall sipp &> /dev/null
+	sipp -sf failure_route.xml -bg -i 127.0.0.1 -m 10 -p 10000 &> /dev/null
+	sipp -sn uac -s ab4-123456785 127.0.0.1:5060 -i 127.0.0.1 -m 10 -p 5061 &> /dev/null
+	ret=$?
+fi;
+
+
+$KILL
+killall -9 sipp
+
+# cleanup database
+$MYSQL "delete from carrier_name where id = 1;"
+$MYSQL "delete from carrier_name where id = 2;"
+$MYSQL "delete from carrier_name where id = 3;"
+$MYSQL "delete from domain_name where id = 10;"
+$MYSQL "delete from domain_name where id = 1;"
+$MYSQL "delete from domain_name where id = 2;"
+$MYSQL "delete from carrierroute where carrier=1;"
+$MYSQL "delete from carrierroute where carrier=2;"
+$MYSQL "delete from carrierroute where carrier=3;"
+$MYSQL "delete from carrierfailureroute where carrier=1;"
+$MYSQL "delete from carrierfailureroute where carrier=2;"
+$MYSQL "delete from carrierfailureroute where carrier=3;"
+
+$MYSQL "delete from subscriber where username='ab4-123456786';"
+$MYSQL "delete from subscriber where username='ab4-123456785';"
+$MYSQL "alter table subscriber drop cr_preferred_carrier;"
+
+mv $CFG.bak $CFG
+
+exit $ret
\ No newline at end of file
diff --git a/test/unit/43.sh b/test/unit/43.sh
new file mode 100755
index 0000000..db5efbe
--- /dev/null
+++ b/test/unit/43.sh
@@ -0,0 +1,102 @@
+#!/bin/bash
+# check forward functionality in utils module
+
+# Copyright (C) 2009 1&1 Internet AG
+#
+# This file is part of Kamailio, a free SIP server.
+#
+# Kamailio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version
+#
+# Kamailio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+source include/common
+source include/require
+source include/database
+
+if ! (check_kamailio && check_module "utils" && check_module "db_mysql" && check_mysql); then
+	exit 0
+fi ;
+
+CFG=43.cfg
+TMPFILE=`mktemp -t kamailio-test.XXXXXXXXX`
+# setup config
+echo "mpath=\"../../modules\"" > $CFG
+echo "loadmodule \"../../modules/tm/tm.so\"" >> $CFG
+echo "loadmodule \"sl/sl.so\"" >> $CFG
+echo "loadmodule \"mi_fifo/mi_fifo.so\"" >> $CFG
+echo "loadmodule \"../../modules/utils/utils.so\"" >> $CFG
+echo "modparam(\"mi_fifo\", \"fifo_name\", \"/tmp/kamailio_fifo\")" >> $CFG
+echo "modparam(\"utils\", \"forward_active\", 1)" >> $CFG
+echo "route {sl_send_reply(\"404\", \"forbidden\");}" >> $CFG
+
+$BIN -w . -f $CFG > /dev/null
+
+
+ret=$?
+
+sleep 1
+
+$CTL fifo forward_list &> /dev/null
+$CTL fifo forward_filter 0=REGISTER:INVITE &> /dev/null
+$CTL fifo forward_list &> /dev/null
+$CTL fifo forward_proxy 0=127.0.0.1:7000 &> /dev/null
+$CTL fifo forward_list > $TMPFILE 
+
+
+
+tmp=`grep -v "Printing forwarding information:
+id switch                         filter proxy
+ 0 off                    REGISTER:INVITE 127.0.0.1:7000" $TMPFILE`
+if [ "$tmp" = "" ] ; then
+	ret=0
+else
+	ret=1
+fi ;
+
+
+if [ "$ret" -eq 0 ] ; then
+	sipp -sn uac -s 123456787 127.0.0.1:5060 -i 127.0.0.1 -m 1 -nr &> /dev/null
+	ret=$?
+	killall sipp &> /dev/null
+fi;
+
+
+if ! [ "$ret" -eq 0 ] ; then
+	$CTL fifo forward_switch 0=on
+	$CTL fifo forward_list > $TMPFILE
+	tmp=`grep -v "Printing forwarding information:
+id switch                         filter proxy
+ 0 on                    REGISTER:INVITE 127.0.0.1:7000" $TMPFILE`
+	if [ "$tmp" = "" ] ; then
+		ret=0
+	else
+		ret=1
+	fi ;
+	nc -l -u -p 7000 1> $TMPFILE 2> /dev/null &
+	sipp -sn uac -s 123456787 127.0.0.1:5060 -i 127.0.0.1 -m 1 -nr  &> /dev/null
+	killall sipp &> /dev/null
+	killall nc &> /dev/null
+fi;
+
+NR=`cat $TMPFILE | grep "INVITE sip:" | wc -l`
+if [ "$NR" -eq 1 ] ; then
+	ret=0
+else
+	ret=1
+fi;
+
+rm $CFG
+rm $TMPFILE
+$KILL
+
+exit $ret
diff --git a/test/unit/44.sh b/test/unit/44.sh
new file mode 100755
index 0000000..0bb4083
--- /dev/null
+++ b/test/unit/44.sh
@@ -0,0 +1,109 @@
+#!/bin/bash
+# database access and persistent storage for registrar on unixodbc
+
+# Copyright (C) 2009 1&1 Internet AG
+#
+# This file is part of Kamailio, a free SIP server.
+#
+# Kamailio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version
+#
+# Kamailio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+source include/common
+source include/require
+source include/database
+
+if ! (check_sipsak && check_kamailio && check_module "db_unixodbc" && check_unixodbc); then
+	exit 0
+fi ;
+
+CFG=11.cfg
+
+cp $CFG $CFG.tmp
+echo "loadmodule \"$SRC_DIR/modules/db_unixodbc/db_unixodbc.so\"" >> $CFG
+echo "modparam(\"usrloc\", \"db_url\", \"unixodbc://kamailio:kamailiorw@localhost/kamailio\")" >> $CFG
+
+$BIN -w . -f $CFG > /dev/null
+ret=$?
+
+sleep 1
+# register a user
+sipsak -U -C sip:foobar at localhost -s sip:49721123456789 at localhost -H localhost &> /dev/null
+ret=$?
+
+if [ "$ret" -eq 0 ]; then
+	$CTL ul show | grep "AOR:: 49721123456789" > /dev/null
+	ret=$?
+fi;
+
+if [ "$ret" -eq 0 ]; then
+	TMP=`echo "select COUNT(*) from location where username='49721123456789';" | $ISQL`
+	if [ "$TMP" -eq 0 ] ; then
+		ret=1
+	fi;
+fi;
+
+if [ "$ret" -eq 0 ]; then
+	# unregister the user
+	sipsak -U -C "*" -s sip:49721123456789 at 127.0.0.1 -H localhost -x 0 &> /dev/null
+fi;
+
+if [ "$ret" -eq 0 ]; then
+	$CTL ul show | grep "AOR:: 49721123456789" > /dev/null
+	ret=$?
+	if [ "$ret" -eq 0 ]; then
+		ret=1
+	else
+		ret=0
+	fi;
+fi;
+
+if [ "$ret" -eq 0 ]; then
+	ret=`echo "select COUNT(*) from location where username='49721123456789';" | $ISQL`
+fi;
+
+echo "delete from location where username like '49721123456789%';" | $ISQL
+
+if [ "$ret" -eq 0 ]; then
+	# register again
+	sipsak -U -C sip:foobar at localhost -s sip:49721123456789 at localhost -H localhost &> /dev/null
+	ret=$?
+fi;
+
+$KILL
+
+# restart to test preload_udomain functionality
+$BIN -w . -f $CFG > /dev/null
+ret=$?
+
+sleep 1
+
+if [ "$ret" -eq 0 ]; then
+	# check if the contact is still registered
+	sipsak -U -C empty -s sip:49721123456789 at 127.0.0.1 -H localhost -q "Contact: <sip:foobar at localhost>" &> /dev/null
+	ret=$?
+fi;
+
+# check if the methods value is correct
+if [ "$ret" -eq 0 ]; then
+	$CTL ul show | grep "Methods:: 4294967295" &> /dev/null
+	ret=$?
+fi;
+
+$KILL
+
+echo "delete from location where username like '49721123456789%';" | $ISQL
+
+mv $CFG.tmp $CFG
+
+exit $ret
diff --git a/test/unit/45.cfg b/test/unit/45.cfg
new file mode 100644
index 0000000..a170672
--- /dev/null
+++ b/test/unit/45.cfg
@@ -0,0 +1,71 @@
+# Kamailio config for lookup / registrar testing
+
+#------------------------Global configuration----------------------------------
+debug=2
+fork=yes
+log_stderror=no
+listen=127.0.0.1
+port=5060
+dns=no
+rev_dns=no
+
+#-----------------------Loading Modules-------------------------------------
+mpath="../../modules/"
+loadmodule "../../modules/db_mysql/db_mysql.so"
+loadmodule "usrloc/usrloc.so"
+loadmodule "registrar/registrar.so"
+loadmodule "sl/sl.so"
+loadmodule "../../modules/tm/tm.so"
+loadmodule "maxfwd/maxfwd.so"
+loadmodule "pv/pv.so"
+loadmodule "cfgutils.so"
+loadmodule "memcached.so"
+#for debugging purposes only
+loadmodule "mi_fifo/mi_fifo.so"
+loadmodule "xlog/xlog.so"
+
+
+#-----------------------Module parameters-------------------------------------
+modparam("mi_fifo", "fifo_name", "/tmp/kamailio_fifo")
+modparam("usrloc", "db_mode", 3)
+modparam("usrloc", "db_url", "mysql://kamailio:kamailiorw@localhost/kamailio")
+modparam("memcached", "memory", 0)
+
+#-----------------------Routing configuration---------------------------------#
+route{
+	if (!mf_process_maxfwd_header("10")) {
+		sl_send_reply("483","Too Many Hops");
+		exit();
+	}
+
+	$mct(test) = "1";
+	$mct(test) = 5;
+	xlog("stored value is $mct(test)");
+	$mct(test) = $null;
+	xlog("stored value is $mct(test) - expected empty");
+
+	$mct(cnt) = 1;
+	$mcinc(cnt) = 1; # increment by 1
+	xlog("counter is now $mct(cnt)");
+	$mcdec(cnt) = 1; # decrement by 1
+	xlog("counter is now $mct(cnt)");
+
+	$mct(test) = 111;
+	xlog("stored value is $mct(test)");
+	$mctex(test) = 1;
+	sleep("2");
+	xlog("stored value is now $mct(test)");
+
+	if (registered("location")) {
+		xlog("contact registered");
+	}
+
+	if(!lookup ("location")){
+		sl_send_reply("404", "Not Found");
+	}
+
+	if (!t_relay()) {
+		sl_reply_error();
+	}
+}
+
diff --git a/test/unit/45.sh b/test/unit/45.sh
new file mode 100755
index 0000000..5f11519
--- /dev/null
+++ b/test/unit/45.sh
@@ -0,0 +1,51 @@
+#!/bin/bash
+# check memcached module with a basic usrloc scenario
+
+# Copyright (C) 2007 1&1 Internet AG
+#
+# This file is part of Kamailio, a free SIP server.
+#
+# Kamailio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version
+#
+# Kamailio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+source include/common
+source include/require
+source include/database
+
+if ! (check_sipp && check_kamailio && check_module "db_mysql" && check_mysql && check_module "memcached"); then
+	exit 0
+fi ;
+
+CFG=45.cfg
+SRV=5060
+UAS=5070
+UAC=5080
+
+
+# add an registrar entry to the db;
+$MYSQL "INSERT INTO location (username,contact,socket,user_agent,cseq,q) VALUES (\"foo\",\"sip:foo at 127.0.0.1:$UAS\",\"udp:127.0.0.1:$UAS\",\"ser_test\",1,-1);"
+
+$BIN -w . -f $CFG &> /dev/null
+
+sipp -sn uas -bg -i 127.0.0.1 -m 10 -f 2 -p $UAS &> /dev/null
+sipp -sn uac -s foo 127.0.0.1:$SRV -i 127.0.0.1 -m 10 -f 2 -p $UAC &> /dev/null
+
+ret=$?
+
+# cleanup
+killall -9 sipp > /dev/null 2>&1
+$KILL > /dev/null 2>&1
+
+$MYSQL "DELETE FROM location WHERE ((contact = \"sip:foo at 127.0.0.1:$UAS\") and (user_agent = \"ser_test\"));"
+exit $ret;
diff --git a/test/unit/46.sh b/test/unit/46.sh
new file mode 100755
index 0000000..2511f41
--- /dev/null
+++ b/test/unit/46.sh
@@ -0,0 +1,94 @@
+#!/bin/bash
+#Check configuration framework implementation in k modules
+
+# Copyright (C) 2007 1&1 Internet AG
+#
+# This file is part of Kamailio, a free SIP server.
+#
+# Kamailio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version
+#
+# Kamailio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+source include/common
+source include/require
+source include/database
+
+if ! (check_sipp && check_kamailio && check_module "db_mysql" && check_mysql ); then
+	exit 0
+fi ;
+
+CFG=11.cfg
+SRV=5060
+UAS=5070
+UAC=5080
+
+function test_module_int()
+{
+	if [ x$# != x3 ] ; then 
+		echo "wrong number of params : usage test_module module cfg_param value"
+		return 1
+	fi
+
+	MODNAME="$1"
+	MODPARAM="$2"
+	MODVAL="$3"
+
+	if [ x$ret = x0 ]  ; then 
+		$SERCMD cfg.set_now_int $MODNAME $MODPARAM $MODVAL &>/dev/null
+		ret=$?
+	fi
+
+	if [ x$ret = x0 ] ; then
+		val=$($SERCMD cfg.get $MODNAME $MODPARAM)
+		ret=$?
+
+		if [ x"$val" = x$MODVAL ] ; then 
+#		    echo "check ok"
+		    ret=0;
+		else
+#		    echo "check failed"
+		    ret=1
+		fi
+	fi
+
+	return $ret
+}
+
+# add an registrar entry to the db
+cp $CFG ${CFG}.bak
+
+echo "loadmodule \"../../modules/db_mysql/db_mysql.so\"" >>$CFG
+echo "loadmodule \"../../modules/ctl/ctl.so\"" >> $CFG
+echo "loadmodule \"../../modules/cfg_rpc/cfg_rpc.so\"" >> $CFG
+$BIN -w . -f $CFG &> /dev/null
+ret=$?
+sleep 1
+
+SERCMD="../../utils/sercmd/sercmd"
+
+if [ ! -x $SERCMD ] ; then
+    ret=1
+    echo "SERCMD executable not found"
+fi
+
+test_module_int registrar default_expires 100
+
+ret=$?
+
+# cleanup
+killall -9 sipp > /dev/null 2>&1
+$KILL > /dev/null 2>&1
+
+mv ${CFG}.bak $CFG
+
+exit $ret;
diff --git a/test/unit/5.cfg b/test/unit/5.cfg
new file mode 100644
index 0000000..9703e7c
--- /dev/null
+++ b/test/unit/5.cfg
@@ -0,0 +1,427 @@
+#
+# $Id$
+#
+# Kamailio basic configuration script
+#     by Anca Vamanu <anca at voice-system.ro>
+#
+# Please refer to the Core CookBook at http://www.kamailio.org/dokuwiki/doku.php
+# for a explanation of possible statements, functions and parameters.
+#
+
+
+####### Global Parameters #########
+
+debug=3
+log_stderror=no
+log_facility=LOG_LOCAL0
+
+fork=yes
+children=4
+
+/* uncomment the following lines to enable debugging */
+#debug=6
+#fork=no
+#log_stderror=yes
+
+/* uncomment the next line to disable TCP (default on) */
+#disable_tcp=yes
+
+/* uncomment the next line to enable the auto temporary blacklisting of 
+   not available destinations (default disabled) */
+#disable_dns_blacklist=no
+
+/* uncomment the next line to enable IPv6 lookup after IPv4 dns 
+   lookup failures (default disabled) */
+#dns_try_ipv6=yes
+
+/* uncomment the next line to disable the auto discovery of local aliases
+   based on revers DNS on IPs (default on) */
+#auto_aliases=no
+
+/* uncomment the following lines to enable TLS support  (default off) */
+#disable_tls = no
+#listen = tls:your_IP:5061
+#tls_verify_server = 1
+#tls_verify_client = 1
+#tls_require_client_certificate = 0
+#tls_method = TLSv1
+#tls_certificate = "/usr/local/etc/kamailio/tls/user/user-cert.pem"
+#tls_private_key = "/usr/local/etc/kamailio/tls/user/user-privkey.pem"
+#tls_ca_list = "/usr/local/etc/kamailio/tls/user/user-calist.pem"
+
+
+port=5060
+
+/* uncomment and configure the following line if you want kamailio to 
+   bind on a specific interface/port/proto (default bind on all available) */
+#listen=udp:192.168.1.2:5060
+
+
+####### Modules Section ########
+
+#set module path
+mpath="../../modules_k"
+
+/* uncomment next line for MySQL DB support */
+#loadmodule "db_mysql.so"
+loadmodule "../../modules/tm/tm.so"
+loadmodule "sl/sl.so"
+loadmodule "rr/rr.so"
+loadmodule "pv/pv.so"
+loadmodule "maxfwd/maxfwd.so"
+loadmodule "usrloc/usrloc.so"
+loadmodule "registrar/registrar.so"
+loadmodule "textops/textops.so"
+loadmodule "mi_fifo/mi_fifo.so"
+loadmodule "uri_db/uri_db.so"
+loadmodule "siputils/siputils.so"
+loadmodule "xlog/xlog.so"
+loadmodule "acc/acc.so"
+
+/* uncomment next lines for MySQL based authentication support 
+   NOTE: a DB (like db_mysql) module must be also loaded */
+#loadmodule "auth.so"
+#loadmodule "auth_db.so"
+/* uncomment next line for aliases support
+   NOTE: a DB (like db_mysql) module must be also loaded */
+#loadmodule "alias_db.so"
+/* uncomment next line for multi-domain support
+   NOTE: a DB (like db_mysql) module must be also loaded
+   NOTE: be sure and enable multi-domain support in all used modules
+         (see "multi-module params" section ) */
+#loadmodule "domain.so"
+/* uncomment the next two lines for presence server support
+   NOTE: a DB (like db_mysql) module must be also loaded */
+#loadmodule "presence.so"
+#loadmodule "presence_xml.so"
+
+
+# ----------------- setting module-specific parameters ---------------
+
+
+# ----- mi_fifo params -----
+modparam("mi_fifo", "fifo_name", "/tmp/kamailio_fifo")
+
+
+# ----- rr params -----
+# add value to ;lr param to cope with most of the UAs
+modparam("rr", "enable_full_lr", 1)
+# do not append from tag to the RR (no need for this script)
+modparam("rr", "append_fromtag", 0)
+
+
+# ----- rr params -----
+modparam("registrar", "method_filtering", 1)
+/* uncomment the next line to disable parallel forking via location */
+# modparam("registrar", "append_branches", 0)
+/* uncomment the next line not to allow more than 10 contacts per AOR */
+#modparam("registrar", "max_contacts", 10)
+
+
+# ----- uri_db params -----
+/* by default we disable the DB support in the module as we do not need it
+   in this configuration */
+modparam("uri_db", "use_uri_table", 0)
+modparam("uri_db", "db_url", "")
+
+
+# ----- acc params -----
+/* what sepcial events should be accounted ? */
+modparam("acc", "early_media", 1)
+modparam("acc", "report_ack", 1)
+modparam("acc", "report_cancels", 1)
+/* by default ww do not adjust the direct of the sequential requests.
+   if you enable this parameter, be sure the enable "append_fromtag"
+   in "rr" module */
+modparam("acc", "detect_direction", 0)
+/* account triggers (flags) */
+modparam("acc", "failed_transaction_flag", 3)
+modparam("acc", "log_flag", 1)
+modparam("acc", "log_missed_flag", 2)
+/* uncomment the following lines to enable DB accounting also */
+modparam("acc", "db_flag", 1)
+modparam("acc", "db_missed_flag", 2)
+
+
+# ----- usrloc params -----
+modparam("usrloc", "db_mode",   0)
+/* uncomment the following lines if you want to enable DB persistency
+   for location entries */
+#modparam("usrloc", "db_mode",   2)
+#modparam("usrloc", "db_url",
+#	"mysql://kamailio:kamailiorw@192.168.1.3/kamailio_1_3")
+
+
+# ----- auth_db params -----
+/* uncomment the following lines if you want to enable the DB based
+   authentication */
+#modparam("auth_db", "calculate_ha1", yes)
+#modparam("auth_db", "password_column", "password")
+#modparam("auth_db", "db_url",
+#	"mysql://kamailio:kamailiorw@192.168.1.3/kamailio_1_3")
+#modparam("auth_db", "load_credentials", "")
+
+
+# ----- alias_db params -----
+/* uncomment the following lines if you want to enable the DB based
+   aliases */
+#modparam("alias_db", "db_url",
+#	"mysql://kamailio:kamailiorw@192.168.1.3/kamailio_1_3")
+
+
+# ----- domain params -----
+/* uncomment the following lines to enable multi-domain detection
+   support */
+#modparam("domain", "db_url",
+#	"mysql://kamailio:kamailiorw@192.168.1.3/kamailio_1_3")
+#modparam("domain", "db_mode", 1)   # Use caching
+
+
+# ----- multi-module params -----
+/* uncomment the following line if you want to enable multi-domain support
+   in the modules (dafault off) */
+#modparam("alias_db|auth_db|usrloc|uri_db", "use_domain", 1)
+
+
+# ----- presence params -----
+/* uncomment the following lines if you want to enable presence */
+#modparam("presence|presence_xml", "db_url",
+#	"mysql://kamailio:kamailiorw@192.168.1.3/kamailio_1_3")
+#modparam("presence_xml", "force_active", 1)
+#modparam("presence", "server_address", "sip:192.168.1.2:5060")
+
+
+####### Routing Logic ########
+
+
+# main request routing logic
+
+route{
+
+	if (!mf_process_maxfwd_header("10")) {
+		sl_send_reply("483","Too Many Hops");
+		exit;
+	}
+
+	if (has_totag()) {
+		# sequential request withing a dialog should
+		# take the path determined by record-routing
+		if (loose_route()) {
+			if (is_method("BYE")) {
+				setflag(1); # do accouting ...
+				setflag(3); # ... even if the transaction fails
+			}
+			route(1);
+		} else {
+			/* uncomment the following lines if you want to enable presence */
+			##if (is_method("SUBSCRIBE") && $rd == "your.server.ip.address") {
+			##	# in-dialog subscribe requests
+			##	route(2);
+			##	exit;
+			##}
+			if ( is_method("ACK") ) {
+				if ( t_check_trans() ) {
+					# non loose-route, but stateful ACK; must be an ACK after a 487 or e.g. 404 from upstream server
+					t_relay();
+					exit;
+				} else {
+					# ACK without matching transaction ... ignore and discard.\n");
+					exit;
+				}
+			}
+			sl_send_reply("404","Not here");
+		}
+		exit;
+	}
+
+	#initial requests
+
+	# CANCEL processing
+	if (is_method("CANCEL"))
+	{
+		if (t_check_trans())
+			t_relay();
+		exit;
+	}
+
+	t_check_trans();
+
+	# authenticate if from local subscriber (uncomment to enable auth)
+	##if (!(method=="REGISTER") && from_uri==myself)
+	##{
+	##	if (!proxy_authorize("", "subscriber")) {
+	##		proxy_challenge("", "0");
+	##		exit;
+	##	}
+	##	if (!check_from()) {
+	##		sl_send_reply("403","Forbidden auth ID");
+	##		exit;
+	##	}
+	##
+	##	consume_credentials();
+	##	# caller authenticated
+	##}
+
+	# record routing
+	if (!is_method("REGISTER|MESSAGE"))
+		record_route();
+
+	# account only INVITEs
+	if (is_method("INVITE")) {
+		setflag(1); # do accouting
+	}
+	if (!uri==myself)
+	/* replace with following line if multi-domain support is used */
+	##if (!is_uri_host_local())
+	{
+		append_hf("P-hint: outbound\r\n"); 
+		# if you have some interdomain connections via TLS
+		##if($rd=="tls_domain1.net") {
+		##	t_relay("tls:domain1.net");
+		##	exit;
+		##} else if($rd=="tls_domain2.net") {
+		##	t_relay("tls:domain2.net");
+		##	exit;
+		##}
+		route(1);
+	}
+
+	# requests for my domain
+
+	/* uncomment this if you want to enable presence server 
+	   and comment the next 'if' block
+	   NOTE: uncomment also the definition of route[2] from  below */
+	##if( is_method("PUBLISH|SUBSCRIBE"))
+	##		route(2);
+
+	if (is_method("PUBLISH"))
+	{
+		sl_send_reply("503", "Service Unavailable");
+		exit;
+	}
+	
+
+	if (is_method("REGISTER"))
+	{
+		# authenticate the REGISTER requests (uncomment to enable auth)
+		##if (!www_authorize("", "subscriber"))
+		##{
+		##	www_challenge("", "0");
+		##	exit;
+		##}
+		##
+		##if (!check_to()) 
+		##{
+		##	sl_send_reply("403","Forbidden auth ID");
+		##	exit;
+		##}
+
+		if (!save("location"))
+			sl_reply_error();
+
+		exit;
+	}
+
+	if ($rU==NULL) {
+		# request with no Username in RURI
+		sl_send_reply("484","Address Incomplete");
+		exit;
+	}
+
+	# apply DB based aliases (uncomment to enable)
+	##alias_db_lookup("dbaliases");
+
+	if (!lookup("location")) {
+		switch ($retcode) {
+			case -1:
+			case -3:
+				t_newtran();
+				t_reply("404", "Not Found");
+				exit;
+			case -2:
+				sl_send_reply("405", "Method Not Allowed");
+				exit;
+		}
+	}
+
+	# when routing via usrloc, log the missed calls also
+	setflag(2);
+
+	route(1);
+}
+
+
+route[1] {
+	# for INVITEs enable some additional helper routes
+	if (is_method("INVITE")) {
+		t_on_branch("2");
+		t_on_reply("2");
+		t_on_failure("1");
+	}
+
+	if (!t_relay()) {
+		sl_reply_error();
+	};
+	exit;
+}
+
+
+# Presence route
+/* uncomment the whole following route for enabling presence
+   NOTE: do not forget to enable the call of this route from the main
+     route */
+##route[2]
+##{
+##	if (!t_newtran())
+##	{
+##		sl_reply_error();
+##		exit;
+##	};
+##
+##	if(is_method("PUBLISH"))
+##	{
+##		handle_publish();
+##		t_release();
+##	}
+##	else
+##	if( is_method("SUBSCRIBE"))
+##	{
+##		handle_subscribe();
+##		t_release();
+##	}
+##
+##	exit;
+##}
+
+
+branch_route[2] {
+	xlog("new branch at $ru\n");
+}
+
+
+onreply_route[2] {
+	xlog("incoming reply\n");
+}
+
+
+failure_route[1] {
+	if (t_was_cancelled()) {
+		exit;
+	}
+
+	# uncomment the following lines if you want to block client 
+	# redirect based on 3xx replies.
+	##if (t_check_status("3[0-9][0-9]")) {
+	##t_reply("404","Not found");
+	##	exit;
+	##}
+
+	# uncomment the following lines if you want to redirect the failed 
+	# calls to a different new destination
+	##if (t_check_status("486|408")) {
+	##	sethostport("192.168.2.100:5060");
+	##	append_branch();
+	##	# do not set the missed call flag again
+	##	t_relay();
+	##}
+}
diff --git a/test/unit/5.sh b/test/unit/5.sh
new file mode 100755
index 0000000..0554ae2
--- /dev/null
+++ b/test/unit/5.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+# loads the kamailio default config
+
+# Copyright (C) 2007 1&1 Internet AG
+#
+# This file is part of Kamailio, a free SIP server.
+#
+# Kamailio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version
+#
+# Kamailio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+# Needs a default kamailio database setup for mysql
+
+source include/common
+source include/require
+
+CFG=$SRC_DIR/etc/kamailio.cfg
+
+if ! (check_kamailio); then
+	exit 0
+fi ;
+        
+
+# start
+$BIN -w . -L $SRC_DIR/modules/ -f $CFG -A WITH_SRCPATH -a no > /dev/null 2>&1
+ret=$?
+
+sleep 1
+$KILL
+
+exit $ret
diff --git a/test/unit/50.cfg b/test/unit/50.cfg
new file mode 100644
index 0000000..5aac5f5
--- /dev/null
+++ b/test/unit/50.cfg
@@ -0,0 +1,85 @@
+# ----------- global configuration parameters ------------------------
+debug=3
+fork=yes
+log_stderror=no
+children=1
+disable_tcp=yes
+
+# ------------------ module loading ----------------------------------
+loadpath "../../modules/:../../modules_k/"
+loadmodule "tm"
+loadmodule "sl"
+loadmodule "rr"
+loadmodule "maxfwd"
+loadmodule "textops"
+loadmodule "xlog"
+loadmodule "pv"
+loadmodule "../../modules/db_mysql/db_mysql.so"
+
+loadmodule "mi_fifo"
+modparam("mi_fifo", "fifo_name", "/tmp/kamailio_fifo")
+
+loadmodule "p_usrloc"
+modparam("p_usrloc", "db_mode", 3)
+modparam("p_usrloc", "read_db_url", "mysql://ser:ser@localhost/ser")
+modparam("p_usrloc", "write_db_url", "mysql://ser:ser@localhost/ser")
+
+modparam("p_usrloc", "write_on_db", 1)
+#modparam("p_usrloc", "write_on_master_db", 1)
+modparam("p_usrloc", "alg_location", 1)
+
+modparam("p_usrloc", "reg_db_table", "locdb")
+
+loadmodule "registrar"
+modparam("registrar", "min_expires", 60)
+
+
+#-------------------------  request routing logic -------------------
+route{
+
+	if (!mf_process_maxfwd_header("10")) {
+		sl_send_reply("483","Too Many Hops");
+		exit;
+	}
+
+	if (msg:len >=  2048 ) {
+		sl_send_reply("513", "Message Too Large");
+		exit;
+	}
+
+	if (!method=="REGISTER")
+		record_route();
+
+	if (loose_route()) {
+		# mark routing logic in request
+		append_hf("P-hint: rr-enforced\r\n");
+		route(1);
+	}
+
+	if (!uri==myself) {
+		append_hf("P-hint: outbound\r\n");
+		route(1);
+	}
+
+	if (uri==myself) {
+		if (method=="REGISTER") {
+			save("location");
+			exit;
+		}
+		if (!lookup("location")) {
+			sl_send_reply("404", "Not Found");
+			exit;
+		}
+		append_hf("P-hint: p_usrloc applied\r\n");
+	}
+
+	route(1);
+}
+
+route[1] {
+	if (!t_relay()) {
+		sl_reply_error();
+	}
+	exit;
+}
+
diff --git a/test/unit/50.sh b/test/unit/50.sh
new file mode 100755
index 0000000..5c0979a
--- /dev/null
+++ b/test/unit/50.sh
@@ -0,0 +1,162 @@
+#!/bin/bash
+# database access and persistent storage for registrar on mysql
+
+# Copyright (C) 2010 marius.zbihlei at 1and1.ro
+#
+# This file is part of Kamailio, a free SIP server.
+#
+# Kamailio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version
+#
+# Kamailio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+source include/common
+source include/require
+source include/database
+
+CFG=50.cfg
+
+if ! (check_sipsak && check_kamailio && check_module "db_mysql" && check_mysql); then
+	exit 0
+fi ;
+
+MYSQL_LOC_A="mysql loc_a --show-warnings --batch --user=ser --password=ser -e"
+MYSQL_LOC_B="mysql loc_b --show-warnings --batch --user=ser --password=ser  -e"
+cp $CFG $CFG.bak
+
+$BIN -w . -f $CFG #> /dev/null
+ret=$?
+
+sleep 1
+
+# register two contacts
+echo "adding new contacts"
+sipsak -U -C sip:foobar at localhost -s sip:49721123456789 at localhost -H localhost -x 30 &> /dev/null
+sipsak -U -C sip:foobar1 at localhost -s sip:49721123456789 at localhost -H localhost -x 30 &> /dev/null
+sipsak -U -C sip:foobar2 at localhost -s sip:49721123456790 at localhost -H localhost -x 30 &> /dev/null
+ret=$?
+
+if [ ! "$ret" -eq 0 ]; then
+    echo "registration failed"
+fi
+
+if [ "$ret" -eq 0 ]; then
+	TMP=`$MYSQL_LOC_A "select COUNT(*) from location where username='49721123456789';" | tail -n 1`
+	if [ "$TMP" -eq 0 ] ; then
+		TMP=`$MYSQL_LOC_B "select COUNT(*) from location where username='49721123456789';" | tail -n 1`
+		if [ "$TMP" -eq 0 ] ; then 
+			echo "User 49721123456789 was NOT saved to either loc_a or loc_b"
+			ret=1
+		fi
+	fi;
+fi;
+
+if [ "$ret" -eq 0 ]; then
+	TMP=`$MYSQL_LOC_A "select COUNT(*) from location where username='49721123456790';" | tail -n 1`
+	if [ "$TMP" -eq 0 ] ; then
+		TMP=`$MYSQL_LOC_B "select COUNT(*) from location where username='49721123456790';" | tail -n 1`
+		if [ "$TMP" -eq 0 ] ; then 
+			echo "User 49721123456790 was NOT saved to either loc_a or loc_b"
+			ret=1
+		fi
+	fi;
+fi;
+
+if [ "$ret" -eq 0 ]; then
+	echo "check if the contact is registered"
+	sipsak -U -C empty -s sip:49721123456789 at 127.0.0.1 -H localhost -q "Contact: <sip:foobar at localhost>" #&> /dev/null
+	ret=$?
+	echo "sipsak exited with status $ret"
+fi;
+
+if [ "$ret" -eq 0 ]; then
+	echo "update the registration"
+	sipsak -U -C sip:foobar at localhost -s sip:49721123456789 at localhost -H localhost &> /dev/null
+	ret=$?
+fi;
+
+if [ "$ret" -eq 0 ]; then
+	echo "check if we get a hint when we try to unregister a non-existent conctact"
+	sipsak -U -C "sip:foobar2 at localhost" -s sip:49721123456789 at 127.0.0.1 -H localhost -x 0 -q "Contact: <sip:foobar at localhost>" &> /dev/null
+	ret=$?
+fi;
+
+if [ "$ret" -eq 0 ]; then
+	echo " unregister the contact"
+	sipsak -U -C "sip:foobar at localhost" -s sip:49721123456789 at 127.0.0.1 -H localhost -x 0 &> /dev/null
+	ret=$?
+fi;
+
+if [ "$ret" -eq 0 ]; then
+	echo "unregister the user again should not fail"
+	sipsak -U -C "sip:foobar at localhost" -s sip:49721123456789 at 127.0.0.1 -H localhost -x 0 #&> /dev/null
+	ret=$?
+fi;
+
+if [ "$ret" -eq 0 ]; then
+	echo "check if the other contact is still registered"
+	sipsak -U -C empty -s sip:49721123456789 at 127.0.0.1 -H localhost -q "Contact: <sip:foobar1 at localhost>" &> /dev/null
+	ret=$?
+fi;
+
+if [ "$ret" -eq 0 ]; then
+	echo " register the other again"
+	sipsak -U -C sip:foobar at localhost -s sip:49721123456789 at localhost -H localhost &> /dev/null
+	ret=$?
+fi;
+
+if [ "$ret" -eq 0 ]; then
+	echo " unregister all contacts"
+	sipsak -U -C "*" -s sip:49721123456789 at 127.0.0.1 -H localhost -x 0 &> /dev/null
+	ret=$?
+fi;
+
+if [ "$ret" -eq 0 ]; then
+	executed=1
+	ret=`$MYSQL_LOC_A "select COUNT(*) from location where username='49721123456789';" | tail -n 1`
+	if [ "$TMP" -eq 0 ] ; then
+		ret=`$MYSQL_LOC_B "select COUNT(*) from location where username='49721123456789';" | tail -n 1`
+	fi;
+fi;
+
+if [ "x$executed" == "x1" ]; then
+    echo "After un-registration user has $ret contacts "
+fi
+
+if [ "$ret" -eq 0 ]; then
+	# test min_expires functionality
+	sipsak -U -C sip:foobar at localhost -s sip:49721123456789 at localhost -H localhost -x 2 &> /dev/null
+	ret=$?
+fi;
+
+if [ "$ret" -eq 0 ]; then
+	sleep 3
+	# check if the contact is still registered
+	sipsak -U -C empty -s sip:49721123456789 at 127.0.0.1 -H localhost -q "Contact: <sip:foobar at localhost>" &> /dev/null
+	ret=$?
+fi;
+
+if [ "$ret" -eq 0 ]; then
+	# register a few more contacts
+	sipsak -U -e 9 -s sip:49721123456789 at localhost -H localhost &> /dev/null
+fi;
+
+
+$MYSQL_LOC_A "delete from location where username like '497211234567%';"
+$MYSQL_LOC_B "delete from location where username like '497211234567%';"
+
+
+$KILL
+
+mv $CFG.bak $CFG
+
+exit $ret
\ No newline at end of file
diff --git a/test/unit/6.sh b/test/unit/6.sh
new file mode 100755
index 0000000..a89284d
--- /dev/null
+++ b/test/unit/6.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+# checks a specific configuration with 'kamailio -c'
+
+# Copyright (C) 2007 1&1 Internet AG
+#
+# This file is part of Kamailio, a free SIP server.
+#
+# Kamailio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version
+#
+# Kamailio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+source include/common
+source include/require
+
+CFG=2.cfg
+
+if ! (check_kamailio); then
+	exit 0
+fi ;
+
+# start
+cat $CFG | cat - route-empty.cfg | $BIN -w . -a no -c -f - > /dev/null 2>&1
+ret=$?
+
+exit $ret
diff --git a/test/unit/7.cfg b/test/unit/7.cfg
new file mode 100644
index 0000000..ab8ddfe
--- /dev/null
+++ b/test/unit/7.cfg
@@ -0,0 +1,1105 @@
+########################################################################
+# This configuration is autogenerated by sip:wizard
+# (http://www.sipwise.com/wizard) on Fri Nov 09 17:06:52 +0100 2007
+# for Kamailio 1.2
+#
+# Copyright (C) 2007 Sipwise (support at sipwise.com)
+########################################################################
+
+########################################################################
+# By obtaining, using, and/or copying this configuration and/or its
+# associated documentation, you agree that you have read, understood,
+# and will comply with the Terms of Usage provided at
+# http://www.sipwise.com/news/?page_id=6 as well as the following
+# additions:
+#
+# Permission to use, copy, modify, and distribute this configuration and
+# its associated documentation for any purpose and without fee is hereby
+# granted, provided that the above copyright notice appears in all
+# copies, and that both that copyright notice and this permission notice
+# appear in supporting documentation, and that the name of Sipwise or
+# the author will not be used in advertising or publicity pertaining to
+# distribution of the configuration without specific, written prior
+# permission.
+########################################################################
+
+########################################################################
+# Before using this configuration, read the following prerequisites in
+# order to gain the designated functionallity:
+#
+# base:
+#    You have to insert all locally served domains (i.e. 
+#    "kamailioctl domain add your.domain.com").
+#    
+# usr-preferences:
+#    This feature relies on UUID-based provisioning. Thus, you have 
+#    to add the uuid-column to the subscriber table ("alter table 
+#    subscriber add column uuid varchar(64);") and populate it with a 
+#    UUID (unique user identifier) per user, for example an 
+#    auto-incremented id.
+#    
+# offnet-incoming-sip:
+#    You have to populate the "trusted"-table with rules for 
+#    allowed peering hosts (i.e. src_ip="1.2.3.4", proto="udp", 
+#    from_pattern="^sip:.*@domain.of.peering.host$", tag="1234"). If the 
+#    feature "usr-preferences" is selected, the tag-value is used as 
+#    caller-uuid for such calls.
+#    
+# offnet-pstn:
+#    You have to add a routing entry for lcr (i.e. "kamailioctl  lcr 
+#    addroute '' '' 1 1"). Additionally, you have to add your gateways 
+#    (i.e. "kamailioctl lcr addgw my-test-gw 1.2.3.4 5060 sip udp 1").
+#    
+# ring-timeout:
+#    You have to provision the ring-timeout (AVP ringtimeout as 
+#    type 1) for each user in the usr_preferences table (i.e. 
+#    uuid='1234', username='', domain='', attribute='ringtimeout', 
+#    type=1, value='60'). If no timeout is provisioned, the default 
+#    timeout will be used.
+#    
+# cfu:
+#    You have to provision the call-forward-unconditional as full 
+#    SIP URI (AVP cfu as type 0) for each user in the usr_preferences 
+#    table (i.e. uuid='1234', username='', domain='', attribute='cfu', 
+#    type=0, value='sip:foo at otherdomain.com').  Forwards to another user 
+#    in the same domain or to other domains are possible.
+#    
+# cfc:
+#    You have to provision the call-forward-conditional as full SIP 
+#    URI (AVP cfc as type 0) for each user in the usr_preferences table 
+#    (i.e. uuid='1234', username='', domain='', attribute='cfc', type=0, 
+#    value='sip:foo at otherdomain.com').  Forwards to another user in the 
+#    same domain or to other domains are possible.
+#    
+# user-aliases:
+#    You have to add aliases for your users (i.e. "kamailioctl alias 
+#    add 01234567 sip:bob at yourdomain.com" for usrloc-based aliases or 
+#    make entries into "dbaliases" table for db-based aliases)
+#    
+# cli:
+#    You have to provision the CLI as full SIP URI (AVP cli as type 
+#    0) for each user in the usr_preferences table (i.e. uuid='1234', 
+#    username='', domain='', attribute='cli', type=0, 
+#    value='sip:01234567 at yourdomain.com').
+#    
+# clir:
+#    You have to provision '1' to enable CLIR and '0' to disable it 
+#    (AVP clir as type 1) for each user in the usr_preferences table 
+#    (i.e. uuid='1234', username='', domain='', attribute='clir', 
+#    type=1, value='1').
+#    
+# acc-db:
+#    You have to add the columns "src_leg" and "dst_leg" to your 
+#    acc-table ("alter table acc add column src_leg varchar(128); alter 
+#    table acc add column dst_leg varchar(128);").
+#    
+########################################################################
+
+########################################################################
+# Configuration 'sip:wizard - Fri Nov 09 17:06:52 +0100 2007'
+########################################################################
+
+listen = udp:127.0.0.1:5060
+mpath = "../../modules"
+children = 8
+debug = 2
+fork = yes
+disable_tcp = no
+log_facility = LOG_DAEMON
+log_stderror = no
+tcp_children = 4
+mhomed = no
+server_signature = yes
+reply_to_via = no
+sip_warning = no
+check_via = no
+dns = no
+rev_dns = no
+disable_core_dump = no
+dns_try_ipv6 = yes
+dns_use_search_list = yes
+
+loadmodule "pv/pv.so"
+loadmodule "corex/corex.so"
+loadmodule "kex/kex.so"
+
+loadmodule "usrloc/usrloc.so"
+modparam("usrloc", "user_column", "username")
+modparam("usrloc", "domain_column", "domain")
+modparam("usrloc", "contact_column", "contact")
+modparam("usrloc", "expires_column", "expires")
+modparam("usrloc", "q_column", "q")
+modparam("usrloc", "callid_column", "callid")
+modparam("usrloc", "cseq_column", "cseq")
+modparam("usrloc", "methods_column", "methods")
+modparam("usrloc", "flags_column", "flags")
+modparam("usrloc", "user_agent_column", "user_agent")
+modparam("usrloc", "received_column", "received")
+modparam("usrloc", "socket_column", "socket")
+modparam("usrloc", "use_domain", 0)
+modparam("usrloc", "desc_time_order", 0)
+modparam("usrloc", "timer_interval", 60)
+modparam("usrloc", "db_url", "mysql://kamailio:kamailiorw@localhost/kamailio")
+modparam("usrloc", "db_mode", 1)
+modparam("usrloc", "matching_mode", 0)
+modparam("usrloc", "cseq_delay", 20)
+modparam("usrloc", "nat_bflag", 6)
+
+loadmodule "maxfwd/maxfwd.so"
+modparam("maxfwd", "max_limit", 256)
+
+loadmodule "rr/rr.so"
+modparam("rr", "enable_full_lr", 0)
+modparam("rr", "append_fromtag", 1)
+modparam("rr", "enable_double_rr", 1)
+modparam("rr", "add_username", 0)
+
+loadmodule "tm/tm.so"
+modparam("tm", "fr_timer", 30)
+modparam("tm", "fr_inv_timer", 120)
+modparam("tm", "wt_timer", 5)
+modparam("tm", "delete_timer", 2)
+modparam("tm", "ruri_matching", 1)
+modparam("tm", "via1_matching", 1)
+modparam("tm", "unix_tx_timeout", 2)
+modparam("tm", "restart_fr_on_each_reply", 1)
+modparam("tm", "pass_provisional_replies", 0)
+modparam("tm", "fr_inv_timer_avp", "$avp(s:callee_fr_inv_timer)")
+
+loadmodule "xlog/xlog.so"
+modparam("xlog", "buf_size", 4096)
+modparam("xlog", "force_color", 0)
+
+loadmodule "mi_fifo/mi_fifo.so"
+modparam("mi_fifo", "fifo_name", "/tmp/kamailio_fifo")
+modparam("mi_fifo", "reply_dir", "/tmp/")
+modparam("mi_fifo", "reply_indent", "\t")
+
+loadmodule "domain/domain.so"
+modparam("domain", "db_url", "mysql://kamailio:kamailiorw@localhost/kamailio")
+modparam("domain", "domain_table", "domain")
+modparam("domain", "domain_col", "domain")
+
+loadmodule "nathelper/nathelper.so"
+modparam("nathelper", "natping_interval", 0)
+modparam("nathelper", "ping_nated_only", 1)
+modparam("nathelper", "sipping_method", "OPTIONS")
+modparam("nathelper", "received_avp", "$avp(i:801)")
+
+loadmodule "rtpproxy/rtpproxy.so"
+modparam("rtpproxy", "rtpproxy_sock", "unix:/var/run/rtpproxy.sock")
+modparam("rtpproxy", "rtpproxy_disable_tout", 60)
+modparam("rtpproxy", "rtpproxy_tout", 1)
+modparam("rtpproxy", "rtpproxy_retr", 5)
+
+loadmodule "textops/textops.so"
+
+loadmodule "siputils/siputils.so"
+
+loadmodule "registrar/registrar.so"
+modparam("registrar", "default_expires", 3600)
+modparam("registrar", "min_expires", 60)
+modparam("registrar", "max_expires", 0)
+modparam("registrar", "default_q", 0)
+modparam("registrar", "append_branches", 1)
+modparam("registrar", "case_sensitive", 0)
+modparam("registrar", "received_param", "received")
+modparam("registrar", "max_contacts", 0)
+modparam("registrar", "retry_after", 0)
+modparam("registrar", "method_filtering", 0)
+modparam("registrar", "path_mode", 2)
+modparam("registrar", "path_use_received", 0)
+modparam("registrar", "received_avp", "$avp(i:801)")
+
+loadmodule "sl/sl.so"
+modparam("sl", "bind_tm", 1)
+
+loadmodule "db_mysql/db_mysql.so"
+modparam("db_mysql", "ping_interval", 300)
+modparam("db_mysql", "auto_reconnect", 1)
+
+loadmodule "auth/auth.so"
+modparam("auth", "nonce_expire", 300)
+
+loadmodule "auth_db/auth_db.so"
+modparam("auth_db", "db_url", "mysql://kamailio:kamailiorw@localhost/kamailio")
+modparam("auth_db", "user_column", "username")
+modparam("auth_db", "domain_column", "domain")
+modparam("auth_db", "password_column", "password")
+modparam("auth_db", "password_column_2", "ha1b")
+modparam("auth_db", "calculate_ha1", 1)
+modparam("auth_db", "use_domain", 0)
+modparam("auth_db", "load_credentials", "$avp(s:caller_uuid)=uuid")
+
+loadmodule "uri_db/uri_db.so"
+modparam("uri_db", "db_url", "mysql://kamailio:kamailiorw@localhost/kamailio")
+modparam("uri_db", "db_table", "subscriber")
+modparam("uri_db", "use_uri_table", 0)
+modparam("uri_db", "use_domain", 0)
+
+loadmodule "avpops/avpops.so"
+modparam("avpops", "db_url", "mysql://kamailio:kamailiorw@localhost/kamailio")
+modparam("avpops", "avp_table", "usr_preferences")
+modparam("avpops", "use_domain", 0)
+modparam("avpops", "uuid_column", "uuid")
+modparam("avpops", "username_column", "username")
+modparam("avpops", "domain_column", "domain")
+modparam("avpops", "attribute_column", "attribute")
+modparam("avpops", "value_column", "value")
+modparam("avpops", "type_column", "type")
+
+loadmodule "enum/enum.so"
+modparam("enum", "domain_suffix", "e164.org.")
+
+loadmodule "permissions/permissions.so"
+modparam("permissions", "default_allow_file", "permissions.allow")
+modparam("permissions", "default_deny_file", "permissions.deny")
+modparam("permissions", "check_all_branches", 1)
+modparam("permissions", "allow_suffix", ".allow")
+modparam("permissions", "deny_suffix", ".deny")
+modparam("permissions", "db_url", "mysql://kamailio:kamailiorw@localhost/kamailio")
+modparam("permissions", "db_mode", 1)
+modparam("permissions", "trusted_table", "trusted")
+modparam("permissions", "source_col", "src_ip")
+modparam("permissions", "proto_col", "proto")
+modparam("permissions", "from_col", "from_pattern")
+modparam("permissions", "tag_col", "tag")
+modparam("permissions", "peer_tag_avp", "$avp(s:peer_uuid)")
+
+loadmodule "lcr/lcr.so"
+modparam("lcr", "db_url", "mysql://kamailio:kamailiorw@localhost/kamailio")
+modparam("lcr", "gw_uri_avp", "$avp(709)")
+modparam("lcr", "ruri_user_avp", "$avp(500)")
+modparam("lcr", "tag_avp", "$avp(lcr_tag)")
+
+loadmodule "uac_redirect/uac_redirect.so"
+modparam("uac_redirect", "default_filter", "accept")
+modparam("uac_redirect", "acc_function", "acc_log_request")
+modparam("uac_redirect", "acc_db_table", "acc")
+
+loadmodule "alias_db/alias_db.so"
+modparam("alias_db", "db_url", "mysql://kamailio:kamailiorw@localhost/kamailio")
+modparam("alias_db", "user_column", "username")
+modparam("alias_db", "domain_column", "domain")
+modparam("alias_db", "alias_user_column", "alias_username")
+modparam("alias_db", "alias_domain_column", "alias_domain")
+modparam("alias_db", "use_domain", 0)
+
+loadmodule "uac/uac.so"
+modparam("uac", "rr_from_store_param", "vsf")
+modparam("uac", "rr_to_store_param", "vsf")
+modparam("uac", "restore_mode", "auto")
+modparam("uac", "restore_passwd", "s1p:Wiz4rd!")
+
+loadmodule "acc/acc.so"
+modparam("acc", "early_media", 0)
+modparam("acc", "failed_transaction_flag", 24)
+modparam("acc", "report_ack", 0)
+modparam("acc", "report_cancels", 0)
+modparam("acc", "log_flag", 0)
+modparam("acc", "log_missed_flag", 0)
+modparam("acc", "log_level", 2)
+modparam("acc", "db_flag", 25)
+modparam("acc", "db_missed_flag", 0)
+modparam("acc", "db_table_acc", "acc")
+modparam("acc", "db_table_missed_calls", "missed_calls")
+modparam("acc", "db_url", "mysql://kamailio:kamailiorw@localhost/kamailio")
+modparam("acc", "acc_method_column", "method")
+modparam("acc", "acc_callid_column", "callid")
+modparam("acc", "acc_time_column", "time")
+modparam("acc", "acc_from_tag_column", "from_tag")
+modparam("acc", "detect_direction", 1)
+modparam("acc", "acc_sip_code_column", "sip_code")
+modparam("acc", "acc_sip_reason_column", "sip_reason")
+modparam("acc", "multi_leg_info", "src_leg=$avp(i:901);dst_leg=$avp(i:902)")
+
+########################################################################
+# Request route 'main'
+########################################################################
+request_route {
+	xlog("L_INFO", "New request - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n");
+	force_rport();
+	if (!mf_process_maxfwd_header("10"))
+	{
+		
+		xlog("L_INFO", "Too many hops - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n");
+		sl_send_reply("483", "Too Many Hops");
+		exit;
+	}
+	if(!is_method("REGISTER"))
+	{
+		if(nat_uac_test("19"))
+		{
+			record_route(";nat=yes");
+		}
+		else
+		{
+			record_route();
+		}
+	}
+	if(is_method("CANCEL") || is_method("BYE"))
+	{
+		rtpproxy_destroy();
+	}
+	if(loose_route())
+	{
+		if(!has_totag())
+		{
+			
+			xlog("L_INFO", "Initial loose-routing rejected - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n");
+			sl_send_reply("403", "Initial Loose-Routing Rejected");
+			exit;
+		}
+		if(nat_uac_test("19") || search("^Route:.*;nat=yes"))
+		{
+			fix_nated_contact();
+			setbflag(6);
+		}
+		if(is_method("BYE"))
+		{
+			setflag(24); # account failed transactions
+			setflag(25); # account successful transactions
+		}
+		# mark as loose-routed for acc
+		setflag(26);
+		
+		route(12);
+	}
+	if(is_method("REGISTER"))
+	{
+		route(11);
+	}
+	setflag(24); # account failed transactions
+	setflag(25); # account successful transactions
+	if(is_method("INVITE"))
+	{
+		route(13);
+	}
+	if(is_method("CANCEL") || is_method("ACK"))
+	{
+		route(19);
+	}
+	
+	route(20);
+}
+
+########################################################################
+# Request route 'clear-usr-preferences-caller'
+########################################################################
+route[1]
+{
+	xlog("L_INFO", "Clear caller preferences - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n");
+	avp_delete("$avp(s:caller_cli)/g");
+	avp_delete("$avp(s:clir)/g");
+	
+}
+
+########################################################################
+# Request route 'clear-usr-preferences-callee'
+########################################################################
+route[2]
+{
+	xlog("L_INFO", "Clear callee preferences - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n");
+	avp_delete("$avp(s:callee_fr_inv_timer)/g");
+	avp_delete("$avp(s:cfu)/g");
+	avp_delete("$avp(s:cfc)/g");
+	
+}
+
+########################################################################
+# Request route 'usr-preferences-caller'
+########################################################################
+route[3]
+{
+	route(1);
+	xlog("L_INFO", "Load caller preferences for uuid '$avp(s:caller_uuid)' - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n");
+	# load caller avps
+	avp_db_load("$avp(s:caller_uuid)", "*");
+	avp_copy("$avp(s:cli)", "$avp(s:caller_cli)/d");
+	if(is_avp_set("$avp(s:clir)/n") && avp_check("$avp(s:clir)", "eq/i:1"))
+	{
+		# mark for anonymization
+		setflag(28);
+	}
+	
+}
+
+########################################################################
+# Request route 'usr-preferences-callee'
+########################################################################
+route[4]
+{
+	xlog("L_INFO", "Load callee preferences for uuid '$avp(s:callee_uuid)' - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n");
+	# load callee avps
+	avp_db_load("$avp(s:callee_uuid)", "*");
+	if(is_avp_set("$avp(s:cfu)/s"))
+	{
+		
+		xlog("L_INFO", "Call-forward-unconditional to '$avp(s:cfu)' found - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n");
+		route(8);
+		avp_delete("$avp(s:caller_uuid)/g");
+		avp_copy("$avp(s:callee_uuid)", "$avp(s:caller_uuid)/d");
+		avp_pushto("$ru", "$avp(s:cfu)");
+		
+		route(3);
+		route(14);
+		exit;
+	}
+	if(is_avp_set("$avp(s:ringtimeout)/n"))
+	{
+		
+		xlog("L_INFO", "Setting ring timeout to $avp(s:ringtimeout) secs - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n");
+		avp_copy("$avp(s:ringtimeout)", "$avp(s:callee_fr_inv_timer)/d");
+	}
+	
+}
+
+########################################################################
+# Request route 'acc-caller'
+########################################################################
+route[5]
+{
+	xlog("L_INFO", "Setting acc source-leg for uuid '$avp(s:caller_uuid)' - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n");
+	avp_printf("$avp(i:901)", "$avp(s:caller_uuid)|$avp(s:acc_caller_user)|$avp(s:acc_caller_domain)|$avp(s:acc_state)");
+	
+}
+
+########################################################################
+# Request route 'acc-callee'
+########################################################################
+route[6]
+{
+	xlog("L_INFO", "Setting acc destination-leg for uuid '$avp(s:callee_uuid)' - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n");
+	avp_printf("$avp(i:902)", "$avp(s:callee_uuid)|$avp(s:acc_callee_user)|$avp(s:acc_callee_domain)");
+	
+}
+
+########################################################################
+# Request route 'acc-failure'
+########################################################################
+route[7]
+{
+	xlog("L_INFO", "Accounting failed request for uuid '$avp(s:caller_uuid)' - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n");
+	route(5);
+	route(6);
+	resetflag(24);
+	acc_db_request("404", "acc");
+	
+}
+
+########################################################################
+# Request route 'cfu-acc'
+########################################################################
+route[8]
+{
+	$avp(s:acc_callee_user) = $rU;
+	$avp(s:acc_callee_domain) = $rd;
+	
+	route(5);
+	route(6);
+	avp_delete("$avp(s:acc_caller_user)");
+	avp_delete("$avp(s:acc_caller_domain)");
+	avp_copy("$avp(s:acc_callee_user)", "$avp(s:acc_caller_user)");
+	avp_copy("$avp(s:acc_callee_domain)", "$avp(s:acc_caller_domain)");
+	avp_delete("$avp(s:acc_state)/g");
+	$avp(s:acc_state) = "cfu";
+	
+}
+
+########################################################################
+# Request route 'clir'
+########################################################################
+route[9]
+{
+	if(isflagset(28) && !isflagset(27))
+	{
+		setflag(27);
+		
+		xlog("L_INFO", "Anonymize caller - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n");
+		uac_replace_from("Anonymous","sip:anonymous at anonymous.invalid");
+		if(is_present_hf("Privacy"))
+		{
+			remove_hf("Privacy");
+		}
+		append_hf("Privacy: id\r\n");
+	}
+	
+}
+
+########################################################################
+# Request route 'stop-media-proxy'
+########################################################################
+route[10]
+{
+	if(isflagset(22))
+	{
+		rtpproxy_destroy();
+	}
+	
+}
+
+########################################################################
+# Request route 'base-route-register'
+########################################################################
+route[11]
+{
+	sl_send_reply("100", "Trying");
+	if(!www_authorize("$td", "subscriber")) 
+	{
+		
+		xlog("L_INFO", "Register authentication failed - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n");
+		www_challenge("$td", "0");
+		exit;
+	}
+	if(!check_to()) 
+	{
+		
+		xlog("L_INFO", "Spoofed To-URI detected - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n");
+		sl_send_reply("403", "Spoofed To-URI Detected");
+		exit;
+	}
+	consume_credentials();
+	if(!search("^Contact:[ ]*\*") && nat_uac_test("19")) 
+	{
+		fix_nated_register();
+		setbflag(6);
+	}
+	if(!save("location")) 
+	{
+		
+		xlog("L_ERR", "Saving contact failed - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n");
+		sl_reply_error();
+		exit;
+	}
+	
+	xlog("L_INFO", "Registration successful - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n");
+	exit;
+	
+}
+
+########################################################################
+# Request route 'base-outbound'
+########################################################################
+route[12]
+{
+	if(is_present_hf("P-Asserted-Identity"))
+	{
+		remove_hf("P-Asserted-Identity");
+	}
+	if(is_present_hf("Remote-Party-ID"))
+	{
+		remove_hf("Remote-Party-ID");
+	}
+	if(is_avp_set("$avp(s:caller_cli)/s"))
+	{
+		if(!isflagset(28))
+		{
+			
+			xlog("L_INFO", "Set caller CLI '$avp(s:caller_cli)' - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n");
+			append_hf("P-Asserted-Identity: <$avp(s:caller_cli)>\r\n");
+		}
+	}
+	
+	route(9);
+	if(isbflagset(6))
+	{
+		if(!isflagset(22) && !search("^Content-Length:[ ]*0"))
+		{
+			setflag(22);
+			rtpproxy_manage();
+		}
+		
+		t_on_reply("2");
+	}
+	else
+	{
+		
+		t_on_reply("1");
+	}
+	if(!isflagset(21))
+	{
+		
+		t_on_failure("2");
+		if(!isflagset(26))
+		{
+			$avp(s:acc_callee_user) = $rU;
+			$avp(s:acc_callee_domain) = $rd;
+			
+			route(5);
+			route(6);
+		}
+	}
+	if(isflagset(29))
+	{
+		append_branch();
+	}
+	if(is_present_hf("Proxy-Authorization"))
+	{
+		consume_credentials();
+	}
+	
+	xlog("L_INFO", "Request leaving server, D-URI='$du' - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n");
+	# no 100 (we already sent it) and no DNS blacklisting
+	if(!t_relay_to("0x05"))
+	{
+		sl_reply_error();
+		if(is_method("INVITE") && isbflagset(6))
+		{
+			rtpproxy_destroy();
+		}
+	}
+	exit;
+	
+}
+
+########################################################################
+# Request route 'base-route-invite'
+########################################################################
+route[13]
+{
+	sl_send_reply("100", "Trying");
+	if(from_gw(1))
+	{
+		$avp(s:caller_uuid) = "0";
+		
+		xlog("L_INFO", "Call from PSTN' - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n");
+		setflag(23);
+	}
+	else
+	{
+		if(allow_trusted())
+		{
+			if(is_avp_set("$avp(s:peer_uuid)/s"))
+			{
+				# use tag-column from trusted-table as uuid for this caller
+				avp_copy("$avp(s:peer_uuid)", "$avp(s:caller_uuid)/d");
+			}
+			else
+			{
+				# if no uuid is set, use "0" as default uuid
+				$avp(s:caller_uuid) = "0";
+			}
+			
+			xlog("L_INFO", "Call from trusted peer with uuid '$avp(s:caller_uuid)' - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n");
+			if(!is_domain_local("$rd"))
+			{
+				
+				xlog("L_INFO", "Rejecting peering attempt with non-local request domain - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n");
+				sl_send_reply("403", "Relaying Denied");
+				exit;
+			}
+			setflag(23);
+		}
+		else
+		{
+			if(!proxy_authorize("$fd", "subscriber")) 
+			{
+				
+				xlog("L_INFO", "Proxy authentication failed - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n");
+				proxy_challenge("$fd", "0");
+				exit;
+			}
+			if(!check_from()) 
+			{
+				
+				xlog("L_INFO", "Spoofed From-URI detected - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n");
+				sl_send_reply("403", "Spoofed From-URI Detected");
+				exit;
+			}
+		}
+	}
+	$avp(s:acc_caller_user) = $fU;
+	$avp(s:acc_caller_domain) = $fd;
+	$avp(s:acc_state) = "call";
+	
+	route(3);
+	if(nat_uac_test("19")) 
+	{
+		fix_nated_contact();
+		setbflag(6);
+	}
+	
+	route(14);
+}
+
+########################################################################
+# Request route 'invite-find-callee'
+########################################################################
+route[14]
+{
+	if(alias_db_lookup("dbaliases"))
+	{
+		
+		xlog("L_INFO", "Callee was aliased - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n");
+	}
+	
+	route(2);
+	if(!is_domain_local("$rd"))
+	{
+		setflag(20);
+		$avp(s:callee_uuid) = "0";
+		
+		route(16);
+	}
+	avp_delete("$avp(s:callee_uuid)");
+	avp_db_query("select uuid from subscriber where username = '$rU'", "$avp(s:callee_uuid)");
+	if(is_avp_set("$avp(s:callee_uuid)/s"))
+	{
+		
+		xlog("L_INFO", "Callee is local, uuid='$avp(s:callee_uuid)' - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n");
+		route(15);
+	}
+	else
+	{
+		$avp(s:callee_uuid) = "0";
+		
+		xlog("L_INFO", "Callee is not local - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n");
+		route(16);
+	}
+	exit;
+	
+}
+
+########################################################################
+# Request route 'invite-to-internal'
+########################################################################
+route[15]
+{
+	route(4);
+	if(!lookup("location")) 
+	{
+		
+		xlog("L_INFO", "Local user offline - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n");
+		$avp(s:acc_callee_user) = $rU;
+		$avp(s:acc_callee_domain) = $rd;
+		
+		route(7);
+		sl_send_reply("404", "User Offline");
+	}
+	else
+	{
+		
+		xlog("L_INFO", "Local user online - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n");
+		route(12);
+	}
+	exit;
+	
+}
+
+########################################################################
+# Request route 'invite-to-external'
+########################################################################
+route[16]
+{
+	if(isflagset(20))
+	{
+		
+		xlog("L_INFO", "Call to foreign domain - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n");
+		route(12);
+		exit;
+	}
+	
+	route(18);
+	if(!isflagset(23))
+	{
+		# don't allow calls relaying from PSTN to PSTN, if not explicitely forwarded
+		if(uri =~ "^sip:[0-9]+@")
+		{
+			# only route numeric users to PSTN
+			if(!load_gws(1))
+			{
+				
+				xlog("L_ERR", "Error loading PSTN gateways - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n");
+				sl_send_reply("503", "PSTN Termination Currently Unavailable");
+				exit;
+			}
+			if(!next_gw())
+			{
+				
+				xlog("L_ERR", "No PSTN gateways available - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n");
+				sl_send_reply("503", "PSTN Termination Currently Unavailable");
+				exit;
+			}
+			setflag(21);
+			
+			t_on_failure("1");
+			route(12);
+		}
+	}
+	
+	xlog("L_INFO", "Call to unknown user - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n");
+	route(7);
+	sl_send_reply("404", "User Not Found");
+	exit;
+	
+}
+
+########################################################################
+# Request route 'normalize-e164'
+########################################################################
+route[17]
+{
+	# European numbering plans look like this:
+	#   CC  = country code (i.e. 43 for Austria)
+	#   NDC = national destination code (i.e. 1 for Vienna)
+	#   SN  = subscriber number (i.e. 4001234)
+	#  
+	#       CC + NDC + SN, i.e. 4314001234
+	#
+	# Within the same CC+NDC, it can be omitted, so if
+	# +4314001234 wants to call +4315002345, one can dial
+	# just 5002345.
+	#
+	# Within the same CC, CC can be ommitted and a "0" is prefixed
+	# to NDC, so if +4314001234 wants to call +4326003456, 
+	# one can dial 026003456.
+	#
+	# For international calls, either "00" or + is prefixed, like
+	# +49123456780 or 0049123456789.
+	#
+	avp_delete("$avp(s:orig_callee_user)/g");
+	$avp(s:orig_callee_user) = $rU;
+	if(uri =~ "^sip:(\+[1-9])?[0-9]+@")
+	{
+		# looks like a PSTN number
+		if(uri =~ "^sip:0[1-9][0-9]+@")
+		{
+			# we have format 0+NDC+SN
+			strip(1);
+			prefix("+49");
+		}
+		else if(uri =~ "^sip:00[1-9]+@")
+		{
+			# we have format 00 + CC + NDC + SN
+			strip(2);
+			prefix("+");
+		}
+		else if(!uri =~ "^sip:\+[1-9][0-9]+@")
+		{
+			# unknown format, maybe NDC wasn't added before?
+			
+			xlog("L_INFO", "Not normalized callee '$avp(s:orig_callee_user)' to E.164 format - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n");
+			return(-1);
+		}
+		# else we have "+" + CC + NDC + SN
+		
+		xlog("L_INFO", "Normalized callee '$avp(s:orig_callee_user)' to E.164 format '$rU' - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n");
+		return(1);
+	}
+	else
+	{
+		
+		xlog("L_INFO", "Not normalized callee '$avp(s:orig_callee_user)' to E.164 format - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n");
+		return(-1);
+	}
+	
+}
+
+########################################################################
+# Request route 'lookup-enum'
+########################################################################
+route[18]
+{
+	route(17);
+	if($rc == 1)
+	{
+		if(enum_query("e164.org."))
+		{
+			# TODO: do GW fallback (load gws, set failure-route)?
+			
+			xlog("L_INFO", "ENUM query succeeded - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n");
+			setdsturi("sip:bogus.localhost:5060");
+			
+			route(12);
+			exit;
+		}
+		else
+		{
+			
+			xlog("L_INFO", "ENUM query failed - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n");
+			# ENUM query failed, revert $rU
+			avp_pushto("$ru/username", "$avp(s:orig_callee_user)");
+		}
+	}
+	
+}
+
+########################################################################
+# Request route 'base-route-local'
+########################################################################
+route[19]
+{
+	t_on_reply("1");
+	if(t_check_trans())
+	{
+		
+		xlog("L_INFO", "Request leaving server - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n");
+		if(!t_relay())
+		{
+			sl_reply_error();
+		}
+	}
+	else
+	{
+		
+		xlog("L_INFO", "Dropping mis-routed request - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n");
+	}
+	exit;
+	
+}
+
+########################################################################
+# Request route 'base-route-generic'
+########################################################################
+route[20]
+{
+	xlog("L_INFO", "Method not supported - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n");
+	sl_send_reply("501", "Method Not Supported Here");
+	exit;
+	
+}
+
+########################################################################
+# Request route 'base-filter-failover'
+########################################################################
+route[21]
+{
+	if(!t_check_status("408|500|503"))
+	{
+		
+		xlog("L_INFO", "No failover routing needed for this response code - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n");
+		route(10);
+		exit;
+	}
+	
+}
+
+########################################################################
+# Reply route 'base-standard-reply'
+########################################################################
+onreply_route[1]
+{
+	xlog("L_INFO", "Reply - S=$rs D=$rr F=$fu T=$tu IP=$si ID=$ci\n");
+	exit;
+	
+}
+
+########################################################################
+# Reply route 'base-nat-reply'
+########################################################################
+onreply_route[2]
+{
+	xlog("L_INFO", "NAT-Reply - S=$rs D=$rr F=$fu T=$tu IP=$si ID=$ci\n");
+	if(nat_uac_test("1"))
+	{
+		fix_nated_contact();
+	}
+	if(isbflagset(6) && status=~"(180)|(183)|2[0-9][0-9]") 
+	{
+		if(!search("^Content-Length:[ ]*0"))
+		{
+			rtpproxy_manage();
+		}
+	}
+	exit;
+	
+}
+
+########################################################################
+# Failure route 'pstn-failover'
+########################################################################
+failure_route[1]
+{
+	xlog("L_INFO", "Failure route for PSTN entered - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n");
+	route(21);
+	if(!next_gw())
+	{
+		
+		xlog("L_ERR", "Failed to select next PSTN gateway - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n");
+		route(10);
+		exit;
+	}
+	
+	t_on_failure("1");
+	route(12);
+}
+
+########################################################################
+# Failure route 'base-standard-failure'
+########################################################################
+failure_route[2]
+{
+	if(t_check_status("422|481|487"))
+	{
+		
+		xlog("L_INFO", "Final reply - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n");
+		route(10);
+		exit;
+	}
+	if(t_check_status("301|302"))
+	{
+		avp_delete("$avp(s:acc_caller_user)/g");
+		avp_delete("$avp(s:acc_caller_domain)/g");
+		avp_delete("$avp(s:acc_state)/g");
+		avp_copy("$avp(s:acc_callee_user)", "$avp(s:acc_caller_user)");
+		avp_copy("$avp(s:acc_callee_domain)", "$avp(s:acc_caller_domain)");
+		$avp(s:acc_state) = "cfc";
+		setflag(29);
+		if(!get_redirects("1:1"))
+		{
+			
+			xlog("L_ERROR", "Failed to fetch contact '$ct' from 301/302 - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n");
+			acc_db_request("480", "acc");
+			
+			route(10);
+			t_reply("480", "Temporarily Unavailable");
+			exit;
+		}
+		# get last URI from destination-set and set it as R-URI
+		avp_delete("$avp(s:tmp)/g");
+		$avp(s:tmp) = $ds;	
+		avp_subst("$avp(s:tmp)", "/.*(sip:.+@[^:;>]+).*$/\1/");
+		avp_pushto("$ru", "$avp(s:tmp)");
+		setflag(29);
+		append_branch();
+		
+		t_on_branch("1");
+		xlog("L_INFO", "Redirect from UAC intercepted - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n");
+		route(14);
+		exit;
+	}
+	if($avp(s:cfc) != $null)
+	{
+		avp_delete("$avp(s:acc_caller_user)/g");
+		avp_delete("$avp(s:acc_caller_domain)/g");
+		avp_delete("$avp(s:acc_state)/g");
+		avp_copy("$avp(s:acc_callee_user)", "$avp(s:acc_caller_user)");
+		avp_copy("$avp(s:acc_callee_domain)", "$avp(s:acc_caller_domain)");
+		$avp(s:acc_state) = "cfc";
+		avp_pushto("$ru", "$avp(s:cfc)");
+		setflag(29);
+		append_branch();
+		
+		t_on_branch("1");
+		xlog("L_INFO", "CFC detected - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n");
+		route(14);
+	}
+	
+	route(21);
+	route(10);
+}
+
+########################################################################
+# Branch route 'cfc-drop-local'
+########################################################################
+branch_route[1]
+{
+	if(is_domain_local("$rd"))
+	{
+		
+		xlog("L_INFO", "Dropping local branch - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n");
+		drop();
+	}
+	
+}
+
diff --git a/test/unit/7.sh b/test/unit/7.sh
new file mode 100755
index 0000000..5aaf636
--- /dev/null
+++ b/test/unit/7.sh
@@ -0,0 +1,42 @@
+#!/bin/bash
+# loads a SIP proxy/registrar config with offnet-termination and accounting
+
+# Copyright (C) 2007 1&1 Internet AG
+#
+# This file is part of Kamailio, a free SIP server.
+#
+# Kamailio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version
+#
+# Kamailio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+# config generated by sipwise wizard
+
+# Needs a default kamailio database setup for mysql
+
+source include/common
+source include/require
+
+CFG=7.cfg
+
+if ! (check_kamailio); then
+	exit 0
+fi ;
+
+# start
+$BIN -a no -w . -f $CFG > /dev/null
+ret=$?
+
+sleep 1
+$KILL
+
+exit $ret
diff --git a/test/unit/8.sh b/test/unit/8.sh
new file mode 100755
index 0000000..3165e2f
--- /dev/null
+++ b/test/unit/8.sh
@@ -0,0 +1,50 @@
+#!/bin/bash
+# creates a dbtext database with kamailiodbctl and deletes it again
+
+# Copyright (C) 2007 1&1 Internet AG
+#
+# This file is part of Kamailio, a free SIP server.
+#
+# Kamailio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version
+#
+# Kamailio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+source include/common
+
+tmp_name=""$RANDOM"_kamailiodb_tmp"
+
+cd $CTL_DIR
+
+# setup config file
+cp $CTLRC $CTLRC.bak
+sed -i'' -e "s/# DBENGINE=MYSQL/DBENGINE=DBTEXT/g" $CTLRC
+sed -i'' -e "s/# INSTALL_EXTRA_TABLES=ask/INSTALL_EXTRA_TABLES=yes/g" $CTLRC
+sed -i'' -e "s/# INSTALL_PRESENCE_TABLES=ask/INSTALL_PRESENCE_TABLES=yes/g" $CTLRC
+sed -i'' -e "s/# INSTALL_DBUID_TABLES=ask/INSTALL_DBUID_TABLES=yes/g" $CTLRC
+
+cp $DBCTL $DBCTL.bak
+sed -i'' -e "s/TEST=\"false\"/TEST=\"true\"/g" $DBCTL
+
+./$DBCTL create $tmp_name > /dev/null
+ret=$?
+
+if [ "$ret" -eq 0 ] ; then
+	./$DBCTL drop $tmp_name > /dev/null
+	ret=$?
+fi ;
+
+# cleanup
+mv $CTLRC.bak $CTLRC
+mv $DBCTL.bak $DBCTL
+
+exit $ret
diff --git a/test/unit/9.sh b/test/unit/9.sh
new file mode 100755
index 0000000..8e21626
--- /dev/null
+++ b/test/unit/9.sh
@@ -0,0 +1,50 @@
+#!/bin/bash
+# test basic db related kamailioctl functionality for mysql
+
+# Copyright (C) 2007 1&1 Internet AG
+#
+# This file is part of Kamailio, a free SIP server.
+#
+# Kamailio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version
+#
+# Kamailio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+source include/common
+
+cd $CTL_DIR
+
+# setup config file
+cp $CTLRC $CTLRC.bak
+cp $CTL $CTL.bak
+sed -i'' -e "s/# DBENGINE=MYSQL/DBENGINE=MYSQL/g" $CTLRC
+sed -i'' -e "s/TEST=\"false\"/TEST=\"true\"/g" $CTL
+
+./$CTL avp list > /dev/null
+
+ret=$?
+
+if [ "$ret" -eq 0 ] ; then
+	./$CTL domain showdb > /dev/null
+	ret=$?
+fi ;
+
+if [ "$ret" -eq 0 ] ; then
+	./$CTL dispatcher show > /dev/null
+	ret=$?
+fi ;
+
+# cleanup
+mv $CTLRC.bak $CTLRC
+mv $CTL.bak $CTL
+
+exit $ret
diff --git a/test/unit/Makefile b/test/unit/Makefile
new file mode 100644
index 0000000..83b3dba
--- /dev/null
+++ b/test/unit/Makefile
@@ -0,0 +1,36 @@
+# Makefile for running test unit
+#
+TESTS_FILES ?= $(wildcard *.sh)
+TESTS_EXCLUDE ?=
+TESTS ?= $(filter-out $(patsubst %,%.sh,$(TESTS_EXCLUDE)), $(TESTS_FILES))
+
+all:
+	@for FILE in $(TESTS) ; do \
+		if [ -f $$FILE ] ; then \
+			if [ -x $$FILE ] ; then \
+				echo "run test `basename $$FILE .sh`:" `head -n 2 "$$FILE" | tail -n 1 | cut -c 3-` ; \
+				./$$FILE ; \
+				ret=$$? ; \
+					if [ ! "$$ret" -eq 0 ] ; then \
+						echo "failed" ; RES=1;\
+					fi ; \
+			fi ; \
+		fi ; \
+	done ; \
+	exit $$RES;
+
+run:
+	- at if [ -f $(UNIT) ] ; then \
+		if [ -x $(UNIT) ] ; then \
+			echo "Run test `basename $(UNIT) .sh`:" `head -n 2 "$(UNIT)" | tail -n 1 | cut -c 3-` ; \
+			./$(UNIT) ; \
+			ret=$$? ; \
+				if [ ! "$$ret" -eq 0 ] ; then \
+					echo "Test unit file $(UNIT): failed" ; \
+				else \
+					echo "Test unit file $(UNIT): ok" ; \
+				fi ; \
+		fi ; \
+	else \
+		echo "Test unit file $(UNIT): not found" ; \
+	fi ;
diff --git a/test/unit/README b/test/unit/README
new file mode 100644
index 0000000..51abf4d
--- /dev/null
+++ b/test/unit/README
@@ -0,0 +1,39 @@
+Kamailio Test Unit
+==================
+
+This directory contains some small "smoke tests", that should assure that
+basic functionality of the server work as required. This tests should consists
+of one shell script and a config file if needed. They should not need much time
+for execution, to allow the run of the complete test suite in a few seconds.
+
+All test scripts must be self-contained, should not have external dependencies
+and must clean up after they are run. The second line in each scripts should
+contain a small comment that describe the task of the test, it should not
+output any messages on successful runs.
+
+This tests should (in the current state) only run by developers who know
+what they do. They could delete your database, produce core dumps that fill
+your harddisk or do other nasty things..
+
+Dependencies
+------------
+
+External tools needed by some test units:
+
+  - SIPP (http://sipp.sourceforge.net)
+  - SIPSAK  (https://github.com/nils-ohlmeier/sipsak)
+
+Usage
+-----
+
+To execute all unit tests, run:
+
+    make all
+
+To run a specific unit test, run:
+
+    make run UNIT=scripname
+
+Scriptname is the name of shell file to execute, for example:
+
+    make run UNIT=1.sh
diff --git a/test/unit/carrierroute-2.cfg b/test/unit/carrierroute-2.cfg
new file mode 100644
index 0000000..f3a6f8f
--- /dev/null
+++ b/test/unit/carrierroute-2.cfg
@@ -0,0 +1,30 @@
+domain proxy {
+	prefix 49721123456787 {
+		max_targets = 2
+
+		target 127.0.0.1:7000 {
+			prob = 0.5
+			status = 1
+		}
+		target 127.0.0.1:8000 {
+			prob = 0.5
+			status = 1
+		}
+	}
+	prefix 49721123456786 {
+		max_targets = 1
+
+		target 127.0.0.1:9000 {
+			prob = 1.0
+			status = 1
+		}
+	}
+	prefix 49721123456785 {
+		max_targets = 1
+
+		target 127.0.0.1:10000 {
+			prob = 1.0
+			status = 1
+		}
+	}
+}
diff --git a/test/unit/carrierroute.cfg b/test/unit/carrierroute.cfg
new file mode 100644
index 0000000..1d0ee3f
--- /dev/null
+++ b/test/unit/carrierroute.cfg
@@ -0,0 +1,100 @@
+domain register {
+	prefix NULL {
+		max_targets = 3
+
+		target test1 {
+			prob = 0.400000
+			hash_index = 3
+			status = 0
+		}
+		target test3.localdomain {
+			prob = 0.500000
+			hash_index = 2
+			status = 1
+		}
+		target test2.localdomain {
+			prob = 0.500000
+			hash_index = 1
+			status = 1
+		}
+	}
+}
+
+domain proxy {
+	prefix 2 {
+		max_targets = 2
+
+		target test8.localdomain {
+			prob = 0.100000
+			hash_index = 2
+			status = 1
+		}
+		target test7.localdomain {
+			prob = 0.700000
+			hash_index = 1
+			status = 1
+		}
+	}
+	prefix 42 {
+		max_targets = 3
+
+		target test6.localdomain {
+			prob = 0.100000
+			hash_index = 2
+			status = 1
+		}
+		target test5.localdomain {
+			prob = 0.200000
+			hash_index = 1
+			status = 1
+		}
+		target test4 {
+			prob = 0.700000
+			hash_index = 3
+			status = 1
+		}
+	}
+	prefix 49 {
+		max_targets = 3
+
+		target test6.localdomain {
+			prob = 0.500000
+			hash_index = 3
+			status = 1
+		}
+		target test5.localdomain {
+			prob = 0.500000
+			hash_index = 1
+			status = 0
+		}
+		target test4 {
+			prob = 0.400000
+			hash_index = 2
+			status = 1
+		}
+	}
+}
+
+domain other {
+	prefix NULL {
+		max_targets = 3
+
+		target test1 {
+			prob = 0.400000
+			hash_index = 3
+			status = 0
+		}
+		target test3.localdomain {
+			prob = 0.500000
+			hash_index = 2
+			status = 1
+			backed_up = {1}
+		}
+		target test2.localdomain {
+			prob = 0.500000
+			hash_index = 1
+			status = 0
+			backup = 2
+		}
+	}
+}
diff --git a/test/unit/cpl_ignore.xml b/test/unit/cpl_ignore.xml
new file mode 100644
index 0000000..dd5ebd5
--- /dev/null
+++ b/test/unit/cpl_ignore.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<cpl>
+  <incoming>
+    <reject status="400" reason="Busy" />
+  </incoming>
+</cpl>
diff --git a/test/unit/cpl_test.xml b/test/unit/cpl_test.xml
new file mode 100644
index 0000000..4bce93d
--- /dev/null
+++ b/test/unit/cpl_test.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<scenario name="invite_client">
+  <send retrans="500">
+      <![CDATA[
+
+      INVITE sip:alice at localhost:5059 SIP/2.0
+      Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
+      From: <sip:alice at localhost>;tag=[call_number]
+      To: <sip:alice at localhost>
+      Call-ID: [call_id]
+      CSeq: 1 INVITE
+      Contact: sip:alice@[local_ip]:[local_port]
+      Max-Forwards: 5
+      Expires: 1800
+      User-Agent: SIPp/Linux
+      Content-Length: 0
+      ]]>
+   </send>
+   <recv response="400" auth="true">
+   </recv>
+</scenario>
diff --git a/test/unit/failure_route.xml b/test/unit/failure_route.xml
new file mode 100644
index 0000000..6603921
--- /dev/null
+++ b/test/unit/failure_route.xml
@@ -0,0 +1,140 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+
+<scenario name="Basic UAS with failure route">
+
+  <recv request="INVITE">
+  </recv>
+
+  <send retrans="500">
+    <![CDATA[
+
+      SIP/2.0 503 Service Unavailable
+      [last_Via:]
+      [last_From:]
+      [last_To:];tag=[call_number]
+      [last_Call-ID:]
+      [last_CSeq:]
+      Contact: <sip:[local_ip]:[local_port];transport=[transport]>
+      Content-Type: application/sdp
+      Content-Length: [len]
+
+      v=0
+      o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip]
+      s=-
+      c=IN IP[media_ip_type] [media_ip]
+      t=0 0
+      m=audio [media_port] RTP/AVP 0
+      a=rtpmap:0 PCMU/8000
+
+    ]]>
+  </send>
+
+  <recv request="ACK">
+  </recv>
+
+  <recv request="INVITE">
+  </recv>
+
+  <send retrans="500">
+    <![CDATA[
+
+      SIP/2.0 486 Busy Here
+      [last_Via:]
+      [last_From:]
+      [last_To:];tag=[call_number]
+      [last_Call-ID:]
+      [last_CSeq:]
+      Contact: <sip:[local_ip]:[local_port];transport=[transport]>
+      Content-Type: application/sdp
+      Content-Length: [len]
+
+      v=0
+      o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip]
+      s=-
+      c=IN IP[media_ip_type] [media_ip]
+      t=0 0
+      m=audio [media_port] RTP/AVP 0
+      a=rtpmap:0 PCMU/8000
+
+    ]]>
+  </send>
+
+  <recv request="ACK">
+  </recv>
+
+  <recv request="INVITE">
+  </recv>
+
+  <send>
+    <![CDATA[
+
+      SIP/2.0 180 Ringing
+      [last_Via:]
+      [last_From:]
+      [last_To:];tag=[call_number]
+      [last_Call-ID:]
+      [last_CSeq:]
+      Contact: <sip:[local_ip]:[local_port];transport=[transport]>
+      Content-Length: 0
+
+    ]]>
+  </send>
+
+  <send retrans="500">
+    <![CDATA[
+
+      SIP/2.0 200 OK
+      [last_Via:]
+      [last_From:]
+      [last_To:];tag=[call_number]
+      [last_Call-ID:]
+      [last_CSeq:]
+      Contact: <sip:[local_ip]:[local_port];transport=[transport]>
+      Content-Type: application/sdp
+      Content-Length: [len]
+
+      v=0
+      o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip]
+      s=-
+      c=IN IP[media_ip_type] [media_ip]
+      t=0 0
+      m=audio [media_port] RTP/AVP 0
+      a=rtpmap:0 PCMU/8000
+
+    ]]>
+  </send>
+
+  <recv request="ACK" optional="true">
+  </recv>
+
+  <recv request="BYE">
+  </recv>
+
+  <send>
+    <![CDATA[
+
+      SIP/2.0 200 OK
+      [last_Via:]
+      [last_From:]
+      [last_To:]
+      [last_Call-ID:]
+      [last_CSeq:]
+      Contact: <sip:[local_ip]:[local_port];transport=[transport]>
+      Content-Length: 0
+
+    ]]>
+  </send>
+
+  <!-- Keep the call open for a while in case the 200 is lost to be     -->
+  <!-- able to retransmit it if we receive the BYE again.               -->
+  <pause milliseconds="4000"/>
+
+
+  <!-- definition of the response time repartition table (unit is ms)   -->
+  <ResponseTimeRepartition value="10, 20, 30, 40, 50, 100, 150, 200"/>
+
+  <!-- definition of the call length repartition table (unit is ms)     -->
+  <CallLengthRepartition value="10, 50, 100, 500, 1000, 5000, 10000"/>
+
+</scenario>
+
diff --git a/test/unit/include/common b/test/unit/include/common
new file mode 100644
index 0000000..2459843
--- /dev/null
+++ b/test/unit/include/common
@@ -0,0 +1,23 @@
+# all database modules
+DB_ALL_MOD="acc|alias_db|auth_db|avpops|dialog|dialplan|dispatcher|domain|domainpolicy|group|imc|lcr|msilo|siptrace|speeddial|uri_db|usrloc|permissions|pdt|userblacklist"
+# root directory relative to tests
+SRC_DIR="../.."
+CTL_DIR="$SRC_DIR/utils/kamctl"
+CTLRC="$CTL_DIR/kamctlrc"
+CTL="$CTL_DIR/kamctl"
+DBCTL="$CTL_DIR/kamdbctl"
+BIN="$SRC_DIR/kamailio"
+if [ -f $SRC_DIR/kamailio ] ; then
+    BIN="$SRC_DIR/kamailio"
+    BNAME="kamailio"
+else
+    if [ -f $SRC_DIR/ser ] ; then
+		BIN="$SRC_DIR/ser"
+		BNAME="ser"
+    else
+		echo "WARNING Binary not found!"
+    fi
+fi
+KILL="killall -15 $BNAME"
+# test directory relative to root
+TEST_DIR="test/unit"
diff --git a/test/unit/include/database b/test/unit/include/database
new file mode 100644
index 0000000..d5e6a0f
--- /dev/null
+++ b/test/unit/include/database
@@ -0,0 +1,69 @@
+# Copyright (C) 2008 1&1 Internet AG
+#
+# This file is part of kamailio, a free SIP server.
+#
+# kamailio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version
+#
+# kamailio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+MYSQL="mysql kamailio --show-warnings --batch --user=kamailio --password=kamailiorw -e"
+
+export PGPASSWORD="kamailiorw"
+PSQL="psql -A -t -n -q -h localhost -U kamailio kamailio -c"
+
+ISQL="isql -b -v -d0x0 kamailio kamailio kamailiorw"
+
+function check_mysql() {
+	$MYSQL "select * from location;" > /dev/null
+	if ! [ "$?" -eq 0 ] ; then
+		echo "can't read from database"
+		return 1
+	fi;
+	$MYSQL "insert into location (user_agent) values ('___test___');" > /dev/null
+	if ! [ "$?" -eq 0 ] ; then
+		echo "can't write to database"
+		return 1
+	fi;
+	$MYSQL "delete from location where user_agent ='___test___';" > /dev/null
+	return 0
+}
+
+function check_postgres() {
+	$PSQL "select * from location;" > /dev/null
+	if ! [ "$?" -eq 0 ] ; then
+		echo "can't read from database"
+		return 1
+	fi;
+	$PSQL "insert into location (user_agent) values ('___test___');" > /dev/null
+	if ! [ "$?" -eq 0 ] ; then
+		echo "can't write to database"
+		return 1
+	fi;
+	$PSQL "delete from location where user_agent ='___test___';" > /dev/null
+	return 0
+}
+
+function check_unixodbc() {
+	echo "select * from location;" | $ISQL  > /dev/null
+	if ! [ "$?" -eq 0 ] ; then
+		echo "can't read from database"
+		return 1
+	fi;
+	echo "insert into location (id, user_agent) values ('$RANDOM', '___test___');" | $ISQL > /dev/null
+	if ! [ "$?" -eq 0 ] ; then
+		echo "can't write to database"
+		return 1
+	fi;
+	echo "delete from location where user_agent ='___test___';" | $ISQL > /dev/null
+	return 0
+}
diff --git a/test/unit/include/require b/test/unit/include/require
new file mode 100644
index 0000000..825dfd7
--- /dev/null
+++ b/test/unit/include/require
@@ -0,0 +1,64 @@
+# Copyright (C) 2008 1&1 Internet AG
+#
+# This file is part of kamailio, a free SIP server.
+#
+# kamailio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version
+#
+# kamailio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+source include/common
+
+function check_kamailio() {
+	if ! (test -e $BIN) ; then
+		echo "kamailio not found, not run"
+		return 1
+	fi;
+	return 0
+}
+
+function check_module() {
+	if [ $# -ne 1 ]; then
+		echo "wrong number of params in check_module()"
+		return 1
+	fi
+
+	if ! (test -e $SRC_DIR/modules/$1/$1.so) ; then
+		echo "$SRC_DIR/modules/$1/$1.so not found, not run"
+		return 1
+	fi;
+	return 0
+}
+
+function check_netcat() {
+	if ! ( which nc > /dev/null ); then
+		echo "netcat not found, not run"
+		return 1
+	fi;
+	return 0
+}
+
+function check_sipp() {
+	if ! ( which sipp > /dev/null ); then
+		echo "sipp not found, not run"
+		return 1
+	fi;
+	return 0
+}
+
+function check_sipsak() {
+	if ! ( which sipsak > /dev/null ); then
+		echo "sipsak not found, not run"
+		return 1
+	fi;
+	return 0
+}
diff --git a/test/unit/inv_auth.xml b/test/unit/inv_auth.xml
new file mode 100644
index 0000000..5aa5902
--- /dev/null
+++ b/test/unit/inv_auth.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<scenario name="invite_client">
+  <send retrans="500">
+      <![CDATA[
+
+      INVITE sip:alice at localhost:5059 SIP/2.0
+      Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
+      From: <sip:alice at localhost>;tag=[call_number]
+      To: <sip:alice at localhost>
+      Call-ID: [call_id]
+      CSeq: 1 INVITE
+      Contact: sip:alice@[local_ip]:[local_port]
+      Max-Forwards: 5
+      Expires: 1800
+      User-Agent: SIPp/Linux
+      Content-Length: 0
+      ]]>
+   </send>
+   <recv response="407" auth="true">
+   </recv>
+
+   <send retrans="500">
+      <![CDATA[
+
+      INVITE sip:alice at localhost:5059 SIP/2.0
+      Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
+      From: <sip:alice at localhost>;tag=[call_number]
+      To: <sip:alice at localhost>
+      Call-ID: [call_id]
+      CSeq: 2 INVITE
+      Contact: sip:alice@[local_ip]:[local_port]
+      [authentication username=alice password=alice realm=localhost];
+      Max-Forwards: 5
+      Expires: 1800
+      User-Agent: SIPp/Linux
+      Content-Length: 0
+    ]]>
+   </send>
+   <recv response="200">
+  </recv>
+   </scenario>
diff --git a/test/unit/invite.sip b/test/unit/invite.sip
new file mode 100644
index 0000000..7a01a69
--- /dev/null
+++ b/test/unit/invite.sip
@@ -0,0 +1,12 @@
+INVITE sip:1000 at 127.0.0.1 SIP/2.0
+Via: SIP/2.0/UDP 172.17.13.240:5061;rport;branch=z9hG4bKydcnjlpe
+Max-Forwards: 70
+To: <sip:1000 at 127.0.0.1>
+From: <sip:1001 at 127.0.0.1>;tag=dyggg
+Call-ID: ccgdnpeqtepegxu at 172.17.13.240
+CSeq: 479 INVITE
+Contact: <sip:1001 at 172.17.13.240:5061>;expires=3600
+Allow: INVITE,ACK,BYE,CANCEL,OPTIONS,PRACK,REFER,NOTIFY,SUBSCRIBE,INFO
+User-Agent: Twinkle/1.0
+Content-Length: 0
+
diff --git a/test/unit/presence.cfg b/test/unit/presence.cfg
new file mode 100644
index 0000000..91cc344
--- /dev/null
+++ b/test/unit/presence.cfg
@@ -0,0 +1,83 @@
+#
+# $Id$
+#
+# simple quick-start config script - Stand-alone presence server
+#
+ 
+# ----------- global configuration parameters ------------------------
+ 
+debug=3      # debug level (cmd line: -dddddddddd)
+fork=yes
+log_stderror=no    # (cmd line: -E)
+children=4
+
+listen=127.0.0.1 
+port=5059
+
+dns=no
+rev_dns=no
+
+# ------------------ module loading ----------------------------------
+
+#set module path
+mpath="../../modules/"
+
+loadmodule "db_mysql/db_mysql.so"
+loadmodule "sl/sl.so"
+loadmodule "maxfwd/maxfwd.so"
+loadmodule "textops/textops.so"
+loadmodule "tm/tm.so"
+loadmodule "rr/rr.so"
+loadmodule "presence/presence.so"
+loadmodule "presence_xml/presence_xml.so"
+loadmodule "avpops/avpops.so"
+loadmodule "mi_fifo/mi_fifo.so"
+ 
+# ----------------- setting module-specific parameters ---------------
+ 
+# -- rr params --
+# add value to ;lr param to make some broken UAs happy
+modparam("rr", "enable_full_lr", 1)
+ 
+# -- presence params --
+modparam("presence|presence_xml", "db_url", "mysql://kamailio:kamailiorw@localhost/kamailio")
+ 
+modparam("presence_xml", "force_active", 1)
+ 
+modparam("presence", "server_address", "sip:10.10.10.10:5060")
+
+modparam("mi_fifo", "fifo_name", "/tmp/kamailio_fifo_presence")
+ 
+# -------------------------  request routing logic -------------------
+ 
+# main routing logic
+ 
+request_route{
+    # initial sanity checks -- messages with
+    # max_forwards==0, or excessively long requests
+    if (!mf_process_maxfwd_header("10")) {
+        sl_send_reply("483","Too Many Hops");
+        exit;
+    }
+ 
+    if (!is_method("SUBSCRIBE|PUBLISH")) {
+        sl_send_reply("488", "Not Acceptable Here");
+        exit;
+    }
+ 
+    # presence handling
+    if (! t_newtran()) {
+        sl_reply_error();
+        exit;
+	}
+ 
+    if(is_method("PUBLISH")) {
+        handle_publish();
+        t_release();
+    } else if( is_method("SUBSCRIBE")) {
+        handle_subscribe();
+        t_release();
+    }
+ 
+    exit;
+}
diff --git a/test/unit/publish.csv b/test/unit/publish.csv
new file mode 100644
index 0000000..bdf856b
--- /dev/null
+++ b/test/unit/publish.csv
@@ -0,0 +1,4 @@
+SEQUENTIAL
+user1;127.0.0.1:5059
+user2;127.0.0.1:5059
+
diff --git a/test/unit/publish_scenario.xml b/test/unit/publish_scenario.xml
new file mode 100644
index 0000000..fedef0b
--- /dev/null
+++ b/test/unit/publish_scenario.xml
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!DOCTYPE scenario SYSTEM "sipp.dtd">
+
+<scenario name="publish_scenario">
+
+  <!--  First PUBLISH without Etag -->
+  <!--  Then another publish with status 'busy'
+  -->
+    <send retrans="1000">
+    <![CDATA[
+
+
+PUBLISH sip:[field0]@[field1] SIP/2.0
+Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
+Max-Forwards: 70
+Contact: sip:[field0]@[local_ip]:[local_port]
+To: <sip:[field0]@[field1]>
+From: <sip:[field0]@[field1]>;tag=[call_number]
+Call-ID: [call_id]
+CSeq: 1 PUBLISH
+Expires: 60
+Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO
+Content-Type: application/pidf+xml
+User-Agent: sipp
+Event: presence
+Content-Length: [len]
+
+<?xml version='1.0' encoding='UTF-8'?><presence xmlns='urn:ietf:params:xml:ns:pidf' xmlns:dm='urn:ietf:params:xml:ns:pidf:data-model' xmlns:rpid='urn:ietf:params:xml:ns:pidf:rpid' xmlns:c='urn:ietf:params:xml:ns:pidf:cipid' entity='sip:[field0]@[field1]'><tuple id='t532d494f'><status><basic>open</basic></status></tuple><dm:person id='p98169736'><rpid:activities><rpid:unknown/></rpid:activities></dm:person></presence>
+]]>
+  </send>
+
+  <recv response="200" rtd="true">
+    <action>
+        <!-- Save the ETag value in [$3] -->
+        <ereg regexp=".*"
+              search_in="hdr"
+              header="SIP-ETag:"
+              check_it="true"
+              assign_to="3"/>	
+        <!-- Save the To-tag value in [$4] -->
+        <ereg regexp=".*;tag=(.*)"
+              search_in="hdr"
+              header=To:"
+              check_it="true"
+              assign_to="19,4"/>	
+    </action>
+  </recv>
+
+  <pause min="500" max="1000"/>
+
+  <send retrans="1000">
+    <![CDATA[
+
+PUBLISH sip:[field0]@[field1] SIP/2.0
+Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]---[$4]
+Max-Forwards: 70
+Contact: sip:[field0]@[local_ip]:[local_port]
+To: "[field0]"<sip:[field0]@[field1]>
+From: "[field0]"<sip:[field0]@[field1]>;tag=[call_number]
+Call-ID: [$4]///[call_id]
+CSeq: 1 PUBLISH
+Expires: 60
+Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO
+Content-Type: application/pidf+xml
+User-Agent: sipp
+Event: presence
+SIP-If-Match:[$3]
+Content-Length: [len]
+
+<?xml version='1.0' encoding='UTF-8'?><presence xmlns='urn:ietf:params:xml:ns:pidf' xmlns:dm='urn:ietf:params:xml:ns:pidf:data-model' xmlns:rpid='urn:ietf:params:xml:ns:pidf:rpid' xmlns:c='urn:ietf:params:xml:ns:pidf:cipid' entity='sip:[field0]@[field1]'><tuple id='t532d494f'><status><basic>open</basic></status></tuple><dm:person id='p98169736'><rpid:activities><rpid:busy/></rpid:activities><dm:note>Busy</dm:note></dm:person></presence>
+]]>
+  </send>
+
+  <recv response="200" rtd="true">
+      <action>
+        <!-- Save the To-tag value in [$4] -->
+        <ereg regexp=".*;tag=(.*)"
+              search_in="hdr"
+              header=To:"
+              check_it="true"
+              assign_to="19,4"/>	
+    </action>
+  </recv>
+
+</scenario>
+
diff --git a/test/unit/reg_auth.xml b/test/unit/reg_auth.xml
new file mode 100644
index 0000000..92a7d49
--- /dev/null
+++ b/test/unit/reg_auth.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<scenario name="register_client">
+  <send retrans="500">
+      <![CDATA[
+
+      REGISTER sip:localhost:5059 SIP/2.0
+      Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
+      From: <sip:alice at localhost>;tag=[call_number]
+      To: <sip:alice at localhost>
+      Call-ID: [call_id]
+      CSeq: 1 REGISTER
+      Contact: sip:alice@[local_ip]:[local_port]
+      Max-Forwards: 5
+      Expires: 1800
+      User-Agent: SIPp/Linux
+      Content-Length: 0
+      ]]>
+   </send>
+   <recv response="401" auth="true">
+   </recv>
+
+   <send retrans="500">
+      <![CDATA[
+      REGISTER sip:localhost:5059 SIP/2.0
+      Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
+      From: <sip:alice at localhost>;tag=[call_number]
+      To: <sip:alice at localhost>
+      Call-ID: [call_id]
+      CSeq: 2 REGISTER
+      Contact: sip:alice@[local_ip]:[local_port]
+      [authentication username=alice password=alice realm=localhost];
+      Max-Forwards: 5
+      Expires: 1800
+      User-Agent: SIPp/Linux
+      Content-Length: 0
+    ]]>
+   </send>
+   <recv response="200">
+  </recv>
+   </scenario>
diff --git a/test/unit/register.sip b/test/unit/register.sip
new file mode 100644
index 0000000..dc409f6
--- /dev/null
+++ b/test/unit/register.sip
@@ -0,0 +1,11 @@
+REGISTER sip:127.0.0.1 SIP/2.0
+Via: SIP/2.0/UDP 172.17.13.240:5061;rport;branch=z9hG4bKydcnjlpe
+Max-Forwards: 70
+To: <sip:1000 at 127.0.0.1>
+From: <sip:1000 at 127.0.0.1>;tag=dyggg
+Call-ID: ccgdnpeqtepegxu at 172.17.13.240
+CSeq: 479 REGISTER
+Contact: <sip:1000 at 172.17.13.240:5061>;expires=3600
+Allow: INVITE,ACK,BYE,CANCEL,OPTIONS,PRACK,REFER,NOTIFY,SUBSCRIBE,INFO
+User-Agent: Twinkle/1.0
+Content-Length: 0
diff --git a/test/unit/route-empty.cfg b/test/unit/route-empty.cfg
new file mode 100644
index 0000000..2ac3275
--- /dev/null
+++ b/test/unit/route-empty.cfg
@@ -0,0 +1,3 @@
+request_route {
+	;
+}
diff --git a/test/unit/subscribe_notify.csv b/test/unit/subscribe_notify.csv
new file mode 100644
index 0000000..2da9384
--- /dev/null
+++ b/test/unit/subscribe_notify.csv
@@ -0,0 +1,4 @@
+SEQUENTIAL
+user1;127.0.0.1:5059;user2
+user2;127.0.0.1:5059;user1
+user2;127.0.0.1:5059;user3
diff --git a/test/unit/subscribe_notify_scenario.xml b/test/unit/subscribe_notify_scenario.xml
new file mode 100644
index 0000000..1cdfa20
--- /dev/null
+++ b/test/unit/subscribe_notify_scenario.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!DOCTYPE scenario SYSTEM "sipp.dtd">
+
+<scenario name="subscribe_notify__presence_scenario">
+
+    <!-- Send SUBSCRIBE for presence  and receive NOTIFY message -->
+
+    <send retrans="1000">
+    <![CDATA[
+
+
+SUBSCRIBE sip:[field2]@[field1] SIP/2.0
+Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
+Max-Forwards: 70
+Contact: sip:[field0]@[local_ip]:[local_port]
+To: <sip:[field2]@[field1]>
+From: "[field0]"<sip:[field0]@[field1]>;tag=[call_number]
+Call-ID: [call_id]
+CSeq: 1 SUBSCRIBE
+Expires: 3600
+Accept: multipart/related, application/rlmi+xml, application/pidf+xml
+Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO
+User-Agent: sipp
+Event: presence
+Content-Length: 0
+
+    ]]>
+  </send>
+
+  <recv response="202" rtd="true">
+  </recv>
+
+  <recv request="NOTIFY">
+  </recv>
+
+  <send crlf="true">
+    <![CDATA[
+
+      SIP/2.0 200 OK
+      [last_Via:]
+      [last_From:]
+      [last_To:]
+      [last_Call-ID:]
+      [last_CSeq:]
+      User-Agent: sipp
+      Content-Length: 0
+
+    ]]>
+  </send>
+
+  <!-- definition of the response time repartition table (unit is ms)   -->
+  <ResponseTimeRepartition value="10, 20, 30, 40, 50, 100, 150, 200"/>
+
+  <!-- definition of the call length repartition table (unit is ms)     -->
+  <CallLengthRepartition value="10, 50, 100, 500, 1000, 5000, 10000"/>
+
+</scenario>
+
diff --git a/test/unit/unregister.sip b/test/unit/unregister.sip
new file mode 100644
index 0000000..2686ddc
--- /dev/null
+++ b/test/unit/unregister.sip
@@ -0,0 +1,11 @@
+REGISTER sip:127.0.0.1 SIP/2.0
+Via: SIP/2.0/UDP 172.17.13.240:5061;rport;branch=z9hG4bKruthdewh
+Max-Forwards: 70
+To: <sip:1000 at 127.0.0.1>
+From: <sip:1000 at 127.0.0.1>;tag=jwnqc
+Call-ID: ccgdnpeqtepegxu at 172.17.13.240
+CSeq: 481 REGISTER
+Contact: <sip:1000 at 172.17.13.240:5061>;expires=0
+Allow: INVITE,ACK,BYE,CANCEL,OPTIONS,PRACK,REFER,NOTIFY,SUBSCRIBE,INFO
+User-Agent: Twinkle/1.0
+Content-Length: 0
diff --git a/test/use_jab.cfg b/test/use_jab.cfg
new file mode 100644
index 0000000..2b7a186
--- /dev/null
+++ b/test/use_jab.cfg
@@ -0,0 +1,86 @@
+#
+# configuration for Jabber module testing
+#
+#
+
+
+debug=9          # debug level (cmd line: -dddddddddd)
+#fork=yes          # (cmd. line: -D)
+fork=no
+log_stderror=yes  # (cmd line: -E)
+#log_stderror=no   # (cmd line: -E)
+
+
+children=4
+check_via=no      # (cmd. line: -v)
+dns=off           # (cmd. line: -r)
+rev_dns=off       # (cmd. line: -R)
+#port=5070
+#listen=10.0.0.179
+#listen=192.168.57.33
+loop_checks=0
+# for more info: sip_router -h
+
+#modules
+loadmodule "modules/print/print.so"
+loadmodule "modules/textops/textops.so"
+loadmodule "modules/tm/tm.so"
+#loadmodule "modules/rr/rr.so"
+loadmodule "modules/maxfwd/maxfwd.so"
+loadmodule "modules/sl/sl.so"
+loadmodule "modules/jabber/jabber.so"
+#loadmodule "modules/cpl/cpl.so"
+
+modparam("jabber","jaddress","gorn.fokus.gmd.de")
+modparam("jabber","jport",5222)
+
+route{
+	sl_filter_ACK();
+
+	if ( !mf_process_maxfwd_header("10") )
+	{
+		sl_send_reply("483","To Many Hops");
+		drop();
+	};
+
+/*
+	if (method=="INVITE")
+	{
+		log("SER : runing CPL!! :)\n");
+		if ( !cpl_run_script() )
+		{
+			log("SER : Error during running CPL script!\n");
+		}else{
+			if ( cpl_is_response_reject() ) {
+				sl_send_reply("603","I am not available!");
+				drop();
+			}else if ( cpl_is_response_redirect() ) {
+				log("SER : redirect\n");
+				cpl_update_contact();
+				sl_send_reply("302","Moved temporarily");
+				drop();
+			};
+		};
+	};
+*/
+
+	if (uri=~"sip:.*@icq\.gorn\.fokus\.gmd\.de" || uri=~"sip:.*@sms\.gorn\.fokus\.gmd\.de"|| uri=~"sip:.*@msn\.gorn\.fokus\.gmd\.de")
+	{
+		if (method=="MESSAGE")
+		{
+			log("MESSAGE received -> sending as JABBER\n");
+			if (jab_send_message())
+			{
+				sl_send_reply("202","Accepted");
+			}else{
+				sl_send_reply("502","Bad gateway");
+			};
+		}else{
+			log("NON_Message request received for JABBER gateway->dropt!\n");
+			sl_send_reply("501","Not implemented");
+		};
+		break;
+	};
+
+	t_relay();
+}
diff --git a/test/via_parse.c b/test/via_parse.c
new file mode 100644
index 0000000..0493c02
--- /dev/null
+++ b/test/via_parse.c
@@ -0,0 +1,1583 @@
+
+/* test program -> via parse */
+/*
+ * Copyright (C) 2001-2003 FhG Fokus
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+
+
+/* parsing:           compact form:
+ */
+
+/* 
+ * still TODO/test:
+ *  - parse next via
+ *  - return a list of header structs
+ *  - '[' ']' ipv6 parsing!
+ *  - return list of params
+ *  - test ^\s...'
+ *  - add support for parsing via front (SIP/2.0/UDP)
+ */
+
+#include <stdio.h>
+
+/* main via states (uri:port ...) */
+enum{	         F_HOST,    P_HOST,
+		L_PORT,  F_PORT,    P_PORT,
+		L_PARAM, F_PARAM,   P_PARAM,
+		L_VIA,   F_VIA,
+		         F_COMMENT, P_COMMENT,
+				 F_IP6HOST, P_IP6HOST,
+				 F_CRLF,
+				 F_LF,
+				 F_CR,
+				 END_OF_HEADER
+	};
+
+/* first via part state */
+enum{	         F_SIP=100,
+		SIP1, SIP2, FIN_SIP,
+		L_VER, F_VER,
+		VER1, VER2, FIN_VER,
+		L_PROTO, F_PROTO, P_PROTO
+	};
+
+/* param related states */
+enum{	L_VALUE=200,   F_VALUE, P_VALUE, P_STRING,
+		HIDDEN1,   HIDDEN2,   HIDDEN3,   HIDDEN4,   HIDDEN5,
+		TTL1,      TTL2,
+		BRANCH1,   BRANCH2,   BRANCH3,   BRANCH4,   BRANCH5,
+		MADDR1,    MADDR2,    MADDR3,    MADDR4,
+		RECEIVED1, RECEIVED2, RECEIVED3, RECEIVED4, RECEIVED5, RECEIVED6,
+		RECEIVED7,
+		/* fin states (227-...)*/
+		FIN_HIDDEN, FIN_TTL, FIN_BRANCH, FIN_MADDR, FIN_RECEIVED,
+		GEN_PARAM
+	};
+
+#define LOG(lev, fmt, args...) fprintf(stderr, fmt, ## args)
+
+
+/* entry state must be F_PARAM, or saved_state=F_PARAM and 
+ * state=F_{LF,CR,CRLF}!
+ * output state = L_PARAM or F_PARAM or END_OF_HEADER 
+ * (and saved_state= last state); everything else => error */
+__inline char* parse_via_param(char* p, int* pstate, int* psaved_state)
+{
+	char* tmp;
+	register int state;
+	int saved_state;
+	int param_type;
+	char* param_name;
+	char* param_value;
+	
+	state=*pstate;
+	saved_state=*psaved_state;
+	param_name=param_value=0;
+	param_type=0;
+	
+	for (tmp=p;*tmp;tmp++){
+		switch(*tmp){
+			case ' ':
+			case '\t':
+				switch(state){
+					case FIN_HIDDEN:
+						*tmp=0;
+						param_type=state;
+						state=L_PARAM;
+						goto endofparam;
+					case FIN_BRANCH:
+					case FIN_TTL:
+					case FIN_MADDR:
+					case FIN_RECEIVED:
+						*tmp=0;
+						param_type=state;
+						state=L_VALUE;
+						goto find_value;
+					case F_PARAM:
+						break;
+					case F_LF:
+					case F_CR:
+					case F_CRLF:
+						state=saved_state;
+						break;
+					case GEN_PARAM:
+					default:
+						*tmp=0;
+						param_type=GEN_PARAM;
+						state=L_VALUE;
+						goto find_value;
+				}
+				break;
+			/* \n and \r*/
+			case '\n':
+				switch(state){
+					case FIN_HIDDEN:
+						*tmp=0;
+						param_type=state;
+						saved_state=L_PARAM;
+						state=F_LF;
+						goto endofparam;
+					case FIN_BRANCH:
+					case FIN_TTL:
+					case FIN_MADDR:
+					case FIN_RECEIVED:
+						*tmp=0;
+						param_type=state;
+						saved_state=L_VALUE;
+						state=F_LF;
+						goto find_value;
+					case F_PARAM:
+						saved_state=state;
+						state=F_LF;
+						break;
+					case F_LF:
+					case F_CRLF:
+						state=END_OF_HEADER;
+						goto end;
+					case F_CR:
+						state=F_CRLF;
+						break;
+					case GEN_PARAM:
+					default:
+						*tmp=0;
+						param_type=GEN_PARAM;
+						saved_state=L_VALUE;
+						state=F_LF;
+						goto find_value;
+				}
+				break;
+			case '\r':
+				switch(state){
+					case FIN_HIDDEN:
+						*tmp=0;
+						param_type=state;
+						saved_state=L_PARAM;
+						state=F_CR;
+						goto endofparam;
+					case FIN_BRANCH:
+					case FIN_TTL:
+					case FIN_MADDR:
+					case FIN_RECEIVED:
+						*tmp=0;
+						param_type=state;
+						saved_state=L_VALUE;
+						state=F_CR;
+						goto find_value;
+					case F_PARAM:
+						saved_state=state;
+						state=F_CR;
+						break;
+					case F_CR:
+					case F_CRLF:
+						state=END_OF_HEADER;
+						goto end;
+					case GEN_PARAM:
+					default:
+						*tmp=0;
+						param_type=GEN_PARAM;
+						saved_state=L_VALUE;
+						state=F_CR;
+						goto find_value;
+				}
+				break;
+
+			case '=':
+				switch(state){
+					case FIN_BRANCH:
+					case FIN_TTL:
+					case FIN_MADDR:
+					case FIN_RECEIVED:
+						*tmp=0;
+						param_type=state;
+						state=F_VALUE;
+						goto find_value;
+					case F_PARAM:
+					case FIN_HIDDEN:
+						LOG(L_ERR, "ERROR: parse_via: invalid char <%c> in"
+								" state %d\n");
+						goto error;
+					case F_CR:
+					case F_LF:
+					case F_CRLF:
+						state=END_OF_HEADER;
+						goto end;
+					case GEN_PARAM:
+					default:
+						*tmp=0;
+						param_type=GEN_PARAM;
+						state=F_VALUE;
+						goto find_value;
+				}
+				break;
+			case ';':
+				switch(state){
+					case FIN_HIDDEN:
+						*tmp=0;
+						param_type=state;
+						state=F_PARAM;
+						goto endofparam;
+					case FIN_BRANCH:
+					case FIN_MADDR:
+					case FIN_TTL:
+					case FIN_RECEIVED:
+						LOG(L_ERR, "ERROR: parse_via: invalid char <%c> in"
+								" state %d\n");
+						goto error;
+					case F_CR:
+					case F_LF:
+					case F_CRLF:
+						state=END_OF_HEADER;
+						goto end;
+					case GEN_PARAM:
+					default:
+						*tmp=0;
+						param_type=GEN_PARAM;
+						state=F_PARAM;
+						goto endofparam;
+				}
+				break;
+				
+				/* param names */
+			case 'h':
+			case 'H':
+				switch(state){
+					case F_PARAM:
+						state=HIDDEN1;
+						param_name=tmp;
+						break;
+					case GEN_PARAM:
+						break;
+					case F_CR:
+					case F_LF:
+					case F_CRLF:
+						state=END_OF_HEADER;
+						goto end;
+					default:
+						state=GEN_PARAM;
+				}
+				break;
+			case 'i':
+			case 'I':
+				switch(state){
+					case HIDDEN1:
+						state=HIDDEN2;
+						break;
+					case RECEIVED4:
+						state=RECEIVED5;
+						break;
+					case GEN_PARAM:
+						break;
+					case F_CR:
+					case F_LF:
+					case F_CRLF:
+						state=END_OF_HEADER;
+						goto end;
+					default:
+						state=GEN_PARAM;
+				}
+				break;
+			case 'd':
+			case 'D':
+				switch(state){
+					case HIDDEN2:
+						state=HIDDEN3;
+						break;
+					case HIDDEN3:
+						state=HIDDEN4;
+						break;
+					case MADDR2:
+						state=MADDR3;
+						break;
+					case MADDR3:
+						state=MADDR4;
+						break;
+					case RECEIVED7:
+						state=FIN_RECEIVED;
+						break;
+					case GEN_PARAM:
+						break;
+					case F_CR:
+					case F_LF:
+					case F_CRLF:
+						state=END_OF_HEADER;
+						goto end;
+					default:
+						state=GEN_PARAM;
+				}
+				break;
+			case 'e':
+			case 'E':
+				switch(state){
+					case HIDDEN4:
+						state=HIDDEN5;
+						break;
+					case RECEIVED1:
+						state=RECEIVED2;
+						break;
+					case RECEIVED3:
+						state=RECEIVED4;
+						break;
+					case RECEIVED6:
+						state=RECEIVED7;
+						break;
+					case GEN_PARAM:
+						break;
+					case F_CR:
+					case F_LF:
+					case F_CRLF:
+						state=END_OF_HEADER;
+						goto end;
+					default:
+						state=GEN_PARAM;
+				}
+				break;
+			case 'n':
+			case 'N':
+				switch(state){
+					case HIDDEN5:
+						state=FIN_HIDDEN;
+						break;
+					case BRANCH3:
+						state=BRANCH4;
+						break;
+					case GEN_PARAM:
+						break;
+					case F_CR:
+					case F_LF:
+					case F_CRLF:
+						state=END_OF_HEADER;
+						goto end;
+					default:
+						state=GEN_PARAM;
+				}
+				break;
+			case 't':
+			case 'T':
+				switch(state){
+					case F_PARAM:
+						state=TTL1;
+						param_name=tmp;
+						break;
+					case TTL1:
+						state=TTL2;
+						break;
+					case GEN_PARAM:
+						break;
+					case F_CR:
+					case F_LF:
+					case F_CRLF:
+						state=END_OF_HEADER;
+						goto end;
+					default:
+						state=GEN_PARAM;
+				}
+				break;
+			case 'l':
+			case 'L':
+				switch(state){
+					case TTL2:
+						state=FIN_TTL;
+						break;
+					case GEN_PARAM:
+						break;
+					case F_CR:
+					case F_LF:
+					case F_CRLF:
+						state=END_OF_HEADER;
+						goto end;
+					default:
+						state=GEN_PARAM;
+				}
+				break;
+			case 'm':
+			case 'M':
+				switch(state){
+					case F_PARAM:
+						state=MADDR1;
+						param_name=tmp;
+						break;
+					case GEN_PARAM:
+						break;
+					case F_CR:
+					case F_LF:
+					case F_CRLF:
+						state=END_OF_HEADER;
+						goto end;
+					default:
+						state=GEN_PARAM;
+				}
+				break;
+			case 'a':
+			case 'A':
+				switch(state){
+					case MADDR1:
+						state=MADDR2;
+						break;
+					case BRANCH2:
+						state=BRANCH3;
+						break;
+					case GEN_PARAM:
+						break;
+					case F_CR:
+					case F_LF:
+					case F_CRLF:
+						state=END_OF_HEADER;
+						goto end;
+					default:
+						state=GEN_PARAM;
+				}
+				break;
+			case 'r':
+			case 'R':
+				switch(state){
+					case MADDR4:
+						state=FIN_MADDR;
+						break;
+					case F_PARAM:
+						state=RECEIVED1;
+						param_name=tmp;
+						break;
+					case BRANCH1:
+						state=BRANCH2;
+						break;
+					case GEN_PARAM:
+						break;
+					case F_CR:
+					case F_LF:
+					case F_CRLF:
+						state=END_OF_HEADER;
+						goto end;
+					default:
+						state=GEN_PARAM;
+				}
+				break;
+			case 'c':
+			case 'C':
+				switch(state){
+					case RECEIVED2:
+						state=RECEIVED3;
+						break;
+					case BRANCH4:
+						state=BRANCH5;
+						break;
+					case GEN_PARAM:
+						break;
+					case F_CR:
+					case F_LF:
+					case F_CRLF:
+						state=END_OF_HEADER;
+						goto end;
+					default:
+						state=GEN_PARAM;
+				}
+				break;
+			case 'v':
+			case 'V':
+				switch(state){
+					case RECEIVED5:
+						state=RECEIVED6;
+						break;
+					case GEN_PARAM:
+						break;
+					case F_CR:
+					case F_LF:
+					case F_CRLF:
+						state=END_OF_HEADER;
+						goto end;
+					default:
+						state=GEN_PARAM;
+				}
+				break;
+			case 'b':
+			case 'B':
+				switch(state){
+					case F_PARAM:
+						state=BRANCH1;
+						param_name=tmp;
+						break;
+					case GEN_PARAM:
+						break;
+					case F_CR:
+					case F_LF:
+					case F_CRLF:
+						state=END_OF_HEADER;
+						goto end;
+					default:
+						state=GEN_PARAM;
+				}
+				break;
+
+			default:
+				switch(state){
+					case F_PARAM:
+						state=GEN_PARAM;
+						param_name=tmp;
+						break;
+					case  GEN_PARAM:
+						break;
+					case F_CR:
+					case F_LF:
+					case F_CRLF:
+						state=END_OF_HEADER;
+						goto end;
+					default:
+						state=GEN_PARAM;
+				}
+		}
+	}/* for tmp*/
+
+/* end of packet?*/
+saved_state=state;
+param_type=state;
+state=END_OF_HEADER;
+goto end;
+
+find_value:
+	tmp++;
+	for(tmp;*tmp;tmp++){
+		switch(*tmp){
+			case ' ':
+			case '\t':
+				switch(state){
+					case L_VALUE:
+					case F_VALUE: /*eat space*/
+						break; 
+					case P_VALUE:
+						*tmp=0;
+						state=L_PARAM;
+						goto endofvalue;
+					case P_STRING:
+						break;
+					case F_CR:
+					case F_LF:
+					case F_CRLF:
+						state=saved_state;
+						break;
+					default:
+						LOG(L_ERR, "ERROR: parse_via: invalid char <%c>"
+								" in state %d\n", state);
+						goto error;
+				}
+				break;
+			case '\n':
+				switch(state){
+					case L_VALUE:
+					case F_VALUE: /*eat space*/
+					case P_STRING:
+						saved_state=state;
+						state=F_LF;
+						break; 
+					case P_VALUE:
+						*tmp=0;
+						saved_state=L_PARAM;
+						state=F_LF;
+						goto endofvalue;
+					case F_LF:
+					case F_CRLF:
+						state=END_OF_HEADER;
+						goto end;
+					case F_CR:
+						state=F_CRLF;
+						break;
+					default:
+						LOG(L_ERR, "ERROR: parse_via: invalid char <%c>"
+								" in state %d\n", state);
+						goto error;
+				}
+				break;
+			case '\r':
+				switch(state){
+					case L_VALUE:
+					case F_VALUE: /*eat space*/
+					case P_STRING:
+						saved_state=state;
+						state=F_CR;
+						break; 
+					case P_VALUE:
+						*tmp=0;
+						saved_state=L_PARAM;
+						state=F_CR;
+						goto endofvalue;
+					case F_LF:
+					case F_CR:
+					case F_CRLF:
+						state=END_OF_HEADER;
+						goto end;
+					default:
+						LOG(L_ERR, "ERROR: parse_via: invalid char <%c>"
+								" in state %d\n", state);
+						goto error;
+				}
+				break;
+
+			case '=':
+				switch(state){
+					case L_VALUE:
+						state=F_VALUE;
+						break;
+					case P_STRING:
+						break;
+					case F_LF:
+					case F_CR:
+					case F_CRLF:
+						state=END_OF_HEADER;
+						goto end;
+					default:
+						LOG(L_ERR, "ERROR: parse_via: invalid char <%c>"
+								" in state %d\n", state);
+						goto error;
+				}
+				break;
+			case ';':
+				switch(state){
+					case P_VALUE:
+						*tmp=0;
+						state=F_PARAM;
+						goto endofvalue;
+					case P_STRING:
+						break; /* what to do? */
+					case F_LF:
+					case F_CR:
+					case F_CRLF:
+						state=END_OF_HEADER;
+						goto end;
+					default:
+						LOG(L_ERR, "ERROR: parse_via: invalid char <%c>"
+								" in state %d\n", state);
+						goto error;
+				}
+				break;
+			
+			case '"':
+				switch(state){
+					case F_VALUE:
+						state=P_STRING;
+						param_value=tmp+1;
+						break;
+					case P_STRING:
+						*tmp=0;
+						state=L_PARAM;
+						goto endofvalue;
+					case F_LF:
+					case F_CR:
+					case F_CRLF:
+						state=END_OF_HEADER;
+						goto end;
+					default:
+						LOG(L_ERR, "ERROR: parse_via: invalid char <%c>"
+								" in state %d\n", state);
+						goto error;
+				}
+				break;
+			default:
+				switch(state){
+					case F_VALUE:
+						state=P_VALUE;
+						param_value=tmp;
+						break;
+					case P_VALUE:
+					case P_STRING:
+						break;
+					case F_LF:
+					case F_CR:
+					case F_CRLF:
+						state=END_OF_HEADER;
+						goto end;
+					default:
+						LOG(L_ERR, "ERROR: parse_via: invalid char <%c>"
+								" in state %d\n", state);
+						goto error;
+				}
+		}
+	} /* for2 tmp*/
+
+	/* if generic_param => it can have no value */
+	if ((state==L_VALUE)&&(param_type==GEN_PARAM)) state=L_PARAM;
+	saved_state=state;
+	state=END_OF_HEADER;
+	goto end;
+
+endofparam:
+endofvalue:
+	printf("end, tmp=%x, <%c>\n", tmp, *tmp);
+	//tmp++;
+end:
+	*pstate=state;
+	*psaved_state=saved_state;
+	printf("Found param type %d, <%s> = <%s>\n", param_type, param_name,
+			param_value);
+	return tmp;
+
+error:
+	fprintf(stderr,"error: via_parse_param\n");
+	*pstate=state;
+	*psaved_state=saved_state;
+	return tmp;
+}
+
+
+
+
+
+
+int main(int argc, char** argv)
+{
+
+	char* tmp;
+	int state;
+	int saved_state;
+	int c_nest;
+	int i;
+	int port;
+	char* host;
+	char* port_str;
+	char* param;
+	char* comment;
+	char* next_via;
+	char *proto; /* in fact transport*/
+
+	host=port_str=param=comment=next_via=proto=0;
+
+	printf(" %s (%d)\n", argv[0], argc);
+	if (argc<2){
+			fprintf(stderr, " no parameters\n");
+			exit(-1);
+	}
+	
+	/* parse start of via ( SIP/2.0/UDP    )*/
+	state=F_SIP;
+	for(tmp=argv[1];*tmp;tmp++){
+		switch(*tmp){
+			case ' ':
+			case'\t':
+				switch(state){
+					case L_VER: /* eat space */
+					case L_PROTO:
+					case F_SIP:
+					case F_VER:
+					case F_PROTO:
+						break;
+					case P_PROTO:
+						*tmp=0;  /* finished proto parsing */
+						state=F_HOST; /* start looking for host*/
+						goto main_via;
+					case FIN_SIP:
+						*tmp=0;
+						state=L_VER;
+						break;
+					case FIN_VER:
+						*tmp=0;
+						state=L_PROTO;
+						break;
+					case F_LF:
+					case F_CRLF:
+					case F_CR: /* header continues on this line */
+						state=saved_state;
+						break;
+					default:
+						LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
+								" state %d\n", *tmp, state);
+						goto error;
+				}
+				break;
+			case '\n':
+				switch(state){
+					case L_VER:
+					case F_SIP:
+					case F_VER:
+					case F_PROTO:
+					case L_PROTO:
+						saved_state=state;
+						state=F_LF;
+						break;
+					case P_PROTO:
+						*tmp=0;
+						state=F_LF;
+						saved_state=F_HOST; /* start looking for host*/
+						goto main_via;
+					case FIN_SIP:
+						*tmp=0;
+						state=F_LF;
+						saved_state=L_VER;
+						break;
+					case FIN_VER:
+						*tmp=0;
+						state=F_LF;
+						saved_state=L_PROTO;
+						break;
+					case F_CR:
+						state=F_CRLF;
+						break;
+					case F_LF:
+					case F_CRLF:
+						state=saved_state;
+						goto endofheader;
+					default:
+						LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
+								" state %d\n", *tmp, state);
+						goto error;
+				}
+				break;
+			case '\r':
+				switch(state){
+					case L_VER:
+					case F_SIP:
+					case F_VER:
+					case F_PROTO:
+					case L_PROTO:
+						saved_state=state;
+						state=F_CR;
+						break;
+					case P_PROTO:
+						*tmp=0;
+						state=F_CR;
+						saved_state=F_HOST;
+						goto main_via;
+					case FIN_SIP:
+						*tmp=0;
+						state=F_CR;
+						saved_state=L_VER;
+						break;
+					case FIN_VER:
+						*tmp=0;
+						state=F_CR;
+						saved_state=L_PROTO;
+						break;
+					case F_LF: /*end of line ?next header?*/
+					case F_CR:
+					case F_CRLF:
+						state=saved_state;
+						goto endofheader;
+					default:
+						LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
+								" state %d\n", *tmp, state);
+						goto error;
+				}
+				break;
+			
+			case '/':
+				switch(state){
+					case FIN_SIP:
+						*tmp=0;
+						state=F_VER;
+						break;
+					case FIN_VER:
+						*tmp=0;
+						state=F_PROTO;
+						break;
+					case L_VER:
+						state=F_VER;
+						break;
+					case L_PROTO:
+						state=F_PROTO;
+						break;
+					default:
+						LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
+								" state %d\n", *tmp, state);
+						goto error;
+				}
+				break;
+				/* match SIP*/
+			case 'S':
+			case 's':
+				switch(state){
+					case F_SIP:
+						state=SIP1;
+						break;
+					/* allow S in PROTO */
+					case F_PROTO:
+						proto=tmp;
+						state=P_PROTO;
+						break;
+					case P_PROTO:
+						break;
+					default:
+						LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
+								" state %d\n", *tmp, state);
+						goto error;
+				}
+				break;
+			case 'I':
+			case 'i':
+				switch(state){
+					case SIP1:
+						state=SIP2;
+						break;
+					/* allow i in PROTO */
+					case F_PROTO:
+						proto=tmp;
+						state=P_PROTO;
+						break;
+					case P_PROTO:
+						break;
+					default:
+						LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
+								" state %d\n", *tmp, state);
+						goto error;
+				}
+				break;
+			case 'p':
+			case 'P':
+				switch(state){
+					case SIP2:
+						state=FIN_SIP;
+						break;
+					/* allow p in PROTO */
+					case F_PROTO:
+						proto=tmp;
+						state=P_PROTO;
+						break;
+					case P_PROTO:
+						break;
+					default:
+						LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
+								" state %d\n", *tmp, state);
+						goto error;
+				}
+				break;
+			/*match 2.0*/
+			case '2':
+				switch(state){
+					case F_VER:
+						state=VER1;
+						break;
+					/* allow 2 in PROTO*/
+					case F_PROTO:
+						proto=tmp;
+						state=P_PROTO;
+						break;
+					case P_PROTO:
+						break;
+					default:
+						LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
+								" state %d\n", *tmp, state);
+						goto error;
+				}
+				break;
+			case '.':
+				switch(state){
+					case VER1:
+						state=VER2;
+						break;
+					/* allow . in PROTO */
+					case F_PROTO:
+						proto=tmp;
+						state=P_PROTO;
+						break;
+					case P_PROTO:
+						break;
+					default:
+						LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
+								" state %d\n", *tmp, state);
+						goto error;
+				}
+				 break;
+			case '0':
+				switch(state){
+					case VER2:
+						state=FIN_VER;
+						break;
+					/* allow 0 in PROTO*/
+					case F_PROTO:
+						proto=tmp;
+						state=P_PROTO;
+						break;
+					case P_PROTO:
+						break;
+					default:
+						LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
+								" state %d\n", *tmp, state);
+						goto error;
+				}
+				break;
+			
+			default:
+				switch(state){
+					case F_PROTO:
+						proto=tmp;
+						state=P_PROTO;
+						break;
+					case P_PROTO:
+						break;
+					default:
+						LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
+								" state %d\n", *tmp, state);
+						goto error;
+				}
+				break;
+		}
+	} /* for tmp*/
+
+/* we should not be here! if everything is ok > main_via*/
+	LOG(L_ERR, "ERROR: parse_via: bad via: end of packet on state=%d\n",
+			state);
+	goto error;
+
+main_via:
+/* inc tmp to point to the next char*/
+	tmp++;
+	c_nest=0;
+	/*state should always be F_HOST here*/;
+	for(;*tmp;tmp++){
+		switch(*tmp){
+			case ' ':
+			case '\t':
+				switch(state){
+					case F_HOST:/*eat the spaces*/
+						break;
+					case P_HOST:
+						 *tmp=0;/*mark end of host*/
+						 state=L_PORT;
+						 break;
+					case L_PORT: /*eat the spaces*/
+					case F_PORT:
+						break;
+					case P_PORT:
+						*tmp=0; /*end of port */
+						state=L_PARAM;
+						break;
+					case L_PARAM: /* eat the space */
+					case F_PARAM:
+						break;
+					case P_PARAM:
+					/*	*tmp=0;*/ /*!?end of param*/
+						state=L_PARAM;
+						break;
+					case L_VIA:
+					case F_VIA: /* eat the space */
+						break;
+					case F_COMMENT:
+					case P_COMMENT:
+						break;
+					case F_IP6HOST: /*eat the spaces*/
+						break;
+					case P_IP6HOST:
+						*tmp=0; /*mark end of host*/
+						state=L_PORT; 
+						break;
+					case F_CRLF:
+					case F_LF:
+					case F_CR:
+						/*previous=crlf and now =' '*/
+						state=saved_state;
+						break;
+					default:
+						LOG(L_CRIT,"BUG: parse_via"
+							" on <%c>, state=%d\n",*tmp, state);
+						goto  error;
+				}
+			break;
+			case '\n':
+				switch(state){
+					case F_HOST:/*eat the spaces*/
+					case L_PORT: /*eat the spaces*/
+					case F_PORT:
+					case L_PARAM: /* eat the space */
+					case F_PARAM:
+					case F_VIA: /* eat the space */
+					case L_VIA:
+					case F_COMMENT:
+					case P_COMMENT:
+					case F_IP6HOST:
+					case P_IP6HOST:
+						saved_state=state;
+						state=F_LF;
+						break;
+					case P_HOST:
+						 *tmp=0;/*mark end of host*/
+						 saved_state=L_PORT;
+						 state=F_LF;
+						 break;
+					case P_PORT:
+						*tmp=0; /*end of port */
+						saved_state=L_PARAM;
+						state=F_LF;
+						break;
+					case P_PARAM:
+					/*	*tmp=0;*/ /*!?end of param*/
+						saved_state=L_PARAM;
+						state=F_LF;
+						break;
+					case F_CR:
+						state=F_CRLF;
+						break;
+					case F_CRLF:
+					case F_LF:
+						state=saved_state;
+						goto endofheader;
+					default:
+						LOG(L_CRIT,"BUG: parse_via"
+							" on <%c>\n",*tmp);
+						goto  error;
+				}
+			break;
+		case '\r':
+				switch(state){
+					case F_HOST:/*eat the spaces*/
+					case L_PORT: /*eat the spaces*/
+					case F_PORT:
+					case L_PARAM: /* eat the space */
+					case F_PARAM:
+					case F_VIA: /* eat the space */
+					case L_VIA:
+					case F_COMMENT:
+					case P_COMMENT:
+					case F_IP6HOST:
+					case P_IP6HOST:
+						saved_state=state;
+						state=F_CR;
+						break;
+					case P_HOST:
+						 *tmp=0;/*mark end of host*/
+						 saved_state=L_PORT;
+						 state=F_CR;
+						 break;
+					case P_PORT:
+						*tmp=0; /*end of port */
+						saved_state=L_PARAM;
+						state=F_CR;
+						break;
+					case P_PARAM:
+					/*	*tmp=0;*/ /*!?end of param*/
+						saved_state=L_PARAM;
+						state=F_CR;
+						break;
+					case F_CRLF:
+					case F_CR:
+					case F_LF:
+						state=saved_state;
+						goto endofheader;
+					default:
+						LOG(L_CRIT,"BUG: parse_via"
+							" on <%c>\n",*tmp);
+						goto  error;
+				}
+			break;
+			
+			case ':':
+				switch(state){
+					case F_HOST:
+					case F_IP6HOST:
+						LOG(L_ERR,"ERROR:parse_via:"
+							" no host found\n");
+						goto error;
+					case P_IP6HOST:
+						LOG(L_ERR, "ERROR:parse_via: bad ipv6 reference\n");
+						goto error;
+					case P_HOST:
+						*tmp=0; /*mark  end of host*/
+						state=F_PORT;
+						break;
+					case L_PORT:
+						state=F_PORT;
+						break;
+					case P_PORT:
+						LOG(L_ERR, "ERROR:parse_via:"
+							" bad port\n");
+						goto error;
+					case L_PARAM:
+					case F_PARAM:
+					case P_PARAM:
+						LOG(L_ERR, "ERROR:parse_via:"
+						" bad char <%c> in state %d\n",
+							*tmp,state);
+						goto error;
+					case L_VIA:
+					case F_VIA:
+						LOG(L_ERR, "ERROR:parse_via:"
+						" bad char in compact via\n");
+						goto error;
+					case F_CRLF:
+					case F_LF:
+					case F_CR:
+						/*previous=crlf and now !=' '*/
+						goto endofheader;
+					case F_COMMENT:/*everything is allowed in a comment*/
+						comment=tmp;
+						state=P_COMMENT;
+						break;
+					case P_COMMENT: /*everything is allowed in a comment*/
+						break;
+					default:
+						LOG(L_CRIT,"BUG: parse_via"
+							" on <%c> state %d\n",
+							*tmp, state);
+						goto error;
+				}
+				break;
+			case ';':
+				switch(state){
+					case F_HOST:
+					case F_IP6HOST:
+						LOG(L_ERR,"ERROR:parse_via:"
+							" no host found\n");
+						goto error;
+					case P_IP6HOST:
+						LOG(L_ERR, "ERROR:parse_via: bad ipv6 reference\n");
+						goto error;
+					case P_HOST:
+					case P_PORT:
+						*tmp=0; /*mark the end*/
+					case L_PORT:
+					case L_PARAM:
+						state=F_PARAM;
+						break;
+					case F_PORT:
+						LOG(L_ERR, "ERROR:parse_via:"
+						" bad char <%c> in state %d\n",
+							*tmp,state);
+						goto error;
+					case F_PARAM:
+						LOG(L_ERR,  "ERROR:parse_via:"
+							" null param?\n");
+						goto error;
+					case P_PARAM:
+						/*hmm next, param?*/
+						state=F_PARAM;
+						break;
+					case L_VIA:
+					case F_VIA:
+						LOG(L_ERR, "ERROR:parse_via:"
+						" bad char <%c> in next via\n",
+							*tmp);
+						goto error;
+					case F_CRLF:
+					case F_LF:
+					case F_CR:
+						/*previous=crlf and now !=' '*/
+						goto endofheader;
+					case F_COMMENT:/*everything is allowed in a comment*/
+						comment=tmp;
+						state=P_COMMENT;
+						break;
+					case P_COMMENT: /*everything is allowed in a comment*/
+						break;
+					
+					default:
+						LOG(L_CRIT,"BUG: parse_via"
+							" on <%c> state %d\n",
+							*tmp, state);
+						goto  error;
+				}
+			break;
+			case ',':
+				switch(state){
+					case F_HOST:
+					case F_IP6HOST:
+						LOG(L_ERR,"ERROR:parse_via:"
+							" no host found\n");
+						goto error;
+					case P_IP6HOST:
+						LOG(L_ERR, "ERROR:parse_via: bad ipv6 reference\n");
+						goto error;
+					case P_HOST:
+					case P_PORT:
+						*tmp=0; /*mark the end*/
+					case L_PORT:
+					case L_PARAM:
+					case P_PARAM:
+					case L_VIA:
+						state=F_VIA;
+						break;
+					case F_PORT:
+					case F_PARAM:
+						LOG(L_ERR, "ERROR:parse_via:"
+						" invalid char <%c> in state"
+						" %d\n", *tmp,state);
+						goto error;
+					case F_VIA:
+						/* do  nothing,  eat ","*/
+						break;	
+					case F_CRLF:
+					case F_LF:
+					case F_CR:
+						/*previous=crlf and now !=' '*/
+						goto endofheader;
+					case F_COMMENT:/*everything is allowed in a comment*/
+						comment=tmp;
+						state=P_COMMENT;
+						break;
+					case P_COMMENT: /*everything is allowed in a comment*/
+						break;
+					default:
+						LOG(L_CRIT,"BUG: parse_via"
+							" on <%c> state %d\n",
+							*tmp, state);
+						goto  error;
+				}
+			break;
+			case '(':
+				switch(state){
+					case F_HOST:
+					case F_PORT:
+					case F_PARAM:
+					case F_VIA:
+					case F_IP6HOST:
+					case P_IP6HOST: /*must be terminated in ']'*/
+						LOG(_ERR,"ERROR:parse_via"
+							" on <%c> state %d\n",
+							*tmp, state);
+						goto  error;
+					case P_HOST:
+					case P_PORT:
+					case P_PARAM:
+						*tmp=0; /*mark the end*/
+					case L_PORT:
+					case L_PARAM:
+					case L_VIA:
+						state=F_COMMENT;
+						c_nest++;
+						printf("found '(', state=%d, c_nest=%d\n",
+								state, c_nest);
+						*tmp=0;
+						break;
+					case P_COMMENT:
+					case F_COMMENT:
+						c_nest++;
+						break;
+					case F_CRLF:
+					case F_LF:
+					case F_CR:
+						/*previous=crlf and now !=' '*/
+						goto endofheader;
+					default:
+						LOG(L_CRIT,"BUG: parse_via"
+							" on <%c> state %d\n",
+							*tmp, state);
+						goto  error;
+				}
+			break;
+			case ')':
+				switch(state){
+					case F_COMMENT:
+					case P_COMMENT:
+						if (c_nest){
+							c_nest--;
+							if(c_nest==0){
+								state=L_VIA;
+								*tmp=0;
+								printf("out of comment\n");
+								break;
+							}
+						}else{
+							LOG(L_ERR,"ERROR:"
+							    "parse_via: "
+							    "missing '(' - "
+							    "nesting = %d\n",
+							    c_nest);
+							 goto error;
+						}
+						break;
+					case F_HOST:
+					case F_PORT:
+					case F_PARAM:
+					case F_VIA:
+					case P_HOST:
+					case P_PORT:
+					case P_PARAM:
+					case L_PORT:
+					case L_PARAM:
+					case L_VIA:
+					case F_IP6HOST:
+					case P_IP6HOST:
+						LOG(L_ERR,"ERROR:parse_via"
+							" on <%c> state %d\n",
+							*tmp, state);
+						goto  error;
+					case F_CRLF:
+					case F_LF:
+					case F_CR:
+						/*previous=crlf and now !=' '*/
+						goto endofheader;
+					default:
+						LOG(L_CRIT,"BUG: parse_via"
+							" on <%c> state %d\n",
+							*tmp, state);
+						goto  error;
+				}
+				break;
+			case '[':
+				switch(state){
+					case F_HOST:
+						state=F_IP6HOST;
+						break;
+					case F_COMMENT:/*everything is allowed in a comment*/
+						comment=tmp;
+						state=P_COMMENT;
+						break;
+					case P_COMMENT:
+						break;
+					case F_CRLF:
+					case F_LF:
+					case F_CR:
+						/*previous=crlf and now !=' '*/
+						goto endofheader;
+					default:
+						LOG(L_ERR,"ERROR:parse_via"
+							" on <%c> state %d\n",
+							*tmp, state);
+						goto  error;
+				}
+				break;
+			case ']':
+				switch(state){
+					case P_IP6HOST:
+						*tmp=0; /*mark the end*/
+						state=L_PORT;
+						break;
+					case F_CRLF:
+					case F_LF:
+					case F_CR:
+						/*previous=crlf and now !=' '*/
+						goto endofheader;
+					case F_COMMENT:/*everything is allowed in a comment*/
+						comment=tmp;
+						state=P_COMMENT;
+						break;
+					case P_COMMENT:
+						break;
+					default:
+						LOG(L_ERR,"ERROR:parse_via"
+							" on <%c> state %d\n",
+							*tmp, state);
+						goto  error;
+				}
+				break;
+						
+			default:
+				switch(state){
+					case F_HOST:
+						state=P_HOST;
+						host=tmp;
+						break;
+					case P_HOST:
+						break;
+					case F_PORT:
+						state=P_PORT;
+						port_str=tmp;
+						break;
+					case P_PORT:
+						/*check if number?*/
+						break;
+					case F_PARAM:
+						/*state=P_PARAM*/;
+						param=tmp;
+						tmp=parse_via_param(tmp, &state, &saved_state);
+						switch(state){
+							case L_PARAM:
+							case F_PARAM:
+							case F_LF:
+							case F_CR:
+								break;
+							case END_OF_HEADER:
+								state=saved_state;
+								goto endofheader;
+							default:
+								LOG(L_ERR, "ERROR: parse_via after"
+										" parse_via_param: invalid"
+										" char <%c> on state %d\n",
+										*tmp, state);
+								goto error;
+						}
+						break;
+					case P_PARAM:
+						break;
+					case F_VIA:
+						next_via=tmp;
+						printf("found new via on <%c>\n", *tmp);
+						goto nextvia;
+					case L_PORT:
+					case L_PARAM:
+					case L_VIA:
+						LOG(L_ERR,"ERROR:parse_via"
+							" on <%c> state %d (default)\n",
+							*tmp, state);
+						goto  error;
+					case F_COMMENT:
+						printf("starting comment parsing on %c \n",*tmp);
+						state=P_COMMENT;
+						comment=tmp;
+						break;
+					case P_COMMENT:
+						break;
+					case F_IP6HOST:
+						state=P_IP6HOST;
+						host=tmp;
+						break;
+					case P_IP6HOST:
+						break;
+					case F_CRLF:
+					case F_LF:
+					case F_CR:
+						/*previous=crlf and now !=' '*/
+						goto endofheader;
+					default:
+						LOG(L_ERR, "BUG:parse_via:"
+							" invalid char <%c>"
+							" in state %d\n",
+							*tmp, state);
+						goto error;
+				}
+				
+					
+		}			
+	}
+
+	printf("end of packet reached, state=%d\n", state);
+	goto endofpacket; /*end of packet, probably should be goto error*/
+	
+endofheader:
+	state=saved_state;
+	printf("end of header reached, state=%d\n", state);
+endofpacket:
+	/* check if error*/
+	switch(state){
+		case P_HOST:
+		case L_PORT:
+		case P_PORT:
+		case L_PARAM:
+		case P_PARAM:
+		case P_VALUE:
+		case GEN_PARAM:
+		case FIN_HIDDEN:
+		case L_VIA:
+			break;
+		default:
+			LOG(L_ERR, "ERROR: parse_via: invalid via - end of header in"
+					" state %d\n", state);
+			goto error;
+	}
+		
+nextvia:
+	if (proto) printf("<SIP/2.0/%s>\n", proto);
+	if (host) printf("host= <%s>\n", host);
+	if (port_str) printf("port= <%s>\n", port_str);
+	if (param) printf("params= <%s>\n", param);
+	if (comment) printf("comment= <%s>\n", comment);
+	if(next_via) printf("next_via= <%s>\n", next_via);
+	printf("rest=<%s>\n", tmp);
+	
+	exit(0);
+
+error:
+	fprintf(stderr, "via parse error\n");
+	exit(-1);
+}
+
diff --git a/test/xx.cfg b/test/xx.cfg
new file mode 100644
index 0000000..7013c72
--- /dev/null
+++ b/test/xx.cfg
@@ -0,0 +1,61 @@
+# forwarding to Cisco phone
+#
+#
+
+
+debug=9          # debug level (cmd line: -dddddddddd)
+log_stderror=yes # (cmd line: -E)
+check_via=yes     # (cmd. line: -v)
+dns=on           # (cmd. line: -r)
+rev_dns=yes      # (cmd. line: -R)
+fork=yes
+children=4
+#fork=no          # (cmd. line: -D)
+port=5080
+#listen=127.0.0.1
+listen=192.168.99.100
+loop_checks=1
+# for more info: sip_router -h
+
+#modules
+loadmodule "modules/print/print.so"
+#loadmodule "modules/tm/tm.so"
+
+
+route[0]{
+	if ( t_lookup_request()) {
+		if ( method=="ACK" )	{
+			t_release();
+#			forward(195.37.77.100, 5090 );
+#			forward(195.37.78.146, 5060 );
+# once it supports ACK too
+#			t_forward(195.37.77.100, 5090 );
+			t_forward("195.37.78.146", "5060" );
+		} else {
+			t_retransmit_reply();
+		};
+		t_unref();
+	} else {
+		if (method=="ACK") {
+#			forward(195.37.77.100, 5090 );
+			forward(195.37.78.146, 5060 );
+		} else {
+			t_add_transaction();
+			if (method=="CANCEL") {
+				t_send_reply( "200", "glad to cancel");
+			} else {
+				t_send_reply("100", "trying -- your call is important to us");
+			};
+#			t_forward("195.37.77.100", "5090" );
+			t_forward("195.37.78.146", "5060" );
+			break;
+			t_unref();
+		};
+	};
+		
+}
+
+#route[0] {
+#	forward(195.37.78.146, 5060);
+#	drop;
+#}
diff --git a/test/xy.cfg b/test/xy.cfg
new file mode 100644
index 0000000..c6a77f4
--- /dev/null
+++ b/test/xy.cfg
@@ -0,0 +1,50 @@
+# forwarding to a fixed non-responding destination
+#
+#
+
+debug=9          # debug level (cmd line: -dddddddddd)
+log_stderror=yes # (cmd line: -E)
+check_via=yes     # (cmd. line: -v)
+dns=on           # (cmd. line: -r)
+rev_dns=yes      # (cmd. line: -R)
+fork=no          # (cmd. line: -D)
+port=5080
+#listen=127.0.0.1
+listen=192.168.99.100
+loop_checks=1
+# for more info: sip_router -h
+
+#modules
+loadmodule "modules/print/print.so"
+#loadmodule "modules/tm/tm.so"
+
+route{
+	if ( t_lookup_request()) {
+		if ( method=="ACK" )	{
+			t_release();
+#			forward(195.37.77.100, 5090 );
+			forward(195.37.78.146, 5030 );
+# once it supports ACK too
+#			t_forward(195.37.77.100, 5090 );
+		} else {
+			t_retransmit_reply();
+		};
+		t_unref();
+	} else {
+		if (method=="ACK") {
+#			forward(195.37.77.100, 5090 );
+			forward(195.37.78.146, 5030 );
+		} else {
+			t_add_transaction();
+			if (method=="CANCEL") {
+				t_send_reply( "200", "glad to cancel");
+			} else {
+				t_send_reply("100", "trying -- your call is important to us");
+			};
+#			t_forward("195.37.77.100", "5090" );
+			t_forward("195.37.78.146", "5030" );
+			t_unref();
+		};
+	};
+		
+}
diff --git a/timer.c b/timer.c
index 786db49..d5e9e72 100644
--- a/timer.c
+++ b/timer.c
@@ -1,16 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -19,23 +17,10 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/* History:
- * --------
- *  2003-03-19  replaced all the mallocs/frees w/ pkg_malloc/pkg_free (andrei)
- *  2003-03-29  cleaning pkg_mallocs introduced (jiri)
- *  2005-07-27  complete re-design/re-implementation (andrei)
- *  2005-12-12  workaround & bug reporting for timer_del(self) called from
- *              a timer handle; added timer_allow_del()  (andrei)
- *  2007-05-26  workaround for darwin sigwait() bug, see slow_timer_main() or
- *              grep __OS_darwin for more info (andrei)
- *  2007-07-01  timer_del() returns <0 if the timer is not active or 
- *               cannot be deleted (andrei)
- */
-
 
 /**
  * @file
- * @brief SIP-router core :: 
+ * @brief Kamailio core :: Timer
  * @ingroup core
  * Module: @ref core
  */
@@ -267,7 +252,7 @@ int init_timer()
 		goto error;
 	}
 	last_time=start_time;
-	DBG("init_timer: starting with *ticks=%u\n", (unsigned) *ticks);
+	LM_DBG("starting with *ticks=%u\n", (unsigned) *ticks);
 	
 	/* init timer structures */
 	for (r=0; r<H0_ENTRIES; r++)
@@ -308,7 +293,7 @@ int init_timer()
 	
 #endif
 	
-	DBG("init_timer: timer_list between %p and %p\n",
+	LM_DBG("timer_list between %p and %p\n",
 			&timer_lst->h0[0], &timer_lst->h2[H2_ENTRIES]);
 	return 0;
 error:
@@ -450,13 +435,13 @@ inline static void adjust_ticks(void)
 #ifndef TIMER_DEBUG
 					if (delta > 2*(s_ticks_t)TIMER_MAX_DRIFT+1)
 #endif
-						DBG("adjusting timer ticks (%lu) with %ld ms"
+						LM_DBG("adjusting timer ticks (%lu) with %ld ms"
 								" (%ld ticks)\n",
 								(unsigned long)*ticks,
 							(long)(delta*1000)/TIMER_TICKS_HZ, (long)delta);
 					*ticks+=(ticks_t)delta;
 				}else{
-					/*DBG("incredible, but our timer is in sync with"
+					/*LM_DBG("incredible, but our timer is in sync with"
 							" real time (%lu)\n", (unsigned long)*ticks);
 					*/
 				}
@@ -585,7 +570,7 @@ int timer_add_safe(struct timer_ln* tl, ticks_t delta)
 					tl->del_calls, tl->del_func, tl->del_file, tl->del_line,
 					tl->init, tl->expires_no);
 #else
-		DBG("timer_add called on an active timer %p (%p, %p),"
+		LM_DBG("timer_add called on an active timer %p (%p, %p),"
 					" flags %x\n", tl, tl->next, tl->prev, tl->flags);
 #endif
 		ret=-1; /* refusing to add active or non-reinit. timer */
@@ -644,7 +629,7 @@ again:
 					tl->init, tl->expires_no);
 #else
 /*
-		DBG("timer_del called on an inactive timer %p (%p, %p),"
+		LM_DBG("called on an inactive timer %p (%p, %p),"
 					" flags %x\n", tl, tl->next, tl->prev, tl->flags);
 */
 #endif
@@ -710,7 +695,7 @@ again:
 						tl->init, tl->expires_no);
 #else
 /*
-				DBG("timer_del: (s) timer %p (%p, %p) flags %x "
+				LM_DBG("(s) timer %p (%p, %p) flags %x "
 							"already detached\n",
 							tl, tl->next, tl->prev, tl->flags);
 */
@@ -780,7 +765,7 @@ again:
 						tl->init, tl->expires_no);
 #else
 /*
-				DBG("timer_del: (f) timer %p (%p, %p) flags %x "
+				LM_DBG("(f) timer %p (%p, %p) flags %x "
 							"already detached\n",
 							tl, tl->next, tl->prev, tl->flags);
 */
@@ -843,7 +828,7 @@ inline static void timer_list_expire(ticks_t t, struct timer_head* h
 	first=h->next;
 #endif
 	
-	/*DBG("timer_list_expire @ ticks = %lu, list =%p\n",
+	/*LM_DBG("@ ticks = %lu, list =%p\n",
 			(unsigned long) *ticks, h);
 	*/
 	while(h->next!=(struct timer_ln*)h){
@@ -929,7 +914,7 @@ static void timer_handler(void)
 	i=(slow_idx_t)(*t_idx%SLOW_LISTS_NO);
 #endif
 	
-	/*DBG("timer_handler: called, ticks=%lu, prev_ticks=%lu\n",
+	/*LM_DBG("called, ticks=%lu, prev_ticks=%lu\n",
 			(unsigned long)*ticks, (unsigned long)prev_ticks);
 	*/
 	run_timer=0; /* reset run_timer */
@@ -1004,7 +989,7 @@ static ticks_t compat_old_handler(ticks_t ti, struct timer_ln* tl,
 	struct sr_timer* t;
 	
 #ifdef TIMER_DEBUG
-	DBG("timer: compat_old_handler: calling, ticks=%u/%u, tl=%p, t=%p\n",
+	LM_DBG("calling, ticks=%u/%u, tl=%p, t=%p\n",
 			prev_ticks, (unsigned)*ticks, tl, data);
 #endif
 	t=(struct sr_timer*)data;
diff --git a/timer.h b/timer.h
index 6ac174d..36a3171 100644
--- a/timer.h
+++ b/timer.h
@@ -1,19 +1,16 @@
 /*
- * $Id$
- *
- *
  * timer related functions (public interface)
  *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -22,14 +19,9 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/* History:
- * --------
- *  2005-07-27  complete re-design/re-implementation (andrei)
- */
-
 /**
  * @file
- * @brief SIP-router core :: timer related functions (public interface)
+ * @brief Kamailio core :: timer related functions (public interface)
  * @ingroup core
  *
  * Module: \ref core
@@ -39,7 +31,7 @@
 
 
 /**
- * @page TimerDoc SIP-router's timer documentation
+ * @page TimerDoc Kamailio's timer documentation
  * @verbinclude timers.txt
  *
  */
diff --git a/timer_funcs.h b/timer_funcs.h
index 0a065a2..05a42ab 100644
--- a/timer_funcs.h
+++ b/timer_funcs.h
@@ -1,19 +1,16 @@
 /*
- * $Id$
- *
- *
  * timer related functions (internal)
  *
  * Copyright (C) 2005 iptelorg GmbH
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -23,14 +20,9 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-/* History:
- * --------
- *  2005-07-27  complete re-design/re-implemnetation (andrei)
- */
-
 /**
  * @file
- * @brief SIP-router core :: Timer related functions (internal)
+ * @brief Kamailio core :: Timer related functions (internal)
  * @ingroup core
  * Module: @ref core
  */
diff --git a/timer_proc.c b/timer_proc.c
index 6c8a081..76b54ee 100644
--- a/timer_proc.c
+++ b/timer_proc.c
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- * 
  * Copyright (C) 2009 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -15,19 +13,10 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/*
- * timer_proc.c  - separate process timers
- * (unrelated to the main fast and slow timers)
- */
-/*
- * History:
- * --------
- *  2009-03-10  initial version (andrei)
-*/
 
 /**
  * @file
- * @brief SIP-router core ::  timer - separate process timers
+ * @brief Kamailio core ::  timer - separate process timers
  *
  *  (unrelated to the main fast and slow timers)
  *
diff --git a/timer_proc.h b/timer_proc.h
index ba445da..bfeddd0 100644
--- a/timer_proc.h
+++ b/timer_proc.h
@@ -14,15 +14,9 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/*
- * History:
- * --------
- *  2009-03-10  initial version (andrei)
-*/
-
 /**
  * @file
- * @brief SIP-router core :: timer_proc.h - separate process timers
+ * @brief Kamailio core :: timer_proc.h - separate process timers
  *
  * (unrelated to the main fast and slow timers)
  * @ingroup core
diff --git a/timer_ticks.h b/timer_ticks.h
index 95e7c04..cdc5588 100644
--- a/timer_ticks.h
+++ b/timer_ticks.h
@@ -1,19 +1,16 @@
 /*
- * $Id$
- *
- *
  * timer frequency and ticks conversions
  *
  * Copyright (C) 2005 iptelorg GmbH
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -22,15 +19,9 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/* History:
- * --------
- *  2005-07-27  complete re-design/re-implemnetation (andrei)
- *  2007-07-02  added ticks comparison macros (andrei)
- */
-
 /**
  * @file
- * @brief SIP-router core :: timer frequency and ticks conversions
+ * @brief Kamailio core :: timer frequency and ticks conversions
  * @ingroup core
  * Module: @ref core
  */
diff --git a/tls_hooks.c b/tls_hooks.c
index 29f82b6..92e709f 100644
--- a/tls_hooks.c
+++ b/tls_hooks.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2007 iptelorg GmbH 
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -15,17 +13,10 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/*
- * tls hooks for modules
- *
- * History:
- * --------
- *  2007-02-09  created by andrei
- */
 
 /**
  * @file
- * @brief SIP-router TLS support :: TLS hooks for modules
+ * @brief Kamailio TLS support :: TLS hooks for modules
  * @ingroup tls
  * Module: @ref tls
  */
diff --git a/tls_hooks.h b/tls_hooks.h
index d08c0bf..3ac5bd2 100644
--- a/tls_hooks.h
+++ b/tls_hooks.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2007 iptelorg GmbH 
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -15,18 +13,10 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/*
- * tls hooks for modules
- *
- * History:
- * --------
- *  2007-02-09  created by andrei
- *  2010-05-14  new hook interface (better suited for async. tcp) (andrei)
- */
 
 /**
  * @file
- * @brief SIP-router TLS support :: TLS hooks for modules
+ * @brief Kamailio TLS support :: TLS hooks for modules
  * @ingroup tls
  * Module: @ref tls
  */
diff --git a/tls_hooks_init.h b/tls_hooks_init.h
index 458e22e..3657769 100644
--- a/tls_hooks_init.h
+++ b/tls_hooks_init.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2007 iptelorg GmbH 
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -15,17 +13,10 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/*
- * tls hooks init
- *
- * History:
- * --------
- *  2007-02-09  created by andrei
- */
 
 /**
  * @file
- * @brief SIP-router TLS support :: TLS hooks init
+ * @brief Kamailio TLS support :: TLS hooks init
  * @ingroup tls
  * Module: @ref tls
  */
diff --git a/trim.h b/trim.h
index 7e9327d..4989075 100644
--- a/trim.h
+++ b/trim.h
@@ -1,21 +1,14 @@
 /* 
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -25,14 +18,13 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-
 #ifndef TRIM_H
 #define TRIM_H
 
 #include "str.h"
 
 
-/*
+/*!
  * This switch-case statement is used in
  * trim_leading and trim_trailing. You can
  * define characters that should be skipped 
diff --git a/tsend.c b/tsend.c
index 1716951..f6f39f4 100644
--- a/tsend.c
+++ b/tsend.c
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,19 +17,10 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/*
- * send with timeout for stream and datagram sockets
- * 
- * History:
- * --------
- *  2004-02-26  created by andrei
- *  2003-03-03  switched to heavy macro use, added tsend_dgram_ev (andrei) 
- *  2006-02-03  tsend* will wait forever if timeout==-1 (andrei)
- */
 
 /*!
  * \file
- * \brief SIP-router core :: 
+ * \brief Kamailio core :: send with timeout for stream and datagram sockets
  * \ingroup core
  * Module: \ref core
  */
diff --git a/tsend.h b/tsend.h
index 8455c7d..346340d 100644
--- a/tsend.h
+++ b/tsend.h
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,11 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
-/*
- *  History:
- * --------
- *  2004-02-26  created by andrei
- */
 
 #ifndef __tsend_h
 #define __tsend_h
diff --git a/types.h b/types.h
index ea2e896..eba0e92 100644
--- a/types.h
+++ b/types.h
@@ -1,22 +1,19 @@
 /*
- * $Id$
- *
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
+ * For a license to use the Kamailio software under conditions
  * other than those described here, or to purchase support for this
  * software, please contact iptel.org by e-mail at the following addresses:
  *    info at iptel.org
  *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/udp_server.c b/udp_server.c
index 63c03ef..5105456 100644
--- a/udp_server.c
+++ b/udp_server.c
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,28 +17,10 @@
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History
- * --------
- *  2003-01-28  packet zero-termination moved to receive_msg (jiri)
- *  2003-02-10  undoed the above changes (andrei)
- *  2003-03-19  replaced all the mallocs/frees w/ pkg_malloc/pkg_free (andrei)
- *  2003-04-14  set sockopts to TOS low delay (andrei)
- *  2004-05-03  applied multicast support patch from janakj
- *              added set multicast ttl support (andrei)
- *  2004-07-05  udp_rcv_loop: drop packets with 0 src port + error msg.
- *              cleanups (andrei)
- *  2005-03-10  multicast options are now set for all the udp sockets (andrei)
- *  2005-06-26  failure to set mcast options is not an error anymore (andrei)
- *  2006-04-12  udp_send() switched to struct dest_info (andrei)
- *  2006-10-13  added STUN support (vlada)
- *  2007-08-28  disable/set MTU discover option for the udp sockets
- *               (in linux it's enabled by default which produces udp packets
- *                with the DF flag ser) (patch from hscholz)
- *  2010-06-15  support for using raw sockets for sending (andrei)
  */
 
 
-/** udp send and loop-receive functions.
+/** Kamailio core :: udp send and loop-receive functions.
  * @file udp_server.c
  * @ingroup core
  * Module: @ref core
@@ -115,7 +90,7 @@ static int dbg_msg_qa(char *buf, int len)
 			case ' ':	if (state==QA_SPACE) {
 							space_cnt++;
 							if (space_cnt==4) {
-								LM_CRIT("DBG_MSG_QA: too many spaces\n");
+								LM_CRIT("too many spaces\n");
 								return 0;
 							}
 						} else space_cnt=0;
@@ -447,7 +422,7 @@ int udp_rcv_loop()
 											&fromlen);
 		if (len==-1){
 			if (errno==EAGAIN){
-				DBG("udp_rcv_loop: packet with bad checksum received\n");
+				LM_DBG("packet with bad checksum received\n");
 				continue;
 			}
 			LM_ERR("recvfrom:[%d] %s\n", errno, strerror(errno));
@@ -477,8 +452,7 @@ int udp_rcv_loop()
 		if (!unlikely(sr_event_enabled(SREV_STUN_IN)) || (unsigned char)*buf != 0x00) {
 			if (len<MIN_UDP_PACKET) {
 				tmp=ip_addr2a(&ri.src_ip);
-				DBG("udp_rcv_loop: probing packet received from %s %d\n",
-					tmp, htons(ri.src_port));
+				LM_DBG("probing packet received from %s %d\n", tmp, htons(ri.src_port));
 				continue;
 			}
 		}
diff --git a/udp_server.h b/udp_server.h
index 38afba6..c67376d 100644
--- a/udp_server.h
+++ b/udp_server.h
@@ -1,21 +1,19 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
+ * For a license to use the Kamailio software under conditions
  * other than those described here, or to purchase support for this
  * software, please contact iptel.org by e-mail at the following addresses:
  *    info at iptel.org
  *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/usr_avp.c b/usr_avp.c
index 94e6a36..96b877b 100644
--- a/usr_avp.c
+++ b/usr_avp.c
@@ -1,19 +1,14 @@
 /*
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -22,19 +17,12 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * ---------
- *  2004-07-21  created (bogdan)
- *  2004-10-09  interface more flexible - more function available (bogdan)
- *  2004-11-07  AVP string values are kept 0 terminated (bogdan)
- *  2004-11-14  global aliases support added
- *  2005-01-05  parse avp name according new syntax
  */
 
 
 /*!
  * \file
- * \brief SIP-router core :: 
+ * \brief Kamailio core :: Attribute value pair handling (AVP)
  * \ingroup core
  * Module: \ref core
  */
@@ -640,7 +628,7 @@ inline void destroy_avp_list(avp_list_t* list)
 {
 	avp_t *avp, *foo;
 
-	DBG("DEBUG:destroy_avp_list: destroying list %p\n", *list);
+	LM_DBG("destroying list %p\n", *list);
 	avp = *list;
 	while( avp ) {
 		foo = avp;
@@ -787,11 +775,11 @@ int add_avp_galias(str *alias, int type, int_str avp_name)
 		ga->avp.name.s.len = avp_name.s.len;
 		memcpy( ga->avp.name.s.s, avp_name.s.s, avp_name.s.len);
 		ga->avp.name.s.s[avp_name.s.len] = 0;
-		DBG("DEBUG:add_avp_galias: registering <%s> for avp name <%s>\n",
+		LM_DBG("registering <%s> for avp name <%s>\n",
 			ga->alias.s, ga->avp.name.s.s);
 	} else {
 		ga->avp.name.n = avp_name.n;
-		DBG("DEBUG:add_avp_galias: registering <%s> for avp id <%d>\n",
+		LM_DBG("registering <%s> for avp id <%d>\n",
 			ga->alias.s, ga->avp.name.n);
 	}
 
@@ -891,7 +879,7 @@ int parse_avp_ident( str *name, avp_ident_t* attr)
 	}
 
 	attr->index = 0;
-	DBG("Parsing '%.*s'\n", name->len, name->s);
+	LM_DBG("Parsing '%.*s'\n", name->len, name->s);
 	if (name->len>=2 && name->s[1]==':') { /* old fashion i: or s: */
 	        /* WARN("i: and s: avp name syntax is deprecated!\n"); */
 		c = name->s[0];
diff --git a/usr_avp.h b/usr_avp.h
index 6eb1074..28d562a 100644
--- a/usr_avp.h
+++ b/usr_avp.h
@@ -1,21 +1,14 @@
 /*
- * $Id$
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
- * This file is part of ser, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * ser is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info at iptel.org
- *
- * ser is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,11 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * History:
- * ---------
- *  2004-07-21  created (bogdan)
- *  2004-11-14  global aliases support added
- *  2005-02-14  list with FLAGS USAGE added (bogdan)
  */
 
 #ifndef _SER_USR_AVP_H_
diff --git a/ut.c b/ut.c
index 7079c70..71907b4 100644
--- a/ut.c
+++ b/ut.c
@@ -1,6 +1,4 @@
 /*
- *$Id$
- *
  * various general purpose functions
  *
  * Copyright (C) 2001-2003 FhG Fokus
@@ -20,7 +18,7 @@
  */
 
 
-/** various general purpose/utility functions.
+/** Kamailio core :: various general purpose/utility functions.
  * @file ut.c
  * @ingroup core
  * Module: core
diff --git a/ut.h b/ut.h
index 3c4a614..abf635e 100644
--- a/ut.h
+++ b/ut.h
@@ -1,6 +1,4 @@
 /*
- *$Id$
- *
  * - various general purpose functions
  *
  * Copyright (C) 2001-2003 FhG Fokus
@@ -17,27 +15,10 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  *
- * History
- * ------
- * 2003-01-18 un_escape function introduced for convenience of code needing
- *            the complex&slow feature of unescaping
- * 2003-01-28 scratchpad removed (jiri)
- * 2003-01-29 pathmax added (jiri)
- * 2003-02-13 strlower added (janakj)
- * 2003-02-28 scratchpad compatibility abandoned (jiri)
- * 2003-03-30 str2int and str2float added (janakj)
- * 2003-04-26 ZSW (jiri)
- * 2004-03-08 updated int2str (64 bits, INT2STR_MAX_LEN used) (andrei)
- * 2005-11-29 reverse_hex2int/int2reverse_hex switched to unsigned int (andrei)
- * 2005-12-09 added msgid_var (andrei)
- * 2007-05-14 added get_sys_ver() (andrei)
- * 2007-06-05 added MAX_UVAR_VALUE(), MAX_int(a,b) MIN_int(a,b) (andrei)
- * 2008-05-21 added ushort2sbuf(), ushort2str() (andrei)
- * 2009-03-16 added sint2strbuf() and incremented INST2STR_MAX_LEN to account
- *             for sign (andrei)
  */
-/** various general purpose/helper functions.
+/** Kamailio core :: various general purpose/helper functions.
  * @file
+ * @ingroup core
  */
 
 
diff --git a/utils/sercmd/EXAMPLES b/utils/kamcmd/EXAMPLES
similarity index 100%
rename from utils/sercmd/EXAMPLES
rename to utils/kamcmd/EXAMPLES
diff --git a/utils/kamcmd/Makefile b/utils/kamcmd/Makefile
new file mode 100644
index 0000000..60fe5e3
--- /dev/null
+++ b/utils/kamcmd/Makefile
@@ -0,0 +1,108 @@
+# $Id$
+COREPATH=../..
+include $(COREPATH)/Makefile.defs
+include $(COREPATH)/Makefile.targets
+
+auto_gen=
+RELEASE=0.2
+UTIL_SRC_NAME=kamcmd
+ifeq ($(FLAVOUR),ser)
+	NAME=sercmd
+else
+	NAME=kamcmd
+endif
+
+readline_locations= /usr/include/readline/readline.h \
+					$(LOCALBASE)/include/readline/readline.h
+
+use_readline ?=
+ifneq (,$(MAKECMDGOALS))
+ifeq (,$(filter-out $(nodep_targets),$(MAKECMDGOALS)))
+#set it to empty, we don't need to detect/use it for clean, doc a.s.o
+override use_readline:=
+quiet=1
+endif
+endif #ifneq (,$(MAKECMDGOALS))
+
+
+# erase common DEFS (not needed)
+C_DEFS:=
+DEFS:= -DNAME='"$(NAME)"' -DSRNAME='"$(MAIN_NAME)"' -DVERSION='"$(RELEASE)"' -D__OS_$(OS) \
+		-DRUN_DIR='"$(run_target)"' \
+		$(filter -D%HAVE -DARCH% -DOS% -D__CPU% -D__OS%, $(DEFS))
+
+# use proper libs (we can't rely on LIBS value since we might be called
+# from a module Makefile)
+#LIBS:=$(filter-out -lfl  -ldl -lpthread -lssl -lcrypto, $(LIBS))
+
+ifeq ($(OS), linux)
+	LIBS:= -lresolv
+endif
+ifeq ($(OS), solaris)
+	LIBS:= -lresolv -L$(LOCALBASE)/lib -lxnet -lnsl
+endif
+ifeq ($(OS), freebsd)
+	LIBS:=
+endif
+ifeq  ($(OS), dragonfly)
+	LIBS:= -L$(LOCALBASE)/lib
+endif
+ifeq ($(OS), openbsd)
+	LIBS:=
+endif
+ifeq ($(OS), netbsd)
+	LIBS:=
+endif
+ifeq ($(OS), darwin)
+	LIBS:= -lresolv
+endif
+ifneq (,$(findstring cygwin, $(OS)))
+	LIBS:= -lresolv
+endif
+
+ifeq ($(use_readline),)
+readline_path := $(shell  \
+						for r in $(readline_locations) ""; do \
+							if [ -r "$$r" ] ; then echo $$r; exit; fi;  \
+						done;\
+					)
+ifneq ($(readline_path),)
+use_readline := 1
+endif
+endif
+
+ifeq ($(use_readline),1)
+	DEFS+=-DUSE_READLINE
+	LIBS+=-lreadline -lncurses
+endif
+
+
+include $(COREPATH)/Makefile.utils
+
+ifeq (,$(quiet))
+ifeq ($(use_readline),1)
+$(info readline detected ($(readline_path)) )
+$(info command completion enabled)
+else
+$(info "no readline include files detected, disabling readline support")
+$(info "command completion disabled" )
+$(info "to force readline support try 'make use_readline=1'")
+endif
+endif # ifeq (,$(quiet))
+
+$(NAME).o: 
+
+.PHONY: msg
+msg:
+	@if [ "$(use_readline)" = "1" ]; then \
+		echo; echo "readline detected ($(readline_path)):"; \
+		echo "command completion enabled"; echo ; \
+	else \
+		echo ; \
+		echo "no readline include files detected, disabling readline support";\
+		echo "command completion disabled"; \
+		echo "(to force readline support try 'make use_readline=1')";\
+		echo ; \
+	fi
+
+modules:
diff --git a/utils/sercmd/README b/utils/kamcmd/README
similarity index 100%
rename from utils/sercmd/README
rename to utils/kamcmd/README
diff --git a/utils/sercmd/TODO b/utils/kamcmd/TODO
similarity index 100%
rename from utils/sercmd/TODO
rename to utils/kamcmd/TODO
diff --git a/utils/kamcmd/kamcmd.8 b/utils/kamcmd/kamcmd.8
new file mode 100644
index 0000000..017c814
--- /dev/null
+++ b/utils/kamcmd/kamcmd.8
@@ -0,0 +1,35 @@
+.\" $Id$
+.TH kamcmd 8 23.10.2012 Kamailio "kamailio" 
+.\" Process with
+.\" groff -man -Tascii kamcmd.8 
+.\"
+.SH NAME
+kamcmd \- kamailio command line tool
+.SH SYNOPSIS
+.B kamcmd
+[
+.B \-h
+]
+
+.SH DESCRIPTION
+.B kamcmd
+is a command line to interact with
+.B Kamailio SIP server
+It can be used to manage users, domains, aliases and other server options.
+
+.SH OPTIONS
+.TP 12
+.B \-h
+display a short usage description, including all available options.
+
+.SH AUTHORS
+
+see 
+.B /usr/share/doc/kamailio/AUTHORS
+
+.SH SEE ALSO
+.BR kamailio(8),
+.BR kamailio.cfg(5)
+.PP
+Full documentation about kamailio is available at
+.I http://www.kamailio.org/.
diff --git a/utils/sercmd/sercmd.c b/utils/kamcmd/kamcmd.c
similarity index 100%
rename from utils/sercmd/sercmd.c
rename to utils/kamcmd/kamcmd.c
diff --git a/utils/sercmd/license.h b/utils/kamcmd/license.h
similarity index 100%
rename from utils/sercmd/license.h
rename to utils/kamcmd/license.h
diff --git a/utils/sercmd/parse_listen_id.c b/utils/kamcmd/parse_listen_id.c
similarity index 100%
rename from utils/sercmd/parse_listen_id.c
rename to utils/kamcmd/parse_listen_id.c
diff --git a/utils/sercmd/parse_listen_id.h b/utils/kamcmd/parse_listen_id.h
similarity index 100%
rename from utils/sercmd/parse_listen_id.h
rename to utils/kamcmd/parse_listen_id.h
diff --git a/utils/kamctl/Makefile b/utils/kamctl/Makefile
index 3056ae0..efbda6c 100644
--- a/utils/kamctl/Makefile
+++ b/utils/kamctl/Makefile
@@ -3,6 +3,12 @@ COREPATH=../..
 include $(COREPATH)/Makefile.defs
 include $(COREPATH)/config.mak
 
+ifeq ($(basedir),)
+kamctltmpdir = /tmp
+else
+kamctltmpdir = $(basedir)
+endif
+
 all:
 		@echo "No compilation needed for kamctl"
 
@@ -25,63 +31,63 @@ install-bin: $(bin_prefix)/$(bin_dir)
 		cat kamctl | \
 		sed -e "s#/usr/local/sbin#$(bin_target)#g" | \
 		sed -e "s#/usr/local/lib/kamailio#$(lib_target)#g" | \
-		sed -e "s#/usr/local/etc/kamailio#$(cfg_target)#g"  >/tmp/kamctl
+		sed -e "s#/usr/local/etc/kamailio#$(cfg_target)#g"  >$(kamctltmpdir)/kamctl
 		$(INSTALL_TOUCH) $(bin_prefix)/$(bin_dir)/kamctl
-		$(INSTALL_BIN) /tmp/kamctl $(bin_prefix)/$(bin_dir)
-		rm -fr /tmp/kamctl
+		$(INSTALL_BIN) $(kamctltmpdir)/kamctl $(bin_prefix)/$(bin_dir)
+		rm -fr $(kamctltmpdir)/kamctl
 		sed -e "s#/usr/local/sbin#$(bin_target)#g" \
-			< kamctl.base > /tmp/kamctl.base
+			< kamctl.base > $(kamctltmpdir)/kamctl.base
 		mkdir -p $(modules_prefix)/$(lib_dir)/kamctl 
 		$(INSTALL_TOUCH) \
 			$(modules_prefix)/$(lib_dir)/kamctl
-		$(INSTALL_CFG) /tmp/kamctl.base \
+		$(INSTALL_CFG) $(kamctltmpdir)/kamctl.base \
 			$(modules_prefix)/$(lib_dir)/kamctl/kamctl.base
-		rm -fr /tmp/kamctl.base
+		rm -fr $(kamctltmpdir)/kamctl.base
 		sed -e "s#/usr/local#$(bin_target)#g" \
-			< kamctl.ctlbase > /tmp/kamctl.ctlbase
-		$(INSTALL_CFG) /tmp/kamctl.ctlbase \
+			< kamctl.ctlbase > $(kamctltmpdir)/kamctl.ctlbase
+		$(INSTALL_CFG) $(kamctltmpdir)/kamctl.ctlbase \
 			$(modules_prefix)/$(lib_dir)/kamctl/kamctl.ctlbase
-		rm -fr /tmp/kamctl.ctlbase
+		rm -fr $(kamctltmpdir)/kamctl.ctlbase
 		sed -e "s#/usr/local#$(bin_target)#g" \
-			< kamctl.fifo > /tmp/kamctl.fifo
-		$(INSTALL_CFG) /tmp/kamctl.fifo \
+			< kamctl.fifo > $(kamctltmpdir)/kamctl.fifo
+		$(INSTALL_CFG) $(kamctltmpdir)/kamctl.fifo \
 			$(modules_prefix)/$(lib_dir)/kamctl/kamctl.fifo
-		rm -fr /tmp/kamctl.fifo
+		rm -fr $(kamctltmpdir)/kamctl.fifo
 		sed -e "s#/usr/local#$(bin_target)#g" \
-			< kamctl.ser > /tmp/kamctl.ser
-		$(INSTALL_CFG) /tmp/kamctl.ser \
+			< kamctl.ser > $(kamctltmpdir)/kamctl.ser
+		$(INSTALL_CFG) $(kamctltmpdir)/kamctl.ser \
 			$(modules_prefix)/$(lib_dir)/kamctl/kamctl.ser
-		rm -fr /tmp/kamctl.ser
+		rm -fr $(kamctltmpdir)/kamctl.ser
 		sed -e "s#/usr/local#$(bin_target)#g" \
-			< kamctl.ser_mi > /tmp/kamctl.ser_mi
-		$(INSTALL_CFG) /tmp/kamctl.ser_mi \
+			< kamctl.ser_mi > $(kamctltmpdir)/kamctl.ser_mi
+		$(INSTALL_CFG) $(kamctltmpdir)/kamctl.ser_mi \
 			$(modules_prefix)/$(lib_dir)/kamctl/kamctl.ser_mi
-		rm -fr /tmp/kamctl.ser_mi
+		rm -fr $(kamctltmpdir)/kamctl.ser_mi
 		sed -e "s#/usr/local#$(bin_target)#g" \
-			< kamctl.unixsock > /tmp/kamctl.unixsock
-		$(INSTALL_CFG) /tmp/kamctl.unixsock \
+			< kamctl.unixsock > $(kamctltmpdir)/kamctl.unixsock
+		$(INSTALL_CFG) $(kamctltmpdir)/kamctl.unixsock \
 			$(modules_prefix)/$(lib_dir)/kamctl/kamctl.unixsock
-		rm -fr /tmp/kamctl.unixsock
+		rm -fr $(kamctltmpdir)/kamctl.unixsock
 		sed -e "s#/usr/local#$(bin_target)#g" \
-			< kamctl.sqlbase > /tmp/kamctl.sqlbase
-		$(INSTALL_CFG) /tmp/kamctl.sqlbase \
+			< kamctl.sqlbase > $(kamctltmpdir)/kamctl.sqlbase
+		$(INSTALL_CFG) $(kamctltmpdir)/kamctl.sqlbase \
 			$(modules_prefix)/$(lib_dir)/kamctl/kamctl.sqlbase
-		rm -fr /tmp/kamctl.sqlbase
+		rm -fr $(kamctltmpdir)/kamctl.sqlbase
 		# install db setup base script
 		sed -e "s#/usr/local/sbin#$(bin_target)#g" \
 			-e "s#/usr/local/etc/kamailio#$(cfg_target)#g" \
 			-e "s#/usr/local/share/kamailio#$(data_target)#g" \
-			< kamdbctl.base > /tmp/kamdbctl.base
-		$(INSTALL_CFG) /tmp/kamdbctl.base \
+			< kamdbctl.base > $(kamctltmpdir)/kamdbctl.base
+		$(INSTALL_CFG) $(kamctltmpdir)/kamdbctl.base \
 			$(modules_prefix)/$(lib_dir)/kamctl/kamdbctl.base
-		rm -fr /tmp/kamdbctl.base
+		rm -fr $(kamctltmpdir)/kamdbctl.base
 		cat kamdbctl | \
 		sed -e "s#/usr/local/sbin#$(bin_target)#g" | \
 		sed -e "s#/usr/local/lib/kamailio#$(lib_target)#g" | \
-		sed -e "s#/usr/local/etc/kamailio#$(cfg_target)#g"  >/tmp/kamdbctl
+		sed -e "s#/usr/local/etc/kamailio#$(cfg_target)#g"  >$(kamctltmpdir)/kamdbctl
 		$(INSTALL_TOUCH) $(bin_prefix)/$(bin_dir)/kamdbctl
-		$(INSTALL_BIN) /tmp/kamdbctl $(bin_prefix)/$(bin_dir)
-		rm -fr /tmp/kamdbctl
+		$(INSTALL_BIN) $(kamctltmpdir)/kamdbctl $(bin_prefix)/$(bin_dir)
+		rm -fr $(kamctltmpdir)/kamdbctl
 
 install-man: $(man_prefix)/$(man_dir)/man8 $(man_prefix)/$(man_dir)/man5
 		sed -e "s#/etc/$(NAME)/$(NAME)\.cfg#$(cfg_target)$(NAME).cfg#g" \
@@ -105,15 +111,15 @@ install-modules: $(bin_prefix)/$(bin_dir)
 		if [ "$(MYSQLON)" = "yes" ]; then \
 			mkdir -p $(modules_prefix)/$(lib_dir)/kamctl ; \
 			sed -e "s#/usr/local/sbin#$(bin_target)#g" \
-				< kamctl.mysql > /tmp/kamctl.mysql ; \
-			$(INSTALL_CFG) /tmp/kamctl.mysql \
+				< kamctl.mysql > $(kamctltmpdir)/kamctl.mysql ; \
+			$(INSTALL_CFG) $(kamctltmpdir)/kamctl.mysql \
 				$(modules_prefix)/$(lib_dir)/kamctl/kamctl.mysql ; \
-			rm -fr /tmp/kamctl.mysql ; \
+			rm -fr $(kamctltmpdir)/kamctl.mysql ; \
 			sed -e "s#/usr/local/share/kamailio#$(data_target)#g" \
-			< kamdbctl.mysql > /tmp/kamdbctl.mysql ; \
+			< kamdbctl.mysql > $(kamctltmpdir)/kamdbctl.mysql ; \
 			$(INSTALL_TOUCH) $(modules_prefix)/$(lib_dir)/kamctl/kamdbctl.mysql ; \
-			$(INSTALL_CFG) /tmp/kamdbctl.mysql $(modules_prefix)/$(lib_dir)/kamctl/ ; \
-			rm -fr /tmp/kamdbctl.mysql ; \
+			$(INSTALL_CFG) $(kamctltmpdir)/kamdbctl.mysql $(modules_prefix)/$(lib_dir)/kamctl/ ; \
+			rm -fr $(kamctltmpdir)/kamdbctl.mysql ; \
 			mkdir -p $(data_prefix)/$(data_dir)/mysql ; \
 			for FILE in $(wildcard mysql/*) ; do \
 				if [ -f $$FILE ] ; then \
@@ -128,15 +134,15 @@ install-modules: $(bin_prefix)/$(bin_dir)
 		if [ "$(PGSQLON)" = "yes" ]; then \
 			mkdir -p $(modules_prefix)/$(lib_dir)/kamctl ; \
 			sed -e "s#/usr/local/sbin#$(bin_target)#g" \
-				< kamctl.pgsql > /tmp/kamctl.pgsql ; \
-			$(INSTALL_CFG) /tmp/kamctl.pgsql \
+				< kamctl.pgsql > $(kamctltmpdir)/kamctl.pgsql ; \
+			$(INSTALL_CFG) $(kamctltmpdir)/kamctl.pgsql \
 				$(modules_prefix)/$(lib_dir)/kamctl/kamctl.pgsql ; \
-			rm -fr /tmp/kamctl.pgsql ; \
+			rm -fr $(kamctltmpdir)/kamctl.pgsql ; \
 			sed -e "s#/usr/local/share/kamailio#$(data_target)#g" \
-				< kamdbctl.pgsql > /tmp/kamdbctl.pgsql ; \
+				< kamdbctl.pgsql > $(kamctltmpdir)/kamdbctl.pgsql ; \
 			$(INSTALL_TOUCH) $(modules_prefix)/$(lib_dir)/kamctl/kamdbctl.pgsql ; \
-			$(INSTALL_CFG) /tmp/kamdbctl.pgsql $(modules_prefix)/$(lib_dir)/kamctl/ ; \
-			rm -fr /tmp/kamdbctl.pgsql ; \
+			$(INSTALL_CFG) $(kamctltmpdir)/kamdbctl.pgsql $(modules_prefix)/$(lib_dir)/kamctl/ ; \
+			rm -fr $(kamctltmpdir)/kamdbctl.pgsql ; \
 			mkdir -p $(data_prefix)/$(data_dir)/postgres ; \
 			for FILE in $(wildcard postgres/*) ; do \
 				if [ -f $$FILE ] ; then \
@@ -151,20 +157,20 @@ install-modules: $(bin_prefix)/$(bin_dir)
 		if [ "$(ORACLEON)" = "yes" ]; then \
 			mkdir -p $(modules_prefix)/$(lib_dir)/kamctl ; \
 			sed -e "s#/usr/local/sbin#$(bin_target)#g" \
-				< kamctl.oracle > /tmp/kamctl.oracle ; \
-			$(INSTALL_CFG) /tmp/kamctl.oracle \
+				< kamctl.oracle > $(kamctltmpdir)/kamctl.oracle ; \
+			$(INSTALL_CFG) $(kamctltmpdir)/kamctl.oracle \
 				$(modules_prefix)/$(lib_dir)/kamctl/kamctl.oracle ; \
-			rm -fr /tmp/kamctl.oracle ; \
+			rm -fr $(kamctltmpdir)/kamctl.oracle ; \
 			sed -e "s#/usr/local/share/kamailio#$(data_target)#g" \
-			< kamdbctl.oracle > /tmp/kamdbctl.oracle ; \
+			< kamdbctl.oracle > $(kamctltmpdir)/kamdbctl.oracle ; \
 			$(INSTALL_TOUCH) $(modules_prefix)/$(lib_dir)/kamctl/kamdbctl.oracle ; \
-			$(INSTALL_CFG) /tmp/kamdbctl.oracle $(modules_prefix)/$(lib_dir)/kamctl/ ; \
-			rm -fr /tmp/kamdbctl.oracle ; \
+			$(INSTALL_CFG) $(kamctltmpdir)/kamdbctl.oracle $(modules_prefix)/$(lib_dir)/kamctl/ ; \
+			rm -fr $(kamctltmpdir)/kamdbctl.oracle ; \
 			sed -e "s#/usr/local/share/kamailio#$(data_target)#g" \
-			< kamdbfunc.oracle > /tmp/kamdbfunc.oracle ; \
+			< kamdbfunc.oracle > $(kamctltmpdir)/kamdbfunc.oracle ; \
 			$(INSTALL_TOUCH) $(modules_prefix)/$(lib_dir)/kamctl/kamdbfunc.oracle ; \
-			$(INSTALL_CFG) /tmp/kamdbfunc.oracle $(modules_prefix)/$(lib_dir)/kamctl/ ; \
-			rm -fr /tmp/kamdbfunc.oracle ; \
+			$(INSTALL_CFG) $(kamctltmpdir)/kamdbfunc.oracle $(modules_prefix)/$(lib_dir)/kamctl/ ; \
+			rm -fr $(kamctltmpdir)/kamdbfunc.oracle ; \
 			mkdir -p $(data_prefix)/$(data_dir)/oracle ; \
 			for FILE in $(wildcard oracle/*) ; do \
 				if [ -f $$FILE ] ; then \
@@ -199,15 +205,15 @@ install-modules: $(bin_prefix)/$(bin_dir)
 		if [ "$(BERKELEYDBON)" = "yes" ]; then \
 			mkdir -p $(modules_prefix)/$(lib_dir)/kamctl ; \
 			sed -e "s#/usr/local/share/kamailio/#$(data_target)#g" \
-				< kamctl.db_berkeley > /tmp/kamctl.db_berkeley ; \
-			$(INSTALL_CFG) /tmp/kamctl.db_berkeley \
+				< kamctl.db_berkeley > $(kamctltmpdir)/kamctl.db_berkeley ; \
+			$(INSTALL_CFG) $(kamctltmpdir)/kamctl.db_berkeley \
 				$(modules_prefix)/$(lib_dir)/kamctl/kamctl.db_berkeley ; \
-			rm -fr /tmp/kamctl.db_berkeley ; \
+			rm -fr $(kamctltmpdir)/kamctl.db_berkeley ; \
 			sed -e "s#/usr/local/share/kamailio#$(data_target)#g" \
-				< kamdbctl.db_berkeley > /tmp/kamdbctl.db_berkeley ; \
+				< kamdbctl.db_berkeley > $(kamctltmpdir)/kamdbctl.db_berkeley ; \
 			$(INSTALL_TOUCH) $(modules_prefix)/$(lib_dir)/kamctl/kamdbctl.db_berkeley ; \
-			$(INSTALL_CFG) /tmp/kamdbctl.db_berkeley $(modules_prefix)/$(lib_dir)/kamctl/ ; \
-			rm -fr /tmp/kamdbctl.db_berkeley ; \
+			$(INSTALL_CFG) $(kamctltmpdir)/kamdbctl.db_berkeley $(modules_prefix)/$(lib_dir)/kamctl/ ; \
+			rm -fr $(kamctltmpdir)/kamdbctl.db_berkeley ; \
 			mkdir -p $(data_prefix)/$(data_dir)/db_berkeley/kamailio ; \
 			for FILE in $(wildcard db_berkeley/kamailio/*) ; do \
 				if [ -f $$FILE ] ; then \
@@ -224,15 +230,15 @@ install-modules: $(bin_prefix)/$(bin_dir)
 		if [ "$(DBTEXTON)" = "yes" ]; then \
 			mkdir -p $(modules_prefix)/$(lib_dir)/kamctl ; \
 			sed -e "s#/usr/local/share/kamailio/#$(data_target)#g" \
-				< kamctl.dbtext > /tmp/kamctl.dbtext ; \
-			$(INSTALL_CFG) /tmp/kamctl.dbtext \
+				< kamctl.dbtext > $(kamctltmpdir)/kamctl.dbtext ; \
+			$(INSTALL_CFG) $(kamctltmpdir)/kamctl.dbtext \
 				$(modules_prefix)/$(lib_dir)/kamctl/kamctl.dbtext ; \
-			rm -fr /tmp/kamctl.dbtext ; \
+			rm -fr $(kamctltmpdir)/kamctl.dbtext ; \
 			sed -e "s#/usr/local/share/kamailio#$(data_target)#g" \
-				< kamdbctl.dbtext > /tmp/kamdbctl.dbtext ; \
+				< kamdbctl.dbtext > $(kamctltmpdir)/kamdbctl.dbtext ; \
 			$(INSTALL_TOUCH) $(modules_prefix)/$(lib_dir)/kamctl/kamdbctl.dbtext ; \
-			$(INSTALL_CFG) /tmp/kamdbctl.dbtext $(modules_prefix)/$(lib_dir)/kamctl/ ; \
-			rm -fr /tmp/kamdbctl.dbtext ; \
+			$(INSTALL_CFG) $(kamctltmpdir)/kamdbctl.dbtext $(modules_prefix)/$(lib_dir)/kamctl/ ; \
+			rm -fr $(kamctltmpdir)/kamdbctl.dbtext ; \
 			mkdir -p $(modules_prefix)/$(lib_dir)/kamctl/dbtextdb ; \
 			$(INSTALL_TOUCH) $(modules_prefix)/$(lib_dir)/kamctl/dbtextdb/dbtextdb.py ; \
 			$(INSTALL_BIN) dbtextdb/dbtextdb.py $(modules_prefix)/$(lib_dir)/kamctl/dbtextdb/ ; \
@@ -250,15 +256,15 @@ install-modules: $(bin_prefix)/$(bin_dir)
 		if [ "$(SQLITEON)" = "yes" ]; then \
 			mkdir -p $(modules_prefix)/$(lib_dir)/kamctl ; \
 			sed -e "s#/usr/local/sbin#$(bin_target)#g" \
-				< kamctl.sqlite > /tmp/kamctl.sqlite ; \
-			$(INSTALL_CFG) /tmp/kamctl.sqlite \
+				< kamctl.sqlite > $(kamctltmpdir)/kamctl.sqlite ; \
+			$(INSTALL_CFG) $(kamctltmpdir)/kamctl.sqlite \
 				$(modules_prefix)/$(lib_dir)/kamctl/kamctl.sqlite ; \
-			rm -fr /tmp/kamctl.sqlite ; \
+			rm -fr $(kamctltmpdir)/kamctl.sqlite ; \
 			sed -e "s#/usr/local/share/kamailio#$(data_target)#g" \
-				< kamdbctl.sqlite > /tmp/kamdbctl.sqlite ; \
+				< kamdbctl.sqlite > $(kamctltmpdir)/kamdbctl.sqlite ; \
 			$(INSTALL_TOUCH) $(modules_prefix)/$(lib_dir)/kamctl/kamdbctl.sqlite ; \
-			$(INSTALL_CFG) /tmp/kamdbctl.sqlite $(modules_prefix)/$(lib_dir)/kamctl/ ; \
-			rm -fr /tmp/kamdbctl.sqlite ; \
+			$(INSTALL_CFG) $(kamctltmpdir)/kamdbctl.sqlite $(modules_prefix)/$(lib_dir)/kamctl/ ; \
+			rm -fr $(kamctltmpdir)/kamdbctl.sqlite ; \
 			mkdir -p $(data_prefix)/$(data_dir)/db_sqlite ; \
 			for FILE in $(wildcard db_sqlite/*) ; do \
 				if [ -f $$FILE ] ; then \
diff --git a/utils/kamctl/db_berkeley/kamailio/acc_cdrs b/utils/kamctl/db_berkeley/kamailio/acc_cdrs
index 32fb63b..57ab533 100644
--- a/utils/kamctl/db_berkeley/kamailio/acc_cdrs
+++ b/utils/kamctl/db_berkeley/kamailio/acc_cdrs
@@ -1,5 +1,5 @@
 METADATA_COLUMNS
-id(int) start_time(str) end_time(str) duration(str)
+id(int) start_time(datetime) end_time(datetime) duration(double)
 METADATA_KEY
 
 METADATA_READONLY
@@ -7,4 +7,4 @@ METADATA_READONLY
 METADATA_LOGFLAGS
 0
 METADATA_DEFAULTS
-NIL|''|''|''
+NIL|'2000-01-01 00:00:00'|'2000-01-01 00:00:00'|0
diff --git a/utils/kamctl/db_berkeley/kamailio/aliases b/utils/kamctl/db_berkeley/kamailio/aliases
index 54a12f6..947d7bd 100644
--- a/utils/kamctl/db_berkeley/kamailio/aliases
+++ b/utils/kamctl/db_berkeley/kamailio/aliases
@@ -1,5 +1,5 @@
 METADATA_COLUMNS
-id(int) ruid(str) username(str) domain(str) contact(str) received(str) path(str) expires(datetime) q(double) callid(str) cseq(int) last_modified(datetime) flags(int) cflags(int) user_agent(str) socket(str) methods(int) instance(str) reg_id(int)
+id(int) ruid(str) username(str) domain(str) contact(str) received(str) path(str) expires(datetime) q(double) callid(str) cseq(int) last_modified(datetime) flags(int) cflags(int) user_agent(str) socket(str) methods(int) instance(str) reg_id(int) server_id(int) connection_id(int) keepalive(int) partition(int)
 METADATA_KEY
 1 2 3 
 METADATA_READONLY
@@ -7,4 +7,4 @@ METADATA_READONLY
 METADATA_LOGFLAGS
 0
 METADATA_DEFAULTS
-NIL|''|''|NULL|''|NULL|NULL|'2030-05-28 21:32:15'|1.0|'Default-Call-ID'|1|'1900-01-01 00:00:01'|0|0|''|NULL|NULL|NULL|0
+NIL|''|''|NULL|''|NULL|NULL|'2030-05-28 21:32:15'|1.0|'Default-Call-ID'|1|'1900-01-01 00:00:01'|0|0|''|NULL|NULL|NULL|0|0|0|0|0
diff --git a/utils/kamctl/db_berkeley/kamailio/location b/utils/kamctl/db_berkeley/kamailio/location
index 54a12f6..947d7bd 100644
--- a/utils/kamctl/db_berkeley/kamailio/location
+++ b/utils/kamctl/db_berkeley/kamailio/location
@@ -1,5 +1,5 @@
 METADATA_COLUMNS
-id(int) ruid(str) username(str) domain(str) contact(str) received(str) path(str) expires(datetime) q(double) callid(str) cseq(int) last_modified(datetime) flags(int) cflags(int) user_agent(str) socket(str) methods(int) instance(str) reg_id(int)
+id(int) ruid(str) username(str) domain(str) contact(str) received(str) path(str) expires(datetime) q(double) callid(str) cseq(int) last_modified(datetime) flags(int) cflags(int) user_agent(str) socket(str) methods(int) instance(str) reg_id(int) server_id(int) connection_id(int) keepalive(int) partition(int)
 METADATA_KEY
 1 2 3 
 METADATA_READONLY
@@ -7,4 +7,4 @@ METADATA_READONLY
 METADATA_LOGFLAGS
 0
 METADATA_DEFAULTS
-NIL|''|''|NULL|''|NULL|NULL|'2030-05-28 21:32:15'|1.0|'Default-Call-ID'|1|'1900-01-01 00:00:01'|0|0|''|NULL|NULL|NULL|0
+NIL|''|''|NULL|''|NULL|NULL|'2030-05-28 21:32:15'|1.0|'Default-Call-ID'|1|'1900-01-01 00:00:01'|0|0|''|NULL|NULL|NULL|0|0|0|0|0
diff --git a/utils/kamctl/db_berkeley/kamailio/presentity b/utils/kamctl/db_berkeley/kamailio/presentity
index ef92481..c3ffcf3 100644
--- a/utils/kamctl/db_berkeley/kamailio/presentity
+++ b/utils/kamctl/db_berkeley/kamailio/presentity
@@ -1,5 +1,5 @@
 METADATA_COLUMNS
-id(int) username(str) domain(str) event(str) etag(str) expires(int) received_time(int) body(str) sender(str)
+id(int) username(str) domain(str) event(str) etag(str) expires(int) received_time(int) body(str) sender(str) priority(int)
 METADATA_KEY
 1 2 3 
 METADATA_READONLY
@@ -7,4 +7,4 @@ METADATA_READONLY
 METADATA_LOGFLAGS
 0
 METADATA_DEFAULTS
-NIL|NIL|NIL|NIL|NIL|NIL|NIL|NIL|NIL
+NIL|NIL|NIL|NIL|NIL|NIL|NIL|NIL|NIL|0
diff --git a/utils/kamctl/db_berkeley/kamailio/silo b/utils/kamctl/db_berkeley/kamailio/silo
index fe5d419..41ff819 100644
--- a/utils/kamctl/db_berkeley/kamailio/silo
+++ b/utils/kamctl/db_berkeley/kamailio/silo
@@ -7,4 +7,4 @@ METADATA_READONLY
 METADATA_LOGFLAGS
 0
 METADATA_DEFAULTS
-NIL|''|''|''|''|0|0|0|'text/plain'|''|''|''|0
+NIL|''|''|''|''|0|0|0|'text/plain'|NIL|NIL|''|0
diff --git a/utils/kamctl/db_berkeley/kamailio/sip_trace b/utils/kamctl/db_berkeley/kamailio/sip_trace
index ceb81fb..d07568e 100644
--- a/utils/kamctl/db_berkeley/kamailio/sip_trace
+++ b/utils/kamctl/db_berkeley/kamailio/sip_trace
@@ -1,5 +1,5 @@
 METADATA_COLUMNS
-id(int) time_stamp(datetime) time_us(int) callid(str) traced_user(str) msg(str) method(str) status(str) fromip(str) toip(str) fromtag(str) direction(str)
+id(int) time_stamp(datetime) time_us(int) callid(str) traced_user(str) msg(str) method(str) status(str) fromip(str) toip(str) fromtag(str) totag(str) direction(str)
 METADATA_KEY
 3 
 METADATA_READONLY
@@ -7,4 +7,4 @@ METADATA_READONLY
 METADATA_LOGFLAGS
 0
 METADATA_DEFAULTS
-NIL|'1900-01-01 00:00:01'|0|''|''|NIL|''|''|''|''|''|''
+NIL|'1900-01-01 00:00:01'|0|''|''|NIL|''|''|''|''|''|''|''
diff --git a/utils/kamctl/db_berkeley/kamailio/version b/utils/kamctl/db_berkeley/kamailio/version
index 827d321..a349513 100644
--- a/utils/kamctl/db_berkeley/kamailio/version
+++ b/utils/kamctl/db_berkeley/kamailio/version
@@ -11,13 +11,13 @@ NIL|0
 acc|
 acc|5
 acc_cdrs|
-acc_cdrs|1
+acc_cdrs|2
 active_watchers|
 active_watchers|11
 address|
 address|6
 aliases|
-aliases|6
+aliases|8
 carrier_name|
 carrier_name|1
 carrierfailureroute|
@@ -69,7 +69,7 @@ lcr_rule|2
 lcr_rule_target|
 lcr_rule_target|1
 location|
-location|6
+location|8
 location_attrs|
 location_attrs|1
 matrix|
@@ -89,7 +89,7 @@ pdt|1
 pl_pipes|
 pl_pipes|1
 presentity|
-presentity|3
+presentity|4
 pua|
 pua|7
 purplemap|
@@ -105,9 +105,9 @@ rtpproxy|1
 sca_subscriptions|
 sca_subscriptions|1
 silo|
-silo|7
+silo|8
 sip_trace|
-sip_trace|3
+sip_trace|4
 speed_dial|
 speed_dial|2
 subscriber|
diff --git a/utils/kamctl/db_sqlite/acc-create.sql b/utils/kamctl/db_sqlite/acc-create.sql
index bdc326a..60b4193 100644
--- a/utils/kamctl/db_sqlite/acc-create.sql
+++ b/utils/kamctl/db_sqlite/acc-create.sql
@@ -12,12 +12,12 @@ CREATE TABLE acc (
 
 CREATE INDEX acc_callid_idx ON acc (callid);
 
-INSERT INTO version (table_name, table_version) values ('acc_cdrs','1');
+INSERT INTO version (table_name, table_version) values ('acc_cdrs','2');
 CREATE TABLE acc_cdrs (
     id INTEGER PRIMARY KEY NOT NULL,
-    start_time VARCHAR(32) DEFAULT '' NOT NULL,
-    end_time VARCHAR(32) DEFAULT '' NOT NULL,
-    duration VARCHAR(32) DEFAULT '' NOT NULL
+    start_time TIMESTAMP WITHOUT TIME ZONE DEFAULT '2000-01-01 00:00:00' NOT NULL,
+    end_time TIMESTAMP WITHOUT TIME ZONE DEFAULT '2000-01-01 00:00:00' NOT NULL,
+    duration REAL DEFAULT 0 NOT NULL
 );
 
 CREATE INDEX acc_cdrs_start_time_idx ON acc_cdrs (start_time);
diff --git a/utils/kamctl/db_sqlite/msilo-create.sql b/utils/kamctl/db_sqlite/msilo-create.sql
index af2fdaa..60f5f75 100644
--- a/utils/kamctl/db_sqlite/msilo-create.sql
+++ b/utils/kamctl/db_sqlite/msilo-create.sql
@@ -1,4 +1,4 @@
-INSERT INTO version (table_name, table_version) values ('silo','7');
+INSERT INTO version (table_name, table_version) values ('silo','8');
 CREATE TABLE silo (
     id INTEGER PRIMARY KEY NOT NULL,
     src_addr VARCHAR(128) DEFAULT '' NOT NULL,
@@ -9,8 +9,8 @@ CREATE TABLE silo (
     exp_time INTEGER DEFAULT 0 NOT NULL,
     snd_time INTEGER DEFAULT 0 NOT NULL,
     ctype VARCHAR(32) DEFAULT 'text/plain' NOT NULL,
-    body BLOB DEFAULT '' NOT NULL,
-    extra_hdrs TEXT DEFAULT '' NOT NULL,
+    body BLOB,
+    extra_hdrs TEXT,
     callid VARCHAR(128) DEFAULT '' NOT NULL,
     status INTEGER DEFAULT 0 NOT NULL
 );
diff --git a/utils/kamctl/db_sqlite/presence-create.sql b/utils/kamctl/db_sqlite/presence-create.sql
index ff8190a..5ae6c08 100644
--- a/utils/kamctl/db_sqlite/presence-create.sql
+++ b/utils/kamctl/db_sqlite/presence-create.sql
@@ -1,4 +1,4 @@
-INSERT INTO version (table_name, table_version) values ('presentity','3');
+INSERT INTO version (table_name, table_version) values ('presentity','4');
 CREATE TABLE presentity (
     id INTEGER PRIMARY KEY NOT NULL,
     username VARCHAR(64) NOT NULL,
@@ -9,6 +9,7 @@ CREATE TABLE presentity (
     received_time INTEGER NOT NULL,
     body BLOB NOT NULL,
     sender VARCHAR(128) NOT NULL,
+    priority INTEGER DEFAULT 0 NOT NULL,
     CONSTRAINT presentity_presentity_idx UNIQUE (username, domain, event, etag)
 );
 
diff --git a/utils/kamctl/db_sqlite/registrar-create.sql b/utils/kamctl/db_sqlite/registrar-create.sql
index b32d61c..d7816c2 100644
--- a/utils/kamctl/db_sqlite/registrar-create.sql
+++ b/utils/kamctl/db_sqlite/registrar-create.sql
@@ -1,4 +1,4 @@
-INSERT INTO version (table_name, table_version) values ('aliases','6');
+INSERT INTO version (table_name, table_version) values ('aliases','8');
 CREATE TABLE aliases (
     id INTEGER PRIMARY KEY NOT NULL,
     ruid VARCHAR(64) DEFAULT '' NOT NULL,
@@ -6,7 +6,7 @@ CREATE TABLE aliases (
     domain VARCHAR(64) DEFAULT NULL,
     contact VARCHAR(255) DEFAULT '' NOT NULL,
     received VARCHAR(128) DEFAULT NULL,
-    path VARCHAR(128) DEFAULT NULL,
+    path VARCHAR(512) DEFAULT NULL,
     expires TIMESTAMP WITHOUT TIME ZONE DEFAULT '2030-05-28 21:32:15' NOT NULL,
     q REAL DEFAULT 1.0 NOT NULL,
     callid VARCHAR(255) DEFAULT 'Default-Call-ID' NOT NULL,
@@ -19,8 +19,13 @@ CREATE TABLE aliases (
     methods INTEGER DEFAULT NULL,
     instance VARCHAR(255) DEFAULT NULL,
     reg_id INTEGER DEFAULT 0 NOT NULL,
+    server_id INTEGER DEFAULT 0 NOT NULL,
+    connection_id INTEGER DEFAULT 0 NOT NULL,
+    keepalive INTEGER DEFAULT 0 NOT NULL,
+    partition INTEGER DEFAULT 0 NOT NULL,
     CONSTRAINT aliases_ruid_idx UNIQUE (ruid)
 );
 
-CREATE INDEX aliases_alias_idx ON aliases (username, domain, contact);
+CREATE INDEX aliases_account_contact_idx ON aliases (username, domain, contact);
+CREATE INDEX aliases_expires_idx ON aliases (expires);
 
diff --git a/utils/kamctl/db_sqlite/siptrace-create.sql b/utils/kamctl/db_sqlite/siptrace-create.sql
index 793b6f6..a19bf23 100644
--- a/utils/kamctl/db_sqlite/siptrace-create.sql
+++ b/utils/kamctl/db_sqlite/siptrace-create.sql
@@ -1,4 +1,4 @@
-INSERT INTO version (table_name, table_version) values ('sip_trace','3');
+INSERT INTO version (table_name, table_version) values ('sip_trace','4');
 CREATE TABLE sip_trace (
     id INTEGER PRIMARY KEY NOT NULL,
     time_stamp TIMESTAMP WITHOUT TIME ZONE DEFAULT '1900-01-01 00:00:01' NOT NULL,
@@ -11,6 +11,7 @@ CREATE TABLE sip_trace (
     fromip VARCHAR(50) DEFAULT '' NOT NULL,
     toip VARCHAR(50) DEFAULT '' NOT NULL,
     fromtag VARCHAR(64) DEFAULT '' NOT NULL,
+    totag VARCHAR(64) DEFAULT '' NOT NULL,
     direction VARCHAR(4) DEFAULT '' NOT NULL
 );
 
diff --git a/utils/kamctl/db_sqlite/usrloc-create.sql b/utils/kamctl/db_sqlite/usrloc-create.sql
index 6d29cae..cc3a378 100644
--- a/utils/kamctl/db_sqlite/usrloc-create.sql
+++ b/utils/kamctl/db_sqlite/usrloc-create.sql
@@ -1,4 +1,4 @@
-INSERT INTO version (table_name, table_version) values ('location','6');
+INSERT INTO version (table_name, table_version) values ('location','8');
 CREATE TABLE location (
     id INTEGER PRIMARY KEY NOT NULL,
     ruid VARCHAR(64) DEFAULT '' NOT NULL,
@@ -19,6 +19,10 @@ CREATE TABLE location (
     methods INTEGER DEFAULT NULL,
     instance VARCHAR(255) DEFAULT NULL,
     reg_id INTEGER DEFAULT 0 NOT NULL,
+    server_id INTEGER DEFAULT 0 NOT NULL,
+    connection_id INTEGER DEFAULT 0 NOT NULL,
+    keepalive INTEGER DEFAULT 0 NOT NULL,
+    partition INTEGER DEFAULT 0 NOT NULL,
     CONSTRAINT location_ruid_idx UNIQUE (ruid)
 );
 
diff --git a/utils/kamctl/dbtext/kamailio/acc_cdrs b/utils/kamctl/dbtext/kamailio/acc_cdrs
index df44e95..45490ad 100644
--- a/utils/kamctl/dbtext/kamailio/acc_cdrs
+++ b/utils/kamctl/dbtext/kamailio/acc_cdrs
@@ -1 +1 @@
-id(int,auto) start_time(string) end_time(string) duration(string) 
+id(int,auto) start_time(int) end_time(int) duration(double) 
diff --git a/utils/kamctl/dbtext/kamailio/aliases b/utils/kamctl/dbtext/kamailio/aliases
index f3f0c72..6a08f3c 100644
--- a/utils/kamctl/dbtext/kamailio/aliases
+++ b/utils/kamctl/dbtext/kamailio/aliases
@@ -1 +1 @@
-id(int,auto) ruid(string) username(string) domain(string,null) contact(string) received(string,null) path(string,null) expires(int) q(double) callid(string) cseq(int) last_modified(int) flags(int) cflags(int) user_agent(string) socket(string,null) methods(int,null) instance(string,null) reg_id(int) 
+id(int,auto) ruid(string) username(string) domain(string,null) contact(string) received(string,null) path(string,null) expires(int) q(double) callid(string) cseq(int) last_modified(int) flags(int) cflags(int) user_agent(string) socket(string,null) methods(int,null) instance(string,null) reg_id(int) server_id(int) connection_id(int) keepalive(int) partition(int) 
diff --git a/utils/kamctl/dbtext/kamailio/location b/utils/kamctl/dbtext/kamailio/location
index f3f0c72..6a08f3c 100644
--- a/utils/kamctl/dbtext/kamailio/location
+++ b/utils/kamctl/dbtext/kamailio/location
@@ -1 +1 @@
-id(int,auto) ruid(string) username(string) domain(string,null) contact(string) received(string,null) path(string,null) expires(int) q(double) callid(string) cseq(int) last_modified(int) flags(int) cflags(int) user_agent(string) socket(string,null) methods(int,null) instance(string,null) reg_id(int) 
+id(int,auto) ruid(string) username(string) domain(string,null) contact(string) received(string,null) path(string,null) expires(int) q(double) callid(string) cseq(int) last_modified(int) flags(int) cflags(int) user_agent(string) socket(string,null) methods(int,null) instance(string,null) reg_id(int) server_id(int) connection_id(int) keepalive(int) partition(int) 
diff --git a/utils/kamctl/dbtext/kamailio/presentity b/utils/kamctl/dbtext/kamailio/presentity
index 0a595e4..106289f 100644
--- a/utils/kamctl/dbtext/kamailio/presentity
+++ b/utils/kamctl/dbtext/kamailio/presentity
@@ -1 +1 @@
-id(int,auto) username(string) domain(string) event(string) etag(string) expires(int) received_time(int) body(string) sender(string) 
+id(int,auto) username(string) domain(string) event(string) etag(string) expires(int) received_time(int) body(string) sender(string) priority(int) 
diff --git a/utils/kamctl/dbtext/kamailio/silo b/utils/kamctl/dbtext/kamailio/silo
index fe19d9b..6e1f609 100644
--- a/utils/kamctl/dbtext/kamailio/silo
+++ b/utils/kamctl/dbtext/kamailio/silo
@@ -1 +1 @@
-id(int,auto) src_addr(string) dst_addr(string) username(string) domain(string) inc_time(int) exp_time(int) snd_time(int) ctype(string) body(string) extra_hdrs(string) callid(string) status(int) 
+id(int,auto) src_addr(string) dst_addr(string) username(string) domain(string) inc_time(int) exp_time(int) snd_time(int) ctype(string) body(string,null) extra_hdrs(string,null) callid(string) status(int) 
diff --git a/utils/kamctl/dbtext/kamailio/sip_trace b/utils/kamctl/dbtext/kamailio/sip_trace
index c9402e7..458c8c5 100644
--- a/utils/kamctl/dbtext/kamailio/sip_trace
+++ b/utils/kamctl/dbtext/kamailio/sip_trace
@@ -1 +1 @@
-id(int,auto) time_stamp(int) time_us(int) callid(string) traced_user(string) msg(string) method(string) status(string) fromip(string) toip(string) fromtag(string) direction(string) 
+id(int,auto) time_stamp(int) time_us(int) callid(string) traced_user(string) msg(string) method(string) status(string) fromip(string) toip(string) fromtag(string) totag(string) direction(string) 
diff --git a/utils/kamctl/dbtext/kamailio/subscriber b/utils/kamctl/dbtext/kamailio/subscriber
index bb335c0..05f626c 100644
--- a/utils/kamctl/dbtext/kamailio/subscriber
+++ b/utils/kamctl/dbtext/kamailio/subscriber
@@ -1 +1 @@
-id(int,auto) username(string) domain(string) password(string) email_address(string,null) ha1(string,null) ha1b(string,null) rpid(string,null) 
+id(int,auto) username(string) domain(string) password(string) email_address(string) ha1(string) ha1b(string) rpid(string,null) 
diff --git a/utils/kamctl/dbtext/kamailio/version b/utils/kamctl/dbtext/kamailio/version
index 94aad98..3d92d61 100644
--- a/utils/kamctl/dbtext/kamailio/version
+++ b/utils/kamctl/dbtext/kamailio/version
@@ -1,9 +1,9 @@
 table_name(string) table_version(int) 
 acc:5
-acc_cdrs:1
+acc_cdrs:2
 active_watchers:11
 address:6
-aliases:6
+aliases:8
 carrier_name:1
 carrierfailureroute:2
 carrierroute:3
@@ -29,7 +29,7 @@ imc_rooms:1
 lcr_gw:3
 lcr_rule:2
 lcr_rule_target:1
-location:6
+location:8
 location_attrs:1
 matrix:1
 missed_calls:4
@@ -39,7 +39,7 @@ mtree:1
 mtrees:2
 pdt:1
 pl_pipes:1
-presentity:3
+presentity:4
 pua:7
 purplemap:1
 re_grp:1
@@ -47,8 +47,8 @@ rls_presentity:1
 rls_watchers:3
 rtpproxy:1
 sca_subscriptions:1
-silo:7
-sip_trace:3
+silo:8
+sip_trace:4
 speed_dial:2
 subscriber:6
 trusted:5
diff --git a/utils/kamctl/kamctl.fifo b/utils/kamctl/kamctl.fifo
index e57c7df..c94a5cc 100644
--- a/utils/kamctl/kamctl.fifo
+++ b/utils/kamctl/kamctl.fifo
@@ -25,7 +25,7 @@ fi
 #
 if [ -z "$FIFOPATH" ]; then
 	if [ -z "$OSER_FIFO" ]; then
-		FIFOPATH=/tmp/kamailio_fifo
+		FIFOPATH=/var/run/kamailio/kamailio_fifo
 	else
 		FIFOPATH=$OSER_FIFO
 	fi
diff --git a/utils/kamctl/kamctlrc b/utils/kamctl/kamctlrc
index b8b241b..f96cab6 100644
--- a/utils/kamctl/kamctlrc
+++ b/utils/kamctl/kamctlrc
@@ -124,7 +124,7 @@
 # CTLENGINE="FIFO"
 
 ## path to FIFO file
-# FIFOPATH="/tmp/kamailio_fifo"
+# FIFOPATH="/var/run/kamailio/kamailio_fifo"
 
 ## check ACL names; default on (1); off (0)
 # VERIFY_ACL=1
@@ -142,7 +142,7 @@
 
 ## Kamailio START Options
 ## PID file path - default is: /var/run/kamailio.pid
-# PID_FILE=/var/run/kamailio.pid
+# PID_FILE=/var/run/kamailio/kamailio.pid
 
 ## Extra start options - default is: not set
 # example: start Kamailio with 64MB share memory: STARTOPTIONS="-m 64"
diff --git a/utils/kamctl/mysql/acc-create.sql b/utils/kamctl/mysql/acc-create.sql
index 04008a2..68e2e99 100644
--- a/utils/kamctl/mysql/acc-create.sql
+++ b/utils/kamctl/mysql/acc-create.sql
@@ -1,38 +1,38 @@
 INSERT INTO version (table_name, table_version) values ('acc','5');
-CREATE TABLE acc (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    method VARCHAR(16) DEFAULT '' NOT NULL,
-    from_tag VARCHAR(64) DEFAULT '' NOT NULL,
-    to_tag VARCHAR(64) DEFAULT '' NOT NULL,
-    callid VARCHAR(255) DEFAULT '' NOT NULL,
-    sip_code VARCHAR(3) DEFAULT '' NOT NULL,
-    sip_reason VARCHAR(128) DEFAULT '' NOT NULL,
-    time DATETIME NOT NULL
+CREATE TABLE `acc` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `method` VARCHAR(16) DEFAULT '' NOT NULL,
+    `from_tag` VARCHAR(64) DEFAULT '' NOT NULL,
+    `to_tag` VARCHAR(64) DEFAULT '' NOT NULL,
+    `callid` VARCHAR(255) DEFAULT '' NOT NULL,
+    `sip_code` VARCHAR(3) DEFAULT '' NOT NULL,
+    `sip_reason` VARCHAR(128) DEFAULT '' NOT NULL,
+    `time` DATETIME NOT NULL
 );
 
-CREATE INDEX callid_idx ON acc (callid);
+CREATE INDEX callid_idx ON acc (`callid`);
 
-INSERT INTO version (table_name, table_version) values ('acc_cdrs','1');
-CREATE TABLE acc_cdrs (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    start_time VARCHAR(32) DEFAULT '' NOT NULL,
-    end_time VARCHAR(32) DEFAULT '' NOT NULL,
-    duration VARCHAR(32) DEFAULT '' NOT NULL
+INSERT INTO version (table_name, table_version) values ('acc_cdrs','2');
+CREATE TABLE `acc_cdrs` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `start_time` DATETIME DEFAULT '2000-01-01 00:00:00' NOT NULL,
+    `end_time` DATETIME DEFAULT '2000-01-01 00:00:00' NOT NULL,
+    `duration` FLOAT(10,3) DEFAULT 0 NOT NULL
 );
 
-CREATE INDEX start_time_idx ON acc_cdrs (start_time);
+CREATE INDEX start_time_idx ON acc_cdrs (`start_time`);
 
 INSERT INTO version (table_name, table_version) values ('missed_calls','4');
-CREATE TABLE missed_calls (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    method VARCHAR(16) DEFAULT '' NOT NULL,
-    from_tag VARCHAR(64) DEFAULT '' NOT NULL,
-    to_tag VARCHAR(64) DEFAULT '' NOT NULL,
-    callid VARCHAR(255) DEFAULT '' NOT NULL,
-    sip_code VARCHAR(3) DEFAULT '' NOT NULL,
-    sip_reason VARCHAR(128) DEFAULT '' NOT NULL,
-    time DATETIME NOT NULL
+CREATE TABLE `missed_calls` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `method` VARCHAR(16) DEFAULT '' NOT NULL,
+    `from_tag` VARCHAR(64) DEFAULT '' NOT NULL,
+    `to_tag` VARCHAR(64) DEFAULT '' NOT NULL,
+    `callid` VARCHAR(255) DEFAULT '' NOT NULL,
+    `sip_code` VARCHAR(3) DEFAULT '' NOT NULL,
+    `sip_reason` VARCHAR(128) DEFAULT '' NOT NULL,
+    `time` DATETIME NOT NULL
 );
 
-CREATE INDEX callid_idx ON missed_calls (callid);
+CREATE INDEX callid_idx ON missed_calls (`callid`);
 
diff --git a/utils/kamctl/mysql/alias_db-create.sql b/utils/kamctl/mysql/alias_db-create.sql
index 86fe793..e6855c6 100644
--- a/utils/kamctl/mysql/alias_db-create.sql
+++ b/utils/kamctl/mysql/alias_db-create.sql
@@ -1,13 +1,13 @@
 INSERT INTO version (table_name, table_version) values ('dbaliases','1');
-CREATE TABLE dbaliases (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    alias_username VARCHAR(64) DEFAULT '' NOT NULL,
-    alias_domain VARCHAR(64) DEFAULT '' NOT NULL,
-    username VARCHAR(64) DEFAULT '' NOT NULL,
-    domain VARCHAR(64) DEFAULT '' NOT NULL
+CREATE TABLE `dbaliases` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `alias_username` VARCHAR(64) DEFAULT '' NOT NULL,
+    `alias_domain` VARCHAR(64) DEFAULT '' NOT NULL,
+    `username` VARCHAR(64) DEFAULT '' NOT NULL,
+    `domain` VARCHAR(64) DEFAULT '' NOT NULL
 );
 
-CREATE INDEX alias_user_idx ON dbaliases (alias_username);
-CREATE INDEX alias_idx ON dbaliases (alias_username, alias_domain);
-CREATE INDEX target_idx ON dbaliases (username, domain);
+CREATE INDEX alias_user_idx ON dbaliases (`alias_username`);
+CREATE INDEX alias_idx ON dbaliases (`alias_username`, `alias_domain`);
+CREATE INDEX target_idx ON dbaliases (`username`, `domain`);
 
diff --git a/utils/kamctl/mysql/auth_db-create.sql b/utils/kamctl/mysql/auth_db-create.sql
index cb83c52..5baf1b7 100644
--- a/utils/kamctl/mysql/auth_db-create.sql
+++ b/utils/kamctl/mysql/auth_db-create.sql
@@ -1,15 +1,15 @@
 INSERT INTO version (table_name, table_version) values ('subscriber','6');
-CREATE TABLE subscriber (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    username VARCHAR(64) DEFAULT '' NOT NULL,
-    domain VARCHAR(64) DEFAULT '' NOT NULL,
-    password VARCHAR(25) DEFAULT '' NOT NULL,
-    email_address VARCHAR(64) DEFAULT '' NOT NULL,
-    ha1 VARCHAR(64) DEFAULT '' NOT NULL,
-    ha1b VARCHAR(64) DEFAULT '' NOT NULL,
-    rpid VARCHAR(64) DEFAULT NULL,
-    CONSTRAINT account_idx UNIQUE (username, domain)
+CREATE TABLE `subscriber` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `username` VARCHAR(64) DEFAULT '' NOT NULL,
+    `domain` VARCHAR(64) DEFAULT '' NOT NULL,
+    `password` VARCHAR(25) DEFAULT '' NOT NULL,
+    `email_address` VARCHAR(64) DEFAULT '' NOT NULL,
+    `ha1` VARCHAR(64) DEFAULT '' NOT NULL,
+    `ha1b` VARCHAR(64) DEFAULT '' NOT NULL,
+    `rpid` VARCHAR(64) DEFAULT NULL,
+    CONSTRAINT account_idx UNIQUE (`username`, `domain`)
 );
 
-CREATE INDEX username_idx ON subscriber (username);
+CREATE INDEX username_idx ON subscriber (`username`);
 
diff --git a/utils/kamctl/mysql/avpops-create.sql b/utils/kamctl/mysql/avpops-create.sql
index bcaaf72..6d9f739 100644
--- a/utils/kamctl/mysql/avpops-create.sql
+++ b/utils/kamctl/mysql/avpops-create.sql
@@ -1,15 +1,15 @@
 INSERT INTO version (table_name, table_version) values ('usr_preferences','2');
-CREATE TABLE usr_preferences (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    uuid VARCHAR(64) DEFAULT '' NOT NULL,
-    username VARCHAR(128) DEFAULT 0 NOT NULL,
-    domain VARCHAR(64) DEFAULT '' NOT NULL,
-    attribute VARCHAR(32) DEFAULT '' NOT NULL,
-    type INT(11) DEFAULT 0 NOT NULL,
-    value VARCHAR(128) DEFAULT '' NOT NULL,
-    last_modified DATETIME DEFAULT '1900-01-01 00:00:01' NOT NULL
+CREATE TABLE `usr_preferences` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `uuid` VARCHAR(64) DEFAULT '' NOT NULL,
+    `username` VARCHAR(128) DEFAULT 0 NOT NULL,
+    `domain` VARCHAR(64) DEFAULT '' NOT NULL,
+    `attribute` VARCHAR(32) DEFAULT '' NOT NULL,
+    `type` INT(11) DEFAULT 0 NOT NULL,
+    `value` VARCHAR(128) DEFAULT '' NOT NULL,
+    `last_modified` DATETIME DEFAULT '1900-01-01 00:00:01' NOT NULL
 );
 
-CREATE INDEX ua_idx ON usr_preferences (uuid, attribute);
-CREATE INDEX uda_idx ON usr_preferences (username, domain, attribute);
+CREATE INDEX ua_idx ON usr_preferences (`uuid`, `attribute`);
+CREATE INDEX uda_idx ON usr_preferences (`username`, `domain`, `attribute`);
 
diff --git a/utils/kamctl/mysql/carrierroute-create.sql b/utils/kamctl/mysql/carrierroute-create.sql
index f937bf0..a8f74fd 100644
--- a/utils/kamctl/mysql/carrierroute-create.sql
+++ b/utils/kamctl/mysql/carrierroute-create.sql
@@ -1,42 +1,42 @@
 INSERT INTO version (table_name, table_version) values ('carrierroute','3');
-CREATE TABLE carrierroute (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    carrier INT(10) UNSIGNED DEFAULT 0 NOT NULL,
-    domain INT(10) UNSIGNED DEFAULT 0 NOT NULL,
-    scan_prefix VARCHAR(64) DEFAULT '' NOT NULL,
-    flags INT(11) UNSIGNED DEFAULT 0 NOT NULL,
-    mask INT(11) UNSIGNED DEFAULT 0 NOT NULL,
-    prob FLOAT DEFAULT 0 NOT NULL,
-    strip INT(11) UNSIGNED DEFAULT 0 NOT NULL,
-    rewrite_host VARCHAR(128) DEFAULT '' NOT NULL,
-    rewrite_prefix VARCHAR(64) DEFAULT '' NOT NULL,
-    rewrite_suffix VARCHAR(64) DEFAULT '' NOT NULL,
-    description VARCHAR(255) DEFAULT NULL
+CREATE TABLE `carrierroute` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `carrier` INT(10) UNSIGNED DEFAULT 0 NOT NULL,
+    `domain` INT(10) UNSIGNED DEFAULT 0 NOT NULL,
+    `scan_prefix` VARCHAR(64) DEFAULT '' NOT NULL,
+    `flags` INT(11) UNSIGNED DEFAULT 0 NOT NULL,
+    `mask` INT(11) UNSIGNED DEFAULT 0 NOT NULL,
+    `prob` FLOAT DEFAULT 0 NOT NULL,
+    `strip` INT(11) UNSIGNED DEFAULT 0 NOT NULL,
+    `rewrite_host` VARCHAR(128) DEFAULT '' NOT NULL,
+    `rewrite_prefix` VARCHAR(64) DEFAULT '' NOT NULL,
+    `rewrite_suffix` VARCHAR(64) DEFAULT '' NOT NULL,
+    `description` VARCHAR(255) DEFAULT NULL
 );
 
 INSERT INTO version (table_name, table_version) values ('carrierfailureroute','2');
-CREATE TABLE carrierfailureroute (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    carrier INT(10) UNSIGNED DEFAULT 0 NOT NULL,
-    domain INT(10) UNSIGNED DEFAULT 0 NOT NULL,
-    scan_prefix VARCHAR(64) DEFAULT '' NOT NULL,
-    host_name VARCHAR(128) DEFAULT '' NOT NULL,
-    reply_code VARCHAR(3) DEFAULT '' NOT NULL,
-    flags INT(11) UNSIGNED DEFAULT 0 NOT NULL,
-    mask INT(11) UNSIGNED DEFAULT 0 NOT NULL,
-    next_domain INT(10) UNSIGNED DEFAULT 0 NOT NULL,
-    description VARCHAR(255) DEFAULT NULL
+CREATE TABLE `carrierfailureroute` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `carrier` INT(10) UNSIGNED DEFAULT 0 NOT NULL,
+    `domain` INT(10) UNSIGNED DEFAULT 0 NOT NULL,
+    `scan_prefix` VARCHAR(64) DEFAULT '' NOT NULL,
+    `host_name` VARCHAR(128) DEFAULT '' NOT NULL,
+    `reply_code` VARCHAR(3) DEFAULT '' NOT NULL,
+    `flags` INT(11) UNSIGNED DEFAULT 0 NOT NULL,
+    `mask` INT(11) UNSIGNED DEFAULT 0 NOT NULL,
+    `next_domain` INT(10) UNSIGNED DEFAULT 0 NOT NULL,
+    `description` VARCHAR(255) DEFAULT NULL
 );
 
 INSERT INTO version (table_name, table_version) values ('carrier_name','1');
-CREATE TABLE carrier_name (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    carrier VARCHAR(64) DEFAULT NULL
+CREATE TABLE `carrier_name` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `carrier` VARCHAR(64) DEFAULT NULL
 );
 
 INSERT INTO version (table_name, table_version) values ('domain_name','1');
-CREATE TABLE domain_name (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    domain VARCHAR(64) DEFAULT NULL
+CREATE TABLE `domain_name` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `domain` VARCHAR(64) DEFAULT NULL
 );
 
diff --git a/utils/kamctl/mysql/cpl-create.sql b/utils/kamctl/mysql/cpl-create.sql
index 7d06ed4..d209c9d 100644
--- a/utils/kamctl/mysql/cpl-create.sql
+++ b/utils/kamctl/mysql/cpl-create.sql
@@ -1,10 +1,10 @@
 INSERT INTO version (table_name, table_version) values ('cpl','1');
-CREATE TABLE cpl (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    username VARCHAR(64) NOT NULL,
-    domain VARCHAR(64) DEFAULT '' NOT NULL,
-    cpl_xml TEXT,
-    cpl_bin TEXT,
-    CONSTRAINT account_idx UNIQUE (username, domain)
+CREATE TABLE `cpl` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `username` VARCHAR(64) NOT NULL,
+    `domain` VARCHAR(64) DEFAULT '' NOT NULL,
+    `cpl_xml` TEXT,
+    `cpl_bin` TEXT,
+    CONSTRAINT account_idx UNIQUE (`username`, `domain`)
 );
 
diff --git a/utils/kamctl/mysql/dialog-create.sql b/utils/kamctl/mysql/dialog-create.sql
index ab9ba4b..d6a0ce7 100644
--- a/utils/kamctl/mysql/dialog-create.sql
+++ b/utils/kamctl/mysql/dialog-create.sql
@@ -1,41 +1,41 @@
 INSERT INTO version (table_name, table_version) values ('dialog','7');
-CREATE TABLE dialog (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    hash_entry INT(10) UNSIGNED NOT NULL,
-    hash_id INT(10) UNSIGNED NOT NULL,
-    callid VARCHAR(255) NOT NULL,
-    from_uri VARCHAR(128) NOT NULL,
-    from_tag VARCHAR(64) NOT NULL,
-    to_uri VARCHAR(128) NOT NULL,
-    to_tag VARCHAR(64) NOT NULL,
-    caller_cseq VARCHAR(20) NOT NULL,
-    callee_cseq VARCHAR(20) NOT NULL,
-    caller_route_set VARCHAR(512),
-    callee_route_set VARCHAR(512),
-    caller_contact VARCHAR(128) NOT NULL,
-    callee_contact VARCHAR(128) NOT NULL,
-    caller_sock VARCHAR(64) NOT NULL,
-    callee_sock VARCHAR(64) NOT NULL,
-    state INT(10) UNSIGNED NOT NULL,
-    start_time INT(10) UNSIGNED NOT NULL,
-    timeout INT(10) UNSIGNED DEFAULT 0 NOT NULL,
-    sflags INT(10) UNSIGNED DEFAULT 0 NOT NULL,
-    iflags INT(10) UNSIGNED DEFAULT 0 NOT NULL,
-    toroute_name VARCHAR(32),
-    req_uri VARCHAR(128) NOT NULL,
-    xdata VARCHAR(512)
+CREATE TABLE `dialog` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `hash_entry` INT(10) UNSIGNED NOT NULL,
+    `hash_id` INT(10) UNSIGNED NOT NULL,
+    `callid` VARCHAR(255) NOT NULL,
+    `from_uri` VARCHAR(128) NOT NULL,
+    `from_tag` VARCHAR(64) NOT NULL,
+    `to_uri` VARCHAR(128) NOT NULL,
+    `to_tag` VARCHAR(64) NOT NULL,
+    `caller_cseq` VARCHAR(20) NOT NULL,
+    `callee_cseq` VARCHAR(20) NOT NULL,
+    `caller_route_set` VARCHAR(512),
+    `callee_route_set` VARCHAR(512),
+    `caller_contact` VARCHAR(128) NOT NULL,
+    `callee_contact` VARCHAR(128) NOT NULL,
+    `caller_sock` VARCHAR(64) NOT NULL,
+    `callee_sock` VARCHAR(64) NOT NULL,
+    `state` INT(10) UNSIGNED NOT NULL,
+    `start_time` INT(10) UNSIGNED NOT NULL,
+    `timeout` INT(10) UNSIGNED DEFAULT 0 NOT NULL,
+    `sflags` INT(10) UNSIGNED DEFAULT 0 NOT NULL,
+    `iflags` INT(10) UNSIGNED DEFAULT 0 NOT NULL,
+    `toroute_name` VARCHAR(32),
+    `req_uri` VARCHAR(128) NOT NULL,
+    `xdata` VARCHAR(512)
 );
 
-CREATE INDEX hash_idx ON dialog (hash_entry, hash_id);
+CREATE INDEX hash_idx ON dialog (`hash_entry`, `hash_id`);
 
 INSERT INTO version (table_name, table_version) values ('dialog_vars','1');
-CREATE TABLE dialog_vars (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    hash_entry INT(10) UNSIGNED NOT NULL,
-    hash_id INT(10) UNSIGNED NOT NULL,
-    dialog_key VARCHAR(128) NOT NULL,
-    dialog_value VARCHAR(512) NOT NULL
+CREATE TABLE `dialog_vars` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `hash_entry` INT(10) UNSIGNED NOT NULL,
+    `hash_id` INT(10) UNSIGNED NOT NULL,
+    `dialog_key` VARCHAR(128) NOT NULL,
+    `dialog_value` VARCHAR(512) NOT NULL
 );
 
-CREATE INDEX hash_idx ON dialog_vars (hash_entry, hash_id);
+CREATE INDEX hash_idx ON dialog_vars (`hash_entry`, `hash_id`);
 
diff --git a/utils/kamctl/mysql/dialog_ng-create.sql b/utils/kamctl/mysql/dialog_ng-create.sql
new file mode 100644
index 0000000..8a8cbde
--- /dev/null
+++ b/utils/kamctl/mysql/dialog_ng-create.sql
@@ -0,0 +1,52 @@
+INSERT INTO version (table_name, table_version) values ('dialog_in', 7), ('dialog_out', 7), ('dialog_vars', 7);
+
+CREATE TABLE `dialog_in` (
+  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+  `hash_entry` int(10) unsigned NOT NULL,
+  `hash_id` int(10) unsigned NOT NULL,
+  `did` varchar(45) NOT NULL,
+  `callid` varchar(255) NOT NULL,
+  `from_uri` varchar(128) NOT NULL,
+  `from_tag` varchar(64) NOT NULL,
+  `caller_original_cseq` varchar(20) NOT NULL,
+  `req_uri` varchar(128) NOT NULL,
+  `caller_route_set` varchar(512) DEFAULT NULL,
+  `caller_contact` varchar(128) NOT NULL,
+  `caller_sock` varchar(64) NOT NULL,
+  `state` int(10) unsigned NOT NULL,
+  `start_time` int(10) unsigned NOT NULL,
+  `timeout` int(10) unsigned NOT NULL DEFAULT '0',
+  `sflags` int(10) unsigned NOT NULL DEFAULT '0',
+  `toroute_name` varchar(32) DEFAULT NULL,
+  `toroute_index` int(11) DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `hash_idx` (`hash_entry`,`hash_id`)
+);
+
+CREATE TABLE `dialog_out` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `hash_entry` int(11) NOT NULL,
+  `hash_id` int(11) NOT NULL,
+  `did` varchar(45) NOT NULL,
+  `to_uri` varchar(128) NOT NULL,
+  `to_tag` varchar(64) NOT NULL,
+  `caller_cseq` varchar(20) NOT NULL,
+  `callee_cseq` varchar(20) NOT NULL,
+  `callee_contact` varchar(128) NOT NULL,
+  `callee_route_set` varchar(512) DEFAULT NULL,
+  `callee_sock` varchar(64) NOT NULL,
+  PRIMARY KEY (`id`)
+);
+
+CREATE TABLE `dialog_vars` (
+  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+  `hash_entry` int(10) unsigned NOT NULL,
+  `hash_id` int(10) unsigned NOT NULL,
+  `dialog_key` varchar(128) NOT NULL,
+  `dialog_value` varchar(512) NOT NULL,
+  PRIMARY KEY (`id`),
+  KEY `hash_idx` (`hash_entry`,`hash_id`)
+);
+
+
+
diff --git a/utils/kamctl/mysql/dialplan-create.sql b/utils/kamctl/mysql/dialplan-create.sql
index b94e7aa..2bd2e8f 100644
--- a/utils/kamctl/mysql/dialplan-create.sql
+++ b/utils/kamctl/mysql/dialplan-create.sql
@@ -1,13 +1,13 @@
 INSERT INTO version (table_name, table_version) values ('dialplan','2');
-CREATE TABLE dialplan (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    dpid INT(11) NOT NULL,
-    pr INT(11) NOT NULL,
-    match_op INT(11) NOT NULL,
-    match_exp VARCHAR(64) NOT NULL,
-    match_len INT(11) NOT NULL,
-    subst_exp VARCHAR(64) NOT NULL,
-    repl_exp VARCHAR(64) NOT NULL,
-    attrs VARCHAR(64) NOT NULL
+CREATE TABLE `dialplan` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `dpid` INT(11) NOT NULL,
+    `pr` INT(11) NOT NULL,
+    `match_op` INT(11) NOT NULL,
+    `match_exp` VARCHAR(64) NOT NULL,
+    `match_len` INT(11) NOT NULL,
+    `subst_exp` VARCHAR(64) NOT NULL,
+    `repl_exp` VARCHAR(64) NOT NULL,
+    `attrs` VARCHAR(64) NOT NULL
 );
 
diff --git a/utils/kamctl/mysql/dispatcher-create.sql b/utils/kamctl/mysql/dispatcher-create.sql
index 4e82750..127bd72 100644
--- a/utils/kamctl/mysql/dispatcher-create.sql
+++ b/utils/kamctl/mysql/dispatcher-create.sql
@@ -1,11 +1,11 @@
 INSERT INTO version (table_name, table_version) values ('dispatcher','4');
-CREATE TABLE dispatcher (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    setid INT DEFAULT 0 NOT NULL,
-    destination VARCHAR(192) DEFAULT '' NOT NULL,
-    flags INT DEFAULT 0 NOT NULL,
-    priority INT DEFAULT 0 NOT NULL,
-    attrs VARCHAR(128) DEFAULT '' NOT NULL,
-    description VARCHAR(64) DEFAULT '' NOT NULL
+CREATE TABLE `dispatcher` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `setid` INT DEFAULT 0 NOT NULL,
+    `destination` VARCHAR(192) DEFAULT '' NOT NULL,
+    `flags` INT DEFAULT 0 NOT NULL,
+    `priority` INT DEFAULT 0 NOT NULL,
+    `attrs` VARCHAR(128) DEFAULT '' NOT NULL,
+    `description` VARCHAR(64) DEFAULT '' NOT NULL
 );
 
diff --git a/utils/kamctl/mysql/domain-create.sql b/utils/kamctl/mysql/domain-create.sql
index 7ab9e7d..d828dc2 100644
--- a/utils/kamctl/mysql/domain-create.sql
+++ b/utils/kamctl/mysql/domain-create.sql
@@ -1,20 +1,20 @@
 INSERT INTO version (table_name, table_version) values ('domain','2');
-CREATE TABLE domain (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    domain VARCHAR(64) NOT NULL,
-    did VARCHAR(64) DEFAULT NULL,
-    last_modified DATETIME DEFAULT '1900-01-01 00:00:01' NOT NULL,
-    CONSTRAINT domain_idx UNIQUE (domain)
+CREATE TABLE `domain` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `domain` VARCHAR(64) NOT NULL,
+    `did` VARCHAR(64) DEFAULT NULL,
+    `last_modified` DATETIME DEFAULT '1900-01-01 00:00:01' NOT NULL,
+    CONSTRAINT domain_idx UNIQUE (`domain`)
 );
 
 INSERT INTO version (table_name, table_version) values ('domain_attrs','1');
-CREATE TABLE domain_attrs (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    did VARCHAR(64) NOT NULL,
-    name VARCHAR(32) NOT NULL,
-    type INT UNSIGNED NOT NULL,
-    value VARCHAR(255) NOT NULL,
-    last_modified DATETIME DEFAULT '1900-01-01 00:00:01' NOT NULL,
-    CONSTRAINT domain_attrs_idx UNIQUE (did, name, value)
+CREATE TABLE `domain_attrs` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `did` VARCHAR(64) NOT NULL,
+    `name` VARCHAR(32) NOT NULL,
+    `type` INT UNSIGNED NOT NULL,
+    `value` VARCHAR(255) NOT NULL,
+    `last_modified` DATETIME DEFAULT '1900-01-01 00:00:01' NOT NULL,
+    CONSTRAINT domain_attrs_idx UNIQUE (`did`, `name`, `value`)
 );
 
diff --git a/utils/kamctl/mysql/domainpolicy-create.sql b/utils/kamctl/mysql/domainpolicy-create.sql
index e68ff88..373faf1 100644
--- a/utils/kamctl/mysql/domainpolicy-create.sql
+++ b/utils/kamctl/mysql/domainpolicy-create.sql
@@ -1,13 +1,13 @@
 INSERT INTO version (table_name, table_version) values ('domainpolicy','2');
-CREATE TABLE domainpolicy (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    rule VARCHAR(255) NOT NULL,
-    type VARCHAR(255) NOT NULL,
-    att VARCHAR(255),
-    val VARCHAR(128),
-    description VARCHAR(255) NOT NULL,
-    CONSTRAINT rav_idx UNIQUE (rule, att, val)
+CREATE TABLE `domainpolicy` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `rule` VARCHAR(255) NOT NULL,
+    `type` VARCHAR(255) NOT NULL,
+    `att` VARCHAR(255),
+    `val` VARCHAR(128),
+    `description` VARCHAR(255) NOT NULL,
+    CONSTRAINT rav_idx UNIQUE (`rule`, `att`, `val`)
 );
 
-CREATE INDEX rule_idx ON domainpolicy (rule);
+CREATE INDEX rule_idx ON domainpolicy (`rule`);
 
diff --git a/utils/kamctl/mysql/drouting-create.sql b/utils/kamctl/mysql/drouting-create.sql
index c53450d..7a94148 100644
--- a/utils/kamctl/mysql/drouting-create.sql
+++ b/utils/kamctl/mysql/drouting-create.sql
@@ -1,39 +1,39 @@
 INSERT INTO version (table_name, table_version) values ('dr_gateways','3');
-CREATE TABLE dr_gateways (
-    gwid INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    type INT(11) UNSIGNED DEFAULT 0 NOT NULL,
-    address VARCHAR(128) NOT NULL,
-    strip INT(11) UNSIGNED DEFAULT 0 NOT NULL,
-    pri_prefix VARCHAR(64) DEFAULT NULL,
-    attrs VARCHAR(255) DEFAULT NULL,
-    description VARCHAR(128) DEFAULT '' NOT NULL
+CREATE TABLE `dr_gateways` (
+    `gwid` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `type` INT(11) UNSIGNED DEFAULT 0 NOT NULL,
+    `address` VARCHAR(128) NOT NULL,
+    `strip` INT(11) UNSIGNED DEFAULT 0 NOT NULL,
+    `pri_prefix` VARCHAR(64) DEFAULT NULL,
+    `attrs` VARCHAR(255) DEFAULT NULL,
+    `description` VARCHAR(128) DEFAULT '' NOT NULL
 );
 
 INSERT INTO version (table_name, table_version) values ('dr_rules','3');
-CREATE TABLE dr_rules (
-    ruleid INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    groupid VARCHAR(255) NOT NULL,
-    prefix VARCHAR(64) NOT NULL,
-    timerec VARCHAR(255) NOT NULL,
-    priority INT(11) DEFAULT 0 NOT NULL,
-    routeid VARCHAR(64) NOT NULL,
-    gwlist VARCHAR(255) NOT NULL,
-    description VARCHAR(128) DEFAULT '' NOT NULL
+CREATE TABLE `dr_rules` (
+    `ruleid` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `groupid` VARCHAR(255) NOT NULL,
+    `prefix` VARCHAR(64) NOT NULL,
+    `timerec` VARCHAR(255) NOT NULL,
+    `priority` INT(11) DEFAULT 0 NOT NULL,
+    `routeid` VARCHAR(64) NOT NULL,
+    `gwlist` VARCHAR(255) NOT NULL,
+    `description` VARCHAR(128) DEFAULT '' NOT NULL
 );
 
 INSERT INTO version (table_name, table_version) values ('dr_gw_lists','1');
-CREATE TABLE dr_gw_lists (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    gwlist VARCHAR(255) NOT NULL,
-    description VARCHAR(128) DEFAULT '' NOT NULL
+CREATE TABLE `dr_gw_lists` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `gwlist` VARCHAR(255) NOT NULL,
+    `description` VARCHAR(128) DEFAULT '' NOT NULL
 );
 
 INSERT INTO version (table_name, table_version) values ('dr_groups','2');
-CREATE TABLE dr_groups (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    username VARCHAR(64) NOT NULL,
-    domain VARCHAR(128) DEFAULT '' NOT NULL,
-    groupid INT(11) UNSIGNED DEFAULT 0 NOT NULL,
-    description VARCHAR(128) DEFAULT '' NOT NULL
+CREATE TABLE `dr_groups` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `username` VARCHAR(64) NOT NULL,
+    `domain` VARCHAR(128) DEFAULT '' NOT NULL,
+    `groupid` INT(11) UNSIGNED DEFAULT 0 NOT NULL,
+    `description` VARCHAR(128) DEFAULT '' NOT NULL
 );
 
diff --git a/utils/kamctl/mysql/group-create.sql b/utils/kamctl/mysql/group-create.sql
index 8632a35..7c271f5 100644
--- a/utils/kamctl/mysql/group-create.sql
+++ b/utils/kamctl/mysql/group-create.sql
@@ -1,19 +1,19 @@
 INSERT INTO version (table_name, table_version) values ('grp','2');
-CREATE TABLE grp (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    username VARCHAR(64) DEFAULT '' NOT NULL,
-    domain VARCHAR(64) DEFAULT '' NOT NULL,
-    grp VARCHAR(64) DEFAULT '' NOT NULL,
-    last_modified DATETIME DEFAULT '1900-01-01 00:00:01' NOT NULL,
-    CONSTRAINT account_group_idx UNIQUE (username, domain, grp)
+CREATE TABLE `grp` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `username` VARCHAR(64) DEFAULT '' NOT NULL,
+    `domain` VARCHAR(64) DEFAULT '' NOT NULL,
+    `grp` VARCHAR(64) DEFAULT '' NOT NULL,
+    `last_modified` DATETIME DEFAULT '1900-01-01 00:00:01' NOT NULL,
+    CONSTRAINT account_group_idx UNIQUE (`username`, `domain`, `grp`)
 );
 
 INSERT INTO version (table_name, table_version) values ('re_grp','1');
-CREATE TABLE re_grp (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    reg_exp VARCHAR(128) DEFAULT '' NOT NULL,
-    group_id INT(11) DEFAULT 0 NOT NULL
+CREATE TABLE `re_grp` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `reg_exp` VARCHAR(128) DEFAULT '' NOT NULL,
+    `group_id` INT(11) DEFAULT 0 NOT NULL
 );
 
-CREATE INDEX group_idx ON re_grp (group_id);
+CREATE INDEX group_idx ON re_grp (`group_id`);
 
diff --git a/utils/kamctl/mysql/htable-create.sql b/utils/kamctl/mysql/htable-create.sql
index afd3b13..7b5efea 100644
--- a/utils/kamctl/mysql/htable-create.sql
+++ b/utils/kamctl/mysql/htable-create.sql
@@ -1,10 +1,10 @@
 INSERT INTO version (table_name, table_version) values ('htable','2');
-CREATE TABLE htable (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    key_name VARCHAR(64) DEFAULT '' NOT NULL,
-    key_type INT DEFAULT 0 NOT NULL,
-    value_type INT DEFAULT 0 NOT NULL,
-    key_value VARCHAR(128) DEFAULT '' NOT NULL,
-    expires INT DEFAULT 0 NOT NULL
+CREATE TABLE `htable` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `key_name` VARCHAR(64) DEFAULT '' NOT NULL,
+    `key_type` INT DEFAULT 0 NOT NULL,
+    `value_type` INT DEFAULT 0 NOT NULL,
+    `key_value` VARCHAR(128) DEFAULT '' NOT NULL,
+    `expires` INT DEFAULT 0 NOT NULL
 );
 
diff --git a/utils/kamctl/mysql/imc-create.sql b/utils/kamctl/mysql/imc-create.sql
index 6ab767d..e884d65 100644
--- a/utils/kamctl/mysql/imc-create.sql
+++ b/utils/kamctl/mysql/imc-create.sql
@@ -1,19 +1,19 @@
 INSERT INTO version (table_name, table_version) values ('imc_rooms','1');
-CREATE TABLE imc_rooms (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    name VARCHAR(64) NOT NULL,
-    domain VARCHAR(64) NOT NULL,
-    flag INT(11) NOT NULL,
-    CONSTRAINT name_domain_idx UNIQUE (name, domain)
+CREATE TABLE `imc_rooms` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `name` VARCHAR(64) NOT NULL,
+    `domain` VARCHAR(64) NOT NULL,
+    `flag` INT(11) NOT NULL,
+    CONSTRAINT name_domain_idx UNIQUE (`name`, `domain`)
 );
 
 INSERT INTO version (table_name, table_version) values ('imc_members','1');
-CREATE TABLE imc_members (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    username VARCHAR(64) NOT NULL,
-    domain VARCHAR(64) NOT NULL,
-    room VARCHAR(64) NOT NULL,
-    flag INT(11) NOT NULL,
-    CONSTRAINT account_room_idx UNIQUE (username, domain, room)
+CREATE TABLE `imc_members` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `username` VARCHAR(64) NOT NULL,
+    `domain` VARCHAR(64) NOT NULL,
+    `room` VARCHAR(64) NOT NULL,
+    `flag` INT(11) NOT NULL,
+    CONSTRAINT account_room_idx UNIQUE (`username`, `domain`, `room`)
 );
 
diff --git a/utils/kamctl/mysql/ims_charging_create.sql b/utils/kamctl/mysql/ims_charging_create.sql
new file mode 100644
index 0000000..d5e0e52
--- /dev/null
+++ b/utils/kamctl/mysql/ims_charging_create.sql
@@ -0,0 +1,24 @@
+INSERT INTO version (table_name, table_version) values ('ro_session','6');
+CREATE TABLE `ro_session` (
+  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+  `hash_entry` int(10) unsigned NOT NULL,
+  `hash_id` int(10) unsigned NOT NULL,
+  `session_id` varchar(100) NOT NULL,
+  `dlg_hash_entry` int(10) unsigned NOT NULL,
+  `dlg_hash_id` int(10) unsigned NOT NULL,
+  `direction` int(1) unsigned NOT NULL,
+  `asserted_identity` varchar(100) NOT NULL,
+  `callee` varchar(100) NOT NULL,
+  `start_time` datetime DEFAULT NULL,
+  `last_event_timestamp` datetime DEFAULT NULL,
+  `reserved_secs` int(10) DEFAULT NULL,
+  `valid_for` int(10) DEFAULT NULL,
+  `state` int(1) DEFAULT NULL,
+  `incoming_trunk_id` varchar(20) DEFAULT NULL,
+  `outgoing_trunk_id` varchar(20) DEFAULT NULL,
+  `rating_group` int(11) DEFAULT NULL,
+  `service_identifier` int(11) DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `hash_idx` (`hash_entry`,`hash_id`)
+);
+
diff --git a/utils/kamctl/mysql/ims_usrloc_scscf-create.sql b/utils/kamctl/mysql/ims_usrloc_scscf-create.sql
index fc17166..51cd30b 100644
--- a/utils/kamctl/mysql/ims_usrloc_scscf-create.sql
+++ b/utils/kamctl/mysql/ims_usrloc_scscf-create.sql
@@ -2,6 +2,7 @@ INSERT INTO version (table_name, table_version) values ('contact','6');
 CREATE TABLE `contact` (
   `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
   `contact` char(255) NOT NULL,
+  `params` varchar(255) DEFAULT NULL,
   `path` varchar(255) DEFAULT NULL,
   `received` varchar(255) DEFAULT NULL,
   `user_agent` varchar(255) DEFAULT NULL,
@@ -34,3 +35,31 @@ CREATE TABLE `impu_contact` (
   PRIMARY KEY (`id`),
   UNIQUE KEY `impu_id` (`impu_id`,`contact_id`)
 );
+
+INSERT INTO version (table_name, table_version) values ('subscriber','6');
+CREATE TABLE `subscriber` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `watcher_uri` varchar(50) NOT NULL,
+  `watcher_contact` varchar(50) NOT NULL,
+  `presentity_uri` varchar(50) NOT NULL,
+  `event` int(11) NOT NULL,
+  `expires` datetime NOT NULL,
+  `version` int(11) NOT NULL,
+  `local_cseq` int(11) NOT NULL,
+  `call_id` varchar(50) NOT NULL,
+  `from_tag` varchar(50) NOT NULL,
+  `to_tag` varchar(50) NOT NULL,
+  `record_route` varchar(50) NOT NULL,
+  `sockinfo_str` varchar(50) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `watcher_uri` (`event`,`watcher_contact`,`presentity_uri`)
+);
+
+INSERT INTO version (table_name, table_version) values ('impu_subscriber','6');
+CREATE TABLE `impu_subscriber` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `impu_id` int(11) NOT NULL,
+  `subscriber_id` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `impu_id` (`impu_id`,`subscriber_id`)
+);
diff --git a/utils/kamctl/mysql/lcr-create.sql b/utils/kamctl/mysql/lcr-create.sql
index 925a43b..b658c3c 100644
--- a/utils/kamctl/mysql/lcr-create.sql
+++ b/utils/kamctl/mysql/lcr-create.sql
@@ -1,45 +1,45 @@
 INSERT INTO version (table_name, table_version) values ('lcr_gw','3');
-CREATE TABLE lcr_gw (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    lcr_id SMALLINT UNSIGNED NOT NULL,
-    gw_name VARCHAR(128),
-    ip_addr VARCHAR(50),
-    hostname VARCHAR(64),
-    port SMALLINT UNSIGNED,
-    params VARCHAR(64),
-    uri_scheme TINYINT UNSIGNED,
-    transport TINYINT UNSIGNED,
-    strip TINYINT UNSIGNED,
-    prefix VARCHAR(16) DEFAULT NULL,
-    tag VARCHAR(64) DEFAULT NULL,
-    flags INT UNSIGNED DEFAULT 0 NOT NULL,
-    defunct INT UNSIGNED DEFAULT NULL
+CREATE TABLE `lcr_gw` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `lcr_id` SMALLINT UNSIGNED NOT NULL,
+    `gw_name` VARCHAR(128),
+    `ip_addr` VARCHAR(50),
+    `hostname` VARCHAR(64),
+    `port` SMALLINT UNSIGNED,
+    `params` VARCHAR(64),
+    `uri_scheme` TINYINT UNSIGNED,
+    `transport` TINYINT UNSIGNED,
+    `strip` TINYINT UNSIGNED,
+    `prefix` VARCHAR(16) DEFAULT NULL,
+    `tag` VARCHAR(64) DEFAULT NULL,
+    `flags` INT UNSIGNED DEFAULT 0 NOT NULL,
+    `defunct` INT UNSIGNED DEFAULT NULL
 );
 
-CREATE INDEX lcr_id_idx ON lcr_gw (lcr_id);
+CREATE INDEX lcr_id_idx ON lcr_gw (`lcr_id`);
 
 INSERT INTO version (table_name, table_version) values ('lcr_rule_target','1');
-CREATE TABLE lcr_rule_target (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    lcr_id SMALLINT UNSIGNED NOT NULL,
-    rule_id INT UNSIGNED NOT NULL,
-    gw_id INT UNSIGNED NOT NULL,
-    priority TINYINT UNSIGNED NOT NULL,
-    weight INT UNSIGNED DEFAULT 1 NOT NULL,
-    CONSTRAINT rule_id_gw_id_idx UNIQUE (rule_id, gw_id)
+CREATE TABLE `lcr_rule_target` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `lcr_id` SMALLINT UNSIGNED NOT NULL,
+    `rule_id` INT UNSIGNED NOT NULL,
+    `gw_id` INT UNSIGNED NOT NULL,
+    `priority` TINYINT UNSIGNED NOT NULL,
+    `weight` INT UNSIGNED DEFAULT 1 NOT NULL,
+    CONSTRAINT rule_id_gw_id_idx UNIQUE (`rule_id`, `gw_id`)
 );
 
-CREATE INDEX lcr_id_idx ON lcr_rule_target (lcr_id);
+CREATE INDEX lcr_id_idx ON lcr_rule_target (`lcr_id`);
 
 INSERT INTO version (table_name, table_version) values ('lcr_rule','2');
-CREATE TABLE lcr_rule (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    lcr_id SMALLINT UNSIGNED NOT NULL,
-    prefix VARCHAR(16) DEFAULT NULL,
-    from_uri VARCHAR(64) DEFAULT NULL,
-    request_uri VARCHAR(64) DEFAULT NULL,
-    stopper INT UNSIGNED DEFAULT 0 NOT NULL,
-    enabled INT UNSIGNED DEFAULT 1 NOT NULL,
-    CONSTRAINT lcr_id_prefix_from_uri_idx UNIQUE (lcr_id, prefix, from_uri)
+CREATE TABLE `lcr_rule` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `lcr_id` SMALLINT UNSIGNED NOT NULL,
+    `prefix` VARCHAR(16) DEFAULT NULL,
+    `from_uri` VARCHAR(64) DEFAULT NULL,
+    `request_uri` VARCHAR(64) DEFAULT NULL,
+    `stopper` INT UNSIGNED DEFAULT 0 NOT NULL,
+    `enabled` INT UNSIGNED DEFAULT 1 NOT NULL,
+    CONSTRAINT lcr_id_prefix_from_uri_idx UNIQUE (`lcr_id`, `prefix`, `from_uri`)
 );
 
diff --git a/utils/kamctl/mysql/matrix-create.sql b/utils/kamctl/mysql/matrix-create.sql
index 8fd87c5..467e294 100644
--- a/utils/kamctl/mysql/matrix-create.sql
+++ b/utils/kamctl/mysql/matrix-create.sql
@@ -1,9 +1,9 @@
 INSERT INTO version (table_name, table_version) values ('matrix','1');
-CREATE TABLE matrix (
-    first INT(10) NOT NULL,
-    second SMALLINT(10) NOT NULL,
-    res INT(10) NOT NULL
+CREATE TABLE `matrix` (
+    `first` INT(10) NOT NULL,
+    `second` SMALLINT(10) NOT NULL,
+    `res` INT(10) NOT NULL
 );
 
-CREATE INDEX matrix_idx ON matrix (first, second);
+CREATE INDEX matrix_idx ON matrix (`first`, `second`);
 
diff --git a/utils/kamctl/mysql/mohqueue-create.sql b/utils/kamctl/mysql/mohqueue-create.sql
index 4326fe4..a84fbfa 100644
--- a/utils/kamctl/mysql/mohqueue-create.sql
+++ b/utils/kamctl/mysql/mohqueue-create.sql
@@ -1,24 +1,24 @@
 INSERT INTO version (table_name, table_version) values ('mohqcalls','1');
-CREATE TABLE mohqcalls (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    mohq_id INT(10) UNSIGNED NOT NULL,
-    call_id VARCHAR(100) NOT NULL,
-    call_status INT UNSIGNED NOT NULL,
-    call_from VARCHAR(100) NOT NULL,
-    call_contact VARCHAR(100),
-    call_time DATETIME NOT NULL,
-    CONSTRAINT mohqcalls_idx UNIQUE (call_id)
+CREATE TABLE `mohqcalls` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `mohq_id` INT(10) UNSIGNED NOT NULL,
+    `call_id` VARCHAR(100) NOT NULL,
+    `call_status` INT UNSIGNED NOT NULL,
+    `call_from` VARCHAR(100) NOT NULL,
+    `call_contact` VARCHAR(100),
+    `call_time` DATETIME NOT NULL,
+    CONSTRAINT mohqcalls_idx UNIQUE (`call_id`)
 );
 
 INSERT INTO version (table_name, table_version) values ('mohqueues','1');
-CREATE TABLE mohqueues (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    name VARCHAR(25) NOT NULL,
-    uri VARCHAR(100) NOT NULL,
-    mohdir VARCHAR(100),
-    mohfile VARCHAR(100) NOT NULL,
-    debug INT NOT NULL,
-    CONSTRAINT mohqueue_uri_idx UNIQUE (uri),
-    CONSTRAINT mohqueue_name_idx UNIQUE (name)
+CREATE TABLE `mohqueues` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `name` VARCHAR(25) NOT NULL,
+    `uri` VARCHAR(100) NOT NULL,
+    `mohdir` VARCHAR(100),
+    `mohfile` VARCHAR(100) NOT NULL,
+    `debug` INT NOT NULL,
+    CONSTRAINT mohqueue_uri_idx UNIQUE (`uri`),
+    CONSTRAINT mohqueue_name_idx UNIQUE (`name`)
 );
 
diff --git a/utils/kamctl/mysql/msilo-create.sql b/utils/kamctl/mysql/msilo-create.sql
index 58c0f5c..85670ab 100644
--- a/utils/kamctl/mysql/msilo-create.sql
+++ b/utils/kamctl/mysql/msilo-create.sql
@@ -1,19 +1,19 @@
-INSERT INTO version (table_name, table_version) values ('silo','7');
-CREATE TABLE silo (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    src_addr VARCHAR(128) DEFAULT '' NOT NULL,
-    dst_addr VARCHAR(128) DEFAULT '' NOT NULL,
-    username VARCHAR(64) DEFAULT '' NOT NULL,
-    domain VARCHAR(64) DEFAULT '' NOT NULL,
-    inc_time INT DEFAULT 0 NOT NULL,
-    exp_time INT DEFAULT 0 NOT NULL,
-    snd_time INT DEFAULT 0 NOT NULL,
-    ctype VARCHAR(32) DEFAULT 'text/plain' NOT NULL,
-    body BLOB DEFAULT '' NOT NULL,
-    extra_hdrs TEXT DEFAULT '' NOT NULL,
-    callid VARCHAR(128) DEFAULT '' NOT NULL,
-    status INT DEFAULT 0 NOT NULL
+INSERT INTO version (table_name, table_version) values ('silo','8');
+CREATE TABLE `silo` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `src_addr` VARCHAR(128) DEFAULT '' NOT NULL,
+    `dst_addr` VARCHAR(128) DEFAULT '' NOT NULL,
+    `username` VARCHAR(64) DEFAULT '' NOT NULL,
+    `domain` VARCHAR(64) DEFAULT '' NOT NULL,
+    `inc_time` INT DEFAULT 0 NOT NULL,
+    `exp_time` INT DEFAULT 0 NOT NULL,
+    `snd_time` INT DEFAULT 0 NOT NULL,
+    `ctype` VARCHAR(32) DEFAULT 'text/plain' NOT NULL,
+    `body` BLOB,
+    `extra_hdrs` TEXT,
+    `callid` VARCHAR(128) DEFAULT '' NOT NULL,
+    `status` INT DEFAULT 0 NOT NULL
 );
 
-CREATE INDEX account_idx ON silo (username, domain);
+CREATE INDEX account_idx ON silo (`username`, `domain`);
 
diff --git a/utils/kamctl/mysql/mtree-create.sql b/utils/kamctl/mysql/mtree-create.sql
index 785d60f..ba2ac6e 100644
--- a/utils/kamctl/mysql/mtree-create.sql
+++ b/utils/kamctl/mysql/mtree-create.sql
@@ -1,17 +1,17 @@
 INSERT INTO version (table_name, table_version) values ('mtree','1');
-CREATE TABLE mtree (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    tprefix VARCHAR(32) DEFAULT '' NOT NULL,
-    tvalue VARCHAR(128) DEFAULT '' NOT NULL,
-    CONSTRAINT tprefix_idx UNIQUE (tprefix)
+CREATE TABLE `mtree` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `tprefix` VARCHAR(32) DEFAULT '' NOT NULL,
+    `tvalue` VARCHAR(128) DEFAULT '' NOT NULL,
+    CONSTRAINT tprefix_idx UNIQUE (`tprefix`)
 );
 
 INSERT INTO version (table_name, table_version) values ('mtrees','2');
-CREATE TABLE mtrees (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    tname VARCHAR(128) DEFAULT '' NOT NULL,
-    tprefix VARCHAR(32) DEFAULT '' NOT NULL,
-    tvalue VARCHAR(128) DEFAULT '' NOT NULL,
-    CONSTRAINT tname_tprefix_tvalue_idx UNIQUE (tname, tprefix, tvalue)
+CREATE TABLE `mtrees` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `tname` VARCHAR(128) DEFAULT '' NOT NULL,
+    `tprefix` VARCHAR(32) DEFAULT '' NOT NULL,
+    `tvalue` VARCHAR(128) DEFAULT '' NOT NULL,
+    CONSTRAINT tname_tprefix_tvalue_idx UNIQUE (`tname`, `tprefix`, `tvalue`)
 );
 
diff --git a/utils/kamctl/mysql/pdt-create.sql b/utils/kamctl/mysql/pdt-create.sql
index 4069638..8281a12 100644
--- a/utils/kamctl/mysql/pdt-create.sql
+++ b/utils/kamctl/mysql/pdt-create.sql
@@ -1,9 +1,9 @@
 INSERT INTO version (table_name, table_version) values ('pdt','1');
-CREATE TABLE pdt (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    sdomain VARCHAR(128) NOT NULL,
-    prefix VARCHAR(32) NOT NULL,
-    domain VARCHAR(128) DEFAULT '' NOT NULL,
-    CONSTRAINT sdomain_prefix_idx UNIQUE (sdomain, prefix)
+CREATE TABLE `pdt` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `sdomain` VARCHAR(128) NOT NULL,
+    `prefix` VARCHAR(32) NOT NULL,
+    `domain` VARCHAR(128) DEFAULT '' NOT NULL,
+    CONSTRAINT sdomain_prefix_idx UNIQUE (`sdomain`, `prefix`)
 );
 
diff --git a/utils/kamctl/mysql/permissions-create.sql b/utils/kamctl/mysql/permissions-create.sql
index 2e69fec..47d4fa4 100644
--- a/utils/kamctl/mysql/permissions-create.sql
+++ b/utils/kamctl/mysql/permissions-create.sql
@@ -1,21 +1,21 @@
 INSERT INTO version (table_name, table_version) values ('trusted','5');
-CREATE TABLE trusted (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    src_ip VARCHAR(50) NOT NULL,
-    proto VARCHAR(4) NOT NULL,
-    from_pattern VARCHAR(64) DEFAULT NULL,
-    tag VARCHAR(64)
+CREATE TABLE `trusted` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `src_ip` VARCHAR(50) NOT NULL,
+    `proto` VARCHAR(4) NOT NULL,
+    `from_pattern` VARCHAR(64) DEFAULT NULL,
+    `tag` VARCHAR(64)
 );
 
-CREATE INDEX peer_idx ON trusted (src_ip);
+CREATE INDEX peer_idx ON trusted (`src_ip`);
 
 INSERT INTO version (table_name, table_version) values ('address','6');
-CREATE TABLE address (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    grp INT(11) UNSIGNED DEFAULT 1 NOT NULL,
-    ip_addr VARCHAR(50) NOT NULL,
-    mask INT DEFAULT 32 NOT NULL,
-    port SMALLINT(5) UNSIGNED DEFAULT 0 NOT NULL,
-    tag VARCHAR(64)
+CREATE TABLE `address` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `grp` INT(11) UNSIGNED DEFAULT 1 NOT NULL,
+    `ip_addr` VARCHAR(50) NOT NULL,
+    `mask` INT DEFAULT 32 NOT NULL,
+    `port` SMALLINT(5) UNSIGNED DEFAULT 0 NOT NULL,
+    `tag` VARCHAR(64)
 );
 
diff --git a/utils/kamctl/mysql/pipelimit-create.sql b/utils/kamctl/mysql/pipelimit-create.sql
index 49c3ff7..576e86c 100644
--- a/utils/kamctl/mysql/pipelimit-create.sql
+++ b/utils/kamctl/mysql/pipelimit-create.sql
@@ -1,8 +1,8 @@
 INSERT INTO version (table_name, table_version) values ('pl_pipes','1');
-CREATE TABLE pl_pipes (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    pipeid VARCHAR(64) DEFAULT '' NOT NULL,
-    algorithm VARCHAR(32) DEFAULT '' NOT NULL,
-    plimit INT DEFAULT 0 NOT NULL
+CREATE TABLE `pl_pipes` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `pipeid` VARCHAR(64) DEFAULT '' NOT NULL,
+    `algorithm` VARCHAR(32) DEFAULT '' NOT NULL,
+    `plimit` INT DEFAULT 0 NOT NULL
 );
 
diff --git a/utils/kamctl/mysql/presence-create.sql b/utils/kamctl/mysql/presence-create.sql
index c8b9e48..b951bb9 100644
--- a/utils/kamctl/mysql/presence-create.sql
+++ b/utils/kamctl/mysql/presence-create.sql
@@ -1,112 +1,113 @@
-INSERT INTO version (table_name, table_version) values ('presentity','3');
-CREATE TABLE presentity (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    username VARCHAR(64) NOT NULL,
-    domain VARCHAR(64) NOT NULL,
-    event VARCHAR(64) NOT NULL,
-    etag VARCHAR(64) NOT NULL,
-    expires INT(11) NOT NULL,
-    received_time INT(11) NOT NULL,
-    body BLOB NOT NULL,
-    sender VARCHAR(128) NOT NULL,
-    CONSTRAINT presentity_idx UNIQUE (username, domain, event, etag)
+INSERT INTO version (table_name, table_version) values ('presentity','4');
+CREATE TABLE `presentity` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `username` VARCHAR(64) NOT NULL,
+    `domain` VARCHAR(64) NOT NULL,
+    `event` VARCHAR(64) NOT NULL,
+    `etag` VARCHAR(64) NOT NULL,
+    `expires` INT(11) NOT NULL,
+    `received_time` INT(11) NOT NULL,
+    `body` BLOB NOT NULL,
+    `sender` VARCHAR(128) NOT NULL,
+    `priority` INT(11) DEFAULT 0 NOT NULL,
+    CONSTRAINT presentity_idx UNIQUE (`username`, `domain`, `event`, `etag`)
 );
 
-CREATE INDEX presentity_expires ON presentity (expires);
-CREATE INDEX account_idx ON presentity (username, domain, event);
+CREATE INDEX presentity_expires ON presentity (`expires`);
+CREATE INDEX account_idx ON presentity (`username`, `domain`, `event`);
 
 INSERT INTO version (table_name, table_version) values ('active_watchers','11');
-CREATE TABLE active_watchers (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    presentity_uri VARCHAR(128) NOT NULL,
-    watcher_username VARCHAR(64) NOT NULL,
-    watcher_domain VARCHAR(64) NOT NULL,
-    to_user VARCHAR(64) NOT NULL,
-    to_domain VARCHAR(64) NOT NULL,
-    event VARCHAR(64) DEFAULT 'presence' NOT NULL,
-    event_id VARCHAR(64),
-    to_tag VARCHAR(64) NOT NULL,
-    from_tag VARCHAR(64) NOT NULL,
-    callid VARCHAR(255) NOT NULL,
-    local_cseq INT(11) NOT NULL,
-    remote_cseq INT(11) NOT NULL,
-    contact VARCHAR(128) NOT NULL,
-    record_route TEXT,
-    expires INT(11) NOT NULL,
-    status INT(11) DEFAULT 2 NOT NULL,
-    reason VARCHAR(64) NOT NULL,
-    version INT(11) DEFAULT 0 NOT NULL,
-    socket_info VARCHAR(64) NOT NULL,
-    local_contact VARCHAR(128) NOT NULL,
-    from_user VARCHAR(64) NOT NULL,
-    from_domain VARCHAR(64) NOT NULL,
-    updated INT(11) NOT NULL,
-    updated_winfo INT(11) NOT NULL,
-    CONSTRAINT active_watchers_idx UNIQUE (callid, to_tag, from_tag)
+CREATE TABLE `active_watchers` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `presentity_uri` VARCHAR(128) NOT NULL,
+    `watcher_username` VARCHAR(64) NOT NULL,
+    `watcher_domain` VARCHAR(64) NOT NULL,
+    `to_user` VARCHAR(64) NOT NULL,
+    `to_domain` VARCHAR(64) NOT NULL,
+    `event` VARCHAR(64) DEFAULT 'presence' NOT NULL,
+    `event_id` VARCHAR(64),
+    `to_tag` VARCHAR(64) NOT NULL,
+    `from_tag` VARCHAR(64) NOT NULL,
+    `callid` VARCHAR(255) NOT NULL,
+    `local_cseq` INT(11) NOT NULL,
+    `remote_cseq` INT(11) NOT NULL,
+    `contact` VARCHAR(128) NOT NULL,
+    `record_route` TEXT,
+    `expires` INT(11) NOT NULL,
+    `status` INT(11) DEFAULT 2 NOT NULL,
+    `reason` VARCHAR(64) NOT NULL,
+    `version` INT(11) DEFAULT 0 NOT NULL,
+    `socket_info` VARCHAR(64) NOT NULL,
+    `local_contact` VARCHAR(128) NOT NULL,
+    `from_user` VARCHAR(64) NOT NULL,
+    `from_domain` VARCHAR(64) NOT NULL,
+    `updated` INT(11) NOT NULL,
+    `updated_winfo` INT(11) NOT NULL,
+    CONSTRAINT active_watchers_idx UNIQUE (`callid`, `to_tag`, `from_tag`)
 );
 
-CREATE INDEX active_watchers_expires ON active_watchers (expires);
-CREATE INDEX active_watchers_pres ON active_watchers (presentity_uri, event);
-CREATE INDEX updated_idx ON active_watchers (updated);
-CREATE INDEX updated_winfo_idx ON active_watchers (updated_winfo, presentity_uri);
+CREATE INDEX active_watchers_expires ON active_watchers (`expires`);
+CREATE INDEX active_watchers_pres ON active_watchers (`presentity_uri`, `event`);
+CREATE INDEX updated_idx ON active_watchers (`updated`);
+CREATE INDEX updated_winfo_idx ON active_watchers (`updated_winfo`, `presentity_uri`);
 
 INSERT INTO version (table_name, table_version) values ('watchers','3');
-CREATE TABLE watchers (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    presentity_uri VARCHAR(128) NOT NULL,
-    watcher_username VARCHAR(64) NOT NULL,
-    watcher_domain VARCHAR(64) NOT NULL,
-    event VARCHAR(64) DEFAULT 'presence' NOT NULL,
-    status INT(11) NOT NULL,
-    reason VARCHAR(64),
-    inserted_time INT(11) NOT NULL,
-    CONSTRAINT watcher_idx UNIQUE (presentity_uri, watcher_username, watcher_domain, event)
+CREATE TABLE `watchers` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `presentity_uri` VARCHAR(128) NOT NULL,
+    `watcher_username` VARCHAR(64) NOT NULL,
+    `watcher_domain` VARCHAR(64) NOT NULL,
+    `event` VARCHAR(64) DEFAULT 'presence' NOT NULL,
+    `status` INT(11) NOT NULL,
+    `reason` VARCHAR(64),
+    `inserted_time` INT(11) NOT NULL,
+    CONSTRAINT watcher_idx UNIQUE (`presentity_uri`, `watcher_username`, `watcher_domain`, `event`)
 );
 
 INSERT INTO version (table_name, table_version) values ('xcap','4');
-CREATE TABLE xcap (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    username VARCHAR(64) NOT NULL,
-    domain VARCHAR(64) NOT NULL,
-    doc MEDIUMBLOB NOT NULL,
-    doc_type INT(11) NOT NULL,
-    etag VARCHAR(64) NOT NULL,
-    source INT(11) NOT NULL,
-    doc_uri VARCHAR(255) NOT NULL,
-    port INT(11) NOT NULL,
-    CONSTRAINT doc_uri_idx UNIQUE (doc_uri)
+CREATE TABLE `xcap` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `username` VARCHAR(64) NOT NULL,
+    `domain` VARCHAR(64) NOT NULL,
+    `doc` MEDIUMBLOB NOT NULL,
+    `doc_type` INT(11) NOT NULL,
+    `etag` VARCHAR(64) NOT NULL,
+    `source` INT(11) NOT NULL,
+    `doc_uri` VARCHAR(255) NOT NULL,
+    `port` INT(11) NOT NULL,
+    CONSTRAINT doc_uri_idx UNIQUE (`doc_uri`)
 );
 
-CREATE INDEX account_doc_type_idx ON xcap (username, domain, doc_type);
-CREATE INDEX account_doc_type_uri_idx ON xcap (username, domain, doc_type, doc_uri);
-CREATE INDEX account_doc_uri_idx ON xcap (username, domain, doc_uri);
+CREATE INDEX account_doc_type_idx ON xcap (`username`, `domain`, `doc_type`);
+CREATE INDEX account_doc_type_uri_idx ON xcap (`username`, `domain`, `doc_type`, `doc_uri`);
+CREATE INDEX account_doc_uri_idx ON xcap (`username`, `domain`, `doc_uri`);
 
 INSERT INTO version (table_name, table_version) values ('pua','7');
-CREATE TABLE pua (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    pres_uri VARCHAR(128) NOT NULL,
-    pres_id VARCHAR(255) NOT NULL,
-    event INT(11) NOT NULL,
-    expires INT(11) NOT NULL,
-    desired_expires INT(11) NOT NULL,
-    flag INT(11) NOT NULL,
-    etag VARCHAR(64) NOT NULL,
-    tuple_id VARCHAR(64),
-    watcher_uri VARCHAR(128) NOT NULL,
-    call_id VARCHAR(255) NOT NULL,
-    to_tag VARCHAR(64) NOT NULL,
-    from_tag VARCHAR(64) NOT NULL,
-    cseq INT(11) NOT NULL,
-    record_route TEXT,
-    contact VARCHAR(128) NOT NULL,
-    remote_contact VARCHAR(128) NOT NULL,
-    version INT(11) NOT NULL,
-    extra_headers TEXT NOT NULL,
-    CONSTRAINT pua_idx UNIQUE (etag, tuple_id, call_id, from_tag)
+CREATE TABLE `pua` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `pres_uri` VARCHAR(128) NOT NULL,
+    `pres_id` VARCHAR(255) NOT NULL,
+    `event` INT(11) NOT NULL,
+    `expires` INT(11) NOT NULL,
+    `desired_expires` INT(11) NOT NULL,
+    `flag` INT(11) NOT NULL,
+    `etag` VARCHAR(64) NOT NULL,
+    `tuple_id` VARCHAR(64),
+    `watcher_uri` VARCHAR(128) NOT NULL,
+    `call_id` VARCHAR(255) NOT NULL,
+    `to_tag` VARCHAR(64) NOT NULL,
+    `from_tag` VARCHAR(64) NOT NULL,
+    `cseq` INT(11) NOT NULL,
+    `record_route` TEXT,
+    `contact` VARCHAR(128) NOT NULL,
+    `remote_contact` VARCHAR(128) NOT NULL,
+    `version` INT(11) NOT NULL,
+    `extra_headers` TEXT NOT NULL,
+    CONSTRAINT pua_idx UNIQUE (`etag`, `tuple_id`, `call_id`, `from_tag`)
 );
 
-CREATE INDEX expires_idx ON pua (expires);
-CREATE INDEX dialog1_idx ON pua (pres_id, pres_uri);
-CREATE INDEX dialog2_idx ON pua (call_id, from_tag);
-CREATE INDEX record_idx ON pua (pres_id);
+CREATE INDEX expires_idx ON pua (`expires`);
+CREATE INDEX dialog1_idx ON pua (`pres_id`, `pres_uri`);
+CREATE INDEX dialog2_idx ON pua (`call_id`, `from_tag`);
+CREATE INDEX record_idx ON pua (`pres_id`);
 
diff --git a/utils/kamctl/mysql/purple-create.sql b/utils/kamctl/mysql/purple-create.sql
index afd55c3..ff472b9 100644
--- a/utils/kamctl/mysql/purple-create.sql
+++ b/utils/kamctl/mysql/purple-create.sql
@@ -1,9 +1,9 @@
 INSERT INTO version (table_name, table_version) values ('purplemap','1');
-CREATE TABLE purplemap (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    sip_user VARCHAR(128) NOT NULL,
-    ext_user VARCHAR(128) NOT NULL,
-    ext_prot VARCHAR(16) NOT NULL,
-    ext_pass VARCHAR(64)
+CREATE TABLE `purplemap` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `sip_user` VARCHAR(128) NOT NULL,
+    `ext_user` VARCHAR(128) NOT NULL,
+    `ext_prot` VARCHAR(16) NOT NULL,
+    `ext_pass` VARCHAR(64)
 );
 
diff --git a/utils/kamctl/mysql/registrar-create.sql b/utils/kamctl/mysql/registrar-create.sql
index 5d9254e..a0d98f6 100644
--- a/utils/kamctl/mysql/registrar-create.sql
+++ b/utils/kamctl/mysql/registrar-create.sql
@@ -1,26 +1,31 @@
-INSERT INTO version (table_name, table_version) values ('aliases','6');
-CREATE TABLE aliases (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    ruid VARCHAR(64) DEFAULT '' NOT NULL,
-    username VARCHAR(64) DEFAULT '' NOT NULL,
-    domain VARCHAR(64) DEFAULT NULL,
-    contact VARCHAR(255) DEFAULT '' NOT NULL,
-    received VARCHAR(128) DEFAULT NULL,
-    path VARCHAR(128) DEFAULT NULL,
-    expires DATETIME DEFAULT '2030-05-28 21:32:15' NOT NULL,
-    q FLOAT(10,2) DEFAULT 1.0 NOT NULL,
-    callid VARCHAR(255) DEFAULT 'Default-Call-ID' NOT NULL,
-    cseq INT(11) DEFAULT 1 NOT NULL,
-    last_modified DATETIME DEFAULT '1900-01-01 00:00:01' NOT NULL,
-    flags INT(11) DEFAULT 0 NOT NULL,
-    cflags INT(11) DEFAULT 0 NOT NULL,
-    user_agent VARCHAR(255) DEFAULT '' NOT NULL,
-    socket VARCHAR(64) DEFAULT NULL,
-    methods INT(11) DEFAULT NULL,
-    instance VARCHAR(255) DEFAULT NULL,
-    reg_id INT(11) DEFAULT 0 NOT NULL,
-    CONSTRAINT ruid_idx UNIQUE (ruid)
+INSERT INTO version (table_name, table_version) values ('aliases','8');
+CREATE TABLE `aliases` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `ruid` VARCHAR(64) DEFAULT '' NOT NULL,
+    `username` VARCHAR(64) DEFAULT '' NOT NULL,
+    `domain` VARCHAR(64) DEFAULT NULL,
+    `contact` VARCHAR(255) DEFAULT '' NOT NULL,
+    `received` VARCHAR(128) DEFAULT NULL,
+    `path` VARCHAR(512) DEFAULT NULL,
+    `expires` DATETIME DEFAULT '2030-05-28 21:32:15' NOT NULL,
+    `q` FLOAT(10,2) DEFAULT 1.0 NOT NULL,
+    `callid` VARCHAR(255) DEFAULT 'Default-Call-ID' NOT NULL,
+    `cseq` INT(11) DEFAULT 1 NOT NULL,
+    `last_modified` DATETIME DEFAULT '1900-01-01 00:00:01' NOT NULL,
+    `flags` INT(11) DEFAULT 0 NOT NULL,
+    `cflags` INT(11) DEFAULT 0 NOT NULL,
+    `user_agent` VARCHAR(255) DEFAULT '' NOT NULL,
+    `socket` VARCHAR(64) DEFAULT NULL,
+    `methods` INT(11) DEFAULT NULL,
+    `instance` VARCHAR(255) DEFAULT NULL,
+    `reg_id` INT(11) DEFAULT 0 NOT NULL,
+    `server_id` INT(11) DEFAULT 0 NOT NULL,
+    `connection_id` INT(11) DEFAULT 0 NOT NULL,
+    `keepalive` INT(11) DEFAULT 0 NOT NULL,
+    `partition` INT(11) DEFAULT 0 NOT NULL,
+    CONSTRAINT ruid_idx UNIQUE (`ruid`)
 );
 
-CREATE INDEX alias_idx ON aliases (username, domain, contact);
+CREATE INDEX account_contact_idx ON aliases (`username`, `domain`, `contact`);
+CREATE INDEX expires_idx ON aliases (`expires`);
 
diff --git a/utils/kamctl/mysql/rls-create.sql b/utils/kamctl/mysql/rls-create.sql
index f165c57..bb1ee33 100644
--- a/utils/kamctl/mysql/rls-create.sql
+++ b/utils/kamctl/mysql/rls-create.sql
@@ -1,51 +1,51 @@
 INSERT INTO version (table_name, table_version) values ('rls_presentity','1');
-CREATE TABLE rls_presentity (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    rlsubs_did VARCHAR(255) NOT NULL,
-    resource_uri VARCHAR(128) NOT NULL,
-    content_type VARCHAR(255) NOT NULL,
-    presence_state BLOB NOT NULL,
-    expires INT(11) NOT NULL,
-    updated INT(11) NOT NULL,
-    auth_state INT(11) NOT NULL,
-    reason VARCHAR(64) NOT NULL,
-    CONSTRAINT rls_presentity_idx UNIQUE (rlsubs_did, resource_uri)
+CREATE TABLE `rls_presentity` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `rlsubs_did` VARCHAR(255) NOT NULL,
+    `resource_uri` VARCHAR(128) NOT NULL,
+    `content_type` VARCHAR(255) NOT NULL,
+    `presence_state` BLOB NOT NULL,
+    `expires` INT(11) NOT NULL,
+    `updated` INT(11) NOT NULL,
+    `auth_state` INT(11) NOT NULL,
+    `reason` VARCHAR(64) NOT NULL,
+    CONSTRAINT rls_presentity_idx UNIQUE (`rlsubs_did`, `resource_uri`)
 );
 
-CREATE INDEX rlsubs_idx ON rls_presentity (rlsubs_did);
-CREATE INDEX updated_idx ON rls_presentity (updated);
-CREATE INDEX expires_idx ON rls_presentity (expires);
+CREATE INDEX rlsubs_idx ON rls_presentity (`rlsubs_did`);
+CREATE INDEX updated_idx ON rls_presentity (`updated`);
+CREATE INDEX expires_idx ON rls_presentity (`expires`);
 
 INSERT INTO version (table_name, table_version) values ('rls_watchers','3');
-CREATE TABLE rls_watchers (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    presentity_uri VARCHAR(128) NOT NULL,
-    to_user VARCHAR(64) NOT NULL,
-    to_domain VARCHAR(64) NOT NULL,
-    watcher_username VARCHAR(64) NOT NULL,
-    watcher_domain VARCHAR(64) NOT NULL,
-    event VARCHAR(64) DEFAULT 'presence' NOT NULL,
-    event_id VARCHAR(64),
-    to_tag VARCHAR(64) NOT NULL,
-    from_tag VARCHAR(64) NOT NULL,
-    callid VARCHAR(255) NOT NULL,
-    local_cseq INT(11) NOT NULL,
-    remote_cseq INT(11) NOT NULL,
-    contact VARCHAR(128) NOT NULL,
-    record_route TEXT,
-    expires INT(11) NOT NULL,
-    status INT(11) DEFAULT 2 NOT NULL,
-    reason VARCHAR(64) NOT NULL,
-    version INT(11) DEFAULT 0 NOT NULL,
-    socket_info VARCHAR(64) NOT NULL,
-    local_contact VARCHAR(128) NOT NULL,
-    from_user VARCHAR(64) NOT NULL,
-    from_domain VARCHAR(64) NOT NULL,
-    updated INT(11) NOT NULL,
-    CONSTRAINT rls_watcher_idx UNIQUE (callid, to_tag, from_tag)
+CREATE TABLE `rls_watchers` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `presentity_uri` VARCHAR(128) NOT NULL,
+    `to_user` VARCHAR(64) NOT NULL,
+    `to_domain` VARCHAR(64) NOT NULL,
+    `watcher_username` VARCHAR(64) NOT NULL,
+    `watcher_domain` VARCHAR(64) NOT NULL,
+    `event` VARCHAR(64) DEFAULT 'presence' NOT NULL,
+    `event_id` VARCHAR(64),
+    `to_tag` VARCHAR(64) NOT NULL,
+    `from_tag` VARCHAR(64) NOT NULL,
+    `callid` VARCHAR(255) NOT NULL,
+    `local_cseq` INT(11) NOT NULL,
+    `remote_cseq` INT(11) NOT NULL,
+    `contact` VARCHAR(128) NOT NULL,
+    `record_route` TEXT,
+    `expires` INT(11) NOT NULL,
+    `status` INT(11) DEFAULT 2 NOT NULL,
+    `reason` VARCHAR(64) NOT NULL,
+    `version` INT(11) DEFAULT 0 NOT NULL,
+    `socket_info` VARCHAR(64) NOT NULL,
+    `local_contact` VARCHAR(128) NOT NULL,
+    `from_user` VARCHAR(64) NOT NULL,
+    `from_domain` VARCHAR(64) NOT NULL,
+    `updated` INT(11) NOT NULL,
+    CONSTRAINT rls_watcher_idx UNIQUE (`callid`, `to_tag`, `from_tag`)
 );
 
-CREATE INDEX rls_watchers_update ON rls_watchers (watcher_username, watcher_domain, event);
-CREATE INDEX rls_watchers_expires ON rls_watchers (expires);
-CREATE INDEX updated_idx ON rls_watchers (updated);
+CREATE INDEX rls_watchers_update ON rls_watchers (`watcher_username`, `watcher_domain`, `event`);
+CREATE INDEX rls_watchers_expires ON rls_watchers (`expires`);
+CREATE INDEX updated_idx ON rls_watchers (`updated`);
 
diff --git a/utils/kamctl/mysql/rtpproxy-create.sql b/utils/kamctl/mysql/rtpproxy-create.sql
index dcb6f08..21c5535 100644
--- a/utils/kamctl/mysql/rtpproxy-create.sql
+++ b/utils/kamctl/mysql/rtpproxy-create.sql
@@ -1,10 +1,10 @@
 INSERT INTO version (table_name, table_version) values ('rtpproxy','1');
-CREATE TABLE rtpproxy (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    setid VARCHAR(32) DEFAULT 00 NOT NULL,
-    url VARCHAR(64) DEFAULT '' NOT NULL,
-    flags INT DEFAULT 0 NOT NULL,
-    weight INT DEFAULT 1 NOT NULL,
-    description VARCHAR(64) DEFAULT '' NOT NULL
+CREATE TABLE `rtpproxy` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `setid` VARCHAR(32) DEFAULT 00 NOT NULL,
+    `url` VARCHAR(64) DEFAULT '' NOT NULL,
+    `flags` INT DEFAULT 0 NOT NULL,
+    `weight` INT DEFAULT 1 NOT NULL,
+    `description` VARCHAR(64) DEFAULT '' NOT NULL
 );
 
diff --git a/utils/kamctl/mysql/sca-create.sql b/utils/kamctl/mysql/sca-create.sql
index db54472..64d3c34 100644
--- a/utils/kamctl/mysql/sca-create.sql
+++ b/utils/kamctl/mysql/sca-create.sql
@@ -1,21 +1,21 @@
 INSERT INTO version (table_name, table_version) values ('sca_subscriptions','1');
-CREATE TABLE sca_subscriptions (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    subscriber VARCHAR(255) NOT NULL,
-    aor VARCHAR(255) NOT NULL,
-    event INT DEFAULT 0 NOT NULL,
-    expires INT(11) DEFAULT 0 NOT NULL,
-    state INT DEFAULT 0 NOT NULL,
-    app_idx INT DEFAULT 0 NOT NULL,
-    call_id VARCHAR(255) NOT NULL,
-    from_tag VARCHAR(64) NOT NULL,
-    to_tag VARCHAR(64) NOT NULL,
-    record_route TEXT,
-    notify_cseq INT(11) NOT NULL,
-    subscribe_cseq INT(11) NOT NULL,
-    CONSTRAINT sca_subscriptions_idx UNIQUE (subscriber, call_id, from_tag, to_tag)
+CREATE TABLE `sca_subscriptions` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `subscriber` VARCHAR(255) NOT NULL,
+    `aor` VARCHAR(255) NOT NULL,
+    `event` INT DEFAULT 0 NOT NULL,
+    `expires` INT(11) DEFAULT 0 NOT NULL,
+    `state` INT DEFAULT 0 NOT NULL,
+    `app_idx` INT DEFAULT 0 NOT NULL,
+    `call_id` VARCHAR(255) NOT NULL,
+    `from_tag` VARCHAR(64) NOT NULL,
+    `to_tag` VARCHAR(64) NOT NULL,
+    `record_route` TEXT,
+    `notify_cseq` INT(11) NOT NULL,
+    `subscribe_cseq` INT(11) NOT NULL,
+    CONSTRAINT sca_subscriptions_idx UNIQUE (`subscriber`, `call_id`, `from_tag`, `to_tag`)
 );
 
-CREATE INDEX sca_expires_idx ON sca_subscriptions (expires);
-CREATE INDEX sca_subscribers_idx ON sca_subscriptions (subscriber, event);
+CREATE INDEX sca_expires_idx ON sca_subscriptions (`expires`);
+CREATE INDEX sca_subscribers_idx ON sca_subscriptions (`subscriber`, `event`);
 
diff --git a/utils/kamctl/mysql/siptrace-create.sql b/utils/kamctl/mysql/siptrace-create.sql
index 28c50e3..c081a56 100644
--- a/utils/kamctl/mysql/siptrace-create.sql
+++ b/utils/kamctl/mysql/siptrace-create.sql
@@ -1,21 +1,22 @@
-INSERT INTO version (table_name, table_version) values ('sip_trace','3');
-CREATE TABLE sip_trace (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    time_stamp DATETIME DEFAULT '1900-01-01 00:00:01' NOT NULL,
-    time_us INT UNSIGNED DEFAULT 0 NOT NULL,
-    callid VARCHAR(255) DEFAULT '' NOT NULL,
-    traced_user VARCHAR(128) DEFAULT '' NOT NULL,
-    msg MEDIUMTEXT NOT NULL,
-    method VARCHAR(50) DEFAULT '' NOT NULL,
-    status VARCHAR(128) DEFAULT '' NOT NULL,
-    fromip VARCHAR(50) DEFAULT '' NOT NULL,
-    toip VARCHAR(50) DEFAULT '' NOT NULL,
-    fromtag VARCHAR(64) DEFAULT '' NOT NULL,
-    direction VARCHAR(4) DEFAULT '' NOT NULL
+INSERT INTO version (table_name, table_version) values ('sip_trace','4');
+CREATE TABLE `sip_trace` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `time_stamp` DATETIME DEFAULT '1900-01-01 00:00:01' NOT NULL,
+    `time_us` INT UNSIGNED DEFAULT 0 NOT NULL,
+    `callid` VARCHAR(255) DEFAULT '' NOT NULL,
+    `traced_user` VARCHAR(128) DEFAULT '' NOT NULL,
+    `msg` MEDIUMTEXT NOT NULL,
+    `method` VARCHAR(50) DEFAULT '' NOT NULL,
+    `status` VARCHAR(128) DEFAULT '' NOT NULL,
+    `fromip` VARCHAR(50) DEFAULT '' NOT NULL,
+    `toip` VARCHAR(50) DEFAULT '' NOT NULL,
+    `fromtag` VARCHAR(64) DEFAULT '' NOT NULL,
+    `totag` VARCHAR(64) DEFAULT '' NOT NULL,
+    `direction` VARCHAR(4) DEFAULT '' NOT NULL
 );
 
-CREATE INDEX traced_user_idx ON sip_trace (traced_user);
-CREATE INDEX date_idx ON sip_trace (time_stamp);
-CREATE INDEX fromip_idx ON sip_trace (fromip);
-CREATE INDEX callid_idx ON sip_trace (callid);
+CREATE INDEX traced_user_idx ON sip_trace (`traced_user`);
+CREATE INDEX date_idx ON sip_trace (`time_stamp`);
+CREATE INDEX fromip_idx ON sip_trace (`fromip`);
+CREATE INDEX callid_idx ON sip_trace (`callid`);
 
diff --git a/utils/kamctl/mysql/speeddial-create.sql b/utils/kamctl/mysql/speeddial-create.sql
index 1531013..edf5c5c 100644
--- a/utils/kamctl/mysql/speeddial-create.sql
+++ b/utils/kamctl/mysql/speeddial-create.sql
@@ -1,14 +1,14 @@
 INSERT INTO version (table_name, table_version) values ('speed_dial','2');
-CREATE TABLE speed_dial (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    username VARCHAR(64) DEFAULT '' NOT NULL,
-    domain VARCHAR(64) DEFAULT '' NOT NULL,
-    sd_username VARCHAR(64) DEFAULT '' NOT NULL,
-    sd_domain VARCHAR(64) DEFAULT '' NOT NULL,
-    new_uri VARCHAR(128) DEFAULT '' NOT NULL,
-    fname VARCHAR(64) DEFAULT '' NOT NULL,
-    lname VARCHAR(64) DEFAULT '' NOT NULL,
-    description VARCHAR(64) DEFAULT '' NOT NULL,
-    CONSTRAINT speed_dial_idx UNIQUE (username, domain, sd_domain, sd_username)
+CREATE TABLE `speed_dial` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `username` VARCHAR(64) DEFAULT '' NOT NULL,
+    `domain` VARCHAR(64) DEFAULT '' NOT NULL,
+    `sd_username` VARCHAR(64) DEFAULT '' NOT NULL,
+    `sd_domain` VARCHAR(64) DEFAULT '' NOT NULL,
+    `new_uri` VARCHAR(128) DEFAULT '' NOT NULL,
+    `fname` VARCHAR(64) DEFAULT '' NOT NULL,
+    `lname` VARCHAR(64) DEFAULT '' NOT NULL,
+    `description` VARCHAR(64) DEFAULT '' NOT NULL,
+    CONSTRAINT speed_dial_idx UNIQUE (`username`, `domain`, `sd_domain`, `sd_username`)
 );
 
diff --git a/utils/kamctl/mysql/standard-create.sql b/utils/kamctl/mysql/standard-create.sql
index d029469..eeeacf9 100644
--- a/utils/kamctl/mysql/standard-create.sql
+++ b/utils/kamctl/mysql/standard-create.sql
@@ -1,6 +1,6 @@
-CREATE TABLE version (
-    table_name VARCHAR(32) NOT NULL,
-    table_version INT UNSIGNED DEFAULT 0 NOT NULL,
-    CONSTRAINT table_name_idx UNIQUE (table_name)
+CREATE TABLE `version` (
+    `table_name` VARCHAR(32) NOT NULL,
+    `table_version` INT UNSIGNED DEFAULT 0 NOT NULL,
+    CONSTRAINT table_name_idx UNIQUE (`table_name`)
 );
 
diff --git a/utils/kamctl/mysql/uac-create.sql b/utils/kamctl/mysql/uac-create.sql
index 5de67b9..aa6a1fd 100644
--- a/utils/kamctl/mysql/uac-create.sql
+++ b/utils/kamctl/mysql/uac-create.sql
@@ -1,16 +1,16 @@
 INSERT INTO version (table_name, table_version) values ('uacreg','1');
-CREATE TABLE uacreg (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    l_uuid VARCHAR(64) DEFAULT '' NOT NULL,
-    l_username VARCHAR(64) DEFAULT '' NOT NULL,
-    l_domain VARCHAR(128) DEFAULT '' NOT NULL,
-    r_username VARCHAR(64) DEFAULT '' NOT NULL,
-    r_domain VARCHAR(128) DEFAULT '' NOT NULL,
-    realm VARCHAR(64) DEFAULT '' NOT NULL,
-    auth_username VARCHAR(64) DEFAULT '' NOT NULL,
-    auth_password VARCHAR(64) DEFAULT '' NOT NULL,
-    auth_proxy VARCHAR(64) DEFAULT '' NOT NULL,
-    expires INT DEFAULT 0 NOT NULL,
-    CONSTRAINT l_uuid_idx UNIQUE (l_uuid)
+CREATE TABLE `uacreg` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `l_uuid` VARCHAR(64) DEFAULT '' NOT NULL,
+    `l_username` VARCHAR(64) DEFAULT '' NOT NULL,
+    `l_domain` VARCHAR(128) DEFAULT '' NOT NULL,
+    `r_username` VARCHAR(64) DEFAULT '' NOT NULL,
+    `r_domain` VARCHAR(128) DEFAULT '' NOT NULL,
+    `realm` VARCHAR(64) DEFAULT '' NOT NULL,
+    `auth_username` VARCHAR(64) DEFAULT '' NOT NULL,
+    `auth_password` VARCHAR(64) DEFAULT '' NOT NULL,
+    `auth_proxy` VARCHAR(64) DEFAULT '' NOT NULL,
+    `expires` INT DEFAULT 0 NOT NULL,
+    CONSTRAINT l_uuid_idx UNIQUE (`l_uuid`)
 );
 
diff --git a/utils/kamctl/mysql/uid_auth_db-create.sql b/utils/kamctl/mysql/uid_auth_db-create.sql
index 529c0df..e088caf 100644
--- a/utils/kamctl/mysql/uid_auth_db-create.sql
+++ b/utils/kamctl/mysql/uid_auth_db-create.sql
@@ -1,18 +1,18 @@
 INSERT INTO version (table_name, table_version) values ('uid_credentials','7');
-CREATE TABLE uid_credentials (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    auth_username VARCHAR(64) NOT NULL,
-    did VARCHAR(64) DEFAULT '_default' NOT NULL,
-    realm VARCHAR(64) NOT NULL,
-    password VARCHAR(28) DEFAULT '' NOT NULL,
-    flags INT DEFAULT 0 NOT NULL,
-    ha1 VARCHAR(32) NOT NULL,
-    ha1b VARCHAR(32) DEFAULT '' NOT NULL,
-    uid VARCHAR(64) NOT NULL
+CREATE TABLE `uid_credentials` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `auth_username` VARCHAR(64) NOT NULL,
+    `did` VARCHAR(64) DEFAULT '_default' NOT NULL,
+    `realm` VARCHAR(64) NOT NULL,
+    `password` VARCHAR(28) DEFAULT '' NOT NULL,
+    `flags` INT DEFAULT 0 NOT NULL,
+    `ha1` VARCHAR(32) NOT NULL,
+    `ha1b` VARCHAR(32) DEFAULT '' NOT NULL,
+    `uid` VARCHAR(64) NOT NULL
 );
 
-CREATE INDEX cred_idx ON uid_credentials (auth_username, did);
-CREATE INDEX uid ON uid_credentials (uid);
-CREATE INDEX did_idx ON uid_credentials (did);
-CREATE INDEX realm_idx ON uid_credentials (realm);
+CREATE INDEX cred_idx ON uid_credentials (`auth_username`, `did`);
+CREATE INDEX uid ON uid_credentials (`uid`);
+CREATE INDEX did_idx ON uid_credentials (`did`);
+CREATE INDEX realm_idx ON uid_credentials (`realm`);
 
diff --git a/utils/kamctl/mysql/uid_avp_db-create.sql b/utils/kamctl/mysql/uid_avp_db-create.sql
index d35f7e7..bf67f3c 100644
--- a/utils/kamctl/mysql/uid_avp_db-create.sql
+++ b/utils/kamctl/mysql/uid_avp_db-create.sql
@@ -1,11 +1,11 @@
 INSERT INTO version (table_name, table_version) values ('uid_user_attrs','3');
-CREATE TABLE uid_user_attrs (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    uid VARCHAR(64) NOT NULL,
-    name VARCHAR(32) NOT NULL,
-    value VARCHAR(128),
-    type INT DEFAULT 0 NOT NULL,
-    flags INT UNSIGNED DEFAULT 0 NOT NULL,
-    CONSTRAINT userattrs_idx UNIQUE (uid, name, value)
+CREATE TABLE `uid_user_attrs` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `uid` VARCHAR(64) NOT NULL,
+    `name` VARCHAR(32) NOT NULL,
+    `value` VARCHAR(128),
+    `type` INT DEFAULT 0 NOT NULL,
+    `flags` INT UNSIGNED DEFAULT 0 NOT NULL,
+    CONSTRAINT userattrs_idx UNIQUE (`uid`, `name`, `value`)
 );
 
diff --git a/utils/kamctl/mysql/uid_domain-create.sql b/utils/kamctl/mysql/uid_domain-create.sql
index e1d4d62..48c97b1 100644
--- a/utils/kamctl/mysql/uid_domain-create.sql
+++ b/utils/kamctl/mysql/uid_domain-create.sql
@@ -1,24 +1,24 @@
 INSERT INTO version (table_name, table_version) values ('uid_domain','2');
-CREATE TABLE uid_domain (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    did VARCHAR(64) NOT NULL,
-    domain VARCHAR(64) NOT NULL,
-    flags INT UNSIGNED DEFAULT 0 NOT NULL,
-    CONSTRAINT domain_idx UNIQUE (domain)
+CREATE TABLE `uid_domain` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `did` VARCHAR(64) NOT NULL,
+    `domain` VARCHAR(64) NOT NULL,
+    `flags` INT UNSIGNED DEFAULT 0 NOT NULL,
+    CONSTRAINT domain_idx UNIQUE (`domain`)
 );
 
-CREATE INDEX did_idx ON uid_domain (did);
+CREATE INDEX did_idx ON uid_domain (`did`);
 
 INSERT INTO version (table_name, table_version) values ('uid_domain_attrs','1');
-CREATE TABLE uid_domain_attrs (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    did VARCHAR(64),
-    name VARCHAR(32) NOT NULL,
-    type INT DEFAULT 0 NOT NULL,
-    value VARCHAR(128),
-    flags INT UNSIGNED DEFAULT 0 NOT NULL,
-    CONSTRAINT domain_attr_idx UNIQUE (did, name, value)
+CREATE TABLE `uid_domain_attrs` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `did` VARCHAR(64),
+    `name` VARCHAR(32) NOT NULL,
+    `type` INT DEFAULT 0 NOT NULL,
+    `value` VARCHAR(128),
+    `flags` INT UNSIGNED DEFAULT 0 NOT NULL,
+    CONSTRAINT domain_attr_idx UNIQUE (`did`, `name`, `value`)
 );
 
-CREATE INDEX domain_did ON uid_domain_attrs (did, flags);
+CREATE INDEX domain_did ON uid_domain_attrs (`did`, `flags`);
 
diff --git a/utils/kamctl/mysql/uid_gflags-create.sql b/utils/kamctl/mysql/uid_gflags-create.sql
index 06e7d5f..88d147b 100644
--- a/utils/kamctl/mysql/uid_gflags-create.sql
+++ b/utils/kamctl/mysql/uid_gflags-create.sql
@@ -1,10 +1,10 @@
 INSERT INTO version (table_name, table_version) values ('uid_global_attrs','1');
-CREATE TABLE uid_global_attrs (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    name VARCHAR(32) NOT NULL,
-    type INT DEFAULT 0 NOT NULL,
-    value VARCHAR(128),
-    flags INT UNSIGNED DEFAULT 0 NOT NULL,
-    CONSTRAINT global_attrs_idx UNIQUE (name, value)
+CREATE TABLE `uid_global_attrs` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `name` VARCHAR(32) NOT NULL,
+    `type` INT DEFAULT 0 NOT NULL,
+    `value` VARCHAR(128),
+    `flags` INT UNSIGNED DEFAULT 0 NOT NULL,
+    CONSTRAINT global_attrs_idx UNIQUE (`name`, `value`)
 );
 
diff --git a/utils/kamctl/mysql/uid_uri_db-create.sql b/utils/kamctl/mysql/uid_uri_db-create.sql
index 96e7d7b..efa03c9 100644
--- a/utils/kamctl/mysql/uid_uri_db-create.sql
+++ b/utils/kamctl/mysql/uid_uri_db-create.sql
@@ -1,26 +1,26 @@
 INSERT INTO version (table_name, table_version) values ('uid_uri','3');
-CREATE TABLE uid_uri (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    uid VARCHAR(64) NOT NULL,
-    did VARCHAR(64) NOT NULL,
-    username VARCHAR(64) NOT NULL,
-    flags INT UNSIGNED DEFAULT 0 NOT NULL,
-    scheme VARCHAR(8) DEFAULT 'sip' NOT NULL
+CREATE TABLE `uid_uri` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `uid` VARCHAR(64) NOT NULL,
+    `did` VARCHAR(64) NOT NULL,
+    `username` VARCHAR(64) NOT NULL,
+    `flags` INT UNSIGNED DEFAULT 0 NOT NULL,
+    `scheme` VARCHAR(8) DEFAULT 'sip' NOT NULL
 );
 
-CREATE INDEX uri_idx1 ON uid_uri (username, did, scheme);
-CREATE INDEX uri_uid ON uid_uri (uid);
+CREATE INDEX uri_idx1 ON uid_uri (`username`, `did`, `scheme`);
+CREATE INDEX uri_uid ON uid_uri (`uid`);
 
 INSERT INTO version (table_name, table_version) values ('uid_uri_attrs','2');
-CREATE TABLE uid_uri_attrs (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    username VARCHAR(64) NOT NULL,
-    did VARCHAR(64) NOT NULL,
-    name VARCHAR(32) NOT NULL,
-    value VARCHAR(128),
-    type INT DEFAULT 0 NOT NULL,
-    flags INT UNSIGNED DEFAULT 0 NOT NULL,
-    scheme VARCHAR(8) DEFAULT 'sip' NOT NULL,
-    CONSTRAINT uriattrs_idx UNIQUE (username, did, name, value, scheme)
+CREATE TABLE `uid_uri_attrs` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `username` VARCHAR(64) NOT NULL,
+    `did` VARCHAR(64) NOT NULL,
+    `name` VARCHAR(32) NOT NULL,
+    `value` VARCHAR(128),
+    `type` INT DEFAULT 0 NOT NULL,
+    `flags` INT UNSIGNED DEFAULT 0 NOT NULL,
+    `scheme` VARCHAR(8) DEFAULT 'sip' NOT NULL,
+    CONSTRAINT uriattrs_idx UNIQUE (`username`, `did`, `name`, `value`, `scheme`)
 );
 
diff --git a/utils/kamctl/mysql/uri_db-create.sql b/utils/kamctl/mysql/uri_db-create.sql
index 70cc89e..4b41fd7 100644
--- a/utils/kamctl/mysql/uri_db-create.sql
+++ b/utils/kamctl/mysql/uri_db-create.sql
@@ -1,10 +1,10 @@
 INSERT INTO version (table_name, table_version) values ('uri','1');
-CREATE TABLE uri (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    username VARCHAR(64) DEFAULT '' NOT NULL,
-    domain VARCHAR(64) DEFAULT '' NOT NULL,
-    uri_user VARCHAR(64) DEFAULT '' NOT NULL,
-    last_modified DATETIME DEFAULT '1900-01-01 00:00:01' NOT NULL,
-    CONSTRAINT account_idx UNIQUE (username, domain, uri_user)
+CREATE TABLE `uri` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `username` VARCHAR(64) DEFAULT '' NOT NULL,
+    `domain` VARCHAR(64) DEFAULT '' NOT NULL,
+    `uri_user` VARCHAR(64) DEFAULT '' NOT NULL,
+    `last_modified` DATETIME DEFAULT '1900-01-01 00:00:01' NOT NULL,
+    CONSTRAINT account_idx UNIQUE (`username`, `domain`, `uri_user`)
 );
 
diff --git a/utils/kamctl/mysql/userblacklist-create.sql b/utils/kamctl/mysql/userblacklist-create.sql
index 12ae2c9..a01f856 100644
--- a/utils/kamctl/mysql/userblacklist-create.sql
+++ b/utils/kamctl/mysql/userblacklist-create.sql
@@ -1,21 +1,21 @@
 INSERT INTO version (table_name, table_version) values ('userblacklist','1');
-CREATE TABLE userblacklist (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    username VARCHAR(64) DEFAULT '' NOT NULL,
-    domain VARCHAR(64) DEFAULT '' NOT NULL,
-    prefix VARCHAR(64) DEFAULT '' NOT NULL,
-    whitelist TINYINT(1) DEFAULT 0 NOT NULL
+CREATE TABLE `userblacklist` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `username` VARCHAR(64) DEFAULT '' NOT NULL,
+    `domain` VARCHAR(64) DEFAULT '' NOT NULL,
+    `prefix` VARCHAR(64) DEFAULT '' NOT NULL,
+    `whitelist` TINYINT(1) DEFAULT 0 NOT NULL
 );
 
-CREATE INDEX userblacklist_idx ON userblacklist (username, domain, prefix);
+CREATE INDEX userblacklist_idx ON userblacklist (`username`, `domain`, `prefix`);
 
 INSERT INTO version (table_name, table_version) values ('globalblacklist','1');
-CREATE TABLE globalblacklist (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    prefix VARCHAR(64) DEFAULT '' NOT NULL,
-    whitelist TINYINT(1) DEFAULT 0 NOT NULL,
-    description VARCHAR(255) DEFAULT NULL
+CREATE TABLE `globalblacklist` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `prefix` VARCHAR(64) DEFAULT '' NOT NULL,
+    `whitelist` TINYINT(1) DEFAULT 0 NOT NULL,
+    `description` VARCHAR(255) DEFAULT NULL
 );
 
-CREATE INDEX globalblacklist_idx ON globalblacklist (prefix);
+CREATE INDEX globalblacklist_idx ON globalblacklist (`prefix`);
 
diff --git a/utils/kamctl/mysql/usrloc-create.sql b/utils/kamctl/mysql/usrloc-create.sql
index b510771..7ad9b43 100644
--- a/utils/kamctl/mysql/usrloc-create.sql
+++ b/utils/kamctl/mysql/usrloc-create.sql
@@ -1,42 +1,46 @@
-INSERT INTO version (table_name, table_version) values ('location','6');
-CREATE TABLE location (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    ruid VARCHAR(64) DEFAULT '' NOT NULL,
-    username VARCHAR(64) DEFAULT '' NOT NULL,
-    domain VARCHAR(64) DEFAULT NULL,
-    contact VARCHAR(255) DEFAULT '' NOT NULL,
-    received VARCHAR(128) DEFAULT NULL,
-    path VARCHAR(512) DEFAULT NULL,
-    expires DATETIME DEFAULT '2030-05-28 21:32:15' NOT NULL,
-    q FLOAT(10,2) DEFAULT 1.0 NOT NULL,
-    callid VARCHAR(255) DEFAULT 'Default-Call-ID' NOT NULL,
-    cseq INT(11) DEFAULT 1 NOT NULL,
-    last_modified DATETIME DEFAULT '1900-01-01 00:00:01' NOT NULL,
-    flags INT(11) DEFAULT 0 NOT NULL,
-    cflags INT(11) DEFAULT 0 NOT NULL,
-    user_agent VARCHAR(255) DEFAULT '' NOT NULL,
-    socket VARCHAR(64) DEFAULT NULL,
-    methods INT(11) DEFAULT NULL,
-    instance VARCHAR(255) DEFAULT NULL,
-    reg_id INT(11) DEFAULT 0 NOT NULL,
-    CONSTRAINT ruid_idx UNIQUE (ruid)
+INSERT INTO version (table_name, table_version) values ('location','8');
+CREATE TABLE `location` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `ruid` VARCHAR(64) DEFAULT '' NOT NULL,
+    `username` VARCHAR(64) DEFAULT '' NOT NULL,
+    `domain` VARCHAR(64) DEFAULT NULL,
+    `contact` VARCHAR(255) DEFAULT '' NOT NULL,
+    `received` VARCHAR(128) DEFAULT NULL,
+    `path` VARCHAR(512) DEFAULT NULL,
+    `expires` DATETIME DEFAULT '2030-05-28 21:32:15' NOT NULL,
+    `q` FLOAT(10,2) DEFAULT 1.0 NOT NULL,
+    `callid` VARCHAR(255) DEFAULT 'Default-Call-ID' NOT NULL,
+    `cseq` INT(11) DEFAULT 1 NOT NULL,
+    `last_modified` DATETIME DEFAULT '1900-01-01 00:00:01' NOT NULL,
+    `flags` INT(11) DEFAULT 0 NOT NULL,
+    `cflags` INT(11) DEFAULT 0 NOT NULL,
+    `user_agent` VARCHAR(255) DEFAULT '' NOT NULL,
+    `socket` VARCHAR(64) DEFAULT NULL,
+    `methods` INT(11) DEFAULT NULL,
+    `instance` VARCHAR(255) DEFAULT NULL,
+    `reg_id` INT(11) DEFAULT 0 NOT NULL,
+    `server_id` INT(11) DEFAULT 0 NOT NULL,
+    `connection_id` INT(11) DEFAULT 0 NOT NULL,
+    `keepalive` INT(11) DEFAULT 0 NOT NULL,
+    `partition` INT(11) DEFAULT 0 NOT NULL,
+    CONSTRAINT ruid_idx UNIQUE (`ruid`)
 );
 
-CREATE INDEX account_contact_idx ON location (username, domain, contact);
-CREATE INDEX expires_idx ON location (expires);
+CREATE INDEX account_contact_idx ON location (`username`, `domain`, `contact`);
+CREATE INDEX expires_idx ON location (`expires`);
 
 INSERT INTO version (table_name, table_version) values ('location_attrs','1');
-CREATE TABLE location_attrs (
-    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
-    ruid VARCHAR(64) DEFAULT '' NOT NULL,
-    username VARCHAR(64) DEFAULT '' NOT NULL,
-    domain VARCHAR(64) DEFAULT NULL,
-    aname VARCHAR(64) DEFAULT '' NOT NULL,
-    atype INT(11) DEFAULT 0 NOT NULL,
-    avalue VARCHAR(255) DEFAULT '' NOT NULL,
-    last_modified DATETIME DEFAULT '1900-01-01 00:00:01' NOT NULL
+CREATE TABLE `location_attrs` (
+    `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    `ruid` VARCHAR(64) DEFAULT '' NOT NULL,
+    `username` VARCHAR(64) DEFAULT '' NOT NULL,
+    `domain` VARCHAR(64) DEFAULT NULL,
+    `aname` VARCHAR(64) DEFAULT '' NOT NULL,
+    `atype` INT(11) DEFAULT 0 NOT NULL,
+    `avalue` VARCHAR(255) DEFAULT '' NOT NULL,
+    `last_modified` DATETIME DEFAULT '1900-01-01 00:00:01' NOT NULL
 );
 
-CREATE INDEX account_record_idx ON location_attrs (username, domain, ruid);
-CREATE INDEX last_modified_idx ON location_attrs (last_modified);
+CREATE INDEX account_record_idx ON location_attrs (`username`, `domain`, `ruid`);
+CREATE INDEX last_modified_idx ON location_attrs (`last_modified`);
 
diff --git a/utils/kamctl/oracle/acc-create.sql b/utils/kamctl/oracle/acc-create.sql
index 3e15a25..2a71e85 100644
--- a/utils/kamctl/oracle/acc-create.sql
+++ b/utils/kamctl/oracle/acc-create.sql
@@ -20,12 +20,12 @@ BEGIN map2users('acc'); END;
 /
 CREATE INDEX acc_callid_idx  ON acc (callid);
 
-INSERT INTO version (table_name, table_version) values ('acc_cdrs','1');
+INSERT INTO version (table_name, table_version) values ('acc_cdrs','2');
 CREATE TABLE acc_cdrs (
     id NUMBER(10) PRIMARY KEY,
-    start_time VARCHAR2(32) DEFAULT '',
-    end_time VARCHAR2(32) DEFAULT '',
-    duration VARCHAR2(32) DEFAULT ''
+    start_time DATE DEFAULT '2000-01-01 00:00:00',
+    end_time DATE DEFAULT '2000-01-01 00:00:00',
+    duration NUMBER(10,3) DEFAULT 0 NOT NULL
 );
 
 CREATE OR REPLACE TRIGGER acc_cdrs_tr
diff --git a/utils/kamctl/oracle/msilo-create.sql b/utils/kamctl/oracle/msilo-create.sql
index 25c4293..7cd8567 100644
--- a/utils/kamctl/oracle/msilo-create.sql
+++ b/utils/kamctl/oracle/msilo-create.sql
@@ -1,4 +1,4 @@
-INSERT INTO version (table_name, table_version) values ('silo','7');
+INSERT INTO version (table_name, table_version) values ('silo','8');
 CREATE TABLE silo (
     id NUMBER(10) PRIMARY KEY,
     src_addr VARCHAR2(128) DEFAULT '',
@@ -9,8 +9,8 @@ CREATE TABLE silo (
     exp_time NUMBER(10) DEFAULT 0 NOT NULL,
     snd_time NUMBER(10) DEFAULT 0 NOT NULL,
     ctype VARCHAR2(32) DEFAULT 'text/plain',
-    body BLOB DEFAULT '',
-    extra_hdrs CLOB DEFAULT '',
+    body BLOB,
+    extra_hdrs CLOB,
     callid VARCHAR2(128) DEFAULT '',
     status NUMBER(10) DEFAULT 0 NOT NULL
 );
diff --git a/utils/kamctl/oracle/presence-create.sql b/utils/kamctl/oracle/presence-create.sql
index 37fbefc..7365d66 100644
--- a/utils/kamctl/oracle/presence-create.sql
+++ b/utils/kamctl/oracle/presence-create.sql
@@ -1,4 +1,4 @@
-INSERT INTO version (table_name, table_version) values ('presentity','3');
+INSERT INTO version (table_name, table_version) values ('presentity','4');
 CREATE TABLE presentity (
     id NUMBER(10) PRIMARY KEY,
     username VARCHAR2(64),
@@ -9,6 +9,7 @@ CREATE TABLE presentity (
     received_time NUMBER(10),
     body BLOB,
     sender VARCHAR2(128),
+    priority NUMBER(10) DEFAULT 0 NOT NULL,
     CONSTRAINT presentity_presentity_idx  UNIQUE (username, domain, event, etag)
 );
 
diff --git a/utils/kamctl/oracle/registrar-create.sql b/utils/kamctl/oracle/registrar-create.sql
index 346564d..728b938 100644
--- a/utils/kamctl/oracle/registrar-create.sql
+++ b/utils/kamctl/oracle/registrar-create.sql
@@ -1,4 +1,4 @@
-INSERT INTO version (table_name, table_version) values ('aliases','6');
+INSERT INTO version (table_name, table_version) values ('aliases','8');
 CREATE TABLE aliases (
     id NUMBER(10) PRIMARY KEY,
     ruid VARCHAR2(64) DEFAULT '',
@@ -6,7 +6,7 @@ CREATE TABLE aliases (
     domain VARCHAR2(64) DEFAULT NULL,
     contact VARCHAR2(255) DEFAULT '',
     received VARCHAR2(128) DEFAULT NULL,
-    path VARCHAR2(128) DEFAULT NULL,
+    path VARCHAR2(512) DEFAULT NULL,
     expires DATE DEFAULT to_date('2030-05-28 21:32:15','yyyy-mm-dd hh24:mi:ss'),
     q NUMBER(10,2) DEFAULT 1.0 NOT NULL,
     callid VARCHAR2(255) DEFAULT 'Default-Call-ID',
@@ -19,6 +19,10 @@ CREATE TABLE aliases (
     methods NUMBER(10) DEFAULT NULL,
     instance VARCHAR2(255) DEFAULT NULL,
     reg_id NUMBER(10) DEFAULT 0 NOT NULL,
+    server_id NUMBER(10) DEFAULT 0 NOT NULL,
+    connection_id NUMBER(10) DEFAULT 0 NOT NULL,
+    keepalive NUMBER(10) DEFAULT 0 NOT NULL,
+    partition NUMBER(10) DEFAULT 0 NOT NULL,
     CONSTRAINT aliases_ruid_idx  UNIQUE (ruid)
 );
 
@@ -30,5 +34,6 @@ END aliases_tr;
 /
 BEGIN map2users('aliases'); END;
 /
-CREATE INDEX aliases_alias_idx  ON aliases (username, domain, contact);
+CREATE INDEX aliases_account_contact_idx  ON aliases (username, domain, contact);
+CREATE INDEX aliases_expires_idx  ON aliases (expires);
 
diff --git a/utils/kamctl/oracle/siptrace-create.sql b/utils/kamctl/oracle/siptrace-create.sql
index c20a8a2..a4f6bee 100644
--- a/utils/kamctl/oracle/siptrace-create.sql
+++ b/utils/kamctl/oracle/siptrace-create.sql
@@ -1,4 +1,4 @@
-INSERT INTO version (table_name, table_version) values ('sip_trace','3');
+INSERT INTO version (table_name, table_version) values ('sip_trace','4');
 CREATE TABLE sip_trace (
     id NUMBER(10) PRIMARY KEY,
     time_stamp DATE DEFAULT to_date('1900-01-01 00:00:01','yyyy-mm-dd hh24:mi:ss'),
@@ -11,6 +11,7 @@ CREATE TABLE sip_trace (
     fromip VARCHAR2(50) DEFAULT '',
     toip VARCHAR2(50) DEFAULT '',
     fromtag VARCHAR2(64) DEFAULT '',
+    totag VARCHAR2(64) DEFAULT '',
     direction VARCHAR2(4) DEFAULT ''
 );
 
diff --git a/utils/kamctl/oracle/usrloc-create.sql b/utils/kamctl/oracle/usrloc-create.sql
index 5397cb8..c2d0b99 100644
--- a/utils/kamctl/oracle/usrloc-create.sql
+++ b/utils/kamctl/oracle/usrloc-create.sql
@@ -1,4 +1,4 @@
-INSERT INTO version (table_name, table_version) values ('location','6');
+INSERT INTO version (table_name, table_version) values ('location','8');
 CREATE TABLE location (
     id NUMBER(10) PRIMARY KEY,
     ruid VARCHAR2(64) DEFAULT '',
@@ -19,6 +19,10 @@ CREATE TABLE location (
     methods NUMBER(10) DEFAULT NULL,
     instance VARCHAR2(255) DEFAULT NULL,
     reg_id NUMBER(10) DEFAULT 0 NOT NULL,
+    server_id NUMBER(10) DEFAULT 0 NOT NULL,
+    connection_id NUMBER(10) DEFAULT 0 NOT NULL,
+    keepalive NUMBER(10) DEFAULT 0 NOT NULL,
+    partition NUMBER(10) DEFAULT 0 NOT NULL,
     CONSTRAINT location_ruid_idx  UNIQUE (ruid)
 );
 
diff --git a/utils/kamctl/postgres/acc-create.sql b/utils/kamctl/postgres/acc-create.sql
index f3b1f55..713514f 100644
--- a/utils/kamctl/postgres/acc-create.sql
+++ b/utils/kamctl/postgres/acc-create.sql
@@ -12,12 +12,12 @@ CREATE TABLE acc (
 
 CREATE INDEX acc_callid_idx ON acc (callid);
 
-INSERT INTO version (table_name, table_version) values ('acc_cdrs','1');
+INSERT INTO version (table_name, table_version) values ('acc_cdrs','2');
 CREATE TABLE acc_cdrs (
     id SERIAL PRIMARY KEY NOT NULL,
-    start_time VARCHAR(32) DEFAULT '' NOT NULL,
-    end_time VARCHAR(32) DEFAULT '' NOT NULL,
-    duration VARCHAR(32) DEFAULT '' NOT NULL
+    start_time TIMESTAMP WITHOUT TIME ZONE DEFAULT '2000-01-01 00:00:00' NOT NULL,
+    end_time TIMESTAMP WITHOUT TIME ZONE DEFAULT '2000-01-01 00:00:00' NOT NULL,
+    duration REAL DEFAULT 0 NOT NULL
 );
 
 CREATE INDEX acc_cdrs_start_time_idx ON acc_cdrs (start_time);
diff --git a/utils/kamctl/postgres/msilo-create.sql b/utils/kamctl/postgres/msilo-create.sql
index 9dd4deb..5c58050 100644
--- a/utils/kamctl/postgres/msilo-create.sql
+++ b/utils/kamctl/postgres/msilo-create.sql
@@ -1,4 +1,4 @@
-INSERT INTO version (table_name, table_version) values ('silo','7');
+INSERT INTO version (table_name, table_version) values ('silo','8');
 CREATE TABLE silo (
     id SERIAL PRIMARY KEY NOT NULL,
     src_addr VARCHAR(128) DEFAULT '' NOT NULL,
@@ -9,8 +9,8 @@ CREATE TABLE silo (
     exp_time INTEGER DEFAULT 0 NOT NULL,
     snd_time INTEGER DEFAULT 0 NOT NULL,
     ctype VARCHAR(32) DEFAULT 'text/plain' NOT NULL,
-    body BYTEA DEFAULT '' NOT NULL,
-    extra_hdrs TEXT DEFAULT '' NOT NULL,
+    body BYTEA,
+    extra_hdrs TEXT,
     callid VARCHAR(128) DEFAULT '' NOT NULL,
     status INTEGER DEFAULT 0 NOT NULL
 );
diff --git a/utils/kamctl/postgres/presence-create.sql b/utils/kamctl/postgres/presence-create.sql
index 55b1449..f16614f 100644
--- a/utils/kamctl/postgres/presence-create.sql
+++ b/utils/kamctl/postgres/presence-create.sql
@@ -1,4 +1,4 @@
-INSERT INTO version (table_name, table_version) values ('presentity','3');
+INSERT INTO version (table_name, table_version) values ('presentity','4');
 CREATE TABLE presentity (
     id SERIAL PRIMARY KEY NOT NULL,
     username VARCHAR(64) NOT NULL,
@@ -9,6 +9,7 @@ CREATE TABLE presentity (
     received_time INTEGER NOT NULL,
     body BYTEA NOT NULL,
     sender VARCHAR(128) NOT NULL,
+    priority INTEGER DEFAULT 0 NOT NULL,
     CONSTRAINT presentity_presentity_idx UNIQUE (username, domain, event, etag)
 );
 
diff --git a/utils/kamctl/postgres/registrar-create.sql b/utils/kamctl/postgres/registrar-create.sql
index 11306cf..21aba71 100644
--- a/utils/kamctl/postgres/registrar-create.sql
+++ b/utils/kamctl/postgres/registrar-create.sql
@@ -1,4 +1,4 @@
-INSERT INTO version (table_name, table_version) values ('aliases','6');
+INSERT INTO version (table_name, table_version) values ('aliases','8');
 CREATE TABLE aliases (
     id SERIAL PRIMARY KEY NOT NULL,
     ruid VARCHAR(64) DEFAULT '' NOT NULL,
@@ -6,7 +6,7 @@ CREATE TABLE aliases (
     domain VARCHAR(64) DEFAULT NULL,
     contact VARCHAR(255) DEFAULT '' NOT NULL,
     received VARCHAR(128) DEFAULT NULL,
-    path VARCHAR(128) DEFAULT NULL,
+    path VARCHAR(512) DEFAULT NULL,
     expires TIMESTAMP WITHOUT TIME ZONE DEFAULT '2030-05-28 21:32:15' NOT NULL,
     q REAL DEFAULT 1.0 NOT NULL,
     callid VARCHAR(255) DEFAULT 'Default-Call-ID' NOT NULL,
@@ -19,8 +19,13 @@ CREATE TABLE aliases (
     methods INTEGER DEFAULT NULL,
     instance VARCHAR(255) DEFAULT NULL,
     reg_id INTEGER DEFAULT 0 NOT NULL,
+    server_id INTEGER DEFAULT 0 NOT NULL,
+    connection_id INTEGER DEFAULT 0 NOT NULL,
+    keepalive INTEGER DEFAULT 0 NOT NULL,
+    partition INTEGER DEFAULT 0 NOT NULL,
     CONSTRAINT aliases_ruid_idx UNIQUE (ruid)
 );
 
-CREATE INDEX aliases_alias_idx ON aliases (username, domain, contact);
+CREATE INDEX aliases_account_contact_idx ON aliases (username, domain, contact);
+CREATE INDEX aliases_expires_idx ON aliases (expires);
 
diff --git a/utils/kamctl/postgres/siptrace-create.sql b/utils/kamctl/postgres/siptrace-create.sql
index 90ab886..d7af4d2 100644
--- a/utils/kamctl/postgres/siptrace-create.sql
+++ b/utils/kamctl/postgres/siptrace-create.sql
@@ -1,4 +1,4 @@
-INSERT INTO version (table_name, table_version) values ('sip_trace','3');
+INSERT INTO version (table_name, table_version) values ('sip_trace','4');
 CREATE TABLE sip_trace (
     id SERIAL PRIMARY KEY NOT NULL,
     time_stamp TIMESTAMP WITHOUT TIME ZONE DEFAULT '1900-01-01 00:00:01' NOT NULL,
@@ -11,6 +11,7 @@ CREATE TABLE sip_trace (
     fromip VARCHAR(50) DEFAULT '' NOT NULL,
     toip VARCHAR(50) DEFAULT '' NOT NULL,
     fromtag VARCHAR(64) DEFAULT '' NOT NULL,
+    totag VARCHAR(64) DEFAULT '' NOT NULL,
     direction VARCHAR(4) DEFAULT '' NOT NULL
 );
 
diff --git a/utils/kamctl/postgres/usrloc-create.sql b/utils/kamctl/postgres/usrloc-create.sql
index 5321b8c..cd096b2 100644
--- a/utils/kamctl/postgres/usrloc-create.sql
+++ b/utils/kamctl/postgres/usrloc-create.sql
@@ -1,4 +1,4 @@
-INSERT INTO version (table_name, table_version) values ('location','6');
+INSERT INTO version (table_name, table_version) values ('location','8');
 CREATE TABLE location (
     id SERIAL PRIMARY KEY NOT NULL,
     ruid VARCHAR(64) DEFAULT '' NOT NULL,
@@ -19,6 +19,10 @@ CREATE TABLE location (
     methods INTEGER DEFAULT NULL,
     instance VARCHAR(255) DEFAULT NULL,
     reg_id INTEGER DEFAULT 0 NOT NULL,
+    server_id INTEGER DEFAULT 0 NOT NULL,
+    connection_id INTEGER DEFAULT 0 NOT NULL,
+    keepalive INTEGER DEFAULT 0 NOT NULL,
+    partition INTEGER DEFAULT 0 NOT NULL,
     CONSTRAINT location_ruid_idx UNIQUE (ruid)
 );
 
diff --git a/utils/kamctl/xhttp_pi/acc-table b/utils/kamctl/xhttp_pi/acc-table
index f7a60e7..e85c5c4 100644
--- a/utils/kamctl/xhttp_pi/acc-table
+++ b/utils/kamctl/xhttp_pi/acc-table
@@ -16,9 +16,9 @@
 		<table_name>acc_cdrs</table_name>
 		<db_url_id>mysql</db_url_id>
 		<column><field>id</field><type>DB1_INT</type></column>
-		<column><field>start_time</field><type>DB1_STR</type></column>
-		<column><field>end_time</field><type>DB1_STR</type></column>
-		<column><field>duration</field><type>DB1_STR</type></column>
+		<column><field>start_time</field><type>DB1_DATETIME</type></column>
+		<column><field>end_time</field><type>DB1_DATETIME</type></column>
+		<column><field>duration</field><type>DB1_DOUBLE</type></column>
 	</db_table>
 	<!-- Declaration of missed_calls table-->
 	<db_table id="missed_calls">
diff --git a/utils/kamctl/xhttp_pi/pi_framework.xml b/utils/kamctl/xhttp_pi/pi_framework.xml
index 22a120a..d0583be 100644
--- a/utils/kamctl/xhttp_pi/pi_framework.xml
+++ b/utils/kamctl/xhttp_pi/pi_framework.xml
@@ -47,9 +47,9 @@
 		<table_name>acc_cdrs</table_name>
 		<db_url_id>mysql</db_url_id>
 		<column><field>id</field><type>DB1_INT</type></column>
-		<column><field>start_time</field><type>DB1_STR</type></column>
-		<column><field>end_time</field><type>DB1_STR</type></column>
-		<column><field>duration</field><type>DB1_STR</type></column>
+		<column><field>start_time</field><type>DB1_DATETIME</type></column>
+		<column><field>end_time</field><type>DB1_DATETIME</type></column>
+		<column><field>duration</field><type>DB1_DOUBLE</type></column>
 	</db_table>
 	<!-- Declaration of missed_calls table-->
 	<db_table id="missed_calls">
@@ -503,6 +503,7 @@
 		<column><field>received_time</field><type>DB1_INT</type></column>
 		<column><field>body</field><type>DB1_BLOB</type></column>
 		<column><field>sender</field><type>DB1_STR</type></column>
+		<column><field>priority</field><type>DB1_INT</type></column>
 	</db_table>
 	<!-- Declaration of active_watchers table-->
 	<db_table id="active_watchers">
@@ -618,6 +619,10 @@
 		<column><field>methods</field><type>DB1_INT</type></column>
 		<column><field>instance</field><type>DB1_STR</type></column>
 		<column><field>reg_id</field><type>DB1_INT</type></column>
+		<column><field>server_id</field><type>DB1_INT</type></column>
+		<column><field>connection_id</field><type>DB1_INT</type></column>
+		<column><field>keepalive</field><type>DB1_INT</type></column>
+		<column><field>partition</field><type>DB1_INT</type></column>
 	</db_table>
 	<!-- Declaration of rls_presentity table-->
 	<db_table id="rls_presentity">
@@ -706,6 +711,7 @@
 		<column><field>fromip</field><type>DB1_STR</type></column>
 		<column><field>toip</field><type>DB1_STR</type></column>
 		<column><field>fromtag</field><type>DB1_STR</type></column>
+		<column><field>totag</field><type>DB1_STR</type></column>
 		<column><field>direction</field><type>DB1_STR</type></column>
 	</db_table>
 	<!-- Declaration of speed_dial table-->
@@ -876,6 +882,10 @@
 		<column><field>methods</field><type>DB1_INT</type></column>
 		<column><field>instance</field><type>DB1_STR</type></column>
 		<column><field>reg_id</field><type>DB1_INT</type></column>
+		<column><field>server_id</field><type>DB1_INT</type></column>
+		<column><field>connection_id</field><type>DB1_INT</type></column>
+		<column><field>keepalive</field><type>DB1_INT</type></column>
+		<column><field>partition</field><type>DB1_INT</type></column>
 	</db_table>
 	<!-- Declaration of location_attrs table-->
 	<db_table id="location_attrs">
@@ -2871,6 +2881,7 @@
 				<col><field>received_time</field></col>
 				<col><field>body</field></col>
 				<col><field>sender</field></col>
+				<col><field>priority</field></col>
 			</query_cols>
 		</cmd>
 		<cmd><cmd_name>add</cmd_name>
@@ -2885,6 +2896,7 @@
 				<col><field>received_time</field></col>
 				<col><field>body</field></col>
 				<col><field>sender</field></col>
+				<col><field>priority</field></col>
 			</query_cols>
 		</cmd>
 		<cmd><cmd_name>update</cmd_name>
@@ -2902,6 +2914,7 @@
 				<col><field>received_time</field></col>
 				<col><field>body</field></col>
 				<col><field>sender</field></col>
+				<col><field>priority</field></col>
 			</query_cols>
 		</cmd>
 		<cmd><cmd_name>delete</cmd_name>
@@ -3280,6 +3293,10 @@
 				<col><field>methods</field></col>
 				<col><field>instance</field></col>
 				<col><field>reg_id</field></col>
+				<col><field>server_id</field></col>
+				<col><field>connection_id</field></col>
+				<col><field>keepalive</field></col>
+				<col><field>partition</field></col>
 			</query_cols>
 		</cmd>
 		<cmd><cmd_name>add</cmd_name>
@@ -3304,6 +3321,10 @@
 				<col><field>methods</field></col>
 				<col><field>instance</field></col>
 				<col><field>reg_id</field></col>
+				<col><field>server_id</field></col>
+				<col><field>connection_id</field></col>
+				<col><field>keepalive</field></col>
+				<col><field>partition</field></col>
 			</query_cols>
 		</cmd>
 		<cmd><cmd_name>update</cmd_name>
@@ -3331,6 +3352,10 @@
 				<col><field>methods</field></col>
 				<col><field>instance</field></col>
 				<col><field>reg_id</field></col>
+				<col><field>server_id</field></col>
+				<col><field>connection_id</field></col>
+				<col><field>keepalive</field></col>
+				<col><field>partition</field></col>
 			</query_cols>
 		</cmd>
 		<cmd><cmd_name>delete</cmd_name>
@@ -3630,6 +3655,7 @@
 				<col><field>fromip</field></col>
 				<col><field>toip</field></col>
 				<col><field>fromtag</field></col>
+				<col><field>totag</field></col>
 				<col><field>direction</field></col>
 			</query_cols>
 		</cmd>
@@ -3647,6 +3673,7 @@
 				<col><field>fromip</field></col>
 				<col><field>toip</field></col>
 				<col><field>fromtag</field></col>
+				<col><field>totag</field></col>
 				<col><field>direction</field></col>
 			</query_cols>
 		</cmd>
@@ -3667,6 +3694,7 @@
 				<col><field>fromip</field></col>
 				<col><field>toip</field></col>
 				<col><field>fromtag</field></col>
+				<col><field>totag</field></col>
 				<col><field>direction</field></col>
 			</query_cols>
 		</cmd>
@@ -4304,6 +4332,10 @@
 				<col><field>methods</field></col>
 				<col><field>instance</field></col>
 				<col><field>reg_id</field></col>
+				<col><field>server_id</field></col>
+				<col><field>connection_id</field></col>
+				<col><field>keepalive</field></col>
+				<col><field>partition</field></col>
 			</query_cols>
 		</cmd>
 		<cmd><cmd_name>add</cmd_name>
@@ -4328,6 +4360,10 @@
 				<col><field>methods</field></col>
 				<col><field>instance</field></col>
 				<col><field>reg_id</field></col>
+				<col><field>server_id</field></col>
+				<col><field>connection_id</field></col>
+				<col><field>keepalive</field></col>
+				<col><field>partition</field></col>
 			</query_cols>
 		</cmd>
 		<cmd><cmd_name>update</cmd_name>
@@ -4355,6 +4391,10 @@
 				<col><field>methods</field></col>
 				<col><field>instance</field></col>
 				<col><field>reg_id</field></col>
+				<col><field>server_id</field></col>
+				<col><field>connection_id</field></col>
+				<col><field>keepalive</field></col>
+				<col><field>partition</field></col>
 			</query_cols>
 		</cmd>
 		<cmd><cmd_name>delete</cmd_name>
diff --git a/utils/kamctl/xhttp_pi/presence-mod b/utils/kamctl/xhttp_pi/presence-mod
index 8fd5a69..1c0b481 100644
--- a/utils/kamctl/xhttp_pi/presence-mod
+++ b/utils/kamctl/xhttp_pi/presence-mod
@@ -13,6 +13,7 @@
 				<col><field>received_time</field></col>
 				<col><field>body</field></col>
 				<col><field>sender</field></col>
+				<col><field>priority</field></col>
 			</query_cols>
 		</cmd>
 		<cmd><cmd_name>add</cmd_name>
@@ -27,6 +28,7 @@
 				<col><field>received_time</field></col>
 				<col><field>body</field></col>
 				<col><field>sender</field></col>
+				<col><field>priority</field></col>
 			</query_cols>
 		</cmd>
 		<cmd><cmd_name>update</cmd_name>
@@ -44,6 +46,7 @@
 				<col><field>received_time</field></col>
 				<col><field>body</field></col>
 				<col><field>sender</field></col>
+				<col><field>priority</field></col>
 			</query_cols>
 		</cmd>
 		<cmd><cmd_name>delete</cmd_name>
diff --git a/utils/kamctl/xhttp_pi/presence-table b/utils/kamctl/xhttp_pi/presence-table
index af716da..53ee382 100644
--- a/utils/kamctl/xhttp_pi/presence-table
+++ b/utils/kamctl/xhttp_pi/presence-table
@@ -11,6 +11,7 @@
 		<column><field>received_time</field><type>DB1_INT</type></column>
 		<column><field>body</field><type>DB1_BLOB</type></column>
 		<column><field>sender</field><type>DB1_STR</type></column>
+		<column><field>priority</field><type>DB1_INT</type></column>
 	</db_table>
 	<!-- Declaration of active_watchers table-->
 	<db_table id="active_watchers">
diff --git a/utils/kamctl/xhttp_pi/registrar-mod b/utils/kamctl/xhttp_pi/registrar-mod
index 76733ae..747675f 100644
--- a/utils/kamctl/xhttp_pi/registrar-mod
+++ b/utils/kamctl/xhttp_pi/registrar-mod
@@ -23,6 +23,10 @@
 				<col><field>methods</field></col>
 				<col><field>instance</field></col>
 				<col><field>reg_id</field></col>
+				<col><field>server_id</field></col>
+				<col><field>connection_id</field></col>
+				<col><field>keepalive</field></col>
+				<col><field>partition</field></col>
 			</query_cols>
 		</cmd>
 		<cmd><cmd_name>add</cmd_name>
@@ -47,6 +51,10 @@
 				<col><field>methods</field></col>
 				<col><field>instance</field></col>
 				<col><field>reg_id</field></col>
+				<col><field>server_id</field></col>
+				<col><field>connection_id</field></col>
+				<col><field>keepalive</field></col>
+				<col><field>partition</field></col>
 			</query_cols>
 		</cmd>
 		<cmd><cmd_name>update</cmd_name>
@@ -74,6 +82,10 @@
 				<col><field>methods</field></col>
 				<col><field>instance</field></col>
 				<col><field>reg_id</field></col>
+				<col><field>server_id</field></col>
+				<col><field>connection_id</field></col>
+				<col><field>keepalive</field></col>
+				<col><field>partition</field></col>
 			</query_cols>
 		</cmd>
 		<cmd><cmd_name>delete</cmd_name>
diff --git a/utils/kamctl/xhttp_pi/registrar-table b/utils/kamctl/xhttp_pi/registrar-table
index d4afc82..58dd49f 100644
--- a/utils/kamctl/xhttp_pi/registrar-table
+++ b/utils/kamctl/xhttp_pi/registrar-table
@@ -21,4 +21,8 @@
 		<column><field>methods</field><type>DB1_INT</type></column>
 		<column><field>instance</field><type>DB1_STR</type></column>
 		<column><field>reg_id</field><type>DB1_INT</type></column>
+		<column><field>server_id</field><type>DB1_INT</type></column>
+		<column><field>connection_id</field><type>DB1_INT</type></column>
+		<column><field>keepalive</field><type>DB1_INT</type></column>
+		<column><field>partition</field><type>DB1_INT</type></column>
 	</db_table>
diff --git a/utils/kamctl/xhttp_pi/siptrace-mod b/utils/kamctl/xhttp_pi/siptrace-mod
index c368dd9..09d62d3 100644
--- a/utils/kamctl/xhttp_pi/siptrace-mod
+++ b/utils/kamctl/xhttp_pi/siptrace-mod
@@ -15,6 +15,7 @@
 				<col><field>fromip</field></col>
 				<col><field>toip</field></col>
 				<col><field>fromtag</field></col>
+				<col><field>totag</field></col>
 				<col><field>direction</field></col>
 			</query_cols>
 		</cmd>
@@ -32,6 +33,7 @@
 				<col><field>fromip</field></col>
 				<col><field>toip</field></col>
 				<col><field>fromtag</field></col>
+				<col><field>totag</field></col>
 				<col><field>direction</field></col>
 			</query_cols>
 		</cmd>
@@ -52,6 +54,7 @@
 				<col><field>fromip</field></col>
 				<col><field>toip</field></col>
 				<col><field>fromtag</field></col>
+				<col><field>totag</field></col>
 				<col><field>direction</field></col>
 			</query_cols>
 		</cmd>
diff --git a/utils/kamctl/xhttp_pi/siptrace-table b/utils/kamctl/xhttp_pi/siptrace-table
index 22d87ea..fcb100f 100644
--- a/utils/kamctl/xhttp_pi/siptrace-table
+++ b/utils/kamctl/xhttp_pi/siptrace-table
@@ -13,5 +13,6 @@
 		<column><field>fromip</field><type>DB1_STR</type></column>
 		<column><field>toip</field><type>DB1_STR</type></column>
 		<column><field>fromtag</field><type>DB1_STR</type></column>
+		<column><field>totag</field><type>DB1_STR</type></column>
 		<column><field>direction</field><type>DB1_STR</type></column>
 	</db_table>
diff --git a/utils/kamctl/xhttp_pi/usrloc-mod b/utils/kamctl/xhttp_pi/usrloc-mod
index 395bdc0..bfc2c93 100644
--- a/utils/kamctl/xhttp_pi/usrloc-mod
+++ b/utils/kamctl/xhttp_pi/usrloc-mod
@@ -23,6 +23,10 @@
 				<col><field>methods</field></col>
 				<col><field>instance</field></col>
 				<col><field>reg_id</field></col>
+				<col><field>server_id</field></col>
+				<col><field>connection_id</field></col>
+				<col><field>keepalive</field></col>
+				<col><field>partition</field></col>
 			</query_cols>
 		</cmd>
 		<cmd><cmd_name>add</cmd_name>
@@ -47,6 +51,10 @@
 				<col><field>methods</field></col>
 				<col><field>instance</field></col>
 				<col><field>reg_id</field></col>
+				<col><field>server_id</field></col>
+				<col><field>connection_id</field></col>
+				<col><field>keepalive</field></col>
+				<col><field>partition</field></col>
 			</query_cols>
 		</cmd>
 		<cmd><cmd_name>update</cmd_name>
@@ -74,6 +82,10 @@
 				<col><field>methods</field></col>
 				<col><field>instance</field></col>
 				<col><field>reg_id</field></col>
+				<col><field>server_id</field></col>
+				<col><field>connection_id</field></col>
+				<col><field>keepalive</field></col>
+				<col><field>partition</field></col>
 			</query_cols>
 		</cmd>
 		<cmd><cmd_name>delete</cmd_name>
diff --git a/utils/kamctl/xhttp_pi/usrloc-table b/utils/kamctl/xhttp_pi/usrloc-table
index 7832158..a78fd4a 100644
--- a/utils/kamctl/xhttp_pi/usrloc-table
+++ b/utils/kamctl/xhttp_pi/usrloc-table
@@ -21,6 +21,10 @@
 		<column><field>methods</field><type>DB1_INT</type></column>
 		<column><field>instance</field><type>DB1_STR</type></column>
 		<column><field>reg_id</field><type>DB1_INT</type></column>
+		<column><field>server_id</field><type>DB1_INT</type></column>
+		<column><field>connection_id</field><type>DB1_INT</type></column>
+		<column><field>keepalive</field><type>DB1_INT</type></column>
+		<column><field>partition</field><type>DB1_INT</type></column>
 	</db_table>
 	<!-- Declaration of location_attrs table-->
 	<db_table id="location_attrs">
diff --git a/utils/pdbt/.gitignore b/utils/pdbt/.gitignore
new file mode 100644
index 0000000..45a2d95
--- /dev/null
+++ b/utils/pdbt/.gitignore
@@ -0,0 +1,2 @@
+utils/pdbt/pdb_server
+utils/pdbt/pdbt
diff --git a/utils/pdbt/debian/pdb-server.init.d b/utils/pdbt/debian/pdb-server.init.d
new file mode 100644
index 0000000..49a9b31
--- /dev/null
+++ b/utils/pdbt/debian/pdb-server.init.d
@@ -0,0 +1,48 @@
+#! /bin/sh
+
+PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
+DAEMON=/usr/bin/pdb_server
+NAME=pdb_server
+DESC=pdb_server
+PIDFILE=/var/run/pdb_server.pid
+
+test -x $DAEMON || exit 0
+
+# Include pdb_server defaults if available
+if [ -f /etc/default/pdb_server ] ; then
+        . /etc/default/pdb_server
+fi
+
+# Include pdb_server config if available
+if [ -f /etc/pdb_server.conf ] ; then
+        . /etc/pdb_server.conf
+fi
+
+set -e
+
+case "$1" in
+  start)
+        echo -n "Starting $DESC: "
+        start-stop-daemon --start --background --make-pidfile --pidfile $PIDFILE -c $PDBUSER -g $PDBGROUP --exec $DAEMON -- -d -m "$MMAPFILE" -i "$BINDADDR" -p "$BINDPORT"
+        echo "."
+        ;;
+  stop)
+        echo -n "Stopping $DESC: "
+        # start-stop-daemon --stop --pidfile $PIDFILE --exec $DAEMON
+        if pgrep -x $NAME &> /dev/null; then killall $NAME; fi
+        rm -f $PIDFILE
+        echo "$NAME."
+        ;;
+  restart|force-reload)
+        if pgrep -x $NAME &> /dev/null; then killall $NAME; fi
+        rm -f $PIDFILE
+        start-stop-daemon --start --background --make-pidfile --pidfile $PIDFILE -c $PDBUSER -g $PDBGROUP --exec $DAEMON -- -d -m "$MMAPFILE" -i "$BINDADDR" -p "$BINDPORT"
+        ;;
+  *)
+        N=/etc/init.d/$NAME
+        echo "Usage: $N {start|stop|restart|force-reload}" >&2
+        exit 1
+        ;;
+esac
+
+exit 0
diff --git a/utils/sercmd/Makefile b/utils/sercmd/Makefile
deleted file mode 100644
index 86db185..0000000
--- a/utils/sercmd/Makefile
+++ /dev/null
@@ -1,107 +0,0 @@
-# $Id$
-COREPATH=../..
-include $(COREPATH)/Makefile.defs
-include $(COREPATH)/Makefile.targets
-
-auto_gen=
-RELEASE=0.2
-UTIL_SRC_NAME=sercmd
-ifeq ($(FLAVOUR),kamailio)
-	NAME=kamcmd
-else
-	NAME=sercmd
-endif
-
-readline_locations= /usr/include/readline/readline.h \
-					$(LOCALBASE)/include/readline/readline.h
-
-use_readline ?=
-ifneq (,$(MAKECMDGOALS))
-ifeq (,$(filter-out $(nodep_targets),$(MAKECMDGOALS)))
-#set it to empty, we don't need to detect/use it for clean, doc a.s.o
-override use_readline:=
-quiet=1
-endif
-endif #ifneq (,$(MAKECMDGOALS))
-
-
-# erase common DEFS (not needed)
-C_DEFS:=
-DEFS:= -DNAME='"$(NAME)"' -DSRNAME='"$(MAIN_NAME)"' -DVERSION='"$(RELEASE)"' -D__OS_$(OS) \
-		$(filter -D%HAVE -DARCH% -DOS% -D__CPU% -D__OS%, $(DEFS))
-
-# use proper libs (we can't rely on LIBS value since we might be called
-# from a module Makefile)
-#LIBS:=$(filter-out -lfl  -ldl -lpthread -lssl -lcrypto, $(LIBS))
-
-ifeq ($(OS), linux)
-	LIBS:= -lresolv
-endif
-ifeq ($(OS), solaris)
-	LIBS:= -lresolv -L$(LOCALBASE)/lib -lxnet -lnsl
-endif
-ifeq ($(OS), freebsd)
-	LIBS:=
-endif
-ifeq  ($(OS), dragonfly)
-	LIBS:= -L$(LOCALBASE)/lib
-endif
-ifeq ($(OS), openbsd)
-	LIBS:=
-endif
-ifeq ($(OS), netbsd)
-	LIBS:=
-endif
-ifeq ($(OS), darwin)
-	LIBS:= -lresolv
-endif
-ifneq (,$(findstring cygwin, $(OS)))
-	LIBS:= -lresolv
-endif
-
-ifeq ($(use_readline),)
-readline_path := $(shell  \
-						for r in $(readline_locations) ""; do \
-							if [ -r "$$r" ] ; then echo $$r; exit; fi;  \
-						done;\
-					)
-ifneq ($(readline_path),)
-use_readline := 1
-endif
-endif
-
-ifeq ($(use_readline),1)
-	DEFS+=-DUSE_READLINE
-	LIBS+=-lreadline -lncurses
-endif
-
-
-include $(COREPATH)/Makefile.utils
-
-ifeq (,$(quiet))
-ifeq ($(use_readline),1)
-$(info readline detected ($(readline_path)) )
-$(info command completion enabled)
-else
-$(info "no readline include files detected, disabling readline support")
-$(info "command completion disabled" )
-$(info "to force readline support try 'make use_readline=1'")
-endif
-endif # ifeq (,$(quiet))
-
-$(NAME).o: 
-
-.PHONY: msg
-msg:
-	@if [ "$(use_readline)" = "1" ]; then \
-		echo; echo "readline detected ($(readline_path)):"; \
-		echo "command completion enabled"; echo ; \
-	else \
-		echo ; \
-		echo "no readline include files detected, disabling readline support";\
-		echo "command completion disabled"; \
-		echo "(to force readline support try 'make use_readline=1')";\
-		echo ; \
-	fi
-
-modules:
diff --git a/utils/sercmd/sercmd.8 b/utils/sercmd/sercmd.8
deleted file mode 100644
index 905ef99..0000000
--- a/utils/sercmd/sercmd.8
+++ /dev/null
@@ -1,35 +0,0 @@
-.\" $Id$
-.TH kamcmd 8 23.10.2012 Kamailio "sip-router" 
-.\" Process with
-.\" groff -man -Tascii kamcmd.8 
-.\"
-.SH NAME
-kamcmd \- sip-router command line tool
-.SH SYNOPSIS
-.B kamcmd
-[
-.B \-h
-]
-
-.SH DESCRIPTION
-.B kamcmd
-is a command line to interact with
-.B Kamailio SIP server
-It can be used to manage users, domains, aliases and other server options.
-
-.SH OPTIONS
-.TP 12
-.B \-h
-display a short usage description, including all available options.
-
-.SH AUTHORS
-
-see 
-.B /usr/share/doc/kamailio/AUTHORS
-
-.SH SEE ALSO
-.BR kamailio(8),
-.BR kamailio.cfg(5)
-.PP
-Full documentation on sip-router is available at
-.I http://www.kamailio.org/.
diff --git a/ver.c b/ver.c
index e81586f..3136e73 100644
--- a/ver.c
+++ b/ver.c
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- * 
  * Copyright (C) 2010 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -15,15 +13,11 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/** version strings.
+
+/** Kamailio core :: version strings.
  * @file ver.c
  * @ingroup: core
  */
-/*
- * History:
- * --------
- *  2010-07-13  initial version (andrei)
-*/
 
 #include "ver_defs.h"
 #include "autover.h" /* REPO_VER, REPO_STATE */
@@ -35,7 +29,15 @@ const char ver_version[] = VERSION;
 const char ver_arch[] = ARCH;
 const char ver_os[] = OS_QUOTED;
 const char ver_id[] = REPO_HASH " " REPO_STATE;
+#ifdef VERSION_NODATE
+const char ver_compiled_time[] =  "" ;
+#else
+#ifdef VERSION_DATE
+const char ver_compiled_time[] =  VERSION_DATE ;
+#else
 const char ver_compiled_time[] =  __TIME__ " " __DATE__ ;
+#endif
+#endif
 const char ver_compiler[] = COMPILER;
 
 const char ver_flags[] = SER_COMPILE_FLAGS;
diff --git a/ver.h b/ver.h
index 25f1309..5216f0c 100644
--- a/ver.h
+++ b/ver.h
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- * 
  * Copyright (C) 2010 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -15,15 +13,11 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
+
 /** version strings.
  * @file ver.h
  * @ingroup: core
  */
-/*
- * History:
- * --------
- *  2010-07-13  initial version (andrei)
-*/
 
 #ifndef __ver_h
 #define __ver_h
diff --git a/ver_defs.h b/ver_defs.h
index e6ada6a..7c9d209 100644
--- a/ver_defs.h
+++ b/ver_defs.h
@@ -1,19 +1,16 @@
 /*
- * $Id$
- *
  * version and compile flags macros 
  *
- *
  * Copyright (C) 2004 FhG Fokus
  *
- * This file is part of SIP-router, a free SIP server.
+ * This file is part of Kamailio, a free SIP server.
  *
- * SIP-router is free software; you can redistribute it and/or modify
+ * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
- * SIP-router is distributed in the hope that it will be useful,
+ * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
diff --git a/xavp.c b/xavp.c
index 3d12f49..a6c62e7 100644
--- a/xavp.c
+++ b/xavp.c
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2009 Daniel-Constantin Mierla (asipto.com) 
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -15,13 +13,13 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/*
- * History:
- * --------
- *  2009-05-20  created by daniel
+/*!
+ * \file
+ * \brief Kamailio core :: Extended AVPs
+ * \ingroup core
+ * Module: \ref core
  */
 
-
 #ifdef WITH_XAVP
 
 #include <stdio.h>
diff --git a/xavp.h b/xavp.h
index 8332069..42413e7 100644
--- a/xavp.h
+++ b/xavp.h
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * Copyright (C) 2009 Daniel-Constantin Mierla (asipto.com) 
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -15,11 +13,6 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/*
- * History:
- * --------
- *  2009-05-20  created by daniel
- */
 
 
 #ifndef _SR_XAVP_H_
@@ -77,7 +70,7 @@ typedef struct _sr_xavp {
 } sr_xavp_t;
 
 int xavp_init_head(void);
-void avpx_free(sr_xavp_t *xa);
+void xavp_free(sr_xavp_t *xa);
 
 int xavp_add(sr_xavp_t *xavp, sr_xavp_t **list);
 int xavp_add_last(sr_xavp_t *xavp, sr_xavp_t **list);

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-voip/kamailio.git



More information about the Pkg-voip-commits mailing list