Add ECT (Call Forwarding) facility message handling
authorAndreas Eversberg <jolly@eversberg.eu>
Tue, 17 Sep 2013 10:48:23 +0000 (12:48 +0200)
committerAndreas Eversberg <jolly@eversberg.eu>
Tue, 15 Dec 2015 19:53:17 +0000 (20:53 +0100)
This allows to connect together two call via ISDN phone's menu.

action.cpp
action_vbox.cpp
apppbx.cpp
apppbx.h
dss1.cpp
dss1.h
message.h

index 5b332c9..b42e301 100644 (file)
@@ -112,7 +112,7 @@ void EndpointAppPBX::action_dialing_internal(void)
                end_trace();
                release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0, 0, 0);
                new_state(EPOINT_STATE_OUT_DISCONNECT);
                end_trace();
                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, "");
+               message_disconnect_port(portlist, CAUSE_UNALLOCATED, LOCATION_PRIVATE_LOCAL, "", NULL);
                set_tone(portlist, "cause_86");
                return;
        }
                set_tone(portlist, "cause_86");
                return;
        }
@@ -123,7 +123,7 @@ void EndpointAppPBX::action_dialing_internal(void)
                end_trace();
                new_state(EPOINT_STATE_OUT_DISCONNECT);
                release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0, 0, 0);
                end_trace();
                new_state(EPOINT_STATE_OUT_DISCONNECT);
                release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0, 0, 0);
-               message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
+               message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "", NULL);
                set_tone(portlist, "cause_81");
                return;
        }
                set_tone(portlist, "cause_81");
                return;
        }
@@ -257,7 +257,7 @@ void EndpointAppPBX::action_dialing_external(void)
                release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_REJECTED, 0, 0, 0);
                set_tone(portlist, "cause_82");
                denied:
                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, "");
+               message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "", NULL);
                new_state(EPOINT_STATE_OUT_DISCONNECT);
                return;
        }
                new_state(EPOINT_STATE_OUT_DISCONNECT);
                return;
        }
@@ -324,7 +324,7 @@ void EndpointAppPBX::action_dialing_vbox_record(void)
                end_trace();
 
                new_state(EPOINT_STATE_OUT_DISCONNECT);
                end_trace();
 
                new_state(EPOINT_STATE_OUT_DISCONNECT);
-               message_disconnect_port(portlist, CAUSE_SERVICEUNAVAIL, LOCATION_PRIVATE_LOCAL, "");
+               message_disconnect_port(portlist, CAUSE_SERVICEUNAVAIL, LOCATION_PRIVATE_LOCAL, "", NULL);
                set_tone(portlist, "cause_3f");
                return;
        }
                set_tone(portlist, "cause_3f");
                return;
        }
@@ -335,7 +335,7 @@ void EndpointAppPBX::action_dialing_vbox_record(void)
                add_trace("extension", NULL, "%s", rparam->string_value);
                end_trace();
                new_state(EPOINT_STATE_OUT_DISCONNECT);
                add_trace("extension", NULL, "%s", rparam->string_value);
                end_trace();
                new_state(EPOINT_STATE_OUT_DISCONNECT);
-               message_disconnect_port(portlist, CAUSE_UNALLOCATED, LOCATION_PRIVATE_LOCAL, "");
+               message_disconnect_port(portlist, CAUSE_UNALLOCATED, LOCATION_PRIVATE_LOCAL, "", NULL);
                set_tone(portlist, "cause_86");
                return;
        }
                set_tone(portlist, "cause_86");
                return;
        }
@@ -345,7 +345,7 @@ void EndpointAppPBX::action_dialing_vbox_record(void)
                trace_header("ACTION vbox-record (internal calls are denied)", DIRECTION_NONE);
                end_trace();
                new_state(EPOINT_STATE_OUT_DISCONNECT);
                trace_header("ACTION vbox-record (internal calls are denied)", DIRECTION_NONE);
                end_trace();
                new_state(EPOINT_STATE_OUT_DISCONNECT);
-               message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
+               message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "", NULL);
                set_tone(portlist, "cause_81");
                return;
        }
                set_tone(portlist, "cause_81");
                return;
        }
@@ -402,7 +402,7 @@ void EndpointAppPBX::action_init_partyline(void)
                end_trace();
                noroom:
                new_state(EPOINT_STATE_OUT_DISCONNECT);
                end_trace();
                noroom:
                new_state(EPOINT_STATE_OUT_DISCONNECT);
-               message_disconnect_port(portlist, CAUSE_SERVICEUNAVAIL, LOCATION_PRIVATE_LOCAL, "");
+               message_disconnect_port(portlist, CAUSE_SERVICEUNAVAIL, LOCATION_PRIVATE_LOCAL, "", NULL);
                set_tone(portlist, "cause_3f");
                return;
        }
                set_tone(portlist, "cause_3f");
                return;
        }
@@ -500,7 +500,7 @@ void EndpointAppPBX::action_dialing_login(void)
                        end_trace();
                        /* extension doesn't exist */
                        new_state(EPOINT_STATE_OUT_DISCONNECT);
                        end_trace();
                        /* extension doesn't exist */
                        new_state(EPOINT_STATE_OUT_DISCONNECT);
-                       message_disconnect_port(portlist, CAUSE_UNALLOCATED, LOCATION_PRIVATE_LOCAL, "");
+                       message_disconnect_port(portlist, CAUSE_UNALLOCATED, LOCATION_PRIVATE_LOCAL, "", NULL);
                        set_tone(portlist, "cause_86");
                        return;
                }
                        set_tone(portlist, "cause_86");
                        return;
                }
@@ -591,7 +591,7 @@ void EndpointAppPBX::action_init_change_callerid(void)
                /* service not available */
                trace_header("ACTION change-callerid (denied for this caller)", DIRECTION_NONE);
                end_trace();
                /* service not available */
                trace_header("ACTION change-callerid (denied for this caller)", DIRECTION_NONE);
                end_trace();
-               message_disconnect_port(portlist, CAUSE_SERVICEUNAVAIL, LOCATION_PRIVATE_LOCAL, "");
+               message_disconnect_port(portlist, CAUSE_SERVICEUNAVAIL, LOCATION_PRIVATE_LOCAL, "", NULL);
                new_state(EPOINT_STATE_OUT_DISCONNECT);
                set_tone(portlist,"cause_87");
                return;
                new_state(EPOINT_STATE_OUT_DISCONNECT);
                set_tone(portlist,"cause_87");
                return;
