home *** CD-ROM | disk | FTP | other *** search
/ ftp.muug.mb.ca / 2014.06.ftp.muug.mb.ca.tar / ftp.muug.mb.ca / pub / openh323.tar.gz / openh323.tar / openh323 / src / h450pdu.cxx < prev    next >
C/C++ Source or Header  |  2003-07-15  |  72KB  |  2,489 lines

  1. /*
  2.  * h450pdu.cxx
  3.  *
  4.  * H.450 Helper functions
  5.  *
  6.  * Open H323 Library
  7.  *
  8.  * Copyright (c) 2001 Norwood Systems Pty. Ltd.
  9.  *
  10.  * The contents of this file are subject to the Mozilla Public License
  11.  * Version 1.0 (the "License"); you may not use this file except in
  12.  * compliance with the License. You may obtain a copy of the License at
  13.  * http://www.mozilla.org/MPL/
  14.  *
  15.  * Software distributed under the License is distributed on an "AS IS"
  16.  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  17.  * the License for the specific language governing rights and limitations
  18.  * under the License.
  19.  *
  20.  * The Original Code is Open H323 Library.
  21.  *
  22.  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
  23.  *
  24.  * Contributor(s): ______________________________________.
  25.  *
  26.  * $Log: h450pdu.cxx,v $
  27.  * Revision 1.20  2003/07/15 11:22:07  csoutheren
  28.  * Improved handling of alias addresses thanks to Federico Pinna
  29.  *
  30.  * Revision 1.19  2002/11/21 22:37:47  robertj
  31.  * Fixed problems with unrecognized invoke APDU, thanks Andrea Bondavalli
  32.  *
  33.  * Revision 1.18  2002/10/01 06:47:39  robertj
  34.  * Fixed GNU compiler warning
  35.  *
  36.  * Revision 1.17  2002/09/25 05:21:11  robertj
  37.  * Fixed warning on no trace version.
  38.  *
  39.  * Revision 1.16  2002/08/05 10:03:47  robertj
  40.  * Cosmetic changes to normalise the usage of pragma interface/implementation.
  41.  *
  42.  * Revision 1.15  2002/07/04 00:40:34  robertj
  43.  * More H.450.11 call intrusion implementation, thanks Aleksandar Todorovic
  44.  *
  45.  * Revision 1.14  2002/06/25 09:56:07  robertj
  46.  * Fixed GNU warnings
  47.  *
  48.  * Revision 1.13  2002/06/22 05:48:42  robertj
  49.  * Added partial implementation for H.450.11 Call Intrusion
  50.  *
  51.  * Revision 1.12  2002/06/13 06:13:28  robertj
  52.  * Added trace dumps for outgoing H.450 supplementary service APDU's.
  53.  *
  54.  * Revision 1.11  2002/02/04 07:17:56  robertj
  55.  * Added H.450.2 Consultation Transfer, thanks Norwood Systems.
  56.  *
  57.  * Revision 1.10  2002/01/14 00:03:01  robertj
  58.  * Added H.450.6
  59.  * Added extra "failure mode" parts of H.250.2.
  60.  * Various other bug fixes.
  61.  *   Thanks Ben Madsen of Norwood Systems
  62.  *
  63.  * Revision 1.9  2001/11/19 07:40:44  robertj
  64.  * Fixed problem with error detection & state change in Call Transfer, thanks Graeme Reid
  65.  *
  66.  * Revision 1.8  2001/08/27 03:59:16  robertj
  67.  * Fixed GNU warnings.
  68.  *
  69.  * Revision 1.7  2001/08/16 07:49:19  robertj
  70.  * Changed the H.450 support to be more extensible. Protocol handlers
  71.  *   are now in separate classes instead of all in H323Connection.
  72.  *
  73.  * Revision 1.6  2001/08/06 03:08:57  robertj
  74.  * Fission of h323.h to h323ep.h & h323con.h, h323.h now just includes files.
  75.  *
  76.  * Revision 1.5  2001/06/14 06:25:16  robertj
  77.  * Added further H.225 PDU build functions.
  78.  * Moved some functionality from connection to PDU class.
  79.  *
  80.  * Revision 1.4  2001/06/05 03:14:41  robertj
  81.  * Upgraded H.225 ASN to v4 and H.245 ASN to v7.
  82.  *
  83.  * Revision 1.3  2001/05/09 04:59:04  robertj
  84.  * Bug fixes in H.450.2, thanks Klein Stefan.
  85.  *
  86.  * Revision 1.2  2001/04/20 02:16:53  robertj
  87.  * Removed GNU C++ warnings.
  88.  *
  89.  * Revision 1.1  2001/04/11 03:01:29  robertj
  90.  * Added H.450.2 (call transfer), thanks a LOT to Graeme Reid & Norwood Systems
  91.  *
  92.  */
  93.  
  94. #include <ptlib.h>
  95.  
  96. #ifdef __GNUC__
  97. #pragma implementation "h450pdu.h"
  98. #endif
  99.  
  100. #include "h450pdu.h"
  101.  
  102. #include "h4501.h"
  103. #include "h4502.h"
  104. #include "h4504.h"
  105. #include "h4506.h"
  106. #include "h45010.h"
  107. #include "h45011.h"
  108. #include "h323pdu.h"
  109. #include "h323ep.h"
  110. #include "h323con.h"
  111.  
  112.  
  113. X880_Invoke& H450ServiceAPDU::BuildInvoke(int invokeId, int operation)
  114. {
  115.   SetTag(X880_ROS::e_invoke);
  116.   X880_Invoke& invoke = (X880_Invoke&) *this;
  117.  
  118.   invoke.m_invokeId = invokeId;
  119.  
  120.   invoke.m_opcode.SetTag(X880_Code::e_local);
  121.   PASN_Integer& opcode = (PASN_Integer&) invoke.m_opcode;
  122.   opcode.SetValue(operation);
  123.  
  124.   return invoke;
  125. }
  126.  
  127.  
  128. X880_ReturnResult& H450ServiceAPDU::BuildReturnResult(int invokeId)
  129. {
  130.   SetTag(X880_ROS::e_returnResult);
  131.   X880_ReturnResult& returnResult = (X880_ReturnResult&) *this;
  132.  
  133.   returnResult.m_invokeId = invokeId;
  134.  
  135.   return returnResult;
  136. }
  137.  
  138.  
  139. X880_ReturnError& H450ServiceAPDU::BuildReturnError(int invokeId, int error)
  140. {
  141.   SetTag(X880_ROS::e_returnError);
  142.   X880_ReturnError& returnError = (X880_ReturnError&) *this;
  143.  
  144.   returnError.m_invokeId = invokeId;
  145.  
  146.   returnError.m_errorCode.SetTag(X880_Code::e_local);
  147.   PASN_Integer& errorCode = (PASN_Integer&) returnError.m_errorCode;
  148.   errorCode.SetValue(error);
  149.  
  150.   return returnError;
  151. }
  152.  
  153.  
  154. X880_Reject& H450ServiceAPDU::BuildReject(int invokeId)
  155. {
  156.   SetTag(X880_ROS::e_reject);
  157.   X880_Reject& reject = (X880_Reject&) *this;
  158.  
  159.   reject.m_invokeId = invokeId;
  160.  
  161.   return reject;
  162. }
  163.  
  164.  
  165. void H450ServiceAPDU::BuildCallTransferInitiate(int invokeId,
  166.                                                 const PString & callIdentity,
  167.                                                 const PString & alias,
  168.                                                 const H323TransportAddress & address)
  169. {
  170.   X880_Invoke& invoke = BuildInvoke(invokeId, H4502_CallTransferOperation::e_callTransferInitiate);
  171.  
  172.   H4502_CTInitiateArg argument;
  173.  
  174.   argument.m_callIdentity = callIdentity;
  175.  
  176.   H4501_ArrayOf_AliasAddress& aliasAddress = argument.m_reroutingNumber.m_destinationAddress;
  177.  
  178.   // We have to have at least a destination transport address or alias.
  179.   if (!alias.IsEmpty() && !address.IsEmpty()) {
  180.     aliasAddress.SetSize(2);
  181.  
  182.     // Set the alias
  183.     aliasAddress[1].SetTag(H225_AliasAddress::e_dialedDigits);
  184.     H323SetAliasAddress(alias, aliasAddress[1]);
  185.  
  186.     // Set the transport
  187.     aliasAddress[0].SetTag(H225_AliasAddress::e_transportID);
  188.     H225_TransportAddress& cPartyTransport = (H225_TransportAddress&) aliasAddress[0];
  189.     address.SetPDU(cPartyTransport);
  190.   }
  191.   else {
  192.     aliasAddress.SetSize(1);
  193.     if (alias.IsEmpty()) {
  194.       // Set the transport, no alias present
  195.       aliasAddress[0].SetTag(H225_AliasAddress::e_transportID);
  196.       H225_TransportAddress& cPartyTransport = (H225_TransportAddress&) aliasAddress[0];
  197.       address.SetPDU(cPartyTransport);
  198.     }
  199.     else {
  200.       // Set the alias, no transport
  201.       aliasAddress[0].SetTag(H225_AliasAddress::e_dialedDigits);
  202.       H323SetAliasAddress(alias, aliasAddress[0]);
  203.     }
  204.   }
  205.  
  206.   PTRACE(4, "H4502\tSending supplementary service PDU argument:\n  "
  207.          << setprecision(2) << argument);
  208.  
  209.   invoke.IncludeOptionalField(X880_Invoke::e_argument);
  210.   invoke.m_argument.EncodeSubType(argument);
  211. }
  212.  
  213.  
  214. void H450ServiceAPDU::BuildCallTransferSetup(int invokeId,
  215.                                              const PString & callIdentity)
  216. {
  217.   X880_Invoke& invoke = BuildInvoke(invokeId, H4502_CallTransferOperation::e_callTransferSetup);
  218.  
  219.   H4502_CTSetupArg argument;
  220.  
  221.   argument.m_callIdentity = callIdentity;
  222.  
  223.   PTRACE(4, "H4502\tSending supplementary service PDU argument:\n  "
  224.          << setprecision(2) << argument);
  225.  
  226.   invoke.IncludeOptionalField(X880_Invoke::e_argument);
  227.   invoke.m_argument.EncodeSubType(argument);
  228. }
  229.  
  230.  
  231. void H450ServiceAPDU::BuildCallTransferIdentify(int invokeId)
  232. {
  233.   X880_Invoke invoke = BuildInvoke(invokeId, H4502_CallTransferOperation::e_callTransferIdentify);
  234. }
  235.  
  236.  
  237. void H450ServiceAPDU::BuildCallTransferAbandon(int invokeId)
  238. {
  239.   X880_Invoke invoke = BuildInvoke(invokeId, H4502_CallTransferOperation::e_callTransferAbandon);
  240. }
  241.  
  242.  
  243. void H450ServiceAPDU::BuildCallWaiting(int invokeId, int numCallsWaiting)
  244. {
  245.   X880_Invoke& invoke = BuildInvoke(invokeId, H4506_CallWaitingOperations::e_callWaiting);
  246.  
  247.   H4506_CallWaitingArg argument;
  248.  
  249.   argument.IncludeOptionalField(H4506_CallWaitingArg::e_nbOfAddWaitingCalls);
  250.   argument.m_nbOfAddWaitingCalls = numCallsWaiting;
  251.  
  252.   PTRACE(4, "H4502\tSending supplementary service PDU argument:\n  "
  253.          << setprecision(2) << argument);
  254.   
  255.   invoke.IncludeOptionalField(X880_Invoke::e_argument);
  256.   invoke.m_argument.EncodeSubType(argument);
  257. }
  258.  
  259.  
  260. void H450ServiceAPDU::BuildCallIntrusionForcedRelease(int invokeId,
  261.                                                       int CICL)
  262. {
  263.   X880_Invoke& invoke = BuildInvoke(invokeId, H45011_H323CallIntrusionOperations::e_callIntrusionForcedRelease);
  264.  
  265.   H45011_CIFrcRelArg argument;
  266.  
  267.   argument.m_ciCapabilityLevel = CICL;
  268.  
  269.   invoke.IncludeOptionalField(X880_Invoke::e_argument);
  270.   invoke.m_argument.EncodeSubType(argument);
  271. }
  272.  
  273.  
  274. X880_ReturnResult& H450ServiceAPDU::BuildCallIntrusionForcedReleaseResult(int invokeId)
  275. {
  276.   PTRACE(1 ,"H450.11\tH450ServiceAPDU::BuildCallIntrusionForcedReleaseResult BEGIN");
  277.   
  278.   X880_ReturnResult& result = BuildReturnResult(invokeId);
  279.   result.IncludeOptionalField(X880_ReturnResult::e_result);
  280.   result.m_result.m_opcode.SetTag(X880_Code::e_local);
  281.   PASN_Integer& operation = (PASN_Integer&) result.m_result.m_opcode;
  282.   operation.SetValue(H45011_H323CallIntrusionOperations::e_callIntrusionForcedRelease);
  283.  
  284.   H45011_CIFrcRelOptRes ciCIPLRes;
  285.  
  286.   PPER_Stream resultStream;
  287.   ciCIPLRes.Encode(resultStream);
  288.   resultStream.CompleteEncoding();
  289.   result.m_result.m_result.SetValue(resultStream);
  290.   PTRACE(4 ,"H450.11\tH450ServiceAPDU::BuildCallIntrusionForcedReleaseResult END");
  291.  
  292.   return result;
  293. }
  294.  
  295.  
  296. void H450ServiceAPDU::BuildCallIntrusionForcedReleaseError()
  297. {
  298. /**
  299.   TBD
  300. */
  301. }
  302.  
  303.  
  304. void H450ServiceAPDU::BuildCallIntrusionGetCIPL(int invokeId)
  305. {
  306.   PTRACE(4, "H450.11\tBuildCallIntrusionGetCIPL invokeId=" << invokeId);
  307.   X880_Invoke invoke = BuildInvoke(invokeId, H45011_H323CallIntrusionOperations::e_callIntrusionGetCIPL);
  308. }
  309.  
  310.  
  311. void H450ServiceAPDU::BuildCallIntrusionImpending(int invokeId)
  312. {
  313.   PTRACE(4, "H450.11\tBuildCallIntrusionImpending invokeId=" << invokeId);
  314.   X880_Invoke& invoke = BuildInvoke(invokeId, H45011_H323CallIntrusionOperations::e_callIntrusionNotification);
  315.  
  316.   H45011_CINotificationArg argument;
  317.  
  318.   argument.m_ciStatusInformation = H45011_CIStatusInformation::e_callIntrusionImpending;
  319.  
  320.   invoke.IncludeOptionalField(X880_Invoke::e_argument);
  321.   invoke.m_argument.EncodeSubType(argument);
  322. }
  323.  
  324.  
  325. void H450ServiceAPDU::BuildCallIntrusionForceRelesed(int invokeId)
  326. {
  327.   PTRACE(4, "H450.11\tBuildCallIntrusionForceRelesed invokeId=" << invokeId);
  328.   X880_Invoke& invoke = BuildInvoke(invokeId, H45011_H323CallIntrusionOperations::e_callIntrusionNotification);
  329.  
  330.   H45011_CINotificationArg argument;
  331.  
  332.   argument.m_ciStatusInformation = H45011_CIStatusInformation::e_callForceReleased;
  333.  
  334.   invoke.IncludeOptionalField(X880_Invoke::e_argument);
  335.   invoke.m_argument.EncodeSubType(argument);
  336. }
  337.  
  338.  
  339. void H450ServiceAPDU::AttachSupplementaryServiceAPDU(H323SignalPDU & pdu)
  340. {
  341.   H4501_SupplementaryService supplementaryService;
  342.  
  343.   // Create an H.450.1 supplementary service object
  344.   // and store the H450ServiceAPDU in the ROS array.
  345.   supplementaryService.m_serviceApdu.SetTag(H4501_ServiceApdus::e_rosApdus);
  346.   H4501_ArrayOf_ROS & operations = (H4501_ArrayOf_ROS &)supplementaryService.m_serviceApdu;
  347.   operations.SetSize(1);
  348.   operations[0] = *this;
  349.  
  350.   PTRACE(4, "H4501\tSending supplementary service PDU:\n  "
  351.          << setprecision(2) << supplementaryService);
  352.  
  353.   // Add the H.450 PDU to the H.323 User-to-User PDU as an OCTET STRING
  354.   pdu.m_h323_uu_pdu.IncludeOptionalField(H225_H323_UU_PDU::e_h4501SupplementaryService);
  355.   pdu.m_h323_uu_pdu.m_h4501SupplementaryService.SetSize(1);
  356.   pdu.m_h323_uu_pdu.m_h4501SupplementaryService[0].EncodeSubType(supplementaryService);
  357. }
  358.  
  359.  
  360. BOOL H450ServiceAPDU::WriteFacilityPDU(H323Connection & connection)
  361. {
  362.   H323SignalPDU facilityPDU;
  363.   facilityPDU.BuildFacility(connection, TRUE);
  364.  
  365.   AttachSupplementaryServiceAPDU(facilityPDU);
  366.  
  367.   return connection.WriteSignalPDU(facilityPDU);
  368. }
  369.  
  370.  
  371. void H450ServiceAPDU::ParseEndpointAddress(H4501_EndpointAddress& endpointAddress,
  372.                                            PString& remoteParty)
  373. {
  374.   H4501_ArrayOf_AliasAddress& destinationAddress = endpointAddress.m_destinationAddress;
  375.  
  376.   PString alias;
  377.   H323TransportAddress transportAddress;
  378.  
  379.   for (PINDEX i = 0; i < destinationAddress.GetSize(); i++) {
  380.     H225_AliasAddress& aliasAddress = destinationAddress[i];
  381.  
  382.     if (aliasAddress.GetTag() == H225_AliasAddress::e_transportID)
  383.       transportAddress = (H225_TransportAddress &)aliasAddress;
  384.     else
  385.       alias = ::H323GetAliasAddressString(aliasAddress);
  386.   }
  387.  
  388.   if (alias.IsEmpty()) {
  389.     remoteParty = transportAddress;
  390.   }
  391.   else if (transportAddress.IsEmpty()) {
  392.     remoteParty = alias;
  393.   }
  394.   else {
  395.     remoteParty = alias + '@' + transportAddress;
  396.   }
  397. }
  398.  
  399.  
  400. /////////////////////////////////////////////////////////////////////////////
  401.  
  402. H450xDispatcher::H450xDispatcher(H323Connection & conn)
  403.   : connection(conn)
  404. {
  405.   opcodeHandler.DisallowDeleteObjects();
  406.  
  407.   nextInvokeId = 0;
  408. }
  409.  
  410.  
  411. void H450xDispatcher::AddOpCode(unsigned opcode, H450xHandler * handler)
  412. {
  413.   PAssertNULL(handler);
  414.   if (handlers.GetObjectsIndex(handler) == P_MAX_INDEX)
  415.     handlers.Append(handler);
  416.  
  417.   opcodeHandler.SetAt(opcode, handler);
  418. }
  419.  
  420.  
  421. void H450xDispatcher::AttachToSetup(H323SignalPDU & pdu)
  422. {
  423.   for (PINDEX i = 0; i < handlers.GetSize(); i++)
  424.     handlers[i].AttachToSetup(pdu);
  425. }
  426.  
  427.  
  428. void H450xDispatcher::AttachToAlerting(H323SignalPDU & pdu)
  429. {
  430.   for (PINDEX i = 0; i < handlers.GetSize(); i++)
  431.     handlers[i].AttachToAlerting(pdu);
  432. }
  433.  
  434.  
  435. void H450xDispatcher::AttachToConnect(H323SignalPDU & pdu)
  436. {
  437.   for (PINDEX i = 0; i < handlers.GetSize(); i++)
  438.     handlers[i].AttachToConnect(pdu);
  439. }
  440.  
  441.  
  442. void H450xDispatcher::AttachToReleaseComplete(H323SignalPDU & pdu)
  443. {
  444.   for (PINDEX i = 0; i < handlers.GetSize(); i++)
  445.     handlers[i].AttachToReleaseComplete(pdu);
  446. }
  447.  
  448.  
  449. BOOL H450xDispatcher::HandlePDU(const H323SignalPDU & pdu)
  450. {
  451. BOOL result = TRUE;
  452.   for (PINDEX i = 0; i < pdu.m_h323_uu_pdu.m_h4501SupplementaryService.GetSize(); i++) {
  453.     H4501_SupplementaryService supplementaryService;
  454.  
  455.     // Decode the supplementary service PDU from the PPER Stream
  456.     if (pdu.m_h323_uu_pdu.m_h4501SupplementaryService[i].DecodeSubType(supplementaryService)) {
  457.       PTRACE(4, "H4501\tReceived supplementary service PDU:\n  "
  458.              << setprecision(2) << supplementaryService);
  459.     }
  460.     else {
  461.       PTRACE(1, "H4501\tInvalid supplementary service PDU decode:\n  "
  462.              << setprecision(2) << supplementaryService);
  463.       continue;
  464.     }
  465.  
  466.     H4501_InterpretationApdu & interpretation = supplementaryService.m_interpretationApdu;
  467.  
  468.     if (supplementaryService.m_serviceApdu.GetTag() == H4501_ServiceApdus::e_rosApdus) {
  469.       H4501_ArrayOf_ROS& operations = (H4501_ArrayOf_ROS&) supplementaryService.m_serviceApdu;
  470.  
  471.       for (PINDEX j = 0; j < operations.GetSize(); j ++) {
  472.         X880_ROS& operation = operations[j];
  473.  
  474.         PTRACE(3, "H4501\tX880 ROS " << operation.GetTagName());
  475.  
  476.         switch (operation.GetTag()) {
  477.           case X880_ROS::e_invoke:
  478.             result = OnReceivedInvoke((X880_Invoke &)operation, interpretation);
  479.             break;
  480.  
  481.           case X880_ROS::e_returnResult:
  482.             result = OnReceivedReturnResult((X880_ReturnResult &)operation);
  483.             break;
  484.  
  485.           case X880_ROS::e_returnError:
  486.             result = OnReceivedReturnError((X880_ReturnError &)operation);
  487.             break;
  488.  
  489.           case X880_ROS::e_reject:
  490.             result = OnReceivedReject((X880_Reject &)operation);
  491.             break;
  492.  
  493.           default :
  494.             break;
  495.         }
  496.       }
  497.     }
  498.   }
  499.   return result;
  500. }
  501.  
  502. BOOL H450xDispatcher::OnReceivedInvoke(X880_Invoke & invoke, H4501_InterpretationApdu & interpretation)
  503. {
  504.   BOOL result = TRUE;
  505.   // Get the invokeId
  506.   int invokeId = invoke.m_invokeId.GetValue();
  507.  
  508.   // Get the linkedId if present
  509.   int linkedId = -1;
  510.   if (invoke.HasOptionalField(X880_Invoke::e_linkedId)) {
  511.     linkedId = invoke.m_linkedId.GetValue();
  512.   }
  513.  
  514.   // Get the argument if present
  515.   PASN_OctetString * argument = NULL;
  516.   if (invoke.HasOptionalField(X880_Invoke::e_argument)) {
  517.     argument = &invoke.m_argument;
  518.   }
  519.  
  520.   // Get the opcode
  521.   if (invoke.m_opcode.GetTag() == X880_Code::e_local) {
  522.     int opcode = ((PASN_Integer&) invoke.m_opcode).GetValue();
  523.     if (!opcodeHandler.Contains(opcode)) {
  524.       PTRACE(2, "H4501\tInvoke of unsupported local opcode:\n  " << invoke);      
  525.       if (interpretation.GetTag() != H4501_InterpretationApdu::e_discardAnyUnrecognizedInvokePdu)
  526.         SendInvokeReject(invokeId, 1 /*X880_InvokeProblem::e_unrecognisedOperation*/);
  527.       if (interpretation.GetTag() == H4501_InterpretationApdu::e_clearCallIfAnyInvokePduNotRecognized)
  528.         result = FALSE;
  529.     }
  530.     else
  531.       result = opcodeHandler[opcode].OnReceivedInvoke(opcode, invokeId, linkedId, argument);
  532.   }
  533.   else {
  534.     if (interpretation.GetTag() != H4501_InterpretationApdu::e_discardAnyUnrecognizedInvokePdu)
  535.       SendInvokeReject(invokeId, 1 /*X880_InvokeProblem::e_unrecognisedOperation*/);
  536.     PTRACE(2, "H4501\tInvoke of unsupported global opcode:\n  " << invoke);
  537.     if (interpretation.GetTag() == H4501_InterpretationApdu::e_clearCallIfAnyInvokePduNotRecognized)
  538.       result = FALSE;
  539.   }
  540.   return result;
  541. }
  542.  
  543.  
  544. BOOL H450xDispatcher::OnReceivedReturnResult(X880_ReturnResult & returnResult)
  545. {
  546.   unsigned invokeId = returnResult.m_invokeId.GetValue();
  547.  
  548.   for (PINDEX i = 0; i < handlers.GetSize(); i++) {
  549.     if (handlers[i].GetInvokeId() == invokeId) {
  550.       handlers[i].OnReceivedReturnResult(returnResult);
  551.       break;
  552.     }
  553.   }
  554.   return TRUE;
  555. }
  556.  
  557.  
  558. BOOL H450xDispatcher::OnReceivedReturnError(X880_ReturnError & returnError)
  559. {
  560.   BOOL result=TRUE;
  561.   unsigned invokeId = returnError.m_invokeId.GetValue();
  562.   int errorCode = 0;
  563.  
  564.   if (returnError.m_errorCode.GetTag() == X880_Code::e_local)
  565.     errorCode = ((PASN_Integer&) returnError.m_errorCode).GetValue();
  566.  
  567.   for (PINDEX i = 0; i < handlers.GetSize(); i++) {
  568.     if (handlers[i].GetInvokeId() == invokeId) {
  569.       result = handlers[i].OnReceivedReturnError(errorCode, returnError);
  570.       break;
  571.     }
  572.   }
  573.   return result;
  574. }
  575.  
  576.  
  577. BOOL H450xDispatcher::OnReceivedReject(X880_Reject & reject)
  578. {
  579.   int problem = 0;
  580.  
  581.   switch (reject.m_problem.GetTag()) {
  582.     case X880_Reject_problem::e_general:
  583.     {
  584.       X880_GeneralProblem & generalProblem = reject.m_problem;
  585.       problem = generalProblem.GetValue();
  586.     }
  587.     break;
  588.  
  589.     case X880_Reject_problem::e_invoke:
  590.     {
  591.       X880_InvokeProblem & invokeProblem = reject.m_problem;
  592.       problem = invokeProblem.GetValue();
  593.     }
  594.     break;
  595.  
  596.     case X880_Reject_problem::e_returnResult:
  597.     {
  598.       X880_ReturnResultProblem & returnResultProblem = reject.m_problem;
  599.       problem = returnResultProblem.GetValue();
  600.     }
  601.     break;
  602.  
  603.     case X880_Reject_problem::e_returnError:
  604.     {
  605.       X880_ReturnErrorProblem & returnErrorProblem = reject.m_problem;
  606.       problem = returnErrorProblem.GetValue();
  607.     }
  608.     break;
  609.  
  610.     default:
  611.       break;
  612.   }
  613.  
  614.  
  615.   unsigned invokeId = reject.m_invokeId;
  616.   for (PINDEX i = 0; i < handlers.GetSize(); i++) {
  617.     if (handlers[i].GetInvokeId() == invokeId) {
  618.       handlers[i].OnReceivedReject(reject.m_problem.GetTag(), problem);
  619.       break;
  620.     }
  621.   }
  622.   return TRUE;
  623. }
  624.  
  625.  
  626. void H450xDispatcher::SendReturnError(int invokeId, int returnError)
  627. {
  628.   H450ServiceAPDU serviceAPDU;
  629.  
  630.   serviceAPDU.BuildReturnError(invokeId, returnError);
  631.  
  632.   serviceAPDU.WriteFacilityPDU(connection);
  633. }
  634.  
  635.  
  636. void H450xDispatcher::SendGeneralReject(int invokeId, int problem)
  637. {
  638.   H450ServiceAPDU serviceAPDU;
  639.  
  640.   X880_Reject & reject = serviceAPDU.BuildReject(invokeId);
  641.   reject.m_problem.SetTag(X880_Reject_problem::e_general);
  642.   X880_GeneralProblem & generalProblem = (X880_GeneralProblem &) reject.m_problem;
  643.   generalProblem = problem;
  644.  
  645.   serviceAPDU.WriteFacilityPDU(connection);
  646. }
  647.  
  648.  
  649. void H450xDispatcher::SendInvokeReject(int invokeId, int problem)
  650. {
  651.   H450ServiceAPDU serviceAPDU;
  652.  
  653.   X880_Reject & reject = serviceAPDU.BuildReject(invokeId);
  654.   reject.m_problem.SetTag(X880_Reject_problem::e_invoke);
  655.   X880_InvokeProblem & invokeProblem = (X880_InvokeProblem &) reject.m_problem;
  656.   invokeProblem = problem;
  657.  
  658.   serviceAPDU.WriteFacilityPDU(connection);
  659. }
  660.  
  661.  
  662. void H450xDispatcher::SendReturnResultReject(int invokeId, int problem)
  663. {
  664.   H450ServiceAPDU serviceAPDU;
  665.  
  666.   X880_Reject & reject = serviceAPDU.BuildReject(invokeId);
  667.   reject.m_problem.SetTag(X880_Reject_problem::e_returnResult);
  668.   X880_ReturnResultProblem & returnResultProblem = reject.m_problem;
  669.   returnResultProblem = problem;
  670.  
  671.   serviceAPDU.WriteFacilityPDU(connection);
  672. }
  673.  
  674.  
  675. void H450xDispatcher::SendReturnErrorReject(int invokeId, int problem)
  676. {
  677.   H450ServiceAPDU serviceAPDU;
  678.  
  679.   X880_Reject & reject = serviceAPDU.BuildReject(invokeId);
  680.   reject.m_problem.SetTag(X880_Reject_problem::e_returnError);
  681.   X880_ReturnErrorProblem & returnErrorProblem = reject.m_problem;
  682.   returnErrorProblem = problem;
  683.  
  684.   serviceAPDU.WriteFacilityPDU(connection);
  685. }
  686.  
  687.  
  688. /////////////////////////////////////////////////////////////////////////////
  689.  
  690. H450xHandler::H450xHandler(H323Connection & conn, H450xDispatcher & disp)
  691.   : endpoint(conn.GetEndPoint()),
  692.     connection(conn),
  693.     dispatcher(disp)
  694. {
  695.   currentInvokeId = 0;
  696. }
  697.  
  698.  
  699. void H450xHandler::AttachToSetup(H323SignalPDU &)
  700. {
  701. }
  702.  
  703.  
  704. void H450xHandler::AttachToAlerting(H323SignalPDU &)
  705. {
  706. }
  707.  
  708.  
  709. void H450xHandler::AttachToConnect(H323SignalPDU &)
  710. {
  711. }
  712.  
  713.  
  714. void H450xHandler::AttachToReleaseComplete(H323SignalPDU &)
  715. {
  716. }
  717.  
  718.  
  719. BOOL H450xHandler::OnReceivedReturnResult(X880_ReturnResult & /*returnResult*/)
  720. {
  721.   return TRUE;
  722. }
  723.  
  724.  
  725. BOOL H450xHandler::OnReceivedReturnError(int /*errorCode*/,
  726.                                         X880_ReturnError & /*returnError*/)
  727. {
  728.   return TRUE;
  729. }
  730.  
  731.  
  732. BOOL H450xHandler::OnReceivedReject(int /*problemType*/,
  733.                                    int /*problemNumber*/)
  734. {
  735.   return TRUE;
  736. }
  737.  
  738.  
  739. void H450xHandler::SendReturnError(int returnError)
  740. {
  741.   dispatcher.SendReturnError(currentInvokeId, returnError);
  742.   currentInvokeId = 0;
  743. }
  744.  
  745.  
  746. void H450xHandler::SendGeneralReject(int problem)
  747. {
  748.   dispatcher.SendGeneralReject(currentInvokeId, problem);
  749.   currentInvokeId = 0;
  750. }
  751.  
  752.  
  753. void H450xHandler::SendInvokeReject(int problem)
  754. {
  755.   dispatcher.SendInvokeReject(currentInvokeId, problem);
  756.   currentInvokeId = 0;
  757. }
  758.  
  759.  
  760. void H450xHandler::SendReturnResultReject(int problem)
  761. {
  762.   dispatcher.SendReturnResultReject(currentInvokeId, problem);
  763.   currentInvokeId = 0;
  764. }
  765.  
  766.  
  767. void H450xHandler::SendReturnErrorReject(int problem)
  768. {
  769.   dispatcher.SendReturnErrorReject(currentInvokeId, problem);
  770.   currentInvokeId = 0;
  771. }
  772.  
  773.  
  774. BOOL H450xHandler::DecodeArguments(PASN_OctetString * argString,
  775.                                   PASN_Object & argObject,
  776.                                   int absentErrorCode)
  777. {
  778.   if (argString == NULL) {
  779.     if (absentErrorCode >= 0)
  780.       SendReturnError(absentErrorCode);
  781.     return FALSE;
  782.   }
  783.  
  784.   PPER_Stream argStream(*argString);
  785.   if (argObject.Decode(argStream)) {
  786.     PTRACE(4, "H4501\tSupplementary service argument:\n  "
  787.            << setprecision(2) << argObject);
  788.     return TRUE;
  789.   }
  790.  
  791.   PTRACE(1, "H4501\tInvalid supplementary service argument:\n  "
  792.          << setprecision(2) << argObject);
  793.   return FALSE;
  794. }
  795.  
  796.  
  797. /////////////////////////////////////////////////////////////////////////////
  798.  
  799. H4502Handler::H4502Handler(H323Connection & conn, H450xDispatcher & disp)
  800.   : H450xHandler(conn, disp)
  801. {
  802.   dispatcher.AddOpCode(H4502_CallTransferOperation::e_callTransferIdentify, this);
  803.   dispatcher.AddOpCode(H4502_CallTransferOperation::e_callTransferAbandon, this);
  804.   dispatcher.AddOpCode(H4502_CallTransferOperation::e_callTransferInitiate, this);
  805.   dispatcher.AddOpCode(H4502_CallTransferOperation::e_callTransferSetup, this);
  806.   dispatcher.AddOpCode(H4502_CallTransferOperation::e_callTransferUpdate, this);
  807.   dispatcher.AddOpCode(H4502_CallTransferOperation::e_subaddressTransfer, this);
  808.   dispatcher.AddOpCode(H4502_CallTransferOperation::e_callTransferComplete, this);
  809.   dispatcher.AddOpCode(H4502_CallTransferOperation::e_callTransferActive, this);
  810.  
  811.   transferringCallToken = "";
  812.   ctState = e_ctIdle;
  813.   ctResponseSent = FALSE;
  814.   CallToken = PString();
  815.   nextCallIdentity = 0;
  816.   consultationTransfer = FALSE;
  817.  
  818.   ctTimer.SetNotifier(PCREATE_NOTIFIER(OnCallTransferTimeOut));
  819. }
  820.  
  821.  
  822. void H4502Handler::AttachToSetup(H323SignalPDU & pdu)
  823. {
  824.   // Do we need to attach a call transfer setup invoke APDU?
  825.   if (ctState != e_ctAwaitSetupResponse)
  826.     return;
  827.  
  828.   H450ServiceAPDU serviceAPDU;
  829.  
  830.   // Store the outstanding invokeID associated with this connection
  831.   currentInvokeId = dispatcher.GetNextInvokeId();
  832.  
  833.   // Use the call identity from the ctInitiateArg
  834.   serviceAPDU.BuildCallTransferSetup(currentInvokeId, transferringCallIdentity);
  835.  
  836.   serviceAPDU.AttachSupplementaryServiceAPDU(pdu);
  837. }
  838.  
  839.  
  840. void H4502Handler::AttachToAlerting(H323SignalPDU & pdu)
  841. {
  842.   // Do we need to send a callTransferSetup return result APDU?
  843.   if (currentInvokeId == 0 || ctResponseSent)
  844.     return;
  845.  
  846.   H450ServiceAPDU serviceAPDU;
  847.   serviceAPDU.BuildReturnResult(currentInvokeId);
  848.   serviceAPDU.AttachSupplementaryServiceAPDU(pdu);
  849.   ctResponseSent = TRUE;
  850.   currentInvokeId = 0;
  851. }
  852.  
  853.  
  854. void H4502Handler::AttachToConnect(H323SignalPDU & pdu)
  855. {
  856.   // Do we need to include a ctInitiateReturnResult APDU in our Release Complete Message?
  857.   if (currentInvokeId == 0 || ctResponseSent)
  858.     return;
  859.  
  860.   H450ServiceAPDU serviceAPDU;
  861.   serviceAPDU.BuildReturnResult(currentInvokeId);
  862.   serviceAPDU.AttachSupplementaryServiceAPDU(pdu);
  863.   ctResponseSent = TRUE;
  864.   currentInvokeId = 0;
  865. }
  866.  
  867.  
  868. void H4502Handler::AttachToReleaseComplete(H323SignalPDU & pdu)
  869. {
  870.   // Do we need to include a ctInitiateReturnResult APDU in our Release Complete Message?
  871.   if (currentInvokeId == 0)
  872.     return;
  873.  
  874.   // If the SETUP message we received from the other end had a callTransferSetup APDU
  875.   // in it, then we need to send back a RELEASE COMPLETE PDU with a callTransferSetup 
  876.   // ReturnError.
  877.   // Else normal call - clear it down
  878.   H450ServiceAPDU serviceAPDU;
  879.  
  880.   if (ctResponseSent) {
  881.     serviceAPDU.BuildReturnResult(currentInvokeId);
  882.     ctResponseSent = FALSE;
  883.     currentInvokeId = 0;
  884.   }
  885.   else {
  886.     serviceAPDU.BuildReturnError(currentInvokeId, H4501_GeneralErrorList::e_notAvailable);
  887.     ctResponseSent = TRUE;
  888.     currentInvokeId = 0;
  889.   }
  890.  
  891.   serviceAPDU.AttachSupplementaryServiceAPDU(pdu);
  892. }
  893.  
  894.  
  895. BOOL H4502Handler::OnReceivedInvoke(int opcode,
  896.                                     int invokeId,
  897.                                     int linkedId,
  898.                                     PASN_OctetString * argument)
  899. {
  900.   currentInvokeId = invokeId;
  901.  
  902.   switch (opcode) {
  903.     case H4502_CallTransferOperation::e_callTransferIdentify:
  904.       OnReceivedCallTransferIdentify(linkedId);
  905.       break;
  906.  
  907.     case H4502_CallTransferOperation::e_callTransferAbandon:
  908.       OnReceivedCallTransferAbandon(linkedId);
  909.       break;
  910.  
  911.     case H4502_CallTransferOperation::e_callTransferInitiate:
  912.       OnReceivedCallTransferInitiate(linkedId, argument);
  913.       break;
  914.  
  915.     case H4502_CallTransferOperation::e_callTransferSetup:
  916.       OnReceivedCallTransferSetup(linkedId, argument);
  917.       break;
  918.  
  919.     case H4502_CallTransferOperation::e_callTransferUpdate:
  920.       OnReceivedCallTransferUpdate(linkedId, argument);
  921.       break;
  922.  
  923.     case H4502_CallTransferOperation::e_subaddressTransfer:
  924.       OnReceivedSubaddressTransfer(linkedId, argument);
  925.       break;
  926.  
  927.     case H4502_CallTransferOperation::e_callTransferComplete:
  928.       OnReceivedCallTransferComplete(linkedId, argument);
  929.       break;
  930.  
  931.     case H4502_CallTransferOperation::e_callTransferActive:
  932.       OnReceivedCallTransferActive(linkedId, argument);
  933.       break;
  934.  
  935.     default:
  936.       currentInvokeId = 0;
  937.       return FALSE;
  938.   }
  939.  
  940.   return TRUE;
  941. }
  942.  
  943.  
  944. void H4502Handler::OnReceivedCallTransferIdentify(int /*linkedId*/)
  945. {
  946.   if (!endpoint.OnCallTransferIdentify(connection))
  947.     SendReturnError(H4501_GeneralErrorList::e_notAvailable);
  948.   
  949.   // Send a FACILITY message with a callTransferIdentify return result
  950.   // Supplementary Service PDU to the transferring endpoint.
  951.   H450ServiceAPDU serviceAPDU;
  952.  
  953.   X880_ReturnResult& result = serviceAPDU.BuildReturnResult(currentInvokeId);
  954.   result.IncludeOptionalField(X880_ReturnResult::e_result);
  955.   result.m_result.m_opcode.SetTag(X880_Code::e_local);
  956.   PASN_Integer& operation = (PASN_Integer&) result.m_result.m_opcode;
  957.   operation.SetValue(H4502_CallTransferOperation::e_callTransferIdentify);
  958.  
  959.   H4502_CTIdentifyRes ctIdentifyResult;
  960.  
  961.   // Restrict the generated value to 4 digits (13 bits)
  962.   unsigned int id = GetNextCallIdentityValue() & 0x1FFF;
  963.   PString pstrId(PString::Unsigned, id);
  964.   ctIdentifyResult.m_callIdentity = pstrId;
  965.  
  966.   // Store the callIdentity of this connection in the dictionary
  967.   endpoint.GetCallIdentityDictionary().SetAt(pstrId, &connection);
  968.  
  969.   H4501_ArrayOf_AliasAddress& aliasAddress = ctIdentifyResult.m_reroutingNumber.m_destinationAddress;
  970.  
  971.   PString localName = connection.GetLocalPartyName();
  972.   if (localName.IsEmpty()) 
  973.     aliasAddress.SetSize(1);
  974.   else {
  975.     aliasAddress.SetSize(2);
  976.     aliasAddress[1].SetTag(H225_AliasAddress::e_dialedDigits);
  977.     H323SetAliasAddress(localName, aliasAddress[1]);  // Will encode as h323-Id if not E.164
  978.   }
  979.  
  980.   H323TransportAddress address;
  981.   address = connection.GetSignallingChannel()->GetLocalAddress();
  982.  
  983.   aliasAddress[0].SetTag(H225_AliasAddress::e_transportID);
  984.   H225_TransportAddress& cPartyTransport = (H225_TransportAddress&) aliasAddress[0];
  985.   address.SetPDU(cPartyTransport);
  986.  
  987.   PPER_Stream resultStream;
  988.   ctIdentifyResult.Encode(resultStream);
  989.   resultStream.CompleteEncoding();
  990.   result.m_result.m_result.SetValue(resultStream);
  991.  
  992.   serviceAPDU.WriteFacilityPDU(connection);
  993.  
  994.   ctState = e_ctAwaitSetup;
  995.  
  996.   // start timer CT-T2
  997.   PTRACE(4, "H450.2\tStarting timer CT-T2");
  998.   StartctTimer(endpoint.GetCallTransferT2());
  999. }
  1000.  
  1001.  
  1002. void H4502Handler::OnReceivedCallTransferAbandon(int /*linkedId*/)
  1003. {
  1004.   switch (ctState) {
  1005.     case e_ctAwaitSetup:
  1006.       {
  1007.         // Stop Timer CT-T2 and enter state e_ctIdle
  1008.         StopctTimer();
  1009.         PTRACE(4, "H4502\tStopping timer CT-T2");
  1010.  
  1011.         currentInvokeId = 0;
  1012.         ctState = e_ctIdle;
  1013.       }
  1014.       break;
  1015.  
  1016.     default:
  1017.       break;
  1018.   }
  1019. }
  1020.  
  1021.  
  1022. void H4502Handler::OnReceivedCallTransferInitiate(int /*linkedId*/,
  1023.                                                   PASN_OctetString * argument)
  1024. {
  1025.   // TBD: Check Call Hold status. If call is held, it must first be 
  1026.   // retrieved before being transferred. -- dcassel 4/01
  1027.  
  1028.   H4502_CTInitiateArg ctInitiateArg;
  1029.   if (!DecodeArguments(argument, ctInitiateArg,
  1030.                        H4502_CallTransferErrors::e_invalidReroutingNumber))
  1031.     return;
  1032.  
  1033.   ctResponseSent = TRUE;
  1034.  
  1035.   PString remoteParty;
  1036.   H450ServiceAPDU::ParseEndpointAddress(ctInitiateArg.m_reroutingNumber, remoteParty);
  1037.  
  1038.   PString newToken;
  1039.   if (!endpoint.OnCallTransferInitiate(connection, remoteParty) ||
  1040.        endpoint.SetupTransfer(connection.GetCallToken(),
  1041.                               ctInitiateArg.m_callIdentity.GetValue(),
  1042.                               remoteParty, newToken) == NULL)
  1043.     SendReturnError(H4502_CallTransferErrors::e_establishmentFailure);
  1044. }
  1045.  
  1046.  
  1047. void H4502Handler::OnReceivedCallTransferSetup(int /*linkedId*/,
  1048.                                                PASN_OctetString * argument)
  1049. {
  1050.   H4502_CTSetupArg ctSetupArg;
  1051.   if (!DecodeArguments(argument, ctSetupArg,
  1052.                        H4502_CallTransferErrors::e_unrecognizedCallIdentity))
  1053.     return;
  1054.  
  1055.   // Get the Transferring User's details if present
  1056.   PString transferringParty;
  1057.   if (ctSetupArg.HasOptionalField(H4502_CTSetupArg::e_transferringNumber)) {
  1058.     H450ServiceAPDU::ParseEndpointAddress(ctSetupArg.m_transferringNumber, transferringParty);
  1059.   }
  1060.  
  1061.   PString callIdentity;
  1062.   callIdentity = ctSetupArg.m_callIdentity;
  1063.  
  1064.   if (callIdentity.IsEmpty()) { // Blind Transfer
  1065.     switch (ctState) {
  1066.       case e_ctIdle:
  1067.         ctState = e_ctAwaitSetupResponse;
  1068.         break;
  1069.  
  1070.       // Wrong State
  1071.       default :
  1072.         break;
  1073.     }
  1074.   }
  1075.   else { // Transfer through Consultation
  1076.     
  1077.     // We need to check that the call identity and destination address information match those in the 
  1078.     // second call.  For the time being we just check that the call identities match as there does not 
  1079.     // appear to be an elegant solution to compare the destination address information.
  1080.  
  1081.     // Get this callIdentity from our dictionary (if present)
  1082.     H323Connection *secondaryCall = endpoint.GetCallIdentityDictionary().GetAt(callIdentity);
  1083.   
  1084.     if (secondaryCall != NULL)
  1085.       secondaryCall->HandleConsultationTransfer(callIdentity, connection);
  1086.     else  // Mismatched callIdentity
  1087.       SendReturnError(H4502_CallTransferErrors::e_unrecognizedCallIdentity);
  1088.   }
  1089. }
  1090.  
  1091.  
  1092. void H4502Handler::OnReceivedCallTransferUpdate(int /*linkedId*/,
  1093.                                                 PASN_OctetString * argument)
  1094. {
  1095.   H4502_CTUpdateArg ctUpdateArg;
  1096.   if (!DecodeArguments(argument, ctUpdateArg, -1))
  1097.     return;
  1098.  
  1099. }
  1100.  
  1101.  
  1102. void H4502Handler::OnReceivedSubaddressTransfer(int /*linkedId*/,
  1103.                                                 PASN_OctetString * argument)
  1104. {
  1105.   H4502_SubaddressTransferArg subaddressTransferArg;
  1106.   if (!DecodeArguments(argument, subaddressTransferArg, -1))
  1107.     return;
  1108.  
  1109. }
  1110.  
  1111.  
  1112. void H4502Handler::OnReceivedCallTransferComplete(int /*linkedId*/,
  1113.                                                   PASN_OctetString * argument)
  1114. {
  1115.   H4502_CTCompleteArg ctCompleteArg;
  1116.   if (!DecodeArguments(argument, ctCompleteArg, -1))
  1117.     return;
  1118.  
  1119. }
  1120.  
  1121.  
  1122. void H4502Handler::OnReceivedCallTransferActive(int /*linkedId*/,
  1123.                                                 PASN_OctetString * argument)
  1124. {
  1125.   H4502_CTActiveArg ctActiveArg;
  1126.   if (!DecodeArguments(argument, ctActiveArg, -1))
  1127.     return;
  1128.  
  1129. }
  1130.  
  1131.  
  1132. BOOL H4502Handler::OnReceivedReturnResult(X880_ReturnResult & returnResult)
  1133. {
  1134.   if (currentInvokeId == returnResult.m_invokeId.GetValue()) {
  1135.     switch (ctState) {
  1136.       case e_ctAwaitInitiateResponse:
  1137.         OnReceivedInitiateReturnResult(); 
  1138.         break;
  1139.  
  1140.       case e_ctAwaitSetupResponse:
  1141.         OnReceivedSetupReturnResult();
  1142.         break;
  1143.  
  1144.       case e_ctAwaitIdentifyResponse:
  1145.         OnReceivedIdentifyReturnResult(returnResult);
  1146.         break;
  1147.  
  1148.       default :
  1149.         break;
  1150.     }
  1151.   }
  1152.   return TRUE;
  1153. }
  1154.  
  1155.  
  1156. void H4502Handler::OnReceivedInitiateReturnResult()
  1157. {
  1158.   // stop timer CT-T3
  1159.   StopctTimer();
  1160.   PTRACE(4, "H4502\tStopping timer CT-T3");
  1161.   ctState = e_ctIdle;
  1162.   currentInvokeId = 0;
  1163.  
  1164.   // clear the primary and secondary call if not already cleared,
  1165. }
  1166.  
  1167.  
  1168. void H4502Handler::OnReceivedSetupReturnResult()
  1169. {
  1170.   // stop timer CT-T4
  1171.   StopctTimer();
  1172.   PTRACE(4, "H4502\tStopping timer CT-T4");
  1173.   ctState = e_ctIdle;
  1174.   currentInvokeId = 0;
  1175.  
  1176.   // Clear the primary call
  1177.   endpoint.ClearCall(transferringCallToken, H323Connection::EndedByCallForwarded);
  1178. }
  1179.  
  1180.  
  1181. void H4502Handler::OnReceivedIdentifyReturnResult(X880_ReturnResult &returnResult)
  1182. {
  1183.   // stop timer CT-T1
  1184.   StopctTimer();
  1185.   PTRACE(4, "H4502\tStopping timer CT-T1");
  1186.  
  1187.   // Have received response.
  1188.   ctState = e_ctIdle;
  1189.  
  1190.   // Get the return result if present
  1191.   PASN_OctetString * result = NULL;
  1192.   if (returnResult.HasOptionalField(X880_ReturnResult::e_result)) {
  1193.     result = &returnResult.m_result.m_result;
  1194.  
  1195.     // Extract the C Party Details
  1196.     H4502_CTIdentifyRes ctIdentifyResult;
  1197.  
  1198.     PPER_Stream resultStream(*result);
  1199.     ctIdentifyResult.Decode(resultStream);
  1200.     PString callIdentity = ctIdentifyResult.m_callIdentity.GetValue();
  1201.  
  1202.     PString remoteParty;
  1203.     H450ServiceAPDU::ParseEndpointAddress(ctIdentifyResult.m_reroutingNumber, remoteParty);
  1204.  
  1205.     // Store the secondary call token on the primary connection so we can send a 
  1206.     // callTransferAbandon invoke APDU on the secondary call at a later stage if we 
  1207.     // get back a callTransferInitiateReturnError
  1208.     H323Connection* primaryConnection = endpoint.FindConnectionWithLock(CallToken);
  1209.  
  1210.     if (primaryConnection != NULL) {
  1211.       primaryConnection->SetAssociatedCallToken(connection.GetCallToken());
  1212.  
  1213.       // Send a callTransferInitiate invoke APDU in a FACILITY message
  1214.       // to the transferred endpoint on the primary call
  1215.       endpoint.TransferCall(primaryConnection->GetCallToken(), remoteParty, callIdentity);
  1216.     }
  1217.   }
  1218. }
  1219.  
  1220.  
  1221. BOOL H4502Handler::OnReceivedReturnError(int errorCode, X880_ReturnError &returnError)
  1222. {
  1223.   if (currentInvokeId == returnError.m_invokeId.GetValue()) {
  1224.     switch (ctState) {
  1225.       case e_ctAwaitInitiateResponse:
  1226.         OnReceivedInitiateReturnError();
  1227.         break;
  1228.  
  1229.       case e_ctAwaitSetupResponse:
  1230.         OnReceivedSetupReturnError(errorCode);
  1231.         break;
  1232.  
  1233.       case e_ctAwaitIdentifyResponse:
  1234.         OnReceivedIdentifyReturnError();
  1235.         break;
  1236.  
  1237.       default :
  1238.         break;
  1239.     }
  1240.   }
  1241.   return TRUE;
  1242. }
  1243.  
  1244.  
  1245. void H4502Handler::OnReceivedInitiateReturnError(const bool timerExpiry)
  1246.   if (!timerExpiry) {
  1247.     // stop timer CT-T3
  1248.     StopctTimer();
  1249.     PTRACE(4, "H4502\tStopping timer CT-T3");
  1250.   }
  1251.   else
  1252.     PTRACE(4, "H4502\tTimer CT-T3 has expired on the Transferring Endpoint awaiting a response to a callTransferInitiate APDU.");
  1253.  
  1254.   currentInvokeId = 0;
  1255.   ctState = e_ctIdle;
  1256.  
  1257.  
  1258.   // Send a callTransferAbandon invoke APDU in a FACILITY message on the secondary call
  1259.   // (if it exists) and enter state CT-Idle.
  1260.   H323Connection* secondaryConnection = endpoint.FindConnectionWithLock(CallToken);
  1261.  
  1262.   if (secondaryConnection != NULL) {
  1263.     H450ServiceAPDU serviceAPDU;
  1264.  
  1265.     serviceAPDU.BuildCallTransferAbandon(dispatcher.GetNextInvokeId());
  1266.     serviceAPDU.WriteFacilityPDU(*secondaryConnection);
  1267.     secondaryConnection->Unlock();
  1268.   }
  1269. }
  1270.  
  1271.  
  1272. void H4502Handler::OnReceivedSetupReturnError(int errorCode,
  1273.                                               const bool timerExpiry)
  1274. {
  1275.   ctState = e_ctIdle;
  1276.   currentInvokeId = 0;
  1277.   
  1278.   if (!timerExpiry) {
  1279.     // stop timer CT-T4 if it is running
  1280.     StopctTimer();
  1281.     PTRACE(4, "H4502\tStopping timer CT-T4");  
  1282.   }
  1283.   else {
  1284.     PTRACE(3, "H4502\tTimer CT-T4 has expired on the Transferred Endpoint awaiting a response to a callTransferSetup APDU.");
  1285.  
  1286.     // Clear the transferred call.
  1287.     endpoint.ClearCall(connection.GetCallToken());
  1288.   }
  1289.  
  1290.   // Send a facility message to the transferring endpoint
  1291.   // containing a call transfer initiate return error
  1292.   H323Connection* primaryConnection = endpoint.FindConnectionWithLock(transferringCallToken);
  1293.  
  1294.   if (primaryConnection != NULL) {
  1295.     primaryConnection->HandleCallTransferFailure(errorCode);
  1296.     primaryConnection->Unlock();
  1297.   }
  1298. }
  1299.  
  1300.  
  1301. void H4502Handler::OnReceivedIdentifyReturnError(const bool timerExpiry)
  1302. {
  1303.   // The transferred-to user cannot participate in our transfer request
  1304.   ctState = e_ctIdle;
  1305.   currentInvokeId = 0;
  1306.  
  1307.   if (!timerExpiry) {
  1308.     // stop timer CT-T1
  1309.     StopctTimer();
  1310.     PTRACE(4, "H4502\tStopping timer CT-T1");
  1311.   }
  1312.   else {
  1313.     PTRACE(4, "H4502\tTimer CT-T1 has expired on the Transferring Endpoint awaiting a response to a callTransferIdentify APDU.");
  1314.  
  1315.     // send a callTransferAbandon invoke APDU in a FACILITY message on the secondary call
  1316.     // and enter state CT-Idle.
  1317.     connection.Lock();
  1318.  
  1319.     H450ServiceAPDU serviceAPDU;
  1320.  
  1321.     serviceAPDU.BuildCallTransferAbandon(dispatcher.GetNextInvokeId());
  1322.     serviceAPDU.WriteFacilityPDU(connection);
  1323.  
  1324.     connection.Unlock();
  1325.   }
  1326. }
  1327.  
  1328. void H4502Handler::TransferCall(const PString & remoteParty,
  1329.                                 const PString & callIdentity)
  1330. {
  1331.   currentInvokeId = dispatcher.GetNextInvokeId();
  1332.  
  1333.   // Send a FACILITY message with a callTransferInitiate Invoke
  1334.   // Supplementary Service PDU to the transferred endpoint.
  1335.   H450ServiceAPDU serviceAPDU;
  1336.  
  1337.   PString alias;
  1338.   H323TransportAddress address;
  1339.   endpoint.ParsePartyName(remoteParty, alias, address);
  1340.  
  1341.   serviceAPDU.BuildCallTransferInitiate(currentInvokeId, callIdentity, alias, address);
  1342.   serviceAPDU.WriteFacilityPDU(connection);
  1343.  
  1344.   ctState = e_ctAwaitInitiateResponse;
  1345.  
  1346.   // start timer CT-T3
  1347.   PTRACE(4, "H4502\tStarting timer CT-T3");
  1348.   StartctTimer(connection.GetEndPoint().GetCallTransferT3());
  1349. }
  1350.  
  1351.  
  1352. void H4502Handler::ConsultationTransfer(const PString & primaryCallToken)
  1353. {
  1354.   currentInvokeId = dispatcher.GetNextInvokeId();
  1355.  
  1356.   // Store the call token of the primary call on the secondary call.
  1357.   SetAssociatedCallToken(primaryCallToken);
  1358.  
  1359.   // Send a FACILITY message with a callTransferIdentify Invoke
  1360.   // Supplementary Service PDU to the transferred-to endpoint.
  1361.   H450ServiceAPDU serviceAPDU;
  1362.  
  1363.   serviceAPDU.BuildCallTransferIdentify(currentInvokeId);
  1364.   serviceAPDU.WriteFacilityPDU(connection);
  1365.  
  1366.   ctState = e_ctAwaitIdentifyResponse;
  1367.  
  1368.   // start timer CT-T1
  1369.   PTRACE(4, "H4502\tStarting timer CT-T1");
  1370.   StartctTimer(endpoint.GetCallTransferT1());
  1371. }
  1372.  
  1373.  
  1374. void H4502Handler::HandleConsultationTransfer(const PString & callIdentity,
  1375.                                               H323Connection& incoming)
  1376. {
  1377.   switch (ctState) {
  1378.     case e_ctAwaitSetup:
  1379.       {
  1380.         // Remove this callIdentity, connection pair from our dictionary as we no longer need it
  1381.         endpoint.GetCallIdentityDictionary().DisallowDeleteObjects();
  1382.         endpoint.GetCallIdentityDictionary().RemoveAt(callIdentity);
  1383.  
  1384.         // Stop timer CT-T2
  1385.         StopctTimer();
  1386.         PTRACE(4, "H4502\tStopping timer CT-T2");
  1387.  
  1388.         PTRACE(4, "H450.2\tConsultation Transfer successful, clearing secondary call");
  1389.  
  1390.         incoming.OnConsultationTransferSuccess(connection);
  1391.  
  1392.         currentInvokeId = 0;
  1393.         ctState = e_ctIdle;
  1394.  
  1395.         endpoint.ClearCall(connection.GetCallToken());
  1396.       }
  1397.       break;
  1398.  
  1399.     // Wrong Call Transfer State
  1400.     default :
  1401.       break;
  1402.  
  1403.   }
  1404. }
  1405.  
  1406.  
  1407. void H4502Handler::AwaitSetupResponse(const PString & token,
  1408.                                       const PString & identity)
  1409. {
  1410.   transferringCallToken = token;
  1411.   transferringCallIdentity = identity;
  1412.   ctState = e_ctAwaitSetupResponse;
  1413.  
  1414.   // start timer CT-T4
  1415.   PTRACE(4, "H450.2\tStarting timer CT-T4");
  1416.   StartctTimer(connection.GetEndPoint().GetCallTransferT4());
  1417. }
  1418.  
  1419.  
  1420. void H4502Handler::onReceivedAdmissionReject(const int returnError)
  1421. {
  1422.   if (ctState == e_ctAwaitSetupResponse) {
  1423.     ctState = e_ctIdle;
  1424.  
  1425.     // Stop timer CT-T4 if it is running
  1426.     StopctTimer();
  1427.     PTRACE(3, "H4502\tStopping timer CT-T4");
  1428.  
  1429.     // Send a FACILITY message back to the transferring party on the primary connection
  1430.     H323Connection * primaryConnection = endpoint.FindConnectionWithLock(transferringCallToken);
  1431.  
  1432.     if (primaryConnection != NULL) {
  1433.       PTRACE(3, "H4502\tReceived an Admission Reject at the Transferred Endpoint - aborting the transfer.");
  1434.       primaryConnection->HandleCallTransferFailure(returnError);
  1435.       primaryConnection->Unlock();
  1436.     }
  1437.   }
  1438. }
  1439.  
  1440.  
  1441. void H4502Handler::HandleCallTransferFailure(const int returnError)
  1442. {
  1443.   SendReturnError(returnError);
  1444. }
  1445.  
  1446.  
  1447. void H4502Handler::StopctTimer()
  1448. {
  1449.   if (ctTimer.IsRunning())
  1450.     ctTimer.Stop();
  1451. }
  1452.  
  1453.  
  1454. void H4502Handler::OnCallTransferTimeOut(PTimer &, INT)
  1455. {
  1456.   switch (ctState) {
  1457.     // CT-T3 Timeout
  1458.     case e_ctAwaitInitiateResponse:
  1459.       OnReceivedInitiateReturnError(true);
  1460.       break;
  1461.  
  1462.     // CT-T1 Timeout
  1463.     case e_ctAwaitIdentifyResponse:
  1464.       OnReceivedIdentifyReturnError(true);
  1465.       break;
  1466.  
  1467.     // CT-T2 Timeout
  1468.     case e_ctAwaitSetup:
  1469.       {
  1470.         // Abort the call transfer
  1471.         ctState = e_ctIdle;
  1472.         currentInvokeId = 0;
  1473.         PTRACE(4, "H450.2\tTimer CT-T2 has expired on the Transferred-to endpoint awaiting a callTransferSetup APDU.");  
  1474.       }
  1475.       break;
  1476.  
  1477.     // CT-T4 Timeout
  1478.     case e_ctAwaitSetupResponse:
  1479.       OnReceivedSetupReturnError(H4502_CallTransferErrors::e_establishmentFailure, true);
  1480.       break;
  1481.  
  1482.     default:
  1483.       break;
  1484.   }
  1485. }
  1486.  
  1487.  
  1488. /////////////////////////////////////////////////////////////////////////////
  1489.  
  1490. H4504Handler::H4504Handler(H323Connection & conn, H450xDispatcher & disp)
  1491.   : H450xHandler(conn, disp)
  1492. {
  1493.   dispatcher.AddOpCode(H4504_CallHoldOperation::e_holdNotific, this);
  1494.   dispatcher.AddOpCode(H4504_CallHoldOperation::e_retrieveNotific, this);
  1495.   dispatcher.AddOpCode(H4504_CallHoldOperation::e_remoteHold, this);
  1496.   dispatcher.AddOpCode(H4504_CallHoldOperation::e_remoteRetrieve, this);
  1497.  
  1498.   holdState = e_ch_Idle;
  1499. }
  1500.  
  1501.  
  1502. BOOL H4504Handler::OnReceivedInvoke(int opcode,
  1503.                                     int invokeId,
  1504.                                     int linkedId,
  1505.                                     PASN_OctetString *)
  1506. {
  1507.   currentInvokeId = invokeId;
  1508.  
  1509.   switch (opcode) {
  1510.     case H4504_CallHoldOperation::e_holdNotific:
  1511.       OnReceivedLocalCallHold(linkedId);
  1512.       break;
  1513.  
  1514.     case H4504_CallHoldOperation::e_retrieveNotific:
  1515.       OnReceivedLocalCallRetrieve(linkedId);
  1516.       break;
  1517.  
  1518.     case H4504_CallHoldOperation::e_remoteHold:
  1519.       OnReceivedRemoteCallHold(linkedId);
  1520.       break;
  1521.  
  1522.     case H4504_CallHoldOperation::e_remoteRetrieve:
  1523.       OnReceivedRemoteCallRetrieve(linkedId);
  1524.       break;
  1525.  
  1526.     default:
  1527.       currentInvokeId = 0;
  1528.       return FALSE;
  1529.   }
  1530.  
  1531.   return TRUE;
  1532. }
  1533.  
  1534.  
  1535. void H4504Handler::OnReceivedLocalCallHold(int /*linkedId*/)
  1536. {
  1537.   PTRACE(4, "H4504\tReceived a holdNotific Invoke APDU from the remote endpoint.");  
  1538.   // Optionally close our transmit channel.
  1539. }
  1540.  
  1541.  
  1542. void H4504Handler::OnReceivedLocalCallRetrieve(int /*linkedId*/)
  1543. {
  1544.   PTRACE(4, "H4504\tReceived a retrieveNotific Invoke APDU from the remote endpoint.");
  1545.   // Re-open our transmit channel if we previously closed it.
  1546. }
  1547.  
  1548.  
  1549. void H4504Handler::OnReceivedRemoteCallHold(int /*linkedId*/)
  1550. {
  1551.     // TBD
  1552. }
  1553.  
  1554.  
  1555. void H4504Handler::OnReceivedRemoteCallRetrieve(int /*linkedId*/)
  1556. {
  1557.     // TBD
  1558. }
  1559.  
  1560.  
  1561. void H4504Handler::HoldCall(BOOL localHold)
  1562. {
  1563.   // TBD: Implement Remote Hold. This implementation only does 
  1564.   // local hold. -- dcassel 4/01. 
  1565.   if (!localHold)
  1566.     return;
  1567.   
  1568.   // Send a FACILITY message with a callNotific Invoke
  1569.   // Supplementary Service PDU to the held endpoint.
  1570.   PTRACE(4, "H4504\tTransmitting a holdNotific Invoke APDU to the remote endpoint.");
  1571.  
  1572.   H450ServiceAPDU serviceAPDU;
  1573.  
  1574.   currentInvokeId = dispatcher.GetNextInvokeId();
  1575.   serviceAPDU.BuildInvoke(currentInvokeId, H4504_CallHoldOperation::e_holdNotific);
  1576.   serviceAPDU.WriteFacilityPDU(connection);
  1577.   
  1578.   // Update hold state
  1579.   holdState = e_ch_NE_Held;
  1580. }
  1581.  
  1582.  
  1583. void H4504Handler::RetrieveCall()
  1584. {
  1585.   // TBD: Implement Remote Hold. This implementation only does
  1586.  
  1587.   // Send a FACILITY message with a retrieveNotific Invoke
  1588.   // Supplementary Service PDU to the held endpoint.
  1589.   PTRACE(4, "H4504\tTransmitting a retrieveNotific Invoke APDU to the remote endpoint.");
  1590.  
  1591.   H450ServiceAPDU serviceAPDU;
  1592.  
  1593.   currentInvokeId = dispatcher.GetNextInvokeId();
  1594.   serviceAPDU.BuildInvoke(currentInvokeId, H4504_CallHoldOperation::e_retrieveNotific);
  1595.   serviceAPDU.WriteFacilityPDU(connection);
  1596.   
  1597.   // Update hold state
  1598.   holdState = e_ch_Idle;
  1599. }
  1600.  
  1601.  
  1602. /////////////////////////////////////////////////////////////////////////////
  1603.  
  1604. H4506Handler::H4506Handler(H323Connection & conn, H450xDispatcher & disp)
  1605.   : H450xHandler(conn, disp)
  1606. {
  1607.   dispatcher.AddOpCode(H4506_CallWaitingOperations::e_callWaiting, this);
  1608.  
  1609.   cwState = e_cw_Idle;
  1610. }
  1611.  
  1612.  
  1613. BOOL H4506Handler::OnReceivedInvoke(int opcode,
  1614.                                     int invokeId,
  1615.                                     int linkedId,
  1616.                                     PASN_OctetString *argument)
  1617. {
  1618.   currentInvokeId = invokeId;
  1619.  
  1620.   switch (opcode) {
  1621.     case H4506_CallWaitingOperations::e_callWaiting:
  1622.       OnReceivedCallWaitingIndication(linkedId, argument);
  1623.       break;
  1624.  
  1625.     default:
  1626.       currentInvokeId = 0;
  1627.       return FALSE;
  1628.   }
  1629.  
  1630.   return TRUE;
  1631. }
  1632.  
  1633.  
  1634. void H4506Handler::OnReceivedCallWaitingIndication(int /*linkedId*/,
  1635.                                                    PASN_OctetString *argument)
  1636. {
  1637.   H4506_CallWaitingArg cwArg;
  1638.  
  1639.   if(!DecodeArguments(argument, cwArg, -1))
  1640.     return;
  1641.  
  1642.   connection.SetRemotCallWaiting(cwArg.m_nbOfAddWaitingCalls.GetValue());
  1643.   return;
  1644. }
  1645.  
  1646.  
  1647. void H4506Handler::AttachToAlerting(H323SignalPDU & pdu,
  1648.                                     unsigned numberOfCallsWaiting)
  1649. {
  1650.   PTRACE(4, "H450.6\tAttaching a Call Waiting Invoke PDU to this Alerting message.");
  1651.   
  1652.   H450ServiceAPDU serviceAPDU;
  1653.  
  1654.   // Store the call waiting invokeID associated with this connection
  1655.   currentInvokeId = dispatcher.GetNextInvokeId();
  1656.  
  1657.   serviceAPDU.BuildCallWaiting(currentInvokeId, numberOfCallsWaiting);
  1658.   serviceAPDU.AttachSupplementaryServiceAPDU(pdu);
  1659.  
  1660.   cwState = e_cw_Invoked;
  1661. }
  1662.  
  1663.  
  1664. /////////////////////////////////////////////////////////////////////////////
  1665.  
  1666. H45011Handler::H45011Handler(H323Connection & conn, H450xDispatcher & disp)
  1667.   : H450xHandler(conn, disp)
  1668. {
  1669.   dispatcher.AddOpCode(H45011_H323CallIntrusionOperations::e_callIntrusionRequest, this);
  1670.   dispatcher.AddOpCode(H45011_H323CallIntrusionOperations::e_callIntrusionGetCIPL, this);
  1671.   dispatcher.AddOpCode(H45011_H323CallIntrusionOperations::e_callIntrusionIsolate, this);
  1672.   dispatcher.AddOpCode(H45011_H323CallIntrusionOperations::e_callIntrusionForcedRelease, this);
  1673.   dispatcher.AddOpCode(H45011_H323CallIntrusionOperations::e_callIntrusionWOBRequest, this);
  1674.   dispatcher.AddOpCode(H45011_H323CallIntrusionOperations::e_callIntrusionSilentMonitor, this);
  1675.   dispatcher.AddOpCode(H45011_H323CallIntrusionOperations::e_callIntrusionNotification, this);
  1676.  
  1677.   dispatcher.AddOpCode(H45010_H323CallOfferOperations::e_cfbOverride, this);
  1678.   dispatcher.AddOpCode(H45010_H323CallOfferOperations::e_remoteUserAlerting, this);
  1679.  
  1680.   dispatcher.AddOpCode(H4506_CallWaitingOperations::e_callWaiting, this);
  1681.  
  1682.   ciState = e_ci_Idle;
  1683.   ciSendState = e_ci_sIdle;
  1684.   ciReturnState = e_ci_rIdle;
  1685.   ciTimer.SetNotifier(PCREATE_NOTIFIER(OnCallIntrudeTimeOut));
  1686. }
  1687.  
  1688.  
  1689. BOOL H45011Handler::OnReceivedInvoke(int opcode,
  1690.                                     int invokeId,
  1691.                                     int linkedId,
  1692.                                     PASN_OctetString * argument)
  1693. {
  1694.   BOOL result = TRUE;
  1695.   currentInvokeId = invokeId;
  1696.  
  1697.   switch (opcode) {
  1698.     case H45011_H323CallIntrusionOperations::e_callIntrusionRequest:
  1699.       OnReceivedCallIntrusionRequest(linkedId, argument);
  1700.       break;
  1701.  
  1702.     case H45011_H323CallIntrusionOperations::e_callIntrusionGetCIPL:
  1703.       OnReceivedCallIntrusionGetCIPL(linkedId, argument);
  1704.       break;
  1705.  
  1706.     case H45011_H323CallIntrusionOperations::e_callIntrusionIsolate:
  1707.       OnReceivedCallIntrusionIsolate(linkedId, argument);
  1708.       break;
  1709.  
  1710.     case H45011_H323CallIntrusionOperations::e_callIntrusionForcedRelease:
  1711.       result = OnReceivedCallIntrusionForcedRelease(linkedId, argument);
  1712.       break;
  1713.  
  1714.     case H45011_H323CallIntrusionOperations::e_callIntrusionWOBRequest:
  1715.       OnReceivedCallIntrusionWOBRequest(linkedId, argument);
  1716.       break;
  1717.  
  1718.     case H45011_H323CallIntrusionOperations::e_callIntrusionSilentMonitor:
  1719.       OnReceivedCallIntrusionSilentMonitor(linkedId, argument);
  1720.       break;
  1721.  
  1722.     case H45011_H323CallIntrusionOperations::e_callIntrusionNotification:
  1723.       OnReceivedCallIntrusionNotification(linkedId, argument);
  1724.       break;
  1725.  
  1726.     case H45010_H323CallOfferOperations::e_cfbOverride:
  1727.       OnReceivedCfbOverride(linkedId, argument);
  1728.       break;
  1729.  
  1730.     case H45010_H323CallOfferOperations::e_remoteUserAlerting:
  1731.       OnReceivedRemoteUserAlerting(linkedId, argument);
  1732.       break;
  1733.  
  1734.     case H4506_CallWaitingOperations::e_callWaiting:
  1735.       OnReceivedCallWaiting(linkedId, argument);
  1736.       break;
  1737.     
  1738.     default:
  1739.       currentInvokeId = 0;
  1740.       return FALSE;
  1741.   }
  1742.  
  1743.   return result;
  1744. }
  1745.  
  1746.  
  1747. void H45011Handler::AttachToSetup(H323SignalPDU & pdu)
  1748. {
  1749.   // Do we need to attach a call transfer setup invoke APDU?
  1750.   if (ciSendState != e_ci_sAttachToSetup)
  1751.     return;
  1752.  
  1753.   H450ServiceAPDU serviceAPDU;
  1754.  
  1755.   // Store the outstanding invokeID associated with this connection
  1756.   currentInvokeId = dispatcher.GetNextInvokeId();
  1757.   PTRACE(4, "H450.11\tAttachToSetup Invoke ID=" << currentInvokeId);
  1758.  
  1759.   switch (ciGenerateState){
  1760.     case e_ci_gConferenceRequest:
  1761.       break;
  1762.     case e_ci_gHeldRequest:
  1763.       break;
  1764.     case e_ci_gSilentMonitorRequest:
  1765.       break;
  1766.     case e_ci_gIsolationRequest:
  1767.       break;
  1768.     case e_ci_gForcedReleaseRequest:
  1769.       serviceAPDU.BuildCallIntrusionForcedRelease(currentInvokeId, ciCICL);
  1770.       break;
  1771.     case e_ci_gWOBRequest:
  1772.       break;
  1773.     default:
  1774.       break;
  1775.   }
  1776.   
  1777.   if(ciGenerateState != e_ci_gIdle){
  1778.     // Use the call identity from the ctInitiateArg
  1779.     serviceAPDU.AttachSupplementaryServiceAPDU(pdu);
  1780.     // start timer CT-T1
  1781.     PTRACE(4, "H450.11\tStarting timer CI-T1");
  1782.     StartciTimer(connection.GetEndPoint().GetCallIntrusionT1());
  1783.     ciState = e_ci_WaitAck;
  1784.   }
  1785.  
  1786.   ciSendState = e_ci_sIdle;
  1787.   ciGenerateState = e_ci_gIdle;
  1788. }
  1789.  
  1790.  
  1791. void H45011Handler::AttachToAlerting(H323SignalPDU & pdu)
  1792. {
  1793.   if (ciSendState != e_ci_sAttachToAlerting)
  1794.     return;
  1795.  
  1796.   PTRACE(4, "H450.11\tAttachToAlerting Invoke ID=" << currentInvokeId);
  1797.  
  1798.   // Store the outstanding invokeID associated with this connection
  1799.   currentInvokeId = dispatcher.GetNextInvokeId();
  1800.   PTRACE(4, "H450.11\tAttachToAlerting Invoke ID=" << currentInvokeId);
  1801.   if(ciReturnState!=e_ci_rIdle){
  1802.     H450ServiceAPDU serviceAPDU;
  1803.     switch (ciReturnState){
  1804.       case e_ci_rCallIntrusionImpending:
  1805.         serviceAPDU.BuildCallIntrusionImpending(currentInvokeId);
  1806.         PTRACE(4, "H450.11\tReturned e_ci_rCallIntrusionImpending");
  1807.         break;
  1808.       case e_ci_rCallIntruded:
  1809.         break;
  1810.       case e_ci_rCallIsolated:
  1811.         break;
  1812.       case e_ci_rCallForceReleased:
  1813.         break;
  1814.       case e_ci_rCallForceReleaseResult:
  1815.         serviceAPDU.BuildCallIntrusionForcedReleaseResult(currentInvokeId);
  1816.         PTRACE(4, "H450.11\tReturned H45011_CallIntrusionForced Release Result");
  1817.         break;
  1818.       case e_ci_rCallIntrusionComplete:
  1819.         break;
  1820.       case e_ci_rCallIntrusionEnd:
  1821.         break;
  1822.       case e_ci_rNotBusy:
  1823.         serviceAPDU.BuildReturnError(currentInvokeId, H45011_CallIntrusionErrors::e_notBusy);
  1824.         PTRACE(4, "H450.11\tReturned H45011_CallIntrusionErrors::e_notBusy");
  1825.         break;
  1826.       case e_ci_rTempUnavailable:
  1827.         PTRACE(4, "H450.11\tReturned H45011_CallIntrusionErrors::e_temporarilyUnavailable");
  1828.         serviceAPDU.BuildReturnError(currentInvokeId, H45011_CallIntrusionErrors::e_temporarilyUnavailable);
  1829.         break;
  1830.       case e_ci_rNotAuthorized:
  1831.         PTRACE(4, "H450.11\tReturned H45011_CallIntrusionErrors::e_notAuthorized");
  1832.         serviceAPDU.BuildReturnError(currentInvokeId, H45011_CallIntrusionErrors::e_notAuthorized);
  1833.         break;
  1834.       default :
  1835.         break;
  1836.     }
  1837.     serviceAPDU.AttachSupplementaryServiceAPDU(pdu);
  1838.   }
  1839.  
  1840.   ciState = e_ci_Idle;
  1841.   ciSendState = e_ci_sIdle;
  1842.   ciReturnState = e_ci_rIdle;
  1843. }
  1844.  
  1845.  
  1846. void H45011Handler::AttachToConnect(H323SignalPDU & pdu)
  1847. {
  1848.   if ((currentInvokeId == 0) || (ciSendState != e_ci_sAttachToConnect))
  1849.     return;
  1850.  
  1851.   currentInvokeId = dispatcher.GetNextInvokeId();
  1852.   PTRACE(4, "H450.11\tAttachToConnect Invoke ID=" << currentInvokeId);
  1853.   if(ciReturnState!=e_ci_rIdle){
  1854.     H450ServiceAPDU serviceAPDU;
  1855.     switch (ciReturnState){
  1856.       case e_ci_rCallIntrusionImpending:
  1857.         break;
  1858.       case e_ci_rCallIntruded:
  1859.         break;
  1860.       case e_ci_rCallIsolated:
  1861.         break;
  1862.       case e_ci_rCallForceReleased:
  1863.         break;
  1864.       case e_ci_rCallForceReleaseResult:
  1865.         serviceAPDU.BuildCallIntrusionForcedReleaseResult(currentInvokeId);
  1866.         PTRACE(4, "H450.11\tReturned H45011_CallIntrusionForced Release Result");
  1867.         break;
  1868.       case e_ci_rCallIntrusionComplete:
  1869.         break;
  1870.       case e_ci_rCallIntrusionEnd:
  1871.         break;
  1872.       case e_ci_rNotBusy:
  1873.         serviceAPDU.BuildReturnError(currentInvokeId, H45011_CallIntrusionErrors::e_notBusy);
  1874.         PTRACE(4, "H450.11\tReturned H45011_CallIntrusionErrors::e_notBusy");
  1875.         break;
  1876.       case e_ci_rTempUnavailable:
  1877.         PTRACE(4, "H450.11\tReturned H45011_CallIntrusionErrors::e_temporarilyUnavailable");
  1878.         serviceAPDU.BuildReturnError(currentInvokeId, H45011_CallIntrusionErrors::e_temporarilyUnavailable);
  1879.         break;
  1880.       case e_ci_rNotAuthorized:
  1881.         PTRACE(4, "H450.11\tReturned H45011_CallIntrusionErrors::e_notAuthorized");
  1882.         serviceAPDU.BuildReturnError(currentInvokeId, H45011_CallIntrusionErrors::e_notAuthorized);
  1883.         break;
  1884.       default :
  1885.         break;
  1886.     }
  1887.  
  1888.     serviceAPDU.AttachSupplementaryServiceAPDU(pdu);
  1889.   }
  1890.  
  1891.  
  1892.   ciState = e_ci_Idle;
  1893.   ciSendState = e_ci_sIdle;
  1894.   ciReturnState = e_ci_rIdle;
  1895.   currentInvokeId = 0;
  1896. }
  1897.  
  1898.  
  1899.  
  1900. void H45011Handler::AttachToReleaseComplete(H323SignalPDU & pdu)
  1901. {
  1902.   // Do we need to attach a call transfer setup invoke APDU?
  1903.   if (ciSendState != e_ci_sAttachToReleseComplete)
  1904.     return;
  1905.  
  1906.   PTRACE(4, "H450.11\tAttachToSetup Invoke ID=" << currentInvokeId);
  1907.   if(ciReturnState!=e_ci_rIdle){
  1908.     H450ServiceAPDU serviceAPDU;
  1909.     switch (ciReturnState){
  1910.       case e_ci_rNotBusy:
  1911.         serviceAPDU.BuildReturnError(currentInvokeId, H45011_CallIntrusionErrors::e_notBusy);
  1912.         PTRACE(4, "H450.11\tReturned H45011_CallIntrusionErrors::e_notBusy");
  1913.         break;
  1914.       case e_ci_rTempUnavailable:
  1915.         PTRACE(4, "H450.11\tReturned H45011_CallIntrusionErrors::e_temporarilyUnavailable");
  1916.         serviceAPDU.BuildReturnError(currentInvokeId, H45011_CallIntrusionErrors::e_temporarilyUnavailable);
  1917.         break;
  1918.       case e_ci_rNotAuthorized:
  1919.         PTRACE(4, "H450.11\tReturned H45011_CallIntrusionErrors::e_notAuthorized");
  1920.         serviceAPDU.BuildReturnError(currentInvokeId, H45011_CallIntrusionErrors::e_notAuthorized);
  1921.         break;
  1922.       case e_ci_rCallForceReleased:
  1923.         PTRACE(4, "H450.11\tReturned H45011_CallIntrusionForceRelease::e_ci_rCallForceReleased");
  1924.         serviceAPDU.BuildCallIntrusionForceRelesed(currentInvokeId);
  1925.         break;
  1926.       default :
  1927.         break;
  1928.     }
  1929.     serviceAPDU.AttachSupplementaryServiceAPDU(pdu);
  1930.   }
  1931.  
  1932.   ciState = e_ci_Idle;
  1933.   ciSendState = e_ci_sIdle;
  1934.   ciReturnState = e_ci_rIdle;
  1935. }
  1936.  
  1937.  
  1938. void H45011Handler::OnReceivedCallIntrusionRequest(int /*linkedId*/,
  1939.                                                    PASN_OctetString *argument)
  1940. {
  1941.  
  1942.   H45011_CIRequestArg ciArg;
  1943.  
  1944.   if(!DecodeArguments(argument, ciArg, -1))
  1945.     return;
  1946. /*
  1947.   TBD
  1948. */
  1949.   return;
  1950. }
  1951.  
  1952.  
  1953. void H45011Handler::OnReceivedCallIntrusionGetCIPL(int /*linkedId*/,
  1954.                                                    PASN_OctetString *argument)
  1955. {
  1956.   PTRACE(4, "H450.11\tReceived GetCIPL Invoke");
  1957.  
  1958.   H45011_CIGetCIPLOptArg ciArg;
  1959.  
  1960.   // !!!!!!!!
  1961.   DecodeArguments(argument, ciArg, -1);
  1962. /*  if(!DecodeArguments(argument, ciArg, -1))
  1963.     return;
  1964. */
  1965.   
  1966.  
  1967.   // Send a FACILITY message with a callTransferIdentify return result
  1968.   // Supplementary Service PDU to the transferring endpoint.
  1969.   H450ServiceAPDU serviceAPDU;
  1970.  
  1971.   X880_ReturnResult& result = serviceAPDU.BuildReturnResult(currentInvokeId);
  1972.   result.IncludeOptionalField(X880_ReturnResult::e_result);
  1973.   result.m_result.m_opcode.SetTag(X880_Code::e_local);
  1974.   PASN_Integer& operation = (PASN_Integer&) result.m_result.m_opcode;
  1975.   operation.SetValue(H45011_H323CallIntrusionOperations::e_callIntrusionGetCIPL);
  1976.  
  1977.   H45011_CIGetCIPLRes ciCIPLRes;
  1978.  
  1979.   ciCIPLRes.m_ciProtectionLevel = endpoint.GetCallIntrusionProtectionLevel();
  1980.   ciCIPLRes.IncludeOptionalField(H45011_CIGetCIPLRes::e_silentMonitoringPermitted);
  1981.   ciCIPLRes.m_silentMonitoringPermitted = FALSE;
  1982.  
  1983.   PPER_Stream resultStream;
  1984.   ciCIPLRes.Encode(resultStream);
  1985.   resultStream.CompleteEncoding();
  1986.   result.m_result.m_result.SetValue(resultStream);
  1987.  
  1988.   serviceAPDU.WriteFacilityPDU(connection);
  1989.   PTRACE(4, "H450.11\tSent GetCIPL Result CIPL=" << ciCIPLRes.m_ciProtectionLevel);
  1990. /*
  1991.   TBD
  1992. */
  1993.   return;
  1994. }
  1995.  
  1996.  
  1997. void H45011Handler::OnReceivedCallIntrusionIsolate(int /*linkedId*/,
  1998.                                                    PASN_OctetString *argument)
  1999. {
  2000.  
  2001.   H45011_CIIsOptArg ciArg;
  2002.  
  2003.   if(!DecodeArguments(argument, ciArg, -1))
  2004.     return;
  2005. /*
  2006.   TBD
  2007. */
  2008.   return;
  2009. }
  2010.  
  2011.  
  2012. BOOL H45011Handler::OnReceivedCallIntrusionForcedRelease(int /*linkedId*/,
  2013.                                                          PASN_OctetString *argument)
  2014. {
  2015.   BOOL result = TRUE;
  2016.   PTRACE(4, "H450.11\tReceived ForcedRelease Invoke");
  2017.  
  2018.   H45011_CIFrcRelArg ciArg;
  2019.  
  2020.   if(!DecodeArguments(argument, ciArg, -1))
  2021.     return FALSE;
  2022.  
  2023.   PStringList tokens = endpoint.GetAllConnections();
  2024.  
  2025.   if(tokens.GetSize() >1) {
  2026.     for (PINDEX i = 0; i < tokens.GetSize(); i++) {
  2027.       if(endpoint.HasConnection(tokens[i])){
  2028.         H323Connection* conn = endpoint.FindConnectionWithLock(tokens[i]);
  2029.         if (conn != NULL){
  2030.           if (conn->IsEstablished()){
  2031.             if((conn->GetLocalCallIntrusionProtectionLevel() < ciArg.m_ciCapabilityLevel)){
  2032.               activeCallToken = conn->GetCallToken();
  2033.               intrudingCallToken = connection.GetCallToken();
  2034.               conn->GetRemoteCallIntrusionProtectionLevel(connection.GetCallToken (), (unsigned)ciArg.m_ciCapabilityLevel);
  2035.               result = TRUE;
  2036.               conn->Unlock ();
  2037.               break;
  2038.             }
  2039.             else
  2040.               result = FALSE;
  2041.           }
  2042.           conn->Unlock ();
  2043.         }
  2044.       }
  2045.     }
  2046.     if(result){
  2047.       ciSendState = e_ci_sAttachToConnect;
  2048.       ciReturnState = e_ci_rCallForceReleaseResult;
  2049.       connection.SetCallIntrusion ();
  2050.     }
  2051.     else {
  2052.       ciSendState = e_ci_sAttachToReleseComplete;
  2053.       ciReturnState = e_ci_rNotAuthorized;
  2054.       connection.ClearCall(H323Connection::EndedByLocalBusy);
  2055.     }
  2056.   }
  2057.   else{
  2058.     ciSendState = e_ci_sAttachToAlerting;
  2059.     ciReturnState = e_ci_rNotBusy;
  2060.   }
  2061.  
  2062.   return result;
  2063. }
  2064.  
  2065.  
  2066. void H45011Handler::OnReceivedCallIntrusionWOBRequest(int /*linkedId*/,
  2067.                                                       PASN_OctetString *argument)
  2068. {
  2069.  
  2070.   H45011_CIWobOptArg ciArg;
  2071.  
  2072.   if(!DecodeArguments(argument, ciArg, -1))
  2073.     return;
  2074. /*
  2075.   TBD
  2076. */
  2077.   return;
  2078. }
  2079.  
  2080.  
  2081. void H45011Handler::OnReceivedCallIntrusionSilentMonitor(int /*linkedId*/,
  2082.                                                          PASN_OctetString *argument)
  2083. {
  2084.  
  2085.   H45011_CISilentArg ciArg;
  2086.  
  2087.   if(!DecodeArguments(argument, ciArg, -1))
  2088.     return;
  2089. /*
  2090.   TBD
  2091. */
  2092.   return;
  2093. }
  2094.  
  2095.  
  2096. void H45011Handler::OnReceivedCallIntrusionNotification(int /*linkedId*/,
  2097.                                                         PASN_OctetString *argument)
  2098. {
  2099.  
  2100.   H45011_CINotificationArg ciArg;
  2101.  
  2102.   if(!DecodeArguments(argument, ciArg, -1))
  2103.     return;
  2104. /*
  2105.   TBD
  2106. */
  2107.   return;
  2108. }
  2109.  
  2110.  
  2111. void H45011Handler::OnReceivedCfbOverride(int /*linkedId*/,
  2112.                                           PASN_OctetString *argument)
  2113. {
  2114.  
  2115.   H45010_CfbOvrOptArg ciArg;
  2116.  
  2117.   if(!DecodeArguments(argument, ciArg, -1))
  2118.     return;
  2119. /*
  2120.   TBD
  2121. */
  2122.   return;
  2123. }
  2124.  
  2125.  
  2126. void H45011Handler::OnReceivedRemoteUserAlerting(int /*linkedId*/,
  2127.                                                  PASN_OctetString *argument)
  2128. {
  2129.  
  2130.   H45010_RUAlertOptArg ciArg;
  2131.  
  2132.   if(!DecodeArguments(argument, ciArg, -1))
  2133.     return;
  2134. /*
  2135.   TBD
  2136. */
  2137.   return;
  2138. }
  2139.  
  2140.  
  2141. void H45011Handler::OnReceivedCallWaiting(int /*linkedId*/,
  2142.                                           PASN_OctetString *argument)
  2143. {
  2144.  
  2145.   H4506_CallWaitingArg ciArg;
  2146.  
  2147.   if(!DecodeArguments(argument, ciArg, -1))
  2148.     return;
  2149. /*
  2150.   TBD
  2151. */
  2152.   return;
  2153. }
  2154.  
  2155.  
  2156. BOOL H45011Handler::OnReceivedReturnResult(X880_ReturnResult & returnResult)
  2157. {
  2158.   PTRACE(4, "H450.11\tReceived Return Result");
  2159.   if (currentInvokeId == returnResult.m_invokeId.GetValue()) {
  2160.     PTRACE(4, "H450.11\tReceived Return Result Invoke ID=" << currentInvokeId);
  2161.     switch (ciState) {
  2162.       case e_ci_WaitAck:
  2163.         OnReceivedCIRequestResult(); 
  2164.         break;
  2165.       case e_ci_GetCIPL:
  2166.         OnReceivedCIGetCIPLResult(returnResult); 
  2167.         break;
  2168.       default :
  2169.         break;
  2170.     }
  2171.   }
  2172.   return TRUE;
  2173. }
  2174.  
  2175.  
  2176. void H45011Handler::OnReceivedCIRequestResult()
  2177. {
  2178.   PTRACE(4, "H450.11\tOnReceivedCIRequestResult");
  2179.   // stop timer CI-T1
  2180.   PTRACE(4, "H450.11\tTrying to stop timer CI-T1");
  2181.   StopciTimer();
  2182. }
  2183.  
  2184.  
  2185. void H45011Handler::OnReceivedCIGetCIPLResult(X880_ReturnResult & returnResult)
  2186. {
  2187.   PTRACE(4, "H450.11\tOnReceivedCIRequestResult");
  2188.   // Get the return result if present
  2189.   PASN_OctetString * result = NULL;
  2190.   if (returnResult.HasOptionalField(X880_ReturnResult::e_result)) {
  2191.     result = &returnResult.m_result.m_result;
  2192.  
  2193.     // Extract the C Party Details
  2194.     H45011_CIGetCIPLRes ciGetCIPLResult;
  2195.  
  2196.     PPER_Stream resultStream(*result);
  2197.     ciGetCIPLResult.Decode(resultStream);
  2198.  
  2199.     PTRACE(4 ,"H450.11\tReceived CIPL=" << ciGetCIPLResult.m_ciProtectionLevel );
  2200.  
  2201.     if (intrudingCallCICL > ciGetCIPLResult.m_ciProtectionLevel){
  2202.  
  2203.       // Send ciNotification.inv (ciImpending) To C
  2204.       connection.Lock();
  2205.       H450ServiceAPDU serviceAPDU;
  2206.       currentInvokeId = dispatcher.GetNextInvokeId();
  2207.       serviceAPDU.BuildCallIntrusionImpending(currentInvokeId);
  2208.       serviceAPDU.WriteFacilityPDU(connection);
  2209.       connection.Unlock();
  2210.  
  2211.       // Send ciNotification.inv (ciImpending) to  intruding (A)
  2212.       H323Connection* conn = endpoint.FindConnectionWithLock(intrudingCallToken);
  2213.       conn->SetIntrusionImpending ();
  2214.  
  2215.       //Send Ringing to intruding (A)
  2216.       conn->AnsweringCall (conn->AnswerCallPending);
  2217.  
  2218.       // MUST RETURN ciNotification.inv (callForceRelesed) to active call (C) when releasing call !!!!!!
  2219.       ciSendState = e_ci_sAttachToReleseComplete;
  2220.       ciReturnState = e_ci_rCallForceReleased;
  2221.       
  2222.       //Send Forced Release Accepted when Answering call to intruding (A)
  2223.       conn->SetForcedReleaseAccepted();
  2224.       conn->Unlock ();
  2225.     }
  2226.     else {
  2227.       PTRACE(4 ,"H450.11\tCICL<CIPL -> Clear Call");
  2228.       // Clear Call with intruding (A)
  2229.       H323Connection* conn = endpoint.FindConnectionWithLock(intrudingCallToken);
  2230.       conn->SetIntrusionNotAuthorized();
  2231.       endpoint.ClearCall (intrudingCallToken);
  2232.     }
  2233.   }
  2234.  
  2235.   // stop timer CI-T5
  2236.   PTRACE(4, "H450.11\tTrying to stop timer CI-T5");
  2237.   StopciTimer();
  2238. }
  2239.  
  2240.  
  2241. BOOL H45011Handler::OnReceivedReturnError(int errorCode, X880_ReturnError &returnError)
  2242. {
  2243.   BOOL result = TRUE;
  2244.   PTRACE(4, "H450.11\tReceived Return Error CODE=" <<errorCode << ", InvokeId=" <<returnError.m_invokeId.GetValue());
  2245.   if (currentInvokeId == returnError.m_invokeId.GetValue()) {
  2246.     switch (ciState) {
  2247.       case e_ci_WaitAck:
  2248.         result = OnReceivedInvokeReturnError(errorCode);
  2249.         break;
  2250.       case e_ci_GetCIPL:
  2251.         result = OnReceivedGetCIPLReturnError(errorCode);
  2252.         break;
  2253.       default :
  2254.         break;
  2255.     }
  2256.   }
  2257.   return result;
  2258. }
  2259.  
  2260.  
  2261. BOOL H45011Handler::OnReceivedInvokeReturnError(int errorCode, const bool timerExpiry)
  2262. {
  2263.   BOOL result = FALSE;
  2264.   PTRACE(4, "H450.11\tOnReceivedInvokeReturnError CODE =" << errorCode);
  2265.   if (!timerExpiry) {
  2266.     // stop timer CI-T1
  2267.     StopciTimer();
  2268.     PTRACE(4, "H450.11\tStopping timer CI-T1");
  2269.   }
  2270.   else
  2271.     PTRACE(4, "H450.11\tTimer CI-T1 has expired awaiting a response to a callIntrusionInvoke return result.");
  2272.  
  2273.   currentInvokeId = 0;
  2274.   ciState = e_ci_Idle;
  2275.   ciSendState = e_ci_sIdle;
  2276.  
  2277.   switch(errorCode){
  2278.     case H45011_CallIntrusionErrors::e_notBusy :
  2279.       PTRACE(4, "H450.11\tH45011_CallIntrusionErrors::e_notBusy");
  2280.       result = TRUE;
  2281.       break;
  2282.     case H45011_CallIntrusionErrors::e_temporarilyUnavailable :
  2283.       PTRACE(4, "H450.11\tH45011_CallIntrusionErrors::e_temporarilyUnavailable");
  2284.       break;
  2285.     case H45011_CallIntrusionErrors::e_notAuthorized :
  2286.       PTRACE(4, "H450.11\tH45011_CallIntrusionErrors::e_notAuthorized");
  2287.       result = TRUE;
  2288.       break;
  2289.     default:
  2290.       PTRACE(4, "H450.11\tH45011_CallIntrusionErrors::DEFAULT");
  2291.       break;
  2292.   }
  2293.   return result;
  2294. }
  2295.  
  2296.  
  2297. #if PTRACING
  2298. #define PTRACE_errorCode errorCode
  2299. #else
  2300. #define PTRACE_errorCode
  2301. #endif
  2302.  
  2303. BOOL H45011Handler::OnReceivedGetCIPLReturnError(int PTRACE_errorCode,
  2304.                                                  const bool timerExpiry)
  2305. {
  2306.   PTRACE(4, "H450.11\tOnReceivedGetCIPLReturnError ErrorCode=" << PTRACE_errorCode);
  2307.   if(!timerExpiry){
  2308.     if (ciTimer.IsRunning()){
  2309.       ciTimer.Stop();
  2310.       PTRACE(4, "H450.11\tStopping timer CI-TX");
  2311.     }
  2312.   }
  2313.  
  2314.   // Send ciNotification.inv (ciImpending) to active call (C)
  2315.   connection.Lock();
  2316.   H450ServiceAPDU serviceAPDU;
  2317.   currentInvokeId = dispatcher.GetNextInvokeId();
  2318.   serviceAPDU.BuildCallIntrusionImpending(currentInvokeId);
  2319.   serviceAPDU.WriteFacilityPDU(connection);
  2320.   connection.Unlock();
  2321.  
  2322.   // Send ciNotification.inv (ciImpending) to intruding (A)
  2323.   H323Connection* conn = endpoint.FindConnectionWithLock(intrudingCallToken);
  2324.   conn->SetIntrusionImpending ();
  2325.  
  2326.   //Send Ringing to intruding (A)
  2327.   conn->AnsweringCall (conn->AnswerCallPending);
  2328.  
  2329.   ciSendState = e_ci_sAttachToReleseComplete;
  2330.   ciReturnState = e_ci_rCallForceReleased;
  2331.       
  2332.   //Forced Release Accepted to send when Answering call to intruding (A)
  2333.   conn->SetForcedReleaseAccepted();
  2334.   conn->Unlock ();
  2335.  
  2336.   return FALSE;
  2337. }
  2338.  
  2339.  
  2340. void H45011Handler::IntrudeCall(int CICL)
  2341. {
  2342.   ciSendState = e_ci_sAttachToSetup;
  2343.   ciGenerateState = e_ci_gForcedReleaseRequest;
  2344.   ciCICL = CICL;
  2345. }
  2346.  
  2347.  
  2348. void H45011Handler::AwaitSetupResponse(const PString & token,
  2349.                                       const PString & identity)
  2350. {
  2351.   intrudingCallToken = token;
  2352.   intrudingCallIdentity = identity;
  2353.   ciState = e_ci_WaitAck;
  2354.  
  2355. }
  2356.  
  2357.  
  2358. BOOL H45011Handler::GetRemoteCallIntrusionProtectionLevel(const PString & token,
  2359.                                                           unsigned intrusionCICL)
  2360. {
  2361.   if (!connection.Lock())
  2362.     return FALSE;
  2363.  
  2364.   intrudingCallToken = token;
  2365.   intrudingCallCICL = intrusionCICL;
  2366.  
  2367.   H450ServiceAPDU serviceAPDU;
  2368.  
  2369.   currentInvokeId = dispatcher.GetNextInvokeId();
  2370.  
  2371.   serviceAPDU.BuildCallIntrusionGetCIPL(currentInvokeId);
  2372.  
  2373.   connection.Unlock();
  2374.  
  2375.   if (!serviceAPDU.WriteFacilityPDU(connection))
  2376.     return FALSE;
  2377.  
  2378.   PTRACE(4, "H450.11\tStarting timer CI-T5");
  2379.   StartciTimer(connection.GetEndPoint().GetCallIntrusionT5());
  2380.   ciState = e_ci_GetCIPL;
  2381.   return TRUE;
  2382. }
  2383.  
  2384.  
  2385. void H45011Handler::SetIntrusionNotAuthorized()
  2386. {
  2387.   ciSendState = e_ci_sAttachToReleseComplete;
  2388.   ciReturnState = e_ci_rNotAuthorized;
  2389. }
  2390.  
  2391.  
  2392. void H45011Handler::SetIntrusionImpending()
  2393. {
  2394.   ciSendState = e_ci_sAttachToAlerting;
  2395.   ciReturnState = e_ci_rCallIntrusionImpending;
  2396. }
  2397.  
  2398.  
  2399. void H45011Handler::SetForcedReleaseAccepted()
  2400. {
  2401.   ciSendState = e_ci_sAttachToConnect;
  2402.   ciReturnState = e_ci_rCallForceReleaseResult;
  2403.   ciState = e_ci_DestNotify;
  2404.  
  2405.   StartciTimer(connection.GetEndPoint().GetCallIntrusionT6());
  2406. }
  2407.  
  2408.  
  2409. void H45011Handler::StopciTimer()
  2410. {
  2411.   if (ciTimer.IsRunning()){
  2412.     ciTimer.Stop();
  2413.     PTRACE(4, "H450.11\tStopping timer CI-TX");
  2414.   }
  2415. }
  2416.  
  2417.  
  2418. void H45011Handler::OnCallIntrudeTimeOut(PTimer &, INT)
  2419. {
  2420.   switch (ciState) {
  2421.     // CI-T1 Timeout
  2422.     case e_ci_WaitAck:
  2423.       PTRACE(4, "H450.11\tTimer CI-T1 has expired");
  2424.       OnReceivedInvokeReturnError(0,true);
  2425.       break;
  2426.     case e_ci_GetCIPL:
  2427.       PTRACE(4, "H450.11\tTimer CI-T5 has expired");
  2428.       OnReceivedGetCIPLReturnError(0,true);
  2429.       break;
  2430.     case e_ci_DestNotify:
  2431.       {
  2432.         PTRACE(4, "H450.11\tOnCallIntrudeTimeOut Timer CI-T6 has expired");
  2433.         // Clear the active call (call with C)
  2434.        PSyncPoint sync;
  2435.        endpoint.ClearCallSynchronous(activeCallToken, H323Connection::EndedByLocalUser, &sync);
  2436.         // Answer intruding call (call with A)
  2437.         PTRACE(4, "H450.11\tOnCallIntrudeTimeOut Trying to answer Call");
  2438.         if(endpoint.HasConnection(intrudingCallToken)){
  2439.           H323Connection* conn = endpoint.FindConnectionWithLock(intrudingCallToken);
  2440.           conn->AnsweringCall (conn->AnswerCallNow);
  2441.           conn->Unlock ();
  2442.         }
  2443.       }
  2444.       break;
  2445.     default:
  2446.       break;
  2447.   }
  2448. }
  2449.  
  2450.  
  2451. #if PTRACING
  2452. #define PTRACE_problemType   problemType
  2453. #define PTRACE_problemNumber problemNumber
  2454. #else
  2455. #define PTRACE_problemType
  2456. #define PTRACE_problemNumber
  2457. #endif
  2458.  
  2459. BOOL H45011Handler::OnReceivedReject(int PTRACE_problemType, int PTRACE_problemNumber)
  2460. {
  2461.   PTRACE(4, "H450.11\tH45011Handler::OnReceivedReject - problemType= "
  2462.          << PTRACE_problemType << ", problemNumber= " << PTRACE_problemNumber);
  2463.  
  2464.   if (ciTimer.IsRunning()){
  2465.     ciTimer.Stop();
  2466.     PTRACE(4, "H450.11\tStopping timer CI-TX");
  2467.   }
  2468.  
  2469.   switch (ciState) {
  2470.     case e_ci_GetCIPL:
  2471.     {
  2472.       H323Connection* conn = endpoint.FindConnectionWithLock(intrudingCallToken);
  2473.       conn->SetIntrusionImpending ();
  2474.  
  2475.       //Send Ringing to  intruding (A)
  2476.       conn->AnsweringCall (conn->AnswerCallPending);
  2477.       conn->SetForcedReleaseAccepted();  
  2478.       conn->Unlock ();
  2479.       break;
  2480.     }
  2481.  
  2482.     default:
  2483.       break;
  2484.   }
  2485.   ciState = e_ci_Idle;
  2486.   return TRUE;
  2487. };
  2488.