예제 #1
0
        public static async ValueTask SendMessageAsync <T>(this WebSocket socket, IMessageWriter writer, T message, WebSocketMessageType type, CancellationToken token = default)
        {
            _buffer.Clear();
            writer.WriteMessage(message, _buffer);

            await socket.SendAsync(_buffer.WrittenMemory, type, true, token);
        }
예제 #2
0
        /// <summary>
        /// Resets the <see cref="Utf8JsonWriter"/> internal state so that it can be re-used with the new instance of <see cref="Stream" />.
        /// </summary>
        /// <param name="utf8Json">An instance of <see cref="Stream" /> used as a destination for writing JSON text into.</param>
        /// <remarks>
        /// The <see cref="Utf8JsonWriter"/> will continue to use the original writer options
        /// but now write to the passed in <see cref="Stream" /> as the new destination.
        /// </remarks>
        /// <exception cref="ArgumentNullException">
        /// Thrown when the instance of <see cref="Stream" /> that is passed in is null.
        /// </exception>
        /// <exception cref="ObjectDisposedException">
        ///   The instance of <see cref="Utf8JsonWriter"/> has been disposed.
        /// </exception>
        public void Reset(Stream utf8Json)
        {
            CheckNotDisposed();

            if (utf8Json == null)
            {
                throw new ArgumentNullException(nameof(utf8Json));
            }
            if (!utf8Json.CanWrite)
            {
                throw new ArgumentException(SR.StreamNotWritable);
            }

            _stream = utf8Json;
            if (_arrayBufferWriter == null)
            {
                _arrayBufferWriter = new ArrayBufferWriter <byte>();
            }
            else
            {
                _arrayBufferWriter.Clear();
            }
            _output = null;

            ResetHelper();
        }
예제 #3
0
        public async Task RunAndBlockAsync(Uri url, CancellationToken cancel)
        {
            var error        = "Error.";
            var bufferWriter = new ArrayBufferWriter <byte>(CHUNK_SIZE);

            try
            {
                using (_ws = new ClientWebSocket())
                {
                    await _ws.ConnectAsync(url, cancel).ConfigureAwait(false);

                    // WebsocketConnected!.Invoke(this);

                    while (true)
                    {
                        var result = await _ws.ReceiveAsync(bufferWriter.GetMemory(CHUNK_SIZE), cancel);

                        bufferWriter.Advance(result.Count);
                        if (result.MessageType == WebSocketMessageType.Close)
                        {
                            var closeMessage = CloseCodes.GetErrorCodeMessage((int?)_ws.CloseStatus ?? 0).Message;
                            error = $"Websocket closed ({_ws.CloseStatus}): {_ws.CloseStatusDescription} {closeMessage}";
                            break;
                        }

                        if (result.EndOfMessage)
                        {
                            var pr   = PayloadReceived;
                            var data = bufferWriter.WrittenMemory.ToArray();
                            bufferWriter.Clear();

                            if (!(pr is null))
                            {
                                await pr.Invoke(data);
                            }
                        }
                    }
                }
            }
            catch (WebSocketException ex)
            {
                Log.Warning("Disconnected, check your internet connection...");
                Log.Debug(ex, "Websocket Exception in websocket client");
            }
            catch (OperationCanceledException)
            {
                // ignored
            }
            catch (Exception ex)
            {
                Log.Error(ex, "Error in websocket client. {Message}", ex.Message);
            }
            finally
            {
                bufferWriter.Clear();
                _ws = null;
                await ClosedAsync(error).ConfigureAwait(false);
            }
        }
 public void Deserialize_LowAllocate()
 {
     for (int i = 0; i < 10000; i++)
     {
         buffer.Clear();
         var deserializer = CryptoDtoDeserializer.DeserializeIgnoreSequence(buffer, remoteChannel, cryptoDtoPacket);
     }
 }
