示例#1
0
        /// <summary>
        /// Start receiving
        /// </summary>
        /// <returns></returns>
        public uint StartReceive()
        {
            SNIPacket packet = null;

            if (ReceiveAsync(ref packet) == TdsEnums.SNI_SUCCESS_IO_PENDING)
            {
                return(TdsEnums.SNI_SUCCESS_IO_PENDING);
            }

            return(SNICommon.ReportSNIError(SNIProviders.SMUX_PROV, 0, SNICommon.ConnNotUsableError, string.Empty));
        }
示例#2
0
 /// <summary>
 /// Dispose object
 /// </summary>
 public override void Dispose()
 {
     try
     {
         SendControlPacket(SNISMUXFlags.SMUX_FIN);
     }
     catch (Exception e)
     {
         SNICommon.ReportSNIError(SNIProviders.SMUX_PROV, SNICommon.InternalExceptionError, e);
     }
 }
示例#3
0
        public SNINpHandle(string serverName, string pipeName, long timerExpire, object callbackObject)
        {
            _sendSync       = new object();
            _targetServer   = serverName;
            _callbackObject = callbackObject;

            try
            {
                _pipeStream = new NamedPipeClientStream(
                    serverName,
                    pipeName,
                    PipeDirection.InOut,
                    PipeOptions.Asynchronous | PipeOptions.WriteThrough);

                bool isInfiniteTimeOut = long.MaxValue == timerExpire;
                if (isInfiniteTimeOut)
                {
                    _pipeStream.Connect(System.Threading.Timeout.Infinite);
                }
                else
                {
                    TimeSpan ts = DateTime.FromFileTime(timerExpire) - DateTime.Now;
                    ts = ts.Ticks < 0 ? TimeSpan.FromTicks(0) : ts;

                    _pipeStream.Connect((int)ts.TotalMilliseconds);
                }
            }
            catch (TimeoutException te)
            {
                SNICommon.ReportSNIError(SNIProviders.NP_PROV, SNICommon.ConnOpenFailedError, te);
                _status = TdsEnums.SNI_ERROR;
                return;
            }
            catch (IOException ioe)
            {
                SNICommon.ReportSNIError(SNIProviders.NP_PROV, SNICommon.ConnOpenFailedError, ioe);
                _status = TdsEnums.SNI_ERROR;
                return;
            }

            if (!_pipeStream.IsConnected || !_pipeStream.CanWrite || !_pipeStream.CanRead)
            {
                SNICommon.ReportSNIError(SNIProviders.NP_PROV, 0, SNICommon.ConnOpenFailedError, string.Empty);
                _status = TdsEnums.SNI_ERROR;
                return;
            }

            _sslOverTdsStream = new SslOverTdsStream(_pipeStream);
            _sslStream        = new SslStream(_sslOverTdsStream, true, new RemoteCertificateValidationCallback(ValidateServerCertificate), null);

            _stream = _pipeStream;
            _status = TdsEnums.SNI_SUCCESS;
        }
示例#4
0
 /// <summary>
 /// Enable SSL on a connection
 /// </summary>
 /// <param name="handle">Connection handle</param>
 /// <param name="options"></param>
 /// <returns>SNI error code</returns>
 internal uint EnableSsl(SNIHandle handle, uint options)
 {
     try
     {
         SqlClientEventSource.Log.TryTraceEvent("SNIProxy.EnableSsl | Info | Session Id {0}", handle?.ConnectionId);
         return(handle.EnableSsl(options));
     }
     catch (Exception e)
     {
         SqlClientEventSource.Log.TryTraceEvent("SNIProxy.EnableSsl | Err | Session Id {0}, SNI Handshake failed with exception: {1}", handle?.ConnectionId, e?.Message);
         return(SNICommon.ReportSNIError(SNIProviders.SSL_PROV, SNICommon.HandshakeFailureError, e));
     }
 }
示例#5
0
        /// <summary>
        /// Receive a packet asynchronously
        /// </summary>
        /// <param name="packet">SNI packet</param>
        /// <returns>SNI error code</returns>
        public override uint ReceiveAsync(ref SNIPacket packet)
        {
            long scopeID = SqlClientEventSource.Log.TrySNIScopeEnterEvent(s_className);

            try
            {
                lock (_receivedPacketQueue)
                {
                    int queueCount = _receivedPacketQueue.Count;

                    if (_connectionError != null)
                    {
                        SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.ERR, "MARS Session Id {0}, _asyncReceives {1}, _receiveHighwater {2}, _sendHighwater {3}, _receiveHighwaterLastAck {4}, _connectionError {5}", args0: ConnectionId, args1: _asyncReceives, args2: _receiveHighwater, args3: _sendHighwater, args4: _receiveHighwaterLastAck, args5: _connectionError);
                        return(SNICommon.ReportSNIError(_connectionError));
                    }

                    if (queueCount == 0)
                    {
                        _asyncReceives++;
                        SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.INFO, "MARS Session Id {0}, queueCount 0, _asyncReceives {1}, _receiveHighwater {2}, _sendHighwater {3}, _receiveHighwaterLastAck {4}", args0: ConnectionId, args1: _asyncReceives, args2: _receiveHighwater, args3: _sendHighwater, args4: _receiveHighwaterLastAck);

                        return(TdsEnums.SNI_SUCCESS_IO_PENDING);
                    }

                    packet = _receivedPacketQueue.Dequeue();

                    if (queueCount == 1)
                    {
#if DEBUG
                        SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.INFO, "MARS Session Id {0}, packet dequeued {1}, packet Owner {2}, packet refCount {3}, received Packet Queue count {4}", args0: ConnectionId, args1: packet?._id, args2: packet?._owner, args3: packet?._refCount, args4: _receivedPacketQueue?.Count);
#endif
                        _packetEvent.Reset();
                    }
                }

                lock (this)
                {
                    _receiveHighwater++;
                }

                SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.INFO, "MARS Session Id {0}, _asyncReceives {1}, _receiveHighwater {2}, _sendHighwater {3}, _receiveHighwaterLastAck {4}, queueCount {5}", args0: ConnectionId, args1: _asyncReceives, args2: _receiveHighwater, args3: _sendHighwater, args4: _receiveHighwaterLastAck, args5: _receivedPacketQueue?.Count);
                SendAckIfNecessary();
                return(TdsEnums.SNI_SUCCESS);
            }
            finally
            {
                SqlClientEventSource.Log.TrySNIScopeLeaveEvent(scopeID);
            }
        }
        internal override uint EnableSsl(ref uint info)
        {
            SNIHandle handle = Handle;

            try
            {
                SqlClientEventSource.Log.TryTraceEvent("TdsParserStateObjectManaged.EnableSsl | Info | Session Id {0}", handle?.ConnectionId);
                return(handle.EnableSsl(info));
            }
            catch (Exception e)
            {
                SqlClientEventSource.Log.TryTraceEvent("TdsParserStateObjectManaged.EnableSsl | Err | Session Id {0}, SNI Handshake failed with exception: {1}", handle?.ConnectionId, e?.Message);
                return(SNICommon.ReportSNIError(SNIProviders.SSL_PROV, SNICommon.HandshakeFailureError, e));
            }
        }