@@ -681,7 +681,7 @@ void EndpointAppPBX::_action_callerid_calleridnext(int next)
        add_trace("new", "caller id", "%s", numberrize_callerinfo(new_id, new_type, options.national, options.international));
        add_trace("new", "present", "%s", (new_present==INFO_PRESENT_RESTRICTED)?"restricted":"allowed");
        end_trace();
        add_trace("new", "caller id", "%s", numberrize_callerinfo(new_id, new_type, options.national, options.international));
        add_trace("new", "present", "%s", (new_present==INFO_PRESENT_RESTRICTED)?"restricted":"allowed");
        end_trace();
-       message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
+       message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "", NULL);
        new_state(EPOINT_STATE_OUT_DISCONNECT);
        set_tone(portlist,"activated");
 }
        new_state(EPOINT_STATE_OUT_DISCONNECT);
        set_tone(portlist,"activated");
 }
@@ -712,7 +712,7 @@ void EndpointAppPBX::action_init_change_forward(void)
                trace_header("ACTION change-forward (denied for this caller)", DIRECTION_NONE);
                end_trace();
                /* service not available */             
                trace_header("ACTION change-forward (denied for this caller)", DIRECTION_NONE);
                end_trace();
                /* service not available */             
-               message_disconnect_port(portlist, CAUSE_SERVICEUNAVAIL, LOCATION_PRIVATE_LOCAL, "");
+               message_disconnect_port(portlist, CAUSE_SERVICEUNAVAIL, LOCATION_PRIVATE_LOCAL, "", NULL);
                new_state(EPOINT_STATE_OUT_DISCONNECT);
                set_tone(portlist,"cause_87");
                return;
                new_state(EPOINT_STATE_OUT_DISCONNECT);
                set_tone(portlist,"cause_87");
                return;
@@ -776,7 +776,7 @@ void EndpointAppPBX::action_dialing_forward(void)
                write_extension(&e_ext, e_ext.number);
        }
        /* function (de)activated */
                write_extension(&e_ext, e_ext.number);
        }
        /* function (de)activated */
-       message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
+       message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "", NULL);
        new_state(EPOINT_STATE_OUT_DISCONNECT);
        if (dest[0])
                set_tone(portlist,"activated");
        new_state(EPOINT_STATE_OUT_DISCONNECT);
        if (dest[0])
                set_tone(portlist,"activated");
@@ -796,7 +796,7 @@ void EndpointAppPBX::action_init_redial_reply(void)
                trace_header("ACTION redial/reply (no last number stored)", DIRECTION_NONE);
                end_trace();
                new_state(EPOINT_STATE_OUT_DISCONNECT);
                trace_header("ACTION redial/reply (no last number stored)", DIRECTION_NONE);
                end_trace();
                new_state(EPOINT_STATE_OUT_DISCONNECT);
-               message_disconnect_port(portlist, CAUSE_SERVICEUNAVAIL, LOCATION_PRIVATE_LOCAL, "");
+               message_disconnect_port(portlist, CAUSE_SERVICEUNAVAIL, LOCATION_PRIVATE_LOCAL, "", NULL);
                set_tone(portlist, "cause_3f");
                return;
        }
                set_tone(portlist, "cause_3f");
                return;
        }
@@ -910,7 +910,7 @@ void EndpointAppPBX::action_dialing_powerdial(void)
                trace_header("ACTION powerdial (no last number stored)", DIRECTION_NONE);
                end_trace();
                new_state(EPOINT_STATE_OUT_DISCONNECT);
                trace_header("ACTION powerdial (no last number stored)", DIRECTION_NONE);
                end_trace();
                new_state(EPOINT_STATE_OUT_DISCONNECT);
-               message_disconnect_port(portlist, CAUSE_SERVICEUNAVAIL, LOCATION_PRIVATE_LOCAL, "");
+               message_disconnect_port(portlist, CAUSE_SERVICEUNAVAIL, LOCATION_PRIVATE_LOCAL, "", NULL);
                set_tone(portlist, "cause_3f");
                return;
        }
                set_tone(portlist, "cause_3f");
                return;
        }
@@ -976,7 +976,7 @@ void EndpointAppPBX::action_dialing_callback(void)
                disconnect:
 
                new_state(EPOINT_STATE_OUT_DISCONNECT);
                disconnect:
 
                new_state(EPOINT_STATE_OUT_DISCONNECT);
-               message_disconnect_port(portlist, CAUSE_SERVICEUNAVAIL, LOCATION_PRIVATE_LOCAL, "");
+               message_disconnect_port(portlist, CAUSE_SERVICEUNAVAIL, LOCATION_PRIVATE_LOCAL, "", NULL);
                set_tone(portlist, "cause_3f");
                e_action = NULL;
                e_cbcaller[0] = e_cbdialing[0] = '\0';
                set_tone(portlist, "cause_3f");
                e_action = NULL;
                e_cbcaller[0] = e_cbdialing[0] = '\0';
@@ -1076,7 +1076,7 @@ void EndpointAppPBX::action_dialing_abbrev(void)
                trace_header("ACTION abbreviation (only for extension)", DIRECTION_NONE);
                end_trace();
                new_state(EPOINT_STATE_OUT_DISCONNECT);
                trace_header("ACTION abbreviation (only for extension)", DIRECTION_NONE);
                end_trace();
                new_state(EPOINT_STATE_OUT_DISCONNECT);
-               message_disconnect_port(portlist, CAUSE_SERVICEUNAVAIL, LOCATION_PRIVATE_LOCAL, "");
+               message_disconnect_port(portlist, CAUSE_SERVICEUNAVAIL, LOCATION_PRIVATE_LOCAL, "", NULL);
                set_tone(portlist, "cause_3f");
                return;
        }
                set_tone(portlist, "cause_3f");
                return;
        }
@@ -1091,7 +1091,7 @@ void EndpointAppPBX::action_dialing_abbrev(void)
                add_trace("abbrev", NULL, "%s", abbrev);
                end_trace();
                new_state(EPOINT_STATE_OUT_DISCONNECT);
                add_trace("abbrev", NULL, "%s", abbrev);
                end_trace();
                new_state(EPOINT_STATE_OUT_DISCONNECT);
-               message_disconnect_port(portlist, CAUSE_UNALLOCATED, LOCATION_PRIVATE_LOCAL, "");
+               message_disconnect_port(portlist, CAUSE_UNALLOCATED, LOCATION_PRIVATE_LOCAL, "", NULL);
                set_tone(portlist, "cause_01");
                return;
        }
                set_tone(portlist, "cause_01");
                return;
        }
@@ -1246,7 +1246,7 @@ void EndpointAppPBX::action_dialing_test(void)
                end_trace();
                new_state(EPOINT_STATE_OUT_DISCONNECT);
                SPRINT(causestr,"cause_%02x",cause);
                end_trace();
                new_state(EPOINT_STATE_OUT_DISCONNECT);
                SPRINT(causestr,"cause_%02x",cause);
