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

1003 lines
31 KiB

  1. #include "precomp.h"
  2. DEBUG_FILEZONE(ZONE_T120_T123PSTN);
  3. /* SCF.cpp
  4. *
  5. * Copyright (c) 1994-1995 by DataBeam Corporation, Lexington, KY
  6. *
  7. * Abstract:
  8. * This is the implementation file for the CLayerSCF class
  9. *
  10. * Private Instance Variables:
  11. * Remote_Call_Reference - List of active SCFCalls initiated by the
  12. * remote site
  13. * Call_Reference - List of active SCFCalls initiated locally
  14. * DLCI_List - This list matches DLCIs to SCFCalls, its
  15. * only real purpose is for DisconnectRequest()
  16. * Message_List - List of OwnerCallback messages that can't
  17. * be processed immediately.
  18. * m_pT123 - Address of owner object
  19. * m_pQ922 - Address of lower layer
  20. * m_nMsgBase - Message base passed in by owner. Used in
  21. * OwnerCallback
  22. * Identifier - Identifier passed to lower layer
  23. * Link_Originator - TRUE if we initiated the connection
  24. * Maximum_Packet_Size - Maximum packet size transmittable
  25. * DataLink_Struct - Address of structure holding DataLink parms
  26. * Data_Request_Memory_Manager - Address of memory manager
  27. * Lower_Layer_Prepend - Holds number of bytes prepended to packet
  28. * by the lower layer
  29. * Lower_Layer_Append - Holds number of bytes appended to packet by
  30. * the lower layer
  31. * Call_Reference_Base - This value holds the next call reference
  32. * number.
  33. *
  34. * Caveats:
  35. * None.
  36. *
  37. * Authors:
  38. * James W. Lawwill
  39. */
  40. #include "scf.h"
  41. /*
  42. * CLayerSCF::CLayerSCF (
  43. * PTransportResources transport_resources,
  44. * IObject * owner_object,
  45. * IProtocolLayer * lower_layer,
  46. * USHORT message_base,
  47. * USHORT identifier,
  48. * BOOL link_originator,
  49. * PChar config_file)
  50. *
  51. * Public
  52. *
  53. * Functional Description:
  54. * This is the CLayerSCF constructor. This routine initializes all
  55. * variables and allocates buffer space.
  56. */
  57. CLayerSCF::CLayerSCF
  58. (
  59. T123 *owner_object,
  60. CLayerQ922 *pQ922, // lower layer
  61. USHORT message_base,
  62. USHORT identifier,
  63. BOOL link_originator,
  64. PDataLinkParameters datalink_struct,
  65. PMemoryManager data_request_memory_manager,
  66. BOOL * initialized
  67. )
  68. :
  69. Remote_Call_Reference (TRANSPORT_HASHING_BUCKETS),
  70. Call_Reference (TRANSPORT_HASHING_BUCKETS),
  71. DLCI_List (TRANSPORT_HASHING_BUCKETS),
  72. m_pT123(owner_object),
  73. m_nMsgBase(message_base),
  74. m_pQ922(pQ922)
  75. {
  76. ProtocolLayerError error;
  77. TRACE_OUT(("CLayerSCF::CLayerSCF"));
  78. Link_Originator = (USHORT)link_originator;
  79. Identifier = identifier;
  80. Data_Request_Memory_Manager = data_request_memory_manager;
  81. Call_Reference_Base = 1;
  82. *initialized = TRUE;
  83. /*
  84. ** Fill in the DataLink_Struct with the proposed values and the default
  85. ** values
  86. */
  87. DataLink_Struct.k_factor = datalink_struct -> k_factor;
  88. DataLink_Struct.default_k_factor = datalink_struct -> default_k_factor;
  89. DataLink_Struct.n201 = datalink_struct -> n201;
  90. DataLink_Struct.default_n201 = datalink_struct -> default_n201;
  91. DataLink_Struct.t200 = datalink_struct -> t200;
  92. DataLink_Struct.default_t200 = datalink_struct -> default_t200;
  93. /*
  94. ** Find the maximum packet size
  95. */
  96. m_pQ922->GetParameters(
  97. &Maximum_Packet_Size,
  98. &Lower_Layer_Prepend,
  99. &Lower_Layer_Append);
  100. /*
  101. ** Register with the lower layer
  102. */
  103. error = m_pQ922->RegisterHigherLayer(
  104. Identifier,
  105. Data_Request_Memory_Manager,
  106. (IProtocolLayer *) this);
  107. if (error != PROTOCOL_LAYER_NO_ERROR)
  108. {
  109. ERROR_OUT(("Multiplexer: constructor: Error registering with lower layer"));
  110. *initialized = FALSE;
  111. }
  112. }
  113. /*
  114. * CLayerSCF::~CLayerSCF (void)
  115. *
  116. * Public
  117. *
  118. * Functional Description:
  119. * This is the CLayerSCF destructor. This routine cleans up everything.
  120. */
  121. CLayerSCF::~CLayerSCF (void)
  122. {
  123. TRACE_OUT(("CLayerSCF::~CLayerSCF"));
  124. PMessageStruct message;
  125. PSCFCall lpSCFCall;
  126. m_pQ922->RemoveHigherLayer(Identifier);
  127. /*
  128. ** Delete all locally initiated calls
  129. */
  130. Call_Reference.reset();
  131. while (Call_Reference.iterate ((PDWORD_PTR) &lpSCFCall))
  132. {
  133. delete lpSCFCall;
  134. }
  135. /*
  136. ** Delete all remotely initiated calls
  137. */
  138. Remote_Call_Reference.reset();
  139. while (Remote_Call_Reference.iterate ((PDWORD_PTR) &lpSCFCall))
  140. {
  141. delete lpSCFCall;
  142. }
  143. /*
  144. ** Delete all passive owner callbacks
  145. */
  146. Message_List.reset();
  147. while (Message_List.iterate ((PDWORD_PTR) &message))
  148. {
  149. delete message;
  150. }
  151. }
  152. /*
  153. * CLayerSCF::ConnectRequest (
  154. * DLCI dlci,
  155. * TransportPriority priority)
  156. *
  157. * Public
  158. *
  159. * Functional Description:
  160. * This function initiates a connection with the remote site. As a result,
  161. * we will create a SCFCall and tell it to initiate a connection.
  162. */
  163. SCFError CLayerSCF::ConnectRequest (
  164. DLCI dlci,
  165. TransportPriority priority)
  166. {
  167. TRACE_OUT(("CLayerSCF::ConnectRequest"));
  168. BOOL initialized;
  169. CallReference call_reference;
  170. SCFError return_value = SCF_NO_ERROR;
  171. PSCFCall lpSCFCall;
  172. /*
  173. ** Get the next valid local call reference value.
  174. */
  175. call_reference = GetNextCallReference ();
  176. if (call_reference == 0)
  177. return (SCF_CONNECTION_FULL);
  178. /*
  179. ** Create an SCFCall object to handle this call reference
  180. */
  181. DBG_SAVE_FILE_LINE
  182. lpSCFCall= new SCFCall(this,
  183. m_pQ922,
  184. call_reference << 8,
  185. &DataLink_Struct,
  186. Data_Request_Memory_Manager,
  187. &initialized);
  188. if (lpSCFCall != NULL)
  189. {
  190. if (initialized)
  191. {
  192. Call_Reference.insert ((DWORD_PTR) call_reference, (DWORD_PTR) lpSCFCall);
  193. /*
  194. ** Register the DLCI and the call reference
  195. */
  196. DLCI_List.insert ((DWORD_PTR) dlci, (DWORD_PTR) lpSCFCall);
  197. lpSCFCall->ConnectRequest (call_reference, dlci, priority);
  198. }
  199. else
  200. {
  201. delete lpSCFCall;
  202. return_value = SCF_MEMORY_ALLOCATION_ERROR;
  203. }
  204. }
  205. else
  206. {
  207. return_value = SCF_MEMORY_ALLOCATION_ERROR;
  208. }
  209. return (return_value);
  210. }
  211. /*
  212. * CLayerSCF::ConnectResponse (
  213. * CallReference call_reference,
  214. * DLCI dlci,
  215. * BOOL valid_dlci)
  216. *
  217. * Public
  218. *
  219. * Functional Description:
  220. * This is the CLayerSCF destructor. This routine cleans up everything.
  221. */
  222. SCFError CLayerSCF::ConnectResponse (
  223. CallReference call_reference,
  224. DLCI dlci,
  225. BOOL valid_dlci)
  226. {
  227. TRACE_OUT(("CLayerSCF::ConnectResponse"));
  228. PSCFCall lpSCFCall = NULL;
  229. if (valid_dlci)
  230. {
  231. if (Remote_Call_Reference.find ((DWORD_PTR) call_reference, (PDWORD_PTR) &lpSCFCall))
  232. DLCI_List.insert ((DWORD_PTR) dlci, (DWORD_PTR) lpSCFCall);
  233. }
  234. if(NULL != lpSCFCall)
  235. {
  236. lpSCFCall->ConnectResponse (valid_dlci);
  237. return (SCF_NO_ERROR);
  238. }
  239. return (SCF_NO_SUCH_DLCI);
  240. }
  241. /*
  242. * SCFError CLayerSCF::DisconnectRequest (
  243. * DLCI dlci)
  244. *
  245. * Public
  246. *
  247. * Functional Description:
  248. * This function calls the SCFCall associated with the DLCI and starts
  249. * the disconnect operation
  250. */
  251. SCFError CLayerSCF::DisconnectRequest (
  252. DLCI dlci)
  253. {
  254. TRACE_OUT(("CLayerSCF::DisconnectRequest"));
  255. PSCFCall lpSCFCall;
  256. if (DLCI_List.find ((DWORD_PTR) dlci, (PDWORD_PTR) &lpSCFCall) == FALSE)
  257. return (SCF_NO_SUCH_DLCI);
  258. lpSCFCall->DisconnectRequest ();
  259. return (SCF_NO_ERROR);
  260. }
  261. /*
  262. * SCFError CLayerSCF::DataIndication (
  263. * LPBYTE packet_address,
  264. * ULONG buffer_size,
  265. * PULong packet_length)
  266. *
  267. * Public
  268. *
  269. * Functional Description:
  270. * This function is called by the lower layer when it has received a
  271. * packet for us to process.
  272. */
  273. ProtocolLayerError CLayerSCF::DataIndication (
  274. LPBYTE packet_address,
  275. ULONG packet_length,
  276. PULong bytes_accepted)
  277. {
  278. TRACE_OUT(("CLayerSCF::DataIndication"));
  279. BOOL legal_packet;
  280. CallReference call_reference;
  281. USHORT length_call_reference;
  282. USHORT message_type;
  283. PSCFCall call;
  284. USHORT remainder_length;
  285. USHORT local;
  286. BOOL initialized;
  287. remainder_length = (USHORT) packet_length;
  288. *bytes_accepted = packet_length;
  289. if (*(packet_address+PROTOCOL_DISCRIMINATOR) != Q931_PROTOCOL_DISCRIMINATOR)
  290. return (PROTOCOL_LAYER_NO_ERROR);
  291. /*
  292. ** Get the call reference value
  293. */
  294. call_reference = *(packet_address + CALL_REFERENCE_VALUE);
  295. if (call_reference == 0)
  296. {
  297. ERROR_OUT(("CLayerSCF: DataIndication: illegal call reference value = 0"));
  298. return (PROTOCOL_LAYER_NO_ERROR);
  299. }
  300. length_call_reference = *(packet_address + LENGTH_CALL_REFERENCE);
  301. packet_address += CALL_REFERENCE_VALUE + length_call_reference;
  302. remainder_length -= (CALL_REFERENCE_VALUE + length_call_reference);
  303. /*
  304. ** Get the message type
  305. */
  306. message_type = *(packet_address++);
  307. remainder_length--;
  308. switch (message_type)
  309. {
  310. case SETUP:
  311. /*
  312. ** If the call reference is already active, return error
  313. */
  314. if (Remote_Call_Reference.find ((DWORD) call_reference))
  315. {
  316. TRACE_OUT(("CLayerSCF: DataIndication: SETUP: call reference is already active"));
  317. break;
  318. }
  319. if ((call_reference & CALL_REFERENCE_ORIGINATOR) == 1)
  320. {
  321. TRACE_OUT(("CLayerSCF: DataIndication: SETUP: call reference Originator bit is set incorrectly"));
  322. break;
  323. }
  324. /*
  325. ** This is a new call reference, create a new SCFCall to handle
  326. ** the call. Since the remote site initiated the call, put this
  327. ** reference in the Remote array
  328. */
  329. call= new SCFCall(this,
  330. m_pQ922,
  331. (call_reference << 8),
  332. &DataLink_Struct,
  333. Data_Request_Memory_Manager,
  334. &initialized);
  335. if (call != NULL)
  336. {
  337. if (initialized)
  338. {
  339. Remote_Call_Reference.insert ((DWORD_PTR) call_reference, (DWORD_PTR) call);
  340. /*
  341. ** Allow the call to process the SETUP command
  342. */
  343. legal_packet = call->ProcessSetup (call_reference, packet_address, remainder_length);
  344. /*
  345. ** If the packet was illegal, remove the reference
  346. */
  347. if (legal_packet == FALSE) {
  348. delete call;
  349. Remote_Call_Reference.remove ((DWORD) call_reference);
  350. }
  351. }
  352. else
  353. {
  354. delete call;
  355. }
  356. }
  357. break;
  358. case CONNECT:
  359. /*
  360. ** The call originator bit must be set to signify that we are
  361. ** the originators of the call
  362. */
  363. if ((call_reference & CALL_REFERENCE_ORIGINATOR) == 0)
  364. {
  365. TRACE_OUT(("CLayerSCF: DataIndication: CONNECT: call reference Originator bit is set incorrectly"));
  366. break;
  367. }
  368. /*
  369. ** If the call reference is not already active, return error
  370. */
  371. call_reference &= CALL_ORIGINATOR_MASK;
  372. if (Call_Reference.find ((DWORD_PTR) call_reference, (PDWORD_PTR) &call) == FALSE)
  373. {
  374. TRACE_OUT(("CLayerSCF: DataIndication: CONNECT: call reference is not already active = %x", call_reference));
  375. break;
  376. }
  377. call->ProcessConnect (packet_address, remainder_length);
  378. break;
  379. case CONNECT_ACKNOWLEDGE:
  380. /*
  381. ** If the call reference is already active, return error
  382. */
  383. if (Remote_Call_Reference.find ((DWORD_PTR) call_reference, (PDWORD_PTR) &call) == FALSE)
  384. {
  385. TRACE_OUT(("CLayerSCF: DataIndication: CONNECT_ACK: call reference is not active"));
  386. break;
  387. }
  388. /*
  389. ** The call originator bit should NOT be set
  390. */
  391. if ((call_reference & CALL_REFERENCE_ORIGINATOR) == 1)
  392. {
  393. TRACE_OUT(("CLayerSCF: DataIndication: CONNECT_ACK: call reference Originator bit is set incorrectly"));
  394. break;
  395. }
  396. call->ProcessConnectAcknowledge (packet_address, remainder_length);
  397. break;
  398. case RELEASE_COMPLETE:
  399. local = call_reference & CALL_REFERENCE_ORIGINATOR;
  400. call_reference &= CALL_ORIGINATOR_MASK;
  401. /*
  402. ** If the call is local, check the Call_Reference list for validity
  403. */
  404. if (local)
  405. {
  406. if (Call_Reference.find ((DWORD_PTR) call_reference, (PDWORD_PTR) &call) == FALSE)
  407. {
  408. TRACE_OUT(("CLayerSCF: DataIndication: RELEASE_COMPLETE: call reference is not already active"));
  409. break;
  410. }
  411. }
  412. else
  413. {
  414. /*
  415. ** If the call is remote, check the Call_Reference list for
  416. ** validity
  417. */
  418. if (Remote_Call_Reference.find ((DWORD_PTR) call_reference, (PDWORD_PTR) &call) == FALSE)
  419. {
  420. TRACE_OUT(("CLayerSCF: DataIndication: RELEASE_COMPLETE: call reference is not already active"));
  421. break;
  422. }
  423. }
  424. call -> ProcessReleaseComplete (packet_address, remainder_length);
  425. ProcessMessages ();
  426. break;
  427. case DISCONNECT:
  428. case RELEASE:
  429. case STATUS:
  430. case STATUS_ENQUIRY:
  431. TRACE_OUT(("CLayerSCF:DataIndication: Illegal command received = %x", message_type));
  432. local = call_reference & CALL_REFERENCE_ORIGINATOR;
  433. call_reference &= CALL_ORIGINATOR_MASK;
  434. /*
  435. ** If the call is local, check the Call_Reference list for validity
  436. */
  437. if (local)
  438. {
  439. if (Call_Reference.find ((DWORD_PTR) call_reference, (PDWORD_PTR) &call) == FALSE)
  440. break;
  441. }
  442. else
  443. {
  444. /*
  445. ** If the call is remote, check the Call_Reference list for
  446. ** validity
  447. */
  448. if (Remote_Call_Reference.find ((DWORD_PTR) call_reference, (PDWORD_PTR) &call) == FALSE)
  449. break;
  450. }
  451. call -> DisconnectRequest ();
  452. break;
  453. default:
  454. ERROR_OUT(("CLayerSCF:DataIndication: Unrecognized command received = %x", message_type));
  455. break;
  456. }
  457. return (PROTOCOL_LAYER_NO_ERROR);
  458. }
  459. /*
  460. * ProtocolLayerError CLayerSCF::PollTransmitter (
  461. * ULONG,
  462. * USHORT data_to_transmit,
  463. * USHORT * pending_data,
  464. * USHORT *)
  465. *
  466. * Public
  467. *
  468. * Functional Description:
  469. * This function should be called frequently to allow the SCF calls to
  470. * transmit packets.
  471. */
  472. ProtocolLayerError CLayerSCF::PollTransmitter (
  473. ULONG_PTR,
  474. USHORT data_to_transmit,
  475. USHORT * pending_data,
  476. USHORT *)
  477. {
  478. // TRACE_OUT(("CLayerSCF::PollTransmitter"));
  479. USHORT local_pending_data;
  480. PSCFCall lpSCFCall;
  481. *pending_data = 0;
  482. /*
  483. ** Go through each of the locally originated calls and attempt to transmit
  484. ** data.
  485. */
  486. Call_Reference.reset();
  487. while (Call_Reference.iterate ((PDWORD_PTR) &lpSCFCall))
  488. {
  489. lpSCFCall->PollTransmitter (data_to_transmit, &local_pending_data);
  490. *pending_data |= local_pending_data;
  491. }
  492. /*
  493. ** Go through each of the remotely originated calls and attempt to transmit
  494. ** data.
  495. */
  496. Remote_Call_Reference.reset();
  497. while (Remote_Call_Reference.iterate ((PDWORD_PTR) &lpSCFCall))
  498. {
  499. lpSCFCall-> PollTransmitter (data_to_transmit, &local_pending_data);
  500. *pending_data |= local_pending_data;
  501. }
  502. ProcessMessages ();
  503. return (PROTOCOL_LAYER_NO_ERROR);
  504. }
  505. /*
  506. * SCFError CLayerSCF::DataRequest (
  507. * ULONG,
  508. * LPBYTE,
  509. * ULONG,
  510. * PULong)
  511. *
  512. * Public
  513. *
  514. * Functional Description:
  515. * This function can not be called. This layer does not permit data
  516. * requests from higher layers.
  517. */
  518. ProtocolLayerError CLayerSCF::DataRequest (
  519. ULONG_PTR,
  520. LPBYTE,
  521. ULONG,
  522. PULong)
  523. {
  524. return (PROTOCOL_LAYER_ERROR);
  525. }
  526. /*
  527. * SCFError CLayerSCF::DataRequest (
  528. * ULONG,
  529. * PMemory,
  530. * USHORT *)
  531. *
  532. * Public
  533. *
  534. * Functional Description:
  535. * This function can not be called. This layer does not permit data
  536. * requests from higher layers.
  537. */
  538. ProtocolLayerError CLayerSCF::DataRequest (
  539. ULONG_PTR,
  540. PMemory,
  541. PULong)
  542. {
  543. return (PROTOCOL_LAYER_ERROR);
  544. }
  545. /*
  546. * void CLayerSCF::PollReceiver (
  547. * ULONG)
  548. *
  549. * Public
  550. *
  551. * Functional Description
  552. * This function only checks its passive callback list. If this function
  553. * had a higher layer that it was passing data too, it would do that. But
  554. * since it has no higher layer, it doesn't do much.
  555. */
  556. ProtocolLayerError CLayerSCF::PollReceiver(void)
  557. {
  558. ProcessMessages ();
  559. return (PROTOCOL_LAYER_NO_ERROR);
  560. }
  561. /*
  562. * CallReference CLayerSCF::GetNextCallReference ()
  563. *
  564. * Functional Description
  565. * This function searches the local call reference list for a valid call
  566. * reference number. If it can not find one, it returns 0. Valid call
  567. * references are 1-127.
  568. *
  569. * Formal Parameters
  570. * None
  571. *
  572. * Return Value
  573. * Call reference value
  574. *
  575. * Side Effects
  576. * None
  577. *
  578. * Caveats
  579. * None
  580. */
  581. USHORT CLayerSCF::GetNextCallReference ()
  582. {
  583. USHORT call_reference;
  584. if (Call_Reference.entries() == 127)
  585. return (0);
  586. call_reference = Call_Reference_Base;
  587. Call_Reference_Base++;
  588. if (Call_Reference_Base == 128)
  589. Call_Reference_Base = 1;
  590. while (Call_Reference.find ((DWORD) call_reference))
  591. {
  592. call_reference++;
  593. if (call_reference == 128)
  594. call_reference = 1;
  595. }
  596. return (call_reference);
  597. }
  598. /*
  599. * ULONG CLayerSCF::OwnerCallback (
  600. * USHORT message,
  601. * ULONG parameter1,
  602. * ULONG parameter2,
  603. * PVoid parameter3)
  604. *
  605. * Functional Description
  606. * This function is called by the SCFCall objects when they need to
  607. * communicate a message to us. If the message can not be processed
  608. * immediately, it is saved in a message structure and processed at a
  609. * later time.
  610. *
  611. * Formal Parameters
  612. * None
  613. *
  614. * Return Value
  615. * Message dependent
  616. *
  617. * Side Effects
  618. * None
  619. *
  620. * Caveats
  621. * None
  622. */
  623. ULONG CLayerSCF::OwnerCallback
  624. (
  625. ULONG message,
  626. void *parameter1,
  627. void *parameter2,
  628. void *parameter3
  629. )
  630. {
  631. TRACE_OUT(("CLayerSCF::OwnerCallback"));
  632. ULONG actual_message;
  633. CallReference call_reference;
  634. PMessageStruct passive_message;
  635. PNetworkConnectStruct connect_struct;
  636. PSCFCall lpSCFCall;
  637. /*
  638. ** The upper byte of the message is the call reference message that it
  639. ** represents
  640. */
  641. call_reference = (CallReference) (message >> 8);
  642. actual_message = message & 0xff;
  643. switch (actual_message)
  644. {
  645. case NETWORK_CONNECT_CONFIRM:
  646. /*
  647. ** A CONNECT_CONFIRM message is returned by the SCFCall when a call
  648. ** that we originated, has been established. We register the
  649. ** SCFCall with the DLCI and call the owner object.
  650. */
  651. connect_struct = (PNetworkConnectStruct) parameter3;
  652. connect_struct -> call_reference = call_reference;
  653. if (Call_Reference.find ((DWORD_PTR) call_reference, (PDWORD_PTR) &lpSCFCall))
  654. {
  655. DLCI_List.insert ((DWORD_PTR) connect_struct->dlci, (DWORD_PTR) lpSCFCall);
  656. }
  657. m_pT123->OwnerCallback(m_nMsgBase + actual_message, 0, 0, parameter3);
  658. break;
  659. case NETWORK_CONNECT_INDICATION:
  660. /*
  661. ** A CONNECT_INDICATION message is returned by the SCFCall when the
  662. ** remote SCF wants to create a new call. We will call the owner
  663. ** of this object to see if he will accept the DLCI requested.
  664. */
  665. connect_struct = (PNetworkConnectStruct) parameter3;
  666. connect_struct -> call_reference = call_reference;
  667. m_pT123->OwnerCallback(m_nMsgBase + actual_message, 0, 0, parameter3);
  668. break;
  669. case NETWORK_DISCONNECT_INDICATION:
  670. /*
  671. ** This message is received from the SCFCall when one side wants
  672. ** to terminate the call. We treat this message differently than
  673. ** the other messages because it involves the deletion of an
  674. ** SCFCall object. Don't forget, if we delete the object and then
  675. ** return to it at the end of this procedure, a GPF could occur.
  676. */
  677. DBG_SAVE_FILE_LINE
  678. passive_message = new MessageStruct;
  679. if (NULL != passive_message)
  680. {
  681. passive_message -> message = message;
  682. passive_message -> parameter1 = parameter1;
  683. passive_message -> parameter2 = parameter2;
  684. passive_message -> parameter3 = parameter3;
  685. Message_List.append ((DWORD_PTR) passive_message);
  686. }
  687. else
  688. {
  689. ERROR_OUT(("CLayerSCF::OwnerCallback: cannot allocate MessageStruct"));
  690. }
  691. break;
  692. default:
  693. ERROR_OUT(("CLayerSCF: Illegal message: %x", actual_message));
  694. break;
  695. }
  696. return (0);
  697. }
  698. /*
  699. * ProtocolLayerError CLayerSCF::GetParameters (
  700. * USHORT,
  701. * USHORT *,
  702. * USHORT *,
  703. * USHORT *)
  704. *
  705. * Public
  706. *
  707. * Functional Description
  708. * This function is not valid in this layer. It must exist because this
  709. * class inherits from inherits from ProtocolLayer and it is a pure virtual
  710. * function.
  711. */
  712. ProtocolLayerError CLayerSCF::GetParameters (
  713. USHORT *,
  714. USHORT *,
  715. USHORT *)
  716. {
  717. return (PROTOCOL_LAYER_REGISTRATION_ERROR);
  718. }
  719. /*
  720. * ProtocolLayerError CLayerSCF::RegisterHigherLayer (
  721. * USHORT,
  722. * PMemoryManager,
  723. * IProtocolLayer *)
  724. *
  725. * Public
  726. *
  727. * Functional Description
  728. * This function is not valid in this layer. It must exist because this
  729. * class inherits from inherits from ProtocolLayer and it is a pure virtual
  730. * function.
  731. */
  732. ProtocolLayerError CLayerSCF::RegisterHigherLayer (
  733. ULONG_PTR,
  734. PMemoryManager,
  735. IProtocolLayer *)
  736. {
  737. return (PROTOCOL_LAYER_REGISTRATION_ERROR);
  738. }
  739. /*
  740. * ProtocolLayerError CLayerSCF::RemoveHigherLayer (
  741. * USHORT)
  742. *
  743. * Public
  744. *
  745. * Functional Description
  746. * This function is not valid in this layer. It must exist because this
  747. * class inherits from inherits from ProtocolLayer and it is a pure virtual
  748. * function.
  749. */
  750. ProtocolLayerError CLayerSCF::RemoveHigherLayer (
  751. ULONG_PTR)
  752. {
  753. return (PROTOCOL_LAYER_REGISTRATION_ERROR);
  754. }
  755. /*
  756. * void CLayerSCF::ProcessMessages ()
  757. *
  758. * Functional Description
  759. * This function is called periodically to check its passive messages.
  760. * Passive messages occur when the SCF gets a callback but can't process
  761. * it immediately. Therefore, it puts the message and its parameters in
  762. * a structure and saves the message for later.
  763. *
  764. * Formal Parameters
  765. * None
  766. *
  767. * Return Value
  768. * Message dependent
  769. *
  770. * Side Effects
  771. * None
  772. *
  773. * Caveats
  774. * None
  775. */
  776. void CLayerSCF::ProcessMessages ()
  777. {
  778. // TRACE_OUT(("CLayerSCF::ProcessMessages"));
  779. PMessageStruct message;
  780. CallReference call_reference;
  781. ULONG actual_message;
  782. USHORT call_originator;
  783. USHORT cause;
  784. DLCI dlci;
  785. BOOL call_reference_valid;
  786. void *parameter1;
  787. void *parameter2;
  788. PSCFCall lpSCFCall;
  789. /*
  790. ** Go thru each message in the list
  791. */
  792. while (Message_List.isEmpty() == FALSE)
  793. {
  794. /*
  795. ** Remote the first message from the list
  796. */
  797. message = (PMessageStruct) Message_List.get ();
  798. call_reference = (CallReference) ((message -> message) >> 8);
  799. actual_message = (message -> message) & 0xff;
  800. parameter1 = message -> parameter1;
  801. parameter2 = message -> parameter2;
  802. switch (actual_message)
  803. {
  804. case NETWORK_DISCONNECT_INDICATION:
  805. /*
  806. ** This message is received from the SCFCall when one side
  807. ** wants to terminate the call. We treat this message
  808. ** differently than the other messages because it involves the
  809. ** deletion of an SCFCall object.
  810. */
  811. dlci = (DLCI) parameter1;
  812. call_originator = (USHORT) (((ULONG_PTR) parameter2) >> 16);
  813. cause = (USHORT) ((ULONG_PTR) parameter2) & 0xffff;
  814. /*
  815. ** dlci is 0 if the SCFCall was never assigned a DLCI by the
  816. ** remote site.
  817. */
  818. if (dlci != 0)
  819. DLCI_List.remove ((DWORD) dlci);
  820. /*
  821. ** If the SCFCall was the call originator, its reference is
  822. ** in Call_Reference, otherwise it is in Remote_Call_Reference.
  823. **
  824. ** Check the Call_Reference list to make sure that the
  825. ** call_reference is valid. The way passive owner callbacks
  826. ** work, it is possible to receive a DISCONNECT for a callback
  827. ** that was already disconnected.
  828. */
  829. call_reference_valid = FALSE;
  830. if (call_originator)
  831. {
  832. if (Call_Reference.find ((DWORD_PTR) call_reference, (PDWORD_PTR) &lpSCFCall))
  833. {
  834. delete lpSCFCall;
  835. Call_Reference.remove ((DWORD) call_reference);
  836. call_reference_valid = TRUE;
  837. }
  838. }
  839. else
  840. {
  841. if (Remote_Call_Reference.find ((DWORD_PTR) call_reference, (PDWORD_PTR) &lpSCFCall))
  842. {
  843. delete lpSCFCall;
  844. Remote_Call_Reference.remove ((DWORD_PTR) call_reference);
  845. call_reference_valid = TRUE;
  846. }
  847. }
  848. if (call_reference_valid)
  849. {
  850. /*
  851. ** If the cause of the disconnect was because the Requested
  852. ** channel was unavailable, we will tell the owner of this
  853. ** layer to retry the connection.
  854. */
  855. if (cause == REQUESTED_CHANNEL_UNAVAILABLE)
  856. {
  857. parameter2 = (void *) ((((ULONG_PTR) call_originator) << 16) | TRUE);
  858. }
  859. else
  860. {
  861. parameter2 = (void *) ((((ULONG_PTR) call_originator) << 16) | FALSE);
  862. }
  863. /*
  864. ** Let the owner of this object know that a disconnect has
  865. ** occured.
  866. */
  867. m_pT123->OwnerCallback(m_nMsgBase + NETWORK_DISCONNECT_INDICATION,
  868. parameter1, parameter2);
  869. }
  870. break;
  871. }
  872. /*
  873. ** Delete the message structure
  874. */
  875. delete message;
  876. }
  877. }
  878.