diff options
author | Nathan Angelacos <nangel@alpinelinux.org> | 2015-06-08 22:03:19 +0000 |
---|---|---|
committer | Natanael Copa <ncopa@alpinelinux.org> | 2015-06-09 14:58:26 +0000 |
commit | 9cec9d32fe869695a47042fb35c5043db9fc57f7 (patch) | |
tree | 88c90304610229620dc933ecedb2e7738aa88f81 /main | |
parent | 465b2767e69576b62efeefa923720d5e2b866ced (diff) | |
download | aports-9cec9d32fe869695a47042fb35c5043db9fc57f7.tar.bz2 aports-9cec9d32fe869695a47042fb35c5043db9fc57f7.tar.xz |
main/kamailio use mohqueue v0.11 module from github
Diffstat (limited to 'main')
-rw-r--r-- | main/kamailio/0002-mohqueue-v0-11.patch | 2851 | ||||
-rw-r--r-- | main/kamailio/APKBUILD | 6 |
2 files changed, 2856 insertions, 1 deletions
diff --git a/main/kamailio/0002-mohqueue-v0-11.patch b/main/kamailio/0002-mohqueue-v0-11.patch new file mode 100644 index 0000000000..f6285a56b0 --- /dev/null +++ b/main/kamailio/0002-mohqueue-v0-11.patch @@ -0,0 +1,2851 @@ +--- a/modules/mohqueue/NOTES ++++ b/modules/mohqueue/NOTES +@@ -1,6 +1,9 @@ +-Things to look into: +- +-* RFC3261, section 12.1.1 requires UAS to copy Record-Route +-* Check to see if any memory leaks. +-* Should probably respond when caller says BYE after queue says BYE. +-* check RAck number ++Things to look into: ++ ++* RFC3261, section 12.1.1 requires UAS to copy Record-Route ++ ++* Check to see if any memory leaks. ++ ++* Should probably respond when caller says BYE after queue says BYE. ++ ++* check RAck number +\ No newline at end of file +--- a/modules/mohqueue/mohq.c ++++ b/modules/mohqueue/mohq.c +@@ -1,10 +1,8 @@ + /* +- * $Id$ ++ * Copyright (C) 2013-15 Robert Boisvert + * +- * Copyright (C) 2013 Robert Boisvert ++ * This file is part of the mohqueue module for Kamailio, a free SIP server. + * +- * This file is part of the mohqueue module for sip-router, 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 + * the Free Software Foundation; either version 2 of the License, or +@@ -61,9 +59,9 @@ + }; + + /* PARAMETERS */ +-str db_url = str_init(DEFAULT_DB_URL); +-str db_ctable = str_init("mohqcalls"); +-str db_qtable = str_init("mohqueues"); ++str db_url = str_init (DEFAULT_DB_URL); ++str db_ctable = str_init ("mohqcalls"); ++str db_qtable = str_init ("mohqueues"); + char *mohdir = ""; + int moh_maxcalls = 50; + +@@ -134,81 +132,84 @@ + static int init_cfg (void) + + { ++int bfnd = 0; ++int berror = 0; ++struct stat psb [1]; ++ + /********** + * db_url, db_ctable, db_qtable exist? + **********/ + +- if (!db_url.s || db_url.len<=0) ++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"); ++ berror = 1; + } +- pmod_data->pcfg->db_url = db_url; +- +- if (!db_ctable.s || db_ctable.len<=0) ++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"); ++ berror = 1; + } +- pmod_data->pcfg->db_ctable = db_ctable; +- +- if (!db_qtable.s || db_qtable.len<=0) ++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"); ++ berror = 1; + } +- pmod_data->pcfg->db_qtable = db_qtable; + +- + /********** + * mohdir + * o exists? + * o directory? + **********/ + +- if (!*mohdir) ++if (!*mohdir) + { +- LM_ERR ("mohdir parameter not set!"); +- return 0; ++ LM_ERR ("mohdir parameter not set!\n"); ++ berror = 1; + } +- if (strlen(mohdir) > MOHDIRLEN) ++else if (strlen (mohdir) > MOHDIRLEN) + { +- LM_ERR ("mohdir too long!"); +- return 0; ++ LM_ERR ("mohdir too long!\n"); ++ berror = 1; + } +- pmod_data->pcfg->mohdir = mohdir; +- +- int bfnd = 0; +- struct stat psb [1]; +- if (!lstat (mohdir, psb)) ++else + { ++ if (!lstat (mohdir, psb)) ++ { + if ((psb->st_mode & S_IFMT) == S_IFDIR) + { bfnd = 1; } +- } ++ } + if (!bfnd) +- { +- LM_ERR ("mohdir is not a directory!"); +- return 0; ++ { ++ LM_ERR ("mohdir is not a directory!\n"); ++ berror = 1; ++ } + } + + /********** +-* max calls +-* o valid count? ++* o max calls valid? + * o alloc memory ++* o save data + **********/ + + if (moh_maxcalls < 1 || moh_maxcalls > 5000) + { +- LM_ERR ("moh_maxcalls not in range of 1-5000!"); +- return 0; ++ LM_ERR ("moh_maxcalls not in range of 1-5000!\n"); ++ berror = 1; + } ++if (berror) ++ { 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; ++ LM_ERR ("Unable to allocate shared memory!\n"); ++ return 0; + } ++pmod_data->pcfg->db_url = db_url; ++pmod_data->pcfg->db_ctable = db_ctable; ++pmod_data->pcfg->db_qtable = db_qtable; ++pmod_data->pcfg->mohdir = mohdir; + memset (pmod_data->pcall_lst, 0, sizeof (call_lst) * moh_maxcalls); + pmod_data->call_cnt = moh_maxcalls; + return -1; +@@ -234,13 +235,13 @@ + str *pdb_url = &pmod_data->pcfg->db_url; + if (db_bind_mod (pdb_url, pmod_data->pdb)) + { +- LM_ERR ("Unable to bind DB API using %s", pdb_url->s); ++ LM_ERR ("Unable to bind DB API using %s!\n", pdb_url->s); + return 0; + } + db_func_t *pdb = pmod_data->pdb; + if (!DB_CAPABILITY ((*pdb), DB_CAP_ALL)) + { +- LM_ERR ("Selected database %s lacks required capabilities", pdb_url->s); ++ LM_ERR ("Selected database %s lacks required capabilities!\n", pdb_url->s); + return 0; + } + db1_con_t *pconn = mohq_dbconnect (); +@@ -256,14 +257,14 @@ + if (db_check_table_version (pdb, pconn, + &pmod_data->pcfg->db_ctable, MOHQ_CTABLE_VERSION) < 0) + { +- LM_ERR ("%s table in DB %s not at version %d", ++ LM_ERR ("%s table in DB %s not at version %d!\n", + pmod_data->pcfg->db_ctable.s, pdb_url->s, MOHQ_CTABLE_VERSION); + goto dberr; + } + if (db_check_table_version (pdb, pconn, + &pmod_data->pcfg->db_qtable, MOHQ_QTABLE_VERSION) < 0) + { +- LM_ERR ("%s table in DB %s not at version %d", ++ LM_ERR ("%s table in DB %s not at version %d!\n", + pmod_data->pcfg->db_qtable.s, pdb_url->s, MOHQ_QTABLE_VERSION); + goto dberr; + } +@@ -303,7 +304,7 @@ + { return 0; } + if (!pmod_data->pdb->init) + { +- LM_CRIT ("DB API not loaded!"); ++ LM_CRIT ("DB API not loaded!\n"); + return -1; + } + return 0; +@@ -357,7 +358,7 @@ + pmod_data = (mod_data *) shm_malloc (sizeof (mod_data)); + if (!pmod_data) + { +- LM_ERR ("Unable to allocate shared memory"); ++ LM_ERR ("Unable to allocate shared memory!\n"); + return -1; + } + memset (pmod_data, 0, sizeof (mod_data)); +@@ -373,47 +374,59 @@ + + 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_stop_c = find_export ("rtpproxy_stop_stream2uac", 0, 0); ++if (!pmod_data->fn_rtp_stop_c) ++ { ++ LM_ERR ("Unable to load rtpproxy_stop_stream2uac!\n"); ++ goto initerr; ++ } ++pmod_data->fn_rtp_stop_s = find_export ("rtpproxy_stop_stream2uas", 0, 0); ++if (!pmod_data->fn_rtp_stop_s) ++ { ++ LM_ERR ("Unable to load rtpproxy_stop_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; + } + +@@ -440,4 +453,4 @@ + shm_free (pmod_data); + pmod_data = NULL; + return -1; +-} ++} +\ No newline at end of file +--- a/modules/mohqueue/mohq.h ++++ b/modules/mohqueue/mohq.h +@@ -1,10 +1,8 @@ + /* +- * $Id$ ++ * Copyright (C) 2013-15 Robert Boisvert + * +- * Copyright (C) 2013 Robert Boisvert ++ * This file is part of the mohqueue module for Kamailio, a free SIP server. + * +- * This file is part of the mohqueue module for sip-router, 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 + * the Free Software Foundation; either version 2 of the License, or +@@ -63,31 +61,35 @@ + + /* call_state values */ + #define CLSTA_ENTER 100 +-#define CLSTA_PRACKSTRT 101 +-#define CLSTA_PRACKRPLY 102 +-#define CLSTA_RINGING 103 ++#define CLSTA_TRYING 101 ++#define CLSTA_PRACKSTRT 102 ++#define CLSTA_PRACKRPLY 103 + #define CLSTA_INVITED 104 + #define CLSTA_CANCEL 105 + #define CLSTA_INQUEUE 200 + #define CLSTA_REFER 301 + #define CLSTA_RFRWAIT 302 ++#define CLSTA_BYEOK 304 + #define CLSTA_BYE 305 + + typedef struct + { +- int call_active; +- char call_id [101]; +- char call_from [URI_LEN + 1]; ++ char call_buffer [1024]; ++ size_t call_bufpos; ++ char *call_id; ++ char *call_from; + char call_referto [URI_LEN + 1]; +- char call_contact [URI_LEN + 1]; +- char call_tag [101]; +- char call_via [1024]; ++ char *call_contact; ++ char *call_tag; ++ char *call_via; ++ char *call_route; + char call_addr [IP_ADDR_MAX_STR_SIZE + 4]; + int call_state; + int call_cseq; + int call_aport; + mohq_lst *pmohq; + time_t call_time; ++ time_t refer_time; + unsigned int call_hash; + unsigned int call_label; + sip_msg_t *call_pmsg; +@@ -120,6 +122,8 @@ + cmd_function fn_rtp_offer; + cmd_function fn_rtp_stream_c; + cmd_function fn_rtp_stream_s; ++ cmd_function fn_rtp_stop_c; ++ cmd_function fn_rtp_stop_s; + } mod_data; + + /********** +--- a/modules/mohqueue/mohq_common.h ++++ b/modules/mohqueue/mohq_common.h +@@ -1,10 +1,8 @@ + /* +- * $Id$ ++ * Copyright (C) 2013-15 Robert Boisvert + * +- * Copyright (C) 2013 Robert Boisvert ++ * This file is part of the mohqueue module for Kamailio, a free SIP server. + * +- * This file is part of the mohqueue module for sip-router, 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 + * the Free Software Foundation; either version 2 of the License, or +@@ -53,6 +51,7 @@ + #include "../../parser/contact/parse_contact.h" + #include "../../parser/parse_expires.h" + #include "../../parser/parse_from.h" ++#include "../../parser/parse_rr.h" + #include "../../parser/sdp/sdp.h" + + /* convenience macros */ +@@ -69,7 +68,7 @@ + + #define MOHQ_STR_APPEND_L( str1, str1_lim, s2, s2_len ) \ + if ((str1)->len + (s2_len) >= (str1_lim)) { \ +- LM_ERR( "Failed to append to str: too long" ); \ ++ LM_ERR( "Failed to append to str: too long!\n" ); \ + } else { \ + MOHQ_STR_APPEND((str1), (s2), (s2_len)); \ + (str1_lim) -= (s2_len); \ +@@ -84,7 +83,7 @@ + + #define MOHQ_STR_APPEND_CSTR_L( str1, str1_lim, cstr1 ) \ + if ((str1)->len + strlen(cstr1) >= (str1_lim)) { \ +- LM_ERR( "Failed to append to str: too long" ); \ ++ LM_ERR( "Failed to append to str: too long!\n" ); \ + } else { \ + MOHQ_STR_APPEND_CSTR((str1), (cstr1)); \ + } +--- a/modules/mohqueue/mohq_db.c ++++ b/modules/mohqueue/mohq_db.c +@@ -1,10 +1,8 @@ + /* +- * $Id$ ++ * Copyright (C) 2013-15 Robert Boisvert + * +- * Copyright (C) 2013 Robert Boisvert ++ * This file is part of the mohqueue module for Kamailio, a free SIP server. + * +- * This file is part of the mohqueue module for sip-router, 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 + * the Free Software Foundation; either version 2 of the License, or +@@ -216,7 +214,7 @@ + fill_call_vals (prvals, pcall, CALL_COLCNT); + if (pdb->insert (pconn, prkeys, prvals, CALL_COLCNT) < 0) + { +- LM_WARN ("%sUnable to add new row to %s", pfncname, ++ LM_WARN ("%sUnable to add new row to %s\n", pfncname, + pmod_data->pcfg->db_ctable.s); + } + mohq_dbdisconnect (pconn); +@@ -243,7 +241,7 @@ + pdb->use_table (pconn, &pmod_data->pcfg->db_ctable); + if (pdb->delete (pconn, 0, 0, 0, 0) < 0) + { +- LM_WARN ("%sUnable to delete all rows from %s", pfncname, ++ LM_WARN ("%sUnable to delete all rows from %s\n", pfncname, + pmod_data->pcfg->db_ctable.s); + } + return; +@@ -277,7 +275,7 @@ + set_call_val (prvals, 0, CALLCOL_CALL, pcall->call_id); + if (pdb->delete (pconn, prkeys, 0, prvals, 1) < 0) + { +- LM_WARN ("%sUnable to delete row from %s", pfncname, ++ LM_WARN ("%sUnable to delete row from %s\n", pfncname, + pmod_data->pcfg->db_ctable.s); + } + mohq_dbdisconnect (pconn); +@@ -297,7 +295,7 @@ + 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; + } + +@@ -348,7 +346,7 @@ + fill_call_vals (puvals, pcall, CALLCOL_STATE); + if (pdb->update (pconn, pqkeys, 0, pqvals, pukeys, puvals, 1, 1) < 0) + { +- LM_WARN ("%sUnable to update row in %s", pfncname, ++ LM_WARN ("%sUnable to update row in %s\n", pfncname, + pmod_data->pcfg->db_ctable.s); + } + mohq_dbdisconnect (pconn); +@@ -390,7 +388,7 @@ + puvals->nul = 0; + if (pdb->update (pconn, pqkeys, 0, pqvals, pukeys, puvals, 1, 1) < 0) + { +- LM_WARN ("%sUnable to update row in %s", pfncname, ++ LM_WARN ("%sUnable to update row in %s\n", pfncname, + pmod_data->pcfg->db_qtable.s); + } + mohq_dbdisconnect (pconn); +@@ -428,7 +426,7 @@ + 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 @@ + 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 @@ + 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 @@ + { + 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 @@ + (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; +@@ -525,21 +523,21 @@ + if (strcmp (pqlst [nidx2].mohq_mohdir, pmohdir)) + { + strcpy (pqlst [nidx2].mohq_mohdir, pmohdir); +- LM_INFO ("Queue,Field (%s,%.*s): Changed", pqname, ++ LM_INFO ("Queue,Field (%s,%.*s): Changed\n", pqname, + STR_FMT (&MOHQCSTR_MDIR)); + } + ptext = (char *)VAL_STRING (prowvals + MOHQCOL_MFILE); + if (strcmp (pqlst [nidx2].mohq_mohfile, ptext)) + { + strcpy (pqlst [nidx2].mohq_mohfile, ptext); +- LM_INFO ("Queue,Field (%s,%.*s): Changed", pqname, ++ LM_INFO ("Queue,Field (%s,%.*s): Changed\n", pqname, + STR_FMT (&MOHQCSTR_MFILE)); + } + ptext = (char *)VAL_STRING (prowvals + MOHQCOL_NAME); + if (strcmp (pqlst [nidx2].mohq_name, ptext)) + { + strcpy (pqlst [nidx2].mohq_name, ptext); +- LM_INFO ("Queue,Field (%s,%.*s): Changed", pqname, ++ LM_INFO ("Queue,Field (%s,%.*s): Changed\n", pqname, + STR_FMT (&MOHQCSTR_NAME)); + } + int bdebug = VAL_INT (prowvals + MOHQCOL_DEBUG) ? MOHQF_DBG : 0; +@@ -549,7 +547,7 @@ + { pqlst [nidx2].mohq_flags |= MOHQF_DBG; } + else + { pqlst [nidx2].mohq_flags &= ~MOHQF_DBG; } +- LM_INFO ("Queue,Field (%s,%.*s): Changed", pqname, ++ LM_INFO ("Queue,Field (%s,%.*s): Changed\n", pqname, + STR_FMT (&MOHQCSTR_DEBUG)); + } + bfnd = -1; +@@ -576,7 +574,7 @@ + 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; +@@ -592,7 +590,7 @@ + (char *)VAL_STRING (prowvals + MOHQCOL_NAME)); + if (VAL_INT (prowvals + MOHQCOL_DEBUG)) + { pnewlst [nsize].mohq_flags |= MOHQF_DBG; } +- LM_INFO ("Added new queue (%s)", pnewlst [nsize].mohq_name); ++ LM_INFO ("Added new queue (%s)\n", pnewlst [nsize].mohq_name); + if (nsize) + { shm_free (pmod_data->pmohq_lst); } + pmod_data->pmohq_lst = pnewlst; +@@ -613,7 +611,7 @@ + + if (pqlst [nidx].mohq_flags & MOHQF_CHK) + { continue; } +- LM_INFO ("Removed queue (%s)", pqlst [nidx].mohq_name); ++ LM_INFO ("Removed queue (%s)\n", pqlst [nidx].mohq_name); + if (nidx != (pmod_data->mohq_cnt - 1)) + { + memcpy (&pqlst [nidx], &pqlst [pmod_data->mohq_cnt - 1], +--- a/modules/mohqueue/mohq_db.h ++++ b/modules/mohqueue/mohq_db.h +@@ -1,9 +1,7 @@ + /* +- * $Id$ ++ * Copyright (C) 2013-15 Robert Boisvert + * +- * 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 +--- a/modules/mohqueue/mohq_funcs.c ++++ b/modules/mohqueue/mohq_funcs.c +@@ -1,10 +1,8 @@ + /* +- * $Id$ ++ * Copyright (C) 2013-15 Robert Boisvert + * +- * Copyright (C) 2013 Robert Boisvert ++ * This file is part of the mohqueue module for Kamailio, a free SIP server. + * +- * This file is part of the mohqueue module for sip-router, 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 + * the Free Software Foundation; either version 2 of the License, or +@@ -34,7 +32,7 @@ + #define ALLOWHDR "Allow: INVITE, ACK, BYE, CANCEL, NOTIFY, PRACK" + #define CLENHDR "Content-Length" + #define SIPEOL "\r\n" +-#define USRAGNT "Kamailio MOH Queue v1.0" ++#define USRAGNT "Kamailio MOH Queue v1.2" + + /********** + * local constants +@@ -48,6 +46,7 @@ + str pmi_nolock [1] = {STR_STATIC_INIT ("Unable to lock queue")}; + str pmi_noqueue [1] = {STR_STATIC_INIT ("No matching queue name found")}; + str prefer [1] = {STR_STATIC_INIT ("REFER")}; ++str presp_busy [1] = {STR_STATIC_INIT ("Busy Here")}; + str presp_noaccept [1] = {STR_STATIC_INIT ("Not Acceptable Here")}; + str presp_noallow [1] = {STR_STATIC_INIT ("Method Not Allowed")}; + str presp_nocall [1] = {STR_STATIC_INIT ("Call/Transaction Does Not Exist")}; +@@ -57,6 +56,7 @@ + str presp_ring [1] = {STR_STATIC_INIT ("Ringing")}; + str psipfrag [1] = {STR_STATIC_INIT ("message/sipfrag")}; + str presp_srverr [1] = {STR_STATIC_INIT ("Server Internal Error")}; ++str presp_trying [1] = {STR_STATIC_INIT ("Trying to enter MOH queue")}; + str presp_unsupp [1] = {STR_STATIC_INIT ("Unsupported Media Type")}; + + rtpmap prtpmap [] = +@@ -88,9 +88,9 @@ + char pbyemsg [] = + { + "%s" ++ "%s" + "Max-Forwards: 70" SIPEOL + "Contact: <%s>" SIPEOL +- "User-Agent: " USRAGNT SIPEOL + }; + + str pextrahdr [1] = +@@ -100,7 +100,6 @@ + "Supported: 100rel" SIPEOL + "Accept-Language: en" SIPEOL + "Content-Type: application/sdp" SIPEOL +- "User-Agent: " USRAGNT SIPEOL + ) + }; + +@@ -118,10 +117,11 @@ + char prefermsg [] = + { + "%s" ++ "%s" ++ "Contact: <%s>" SIPEOL + "Max-Forwards: 70" SIPEOL + "Refer-To: <%s>" SIPEOL +- "Referred-By: <%.*s>" SIPEOL +- "User-Agent: " USRAGNT SIPEOL ++ "Referred-By: <%s>" SIPEOL + }; + + char preinvitemsg [] = +@@ -131,7 +131,6 @@ + "Contact: <%s>" SIPEOL + ALLOWHDR SIPEOL + "Supported: 100rel" SIPEOL +- "User-Agent: " USRAGNT SIPEOL + "Accept-Language: en" SIPEOL + "Content-Type: application/sdp" SIPEOL + }; +@@ -153,8 +152,7 @@ + **********/ + + void delete_call (call_lst *); +-void drop_call (sip_msg_t *, call_lst *); +-int find_call (sip_msg_t *, call_lst **); ++void end_RTP (sip_msg_t *, call_lst *); + dlg_t *form_dialog (call_lst *, struct to_body *); + int form_rtp_SDP (str *, call_lst *, char *); + static void invite_cb (struct cell *, int, struct tmcb_params *); +@@ -164,6 +162,7 @@ + int send_rtp_answer (sip_msg_t *, call_lst *); + int search_hdr_ext (struct hdr_field *, str *); + int start_stream (sip_msg_t *, call_lst *, int); ++int stop_stream (sip_msg_t *, call_lst *, int); + + /********** + * local functions +@@ -175,10 +174,10 @@ + * INPUT: + * Arg (1) = SIP message pointer + * Arg (2) = call pointer +-* OUTPUT: 0=failed ++* OUTPUT: none + **********/ + +-int ack_msg (sip_msg_t *pmsg, call_lst *pcall) ++void ack_msg (sip_msg_t *pmsg, call_lst *pcall) + + { + /********** +@@ -195,13 +194,13 @@ + **********/ + + 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; ++ return; + } + + /********** +@@ -212,17 +211,17 @@ + + 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; ++ return; + } + 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; ++ return; + } + } + pcall->call_hash = pcall->call_label = 0; +@@ -235,6 +234,47 @@ + mohq_debug (pcall->pmohq, + "%sACK received for call (%s); placed in queue (%s)", + pfncname, pcall->call_from, pcall->pmohq->mohq_name); ++return; ++} ++ ++/********** ++* Add String to Buffer ++* ++* INPUT: ++* Arg (1) = string pointer ++* Arg (2) = string length ++* Arg (3) = pointer to buffer pointer ++* Arg (4) = pointer to buffer size ++* Arg (5) = add NUL flag ++* OUTPUT: =0 if insufficent space ++* bufpointer incremented, size decremented ++**********/ ++ ++int addstrbfr (char *pstr, size_t nlen, char **pbuf, size_t *nmax, int bnull) ++ ++{ ++/********** ++* o enough space? ++* o copy string ++* o adjust position/size ++**********/ ++ ++size_t nsize = nlen; ++if (bnull) ++ { nsize++; } ++if (nsize > *nmax) ++ { return 0; } ++if (nlen) ++ { ++ strncpy (*pbuf, pstr, nlen); ++ *pbuf += nlen; ++ } ++if (bnull) ++ { ++ **pbuf = '\0'; ++ (*pbuf)++; ++ } ++*nmax -= nsize; + return 1; + } + +@@ -261,7 +301,7 @@ + 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 +309,7 @@ + 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 +@@ -288,33 +328,43 @@ + * INPUT: + * Arg (1) = SIP message pointer + * Arg (2) = call pointer +-* OUTPUT: 0=failed ++* OUTPUT: none + **********/ + +-int bye_msg (sip_msg_t *pmsg, call_lst *pcall) ++void bye_msg (sip_msg_t *pmsg, call_lst *pcall) + + { + /********** +-* o send OK +-* o teardown call ++* o responded? ++* o teardown RTP + **********/ + + char *pfncname = "bye_msg: "; +-if (pmod_data->psl->freply (pmsg, 200, presp_ok) < 0) ++if (pcall->call_state == CLSTA_BYEOK) ++ { return; } ++if (pcall->call_state >= CLSTA_INQUEUE) + { +- LM_ERR ("%sUnable to create reply to call (%s)", pfncname, +- pcall->call_from); +- return 1; ++ pcall->call_state = CLSTA_BYEOK; ++ end_RTP (pmsg, pcall); + } +-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); + } +-return 1; ++ ++/********** ++* send OK and delete from queue ++**********/ ++ ++if (pmod_data->psl->freply (pmsg, 200, presp_ok) < 0) ++ { ++ LM_ERR ("%sUnable to create reply to call (%s)!\n", pfncname, ++ pcall->call_from); ++ return; ++ } ++delete_call (pcall); ++return; + } + + /********** +@@ -323,14 +373,15 @@ + * INPUT: + * Arg (1) = SIP message pointer + * Arg (2) = call pointer +-* OUTPUT: 0=failed ++* OUTPUT: none + **********/ + +-int cancel_msg (sip_msg_t *pmsg, call_lst *pcall) ++void cancel_msg (sip_msg_t *pmsg, call_lst *pcall) + + { + /********** +-* still in INVITE dialog? ++* RFC 3261 section 9.2 ++* o still in INVITE dialog? + **********/ + + char *pfncname = "cancel_msg: "; +@@ -340,16 +391,16 @@ + 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; ++return; + } + + /********** +@@ -365,23 +416,14 @@ + + { + /********** +-* o destroy proxy connection ++* o destroy RTP connection + * o create dialog + **********/ + + char *pfncname = "close_call: "; + int bsent = 0; + char *phdr = 0; +-if (pmsg != FAKED_REPLY) +- { +- mohq_debug (pcall->pmohq, "%sDestroying RTP link for call (%s)", +- pfncname, pcall->call_from); +- if (pmod_data->fn_rtp_destroy (pmsg, 0, 0) != 1) +- { +- LM_ERR ("%srtpproxy_destroy refused for call (%s)!", +- pfncname, pcall->call_from); +- } +- } ++end_RTP (pmsg, pcall); + struct to_body ptob [2]; + dlg_t *pdlg = form_dialog (pcall, ptob); + if (!pdlg) +@@ -398,15 +440,17 @@ + char *pquri = pcall->pmohq->mohq_uri; + int npos1 = sizeof (pbyemsg) // BYE template + + strlen (pcall->call_via) // Via ++ + strlen (pcall->call_route) // Route + + strlen (pquri); // Contact + 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, + pcall->call_via, // Via ++ pcall->call_route, // Route + pquri); // Contact + str phdrs [1]; + phdrs->s = phdr; +@@ -422,7 +466,7 @@ + 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; + } +@@ -449,138 +493,127 @@ + * Create New Call Record + * + * INPUT: +-* Arg (1) = queue index +-* Arg (2) = SIP message pointer +-* OUTPUT: call index; -1 if unable to create ++* Arg (1) = SIP message pointer ++* Arg (2) = call pointer ++* Arg (3) = call index ++* Arg (4) = queue index ++* OUTPUT: initializes call record; =0 if failed + **********/ + +-int create_call (int mohq_idx, sip_msg_t *pmsg) ++int ++create_call (sip_msg_t *pmsg, call_lst *pcall, int ncall_idx, int mohq_idx) + + { + /********** +-* o lock calls +-* o already in use? +-* o find inactive slot +-**********/ +- +-char *pfncname = "create_call: "; +-if (!mohq_lock_set (pmod_data->pcall_lock, 1, 2000)) +- { +- LM_ERR ("%sUnable to lock calls!", pfncname); +- return -1; +- } +-call_lst *pcall; +-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); +- return -1; +- } +-for (ncall_idx = 0; ncall_idx < pmod_data->call_cnt; ncall_idx++) +- { +- if (!pmod_data->pcall_lst [ncall_idx].call_active) +- { break; } +- } +-if (ncall_idx == pmod_data->call_cnt) +- { +- mohq_lock_release (pmod_data->pcall_lock); +- LM_ERR ("%sNo call slots available!", pfncname); +- return -1; +- } +- +-/********** + * add values to new entry + **********/ + +-pcall = &pmod_data->pcall_lst [ncall_idx]; +-pcall->call_active = 1; ++char *pfncname = "create_call: "; + pcall->pmohq = &pmod_data->pmohq_lst [mohq_idx]; +-pcall->call_state = 0; + str *pstr = &pmsg->callid->body; +-strncpy (pcall->call_id, pstr->s, pstr->len); +-pcall->call_id [pstr->len] = '\0'; ++char *pbuf = pcall->call_buffer; ++pcall->call_bufpos = sizeof (pcall->call_buffer); ++pcall->call_id = pbuf; ++if (!addstrbfr (pstr->s, pstr->len, &pbuf, &pcall->call_bufpos, 1)) ++ { return 0; } + pstr = &pmsg->from->body; +-strncpy (pcall->call_from, pstr->s, pstr->len); +-pcall->call_from [pstr->len] = '\0'; +-*pcall->call_tag = '\0'; +-if (!pmsg->contact) +- { *pcall->call_contact = '\0'; } +-else ++pcall->call_from = pbuf; ++if (!addstrbfr (pstr->s, pstr->len, &pbuf, &pcall->call_bufpos, 1)) ++ { return 0; } ++pcall->call_tag = pbuf; ++if (!addstrbfr (0, 0, &pbuf, &pcall->call_bufpos, 1)) ++ { return 0; } ++pcall->call_contact = pbuf; ++if (pmsg->contact) + { + pstr = &pmsg->contact->body; +- strncpy (pcall->call_contact, pstr->s, pstr->len); +- pcall->call_contact [pstr->len] = '\0'; ++ if (!addstrbfr (pstr->s, pstr->len, &pbuf, &pcall->call_bufpos, 0)) ++ { return 0; } + } ++if (!addstrbfr (0, 0, &pbuf, &pcall->call_bufpos, 1)) ++ { return 0; } + + /********** + * extract Via headers + **********/ + ++pcall->call_via = pbuf; + hdr_field_t *phdr = pmsg->h_via1; + if (phdr) + { +- int npos1 = 0; + while ((phdr = next_sibling_hdr (phdr))) + { + struct via_body *pvia; + char *pviabuf; +- int bovrflow = 0; +- int npos2; +- int nvia_max = sizeof (pcall->call_via); ++ int npos; + for (pvia = (struct via_body *)phdr->parsed; pvia; pvia = pvia->next) + { + /********** +- * o skip trailing whitespace +- * o check if overflow ++ * skip trailing whitespace + **********/ + +- npos2 = pvia->bsize; ++ npos = pvia->bsize; + pviabuf = pvia->name.s; +- while (npos2) ++ while (npos) + { +- --npos2; +- if (pviabuf [npos2] == ' ' || pviabuf [npos2] == '\r' +- || pviabuf [npos2] == '\n' || pviabuf [npos2] == '\t' || pviabuf [npos2] == ',') ++ --npos; ++ if (pviabuf [npos] == ' ' || pviabuf [npos] == '\r' ++ || pviabuf [npos] == '\n' || pviabuf [npos] == '\t' ++ || pviabuf [npos] == ',') + { continue; } + break; + } +- if ((npos2 + npos1 + 7) >= nvia_max) +- { +- LM_WARN ("%sVia buffer overflowed!", pfncname); +- bovrflow = 1; +- break; +- } + + /********** + * copy via + **********/ + +- strcpy (&pcall->call_via [npos1], "Via: "); +- npos1 += 5; +- strncpy (&pcall->call_via [npos1], pviabuf, npos2); +- npos1 += npos2; +- strcpy (&pcall->call_via [npos1], SIPEOL); +- npos1 += 2; ++ if (!addstrbfr ("Via: ", 5, &pbuf, &pcall->call_bufpos, 0)) ++ { return 0; } ++ if (!addstrbfr (pviabuf, npos, &pbuf, &pcall->call_bufpos, 0)) ++ { return 0; } ++ if (!addstrbfr (SIPEOL, 2, &pbuf, &pcall->call_bufpos, 0)) ++ { return 0; } + } +- if (bovrflow) +- { break; } + } + } ++if (!addstrbfr (0, 0, &pbuf, &pcall->call_bufpos, 1)) ++ { return 0; } + + /********** +-* o release call lock +-* o update DB +-* o lock MOH queue ++* extract Route headers + **********/ + ++pcall->call_route = pbuf; ++struct hdr_field *proute; ++for (proute = pmsg->record_route; proute; proute = next_sibling_hdr (proute)) ++ { ++ if (parse_rr (proute) < 0) ++ { return 0; } ++ rr_t *prouterr; ++ for (prouterr = proute->parsed; prouterr; prouterr = prouterr->next) ++ { ++ if (!addstrbfr ("Route: ", 7, &pbuf, &pcall->call_bufpos, 0)) ++ { return 0; } ++ if (!addstrbfr (prouterr->nameaddr.name.s, prouterr->len, ++ &pbuf, &pcall->call_bufpos, 0)) ++ { return 0; } ++ if (!addstrbfr (SIPEOL, 2, &pbuf, &pcall->call_bufpos, 0)) ++ { return 0; } ++ } ++ } ++if (!addstrbfr (0, 0, &pbuf, &pcall->call_bufpos, 1)) ++ { return 0; } ++ ++/********** ++* update DB ++**********/ ++ + pcall->call_state = CLSTA_ENTER; +-mohq_lock_release (pmod_data->pcall_lock); + add_call_rec (ncall_idx); +-mohq_lock_set (pmod_data->pmohq_lock, 0, 0); + mohq_debug (pcall->pmohq, "%sAdded call (%s) to queue (%s)", + pfncname, pcall->call_from, pcall->pmohq->mohq_name); +-return ncall_idx; ++return 1; + } + + /********** +@@ -605,15 +638,15 @@ + { + if (ptm->t_lookup_ident (&ptrans, pcall->call_hash, pcall->call_label) < 0) + { +- LM_ERR ("%sLookup transaction failed for call (%s)!", pfncname, +- pcall->call_from); ++ LM_ERR ("%sLookup transaction failed for call (%s) from queue (%s)!\n", ++ pfncname, pcall->call_from, pcall->pmohq->mohq_name); + } + else + { + if (ptm->t_release (pcall->call_pmsg) < 0) + { +- LM_ERR ("%sRelease transaction failed for call (%s)!", +- pfncname, pcall->call_from); ++ LM_ERR ("%sRelease transaction failed for call (%s) from queue (%s)!\n", ++ pfncname, pcall->call_from, pcall->pmohq->mohq_name); + } + } + pcall->call_hash = pcall->call_label = 0; +@@ -622,14 +655,21 @@ + /********** + * o update DB + * o inactivate slot +-* o release MOH queue + **********/ + +-mohq_debug (pcall->pmohq, "delete_call: Deleting call (%s) from queue (%s)", +- pcall->call_from, pcall->pmohq->mohq_name); +-delete_call_rec (pcall); +-pcall->call_active = 0; +-mohq_lock_release (pmod_data->pmohq_lock); ++if (!mohq_lock_set (pmod_data->pcall_lock, 1, 5000)) ++ { ++ LM_ERR ("%sUnable to set call lock for call (%s) from queue (%s)!\n", ++ pfncname, pcall->call_from, pcall->pmohq->mohq_name); ++ } ++else ++ { ++ mohq_debug (pcall->pmohq, "%sDeleting call (%s) from queue (%s)", ++ pfncname, pcall->call_from, pcall->pmohq->mohq_name); ++ delete_call_rec (pcall); ++ mohq_lock_release (pmod_data->pcall_lock); ++ } ++pcall->call_state = 0; + return; + } + +@@ -655,28 +695,28 @@ + 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 ("%sRefused %.*s for call (%s)!", pfncname, ++ { LM_ERR ("%sUnable to add Allow header!\n", pfncname); } ++LM_ERR ("%sRefused %.*s for call (%s)!\n", 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; + } + + /********** +-* Drop the Call ++* End RTP + * + * INPUT: + * Arg (1) = SIP message pointer +@@ -684,26 +724,24 @@ + * OUTPUT: none + **********/ + +-void drop_call (sip_msg_t *pmsg, call_lst *pcall) ++void end_RTP (sip_msg_t *pmsg, call_lst *pcall) + + { + /********** +-* o destroy proxy connection +-* o delete call ++* destroy RTP connection + **********/ + +-char *pfncname = "drop_call: "; +-if (pmsg != FAKED_REPLY) ++char *pfncname = "end_RTP: "; ++if ((pmsg != FAKED_REPLY) && (pcall->call_state != CLSTA_ENTER)) + { + mohq_debug (pcall->pmohq, "%sDestroying RTP link for call (%s)", + 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); + } + } +-delete_call (pcall); + return; + } + +@@ -712,62 +750,37 @@ + * + * INPUT: + * Arg (1) = SIP message pointer +-* Arg (2) = pointer to call pointer +-* OUTPUT: queue index; -1 if unable to find ++* Arg (2) = queue index ++* OUTPUT: call pointer; =0 if unable to find/create + **********/ + +-int find_call (sip_msg_t *pmsg, call_lst **ppcall) ++call_lst *find_call (sip_msg_t *pmsg, int mohq_idx) + + { + /********** +-* o find current RURI +-* o strip off parms or headers +-* o search MOH queue +-**********/ +- +-str *pruri = +- pmsg->new_uri.s ? &pmsg->new_uri : &pmsg->first_line.u.request.uri; +-int nidx; +-str pstr [1]; +-pstr->s = pruri->s; +-pstr->len = pruri->len; +-for (nidx = 0; nidx < pruri->len; nidx++) +- { +- if (pstr->s [nidx] == ';' || pstr->s [nidx] == '?') +- { +- pstr->len = nidx; +- break; +- } +- } +-mohq_lst *pqlst = pmod_data->pmohq_lst; +-int nqidx; +-for (nqidx = 0; nqidx < pmod_data->mohq_cnt; nqidx++) +- { +- str pmohstr [1]; +- pmohstr->s = pqlst [nqidx].mohq_uri; +- pmohstr->len = strlen (pmohstr->s); +- if (STR_EQ (*pmohstr, *pstr)) +- { break; } +- } +-*ppcall = 0; +-if (nqidx == pmod_data->mohq_cnt) +- { return -1;} +- +-/********** + * o get to tag + * o get callID +-* o ignore to tag if CANCEL on first INVITE +-* o search call queue ++* o search calls + **********/ + ++char *pfncname = "find_call: "; + str *ptotag = &(get_to (pmsg)->tag_value); + if (!ptotag->len) + { ptotag = 0; } + if (!pmsg->callid) +- { return -1; } ++ { ++ LM_ERR ("%sNo call ID!\n", pfncname); ++ return 0; ++ } + str *pcallid = &pmsg->callid->body; + if (!pcallid) +- { return -1; } ++ { ++ LM_ERR ("%sNo call ID!\n", pfncname); ++ return 0; ++ } ++int nopen = -1; ++int nidx; ++call_lst *pcall; + for (nidx = 0; nidx < pmod_data->call_cnt; nidx++) + { + /********** +@@ -775,21 +788,25 @@ + * o call timed out on ACK? + * o callID matches? + * o to tag matches? +- * o return call pointer + **********/ + +- call_lst *pcall = &pmod_data->pcall_lst [nidx]; +- if (!pcall->call_active) +- { continue; } ++ pcall = &pmod_data->pcall_lst [nidx]; ++ if (!pcall->call_state) ++ { ++ nopen = nidx; ++ continue; ++ } ++#if 0 /* ??? need to handle */ + if (pcall->call_time && (pcall->call_state < CLSTA_INQUEUE)) + { + if ((pcall->call_time + 32) < time (0)) + { +- LM_ERR ("find_call: No ACK response for call (%s)", pcall->call_from); ++ LM_ERR ("%sNo ACK response for call (%s)!\n", pfncname, pcall->call_from); + delete_call (pcall); + continue; + } + } ++#endif /* ??? */ + str tmpstr [1]; + tmpstr->s = pcall->call_id; + tmpstr->len = strlen (tmpstr->s); +@@ -802,36 +819,101 @@ + if (!STR_EQ (*tmpstr, *ptotag)) + { continue; } + } +- *ppcall = pcall; +- return nqidx; ++ else ++ { ++ /********** ++ * match not allowed for INVITE ++ **********/ ++ ++ if (pmsg->REQ_METHOD == METHOD_INVITE) ++ { return 0; } ++ } ++ return pcall; + } + + /********** +-* first INVITE? ++* o first INVITE? ++* o create a new call record + **********/ + +-if (pmsg->REQ_METHOD == METHOD_INVITE) ++if (pmsg->REQ_METHOD != METHOD_INVITE) + { return 0; } +-return -1; ++if (ptotag) ++ { return 0; } ++if (nopen < 0) ++ { ++ LM_ERR ("%sNo call slots available!\n", pfncname); ++ return 0; ++ } ++pcall = &pmod_data->pcall_lst [nopen]; ++if (!create_call (pmsg, pcall, nopen, mohq_idx)) ++ { return 0; } ++return pcall; + } + + /********** + * Find Queue + * + * INPUT: ++* Arg (1) = SIP message pointer ++* OUTPUT: queue index; -1 if unable to find ++**********/ ++ ++int find_queue (sip_msg_t *pmsg) ++ ++{ ++/********** ++* o find current RURI ++* o strip off parms or headers ++* o search queues ++**********/ ++ ++str *pruri = ++ pmsg->new_uri.s ? &pmsg->new_uri : &pmsg->first_line.u.request.uri; ++int nidx; ++str pstr [1]; ++pstr->s = pruri->s; ++pstr->len = pruri->len; ++for (nidx = 0; nidx < pruri->len; nidx++) ++ { ++ if (pstr->s [nidx] == ';' || pstr->s [nidx] == '?') ++ { ++ pstr->len = nidx; ++ break; ++ } ++ } ++mohq_lst *pqlst = pmod_data->pmohq_lst; ++int nqidx; ++for (nqidx = 0; nqidx < pmod_data->mohq_cnt; nqidx++) ++ { ++ str pmohstr [1]; ++ pmohstr->s = pqlst [nqidx].mohq_uri; ++ pmohstr->len = strlen (pmohstr->s); ++ if (STR_EQ (*pmohstr, *pstr)) ++ { break; } ++ } ++if (nqidx == pmod_data->mohq_cnt) ++ { return -1;} ++return nqidx; ++} ++ ++/********** ++* Find Queue Name ++* ++* INPUT: + * Arg (1) = queue name str pointer + * OUTPUT: queue index; -1 if unable to find + **********/ + +-int find_queue (str *pqname) ++int find_qname (str *pqname) + + { +-char *pfncname = "find_queue: "; ++char *pfncname = "find_qname: "; + 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 +925,7 @@ + } + 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); +@@ -871,7 +953,7 @@ + if (pref->error != PARSE_OK) + { + // should never happen +- LM_ERR ("%sInvalid Referred-By URI (%.*s)!", pfncname, STR_FMT (pvalue)); ++ LM_ERR ("%sInvalid Referred-By URI (%.*s)!\n", pfncname, STR_FMT (pvalue)); + return -1; + } + if (pref->param_lst) +@@ -886,7 +968,7 @@ + struct to_body pfrom [1]; + for (nidx = 0; nidx < pmod_data->call_cnt; nidx++) + { +- if (!pmod_data->pcall_lst [nidx].call_active) ++ if (!pmod_data->pcall_lst [nidx].call_state) + { continue; } + tmpstr.s = pmod_data->pcall_lst [nidx].call_from; + tmpstr.len = strlen (tmpstr.s); +@@ -894,7 +976,7 @@ + if (pfrom->error != PARSE_OK) + { + // should never happen +- LM_ERR ("%sInvalid From URI (%.*s)!", pfncname, STR_FMT (&tmpstr)); ++ LM_ERR ("%sInvalid From URI (%.*s)!\n", pfncname, STR_FMT (&tmpstr)); + continue; + } + if (pfrom->param_lst) +@@ -910,55 +992,65 @@ + * + * INPUT: + * Arg (1) = SIP message pointer +-* Arg (2) = queue index +-* OUTPUT: 0=failed ++* Arg (2) = call pointer ++* OUTPUT: none + **********/ + +-int first_invite_msg (sip_msg_t *pmsg, int mohq_idx) ++void first_invite_msg (sip_msg_t *pmsg, call_lst *pcall) + + { +-/********** +-* create call record +-**********/ +- + char *pfncname = "first_invite_msg: "; +-int ncall_idx = create_call (mohq_idx, pmsg); +-if (ncall_idx == -1) +- { return 0; } +-call_lst *pcall = &pmod_data->pcall_lst [ncall_idx]; + + /********** + * o SDP exists? + * o accepts REFER? +-* o send rtpproxy offer ++* o send RTP offer + **********/ + + if (!(pmsg->msg_flags & FL_SDP_BODY)) + { + if (parse_sdp (pmsg)) + { +- LM_ERR ("%sINVITE lacks SDP (%s)!", pfncname, pcall->call_from); ++ if (pmod_data->psl->freply (pmsg, 488, presp_noaccept) < 0) ++ { ++ LM_ERR ("%sUnable to create reply!\n", pfncname); ++ return; ++ } ++ LM_ERR ("%sINVITE lacks SDP (%s) from queue (%s)!\n", ++ pfncname, pcall->call_from, pcall->pmohq->mohq_name); + delete_call (pcall); +- return 0; ++ return; + } + } + if (pmsg->allow) + { + if (!search_hdr_ext (pmsg->allow, prefer)) + { +- LM_ERR ("%sMissing REFER support (%s)!", pfncname, pcall->call_from); ++ if (pmod_data->psl->freply (pmsg, 488, presp_noaccept) < 0) ++ { ++ LM_ERR ("%sUnable to create reply!\n", pfncname); ++ return; ++ } ++ LM_ERR ("%sMissing REFER support (%s) from queue (%s)!\n", ++ pfncname, pcall->call_from, pcall->pmohq->mohq_name); + delete_call (pcall); +- return 0; ++ return; + } + } +-mohq_debug (pcall->pmohq, "%sMaking offer for RTP link for call (%s)", +- pfncname, pcall->call_from); ++mohq_debug (pcall->pmohq, ++ "%sMaking offer for RTP link for call (%s) from queue (%s)", ++ pfncname, pcall->call_from, pcall->pmohq->mohq_name); + if (pmod_data->fn_rtp_offer (pmsg, 0, 0) != 1) + { +- LM_ERR ("%srtpproxy_offer refused for call (%s)!", +- pfncname, pcall->call_from); ++ if (pmod_data->psl->freply (pmsg, 486, presp_busy) < 0) ++ { ++ LM_ERR ("%sUnable to create reply!\n", pfncname); ++ return; ++ } ++ LM_ERR ("%srtpproxy_offer refused for call (%s)!\n", ++ pfncname, pcall->call_from); + delete_call (pcall); +- return 0; ++ return; + } + + /********** +@@ -971,10 +1063,11 @@ + tm_api_t *ptm = pmod_data->ptm; + if (ptm->t_newtran (pmsg) < 0) + { +- LM_ERR ("%sUnable to create new transaction for call (%s)!", ++ LM_ERR ("%sUnable to create new transaction for call (%s)!\n", + pfncname, pcall->call_from); ++ end_RTP (pmsg, pcall); + delete_call (pcall); +- return 0; ++ return; + } + struct cell *ptrans = ptm->t_gett (); + pcall->call_hash = ptrans->hash_index; +@@ -982,28 +1075,53 @@ + str ptotag [1]; + if (ptm->t_get_reply_totag (pmsg, ptotag) != 1) + { +- LM_ERR ("%sUnable to create totag for call (%s)!", ++ LM_ERR ("%sUnable to create totag for call (%s)!\n", + pfncname, pcall->call_from); + if (ptm->t_reply (pmsg, 500, presp_srverr->s) < 0) +- { LM_ERR ("%sUnable to reply to INVITE!", pfncname); } ++ { LM_ERR ("%sUnable to reply to INVITE!\n", pfncname); } ++ end_RTP (pmsg, pcall); + delete_call (pcall); +- return 1; ++ return; + } +-strncpy (pcall->call_tag, ptotag->s, ptotag->len); +-pcall->call_tag [ptotag->len] = '\0'; ++char *pbuf = &pcall->call_buffer [pcall->call_bufpos]; ++pcall->call_tag = pbuf; ++if (!addstrbfr (ptotag->s, ptotag->len, &pbuf, &pcall->call_bufpos, 1)) ++ { ++ LM_ERR ("%sInsufficient buffer space for call (%s)!\n", ++ pfncname, pcall->call_from); ++ if (ptm->t_reply (pmsg, 500, presp_srverr->s) < 0) ++ { LM_ERR ("%sUnable to reply to INVITE!\n", pfncname); } ++ end_RTP (pmsg, pcall); ++ delete_call (pcall); ++ return; ++ } + pcall->call_cseq = 1; + if (ptm->register_tmcb (pmsg, 0, TMCB_DESTROY | TMCB_ON_FAILURE, + invite_cb, pcall, 0) < 0) + { +- LM_ERR ("%sUnable to set callback for call (%s)!", ++ LM_ERR ("%sUnable to set callback for call (%s)!\n", + pfncname, pcall->call_from); + if (ptm->t_reply (pmsg, 500, presp_srverr->s) < 0) +- { LM_ERR ("%sUnable to reply to INVITE!", pfncname); } ++ { LM_ERR ("%sUnable to reply to INVITE!\n", pfncname); } ++ end_RTP (pmsg, pcall); + delete_call (pcall); +- return 1; ++ return; + } + + /********** ++* reply with trying ++**********/ ++ ++if (ptm->t_reply (pmsg, 100, presp_trying->s) < 0) ++ { ++ LM_ERR ("%sUnable to create reply!\n", pfncname); ++ end_RTP (pmsg, pcall); ++ delete_call (pcall); ++ return; ++ } ++pcall->call_state = CLSTA_TRYING; ++ ++/********** + * o add contact to reply + * o supports/requires PRACK? (RFC 3262 section 3) + * o exit if not ringing +@@ -1011,19 +1129,20 @@ + + str pcontact [1]; + char *pcontacthdr = "Contact: <%s>" SIPEOL; +-pcontact->s = pkg_malloc (strlen (pmod_data->pmohq_lst [mohq_idx].mohq_uri) +- + strlen (pcontacthdr)); ++pcontact->s ++ = pkg_malloc (strlen (pcall->pmohq->mohq_uri) + strlen (pcontacthdr)); + if (!pcontact->s) + { +- LM_ERR ("%sNo more memory!", pfncname); ++ LM_ERR ("%sNo more memory!\n", pfncname); ++ end_RTP (pmsg, pcall); + delete_call (pcall); +- return 1; ++ return; + } +-sprintf (pcontact->s, pcontacthdr, pmod_data->pmohq_lst [mohq_idx].mohq_uri); ++sprintf (pcontact->s, pcontacthdr, pcall->pmohq->mohq_uri); + pcontact->len = strlen (pcontact->s); + if (!add_lump_rpl2 (pmsg, pcontact->s, pcontact->len, LUMP_RPL_HDR)) + { +- LM_ERR ("%sUnable to add contact (%s) to call (%s)!", ++ LM_ERR ("%sUnable to add contact (%s) to call (%s)!\n", + pfncname, pcontact->s, pcall->call_from); + } + pkg_free (pcontact->s); +@@ -1032,42 +1151,30 @@ + { + if (!send_prov_rsp (pmsg, pcall)) + { ++ end_RTP (pmsg, pcall); + delete_call (pcall); +- return 1; ++ return; + } +- } +-else +- { +- if (ptm->t_reply (pmsg, 180, presp_ring->s) < 0) ++ if (pcall->call_state == CLSTA_CANCEL) + { +- LM_ERR ("%sUnable to reply to INVITE!", pfncname); +- return 1; ++ end_RTP (pmsg, pcall); ++ delete_call (pcall); ++ return; + } +- else +- { +- pcall->call_state = CLSTA_RINGING; +- mohq_debug (pcall->pmohq, "%sSent RINGING for call (%s)", +- pfncname, pcall->call_from); +- } + } + + /********** +-* o call cancelled? +-* o accept call with RTP ++* accept call with RTP + **********/ + +-if (pcall->call_state == CLSTA_CANCEL) +- { +- delete_call (pcall); +- return 1; +- } + if (!send_rtp_answer (pmsg, pcall)) + { + if (pmod_data->psl->freply (pmsg, 500, presp_srverr) < 0) +- { LM_ERR ("%sUnable to create reply!", pfncname); } ++ { LM_ERR ("%sUnable to create reply!\n", pfncname); } ++ end_RTP (pmsg, pcall); + delete_call (pcall); + } +-return 1; ++return; + } + + /********** +@@ -1087,6 +1194,9 @@ + **********/ + + char *pfncname = "form_dialog: "; ++str pdsturi [1], ptarget [1]; ++int index; ++name_addr_t pname [1]; + struct to_body *ptob = &pto_body [0]; + struct to_body *pcontact = &pto_body [1]; + parse_to (pcall->call_from, +@@ -1094,12 +1204,49 @@ + if (ptob->error != PARSE_OK) + { + // should never happen +- LM_ERR ("%sInvalid from URI (%s)!", pfncname, pcall->call_from); ++ LM_ERR ("%sInvalid from URI (%s)!\n", pfncname, pcall->call_from); + return 0; + } + if (ptob->param_lst) + { free_to_params (ptob); } +-str ptarget [1]; ++ ++/********** ++* form dest URI from record route ++**********/ ++ ++if (!*pcall->call_route) ++ { pdsturi->s = 0; } ++else ++ { ++ /********** ++ * o find first route URI ++ * o strip off parameter ++ **********/ ++ ++ pdsturi->s = pcall->call_route; ++ pdsturi->len = strlen (pcall->call_route); ++ if (parse_nameaddr (pdsturi, pname) < 0) ++ { ++ // should never happen ++ LM_ERR ("%sUnable to parse route (%s)!\n", pfncname, pcall->call_from); ++ return 0; ++ } ++ pdsturi->s = pname->uri.s; ++ pdsturi->len = pname->uri.len; ++ for (index = 1; index < pdsturi->len; index++) ++ { ++ if (pdsturi->s [index] == ';') ++ { ++ pdsturi->len = index; ++ break; ++ } ++ } ++ } ++ ++/********** ++* form target URI ++**********/ ++ + if (!*pcall->call_contact) + { + ptarget->s = ptob->uri.s; +@@ -1112,7 +1259,7 @@ + if (pcontact->error != PARSE_OK) + { + // should never happen +- LM_ERR ("%sInvalid contact (%s) for call (%s)!", pfncname, ++ LM_ERR ("%sInvalid contact (%s) for call (%s)!\n", pfncname, + pcall->call_contact, pcall->call_from); + return 0; + } +@@ -1129,7 +1276,7 @@ + dlg_t *pdlg = (dlg_t *)pkg_malloc (sizeof (dlg_t)); + if (!pdlg) + { +- LM_ERR ("%sNo more memory!", pfncname); ++ LM_ERR ("%sNo more memory!\n", pfncname); + return 0; + } + memset (pdlg, 0, sizeof (dlg_t)); +@@ -1147,6 +1294,11 @@ + pdlg->loc_uri.len = strlen (pdlg->loc_uri.s); + pdlg->rem_uri.s = ptob->uri.s; + pdlg->rem_uri.len = ptob->uri.len; ++if (pdsturi->s) ++ { ++ pdlg->dst_uri.s = pdsturi->s; ++ pdlg->dst_uri.len = pdsturi->len; ++ } + return pdlg; + } + +@@ -1173,7 +1325,7 @@ + pcall->pmohq->mohq_mohfile); + if (!pmohfiles [0]) + { +- LM_ERR ("%sUnable to find any MOH files for queue (%s)!", pfncname, ++ LM_ERR ("%sUnable to find any MOH files for queue (%s)!\n", pfncname, + pcall->pmohq->mohq_name); + return 0; + } +@@ -1193,7 +1345,7 @@ + pstr->s = pkg_malloc (nsize + 1); + if (!pstr->s) + { +- LM_ERR ("%sNo more memory!", pfncname); ++ LM_ERR ("%sNo more memory!\n", pfncname); + return 0; + } + strcpy (pstr->s, pSDP); +@@ -1240,7 +1392,7 @@ + call_lst *pcall = (call_lst *)*pcbp->param; + if (ntype == TMCB_DESTROY) + { pcall->call_hash = pcall->call_label = 0; } +-LM_ERR ("invite_cb: INVITE failed for call (%s)!", pcall->call_from); ++LM_ERR ("invite_cb: INVITE failed for call (%s)!\n", pcall->call_from); + delete_call (pcall); + return; + } +@@ -1251,10 +1403,10 @@ + * INPUT: + * Arg (1) = SIP message pointer + * Arg (2) = call pointer +-* OUTPUT: 0=failed ++* OUTPUT: none + **********/ + +-int notify_msg (sip_msg_t *pmsg, call_lst *pcall) ++void notify_msg (sip_msg_t *pmsg, call_lst *pcall) + + { + /********** +@@ -1264,11 +1416,11 @@ + char *pfncname = "notify_msg: "; + if (pcall->call_state != CLSTA_RFRWAIT) + { +- LM_ERR ("%sNot waiting on a REFER for call (%s)!", pfncname, ++ LM_ERR ("%sNot waiting on a REFER 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); } +- return 1; ++ { LM_ERR ("%sUnable to create reply!\n", pfncname); } ++ return; + } + + /********** +@@ -1279,28 +1431,28 @@ + + if (!search_hdr_ext (pmsg->content_type, psipfrag)) + { +- LM_ERR ("%sNot a %s type for call (%s)!", pfncname, ++ LM_ERR ("%sNot a %s type for call (%s)!\n", pfncname, + psipfrag->s, pcall->call_from); + if (pmod_data->psl->freply (pmsg, 415, presp_unsupp) < 0) +- { LM_ERR ("%sUnable to create reply!", pfncname); } +- return 1; ++ { LM_ERR ("%sUnable to create reply!\n", pfncname); } ++ return; + } + char *pfrag = get_body (pmsg); + if (!pfrag) + { +- LM_ERR ("%s%s body missing for call (%s)!", pfncname, ++ LM_ERR ("%s%s body missing for call (%s)!\n", pfncname, + psipfrag->s, pcall->call_from); + if (pmod_data->psl->freply (pmsg, 415, presp_unsupp) < 0) +- { LM_ERR ("%sUnable to create reply!", pfncname); } +- return 1; ++ { LM_ERR ("%sUnable to create reply!\n", pfncname); } ++ return; + } + str pbody [1]; + pbody->len = pmsg->len - (int)(pfrag - pmsg->buf); + pbody->s = pkg_malloc (pbody->len + 2); + if (!pbody->s) + { +- LM_ERR ("%sNo more memory!", pfncname); +- return 1; ++ LM_ERR ("%sNo more memory!\n", pfncname); ++ return; + } + strncpy (pbody->s, pfrag, pbody->len); + if (pbody->s [pbody->len - 1] != '\n') +@@ -1313,10 +1465,10 @@ + pkg_free (pbody->s); + if (pstart->type != SIP_REPLY) + { +- LM_ERR ("%sReply missing for call (%s)!", pfncname, pcall->call_from); ++ LM_ERR ("%sReply missing for call (%s)!\n", pfncname, pcall->call_from); + if (pmod_data->psl->freply (pmsg, 415, presp_unsupp) < 0) +- { LM_ERR ("%sUnable to create reply!", pfncname); } +- return 1; ++ { LM_ERR ("%sUnable to create reply!\n", pfncname); } ++ return; + } + + /********** +@@ -1324,32 +1476,34 @@ + * o REFER done? + **********/ + ++int nreply = pstart->u.reply.statuscode; + if (pmod_data->psl->freply (pmsg, 200, presp_ok) < 0) + { +- LM_ERR ("%sUnable to create reply for call (%s)!", ++ LM_ERR ("%sUnable to create reply for call (%s)!\n", + pfncname, pcall->call_from); +- return 1; ++ return; + } +-int nreply = pstart->u.reply.statuscode; + mohq_debug (pcall->pmohq, "%sNOTIFY received reply (%d) for call (%s)", + pfncname, nreply, pcall->call_from); + switch (nreply / 100) + { + case 1: ++ pcall->refer_time = time (0); + break; + case 2: + close_call (pmsg, pcall); + break; + default: +- LM_WARN ("%sUnable to redirect call (%s)!", pfncname, pcall->call_from); ++ LM_WARN ("%sUnable to redirect call (%s)\n", pfncname, pcall->call_from); + if (nreply == 487) + { + /********** +- * call was canceled ++ * call was cancelled + **********/ + +- drop_call (pmsg, pcall); +- return 1; ++ end_RTP (pmsg, pcall); ++ delete_call (pcall); ++ return; + } + + /********** +@@ -1360,7 +1514,7 @@ + update_call_rec (pcall); + break; + } +-return 1; ++return; + } + + /********** +@@ -1369,10 +1523,10 @@ + * INPUT: + * Arg (1) = SIP message pointer + * Arg (2) = call pointer +-* OUTPUT: 0=failed ++* OUTPUT: none + **********/ + +-int prack_msg (sip_msg_t *pmsg, call_lst *pcall) ++void prack_msg (sip_msg_t *pmsg, call_lst *pcall) + + { + /********** +@@ -1383,10 +1537,10 @@ + tm_api_t *ptm = pmod_data->ptm; + if (pcall->call_state != CLSTA_PRACKSTRT) + { +- LM_ERR ("%sUnexpected PRACK (%s)!", pfncname, pcall->call_from); ++ LM_ERR ("%sUnexpected PRACK (%s)!\n", pfncname, pcall->call_from); + if (pmod_data->psl->freply (pmsg, 481, presp_nocall) < 0) +- { LM_ERR ("%sUnable to create reply!", pfncname); } +- return 1; ++ { LM_ERR ("%sUnable to create reply!\n", pfncname); } ++ return; + } + + /********** +@@ -1396,20 +1550,20 @@ + + if (ptm->t_newtran (pmsg) < 0) + { +- LM_ERR ("%sUnable to create new transaction for call (%s)!", ++ LM_ERR ("%sUnable to create new transaction for call (%s)!\n", + pfncname, pcall->call_from); + if (pmod_data->psl->freply (pmsg, 500, presp_srverr) < 0) +- { LM_ERR ("%sUnable to create reply!", pfncname); } +- return 1; ++ { LM_ERR ("%sUnable to create reply!\n", pfncname); } ++ return; + } + if (ptm->t_reply (pmsg, 200, presp_ok->s) < 0) + { +- LM_ERR ("%sUnable to reply to PRACK for call (%s)!", ++ LM_ERR ("%sUnable to reply to PRACK for call (%s)!\n", + pfncname, pcall->call_from); +- return 1; ++ return; + } + pcall->call_state = CLSTA_PRACKRPLY; +-return 1; ++return; + } + + /********** +@@ -1450,18 +1604,22 @@ + puri->len = strlen (puri->s); + int npos1 = sizeof (prefermsg) // REFER template + + strlen (pcall->call_via) // Via ++ + strlen (pcall->call_route) // Route ++ + strlen (pcall->pmohq->mohq_uri) // Contact + + puri->len // Refer-To +- + ptob->uri.len; // Referred-By ++ + strlen (pcall->pmohq->mohq_uri); // Referred-By + char *pbuf = pkg_malloc (npos1); + if (!pbuf) + { +- LM_ERR ("%sNo more memory!", pfncname); ++ LM_ERR ("%sNo more memory!\n", pfncname); + goto refererr; + } + sprintf (pbuf, prefermsg, + pcall->call_via, // Via ++ pcall->call_route, // Route ++ pcall->pmohq->mohq_uri, // Contact + puri->s, // Refer-To +- STR_FMT (&ptob->uri)); // Referred-By ++ pcall->pmohq->mohq_uri); // Referred-By + + /********** + * send REFER request +@@ -1474,13 +1632,14 @@ + phdrs->len = strlen (pbuf); + set_uac_req (puac, prefer, phdrs, 0, pdlg, + TMCB_LOCAL_COMPLETED | TMCB_ON_FAILURE, refer_cb, pcall); ++pcall->refer_time = time (0); + pcall->call_state = CLSTA_REFER; + update_call_rec (pcall); + mohq_lock_release (plock); + if (ptm->t_request_within (puac) < 0) + { + pcall->call_state = CLSTA_INQUEUE; +- LM_ERR ("%sUnable to create REFER request for call (%s)!", ++ LM_ERR ("%sUnable to create REFER request for call (%s)!\n", + pfncname, pcall->call_from); + update_call_rec (pcall); + goto refererr; +@@ -1514,21 +1673,23 @@ + call_lst *pcall = (call_lst *)*pcbp->param; + if ((ntype == TMCB_ON_FAILURE) || (pcbp->req == FAKED_REPLY)) + { +- LM_ERR ("%sCall (%s) did not respond to REFER", pfncname, ++ LM_ERR ("%sCall (%s) did not respond to REFER!\n", pfncname, + pcall->call_from); +- drop_call (pcbp->req, pcall); ++ end_RTP (pcbp->req, pcall); ++ delete_call (pcall); + return; + } + int nreply = pcbp->code; + if ((nreply / 100) == 2) + { ++ pcall->refer_time = time (0); + pcall->call_state = CLSTA_RFRWAIT; + mohq_debug (pcall->pmohq, "%sCall (%s) REFER reply=%d", + pfncname, pcall->call_from, nreply); + } + else + { +- LM_ERR ("%sCall (%s) REFER error (%d)", pfncname, ++ LM_ERR ("%sCall (%s) REFER error (%d)!\n", pfncname, + pcall->call_from, nreply); + if (nreply == 481) + { delete_call (pcall); } +@@ -1547,10 +1708,10 @@ + * INPUT: + * Arg (1) = SIP message pointer + * Arg (2) = call pointer +-* OUTPUT: 0=failed ++* OUTPUT: none + **********/ + +-int reinvite_msg (sip_msg_t *pmsg, call_lst *pcall) ++void reinvite_msg (sip_msg_t *pmsg, call_lst *pcall) + + { + /********** +@@ -1565,17 +1726,17 @@ + mohq_debug (pcall->pmohq, "%sINVITE still pending for call (%s)", + pfncname, pcall->call_from); + if (pmod_data->psl->freply (pmsg, 491, presp_reqpend) < 0) +- { LM_ERR ("%sUnable to create reply!", pfncname); } +- return 1; ++ { LM_ERR ("%sUnable to create reply!\n", pfncname); } ++ return; + } + if (!(pmsg->msg_flags & FL_SDP_BODY)) + { + if (parse_sdp (pmsg)) + { +- LM_ERR ("%sre-INVITE lacks SDP (%s)!", pfncname, pcall->call_from); ++ LM_ERR ("%sre-INVITE lacks SDP (%s)!\n", pfncname, pcall->call_from); + if (pmod_data->psl->freply (pmsg, 488, presp_noaccept) < 0) +- { LM_ERR ("%sUnable to create reply!", pfncname); } +- return 1; ++ { LM_ERR ("%sUnable to create reply!\n", pfncname); } ++ return; + } + } + +@@ -1645,12 +1806,12 @@ + { + if (!bmatch) + { +- LM_ERR ("%sre-INVITE refused because no matching payload for call (%s)!", ++ LM_ERR ("%sre-INVITE refused because no matching payload for call (%s)!\n", + pfncname, pcall->call_from); + if (pmod_data->psl->freply (pmsg, 488, presp_noaccept) < 0) + { +- LM_ERR ("%sUnable to create reply!", pfncname); +- return 1; ++ LM_ERR ("%sUnable to create reply!\n", pfncname); ++ return; + } + } + else +@@ -1659,26 +1820,26 @@ + pfncname, pcall->call_from); + if (pmod_data->psl->freply (pmsg, 200, presp_ok) < 0) + { +- LM_ERR ("%sUnable to create reply!", pfncname); +- return 1; ++ LM_ERR ("%sUnable to create reply!\n", pfncname); ++ return; + } + } +- return 1; ++ return; + } + + /********** + * hold not allowed, say good-bye + **********/ + +-LM_ERR ("%sTerminating call (%s) because hold not allowed!", ++LM_ERR ("%sTerminating call (%s) because hold not allowed!\n", + pfncname, pcall->call_from); + if (pmod_data->psl->freply (pmsg, 200, presp_ok) < 0) + { +- LM_ERR ("%sUnable to create reply!", pfncname); +- return 1; ++ LM_ERR ("%sUnable to create reply!\n", pfncname); ++ return; + } + close_call (pmsg, pcall); +-return 1; ++return; + } + + /********** +@@ -1746,22 +1907,21 @@ + "Accept-Language: en" SIPEOL + "Require: 100rel" SIPEOL + "RSeq: %d" SIPEOL +- "User-Agent: " USRAGNT SIPEOL + ; + sprintf (phdrtmp, phdrtmplt, pcall->call_cseq); + struct lump_rpl **phdrlump = add_lump_rpl2 (pmsg, phdrtmp, + strlen (phdrtmp), LUMP_RPL_HDR); + if (!phdrlump) + { +- LM_ERR ("%sUnable to create new header for call (%s)!", ++ LM_ERR ("%sUnable to create new header for call (%s)!\n", + pfncname, pcall->call_from); + if (pmod_data->psl->freply (pmsg, 500, presp_srverr) < 0) +- { LM_ERR ("%sUnable to create reply!", pfncname); } ++ { LM_ERR ("%sUnable to create reply!\n", pfncname); } + return 0; + } + if (ptm->t_reply (pmsg, 180, presp_ring->s) < 0) + { +- LM_ERR ("%sUnable to reply to INVITE for call (%s)", ++ LM_ERR ("%sUnable to reply to INVITE for call (%s)!\n", + pfncname, pcall->call_from); + return 0; + } +@@ -1782,7 +1942,7 @@ + { break; } + if (nstart < time (0)) + { +- LM_ERR ("%sNo PRACK response for call (%s)", ++ LM_ERR ("%sNo PRACK response for call (%s)!\n", + pfncname, pcall->call_from); + break; + } +@@ -1822,7 +1982,7 @@ + (unsigned int *)&pbuf->len, pBM); + if (!pbuf->s || !pbuf->len) + { +- LM_ERR ("%sUnable to create SDP response for call (%s)!", ++ LM_ERR ("%sUnable to create SDP response for call (%s)!\n", + pfncname, pcall->call_from); + return 0; + } +@@ -1895,7 +2055,7 @@ + char *pnewbuf = pkg_malloc (npos1); + if (!pnewbuf) + { +- LM_ERR ("%sNo more memory!", pfncname); ++ LM_ERR ("%sNo more memory!\n", pfncname); + goto answer_done; + } + for (npos1 = npos2 = 0; npos2 < nhdrcnt; npos2++) +@@ -1925,7 +2085,7 @@ + memcpy (&pnmsg->rcv, &pmsg->rcv, sizeof (struct receive_info)); + + /********** +-* o send rtpproxy answer ++* o send RTP answer + * o form stream file + * o send stream + **********/ +@@ -1934,7 +2094,7 @@ + pfncname, pcall->call_from); + if (pmod_data->fn_rtp_answer (pnmsg, 0, 0) != 1) + { +- LM_ERR ("%srtpproxy_answer refused for call (%s)!", ++ LM_ERR ("%srtpproxy_answer refused for call (%s)!\n", + pfncname, pcall->call_from); + goto answer_done; + } +@@ -1951,7 +2111,7 @@ + free_sip_msg (pnmsg); + if (!pbuf->s || !pbuf->len) + { +- LM_ERR ("%sUnable to create SDP response for call (%s)!", ++ LM_ERR ("%sUnable to create SDP response for call (%s)!\n", + pfncname, pcall->call_from); + goto answer_done; + } +@@ -1975,26 +2135,26 @@ + if (!pfnd) + { + // should not happen +- LM_ERR ("%sUnable to find audio port for call (%s)!", ++ LM_ERR ("%sUnable to find audio port for call (%s)!\n", + pfncname, pcall->call_from); + goto answer_done; + } + pcall->call_aport = strtol (pfnd + 8, NULL, 10); + if (!add_lump_rpl2 (pmsg, pextrahdr->s, pextrahdr->len, LUMP_RPL_HDR)) + { +- LM_ERR ("%sUnable to add header for call (%s)!", ++ LM_ERR ("%sUnable to add header for call (%s)!\n", + pfncname, pcall->call_from); + goto answer_done; + } + if (!add_lump_rpl2 (pmsg, pnewSDP->s, pnewSDP->len, LUMP_RPL_BODY)) + { +- LM_ERR ("%sUnable to add SDP body for call (%s)!", ++ LM_ERR ("%sUnable to add SDP body for call (%s)!\n", + pfncname, pcall->call_from); + goto answer_done; + } + if (ptm->t_reply (pmsg, 200, presp_ok->s) < 0) + { +- LM_ERR ("%sUnable to reply to INVITE for call (%s)!", ++ LM_ERR ("%sUnable to reply to INVITE for call (%s)!\n", + pfncname, pcall->call_from); + goto answer_done; + } +@@ -2043,7 +2203,7 @@ + pfncname, pcall->call_from); + if (fn_stream (pmsg, (char *)pmodel, (char *)-1) != 1) + { +- LM_ERR ("%srtpproxy_stream refused for call (%s)!", ++ LM_ERR ("%srtpproxy_stream refused for call (%s)!\n", + pfncname, pcall->call_from); + return 0; + } +@@ -2051,6 +2211,33 @@ + } + + /********** ++* Stop Streaming ++* ++* INPUT: ++* Arg (1) = SIP message pointer ++* Arg (2) = call pointer ++* Arg (3) = server flag ++* OUTPUT: 0 if failed ++**********/ ++ ++int stop_stream (sip_msg_t *pmsg, call_lst *pcall, int bserver) ++ ++{ ++char *pfncname = "stop_stream: "; ++cmd_function fn_stop = bserver ? pmod_data->fn_rtp_stop_s ++ : pmod_data->fn_rtp_stop_c; ++mohq_debug (pcall->pmohq, "%sStopping RTP link for call (%s)", ++ pfncname, pcall->call_from); ++if (fn_stop (pmsg, (char *)-1, (char *)-1) != 1) ++ { ++ LM_ERR ("%srtpproxy_stop refused for call (%s)!\n", ++ pfncname, pcall->call_from); ++ return 0; ++ } ++return 1; ++} ++ ++/********** + * Form Char Array from STR + * + * INPUT: +@@ -2064,7 +2251,7 @@ + char *pcstr = malloc (pstr->len + 1); + if (!pcstr) + { +- LM_ERR ("No more memory!"); ++ LM_ERR ("No more memory!\n"); + return NULL; + } + memcpy (pcstr, pstr->s, pstr->len); +@@ -2164,7 +2351,7 @@ + struct mi_node *pnode = pcmd_tree->node.kids; + if (!pnode || !pnode->next || pnode->next->next) + { return init_mi_tree (400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN); } +-int nq_idx = find_queue (&pnode->value); ++int nq_idx = find_qname (&pnode->value); + if (nq_idx == -1) + { return init_mi_tree (400, pmi_noqueue->s, pmi_noqueue->len); } + char pint [20]; +@@ -2217,7 +2404,7 @@ + struct mi_node *pnode = pcmd_tree->node.kids; + if (!pnode || !pnode->next || pnode->next->next) + { return init_mi_tree (400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN); } +-int nq_idx = find_queue (&pnode->value); ++int nq_idx = find_qname (&pnode->value); + if (nq_idx == -1) + { return init_mi_tree (400, pmi_noqueue->s, pmi_noqueue->len); } + if (!mohq_lock_set (pmod_data->pcall_lock, 0, 5000)) +@@ -2240,7 +2427,7 @@ + **********/ + + call_lst *pcall = &pmod_data->pcall_lst [nidx]; +- if (!pcall->call_active) ++ if (!pcall->call_state) + { continue; } + if (pqueue->mohq_id != pcall->pmohq->mohq_id) + { continue; } +@@ -2279,12 +2466,12 @@ + str pqname [1]; + if (!pqueue || !presult) + { +- LM_ERR ("%sParameters missing!", pfncname); ++ LM_ERR ("%sParameters missing!\n", pfncname); + return -1; + } + if (fixup_get_svalue (pmsg, (gparam_p)pqueue, pqname)) + { +- LM_ERR ("%sInvalid queue name!", pfncname); ++ LM_ERR ("%sInvalid queue name!\n", pfncname); + return -1; + } + +@@ -2294,12 +2481,12 @@ + * o count items in queue + **********/ + +-int nq_idx = find_queue (pqname); ++int nq_idx = find_qname (pqname); + int ncount = 0; + call_lst *pcalls = pmod_data->pcall_lst; + int ncall_idx, mohq_id; + if (!mohq_lock_set (pmod_data->pcall_lock, 0, 200)) +- { LM_ERR ("%sUnable to lock calls!", pfncname); } ++ { LM_ERR ("%sUnable to lock calls!\n", pfncname); } + else + { + if (nq_idx != -1) +@@ -2307,7 +2494,7 @@ + mohq_id = pmod_data->pmohq_lst [nq_idx].mohq_id; + for (ncall_idx = 0; ncall_idx < pmod_data->call_cnt; ncall_idx++) + { +- if (!pcalls [ncall_idx].call_active) ++ if (!pcalls [ncall_idx].call_state) + { continue; } + if (pcalls [ncall_idx].pmohq->mohq_id == mohq_id + && pcalls [ncall_idx].call_state == CLSTA_INQUEUE) +@@ -2328,7 +2515,7 @@ + pavp_val->flags = PV_TYPE_INT | PV_VAL_INT; + if (presult->setf (pmsg, &presult->pvp, (int)EQ_T, pavp_val) < 0) + { +- LM_ERR ("%sUnable to set pv value for mohq_count ()!", pfncname); ++ LM_ERR ("%sUnable to set pv value for mohq_count ()!\n", pfncname); + return -1; + } + return 1; +@@ -2366,7 +2553,7 @@ + va_start (ap, pfmt); + vsnprintf (ptext, sizeof (ptext), pfmt, ap); + va_end (ap); +-LM_DBG ("%s", ptext); ++LM_DBG ("%s\n", ptext); + if (nsys_log < nmohq_log) + { reset_local_debug_level (); } + return; +@@ -2377,39 +2564,28 @@ + * + * INPUT: + * Arg (1) = SIP message pointer +-* OUTPUT: -1=not directed to queue; 1=successfully processed ++* OUTPUT: -1=not directed to queue or other error; 1=processed + **********/ + + int mohq_process (sip_msg_t *pmsg) + + { + /********** +-* o parse headers +-* o lock MOH queue +-* o directed to message queue? +-* o connect to database ++* read lock queue and check for updates + **********/ + + char *pfncname = "mohq_process: "; +-if (parse_headers (pmsg, HDR_EOH_F, 0) < 0) ++if (!mohq_lock_set (pmod_data->pmohq_lock, 0, 500)) + { +- LM_ERR ("%sUnable to parse header!", pfncname); ++ LM_ERR ("%sUnable to read lock queue!\n", pfncname); + return -1; + } +-if (!mohq_lock_set (pmod_data->pmohq_lock, 0, 2000)) +- { +- LM_ERR ("%sUnable to lock calls!", pfncname); +- return -1; +- } +-call_lst *pcall; +-int mohq_idx = find_call (pmsg, &pcall); + db1_con_t *pconn = mohq_dbconnect (); + if (pconn) + { + /********** + * o last update older than 1 minute? +- * o exclusively lock MOH queue +- * o update queue ++ * o update write locked queue + **********/ + + if (pmod_data->mohq_update + 60 < time (0)) +@@ -2423,22 +2599,51 @@ + } + mohq_dbdisconnect (pconn); + } ++ ++/********** ++* o parse headers ++* o directed to message queue? ++* o write lock calls ++* o search for call ++* o release call lock ++**********/ ++ ++if (parse_headers (pmsg, HDR_EOH_F, 0) < 0) ++ { ++ mohq_lock_release (pmod_data->pmohq_lock); ++ LM_ERR ("%sUnable to parse header!\n", pfncname); ++ return -1; ++ } ++int mohq_idx = find_queue (pmsg); + if (mohq_idx < 0) + { + mohq_lock_release (pmod_data->pmohq_lock); + return -1; + } ++if (!mohq_lock_set (pmod_data->pcall_lock, 1, 500)) ++ { ++ mohq_lock_release (pmod_data->pmohq_lock); ++ LM_ERR ("%sUnable to write lock calls!\n", pfncname); ++ return 1; ++ } ++call_lst *pcall = find_call (pmsg, mohq_idx); ++mohq_lock_release (pmod_data->pcall_lock); ++if (!pcall) ++ { ++ mohq_lock_release (pmod_data->pmohq_lock); ++ return 1; ++ } + + /********** + * o process message +-* o release MOH queue ++* o release queue lock + **********/ + + mohq_debug (&pmod_data->pmohq_lst [mohq_idx], + "%sProcessing %.*s, queue (%s)", pfncname, + STR_FMT (&REQ_LINE (pmsg).method), + pmod_data->pmohq_lst [mohq_idx].mohq_name); +-int ret; ++str *ptotag; + switch (pmsg->REQ_METHOD) + { + case METHOD_INVITE: +@@ -2446,33 +2651,35 @@ + * initial INVITE? + **********/ + +- if (!pcall) +- { ret = first_invite_msg (pmsg, mohq_idx); } ++ ptotag = &(get_to (pmsg)->tag_value); ++ if (!ptotag->len) ++ { ptotag = 0; } ++ if (!ptotag) ++ { first_invite_msg (pmsg, pcall); } + else +- { ret = reinvite_msg (pmsg, pcall); } ++ { reinvite_msg (pmsg, pcall); } + break; + case METHOD_NOTIFY: +- ret = notify_msg (pmsg, pcall); ++ notify_msg (pmsg, pcall); + break; + case METHOD_PRACK: +- ret = prack_msg (pmsg, pcall); ++ prack_msg (pmsg, pcall); + break; + case METHOD_ACK: +- ret = ack_msg (pmsg, pcall); ++ ack_msg (pmsg, pcall); + break; + case METHOD_BYE: +- ret = bye_msg (pmsg, pcall); ++ bye_msg (pmsg, pcall); + break; + case METHOD_CANCEL: +- ret = cancel_msg (pmsg, pcall); ++ cancel_msg (pmsg, pcall); + break; + default: + deny_method (pmsg, pcall); +- ret = 1; + break; + } + mohq_lock_release (pmod_data->pmohq_lock); +-return ret ? 1 : -1; ++return 1; + } + + /********** +@@ -2497,28 +2704,28 @@ + str puri [1], pqname [1]; + if (!pqueue || !pURI) + { +- LM_ERR ("%sParameters missing!", pfncname); ++ LM_ERR ("%sParameters missing!\n", pfncname); + return -1; + } + if (fixup_get_svalue (pmsg, (gparam_p)pqueue, pqname)) + { +- LM_ERR ("%sInvalid queue name!", pfncname); ++ LM_ERR ("%sInvalid queue name!\n", pfncname); + return -1; + } + if (fixup_get_svalue (pmsg, (gparam_p)pURI, puri)) + { +- LM_ERR ("%sInvalid URI!", pfncname); ++ LM_ERR ("%sInvalid URI!\n", pfncname); + return -1; + } + if (puri->len > URI_LEN) + { +- LM_ERR ("%sURI too long!", pfncname); ++ LM_ERR ("%sURI too long!\n", pfncname); + return -1; + } + struct sip_uri puri_parsed [1]; + if (parse_uri (puri->s, puri->len, puri_parsed)) + { +- LM_ERR ("%sInvalid URI (%.*s)!", pfncname, STR_FMT (puri)); ++ LM_ERR ("%sInvalid URI (%.*s)!\n", pfncname, STR_FMT (puri)); + return -1; + } + +@@ -2528,12 +2735,12 @@ + * o find oldest call + **********/ + +-int nq_idx = find_queue (pqname); ++int nq_idx = find_qname (pqname); + if (nq_idx == -1) + { return -1; } + if (!mohq_lock_set (pmod_data->pcall_lock, 0, 200)) + { +- LM_ERR ("%sUnable to lock calls!", pfncname); ++ LM_ERR ("%sUnable to lock calls!\n", pfncname); + return -1; + } + call_lst *pcall = 0; +@@ -2546,15 +2753,27 @@ + /********** + * o active call? + * o matching queue? ++ * o refer stuck? + * o in queue? + * o check age + **********/ + + pcall = &pmod_data->pcall_lst [ncall_idx]; +- if (!pcall->call_active) ++ if (!pcall->call_state) + { continue; } + if (pcall->pmohq->mohq_id != mohq_id) + { continue; } ++ if ((pcall->call_state == CLSTA_REFER) ++ || (pcall->call_state == CLSTA_RFRWAIT)) ++ { ++ if ((pcall->refer_time + 32) < time (0)) ++ { ++ LM_ERR ++ ("%sDropping call because no response to REFER for call (%s)!\n", ++ pfncname, pcall->call_from); ++ close_call (FAKED_REPLY, pcall); ++ } ++ } + if (pcall->call_state != CLSTA_INQUEUE) + { continue; } + if (!ntime) +@@ -2573,7 +2792,7 @@ + } + if (nfound == -1) + { +- LM_WARN ("%sNo calls in queue (%.*s)", pfncname, STR_FMT (pqname)); ++ LM_WARN ("%sNo calls in queue (%.*s)\n", pfncname, STR_FMT (pqname)); + mohq_lock_release (pmod_data->pcall_lock); + return -1; + } +@@ -2588,7 +2807,7 @@ + pcall->call_referto [puri->len] = '\0'; + if (refer_call (pcall, pmod_data->pcall_lock)) + { return 1; } +-LM_ERR ("%sUnable to refer call (%s)!", pfncname, pcall->call_from); ++LM_ERR ("%sUnable to refer call (%s)!\n", pfncname, pcall->call_from); + return -1; + } + +@@ -2612,24 +2831,24 @@ + char *pfncname = "mohq_send: "; + if (pmsg->REQ_METHOD != METHOD_INVITE) + { +- LM_ERR ("%sNot an INVITE message!", pfncname); ++ LM_ERR ("%sNot an INVITE message!\n", pfncname); + return -1; + } + to_body_t *pto_body = get_to (pmsg); + if (pto_body->tag_value.len) + { +- LM_ERR ("%sNot a first INVITE message!", pfncname); ++ LM_ERR ("%sNot a first INVITE message!\n", pfncname); + return -1; + } + str pqname [1]; + if (!pqueue) + { +- LM_ERR ("%sParameters missing!", pfncname); ++ LM_ERR ("%sParameters missing!\n", pfncname); + return -1; + } + if (fixup_get_svalue (pmsg, (gparam_p)pqueue, pqname)) + { +- LM_ERR ("%sInvalid queue name!", pfncname); ++ LM_ERR ("%sInvalid queue name!\n", pfncname); + return -1; + } + +@@ -2639,14 +2858,14 @@ + * o relay message + **********/ + +-int nq_idx = find_queue (pqname); ++int nq_idx = find_qname (pqname); + if (nq_idx == -1) + { return -1; } + str pruri [1] = {{0, strlen (pmod_data->pmohq_lst [nq_idx].mohq_uri)}}; + pruri->s = pkg_malloc (pruri->len + 1); + if (!pruri->s) + { +- LM_ERR ("%sNo more memory!", pfncname); ++ LM_ERR ("%sNo more memory!\n", pfncname); + return -1; + } + strcpy (pruri->s, pmod_data->pmohq_lst [nq_idx].mohq_uri); +@@ -2658,7 +2877,7 @@ + pmsg->parsed_orig_ruri_ok = 0; + if (pmod_data->ptm->t_relay (pmsg, 0, 0) < 0) + { +- LM_ERR ("%sUnable to relay INVITE!", pfncname); ++ LM_ERR ("%sUnable to relay INVITE!\n", pfncname); + return -1; + } + return 1; +--- a/modules/mohqueue/mohq_funcs.h ++++ b/modules/mohqueue/mohq_funcs.h +@@ -1,9 +1,7 @@ + /* +- * $Id$ ++ * Copyright (C) 2013-15 Robert Boisvert + * +- * 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 +--- a/modules/mohqueue/mohq_locks.c ++++ b/modules/mohqueue/mohq_locks.c +@@ -1,10 +1,8 @@ + /* +- * $Id$ ++ * Copyright (C) 2013-15 Robert Boisvert + * +- * Copyright (C) 2013 Robert Boisvert ++ * This file is part of the mohqueue module for Kamailio, a free SIP server. + * +- * This file is part of the mohqueue module for sip-router, 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 + * the Free Software Foundation; either version 2 of the License, or +@@ -103,12 +101,12 @@ + plock->plock = lock_alloc (); + if (!plock->plock) + { +- LM_ERR ("%sUnable to allocate lock memory!", pfncname); ++ LM_ERR ("%sUnable to allocate lock memory!\n", pfncname); + return 0; + } + if (!lock_init (plock->plock)) + { +- LM_ERR ("%sUnable to init lock!", pfncname); ++ LM_ERR ("%sUnable to init lock!\n", pfncname); + lock_dealloc (plock->plock); + return 0; + } +@@ -140,7 +138,7 @@ + plock->lock_cnt = 0; + break; + case 0: +- LM_WARN ("mohq_lock_release: Lock was not set"); ++ LM_WARN ("mohq_lock_release: Lock was not set.\n"); + break; + default: + plock->lock_cnt--; +--- a/modules/mohqueue/mohq_locks.h ++++ b/modules/mohqueue/mohq_locks.h +@@ -1,9 +1,7 @@ + /* +- * $Id$ ++ * Copyright (C) 2013-15 Robert Boisvert + * +- * 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 diff --git a/main/kamailio/APKBUILD b/main/kamailio/APKBUILD index ccf91bb8e4..e6589894a9 100644 --- a/main/kamailio/APKBUILD +++ b/main/kamailio/APKBUILD @@ -13,7 +13,7 @@ _gittag=HEAD pkgver=4.2.5 -pkgrel=0 +pkgrel=1 [ -z "${_gitcommit}" ] && _suffix="_src" || _suffix="-${_gitcommit}" pkgdesc="Open Source SIP Server" @@ -227,6 +227,7 @@ source="http://www.kamailio.org/pub/kamailio/$pkgver/src/kamailio-${pkgver}${_su 0001-musl-fixes.patch kamailio-4.2-ipops-srv-query.patch DMQ-multi-notify.patch + 0002-mohqueue-v0-11.patch default_ctl.patch kamctl_build.patch @@ -496,6 +497,7 @@ bad1ac2d4c95043df271d2ea6d37627a kamailio-4.2-backslash.patch 4685288dc54680597b00f956dc95d4d6 0001-musl-fixes.patch e9c0ba8192a1a4f2a08a2e2add20e3d7 kamailio-4.2-ipops-srv-query.patch 7df723eb9e14df28adfff8643d99a1a9 DMQ-multi-notify.patch +2ebca868c6f99ffc12f544b7585d11bf 0002-mohqueue-v0-11.patch 841fa62c432c5d8aeb57ad70d2ec3030 default_ctl.patch d0052e6054884b9cec955af4480c7c85 kamctl_build.patch 299706d97e30a4f0d9b4c873df422866 kamailio.cfg @@ -505,6 +507,7 @@ d7e59be721ed0ad4621d404493b9a519708d801e9d4914b0164b819fa1abcd13 kamailio-4.2-b b98555ff304b51b82c6cf7e01d757b15ea4f05bd2e603c84d4384df6a6be62b6 0001-musl-fixes.patch 7e33c95bdb942e4ed6d54e14476cad2ee7edfc256b1f250e5f133d9e8a9b2a67 kamailio-4.2-ipops-srv-query.patch 384eeaa5b253228341dc7a74ec61314db4b8f2f1c9c2f3bdf9ba189d2d56911d DMQ-multi-notify.patch +67367f0ebd85dcdfde1fbf4ac964fd70e6ee16cddcb81e7320b0eceddf91d08f 0002-mohqueue-v0-11.patch 755efa4ad126c672bc67c53268260b57f7da1f454cdc1a1601778ed7c7d5f0e5 default_ctl.patch e00eefed792acbc1ee6eca8fa7389f9973bd53b68fa7abc573f19f1ff26812a1 kamctl_build.patch 8b742ff710ef67ff59ec07a260690ebcdda24fb6f0b7b64dc50433a1bacf99f2 kamailio.cfg @@ -514,6 +517,7 @@ a9bb1e8f9f373264b8351ddae099a36a46ddd46fdec09e468d297ba4f64bb4896e7d6e599da70a42 dea7ef2ccf01357576045ba375d41301e2447b4454324007c7ca1862322835c57045852017192ca5434b32dd1b7a2e9669209b7111889dab335b74f042d0f11f 0001-musl-fixes.patch b5c048b6e06de0c7514c14d0ec99bbe939eaa956d9d9d3dd5f48b1bcbcff06dbd6498d384427253fb655997a10ec5fa31dcc5cfd2f8cc5c64dcd531649133781 kamailio-4.2-ipops-srv-query.patch 7ddf6444c15f7338e7aab779ea5b75f4fd936b51cf5d9ba0d09e813566e527f74e59e100661d2b27db99e5fa042614c83e8145e999a8b6bfcfab71c9595bb626 DMQ-multi-notify.patch +3e6c961e7674bc7b464ea3b8694b35962dae7a432cad724ea0bd9e6cb9dd62bb898ad4dd09270d847d6473d3ed62bc7a08f5683f69d72b462d083a6ab5c44eae 0002-mohqueue-v0-11.patch 2321d8afe29b53057ce21e0552dfb80fd6a0e7dc0caf3c4798a8b253518f4c8c546797302933373f4b055a4531329a36ee2d7117b0a88fe39cf153bfef91a656 default_ctl.patch 4c2c9bde3a4c44feca2863bb03cb031aa55e1c3df21dc7c0acb3a392c34cb36d9a132bcbdf451a0624f8ec202152f1cf238c89280c32f1c04312ce80427a18c6 kamctl_build.patch c1abf69b48847dc8c7ab0d11ef9adb531aa4635f9d44db6933981edc5a47df374664fb24867b19aa64abbcc9777bf1cd0360d9aea54e27b081065928c61e0f0b kamailio.cfg |