예제 #5
0
 /// <summary>
 /// Resets the <see cref="Utf8JsonWriter"/> internal state so that it can be re-used.
 /// </summary>
 /// <remarks>
 /// The <see cref="Utf8JsonWriter"/> will continue to use the original writer options
 /// and the original output as the destination (either <see cref="IBufferWriter{Byte}" /> or <see cref="Stream" />).
 /// </remarks>
 public void Reset()
 {
     if (_arrayBufferWriter != null)
     {
         _arrayBufferWriter.Clear();
     }
     ResetHelper();
 }
        public async Task WriteAndCopyToStreamAsync()
        {
            var output = new ArrayBufferWriter <byte>();

            WriteData(output, 100);

            using var memStream = new MemoryStream(100);

            Assert.Equal(100, output.WrittenCount);

            ReadOnlyMemory <byte> outputMemory = output.WrittenMemory.ToArray();

            ReadOnlyMemory <byte> transient = output.WrittenMemory;

            Assert.True(transient.Span[0] != 0);

            await memStream.WriteAsync(transient.ToArray(), 0, transient.Length);

            output.Clear();

            Assert.True(transient.Span[0] == 0);

            Assert.Equal(0, output.WrittenCount);
            byte[] streamOutput = memStream.ToArray();

            Assert.True(ReadOnlyMemory <byte> .Empty.Span.SequenceEqual(output.WrittenMemory.Span));
            Assert.True(ReadOnlySpan <byte> .Empty.SequenceEqual(output.WrittenMemory.Span));

            Assert.Equal(outputMemory.Length, streamOutput.Length);
            Assert.True(outputMemory.Span.SequenceEqual(streamOutput));
        }
예제 #7
0
        /// <summary>
        /// Resets the <see cref="Utf8JsonWriter"/> internal state so that it can be re-used.
        /// </summary>
        /// <remarks>
        /// The <see cref="Utf8JsonWriter"/> will continue to use the original writer options
        /// and the original output as the destination (either <see cref="IBufferWriter{Byte}" /> or <see cref="Stream" />).
        /// </remarks>
        /// <exception cref="ObjectDisposedException">
        ///   The instance of <see cref="Utf8JsonWriter"/> has been disposed.
        /// </exception>
        public void Reset()
        {
            CheckNotDisposed();

            _arrayBufferWriter?.Clear();
            ResetHelper();
        }
예제 #8
0
        /// <summary>
        /// Reads messages from web socket and writes them to channel.
        /// Complete() will be called on channel writer when a close message is received from socket.
        /// On exception or cancellation, channel writer will not be set to complete.
        /// </summary>
        /// <exception cref="WebSocketException"></exception>
        /// <exception cref="OperationCanceledException"></exception>
        internal static async Task ReceiveLoop(this ChannelWriter <Message> channelWriter, WebSocket socket, CancellationToken cancellationToken)
        {
            Requires.NotNull(channelWriter, nameof(channelWriter));
            Requires.NotNull(socket, nameof(socket));

            var bufferWriter = new ArrayBufferWriter <byte>();

            while (await ReadMessageAsync().ConfigureAwait(false))
            {
            }

            async Task <bool> ReadMessageAsync()
            {
                ValueWebSocketReceiveResult result;

                do
                {
                    result = await socket.ReceiveAsync(bufferWriter.GetMemory(), cancellationToken).ConfigureAwait(false);

                    switch (result.MessageType)
                    {
                    case WebSocketMessageType.Text:
                    case WebSocketMessageType.Binary:
                        bufferWriter.Advance(result.Count);
                        break;

                    case WebSocketMessageType.Close:
                        return(false);
                    }
                } while (!result.EndOfMessage);

                channelWriter.TryWrite(new Message(Convert(result.MessageType), bufferWriter.WrittenSpan.ToArray()));
                bufferWriter.Clear();

                return(true);
예제 #9
0
        private const uint hpSMT = 0x534D5400u; // SMT

        public ReadOnlyMemory <byte> Sign(KeyPair keyPair, out Hash256 hash)
        {
            Signers       = null;
            TxnSignature  = null;
            SigningPubKey = keyPair.PublicKey.GetCanoncialBytes();
            var bufferWriter = new ArrayBufferWriter <byte>();

            System.Buffers.Binary.BinaryPrimitives.WriteUInt32BigEndian(bufferWriter.GetSpan(4), hpSTX);
            bufferWriter.Advance(4);
            Serialize(bufferWriter, true);

            // Calculate signature and serialize again
            TxnSignature = keyPair.Sign(bufferWriter.WrittenSpan);
            bufferWriter.Clear();

            System.Buffers.Binary.BinaryPrimitives.WriteUInt32BigEndian(bufferWriter.GetSpan(4), hpTXN);
            bufferWriter.Advance(4);

            Serialize(bufferWriter, false);

            using (var sha512 = System.Security.Cryptography.SHA512.Create())
            {
                Span <byte> hashSpan = stackalloc byte[64];
                sha512.TryComputeHash(bufferWriter.WrittenSpan, hashSpan, out var bytesWritten);
                hash = new Hash256(hashSpan.Slice(0, 32));
            }

            return(bufferWriter.WrittenMemory.Slice(4));
        }
예제 #10
0
        private void Grow(int requiredSize)
        {
            if (_memory.Length == 0)
            {
                FirstGrow(requiredSize);
                return;
            }

            int sizeHint = Math.Max(DefaultGrowthSize, requiredSize);

            Debug.Assert(BytesPending != 0);

            if (_stream != null)
            {
                Debug.Assert(_arrayBufferWriter != null);

                _arrayBufferWriter.Advance(BytesPending);

                Debug.Assert(BytesPending == _arrayBufferWriter.WrittenCount);

                _stream.Write(_arrayBufferWriter.WrittenSpan);

                _arrayBufferWriter.Clear();

                _memory = _arrayBufferWriter.GetMemory(sizeHint);

                Debug.Assert(_memory.Length >= sizeHint);
            }
            else
            {
                Debug.Assert(_output != null);

                _output.Advance(BytesPending);

                _memory = _output.GetMemory(sizeHint);

                if (_memory.Length < sizeHint)
                {
                    // ToDo - replace this
                    throw new Exception("Need more Span size");
                }
            }

            BytesCommitted += BytesPending;
            BytesPending    = 0;
        }
예제 #11
0
            public T Clone <T>(T item)
            {
                _bufferWriter.Clear();
                _jsonWriter.Reset();

                JsonSerializer.Serialize(_jsonWriter, item, _options);

                return(JsonSerializer.Deserialize <T>(_bufferWriter.WrittenSpan, _options));
            }
예제 #12
0
        public static void RenderToBuffer()
        {
            const string placeholder = "%s";
            var template = "Hello, %s!%s".AsTemplate(placeholder);
            var writer = new ArrayBufferWriter<char>();
            template.Render(writer, Rewrite);
            Equal("Hello, world!!", writer.BuildString());

            writer.Clear();
            template = "%s%s".AsTemplate(placeholder);
            template.Render(writer, Rewrite);
            Equal("world!", writer.BuildString());

            writer.Clear();
            template = "%s!!%s".AsTemplate(placeholder);
            template.Render(writer, Rewrite);
            Equal("world!!!", writer.BuildString());
        }
예제 #13
0
        //Can we change the ChaCha20Poly1305 input to some kind of ICrypto interface or action with 'Encrypt' and 'Decrypt'?
        private void Pack(IBufferWriter <byte> output, CryptoDtoHeaderDto header, ChaCha20Poly1305 crypto, ReadOnlySpan <byte> dtoNameBuffer, ReadOnlySpan <byte> dtoBuffer)
        {
            lock (bufferLock)
            {
                headerBuffer.Clear();
                MessagePackSerializer.Serialize(headerBuffer, header);
                ReadOnlySpan <byte> headerBytes = headerBuffer.WrittenSpan;

                ushort headerLength = (ushort)headerBytes.Length;
                BinaryPrimitives.WriteUInt16LittleEndian(headerLengthBytes, headerLength);
                ushort dtoNameLength = (ushort)dtoNameBuffer.Length;
                BinaryPrimitives.WriteUInt16LittleEndian(dtoNameLengthBytes, dtoNameLength);
                ushort dtoLength = (ushort)dtoBuffer.Length;
                BinaryPrimitives.WriteUInt16LittleEndian(dtoLengthBytes, dtoLength);

                switch (header.Mode)
                {
                case CryptoDtoMode.ChaCha20Poly1305:
                {
                    int adLength = 2 + headerLength;
                    int aeLength = 2 + dtoNameLength + 2 + dtoLength;

                    // Copy data into associated data buffer
                    adBuffer.Clear();
                    adBuffer.Write(headerLengthBytes);
                    adBuffer.Write(headerBytes);

                    // Copy data into authenticated encryption buffer
                    aeBuffer.Clear();
                    aeBuffer.Write(dtoNameLengthBytes);
                    aeBuffer.Write(dtoNameBuffer);
                    aeBuffer.Write(dtoLengthBytes);
                    aeBuffer.Write(dtoBuffer);

                    Span <byte> nonceSpan = new Span <byte>(nonceBytes);
                    BinaryPrimitives.WriteUInt64LittleEndian(nonceSpan.Slice(4), header.Sequence);

                    var adSpan         = adBuffer.WrittenSpan;
                    var aeSpan         = aeBuffer.WrittenSpan;
                    var cipherTextSpan = cipherText.Span.Slice(0, aeLength);
                    cipherTextSpan.Clear();
                    Span <byte> tagSpan = tagBuffer;
                    tagSpan.Clear();
                    crypto.Encrypt(nonceSpan, aeSpan, cipherTextSpan, tagSpan, adSpan);

                    output.Write(adSpan);
                    output.Write(cipherTextSpan);
                    output.Write(tagSpan);
                    break;
                }

                default:
                    throw new CryptographicException("Mode not recognised");
                }
            }
        }
예제 #14
0
 // Hint for callers using ArrayBufferWriter<byte> - output.WrittenSpan contains the serialised data
 public void Serialize <T>(IBufferWriter <byte> output, CryptoDtoChannel channel, CryptoDtoMode mode, T dto)
 {
     lock (bufferLock)
     {
         ReadOnlySpan <byte> dtoNameBuffer = GetDtoNameBytes <T>();
         dtoBuffer.Clear();
         MessagePackSerializer.Serialize(dtoBuffer, dto);
         Pack(output, channel, mode, dtoNameBuffer, dtoBuffer.WrittenSpan);
     }
 }
 public void Reset()
 {
     PayloadLength = null;
     if (_bufferWriter != null)
     {
         // Reuse existing buffer writer
         _bufferWriter.Clear();
     }
     _array = null;
     _state = InternalState.Initialized;
 }
예제 #16
0
        public void SerializeToBufferLessTimes()
        {
            var buffer = new ArrayBufferWriter <byte>();
            var obj    = new SampleObject();

            for (var i = 0; i < 3; i++)
            {
                buffer.Clear();
                MessagePackSerializer.Serialize(buffer, obj);
            }
        }
예제 #17
0
        public void Init(ICharMetric cdi)
        {
            _buffer.Clear();

            _indexOnLine          = cdi.IndexEachLine;
            _location             = new Point2D((int)cdi.Left, cdi.Y);
            _buffer.GetSpan(1)[0] = cdi.Char;
            _buffer.Advance(1);
            _font  = cdi.Font;
            _color = cdi.Color;
        }
예제 #18
0
        public void Reset()
        {
            _compressionProvider = ResolveCompressionProvider();

            _payloadLength = null;
            if (_bufferWriter != null)
            {
                // Reuse existing buffer writer
                _bufferWriter.Clear();
            }
            _state = InternalState.Initialized;
        }
예제 #19
0
 public void Pack_ZeroAllocate()
 {
     for (int i = 0; i < 10000; i++)
     {
         if (cryptoChannelStore.TryGetChannel("Benchmark", out CryptoDtoChannel channel))
         {
             buffer.Clear();
             serializer.Pack(buffer, channel, CryptoDtoMode.ChaCha20Poly1305, typeNameBytes, dtoBytes);
             var packetBytes = buffer.WrittenSpan;
         }
     }
 }
예제 #20
0
        public ReadOnlyMemory <byte> Sign(ReadOnlySpan <ValueTuple <AccountId, KeyPair> > signers, out Hash256 hash)
        {
            var signerArray = new Signer[signers.Length];

            for (int i = 0; i < signers.Length; ++i)
            {
                var signer = new Signer();
                signer.Account       = signers[i].Item1;
                signer.SigningPubKey = signers[i].Item2.PublicKey.GetCanoncialBytes();
                signer.TxnSignature  = null;
                signerArray[i]       = signer;
            }
            Signers       = Array.AsReadOnly(signerArray);
            TxnSignature  = null;
            SigningPubKey = null;
            var bufferWriter = new ArrayBufferWriter <byte>();

            // Calculate signatures and then serialize again
            for (int i = 0; i < signers.Length; ++i)
            {
                // For each signer we need to write the account being signed for the the buffer, sign that then rewind
                System.Buffers.Binary.BinaryPrimitives.WriteUInt32BigEndian(bufferWriter.GetSpan(4), hpSMT);
                bufferWriter.Advance(4);
                Serialize(bufferWriter, true);
                Signers[i].Account.CopyTo(bufferWriter.GetSpan(20));
                bufferWriter.Advance(20);

                signerArray[i].TxnSignature = signers[i].Item2.Sign(bufferWriter.WrittenSpan);
                bufferWriter.Clear();
            }

            Array.Sort <Signer>(signerArray, (x, y) => x.Account.CompareTo(y.Account));
            Signers = Array.AsReadOnly(signerArray);

            System.Buffers.Binary.BinaryPrimitives.WriteUInt32BigEndian(bufferWriter.GetSpan(4), hpTXN);
            bufferWriter.Advance(4);

            Serialize(bufferWriter, false);

            using (var sha512 = System.Security.Cryptography.SHA512.Create())
            {
                Span <byte> hashSpan = stackalloc byte[64];
                sha512.TryComputeHash(bufferWriter.WrittenSpan, hashSpan, out var bytesWritten);
                hash = new Hash256(hashSpan.Slice(0, 32));
            }

            return(bufferWriter.WrittenMemory.Slice(4));
        }
예제 #21
0
        public void TestHandshakeActThreeResponderSide(string actOneInput, string actThreeInput)
        {
            _noiseProtocol = GetResponderNoiseProtocol();

            var buffer = new ArrayBufferWriter <byte>();

            //read
            _noiseProtocol.Handshake(new ReadOnlySequence <byte>(actOneInput.ToByteArray()), buffer);
            buffer.Clear();

            //write
            _noiseProtocol.Handshake(new ReadOnlySequence <byte>(actThreeInput.ToByteArray()), buffer);

            Assert.Equal(buffer.WrittenCount, 0);
            Assert.Empty(buffer.WrittenSpan.ToArray());
        }
예제 #22
0
        public void Clear()
        {
            var output            = new ArrayBufferWriter <T>(256);
            int previousAvailable = output.FreeCapacity;

            WriteData(output, 2);
            Assert.True(output.FreeCapacity < previousAvailable);
            Assert.True(output.WrittenCount > 0);
            Assert.False(ReadOnlySpan <T> .Empty.SequenceEqual(output.WrittenSpan));
            Assert.False(ReadOnlyMemory <T> .Empty.Span.SequenceEqual(output.WrittenMemory.Span));
            Assert.True(output.WrittenSpan.SequenceEqual(output.WrittenMemory.Span));
            output.Clear();
            Assert.Equal(0, output.WrittenCount);
            Assert.True(ReadOnlySpan <T> .Empty.SequenceEqual(output.WrittenSpan));
            Assert.True(ReadOnlyMemory <T> .Empty.Span.SequenceEqual(output.WrittenMemory.Span));
            Assert.Equal(previousAvailable, output.FreeCapacity);
        }
예제 #23
0
        public void TestHandshakeActTwoInitiatorSide(string expectedInputHex)
        {
            _noiseProtocol = GetInitiatorNoiseProtocol();

            var buffer = new ArrayBufferWriter <byte>();

            //write
            _noiseProtocol.Handshake(new ReadOnlySequence <byte>(), buffer);
            buffer.Clear();

            //read & write
            _noiseProtocol.Handshake(new ReadOnlySequence <byte>(expectedInputHex.ToByteArray()), buffer);

            //encrypted null so nothing to decrypt
            Assert.Equal(buffer.WrittenCount, 66);
            Assert.NotEmpty(buffer.WrittenSpan.ToArray());
        }
예제 #24
0
        public async Task Write(object message)
        {
            _serializer.Serialize(_buffer, message);

            ReadOnlyMemory <byte> messageMemory = _buffer.WrittenMemory;

            (int messageSize, ReadOnlyMemory <byte> messageSizeMemory) = WriteMessageSize();

            _messageLogger.Log(messageSizeMemory);
            _messageLogger.Log(messageMemory);

            await _stream.WriteAsync(messageSizeMemory);

            await _stream.WriteAsync(messageMemory);

            _buffer.Clear();
        }
예제 #25
0
        public void TestHandshakeActThreeInitiatorSide(string actTwoInput, string expectedOutputHex)
        {
            _noiseProtocol = GetInitiatorNoiseProtocol();

            var buffer = new ArrayBufferWriter <byte>();

            //write
            _noiseProtocol.Handshake(new ReadOnlySequence <byte>(), buffer);
            buffer.Clear();

            //read & write
            _noiseProtocol.Handshake(new ReadOnlySequence <byte>(actTwoInput.ToByteArray()), buffer);

            var expectedOutput = expectedOutputHex.ToByteArray();

            Assert.Equal(buffer.WrittenCount, expectedOutput.Length);
            Assert.Equal(buffer.WrittenSpan.ToArray(), expectedOutput);
        }
        public int ReadMessageLength(ReadOnlySequence <byte> encryptedHeader) //TODO David add tests
        {
            if (_transport == null)
            {
                throw new InvalidOperationException("Must complete handshake before reading messages");
            }

            _inputHeaderCache.Clear();

            _transport.ReadMessage(encryptedHeader, _inputHeaderCache);

            ushort messageLengthDecrypted =
                BinaryPrimitives.ReadUInt16BigEndian(_inputHeaderCache
                                                     .WrittenSpan); // TODO Dan test header size bigger then 2 bytes

            // Return the message length plus the 16 byte mac data
            // the caller does not need to know the message has mac data
            return(messageLengthDecrypted + AEAD_TAG_SIZE);
        }
예제 #27
0
 public void Dispose()
 {
     writer.Dispose();
     buffer.Clear();
 }
예제 #28
0
            public string[] ReadHeaderLines()
            {
                if (State != ReaderState.Headers)
                {
                    throw new InvalidOperationException();
                }

                List <string> lines        = new List <string>();
                var           outputBuffer = new ArrayBufferWriter <byte>();

                if (endOfClearText)
                {
                    // If we were reading clear text before then we consumed
                    // the first two dashes of the separator.
                    outputBuffer.Write(new[] { (byte)'-', (byte)'-' });
                }

                for (; ;)
                {
                    var b = innerStream.ReadByte();
                    switch (b)
                    {
                    case -1:
                        return(Array.Empty <string>());

                    case '\n':
                        if (!ignoreNL)
                        {
                            goto case '\r';
                        }
                        ignoreNL = false;
                        break;

                    case '\r':
                        ignoreNL = b == '\r';

                        // Non-empty line
                        string?line = null;
                        if (outputBuffer.WrittenCount > 0)
                        {
                            line = Encoding.ASCII.GetString(outputBuffer.WrittenSpan);
                            outputBuffer.Clear();
                        }

                        if (!string.IsNullOrWhiteSpace(line))
                        {
                            lines.Add(line);
                        }
                        else if (lines.Count > 0)
                        {
                            // TODO: Verify the headers
                            headerEndLineLength = lines.First().Length - 2;     // -2 for BEGIN -> END

                            State =
                                !endOfClearText && Equals(lines.FirstOrDefault(), "-----BEGIN PGP SIGNED MESSAGE-----") ?
                                ReaderState.ClearText : ReaderState.Base64;
                            return(lines.ToArray());
                        }

                        break;

                    default:
                        outputBuffer.GetSpan(1)[0] = (byte)b;
                        outputBuffer.Advance(1);
                        break;
                    }
                }
            }
        // Currently supports https://github.com/grafana/loki/blob/master/docs/api.md#post-lokiapiv1push
        public void Format(IEnumerable <LogEvent> logEvents, ITextFormatter formatter, TextWriter output)
        {
            if (logEvents == null)
            {
                throw new ArgumentNullException(nameof(logEvents));
            }
            if (output == null)
            {
                throw new ArgumentNullException(nameof(output));
            }

            if (!logEvents.Any())
            {
                return;
            }

            var timestampOverride = SystemClock.Instance.GetCurrentInstant();

            // process labels for grouping/sorting
            var sortedStreams = logEvents
                                .GroupBy(x => x.Properties
                                         .Where(prop => _labelNames.Contains(prop.Key))
                                         .Select(prop => new KeyValuePair <string, string>(prop.Key, cleanseString(prop.Value.ToString())))
                                         .Concat(_labelNames.Contains("level") ? new[] { new KeyValuePair <string, string>("level", GetLevel(x.Level)) } : new KeyValuePair <string, string>[] { })
                                         .Concat(_globalLabels).ToHashSet(), new HashSetComparer())
                                .Select(stream => new KeyValuePair <HashSet <KeyValuePair <string, string> >, IOrderedEnumerable <LogEvent> >(stream.Key, stream.OrderBy(log => log.Timestamp)));

            var logLineBuffer = new ArrayBufferWriter <byte>();

            using var logLineJsonWriter = new Utf8JsonWriter(logLineBuffer);
            var outputBuffer = new ArrayBufferWriter <byte>();

            using var jsonWriter = new Utf8JsonWriter(outputBuffer);

            jsonWriter.WriteStartObject();
            jsonWriter.WriteStartArray("streams");

            foreach (var stream in sortedStreams)
            {
                jsonWriter.WriteStartObject();
                jsonWriter.WriteStartObject("stream");

                foreach (var label in stream.Key)
                {
                    jsonWriter.WriteString(label.Key, label.Value);
                }

                jsonWriter.WriteEndObject();

                jsonWriter.WriteStartArray("values");

                foreach (var logEvent in stream.Value)
                {
                    jsonWriter.WriteStartArray();

                    var timestamp = this._preserveTimestamps ? Instant.FromDateTimeOffset(logEvent.Timestamp) : timestampOverride;
                    jsonWriter.WriteStringValue((timestamp.ToUnixTimeTicks() * 100).ToString());

                    // Construct a json object for the log line
                    logLineJsonWriter.WriteStartObject();
                    logLineJsonWriter.WriteString("message", logEvent.RenderMessage());

                    foreach (var property in logEvent.Properties)
                    {
                        logLineJsonWriter.WriteString(property.Key, cleanseString(property.Value.ToString()));
                    }

                    if (this._preserveTimestamps == false)
                    {
                        logLineJsonWriter.WriteString("timestamp", Instant.FromDateTimeOffset(logEvent.Timestamp).ToString());
                    }

                    if (logEvent.Exception != null)
                    {
                        var sb = new StringBuilder();
                        var e  = logEvent.Exception;
                        while (e != null)
                        {
                            sb.AppendLine(e.Message);
                            sb.AppendLine(e.StackTrace);
                            e = e.InnerException;
                        }
                        logLineJsonWriter.WriteString("exception", sb.ToString());
                    }

                    logLineJsonWriter.WriteEndObject();
                    logLineJsonWriter.Flush();
                    jsonWriter.WriteStringValue(Encoding.UTF8.GetString(logLineBuffer.WrittenSpan));
                    jsonWriter.WriteEndArray();
                    logLineJsonWriter.Reset();
                    logLineBuffer.Clear();
                }

                jsonWriter.WriteEndArray();
                jsonWriter.WriteEndObject();
            }

            jsonWriter.WriteEndArray();
            jsonWriter.WriteEndObject();
            jsonWriter.Flush();

            output.Write(Encoding.UTF8.GetString(outputBuffer.WrittenSpan));
        }
예제 #30
0
            public int ReadClearText(Span <byte> buffer)
            {
                if (State != ReaderState.ClearText)
                {
                    throw new InvalidOperationException();
                }

                // We usually try to output one character for one input character
                // but new line and dash sequences can produce up to 4 characters
                // at once, so size the buffer to accommodate that. We can also
                // overshoot the buffer with pending whitespace.
                var outputBuffer = new ArrayBufferWriter <byte>(buffer.Length + 3);

                if (pendingData != null)
                {
                    outputBuffer.Write(pendingData);
                }

                while (!endOfClearText && outputBuffer.WrittenCount < buffer.Length)
                {
                    var b = innerStream.ReadByte();

                    // End of stream
                    if (b == -1)
                    {
                        break;
                    }

                    switch (b)
                    {
                    case ' ':
                    case '\t':
                        // Collect pending whitespace because it could be trailing whitespace
                        // at end of line
                        pendingWhitespace.GetSpan(1)[0] = (byte)b;
                        pendingWhitespace.Advance(1);
                        break;

                    case '\r':
                    case '\n':
                        // Ignore \n that was still part of header
                        if (ignoreNL && b == '\n')
                        {
                            ignoreNL = false;
                            break;
                        }

                        // Discard any pending whitespace
                        pendingWhitespace.Clear();

                        // Read next character after the new line
                        var nextB = innerStream.ReadByte();
                        if (b == '\r' && nextB == '\n')
                        {
                            nextB = innerStream.ReadByte();
                        }

                        if (nextB == '-')
                        {
                            // New line followed byt dash. Now we are looking either at the end of
                            // clear text or a dash escape
                            nextB = innerStream.ReadByte();
                            if (nextB == ' ')
                            {
                                // Dash escape, remove it and flush the new line
                                outputBuffer.Write(new[] { (byte)'\r', (byte)'\n' });
                            }
                            else if (nextB == '-')
                            {
                                // Possible end of clear text
                                endOfClearText = true;
                                break;
                            }
                            else
                            {
                                // Invalid clear text, flush the new lind and output it
                                var clearText = outputBuffer.GetSpan(4);
                                clearText[0] = (byte)'\r';
                                clearText[1] = (byte)'\n';
                                clearText[2] = (byte)'-';
                                clearText[3] = (byte)nextB;
                                outputBuffer.Advance(4);
                            }
                        }
                        else
                        {
                            // Flush the new line
                            outputBuffer.Write(new[] { (byte)'\r', (byte)'\n' });

                            if (nextB == '\r' || nextB == '\n')
                            {
                                b = nextB;
                                goto case '\r';
                            }
                            else if (nextB == ' ' || nextB == '\t')
                            {
                                pendingWhitespace.GetSpan(1)[0] = (byte)nextB;
                                pendingWhitespace.Advance(1);
                            }
                            else
                            {
                                outputBuffer.GetSpan(1)[0] = (byte)nextB;
                                outputBuffer.Advance(1);
                            }
                        }
                        break;

                    default:
                        // Flush any pending whitespace
                        if (pendingWhitespace.WrittenCount > 0)
                        {
                            outputBuffer.Write(pendingWhitespace.WrittenSpan);
                            pendingWhitespace.Clear();
                        }

                        outputBuffer.GetSpan(1)[0] = (byte)b;
                        outputBuffer.Advance(1);
                        break;
                    }
                }

                if (outputBuffer.WrittenCount > buffer.Length)
                {
                    pendingData = outputBuffer.WrittenSpan.Slice(buffer.Length).ToArray();
                    outputBuffer.WrittenSpan.Slice(0, buffer.Length).CopyTo(buffer);
                    return(buffer.Length);
                }
                else
                {
                    if (endOfClearText)
                    {
                        State = ReaderState.Headers;
                    }
                    pendingData = null;
                    outputBuffer.WrittenSpan.CopyTo(buffer);
                    return(outputBuffer.WrittenCount);
                }
            }