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

679 lines
30 KiB

  1. /****************************************************************************/
  2. /* tdapi.c */
  3. /* */
  4. /* Transport driver - portable specific API */
  5. /* */
  6. /* Copyright (C) 1997-1999 Microsoft Corporation */
  7. /****************************************************************************/
  8. #include <adcg.h>
  9. extern "C" {
  10. #define TRC_FILE "tdapi"
  11. #define TRC_GROUP TRC_GROUP_NETWORK
  12. #include <atrcapi.h>
  13. }
  14. #include "autil.h"
  15. #include "td.h"
  16. #include "xt.h"
  17. #include "nl.h"
  18. CTD::CTD(CObjs* objs)
  19. {
  20. _pClientObjects = objs;
  21. }
  22. CTD::~CTD()
  23. {
  24. }
  25. /****************************************************************************/
  26. /* Name: TD_Init */
  27. /* */
  28. /* Purpose: Initializes the transport driver. This is called on the */
  29. /* receiver thread. */
  30. /****************************************************************************/
  31. DCVOID DCAPI CTD::TD_Init(DCVOID)
  32. {
  33. DC_BEGIN_FN("TD_Init");
  34. _pNl = _pClientObjects->_pNlObject;
  35. _pUt = _pClientObjects->_pUtObject;
  36. _pXt = _pClientObjects->_pXTObject;
  37. _pUi = _pClientObjects->_pUiObject;
  38. _pCd = _pClientObjects->_pCdObject;
  39. /************************************************************************/
  40. /* Initialize the global data and set the initial FSM state. */
  41. /************************************************************************/
  42. DC_MEMSET(&_TD, 0, sizeof(_TD));
  43. _TD.fsmState = TD_ST_NOTINIT;
  44. /************************************************************************/
  45. /* Call the FSM. */
  46. /************************************************************************/
  47. TDConnectFSMProc(TD_EVT_TDINIT, 0);
  48. DC_END_FN();
  49. } /* TD_Init */
  50. /****************************************************************************/
  51. /* Name: TD_Term */
  52. /* */
  53. /* Purpose: Terminates the transport driver. This is called on the */
  54. /* receiver thread. */
  55. /****************************************************************************/
  56. DCVOID DCAPI CTD::TD_Term(DCVOID)
  57. {
  58. DC_BEGIN_FN("TD_Term");
  59. /************************************************************************/
  60. /* Call the FSM. */
  61. /************************************************************************/
  62. TDConnectFSMProc(TD_EVT_TDTERM, 0);
  63. DC_END_FN();
  64. } /* TD_Term */
  65. /****************************************************************************/
  66. /* Name: TD_Connect */
  67. /* */
  68. /* Purpose: Connects to a remote server. Called on the receiver thread. */
  69. /* */
  70. /* Params: */
  71. /* IN bInitateConnect : TRUE if we are making connection, */
  72. /* FALSE if connect with already connected socket */
  73. /* */
  74. /****************************************************************************/
  75. DCVOID DCAPI CTD::TD_Connect(BOOL bInitateConnect, PDCTCHAR pServerAddress)
  76. {
  77. DCUINT i;
  78. DCUINT errorCode;
  79. u_long addr;
  80. DCUINT nextEvent;
  81. ULONG_PTR eventData;
  82. DCACHAR ansiBuffer[256];
  83. DC_BEGIN_FN("TD_Connect");
  84. /************************************************************************/
  85. /* Check that the string is not null. */
  86. /************************************************************************/
  87. if( bInitateConnect )
  88. {
  89. TRC_ASSERT((0 != *pServerAddress),
  90. (TB, _T("Server address is NULL")));
  91. }
  92. /************************************************************************/
  93. /* Check that all the buffers are not in-use. */
  94. /************************************************************************/
  95. for (i = 0; i < TD_SNDBUF_PUBNUM; i++)
  96. {
  97. if (_TD.pubSndBufs[i].inUse)
  98. {
  99. TD_TRACE_SENDINFO(TRC_LEVEL_ERR);
  100. TRC_ABORT((TB, _T("Public buffer %u still in-use"), i));
  101. }
  102. }
  103. for (i = 0; i < TD_SNDBUF_PRINUM; i++)
  104. {
  105. if (_TD.priSndBufs[i].inUse)
  106. {
  107. TD_TRACE_SENDINFO(TRC_LEVEL_ERR);
  108. TRC_ABORT((TB, _T("Private buffer %u still in-use"), i));
  109. }
  110. }
  111. /************************************************************************/
  112. /* Trace out the send buffer information. */
  113. /************************************************************************/
  114. TD_TRACE_SENDINFO(TRC_LEVEL_NRM);
  115. if( FALSE == bInitateConnect )
  116. {
  117. TDConnectFSMProc(TD_EVT_CONNECTWITHENDPOINT, NULL);
  118. DC_QUIT; // all we need is the buffer.
  119. }
  120. #ifdef UNICODE
  121. /************************************************************************/
  122. /* WinSock 1.1 only supports ANSI, so we need to convert any Unicode */
  123. /* strings at this point. */
  124. /************************************************************************/
  125. if (!WideCharToMultiByte(CP_ACP,
  126. 0,
  127. pServerAddress,
  128. -1,
  129. ansiBuffer,
  130. 256,
  131. NULL,
  132. NULL))
  133. {
  134. /********************************************************************/
  135. /* Conversion failed */
  136. /********************************************************************/
  137. TRC_ERR((TB, _T("Failed to convert address to ANSI")));
  138. /********************************************************************/
  139. /* Generate the error code. */
  140. /********************************************************************/
  141. errorCode = NL_MAKE_DISCONNECT_ERR(NL_ERR_TDANSICONVERT);
  142. TRC_ASSERT((HIWORD(errorCode) == 0),
  143. (TB, _T("disconnect reason code unexpectedly using 32 bits")));
  144. _pXt->XT_OnTDDisconnected(errorCode);
  145. }
  146. #else
  147. DC_ASTRCPY(ansiBuffer, pServerAddress);
  148. #endif /* UNICODE */
  149. /************************************************************************/
  150. /* Check that the address is not the limited broadcast address */
  151. /* (255.255.255.255). */
  152. /************************************************************************/
  153. if (0 == DC_ASTRCMP(ansiBuffer, TD_LIMITED_BROADCAST_ADDRESS))
  154. {
  155. TRC_ALT((TB, _T("Cannot connect to the limited broadcast address")));
  156. /********************************************************************/
  157. /* Generate the error code. */
  158. /********************************************************************/
  159. errorCode = NL_MAKE_DISCONNECT_ERR(NL_ERR_TDBADIPADDRESS);
  160. TRC_ASSERT((HIWORD(errorCode) == 0),
  161. (TB, _T("disconnect reason code unexpectedly using 32 bits")));
  162. _pXt->XT_OnTDDisconnected(errorCode);
  163. DC_QUIT;
  164. }
  165. /************************************************************************/
  166. /* Now determine whether a DNS lookup is required. */
  167. /************************************************************************/
  168. TRC_NRM((TB, _T("ServerAddress:%s"), ansiBuffer));
  169. /************************************************************************/
  170. /* Check that we have a string and that the address is not the limited */
  171. /* broadcast address. */
  172. /************************************************************************/
  173. TRC_ASSERT((NULL != ansiBuffer), (TB, _T("ansiBuffer is NULL")));
  174. TRC_ASSERT(('\0' != ansiBuffer[0]),
  175. (TB, _T("Empty server address string")));
  176. TRC_ASSERT((0 != DC_ASTRCMP(ansiBuffer, TD_LIMITED_BROADCAST_ADDRESS)),
  177. (TB, _T("Cannot connect to the limited broadcast address")));
  178. /************************************************************************/
  179. /* Check for a dotted-IP address string. */
  180. /************************************************************************/
  181. addr = inet_addr(ansiBuffer);
  182. TRC_NRM((TB, _T("Address returned is %#lx"), addr));
  183. /************************************************************************/
  184. /* Now determine whether this is an address string or a host name. */
  185. /* Note that inet_addr doesn't distinguish between an invalid IP */
  186. /* address and the limited broadcast address (255.255.255.255). */
  187. /* However since we don't allow the limited broadcast address and have */
  188. /* already checked explicitly for it we don't need to worry about this */
  189. /* case. */
  190. /************************************************************************/
  191. if (INADDR_NONE == addr)
  192. {
  193. /********************************************************************/
  194. /* This looks like a host name so call the FSM with the current */
  195. /* address. */
  196. /********************************************************************/
  197. TRC_NRM((TB, _T("%s looks like a hostname - need DNS lookup"),
  198. ansiBuffer));
  199. nextEvent = TD_EVT_TDCONNECT_DNS;
  200. eventData = (ULONG_PTR) ansiBuffer;
  201. }
  202. else
  203. {
  204. /********************************************************************/
  205. /* If we get here then it appears to be a dotted-IP address. Call */
  206. /* the FSM with the updated address. */
  207. /********************************************************************/
  208. TRC_NRM((TB, _T("%s looks like a dotted-IP address:%lu"),
  209. ansiBuffer,
  210. addr));
  211. nextEvent = TD_EVT_TDCONNECT_IP;
  212. eventData = addr;
  213. }
  214. /************************************************************************/
  215. /* Now call the FSM with the appropriate parameters. */
  216. /************************************************************************/
  217. TDConnectFSMProc(nextEvent, eventData);
  218. DC_EXIT_POINT:
  219. DC_END_FN();
  220. } /* TD_Connect */
  221. /****************************************************************************/
  222. /* Name: TD_Disconnect */
  223. /* */
  224. /* Purpose: Disconnects from the server. This is called on the receiver */
  225. /* thread. */
  226. /****************************************************************************/
  227. DCVOID DCAPI CTD::TD_Disconnect(DCVOID)
  228. {
  229. DC_BEGIN_FN("TD_Disconnect");
  230. /************************************************************************/
  231. /* Call the FSM. We pass NL_DISCONNECT_LOCAL which will be used as the */
  232. /* return code to XT in the cases where we are waiting for the DNS */
  233. /* lookup to return or the socket to connect. */
  234. /************************************************************************/
  235. TDConnectFSMProc(TD_EVT_TDDISCONNECT, NL_DISCONNECT_LOCAL);
  236. DC_END_FN();
  237. } /* TD_Disconnect */
  238. //
  239. // TD_DropLink - drops the link immediately (ungracefully)
  240. //
  241. VOID
  242. CTD::TD_DropLink(DCVOID)
  243. {
  244. DC_BEGIN_FN("TD_DropLink");
  245. TDConnectFSMProc(TD_EVT_DROPLINK, NL_DISCONNECT_LOCAL);
  246. DC_END_FN();
  247. }
  248. /****************************************************************************/
  249. /* Name: TD_GetPublicBuffer */
  250. /* */
  251. /* Purpose: Attempts to allocate a buffer from the public TD buffer pool. */
  252. /* */
  253. /* Returns: If the allocation succeeds then this function returns TRUE */
  254. /* otherwise it returns FALSE. */
  255. /* */
  256. /* Params: IN dataLength - length of the buffer requested. */
  257. /* OUT ppBuffer - a pointer to a pointer to the buffer. */
  258. /* OUT pBufHandle - a pointer to a buffer handle. */
  259. /****************************************************************************/
  260. DCBOOL DCAPI CTD::TD_GetPublicBuffer(DCUINT dataLength,
  261. PPDCUINT8 ppBuffer,
  262. PTD_BUFHND pBufHandle)
  263. {
  264. DCUINT i;
  265. DCBOOL rc = FALSE;
  266. DCUINT lastfree = TD_SNDBUF_PUBNUM;
  267. PDCUINT8 pbOldBuffer;
  268. DCUINT cbOldBuffer;
  269. DC_BEGIN_FN("TD_GetPublicBuffer");
  270. // Check that we're in the correct state. If we're disconnected
  271. // then fail the call. Note that the FSM state is maintained by the
  272. // receiver thread - but we're on the sender thread.
  273. if (_TD.fsmState == TD_ST_CONNECTED) {
  274. TRC_DBG((TB, _T("Searching for a buffer big enough for %u bytes"),
  275. dataLength));
  276. // Trace out the send buffer information.
  277. TD_TRACE_SENDINFO(TRC_LEVEL_DBG);
  278. // Search the array of buffers looking for the first free one that is
  279. // large enough.
  280. for (i = 0; i < TD_SNDBUF_PUBNUM; i++) {
  281. TRC_DBG((TB, _T("Trying buf:%u inUse:%s size:%u"),
  282. i,
  283. _TD.pubSndBufs[i].inUse ? "TRUE" : "FALSE",
  284. _TD.pubSndBufs[i].size));
  285. if(!_TD.pubSndBufs[i].inUse)
  286. {
  287. lastfree = i;
  288. }
  289. if ((!(_TD.pubSndBufs[i].inUse)) &&
  290. (_TD.pubSndBufs[i].size >= dataLength)) {
  291. TRC_DBG((TB, _T("bufHandle:%p (idx:%u) free - size:%u (req:%u)"),
  292. &_TD.pubSndBufs[i], i, _TD.pubSndBufs[i].size,
  293. dataLength));
  294. // Now mark this buffer as being in use and set up the return
  295. // values. The handle is just a pointer to the buffer
  296. // information structure.
  297. _TD.pubSndBufs[i].inUse = TRUE;
  298. *ppBuffer = _TD.pubSndBufs[i].pBuffer;
  299. *pBufHandle = (TD_BUFHND) (PDCVOID)&_TD.pubSndBufs[i];
  300. // Set a good return code.
  301. rc = TRUE;
  302. // Check that the other fields are set correctly.
  303. TRC_ASSERT((_TD.pubSndBufs[i].pNext == NULL),
  304. (TB, _T("Buf:%u next non-zero"), i));
  305. TRC_ASSERT((_TD.pubSndBufs[i].bytesLeftToSend == 0),
  306. (TB, _T("Buf:%u bytesLeftToSend non-zero"), i));
  307. TRC_ASSERT((_TD.pubSndBufs[i].pDataLeftToSend == NULL),
  308. (TB, _T("Buf:%u pDataLeftToSend non-null"), i));
  309. // Update the performance counter.
  310. PRF_INC_COUNTER(PERF_PKTS_ALLOCATED);
  311. // That's all we need to do so just quit.
  312. DC_QUIT;
  313. }
  314. }
  315. // check if we need to re-allocate
  316. if(lastfree < TD_SNDBUF_PUBNUM)
  317. {
  318. pbOldBuffer = _TD.pubSndBufs[lastfree].pBuffer;
  319. cbOldBuffer = _TD.pubSndBufs[lastfree].size;
  320. // reallocate space
  321. TDAllocBuf(
  322. &_TD.pubSndBufs[lastfree],
  323. dataLength
  324. );
  325. // TDAllocBuf() return DCVOID with UI_FatalError()
  326. if( NULL != _TD.pubSndBufs[lastfree].pBuffer )
  327. {
  328. UT_Free( _pUt, pbOldBuffer );
  329. // Now mark this buffer as being in use and set up the return
  330. // values. The handle is just a pointer to the buffer
  331. // information structure.
  332. _TD.pubSndBufs[lastfree].inUse = TRUE;
  333. *ppBuffer = _TD.pubSndBufs[lastfree].pBuffer;
  334. *pBufHandle = (TD_BUFHND) (PDCVOID)&_TD.pubSndBufs[lastfree];
  335. // Set a good return code.
  336. rc = TRUE;
  337. // Update the performance counter.
  338. PRF_INC_COUNTER(PERF_PKTS_ALLOCATED);
  339. // That's all we need to do so just quit.
  340. DC_QUIT;
  341. }
  342. else
  343. {
  344. // restore pointer and size.
  345. _TD.pubSndBufs[lastfree].pBuffer = pbOldBuffer;
  346. _TD.pubSndBufs[lastfree].size = cbOldBuffer;
  347. }
  348. }
  349. // We failed to find a free buffer. Trace the send buffer info.
  350. _TD.getBufferFailed = TRUE;
  351. TRC_ALT((TB, _T("Failed to find a free buffer (req dataLength:%u) Bufs:"),
  352. dataLength));
  353. TD_TRACE_SENDINFO(TRC_LEVEL_ALT);
  354. }
  355. else {
  356. TRC_NRM((TB, _T("Not connected therefore fail get buffer call")));
  357. }
  358. DC_EXIT_POINT:
  359. DC_END_FN();
  360. return rc;
  361. } /* TD_GetPublicBuffer */
  362. /****************************************************************************/
  363. /* Name: TD_GetPrivateBuffer */
  364. /* */
  365. /* Purpose: Attempts to allocate a buffer from the private TD buffer */
  366. /* pool. */
  367. /* */
  368. /* Returns: If the allocation succeeds then this function returns TRUE */
  369. /* otherwise it returns FALSE. */
  370. /* */
  371. /* Params: IN dataLength - length of the buffer requested. */
  372. /* OUT ppBuffer - a pointer to a pointer to the buffer. */
  373. /* OUT pBufHandle - a pointer to a buffer handle. */
  374. /* */
  375. /* Operation: This function should always return a buffer - it it up to */
  376. /* the network layer to ensure that it does not allocate more */
  377. /* buffers than are available in the private list. */
  378. /****************************************************************************/
  379. DCBOOL DCAPI CTD::TD_GetPrivateBuffer(DCUINT dataLength,
  380. PPDCUINT8 ppBuffer,
  381. PTD_BUFHND pBufHandle)
  382. {
  383. DCUINT i;
  384. DCBOOL rc = FALSE;
  385. DC_BEGIN_FN("TD_GetPrivateBuffer");
  386. // Check that we're in the correct state. If we're disconnected
  387. // then fail the call. Note that the FSM state is maintained by the
  388. // receiver thread - but we're on the sender thread.
  389. if (_TD.fsmState == TD_ST_CONNECTED) {
  390. TRC_DBG((TB, _T("Searching for a buffer big enough for %u bytes"),
  391. dataLength));
  392. // Trace out the send buffer information.
  393. TD_TRACE_SENDINFO(TRC_LEVEL_DBG);
  394. // Search the array of buffers looking for the first free one that is
  395. // large enough.
  396. for (i = 0; i < TD_SNDBUF_PRINUM; i++) {
  397. TRC_DBG((TB, _T("Trying buf:%u inUse:%s size:%u"),
  398. i,
  399. _TD.priSndBufs[i].inUse ? "TRUE" : "FALSE",
  400. _TD.priSndBufs[i].size));
  401. if ((!(_TD.priSndBufs[i].inUse)) &&
  402. (_TD.priSndBufs[i].size >= dataLength)) {
  403. TRC_DBG((TB, _T("bufHandle:%p (idx:%u) free - size:%u (req:%u)"),
  404. &_TD.priSndBufs[i], i, _TD.priSndBufs[i].size,
  405. dataLength));
  406. // Now mark this buffer as being in use and set up the return
  407. // values. The handle is just a pointer to the buffer
  408. // information structure.
  409. _TD.priSndBufs[i].inUse = TRUE;
  410. *ppBuffer = _TD.priSndBufs[i].pBuffer;
  411. *pBufHandle = (TD_BUFHND) (PDCVOID)&_TD.priSndBufs[i];
  412. // Set a good return code.
  413. rc = TRUE;
  414. // Check that the other fields are set correctly.
  415. TRC_ASSERT((_TD.priSndBufs[i].pNext == NULL),
  416. (TB, _T("Buf:%u next non-zero"), i));
  417. TRC_ASSERT((_TD.priSndBufs[i].bytesLeftToSend == 0),
  418. (TB, _T("Buf:%u bytesLeftToSend non-zero"), i));
  419. TRC_ASSERT((_TD.priSndBufs[i].pDataLeftToSend == NULL),
  420. (TB, _T("Buf:%u pDataLeftToSend non-null"), i));
  421. // That's all we need to do so just quit.
  422. DC_QUIT;
  423. }
  424. }
  425. // We failed to find a free buffer - flag this internal error by
  426. // tracing out the entire buffer structure and then aborting.
  427. TD_TRACE_SENDINFO(TRC_LEVEL_ERR);
  428. TRC_ABORT((TB, _T("Failed to find a free buffer (req dataLength:%u)"),
  429. dataLength));
  430. }
  431. else {
  432. TRC_NRM((TB, _T("Not connected therefore fail get buffer call")));
  433. }
  434. DC_EXIT_POINT:
  435. DC_END_FN();
  436. return(rc);
  437. } /* TD_GetPrivateBuffer */
  438. /****************************************************************************/
  439. /* Name: TD_SendBuffer */
  440. /* */
  441. /* Purpose: Sends a buffer. The buffer is added to the end of the */
  442. /* pending queue and all data on the pending queue is then */
  443. /* sent. */
  444. /* */
  445. /* Params: IN pData - pointer to the start of the data. */
  446. /* IN dataLength - amount of the buffer used. */
  447. /* IN bufHandle - handle to a buffer. */
  448. /****************************************************************************/
  449. DCVOID DCAPI CTD::TD_SendBuffer(PDCUINT8 pData,
  450. DCUINT dataLength,
  451. TD_BUFHND bufHandle)
  452. {
  453. PTD_SNDBUF_INFO pNext;
  454. PTD_SNDBUF_INFO pHandle = (PTD_SNDBUF_INFO) bufHandle;
  455. DC_BEGIN_FN("TD_SendBuffer");
  456. // Trace out the function parameters.
  457. TRC_DBG((TB, _T("bufHandle:%p dataLength:%u pData:%p"), bufHandle,
  458. dataLength, pData));
  459. // Check that the handle is valid.
  460. TRC_ASSERT((((pHandle >= &_TD.pubSndBufs[0]) &&
  461. (pHandle <= &_TD.pubSndBufs[TD_SNDBUF_PUBNUM - 1])) ||
  462. ((pHandle >= &_TD.priSndBufs[0]) &&
  463. (pHandle <= &_TD.priSndBufs[TD_SNDBUF_PRINUM - 1]))),
  464. (TB, _T("Invalid buffer handle:%p"), bufHandle));
  465. // Verify buffer contents.
  466. TRC_ASSERT((0 == pHandle->bytesLeftToSend),
  467. (TB, _T("pHandle->bytesLeftToSend non-zero (pHandle:%p)"), pHandle));
  468. TRC_ASSERT((NULL == pHandle->pDataLeftToSend),
  469. (TB, _T("pHandle->pDataLeftToSend non NULL (pHandle:%p)"), pHandle));
  470. TRC_ASSERT((NULL != pHandle->pBuffer),
  471. (TB, _T("pHandle->pBuffer is NULL (pHandle:%p)"), pHandle));
  472. TRC_ASSERT((NULL == pHandle->pNext),
  473. (TB, _T("pHandle->pNext (pHandle:%p) non NULL"), pHandle));
  474. TRC_ASSERT((pHandle->inUse), (TB, _T("pHandle %p is not in-use"), pHandle));
  475. // Check that pData lies within the buffer and pData+dataLength does not
  476. // overrun the end.
  477. TRC_ASSERT(((pData >= pHandle->pBuffer) &&
  478. (pData < (pHandle->pBuffer + pHandle->size))),
  479. (TB, _T("pData lies outwith range")));
  480. TRC_ASSERT(((pData + dataLength) <= (pHandle->pBuffer + pHandle->size)),
  481. (TB, _T("pData + dataLength over the end of the buffer")));
  482. //
  483. // Update the fields in the buffer information structure and add to the
  484. // pending buffer queue.
  485. //
  486. pHandle->pDataLeftToSend = pData;
  487. pHandle->bytesLeftToSend = dataLength;
  488. if (NULL == _TD.pFQBuf) {
  489. TRC_DBG((TB, _T("Inserted buffer:%p at queue head"), pHandle));
  490. _TD.pFQBuf = pHandle;
  491. }
  492. else {
  493. // OK - the queue is not empty. We need to scan through the queue
  494. // looking for the first empty slot to insert this buffer in at.
  495. pNext = _TD.pFQBuf;
  496. while (NULL != pNext->pNext)
  497. pNext = pNext->pNext;
  498. // Update the next field of the this buffer information structure.
  499. pNext->pNext = pHandle;
  500. TRC_DBG((TB, _T("Inserted buffer:%p"), pHandle));
  501. }
  502. // Finally attempt to flush the send queue.
  503. TDFlushSendQueue(0);
  504. DC_END_FN();
  505. } /* TD_SendBuffer */
  506. /****************************************************************************/
  507. /* Name: TD_FreeBuffer */
  508. /* */
  509. /* Purpose: Frees the passed buffer. */
  510. /****************************************************************************/
  511. DCVOID DCAPI CTD::TD_FreeBuffer(TD_BUFHND bufHandle)
  512. {
  513. PTD_SNDBUF_INFO pHandle = (PTD_SNDBUF_INFO) bufHandle;
  514. DC_BEGIN_FN("TD_FreeBuffer");
  515. // Trace out the function parameters.
  516. TRC_DBG((TB, _T("bufHandle:%p"), bufHandle));
  517. // Check that the handle is valid.
  518. TRC_ASSERT((((pHandle >= &_TD.pubSndBufs[0]) &&
  519. (pHandle <= &_TD.pubSndBufs[TD_SNDBUF_PUBNUM - 1])) ||
  520. ((pHandle >= &_TD.priSndBufs[0]) &&
  521. (pHandle <= &_TD.priSndBufs[TD_SNDBUF_PRINUM - 1]))),
  522. (TB, _T("Invalid buffer handle:%p"), bufHandle));
  523. // Verify the buffer contents. InUse does not matter, we can legitimately
  524. // free a non-in-use buffer.
  525. TRC_ASSERT((0 == pHandle->bytesLeftToSend),
  526. (TB, _T("pHandle->bytesLeftToSend non-zero (pHandle:%p)"), pHandle));
  527. TRC_ASSERT((NULL == pHandle->pDataLeftToSend),
  528. (TB, _T("pHandle->pDataLeftToSend non NULL (pHandle:%p)"), pHandle));
  529. TRC_ASSERT((NULL != pHandle->pBuffer),
  530. (TB, _T("pHandle->pBuffer is NULL (pHandle:%p)"), pHandle));
  531. TRC_ASSERT((NULL == pHandle->pNext),
  532. (TB, _T("pHandle->pNext (pHandle:%p) non NULL"), pHandle));
  533. // Free the buffer.
  534. pHandle->inUse = FALSE;
  535. // Update the performance counter.
  536. PRF_INC_COUNTER(PERF_PKTS_FREED);
  537. DC_END_FN();
  538. } /* TD_FreeBuffer */
  539. #ifdef DC_DEBUG
  540. /****************************************************************************/
  541. /* Name: TD_SetBufferOwner */
  542. /* */
  543. /* Purpose: Note the owner of a TD buffer */
  544. /* */
  545. /* Params: bufHandle - handle to the buffer */
  546. /* pOwner - name of the 'owner' */
  547. /****************************************************************************/
  548. DCVOID DCAPI CTD::TD_SetBufferOwner(TD_BUFHND bufHandle, PDCTCHAR pOwner)
  549. {
  550. PTD_SNDBUF_INFO pHandle = (PTD_SNDBUF_INFO) bufHandle;
  551. DC_BEGIN_FN("TD_SetBufferOwner");
  552. /************************************************************************/
  553. /* Trace out the function parameters. */
  554. /************************************************************************/
  555. TRC_DBG((TB, _T("bufHandle:%p owner %s"), bufHandle, pOwner));
  556. /************************************************************************/
  557. /* Check that the handle is valid. */
  558. /************************************************************************/
  559. TRC_ASSERT((((pHandle >= &_TD.pubSndBufs[0]) &&
  560. (pHandle <= &_TD.pubSndBufs[TD_SNDBUF_PUBNUM - 1])) ||
  561. ((pHandle >= &_TD.priSndBufs[0]) &&
  562. (pHandle <= &_TD.priSndBufs[TD_SNDBUF_PRINUM - 1]))),
  563. (TB, _T("Invalid buffer handle:%p"), bufHandle));
  564. /************************************************************************/
  565. /* Save the owner */
  566. /************************************************************************/
  567. pHandle->pOwner = pOwner;
  568. DC_END_FN();
  569. } /* TD_SetBufferOwner */
  570. #endif/* DC_DEBUG */