Opc.Ua.Bindings.TcpClientChannel.ProcessOpenSecureChannelResponse C# (CSharp) Method

ProcessOpenSecureChannelResponse() private method

Processes an OpenSecureChannel response message.
private ProcessOpenSecureChannelResponse ( uint messageType, ArraySegment messageChunk ) : bool
messageType uint
messageChunk ArraySegment
return bool
        private bool ProcessOpenSecureChannelResponse(uint messageType, ArraySegment<byte> messageChunk)
        {
            Utils.Trace("Channel {0}: ProcessOpenSecureChannelResponse()", ChannelId);

            // validate the channel state.            
            if (State != TcpChannelState.Opening && State != TcpChannelState.Open)
            {
                ForceReconnect(ServiceResult.Create(StatusCodes.BadTcpMessageTypeInvalid, "Server sent an unexpected OpenSecureChannel response."));
                return false;
            }

            // check if operation was abandoned.
            if (m_handshakeOperation == null)
            {
                return false;
            }
            
            // parse the security header.
            uint channelId = 0;
            X509Certificate2 serverCertificate = null;
            uint requestId = 0;
            uint sequenceNumber = 0;
                
            ArraySegment<byte> messageBody; 
                
            try
            {
                messageBody = ReadAsymmetricMessage(
                    messageChunk,
                    ClientCertificate,
                    out channelId,
                    out serverCertificate,
                    out requestId,
                    out sequenceNumber);
            }
            catch (Exception e)
            {
                ForceReconnect(ServiceResult.Create(e, StatusCodes.BadSecurityChecksFailed, "Could not verify security on OpenSecureChannel response."));
                return false;
            }
  
            BufferCollection chunksToProcess = null;
            
            try
            {                   
                // verify server certificate.
                CompareCertificates(ServerCertificate, serverCertificate, true);

                // verify sequence number.
                ResetSequenceNumber(sequenceNumber);
                
                // check if it is necessary to wait for more chunks.
                if (!TcpMessageType.IsFinal(messageType))
                {
                    SaveIntermediateChunk(requestId, messageBody);
                    return false;
                }
                
                // get the chunks to process.
                chunksToProcess = GetSavedChunks(requestId, messageBody);

                // read message body.
                OpenSecureChannelResponse response = ParseResponse(chunksToProcess) as OpenSecureChannelResponse;

                if (response == null)
                {
                    throw ServiceResultException.Create(StatusCodes.BadTypeMismatch, "Server did not return a valid OpenSecureChannelResponse.");
                }

                // the client needs to use the creation time assigned when it sent 
                // the request and ignores the creation time in the response because
                // the server and client clocks may not be synchronized.

                // update token.
                m_requestedToken.TokenId     = response.SecurityToken.TokenId;
                m_requestedToken.Lifetime    = (int)response.SecurityToken.RevisedLifetime;
                m_requestedToken.ServerNonce = response.ServerNonce;
                
                // log security information.
                if (State == TcpChannelState.Opening)
                {
                    Opc.Ua.Security.Audit.SecureChannelCreated(
                        g_ImplementationString,
                        this.m_url.ToString(),
                        Utils.Format("{0}", channelId),
                        this.EndpointDescription,
                        this.ClientCertificate,
                        serverCertificate,
                        BinaryEncodingSupport.Required);
                }
                else
                {
                    Opc.Ua.Security.Audit.SecureChannelRenewed(
                        g_ImplementationString,
                        Utils.Format("{0}", channelId));
                }

                ChannelId = m_requestedToken.ChannelId = channelId;
                ActivateToken(m_requestedToken);
                m_requestedToken = null;                                
 
                // ready to send requests.
                State = TcpChannelState.Open;
                m_reconnecting = false;

                // enable reconnects.
                m_waitBetweenReconnects = Timeout.Infinite;
                // m_waitBetweenReconnects = TcpMessageLimits.MinTimeBetweenReconnects;
                
                // schedule reconnect before token expires.
                ScheduleTokenRenewal(CurrentToken);

                // connect finally complete.
                m_handshakeOperation.Complete(0);
            }
            catch (Exception e)
            {                
                m_handshakeOperation.Fault(e, StatusCodes.BadTcpInternalError, "Could not process OpenSecureChannelResponse.");
            }
            finally
            {
                if (chunksToProcess != null)
                {
                    chunksToProcess.Release(BufferManager, "ProcessOpenSecureChannelResponse");
                }
            }

            return false;
        }
        #endregion