Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3342 lines
102 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. if(!m_DomainList2.Append(*domain_selector, domain))
  1342. {
  1343. delete domain;
  1344. return_value = MCS_ALLOCATION_FAILURE;
  1345. }
  1346. else
  1347. {
  1348. return_value = MCS_NO_ERROR;
  1349. }
  1350. }
  1351. else
  1352. {
  1353. /*
  1354. * Set the return value to indication a memory allocation failure.
  1355. */
  1356. WARNING_OUT (("Controller::ApplicationCreateDomain: "
  1357. "domain creation failed"));
  1358. return_value = MCS_ALLOCATION_FAILURE;
  1359. }
  1360. }
  1361. else
  1362. {
  1363. /*
  1364. * The domain was not created since it already exists.
  1365. */
  1366. WARNING_OUT (("Controller::ApplicationCreateDomain: "
  1367. "domain already exists"));
  1368. return_value = MCS_DOMAIN_ALREADY_EXISTS;
  1369. }
  1370. return (return_value);
  1371. }
  1372. /*
  1373. * MCSError ApplicationDeleteDomain ()
  1374. *
  1375. * Private
  1376. *
  1377. * Functional Description:
  1378. * This request comes from one of the application interface objects. It
  1379. * instructs the controller to delete an existing domain, with the only
  1380. * parameter identifying the domain to be deleted. If the domain exists,
  1381. * then it will be destroyed.
  1382. *
  1383. * Note that all user attachments and MCS connections that are attached
  1384. * to the domain when it is deleted will also be deleted (automatically).
  1385. *
  1386. * Formal Parameters:
  1387. * domain_selector (i)
  1388. * This is the domain selector for the domain to be deleted.
  1389. * domain_selector_length (i)
  1390. * This is the length of the above domain selector.
  1391. *
  1392. * Return Value:
  1393. * MCS_NO_ERROR
  1394. * The domain was successfully deleted.
  1395. * MCS_NO_SUCH_DOMAIN
  1396. * There is no domain associated with the passed in domain selector.
  1397. *
  1398. * Side Effects:
  1399. * When the domain is deleted, all resources used by it (including user
  1400. * attachments and MCS connections) will be deleted as well.
  1401. *
  1402. * Caveats:
  1403. * None.
  1404. */
  1405. MCSError Controller::ApplicationDeleteDomain
  1406. (
  1407. GCCConfID *domain_selector
  1408. )
  1409. {
  1410. PDomain domain;
  1411. MCSError return_value;
  1412. /*
  1413. * Check to see if the domain selector refers to a valid domain.
  1414. */
  1415. if (NULL != (domain = m_DomainList2.Remove(*domain_selector)))
  1416. {
  1417. /*
  1418. * If the domain selector is valid, then remove the domain from the
  1419. * dictionary and delete it. Everything else happens automatically
  1420. * as a result of destroying the domain object.
  1421. */
  1422. TRACE_OUT (("Controller::ApplicationDeleteDomain: deleting domain"));
  1423. delete domain;
  1424. return_value = MCS_NO_ERROR;
  1425. }
  1426. else
  1427. {
  1428. /*
  1429. * If the domain selector is not in the dictionary, then report the
  1430. * error to the caller.
  1431. */
  1432. ERROR_OUT (("Controller::ApplicationDeleteDomain: invalid domain"));
  1433. return_value = MCS_NO_SUCH_DOMAIN;
  1434. }
  1435. return (return_value);
  1436. }
  1437. /*
  1438. * MCSError ApplicationConnectProviderRequest ()
  1439. *
  1440. * Private
  1441. *
  1442. * Functional Description:
  1443. * This request originates from one of the application interface objects.
  1444. * This happens as the result of the node controller issuing a
  1445. * ConnectProviderRequest to whichever application interface object
  1446. * that it is attached to. If the parameters are valid, then a new
  1447. * connection object will be created to represent the outbound connection.
  1448. * This will result in the connection object calling the proper transport
  1449. * interface to create the transport connection, etc.
  1450. *
  1451. * Formal Parameters:
  1452. * pcriConnectRequestInfo (i)
  1453. * Contains all the needed info to complete the Connect Provider Request.
  1454. *
  1455. * Return Value:
  1456. * MCS_NO_ERROR
  1457. * The request was successful. The connection handle for the newly
  1458. * created connection has been stored at the address passed into this
  1459. * request (see parameter list above). Note that this connection
  1460. * handle can be used to destroy the new connection immediately, even
  1461. * if the physical connection has not yet been established. This
  1462. * allows the node controller to abort a dial in-progress by calling
  1463. * DisconnectProviderRequest.
  1464. * MCS_INVALID_PARAMETER
  1465. * The format of the called address field is incorrect.
  1466. * MCS_ALLOCATION_FAILURE
  1467. * The request was unable to complete successfully due to a memory
  1468. * allocation failure (either in MCS or the transport layer).
  1469. * MCS_TRANSPORT_NOT_READY
  1470. * The transport layer could not process the request because it is not
  1471. * ready. This usually means that initialization has not successfully
  1472. * completed.
  1473. * MCS_DOMAIN_NOT_HIERARCHICAL
  1474. * This request is attempting to create an upward connection to a
  1475. * domain that already has an upward connection (which is not valid).
  1476. * MCS_NO_SUCH_DOMAIN
  1477. * The specified local domain does not exist within this provider.
  1478. *
  1479. * Side Effects:
  1480. * An outbound connect establishment process is begun.
  1481. *
  1482. * Caveats:
  1483. * None.
  1484. */
  1485. MCSError Controller::ApplicationConnectProviderRequest (
  1486. PConnectRequestInfo pcriConnectRequestInfo)
  1487. {
  1488. PDomain domain;
  1489. BOOL bTransportIdFound;
  1490. PConnection connection;
  1491. MCSError return_value;
  1492. PChar called_address = pcriConnectRequestInfo->called_address;
  1493. PConnectionHandle connection_handle = pcriConnectRequestInfo->connection_handle;
  1494. /*
  1495. * Make sure the local domain specified corresponds to an existing
  1496. * domain.
  1497. */
  1498. ASSERT(sizeof(GCCConfID) == sizeof(*(pcriConnectRequestInfo->calling_domain)));
  1499. if (NULL != (domain = m_DomainList2.Find(*(pcriConnectRequestInfo->calling_domain))))
  1500. {
  1501. /*
  1502. * Check to make sure that the requested connection is valid.
  1503. * Specifically, make sure that this is not a request for an upward
  1504. * connection to a domain that already has an upward connection.
  1505. * This would result in a non-hierarchical domain, which is illegal.
  1506. */
  1507. if ((pcriConnectRequestInfo->upward_connection == FALSE) || (domain->IsTopProvider ()))
  1508. {
  1509. PChar pColon;
  1510. /*
  1511. * Look for the colon that separates the identifier from the
  1512. * address.
  1513. */
  1514. for (bTransportIdFound = FALSE, pColon = called_address; *pColon; pColon++)
  1515. if (*pColon == ':') {
  1516. bTransportIdFound = TRUE;
  1517. break;
  1518. }
  1519. /*
  1520. * Make sure that there was a colon before continuing.
  1521. */
  1522. if (bTransportIdFound)
  1523. {
  1524. ASSERT (g_Transport != NULL);
  1525. called_address = pColon + 1;
  1526. /*
  1527. * Allocate an unused connection handle to be
  1528. * associated with the new MCS connection.
  1529. */
  1530. *connection_handle = AllocateConnectionHandle ();
  1531. /*
  1532. * Create a new connection object. The constructor
  1533. * parameters provide everything that the connection
  1534. * object will need to create a new outbound MCS
  1535. * connection.
  1536. */
  1537. DBG_SAVE_FILE_LINE
  1538. connection = new Connection (domain,
  1539. *connection_handle,
  1540. pcriConnectRequestInfo->calling_domain,
  1541. pcriConnectRequestInfo->called_domain,
  1542. called_address,
  1543. pcriConnectRequestInfo->fSecure,
  1544. pcriConnectRequestInfo->upward_connection,
  1545. pcriConnectRequestInfo->domain_parameters,
  1546. pcriConnectRequestInfo->user_data,
  1547. pcriConnectRequestInfo->user_data_length,
  1548. &return_value);
  1549. /*
  1550. * Check to see if the allocation of the connection
  1551. * worked.
  1552. */
  1553. if (connection != NULL)
  1554. {
  1555. /*
  1556. * Even if the connection object was allocated
  1557. * successfully, it is still possible that an error
  1558. * occurred while it was trying to initialize. So
  1559. * check the return value from the contructor.
  1560. */
  1561. if (return_value == MCS_NO_ERROR)
  1562. {
  1563. /*
  1564. * Put the connection into the connection list
  1565. * dictionary.
  1566. */
  1567. TRACE_OUT (("Controller::ApplicationConnectProviderRequest: "
  1568. "new connection created"));
  1569. m_ConnectionList2.Insert(*connection_handle, connection);
  1570. m_ConnPollList.Append(connection);
  1571. }
  1572. else
  1573. {
  1574. /*
  1575. * If the connection object was successfully
  1576. * allocated, but its initialization failed,
  1577. * then it is necessary to destroy the faulty
  1578. * connection and return the appropriate error
  1579. * to the caller.
  1580. */
  1581. WARNING_OUT (("Controller::ApplicationConnectProviderRequest: "
  1582. "deleting faulty connection"));
  1583. delete connection;
  1584. }
  1585. }
  1586. else
  1587. {
  1588. /*
  1589. * The allocation of the connection object has
  1590. * failed. Simply return the appropriate error and
  1591. * abort the request.
  1592. */
  1593. WARNING_OUT (("Controller::ApplicationConnectProviderRequest: "
  1594. "connection allocation failed"));
  1595. return_value = MCS_ALLOCATION_FAILURE;
  1596. }
  1597. // Put back the colon in the "called_address"
  1598. *pColon = ':';
  1599. }
  1600. else
  1601. {
  1602. /*
  1603. * There was not a colon in the called address, so MCS has
  1604. * no way of extracting the transport identifier. The request
  1605. * must therefore fail.
  1606. */
  1607. ERROR_OUT (("Controller::ApplicationConnectProviderRequest: "
  1608. "no colon in called address"));
  1609. return_value = MCS_INVALID_PARAMETER;
  1610. }
  1611. }
  1612. else
  1613. {
  1614. /*
  1615. * The domain already has an upward connection (or one pending).
  1616. * This request is therefore invalid and must be rejected.
  1617. */
  1618. ERROR_OUT (("Controller::ApplicationConnectProviderRequest: "
  1619. "domain not hierarchical"));
  1620. return_value = MCS_DOMAIN_NOT_HIERARCHICAL;
  1621. }
  1622. }
  1623. else
  1624. {
  1625. /*
  1626. * If the local domain selector does not correspond to a valid
  1627. * domain in this provider, then fail the request immediately by
  1628. * returning the appropriate error.
  1629. */
  1630. ERROR_OUT (("Controller::ApplicationConnectProviderRequest: "
  1631. "invalid local domain"));
  1632. return_value = MCS_NO_SUCH_DOMAIN;
  1633. }
  1634. return (return_value);
  1635. }
  1636. /*
  1637. * MCSError ApplicationConnectProviderResponse ()
  1638. *
  1639. * Private
  1640. *
  1641. * Functional Description:
  1642. * This request originates from one of the application interface objects.
  1643. * This happens as the result of the node controller issuing a
  1644. * ConnectProviderResponse to whichever application interface object
  1645. * that it is attached to. If the connection handle is valid, and the
  1646. * local domain still exists, then that domain will be told whether or not
  1647. * the incoming connection was accepted. This allows it to repsond
  1648. * appropriately.
  1649. *
  1650. * Formal Parameters:
  1651. * connection_handle (i)
  1652. * This identifies the connection from which a previous connect
  1653. * provider indication originated. This request essentially states
  1654. * whether or not this incoming connection is accepted.
  1655. * domain_selector (i)
  1656. * This is the domain selector of the domain that the node controller
  1657. * wishes to bind the incoming connection to.
  1658. * domain_selector_length (i)
  1659. * This is the length of the above domain selector.
  1660. * domain_parameters (i)
  1661. * This is a pointer to a structure containing the domain parameters
  1662. * that the node controller wishes to use for this connection.
  1663. * result (i)
  1664. * This is the result to be sent to the remote provider. Coming
  1665. * from the node controller this should be either RESULT_SUCCESSFUL
  1666. * or RESULT_USER_REJECTED. If it is anything but RESULT_SUCCESSFUL,
  1667. * the associated connection will be immediately destroyed.
  1668. * user_data (i)
  1669. * This is the address of the user data that is to be sent in the
  1670. * connect response PDU to the remote provider.
  1671. * user_data_length (i)
  1672. * This is the length of the user data to be sent in the connect
  1673. * response PDU to the remote provider.
  1674. *
  1675. * Return Value:
  1676. * MCS_NO_ERROR
  1677. * The response was sent to the appropriate domain successfully.
  1678. * MCS_DOMAIN_PARAMETERS_UNACCEPTABLE
  1679. * This indicates that there is no overlap in the min and max
  1680. * parameters specified by the remote node, and the min and max
  1681. * parameters acceptable to the specified domain. Therefore, no
  1682. * connection is possible. This does NOT indicate that there is
  1683. * anything wrong with the specified target parameters (which are
  1684. * just suggested values anyway).
  1685. * MCS_ALLOCATION_FAILURE
  1686. * The response failed due to a memory allocation failure.
  1687. * MCS_NO_SUCH_DOMAIN
  1688. * This indicates that the domain associated with the pending
  1689. * response has been deleted since the indication was sent.
  1690. * MCS_NO_SUCH_CONNECTION
  1691. * This indicates that the connection has been lost since the
  1692. * indication was issued.
  1693. * MCS_DOMAIN_NOT_HIERARCHICAL
  1694. * This request is attempting to create an upward connection to a
  1695. * domain that already has an upward connection (which is not valid).
  1696. *
  1697. * Side Effects:
  1698. * If the response is other than RESULT_SUCCESSFUL, the transport
  1699. * connection that conveys the connect response PDU will be severed.
  1700. *
  1701. * Caveats:
  1702. * None.
  1703. */
  1704. MCSError Controller::ApplicationConnectProviderResponse (
  1705. ConnectionHandle connection_handle,
  1706. GCCConfID *domain_selector,
  1707. PDomainParameters domain_parameters,
  1708. Result result,
  1709. PUChar user_data,
  1710. ULong user_data_length)
  1711. {
  1712. PConnectionPending connection_pending;
  1713. TransportConnection transport_connection;
  1714. BOOL upward_connection;
  1715. PDomain domain;
  1716. PConnection connection;
  1717. MCSError return_value;
  1718. /*
  1719. * Check to see if the connection handle corresponds to a connection
  1720. * that is awaiting a response.
  1721. */
  1722. if (NULL != (connection_pending = m_ConnPendingList2.Find(connection_handle)))
  1723. {
  1724. /*
  1725. * Get the address of the structure containing information about the
  1726. * pending connection. Then load the contained information into
  1727. * automatic variables for easier manipulation.
  1728. */
  1729. transport_connection = connection_pending->transport_connection;
  1730. upward_connection = connection_pending->upward_connection;
  1731. if (domain_parameters == NULL)
  1732. domain_parameters = &connection_pending->domain_parameters;
  1733. /*
  1734. * See if the node controller has elected to accept or reject the
  1735. * incoming connection. If it is accepted, then the response must
  1736. * be sent through the appropriate domain object. If it is
  1737. * rejected, then the response can be sent directly to the
  1738. * connection object (which will then delete itself).
  1739. */
  1740. if (result == RESULT_SUCCESSFUL)
  1741. {
  1742. /*
  1743. * See if the specified domain is valid, before trying to send
  1744. * the response to it.
  1745. */
  1746. if (NULL != (domain = m_DomainList2.Find(*domain_selector)))
  1747. {
  1748. /*
  1749. * Check to make sure that the requested connection is valid.
  1750. * Specifically, make sure that this is not a request for an
  1751. * upward connection to a domain that already has an upward
  1752. * connection. This would result in a non-hierarchical domain,
  1753. * which is illegal.
  1754. */
  1755. if ((upward_connection == FALSE) || (domain->IsTopProvider ()))
  1756. {
  1757. /*
  1758. * Create the connection object that will be responsible
  1759. * for the inbound connection. It will automatically issue
  1760. * a ConnectResponse during construction.
  1761. */
  1762. DBG_SAVE_FILE_LINE
  1763. connection = new Connection (domain,
  1764. connection_handle, transport_connection,
  1765. upward_connection, domain_parameters,
  1766. &connection_pending->minimum_domain_parameters,
  1767. &connection_pending->maximum_domain_parameters,
  1768. user_data, user_data_length,
  1769. &return_value);
  1770. if (connection != NULL)
  1771. {
  1772. if (return_value == MCS_NO_ERROR)
  1773. {
  1774. /*
  1775. * Everything worked fine. Remove the connection
  1776. * handle from the pending list, and put the newly
  1777. * created connection object into the active
  1778. * connection list.
  1779. */
  1780. TRACE_OUT(("Controller::ApplicationConnectProviderResponse: "
  1781. "connection created successfully"));
  1782. m_ConnPendingList2.Remove(connection_handle);
  1783. delete connection_pending;
  1784. m_ConnectionList2.Insert(connection_handle, connection);
  1785. m_ConnPollList.Append(connection);
  1786. }
  1787. else
  1788. {
  1789. /*
  1790. * The contructor failed, which probably indicates
  1791. * an allocation failure. Report this to the node
  1792. * controller, and delete the faulty connection
  1793. * object.
  1794. */
  1795. WARNING_OUT (("Controller::ApplicationConnectProviderResponse: "
  1796. "connection constructor failed"));
  1797. delete connection;
  1798. }
  1799. }
  1800. else
  1801. {
  1802. /*
  1803. * The allocation failed. Report this to the node
  1804. * controller.
  1805. */
  1806. WARNING_OUT (("Controller::ApplicationConnectProviderResponse: "
  1807. "connection constructor failed"));
  1808. return_value = MCS_ALLOCATION_FAILURE;
  1809. }
  1810. }
  1811. else
  1812. {
  1813. /*
  1814. * The domain already has an upward connection (or one
  1815. * pending). This request is therefore invalid and must be
  1816. * rejected.
  1817. */
  1818. ERROR_OUT (("Controller::ApplicationConnectProviderResponse:"
  1819. " domain not hierarchical"));
  1820. return_value = MCS_DOMAIN_NOT_HIERARCHICAL;
  1821. }
  1822. }
  1823. else
  1824. {
  1825. /*
  1826. * If the indicated domain is not valid, then simply return
  1827. * the appropriate error.
  1828. */
  1829. WARNING_OUT (("Controller::ApplicationConnectProviderResponse: "
  1830. "invalid domain"));
  1831. return_value = MCS_NO_SUCH_DOMAIN;
  1832. }
  1833. }
  1834. else
  1835. {
  1836. /*
  1837. * The node controller has elected to reject the incoming
  1838. * connection. It is therefore not necessary to create a
  1839. * connection object. Send the connect response directly to
  1840. * the transport interface object, and then disconnect the
  1841. * transport connection.
  1842. */
  1843. TRACE_OUT (("Controller::ApplicationConnectProviderResponse: connection rejected"));
  1844. ASSERT (g_Transport);
  1845. ConnectResponse (transport_connection, result,
  1846. domain_parameters, 0, user_data, user_data_length);
  1847. g_Transport->DisconnectRequest (transport_connection);
  1848. /*
  1849. * Remove the connection handle from the pending list, and
  1850. * delete the structure that was holding information about
  1851. * the pending connection.
  1852. */
  1853. m_ConnPendingList2.Remove(connection_handle);
  1854. delete connection_pending;
  1855. return_value = MCS_NO_ERROR;
  1856. }
  1857. }
  1858. else
  1859. {
  1860. /*
  1861. * If the connection handle is no longer valid, then fail the request
  1862. * with the appropriate error.
  1863. */
  1864. WARNING_OUT (("Controller::ApplicationConnectProviderResponse: "
  1865. "invalid connection"));
  1866. return_value = MCS_NO_SUCH_CONNECTION;
  1867. }
  1868. return (return_value);
  1869. }
  1870. /*
  1871. * MCSError ApplicationDisconnectProviderRequest ()
  1872. *
  1873. * Private
  1874. *
  1875. * Functional Description:
  1876. * This request originates from one of the application interface objects.
  1877. * This happens as the result of the node controller issuing a
  1878. * DisconnectProviderRequest to whichever application interface object
  1879. * that it is attached to. If the connection handle is valid, then the
  1880. * connection object wil be destroyed, which will break the transport
  1881. * connections associated with it.
  1882. *
  1883. * Formal Parameters:
  1884. * connection_handle (i)
  1885. * This identifies the connection to be destroyed.
  1886. *
  1887. * Return Value:
  1888. * MCS_NO_ERROR
  1889. * The named connection has been successfully deleted.
  1890. * MCS_NO_SUCH_CONNECTION
  1891. * The connection handle is invalid.
  1892. *
  1893. * Side Effects:
  1894. * One or more transport connections will be broken. Furthermore, if
  1895. * this is an upward connection for a domain, then the domain itself
  1896. * will be eradicated (all attachments and connections will be severed).
  1897. *
  1898. * Caveats:
  1899. * None.
  1900. */
  1901. MCSError Controller::ApplicationDisconnectProviderRequest (
  1902. ConnectionHandle connection_handle)
  1903. {
  1904. MCSError return_value;
  1905. PConnection connection;
  1906. PConnectionPending connection_pending;
  1907. /*
  1908. * Check to see if the connection handle refers to an existing connection.
  1909. */
  1910. if (NULL != (connection = m_ConnectionList2.Find(connection_handle)))
  1911. {
  1912. /*
  1913. * If the connection handle is valid, then delete the associated
  1914. * connection and remove it from the connection dictionary. It is also
  1915. * necessary to delete the connection information structure.
  1916. */
  1917. TRACE_OUT (("Controller::ApplicationDisconnectProviderRequest: "
  1918. "deleting connection"));
  1919. m_ConnectionList2.Remove(connection_handle);
  1920. m_ConnPollList.Remove(connection);
  1921. delete connection;
  1922. /*
  1923. * Check to see if this connection handle is also in the connection
  1924. * deletion list. If so, then remove it from there as well.
  1925. */
  1926. m_ConnectionDeletionList2.Remove(connection_handle);
  1927. return_value = MCS_NO_ERROR;
  1928. }
  1929. else if (NULL != (connection_pending = m_ConnPendingList2.Remove(connection_handle)))
  1930. {
  1931. /*
  1932. * This connection handle refers to a connection that is still
  1933. * pending. Delete it from there.
  1934. */
  1935. WARNING_OUT (("Controller::ApplicationDisconnectProviderRequest: "
  1936. "deleting pending connection"));
  1937. delete connection_pending;
  1938. return_value = MCS_NO_ERROR;
  1939. }
  1940. else
  1941. {
  1942. /*
  1943. * If the connection handle is not in either of the above dictionaries,
  1944. * then return the appropriate error.
  1945. */
  1946. TRACE_OUT (("Controller::ApplicationDisconnectProviderRequest: "
  1947. "invalid connection"));
  1948. return_value = MCS_NO_SUCH_CONNECTION;
  1949. }
  1950. return (return_value);
  1951. }
  1952. /*
  1953. * MCSError ApplicationAttachUserRequest ()
  1954. *
  1955. * Private
  1956. *
  1957. * Functional Description:
  1958. * This function is used to attach a user application to an existing
  1959. * domain. The user handle that is returned can then be used by the
  1960. * application to request services from MCS.
  1961. *
  1962. * After verifying that the specified domain really does exist, the
  1963. * controller will create a new user object. The new user object will
  1964. * attach itself to both the domain and the application interface
  1965. * specified by the controller. At that point, information can flow
  1966. * through the application interface to the user and then on to the
  1967. * domain without having to pass through the controller.
  1968. *
  1969. * Formal Parameters:
  1970. * domain_selector (i)
  1971. * This identifies the domain to which the user wants to attach.
  1972. * domain_selector_length (i)
  1973. * This is the length of the above domain selector.
  1974. * attachment_flags (i)
  1975. * This is a set of flags that allow the user application to control
  1976. * how the attachment is handled. The only flag currently used by
  1977. * the controller specifies whether or not the user wants to receive
  1978. * callbacks during the controller's heartbeat.
  1979. * ppUser (o)
  1980. * This is a pointer to a user handle, which will be set to a valid
  1981. * value by the controller if this function completes successfully.
  1982. * The user handle is really a pointer to a User object.
  1983. *
  1984. * Return Value:
  1985. * MCS_NO_ERROR
  1986. * Everything completed successfully. Note that the attachment
  1987. * cannot actually be used by the user application until it has
  1988. * received a successful attach user confirm from the domain to
  1989. * which it has attached. This return value merely indicates that
  1990. * process was started successfully.
  1991. * MCS_ALLOCATION_FAILURE
  1992. * This attach request was unable to successfully complete due to a
  1993. * memory allocation failure.
  1994. * MCS_NO_SUCH_DOMAIN
  1995. * This attach request was unable to successfully complete because
  1996. * the specified domain does not exist within this provider.
  1997. *
  1998. * Side Effects:
  1999. * None.
  2000. *
  2001. * Caveats:
  2002. * None.
  2003. */
  2004. MCSError Controller::ApplicationAttachUserRequest
  2005. (
  2006. GCCConfID *domain_selector,
  2007. PUser *ppUser
  2008. )
  2009. {
  2010. MCSError return_value;
  2011. PDomain domain;
  2012. /*
  2013. * First of all make sure that the domain selector refers to a valid
  2014. * domain. If it doesn't, then return the appropriate error.
  2015. */
  2016. if (NULL != (domain = m_DomainList2.Find(*domain_selector)))
  2017. {
  2018. /*
  2019. * Instantiate a new user object, with the domain and the application
  2020. * interface pointer as parameters.
  2021. */
  2022. DBG_SAVE_FILE_LINE
  2023. *ppUser = (PUser) new User (domain, &return_value);
  2024. /*
  2025. * Make sure the allocation completed successfully
  2026. */
  2027. if (*ppUser != NULL) {
  2028. /*
  2029. * The creation of the user object was successful.
  2030. */
  2031. if (return_value != MCS_NO_ERROR) {
  2032. // We have to cleanup the object.
  2033. (*ppUser)->Release();
  2034. }
  2035. }
  2036. else {
  2037. /*
  2038. * There was a memory allocation failure, so return the
  2039. * appropriate error.
  2040. */
  2041. WARNING_OUT (("Controller::ApplicationAttachUserRequest: "
  2042. "user creation failed"));
  2043. return_value = MCS_ALLOCATION_FAILURE;
  2044. }
  2045. }
  2046. else
  2047. {
  2048. /*
  2049. * The specified domain does not exist, so return the appropriate
  2050. * error.
  2051. */
  2052. WARNING_OUT (("Controller::ApplicationAttachUserRequest: invalid domain"));
  2053. return_value = MCS_NO_SUCH_DOMAIN;
  2054. }
  2055. return (return_value);
  2056. }
  2057. /*
  2058. * Void ConnectionDeleteConnection ()
  2059. *
  2060. * Private
  2061. *
  2062. * Functional Description:
  2063. * This request originates within a connection object when it determines
  2064. * the need to delete itself. This is usually caused by one of three
  2065. * things. First, the connection was rejected (inbound or outbound).
  2066. * Second, either the local or remote domain issued a disconnect
  2067. * provider ultimatum. Or third, a transport connection was unexpectedly
  2068. * lost.
  2069. *
  2070. * The controller responds by deleting the connection, after the
  2071. * parameters are validated. It also issues a disconnect provider
  2072. * indication to the node controller.
  2073. *
  2074. * Formal Parameters:
  2075. * connection_handle (i)
  2076. * This is the handle of the connection object that wishes to be
  2077. * deleted.
  2078. *
  2079. * Return Value:
  2080. * None.
  2081. *
  2082. * Side Effects:
  2083. * An MCS connection is terminated, which may result in the destruction
  2084. * of one or more transport connections.
  2085. *
  2086. * Caveats:
  2087. * None.
  2088. */
  2089. Void Controller::ConnectionDeleteConnection (
  2090. ConnectionHandle connection_handle)
  2091. {
  2092. PConnection connection;
  2093. /*
  2094. * Make sure the connection handle is in the dictionary before proceeding.
  2095. */
  2096. if (NULL != (connection = m_ConnectionList2.Find(connection_handle)))
  2097. {
  2098. /*
  2099. * See if the deletion of this connection is already pending. If so,
  2100. * there is no need to queue it up again.
  2101. */
  2102. if (! m_ConnectionDeletionList2.Find(connection_handle))
  2103. {
  2104. /*
  2105. * Put the connection object into the deletion list and set the
  2106. * deletion pending flag.
  2107. */
  2108. TRACE_OUT (("Controller::ConnectionDeleteConnection: "
  2109. "adding connection to deletion list"));
  2110. m_ConnectionDeletionList2.Insert(connection_handle, connection);
  2111. Connection_Deletion_Pending = TRUE;
  2112. SetEvent(Connection_Deletion_Pending_Event);
  2113. /*
  2114. * Post the message to the controller window (GCC and MCS
  2115. * use the same window to post messages to their controllers).
  2116. */
  2117. if (! PostMessage (g_pControlSap->GetHwnd(),
  2118. MCTRLMSG_BASE + MCS_DISCONNECT_PROVIDER_INDICATION,
  2119. NULL, (LPARAM) connection_handle)) {
  2120. ERROR_OUT(("Controller::ConnectionDeleteConnection: "
  2121. "failed to post msg to MCS controller window. Error: %d", GetLastError()));
  2122. }
  2123. }
  2124. }
  2125. else
  2126. {
  2127. /*
  2128. * If the connection handle cannot be found in the connection
  2129. * dictionary, then simply ignore the request.
  2130. */
  2131. WARNING_OUT (("Controller::ConnectionDeleteConnection: "
  2132. "unknown connection"));
  2133. }
  2134. }
  2135. /*
  2136. * Void ConnectionConnectProviderConfirm ()
  2137. *
  2138. * Private
  2139. *
  2140. * Functional Description:
  2141. * This request originates within a domain object upon reception of a
  2142. * connect response PDU. The controller responds by sending a connect
  2143. * provider confirm to the node controller.
  2144. *
  2145. * Formal Parameters:
  2146. * connection_handle (i)
  2147. * This is the handle of the connection object from which the connect
  2148. * provider confirm was received.
  2149. * domain_parameters (i)
  2150. * This is a pointer to a structure that contains the domain parameters
  2151. * that were decided on during capabilities arbitration.
  2152. * result (i)
  2153. * This contains the result of the connect request. Anything but
  2154. * RESULT_SUCCESSFUL means that the connection was rejected.
  2155. * memory (i)
  2156. * If this is not NULL, it contains the user data that was received
  2157. * in the connect response PDU.
  2158. *
  2159. * Return Value:
  2160. * None.
  2161. *
  2162. * Side Effects:
  2163. * A connect provider confirm is sent to the node controller.
  2164. *
  2165. * Caveats:
  2166. * None.
  2167. */
  2168. void Controller::ConnectionConnectProviderConfirm (
  2169. ConnectionHandle connection_handle,
  2170. PDomainParameters domain_parameters,
  2171. Result result,
  2172. PMemory memory)
  2173. {
  2174. PConnection connection;
  2175. PUChar user_data;
  2176. ULong user_data_length;
  2177. ConnectProviderConfirm *pconnect_provider_confirm;
  2178. /*
  2179. * Make sure the connection handle is in the dictionary before proceeding.
  2180. */
  2181. if (NULL != (connection = m_ConnectionList2.Find(connection_handle)))
  2182. {
  2183. // Allocate the node controller msg.
  2184. DBG_SAVE_FILE_LINE
  2185. pconnect_provider_confirm = new ConnectProviderConfirm;
  2186. if (pconnect_provider_confirm != NULL) {
  2187. /*
  2188. * Check to see if there is user data associated with this confirm.
  2189. */
  2190. if (memory != NULL)
  2191. {
  2192. /*
  2193. * If there is user data, lock it, and get the address and length
  2194. * into temporary variables.
  2195. */
  2196. LockMemory (memory);
  2197. user_data = memory->GetPointer ();
  2198. user_data_length = memory->GetLength ();
  2199. }
  2200. else
  2201. {
  2202. /*
  2203. * If there is no user data, then set the address and length fields
  2204. * to default values.
  2205. */
  2206. user_data = NULL;
  2207. user_data_length = 0;
  2208. }
  2209. /*
  2210. * Put all information about this confirm into the node controller
  2211. * message structure allocated above.
  2212. */
  2213. pconnect_provider_confirm->connection_handle = (ConnectionHandle) connection_handle;
  2214. pconnect_provider_confirm->domain_parameters = *domain_parameters;
  2215. pconnect_provider_confirm->result = result;
  2216. pconnect_provider_confirm->user_data = user_data;
  2217. pconnect_provider_confirm->user_data_length = user_data_length;
  2218. pconnect_provider_confirm->pb_cred = NULL;
  2219. pconnect_provider_confirm->cb_cred = 0;
  2220. DWORD cb = 0;
  2221. if (GetSecurityInfo(connection_handle, NULL, &cb))
  2222. {
  2223. if (cb > 0 && NOT_DIRECTLY_CONNECTED != cb)
  2224. {
  2225. pconnect_provider_confirm->pb_cred = (PBYTE) CoTaskMemAlloc(cb);
  2226. if (NULL != pconnect_provider_confirm->pb_cred)
  2227. {
  2228. if (GetSecurityInfo(connection_handle, pconnect_provider_confirm->pb_cred, &cb))
  2229. {
  2230. pconnect_provider_confirm->cb_cred = cb;
  2231. }
  2232. else
  2233. {
  2234. CoTaskMemFree(pconnect_provider_confirm->pb_cred);
  2235. pconnect_provider_confirm->pb_cred = NULL;
  2236. }
  2237. }
  2238. else
  2239. {
  2240. ERROR_OUT(("Controller::ConnectionConnectProviderConfirm: Memory Allocation Error"));
  2241. }
  2242. }
  2243. }
  2244. /*
  2245. * Post the message to the controller window (GCC and MCS
  2246. * use the same window to post messages to their controllers).
  2247. */
  2248. if (! PostMessage (g_pControlSap->GetHwnd(),
  2249. MCTRLMSG_BASE + MCS_CONNECT_PROVIDER_CONFIRM,
  2250. (WPARAM) memory, (LPARAM) pconnect_provider_confirm))
  2251. {
  2252. delete pconnect_provider_confirm;
  2253. pconnect_provider_confirm = NULL;
  2254. ERROR_OUT(("Controller::ConnectionDeleteConnection: "
  2255. "failed to post msg to MCS controller window. Error: %d", GetLastError()));
  2256. }
  2257. /*
  2258. * If the result of this confirm is not successful, and the connection
  2259. * is not already queued for deletion, then we need to queue it for
  2260. * deletion.
  2261. */
  2262. if ((result != RESULT_SUCCESSFUL) &&
  2263. (! m_ConnectionDeletionList2.Find(connection_handle)))
  2264. {
  2265. /*
  2266. * Put the connection object into the deletion list and set the
  2267. * deletion pending flag.
  2268. */
  2269. TRACE_OUT (("Controller::ConnectionConnectProviderConfirm: "
  2270. "adding connection to deletion list"));
  2271. m_ConnectionDeletionList2.Insert(connection_handle, connection);
  2272. Connection_Deletion_Pending = TRUE;
  2273. SetEvent(Connection_Deletion_Pending_Event);
  2274. }
  2275. }
  2276. else
  2277. ERROR_OUT(("Controller::ConnectionConnectProviderConfirm: "
  2278. "failed to allocate node controller msg."));
  2279. }
  2280. else
  2281. {
  2282. /*
  2283. * If the connection handle cannot be found in the connection
  2284. * dictionary, then simply ignore the request.
  2285. */
  2286. WARNING_OUT (("Controller::ConnectionConnectProviderConfirm: "
  2287. "unknown connection"));
  2288. }
  2289. }
  2290. /*
  2291. * Void TransportDisconnectIndication ()
  2292. *
  2293. * Private
  2294. *
  2295. * Functional Description:
  2296. * This request originates within a transport interface object when it
  2297. * gets a disconnect indication from the transport layer for a transport
  2298. * connection that is not assigned to a connection object. This could
  2299. * happen in the case where a remote node issues a connect provider request
  2300. * followed by a disconnect provider request before this node issues a
  2301. * connect provider response.
  2302. *
  2303. * The controller responds by simply removing the information from the
  2304. * connection pending list.
  2305. *
  2306. * Formal Parameters:
  2307. * transport_connection (i)
  2308. * This is the transport connection handle that has been assigned to
  2309. * the newly created transport connection.
  2310. *
  2311. * Return Value:
  2312. * None.
  2313. *
  2314. * Side Effects:
  2315. * None.
  2316. *
  2317. * Caveats:
  2318. * None.
  2319. */
  2320. Void Controller::TransportDisconnectIndication (
  2321. TransportConnection transport_connection)
  2322. {
  2323. PConnectionPending connection_pending;
  2324. ConnectionHandle connection_handle;
  2325. /*
  2326. * Find the entry in the connection pending list which is associated with
  2327. * the given transport connection. If found, remove the entry.
  2328. */
  2329. m_ConnPendingList2.Reset();
  2330. while (NULL != (connection_pending = m_ConnPendingList2.Iterate(&connection_handle)))
  2331. {
  2332. if (IS_SAME_TRANSPORT_CONNECTION(connection_pending->transport_connection, transport_connection))
  2333. {
  2334. m_ConnPendingList2.Remove(connection_handle);
  2335. delete connection_pending;
  2336. break;
  2337. }
  2338. }
  2339. }
  2340. /*
  2341. * Void TransportDataIndication ()
  2342. *
  2343. * Private
  2344. *
  2345. * Functional Description:
  2346. * This function is called when data is received from the transport layer
  2347. * on a transport connection that no other object has registered
  2348. * ownership of.
  2349. *
  2350. * Formal Parameters:
  2351. * transport_connection (i)
  2352. * This is the transport connection handle that has been assigned to
  2353. * the newly created transport connection.
  2354. * user_data
  2355. * A pointer to the data received.
  2356. * user_data_length
  2357. * The length of the data received.
  2358. *
  2359. * Return Value:
  2360. * None.
  2361. *
  2362. * Side Effects:
  2363. * None.
  2364. *
  2365. * Caveats:
  2366. * None.
  2367. */
  2368. Void Controller::TransportDataIndication (
  2369. TransportConnection transport_connection,
  2370. PUChar user_data,
  2371. ULong user_data_length)
  2372. {
  2373. PPacket packet;
  2374. PacketError packet_error;
  2375. PVoid pdu_structure;
  2376. ASSERT (g_Transport);
  2377. /*
  2378. * Create a packet from the encoded data received from the transport
  2379. * interface. Retrieve the decoded PDU structure from the packet and
  2380. * pass it on to the appropriate processing routine.
  2381. */
  2382. DBG_SAVE_FILE_LINE
  2383. packet = new Packet (
  2384. (PPacketCoder) g_MCSCoder,
  2385. BASIC_ENCODING_RULES,
  2386. user_data + PROTOCOL_OVERHEAD_X224,
  2387. user_data_length - PROTOCOL_OVERHEAD_X224,
  2388. CONNECT_MCS_PDU,
  2389. TRUE,
  2390. &packet_error);
  2391. if (packet != NULL)
  2392. {
  2393. if (packet_error == PACKET_NO_ERROR)
  2394. {
  2395. /*
  2396. * Get a pointer to the decoded data.
  2397. */
  2398. pdu_structure = packet->GetDecodedData ();
  2399. switch (((ConnectMCSPDU *) pdu_structure)->choice)
  2400. {
  2401. case CONNECT_INITIAL_CHOSEN:
  2402. ProcessConnectInitial (
  2403. transport_connection,
  2404. &((ConnectMCSPDU *) pdu_structure)->u.
  2405. connect_initial);
  2406. break;
  2407. case CONNECT_ADDITIONAL_CHOSEN:
  2408. ProcessConnectAdditional (
  2409. transport_connection,
  2410. &((ConnectMCSPDU *) pdu_structure)->u.
  2411. connect_additional);
  2412. break;
  2413. default:
  2414. ERROR_OUT (("Controller::TransportDataIndication: "
  2415. "received invalid PDU (%d)",
  2416. ((ConnectMCSPDU *) pdu_structure)->choice));
  2417. g_Transport->DisconnectRequest (transport_connection);
  2418. break;
  2419. }
  2420. }
  2421. else
  2422. {
  2423. /*
  2424. * A memory allocation failure has prevented us from processing
  2425. * this PDU. Destroy the connection that carried it.
  2426. */
  2427. WARNING_OUT (("Controller::TransportDataIndication: "
  2428. "packet constructor failed"));
  2429. g_Transport->DisconnectRequest (transport_connection);
  2430. }
  2431. packet->Unlock ();
  2432. }
  2433. else
  2434. {
  2435. /*
  2436. * A memory allocation failure has prevented us from processing
  2437. * this PDU. Destroy the connection that carried it.
  2438. */
  2439. WARNING_OUT (("Controller::TransportDataIndication: "
  2440. "packet allocation failed"));
  2441. g_Transport->DisconnectRequest (transport_connection);
  2442. }
  2443. }
  2444. #ifdef TSTATUS_INDICATION
  2445. /*
  2446. * Void TransportStatusIndication ()
  2447. *
  2448. * Private
  2449. *
  2450. * Functional Description:
  2451. * This request originates within a transport interface object when it
  2452. * receives a status indication from its transport layer. This function
  2453. * will forward the status indication to the node controller.
  2454. *
  2455. * Formal Parameters:
  2456. * transport_status
  2457. * This is a pointer to the TransportStatus structure that describes
  2458. * the reason for the indication.
  2459. *
  2460. * Return Value:
  2461. * None.
  2462. *
  2463. * Side Effects:
  2464. * None.
  2465. *
  2466. * Caveats:
  2467. * None.
  2468. */
  2469. Void Controller::TransportStatusIndication (
  2470. PTransportStatus transport_status)
  2471. {
  2472. ULong device_identifier_length;
  2473. ULong remote_address_length;
  2474. ULong message_length;
  2475. PMemory memory;
  2476. PUChar string_address;
  2477. PNodeControllerMessage node_controller_message;
  2478. /*
  2479. * Determine the length of each of the ASCII strings contained in the
  2480. * transport status indications. This will be used to allocate a
  2481. * memory block large enough to hold them all. Note that each length
  2482. * includes one extra byte to hold the ASCII NULL terminator.
  2483. */
  2484. device_identifier_length =
  2485. (ULong) lstrlen (transport_status->device_identifier) + 1;
  2486. remote_address_length =
  2487. (ULong) lstrlen (transport_status->remote_address) + 1;
  2488. message_length =
  2489. (ULong) lstrlen (transport_status->message) + 1;
  2490. /*
  2491. * Use the memory manager to allocate a memory block large enough to
  2492. * hold all of the strings.
  2493. */
  2494. DBG_SAVE_FILE_LINE
  2495. memory = AllocateMemory (NULL,
  2496. (device_identifier_length + remote_address_length + message_length));
  2497. if (memory != NULL)
  2498. {
  2499. DBG_SAVE_FILE_LINE
  2500. node_controller_message = new NodeControllerMessage;
  2501. if (node_controller_message != NULL) {
  2502. /*
  2503. * Get the address of the memory block that was allocated.
  2504. */
  2505. string_address = memory->GetPointer ();
  2506. /*
  2507. * Indicate what type of message this is.
  2508. */
  2509. node_controller_message->message_type = MCS_TRANSPORT_STATUS_INDICATION;
  2510. /*
  2511. * Copy all of the ASCII strings into the memory block that was
  2512. * allocated above. This block will remain valid until this
  2513. * message is sent to the node controller.
  2514. */
  2515. memcpy (string_address, transport_status->device_identifier,
  2516. device_identifier_length);
  2517. node_controller_message->u.transport_status_indication.
  2518. device_identifier = (PChar) string_address;
  2519. string_address += (Int) device_identifier_length;
  2520. memcpy (string_address, transport_status->remote_address,
  2521. remote_address_length);
  2522. node_controller_message->u.transport_status_indication.
  2523. remote_address = (PChar) string_address;
  2524. string_address += (Int) remote_address_length;
  2525. memcpy (string_address, transport_status->message,
  2526. message_length);
  2527. node_controller_message->u.transport_status_indication.
  2528. message = (PChar) string_address;
  2529. node_controller_message->u.transport_status_indication.
  2530. state = transport_status->state;
  2531. node_controller_message->memory = memory;
  2532. /*
  2533. * Put this message into the control queue to be sent to the node
  2534. * controller during the next heartbeat.
  2535. */
  2536. AddToMessageQueue (node_controller_message);
  2537. }
  2538. else
  2539. WARNING_OUT(("Controller::TransportStatusIndication: "
  2540. "WARNING - memory allocation failure"));
  2541. }
  2542. else
  2543. {
  2544. /*
  2545. * A memory allocation failure has occurred. This prevents us from
  2546. * being able to deliver this status indication to the node controller.
  2547. * This does not compromise the integrity of MCS, but could cause
  2548. * problems at a higher level.
  2549. */
  2550. ERROR_OUT (("Controller::TransportStatusIndication: "
  2551. "WARNING - memory allocation failure"));
  2552. }
  2553. }
  2554. #endif
  2555. /*
  2556. * Void ProcessConnectInitial()
  2557. *
  2558. * Private
  2559. *
  2560. * Functional Description:
  2561. * Processes incoming connect initial PDUs. Sends a connect provider
  2562. * indication to the node controller if everything checks out.
  2563. *
  2564. * Formal Parameters:
  2565. * transport_connection (i)
  2566. * This is assigned transport connection handle for the connection
  2567. * that carried the PDU.
  2568. * pdu_structure (i)
  2569. * This is a pointer to the PDU itself.
  2570. *
  2571. * Return Value:
  2572. * None.
  2573. *
  2574. * Side Effects:
  2575. * None.
  2576. *
  2577. * Caveats:
  2578. * None.
  2579. */
  2580. void Controller::ProcessConnectInitial (
  2581. TransportConnection transport_connection,
  2582. ConnectInitialPDU * pdu_structure)
  2583. {
  2584. PConnectionPending connection_pending;
  2585. PMemory memory;
  2586. PUChar memory_address;
  2587. ConnectProviderIndication *pconnect_provider_indication;
  2588. ConnectionHandle connection_handle;
  2589. BOOL upward_connection;
  2590. //DomainParameters domain_parameters;
  2591. /*
  2592. * Try to allocate a connection pending structure. This will be used to
  2593. * hold information about the incoming connection that will not be passed
  2594. * back in the connect provider response.
  2595. */
  2596. DBG_SAVE_FILE_LINE
  2597. connection_pending = new ConnectionPending;
  2598. DBG_SAVE_FILE_LINE
  2599. pconnect_provider_indication = new ConnectProviderIndication;
  2600. if (connection_pending != NULL && pconnect_provider_indication != NULL)
  2601. {
  2602. /*
  2603. * Allocate a memory block to hold the user data field in the
  2604. * incoming connection.
  2605. */
  2606. DBG_SAVE_FILE_LINE
  2607. memory = AllocateMemory (NULL, pdu_structure->user_data.length);
  2608. if (memory != NULL) {
  2609. memory_address = memory->GetPointer ();
  2610. /*
  2611. * Allocate a connection handle for this inbound connection,
  2612. * and put it into the indication structure. Also fill in the
  2613. * physical connection handle, which is obtained by asking the
  2614. * transport interface for it.
  2615. */
  2616. connection_handle = AllocateConnectionHandle ();
  2617. pconnect_provider_indication->connection_handle = connection_handle;
  2618. pconnect_provider_indication->fSecure =
  2619. g_Transport->GetSecurity ( transport_connection );
  2620. /*
  2621. * Copy the user data field into the
  2622. * newly allocated memory block. Also set the pointers in
  2623. * the node controller message structure to point into the
  2624. * memory block.
  2625. */
  2626. memcpy (memory_address,
  2627. pdu_structure->user_data.value,
  2628. pdu_structure->user_data.length);
  2629. pconnect_provider_indication->user_data = memory_address;
  2630. pconnect_provider_indication->user_data_length =
  2631. pdu_structure->user_data.length;
  2632. /*
  2633. * Retrieve the direction of the incoming connection. Put it
  2634. * into both the connect provider indication structure and the
  2635. * connection pending structure. Note that in the connection
  2636. * pending structure, we need to reverse the direction of the
  2637. * flag so that it is from the point-of-view of this provider.
  2638. */
  2639. upward_connection = pdu_structure->upward_flag;
  2640. pconnect_provider_indication->upward_connection = upward_connection;
  2641. if (upward_connection)
  2642. connection_pending->upward_connection = FALSE;
  2643. else
  2644. connection_pending->upward_connection = TRUE;
  2645. /*
  2646. * Retrieve the target domain parameters and put them into both
  2647. * the connect provider indication structure, and into the
  2648. * connection pending structure (for possible later use).
  2649. */
  2650. memcpy (&(pconnect_provider_indication->domain_parameters),
  2651. &(pdu_structure->target_parameters), sizeof (PDUDomainParameters));
  2652. memcpy (&(connection_pending->domain_parameters),
  2653. &(pdu_structure->target_parameters), sizeof (PDUDomainParameters));
  2654. /*
  2655. * Retrieve the minimum domain parameters and put them into
  2656. * the connection pending structure (for possible later use).
  2657. */
  2658. memcpy (&(connection_pending->minimum_domain_parameters),
  2659. &(pdu_structure->minimum_parameters), sizeof(PDUDomainParameters));
  2660. /*
  2661. * Retrieve the maximum domain parameters and put them into
  2662. * the connection pending structure (for possible later use).
  2663. */
  2664. memcpy (&(connection_pending->maximum_domain_parameters),
  2665. &(pdu_structure->maximum_parameters), sizeof(PDUDomainParameters));
  2666. /*
  2667. * Post the message to the controller window (GCC and MCS
  2668. * use the same window to post messages to their controllers).
  2669. */
  2670. if (NULL != g_pControlSap) {
  2671. if (! PostMessage (g_pControlSap->GetHwnd(),
  2672. MCTRLMSG_BASE + MCS_CONNECT_PROVIDER_INDICATION,
  2673. (WPARAM) memory, (LPARAM) pconnect_provider_indication)) {
  2674. ERROR_OUT(("Controller::ProcessConnectInitial: "
  2675. "failed to post msg to MCS controller window. Error: %d", GetLastError()));
  2676. }
  2677. }
  2678. /*
  2679. * We also need to remember which transport interface and
  2680. * transport connection are associated with this pending
  2681. * MCS connection. Then put the connection pending structure
  2682. * into a list for later use.
  2683. */
  2684. connection_pending->transport_connection = transport_connection;
  2685. m_ConnPendingList2.Append(connection_handle, connection_pending);
  2686. // No errors have occurred.
  2687. return;
  2688. }
  2689. }
  2690. /*
  2691. * A memory allocation failure has occurred. We have no choice
  2692. * but to terminate the connection upon which this PDU arrived.
  2693. */
  2694. ASSERT (g_Transport);
  2695. WARNING_OUT(("Controller::ProcessConnectInitial: memory allocation failure"));
  2696. delete connection_pending;
  2697. delete pconnect_provider_indication;
  2698. g_Transport->DisconnectRequest (transport_connection);
  2699. }
  2700. /*
  2701. * Void ProcessConnectAdditional ()
  2702. *
  2703. * Private
  2704. *
  2705. * Functional Description:
  2706. * Processes incoming connect additional PDUs. If the connection handle
  2707. * contained therein is valid, it will bind the connection to the
  2708. * proper connection object.
  2709. *
  2710. * Formal Parameters:
  2711. * transport_connection (i)
  2712. * This is assigned transport connection handle for the connection
  2713. * that carried the PDU.
  2714. * pdu_structure (i)
  2715. * This is a pointer to the PDU itself.
  2716. *
  2717. * Return Value:
  2718. * None.
  2719. *
  2720. * Side Effects:
  2721. * None.
  2722. *
  2723. * Caveats:
  2724. * None.
  2725. */
  2726. Void Controller::ProcessConnectAdditional (
  2727. TransportConnection transport_connection,
  2728. ConnectAdditionalPDU * pdu_structure)
  2729. {
  2730. ConnectionHandle connection_handle;
  2731. Priority priority;
  2732. PConnection connection;
  2733. ASSERT (g_Transport);
  2734. connection_handle = (ConnectionHandle) pdu_structure->called_connect_id;
  2735. priority = (Priority) pdu_structure->data_priority;
  2736. if (NULL != (connection = m_ConnectionList2.Find(connection_handle)))
  2737. {
  2738. /*
  2739. * The indicated connection does exist, so call upon it to accept
  2740. * and register the new transport connection.
  2741. */
  2742. connection->RegisterTransportConnection (transport_connection, priority);
  2743. }
  2744. else
  2745. {
  2746. /*
  2747. * The indicated connection handle is not in the dictionary. Issue
  2748. * a connect result with a failure result, and disconnect the
  2749. * transport connection.
  2750. */
  2751. ConnectResult (transport_connection, RESULT_UNSPECIFIED_FAILURE);
  2752. g_Transport->DisconnectRequest (transport_connection);
  2753. }
  2754. }
  2755. /*
  2756. * Void ConnectResponse ()
  2757. *
  2758. * Private
  2759. *
  2760. * Functional Description:
  2761. * Sends a failed connect response PDU (when something goes wrong).
  2762. *
  2763. * Formal Parameters:
  2764. * transport_connection (i)
  2765. * This is assigned transport connection handle for the connection
  2766. * that is to carry the PDU.
  2767. * result (i)
  2768. * This is the result being sent in the connect response.
  2769. * domain_parameters (i)
  2770. * This is a pointer to a structure containing domain parameters.
  2771. * These parameters will not be used for anything since the connection
  2772. * is being rejected.
  2773. * connect_id (i)
  2774. * This is the connect ID that would be used for any additional
  2775. * transport connection to be bound to this one. This is not
  2776. * required since the connection is being rejected.
  2777. * user_data (i)
  2778. * This is a pointer to the user data to be transmitted to the remote
  2779. * side along with the response.
  2780. * user_data_lengthn (i)
  2781. * This is the length of the above user data.
  2782. *
  2783. * Return Value:
  2784. * None.
  2785. *
  2786. * Side Effects:
  2787. * None.
  2788. *
  2789. * Caveats:
  2790. */
  2791. Void Controller::ConnectResponse (
  2792. TransportConnection transport_connection,
  2793. Result result,
  2794. PDomainParameters domain_parameters,
  2795. ConnectID connect_id,
  2796. PUChar user_data,
  2797. ULong user_data_length)
  2798. {
  2799. ConnectMCSPDU connect_response_pdu;
  2800. PPacket packet;
  2801. PacketError packet_error;
  2802. //PVoid encoded_data;
  2803. //ULong encoded_data_length;
  2804. ASSERT (g_Transport);
  2805. /*
  2806. * Fill in the ConnectResponse PDU structure to be encoded.
  2807. */
  2808. connect_response_pdu.choice = CONNECT_RESPONSE_CHOSEN;
  2809. connect_response_pdu.u.connect_response.result = (PDUResult)result;
  2810. connect_response_pdu.u.connect_response.called_connect_id = connect_id;
  2811. memcpy (&(connect_response_pdu.u.connect_response.domain_parameters),
  2812. domain_parameters, sizeof(PDUDomainParameters));
  2813. connect_response_pdu.u.connect_response.user_data.length = user_data_length;
  2814. connect_response_pdu.u.connect_response.user_data.value = user_data;
  2815. /*
  2816. * Create a packet which will be used to hold the data to be sent
  2817. * through the transport interface. Check to make sure the packet is
  2818. * successfully created..
  2819. */
  2820. DBG_SAVE_FILE_LINE
  2821. packet = new Packet (
  2822. (PPacketCoder) g_MCSCoder,
  2823. BASIC_ENCODING_RULES,
  2824. &connect_response_pdu,
  2825. CONNECT_MCS_PDU,
  2826. TRUE,
  2827. &packet_error);
  2828. if (packet != NULL)
  2829. {
  2830. if (packet_error == PACKET_NO_ERROR)
  2831. {
  2832. /*
  2833. * Send the packet through the transport interface.
  2834. */
  2835. #ifdef DEBUG
  2836. TransportError err = DataRequest (transport_connection,
  2837. (PSimplePacket) packet);
  2838. ASSERT (err == TRANSPORT_NO_ERROR);
  2839. #else // DEBUG
  2840. DataRequest (transport_connection, (PSimplePacket) packet);
  2841. #endif // DEBUG
  2842. }
  2843. else
  2844. {
  2845. /*
  2846. * The packet creation has failed due to an internal error so
  2847. * report the error through a print statement. Note that no
  2848. * further action need be taken since this transport connection
  2849. * is being terminated anyway.
  2850. */
  2851. WARNING_OUT (("Controller::ConnectResponse: "
  2852. "internal allocation failure"));
  2853. }
  2854. packet->Unlock ();
  2855. }
  2856. else
  2857. {
  2858. /*
  2859. * The packet creation has failed so report the error through a print
  2860. * statement. Note that no further action need be taken since this
  2861. * transport connection is being terminated anyway.
  2862. */
  2863. WARNING_OUT (("Controller::ConnectResponse: "
  2864. "packet allocation failure"));
  2865. }
  2866. }
  2867. /*
  2868. * Void ConnectResult ()
  2869. *
  2870. * Private
  2871. *
  2872. * Functional Description:
  2873. * Sends a failed connect response PDU (when something goes wrong).
  2874. *
  2875. * Formal Parameters:
  2876. * transport_connection (i)
  2877. * This is assigned transport connection handle for the connection
  2878. * that is to carry the PDU.
  2879. * result (i)
  2880. * This is the result being sent in the connect result.
  2881. *
  2882. * Return Value:
  2883. * None.
  2884. *
  2885. * Side Effects:
  2886. * None.
  2887. *
  2888. * Caveats:
  2889. */
  2890. Void Controller::ConnectResult (
  2891. TransportConnection transport_connection,
  2892. Result result)
  2893. {
  2894. ConnectMCSPDU connect_result_pdu;
  2895. PPacket packet;
  2896. PacketError packet_error;
  2897. //PVoid encoded_data;
  2898. //ULong encoded_data_length;
  2899. ASSERT (g_Transport);
  2900. /*
  2901. * Fill in the PDU structure to be encoded.
  2902. */
  2903. connect_result_pdu.choice = CONNECT_RESULT_CHOSEN;
  2904. connect_result_pdu.u.connect_result.result = (PDUResult)result;
  2905. /*
  2906. * Create a packet which will be used to hold the data to be sent
  2907. * through the transport interface. Check to make sure the packet is
  2908. * successfully created..
  2909. */
  2910. DBG_SAVE_FILE_LINE
  2911. packet = new Packet (
  2912. (PPacketCoder) g_MCSCoder,
  2913. BASIC_ENCODING_RULES,
  2914. &connect_result_pdu,
  2915. CONNECT_MCS_PDU,
  2916. TRUE,
  2917. &packet_error);
  2918. if (packet != NULL)
  2919. {
  2920. if (packet_error == PACKET_NO_ERROR)
  2921. {
  2922. /*
  2923. * Send the packet through the transport interface.
  2924. */
  2925. #ifdef DEBUG
  2926. TransportError err = DataRequest (transport_connection,
  2927. (PSimplePacket) packet);
  2928. ASSERT (err == TRANSPORT_NO_ERROR);
  2929. #else // DEBUG
  2930. DataRequest (transport_connection, (PSimplePacket) packet);
  2931. #endif // DEBUG
  2932. }
  2933. else
  2934. {
  2935. /*
  2936. * The packet creation has failed due to an internal error so
  2937. * report the error through a print statement. Note that no
  2938. * further action need be taken since this transport connection
  2939. * is being terminated anyway.
  2940. */
  2941. WARNING_OUT (("Controller::ConnectResult: "
  2942. "internal allocation failure"));
  2943. }
  2944. packet->Unlock ();
  2945. }
  2946. else
  2947. {
  2948. /*
  2949. * The packet creation has failed so report the error through a print
  2950. * statement. Note that no further action need be taken since this
  2951. * transport connection is being terminated anyway.
  2952. */
  2953. WARNING_OUT (("Controller::ConnectResult: "
  2954. "packet allocation failure"));
  2955. }
  2956. }
  2957. /*
  2958. * ConnectionHandle AllocateConnectionHandle ()
  2959. *
  2960. * Private
  2961. *
  2962. * Functional Description:
  2963. * This routine allocates a unique connection handle to be used for a newly
  2964. * created connection object. It is based on a rolling instance variable,
  2965. * so that no two handles will ever be reused until the number rolls
  2966. * over at 0xffff.
  2967. *
  2968. * Note that 0 is not a valid connection handle, and will never be used.
  2969. *
  2970. * Formal Parameters:
  2971. * None.
  2972. *
  2973. * Return Value:
  2974. * The unique connection handle.
  2975. *
  2976. * Side Effects:
  2977. * None.
  2978. *
  2979. * Caveats:
  2980. * Note that the assumption is made that there will never be more than
  2981. * 65,534 handles in use at once. In other words, this loop assumes that
  2982. * there is at least 1 available handle left. If there is not, then the
  2983. * loop will hang forever (this is a pretty safe bet for now).
  2984. */
  2985. ConnectionHandle Controller::AllocateConnectionHandle ()
  2986. {
  2987. /*
  2988. * This loop simply increments a rolling number, looking for the next
  2989. * one that is not already in use.
  2990. */
  2991. while (1)
  2992. {
  2993. Connection_Handle_Counter++;
  2994. /*
  2995. * 0 is not a valid handle, so skip it.
  2996. */
  2997. if (Connection_Handle_Counter == 0)
  2998. continue;
  2999. /*
  3000. * If this handle is not in use, break from the loop and use it.
  3001. */
  3002. if (! m_ConnectionList2.Find(Connection_Handle_Counter))
  3003. break;
  3004. }
  3005. return (Connection_Handle_Counter);
  3006. }
  3007. BOOL Controller::GetLocalAddress(ConnectionHandle connection_handle,
  3008. TransportAddress local_address,
  3009. PInt local_address_length)
  3010. {
  3011. PConnection connection = NULL;
  3012. PConnectionPending connection_pending = NULL;
  3013. TransportError transport_error;
  3014. BOOL return_value = FALSE;
  3015. if (NULL == (connection = m_ConnectionList2.Find(connection_handle)))
  3016. {
  3017. connection_pending = m_ConnPendingList2.Find(connection_handle);
  3018. }
  3019. if(connection || connection_pending)
  3020. {
  3021. // Ask the local address to the transport interface
  3022. if (connection)
  3023. {
  3024. transport_error = ::GetLocalAddress(connection->GetTransportConnection(TOP_PRIORITY),
  3025. local_address,
  3026. local_address_length);
  3027. }
  3028. else
  3029. {
  3030. transport_error = ::GetLocalAddress(connection_pending->transport_connection,
  3031. local_address,
  3032. local_address_length);
  3033. }
  3034. // Check the error code
  3035. if (TRANSPORT_NO_ERROR == transport_error) {
  3036. return_value = TRUE;
  3037. }
  3038. }
  3039. return(return_value);
  3040. }
  3041. BOOL Controller::FindSocketNumber(ConnectionHandle connection_handle, SOCKET * socket_number)
  3042. {
  3043. PConnection connection = NULL;
  3044. PConnectionPending connection_pending = NULL;
  3045. if (NULL != (connection = m_ConnectionList2.Find(connection_handle)))
  3046. {
  3047. TransportConnection XprtConn = connection->GetTransportConnection(TOP_PRIORITY);
  3048. if (IS_SOCKET(XprtConn))
  3049. {
  3050. * socket_number = XprtConn.nLogicalHandle;
  3051. return TRUE;
  3052. }
  3053. }
  3054. else
  3055. if (NULL != (connection_pending = m_ConnPendingList2.Find(connection_handle)))
  3056. {
  3057. if (IS_SOCKET(connection_pending->transport_connection))
  3058. {
  3059. * socket_number = connection_pending->transport_connection.nLogicalHandle;
  3060. return TRUE;
  3061. }
  3062. }
  3063. return FALSE;
  3064. }