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.

1448 lines
47 KiB

  1. #include "precomp.h"
  2. DEBUG_FILEZONE(ZONE_T120_T123PSTN);
  3. /* TransportController.cpp
  4. *
  5. * Copyright (c) 1993-1995 by DataBeam Corporation, Lexington, KY
  6. *
  7. * Abstract:
  8. * This is the implementation file for the TransportController class
  9. *
  10. * Private Instance Variables:
  11. * Logical_Connection_List - This list uses the LogicalHandle
  12. * as a key and a pointer to a
  13. * TransportConnectionStruct as the value. This
  14. * structure holds all of the pertinent information
  15. * about the connection.
  16. * Protocol_Stacks - This list uses the physical handle as a key and
  17. * a pointer to a pointer to a object as the value.
  18. * Sometimes we need to find the T123 object
  19. * associated with a physical handle
  20. * Message_List - Owner callback calls are placed in this list if
  21. * we can not process them immediately.
  22. * Controller - Address of the PSTNController
  23. * Emergency_Shutdown - Set to TRUE if we have encountered a situation
  24. * where the integrity of the Transport has been
  25. * compromised. As a result, all connections will
  26. * be purged.
  27. * Poll_Active - Set to TRUE while we are in a PollReceiver() or
  28. * PollTransmitter() call. This solves our re-
  29. * entrancy problems.
  30. *
  31. * Caveats:
  32. * None
  33. *
  34. * Author:
  35. * James W. Lawwill
  36. */
  37. #include "tprtcore.h"
  38. /*
  39. * TransportController::TransportController (
  40. * PTransportResources transport_resources)
  41. *
  42. * Public
  43. *
  44. * Functional Description:
  45. * TransportController constructor. We instantiate the PSTNController
  46. * and initialize the T123 class.
  47. */
  48. TransportController::TransportController(void)
  49. :
  50. Protocol_Stacks (TRANSPORT_HASHING_BUCKETS),
  51. Logical_Connection_List (TRANSPORT_HASHING_BUCKETS)
  52. {
  53. TRACE_OUT(("TransportController::TransportController"));
  54. Emergency_Shutdown = FALSE;
  55. Poll_Active = FALSE;
  56. }
  57. /*
  58. * TransportController::~TransportController (void)
  59. *
  60. * Public
  61. *
  62. * Functional Description:
  63. * This is the TransportController destructor. All allocated memory is
  64. * released and all lists are cleared
  65. */
  66. TransportController::~TransportController (void)
  67. {
  68. TRACE_OUT(("TransportController::~TransportController"));
  69. Reset (FALSE);
  70. }
  71. TransportError TransportController::CreateTransportStack
  72. (
  73. BOOL fCaller,
  74. HANDLE hCommLink,
  75. HANDLE hevtClose,
  76. PLUGXPRT_PARAMETERS *pParams
  77. )
  78. {
  79. TRACE_OUT(("TransportController::CreateTransportStack"));
  80. DBG_SAVE_FILE_LINE
  81. ComPort *comport = new ComPort(this, PHYSICAL_LAYER_MESSAGE_BASE,
  82. pParams,
  83. hCommLink,
  84. hevtClose);
  85. if (NULL != comport)
  86. {
  87. TransportError rc = CreateT123Stack(hCommLink, fCaller, comport, pParams);
  88. if (TRANSPORT_NO_ERROR == rc)
  89. {
  90. ComPortError cperr = comport->Open();
  91. if (COMPORT_NO_ERROR == cperr)
  92. {
  93. return TRANSPORT_NO_ERROR;
  94. }
  95. }
  96. ERROR_OUT(("TransportController::CreateTransportStack: cannot open comm port"));
  97. return TRANSPORT_INITIALIZATION_FAILED;
  98. }
  99. ERROR_OUT(("TransportController::CreateTransportStack: cannot allocate ComPort"));
  100. return TRANSPORT_MEMORY_FAILURE;
  101. }
  102. TransportError TransportController::CloseTransportStack
  103. (
  104. HANDLE hCommLink
  105. )
  106. {
  107. TRACE_OUT(("TransportController::CloseTransportStack"));
  108. /*
  109. ** If for some reason we get an error on the ConnectRequest(),
  110. ** take the physical connection down.
  111. */
  112. T123 *t123 = NULL;
  113. if (Protocol_Stacks.find((DWORD_PTR) hCommLink, (PDWORD_PTR) &t123))
  114. {
  115. RemoveLogicalConnections (hCommLink);
  116. /*
  117. ** Remove the T123 object from the lists and
  118. ** delete the object
  119. */
  120. Transmitter_List.remove((DWORD_PTR) t123);
  121. Protocol_Stacks.remove((DWORD_PTR) hCommLink);
  122. delete t123;
  123. }
  124. // find the physical layer through the physical handle
  125. ComPort *comport;
  126. if (! g_pComPortList2->find((DWORD_PTR) hCommLink, (PDWORD_PTR) &comport))
  127. {
  128. WARNING_OUT(("TransportController::CloseTransportStack: cannot find comport for hCommLink=%d", hCommLink));
  129. return TRANSPORT_PHYSICAL_LAYER_NOT_FOUND;
  130. }
  131. ASSERT(NULL != comport);
  132. // close and delete the device
  133. // g_pComPortList2->remove((DWORD) hCommLink); // removed in handling "delete event"
  134. comport->Release();
  135. return TRANSPORT_NO_ERROR;
  136. }
  137. /*
  138. * TransportError TransportController::ConnectRequest (
  139. * TransportAddress transport_address,
  140. * TransportPriority transport_priority,
  141. * LogicalHandle * logical_handle)
  142. *
  143. * Public
  144. *
  145. * Functional Description:
  146. * This function initiates a connection. It passes the transport address
  147. * to the PSTN Controller. It will either deny the request or accept the
  148. * request and call us back when the physical connection is established.
  149. *
  150. * We return the transport connection handle in the logical_handle
  151. * address. Although we return this transport number to the user, it
  152. * is not ready for data transfer until the user receives the
  153. * TRANSPORT_CONNECT_INDICATION message via the callback. At that point,
  154. * the logical connection is up and running.
  155. */
  156. TransportError TransportController::ConnectRequest
  157. (
  158. LogicalHandle *logical_handle,
  159. HANDLE hCommLink, // physical handle
  160. TransportPriority transport_priority
  161. )
  162. {
  163. TRACE_OUT(("TransportController::CreateConnection"));
  164. *logical_handle = GetNextLogicalHandle();
  165. if (INVALID_LOGICAL_HANDLE == *logical_handle)
  166. {
  167. ERROR_OUT(("TransportController::ConnectRequest: cannot allocate logical handle"));
  168. return TRANSPORT_MEMORY_FAILURE;
  169. }
  170. // find the physical layer through the physical handle
  171. ComPort *comport;
  172. if (! g_pComPortList2->find((DWORD_PTR) hCommLink, (PDWORD_PTR) &comport))
  173. {
  174. ERROR_OUT(("TransportController::ConnectRequest: cannot find comport for hCommLink=%d", hCommLink));
  175. return TRANSPORT_PHYSICAL_LAYER_NOT_FOUND;
  176. }
  177. ASSERT(NULL != comport);
  178. /*
  179. ** Register the connection handle in out Logical_Connection_List. After the
  180. ** physical connection is established, we will create a T123 object
  181. ** and request a logical connection to the remote site.
  182. **
  183. ** This structure contains the information necessary to maintain the
  184. ** logical connection.
  185. **
  186. ** The t123_connection_requested is set to TRUE when we have issued
  187. ** a ConnectRequest() to the T123 object for this logical connection.
  188. */
  189. DBG_SAVE_FILE_LINE
  190. PLogicalConnectionStruct pConn = new LogicalConnectionStruct;
  191. if (pConn == NULL)
  192. {
  193. ERROR_OUT(("TransportController::ConnectRequest: cannot to allocate LogicalConnectionStruct"));
  194. return (TRANSPORT_MEMORY_FAILURE);
  195. }
  196. pConn->fCaller = TRUE;
  197. pConn->comport = comport;
  198. pConn->t123 = NULL;
  199. pConn->t123_connection_requested = FALSE;
  200. pConn->t123_disconnect_requested = FALSE;
  201. pConn->priority = transport_priority;
  202. pConn->hCommLink = hCommLink;
  203. Logical_Connection_List.insert((DWORD_PTR) *logical_handle, (DWORD_PTR) pConn);
  204. return NewConnection(hCommLink, TRUE, comport);
  205. }
  206. /*
  207. * TransportError TransportController::ConnectResponse (
  208. * LogicalHandle logical_handle)
  209. *
  210. * Public
  211. *
  212. * Functional Description:
  213. * This function is called by the user in response to a
  214. * TRANSPORT_CONNECT_INDICATION callback from us. By making this call the
  215. * user is accepting the call. If the user does not want to accept the
  216. * he should call DisconnectRequest ();
  217. */
  218. TransportError TransportController::ConnectResponse
  219. (
  220. LogicalHandle logical_handle
  221. )
  222. {
  223. TRACE_OUT(("TransportController::ConnectResponse"));
  224. PLogicalConnectionStruct pConn;
  225. PT123 t123;
  226. /*
  227. ** If this is an invalid handle, return error
  228. */
  229. if (! Logical_Connection_List.find (logical_handle, (PDWORD_PTR) &pConn))
  230. return (TRANSPORT_NO_SUCH_CONNECTION);
  231. t123 = pConn -> t123;
  232. /*
  233. ** If the user calls this function before the T123 object is created, that
  234. ** is an error
  235. */
  236. return (t123 != NULL) ? t123->ConnectResponse(logical_handle) : TRANSPORT_NO_SUCH_CONNECTION;
  237. }
  238. /*
  239. * TransportError TransportController::DisconnectRequest (
  240. * LogicalHandle logical_handle,
  241. * BOOL trash_packets)
  242. *
  243. * Public
  244. *
  245. * Functional Description:
  246. * This function issues a Disconnect request to the T123 object (if it
  247. * exists). If T123 does not exist, it hangs up the physical connection.
  248. */
  249. TransportError TransportController::DisconnectRequest
  250. (
  251. LogicalHandle logical_handle,
  252. UINT_PTR trash_packets
  253. )
  254. {
  255. TRACE_OUT(("TransportController::DisconnectRequest"));
  256. PhysicalHandle physical_handle;
  257. PLogicalConnectionStruct pConn;
  258. BOOL transport_found;
  259. PT123 t123;
  260. PMessageStruct passive_message;
  261. TransportError rc = TRANSPORT_NO_ERROR;
  262. /*
  263. ** If the logical connection handle is not registered, return error
  264. */
  265. if (Logical_Connection_List.find (logical_handle, (PDWORD_PTR) &pConn) == FALSE)
  266. return (TRANSPORT_NO_SUCH_CONNECTION);
  267. TRACE_OUT(("TPRTCTRL: DisconnectRequest for logical handle %d", logical_handle));
  268. /*
  269. ** Calling this function during a callback from this transport
  270. ** is a re-entrancy problem. In this case, we add a message to
  271. ** our Message_List and process the request later.
  272. */
  273. if (! Poll_Active)
  274. {
  275. /*
  276. ** We set the t123_disconnect_requested to TRUE at this point so
  277. ** that when we get the TPRT_DISCONNECT_INDICATION message back
  278. ** from the t123 object, we will know who originated the
  279. ** operation. If we originated the operation locally, we do not
  280. ** issue a TRANSPORT_DISCONNECT_INDICATION to the user.
  281. */
  282. pConn -> t123_disconnect_requested = TRUE;
  283. /*
  284. ** If a T123 object is associated with this object, issue a disconnect
  285. */
  286. t123 = pConn -> t123;
  287. if (t123 != NULL)
  288. {
  289. t123 -> DisconnectRequest (logical_handle, trash_packets);
  290. }
  291. else
  292. {
  293. /*
  294. ** This occurs if the user wants to terminate the connection
  295. ** before it comes all the way up
  296. **
  297. ** Remove the transport connection handle from the
  298. ** Logical_Connection_List
  299. */
  300. Logical_Connection_List.remove (logical_handle);
  301. delete pConn;
  302. }
  303. }
  304. else
  305. {
  306. /*
  307. ** If we are in the middle of a PollReceiver() or PollTransmitter(),
  308. ** and this function is being called during a callback from this
  309. ** transport, save the message and process it later.
  310. */
  311. DBG_SAVE_FILE_LINE
  312. passive_message = new MessageStruct;
  313. if (passive_message != NULL)
  314. {
  315. passive_message -> message = TPRT_DISCONNECT_REQUEST;
  316. passive_message -> parameter1 = (void *) logical_handle;
  317. passive_message -> parameter2 = (void *) trash_packets;
  318. Message_List.append ((DWORD_PTR) passive_message);
  319. }
  320. else
  321. {
  322. ERROR_OUT(("TransportController::DisconnectRequest: cannot allocate MessageStruct"));
  323. rc = TRANSPORT_MEMORY_FAILURE;
  324. }
  325. }
  326. return rc;
  327. }
  328. /*
  329. * TransportError TransportController::EnableReceiver (void)
  330. *
  331. * Public
  332. *
  333. * Functional Description:
  334. * This function allows data packets to be sent to the user application.
  335. * Prior to this call, we must have sent a data packet to the user and
  336. * the user must not have been able to accept it. When this happens, the
  337. * user must issue this call to re-enable TRANSPORT_DATA_INDICATIONs.
  338. * callbacks.
  339. */
  340. void TransportController::EnableReceiver(void)
  341. {
  342. TRACE_OUT(("TransportController::EnableReceiver"));
  343. PT123 t123;
  344. PLogicalConnectionStruct pConn;
  345. /*
  346. ** Go through each of the Transports and enable the receivers
  347. */
  348. Logical_Connection_List.reset();
  349. while (Logical_Connection_List.iterate((PDWORD_PTR) &pConn))
  350. {
  351. t123 = pConn -> t123;
  352. /*
  353. ** If the protocol stack pointer is set to NULL, then we have not
  354. ** realized that the socket is up and functional.
  355. */
  356. if (t123 != NULL)
  357. {
  358. t123 -> EnableReceiver ();
  359. }
  360. }
  361. }
  362. /*
  363. * TransportError TransportController::DataRequest (
  364. * LogicalHandle logical_handle,
  365. * LPBYTE user_data,
  366. * ULONG user_data_length)
  367. *
  368. * Public
  369. *
  370. * Functional Description:
  371. * This function is used to send a data packet to the remote site.
  372. * This function passes the request to the T123 stack associated with
  373. * the transport connection handle
  374. */
  375. TransportError TransportController::DataRequest
  376. (
  377. LogicalHandle logical_handle,
  378. LPBYTE user_data,
  379. ULONG user_data_length
  380. )
  381. {
  382. TRACE_OUT(("TransportController::DataRequest"));
  383. PLogicalConnectionStruct pConn;
  384. PT123 t123;
  385. /*
  386. ** Verify that this connection exists and is ready for data
  387. */
  388. if (! Logical_Connection_List.find (logical_handle, (PDWORD_PTR) &pConn))
  389. {
  390. WARNING_OUT(("TPRTCTRL: DataRequest: Illegal logical_handle"));
  391. return (TRANSPORT_NO_SUCH_CONNECTION);
  392. }
  393. /*
  394. ** Attempt to send that data to the T123 Layer
  395. */
  396. t123 = pConn -> t123;
  397. return (t123 != NULL) ? t123->DataRequest(logical_handle, user_data, user_data_length) :
  398. TRANSPORT_NOT_READY_TO_TRANSMIT;
  399. }
  400. /*
  401. * TransportError TransportController::PurgeRequest (
  402. * LogicalHandle logical_handle)
  403. *
  404. * Public
  405. *
  406. * Functional Description:
  407. * This function is called to remove data from our output queues. The
  408. * user application usually calls this to speed up the disconnect process.
  409. */
  410. TransportError TransportController::PurgeRequest
  411. (
  412. LogicalHandle logical_handle
  413. )
  414. {
  415. TRACE_OUT(("TransportController::PurgeRequest"));
  416. PLogicalConnectionStruct pConn;
  417. PT123 t123;
  418. /*
  419. ** If the transport connection handle is not registered, return error
  420. */
  421. if (! Logical_Connection_List.find (logical_handle, (PDWORD_PTR) &pConn))
  422. return (TRANSPORT_NO_SUCH_CONNECTION);
  423. t123 = pConn -> t123;
  424. return (t123 != NULL) ? t123->PurgeRequest(logical_handle) : TRANSPORT_NO_ERROR;
  425. }
  426. /*
  427. * void TransportController::PollReceiver (void)
  428. *
  429. * Public
  430. *
  431. * Functional Description:
  432. * This function is called to give us a chance to process incoming data
  433. */
  434. void TransportController::PollReceiver(void)
  435. {
  436. // TRACE_OUT(("TransportController::PollReceiver"));
  437. PT123 t123;
  438. if (! Poll_Active)
  439. {
  440. ProcessMessages ();
  441. Poll_Active = TRUE;
  442. if (! Transmitter_List.isEmpty())
  443. {
  444. Transmitter_List.reset();
  445. while (Transmitter_List.iterate((PDWORD_PTR) &t123))
  446. {
  447. t123-> PollReceiver ();
  448. }
  449. /*
  450. ** The following code removes the first t123 object from the
  451. ** list and puts it at the end of the list. This attempts to
  452. ** give the t123 objects equal access to the user application.
  453. ** If we did not do this, one t123 object would always be able
  454. ** to send its data to the user application and other t123
  455. ** objects would be locked out.
  456. */
  457. Transmitter_List.append (Transmitter_List.get ());
  458. }
  459. Poll_Active = FALSE;
  460. }
  461. }
  462. /*
  463. * void TransportController::PollReceiver (
  464. * PhysicalHandle physical_handle)
  465. *
  466. * Public
  467. *
  468. * Functional Description:
  469. * This function gives the t123 object associated with this physical
  470. * handle a chance to process incoming data.
  471. */
  472. void TransportController::PollReceiver
  473. (
  474. PhysicalHandle physical_handle
  475. )
  476. {
  477. // TRACE_OUT(("TransportController::PollReceiver"));
  478. PT123 t123;
  479. if (! Poll_Active)
  480. {
  481. ProcessMessages ();
  482. Poll_Active = TRUE;
  483. /*
  484. ** See if there is a t123 object associated with this
  485. ** physical handle
  486. */
  487. if (Protocol_Stacks.find((DWORD_PTR) physical_handle, (PDWORD_PTR) &t123))
  488. {
  489. if (t123->PollReceiver() == PROTOCOL_LAYER_ERROR)
  490. {
  491. Transmitter_List.remove((DWORD_PTR) t123);
  492. Protocol_Stacks.remove((DWORD_PTR) physical_handle);
  493. delete t123;
  494. }
  495. }
  496. Poll_Active = FALSE;
  497. }
  498. }
  499. /*
  500. * void TransportController::PollTransmitter (void)
  501. *
  502. * Public
  503. *
  504. * Functional Description:
  505. * This function processes output data to remote sites. This
  506. * function MUST be called on a REGULAR and FREQUENT basis so that
  507. * we can maintain the physical connections in a timely manner.
  508. */
  509. void TransportController::PollTransmitter(void)
  510. {
  511. // TRACE_OUT(("TransportController::PollTransmitter"));
  512. if (! Poll_Active)
  513. {
  514. PT123 t123;
  515. Poll_Active = TRUE;
  516. /*
  517. ** Allow each t123 object to transmit any data it has available.
  518. */
  519. Transmitter_List.reset();
  520. while (Transmitter_List.iterate ((PDWORD_PTR) &t123))
  521. {
  522. t123->PollTransmitter ();
  523. }
  524. Poll_Active = FALSE;
  525. ProcessMessages ();
  526. }
  527. }
  528. /*
  529. * void TransportController::PollTransmitter (
  530. * PhysicalHandle physical_handle)
  531. *
  532. * Public
  533. *
  534. * Functional Description:
  535. */
  536. void TransportController::PollTransmitter
  537. (
  538. PhysicalHandle physical_handle
  539. )
  540. {
  541. // TRACE_OUT(("TransportController::PollTransmitter"));
  542. PT123 t123;
  543. if (! Poll_Active)
  544. {
  545. Poll_Active = TRUE;
  546. /*
  547. ** See if there is a t123 object associated with this
  548. ** physical handle
  549. */
  550. if (Protocol_Stacks.find((DWORD_PTR) physical_handle, (PDWORD_PTR) &t123))
  551. {
  552. t123->PollTransmitter();
  553. }
  554. Poll_Active = FALSE;
  555. ProcessMessages ();
  556. }
  557. }
  558. /*
  559. * PhysicalHandle TransportController::GetPhysicalHandle (
  560. * LogicalHandle logical_handle);
  561. *
  562. * Public
  563. *
  564. * Functional Description:
  565. * This function returns the physical handle associated with the
  566. * logical handle.
  567. */
  568. PhysicalHandle TransportController::GetPhysicalHandle (
  569. LogicalHandle logical_handle)
  570. {
  571. TRACE_OUT(("TransportController::GetPhysicalHandle"));
  572. PhysicalHandle physical_handle;
  573. PLogicalConnectionStruct pConn;
  574. if (Logical_Connection_List.find (logical_handle, (PDWORD_PTR) &pConn))
  575. {
  576. physical_handle = pConn -> hCommLink;
  577. }
  578. else
  579. {
  580. physical_handle = 0;
  581. }
  582. return (physical_handle);
  583. }
  584. /*
  585. * ULONG TransportController::OwnerCallback (
  586. * CallbackMessage message,
  587. * ULONG parameter1,
  588. * ULONG parameter2,
  589. * PVoid parameter3)
  590. *
  591. * Public
  592. *
  593. * Functional Description:
  594. * This function is called by the PSTNController and the T123 object(s).
  595. * This function is called when a significant event occurs. This gives the
  596. * lower objects the ability to communicate with the higher layer.
  597. */
  598. ULONG_PTR TransportController::OwnerCallback
  599. (
  600. ULONG message,
  601. void *parameter1,
  602. void *parameter2,
  603. void *parameter3
  604. )
  605. {
  606. TRACE_OUT(("TransportController::OwnerCallback"));
  607. PMessageStruct passive_message;
  608. LogicalHandle logical_handle;
  609. PLogicalConnectionStruct pConn;
  610. LegacyTransportID transport_identifier;
  611. ULONG_PTR return_value = 0;
  612. PT123 t123;
  613. message = message - TRANSPORT_CONTROLLER_MESSAGE_BASE;
  614. switch (message)
  615. {
  616. case TPRT_CONNECT_INDICATION:
  617. /*
  618. ** The TPRT_CONNECT_INDICATION message comes from a T123
  619. ** object when the remote site is attempting to make a
  620. ** logical connection with us. We issue a callback to the
  621. ** user to notify him of the request
  622. */
  623. // LONCHANC: we automatically accept the call
  624. ConnectResponse((LogicalHandle) parameter1);
  625. transport_identifier.logical_handle = (LogicalHandle) parameter1;
  626. if (Logical_Connection_List.find((DWORD_PTR) parameter1, (PDWORD_PTR) &pConn))
  627. {
  628. transport_identifier.hCommLink = pConn->hCommLink;
  629. }
  630. else
  631. {
  632. transport_identifier.hCommLink = NULL;
  633. }
  634. TRACE_OUT(("TPRTCTRL: CONNECT_INDICATION: physical_handle = %d",
  635. transport_identifier.hCommLink));
  636. ::NotifyT120(TRANSPORT_CONNECT_INDICATION, &transport_identifier);
  637. break;
  638. case TPRT_CONNECT_CONFIRM:
  639. /*
  640. ** The TPRT_CONNECT_CONFIRM message comes from a T123 object
  641. ** when a logical connection that we requested is up and
  642. ** running. We notify the user of this by issuing a callback.
  643. */
  644. transport_identifier.logical_handle = (LogicalHandle) parameter1;
  645. if (Logical_Connection_List.find((DWORD_PTR) parameter1, (PDWORD_PTR) &pConn))
  646. {
  647. transport_identifier.hCommLink = pConn->hCommLink;
  648. }
  649. else
  650. {
  651. transport_identifier.hCommLink = NULL;
  652. }
  653. TRACE_OUT(("TPRTCTRL: CONNECT_CONFIRM: physical_handle = %d",
  654. transport_identifier.hCommLink));
  655. ::NotifyT120(TRANSPORT_CONNECT_CONFIRM, &transport_identifier);
  656. break;
  657. case REQUEST_TRANSPORT_CONNECTION:
  658. /*
  659. ** This message is issued when a T123 object is making a new
  660. ** logical connection and needs a new logical handle.
  661. **
  662. ** If we return INVALID_LOGICAL_HANDLE, we wer not able to
  663. ** get a handle.
  664. */
  665. logical_handle = GetNextLogicalHandle();
  666. if (logical_handle == INVALID_LOGICAL_HANDLE)
  667. {
  668. return_value = INVALID_LOGICAL_HANDLE;
  669. break;
  670. }
  671. /*
  672. ** Register the new transport connection handle in the
  673. ** Logical_Connection_List
  674. **
  675. ** Parameter1 holds the physical handle
  676. */
  677. DBG_SAVE_FILE_LINE
  678. pConn = new LogicalConnectionStruct;
  679. if (pConn != NULL)
  680. {
  681. Logical_Connection_List.insert (logical_handle, (DWORD_PTR) pConn);
  682. pConn->fCaller = FALSE;
  683. pConn->hCommLink = (PhysicalHandle) parameter1;
  684. Protocol_Stacks.find((DWORD_PTR) parameter1, (PDWORD_PTR) &t123);
  685. pConn -> t123 = t123;
  686. /*
  687. ** Set the t123_connection_requested to TRUE. We didn't
  688. ** actually make a ConnectRequest() but the T123 object does
  689. ** know about the connection
  690. */
  691. pConn -> t123_connection_requested = TRUE;
  692. pConn -> t123_disconnect_requested = FALSE;
  693. return_value = logical_handle;
  694. }
  695. else
  696. {
  697. TRACE_OUT(("TPRTCTRL: Unable to allocate memory "
  698. "for connection"));
  699. return_value = INVALID_LOGICAL_HANDLE;
  700. }
  701. break;
  702. /*
  703. ** The following messages can NOT be processed during the callback.
  704. ** They are passive messages, that is they must be saved and
  705. ** processed at a later time. The BROKEN_CONNECTION and
  706. ** TPRT_DISCONNECT_INDICATION messages involve destroying t123
  707. ** objects. If we deleted an object here and then returned to
  708. ** the object, this would cause a GPF. Therefore these messages
  709. ** are processed later.
  710. **
  711. ** The NEW_CONNECTION callback is processed later because we want
  712. ** to process certain messages in the order they were received. If
  713. ** we received a NEW_CONNECTION followed by a BROKEN_CONNECTION
  714. ** followed by a NEW_CONNECTION, and we only processed the
  715. ** NEW_CONNECTION messages as they were received, it would really
  716. ** confuse the code.
  717. */
  718. case TPRT_DISCONNECT_INDICATION:
  719. case BROKEN_CONNECTION:
  720. DBG_SAVE_FILE_LINE
  721. passive_message = new MessageStruct;
  722. if (passive_message != NULL)
  723. {
  724. passive_message -> message = message;
  725. passive_message -> parameter1 = parameter1;
  726. passive_message -> parameter2 = parameter2;
  727. passive_message -> parameter3 = parameter3;
  728. Message_List.append ((DWORD_PTR) passive_message);
  729. }
  730. else
  731. {
  732. ERROR_OUT(("TPRTCTRL: TPRT_DISCONNECT_INDICATION: cannot allocate MessageStruct"));
  733. Emergency_Shutdown = TRUE;
  734. }
  735. break;
  736. case NEW_CONNECTION:
  737. /*
  738. ** If we can not allocate the memory needed to store this
  739. ** message, we need to return a non-zero value to the
  740. ** calling routine.
  741. */
  742. DBG_SAVE_FILE_LINE
  743. passive_message = new MessageStruct;
  744. if (passive_message != NULL)
  745. {
  746. passive_message -> message = message;
  747. passive_message -> parameter1 = parameter1;
  748. passive_message -> parameter2 = parameter2;
  749. passive_message -> parameter3 = parameter3;
  750. Message_List.append ((DWORD_PTR) passive_message);
  751. }
  752. else
  753. {
  754. ERROR_OUT(("TPRTCTRL: NEW_CONNECTION: cannot allocate MessageStruct"));
  755. return_value = 1;
  756. }
  757. break;
  758. default:
  759. ERROR_OUT(("TPRTCTRL: OwnerCallback: Illegal message = %lx", message));
  760. break;
  761. }
  762. return (return_value);
  763. }
  764. /*
  765. * void TransportController::ProcessMessages (void)
  766. *
  767. * Functional Description
  768. * This function is called periodically to process any passive owner
  769. * callbacks. If an owner callback can not be processed immediately,
  770. * it is put into the Message_List and processed at a later time.
  771. *
  772. * Formal Parameters
  773. * None
  774. *
  775. * Return Value
  776. * None
  777. *
  778. * Side Effects
  779. * None
  780. *
  781. * Caveats
  782. * None
  783. */
  784. void TransportController::ProcessMessages(void)
  785. {
  786. // TRACE_OUT(("TransportController::ProcessMessages"));
  787. ULONG message;
  788. PMessageStruct message_struct;
  789. IProtocolLayer *physical_layer;
  790. void *parameter1;
  791. void *parameter2;
  792. void *parameter3;
  793. LogicalHandle logical_handle;
  794. PLogicalConnectionStruct pConn;
  795. PhysicalHandle physical_handle;
  796. BOOL save_message = FALSE;
  797. LegacyTransportID transport_identifier;
  798. PT123 t123;
  799. BOOL link_originator;
  800. BOOL disconnect_requested;
  801. ComPort *comport;
  802. /*
  803. ** This routine can not be called during a callback from this transport.
  804. ** In other words this code is not re-entrant.
  805. */
  806. if (Poll_Active)
  807. return;
  808. /*
  809. ** Emergency_Shutdown can occur if we unsuccessfully attempt to allocate
  810. ** memory. In this situation, we shutdown the entire Transport
  811. */
  812. if (Emergency_Shutdown)
  813. {
  814. Reset (TRUE);
  815. Emergency_Shutdown = FALSE;
  816. }
  817. /*
  818. ** Go thru the Message_List until it is empty or until a message
  819. ** can not be processed.
  820. */
  821. while ((! Message_List.isEmpty ()) && (! save_message))
  822. {
  823. /*
  824. ** Look at the first message in the Message_List.
  825. */
  826. message_struct = (PMessageStruct) Message_List.read ();
  827. message = (message_struct -> message) - TRANSPORT_CONTROLLER_MESSAGE_BASE;
  828. parameter1 = message_struct -> parameter1;
  829. parameter2 = message_struct -> parameter2;
  830. parameter3 = message_struct -> parameter3;
  831. switch (message)
  832. {
  833. case NEW_CONNECTION:
  834. ASSERT(0); // impossible
  835. /*
  836. ** This message is issued by the PSTNController to notify us
  837. ** a new physical connection exists or that a previously
  838. ** requested connection is going to be muxed over a
  839. ** currently active physical connection
  840. **
  841. ** Parameter1 is the physical handle
  842. ** Parameter2 is a BOOL used to tell us if
  843. ** Parameter3 is the address of the physical layer handling
  844. ** this connection.
  845. */
  846. physical_handle = (PhysicalHandle) parameter1;
  847. link_originator = (BOOL) (DWORD_PTR)parameter2;
  848. comport = (ComPort *) parameter3;
  849. TRACE_OUT(("TPRTCTRL: ProcessMessage NEW_CONNECTION: Physical: handle = %ld", physical_handle));
  850. if (TRANSPORT_NO_ERROR != NewConnection(physical_handle, link_originator, comport))
  851. {
  852. save_message = TRUE;
  853. }
  854. break;
  855. case BROKEN_CONNECTION:
  856. ASSERT(0); // impossible
  857. /*
  858. ** This message is issued by the PSTNController when a
  859. ** physical connection has been broken.
  860. **
  861. ** parameter1 = physical_handle
  862. */
  863. physical_handle = (PhysicalHandle) parameter1;
  864. TRACE_OUT(("TPRTCTRL: BROKEN_CONNECTION: phys_handle = %lx", physical_handle));
  865. /*
  866. ** RemoveLogicalConnections() terminates all logical
  867. ** connections associated with this physical handle.
  868. ** There may be logical connections in our list even
  869. ** though a T123 does not exist for the physical handle
  870. */
  871. TRACE_OUT(("TPRTCTRL: RemoveLogicalConnections: phys_handle = %lx", physical_handle));
  872. RemoveLogicalConnections (physical_handle);
  873. /*
  874. ** Check to see if there is a t123 stack associated
  875. ** with this physical handle.
  876. */
  877. if (Protocol_Stacks.find((DWORD_PTR) physical_handle, (PDWORD_PTR) &t123))
  878. {
  879. /*
  880. ** Remove the T123 protocol stacks from our lists and
  881. ** delete it.
  882. */
  883. Transmitter_List.remove((DWORD_PTR) t123);
  884. Protocol_Stacks.remove((DWORD_PTR) physical_handle);
  885. delete t123;
  886. }
  887. break;
  888. case TPRT_DISCONNECT_REQUEST:
  889. /*
  890. ** This message occurs when a DisconnectRequest() was received
  891. ** during a PollReceiver() call. We can NOT process the
  892. ** DisconnectRequest() during our callback to the user
  893. ** application, but we can queue the message and process it
  894. ** now
  895. */
  896. DisconnectRequest((LogicalHandle) parameter1, (BOOL) (DWORD_PTR)parameter2);
  897. break;
  898. case TPRT_DISCONNECT_INDICATION:
  899. /*
  900. ** This message is received from a T123 object when a logical
  901. ** connection is terminated. If the logical connection
  902. ** handle passed in parameter1 is INVALID_LOGICAL_HANDLE,
  903. ** the T123 object is telling us to terminate it.
  904. **
  905. ** parameter1 = logical_handle
  906. ** parameter2 = physical_handle
  907. ** parameter3 = BOOL - TRUE if we requested this
  908. ** disconnection.
  909. */
  910. logical_handle = (LogicalHandle) parameter1;
  911. physical_handle = (PhysicalHandle) parameter2;
  912. /*
  913. ** Check the physical_handle to make sure it is valid
  914. */
  915. if (! Protocol_Stacks.find((DWORD_PTR) physical_handle, (PDWORD_PTR) &t123))
  916. {
  917. ERROR_OUT(("TPRTCTRL: ProcessMessages: DISCONNECT_IND **** Illegal Physical Handle = %ld", physical_handle));
  918. break;
  919. }
  920. /*
  921. ** If the logical_handle is INVALID_LOGICAL_HANDLE, the
  922. ** T123 object is telling us to delete it.
  923. */
  924. if (logical_handle == INVALID_LOGICAL_HANDLE)
  925. {
  926. TRACE_OUT(("TPRTCTRL: Protocol stack deleted - phys handle = %ld", physical_handle));
  927. /*
  928. ** Find out the value of parameter3 before we
  929. ** delete the t123 object.
  930. */
  931. disconnect_requested = *((BOOL *) parameter3);
  932. /*
  933. ** Call RemoveLogicalConnections() to remove all logical
  934. ** connections associated with this physical handle.
  935. */
  936. RemoveLogicalConnections (physical_handle);
  937. /*
  938. ** Remove the T123 object from the lists and delete the
  939. ** object
  940. */
  941. Transmitter_List.remove((DWORD_PTR) t123);
  942. Protocol_Stacks.remove((DWORD_PTR) physical_handle);
  943. delete t123;
  944. }
  945. else
  946. if (Logical_Connection_List.find (logical_handle, (PDWORD_PTR) &pConn))
  947. {
  948. /*
  949. ** This specifies that a logical connection needs to be
  950. ** removed. We remove it from the Logical_Connection_List
  951. ** and notify the user of the disconnection
  952. */
  953. Logical_Connection_List.remove (logical_handle);
  954. if (! pConn->t123_disconnect_requested)
  955. {
  956. transport_identifier.logical_handle = logical_handle;
  957. transport_identifier.hCommLink = physical_handle;
  958. ::NotifyT120(TRANSPORT_DISCONNECT_INDICATION, &transport_identifier);
  959. }
  960. delete pConn;
  961. }
  962. break;
  963. default:
  964. ERROR_OUT(("TPRTCTRL: ProcessMessages: Illegal message = %lx", message));
  965. break;
  966. }
  967. /*
  968. ** If save_message is TRUE, the message needs to be re-processed at a
  969. ** later time.
  970. */
  971. if (! save_message)
  972. {
  973. delete ((PMessageStruct) Message_List.get ());
  974. }
  975. }
  976. }
  977. /*
  978. * void TransportController::Reset (
  979. * BOOL notify_user)
  980. *
  981. * Functional Description
  982. * This function deletes all stacks and TCs. If the notify_user flag is
  983. * set to TRUE, it makes a callback to the user.
  984. *
  985. * Formal Parameters
  986. * notify_user (i) - Notify User flag
  987. *
  988. * Return Value
  989. * None
  990. *
  991. * Side Effects
  992. * None
  993. *
  994. * Caveats
  995. * None
  996. */
  997. void TransportController::Reset
  998. (
  999. BOOL notify_user
  1000. )
  1001. {
  1002. TRACE_OUT(("TransportController::Reset"));
  1003. LogicalHandle logical_handle;
  1004. PMessageStruct message_struct;
  1005. LegacyTransportID transport_identifier;
  1006. PhysicalHandle physical_handle;
  1007. PLogicalConnectionStruct pConn;
  1008. PT123 t123;
  1009. TRACE_OUT(("TPRTCTRL: reset: notify_user = %d", notify_user));
  1010. /*
  1011. ** Delete all of the stacks
  1012. */
  1013. Protocol_Stacks.reset();
  1014. while (Protocol_Stacks.iterate((PDWORD_PTR) &t123))
  1015. {
  1016. delete t123;
  1017. }
  1018. Protocol_Stacks.clear ();
  1019. Transmitter_List.clear ();
  1020. /*
  1021. ** Empty the message list
  1022. */
  1023. while (! Message_List.isEmpty ())
  1024. {
  1025. delete ((PMessageStruct) Message_List.get ());
  1026. }
  1027. /*
  1028. ** Empty the Logical_Connection_List
  1029. */
  1030. Logical_Connection_List.reset();
  1031. while (Logical_Connection_List.iterate((PDWORD_PTR) &pConn, (PDWORD_PTR) &logical_handle))
  1032. {
  1033. if (pConn != NULL)
  1034. {
  1035. physical_handle = pConn->hCommLink;
  1036. delete pConn;
  1037. }
  1038. else
  1039. {
  1040. physical_handle = 0;
  1041. }
  1042. if (notify_user)
  1043. {
  1044. transport_identifier.logical_handle = logical_handle;
  1045. transport_identifier.hCommLink = physical_handle;
  1046. ::NotifyT120(TRANSPORT_DISCONNECT_INDICATION, &transport_identifier);
  1047. }
  1048. }
  1049. Logical_Connection_List.clear ();
  1050. }
  1051. /*
  1052. * BOOL TransportController::NewConnection (
  1053. * PhysicalHandle physical_handle,
  1054. * BOOL link_originator,
  1055. * IProtocolLayer * physical_layer)
  1056. *
  1057. * Functional Description
  1058. * This function is called when a new physical connection is created. It
  1059. * creates a T123 object if necessary.
  1060. *
  1061. * Formal Parameters
  1062. * physical_handle (i) - physical handle of the new physical connection
  1063. * link_originator (i) - TRUE if we initiated the connection.
  1064. * physical_layer (i) - Address of the physical layer.
  1065. *
  1066. * Return Value
  1067. * TRUE, if the new connection was successfully executed.
  1068. *
  1069. * Side Effects
  1070. * None
  1071. *
  1072. * Caveats
  1073. * None
  1074. */
  1075. TransportError TransportController::CreateT123Stack
  1076. (
  1077. PhysicalHandle hCommLink,
  1078. BOOL link_originator, // fCaller
  1079. ComPort *comport,
  1080. PLUGXPRT_PARAMETERS *pParams
  1081. )
  1082. {
  1083. TRACE_OUT(("TransportController::CreateT123Stack"));
  1084. TransportError rc = TRANSPORT_NO_ERROR;
  1085. /*
  1086. ** Do we need to create a new t123 stack for this physical connection.
  1087. */
  1088. T123 *t123 = NULL;
  1089. if (! Protocol_Stacks.find((DWORD_PTR) hCommLink, (PDWORD_PTR) &t123))
  1090. {
  1091. BOOL initialized;
  1092. DBG_SAVE_FILE_LINE
  1093. t123 = new T123(this,
  1094. TRANSPORT_CONTROLLER_MESSAGE_BASE,
  1095. link_originator,
  1096. comport,
  1097. hCommLink,
  1098. pParams,
  1099. &initialized);
  1100. if (t123 != NULL && initialized)
  1101. {
  1102. /*
  1103. ** Put the T123 object into the Protocol_Stacks
  1104. ** and Transmitter_List arrays
  1105. */
  1106. Protocol_Stacks.insert((DWORD_PTR) hCommLink, (DWORD_PTR) t123);
  1107. Transmitter_List.append((DWORD_PTR) t123);
  1108. }
  1109. else
  1110. {
  1111. ERROR_OUT(("TPRTCTRL: CreateT123Stack: cannot allocate T123"));
  1112. delete t123;
  1113. rc = TRANSPORT_MEMORY_FAILURE;
  1114. }
  1115. }
  1116. return rc;
  1117. }
  1118. TransportError TransportController::NewConnection
  1119. (
  1120. PhysicalHandle hCommLink,
  1121. BOOL link_originator,
  1122. ComPort *comport
  1123. )
  1124. {
  1125. TRACE_OUT(("TransportController::NewConnection"));
  1126. LogicalHandle logical_handle;
  1127. PLogicalConnectionStruct pConn;
  1128. BOOL initialized;
  1129. T123 *t123;
  1130. TransportError rc;
  1131. if (! Protocol_Stacks.find((DWORD_PTR) hCommLink, (PDWORD_PTR) &t123))
  1132. {
  1133. ERROR_OUT(("TransportController::NewConnection: cannot find T123 stack, hCommLink=%d", hCommLink));
  1134. return TRANSPORT_NO_T123_STACK;
  1135. }
  1136. /*
  1137. ** Go through each of the logical connections to find the
  1138. ** ones that are waiting for this physical connection to be
  1139. ** established. The PSTNController object issues a
  1140. ** NEW_CONNECTION callback for each logical connection that
  1141. ** needs to be initiated.
  1142. */
  1143. Logical_Connection_List.reset();
  1144. while (Logical_Connection_List.iterate((PDWORD_PTR) &pConn, (PDWORD_PTR) &logical_handle))
  1145. {
  1146. /*
  1147. ** Compare the physical handles, if they are the same,
  1148. ** check to see if this logical connection has already issued
  1149. ** a ConnectRequest() to the T123 object.
  1150. */
  1151. if (hCommLink == pConn->hCommLink)
  1152. {
  1153. /*
  1154. ** See if this connection has already issued a ConnectRequest
  1155. */
  1156. if (! pConn->t123_connection_requested)
  1157. {
  1158. /*
  1159. ** Fill in the transport structure.
  1160. */
  1161. pConn->t123 = t123;
  1162. pConn->comport = comport;
  1163. pConn->t123_connection_requested = TRUE;
  1164. /*
  1165. ** Issue a Connect Request to the T123 object
  1166. */
  1167. rc = t123->ConnectRequest(logical_handle, pConn->priority);
  1168. /*
  1169. ** If for some reason we get an error on the ConnectRequest(),
  1170. ** take the physical connection down.
  1171. */
  1172. if (rc != TRANSPORT_NO_ERROR)
  1173. {
  1174. RemoveLogicalConnections (hCommLink);
  1175. /*
  1176. ** Remove the T123 object from the lists and
  1177. ** delete the object
  1178. */
  1179. Transmitter_List.remove((DWORD_PTR) t123);
  1180. Protocol_Stacks.remove((DWORD_PTR) hCommLink);
  1181. delete t123;
  1182. }
  1183. }
  1184. }
  1185. }
  1186. return TRANSPORT_NO_ERROR;
  1187. }
  1188. /*
  1189. * LogicalHandle TransportController::GetNextLogicalHandle (void);
  1190. *
  1191. * Functional Description
  1192. * This function returns an available logical handle
  1193. *
  1194. * Formal Parameters
  1195. * None
  1196. *
  1197. * Return Value
  1198. * The next available logical handle
  1199. *
  1200. * Side Effects
  1201. * None
  1202. *
  1203. * Caveats
  1204. * None
  1205. */
  1206. LogicalHandle TransportController::GetNextLogicalHandle (void)
  1207. {
  1208. LogicalHandle logical_handle = 1;
  1209. /*
  1210. ** Go thru the Logical_Connection_list, looking for the first
  1211. ** available entry
  1212. */
  1213. while (Logical_Connection_List.find (logical_handle) &&
  1214. (logical_handle != INVALID_LOGICAL_HANDLE))
  1215. {
  1216. logical_handle++;
  1217. }
  1218. return (logical_handle);
  1219. }
  1220. /*
  1221. * void TransportController::RemoveLogicalConnections (
  1222. * PhysicalHandle physical_handle)
  1223. *
  1224. * Functional Description
  1225. * This function removes all logical connections associated with the
  1226. * passed in physical handle
  1227. *
  1228. * Formal Parameters
  1229. * physical_handle (i) - PSTNController generated physical handle
  1230. *
  1231. * Return Value
  1232. * None
  1233. *
  1234. * Side Effects
  1235. * None
  1236. *
  1237. * Caveats
  1238. * None
  1239. */
  1240. void TransportController::RemoveLogicalConnections
  1241. (
  1242. PhysicalHandle physical_handle
  1243. )
  1244. {
  1245. TRACE_OUT(("TransportController::RemoveLogicalConnections"));
  1246. LogicalHandle logical_handle;
  1247. PLogicalConnectionStruct pConn;
  1248. LegacyTransportID transport_identifier;
  1249. /*
  1250. ** Go thru each logical connection to see if it is associated with the
  1251. ** specified physical handle.
  1252. */
  1253. Logical_Connection_List.reset();
  1254. while (Logical_Connection_List.iterate((PDWORD_PTR) &pConn, (PDWORD_PTR) &logical_handle))
  1255. {
  1256. /*
  1257. ** If the physical handle is used by the logical connection,
  1258. ** delete the structure and remove it from the Logical_Connection_List
  1259. */
  1260. if (physical_handle == pConn->hCommLink)
  1261. {
  1262. Logical_Connection_List.remove(logical_handle);
  1263. /*
  1264. ** Notify the user that the logical connection is no longer valid
  1265. ** If the user had previously issued a DisconnectRequest(), don't
  1266. ** issue the TRANSPORT_DISCONNECT_INDICATION callback. The user
  1267. ** isn't expecting a callback.
  1268. */
  1269. if (! pConn->t123_disconnect_requested)
  1270. {
  1271. transport_identifier.logical_handle = logical_handle;
  1272. transport_identifier.hCommLink = physical_handle;
  1273. ::NotifyT120(TRANSPORT_DISCONNECT_INDICATION, &transport_identifier);
  1274. }
  1275. delete pConn;
  1276. /*
  1277. ** Since we removed an entry from the Logical_Connection_List,
  1278. ** reset the iterator.
  1279. */
  1280. Logical_Connection_List.reset ();
  1281. }
  1282. }
  1283. }
  1284.