/*****************************************************************************

 @(#) $Id: mtp_tsrc.h,v 0.7.2.3 2001/02/03 05:48:42 brian Test $

 -----------------------------------------------------------------------------

 Copyright (C) 1997-2001  Brian Bidulock <bidulock@dallas.net>

 All Rights Reserved.

 This program is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free Software
 Foundation; either version 2 of the License, or (at your option) any later
 version.

 This program is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 details.

 You should have received a copy of the GNU General Public License along with
 this program; if not, write to the Free Software Foundation, Inc., 675 Mass
 Ave, Cambridge, MA 02139, USA.

 -----------------------------------------------------------------------------

 Last Modified $Date: 2001/02/03 05:48:42 $ by $Author: brian $

 *****************************************************************************/

#ifndef __MTP_TSRC_H__
#define __MTP_TSRC_H__

/*
 *  Referenced functions.
 */

static inline void rs_hmrt_adjacent_sp_restarting(rs_t *rs);
static inline void rs_hmrt_traffic_restart_allowed(rs_t *rs);

static inline void rs_llsc_emergency_ceases(rs_t *rs);
static inline void rs_llsc_emergency(rs_t *rs);

static inline void rs_lsda_alternative_routing_data(rs_t *rs);

static inline void rs_rsrt_accessibility_data(rs_t *rs);
static inline void rs_rsrt_adjacent_sp_restarted(rs_t *rs);
static inline void rs_rsrt_adjacent_sp_restarting(rs_t *rs);
static inline void rs_rsrt_start_route_set_test(rs_t *rs);

static inline void rs_rtac_destination_accessible(rs_t *rs);
static inline void rs_rtac_destination_inaccessible(rs_t *rs);
static inline void rs_rtac_forced_rerouting(rs_t *rs);
static inline void rs_rtac_stp_no_longer_used_for_destination(rs_t *rs);

static inline void rs_rtpc_destination_inaccessible(rs_t *rs);
static inline void rs_rtpc_send_transfer_prohibited_message(rs_t *rs);
static inline void rs_rtpc_send_transfer_prohibited_messages(rs_t *rs);

static inline void rs_rtrc_destination_restricted(rs_t *rs);
static inline void rs_rtrc_send_transfer_restricted_message(rs_t *rs);

static inline void rs_tcbc_alternative_routing_data(rs_t *rs);

static inline void rs_tcoc_alternative_routing_data(rs_t *rs);

static inline void rs_tcrc_alternative_routing_data(rs_t *rs);
static inline void rs_tcrc_signalling_route_restricted(rs_t *rs);

static inline void rs_tfrc_alternative_routing_data(rs_t *rs);
static inline void rs_tfrc_signalling_route_unavailable(rs_t *rs);

static inline void rs_tlac_adjacent_sp_restarted(rs_t *rs);
static inline void rs_tlac_adjacent_sp_restarting(rs_t *rs);
static inline void rs_tlac_local_inhibit_allowed(rs_t *rs);
static inline void rs_tlac_local_inhibit_denied(rs_t *rs);
static inline void rs_tlac_remote_inhibit_allowed(rs_t *rs);
static inline void rs_tlac_remote_inhibit_denied(rs_t *rs);
static inline void rs_tlac_uninhibiting_not_possible(rs_t *rs);
static inline void rs_tlac_uninhibiting_possible(rs_t *rs);
static inline void rs_tlac_uninhibit_signalling_link(rs_t *rs);

static inline void rs_tprc_adjacent_sp_restarting(rs_t *rs);
static inline void rs_tprc_signalling_point_restart_indication(rs_t *rs);
static inline void rs_tprc_status_sent(rs_t *rs);
static inline void rs_tprc_stop_restart(rs_t *rs);

static inline void rs_trcc_accessibility_data(rs_t *rs);
static inline void rs_trcc_destination_inaccessible(rs_t *rs);

static inline void rs_tsfc_destination_accessible(rs_t *rs);
static inline void rs_tsfc_destination_congestion_status(rs_t *rs);
static inline void rs_tsfc_destination_inaccessible(rs_t *rs);

/*
 *  Forward declarations.
 */

static inline void rs_t21_timeout(rs_t *rs);
static inline void rs_t11_timeout(rs_t *rs);
static inline void rs_t20_timeout(rs_t *rs);