-               message_disconnect_port(portlist, cause, LOCATION_PRIVATE_LOCAL, "");
+               message_disconnect_port(portlist, cause, LOCATION_PRIVATE_LOCAL, "", NULL);
                set_tone(portlist, causestr);
                break;
 
                set_tone(portlist, causestr);
                break;
 
@@ -1256,7 +1256,7 @@ void EndpointAppPBX::action_dialing_test(void)
                add_trace("cause", NULL, "16");
                end_trace();
                new_state(EPOINT_STATE_OUT_DISCONNECT);
                add_trace("cause", NULL, "16");
                end_trace();
                new_state(EPOINT_STATE_OUT_DISCONNECT);
-               message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
+               message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "", NULL);
                set_tone(portlist, "release");
                break;
 
                set_tone(portlist, "release");
                break;
 
@@ -1297,7 +1297,7 @@ void EndpointAppPBX::action_init_play(void)
 
                disconnect:
                new_state(EPOINT_STATE_OUT_DISCONNECT);
 
                disconnect:
                new_state(EPOINT_STATE_OUT_DISCONNECT);
-               message_disconnect_port(portlist, CAUSE_UNSPECIFIED, LOCATION_PRIVATE_LOCAL, "");
+               message_disconnect_port(portlist, CAUSE_UNSPECIFIED, LOCATION_PRIVATE_LOCAL, "", NULL);
                set_tone(portlist, "cause_3f");
                e_action = NULL;
                return;
                set_tone(portlist, "cause_3f");
                e_action = NULL;
                return;
@@ -1569,7 +1569,7 @@ void EndpointAppPBX::_action_goto_menu(int mode)
 
                disconnect:
                new_state(EPOINT_STATE_OUT_DISCONNECT);
 
                disconnect:
                new_state(EPOINT_STATE_OUT_DISCONNECT);
-               message_disconnect_port(portlist, CAUSE_SERVICEUNAVAIL, LOCATION_PRIVATE_LOCAL, "");
+               message_disconnect_port(portlist, CAUSE_SERVICEUNAVAIL, LOCATION_PRIVATE_LOCAL, "", NULL);
                set_tone(portlist, "cause_3f");
                e_action = NULL;
                return;
                set_tone(portlist, "cause_3f");
                e_action = NULL;
                return;
@@ -1682,7 +1682,7 @@ void EndpointAppPBX::action_dialing_disconnect(void)
        new_state(EPOINT_STATE_OUT_DISCONNECT);
        set_tone(portlist, cause_string);
        if (!(rparam = routeparam(e_action, PARAM_CONNECT))) {
        new_state(EPOINT_STATE_OUT_DISCONNECT);
        set_tone(portlist, cause_string);
        if (!(rparam = routeparam(e_action, PARAM_CONNECT))) {
-               message_disconnect_port(portlist, cause, location, display);
+               message_disconnect_port(portlist, cause, location, display, NULL);
        } else {
                message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
                SCPY(message->param.notifyinfo.display, display);
        } else {
                message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
                SCPY(message->param.notifyinfo.display, display);
@@ -2019,7 +2019,7 @@ void EndpointAppPBX::action_dialing_password(void)
                e_connectedmode = 0;
                e_dtmf = 0;
                new_state(EPOINT_STATE_OUT_DISCONNECT);
                e_connectedmode = 0;
                e_dtmf = 0;
                new_state(EPOINT_STATE_OUT_DISCONNECT);
-               message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
+               message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "", NULL);
                set_tone(portlist, "cause_10");
                return;
        }
                set_tone(portlist, "cause_10");
                return;
        }
@@ -2069,7 +2069,7 @@ void EndpointAppPBX::action_init_pots_retrieve(void)
 
                disconnect:
                new_state(EPOINT_STATE_OUT_DISCONNECT);
 
                disconnect:
                new_state(EPOINT_STATE_OUT_DISCONNECT);
-               message_disconnect_port(portlist, CAUSE_UNSPECIFIED, LOCATION_PRIVATE_LOCAL, "");
+               message_disconnect_port(portlist, CAUSE_UNSPECIFIED, LOCATION_PRIVATE_LOCAL, "", NULL);
                set_tone(portlist, "cause_3f");
                e_action = NULL;
                return;
                set_tone(portlist, "cause_3f");
                e_action = NULL;
                return;
@@ -2138,7 +2138,7 @@ void EndpointAppPBX::action_init_pots_release(void)
 
                disconnect:
                new_state(EPOINT_STATE_OUT_DISCONNECT);
 
                disconnect:
                new_state(EPOINT_STATE_OUT_DISCONNECT);
-               message_disconnect_port(portlist, CAUSE_UNSPECIFIED, LOCATION_PRIVATE_LOCAL, "");
+               message_disconnect_port(portlist, CAUSE_UNSPECIFIED, LOCATION_PRIVATE_LOCAL, "", NULL);
                set_tone(portlist, "cause_3f");
                e_action = NULL;
                return;
                set_tone(portlist, "cause_3f");
                e_action = NULL;
                return;
@@ -2176,7 +2176,7 @@ void EndpointAppPBX::action_init_pots_release(void)
 #if 0
        /* disconnect our call */
        new_state(EPOINT_STATE_OUT_DISCONNECT);
 #if 0
        /* disconnect our call */
        new_state(EPOINT_STATE_OUT_DISCONNECT);
-       message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
+       message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "", NULL);
        set_tone(portlist, "hangup");
        e_action = NULL;
 #endif
        set_tone(portlist, "hangup");
        e_action = NULL;
 #endif
@@ -2208,7 +2208,7 @@ void EndpointAppPBX::action_init_pots_reject(void)
                end_trace();
                disconnect:
                new_state(EPOINT_STATE_OUT_DISCONNECT);
                end_trace();
                disconnect:
                new_state(EPOINT_STATE_OUT_DISCONNECT);
-               message_disconnect_port(portlist, CAUSE_UNSPECIFIED, LOCATION_PRIVATE_LOCAL, "");
+               message_disconnect_port(portlist, CAUSE_UNSPECIFIED, LOCATION_PRIVATE_LOCAL, "", NULL);
                set_tone(portlist, "cause_3f");
                e_action = NULL;
                return;
                set_tone(portlist, "cause_3f");
                e_action = NULL;
                return;
@@ -2259,7 +2259,7 @@ void EndpointAppPBX::action_init_pots_answer(void)
                end_trace();
                disconnect:
                new_state(EPOINT_STATE_OUT_DISCONNECT);
                end_trace();
                disconnect:
                new_state(EPOINT_STATE_OUT_DISCONNECT);
