Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

297 lines
9.0 KiB

//-----------------------------------------------------------------------------
//
//
// File: smproute.cpp
//
// Description:
// Implementation of CSimpleMessageRouter.
//
// Author: Mike Swafford (MikeSwa)
//
// History:
// 5/20/98 - MikeSwa Created
//
// Copyright (C) 1998 Microsoft Corporation
//
//-----------------------------------------------------------------------------
#include "aqprecmp.h"
#include "smproute.h"
#include "domcfg.h"
#ifdef AQ_DEFAULT_MESSAGE_ROUTER_DEBUG
#undef AQ_DEFAULT_MESSAGE_ROUTER_DEBUG
#endif //AQ_DEFAULT_MESSAGE_ROUTER_DEBUG
//If you are interested is using the default router to test how AQ handles
//multiple message types and schedule ID's, the uncomment the following
//#define AQ_DEFAULT_MESSAGE_ROUTER_DEBUG
//---[ CAQDefaultMessageRouter::CAQDefaultMessageRouter ]----------------------
//
//
// Description:
// Constructor for CSimpleMessageRouter
// Parameters:
// pguid - pointer to GUID to use to identify self
// Returns:
// -
// History:
// 5/20/98 - MikeSwa Created
//
//-----------------------------------------------------------------------------
CAQDefaultMessageRouter::CAQDefaultMessageRouter(GUID *pguid, CAQSvrInst *paqinst)
{
_ASSERT(paqinst);
m_dwSignature = AQ_DEFAULT_ROUTER_SIG;
m_cPeakReferences = 1;
ZeroMemory(&m_rgcMsgTypeReferences, NUM_MESSAGE_TYPES*sizeof(DWORD));
if (pguid)
memcpy(&m_guid, pguid, sizeof(GUID));
else
ZeroMemory(&m_guid, sizeof(GUID));
m_dwCurrentReference = 0;
m_paqinst = paqinst;
m_paqinst->AddRef();
}
//---[ CAQDefaultMessageRouter::~CAQDefaultMessageRouter ]---------------------
//
//
// Description:
// Destructor for CAQDefaultMessageRouter. Will assert that all message
// types have been release correctly
// Parameters:
// -
// Returns:
// -
// History:
// 5/21/98 - MikeSwa Created
//
//-----------------------------------------------------------------------------
CAQDefaultMessageRouter::~CAQDefaultMessageRouter()
{
m_paqinst->Release();
for (int i = 0; i < NUM_MESSAGE_TYPES; i++)
_ASSERT((0 == m_rgcMsgTypeReferences[i]) && "Message Types were not released");
}
//---[ CAQDefaultMessageRouter::GetTransportSinkID ]---------------------------
//
//
// Description:
// Returns GUID id for this messager router interface
// Parameters:
// -
// Returns:
// GUID for this IMessageRouter
// History:
// 5/20/98 - MikeSwa Created
//
//-----------------------------------------------------------------------------
GUID CAQDefaultMessageRouter::GetTransportSinkID()
{
return m_guid;
}
//---[ CAQDefaultMessageRouter::GetMessageType ]-------------------------------
//
//
// Description:
// Wrapper for routing get-message-type event.
// Parameters:
// IN pIMailMsg IMailMsgProperties of message to classify
// OUT pdwMsgType DWORD message type of message
// Returns:
// S_OK on success
// failure code from routing event
// History:
// 5/19/98 - MikeSwa Created
//
//-----------------------------------------------------------------------------
HRESULT CAQDefaultMessageRouter::GetMessageType(
IN IMailMsgProperties *pIMailMsg,
OUT DWORD *pdwMessageType)
{
HRESULT hr = S_OK;
DWORD dwMessageType = InterlockedIncrement((PLONG) &m_dwCurrentReference);
_ASSERT(pdwMessageType);
#ifdef AQ_DEFAULT_MESSAGE_ROUTER_DEBUG
//For debug versions we will autostress ourselves by generating msg types
//simulate failures
if (0 == (dwMessageType % NUM_MESSAGE_TYPES))
return E_FAIL;
dwMessageType %= NUM_MESSAGE_TYPES;
#else
dwMessageType = 0;
#endif //AQ_DEFAULT_MESSAGE_ROUTER_DEBUG
InterlockedIncrement((PLONG) &m_rgcMsgTypeReferences[dwMessageType]);
*pdwMessageType = dwMessageType;
return hr;
}
//---[ CAQDefaultMessageRouter::ReleaseMessageType ]---------------------------
//
//
// Description:
// Wrapper for ReiReleaseMessageType... releases references to message
// type returned by HrGetMessageType.
// Parameters:
// IN dwMessageType Msg type (as return by HrGetNextMessage) to release
// IN dwReleaseCount Number of references to release
// Returns:
// S_OK on success
// History:
// 5/19/98 - MikeSwa Created
//
//-----------------------------------------------------------------------------
HRESULT CAQDefaultMessageRouter::ReleaseMessageType(
IN DWORD dwMessageType,
IN DWORD dwReleaseCount)
{
HRESULT hr = S_OK;
_ASSERT(dwMessageType < NUM_MESSAGE_TYPES);
_ASSERT(m_rgcMsgTypeReferences[dwMessageType]);
_ASSERT(m_rgcMsgTypeReferences[dwMessageType] >= dwReleaseCount);
_ASSERT(0 == (dwReleaseCount & 0x80000000)); //non-negative
InterlockedExchangeAdd((PLONG) &m_rgcMsgTypeReferences[dwMessageType], -1 * (LONG) dwReleaseCount);
return hr;
}
//---[ CAQDefaultMessageRouter::GetNextHop ]------------------------------------
//
//
// Description:
// Wrapper for routing ReiGetNextHop. Returns the <domain, schedule id>
// pair for the next hop link
// Parameters:
//
// Returns:
// S_OK on success
// History:
// 5/19/98 - MikeSwa Created
//
//-----------------------------------------------------------------------------
HRESULT CAQDefaultMessageRouter::GetNextHop(
IN LPSTR szDestinationAddressType,
IN LPSTR szDestinationAddress,
IN DWORD dwMessageType,
OUT LPSTR *pszRouteAddressType,
OUT LPSTR *pszRouteAddress,
OUT LPDWORD pdwScheduleID,
OUT LPSTR *pszRouteAddressClass,
OUT LPSTR *pszConnectorName,
OUT LPDWORD pdwNextHopType)
{
HRESULT hr = S_OK;
CInternalDomainInfo *pIntDomainInfo = NULL;
_ASSERT(dwMessageType < NUM_MESSAGE_TYPES);
_ASSERT(!lstrcmpi(MTI_ROUTING_ADDRESS_TYPE_SMTP, szDestinationAddressType));
_ASSERT(szDestinationAddress);
_ASSERT(pdwNextHopType);
_ASSERT(pszConnectorName);
_ASSERT(pszRouteAddressType);
_ASSERT(pszRouteAddress);
_ASSERT(pszRouteAddressClass);
//For now, we will use essentially non-routed behavior... every thing will
//go it's own link, and will use the same schedule ID. No address class
//will be returned.
*pdwNextHopType = MTI_NEXT_HOP_TYPE_EXTERNAL_SMTP;
#ifdef AQ_DEFAULT_MESSAGE_ROUTER_DEBUG
//Use m_dwCurrentReference to randomize schedule Id
*pdwScheduleID = m_dwCurrentReference & 0x00000002;
#else //retail build
*pdwScheduleID = 0;
#endif //AQ_DEFAULT_MESSAGE_ROUTER_DEBUG
pszConnectorName = NULL;
*pszRouteAddressType = MTI_ROUTING_ADDRESS_TYPE_SMTP;
*pszRouteAddressClass = NULL;
#ifdef AQ_DEFAULT_MESSAGE_ROUTER_DEBUG
//Get smarthost for this domain if stressing routing
hr = m_paqinst->HrGetInternalDomainInfo( strlen(szDestinationAddress),
szDestinationAddress, &pIntDomainInfo);
if (FAILED(hr))
goto Exit;
if (pIntDomainInfo->m_DomainInfo.szSmartHostDomainName)
{
//smart host exists... use it
*pszRouteAddress = (LPSTR) pvMalloc(sizeof(CHAR) *
(pIntDomainInfo->m_DomainInfo.cbSmartHostDomainNameLength+1));
if (!*pszRouteAddress)
{
hr = E_OUTOFMEMORY;
goto Exit;
}
lstrcpy(*pszRouteAddress, pIntDomainInfo->m_DomainInfo.szSmartHostDomainName);
}
else
{
*pszRouteAddress = szDestinationAddress;
}
Exit:
#else //AQ_DEFAULT_MESSAGE_ROUTER_DEBUG
*pszRouteAddress = szDestinationAddress;
#endif //AQ_DEFAULT_MESSAGE_ROUTER_DEBUG
if (pIntDomainInfo)
pIntDomainInfo->Release();
return hr;
}
//---[ CAQDefaultMessageRouter::GetNextHopFree ]------------------------------------
//
//
// Description:
// Wrapper for routing ReiGetNextHopFree.
// Free's the strings allocated in GetNextHop
// NOTE: szDestinationAddressType/szDestinationAddress will never
// be free'd. They are arguments as an optimization trick (to
// avoid alloc/freeing when szDestinationAddress=szRouteAddress)
//
// Parameters:
// szDestinationAddressType: DestinationAddressType passed into GetNextHopF
// szDestinationAddress: DestinationAddress passed into GetNextHop
//
// Returns:
// S_OK on success
// History:
// jstamerj 1998/07/10 19:52:56: Created
//
//-----------------------------------------------------------------------------
STDMETHODIMP CAQDefaultMessageRouter::GetNextHopFree(
IN LPSTR szDestinationAddressType,
IN LPSTR szDestinationAddress,
IN LPSTR szConnectorName,
IN LPSTR szRouteAddressType,
IN LPSTR szRouteAddress,
IN LPSTR szRouteAddressClass)
{
//
// The only string necessary to free is szRouteAddress
//
if(szRouteAddress && (szRouteAddress != szDestinationAddress))
FreePv(szRouteAddress);
return S_OK;
}