示例#7
0
        /// <summary>
        /// Start receiving
        /// </summary>
        /// <returns></returns>
        public uint StartReceive()
        {
            using (TrySNIEventScope.Create(nameof(SNIMarsConnection)))
            {
                SNIPacket packet = null;

                if (ReceiveAsync(ref packet) == TdsEnums.SNI_SUCCESS_IO_PENDING)
                {
                    SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNIMarsConnection), EventType.INFO, "MARS Session Id {0}, Success IO pending.", args0: ConnectionId);
                    return(TdsEnums.SNI_SUCCESS_IO_PENDING);
                }
                SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNIMarsConnection), EventType.ERR, "MARS Session Id {0}, Connection not usable.", args0: ConnectionId);
                return(SNICommon.ReportSNIError(SNIProviders.SMUX_PROV, 0, SNICommon.ConnNotUsableError, Strings.SNI_ERROR_19));
            }
        }
示例#8
0
        /// <summary>
        /// Receive a packet synchronously
        /// </summary>
        /// <param name="packet">SNI packet</param>
        /// <param name="timeoutInMilliseconds">Timeout in Milliseconds</param>
        /// <returns>SNI error code</returns>
        public override uint Receive(out SNIPacket packet, int timeoutInMilliseconds)
        {
            packet = null;
            int  queueCount;
            uint result = TdsEnums.SNI_SUCCESS_IO_PENDING;

            while (true)
            {
                lock (_receivedPacketQueue)
                {
                    if (_connectionError != null)
                    {
                        return(SNICommon.ReportSNIError(_connectionError));
                    }

                    queueCount = _receivedPacketQueue.Count;

                    if (queueCount > 0)
                    {
                        packet = _receivedPacketQueue.Dequeue();

                        if (queueCount == 1)
                        {
                            _packetEvent.Reset();
                        }

                        result = TdsEnums.SNI_SUCCESS;
                    }
                }

                if (result == TdsEnums.SNI_SUCCESS)
                {
                    lock (this)
                    {
                        _receiveHighwater++;
                    }

                    SendAckIfNecessary();
                    return(result);
                }

                if (!_packetEvent.Wait(timeoutInMilliseconds))
                {
                    SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.SMUX_PROV, 0, SNICommon.ConnTimeoutError, string.Empty);
                    return(TdsEnums.SNI_WAIT_TIMEOUT);
                }
            }
        }
 /// <summary>
 /// Dispose object
 /// </summary>
 public override void Dispose()
 {
     using (TrySNIEventScope.Create(nameof(SNIMarsHandle)))
     {
         try
         {
             SendControlPacket(SNISMUXFlags.SMUX_FIN);
             SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNIMarsHandle), EventType.INFO, "MARS Session Id {0}, Sent SMUX_FIN packet to terminate session.", args0: ConnectionId);
         }
         catch (Exception e)
         {
             SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNIMarsHandle), EventType.ERR, "MARS Session Id {0}, Internal exception error = {1}, Member Name={2}", args0: ConnectionId, args1: e?.Message, args2: e?.GetType()?.Name);
             SNICommon.ReportSNIError(SNIProviders.SMUX_PROV, SNICommon.InternalExceptionError, e);
         }
     }
 }
示例#10
0
        /// <summary>
        /// Dispose object
        /// </summary>
        public override void Dispose()
        {
            long scopeID = SqlClientEventSource.Log.SNIScopeEnterEvent("<sc.SNI.SNIMarsHandle.Dispose |SNI|INFO|SCOPE>");

            try
            {
                SendControlPacket(SNISMUXFlags.SMUX_FIN);
            }
            catch (Exception e)
            {
                SqlClientEventSource.Log.SNITraceEvent("<sc.SNI.SNIMarsHandle.Dispose |SNI|ERR> internal exception error = {0}, Member Name={1}", e.Message, e.GetType().Name);
                SNICommon.ReportSNIError(SNIProviders.SMUX_PROV, SNICommon.InternalExceptionError, e);
            }
            finally
            {
                SqlClientEventSource.Log.SNIScopeLeaveEvent(scopeID);
            }
        }
示例#11
0
 /// <summary>
 /// Dispose object
 /// </summary>
 public override void Dispose()
 {
     // SendControlPacket will lock so make sure that it cannot deadlock by failing to enter the DemuxerLock
     Debug.Assert(_connection != null && Monitor.IsEntered(_connection.DemuxerSync), "SNIMarsHandle.HandleRecieveComplete should be called while holding the SNIMarsConnection.DemuxerSync because it can cause deadlocks");
     using (TrySNIEventScope.Create(nameof(SNIMarsHandle)))
     {
         try
         {
             SendControlPacket(SNISMUXFlags.SMUX_FIN);
             SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNIMarsHandle), EventType.INFO, "MARS Session Id {0}, Sent SMUX_FIN packet to terminate session.", args0: ConnectionId);
         }
         catch (Exception e)
         {
             SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNIMarsHandle), EventType.ERR, "MARS Session Id {0}, Internal exception error = {1}, Member Name={2}", args0: ConnectionId, args1: e?.Message, args2: e?.GetType()?.Name);
             SNICommon.ReportSNIError(SNIProviders.SMUX_PROV, SNICommon.InternalExceptionError, e);
         }
     }
 }
示例#12
0
        /// <summary>
        /// Dispose object
        /// </summary>
        public override void Dispose()
        {
            long scopeID = SqlClientEventSource.Log.TrySNIScopeEnterEvent(s_className);

            try
            {
                SendControlPacket(SNISMUXFlags.SMUX_FIN);
                SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.INFO, "MARS Session Id {0}, Sent SMUX_FIN packet to terminate session.", args0: ConnectionId);
            }
            catch (Exception e)
            {
                SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.ERR, "MARS Session Id {0}, Internal exception error = {1}, Member Name={2}", args0: ConnectionId, args1: e?.Message, args2: e?.GetType()?.Name);
                SNICommon.ReportSNIError(SNIProviders.SMUX_PROV, SNICommon.InternalExceptionError, e);
            }
            finally
            {
                SqlClientEventSource.Log.TrySNIScopeLeaveEvent(scopeID);
            }
        }
