private FinishRead ( byte renegotiateBuffer ) : void | ||
renegotiateBuffer | byte | |
return | void |
// // Combined sync/async read method. For sync request asyncRequest==null. // private int ProcessRead(byte[] buffer, int offset, int count, BufferAsyncResult asyncResult) { ValidateParameters(buffer, offset, count); if (Interlocked.Exchange(ref _nestedRead, 1) == 1) { throw new NotSupportedException(SR.Format(SR.net_io_invalidnestedcall, (asyncResult != null? "BeginRead":"Read"), "read")); } // If this is an async operation, get the AsyncProtocolRequest to use. // We do this only after we verify we're the sole write operation in flight. AsyncProtocolRequest asyncRequest = GetOrCreateProtocolRequest(ref _readProtocolRequest, asyncResult); bool failed = false; try { int copyBytes; if (InternalBufferCount != 0) { copyBytes = InternalBufferCount > count ? count : InternalBufferCount; if (copyBytes != 0) { Buffer.BlockCopy(InternalBuffer, InternalOffset, buffer, offset, copyBytes); SkipBytes(copyBytes); } asyncRequest?.CompleteUser(copyBytes); return(copyBytes); } return(StartReading(buffer, offset, count, asyncRequest)); } catch (Exception e) { _sslState.FinishRead(null); failed = true; if (e is IOException) { throw; } throw new IOException(SR.net_io_read, e); } finally { if (asyncRequest == null || failed) { _nestedRead = 0; } } }
// // Combined sync/async read method. For sync request asyncRequest==null // There is a little overhead because we need to pass buffer/offset/count used only in sync. // Still the benefit is that we have a common sync/async code path. // private int ProcessRead(byte[] buffer, int offset, int count, AsyncProtocolRequest asyncRequest) { ValidateParameters(buffer, offset, count); if (Interlocked.Exchange(ref _NestedRead, 1) == 1) { throw new NotSupportedException(SR.Format(SR.net_io_invalidnestedcall, (asyncRequest != null ? "BeginRead" : "Read"), "read")); } bool failed = false; try { int copyBytes; if (InternalBufferCount != 0) { copyBytes = InternalBufferCount > count ? count : InternalBufferCount; if (copyBytes != 0) { Buffer.BlockCopy(InternalBuffer, InternalOffset, buffer, offset, copyBytes); SkipBytes(copyBytes); } if (asyncRequest != null) { asyncRequest.CompleteUser((object)copyBytes); } return(copyBytes); } return(StartReading(buffer, offset, count, asyncRequest)); } catch (Exception e) { _SslState.FinishRead(null); failed = true; if (e is IOException) { throw; } throw new IOException(SR.net_io_read, e); } finally { // If sync request or exception. if (asyncRequest == null || failed) { _NestedRead = 0; } } }
// // Sync read method. // private int ProcessRead(byte[] buffer, int offset, int count) { ValidateParameters(buffer, offset, count); if (Interlocked.Exchange(ref _NestedRead, 1) == 1) { throw new NotSupportedException(SR.Format(SR.net_io_invalidnestedcall, "Read", "read")); } try { int copyBytes; if (InternalBufferCount != 0) { copyBytes = InternalBufferCount > count ? count : InternalBufferCount; if (copyBytes != 0) { Buffer.BlockCopy(InternalBuffer, InternalOffset, buffer, offset, copyBytes); SkipBytes(copyBytes); } return(copyBytes); } return(StartReading(buffer, offset, count)); } catch (Exception e) { _SslState.FinishRead(null); if (e is IOException) { throw; } throw new IOException(SR.net_io_read, e); } finally { _NestedRead = 0; } }
private async ValueTask <int> ReadAsyncInternal <TReadAdapter>(TReadAdapter adapter, Memory <byte> buffer) where TReadAdapter : ISslReadAdapter { if (Interlocked.Exchange(ref _nestedRead, 1) == 1) { throw new NotSupportedException(SR.Format(SR.net_io_invalidnestedcall, nameof(ReadAsync), "read")); } while (true) { int copyBytes; if (_decryptedBytesCount != 0) { copyBytes = CopyDecryptedData(buffer); _sslState.FinishRead(null); _nestedRead = 0; return(copyBytes); } copyBytes = await adapter.LockAsync(buffer).ConfigureAwait(false); try { if (copyBytes > 0) { return(copyBytes); } ResetReadBuffer(); int readBytes = await FillBufferAsync(adapter, SecureChannel.ReadHeaderSize).ConfigureAwait(false); if (readBytes == 0) { return(0); } int payloadBytes = _sslState.GetRemainingFrameSize(_internalBuffer, _internalOffset, readBytes); if (payloadBytes < 0) { throw new IOException(SR.net_frame_read_size); } readBytes = await FillBufferAsync(adapter, SecureChannel.ReadHeaderSize + payloadBytes).ConfigureAwait(false); if (readBytes < 0) { throw new IOException(SR.net_frame_read_size); } // At this point, readBytes contains the size of the header plus body. // Set _decrytpedBytesOffset/Count to the current frame we have (including header) // DecryptData will decrypt in-place and modify these to point to the actual decrypted data, which may be smaller. _decryptedBytesOffset = _internalOffset; _decryptedBytesCount = readBytes; SecurityStatusPal status = _sslState.DecryptData(_internalBuffer, ref _decryptedBytesOffset, ref _decryptedBytesCount); // Treat the bytes we just decrypted as consumed // Note, we won't do another buffer read until the decrypted bytes are processed ConsumeBufferedBytes(readBytes); if (status.ErrorCode != SecurityStatusPalErrorCode.OK) { byte[] extraBuffer = null; if (_decryptedBytesCount != 0) { extraBuffer = new byte[_decryptedBytesCount]; Buffer.BlockCopy(_internalBuffer, _decryptedBytesOffset, extraBuffer, 0, _decryptedBytesCount); _decryptedBytesCount = 0; } ProtocolToken message = new ProtocolToken(null, status); if (NetEventSource.IsEnabled) { NetEventSource.Info(null, $"***Processing an error Status = {message.Status}"); } if (message.Renegotiate) { if (!_sslState._sslAuthenticationOptions.AllowRenegotiation) { throw new IOException(SR.net_ssl_io_renego); } _sslState.ReplyOnReAuthentication(extraBuffer); // Loop on read. return(-1); } if (message.CloseConnection) { _sslState.FinishRead(null); return(0); } throw new IOException(SR.net_io_decrypt, message.GetException()); } } catch (Exception e) { _sslState.FinishRead(null); if (e is IOException) { throw; } throw new IOException(SR.net_io_read, e); } finally { _nestedRead = 0; } } }