static inline void rs_tsrc_accessibility_data_request(rs_t *rs);
static inline void rs_tsrc_alternative_routing_data_request_lsda(rs_t *rs);
static inline void rs_tsrc_alternative_routing_data_request_tcbc(rs_t *rs);
static inline void rs_tsrc_alternative_routing_data_request_tcoc(rs_t *rs);
static inline void rs_tsrc_alternative_routing_data_request_tcrc(rs_t *rs);
static inline void rs_tsrc_alternative_routing_data_request_tfrc(rs_t *rs);
static inline void rs_tsrc_cancel_link_inhibited(rs_t *rs);
static inline void rs_tsrc_changeover_executed(rs_t *rs);
static inline void rs_tsrc_changeover_not_required(rs_t *rs);
static inline void rs_tsrc_link_congestion_status(rs_t *rs);
static inline void rs_tsrc_link_in_service_at_level_2(rs_t *rs);
static inline void rs_tsrc_link_inhibited(rs_t *rs);
static inline void rs_tsrc_local_inhibit_request(rs_t *rs);
static inline void rs_tsrc_procedure_terminated(rs_t *rs);
static inline void rs_tsrc_remote_inhibit_request(rs_t *rs);
static inline void rs_tsrc_restart_begins(rs_t *rs);
static inline void rs_tsrc_restart_ends(rs_t *rs);
static inline void rs_tsrc_send_status(rs_t *rs);
static inline void rs_tsrc_send_status_information(rs_t *rs);
static inline void rs_tsrc_sending_status_phase(rs_t *rs);
static inline void rs_tsrc_signalling_link_available(rs_t *rs);
static inline void rs_tsrc_signalling_link_congested(rs_t *rs);
static inline void rs_tsrc_signalling_link_unavailable(rs_t *rs);
static inline void rs_tsrc_signalling_link_uncongested(rs_t *rs);
static inline void rs_tsrc_signalling_route_available(rs_t *rs);
static inline void rs_tsrc_signalling_route_restricted(rs_t *rs);
static inline void rs_tsrc_signalling_route_unavailable(rs_t *rs);
static inline void rs_tsrc_traffic_restart_allowed(rs_t *rs);
static inline void rs_tsrc_uninhibit_request(rs_t *rs);

/*
 *  Signalling Traffic Management (STM)
 *  Signalling Routing Control (TSRC)
 *  Figure 29/Q.704
 */

static inline void rs_t21_timeout(rs_t *rs)
{
    switch ( rs->statem.tsrc_state ) {
        case RS_STATE_IDLE:
            rs->statem.adjacent_sp_restarting = 0;
            rs_tlac_adjacent_sp_restarted(rs); /* for all links of the linkset */
            rs_rsrt_adjacent_sp_restarted(rs);
            if ( /* any unavailable or restricted route? */ ) {
                for ( /* each of these destinations */ ) {
                    /* select one of these destinations */
                    rs_rsrt_start_route_set_test(rs);
                }
            }
            if ( /* STP function */ ) {
                rs_rtac_destination_accessible(rs); /* concerning the adjacent SP */
            }
            rs_tspc_destination_accessible(rs);
            if ( /* any destination becoming available? */ ) {
                /* via the adjacent SP restarted */
                for ( /* each of these destinations */ ) {
                    /* select one destination */
                    rs_tspc_destination_accessible(rs);
                    if ( /* STP function */ ) {
                        rs_rtac_destination_accessible(rs);
                        if ( /* adjacent SP becoming available */ ) {
                            if ( /* any destination inaccessible? */ ) {
                                for ( /* each destination inaccessible */ ) {
                                    /* select one of the inaccessible destinations */
                                    rs_rtpc_send_transfer_prohibited_message(rs); /* to the newly available SP */
                                }
                            }
                            if ( /* any destination restricted */ ) {
                                for ( /* each destination restricted */ ) {
                                    /* select one of the restricted destinations */
                                    rs_rtrc_send_transfer_restricted_message(rs);
                                }
                            }
                        }
                    }
                }
            }
            break;
    }
}

static inline void rs_tsrc_restart_begins(rs_t *rs)
{
    switch ( rs->statem.tsrc_state ) {
        case RS_STATE_IDLE:
            for ( /* all routes */ ) {
                rs->statem.available = 1;
            }
            for ( /* all local/remote inhibit requests */ ) {
                /* cancel local/remote inhibit request */
            }
            for ( /* all links */ ) {
                /* cancel inhibited link */
            }
            break;
    }
}