示例#13
0
        /// <summary>
        /// Receive a packet asynchronously
        /// </summary>
        /// <param name="packet">SNI packet</param>
        /// <returns>SNI error code</returns>
        public override uint ReceiveAsync(ref SNIPacket packet)
        {
            long scopeID = SqlClientEventSource.Log.SNIScopeEnterEvent("<sc.SNI.SNIMarsHandle.SendAsync |SNI|INFO|SCOPE>");

            try
            {
                lock (_receivedPacketQueue)
                {
                    int queueCount = _receivedPacketQueue.Count;

                    if (_connectionError != null)
                    {
                        return(SNICommon.ReportSNIError(_connectionError));
                    }

                    if (queueCount == 0)
                    {
                        _asyncReceives++;
                        return(TdsEnums.SNI_SUCCESS_IO_PENDING);
                    }

                    packet = _receivedPacketQueue.Dequeue();

                    if (queueCount == 1)
                    {
                        _packetEvent.Reset();
                    }
                }

                lock (this)
                {
                    _receiveHighwater++;
                }

                SendAckIfNecessary();
                return(TdsEnums.SNI_SUCCESS);
            }
            finally
            {
                SqlClientEventSource.Log.SNIScopeLeaveEvent(scopeID);
            }
        }
        /// <summary>
        /// Start receiving
        /// </summary>
        /// <returns></returns>
        public uint StartReceive()
        {
            long scopeID = SqlClientEventSource.Log.TrySNIScopeEnterEvent(s_className);

            try
            {
                SNIPacket packet = null;

                if (ReceiveAsync(ref packet) == TdsEnums.SNI_SUCCESS_IO_PENDING)
                {
                    SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.INFO, "MARS Session Id {0}, Success IO pending.", args0: ConnectionId);
                    return(TdsEnums.SNI_SUCCESS_IO_PENDING);
                }
                SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.ERR, "MARS Session Id {0}, Connection not usable.", args0: ConnectionId);
                return(SNICommon.ReportSNIError(SNIProviders.SMUX_PROV, 0, SNICommon.ConnNotUsableError, Strings.SNI_ERROR_19));
            }
            finally
            {
                SqlClientEventSource.Log.TrySNIScopeLeaveEvent(scopeID);
            }
        }
示例#15
0
        /// <summary>
        /// Start receiving
        /// </summary>
        /// <returns></returns>
        public uint StartReceive()
        {
            long scopeID = SqlClientEventSource.Log.TrySNIScopeEnterEvent("<sc.SNI.SNIMarsConnection.StartReceive |SNI|INFO|SCOPE> StartReceive");

            try
            {
                SNIPacket packet = null;

                if (ReceiveAsync(ref packet) == TdsEnums.SNI_SUCCESS_IO_PENDING)
                {
                    SqlClientEventSource.Log.TrySNITraceEvent("<sc.SNI.SNIMarsConnection.StartReceive |SNI|INFO|Trace> Success IO pending.");
                    return(TdsEnums.SNI_SUCCESS_IO_PENDING);
                }
                SqlClientEventSource.Log.TrySNITraceEvent("<sc.SNI.SNIMarsConnection.StartReceive |SNI|ERR> Connection not useable.");
                return(SNICommon.ReportSNIError(SNIProviders.SMUX_PROV, 0, SNICommon.ConnNotUsableError, Strings.SNI_ERROR_19));
            }
            finally
            {
                SqlClientEventSource.Log.TrySNIScopeLeaveEvent(scopeID);
            }
        }
示例#16
0
        public override uint EnableSsl(uint options)
        {
            _validateCert = (options & TdsEnums.SNI_SSL_VALIDATE_CERTIFICATE) != 0;

            try
            {
                _sslStream.AuthenticateAsClientAsync(_targetServer).GetAwaiter().GetResult();
                _sslOverTdsStream.FinishHandshake();
            }
            catch (AuthenticationException aue)
            {
                return(SNICommon.ReportSNIError(SNIProviders.NP_PROV, SNICommon.InternalExceptionError, aue));
            }
            catch (InvalidOperationException ioe)
            {
                return(SNICommon.ReportSNIError(SNIProviders.NP_PROV, SNICommon.InternalExceptionError, ioe));
            }

            _stream = _sslStream;
            return(TdsEnums.SNI_SUCCESS);
        }
示例#17
0
 public override uint EnableSsl(uint options)
 {
     using (TrySNIEventScope.Create(nameof(SNINpHandle)))
     {
         _validateCert = (options & TdsEnums.SNI_SSL_VALIDATE_CERTIFICATE) != 0;
         try
         {
             _sslStream.AuthenticateAsClient(_targetServer, null, SupportedProtocols, false);
             _sslOverTdsStream.FinishHandshake();
         }
         catch (AuthenticationException aue)
         {
             SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNINpHandle), EventType.ERR, "Connection Id {0}, AuthenticationException message = {1}.", args0: ConnectionId, args1: aue?.Message);
             return(SNICommon.ReportSNIError(SNIProviders.NP_PROV, SNICommon.InternalExceptionError, aue));
         }
         catch (InvalidOperationException ioe)
         {
             SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNINpHandle), EventType.ERR, "Connection Id {0}, InvalidOperationException message = {1}.", args0: ConnectionId, args1: ioe?.Message);
             return(SNICommon.ReportSNIError(SNIProviders.NP_PROV, SNICommon.InternalExceptionError, ioe));
         }
         _stream = _sslStream;
         return(TdsEnums.SNI_SUCCESS);
     }
 }
