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

 @(#) $Id: mtp_hmrt.h,v 0.7.2.3 2001/02/03 05:48:40 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:40 $ by $Author: brian $

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

#ifndef __MTP_HMRT_H__
#define __MTP_HMRT_H__

/*
 *  Referenced functions.
 */

static inline void mtp_hmcg_message(mtp_t *mtp, mblk_t *mp);

static inline void mtp_mgmt_message_received_for_unknown_sp(mtp_t *mtp, mblk_t *mp);

static inline void mtp_rtpc_message_received_for_inaccessible_sp(mtp_t *mtp, mblk_t *mp);

/*
 *  Forward declarations.
 */

static inline void mtp_hmrt_adjacent_sp_restart(mtp_t *mtp);
static inline void mtp_hmrt_message_for_routing(mtp_t *mtp, mblk_t *mp);
static inline void mtp_hmrt_mtp_testing_user_part_message(mtp_t *mtp);
static inline void mtp_hmrt_restart_begins(mtp_t *mtp);
static inline void mtp_hmrt_restart_ends(mtp_t *mtp);
static inline void mtp_hmrt_signalling_link_management_message(mtp_t *mtp, mblk_t *mp);
static inline void mtp_hmrt_signalling_route_management_message(mtp_t *mtp);
static inline void mtp_hmrt_update_routing_tables(mtp_t *mtp);

/*
 *  Signalling Message Handling (SMH)
 *  Message Routing (HMRT)
 *  Figure 26/Q.704
 */

/*
 *  Another ridiculous 2-state state machine which can (and should) be
 *  reorganized to simply use a flag for "Own SP Restart".  Then it is merely
 *  a group of function calls.
 */

#define mtp_hmrt_transfer_request(mtp) mtp_hmrt_message_for_routing(mtp)
static inline void mtp_hmrt_message_for_routing(mtp_t *mtp, mblk_t *mp)
{
    rs_t *rs;   /* route set */
    ls_t *ls;   /* link set (route) */
    lk_t *lk;   /* link */
    switch ( mtp->statem.hmrt_state ) {
        case MTP_STATE_IDLE:
            if ( (rs = /* routing for DPC exists */) ) {
                if ( rs->statem.sp_restart ) {
                    /* discard message */
                    freemsg(mp);
                } else {
#if !national_option
                    if ( rs->statem.congested )
                        mtp_tsec_message_for_congested_destination(rs);
#endif
                    if ( rs->config.load_sharing_between_link_sets )
                        ls = /* select link set on the basis of sls */;
                    else
                        ls = /* ???? */;
                    lk = /* select link in linkset on the basis of sls */;
#if national_option
                    mtp_hmcg_message(mtp, mp);
#endif
                    lk->dcalls->sl_pdu(lk, mp);
                }
            } else {
                if ( /* message did no originate at this SP */ ) {
                    mtp_mgmt_message_received_for_unknown_sp(mtp, mp);
                    mtp_rtpc_message_received_for_inaccessible_sp(mtp, mp);
                    /* discard message */
                    freemsg(mp);
                }
            }
            break;
    }
}

static inline void mtp_hmrt_adjacent_sp_restart(mtp_t *mtp)
{
    switch ( mtp->statem.hmrt_state ) {
        case MTP_STATE_IDLE:
            mtp_>statem.adjacent_sp_restart = 1;
            break;
    }
}

static inline void mtp_hmrt_update_routing_tables(mtp_t *mtp)
{
    /* From changeover, changeback, forced or controlled rerouting */
    switch ( mtp->statem.hmrt_state ) {
        case MTP_STATE_IDLE:
            /* update routing tables */
            break;
    }
}

static inline void mtp_hmrt_signalling_link_management_message(mtp_t *mtp, mblk_t *mp)
{
    /* A signal is accomplished by routing data obtained at the source of the
     * signal from TSRC */
    rs_t *rs;   /* route set */
    ls_t *ls;   /* link set (route) */
    lk_t *lk:   /* link */
    switch ( mtp->statem.hmrt_state ) {
        case MTP_STATE_IDLE:
            if ( (rs = /* routing for DPC exists */) ) {
                if ( rs->statem.sp_restart ) {
                    /* discard message */
                    freemsg(mp);
                } else { 
                    ls = /* select an available link */;
                    lk = /* select an available link */;
#if national_option
                    mtp_hmcg_message(mtp, mp);
#endif
                    lk->dcalls->sl_pdu(lk, mp);
                }
            } else {
                if ( /* message did no originate at this SP */ ) {
                    mtp_mgmt_message_received_for_unknown_sp(mtp, mp);
                    mtp_rtpc_message_received_for_inaccessible_sp(mtp, mp);
                    /* discard message */
                    freemsg(mp);
                }
            }
            break;
            }
            break;
    }
}

