Source code of Windows XP (NT5)
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.

2640 lines
86 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1999 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: Receive.cpp
  6. * Content: This file contains code which receives indications of incoming data
  7. * from a ServiceProvider, cracks the data, and handles it appropriately.
  8. * History:
  9. * Date By Reason
  10. * ==== == ======
  11. * 11/06/98 ejs Created
  12. * 07/01/2000 masonb Assumed Ownership
  13. *
  14. ****************************************************************************/
  15. #include "dnproti.h"
  16. #include <tchar.h>
  17. #include <stdio.h>
  18. // local protos
  19. BOOL CancelFrame(PEPD, BYTE, DWORD tNow);
  20. VOID CompleteSends(PEPD);
  21. VOID DropReceive(PEPD, PRCD);
  22. HRESULT IndicateReceive(PSPD, PSPIE_DATA);
  23. HRESULT IndicateConnect(PSPD, PSPIE_CONNECT);
  24. HRESULT ProcessEnumQuery( PSPD, PSPIE_QUERY );
  25. HRESULT ProcessQueryResponse( PSPD, PSPIE_QUERYRESPONSE );
  26. VOID ProcessConnectedResponse(PSPD, PEPD, PCFRAME, DWORD);
  27. VOID ProcessConnectRequest(PSPD, PEPD, PCFRAME);
  28. VOID ProcessEndOfStream(PEPD);
  29. VOID ProcessListenStatus(PSPD, PSPIE_LISTENSTATUS);
  30. VOID ProcessConnectAddressInfo(PSPD, PSPIE_CONNECTADDRESSINFO);
  31. VOID ProcessEnumAddressInfo(PSPD, PSPIE_ENUMADDRESSINFO);
  32. VOID ProcessListenAddressInfo(PSPD, PSPIE_LISTENADDRESSINFO);
  33. VOID ProcessSendMask(PEPD, BYTE, ULONG, ULONG, DWORD tNow);
  34. VOID ProcessSPDisconnect(PSPD, PSPIE_DISCONNECT);
  35. VOID ReceiveInOrderFrame(PEPD, PRCD);
  36. VOID ReceiveOutOfOrderFrame(PEPD, PRCD, ULONG);
  37. HRESULT CrackCommand(PSPD, PEPD, PSPRECEIVEDBUFFER, DWORD);
  38. HRESULT CrackDataFrame(PSPD, PEPD, PSPRECEIVEDBUFFER, DWORD);
  39. /*
  40. ** Indicate Receive
  41. **
  42. ** Service Provider calls this entry when data arrives on the network.
  43. ** We will quickly validate the frame and then figure what to do with it...
  44. **
  45. ** Poll/Response activity should be handled before data is indicated to
  46. ** clients. We want to measure the network latency up to delivery, not including
  47. ** delivery.
  48. */
  49. #undef DPF_MODNAME
  50. #define DPF_MODNAME "DNSP_IndicateEvent"
  51. HRESULT WINAPI DNSP_IndicateEvent(IDP8SPCallback *pIDNSP, SP_EVENT_TYPE Opcode, PVOID DataBlock)
  52. {
  53. PSPD pSPD = (PSPD) pIDNSP;
  54. ASSERT_SPD(pSPD);
  55. switch(Opcode)
  56. {
  57. case SPEV_DATA:
  58. return IndicateReceive(pSPD, (PSPIE_DATA) DataBlock);
  59. case SPEV_CONNECT:
  60. return IndicateConnect(pSPD, (PSPIE_CONNECT) DataBlock);
  61. case SPEV_ENUMQUERY:
  62. return ProcessEnumQuery( pSPD, (PSPIE_QUERY) DataBlock );
  63. case SPEV_QUERYRESPONSE:
  64. return ProcessQueryResponse( pSPD, (PSPIE_QUERYRESPONSE) DataBlock );
  65. case SPEV_DISCONNECT:
  66. ProcessSPDisconnect(pSPD, (PSPIE_DISCONNECT) DataBlock);
  67. break;
  68. case SPEV_LISTENSTATUS:
  69. ProcessListenStatus(pSPD, (PSPIE_LISTENSTATUS) DataBlock);
  70. break;
  71. case SPEV_LISTENADDRESSINFO:
  72. ProcessListenAddressInfo(pSPD, (PSPIE_LISTENADDRESSINFO) DataBlock);
  73. break;
  74. case SPEV_CONNECTADDRESSINFO:
  75. ProcessConnectAddressInfo(pSPD, (PSPIE_CONNECTADDRESSINFO) DataBlock);
  76. break;
  77. case SPEV_ENUMADDRESSINFO:
  78. ProcessEnumAddressInfo(pSPD, (PSPIE_ENUMADDRESSINFO) DataBlock);
  79. break;
  80. //
  81. // SP passed something unexpected
  82. //
  83. default:
  84. DPFX(DPFPREP,0, "Unknown Event indicated by SP");
  85. ASSERT(0);
  86. break;
  87. }
  88. return DPN_OK;
  89. }
  90. /*
  91. ** Indicate Connect
  92. **
  93. ** This event is indicated for both calling and listening sides. The
  94. ** calling side will do most of its work when the SP Connect call completes
  95. ** and the listening side will do most of its work when the CONNECT frame
  96. ** gets delivered. All we do here is allocate the EPD and attach it to the
  97. ** MSD (for calling case)
  98. **
  99. ** Since we have a connect protocol, there will always be a CONNECT
  100. ** frame following closely on the heels of this indication. Therefore,
  101. ** there is not a whole lot of stuff that we need to do here. We will
  102. ** allocate the EndPoint and leave it dormant.
  103. **
  104. ** Synchronization Issue: We have decided that if an SP Listen command is cancelled,
  105. ** the cancel call will not complete until all ConnectIndications have returned from the
  106. ** protocol. This means that we are GUARANTEED that the Listen command in the context
  107. ** will be valid throughout this call. This is important because now we can add a reference
  108. ** to the Listen's MSD here and now and we will know that it wont disappear on us before we
  109. ** do it. Truth, however, is that there will be a race until SP fixes itself to follow
  110. ** this behavior.
  111. */
  112. #undef DPF_MODNAME
  113. #define DPF_MODNAME "IndicateConnect"
  114. HRESULT IndicateConnect(PSPD pSPD, PSPIE_CONNECT pConnData)
  115. {
  116. PEPD pEPD;
  117. PMSD pMSD;
  118. pMSD = (PMSD) pConnData->pCommandContext;
  119. ASSERT_MSD(pMSD);
  120. ASSERT(pMSD->pSPD == pSPD);
  121. DPFX(DPFPREP,DPF_CALLIN_LVL, "Parameters: pSPD[%p], pConnData[%p] - pMSD[%p]", pSPD, pConnData, pMSD);
  122. Lock(&pMSD->CommandLock);
  123. LOCK_MSD(pMSD, "EPD Ref"); // Place a reference on the command object. This prevents it from
  124. // going away during the Connect Protocol, an assumption which simplifies
  125. // life extraordinarily. We will want to ASSERT this fact, however, to make
  126. // sure that SP is playing by our rules.
  127. if ((pMSD->CommandID != COMMAND_ID_CONNECT) && (pMSD->CommandID != COMMAND_ID_LISTEN))
  128. {
  129. DPFX(DPFPREP,1, "Connect Rejected - CommandID is not Connect or Listen, returning DPNERR_ABORTED, pMSD[%p]", pMSD);
  130. RELEASE_MSD(pMSD, "EPD Ref"); // Releases CommandLock
  131. return DPNERR_ABORTED;
  132. }
  133. if ((pMSD->CommandID == COMMAND_ID_CONNECT) && (pMSD->pEPD != NULL))
  134. {
  135. DPFX(DPFPREP,1, "Connect Rejected - Connect command already has an endpoint, returning DPNERR_ABORTED, pMSD[%p], pEPD[%p]", pMSD, pMSD->pEPD);
  136. RELEASE_MSD(pMSD, "EPD Ref"); // Releases CommandLock
  137. return DPNERR_ABORTED;
  138. }
  139. if(pMSD->ulMsgFlags1 & MFLAGS_ONE_CANCELLED)
  140. {
  141. DPFX(DPFPREP,1, "Connect Rejected - Command is cancelled, returning DPNERR_ABORTED, pMSD[%p]", pMSD);
  142. RELEASE_MSD(pMSD, "EPD Ref"); // Releases CommandLock
  143. return DPNERR_ABORTED;
  144. }
  145. if((pEPD = NewEndPoint(pSPD, pConnData->hEndpoint)) == NULL)
  146. {
  147. DPFX(DPFPREP,0, "Failed to allocate new EPD, returning DPNERR_ABORTED, pMSD[%p]", pMSD);
  148. RELEASE_MSD(pMSD, "EPD Ref"); // Releases CommandLock
  149. return DPNERR_ABORTED; // This error will implicitly DISCONNECT from Endpoint
  150. }
  151. // Associate either the Connect or Listen with this Endpoint, this will be removed when the connection is complete.
  152. // The EPD Ref placed above will be carried around until this is NULL'd.
  153. pEPD->pCommand = pMSD;
  154. if(pMSD->CommandID == COMMAND_ID_CONNECT)
  155. {
  156. DPFX(DPFPREP,5, "INDICATE CONNECT (CALLING) -- EPD = %p, pMSD[%p]", pEPD, pMSD);
  157. pMSD->pEPD = pEPD;
  158. }
  159. else
  160. {
  161. DPFX(DPFPREP,5, "INDICATE CONNECT (LISTENING) -- EPD = %p, pMSD[%p]", pEPD, pMSD);
  162. ASSERT(pMSD->CommandID == COMMAND_ID_LISTEN);
  163. ASSERT((pEPD->ulEPFlags & EPFLAGS_LINKED_TO_LISTEN)==0);
  164. // For a Listen command, connecting endpoints are held on the blFrameList
  165. pEPD->blSPLinkage.InsertBefore( &pMSD->blFrameList);
  166. pEPD->ulEPFlags |= EPFLAGS_LINKED_TO_LISTEN;
  167. }
  168. pConnData->pEndpointContext = pEPD;
  169. Unlock(&pMSD->CommandLock);
  170. return DPN_OK;
  171. }
  172. /*
  173. ** Indicate Receive
  174. **
  175. ** A frame has been delivered by the service provider. We are Guaranteed to
  176. ** have an active Endpoint in our hash table (or else something is wrong). I have not
  177. ** decided whether I will respond to POLL bits at this high level or else let
  178. ** each handler repond in its own particular... eh... idiom.
  179. **
  180. ** Our return value controls whether SP will recycle the receive buffer, or whether
  181. ** we can keep the buffer around until we are ready to indicate it to higher levels
  182. ** later on. If we return DPN_OK then we are done with the buffer and it will be recycled.
  183. ** If we return DPNERR_PENDING then we may hold on to the buffer until we release them later.
  184. */
  185. #undef DPF_MODNAME
  186. #define DPF_MODNAME "IndicateReceive"
  187. #define MINDATAFRAMESIZE (sizeof(DFRAME))
  188. #define MINCMDFRAMESIZE (MIN(sizeof(CFRAME), sizeof(SACKFRAME8)))
  189. HRESULT IndicateReceive(PSPD pSPD, PSPIE_DATA pDataBlock)
  190. {
  191. PEPD pEPD = static_cast<PEPD>( pDataBlock->pEndpointContext );
  192. HRESULT hr;
  193. PPacketHeader pFrame = (PPacketHeader) pDataBlock->pReceivedData->BufferDesc.pBufferData;
  194. DWORD tNow = GETTIMESTAMP();
  195. DWORD dwDataLength = pDataBlock->pReceivedData->BufferDesc.dwBufferSize;
  196. DPFX(DPFPREP,DPF_CALLIN_LVL, "Parameters: pSPD[%p], pDataBlock[%p] - pEPD[%p]", pSPD, pDataBlock, pEPD);
  197. if(pSPD->ulSPFlags & SPFLAGS_TERMINATING)
  198. {
  199. DPFX(DPFPREP,1, "(%p) SP is terminating, returning DPN_OK, pSPD[%p]", pEPD, pSPD);
  200. return DPN_OK;
  201. }
  202. ASSERT_EPD(pEPD);
  203. ASSERT(pEPD->pSPD == pSPD);
  204. if(LOCK_EPD(pEPD, "LOCK (IND RECEIVE)") == 0)
  205. {
  206. ASSERT(0);
  207. DPFX(DPFPREP,1, "(%p) Rejecting receive on unreferenced EPD, returning DPN_OK", pEPD);
  208. return DPN_OK;
  209. }
  210. pEPD->tLastPacket = tNow; // Track last time each guy writes to us
  211. #ifdef DEBUG
  212. // copy this frame to buffer in EPD so we can look after a break.
  213. DWORD dwLen = MIN(32, pDataBlock->pReceivedData->BufferDesc.dwBufferSize);
  214. memcpy(pEPD->LastPacket, pDataBlock->pReceivedData->BufferDesc.pBufferData, dwLen);
  215. #endif
  216. // A valid data packet is one that meets the length requirements and has the Data flag set.
  217. // All other flags are allowed on a data frame (NOTE: even PACKET_COMMAND_CFRAME is allowed
  218. // as it shares its value with PACKET_COMMAND_USER_2).
  219. if( (dwDataLength >= MINDATAFRAMESIZE) && // Validate the length first
  220. (pFrame->bCommand & PACKET_COMMAND_DATA)) // Data goes this way
  221. {
  222. hr = CrackDataFrame(pSPD, pEPD, pDataBlock->pReceivedData, tNow);
  223. }
  224. else if ((dwDataLength >= MINCMDFRAMESIZE) && // Validate the length first
  225. ((pFrame->bCommand == PACKET_COMMAND_CFRAME) || // Only the CFRAME and POLL flags are allowed on a CFrame
  226. (pFrame->bCommand == (PACKET_COMMAND_CFRAME|PACKET_COMMAND_POLL))))
  227. {
  228. hr = CrackCommand(pSPD, pEPD, pDataBlock->pReceivedData, tNow);
  229. }
  230. else
  231. {
  232. DPFX(DPFPREP,1, "(%p) Received frame that is neither Command nor Data, rejecting", pEPD);
  233. DNASSERTX(FALSE, 2);
  234. RejectInvalidPacket(pEPD, FALSE); // Lock not already held
  235. hr = DPN_OK;
  236. }
  237. Lock(&pEPD->EPLock);
  238. RELEASE_EPD(pEPD, "UNLOCK (IND RCV DONE)"); // Releases EPLock
  239. // This is either DPN_OK or DPNSUCCESS_PENDING. If it is pending we have to return the buffer later.
  240. return hr;
  241. }
  242. /*
  243. ** Process Enum Query
  244. **
  245. ** A frame has been delivered by the service provider representing an enumereation
  246. ** query.
  247. */
  248. #undef DPF_MODNAME
  249. #define DPF_MODNAME "ProcessEnumQuery"
  250. HRESULT ProcessEnumQuery( PSPD pSPD, PSPIE_QUERY pQueryBlock )
  251. {
  252. MSD *pMSD;
  253. PROTOCOL_ENUM_DATA EnumData;
  254. pMSD = static_cast<MSD*>( pQueryBlock->pUserContext );
  255. ASSERT_MSD(pMSD);
  256. ASSERT(pMSD->pSPD == pSPD);
  257. DPFX(DPFPREP,DPF_CALLIN_LVL, "Parameters: pSPD[%p], pQueryBlock[%p] - pMSD[%p]", pSPD, pQueryBlock, pMSD);
  258. EnumData.pSenderAddress = pQueryBlock->pAddressSender;
  259. EnumData.pDeviceAddress = pQueryBlock->pAddressDevice;
  260. EnumData.ReceivedData.pBufferData = pQueryBlock->pReceivedData->BufferDesc.pBufferData;
  261. EnumData.ReceivedData.dwBufferSize = pQueryBlock->pReceivedData->BufferDesc.dwBufferSize;
  262. EnumData.hEnumQuery = pQueryBlock;
  263. DBG_CASSERT( sizeof( &EnumData ) == sizeof( PBYTE ) );
  264. DPFX(DPFPREP,DPF_CALLOUT_LVL, "(%p) Calling Core->IndicateEnumQuery, Core Context[%p]", pMSD, pMSD->Context);
  265. pSPD->pPData->pfVtbl->IndicateEnumQuery( pSPD->pPData->Parent,
  266. pMSD->Context,
  267. pMSD,
  268. reinterpret_cast<PBYTE>( &EnumData ),
  269. sizeof( EnumData ));
  270. return DPN_OK;
  271. }
  272. /*
  273. ** Process Query Response
  274. **
  275. ** A frame has been delivered by the service provider representing a response to an enum.
  276. */
  277. #undef DPF_MODNAME
  278. #define DPF_MODNAME "ProcessQueryResponse"
  279. HRESULT ProcessQueryResponse( PSPD pSPD, PSPIE_QUERYRESPONSE pQueryResponseBlock)
  280. {
  281. MSD *pMSD;
  282. PROTOCOL_ENUM_RESPONSE_DATA EnumResponseData;
  283. pMSD = static_cast<MSD*>( pQueryResponseBlock->pUserContext );
  284. ASSERT_MSD(pMSD);
  285. ASSERT(pMSD->pSPD == pSPD);
  286. DPFX(DPFPREP,DPF_CALLIN_LVL, "Parameters: pSPD[%p], pQueryResponseBlock[%p] - pMSD[%p]", pSPD, pQueryResponseBlock, pMSD);
  287. EnumResponseData.pSenderAddress = pQueryResponseBlock->pAddressSender;
  288. EnumResponseData.pDeviceAddress = pQueryResponseBlock->pAddressDevice;
  289. EnumResponseData.ReceivedData.pBufferData = pQueryResponseBlock->pReceivedData->BufferDesc.pBufferData;
  290. EnumResponseData.ReceivedData.dwBufferSize = pQueryResponseBlock->pReceivedData->BufferDesc.dwBufferSize;
  291. EnumResponseData.dwRoundTripTime = pQueryResponseBlock->dwRoundTripTime;
  292. DBG_CASSERT( sizeof( &EnumResponseData ) == sizeof( PBYTE ) );
  293. DPFX(DPFPREP,DPF_CALLOUT_LVL, "(%p) Calling Core->IndicateEnumResponse, Core Context[%p]", pMSD, pMSD->Context);
  294. pSPD->pPData->pfVtbl->IndicateEnumResponse( pSPD->pPData->Parent,
  295. pMSD,
  296. pMSD->Context,
  297. reinterpret_cast<PBYTE>( &EnumResponseData ),
  298. sizeof( EnumResponseData ));
  299. return DPN_OK;
  300. }
  301. // *** Called with lock held or not depending on parameter, Returns with EPLock released
  302. #undef DPF_MODNAME
  303. #define DPF_MODNAME "RejectInvalidPacket"
  304. VOID RejectInvalidPacket(PEPD pEPD, BOOL fLockHeld)
  305. {
  306. PMSD pMSD;
  307. if (!fLockHeld)
  308. {
  309. Lock(&pEPD->EPLock);
  310. }
  311. else
  312. {
  313. AssertCriticalSectionIsTakenByThisThread(&pEPD->EPLock, TRUE);
  314. }
  315. if(pEPD->ulEPFlags & EPFLAGS_STATE_DORMANT)
  316. {
  317. // Unlink MSD from EPD, there should always be one if we are in the DORMANT state
  318. pMSD = pEPD->pCommand;
  319. ASSERT_MSD(pMSD);
  320. if (pMSD->CommandID == COMMAND_ID_LISTEN)
  321. {
  322. pEPD->pCommand = NULL;
  323. LOCK_EPD(pEPD, "Temp Ref");
  324. DPFX(DPFPREP,1, "(%p) Received invalid frame on a dormant, listening endpoint, dropping link", pEPD);
  325. DropLink(pEPD); // This will release the EPLock
  326. // The order here is important. We call DropLink first without ever leaving the EPLock because
  327. // we need to ensure no new packets try to come in. After calling DropLink we know we stay in the
  328. // TERMINATING state until returning to the pool, so state is not an issue after that call.
  329. Lock(&pMSD->CommandLock);
  330. Lock(&pEPD->EPLock);
  331. // If a cancel on a listen comes in at the same time as this happens, it is possible that the cancel came
  332. // through and already unlinked this EPD from the Listen while we were outside the lock. If so, removing
  333. // it from the pMSD->blFrameList twice is harmless.
  334. pEPD->ulEPFlags &= ~(EPFLAGS_LINKED_TO_LISTEN);
  335. pEPD->blSPLinkage.RemoveFromList(); // Unlink EPD from Listen Queue
  336. RELEASE_EPD(pEPD, "Temp Ref"); // Releases EPLock
  337. RELEASE_MSD(pMSD, "EPD Ref"); // Releases CommandLock
  338. }
  339. else
  340. {
  341. DPFX(DPFPREP,1, "(%p) Received invalid frame on a dormant, connecting endpoint, ignoring", pEPD);
  342. Unlock(&pEPD->EPLock);
  343. }
  344. }
  345. else
  346. {
  347. DPFX(DPFPREP,1, "(%p) Received invalid frame on a non-dormant endpoint, ignoring", pEPD);
  348. Unlock(&pEPD->EPLock);
  349. }
  350. }
  351. /*
  352. ** Crack Command
  353. **
  354. ** This frame is a maintainance frame containing no user data
  355. **
  356. */
  357. #undef DPF_MODNAME
  358. #define DPF_MODNAME "CrackCommand"
  359. HRESULT CrackCommand(PSPD pSPD, PEPD pEPD, PSPRECEIVEDBUFFER pRcvBuffer, DWORD tNow)
  360. {
  361. DWORD dwDataLength = pRcvBuffer->BufferDesc.dwBufferSize;
  362. UNALIGNED ULONG *array_ptr;
  363. ULONG mask1, mask2;
  364. union
  365. {
  366. PCFRAME pCFrame;
  367. PSFBIG8 pSack;
  368. } pData;
  369. pData.pCFrame = (PCFRAME) pRcvBuffer->BufferDesc.pBufferData;
  370. switch(pData.pCFrame->bExtOpcode)
  371. {
  372. case FRAME_EXOPCODE_SACK:
  373. DPFX(DPFPREP,7, "(%p) SACK Frame Received", pEPD);
  374. Lock(&pEPD->EPLock);
  375. // Check state
  376. if(!(pEPD->ulEPFlags & EPFLAGS_STATE_CONNECTED))
  377. {
  378. DPFX(DPFPREP,1, "(%p) Received SACK on non-connected endpoint, rejecting...", pEPD);
  379. DNASSERTX(FALSE, 4);
  380. RejectInvalidPacket(pEPD, TRUE); // TRUE means lock held, returns with lock released
  381. break;
  382. }
  383. // Drop short frames (should not happen)
  384. DWORD dwRequiredLength;
  385. dwRequiredLength = sizeof(SACKFRAME8);
  386. array_ptr = pData.pSack->rgMask;
  387. if (pData.pSack->bFlags & SACK_FLAGS_SACK_MASK1)
  388. {
  389. dwRequiredLength += sizeof(DWORD);
  390. }
  391. if (pData.pSack->bFlags & SACK_FLAGS_SACK_MASK2)
  392. {
  393. dwRequiredLength += sizeof(DWORD);
  394. }
  395. if (pData.pSack->bFlags & SACK_FLAGS_SEND_MASK1)
  396. {
  397. dwRequiredLength += sizeof(DWORD);
  398. }
  399. if (pData.pSack->bFlags & SACK_FLAGS_SEND_MASK2)
  400. {
  401. dwRequiredLength += sizeof(DWORD);
  402. }
  403. if (dwDataLength < dwRequiredLength)
  404. {
  405. DPFX(DPFPREP,1, "(%p) Dropping short frame on connected link", pEPD);
  406. DNASSERTX(FALSE, 2);
  407. Unlock(&pEPD->EPLock);
  408. return DPN_OK;
  409. }
  410. if( pData.pSack->bFlags & SACK_FLAGS_RESPONSE )
  411. {
  412. DPFX(DPFPREP,7, "(%p) ACK RESP RCVD: Retry=%d, N(R)=0x%02x", pEPD, pData.pSack->bRetry, pData.pSack->bNRcv);
  413. }
  414. mask1 = pData.pSack->bFlags & SACK_FLAGS_SACK_MASK1 ? *array_ptr++ : 0;
  415. mask2 = pData.pSack->bFlags & SACK_FLAGS_SACK_MASK2 ? *array_ptr++ : 0;
  416. DPFX(DPFPREP,7, "(%p) UpdateXmitState - N(R) 0x%02x Mask 0x%08x 0x%08x", pEPD, (DWORD)pData.pSack->bNRcv, mask2, mask1);
  417. UpdateXmitState(pEPD, pData.pSack->bNRcv, mask1, mask2, tNow);
  418. mask1 = pData.pSack->bFlags & SACK_FLAGS_SEND_MASK1 ? *array_ptr++ : 0;
  419. mask2 = pData.pSack->bFlags & SACK_FLAGS_SEND_MASK2 ? *array_ptr++ : 0;
  420. if(mask1 | mask2)
  421. {
  422. DPFX(DPFPREP,7, "(%p) Processing Send Mask N(S) 0x%02x Mask 0x%08x 0x%08x", pEPD, (DWORD) pData.pSack->bNSeq, mask2, mask1);
  423. ProcessSendMask(pEPD, pData.pSack->bNSeq, mask1, mask2, tNow);
  424. }
  425. if( (!pEPD->blCompleteList.IsEmpty()) && ((pEPD->ulEPFlags & EPFLAGS_IN_RECEIVE_COMPLETE) == FALSE))
  426. {
  427. DPFX(DPFPREP,8, "(%p) Completing Receives...", pEPD);
  428. pEPD->ulEPFlags |= EPFLAGS_IN_RECEIVE_COMPLETE; // ReceiveComplete will clear this flag when done
  429. ReceiveComplete(pEPD); // Deliver the goods, returns with EPLock released
  430. }
  431. else
  432. {
  433. Unlock(&pEPD->EPLock);
  434. }
  435. DPFX(DPFPREP,8, "(%p) Completing Sends...", pEPD);
  436. CompleteSends(pEPD);
  437. break;
  438. case FRAME_EXOPCODE_CONNECT:
  439. DPFX(DPFPREP,7, "(%p) CONNECT Frame Received", pEPD);
  440. if (dwDataLength < sizeof(CFRAME))
  441. {
  442. DPFX(DPFPREP,1, "(%p) Received short CONNECT frame, rejecting...", pEPD);
  443. DNASSERTX(FALSE, 2);
  444. RejectInvalidPacket(pEPD, FALSE); // FALSE means lock not held
  445. return DPN_OK;
  446. }
  447. ProcessConnectRequest(pSPD, pEPD, pData.pCFrame);
  448. break;
  449. case FRAME_EXOPCODE_CONNECTED:
  450. DPFX(DPFPREP,7, "(%p) CONNECTED Frame Received", pEPD);
  451. if (dwDataLength < sizeof(CFRAME))
  452. {
  453. DPFX(DPFPREP,1, "(%p) Received short CONNECTED frame, rejecting...", pEPD);
  454. DNASSERTX(FALSE, 2);
  455. RejectInvalidPacket(pEPD, FALSE); // FALSE means lock not held
  456. return DPN_OK;
  457. }
  458. ProcessConnectedResponse(pSPD, pEPD, pData.pCFrame, tNow);
  459. break;
  460. default:
  461. DPFX(DPFPREP,1, "(%p) Received invalid CFrame, rejecting...", pEPD);
  462. DNASSERTX(FALSE, 2);
  463. RejectInvalidPacket(pEPD, FALSE); // FALSE means lock not held
  464. break;
  465. }
  466. return DPN_OK;
  467. }
  468. /*
  469. ** Crack Data Frame
  470. **
  471. ** In addition to delivering data contained in the frame, we also must
  472. ** use the included state info to drive the transmission process. We will update
  473. ** our link state according to this info and see if we need to put this session
  474. ** back into the sending pipeline.
  475. **
  476. ** Of course, data will only be delivered if we have completed an entire message.
  477. **
  478. ** CRITICAL SECTION NOTE -- It might seem rather lavish the way we hold the EPD->StateLock
  479. ** thru this entire routine, but anything less would require an obscene level of complexity
  480. ** to keep ironed out. This is why I defer all ReceiveIndications and buffer mappings until
  481. ** the end of the routine when the Lock can be released.
  482. **
  483. */
  484. #undef DPF_MODNAME
  485. #define DPF_MODNAME "CrackDataFrame"
  486. HRESULT CrackDataFrame(PSPD pSPD, PEPD pEPD, PSPRECEIVEDBUFFER pRcvBuffer, DWORD tNow)
  487. {
  488. DWORD dwDataLength = pRcvBuffer->BufferDesc.dwBufferSize;
  489. PDFBIG pFrame = (PDFBIG) (pRcvBuffer->BufferDesc.pBufferData);
  490. PRCD pRCD;
  491. ULONG bit;
  492. UINT count;
  493. UNALIGNED ULONG *array_ptr;
  494. ULONG MaskArray[4];
  495. UINT header_size;
  496. ULONG mask;
  497. Lock(&pEPD->EPLock);
  498. // Data on an unconnected link
  499. //
  500. // There are two possibilities (as I see it today). Either we have dropped our link because partner
  501. // went silent, but now he has started sending again. OR We have disconnected and are now reconnecting
  502. // but there are some old data frames bouncing around (less likely).
  503. //
  504. // If we have dropped and partner is just figuring it out, we must kill the endpoint or else it will hang
  505. // around forever after partner stops bothering us. We can help out partner by sending him a DISC frame
  506. // so he knows that we arent playing anymore, buts its not technically necessary.
  507. //
  508. // In the second case, we do not want to close the EP because that will crush the session startup that
  509. // is supposedly in progress. Therefore, if we are not in a DORMANT state, then we know a session
  510. // startup is in progress, and we will let the EP remain open.
  511. if(!(pEPD->ulEPFlags & EPFLAGS_STATE_CONNECTED))
  512. {
  513. DPFX(DPFPREP,1, "(%p) Received data on non-connected endpoint, rejecting...", pEPD);
  514. DNASSERTX(FALSE, 4);
  515. RejectInvalidPacket(pEPD, TRUE); // TRUE means lock held, returns with lock released
  516. return DPN_OK; // do not accept data before we have connected
  517. }
  518. BYTE bSeq = pFrame->bSeq;
  519. DPFX(DPFPREP,7, "(%p) Data Frame Arrives Seq=%x; N(R)=%x", pEPD, bSeq, pEPD->bNextReceive);
  520. // Make sure that new frame is within our receive window
  521. if((BYTE)(bSeq - pEPD->bNextReceive) >= (BYTE) MAX_FRAME_OFFSET)
  522. {
  523. DPFX(DPFPREP,1, "(%p) Rejecting frame that is out of receive window SeqN=%x, N(R)=%x", pEPD, bSeq, pEPD->bNextReceive);
  524. pEPD->ulEPFlags |= EPFLAGS_DELAY_ACKNOWLEDGE;
  525. if(pFrame->bCommand & PACKET_COMMAND_POLL)
  526. {
  527. // Is he asking for an immediate response
  528. DPFX(DPFPREP,7, "(%p) Sending Ack Frame", pEPD);
  529. SendAckFrame(pEPD, 1); // This unlocks the EPLock since param 2 is 1
  530. }
  531. else if(pEPD->DelayedAckTimer == 0)
  532. {
  533. // If timer is not running better start it now
  534. LOCK_EPD(pEPD, "LOCK (DelayedAckTimer)"); // Bump RefCnt for new timer
  535. DPFX(DPFPREP,7, "(%p) Setting Delayed Ack Timer", pEPD);
  536. SetMyTimer(SHORT_DELAYED_ACK_TIMEOUT, 0, DelayedAckTimeout, (PVOID) pEPD, &pEPD->DelayedAckTimer, &pEPD->DelayedAckTimerUnique);
  537. Unlock(&pEPD->EPLock);
  538. }
  539. else
  540. {
  541. Unlock(&pEPD->EPLock);
  542. }
  543. return DPN_OK;
  544. }
  545. DWORD dwRequiredLength = sizeof(DFRAME);
  546. if (pFrame->bControl & PACKET_CONTROL_SACK_MASK1)
  547. {
  548. dwRequiredLength += sizeof(DWORD);
  549. }
  550. if (pFrame->bControl & PACKET_CONTROL_SACK_MASK2)
  551. {
  552. dwRequiredLength += sizeof(DWORD);
  553. }
  554. if (pFrame->bControl & PACKET_CONTROL_SEND_MASK1)
  555. {
  556. dwRequiredLength += sizeof(DWORD);
  557. }
  558. if (pFrame->bControl & PACKET_CONTROL_SEND_MASK2)
  559. {
  560. dwRequiredLength += sizeof(DWORD);
  561. }
  562. if (dwDataLength < dwRequiredLength)
  563. {
  564. DPFX(DPFPREP,1, "(%p) Dropping short frame on connected link", pEPD);
  565. DNASSERTX(FALSE, 2);
  566. Unlock(&pEPD->EPLock);
  567. return DPN_OK;
  568. }
  569. // Determine how large the variable length header is
  570. mask = (pFrame->bControl & PACKET_CONTROL_VARIABLE_MASKS) / PACKET_CONTROL_SACK_MASK1;
  571. if(mask)
  572. {
  573. array_ptr = pFrame->rgMask;
  574. for(count = 0; count < 4; count++, mask >>= 1)
  575. {
  576. MaskArray[count] = (mask & 1) ? *array_ptr++ : 0;
  577. }
  578. header_size = (UINT) ((UINT_PTR) array_ptr - (UINT_PTR) pFrame);
  579. // See if this frame Acknowledges any of our outstanding data
  580. DPFX(DPFPREP,7, "(%p) UpdateXmitState - N(R) 0x%02x Mask 0x%08x 0x%08x", pEPD, (DWORD)pFrame->bNRcv, MaskArray[1], MaskArray[0]);
  581. UpdateXmitState(pEPD, pFrame->bNRcv, MaskArray[0], MaskArray[1], tNow); // Do this before taking StateLock
  582. // Determine if there is a SendMask in this frame which identifies dropped frames as unreliable
  583. if(pFrame->bControl & (PACKET_CONTROL_SEND_MASK1 | PACKET_CONTROL_SEND_MASK2))
  584. {
  585. DPFX(DPFPREP,7, "(%p) Processing Send Mask N(S) 0x%02x Mask 0x%08x 0x%08x", pEPD, (DWORD)pFrame->bSeq, MaskArray[3], MaskArray[2]);
  586. ProcessSendMask(pEPD, pFrame->bSeq, MaskArray[2], MaskArray[3], tNow);
  587. // NOTE: ProcessSendMask may have advanced N(R)
  588. // Re-verify that the new frame is within our receive window
  589. if((BYTE)(bSeq - pEPD->bNextReceive) >= (BYTE) MAX_FRAME_OFFSET)
  590. {
  591. DPFX(DPFPREP,1, "(%p) ProcessSendMask advanced N(R) such that the current frame is out of window, rejecting receive, N(R)=0x%02x, Seq=0x%02x", pEPD, (DWORD)pEPD->bNextReceive, (DWORD)pFrame->bSeq);
  592. Unlock(&pEPD->EPLock);
  593. return DPN_OK;
  594. }
  595. }
  596. }
  597. else
  598. {
  599. header_size = sizeof(DFRAME);
  600. DPFX(DPFPREP,7, "(%p) UpdateXmitState - N(R) 0x%02x No Mask", pEPD, (DWORD)pFrame->bNRcv);
  601. UpdateXmitState(pEPD, pFrame->bNRcv, 0, 0, tNow); // Do this before taking StateLock
  602. }
  603. // We can receive this frame. Copy relevant info into Receive descriptor
  604. if((pRCD = static_cast<PRCD>( RCDPool->Get(RCDPool) )) == NULL)
  605. {
  606. DPFX(DPFPREP,0, "(%p) Failed to allocate new RCD", pEPD);
  607. Unlock(&pEPD->EPLock);
  608. return DPN_OK;
  609. }
  610. pEPD->ulEPFlags |= EPFLAGS_DELAY_ACKNOWLEDGE; // State has changed. Make sure it gets sent.
  611. pRCD->bSeq = bSeq;
  612. pRCD->bFrameFlags = pFrame->bCommand;
  613. pRCD->bFrameControl = pFrame->bControl;
  614. pRCD->pbData = (PBYTE) (((PBYTE) pFrame) + header_size);
  615. pRCD->uiDataSize = dwDataLength - header_size;
  616. pRCD->tTimestamp = tNow;
  617. pRCD->pRcvBuff = pRcvBuffer;
  618. // Update our receiving state info.
  619. //
  620. // RCDs go onto one of two queues. If it is the next numbered (expected) frame then it is
  621. // placed on the ReceiveList (in EPD). If this frame completes a message it can now be
  622. // indicated. If this frame fills a hole left by previous frames then a condensation with
  623. // the second list must occur.
  624. // If it is not the next numbered frame then it is placed, in order, on the MisOrdered frame
  625. // list, and the bitmask is updated.
  626. //
  627. // Condensation of lists is performed by testing the LSB of the ReceiveMask. Each time LSB is set,
  628. // the first frame on the list can be moved to the ReceiveList, and the mask is shifted right.
  629. // As each frame is moved to the ReceiveList, the EOM flag must be checked for and if set, then
  630. // everything on the ReceiveList should be moved to the CompleteList for indication to the user.
  631. BOOL fPoll = pFrame->bCommand & PACKET_COMMAND_POLL;
  632. BOOL fCorrelate = pFrame->bControl & PACKET_CONTROL_CORRELATE;
  633. if(bSeq == pEPD->bNextReceive)
  634. {
  635. // Frame is the next expected # in sequence
  636. DPFX(DPFPREP,8, "(%p) Receiving In-Order Frame, pRCD[%p]", pEPD, pRCD);
  637. ReceiveInOrderFrame(pEPD, pRCD); // Build frame into message AND move adjacent frames off OddFrameList
  638. // NOTE: ReceiveInOrderFrame may have caused the frame to be freed via DropReceive
  639. // so we absolutely must not use pFrame past this point!
  640. // See if we need to respond right away...
  641. //
  642. // Because there are lots of way to generate POLL bits (full window, empty queue, poll count) we sometimes find ourselves
  643. // generating too much dedicated ack-traffic. Therefore, we will treat the POLL not as Respond-Immediately but instead as
  644. // Respond-Soon. We will not wait the full Delayed_Ack_Timeout interval but we will wait long enough to allow a quick piggyback
  645. // response (say 5ms) (we may want this longer on a slow connection...)
  646. // Is he asking for an instant response?
  647. if(fCorrelate)
  648. {
  649. DPFX(DPFPREP,7, "(%p) Sending Ack Frame", pEPD);
  650. SendAckFrame(pEPD, 0); // Send Ack w/timing info
  651. }
  652. // Is he asking for a response soon?
  653. else if(fPoll)
  654. {
  655. if(pEPD->ulEPFlags & EPFLAGS_USE_POLL_DELAY)
  656. {
  657. if(pEPD->DelayedAckTimer != NULL)
  658. {
  659. DPFX(DPFPREP,7, "(%p) Cancelling Delayed Ack Timer", pEPD);
  660. if(CancelMyTimer(pEPD->DelayedAckTimer, pEPD->DelayedAckTimerUnique)!= DPN_OK)
  661. {
  662. DPFX(DPFPREP,7, "(%p) Cancelling Delayed Ack Timer Failed", pEPD);
  663. LOCK_EPD(pEPD, "LOCK (re-start delayed ack timer)");
  664. }
  665. }
  666. else
  667. {
  668. LOCK_EPD(pEPD, "LOCK (start short delayed ack timer)");
  669. }
  670. DPFX(DPFPREP,7, "Delaying POLL RESP");
  671. pEPD->ulEPFlags |= EPFLAGS_DELAY_ACKNOWLEDGE;
  672. DPFX(DPFPREP,7, "(%p) Setting Delayed Ack Timer", pEPD);
  673. SetMyTimer(4, 4, DelayedAckTimeout, (PVOID) pEPD, &pEPD->DelayedAckTimer, &pEPD->DelayedAckTimerUnique);
  674. }
  675. else
  676. {
  677. DPFX(DPFPREP,7, "(%p) Sending Ack Frame", pEPD);
  678. SendAckFrame(pEPD, 0); // Send Ack w/timing info
  679. }
  680. }
  681. else if(pEPD->DelayedAckTimer == 0)
  682. {
  683. // If timer is not running better start it now
  684. LOCK_EPD(pEPD, "LOCK (DelayedAckTimer)"); // Bump RefCnt for timer
  685. SetMyTimer(DELAYED_ACK_TIMEOUT, 0, DelayedAckTimeout, (PVOID) pEPD, &pEPD->DelayedAckTimer, &pEPD->DelayedAckTimerUnique);
  686. }
  687. } // IF frame is in order
  688. else
  689. {
  690. // Frame arrives out of order
  691. // bit location in mask for this frame
  692. bit = (BYTE) ((bSeq - pEPD->bNextReceive) - 1);
  693. // Make sure this is not a duplicate frame
  694. if( ((bit < 32) && (pEPD->ulReceiveMask & (1 << bit))) || ((bit > 31) && (pEPD->ulReceiveMask2 & (1 << (bit - 32)))) )
  695. {
  696. DPFX(DPFPREP,7, "(%p) REJECT DUPLICATE OUT-OF-ORDER Frame Seq=%x", pEPD, bSeq);
  697. Unlock(&pEPD->EPLock);
  698. pRCD->pRcvBuff = NULL;
  699. RELEASE_RCD(pRCD);
  700. return DPN_OK;
  701. }
  702. DPFX(DPFPREP,8, "(%p) Receiving Out-of-Order Frame, pRCD[%p]", pEPD, pRCD);
  703. ReceiveOutOfOrderFrame(pEPD, pRCD, bit);
  704. // NOTE: ReceiveOutOfOrderFrame may have caused the frame to be freed via DropReceive
  705. // so we absolutely must not use pFrame past this point!
  706. if(fPoll)
  707. {
  708. if(pEPD->DelayedAckTimer != NULL)
  709. {
  710. DPFX(DPFPREP,7, "(%p) Cancelling Delayed Ack Timer", pEPD);
  711. if(CancelMyTimer(pEPD->DelayedAckTimer, pEPD->DelayedAckTimerUnique)!= DPN_OK)
  712. {
  713. DPFX(DPFPREP,7, "(%p) Cancelling Delayed Ack Timer Failed", pEPD);
  714. LOCK_EPD(pEPD, "LOCK (re-start delayed ack timer)");
  715. }
  716. // Start an abreviated delayed ack timer in case NACK gets cancelled
  717. }
  718. else
  719. {
  720. LOCK_EPD(pEPD, "LOCK (start short delayed ack timer)");
  721. }
  722. DPFX(DPFPREP,7, "Delaying POLL RESP");
  723. pEPD->ulEPFlags |= EPFLAGS_DELAY_ACKNOWLEDGE;
  724. DPFX(DPFPREP,7, "(%p) Setting Delayed Ack Timer", pEPD);
  725. SetMyTimer(5, 5, DelayedAckTimeout, (PVOID) pEPD, &pEPD->DelayedAckTimer, &pEPD->DelayedAckTimerUnique);
  726. }
  727. }
  728. // EPD->StateLock is still HELD
  729. //
  730. // We use a FLAG for exclusive access to ReceiveComplete routine. This is safe because the flag is only
  731. // tested and modified while holding the EPD->StateLock. Lets be sure to keep it that way...
  732. if( (!pEPD->blCompleteList.IsEmpty()) && ((pEPD->ulEPFlags & EPFLAGS_IN_RECEIVE_COMPLETE) == FALSE))
  733. {
  734. DPFX(DPFPREP,8, "(%p) Completing Receives...", pEPD);
  735. pEPD->ulEPFlags |= EPFLAGS_IN_RECEIVE_COMPLETE; // ReceiveComplete will clear this flag when done
  736. ReceiveComplete(pEPD); // Deliver the goods, returns with EPLock released
  737. }
  738. else
  739. {
  740. DPFX(DPFPREP,7, "(%p) Already in ReceiveComplete, letting other thread handle receives", pEPD);
  741. Unlock(&pEPD->EPLock);
  742. }
  743. DPFX(DPFPREP,8, "(%p) Completing Sends...", pEPD);
  744. CompleteSends(pEPD);
  745. return DPNERR_PENDING;
  746. }
  747. /*
  748. ** Receive In Order Frame
  749. **
  750. ** The interesting part of this function is moving frames off of the OddFrameList that
  751. ** the new frame adjoins. This may also be called with a NULL frame which will happen when
  752. ** a cancelled frame is the next-in-order receive.
  753. **
  754. ** One result of having cancelled frames running around is that we may miss the SOM or EOM
  755. ** flags which delimit messages. Therefore, we must watch as we assemble messages that we do not
  756. ** see unexpected flags, ie a new message w/o an SOM on first frame which means that part of the
  757. ** message must have been lost, and the whole thing must be trashed...
  758. **
  759. ** ** EPLOCK is HELD through this entire function **
  760. */
  761. #undef DPF_MODNAME
  762. #define DPF_MODNAME "ReceiveInOrderFrame"
  763. VOID
  764. ReceiveInOrderFrame(PEPD pEPD, PRCD pRCD)
  765. {
  766. CBilink *pLink;
  767. UINT flag;
  768. AssertCriticalSectionIsTakenByThisThread(&pEPD->EPLock, TRUE);
  769. // Condensing Loop WHILE (Next In-Order Frame has been received)
  770. do
  771. {
  772. ASSERT(pRCD->bSeq == pEPD->bNextReceive);
  773. pEPD->tLastDataFrame = pRCD->tTimestamp; // Always keep the receive time of (N(R) - 1)
  774. pEPD->bLastDataRetry = (pRCD->bFrameControl & PACKET_CONTROL_RETRY);
  775. #ifdef DEBUG
  776. pEPD->bLastDataSeq = pRCD->bSeq;
  777. #endif
  778. pRCD->pMsgLink = NULL;
  779. if(pEPD->pNewMessage == NULL)
  780. {
  781. // Add this frame to the in-order rcv list
  782. // pNewMessage implies we have no current message, head or tail
  783. ASSERT(pEPD->pNewTail == NULL);
  784. if(!(pRCD->bFrameFlags & PACKET_COMMAND_NEW_MSG))
  785. {
  786. // There is no NEW_MESSAGE flag on the first frame we see. We must
  787. // have lost the first frame or this is an invalid packet. We can throw
  788. // this frame away...
  789. DPFX(DPFPREP,1, "(%p) NEW_MESSAGE flag not set on first frame of message, scrapping frame (%x)", pEPD, pRCD->bSeq);
  790. pRCD->ulRFlags |= RFLAGS_FRAME_LOST;
  791. pRCD->bFrameFlags |= PACKET_COMMAND_END_MSG; // Turn this on so we will release buffer right away
  792. }
  793. // Even if we get rid of it, we will need these below
  794. pEPD->pNewMessage = pRCD;
  795. pEPD->pNewTail = pRCD;
  796. pRCD->uiFrameCount = 1;
  797. pRCD->uiMsgSize = pRCD->uiDataSize;
  798. DPFX(DPFPREP,8, "(%p) Queuing Frame (NEW MESSAGE) (%x)", pEPD, pRCD->bSeq);
  799. }
  800. else
  801. {
  802. if (pRCD->bFrameFlags & PACKET_COMMAND_NEW_MSG)
  803. {
  804. // We are getting the start of a new message in the start of an existing message, drop it all
  805. DPFX(DPFPREP,1, "(%p) NEW_MESSAGE flag set in the middle of existing message, scrapping message (%x, %x)", pEPD, pEPD->pNewMessage->bSeq, pRCD->bSeq);
  806. pRCD->ulRFlags |= RFLAGS_FRAME_LOST;
  807. pRCD->bFrameFlags |= PACKET_COMMAND_END_MSG; // Turn this on so we will release buffer right away
  808. }
  809. ASSERT((pEPD->pNewTail->bSeq) == (BYTE)(pRCD->bSeq - 1)); // Make sure they stay sequential
  810. pEPD->pNewTail->pMsgLink = pRCD;
  811. pEPD->pNewMessage->uiFrameCount++;
  812. pEPD->pNewMessage->uiMsgSize += pRCD->uiDataSize;
  813. pEPD->pNewMessage->ulRFlags |= (pRCD->ulRFlags & RFLAGS_FRAME_LOST);// UNION FRAME_LOST flag from all frames of a message
  814. pEPD->pNewTail = pRCD;
  815. DPFX(DPFPREP,8, "(%p) Queuing Frame (ON TAIL) (%x)", pEPD, pRCD->bSeq);
  816. }
  817. if(pRCD->bFrameFlags & PACKET_COMMAND_END_MSG)
  818. {
  819. // Either this frame completes a message or we decided to drop this one above
  820. // All frames on the ReceiveList should now be removed and delivered
  821. // Get either the message we are dropping above, or the beginning of the sequence of messages we are completing
  822. pRCD = pEPD->pNewMessage;
  823. pEPD->pNewMessage = NULL;
  824. if(pRCD->ulRFlags & RFLAGS_FRAME_LOST)
  825. {
  826. // We need to throw this away
  827. DPFX(DPFPREP,7, "(%p) Throwing away message with missing frames (%x, %x)", pEPD, pRCD->bSeq, pEPD->pNewTail->bSeq);
  828. pEPD->pNewTail = NULL;
  829. DropReceive(pEPD, pRCD);
  830. }
  831. else
  832. {
  833. // We need to complete this sequence
  834. pRCD->blCompleteLinkage.InsertBefore( &pEPD->blCompleteList); // place on end of Completion list
  835. DPFX(DPFPREP,7, "(%p) Adding msg to complete list FirstSeq=%x, LastSeq=%x QueueSize=%d",
  836. pEPD, pRCD->bSeq, pEPD->pNewTail->bSeq, pEPD->uiCompleteMsgCount);
  837. pEPD->pNewTail = NULL;
  838. pEPD->uiCompleteMsgCount++;
  839. }
  840. }
  841. // Since we are allowing out of order indication of receives it is possible that frames later than
  842. // the new one have already been indicated. This means that there may be bits set in the ReceiveMask
  843. // whose correlating frames do not need to be indicated. The most straightforward way to implement this
  844. // is to leave the early-indicated frames in the list, but mark them as INDICATED_NONSEQ. So inside this
  845. // master DO loop there will be an inner DO loop which passes over INDICATED frames and just takes them off
  846. // the list.
  847. //
  848. // Now its possible that a NonSeq indicated frame is still sitting on the CompleteList awaiting indication,
  849. // so I am using a ref count. An extra ref is added when a frame is completed non-seq. When a completed frame
  850. // is removed below we will release one reference, and the indication code will release one reference when it
  851. // finishes on that end. Happily, we can release the actual buffers while the RCD turd is still sitting on the
  852. // OddFrameList.
  853. BOOL fIndicatedNonSeq = FALSE;
  854. do
  855. {
  856. flag = pEPD->ulReceiveMask & 1; // set flag if next frame in stream is present
  857. pEPD->bNextReceive += 1; // Update receive window
  858. RIGHT_SHIFT_64(pEPD->ulReceiveMask2, pEPD->ulReceiveMask);// shift mask because base has changed
  859. DPFX(DPFPREP,7, "(%p) N(R) incremented to %x, Mask %x %x", pEPD, pEPD->bNextReceive, pEPD->ulReceiveMask2, pEPD->ulReceiveMask);
  860. if(flag)
  861. {
  862. // The next frame in the sequence has arrived already since low bit of ulReceiveMask was set
  863. // Several things can happen here:
  864. // 1) We are in the middle of a message, in which case, its next piece is on the out of order list
  865. // 2) We have just finished a message, which leaves two subcases:
  866. // a) We are beginning a new message. In this case our first piece is on the out of order list
  867. // b) Out-of-order non-sequential messages have completed while we were completing our in-order message
  868. // In this case there are some already indicated RCDs on the out of order list, and a new partial
  869. // message may or may not follow.
  870. pLink = pEPD->blOddFrameList.GetNext();
  871. ASSERT(pLink != &pEPD->blOddFrameList); // Make sure we didn't run out of RCDs on the list
  872. pRCD = CONTAINING_RECORD(pLink, RCD, blOddFrameLinkage);
  873. ASSERT_RCD(pRCD);
  874. pLink->RemoveFromList(); // take next frame out of OddFrameList
  875. // Make sure everything previous got removed from the odd frame list, and it is sorted correctly
  876. ASSERT(pRCD->bSeq == pEPD->bNextReceive);
  877. if (pRCD->ulRFlags & RFLAGS_FRAME_INDICATED_NONSEQ)
  878. {
  879. if (pEPD->pNewMessage)
  880. {
  881. // We need to throw this away
  882. PRCD pRCDTemp = pEPD->pNewMessage;
  883. pEPD->pNewMessage = NULL;
  884. DPFX(DPFPREP,1, "(%p) Throwing away non-ended message (%x, %x)", pEPD, pRCDTemp->bSeq, pEPD->pNewTail->bSeq);
  885. pEPD->pNewTail = NULL;
  886. DropReceive(pEPD, pRCDTemp);
  887. }
  888. fIndicatedNonSeq = TRUE;
  889. DPFX(DPFPREP,7, "(%p) Pulling Indicated-NonSequential message off of Out-of-Order List Seq=%x", pEPD, pRCD->bSeq);
  890. pEPD->tLastDataFrame = pRCD->tTimestamp; // Always keep the receive time of (N(R) - 1)
  891. pEPD->bLastDataRetry = (pRCD->bFrameControl & PACKET_CONTROL_RETRY);
  892. DEBUG_ONLY(pEPD->bLastDataSeq = pRCD->bSeq);
  893. RELEASE_RCD(pRCD);
  894. }
  895. else
  896. {
  897. // In the case of cancelling one of the messages in the middle of a large message,
  898. // we will drop all previous, drop that one, and then we will get to a situation where we aren't
  899. // currently working on a new message (pNewMessage was NULL'ed in the cancelling) and the current
  900. // message does not have the NEW_MSG flag, in which case we scrap it above.
  901. ASSERT(!fIndicatedNonSeq || (pRCD->bFrameFlags & PACKET_COMMAND_NEW_MSG) ||
  902. (!pEPD->pNewMessage && !(pRCD->bFrameFlags & PACKET_COMMAND_NEW_MSG)));
  903. // go ahead and move this to the receive list
  904. DPFX(DPFPREP,7, "(%p) Moving OutOfOrder frame to received list Seq=%x", pEPD, pRCD->bSeq);
  905. ASSERT(pRCD->bSeq == pEPD->bNextReceive);
  906. break; // Back to the top
  907. }
  908. }
  909. }
  910. while (flag); // DO WHILE (There are still in order frames that have already arrived with no incomplete messages)
  911. }
  912. while (flag); // DO WHILE (There are still in order frames that have already arrived with an incomplete message)
  913. if((pEPD->ulReceiveMask | pEPD->ulReceiveMask2)==0)
  914. {
  915. pEPD->ulEPFlags &= ~(EPFLAGS_DELAYED_NACK);
  916. if(((pEPD->ulEPFlags & EPFLAGS_DELAYED_SENDMASK)==0)&&(pEPD->DelayedMaskTimer != NULL))
  917. {
  918. DPFX(DPFPREP,7, "(%p) Cancelling Delayed Mask Timer", pEPD);
  919. if(CancelMyTimer(pEPD->DelayedMaskTimer, pEPD->DelayedMaskTimerUnique) == DPN_OK)
  920. {
  921. DECREMENT_EPD(pEPD, "UNLOCK (cancel DelayedMask)"); // SPLock not already held
  922. pEPD->DelayedMaskTimer = 0;
  923. }
  924. else
  925. {
  926. DPFX(DPFPREP,7, "(%p) Cancelling Delayed Mask Timer Failed", pEPD);
  927. }
  928. }
  929. }
  930. }
  931. /*
  932. ** Receive Out Of Order Frame
  933. **
  934. ** Its like the title says. We must set the appropriate bit in the 64-bit ReceiveMask
  935. ** and then place it into the OddFrameList in its proper sorted place. After that, we must
  936. ** scan to see if a complete message has been formed and see if we are able to indicate it
  937. ** early.
  938. **
  939. ** ** EPLOCK is HELD through this entire function **
  940. */
  941. #undef DPF_MODNAME
  942. #define DPF_MODNAME "ReceiveOutOfOrderFrame"
  943. VOID
  944. ReceiveOutOfOrderFrame(PEPD pEPD, PRCD pRCD, ULONG bit)
  945. {
  946. PRCD pRCD1;
  947. PRCD pRCD2;
  948. CBilink *pLink;
  949. BYTE NextSeq;
  950. ULONG highbit;
  951. ULONG Mask;
  952. ULONG WorkMaskHigh;
  953. ULONG WorkMaskLow;
  954. ULONG MaskHigh;
  955. ULONG MaskLow;
  956. BOOL nack = FALSE;
  957. UINT count;
  958. BOOL lost = FALSE;
  959. UINT frame_count = 0;
  960. UINT msg_length = 0;
  961. DPFX(DPFPREP,8,"(%p) Received out of order frame, Seq=%x, bit=%x", pEPD, pRCD->bSeq, bit);
  962. // Bit shouldn't be more than 64 (MAX_RECEIVE_RANGE)
  963. ASSERT(bit <= MAX_RECEIVE_RANGE);
  964. AssertCriticalSectionIsTakenByThisThread(&pEPD->EPLock, TRUE);
  965. // RECEIVE OUT OF ORDER FRAME
  966. //
  967. // DO WE SEND IMMEDIATE ACK FOR THIS OUT OF ORDER FRAME?
  968. //
  969. // When we receive an OutOfOrder frame it is almost certainly because the missing frame has been lost.
  970. // So we can accelerate the re-transmission process greatly by telling partner right away that frames
  971. // are missing. HOWEVER, with a large send window we will get many mis-ordered frames for each drop,
  972. // but we only want to send a Negative Ack once. SO, we will only initiate a NACK here if we have
  973. // created a NEW HOLE in our receive mask!
  974. //
  975. // First, we will not have created a new hole unless we added to the END of the OddFrameList.
  976. // Second, we will not have created a new hole unless the FIRST BIT TO THE RIGHT of the new bit
  977. // is CLEAR.
  978. //
  979. // So we will only generate an immediate NACK frame if both of the above cases are true!
  980. // NOTE - if this is the only OoO frame, then we should always send a NACK
  981. //
  982. // ANOTHER NOTE. SP implementation has been changed so that it frequently misorders receives in close
  983. // proximity. One effect of this is that we must not immediately send a NACK for an out of order frame, but
  984. // instead should wait a short period (say ~5ms) and see if the missing frame hasn't shown up.
  985. // Make sure this RCD is within the receive window
  986. // NOTE: Presume SACK arrives with bNSeq of 84, N(R) is 20, and all bits are set except the one representing 20.
  987. // In that case, pRCD->bSeq - pEPD->bNextReceive will be equal to 63 (ie MAX_FRAME_OFFSET).
  988. ASSERT((BYTE)(pRCD->bSeq - pEPD->bNextReceive) <= (BYTE)MAX_FRAME_OFFSET);
  989. // We will insert frame in OddFrameList maintaining sort by Seq number
  990. //
  991. // We can optimize for most likely case, which is new frames are added to END of list. We can
  992. // check for this first case by investigating whether the new bit is the left-most bit in the mask.
  993. // If it is LMB, then it trivially gets added to the END of the list.
  994. //
  995. // Please note that both this and the following algorithms assume that we have already verified
  996. // that the new frame is NOT already in the list
  997. MaskLow = pEPD->ulReceiveMask; // Get scratch copy of Mask
  998. MaskHigh = pEPD->ulReceiveMask2;
  999. if(bit < 32)
  1000. {
  1001. // Frame is within 32 of N(Rcv)
  1002. WorkMaskLow = 1 << bit; // Find bit in mask for new frame
  1003. WorkMaskHigh = 0;
  1004. pEPD->ulReceiveMask |= WorkMaskLow; // Set appropriate bit in mask
  1005. // check immediately preceeding bit for NACK determination
  1006. if( (MaskLow & (WorkMaskLow >> 1)) == 0)
  1007. {
  1008. nack = TRUE; // preceeding bit is not set
  1009. }
  1010. }
  1011. else
  1012. {
  1013. highbit = bit - 32;
  1014. WorkMaskHigh = 1 << highbit;
  1015. WorkMaskLow = 0;
  1016. pEPD->ulReceiveMask2 |= WorkMaskHigh; // Set appropriate bit in mask
  1017. if(highbit)
  1018. {
  1019. // check preceeding bit for NACK determination
  1020. if( (MaskHigh & (WorkMaskHigh >> 1)) == 0)
  1021. {
  1022. nack = TRUE; // preceeding bit is not set
  1023. }
  1024. }
  1025. else
  1026. {
  1027. if( (MaskLow & 0x80000000) == 0)
  1028. {
  1029. nack = TRUE;
  1030. }
  1031. }
  1032. }
  1033. // Insert frame in sorted OddFrameList.
  1034. //
  1035. // First test for trivial insert at tail condition. True if new bit is LEFTMOST set bit in
  1036. // both masks.
  1037. if( (WorkMaskHigh > MaskHigh) || ( (MaskHigh == 0) && (WorkMaskLow > MaskLow) ) )
  1038. {
  1039. // TAIL INSERTION
  1040. DPFX(DPFPREP,7, "(%p) Received %x OUT OF ORDER - INSERT AT TAIL NRcv=%x MaskL=%x MaskH=%x",
  1041. pEPD, pRCD->bSeq, pEPD->bNextReceive, pEPD->ulReceiveMask, pEPD->ulReceiveMask2);
  1042. pLink = &pEPD->blOddFrameList;
  1043. // Make sure this is either the only RCD in the list, or it is farther in the window than the last one
  1044. ASSERT(pLink->IsEmpty() || ((BYTE)(CONTAINING_RECORD(pLink->GetPrev(), RCD, blOddFrameLinkage))->bSeq - pEPD->bNextReceive) < (BYTE)(pRCD->bSeq - pEPD->bNextReceive));
  1045. pRCD->blOddFrameLinkage.InsertBefore( pLink);
  1046. // Check to see if we should NACK (negative acknowledge) any frames. We only want to NACK a given
  1047. // frame once so we will NACK if this is the first frame added to the OOF list, or if the immediately
  1048. // preceeding frame is missing. First condition is trivial to test.
  1049. if( ((MaskLow | MaskHigh) == 0) || (nack == 1) )
  1050. {
  1051. pEPD->ulEPFlags |= EPFLAGS_DELAYED_NACK;
  1052. if(pEPD->DelayedMaskTimer == 0)
  1053. {
  1054. DPFX(DPFPREP,7, "(%p) Setting Delayed Mask Timer", pEPD);
  1055. LOCK_EPD(pEPD, "LOCK (DelayedMaskTimer)"); // Bump RefCnt for timer
  1056. SetMyTimer(SHORT_DELAYED_ACK_TIMEOUT, 5, DelayedAckTimeout, (PVOID) pEPD, &pEPD->DelayedMaskTimer, &pEPD->DelayedMaskTimerUnique);
  1057. pEPD->tReceiveMaskDelta = GETTIMESTAMP();
  1058. }
  1059. else
  1060. {
  1061. DPFX(DPFPREP,7, "(%p) *** DELAYED NACK *** Timer already running", pEPD);
  1062. }
  1063. }
  1064. }
  1065. else
  1066. {
  1067. // NOT TAIL INSERTION
  1068. // This is the non-trivial case, ie new frame goes at beginning or in middle of OddFrameList.
  1069. // So we need to count the ONE bits that are to the RIGHT of the new bit in the ReceiveMask.
  1070. // We will mask off bits higher then the New Bit and then do a quick bit-count...
  1071. DPFX(DPFPREP,7, "(%p) Receive OUT OF ORDER - Walking Frame List (Seq=%x, NRcv=%x) MaskL=%x MaskH=%x", pEPD, pRCD->bSeq, pEPD->bNextReceive, pEPD->ulReceiveMask, pEPD->ulReceiveMask2);
  1072. // If we are inserting into high mask, we must count all one-bits in low mask
  1073. //
  1074. // We will test for the special case of all-bits-set at the outset...
  1075. pLink = pEPD->blOddFrameList.GetNext(); // pLink = First frame in list; we will walk list as we count
  1076. if(WorkMaskHigh)
  1077. {
  1078. // new frame in high mask. only count bits to right of new bit
  1079. WorkMaskHigh -= 1; // Convert to mask preserving all bits to right of new bit
  1080. WorkMaskHigh &= MaskHigh; // WMH now represents all bits to right of new bit
  1081. while(WorkMaskHigh)
  1082. {
  1083. // Make sure this is farther in the window than the one we are skipping
  1084. ASSERT(((BYTE)(CONTAINING_RECORD(pLink, RCD, blOddFrameLinkage))->bSeq - pEPD->bNextReceive) < (BYTE)(pRCD->bSeq - pEPD->bNextReceive));
  1085. // Count bits in WMH
  1086. Mask = WorkMaskHigh - 1;
  1087. WorkMaskHigh &= Mask;
  1088. pLink = pLink->GetNext();
  1089. }
  1090. if(MaskLow == 0xFFFFFFFF)
  1091. {
  1092. // special case if low mask is full
  1093. for(count = 0; count < 32; count++)
  1094. {
  1095. // Make sure this is farther in the window than the one we are skipping
  1096. ASSERT(((BYTE)(CONTAINING_RECORD(pLink, RCD, blOddFrameLinkage))->bSeq - pEPD->bNextReceive) < (BYTE)(pRCD->bSeq - pEPD->bNextReceive));
  1097. pLink = pLink->GetNext();
  1098. }
  1099. }
  1100. else
  1101. {
  1102. // else count all bits in lower mask
  1103. while(MaskLow)
  1104. {
  1105. // Make sure this is farther in the window than the one we are skipping
  1106. ASSERT(((BYTE)(CONTAINING_RECORD(pLink, RCD, blOddFrameLinkage))->bSeq - pEPD->bNextReceive) < (BYTE)(pRCD->bSeq - pEPD->bNextReceive));
  1107. Mask = MaskLow - 1;
  1108. MaskLow &= Mask; // Mask off low 1-bit
  1109. pLink = pLink->GetNext();
  1110. }
  1111. }
  1112. }
  1113. else
  1114. {
  1115. WorkMaskLow -= 1;
  1116. WorkMaskLow &= MaskLow; // WML == bits to the right of new bit
  1117. while(WorkMaskLow)
  1118. {
  1119. // Make sure this is farther in the window than the one we are skipping
  1120. ASSERT(((BYTE)(CONTAINING_RECORD(pLink, RCD, blOddFrameLinkage))->bSeq - pEPD->bNextReceive) < (BYTE)(pRCD->bSeq - pEPD->bNextReceive));
  1121. Mask = WorkMaskLow - 1;
  1122. WorkMaskLow &= Mask; // Mask off low 1-bit
  1123. pLink = pLink->GetNext();
  1124. }
  1125. }
  1126. // Make sure this is farther in the window than the last one
  1127. ASSERT(((BYTE)(CONTAINING_RECORD(pLink->GetPrev(), RCD, blOddFrameLinkage))->bSeq - pEPD->bNextReceive) < (BYTE)(pRCD->bSeq - pEPD->bNextReceive));
  1128. pRCD->blOddFrameLinkage.InsertBefore( pLink); // Insert new frame in sorted list
  1129. } // Receive not at tail
  1130. #ifdef DEBUG
  1131. // Dump the contents of the Out of Order Frame List for verification. There are at most 64 frames.
  1132. {
  1133. BYTE bCurSeq = pEPD->bNextReceive + 1;
  1134. ULONG64 ulMask = ((ULONG64)pEPD->ulReceiveMask2 << 32) | ((ULONG64)pEPD->ulReceiveMask);
  1135. CBilink* pTemp;
  1136. TCHAR szOOFL[256];
  1137. szOOFL[0] = 0;
  1138. pTemp = pEPD->blOddFrameList.GetNext();
  1139. while (pTemp != &pEPD->blOddFrameList)
  1140. {
  1141. while (ulMask != 0 && !(ulMask & 1))
  1142. {
  1143. ulMask >>= 1;
  1144. bCurSeq++;
  1145. }
  1146. ASSERT(ulMask != 0);
  1147. PRCD pRCDTemp = CONTAINING_RECORD(pTemp, RCD, blOddFrameLinkage);
  1148. ASSERT_RCD(pRCDTemp);
  1149. ASSERT(bCurSeq == pRCDTemp->bSeq);
  1150. _stprintf(szOOFL, _T("%s %02x"), szOOFL, pRCDTemp->bSeq);
  1151. ulMask >>= 1;
  1152. bCurSeq++;
  1153. pTemp = pTemp->GetNext();
  1154. }
  1155. DPFX(DPFPREP, 7, "OOFL contents: %s", szOOFL);
  1156. }
  1157. #endif // DEBUG
  1158. // ** Non-Sequential Indication
  1159. //
  1160. // This is the Non-Trivial implementation of non-sequential receive indication.
  1161. // We will work from the assumption that we only need to complete messages that are touched by the new frame.
  1162. // So we must back up in the OddFrame list until we see either a gap or a Start of Message marker. Then we must work
  1163. // forward looking for an End of Message...
  1164. //
  1165. // One more complication is the fact that dropped packets might in the list via place-holding dummies. Since we
  1166. // do not know what SOM/EOM flags would have been present on a dropped frame, we can consider them to have BOTH flags.
  1167. // Then we also need to be aware that frames bordering on dropped frames without a delimiter (SOM or EOM) are fragments
  1168. // and therefore count as dropped data too. I think to keep this from getting too complex, we wont probe further for
  1169. // neighbors of lost data frames. We will discover them when we are building a message later.
  1170. //
  1171. // pLink = Item after new element in Out of Order list
  1172. // pRCD = new Item
  1173. // IF this frame is not marked as SEQUENTIAL
  1174. if((pRCD->bFrameFlags & PACKET_COMMAND_SEQUENTIAL)==0)
  1175. {
  1176. DPFX(DPFPREP,7, "(%p) Received Non-Seq %x out of order; flags=%x", pEPD, pRCD->bSeq, pRCD->bFrameFlags);
  1177. NextSeq = pRCD->bSeq;
  1178. // NOTE: The first pLink will be the passed in RCD so we will have included that in the frame_count and msg_length after leaving this while
  1179. while ( (pLink = pLink->GetPrev()) != &pEPD->blOddFrameList )
  1180. {
  1181. pRCD1 = CONTAINING_RECORD(pLink, RCD, blOddFrameLinkage);
  1182. ASSERT_RCD(pRCD1);
  1183. frame_count++;
  1184. msg_length += pRCD1->uiDataSize;
  1185. if((pRCD1->bFrameFlags & PACKET_COMMAND_NEW_MSG) || (pRCD1->bSeq != NextSeq))
  1186. {
  1187. break; // Stop probing when we find a NEW_MSG flag OR a gap in the frame sequence numbers
  1188. }
  1189. --NextSeq;
  1190. }
  1191. // We have either found a NEW_MSG or a sequence gap. If its a NEW_MSG, then we probe forward for an END_MSG
  1192. if((pRCD1->bFrameFlags & PACKET_COMMAND_NEW_MSG) && (pRCD1->bSeq == NextSeq))
  1193. {
  1194. // So far so good. We have a sequential message start frame
  1195. //
  1196. // pRCD = frame just arrived
  1197. // pRCD1 = Start of message frame
  1198. // pLink = Start of message linkage
  1199. pLink = &pRCD->blOddFrameLinkage;
  1200. NextSeq = pRCD->bSeq;
  1201. // Look for the message end or a sequence gap
  1202. while ( ( (pRCD->bFrameFlags & PACKET_COMMAND_END_MSG)==0 ) && (pRCD->bSeq == NextSeq))
  1203. {
  1204. // Stop if we hit the end of the OddFrameList
  1205. if((pLink = pLink->GetNext()) == &pEPD->blOddFrameList)
  1206. {
  1207. break;
  1208. }
  1209. // NOTE: the first pLink here will be the one after the passed in RCD. If there is a gap that won't
  1210. // matter because we are out of here after the next if. If it is the next message we will continue until
  1211. // we hit the END_MSG and have a proper frame_count and msg_length.
  1212. pRCD = CONTAINING_RECORD(pLink, RCD, blOddFrameLinkage);
  1213. ASSERT_RCD(pRCD);
  1214. frame_count++;
  1215. msg_length += pRCD->uiDataSize;
  1216. NextSeq++;
  1217. }
  1218. // pLink should not be used after this point due to the way the above while could have left it either valid
  1219. // or at &pEPD->blOddFrameList.
  1220. pLink = NULL;
  1221. if((pRCD->bFrameFlags & PACKET_COMMAND_END_MSG) && (pRCD->bSeq == NextSeq))
  1222. {
  1223. // We have completed a message
  1224. //
  1225. // pRCD1 = First frame in message
  1226. // pRCD = Last frame in message
  1227. DPFX(DPFPREP,7, "(%p) Completed Non-Seq Msg: First=%x, Last=%x", pEPD, pRCD1->bSeq, pRCD->bSeq);
  1228. lost = FALSE;
  1229. pRCD->ulRFlags |= RFLAGS_FRAME_INDICATED_NONSEQ;
  1230. pRCD->pMsgLink = NULL;
  1231. lost |= pRCD->ulRFlags & RFLAGS_FRAME_LOST;
  1232. // Get the pointer to the next to last message so we can remove the last
  1233. pLink = pRCD->blOddFrameLinkage.GetPrev();
  1234. LOCK_RCD(pRCD); // ReceiveInOrderFrame must remove this
  1235. // Walk from the last message to the first message accumulating lost flags, linking messages,
  1236. // setting indicated flag, and pulling off of the odd frame list
  1237. while (pRCD != pRCD1)
  1238. {
  1239. ASSERT(pLink != &pEPD->blOddFrameList); // Make sure we didn't run out of RCDs on the list
  1240. pRCD2 = CONTAINING_RECORD(pLink, RCD, blOddFrameLinkage);
  1241. ASSERT_RCD(pRCD2);
  1242. pRCD2->pMsgLink = pRCD;
  1243. LOCK_RCD(pRCD2); // ReceiveInOrderFrame must remove this
  1244. pRCD2->ulRFlags |= RFLAGS_FRAME_INDICATED_NONSEQ;
  1245. lost |= pRCD2->ulRFlags & RFLAGS_FRAME_LOST;
  1246. pLink = pRCD2->blOddFrameLinkage.GetPrev();
  1247. pRCD = pRCD2;
  1248. }
  1249. // Both RCD and RCD1 point to the first message now
  1250. // If any were lost, drop the receive, otherwise complete it
  1251. if(!lost)
  1252. {
  1253. pRCD->uiFrameCount = frame_count;
  1254. pRCD->uiMsgSize = msg_length;
  1255. DPFX(DPFPREP,7, "(%p) Adding msg to complete list FirstSeq=%x QueueSize=%d", pEPD, pRCD->bSeq, pEPD->uiCompleteMsgCount);
  1256. pRCD->blCompleteLinkage.InsertBefore( &pEPD->blCompleteList);
  1257. pEPD->uiCompleteMsgCount++;
  1258. }
  1259. else
  1260. {
  1261. DPFX(DPFPREP,7, "(%p) Complete Non-Seq MSG is dropped due to missing frames", pEPD);
  1262. DropReceive(pEPD, pRCD);
  1263. }
  1264. }
  1265. } // else there is nothing to complete at this time...
  1266. } // IF NON SEQUENTIAL
  1267. }
  1268. /*
  1269. ** Drop Receive
  1270. **
  1271. ** One or more frames composing a message have been dropped, so the entire message can be scrapped.
  1272. ** If this was determined during an out of order receive then the RCDs will remain on the OddFrameList
  1273. ** as usual.
  1274. */
  1275. #undef DPF_MODNAME
  1276. #define DPF_MODNAME "DropReceive"
  1277. VOID
  1278. DropReceive(PEPD pEPD, PRCD pRCD)
  1279. {
  1280. PRCD pNext;
  1281. PSPRECEIVEDBUFFER pRcvBuff = NULL;
  1282. while(pRCD != NULL)
  1283. {
  1284. ASSERT_RCD(pRCD);
  1285. if (pRCD->bFrameFlags & PACKET_COMMAND_RELIABLE)
  1286. {
  1287. DPFX(DPFPREP,1, "(%p) Dropping G receive frame %x!!!", pEPD, pRCD->bSeq);
  1288. }
  1289. else
  1290. {
  1291. DPFX(DPFPREP,7, "(%p) Dropping NG receive frame %x", pEPD, pRCD->bSeq);
  1292. }
  1293. RELEASE_SP_BUFFER(pRCD->pRcvBuff);
  1294. pNext = pRCD->pMsgLink;
  1295. RELEASE_RCD(pRCD);
  1296. pRCD = pNext;
  1297. }
  1298. if(pRcvBuff != NULL)
  1299. {
  1300. DPFX(DPFPREP,DPF_CALLOUT_LVL, "(%p) Calling SP->ReturnReceiveBuffers, pSPD[%p]", pEPD, pEPD->pSPD);
  1301. IDP8ServiceProvider_ReturnReceiveBuffers(pEPD->pSPD->IISPIntf, pRcvBuff);
  1302. }
  1303. }
  1304. /*
  1305. ** Receive Complete
  1306. **
  1307. ** We have received an entire reliable message, potentially spanning
  1308. ** multiple messages. We are still on the receive thread right now so depending
  1309. ** upon our desired indication behavior we will either indicate it directly or
  1310. ** else queue it to be indicated on a background thread of some sort.
  1311. **
  1312. ** Messages spanning multiple frames (for now) will be copied into a contiguous
  1313. ** buffer for delivery. CODEWORK -- Server implementations should be able to receive
  1314. ** large messages as buffer chains (or arrays of BufDescs).
  1315. **
  1316. ** This is also where we must notice that an End Of Stream flag is set in a message,
  1317. ** indicating that the connection is being closed.
  1318. **
  1319. ** *** CALLED WITH EPD->STATELOCK HELD *** RETURNS WITH STATELOCK RELEASED ***
  1320. */
  1321. #undef DPF_MODNAME
  1322. #define DPF_MODNAME "ReceiveComplete"
  1323. VOID
  1324. ReceiveComplete(PEPD pEPD)
  1325. {
  1326. CBilink *pLink;
  1327. PRCD pRCD;
  1328. PRCD pNext;
  1329. PSPRECEIVEDBUFFER pRcvBuff = NULL;
  1330. PBIGBUF pBuf;
  1331. PBYTE write;
  1332. UINT length;
  1333. UINT frames;
  1334. DWORD flag;
  1335. UINT MsgSize;
  1336. HRESULT hr;
  1337. AssertCriticalSectionIsTakenByThisThread(&pEPD->EPLock, TRUE);
  1338. while((pLink = pEPD->blCompleteList.GetNext()) != &pEPD->blCompleteList)
  1339. {
  1340. pLink->RemoveFromList();
  1341. ASSERT(pEPD->uiCompleteMsgCount > 0);
  1342. pEPD->uiCompleteMsgCount--;
  1343. Unlock(&pEPD->EPLock);
  1344. pRCD = CONTAINING_RECORD(pLink, RCD, blCompleteLinkage);
  1345. ASSERT_RCD(pRCD);
  1346. // Handle easy case first
  1347. if(pRCD->uiFrameCount == 1) // message is only 1 frame
  1348. {
  1349. if(pRCD->uiDataSize > 0)
  1350. {
  1351. pEPD->uiMessagesReceived++;
  1352. if(pRCD->bFrameFlags & PACKET_COMMAND_RELIABLE)
  1353. {
  1354. pEPD->uiGuaranteedFramesReceived++;
  1355. pEPD->uiGuaranteedBytesReceived += pRCD->uiDataSize;
  1356. }
  1357. else
  1358. {
  1359. pEPD->uiDatagramFramesReceived++;
  1360. pEPD->uiDatagramBytesReceived += pRCD->uiDataSize;
  1361. }
  1362. pRCD->pRcvBuff->dwProtocolData = RBT_SERVICE_PROVIDER_BUFFER;
  1363. pRCD->pRcvBuff->pServiceProviderDescriptor = pEPD->pSPD;
  1364. flag = (((DWORD) pRCD->bFrameFlags) & (PACKET_COMMAND_USER_1 | PACKET_COMMAND_USER_2)) * (DN_SENDFLAGS_SET_USER_FLAG / PACKET_COMMAND_USER_1);
  1365. DEBUG_ONLY(InterlockedIncrement(&pEPD->pSPD->pPData->ThreadsInReceive));
  1366. DEBUG_ONLY(InterlockedIncrement(&pEPD->pSPD->pPData->BuffersInReceive));
  1367. DPFX(DPFPREP,DPF_CALLOUT_LVL, "(%p) Calling Core->IndicateReceive, pRCD[%p], Core Context[%p]", pEPD, pRCD, pEPD->Context);
  1368. hr = pEPD->pSPD->pPData->pfVtbl->IndicateReceive(pEPD->pSPD->pPData->Parent, pEPD->Context, pRCD->pbData, pRCD->uiDataSize, pRCD->pRcvBuff, flag);
  1369. if(hr == DPN_OK)
  1370. {
  1371. RELEASE_SP_BUFFER(pRCD->pRcvBuff); // Really only queues it to be released
  1372. DEBUG_ONLY(InterlockedDecrement(&pEPD->pSPD->pPData->BuffersInReceive));
  1373. }
  1374. else
  1375. {
  1376. ASSERT(hr == DPNERR_PENDING);
  1377. // The Core owns it now and is responsible for calling DNPReleaseReceiveBuffer to free it
  1378. pRCD->pRcvBuff = NULL;
  1379. }
  1380. DEBUG_ONLY(InterlockedDecrement(&pEPD->pSPD->pPData->ThreadsInReceive));
  1381. }
  1382. else
  1383. {
  1384. // If DataSize == 0 & EOS is not set, then this was a keep alive message and is ignored
  1385. if(pRCD->bFrameControl & PACKET_CONTROL_END_STREAM)
  1386. {
  1387. // END OF STREAM indicated
  1388. DPFX(DPFPREP,7, "(%p) Processing EndOfStream, pRCD[%p]", pEPD, pRCD);
  1389. ProcessEndOfStream(pEPD);
  1390. }
  1391. RELEASE_SP_BUFFER(pRCD->pRcvBuff); // Really only queues it to be released
  1392. }
  1393. RELEASE_RCD(pRCD); // Release reference for Complete Processing
  1394. }
  1395. else // Message spans multiple frames
  1396. {
  1397. // Multiple buffers. Need to copy data into contiguous buffer.
  1398. if((MsgSize = pRCD->uiMsgSize) <= SMALL_BUFFER_SIZE)
  1399. {
  1400. pBuf = static_cast<PBIGBUF>( BufPool->Get(BufPool) );
  1401. }
  1402. else if (MsgSize <= MEDIUM_BUFFER_SIZE)
  1403. {
  1404. pBuf = static_cast<PBIGBUF>( MedBufPool->Get(MedBufPool) );
  1405. }
  1406. else if (MsgSize <= LARGE_BUFFER_SIZE)
  1407. {
  1408. pBuf = static_cast<PBIGBUF>( BigBufPool->Get(BigBufPool) );
  1409. }
  1410. else
  1411. {
  1412. DPFX(DPFPREP,7, "(%p) RECEIVE HUGE MESSAGE", pEPD);
  1413. // Receive is larger then our biggest static receive buffer. This means we have to allocate a dynamic buffer.
  1414. pBuf = (PBIGBUF) DNMalloc(MsgSize + sizeof(DYNBUF));
  1415. if(pBuf)
  1416. {
  1417. pBuf->Type = RBT_DYNAMIC_BUFFER;
  1418. }
  1419. }
  1420. if(pBuf == NULL)
  1421. {
  1422. DPFX(DPFPREP,0, "MEMORY ALLOC FAILED. Cannot deliver data");
  1423. while(pRCD != NULL)
  1424. {
  1425. ASSERT_RCD(pRCD);
  1426. pNext = pRCD->pMsgLink;
  1427. RELEASE_SP_BUFFER(pRCD->pRcvBuff);
  1428. RELEASE_RCD(pRCD);
  1429. pRCD = pNext;
  1430. }
  1431. Lock(&pEPD->EPLock);
  1432. continue; // blow it off!
  1433. }
  1434. write = pBuf->data; // initialize write pointer
  1435. length = 0;
  1436. frames = 0;
  1437. while(pRCD != NULL)
  1438. {
  1439. ASSERT_RCD(pRCD);
  1440. memcpy(write, pRCD->pbData, pRCD->uiDataSize);
  1441. write += pRCD->uiDataSize;
  1442. length += pRCD->uiDataSize;
  1443. frames++;
  1444. pNext = pRCD->pMsgLink;
  1445. flag = (DWORD) pRCD->bFrameFlags;
  1446. RELEASE_SP_BUFFER(pRCD->pRcvBuff);
  1447. RELEASE_RCD(pRCD);
  1448. pRCD = pNext;
  1449. }
  1450. pEPD->uiMessagesReceived++;
  1451. if(flag & PACKET_COMMAND_RELIABLE)
  1452. {
  1453. pEPD->uiGuaranteedFramesReceived += frames;
  1454. pEPD->uiGuaranteedBytesReceived += length;
  1455. }
  1456. else
  1457. {
  1458. pEPD->uiDatagramFramesReceived += frames;
  1459. pEPD->uiDatagramBytesReceived += length;
  1460. }
  1461. flag = (flag & (PACKET_COMMAND_USER_1 | PACKET_COMMAND_USER_2)) * (DN_SENDFLAGS_SET_USER_FLAG / PACKET_COMMAND_USER_1);
  1462. DPFX(DPFPREP,DPF_CALLOUT_LVL, "(%p) Calling Core->IndicateReceive, Core Context[%p]", pEPD, pEPD->Context);
  1463. hr = pEPD->pSPD->pPData->pfVtbl->IndicateReceive(pEPD->pSPD->pPData->Parent, pEPD->Context, pBuf->data, length, pBuf, flag);
  1464. if(hr == DPN_OK)
  1465. {
  1466. if(pBuf->Type == RBT_PROTOCOL_BUFFER)
  1467. {
  1468. pBuf->Owner->Release(pBuf->Owner, pBuf);
  1469. }
  1470. else
  1471. {
  1472. DNFree(pBuf);
  1473. }
  1474. }
  1475. else
  1476. {
  1477. ASSERT(hr == DPNERR_PENDING);
  1478. }
  1479. }
  1480. Lock(&pEPD->EPLock);
  1481. }
  1482. ASSERT(pEPD->blCompleteList.IsEmpty());
  1483. pEPD->ulEPFlags &= ~(EPFLAGS_IN_RECEIVE_COMPLETE); // Clear this before releasing Lock final time
  1484. Unlock(&pEPD->EPLock);
  1485. if(pRcvBuff != NULL)
  1486. {
  1487. DPFX(DPFPREP,DPF_CALLOUT_LVL, "(%p) Calling SP->ReturnReceiveBuffers, pSPD[%p]", pEPD, pEPD->pSPD);
  1488. IDP8ServiceProvider_ReturnReceiveBuffers(pEPD->pSPD->IISPIntf, pRcvBuff);
  1489. }
  1490. }
  1491. /*
  1492. ** Process Send Mask
  1493. **
  1494. ** The send mask is what our partner uses to tell us to stop waiting for particular frames.
  1495. ** This will happen after an Unreliable frame is dropped. Instead of retransmitting the unreliable
  1496. ** frame, the sender will forward the appropriate bit in a send mask. In this routine, we attempt
  1497. ** to update our receive state pursuant to the newly received mask.
  1498. **
  1499. ** THIS IS CALLED WITH STATELOCK HELD AND RETURNS WITH STATELOCK HELD
  1500. **
  1501. ** suffice it to say that we should not release statelock anywhere in the following
  1502. */
  1503. #undef DPF_MODNAME
  1504. #define DPF_MODNAME "ProcessSendMask"
  1505. VOID
  1506. ProcessSendMask(PEPD pEPD, BYTE bSeq, ULONG MaskLow, ULONG MaskHigh, DWORD tNow)
  1507. {
  1508. INT deltaS;
  1509. ULONG workmaskS;
  1510. BYTE bThisFrame;
  1511. UINT skip;
  1512. ASSERT(MaskLow | MaskHigh);
  1513. DPFX(DPFPREP,7, "(%p) PROCESS SEND MASK N(R)=%x, bSeq=%x, MaskL=%x, MaskH=%x", pEPD, pEPD->bNextReceive, bSeq, MaskLow, MaskHigh);
  1514. // The mask can only refer to frames earlier than the Seq number in this frame. So if this frame
  1515. // is the next In-Order then the mask can have nothing interesting in it.
  1516. //
  1517. // The SendMask is coded with decending frame numbers starting at the Seq in this frame - 1.
  1518. // The ReceiveMask is coded with ascending frame numbers start at N(Rcv) + 1.
  1519. //
  1520. // We will walk forward through the rcvmask and backward through the sendmask looking for the magic combo
  1521. // of a bit clear in the rcvmask and the corresponding bit set in the sendmask. For each of these matches,
  1522. // a dummy cancel frame can be 'received' for that sequence number.
  1523. //
  1524. // This would be fairly straightforward if it wasn't for the fact that both masks are 64 bits so the code has
  1525. // to track which DWORD of each mask we are dealing with at any given time.
  1526. //
  1527. // NOTE: It is perfectly legitimate for a SACK to come in with a bNSeq at MAX_FRAME_OFFSET from pEPD->bNextReceive. Consider
  1528. // the case where pEPD->bNextReceive is 0 and the sender has sent and timed out 0-63. A SACK would arrive with a bNSeq of 64
  1529. // and both masks fully set.
  1530. top:
  1531. if (bSeq != pEPD->bNextReceive)
  1532. {
  1533. deltaS = (INT) (((BYTE)(bSeq - pEPD->bNextReceive)) - 1); // count of frames between first missing frame and sequence base of mask
  1534. bThisFrame = pEPD->bNextReceive;
  1535. if ( deltaS <= MAX_FRAME_OFFSET )
  1536. {
  1537. // If the difference is greater then 32 frames then we need to look at the high mask first and
  1538. // then fall through to the low mask. Otherwise, we can ignore the highmask and start with the low.
  1539. while((deltaS > 31) && (MaskHigh)) // Any work to do in the upper bits?
  1540. {
  1541. workmaskS = 1 << (deltaS - 32); // walks bit positions backward in send mask
  1542. // See if the next frame we are interested in is covered by this mask
  1543. if(workmaskS & MaskHigh)
  1544. {
  1545. CancelFrame(pEPD, bThisFrame, tNow);
  1546. MaskHigh &= ~workmaskS;
  1547. // N(R) may have been bumped up multiple times by CancelFrame, reset to make sure we work with
  1548. // up to date information.
  1549. goto top;
  1550. }
  1551. else
  1552. {
  1553. bThisFrame++;
  1554. deltaS--;
  1555. }
  1556. }
  1557. if(deltaS > 31)
  1558. {
  1559. skip = deltaS - 31; // how many bit positions did we skip
  1560. bThisFrame += (BYTE) skip;
  1561. deltaS -= skip;
  1562. }
  1563. while((deltaS >= 0) && (MaskLow)) // Any work to do in the lower bits?
  1564. {
  1565. workmaskS = 1 << deltaS;
  1566. if(workmaskS & MaskLow)
  1567. {
  1568. CancelFrame(pEPD, bThisFrame, tNow);
  1569. MaskLow &= ~workmaskS;
  1570. // N(R) may have been bumped up multiple times by CancelFrame, reset to make sure we work with
  1571. // up to date information.
  1572. goto top;
  1573. }
  1574. else
  1575. {
  1576. bThisFrame++;
  1577. deltaS--;
  1578. }
  1579. }
  1580. }
  1581. }
  1582. // We need to ACK every time a send mask. Consider the case of one way Non-Guaranteed traffic. If data or an ACK gets lost,
  1583. // this will be the only way we get back in sync with the other side.
  1584. // If timer is not running better start it now
  1585. if(pEPD->DelayedAckTimer == 0)
  1586. {
  1587. LOCK_EPD(pEPD, "LOCK (DelayedAckTimer)"); // Bump RefCnt for timer
  1588. pEPD->ulEPFlags |= EPFLAGS_DELAY_ACKNOWLEDGE;
  1589. DPFX(DPFPREP,7, "(%p) Setting Delayed Ack Timer", pEPD);
  1590. SetMyTimer(DELAYED_ACK_TIMEOUT, 0, DelayedAckTimeout, (PVOID) pEPD, &pEPD->DelayedAckTimer, &pEPD->DelayedAckTimerUnique);
  1591. }
  1592. }
  1593. #undef DPF_MODNAME
  1594. #define DPF_MODNAME "BuildCancelledRCD"
  1595. PRCD
  1596. BuildCancelledRCD(PEPD pEPD, BYTE bSeq, DWORD tNow)
  1597. {
  1598. PRCD pRCD;
  1599. if((pRCD = static_cast<PRCD> (RCDPool->Get(RCDPool))) == NULL)
  1600. {
  1601. DPFX(DPFPREP,0, "Failed to allocate RCD");
  1602. return NULL;
  1603. }
  1604. pRCD->bSeq = bSeq;
  1605. pRCD->bFrameFlags = PACKET_COMMAND_NEW_MSG | PACKET_COMMAND_END_MSG;
  1606. pRCD->bFrameControl = 0;
  1607. pRCD->pbData = NULL;
  1608. pRCD->uiDataSize = 0;
  1609. pRCD->tTimestamp = tNow;
  1610. pRCD->pRcvBuff = NULL;
  1611. pRCD->ulRFlags = RFLAGS_FRAME_LOST;
  1612. return pRCD;
  1613. }
  1614. /* Cancel Frame
  1615. **
  1616. ** An unreliable frame has been reported as lost by sender. This means we should consider it acknowledged
  1617. ** and remove it from our receive window. This may require us to place a dummy receive descriptor in the OddFrameList
  1618. ** to hold its place until the window moves past it.
  1619. */
  1620. #undef DPF_MODNAME
  1621. #define DPF_MODNAME "CancelFrame"
  1622. BOOL
  1623. CancelFrame(PEPD pEPD, BYTE bSeq, DWORD tNow)
  1624. {
  1625. PRCD pRCD;
  1626. ULONG bit;
  1627. DPFX(DPFPREP,7, "(%p) CANCEL FRAME: Seq=%x", pEPD, bSeq);
  1628. AssertCriticalSectionIsTakenByThisThread(&pEPD->EPLock, TRUE);
  1629. // Trivial case is when the cancelled frame is at the front of the window. In this case we can complete not only
  1630. // this frame but any contiguous frames following it in the OddFrameList
  1631. if(pEPD->bNextReceive == bSeq)
  1632. {
  1633. if((pRCD = BuildCancelledRCD(pEPD, bSeq, tNow)) == NULL)
  1634. {
  1635. return FALSE;
  1636. }
  1637. ReceiveInOrderFrame(pEPD, pRCD);
  1638. }
  1639. // Here we have to place a dummy node on the OddFrameList to represent this frame.
  1640. else
  1641. {
  1642. // bit location in mask for this frame
  1643. bit = (BYTE) ((bSeq - pEPD->bNextReceive) - 1);
  1644. // Make sure this is not a duplicate frame
  1645. if( ((bit < 32) && (pEPD->ulReceiveMask & (1 << bit))) || ((bit > 31) && (pEPD->ulReceiveMask2 & (1 << (bit - 32)))) )
  1646. {
  1647. DPFX(DPFPREP,7, "(%p) Received CancelMask for frame that's already received Seq=%x", pEPD, bSeq);
  1648. return FALSE;
  1649. }
  1650. if((pRCD = BuildCancelledRCD(pEPD, bSeq, tNow)) == NULL)
  1651. {
  1652. return FALSE;
  1653. }
  1654. ReceiveOutOfOrderFrame(pEPD, pRCD, bit);
  1655. }
  1656. return TRUE;
  1657. }
  1658. /*
  1659. ** Release Receive Buffer
  1660. **
  1661. ** The core calls this function to return buffers previously handed
  1662. ** over in an IndicateUserData call. This call may be made before the
  1663. ** actual indication returns.
  1664. */
  1665. #undef DPF_MODNAME
  1666. #define DPF_MODNAME "DNPReleaseReceiveBuffer"
  1667. HRESULT
  1668. DNPReleaseReceiveBuffer(HANDLE hBuffer)
  1669. {
  1670. union
  1671. {
  1672. PBIGBUF pBuf;
  1673. PSPRECEIVEDBUFFER pRcvBuff;
  1674. } pBuffer;
  1675. PSPD pSPD;
  1676. DPFX(DPFPREP,DPF_CALLIN_LVL, "Parameters: hBuffer[%p]", hBuffer);
  1677. pBuffer.pBuf = (PBIGBUF) hBuffer;
  1678. switch(pBuffer.pBuf->Type)
  1679. {
  1680. case RBT_SERVICE_PROVIDER_BUFFER:
  1681. pSPD = (PSPD) pBuffer.pRcvBuff->pServiceProviderDescriptor;
  1682. ASSERT_SPD(pSPD);
  1683. DEBUG_ONLY(InterlockedDecrement(&pSPD->pPData->BuffersInReceive));
  1684. pBuffer.pRcvBuff->pNext = NULL;
  1685. DPFX(DPFPREP,DPF_CALLOUT_LVL, "Calling SP->ReturnReceiveBuffers, pRcvBuff[%p], pSPD[%p]", pBuffer.pRcvBuff, pSPD);
  1686. IDP8ServiceProvider_ReturnReceiveBuffers(pSPD->IISPIntf, pBuffer.pRcvBuff);
  1687. break;
  1688. case RBT_PROTOCOL_BUFFER:
  1689. pBuffer.pBuf->Owner->Release(pBuffer.pBuf->Owner, pBuffer.pBuf);
  1690. break;
  1691. case RBT_DYNAMIC_BUFFER:
  1692. DNFree(hBuffer);
  1693. break;
  1694. default:
  1695. DPFX(DPFPREP,0, "RELEASE RECEIVE BUFFER CALLED WITH BAD PARAMETER");
  1696. return DPNERR_INVALIDPARAM;
  1697. }
  1698. return DPN_OK;
  1699. }
  1700. /*
  1701. ** Complete Sends
  1702. **
  1703. ** Reliable sends are completed upon acknowlegement. Acknowlegements are discovered inside
  1704. ** the UpdateXmitState routine while walking through the pending window. Since the actual completion
  1705. ** event requires the user to be called, state can change. So the easiest thing to do is defer these
  1706. ** completion callbacks until we are finished walking and can release any state locks. Also, this way
  1707. ** we can defer the callbacks until after we have indicated any data which the acks were piggybacking on,
  1708. ** something which ought to have priority anyway.
  1709. **
  1710. ** So we will place all completed reliable sends onto a complete list and after all other processing
  1711. ** we will come here and callback everything on the list.
  1712. */
  1713. #undef DPF_MODNAME
  1714. #define DPF_MODNAME "CompleteSends"
  1715. VOID CompleteSends(PEPD pEPD)
  1716. {
  1717. PMSD pMSD;
  1718. CBilink *pLink;
  1719. Lock(&pEPD->EPLock);
  1720. pLink = pEPD->blCompleteSendList.GetNext();
  1721. while((pEPD->ulEPFlags & EPFLAGS_COMPLETE_SENDS) &&
  1722. (pLink != &pEPD->blCompleteSendList))
  1723. {
  1724. pMSD = CONTAINING_RECORD(pLink, MSD, blQLinkage);
  1725. ASSERT_MSD(pMSD);
  1726. if(pMSD->CommandID != COMMAND_ID_SEND_DATAGRAM)
  1727. {
  1728. // Reliables, Keepalives, and Disconnects will come down this path
  1729. if(pMSD->ulMsgFlags2 & (MFLAGS_TWO_SEND_COMPLETE|MFLAGS_TWO_ABORT))
  1730. {
  1731. if (pMSD->uiFrameCount == 0)
  1732. {
  1733. DPFX(DPFPREP, DPF_FRAMECNT_LVL, "Completing, pMSD[%p], framecount[%u]", pMSD, pMSD->uiFrameCount);
  1734. pLink->RemoveFromList();
  1735. Unlock(&pEPD->EPLock);
  1736. Lock(&pMSD->CommandLock);
  1737. CompleteReliableSend(pEPD->pSPD, pMSD, DPN_OK); // This releases the CommandLock
  1738. Lock(&pEPD->EPLock);
  1739. pLink = pEPD->blCompleteSendList.GetNext();
  1740. }
  1741. else
  1742. {
  1743. DPFX(DPFPREP, DPF_FRAMECNT_LVL, "Frames still out, pMSD[%p], framecount[%u]", pMSD, pMSD->uiFrameCount);
  1744. pLink = pLink->GetNext();
  1745. }
  1746. }
  1747. else
  1748. {
  1749. DPFX(DPFPREP, DPF_FRAMECNT_LVL, "Message not yet complete, pMSD[%p], framecount[%u]", pMSD, pMSD->uiFrameCount);
  1750. break; // These will complete in order, so stop checking when we see one that's not Complete.
  1751. }
  1752. }
  1753. else
  1754. {
  1755. // Datagrams will come down this path
  1756. DPFX(DPFPREP, DPF_FRAMECNT_LVL, "Skipping datagram frame on complete list, pMSD[%p], framecount[%u]", pMSD, pMSD->uiFrameCount);
  1757. pLink = pLink->GetNext();
  1758. }
  1759. }
  1760. #ifdef DEBUG
  1761. // In DEBUG we want to assert that no one one the list could have been completed if we are leaving here
  1762. pLink = pEPD->blCompleteSendList.GetNext();
  1763. while(pLink != &pEPD->blCompleteSendList)
  1764. {
  1765. pMSD = CONTAINING_RECORD(pLink, MSD, blQLinkage);
  1766. ASSERT_MSD(pMSD);
  1767. ASSERT(!(pMSD->ulMsgFlags2 & (MFLAGS_TWO_SEND_COMPLETE|MFLAGS_TWO_ABORT)) || pMSD->uiFrameCount != 0);
  1768. pLink = pLink->GetNext();
  1769. }
  1770. #endif
  1771. pEPD->ulEPFlags &= ~(EPFLAGS_COMPLETE_SENDS);
  1772. Unlock(&pEPD->EPLock);
  1773. }
  1774. /*
  1775. ** Lookup CheckPoint
  1776. **
  1777. ** Walk the EndPoint's list of active CPs looking for one with the provided
  1778. ** response correlator.
  1779. ** We keep the CKPT queue sorted by age so the matches should be at the front
  1780. ** of the queue. So as we pass by entries at the head we will check the age of each
  1781. ** and timeout the ones that are 4(RTT) or greater.
  1782. ** Since DG drops are reported by the partner, we dont need to do any booking about
  1783. ** the orphaned checkpoints.
  1784. **
  1785. ** *!* This link's StateLock must be held on entry
  1786. */
  1787. #ifdef DEBUG
  1788. #undef DPF_MODNAME
  1789. #define DPF_MODNAME "DumpChkPtList"
  1790. VOID
  1791. DumpChkPtList(PEPD pEPD)
  1792. {
  1793. CBilink *pLink;
  1794. PCHKPT pCP;
  1795. AssertCriticalSectionIsTakenByThisThread(&pEPD->EPLock, TRUE);
  1796. DPFX(DPFPREP,1, "==== DUMPING CHECKPOINT LIST ==== (pEPD = %p)", pEPD);
  1797. pLink = pEPD->blChkPtQueue.GetNext();
  1798. while(pLink != &pEPD->blChkPtQueue)
  1799. {
  1800. pCP = CONTAINING_RECORD(pLink, CHKPT, blLinkage);
  1801. DPFX(DPFPREP,1, "(%p) MsgID=%x; Timestamp=%x", pEPD, pCP->bMsgID, pCP->tTimestamp);
  1802. pLink = pLink->GetNext();
  1803. }
  1804. }
  1805. #endif
  1806. #undef DPF_MODNAME
  1807. #define DPF_MODNAME "LookupCheckPoint"
  1808. PCHKPT LookupCheckPoint(PEPD pEPD, BYTE bRspID)
  1809. {
  1810. CBilink *pLink;
  1811. PCHKPT pCP;
  1812. AssertCriticalSectionIsTakenByThisThread(&pEPD->EPLock, TRUE);
  1813. pCP = CONTAINING_RECORD((pLink = pEPD->blChkPtQueue.GetNext()), CHKPT, blLinkage);
  1814. while(pLink != &pEPD->blChkPtQueue)
  1815. {
  1816. // Look for checkpoint that matches correlator
  1817. if(pCP->bMsgID == bRspID)
  1818. {
  1819. pLink->RemoveFromList();
  1820. return pCP;
  1821. }
  1822. // We have passed the spot for this correlator!
  1823. else if ((bRspID - pCP->bMsgID) & 0x80)
  1824. {
  1825. DPFX(DPFPREP,1, "(%p) CHECKPOINT NOT FOUND - Later Chkpt found in list (%x)", pEPD, bRspID);
  1826. return NULL;
  1827. }
  1828. else
  1829. {
  1830. pLink = pLink->GetNext(); // Remove ChkPts prior to the one received
  1831. pCP->blLinkage.RemoveFromList(); // ..target and remove the stale ones.
  1832. ChkPtPool->Release(ChkPtPool, pCP); // we expect them to complete in order of queue
  1833. pCP = CONTAINING_RECORD(pLink, CHKPT, blLinkage);
  1834. }
  1835. }
  1836. DPFX(DPFPREP,1, "(%p) CHECKPOINT NOT FOUND - EXHAUSTED LIST W/O MATCH (%x)", pEPD, bRspID);
  1837. #ifdef DEBUG
  1838. DumpChkPtList(pEPD);
  1839. #endif
  1840. return NULL;
  1841. }
  1842. #undef DPF_MODNAME
  1843. #define DPF_MODNAME "FlushCheckPoints"
  1844. VOID FlushCheckPoints(PEPD pEPD)
  1845. {
  1846. PCHKPT pCP;
  1847. AssertCriticalSectionIsTakenByThisThread(&pEPD->EPLock, TRUE);
  1848. while(!pEPD->blChkPtQueue.IsEmpty())
  1849. {
  1850. pCP = CONTAINING_RECORD(pEPD->blChkPtQueue.GetNext(), CHKPT, blLinkage);
  1851. pCP->blLinkage.RemoveFromList();
  1852. ChkPtPool->Release(ChkPtPool, pCP);
  1853. }
  1854. }
  1855. /*
  1856. ** Process End Of Stream
  1857. **
  1858. ** Our partner has initiated an orderly link termination. He will not be
  1859. ** sending us any more data. We are allowed to finish sending any data in our
  1860. ** pipeline, but should not allow any new sends to be accepted. When our send
  1861. ** pipeline is emptied, we should send an EOS frame and take down our
  1862. ** link. Easiest way to do this is enqueue the EOS at the end of send queue now.
  1863. */
  1864. #undef DPF_MODNAME
  1865. #define DPF_MODNAME "ProcessEndOfStream"
  1866. VOID ProcessEndOfStream(PEPD pEPD)
  1867. {
  1868. PMSD pMSD;
  1869. Lock(&pEPD->EPLock);
  1870. // Since an EOS comes in as a data packet, and we must be Connected to receive data, we know
  1871. // we can now be in either the Connected or Terminating state. If we are in the Terminating
  1872. // state, someone is already attempting to destroy the link and we will ignore this EOS, and
  1873. // let that termination finish. Otherwise, we expect to be in the Connected state, and this
  1874. // is a normal disconnect.
  1875. if (pEPD->ulEPFlags & EPFLAGS_STATE_TERMINATING)
  1876. {
  1877. DPFX(DPFPREP,7, "(%p) Received EndOfStream on an already terminating link, ignoring", pEPD);
  1878. Unlock(&pEPD->EPLock);
  1879. return;
  1880. }
  1881. ASSERT(pEPD->ulEPFlags & EPFLAGS_STATE_CONNECTED);
  1882. DPFX(DPFPREP,7, "(%p) Process EndOfStream", pEPD);
  1883. // Have we started closing on this side?
  1884. if(!(pEPD->ulEPFlags & EPFLAGS_RECEIVED_DISCONNECT))
  1885. {
  1886. // Our side has not started closing yet, so our partner must have initiated a Disconnect.
  1887. // We are allowed to finish sending all data in our pipeline, but we should not accept
  1888. // any new data. We must deliver an indication to the application telling him that
  1889. // Disconnection is now underway.
  1890. //
  1891. // Please note that we do not set the TERMINATING flag until the Disconnecting indication
  1892. // returns. This allows the application to send any final messages (last words) before
  1893. // the gate is slammed shut.
  1894. DPFX(DPFPREP,7, "(%p) Partner Disconnect received (refcnt=%d)", pEPD, pEPD->lRefCnt);
  1895. // Don't let anyone else in here again.
  1896. pEPD->ulEPFlags |= EPFLAGS_RECEIVED_DISCONNECT;
  1897. // Force 3 disconnect ACKs now since we are going away.
  1898. // Setting fFinalAck to TRUE on last ACK so CommandComplete will drop if appropriate
  1899. DPFX(DPFPREP,7, "(%p) ACK'ing Partner's Disconnect", pEPD);
  1900. SendAckFrame(pEPD, 0);
  1901. SendAckFrame(pEPD, 0);
  1902. SendAckFrame(pEPD, 0, TRUE);
  1903. // There is the possibility that this side initiated a disconnect, and is now receiving a
  1904. // disconnect from the other side simultaneously. In this case, we do not want to tell the
  1905. // Core on our side about the disconnect, because the Core on our side is already disconnecting
  1906. // anyway. We also do not need to send an EOS, because we have sent one already, and can
  1907. // just wait for that one to be ACK'd.
  1908. if(!(pEPD->ulEPFlags & EPFLAGS_SENT_DISCONNECT))
  1909. {
  1910. // We know we won't get in here twice because of EPFLAGS_RECEIVED_DISCONNECT above.
  1911. Unlock(&pEPD->EPLock);
  1912. DPFX(DPFPREP,DPF_CALLOUT_LVL, "(%p) Calling Core->IndicateDisconnect, Core Context[%p]", pEPD, pEPD->Context);
  1913. pEPD->pSPD->pPData->pfVtbl->IndicateDisconnect(pEPD->pSPD->pPData->Parent, pEPD->Context);
  1914. Lock(&pEPD->EPLock);
  1915. // This will prevent any new sends, so don't set it until after calling IndicateDisconnect.
  1916. pEPD->ulEPFlags |= EPFLAGS_SENT_DISCONNECT;
  1917. if((pMSD = BuildDisconnectFrame(pEPD)) == NULL)
  1918. {
  1919. DropLink(pEPD); // DROPLINK will release EPLock for us
  1920. return;
  1921. }
  1922. pMSD->CommandID = COMMAND_ID_DISC_RESPONSE; // Mark MSD so we know its not a user command
  1923. LOCK_EPD(pEPD, "LOCK (DISC RESP)"); // Add reference for this frame
  1924. pEPD->pCommand = pMSD; // Store the DisconnectResp on the Endpoint until it is complete
  1925. DPFX(DPFPREP,7, "(%p) Responding to Disconnect. pMSD=0x%p", pEPD, pMSD);
  1926. EnqueueMessage(pMSD, pEPD); // Enqueue the DISC frame at end of sendQ
  1927. }
  1928. }
  1929. Unlock(&pEPD->EPLock);
  1930. }
  1931. /*
  1932. ** Process SP Disconnect
  1933. **
  1934. ** Service Provider has told us that an endpoint has gone away. This is probably
  1935. ** because we have Disconnected it ourselves, in which case the IN_USE flag will be
  1936. ** clear. Otherwise, we need to clean this thing up ourselves...
  1937. */
  1938. #undef DPF_MODNAME
  1939. #define DPF_MODNAME "ProcessSPDisconnect"
  1940. VOID
  1941. ProcessSPDisconnect(PSPD pSPD, PSPIE_DISCONNECT pDataBlock)
  1942. {
  1943. PEPD pEPD = static_cast<PEPD>( pDataBlock->pEndpointContext );
  1944. ASSERT_EPD(pEPD);
  1945. ASSERT(pEPD->pSPD == pSPD);
  1946. PMSD pMSD = NULL;
  1947. DPFX(DPFPREP,DPF_CALLIN_LVL, "Parameters: pSPD[%p], pDataBlock[%p] - pEPD[%p]", pSPD, pDataBlock, pEPD);
  1948. Lock(&pEPD->EPLock);
  1949. // Make sure ReleaseEPD knows that this occurred
  1950. pEPD->ulEPFlags |= EPFLAGS_SP_DISCONNECTED;
  1951. if (!(pEPD->ulEPFlags & EPFLAGS_STATE_TERMINATING))
  1952. {
  1953. DECREMENT_EPD(pEPD, "SP reference"); // Remove the SP reference
  1954. // If there is an outstanding connection, clean it up
  1955. if (pEPD->ulEPFlags & (EPFLAGS_STATE_CONNECTING|EPFLAGS_STATE_DORMANT))
  1956. {
  1957. // Even if this is COMMAND_ID_CONNECT this is safe to do
  1958. pEPD->ulEPFlags &= ~(EPFLAGS_LINKED_TO_LISTEN);
  1959. pEPD->blSPLinkage.RemoveFromList(); // Unlink EPD from Listen Queue
  1960. // We know this will only happen once because the person who does it will transition us out
  1961. // of the CONNECTING state, and we can't get here unless we are in that state.
  1962. pMSD = pEPD->pCommand;
  1963. pEPD->pCommand = NULL;
  1964. }
  1965. DropLink(pEPD); // This will release the EPLock
  1966. if (pMSD)
  1967. {
  1968. Lock(&pMSD->CommandLock);
  1969. RELEASE_MSD(pMSD, "EPD Ref");
  1970. }
  1971. }
  1972. else
  1973. {
  1974. RELEASE_EPD(pEPD, "SP reference"); // releases EPLock
  1975. }
  1976. }
  1977. /*
  1978. ** Process Listen Status
  1979. **
  1980. ** This call tells us that a submitted Listen command has become active. Truth is, we
  1981. ** dont care. We are just interested in seeing the Connect indications as they arrive. What we
  1982. ** do care about, however, is the Endpoint handle associated with this listen in case we are
  1983. ** later asked about the address associated with the listen. So we will pull it out of the
  1984. ** data block and save it in our MSD.
  1985. */
  1986. #undef DPF_MODNAME
  1987. #define DPF_MODNAME "ProcessListenStatus"
  1988. VOID
  1989. ProcessListenStatus(PSPD pSPD, PSPIE_LISTENSTATUS pDataBlock)
  1990. {
  1991. PMSD pMSD;
  1992. DPFX(DPFPREP,DPF_CALLIN_LVL, "Parameters: pSPD[%p], pDataBlock[%p] - hr=%x", pSPD, pDataBlock, pDataBlock->hResult);
  1993. pMSD = (PMSD) pDataBlock->pUserContext;
  1994. ASSERT_MSD(pMSD);
  1995. ASSERT(pMSD->pSPD == pSPD);
  1996. ASSERT(pMSD->CommandID == COMMAND_ID_LISTEN);
  1997. pMSD->hListenEndpoint = pDataBlock->hEndpoint;
  1998. DPFX(DPFPREP,DPF_CALLOUT_LVL, "Calling Core->CompleteListen, pMSD[%p], Core Context[%p], hr[%x]", pMSD, pMSD->Context, pDataBlock->hResult);
  1999. pSPD->pPData->pfVtbl->CompleteListen(pSPD->pPData->Parent, &pMSD->Context, pDataBlock->hResult, pDataBlock->hEndpoint);
  2000. if(pDataBlock->hResult != DPN_OK)
  2001. {
  2002. // Release the final reference on the MSD AFTER indicating to the Core
  2003. Lock(&pMSD->CommandLock);
  2004. RELEASE_MSD(pMSD, "Release On Complete");
  2005. }
  2006. return;
  2007. }
  2008. /*
  2009. ** Process Connect Address Info
  2010. **
  2011. ** This call tells us what addressing information has been used to start a connect.
  2012. */
  2013. #undef DPF_MODNAME
  2014. #define DPF_MODNAME "ProcessConnectAddressInfo"
  2015. VOID
  2016. ProcessConnectAddressInfo(PSPD pSPD, PSPIE_CONNECTADDRESSINFO pDataBlock)
  2017. {
  2018. PMSD pMSD;
  2019. pMSD = (PMSD) pDataBlock->pCommandContext;
  2020. DPFX(DPFPREP,DPF_CALLIN_LVL, "Parameters: pSPD[%p], pDataBlock[%p] - pMSD[%p]", pSPD, pDataBlock, pMSD);
  2021. ASSERT_MSD(pMSD);
  2022. ASSERT(pMSD->pSPD == pSPD);
  2023. ASSERT(pMSD->CommandID == COMMAND_ID_CONNECT);
  2024. DPFX(DPFPREP,DPF_CALLOUT_LVL, "(%p) Calling Core->AddressInfoConnect, Core Context[%p]", pMSD, pMSD->Context);
  2025. pSPD->pPData->pfVtbl->AddressInfoConnect( pSPD->pPData->Parent,
  2026. pMSD->Context,
  2027. pDataBlock->hCommandStatus,
  2028. pDataBlock->pHostAddress,
  2029. pDataBlock->pDeviceAddress );
  2030. return;
  2031. }
  2032. /*
  2033. ** Process Enum Address Info
  2034. **
  2035. ** This call tells us what addressing information has been used to start an enum.
  2036. */
  2037. #undef DPF_MODNAME
  2038. #define DPF_MODNAME "ProcessEnumAddressInfo"
  2039. VOID
  2040. ProcessEnumAddressInfo(PSPD pSPD, PSPIE_ENUMADDRESSINFO pDataBlock)
  2041. {
  2042. PMSD pMSD;
  2043. pMSD = (PMSD) pDataBlock->pCommandContext;
  2044. DPFX(DPFPREP,DPF_CALLIN_LVL, "Parameters: pSPD[%p], pDataBlock[%p] - pMSD[%p]", pSPD, pDataBlock, pMSD);
  2045. ASSERT_MSD(pMSD);
  2046. ASSERT(pMSD->pSPD == pSPD);
  2047. ASSERT(pMSD->CommandID == COMMAND_ID_ENUM );
  2048. DPFX(DPFPREP,DPF_CALLOUT_LVL, "(%p) Calling Core->AddressInfoEnum, Core Context[%p]", pMSD, pMSD->Context);
  2049. pSPD->pPData->pfVtbl->AddressInfoEnum( pSPD->pPData->Parent,
  2050. pMSD->Context,
  2051. pDataBlock->hCommandStatus,
  2052. pDataBlock->pHostAddress,
  2053. pDataBlock->pDeviceAddress );
  2054. return;
  2055. }
  2056. /*
  2057. ** Process Listen Address Info
  2058. **
  2059. ** This call tells us what addressing information has been used to start a listen.
  2060. */
  2061. #undef DPF_MODNAME
  2062. #define DPF_MODNAME "ProcessListenAddressInfo"
  2063. VOID
  2064. ProcessListenAddressInfo(PSPD pSPD, PSPIE_LISTENADDRESSINFO pDataBlock)
  2065. {
  2066. PMSD pMSD;
  2067. pMSD = (PMSD) pDataBlock->pCommandContext;
  2068. DPFX(DPFPREP,DPF_CALLIN_LVL, "Parameters: pSPD[%p], pDataBlock[%p] - pMSD[%p]", pSPD, pDataBlock, pMSD);
  2069. ASSERT_MSD(pMSD);
  2070. ASSERT(pMSD->pSPD == pSPD);
  2071. ASSERT(pMSD->CommandID == COMMAND_ID_LISTEN );
  2072. DPFX(DPFPREP,DPF_CALLOUT_LVL, "(%p) Calling Core->AddressInfoListen, Core Context[%p]", pMSD, pMSD->Context);
  2073. pSPD->pPData->pfVtbl->AddressInfoListen( pSPD->pPData->Parent,
  2074. pMSD->Context,
  2075. pDataBlock->hCommandStatus,
  2076. pDataBlock->pDeviceAddress );
  2077. return;
  2078. }
  2079. /*************************************
  2080. **
  2081. ** RECEIVE BUFFER MANAGEMENT
  2082. **
  2083. ** When multiple frame messages arrive we *may* have to copy them in to a single contiguous
  2084. ** buffer. We are supporting an OPTIONAL scatter-receive option which would allow sophisticated
  2085. ** clients to receive a BUFFER_DESCRIPTOR array instead of a single cont-buffer, and avoiding
  2086. ** a large datacopy.
  2087. **
  2088. ** For clients which dont support scatter-receive, we need a pooling strategy for large receive
  2089. ** buffers. We will only need buffers LARGER then our frame limit because smaller receives are delivered
  2090. ** in the SPs buffer.
  2091. **
  2092. ** Try placing receives into generally sized buffers. If frame size is usu 1.4K bytes, 2K is a small
  2093. ** buffer, 4K, 16K, 32K, 64K. If frame size is <1K we can have 1K buffers too.
  2094. **
  2095. **
  2096. *************************************/
  2097. /***********************
  2098. ========SPACER==========
  2099. ************************/
  2100. /*
  2101. ** RCD Pool support routines
  2102. **
  2103. ** These are the functions called by Fixed Pool Manager as it handles RCDs.
  2104. */
  2105. #define pELEMENT ((PRCD) pElement)
  2106. #undef DPF_MODNAME
  2107. #define DPF_MODNAME "RCD_Allocate"
  2108. BOOL RCD_Allocate(PVOID pElement)
  2109. {
  2110. DPFX(DPFPREP,7, "(%p) Allocating new RCD", pELEMENT);
  2111. pELEMENT->blOddFrameLinkage.Initialize();
  2112. pELEMENT->blCompleteLinkage.Initialize();
  2113. pELEMENT->Sign = RCD_SIGN;
  2114. return TRUE;
  2115. }
  2116. // Get is called each time an MSD is used
  2117. #undef DPF_MODNAME
  2118. #define DPF_MODNAME "RCD_Get"
  2119. VOID RCD_Get(PVOID pElement)
  2120. {
  2121. DPFX(DPFPREP,DPF_REFCNT_FINAL_LVL, "CREATING RCD %p", pELEMENT);
  2122. // NOTE: First sizeof(PVOID) bytes will have been overwritten by the pool code,
  2123. // we must set them to acceptable values.
  2124. pELEMENT->pRcvBuff = NULL;
  2125. pELEMENT->lRefCnt = 1;
  2126. pELEMENT->ulRFlags = 0;
  2127. ASSERT_RCD(pELEMENT);
  2128. }
  2129. // RCD Release -- This release call will release an entire chain of RCDs
  2130. // that are linked together... or then again maybe not.
  2131. #undef DPF_MODNAME
  2132. #define DPF_MODNAME "RCD_Release"
  2133. VOID RCD_Release(PVOID pElement)
  2134. {
  2135. ASSERT_RCD(pELEMENT);
  2136. ASSERT(pELEMENT->lRefCnt == 0);
  2137. ASSERT(pELEMENT->pRcvBuff == NULL);
  2138. DPFX(DPFPREP,DPF_REFCNT_FINAL_LVL, "RELEASING RCD %p", pELEMENT);
  2139. }
  2140. #undef DPF_MODNAME
  2141. #define DPF_MODNAME "RCD_Free"
  2142. VOID RCD_Free(PVOID pElement)
  2143. {
  2144. }
  2145. #undef pELEMENT
  2146. /*
  2147. ** Buffer pool support
  2148. **
  2149. **
  2150. */
  2151. #define pELEMENT ((PBUF) pElement)
  2152. #undef DPF_MODNAME
  2153. #define DPF_MODNAME "Buf_Allocate"
  2154. BOOL Buf_Allocate(PVOID pElement)
  2155. {
  2156. DPFX(DPFPREP,7, "(%p) Allocating new Buf", pElement);
  2157. return TRUE;
  2158. }
  2159. #undef DPF_MODNAME
  2160. #define DPF_MODNAME "Buf_Get"
  2161. VOID Buf_Get(PVOID pElement)
  2162. {
  2163. // NOTE: First sizeof(PVOID) bytes will have been overwritten by the pool code,
  2164. // we must set them to acceptable values.
  2165. pELEMENT->Type = RBT_PROTOCOL_BUFFER;
  2166. pELEMENT->Owner = BufPool;
  2167. }
  2168. #undef DPF_MODNAME
  2169. #define DPF_MODNAME "Buf_GetMed"
  2170. VOID Buf_GetMed(PVOID pElement)
  2171. {
  2172. // NOTE: First sizeof(PVOID) bytes will have been overwritten by the pool code,
  2173. // we must set them to acceptable values.
  2174. pELEMENT->Type = RBT_PROTOCOL_BUFFER;
  2175. pELEMENT->Owner = MedBufPool;
  2176. }
  2177. #undef DPF_MODNAME
  2178. #define DPF_MODNAME "Buf_GetBig"
  2179. VOID Buf_GetBig(PVOID pElement)
  2180. {
  2181. // NOTE: First sizeof(PVOID) bytes will have been overwritten by the pool code,
  2182. // we must set them to acceptable values.
  2183. pELEMENT->Type = RBT_PROTOCOL_BUFFER;
  2184. pELEMENT->Owner = BigBufPool;
  2185. }
  2186. #undef pELEMENT