-               message_disconnect_port(portlist, CAUSE_UNSPECIFIED, LOCATION_PRIVATE_LOCAL, "");
+               message_disconnect_port(portlist, CAUSE_UNSPECIFIED, LOCATION_PRIVATE_LOCAL, "", NULL);
                set_tone(portlist, "cause_3f");
                e_action = NULL;
                return;
                set_tone(portlist, "cause_3f");
                e_action = NULL;
                return;
@@ -2312,7 +2312,7 @@ void EndpointAppPBX::action_init_pots_3pty(void)
                end_trace();
                disconnect:
                new_state(EPOINT_STATE_OUT_DISCONNECT);
                end_trace();
                disconnect:
                new_state(EPOINT_STATE_OUT_DISCONNECT);
-               message_disconnect_port(portlist, CAUSE_UNSPECIFIED, LOCATION_PRIVATE_LOCAL, "");
+               message_disconnect_port(portlist, CAUSE_UNSPECIFIED, LOCATION_PRIVATE_LOCAL, "", NULL);
                set_tone(portlist, "cause_3f");
                e_action = NULL;
                return;
                set_tone(portlist, "cause_3f");
                e_action = NULL;
                return;
@@ -2390,7 +2390,7 @@ void EndpointAppPBX::action_init_pots_transfer(void)
 
                disconnect:
                new_state(EPOINT_STATE_OUT_DISCONNECT);
 
                disconnect:
                new_state(EPOINT_STATE_OUT_DISCONNECT);
-               message_disconnect_port(portlist, CAUSE_UNSPECIFIED, LOCATION_PRIVATE_LOCAL, "");
+               message_disconnect_port(portlist, CAUSE_UNSPECIFIED, LOCATION_PRIVATE_LOCAL, "", NULL);
                set_tone(portlist, "cause_3f");
                e_action = NULL;
                return;
                set_tone(portlist, "cause_3f");
                e_action = NULL;
                return;
@@ -2474,7 +2474,7 @@ void EndpointAppPBX::process_dialing(int timeout)
                add_trace("max-levels", NULL, "%d", RULE_NESTING);
                end_trace();
                new_state(EPOINT_STATE_OUT_DISCONNECT);
                add_trace("max-levels", NULL, "%d", RULE_NESTING);
                end_trace();
                new_state(EPOINT_STATE_OUT_DISCONNECT);
-               message_disconnect_port(portlist, CAUSE_UNSPECIFIED, LOCATION_PRIVATE_LOCAL, "");
+               message_disconnect_port(portlist, CAUSE_UNSPECIFIED, LOCATION_PRIVATE_LOCAL, "", NULL);
                set_tone(portlist, "cause_3f");
                unsched_timer(&e_action_timeout);
                unsched_timer(&e_match_timeout);
                set_tone(portlist, "cause_3f");
                unsched_timer(&e_action_timeout);
                unsched_timer(&e_match_timeout);
@@ -2501,7 +2501,7 @@ void EndpointAppPBX::process_dialing(int timeout)
                        /* nothing more, so we release */
                        PDEBUG(DEBUG_ROUTE|DEBUG_EPOINT, "EPOINT(%d): action timed out, and we have no next action, so we disconnect.\n", ea_endpoint->ep_serial);
                        new_state(EPOINT_STATE_OUT_DISCONNECT);
                        /* nothing more, so we release */
                        PDEBUG(DEBUG_ROUTE|DEBUG_EPOINT, "EPOINT(%d): action timed out, and we have no next action, so we disconnect.\n", ea_endpoint->ep_serial);
                        new_state(EPOINT_STATE_OUT_DISCONNECT);
-                       message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
+                       message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "", NULL);
                        set_tone(portlist, "cause_3f");
                        goto end;
                }
                        set_tone(portlist, "cause_3f");
                        goto end;
                }
@@ -2530,7 +2530,7 @@ void EndpointAppPBX::process_dialing(int timeout)
                        goto end;
                }
                /* invalid dialing */
                        goto end;
                }
                /* invalid dialing */
-               message_disconnect_port(portlist, CAUSE_INCALID, LOCATION_PRIVATE_LOCAL, "");
+               message_disconnect_port(portlist, CAUSE_INCALID, LOCATION_PRIVATE_LOCAL, "", NULL);
                        message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DISCONNECT);
                        message->param.disconnectinfo.cause = CAUSE_INVALID;
                        message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
                        message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DISCONNECT);
                        message->param.disconnectinfo.cause = CAUSE_INVALID;
                        message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
index 120bfa6..3b222e2 100644 (file)
@@ -82,7 +82,7 @@ void EndpointAppPBX::action_init_vbox_play(void)
                SCPY(e_vbox, rparam->string_value);
        if (e_vbox[0] == '\0') {
                /* facility rejected */
                SCPY(e_vbox, rparam->string_value);
        if (e_vbox[0] == '\0') {
                /* facility rejected */
-               message_disconnect_port(portlist, CAUSE_FACILITYREJECTED, LOCATION_PRIVATE_LOCAL, "");
+               message_disconnect_port(portlist, CAUSE_FACILITYREJECTED, LOCATION_PRIVATE_LOCAL, "", NULL);
                new_state(EPOINT_STATE_OUT_DISCONNECT);
                set_tone(portlist,"cause_22");
                return;
                new_state(EPOINT_STATE_OUT_DISCONNECT);
                set_tone(portlist,"cause_22");
                return;
index 9752b87..9f2b2e0 100644 (file)
@@ -522,7 +522,7 @@ void EndpointAppPBX::keypad_function(char digit)
                if ((port->p_type & PORT_CLASS_POTS_MASK) == PORT_CLASS_POTS_FXS)
                        join_join_fxs();
                else if ((port->p_type & PORT_CLASS_mISDN_MASK) == PORT_CLASS_DSS1)
                if ((port->p_type & PORT_CLASS_POTS_MASK) == PORT_CLASS_POTS_FXS)
                        join_join_fxs();
                else if ((port->p_type & PORT_CLASS_mISDN_MASK) == PORT_CLASS_DSS1)
-                       join_join_dss1();
+                       join_join_dss1(-1);
                break;
 
                /* VOOTP on */
                break;
 
                /* VOOTP on */
@@ -1317,7 +1317,7 @@ int password_timeout(struct lcr_timer *timer, void *instance, int index)
                ea->new_state(EPOINT_STATE_OUT_DISCONNECT);
                portlist = ea->ea_endpoint->ep_portlist;
                if (portlist) {
                ea->new_state(EPOINT_STATE_OUT_DISCONNECT);
                portlist = ea->ea_endpoint->ep_portlist;
                if (portlist) {
-                       ea->message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
+                       ea->message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "", NULL);
                        ea->set_tone(portlist, "cause_10");
                }
        }
                        ea->set_tone(portlist, "cause_10");
                }
        }
