⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 state.c

📁 Vista 核心Rally技术之-LLTD 实现源代码
💻 C
字号:
/*
 * LICENSE NOTICE.
 *
 * Use of the Microsoft Windows Rally Development Kit is covered under
 * the Microsoft Windows Rally Development Kit License Agreement,
 * which is provided within the Microsoft Windows Rally Development
 * Kit or at http://www.microsoft.com/whdc/rally/rallykit.mspx. If you
 * want a license from Microsoft to use the software in the Microsoft
 * Windows Rally Development Kit, you must (1) complete the designated
 * "licensee" information in the Windows Rally Development Kit License
 * Agreement, and (2) sign and return the Agreement AS IS to Microsoft
 * at the address provided in the Agreement.
 */

/*
 * Copyright (c) Microsoft Corporation 2005.  All rights reserved.
 * This software is provided with NO WARRANTY.
 */

#include <stdio.h>
#include <string.h>
#include <assert.h>

#include "globals.h"

#include "statemachines.h"
#include "bandfuncs.h"
#include "packetio.h"

/****************************
 * Timeout handlers - 
 * these are the time-based entry points, which also clock the state machine.
 */

void
state_block_timeout(void *cookie)
{
    g_block_timer = NULL;
    g_this_event.evtType = evtBlockTimeout;
    state_process_timeout();
}

void
state_charge_timeout(void *cookie)
{
    g_charge_timer     = NULL;
    g_ctc_packets      = 0;
    g_ctc_bytes        = 0;
    g_this_event.evtType  = evtChargeTimeout;
    g_this_event.ssn      = (session_t*) cookie;
    state_process_timeout();
}

void
state_emit_timeout(void *cookie)
{
    g_emit_timer       = NULL;
    g_this_event.evtType  = evtEmitTimeout;

    /* Probes are forced to associate with the mapping session, if there is one. */
    if (g_topo_session != NULL  &&  g_topo_session->ssn_is_valid)
    {
        g_this_event.ssn = g_topo_session;
    }

    state_process_timeout();
}

void
state_hello_delay_timeout(void *cookie)
{
    g_hello_timer      = NULL;
    g_this_event.evtType  = evtHelloDelayTimeout;
    g_this_event.ssn      = (session_t*) cookie;
    state_process_timeout();
}

void
state_inactivity_timeout(void *cookie)
{
    g_this_event.evtType  = evtInactivityTimeout;
    g_this_event.ssn      = (session_t*) cookie;
    g_this_event.ssn->ssn_InactivityTimer = NULL;
    state_process_timeout();
}


/* This function locates an existing session that is associated with the passed-in address */
static session_t *
find_session(etheraddr_t *this_addr)
{
    session_t   *ssn = &g_sessions[0];
    int i;

    for (i=0; i < MAX_NUM_SESSIONS; ssn++, i++)
    {
        if ( (ssn->ssn_is_valid) && (ETHERADDR_EQUALS(&ssn->ssn_mapper_real, this_addr)) )
        {
//*/        DEBUG({printf("find_session returning session %d @ %X\n",i,(uint)ssn);})
            return ssn;
        }
    }
//*/DEBUG({puts("find_session returning NULL");})
    return NULL;
}


static session_t *
new_session()
{
    session_t   *ssn = &g_sessions[0];
    int i;

    for (i=0; i < MAX_NUM_SESSIONS; ssn++, i++)
    {
        if ( !(ssn->ssn_is_valid) )
        {
            ssn->ssn_is_valid = TRUE;
	    ssn->ssn_count = BAND_TXC;
            ssn->ssn_XID = 0;
            memset(&ssn->ssn_mapper_real,0,sizeof(etheraddr_t));
            memset(&ssn->ssn_mapper_current,0,sizeof(etheraddr_t));
            ssn->ssn_use_broadcast = TRUE;
            ssn->ssn_TypeOfSvc = ToS_Unknown;
            ssn->ssn_InactivityTimer = NULL;
            return ssn;
        }
    }
    return NULL;
}


