/// <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)); }
/// <summary> /// Dispose object /// </summary> public override void Dispose() { try { SendControlPacket(SNISMUXFlags.SMUX_FIN); } catch (Exception e) { SNICommon.ReportSNIError(SNIProviders.SMUX_PROV, SNICommon.InternalExceptionError, e); } }
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; }
/// <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)); } }
/// <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)); } }
/// <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)); } }
/// <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); } } }
/// <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); } }
/// <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); } } }
/// <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); } }
/// <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); } }
/// <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); } }
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); }
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); } }
/// <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; } } } }
/// <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); } }
private uint ReportTcpSNIError(uint nativeError, uint sniError, string errorMessage) { _status = TdsEnums.SNI_ERROR; return(SNICommon.ReportSNIError(SNIProviders.TCP_PROV, nativeError, sniError, errorMessage)); }
private uint ReportTcpSNIError(Exception sniException) { _status = TdsEnums.SNI_ERROR; return(SNICommon.ReportSNIError(SNIProviders.TCP_PROV, SNICommon.InternalExceptionError, sniException)); }
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); } }
/// <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); } }
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); } }
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; } } } }