public unsafe static void WriteHex(this WritableBuffer buffer, int value) { if (value < 16) { buffer.Write(new Span <byte>(HexChars, value, 1)); return; } // TODO: Don't use 2 passes int length = 0; var val = value; while (val > 0) { val >>= 4; length++; } // Allocate space for writing the hex number byte *digits = stackalloc byte[length]; var span = new Span <byte>(digits, length); int index = span.Length - 1; while (value > 0) { span[index--] = HexChars[value & 0x0f]; value >>= 4; } // Write the span to the buffer buffer.Write(span); }
/// <summary> /// Writes a string as a RedisBulkString to the Stream. /// </summary> /// <param name="str">The string to write.</param> static void WriteRedisBulkString(WritableBuffer output, Utf8String str) { output.Write(RedisProtocol.Utf8BulkStringStart); output.Append(str.Length, TextEncoder.Utf8); output.Write(str); output.Write(RedisProtocol.Utf8CRLF); }
/// <summary> /// Writes an object to the Stream. /// </summary> /// <param name="value">The object to add.</param> static void WriteObject(WritableBuffer output, object value) { if (value == null) { output.Write(RedisProtocol.Utf8NullString); } var objType = value.GetType(); if (objType == typeof(string)) { WriteRedisBulkString(output, (Utf8String)(value as string)); } else if (objType == typeof(byte[])) { WriteRedisBulkString(output, new Utf8String(value as byte[])); } else if (objType == typeof(bool)) { WriteRedisBulkString(output, (bool)value ? RedisProtocol.Utf8RedisTrue : RedisProtocol.Utf8RedisFalse); } else { WriteRedisBulkString(output, (Utf8String)(value.ToString())); } }
unsafe void IMessageWriter.Write(ref WritableBuffer buffer) { if (count != 0) { buffer.Write(value, offset, count); } }
public static void WriteCertificateEntry(ref WritableBuffer writer, byte[] certificate) { writer.Ensure(3); writer.Memory.Write24BitNumber(certificate.Length); writer.Advance(3); writer.Write(certificate); }
public static int WriteBeginChunkBytes(ref WritableBuffer start, int dataCount) { var chunkSegment = BeginChunkBytes(dataCount); start.Write(chunkSegment.Array, chunkSegment.Offset, chunkSegment.Count); return(chunkSegment.Count); }
void IMessageWriter.WritePayload(WritableBuffer buffer) { if (count != 0) { buffer.Write(new Span <byte>(value, offset, count)); } }
protected void Copy(ReadOnlyBuffer readableBuffer, WritableBuffer writableBuffer) { _context.TimeoutControl.BytesRead(readableBuffer.Length); if (readableBuffer.IsSingleSpan) { writableBuffer.Write(readableBuffer.First.Span); } else { foreach (var memory in readableBuffer) { writableBuffer.Write(memory.Span); } } }
public static void WriteServerName(ref WritableBuffer buffer, IConnectionStateTls13 connectionState) { buffer.WriteBigEndian(ExtensionType.server_name); buffer.WriteBigEndian((ushort)(sizeof(ushort) + connectionState.ServerName.Length)); buffer.WriteBigEndian((ushort)connectionState.ServerName.Length); buffer.Write(Encoding.UTF8.GetBytes(connectionState.ServerName)); }
public static unsafe void WriteUInt64(WritableBuffer buffer, ulong value, byte preamble, int n) { if (n < 0 || n > 8) { throw new ArgumentOutOfRangeException(nameof(n)); } var mask = ~0UL << n; byte *scratch = stackalloc byte[16], writeHead = scratch; if ((value & mask) == 0) { // value fits inside the single byte, yay! preamble |= (byte)value; *writeHead++ = preamble; } else { preamble |= (byte)(~mask); *writeHead++ = preamble; value -= ~mask; const ulong MoreThanSevenBits = ~(127UL); while ((value & MoreThanSevenBits) != 0) { *writeHead++ = (byte)(0x80 | (value & 0x7F)); value >>= 7; } *writeHead++ = (byte)value; } buffer.Write(new Span <byte>(scratch, (int)(writeHead - scratch))); }
public void Write(ReadOnlySpan <byte> input) { _innerBuffer.Ensure(input.Length); _innerBuffer.Write(input); _handshakeHash?.HashData(input); _bytesWritten += input.Length; _bytesRemaining = _innerBuffer.Buffer.Length; }
public unsafe int SignHash(IHashProvider provider, SignatureScheme scheme, ref WritableBuffer writer, byte *message, int messageLength) { var span = new Span <byte>(message, messageLength); var result = _privateKey.SignData(span.ToArray(), GetHashName(scheme), GetPaddingMode(scheme)); writer.Write(result); return(result.Length); }
private void WriteBeginResponseHeaders(ref WritableBuffer buffer, ref bool autoChunk) { if (HasStarted) { return; } HasStarted = true; buffer.Write(_http11Bytes.Slice()); var status = ReasonPhrases.ToStatusBytes(StatusCode); buffer.Write(status.Slice()); autoChunk = !HasContentLength && !HasTransferEncoding && KeepAlive; ResponseHeaders.CopyTo(autoChunk, ref buffer); }
public unsafe void WritePublicKey(ref WritableBuffer keyBuffer) { var tmpBuffer = stackalloc byte[_keyExchangeSize + 8]; int resultSize; ExceptionHelper.CheckReturnCode(BCryptExportKey(_key, IntPtr.Zero, KeyBlobType.BCRYPT_ECCPUBLIC_BLOB, (IntPtr)tmpBuffer, _keyExchangeSize + 8, out resultSize, 0)); var keySpan = new Span <byte>(tmpBuffer + 8, resultSize - 8); keyBuffer.WriteBigEndian((byte)4); keyBuffer.Write(keySpan); }
/// <summary> /// Sends a command and it's parameters to the Stream. /// </summary> /// <param name="connection">The connection to the Redis Server.</param> /// <param name="command">The command.</param> /// <param name="parameters">The paramaters for the command.</param> public static async Task WriteCommandAsync(this RedisConnection connection, string command, IEnumerable <object> parameters = null) { if (command == null) { throw new ArgumentNullException(nameof(command)); } if (connection == null) { throw new ArgumentNullException(nameof(connection)); } var sizeOfCommandArray = 1 + (parameters?.Count() ?? 0); WritableBuffer output = connection.Output.Alloc(); // output the command array start output.Write(RedisProtocol.Utf8ArrayStart); output.Append(sizeOfCommandArray, TextEncoder.Utf8); output.Write(RedisProtocol.Utf8CRLF); // output the command var commandData = (Utf8String)command; WriteRedisBulkString(output, commandData); if (sizeOfCommandArray > 1) { foreach (object obj in parameters) { WriteObject(output, obj); } } await output.FlushAsync(); // TODO: should I call this? // connection.Output.Complete(); }
internal void WriteSessionKey(ref WritableBuffer writer, IConnectionState state) { writer.WriteBigEndian(_randomServiceId); writer.WriteBigEndian(_randomId); var sequence = System.Threading.Interlocked.Increment(ref _sequence); writer.WriteBigEndian(_nounceStart ^ sequence); writer.Write(_nounceBase.Slice(8)); //Now we have to encrypt the data writer.WriteBigEndian(state.CipherSuite.CipherCode); writer.WriteBigEndian(state.Version); //writer.Write(state.KeySchedule.ResumptionSecret); }
public static void WriteRecord(ref WritableBuffer buffer, RecordType recordType, Span <byte> plainText, State.IConnectionState state) { buffer.Ensure(RecordHeaderLength); if (state.WriteKey == null) { buffer.WriteBigEndian(recordType); buffer.WriteBigEndian(TlsRecordVersion); buffer.WriteBigEndian((ushort)plainText.Length); buffer.Write(plainText); return; } buffer.WriteBigEndian(RecordType.Application); buffer.WriteBigEndian(TlsRecordVersion); var totalSize = plainText.Length + state.WriteKey.Overhead + sizeof(RecordType); buffer.WriteBigEndian((ushort)totalSize); state.WriteKey.Encrypt(ref buffer, plainText, recordType); }
public unsafe int SignHash(IHashProvider provider, SignatureScheme scheme, ref WritableBuffer writer, byte *message, int messageLength) { var hash = provider.GetHashInstance(_hashType); hash.HashData(message, messageLength); var digest = new byte[hash.HashSize]; fixed(byte *dPtr = digest) { hash.InterimHash(dPtr, digest.Length); } var result = _privateKey.SignHash(digest); var enc = new System.Security.Cryptography.AsnEncodedData(_certificate.SignatureAlgorithm, result); writer.Write(result); return(result.Length); }
public unsafe int SignHash(IHashProvider provider, SignatureScheme scheme, ref WritableBuffer writer, byte *message, int messageLength) { var hash = provider.GetHashInstance(_hashType); hash.HashData(message, messageLength); var digest = new byte[hash.HashSize]; fixed(byte *dPtr = digest) { hash.InterimHash(dPtr, digest.Length); } writer.Ensure(_privateKey.KeySize); var result = _privateKey.SignHash(digest); writer.Write(result); return(result.Length); }
internal static unsafe SecurityStatus Decrypt <T>(this T context, ReadableBuffer buffer, WritableBuffer decryptedData) where T : ISecureContext { void *pointer; if (buffer.IsSingleSpan) { buffer.First.TryGetPointer(out pointer); } else { if (buffer.Length > SecurityContext.MaxStackAllocSize) { throw new OverflowException($"We need to create a buffer on the stack of size {buffer.Length} but the max is {SecurityContext.MaxStackAllocSize}"); } byte * tmpBuffer = stackalloc byte[buffer.Length]; Span <byte> span = new Span <byte>(tmpBuffer, buffer.Length); buffer.CopyTo(span); pointer = tmpBuffer; } int offset = 0; int count = buffer.Length; var secStatus = DecryptMessage(pointer, ref offset, ref count, context.ContextHandle); if (buffer.IsSingleSpan) { buffer = buffer.Slice(offset, count); decryptedData.Append(ref buffer); } else { decryptedData.Ensure(buffer.Length); decryptedData.Write(new Span <byte>(pointer, buffer.Length)); } return(secStatus); }
public void CopyTo(bool chunk, ref WritableBuffer buffer) { foreach (var header in _headers) { buffer.Write(_headersStartBytes.Slice()); WritableBufferExtensions.WriteAsciiString(ref buffer, header.Key); buffer.Write(_headersSeperatorBytes.Slice()); WritableBufferExtensions.WriteAsciiString(ref buffer, header.Value); } if (chunk) { buffer.Write(_chunkedHeaderBytes.Slice()); } buffer.Write(_serverHeaderBytes.Slice()); var date = _dateHeaderValueManager.GetDateHeaderValues().Bytes; buffer.Write(date.Slice()); buffer.Write(_headersEndBytes.Slice()); }
public void CopyTo(bool chunk, WritableBuffer buffer) { foreach (var header in _headers) { buffer.Write(_headersStartBytes); buffer.Append(header.Key, SymbolTable.InvariantUtf8); buffer.Write(_headersSeperatorBytes); buffer.Append(header.Value.ToString(), SymbolTable.InvariantUtf8); } if (chunk) { buffer.Write(_chunkedHeaderBytes); } buffer.Write(_serverHeaderBytes); var date = _dateHeaderValueManager.GetDateHeaderValues().Bytes; buffer.Write(date); buffer.Write(_headersEndBytes); }
private async Task ReceiveFromSocketAndPushToWriterAsync() { SocketAsyncEventArgs args = null; try { // wait for someone to be interested in data before we // start allocating buffers and probing the socket args = GetOrCreateSocketAsyncEventArgs(); while (!_stopping) { bool haveWriteBuffer = false; WritableBuffer buffer = default(WritableBuffer); var initialSegment = default(ArraySegment <byte>); try { int bytesFromInitialDataBuffer = 0; if (Socket.Available == 0) { // now, this gets a bit messy unfortunately, because support for the ideal option // (zero-length reads) is platform dependent switch (_bufferStyle) { case BufferStyle.Unknown: try { initialSegment = await ReceiveInitialDataUnknownStrategyAsync(args); } catch { initialSegment = default(ArraySegment <byte>); } if (initialSegment.Array == null) { continue; // redo from start } break; case BufferStyle.UseZeroLengthBuffer: // if we already have a buffer, use that (but: zero count); otherwise use a shared // zero-length; this avoids constantly changing the buffer that the args use, which // avoids some overheads args.SetBuffer(args.Buffer ?? _zeroLengthBuffer, 0, 0); // await async for the io work to be completed await Socket.ReceiveSignalAsync(args); break; case BufferStyle.UseSmallBuffer: // We need to do a speculative receive with a *cheap* buffer while we wait for input; it would be *nice* if // we could do a zero-length receive, but this is not supported equally on all platforms (fine on Windows, but // linux hates it). The key aim here is to make sure that we don't tie up an entire block from the memory pool // waiting for input on a socket; fine for 1 socket, not so fine for 100,000 sockets // do a short receive while we wait (async) for data initialSegment = LeaseSmallBuffer(); args.SetBuffer(initialSegment.Array, initialSegment.Offset, initialSegment.Count); // await async for the io work to be completed await Socket.ReceiveSignalAsync(args); break; } if (args.SocketError != SocketError.Success) { throw new SocketException((int)args.SocketError); } // note we can't check BytesTransferred <= 0, as we always // expect 0; but if we returned, we expect data to be // buffered *on the socket*, else EOF if ((bytesFromInitialDataBuffer = args.BytesTransferred) <= 0) { if (ReferenceEquals(initialSegment.Array, _zeroLengthBuffer)) { // sentinel value that means we should just // consume sync (we expect there to be data) initialSegment = default(ArraySegment <byte>); } else { // socket reported EOF RecycleSmallBuffer(ref initialSegment); } if (Socket.Available == 0) { // yup, definitely an EOF break; } } } // note that we will try to coalesce things here to reduce the number of flushes; we // certainly want to coalesce the initial buffer (from the speculative receive) with the initial // data, but we probably don't want to buffer indefinitely; for now, it will buffer up to 4 pages // before flushing (entirely arbitrarily) - might want to make this configurable later buffer = _input.Writer.Alloc(SmallBufferSize * 2); haveWriteBuffer = true; const int FlushInputEveryBytes = 4 * MemoryPool.MaxPooledBlockLength; if (initialSegment.Array != null) { // need to account for anything that we got in the speculative receive if (bytesFromInitialDataBuffer != 0) { buffer.Write(new Span <byte>(initialSegment.Array, initialSegment.Offset, bytesFromInitialDataBuffer)); } // make the small buffer available to other consumers RecycleSmallBuffer(ref initialSegment); } bool isEOF = false; while (Socket.Available != 0 && buffer.BytesWritten < FlushInputEveryBytes) { buffer.Ensure(); // ask for *something*, then use whatever is available (usually much much more) SetBuffer(buffer.Buffer, args); // await async for the io work to be completed await Socket.ReceiveSignalAsync(args); // either way, need to validate if (args.SocketError != SocketError.Success) { throw new SocketException((int)args.SocketError); } int len = args.BytesTransferred; if (len <= 0) { // socket reported EOF isEOF = true; break; } // record what data we filled into the buffer buffer.Advance(len); } if (isEOF) { break; } } finally { RecycleSmallBuffer(ref initialSegment); if (haveWriteBuffer) { _stopping = (await buffer.FlushAsync()).IsCompleted; } } } _input.Writer.Complete(); } catch (Exception ex) { // don't trust signal after an error; someone else could // still have it and invoke Set if (args != null) { args.UserToken = null; } _input?.Writer.Complete(ex); } finally { try { Socket.Shutdown(SocketShutdown.Receive); } catch { } RecycleSocketAsyncEventArgs(args); } }
public unsafe void WriteNonce(ref WritableBuffer buffer) { buffer.Ensure(8); buffer.Write(new Span <byte>((byte *)_ivPointer + 4, 8)); }
public unsafe void Encrypt(ref WritableBuffer buffer, ReadableBuffer plainText, RecordType recordType) { var cInfo = new BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO(); cInfo.dwInfoVersion = 1; cInfo.cbSize = sizeof(BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO); cInfo.cbNonce = _iVLength; cInfo.pbNonce = _ivPointer; var iv = stackalloc byte[_blockLength]; var macRecord = stackalloc byte[_maxTagLength]; var tag = stackalloc byte[_overhead]; cInfo.dwFlags = AuthenticatedCipherModeInfoFlags.ChainCalls; cInfo.cbMacContext = _maxTagLength; cInfo.pbMacContext = (IntPtr)macRecord; cInfo.pbTag = (IntPtr)tag; cInfo.cbTag = _overhead; cInfo.pbAuthData = _ivPointer; cInfo.cbAuthData = 0; var totalDataLength = plainText.Length; int outLength; GCHandle inHandle, outHandle; foreach (var b in plainText) { totalDataLength = totalDataLength - b.Length; if (b.Length == 0 && totalDataLength > 0) { continue; } buffer.Ensure(b.Length); var inPtr = b.GetPointer(out inHandle); var outPtr = buffer.Memory.GetPointer(out outHandle); try { outLength = buffer.Memory.Length; int amountWritten; Interop.Windows.ExceptionHelper.CheckReturnCode(BCryptEncrypt(_key, inPtr, b.Length, &cInfo, iv, _blockLength, outPtr, b.Length, out amountWritten, 0)); cInfo.dwFlags = AuthenticatedCipherModeInfoFlags.InProgress; buffer.Advance(amountWritten); } finally { if (inHandle.IsAllocated) { inHandle.Free(); } if (outHandle.IsAllocated) { outHandle.Free(); } } if (totalDataLength == 0) { break; } } buffer.Ensure(Overhead + sizeof(RecordType)); var writePtr = buffer.Memory.GetPointer(out outHandle); outLength = buffer.Memory.Length; if (_paddingSize == 0) { cInfo.dwFlags = AuthenticatedCipherModeInfoFlags.None; } Interop.Windows.ExceptionHelper.CheckReturnCode(BCryptEncrypt(_key, &recordType, sizeof(RecordType), &cInfo, iv, _iVLength, writePtr, buffer.Memory.Length, out outLength, 0)); buffer.Advance(outLength); if (_paddingSize > 0) { outLength = _paddingSize; writePtr = buffer.Memory.GetPointer(out outHandle); cInfo.dwFlags = AuthenticatedCipherModeInfoFlags.None; Interop.Windows.ExceptionHelper.CheckReturnCode(BCryptEncrypt(_key, (void *)s_zeroBuffer, _paddingSize, &cInfo, iv, _iVLength, writePtr, buffer.Memory.Length, out outLength, 0)); buffer.Advance(outLength); } writePtr = buffer.Memory.GetPointer(out outHandle); buffer.Write(new Span <byte>(tag, _overhead)); buffer.Advance(_overhead); }
private void WriteEndResponse(ref WritableBuffer buffer) { buffer.Write(_chunkedEndBytes, 0, _chunkedEndBytes.Length); }
public void Write(Span <byte> data) { EnsureBuffer(); _writableBuffer.Write(data); }
public static void WriteEndChunkBytes(ref WritableBuffer start) { start.Write(_endChunkBytes.Array, _endChunkBytes.Offset, _endChunkBytes.Count); }
private void WriteEndResponse(ref WritableBuffer buffer) { buffer.Write(_chunkedEndBytes.Slice()); }
private void WriteEndResponse(WritableBuffer buffer) { buffer.Write(_chunkedEndBytes); }