Show MdForwarder.c syntax highlighted
////////////////////////////////////////////////////////////////////////////
//
// CENS
//
// Copyright (c) 2003 The Regents of the University of California. All
// rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// - Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// - Neither the name of the University nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS''
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Contents: This file contains the module used to forward messages in
// Micro Diffusion.
//
// Purpose: The purpose of this module is to logically connect all of the
// user and system logic in Micro Diffusion.
//
////////////////////////////////////////////////////////////////////////////
//
// $Id: MdForwarder.c,v 1.6 2004/04/06 08:22:27 adparker Exp $
#include "libdev/packet_dev.h"
#include "Mdiff.h"
#include "MdMatch.h"
#include "MdForwarder.h"
#include "MdOppGradient.h"
////////////////////////////////////////////////////////////////////////////
//
// Commad: StdControl.init( )
//
// Purpose: This command is used to init this component.
//
////////////////////////////////////////////////////////////////////////////
result_t MdForwarder_init( Mdiff_state_t * state )
{
// Sequence number for outbound messages that originate on this node.
elog(LOG_INFO," ");
state->MdForwarder->m_uiSeq = 0;
return SUCCESS;
}
////////////////////////////////////////////////////////////////////////////
//
// Commad: StdControl.start( )
//
// Purpose: This command is used to start this component.
//
////////////////////////////////////////////////////////////////////////////
result_t MdForwarder_start( Mdiff_state_t * state )
{
elog(LOG_INFO," ");
return SUCCESS;
}
////////////////////////////////////////////////////////////////////////////
//
// Commad: StdControl.stop( )
//
// Purpose: This command is used to stop this component.
//
////////////////////////////////////////////////////////////////////////////
result_t MdForwarder_stop( Mdiff_state_t * state)
{
// Destroy devices and client contexts ???
elog(LOG_INFO," ");
return SUCCESS;
}
////////////////////////////////////////////////////////////////////////////
//
// Commad: TdForwarderI.recvFromFilter( )
//
// Purpose: This event is called from a filter if it has decided to pass its
// message on to the next filter. The expected behavior of this
// event is to cause messages to proceed up the filter stack.
//
////////////////////////////////////////////////////////////////////////////
//
// Pass ownership of p_pMsg to MdForwarder_callFilter
result_t MdForwarder_recvFromFilter( Mdiff_state_t * state, IntDiffMsg_t *p_pMsg )
{
result_t tReturn = SUCCESS;
elog(LOG_INFO," ");
// Make sure we have a message.
if ( NULL == p_pMsg )
{
elog( LOG_NOTICE,
"%s [%d] - Message is NULL.\n",
__FILE__,
__LINE__ );
tReturn = FAIL;
}
// If all is well...
else
{
p_pMsg->m_uiPriority++;
tReturn = MdForwarder_callFilter(state, p_pMsg);
}
return tReturn;
}
////////////////////////////////////////////////////////////////////////////
//
// Command: TdForwarderI.sendMsg( )
//
// Purpose: This command is used to send a Tiny Diffusion message from a user
// application to Tiny Diffusion. This message is sent up from the
// bottom of the priority stack.
//
////////////////////////////////////////////////////////////////////////////
//
// p_pMsg is owned by us.
// p_pMsg will be memcopied to a IntDiffMsg_t so that it's contiguous.
// p_pMsg will be freed.
//
// tMsg is malloc'ed.
// tMsg ownership is passed to MdForwarder_callFilter()
result_t MdForwarder_sendMsg( Mdiff_state_t * state,
uint16_t p_uiLastHop,
DiffMsg_t *p_pMsg )
{
uint8_t uiAttrs = 0;
uint16_t ui = 0;
result_t tReturn = SUCCESS;
// This is the internal message that we will enqueue.
IntDiffMsg_t * tMsg = (IntDiffMsg_t *)malloc(sizeof(IntDiffMsg_t));
DiffAttr_t *pAttr = NULL;
elog(LOG_INFO," ");
// zero out tMsg;
memset(tMsg,0,sizeof(IntDiffMsg_t));
// Check to see if we have a valid message.
if ( NULL == p_pMsg )
{
elog( LOG_NOTICE,
"%s [%d] - Unable to use NULL message.\n",
__FILE__,
__LINE__ );
tReturn = FAIL;
}
else if ( p_pMsg->m_uiDataLen > TD_MAX_MSG_LEN )
{
elog( LOG_NOTICE,
"%s [%d] - Input message length was: %u (greater than %d).\n",
__FILE__,
__LINE__,
p_pMsg->m_uiDataLen,
TD_MAX_MSG_LEN );
tReturn = FAIL;
}
// If all is well...
else
{
uiAttrs = 0;
// Loop over the DiffMsg_t counting attributes.
for ( ui = 0;
ui < p_pMsg->m_uiDataLen;
uiAttrs++ )
{
// Cast the pointer.
pAttr = ( DiffAttr_t * ) &( p_pMsg->m_pData[ ui ] );
// Check to see if this is a BLOB attribute (i.e. of a
// non-standard size).
//
// If not...
if ( TD_ATTR_USER_BASE_BLOB > pAttr->m_uiAttr
|| TD_ATTR_USER_BASE_KEY <= pAttr->m_uiAttr )
{
// Just advance the pointer by the length of a standard attribute.
ui += sizeof( DiffAttr_t );
}
// Otherwise...
else if (0 == pAttr->m_uiOp
|| (p_pMsg->m_uiDataLen - ui) < pAttr->m_uiOp)
{
elog(LOG_ALERT,"Bounds error. Blob length %u is invalid with %u out of %u bytes left in message.",
pAttr->m_uiOp,
(p_pMsg->m_uiDataLen - ui),
p_pMsg->m_uiDataLen);
tReturn = FAIL;
break;
}
else
{
// This is a BLOB and the operator variable is overloaded to
// specify the length of the BLOB.
ui += pAttr->m_uiOp;
}
}
if ( SUCCESS == tReturn)
{
// Set the number of attributes that we found in the internal message.
tMsg->m_uiNumAttrs = uiAttrs;
// Set the last hop address:
tMsg->m_uiLastHop = p_uiLastHop;
// Copy into the payload of our internal message to be the entire DiffMsg_t.
memcpy( &( tMsg->m_tMsg ),
p_pMsg,
sizeof( DiffMsg_t ) );
// If this message originated on this node, then this is its first hop...
if ( ( uint16_t ) TD_LOCAL_ADDR == p_uiLastHop )
{
// We first assign it our next sequence number.
tMsg->m_tMsg.m_uiSeq = ++state->MdForwarder->m_uiSeq;
// Then we set its TTL to our default.
tMsg->m_tMsg.m_uiTtl = TD_MAX_TTL;
}
// Since this message is going to traverse the stack from the bottom,
// we will set its parameter to 0.
tMsg->m_uiPriority = 0;
// Passing ownership of tMsg
tReturn = MdForwarder_callFilter(state, tMsg);
}
}
free(p_pMsg);
return tReturn;
}
/////////////////////////////////////////////////////////
// Ownership of tMsg goes to MdFilter_recv or MdFilter_callPreGradient
// (only if it returns SUCCESS). If not, I'm still responsible for
// tMsg.
result_t MdForwarder_callFilter( Mdiff_state_t * state, IntDiffMsg_t * tMsg )
{
result_t tReturn = SUCCESS;
elog(LOG_INFO," ");
// If the message priority is 0, then set the message priority to
// the first filter's priority, and pass the message to it. ???
if (tMsg->m_uiPriority < TD_FILTER_GRADIENT) {
// call function that returns first PD client with priorty >= priority.
if (SUCCESS != MdForwarder_callPreGradient(state, tMsg)) {
tMsg->m_uiPriority = TD_FILTER_GRADIENT;
MdOppGradient_recv(state, tMsg);
}
}
else if (tMsg->m_uiPriority == TD_FILTER_GRADIENT) {
// pass to gradient
MdOppGradient_recv(state, tMsg);
}
else {
if (SUCCESS != MdForwarder_callPostGradient(state, tMsg)) {
free(tMsg);
}
}
return tReturn;
}
void MdForwarder_filterReceive(pd_context_t * pd_ref, pd_client_t * pdc,
IntDiffMsg_t * tMsg)
{
MdMsg_t * msg = (MdMsg_t*)malloc(sizeof(MdMsg_t)+sizeof(IntDiffMsg_t));
elog(LOG_INFO," ");
memset(msg,0,sizeof(MdMsg_t)+sizeof(IntDiffMsg_t));
msg->type = MdRecv;
msg->length = sizeof(IntDiffMsg_t);
memcpy(msg->data,tMsg,sizeof(IntDiffMsg_t));
pd_client_receive(pd_ref, pdc, msg, sizeof(MdMsg_t)+sizeof(IntDiffMsg_t), NULL);
free(msg);
}
result_t MdForwarder_callPreGradient(Mdiff_state_t * state, IntDiffMsg_t * tMsg)
{
result_t tReturn = FAIL;
pd_client_t * pdc = pd_client_top(state->filter_pd_ref);
uint8_t client_priority = 0;
pd_client_t * best_pdc = NULL;
uint8_t best_priority = 0;
elog(LOG_INFO," ");
for ( ; pdc != NULL; pdc = pd_client_next(pdc) ) {
if ( pd_client_data(pdc) == NULL) continue;
client_priority = *((uint8_t *)pd_client_data(pdc));
if (client_priority >= TD_FILTER_GRADIENT) continue;
if (client_priority < tMsg->m_uiPriority) continue;
if ( (NULL == best_pdc)
|| ( client_priority < best_priority ) ) {
best_pdc = pdc;
best_priority = client_priority;
tReturn = SUCCESS;
}
}
if (tReturn == SUCCESS) {
tMsg->m_uiPriority = best_priority;
MdForwarder_filterReceive(state->filter_pd_ref, best_pdc, tMsg);
free(tMsg);
}
return tReturn;
}
result_t MdForwarder_callPostGradient(Mdiff_state_t * state, IntDiffMsg_t * tMsg)
{
result_t tReturn = FAIL;
pd_client_t * pdc = pd_client_top(state->filter_pd_ref);
uint8_t client_priority = 0;
pd_client_t * best_pdc = NULL;
uint8_t best_priority = 0;
elog(LOG_INFO," ");
for ( ; pdc != NULL; pdc = pd_client_next(pdc) ) {
if ( pd_client_data(pdc) == NULL) continue;
client_priority = *((uint8_t *)pd_client_data(pdc));
if (client_priority <= TD_FILTER_GRADIENT) continue;
if (client_priority < tMsg->m_uiPriority) continue;
if ( (NULL == best_pdc)
|| ( client_priority < best_priority ) ) {
best_pdc = pdc;
best_priority = client_priority;
tReturn = SUCCESS;
}
}
if (tReturn == SUCCESS) {
tMsg->m_uiPriority = best_priority;
MdForwarder_filterReceive(state->filter_pd_ref, best_pdc, tMsg);
free(tMsg);
}
return tReturn;
}
See more files for this project here