/// <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; } } } }