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.

1497 lines
73 KiB

  1. /****************************************************************************/
  2. // mcsint.cpp
  3. //
  4. // MCS internal portable functions.
  5. //
  6. // Copyright (C) 1997-1999 Microsoft Corporation
  7. /****************************************************************************/
  8. #include <adcg.h>
  9. extern "C" {
  10. #define TRC_FILE "amcsint"
  11. #define TRC_GROUP TRC_GROUP_NETWORK
  12. #include <atrcapi.h>
  13. }
  14. #include "autil.h"
  15. #include "mcs.h"
  16. #include "cd.h"
  17. #include "xt.h"
  18. #include "nc.h"
  19. #include "nl.h"
  20. /****************************************************************************/
  21. /* Name: MCSSendConnectInitial */
  22. /* */
  23. /* Purpose: This function generates and sends a MCS connect-initial PDU. */
  24. /****************************************************************************/
  25. DCVOID DCINTERNAL CMCS::MCSSendConnectInitial(ULONG_PTR unused)
  26. {
  27. XT_BUFHND bufHandle;
  28. PDCUINT8 pData = NULL;
  29. DCUINT pduLength;
  30. DCUINT dataLength;
  31. DCBOOL intRC;
  32. MCS_PDU_CONNECTINITIAL ciPDU = MCS_DATA_CONNECTINITIAL;
  33. DC_BEGIN_FN("MCSSendConnectInitial");
  34. DC_IGNORE_PARAMETER(unused);
  35. /************************************************************************/
  36. /* Calculate the size of the data to send. The pdu length is the size */
  37. /* of the Connect-Initial header plus the user data. The data length */
  38. /* is the length transmitted in the length field of the PDU, which */
  39. /* doesn't include the PDU type (2 bytes) or the length field (3 */
  40. /* bytes). Thus we need to subtract 5 bytes. */
  41. /************************************************************************/
  42. pduLength = sizeof(ciPDU) + _MCS.userDataLength;
  43. dataLength = pduLength - 5;
  44. TRC_NRM((TB, _T("CI total length:%u (data:%u) (hc:%u user-data:%u)"),
  45. pduLength,
  46. dataLength,
  47. sizeof(ciPDU),
  48. _MCS.userDataLength));
  49. /************************************************************************/
  50. /* Assume that the total CI length is less than the maximum MCS send */
  51. /* packet size. */
  52. /************************************************************************/
  53. TRC_ASSERT((dataLength <= MCS_MAX_SNDPKT_LENGTH),
  54. (TB, _T("Datalength out of range: %u"), dataLength));
  55. TRC_ASSERT((_MCS.pReceivedPacket != NULL), (TB, _T("Null rcv packet buffer")));
  56. /************************************************************************/
  57. /* Update the MCS CI header with the data size. */
  58. /************************************************************************/
  59. ciPDU.length = MCSLocalToWire16((DCUINT16)dataLength);
  60. /************************************************************************/
  61. /* Update the MCS user-data octet string length. */
  62. /************************************************************************/
  63. ciPDU.udLength = MCSLocalToWire16((DCUINT16)_MCS.userDataLength);
  64. /************************************************************************/
  65. /* Get a private buffer from XT. */
  66. /************************************************************************/
  67. intRC = _pXt->XT_GetPrivateBuffer(pduLength, &pData, &bufHandle);
  68. if (!intRC)
  69. {
  70. /********************************************************************/
  71. /* We've failed to get a private buffer. This ONLY happens when TD */
  72. /* has disconnected while the layers above are still trying to */
  73. /* connect. Since TD has now disconnected and is refusing to give */
  74. /* us a buffer we might as well just give up trying to get a */
  75. /* buffer. */
  76. /********************************************************************/
  77. TRC_NRM((TB, _T("Failed to get a private buffer - just quit")));
  78. DC_QUIT;
  79. }
  80. /************************************************************************/
  81. /* Now fill in the buffer that we've just got. */
  82. /************************************************************************/
  83. DC_MEMCPY(pData, &ciPDU, sizeof(ciPDU));
  84. DC_MEMCPY((pData + sizeof(ciPDU)),
  85. _MCS.pReceivedPacket,
  86. _MCS.userDataLength);
  87. /************************************************************************/
  88. /* Trace out the PDU. */
  89. /************************************************************************/
  90. TRC_DATA_NRM("Connect-Initial PDU", pData, pduLength);
  91. /************************************************************************/
  92. /* Send the buffer. If everything has worked OK, we should receive a */
  93. /* Connect-Response PDU shortly. */
  94. /************************************************************************/
  95. _pXt->XT_SendBuffer(pData, pduLength, bufHandle);
  96. DC_EXIT_POINT:
  97. DC_END_FN();
  98. } /* MCSSendConnectInitial */
  99. /****************************************************************************/
  100. /* Name: MCSSendErectDomainRequest */
  101. /* */
  102. /* Purpose: Generates and sends an Erect-Domain-Request (EDrq) PDU. */
  103. /****************************************************************************/
  104. DCVOID DCINTERNAL CMCS::MCSSendErectDomainRequest(ULONG_PTR unused)
  105. {
  106. PDCUINT8 pData = NULL;
  107. XT_BUFHND bufHandle;
  108. DCBOOL intRC;
  109. MCS_PDU_ERECTDOMAINREQUEST edrPDU = MCS_DATA_ERECTDOMAINREQUEST;
  110. DC_BEGIN_FN("MCSSendErectDomainRequest");
  111. DC_IGNORE_PARAMETER(unused);
  112. /************************************************************************/
  113. /* Get a internal send buffer from XT. */
  114. /************************************************************************/
  115. intRC = _pXt->XT_GetPrivateBuffer(sizeof(edrPDU), &pData, &bufHandle);
  116. if (!intRC)
  117. {
  118. /********************************************************************/
  119. /* We've failed to get a private buffer. This ONLY happens when TD */
  120. /* has disconnected while the layers above are still trying to */
  121. /* connect. Since TD has now disconnected and is refusing to give */
  122. /* us a buffer we might as well just give up trying to get a */
  123. /* buffer. */
  124. /********************************************************************/
  125. TRC_NRM((TB, _T("Failed to get a private buffer - just quit")));
  126. DC_QUIT;
  127. }
  128. /************************************************************************/
  129. /* Now fill in the buffer with the AUR PDU. */
  130. /************************************************************************/
  131. DC_MEMCPY(pData, &edrPDU, sizeof(edrPDU));
  132. TRC_DATA_NRM("EDR PDU:", &edrPDU, sizeof(edrPDU));
  133. /************************************************************************/
  134. /* Now send the buffer. */
  135. /************************************************************************/
  136. TRC_NRM((TB, _T("Sending EDR PDU...")));
  137. _pXt->XT_SendBuffer(pData, sizeof(edrPDU), bufHandle);
  138. DC_EXIT_POINT:
  139. DC_END_FN();
  140. } /* MCSSendErectDomainRequest */
  141. /****************************************************************************/
  142. /* Name: MCSSendAttachUserRequest */
  143. /* */
  144. /* Purpose: Generates and sends an MCS Attach-User-Request (AUrq) PDU. */
  145. /****************************************************************************/
  146. DCVOID DCINTERNAL CMCS::MCSSendAttachUserRequest(ULONG_PTR unused)
  147. {
  148. PDCUINT8 pData = NULL;
  149. XT_BUFHND bufHandle;
  150. DCBOOL intRC;
  151. MCS_PDU_ATTACHUSERREQUEST aurPDU = MCS_DATA_ATTACHUSERREQUEST;
  152. DC_BEGIN_FN("MCSSendAttachUserRequest");
  153. DC_IGNORE_PARAMETER(unused);
  154. /************************************************************************/
  155. /* Get a internal send buffer from XT. */
  156. /************************************************************************/
  157. intRC = _pXt->XT_GetPrivateBuffer(sizeof(aurPDU), &pData, &bufHandle);
  158. if (!intRC)
  159. {
  160. /********************************************************************/
  161. /* We've failed to get a private buffer. This ONLY happens when TD */
  162. /* has disconnected while the layers above are still trying to */
  163. /* connect. Since TD has now disconnected and is refusing to give */
  164. /* us a buffer we might as well just give up trying to get a */
  165. /* buffer. */
  166. /********************************************************************/
  167. TRC_NRM((TB, _T("Failed to get a private buffer - just quit")));
  168. DC_QUIT;
  169. }
  170. /************************************************************************/
  171. /* Now fill in the buffer with the AUR PDU. */
  172. /************************************************************************/
  173. DC_MEMCPY(pData, &aurPDU, sizeof(aurPDU));
  174. TRC_DATA_NRM("AUR PDU:", &aurPDU, sizeof(aurPDU));
  175. /************************************************************************/
  176. /* Now send the buffer. */
  177. /************************************************************************/
  178. TRC_NRM((TB, _T("Sending AUR PDU...")));
  179. _pXt->XT_SendBuffer(pData, sizeof(aurPDU), bufHandle);
  180. DC_EXIT_POINT:
  181. DC_END_FN();
  182. return;
  183. } /* MCSSendAttachUserRequest */
  184. /****************************************************************************/
  185. /* Name: MCSSendChannelJoinRequest */
  186. /* */
  187. /* Purpose: Generates and sends a Channel-Join-Request (CJrq) PDU. */
  188. /* */
  189. /* Params: IN channelID - the channel ID to join. */
  190. /****************************************************************************/
  191. DCVOID DCINTERNAL CMCS::MCSSendChannelJoinRequest(PDCVOID pData, DCUINT dataLen)
  192. {
  193. PDCUINT8 pBuffer = NULL;
  194. XT_BUFHND bufHandle;
  195. DCBOOL intRC;
  196. MCS_PDU_CHANNELJOINREQUEST cjrPDU = MCS_DATA_CHANNELJOINREQUEST;
  197. PMCS_DECOUPLEINFO pDecoupleInfo = (PMCS_DECOUPLEINFO)pData;
  198. DC_BEGIN_FN("MCSSendChannelJoinRequest");
  199. DC_IGNORE_PARAMETER(dataLen);
  200. TRC_NRM((TB, _T("Join channel:%#x for user:%#x"),
  201. pDecoupleInfo->channel,
  202. pDecoupleInfo->userID));
  203. /************************************************************************/
  204. /* Assert that the hiword of the channel is 0. */
  205. /************************************************************************/
  206. TRC_ASSERT((0 == HIWORD((DCUINT32)pDecoupleInfo->channel)),
  207. (TB, _T("Hi-word of channel is non-zero")));
  208. /************************************************************************/
  209. /* Assert that the hiword of the user-id is 0. */
  210. /************************************************************************/
  211. TRC_ASSERT((0 == HIWORD((DCUINT32)pDecoupleInfo->userID)),
  212. (TB, _T("Hi-word of userID is non-zero")));
  213. /************************************************************************/
  214. /* Add the channel and user ids. */
  215. /************************************************************************/
  216. cjrPDU.initiator =
  217. MCSLocalUserIDToWireUserID((DCUINT16)pDecoupleInfo->userID);
  218. cjrPDU.channelID = MCSLocalToWire16((DCUINT16)pDecoupleInfo->channel);
  219. /************************************************************************/
  220. /* Get a internal send buffer from XT. */
  221. /************************************************************************/
  222. intRC = _pXt->XT_GetPrivateBuffer(sizeof(cjrPDU), &pBuffer, &bufHandle);
  223. if (!intRC)
  224. {
  225. /********************************************************************/
  226. /* We've failed to get a private buffer. This ONLY happens when TD */
  227. /* has disconnected while the layers above are still trying to */
  228. /* connect. Since TD has now disconnected and is refusing to give */
  229. /* us a buffer we might as well just give up trying to get a */
  230. /* buffer. */
  231. /********************************************************************/
  232. TRC_NRM((TB, _T("Failed to get a private buffer - just quit")));
  233. DC_QUIT;
  234. }
  235. /************************************************************************/
  236. /* Now fill in the buffer with the CJR PDU. */
  237. /************************************************************************/
  238. DC_MEMCPY(pBuffer, &cjrPDU, sizeof(cjrPDU));
  239. TRC_DATA_NRM("CJR PDU:", &cjrPDU, sizeof(cjrPDU));
  240. /************************************************************************/
  241. /* Now send the buffer. */
  242. /************************************************************************/
  243. TRC_NRM((TB, _T("Sending Channel-Join-Request PDU...")));
  244. _pXt->XT_SendBuffer(pBuffer, sizeof(cjrPDU), bufHandle);
  245. DC_EXIT_POINT:
  246. DC_END_FN();
  247. } /* MCSSendChannelJoinRequest */
  248. /****************************************************************************/
  249. /* Name: MCSSendDisconnectProviderUltimatum */
  250. /* */
  251. /* Purpose: Generates and sends a Disconnect-Provider-Ultimatum (DPum) */
  252. /* PDU with the reason code set to rn-user-requested. */
  253. /****************************************************************************/
  254. DCVOID DCINTERNAL CMCS::MCSSendDisconnectProviderUltimatum(ULONG_PTR unused)
  255. {
  256. PDCUINT8 pData = NULL;
  257. XT_BUFHND bufHandle;
  258. DCBOOL intRC;
  259. MCS_PDU_DISCONNECTPROVIDERUM dpumPDU = MCS_DATA_DISCONNECTPROVIDERUM;
  260. DC_BEGIN_FN("MCSSendDisconnectProviderUltimatum");
  261. DC_IGNORE_PARAMETER(unused);
  262. /************************************************************************/
  263. /* Get a internal send buffer from XT. */
  264. /************************************************************************/
  265. intRC = _pXt->XT_GetPrivateBuffer(sizeof(dpumPDU), &pData, &bufHandle);
  266. if (!intRC)
  267. {
  268. /********************************************************************/
  269. /* We've failed to get a private buffer. This ONLY happens when TD */
  270. /* has disconnected while the layers above are still trying to */
  271. /* connect. Since TD has now disconnected and is refusing to give */
  272. /* us a buffer we might as well just give up trying to get a */
  273. /* buffer. */
  274. /********************************************************************/
  275. TRC_NRM((TB, _T("Failed to get a private buffer - just quit")));
  276. DC_QUIT;
  277. }
  278. /************************************************************************/
  279. /* Now fill in the buffer with the DPum PDU. */
  280. /************************************************************************/
  281. DC_MEMCPY(pData, &dpumPDU, sizeof(dpumPDU));
  282. TRC_DATA_NRM("DPUM PDU:", &dpumPDU, sizeof(dpumPDU));
  283. /************************************************************************/
  284. /* Now send the buffer. */
  285. /************************************************************************/
  286. TRC_NRM((TB, _T("Sending Disconnect-Provider-Ultimatum PDU...")));
  287. _pXt->XT_SendBuffer(pData, sizeof(dpumPDU), bufHandle);
  288. DC_EXIT_POINT:
  289. /************************************************************************/
  290. /* We don't get any feedback for this PDU (i.e. there is no */
  291. /* Disconnect-Provider-Confirm PDU), so we need to decouple back to */
  292. /* the receiver thread and get it to begin disconnecting the layers */
  293. /* below. */
  294. /************************************************************************/
  295. TRC_NRM((TB, _T("Decouple to receiver thrd and call MCSContinueDisconnect")));
  296. _pCd->CD_DecoupleSimpleNotification(CD_RCV_COMPONENT, this,
  297. CD_NOTIFICATION_FUNC(CMCS,MCSContinueDisconnect),
  298. (ULONG_PTR) 0);
  299. DC_END_FN();
  300. } /* MCSSendDisconnectProviderUltimatum */
  301. /****************************************************************************/
  302. /* Name: MCSContinueDisconnect */
  303. /* */
  304. /* Purpose: Continue the disconnect processing on the receiver thread */
  305. /* after having sent a MCS DPum on the sender thread. */
  306. /****************************************************************************/
  307. DCVOID DCINTERNAL CMCS::MCSContinueDisconnect(ULONG_PTR unused)
  308. {
  309. DC_BEGIN_FN("MCSContinueDisconnect");
  310. DC_IGNORE_PARAMETER(unused);
  311. /************************************************************************/
  312. /* Just call XT_Disconnect. */
  313. /************************************************************************/
  314. TRC_NRM((TB, _T("Disconnect lower layers - call XT_Disconnect")));
  315. _pXt->XT_Disconnect();
  316. DC_END_FN();
  317. } /* MCSContinueDisconnect */
  318. /****************************************************************************/
  319. /* Name: MCSGetSDRHeaderLength */
  320. /* */
  321. /* Purpose: This function calculates the length of a Send-Data-Request */
  322. /* PDU header based on the length of the data passed in. */
  323. /* */
  324. /* Returns: The length of the SDR header required for dataLength bytes */
  325. /* of data. */
  326. /* */
  327. /* Params: IN dataLength - the length of the data to base the header */
  328. /* calculation on. */
  329. /****************************************************************************/
  330. DCUINT DCINTERNAL CMCS::MCSGetSDRHeaderLength(DCUINT dataLength)
  331. {
  332. DCUINT headerLength;
  333. DC_BEGIN_FN("MCSGetSDRHeaderLength");
  334. /************************************************************************/
  335. /* Check that we're being asked to send less than the maximum amount */
  336. /* of data. */
  337. /************************************************************************/
  338. TRC_ASSERT((dataLength < MCS_MAX_SNDPKT_LENGTH),
  339. (TB, _T("Too much data to send:%u"), dataLength));
  340. /************************************************************************/
  341. /* Calculate the maximum size of a MCS data header. This is comprised */
  342. /* of a constant length part (which contains pkt type, user-id etc) and */
  343. /* a variable size field which encodes the length of the user-data */
  344. /* according to the PER encoding rules. */
  345. /* */
  346. /* First get the length of the constant part. */
  347. /************************************************************************/
  348. headerLength = sizeof(MCS_PDU_SENDDATAREQUEST);
  349. /************************************************************************/
  350. /* Now use the length of the data to calculate how many bytes are */
  351. /* required to encode it. */
  352. /************************************************************************/
  353. if (dataLength < 128)
  354. {
  355. /********************************************************************/
  356. /* We need only one byte to encode the length of the data. */
  357. /********************************************************************/
  358. headerLength += 1;
  359. }
  360. else
  361. {
  362. /********************************************************************/
  363. /* We need two bytes to encode the length of the data. */
  364. /********************************************************************/
  365. headerLength += 2;
  366. }
  367. TRC_DBG((TB, _T("Returning header length of:%u for data length:%u"),
  368. headerLength,
  369. dataLength));
  370. DC_END_FN();
  371. return(headerLength);
  372. } /* MCSGetSDRHeaderLength */
  373. /****************************************************************************/
  374. /* Name: MCSRecvToHdrBuf */
  375. /* */
  376. /* Purpose: Receives data into the header buffer. */
  377. /* */
  378. /* Returns: TRUE if the receive bytes needed count is zero, FALSE */
  379. /* otherwise. */
  380. /****************************************************************************/
  381. DCBOOL DCINTERNAL CMCS::MCSRecvToHdrBuf(DCVOID)
  382. {
  383. DCUINT bytesRecv;
  384. DCBOOL rc;
  385. DC_BEGIN_FN("MCSRecvToHdrBuf");
  386. TRC_ASSERT((NULL != _MCS.pHdrBuf), (TB, _T("No MCS header buffer!")));
  387. /************************************************************************/
  388. /* Make sure that we're expected to receive some data. */
  389. /************************************************************************/
  390. TRC_ASSERT((_MCS.hdrBytesNeeded != 0), (TB, _T("No data to receive")));
  391. /************************************************************************/
  392. /* Reallocate a larger buffer for the header if the current one is too */
  393. /* small to contain the incoming data. */
  394. /************************************************************************/
  395. if( _MCS.hdrBufLen < _MCS.hdrBytesRead + _MCS.hdrBytesNeeded )
  396. {
  397. PDCUINT8 pNewHdrBuf;
  398. pNewHdrBuf = (PDCUINT8)UT_Malloc( _pUt, _MCS.hdrBytesRead + _MCS.hdrBytesNeeded );
  399. if( NULL == pNewHdrBuf )
  400. {
  401. TRC_ABORT((TB,
  402. _T("Cannot allocate memory to receive MCS header (%u)"),
  403. _MCS.hdrBytesNeeded + _MCS.hdrBytesRead));
  404. return( FALSE );
  405. }
  406. DC_MEMCPY( pNewHdrBuf, _MCS.pHdrBuf, _MCS.hdrBytesRead );
  407. UT_Free( _pUt, _MCS.pHdrBuf );
  408. _MCS.pHdrBuf = pNewHdrBuf;
  409. _MCS.hdrBufLen = _MCS.hdrBytesRead + _MCS.hdrBytesNeeded;
  410. }
  411. /************************************************************************/
  412. /* Get some data into the header buffer. */
  413. /************************************************************************/
  414. bytesRecv = _pXt->XT_Recv(_MCS.pHdrBuf + _MCS.hdrBytesRead, _MCS.hdrBytesNeeded);
  415. TRC_DBG((TB, _T("Received %u of %u needed bytes"),
  416. bytesRecv,
  417. _MCS.hdrBytesNeeded));
  418. /************************************************************************/
  419. /* Update the receive byte counts. */
  420. /************************************************************************/
  421. _MCS.hdrBytesNeeded -= bytesRecv;
  422. _MCS.hdrBytesRead += bytesRecv;
  423. /************************************************************************/
  424. /* Determine if we've got all the bytes that we need. */
  425. /************************************************************************/
  426. if (0 == _MCS.hdrBytesNeeded)
  427. {
  428. /********************************************************************/
  429. /* We've got all that we were asked for - return TRUE. */
  430. /********************************************************************/
  431. TRC_DBG((TB, _T("Got all the bytes needed")));
  432. rc = TRUE;
  433. }
  434. else
  435. {
  436. /********************************************************************/
  437. /* We need to wait for some more bytes. */
  438. /********************************************************************/
  439. TRC_NRM((TB, _T("Wait for %u more bytes"), _MCS.hdrBytesNeeded));
  440. rc = FALSE;
  441. }
  442. DC_END_FN();
  443. return(rc);
  444. } /* MCSRecvToHdrBuf */
  445. /****************************************************************************/
  446. /* Name: MCSGetPERInfo */
  447. /* */
  448. /* Purpose: This function identifies PER PDUs based on the first byte in */
  449. /* the header buffer and also calculates how many additional */
  450. /* header bytes are needed for a complete PDU. */
  451. /* */
  452. /* Params: OUT pType - the PDU type. */
  453. /* OUT pSize - the number of additional header bytes needed. */
  454. /****************************************************************************/
  455. DCVOID DCINTERNAL CMCS::MCSGetPERInfo(PDCUINT pType, PDCUINT pSize)
  456. {
  457. DC_BEGIN_FN("MCSGetPERInfo");
  458. TRC_ASSERT((NULL != pType), (TB, _T("pType is NULL")));
  459. TRC_ASSERT((NULL != pSize), (TB, _T("pSize is NULL")));
  460. /************************************************************************/
  461. /* Trace out the header buffer. */
  462. /************************************************************************/
  463. TRC_DATA_DBG("Header buffer contains", _MCS.pHdrBuf, _MCS.hdrBytesRead);
  464. /************************************************************************/
  465. /* This a PER encoded PDU. The six most-significant bits of the first */
  466. /* byte contain the PDU type - mask out the remainder. */
  467. /************************************************************************/
  468. *pType = _MCS.pHdrBuf[0] & MCS_PDUTYPEMASK;
  469. /************************************************************************/
  470. /* Check for PDU types that we don't expect to receive. If we get any */
  471. /* of the following then we disconnect as the server is asking us to do */
  472. /* things that we can't do - and which will require a response from us. */
  473. /************************************************************************/
  474. if ((MCS_TYPE_ATTACHUSERREQUEST == *pType) ||
  475. (MCS_TYPE_DETACHUSERREQUEST == *pType) ||
  476. (MCS_TYPE_CHANNELJOINREQUEST == *pType) ||
  477. (MCS_TYPE_SENDDATAREQUEST == *pType))
  478. {
  479. TRC_ABORT((TB, _T("Unexpected MCS PDU type:%#x"), *pType));
  480. MCSSetReasonAndDisconnect(NL_ERR_MCSUNEXPECTEDPDU);
  481. DC_QUIT;
  482. }
  483. /************************************************************************/
  484. /* Now calculate the number of bytes that we still need for the */
  485. /* different PDU types. This is the size of the PDU minus the number */
  486. /* of bytes that we've read so far. */
  487. /************************************************************************/
  488. switch (*pType)
  489. {
  490. case MCS_TYPE_SENDDATAINDICATION:
  491. {
  492. *pSize = sizeof(MCS_PDU_SENDDATAINDICATION) - _MCS.hdrBytesRead;
  493. TRC_DBG((TB, _T("MCS_PDU_SENDDATAINDICATION (%#x) read:%u need:%u"),
  494. *pType,
  495. _MCS.hdrBytesRead,
  496. *pSize));
  497. }
  498. break;
  499. case MCS_TYPE_ATTACHUSERCONFIRM:
  500. {
  501. /****************************************************************/
  502. /* The user-id is optional, so determine if it is present. */
  503. /****************************************************************/
  504. if (_MCS.pHdrBuf[0] & MCS_AUC_OPTIONALUSERIDMASK)
  505. {
  506. /************************************************************/
  507. /* The user-id is present. */
  508. /************************************************************/
  509. TRC_NRM((TB, _T("Optional user-id is present in AUC")));
  510. *pSize = sizeof(MCS_PDU_ATTACHUSERCONFIRMFULL) -
  511. _MCS.hdrBytesRead;
  512. }
  513. else
  514. {
  515. /************************************************************/
  516. /* The user-id is NOT present. */
  517. /************************************************************/
  518. TRC_NRM((TB, _T("Optional user-id is NOT present in AUC")));
  519. *pSize = sizeof(MCS_PDU_ATTACHUSERCONFIRMCOMMON) -
  520. _MCS.hdrBytesRead;
  521. }
  522. TRC_NRM((TB, _T("MCS_PDU_ATTACHUSERCONFIRM (%#x) read:%u need:%u"),
  523. *pType,
  524. _MCS.hdrBytesRead,
  525. *pSize));
  526. }
  527. break;
  528. case MCS_TYPE_DETACHUSERINDICATION:
  529. {
  530. *pSize = sizeof(MCS_PDU_DETACHUSERINDICATION) - _MCS.hdrBytesRead;
  531. TRC_NRM((TB, _T("MCS_PDU_DETACHUSERINDICATION (%#x) read:%u need:%u"),
  532. *pType,
  533. _MCS.hdrBytesRead,
  534. *pSize));
  535. }
  536. break;
  537. case MCS_TYPE_CHANNELJOINCONFIRM:
  538. {
  539. /****************************************************************/
  540. /* The channel-id is optional, so determine if it is present. */
  541. /****************************************************************/
  542. if (_MCS.pHdrBuf[0] & MCS_CJC_OPTIONALCHANNELIDMASK)
  543. {
  544. /************************************************************/
  545. /* The channel-id is present. */
  546. /************************************************************/
  547. TRC_NRM((TB, _T("Optional channel-id is present in CJC")));
  548. *pSize = sizeof(MCS_PDU_CHANNELJOINCONFIRMFULL) -
  549. _MCS.hdrBytesRead;
  550. }
  551. else
  552. {
  553. /************************************************************/
  554. /* The channel-id is NOT present. */
  555. /************************************************************/
  556. TRC_NRM((TB, _T("Optional channel-id is NOT present in CJC")));
  557. *pSize = sizeof(MCS_PDU_CHANNELJOINCONFIRMCOMMON) -
  558. _MCS.hdrBytesRead;
  559. }
  560. TRC_NRM((TB, _T("MCS_PDU_CHANNELJOINCONFIRM (%#x) read:%u need:%u"),
  561. *pType,
  562. _MCS.hdrBytesRead,
  563. *pSize));
  564. }
  565. break;
  566. case MCS_TYPE_DISCONNECTPROVIDERUM:
  567. {
  568. *pSize = sizeof(MCS_PDU_DISCONNECTPROVIDERUM) - _MCS.hdrBytesRead;
  569. TRC_NRM((TB, _T("MCS_PDU_DISCONNECTPROVIDERUM (%#x) read:%u need:%u"),
  570. *pType,
  571. _MCS.hdrBytesRead,
  572. *pSize));
  573. }
  574. break;
  575. default:
  576. {
  577. /****************************************************************/
  578. /* This is an unexpected MCS PDU - disconnect, as something has */
  579. /* gone horribly wrong! */
  580. /****************************************************************/
  581. TRC_ABORT((TB, _T("Unexpected MCS PDU type:%#x"), *pType));
  582. MCSSetReasonAndDisconnect(NL_ERR_MCSUNEXPECTEDPDU);
  583. *pSize = 0;
  584. DC_QUIT;
  585. }
  586. break;
  587. }
  588. DC_EXIT_POINT:
  589. DC_END_FN();
  590. } /* MCSGetPERInfo */
  591. /****************************************************************************/
  592. /* Name: MCSHandleControlPkt */
  593. /* */
  594. /* Purpose: This function handles a MCS control packet which is located */
  595. /* in the header buffer. After identifying the PDU type it */
  596. /* calls a NC callback. */
  597. /****************************************************************************/
  598. DCVOID DCINTERNAL CMCS::MCSHandleControlPkt(DCVOID)
  599. {
  600. DCUINT pduType;
  601. DCUINT pduSize;
  602. DC_BEGIN_FN("MCSHandleControlPkt");
  603. /************************************************************************/
  604. /* Trace out the header buffer contents. */
  605. /************************************************************************/
  606. TRC_DATA_NRM("Header bytes read:", _MCS.pHdrBuf, _MCS.hdrBytesRead);
  607. /************************************************************************/
  608. /* Work out the PDU type. */
  609. /************************************************************************/
  610. if (MCS_BER_CONNECT_PREFIX == _MCS.pHdrBuf[0])
  611. {
  612. /********************************************************************/
  613. /* This is a BER encoded PDU. The next byte is the type. */
  614. /********************************************************************/
  615. pduType = _MCS.pHdrBuf[1];
  616. }
  617. else
  618. {
  619. /********************************************************************/
  620. /* This is a PER encoded PDU. Get the PDU type. */
  621. /********************************************************************/
  622. MCSGetPERInfo(&pduType, &pduSize);
  623. }
  624. /************************************************************************/
  625. /* Now switch on the PDU type. */
  626. /************************************************************************/
  627. TRC_NRM((TB, _T("PDU type:%#x"), pduType));
  628. switch (pduType)
  629. {
  630. case MCS_TYPE_CONNECTRESPONSE:
  631. {
  632. TRC_NRM((TB, _T("Connect response PDU received")));
  633. MCSHandleCRPDU();
  634. }
  635. break;
  636. case MCS_TYPE_ATTACHUSERCONFIRM:
  637. {
  638. PMCS_PDU_ATTACHUSERCONFIRMCOMMON pAUCCommon;
  639. PMCS_PDU_ATTACHUSERCONFIRMFULL pAUCFull;
  640. DCUINT result;
  641. DCUINT16 userID;
  642. TRC_NRM((TB, _T("MCS Attach-User-Confirm PDU received")));
  643. /****************************************************************/
  644. /* Determine if this PDU includes the optional user-id as well. */
  645. /****************************************************************/
  646. if (!(_MCS.pHdrBuf[0] & MCS_AUC_OPTIONALUSERIDMASK))
  647. {
  648. TRC_ABORT((TB, _T("Optional user-id NOT present in AUC")));
  649. MCSSetReasonAndDisconnect(NL_ERR_MCSNOUSERIDINAUC);
  650. DC_QUIT;
  651. }
  652. /****************************************************************/
  653. /* Cast the header buffer in the form of the common part of */
  654. /* this PDU. */
  655. /****************************************************************/
  656. pAUCCommon = (PMCS_PDU_ATTACHUSERCONFIRMCOMMON)_MCS.pHdrBuf;
  657. /****************************************************************/
  658. /* Pull out the result code from the PDU and translate it. */
  659. /****************************************************************/
  660. result = MCSGetResult(pAUCCommon->typeResult,
  661. MCS_AUC_RESULTCODEOFFSET);
  662. /****************************************************************/
  663. /* Retrieve the user-id as well. */
  664. /****************************************************************/
  665. pAUCFull = (PMCS_PDU_ATTACHUSERCONFIRMFULL)_MCS.pHdrBuf;
  666. userID = MCSWireUserIDToLocalUserID(pAUCFull->userID);
  667. TRC_NRM((TB, _T("Calling NC_OnMCSAUC - result:%u userID:%#x"),
  668. result,
  669. userID));
  670. _pNc->NC_OnMCSAttachUserConfirm(result, userID);
  671. }
  672. break;
  673. case MCS_TYPE_CHANNELJOINCONFIRM:
  674. {
  675. PMCS_PDU_CHANNELJOINCONFIRMCOMMON pCJCCommon;
  676. PMCS_PDU_CHANNELJOINCONFIRMFULL pCJCFull;
  677. DCUINT16 channelID;
  678. DCUINT result;
  679. TRC_NRM((TB, _T("MCS Channel-Join-Confirm PDU received")));
  680. /****************************************************************/
  681. /* Determine if this PDU includes the optional channel-id as */
  682. /* well. */
  683. /****************************************************************/
  684. if (!(_MCS.pHdrBuf[0] & MCS_CJC_OPTIONALCHANNELIDMASK))
  685. {
  686. TRC_ABORT((TB, _T("Optional channel-id NOT present in CJC")));
  687. MCSSetReasonAndDisconnect(NL_ERR_MCSNOCHANNELIDINCJC);
  688. DC_QUIT;
  689. }
  690. /****************************************************************/
  691. /* Cast the header buffer in the form of this PDU. */
  692. /****************************************************************/
  693. pCJCCommon = (PMCS_PDU_CHANNELJOINCONFIRMCOMMON)_MCS.pHdrBuf;
  694. /****************************************************************/
  695. /* Pull out the result code from the PDU and translate it. */
  696. /****************************************************************/
  697. result = MCSGetResult(pCJCCommon->typeResult,
  698. MCS_CJC_RESULTCODEOFFSET);
  699. /****************************************************************/
  700. /* Retrieve the channel id. */
  701. /****************************************************************/
  702. pCJCFull = (PMCS_PDU_CHANNELJOINCONFIRMFULL)_MCS.pHdrBuf;
  703. channelID = MCSWireToLocal16(pCJCFull->channelID);
  704. TRC_NRM((TB, _T("Calling NC_OnMCSCJC - result:%u channelID:%#x"),
  705. result,
  706. channelID));
  707. _pNc->NC_OnMCSChannelJoinConfirm(result, channelID);
  708. }
  709. break;
  710. case MCS_TYPE_DETACHUSERINDICATION:
  711. {
  712. /****************************************************************/
  713. /* The following code is only compiled in if normal level */
  714. /* tracing is enabled - otherwise we just ignore detach-user */
  715. /* indications. The server will send us a disconnect-provider */
  716. /* when it wants us to detach. */
  717. /****************************************************************/
  718. #ifdef TRC_ENABLE_NRM
  719. DCUINT16 userID;
  720. PMCS_PDU_DETACHUSERINDICATION pDUI;
  721. /****************************************************************/
  722. /* Cast the header buffer in the form of this PDU. */
  723. /****************************************************************/
  724. pDUI = (PMCS_PDU_DETACHUSERINDICATION)_MCS.pHdrBuf;
  725. /****************************************************************/
  726. /* Dig out the MCS user id and issue the NC callback. */
  727. /****************************************************************/
  728. userID = MCSWireUserIDToLocalUserID(pDUI->userID);
  729. TRC_NRM((TB, _T("MCS Detach-User-Indication PDU recv'd - userID:%#x"),
  730. userID));
  731. #endif /* TRC_ENABLE_NRM */
  732. }
  733. break;
  734. case MCS_TYPE_DISCONNECTPROVIDERUM:
  735. {
  736. PMCS_PDU_DISCONNECTPROVIDERUM pDPum;
  737. DCUINT reason;
  738. TRC_NRM((TB, _T("Disconnect Provider Ultimatum received")));
  739. /****************************************************************/
  740. /* Cast the header buffer in the form of this PDU. */
  741. /****************************************************************/
  742. pDPum = (PMCS_PDU_DISCONNECTPROVIDERUM)_MCS.pHdrBuf;
  743. /****************************************************************/
  744. /* Pull out the reason code from the PDU. */
  745. /****************************************************************/
  746. reason = MCSGetReason(pDPum->typeReason,
  747. MCS_DPUM_REASONCODEOFFSET);
  748. TRC_ASSERT((reason <= MCS_REASON_CHANNEL_PURGED),
  749. (TB, _T("Unexpected MCS reason code:%u"), reason));
  750. /****************************************************************/
  751. /* Switch on the reason code. */
  752. /****************************************************************/
  753. switch (reason)
  754. {
  755. case MCS_REASON_PROVIDER_INITIATED:
  756. {
  757. /********************************************************/
  758. /* The server has disconnected us. */
  759. /********************************************************/
  760. TRC_NRM((TB,
  761. _T("DPum with reason MCS_REASON_PROVIDER_INITIATED")));
  762. _MCS.disconnectReason = NL_DISCONNECT_REMOTE_BY_SERVER;
  763. }
  764. break;
  765. case MCS_REASON_USER_REQUESTED:
  766. {
  767. /********************************************************/
  768. /* We initiated the disconnection and the server */
  769. /* concurred. */
  770. /********************************************************/
  771. TRC_NRM((TB,
  772. _T("DPum with reason MCS_REASON_USER_REQUESTED")));
  773. _MCS.disconnectReason = NL_DISCONNECT_REMOTE_BY_USER;
  774. }
  775. break;
  776. default:
  777. {
  778. /********************************************************/
  779. /* This is an unrecognized reason code. */
  780. /********************************************************/
  781. TRC_ABORT((TB, _T("Unexpected MCS reason code:%u"), reason));
  782. _MCS.disconnectReason =
  783. NL_MAKE_DISCONNECT_ERR(NL_ERR_MCSBADMCSREASON);
  784. }
  785. break;
  786. }
  787. /****************************************************************/
  788. /* Getting a DPum means we should disconnect so call XT to */
  789. /* disconnect the lower layers. */
  790. /****************************************************************/
  791. _pXt->XT_Disconnect();
  792. }
  793. break;
  794. default:
  795. {
  796. TRC_ABORT((TB, _T("Unrecognised PDU type:%#x"), pduType));
  797. }
  798. break;
  799. }
  800. DC_EXIT_POINT:
  801. DC_END_FN();
  802. return;
  803. } /* MCSHandleControlPkt */
  804. /****************************************************************************/
  805. /* Name: MCSHandleCRPDU */
  806. /* */
  807. /* Purpose: Handles a MCS Connect-Response PDU. This function splits out */
  808. /* the MCS result code and user-data from the PDU and issues a */
  809. /* callback to NC with these values. */
  810. /****************************************************************************/
  811. DCVOID DCINTERNAL CMCS::MCSHandleCRPDU(DCVOID)
  812. {
  813. BOOL fBadFields = FALSE;
  814. PDCUINT8 pPDU;
  815. DCUINT length, nBERBytes;
  816. DCUINT i;
  817. DCUINT result = MCS_RESULT_UNSPECIFIED_FAILURE;
  818. DC_BEGIN_FN("MCSHandleCRPDU");
  819. TRC_NRM((TB, _T("MCS Connect-Response PDU received")));
  820. TRC_DATA_NRM("Connect-Response data:", _MCS.pHdrBuf, _MCS.hdrBytesRead);
  821. /************************************************************************/
  822. /* Set our local pointer to the start of the PDU. */
  823. /************************************************************************/
  824. pPDU = _MCS.pHdrBuf;
  825. /************************************************************************/
  826. /* Skip the PDU type fields. */
  827. /************************************************************************/
  828. pPDU += 2;
  829. /************************************************************************/
  830. /* Skip the length field. Note that we add one to the result of */
  831. /* MCSGetBERLengthSize as this function returns the number of */
  832. /* additional bytes that are needed to encode the length. */
  833. /* We know that it's safe to skip these first few bytes since we */
  834. /* already verified that they were received in MCS_RCVST_BERHEADER */
  835. /* and MCS_RCVST_BERLENGTH. */
  836. /************************************************************************/
  837. pPDU += MCSGetBERLengthSize(*pPDU);
  838. TRC_NRM((TB, _T("Skipped type and length %p->%p"),
  839. _MCS.pHdrBuf,
  840. pPDU));
  841. /************************************************************************/
  842. /* Now loop through the PDU fields. We are only interested in two of */
  843. /* the fields - the result and the user data. */
  844. /************************************************************************/
  845. for (i = 0; i < MCS_CRPDU_NUMFIELDS; i++)
  846. {
  847. /********************************************************************/
  848. /* We need one byte for the BER encoded fieldtype. Also, we need at */
  849. /* least one byte to get the NUMBER of bytes in the BER length (1 */
  850. /* or 2 bytes). */
  851. /********************************************************************/
  852. if ((pPDU + 2) > (_MCS.pHdrBuf + _MCS.hdrBytesRead))
  853. {
  854. fBadFields = TRUE;
  855. DC_QUIT;
  856. }
  857. /********************************************************************/
  858. /* The first item in a BER encoded field is the type. We're not */
  859. /* interested in this so just skip it. */
  860. /********************************************************************/
  861. pPDU++;
  862. /********************************************************************/
  863. /* The next byte has the NUMBER of bytes for the length. */
  864. /********************************************************************/
  865. nBERBytes = MCSGetBERLengthSize(*pPDU);
  866. /********************************************************************/
  867. /* The number of bytes had better be 1-3. Also, make sure we have */
  868. /* at least this many bytes left! */
  869. /********************************************************************/
  870. if (nBERBytes > 3 ||
  871. ((pPDU + nBERBytes) > (_MCS.pHdrBuf + _MCS.hdrBytesRead)))
  872. {
  873. fBadFields = TRUE;
  874. DC_QUIT;
  875. }
  876. /********************************************************************/
  877. /* The second item is the length. Calculate it and the number of */
  878. /* bytes that the length was encoded in. Note that we add one to */
  879. /* the result of MCSGetBERNumOfLengthBytes as this function returns */
  880. /* the number of additional bytes that are needed to encode the */
  881. /* length. */
  882. /********************************************************************/
  883. length = MCSGetBERLength(pPDU);
  884. pPDU += nBERBytes;
  885. TRC_NRM((TB, _T("Field %u has length:%u (pPDU:%p)"), i, length, pPDU));
  886. /********************************************************************/
  887. /* Of course, we had better have enough space for the actual len. */
  888. /********************************************************************/
  889. if ((pPDU + length) > (_MCS.pHdrBuf + _MCS.hdrBytesRead))
  890. {
  891. fBadFields = TRUE;
  892. DC_QUIT;
  893. }
  894. /********************************************************************/
  895. /* The third item is the actual data - switch on the field number */
  896. /* to determine if this a piece of data that we're interested in. */
  897. /********************************************************************/
  898. switch (i)
  899. {
  900. case MCS_CRPDU_RESULTOFFSET:
  901. {
  902. /************************************************************/
  903. /* This is the MCS result field - dig it out and store it. */
  904. /************************************************************/
  905. TRC_ASSERT((MCS_CR_RESULTLEN == length),
  906. (TB, _T("Bad CR result length expect:%u got:%u"),
  907. MCS_CR_RESULTLEN,
  908. length));
  909. result = *pPDU;
  910. TRC_NRM((TB, _T("Connect-Response result code:%u"), result));
  911. /************************************************************/
  912. /* If the rc is good then we need to send a MCS */
  913. /* Erect-Domain-Request to the server. */
  914. /************************************************************/
  915. if (MCS_RESULT_SUCCESSFUL == result)
  916. {
  917. TRC_NRM((TB, _T("Generating EDR PDU")));
  918. _pCd->CD_DecoupleSimpleNotification(CD_SND_COMPONENT, this,
  919. CD_NOTIFICATION_FUNC(CMCS,MCSSendErectDomainRequest),
  920. (ULONG_PTR) 0);
  921. }
  922. }
  923. break;
  924. case MCS_CRPDU_USERDATAOFFSET:
  925. {
  926. /************************************************************/
  927. /* This is the user-data, so issue the NC callback. */
  928. /************************************************************/
  929. TRC_NRM((TB, _T("Call NC_OnMCSCPC - rc:%u pUserData:%p len:%u"),
  930. result,
  931. pPDU,
  932. length));
  933. _pNc->NC_OnMCSConnected(result,
  934. pPDU,
  935. length);
  936. }
  937. break;
  938. default:
  939. {
  940. /************************************************************/
  941. /* This is a field that we're not interested in so just */
  942. /* skip it. */
  943. /************************************************************/
  944. TRC_NRM((TB, _T("Offset %u - skip %u bytes of data"), i, length));
  945. }
  946. break;
  947. }
  948. /********************************************************************/
  949. /* Skip the data field. */
  950. /********************************************************************/
  951. pPDU += length;
  952. }
  953. DC_EXIT_POINT:
  954. if (fBadFields)
  955. {
  956. TRC_ABORT((TB, _T("Bad CR PDU fields")));
  957. MCSSetReasonAndDisconnect(NL_ERR_MCSBADCRFIELDS);
  958. }
  959. DC_END_FN();
  960. } /* MCSHandleCRPDU */
  961. // This check will be sure that MCS.dataBytesNeeded is not greater than
  962. // XT.dataBytesLeft. This should be use ONLY when the MCS needs to read all
  963. // it's data from the XT and is not allowed any network reads. In these cases,
  964. // without enough data in XT, the client goes into an endless loop
  965. // BUG 647947
  966. #define CHECK_VALID_MCS_DATABYTESNEEDED( mcsInst, xtInst, hr ) \
  967. TRC_DBG(( TB, _T("_MCS.dataBytesNeeded = %d"), (mcsInst).dataBytesNeeded )); \
  968. if ((xtInst).dataBytesLeft < (mcsInst).dataBytesNeeded) { \
  969. TRC_ABORT((TB, _T("Bad _MCS.dataBytesNeeded:%u _XT.dataBytesLeft=%u"), \
  970. (mcsInst).dataBytesNeeded, (xtInst).dataBytesLeft )); \
  971. MCSSetReasonAndDisconnect(NL_ERR_MCSINVALIDPACKETFORMAT); \
  972. (hr) = E_ABORT; \
  973. DC_QUIT; \
  974. }
  975. /****************************************************************************/
  976. /* Name: MCSRecvData */
  977. /* */
  978. /* Purpose: This is the main data receiver function. It reads data from */
  979. /* the user-data section of a MCS SDin PDU and places it in the */
  980. /* receiver buffer. */
  981. /* */
  982. /* Returns: *pfFinishedData is TRUE if the data section of a MCS PDU was */
  983. /* completely processed and FALSE if not. */
  984. /****************************************************************************/
  985. HRESULT DCINTERNAL CMCS::MCSRecvData(BOOL *pfFinishedData)
  986. {
  987. BOOL fFinishedData = FALSE;
  988. HRESULT hrc = S_OK;
  989. PMCS_PDU_SENDDATAINDICATION pSDI;
  990. DCUINT16 senderID;
  991. DCUINT16 channelID;
  992. DCUINT fragCount;
  993. DC_BEGIN_FN("MCSRecvData");
  994. /************************************************************************/
  995. /* Switch on the data state. */
  996. /************************************************************************/
  997. switch (_MCS.dataState)
  998. {
  999. case MCS_DATAST_SIZE1:
  1000. {
  1001. /****************************************************************/
  1002. /* Try to receive the data into the header buffer. */
  1003. /****************************************************************/
  1004. if (MCSRecvToHdrBuf())
  1005. {
  1006. /************************************************************/
  1007. /* Trace out the contents of the header buffer. */
  1008. /************************************************************/
  1009. TRC_DATA_DBG("Header buf contains:",
  1010. _MCS.pHdrBuf,
  1011. _MCS.hdrBytesRead);
  1012. /************************************************************/
  1013. /* Cast the contents of the header buffer. */
  1014. /************************************************************/
  1015. pSDI = (PMCS_PDU_SENDDATAINDICATION)_MCS.pHdrBuf;
  1016. /************************************************************/
  1017. /* Check to determine if the header begin segmentation flag */
  1018. /* is set. */
  1019. /* If the flag is set, the count of bytes read should be 0. */
  1020. /* If it is NOT set, the count of bytes should be non-zero. */
  1021. /************************************************************/
  1022. if (((pSDI->priSeg & MCS_SDI_BEGINSEGMASK) &&
  1023. (0 != _MCS.dataBytesRead)) ||
  1024. (!(pSDI->priSeg & MCS_SDI_BEGINSEGMASK) &&
  1025. (0 == _MCS.dataBytesRead)))
  1026. {
  1027. TRC_ABORT((TB, _T("Segmentation flag does not match data bytes read (%u)"),
  1028. _MCS.dataBytesRead));
  1029. MCSSetReasonAndDisconnect(NL_ERR_MCSINVALIDPACKETFORMAT);
  1030. hrc = E_ABORT;
  1031. DC_QUIT;
  1032. }
  1033. /************************************************************/
  1034. /* Update the state variable. */
  1035. /************************************************************/
  1036. TRC_DBG((TB, _T("State: DATA_SIZE1->DATA_SIZE2")));
  1037. _MCS.dataState = MCS_DATAST_SIZE2;
  1038. }
  1039. }
  1040. break;
  1041. case MCS_DATAST_SIZE2:
  1042. {
  1043. /****************************************************************/
  1044. /* Now try to receive the first of the data size bytes into the */
  1045. /* size buffer. Since the size may be completely contained */
  1046. /* within a single byte we only want to read one byte at this */
  1047. /* time. */
  1048. /****************************************************************/
  1049. if (0 != _pXt->XT_Recv(&(_MCS.pSizeBuf[0]), 1))
  1050. {
  1051. /************************************************************/
  1052. /* Trace out the contents of the size buffer. */
  1053. /************************************************************/
  1054. TRC_DATA_DBG("Size buf contains:", _MCS.pSizeBuf, 2);
  1055. if (_MCS.pSizeBuf[0] & 0x80)
  1056. {
  1057. /********************************************************/
  1058. /* The MSB of the first byte is set. We now need to */
  1059. /* look at the second bit to discover if the following */
  1060. /* data is fragmented. */
  1061. /********************************************************/
  1062. if (_MCS.pSizeBuf[0] & 0x40)
  1063. {
  1064. /****************************************************/
  1065. /* Bits 1-6 now contain a number between 1 and 4 */
  1066. /* which when multiplied by 16K gives the length */
  1067. /* of the following fragment. We expect a */
  1068. /* maximum packet size of 32K, so the most that */
  1069. /* this value should be is 2. */
  1070. /****************************************************/
  1071. fragCount = _MCS.pSizeBuf[0] & 0x3F;
  1072. if (fragCount > 2)
  1073. {
  1074. TRC_ABORT((TB, _T("Bad fragCount:%u"), fragCount));
  1075. MCSSetReasonAndDisconnect(NL_ERR_MCSINVALIDPACKETFORMAT);
  1076. hrc = E_ABORT;
  1077. DC_QUIT;
  1078. }
  1079. TRC_DBG((TB, _T("Fragmentation count is %u"), fragCount));
  1080. /****************************************************/
  1081. /* Now work out the number of bytes to read and */
  1082. /* change state. */
  1083. /****************************************************/
  1084. _MCS.dataBytesNeeded = fragCount * 16384;
  1085. CHECK_VALID_MCS_DATABYTESNEEDED( _MCS, _pXt->_XT, hrc );
  1086. _MCS.dataState = MCS_DATAST_READFRAG;
  1087. /************************************************************/
  1088. /* There is a retail check for size in MCS_RecvToDataBuf, */
  1089. /* but this helps us debug it before that point. */
  1090. /************************************************************/
  1091. TRC_ASSERT((_MCS.dataBytesNeeded < 65535),
  1092. (TB,_T("Data recv size %u too large"), _MCS.dataBytesNeeded));
  1093. TRC_DBG((TB, _T("Data bytes needed is now %u"),
  1094. _MCS.dataBytesNeeded));
  1095. TRC_DBG((TB, _T("State: DATA_SIZE2->DATA_READSEG")));
  1096. }
  1097. else
  1098. {
  1099. /****************************************************/
  1100. /* This section is not fragmented, and contains */
  1101. /* between 128 bytes and 16K of data. We need to */
  1102. /* read another byte before we can work out how */
  1103. /* much data we need. Change state. */
  1104. /****************************************************/
  1105. _MCS.dataState = MCS_DATAST_SIZE3;
  1106. TRC_DBG((TB, _T("State: DATA_SIZE2->DATA_SIZE3")));
  1107. }
  1108. }
  1109. else
  1110. {
  1111. /********************************************************/
  1112. /* The MSB of the first byte is not set, so this */
  1113. /* section contains less than 128 bytes of data. This */
  1114. /* means we can just set the count of bytes needed to */
  1115. /* the size of this byte and update the state to */
  1116. /* reading remainder. */
  1117. /********************************************************/
  1118. _MCS.dataBytesNeeded = _MCS.pSizeBuf[0];
  1119. CHECK_VALID_MCS_DATABYTESNEEDED( _MCS, _pXt->_XT, hrc );
  1120. _MCS.dataState = MCS_DATAST_READREMAINDER;
  1121. /************************************************************/
  1122. /* There is a retail check for size in MCS_RecvToDataBuf, */
  1123. /* but this helps us debug it before that point. */
  1124. /************************************************************/
  1125. TRC_ASSERT((_MCS.dataBytesNeeded < 65535),
  1126. (TB,_T("Data recv size %u too large"), _MCS.dataBytesNeeded));
  1127. TRC_DBG((TB, _T("Read %u bytes"), _MCS.dataBytesNeeded));
  1128. TRC_DBG((TB, _T("State: DATA_SIZE2->DATA_READREMAINDER")));
  1129. }
  1130. }
  1131. }
  1132. break;
  1133. case MCS_DATAST_SIZE3:
  1134. {
  1135. /****************************************************************/
  1136. /* The length field is 2 bytes long (i.e. the data size lies */
  1137. /* somewhere between 128 bytes and 16K) so try to read the */
  1138. /* second byte. Just call XT_Recv directly to get the single */
  1139. /* byte. */
  1140. /****************************************************************/
  1141. if (0 != _pXt->XT_Recv(&(_MCS.pSizeBuf[1]), 1))
  1142. {
  1143. /************************************************************/
  1144. /* Trace out the contents of the size buffer. */
  1145. /************************************************************/
  1146. TRC_DATA_DBG("Size buf contains:", _MCS.pSizeBuf, 2);
  1147. /************************************************************/
  1148. /* We can now work out how much data to receive, so do it */
  1149. /* now. */
  1150. /************************************************************/
  1151. _MCS.dataBytesNeeded =
  1152. _MCS.pSizeBuf[1] + ((_MCS.pSizeBuf[0] & 0x3F) << 8);
  1153. CHECK_VALID_MCS_DATABYTESNEEDED( _MCS, _pXt->_XT, hrc );
  1154. _MCS.dataState = MCS_DATAST_READREMAINDER;
  1155. /************************************************************/
  1156. /* There is a retail check for size in MCS_RecvToDataBuf, */
  1157. /* but this helps us debug it before that point. */
  1158. /************************************************************/
  1159. TRC_ASSERT((_MCS.dataBytesNeeded < 65535),
  1160. (TB,_T("Data recv size %u too large"), _MCS.dataBytesNeeded));
  1161. TRC_DBG((TB, _T("State: DATA_SIZE3->DATA_READREMAINDER")));
  1162. }
  1163. }
  1164. break;
  1165. case MCS_DATAST_READFRAG:
  1166. {
  1167. MCS_RecvToDataBuf(hrc, _pXt, this);
  1168. if (!SUCCEEDED(hrc))
  1169. {
  1170. MCSSetReasonAndDisconnect(NL_ERR_MCSINVALIDPACKETFORMAT);
  1171. DC_QUIT;
  1172. }
  1173. if (S_OK == hrc) {
  1174. fFinishedData = TRUE;
  1175. /************************************************************/
  1176. /* We've read this fragment completely so change state. */
  1177. /************************************************************/
  1178. _MCS.dataState = MCS_DATAST_SIZE2;
  1179. TRC_DBG((TB, _T("State: DATA_READFRAG->DATA_SIZE2")));
  1180. }
  1181. }
  1182. break;
  1183. case MCS_DATAST_READREMAINDER:
  1184. {
  1185. MCS_RecvToDataBuf(hrc, _pXt, this);
  1186. if (!SUCCEEDED(hrc))
  1187. {
  1188. MCSSetReasonAndDisconnect(NL_ERR_MCSINVALIDPACKETFORMAT);
  1189. DC_QUIT;
  1190. }
  1191. if (S_OK == hrc) {
  1192. /************************************************************/
  1193. /* We've completely read the data part of a MCS data */
  1194. /* packet, so return TRUE. */
  1195. /************************************************************/
  1196. fFinishedData = TRUE;
  1197. /************************************************************/
  1198. /* Cast the contents of the header buffer. */
  1199. /************************************************************/
  1200. pSDI = (PMCS_PDU_SENDDATAINDICATION)_MCS.pHdrBuf;
  1201. /************************************************************/
  1202. /* Decide if we should issue a callback to the layer above */
  1203. /* with the packet - we do this if this is the last */
  1204. /* segment (i.e. the end segmentation flag is set). */
  1205. /************************************************************/
  1206. if (pSDI->priSeg & MCS_SDI_ENDSEGMASK)
  1207. {
  1208. /********************************************************/
  1209. /* Dig out the sender id. */
  1210. /********************************************************/
  1211. senderID = MCSWireUserIDToLocalUserID(pSDI->userID);
  1212. channelID = MCSWireToLocal16(pSDI->channelID);
  1213. /********************************************************/
  1214. /* Update the performance counter. */
  1215. /********************************************************/
  1216. PRF_INC_COUNTER(PERF_PKTS_RECV);
  1217. /********************************************************/
  1218. /* The flag is set, so issue the callback. */
  1219. /********************************************************/
  1220. TRC_DBG((TB,
  1221. _T("Calling PRcb (senderID:%#x, channelID:%#x, size:%u)"),
  1222. senderID, channelID,
  1223. _MCS.dataBytesRead));
  1224. TRC_ASSERT((_MCS.pReceivedPacket != NULL),
  1225. (TB, _T("Null rcv packet buffer")));
  1226. /********************************************************/
  1227. /* If this function fails, we bail out of the rest of */
  1228. /* the packet (outside of this function). */
  1229. /********************************************************/
  1230. hrc = _pNl->_NL.callbacks.onPacketReceived(_pSl, _MCS.pReceivedPacket,
  1231. _MCS.dataBytesRead,
  1232. 0,
  1233. channelID,
  1234. 0);
  1235. /********************************************************/
  1236. /* Reset the count of bytes read. */
  1237. /********************************************************/
  1238. _MCS.dataBytesRead = 0;
  1239. }
  1240. /************************************************************/
  1241. /* Finally update the state. */
  1242. /************************************************************/
  1243. _MCS.dataState = MCS_DATAST_SIZE1;
  1244. TRC_DBG((TB, _T("State: DATA_READREMAINDER->DATA_SIZE1")));
  1245. }
  1246. }
  1247. break;
  1248. default:
  1249. {
  1250. TRC_ABORT((TB, _T("Unknown data state:%u"), _MCS.dataState));
  1251. }
  1252. break;
  1253. }
  1254. DC_EXIT_POINT:
  1255. *pfFinishedData = fFinishedData;
  1256. DC_END_FN();
  1257. return(hrc);
  1258. } /* MCSRecvData */
  1259. /****************************************************************************/
  1260. /* Name: MCSSetReasonAndDisconnect */
  1261. /* */
  1262. /* Purpose: This function is called when MCS detects that an error has */
  1263. /* occurred while processing a PDU. It sets the reason code for */
  1264. /* the disconnection which is used to over-ride the value that */
  1265. /* comes back in the OnDisconnected callback from XT. After */
  1266. /* setting this variable it then calls XT_Disconnect to begin */
  1267. /* the disconnection process. */
  1268. /* */
  1269. /* Params: IN reason - the reason code for the disconnection. */
  1270. /****************************************************************************/
  1271. DCVOID DCINTERNAL CMCS::MCSSetReasonAndDisconnect(DCUINT reason)
  1272. {
  1273. DC_BEGIN_FN("MCSSetReasonAndDisconnect");
  1274. /************************************************************************/
  1275. /* Set the disconnect error code. This will be used to over-ride the */
  1276. /* error value in the OnDisconnected callback from XT before we pass it */
  1277. /* to NC. */
  1278. /************************************************************************/
  1279. TRC_ASSERT((0 == _MCS.disconnectReason),
  1280. (TB, _T("Disconnect reason has already been set!")));
  1281. _MCS.disconnectReason = NL_MAKE_DISCONNECT_ERR(reason);
  1282. /************************************************************************/
  1283. /* Attempt to disconnect. */
  1284. /************************************************************************/
  1285. TRC_NRM((TB, _T("Set reason code to %#x so now call XT_Disconnect..."),
  1286. _MCS.disconnectReason));
  1287. _pXt->XT_Disconnect();
  1288. DC_END_FN();
  1289. } /* MCSSetReasonAndDisconnect */