Added "release" action and timeout to "execute" action.
authorAndreas Eversberg <jolly@eversberg.eu>
Sat, 16 Jan 2010 10:42:46 +0000 (11:42 +0100)
committerAndreas Eversberg <jolly@eversberg.eu>
Sat, 16 Jan 2010 10:42:46 +0000 (11:42 +0100)
modified:   README
modified:   action.cpp
modified:   apppbx.cpp
modified:   apppbx.h
modified:   dss1.cpp
modified:   mISDN.cpp
modified:   message.h
modified:   route.c
modified:   route.h
modified:   socket_server.c

README
action.cpp
apppbx.cpp
apppbx.h
dss1.cpp
mISDN.cpp
message.h
route.c
route.h
socket_server.c

diff --git a/README b/README
index 2515150..bc747c2 100644 (file)
--- a/README
+++ b/README
@@ -534,6 +534,7 @@ Changes after Version 1.7
 - Added new option to interface.conf: "nonotify" to disable notify messages.
 - Replaced polling main loop by event driven "select()" loop.
 - Also replaced polling main loop by event driven "select()" loop on chan_lcr.
+- Added "release" action and timeout to "execute" action.
 
 
 
index bf7c23d..aa83304 100644 (file)
@@ -135,7 +135,7 @@ void EndpointAppPBX::action_dialing_internal(void)
                trace_header("ACTION extension (extension doesn't exist)", DIRECTION_NONE);
                add_trace("extension", NULL, dialinginfo.id);
                end_trace();
-               release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0, 0);
+               release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0, 0, 0);
                new_state(EPOINT_STATE_OUT_DISCONNECT);
                message_disconnect_port(portlist, CAUSE_UNALLOCATED, LOCATION_PRIVATE_LOCAL, "");
                set_tone(portlist, "cause_86");
@@ -147,7 +147,7 @@ void EndpointAppPBX::action_dialing_internal(void)
                add_trace("extension", NULL, dialinginfo.id);
                end_trace();
                new_state(EPOINT_STATE_OUT_DISCONNECT);
-               release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0, 0);
+               release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0, 0, 0);
                message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
                set_tone(portlist, "cause_81");
                return;
@@ -273,7 +273,7 @@ void EndpointAppPBX::action_dialing_external(void)
        if (e_ext.rights < 2) {
                trace_header("ACTION extern (calling denied)", DIRECTION_NONE);
                end_trace();
-               release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_REJECTED, 0, 0);
+               release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_REJECTED, 0, 0, 0);
                set_tone(portlist, "cause_82");
                denied:
                message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
@@ -288,7 +288,7 @@ void EndpointAppPBX::action_dialing_external(void)
                if (e_ext.rights < 3) {
                        trace_header("ACTION extern (national calls denied)", DIRECTION_NONE);
                        end_trace();
-                       release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_REJECTED, 0, 0);
+                       release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_REJECTED, 0, 0, 0);
                        set_tone(portlist, "cause_83");
                        goto denied;
                }
@@ -300,7 +300,7 @@ void EndpointAppPBX::action_dialing_external(void)
                if (e_ext.rights < 4) {
                        trace_header("ACTION extern (international calls denied)", DIRECTION_NONE);
                        end_trace();
-                       release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_REJECTED, 0, 0);
+                       release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_REJECTED, 0, 0, 0);
                        set_tone(portlist, "cause_84");
                        goto denied;
                }
@@ -1781,6 +1781,48 @@ void EndpointAppPBX::action_dialing_disconnect(void)
 
 
 /*
+ * process dialing release
+ */
+void EndpointAppPBX::action_dialing_release(void)
+{
+       struct route_param *rparam;
+       int cause = CAUSE_NORMAL; /* normal call clearing */
+       int location = LOCATION_PRIVATE_LOCAL;
+       char cause_string[256] = "", display[84] = "";
+
+       /* check cause parameter */
+       if ((rparam = routeparam(e_action, PARAM_CAUSE))) {
+               cause = rparam->integer_value;
+               PDEBUG(DEBUG_EPOINT, "EPOINT(%d): 'cause' is given: %d\n", ea_endpoint->ep_serial, cause);
+       }
+       if ((rparam = routeparam(e_action, PARAM_LOCATION))) {
+               location = rparam->integer_value;
+               PDEBUG(DEBUG_EPOINT, "EPOINT(%d): 'location' is given: %d\n", ea_endpoint->ep_serial, location);
+       }
+
+
+       /* use cause as sample, if not given later */
+       SPRINT(cause_string, "cause_%02x", cause);
+
+       /* check display */
+       if ((rparam = routeparam(e_action, PARAM_DISPLAY))) {
+               SCPY(display, rparam->string_value);
+               PDEBUG(DEBUG_EPOINT, "EPOINT(%d): 'display' is given: %s\n", ea_endpoint->ep_serial, display);
+       }
+
+       /* disconnect only if connect parameter is not given */
+       trace_header("ACTION release", DIRECTION_NONE);
+       add_trace("cause", "value", "%d", cause);
+       add_trace("cause", "location", "%d", location);
+       if (display[0])
+               add_trace("display", NULL, "%s", display);
+       end_trace();
+       e_action = NULL;
+       release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, location, cause, 1);
+       return;
+}
+
+/*
  * process dialing help
  */
 void EndpointAppPBX::action_dialing_help(void)
