Plane commits (a.k.a. the Delta deltas): 1) Make muted reconnect 2) Add "X" option...
authorMark Spencer <markster@digium.com>
Tue, 3 Aug 2004 06:31:20 +0000 (06:31 +0000)
committerMark Spencer <markster@digium.com>
Tue, 3 Aug 2004 06:31:20 +0000 (06:31 +0000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@3572 65c4cc65-6c06-0410-ace0-fbb531ad65f3

CHANGES
HARDWARE
apps/app_meetme.c
asterisk.c
channels/chan_mgcp.c
muted.c
pbx.c
res/res_features.c
sounds/fpm-sunshine.mp3 [new file with mode: 0755]

diff --git a/CHANGES b/CHANGES
index cf21e72..b4ea88b 100755 (executable)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,10 @@
+ -- Additional CDR backends
+ -- Allow muted to reconnect
+ -- Call parking improvements (including SIP parking support)
+ -- Added licensed hold music from FreePlayMusic
+ -- GR-303 and Zap improvements
+ -- More bug fixes from the bug tracker
+ -- Improved FreeBSD/OpenBSD/MacOS X support
 Asterisk 1.0-RC1
  -- Innumerable bug fixes and features from the bug tracker
  -- Added Open Settlement Protocol (OSP) support
index 990d054..86b28be 100755 (executable)
--- a/HARDWARE
+++ b/HARDWARE
@@ -16,11 +16,11 @@ Zaptel compatible hardware
    * Wildcard X100P - Single FXO interface connects to Loopstart phone 
      line
 
-   * Wildcard T400P - Quad T1 interface connects to four T1/PRI 
+   * Wildcard T400P (obsolete) - Quad T1 interface connects to four T1/PRI 
      interfaces.  Supports RBS and PRI voice and PPP, FR, and HDLC data.
 
-   * Wildcard E400P - Quad E1 interface connects to four E1/PRI (or PRA)
-     interfaces.  Supports PRA/PRI, EuroISDN voice and PPP, FR, HDLC data.
+   * Wildcard E400P (obsolete)- Quad E1 interface connects to four E1/PRI 
+     (or PRA) interfaces.  Supports PRA/PRI, EuroISDN voice and data.
 
    * Wildcard T100P - Single T1 interface connects to a single T1/PRI
      interface.  Supports RBS and PRI voice and PPP, FR, and HDLC data.
index bb7aa8e..6b03b97 100755 (executable)
@@ -59,6 +59,9 @@ static char *descrip =
 "      'm' -- set monitor only mode (Listen only, no talking)\n"
 "      't' -- set talk only mode. (Talk only, no listening)\n"
 "      'p' -- allow user to exit the conference by pressing '#'\n"
+"      'X' -- allow user to exit the conference by entering a valid single\n"
+"             digit extension ${MEETME_EXIT_CONTEXT} or the current context\n"
+"             if that variable is not defined.\n"
 "      'd' -- dynamically add conference\n"
 "      'D' -- dynamically add conference, prompting for a PIN\n"
 "      'e' -- select an empty conference\n"
@@ -148,6 +151,7 @@ static int admin_exec(struct ast_channel *chan, void *data);
 #define CONFFLAG_MOH (1 << 9)          /* Set to have music on hold when user is alone in conference */
 #define CONFFLAG_ADMINEXIT (1 << 10)    /* If set the MeetMe will return if all marked with this flag left */
 #define CONFFLAG_WAITMARKED (1 << 11)          /* If set, the MeetMe will wait until a marked user enters */
+#define CONFFLAG_EXIT_CONTEXT (1 << 12)                /* If set, the MeetMe will wait until a marked user enters */
 
 
 static int careful_write(int fd, unsigned char *data, int len)
@@ -504,6 +508,7 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, int c
        char *agifile;
        char *agifiledefault = "conf-background.agi";
        char meetmesecs[30] = "";
+       char exitcontext[AST_MAX_EXTENSION] = "";
 
        ZT_BUFFERINFO bi;
        char __buf[CONF_SIZE + AST_FRIENDLY_OFFSET];
@@ -560,6 +565,14 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, int c
        user->adminflags = 0;
        ast_mutex_unlock(&conflock);
        origquiet = confflags & CONFFLAG_QUIET;
+       if (confflags & CONFFLAG_EXIT_CONTEXT) {
+               if ((agifile = pbx_builtin_getvar_helper(chan, "MEETME_EXIT_CONTEXT"))) 
+                       strncpy(exitcontext, agifile, sizeof(exitcontext) - 1);
+               else if (!ast_strlen_zero(chan->macrocontext)) 
+                       strncpy(exitcontext, chan->macrocontext, sizeof(exitcontext) - 1);
+               else
+                       strncpy(exitcontext, chan->context, sizeof(exitcontext) - 1);
+       }
        while((confflags & CONFFLAG_WAITMARKED) && (conf->markedusers < 0)) {
                confflags &= ~CONFFLAG_QUIET;
                confflags |= origquiet;
@@ -806,7 +819,18 @@ zapretry:
                                f = ast_read(c);
                                if (!f) 
                                        break;
-                               if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '#') && (confflags & CONFFLAG_POUNDEXIT)) {
+                               if ((f->frametype == AST_FRAME_DTMF) && (confflags & CONFFLAG_EXIT_CONTEXT)) {
+                                       char tmp[2];
+                                       tmp[0] = f->subclass;
+                                       tmp[1] = '\0';
+                                       if (ast_exists_extension(chan, exitcontext, tmp, 1, chan->callerid)) {
+                                               strncpy(chan->context, exitcontext, sizeof(chan->context) - 1);
+                                               strncpy(chan->exten, tmp, sizeof(chan->exten) - 1);
+                                               chan->priority = 0;
+                                               ret = 0;
+                                               break;
+                                       }
+                               } else if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '#') && (confflags & CONFFLAG_POUNDEXIT)) {
                                        ret = 0;
                                        break;
                                } else if (((f->frametype == AST_FRAME_DTMF) && (f->subclass == '*') && (confflags & CONFFLAG_STARMENU)) || ((f->frametype == AST_FRAME_DTMF) && menu_active)) {
@@ -1187,6 +1211,8 @@ static int conf_exec(struct ast_channel *chan, void *data)
                        confflags |= CONFFLAG_MOH;
                if (strchr(inflags, 'x'))
                        confflags |= CONFFLAG_ADMINEXIT;
+               if (strchr(inflags, 'X'))
+                       confflags |= CONFFLAG_EXIT_CONTEXT;
                if (strchr(inflags, 'b'))
                        confflags |= CONFFLAG_AGI;
                if (strchr(inflags, 'w'))
index 575ddbc..62b01c1 100755 (executable)
@@ -689,7 +689,7 @@ static int remoteconsolehandler(char *s)
 {
        int ret = 0;
        /* Called when readline data is available */
-       if (s && !ast_strlen_zero(s))
+       if (s && !ast_all_zeros(s))
                ast_el_add_history(s);
        /* Give the console access to the shell */
        if (s) {
@@ -1341,6 +1341,8 @@ static int ast_el_read_history(char *filename)
                fgets(buf, sizeof(buf), f);
                if (!strcmp(buf, "_HiStOrY_V2_\n"))
                        continue;
+               if (ast_all_zeros(buf))
+                       continue;
                if ((ret = ast_el_add_history(buf)) == -1)
                        break;
        }
index 8adeede..f30e4ab 100755 (executable)
@@ -2808,9 +2808,9 @@ static void handle_hd_hf(struct mgcp_subchannel *sub, char *ev)
             }
         } else {
             if (p->hookstate == MGCP_OFFHOOK) {
-                ast_log(LOG_WARNING, "Off hook, but alreaedy have owner on %s@%s\n", p->name, p->parent->name);
+                ast_log(LOG_WARNING, "Off hook, but already have owner on %s@%s\n", p->name, p->parent->name);
             } else {
-                ast_log(LOG_WARNING, "On hook, but alreaedy have owner on %s@%s\n", p->name, p->parent->name);
+                ast_log(LOG_WARNING, "On hook, but already have owner on %s@%s\n", p->name, p->parent->name);
                 ast_log(LOG_WARNING, "If we're onhook why are we here trying to handle a hd or hf?");
             }
             if (sub->owner->bridge) {
@@ -2921,8 +2921,8 @@ static int handle_request(struct mgcp_subchannel *sub, struct mgcp_request *req,
                 /* Thanks to point on IRC for pointing this out */
                 return -1;
             }
-           /* do not let * confrnce two down channels */  
-           if( sub->owner && sub->owner->_state == AST_STATE_DOWN && !sub->next->owner) return -1;
+                   /* do not let * confrnce two down channels */  
+                   if( sub->owner && sub->owner->_state == AST_STATE_DOWN && !sub->next->owner) return -1;
 
             if (p->callwaiting || p->transfer || p->threewaycalling) {
                 if (option_verbose > 2) {
diff --git a/muted.c b/muted.c
index a039fb4..ac8d5d9 100755 (executable)
--- a/muted.c
+++ b/muted.c
@@ -535,8 +535,16 @@ int main(int argc, char *argv[])
        if (needfork)
                daemon(0,0);
        for(;;) {
-               if (wait_event())
-                       exit(1);
+               if (wait_event()) {
+                       fclose(astf);
+                       while(connect_asterisk()) {
+                               sleep(5);
+                       }
+                       if (login_asterisk()) {
+                               fclose(astf);
+                               exit(1);
+                       }
+               }
        }
        exit(0);
 }
diff --git a/pbx.c b/pbx.c
index 1a18208..c39d7e1 100755 (executable)
--- a/pbx.c
+++ b/pbx.c
@@ -1,4 +1,4 @@
-/*
+ /*
  * Asterisk -- A telephony toolkit for Linux.
  *
  * Core PBX routines.
@@ -2044,7 +2044,7 @@ int ast_context_remove_include2(struct ast_context *con, char *include, char *re
        while (i) {
                /* find our include */
                if (!strcmp(i->name, include) && 
-                       (!strcmp(i->registrar, registrar) || !registrar)) {
+                       (!registrar || !strcmp(i->registrar, registrar))) {
                        /* remove from list */
                        if (pi)
                                pi->next = i->next;
@@ -2116,7 +2116,7 @@ int ast_context_remove_switch2(struct ast_context *con, char *sw, char *data, ch
        while (i) {
                /* find our switch */
                if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 
-                       (!strcmp(i->registrar, registrar) || !registrar)) {
+                       (!registrar || !strcmp(i->registrar, registrar))) {
                        /* remove from list */
                        if (pi)
                                pi->next = i->next;
@@ -2189,7 +2189,7 @@ int ast_context_remove_extension2(struct ast_context *con, char *extension, int
 
                /* look for right extension */
                if (!strcmp(exten->exten, extension) &&
-                       (!strcmp(exten->registrar, registrar) || !registrar)) {
+                       (!registrar || !strcmp(exten->registrar, registrar))) {
                        struct ast_exten *peer;
 
                        /* should we free all peers in this extension? (priority == 0)? */
@@ -2224,7 +2224,7 @@ int ast_context_remove_extension2(struct ast_context *con, char *extension, int
                                while (peer) {
                                        /* is this our extension? */
                                        if (peer->priority == priority &&
-                                               (!strcmp(peer->registrar, registrar) || !registrar)) {
+                                               (!registrar || !strcmp(peer->registrar, registrar) )) {
                                                /* we are first priority extension? */
                                                if (!previous_peer) {
                                                        /* exists previous extension here? */
@@ -3459,7 +3459,7 @@ int ast_context_remove_ignorepat2(struct ast_context *con, char *ignorepat, char
        ip = con->ignorepats;
        while (ip) {
                if (!strcmp(ip->pattern, ignorepat) &&
-                       (registrar == ip->registrar || !registrar)) {
+                       (!registrar || (registrar == ip->registrar))) {
                        if (ipl) {
                                ipl->next = ip->next;
                                free(ip);
index f6b4dfc..b8639f6 100755 (executable)
@@ -62,7 +62,7 @@ static int parking_stop = 750;
 static int transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
 
 /* Registrar for operations */
-static char *registrar = "res_parking";
+static char *registrar = "res_features";
 
 static char *synopsis = "Answer a parked call";
 
@@ -72,6 +72,18 @@ static char *descrip = "ParkedCall(exten):"
 "into the dialplan, although you should include the 'parkedcalls'\n"
 "context.\n";
 
+
+static char *parkcall = "Park";
+
+static char *synopsis2 = "Park yourself";
+
+static char *descrip2 = "Park(exten):"
+"Used to park yourself (typically in combination with a supervised\n"
+"transfer to know the parking space.  This Application is always\n"
+"registered internally and does not need to be explicitly added\n"
+"into the dialplan, although you should include the 'parkedcalls'\n"
+"context.\n";
+
 struct parkeduser {
        struct ast_channel *chan;
        struct timeval start;
@@ -81,6 +93,7 @@ struct parkeduser {
        char exten[AST_MAX_EXTENSION];
        int priority;
        int parkingtime;
+       int notquiteyet;
        struct parkeduser *next;
 };
 
@@ -110,6 +123,8 @@ int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeou
           after these channels too */
        struct parkeduser *pu, *cur;
        int x;
+       char exten[AST_MAX_EXTENSION];
+       struct ast_context *con;
        pu = malloc(sizeof(struct parkeduser));
        if (pu) {
                ast_mutex_lock(&parking_lock);
@@ -129,7 +144,8 @@ int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeou
 
                        pu->chan = chan;
                        /* Start music on hold */
-                       ast_moh_start(pu->chan, NULL);
+                       if (chan != peer)
+                               ast_moh_start(pu->chan, NULL);
                        gettimeofday(&pu->start, NULL);
                        pu->parkingnum = x;
                        if (timeout > 0)
@@ -154,6 +170,9 @@ int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeou
                                pu->priority = chan->priority;
                        pu->next = parkinglot;
                        parkinglot = pu;
+                       /* If parking a channel directly, don't quiet yet get parking running on it */
+                       if (peer == chan)
+                               pu->notquiteyet = 1;
                        ast_mutex_unlock(&parking_lock);
                        /* Wake up the (presumably select()ing) thread */
                        pthread_kill(parking_thread, SIGURG);
@@ -171,8 +190,26 @@ int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeou
                                 ,(pu->chan->callerid ? pu->chan->callerid : "")
                                 );
 
-                       if (peer)
+                       if (peer) {
                                ast_say_digits(peer, pu->parkingnum, "", peer->language);
+                               if (pu->notquiteyet) {
+                                       /* Wake up parking thread if we're really done */
+                                       ast_moh_start(pu->chan, NULL);
+                                       pu->notquiteyet = 0;
+                                       pthread_kill(parking_thread, SIGURG);
+                               }
+                       }
+                       con = ast_context_find(parking_con);
+                       if (!con) {
+                               con = ast_context_create(NULL,parking_con, registrar);
+                               if (!con) {
+                                       ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
+                               }
+                       }
+                       if (con) {
+                               snprintf(exten, sizeof(exten), "%d", x);
+                               ast_add_extension2(con, 1, exten, 1, NULL, parkedcall, strdup(exten), free, registrar);
+                       }
                        return 0;
                } else {
                        ast_log(LOG_WARNING, "No more parking spaces\n");
@@ -441,6 +478,8 @@ static void *do_parking_thread(void *ignore)
        struct parkeduser *pu, *pl, *pt = NULL;
        struct timeval tv;
        struct ast_frame *f;
+       char exten[AST_MAX_EXTENSION];
+       struct ast_context *con;
        int x;
        fd_set rfds, efds;
        fd_set nrfds, nefds;
@@ -456,6 +495,12 @@ static void *do_parking_thread(void *ignore)
                FD_ZERO(&nrfds);
                FD_ZERO(&nefds);
                while(pu) {
+                       if (pu->notquiteyet) {
+                               /* Pretend this one isn't here yet */
+                               pl = pu;
+                               pu = pu->next;
+                               continue;
+                       }
                        tms = (tv.tv_sec - pu->start.tv_sec) * 1000 + (tv.tv_usec - pu->start.tv_usec) / 1000;
                        if (tms > pu->parkingtime) {
                                /* They've been waiting too long, send them back to where they came.  Theoretically they
@@ -477,6 +522,13 @@ static void *do_parking_thread(void *ignore)
                                        parkinglot = pu->next;
                                pt = pu;
                                pu = pu->next;
+                               con = ast_context_find(parking_con);
+                               if (con) {
+                                       snprintf(exten, sizeof(exten), "%d", pt->parkingnum);
+                                       if (ast_context_remove_extension2(con, exten, 1, NULL))
+                                               ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
+                               } else
+                                       ast_log(LOG_WARNING, "Whoa, no parking context?\n");
                                free(pt);
                        } else {
                                for (x=0;x<AST_MAX_FDS;x++) {
@@ -498,6 +550,13 @@ static void *do_parking_thread(void *ignore)
                                                                parkinglot = pu->next;
                                                        pt = pu;
                                                        pu = pu->next;
+                                                       con = ast_context_find(parking_con);
+                                                       if (con) {
+                                                               snprintf(exten, sizeof(exten), "%d", pt->parkingnum);
+                                                               if (ast_context_remove_extension2(con, exten, 1, NULL))
+                                                                       ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
+                                                       } else
+                                                               ast_log(LOG_WARNING, "Whoa, no parking context?\n");
                                                        free(pt);
                                                        break;
                                                } else {
@@ -537,12 +596,37 @@ std:                                      for (x=0;x<AST_MAX_FDS;x++) {
        return NULL;    /* Never reached */
 }
 
+static int park_call_exec(struct ast_channel *chan, void *data)
+{
+       /* Data is unused at the moment but could contain a parking
+          lot context eventually */
+       int res=0;
+       struct localuser *u;
+       LOCAL_USER_ADD(u);
+       /* Setup the exten/priority to be s/1 since we don't know
+          where this call should return */
+       strcpy(chan->exten, "s");
+       chan->priority = 1;
+       if (chan->_state != AST_STATE_UP)
+               res = ast_answer(chan);
+       if (!res)
+               res = ast_safe_sleep(chan, 1000);
+       if (!res)
+               res = ast_park_call(chan, chan, 0, NULL);
+       LOCAL_USER_REMOVE(u);
+       if (!res)
+               res = AST_PBX_KEEPALIVE;
+       return res;
+}
+
 static int park_exec(struct ast_channel *chan, void *data)
 {
        int res=0;
        struct localuser *u;
        struct ast_channel *peer=NULL;
        struct parkeduser *pu, *pl=NULL;
+       char exten[AST_MAX_EXTENSION];
+       struct ast_context *con;
        int park;
        int dres;
        struct ast_bridge_config config;
@@ -569,6 +653,13 @@ static int park_exec(struct ast_channel *chan, void *data)
        ast_mutex_unlock(&parking_lock);
        if (pu) {
                peer = pu->chan;
+               con = ast_context_find(parking_con);
+               if (con) {
+                       snprintf(exten, sizeof(exten), "%d", pu->parkingnum);
+                       if (ast_context_remove_extension2(con, exten, 1, NULL))
+                               ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
+               } else
+                       ast_log(LOG_WARNING, "Whoa, no parking context?\n");
                free(pu);
        }
        /* JK02: it helps to answer the channel if not already up */
@@ -696,10 +787,8 @@ static int manager_parking_status( struct mansession *s, struct message *m )
 int load_module(void)
 {
        int res;
-       int x;
        int start, end;
        struct ast_context *con;
-       char exten[AST_MAX_EXTENSION];
        struct ast_config *cfg;
        struct ast_variable *var;
 
@@ -750,12 +839,11 @@ int load_module(void)
                        return -1;
                }
        }
-       for(x=parking_start; x<=parking_stop;x++) {
-               snprintf(exten, sizeof(exten), "%d", x);
-               ast_add_extension2(con, 1, exten, 1, NULL, parkedcall, strdup(exten), free, registrar);
-       }
+       ast_add_extension2(con, 1, ast_parking_ext(), 1, NULL, parkcall, strdup(""),free, registrar);
        pthread_create(&parking_thread, NULL, do_parking_thread, NULL);
        res = ast_register_application(parkedcall, park_exec, synopsis, descrip);
+       if (!res)
+               res = ast_register_application(parkcall, park_call_exec, synopsis2, descrip2);
        if (!res) {
                ast_manager_register( "ParkedCalls", 0, manager_parking_status, "List parked calls" );
        }
@@ -802,7 +890,7 @@ int unload_module(void)
 
        ast_manager_unregister( "ParkedCalls" );
        ast_cli_unregister(&showparked);
-
+       ast_unregister_application(parkcall);
        return ast_unregister_application(parkedcall);
 }
 
diff --git a/sounds/fpm-sunshine.mp3 b/sounds/fpm-sunshine.mp3
new file mode 100755 (executable)
index 0000000..f572cf3
Binary files /dev/null and b/sounds/fpm-sunshine.mp3 differ