示例#18
0
        /// <summary>
        /// Process a receive completion
        /// </summary>
        /// <param name="packet">SNI packet</param>
        /// <param name="sniErrorCode">SNI error code</param>
        public void HandleReceiveComplete(SNIPacket packet, uint sniErrorCode)
        {
            SNISMUXHeader currentHeader  = null;
            SNIPacket     currentPacket  = null;
            SNIMarsHandle currentSession = null;

            if (sniErrorCode != TdsEnums.SNI_SUCCESS)
            {
                lock (this)
                {
                    HandleReceiveError(packet);
                    return;
                }
            }

            while (true)
            {
                lock (this)
                {
                    if (_currentHeaderByteCount != SNISMUXHeader.HEADER_LENGTH)
                    {
                        currentHeader  = null;
                        currentPacket  = null;
                        currentSession = null;

                        while (_currentHeaderByteCount != SNISMUXHeader.HEADER_LENGTH)
                        {
                            int bytesTaken = packet.TakeData(_headerBytes, _currentHeaderByteCount, SNISMUXHeader.HEADER_LENGTH - _currentHeaderByteCount);
                            _currentHeaderByteCount += bytesTaken;

                            if (bytesTaken == 0)
                            {
                                packet.Dispose();
                                packet       = null;
                                sniErrorCode = ReceiveAsync(ref packet);

                                if (sniErrorCode == TdsEnums.SNI_SUCCESS_IO_PENDING)
                                {
                                    return;
                                }

                                HandleReceiveError(packet);
                                return;
                            }
                        }

                        _currentHeader.Read(_headerBytes);

                        _dataBytesLeft = (int)_currentHeader.length;
                        _currentPacket = new SNIPacket((int)_currentHeader.length);
                    }

                    currentHeader = _currentHeader;
                    currentPacket = _currentPacket;

                    if (_currentHeader.flags == (byte)SNISMUXFlags.SMUX_DATA)
                    {
                        if (_dataBytesLeft > 0)
                        {
                            int length = packet.TakeData(_currentPacket, _dataBytesLeft);
                            _dataBytesLeft -= length;

                            if (_dataBytesLeft > 0)
                            {
                                packet.Dispose();
                                packet       = null;
                                sniErrorCode = ReceiveAsync(ref packet);

                                if (sniErrorCode == TdsEnums.SNI_SUCCESS_IO_PENDING)
                                {
                                    return;
                                }

                                HandleReceiveError(packet);
                                return;
                            }
                        }
                    }

                    _currentHeaderByteCount = 0;

                    if (!_sessions.ContainsKey(_currentHeader.sessionId))
                    {
                        SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.SMUX_PROV, 0, SNICommon.InvalidParameterError, string.Empty);
                        HandleReceiveError(packet);
                        _lowerHandle.Dispose();
                        _lowerHandle = null;
                        return;
                    }

                    if (_currentHeader.flags == (byte)SNISMUXFlags.SMUX_FIN)
                    {
                        _sessions.Remove(_currentHeader.sessionId);
                    }
                    else
                    {
                        currentSession = _sessions[_currentHeader.sessionId];
                    }
                }

                if (currentHeader.flags == (byte)SNISMUXFlags.SMUX_DATA)
                {
                    currentSession.HandleReceiveComplete(currentPacket, currentHeader);
                }

                if (_currentHeader.flags == (byte)SNISMUXFlags.SMUX_ACK)
                {
                    try
                    {
                        currentSession.HandleAck(currentHeader.highwater);
                    }
                    catch (Exception e)
                    {
                        SNICommon.ReportSNIError(SNIProviders.SMUX_PROV, SNICommon.InternalExceptionError, e);
                    }
                }

                lock (this)
                {
                    if (packet.DataLeft == 0)
                    {
                        packet.Dispose();
                        packet       = null;
                        sniErrorCode = ReceiveAsync(ref packet);

                        if (sniErrorCode == TdsEnums.SNI_SUCCESS_IO_PENDING)
                        {
                            return;
                        }

                        HandleReceiveError(packet);
                        return;
                    }
                }
            }
        }
示例#19
0
        /// <summary>
        /// Process a receive completion
        /// </summary>
        /// <param name="packet">SNI packet</param>
        /// <param name="sniErrorCode">SNI error code</param>
        public void HandleReceiveComplete(SNIPacket packet, uint sniErrorCode)
        {
            long scopeID = SqlClientEventSource.Log.TrySNIScopeEnterEvent("<sc.SNI.SNIMarsConnection.HandleReceiveComplete |SNI|INFO|SCOPE>");

            try
            {
                SNISMUXHeader currentHeader  = null;
                SNIPacket     currentPacket  = null;
                SNIMarsHandle currentSession = null;

                if (sniErrorCode != TdsEnums.SNI_SUCCESS)
                {
                    lock (this)
                    {
                        HandleReceiveError(packet);
                        SqlClientEventSource.Log.TrySNITraceEvent("<sc.SNI.SNIMarsConnection.HandleReceiveComplete |SNI|ERR> not successful.");
                        return;
                    }
                }

                while (true)
                {
                    lock (this)
                    {
                        if (_currentHeaderByteCount != SNISMUXHeader.HEADER_LENGTH)
                        {
                            currentHeader  = null;
                            currentPacket  = null;
                            currentSession = null;

                            while (_currentHeaderByteCount != SNISMUXHeader.HEADER_LENGTH)
                            {
                                int bytesTaken = packet.TakeData(_headerBytes, _currentHeaderByteCount, SNISMUXHeader.HEADER_LENGTH - _currentHeaderByteCount);
                                _currentHeaderByteCount += bytesTaken;

                                if (bytesTaken == 0)
                                {
                                    sniErrorCode = ReceiveAsync(ref packet);

                                    if (sniErrorCode == TdsEnums.SNI_SUCCESS_IO_PENDING)
                                    {
                                        SqlClientEventSource.Log.TrySNITraceEvent("<sc.SNI.SNIMarsConnection.HandleReceiveComplete |SNI|ERR> not successful.");
                                        return;
                                    }

                                    HandleReceiveError(packet);
                                    return;
                                }
                            }

                            _currentHeader.Read(_headerBytes);

                            _dataBytesLeft = (int)_currentHeader.length;
                            _currentPacket = _lowerHandle.RentPacket(headerSize: 0, dataSize: (int)_currentHeader.length);
                        }

                        currentHeader = _currentHeader;
                        currentPacket = _currentPacket;

                        if (_currentHeader.flags == (byte)SNISMUXFlags.SMUX_DATA)
                        {
                            if (_dataBytesLeft > 0)
                            {
                                int length = packet.TakeData(_currentPacket, _dataBytesLeft);
                                _dataBytesLeft -= length;

                                if (_dataBytesLeft > 0)
                                {
                                    sniErrorCode = ReceiveAsync(ref packet);

                                    if (sniErrorCode == TdsEnums.SNI_SUCCESS_IO_PENDING)
                                    {
                                        return;
                                    }

                                    HandleReceiveError(packet);
                                    return;
                                }
                            }
                        }

                        _currentHeaderByteCount = 0;

                        if (!_sessions.ContainsKey(_currentHeader.sessionId))
                        {
                            SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.SMUX_PROV, 0, SNICommon.InvalidParameterError, Strings.SNI_ERROR_5);
                            HandleReceiveError(packet);
                            _lowerHandle.Dispose();
                            _lowerHandle = null;
                            return;
                        }

                        if (_currentHeader.flags == (byte)SNISMUXFlags.SMUX_FIN)
                        {
                            _sessions.Remove(_currentHeader.sessionId);
                        }
                        else
                        {
                            currentSession = _sessions[_currentHeader.sessionId];
                        }
                    }

                    if (currentHeader.flags == (byte)SNISMUXFlags.SMUX_DATA)
                    {
                        currentSession.HandleReceiveComplete(currentPacket, currentHeader);
                    }

                    if (_currentHeader.flags == (byte)SNISMUXFlags.SMUX_ACK)
                    {
                        try
                        {
                            currentSession.HandleAck(currentHeader.highwater);
                        }
                        catch (Exception e)
                        {
                            SNICommon.ReportSNIError(SNIProviders.SMUX_PROV, SNICommon.InternalExceptionError, e);
                        }

                        Debug.Assert(_currentPacket == currentPacket, "current and _current are not the same");
                        ReturnPacket(currentPacket);
                        currentPacket  = null;
                        _currentPacket = null;
                    }

                    lock (this)
                    {
                        if (packet.DataLeft == 0)
                        {
                            sniErrorCode = ReceiveAsync(ref packet);

                            if (sniErrorCode == TdsEnums.SNI_SUCCESS_IO_PENDING)
                            {
                                return;
                            }

                            HandleReceiveError(packet);
                            return;
                        }
                    }
                }
            }
            finally
            {
                SqlClientEventSource.Log.TrySNIScopeLeaveEvent(scopeID);
            }
        }