@@ -1424,7 +1424,7 @@ void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, un
                        trace_header("EXTENSION (not created)", DIRECTION_IN);
                        add_trace("extension", NULL, "%s", e_ext.number);
                        end_trace();
                        trace_header("EXTENSION (not created)", DIRECTION_IN);
                        add_trace("extension", NULL, "%s", e_ext.number);
                        end_trace();
-                       message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
+                       message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "", NULL);
                        new_state(EPOINT_STATE_OUT_DISCONNECT);
                        set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
                        e_ext.number[0] = '\0'; /* no terminal */
                        new_state(EPOINT_STATE_OUT_DISCONNECT);
                        set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
                        e_ext.number[0] = '\0'; /* no terminal */
@@ -1991,7 +1991,7 @@ void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type,
                if (!read_extension(&e_ext, e_ext.number)) {
                        /* extension doesn't exist */
                        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) rejecting callback from not existing extension: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
                if (!read_extension(&e_ext, e_ext.number)) {
                        /* extension doesn't exist */
                        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) rejecting callback from not existing extension: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
-                       message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
+                       message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "", NULL);
                        new_state(EPOINT_STATE_OUT_DISCONNECT);
                        set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
                        return;
                        new_state(EPOINT_STATE_OUT_DISCONNECT);
                        set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
                        return;
@@ -2260,7 +2260,7 @@ void EndpointAppPBX::port_timeout(struct port_list *portlist, int message_type,
        SCPY(e_tone, cause);
        while(portlist) {
                set_tone(portlist, cause);
        SCPY(e_tone, cause);
        while(portlist) {
                set_tone(portlist, cause);
-               message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
+               message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "", NULL);
                portlist = portlist->next;
        }
        release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
                portlist = portlist->next;
        }
        release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
@@ -2389,14 +2389,25 @@ void EndpointAppPBX::port_transfer(struct port_list *portlist, int message_type,
        logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
 
        class Port *port;
        logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
 
        class Port *port;
+       struct lcr_msg *message;
+       int rc;
 
        /* bridge for real */
        if (!(port = find_port_id(portlist->port_id)))
                return;
        if ((port->p_type & PORT_CLASS_POTS_MASK) == PORT_CLASS_POTS_FXS)
                join_join_fxs();
 
        /* bridge for real */
        if (!(port = find_port_id(portlist->port_id)))
                return;
        if ((port->p_type & PORT_CLASS_POTS_MASK) == PORT_CLASS_POTS_FXS)
                join_join_fxs();
-       else if ((port->p_type & PORT_CLASS_mISDN_MASK) == PORT_CLASS_DSS1)
-               join_join_dss1();
+       else if ((port->p_type & PORT_CLASS_mISDN_MASK) == PORT_CLASS_DSS1) {
+               rc = join_join_dss1(param->transfer.invoke_id);
+
+               if (rc < 0) {
+                       message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_TRANSFER);
+                       message->param.transfer.error = 1;
+                       message->param.transfer.invoke_id = param->transfer.invoke_id;
+                       logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
+                       message_put(message);
+               }
+       }
 }
 
 /* port MESSAGE_SUSPEND */
 }
 
 /* port MESSAGE_SUSPEND */
@@ -3020,7 +3031,7 @@ void EndpointAppPBX::join_disconnect_release(int message_type, union parameter *
        portlist = ea_endpoint->ep_portlist;
        while(portlist) {
                set_tone(portlist, cause);
        portlist = ea_endpoint->ep_portlist;
        while(portlist) {
                set_tone(portlist, cause);
-               message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
+               message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "", &param->disconnectinfo.transfer);
                portlist = portlist->next;
        }
 }
                portlist = portlist->next;
        }
 }
@@ -3338,7 +3349,9 @@ void EndpointAppPBX::ea_message_join(unsigned int join_id, int message_type, uni
                case MESSAGE_ALERTING:
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received alerting\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
                if (e_state!=EPOINT_STATE_IN_OVERLAP
                case MESSAGE_ALERTING:
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received alerting\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
                if (e_state!=EPOINT_STATE_IN_OVERLAP
-                && e_state!=EPOINT_STATE_IN_PROCEEDING) {
+                && e_state!=EPOINT_STATE_IN_PROCEEDING
+                && e_state!=EPOINT_STATE_IN_ALERTING /* second alerting */
+                && e_state!=EPOINT_STATE_CONNECT) { /* alerting after transfer */
                        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup or proceeding state.\n", ea_endpoint->ep_serial);
                        break;
                }
                        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup or proceeding state.\n", ea_endpoint->ep_serial);
                        break;
                }
@@ -3553,7 +3566,7 @@ void EndpointAppPBX::pick_join(char *extensions)
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) nobody is ringing internally (or we don't have her in the access list), so we disconnect.\n", ea_endpoint->ep_serial);
 reject:
                set_tone(ea_endpoint->ep_portlist, "cause_10");
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) nobody is ringing internally (or we don't have her in the access list), so we disconnect.\n", ea_endpoint->ep_serial);
 reject:
                set_tone(ea_endpoint->ep_portlist, "cause_10");
-               message_disconnect_port(ea_endpoint->ep_portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
+               message_disconnect_port(ea_endpoint->ep_portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "", NULL);
                new_state(EPOINT_STATE_OUT_DISCONNECT);
                return;
        }
                new_state(EPOINT_STATE_OUT_DISCONNECT);
                return;
        }
@@ -3691,7 +3704,7 @@ reject:
 
 /* join calls (look for a join that is on hold (same isdn interface/terminal))
  */
 
 /* join calls (look for a join that is on hold (same isdn interface/terminal))
  */
