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.

433 lines
12 KiB

  1. #include "precomp.h"
  2. DEBUG_FILEZONE(ZONE_T120_MCSNC);
  3. /*
  4. * datapkt.cpp
  5. *
  6. * Copyright (c) 1997 by Microsoft Corporation, Redmond, WA
  7. *
  8. * Abstract:
  9. * This is the implementation file for the MCS data packet class. The data packet
  10. * class is responsible for encoding and decoding the PDUs, as well as
  11. * maintaining the necessary pointers to the encoded and decoded data.
  12. * However, they differ from normal packets, in that there is only one copy of the
  13. * user data in the encoded and decoded buffers. Only the encoded buffer has the user data,
  14. * while the decoded one maintains a pointer to the data.
  15. * Instances of this class will be created both by User and Connection
  16. * objects as PDUs flow through MCS.
  17. *
  18. * Private Instance Variables:
  19. * ulDataOffset
  20. * Maintains the offset of the starting byte of the user data
  21. * from the start of the encoded buffer.
  22. *
  23. * Caveats:
  24. * None.
  25. *
  26. * Author:
  27. * Christos Tsollis
  28. */
  29. #include "omcscode.h"
  30. /*
  31. * This is a global variable that has a pointer to the one MCS coder that
  32. * is instantiated by the MCS Controller. Most objects know in advance
  33. * whether they need to use the MCS or the GCC coder, so, they do not need
  34. * this pointer in their constructors.
  35. */
  36. extern CMCSCoder *g_MCSCoder;
  37. /*
  38. * The following array contains a template for the X.224 data header.
  39. * The 5 of the 7 bytes that it initializes are actually sent to the
  40. * wire. Bytes 3 and 4 will be set to contain the size of the PDU.
  41. * The array is only used when we encode a data PDU.
  42. */
  43. extern UChar g_X224Header[];
  44. /*
  45. * These are globals that correspond to the static variables declared as part
  46. * of this class.
  47. */
  48. PVoid * DataPacket::Object_Array;
  49. long DataPacket::Object_Count;
  50. /*
  51. * operator new
  52. *
  53. * Public
  54. *
  55. * Functional Description:
  56. * This is the "new" operator for the DataPacket class.
  57. *
  58. */
  59. PVoid DataPacket::operator new (size_t)
  60. {
  61. PVoid pNewObject;
  62. TRACE_OUT(("DataPacket::DataPacket: %d pre-allocated data packet objects are left.",
  63. Object_Count));
  64. if (Object_Count > 0) {
  65. pNewObject = Object_Array[--Object_Count];
  66. }
  67. else {
  68. // Allocate an object from the heap
  69. DBG_SAVE_FILE_LINE
  70. pNewObject = (PVoid) new BYTE[sizeof(DataPacket)];
  71. if (pNewObject != NULL)
  72. ((PDataPacket) pNewObject)->fPreAlloc = FALSE;
  73. }
  74. return (pNewObject);
  75. }
  76. /*
  77. * operator delete
  78. *
  79. * Public
  80. *
  81. * Functional Description:
  82. * This is the "delete" operator for the Packet class.
  83. *
  84. */
  85. Void DataPacket::operator delete (PVoid object)
  86. {
  87. if (((PDataPacket) object)->fPreAlloc) {
  88. Object_Array[Object_Count++] = object;
  89. }
  90. else
  91. delete [] ((BYTE *) object);
  92. }
  93. /*
  94. * The AllocateMemoryPool static function pre-allocates DataPacket
  95. * objects for use by MCS.
  96. */
  97. Void DataPacket::AllocateMemoryPool (long maximum_objects)
  98. {
  99. ULong memory_size;
  100. PUChar object_ptr;
  101. long object_count;
  102. PVoid *pStack;
  103. /*
  104. * Calculate the amount of memory needed to hold the specified number of
  105. * entries. This memory block will contains two different types of
  106. * information:
  107. *
  108. * 1. A stack of available objects (each entry is a PVoid). The "new"
  109. * operator pops the top entry off the stack. The "delete" operator
  110. * pushes one back on.
  111. * 2. The objects themselves, sequentially in memory.
  112. *
  113. * That is why this calculation adds the size of a PVoid to the size of
  114. * an instance of the class, and multiplies by the specified number. This
  115. * allows enough room for both sections.
  116. */
  117. memory_size = ((sizeof (PVoid) + sizeof (DataPacket)) * maximum_objects);
  118. /*
  119. * Allocate the memory required.
  120. */
  121. DBG_SAVE_FILE_LINE
  122. Object_Array = (PVoid *) new BYTE[memory_size];
  123. if (Object_Array != NULL)
  124. {
  125. Object_Count = maximum_objects;
  126. /*
  127. * Set a pointer to the first object, which immediately follows the
  128. * stack of available objects.
  129. */
  130. object_ptr = (PUChar) Object_Array + (sizeof (PVoid) * maximum_objects);
  131. /*
  132. * This loop initializes the stack of available objects to contain all
  133. * objects, in sequential order.
  134. */
  135. for (pStack = Object_Array, object_count = 0; object_count < maximum_objects;
  136. object_count++)
  137. {
  138. *pStack++ = (PVoid) object_ptr;
  139. ((PDataPacket) object_ptr)->fPreAlloc = TRUE; // this object is pre-allocated
  140. object_ptr += sizeof (DataPacket);
  141. }
  142. }
  143. else
  144. {
  145. /*
  146. * The memory allocation failed. Set the static variable indicating
  147. * that there are no objects left. This way, ALL attempted allocations
  148. * will fail.
  149. */
  150. Object_Count = 0;
  151. }
  152. }
  153. /*
  154. * The FreeMemoryPool static function frees the pre-allocates DataPacket
  155. * objects. It also deletes the critical section
  156. * that controls access to these objects and the memory-tracking
  157. * mechanisms in T.120
  158. */
  159. Void DataPacket::FreeMemoryPool ()
  160. {
  161. if (Object_Array != NULL)
  162. delete [] ((BYTE *) Object_Array);
  163. };
  164. /*
  165. * DataPacket ()
  166. *
  167. * Public
  168. *
  169. * Functional Description:
  170. * This constructor is used to create an outgoing data packet.
  171. * The packet is created by the user object, when the request
  172. * for a send data or uniform send data comes through the user
  173. * portal.
  174. */
  175. //outgoing data packets.
  176. DataPacket::DataPacket (ASN1choice_t choice,
  177. PUChar data_ptr,
  178. ULong data_length,
  179. UINT channel_id,
  180. Priority priority,
  181. Segmentation segmentation,
  182. UINT initiator_id,
  183. SendDataFlags flags,
  184. PMemory memory,
  185. PPacketError packet_error)
  186. :
  187. SimplePacket(TRUE),
  188. m_fIncoming (FALSE),
  189. m_Memory (memory),
  190. m_EncodedDataBroken (FALSE),
  191. m_nMessageType(0)
  192. {
  193. *packet_error = PACKET_NO_ERROR;
  194. // Fill in the decoded domain PDU fields.
  195. m_DecodedPDU.choice = choice;
  196. m_DecodedPDU.u.send_data_request.initiator = (UserID) initiator_id;
  197. m_DecodedPDU.u.send_data_request.channel_id = (ChannelID) channel_id;
  198. m_DecodedPDU.u.send_data_request.data_priority = (PDUPriority) priority;
  199. m_DecodedPDU.u.send_data_request.segmentation = (PDUSegmentation) segmentation;
  200. m_DecodedPDU.u.send_data_request.user_data.length = data_length;
  201. m_DecodedPDU.u.send_data_request.user_data.value = (ASN1octet_t *) data_ptr;
  202. /*
  203. * Now, encode the data PDU. Note that no error/allocation should
  204. * occur during the Encode operation.
  205. */
  206. if (flags == APP_ALLOCATION) {
  207. ASSERT (m_Memory == NULL);
  208. // We will need to memcpy the data
  209. m_EncodedPDU = NULL;
  210. }
  211. else {
  212. // No need for data memcpy!
  213. ASSERT (m_Memory != NULL);
  214. /*
  215. * We need to set the m_EncodedPDU ptr. If this is the 1st packet
  216. * of the data request, the space is already allocated. Otherwise,
  217. * we need to allocate it.
  218. */
  219. if (segmentation & SEGMENTATION_BEGIN) {
  220. m_EncodedPDU = data_ptr - MAXIMUM_PROTOCOL_OVERHEAD;
  221. }
  222. else {
  223. DBG_SAVE_FILE_LINE
  224. m_EncodedPDU = Allocate (MAXIMUM_PROTOCOL_OVERHEAD);
  225. if (NULL != m_EncodedPDU) {
  226. m_EncodedDataBroken = TRUE;
  227. }
  228. else {
  229. WARNING_OUT (("DataPacket::DataPacket: Failed to allocate MCS encoded headers."));
  230. *packet_error = PACKET_MALLOC_FAILURE;
  231. }
  232. }
  233. /*
  234. * We lock the big buffer that contains the data included in this packet.
  235. */
  236. LockMemory (m_Memory);
  237. }
  238. if (*packet_error == PACKET_NO_ERROR) {
  239. if (g_MCSCoder->Encode ((LPVOID) &m_DecodedPDU, DOMAIN_MCS_PDU,
  240. PACKED_ENCODING_RULES, &m_EncodedPDU,
  241. &Encoded_Data_Length)) {
  242. if (m_Memory == NULL) {
  243. m_Memory = GetMemoryObjectFromEncData(m_EncodedPDU);
  244. }
  245. }
  246. else {
  247. WARNING_OUT (("DataPacket::DataPacket: Encode failed. Possibly, allocation error."));
  248. *packet_error = PACKET_MALLOC_FAILURE;
  249. }
  250. }
  251. }
  252. /*
  253. * Packet ()
  254. *
  255. * Public
  256. *
  257. * Functional Description:
  258. * This version of the constructor is used to create a DataPacket object
  259. * for incomming PDUs when the packet is to be created from an encoded
  260. * data stream containing the PDU data to be decoded.
  261. *
  262. * Input parameters:
  263. * pTransportData: This structure contains the following fields:
  264. * user_data: Pointer to space containing the real user data + 7 initial
  265. * bytes for X.224 headers.
  266. * user_data_length: Length of the user data including the 7-byte X.224
  267. * header.
  268. * buffer: The beginning of the buffer containing the user_data ptr. These
  269. * 2 ptrs can be different because of security. This is the buffer
  270. * to be freed after we no longer need the data.
  271. * buffer_length: size of "buffer" space. It's only used for accounting
  272. * purposes. RECV_PRIORITY space is limited.
  273. * fPacketDirectionUp: Direction of the data pkt in MCS domain.
  274. */
  275. // incoming packets
  276. DataPacket::DataPacket(PTransportData pTransportData,
  277. BOOL fPacketDirectionUp)
  278. :
  279. SimplePacket(fPacketDirectionUp),
  280. m_fIncoming (TRUE),
  281. m_Memory (pTransportData->memory),
  282. m_EncodedDataBroken (FALSE),
  283. m_nMessageType(0)
  284. {
  285. m_EncodedPDU = (LPBYTE) pTransportData->user_data;
  286. Encoded_Data_Length = (UINT) pTransportData->user_data_length;
  287. // take care of the X.224 header
  288. memcpy (m_EncodedPDU, g_X224Header, PROTOCOL_OVERHEAD_X224);
  289. AddRFCSize (m_EncodedPDU, Encoded_Data_Length);
  290. // Now, we can decode the PDU
  291. g_MCSCoder->Decode (m_EncodedPDU + PROTOCOL_OVERHEAD_X224,
  292. Encoded_Data_Length - PROTOCOL_OVERHEAD_X224,
  293. DOMAIN_MCS_PDU, PACKED_ENCODING_RULES,
  294. (LPVOID *) &m_DecodedPDU, NULL);
  295. TRACE_OUT (("DataPacket::DataPacket: incoming data PDU packet was created successfully. Encoded size: %d",
  296. Encoded_Data_Length - PROTOCOL_OVERHEAD_X224));
  297. }
  298. /*
  299. * ~DataPacket ()
  300. *
  301. * Public
  302. *
  303. * Functional Description:
  304. * Destructor for the DataPacket class. The destructor ensures that all
  305. * resources that have been allocated are freed.
  306. */
  307. DataPacket::~DataPacket(void)
  308. {
  309. if (m_EncodedPDU != NULL) {
  310. UnlockMemory (m_Memory);
  311. if (m_EncodedDataBroken) {
  312. // Free the MCS and X.224 header buffer.
  313. Free (m_EncodedPDU);
  314. }
  315. }
  316. }
  317. /*
  318. * Equivalent ()
  319. *
  320. * Public
  321. *
  322. * Functional Description:
  323. * This function returns TRUE if the 2 packets belong to the same
  324. * original SendData request (normal or uniform), and FALSE, otherwise.
  325. */
  326. BOOL DataPacket::Equivalent (PDataPacket packet)
  327. {
  328. ASSERT (m_DecodedPDU.u.send_data_request.segmentation == SEGMENTATION_END);
  329. ASSERT ((packet->m_DecodedPDU.u.send_data_request.segmentation & SEGMENTATION_END) == 0);
  330. return ((m_DecodedPDU.u.send_data_request.initiator == packet->m_DecodedPDU.u.send_data_request.initiator) &&
  331. (m_DecodedPDU.u.send_data_request.channel_id == packet->m_DecodedPDU.u.send_data_request.channel_id) &&
  332. (m_DecodedPDU.u.send_data_request.data_priority == packet->m_DecodedPDU.u.send_data_request.data_priority) &&
  333. (m_DecodedPDU.choice == packet->m_DecodedPDU.choice));
  334. }
  335. /*
  336. * IsDataPacket ()
  337. *
  338. * Public
  339. *
  340. * Functional Description:
  341. * This function returns whether this is a data packet (it is).
  342. */
  343. BOOL DataPacket::IsDataPacket(void)
  344. {
  345. return (TRUE);
  346. }
  347. /*
  348. * SetDirection ()
  349. *
  350. * Public
  351. *
  352. * Functional Description:
  353. * If the DataPacket object is oriented differently than desired
  354. * by the caller of this method, then the packet coder is called to
  355. * reverse the direction of the PDU.
  356. */
  357. Void DataPacket::SetDirection (DBBoolean packet_direction_up)
  358. {
  359. /*
  360. * If the packet's encoded data is oriented differently from the desired
  361. * direction, call the packet coder's ReverseDirection method and
  362. * reverse the packet's direction indicator.
  363. */
  364. if (packet_direction_up != Packet_Direction_Up)
  365. {
  366. /*
  367. * Reverse the direction of the PDU.
  368. */
  369. g_MCSCoder->ReverseDirection (m_EncodedPDU);
  370. /*
  371. * The packet coder has reversed the direction of the PDU. Set
  372. * the Packet_Direction_Up flag to indicate the new state.
  373. */
  374. Packet_Direction_Up = packet_direction_up;
  375. }
  376. }
  377. /*
  378. * GetDecodedData ()
  379. *
  380. * Public
  381. *
  382. * Functional Description:
  383. * The GetDecodedData method returns a pointer to the decoded data
  384. * buffer. If the packet does not have decoded data the Decode method is
  385. * called.
  386. */
  387. PVoid DataPacket::GetDecodedData ()
  388. {
  389. return ((PVoid) &m_DecodedPDU);
  390. }
  391. /*
  392. * GetPDUType ()
  393. *
  394. * Public
  395. *
  396. * Functional Description:
  397. * The GetPDUType method returns the PDU type for the data packet.
  398. * For such a packet, the value is always
  399. */
  400. int DataPacket::GetPDUType ()
  401. {
  402. return (DOMAIN_MCS_PDU);
  403. }