docs: public void connect(ConnectionProperties cp, ClientComponentHandshake cch)
        throws SIResourceException, SIAuthenticationException
     {
        if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.entry(this, tc, "connect", new Object[] {cp, cch});
  
        ClientConnectionManager conMan = null;
  
        if (cp == null)
        {
           // The caller of this method passed in a null for the connection properties. This is
           // bad as we kinda need those so we know where to connect to.
           SIErrorException e = new SIErrorException(
              nls.getFormattedMessage("NULL_CONNECTION_PROPERTIES_SICO1039", null, null)
           );
  
           FFDCFilter.processException(e, CLASS_NAME + ".connect",
                                       CommsConstants.CLIENTSIDECONNECTION_CONNECT_04, this);
  
           throw e;
        }
  
        if (cch == null)
        {
           // The caller of this method passed in null for the client component handshake. We need
           // this so we can call back to them to inform them to handshake.
           SIErrorException e = new SIErrorException(
              nls.getFormattedMessage("NULL_CCH_SICO1040", null, null)
           );
  
           FFDCFilter.processException(e, CLASS_NAME + ".connect",
                                       CommsConstants.CLIENTSIDECONNECTION_CONNECT_05, this);
  
           throw e;
        }
  
        // Use the JFAP Channel to connect to the server
        Conversation con = null;
        boolean handshakeCompletedOk = false;
  
        try
        {
           ClientConnectionManager.initialise();
           conMan = ClientConnectionManager.getRef();
  
           // Establish a connection using details passed in via TRM.
           // These details can either be a hostname / port or a WLM
           // end point.
           if (cp.getMode() == ConnectionProperties.PropertiesType.HOST_PORT)
           {
              final String host = cp.getEndPoint().getHost();
              final int port = cp.getEndPoint().getPort().intValue();
              final String chainName = cp.getChainName();
  
              connectionInfo = host + ":" + port + " - " + chainName;
              if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(this, tc, "Connecting to: " + connectionInfo);
  
              final InetSocketAddress addr = AccessController.doPrivileged(new PrivilegedAction<InetSocketAddress>() {
                 @Override
                 public InetSocketAddress run() {
                    return new InetSocketAddress(host, port);
                 }
              });
              con = conMan.connect(addr, new ProxyReceiveListener(), chainName);
           }
           else if (cp.getMode() == ConnectionProperties.PropertiesType.WLM_EP)
           {
              Object wlmEndpointData = cp.getWLMEndPointData();
  
              connectionInfo = wlmEndpointData.toString();
              if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(this, tc, "Connecting to: " + connectionInfo);
  
              con = conMan.connect(wlmEndpointData,
                                   new ProxyReceiveListener());
           }
           else // cp.getMode() == ConnectionProperties.Z_TCP_PROXY
           {
              connectionInfo = "tcp bridge service";
              if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(this, tc, "Connecting via: "+connectionInfo);
              con = conMan.connect(new ProxyReceiveListener(), ConversationUsageType.JFAP);
           }
  
           // Store the Conversation reference
           setConversation(con);
           // We need to store Conversation state for each conversation so now
           // seems a good time to create the state storage object
           createConversationState();
  
           // Store away the ClientSideConnection associated with this conversation
           this.setCommsConnection(this);
  
           // Start F247845
           // Check and see the multicast parameters passed into us by TRM
           Map trmProperties = cp.getClientConnectionPropertyMap();
           if (trmProperties != null)
           {
              if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(this, tc, "Client properties: ", trmProperties);
  
              // Work out if Multicast is infact enabled
              String subProtocol = (String) trmProperties.get(SibTrmConstants.SUBSCRIPTION_PROTOCOL);
              if (subProtocol != null)
              {
                 if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(this, tc, "Subscription protocol:", subProtocol);
  
                 if (subProtocol.equals(SibTrmConstants.SUBSCRIPTION_PROTOCOL_MULTICAST))
                 {
                    // TODO: fix this up!
                    throw new SIErrorException("This shouldn't happen!");
                 }
              }
           }
  
           // We only need to do Comms and MFP handshaking if the connection was made
           // using a brand new socket
           if (con.isFirst())
           {
              // Set the connection closed listener
              con.addConnectionClosedListener(this, ConversationUsageType.JFAP);
  
              initiateCommsHandshaking();
  
              if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(this, tc, "Comms handshake completed successfully");
              
              // Get hold of product version
              int productVersion = getConversation().getHandshakeProperties().getMajorVersion();
  
              try
              {
                 // Get hold of MFP and drive it to handshake
                 CompHandshake ch = (CompHandshake) CompHandshakeFactory.getInstance();
                 ch.compStartHandshake(this,productVersion);
              }
              catch (Exception e1)
              {
                 FFDCFilter.processException(e1, CLASS_NAME + ".connect",
                                            CommsConstants.CLIENTSIDECONNECTION_CONNECT_03, this);
  
                 if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(this, tc, "MFP unable to create CompHandshake Singleton", e1);
  
                 String message = nls.getFormattedMessage(
                    "MFP_HANDSHAKE_FAILED_SICO1005", new Object[] { e1 }, null
                 );
  
                 SIResourceException ce = new SIResourceException(message, e1);
                 throw ce;
              }
           }
  
           // Now call TRM to do its handshaking
           if (!cch.connect(this))
           {
              // If TRM returned false here, we need to throw an exception
              // to cancel the proceedings. This may be a TRM failure or more
              // likely an authorisation problem. No matter what though, we
              // just indicate this to TRM and let them figure out why
              if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(this, tc, "TRM connection returned false - connection will be aborted");  //d179741
  
              // The caller of this method passed in null for the client component handshake. We need
              // this so we can call back to them to inform them to handshake.
              SIResourceException e = new SIResourceException(
                 nls.getFormattedMessage("TRM_HANDSHAKE_FAILED_SICO1037", null, null)
              );
  
              FFDCFilter.processException(e, CLASS_NAME + ".connect",
                                          CommsConstants.CLIENTSIDECONNECTION_CONNECT_06, this);
  
              throw e;
           }
           
           if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(this, tc, "TRM handshake completed successfully"); // D223615
           handshakeCompletedOk = true;
        }
        catch (SIException e)
        {
           // No FFDC code needed
  
           // We don't FFDC here as being unable to connect is not necessarily a problem. In the case of bootstraping clients
           // each bootstrap triplet will be tried since being unable to connect to some targets is to be expected - particularly
           // in fail over scenarios. We have also discovered that a FFDC during a fail over can slow the fail over process. Instead
           // we just throw the exception back to our caller and let the layers above which know the bigger picture decide whether
           // to FFDC or not.
  
           if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(this, tc, "Unable to make initial connection", e);
  
           SIResourceException ce = new SIResourceException(
              nls.getFormattedMessage("CONNECT_FAILED_SICO1001", new Object[] { e }, null)
           );
  
           ce.initCause(e);
           if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.exit(this, tc, "connect", ce);
           throw ce;
        }
        finally
        {
           // Ensure we always call this - as even if we fail we don't want to block everyone
           // else out from starting a conversation
           if (con != null)
           {
              if (handshakeCompletedOk)
              {
                 con.handshakeComplete();
              }
              else
              {
              	// release any handshake waiters  
                  if (con != null)
                     con.handshakeFailed();
                  
                  // Start D273578
                  // Ensure we close the conversation down ignoring any exceptions
                  try 
                  {
                     if (con != null)
                        con.close();
                  }
                  catch (SIException e2)
                  {
                     // No FFDC Code Needed
                     if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(this, tc, "Failed to close connection: " + e2);
                  }
                  // End D273578
                  
                  con = null;
              }
           }
        }
  
        if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.exit(this, tc, "connect");
     }