-int EndpointAppPBX::join_join_dss1(void)
+int EndpointAppPBX::join_join_dss1(int invoke_id)
 {
 #ifdef WITH_MISDN
        struct lcr_msg *message;
 {
 #ifdef WITH_MISDN
        struct lcr_msg *message;
@@ -3699,7 +3712,7 @@ int EndpointAppPBX::join_join_dss1(void)
        struct join_relation **add_relation_pointer, **remove_relation_pointer;
        class Join *our_join, *other_join, *add_join, *remove_join;
        class JoinPBX *our_joinpbx, *other_joinpbx, *add_joinpbx, *remove_joinpbx;
        struct join_relation **add_relation_pointer, **remove_relation_pointer;
        class Join *our_join, *other_join, *add_join, *remove_join;
        class JoinPBX *our_joinpbx, *other_joinpbx, *add_joinpbx, *remove_joinpbx;
-       class EndpointAppPBX *other_eapp, *remove_eapp;
+       class EndpointAppPBX *other_eapp, *remove_eapp_hold, *remove_eapp_active;
        class Port *our_port, *other_port;
        class Pdss1 *our_pdss1, *other_pdss1;
        class Endpoint *temp_epoint;
        class Port *our_port, *other_port;
        class Pdss1 *our_pdss1, *other_pdss1;
        class Endpoint *temp_epoint;
@@ -3793,14 +3806,16 @@ int EndpointAppPBX::join_join_dss1(void)
        /* now find out which is ACTIVE-IDLE and which is ACTIVE-HELD */
        if (our_pdss1->p_m_hold && !other_pdss1->p_m_hold) {
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) our relation is on hold and other is active, so we move our relations to other relations\n", ea_endpoint->ep_serial);
        /* now find out which is ACTIVE-IDLE and which is ACTIVE-HELD */
        if (our_pdss1->p_m_hold && !other_pdss1->p_m_hold) {
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) our relation is on hold and other is active, so we move our relations to other relations\n", ea_endpoint->ep_serial);
-               remove_eapp = this;
+               remove_eapp_hold = this;
+               remove_eapp_active = other_eapp;
                remove_join = our_join;
                remove_joinpbx = our_joinpbx;
                add_join = other_join;
                add_joinpbx = other_joinpbx;
        } else {
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) our relation is active or other is on hold, so we move ohter relations to our relations\n", ea_endpoint->ep_serial);
                remove_join = our_join;
                remove_joinpbx = our_joinpbx;
                add_join = other_join;
                add_joinpbx = other_joinpbx;
        } else {
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) our relation is active or other is on hold, so we move ohter relations to our relations\n", ea_endpoint->ep_serial);
-               remove_eapp = other_eapp;
+               remove_eapp_hold = other_eapp;
+               remove_eapp_active = this;
                remove_join = other_join;
                remove_joinpbx = other_joinpbx;
                add_join = our_join;
                remove_join = other_join;
                remove_joinpbx = other_joinpbx;
                add_join = our_join;
@@ -3811,13 +3826,13 @@ int EndpointAppPBX::join_join_dss1(void)
        remove_relation = remove_joinpbx->j_relation;
        remove_relation_pointer = &remove_joinpbx->j_relation;
        while(remove_relation) {
        remove_relation = remove_joinpbx->j_relation;
        remove_relation_pointer = &remove_joinpbx->j_relation;
        while(remove_relation) {
-               if (remove_relation->epoint_id == remove_eapp->ea_endpoint->ep_serial) {
-                       /* detach other endpoint */
+               if (remove_relation->epoint_id == remove_eapp_hold->ea_endpoint->ep_serial) {
+                       /* detach endpoint on hold */
                        *remove_relation_pointer = remove_relation->next;
                        FREE(remove_relation, sizeof(struct join_relation));
                        cmemuse--;
                        remove_relation = *remove_relation_pointer;
                        *remove_relation_pointer = remove_relation->next;
                        FREE(remove_relation, sizeof(struct join_relation));
                        cmemuse--;
                        remove_relation = *remove_relation_pointer;
-                       remove_eapp->ea_endpoint->ep_join_id = 0;
+                       remove_eapp_hold->ea_endpoint->ep_join_id = 0;
                        continue;
                }
 
                        continue;
                }
 
@@ -3831,9 +3846,43 @@ int EndpointAppPBX::join_join_dss1(void)
                remove_relation_pointer = &remove_relation->next;
                remove_relation = remove_relation->next;
        }
                remove_relation_pointer = &remove_relation->next;
                remove_relation = remove_relation->next;
        }
-       PDEBUG(DEBUG_EPOINT, "EPOINT(%d) endpoint removed, other enpoints on join relinked.\n", ea_endpoint->ep_serial);
+       PDEBUG(DEBUG_EPOINT, "EPOINT(%d) endpoint (hold) removed, other enpoints on join relinked.\n", ea_endpoint->ep_serial);
+
+       if (invoke_id >= 0) {
+               /* remove relation to endpoint for active join */
+               remove_relation = add_joinpbx->j_relation;
+               remove_relation_pointer = &add_joinpbx->j_relation;
+               while(remove_relation) {
+                       if (remove_relation->epoint_id == remove_eapp_active->ea_endpoint->ep_serial) {
+                               /* detach active endpoint */
+                               *remove_relation_pointer = remove_relation->next;
+                               FREE(remove_relation, sizeof(struct join_relation));
+                               cmemuse--;
+                               remove_relation = *remove_relation_pointer;
+                               remove_eapp_active->ea_endpoint->ep_join_id = 0;
+                               continue;
+                       }
 
 
-       /* join call relations */
+                       remove_relation_pointer = &remove_relation->next;
+                       remove_relation = remove_relation->next;
+               }
+               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) endpoint (active) removed, other enpoints on join relinked.\n", ea_endpoint->ep_serial);
+
+               /* if active endpoint is in alerting state, send alerting message to join */
+               if (remove_eapp_active->e_state == EPOINT_STATE_IN_ALERTING) {
+                       if (add_joinpbx->j_relation && !add_joinpbx->j_relation->next) {
+                               /* if channel state indicateds "audio" (1), we tell the other endpoint that patterns are available */
+                               if (add_joinpbx->j_relation->channel_state) {
+                                       message = message_create(add_joinpbx->j_relation->epoint_id, add_join->j_serial, EPOINT_TO_JOIN, MESSAGE_PATTERN);
+                                       message_put(message);
+                               }
+                               message = message_create(add_joinpbx->j_relation->epoint_id, add_join->j_serial, EPOINT_TO_JOIN, MESSAGE_ALERTING);
+                               message_put(message);
+                       }
+               }
+       }
+
+       /* join call relations: we add the members of the join on hold to the active join */
        add_relation = add_joinpbx->j_relation;
        add_relation_pointer = &add_joinpbx->j_relation;
        while(add_relation) {
        add_relation = add_joinpbx->j_relation;
        add_relation_pointer = &add_joinpbx->j_relation;
        while(add_relation) {
@@ -3844,12 +3893,32 @@ int EndpointAppPBX::join_join_dss1(void)
        remove_joinpbx->j_relation = NULL;
        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) relations joined.\n", ea_endpoint->ep_serial);
 
        remove_joinpbx->j_relation = NULL;
        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) relations joined.\n", ea_endpoint->ep_serial);
 