示例#20
0
 private uint ReportTcpSNIError(uint nativeError, uint sniError, string errorMessage)
 {
     _status = TdsEnums.SNI_ERROR;
     return(SNICommon.ReportSNIError(SNIProviders.TCP_PROV, nativeError, sniError, errorMessage));
 }
示例#21
0
 private uint ReportTcpSNIError(Exception sniException)
 {
     _status = TdsEnums.SNI_ERROR;
     return(SNICommon.ReportSNIError(SNIProviders.TCP_PROV, SNICommon.InternalExceptionError, sniException));
 }
示例#22
0
        public SNINpHandle(string serverName, string pipeName, long timerExpire, object callbackObject)
        {
            long scopeID = SqlClientEventSource.Log.TrySNIScopeEnterEvent("<sc.SNI.SNINpHandle.SNINpHandle |SNI|INFO|SCOPE> Constructor");

            SqlClientEventSource.Log.TrySNITraceEvent("<sc.SNI.SNINpHandle.SNINpHandle |SNI|INFO> Constructor. server name = {0}, pipe name = {1}", serverName, pipeName);
            try
            {
                _sendSync       = new object();
                _targetServer   = serverName;
                _callbackObject = callbackObject;

                try
                {
                    _pipeStream = new NamedPipeClientStream(
                        serverName,
                        pipeName,
                        PipeDirection.InOut,
                        PipeOptions.Asynchronous | PipeOptions.WriteThrough);

                    bool isInfiniteTimeOut = long.MaxValue == timerExpire;
                    if (isInfiniteTimeOut)
                    {
                        _pipeStream.Connect(System.Threading.Timeout.Infinite);
                    }
                    else
                    {
                        TimeSpan ts = DateTime.FromFileTime(timerExpire) - DateTime.Now;
                        ts = ts.Ticks < 0 ? TimeSpan.FromTicks(0) : ts;

                        _pipeStream.Connect((int)ts.TotalMilliseconds);
                    }
                }
                catch (TimeoutException te)
                {
                    SNICommon.ReportSNIError(SNIProviders.NP_PROV, SNICommon.ConnOpenFailedError, te);
                    _status = TdsEnums.SNI_ERROR;
                    SqlClientEventSource.Log.TrySNITraceEvent("<sc.SNI.SNINpHandle.SNINpHandle |SNI|ERR> Timed out. Exception = {0}", te.Message);
                    return;
                }
                catch (IOException ioe)
                {
                    SNICommon.ReportSNIError(SNIProviders.NP_PROV, SNICommon.ConnOpenFailedError, ioe);
                    _status = TdsEnums.SNI_ERROR;
                    SqlClientEventSource.Log.TrySNITraceEvent("<sc.SNI.SNINpHandle.SNINpHandle |SNI|ERR> IOException = {0}", ioe.Message);
                    return;
                }

                if (!_pipeStream.IsConnected || !_pipeStream.CanWrite || !_pipeStream.CanRead)
                {
                    SNICommon.ReportSNIError(SNIProviders.NP_PROV, 0, SNICommon.ConnOpenFailedError, string.Empty);
                    _status = TdsEnums.SNI_ERROR;
                    SqlClientEventSource.Log.TrySNITraceEvent("<sc.SNI.SNINpHandle.SNINpHandle |SNI|ERR> Pipe stream is not connected or cannot write or read to/from it.");
                    return;
                }

                _sslOverTdsStream = new SslOverTdsStream(_pipeStream);
                _sslStream        = new SslStream(_sslOverTdsStream, true, new RemoteCertificateValidationCallback(ValidateServerCertificate), null);

                _stream = _pipeStream;
                _status = TdsEnums.SNI_SUCCESS;
            }
            finally
            {
                SqlClientEventSource.Log.TrySNIScopeLeaveEvent(scopeID);
            }
        }
示例#23
0
        /// <summary>
        /// Receive a packet synchronously
        /// </summary>
        /// <param name="packet">SNI packet</param>
        /// <param name="timeoutInMilliseconds">Timeout in Milliseconds</param>
        /// <returns>SNI error code</returns>
        public override uint Receive(out SNIPacket packet, int timeoutInMilliseconds)
        {
            long scopeID = SqlClientEventSource.Log.TrySNIScopeEnterEvent(s_className);

            try
            {
                packet = null;
                int  queueCount;
                uint result = TdsEnums.SNI_SUCCESS_IO_PENDING;

                while (true)
                {
                    lock (_receivedPacketQueue)
                    {
                        if (_connectionError != null)
                        {
                            SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.ERR, "MARS Session Id {0}, _sequenceNumber {1}, _sendHighwater {2}, _connectionError found: {3}.", args0: ConnectionId, args1: _sequenceNumber, args2: _sendHighwater, args3: _connectionError);
                            return(SNICommon.ReportSNIError(_connectionError));
                        }

                        queueCount = _receivedPacketQueue.Count;
                        SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.INFO, "MARS Session Id {0}, _sequenceNumber {1}, _sendHighwater {2}, W_receivedPacketQueue count {3}.", args0: ConnectionId, args1: _sequenceNumber, args2: _sendHighwater, args3: queueCount);

                        if (queueCount > 0)
                        {
                            packet = _receivedPacketQueue.Dequeue();

                            if (queueCount == 1)
                            {
                                _packetEvent.Reset();
                                SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.INFO, "MARS Session Id {0}, _sequenceNumber {1}, _sendHighwater {2}, packet event reset, _receivedPacketQueue count 1.", args0: ConnectionId, args1: _sequenceNumber, args2: _sendHighwater);
                            }

                            result = TdsEnums.SNI_SUCCESS;
                        }
                    }

                    if (result == TdsEnums.SNI_SUCCESS)
                    {
                        lock (this)
                        {
                            _receiveHighwater++;
                        }

                        SendAckIfNecessary();
                        SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.INFO, "MARS Session Id {0}, _sequenceNumber {1}, _sendHighwater {2}, returning with result {3}.", args0: ConnectionId, args1: _sequenceNumber, args2: _sendHighwater, args3: result);
                        return(result);
                    }

                    SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.INFO, "MARS Session Id {0}, _sequenceNumber {1}, _sendHighwater {2}, Waiting for packet event.", args0: ConnectionId, args1: _sequenceNumber, args2: _sendHighwater);
                    if (!_packetEvent.Wait(timeoutInMilliseconds))
                    {
                        SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.SMUX_PROV, 0, SNICommon.ConnTimeoutError, Strings.SNI_ERROR_11);
                        SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.INFO, "MARS Session Id {0}, _sequenceNumber {1}, _sendHighwater {2}, _packetEvent wait timed out.", args0: ConnectionId, args1: _sequenceNumber, args2: _sendHighwater);
                        return(TdsEnums.SNI_WAIT_TIMEOUT);
                    }
                }
            }
            finally
            {
                SqlClientEventSource.Log.TrySNIScopeLeaveEvent(scopeID);
            }
        }
