Fix for redirection number. Thanx to Dennis for this bugfix.
[lcr.git] / apppbx.cpp
index 46b1f62..cfaf6cb 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);
                        }
@@ -594,7 +595,7 @@ struct mISDNport *EndpointAppPBX::hunt_port(char *ifname, int *channel)
        if (!interface) {
                if (!there_is_an_external && !(ifname && ifname[0])) {
                        trace_header("CHANNEL SELECTION (no external interface specified)", DIRECTION_NONE);
-                       add_trace("info", NULL, "Add 'external' parameter to interface.conf.");
+                       add_trace("info", NULL, "Add 'extern' parameter to interface.conf.");
                        end_trace();
                }
                return(NULL);
@@ -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,9 +893,10 @@ 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 */
                }
+               e_dialinginfo.sending_complete = 1;
 
                if (e_dialinginfo.itype == INFO_ITYPE_VBOX) {
                        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing directly to VBOX\n", ea_endpoint->ep_serial);
@@ -1156,7 +1158,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;
@@ -1212,6 +1214,7 @@ void EndpointAppPBX::out_setup(void)
                                SCPY(dialinginfo.id, number);
                        dialinginfo.itype = INFO_ITYPE_ISDN;
                        dialinginfo.ntype = e_dialinginfo.ntype;
+                       dialinginfo.sending_complete = e_dialinginfo.sending_complete;
                        portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
                        if (!portlist) {
                                PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
@@ -1245,7 +1248,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 +1427,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 +2240,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 +2257,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 +2272,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 +2286,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 +2294,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 +2308,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 +2326,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 */
@@ -2466,6 +2469,25 @@ void EndpointAppPBX::port_notify(struct port_list *portlist, int message_type, u
 
 }
 
+/* port MESSAGE_PROGRESS */
+void EndpointAppPBX::port_progress(struct port_list *portlist, int message_type, union parameter *param)
+{
+       logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
+
+       struct lcr_msg *message;
+
+       /* signal to call tool */
+       admin_call_response(e_adminid, ADMIN_CALL_PROGRESS, "", 0, param->progressinfo.location, param->progressinfo.progress);
+
+       /* send progress to call if available */
+       if (ea_endpoint->ep_join_id) {
+               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PROGRESS);
+               memcpy(&message->param.progressinfo, &param->progressinfo, sizeof(struct progress_info));
+               message_put(message);
+       }
+
+}
+
 /* port MESSAGE_FACILITY */
 void EndpointAppPBX::port_facility(struct port_list *portlist, int message_type, union parameter *param)
 {
@@ -2662,6 +2684,12 @@ void EndpointAppPBX::ea_message_port(unsigned int port_id, int message_type, uni
                port_notify(portlist, message_type, param);
                break;
 
+               /* PORT sends a PROGRESS message */
+               case MESSAGE_PROGRESS:
+               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received progress.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
+               port_progress(portlist, message_type, param);
+               break;
+
                /* PORT sends a SUSPEND message */
                case MESSAGE_SUSPEND:
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received suspend.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
@@ -2919,7 +2947,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 +2998,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 +3020,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);
@@ -4105,6 +4133,65 @@ void EndpointAppPBX::logmessage(int message_type, union parameter *param, unsign
                end_trace();
                break;
 
+               case MESSAGE_PROGRESS:
+               switch(param->progressinfo.progress) {
+                       case 0x01:
+                       logtext = "Call is not end to end ISDN";
+                       break;
+                       case 0x02:
+                       logtext = "Destination address is non-ISDN";
+                       break;
+                       case 0x03:
+                       logtext = "Origination address is non-ISDN";
+                       break;
+                       case 0x04:
+                       logtext = "Call has returned to the ISDN";
+                       break;
+                       case 0x08:
+                       logtext = "In-band info or pattern available";
+                       break;
+                       default:
+                       SPRINT(buffer, "%d", param->progressinfo.progress);
+                       logtext = buffer;
+
+               }
+               trace_header("PROGRESS", dir);
+               if (dir == DIRECTION_OUT)
+                       add_trace("to", NULL, "CH(%lu)", port_id);
+               if (dir == DIRECTION_IN)
+                       add_trace("from", NULL, "CH(%lu)", port_id);
+               add_trace("indicator", NULL, "%s", logtext);
+               switch(param->progressinfo.location) {
+                       case LOCATION_USER:
+                       add_trace("cause", "location", "0-User");
+                       break;
+                       case LOCATION_PRIVATE_LOCAL:
+                       add_trace("cause", "location", "1-Local-PBX");
+                       break;
+                       case LOCATION_PUBLIC_LOCAL:
+                       add_trace("cause", "location", "2-Local-Exchange");
+                       break;
+                       case LOCATION_TRANSIT:
+                       add_trace("cause", "location", "3-Transit");
+                       break;
+                       case LOCATION_PUBLIC_REMOTE:
+                       add_trace("cause", "location", "4-Remote-Exchange");
+                       break;
+                       case LOCATION_PRIVATE_REMOTE:
+                       add_trace("cause", "location", "5-Remote-PBX");
+                       break;
+                       case LOCATION_INTERNATIONAL:
+                       add_trace("cause", "location", "7-International-Exchange");
+                       break;
+                       case LOCATION_BEYOND:
+                       add_trace("cause", "location", "10-Beyond-Interworking");
+                       break;
+                       default:
+                       add_trace("cause", "location", "%d", param->progressinfo.location);
+               }
+               end_trace();
+               break;
+
                case MESSAGE_INFORMATION:
                trace_header("INFORMATION", dir);
                if (dir == DIRECTION_OUT)