-       /* release endpoint */
-       message = message_create(remove_joinpbx->j_serial, remove_eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
+       /* release endpoint on hold */
+       message = message_create(remove_joinpbx->j_serial, remove_eapp_hold->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
        message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal */
        message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
        message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal */
        message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
+       if (invoke_id >= 0) {
+               /* send the result with disconnect message to the invoking endpoint */
+               if (remove_eapp_hold->ea_endpoint->ep_serial == ea_endpoint->ep_serial) {
+                       message->param.disconnectinfo.transfer.result = 1;
+                       message->param.disconnectinfo.transfer.invoke_id = invoke_id;
+               }
+       }
        message_put(message);
        
        message_put(message);
        
+       if (invoke_id >= 0) {
+               /* release active endpoint */
+               message = message_create(add_joinpbx->j_serial, remove_eapp_active->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
+               message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal */
+               message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
+               /* send the result with disconnect message to the invoking endpoint */
+               if (remove_eapp_active->ea_endpoint->ep_serial == ea_endpoint->ep_serial) {
+                       message->param.disconnectinfo.transfer.result = 1;
+                       message->param.disconnectinfo.transfer.invoke_id = invoke_id;
+               }
+               message_put(message);
+       }
+
        /* if we are not a partyline, we get partyline state from other join */
        add_joinpbx->j_partyline += remove_joinpbx->j_partyline; 
 
        /* if we are not a partyline, we get partyline state from other join */
        add_joinpbx->j_partyline += remove_joinpbx->j_partyline; 
 
@@ -4874,6 +4943,13 @@ void EndpointAppPBX::logmessage(int message_type, union parameter *param, unsign
 
                case MESSAGE_TRANSFER:
                trace_header("TRANSFER", dir);
 
                case MESSAGE_TRANSFER:
                trace_header("TRANSFER", dir);
+               if (param->transfer.invoke)
+                       add_trace("action", NULL, "invoke");
+               if (param->transfer.result)
+                       add_trace("action", NULL, "result");
+               if (param->transfer.error)
+                       add_trace("action", NULL, "error");
+               add_trace("invoke-id", NULL, "%d", param->transfer.invoke_id);
                end_trace();
                break;
 
                end_trace();
                break;
 
@@ -4906,7 +4982,7 @@ void EndpointAppPBX::logmessage(int message_type, union parameter *param, unsign
        }
 }
 
        }
 }
 
-void EndpointAppPBX::message_disconnect_port(struct port_list *portlist, int cause, int location, const char *display)
+void EndpointAppPBX::message_disconnect_port(struct port_list *portlist, int cause, int location, const char *display, const struct param_transfer *transfer)
 {
        struct lcr_msg *message;
 
 {
        struct lcr_msg *message;
 
@@ -4930,6 +5006,9 @@ void EndpointAppPBX::message_disconnect_port(struct port_list *portlist, int cau
                else
                        SCPY(message->param.notifyinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
        }
                else
                        SCPY(message->param.notifyinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
        }
+       if (transfer) {
+               memcpy(&message->param.disconnectinfo.transfer, transfer, sizeof(struct param_transfer));
+       }
        message_put(message);
        logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
 }
        message_put(message);
        logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
 }
index 618d9ac..068f2e5 100644 (file)
--- a/apppbx.h
+++ b/apppbx.h
@@ -323,7 +323,7 @@ class EndpointAppPBX : public EndpointApp
 
        /* facility function */
        void pick_join(char *extension);
 
        /* facility function */
        void pick_join(char *extension);
-       int join_join_dss1(void);
+       int join_join_dss1(int invoke_id);
        int join_join_fxs(void);
        int join_3pty_dss1(void);
        int join_3pty_fxs(void);
        int join_join_fxs(void);
        int join_3pty_dss1(void);
        int join_3pty_fxs(void);
@@ -373,7 +373,7 @@ class EndpointAppPBX : public EndpointApp
        void cryptman_timeout(int secs);
        int vootp_on(int enable);
 
        void cryptman_timeout(int secs);
        int vootp_on(int enable);
 
-       void message_disconnect_port(struct port_list *portlist, int cause, int location, const char *display);
+       void message_disconnect_port(struct port_list *portlist, int cause, int location, const char *display, const struct param_transfer *transfer);
        void logmessage(int message_type, union parameter *param, unsigned int port_id, int dir);
        void trace_header(const char *name, int direction);
 
        void logmessage(int message_type, union parameter *param, unsigned int port_id, int dir);
        void trace_header(const char *name, int direction);
 
index 43452bb..f2c2ba5 100644 (file)
--- a/dss1.cpp
+++ b/dss1.cpp
@@ -1675,6 +1675,13 @@ void Pdss1::facility_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
                        message->param.threepty.invoke_id = fac.u.inv.invokeId;
                        message_put(message);
                        return;
                        message->param.threepty.invoke_id = fac.u.inv.invokeId;
                        message_put(message);
                        return;
+
+                       case Fac_EctExecute:
+                       message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_TRANSFER);
+                       message->param.transfer.invoke = 1;
+                       message->param.transfer.invoke_id = fac.u.inv.invokeId;
+                       message_put(message);
+                       return;
                default:
                        ;
                }
                default:
                        ;
                }
@@ -2348,6 +2355,43 @@ void Pdss1::message_3pty(unsigned int epoint_id, int message_id, union parameter
        p_m_mISDNport->ml3->to_layer3(p_m_mISDNport->ml3, MT_FACILITY, p_m_d_l3id, l3m);
 }
 
        p_m_mISDNport->ml3->to_layer3(p_m_mISDNport->ml3, MT_FACILITY, p_m_d_l3id, l3m);
 }
 
