/// <summary> /// Start receiving /// </summary> public void StartReceive() { SNIPacket packet = null; ReceiveAsync(ref packet); }
/// <summary> /// Set packet data /// </summary> /// <param name="packet">SNI packet</param> /// <param name="data">Data</param> /// <param name="length">Length</param> public void PacketSetData(SNIPacket packet, byte[] data, int length) { packet.SetData(data, length); }
/// <summary> /// Handle send completion /// </summary> public void HandleSendComplete(SNIPacket packet, SNIError sniError) { Debug.Assert(_callbackObject != null); _callbackObject.WriteAsyncCallback(packet, sniError); }
internal void WriteAsyncCallback(SNIPacket packet, UInt32 sniError) => WriteAsyncCallback(IntPtr.Zero, packet, sniError);
/// <summary> /// Reset a packet /// </summary> /// <param name="handle">SNI handle</param> /// <param name="write">true if packet is for write</param> /// <param name="packet">SNI packet</param> public void PacketReset(SNIHandle handle, bool write, SNIPacket packet) { packet.Reset(); }
internal void ReadAsyncCallback(SNIPacket packet, uint error) => ReadAsyncCallback(IntPtr.Zero, PacketHandle.FromManagedPacket(packet), error);
protected override bool CheckPacket(object packet, TaskCompletionSource <object> source) { SNIPacket p = packet as SNIPacket; return(p.IsInvalid || (!p.IsInvalid && source != null)); }
/// <summary> /// Receive a packet asynchronously /// </summary> public abstract bool ReceiveAsync(bool forceCallback, ref SNIPacket packet, out SNIError sniError);
/// <summary> /// Read packet asynchronously /// </summary> /// <param name="handle">SNI handle</param> /// <param name="packet">Packet</param> /// <returns>SNI error status</returns> public uint ReadAsync(SNIHandle handle, out SNIPacket packet, bool isMars = false) { packet = new SNIPacket(null); return(handle.ReceiveAsync(ref packet)); }
/// <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> /// Receive a packet synchronously /// </summary> /// <param name="packet">SNI packet</param> /// <param name="timeoutInMilliseconds">Timeout in Milliseconds</param> /// <returns>SNI error code</returns> public abstract SNIError Receive(ref SNIPacket packet, int timeout);
/// <summary> /// Send a packet synchronously /// </summary> /// <param name="packet">SNI packet</param> /// <returns>SNI error code</returns> public abstract SNIError Send(SNIPacket packet);
/// <summary> /// Append another packet /// </summary> /// <param name="packet">Packet</param> public void AppendPacket(SNIPacket packet) { Buffer.BlockCopy(packet._data, 0, _data, _length, packet._length); _length += packet._length; }
private static void NullCallback(SNIPacket packet, SNIError error) { }
/// <summary> /// Read packet asynchronously /// </summary> /// <param name="handle">SNI handle</param> /// <param name="packet">Packet</param> /// <returns>SNI error status</returns> public uint ReadAsync(SNIHandle handle, out SNIPacket packet) { packet = null; return(handle.ReceiveAsync(ref packet)); }
/// <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); if (_currentHeader.flags == (byte)SNISMUXFlags.SMUX_FIN) { _sessions.Remove(_currentHeader.sessionId); } } 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, 0, "Packet for unknown MARS session received"); HandleReceiveError(); _lowerHandle.Dispose(); _lowerHandle = null; return; } 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.TCP_PROV, 0, 0, e.Message); } } lock (this) { if (packet.DataLeft == 0) { sniErrorCode = ReceiveAsync(ref packet); if (sniErrorCode == TdsEnums.SNI_SUCCESS_IO_PENDING) { return; } HandleReceiveError(); return; } } } }
protected override bool CheckPacket(PacketHandle packet, TaskCompletionSource <object> source) { SNIPacket p = packet.ManagedPacket; return(p.IsInvalid || source != null); }
/// <summary> /// Process a send completion /// </summary> /// <param name="packet">SNI packet</param> /// <param name="sniErrorCode">SNI error code</param> public void HandleSendComplete(SNIPacket packet, uint sniErrorCode) { packet.InvokeCompletionCallback(sniErrorCode); }
internal void WriteAsyncCallback(SNIPacket packet, uint sniError) => WriteAsyncCallback(IntPtr.Zero, PacketHandle.FromManagedPacket(packet), sniError);
/// <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) { 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(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, 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) { sniErrorCode = ReceiveAsync(ref packet); if (sniErrorCode == TdsEnums.SNI_SUCCESS_IO_PENDING) { return; } HandleReceiveError(packet); return; } } } }
internal void ReadAsyncCallback(SNIPacket packet, UInt32 error) => ReadAsyncCallback(IntPtr.Zero, packet, error);
private uint ReportErrorAndReleasePacket(SNIPacket packet, string errorMessage) { packet.Release(); return(ReportTcpSNIError(0, 0, errorMessage)); }
/// <summary> /// Read synchronously /// </summary> /// <param name="handle">SNI handle</param> /// <param name="packet">SNI packet</param> /// <param name="timeout">Timeout</param> /// <returns>SNI error status</returns> public uint ReadSyncOverAsync(SNIHandle handle, out SNIPacket packet, int timeout) { return(handle.Receive(out packet, timeout)); }
/// <summary> /// Process a send completion /// </summary> public void HandleSendComplete(SNIPacket packet, SNIError sniError) { packet.InvokeCompletionCallback(sniError); }
/// <summary> /// Read packet asynchronously /// </summary> /// <param name="handle">SNI handle</param> /// <param name="packet">Packet</param> /// <returns>SNI error status</returns> public uint ReadAsync(SNIHandle handle, ref SNIPacket packet) { packet = new SNIPacket(null); return(handle.ReceiveAsync(ref packet)); }
/// <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> /// Release packet /// </summary> /// <param name="packet">SNI packet</param> public void PacketRelease(SNIPacket packet) { packet.Release(); }
/// <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); } }