static inline void rs_tsrc_traffic_restart_allowed(rs_t *rs)
{
    switch ( rs->statem.tsrc_state ) {
        case RS_STATE_IDLE:
            if ( /* from adjacent sp restarting? */ ) {
                if ( /* Sending phase finished? */ ) {
                    rs->statem.sending_phase_finished = 0;
                    rs_timer_stop(t21);
                    rs->statem.adjacent_sp_restarting = 0;
                    rs_tlac_adjacent_sp_restarted(rs); /* for all links of the linkset */
                    rs_rsrt_adjacent_sp_restarted(rs);
                    if ( /* any unavailable or restricted route? */ ) {
                        for ( /* each of these destinations */ ) {
                            /* select one of these destinations */
                            rs_rsrt_start_route_set_test(rs);
                        }
                    }
                    if ( /* STP function */ ) {
                        rs_rtac_destination_accessible(rs); /* concerning the adjacent SP */
                    }
                    rs_tspc_destination_accessible(rs);
                    if ( /* any destination becoming available? */ ) {
                        /* via the adjacent SP restarted */
                        for ( /* each of these destinations */ ) {
                            /* select one destination */
                            rs_tspc_destination_accessible(rs);
                            if ( /* STP function */ ) {
                                rs_rtac_destination_accessible(rs);
                                if ( /* adjacent SP becoming available */ ) {
                                    if ( /* any destination inaccessible? */ ) {
                                        for ( /* each destination inaccessible */ ) {
                                            /* select one of the inaccessible destinations */
                                            rs_rtpc_send_transfer_prohibited_message(rs); /* to the newly available SP */
                                        }
                                    }
                                    if ( /* any destination restricted */ ) {
                                        for ( /* each destination restricted */ ) {
                                            /* select one of the restricted destinations */
                                            rs_rtrc_send_transfer_restricted_message(rs);
                                        }
                                    }
                                }
                            }
                        }
                } else {
                    rs->statem.tra_received = 1;
                }
            } else {
                /* Unexpected TRA */
                if ( /* STP function */ ) {
                    if ( /* any accessible destination? */ ) {
                        for ( /* each inaccessible destination */ ) {
                            /* select one of the inaccessible destinations */
                            rs_rtpc_send_transfer_prohibited_message(rs);
                        }
                    }
                    if ( /* any destination restricted? */ ) {
                        for ( /* each restricted destination */ ) {
                            /* select one of the restricted destinations */
                            rs_rtrc_send_transfer_restricted_message(rs);
                        }
                    }
                }
                rs_hmrt_traffic_restart_allowed(rs);
            }
            break;
    }
}

static inline void rs_tsrc_sending_status_phase(rs_t *rs)
{
    switch ( rs->statem.tsrc_state ) {
        case RS_STATE_IDLE:
            rs->statem.tsrc_state = RS_STATE_WAIT05;
            break;
    }
}

static inline void rs_tsrc_signalling_link_unavailable(rs_t *rs)
{
    switch ( rs->statem.tsrc_state ) {
        case RS_STATE_IDLE:
            rs->statem.link_available;
            if ( rs->statem.emergency ) {   /* see 12.2.4 */
                rs_llsc_emergency(rs);
            }
            if ( ! /* alternative link in linkset */ ) {
                /* select one of affected destinations */
                /* in normal or alternative linkset */
                if ( /* sp restarting */ ) {
                    /* mark unavailable */
                }
            }

            break;
    }
}

static inline void rs_tsrc_accessibility_data_request(rs_t *rs)
{
    switch ( rs->statem.tsrc_state ) {
        case RS_STATE_IDLE:
            /* Obtain accessibility data for concerned destination */
            /* Routes via restarting adjacent SPs are considered prohibited */
            rs_rsrt_accessibility_data(rs);
            break;
    }
}

static inline void rs_tsrc_signalling_link_available(rs_t *rs)
{
    switch ( rs->statem.tsrc_state ) {
        case RS_STATE_IDLE:
            rs->statem.link_available = 1;
            if ( !rs->statem.emergency )
                rs_llsc_emergency_ceases(rs);
            if ( /* other links available in linkset? */ )
                break;
            if ( !rs->statem.own_sp_restarting ) {
                rs_timer_stop(t11);
            }
            for ( /* each destination for which linkset may be used */ ) {
                /* Select destination for which linkset may be used */
                if ( rs->statem.own_sp_restarting ) {
                    rs->statem.route_available = 1;
                } else {
                    if ( rs->statem.destination_accessible ){
                        if ( /* STP no longer used for destination? */ ) {

                    }
                }
            }
            break;
    }
}

static inline void rs_tsrc_(rs_t *rs)
{
    switch ( rs->statem.tsrc_state ) {
        case RS_STATE_IDLE:
            break;
    }
}

static inline void rs_tsrc_(rs_t *rs)
{
    switch ( rs->statem.tsrc_state ) {
        case RS_STATE_IDLE:
            break;
    }
}

static inline void rs_tsrc_(rs_t *rs)
{
    switch ( rs->statem.tsrc_state ) {
        case RS_STATE_IDLE:
            break;
    }
}


#endif  __MTP_TSRC_H__

