[asterisk-commits] mvanbaak: branch group/multiparking r104047 - /team/group/multiparking/
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Sat Feb 23 05:48:09 CST 2008
Author: mvanbaak
Date: Sat Feb 23 05:48:08 2008
New Revision: 104047
URL: http://svn.digium.com/view/asterisk?view=rev&rev=104047
Log:
add patchfile so both me and oej can have a look at it
Added:
team/group/multiparking/multipark_clean.diff (with props)
Added: team/group/multiparking/multipark_clean.diff
URL: http://svn.digium.com/view/asterisk/team/group/multiparking/multipark_clean.diff?view=auto&rev=104047
==============================================================================
--- team/group/multiparking/multipark_clean.diff (added)
+++ team/group/multiparking/multipark_clean.diff Sat Feb 23 05:48:08 2008
@@ -1,0 +1,1860 @@
+diff -ruN trunk/channels/chan_iax2.c multiparking/channels/chan_iax2.c
+--- trunk/channels/chan_iax2.c 2007-05-25 00:07:50.000000000 +0200
++++ multiparking/channels/chan_iax2.c 2007-05-25 01:13:02.000000000 +0200
+@@ -149,6 +151,7 @@
+
+
+ static char context[80] = "default";
++static char default_parkinglot[AST_MAX_EXTENSION];
+
+ static char language[MAX_LANGUAGE] = "";
+ static char regcontext[AST_MAX_CONTEXT] = "";
+@@ -313,6 +316,8 @@
+
+ int authmethods;
+ int encmethods;
++ char parkinglot[AST_MAX_EXTENSION]; /*!< Default parkinglot for device */
++ /* XXX Needs to be a string field */
+ int amaflags;
+ int adsi;
+ unsigned int flags;
+@@ -346,6 +351,7 @@
+ AST_STRING_FIELD(cid_name); /*!< Default context (for transfer really) */
+ AST_STRING_FIELD(zonetag); /*!< Time Zone */
+ );
++ char parkinglot[AST_MAX_EXTENSION]; /*!< Default parkinglot for device */
+ struct ast_codec_pref prefs;
+ struct ast_dnsmgr_entry *dnsmgr; /*!< DNS refresh manager */
+ struct sockaddr_in addr;
+@@ -634,6 +640,7 @@
+ int calling_ton;
+ int calling_tns;
+ int calling_pres;
++ char parkinglot[AST_MAX_EXTENSION]; /*!< Default parkinglot for device */
+ int amaflags;
+ AST_LIST_HEAD_NOLOCK(, iax2_dpcache) dpentries;
+ struct ast_variable *vars;
+@@ -1376,6 +1383,7 @@
+ ast_string_field_set(iaxs[x], accountcode, accountcode);
+ ast_string_field_set(iaxs[x], mohinterpret, mohinterpret);
+ ast_string_field_set(iaxs[x], mohsuggest, mohsuggest);
++ ast_copy_string(iaxs[x]->parkinglot, default_parkinglot, sizeof(iaxs[x]->parkinglot));
+ } else {
+ ast_log(LOG_WARNING, "Out of resources\n");
+ ast_mutex_unlock(&iaxsl[x]);
+@@ -2104,6 +2112,7 @@
+ ast_cli(fd, " * Name : %s\n", peer->name);
+ ast_cli(fd, " Secret : %s\n", ast_strlen_zero(peer->secret)?"<Not set>":"<Set>");
+ ast_cli(fd, " Context : %s\n", peer->context);
++ ast_cli(fd, " Parking lot : %s\n", peer->parkinglot);
+ ast_cli(fd, " Mailbox : %s\n", peer->mailbox);
+ ast_cli(fd, " Dynamic : %s\n", ast_test_flag(peer, IAX_DYNAMIC) ? "Yes":"No");
+ ast_cli(fd, " Callerid : %s\n", ast_callerid_merge(cbuf, sizeof(cbuf), peer->cid_name, peer->cid_num, "<unspecified>"));
+@@ -3449,6 +3458,8 @@
+ tmp->writeformat = ast_best_codec(capability);
+ tmp->tech_pvt = CALLNO_TO_PTR(i->callno);
+
++ if (!ast_strlen_zero(i->parkinglot))
++ ast_string_field_set(tmp, parkinglot, i->parkinglot);
+ /* Don't use ast_set_callerid() here because it will
+ * generate a NewCallerID event before the NewChannel event */
+ tmp->cid.cid_num = ast_strdup(i->cid_num);
+@@ -4927,6 +4938,8 @@
+ ast_string_field_set(iaxs[callno], mohinterpret, user->mohinterpret);
+ if (!ast_strlen_zero(user->mohsuggest))
+ ast_string_field_set(iaxs[callno], mohsuggest, user->mohsuggest);
++ if (!ast_strlen_zero(user->parkinglot))
++ ast_copy_string(iaxs[callno]->parkinglot, user->parkinglot, sizeof(iaxs[callno]->parkinglot));
+ if (user->amaflags)
+ iaxs[callno]->amaflags = user->amaflags;
+ if (!ast_strlen_zero(user->language))
+@@ -9021,6 +9034,8 @@
+ ast_string_field_set(user, mohinterpret, v->value);
+ } else if (!strcasecmp(v->name, "mohsuggest")) {
+ ast_string_field_set(user, mohsuggest, v->value);
++ } else if (!strcasecmp(v->name, "parkinglot")) {
++ ast_copy_string(user->parkinglot, v->value, sizeof(user->parkinglot));
+ } else if (!strcasecmp(v->name, "language")) {
+ ast_string_field_set(user, language, v->value);
+ } else if (!strcasecmp(v->name, "amaflags")) {
+@@ -9225,6 +9240,8 @@
+ #ifdef SO_NO_CHECK
+ nochecksums = 0;
+ #endif
++ /* Reset default parking lot */
++ default_parkinglot[0] = '\0';
+
+ min_reg_expire = IAX_DEFAULT_REG_EXPIRE;
+ max_reg_expire = IAX_DEFAULT_REG_EXPIRE;
+@@ -9424,6 +9441,8 @@
+ } else if (!strcasecmp(v->name, "cos")) {
+ if (ast_str2cos(v->value, &cos))
+ ast_log(LOG_WARNING, "Invalid cos value at line %d, see doc/qos.tex for more information.'\n", v->lineno);
++ } else if (!strcasecmp(v->name, "parkinglot")) {
++ ast_copy_string(default_parkinglot, v->value, sizeof(default_parkinglot));
+ } else if (!strcasecmp(v->name, "accountcode")) {
+ ast_copy_string(accountcode, v->value, sizeof(accountcode));
+ } else if (!strcasecmp(v->name, "mohinterpret")) {
+diff -ruN trunk/channels/chan_zap.c multiparking/channels/chan_zap.c
+--- trunk/channels/chan_zap.c 2007-05-30 18:11:57.000000000 +0200
++++ multiparking/channels/chan_zap.c 2007-05-30 19:14:45.000000000 +0200
+@@ -214,6 +214,7 @@
+ static char defaultcic[64] = "";
+ static char defaultozz[64] = "";
+
++static char parkinglot[AST_MAX_EXTENSION] = ""; /*!< Default parking lot for this channel */
+ static char progzone[10] = "";
+
+ static int usedistinctiveringdetection = 0;
+@@ -556,6 +557,7 @@
+ char language[MAX_LANGUAGE];
+ char mohinterpret[MAX_MUSICCLASS];
+ char mohsuggest[MAX_MUSICCLASS];
++ AST_STRING_FIELD(parkinglot); /*!< Parking lot for this channel */
+ #ifdef PRI_ANI
+ char cid_ani[AST_MAX_EXTENSION];
+ #endif
+@@ -5638,6 +5640,8 @@
+ tmp->callgroup = i->callgroup;
+ tmp->pickupgroup = i->pickupgroup;
+ }
++ if (!ast_strlen_zero(i->parkinglot))
++ ast_string_field_set(tmp, parkinglot, i->parkinglot);
+ if (!ast_strlen_zero(i->language))
+ ast_string_field_set(tmp, language, i->language);
+ if (!i->owner)
+@@ -7886,6 +7890,7 @@
+ ast_copy_string(tmp->mohsuggest, conf.chan.mohsuggest, sizeof(tmp->mohsuggest));
+ ast_copy_string(tmp->context, conf.chan.context, sizeof(tmp->context));
+ ast_copy_string(tmp->cid_num, conf.chan.cid_num, sizeof(tmp->cid_num));
++ ast_string_field_set((tmp->parkinglot, parkinglot, sizeof(tmp->parkinglot));
+ tmp->cid_ton = 0;
+ ast_copy_string(tmp->cid_name, conf.chan.cid_name, sizeof(tmp->cid_name));
+ ast_copy_string(tmp->mailbox, conf.chan.mailbox, sizeof(tmp->mailbox));
+@@ -12054,6 +12059,8 @@
+ ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
+ } else if (!strcasecmp(v->name, "mohsuggest")) {
+ ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
++ } else if (!strcasecmp(v->name, "parkinglot")) {
++ ast_copy_string(parkinglot, v->value, sizeof(parkinglot));
+ } else if (!strcasecmp(v->name, "stripmsd")) {
+ confp->chan.stripmsd = atoi(v->value);
+ } else if (!strcasecmp(v->name, "jitterbuffers")) {
+diff -ruN trunk/configs/features.conf.sample multiparking/configs/features.conf.sample
+--- trunk/configs/features.conf.sample 2007-05-31 16:52:30.000000000 +0200
++++ multiparking/configs/features.conf.sample 2007-05-14 19:46:53.000000000 +0200
+@@ -3,10 +3,11 @@
+ ;
+
+ [general]
+-parkext => 700 ; What extension to dial to park
+-parkpos => 701-720 ; What extensions to park calls on. These needs to be
+- ; numeric, as Asterisk starts from the start position
++parkext => 700 ; What extension to dial to park (all parking lots)
++parkpos => 701-720 ; What extensions to park calls on. (defafult parking lot)
++ ; These needs to be numeric, as Asterisk starts from the start position
+ ; and increments with one for the next parked call.
++context => parkedcalls ; Which context parked calls are in (default parking lot)
+ context => parkedcalls ; Which context parked calls are in
+ ;parkingtime => 45 ; Number of seconds a call can be parked for
+ ; (default is 45 seconds)
+@@ -42,6 +43,7 @@
+ ;atxfercallbackretries = 2 ; Number of times to attempt to send the call back to the transferer.
+ ; By default, this is 2.
+
++
+ [featuremap]
+ ;blindxfer => #1 ; Blind transfer (default is #)
+ ;disconnect => *0 ; Disconnect (default is *)
+@@ -56,6 +58,7 @@
+ ;
+ ; Set(DYNAMIC_FEATURES=myfeature1#myfeature2#myfeature3)
+ ;
++
+ ;
+ ; The syntax for declaring a dynamic feature is the following:
+ ;
+@@ -100,20 +103,15 @@
+ ;unpauseMonitor => #3,self/callee,UnPauseMonitor ;Allow the callee to unpause monitoring
+ ; ;on their channel
+ ;
+-; GROUPS
+-; Groups are groupings of features defined in [applicationmap]
+-; that can have their own key mappings.
+-;
+-; Groups are defined as a configuration section,
+-; and can be set as part of DYNAMIC_FEATURES in
+-; the same way that a normal feature can...
+-; etc:
+-;
+-; Set(DYNAMIC_FEATURES=myGroupName);
+-;
+-; example:
+-; [myGroupName] ; defines the group named myGroupName
+-; testfeature => #9 ; associates testfeature with the group and the keycode #9
+-; pauseMonitor ; associates pauseMonitor with the group and the keycode
+-; ; defined in [applicationmap]
+
++
++
++;*** Define another parking lot
++;
++; You can set parkinglot with the CHANNEL dialplan function
++; or configure it in the device configuration in the channel
++;
++;[parkinglot_edvina]
++;context => edvinapark
++;parkpos => 800-850
++;findslot => next
+diff -ruN trunk/configs/iax.conf.sample multiparking/configs/iax.conf.sample
+--- trunk/configs/iax.conf.sample 2007-04-30 18:16:26.000000000 +0200
++++ multiparking/configs/iax.conf.sample 2007-05-14 19:46:53.000000000 +0200
+@@ -286,6 +286,10 @@
+ ; has expired based on its registration interval, used the stored
+ ; address information regardless. (yes|no)
+
++;parkinglot=edvina ; Default parkinglot for IAX peers and users
++ ; This can also be configured per device
++ ; Parkinglots are defined in features.conf
++
+ ; Guest sections for unauthenticated connection attempts. Just specify an
+ ; empty secret, or provide no secret section.
+ ;
+diff -ruN trunk/configs/sip.conf.sample multiparking/configs/sip.conf.sample
+--- trunk/configs/sip.conf.sample 2007-05-16 09:35:56.000000000 +0200
++++ multiparking/configs/sip.conf.sample 2007-05-16 10:06:18.000000000 +0200
+@@ -100,6 +100,9 @@
+ ;
+ ;mohsuggest=default
+ ;
++;parkinglot=plaza ; Sets the default parking lot for call parking
++ ; This may also be set for individual users/peers
++ ; Parkinglots are configured in features.conf
+ ;language=en ; Default language setting for all users/peers
+ ; This may also be set for individual users/peers
+ ;relaxdtmf=yes ; Relax dtmf handling
+diff -ruN trunk/funcs/func_channel.c multiparking/funcs/func_channel.c
+--- trunk/funcs/func_channel.c 2007-04-20 23:12:53.000000000 +0200
++++ multiparking/funcs/func_channel.c 2007-05-14 19:46:53.000000000 +0200
+@@ -83,6 +83,8 @@
+ locked_copy_string(chan, buf, chan->language, len);
+ else if (!strcasecmp(data, "musicclass"))
+ locked_copy_string(chan, buf, chan->musicclass, len);
++ else if (!strcasecmp(data, "parkinglot"))
++ locked_copy_string(chan, buf, chan->parkinglot, len);
+ else if (!strcasecmp(data, "state"))
+ locked_copy_string(chan, buf, ast_state2str(chan->_state), len);
+ else if (!strcasecmp(data, "channeltype"))
+@@ -109,6 +111,8 @@
+
+ if (!strcasecmp(data, "language"))
+ locked_string_field_set(chan, language, value);
++ else if (!strcasecmp(data, "parkinglot"))
++ locked_string_field_set(chan, parkinglot, value);
+ else if (!strcasecmp(data, "musicclass"))
+ locked_string_field_set(chan, musicclass, value);
+ else if (!strcasecmp(data, "tonezone")) {
+@@ -157,6 +161,7 @@
+ "R/O channeltype technology used for channel\n"
+ "R/W language language for sounds played\n"
+ "R/W musicclass class (from musiconhold.conf) for hold music\n"
++ "R/W parkinglot parkinglot for parking\n"
+ "R/W rxgain set rxgain level on channel drivers that support it\n"
+ "R/O state state for channel\n"
+ "R/W tonezone zone for indications played\n"
+diff -ruN trunk/include/asterisk/channel.h multiparking/include/asterisk/channel.h
+--- trunk/include/asterisk/channel.h 2007-05-22 20:52:59.000000000 +0200
++++ multiparking/include/asterisk/channel.h 2007-05-22 21:11:13.000000000 +0200
+@@ -394,6 +394,7 @@
+ AST_STRING_FIELD(accountcode); /*!< Account code for billing */
+ AST_STRING_FIELD(call_forward); /*!< Where to forward to if asked to dial on this interface */
+ AST_STRING_FIELD(uniqueid); /*!< Unique Channel Identifier */
++ AST_STRING_FIELD(parkinglot); /*! Default parking lot, if empty, default parking lot */
+ );
+
+ /*! \brief File descriptor for channel -- Drivers will poll on these file descriptors, so at least one must be non -1. See \ref AstFileDesc */
+diff -ruN trunk/res/res_features.c multiparking/res/res_features.c
+--- trunk/res/res_features.c 2007-05-31 16:52:30.000000000 +0200
++++ multiparking/res/res_features.c 2007-05-22 15:05:38.000000000 +0200
+@@ -58,10 +58,12 @@
+ #include "asterisk/adsi.h"
+ #include "asterisk/devicestate.h"
+ #include "asterisk/monitor.h"
++#include "asterisk/astobj.h"
+
+-#define DEFAULT_PARK_TIME 45000
+-#define DEFAULT_TRANSFER_DIGIT_TIMEOUT 3000
++#define DEFAULT_PARK_TIME 45000 /*!< Default parking time */
++#define DEFAULT_TRANSFER_DIGIT_TIMEOUT 3000
+ #define DEFAULT_FEATURE_DIGIT_TIMEOUT 500
++#define DEFAULT_PARKINGLOT "default" /*!< Default parking lot */
+ #define DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER 15000
+ #define DEFAULT_ATXFER_DROP_CALL 0
+ #define DEFAULT_ATXFER_LOOP_DELAY 10000
+@@ -69,6 +71,7 @@
+
+ #define AST_MAX_WATCHERS 256
+
++/*! \bug Why isn't these flags documented? */
+ enum {
+ AST_FEATURE_FLAG_NEEDSDTMF = (1 << 0),
+ AST_FEATURE_FLAG_ONPEER = (1 << 1),
+@@ -78,48 +81,49 @@
+ AST_FEATURE_FLAG_BYBOTH = (3 << 3),
+ };
+
+-struct feature_group_exten {
+- AST_LIST_ENTRY(feature_group_exten) entry;
+- char exten[FEATURE_MAX_LEN];
+- struct ast_call_feature *feature;
+-};
+-
+-struct feature_group {
+- AST_LIST_ENTRY(feature_group) entry;
+- char gname[80];
+- AST_LIST_HEAD_NOLOCK(, feature_group_exten) features;
+-};
+-
+-static AST_RWLIST_HEAD_STATIC(feature_groups, feature_group);
+-
+ static char *parkedcall = "ParkedCall";
+
+ static int parkaddhints = 0; /*!< Add parking hints automatically */
+ static int parkedcalltransfers = 0; /*!< Enable DTMF based transfers on bridge when picking up parked calls */
+ static int parkedcallreparking = 0; /*!< Enable DTMF based parking on bridge when picking up parked calls */
+ static int parkingtime = DEFAULT_PARK_TIME; /*!< No more than 45 seconds parked before you do something with them */
+-static char parking_con[AST_MAX_EXTENSION]; /*!< Context for which parking is made accessible */
+-static char parking_con_dial[AST_MAX_EXTENSION]; /*!< Context for dialback for parking (KLUDGE) */
+-static char parking_ext[AST_MAX_EXTENSION]; /*!< Extension you type to park the call */
+ static char pickup_ext[AST_MAX_EXTENSION]; /*!< Call pickup extension */
+ static char parkmohclass[MAX_MUSICCLASS]; /*!< Music class used for parking */
+-static int parking_start; /*!< First available extension for parking */
+-static int parking_stop; /*!< Last available extension for parking */
+
++/* XXX This is used in many modules, so for now it's the same for all parking lots */
++static char parking_ext[AST_MAX_EXTENSION] = "700"; /*!< Extension you type to park the call */
++
++/* Default sounds */
+ static char courtesytone[256]; /*!< Courtesy tone */
+ static int parkedplay = 0; /*!< Who to play the courtesy tone to */
+ static char xfersound[256]; /*!< Call transfer sound */
+ static char xferfailsound[256]; /*!< Call transfer failure sound */
+
+-static int parking_offset;
+-static int parkfindnext;
++/*! \brief Structure for parking lots in a linked list. */
++struct ast_parkinglot {
++ ASTOBJ_COMPONENTS(struct ast_parkinglot); /*!< various object stuff, including ->name */
++ char parking_con[AST_MAX_EXTENSION]; /*!< Context for which parking is made accessible */
++ char parking_con_dial[AST_MAX_EXTENSION]; /*!< Context for dialback for parking (KLUDGE) */
++ int parking_start; /*!< First available extension for parking */
++ int parking_stop; /*!< Last available extension for parking */
++ int parking_offset;
++ int parkfindnext;
++ int parkingtime; /*!< Default parking time */
++ struct parkeduser *occupiedlots;
++};
+
+-static int adsipark;
++struct ast_parkinglot_list {
++ ASTOBJ_CONTAINER_COMPONENTS(struct ast_parkinglot);
++} parkinglots;
+
+-static int transferdigittimeout;
+-static int featuredigittimeout;
++struct ast_parkinglot *default_parkinglot;
+ static int comebacktoorigin = 1;
+
++static int adsipark = 0;
++
++static int transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
++static int featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
++
+ static int atxfernoanswertimeout;
+ static unsigned int atxferdropcall;
+ static unsigned int atxferloopdelay;
+@@ -154,6 +158,7 @@
+ static struct ast_app *monitor_app = NULL;
+ static int monitor_ok = 1;
+
++/*! \brief Structure to handle one parked user */
+ struct parkeduser {
+ struct ast_channel *chan; /*!< Parking channel */
+ struct timeval start; /*!< Time the parking started */
+@@ -167,14 +172,24 @@
+ char peername[1024];
+ unsigned char moh_trys;
+ struct parkeduser *next;
++ struct ast_parkinglot *parkinglot;
+ };
+
+-static struct parkeduser *parkinglot;
+
++/*! Lock for parking */
+ AST_MUTEX_DEFINE_STATIC(parking_lock); /*!< protects all static variables above */
+
+ static pthread_t parking_thread;
+
++/* Forward declarations */
++static struct ast_parkinglot *parkinglot_addref(struct ast_parkinglot *parkinglot);
++static void parkinglot_unref(struct ast_parkinglot *parkinglot);
++static void parkinglot_destroy(struct ast_parkinglot *ruin);
++int manage_parkinglot(struct ast_parkinglot *curlot, fd_set *rfds, fd_set *efds, fd_set *nrfds, fd_set *nefds);
++int ast_park_call_full(struct ast_channel *chan, struct ast_channel *peer, int timeout, int *extout, struct ast_parkinglot *parkinglot);
++struct ast_parkinglot *find_parkinglot(const char *name);
++
++
+ char *ast_parking_ext(void)
+ {
+ return parking_ext;
+@@ -203,6 +218,7 @@
+ chan->priority = pri;
+ }
+
++/*! If GOTO_ON_BLINDXFR is set, transferer in a blind transfer will be sent there. */
+ static void check_goto_on_transfer(struct ast_channel *chan)
+ {
+ struct ast_channel *xferchan;
+@@ -261,6 +277,7 @@
+ ast_cdr_setdestchan(tobj->peer->cdr, tobj->chan->name);
+ }
+
++
+ ast_bridge_call(tobj->peer, tobj->chan, &tobj->bconfig);
+
+ if (tobj->return_to_pbx) {
+@@ -288,6 +305,7 @@
+ return NULL;
+ }
+
++
+ static void ast_bridge_call_thread_launch(void *data)
+ {
+ pthread_t thread;
+@@ -317,6 +335,23 @@
+ return ast_adsi_print(chan, message, justify, 1);
+ }
+
++/*! \brief Find parking lot name from channel */
++static const char *findparkinglotname(struct ast_channel *chan)
++{
++ const char *temp, *parkinglot = NULL;
++
++ /* Check if the channel has a parking lot */
++ if (!ast_strlen_zero(chan->parkinglot))
++ parkinglot = chan->parkinglot;
++
++ /* Channel variables override everything */
++
++ if ((temp = pbx_builtin_getvar_helper(chan, "PARKINGLOT")))
++ return temp;
++
++ return parkinglot;
++}
++
+ /*! \brief Notify metermaids that we've changed an extension */
+ static void notify_metermaids(char *exten, char *context)
+ {
+@@ -353,36 +388,55 @@
+ /*! \brief Park a call
+ \note We put the user in the parking list, then wake up the parking thread to be sure it looks
+ after these channels too */
+-int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeout, int *extout)
++int ast_park_call_full(struct ast_channel *chan, struct ast_channel *peer, int timeout, int *extout, struct ast_parkinglot *parkinglot)
+ {
+ struct parkeduser *pu, *cur;
+ int i, x = -1, parking_range;
+ struct ast_context *con;
++ const char *parkinglotname;
+ const char *parkingexten;
+
++ parkinglotname = findparkinglotname(peer);
++
++ if (parkinglotname) {
++ if (option_debug)
++ ast_log(LOG_DEBUG, "Found chanvar Parkinglot: %s\n", parkinglotname);
++ parkinglot = find_parkinglot(parkinglotname);
++ }
++ if (!parkinglot)
++ parkinglot = default_parkinglot;
++
++ parkinglot_addref(parkinglot);
++ if (option_debug)
++ ast_log(LOG_DEBUG, "Parkinglot: %s\n", parkinglot->name);
++
++
+ /* Allocate memory for parking data */
+- if (!(pu = ast_calloc(1, sizeof(*pu))))
++ if (!(pu = ast_calloc(1, sizeof(*pu)))) {
++ parkinglot_unref(parkinglot);
+ return -1;
++ }
++ ASTOBJ_WRLOCK(parkinglot);
+
+- /* Lock parking lot */
+- ast_mutex_lock(&parking_lock);
+ /* Check for channel variable PARKINGEXTEN */
+ parkingexten = pbx_builtin_getvar_helper(chan, "PARKINGEXTEN");
+ if (!ast_strlen_zero(parkingexten)) {
+- if (ast_exists_extension(NULL, parking_con, parkingexten, 1, NULL)) {
++ if (ast_exists_extension(NULL, parkinglot->parking_con, parkingexten, 1, NULL)) {
+ ast_mutex_unlock(&parking_lock);
++ parkinglot_unref(parkinglot);
++ ASTOBJ_UNLOCK(parkinglot);
+ free(pu);
+- ast_log(LOG_WARNING, "Requested parking extension already exists: %s@%s\n", parkingexten, parking_con);
++ ast_log(LOG_WARNING, "Requested parking extension already exists: %s@%s\n", parkingexten, parkinglot->parking_con);
+ return 0; /* Continue execution if possible */
+ }
+ ast_copy_string(pu->parkingexten, parkingexten, sizeof(pu->parkingexten));
+ x = atoi(parkingexten);
+ } else {
+ /* Select parking space within range */
+- parking_range = parking_stop - parking_start+1;
++ parking_range = parkinglot->parking_stop - parkinglot->parking_start + 1;
+ for (i = 0; i < parking_range; i++) {
+- x = (i + parking_offset) % parking_range + parking_start;
+- cur = parkinglot;
++ x = (i + parkinglot->parking_offset) % parking_range + parkinglot->parking_start;
++ cur = parkinglot->occupiedlots;
+ while(cur) {
+ if (cur->parkingnum == x)
+ break;
+@@ -393,16 +447,17 @@
+ }
+
+ if (!(i < parking_range)) {
+- ast_log(LOG_WARNING, "No more parking spaces\n");
++ ast_log(LOG_WARNING, "No more parking spaces in parking lot \"%s\"\n", parkinglot->name);
+ free(pu);
+ ast_mutex_unlock(&parking_lock);
++ parkinglot_unref(parkinglot);
++ ASTOBJ_UNLOCK(parkinglot);
+ return -1;
+ }
+ /* Set pointer for next parking */
+- if (parkfindnext)
+- parking_offset = x - parking_start + 1;
++ if (parkinglot->parkfindnext)
++ parkinglot->parking_offset = x - parkinglot->parking_start + 1;
+ }
+-
+ chan->appl = "Parked Call";
+ chan->data = NULL;
+
+@@ -417,11 +472,13 @@
+
+ pu->start = ast_tvnow();
+ pu->parkingnum = x;
++ pu->parkinglot = parkinglot;
+ pu->parkingtime = (timeout > 0) ? timeout : parkingtime;
++
+ if (extout)
+ *extout = x;
+
+- if (peer)
++ if (peer) /* Parking channel */
+ ast_copy_string(pu->peername, peer->name, sizeof(pu->peername));
+
+ /* Remember what had been dialed, so that if the parking
+@@ -429,8 +486,9 @@
+ ast_copy_string(pu->context, S_OR(chan->macrocontext, chan->context), sizeof(pu->context));
+ ast_copy_string(pu->exten, S_OR(chan->macroexten, chan->exten), sizeof(pu->exten));
+ pu->priority = chan->macropriority ? chan->macropriority : chan->priority;
+- pu->next = parkinglot;
+- parkinglot = pu;
++ pu->next = parkinglot->occupiedlots;
++ parkinglot->occupiedlots = pu;
++ ASTOBJ_UNLOCK(parkinglot);
+
+ /* If parking a channel directly, don't quiet yet get parking running on it */
+ if (peer == chan)
+@@ -439,18 +497,19 @@
+ /* Wake up the (presumably select()ing) thread */
+ pthread_kill(parking_thread, SIGURG);
+ if (option_verbose > 1)
+- ast_verbose(VERBOSE_PREFIX_2 "Parked %s on %d@%s. Will timeout back to extension [%s] %s, %d in %d seconds\n", pu->chan->name, pu->parkingnum, parking_con, pu->context, pu->exten, pu->priority, (pu->parkingtime/1000));
++ ast_verbose(VERBOSE_PREFIX_2 "Parked %s on %d (lot %s). Will timeout back to extension [%s] %s, %d in %d seconds\n", pu->chan->name, pu->parkingnum, parkinglot->name, pu->context, pu->exten, pu->priority, (pu->parkingtime/1000));
+
+ if (pu->parkingnum != -1)
+ snprintf(pu->parkingexten, sizeof(pu->parkingexten), "%d", x);
+ manager_event(EVENT_FLAG_CALL, "ParkedCall",
+ "Exten: %s\r\n"
+ "Channel: %s\r\n"
++ "Parkinglot: %s\r\n"
+ "From: %s\r\n"
+ "Timeout: %ld\r\n"
+ "CallerIDNum: %s\r\n"
+ "CallerIDName: %s\r\n",
+- pu->parkingexten, pu->chan->name, peer ? peer->name : "",
++ pu->parkingexten, pu->chan->name, pu->parkinglot->name, peer ? peer->name : "",
+ (long)pu->start.tv_sec + (long)(pu->parkingtime/1000) - (long)time(NULL),
+ S_OR(pu->chan->cid.cid_num, "<unknown>"),
+ S_OR(pu->chan->cid.cid_name, "<unknown>")
+@@ -460,15 +519,15 @@
+ adsi_announce_park(peer, pu->parkingexten); /* Only supports parking numbers */
+ ast_adsi_unload_session(peer);
+ }
+-
+- con = ast_context_find(parking_con);
++ con = ast_context_find(parkinglot->parking_con);
+ if (!con)
+- con = ast_context_create(NULL, parking_con, registrar);
++ con = ast_context_create(NULL, parkinglot->parking_con, registrar);
+ if (!con) /* Still no context? Bad */
+- ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
++ ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parkinglot->parking_con);
+ else { /* Add extension to context */
+ if (!ast_add_extension2(con, 1, pu->parkingexten, 1, NULL, NULL, parkedcall, strdup(pu->parkingexten), ast_free, registrar))
+- notify_metermaids(pu->parkingexten, parking_con);
++ notify_metermaids(pu->parkingexten, parkinglot->parking_con);
++
+ }
+ /* Tell the peer channel the number of the parking space */
+ if (peer && pu->parkingnum != -1) /* Only say number if it's a number */
+@@ -484,6 +543,11 @@
+ return 0;
+ }
+
++int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeout, int *extout)
++{
++ return ast_park_call_full(chan, peer, timeout, extout, NULL);
++}
++
+ int ast_masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, int timeout, int *extout)
+ {
+ struct ast_channel *chan;
+@@ -1024,7 +1088,7 @@
+ AST_RWLOCK_DEFINE_STATIC(features_lock);
+
+ static struct ast_call_feature builtin_features[] =
+-{
++ {
+ { AST_FEATURE_REDIRECT, "Blind Transfer", "blindxfer", "#", "#", builtin_blindtransfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
+ { AST_FEATURE_REDIRECT, "Attended Transfer", "atxfer", "", "", builtin_atxfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
+ { AST_FEATURE_AUTOMON, "One Touch Monitor", "automon", "", "", builtin_automonitor, AST_FEATURE_FLAG_NEEDSDTMF, "" },
+@@ -1051,64 +1115,6 @@
+ ast_verbose(VERBOSE_PREFIX_2 "Registered Feature '%s'\n",feature->sname);
+ }
+
+-/*! \brief This function must be called while feature_groups is locked... */
+-static struct feature_group* register_group(const char *fgname)
+-{
+- struct feature_group *fg;
+-
+- if (!fgname) {
+- ast_log(LOG_NOTICE, "You didn't pass a new group name!\n");
+- return NULL;
+- }
+-
+- fg = ast_calloc(1, sizeof(*fg));
+-
+- if (!fg) {
+- ast_log(LOG_ERROR, "Failed to allocate memory for group '%s'\n", fgname);
+- return NULL;
+- }
+-
+- ast_copy_string(fg->gname, fgname, sizeof(fg->gname));
+-
+- AST_LIST_INSERT_HEAD(&feature_groups, fg, entry);
+-
+- if (option_verbose >= 2)
+- ast_verbose(VERBOSE_PREFIX_2 "Registered group '%s'\n", fg->gname);
+-
+- return fg;
+-}
+-
+-/*! \brief This function must be called while feature_groups is locked... */
+-
+-static void register_group_feature(struct feature_group *fg, const char *exten, struct ast_call_feature *feature)
+-{
+- struct feature_group_exten *fge;
+-
+- fge = ast_calloc(1, sizeof(*fge));
+-
+- if (!fge) return;
+-
+- if (!fg) {
+- ast_log(LOG_NOTICE, "You didn't pass a group!\n");
+- return;
+- }
+-
+- if (!feature) {
+- ast_log(LOG_NOTICE, "You didn't pass a feature!\n");
+- return;
+- }
+-
+- ast_copy_string(fge->exten, (ast_strlen_zero(exten) ? feature->exten : exten), sizeof(fge->exten));
+-
+- fge->feature = feature;
+-
+- AST_LIST_INSERT_HEAD(&fg->features, fge, entry);
+-
+- if (option_verbose >= 2)
+- ast_verbose(VERBOSE_PREFIX_2 "Registered feature '%s' for group '%s' at exten '%s'\n",
+- feature->sname, fg->gname, exten);
+-}
+-
+ /*! \brief unregister feature from feature_list */
+ void ast_unregister_feature(struct ast_call_feature *feature)
+ {
+@@ -1145,44 +1151,6 @@
+ return tmp;
+ }
+
+-/*! \brief Remove all groups in the list */
+-static void ast_unregister_groups(void)
+-{
+- struct feature_group *fg;
+- struct feature_group_exten *fge;
+-
+- AST_RWLIST_WRLOCK(&feature_groups);
+- while ((fg = AST_LIST_REMOVE_HEAD(&feature_groups, entry))) {
+- while ((fge = AST_LIST_REMOVE_HEAD(&fg->features, entry)))
+- free(fge);
+- free(fg);
+- }
+- AST_RWLIST_UNLOCK(&feature_groups);
+-}
+-
+-/*! \brief Find a group by name */
+-static struct feature_group *find_group(const char *name) {
+- struct feature_group *fg = NULL;
+-
+- AST_LIST_TRAVERSE(&feature_groups, fg, entry) {
+- if (!strcasecmp(fg->gname, name))
+- break;
+- }
+-
+- return fg;
+-}
+-
+-static struct feature_group_exten *find_group_exten(struct feature_group *fg, const char *code) {
+- struct feature_group_exten *fge = NULL;
+-
+- AST_LIST_TRAVERSE(&fg->features, fge, entry) {
+- if(!strcasecmp(fge->exten, code))
+- break;
+- }
+-
+- return fge;
+-}
+-
+ void ast_rdlock_call_features(void)
+ {
+ ast_rwlock_rdlock(&features_lock);
+@@ -1307,15 +1275,13 @@
+ struct ast_flags features;
+ int res = FEATURE_RETURN_PASSDIGITS;
+ struct ast_call_feature *feature;
+- struct feature_group *fg = NULL;
+- struct feature_group_exten *fge;
+ const char *dynamic_features=pbx_builtin_getvar_helper(chan,"DYNAMIC_FEATURES");
+ char *tmp, *tok;
+
+ if (sense == FEATURE_SENSE_CHAN)
+- ast_copy_flags(&features, &(config->features_caller), AST_FLAGS_ALL);
++ ast_copy_flags(&features, &(config->features_caller), AST_FLAGS_ALL);
+ else
+- ast_copy_flags(&features, &(config->features_callee), AST_FLAGS_ALL);
++ ast_copy_flags(&features, &(config->features_callee), AST_FLAGS_ALL);
+ if (option_debug > 2)
+ ast_log(LOG_DEBUG, "Feature interpret: chan=%s, peer=%s, sense=%d, features=%d\n", chan->name, peer->name, sense, features.flags);
+
+@@ -1341,23 +1307,9 @@
+ tmp = ast_strdupa(dynamic_features);
+
+ while ((tok = strsep(&tmp, "#"))) {
+- AST_RWLIST_RDLOCK(&feature_groups);
+-
+- fg = find_group(tok);
+-
+- if (fg && (fge = find_group_exten(fg, code))) {
+- res = fge->feature->operation(chan, peer, config, code, sense);
+- AST_RWLIST_UNLOCK(&feature_groups);
++ AST_LIST_LOCK(&feature_list);
++ if (!(feature = find_dynamic_feature(tok)))
+ continue;
+- }
+-
+- AST_RWLIST_UNLOCK(&feature_groups);
+- AST_LIST_LOCK(&feature_list);
+-
+- if(!(feature = find_dynamic_feature(tok))) {
+- AST_LIST_UNLOCK(&feature_list);
+- continue;
+- }
+
+ /* Feature is up for consideration */
+ if (!strcmp(feature->exten, code)) {
+@@ -1430,7 +1382,8 @@
+
+ if ((chan = ast_request(type, format, data, &cause))) {
+ ast_set_callerid(chan, cid_num, cid_name, cid_num);
+- ast_channel_inherit_variables(caller, chan);
++ ast_channel_inherit_variables(caller, chan);
++
+ pbx_builtin_setvar_helper(chan, "TRANSFERERNAME", caller->name);
+ if (!chan->cdr) {
+ chan->cdr=ast_cdr_alloc();
+@@ -1874,180 +1827,204 @@
+ manager_event(EVENT_FLAG_CALL, s,
+ "Exten: %s\r\n"
+ "Channel: %s\r\n"
++ "Parkinglot: %s\r\n"
+ "CallerIDNum: %s\r\n"
+ "CallerIDName: %s\r\n\r\n",
+ pu->parkingexten,
+ pu->chan->name,
++ pu->parkinglot->name,
+ S_OR(pu->chan->cid.cid_num, "<unknown>"),
+ S_OR(pu->chan->cid.cid_name, "<unknown>")
+ );
+ }
+
+-/*! \brief Take care of parked calls and unpark them if needed */
+-static void *do_parking_thread(void *ignore)
++/*! \brief Run management on parkinglots, called once per parkinglot */
++int manage_parkinglot(struct ast_parkinglot *curlot, fd_set *rfds, fd_set *efds, fd_set *nrfds, fd_set *nefds)
+ {
+- char parkingslot[AST_MAX_EXTENSION];
+- fd_set rfds, efds; /* results from previous select, to be preserved across loops. */
++ int ms = -1; /* select timeout, uninitialized */
++ int max = -1; /* max fd, none there yet */
++ struct parkeduser *pu, *pl = NULL, *pt = NULL;
++ int res = 0;
+
+- FD_ZERO(&rfds);
+- FD_ZERO(&efds);
++ parkinglot_addref(curlot);
++ pu = curlot->occupiedlots;
++
++ while(pu) {
++ struct ast_channel *chan = pu->chan; /* shorthand */
++ int tms; /* timeout for this item */
++ int x; /* fd index in channel */
++ struct ast_context *con;
++
++ if (pu->notquiteyet) { /* Pretend this one isn't here yet */
++ pl = pu;
++ pu = pu->next;
++ continue;
++ }
++ tms = ast_tvdiff_ms(ast_tvnow(), pu->start);
++ if (tms > pu->parkingtime) {
++ /* Stop music on hold */
++ ast_indicate(pu->chan, AST_CONTROL_UNHOLD);
++ /* Get chan, exten from derived kludge */
++ if (pu->peername[0]) {
++ char *peername = ast_strdupa(pu->peername);
++ char *cp = strrchr(peername, '-');
++
++ if (cp)
++ *cp = 0;
++ con = ast_context_find(pu->parkinglot->parking_con_dial);
++ if (!con)
++ con = ast_context_create(NULL, pu->parkinglot->parking_con_dial, registrar);
++ if (!con)
++ ast_log(LOG_ERROR, "Parking dial context '%s' does not exist and unable to create\n", pu->parkinglot->parking_con_dial);
++ if (con) {
++ char returnexten[AST_MAX_EXTENSION];
+
+- for (;;) {
+- struct parkeduser *pu, *pl, *pt = NULL;
+- int ms = -1; /* select timeout, uninitialized */
+- int max = -1; /* max fd, none there yet */
+- fd_set nrfds, nefds; /* args for the next select */
+- FD_ZERO(&nrfds);
+- FD_ZERO(&nefds);
++ snprintf(returnexten, sizeof(returnexten), "%s||t", peername);
++ ast_add_extension2(con, 1, peername, 1, NULL, NULL, "Dial", strdup(returnexten), ast_free, registrar);
++ }
++ if (comebacktoorigin)
++ set_c_e_p(chan, pu->parkinglot->parking_con_dial, peername, 1);
++ else {
++ char parkingslot[AST_MAX_EXTENSION];
++ ast_log(LOG_WARNING, "now going to parkedcallstimeout,s,1 | ps is %d\n",pu->parkingnum);
++ snprintf(parkingslot, sizeof(parkingslot), "%d", pu->parkingnum);
++ pbx_builtin_setvar_helper(chan, "PARKINGSLOT", parkingslot);
++ set_c_e_p(chan, "parkedcallstimeout", peername, 1);
++ }
+
+- ast_mutex_lock(&parking_lock);
+- pl = NULL;
+- pu = parkinglot;
+- /* navigate the list with prev-cur pointers to support removals */
+- while (pu) {
+- struct ast_channel *chan = pu->chan; /* shorthand */
+- int tms; /* timeout for this item */
+- int x; /* fd index in channel */
+- struct ast_context *con;
++ } else {
++ /* They've been waiting too long, send them back to where they came. Theoretically they
++ should have their original extensions and such, but we copy to be on the safe side */
++ set_c_e_p(chan, pu->context, pu->exten, pu->priority);
+
+- if (pu->notquiteyet) { /* Pretend this one isn't here yet */
+- pl = pu;
+- pu = pu->next;
+- continue;
+ }
+- tms = ast_tvdiff_ms(ast_tvnow(), pu->start);
+- if (tms > pu->parkingtime) {
+- ast_indicate(chan, AST_CONTROL_UNHOLD);
+- /* Get chan, exten from derived kludge */
+- if (pu->peername[0]) {
+- char *peername = ast_strdupa(pu->peername);
+- char *cp = strrchr(peername, '-');
+- if (cp)
+- *cp = 0;
+- con = ast_context_find(parking_con_dial);
+- if (!con) {
+- con = ast_context_create(NULL, parking_con_dial, registrar);
+- if (!con)
+- ast_log(LOG_ERROR, "Parking dial context '%s' does not exist and unable to create\n", parking_con_dial);
+- }
+- if (con) {
+- char returnexten[AST_MAX_EXTENSION];
+- snprintf(returnexten, sizeof(returnexten), "%s||t", peername);
+- ast_add_extension2(con, 1, peername, 1, NULL, NULL, "Dial", strdup(returnexten), ast_free, registrar);
+- }
+- if (comebacktoorigin) {
+- set_c_e_p(chan, parking_con_dial, peername, 1);
+- } else {
+- ast_log(LOG_WARNING, "now going to parkedcallstimeout,s,1 | ps is %d\n",pu->parkingnum);
+- snprintf(parkingslot, sizeof(parkingslot), "%d", pu->parkingnum);
+- pbx_builtin_setvar_helper(pu->chan, "PARKINGSLOT", parkingslot);
+- set_c_e_p(chan, "parkedcallstimeout", peername, 1);
+- }
+- } else {
+- /* They've been waiting too long, send them back to where they came. Theoretically they
+- should have their original extensions and such, but we copy to be on the safe side */
+- set_c_e_p(chan, pu->context, pu->exten, pu->priority);
+- }
+-
+- post_manager_event("ParkedCallTimeOut", pu);
++ post_manager_event("ParkedCallTimeOut", pu);
+
+- if (option_verbose > 1)
+- ast_verbose(VERBOSE_PREFIX_2 "Timeout for %s parked on %d. Returning to %s,%s,%d\n", chan->name, pu->parkingnum, chan->context, chan->exten, chan->priority);
+- /* Start up the PBX, or hang them up */
+- if (ast_pbx_start(chan)) {
+- ast_log(LOG_WARNING, "Unable to restart the PBX for user on '%s', hanging them up...\n", chan->name);
+- ast_hangup(chan);
+- }
+- /* And take them out of the parking lot */
+- if (pl)
+- pl->next = pu->next;
++ if (option_verbose > 1)
++ ast_verbose(VERBOSE_PREFIX_2 "Timeout for %s parked on %d (%s). Returning to %s,%s,%d\n", pu->chan->name, pu->parkingnum, pu->parkinglot->name, pu->chan->context, pu->chan->exten, pu->chan->priority);
++ /* Start up the PBX, or hang them up */
++ if (ast_pbx_start(chan)) {
++ ast_log(LOG_WARNING, "Unable to restart the PBX for user on '%s', hanging them up...\n", pu->chan->name);
++ ast_hangup(chan);
++ }
++ /* And take them out of the parking lot */
++ if (pl)
++ pl->next = pu->next;
++ else
++ curlot->occupiedlots = pu->next;
++ pt = pu;
++ pu = pu->next;
++ con = ast_context_find(pt->parkinglot->parking_con);
++ if (con) {
++ if (ast_context_remove_extension2(con, pt->parkingexten, 1, NULL))
++ ast_log(LOG_WARNING, "Whoa, failed to remove the parking extension!\n");
+ else
+- parkinglot = pu->next;
+- pt = pu;
+- pu = pu->next;
+- con = ast_context_find(parking_con);
+- if (con) {
+- if (ast_context_remove_extension2(con, pt->parkingexten, 1, NULL))
+- ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
+- else
+- notify_metermaids(pt->parkingexten, parking_con);
+- } else
+- ast_log(LOG_WARNING, "Whoa, no parking context?\n");
+- free(pt);
+- } else { /* still within parking time, process descriptors */
+- for (x = 0; x < AST_MAX_FDS; x++) {
+- struct ast_frame *f;
++ notify_metermaids(pt->parkingexten, curlot->parking_con);
++ } else
++ ast_log(LOG_WARNING, "Whoa, no parking context?\n");
++ free(pt);
++ parkinglot_unref(curlot);
++ } else { /* still within parking time, process descriptors */
++ for (x = 0; x < AST_MAX_FDS; x++) {
++ struct ast_frame *f;
[... 884 lines stripped ...]
More information about the asterisk-commits
mailing list