/// <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; if (timeoutInMilliseconds > 0) { _socket.ReceiveTimeout = timeoutInMilliseconds; } else if (timeoutInMilliseconds == -1) { // SqlCient internally represents infinite timeout by -1, and for TcpClient this is translated to a timeout of 0 _socket.ReceiveTimeout = 0; } else { // otherwise it is timeout for 0 or less than -1 ReportTcpSNIError(0, SNICommon.ConnTimeoutError, string.Empty); return(TdsEnums.SNI_WAIT_TIMEOUT); } _sniPacket.Allocate(_bufferSize); try { _sniPacket.ReadFromStream(_stream); if (_sniPacket.Length == 0) { Win32Exception e = new Win32Exception(); return(ReportErrorAndReleasePacket(_sniPacket, (uint)e.NativeErrorCode, 0, e.Message)); } packet = _sniPacket; return(TdsEnums.SNI_SUCCESS); } catch (ObjectDisposedException ode) { return(ReportErrorAndReleasePacket(packet, ode)); } catch (SocketException se) { return(ReportErrorAndReleasePacket(packet, se)); } catch (IOException ioe) { if (ioe.InnerException is SocketException && ((SocketException)(ioe.InnerException)).SocketErrorCode == SocketError.TimedOut) { return(TdsEnums.SNI_WAIT_TIMEOUT); } else { return(ReportErrorAndReleasePacket(packet, ioe)); } } finally { _socket.ReceiveTimeout = 0; } }
public override uint Receive(out SNIPacket packet, int timeout) { lock (this) { packet = null; try { packet = new SNIPacket(null); packet.Allocate(_bufferSize); packet.ReadFromStream(_stream); if (packet.Length == 0) { var e = new Win32Exception(); return(ReportErrorAndReleasePacket(packet, (uint)e.NativeErrorCode, 0, e.Message)); } } catch (ObjectDisposedException ode) { return(ReportErrorAndReleasePacket(packet, ode)); } catch (IOException ioe) { return(ReportErrorAndReleasePacket(packet, ioe)); } return(TdsEnums.SNI_SUCCESS); } }
public override uint Receive(out SNIPacket packet, int timeout) { lock (this) { packet = null; try { packet = new SNIPacket(null); packet.Allocate(_bufferSize); packet.ReadFromStream(_stream); if (packet.Length == 0) { return(ReportErrorAndReleasePacket(packet, 0, SNICommon.ConnTerminatedError, string.Empty)); } } catch (ObjectDisposedException ode) { return(ReportErrorAndReleasePacket(packet, ode)); } catch (IOException ioe) { return(ReportErrorAndReleasePacket(packet, ioe)); } return(TdsEnums.SNI_SUCCESS); } }
/// <summary> /// Receive a packet asynchronously /// </summary> /// <param name="packet">SNI packet</param> /// <returns>SNI error code</returns> public override uint ReceiveAsync(ref SNIPacket packet, bool isMars = false) { lock (this) { packet = new SNIPacket(null); packet.Allocate(_bufferSize); try { packet.ReadFromStreamAsync(_stream, _receiveCallback, isMars); return(TdsEnums.SNI_SUCCESS_IO_PENDING); } catch (ObjectDisposedException ode) { return(ReportErrorAndReleasePacket(packet, ode)); } catch (SocketException se) { return(ReportErrorAndReleasePacket(packet, se)); } catch (IOException ioe) { return(ReportErrorAndReleasePacket(packet, ioe)); } } }
/// <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) { lock (this) { packet = null; try { if (timeoutInMilliseconds > 0) { _tcpClient.ReceiveTimeout = timeoutInMilliseconds; } else if (timeoutInMilliseconds == -1) { // SqlCient internally represents infinite timeout by -1, and for TcpClient this is translated to a timeout of 0 _tcpClient.ReceiveTimeout = 0; } else { // otherwise it is timeout for 0 or less than -1 ReportTcpSNIError(SR.SNI_ERROR_11); //timeout error message return(TdsEnums.SNI_WAIT_TIMEOUT); } packet = new SNIPacket(null); packet.Allocate(_bufferSize); packet.ReadFromStream(_stream); if (packet.Length == 0) { return(ReportErrorAndReleasePacket(packet, "Connection was terminated")); } return(TdsEnums.SNI_SUCCESS); } catch (ObjectDisposedException ode) { return(ReportErrorAndReleasePacket(packet, ode.Message)); } catch (SocketException se) { return(ReportErrorAndReleasePacket(packet, se.Message)); } catch (IOException ioe) { uint errorCode = ReportErrorAndReleasePacket(packet, ioe.Message); if (ioe.InnerException is SocketException && ((SocketException)(ioe.InnerException)).SocketErrorCode == SocketError.TimedOut) { errorCode = TdsEnums.SNI_WAIT_TIMEOUT; } return(errorCode); } finally { _tcpClient.ReceiveTimeout = 0; } } }
/// <summary> /// Generate a packet with SMUX header /// </summary> /// <param name="packet">SNI packet</param> /// <returns>Encapsulated SNI packet</returns> private SNIPacket GetSMUXEncapsulatedPacket(SNIPacket packet) { uint xSequenceNumber = _sequenceNumber; byte[] headerBytes = null; GetSMUXHeaderBytes(packet.Length, (byte)SNISMUXFlags.SMUX_DATA, ref headerBytes); SNIPacket smuxPacket = new SNIPacket(); smuxPacket.Description = string.Format("({0}) SMUX packet {1}", packet.Description == null ? "" : packet.Description, xSequenceNumber); smuxPacket.Allocate(16 + packet.Length); smuxPacket.AppendData(headerBytes, 16); smuxPacket.AppendPacket(packet); return(smuxPacket); }
/// <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 sealed override SNIError Receive(ref SNIPacket packet, int timeoutInMilliseconds) { packet = packet ?? new SNIPacket(); using (_debugLock.Acquire(this)) { try { SNIError timeoutError = SetupTimeoutForReceive(timeoutInMilliseconds); if (timeoutError != null) { return(timeoutError); } packet.Allocate(_bufferSize); packet.ReadFromStream(_stream); if (packet.Length == 0) { return(new SNIError(ProviderNumber, 0, 0, "Connection was terminated")); } return(null); } catch (ObjectDisposedException ode) { packet = null; return(new SNIError(ProviderNumber, 0, ode)); } catch (SocketException se) { packet = null; return(new SNIError(ProviderNumber, 0, se)); } catch (IOException ioe) { SNIErrorCode errorCode = SNIErrorCode.NoError; if (ioe.InnerException is SocketException && ((SocketException)(ioe.InnerException)).SocketErrorCode == SocketError.TimedOut) { errorCode = SNIErrorCode.ConnTimeoutError; } packet = null; return(new SNIError(ProviderNumber, errorCode, ioe)); } } }
/// <summary> /// Receive a packet synchronously /// </summary> /// <param name="packet">SNI packet</param> /// <param name="timeout">Timeout</param> /// <returns>SNI error code</returns> public override uint Receive(ref SNIPacket packet, int timeout) { lock (this) { try { _tcpClient.ReceiveTimeout = (timeout != 0) ? timeout : 1; packet = new SNIPacket(null); packet.Allocate(_bufferSize); packet.ReadFromStream(_stream); if (packet.Length == 0) { return(ReportErrorAndReleasePacket(packet, "Connection was terminated")); } return(TdsEnums.SNI_SUCCESS); } catch (ObjectDisposedException ode) { return(ReportErrorAndReleasePacket(packet, ode.Message)); } catch (SocketException se) { return(ReportErrorAndReleasePacket(packet, se.Message)); } catch (IOException ioe) { uint errorCode = ReportErrorAndReleasePacket(packet, ioe.Message); if (ioe.InnerException is SocketException && ((SocketException)(ioe.InnerException)).SocketErrorCode == SocketError.TimedOut) { errorCode = TdsEnums.SNI_WAIT_TIMEOUT; } return(errorCode); } finally { _tcpClient.ReceiveTimeout = 0; } } }
/// <summary> /// Receive a packet asynchronously /// </summary> /// <param name="packet">SNI packet</param> /// <returns>SNI error code</returns> public sealed override bool ReceiveAsync(bool forceCallback, ref SNIPacket packet, out SNIError sniError) { packet = packet ?? new SNIPacket(); packet.Allocate(_bufferSize); using (_debugLock.Acquire(this)) { try { packet.ReadFromStreamAsync(_stream, _receiveCallback); sniError = null; return(false); } catch (ObjectDisposedException ode) { sniError = new SNIError(ProviderNumber, 0, ode); } catch (SocketException se) { sniError = new SNIError(ProviderNumber, 0, se); } catch (IOException ioe) { sniError = new SNIError(ProviderNumber, 0, ioe); } // Fallthrough: Something failed Debug.Assert(sniError != null, "Error should be set if we didn't already return"); if (forceCallback) { Task.Factory.StartNew( ReceiveAsyncErrorContinuation, Tuple.Create(packet, sniError), CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); sniError = null; return(false); } return(true); } }
/// <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(); 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) { return; } HandleReceiveError(); return; } } _currentHeader = new SNISMUXHeader() { SMID = _headerBytes[0], flags = _headerBytes[1], sessionId = BitConverter.ToUInt16(_headerBytes, 2), length = BitConverter.ToUInt32(_headerBytes, 4) - SNISMUXHeader.HEADER_LENGTH, sequenceNumber = BitConverter.ToUInt32(_headerBytes, 8), highwater = BitConverter.ToUInt32(_headerBytes, 12) }; _dataBytesLeft = (int)_currentHeader.length; _currentPacket = new SNIPacket(null); _currentPacket.Allocate((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(); return; } } } _currentHeaderByteCount = 0; if (!_sessions.ContainsKey(_currentHeader.sessionId)) { SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.SMUX_PROV, 0, SNICommon.InvalidParameterError, string.Empty); HandleReceiveError(); _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) { sniErrorCode = ReceiveAsync(ref packet); if (sniErrorCode == TdsEnums.SNI_SUCCESS_IO_PENDING) { return; } HandleReceiveError(); return; } } } }
/// <summary> /// Process a receive completion /// </summary> public void HandleReceiveComplete(SNIPacket packet, SNIError sniError) { SNISMUXHeader currentHeader = null; SNIPacket currentPacket = null; SNIMarsHandle currentSession = null; if (sniError != null) { lock (this) { HandleReceiveError(sniError); return; } } int packetOffset = 0; while (true) { lock (this) { bool sessionRemoved = false; if (_currentHeaderByteCount != SNISMUXHeader.HEADER_LENGTH) { currentHeader = null; currentPacket = null; currentSession = null; while (_currentHeaderByteCount != SNISMUXHeader.HEADER_LENGTH) { int bytesTaken = packet.TakeData(packetOffset, _headerBytes, _currentHeaderByteCount, SNISMUXHeader.HEADER_LENGTH - _currentHeaderByteCount); packetOffset += bytesTaken; _currentHeaderByteCount += bytesTaken; if (bytesTaken == 0) { packetOffset = 0; ReceiveAsync(ref packet); return; } } _currentHeader = new SNISMUXHeader() { SMID = _headerBytes[0], flags = _headerBytes[1], sessionId = BitConverter.ToUInt16(_headerBytes, 2), length = BitConverter.ToUInt32(_headerBytes, 4) - SNISMUXHeader.HEADER_LENGTH, sequenceNumber = BitConverter.ToUInt32(_headerBytes, 8), highwater = BitConverter.ToUInt32(_headerBytes, 12) }; _dataBytesLeft = (int)_currentHeader.length; _currentPacket = new SNIPacket(); _currentPacket.Allocate((int)_currentHeader.length); } currentHeader = _currentHeader; currentPacket = _currentPacket; if (_currentHeader.flags == (byte)SNISMUXFlags.SMUX_DATA) { if (_dataBytesLeft > 0) { int length = packet.TakeData(packetOffset, _currentPacket, _dataBytesLeft); packetOffset += length; _dataBytesLeft -= length; if (_dataBytesLeft > 0) { packetOffset = 0; ReceiveAsync(ref packet); return; } } } _currentHeaderByteCount = 0; if (!sessionRemoved && !_sessions.TryGetValue(_currentHeader.sessionId, out currentSession)) { sniError = new SNIError(SNIProviders.TCP_PROV, 0, 0, "Packet for unknown MARS session received"); HandleReceiveError(sniError); return; } if (_currentHeader.flags == (byte)SNISMUXFlags.SMUX_FIN) { RemoveSession(_currentHeader.sessionId); sessionRemoved = true; } else { currentSession = _sessions[_currentHeader.sessionId]; } } if (currentSession != null) { if (currentHeader.flags == (byte)SNISMUXFlags.SMUX_DATA) { currentSession.HandleReceiveComplete(currentPacket, currentHeader); } else if (_currentHeader.flags == (byte)SNISMUXFlags.SMUX_ACK) { currentSession.HandleAck(currentHeader.highwater); } } lock (this) { if (packet.Length - packetOffset == 0) { packetOffset = 0; ReceiveAsync(ref packet); return; } } } }