示例#24
0
        public SNINpHandle(string serverName, string pipeName, long timerExpire)
        {
            long scopeID = SqlClientEventSource.Log.TrySNIScopeEnterEvent(s_className);

            SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.INFO, "Connection Id {0}, Setting server name = {1}, pipe name = {2}", args0: _connectionId, args1: serverName, args2: pipeName);
            try
            {
                _sendSync     = new object();
                _targetServer = serverName;

                try
                {
                    _pipeStream = new NamedPipeClientStream(
                        serverName,
                        pipeName,
                        PipeDirection.InOut,
                        PipeOptions.Asynchronous | PipeOptions.WriteThrough);

                    bool isInfiniteTimeOut = long.MaxValue == timerExpire;
                    if (isInfiniteTimeOut)
                    {
                        _pipeStream.Connect(Timeout.Infinite);
                    }
                    else
                    {
                        TimeSpan ts = DateTime.FromFileTime(timerExpire) - DateTime.Now;
                        ts = ts.Ticks < 0 ? TimeSpan.FromTicks(0) : ts;

                        _pipeStream.Connect((int)ts.TotalMilliseconds);
                    }
                }
                catch (TimeoutException te)
                {
                    SNICommon.ReportSNIError(SNIProviders.NP_PROV, SNICommon.ConnOpenFailedError, te);
                    _status = TdsEnums.SNI_ERROR;
                    SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.ERR, "Connection Id {0}, Connection Timed out. Error Code 1 Exception = {1}", args0: _connectionId, args1: te?.Message);
                    return;
                }
                catch (IOException ioe)
                {
                    SNICommon.ReportSNIError(SNIProviders.NP_PROV, SNICommon.ConnOpenFailedError, ioe);
                    _status = TdsEnums.SNI_ERROR;
                    SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.ERR, "Connection Id {0}, IO Exception occurred. Error Code 1 Exception = {1}", args0: _connectionId, args1: ioe?.Message);
                    return;
                }

                if (!_pipeStream.IsConnected || !_pipeStream.CanWrite || !_pipeStream.CanRead)
                {
                    SNICommon.ReportSNIError(SNIProviders.NP_PROV, 0, SNICommon.ConnOpenFailedError, Strings.SNI_ERROR_40);
                    _status = TdsEnums.SNI_ERROR;
                    SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.ERR, "Connection Id {0}, Pipe Stream not operational. Error Code 1 Exception = {1}", args0: _connectionId, args1: Strings.SNI_ERROR_1);
                    return;
                }

                _sslOverTdsStream = new SslOverTdsStream(_pipeStream, _connectionId);
                _sslStream        = new SNISslStream(_sslOverTdsStream, true, new RemoteCertificateValidationCallback(ValidateServerCertificate));

                _stream = _pipeStream;
                _status = TdsEnums.SNI_SUCCESS;
            }
            finally
            {
                SqlClientEventSource.Log.TrySNIScopeLeaveEvent(scopeID);
            }
        }
        /// <summary>
        /// Process a receive completion
        /// </summary>
        /// <param name="packet">SNI packet</param>
        /// <param name="sniErrorCode">SNI error code</param>
        public void HandleReceiveComplete(SNIPacket packet, uint sniErrorCode)
        {
            long scopeID = SqlClientEventSource.Log.TrySNIScopeEnterEvent(s_className);

            try
            {
                SNISMUXHeader currentHeader  = null;
                SNIPacket     currentPacket  = null;
                SNIMarsHandle currentSession = null;

                if (sniErrorCode != TdsEnums.SNI_SUCCESS)
                {
                    lock (this)
                    {
                        HandleReceiveError(packet);
                        SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.ERR, "MARS Session Id {0}, Handled receive error code: {1}", args0: _lowerHandle?.ConnectionId, args1: sniErrorCode);
                        return;
                    }
                }

                while (true)
                {
                    lock (this)
                    {
                        if (_currentHeaderByteCount != SNISMUXHeader.HEADER_LENGTH)
                        {
                            currentHeader  = null;
                            currentPacket  = null;
                            currentSession = null;

                            while (_currentHeaderByteCount != SNISMUXHeader.HEADER_LENGTH)
                            {
                                int bytesTaken = packet.TakeData(_headerBytes, _currentHeaderByteCount, SNISMUXHeader.HEADER_LENGTH - _currentHeaderByteCount);
                                _currentHeaderByteCount += bytesTaken;

                                if (bytesTaken == 0)
                                {
                                    sniErrorCode = ReceiveAsync(ref packet);
                                    SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.INFO, "MARS Session Id {0}, Non-SMUX Header SNI Packet received with code {1}", args0: ConnectionId, args1: sniErrorCode);

                                    if (sniErrorCode == TdsEnums.SNI_SUCCESS_IO_PENDING)
                                    {
                                        return;
                                    }

                                    HandleReceiveError(packet);
                                    SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.ERR, "MARS Session Id {0}, Handled receive error code: {1}", args0: _lowerHandle?.ConnectionId, args1: sniErrorCode);
                                    return;
                                }
                            }

                            _currentHeader.Read(_headerBytes);
                            _dataBytesLeft = (int)_currentHeader.length;
                            _currentPacket = _lowerHandle.RentPacket(headerSize: 0, dataSize: (int)_currentHeader.length);
#if DEBUG
                            SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.INFO, "MARS Session Id {0}, _dataBytesLeft {1}, _currentPacket {2}, Reading data of length: _currentHeader.length {3}", args0: _lowerHandle?.ConnectionId, args1: _dataBytesLeft, args2: currentPacket?._id, args3: _currentHeader?.length);
#endif
                        }

                        currentHeader = _currentHeader;
                        currentPacket = _currentPacket;

                        if (_currentHeader.flags == (byte)SNISMUXFlags.SMUX_DATA)
                        {
                            if (_dataBytesLeft > 0)
                            {
                                int length = packet.TakeData(_currentPacket, _dataBytesLeft);
                                _dataBytesLeft -= length;

                                if (_dataBytesLeft > 0)
                                {
                                    sniErrorCode = ReceiveAsync(ref packet);
                                    SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.INFO, "MARS Session Id {0}, SMUX DATA Header SNI Packet received with code {1}, _dataBytesLeft {2}", args0: ConnectionId, args1: sniErrorCode, args2: _dataBytesLeft);

                                    if (sniErrorCode == TdsEnums.SNI_SUCCESS_IO_PENDING)
                                    {
                                        return;
                                    }

                                    HandleReceiveError(packet);
                                    SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.ERR, "MARS Session Id {0}, Handled receive error code: {1}", args0: _lowerHandle?.ConnectionId, args1: sniErrorCode);
                                    return;
                                }
                            }
                        }

                        _currentHeaderByteCount = 0;

                        if (!_sessions.ContainsKey(_currentHeader.sessionId))
                        {
                            SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.SMUX_PROV, 0, SNICommon.InvalidParameterError, Strings.SNI_ERROR_5);
                            HandleReceiveError(packet);
                            SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.ERR, "Current Header Session Id {0} not found, MARS Session Id {1} will be destroyed, New SNI error created: {2}", args0: _currentHeader?.sessionId, args1: _lowerHandle?.ConnectionId, args2: sniErrorCode);
                            _lowerHandle.Dispose();
                            _lowerHandle = null;
                            return;
                        }

                        if (_currentHeader.flags == (byte)SNISMUXFlags.SMUX_FIN)
                        {
                            _sessions.Remove(_currentHeader.sessionId);
                            SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.INFO, "SMUX_FIN | MARS Session Id {0}, SMUX_FIN flag received, Current Header Session Id {1} removed", args0: _lowerHandle?.ConnectionId, args1: _currentHeader?.sessionId);
                        }
                        else
                        {
                            currentSession = _sessions[_currentHeader.sessionId];
                            SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.INFO, "MARS Session Id {0}, Current Session assigned to Session Id {1}", args0: _lowerHandle?.ConnectionId, args1: _currentHeader?.sessionId);
                        }
                    }

                    if (currentHeader.flags == (byte)SNISMUXFlags.SMUX_DATA)
                    {
                        currentSession.HandleReceiveComplete(currentPacket, currentHeader);
                        SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.INFO, "SMUX_DATA | MARS Session Id {0}, Current Session {1} completed receiving Data", args0: _lowerHandle?.ConnectionId, args1: _currentHeader?.sessionId);
                    }

                    if (_currentHeader.flags == (byte)SNISMUXFlags.SMUX_ACK)
                    {
                        try
                        {
                            currentSession.HandleAck(currentHeader.highwater);
                            SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.INFO, "SMUX_ACK | MARS Session Id {0}, Current Session {1} handled ack", args0: _lowerHandle?.ConnectionId, args1: _currentHeader?.sessionId);
                        }
                        catch (Exception e)
                        {
                            SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.ERR, "SMUX_ACK | MARS Session Id {0}, Exception occurred: {2}", args0: _currentHeader?.sessionId, args1: e?.Message);
                            SNICommon.ReportSNIError(SNIProviders.SMUX_PROV, SNICommon.InternalExceptionError, e);
                        }
