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);
     }
 }
예제 #5
0
 public static void WriteCertificateEntry(ref WritableBuffer writer, byte[] certificate)
 {
     writer.Ensure(3);
     writer.Memory.Write24BitNumber(certificate.Length);
     writer.Advance(3);
     writer.Write(certificate);
 }
예제 #6
0
        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);
                }
            }
        }
예제 #9
0
 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));
 }
예제 #10
0
        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)));
        }
예제 #11
0
 public void Write(ReadOnlySpan <byte> input)
 {
     _innerBuffer.Ensure(input.Length);
     _innerBuffer.Write(input);
     _handshakeHash?.HashData(input);
     _bytesWritten  += input.Length;
     _bytesRemaining = _innerBuffer.Buffer.Length;
 }
예제 #12
0
        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);
        }
예제 #13
0
        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);
        }
예제 #14
0
        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();
        }
예제 #16
0
        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);
        }
예제 #17
0
        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);
        }
예제 #18
0
        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);
        }
예제 #19
0
        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);
        }
예제 #23
0
        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);
            }
        }
예제 #24
0
 public unsafe void WriteNonce(ref WritableBuffer buffer)
 {
     buffer.Ensure(8);
     buffer.Write(new Span <byte>((byte *)_ivPointer + 4, 8));
 }
예제 #25
0
        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);
        }
예제 #26
0
 private void WriteEndResponse(ref WritableBuffer buffer)
 {
     buffer.Write(_chunkedEndBytes, 0, _chunkedEndBytes.Length);
 }
예제 #27
0
 public void Write(Span <byte> data)
 {
     EnsureBuffer();
     _writableBuffer.Write(data);
 }
예제 #28
0
 public static void WriteEndChunkBytes(ref WritableBuffer start)
 {
     start.Write(_endChunkBytes.Array, _endChunkBytes.Offset, _endChunkBytes.Count);
 }
예제 #29
0
 private void WriteEndResponse(ref WritableBuffer buffer)
 {
     buffer.Write(_chunkedEndBytes.Slice());
 }
예제 #30
0
 private void WriteEndResponse(WritableBuffer buffer)
 {
     buffer.Write(_chunkedEndBytes);
 }