@@ -2148,10 +2190,10 @@ void EndpointAppPBX::process_dialing(int timeout)
                if (e_action->index == ACTION_DISCONNECT
                 || e_state == EPOINT_STATE_OUT_DISCONNECT) {
                        /* release after disconnect */
-                       release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
+                       release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
                        goto end;
                }
-               release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0, 0);
+               release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0, 0, 0);
                e_action = e_action->next;
                if (!e_action) {
                        /* nothing more, so we release */
index 46b1f62..f630dbf 100644 (file)
@@ -201,7 +201,7 @@ void EndpointAppPBX::new_state(int state)
 
 /* release join and port (as specified)
  */
-void EndpointAppPBX::release(int release, int joinlocation, int joincause, int portlocation, int portcause)
+void EndpointAppPBX::release(int release, int joinlocation, int joincause, int portlocation, int portcause, int force)
 {
        struct port_list *portlist;
        struct lcr_msg *message;
@@ -238,6 +238,7 @@ void EndpointAppPBX::release(int release, int joinlocation, int joincause, int p
                                message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
                                message->param.disconnectinfo.cause = portcause;
                                message->param.disconnectinfo.location = portlocation;
+                               message->param.disconnectinfo.force = force; // set, if port should release imediately
                                message_put(message);
                                logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
                        }
@@ -879,7 +880,7 @@ void EndpointAppPBX::out_setup(void)
                        }
                        if (atemp) {
                                PERROR("EPOINT(%d) noknocking and currently a call\n", ea_endpoint->ep_serial);
-                               release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_BUSY, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYSPE_ join, port */
+                               release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_BUSY, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYSPE_ join, port */
                                return; /* must exit here */
                        }
                }
@@ -892,7 +893,7 @@ void EndpointAppPBX::out_setup(void)
 //             if (!read_extension(&e_ext, exten))
                if (!read_extension(&e_ext, e_dialinginfo.id)) {
                        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) extension %s not configured\n", ea_endpoint->ep_serial, e_dialinginfo.id);
-                       release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_OUTOFORDER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
+                       release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_OUTOFORDER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
                        return; /* must exit here */
                }
 
@@ -1156,7 +1157,7 @@ void EndpointAppPBX::out_setup(void)
                        end_trace();
                        if (!ea_endpoint->ep_join_id)
                                break;
-                       release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
+                       release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
                        return; /* must exit here */
                }
                break;
@@ -1245,7 +1246,7 @@ void EndpointAppPBX::out_setup(void)
                        end_trace();
                        if (!ea_endpoint->ep_join_id)
                                break;
-                       release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOCHANNEL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
+                       release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOCHANNEL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
                        return; /* must exit here */
                }
                break;
@@ -1424,7 +1425,7 @@ void EndpointAppPBX::hookflash(void)
                port->set_echotest(0);
        }
        if (ea_endpoint->ep_join_id) {
-               release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
+               release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
        }
        e_ruleset = ruleset_main;
        if (e_ruleset)
@@ -2237,7 +2238,7 @@ void EndpointAppPBX::port_disconnect_release(struct port_list *portlist, int mes
        }
        if (message_type == MESSAGE_RELEASE)
                ea_endpoint->free_portlist(portlist);