/*****************************************************************************
 *
 * This code processes the current packet-event (in g_this_event) by locating
 * (and possibly creating) the session with which it must be associated,
 * then passing it to the 3 state machines, smS, smE, and smT, in that order.
 *
 *****************************************************************************/ 

uint
state_process_packet()
{
    session_t           *this_session;
    enum sm_Status       smStatus;

    IF_TRACED((TRC_STATE|TRC_PACKET))
        printf("state_process_packet: Entered with event %s",smEvent_names[g_this_event.evtType]);
        if (g_this_event.evtType==evtPacketRcvd)
        {
            printf(" (%s)\n",Topo_opcode_names[g_opcode]);
        } else {
            puts("");
        }
    END_TRACE

    g_this_event.isInternalEvt = FALSE;	// It's a real event, not internally generated

    /* First, look this RealSrc up in the session table, to
     * locate any association with an established session.
     *
     * If there is no matching session, create a new one, iff the
     * packet is a valid Discover of either topo- or quick- TOS ... */

    g_this_event.isNewSession = FALSE;

    if ((this_session = find_session(&g_base_hdr->tbh_realsrc)) == NULL)
    {
        /* Not found: Check for a Discovery packet (validated in packetio.c) */
        if (g_opcode == Opcode_Discover)
        {
            /* Create a new session for this association */
            if ((this_session = new_session()) == NULL)
            {
                /* No room in the table: drop the packet and whine. */
                warn("state_process_packet: no room to create new session. Packet dropped.\n");
                return UINT_MAX;
            }
            g_this_event.isNewSession = TRUE;

            /* Fill in the newly valid session table entry with info from the packet */
            this_session->ssn_XID            = g_sequencenum;
            this_session->ssn_mapper_real    = g_base_hdr->tbh_realsrc;
            this_session->ssn_mapper_current = g_ethernet_hdr->eh_src;
            this_session->ssn_TypeOfSvc      = g_base_hdr->tbh_tos;
            IF_TRACED(TRC_STATE)
                printf("New Session:\n\tXID = %X\n\treal address: " ETHERADDR_FMT \
                       "\n",this_session->ssn_XID, \
                       ETHERADDR_PRINT(&this_session->ssn_mapper_real) );

                printf("\tcurrent address: " ETHERADDR_FMT "\n\tToS: %s\n",
                       ETHERADDR_PRINT(&this_session->ssn_mapper_current),
                       Lld2_tos_names[this_session->ssn_TypeOfSvc] );
            END_TRACE
            g_this_event.ssn = this_session;

        }   /*** end of if (g_opcode == Opcode_Discover) ***/

        /* Probes are forced to associate with the mapping session, if there is one. */
        if (g_opcode == Opcode_Probe)
        {
             if (g_topo_session != NULL  &&  g_topo_session->ssn_is_valid)
             {
                this_session = g_topo_session;
             }
        }

    }   /*** endo of if (find_session()==NULL) ***/

    /* We have associated whatever session that we can with this packet - pass to state machines */
    g_this_event.ssn = this_session;

    smStatus = smS_process_event( &g_this_event );

    if (smStatus != PROCESSING_ABORTED)
    {
        smStatus = smE_process_event( &g_this_event );
    }

    if (smStatus != PROCESSING_ABORTED)
    {
        smStatus = smT_process_event( &g_this_event );
    }

    /* Remove any "new-session" marking */
    g_this_event.isNewSession = FALSE;

    IF_TRACED(TRC_PACKET)
        printf("state_process_packet: Leaving - done with event %s\n",smEvent_names[g_this_event.evtType]);
    END_TRACE
    return 0;	/* Success! */
}


/******************************************************************************
 *
 * This code processes the current timeout-event (in g_this_event). Any session
 * associated with this event (only happens with activity-timeouts) is already
 * noted in the GLOBAL g_this_event (g_this_event).
 *
 ******************************************************************************/ 

