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

3330 lines
99 KiB

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