-       release(RELEASE_ALL, location, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, callcause, portcause */
+       release(RELEASE_ALL, location, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, callcause, portcause */
        return; /* must exit here */
 }
 
@@ -2254,7 +2255,7 @@ void EndpointAppPBX::port_timeout(struct port_list *portlist, int message_type,
                add_trace("state", NULL, "outgoing setup/dialing");
                end_trace();
                /* no user responding */
-               release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
+               release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
                return; /* must exit here */
 
                case PORT_STATE_IN_SETUP:
@@ -2269,7 +2270,7 @@ void EndpointAppPBX::port_timeout(struct port_list *portlist, int message_type,
                end_trace();
                param->disconnectinfo.cause = CAUSE_NOUSER; /* no user responding */
                param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
-               release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
+               release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
                return; /* must exit here */
 
                case PORT_STATE_IN_PROCEEDING:
@@ -2283,7 +2284,7 @@ void EndpointAppPBX::port_timeout(struct port_list *portlist, int message_type,
                end_trace();
                param->disconnectinfo.cause = CAUSE_NOANSWER; /* no answer */
                param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
-               release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOANSWER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
+               release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOANSWER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
                return; /* must exit here */
 
                case PORT_STATE_CONNECT:
@@ -2291,7 +2292,7 @@ void EndpointAppPBX::port_timeout(struct port_list *portlist, int message_type,
                end_trace();
                param->disconnectinfo.cause = CAUSE_NORMAL; /* normal */
                param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
-               release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
+               release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
                return; /* must exit here */
 
                case PORT_STATE_IN_ALERTING:
@@ -2305,7 +2306,7 @@ void EndpointAppPBX::port_timeout(struct port_list *portlist, int message_type,
                add_trace("state", NULL, "disconnect");
                end_trace();
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) in this special case, we release due to disconnect timeout.\n", ea_endpoint->ep_serial);
-               release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
+               release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
                return; /* must exit here */
 
                default:
@@ -2323,7 +2324,7 @@ void EndpointAppPBX::port_timeout(struct port_list *portlist, int message_type,
                message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
                portlist = portlist->next;
        }
-       release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
+       release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
 }
 
 /* port MESSAGE_NOTIFY */
@@ -2919,7 +2920,7 @@ void EndpointAppPBX::join_disconnect_release(int message_type, union parameter *
 
        /* we are powerdialing, if e_powerdial_on is set and limit is not exceeded if given */
        if (e_powerdial_on && ((e_powercount+1)<e_powerlimit || e_powerlimit<1)) {
-               release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
+               release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL,0 ); /* RELEASE_TYPE, join, port */
 
                /* set time for power dialing */
                schedule_timer(&e_powerdial_timeout, (int)e_powerdelay, 0); /* set redial in the future */
@@ -2970,7 +2971,7 @@ void EndpointAppPBX::join_disconnect_release(int message_type, union parameter *
          && e_state!=EPOINT_STATE_IN_ALERTING)
         || !ea_endpoint->ep_portlist) { /* or no port */
                process_hangup(param->disconnectinfo.cause, param->disconnectinfo.location);
-               release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, param->disconnectinfo.cause); /* RELEASE_TYPE, join, port */
+               release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, param->disconnectinfo.cause, 0); /* RELEASE_TYPE, join, port */
                return; /* must exit here */
        }
        /* save cause */
@@ -2992,7 +2993,7 @@ void EndpointAppPBX::join_disconnect_release(int message_type, union parameter *
         || !e_join_pattern) { /* no patterns */
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have own cause or we have no patterns. (own_cause=%d pattern=%d)\n", ea_endpoint->ep_serial, e_ext.own_cause, e_join_pattern);
                if (message_type != MESSAGE_RELEASE)
-                       release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
+                       release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
                e_join_pattern = 0;
        } else { /* else we enable audio */
                message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
index b10a119..8d2cb07 100644 (file)
--- a/apppbx.h
+++ b/apppbx.h
@@ -224,7 +224,7 @@ class EndpointAppPBX : public EndpointApp
 
        /* epoint */
        void new_state(int state);
-       void release(int release, int joinlocation, int joincause, int portlocation, int portcause);
+       void release(int release, int joinlocation, int joincause, int portlocation, int portcause, int force);
        void notify_active(void);
        void keypad_function(char digit);
        void set_tone(struct port_list *portlist, const char *tone);
@@ -288,6 +288,7 @@ class EndpointAppPBX : public EndpointApp
        void action_dialing_goto(void);
        void action_dialing_menu(void);
        void action_dialing_disconnect(void);
+       void action_dialing_release(void);
        void action_dialing_help(void);
        void action_dialing_deflect(void);
        void action_dialing_setforward(void);
index 4a96e28..3bcf410 100644 (file)
--- a/dss1.cpp
+++ b/dss1.cpp
@@ -2607,45 +2607,46 @@ void Pdss1::message_release(unsigned int epoint_id, int message_id, union parame
        char *p = NULL;
 
        /*
-        * we may only release during incoming disconnect state.
-        * this means that the endpoint doesnt require audio anymore
+        * if we are on incoming call setup, we may reject by sending a release_complete
+        * also on outgoing call setup, we send a release complete, BUT this is not conform. (i don't know any other way)
         */
-       if (p_state == PORT_STATE_IN_DISCONNECT
-        || p_state == PORT_STATE_OUT_DISCONNECT) {
-               /* sending release */
+       if (p_state==PORT_STATE_IN_SETUP
+        || p_state==PORT_STATE_OUT_SETUP) {
+//#warning remove me
+//PDEBUG(DEBUG_LOG, "JOLLY sending release complete %d\n", p_serial);
+               /* sending release complete */
                l3m = create_l3msg();
                l1l2l3_trace_header(p_m_mISDNport, this, L3_RELEASE_REQ, DIRECTION_OUT);
                /* send cause */
                enc_ie_cause(l3m, (p_m_mISDNport->locally && param->disconnectinfo.location==LOCATION_PRIVATE_LOCAL)?LOCATION_PRIVATE_LOCAL:param->disconnectinfo.location, param->disconnectinfo.cause);
                end_trace();
-               p_m_mISDNport->ml3->to_layer3(p_m_mISDNport->ml3, MT_RELEASE, p_m_d_l3id, l3m);
+               p_m_mISDNport->ml3->to_layer3(p_m_mISDNport->ml3, MT_RELEASE_COMPLETE, p_m_d_l3id, l3m);
                new_state(PORT_STATE_RELEASE);
                /* remove epoint */
                free_epointid(epoint_id);
                // wait for callref to be released
                return;
-
        }
        /*
-        * if we are on incoming call setup, we may reject by sending a release_complete
-        * also on outgoing call setup, we send a release complete, BUT this is not conform. (i don't know any other way)
+        * we may only release during incoming disconnect state.
+        * this means that the endpoint doesnt require audio anymore
         */
-       if (p_state==PORT_STATE_IN_SETUP
-        || p_state==PORT_STATE_OUT_SETUP) {
-//#warning remove me
-//PDEBUG(DEBUG_LOG, "JOLLY sending release complete %d\n", p_serial);
-               /* sending release complete */
+       if (p_state == PORT_STATE_IN_DISCONNECT
+        || p_state == PORT_STATE_OUT_DISCONNECT
+        || param->disconnectinfo.force) {
+               /* sending release */
                l3m = create_l3msg();
                l1l2l3_trace_header(p_m_mISDNport, this, L3_RELEASE_REQ, DIRECTION_OUT);
                /* send cause */
                enc_ie_cause(l3m, (p_m_mISDNport->locally && param->disconnectinfo.location==LOCATION_PRIVATE_LOCAL)?LOCATION_PRIVATE_LOCAL:param->disconnectinfo.location, param->disconnectinfo.cause);
                end_trace();
-               p_m_mISDNport->ml3->to_layer3(p_m_mISDNport->ml3, MT_RELEASE_COMPLETE, p_m_d_l3id, l3m);
+               p_m_mISDNport->ml3->to_layer3(p_m_mISDNport->ml3, MT_RELEASE, p_m_d_l3id, l3m);
                new_state(PORT_STATE_RELEASE);
                /* remove epoint */
                free_epointid(epoint_id);
                // wait for callref to be released
                return;
+
        }
 
 #if 0
index 3e7751e..035b78b 100644 (file)
--- a/mISDN.cpp
+++ b/mISDN.cpp
@@ -1834,8 +1834,11 @@ static int mISDN_upqueue(struct lcr_fd *fd, unsigned int what, void *instance, i
        char byte;
 
        /* unset global semaphore */
-       read(fd->fd, &byte, 1);
        upqueue_avail = 0;
+       // with a very small incident, upqueue_avail may be set by mISDN thread and
+       // another byte may be sent to the pipe, which causes a call to this function
+       // again with nothing in the upqueue. this is no problem.
+       read(fd->fd, &byte, 1);
 
        /* process all ports */
        mISDNport = mISDNport_first;
@@ -2060,6 +2063,9 @@ int do_layer3(struct mlayer3 *ml3, unsigned int cmd, unsigned int pid, struct l3
        l3m->pid = pid;
        mqueue_tail(&mISDNport->upqueue, mb);
        if (!upqueue_avail) {
+               // multiple threads may cause multiple calls of this section, but this
+               // results only in multiple processing of the upqueue read.
+               // this is no problem.
                upqueue_avail = 1;
                char byte = 0;
                write(upqueue_pipe[1], &byte, 1);
index a7f15b7..3c775cc 100644 (file)
--- a/message.h
+++ b/message.h
@@ -199,6 +199,7 @@ struct disconnect_info {
        int cause;                      /* reason for disconnect */
        int location;                   /* disconnect location */
        char display[84];               /* optional display information */
+       int force;                      /* special flag to release imediately */
 };
 
 /* call-info structure REDIR */
diff --git a/route.c b/route.c
index a448f39..959b584 100644 (file)
--- a/route.c
+++ b/route.c
@@ -342,6 +342,10 @@ struct action_defs action_defs[] = {
          "disconnect", NULL, &EndpointAppPBX::action_dialing_disconnect, NULL,
          PARAM_CONNECT | PARAM_CAUSE | PARAM_LOCATION | PARAM_SAMPLE | PARAM_DISPLAY,
          "Caller gets disconnected optionally with given cause and given sample and given display text."},
+       { ACTION_RELEASE,
+         "release",    NULL, &EndpointAppPBX::action_dialing_release, NULL,
+         PARAM_CONNECT | PARAM_CAUSE | PARAM_LOCATION | PARAM_DISPLAY,
+         "Same as 'disconnect', but using RELEASE message on ISDN."},
        { ACTION_DEFLECT,
          "deflect",    NULL, &EndpointAppPBX::action_dialing_deflect, NULL,
          PARAM_DEST,
@@ -354,7 +358,7 @@ struct action_defs action_defs[] = {
 //       "The call forward is set within the telephone network of the external line."},
        { ACTION_EXECUTE,
          "execute",    &EndpointAppPBX::action_init_execute, NULL, &EndpointAppPBX::action_hangup_execute,
-         PARAM_CONNECT | PARAM_EXECUTE | PARAM_PARAM | PARAM_ON,
+         PARAM_CONNECT | PARAM_EXECUTE | PARAM_PARAM | PARAM_ON | PARAM_TIMEOUT,
          "Executes the given script file. The file must terminate quickly, because it will halt the PBX."},
        { ACTION_FILE,
          "file",       NULL, NULL, &EndpointAppPBX::action_hangup_file,
diff --git a/route.h b/route.h
index 3530ef4..dca5a4e 100644 (file)
--- a/route.h
+++ b/route.h
@@ -174,15 +174,16 @@ enum { /* defines when a statement should be executed */
 #define        ACTION_GOTO             20
 #define        ACTION_MENU             21
 #define        ACTION_DISCONNECT       22
-#define ACTION_DEFLECT         23
-#define ACTION_SETFORWARD      24
-#define ACTION_EXECUTE         25
-#define ACTION_FILE            26
-#define ACTION_PICK            27
-#define        ACTION_PASSWORD         28
-#define        ACTION_PASSWORD_WRITE   29
-#define        ACTION_NOTHING          30
-#define        ACTION_EFI              31
+#define        ACTION_RELEASE          23
+#define ACTION_DEFLECT         24
+#define ACTION_SETFORWARD      25
+#define ACTION_EXECUTE         26
+#define ACTION_FILE            27
+#define ACTION_PICK            28
+#define        ACTION_PASSWORD         29
+#define        ACTION_PASSWORD_WRITE   30
+#define        ACTION_NOTHING          31
+#define        ACTION_EFI              32
 
 struct route_cond { /* an item */
        struct route_cond       *next;                  /* next entry */
index b67b91f..3083085 100644 (file)
@@ -278,7 +278,7 @@ int admin_route(struct admin_queue **responsep)
                        release:
                        unsched_timer(&apppbx->e_callback_timeout);
                        apppbx->e_action = NULL;
-                       apppbx->release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
+                       apppbx->release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
                        start_trace(-1,
                                NULL,
                                numberrize_callerinfo(apppbx->e_callerinfo.id, apppbx->e_callerinfo.ntype, options.national, options.international),
@@ -488,7 +488,7 @@ int admin_release(struct admin_queue **responsep, char *message)
        }
 
        unsched_timer(&apppbx->e_callback_timeout);
-       apppbx->release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
+       apppbx->release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
 
        out:
        /* attach to response chain */
@@ -1123,7 +1123,7 @@ int admin_handle_con(struct lcr_fd *fd, unsigned int what, void *instance, int i
                                epoint = find_epoint_id(admin->epointid);
                                if (epoint) {
                                        ((class DEFAULT_ENDPOINT_APP *)epoint->ep_app)->
-                                               release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
+                                               release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
                                }
                        }