Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3332 lines
99 KiB

  1. #include "precomp.h"
  2. #include "cnpcoder.h"
  3. DEBUG_FILEZONE(ZONE_T120_MCSNC);
  4. /*
  5. * control.cpp
  6. *
  7. * Copyright (c) 1993 - 1996 by DataBeam Corporation, Lexington, KY
  8. *
  9. * Abstract:
  10. * This is the implementation file for the MCS controller. Its primary
  11. * purpose is to create and destroy objects as needed at run-time. The
  12. * interface file contains a detailed description of what this class
  13. * does.
  14. *
  15. * There can be only one instance of this object within an MCS provider.
  16. * Once initialization is complete, this object performs all activity
  17. * as part of an owner callback from one of its "children".
  18. *
  19. * The owner callback member function determines which callback is
  20. * occurring, unpacks the parameters, and calls a private member function
  21. * that is associated with that callback. So when reading through the
  22. * code, it is possible to view those private member functions as though
  23. * they were direct calls from the child objects. It is worth noting
  24. * that all of the owner callback private member functions follow the
  25. * same naming convention. The function name is the name of the
  26. * originating object followed by the name of the operation. For
  27. * example, if an application interface object sends a create domain
  28. * request to the controller through the owner callback, the name of
  29. * the associated member function is ApplicationCreateDomain. When a
  30. * connection object wishes to delete itself, this is called
  31. * ConnectionDeleteConnection.
  32. *
  33. * The Windows version of the constructor can optionally allocate a
  34. * Windows timer to provider MCS with a heartbeat. The timer procedure
  35. * uses a static variable to "jump into" the context of the controller
  36. * object. For this reason, there can only be one instance of this class.
  37. *
  38. * This class is also responsible for sending four different messages
  39. * to the node controller: connect provider indication; connect provider
  40. * confirm; disconnect provider indication; and transport status
  41. * indication. A control queue is maintained to buffer these indications
  42. * and confirms until the next time slice.
  43. *
  44. * Private Instance Variables:
  45. * Connection_Handle_Counter
  46. * A rolling counter used by the controller to generate connection
  47. * handles. It is 16-bit, and will not repeat a handle until all 64K
  48. * have been used (0 is NOT a valid handle).
  49. * ASN_Coder
  50. * When using the DataBeam's implementation of ASN.1, this is the
  51. * ASN coder. When the MCS coder is created, this object is passed
  52. * to it, but this instance variable allows us to later delete this
  53. * object.
  54. * m_DomainList2
  55. * A list of existing Domains, indexed by DomainSelector. These are
  56. * created when the controller receives a CreateDomain.
  57. * m_ConnectionList2
  58. * A list of existing Connections, indexed by ConnectionHandle. These
  59. * are created in one of two ways. First, in response to a locally
  60. * generated ConnectProviderRequest (with a valid local domain and
  61. * transport address). Second, in response to a locally generated
  62. * ConnectProviderResponse (which is responding to an incoming
  63. * connection).
  64. * m_ConnPollList
  65. * This is a list of active connection objects which is used for
  66. * polling in the heartbeat call. The order of the entries is modified
  67. * every heartbeat in order to provide fair access to resources.
  68. * m_ConnPendingList2
  69. * This is a list of incoming connections for which a connect provider
  70. * response has not yet been received. This list holds pertinent
  71. * information about the pending connection that will not be passed
  72. * back in the ConnectProviderResponse..
  73. * m_ConnectionDeletionList2
  74. * A list of connection objects awaiting deletion,
  75. * Connection_Deletion_Pending
  76. * A flag that indicates whether or not there is anything in the
  77. * connection deletion list.
  78. * Private Member Functions:
  79. * LoadTransportStacks
  80. * This function is called by the constructor to load all available
  81. * transport stacks for use by MCS. It reads the INI file to
  82. * determine which DLLs are to be used, and then instantiate a
  83. * transport interface object for each. This code is NOT portable.
  84. * ApplicationCreateDomain
  85. * This is an owner callback function that results from a call to
  86. * CreateDomain. This callback comes from the application interface
  87. * object that represents the originator of the request. The named
  88. * domain will be created (if it doesn't already exist).
  89. * ApplicationDeleteDomain
  90. * This is an owner callback function that results from a call to
  91. * DeleteDomain. This callback comes from the application interface
  92. * object that represents the originator of the request. The named
  93. * domain will be deleted (if it exists).
  94. * ApplicationConnectProviderRequest
  95. * This is an owner callback function that occurs when the node
  96. * controller calls ConnectProviderRequest. After parameters are
  97. * validated, a new connection object will be created.
  98. * ApplicationConnectProviderResponse
  99. * This is an owner callback function that occurs when the node
  100. * controller calls ConnectProviderResponse. The controller responds
  101. * by sending a message to the proper domain object, letting it know
  102. * whether an inbound connection was accepted or rejected.
  103. * ApplicationDisconnectProviderRequest
  104. * This is an owner callback function that occurs when the node
  105. * controller calls DisconnectProviderRequest. If the connection
  106. * handle is valid, the associated connection object will be deleted.
  107. * ApplicationAttachUserRequest
  108. * This is an owner callback function that occurs when any application
  109. * sends an AttachUserRequest via one of the active application
  110. * interface objects. The controller will create a new user object
  111. * after parameter validation.
  112. * ConnectionDeleteConnection
  113. * This is an owner callback function that occurs when a connection
  114. * object determines the need to delete itself. This can occur for
  115. * two reasons. First, in response to a disconnect provider ultimatum
  116. * from either the local or the remote domain. Second, in response
  117. * to a loss of connection from the transport layer.
  118. * ConnectionConnectProviderConfirm
  119. * This is an owner callback function that occurs when a connection
  120. * object receives a connect response PDU from a remote provider for an
  121. * outstanding connect initial. The controller responds by sending a
  122. * connect provider confirm to the node controller.
  123. * TransportDataIndication
  124. * This is an owner callback function that occurs when data is
  125. * received on a transport connection for which no other object has
  126. * registered.
  127. * TransportStatusIndication
  128. * This is an owner callback function that occurs when a status
  129. * indication message comes from the transport layer. This information
  130. * is forwarded to the node controller in the form of a transport
  131. * status indication message.
  132. * ProcessConnectInitial
  133. * Processes incoming connect initial PDUs. Sends connect provider
  134. * indication to the node controller.
  135. * ProcessConnectAdditional
  136. * Processes incoming connect additional PDUs. Binds them to the
  137. * appropriate connection, if possible.
  138. * ConnectResponse
  139. * Issues a failed connect response when something goes wrong.
  140. * ConnectResult
  141. * Issues a failed connect result when something goes wrong.
  142. * AllocateConnectionHandle
  143. * This private member function is used by the controller to allocate
  144. * new connection handles when creating a new connection object.
  145. * FlushMessageQueue
  146. * This member function flushes the control message queue by sending
  147. * all contained messages to the node controller.
  148. *
  149. * Caveats:
  150. * There can only one instance of this object at a time.
  151. *
  152. * Author:
  153. * James P. Galvin, Jr.
  154. */
  155. /*
  156. * External Interfaces
  157. */
  158. #include <nmqos.h>
  159. #include <t120qos.h>
  160. #include "csap.h"
  161. /*
  162. * Macros
  163. */
  164. enum
  165. {
  166. TRANSPORT_TRANSMIT_EVENT,
  167. CONNECTION_DELETION_PENDING_EVENT,
  168. GCC_FLUSH_OUTGOING_PDU_EVENT,
  169. NUMBER_OF_EVENTS
  170. };
  171. /*
  172. * Macros
  173. *
  174. * These macros define the maximum length of various strings within the
  175. * controller. They are used when reading data from the INI file, which is
  176. * very Windows specific. These values are somewhat arbitrary and may be
  177. * changed in future releases, if necessary.
  178. */
  179. #define MAXIMUM_CONFIGURATION_ITEM_LENGTH 20
  180. #define MAXIMUM_TRANSPORT_IDENTIFIER_LENGTH 40
  181. /* The MSMCSTCP window class name. This name must be unique system-wide. */
  182. #define MSMCSTCP_WINDOW_CLASS_NAME "NM TCP Window"
  183. /* Timer duration. We can get a timer event every X milliseconds. During
  184. * this time, we can do any maintenance that is necessary. */
  185. #define MSMCSTCP_TIMER_DURATION 30000
  186. /*
  187. * This is the number of extra memory blocks that the local memory
  188. * manager can allocate.
  189. * This number should be set to 3 * prime number and close to the
  190. * maximum number of extra memory blocks that can be allocated.
  191. */
  192. #define DEFAULT_MAX_EXTERNAL_MEMORY 237
  193. /*
  194. * This is a prototype for the controller thread entry point.
  195. */
  196. ULong APIENTRY ControllerThread (PVoid);
  197. // The DLL's HINSTANCE.
  198. extern HINSTANCE g_hDllInst;
  199. // The TCP socket window handle
  200. HWND TCP_Window_Handle;
  201. // The global MCS Critical Section
  202. CRITICAL_SECTION g_MCS_Critical_Section;
  203. /*
  204. * This is a global variable that has a pointer to the one MCS coder that
  205. * is instantiated by the MCS Controller. Most objects know in advance
  206. * whether they need to use the MCS or the GCC coder, so, they do not need
  207. * this pointer in their constructors.
  208. */
  209. extern CMCSCoder *g_MCSCoder;
  210. extern CCNPCoder *g_CNPCoder;
  211. // The global TransportInterface pointer (for transport access)
  212. extern PTransportInterface g_Transport;
  213. BOOL GetSecurityInfo(ConnectionHandle connection_handle, PBYTE pInfo, PDWORD pcbInfo);
  214. /*
  215. * g_pMCSController
  216. * This is a pointer to the one-and-only controller created within the
  217. * MCS system. This object is created during MCSInitialize by the process
  218. * that is taking on the responsibilities of the node controller.
  219. */
  220. PController g_pMCSController = NULL;
  221. // The MCS main thread handle
  222. HANDLE g_hMCSThread = NULL;
  223. /*
  224. * These macros define the number of buckets to be used in various hash
  225. * dictionaries that are maintained by the controller. Having more buckets
  226. * allows the dictionaries to handle more entries efficiently, but costs
  227. * more resources.
  228. */
  229. #define CONNECTION_LIST_NUMBER_OF_BUCKETS 16
  230. /*
  231. * Controller ()
  232. *
  233. * Public
  234. *
  235. * Functional Description:
  236. * This is the constructor for the Controller. It creates the application
  237. * interface and transport interface objects that will be used by MCS.
  238. * It also creates the memory manager object that will used throughout
  239. * the system by anyone requiring memory management services. And its
  240. * last duty is to allocate a Windows timer for use in getting a time
  241. * slice within which MCS does its work.
  242. */
  243. Controller::Controller
  244. (
  245. PMCSError mcs_error
  246. )
  247. :
  248. CRefCount(MAKE_STAMP_ID('M','C','t','r')),
  249. m_DomainList2(),
  250. m_ConnectionList2(CONNECTION_LIST_NUMBER_OF_BUCKETS),
  251. m_ConnPendingList2(),
  252. m_ConnectionDeletionList2(CONNECTION_LIST_NUMBER_OF_BUCKETS)
  253. {
  254. ULong thread_id;
  255. TransportInterfaceError transport_interface_error;
  256. /*
  257. * Initialize the return value to indicate that no error has yet occured.
  258. */
  259. *mcs_error = MCS_NO_ERROR;
  260. // Perform memory pool allocation for DataPacket objects.
  261. DataPacket::AllocateMemoryPool (ALLOCATE_DATA_PACKET_OBJECTS);
  262. /*
  263. * Give all pointers and handles initial values so that the destructor
  264. * will not try to free unallocated resources when the constructor fails
  265. * part-way.
  266. */
  267. TCP_Window_Handle = NULL;
  268. Transport_Transmit_Event = NULL;
  269. Connection_Deletion_Pending_Event = NULL;
  270. m_fControllerThreadActive = FALSE;
  271. #ifndef NO_TCP_TIMER
  272. Timer_ID = 0;
  273. #endif /* NO_TCP_TIMER */
  274. /*
  275. * Initialize the handle counters to 0. These rolling instance variables
  276. * are used to generate uniwue handles as each user and connection object
  277. * is created.
  278. */
  279. Connection_Handle_Counter = 0;
  280. Connection_Deletion_Pending = FALSE;
  281. // Initialize MCS's critical section.
  282. InitializeCriticalSection (&g_MCS_Critical_Section);
  283. /*
  284. * Create an ASN.1 coder which will encode all ASN.1 PDUs. Check
  285. * to make sure the coder was successfully created.
  286. */
  287. DBG_SAVE_FILE_LINE
  288. g_MCSCoder = new CMCSCoder ();
  289. /*
  290. * Make sure the creation of the packet coder was successful before
  291. * proceeding.
  292. */
  293. if (g_MCSCoder == NULL)
  294. {
  295. /*
  296. * If the packet coder could not be createdm then report the error.
  297. * This IS a fatal error, so the faulty controller should be
  298. * destroyed and never used.
  299. */
  300. WARNING_OUT (("Controller::Controller: failure creating packet coder"));
  301. *mcs_error = MCS_ALLOCATION_FAILURE;
  302. }
  303. /*
  304. * Do not continue with the initialization if an error has occured.
  305. */
  306. if (*mcs_error == MCS_NO_ERROR)
  307. {
  308. // We have to initialize the User class
  309. if (FALSE == User::InitializeClass()) {
  310. /*
  311. * The initialization of the User class failed, so we
  312. * must fail the creation of this controller.
  313. */
  314. WARNING_OUT (("Controller::Controller: "
  315. "failed to initialize User class."));
  316. *mcs_error = MCS_ALLOCATION_FAILURE;
  317. }
  318. }
  319. /*
  320. * Do not continue with the initialization if an error has occured.
  321. */
  322. if (*mcs_error == MCS_NO_ERROR)
  323. {
  324. /*
  325. * We must allocate an event object that will used to notify the
  326. * controller when data is ready to be transmitted to a transport
  327. * stack.
  328. */
  329. Transport_Transmit_Event = CreateEvent (NULL, FALSE, FALSE, NULL);
  330. if (Transport_Transmit_Event == NULL)
  331. {
  332. /*
  333. * Were unable to allocate an event object for this task, so we
  334. * must fail the creation of this controller.
  335. */
  336. WARNING_OUT (("Controller::Controller: "
  337. "failure allocating transport transmit event object"));
  338. *mcs_error = MCS_ALLOCATION_FAILURE;
  339. }
  340. }
  341. /*
  342. * Do not continue with the initialization if an error has occured.
  343. */
  344. if (*mcs_error == MCS_NO_ERROR)
  345. {
  346. /*
  347. * We must allocate an event object that will used for
  348. * synchronization between the event loop thread and the thread
  349. * that creates/destroys the Controller object.
  350. */
  351. Synchronization_Event = CreateEvent (NULL, FALSE, FALSE, NULL);
  352. if (Synchronization_Event == NULL)
  353. {
  354. /*
  355. * Were unable to allocate an event object for this task, so we
  356. * must fail the creation of this controller.
  357. */
  358. WARNING_OUT (("Controller::Controller: "
  359. "failure allocating synchronization event object"));
  360. *mcs_error = MCS_ALLOCATION_FAILURE;
  361. }
  362. }
  363. /*
  364. * Do not continue with the initialization if an error has occured.
  365. */
  366. if (*mcs_error == MCS_NO_ERROR)
  367. {
  368. /*
  369. * We must allocate an event object that will used to notify the
  370. * controller when data is ready to be transmitted to a transport
  371. * stack.
  372. */
  373. Connection_Deletion_Pending_Event = CreateEvent (NULL, FALSE, FALSE, NULL);
  374. if (Connection_Deletion_Pending_Event == NULL)
  375. {
  376. /*
  377. * Were unable to allocate an event object for this task, so we
  378. * must fail the creation of this controller.
  379. */
  380. WARNING_OUT (("Controller::Controller: "
  381. "failure allocating connection deletion pending event object"));
  382. *mcs_error = MCS_ALLOCATION_FAILURE;
  383. }
  384. }
  385. /*
  386. * Do not continue with the initialization if an error has occured.
  387. */
  388. if (*mcs_error == MCS_NO_ERROR)
  389. {
  390. /*
  391. * Initialize the flag that indicates that the controller is not yet
  392. * shutting down.
  393. */
  394. Controller_Closing = FALSE;
  395. /*
  396. * Since everything else was successful, we must create a thread
  397. * winthin which the controller will do most of its work.
  398. */
  399. g_hMCSThread = CreateThread (NULL, 0, ControllerThread,
  400. (PVoid) this, 0, &thread_id);
  401. if (g_hMCSThread == NULL)
  402. {
  403. /*
  404. * We were unable to create the thread that the controller needs
  405. * to do its job in an event-driven fashion. We must therefore
  406. * fail the creation of this controller.
  407. */
  408. WARNING_OUT (("Controller::Controller: failure creating thread"));
  409. *mcs_error = MCS_ALLOCATION_FAILURE;
  410. }
  411. }
  412. if (*mcs_error == MCS_NO_ERROR) {
  413. // We need to wait until the event loop thread creates the TCP msg window.
  414. WaitForSingleObject (Synchronization_Event, INFINITE);
  415. if (TCP_Window_Handle == NULL) {
  416. WARNING_OUT (("Controller::Controller: The event-loop thread failed to create the TCP msg window."));
  417. *mcs_error = MCS_NO_TRANSPORT_STACKS;
  418. /*
  419. * We assume that the event loop thread has exited.
  420. */
  421. ClosePh (&g_hMCSThread);
  422. }
  423. else {
  424. /*
  425. * We set the flag used by the destructor
  426. * to check whether we should wait for the thread to finish.
  427. */
  428. m_fControllerThreadActive = TRUE;
  429. }
  430. }
  431. if (*mcs_error == MCS_NO_ERROR)
  432. {
  433. g_CNPCoder = new CCNPCoder();
  434. if (g_CNPCoder != NULL)
  435. {
  436. g_CNPCoder->Init();
  437. }
  438. else
  439. {
  440. WARNING_OUT(("Controller::Controller: "
  441. "failuer allocating CNP Coder"));
  442. *mcs_error = MCS_ALLOCATION_FAILURE;
  443. }
  444. }
  445. /*
  446. * Now, load the transport interface.
  447. */
  448. if (*mcs_error == MCS_NO_ERROR)
  449. {
  450. DBG_SAVE_FILE_LINE
  451. g_Transport = new TransportInterface (Transport_Transmit_Event,
  452. &transport_interface_error);
  453. /*
  454. * Make sure the creation of the object was successful before
  455. * proceeding.
  456. */
  457. if (g_Transport != NULL)
  458. {
  459. /*
  460. * Check the return value from the constructor.
  461. */
  462. if (transport_interface_error == TRANSPORT_INTERFACE_NO_ERROR)
  463. {
  464. /*
  465. * If everything was successful, put the new transport
  466. * interface object into the dictionary.
  467. */
  468. WARNING_OUT (("Controller::Controller: "
  469. "TCP transport interface has been created successfully."));
  470. }
  471. else
  472. {
  473. /*
  474. * If the return value indicates that something went
  475. * wrong during the creation of the transport interface
  476. * object, then must destroy it immediately to insure
  477. * that it does not get used.
  478. */
  479. WARNING_OUT (("Controller::Controller: "
  480. "deleting faulty TCP transport interface"));
  481. delete g_Transport;
  482. g_Transport = NULL;
  483. *mcs_error = MCS_NO_TRANSPORT_STACKS;
  484. }
  485. }
  486. else
  487. {
  488. /*
  489. * We were unable to create the transport interface object.
  490. * The MCS_NO_TRANSPORT_STACKS error is now a fatal error.
  491. */
  492. WARNING_OUT (("Controller::Controller: "
  493. "failure allocating TCP transport interface"));
  494. *mcs_error = MCS_NO_TRANSPORT_STACKS;
  495. }
  496. }
  497. }
  498. /*
  499. * ~Controller ()
  500. *
  501. * Public
  502. *
  503. * Functional Description:
  504. * This is the destructor for the Controller. It destroys all objects
  505. * owned by the controller. Note that it attempts to do this in a
  506. * systematic way to facilitate cleanup shut down. If first deletes
  507. * connection objects, giving them the opportunity to send disconnects
  508. * to both the local and remote domains. Then it deletes the transport
  509. * interfaces. Next it deletes the user objects, giving them the
  510. * opportunity to cleanly sever their attachments to both the user
  511. * applications and the local domains. Then it deletes the application
  512. * interfaces (which should no longer be needed). Lastly it deletes
  513. * the domains, which should be empty as a result of all user attachments
  514. * and MCS connections being destroyed.
  515. */
  516. Controller::~Controller ()
  517. {
  518. PConnection lpConnection;
  519. PConnectionPending lpConnectionPending;
  520. //PTransportInterface lpTransportInterface;
  521. //PUser lpUser;
  522. PDomain lpDomain;
  523. /*
  524. * We need to wait for the mutex before destroying the controller. Note
  525. * that we do not check the return value from the wait because we have to
  526. * destroy this object no matter what.
  527. */
  528. EnterCriticalSection (&g_MCS_Critical_Section);
  529. /*
  530. * This code clears out the Connection List. Here it necessary to delete
  531. * not only the connection objects, but also the connection information
  532. * structure which is maintained by the controller.
  533. */
  534. m_ConnectionList2.Reset();
  535. while (NULL != (lpConnection = m_ConnectionList2.Iterate()))
  536. {
  537. delete lpConnection;
  538. }
  539. Connection_Deletion_Pending = FALSE;
  540. /*
  541. * Clear out the connection pending list. This includes freeing up memory
  542. * that was allocated to hold the connection pending structure.
  543. */
  544. while (NULL != (lpConnectionPending = m_ConnPendingList2.Get()))
  545. {
  546. delete lpConnectionPending;
  547. }
  548. /*
  549. * This code clears out the Domain List. All domain objects are deleted.
  550. */
  551. while (NULL != (lpDomain = m_DomainList2.Get()))
  552. {
  553. delete lpDomain;
  554. }
  555. if (m_fControllerThreadActive)
  556. {
  557. /*
  558. * Set the flag that indicates to the event loop thread that it is time to
  559. * die. Then, we wait for the thread to terminate itself.
  560. */
  561. Controller_Closing = TRUE;
  562. // Give the eventloop a chance to exit
  563. SetEvent(Connection_Deletion_Pending_Event);
  564. }
  565. // We can now leave MCS's critical section
  566. LeaveCriticalSection (&g_MCS_Critical_Section);
  567. /*
  568. * If a thread termination event was successfully created for this controller, we must
  569. * wait on it.
  570. */
  571. if (m_fControllerThreadActive)
  572. {
  573. /*
  574. * If the DLL instance variable is NULL, the process is
  575. * detaching from the DLL. This is the abnormal termination
  576. * case (after a GPF, for example). In this case, the event
  577. * loop thread has already exited, and we should not wait for it.
  578. */
  579. if (g_hDllInst != NULL)
  580. WaitForSingleObject (Synchronization_Event, INFINITE);
  581. CloseHandle (Synchronization_Event);
  582. //
  583. // Relinquish the remainder of our time slice, to allow controller thread to exit.
  584. //
  585. Sleep(0);
  586. }
  587. // Now, we can delete MCS's critical section
  588. DeleteCriticalSection (&g_MCS_Critical_Section);
  589. // Delete the transport interface and the application interfaces
  590. delete g_Transport;
  591. /*
  592. * If an event object was successfully allocated for application interface
  593. * events, then destroy it.
  594. */
  595. if (Transport_Transmit_Event != NULL)
  596. CloseHandle (Transport_Transmit_Event);
  597. /*
  598. * If an event object was successfully allocated for connection deletion pending
  599. * events, then destroy it.
  600. */
  601. if (Connection_Deletion_Pending_Event != NULL)
  602. CloseHandle (Connection_Deletion_Pending_Event);
  603. /*
  604. * If there is a packet coder, then delete it here.
  605. */
  606. delete g_MCSCoder;
  607. delete g_CNPCoder;
  608. // Cleanup the User class
  609. User::CleanupClass();
  610. // Free up the preallocated DataPacket objects.
  611. DataPacket::FreeMemoryPool ();
  612. g_pMCSController = NULL;
  613. }
  614. /*
  615. * ULong APIENTRY ControllerThread ()
  616. *
  617. * Public
  618. *
  619. * Functional Description:
  620. */
  621. ULong APIENTRY ControllerThread (
  622. PVoid controller_ptr)
  623. {
  624. //BOOL bTcpOK;
  625. PController pController = (PController) controller_ptr;
  626. /*
  627. * This is the "C" entry point for the controller thread. All it does is
  628. * use the address passed in to invoke the proper public member function of
  629. * the object that owns the thread. All real work is done in the C++
  630. * member function.
  631. */
  632. /* Set the New Thread's Priority. It's OK if the call fails. */
  633. SetThreadPriority (GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
  634. pController->CreateTCPWindow ();
  635. SetEvent (pController->Synchronization_Event);
  636. if (TCP_Window_Handle != NULL) {
  637. // Initialize QoS
  638. CoInitialize(NULL);
  639. InitializeQoS();
  640. pController->EventLoop ();
  641. /*
  642. * Destroy the TCP window. Since we are here, it has been created
  643. * successfully.
  644. */
  645. pController->DestroyTCPWindow ();
  646. // Notify the Controller destructor that the thread exited
  647. SetEvent (pController->Synchronization_Event);
  648. // Cleanup QoS
  649. DeInitializeQoS();
  650. CoUninitialize();
  651. }
  652. return (0);
  653. }
  654. /*
  655. * Void CreateTCPWindow ()
  656. *
  657. * Private
  658. *
  659. * Functional Description:
  660. * This method registers the class of the TCP window and creates it.
  661. *
  662. * Returns:
  663. * TRUE, if successful. FALSE, otherwise
  664. */
  665. Void Controller::CreateTCPWindow ()
  666. {
  667. /*
  668. * Create the window and the resources needed by the transport
  669. */
  670. WNDCLASS window_class = {
  671. 0, /* style */
  672. WindowProcedure, /* lpfnWndProc */
  673. 0, /* cbClsExtra */
  674. 0, /* cbWndExtra */
  675. 0, /* hInstance */
  676. NULL, /* hIcon */
  677. NULL, /* hCursor */
  678. NULL, /* hbrBackground */
  679. NULL, /* lpszMenuName */
  680. MSMCSTCP_WINDOW_CLASS_NAME /* lpszClassName */
  681. };
  682. /* Get the HINSTANCE for this Thread */
  683. window_class.hInstance = g_hDllInst;
  684. /* Register the hidden window's class */
  685. if(RegisterClass((const WNDCLASS *) (&window_class)) != 0) {
  686. TCP_Window_Handle = CreateWindow(
  687. MSMCSTCP_WINDOW_CLASS_NAME, /* address of registered class name */
  688. MSMCSTCP_WINDOW_CLASS_NAME, /* address of window name */
  689. WS_POPUP, /* window style */
  690. CW_USEDEFAULT, /* horizontal position of window */
  691. CW_USEDEFAULT, /* vertical position of window */
  692. CW_USEDEFAULT, /* window width */
  693. CW_USEDEFAULT, /* window height */
  694. HWND(NULL), /* handle of parent or owner window */
  695. HMENU(NULL), /* handle of menu */
  696. g_hDllInst, /* handle of application instance */
  697. LPVOID(NULL)); /* address of window-creation data */
  698. if(TCP_Window_Handle != NULL) {
  699. #ifndef NO_TCP_TIMER
  700. /* Create a timer */
  701. Timer_ID = SetTimer (TCP_Window_Handle, 0,
  702. (unsigned int) MSMCSTCP_TIMER_DURATION,
  703. (TIMERPROC) NULL);
  704. #endif /* NO_TCP_TIMER */
  705. }
  706. else {
  707. WARNING_OUT (( "Controller::CreateTCPWindow: Error Creating %s", MSMCSTCP_WINDOW_CLASS_NAME));
  708. }
  709. }
  710. else {
  711. WARNING_OUT (( "Controller::CreateTCPWindow: Error Registering %s",MSMCSTCP_WINDOW_CLASS_NAME));
  712. }
  713. }
  714. /*
  715. * Void DestroyTCPWindow ()
  716. *
  717. * Private
  718. *
  719. * Functional Description:
  720. * This method destroys the TCP window and its class.
  721. *
  722. */
  723. Void Controller::DestroyTCPWindow ()
  724. {
  725. /*
  726. * This code clears out the TCP Transport interface.
  727. */
  728. if (TCP_Window_Handle != NULL) {
  729. TRACE_OUT(("Controller::DestroyTCPWindow: Destroying TCP window..."));
  730. #ifndef NO_TCP_TIMER
  731. if (Timer_ID != 0)
  732. KillTimer (TCP_Window_Handle, Timer_ID);
  733. #endif /* NO_TCP_TIMER */
  734. if(DestroyWindow (TCP_Window_Handle) == FALSE)
  735. {
  736. WARNING_OUT (("Controller::DestroyTCPWindow: Error Destroying %s", MSMCSTCP_WINDOW_CLASS_NAME));
  737. }
  738. /* Unregister the Window Class */
  739. if(UnregisterClass(MSMCSTCP_WINDOW_CLASS_NAME, g_hDllInst) == FALSE)
  740. {
  741. WARNING_OUT (("Controller::DestroyTCPWindow: Error Unregistering %s", MSMCSTCP_WINDOW_CLASS_NAME));
  742. }
  743. }
  744. }
  745. /*
  746. * Void EventLoop ()
  747. *
  748. * Public
  749. *
  750. * Functional Description:
  751. */
  752. Void Controller::EventLoop ()
  753. {
  754. HANDLE event_list[NUMBER_OF_EVENTS];
  755. ULong object_signaled;
  756. BOOL bFlushMoreData;
  757. MSG msg;
  758. BOOL fGCCWork;
  759. //
  760. // Externals from GCC.
  761. //
  762. extern HANDLE g_hevGCCOutgoingPDU;
  763. BOOL GCCRetryFlushOutgoingPDU ( void );
  764. /*
  765. * Set the initial timeout interval to infinite
  766. */
  767. Controller_Wait_Timeout = INFINITE;
  768. Controller_Event_Mask = 0;
  769. /*
  770. * Set up the event list (this is used in the Wait call below).
  771. */
  772. event_list[TRANSPORT_TRANSMIT_EVENT] = Transport_Transmit_Event;
  773. event_list[CONNECTION_DELETION_PENDING_EVENT] = Connection_Deletion_Pending_Event;
  774. event_list[GCC_FLUSH_OUTGOING_PDU_EVENT] = g_hevGCCOutgoingPDU;
  775. /*
  776. * Continue looping until this controller closes down.
  777. */
  778. while (TRUE)
  779. {
  780. // Process the TCP window messages.
  781. while (PeekMessage (&msg, TCP_Window_Handle, 0, 0, PM_REMOVE)) {
  782. ASSERT (TCP_Window_Handle == msg.hwnd);
  783. EnterCriticalSection (&g_MCS_Critical_Section);
  784. DispatchMessage (&msg);
  785. LeaveCriticalSection (&g_MCS_Critical_Section);
  786. }
  787. /*
  788. * Go wait for something to happen (or for the timeout to expire,
  789. * which will cause us to poll for unfinished activity).
  790. */
  791. object_signaled = MsgWaitForMultipleObjects (NUMBER_OF_EVENTS, event_list,
  792. FALSE, Controller_Wait_Timeout, QS_ALLINPUT);
  793. //
  794. // Default is that no GCC work needs to be done.
  795. //
  796. fGCCWork = FALSE;
  797. /*
  798. * Wait for the critical section to be available, before performing
  799. * any work on the event.
  800. */
  801. EnterCriticalSection (&g_MCS_Critical_Section);
  802. if(Controller_Closing) {
  803. LeaveCriticalSection (&g_MCS_Critical_Section);
  804. break;
  805. }
  806. /*
  807. * Respond to the event dependent on which event occured.
  808. */
  809. switch (object_signaled) {
  810. case WAIT_TIMEOUT:
  811. fGCCWork = (Controller_Event_Mask & GCC_FLUSH_OUTGOING_PDU_MASK);
  812. /*
  813. * We need to retry an operation.
  814. */
  815. PollMCSDevices ();
  816. break;
  817. case WAIT_OBJECT_0 + CONNECTION_DELETION_PENDING_EVENT:
  818. /*
  819. * If a Connection object has asked to be deleted, then do it.
  820. */
  821. while (Connection_Deletion_Pending)
  822. {
  823. CConnectionList2 Deletion_Pending_Copy(m_ConnectionDeletionList2);
  824. ConnectionHandle connection_handle;
  825. PConnection connection;
  826. Connection_Deletion_Pending = FALSE;
  827. while (NULL != (connection = Deletion_Pending_Copy.Get(&connection_handle)))
  828. {
  829. /*
  830. * Get the handle and pointer to the connection object to
  831. * be deleted. Then remove it from both the connection
  832. * list, and the connection polling list. Finally, delete
  833. * the connection object.
  834. */
  835. m_ConnectionList2.Remove(connection_handle);
  836. m_ConnPollList.Remove(connection);
  837. delete connection; // This could set the Connection_Deletion_Pending flag to TRUE
  838. m_ConnectionDeletionList2.Remove(connection_handle);
  839. }
  840. if (Connection_Deletion_Pending == FALSE)
  841. {
  842. m_ConnectionDeletionList2.Clear();
  843. }
  844. }
  845. break;
  846. case WAIT_OBJECT_0 + TRANSPORT_TRANSMIT_EVENT:
  847. /*
  848. * Iterate through the poll list, asking each connection to
  849. * flush any queued messages.
  850. */
  851. PConnection lpConnection;
  852. bFlushMoreData = FALSE;
  853. Domain_Traffic_Allowed = TRUE;
  854. m_ConnPollList.Reset();
  855. while (NULL != (lpConnection = m_ConnPollList.Iterate()))
  856. {
  857. if (lpConnection->FlushMessageQueue ()) {
  858. bFlushMoreData = TRUE;
  859. /*
  860. * We have flushed the connection, but it has more to send to
  861. * the other end. Normally, we will get an FD_WRITE that allows
  862. * us to resume sending the queued data and will set this event
  863. * again to allow more sending. However, there is a special case
  864. * when the domain traffic is disallowed while a connection is
  865. * coming up. For this case, the timeout has to be small, and
  866. * we need to set the Domain_Traffic_Allowed variable to
  867. * distinguish between the two cases.
  868. */
  869. Domain_Traffic_Allowed &= lpConnection->IsDomainTrafficAllowed();
  870. }
  871. }
  872. UpdateWaitInfo (bFlushMoreData, TRANSPORT_TRANSMIT_INDEX);
  873. break;
  874. case WAIT_OBJECT_0 + GCC_FLUSH_OUTGOING_PDU_EVENT:
  875. fGCCWork = TRUE;
  876. break;
  877. }
  878. // Leave the MCS critical section
  879. LeaveCriticalSection (&g_MCS_Critical_Section);
  880. //
  881. // GCC work is done here WITHOUT MCS critical section.
  882. // The order of critical section in T120 is always GCC in front of MCS.
  883. // If we enter MCS here and enter GCC later in GCCRetryFlushOutgoingPDU(),
  884. // then we introduce a potential deadlock.
  885. //
  886. if (fGCCWork)
  887. {
  888. ASSERT(WAIT_TIMEOUT == object_signaled ||
  889. (WAIT_OBJECT_0 + GCC_FLUSH_OUTGOING_PDU_EVENT) == object_signaled);
  890. bFlushMoreData = GCCRetryFlushOutgoingPDU();
  891. UpdateWaitInfo (bFlushMoreData, GCC_FLUSH_OUTGOING_PDU_INDEX);
  892. }
  893. }
  894. }
  895. /*
  896. * Controller::UpdateWaitInfo ()
  897. *
  898. * Private Function Description
  899. * This routine updates the instance variables Controller_Wait_Timeout
  900. * and Controller_Event_Mask after the processing of an event
  901. * in the EventLoop.
  902. *
  903. * Formal Parameters:
  904. * bMoreData - (i) Flag that informs us whether the msg flush that holds a GCC conference query
  905. * triggered by the event was complete or left msgs
  906. * unprocessed
  907. * EventMask - (i) Tells us which event was processed
  908. *
  909. * Return Value
  910. * None
  911. *
  912. * Side Effects
  913. * Controller_Event_Mask and Controller_Wait_Timeout are updated
  914. *
  915. * Caveats
  916. * None
  917. */
  918. Void Controller::UpdateWaitInfo (
  919. BOOL bMoreData,
  920. unsigned int index)
  921. {
  922. if (bMoreData) {
  923. Controller_Event_Mask |= (0x1 << index);
  924. }
  925. else {
  926. if (0 != Controller_Event_Mask)
  927. Controller_Event_Mask &= ~(0x1 << index);
  928. }
  929. if (0 == Controller_Event_Mask)
  930. Controller_Wait_Timeout = INFINITE;
  931. else if (Controller_Event_Mask & TRANSPORT_MASK) {
  932. if ((Controller_Event_Mask & TRANSPORT_TRANSMIT_MASK) &&
  933. (Domain_Traffic_Allowed == FALSE))
  934. Controller_Wait_Timeout = CONTROLLER_THREAD_TIMEOUT;
  935. else if (Controller_Event_Mask & TRANSPORT_RECEIVE_MASK)
  936. Controller_Wait_Timeout = TRANSPORT_RECEIVE_TIMEOUT;
  937. else
  938. Controller_Wait_Timeout = TRANSPORT_TRANSMIT_TIMEOUT;
  939. }
  940. else
  941. Controller_Wait_Timeout = CONTROLLER_THREAD_TIMEOUT;
  942. }
  943. /*
  944. * ULong OwnerCallback ()
  945. *
  946. * Public
  947. *
  948. * Functional Description:
  949. * This is the owner callback entry function for the controller. It is
  950. * through this function that all of the controller's "children" make
  951. * requests of the controller. Rather than put a lot of otherwise
  952. * unrelated code in one place, this function merely unpacks the
  953. * parameters and sends them to a different private member function
  954. * for each owner callback.
  955. *
  956. * Sometimes the parameters are packed directly into the two long
  957. * parameters, and sometimes one of the parameters is a pointer to a
  958. * structure that contains more data. This function takes care of that
  959. * distinction, and passes the appropriate data along to each separate
  960. * member function.
  961. */
  962. void Controller::HandleTransportDataIndication
  963. (
  964. PTransportData pTransport_data
  965. )
  966. {
  967. // Wait for the critical section before attempting any processing
  968. EnterCriticalSection(&g_MCS_Critical_Section);
  969. TransportDataIndication(pTransport_data->transport_connection,
  970. pTransport_data->user_data,
  971. pTransport_data->user_data_length);
  972. // We need to free up the transport buffer with the original data.
  973. FreeMemory(pTransport_data->memory);
  974. // Release the critical section
  975. LeaveCriticalSection(&g_MCS_Critical_Section);
  976. }
  977. void Controller::HandleTransportWaitUpdateIndication
  978. (
  979. BOOL fMoreData
  980. )
  981. {
  982. // Wait for the critical section before attempting any processing
  983. EnterCriticalSection(&g_MCS_Critical_Section);
  984. /*
  985. * We are setting ourselves to wake up again after some time
  986. * because there has been a read message that could not allocate any
  987. * buffers.
  988. */
  989. UpdateWaitInfo(fMoreData, TRANSPORT_RECEIVE_INDEX);
  990. // Release the critical section
  991. LeaveCriticalSection(&g_MCS_Critical_Section);
  992. }
  993. #ifdef NM_RESET_DEVICE
  994. MCSError Controller::HandleAppletResetDevice
  995. (
  996. PResetDeviceInfo pDevInfo
  997. )
  998. {
  999. // Wait for the critical section before attempting any processing
  1000. EnterCriticalSection(&g_MCS_Critical_Section);
  1001. MCSError rc = ApplicationResetDevice(pDevInfo->device_identifier);
  1002. // Release the critical section
  1003. LeaveCriticalSection(&g_MCS_Critical_Section);
  1004. return rc;
  1005. }
  1006. #endif // NM_RESET_DEVICE
  1007. MCSError Controller::HandleAppletCreateDomain
  1008. (
  1009. GCCConfID *domain_selector
  1010. )
  1011. {
  1012. // Wait for the critical section before attempting any processing
  1013. EnterCriticalSection(&g_MCS_Critical_Section);
  1014. MCSError rc = ApplicationCreateDomain(domain_selector);
  1015. // Release the critical section
  1016. LeaveCriticalSection(&g_MCS_Critical_Section);
  1017. return rc;
  1018. }
  1019. MCSError Controller::HandleAppletDeleteDomain
  1020. (
  1021. GCCConfID *domain_selector
  1022. )
  1023. {
  1024. // Wait for the critical section before attempting any processing
  1025. EnterCriticalSection(&g_MCS_Critical_Section);
  1026. MCSError rc = ApplicationDeleteDomain(domain_selector);
  1027. // Release the critical section
  1028. LeaveCriticalSection(&g_MCS_Critical_Section);
  1029. return rc;
  1030. }
  1031. MCSError Controller::HandleAppletConnectProviderRequest
  1032. (
  1033. PConnectRequestInfo pReqInfo
  1034. )
  1035. {
  1036. // Wait for the critical section before attempting any processing
  1037. EnterCriticalSection(&g_MCS_Critical_Section);
  1038. MCSError rc = ApplicationConnectProviderRequest(pReqInfo);
  1039. // Release the critical section
  1040. LeaveCriticalSection(&g_MCS_Critical_Section);
  1041. return rc;
  1042. }
  1043. MCSError Controller::HandleAppletConnectProviderResponse
  1044. (
  1045. PConnectResponseInfo pRespInfo
  1046. )
  1047. {
  1048. // Wait for the critical section before attempting any processing
  1049. EnterCriticalSection(&g_MCS_Critical_Section);
  1050. MCSError rc = ApplicationConnectProviderResponse(
  1051. pRespInfo->connection_handle,
  1052. pRespInfo->domain_selector,
  1053. pRespInfo->domain_parameters,
  1054. pRespInfo->result,
  1055. pRespInfo->user_data,
  1056. pRespInfo->user_data_length);
  1057. // Release the critical section
  1058. LeaveCriticalSection(&g_MCS_Critical_Section);
  1059. return rc;
  1060. }
  1061. MCSError Controller::HandleAppletDisconnectProviderRequest
  1062. (
  1063. ConnectionHandle hConn
  1064. )
  1065. {
  1066. // Wait for the critical section before attempting any processing
  1067. EnterCriticalSection(&g_MCS_Critical_Section);
  1068. MCSError rc = ApplicationDisconnectProviderRequest(hConn);
  1069. // Release the critical section
  1070. LeaveCriticalSection(&g_MCS_Critical_Section);
  1071. return rc;
  1072. }
  1073. MCSError Controller::HandleAppletAttachUserRequest
  1074. (
  1075. PAttachRequestInfo pReqInfo
  1076. )
  1077. {
  1078. // Wait for the critical section before attempting any processing
  1079. EnterCriticalSection(&g_MCS_Critical_Section);
  1080. MCSError rc = ApplicationAttachUserRequest(pReqInfo->domain_selector,
  1081. pReqInfo->ppuser);
  1082. // Release the critical section
  1083. LeaveCriticalSection(&g_MCS_Critical_Section);
  1084. return rc;
  1085. }
  1086. void Controller::HandleConnDeleteConnection
  1087. (
  1088. ConnectionHandle hConn
  1089. )
  1090. {
  1091. // Wait for the critical section before attempting any processing
  1092. EnterCriticalSection(&g_MCS_Critical_Section);
  1093. ConnectionDeleteConnection(hConn);
  1094. // Release the critical section
  1095. LeaveCriticalSection(&g_MCS_Critical_Section);
  1096. }
  1097. void Controller::HandleConnConnectProviderConfirm
  1098. (
  1099. PConnectConfirmInfo pConfirmInfo,
  1100. ConnectionHandle hConn
  1101. )
  1102. {
  1103. // Wait for the critical section before attempting any processing
  1104. EnterCriticalSection(&g_MCS_Critical_Section);
  1105. ConnectionConnectProviderConfirm(hConn,
  1106. pConfirmInfo->domain_parameters,
  1107. pConfirmInfo->result,
  1108. pConfirmInfo->memory);
  1109. // Release the critical section
  1110. LeaveCriticalSection(&g_MCS_Critical_Section);
  1111. }
  1112. void Controller::HandleTransportDisconnectIndication
  1113. (
  1114. TransportConnection TrnsprtConn,
  1115. ULONG *pnNotify
  1116. )
  1117. {
  1118. // Wait for the critical section before attempting any processing
  1119. EnterCriticalSection(&g_MCS_Critical_Section);
  1120. TransportDisconnectIndication(TrnsprtConn);
  1121. // Release the critical section
  1122. LeaveCriticalSection(&g_MCS_Critical_Section);
  1123. }
  1124. #ifdef TSTATUS_INDICATION
  1125. void Controller::HandleTransportStatusIndication
  1126. (
  1127. PTransportStatus pStatus
  1128. )
  1129. {
  1130. // Wait for the critical section before attempting any processing
  1131. EnterCriticalSection(&g_MCS_Critical_Section);
  1132. TransportStatusIndication(pStatus);
  1133. // Release the critical section
  1134. LeaveCriticalSection(&g_MCS_Critical_Section);
  1135. }
  1136. #endif
  1137. #ifdef NM_RESET_DEVICE
  1138. /*
  1139. * ULong ApplicationResetDevice ()
  1140. *
  1141. * Private
  1142. *
  1143. * Functional Description:
  1144. * This function is used to send a reset command to a specified transport
  1145. * stack. MCS performs no processing on this command except to pass it
  1146. * through.
  1147. *
  1148. * Formal Parameters:
  1149. * device_identifier
  1150. * This is an ASCII string that is passed through to the transport
  1151. * stack to effect the reset. It will typically contain information
  1152. * identifying which device within the stack is to be reset.
  1153. *
  1154. * Return Value:
  1155. * MCS_NO_ERROR
  1156. * Everything worked fine.
  1157. * MCS_INVALID_PARAMETER
  1158. * The specified transport stack does not exist.
  1159. *
  1160. * Side Effects:
  1161. * None.
  1162. *
  1163. * Caveats:
  1164. * None.
  1165. */
  1166. ULong Controller::ApplicationResetDevice (
  1167. PChar device_identifier)
  1168. {
  1169. TransportError transport_error;
  1170. MCSError return_value;
  1171. ASSERT (g_Transport != NULL);
  1172. /*
  1173. * Forward the reset device command to the transport interface
  1174. * object.
  1175. */
  1176. TRACE_OUT(("Controller::ApplicationResetDevice: "
  1177. "sending ResetDevice to transport interface"));
  1178. transport_error = g_Transport->ResetDevice (device_identifier);
  1179. /*
  1180. * Set the return value appropriate for the value returned from the
  1181. * transport call.
  1182. */
  1183. switch (transport_error)
  1184. {
  1185. case TRANSPORT_ILLEGAL_COMMAND:
  1186. return_value = MCS_INVALID_PARAMETER;
  1187. break;
  1188. case TRANSPORT_MEMORY_FAILURE:
  1189. return_value = MCS_ALLOCATION_FAILURE;
  1190. break;
  1191. default:
  1192. return_value = MCS_NO_ERROR;
  1193. }
  1194. //
  1195. // Remove this connection from the connection list
  1196. //
  1197. PConnection connection;
  1198. ConnectionHandle connection_handle;
  1199. while (NULL != (connection = m_ConnectionList2.Iterate(&connection_handle)))
  1200. {
  1201. if (0 == ::My_strcmpA(connection->GetCalledAddress(), device_identifier))
  1202. {
  1203. PNodeControllerMessage node_controller_message;
  1204. DBG_SAVE_FILE_LINE
  1205. node_controller_message = new NodeControllerMessage;
  1206. if (node_controller_message != NULL) {
  1207. /*
  1208. * Fill out the node controller message structure to indicate the
  1209. * disconnect.
  1210. */
  1211. node_controller_message->message_type =
  1212. MCS_DISCONNECT_PROVIDER_INDICATION;
  1213. node_controller_message->u.disconnect_provider_indication.
  1214. connection_handle = (ConnectionHandle) connection_handle;
  1215. node_controller_message->u.disconnect_provider_indication.
  1216. reason = REASON_DOMAIN_DISCONNECTED;
  1217. node_controller_message->memory = NULL;
  1218. /*
  1219. * Put the message into the control queue to be sent to the node
  1220. * controller during the next heartbeat.
  1221. */
  1222. AddToMessageQueue (node_controller_message);
  1223. }
  1224. else
  1225. ERROR_OUT (("Controller::ApplicationResetDevice: "
  1226. "failed to allocate node controller msg"));
  1227. }
  1228. }
  1229. return ((ULong) return_value);
  1230. }
  1231. #endif //NM_RESET_DEVICE
  1232. /*
  1233. * Controller::PollMCSDevices ()
  1234. *
  1235. * Public Function Description
  1236. * This is the MCS controller's heartbeat. It will call the heartbeat
  1237. * equivalent functions for the Application SAPs, the connections and
  1238. * the users.
  1239. */
  1240. Void Controller::PollMCSDevices()
  1241. {
  1242. BOOL bFlushMoreData;
  1243. if (Controller_Event_Mask & TRANSPORT_TRANSMIT_MASK) {
  1244. /*
  1245. * Iterate through the poll list, asking each connection to
  1246. * flush any queued messages.
  1247. */
  1248. PConnection lpConnection;
  1249. bFlushMoreData = FALSE;
  1250. Domain_Traffic_Allowed = TRUE;
  1251. m_ConnPollList.Reset();
  1252. while (NULL != (lpConnection = m_ConnPollList.Iterate()))
  1253. {
  1254. if (lpConnection->FlushMessageQueue ()) {
  1255. bFlushMoreData = TRUE;
  1256. /*
  1257. * We have flushed the connection, but it has more to send to
  1258. * the other end. Normally, we will get an FD_WRITE that allows
  1259. * us to resume sending the queued data and will set this event
  1260. * again to allow more sending. However, there is a special case
  1261. * when the domain traffic is disallowed while a connection is
  1262. * coming up. For this case, the timeout has to be small, and
  1263. * we need to set the Domain_Traffic_Allowed variable to
  1264. * distinguish between the two cases.
  1265. */
  1266. Domain_Traffic_Allowed &= lpConnection->IsDomainTrafficAllowed();
  1267. }
  1268. }
  1269. UpdateWaitInfo (bFlushMoreData, TRANSPORT_TRANSMIT_INDEX);
  1270. }
  1271. if (Controller_Event_Mask & TRANSPORT_RECEIVE_MASK) {
  1272. ASSERT (g_Transport);
  1273. g_Transport->ReceiveBufferAvailable();
  1274. }
  1275. }
  1276. /*
  1277. * MCSError ApplicationCreateDomain ()
  1278. *
  1279. * Private
  1280. *
  1281. * Functional Description:
  1282. * This request comes through one of the application interface objects.
  1283. * the only parameter is a domain selector. If a domain with that
  1284. * selector does not currently exist, it will be created.
  1285. *
  1286. * A domain must be created before user attachments or MCS connections can
  1287. * be created.
  1288. *
  1289. * Formal Parameters:
  1290. * domain_selector (i)
  1291. * This is the domain selector for the new domain.
  1292. * domain_selector_length (i)
  1293. * This is the length of the above domain selector.
  1294. *
  1295. * Return Value:
  1296. * MCS_NO_ERROR
  1297. * The domain was successfully created.
  1298. * MCS_ALLOCATION_FAILURE
  1299. * A memory allocation failure prevented the successful creation of
  1300. * the new domain.
  1301. * MCS_DOMAIN_ALREADY_EXISTS
  1302. * The named domain already exists.
  1303. *
  1304. * Side Effects:
  1305. * A logical domain now exists that can accomodate both user attachments
  1306. * and MCS connections.
  1307. *
  1308. * Caveats:
  1309. * None.
  1310. */
  1311. MCSError Controller::ApplicationCreateDomain
  1312. (
  1313. GCCConfID *domain_selector
  1314. )
  1315. {
  1316. PDomain domain;
  1317. MCSError return_value;
  1318. /*
  1319. * Check to see if the requested domain already exists. If so, then
  1320. * do not attempt to create a new one. Just return the appropriate
  1321. * return value.
  1322. */
  1323. if (m_DomainList2.Find(*domain_selector) == FALSE)
  1324. {
  1325. /*
  1326. * The next action is to instantiate a new domain object. This
  1327. * is initially an empty domain that will be associated with the
  1328. * user provided domain selector.
  1329. */
  1330. DBG_SAVE_FILE_LINE
  1331. domain = new Domain ();
  1332. if (domain != NULL)
  1333. {
  1334. /*
  1335. * If everything was allocated successfully, then simply put
  1336. * the new domain into the domain list dictionary. and set the
  1337. * return value to indicate success.
  1338. */
  1339. TRACE_OUT (("Controller::ApplicationCreateDomain: "
  1340. "domain creation successful"));
  1341. m_DomainList2.Append(*domain_selector, domain);
  1342. return_value = MCS_NO_ERROR;
  1343. }
  1344. else
  1345. {
  1346. /*
  1347. * Set the return value to indication a memory allocation failure.
  1348. */
  1349. WARNING_OUT (("Controller::ApplicationCreateDomain: "
  1350. "domain creation failed"));
  1351. return_value = MCS_ALLOCATION_FAILURE;
  1352. }
  1353. }
  1354. else
  1355. {
  1356. /*
  1357. * The domain was not created since it already exists.
  1358. */
  1359. WARNING_OUT (("Controller::ApplicationCreateDomain: "
  1360. "domain already exists"));
  1361. return_value = MCS_DOMAIN_ALREADY_EXISTS;
  1362. }
  1363. return (return_value);
  1364. }
  1365. /*
  1366. * MCSError ApplicationDeleteDomain ()
  1367. *
  1368. * Private
  1369. *
  1370. * Functional Description:
  1371. * This request comes from one of the application interface objects. It
  1372. * instructs the controller to delete an existing domain, with the only
  1373. * parameter identifying the domain to be deleted. If the domain exists,
  1374. * then it will be destroyed.
  1375. *
  1376. * Note that all user attachments and MCS connections that are attached
  1377. * to the domain when it is deleted will also be deleted (automatically).
  1378. *
  1379. * Formal Parameters:
  1380. * domain_selector (i)
  1381. * This is the domain selector for the domain to be deleted.
  1382. * domain_selector_length (i)
  1383. * This is the length of the above domain selector.
  1384. *
  1385. * Return Value:
  1386. * MCS_NO_ERROR
  1387. * The domain was successfully deleted.
  1388. * MCS_NO_SUCH_DOMAIN
  1389. * There is no domain associated with the passed in domain selector.
  1390. *
  1391. * Side Effects:
  1392. * When the domain is deleted, all resources used by it (including user
  1393. * attachments and MCS connections) will be deleted as well.
  1394. *
  1395. * Caveats:
  1396. * None.
  1397. */
  1398. MCSError Controller::ApplicationDeleteDomain
  1399. (
  1400. GCCConfID *domain_selector
  1401. )
  1402. {
  1403. PDomain domain;
  1404. MCSError return_value;
  1405. /*
  1406. * Check to see if the domain selector refers to a valid domain.
  1407. */
  1408. if (NULL != (domain = m_DomainList2.Remove(*domain_selector)))
  1409. {
  1410. /*
  1411. * If the domain selector is valid, then remove the domain from the
  1412. * dictionary and delete it. Everything else happens automatically
  1413. * as a result of destroying the domain object.
  1414. */
  1415. TRACE_OUT (("Controller::ApplicationDeleteDomain: deleting domain"));
  1416. delete domain;
  1417. return_value = MCS_NO_ERROR;
  1418. }
  1419. else
  1420. {
  1421. /*
  1422. * If the domain selector is not in the dictionary, then report the
  1423. * error to the caller.
  1424. */
  1425. ERROR_OUT (("Controller::ApplicationDeleteDomain: invalid domain"));
  1426. return_value = MCS_NO_SUCH_DOMAIN;
  1427. }
  1428. return (return_value);
  1429. }
  1430. /*
  1431. * MCSError ApplicationConnectProviderRequest ()
  1432. *
  1433. * Private
  1434. *
  1435. * Functional Description:
  1436. * This request originates from one of the application interface objects.
  1437. * This happens as the result of the node controller issuing a
  1438. * ConnectProviderRequest to whichever application interface object
  1439. * that it is attached to. If the parameters are valid, then a new
  1440. * connection object will be created to represent the outbound connection.
  1441. * This will result in the connection object calling the proper transport
  1442. * interface to create the transport connection, etc.
  1443. *
  1444. * Formal Parameters:
  1445. * pcriConnectRequestInfo (i)
  1446. * Contains all the needed info to complete the Connect Provider Request.
  1447. *
  1448. * Return Value:
  1449. * MCS_NO_ERROR
  1450. * The request was successful. The connection handle for the newly
  1451. * created connection has been stored at the address passed into this
  1452. * request (see parameter list above). Note that this connection
  1453. * handle can be used to destroy the new connection immediately, even
  1454. * if the physical connection has not yet been established. This
  1455. * allows the node controller to abort a dial in-progress by calling
  1456. * DisconnectProviderRequest.
  1457. * MCS_INVALID_PARAMETER
  1458. * The format of the called address field is incorrect.
  1459. * MCS_ALLOCATION_FAILURE
  1460. * The request was unable to complete successfully due to a memory
  1461. * allocation failure (either in MCS or the transport layer).
  1462. * MCS_TRANSPORT_NOT_READY
  1463. * The transport layer could not process the request because it is not
  1464. * ready. This usually means that initialization has not successfully
  1465. * completed.
  1466. * MCS_DOMAIN_NOT_HIERARCHICAL
  1467. * This request is attempting to create an upward connection to a
  1468. * domain that already has an upward connection (which is not valid).
  1469. * MCS_NO_SUCH_DOMAIN
  1470. * The specified local domain does not exist within this provider.
  1471. *
  1472. * Side Effects:
  1473. * An outbound connect establishment process is begun.
  1474. *
  1475. * Caveats:
  1476. * None.
  1477. */
  1478. MCSError Controller::ApplicationConnectProviderRequest (
  1479. PConnectRequestInfo pcriConnectRequestInfo)
  1480. {
  1481. PDomain domain;
  1482. BOOL bTransportIdFound;
  1483. PConnection connection;
  1484. MCSError return_value;
  1485. PChar called_address = pcriConnectRequestInfo->called_address;
  1486. PConnectionHandle connection_handle = pcriConnectRequestInfo->connection_handle;
  1487. /*
  1488. * Make sure the local domain specified corresponds to an existing
  1489. * domain.
  1490. */
  1491. ASSERT(sizeof(GCCConfID) == sizeof(*(pcriConnectRequestInfo->calling_domain)));
  1492. if (NULL != (domain = m_DomainList2.Find(*(pcriConnectRequestInfo->calling_domain))))
  1493. {
  1494. /*
  1495. * Check to make sure that the requested connection is valid.
  1496. * Specifically, make sure that this is not a request for an upward
  1497. * connection to a domain that already has an upward connection.
  1498. * This would result in a non-hierarchical domain, which is illegal.
  1499. */
  1500. if ((pcriConnectRequestInfo->upward_connection == FALSE) || (domain->IsTopProvider ()))
  1501. {
  1502. PChar pColon;
  1503. /*
  1504. * Look for the colon that separates the identifier from the
  1505. * address.
  1506. */
  1507. for (bTransportIdFound = FALSE, pColon = called_address; *pColon; pColon++)
  1508. if (*pColon == ':') {
  1509. bTransportIdFound = TRUE;
  1510. break;
  1511. }
  1512. /*
  1513. * Make sure that there was a colon before continuing.
  1514. */
  1515. if (bTransportIdFound)
  1516. {
  1517. ASSERT (g_Transport != NULL);
  1518. called_address = pColon + 1;
  1519. /*
  1520. * Allocate an unused connection handle to be
  1521. * associated with the new MCS connection.
  1522. */
  1523. *connection_handle = AllocateConnectionHandle ();
  1524. /*
  1525. * Create a new connection object. The constructor
  1526. * parameters provide everything that the connection
  1527. * object will need to create a new outbound MCS
  1528. * connection.
  1529. */
  1530. DBG_SAVE_FILE_LINE
  1531. connection = new Connection (domain,
  1532. *connection_handle,
  1533. pcriConnectRequestInfo->calling_domain,
  1534. pcriConnectRequestInfo->called_domain,
  1535. called_address,
  1536. pcriConnectRequestInfo->fSecure,
  1537. pcriConnectRequestInfo->upward_connection,
  1538. pcriConnectRequestInfo->domain_parameters,
  1539. pcriConnectRequestInfo->user_data,
  1540. pcriConnectRequestInfo->user_data_length,
  1541. &return_value);
  1542. /*
  1543. * Check to see if the allocation of the connection
  1544. * worked.
  1545. */
  1546. if (connection != NULL)
  1547. {
  1548. /*
  1549. * Even if the connection object was allocated
  1550. * successfully, it is still possible that an error
  1551. * occurred while it was trying to initialize. So
  1552. * check the return value from the contructor.
  1553. */
  1554. if (return_value == MCS_NO_ERROR)
  1555. {
  1556. /*
  1557. * Put the connection into the connection list
  1558. * dictionary.
  1559. */
  1560. TRACE_OUT (("Controller::ApplicationConnectProviderRequest: "
  1561. "new connection created"));
  1562. m_ConnectionList2.Insert(*connection_handle, connection);
  1563. m_ConnPollList.Append(connection);
  1564. }
  1565. else
  1566. {
  1567. /*
  1568. * If the connection object was successfully
  1569. * allocated, but its initialization failed,
  1570. * then it is necessary to destroy the faulty
  1571. * connection and return the appropriate error
  1572. * to the caller.
  1573. */
  1574. WARNING_OUT (("Controller::ApplicationConnectProviderRequest: "
  1575. "deleting faulty connection"));
  1576. delete connection;
  1577. }
  1578. }
  1579. else
  1580. {
  1581. /*
  1582. * The allocation of the connection object has
  1583. * failed. Simply return the appropriate error and
  1584. * abort the request.
  1585. */
  1586. WARNING_OUT (("Controller::ApplicationConnectProviderRequest: "
  1587. "connection allocation failed"));
  1588. return_value = MCS_ALLOCATION_FAILURE;
  1589. }
  1590. // Put back the colon in the "called_address"
  1591. *pColon = ':';
  1592. }
  1593. else
  1594. {
  1595. /*
  1596. * There was not a colon in the called address, so MCS has
  1597. * no way of extracting the transport identifier. The request
  1598. * must therefore fail.
  1599. */
  1600. ERROR_OUT (("Controller::ApplicationConnectProviderRequest: "
  1601. "no colon in called address"));
  1602. return_value = MCS_INVALID_PARAMETER;
  1603. }
  1604. }
  1605. else
  1606. {
  1607. /*
  1608. * The domain already has an upward connection (or one pending).
  1609. * This request is therefore invalid and must be rejected.
  1610. */
  1611. ERROR_OUT (("Controller::ApplicationConnectProviderRequest: "
  1612. "domain not hierarchical"));
  1613. return_value = MCS_DOMAIN_NOT_HIERARCHICAL;
  1614. }
  1615. }
  1616. else
  1617. {
  1618. /*
  1619. * If the local domain selector does not correspond to a valid
  1620. * domain in this provider, then fail the request immediately by
  1621. * returning the appropriate error.
  1622. */
  1623. ERROR_OUT (("Controller::ApplicationConnectProviderRequest: "
  1624. "invalid local domain"));
  1625. return_value = MCS_NO_SUCH_DOMAIN;
  1626. }
  1627. return (return_value);
  1628. }
  1629. /*
  1630. * MCSError ApplicationConnectProviderResponse ()
  1631. *
  1632. * Private
  1633. *
  1634. * Functional Description:
  1635. * This request originates from one of the application interface objects.
  1636. * This happens as the result of the node controller issuing a
  1637. * ConnectProviderResponse to whichever application interface object
  1638. * that it is attached to. If the connection handle is valid, and the
  1639. * local domain still exists, then that domain will be told whether or not
  1640. * the incoming connection was accepted. This allows it to repsond
  1641. * appropriately.
  1642. *
  1643. * Formal Parameters:
  1644. * connection_handle (i)
  1645. * This identifies the connection from which a previous connect
  1646. * provider indication originated. This request essentially states
  1647. * whether or not this incoming connection is accepted.
  1648. * domain_selector (i)
  1649. * This is the domain selector of the domain that the node controller
  1650. * wishes to bind the incoming connection to.
  1651. * domain_selector_length (i)
  1652. * This is the length of the above domain selector.
  1653. * domain_parameters (i)
  1654. * This is a pointer to a structure containing the domain parameters
  1655. * that the node controller wishes to use for this connection.
  1656. * result (i)
  1657. * This is the result to be sent to the remote provider. Coming
  1658. * from the node controller this should be either RESULT_SUCCESSFUL
  1659. * or RESULT_USER_REJECTED. If it is anything but RESULT_SUCCESSFUL,
  1660. * the associated connection will be immediately destroyed.
  1661. * user_data (i)
  1662. * This is the address of the user data that is to be sent in the
  1663. * connect response PDU to the remote provider.
  1664. * user_data_length (i)
  1665. * This is the length of the user data to be sent in the connect
  1666. * response PDU to the remote provider.
  1667. *
  1668. * Return Value:
  1669. * MCS_NO_ERROR
  1670. * The response was sent to the appropriate domain successfully.
  1671. * MCS_DOMAIN_PARAMETERS_UNACCEPTABLE
  1672. * This indicates that there is no overlap in the min and max
  1673. * parameters specified by the remote node, and the min and max
  1674. * parameters acceptable to the specified domain. Therefore, no
  1675. * connection is possible. This does NOT indicate that there is
  1676. * anything wrong with the specified target parameters (which are
  1677. * just suggested values anyway).
  1678. * MCS_ALLOCATION_FAILURE
  1679. * The response failed due to a memory allocation failure.
  1680. * MCS_NO_SUCH_DOMAIN
  1681. * This indicates that the domain associated with the pending
  1682. * response has been deleted since the indication was sent.
  1683. * MCS_NO_SUCH_CONNECTION
  1684. * This indicates that the connection has been lost since the
  1685. * indication was issued.
  1686. * MCS_DOMAIN_NOT_HIERARCHICAL
  1687. * This request is attempting to create an upward connection to a
  1688. * domain that already has an upward connection (which is not valid).
  1689. *
  1690. * Side Effects:
  1691. * If the response is other than RESULT_SUCCESSFUL, the transport
  1692. * connection that conveys the connect response PDU will be severed.
  1693. *
  1694. * Caveats:
  1695. * None.
  1696. */
  1697. MCSError Controller::ApplicationConnectProviderResponse (
  1698. ConnectionHandle connection_handle,
  1699. GCCConfID *domain_selector,
  1700. PDomainParameters domain_parameters,
  1701. Result result,
  1702. PUChar user_data,
  1703. ULong user_data_length)
  1704. {
  1705. PConnectionPending connection_pending;
  1706. TransportConnection transport_connection;
  1707. BOOL upward_connection;
  1708. PDomain domain;
  1709. PConnection connection;
  1710. MCSError return_value;
  1711. /*
  1712. * Check to see if the connection handle corresponds to a connection
  1713. * that is awaiting a response.
  1714. */
  1715. if (NULL != (connection_pending = m_ConnPendingList2.Find(connection_handle)))
  1716. {
  1717. /*
  1718. * Get the address of the structure containing information about the
  1719. * pending connection. Then load the contained information into
  1720. * automatic variables for easier manipulation.
  1721. */
  1722. transport_connection = connection_pending->transport_connection;
  1723. upward_connection = connection_pending->upward_connection;
  1724. if (domain_parameters == NULL)
  1725. domain_parameters = &connection_pending->domain_parameters;
  1726. /*
  1727. * See if the node controller has elected to accept or reject the
  1728. * incoming connection. If it is accepted, then the response must
  1729. * be sent through the appropriate domain object. If it is
  1730. * rejected, then the response can be sent directly to the
  1731. * connection object (which will then delete itself).
  1732. */
  1733. if (result == RESULT_SUCCESSFUL)
  1734. {
  1735. /*
  1736. * See if the specified domain is valid, before trying to send
  1737. * the response to it.
  1738. */
  1739. if (NULL != (domain = m_DomainList2.Find(*domain_selector)))
  1740. {
  1741. /*
  1742. * Check to make sure that the requested connection is valid.
  1743. * Specifically, make sure that this is not a request for an
  1744. * upward connection to a domain that already has an upward
  1745. * connection. This would result in a non-hierarchical domain,
  1746. * which is illegal.
  1747. */
  1748. if ((upward_connection == FALSE) || (domain->IsTopProvider ()))
  1749. {
  1750. /*
  1751. * Create the connection object that will be responsible
  1752. * for the inbound connection. It will automatically issue
  1753. * a ConnectResponse during construction.
  1754. */
  1755. DBG_SAVE_FILE_LINE
  1756. connection = new Connection (domain,
  1757. connection_handle, transport_connection,
  1758. upward_connection, domain_parameters,
  1759. &connection_pending->minimum_domain_parameters,
  1760. &connection_pending->maximum_domain_parameters,
  1761. user_data, user_data_length,
  1762. &return_value);
  1763. if (connection != NULL)
  1764. {
  1765. if (return_value == MCS_NO_ERROR)
  1766. {
  1767. /*
  1768. * Everything worked fine. Remove the connection
  1769. * handle from the pending list, and put the newly
  1770. * created connection object into the active
  1771. * connection list.
  1772. */
  1773. TRACE_OUT(("Controller::ApplicationConnectProviderResponse: "
  1774. "connection created successfully"));
  1775. m_ConnPendingList2.Remove(connection_handle);
  1776. delete connection_pending;
  1777. m_ConnectionList2.Insert(connection_handle, connection);
  1778. m_ConnPollList.Append(connection);
  1779. }
  1780. else
  1781. {
  1782. /*
  1783. * The contructor failed, which probably indicates
  1784. * an allocation failure. Report this to the node
  1785. * controller, and delete the faulty connection
  1786. * object.
  1787. */
  1788. WARNING_OUT (("Controller::ApplicationConnectProviderResponse: "
  1789. "connection constructor failed"));
  1790. delete connection;
  1791. }
  1792. }
  1793. else
  1794. {
  1795. /*
  1796. * The allocation failed. Report this to the node
  1797. * controller.
  1798. */
  1799. WARNING_OUT (("Controller::ApplicationConnectProviderResponse: "
  1800. "connection constructor failed"));
  1801. return_value = MCS_ALLOCATION_FAILURE;
  1802. }
  1803. }
  1804. else
  1805. {
  1806. /*
  1807. * The domain already has an upward connection (or one
  1808. * pending). This request is therefore invalid and must be
  1809. * rejected.
  1810. */
  1811. ERROR_OUT (("Controller::ApplicationConnectProviderResponse:"
  1812. " domain not hierarchical"));
  1813. return_value = MCS_DOMAIN_NOT_HIERARCHICAL;
  1814. }
  1815. }
  1816. else
  1817. {
  1818. /*
  1819. * If the indicated domain is not valid, then simply return
  1820. * the appropriate error.
  1821. */
  1822. WARNING_OUT (("Controller::ApplicationConnectProviderResponse: "
  1823. "invalid domain"));
  1824. return_value = MCS_NO_SUCH_DOMAIN;
  1825. }
  1826. }
  1827. else
  1828. {
  1829. /*
  1830. * The node controller has elected to reject the incoming
  1831. * connection. It is therefore not necessary to create a
  1832. * connection object. Send the connect response directly to
  1833. * the transport interface object, and then disconnect the
  1834. * transport connection.
  1835. */
  1836. TRACE_OUT (("Controller::ApplicationConnectProviderResponse: connection rejected"));
  1837. ASSERT (g_Transport);
  1838. ConnectResponse (transport_connection, result,
  1839. domain_parameters, 0, user_data, user_data_length);
  1840. g_Transport->DisconnectRequest (transport_connection);
  1841. /*
  1842. * Remove the connection handle from the pending list, and
  1843. * delete the structure that was holding information about
  1844. * the pending connection.
  1845. */
  1846. m_ConnPendingList2.Remove(connection_handle);
  1847. delete connection_pending;
  1848. return_value = MCS_NO_ERROR;
  1849. }
  1850. }
  1851. else
  1852. {
  1853. /*
  1854. * If the connection handle is no longer valid, then fail the request
  1855. * with the appropriate error.
  1856. */
  1857. WARNING_OUT (("Controller::ApplicationConnectProviderResponse: "
  1858. "invalid connection"));
  1859. return_value = MCS_NO_SUCH_CONNECTION;
  1860. }
  1861. return (return_value);
  1862. }
  1863. /*
  1864. * MCSError ApplicationDisconnectProviderRequest ()
  1865. *
  1866. * Private
  1867. *
  1868. * Functional Description:
  1869. * This request originates from one of the application interface objects.
  1870. * This happens as the result of the node controller issuing a
  1871. * DisconnectProviderRequest to whichever application interface object
  1872. * that it is attached to. If the connection handle is valid, then the
  1873. * connection object wil be destroyed, which will break the transport
  1874. * connections associated with it.
  1875. *
  1876. * Formal Parameters:
  1877. * connection_handle (i)
  1878. * This identifies the connection to be destroyed.
  1879. *
  1880. * Return Value:
  1881. * MCS_NO_ERROR
  1882. * The named connection has been successfully deleted.
  1883. * MCS_NO_SUCH_CONNECTION
  1884. * The connection handle is invalid.
  1885. *
  1886. * Side Effects:
  1887. * One or more transport connections will be broken. Furthermore, if
  1888. * this is an upward connection for a domain, then the domain itself
  1889. * will be eradicated (all attachments and connections will be severed).
  1890. *
  1891. * Caveats:
  1892. * None.
  1893. */
  1894. MCSError Controller::ApplicationDisconnectProviderRequest (
  1895. ConnectionHandle connection_handle)
  1896. {
  1897. MCSError return_value;
  1898. PConnection connection;
  1899. PConnectionPending connection_pending;
  1900. /*
  1901. * Check to see if the connection handle refers to an existing connection.
  1902. */
  1903. if (NULL != (connection = m_ConnectionList2.Find(connection_handle)))
  1904. {
  1905. /*
  1906. * If the connection handle is valid, then delete the associated
  1907. * connection and remove it from the connection dictionary. It is also
  1908. * necessary to delete the connection information structure.
  1909. */
  1910. TRACE_OUT (("Controller::ApplicationDisconnectProviderRequest: "
  1911. "deleting connection"));
  1912. m_ConnectionList2.Remove(connection_handle);
  1913. m_ConnPollList.Remove(connection);
  1914. delete connection;
  1915. /*
  1916. * Check to see if this connection handle is also in the connection
  1917. * deletion list. If so, then remove it from there as well.
  1918. */
  1919. m_ConnectionDeletionList2.Remove(connection_handle);
  1920. return_value = MCS_NO_ERROR;
  1921. }
  1922. else if (NULL != (connection_pending = m_ConnPendingList2.Remove(connection_handle)))
  1923. {
  1924. /*
  1925. * This connection handle refers to a connection that is still
  1926. * pending. Delete it from there.
  1927. */
  1928. WARNING_OUT (("Controller::ApplicationDisconnectProviderRequest: "
  1929. "deleting pending connection"));
  1930. delete connection_pending;
  1931. return_value = MCS_NO_ERROR;
  1932. }
  1933. else
  1934. {
  1935. /*
  1936. * If the connection handle is not in either of the above dictionaries,
  1937. * then return the appropriate error.
  1938. */
  1939. TRACE_OUT (("Controller::ApplicationDisconnectProviderRequest: "
  1940. "invalid connection"));
  1941. return_value = MCS_NO_SUCH_CONNECTION;
  1942. }
  1943. return (return_value);
  1944. }
  1945. /*
  1946. * MCSError ApplicationAttachUserRequest ()
  1947. *
  1948. * Private
  1949. *
  1950. * Functional Description:
  1951. * This function is used to attach a user application to an existing
  1952. * domain. The user handle that is returned can then be used by the
  1953. * application to request services from MCS.
  1954. *
  1955. * After verifying that the specified domain really does exist, the
  1956. * controller will create a new user object. The new user object will
  1957. * attach itself to both the domain and the application interface
  1958. * specified by the controller. At that point, information can flow
  1959. * through the application interface to the user and then on to the
  1960. * domain without having to pass through the controller.
  1961. *
  1962. * Formal Parameters:
  1963. * domain_selector (i)
  1964. * This identifies the domain to which the user wants to attach.
  1965. * domain_selector_length (i)
  1966. * This is the length of the above domain selector.
  1967. * attachment_flags (i)
  1968. * This is a set of flags that allow the user application to control
  1969. * how the attachment is handled. The only flag currently used by
  1970. * the controller specifies whether or not the user wants to receive
  1971. * callbacks during the controller's heartbeat.
  1972. * ppUser (o)
  1973. * This is a pointer to a user handle, which will be set to a valid
  1974. * value by the controller if this function completes successfully.
  1975. * The user handle is really a pointer to a User object.
  1976. *
  1977. * Return Value:
  1978. * MCS_NO_ERROR
  1979. * Everything completed successfully. Note that the attachment
  1980. * cannot actually be used by the user application until it has
  1981. * received a successful attach user confirm from the domain to
  1982. * which it has attached. This return value merely indicates that
  1983. * process was started successfully.
  1984. * MCS_ALLOCATION_FAILURE
  1985. * This attach request was unable to successfully complete due to a
  1986. * memory allocation failure.
  1987. * MCS_NO_SUCH_DOMAIN
  1988. * This attach request was unable to successfully complete because
  1989. * the specified domain does not exist within this provider.
  1990. *
  1991. * Side Effects:
  1992. * None.
  1993. *
  1994. * Caveats:
  1995. * None.
  1996. */
  1997. MCSError Controller::ApplicationAttachUserRequest
  1998. (
  1999. GCCConfID *domain_selector,
  2000. PUser *ppUser
  2001. )
  2002. {
  2003. MCSError return_value;
  2004. PDomain domain;
  2005. /*
  2006. * First of all make sure that the domain selector refers to a valid
  2007. * domain. If it doesn't, then return the appropriate error.
  2008. */
  2009. if (NULL != (domain = m_DomainList2.Find(*domain_selector)))
  2010. {
  2011. /*
  2012. * Instantiate a new user object, with the domain and the application
  2013. * interface pointer as parameters.
  2014. */
  2015. DBG_SAVE_FILE_LINE
  2016. *ppUser = (PUser) new User (domain, &return_value);
  2017. /*
  2018. * Make sure the allocation completed successfully
  2019. */
  2020. if (*ppUser != NULL) {
  2021. /*
  2022. * The creation of the user object was successful.
  2023. */
  2024. if (return_value != MCS_NO_ERROR) {
  2025. // We have to cleanup the object.
  2026. (*ppUser)->Release();
  2027. }
  2028. }
  2029. else {
  2030. /*
  2031. * There was a memory allocation failure, so return the
  2032. * appropriate error.
  2033. */
  2034. WARNING_OUT (("Controller::ApplicationAttachUserRequest: "
  2035. "user creation failed"));
  2036. return_value = MCS_ALLOCATION_FAILURE;
  2037. }
  2038. }
  2039. else
  2040. {
  2041. /*
  2042. * The specified domain does not exist, so return the appropriate
  2043. * error.
  2044. */
  2045. WARNING_OUT (("Controller::ApplicationAttachUserRequest: invalid domain"));
  2046. return_value = MCS_NO_SUCH_DOMAIN;
  2047. }
  2048. return (return_value);
  2049. }
  2050. /*
  2051. * Void ConnectionDeleteConnection ()
  2052. *
  2053. * Private
  2054. *
  2055. * Functional Description:
  2056. * This request originates within a connection object when it determines
  2057. * the need to delete itself. This is usually caused by one of three
  2058. * things. First, the connection was rejected (inbound or outbound).
  2059. * Second, either the local or remote domain issued a disconnect
  2060. * provider ultimatum. Or third, a transport connection was unexpectedly
  2061. * lost.
  2062. *
  2063. * The controller responds by deleting the connection, after the
  2064. * parameters are validated. It also issues a disconnect provider
  2065. * indication to the node controller.
  2066. *
  2067. * Formal Parameters:
  2068. * connection_handle (i)
  2069. * This is the handle of the connection object that wishes to be
  2070. * deleted.
  2071. *
  2072. * Return Value:
  2073. * None.
  2074. *
  2075. * Side Effects:
  2076. * An MCS connection is terminated, which may result in the destruction
  2077. * of one or more transport connections.
  2078. *
  2079. * Caveats:
  2080. * None.
  2081. */
  2082. Void Controller::ConnectionDeleteConnection (
  2083. ConnectionHandle connection_handle)
  2084. {
  2085. PConnection connection;
  2086. /*
  2087. * Make sure the connection handle is in the dictionary before proceeding.
  2088. */
  2089. if (NULL != (connection = m_ConnectionList2.Find(connection_handle)))
  2090. {
  2091. /*
  2092. * See if the deletion of this connection is already pending. If so,
  2093. * there is no need to queue it up again.
  2094. */
  2095. if (! m_ConnectionDeletionList2.Find(connection_handle))
  2096. {
  2097. /*
  2098. * Put the connection object into the deletion list and set the
  2099. * deletion pending flag.
  2100. */
  2101. TRACE_OUT (("Controller::ConnectionDeleteConnection: "
  2102. "adding connection to deletion list"));
  2103. m_ConnectionDeletionList2.Insert(connection_handle, connection);
  2104. Connection_Deletion_Pending = TRUE;
  2105. SetEvent(Connection_Deletion_Pending_Event);
  2106. /*
  2107. * Post the message to the controller window (GCC and MCS
  2108. * use the same window to post messages to their controllers).
  2109. */
  2110. if (! PostMessage (g_pControlSap->GetHwnd(),
  2111. MCTRLMSG_BASE + MCS_DISCONNECT_PROVIDER_INDICATION,
  2112. NULL, (LPARAM) connection_handle)) {
  2113. ERROR_OUT(("Controller::ConnectionDeleteConnection: "
  2114. "failed to post msg to MCS controller window. Error: %d", GetLastError()));
  2115. }
  2116. }
  2117. }
  2118. else
  2119. {
  2120. /*
  2121. * If the connection handle cannot be found in the connection
  2122. * dictionary, then simply ignore the request.
  2123. */
  2124. WARNING_OUT (("Controller::ConnectionDeleteConnection: "
  2125. "unknown connection"));
  2126. }
  2127. }
  2128. /*
  2129. * Void ConnectionConnectProviderConfirm ()
  2130. *
  2131. * Private
  2132. *
  2133. * Functional Description:
  2134. * This request originates within a domain object upon reception of a
  2135. * connect response PDU. The controller responds by sending a connect
  2136. * provider confirm to the node controller.
  2137. *
  2138. * Formal Parameters:
  2139. * connection_handle (i)
  2140. * This is the handle of the connection object from which the connect
  2141. * provider confirm was received.
  2142. * domain_parameters (i)
  2143. * This is a pointer to a structure that contains the domain parameters
  2144. * that were decided on during capabilities arbitration.
  2145. * result (i)
  2146. * This contains the result of the connect request. Anything but
  2147. * RESULT_SUCCESSFUL means that the connection was rejected.
  2148. * memory (i)
  2149. * If this is not NULL, it contains the user data that was received
  2150. * in the connect response PDU.
  2151. *
  2152. * Return Value:
  2153. * None.
  2154. *
  2155. * Side Effects:
  2156. * A connect provider confirm is sent to the node controller.
  2157. *
  2158. * Caveats:
  2159. * None.
  2160. */
  2161. void Controller::ConnectionConnectProviderConfirm (
  2162. ConnectionHandle connection_handle,
  2163. PDomainParameters domain_parameters,
  2164. Result result,
  2165. PMemory memory)
  2166. {
  2167. PConnection connection;
  2168. PUChar user_data;
  2169. ULong user_data_length;
  2170. ConnectProviderConfirm *pconnect_provider_confirm;
  2171. /*
  2172. * Make sure the connection handle is in the dictionary before proceeding.
  2173. */
  2174. if (NULL != (connection = m_ConnectionList2.Find(connection_handle)))
  2175. {
  2176. // Allocate the node controller msg.
  2177. DBG_SAVE_FILE_LINE
  2178. pconnect_provider_confirm = new ConnectProviderConfirm;
  2179. if (pconnect_provider_confirm != NULL) {
  2180. /*
  2181. * Check to see if there is user data associated with this confirm.
  2182. */
  2183. if (memory != NULL)
  2184. {
  2185. /*
  2186. * If there is user data, lock it, and get the address and length
  2187. * into temporary variables.
  2188. */
  2189. LockMemory (memory);
  2190. user_data = memory->GetPointer ();
  2191. user_data_length = memory->GetLength ();
  2192. }
  2193. else
  2194. {
  2195. /*
  2196. * If there is no user data, then set the address and length fields
  2197. * to default values.
  2198. */
  2199. user_data = NULL;
  2200. user_data_length = 0;
  2201. }
  2202. /*
  2203. * Put all information about this confirm into the node controller
  2204. * message structure allocated above.
  2205. */
  2206. pconnect_provider_confirm->connection_handle = (ConnectionHandle) connection_handle;
  2207. pconnect_provider_confirm->domain_parameters = *domain_parameters;
  2208. pconnect_provider_confirm->result = result;
  2209. pconnect_provider_confirm->user_data = user_data;
  2210. pconnect_provider_confirm->user_data_length = user_data_length;
  2211. pconnect_provider_confirm->pb_cred = NULL;
  2212. pconnect_provider_confirm->cb_cred = 0;
  2213. DWORD cb = 0;
  2214. if (GetSecurityInfo(connection_handle, NULL, &cb))
  2215. {
  2216. if (cb > 0 && NOT_DIRECTLY_CONNECTED != cb)
  2217. {
  2218. pconnect_provider_confirm->pb_cred = (PBYTE) CoTaskMemAlloc(cb);
  2219. if (NULL != pconnect_provider_confirm->pb_cred)
  2220. {
  2221. if (GetSecurityInfo(connection_handle, pconnect_provider_confirm->pb_cred, &cb))
  2222. {
  2223. pconnect_provider_confirm->cb_cred = cb;
  2224. }
  2225. else
  2226. {
  2227. CoTaskMemFree(pconnect_provider_confirm->pb_cred);
  2228. pconnect_provider_confirm->pb_cred = NULL;
  2229. }
  2230. }
  2231. else
  2232. {
  2233. ERROR_OUT(("Controller::ConnectionConnectProviderConfirm: Memory Allocation Error"));
  2234. }
  2235. }
  2236. }
  2237. /*
  2238. * Post the message to the controller window (GCC and MCS
  2239. * use the same window to post messages to their controllers).
  2240. */
  2241. if (! PostMessage (g_pControlSap->GetHwnd(),
  2242. MCTRLMSG_BASE + MCS_CONNECT_PROVIDER_CONFIRM,
  2243. (WPARAM) memory, (LPARAM) pconnect_provider_confirm)) {
  2244. ERROR_OUT(("Controller::ConnectionDeleteConnection: "
  2245. "failed to post msg to MCS controller window. Error: %d", GetLastError()));
  2246. }
  2247. /*
  2248. * If the result of this confirm is not successful, and the connection
  2249. * is not already queued for deletion, then we need to queue it for
  2250. * deletion.
  2251. */
  2252. if ((result != RESULT_SUCCESSFUL) &&
  2253. (! m_ConnectionDeletionList2.Find(connection_handle)))
  2254. {
  2255. /*
  2256. * Put the connection object into the deletion list and set the
  2257. * deletion pending flag.
  2258. */
  2259. TRACE_OUT (("Controller::ConnectionConnectProviderConfirm: "
  2260. "adding connection to deletion list"));
  2261. m_ConnectionDeletionList2.Insert(connection_handle, connection);
  2262. Connection_Deletion_Pending = TRUE;
  2263. SetEvent(Connection_Deletion_Pending_Event);
  2264. }
  2265. }
  2266. else
  2267. ERROR_OUT(("Controller::ConnectionConnectProviderConfirm: "
  2268. "failed to allocate node controller msg."));
  2269. }
  2270. else
  2271. {
  2272. /*
  2273. * If the connection handle cannot be found in the connection
  2274. * dictionary, then simply ignore the request.
  2275. */
  2276. WARNING_OUT (("Controller::ConnectionConnectProviderConfirm: "
  2277. "unknown connection"));
  2278. }
  2279. }
  2280. /*
  2281. * Void TransportDisconnectIndication ()
  2282. *
  2283. * Private
  2284. *
  2285. * Functional Description:
  2286. * This request originates within a transport interface object when it
  2287. * gets a disconnect indication from the transport layer for a transport
  2288. * connection that is not assigned to a connection object. This could
  2289. * happen in the case where a remote node issues a connect provider request
  2290. * followed by a disconnect provider request before this node issues a
  2291. * connect provider response.
  2292. *
  2293. * The controller responds by simply removing the information from the
  2294. * connection pending list.
  2295. *
  2296. * Formal Parameters:
  2297. * transport_connection (i)
  2298. * This is the transport connection handle that has been assigned to
  2299. * the newly created transport connection.
  2300. *
  2301. * Return Value:
  2302. * None.
  2303. *
  2304. * Side Effects:
  2305. * None.
  2306. *
  2307. * Caveats:
  2308. * None.
  2309. */
  2310. Void Controller::TransportDisconnectIndication (
  2311. TransportConnection transport_connection)
  2312. {
  2313. PConnectionPending connection_pending;
  2314. ConnectionHandle connection_handle;
  2315. /*
  2316. * Find the entry in the connection pending list which is associated with
  2317. * the given transport connection. If found, remove the entry.
  2318. */
  2319. m_ConnPendingList2.Reset();
  2320. while (NULL != (connection_pending = m_ConnPendingList2.Iterate(&connection_handle)))
  2321. {
  2322. if (IS_SAME_TRANSPORT_CONNECTION(connection_pending->transport_connection, transport_connection))
  2323. {
  2324. m_ConnPendingList2.Remove(connection_handle);
  2325. delete connection_pending;
  2326. break;
  2327. }
  2328. }
  2329. }
  2330. /*
  2331. * Void TransportDataIndication ()
  2332. *
  2333. * Private
  2334. *
  2335. * Functional Description:
  2336. * This function is called when data is received from the transport layer
  2337. * on a transport connection that no other object has registered
  2338. * ownership of.
  2339. *
  2340. * Formal Parameters:
  2341. * transport_connection (i)
  2342. * This is the transport connection handle that has been assigned to
  2343. * the newly created transport connection.
  2344. * user_data
  2345. * A pointer to the data received.
  2346. * user_data_length
  2347. * The length of the data received.
  2348. *
  2349. * Return Value:
  2350. * None.
  2351. *
  2352. * Side Effects:
  2353. * None.
  2354. *
  2355. * Caveats:
  2356. * None.
  2357. */
  2358. Void Controller::TransportDataIndication (
  2359. TransportConnection transport_connection,
  2360. PUChar user_data,
  2361. ULong user_data_length)
  2362. {
  2363. PPacket packet;
  2364. PacketError packet_error;
  2365. PVoid pdu_structure;
  2366. ASSERT (g_Transport);
  2367. /*
  2368. * Create a packet from the encoded data received from the transport
  2369. * interface. Retrieve the decoded PDU structure from the packet and
  2370. * pass it on to the appropriate processing routine.
  2371. */
  2372. DBG_SAVE_FILE_LINE
  2373. packet = new Packet (
  2374. (PPacketCoder) g_MCSCoder,
  2375. BASIC_ENCODING_RULES,
  2376. user_data + PROTOCOL_OVERHEAD_X224,
  2377. user_data_length - PROTOCOL_OVERHEAD_X224,
  2378. CONNECT_MCS_PDU,
  2379. TRUE,
  2380. &packet_error);
  2381. if (packet != NULL)
  2382. {
  2383. if (packet_error == PACKET_NO_ERROR)
  2384. {
  2385. /*
  2386. * Get a pointer to the decoded data.
  2387. */
  2388. pdu_structure = packet->GetDecodedData ();
  2389. switch (((ConnectMCSPDU *) pdu_structure)->choice)
  2390. {
  2391. case CONNECT_INITIAL_CHOSEN:
  2392. ProcessConnectInitial (
  2393. transport_connection,
  2394. &((ConnectMCSPDU *) pdu_structure)->u.
  2395. connect_initial);
  2396. break;
  2397. case CONNECT_ADDITIONAL_CHOSEN:
  2398. ProcessConnectAdditional (
  2399. transport_connection,
  2400. &((ConnectMCSPDU *) pdu_structure)->u.
  2401. connect_additional);
  2402. break;
  2403. default:
  2404. ERROR_OUT (("Controller::TransportDataIndication: "
  2405. "received invalid PDU (%d)",
  2406. ((ConnectMCSPDU *) pdu_structure)->choice));
  2407. g_Transport->DisconnectRequest (transport_connection);
  2408. break;
  2409. }
  2410. }
  2411. else
  2412. {
  2413. /*
  2414. * A memory allocation failure has prevented us from processing
  2415. * this PDU. Destroy the connection that carried it.
  2416. */
  2417. WARNING_OUT (("Controller::TransportDataIndication: "
  2418. "packet constructor failed"));
  2419. g_Transport->DisconnectRequest (transport_connection);
  2420. }
  2421. packet->Unlock ();
  2422. }
  2423. else
  2424. {
  2425. /*
  2426. * A memory allocation failure has prevented us from processing
  2427. * this PDU. Destroy the connection that carried it.
  2428. */
  2429. WARNING_OUT (("Controller::TransportDataIndication: "
  2430. "packet allocation failed"));
  2431. g_Transport->DisconnectRequest (transport_connection);
  2432. }
  2433. }
  2434. #ifdef TSTATUS_INDICATION
  2435. /*
  2436. * Void TransportStatusIndication ()
  2437. *
  2438. * Private
  2439. *
  2440. * Functional Description:
  2441. * This request originates within a transport interface object when it
  2442. * receives a status indication from its transport layer. This function
  2443. * will forward the status indication to the node controller.
  2444. *
  2445. * Formal Parameters:
  2446. * transport_status
  2447. * This is a pointer to the TransportStatus structure that describes
  2448. * the reason for the indication.
  2449. *
  2450. * Return Value:
  2451. * None.
  2452. *
  2453. * Side Effects:
  2454. * None.
  2455. *
  2456. * Caveats:
  2457. * None.
  2458. */
  2459. Void Controller::TransportStatusIndication (
  2460. PTransportStatus transport_status)
  2461. {
  2462. ULong device_identifier_length;
  2463. ULong remote_address_length;
  2464. ULong message_length;
  2465. PMemory memory;
  2466. PUChar string_address;
  2467. PNodeControllerMessage node_controller_message;
  2468. /*
  2469. * Determine the length of each of the ASCII strings contained in the
  2470. * transport status indications. This will be used to allocate a
  2471. * memory block large enough to hold them all. Note that each length
  2472. * includes one extra byte to hold the ASCII NULL terminator.
  2473. */
  2474. device_identifier_length =
  2475. (ULong) lstrlen (transport_status->device_identifier) + 1;
  2476. remote_address_length =
  2477. (ULong) lstrlen (transport_status->remote_address) + 1;
  2478. message_length =
  2479. (ULong) lstrlen (transport_status->message) + 1;
  2480. /*
  2481. * Use the memory manager to allocate a memory block large enough to
  2482. * hold all of the strings.
  2483. */
  2484. DBG_SAVE_FILE_LINE
  2485. memory = AllocateMemory (NULL,
  2486. (device_identifier_length + remote_address_length + message_length));
  2487. if (memory != NULL)
  2488. {
  2489. DBG_SAVE_FILE_LINE
  2490. node_controller_message = new NodeControllerMessage;
  2491. if (node_controller_message != NULL) {
  2492. /*
  2493. * Get the address of the memory block that was allocated.
  2494. */
  2495. string_address = memory->GetPointer ();
  2496. /*
  2497. * Indicate what type of message this is.
  2498. */
  2499. node_controller_message->message_type = MCS_TRANSPORT_STATUS_INDICATION;
  2500. /*
  2501. * Copy all of the ASCII strings into the memory block that was
  2502. * allocated above. This block will remain valid until this
  2503. * message is sent to the node controller.
  2504. */
  2505. memcpy (string_address, transport_status->device_identifier,
  2506. device_identifier_length);
  2507. node_controller_message->u.transport_status_indication.
  2508. device_identifier = (PChar) string_address;
  2509. string_address += (Int) device_identifier_length;
  2510. memcpy (string_address, transport_status->remote_address,
  2511. remote_address_length);
  2512. node_controller_message->u.transport_status_indication.
  2513. remote_address = (PChar) string_address;
  2514. string_address += (Int) remote_address_length;
  2515. memcpy (string_address, transport_status->message,
  2516. message_length);
  2517. node_controller_message->u.transport_status_indication.
  2518. message = (PChar) string_address;
  2519. node_controller_message->u.transport_status_indication.
  2520. state = transport_status->state;
  2521. node_controller_message->memory = memory;
  2522. /*
  2523. * Put this message into the control queue to be sent to the node
  2524. * controller during the next heartbeat.
  2525. */
  2526. AddToMessageQueue (node_controller_message);
  2527. }
  2528. else
  2529. WARNING_OUT(("Controller::TransportStatusIndication: "
  2530. "WARNING - memory allocation failure"));
  2531. }
  2532. else
  2533. {
  2534. /*
  2535. * A memory allocation failure has occurred. This prevents us from
  2536. * being able to deliver this status indication to the node controller.
  2537. * This does not compromise the integrity of MCS, but could cause
  2538. * problems at a higher level.
  2539. */
  2540. ERROR_OUT (("Controller::TransportStatusIndication: "
  2541. "WARNING - memory allocation failure"));
  2542. }
  2543. }
  2544. #endif
  2545. /*
  2546. * Void ProcessConnectInitial()
  2547. *
  2548. * Private
  2549. *
  2550. * Functional Description:
  2551. * Processes incoming connect initial PDUs. Sends a connect provider
  2552. * indication to the node controller if everything checks out.
  2553. *
  2554. * Formal Parameters:
  2555. * transport_connection (i)
  2556. * This is assigned transport connection handle for the connection
  2557. * that carried the PDU.
  2558. * pdu_structure (i)
  2559. * This is a pointer to the PDU itself.
  2560. *
  2561. * Return Value:
  2562. * None.
  2563. *
  2564. * Side Effects:
  2565. * None.
  2566. *
  2567. * Caveats:
  2568. * None.
  2569. */
  2570. void Controller::ProcessConnectInitial (
  2571. TransportConnection transport_connection,
  2572. ConnectInitialPDU * pdu_structure)
  2573. {
  2574. PConnectionPending connection_pending;
  2575. PMemory memory;
  2576. PUChar memory_address;
  2577. ConnectProviderIndication *pconnect_provider_indication;
  2578. ConnectionHandle connection_handle;
  2579. BOOL upward_connection;
  2580. //DomainParameters domain_parameters;
  2581. /*
  2582. * Try to allocate a connection pending structure. This will be used to
  2583. * hold information about the incoming connection that will not be passed
  2584. * back in the connect provider response.
  2585. */
  2586. DBG_SAVE_FILE_LINE
  2587. connection_pending = new ConnectionPending;
  2588. DBG_SAVE_FILE_LINE
  2589. pconnect_provider_indication = new ConnectProviderIndication;
  2590. if (connection_pending != NULL && pconnect_provider_indication != NULL)
  2591. {
  2592. /*
  2593. * Allocate a memory block to hold the user data field in the
  2594. * incoming connection.
  2595. */
  2596. DBG_SAVE_FILE_LINE
  2597. memory = AllocateMemory (NULL, pdu_structure->user_data.length);
  2598. if (memory != NULL) {
  2599. memory_address = memory->GetPointer ();
  2600. /*
  2601. * Allocate a connection handle for this inbound connection,
  2602. * and put it into the indication structure. Also fill in the
  2603. * physical connection handle, which is obtained by asking the
  2604. * transport interface for it.
  2605. */
  2606. connection_handle = AllocateConnectionHandle ();
  2607. pconnect_provider_indication->connection_handle = connection_handle;
  2608. pconnect_provider_indication->fSecure =
  2609. g_Transport->GetSecurity ( transport_connection );
  2610. /*
  2611. * Copy the user data field into the
  2612. * newly allocated memory block. Also set the pointers in
  2613. * the node controller message structure to point into the
  2614. * memory block.
  2615. */
  2616. memcpy (memory_address,
  2617. pdu_structure->user_data.value,
  2618. pdu_structure->user_data.length);
  2619. pconnect_provider_indication->user_data = memory_address;
  2620. pconnect_provider_indication->user_data_length =
  2621. pdu_structure->user_data.length;
  2622. /*
  2623. * Retrieve the direction of the incoming connection. Put it
  2624. * into both the connect provider indication structure and the
  2625. * connection pending structure. Note that in the connection
  2626. * pending structure, we need to reverse the direction of the
  2627. * flag so that it is from the point-of-view of this provider.
  2628. */
  2629. upward_connection = pdu_structure->upward_flag;
  2630. pconnect_provider_indication->upward_connection = upward_connection;
  2631. if (upward_connection)
  2632. connection_pending->upward_connection = FALSE;
  2633. else
  2634. connection_pending->upward_connection = TRUE;
  2635. /*
  2636. * Retrieve the target domain parameters and put them into both
  2637. * the connect provider indication structure, and into the
  2638. * connection pending structure (for possible later use).
  2639. */
  2640. memcpy (&(pconnect_provider_indication->domain_parameters),
  2641. &(pdu_structure->target_parameters), sizeof (PDUDomainParameters));
  2642. memcpy (&(connection_pending->domain_parameters),
  2643. &(pdu_structure->target_parameters), sizeof (PDUDomainParameters));
  2644. /*
  2645. * Retrieve the minimum domain parameters and put them into
  2646. * the connection pending structure (for possible later use).
  2647. */
  2648. memcpy (&(connection_pending->minimum_domain_parameters),
  2649. &(pdu_structure->minimum_parameters), sizeof(PDUDomainParameters));
  2650. /*
  2651. * Retrieve the maximum domain parameters and put them into
  2652. * the connection pending structure (for possible later use).
  2653. */
  2654. memcpy (&(connection_pending->maximum_domain_parameters),
  2655. &(pdu_structure->maximum_parameters), sizeof(PDUDomainParameters));
  2656. /*
  2657. * Post the message to the controller window (GCC and MCS
  2658. * use the same window to post messages to their controllers).
  2659. */
  2660. if (NULL != g_pControlSap) {
  2661. if (! PostMessage (g_pControlSap->GetHwnd(),
  2662. MCTRLMSG_BASE + MCS_CONNECT_PROVIDER_INDICATION,
  2663. (WPARAM) memory, (LPARAM) pconnect_provider_indication)) {
  2664. ERROR_OUT(("Controller::ProcessConnectInitial: "
  2665. "failed to post msg to MCS controller window. Error: %d", GetLastError()));
  2666. }
  2667. }
  2668. /*
  2669. * We also need to remember which transport interface and
  2670. * transport connection are associated with this pending
  2671. * MCS connection. Then put the connection pending structure
  2672. * into a list for later use.
  2673. */
  2674. connection_pending->transport_connection = transport_connection;
  2675. m_ConnPendingList2.Append(connection_handle, connection_pending);
  2676. // No errors have occurred.
  2677. return;
  2678. }
  2679. }
  2680. /*
  2681. * A memory allocation failure has occurred. We have no choice
  2682. * but to terminate the connection upon which this PDU arrived.
  2683. */
  2684. ASSERT (g_Transport);
  2685. WARNING_OUT(("Controller::ProcessConnectInitial: memory allocation failure"));
  2686. delete connection_pending;
  2687. delete pconnect_provider_indication;
  2688. g_Transport->DisconnectRequest (transport_connection);
  2689. }
  2690. /*
  2691. * Void ProcessConnectAdditional ()
  2692. *
  2693. * Private
  2694. *
  2695. * Functional Description:
  2696. * Processes incoming connect additional PDUs. If the connection handle
  2697. * contained therein is valid, it will bind the connection to the
  2698. * proper connection object.
  2699. *
  2700. * Formal Parameters:
  2701. * transport_connection (i)
  2702. * This is assigned transport connection handle for the connection
  2703. * that carried the PDU.
  2704. * pdu_structure (i)
  2705. * This is a pointer to the PDU itself.
  2706. *
  2707. * Return Value:
  2708. * None.
  2709. *
  2710. * Side Effects:
  2711. * None.
  2712. *
  2713. * Caveats:
  2714. * None.
  2715. */
  2716. Void Controller::ProcessConnectAdditional (
  2717. TransportConnection transport_connection,
  2718. ConnectAdditionalPDU * pdu_structure)
  2719. {
  2720. ConnectionHandle connection_handle;
  2721. Priority priority;
  2722. PConnection connection;
  2723. ASSERT (g_Transport);
  2724. connection_handle = (ConnectionHandle) pdu_structure->called_connect_id;
  2725. priority = (Priority) pdu_structure->data_priority;
  2726. if (NULL != (connection = m_ConnectionList2.Find(connection_handle)))
  2727. {
  2728. /*
  2729. * The indicated connection does exist, so call upon it to accept
  2730. * and register the new transport connection.
  2731. */
  2732. connection->RegisterTransportConnection (transport_connection, priority);
  2733. }
  2734. else
  2735. {
  2736. /*
  2737. * The indicated connection handle is not in the dictionary. Issue
  2738. * a connect result with a failure result, and disconnect the
  2739. * transport connection.
  2740. */
  2741. ConnectResult (transport_connection, RESULT_UNSPECIFIED_FAILURE);
  2742. g_Transport->DisconnectRequest (transport_connection);
  2743. }
  2744. }
  2745. /*
  2746. * Void ConnectResponse ()
  2747. *
  2748. * Private
  2749. *
  2750. * Functional Description:
  2751. * Sends a failed connect response PDU (when something goes wrong).
  2752. *
  2753. * Formal Parameters:
  2754. * transport_connection (i)
  2755. * This is assigned transport connection handle for the connection
  2756. * that is to carry the PDU.
  2757. * result (i)
  2758. * This is the result being sent in the connect response.
  2759. * domain_parameters (i)
  2760. * This is a pointer to a structure containing domain parameters.
  2761. * These parameters will not be used for anything since the connection
  2762. * is being rejected.
  2763. * connect_id (i)
  2764. * This is the connect ID that would be used for any additional
  2765. * transport connection to be bound to this one. This is not
  2766. * required since the connection is being rejected.
  2767. * user_data (i)
  2768. * This is a pointer to the user data to be transmitted to the remote
  2769. * side along with the response.
  2770. * user_data_lengthn (i)
  2771. * This is the length of the above user data.
  2772. *
  2773. * Return Value:
  2774. * None.
  2775. *
  2776. * Side Effects:
  2777. * None.
  2778. *
  2779. * Caveats:
  2780. */
  2781. Void Controller::ConnectResponse (
  2782. TransportConnection transport_connection,
  2783. Result result,
  2784. PDomainParameters domain_parameters,
  2785. ConnectID connect_id,
  2786. PUChar user_data,
  2787. ULong user_data_length)
  2788. {
  2789. ConnectMCSPDU connect_response_pdu;
  2790. PPacket packet;
  2791. PacketError packet_error;
  2792. //PVoid encoded_data;
  2793. //ULong encoded_data_length;
  2794. ASSERT (g_Transport);
  2795. /*
  2796. * Fill in the ConnectResponse PDU structure to be encoded.
  2797. */
  2798. connect_response_pdu.choice = CONNECT_RESPONSE_CHOSEN;
  2799. connect_response_pdu.u.connect_response.result = (PDUResult)result;
  2800. connect_response_pdu.u.connect_response.called_connect_id = connect_id;
  2801. memcpy (&(connect_response_pdu.u.connect_response.domain_parameters),
  2802. domain_parameters, sizeof(PDUDomainParameters));
  2803. connect_response_pdu.u.connect_response.user_data.length = user_data_length;
  2804. connect_response_pdu.u.connect_response.user_data.value = user_data;
  2805. /*
  2806. * Create a packet which will be used to hold the data to be sent
  2807. * through the transport interface. Check to make sure the packet is
  2808. * successfully created..
  2809. */
  2810. DBG_SAVE_FILE_LINE
  2811. packet = new Packet (
  2812. (PPacketCoder) g_MCSCoder,
  2813. BASIC_ENCODING_RULES,
  2814. &connect_response_pdu,
  2815. CONNECT_MCS_PDU,
  2816. TRUE,
  2817. &packet_error);
  2818. if (packet != NULL)
  2819. {
  2820. if (packet_error == PACKET_NO_ERROR)
  2821. {
  2822. /*
  2823. * Send the packet through the transport interface.
  2824. */
  2825. #ifdef DEBUG
  2826. TransportError err = DataRequest (transport_connection,
  2827. (PSimplePacket) packet);
  2828. ASSERT (err == TRANSPORT_NO_ERROR);
  2829. #else // DEBUG
  2830. DataRequest (transport_connection, (PSimplePacket) packet);
  2831. #endif // DEBUG
  2832. }
  2833. else
  2834. {
  2835. /*
  2836. * The packet creation has failed due to an internal error so
  2837. * report the error through a print statement. Note that no
  2838. * further action need be taken since this transport connection
  2839. * is being terminated anyway.
  2840. */
  2841. WARNING_OUT (("Controller::ConnectResponse: "
  2842. "internal allocation failure"));
  2843. }
  2844. packet->Unlock ();
  2845. }
  2846. else
  2847. {
  2848. /*
  2849. * The packet creation has failed so report the error through a print
  2850. * statement. Note that no further action need be taken since this
  2851. * transport connection is being terminated anyway.
  2852. */
  2853. WARNING_OUT (("Controller::ConnectResponse: "
  2854. "packet allocation failure"));
  2855. }
  2856. }
  2857. /*
  2858. * Void ConnectResult ()
  2859. *
  2860. * Private
  2861. *
  2862. * Functional Description:
  2863. * Sends a failed connect response PDU (when something goes wrong).
  2864. *
  2865. * Formal Parameters:
  2866. * transport_connection (i)
  2867. * This is assigned transport connection handle for the connection
  2868. * that is to carry the PDU.
  2869. * result (i)
  2870. * This is the result being sent in the connect result.
  2871. *
  2872. * Return Value:
  2873. * None.
  2874. *
  2875. * Side Effects:
  2876. * None.
  2877. *
  2878. * Caveats:
  2879. */
  2880. Void Controller::ConnectResult (
  2881. TransportConnection transport_connection,
  2882. Result result)
  2883. {
  2884. ConnectMCSPDU connect_result_pdu;
  2885. PPacket packet;
  2886. PacketError packet_error;
  2887. //PVoid encoded_data;
  2888. //ULong encoded_data_length;
  2889. ASSERT (g_Transport);
  2890. /*
  2891. * Fill in the PDU structure to be encoded.
  2892. */
  2893. connect_result_pdu.choice = CONNECT_RESULT_CHOSEN;
  2894. connect_result_pdu.u.connect_result.result = (PDUResult)result;
  2895. /*
  2896. * Create a packet which will be used to hold the data to be sent
  2897. * through the transport interface. Check to make sure the packet is
  2898. * successfully created..
  2899. */
  2900. DBG_SAVE_FILE_LINE
  2901. packet = new Packet (
  2902. (PPacketCoder) g_MCSCoder,
  2903. BASIC_ENCODING_RULES,
  2904. &connect_result_pdu,
  2905. CONNECT_MCS_PDU,
  2906. TRUE,
  2907. &packet_error);
  2908. if (packet != NULL)
  2909. {
  2910. if (packet_error == PACKET_NO_ERROR)
  2911. {
  2912. /*
  2913. * Send the packet through the transport interface.
  2914. */
  2915. #ifdef DEBUG
  2916. TransportError err = DataRequest (transport_connection,
  2917. (PSimplePacket) packet);
  2918. ASSERT (err == TRANSPORT_NO_ERROR);
  2919. #else // DEBUG
  2920. DataRequest (transport_connection, (PSimplePacket) packet);
  2921. #endif // DEBUG
  2922. }
  2923. else
  2924. {
  2925. /*
  2926. * The packet creation has failed due to an internal error so
  2927. * report the error through a print statement. Note that no
  2928. * further action need be taken since this transport connection
  2929. * is being terminated anyway.
  2930. */
  2931. WARNING_OUT (("Controller::ConnectResult: "
  2932. "internal allocation failure"));
  2933. }
  2934. packet->Unlock ();
  2935. }
  2936. else
  2937. {
  2938. /*
  2939. * The packet creation has failed so report the error through a print
  2940. * statement. Note that no further action need be taken since this
  2941. * transport connection is being terminated anyway.
  2942. */
  2943. WARNING_OUT (("Controller::ConnectResult: "
  2944. "packet allocation failure"));
  2945. }
  2946. }
  2947. /*
  2948. * ConnectionHandle AllocateConnectionHandle ()
  2949. *
  2950. * Private
  2951. *
  2952. * Functional Description:
  2953. * This routine allocates a unique connection handle to be used for a newly
  2954. * created connection object. It is based on a rolling instance variable,
  2955. * so that no two handles will ever be reused until the number rolls
  2956. * over at 0xffff.
  2957. *
  2958. * Note that 0 is not a valid connection handle, and will never be used.
  2959. *
  2960. * Formal Parameters:
  2961. * None.
  2962. *
  2963. * Return Value:
  2964. * The unique connection handle.
  2965. *
  2966. * Side Effects:
  2967. * None.
  2968. *
  2969. * Caveats:
  2970. * Note that the assumption is made that there will never be more than
  2971. * 65,534 handles in use at once. In other words, this loop assumes that
  2972. * there is at least 1 available handle left. If there is not, then the
  2973. * loop will hang forever (this is a pretty safe bet for now).
  2974. */
  2975. ConnectionHandle Controller::AllocateConnectionHandle ()
  2976. {
  2977. /*
  2978. * This loop simply increments a rolling number, looking for the next
  2979. * one that is not already in use.
  2980. */
  2981. while (1)
  2982. {
  2983. Connection_Handle_Counter++;
  2984. /*
  2985. * 0 is not a valid handle, so skip it.
  2986. */
  2987. if (Connection_Handle_Counter == 0)
  2988. continue;
  2989. /*
  2990. * If this handle is not in use, break from the loop and use it.
  2991. */
  2992. if (! m_ConnectionList2.Find(Connection_Handle_Counter))
  2993. break;
  2994. }
  2995. return (Connection_Handle_Counter);
  2996. }
  2997. BOOL Controller::GetLocalAddress(ConnectionHandle connection_handle,
  2998. TransportAddress local_address,
  2999. PInt local_address_length)
  3000. {
  3001. PConnection connection = NULL;
  3002. PConnectionPending connection_pending = NULL;
  3003. TransportError transport_error;
  3004. BOOL return_value = FALSE;
  3005. if (NULL == (connection = m_ConnectionList2.Find(connection_handle)))
  3006. {
  3007. connection_pending = m_ConnPendingList2.Find(connection_handle);
  3008. }
  3009. if(connection || connection_pending)
  3010. {
  3011. // Ask the local address to the transport interface
  3012. if (connection)
  3013. {
  3014. transport_error = ::GetLocalAddress(connection->GetTransportConnection(TOP_PRIORITY),
  3015. local_address,
  3016. local_address_length);
  3017. }
  3018. else
  3019. {
  3020. transport_error = ::GetLocalAddress(connection_pending->transport_connection,
  3021. local_address,
  3022. local_address_length);
  3023. }
  3024. // Check the error code
  3025. if (TRANSPORT_NO_ERROR == transport_error) {
  3026. return_value = TRUE;
  3027. }
  3028. }
  3029. return(return_value);
  3030. }
  3031. BOOL Controller::FindSocketNumber(ConnectionHandle connection_handle, SOCKET * socket_number)
  3032. {
  3033. PConnection connection = NULL;
  3034. PConnectionPending connection_pending = NULL;
  3035. if (NULL != (connection = m_ConnectionList2.Find(connection_handle)))
  3036. {
  3037. TransportConnection XprtConn = connection->GetTransportConnection(TOP_PRIORITY);
  3038. if (IS_SOCKET(XprtConn))
  3039. {
  3040. * socket_number = XprtConn.nLogicalHandle;
  3041. return TRUE;
  3042. }
  3043. }
  3044. else
  3045. if (NULL != (connection_pending = m_ConnPendingList2.Find(connection_handle)))
  3046. {
  3047. if (IS_SOCKET(connection_pending->transport_connection))
  3048. {
  3049. * socket_number = connection_pending->transport_connection.nLogicalHandle;
  3050. return TRUE;
  3051. }
  3052. }
  3053. return FALSE;
  3054. }