private static void ReadFromStreamAsyncContinuation(Task <int> t, object state) { SNIPacket packet = (SNIPacket)state; SNIError error = null; Exception e = t.Exception?.InnerException; if (e != null) { error = new SNIError(SNIProviders.TCP_PROV, 0, 0, e.Message); } else { packet._length = t.Result; if (packet._length == 0) { error = new SNIError(SNIProviders.TCP_PROV, 0, SNIErrorCode.ConnTerminatedError, string.Empty); } } SNIAsyncCallback callback = packet._completionCallback; packet._completionCallback = null; callback(packet, error); }
/// <summary> /// Enables MARS for a TdsParserStateObject and returns its new handle. /// </summary> public static SNIMarsHandle EnableMars(TdsParserStateObject stateObject, out SNIError sniError) { Debug.Assert(!(stateObject.Handle is SNIMarsHandle), "Cannot enable MARS on a SNIMarsHandle"); SNIMarsConnection marsConnection = new SNIMarsConnection(stateObject.Handle); marsConnection.StartReceive(); return(marsConnection.CreateSession(stateObject, out sniError)); }
private void ReceiveAsyncErrorContinuation(object rawState) { var state = (Tuple <SNIPacket, SNIError>)rawState; SNIPacket packet = state.Item1; SNIError sniError = state.Item2; _receiveCallback(packet, sniError); }
private static void SendAsyncErrorContinuation(object rawState) { var state = (Tuple <SNIPacket, SNIAsyncCallback, SNIError>)rawState; SNIPacket packet = state.Item1; SNIAsyncCallback callback = state.Item2; SNIError sniError = state.Item3; callback(packet, sniError); }
/// <summary> /// Process a receive error /// </summary> public void HandleReceiveError(SNIError sniError) { Debug.Assert(Monitor.IsEntered(this), "HandleReceiveError was called without being locked."); foreach (SNIMarsHandle handle in _sessions.Values) { handle.HandleReceiveError(new SNIPacket(), sniError); } _lowerHandle.Dispose(); }
public SNIMarsHandle CreateSession(TdsParserStateObject callbackObject, out SNIError sniError) { lock (this) { ushort sessionId = _nextSessionId++; SNIMarsHandle handle = new SNIMarsHandle(this, sessionId, callbackObject, out sniError); _sessions.Add(sessionId, handle); return(handle); } }
/// <summary> /// Handle receive error /// </summary> public void HandleReceiveError(SNIPacket packet) { lock (_receivedPacketQueue) { _connectionError = SNILoadHandle.SingletonInstance.LastError; _packetEvent.Set(); } ((TdsParserStateObject)_callbackObject).ReadAsyncCallback(packet, 1); }
/// <summary> /// Handle receive error /// </summary> public void HandleReceiveError() { lock (_receivedPacketQueue) { _connectionError = SNILoadHandle.SingletonInstance.LastError; _packetEvent.Set(); } #if MANAGED_SNI // Causes build issue if uncommented in unmanaged version ((TdsParserStateObject)_callbackObject).ReadAsyncCallback(null, 1); #endif }
/// <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)); } } }
private static void SendAsyncContinuation(Task task, object rawState) { var state = (Tuple <SNITransportHandle, SNIPacket, SNIAsyncCallback>)rawState; SNITransportHandle handle = state.Item1; SNIPacket packet = state.Item2; SNIAsyncCallback callback = state.Item3; if (task.IsFaulted) { SNIError sniError = new SNIError(handle.ProviderNumber, 0, task.Exception); callback(packet, sniError); } else { callback(packet, null); } }
public SNINpHandle(string serverName, string pipeName, long timerExpire, out SNIError error) : base(serverName) { try { _pipeStream = new NamedPipeClientStream(serverName, pipeName, PipeDirection.InOut, PipeOptions.WriteThrough | PipeOptions.Asynchronous); bool isInfiniteTimeOut = long.MaxValue == timerExpire; if (isInfiniteTimeOut) { _pipeStream.Connect(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) { error = new SNIError(SNIProviders.NP_PROV, SNIErrorCode.ConnTimeoutError, te); return; } catch (IOException ioe) { error = new SNIError(SNIProviders.NP_PROV, SNIErrorCode.ConnOpenFailedError, ioe); return; } if (!_pipeStream.IsConnected || !_pipeStream.CanWrite || !_pipeStream.CanRead) { error = new SNIError(SNIProviders.NP_PROV, 0, SNIErrorCode.ConnOpenFailedError, string.Empty); return; } _sslOverTdsStream = new SslOverTdsStream(_pipeStream); _sslStream = new SslStream(_sslOverTdsStream, true, new RemoteCertificateValidationCallback(ValidateServerCertificate), null); _stream = _pipeStream; error = null; }
/// <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> /// Handle receive error /// </summary> public void HandleReceiveError(SNIPacket packet, SNIError sniError) { int callbacksPending; lock (_receivedPacketQueue) { Debug.Assert(_connectionError == null, "Already have a stored connection error"); _connectionError = sniError; // Wake any pending sync receives _packetEvent.Set(); callbacksPending = _asyncReceives; _asyncReceives = 0; } // Callback to any pending async receives for (int i = 0; i < _asyncReceives; i++) { _callbackObject.ReadAsyncCallback(packet, _connectionError); } }
/// <summary> /// Receive a packet asynchronously /// </summary> /// <returns>True if completed synchronously, otherwise false</returns> public override bool ReceiveAsync(bool forceCallback, ref SNIPacket packet, out SNIError sniError) { Debug.Assert(!forceCallback, "SNIMarsHandles should never be forced to use a callback"); lock (_receivedPacketQueue) { int queueCount = _receivedPacketQueue.Count; if (_connectionError != null) { sniError = _connectionError; return(true); } if (queueCount == 0) { _asyncReceives++; sniError = null; return(false); } packet = _receivedPacketQueue.Dequeue(); if (queueCount == 1) { _packetEvent.Reset(); } } lock (this) { _receiveHighwater++; } sniError = SendAckIfNecessary(); return(true); }
/// <summary> /// Send a packet asynchronously /// </summary> /// <param name="packet">SNI packet</param> /// <param name="callback">Completion callback</param> /// <returns>SNI error code</returns> public override bool SendAsync(SNIPacket packet, SNIAsyncCallback callback, bool forceCallback, out SNIError sniError) { lock (this) { _sendPacketQueue.Enqueue(new SNIMarsQueuedPacket(packet, callback != null ? callback : HandleSendComplete)); } SendPendingPackets(); sniError = null; return(false); }
/// <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; } } } }
/// <summary> /// Process a send completion /// </summary> public void HandleSendComplete(SNIPacket packet, SNIError sniError) { packet.InvokeCompletionCallback(sniError); }
/// <summary> /// Creates a new MARS session. /// </summary> public override SNIHandle CreateSession(TdsParserStateObject callbackObject, out SNIError sniError) { return(_connection.CreateSession(callbackObject, out sniError)); }
/// <summary> /// Send a packet asynchronously /// </summary> /// <param name="packet">SNI packet</param> /// <param name="callback">Completion callback</param> /// <returns>SNI error code</returns> public sealed override bool SendAsync(SNIPacket packet, SNIAsyncCallback callback, bool forceCallback, out SNIError sniError) { try { Task writeTask; using (_debugLock.Acquire(this)) { writeTask = packet.WriteToStreamAsync(_stream); } if (writeTask.IsCompleted && !forceCallback) { if (writeTask.IsFaulted) { sniError = new SNIError(ProviderNumber, 0, writeTask.Exception); } else { sniError = null; } return(true); } else { writeTask.ContinueWith(SendAsyncContinuation, Tuple.Create(this, packet, callback ?? _sendCallback), CancellationToken.None, TaskContinuationOptions.DenyChildAttach, TaskScheduler.Default); 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: We caught an error Debug.Assert(sniError != null, "Should have either set an error or returned early"); if (forceCallback) { Task.Factory.StartNew(SendAsyncErrorContinuation, Tuple.Create(packet, callback ?? _sendCallback, sniError), CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); sniError = null; return(false); } else { return(true); } }
public override SNIHandle CreateSession(TdsParserStateObject callbackObject, out SNIError sniError) { Debug.Assert(false, "Not a MARS connection"); sniError = null; return(null); }
/// <summary> /// Constructor /// </summary> /// <param name="serverName">Server name</param> /// <param name="port">TCP port number</param> /// <param name="timerExpire">Connection timer expiration</param> /// <param name="callbackObject">Callback object</param> public SNITCPHandle(string serverName, int port, long timerExpire, bool parallel, out SNIError sniError) : base(serverName) { try { TimeSpan ts; // In case the Timeout is Infinite, we will receive the max value of Int64 as the tick count // The infinite Timeout is a function of ConnectionString Timeout=0 bool isInfiniteTimeOut = long.MaxValue == timerExpire; if (!isInfiniteTimeOut) { ts = DateTime.FromFileTime(timerExpire) - DateTime.Now; ts = ts.Ticks < 0 ? TimeSpan.FromTicks(0) : ts; } Task <Socket> connectTask; if (parallel) { Task <IPAddress[]> serverAddrTask = Dns.GetHostAddressesAsync(serverName); serverAddrTask.Wait(ts); IPAddress[] serverAddresses = serverAddrTask.Result; if (serverAddresses.Length > MaxParallelIpAddresses) { // Fail if above 64 to match legacy behavior sniError = new SNIError(SNIProviders.TCP_PROV, 0, SNIErrorCode.MultiSubnetFailoverWithMoreThan64IPs, string.Empty); return; } connectTask = ConnectAsync(serverAddresses, port); } else { connectTask = ConnectAsync(serverName, port); } if (!(isInfiniteTimeOut ? connectTask.Wait(-1) : connectTask.Wait(ts))) { sniError = new SNIError(SNIProviders.TCP_PROV, 0, SNIErrorCode.ConnOpenFailedError, SQLMessage.Timeout()); return; } _socket = connectTask.Result; _socket.NoDelay = true; _tcpStream = new NetworkStream(_socket, true); _sslOverTdsStream = new SslOverTdsStream(_tcpStream); _sslStream = new SslStream(_sslOverTdsStream, true, new RemoteCertificateValidationCallback(ValidateServerCertificate), null); } catch (SocketException se) { sniError = new SNIError(SNIProviders.TCP_PROV, 0, se); return; } catch (Exception e) { sniError = new SNIError(SNIProviders.TCP_PROV, 0, e); return; } _stream = _tcpStream; sniError = null; }
private static void NullCallback(SNIPacket packet, SNIError error) { }
/// <summary> /// Constructor /// </summary> /// <param name="connection">MARS connection</param> /// <param name="sessionId">MARS session ID</param> /// <param name="callbackObject">Callback object</param> /// <param name="async">true if connection is asynchronous</param> public SNIMarsHandle(SNIMarsConnection connection, ushort sessionId, TdsParserStateObject callbackObject, out SNIError sniError) { _sessionId = sessionId; _connection = connection; _callbackObject = callbackObject; sniError = SendControlPacket(SNISMUXFlags.SMUX_SYN, true); }
/// <summary> /// Send a packet asynchronously /// </summary> /// <param name="packet">SNI packet</param> /// <param name="callback">Completion callback</param> /// <returns>True if completed synchronously, otherwise false</returns> public bool SendAsync(SNIPacket packet, SNIAsyncCallback callback, bool forceCallback, out SNIError sniError) { lock (this) { return(_lowerHandle.SendAsync(packet, callback, forceCallback, out sniError)); } }
/// <summary> /// Receive a packet asynchronously /// </summary> public abstract bool ReceiveAsync(bool forceCallback, ref SNIPacket packet, out SNIError sniError);
/// <summary> /// Handle receive error /// </summary> public void HandleReceiveError() { lock (_receivedPacketQueue) { _connectionError = SNILoadHandle.SingletonInstance.LastError; _packetEvent.Set(); } ((TdsParserStateObject)_callbackObject).ReadAsyncCallback(null, 1); }
/// <summary> /// If this is a multiplexed connection, creates a new session. /// </summary> public abstract SNIHandle CreateSession(TdsParserStateObject callbackObject, out SNIError sniError);
/// <summary> /// Handle send completion /// </summary> public void HandleSendComplete(SNIPacket packet, SNIError sniError) { Debug.Assert(_callbackObject != null); _callbackObject.WriteAsyncCallback(packet, sniError); }
/// <summary> /// Sets last error encountered for SNI /// </summary> /// <param name="error">SNI error</param> /// <returns></returns> internal static uint ReportSNIError(SNIError error) { SNILoadHandle.SingletonInstance.LastError = error; return(TdsEnums.SNI_ERROR); }
/// <summary> /// Send a packet asynchronously /// </summary> /// <param name="packet">SNI packet</param> /// <param name="callback">Completion callback</param> /// <returns>True if completed synchronously, otherwise false</returns> public abstract bool SendAsync(SNIPacket packet, SNIAsyncCallback callback, bool forceCallback, out SNIError error);
/// <summary> /// Sets last error encountered for SNI /// </summary> /// <param name="error">SNI error</param> /// <returns></returns> internal static uint ReportSNIError(SNIError error) { SNILoadHandle.SingletonInstance.LastError = error; return TdsEnums.SNI_ERROR; }
/// <summary> /// Invoke the completion callback /// </summary> /// <param name="sniError">SNI error</param> public void InvokeCompletionCallback(SNIError sniError) { _completionCallback(this, sniError); }