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.

2242 lines
72 KiB

  1. #include "precomp.h"
  2. DEBUG_FILEZONE(ZONE_T120_T123PSTN);
  3. /* T123.cpp
  4. *
  5. * Copyright (c) 1993-1995 by DataBeam Corporation, Lexington, KY
  6. *
  7. * Abstract:
  8. * This is the implementation file for the T123 class.
  9. *
  10. * Beware::
  11. * When we refer to a Transport in this class, we are
  12. * talking about X224/Class 0.
  13. *
  14. * When we refer to a DataLink in this class, we are
  15. * talking about the Q922 Layer.
  16. *
  17. * Private Instance Variables:
  18. * Logical_Connection_List - This list uses the logical_handle as the
  19. * key and a DLCI as the value. From the DLCI we
  20. * can determine the specifics about the logical
  21. * connection
  22. * DLCI_List - This list uses a DLCI as the key and a
  23. * DLCIStruct as the value. The DLCIStruct holds
  24. * all of the important information about the
  25. * DLCI connection
  26. * Message_List - List used to hold owner callback information
  27. * that can not be processed immediately.
  28. * DataLink_List - This is a list of all the DataLink connections.
  29. * We keep a seperate list so that during the
  30. * PollTransmitter() call, we can round-robin thru
  31. * the list, giving each DataLink a chance to
  32. * transmit.
  33. * Transport_Priority_List- This is a prioritized list of DLCIs
  34. * During PollTransmitter() we process the
  35. * logical connections in priority order.
  36. *
  37. * m_pController - Address of the owner object
  38. * Link_Originator - TRUE if we originated the physical connection
  39. * m_nMsgBase - Message base used in the owner callback.
  40. * Identifier - Identifier to be passed back in the owner
  41. * callback
  42. * m_pSCF - Address of the network layer associated with
  43. * this T123 stack.
  44. * m_pQ922 - Address of DataLink Layer associated with the
  45. * Network Layer (DLCI 0).
  46. * m_pMultiplexer - Address of Multiplexer layer
  47. * m_pComPort - Address of physical layer
  48. * m_hCommLink - Physical handle used to access the physical
  49. * layer.
  50. * DataLink_Struct - Holds default Q922 values.
  51. * Data_Request_Memory_Manager - Holds the memory manager for the DLCI0
  52. * DataLink.
  53. * Random - Random number generator
  54. * Disconnect_Requested- TRUE, if the user has requested that the
  55. * complete stack be taken down.
  56. *
  57. *
  58. * Caveats:
  59. * None
  60. *
  61. * Author:
  62. * James W. Lawwill
  63. */
  64. #include "t123.h"
  65. #include "pstnfram.h"
  66. #include "crc.h"
  67. #define PSTN_DATALINK_MAX_OUTSTANDING_BYTES 1024
  68. #define TRANSPORT_DEFAULT_PDU_SIZE 128
  69. #define DEFAULT_PSTN_N201 260
  70. #define TRANSPORT_MAXIMUM_USER_DATA_SIZE 256
  71. #define NETWORK_RETRIES 20
  72. #define NUMBER_8K_BLOCKS 1
  73. #define NUMBER_64_BYTE_BLOCKS 64
  74. #define DEFAULT_MAXIMUM_OUTSTANDING_PACKETS 20
  75. #define DEFAULT_T200_TIMEOUT 3000
  76. #define DEFAULT_T200_COMM_TIMEOUT 500
  77. /*
  78. * T123::T123 (
  79. * PTransportResources transport_resources,
  80. * IObject * owner_object,
  81. * USHORT message_base,
  82. * BOOL link_originator,
  83. * IProtocolLayer * physical_layer,
  84. * PhysicalHandle physical_handle,
  85. * BOOL * t123_initialized)
  86. *
  87. * Public
  88. *
  89. * Functional Description:
  90. * This is the T123 constructor. It instantiates the multiplexer.
  91. */
  92. T123::T123
  93. (
  94. TransportController *owner_object,
  95. USHORT message_base,
  96. BOOL link_originator,
  97. ComPort *comport, // physical layer
  98. PhysicalHandle hCommLink, // physical handle
  99. PLUGXPRT_PARAMETERS *pParams,
  100. BOOL * t123_initialized
  101. )
  102. :
  103. Logical_Connection_List (TRANSPORT_HASHING_BUCKETS),
  104. DLCI_List (TRANSPORT_HASHING_BUCKETS),
  105. DataLink_List (),
  106. m_pController(owner_object),
  107. m_nMsgBase(message_base),
  108. m_hCommLink(hCommLink),
  109. m_pComPort(comport)
  110. {
  111. TRACE_OUT(("T123::T123"));
  112. PPacketFrame framer;
  113. PCRC crc;
  114. BOOL initialized;
  115. DWORD i;
  116. // SDK parameters
  117. if (NULL != pParams)
  118. {
  119. m_fValidSDKParams = TRUE;
  120. m_SDKParams = *pParams;
  121. }
  122. else
  123. {
  124. m_fValidSDKParams = FALSE;
  125. ::ZeroMemory(&m_SDKParams, sizeof(m_SDKParams));
  126. }
  127. // initialize priority list
  128. for (i = 0; i < NUMBER_OF_PRIORITIES; i++)
  129. {
  130. DBG_SAVE_FILE_LINE
  131. Logical_Connection_Priority_List[i] = new SListClass;
  132. }
  133. Link_Originator = link_originator;
  134. Disconnect_Requested = FALSE;
  135. m_pSCF = NULL;
  136. m_pQ922 = NULL;
  137. Data_Request_Memory_Manager = NULL;
  138. m_pMultiplexer = NULL;
  139. *t123_initialized = TRUE;
  140. DataLink_Struct.default_k_factor = DEFAULT_MAXIMUM_OUTSTANDING_PACKETS;
  141. DataLink_Struct.default_n201 = DEFAULT_PSTN_N201;
  142. ULONG baud_rate = m_pComPort->GetBaudRate();
  143. DataLink_Struct.default_t200 = ((m_pComPort->GetCallControlType() == PLUGXPRT_PSTN_CALL_CONTROL_MANUAL) ?
  144. ((baud_rate < CBR_2400 ) ?
  145. DEFAULT_T200_COMM_TIMEOUT << 4 : DEFAULT_T200_COMM_TIMEOUT ): DEFAULT_T200_TIMEOUT);
  146. TRACE_OUT(("T123: Defaults: k = %d n201 = %d t200 = %d",
  147. DataLink_Struct.default_k_factor,
  148. DataLink_Struct.default_n201,
  149. DataLink_Struct.default_t200));
  150. DataLink_Struct.k_factor = DEFAULT_MAXIMUM_OUTSTANDING_PACKETS;
  151. DataLink_Struct.n201 = DEFAULT_PSTN_N201;
  152. DataLink_Struct.t200 = DataLink_Struct.default_t200;
  153. /*
  154. ** Create the CRC object and pass it to the Multiplexer.
  155. ** Create a framer and send it to the Multiplexer.
  156. */
  157. DBG_SAVE_FILE_LINE
  158. crc = new CRC ();
  159. if (crc != NULL)
  160. {
  161. DBG_SAVE_FILE_LINE
  162. framer = (PPacketFrame) new PSTNFrame ();
  163. if (framer != NULL)
  164. {
  165. DBG_SAVE_FILE_LINE
  166. m_pMultiplexer = new Multiplexer(
  167. this,
  168. m_pComPort,
  169. m_hCommLink,
  170. MULTIPLEXER_LAYER_MESSAGE_BASE,
  171. framer,
  172. crc,
  173. &initialized);
  174. if (m_pMultiplexer != NULL && initialized)
  175. {
  176. /*
  177. ** Notify the Multiplexer layer to start a connection
  178. */
  179. m_pMultiplexer->ConnectRequest();
  180. }
  181. else
  182. {
  183. /*
  184. ** To get here, either the m_pMultiplexer == NULL or
  185. ** initialized == FALSE
  186. */
  187. if (m_pMultiplexer != NULL)
  188. {
  189. delete m_pMultiplexer;
  190. m_pMultiplexer = NULL;
  191. }
  192. else
  193. {
  194. delete crc;
  195. delete framer;
  196. }
  197. *t123_initialized = FALSE;
  198. }
  199. }
  200. else
  201. {
  202. delete crc;
  203. *t123_initialized = FALSE;
  204. }
  205. }
  206. else
  207. {
  208. *t123_initialized = FALSE;
  209. }
  210. }
  211. /*
  212. * T123::~T123 (void)
  213. *
  214. * Public
  215. *
  216. * Functional Description:
  217. * This is the destructor for the T123 object. It releases all memory
  218. */
  219. T123::~T123 (void)
  220. {
  221. TRACE_OUT(("T123::~T123"));
  222. DWORD i;
  223. /*
  224. ** Reset deletes all DataLink, Network, and Transport objects associated
  225. ** with this stack.
  226. */
  227. Reset ();
  228. /*
  229. ** Go thru the Message list and delete all passive owner callback messages
  230. */
  231. while (Message_List.isEmpty () == FALSE)
  232. {
  233. delete (PMessageStruct) Message_List.get ();
  234. }
  235. /*
  236. ** Delete the multiplexer layer
  237. */
  238. delete m_pMultiplexer;
  239. TRACE_OUT(("T123: Destructor"));
  240. for (i = 0; i < NUMBER_OF_PRIORITIES; i++)
  241. delete Logical_Connection_Priority_List[i];
  242. }
  243. /*
  244. * TransportError T123::ConnectRequest (
  245. * LogicalHandle logical_handle,
  246. * TransportPriority priority)
  247. *
  248. * Public
  249. *
  250. * Functional Description:
  251. * This is the function that initiates a logical connection with the
  252. * remote site.
  253. */
  254. TransportError T123::ConnectRequest (
  255. LogicalHandle logical_handle,
  256. TransportPriority priority)
  257. {
  258. TRACE_OUT(("T123::ConnectRequest"));
  259. PDLCIStruct dlci_struct;
  260. DLCI dlci;
  261. SCFError network_error;
  262. TransportError transport_error = TRANSPORT_NO_ERROR;
  263. /*
  264. ** Get a proposed DLCI for the connection
  265. */
  266. dlci = GetNextDLCI ();
  267. /*
  268. ** Add the new connection to the Logical_Connection_List
  269. */
  270. Logical_Connection_List.insert (logical_handle, (DWORD) dlci);
  271. /*
  272. ** Add the proposed DLCI to the DLCI_List
  273. ** Initialize all of the items in the DLCI structure
  274. */
  275. DBG_SAVE_FILE_LINE
  276. dlci_struct = new DLCIStruct;
  277. if (dlci_struct != NULL)
  278. {
  279. DLCI_List.insert ((DWORD_PTR) dlci, (DWORD_PTR) dlci_struct);
  280. dlci_struct -> link_originator = TRUE;
  281. dlci_struct -> x224 = NULL; // X.224
  282. dlci_struct -> q922 = NULL; // Q.922
  283. dlci_struct -> priority = priority;
  284. dlci_struct -> connect_requested = FALSE;
  285. dlci_struct -> disconnect_requested = FALSE;
  286. dlci_struct -> data_request_memory_manager = NULL;
  287. dlci_struct -> network_retries = 0;
  288. }
  289. else
  290. {
  291. /*
  292. ** Remove this entry and send a message to the owner
  293. */
  294. NetworkDisconnectIndication (dlci, TRUE, FALSE);
  295. return (TRANSPORT_MEMORY_FAILURE);
  296. }
  297. /*
  298. ** If the Network Layer exists, issue a connect request
  299. **
  300. ** If the Network Layer does not exist yet, the connection will be
  301. ** requested at a later time.
  302. */
  303. if (m_pSCF != NULL)
  304. {
  305. /*
  306. ** Mark this DLCI as already submitting its ConnectRequest()
  307. */
  308. dlci_struct -> connect_requested = TRUE;
  309. network_error = m_pSCF->ConnectRequest(dlci, priority);
  310. if (network_error != SCF_NO_ERROR)
  311. {
  312. /*
  313. ** Remove this entry and send a message to the owner
  314. */
  315. NetworkDisconnectIndication (dlci, TRUE, FALSE);
  316. if (network_error == SCF_MEMORY_ALLOCATION_ERROR)
  317. return (TRANSPORT_MEMORY_FAILURE);
  318. else
  319. return (TRANSPORT_CONNECT_REQUEST_FAILED);
  320. }
  321. }
  322. /*
  323. ** Process any passive owner callbacks that may have occured
  324. */
  325. ProcessMessages ();
  326. return (transport_error);
  327. }
  328. /*
  329. * TransportError T123::ConnectResponse (
  330. * LogicalHandle logical_handle)
  331. *
  332. * Public
  333. *
  334. * Functional Description:
  335. * This function is called in response to TPRT_CONNECT_INDICATION that we
  336. * issued to the controller. By making this call, the controller is
  337. * accepting the incoming call.
  338. */
  339. TransportError T123::ConnectResponse (
  340. LogicalHandle logical_handle)
  341. {
  342. TRACE_OUT(("T123::ConnectResponse"));
  343. PDLCIStruct dlci_struct;
  344. TransportError return_value;
  345. DWORD_PTR dwTempDLCI;
  346. /*
  347. ** Verify that this connection exists and is ready for data
  348. */
  349. if (Logical_Connection_List.find (logical_handle, &dwTempDLCI) == FALSE)
  350. return (TRANSPORT_NO_SUCH_CONNECTION);
  351. /*
  352. ** Get the Transport address from the DLCI_List and relay the call
  353. */
  354. DLCI_List.find (dwTempDLCI, (PDWORD_PTR) &dlci_struct);
  355. if (dlci_struct->x224 != NULL)
  356. return_value = dlci_struct->x224->ConnectResponse();
  357. else
  358. return_value = TRANSPORT_CONNECT_REQUEST_FAILED;
  359. /*
  360. ** Process any passive owner callbacks that may have been received
  361. */
  362. ProcessMessages ();
  363. return (return_value);
  364. }
  365. /*
  366. * TransportError T123::DisconnectRequest (
  367. * LogicalHandle logical_handle,
  368. * BOOL trash_packets)
  369. *
  370. * Public
  371. *
  372. * Functional Description:
  373. * This function terminates the user's logical connection.
  374. */
  375. TransportError T123::DisconnectRequest (
  376. LogicalHandle logical_handle,
  377. UINT_PTR trash_packets)
  378. {
  379. TRACE_OUT(("T123::DisconnectRequest"));
  380. Short priority;
  381. DLCI dlci;
  382. PDLCIStruct dlci_struct;
  383. DWORD_PTR dw_dlci;
  384. TRACE_OUT(("T123: DisconnectRequest: logical_handle = %d", logical_handle));
  385. /*
  386. ** If the logical_handle == INVALID_LOGICAL_HANDLE, the user is
  387. ** telling us to disconnect all logical connections including DLCI 0.
  388. */
  389. if (logical_handle == INVALID_LOGICAL_HANDLE)
  390. {
  391. Disconnect_Requested = TRUE;
  392. if (m_pQ922 != NULL)
  393. m_pQ922->ReleaseRequest();
  394. else
  395. {
  396. m_pController->OwnerCallback(
  397. m_nMsgBase + TPRT_DISCONNECT_INDICATION,
  398. INVALID_LOGICAL_HANDLE,
  399. m_hCommLink,
  400. &Disconnect_Requested);
  401. }
  402. /*
  403. ** For each priority level, clear the Priority list
  404. */
  405. for (priority=(NUMBER_OF_PRIORITIES - 1); priority>=0; priority--)
  406. Logical_Connection_Priority_List[priority]->clear ();
  407. /*
  408. ** Clear the Logical_Connection_List and DataLink_List
  409. */
  410. Logical_Connection_List.clear ();
  411. DataLink_List.clear ();
  412. /*
  413. ** Go thru each Transport and DataLink layer (excluding DLCI 0) and
  414. ** delete them. Delete the DLCIStruct. Finally, clear the list.
  415. */
  416. DLCI_List.reset();
  417. while (DLCI_List.iterate ((PDWORD_PTR) &dlci_struct))
  418. {
  419. delete dlci_struct -> x224;
  420. if (dlci_struct -> q922 != NULL)
  421. {
  422. delete dlci_struct -> q922;
  423. delete dlci_struct -> data_request_memory_manager;
  424. }
  425. delete dlci_struct;
  426. }
  427. DLCI_List.clear ();
  428. return (TRANSPORT_NO_ERROR);
  429. }
  430. /*
  431. ** Start breaking down the link from the Transport Layer down
  432. */
  433. if (Logical_Connection_List.find (logical_handle, &dw_dlci) == FALSE)
  434. return (TRANSPORT_NO_SUCH_CONNECTION);
  435. DLCI_List.find (dw_dlci, (PDWORD_PTR) &dlci_struct);
  436. dlci = (DLCI) dw_dlci;
  437. /*
  438. ** It is illegal for the user to ask us to preserve the user data when
  439. ** a Transport Layer doesn't even exist yet.
  440. */
  441. if ((trash_packets == FALSE) && ((dlci_struct -> x224) == NULL))
  442. {
  443. trash_packets = TRUE;
  444. }
  445. if (trash_packets)
  446. {
  447. /*
  448. ** If the Transport object exists, delete it and remove it from our
  449. ** lists. It is no longer valid.
  450. */
  451. if ((dlci_struct -> x224) != NULL)
  452. {
  453. delete dlci_struct -> x224;
  454. dlci_struct -> x224 = NULL;
  455. Logical_Connection_Priority_List[dlci_struct->priority]->remove (dlci);
  456. }
  457. /*
  458. ** If the DataLink object exists, delete it and remove it from our
  459. ** lists. It is no longer valid.
  460. */
  461. if (dlci_struct -> q922 != NULL)
  462. {
  463. delete dlci_struct -> q922;
  464. delete dlci_struct -> data_request_memory_manager;
  465. dlci_struct -> data_request_memory_manager = NULL;
  466. dlci_struct -> q922 = NULL;
  467. DataLink_List.remove (dlci);
  468. }
  469. /*
  470. ** If the Network Layer exists, issue a disconnect
  471. **
  472. ** The Logical Connection has been removed from every list except the
  473. ** Logical_Connection_List and the DLCI_List. When we get the
  474. ** NETWORK_DISCONNECT_INDICATION from the Network layer, we will
  475. ** complete this operation.
  476. */
  477. if (m_pSCF != NULL)
  478. {
  479. m_pSCF->DisconnectRequest(dlci);
  480. }
  481. else
  482. {
  483. /*
  484. ** If the Network Layer does not exist yet, remove the logical
  485. ** connection from our Transport List and from the DLCI_List
  486. */
  487. Logical_Connection_List.remove (logical_handle);
  488. delete dlci_struct;
  489. DLCI_List.remove (dw_dlci);
  490. }
  491. }
  492. else
  493. {
  494. /*
  495. ** This mode requires us to terminate the connection after all user
  496. ** data has been successfully sent to the remote side.
  497. */
  498. if ((dlci_struct != NULL) && (dlci_struct -> x224 != NULL))
  499. {
  500. dlci_struct->x224->ShutdownReceiver ();
  501. dlci_struct->x224->ShutdownTransmitter ();
  502. dlci_struct->disconnect_requested = TRUE;
  503. }
  504. }
  505. return (TRANSPORT_NO_ERROR);
  506. }
  507. /*
  508. * TransportError T123::DataRequest (
  509. * LogicalHandle logical_handle,
  510. * LPBYTE user_data,
  511. * ULONG user_data_length)
  512. *
  513. * Public
  514. *
  515. * Functional Description:
  516. * This function is used to send a data packet to the remote site.
  517. */
  518. TransportError T123::DataRequest (
  519. LogicalHandle logical_handle,
  520. LPBYTE user_data,
  521. ULONG user_data_length)
  522. {
  523. TRACE_OUT(("T123::DataRequest"));
  524. CLayerX224 *x224;
  525. ULONG bytes_accepted;
  526. PDLCIStruct dlci_struct;
  527. DWORD_PTR dw_dlci;
  528. TransportError return_value;
  529. /*
  530. ** Verify that this connection exists and is ready for data
  531. */
  532. if (Logical_Connection_List.find (logical_handle, &dw_dlci) == FALSE)
  533. return (TRANSPORT_NO_SUCH_CONNECTION);
  534. /*
  535. ** Get the DLCI structure associated with this logical connection
  536. */
  537. DLCI_List.find (dw_dlci, (PDWORD_PTR) &dlci_struct);
  538. /*
  539. ** Attempt to send that data to the Transport Layer
  540. */
  541. x224 = dlci_struct -> x224;
  542. if (x224 == NULL)
  543. return (TRANSPORT_NOT_READY_TO_TRANSMIT);
  544. /*
  545. ** Pass the data to the Transport object for transmission
  546. */
  547. return_value = x224 -> DataRequest (
  548. 0, user_data, user_data_length, &bytes_accepted);
  549. /*
  550. ** If it didn't accept the packet, its buffers must be full
  551. */
  552. if (bytes_accepted != user_data_length)
  553. return_value = TRANSPORT_WRITE_QUEUE_FULL;
  554. return (return_value);
  555. }
  556. /*
  557. * void T123::EnableReceiver (void)
  558. *
  559. * Public
  560. *
  561. * Functional Description:
  562. * This function enables the receiver so that packets can be passed to the
  563. * user application.
  564. */
  565. void T123::EnableReceiver (void)
  566. {
  567. TRACE_OUT(("T123::EnableReceiver"));
  568. PDLCIStruct dlci_struct;
  569. DLCI_List.reset();
  570. while (DLCI_List.iterate ((PDWORD_PTR) &dlci_struct))
  571. {
  572. if (dlci_struct->x224 != NULL)
  573. {
  574. dlci_struct->x224->EnableReceiver ();
  575. }
  576. }
  577. return;
  578. }
  579. /*
  580. * TransportError T123::PurgeRequest (
  581. * LogicalHandle logical_handle)
  582. *
  583. * Public
  584. *
  585. * Functional Description:
  586. * This function notifies the X224 layer to purge all outbound packets.
  587. */
  588. TransportError T123::PurgeRequest (
  589. LogicalHandle logical_handle)
  590. {
  591. TRACE_OUT(("T123::PurgeRequest"));
  592. DWORD_PTR dw_dlci;
  593. PDLCIStruct dlci_struct;
  594. /*
  595. ** Verify that this connection exists and is ready for data
  596. */
  597. if (Logical_Connection_List.find (logical_handle, &dw_dlci) == FALSE)
  598. return (TRANSPORT_NO_SUCH_CONNECTION);
  599. /*
  600. ** Get the DLCI structure associated with this logical connection
  601. */
  602. DLCI_List.find (dw_dlci, (PDWORD_PTR) &dlci_struct);
  603. /*
  604. ** If the Transport layer == NULL, the stack is not completely up yet
  605. */
  606. if ((dlci_struct -> x224) == NULL)
  607. return (TRANSPORT_NOT_READY_TO_TRANSMIT);
  608. dlci_struct->x224->PurgeRequest ();
  609. return (TRANSPORT_NO_ERROR);
  610. }
  611. /*
  612. * void T123::PollReceiver (void)
  613. *
  614. * Public
  615. *
  616. * Functional Description:
  617. * This function gives each of the layers a chance to process incoming
  618. * data and pass it to their higher layers.
  619. *
  620. * We start this process by calling the higher layers first so that they
  621. * can empty buffers that the lower layers may need.
  622. */
  623. ULONG T123::PollReceiver (void)
  624. {
  625. // TRACE_OUT(("T123::PollReceiver"));
  626. PDLCIStruct dlci_struct;
  627. IProtocolLayer * protocol_layer;
  628. ULONG return_error = FALSE;
  629. if (m_pSCF != NULL)
  630. {
  631. m_pSCF->PollReceiver();
  632. }
  633. if (m_pQ922 != NULL)
  634. {
  635. m_pQ922->PollReceiver();
  636. }
  637. /*
  638. ** Go through each of the Transport and Datalink layers and give them
  639. ** a chance to pass data up the line
  640. */
  641. DLCI_List.reset();
  642. while (DLCI_List.iterate ((PDWORD_PTR) &dlci_struct))
  643. {
  644. protocol_layer = dlci_struct -> x224;
  645. if (protocol_layer != NULL)
  646. protocol_layer -> PollReceiver();
  647. protocol_layer = dlci_struct -> q922;
  648. if (protocol_layer != NULL)
  649. protocol_layer -> PollReceiver();
  650. }
  651. if (m_pMultiplexer != NULL)
  652. {
  653. m_pMultiplexer->PollReceiver();
  654. }
  655. /*
  656. ** The Physical Layer is the only layer that has a handle associated
  657. ** with it.
  658. */
  659. if (m_pComPort != NULL)
  660. {
  661. if (m_pComPort->PollReceiver() == PROTOCOL_LAYER_ERROR)
  662. {
  663. return_error = PROTOCOL_LAYER_ERROR;
  664. }
  665. }
  666. /*
  667. ** Go back through the Transport layers and allow them to issue
  668. ** TRANSPORT_BUFFER_AVAILABLE_INDICATIONs to the user. This will refill
  669. ** the input buffers.
  670. */
  671. DLCI_List.reset ();
  672. while (DLCI_List.iterate ((PDWORD_PTR) &dlci_struct))
  673. {
  674. if (dlci_struct -> x224 != NULL)
  675. (dlci_struct -> x224) -> CheckUserBuffers ();
  676. }
  677. /*
  678. ** Process any passive owner callbacks that may have come in
  679. */
  680. ProcessMessages ();
  681. return(return_error);
  682. }
  683. /*
  684. * void T123::PollTransmitter (void)
  685. *
  686. * Public
  687. *
  688. * Functional Description:
  689. * This function gives each of the layers a chance to transmit data
  690. *
  691. * We poll the transmitters in reverse order from the PollReceiver() call.
  692. * We start at the lower layers and let them empty their buffers before we
  693. * go to the higher layers. This should give the higher layers a better
  694. * opportunity to get their packets sent down.
  695. *
  696. * We treat the DataLink layers differently than all other layers. They
  697. * must send out control and user data. If they don't get a chance to
  698. * send out their control data, the remote side will eventually hangup on
  699. * them. Therefore we give each DataLink layer a chance to send its
  700. * control data before any DataLink can send out user data. The only
  701. * exception to this is the DataLink 0 (DLCI 0). It actaully sends out
  702. * very little user data.A
  703. *
  704. * After all of the control data is sent out, we go thru the Datalink
  705. * Layers based on the priority given to the Transport Layer. Higher
  706. * priority Transport Layers get to send their data out first. If there
  707. * any room left, the lower layers get to send their data. We round-robin
  708. * thru the Transports of equal priority
  709. */
  710. void T123::PollTransmitter (void)
  711. {
  712. // TRACE_OUT(("T123::PollTransmitter"));
  713. PDLCIStruct dlci_struct;
  714. DWORD_PTR dlci;
  715. IProtocolLayer * protocol_layer;
  716. USHORT data_to_transmit;
  717. USHORT data_pending;
  718. USHORT datalink_data_to_transmit;
  719. USHORT datalink_data_pending;
  720. USHORT holding_data;
  721. Short priority;
  722. /*
  723. ** Since we are going to call the Physical and Multiplexer layers, set
  724. ** the data_to_transmit to both types of data
  725. */
  726. data_to_transmit = PROTOCOL_CONTROL_DATA | PROTOCOL_USER_DATA;
  727. datalink_data_to_transmit = PROTOCOL_CONTROL_DATA | PROTOCOL_USER_DATA;
  728. if (m_pComPort != NULL)
  729. {
  730. m_pComPort->PollTransmitter(
  731. (ULONG_PTR) m_hCommLink,
  732. data_to_transmit,
  733. &data_pending,
  734. &holding_data);
  735. }
  736. if (m_pMultiplexer != NULL)
  737. {
  738. m_pMultiplexer->PollTransmitter(
  739. 0,
  740. data_to_transmit,
  741. &data_pending,
  742. &holding_data);
  743. }
  744. /*
  745. ** The SCF Datalink Layer is the highest priority
  746. */
  747. if (m_pQ922 != NULL)
  748. {
  749. m_pQ922->PollTransmitter(
  750. 0,
  751. datalink_data_to_transmit,
  752. &datalink_data_pending,
  753. &holding_data);
  754. /*
  755. ** If this DataLink returns and still has data that needs to go out,
  756. ** we won't let the other DataLinks transmit any data at all.
  757. */
  758. if ((datalink_data_pending & PROTOCOL_USER_DATA) ||
  759. (datalink_data_pending & PROTOCOL_CONTROL_DATA))
  760. datalink_data_to_transmit = 0;
  761. }
  762. if (m_pSCF != NULL)
  763. {
  764. m_pSCF->PollTransmitter(
  765. 0,
  766. data_to_transmit,
  767. &data_pending,
  768. &holding_data);
  769. if (data_pending & PROTOCOL_USER_DATA)
  770. datalink_data_to_transmit = PROTOCOL_CONTROL_DATA;
  771. }
  772. /*
  773. ** Go thru each of the DataLinks giving them a chance to send out control
  774. ** data. At the end of the iterator, we take the first entry and put it
  775. ** at the end of the list. This gives all DataLinks a chance to send out
  776. ** control data. This does not guarantee that each DataLink will get
  777. ** equal treatment.
  778. */
  779. if (datalink_data_to_transmit & PROTOCOL_CONTROL_DATA)
  780. {
  781. /*
  782. ** Go through the DataLink layers to transmit control
  783. */
  784. DataLink_List.reset();
  785. while (DataLink_List.iterate (&dlci))
  786. {
  787. DLCI_List.find (dlci, (PDWORD_PTR) &dlci_struct);
  788. dlci_struct->q922->PollTransmitter(0,
  789. PROTOCOL_CONTROL_DATA,
  790. &datalink_data_pending,
  791. &holding_data);
  792. if (datalink_data_pending & PROTOCOL_CONTROL_DATA)
  793. datalink_data_to_transmit = PROTOCOL_CONTROL_DATA;
  794. }
  795. if (DataLink_List.entries() > 1)
  796. {
  797. DataLink_List.append (DataLink_List.get ());
  798. }
  799. }
  800. /*
  801. ** Go thru each of the priorities, Issuing PollTransmitter() calls.
  802. **
  803. ** This loop allows the DataLink and Transport to send out User or
  804. ** Control data.
  805. */
  806. if (datalink_data_to_transmit & PROTOCOL_USER_DATA)
  807. {
  808. for (priority=(NUMBER_OF_PRIORITIES - 1); priority>=0; priority--)
  809. {
  810. if (Logical_Connection_Priority_List[priority]->isEmpty ())
  811. continue;
  812. /*
  813. ** Go thru each priority level
  814. */
  815. Logical_Connection_Priority_List[priority]->reset();
  816. while (Logical_Connection_Priority_List[priority]->iterate (&dlci))
  817. {
  818. DLCI_List.find (dlci, (PDWORD_PTR) &dlci_struct);
  819. protocol_layer = dlci_struct -> x224;
  820. if (protocol_layer == NULL)
  821. continue;
  822. /*
  823. ** Allow the DataLink to transmit first, followed by the
  824. ** Transport
  825. */
  826. dlci_struct->q922->PollTransmitter(
  827. 0,
  828. PROTOCOL_CONTROL_DATA | PROTOCOL_USER_DATA,
  829. &datalink_data_pending,
  830. &holding_data);
  831. protocol_layer -> PollTransmitter (
  832. 0,
  833. PROTOCOL_CONTROL_DATA | PROTOCOL_USER_DATA,
  834. &data_pending,
  835. &holding_data);
  836. /*
  837. ** The Disconnect_Requested flag is set to TRUE if someone
  838. ** wants to break the TC but transmit all data in the queue
  839. */
  840. if ((dlci_struct -> disconnect_requested))
  841. {
  842. /*
  843. ** Re-call the DataLink layer to see if the Transport
  844. ** layer put any data in it to be transmitted.
  845. */
  846. dlci_struct->q922->PollTransmitter(
  847. 0,
  848. PROTOCOL_CONTROL_DATA | PROTOCOL_USER_DATA,
  849. &datalink_data_pending,
  850. &holding_data);
  851. /*
  852. ** If the DataLink layer has no data to transmit and it
  853. ** is not holding any packets to be acknowledged,
  854. ** disconnect the TC.
  855. */
  856. if ((datalink_data_pending == 0) && (holding_data == 0))
  857. {
  858. dlci_struct -> disconnect_requested = FALSE;
  859. m_pSCF->DisconnectRequest ((DLCI) dlci);
  860. }
  861. }
  862. }
  863. /*
  864. ** Change the order of the list at this priority level
  865. */
  866. Logical_Connection_Priority_List[priority]->append (
  867. Logical_Connection_Priority_List[priority]->get ());
  868. }
  869. }
  870. /*
  871. ** Process any passive owner callbacks
  872. */
  873. ProcessMessages ();
  874. }
  875. /*
  876. * ULONG T123::OwnerCallback (
  877. * USHORT message,
  878. * ULONG parameter1,
  879. * ULONG parameter2,
  880. * PVoid parameter3)
  881. *
  882. * Public
  883. *
  884. * Functional Description:
  885. * This is the owner callback function. Layers owned by this layer can
  886. * issue an owner callback to this object when a significant event occurs.
  887. */
  888. ULONG T123::OwnerCallback
  889. (
  890. ULONG layer_message,
  891. void *parameter1,
  892. void *parameter2,
  893. void *parameter3
  894. )
  895. {
  896. TRACE_OUT(("T123::OwnerCallback"));
  897. ULONG message;
  898. PMessageStruct passive_message;
  899. ULONG return_value = 0;
  900. message = layer_message & MESSAGE_MASK;
  901. switch (message)
  902. {
  903. case NETWORK_CONNECT_INDICATION:
  904. /*
  905. ** This message comes from the Network Layer when the remote site
  906. ** has requested a logical connection.
  907. **
  908. ** We will check the requested dlci to make sure it is valid.
  909. ** We will make a ConnectResponse() call to the Network layer to
  910. ** let it know.
  911. */
  912. NetworkConnectIndication ((PNetworkConnectStruct) parameter3);
  913. break;
  914. case NETWORK_CONNECT_CONFIRM:
  915. /*
  916. ** This message is issued from the Network Layer. The
  917. ** ConnectRequest() call we made to the layer has resulted in
  918. ** a new DLCI (permission to create a new logical connection)
  919. */
  920. NetworkConnectConfirm ((PNetworkConnectStruct) parameter3);
  921. break;
  922. case DATALINK_ESTABLISH_CONFIRM:
  923. case DATALINK_ESTABLISH_INDICATION:
  924. /*
  925. ** These messages come from the DataLink layer when a connection
  926. ** has been established. If the DLCI returned is 0, this signifies
  927. ** that we need to create a Network Layer, otherwise we need to
  928. ** create a Transport Layer.
  929. */
  930. DataLinkEstablish ((DLCI) parameter1);
  931. break;
  932. /*
  933. ** Transport messages
  934. */
  935. case TPRT_CONNECT_CONFIRM:
  936. /*
  937. ** This message is received from the Transport Layer to confirm
  938. ** that the Transport Layer (that we initiated) is up and running
  939. **
  940. ** We notify the owner object that the connection is now valid.
  941. */
  942. m_pController->OwnerCallback(m_nMsgBase + TPRT_CONNECT_CONFIRM,
  943. parameter1);
  944. break;
  945. case TPRT_CONNECT_INDICATION:
  946. /*
  947. ** This message is received from the Transport Layer to confirm
  948. ** that the Transport Layer (that the remote site initiated) is
  949. ** up.
  950. **
  951. ** We notify the owner object that the connection is up.
  952. */
  953. m_pController->OwnerCallback(m_nMsgBase + TPRT_CONNECT_INDICATION,
  954. parameter1);
  955. break;
  956. case NEW_CONNECTION:
  957. /*
  958. ** Multiplexer is initiated and ready, create a DataLink to sit
  959. ** on top of this layer. The Link_Originator flag tells the
  960. ** DataLink whether to start link establishment
  961. */
  962. NewConnection ();
  963. break;
  964. case BROKEN_CONNECTION:
  965. case TPRT_DISCONNECT_INDICATION:
  966. case NETWORK_DISCONNECT_INDICATION:
  967. case DATALINK_RELEASE_INDICATION:
  968. case DATALINK_RELEASE_CONFIRM:
  969. /*
  970. ** These messages need to be processed at a later time.
  971. */
  972. DBG_SAVE_FILE_LINE
  973. passive_message = new MessageStruct;
  974. if (NULL != passive_message)
  975. {
  976. passive_message -> message = layer_message;
  977. passive_message -> parameter1 = parameter1;
  978. passive_message -> parameter2 = parameter2;
  979. passive_message -> parameter3 = parameter3;
  980. Message_List.append ((DWORD_PTR) passive_message);
  981. }
  982. else
  983. {
  984. ERROR_OUT(("T123::OwnerCallback: cannot allocate MessageStruct"));
  985. }
  986. break;
  987. case T123_STATUS_MESSAGE:
  988. TRACE_OUT(("T123: OwnerCallback: T123_STATUS_MESSAGE"));
  989. switch ((UINT)((UINT_PTR)(parameter2)))
  990. {
  991. case DATALINK_TIMING_ERROR:
  992. ERROR_OUT(("T123: OwnerCallback: DATALINK_TIMING_ERROR"));
  993. break;
  994. default:
  995. ERROR_OUT(("T123: OwnerCallback: Illegal status message = %ld", (UINT)((UINT_PTR)parameter2)));
  996. break;
  997. }
  998. break;
  999. default:
  1000. ERROR_OUT(("T123: OwnerCallback: Illegal message = %lx", message));
  1001. break;
  1002. }
  1003. return (return_value);
  1004. }
  1005. /*
  1006. * void Controller::ProcessMessages (void)
  1007. *
  1008. * Public
  1009. *
  1010. * Functional Description:
  1011. * This function processes the passive owner callbacks.
  1012. */
  1013. void T123::ProcessMessages (void)
  1014. {
  1015. // TRACE_OUT(("T123::ProcessMessages"));
  1016. ULONG message;
  1017. PMessageStruct message_struct;
  1018. void *parameter1;
  1019. void *parameter2;
  1020. LogicalHandle logical_handle;
  1021. DLCI dlci;
  1022. USHORT link_originator;
  1023. USHORT retry;
  1024. DataLinkDisconnectType error;
  1025. /*
  1026. ** Go thru the Message List processing the messages until the messages
  1027. ** are gone
  1028. */
  1029. while (! Message_List.isEmpty())
  1030. {
  1031. message_struct = (PMessageStruct) Message_List.get();
  1032. message = (message_struct -> message) & MESSAGE_MASK;
  1033. parameter1 = message_struct -> parameter1;
  1034. parameter2 = message_struct -> parameter2;
  1035. switch (message)
  1036. {
  1037. /*
  1038. ** DataLink messages
  1039. */
  1040. case DATALINK_RELEASE_INDICATION:
  1041. case DATALINK_RELEASE_CONFIRM:
  1042. /*
  1043. ** These messages occur when the DataLink has broken the link
  1044. */
  1045. dlci = (DLCI) parameter1;
  1046. error = (DataLinkDisconnectType) (UINT_PTR) parameter2;
  1047. DataLinkRelease (dlci, error);
  1048. break;
  1049. /*
  1050. ** Network messages
  1051. */
  1052. case NETWORK_DISCONNECT_INDICATION:
  1053. /*
  1054. ** The Network Layer issues this message when it needs to
  1055. ** terminate a logical connection
  1056. */
  1057. dlci = (DLCI) parameter1;
  1058. link_originator = (USHORT) (((UINT_PTR) parameter2) >> 16);
  1059. retry = (USHORT) ((UINT_PTR) parameter2) & 0xffff;
  1060. NetworkDisconnectIndication (dlci, link_originator, retry);
  1061. break;
  1062. case TPRT_DISCONNECT_INDICATION:
  1063. /*
  1064. ** If the Transport is breaking the connection, the
  1065. ** Connect arbitration must not have worked. Issue a
  1066. ** DisconnectRequest() to ourselves with the logical
  1067. ** connection
  1068. **
  1069. ** parameter1 = logical connection
  1070. */
  1071. TRACE_OUT(("T123: ProcessMessages: TPRT_DISCONNECT_INDICATION from X224"));
  1072. logical_handle = (LogicalHandle) parameter1;
  1073. DisconnectRequest (logical_handle, TRUE);
  1074. break;
  1075. case BROKEN_CONNECTION:
  1076. /*
  1077. ** This message is issued by the Multiplexer when its
  1078. ** disconnect is completed. When this occurs, we notify the
  1079. ** owner that the T123 stack is terminating.
  1080. */
  1081. TRACE_OUT(("t123: BROKEN_CONNECTION from MPLEX"));
  1082. m_pController->OwnerCallback(
  1083. m_nMsgBase + TPRT_DISCONNECT_INDICATION,
  1084. INVALID_LOGICAL_HANDLE,
  1085. m_hCommLink,
  1086. &Disconnect_Requested);
  1087. break;
  1088. }
  1089. /*
  1090. ** Delete the message and remove it from the list
  1091. */
  1092. delete message_struct;
  1093. Message_List.remove ((DWORD_PTR) message_struct);
  1094. }
  1095. }
  1096. /*
  1097. * DLCI T123::GetNextDLCI (void)
  1098. *
  1099. * Functional Description
  1100. * This function searches the DLCI list for the first available DLCI. The
  1101. * T123 spec. allows DLCIs between a specified range.
  1102. *
  1103. * Formal Parameters
  1104. * None
  1105. *
  1106. * Return Value
  1107. * Valid DLCI
  1108. *
  1109. * Side Effects
  1110. * None
  1111. *
  1112. * Caveats
  1113. * None
  1114. */
  1115. DLCI T123::GetNextDLCI (void)
  1116. {
  1117. DLCI dlci;
  1118. dlci = (DLCI) ((GetTickCount() % (HIGHEST_DLCI_VALUE + 1 - LOWEST_DLCI_VALUE)) + LOWEST_DLCI_VALUE);
  1119. while(1)
  1120. {
  1121. if(DLCI_List.find ((DWORD) dlci) == FALSE)
  1122. break;
  1123. if (++dlci > HIGHEST_DLCI_VALUE)
  1124. dlci = LOWEST_DLCI_VALUE;
  1125. }
  1126. return (dlci);
  1127. }
  1128. /*
  1129. * void T123::Reset (void)
  1130. *
  1131. * Functional Description
  1132. * This function deletes all Transport Layers, DataLink Layers and
  1133. * Network Layers that are active. It clears our lists and puts us
  1134. * in a reset state.
  1135. *
  1136. * Formal Parameters
  1137. * None
  1138. *
  1139. * Return Value
  1140. * Valid DLCI
  1141. *
  1142. * Side Effects
  1143. * None
  1144. *
  1145. * Caveats
  1146. * None
  1147. */
  1148. void T123::Reset (void)
  1149. {
  1150. TRACE_OUT(("T123::Reset"));
  1151. TRACE_OUT(("T123::Reset network layer = %lx", m_pSCF));
  1152. Short priority;
  1153. PDLCIStruct dlci_struct;
  1154. /*
  1155. ** Delete the Network Layer if it exists
  1156. */
  1157. delete m_pSCF;
  1158. m_pSCF = NULL;
  1159. /*
  1160. ** Delete the DLCI 0 DataLink Layer, if it exists
  1161. */
  1162. delete m_pQ922;
  1163. m_pQ922 = NULL;
  1164. delete Data_Request_Memory_Manager;
  1165. Data_Request_Memory_Manager = NULL;
  1166. /*
  1167. ** For each priority level, clear the Priority list
  1168. */
  1169. for (priority=(NUMBER_OF_PRIORITIES - 1); priority>=0; priority--)
  1170. Logical_Connection_Priority_List[priority]->clear ();
  1171. /*
  1172. ** Clear the Logical_Connection_List and DataLink_List
  1173. */
  1174. Logical_Connection_List.clear ();
  1175. DataLink_List.clear ();
  1176. /*
  1177. ** Go thru each Transport and DataLink layer (excluding DLCI 0) and delete
  1178. ** them. Delete the DLCIStruct. Finally, clear the list
  1179. */
  1180. DLCI_List.reset();
  1181. while (DLCI_List.iterate ((PDWORD_PTR) &dlci_struct))
  1182. {
  1183. delete dlci_struct->x224;
  1184. if (dlci_struct->q922 != NULL)
  1185. {
  1186. delete dlci_struct->q922;
  1187. delete dlci_struct->data_request_memory_manager;
  1188. }
  1189. delete dlci_struct;
  1190. }
  1191. DLCI_List.clear ();
  1192. }
  1193. /*
  1194. * void T123::NetworkDisconnectIndication (
  1195. * DLCI dlci,
  1196. * BOOL link_originator,
  1197. * BOOL retry)
  1198. *
  1199. * Functional Description
  1200. * This function is called when we receive a NETWORK_DISCONNECT_INDICATION
  1201. * message from the SCF Layer. It removes the TC and if no TCs remain, it
  1202. * tears down the stack
  1203. *
  1204. * Formal Parameters
  1205. * dlci (i) - Connection identifier
  1206. * link_originiator (i) - TRUE, if this side originated the logical
  1207. * connection
  1208. * retry (i) - TRUE, if we should retry the connection.
  1209. *
  1210. * Return Value
  1211. * void
  1212. *
  1213. * Side Effects
  1214. * None
  1215. *
  1216. * Caveats
  1217. * None
  1218. */
  1219. void T123::NetworkDisconnectIndication (
  1220. DLCI dlci,
  1221. BOOL link_originator,
  1222. BOOL retry)
  1223. {
  1224. TRACE_OUT(("T123::NetworkDisconnectIndication"));
  1225. DLCI new_dlci;
  1226. LogicalHandle logical_handle;
  1227. BOOL transport_found;
  1228. PDLCIStruct lpdlciStruct;
  1229. DWORD_PTR dwTemp_dlci;
  1230. TRACE_OUT(("T123: NetworkDisconnectIndication"));
  1231. if (DLCI_List.find ((DWORD_PTR) dlci, (PDWORD_PTR) &lpdlciStruct) == FALSE)
  1232. return;
  1233. /*
  1234. ** if dlci equals 0, a connection was requested by the remote
  1235. ** site but the connection was not fully established. This object
  1236. ** will not do anything about it. It only recognizes that it
  1237. ** occured.
  1238. */
  1239. transport_found = FALSE;
  1240. if (dlci != 0)
  1241. {
  1242. Logical_Connection_List.reset();
  1243. while (Logical_Connection_List.iterate(&dwTemp_dlci, (PDWORD_PTR) &logical_handle))
  1244. {
  1245. if (dlci == (DLCI) dwTemp_dlci)
  1246. {
  1247. /*
  1248. ** It is VERY important to check the link_originator flag,
  1249. ** otherwise we may break the wrong connection
  1250. */
  1251. if (link_originator == lpdlciStruct-> link_originator)
  1252. {
  1253. transport_found = TRUE;
  1254. break;
  1255. }
  1256. }
  1257. }
  1258. }
  1259. /*
  1260. ** retry is set to TRUE if during the request for this new
  1261. ** connection, the remote site refused our DLCI selection.
  1262. ** This is not a major error, we will request another
  1263. ** connection using another DLCI.
  1264. */
  1265. TRACE_OUT(("retry = %d link_originator = %d retries = %d",
  1266. retry, link_originator, lpdlciStruct->network_retries));
  1267. if (retry && link_originator &&
  1268. (lpdlciStruct->network_retries < NETWORK_RETRIES))
  1269. {
  1270. lpdlciStruct->network_retries++;
  1271. /*
  1272. ** Get another DLCI and replace the old dlci in the
  1273. ** Logical_Connection_List. Add the new DLCI to the DLCI_List
  1274. ** and remove the old one.
  1275. */
  1276. new_dlci = GetNextDLCI ();
  1277. Logical_Connection_List.insert (logical_handle, (DWORD_PTR) new_dlci);
  1278. DLCI_List.insert ((DWORD_PTR) new_dlci, (DWORD_PTR) lpdlciStruct);
  1279. DLCI_List.remove ((DWORD_PTR) dlci);
  1280. /*
  1281. ** Issue another ConnectRequest to the Network Layer.
  1282. */
  1283. m_pSCF->ConnectRequest(new_dlci, lpdlciStruct->priority);
  1284. }
  1285. else
  1286. {
  1287. /*
  1288. ** If a transport was found in our list and we don't want
  1289. ** to retry the connection, delete the Transport and
  1290. ** DataLink and remove them from our lists
  1291. */
  1292. if (transport_found)
  1293. {
  1294. if (lpdlciStruct != NULL)
  1295. {
  1296. delete lpdlciStruct -> x224;
  1297. lpdlciStruct->x224 = NULL;
  1298. delete lpdlciStruct->q922;
  1299. lpdlciStruct->q922 = NULL;
  1300. delete lpdlciStruct->data_request_memory_manager;
  1301. lpdlciStruct->data_request_memory_manager = NULL;
  1302. /*
  1303. ** Remove the logical connection from the lists
  1304. */
  1305. Logical_Connection_Priority_List[lpdlciStruct->priority]->remove (dlci);
  1306. DataLink_List.remove (dlci);
  1307. delete lpdlciStruct;
  1308. }
  1309. Logical_Connection_List.remove (logical_handle);
  1310. DLCI_List.remove ((DWORD) dlci);
  1311. /*
  1312. ** Notify the owner object that the logical
  1313. ** connection is no longer valid.
  1314. */
  1315. m_pController->OwnerCallback(
  1316. m_nMsgBase + TPRT_DISCONNECT_INDICATION,
  1317. (void *) logical_handle,
  1318. m_hCommLink);
  1319. }
  1320. /*
  1321. ** This check determines if we will automatically tear down the
  1322. ** T.120 stack if the logical connection count reaches zero.
  1323. */
  1324. if (m_pComPort->PerformAutomaticDisconnect())
  1325. {
  1326. TRACE_OUT(("T123: NetworkDisconnectIndication: Perform Auto Disconnect"));
  1327. /*
  1328. ** If there aren't any more Logical Connections and I
  1329. ** was the link originator, initiate a Release Request to
  1330. ** the DataLink of DLCI 0
  1331. */
  1332. if (Logical_Connection_List.isEmpty() && Link_Originator)
  1333. {
  1334. delete m_pSCF;
  1335. m_pSCF = NULL;
  1336. if (m_pQ922 != NULL)
  1337. {
  1338. m_pQ922->ReleaseRequest();
  1339. }
  1340. else
  1341. {
  1342. m_pController->OwnerCallback(
  1343. m_nMsgBase + TPRT_DISCONNECT_INDICATION,
  1344. INVALID_LOGICAL_HANDLE,
  1345. m_hCommLink,
  1346. &Disconnect_Requested);
  1347. }
  1348. }
  1349. }
  1350. }
  1351. }
  1352. /*
  1353. * void T123::DataLinkRelease (
  1354. * DLCI dlci,
  1355. * DisconnectType error)
  1356. *
  1357. * Functional Description
  1358. * This function is called when we receive a DATALINK_RELEASE message
  1359. * message from the DataLink Layer. As a result we may disconnect a
  1360. * logical connection or (if it is DLCI 0) the whole stack.
  1361. *
  1362. * Formal Parameters
  1363. * dlci (i) - Connection identifier
  1364. * error (i) - error type
  1365. *
  1366. * Return Value
  1367. * Valid DLCI
  1368. *
  1369. * Side Effects
  1370. * None
  1371. *
  1372. * Caveats
  1373. * None
  1374. */
  1375. void T123::DataLinkRelease (
  1376. DLCI dlci,
  1377. DataLinkDisconnectType disconnect_type)
  1378. {
  1379. TRACE_OUT(("T123::DataLinkRelease"));
  1380. BOOL transport_found;
  1381. LogicalHandle logical_handle;
  1382. USHORT message;
  1383. TRACE_OUT(("T123: DataLinkRelease: DLCI = %d", dlci));
  1384. /*
  1385. ** If DLCI 0 is terminating, all Transports and DataLinks must
  1386. ** be terminated
  1387. */
  1388. if (dlci == 0)
  1389. {
  1390. /*
  1391. ** If the DataLink broke the connection because of a
  1392. ** Fatal Error, issue an immediate TPRT_DISCONNECT_INDICATION
  1393. ** to the owner object. This may cause the owner object
  1394. ** to delete us immediately. If the error is not Fatal
  1395. ** disconnect the Multiplexer so that it can send out
  1396. ** its remaining data
  1397. */
  1398. if (disconnect_type != DATALINK_NORMAL_DISCONNECT)
  1399. {
  1400. /*
  1401. ** This function deletes all of the DataLinks,
  1402. ** Network Layers, and Transports.
  1403. */
  1404. Reset ();
  1405. /*
  1406. ** Notify the owner that DLCI 0 is terminating
  1407. */
  1408. m_pController->OwnerCallback(
  1409. m_nMsgBase + TPRT_DISCONNECT_INDICATION,
  1410. INVALID_LOGICAL_HANDLE,
  1411. m_hCommLink,
  1412. &Disconnect_Requested);
  1413. }
  1414. else
  1415. {
  1416. /*
  1417. ** If the error is not Fatal, let the Multiplexer
  1418. ** complete its transmission.
  1419. */
  1420. m_pMultiplexer->DisconnectRequest();
  1421. }
  1422. }
  1423. else
  1424. {
  1425. DWORD_PTR dwTemp_dlci;
  1426. /*
  1427. ** The DataLink associated with a Transport is terminating
  1428. */
  1429. if (DLCI_List.find ((DWORD) dlci) == FALSE)
  1430. return;
  1431. transport_found = FALSE;
  1432. /*
  1433. ** Find the logical connection associated with this DLCI
  1434. */
  1435. Logical_Connection_List.reset();
  1436. while (Logical_Connection_List.iterate(&dwTemp_dlci, (PDWORD_PTR) &logical_handle) == TRUE)
  1437. {
  1438. if (dlci == (DLCI) dwTemp_dlci)
  1439. {
  1440. transport_found = TRUE;
  1441. break;
  1442. }
  1443. }
  1444. if (transport_found)
  1445. DisconnectRequest (logical_handle, TRUE);
  1446. }
  1447. }
  1448. /*
  1449. * void T123::NewConnection (void)
  1450. *
  1451. * Functional Description
  1452. * This function is called when we receive a NEW_CONNECTION message from
  1453. * the Multiplexer Layer. It instantiates a DataLink Layer to serve
  1454. * the SCF.
  1455. *
  1456. * Formal Parameters
  1457. * None
  1458. *
  1459. * Return Value
  1460. * Valid DLCI
  1461. *
  1462. * Side Effects
  1463. * None
  1464. *
  1465. * Caveats
  1466. * None
  1467. */
  1468. void T123::NewConnection (void)
  1469. {
  1470. TRACE_OUT(("T123::NewConnection"));
  1471. USHORT max_outstanding_bytes;
  1472. BOOL initialized;
  1473. MemoryTemplate memory_template[2];
  1474. MemoryManagerError memory_manager_error;
  1475. memory_template[0].block_size = 128;
  1476. memory_template[0].block_count = 4;
  1477. DBG_SAVE_FILE_LINE
  1478. Data_Request_Memory_Manager = new MemoryManager (
  1479. memory_template,
  1480. 1,
  1481. &memory_manager_error,
  1482. 9,
  1483. TRUE);
  1484. if ((Data_Request_Memory_Manager != NULL) &&
  1485. (memory_manager_error != MEMORY_MANAGER_NO_ERROR))
  1486. {
  1487. delete Data_Request_Memory_Manager;
  1488. Data_Request_Memory_Manager = NULL;
  1489. }
  1490. if (Data_Request_Memory_Manager != NULL)
  1491. {
  1492. max_outstanding_bytes = PSTN_DATALINK_MAX_OUTSTANDING_BYTES;
  1493. DBG_SAVE_FILE_LINE
  1494. m_pQ922 = new CLayerQ922(this,
  1495. m_pMultiplexer,
  1496. DATALINK_LAYER_MESSAGE_BASE,
  1497. 0,
  1498. Link_Originator,
  1499. 4,
  1500. 4,
  1501. DataLink_Struct.default_k_factor,
  1502. DataLink_Struct.default_n201,
  1503. DataLink_Struct.default_t200,
  1504. max_outstanding_bytes,
  1505. Data_Request_Memory_Manager,
  1506. m_pComPort->GetCallControlType(),
  1507. m_fValidSDKParams ? &m_SDKParams : NULL,
  1508. &initialized);
  1509. if (m_pQ922 == NULL)
  1510. {
  1511. m_pController->OwnerCallback(
  1512. m_nMsgBase + TPRT_DISCONNECT_INDICATION,
  1513. INVALID_LOGICAL_HANDLE,
  1514. m_hCommLink,
  1515. &Disconnect_Requested);
  1516. }
  1517. else if (initialized == FALSE)
  1518. {
  1519. delete m_pQ922;
  1520. m_pQ922 = NULL;
  1521. m_pController->OwnerCallback(
  1522. m_nMsgBase + TPRT_DISCONNECT_INDICATION,
  1523. INVALID_LOGICAL_HANDLE,
  1524. m_hCommLink,
  1525. &Disconnect_Requested);
  1526. }
  1527. }
  1528. else
  1529. {
  1530. TRACE_OUT(("T123: Allocation of memory manager failed"));
  1531. m_pController->OwnerCallback(
  1532. m_nMsgBase + TPRT_DISCONNECT_INDICATION,
  1533. INVALID_LOGICAL_HANDLE,
  1534. m_hCommLink,
  1535. &Disconnect_Requested);
  1536. }
  1537. }
  1538. /*
  1539. * void T123::NetworkConnectIndication (
  1540. * PNetworkConnectStruct connect_struct)
  1541. *
  1542. * Functional Description
  1543. * This function is called when we receive a NETWORK_CONNECT_INDICATION
  1544. * message from the SCF Layer. It instantiates a DataLink Layer to serve
  1545. * the new TC.
  1546. *
  1547. * Formal Parameters
  1548. * None
  1549. *
  1550. * Return Value
  1551. * Valid DLCI
  1552. *
  1553. * Side Effects
  1554. * None
  1555. *
  1556. * Caveats
  1557. * None
  1558. */
  1559. void T123::NetworkConnectIndication (
  1560. PNetworkConnectStruct connect_struct)
  1561. {
  1562. TRACE_OUT(("T123::NetworkConnectIndication"));
  1563. USHORT blocks;
  1564. CLayerQ922 *q922;
  1565. BOOL initialized;
  1566. PMemoryManager data_request_memory_manager;
  1567. BOOL valid_dlci;
  1568. PDLCIStruct dlci_struct;
  1569. USHORT max_outstanding_bytes;
  1570. MemoryTemplate memory_template[2];
  1571. MemoryManagerError memory_manager_error;
  1572. ULONG max_transport_tpdu_size;
  1573. /*
  1574. ** See if the DLCI is already being used elsewhere. If it is,
  1575. ** set valid_dlci to FALSE and call ConnectResponse(). If it is
  1576. ** not, put the DLCI in out DLCI_List
  1577. */
  1578. if (DLCI_List.find ((DWORD) (connect_struct->dlci)))
  1579. valid_dlci = FALSE;
  1580. else
  1581. {
  1582. DBG_SAVE_FILE_LINE
  1583. dlci_struct = new DLCIStruct;
  1584. if (dlci_struct != NULL)
  1585. {
  1586. DLCI_List.insert ((DWORD_PTR) (connect_struct->dlci), (DWORD_PTR) dlci_struct);
  1587. dlci_struct -> link_originator = FALSE;
  1588. dlci_struct -> x224 = NULL; // X.224
  1589. dlci_struct -> q922 = NULL; // Q.922
  1590. dlci_struct -> disconnect_requested = FALSE;
  1591. dlci_struct -> data_request_memory_manager = NULL;
  1592. dlci_struct -> network_retries = 0;
  1593. dlci_struct -> priority = connect_struct->priority;
  1594. /*
  1595. ** Connect_Requested does not mean tha we issued a
  1596. ** ConnectRequest() to the Network Layer. It means that the
  1597. ** Network Layer is aware of the connection.
  1598. */
  1599. dlci_struct -> connect_requested = TRUE;
  1600. valid_dlci = TRUE;
  1601. }
  1602. else
  1603. {
  1604. valid_dlci = FALSE;
  1605. }
  1606. }
  1607. if (valid_dlci)
  1608. {
  1609. /*
  1610. ** Create a DataLink that will service this Transport Layer
  1611. */
  1612. max_transport_tpdu_size = CLayerX224::GetMaxTPDUSize (
  1613. (ULONG) (connect_struct->datalink_struct) -> n201);
  1614. blocks = (USHORT) (MAXIMUM_USER_DATA_SIZE /
  1615. (max_transport_tpdu_size - DATA_PACKET_HEADER_SIZE)) + 1;
  1616. /*
  1617. ** Allow for one extra block so that a HIGH_PRIORITY memory
  1618. ** allocation can get as many blocks as it needs to hold the
  1619. ** MAXIMUM_USER_DATA_SIZE packet.
  1620. */
  1621. blocks++;
  1622. TRACE_OUT(("T123: NCIndication: max_tpdu = %d",max_transport_tpdu_size));
  1623. /*
  1624. ** Allow for X 8K blocks
  1625. */
  1626. blocks *= NUMBER_8K_BLOCKS;
  1627. /*
  1628. ** The '2' in the following statement is for the CRC added by the
  1629. ** multiplexer.
  1630. */
  1631. memory_template[0].block_size = max_transport_tpdu_size +
  1632. DATALINK_PACKET_OVERHEAD +
  1633. 2;
  1634. memory_template[0].block_count = blocks;
  1635. memory_template[1].block_size = 64;
  1636. memory_template[1].block_count = NUMBER_64_BYTE_BLOCKS;
  1637. DBG_SAVE_FILE_LINE
  1638. data_request_memory_manager = new MemoryManager (
  1639. memory_template,
  1640. 2,
  1641. &memory_manager_error,
  1642. 33,
  1643. TRUE);
  1644. if ((data_request_memory_manager != NULL) &&
  1645. (memory_manager_error != MEMORY_MANAGER_NO_ERROR))
  1646. {
  1647. delete data_request_memory_manager;
  1648. data_request_memory_manager = NULL;
  1649. }
  1650. if (data_request_memory_manager != NULL)
  1651. {
  1652. dlci_struct->priority = connect_struct -> priority;
  1653. dlci_struct->data_request_memory_manager = data_request_memory_manager;
  1654. max_outstanding_bytes = PSTN_DATALINK_MAX_OUTSTANDING_BYTES;
  1655. DBG_SAVE_FILE_LINE
  1656. q922 = new CLayerQ922(this,
  1657. m_pMultiplexer,
  1658. DATALINK_LAYER_MESSAGE_BASE,
  1659. connect_struct->dlci,
  1660. dlci_struct->link_originator,
  1661. 1,
  1662. 4,
  1663. (connect_struct->datalink_struct)->k_factor,
  1664. (connect_struct->datalink_struct)->n201,
  1665. (connect_struct->datalink_struct)->t200,
  1666. max_outstanding_bytes,
  1667. data_request_memory_manager,
  1668. m_pComPort->GetCallControlType(),
  1669. m_fValidSDKParams ? &m_SDKParams : NULL,
  1670. &initialized);
  1671. if (q922 != NULL)
  1672. {
  1673. if (initialized)
  1674. {
  1675. /*
  1676. ** Add it to the DataLink list
  1677. */
  1678. dlci_struct->q922 = q922;
  1679. DataLink_List.append (connect_struct->dlci);
  1680. }
  1681. else
  1682. {
  1683. delete q922;
  1684. delete data_request_memory_manager;
  1685. valid_dlci = FALSE;
  1686. }
  1687. }
  1688. else
  1689. {
  1690. delete data_request_memory_manager;
  1691. valid_dlci = FALSE;
  1692. }
  1693. }
  1694. else
  1695. {
  1696. ERROR_OUT(("t123: Unable to allocate memory manager"));
  1697. valid_dlci = FALSE;
  1698. }
  1699. // Clean up on error
  1700. if (FALSE == valid_dlci)
  1701. {
  1702. DLCI_List.remove((DWORD) connect_struct->dlci);
  1703. delete dlci_struct;
  1704. }
  1705. }
  1706. /*
  1707. ** Contact the Network Layer with a response
  1708. */
  1709. m_pSCF->ConnectResponse(
  1710. connect_struct -> call_reference,
  1711. connect_struct -> dlci,
  1712. valid_dlci);
  1713. }
  1714. /*
  1715. * void T123::NetworkConnectConfirm (
  1716. * PNetworkConnectStruct connect_struct)
  1717. *
  1718. * Functional Description
  1719. * This function is called when we receive a NETWORK_CONFIRM message
  1720. * from the SCF Layer. It instantiates a DataLink Layer to serve the
  1721. * new logical connection.
  1722. *
  1723. * Formal Parameters
  1724. * connect_struct (i) - Address of connect struct. It holds the DLCI
  1725. * and priority.
  1726. *
  1727. * Return Value
  1728. * None.
  1729. *
  1730. * Side Effects
  1731. * None
  1732. *
  1733. * Caveats
  1734. * None
  1735. */
  1736. void T123::NetworkConnectConfirm (
  1737. PNetworkConnectStruct connect_struct)
  1738. {
  1739. TRACE_OUT(("T123::NetworkConnectConfirm"));
  1740. DLCI dlci;
  1741. USHORT blocks;
  1742. CLayerQ922 *q922;
  1743. BOOL initialized;
  1744. PMemoryManager data_request_memory_manager;
  1745. MemoryTemplate memory_template[2];
  1746. MemoryManagerError memory_manager_error;
  1747. USHORT max_outstanding_bytes;
  1748. ULONG max_transport_tpdu_size;
  1749. PDLCIStruct dlci_struct;
  1750. max_transport_tpdu_size = CLayerX224::GetMaxTPDUSize (
  1751. (ULONG) (connect_struct->datalink_struct) -> n201);
  1752. blocks = (USHORT) (MAXIMUM_USER_DATA_SIZE /
  1753. (max_transport_tpdu_size - DATA_PACKET_HEADER_SIZE)) + 1;
  1754. TRACE_OUT(("T123: NCConfirm: max_tpdu = %d", max_transport_tpdu_size));
  1755. /*
  1756. ** Allow for one extra block so that a HIGH_PRIORITY memory
  1757. ** allocation can get as many blocks as it needs to hold the
  1758. ** MAXIMUM_USER_DATA_SIZE packet.
  1759. */
  1760. blocks++;
  1761. /*
  1762. ** Allow for X 8K blocks
  1763. */
  1764. blocks *= NUMBER_8K_BLOCKS;
  1765. /*
  1766. ** Figure out the maximum packet size; The '2' is for the CRC appended
  1767. ** to the end of a packet.
  1768. */
  1769. memory_template[0].block_size = max_transport_tpdu_size +
  1770. DATALINK_PACKET_OVERHEAD +
  1771. 2;
  1772. memory_template[0].block_count = blocks;
  1773. memory_template[1].block_size = 64;
  1774. memory_template[1].block_count = NUMBER_64_BYTE_BLOCKS;
  1775. DBG_SAVE_FILE_LINE
  1776. data_request_memory_manager = new MemoryManager (
  1777. memory_template,
  1778. 2,
  1779. &memory_manager_error,
  1780. 33,
  1781. TRUE);
  1782. if ((data_request_memory_manager != NULL) &&
  1783. (memory_manager_error != MEMORY_MANAGER_NO_ERROR))
  1784. {
  1785. delete data_request_memory_manager;
  1786. data_request_memory_manager = NULL;
  1787. }
  1788. if (data_request_memory_manager != NULL)
  1789. {
  1790. dlci = connect_struct -> dlci;
  1791. DLCI_List.find ((DWORD_PTR) dlci, (PDWORD_PTR) &dlci_struct);
  1792. dlci_struct->data_request_memory_manager = data_request_memory_manager;
  1793. /*
  1794. ** The DLCI is already entered in our DLCI list, set the priority
  1795. ** and create a DataLink for it.
  1796. */
  1797. dlci_struct->q922 = NULL;
  1798. dlci_struct->priority = connect_struct->priority;
  1799. max_outstanding_bytes = PSTN_DATALINK_MAX_OUTSTANDING_BYTES;
  1800. DBG_SAVE_FILE_LINE
  1801. q922 = new CLayerQ922(this,
  1802. m_pMultiplexer,
  1803. DATALINK_LAYER_MESSAGE_BASE,
  1804. dlci,
  1805. dlci_struct->link_originator,
  1806. 1,
  1807. 4,
  1808. (connect_struct->datalink_struct)->k_factor,
  1809. (connect_struct->datalink_struct)->n201,
  1810. (connect_struct->datalink_struct)->t200,
  1811. max_outstanding_bytes,
  1812. data_request_memory_manager,
  1813. m_pComPort->GetCallControlType(),
  1814. m_fValidSDKParams ? &m_SDKParams : NULL,
  1815. &initialized);
  1816. if (q922 != NULL)
  1817. {
  1818. if (initialized)
  1819. {
  1820. dlci_struct->q922 = q922;
  1821. DataLink_List.append (dlci);
  1822. }
  1823. else
  1824. {
  1825. delete q922;
  1826. delete data_request_memory_manager;
  1827. m_pSCF->DisconnectRequest(dlci);
  1828. }
  1829. }
  1830. else
  1831. {
  1832. delete data_request_memory_manager;
  1833. m_pSCF->DisconnectRequest(dlci);
  1834. }
  1835. }
  1836. }
  1837. /*
  1838. * void T123::DataLinkEstablish (
  1839. * DLCI dlci)
  1840. *
  1841. * Functional Description
  1842. * This function is called when we receive a DATALINK_ESTABLISH message
  1843. * from a DataLink Layer. Depending on which DataLink is successfully up,
  1844. * it creates the layer on top of it.
  1845. *
  1846. * Formal Parameters
  1847. * dlci (i) - DLCI value
  1848. *
  1849. * Return Value
  1850. * None
  1851. *
  1852. * Side Effects
  1853. * None
  1854. *
  1855. * Caveats
  1856. * None
  1857. */
  1858. void T123::DataLinkEstablish (DLCI dlci)
  1859. {
  1860. TRACE_OUT(("T123::DataLinkEstablish, dlci=%d", dlci));
  1861. BOOL initialized;
  1862. BOOL transport_found;
  1863. PDLCIStruct dlci_struct;
  1864. LogicalHandle logical_handle;
  1865. TransportPriority priority;
  1866. DWORD_PTR dwTemp_dlci;
  1867. if (dlci == 0)
  1868. {
  1869. DBG_SAVE_FILE_LINE
  1870. m_pSCF = new CLayerSCF(this,
  1871. m_pQ922,
  1872. NETWORK_LAYER_MESSAGE_BASE,
  1873. 0,
  1874. Link_Originator,
  1875. &DataLink_Struct,
  1876. Data_Request_Memory_Manager,
  1877. &initialized);
  1878. if (m_pSCF == NULL)
  1879. {
  1880. m_pQ922->ReleaseRequest();
  1881. return;
  1882. }
  1883. else if (initialized == FALSE)
  1884. {
  1885. delete m_pSCF;
  1886. m_pQ922->ReleaseRequest();
  1887. return;
  1888. }
  1889. /*
  1890. ** Go thru the Transport list and attempt connections
  1891. ** for all Transport requests that we have received
  1892. */
  1893. DLCI_List.reset();
  1894. while (DLCI_List.iterate ((PDWORD_PTR) &dlci_struct, &dwTemp_dlci))
  1895. {
  1896. dlci = (DLCI) dwTemp_dlci;
  1897. /*
  1898. ** The Link_Originator is set to TRUE if the
  1899. ** ConnectRequest() function was called. We have to check
  1900. ** the Connect_Requested variable to see if we have
  1901. ** already made the request to the Network Layer.
  1902. */
  1903. if (dlci_struct->link_originator
  1904. && (dlci_struct->connect_requested == FALSE))
  1905. {
  1906. dlci_struct -> connect_requested = TRUE;
  1907. m_pSCF->ConnectRequest(dlci, dlci_struct -> priority);
  1908. }
  1909. }
  1910. }
  1911. else
  1912. {
  1913. /*
  1914. ** If DLCI != 0, this is a DataLink for a Transport Layer
  1915. */
  1916. transport_found = FALSE;
  1917. /*
  1918. ** Go thru each of the Transports to find the one associated
  1919. ** with the DLCI.
  1920. */
  1921. Logical_Connection_List.reset();
  1922. while (Logical_Connection_List.iterate((PDWORD_PTR) &dwTemp_dlci, (PDWORD_PTR) &logical_handle))
  1923. {
  1924. if (dlci == (DLCI) dwTemp_dlci)
  1925. {
  1926. transport_found = TRUE;
  1927. break;
  1928. }
  1929. }
  1930. /*
  1931. ** If we go thru the list and don't find the logical
  1932. ** connection we have to request a new logical connection
  1933. ** handle from the controller.
  1934. */
  1935. if (transport_found == FALSE)
  1936. {
  1937. logical_handle = (LogicalHandle) m_pController->OwnerCallback(
  1938. m_nMsgBase + REQUEST_TRANSPORT_CONNECTION,
  1939. m_hCommLink,
  1940. 0,
  1941. NULL);
  1942. if (logical_handle != INVALID_LOGICAL_HANDLE)
  1943. {
  1944. /*
  1945. ** Set the Logical_Connection_List appropriately
  1946. */
  1947. Logical_Connection_List.insert (logical_handle, (DWORD) dlci);
  1948. }
  1949. else
  1950. {
  1951. m_pSCF->DisconnectRequest(dlci);
  1952. return;
  1953. }
  1954. }
  1955. /*
  1956. ** Create a Transport Layer to go with the DataLink layer.
  1957. */
  1958. DLCI_List.find ((DWORD_PTR) dlci, (PDWORD_PTR) &dlci_struct);
  1959. DBG_SAVE_FILE_LINE
  1960. dlci_struct->x224 = new CLayerX224 (
  1961. this,
  1962. dlci_struct->q922,
  1963. TRANSPORT_LAYER_MESSAGE_BASE,
  1964. logical_handle,
  1965. 0,
  1966. 1,
  1967. TRANSPORT_DEFAULT_PDU_SIZE,
  1968. dlci_struct -> data_request_memory_manager,
  1969. &initialized);
  1970. if (dlci_struct->x224 != NULL)
  1971. {
  1972. if (initialized)
  1973. {
  1974. /*
  1975. ** Put the dlci in the Priority list
  1976. */
  1977. priority = dlci_struct->priority;
  1978. Logical_Connection_Priority_List[priority]->append ((DWORD) dlci);
  1979. /*
  1980. ** If transport_found == TRUE, we must have initiated
  1981. ** the request for this logical connection, so issue
  1982. ** the ConnectRequest() to the Transport Layer.
  1983. */
  1984. if (transport_found)
  1985. {
  1986. dlci_struct->x224->ConnectRequest ();
  1987. }
  1988. }
  1989. else
  1990. {
  1991. m_pSCF->DisconnectRequest (dlci);
  1992. }
  1993. }
  1994. else
  1995. {
  1996. m_pSCF->DisconnectRequest (dlci);
  1997. }
  1998. }
  1999. }