static inline void mtp_hmrt_signalling_route_management_message(mtp_t *mtp)
{
    rs_t *rs;   /* route set */
    ls_t *ls;   /* link set (route) */
    lk_t *lk:   /* link */
    switch ( mtp->statem.hmrt_state ) {
        case MTP_STATE_IDLE:
            if ( (rs = /* routing for DPC exists */) ) {
                if ( rs->statem.sp_restart ) {
                    switch ( message_type ) {
                        case MTP_SRM_TFA:
                        case MTP_SRM_TFR:
                        case MTP_SRM_TFP:
#if !national_option
                            if ( rs->statem.congested )
                                mtp_tsec_message_for_congested_destination(rs);
#endif
                            if ( rs->config.load_sharing_between_link_sets )
                                ls = /* select link set on the basis of sls */;
                            else
                                ls = /* ???? */;
                            lk = /* select link in linkset on the basis of sls */;
#if national_option
                            mtp_hmcg_message(mtp, mp);
#endif
                            lk->dcalls->sl_pdu(lk, mp);
                            break;
                        default:
                            /* discard message */
                            freemsg(mp);
                            break;
                    }
                } else {
#if !national_option
                    if ( rs->statem.congested )
                        mtp_tsec_message_for_congested_destination(rs);
#endif
                    if ( rs->config.load_sharing_between_link_sets )
                        ls = /* select link set on the basis of sls */;
                    else
                        ls = /* ???? */;
                    lk = /* select link in linkset on the basis of sls */;
#if national_option
                    mtp_hmcg_message(mtp, mp);
#endif
                    lk->dcalls->sl_pdu(lk, mp);
                }
            } else {
                if ( /* message did no originate at this SP */ ) {
                    mtp_mgmt_message_received_for_unknown_sp(mtp, mp);
                    mtp_rtpc_message_received_for_inaccessible_sp(mtp, mp);
                    /* discard message */
                    freemsg(mp);
                }
            }
            break;
    }
}

static inline void mtp_hmrt_mtp_testing_user_part_message(mtp_t *mtp)
{
    switch ( mtp->statem.hmrt_state ) {
        case MTP_STATE_IDLE:
            /*
             *  NOTE - Some special routing for MTP Testing User Part may be
             *  needed depending on the function and requirements of such a
             *  User Part.
             */
            break;
    }
}

static inline void mtp_hmrt_restart_ends(mtp_t *mtp)
{
    switch ( mtp->statem.hmrt_state ) {
        case MTP_STATE_IDLE:
            /* cancel marks */
            break;
        case MTP_STATE_OWN_SP_RESTART:
            break;
    }
}

static inline void mtp_hmrt_restart_begins(mtp_t *mtp)
{
    switch ( mtp->statem.hmrt_state ) {
        case MTP_STATE_IDLE:
            mtp->statem.hmrt_state = MTP_STATE_OWN_SP_RESTART;
            break;
    }
}


#endif  __MTP_HMRT_H__