+void Pdss1::enc_ie_facility_ect(l3_msg *l3m, struct param_transfer *transfer)
+{
+       unsigned char fac_ie[256];
+       struct asn1_parm fac;
+
+       /* encode ECT facility */
+       memset(&fac, 0, sizeof(fac));
+       fac.Valid = 1;
+       if (transfer->result) {
+               fac.comp = CompReturnResult;
+               fac.u.retResult.invokeId = transfer->invoke_id;
+               fac.u.retResult.operationValuePresent = 1;
+               fac.u.retResult.operationValue = Fac_EctExecute;
+       }
+       if (transfer->error) {
+               fac.comp = CompReturnError;
+               fac.u.retError.invokeId = transfer->invoke_id;
+               fac.u.retError.errorValue = FacError_Gen_InvalidCallState;
+       }
+       encodeFac(fac_ie, &fac);
+
+       enc_ie_facility(l3m, fac_ie + 2, fac_ie[1]);
+}
+
+/* MESSAGE_TRANSFER */
+void Pdss1::message_transfer(unsigned int epoint_id, int message_id, union parameter *param)
+{
+       l3_msg *l3m;
+
+       /* sending facility */
+       l3m = create_l3msg();
+       l1l2l3_trace_header(p_m_mISDNport, this, L3_FACILITY_REQ, DIRECTION_OUT);
+       enc_ie_facility_ect(l3m, &param->transfer);
+       end_trace();
+       p_m_mISDNport->ml3->to_layer3(p_m_mISDNport->ml3, MT_FACILITY, p_m_d_l3id, l3m);
+}
+
 /* MESSAGE_NOTIFY */
 void Pdss1::message_notify(unsigned int epoint_id, int message_id, union parameter *param)
 {
 /* MESSAGE_NOTIFY */
 void Pdss1::message_notify(unsigned int epoint_id, int message_id, union parameter *param)
 {
@@ -2689,6 +2733,10 @@ if (/*    ||*/ p_state==PORT_STATE_OUT_SETUP) {
                enc_ie_progress(l3m, 0, (p_m_d_ntmode)?1:5, 8);
        /* send cause */
        enc_ie_cause(l3m, (!p_m_mISDNport->locally && param->disconnectinfo.location==LOCATION_PRIVATE_LOCAL)?LOCATION_PRIVATE_REMOTE:param->disconnectinfo.location, param->disconnectinfo.cause);
                enc_ie_progress(l3m, 0, (p_m_d_ntmode)?1:5, 8);
        /* send cause */
        enc_ie_cause(l3m, (!p_m_mISDNport->locally && param->disconnectinfo.location==LOCATION_PRIVATE_LOCAL)?LOCATION_PRIVATE_REMOTE:param->disconnectinfo.location, param->disconnectinfo.cause);
+       /* send facility */
+       if (param->disconnectinfo.transfer.result) {
+               enc_ie_facility_ect(l3m, &param->disconnectinfo.transfer);
+       }
        /* send display */
        if (param->disconnectinfo.display[0])
                p = param->disconnectinfo.display;
        /* send display */
        if (param->disconnectinfo.display[0])
                p = param->disconnectinfo.display;
@@ -2859,6 +2907,10 @@ int Pdss1::message_epoint(unsigned int epoint_id, int message_id, union paramete
                message_3pty(epoint_id, message_id, param);
                break;
 
                message_3pty(epoint_id, message_id, param);
                break;
 
+               case MESSAGE_TRANSFER: /* begin result message */
+               message_transfer(epoint_id, message_id, param);
+               break;
+
                case MESSAGE_OVERLAP: /* more information is needed */
                if (p_state!=PORT_STATE_IN_SETUP) {
                        break;
                case MESSAGE_OVERLAP: /* more information is needed */
                if (p_state!=PORT_STATE_IN_SETUP) {
                        break;
diff --git a/dss1.h b/dss1.h
index d9487b3..b6966b2 100644 (file)
--- a/dss1.h
+++ b/dss1.h
@@ -58,6 +58,7 @@ class Pdss1 : public PmISDN
        void message_notify(unsigned int epoint_id, int message_id, union parameter *param);
        void message_facility(unsigned int epoint_id, int message_id, union parameter *param);
        void message_3pty(unsigned int epoint_id, int message_id, union parameter *param);
        void message_notify(unsigned int epoint_id, int message_id, union parameter *param);
        void message_facility(unsigned int epoint_id, int message_id, union parameter *param);
        void message_3pty(unsigned int epoint_id, int message_id, union parameter *param);
+       void message_transfer(unsigned int epoint_id, int message_id, union parameter *param);
        void message_overlap(unsigned int epoint_id, int message_id, union parameter *param);
        void message_proceeding(unsigned int epoint_id, int message_id, union parameter *param);
        void message_alerting(unsigned int epoint_id, int message_id, union parameter *param);
        void message_overlap(unsigned int epoint_id, int message_id, union parameter *param);
        void message_proceeding(unsigned int epoint_id, int message_id, union parameter *param);
        void message_alerting(unsigned int epoint_id, int message_id, union parameter *param);
@@ -99,6 +100,7 @@ class Pdss1 : public PmISDN
        void dec_ie_redir_dn(struct l3_msg *l3m, int *type, int *plan, int *present, unsigned char *number, int number_len);
        void enc_ie_facility(struct l3_msg *l3m, unsigned char *facility, int facility_len);
        void dec_ie_facility(struct l3_msg *l3m, unsigned char *facility, int *facility_len);
        void dec_ie_redir_dn(struct l3_msg *l3m, int *type, int *plan, int *present, unsigned char *number, int number_len);
        void enc_ie_facility(struct l3_msg *l3m, unsigned char *facility, int facility_len);
        void dec_ie_facility(struct l3_msg *l3m, unsigned char *facility, int *facility_len);
+       void enc_ie_facility_ect(l3_msg *l3m, struct param_transfer *transfer);
        void dec_facility_centrex(struct l3_msg *l3m, unsigned char *cnip, int cnip_len);
        void enc_ie_useruser(struct l3_msg *l3m, int protocol, unsigned char *user, int user_len);
        void dec_ie_useruser(struct l3_msg *l3m, int *protocol, unsigned char *user, int *user_len);
        void dec_facility_centrex(struct l3_msg *l3m, unsigned char *cnip, int cnip_len);
        void enc_ie_useruser(struct l3_msg *l3m, int protocol, unsigned char *user, int user_len);
        void dec_ie_useruser(struct l3_msg *l3m, int *protocol, unsigned char *user, int *user_len);
index 47952ac..fb11384 100644 (file)
--- a/message.h
+++ b/message.h
@@ -156,6 +156,11 @@ struct rtp_info {
        unsigned short port;            /* peer's port */
 };
 
        unsigned short port;            /* peer's port */
 };
 
+struct param_transfer {
+       int invoke, result, error;
+       unsigned char invoke_id;
+};
+
 /* call-info structure CALLER */
 struct caller_info {
        char id[32];                    /* id of caller (user number) */
 /* call-info structure CALLER */
 struct caller_info {
        char id[32];                    /* id of caller (user number) */
@@ -210,6 +215,7 @@ struct disconnect_info {
        int location;                   /* disconnect location */
        char display[84];               /* optional display information */
        int force;                      /* special flag to release imediately */
        int location;                   /* disconnect location */
        char display[84];               /* optional display information */
        int force;                      /* special flag to release imediately */
+       struct param_transfer transfer; /* used to return result to the invoking endpoint */
 };
 
 /* call-info structure REDIR */
 };
 
 /* call-info structure REDIR */
@@ -392,6 +398,7 @@ union parameter {
        struct param_traffic traffic; /* MESSAGE_TRAFFIC */
        struct param_3pty threepty; /* MESSAGE_TRAFFIC */
        struct param_dov dov; /* MESSAGE_DOV */
        struct param_traffic traffic; /* MESSAGE_TRAFFIC */
        struct param_3pty threepty; /* MESSAGE_TRAFFIC */
        struct param_dov dov; /* MESSAGE_DOV */
+       struct param_transfer transfer; /* MESSAGE_TRANSFER (ECT in case of ISDN) */
        unsigned int queue; /* MESSAGE_DISABLE_DEJITTER */
        struct param_vootp vootp; /* MESSAGE_VOOTP */
 };
        unsigned int queue; /* MESSAGE_DISABLE_DEJITTER */
        struct param_vootp vootp; /* MESSAGE_VOOTP */
 };