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

  1. //-----------------------------------------------------------------------------
  2. //
  3. //
  4. // File: smproute.cpp
  5. //
  6. // Description:
  7. // Implementation of CSimpleMessageRouter.
  8. //
  9. // Author: Mike Swafford (MikeSwa)
  10. //
  11. // History:
  12. // 5/20/98 - MikeSwa Created
  13. //
  14. // Copyright (C) 1998 Microsoft Corporation
  15. //
  16. //-----------------------------------------------------------------------------
  17. #include "aqprecmp.h"
  18. #include "smproute.h"
  19. #include "domcfg.h"
  20. #ifdef AQ_DEFAULT_MESSAGE_ROUTER_DEBUG
  21. #undef AQ_DEFAULT_MESSAGE_ROUTER_DEBUG
  22. #endif //AQ_DEFAULT_MESSAGE_ROUTER_DEBUG
  23. //If you are interested is using the default router to test how AQ handles
  24. //multiple message types and schedule ID's, the uncomment the following
  25. //#define AQ_DEFAULT_MESSAGE_ROUTER_DEBUG
  26. //---[ CAQDefaultMessageRouter::CAQDefaultMessageRouter ]----------------------
  27. //
  28. //
  29. // Description:
  30. // Constructor for CSimpleMessageRouter
  31. // Parameters:
  32. // pguid - pointer to GUID to use to identify self
  33. // Returns:
  34. // -
  35. // History:
  36. // 5/20/98 - MikeSwa Created
  37. //
  38. //-----------------------------------------------------------------------------
  39. CAQDefaultMessageRouter::CAQDefaultMessageRouter(GUID *pguid, CAQSvrInst *paqinst)
  40. {
  41. _ASSERT(paqinst);
  42. m_dwSignature = AQ_DEFAULT_ROUTER_SIG;
  43. m_cPeakReferences = 1;
  44. ZeroMemory(&m_rgcMsgTypeReferences, NUM_MESSAGE_TYPES*sizeof(DWORD));
  45. if (pguid)
  46. memcpy(&m_guid, pguid, sizeof(GUID));
  47. else
  48. ZeroMemory(&m_guid, sizeof(GUID));
  49. m_dwCurrentReference = 0;
  50. m_paqinst = paqinst;
  51. m_paqinst->AddRef();
  52. }
  53. //---[ CAQDefaultMessageRouter::~CAQDefaultMessageRouter ]---------------------
  54. //
  55. //
  56. // Description:
  57. // Destructor for CAQDefaultMessageRouter. Will assert that all message
  58. // types have been release correctly
  59. // Parameters:
  60. // -
  61. // Returns:
  62. // -
  63. // History:
  64. // 5/21/98 - MikeSwa Created
  65. //
  66. //-----------------------------------------------------------------------------
  67. CAQDefaultMessageRouter::~CAQDefaultMessageRouter()
  68. {
  69. m_paqinst->Release();
  70. for (int i = 0; i < NUM_MESSAGE_TYPES; i++)
  71. _ASSERT((0 == m_rgcMsgTypeReferences[i]) && "Message Types were not released");
  72. }
  73. //---[ CAQDefaultMessageRouter::GetTransportSinkID ]---------------------------
  74. //
  75. //
  76. // Description:
  77. // Returns GUID id for this messager router interface
  78. // Parameters:
  79. // -
  80. // Returns:
  81. // GUID for this IMessageRouter
  82. // History:
  83. // 5/20/98 - MikeSwa Created
  84. //
  85. //-----------------------------------------------------------------------------
  86. GUID CAQDefaultMessageRouter::GetTransportSinkID()
  87. {
  88. return m_guid;
  89. }
  90. //---[ CAQDefaultMessageRouter::GetMessageType ]-------------------------------
  91. //
  92. //
  93. // Description:
  94. // Wrapper for routing get-message-type event.
  95. // Parameters:
  96. // IN pIMailMsg IMailMsgProperties of message to classify
  97. // OUT pdwMsgType DWORD message type of message
  98. // Returns:
  99. // S_OK on success
  100. // failure code from routing event
  101. // History:
  102. // 5/19/98 - MikeSwa Created
  103. //
  104. //-----------------------------------------------------------------------------
  105. HRESULT CAQDefaultMessageRouter::GetMessageType(
  106. IN IMailMsgProperties *pIMailMsg,
  107. OUT DWORD *pdwMessageType)
  108. {
  109. HRESULT hr = S_OK;
  110. DWORD dwMessageType = InterlockedIncrement((PLONG) &m_dwCurrentReference);
  111. _ASSERT(pdwMessageType);
  112. #ifdef AQ_DEFAULT_MESSAGE_ROUTER_DEBUG
  113. //For debug versions we will autostress ourselves by generating msg types
  114. //simulate failures
  115. if (0 == (dwMessageType % NUM_MESSAGE_TYPES))
  116. return E_FAIL;
  117. dwMessageType %= NUM_MESSAGE_TYPES;
  118. #else
  119. dwMessageType = 0;
  120. #endif //AQ_DEFAULT_MESSAGE_ROUTER_DEBUG
  121. InterlockedIncrement((PLONG) &m_rgcMsgTypeReferences[dwMessageType]);
  122. *pdwMessageType = dwMessageType;
  123. return hr;
  124. }
  125. //---[ CAQDefaultMessageRouter::ReleaseMessageType ]---------------------------
  126. //
  127. //
  128. // Description:
  129. // Wrapper for ReiReleaseMessageType... releases references to message
  130. // type returned by HrGetMessageType.
  131. // Parameters:
  132. // IN dwMessageType Msg type (as return by HrGetNextMessage) to release
  133. // IN dwReleaseCount Number of references to release
  134. // Returns:
  135. // S_OK on success
  136. // History:
  137. // 5/19/98 - MikeSwa Created
  138. //
  139. //-----------------------------------------------------------------------------
  140. HRESULT CAQDefaultMessageRouter::ReleaseMessageType(
  141. IN DWORD dwMessageType,
  142. IN DWORD dwReleaseCount)
  143. {
  144. HRESULT hr = S_OK;
  145. _ASSERT(dwMessageType < NUM_MESSAGE_TYPES);
  146. _ASSERT(m_rgcMsgTypeReferences[dwMessageType]);
  147. _ASSERT(m_rgcMsgTypeReferences[dwMessageType] >= dwReleaseCount);
  148. _ASSERT(0 == (dwReleaseCount & 0x80000000)); //non-negative
  149. InterlockedExchangeAdd((PLONG) &m_rgcMsgTypeReferences[dwMessageType], -1 * (LONG) dwReleaseCount);
  150. return hr;
  151. }
  152. //---[ CAQDefaultMessageRouter::GetNextHop ]------------------------------------
  153. //
  154. //
  155. // Description:
  156. // Wrapper for routing ReiGetNextHop. Returns the <domain, schedule id>
  157. // pair for the next hop link
  158. // Parameters:
  159. //
  160. // Returns:
  161. // S_OK on success
  162. // History:
  163. // 5/19/98 - MikeSwa Created
  164. //
  165. //-----------------------------------------------------------------------------
  166. HRESULT CAQDefaultMessageRouter::GetNextHop(
  167. IN LPSTR szDestinationAddressType,
  168. IN LPSTR szDestinationAddress,
  169. IN DWORD dwMessageType,
  170. OUT LPSTR *pszRouteAddressType,
  171. OUT LPSTR *pszRouteAddress,
  172. OUT LPDWORD pdwScheduleID,
  173. OUT LPSTR *pszRouteAddressClass,
  174. OUT LPSTR *pszConnectorName,
  175. OUT LPDWORD pdwNextHopType)
  176. {
  177. HRESULT hr = S_OK;
  178. CInternalDomainInfo *pIntDomainInfo = NULL;
  179. _ASSERT(dwMessageType < NUM_MESSAGE_TYPES);
  180. _ASSERT(!lstrcmpi(MTI_ROUTING_ADDRESS_TYPE_SMTP, szDestinationAddressType));
  181. _ASSERT(szDestinationAddress);
  182. _ASSERT(pdwNextHopType);
  183. _ASSERT(pszConnectorName);
  184. _ASSERT(pszRouteAddressType);
  185. _ASSERT(pszRouteAddress);
  186. _ASSERT(pszRouteAddressClass);
  187. //For now, we will use essentially non-routed behavior... every thing will
  188. //go it's own link, and will use the same schedule ID. No address class
  189. //will be returned.
  190. *pdwNextHopType = MTI_NEXT_HOP_TYPE_EXTERNAL_SMTP;
  191. #ifdef AQ_DEFAULT_MESSAGE_ROUTER_DEBUG
  192. //Use m_dwCurrentReference to randomize schedule Id
  193. *pdwScheduleID = m_dwCurrentReference & 0x00000002;
  194. #else //retail build
  195. *pdwScheduleID = 0;
  196. #endif //AQ_DEFAULT_MESSAGE_ROUTER_DEBUG
  197. pszConnectorName = NULL;
  198. *pszRouteAddressType = MTI_ROUTING_ADDRESS_TYPE_SMTP;
  199. *pszRouteAddressClass = NULL;
  200. #ifdef AQ_DEFAULT_MESSAGE_ROUTER_DEBUG
  201. //Get smarthost for this domain if stressing routing
  202. hr = m_paqinst->HrGetInternalDomainInfo( strlen(szDestinationAddress),
  203. szDestinationAddress, &pIntDomainInfo);
  204. if (FAILED(hr))
  205. goto Exit;
  206. if (pIntDomainInfo->m_DomainInfo.szSmartHostDomainName)
  207. {
  208. //smart host exists... use it
  209. *pszRouteAddress = (LPSTR) pvMalloc(sizeof(CHAR) *
  210. (pIntDomainInfo->m_DomainInfo.cbSmartHostDomainNameLength+1));
  211. if (!*pszRouteAddress)
  212. {
  213. hr = E_OUTOFMEMORY;
  214. goto Exit;
  215. }
  216. lstrcpy(*pszRouteAddress, pIntDomainInfo->m_DomainInfo.szSmartHostDomainName);
  217. }
  218. else
  219. {
  220. *pszRouteAddress = szDestinationAddress;
  221. }
  222. Exit:
  223. #else //AQ_DEFAULT_MESSAGE_ROUTER_DEBUG
  224. *pszRouteAddress = szDestinationAddress;
  225. #endif //AQ_DEFAULT_MESSAGE_ROUTER_DEBUG
  226. if (pIntDomainInfo)
  227. pIntDomainInfo->Release();
  228. return hr;
  229. }
  230. //---[ CAQDefaultMessageRouter::GetNextHopFree ]------------------------------------
  231. //
  232. //
  233. // Description:
  234. // Wrapper for routing ReiGetNextHopFree.
  235. // Free's the strings allocated in GetNextHop
  236. // NOTE: szDestinationAddressType/szDestinationAddress will never
  237. // be free'd. They are arguments as an optimization trick (to
  238. // avoid alloc/freeing when szDestinationAddress=szRouteAddress)
  239. //
  240. // Parameters:
  241. // szDestinationAddressType: DestinationAddressType passed into GetNextHopF
  242. // szDestinationAddress: DestinationAddress passed into GetNextHop
  243. //
  244. // Returns:
  245. // S_OK on success
  246. // History:
  247. // jstamerj 1998/07/10 19:52:56: Created
  248. //
  249. //-----------------------------------------------------------------------------
  250. STDMETHODIMP CAQDefaultMessageRouter::GetNextHopFree(
  251. IN LPSTR szDestinationAddressType,
  252. IN LPSTR szDestinationAddress,
  253. IN LPSTR szConnectorName,
  254. IN LPSTR szRouteAddressType,
  255. IN LPSTR szRouteAddress,
  256. IN LPSTR szRouteAddressClass)
  257. {
  258. //
  259. // The only string necessary to free is szRouteAddress
  260. //
  261. if(szRouteAddress && (szRouteAddress != szDestinationAddress))
  262. FreePv(szRouteAddress);
  263. return S_OK;
  264. }