#if DEBUG
                        Debug.Assert(_currentPacket == currentPacket, "current and _current are not the same");
                        SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.INFO, "SMUX_ACK | MARS Session Id {0}, Current Packet {1} returned", args0: _lowerHandle?.ConnectionId, args1: currentPacket?._id);
#endif
                        ReturnPacket(currentPacket);
                        currentPacket  = null;
                        _currentPacket = null;
                    }

                    lock (this)
                    {
                        if (packet.DataLeft == 0)
                        {
                            sniErrorCode = ReceiveAsync(ref packet);

                            if (sniErrorCode == TdsEnums.SNI_SUCCESS_IO_PENDING)
                            {
                                return;
                            }

                            HandleReceiveError(packet);
                            SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.ERR, "MARS Session Id {0}, packet.DataLeft 0, SNI error {2}", args0: _lowerHandle?.ConnectionId, args1: sniErrorCode);
                            return;
                        }
                    }
                }
            }
            finally
            {
                SqlClientEventSource.Log.TrySNIScopeLeaveEvent(scopeID);
            }
        }
示例#26
0
        public void HandleReceiveComplete(SNIPacket packet, uint sniErrorCode)
        {
            using (TrySNIEventScope.Create(nameof(SNIMarsConnection)))
            {
                if (sniErrorCode != TdsEnums.SNI_SUCCESS)
                {
                    lock (DemuxerSync)
                    {
                        HandleReceiveError(packet);
                        SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNIMarsConnection), EventType.ERR, "MARS Session Id {0}, Handled receive error code: {1}", args0: _lowerHandle?.ConnectionId, args1: sniErrorCode);
                        return;
                    }
                }

                State state     = State.Demux;
                State nextState = State.Demux;

                SNISMUXHeader handleHeader  = default;
                SNIMarsHandle handleSession = null;
                SNIPacket     handlePacket  = null;

                while (state != State.Error && state != State.Finish)
                {
                    switch (state)
                    {
                    case State.Demux:
                        lock (DemuxerSync)
                        {
                            switch (_demuxState)
                            {
                            case DemuxState.Header:
                                int taken = packet.TakeData(_headerBytes, _headerCount, SNISMUXHeader.HEADER_LENGTH - _headerCount);
                                _headerCount += taken;
                                SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNIMarsConnection), EventType.INFO, "MARS Session Id {0}, took {1} header bytes", args0: _lowerHandle?.ConnectionId, args1: packet.DataLeft, args2: taken);
                                if (_headerCount == SNISMUXHeader.HEADER_LENGTH)
                                {
                                    _header.Read(_headerBytes);
                                    _payloadLength = (int)_header.Length;
                                    _payloadCount  = 0;
                                    _demuxState    = DemuxState.Payload;
                                    state          = State.Demux;
                                    SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNIMarsConnection), EventType.INFO, "MARS Session Id {0}, header complete, _payloadLength {1}", args0: _lowerHandle?.ConnectionId, args1: _payloadLength);
                                    goto case DemuxState.Payload;
                                }
                                else
                                {
                                    state = State.Receive;
                                }
                                break;

                            case DemuxState.Payload:
                                if (packet.DataLeft == _payloadLength && _partial == null)
                                {
                                    // if the data in the packet being processed is exactly and only the data that is going to sent
                                    // on to the parser then don't copy it to a new packet just forward the current packet once we've
                                    // fiddled the data pointer so that it skips the header data
                                    _partial = packet;
                                    packet   = null;
                                    _partial.SetDataToRemainingContents();
                                    _demuxState = DemuxState.Dispatch;
                                    state       = State.Demux;
                                    SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNIMarsConnection), EventType.INFO, "MARS Session Id {0}, forwarding packet contents", args0: _lowerHandle?.ConnectionId, args1: _header.SessionId);
                                    goto case DemuxState.Dispatch;
                                }
                                else
                                {
                                    if (_partial == null)
                                    {
                                        _partial = RentPacket(headerSize: 0, dataSize: _payloadLength);
                                    }
                                    SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNIMarsConnection), EventType.INFO, "MARS Session Id {0}, reconstructing packet contents", args0: _lowerHandle?.ConnectionId, args1: _header.SessionId);
                                    int wanted      = _payloadLength - _payloadCount;
                                    int transferred = SNIPacket.TransferData(packet, _partial, wanted);
                                    _payloadCount += transferred;
                                    SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNIMarsConnection), EventType.INFO, "MARS Session Id {0}, took {1} payload bytes", args0: _lowerHandle?.ConnectionId, args1: transferred);

                                    if (_payloadCount == _payloadLength)
                                    {
                                        // payload is complete so dispatch the current packet
                                        _demuxState = DemuxState.Dispatch;
                                        state       = State.Receive;
                                        goto case DemuxState.Dispatch;
                                    }
                                    else if (packet.DataLeft == 0)
                                    {
                                        // no more data in the delivered packet so wait for a new one
                                        _demuxState = DemuxState.Payload;
                                        state       = State.Receive;
                                    }
                                    else
                                    {
                                        // data left in the delivered packet so start the demux loop
                                        // again and decode the next packet in the input
                                        _headerCount = 0;
                                        _demuxState  = DemuxState.Header;
                                        state        = State.Demux;
                                    }
                                }

                                break;

                            case DemuxState.Dispatch:
                                if (_sessions.TryGetValue(_header.SessionId, out SNIMarsHandle session))
                                {
                                    SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNIMarsConnection), EventType.INFO, "MARS Session Id {0}, Current Session assigned to Session Id {1}", args0: _lowerHandle?.ConnectionId, args1: _header.SessionId);
                                    switch ((SNISMUXFlags)_header.Flags)
                                    {
                                    case SNISMUXFlags.SMUX_DATA:
                                        handleSession = session;
                                        session       = null;
                                        handleHeader  = _header.Clone();
                                        handlePacket  = _partial;
                                        _partial      = null;
                                        // move to the state for sending the data to the mars handle and setup
                                        // the state that should be moved to after that operation has succeeded
                                        state = State.HandleData;
                                        if (packet != null && packet.DataLeft > 0)
                                        {
                                            nextState = State.Demux;
                                        }
                                        else
                                        {
                                            nextState = State.Receive;
                                        }
                                        break;

                                    case SNISMUXFlags.SMUX_ACK:
                                        handleSession = session;
                                        session       = null;
                                        handleHeader  = _header.Clone();
                                        ReturnPacket(_partial);
                                        _partial = null;
                                        // move to the state for sending the data to the mars handle and setup
                                        // the state that should be moved to after that operation has succeeded
                                        state = State.HandleAck;
                                        if (packet != null && packet.DataLeft > 0)
                                        {
                                            nextState = State.Demux;
                                        }
                                        else
                                        {
                                            nextState = State.Receive;
                                        }
                                        break;

                                    case SNISMUXFlags.SMUX_FIN:
                                        ReturnPacket(_partial);
                                        _partial = null;
                                        _sessions.Remove(_header.SessionId);
                                        SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNIMarsConnection), EventType.INFO, "SMUX_FIN | MARS Session Id {0}, SMUX_FIN flag received, Current Header Session Id {1} removed", args0: _lowerHandle?.ConnectionId, args1: _header.SessionId);
                                        break;

                                    default:
                                        Debug.Fail("unknown smux packet flag");
                                        break;
                                    }

                                    // a full packet has been decoded and queued for sending by setting the state or the
                                    // handle it was sent to no longer exists and the handle has been dropped. Now reset the
                                    // demuxer state ready to recode another packet
                                    _header.Clear();
                                    _headerCount = 0;
                                    _demuxState  = DemuxState.Header;

                                    // if the state is set to demux more data and there is no data left then change
                                    // the state to request more data
                                    if (state == State.Demux && (packet == null || packet.DataLeft == 0))
                                    {
                                        if (packet != null)
                                        {
                                            SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNIMarsConnection), EventType.INFO, "MARS Session Id {0}, run out of data , queuing receive", args0: _lowerHandle?.ConnectionId, args1: _header.SessionId);
                                        }
                                        state = State.Receive;
                                    }
                                }
                                else
                                {
                                    SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.SMUX_PROV, 0, SNICommon.InvalidParameterError, string.Empty);
                                    HandleReceiveError(packet);
                                    SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNIMarsConnection), EventType.ERR, "Current Header Session Id {0} not found, MARS Session Id {1} will be destroyed, New SNI error created: {2}", args0: _header.SessionId, args1: _lowerHandle?.ConnectionId, args2: sniErrorCode);
                                    packet = null;
                                    _lowerHandle.Dispose();
                                    _lowerHandle = null;
                                    state        = State.Error;
                                }
                                break;
                            }
                        }
                        break;

                    case State.HandleAck:
                        Debug.Assert(handleSession != null, "dispatching ack to null SNIMarsHandle");
                        Debug.Assert(!Monitor.IsEntered(DemuxerSync), "do not dispatch ack to session handle while holding the demuxer lock");
                        try
                        {
                            handleSession.HandleAck(handleHeader.Highwater);
                            SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNIMarsConnection), EventType.INFO, "SMUX_ACK | MARS Session Id {0}, Current Session {1} handled ack", args0: _lowerHandle?.ConnectionId, args1: _header.SessionId);
                        }
                        catch (Exception e)
                        {
                            SNICommon.ReportSNIError(SNIProviders.SMUX_PROV, SNICommon.InternalExceptionError, e);
                        }
                        finally
                        {
                            handleHeader  = default;
                            handleSession = null;
                        }
                        state     = nextState;
                        nextState = State.Finish;
                        break;

                    case State.HandleData:
                        Debug.Assert(handleSession != null, "dispatching data to null SNIMarsHandle");
                        Debug.Assert(handlePacket != null, "dispatching null data to SNIMarsHandle");
                        Debug.Assert(!Monitor.IsEntered(DemuxerSync), "do not dispatch data to session handle while holding the demuxer lock");
                        // do not ReturnPacket(handlePacket) the receiver is responsible for returning the packet
                        // once it has been used because it can take sync and async paths from to the receiver and
                        // only the reciever can make the decision on when it is completed and can be returned
                        try
                        {
                            handleSession.HandleReceiveComplete(handlePacket, handleHeader);
                            SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNIMarsConnection), EventType.INFO, "SMUX_DATA | MARS Session Id {0}, Current Session {1} completed receiving Data", args0: _lowerHandle?.ConnectionId, args1: _header.SessionId);
                        }
                        finally
                        {
                            handleHeader  = default;
                            handleSession = null;
                            handlePacket  = null;
                        }
                        state     = nextState;
                        nextState = State.Finish;
                        break;

                    case State.Receive:
                        if (packet != null)
                        {
                            Debug.Assert(packet.DataLeft == 0, "loop exit with data remaining");
                            ReturnPacket(packet);
                            packet = null;
                        }

                        lock (DemuxerSync)
                        {
                            uint receiveResult = ReceiveAsync(ref packet);
                            if (receiveResult == TdsEnums.SNI_SUCCESS_IO_PENDING)
                            {
                                SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNIMarsConnection), EventType.INFO, "MARS Session Id {0}, SMUX DATA Header SNI Packet received with code {1}", args0: ConnectionId, args1: receiveResult);
                                packet = null;
                            }
                            else
                            {
                                HandleReceiveError(packet);
                                SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNIMarsConnection), EventType.ERR, "MARS Session Id {0}, Handled receive error code: {1}", args0: _lowerHandle?.ConnectionId, args1: receiveResult);
                            }
                        }
                        state = State.Finish;
                        break;
                    }
                }
            }
        }