uint
state_process_timeout()
{
    enum sm_Status         smStatus;

    IF_TRACED(TRC_STATE)
        if (g_this_event.evtType!=evtBlockTimeout)
            printf("state_process_timeout: Entered with event %s\n",smEvent_names[g_this_event.evtType]);
    END_TRACE

    g_rcvd_pkt_len = 0;

    /* Finish initializing the protocol-event */

    /* g_this_event.evtType    = <set in individual timeout handler> */
    /* g_this_event.ssn        = <set in individual timeout handler> */
    g_this_event.isNewSession  = FALSE;
    g_this_event.isAckingMe    = FALSE;
    g_this_event.isInternalEvt = FALSE;	// It's a real event, not internally generated
    g_this_event.numDescrs     = 0;

    /* pass Hello-Delay timer events to each existing session's smS state-machine */
    if (g_this_event.evtType == evtHelloDelayTimeout)
    {
        session_t     *ssn = &g_sessions[0];
        int            i;

        for (i=0; i < MAX_NUM_SESSIONS; ssn++, i++)
        {
            if (ssn->ssn_is_valid)
            {
                g_this_event.ssn = ssn;
                smS_process_event( &g_this_event );
            }
        }
        g_this_event.ssn = NULL;
    }

    /* Pass per-session activity timeouts to the associated session.  The remaining
     * timeouts, for charge and emit, need only be processed by smE & smT...        */
    if (g_this_event.evtType == evtInactivityTimeout)
    {
        smS_process_event( &g_this_event );
    }

    /* send all the timeouts to smE and then smT */

    smStatus = smE_process_event( &g_this_event );

    if (smStatus != PROCESSING_ABORTED)
    {
        smT_process_event( &g_this_event );
    }

    return 0;	/* Success! */
}


/****************************
 * Helper functions -
 * actions performed as part of state processing.
 */

/* Restart the inactivity timer for the session associated with the current event */
void
restart_inactivity_timer(uint32_t timeout)
{
    struct timeval now;

    if (g_this_event.ssn == NULL  ||  g_this_event.ssn->ssn_is_valid != TRUE)   return;

    gettimeofday(&now, NULL);
    timeval_add_ms(&now, timeout);
    CANCEL(g_this_event.ssn->ssn_InactivityTimer);
    g_this_event.ssn->ssn_InactivityTimer = event_add(&now, state_inactivity_timeout, g_this_event.ssn);
}


/* Searches session table - returns TRUE if all valid sessions are in smS_Complete state */

bool_t
OnlyCompleteSessions(void)
{
    session_t   *ssn = &g_sessions[0];
    int i;

    for (i=0; i < MAX_NUM_SESSIONS; ssn++, i++)
    {
        if (ssn->ssn_is_valid && ssn->ssn_state != smS_Complete)
        {
            return FALSE;
        }
    }
    return TRUE;
}


/* Searches session table - returns TRUE if all sessions are invalid */

bool_t
SessionTableIsEmpty(void)
{
    session_t   *ssn = &g_sessions[0];
    int i;

    for (i=0; i < MAX_NUM_SESSIONS; ssn++, i++)
    {
        if (ssn->ssn_is_valid)
        {
            return FALSE;
        }
    }
    return TRUE;
}

bool_t
set_emit_timer(void)
{
    topo_emitee_desc_t *ed;

    assert(g_emit_remaining > 0);
    assert(g_emit_timer == NULL);

    /* get the next emitee_desc and schedule a callback when it is due
     * to be transmitted */
    ed = g_emitdesc;
    if (ed->ed_pause != 0)
    {
	struct timeval now;
	gettimeofday(&now, NULL);
	timeval_add_ms(&now, ed->ed_pause);
	g_emit_timer = event_add(&now, state_emit_timeout, NULL);
        return TRUE;
    } else {
	/* no pause; return PAUSE=FALSE */
	return FALSE;
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -