Full Code of a1q123456/Harmonic for AI

master dba877459e5b cached
226 files
429.0 KB
94.9k tokens
675 symbols
1 requests
Download .txt
Showing preview only (480K chars total). Download the full file or copy to clipboard to get everything.
Repository: a1q123456/Harmonic
Branch: master
Commit: dba877459e5b
Files: 226
Total size: 429.0 KB

Directory structure:
gitextract_v87mtvnp/

├── .github/
│   └── workflows/
│       └── dotnetcore.yml
├── .gitignore
├── Harmonic/
│   ├── Buffers/
│   │   └── ByteBuffer.cs
│   ├── Controllers/
│   │   ├── Living/
│   │   │   ├── LivingController.cs
│   │   │   └── LivingStream.cs
│   │   ├── NeverRegisterAttribute.cs
│   │   ├── Record/
│   │   │   ├── RecordController.cs
│   │   │   └── RecordStream.cs
│   │   ├── RtmpController.cs
│   │   ├── WebSocketController.cs
│   │   └── WebSocketPlayController.cs
│   ├── Harmonic.csproj
│   ├── Hosting/
│   │   ├── IStartup.cs
│   │   ├── RtmpServer.cs
│   │   ├── RtmpServerBuilder.cs
│   │   ├── RtmpServerOptions.cs
│   │   └── WebSocketOptions.cs
│   ├── Networking/
│   │   ├── Amf/
│   │   │   ├── Common/
│   │   │   │   ├── Amf3Object.cs
│   │   │   │   ├── TypeRegisterState.cs
│   │   │   │   ├── Undefined.cs
│   │   │   │   └── Unsupported.cs
│   │   │   ├── Data/
│   │   │   │   ├── IDynamicObject.cs
│   │   │   │   ├── IExternalizable.cs
│   │   │   │   └── Message.cs
│   │   │   └── Serialization/
│   │   │       ├── Amf0/
│   │   │       │   ├── Amf0CommonValues.cs
│   │   │       │   ├── Amf0Reader.cs
│   │   │       │   ├── Amf0Type.cs
│   │   │       │   ├── Amf0Writer.cs
│   │   │       │   └── SerializationContext.cs
│   │   │       ├── Amf3/
│   │   │       │   ├── Amf3Array.cs
│   │   │       │   ├── Amf3ClassTraits.cs
│   │   │       │   ├── Amf3CommonValues.cs
│   │   │       │   ├── Amf3Dictionary.cs
│   │   │       │   ├── Amf3Reader.cs
│   │   │       │   ├── Amf3Type.cs
│   │   │       │   ├── Amf3Writer.cs
│   │   │       │   ├── Amf3Xml.cs
│   │   │       │   ├── SerializationContext.cs
│   │   │       │   └── Vector.cs
│   │   │       └── Attributes/
│   │   │           ├── ClassFieldAttribute.cs
│   │   │           └── TypedObjectAttribute.cs
│   │   ├── ConnectionInformation.cs
│   │   ├── Flv/
│   │   │   ├── Data/
│   │   │   │   ├── AacPacketType.cs
│   │   │   │   ├── AudioData.cs
│   │   │   │   ├── CodecId.cs
│   │   │   │   ├── FlvAudioData.cs
│   │   │   │   ├── FlvVideoData.cs
│   │   │   │   ├── FrameType.cs
│   │   │   │   ├── SoundFormat.cs
│   │   │   │   ├── SoundRate.cs
│   │   │   │   ├── SoundSize.cs
│   │   │   │   └── SoundType.cs
│   │   │   ├── FlvDemuxer.cs
│   │   │   └── FlvMuxer.cs
│   │   ├── Rtmp/
│   │   │   ├── ChunkStreamContext.cs
│   │   │   ├── Data/
│   │   │   │   ├── ChunkBasicHeader.cs
│   │   │   │   ├── ChunkHeader.cs
│   │   │   │   ├── ChunkHeaderType.cs
│   │   │   │   ├── Message.cs
│   │   │   │   ├── MessageHeader.cs
│   │   │   │   ├── MessageType.cs
│   │   │   │   ├── SharedObjectMessage.cs
│   │   │   │   └── UserControlMessageEvents.cs
│   │   │   ├── Exceptions/
│   │   │   │   └── UnknownMessageReceivedException.cs
│   │   │   ├── HandshakeContext.cs
│   │   │   ├── IOPipeLine.cs
│   │   │   ├── MessageReadingState.cs
│   │   │   ├── Messages/
│   │   │   │   ├── AbortMessage.cs
│   │   │   │   ├── AcknowledgementMessage.cs
│   │   │   │   ├── AggregateMessage.cs
│   │   │   │   ├── AmfEncodingVersion.cs
│   │   │   │   ├── AudioMessage.cs
│   │   │   │   ├── Commands/
│   │   │   │   │   ├── CallCommandMessage.cs
│   │   │   │   │   ├── CommandMessage.cs
│   │   │   │   │   ├── CommandMessageFactory.cs
│   │   │   │   │   ├── ConnectCommandMessage.cs
│   │   │   │   │   ├── CreateStreamCommandMessage.cs
│   │   │   │   │   ├── DeleteStreamCommandMessage.cs
│   │   │   │   │   ├── OnStatusCommandMessage.cs
│   │   │   │   │   ├── PauseCommandMessage.cs
│   │   │   │   │   ├── Play2CommandMessage.cs
│   │   │   │   │   ├── PlayCommandMessage.cs
│   │   │   │   │   ├── PublishCommandMessage.cs
│   │   │   │   │   ├── ReceiveAudioCommandMessage.cs
│   │   │   │   │   ├── ReceiveVideoCommandMessage.cs
│   │   │   │   │   ├── ReturnResultCommandMessage.cs
│   │   │   │   │   └── SeekCommandMessage.cs
│   │   │   │   ├── ControlMessage.cs
│   │   │   │   ├── DataMessage.cs
│   │   │   │   ├── SetChunkSizeMessage.cs
│   │   │   │   ├── SetPeerBandwidthMessage.cs
│   │   │   │   ├── UserControlMessages/
│   │   │   │   │   ├── PingRequestMessage.cs
│   │   │   │   │   ├── PingResponseMessage.cs
│   │   │   │   │   ├── SetBufferLengthMessage.cs
│   │   │   │   │   ├── StreamBeginMessage.cs
│   │   │   │   │   ├── StreamDryMessage.cs
│   │   │   │   │   ├── StreamEofMessage.cs
│   │   │   │   │   ├── StreamIsRecordedMessage.cs
│   │   │   │   │   ├── UserControlMessage.cs
│   │   │   │   │   └── UserControlMessageFactory.cs
│   │   │   │   ├── VideoMessage.cs
│   │   │   │   └── WindowAcknowledgementSizeMessage.cs
│   │   │   ├── NetConnection.cs
│   │   │   ├── NetStream.cs
│   │   │   ├── RtmpChunkStream.cs
│   │   │   ├── RtmpControlChunkStream.cs
│   │   │   ├── RtmpControlMessageStream.cs
│   │   │   ├── RtmpMessageStream.cs
│   │   │   ├── RtmpSession.cs
│   │   │   ├── Serialization/
│   │   │   │   ├── OptionalArgumentAttribute.cs
│   │   │   │   ├── RtmpCommandAttribute.cs
│   │   │   │   ├── RtmpMessageAttribute.cs
│   │   │   │   ├── SerializationContext.cs
│   │   │   │   └── UserControlMessageAttribute.cs
│   │   │   ├── Streaming/
│   │   │   │   ├── PublishingType.cs
│   │   │   │   └── PublishingTypeNameAttribute.cs
│   │   │   ├── Supervisor.cs
│   │   │   └── WriteState.cs
│   │   ├── Utils/
│   │   │   ├── NetworkBitConverter.cs
│   │   │   └── StreamHelper.cs
│   │   └── WebSocket/
│   │       └── WebSocketSession.cs
│   ├── Rpc/
│   │   ├── CommandObjectAttribute.cs
│   │   ├── FromCommandObjectAttribute.cs
│   │   ├── FromOptionalArgumentAttribute.cs
│   │   ├── RpcMethodAttribute.cs
│   │   └── RpcService.cs
│   └── Service/
│       ├── PublisherSessionService.cs
│       ├── RecordService.cs
│       └── RecordServiceConfiguration.cs
├── Harmonic.sln
├── LICENSE
├── README.md
├── RoadMap.md
├── UnitTest/
│   ├── TestAmf0Reader.cs
│   ├── TestAmf0Writer.cs
│   ├── TestAmf3Reader.cs
│   ├── TestAmf3Writer.cs
│   ├── TestUnlimitedBuffer.cs
│   └── UnitTest.csproj
├── demo/
│   ├── MyLivingController.cs
│   ├── MyLivingStream.cs
│   ├── Program.cs
│   ├── StartUp.cs
│   └── demo.csproj
├── docs/
│   ├── README.md
│   ├── api.md
│   └── rpc.md
└── samples/
    ├── amf0/
    │   ├── boolean/
    │   │   ├── false.amf0
    │   │   └── true.amf0
    │   ├── misc/
    │   │   ├── array.amf0
    │   │   ├── date.amf0
    │   │   ├── ecmaarray.amf0
    │   │   ├── longstring.amf0
    │   │   ├── null.amf0
    │   │   ├── object.amf0
    │   │   ├── packet.amf0
    │   │   ├── undefined.amf0
    │   │   └── xml.amf0
    │   ├── number/
    │   │   ├── 1.1261843717924092.amf0
    │   │   ├── 2.3763213699559538.amf0
    │   │   ├── 3.498957015368982.amf0
    │   │   ├── 3.9231228517554273.amf0
    │   │   ├── 4.141123418573091.amf0
    │   │   ├── 4.485998361678176.amf0
    │   │   ├── 5.442560101247932.amf0
    │   │   ├── 7.560779119365773.amf0
    │   │   ├── 9.719564819564491.amf0
    │   │   └── 9.844079468164518.amf0
    │   └── string/
    │       ├── fkqudskxxb.amf0
    │       ├── grkogrokmq.amf0
    │       ├── gymtsavnng.amf0
    │       ├── karxrlzavl.amf0
    │       ├── lbwkjydfuv.amf0
    │       ├── qsqwosrxcl.amf0
    │       ├── rpwhhjwary.amf0
    │       ├── sjceuhcjfa.amf0
    │       ├── vrouinfvzr.amf0
    │       └── vsyrigrfbn.amf0
    └── amf3/
        ├── boolean/
        │   ├── false.amf3
        │   └── true.amf3
        ├── intenger/
        │   ├── 56.amf3
        │   ├── 57.amf3
        │   ├── 60.amf3
        │   ├── 67.amf3
        │   ├── 72.amf3
        │   ├── 73.amf3
        │   ├── 75.amf3
        │   ├── 78.amf3
        │   ├── 82.amf3
        │   └── 98.amf3
        ├── misc/
        │   ├── array.amf3
        │   ├── bytearray.amf3
        │   ├── date.amf3
        │   ├── dictionary.amf3
        │   ├── externalizable.amf3
        │   ├── null.amf3
        │   ├── object.amf3
        │   ├── packet.amf3
        │   ├── undefined.amf3
        │   ├── vector_any_object.amf3
        │   ├── vector_double.amf3
        │   ├── vector_int.amf3
        │   ├── vector_typted_object.amf3
        │   ├── vector_uint.amf3
        │   ├── xml.amf3
        │   └── xml_document.amf3
        ├── number/
        │   ├── 0.05806697191443333.amf3
        │   ├── 3.962148410082559.amf3
        │   ├── 4.465764800567858.amf3
        │   ├── 6.863435764713296.amf3
        │   ├── 7.645173446829178.amf3
        │   ├── 8.451623695104308.amf3
        │   ├── 8.518697602984554.amf3
        │   ├── 8.85002823631796.amf3
        │   ├── 9.838871036292584.amf3
        │   └── 9.98509389093438.amf3
        └── string/
            ├── aoxqmkvbxa.amf3
            ├── bghnwadduz.amf3
            ├── cmaljzrwgc.amf3
            ├── cuyerozwyf.amf3
            ├── dfjfucqvpr.amf3
            ├── fxxcsjosdu.amf3
            ├── korbgwizge.amf3
            ├── psvigwvvpx.amf3
            ├── ubteltbaku.amf3
            └── vqayztgtuf.amf3

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/workflows/dotnetcore.yml
================================================
name: .NET Core

on: [push]

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v1
    - name: Setup .NET Core
      uses: actions/setup-dotnet@v1
      with:
        dotnet-version: 2.2.108
    - name: Build with dotnet
      run: dotnet pack --configuration Release

    - name: Nuget Push
      run: dotnet nuget push Harmonic/bin/Release/*.nupkg -k ${{ secrets.NUGET_TOKEN }} -s https://api.nuget.org/v3/index.json


================================================
FILE: .gitignore
================================================
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore

# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates

# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs

# Publish results
publish/

# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/

# Visual Studio 2015 cache/options directory
.vs/
.vscode/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/

# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*

# NUNIT
*.VisualState.xml
TestResult.xml

# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c

# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
**/Properties/launchSettings.json

*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc

# Chutzpah Test files
_Chutzpah*

# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb

# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap

# TFS 2012 Local Workspace
$tf/

# Guidance Automation Toolkit
*.gpState

# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user

# JustCode is a .NET coding add-in
.JustCode

# TeamCity is a build add-in
_TeamCity*

# DotCover is a Code Coverage Tool
*.dotCover

# Visual Studio code coverage results
*.coverage
*.coveragexml

# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*

# MightyMoose
*.mm.*
AutoTest.Net/

# Web workbench (sass)
.sass-cache/

# Installshield output folder
[Ee]xpress/

# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html

# Click-Once directory
publish/

# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj

# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/

# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets

# Microsoft Azure Build Output
csx/
*.build.csdef

# Microsoft Azure Emulator
ecf/
rcf/

# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt

# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/

# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs

# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/

# RIA/Silverlight projects
Generated_Code/

# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm

# SQL Server files
*.mdf
*.ldf

# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings

# Microsoft Fakes
FakesAssemblies/

# GhostDoc plugin setting file
*.GhostDoc.xml

# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/

# Typescript v1 declaration files
typings/

# Visual Studio 6 build log
*.plg

# Visual Studio 6 workspace options file
*.opt

# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw

# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions

# Paket dependency manager
.paket/paket.exe
paket-files/

# FAKE - F# Make
.fake/

# JetBrains Rider
.idea/
*.sln.iml

# CodeRush
.cr/

# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc

# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config

# Telerik's JustMock configuration file
*.jmconfig


================================================
FILE: Harmonic/Buffers/ByteBuffer.cs
================================================
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Threading.Tasks.Sources;

namespace Harmonic.Buffers
{
    public class ByteBuffer : IDisposable
    {
        private List<byte[]> _buffers = new List<byte[]>();
        private int _bufferEnd = 0;
        private int _bufferStart = 0;
        private readonly int _maxiumBufferSize = 0;
        private event Action _memoryUnderLimit;
        private event Action _dataWritten;
        private object _sync = new object();
        private ArrayPool<byte> _arrayPool;
        public int BufferSegmentSize { get; }
        public int Length
        {
            get
            {
                return _buffers.Count * BufferSegmentSize - BufferBytesAvailable() - _bufferStart;
            }
        }

        public ByteBuffer(int bufferSegmentSize = 1024, int maxiumBufferSize = -1, ArrayPool<byte> arrayPool = null)
        {
            if (bufferSegmentSize == 0)
            {
                throw new ArgumentOutOfRangeException();
            }

            BufferSegmentSize = bufferSegmentSize;
            _maxiumBufferSize = maxiumBufferSize;
            if (arrayPool != null)
            {
                _arrayPool = arrayPool;
            }
            else
            {
                _arrayPool = ArrayPool<byte>.Shared;
            }
            _buffers.Add(_arrayPool.Rent(bufferSegmentSize));
        }

        private int BufferBytesAvailable()
        {
            return BufferSegmentSize - _bufferEnd;
        }

        private void AddNewBufferSegment()
        {
            var arr = _arrayPool.Rent(BufferSegmentSize);
            Debug.Assert(_buffers.IndexOf(arr) == -1);
            _buffers.Add(arr);
            _bufferEnd = 0;
        }

        public void WriteToBuffer(byte data)
        {
            if (Length > _maxiumBufferSize && _maxiumBufferSize >= 0)
            {
                throw new InvalidOperationException("buffer length exceeded");
            }
            lock (_sync)
            {
                int available = BufferBytesAvailable();
                byte[] buffer = null;
                if (available == 0)
                {
                    AddNewBufferSegment();
                    buffer = _buffers.Last();
                }
                else
                {
                    buffer = _buffers.Last();
                }
                buffer[_bufferEnd] = data;
                _bufferEnd += 1;
            }
        }

        private void WriteToBufferNoCheck(ReadOnlySpan<byte> bytes)
        {
            lock (_sync)
            {
                var requiredLength = bytes.Length;
                int available = BufferBytesAvailable();
                if (available < requiredLength)
                {
                    var bytesIndex = 0;
                    do
                    {
                        var buffer = _buffers.Last();
                        var seq = bytes.Slice(bytesIndex, Math.Min(available, requiredLength));
                        seq.CopyTo(buffer.AsSpan(_bufferEnd));
                        _bufferEnd += seq.Length;
                        requiredLength -= seq.Length;
                        available -= seq.Length;
                        bytesIndex += seq.Length;

                        if (available == 0)
                        {
                            AddNewBufferSegment();
                            available = BufferBytesAvailable();
                        }
                    }
                    while (requiredLength != 0);
                }
                else
                {
                    var buffer = _buffers.Last();
                    bytes.CopyTo(buffer.AsSpan(_bufferEnd));
                    _bufferEnd += bytes.Length;
                }
            }
            _dataWritten?.Invoke();
        }
        class _source : IValueTaskSource
        {
            private static readonly Action<object> CallbackCompleted = _ => { Debug.Assert(false, "Should not be invoked"); };

            private List<Action> cb = new List<Action>();
            private ValueTaskSourceStatus status = ValueTaskSourceStatus.Pending;
            private ExecutionContext executionContext;
            private object scheduler;
            private object state;
            private Action<object> continuation;

            public _source()
            {
            }

            public void Cancel()
            {
                status = ValueTaskSourceStatus.Canceled;
            }
            public void Success()
            {
                status = ValueTaskSourceStatus.Succeeded;
                var previousContinuation = Interlocked.CompareExchange(ref this.continuation, CallbackCompleted, null);
                if (previousContinuation != null)
                {
                    // Async work completed, continue with... continuation
                    ExecutionContext ec = executionContext;
                    if (ec == null)
                    {
                        InvokeContinuation(previousContinuation, this.state, forceAsync: false);
                    }
                    else
                    {
                        // This case should be relatively rare, as the async Task/ValueTask method builders
                        // use the awaiter's UnsafeOnCompleted, so this will only happen with code that
                        // explicitly uses the awaiter's OnCompleted instead.
                        executionContext = null;
                        ExecutionContext.Run(ec, runState =>
                        {
                            var t = (Tuple<_source, Action<object>, object>)runState;
                            t.Item1.InvokeContinuation(t.Item2, t.Item3, forceAsync: false);
                        }, Tuple.Create(this, previousContinuation, this.state));
                    }
                }
            }

            public void GetResult(short token)
            {
                return;
            }

            public ValueTaskSourceStatus GetStatus(short token)
            {
                return status;
            }

            public void OnCompleted(Action<object> continuation, object state, short token, ValueTaskSourceOnCompletedFlags flags)
            {
                if ((flags & ValueTaskSourceOnCompletedFlags.FlowExecutionContext) != 0)
                {
                    this.executionContext = ExecutionContext.Capture();
                }

                if ((flags & ValueTaskSourceOnCompletedFlags.UseSchedulingContext) != 0)
                {
                    SynchronizationContext sc = SynchronizationContext.Current;
                    if (sc != null && sc.GetType() != typeof(SynchronizationContext))
                    {
                        this.scheduler = sc;
                    }
                    else
                    {
                        TaskScheduler ts = TaskScheduler.Current;
                        if (ts != TaskScheduler.Default)
                        {
                            this.scheduler = ts;
                        }
                    }
                }

                // Remember current state
                this.state = state;
                // Remember continuation to be executed on completed (if not already completed, in case of which
                // continuation will be set to CallbackCompleted)
                var previousContinuation = Interlocked.CompareExchange(ref this.continuation, continuation, null);
                if (previousContinuation != null)
                {
                    if (!ReferenceEquals(previousContinuation, CallbackCompleted))
                    {
                        throw new InvalidOperationException();
                    }

                    // Lost the race condition and the operation has now already completed.
                    // We need to invoke the continuation, but it must be asynchronously to
                    // avoid a stack dive.  However, since all of the queueing mechanisms flow
                    // ExecutionContext, and since we're still in the same context where we
                    // captured it, we can just ignore the one we captured.
                    executionContext = null;
                    this.state = null; // we have the state in "state"; no need for the one in UserToken
                    InvokeContinuation(continuation, state, forceAsync: true);
                }

                cb.Add(() => continuation(state));
            }

            private void InvokeContinuation(Action<object> continuation, object state, bool forceAsync)
            {
                if (continuation == null)
                    return;

                object scheduler = this.scheduler;
                this.scheduler = null;
                if (scheduler != null)
                {
                    if (scheduler is SynchronizationContext sc)
                    {
                        sc.Post(s =>
                        {
                            var t = (Tuple<Action<object>, object>)s;
                            t.Item1(t.Item2);
                        }, Tuple.Create(continuation, state));
                    }
                    else
                    {
                        Debug.Assert(scheduler is TaskScheduler, $"Expected TaskScheduler, got {scheduler}");
                        Task.Factory.StartNew(continuation, state, CancellationToken.None, TaskCreationOptions.DenyChildAttach, (TaskScheduler)scheduler);
                    }
                }
                else if (forceAsync)
                {
                    ThreadPool.QueueUserWorkItem(continuation, state, preferLocal: true);
                }
                else
                {
                    continuation(state);
                }
            }
        }

        public ValueTask WriteToBufferAsync(ReadOnlyMemory<byte> bytes)
        {
            lock (_sync)
            {
                if (Length + bytes.Length > _maxiumBufferSize && _maxiumBufferSize >= 0)
                {
                    var source = new _source();
                    Action ac = null;
                    ac = () =>
                    {
                        _memoryUnderLimit -= ac;
                        WriteToBufferNoCheck(bytes.Span);
                        source.Success();
                    };
                    _memoryUnderLimit += ac;
                    return new ValueTask(source, 0);
                }
            }

            WriteToBufferNoCheck(bytes.Span);
            return default;
        }

        public void WriteToBuffer(ReadOnlySpan<byte> bytes)
        {
            while (Length + bytes.Length > _maxiumBufferSize && _maxiumBufferSize >= 0)
            {
                Thread.Yield();
            }
            WriteToBufferNoCheck(bytes);
        }

        private void TakeOutMemoryNoCheck(Span<byte> buffer)
        {
            lock (_sync)
            {
                var discardBuffers = new List<byte[]>();
                bool prevDiscarded = false;
                if (Length < buffer.Length && _maxiumBufferSize >= 0)
                {
                    throw new InvalidProgramException();
                }
                foreach (var b in _buffers)
                {
                    if (buffer.Length == 0)
                    {
                        break;
                    }
                    var start = 0;
                    var end = BufferSegmentSize;
                    var isFirst = b == _buffers.First() || prevDiscarded;
                    var isLast = b == _buffers.Last();
                    if (isFirst)
                    {
                        start = _bufferStart;
                    }
                    if (isLast)
                    {
                        end = _bufferEnd;
                    }
                    var length = end - start;
                    var needToCopy = Math.Min(buffer.Length, length);

                    b.AsSpan(start, needToCopy).CopyTo(buffer);

                    start += needToCopy;
                    if (isFirst)
                    {
                        _bufferStart += needToCopy;
                    }

                    if (end - start == 0)
                    {
                        if (isFirst)
                        {
                            _bufferStart = 0;
                        }
                        if (isLast)
                        {
                            _bufferEnd = 0;
                        }
                        discardBuffers.Add(b);
                        prevDiscarded = true;
                    }
                    else
                    {
                        prevDiscarded = false;
                    }

                    buffer = buffer.Slice(needToCopy);
                }
                //Console.WriteLine(Length);
                Debug.Assert(buffer.Length == 0 || _maxiumBufferSize < 0);
                while (discardBuffers.Any())
                {
                    var b = discardBuffers.First();
                    _arrayPool.Return(b);
                    discardBuffers.Remove(b);
                    _buffers.Remove(b);
                }
                if (!_buffers.Any())
                {
                    AddNewBufferSegment();
                }
            }
            if (Length <= _maxiumBufferSize && _maxiumBufferSize >= 0)
            {
                _memoryUnderLimit?.Invoke();
            }
        }

        public ValueTask TakeOutMemoryAsync(Memory<byte> buffer, CancellationToken ct = default)
        {
            lock (_sync)
            {
                if (buffer.Length > Length && _maxiumBufferSize >= 0)
                {
                    var source = new _source();
                    var reg = ct.Register(() =>
                    {
                        source.Cancel();
                    });
                    Action ac = null;
                    ac = () =>
                    {
                        if (buffer.Length <= Length)
                        {
                            _dataWritten -= ac;
                            reg.Dispose();
                            TakeOutMemoryNoCheck(buffer.Span);
                            source.Success();
                        }
                    };
                    _dataWritten += ac;
                    return new ValueTask(source, 0);
                }
            }

            TakeOutMemoryNoCheck(buffer.Span);
            return default;
        }

        public void TakeOutMemory(Span<byte> buffer)
        {
            while (buffer.Length > Length && _maxiumBufferSize >= 0)
            {
                Thread.Yield();
            }
            TakeOutMemoryNoCheck(buffer);
        }

        #region IDisposable Support
        private bool disposedValue = false;

        protected virtual void Dispose(bool disposing)
        {
            if (!disposedValue)
            {
                if (disposing)
                {
                    foreach (var buffer in _buffers)
                    {
                        _arrayPool.Return(buffer);
                    }
                    _buffers.Clear();
                }
                disposedValue = true;
            }
        }

        // ~UnlimitedBuffer() {
        //   Dispose(false);
        // }

        public void Dispose()
        {
            Dispose(true);
            // GC.SuppressFinalize(this);
        }
        #endregion
    }
}


================================================
FILE: Harmonic/Controllers/Living/LivingController.cs
================================================
using Harmonic.Networking.Rtmp;
using Harmonic.Rpc;
using System;
using System.Collections.Generic;
using System.Text;

namespace Harmonic.Controllers.Living
{
    public class LivingController : RtmpController
    {
        [RpcMethod("createStream")]
        public uint CreateStream()
        {
            var stream = RtmpSession.CreateNetStream<LivingStream>();
            return stream.MessageStream.MessageStreamId;
        }
    }
}


================================================
FILE: Harmonic/Controllers/Living/LivingStream.cs
================================================
using Harmonic.Networking.Amf.Common;
using Harmonic.Networking.Rtmp;
using Harmonic.Networking.Rtmp.Data;
using Harmonic.Networking.Rtmp.Messages;
using Harmonic.Networking.Rtmp.Messages.Commands;
using Harmonic.Networking.Rtmp.Messages.UserControlMessages;
using Harmonic.Networking.Rtmp.Streaming;
using Harmonic.Rpc;
using Harmonic.Service;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;

namespace Harmonic.Controllers.Living
{
    public class LivingStream : NetStream
    {
        private List<Action> _cleanupActions = new List<Action>();
        private PublishingType _publishingType;
        private PublisherSessionService _publisherSessionService = null;
        public DataMessage FlvMetadata = null;
        public AudioMessage AACConfigureRecord = null;
        public VideoMessage AVCConfigureRecord = null;
        public event Action<VideoMessage> OnVideoMessage;
        public event Action<AudioMessage> OnAudioMessage;
        private RtmpChunkStream _videoChunkStream = null;
        private RtmpChunkStream _audioChunkStream = null;

        public LivingStream(PublisherSessionService publisherSessionService)
        {
            _publisherSessionService = publisherSessionService;
        }

        [RpcMethod("play")]
        public async Task Play(
            [FromOptionalArgument] string streamName,
            [FromOptionalArgument] double start = -1,
            [FromOptionalArgument] double duration = -1,
            [FromOptionalArgument] bool reset = false)
        {
            var publisher = _publisherSessionService.FindPublisher(streamName);
            if (publisher == null)
            {
                throw new KeyNotFoundException();
            }
            var resetData = new AmfObject
            {
                {"level", "status" },
                {"code", "NetStream.Play.Reset" },
                {"description", "Resetting and playing stream." },
                {"details", streamName }
            };
            var resetStatus = RtmpSession.CreateCommandMessage<OnStatusCommandMessage>();
            resetStatus.InfoObject = resetData;
            await MessageStream.SendMessageAsync(ChunkStream, resetStatus);

            var startData = new AmfObject
            {
                {"level", "status" },
                {"code", "NetStream.Play.Start" },
                {"description", "Started playing." },
                {"details", streamName }
            };
            var startStatus = RtmpSession.CreateCommandMessage<OnStatusCommandMessage>();
            startStatus.InfoObject = startData;
            await MessageStream.SendMessageAsync(ChunkStream, startStatus);

            var flvMetadata = RtmpSession.CreateData<DataMessage>();
            flvMetadata.MessageHeader = (MessageHeader)publisher.FlvMetadata.MessageHeader.Clone();
            flvMetadata.Data = publisher.FlvMetadata.Data;
            await MessageStream.SendMessageAsync(ChunkStream, flvMetadata);

            _videoChunkStream = RtmpSession.CreateChunkStream();
            _audioChunkStream = RtmpSession.CreateChunkStream();

            if (publisher.AACConfigureRecord != null)
            {
                await MessageStream.SendMessageAsync(_audioChunkStream, publisher.AACConfigureRecord.Clone() as AudioMessage);
            }
            if (publisher.AVCConfigureRecord != null)
            {
                await MessageStream.SendMessageAsync(_videoChunkStream, publisher.AVCConfigureRecord.Clone() as VideoMessage);
            }

            publisher.OnAudioMessage += SendAudio;
            publisher.OnVideoMessage += SendVideo;
            _cleanupActions.Add(() =>
            {
                publisher.OnVideoMessage -= SendVideo;
                publisher.OnAudioMessage -= SendAudio;
            });
        }

        private async void SendVideo(VideoMessage message)
        {
            var video = message.Clone() as VideoMessage;
            
            try
            {
                await MessageStream.SendMessageAsync(_videoChunkStream, video);
            }
            catch
            {
                foreach (var a in _cleanupActions)
                {
                    a();
                }
                RtmpSession.Close();
            }
        }

        private async void SendAudio(AudioMessage message)
        {
            var audio = message.Clone();
            try
            {
                await MessageStream.SendMessageAsync(_audioChunkStream, audio as AudioMessage);
            }
            catch
            {
                foreach (var a in _cleanupActions)
                {
                    a();
                }
                RtmpSession.Close();
            }
        }

        [RpcMethod(Name = "publish")]
        public void Publish([FromOptionalArgument] string publishingName, [FromOptionalArgument] string publishingType)
        {
            if (string.IsNullOrEmpty(publishingName))
            {
                throw new InvalidOperationException("empty publishing name");
            }
            if (!PublishingHelpers.IsTypeSupported(publishingType))
            {
                throw new InvalidOperationException($"not supported publishing type {publishingType}");
            }

            _publishingType = PublishingHelpers.PublishingTypes[publishingType];

            _publisherSessionService.RegisterPublisher(publishingName, this);

            RtmpSession.SendControlMessageAsync(new StreamBeginMessage() { StreamID = MessageStream.MessageStreamId });
            var onStatus = RtmpSession.CreateCommandMessage<OnStatusCommandMessage>();
            MessageStream.RegisterMessageHandler<DataMessage>(HandleDataMessage);
            MessageStream.RegisterMessageHandler<AudioMessage>(HandleAudioMessage);
            MessageStream.RegisterMessageHandler<VideoMessage>(HandleVideoMessage);
            onStatus.InfoObject = new AmfObject
            {
                {"level", "status" },
                {"code", "NetStream.Publish.Start" },
                {"description", "Stream is now published." },
                {"details", publishingName }
            };
            MessageStream.SendMessageAsync(ChunkStream, onStatus);
        }

        private void HandleDataMessage(DataMessage msg)
        {
            FlvMetadata = msg;
        }

        private void HandleAudioMessage(AudioMessage audioData)
        {
            if (AACConfigureRecord == null && audioData.Data.Length >= 2)
            {
                AACConfigureRecord = audioData;
                return;
            }
            OnAudioMessage?.Invoke(audioData);
        }

        private void HandleVideoMessage(VideoMessage videoData)
        {
            if (AVCConfigureRecord == null && videoData.Data.Length >= 2)
            {
                AVCConfigureRecord = videoData;
            }
            OnVideoMessage?.Invoke(videoData);
        }

        #region Disposable Support

        private bool disposedValue = false;

        protected override void Dispose(bool disposing)
        {
            if (!disposedValue)
            {
                base.Dispose(disposing);
                _publisherSessionService.RemovePublisher(this);
                _videoChunkStream?.Dispose();
                _audioChunkStream?.Dispose();

                disposedValue = true;
            }
        }
        #endregion
    }
}


================================================
FILE: Harmonic/Controllers/NeverRegisterAttribute.cs
================================================
using System;
using System.Collections.Generic;
using System.Text;

namespace Harmonic.Controllers
{
    [AttributeUsage(AttributeTargets.Class)]
    public class NeverRegisterAttribute : Attribute
    {

    }
}


================================================
FILE: Harmonic/Controllers/Record/RecordController.cs
================================================
using Harmonic.Networking.Rtmp.Messages;
using Harmonic.Rpc;
using System;
using System.Collections.Generic;
using System.Text;

namespace Harmonic.Controllers.Record
{
    public class RecordController : RtmpController
    {
        [RpcMethod("createStream")]
        public uint CreateStream()
        {
            var stream = RtmpSession.CreateNetStream<RecordStream>();
            return stream.MessageStream.MessageStreamId;
        }
    }
}


================================================
FILE: Harmonic/Controllers/Record/RecordStream.cs
================================================
using Harmonic.Networking.Flv;
using Harmonic.Networking.Amf.Common;
using Harmonic.Networking.Amf.Serialization.Amf0;
using Harmonic.Networking.Amf.Serialization.Amf3;
using Harmonic.Networking.Rtmp;
using Harmonic.Networking.Rtmp.Data;
using Harmonic.Networking.Rtmp.Messages;
using Harmonic.Networking.Rtmp.Messages.Commands;
using Harmonic.Networking.Rtmp.Messages.UserControlMessages;
using Harmonic.Networking.Rtmp.Streaming;
using Harmonic.Networking.Utils;
using Harmonic.Rpc;
using Harmonic.Service;
using System;
using System.Buffers;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Harmonic.Networking.Flv.Data;

namespace Harmonic.Controllers.Record
{
    public class RecordStream : NetStream
    {
        private PublishingType _publishingType;
        private FileStream _recordFile = null;
        private FileStream _recordFileData = null;
        private RecordService _recordService = null;
        private DataMessage _metaData = null;
        private uint _currentTimestamp = 0;
        private SemaphoreSlim _playLock = new SemaphoreSlim(1);
        private int _playing = 0;
        private AmfObject _keyframes = null;
        private List<object> _keyframeTimes;
        private List<object> _keyframeFilePositions;
        private long _bufferMs = -1;

        private RtmpChunkStream VideoChunkStream { get; set; } = null;
        private RtmpChunkStream AudioChunkStream { get; set; } = null;
        private bool _disposed = false;
        private CancellationTokenSource _playCts;

        protected override async void Dispose(bool disposing)
        {
            base.Dispose(disposing);
            if (!_disposed)
            {
                _disposed = true;
                if (_recordFileData != null)
                {
                    try
                    {
                        var filePath = _recordFileData.Name;
                        using (var recordFile = new FileStream(filePath.Substring(0, filePath.Length - 5) + ".flv", FileMode.OpenOrCreate))
                        {
                            recordFile.SetLength(0);
                            recordFile.Seek(0, SeekOrigin.Begin);
                            await recordFile.WriteAsync(FlvMuxer.MultiplexFlvHeader(true, true));
                            var metaData = _metaData.Data[1] as Dictionary<string, object>;
                            metaData["duration"] = ((double)_currentTimestamp) / 1000;
                            metaData["keyframes"] = _keyframes;
                            _metaData.MessageHeader.MessageLength = 0;
                            var dataTagLen = FlvMuxer.MultiplexFlv(_metaData).Length;

                            var offset = recordFile.Position + dataTagLen;
                            for (int i = 0; i < _keyframeFilePositions.Count; i++)
                            {
                                _keyframeFilePositions[i] = (double)_keyframeFilePositions[i] + offset;
                            }

                            await recordFile.WriteAsync(FlvMuxer.MultiplexFlv(_metaData));
                            _recordFileData.Seek(0, SeekOrigin.Begin);
                            await _recordFileData.CopyToAsync(recordFile);
                            _recordFileData.Dispose();
                            File.Delete(filePath);
                        }
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e);
                    }
                }
                _recordFile?.Dispose();
            }
        }

        public RecordStream(RecordService recordService)
        {
            _recordService = recordService;
        }


        [RpcMethod(Name = "publish")]
        public async Task Publish([FromOptionalArgument] string streamName, [FromOptionalArgument] string publishingType)
        {
            if (string.IsNullOrEmpty(streamName))
            {
                throw new InvalidOperationException("empty publishing name");
            }
            if (!PublishingHelpers.IsTypeSupported(publishingType))
            {
                throw new InvalidOperationException($"not supported publishing type {publishingType}");
            }

            _publishingType = PublishingHelpers.PublishingTypes[publishingType];

            await RtmpSession.SendControlMessageAsync(new StreamIsRecordedMessage() { StreamID = MessageStream.MessageStreamId });
            await RtmpSession.SendControlMessageAsync(new StreamBeginMessage() { StreamID = MessageStream.MessageStreamId });
            var onStatus = RtmpSession.CreateCommandMessage<OnStatusCommandMessage>();
            MessageStream.RegisterMessageHandler<DataMessage>(HandleData);
            MessageStream.RegisterMessageHandler<AudioMessage>(HandleAudioMessage);
            MessageStream.RegisterMessageHandler<VideoMessage>(HandleVideoMessage);
            MessageStream.RegisterMessageHandler<UserControlMessage>(HandleUserControlMessage);
            onStatus.InfoObject = new AmfObject
            {
                {"level", "status" },
                {"code", "NetStream.Publish.Start" },
                {"description", "Stream is now published." },
                {"details", streamName }
            };
            await MessageStream.SendMessageAsync(ChunkStream, onStatus);

            _recordFileData = new FileStream(_recordService.GetRecordFilename(streamName) + ".data", FileMode.OpenOrCreate);
            _recordFileData.SetLength(0);
            _keyframes = new AmfObject();
            _keyframeTimes = new List<object>();
            _keyframeFilePositions = new List<object>();
            _keyframes.Add("times", _keyframeTimes);
            _keyframes.Add("filepositions", _keyframeFilePositions);
        }

        private void HandleUserControlMessage(UserControlMessage msg)
        {
            if (msg.UserControlEventType == UserControlEventType.SetBufferLength)
            {
                _bufferMs = (msg as SetBufferLengthMessage).BufferMilliseconds;
            }
        }

        private async void HandleAudioMessage(AudioMessage message)
        {
            try
            {
                _currentTimestamp = Math.Max(_currentTimestamp, message.MessageHeader.Timestamp);

                await SaveMessage(message);
            }
            catch
            {
                RtmpSession.Close();
            }
        }

        private async void HandleVideoMessage(VideoMessage message)
        {
            try
            {
                _currentTimestamp = Math.Max(_currentTimestamp, message.MessageHeader.Timestamp);

                var head = message.Data.Span[0];

                var data = FlvDemuxer.DemultiplexVideoData(message);
                if (data.FrameType == FrameType.KeyFrame)
                {
                    _keyframeTimes.Add((double)message.MessageHeader.Timestamp / 1000);
                    _keyframeFilePositions.Add((double)_recordFileData.Position);
                }

                await SaveMessage(message);
            }
            catch
            {
                RtmpSession.Close();
            }
        }

        private void HandleData(DataMessage message)
        {
            try
            {
                _metaData = message;
                _metaData.Data.RemoveAt(0);
            }
            catch
            {
                RtmpSession.Close();
            }
        }

        [RpcMethod("seek")]
        public async Task Seek([FromOptionalArgument] double milliSeconds)
        {
            var resetData = new AmfObject
            {
                {"level", "status" },
                {"code", "NetStream.Seek.Notify" },
                {"description", "Seeking stream." },
                {"details", "seek" }
            };
            var resetStatus = RtmpSession.CreateCommandMessage<OnStatusCommandMessage>();
            resetStatus.InfoObject = resetData;
            await MessageStream.SendMessageAsync(ChunkStream, resetStatus);

            _playCts?.Cancel();
            while (_playing == 1)
            {
                await Task.Yield();
            }

            var cts = new CancellationTokenSource();
            _playCts?.Dispose();
            _playCts = cts;
            await SeekAndPlay(milliSeconds, cts.Token);
        }

        [RpcMethod("play")]
        public async Task Play(
     [FromOptionalArgument] string streamName,
     [FromOptionalArgument] double start = -1,
     [FromOptionalArgument] double duration = -1,
     [FromOptionalArgument] bool reset = false)
        {
            _recordFile = new FileStream(_recordService.GetRecordFilename(streamName) + ".flv", FileMode.Open, FileAccess.Read);
            await FlvDemuxer.AttachStream(_recordFile);

            var resetData = new AmfObject
            {
                {"level", "status" },
                {"code", "NetStream.Play.Reset" },
                {"description", "Resetting and playing stream." },
                {"details", streamName }
            };
            var resetStatus = RtmpSession.CreateCommandMessage<OnStatusCommandMessage>();
            resetStatus.InfoObject = resetData;
            await MessageStream.SendMessageAsync(ChunkStream, resetStatus);

            var startData = new AmfObject
            {
                {"level", "status" },
                {"code", "NetStream.Play.Start" },
                {"description", "Started playing." },
                {"details", streamName }
            };

            var startStatus = RtmpSession.CreateCommandMessage<OnStatusCommandMessage>();
            startStatus.InfoObject = startData;
            await MessageStream.SendMessageAsync(ChunkStream, startStatus);
            var bandwidthLimit = new WindowAcknowledgementSizeMessage()
            {
                WindowSize = 500 * 1024
            };
            await RtmpSession.ControlMessageStream.SendMessageAsync(RtmpSession.ControlChunkStream, bandwidthLimit);
            VideoChunkStream = RtmpSession.CreateChunkStream();
            AudioChunkStream = RtmpSession.CreateChunkStream();

            var cts = new CancellationTokenSource();
            _playCts?.Dispose();
            _playCts = cts;
            start = Math.Max(start, 0);
            await SeekAndPlay(start / 1000, cts.Token);
        }

        [RpcMethod("pause")]
        public async Task Pause([FromOptionalArgument] bool isPause, [FromOptionalArgument] double milliseconds)
        {
            if (isPause)
            {
                _playCts?.Cancel();
                while (_playing == 1)
                {
                    await Task.Yield();
                }
            }
            else
            {
                var cts = new CancellationTokenSource();
                _playCts?.Dispose();
                _playCts = cts;
                await SeekAndPlay(milliseconds, cts.Token);
            }
        }

        private async Task StartPlayNoLock(CancellationToken ct)
        {
            while (_recordFile.Position < _recordFile.Length && !ct.IsCancellationRequested)
            {
                while (_bufferMs != -1 && _currentTimestamp >= _bufferMs)
                {
                    await Task.Yield();
                }

                await PlayRecordFileNoLock(ct);
            }
        }

        private Task<Message> ReadMessage(CancellationToken ct)
        {
            return FlvDemuxer.DemultiplexFlvAsync(ct);
        }

        private async Task SeekAndPlay(double milliSeconds, CancellationToken ct)
        {
            await _playLock.WaitAsync();
            Interlocked.Exchange(ref _playing, 1);
            try
            {

                _recordFile.Seek(9, SeekOrigin.Begin);
                FlvDemuxer.SeekNoLock(milliSeconds, _metaData == null ? null : _metaData.Data[2] as Dictionary<string, object>, ct);
                await StartPlayNoLock(ct);
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
            finally
            {
                Interlocked.Exchange(ref _playing, 0);
                _playLock.Release();
            }
        }

        private async Task PlayRecordFileNoLock(CancellationToken ct)
        {
            var message = await ReadMessage(ct);
            if (message is AudioMessage)
            {
                await MessageStream.SendMessageAsync(AudioChunkStream, message);
            }
            else if (message is VideoMessage)
            {
                await MessageStream.SendMessageAsync(VideoChunkStream, message);
            }
            else if (message is DataMessage data)
            {
                data.Data.Insert(0, "@setDataFrame");
                _metaData = data;
                await MessageStream.SendMessageAsync(ChunkStream, data);
            }
            _currentTimestamp = Math.Max(_currentTimestamp, message.MessageHeader.Timestamp);
        }

        private async Task SaveMessage(Message message)
        {
            await _recordFileData.WriteAsync(FlvMuxer.MultiplexFlv(message));
        }
    }
}


================================================
FILE: Harmonic/Controllers/RtmpController.cs
================================================
using Harmonic.Networking.Flv;
using Harmonic.Networking.Rtmp;
using Harmonic.Rpc;
using System;
using System.Collections.Generic;
using System.Text;

namespace Harmonic.Controllers
{
    public abstract class RtmpController
    {
        public RtmpMessageStream MessageStream { get; internal set; } = null;
        public RtmpChunkStream ChunkStream { get; internal set; } = null;
        public RtmpSession RtmpSession { get; internal set; } = null;


        private FlvMuxer _flvMuxer = null;
        private FlvDemuxer _flvDemuxer = null;

        public FlvMuxer FlvMuxer
        {
            get
            {
                if (_flvMuxer == null)
                {
                    _flvMuxer = new FlvMuxer();
                }
                return _flvMuxer;
            }
        }
        public FlvDemuxer FlvDemuxer
        {
            get
            {
                if (_flvDemuxer == null)
                {
                    _flvDemuxer = new FlvDemuxer(RtmpSession.IOPipeline.Options.MessageFactories);
                }
                return _flvDemuxer;
            }
        }

        [RpcMethod("deleteStream")]
        public void DeleteStream([FromOptionalArgument] double streamId)
        {
            RtmpSession.DeleteNetStream((uint)streamId);
        }
    }
}


================================================
FILE: Harmonic/Controllers/WebSocketController.cs
================================================
using Harmonic.Networking.Flv;
using Harmonic.Networking.Rtmp;
using Harmonic.Networking.WebSocket;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Text;
using System.Threading.Tasks;

namespace Harmonic.Controllers
{
    public abstract class WebSocketController
    {
        public string StreamName { get; internal set; }
        public NameValueCollection Query { get; internal set; }
        public WebSocketSession Session { get; internal set; }
        private FlvMuxer _flvMuxer = null;
        private FlvDemuxer _flvDemuxer = null;

        public FlvMuxer FlvMuxer
        {
            get
            {
                if (_flvMuxer == null)
                {
                    _flvMuxer = new FlvMuxer();
                }
                return _flvMuxer;
            }
        }
        public FlvDemuxer FlvDemuxer
        {
            get
            {
                if (_flvDemuxer == null)
                {
                    _flvDemuxer = new FlvDemuxer(Session.Options.MessageFactories);
                }
                return _flvDemuxer;
            }
        }
        public abstract Task OnConnect();

        public abstract void OnMessage(string msg);
    }
}


================================================
FILE: Harmonic/Controllers/WebSocketPlayController.cs
================================================
using Harmonic.Networking;
using Harmonic.Networking.Rtmp.Messages;
using Harmonic.Service;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Buffers;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Harmonic.Controllers
{
    public class WebSocketPlayController : WebSocketController, IDisposable
    {
        private RecordService _recordService = null;
        private PublisherSessionService _publisherSessionService = null;
        private List<Action> _cleanupActions = new List<Action>();
        private FileStream _recordFile = null;
        private SemaphoreSlim _playLock = new SemaphoreSlim(1);
        private int _playing = 0;
        private long _playRangeTo = 0;

        public WebSocketPlayController(PublisherSessionService publisherSessionService, RecordService recordService)
        {
            _publisherSessionService = publisherSessionService;
            _recordService = recordService;
        }

        public override async Task OnConnect()
        {
            var publisher = _publisherSessionService.FindPublisher(StreamName);
            if (publisher != null)
            {
                _cleanupActions.Add(() =>
                {
                    publisher.OnAudioMessage -= SendAudio;
                    publisher.OnVideoMessage -= SendVideo;
                });

                var metadata = (Dictionary<string, object>)publisher.FlvMetadata.Data.Last();
                var hasAudio = metadata.ContainsKey("audiocodecid");
                var hasVideo = metadata.ContainsKey("videocodecid");

                await Session.SendFlvHeaderAsync(hasAudio, hasVideo);

                await Session.SendMessageAsync(publisher.FlvMetadata);
                if (hasAudio)
                {
                    await Session.SendMessageAsync(publisher.AACConfigureRecord);
                }
                if (hasVideo)
                {
                    await Session.SendMessageAsync(publisher.AVCConfigureRecord);
                }

                publisher.OnAudioMessage += SendAudio;
                publisher.OnVideoMessage += SendVideo;
            }
            // play record
            else
            {
                _recordFile = new FileStream(_recordService.GetRecordFilename(StreamName) + ".flv", FileMode.Open, FileAccess.Read);
                var fromStr = Query.Get("from");
                long from = 0;
                if (fromStr != null)
                {
                    from = long.Parse(fromStr);
                }
                var toStr = Query.Get("to");
                _playRangeTo = -1;
                if (toStr != null)
                {
                    _playRangeTo = long.Parse(toStr);
                }

                var header = new byte[9];

                await _recordFile.ReadBytesAsync(header);
                await Session.SendRawDataAsync(header);

                from = Math.Max(from, 9);

                _recordFile.Seek(from, SeekOrigin.Begin);

                await PlayRecordFile();
            }
        }

        private async Task PlayRecordFile()
        {
            Interlocked.Exchange(ref _playing, 1);
            var buffer = new byte[512];
            int bytesRead;
            do
            {
                await _playLock.WaitAsync();
                bytesRead = await _recordFile.ReadAsync(buffer);
                await Session.SendRawDataAsync(buffer);
                _playLock.Release();
                if (_playRangeTo < _recordFile.Position && _playRangeTo != -1)
                {
                    break;
                }
            } while (bytesRead != 0);
            Interlocked.Exchange(ref _playing, 0);
        }

        private void SendVideo(VideoMessage message)
        {
            Session.SendMessageAsync(message);
        }

        private void SendAudio(AudioMessage message)
        {
            Session.SendMessageAsync(message);
        }

        public override void OnMessage(string msg)
        {
        }

        #region IDisposable Support
        private bool disposedValue = false;

        protected virtual void Dispose(bool disposing)
        {
            if (!disposedValue)
            {
                if (disposing)
                {
                    foreach (var c in _cleanupActions)
                    {
                        c();
                    }
                    _recordFile?.Dispose();
                }

                disposedValue = true;
            }
        }

        // ~WebSocketPlayController()
        // {
        //   Dispose(false);
        // }

        public void Dispose()
        {
            Dispose(true);
            // GC.SuppressFinalize(this);
        }
        #endregion
    }
}


================================================
FILE: Harmonic/Harmonic.csproj
================================================
<Project Sdk="Microsoft.NET.Sdk" 
  xmlns="http://schemas.microsoft.com/developer/msbuild/2003">


  <PropertyGroup>
    <PackageId>Harmonic</PackageId>
    <Version>0.0.2</Version>
    <Authors>kyokunnodenwa</Authors>
    <Company>kyokunnodenwa</Company>

    <TargetFramework>netcoreapp2.2</TargetFramework>
    <LangVersion>latest</LangVersion>
    <AllowUnsafeBlocks>false</AllowUnsafeBlocks>
  </PropertyGroup>

  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
    <Optimize>true</Optimize>
    <DefineConstants>TRACE</DefineConstants>
    <DebugType>full</DebugType>
    <DebugSymbols>true</DebugSymbols>
  </PropertyGroup>

  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
    <Optimize>false</Optimize>
  </PropertyGroup>

  <ItemGroup>
    <Compile Remove="Networking\IStreamSession.cs" />
    <Compile Remove="Networking\Rtmp\Supervisor.cs" />
    <Compile Remove="Networking\StreamHelper.cs" />
  </ItemGroup>
  <ItemGroup>
    <PackageReference Include="Autofac" Version="4.9.3" />
    <PackageReference Include="Fleck" Version="1.1.0" />
    <PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
    <PackageReference Include="System.IO.Pipelines" Version="4.5.3" />
  </ItemGroup>
</Project>


================================================
FILE: Harmonic/Hosting/IStartup.cs
================================================
using System;
using Autofac;

namespace Harmonic.Hosting
{
    public interface IStartup
    {
        void ConfigureServices(ContainerBuilder builder);

    }
}

================================================
FILE: Harmonic/Hosting/RtmpServer.cs
================================================
using Autofac;
using Harmonic.Networking.Rtmp;
using Harmonic.Service;
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Fleck;
using Harmonic.Networking.WebSocket;

namespace Harmonic.Hosting
{
    public class RtmpServer
    {
        private readonly Socket _listener;
        private ManualResetEvent _allDone = new ManualResetEvent(false);
        private readonly RtmpServerOptions _options;
        private WebSocketServer _webSocketServer = null;
        private WebSocketOptions _webSocketOptions = null;

        public bool Started { get; private set; } = false;

        internal RtmpServer(RtmpServerOptions options, WebSocketOptions webSocketOptions)
        {
            _options = options;
            _listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            _listener.NoDelay = true;
            _listener.Bind(options.RtmpEndPoint);
            _listener.Listen(128);
            _webSocketOptions = webSocketOptions;
            if (webSocketOptions != null)
            {
                _webSocketServer = new WebSocketServer($"{(options.Cert == null ? "ws" : "wss")}://{webSocketOptions.BindEndPoint.ToString()}");
                
            }

        }
        public Task StartAsync(CancellationToken ct = default)
        {
            if (Started)
            {
                throw new InvalidOperationException("already started");
            }
            _webSocketServer?.Start(c =>
            {
                var session = new WebSocketSession(c, _webSocketOptions);
                c.OnOpen = session.HandleOpen;
                c.OnClose = session.HandleClose;
                c.OnMessage = session.HandleMessage;
            });

            if (_webSocketServer != null)
            {
                CancellationTokenRegistration reg = default;
                reg = ct.Register(() =>
                {
                    reg.Dispose();
                    _webSocketServer.Dispose();
                    _webSocketServer = new WebSocketServer(_webSocketOptions.BindEndPoint.ToString());
                });
            }
            Started = true;
            var ret = new TaskCompletionSource<int>();
            var t = new Thread(o =>
            {
                try
                {
                    while (!ct.IsCancellationRequested)
                    {
                        try
                        {
                            _allDone.Reset();
                            _listener.BeginAccept(new AsyncCallback(ar =>
                            {
                                AcceptCallback(ar, ct);
                            }), _listener);
                            while (!_allDone.WaitOne(1))
                            {
                                ct.ThrowIfCancellationRequested();
                            }
                        }
                        catch (OperationCanceledException)
                        {
                            throw;
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine(e.ToString());
                        }
                    }
                }
                catch (OperationCanceledException) { }
                finally
                {
                    ret.SetResult(1);
                }
            });

            t.Start();
            return ret.Task;
        }
        private async void AcceptCallback(IAsyncResult ar, CancellationToken ct)
        {
            Socket listener = (Socket)ar.AsyncState;
            Socket client = listener.EndAccept(ar);
            client.NoDelay = true;
            // Signal the main thread to continue.
            _allDone.Set();
            IOPipeLine pipe = null;
            try
            {
                pipe = new IOPipeLine(client, _options);
                await pipe.StartAsync(ct);
            }
            catch (TimeoutException)
            {
                client.Close();
            }
            catch (Exception e)
            {
                Console.WriteLine("{0} Message: {1}", e.GetType().ToString(), e.Message);
                Console.WriteLine(e.StackTrace);
                client.Close();
            }
            finally
            {
                pipe?.Dispose();
            }
        }
    }
}


================================================
FILE: Harmonic/Hosting/RtmpServerBuilder.cs
================================================
using Harmonic.Controllers;
using Harmonic.Controllers.Living;
using Harmonic.Controllers.Record;
using Harmonic.Networking.Rtmp;
using System;
using System.Reflection;
using System.Security.Cryptography.X509Certificates;

namespace Harmonic.Hosting
{
    public class RtmpServerBuilder
    {
        private IStartup _startup = null;
        private X509Certificate2 _cert = null;
        private bool _useWebSocket = false;
        private bool _useSsl = false;
        private WebSocketOptions _websocketOptions = null;

        private RtmpServerOptions _options = null;

        public RtmpServerBuilder UseStartup<T>() where T: IStartup, new()
        {
            _startup = new T();
            return this;
        }
        public RtmpServerBuilder UseSsl(X509Certificate2 cert)
        {
            _useSsl = true;
            _cert = cert;
            return this;
        }

        public RtmpServerBuilder UseWebSocket(Action<WebSocketOptions> conf)
        {
            _useWebSocket = true;
            _websocketOptions = new WebSocketOptions();
            conf(_websocketOptions);
            return this;
        }

        public RtmpServerBuilder UseHarmonic(Action<RtmpServerOptions> config)
        {
            _options = new RtmpServerOptions();
            config(_options);
            return this;
        }

        public RtmpServer Build()
        {
            _options = _options ?? new RtmpServerOptions();
            _options.Startup = _startup;
            var types = Assembly.GetCallingAssembly().GetTypes();

            var registerInternalControllers = true;
            _websocketOptions._serverOptions = _options;
            foreach (var type in types)
            {
                var neverRegister = type.GetCustomAttribute<NeverRegisterAttribute>();
                if (neverRegister != null)
                {
                    continue;
                }

                if (typeof(NetStream).IsAssignableFrom(type) && !type.IsAbstract)
                {
                    _options.RegisterStream(type);
                }
                else if (typeof(RtmpController).IsAssignableFrom(type) && !type.IsAbstract)
                {
                    _options.RegisterController(type);
                }

                if (typeof(LivingController).IsAssignableFrom(type))
                {
                    registerInternalControllers = false;
                }
                if (_useWebSocket)
                {
                    if (typeof(WebSocketController).IsAssignableFrom(type) && !type.IsAbstract)
                    {
                        _websocketOptions.RegisterController(type);
                    }
                    if (typeof(WebSocketPlayController).IsAssignableFrom(type))
                    {
                        registerInternalControllers = false;
                    }
                }
            }

            if (registerInternalControllers)
            {
                _options.RegisterController<LivingController>();
                _options.RegisterStream<LivingStream>();
                _options.RegisterStream<RecordStream>();
                _options.RegisterController<RecordController>();
                if (_useWebSocket)
                {
                    _websocketOptions.RegisterController<WebSocketPlayController>();
                }
            }
           
            if (_useSsl)
            {
                _options.Cert = _cert;
            }
            _options.CleanupRpcRegistration();
            _options.BuildContainer();
            var ret = new RtmpServer(_options, _websocketOptions);
            return ret;
        }

    }
}

================================================
FILE: Harmonic/Hosting/RtmpServerOptions.cs
================================================
using Autofac;
using Harmonic.Controllers;
using Harmonic.Controllers.Living;
using Harmonic.Networking.Rtmp;
using Harmonic.Networking.Rtmp.Data;
using Harmonic.Networking.Rtmp.Messages;
using Harmonic.Networking.Rtmp.Messages.Commands;
using Harmonic.Networking.Rtmp.Messages.UserControlMessages;
using Harmonic.Networking.Rtmp.Serialization;
using Harmonic.Rpc;
using Harmonic.Service;
using System;
using System.Collections.Generic;
using System.Net;
using System.Reflection;
using System.Text;
using System.Security.Cryptography.X509Certificates;

namespace Harmonic.Hosting
{
    public class RtmpServerOptions
    {
        internal Dictionary<MessageType, MessageFactory> _messageFactories = new Dictionary<MessageType, MessageFactory>();
        public IReadOnlyDictionary<MessageType, MessageFactory> MessageFactories => _messageFactories;
        public delegate Message MessageFactory(MessageHeader header, Networking.Rtmp.Serialization.SerializationContext context, out int consumed);
        private Dictionary<string, Type> _registeredControllers = new Dictionary<string, Type>();
        internal ContainerBuilder _builder = null;
        private RpcService _rpcService = null;
        internal IStartup _startup = null;
        internal IStartup Startup
        {
            get
            {
                return _startup;
            }
            set
            {
                _startup = value;
                _builder = new ContainerBuilder();
                _startup.ConfigureServices(_builder);
                RegisterCommonServices(_builder);
            }
        }
        internal IContainer ServiceContainer { get; private set; }
        internal ILifetimeScope ServerLifetime { get; private set; }

        internal IReadOnlyDictionary<string, Type> RegisteredControllers => _registeredControllers;
        internal IPEndPoint RtmpEndPoint { get; set; } = new IPEndPoint(IPAddress.Any, 1935);
        internal bool UseUdp { get; set; } = true;
        internal bool UseWebsocket { get; set; } = true;
        internal X509Certificate2 Cert { get; set; }

        internal RtmpServerOptions()
        {
            var userControlMessageFactory = new UserControlMessageFactory();
            var commandMessageFactory = new CommandMessageFactory();
            RegisterMessage<AbortMessage>();
            RegisterMessage<AcknowledgementMessage>();
            RegisterMessage<SetChunkSizeMessage>();
            RegisterMessage<SetPeerBandwidthMessage>();
            RegisterMessage<WindowAcknowledgementSizeMessage>();
            RegisterMessage<DataMessage>((MessageHeader header, SerializationContext context, out int consumed) =>
            {
                consumed = 0;
                return new DataMessage(header.MessageType == MessageType.Amf0Data ? AmfEncodingVersion.Amf0 : AmfEncodingVersion.Amf3);
            });
            RegisterMessage<VideoMessage>();
            RegisterMessage<AudioMessage>();
            RegisterMessage<UserControlMessage>(userControlMessageFactory.Provide);
            RegisterMessage<CommandMessage>(commandMessageFactory.Provide);
            _rpcService = new RpcService();
        }

        internal void BuildContainer()
        {
            ServiceContainer = _builder.Build();
            ServerLifetime = ServiceContainer.BeginLifetimeScope();
        }

        public void RegisterMessage<T>(MessageFactory factory) where T : Message
        {
            var tType = typeof(T);
            var attr = tType.GetCustomAttribute<RtmpMessageAttribute>();
            if (attr == null)
            {
                throw new InvalidOperationException();
            }

            foreach (var messageType in attr.MessageTypes)
            {
                _messageFactories.Add(messageType, factory);
            }
        }

        public void RegisterMessage<T>() where T : Message, new()
        {
            var tType = typeof(T);
            var attr = tType.GetCustomAttribute<RtmpMessageAttribute>();
            if (attr == null)
            {
                throw new InvalidOperationException();
            }

            foreach (var messageType in attr.MessageTypes)
            {
                _messageFactories.Add(messageType, (MessageHeader a, SerializationContext b, out int c) =>
                {
                    c = 0;
                    return new T();
                });
            }
        }

        internal void RegisterController(Type controllerType, string appName = null)
        {
            if (!typeof(RtmpController).IsAssignableFrom(controllerType))
            {
                throw new InvalidOperationException("controllerType must inherit from AbstractController");
            }
            var name = appName ?? controllerType.Name.Replace("Controller", "");
            _registeredControllers.Add(name.ToLower(), controllerType);
            _rpcService.RegeisterController(controllerType);
            _builder.RegisterType(controllerType).AsSelf();
        }
        internal void RegisterStream(Type streamType)
        {
            if (!typeof(NetStream).IsAssignableFrom(streamType))
            {
                throw new InvalidOperationException("streamType must inherit from NetStream");
            }
            _rpcService.RegeisterController(streamType);
            _builder.RegisterType(streamType).AsSelf();
        }

        internal void CleanupRpcRegistration()
        {
            _rpcService.CleanupRegistration();
        }
        private void RegisterCommonServices(ContainerBuilder builder)
        {
            builder.Register(c => new RecordServiceConfiguration())
                .AsSelf();
            builder.Register(c => new RecordService(c.Resolve<RecordServiceConfiguration>()))
                .AsSelf()
                .InstancePerLifetimeScope();
            builder.Register(c => new PublisherSessionService())
                .AsSelf()
                .InstancePerLifetimeScope();
            builder.Register(c => _rpcService)
                .AsSelf()
                .SingleInstance();
        }

        internal void RegisterController<T>(string appName = null) where T : RtmpController
        {
            RegisterController(typeof(T), appName);
        }
        internal void RegisterStream<T>() where T : NetStream
        {
            RegisterStream(typeof(T));
        }
    }
}


================================================
FILE: Harmonic/Hosting/WebSocketOptions.cs
================================================
using Autofac;
using Harmonic.Controllers;
using System;
using System.Collections.Generic;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;

namespace Harmonic.Hosting
{
    public class WebSocketOptions
    {
        public IPEndPoint BindEndPoint { get; set; }
        public Regex UrlMapping { get; set; } = new Regex(@"/(?<controller>[a-zA-Z0-9]+)/(?<streamName>[a-zA-Z0-9\.]+)", RegexOptions.IgnoreCase);

        internal Dictionary<string, Type> _controllers = new Dictionary<string, Type>();

        internal RtmpServerOptions _serverOptions = null;

        internal void RegisterController<T>() where T: WebSocketController
        {
            RegisterController(typeof(T));
        }

        internal void RegisterController(Type controllerType)
        {
            if (!typeof(WebSocketController).IsAssignableFrom(controllerType))
            {
                throw new ArgumentException("controller not inherit from WebSocketController");
            }
            _controllers.Add(controllerType.Name.Replace("Controller", "").ToLower(), controllerType);
            _serverOptions._builder.RegisterType(controllerType).AsSelf();
        }

    }
}


================================================
FILE: Harmonic/Networking/Amf/Common/Amf3Object.cs
================================================
using Harmonic.Networking.Amf.Data;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Harmonic.Networking.Amf.Common
{
    public class AmfObject : IDynamicObject, IEnumerable
    {
        private Dictionary<string, object> _fields = new Dictionary<string, object>();

        private Dictionary<string, object> _dynamicFields = new Dictionary<string, object>();

        public bool IsAnonymous { get => GetType() == typeof(AmfObject); }
        public bool IsDynamic { get => _dynamicFields.Any(); }

        public IReadOnlyDictionary<string, object> DynamicFields { get => _dynamicFields; }

        public IReadOnlyDictionary<string, object> Fields { get => _fields; }

        public AmfObject()
        {

        }

        public AmfObject(Dictionary<string, object> values)
        {
            _fields = values;
        }

        public void Add(string memberName, object member)
        {
            _fields.Add(memberName, member);
        }

        public void AddDynamic(string memberName, object member)
        {
            _dynamicFields.Add(memberName, member);
        }

        public IEnumerator GetEnumerator()
        {
            return ((IEnumerable)Fields).GetEnumerator();
        }
    }
}


================================================
FILE: Harmonic/Networking/Amf/Common/TypeRegisterState.cs
================================================
using System;
using System.Collections.Generic;
using System.Text;

namespace Harmonic.Networking.Amf.Common
{
    class TypeRegisterState
    {
        public Type Type { get; set; }
        public Dictionary<string, Action<object, object>> Members { get; set; }
    }
}


================================================
FILE: Harmonic/Networking/Amf/Common/Undefined.cs
================================================
using System;
using System.Collections.Generic;
using System.Text;

namespace Harmonic.Networking.Amf.Common
{
    public class Undefined
    {
    }
}


================================================
FILE: Harmonic/Networking/Amf/Common/Unsupported.cs
================================================
using System;
using System.Collections.Generic;
using System.Text;

namespace Harmonic.Networking.Amf.Common
{
    public class Unsupported
    {
    }
}


================================================
FILE: Harmonic/Networking/Amf/Data/IDynamicObject.cs
================================================
using System;
using System.Collections.Generic;
using System.Text;

namespace Harmonic.Networking.Amf.Data
{
    public interface IDynamicObject
    {
        IReadOnlyDictionary<string, object> DynamicFields { get; }

        void AddDynamic(string key, object data);
    }
}


================================================
FILE: Harmonic/Networking/Amf/Data/IExternalizable.cs
================================================
using Harmonic.Buffers;
using System;
using System.Collections.Generic;
using System.Text;

namespace Harmonic.Networking.Amf.Data
{
    public interface IExternalizable
    {
        bool TryDecodeData(Span<byte> buffer, out int consumed);

        bool TryEncodeData(ByteBuffer buffer);
    }
}


================================================
FILE: Harmonic/Networking/Amf/Data/Message.cs
================================================
using System;
using System.Collections.Generic;
using System.Text;

namespace Harmonic.Networking.Amf.Data
{
    public class Message
    {
        public string TargetUri { get; set; }
        public string ResponseUri { get; set; }
        public object Content { get; set; }
    }
}


================================================
FILE: Harmonic/Networking/Amf/Serialization/Amf0/Amf0CommonValues.cs
================================================
using Harmonic.Networking.Amf.Common;
using Harmonic.Networking.Rtmp.Data;
using Harmonic.Networking.Rtmp.Serialization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;

namespace Harmonic.Networking.Amf.Serialization.Amf0
{
    public static class Amf0CommonValues
    {
        public static readonly int TIMEZONE_LENGTH = 2;
        public static readonly int MARKER_LENGTH = 1;
        public static readonly int STRING_HEADER_LENGTH = sizeof(ushort);
        public static readonly int LONG_STRING_HEADER_LENGTH = sizeof(uint);
    }
}


================================================
FILE: Harmonic/Networking/Amf/Serialization/Amf0/Amf0Reader.cs
================================================
using Harmonic.Networking.Amf.Attributes;
using Harmonic.Networking.Amf.Common;
using Harmonic.Networking.Amf.Data;
using Harmonic.Networking.Amf.Serialization.Amf3;
using Harmonic.Networking.Amf.Serialization.Attributes;
using Harmonic.Networking.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Xml;

namespace Harmonic.Networking.Amf.Serialization.Amf0
{
    public class Amf0Reader
    {
        public readonly IReadOnlyDictionary<Amf0Type, long> TypeLengthMap = new Dictionary<Amf0Type, long>()
        {
            { Amf0Type.Number, 8 },
            { Amf0Type.Boolean, sizeof(byte) },
            { Amf0Type.String, Amf0CommonValues.STRING_HEADER_LENGTH },
            { Amf0Type.LongString, Amf0CommonValues.LONG_STRING_HEADER_LENGTH },
            { Amf0Type.Object, /* object marker*/ Amf0CommonValues.MARKER_LENGTH - /* utf8-empty */Amf0CommonValues.STRING_HEADER_LENGTH - /* object end marker */Amf0CommonValues.MARKER_LENGTH },
            { Amf0Type.Null, 0 },
            { Amf0Type.Undefined, 0 },
            { Amf0Type.Reference, sizeof(ushort) },
            { Amf0Type.EcmaArray, sizeof(uint) },
            { Amf0Type.StrictArray, sizeof(uint) },
            { Amf0Type.Date, 10 },
            { Amf0Type.Unsupported, 0 },
            { Amf0Type.XmlDocument, 0 },
            { Amf0Type.TypedObject, /* object marker*/ Amf0CommonValues.MARKER_LENGTH - /* class name */ Amf0CommonValues.STRING_HEADER_LENGTH - /* at least on character for class name */ 1 - /* utf8-empty */Amf0CommonValues.STRING_HEADER_LENGTH - /* object end marker */Amf0CommonValues.MARKER_LENGTH },
            { Amf0Type.AvmPlusObject, 0 },
            { Amf0Type.ObjectEnd, 0 }
        };

        private delegate bool ReadDataHandler<T>(Span<byte> buffer, out T data, out int consumedLength);
        private delegate bool ReadDataHandler(Span<byte> buffer, out object data, out int consumedLength);

        private List<Type> _registeredTypes = new List<Type>();
        public IReadOnlyList<Type> RegisteredTypes { get; }
        private IReadOnlyDictionary<Amf0Type, ReadDataHandler> _readDataHandlers;
        private Dictionary<string, TypeRegisterState> _registeredTypeStates = new Dictionary<string, TypeRegisterState>();
        private List<object> _referenceTable = new List<object>();
        private Amf3.Amf3Reader _amf3Reader = new Amf3.Amf3Reader();
        public bool StrictMode { get; set; } = true;

        public Amf0Reader()
        {
            var readDataHandlers = new Dictionary<Amf0Type, ReadDataHandler>
            {
                [Amf0Type.Number] = OutValueTypeEraser<double>(TryGetNumber),
                [Amf0Type.Boolean] = OutValueTypeEraser<bool>(TryGetBoolean),
                [Amf0Type.String] = OutValueTypeEraser<string>(TryGetString),
                [Amf0Type.Object] = OutValueTypeEraser<AmfObject>(TryGetObject),
                [Amf0Type.Null] = OutValueTypeEraser<object>(TryGetNull),
                [Amf0Type.Undefined] = OutValueTypeEraser<Undefined>(TryGetUndefined),
                [Amf0Type.Reference] = OutValueTypeEraser<object>(TryGetReference),
                [Amf0Type.EcmaArray] = OutValueTypeEraser<Dictionary<string, object>>(TryGetEcmaArray),
                [Amf0Type.StrictArray] = OutValueTypeEraser<List<object>>(TryGetStrictArray),
                [Amf0Type.Date] = OutValueTypeEraser<DateTime>(TryGetDate),
                [Amf0Type.LongString] = OutValueTypeEraser<string>(TryGetLongString),
                [Amf0Type.Unsupported] = OutValueTypeEraser<Unsupported>(TryGetUnsupported),
                [Amf0Type.XmlDocument] = OutValueTypeEraser<XmlDocument>(TryGetXmlDocument),
                [Amf0Type.TypedObject] = OutValueTypeEraser<object>(TryGetTypedObject),
                [Amf0Type.AvmPlusObject] = OutValueTypeEraser<object>(TryGetAvmPlusObject)
            };
            _readDataHandlers = readDataHandlers;
        }

        public void ResetReference()
        {
            _referenceTable.Clear();
        }
        public void RegisterType<T>() where T : new()
        {
            var type = typeof(T);
            var props = type.GetProperties();
            var fields = props.Where(p => p.CanWrite && Attribute.GetCustomAttribute(p, typeof(ClassFieldAttribute)) != null).ToList();
            var members = fields.ToDictionary(p => ((ClassFieldAttribute)Attribute.GetCustomAttribute(p, typeof(ClassFieldAttribute))).Name ?? p.Name, p => new Action<object, object>(p.SetValue));
            if (members.Keys.Where(s => string.IsNullOrEmpty(s)).Any())
            {
                throw new InvalidOperationException("Field name cannot be empty or null");
            }
            string mapedName = null;
            var attr = type.GetCustomAttribute<TypedObjectAttribute>();
            if (attr != null)
            {
                mapedName = attr.Name;
            }
            var typeName = mapedName == null ? type.Name : mapedName;
            var state = new TypeRegisterState()
            {
                Members = members,
                Type = type
            };
            _registeredTypes.Add(type);
            _registeredTypeStates.Add(typeName, state);
            _amf3Reader.RegisterTypedObject(typeName, state);
        }

        public void RegisterIExternalizableForAvmPlus<T>() where T : IExternalizable, new()
        {
            _amf3Reader.RegisterExternalizable<T>();
        }

        private ReadDataHandler OutValueTypeEraser<T>(ReadDataHandler<T> handler)
        {
            return (Span<byte> b, out object d, out int c) =>
            {
                var ret = handler(b, out var n, out c);
                d = n;
                return ret;
            };
        }

        private bool TryReadHeader(Span<byte> buffer, out KeyValuePair<string, object> header, out int consumed)
        {
            header = default;
            consumed = 0;
            if (!TryGetStringImpl(buffer, Amf0.Amf0CommonValues.STRING_HEADER_LENGTH, out var headerName, out var nameConsumed))
            {
                return false;
            }

            buffer = buffer.Slice(nameConsumed);
            if (buffer.Length < 1)
            {
                return false;
            }
            var mustUnderstand = buffer[0];
            buffer = buffer.Slice(1);
            if (buffer.Length < sizeof(uint))
            {
                return false;
            }

            buffer = buffer.Slice(sizeof(uint));
            if (!TryGetValue(buffer, out _, out var headerValue, out var valueConsumed))
            {
                return false;
            }
            header = new KeyValuePair<string, object>(headerName, headerValue);
            consumed = nameConsumed + 1 + sizeof(uint) + valueConsumed;
            return true;
        }

        public bool TryGetMessage(Span<byte> buffer, out Message message, out int consumed)
        {
            message = default;
            consumed = default;

            if (!TryGetStringImpl(buffer, Amf0CommonValues.STRING_HEADER_LENGTH, out var targetUri, out var targetUriConsumed))
            {
                return false;
            }

            buffer = buffer.Slice(targetUriConsumed);
            if (!TryGetStringImpl(buffer, Amf0CommonValues.STRING_HEADER_LENGTH, out var responseUri, out var responseUriConsumed))
            {
                return false;
            }

            buffer = buffer.Slice(responseUriConsumed);
            if (buffer.Length < sizeof(uint))
            {
                return false;
            }
            var messageLength = NetworkBitConverter.ToUInt32(buffer);
            if (messageLength >= 0 && buffer.Length < messageLength)
            {
                return false;
            }
            if (messageLength == 0 && StrictMode)
            {
                return true;
            }
            buffer = buffer.Slice(sizeof(uint));
            if (!TryGetValue(buffer, out _, out var content, out var contentConsumed))
            {
                return false;
            }
            consumed = targetUriConsumed + responseUriConsumed + sizeof(uint) + contentConsumed;
            message = new Message()
            {
                TargetUri = targetUri,
                ResponseUri = responseUri,
                Content = content
            };
            return true;
        }

        public bool TryGetPacket(Span<byte> buffer, out List<KeyValuePair<string, object>> headers, out List<Message> messages, out int consumed)
        {
            headers = default;
            messages = default;
            consumed = 0;

            if (buffer.Length < 1)
            {
                return false;
            }
            var version = NetworkBitConverter.ToUInt16(buffer);
            buffer = buffer.Slice(sizeof(ushort));
            consumed += sizeof(ushort);
            var headerCount = NetworkBitConverter.ToUInt16(buffer);
            buffer = buffer.Slice(sizeof(ushort));
            consumed += sizeof(ushort);
            headers = new List<KeyValuePair<string, object>>();
            messages = new List<Message>();
            for (int i = 0; i < headerCount; i++)
            {
                if (!TryReadHeader(buffer, out var header, out var headerConsumed))
                {
                    return false;
                }
                headers.Add(header);
                buffer = buffer.Slice(headerConsumed);
                consumed += headerConsumed;
            }

            var messageCount = NetworkBitConverter.ToUInt16(buffer);
            buffer = buffer.Slice(sizeof(ushort));
            consumed += sizeof(ushort);
            for (int i = 0; i < messageCount; i++)
            {
                if (!TryGetMessage(buffer, out var message, out var messageConsumed))
                {
                    return false;
                }
                messages.Add(message);
                consumed += messageConsumed;
            }
            return true;
        }

        public bool TryDescribeData(Span<byte> buffer, out Amf0Type type, out int consumedLength)
        {
            type = default;
            consumedLength = default;
            if (buffer.Length < Amf0CommonValues.MARKER_LENGTH)
            {
                return false;
            }

            var marker = (Amf0Type)buffer[0];
            if (!TypeLengthMap.TryGetValue(marker, out var bytesNeed))
            {
                return false;
            }
            if (buffer.Length - Amf0CommonValues.MARKER_LENGTH < bytesNeed)
            {
                return false;
            }

            type = marker;
            consumedLength = (int)bytesNeed + Amf0CommonValues.MARKER_LENGTH;

            return true;
        }

        public bool TryGetNumber(Span<byte> buffer, out double value, out int bytesConsumed)
        {
            value = default;
            bytesConsumed = default;
            if (!TryDescribeData(buffer, out var type, out var length))
            {
                return false;
            }
            if (type != Amf0Type.Number)
            {
                return false;
            }
            value = NetworkBitConverter.ToDouble(buffer.Slice(Amf0CommonValues.MARKER_LENGTH));
            bytesConsumed = length;
            return true;
        }

        public bool TryGetBoolean(Span<byte> buffer, out bool value, out int bytesConsumed)
        {
            value = default;
            bytesConsumed = default;

            if (!TryDescribeData(buffer, out var type, out var length))
            {
                return false;
            }

            if (type != Amf0Type.Boolean)
            {
                return false;
            }

            value = buffer[1] != 0;
            bytesConsumed = length;
            return true;
        }
        public bool TryGetString(Span<byte> buffer, out string value, out int bytesConsumed)
        {
            value = default;
            bytesConsumed = default;

            if (!TryDescribeData(buffer, out var type, out _))
            {
                return false;
            }

            if (type != Amf0Type.String)
            {
                return false;
            }

            if (!TryGetStringImpl(buffer.Slice(Amf0CommonValues.MARKER_LENGTH), Amf0CommonValues.STRING_HEADER_LENGTH, out value, out bytesConsumed))
            {
                return false;
            }

            bytesConsumed += Amf0CommonValues.MARKER_LENGTH;
            _referenceTable.Add(value);
            return true;
        }

        private bool TryGetObjectImpl(Span<byte> objectBuffer, out Dictionary<string, object> value, out int bytesConsumed)
        {
            value = default;
            bytesConsumed = default;
            var obj = new Dictionary<string, object>();
            _referenceTable.Add(obj);
            var consumed = 0;
            while (true)
            {
                if (!TryGetStringImpl(objectBuffer, Amf0CommonValues.STRING_HEADER_LENGTH, out var key, out var keyLength))
                {
                    return false;
                }
                consumed += keyLength;
                objectBuffer = objectBuffer.Slice(keyLength);

                if (!TryGetValue(objectBuffer, out var dataType, out var data, out var valueLength))
                {
                    return false;
                }
                consumed += valueLength;
                objectBuffer = objectBuffer.Slice(valueLength);

                if (!key.Any() && dataType == Amf0Type.ObjectEnd)
                {
                    break;
                }
                obj.Add(key, data);
            }
            value = obj;
            bytesConsumed = consumed;
            return true;
        }

        public bool TryGetObject(Span<byte> buffer, out AmfObject value, out int bytesConsumed)
        {
            value = default;
            bytesConsumed = default;

            if (!TryDescribeData(buffer, out var type, out _))
            {
                return false;
            }

            if (type == Amf0Type.Null)
            {
                if (!TryGetNull(buffer, out _, out bytesConsumed))
                {
                    return false;
                }
                value = null;
                return true;
            }

            if (type != Amf0Type.Object)
            {
                return false;
            }

            var objectBuffer = buffer.Slice(Amf0CommonValues.MARKER_LENGTH);

            if (!TryGetObjectImpl(objectBuffer, out var obj, out var consumed))
            {
                return false;
            }

            value = new AmfObject(obj);
            bytesConsumed = consumed + Amf0CommonValues.MARKER_LENGTH;


            return true;
        }

        public bool TryGetNull(Span<byte> buffer, out object value, out int bytesConsumed)
        {
            value = default;
            bytesConsumed = default;
            if (!TryDescribeData(buffer, out var type, out var length))
            {
                return false;
            }

            if (type != Amf0Type.Null)
            {
                return false;
            }
            value = null;
            bytesConsumed = Amf0CommonValues.MARKER_LENGTH;
            return true;
        }

        public bool TryGetUndefined(Span<byte> buffer, out Undefined value, out int consumedLength)
        {
            value = default;
            consumedLength = default;
            if (!TryDescribeData(buffer, out var type, out var length))
            {
                return false;
            }

            if (type != Amf0Type.Undefined)
            {
                return false;
            }
            value = new Undefined();
            consumedLength = Amf0CommonValues.MARKER_LENGTH;
            return true;
        }

        private bool TryGetReference(Span<byte> buffer, out object value, out int consumedLength)
        {
            var index = 0;
            value = default;
            consumedLength = default;
            if (!TryDescribeData(buffer, out var type, out var length))
            {
                return false;
            }

            if (type != Amf0Type.Reference)
            {
                return false;
            }

            index = NetworkBitConverter.ToUInt16(buffer.Slice(Amf0CommonValues.MARKER_LENGTH, sizeof(ushort)));
            consumedLength = Amf0CommonValues.MARKER_LENGTH + sizeof(ushort);
            if (_referenceTable.Count <= index)
            {
                return false;
            }
            value = _referenceTable[index];
            return true;
        }

        private bool TryGetKeyValuePair(Span<byte> buffer, out KeyValuePair<string, object> value, out bool kvEnd, out int consumed)
        {
            value = default;
            kvEnd = default;

            consumed = 0;
            if (!TryGetStringImpl(buffer, Amf0CommonValues.STRING_HEADER_LENGTH, out var key, out var keyLength))
            {
                return false;
            }
            consumed += keyLength;
            if (buffer.Length - keyLength < 0)
            {
                return false;
            }
            buffer = buffer.Slice(keyLength);

            if (!TryGetValue(buffer, out var elementType, out var element, out var valueLength))
            {
                return false;
            }
            consumed += valueLength;
            value = new KeyValuePair<string, object>(key, element);
            kvEnd = !key.Any() && elementType == Amf0Type.ObjectEnd;

            return true;
        }

        public bool TryGetEcmaArray(Span<byte> buffer, out Dictionary<string, object> value, out int consumedLength)
        {
            value = default;
            consumedLength = default;
            int consumed = 0;

            if (!TryDescribeData(buffer, out var type, out _))
            {
                return false;
            }

            if (type != Amf0Type.EcmaArray)
            {
                return false;
            }

            var obj = new Dictionary<string, object>();
            _referenceTable.Add(obj);

            var elementCount = NetworkBitConverter.ToUInt32(buffer.Slice(Amf0CommonValues.MARKER_LENGTH, sizeof(uint)));

            var arrayBodyBuffer = buffer.Slice(Amf0CommonValues.MARKER_LENGTH + sizeof(uint));
            consumed = Amf0CommonValues.MARKER_LENGTH + sizeof(uint);
            if (StrictMode)
            {
                for (int i = 0; i < elementCount; i++)
                {
                    if (!TryGetKeyValuePair(arrayBodyBuffer, out var kv, out _, out var kvConsumed))
                    {
                        return false;
                    }
                    arrayBodyBuffer = arrayBodyBuffer.Slice(kvConsumed);
                    consumed += kvConsumed;
                    obj.Add(kv.Key, kv.Value);
                }
                if (!TryGetStringImpl(arrayBodyBuffer, Amf0CommonValues.STRING_HEADER_LENGTH, out var emptyStr, out var emptyStrConsumed))
                {
                    return false;
                }
                if (emptyStr.Any())
                {
                    return false;
                }
                consumed += emptyStrConsumed;
                arrayBodyBuffer = arrayBodyBuffer.Slice(emptyStrConsumed);
                if (!TryDescribeData(arrayBodyBuffer, out var objEndType, out var objEndConsumed))
                {
                    return false;
                }
                if (objEndType != Amf0Type.ObjectEnd)
                {
                    return false;
                }
                consumed += objEndConsumed;
            }
            else
            {
                while (true)
                {
                    if (!TryGetKeyValuePair(arrayBodyBuffer, out var kv, out var isEnd, out var kvConsumed))
                    {
                        return false;
                    }
                    arrayBodyBuffer = arrayBodyBuffer.Slice(kvConsumed);
                    consumed += kvConsumed;
                    if (isEnd)
                    {
                        break;
                    }
                    obj.Add(kv.Key, kv.Value);
                }
            }


            value = obj;
            consumedLength = consumed;
            return true;
        }

        public bool TryGetStrictArray(Span<byte> buffer, out List<object> array, out int consumedLength)
        {
            array = default;
            consumedLength = default;

            if (!TryDescribeData(buffer, out var type, out _))
            {
                return false;
            }

            if (type != Amf0Type.StrictArray)
            {
                return false;
            }

            var obj = new List<object>();
            _referenceTable.Add(obj);

            var elementCount = NetworkBitConverter.ToUInt32(buffer.Slice(Amf0CommonValues.MARKER_LENGTH, sizeof(uint)));

            int consumed = Amf0CommonValues.MARKER_LENGTH + sizeof(uint);
            var arrayBodyBuffer = buffer.Slice(consumed);
            var elementBodyBuffer = arrayBodyBuffer;
            System.Diagnostics.Debug.WriteLine(elementCount);
            for (uint i = 0; i < elementCount; i++)
            {
                if (!TryGetValue(elementBodyBuffer, out _, out var element, out var bufferConsumed))
                {
                    return false;
                }

                obj.Add(element);
                if (elementBodyBuffer.Length - bufferConsumed < 0)
                {
                    return false;
                }
                elementBodyBuffer = elementBodyBuffer.Slice(bufferConsumed);
                consumed += bufferConsumed;
            }
            array = obj;
            consumedLength = consumed;

            return true;
        }

        public bool TryGetDate(Span<byte> buffer, out DateTime value, out int consumendLength)
        {
            value = default;
            consumendLength = default;

            if (!TryDescribeData(buffer, out var type, out var length))
            {
                return false;
            }

            if (type != Amf0Type.Date)
            {
                return false;
            }

            var timestamp = NetworkBitConverter.ToDouble(buffer.Slice(Amf0CommonValues.MARKER_LENGTH));
            value = DateTimeOffset.FromUnixTimeMilliseconds((long)timestamp).LocalDateTime;
            consumendLength = length;
            return true;
        }

        public bool TryGetLongString(Span<byte> buffer, out string value, out int consumedLength)
        {
            value = default;
            consumedLength = default;

            if (!TryDescribeData(buffer, out var type, out _))
            {
                return false;
            }

            if (type != Amf0Type.LongString)
            {
                return false;
            }

            if (!TryGetStringImpl(buffer.Slice(Amf0CommonValues.MARKER_LENGTH), Amf0CommonValues.LONG_STRING_HEADER_LENGTH, out value, out consumedLength))
            {
                return false;
            }

            consumedLength += Amf0CommonValues.MARKER_LENGTH;

            return true;
        }

        internal bool TryGetStringImpl(Span<byte> buffer, int lengthOfLengthField, out string value, out int consumedLength)
        {
            value = default;
            consumedLength = default;
            var stringLength = 0;
            if (lengthOfLengthField == Amf0CommonValues.STRING_HEADER_LENGTH)
            {
                stringLength = (int)NetworkBitConverter.ToUInt16(buffer);
            }
            else
            {
                stringLength = (int)NetworkBitConverter.ToUInt32(buffer);
            }

            if (buffer.Length - lengthOfLengthField < stringLength)
            {
                return false;
            }

            value = Encoding.UTF8.GetString(buffer.Slice(lengthOfLengthField, stringLength));
            consumedLength = lengthOfLengthField + stringLength;
            return true;
        }

        private bool TryGetUnsupported(Span<byte> buffer, out Unsupported value, out int consumedLength)
        {
            value = default;
            consumedLength = default;

            if (!TryDescribeData(buffer, out var type, out var length))
            {
                return false;
            }

            if (type != Amf0Type.Unsupported)
            {
                return false;
            }

            value = new Unsupported();
            consumedLength = Amf0CommonValues.MARKER_LENGTH;

            return true;
        }

        public bool TryGetXmlDocument(Span<byte> buffer, out XmlDocument value, out int consumedLength)
        {
            value = default;
            consumedLength = default;
            if (!TryDescribeData(buffer, out var type, out _))
            {
                return false;
            }

            if (!TryGetStringImpl(buffer.Slice(Amf0CommonValues.MARKER_LENGTH), Amf0CommonValues.LONG_STRING_HEADER_LENGTH, out var str, out consumedLength))
            {
                return false;
            }

            value = new XmlDocument();
            value.LoadXml(str);
            consumedLength += Amf0CommonValues.MARKER_LENGTH;

            return true;
        }

        public bool TryGetTypedObject(Span<byte> buffer, out object value, out int consumedLength)
        {
            value = default;
            consumedLength = default;

            if (!TryDescribeData(buffer, out var type, out _))
            {
                return true;
            }

            if (type != Amf0Type.TypedObject)
            {
                return false;
            }

            var consumed = Amf0CommonValues.MARKER_LENGTH;

            if (!TryGetStringImpl(buffer.Slice(Amf0CommonValues.MARKER_LENGTH), Amf0CommonValues.STRING_HEADER_LENGTH, out var className, out var stringLength))
            {
                return false;
            }

            consumed += stringLength;

            var objectBuffer = buffer.Slice(consumed);

            if (!TryGetObjectImpl(objectBuffer, out var dict, out var objectConsumed))
            {
                return false;
            }

            consumed += objectConsumed;

            if (!_registeredTypeStates.TryGetValue(className, out var state))
            {
                return false;
            }
            var objectType = state.Type;
            var obj = Activator.CreateInstance(objectType);

            if (state.Members.Keys.Except(dict.Keys).Any())
            {
                return false;
            }
            else if (dict.Keys.Except(state.Members.Keys).Any())
            {
                return false;
            }

            foreach ((var name, var setter) in state.Members)
            {
                setter(obj, dict[name]);
            }

            value = obj;
            consumedLength = consumed;

            return true;
        }

        public bool TryGetAvmPlusObject(Span<byte> buffer, out object value, out int consumed)
        {
            value = default;
            consumed = default;

            if (!TryDescribeData(buffer, out var type, out _))
            {
                return false;
            }
            if (type != Amf0Type.AvmPlusObject)
            {
                return false;
            }

            buffer = buffer.Slice(Amf0CommonValues.MARKER_LENGTH);

            if (!_amf3Reader.TryGetValue(buffer, out value, out consumed))
            {
                return false;
            }

            consumed += Amf0CommonValues.MARKER_LENGTH;

            return true;
        }

        public bool TryGetValue(Span<byte> objectBuffer, out Amf0Type objectType, out object data, out int valueLength)
        {
            data = default;
            valueLength = default;
            objectType = default;
            if (!TryDescribeData(objectBuffer, out var type, out var length))
            {
                return false;
            }

            if (type == Amf0Type.ObjectEnd)
            {
                objectType = type;
                valueLength = Amf0CommonValues.MARKER_LENGTH;
                return true;
            }

            if (!_readDataHandlers.TryGetValue(type, out var handler))
            {
                return false;
            }

            if (!handler(objectBuffer, out data, out valueLength))
            {
                return false;
            }
            objectType = type;
            return true;
        }
    }
}


================================================
FILE: Harmonic/Networking/Amf/Serialization/Amf0/Amf0Type.cs
================================================
using System;
using System.Collections.Generic;
using System.Text;

namespace Harmonic.Networking.Amf.Serialization.Amf0
{
    public enum Amf0Type
    {
        Number,
        Boolean,
        String,
        Object,
        Moveclip,
        Null,
        Undefined,
        Reference,
        EcmaArray,
        ObjectEnd,
        StrictArray,
        Date,
        LongString,
        Unsupported,
        Recordset,
        XmlDocument,
        TypedObject,
        AvmPlusObject
    }
}


================================================
FILE: Harmonic/Networking/Amf/Serialization/Amf0/Amf0Writer.cs
================================================
using Harmonic.Buffers;
using Harmonic.Networking.Amf.Attributes;
using Harmonic.Networking.Amf.Common;
using Harmonic.Networking.Amf.Serialization.Attributes;
using Harmonic.Networking.Utils;
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.IO;
using System.IO.Pipelines;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Xml;

namespace Harmonic.Networking.Amf.Serialization.Amf0
{
    public class Amf0Writer
    {
        private delegate void GetBytesHandler<T>(T value, SerializationContext context);
        private delegate void GetBytesHandler(object value, SerializationContext context);
        private IReadOnlyDictionary<Type, GetBytesHandler> _getBytesHandlers = null;
        private ArrayPool<byte> _arrayPool = ArrayPool<byte>.Shared;

        public Amf0Writer()
        {
            var getBytesHandlers = new Dictionary<Type, GetBytesHandler>();
            getBytesHandlers[typeof(double)] = GetBytesWrapper<double>(WriteBytes);
            getBytesHandlers[typeof(int)] = GetBytesWrapper<double>(WriteBytes);
            getBytesHandlers[typeof(short)] = GetBytesWrapper<double>(WriteBytes);
            getBytesHandlers[typeof(long)] = GetBytesWrapper<double>(WriteBytes);
            getBytesHandlers[typeof(uint)] = GetBytesWrapper<double>(WriteBytes);
            getBytesHandlers[typeof(ushort)] = GetBytesWrapper<double>(WriteBytes);
            getBytesHandlers[typeof(ulong)] = GetBytesWrapper<double>(WriteBytes);
            getBytesHandlers[typeof(float)] = GetBytesWrapper<double>(WriteBytes);
            getBytesHandlers[typeof(DateTime)] = GetBytesWrapper<DateTime>(WriteBytes);
            getBytesHandlers[typeof(string)] = GetBytesWrapper<string>(WriteBytes);
            getBytesHandlers[typeof(XmlDocument)] = GetBytesWrapper<XmlDocument>(WriteBytes);
            getBytesHandlers[typeof(Unsupported)] = GetBytesWrapper<Unsupported>(WriteBytes);
            getBytesHandlers[typeof(Undefined)] = GetBytesWrapper<Undefined>(WriteBytes);
            getBytesHandlers[typeof(bool)] = GetBytesWrapper<bool>(WriteBytes);
            getBytesHandlers[typeof(object)] = GetBytesWrapper<object>(WriteTypedBytes);
            getBytesHandlers[typeof(AmfObject)] = GetBytesWrapper<AmfObject>(WriteBytes);
            getBytesHandlers[typeof(Dictionary<string, object>)] = GetBytesWrapper<Dictionary<string, object>>(WriteBytes);
            getBytesHandlers[typeof(List<object>)] = GetBytesWrapper<List<object>>(WriteBytes);
            _getBytesHandlers = getBytesHandlers;
        }


        private GetBytesHandler GetBytesWrapper<T>(GetBytesHandler<T> handler)
        {
            return (object v, SerializationContext context) =>
            {
                if (v is T tv)
                {
                    handler(tv, context);
                }
                else
                {
                    handler((T)Convert.ChangeType(v, typeof(T)), context);
                }
            };
        }

        public void WriteAvmPlusBytes(SerializationContext context)
        {
            context.Buffer.WriteToBuffer((byte)Amf0Type.AvmPlusObject);
        }

        private void WriteStringBytesImpl(string str, SerializationContext context, out bool isLongString, bool marker = false, bool forceLongString = false)
        {
            var bytesNeed = 0;
            var headerLength = 0;
            var bodyLength = 0;

            bodyLength = Encoding.UTF8.GetByteCount(str);
            bytesNeed += bodyLength;

            if (bodyLength > ushort.MaxValue || forceLongString)
            {
                headerLength = Amf0CommonValues.LONG_STRING_HEADER_LENGTH;
                isLongString = true;
                if (marker)
                {
                    context.Buffer.WriteToBuffer((byte)Amf0Type.LongString);
                }

            }
            else
            {
                isLongString = false;
                headerLength = Amf0CommonValues.STRING_HEADER_LENGTH;
                if (marker)
                {
                    context.Buffer.WriteToBuffer((byte)Amf0Type.String);
                }
            }
            bytesNeed += headerLength;
            var bufferBackend = _arrayPool.Rent(bytesNeed);
            try
            {
                var buffer = bufferBackend.AsSpan(0, bytesNeed);
                if (isLongString)
                {
                    NetworkBitConverter.TryGetBytes((uint)bodyLength, buffer);
                }
                else
                {
                    var contractRet = NetworkBitConverter.TryGetBytes((ushort)bodyLength, buffer);
                    Contract.Assert(contractRet);
                }

                Encoding.UTF8.GetBytes(str, buffer.Slice(headerLength));

                context.Buffer.WriteToBuffer(buffer);
            }
            finally
            {
                _arrayPool.Return(bufferBackend);
            }

        }

        public void WriteBytes(string str, SerializationContext context)
        {
            var bytesNeed = Amf0CommonValues.MARKER_LENGTH;

            var refIndex = context.ReferenceTable.IndexOf(str);

            if (refIndex != -1)
            {
                WriteReferenceIndexBytes((ushort)refIndex, context);
                return;
            }

            WriteStringBytesImpl(str, context, out var isLongString, true);
            context.ReferenceTable.Add(str);
        }

        public void WriteBytes(double val, SerializationContext context)
        {
            var bytesNeed = Amf0CommonValues.MARKER_LENGTH + sizeof(double);
            var bufferBackend = _arrayPool.Rent(bytesNeed);
            try
            {
                var buffer = bufferBackend.AsSpan(0, bytesNeed);
                buffer[0] = (byte)Amf0Type.Number;
                var contractRet = NetworkBitConverter.TryGetBytes(val, buffer.Slice(Amf0CommonValues.MARKER_LENGTH));
                Contract.Assert(contractRet);
                context.Buffer.WriteToBuffer(buffer);
            }
            finally
            {
                _arrayPool.Return(bufferBackend);
            }
        }

        public void WriteBytes(bool val, SerializationContext context)
        {
            var bytesNeed = Amf0CommonValues.MARKER_LENGTH + sizeof(byte);

            context.Buffer.WriteToBuffer((byte)Amf0Type.Boolean);
            context.Buffer.WriteToBuffer((byte)(val ? 1 : 0));

        }

        public void WriteBytes(Undefined value, SerializationContext context)
        {
            var bytesNeed = Amf0CommonValues.MARKER_LENGTH;
            var bufferBackend = _arrayPool.Rent(bytesNeed);

            context.Buffer.WriteToBuffer((byte)Amf0Type.Undefined);
        }

        public void WriteBytes(Unsupported value, SerializationContext context)
        {
            var bytesNeed = Amf0CommonValues.MARKER_LENGTH;
            context.Buffer.WriteToBuffer((byte)Amf0Type.Unsupported);
        }

        private void WriteReferenceIndexBytes(ushort index, SerializationContext context)
        {
            var bytesNeed = Amf0CommonValues.MARKER_LENGTH + sizeof(ushort);
            var backend = _arrayPool.Rent(bytesNeed);
            try
            {
                var buffer = backend.AsSpan(0, bytesNeed);
                buffer[0] = (byte)Amf0Type.Reference;
                var contractRet = NetworkBitConverter.TryGetBytes(index, buffer.Slice(Amf0CommonValues.MARKER_LENGTH));
                Contract.Assert(contractRet);
                context.Buffer.WriteToBuffer(buffer);
            }
            finally
            {
                _arrayPool.Return(backend);
            }

        }

        private void WriteObjectEndBytes(SerializationContext context)
        {
            var bytesNeed = Amf0CommonValues.MARKER_LENGTH;
            context.Buffer.WriteToBuffer((byte)Amf0Type.ObjectEnd);
        }

        public void WriteBytes(DateTime dateTime, SerializationContext context)
        {
            var bytesNeed = Amf0CommonValues.MARKER_LENGTH + sizeof(double) + sizeof(short);

            var backend = _arrayPool.Rent(bytesNeed);
            try
            {
                var buffer = backend.AsSpan(0, bytesNeed);
                buffer.Slice(0, bytesNeed).Clear();
                buffer[0] = (byte)Amf0Type.Date;
                var dof = new DateTimeOffset(dateTime);
                var timestamp = (double)dof.ToUnixTimeMilliseconds();
                var contractRet = NetworkBitConverter.TryGetBytes(timestamp, buffer.Slice(Amf0CommonValues.MARKER_LENGTH));
                Contract.Assert(contractRet);
                context.Buffer.WriteToBuffer(buffer);
            }
            finally
            {
                _arrayPool.Return(backend);
            }

        }

        public void WriteBytes(XmlDocument xml, SerializationContext context)
        {
            string content = null;
            using (var stringWriter = new StringWriter())
            using (var xmlTextWriter = XmlWriter.Create(stringWriter))
            {
                xml.WriteTo(xmlTextWriter);
                xmlTextWriter.Flush();
                content = stringWriter.GetStringBuilder().ToString();
            }

            context.Buffer.WriteToBuffer((byte)Amf0Type.XmlDocument);
            WriteStringBytesImpl(content, context, out _, forceLongString: true);
        }

        public void WriteNullBytes(SerializationContext context)
        {
            context.Buffer.WriteToBuffer((byte)Amf0Type.Null);
        }

        public void WriteValueBytes(object value, SerializationContext context)
        {
            var valueType = value != null ? value.GetType() : typeof(object);
            if (!_getBytesHandlers.TryGetValue(valueType, out var handler))
            {
                throw new InvalidOperationException();
            }


            handler(value, context);
        }

        // strict array
        public void WriteBytes(List<object> value, SerializationContext context)
        {
            if (value == null)
            {
                WriteNullBytes(context);
                return;
            }

            var bytesNeed = Amf0CommonValues.MARKER_LENGTH + sizeof(uint);

            var refIndex = context.ReferenceTable.IndexOf(value);

            if (refIndex >= 0)
            {
                WriteReferenceIndexBytes((ushort)refIndex, context);
                return;
            }
            context.ReferenceTable.Add(value);

            context.Buffer.WriteToBuffer((byte)Amf0Type.StrictArray);
            var countBuffer = _arrayPool.Rent(sizeof(uint));
            try
            {
                var contractRet = NetworkBitConverter.TryGetBytes((uint)value.Count, countBuffer);
                Contract.Assert(contractRet);
                context.Buffer.WriteToBuffer(countBuffer.AsSpan(0, sizeof(uint)));
            }
            finally
            {
                _arrayPool.Return(countBuffer);
            }

            foreach (var data in value)
            {
                WriteValueBytes(data, context);
            }
        }

        // ecma array
        public void WriteBytes(Dictionary<string, object> value, SerializationContext context)
        {
            if (value == null)
            {
                WriteNullBytes(context);
                return;
            }

            var refIndex = context.ReferenceTable.IndexOf(value);

            if (refIndex >= 0)
            {
                WriteReferenceIndexBytes((ushort)refIndex, context);
                return;
            }
            context.Buffer.WriteToBuffer((byte)Amf0Type.EcmaArray);
            context.ReferenceTable.Add(value);
            var countBuffer = _arrayPool.Rent(sizeof(uint));
            try
            {
                var contractRet = NetworkBitConverter.TryGetBytes((uint)value.Count, countBuffer);
                Contract.Assert(contractRet);
                context.Buffer.WriteToBuffer(countBuffer.AsSpan(0, sizeof(uint)));
            }
            finally
            {
                _arrayPool.Return(countBuffer);
            }

            foreach ((var key, var data) in value)
            {
                WriteStringBytesImpl(key, context, out _);
                WriteValueBytes(data, context);
            }
            WriteStringBytesImpl("", context, out _);
            WriteObjectEndBytes(context);
        }

        public void WriteTypedBytes(object value, SerializationContext context)
        {
            if (value == null)
            {
                WriteNullBytes(context);
                return;
            }
            var refIndex = context.ReferenceTable.IndexOf(value);

            if (refIndex >= 0)
            {
                WriteReferenceIndexBytes((ushort)refIndex, context);
                return;
            }
            context.Buffer.WriteToBuffer((byte)Amf0Type.TypedObject);
            context.ReferenceTable.Add(value);

            var valueType = value.GetType();
            var className = valueType.Name;

            var clsAttr = (TypedObjectAttribute)Attribute.GetCustomAttribute(valueType, typeof(TypedObjectAttribute));
            if (clsAttr != null && clsAttr.Name != null)
            {
                className = clsAttr.Name;
            }

            WriteStringBytesImpl(className, context, out _);

            var props = valueType.GetProperties();

            foreach (var prop in props)
            {
                var attr = (ClassFieldAttribute)Attribute.GetCustomAttribute(prop, typeof(ClassFieldAttribute));
                if (attr != null)
                {
                    WriteStringBytesImpl(attr.Name ?? prop.Name, context, out _);
                    WriteValueBytes(prop.GetValue(value), context);
                }
            }

            WriteStringBytesImpl("", context, out _);
            WriteObjectEndBytes(context);
        }

        public void WriteBytes(AmfObject value, SerializationContext context)
        {
            if (value == null)
            {
                WriteNullBytes(context);
                return;
            }
            var refIndex = context.ReferenceTable.IndexOf(value);

            if (refIndex >= 0)
            {
                WriteReferenceIndexBytes((ushort)refIndex, context);
                return;
            }
            context.Buffer.WriteToBuffer((byte)Amf0Type.Object);
            context.ReferenceTable.Add(value);

            foreach (var field in value.Fields)
            {
                WriteStringBytesImpl(field.Key, context, out _);
                WriteValueBytes(field.Value, context);
            }

            foreach (var field in value.DynamicFields)
            {
                WriteStringBytesImpl(field.Key, context, out _);
                WriteValueBytes(field.Value, context);
            }

            WriteStringBytesImpl("", context, out _);
            WriteObjectEndBytes(context);
        }


    }
}


================================================
FILE: Harmonic/Networking/Amf/Serialization/Amf0/SerializationContext.cs
================================================
using Harmonic.Buffers;
using System;
using System.Collections.Generic;
using System.Text;

namespace Harmonic.Networking.Amf.Serialization.Amf0
{
    public class SerializationContext : IDisposable
    {
        public ByteBuffer Buffer { get; private set; }
        public List<object> ReferenceTable { get; set; } = new List<object>();

        public int MessageLength => Buffer.Length;

        private bool _disposeBuffer = true;

        public SerializationContext()
        {
            Buffer = new ByteBuffer();
        }

        public SerializationContext(ByteBuffer buffer)
        {
            Buffer = buffer;
            _disposeBuffer = false;
        }

        public void GetMessage(Span<byte> buffer)
        {
            ReferenceTable.Clear();
            Buffer.TakeOutMemory(buffer);
        }

        public void Dispose()
        {
            if (_disposeBuffer)
            {
                ((IDisposable)Buffer).Dispose();
            }
        }
    }
}


================================================
FILE: Harmonic/Networking/Amf/Serialization/Amf3/Amf3Array.cs
================================================
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;

namespace Harmonic.Networking.Amf.Serialization.Amf3
{
    public class Amf3Array
    {
        public Dictionary<string, object> SparsePart { get; set; } = new Dictionary<string, object>();
        public List<object> DensePart { get; set; } = new List<object>();

        
        public object this[string key]
        {
            get
            {
                return SparsePart[key];
            }
            set
            {
                SparsePart[key] = value;
            }
        }

        public object this[int index]
        {
            get
            {
                return DensePart[index];
            }
            set
            {
                DensePart[index] = value;
            }
        }
    }
}


================================================
FILE: Harmonic/Networking/Amf/Serialization/Amf3/Amf3ClassTraits.cs
================================================
using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;

namespace Harmonic.Networking.Amf.Serialization.Amf3
{
    public enum Amf3ClassType
    {
        Anonymous,
        Typed,
        Externalizable
    }

    public class Amf3ClassTraits : IEquatable<Amf3ClassTraits>
    {
        public bool IsDynamic { get; set; } = false;
        public Amf3ClassType ClassType { get; set; }
        public string ClassName { get; set; }
        public List<string> Members { get; set; } = new List<string>();

        public override bool Equals(object obj)
        {
            if (obj is Amf3ClassTraits traits)
            {
                Equals(traits);
            }

            return base.Equals(obj);
        }

        public bool Equals(Amf3ClassTraits traits)
        {
            return traits.ClassType == ClassType &&
                traits.ClassName == ClassName &&
                traits.Members.SequenceEqual(Members);
        }

        public override int GetHashCode()
        {
            var hash = new HashCode();
            hash.Add(ClassType);
            hash.Add(ClassName);
            foreach (var member in Members)
            {
                hash.Add(member);
            }
            return hash.ToHashCode();
        }
    }
}


================================================
FILE: Harmonic/Networking/Amf/Serialization/Amf3/Amf3CommonValues.cs
================================================
using System;
using System.Linq;
using System.Buffers;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Dynamic;
using System.IO;

namespace Harmonic.Networking.Amf.Serialization.Amf3
{
    public static class Amf3CommonValues
    {
        public static readonly int MARKER_LENGTH = 1;
        
    }
}


================================================
FILE: Harmonic/Networking/Amf/Serialization/Amf3/Amf3Dictionary.cs
================================================
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Text;

namespace Harmonic.Networking.Amf.Serialization.Amf3
{
    public class Amf3Dictionary<TKey, TValue> : Dictionary<TKey, TValue>
    {
        public bool WeakKeys { get; set; } = false;

        public Amf3Dictionary() : base() { }

        public Amf3Dictionary(IDictionary<TKey, TValue> dictionary) : base(dictionary) { }

        public Amf3Dictionary(IEnumerable<KeyValuePair<TKey, TValue>> collection) : base(collection) { }

        public Amf3Dictionary(IEqualityComparer<TKey> comparer) : base(comparer) { }

        public Amf3Dictionary(int capacity) : base(capacity) { }

        public Amf3Dictionary(IDictionary<TKey, TValue> dictionary, IEqualityComparer<TKey> comparer) : base(dictionary, comparer) { }

        public Amf3Dictionary(IEnumerable<KeyValuePair<TKey, TValue>> collection, IEqualityComparer<TKey> comparer) : base(collection, comparer) { }

        public Amf3Dictionary(int capacity, IEqualityComparer<TKey> comparer) : base(capacity, comparer) { }

        protected Amf3Dictionary(SerializationInfo info, StreamingContext context) : base(info, context) { }

    }
}


================================================
FILE: Harmonic/Networking/Amf/Serialization/Amf3/Amf3Reader.cs
================================================
using Harmonic.Networking.Amf.Common;
using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using Harmonic.Networking.Utils;
using System.Buffers;
using Harmonic.Networking.Amf.Data;
using System.Reflection;
using Harmonic.Networking.Amf.Attributes;
using Harmonic.Networking.Amf.Serialization.Attributes;

namespace Harmonic.Networking.Amf.Serialization.Amf3
{
    public class Amf3Reader
    {
        private delegate bool ReaderHandler<T>(Span<byte> buffer, out T value, out int consumed);
        private delegate bool ReaderHandler(Span<byte> buffer, out object value, out int consumed);

        private List<object> _objectReferenceTable = new List<object>();
        private List<string> _stringReferenceTable = new List<string>();
        private List<Amf3ClassTraits> _objectTraitsReferenceTable = new List<Amf3ClassTraits>();
        private Dictionary<Amf3Type, ReaderHandler> _readerHandlers = new Dictionary<Amf3Type, ReaderHandler>();
        private Dictionary<string, TypeRegisterState> _registeredTypedObejectStates = new Dictionary<string, TypeRegisterState>();
        private List<Type> _registeredTypes = new List<Type>();
        private Dictionary<string, Type> _registeredExternalizable = new Dictionary<string, Type>();
        private readonly IReadOnlyList<Amf3Type> _supportedTypes = null;
        private MemoryPool<byte> _memoryPool = MemoryPool<byte>.Shared;

        public IReadOnlyList<Type> RegisteredTypes { get => _registeredTypes; }

        public Amf3Reader()
        {
            var supportedTypes = new List<Amf3Type>()
            {
                 Amf3Type.Undefined ,
                 Amf3Type.Null ,
                 Amf3Type.False ,
                 Amf3Type.True,
                 Amf3Type.Integer ,
                 Amf3Type.Double ,
                 Amf3Type.String ,
                 Amf3Type.Xml ,
                 Amf3Type.XmlDocument ,
                 Amf3Type.Date ,
                 Amf3Type.Array ,
                 Amf3Type.Object ,
                 Amf3Type.ByteArray ,
                 Amf3Type.VectorObject ,
                 Amf3Type.VectorDouble ,
                 Amf3Type.VectorInt ,
                 Amf3Type.VectorUInt ,
                 Amf3Type.Dictionary
            };
            _supportedTypes = supportedTypes;

            var readerHandlers = new Dictionary<Amf3Type, ReaderHandler>
            {
                [Amf3Type.Undefined] = ReaderHandlerWrapper<Undefined>(TryGetUndefined),
                [Amf3Type.Null] = ReaderHandlerWrapper<object>(TryGetNull),
                [Amf3Type.True] = ReaderHandlerWrapper<bool>(TryGetTrue),
                [Amf3Type.False] = ReaderHandlerWrapper<bool>(TryGetFalse),
                [Amf3Type.Double] = ReaderHandlerWrapper<double>(TryGetDouble),
                [Amf3Type.Integer] = ReaderHandlerWrapper<uint>(TryGetUInt29),
                [Amf3Type.String] = ReaderHandlerWrapper<string>(TryGetString),
                [Amf3Type.Xml] = ReaderHandlerWrapper<Amf3Xml>(TryGetXml),
                [Amf3Type.XmlDocument] = ReaderHandlerWrapper<XmlDocument>(TryGetXmlDocument),
                [Amf3Type.Date] = ReaderHandlerWrapper<DateTime>(TryGetDate),
                [Amf3Type.ByteArray] = ReaderHandlerWrapper<byte[]>(TryGetByteArray),
                [Amf3Type.VectorDouble] = ReaderHandlerWrapper<Vector<double>>(TryGetVectorDouble),
                [Amf3Type.VectorInt] = ReaderHandlerWrapper<Vector<int>>(TryGetVectorInt),
                [Amf3Type.VectorUInt] = ReaderHandlerWrapper<Vector<uint>>(TryGetVectorUint),
                [Amf3Type.VectorObject] = ReaderHandlerWrapper<object>(TryGetVectorObject),
                [Amf3Type.Array] = ReaderHandlerWrapper<Amf3Array>(TryGetArray),
                [Amf3Type.Object] = ReaderHandlerWrapper<object>(TryGetObject),
                [Amf3Type.Dictionary] = ReaderHandlerWrapper<Amf3Dictionary<object, object>>(TryGetDictionary)
            };
            _readerHandlers = readerHandlers;
        }

        public void ResetReference()
        {
            _objectReferenceTable.Clear();
            _objectTraitsReferenceTable.Clear();
            _stringReferenceTable.Clear();
        }

        private ReaderHandler ReaderHandlerWrapper<T>(ReaderHandler<T> handler)
        {
            return (Span<byte> b, out object value, out int consumed) =>
            {
                value = default;
                consumed = default;

                if (handler(b, out var data, out consumed))
                {
                    value = data;
                    return true;
                }
                return false;
            };
        }

        internal void RegisterTypedObject(string mappedName, TypeRegisterState state)
        {
            _registeredTypedObejectStates.Add(mappedName, state);
        }

        public void RegisterTypedObject<T>() where T: new()
        {
            var type = typeof(T);
            var props = type.GetProperties();
            var fields = props.Where(p => p.CanWrite && Attribute.GetCustomAttribute(p, typeof(ClassFieldAttribute)) != null).ToList();
            var members = fields.ToDictionary(p => ((ClassFieldAttribute)Attribute.GetCustomAttribute(p, typeof(ClassFieldAttribute))).Name ?? p.Name, p => new Action<object, object>(p.SetValue));
            if (members.Keys.Where(s => string.IsNullOrEmpty(s)).Any())
            {
                throw new InvalidOperationException("Field name cannot be empty or null");
            }
            string mapedName = null;
            var attr = type.GetCustomAttribute<TypedObjectAttribute>();
            if (attr != null)
            {
                mapedName = attr.Name;
            }

            var typeName = mapedName == null ? type.Name : mapedName;
            var state = new TypeRegisterState()
            {
                Members = members,
                Type = type
            };
            _registeredTypes.Add(type);
            _registeredTypedObejectStates.Add(typeName, state);
        }

        public void RegisterExternalizable<T>() where T : IExternalizable, new()
        {
            var type = typeof(T);
            string mapedName = null;
            var attr = type.GetCustomAttribute<TypedObjectAttribute>();
            if (attr != null)
            {
                mapedName = attr.Name;
            }
            var typeName = mapedName == null ? type.Name : mapedName;
            _registeredExternalizable.Add(typeName, type);
        }

        public bool TryDescribeData(Span<byte> buffer, out Amf3Type type)
        {
            type = default;
            if (buffer.Length < Amf3CommonValues.MARKER_LENGTH)
            {
                return false;
            }

            var typeMark = (Amf3Type)buffer[0];
            if (!_supportedTypes.Contains(typeMark))
            {
                return false;
            }

            type = typeMark;
            return true;
        }

        public bool DataIsType(Span<byte> buffer, Amf3Type type)
        {
            if (!TryDescribeData(buffer, out var dataType))
            {
                return false;
            }
            return dataType == type;
        }

        public bool TryGetUndefined(Span<byte> buffer, out Undefined value, out int consumed)
        {
            value = default;
            consumed = default;
            if (!DataIsType(buffer, Amf3Type.Undefined))
            {
                return false;
            }

            value = new Undefined();
            consumed = Amf3CommonValues.MARKER_LENGTH;
            return true;
        }

        public bool TryGetNull(Span<byte> buffer, out object value, out int consumed)
        {
            value = default;
            consumed = default;
            if (!DataIsType(buffer, Amf3Type.Null))
            {
                return false;
            }

            value = null;
            consumed = Amf3CommonValues.MARKER_LENGTH;
            return true;
        }

        public bool TryGetTrue(Span<byte> buffer, out bool value, out int consumed)
        {
            value = default;
            consumed = default;
            if (!DataIsType(buffer, Amf3Type.True))
            {
                return false;
            }

            value = true;
            consumed = Amf3CommonValues.MARKER_LENGTH;
            return true;
        }

        public bool TryGetBoolean(Span<byte> buffer, out bool value, out int consumed)
        {
            if (DataIsType(buffer, Amf3Type.True))
            {
                consumed = Amf3CommonValues.MARKER_LENGTH;
                value = true;
                return true;
            }
            else if (DataIsType(buffer, Amf3Type.False))
            {
                consumed = Amf3CommonValues.MARKER_LENGTH;
                value = false;
                return true;
            }
            value = default;
            consumed = default;
            return false;
        }

        public bool TryGetFalse(Span<byte> buffer, out bool value, out int consumed)
        {
            value = default;
            consumed = default;
            if (!DataIsType(buffer, Amf3Type.False))
            {
                return false;
            }

            value = false;
            consumed = Amf3CommonValues.MARKER_LENGTH;
            return true;
        }

        public bool TryGetUInt29(Span<byte> buffer, out uint value, out int consumed)
        {
            value = default;
            consumed = default;
            if (!DataIsType(buffer, Amf3Type.Integer))
            {
                return false;
            }

            var dataBuffer = buffer.Slice(Amf3CommonValues.MARKER_LENGTH);

            if (!TryGetU29Impl(dataBuffer, out value, out var dataConsumed))
            {
                return false;
            }

            consumed = Amf3CommonValues.MARKER_LENGTH + dataConsumed;

            return true;
        }

        private bool TryGetU29Impl(Span<byte> dataBuffer, out uint value, out int consumed)
        {
            value = default;
            consumed = default;
            var bytesNeed = 0;
            for (int i = 0; i < 4; i++)
            {
                bytesNeed++;
                if (dataBuffer.Length < bytesNeed)
                {
                    return false;
                }
                var hasBytes = ((dataBuffer[i] >> 7 & 0x01) == 0x01);
                if (!hasBytes)
                {
                    break;
                }
            }

            switch (bytesNeed)
            {
                case 3:
                case 4:
                    dataBuffer[2] = (byte)(0x7F & dataBuffer[2]);
                    dataBuffer[1] = (byte)(0x7F & dataBuffer[1]);
                    dataBuffer[0] = (byte)(0x7F & dataBuffer[0]);
                    dataBuffer[2] = (byte)(dataBuffer[1] << 7 | dataBuffer[2]);
                    dataBuffer[1] = (byte)(dataBuffer[0] << 6 | (dataBuffer[1] >> 1));
                    dataBuffer[0] = (byte)(dataBuffer[0] >> 2);
                    break;
                case 2:
                    dataBuffer[1] = (byte)(0x7F & dataBuffer[1]);
                    dataBuffer[1] = (byte)(dataBuffer[0] << 7 | dataBuffer[1]);
                    dataBuffer[0] = (byte)(0x7F & dataBuffer[0]);
                    dataBuffer[0] = (byte)(dataBuffer[0] >> 1);
                    break;
            }

            using (var mem = _memoryPool.Rent(sizeof(uint)))
            {
                var buffer = mem.Memory.Span;
                buffer.Clear();
                dataBuffer.Slice(0, bytesNeed).CopyTo(buffer.Slice(sizeof(uint) - bytesNeed));
                value = NetworkBitConverter.ToUInt32(buffer);
                consumed = bytesNeed;
                return true;
            }


        }

        public bool TryGetDouble(Span<byte> buffer, out double value, out int consumed)
        {
            value = default;
            consumed = default;
            if (!DataIsType(buffer, Amf3Type.Double))
            {
                return false;
            }

            value = NetworkBitConverter.ToDouble(buffer.Slice(Amf3CommonValues.MARKER_LENGTH));
            consumed = Amf3CommonValues.MARKER_LENGTH + sizeof(double);
            return true;
        }
        public bool TryGetString(Span<byte> buffer, out string value, out int consumed)
        {
            value = default;
            consumed = default;
            if (!DataIsType(buffer, Amf3Type.String))
            {
                return false;
            }

            var objectBuffer = buffer.Slice(Amf3CommonValues.MARKER_LENGTH);
            TryGetStringImpl(objectBuffer, _stringReferenceTable, out var str, out var strConsumed);
            value = str;
            consumed = Amf3CommonValues.MARKER_LENGTH + strConsumed;
            return true;
        }

        private bool TryGetStringImpl<T>(Span<byte> objectBuffer, List<T> referenceTable, out string value, out int consumed) where T : class
        {
            value = default;
            consumed = default;
            if (!TryGetU29Impl(objectBuffer, out var header, out int headerLen))
            {
                return false;
            }
            if (!TryGetReference(header, _stringReferenceTable, out var headerData, out string refValue, out var isRef))
            {
                return false;
            }
            if (isRef)
            {
                value = refValue;
                consumed = headerLen;
                return true;
            }

            var strLen = (int)headerData;
            if (objectBuffer.Length - headerLen < strLen)
            {
                return false;
            }

            value = Encoding.UTF8.GetString(objectBuffer.Slice(headerLen, strLen));
            consumed = headerLen + strLen;
            if (value.Any())
            {
                referenceTable.Add(value as T);
            }
            
            return true;
        }

        public bool TryGetXmlDocument(Span<byte> buffer, out XmlDocument value, out int consumed)
        {
            value = default;
            consumed = default;
            if (!DataIsType(buffer, Amf3Type.XmlDocument))
            {
                return false;
            }

            var objectBuffer = buffer.Slice(Amf3CommonValues.MARKER_LENGTH);
            TryGetStringImpl(objectBuffer, _objectReferenceTable, out var str, out var strConsumed);
            var xml = new XmlDocument();
            xml.LoadXml(str);
            value = xml;
            consumed = Amf3CommonValues.MARKER_LENGTH + strConsumed;
            return true;
        }

        public bool TryGetDate(Span<byte> buffer, out DateTime value, out int consumed)
        {
            value = default;
            consumed = default;
            if (!DataIsType(buffer, Amf3Type.Date))
            {
                return false;
            }

            var objectBuffer = buffer.Slice(Amf3CommonValues.MARKER_LENGTH);

            if (!TryGetU29Impl(objectBuffer, out var header, out var headerLength))
            {
                return false;
            }
            if (!TryGetReference(header, _objectReferenceTable, out var headerData, out DateTime refValue, out var isRef))
            {
                return false;
            }
            if (isRef)
            {
                value = refValue;
                consumed = Amf3CommonValues.MARKER_LENGTH + headerLength;
                return true;
            }

            var timestamp = NetworkBitConverter.ToDouble(objectBuffer.Slice(headerLength));
            value = DateTimeOffset.FromUnixTimeMilliseconds((long)(timestamp)).LocalDateTime;
            consumed = Amf3CommonValues.MARKER_LENGTH + headerLength + sizeof(double);
            _objectReferenceTable.Add(value);
            return true;
        }

        public bool TryGetArray(Span<byte> buffer, out Amf3Array value, out int consumed)
        {
            value = default;
            consumed = default;
            if (!DataIsType(buffer, Amf3Type.Array))
            {
                return false;
            }

            if (!TryGetU29Impl(buffer.Slice(Amf3CommonValues.MARKER_LENGTH), out var header, out var headerConsumed))
            {
                return false;
            }

            if (!TryGetReference(header, _objectReferenceTable, out var headerData, out Amf3Array refValue, out var isRef))
            {
                return false;
            }
            if (isRef)
            {
                value = refValue;
                consumed = Amf3CommonValues.MARKER_LENGTH + headerConsumed;
                return true;
            }

            var arrayConsumed = 0;
            var arrayBuffer = buffer.Slice(Amf3CommonValues.MARKER_LENGTH + headerConsumed);
            var denseItemCount = (int)headerData;

            if (!TryGetStringImpl(arrayBuffer, _stringReferenceTable, out var key, out var keyConsumed))
            {
                return false;
            }
            var array = new Amf3Array();
            _objectReferenceTable.Add(array);
            if (key.Any())
            {
                do
                {
                    arrayBuffer = arrayBuffer.Slice(keyConsumed);
                    arrayConsumed += keyConsumed;
                    if (!TryGetValue(arrayBuffer, out var item, out var itemConsumed))
                    {
                        return false;
                    }

                    arrayConsumed += itemConsumed;
                    arrayBuffer = arrayBuffer.Slice(itemConsumed);
                    array.SparsePart.Add(key, item);
                    if (!TryGetStringImpl(arrayBuffer, _stringReferenceTable, out key, out keyConsumed))
                    {
                        return false;
                    }
                }
                while (key.Any());
            }
            arrayConsumed += keyConsumed;
            arrayBuffer = arrayBuffer.Slice(keyConsumed);

            for (int i = 0; i < denseItemCount; i++)
            {
                if (!TryGetValue(arrayBuffer, out var item, out var itemConsumed))
                {
                    return false;
                }
                array.DensePart.Add(item);
                arrayConsumed += itemConsumed;
                arrayBuffer = arrayBuffer.Slice(itemConsumed);
            }

            value = array;
            consumed = Amf3CommonValues.MARKER_LENGTH + headerConsumed + arrayConsumed;
            return true;
        }

        public bool TryGetObject(Span<byte> buffer, out object value, out int consumed)
        {
            value = default;
            consumed = 0;
            if (!DataIsType(buffer, Amf3Type.Object))
            {
                return false;
            }
            consumed = Amf3CommonValues.MARKER_LENGTH;
            if (!TryGetU29Impl(buffer.Slice(Amf3CommonValues.MARKER_LENGTH), out var header, out var headerLength))
            {
                return false;
            }
            consumed += headerLength;

            if (!TryGetReference(header, _objectReferenceTable, out var headerData, out object refValue, out var isRef))
            {
                return false;
            }

            if (isRef)
            {
                value = refValue;
                return true;
            }
            Amf3ClassTraits traits = null;
            if ((header & 0x02) == 0x00)
            {
                var referenceIndex = (int)((header >> 2) & 0x3FFFFFFF);
                if (_objectTraitsReferenceTable.Count <= referenceIndex)
                {
                    return false;
                }

                if (_objectTraitsReferenceTable[referenceIndex] is Amf3ClassTraits obj)
                {
                    traits = obj;
                }
                else
                {
                    return false;
                }
            }
            else
            {
                traits = new Amf3ClassTraits();
                var dataBuffer = buffer.Slice(Amf3CommonValues.MARKER_LENGTH + headerLength);
                if ((header & 0x04) == 0x04)
                {
                    traits.ClassType = Amf3ClassType.Externalizable;
                    if (!TryGetStringImpl(dataBuffer, _stringReferenceTable, out var extClassName, out int extClassNameConsumed))
                    {
                        return false;
                    }
                    consumed += extClassNameConsumed;
                    traits.ClassName = extClassName;
                    var externailzableBuffer = dataBuffer.Slice(extClassNameConsumed);

                    if (!_registeredExternalizable.TryGetValue(extClassName, out var extType))
                    {
                        return false;
                    }
                    var extObj = Activator.CreateInstance(extType) as IExternalizable;
                    if (!extObj.TryDecodeData(externailzableBuffer, out var extConsumed))
                    {
                        return false;
                    }

                    value = extObj;
                    consumed = Amf3CommonValues.MARKER_LENGTH + headerLength + extClassNameConsumed + extConsumed;
                    return true;
                }

                if (!TryGetStringImpl(dataBuffer, _stringReferenceTable, out var className, out int classNameConsumed))
                {
                    return false;
                }
                dataBuffer = dataBuffer.Slice(classNameConsumed);
                consumed += classNameConsumed;
                if (className.Any())
                {
                    traits.ClassType = Amf3ClassType.Typed;
                    traits.ClassName = className;
                }
                else
                {
                    traits.ClassType = Amf3ClassType.Anonymous;
                }

                if ((header & 0x08) == 0x08)
                {
                    traits.IsDynamic = true;
                }
                var memberCount = header >> 4;
                for (int i = 0; i < memberCount; i++)
                {
                    if (!TryGetStringImpl(dataBuffer, _stringReferenceTable, out var key, out var keyConsumed))
                    {
                        return false;
                    }
                    traits.Members.Add(key);
                    dataBuffer = dataBuffer.Slice(keyConsumed);
                    consumed += keyConsumed;
                }
                _objectTraitsReferenceTable.Add(traits);
            }

            object deserailziedObject = null;
            var valueBuffer = buffer.Slice(consumed);
            if (traits.ClassType == Amf3ClassType.Typed)
            {
                if (!_registeredTypedObejectStates.TryGetValue(traits.ClassName, out var state))
                {
                    return false;
                }

                var classType = state.Type;
                if (!traits.Members.OrderBy(m => m).SequenceEqual(state.Members.Keys.OrderBy(p => p)))
                {
                    return false;
                }

                deserailziedObject = Activator.CreateInstance(classType);
                _objectReferenceTable.Add(deserailziedObject);
                foreach (var member in traits.Members)
                {
                    if (!TryGetValue(valueBuffer, out var data, out var dataConsumed))
                    {
                        return false;
                    }
                    valueBuffer = valueBuffer.Slice(dataConsumed);
                    consumed += dataConsumed;
                    state.Members[member](deserailziedObject, data);
                }
            }
            else
            {
                var obj = new AmfObject();
                _objectReferenceTable.Add(obj);
                foreach (var member in traits.Members)
                {
                    if (!TryGetValue(valueBuffer, out var data, out var dataConsumed))
                    {
                        return false;
                    }
                    valueBuffer = valueBuffer.Slice(dataConsumed);
                    consumed += dataConsumed;
                    obj.Add(member, data);
                }

                deserailziedObject = obj;
            }
            if (traits.IsDynamic)
            {
                var dynamicObject = deserailziedObject as IDynamicObject;
                if (dynamicObject == null)
                {
                    return false;
                }
                if (!TryGetStringImpl(valueBuffer, _stringReferenceTable, out var key, out var keyConsumed))
                {
                    return false;
                }
                consumed += keyConsumed;
                valueBuffer = valueBuffer.Slice(keyConsumed);
                while (key.Any())
                {
                    if (!TryGetValue(valueBuffer, out var data, out var dataConsumed))
                    {
                        return false;
                    }
                    valueBuffer = valueBuffer.Slice(dataConsumed);
                    consumed += dataConsumed;

                    dynamicObject.AddDynamic(key, data);

                    if (!TryGetStringImpl(valueBuffer, _stringReferenceTable, out key, out keyConsumed))
                    {
                        return false;
                    }
                    valueBuffer = valueBuffer.Slice(keyConsumed);
                    consumed += keyConsumed;
                }
            }

            value = deserailziedObject;

            return true;
        }

        public bool TryGetXml(Span<byte> buffer, out Amf3Xml value, out int consumed)
        {
            value = default;
            consumed = default;
            if (!DataIsType(buffer, Amf3Type.Xml))
            {
                return false;
            }

            var objectBuffer = buffer.Slice(Amf3CommonValues.MARKER_LENGTH);
            TryGetStringImpl(objectBuffer, _objectReferenceTable, out var str, out var strConsumed);
            var xml = new Amf3Xml();
            xml.LoadXml(str);

            value = xml;
            consumed = Amf3CommonValues.MARKER_LENGTH + strConsumed;
            return true;
        }

        public bool TryGetByteArray(Span<byte> buffer, out byte[] value, out int consumed)
        {
            value = default;
            consumed = default;
            if (!DataIsType(buffer, Amf3Type.ByteArray))
            {
                return false;
            }

            var objectBuffer = buffer.Slice(Amf3CommonValues.MARKER_LENGTH);

            if (!TryGetU29Impl(objectBuffer, out var header, out int headerLen))
            {
                return false;
            }

            if (!TryGetReference(header, _objectReferenceTable, out var headerData, out byte[] refValue, out var isRef))
            {
                return false;
            }
            if (isRef)
            {
                value = refValue;
                consumed = Amf3CommonValues.MARKER_LENGTH + headerLen;
                return true;
            }

            var arrayLen = (int)headerData;
            if (objectBuffer.Length - headerLen < arrayLen)
            {
                return false;
            }

            value = new byte[arrayLen];

            objectBuffer.Slice(headerLen, arrayLen).CopyTo(value);
            _objectReferenceTable.Add(value);
            consumed = Amf3CommonValues.MARKER_LENGTH + headerLen + arrayLen;
            return true;
        }

        public bool TryGetValue(Span<byte> buffer, out object value, out int consumed)
        {
            value = default;
            consumed = default;

            if (!TryDescribeData(buffer, out var type))
            {
                return false;
            }

            if (!_readerHandlers.TryGetValue(type, out var handler))
            {
                return false;
            }

            if (!handler(buffer, out value, out consumed))
            {
                return false;
            }
            return true;
        }

        public bool TryGetVectorInt(Span<byte> buffer, out Vector<int> value, out int consumed)
        {
            value = default;
            consumed = Amf3CommonValues.MARKER_LENGTH;
            if (!DataIsType(buffer, Amf3Type.VectorInt))
            {
                return false;
            }

            buffer = buffer.Slice(Amf3CommonValues.MARKER_LENGTH);
            if (!ReadVectorHeader(ref buffer, ref value, ref consumed, out var itemCount, out var isFixedSize, out var isRef))
            {
                return false;
            }

            if (isRef)
            {
                return true;
            }

            var vector = new Vector<int> { IsFixedSize = isFixedSize };
            _objectReferenceTable.Add(vector);
            for (int i = 0; i < itemCount; i++)
            {
                if (!TryGetIntVectorData(ref buffer, vector, ref consumed))
                {
                    return false;
                }
            }
            value = vector;
            return true;
        }

        public bool TryGetVectorUint(Span<byte> buffer, out Vector<uint> value, out int consumed)
        {
            value = default;
            consumed = Amf3CommonValues.MARKER_LENGTH;
            if (!DataIsType(buffer, Amf3Type.VectorUInt))
            {
                return false;
            }

            buffer = buffer.Slice(Amf3CommonValues.MARKER_LENGTH);
            if (!ReadVectorHeader(ref buffer, ref value, ref consumed, out var itemCount, out var isFixedSize, out var isRef))
            {
                return false;
            }

            if (isRef)
            {
                return true;
            }

            var vector = new Vector<uint> { IsFixedSize = isFixedSize };
            _objectReferenceTable.Add(vector);
            for (int i = 0; i < itemCount; i++)
            {
                if (!TryGetUIntVectorData(ref buffer, vector, ref consumed))
                {
                    return false;
                }
            }

            value = vector;
            return true;
        }

        public bool TryGetVectorDouble(Span<byte> buffer, out Vector<double> value, out int consumed)
        {
            value = default;
            consumed = default;
            if (!DataIsType(buffer, Amf3Type.VectorDouble))
            {
                return false;
            }

            buffer = buffer.Slice(Amf3CommonValues.MARKER_LENGTH);
            if (!ReadVectorHeader(ref buffer, ref value, ref consumed, out var itemCount, out var isFixedSize, out var isRef))
            {
                return false;
            }

            if (isRef)
            {
                return true;
            }

            var vector = new Vector<double>() { IsFixedSize = isFixedSize };
            _objectReferenceTable.Add(vector);
            for (int i = 0; i < itemCount; i++)
            {
                if (!TryGetDoubleVectorData(ref buffer, vector, ref consumed))
                {
                    return false;
                }
            }

            value = vector;
            return true;
        }

        private bool TryGetIntVectorData(ref Span<byte> buffer, Vector<int> vector, ref int consumed)
        {
            var value = NetworkBitConverter.ToInt32(buffer);
            vector.Add(value);
            consumed += sizeof(int);
            buffer = buffer.Slice(sizeof(int));
            return true;

        }

        private bool TryGetUIntVectorData(ref Span<byte> buffer, Vector<uint> vector, ref int consumed)
        {
            var value = NetworkBitConverter.ToUInt32(buffer);
            vector.Add(value);
            consumed += sizeof(uint);
            buffer = buffer.Slice(sizeof(uint));
            return true;
        }

        private bool TryGetDoubleVectorData(ref Span<byte> buffer, Vector<double> vector, ref int consumed)
        {
            var value = NetworkBitConverter.ToDouble(buffer);
            vector.Add(value);
            consumed += sizeof(double);
            buffer = buffer.Slice(sizeof(double));
            return true;

        }

        private bool TryGetReference<T, TTableEle>(uint header, List<TTableEle> referenceTable, out uint headerData, out T value, out bool isRef)
        {
            isRef = default;
            value = default;
            headerData = header >> 1;
            if ((header & 0x01) == 0x00)
            {
                var referenceIndex = (int)headerData;
                if (referenceTable.Count <= referenceIndex)
                {
                    return false;
                }
                if (referenceTable[referenceIndex] is T refObject)
                {
                    value = refObject;
                    isRef = true;
                    return true;
                }
                else
                {
                    return false;
                }
            }
            isRef = false;
            return true;
        }

        private bool ReadVectorHeader<T>(ref Span<byte> buffer, ref T value, ref int consumed, out int itemCount, out bool isFixedSize, out bool isRef)
        {
            isFixedSize = default;
            itemCount = default;
            isRef = default;
            if (!TryGetU29Impl(buffer, out var header, out var headerLength))
            {
                return false;
            }

            if (!TryGetReference(header, _objectReferenceTable, out var headerData, out T refValue, out isRef))
            {
                return false;
            }

            if (isRef)
            {
                value = refValue;
                consumed = Amf3CommonValues.MARKER_LENGTH + headerLength;
                return true;
            }

            itemCount = (int)headerData;

            var objectBuffer = buffer.Slice(headerLength);

            if (objectBuffer.Length < sizeof(byte))
            {
                return false;
            }

            isFixedSize = objectBuffer[0] == 0x01;
            buffer = objectBuffer.Slice(sizeof(byte));
            consumed = Amf3CommonValues.MARKER_LENGTH + headerLength + sizeof(byte);
            return true;
        }

        private bool ReadVectorTypeName(ref Span<byte> typeNameBuffer, out string typeName, out int typeNameConsumed)
        {
            typeName = default;
            typeNameConsumed = default;
            if (!TryGetStringImpl(typeNameBuffer, _stringReferenceTable, out typeName, out typeNameConsumed))
            {
                return false;
            }
            typeNameBuffer = typeNameBuffer.Slice(typeNameConsumed);
            return true;
        }

        public bool TryGetVectorObject(Span<byte> buffer, out object value, out int consumed)
        {
            value = default;
            consumed = default;

            if (!DataIsType(buffer, Amf3Type.VectorObject))
            {
                return false;
            }

            buffer = buffer.Slice(Amf3CommonValues.MARKER_LENGTH);

            int arrayConsumed = 0;

            if (!ReadVectorHeader(ref buffer, ref value, ref arrayConsumed, out var itemCount, out var isFixedSize, out var isRef))
            {
                return false;
            }

            if (isRef)
            {
                consumed = arrayConsumed;
                return true;
            }

            if (!ReadVectorTypeName(ref buffer, out var typeName, out var typeNameConsumed))
            {
                return false;
            }

            var arrayBodyBuffer = buffer;

            object resultVector = null;
            Type elementType = null;
            Action<object> addAction = null;
            if (typeName == "*")
            {
                elementType = typeof(object);
                var v = new Vector<object>();
                _objectReferenceTable.Add(v);
                v.IsFixedSize = isFixedSize;
                resultVector = v;
                addAction = v.Add;
            }
            else
            {
                if (!_registeredTypedObejectStates.TryGetValue(typeName, out var state))
                {
                    return false;
                }
                elementType = state.Type;

                var vectorType = typeof(Vector<>).MakeGenericType(elementType);
                resultVector = Activator.CreateInstance(vectorType);
                _objectReferenceTable.Add(resultVector);
                vectorType.GetProperty("IsFixedSize").SetValue(resultVector, isFixedSize);
                var addMethod = vectorType.GetMethod("Add");
                addAction = o => addMethod.Invoke(resultVector, new object[] { o });
            }
            for (int i = 0; i < itemCount; i++)
            {
                if (!TryGetValue(arrayBodyBuffer, out var item, out var itemConsumed))
                {
                    return false;
                }
                addAction(item);

                arrayBodyBuffer = arrayBodyBuffer.Slice(itemConsumed);
                arrayConsumed += itemConsumed;
            }
            value = resultVector;
            consumed = typeNameConsumed + arrayConsumed;
            return true;
        }

        public bool TryGetDictionary(Span<byte> buffer, out Amf3Dictionary<object, object> value, out int consumed)
        {
            value = default;
            consumed = default;
            if (!DataIsType(buffer, Amf3Type.Dictionary))
            {
                return false;
            }

            if (!TryGetU29Impl(buffer.Slice(Amf3CommonValues.MARKER_LENGTH), out var header, out var headerLength))
            {
                return false;
            }

            if (!TryGetReference(header, _objectReferenceTable, out var headerData, out Amf3Dictionary<object, object> refValue, out var isRef))
            {
                return false;
            }
            if (isRef)
            {
                value = refValue;
                consumed = Amf3CommonValues.MARKER_LENGTH + headerLength;
                return true;
            }

            var itemCount = (int)headerData;
            var dictConsumed = 0;
            if (buffer.Length - Amf3CommonValues.MARKER_LENGTH - headerLength < sizeof(byte))
            {
                return false;
            }
            var weakKeys = buffer[Amf3CommonValues.MARKER_LENGTH + headerLength] == 0x01;

            var dictBuffer = buffer.Slice(Amf3CommonValues.MARKER_LENGTH + headerLength + /* weak key flag */ sizeof(byte));
            var dict = new Amf3Dictionary<object, object>()
            {
                WeakKeys = weakKeys
            };
            _objectReferenceTable.Add(dict);
            for (int i = 0; i < itemCount; i++)
            {
                if (!TryGetValue(dictBuffer, out var key, out var keyConsumed))
                {
                    return false;
                }
                dictBuffer = dictBuffer.Slice(keyConsumed);
                dictConsumed += keyConsumed;
                if (!TryGetValue(dictBuffer, out var data, out var dataConsumed))
                {
                    return false;
                }
                dictBuffer = dictBuffer.Slice(dataConsumed);
                dict.Add(key, data);
                dictConsumed += dataConsumed;
            }
            value = dict;
            consumed = Amf3CommonValues.MARKER_LENGTH + headerLength + dictConsumed + /* weak key flag */ sizeof(byte);
            return true;
        }
    }
}


================================================
FILE: Harmonic/Networking/Amf/Serialization/Amf3/Amf3Type.cs
================================================
using System;
using System.Collections.Generic;
using System.Text;

namespace Harmonic.Networking.Amf.Serialization.Amf3
{
    public enum Amf3Type : byte
    {
        Undefined,
        Null,
        False,
        True,
        Integer,
        Double,
        String,
        XmlDocument,
        Date,
        Array,
        Object,
        Xml,
        ByteArray,
        VectorInt,
        VectorUInt,
        VectorDouble,
        VectorObject,
        Dictionary
    }
}


================================================
FILE: Harmonic/Networking/Amf/Serialization/Amf3/Amf3Writer.cs
================================================
using Harmonic.Networking.Amf.Common;
using System;
using System.Linq;
using System.Buffers;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.IO;
using Harmonic.Buffers;
using Harmonic.Networking.Utils;
using Harmonic.Networking.Amf.Data;
using System.Diagnostics.Contracts;
using System.Reflection;
using Harmonic.Networking.Amf.Attributes;
using Harmonic.Networking.Amf.Serialization.Attributes;

namespace Harmonic.Networking.Amf.Serialization.Amf3
{
    public class Amf3Writer
    {
        private delegate void WriteHandler<T>(T value, SerializationContext context);
        private delegate void WriteHandler(object value, SerializationContext context);

        private ArrayPool<byte> _arrayPool = ArrayPool<byte>.Shared;

        private Dictionary<Type, WriteHandler> _writeHandlers = new Dictionary<Type, WriteHandler>();

        public static readonly uint U29MAX = 0x1FFFFFFF;
        private MethodInfo _writeVectorTMethod = null;
        private MethodInfo _writeDictionaryTMethod = null;

        public Amf3Writer()
        {

            var writeHandlers = new Dictionary<Type, WriteHandler>
            {
                [typeof(int)] = WriteHandlerWrapper<double>(WriteBytes),
                [typeof(uint)] = WriteHandlerWrapper<uint>(WriteBytes),
                [typeof(long)] = WriteHandlerWrapper<double>(WriteBytes),
                [typeof(ulong)] = WriteHandlerWrapper<uint>(WriteBytes),
                [typeof(short)] = WriteHandlerWrapper<double>(WriteBytes),
                [typeof(ushort)] = WriteHandlerWrapper<uint>(WriteBytes),
                [typeof(double)] = WriteHandlerWrapper<double>(WriteBytes),
                [typeof(Undefined)] = WriteHandlerWrapper<Undefined>(WriteBytes),
                [typeof(object)] = WriteHandlerWrapper<object>(WriteBytes),
                [typeof(DateTime)] = WriteHandlerWrapper<DateTime>(WriteBytes),
                [typeof(XmlDocument)] = WriteHandlerWrapper<XmlDocument>(WriteBytes),
                [typeof(Amf3Xml)] = WriteHandlerWrapper<Amf3Xml>(WriteBytes),
                [typeof(bool)] = WriteHandlerWrapper<bool>(WriteBytes),
                [typeof(Memory<byte>)] = WriteHandlerWrapper<Memory<byte>>(WriteBytes),
                [typeof(string)] = WriteHandlerWrapper<string>(WriteBytes),
                [typeof(Vector<int>)] = WriteHandlerWrapper<Vector<int>>(WriteBytes),
                [typeof(Vector<uint>)] = WriteHandlerWrapper<Vector<uint>>(WriteBytes),
                [typeof(Vector<double>)] = WriteHandlerWrapper<Vector<double>>(WriteBytes),
                [typeof(Vector<>)] = WrapVector,
                [typeof(Amf3Dictionary<,>)] = WrapDictionary
            };
            _writeHandlers = writeHandlers;

            Action<Vector<int>, SerializationContext> method = WriteBytes<int>;
            _writeVectorTMethod = method.Method.GetGenericMethodDefinition();

            Action<Amf3Dictionary<int, int>, SerializationContext> dictMethod = WriteBytes;
            _writeDictionaryTMethod = dictMethod.Method.GetGenericMethodDefinition();

        }

        private void WrapVector(object value, SerializationContext context)
        {
            var valueType = value.GetType();
            var contractRet = valueType.IsGenericType;
            Contract.Assert(contractRet);
            var defination = valueType.GetGenericTypeDefinition();
            Contract.Assert(defination == typeof(Vector<>));
            var vectorT = valueType.GetGenericArguments().First();

            _writeVectorTMethod.MakeGenericMethod(vectorT).Invoke(this, new object[] { value, context });
        }

        private void WrapDictionary(object value, SerializationContext context)
        {
            var valueType = value.GetType();
            var contractRet = valueType.IsGenericType;
            Contract.Assert(contractRet);
            var defination = valueType.GetGenericTypeDefinition();
            Contract.Assert(defination == typeof(Amf3Dictionary<,>));
            var tKey = valueType.GetGenericArguments().First();
            var tValue = valueType.GetGenericArguments().Last();

            _writeDictionaryTMethod.MakeGenericMethod(tKey, tValue).Invoke(this, new object[] { value, context });
        }

        private WriteHandler WriteHandlerWrapper<T>(WriteHandler<T> handler)
        {
            return (object obj, SerializationContext context) =>
            {
                if (obj is T tObj)
                {
                    handler(tObj, context);
                }
                else
                {
                    handler((T)Convert.ChangeType(obj, typeof(T)), context);
                }

            };
        }

        private string XmlToString(XmlDocument xml)
        {
            using (var stringWriter = new StringWriter())
            using (var xmlTextWriter = XmlWriter.Create(stringWriter))
            {
                xml.WriteTo(xmlTextWriter);
                xmlTextWriter.Flush();
                return stringWriter.GetStringBuilder().ToString();
            }
        }

        public void WriteBytes(Undefined value, SerializationContext context)
        {
            context.Buffer.WriteToBuffer((byte)Amf3Type.Undefined);
        }

        public void WriteBytes(bool value, SerializationContext context)
        {
            if (value)
            {
                context.Buffer.WriteToBuffer((byte)Amf3Type.True);
            }
            else
            {
                context.Buffer.WriteToBuffer((byte)Amf3Type.False);
            }

        }

        private void WriteU29BytesImpl(uint value, SerializationContext context)
        {
            var length = 0;
            if (value <= 0x7F)
            {
                length = 1;
            }
            else if (value <= 0x3FFF)
            {
                length = 2;
            }
            else if (value <= 0x1FFFFF)
            {
                length = 3;
            }
            else if (value <= U29MAX)
            {
                length = 4;
            }
            else
            {
                throw new ArgumentOutOfRangeException();
            }
            var arr = ArrayPool<byte>.Shared.Rent(4);
            try
            {
                NetworkBitConverter.TryGetBytes(value, arr);

                switch (length)
                {
                    case 4:
                        context.Buffer.WriteToBuffer((byte)(arr[0] << 2 | ((arr[1]) >> 6) | 0x80));
                        context.Buffer.WriteToBuffer((byte)(arr[1] << 1 | ((arr[2]) >> 7) | 0x80));
                        context.Buffer.WriteToBuffer((byte)(arr[2] | 0x80));
                        context.Buffer.WriteToBuffer(arr[3]);
                        break;
                    case 3:
                        context.Buffer.WriteToBuffer((byte)(arr[1] << 2 | ((arr[2]) >> 6) | 0x80));
                        context.Buffer.WriteToBuffer((byte)(arr[2] << 1 | ((arr[3]) >> 7) | 0x80));
                        context.Buffer.WriteToBuffer((byte)(arr[3] & 0x7F));
                        break;
                    case 2:
                        context.Buffer.WriteToBuffer((byte)(arr[2] << 1 | ((arr[3]) >> 7) | 0x80));
                        context.Buffer.WriteToBuffer((byte)(arr[3] & 0x7F));
                        break;
                    case 1:
                        context.Buffer.WriteToBuffer((byte)(arr[3]));
                        break;
                    default:
                        throw new ApplicationException();

                }

            }
            finally
            {
                ArrayPool<byte>.Shared.Return(arr);
            }
        }

        public void WriteBytes(uint value, SerializationContext context)
        {
            context.Buffer.WriteToBuffer((byte)Amf3Type.Integer);
            WriteU29BytesImpl(value, context);
        }

        public void WriteBytes(double value, SerializationContext context)
        {
            context.Buffer.WriteToBuffer((byte)Amf3Type.Double);
            var backend = _arrayPool.Rent(sizeof(double));
            try
            {
                var contractRet = NetworkBitConverter.TryGetBytes(value, backend);
                Contract.Assert(contractRet);
                context.Buffer.WriteToBuffer(backend.AsSpan(0, sizeof(double)));
            }
            finally
            {
                _arrayPool.Return(backend);
            }

        }

        private void WriteStringBytesImpl<T>(string value, SerializationContext context, List<T> referenceTable)
        {
            if (value is T tValue)
            {
                var refIndex = referenceTable.IndexOf(tValue);
                if (refIndex >= 0)
                {
                    var header = (uint)refIndex << 1;
                    WriteU29BytesImpl(header, context);
                    return;
                }
                else
                {
                    var byteCount = (uint)Encoding.UTF8.GetByteCount(value);
                    var header = (byteCount << 1) | 0x01;
                    WriteU29BytesImpl(header, context);
                    var backend = _arrayPool.Rent((int)byteCount);
                    try
                    {
                        Encoding.UTF8.GetBytes(value, backend);
                        context.Buffer.WriteToBuffer(backend.AsSpan(0, (int)byteCount));
                    }
                    finally
                    {
                        _arrayPool.Return(backend);
                    }

                    if (value.Any())
                    {
                        referenceTable.Add(tValue);
                    }
                }
            }
            else
            {
                Contract.Assert(false);
            }
        }

        public void WriteBytes(string value, SerializationContext context)
        {
            context.Buffer.WriteToBuffer((byte)Amf3Type.String);
            WriteStringBytesImpl(value, context, context.StringReferenceTable);
        }

        public void WriteBytes(XmlDocument xml, SerializationContext context)
        {
            context.Buffer.WriteToBuffer((byte)Amf3Type.XmlDocument);
            var content = XmlToString(xml);

            WriteStringBytesImpl(content, context, context.ObjectReferenceTable);
        }

        public void WriteBytes(DateTime dateTime, SerializationContext context)
        {
            context.Buffer.WriteToBuffer((byte)Amf3Type.Date);

            var refIndex = context.ObjectReferenceTable.IndexOf(dateTime);
            uint header = 0;
            if (refIndex >= 0)
            {
                header = (uint)refIndex << 1;

                WriteU29BytesImpl(header, context);
                return;
            }
            context.ObjectReferenceTable.Add(dateTime);

            var timeOffset = new DateTimeOffset(dateTime);
            var timestamp = timeOffset.ToUnixTimeMilliseconds();
            header = 0x01;
            WriteU29BytesImpl(header, context);
            var backend = _arrayPool.Rent(sizeof(double));
            try
            {
                var contractRet = NetworkBitConverter.TryGetBytes(timestamp, backend);
                Contract.Assert(contractRet);
                context.Buffer.WriteToBuffer(backend.AsSpan(0, sizeof(double)));
            }
            finally
            {
                _arrayPool.Return(backend);
            }

        }

        public void WriteBytes(Amf3Xml xml, SerializationContext context)
        {
            context.Buffer.WriteToBuffer((byte)Amf3Type.Xml);
            var content = XmlToString(xml);

            WriteStringBytesImpl(content, context, context.ObjectReferenceTable);
        }

        public void WriteBytes(Memory<byte> value, SerializationContext context)
        {
            context.Buffer.WriteToBuffer((byte)Amf3Type.ByteArray);
            uint header = 0;
            var refIndex = context.ObjectReferenceTable.IndexOf(value);
            if (refIndex >= 0)
            {
                header = (uint)refIndex << 1;
                WriteU29BytesImpl(header, context);
                return;
            }

            header = ((uint)value.Length << 1) | 0x01;
            WriteU29BytesImpl(header, context);

            context.Buffer.WriteToBuffer(value.Span);
            context.ObjectReferenceTable.Add(value);
        }

        public void WriteValueBytes(object value, SerializationContext context)
        {
            if (value == null)
            {
                WriteBytes((object)null, context);
                return;
            }
            var valueType = value.GetType();
            if (_writeHandlers.TryGetValue(valueType, out var handler))
            {
                handler(value, context);
            }
            else
            {
                if (valueType.IsGenericType)
                {
                    var genericDefination = valueType.GetGenericTypeDefinition();

                    if (genericDefination != typeof(Vector<>) && genericDefination != typeof(Amf3Dictionary<,>))
                    {
                        throw new NotSupportedException();
                    }

                    if (_writeHandlers.TryGetValue(genericDefination, out handler))
                    {
                        handler(value, context);
                    }
                }
                else
                {
                    WriteBytes(value, context);
                }
            }


        }

        public void WriteBytes(object value, SerializationContext context)
        {
            uint header = 0;
            if (value == null)
            {
                context.Buffer.WriteToBuffer((byte)Amf3Type.Null);
                return;
            }
            else
            {
                context.Buffer.WriteToBuffer((byte)Amf3Type.Object);
            }

            var refIndex = context.ObjectReferenceTable.IndexOf(value);
            if (refIndex >= 0)
            {
                header = (uint)refIndex << 1;
                WriteU29BytesImpl(header, context);
                return;
            }

            var objType = value.GetType();
            string attrTypeName = null;
            var classAttr = objType.GetCustomAttribute<TypedObjectAttribute>();
            if (classAttr != null)
            {
                attrTypeName = classAttr.Name;
            }
            var traits = new Amf3ClassTraits();
            var memberValues = new List<object>();
            if (value is AmfObject amf3Object)
            {
                if (amf3Object.IsAnonymous)
                {
                    traits.ClassName = "";
                    traits.ClassType = Amf3ClassType.Anonymous;
                }
                else
                {
                    traits.ClassName = attrTypeName ?? objType.Name;
                    traits.ClassType = Amf3ClassType.Typed;
                }
                traits.IsDynamic = amf3Object.IsDynamic;
                traits.Members = new List<string>(amf3Object.Fields.Keys);
                memberValues = new List<object>(amf3Object.Fields.Keys.Select(k => amf3Object.Fields[k]));
            }
            else if (value is IExternalizable)
            {
                traits.ClassName = attrTypeName ?? objType.Name;
                traits.ClassType = Amf3ClassType.Externalizable;
            }
            else
            {
                traits.ClassName = attrTypeName ?? objType.Name;
                traits.ClassType = Amf3ClassType.Typed;
                var props = objType.GetProperties();
                foreach (var prop in props)
                {
                    var attr = (ClassFieldAttribute)Attribute.GetCustomAttribute(prop, typeof(ClassFieldAttribute));
                    if (attr != null)
                    {
                        traits.Members.Add(attr.Name ?? prop.Name);
                        memberValues.Add(prop.GetValue(value));
                    }
                }
                traits.IsDynamic = value is IDynamicObject;
            }
            context.ObjectReferenceTable.Add(value);


            var traitRefIndex = context.ObjectTraitsReferenceTable.IndexOf(traits);
            if (traitRefIndex >= 0)
            {
                header = ((uint)traitRefIndex << 2) | 0x01;
                WriteU29BytesImpl(header, context);
            }
            else
            {
                if (traits.ClassType == Amf3ClassType.Externalizable)
                {
                    header = 0x07;
                    WriteU29BytesImpl(header, context);
                    WriteStringBytesImpl(traits.ClassName, context, context.StringReferenceTable);
                    var extObj = value as IExternalizable;
                    extObj.TryEncodeData(context.Buffer);
                    return;
                }
                else
                {
                    header = 0x03;
                    if (traits.IsDynamic)
                    {
                        header |= 0x08;
                    }
                    var memberCount = (uint)traits.Members.Count;
                    header |= memberCount << 4;
                    WriteU29BytesImpl(header, context);
                    WriteStringBytesImpl(traits.ClassName, context, context.StringReferenceTable);

                    foreach (var memberName in traits.Members)
                    {
                        WriteStringBytesImpl(memberName, context, context.StringReferenceTable);
                    }
                }
                context.ObjectTraitsReferenceTable.Add(traits);
            }


            foreach (var memberValue in memberValues)
            {
                WriteValueBytes(memberValue, context);
            }

            if (traits.IsDynamic)
            {
                var amf3Obj = value as IDynamicObject;
                foreach ((var key, var item) in amf3Obj.DynamicFields)
                {
                    WriteStringBytesImpl(key, context, context.StringReferenceTable);
                    WriteValueBytes(item, context);
                }
                WriteStringBytesImpl("", context, context.StringReferenceTable);
            }
        }

        public void WriteBytes(Vector<uint> value, SerializationContext context)
        {
            context.Buffer.WriteToBuffer((byte)Amf3Type.VectorUInt);

            var refIndex = context.ObjectReferenceTable.IndexOf(value);
            if (refIndex >= 0)
            {
                var header = (uint)refIndex << 1;
                WriteU29BytesImpl(header, context);
                return;
            }
            else
            {
                context.ObjectReferenceTable.Add(value);
                var header = ((uint)value.Count << 1) | 0x01;
                WriteU29BytesImpl(header, context);
                context.Buffer.WriteToBuffer(value.IsFixedSize ? (byte)0x01 : (byte)0x00);
                var buffer = _arrayPool.Rent(sizeof(uint));
                try
                {
                    foreach (var i in value)
                    {
                        var contractRet = NetworkBitConverter.TryGetBytes(i, buffer);
                        Contract.Assert(contractRet);
                        context.Buffer.WriteToBuffer(buffer.AsSpan(0, sizeof(uint)));
                    }
                }
                finally
                {
                    _arrayPool.Return(buffer);
                }
            }
        }

        public void WriteBytes(Vector<int> value, SerializationContext context)
        {
            context.Buffer.WriteToBuffer((byte)Amf3Type.VectorInt);

            var refIndex = context.ObjectReferenceTable.IndexOf(value);
            if (refIndex >= 0)
            {
                var header = (uint)refIndex << 1;
                WriteU29BytesImpl(header, context);
                return;
            }
            else
            {
                context.ObjectReferenceTable.Add(value);
                var header = ((uint)value.Count << 1) | 0x01;
                WriteU29BytesImpl(header, context);
                context.Buffer.WriteToBuffer(value.IsFixedSize ? (byte)0x01 : (byte)0x00);
                var buffer = _arrayPool.Rent(sizeof(int));
                try
                {

                    foreach (var i in value)
                    {
                        var contractRet = NetworkBitConverter.TryGetBytes(i, buffer);
                        Contract.Assert(contractRet);
                        context.Buffer.WriteToBuffer(buffer.AsSpan(0, sizeof(int)));
                    }
                }
                finally
                {
                    _arrayPool.Return(buffer);
                }
                return;
            }
        }

        public void WriteBytes(Vector<double> value, SerializationContext context)
        {
            context.Buffer.WriteToBuffer((byte)Amf3Type.VectorDouble);

            var refIndex = context.ObjectReferenceTable.IndexOf(value);
            if (refIndex >= 0)
            {
                var header = (uint)refIndex << 1;
                WriteU29BytesImpl(header, context);
                return;
            }
            else
            {
                context.ObjectReferenceTable.Add(value);
                var header = ((uint)value.Count << 1) | 0x01;
                WriteU29BytesImpl(header, context);
                context.Buffer.WriteToBuffer(value.IsFixedSize ? (byte)0x01 : (byte)0x00);
                var buffer = _arrayPool.Rent(sizeof(double));
                try
                {
                    foreach (var i in value)
                    {
                        var contractRet = NetworkBitConverter.TryGetBytes(i, buffer);
                        Contract.Assert(contractRet);
                        context.Buffer.WriteToBuffer(buffer.AsSpan(0, sizeof(double)));
                    }
                }
                finally
                {
                    _arrayPool.Return(buffer);
                }
                return;
            }
        }

        public void WriteBytes<T>(Vector<T> value, SerializationContext context)
        {
            context.Buffer.WriteToBuffer((byte)Amf3Type.VectorObject);

            var refIndex = context.ObjectReferenceTable.IndexOf(value);
            if (refIndex >= 0)
            {
                var header = (uint)refIndex << 1;
                WriteU29BytesImpl(header, context);
                return;
            }
            else
            {
                context.ObjectReferenceTable.Add(value);
                var header = ((uint)value.Count << 1) | 0x01;
                WriteU29BytesImpl(header, context);
                context.Buffer.WriteToBuffer(value.IsFixedSize ? (byte)0x01 : (byte)0x00);
                var tType = typeof(T);

                string typeName = tType.Name;
                var attr = tType.GetCustomAttribute<TypedObjectAttribute>();
                if (attr != null)
                {
                    typeName = attr.Name;
                }

                var className = typeof(T) == typeof(object) ? "*" : typeName;
                WriteStringBytesImpl(className, context, context.StringReferenceTable);

                foreach (var i in value)
                {
                    WriteValueBytes(i, context);
                }
                return;
            }

        }

        public void WriteBytes(Amf3Array value, SerializationContext context)
        {
            context.Buffer.WriteToBuffer((byte)Amf3Type.Array);

            var refIndex = context.ObjectReferenceTable.IndexOf(value);
            if (refIndex >= 0)
            {
                var header = (uint)refIndex << 1;
                WriteU29BytesImpl(header, context);
                return;
            }
            else
            {
                context.ObjectReferenceTable.Add(value);
                var header = ((uint)value.DensePart.Count << 1) | 0x01;
                WriteU29BytesImpl(header, context);
                foreach ((var key, var item) in value.SparsePart)
                {
                    WriteStringBytesImpl(key, context, context.StringReferenceTable);
                    WriteValueBytes(item, context);
                }
                WriteStringBytesImpl("", context, context.StringReferenceTable);

                foreach (var i in value.DensePart)
                {
                    WriteValueBytes(i, context);
                }

                return;
            }
        }

        public void WriteBytes<TKey, TValue>(Amf3Dictionary<TKey, TValue> value, SerializationContext context)
        {
            context.Buffer.WriteToBuffer((byte)Amf3Type.Dictionary);

            var refIndex = context.ObjectReferenceTable.IndexOf(value);

            if (refIndex >= 0)
            {
                var header = (uint)refIndex << 1;
                WriteU29BytesImpl(header, context);
                return;
            }
            else
            {
                context.ObjectReferenceTable.Add(value);
                var header = (uint)value.Count << 1 | 0x01;
                WriteU29BytesImpl(header, context);

                context.Buffer.WriteToBuffer((byte)(value.WeakKeys ? 0x01 : 0x00));
                foreach ((var key, var item) in value)
                {
                    WriteValueBytes(key, context);
                    WriteValueBytes(item, context);
                }
                return;
            }
        }

    }
}


================================================
FILE: Harmonic/Networking/Amf/Serialization/Amf3/Amf3Xml.cs
================================================
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;

namespace Harmonic.Networking.Amf.Serialization.Amf3
{
    public class Amf3Xml : XmlDocument
    {
        public Amf3Xml() : base() { }

        public Amf3Xml(XmlNameTable nt) : base(nt) { }

        protected internal Amf3Xml(XmlImplementation imp) : base(imp) { }
    }
}


================================================
FILE: Harmonic/Networking/Amf/Serialization/Amf3/SerializationContext.cs
================================================
using Harmonic.Buffers;
using System;
using System.Collections.Generic;
using System.Text;

namespace Harmonic.Networking.Amf.Serialization.Amf3
{
    public class SerializationContext : IDisposable
    {
        public ByteBuffer Buffer { get; private set; }
        public List<object> ObjectReferenceTable { get; set; } = new List<object>();
        public List<string> StringReferenceTable { get; set; } = new List<string>();
        public List<Amf3ClassTraits> ObjectTraitsReferenceTable { get; set; } = new List<Amf3ClassTraits>();

        public int MessageLength => Buffer.Length;
        private bool _disposeBuffer = true;

        public SerializationContext()
        {
            Buffer = new ByteBuffer();
        }

        public SerializationContext(ByteBuffer buffer)
        {
            Buffer = buffer;
            _disposeBuffer = false;
        }

        public void Dispose()
        {
            if (_disposeBuffer)
            {
                ((IDisposable)Buffer).Dispose();
            }
        }

        public void GetMessage(Span<byte> buffer)
        {
            ObjectReferenceTable.Clear();
            StringReferenceTable.Clear();
            ObjectTraitsReferenceTable.Clear();
            Buffer.TakeOutMemory(buffer);
        }

    }
}


================================================
FILE: Harmonic/Networking/Amf/Serialization/Amf3/Vector.cs
================================================
using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;

namespace Harmonic.Networking.Amf.Serialization.Amf3
{
    public class Vector<T> : List<T>, IEquatable<List<T>>
    {
        private List<T> _data = new List<T>();
        public bool IsFixedSize { get; set; } = false;

        public new void Add(T item)
        {
            if (IsFixedSize)
            {
                throw new NotSupportedException();
            }
            ((List<T>)this).Add(item);
        }

        public override bool Equals(object obj)
        {
            if (obj is Vector<T> en)
            {
                return IsFixedSize == en.IsFixedSize && en.SequenceEqual(this);
            }
            return base.Equals(obj);
        }

        public bool Equals(List<T> other)
        {
            return other.SequenceEqual(this);
        }

        public override int GetHashCode()
        {
            var hash = new HashCode();
            foreach (var d in _data)
            {
                hash.Add(d);
            }
            hash.Add(IsFixedSize);
            return hash.ToHashCode();
        }
    }
}


================================================
FILE: Harmonic/Networking/Amf/Serialization/Attributes/ClassFieldAttribute.cs
================================================
using System;
using System.Collections.Generic;
using System.Text;

namespace Harmonic.Networking.Amf.Serialization.Attributes
{
    [AttributeUsage(AttributeTargets.Property)]
    public class ClassFieldAttribute : Attribute
    {
        public string Name { get; set; } = null;
    }
}


================================================
FILE: Harmonic/Networking/Amf/Serialization/Attributes/TypedObjectAttribute.cs
================================================
using System;
using System.Collections.Generic;
using System.Text;

namespace Harmonic.Networking.Amf.Attributes
{
    [AttributeUsage(AttributeTargets.Class)]
    public class TypedObjectAttribute : Attribute
    {
        public string Name { get; set; } = null;
    }
}


================================================
FILE: Harmonic/Networking/ConnectionInformation.cs
================================================


using Harmonic.Networking.Rtmp.Messages.Commands;
using Harmonic.Networking.Rtmp.Messages;

namespace Harmonic.Networking
{
    public class ConnectionInformation
    {
        public string App { get; set; }
        public string Flashver { get; set; }
        public string SwfUrl { get; set; }
        public string TcUrl { get; set; }
        public bool Fpad { get; set; }
        public int AudioCodecs { get; set; }
        public int VideoCodecs { get; set; }
        int VideoFunction { get; set; }
        public string PageUrl { get; set; }
        public AmfEncodingVersion AmfEncodingVersion { get; set; }
    }
}

================================================
FILE: Harmonic/Networking/Flv/Data/AacPacketType.cs
================================================
using System;
using System.Collections.Generic;
using System.Text;

namespace Harmonic.Networking.Flv.Data
{
    public enum AacPacketType
    {
        SequenceHeader,
        Raw
    }
}


================================================
FILE: Harmonic/Networking/Flv/Data/AudioData.cs
================================================
using System;
using System.Collections.Generic;
using System.Text;

namespace Harmonic.Networking.Flv.Data
{
    public class AudioData
    {
        public AacPacketType? AacPacketType { get; set; } = null;
        public ReadOnlyMemory<byte> Data { get; set; }
    }
}


================================================
FILE: Harmonic/Networking/Flv/Data/CodecId.cs
================================================
using System;
using System.Collections.Generic;
using System.Text;

namespace Harmonic.Networking.Flv.Data
{
    public enum CodecId
    {
        Jpeg = 1,
        H263,
        ScreenVideo,
        Vp6,
        Vp6WithAlpha,
        ScreenVideo2,
        Avc
    }
}


================================================
FILE: Harmonic/Networking/Flv/Data/FlvAudioData.cs
================================================
using System;
using System.Collections.Generic;
using System.Text;

namespace Harmonic.Networking.Flv.Data
{
    public class FlvAudioData
    {
        public SoundFormat SoundFormat { get; set; }
        public SoundRate SoundRate { get; set; }
        public SoundSize SoundSize { get; set; }
        public SoundType SoundType { get; set; }
        public AudioData AudioData { get; set; }
    }
}


================================================
FILE: Harmonic/Networking/Flv/Data/FlvVideoData.cs
================================================
using System;
using System.Collections.Generic;
using System.Text;

namespace Harmonic.Networking.Flv.Data
{
    public class FlvVideoData
    {
        public FrameType FrameType { get; set; }
        public CodecId CodecId { get; set; }

        public ReadOnlyMemory<byte> VideoData { get; set; }

    }
}


================================================
FILE: Harmonic/Networking/Flv/Data/FrameType.cs
================================================
using System;
using System.Collections.Generic;
using System.Text;

namespace Harmonic.Networking.Flv.Data
{
    public enum FrameType
    {
        KeyFrame = 1,
        InterFrame,
        DisposableInterFrame,
        GeneratedKeyFrame,
        VideoInfoOrCommandFrame
    }
}


================================================
FILE: Harmonic/Networking/Flv/Data/SoundFormat.cs
================================================
using System;
using System.Collections.Generic;
using System.Text;

namespace Harmonic.Networking.Flv.Data
{
    public enum SoundFormat
    {
        PcmPE,
        Adpcm,
        Mp3,
        PcmLE,
        Nellymonser16k,
        Nellymonser8k,
        Nellymonser,
        G711ALawPcm,
        G711MuLawPcm,
        Aac = 10,
        Speex,
        Mp38k = 14,
        DeviceSpecificSound
    }
}


================================================
FILE: Harmonic/Networking/Flv/Data/SoundRate.cs
================================================
using System;
using System.Collections.Generic;
using System.Text;

namespace Harmonic.Networking.Flv.Data
{
    public enum SoundRate
    {
        Hz5Dot5,
        Hz11,
        Hz22,
        Hz44
    }
}


================================================
FILE: Harmonic/Networking/Flv/Data/SoundSize.cs
================================================
using System;
using System.Collections.Generic;
using System.Text;

namespace Harmonic.Networking.Flv.Data
{
    public enum SoundSize
    {
        Snd8Bit,
        Snd16Bit
    }
}


================================================
FILE: Harmonic/Networking/Flv/Data/SoundType.cs
================
Download .txt
gitextract_v87mtvnp/

├── .github/
│   └── workflows/
│       └── dotnetcore.yml
├── .gitignore
├── Harmonic/
│   ├── Buffers/
│   │   └── ByteBuffer.cs
│   ├── Controllers/
│   │   ├── Living/
│   │   │   ├── LivingController.cs
│   │   │   └── LivingStream.cs
│   │   ├── NeverRegisterAttribute.cs
│   │   ├── Record/
│   │   │   ├── RecordController.cs
│   │   │   └── RecordStream.cs
│   │   ├── RtmpController.cs
│   │   ├── WebSocketController.cs
│   │   └── WebSocketPlayController.cs
│   ├── Harmonic.csproj
│   ├── Hosting/
│   │   ├── IStartup.cs
│   │   ├── RtmpServer.cs
│   │   ├── RtmpServerBuilder.cs
│   │   ├── RtmpServerOptions.cs
│   │   └── WebSocketOptions.cs
│   ├── Networking/
│   │   ├── Amf/
│   │   │   ├── Common/
│   │   │   │   ├── Amf3Object.cs
│   │   │   │   ├── TypeRegisterState.cs
│   │   │   │   ├── Undefined.cs
│   │   │   │   └── Unsupported.cs
│   │   │   ├── Data/
│   │   │   │   ├── IDynamicObject.cs
│   │   │   │   ├── IExternalizable.cs
│   │   │   │   └── Message.cs
│   │   │   └── Serialization/
│   │   │       ├── Amf0/
│   │   │       │   ├── Amf0CommonValues.cs
│   │   │       │   ├── Amf0Reader.cs
│   │   │       │   ├── Amf0Type.cs
│   │   │       │   ├── Amf0Writer.cs
│   │   │       │   └── SerializationContext.cs
│   │   │       ├── Amf3/
│   │   │       │   ├── Amf3Array.cs
│   │   │       │   ├── Amf3ClassTraits.cs
│   │   │       │   ├── Amf3CommonValues.cs
│   │   │       │   ├── Amf3Dictionary.cs
│   │   │       │   ├── Amf3Reader.cs
│   │   │       │   ├── Amf3Type.cs
│   │   │       │   ├── Amf3Writer.cs
│   │   │       │   ├── Amf3Xml.cs
│   │   │       │   ├── SerializationContext.cs
│   │   │       │   └── Vector.cs
│   │   │       └── Attributes/
│   │   │           ├── ClassFieldAttribute.cs
│   │   │           └── TypedObjectAttribute.cs
│   │   ├── ConnectionInformation.cs
│   │   ├── Flv/
│   │   │   ├── Data/
│   │   │   │   ├── AacPacketType.cs
│   │   │   │   ├── AudioData.cs
│   │   │   │   ├── CodecId.cs
│   │   │   │   ├── FlvAudioData.cs
│   │   │   │   ├── FlvVideoData.cs
│   │   │   │   ├── FrameType.cs
│   │   │   │   ├── SoundFormat.cs
│   │   │   │   ├── SoundRate.cs
│   │   │   │   ├── SoundSize.cs
│   │   │   │   └── SoundType.cs
│   │   │   ├── FlvDemuxer.cs
│   │   │   └── FlvMuxer.cs
│   │   ├── Rtmp/
│   │   │   ├── ChunkStreamContext.cs
│   │   │   ├── Data/
│   │   │   │   ├── ChunkBasicHeader.cs
│   │   │   │   ├── ChunkHeader.cs
│   │   │   │   ├── ChunkHeaderType.cs
│   │   │   │   ├── Message.cs
│   │   │   │   ├── MessageHeader.cs
│   │   │   │   ├── MessageType.cs
│   │   │   │   ├── SharedObjectMessage.cs
│   │   │   │   └── UserControlMessageEvents.cs
│   │   │   ├── Exceptions/
│   │   │   │   └── UnknownMessageReceivedException.cs
│   │   │   ├── HandshakeContext.cs
│   │   │   ├── IOPipeLine.cs
│   │   │   ├── MessageReadingState.cs
│   │   │   ├── Messages/
│   │   │   │   ├── AbortMessage.cs
│   │   │   │   ├── AcknowledgementMessage.cs
│   │   │   │   ├── AggregateMessage.cs
│   │   │   │   ├── AmfEncodingVersion.cs
│   │   │   │   ├── AudioMessage.cs
│   │   │   │   ├── Commands/
│   │   │   │   │   ├── CallCommandMessage.cs
│   │   │   │   │   ├── CommandMessage.cs
│   │   │   │   │   ├── CommandMessageFactory.cs
│   │   │   │   │   ├── ConnectCommandMessage.cs
│   │   │   │   │   ├── CreateStreamCommandMessage.cs
│   │   │   │   │   ├── DeleteStreamCommandMessage.cs
│   │   │   │   │   ├── OnStatusCommandMessage.cs
│   │   │   │   │   ├── PauseCommandMessage.cs
│   │   │   │   │   ├── Play2CommandMessage.cs
│   │   │   │   │   ├── PlayCommandMessage.cs
│   │   │   │   │   ├── PublishCommandMessage.cs
│   │   │   │   │   ├── ReceiveAudioCommandMessage.cs
│   │   │   │   │   ├── ReceiveVideoCommandMessage.cs
│   │   │   │   │   ├── ReturnResultCommandMessage.cs
│   │   │   │   │   └── SeekCommandMessage.cs
│   │   │   │   ├── ControlMessage.cs
│   │   │   │   ├── DataMessage.cs
│   │   │   │   ├── SetChunkSizeMessage.cs
│   │   │   │   ├── SetPeerBandwidthMessage.cs
│   │   │   │   ├── UserControlMessages/
│   │   │   │   │   ├── PingRequestMessage.cs
│   │   │   │   │   ├── PingResponseMessage.cs
│   │   │   │   │   ├── SetBufferLengthMessage.cs
│   │   │   │   │   ├── StreamBeginMessage.cs
│   │   │   │   │   ├── StreamDryMessage.cs
│   │   │   │   │   ├── StreamEofMessage.cs
│   │   │   │   │   ├── StreamIsRecordedMessage.cs
│   │   │   │   │   ├── UserControlMessage.cs
│   │   │   │   │   └── UserControlMessageFactory.cs
│   │   │   │   ├── VideoMessage.cs
│   │   │   │   └── WindowAcknowledgementSizeMessage.cs
│   │   │   ├── NetConnection.cs
│   │   │   ├── NetStream.cs
│   │   │   ├── RtmpChunkStream.cs
│   │   │   ├── RtmpControlChunkStream.cs
│   │   │   ├── RtmpControlMessageStream.cs
│   │   │   ├── RtmpMessageStream.cs
│   │   │   ├── RtmpSession.cs
│   │   │   ├── Serialization/
│   │   │   │   ├── OptionalArgumentAttribute.cs
│   │   │   │   ├── RtmpCommandAttribute.cs
│   │   │   │   ├── RtmpMessageAttribute.cs
│   │   │   │   ├── SerializationContext.cs
│   │   │   │   └── UserControlMessageAttribute.cs
│   │   │   ├── Streaming/
│   │   │   │   ├── PublishingType.cs
│   │   │   │   └── PublishingTypeNameAttribute.cs
│   │   │   ├── Supervisor.cs
│   │   │   └── WriteState.cs
│   │   ├── Utils/
│   │   │   ├── NetworkBitConverter.cs
│   │   │   └── StreamHelper.cs
│   │   └── WebSocket/
│   │       └── WebSocketSession.cs
│   ├── Rpc/
│   │   ├── CommandObjectAttribute.cs
│   │   ├── FromCommandObjectAttribute.cs
│   │   ├── FromOptionalArgumentAttribute.cs
│   │   ├── RpcMethodAttribute.cs
│   │   └── RpcService.cs
│   └── Service/
│       ├── PublisherSessionService.cs
│       ├── RecordService.cs
│       └── RecordServiceConfiguration.cs
├── Harmonic.sln
├── LICENSE
├── README.md
├── RoadMap.md
├── UnitTest/
│   ├── TestAmf0Reader.cs
│   ├── TestAmf0Writer.cs
│   ├── TestAmf3Reader.cs
│   ├── TestAmf3Writer.cs
│   ├── TestUnlimitedBuffer.cs
│   └── UnitTest.csproj
├── demo/
│   ├── MyLivingController.cs
│   ├── MyLivingStream.cs
│   ├── Program.cs
│   ├── StartUp.cs
│   └── demo.csproj
├── docs/
│   ├── README.md
│   ├── api.md
│   └── rpc.md
└── samples/
    ├── amf0/
    │   ├── boolean/
    │   │   ├── false.amf0
    │   │   └── true.amf0
    │   ├── misc/
    │   │   ├── array.amf0
    │   │   ├── date.amf0
    │   │   ├── ecmaarray.amf0
    │   │   ├── longstring.amf0
    │   │   ├── null.amf0
    │   │   ├── object.amf0
    │   │   ├── packet.amf0
    │   │   ├── undefined.amf0
    │   │   └── xml.amf0
    │   ├── number/
    │   │   ├── 1.1261843717924092.amf0
    │   │   ├── 2.3763213699559538.amf0
    │   │   ├── 3.498957015368982.amf0
    │   │   ├── 3.9231228517554273.amf0
    │   │   ├── 4.141123418573091.amf0
    │   │   ├── 4.485998361678176.amf0
    │   │   ├── 5.442560101247932.amf0
    │   │   ├── 7.560779119365773.amf0
    │   │   ├── 9.719564819564491.amf0
    │   │   └── 9.844079468164518.amf0
    │   └── string/
    │       ├── fkqudskxxb.amf0
    │       ├── grkogrokmq.amf0
    │       ├── gymtsavnng.amf0
    │       ├── karxrlzavl.amf0
    │       ├── lbwkjydfuv.amf0
    │       ├── qsqwosrxcl.amf0
    │       ├── rpwhhjwary.amf0
    │       ├── sjceuhcjfa.amf0
    │       ├── vrouinfvzr.amf0
    │       └── vsyrigrfbn.amf0
    └── amf3/
        ├── boolean/
        │   ├── false.amf3
        │   └── true.amf3
        ├── intenger/
        │   ├── 56.amf3
        │   ├── 57.amf3
        │   ├── 60.amf3
        │   ├── 67.amf3
        │   ├── 72.amf3
        │   ├── 73.amf3
        │   ├── 75.amf3
        │   ├── 78.amf3
        │   ├── 82.amf3
        │   └── 98.amf3
        ├── misc/
        │   ├── array.amf3
        │   ├── bytearray.amf3
        │   ├── date.amf3
        │   ├── dictionary.amf3
        │   ├── externalizable.amf3
        │   ├── null.amf3
        │   ├── object.amf3
        │   ├── packet.amf3
        │   ├── undefined.amf3
        │   ├── vector_any_object.amf3
        │   ├── vector_double.amf3
        │   ├── vector_int.amf3
        │   ├── vector_typted_object.amf3
        │   ├── vector_uint.amf3
        │   ├── xml.amf3
        │   └── xml_document.amf3
        ├── number/
        │   ├── 0.05806697191443333.amf3
        │   ├── 3.962148410082559.amf3
        │   ├── 4.465764800567858.amf3
        │   ├── 6.863435764713296.amf3
        │   ├── 7.645173446829178.amf3
        │   ├── 8.451623695104308.amf3
        │   ├── 8.518697602984554.amf3
        │   ├── 8.85002823631796.amf3
        │   ├── 9.838871036292584.amf3
        │   └── 9.98509389093438.amf3
        └── string/
            ├── aoxqmkvbxa.amf3
            ├── bghnwadduz.amf3
            ├── cmaljzrwgc.amf3
            ├── cuyerozwyf.amf3
            ├── dfjfucqvpr.amf3
            ├── fxxcsjosdu.amf3
            ├── korbgwizge.amf3
            ├── psvigwvvpx.amf3
            ├── ubteltbaku.amf3
            └── vqayztgtuf.amf3
Download .txt
SYMBOL INDEX (675 symbols across 135 files)

FILE: Harmonic/Buffers/ByteBuffer.cs
  class ByteBuffer (line 13) | public class ByteBuffer : IDisposable
    method ByteBuffer (line 32) | public ByteBuffer(int bufferSegmentSize = 1024, int maxiumBufferSize =...
    method BufferBytesAvailable (line 52) | private int BufferBytesAvailable()
    method AddNewBufferSegment (line 57) | private void AddNewBufferSegment()
    method WriteToBuffer (line 65) | public void WriteToBuffer(byte data)
    method WriteToBufferNoCheck (line 89) | private void WriteToBufferNoCheck(ReadOnlySpan<byte> bytes)
    class _source (line 125) | class _source : IValueTaskSource
      method _source (line 136) | public _source()
      method Cancel (line 140) | public void Cancel()
      method Success (line 144) | public void Success()
      method GetResult (line 171) | public void GetResult(short token)
      method GetStatus (line 176) | public ValueTaskSourceStatus GetStatus(short token)
      method OnCompleted (line 181) | public void OnCompleted(Action<object> continuation, object state, s...
      method InvokeContinuation (line 230) | private void InvokeContinuation(Action<object> continuation, object ...
    method WriteToBufferAsync (line 264) | public ValueTask WriteToBufferAsync(ReadOnlyMemory<byte> bytes)
    method WriteToBuffer (line 287) | public void WriteToBuffer(ReadOnlySpan<byte> bytes)
    method TakeOutMemoryNoCheck (line 296) | private void TakeOutMemoryNoCheck(Span<byte> buffer)
    method TakeOutMemoryAsync (line 375) | public ValueTask TakeOutMemoryAsync(Memory<byte> buffer, CancellationT...
    method TakeOutMemory (line 406) | public void TakeOutMemory(Span<byte> buffer)
    method Dispose (line 418) | protected virtual void Dispose(bool disposing)
    method Dispose (line 438) | public void Dispose()

FILE: Harmonic/Controllers/Living/LivingController.cs
  class LivingController (line 9) | public class LivingController : RtmpController
    method CreateStream (line 11) | [RpcMethod("createStream")]

FILE: Harmonic/Controllers/Living/LivingStream.cs
  class LivingStream (line 17) | public class LivingStream : NetStream
    method LivingStream (line 30) | public LivingStream(PublisherSessionService publisherSessionService)
    method Play (line 35) | [RpcMethod("play")]
    method SendVideo (line 95) | private async void SendVideo(VideoMessage message)
    method SendAudio (line 113) | private async void SendAudio(AudioMessage message)
    method Publish (line 130) | [RpcMethod(Name = "publish")]
    method HandleDataMessage (line 161) | private void HandleDataMessage(DataMessage msg)
    method HandleAudioMessage (line 166) | private void HandleAudioMessage(AudioMessage audioData)
    method HandleVideoMessage (line 176) | private void HandleVideoMessage(VideoMessage videoData)
    method Dispose (line 189) | protected override void Dispose(bool disposing)

FILE: Harmonic/Controllers/NeverRegisterAttribute.cs
  class NeverRegisterAttribute (line 7) | [AttributeUsage(AttributeTargets.Class)]

FILE: Harmonic/Controllers/Record/RecordController.cs
  class RecordController (line 9) | public class RecordController : RtmpController
    method CreateStream (line 11) | [RpcMethod("createStream")]

FILE: Harmonic/Controllers/Record/RecordStream.cs
  class RecordStream (line 25) | public class RecordStream : NetStream
    method Dispose (line 45) | protected override async void Dispose(bool disposing)
    method RecordStream (line 89) | public RecordStream(RecordService recordService)
    method Publish (line 95) | [RpcMethod(Name = "publish")]
    method HandleUserControlMessage (line 134) | private void HandleUserControlMessage(UserControlMessage msg)
    method HandleAudioMessage (line 142) | private async void HandleAudioMessage(AudioMessage message)
    method HandleVideoMessage (line 156) | private async void HandleVideoMessage(VideoMessage message)
    method HandleData (line 179) | private void HandleData(DataMessage message)
    method Seek (line 192) | [RpcMethod("seek")]
    method Play (line 218) | [RpcMethod("play")]
    method Pause (line 265) | [RpcMethod("pause")]
    method StartPlayNoLock (line 285) | private async Task StartPlayNoLock(CancellationToken ct)
    method ReadMessage (line 298) | private Task<Message> ReadMessage(CancellationToken ct)
    method SeekAndPlay (line 303) | private async Task SeekAndPlay(double milliSeconds, CancellationToken ct)
    method PlayRecordFileNoLock (line 325) | private async Task PlayRecordFileNoLock(CancellationToken ct)
    method SaveMessage (line 345) | private async Task SaveMessage(Message message)

FILE: Harmonic/Controllers/RtmpController.cs
  class RtmpController (line 10) | public abstract class RtmpController
    method DeleteStream (line 43) | [RpcMethod("deleteStream")]

FILE: Harmonic/Controllers/WebSocketController.cs
  class WebSocketController (line 12) | public abstract class WebSocketController
    method OnConnect (line 42) | public abstract Task OnConnect();
    method OnMessage (line 44) | public abstract void OnMessage(string msg);

FILE: Harmonic/Controllers/WebSocketPlayController.cs
  class WebSocketPlayController (line 17) | public class WebSocketPlayController : WebSocketController, IDisposable
    method WebSocketPlayController (line 27) | public WebSocketPlayController(PublisherSessionService publisherSessio...
    method OnConnect (line 33) | public override async Task OnConnect()
    method PlayRecordFile (line 93) | private async Task PlayRecordFile()
    method SendVideo (line 112) | private void SendVideo(VideoMessage message)
    method SendAudio (line 117) | private void SendAudio(AudioMessage message)
    method OnMessage (line 122) | public override void OnMessage(string msg)
    method Dispose (line 129) | protected virtual void Dispose(bool disposing)
    method Dispose (line 151) | public void Dispose()

FILE: Harmonic/Hosting/IStartup.cs
  type IStartup (line 6) | public interface IStartup
    method ConfigureServices (line 8) | void ConfigureServices(ContainerBuilder builder);

FILE: Harmonic/Hosting/RtmpServer.cs
  class RtmpServer (line 16) | public class RtmpServer
    method RtmpServer (line 26) | internal RtmpServer(RtmpServerOptions options, WebSocketOptions webSoc...
    method StartAsync (line 41) | public Task StartAsync(CancellationToken ct = default)
    method AcceptCallback (line 105) | private async void AcceptCallback(IAsyncResult ar, CancellationToken ct)

FILE: Harmonic/Hosting/RtmpServerBuilder.cs
  class RtmpServerBuilder (line 11) | public class RtmpServerBuilder
    method UseStartup (line 21) | public RtmpServerBuilder UseStartup<T>() where T: IStartup, new()
    method UseSsl (line 26) | public RtmpServerBuilder UseSsl(X509Certificate2 cert)
    method UseWebSocket (line 33) | public RtmpServerBuilder UseWebSocket(Action<WebSocketOptions> conf)
    method UseHarmonic (line 41) | public RtmpServerBuilder UseHarmonic(Action<RtmpServerOptions> config)
    method Build (line 48) | public RtmpServer Build()

FILE: Harmonic/Hosting/RtmpServerOptions.cs
  class RtmpServerOptions (line 21) | public class RtmpServerOptions
    method RtmpServerOptions (line 53) | internal RtmpServerOptions()
    method BuildContainer (line 74) | internal void BuildContainer()
    method RegisterMessage (line 80) | public void RegisterMessage<T>(MessageFactory factory) where T : Message
    method RegisterMessage (line 95) | public void RegisterMessage<T>() where T : Message, new()
    method RegisterController (line 114) | internal void RegisterController(Type controllerType, string appName =...
    method RegisterStream (line 125) | internal void RegisterStream(Type streamType)
    method CleanupRpcRegistration (line 135) | internal void CleanupRpcRegistration()
    method RegisterCommonServices (line 139) | private void RegisterCommonServices(ContainerBuilder builder)
    method RegisterController (line 154) | internal void RegisterController<T>(string appName = null) where T : R...
    method RegisterStream (line 158) | internal void RegisterStream<T>() where T : NetStream

FILE: Harmonic/Hosting/WebSocketOptions.cs
  class WebSocketOptions (line 11) | public class WebSocketOptions
    method RegisterController (line 20) | internal void RegisterController<T>() where T: WebSocketController
    method RegisterController (line 25) | internal void RegisterController(Type controllerType)

FILE: Harmonic/Networking/Amf/Common/Amf3Object.cs
  class AmfObject (line 10) | public class AmfObject : IDynamicObject, IEnumerable
    method AmfObject (line 23) | public AmfObject()
    method AmfObject (line 28) | public AmfObject(Dictionary<string, object> values)
    method Add (line 33) | public void Add(string memberName, object member)
    method AddDynamic (line 38) | public void AddDynamic(string memberName, object member)
    method GetEnumerator (line 43) | public IEnumerator GetEnumerator()

FILE: Harmonic/Networking/Amf/Common/TypeRegisterState.cs
  class TypeRegisterState (line 7) | class TypeRegisterState

FILE: Harmonic/Networking/Amf/Common/Undefined.cs
  class Undefined (line 7) | public class Undefined

FILE: Harmonic/Networking/Amf/Common/Unsupported.cs
  class Unsupported (line 7) | public class Unsupported

FILE: Harmonic/Networking/Amf/Data/IDynamicObject.cs
  type IDynamicObject (line 7) | public interface IDynamicObject
    method AddDynamic (line 11) | void AddDynamic(string key, object data);

FILE: Harmonic/Networking/Amf/Data/IExternalizable.cs
  type IExternalizable (line 8) | public interface IExternalizable
    method TryDecodeData (line 10) | bool TryDecodeData(Span<byte> buffer, out int consumed);
    method TryEncodeData (line 12) | bool TryEncodeData(ByteBuffer buffer);

FILE: Harmonic/Networking/Amf/Data/Message.cs
  class Message (line 7) | public class Message

FILE: Harmonic/Networking/Amf/Serialization/Amf0/Amf0CommonValues.cs
  class Amf0CommonValues (line 12) | public static class Amf0CommonValues

FILE: Harmonic/Networking/Amf/Serialization/Amf0/Amf0Reader.cs
  class Amf0Reader (line 16) | public class Amf0Reader
    method Amf0Reader (line 49) | public Amf0Reader()
    method ResetReference (line 72) | public void ResetReference()
    method RegisterType (line 76) | public void RegisterType<T>() where T : new()
    method RegisterIExternalizableForAvmPlus (line 103) | public void RegisterIExternalizableForAvmPlus<T>() where T : IExternal...
    method OutValueTypeEraser (line 108) | private ReadDataHandler OutValueTypeEraser<T>(ReadDataHandler<T> handler)
    method TryReadHeader (line 118) | private bool TryReadHeader(Span<byte> buffer, out KeyValuePair<string,...
    method TryGetMessage (line 149) | public bool TryGetMessage(Span<byte> buffer, out Message message, out ...
    method TryGetPacket (line 194) | public bool TryGetPacket(Span<byte> buffer, out List<KeyValuePair<stri...
    method TryDescribeData (line 238) | public bool TryDescribeData(Span<byte> buffer, out Amf0Type type, out ...
    method TryGetNumber (line 263) | public bool TryGetNumber(Span<byte> buffer, out double value, out int ...
    method TryGetBoolean (line 280) | public bool TryGetBoolean(Span<byte> buffer, out bool value, out int b...
    method TryGetString (line 299) | public bool TryGetString(Span<byte> buffer, out string value, out int ...
    method TryGetObjectImpl (line 324) | private bool TryGetObjectImpl(Span<byte> objectBuffer, out Dictionary<...
    method TryGetObject (line 358) | public bool TryGetObject(Span<byte> buffer, out AmfObject value, out i...
    method TryGetNull (line 397) | public bool TryGetNull(Span<byte> buffer, out object value, out int by...
    method TryGetUndefined (line 415) | public bool TryGetUndefined(Span<byte> buffer, out Undefined value, ou...
    method TryGetReference (line 433) | private bool TryGetReference(Span<byte> buffer, out object value, out ...
    method TryGetKeyValuePair (line 458) | private bool TryGetKeyValuePair(Span<byte> buffer, out KeyValuePair<st...
    method TryGetEcmaArray (line 486) | public bool TryGetEcmaArray(Span<byte> buffer, out Dictionary<string, ...
    method TryGetStrictArray (line 565) | public bool TryGetStrictArray(Span<byte> buffer, out List<object> arra...
    method TryGetDate (line 610) | public bool TryGetDate(Span<byte> buffer, out DateTime value, out int ...
    method TryGetLongString (line 631) | public bool TryGetLongString(Span<byte> buffer, out string value, out ...
    method TryGetStringImpl (line 656) | internal bool TryGetStringImpl(Span<byte> buffer, int lengthOfLengthFi...
    method TryGetUnsupported (line 680) | private bool TryGetUnsupported(Span<byte> buffer, out Unsupported valu...
    method TryGetXmlDocument (line 701) | public bool TryGetXmlDocument(Span<byte> buffer, out XmlDocument value...
    method TryGetTypedObject (line 722) | public bool TryGetTypedObject(Span<byte> buffer, out object value, out...
    method TryGetAvmPlusObject (line 782) | public bool TryGetAvmPlusObject(Span<byte> buffer, out object value, o...
    method TryGetValue (line 808) | public bool TryGetValue(Span<byte> objectBuffer, out Amf0Type objectTy...

FILE: Harmonic/Networking/Amf/Serialization/Amf0/Amf0Type.cs
  type Amf0Type (line 7) | public enum Amf0Type

FILE: Harmonic/Networking/Amf/Serialization/Amf0/Amf0Writer.cs
  class Amf0Writer (line 19) | public class Amf0Writer
    method Amf0Writer (line 26) | public Amf0Writer()
    method GetBytesWrapper (line 51) | private GetBytesHandler GetBytesWrapper<T>(GetBytesHandler<T> handler)
    method WriteAvmPlusBytes (line 66) | public void WriteAvmPlusBytes(SerializationContext context)
    method WriteStringBytesImpl (line 71) | private void WriteStringBytesImpl(string str, SerializationContext con...
    method WriteBytes (line 125) | public void WriteBytes(string str, SerializationContext context)
    method WriteBytes (line 141) | public void WriteBytes(double val, SerializationContext context)
    method WriteBytes (line 159) | public void WriteBytes(bool val, SerializationContext context)
    method WriteBytes (line 168) | public void WriteBytes(Undefined value, SerializationContext context)
    method WriteBytes (line 176) | public void WriteBytes(Unsupported value, SerializationContext context)
    method WriteReferenceIndexBytes (line 182) | private void WriteReferenceIndexBytes(ushort index, SerializationConte...
    method WriteObjectEndBytes (line 201) | private void WriteObjectEndBytes(SerializationContext context)
    method WriteBytes (line 207) | public void WriteBytes(DateTime dateTime, SerializationContext context)
    method WriteBytes (line 230) | public void WriteBytes(XmlDocument xml, SerializationContext context)
    method WriteNullBytes (line 245) | public void WriteNullBytes(SerializationContext context)
    method WriteValueBytes (line 250) | public void WriteValueBytes(object value, SerializationContext context)
    method WriteBytes (line 263) | public void WriteBytes(List<object> value, SerializationContext context)
    method WriteBytes (line 302) | public void WriteBytes(Dictionary<string, object> value, Serialization...
    method WriteTypedBytes (line 340) | public void WriteTypedBytes(object value, SerializationContext context)
    method WriteBytes (line 384) | public void WriteBytes(AmfObject value, SerializationContext context)

FILE: Harmonic/Networking/Amf/Serialization/Amf0/SerializationContext.cs
  class SerializationContext (line 8) | public class SerializationContext : IDisposable
    method SerializationContext (line 17) | public SerializationContext()
    method SerializationContext (line 22) | public SerializationContext(ByteBuffer buffer)
    method GetMessage (line 28) | public void GetMessage(Span<byte> buffer)
    method Dispose (line 34) | public void Dispose()

FILE: Harmonic/Networking/Amf/Serialization/Amf3/Amf3Array.cs
  class Amf3Array (line 8) | public class Amf3Array

FILE: Harmonic/Networking/Amf/Serialization/Amf3/Amf3ClassTraits.cs
  type Amf3ClassType (line 8) | public enum Amf3ClassType
  class Amf3ClassTraits (line 15) | public class Amf3ClassTraits : IEquatable<Amf3ClassTraits>
    method Equals (line 22) | public override bool Equals(object obj)
    method Equals (line 32) | public bool Equals(Amf3ClassTraits traits)
    method GetHashCode (line 39) | public override int GetHashCode()

FILE: Harmonic/Networking/Amf/Serialization/Amf3/Amf3CommonValues.cs
  class Amf3CommonValues (line 12) | public static class Amf3CommonValues

FILE: Harmonic/Networking/Amf/Serialization/Amf3/Amf3Dictionary.cs
  class Amf3Dictionary (line 8) | public class Amf3Dictionary<TKey, TValue> : Dictionary<TKey, TValue>
    method Amf3Dictionary (line 12) | public Amf3Dictionary() : base() { }
    method Amf3Dictionary (line 14) | public Amf3Dictionary(IDictionary<TKey, TValue> dictionary) : base(dic...
    method Amf3Dictionary (line 16) | public Amf3Dictionary(IEnumerable<KeyValuePair<TKey, TValue>> collecti...
    method Amf3Dictionary (line 18) | public Amf3Dictionary(IEqualityComparer<TKey> comparer) : base(compare...
    method Amf3Dictionary (line 20) | public Amf3Dictionary(int capacity) : base(capacity) { }
    method Amf3Dictionary (line 22) | public Amf3Dictionary(IDictionary<TKey, TValue> dictionary, IEqualityC...
    method Amf3Dictionary (line 24) | public Amf3Dictionary(IEnumerable<KeyValuePair<TKey, TValue>> collecti...
    method Amf3Dictionary (line 26) | public Amf3Dictionary(int capacity, IEqualityComparer<TKey> comparer) ...
    method Amf3Dictionary (line 28) | protected Amf3Dictionary(SerializationInfo info, StreamingContext cont...

FILE: Harmonic/Networking/Amf/Serialization/Amf3/Amf3Reader.cs
  class Amf3Reader (line 16) | public class Amf3Reader
    method Amf3Reader (line 33) | public Amf3Reader()
    method ResetReference (line 82) | public void ResetReference()
    method ReaderHandlerWrapper (line 89) | private ReaderHandler ReaderHandlerWrapper<T>(ReaderHandler<T> handler)
    method RegisterTypedObject (line 105) | internal void RegisterTypedObject(string mappedName, TypeRegisterState...
    method RegisterTypedObject (line 110) | public void RegisterTypedObject<T>() where T: new()
    method RegisterExternalizable (line 137) | public void RegisterExternalizable<T>() where T : IExternalizable, new()
    method TryDescribeData (line 150) | public bool TryDescribeData(Span<byte> buffer, out Amf3Type type)
    method DataIsType (line 168) | public bool DataIsType(Span<byte> buffer, Amf3Type type)
    method TryGetUndefined (line 177) | public bool TryGetUndefined(Span<byte> buffer, out Undefined value, ou...
    method TryGetNull (line 191) | public bool TryGetNull(Span<byte> buffer, out object value, out int co...
    method TryGetTrue (line 205) | public bool TryGetTrue(Span<byte> buffer, out bool value, out int cons...
    method TryGetBoolean (line 219) | public bool TryGetBoolean(Span<byte> buffer, out bool value, out int c...
    method TryGetFalse (line 238) | public bool TryGetFalse(Span<byte> buffer, out bool value, out int con...
    method TryGetUInt29 (line 252) | public bool TryGetUInt29(Span<byte> buffer, out uint value, out int co...
    method TryGetU29Impl (line 273) | private bool TryGetU29Impl(Span<byte> dataBuffer, out uint value, out ...
    method TryGetDouble (line 324) | public bool TryGetDouble(Span<byte> buffer, out double value, out int ...
    method TryGetString (line 337) | public bool TryGetString(Span<byte> buffer, out string value, out int ...
    method TryGetStringImpl (line 353) | private bool TryGetStringImpl<T>(Span<byte> objectBuffer, List<T> refe...
    method TryGetXmlDocument (line 388) | public bool TryGetXmlDocument(Span<byte> buffer, out XmlDocument value...
    method TryGetDate (line 406) | public bool TryGetDate(Span<byte> buffer, out DateTime value, out int ...
    method TryGetArray (line 439) | public bool TryGetArray(Span<byte> buffer, out Amf3Array value, out in...
    method TryGetObject (line 514) | public bool TryGetObject(Span<byte> buffer, out object value, out int ...
    method TryGetXml (line 704) | public bool TryGetXml(Span<byte> buffer, out Amf3Xml value, out int co...
    method TryGetByteArray (line 723) | public bool TryGetByteArray(Span<byte> buffer, out byte[] value, out i...
    method TryGetValue (line 764) | public bool TryGetValue(Span<byte> buffer, out object value, out int c...
    method TryGetVectorInt (line 786) | public bool TryGetVectorInt(Span<byte> buffer, out Vector<int> value, ...
    method TryGetVectorUint (line 819) | public bool TryGetVectorUint(Span<byte> buffer, out Vector<uint> value...
    method TryGetVectorDouble (line 853) | public bool TryGetVectorDouble(Span<byte> buffer, out Vector<double> v...
    method TryGetIntVectorData (line 887) | private bool TryGetIntVectorData(ref Span<byte> buffer, Vector<int> ve...
    method TryGetUIntVectorData (line 897) | private bool TryGetUIntVectorData(ref Span<byte> buffer, Vector<uint> ...
    method TryGetDoubleVectorData (line 906) | private bool TryGetDoubleVectorData(ref Span<byte> buffer, Vector<doub...
    method TryGetReference (line 916) | private bool TryGetReference<T, TTableEle>(uint header, List<TTableEle...
    method ReadVectorHeader (line 943) | private bool ReadVectorHeader<T>(ref Span<byte> buffer, ref T value, r...
    method ReadVectorTypeName (line 980) | private bool ReadVectorTypeName(ref Span<byte> typeNameBuffer, out str...
    method TryGetVectorObject (line 992) | public bool TryGetVectorObject(Span<byte> buffer, out object value, ou...
    method TryGetDictionary (line 1067) | public bool TryGetDictionary(Span<byte> buffer, out Amf3Dictionary<obj...

FILE: Harmonic/Networking/Amf/Serialization/Amf3/Amf3Type.cs
  type Amf3Type (line 7) | public enum Amf3Type : byte

FILE: Harmonic/Networking/Amf/Serialization/Amf3/Amf3Writer.cs
  class Amf3Writer (line 19) | public class Amf3Writer
    method Amf3Writer (line 32) | public Amf3Writer()
    method WrapVector (line 68) | private void WrapVector(object value, SerializationContext context)
    method WrapDictionary (line 80) | private void WrapDictionary(object value, SerializationContext context)
    method WriteHandlerWrapper (line 93) | private WriteHandler WriteHandlerWrapper<T>(WriteHandler<T> handler)
    method XmlToString (line 109) | private string XmlToString(XmlDocument xml)
    method WriteBytes (line 120) | public void WriteBytes(Undefined value, SerializationContext context)
    method WriteBytes (line 125) | public void WriteBytes(bool value, SerializationContext context)
    method WriteU29BytesImpl (line 138) | private void WriteU29BytesImpl(uint value, SerializationContext context)
    method WriteBytes (line 198) | public void WriteBytes(uint value, SerializationContext context)
    method WriteBytes (line 204) | public void WriteBytes(double value, SerializationContext context)
    method WriteStringBytesImpl (line 221) | private void WriteStringBytesImpl<T>(string value, SerializationContex...
    method WriteBytes (line 260) | public void WriteBytes(string value, SerializationContext context)
    method WriteBytes (line 266) | public void WriteBytes(XmlDocument xml, SerializationContext context)
    method WriteBytes (line 274) | public void WriteBytes(DateTime dateTime, SerializationContext context)
    method WriteBytes (line 307) | public void WriteBytes(Amf3Xml xml, SerializationContext context)
    method WriteBytes (line 315) | public void WriteBytes(Memory<byte> value, SerializationContext context)
    method WriteValueBytes (line 334) | public void WriteValueBytes(object value, SerializationContext context)
    method WriteBytes (line 371) | public void WriteBytes(object value, SerializationContext context)
    method WriteBytes (line 496) | public void WriteBytes(Vector<uint> value, SerializationContext context)
    method WriteBytes (line 530) | public void WriteBytes(Vector<int> value, SerializationContext context)
    method WriteBytes (line 566) | public void WriteBytes(Vector<double> value, SerializationContext cont...
    method WriteBytes (line 601) | public void WriteBytes<T>(Vector<T> value, SerializationContext context)
    method WriteBytes (line 639) | public void WriteBytes(Amf3Array value, SerializationContext context)
    method WriteBytes (line 671) | public void WriteBytes<TKey, TValue>(Amf3Dictionary<TKey, TValue> valu...

FILE: Harmonic/Networking/Amf/Serialization/Amf3/Amf3Xml.cs
  class Amf3Xml (line 8) | public class Amf3Xml : XmlDocument
    method Amf3Xml (line 10) | public Amf3Xml() : base() { }
    method Amf3Xml (line 12) | public Amf3Xml(XmlNameTable nt) : base(nt) { }
    method Amf3Xml (line 14) | protected internal Amf3Xml(XmlImplementation imp) : base(imp) { }

FILE: Harmonic/Networking/Amf/Serialization/Amf3/SerializationContext.cs
  class SerializationContext (line 8) | public class SerializationContext : IDisposable
    method SerializationContext (line 18) | public SerializationContext()
    method SerializationContext (line 23) | public SerializationContext(ByteBuffer buffer)
    method Dispose (line 29) | public void Dispose()
    method GetMessage (line 37) | public void GetMessage(Span<byte> buffer)

FILE: Harmonic/Networking/Amf/Serialization/Amf3/Vector.cs
  class Vector (line 8) | public class Vector<T> : List<T>, IEquatable<List<T>>
    method Add (line 13) | public new void Add(T item)
    method Equals (line 22) | public override bool Equals(object obj)
    method Equals (line 31) | public bool Equals(List<T> other)
    method GetHashCode (line 36) | public override int GetHashCode()

FILE: Harmonic/Networking/Amf/Serialization/Attributes/ClassFieldAttribute.cs
  class ClassFieldAttribute (line 7) | [AttributeUsage(AttributeTargets.Property)]

FILE: Harmonic/Networking/Amf/Serialization/Attributes/TypedObjectAttribute.cs
  class TypedObjectAttribute (line 7) | [AttributeUsage(AttributeTargets.Class)]

FILE: Harmonic/Networking/ConnectionInformation.cs
  class ConnectionInformation (line 8) | public class ConnectionInformation

FILE: Harmonic/Networking/Flv/Data/AacPacketType.cs
  type AacPacketType (line 7) | public enum AacPacketType

FILE: Harmonic/Networking/Flv/Data/AudioData.cs
  class AudioData (line 7) | public class AudioData

FILE: Harmonic/Networking/Flv/Data/CodecId.cs
  type CodecId (line 7) | public enum CodecId

FILE: Harmonic/Networking/Flv/Data/FlvAudioData.cs
  class FlvAudioData (line 7) | public class FlvAudioData

FILE: Harmonic/Networking/Flv/Data/FlvVideoData.cs
  class FlvVideoData (line 7) | public class FlvVideoData

FILE: Harmonic/Networking/Flv/Data/FrameType.cs
  type FrameType (line 7) | public enum FrameType

FILE: Harmonic/Networking/Flv/Data/SoundFormat.cs
  type SoundFormat (line 7) | public enum SoundFormat

FILE: Harmonic/Networking/Flv/Data/SoundRate.cs
  type SoundRate (line 7) | public enum SoundRate

FILE: Harmonic/Networking/Flv/Data/SoundSize.cs
  type SoundSize (line 7) | public enum SoundSize

FILE: Harmonic/Networking/Flv/Data/SoundType.cs
  type SoundType (line 7) | public enum SoundType

FILE: Harmonic/Networking/Flv/FlvDemuxer.cs
  class FlvDemuxer (line 22) | public class FlvDemuxer
    method FlvDemuxer (line 30) | public FlvDemuxer(IReadOnlyDictionary<MessageType, MessageFactory> fac...
    method AttachStream (line 36) | public async Task<byte[]> AttachStream(Stream stream, bool disposeOld ...
    method SeekNoLock (line 48) | public void SeekNoLock(double milliseconds, Dictionary<string, object>...
    method ReadHeader (line 67) | private async Task<MessageHeader> ReadHeader(CancellationToken ct = de...
    method DemultiplexAudioData (line 105) | public FlvAudioData DemultiplexAudioData(AudioMessage message)
    method DemultiplexVideoData (line 128) | public FlvVideoData DemultiplexVideoData(VideoMessage message)
    method DemultiplexFlvAsync (line 138) | public async Task<Message> DemultiplexFlvAsync(CancellationToken ct = ...

FILE: Harmonic/Networking/Flv/FlvMuxer.cs
  class FlvMuxer (line 12) | public class FlvMuxer
    method MultiplexFlvHeader (line 17) | public byte[] MultiplexFlvHeader(bool hasAudio, bool hasVideo)
    method MultiplexFlv (line 36) | public byte[] MultiplexFlv(Message data)

FILE: Harmonic/Networking/Rtmp/ChunkStreamContext.cs
  class ChunkStreamContext (line 22) | class ChunkStreamContext : IDisposable
    method ChunkStreamContext (line 54) | public ChunkStreamContext(IOPipeLine stream)
    method Dispose (line 65) | public void Dispose()
    method MultiplexMessageAsync (line 70) | internal async Task MultiplexMessageAsync(uint chunkStreamId, Message ...
    method GenerateMesesageHeader (line 196) | private void GenerateMesesageHeader(ChunkHeaderType chunkHeaderType, M...
    method GenerateBasicHeader (line 237) | private void GenerateBasicHeader(ChunkHeaderType chunkHeaderType, uint...
    method SelectChunkType (line 267) | private ChunkHeaderType SelectChunkType(MessageHeader messageHeader, M...
    method FillHeader (line 303) | private void FillHeader(ChunkHeader header)
    method ProcessFirstByteBasicHeader (line 333) | public bool ProcessFirstByteBasicHeader(ReadOnlySequence<byte> buffer,...
    method ProcessChunkMessageHeader (line 365) | private bool ProcessChunkMessageHeader(ReadOnlySequence<byte> buffer, ...
    method ProcessExtendedTimestamp (line 455) | private bool ProcessExtendedTimestamp(ReadOnlySequence<byte> buffer, r...
    method ProcessCompleteMessage (line 471) | private bool ProcessCompleteMessage(ReadOnlySequence<byte> buffer, ref...

FILE: Harmonic/Networking/Rtmp/Data/ChunkBasicHeader.cs
  class ChunkBasicHeader (line 9) | class ChunkBasicHeader

FILE: Harmonic/Networking/Rtmp/Data/ChunkHeader.cs
  class ChunkHeader (line 8) | class ChunkHeader

FILE: Harmonic/Networking/Rtmp/Data/ChunkHeaderType.cs
  type ChunkHeaderType (line 7) | public enum ChunkHeaderType : byte

FILE: Harmonic/Networking/Rtmp/Data/Message.cs
  class Message (line 10) | public abstract class Message
    method Message (line 14) | internal Message()
    method Deserialize (line 18) | public abstract void Deserialize(SerializationContext context);
    method Serialize (line 19) | public abstract void Serialize(SerializationContext context);

FILE: Harmonic/Networking/Rtmp/Data/MessageHeader.cs
  class MessageHeader (line 7) | public class MessageHeader: ICloneable
    method Clone (line 14) | public object Clone()

FILE: Harmonic/Networking/Rtmp/Data/MessageType.cs
  type MessageType (line 7) | public enum MessageType : byte

FILE: Harmonic/Networking/Rtmp/Data/SharedObjectMessage.cs
  class SharedObjectMessage (line 8) | public class SharedObjectMessage

FILE: Harmonic/Networking/Rtmp/Data/UserControlMessageEvents.cs
  type UserControlMessageEvents (line 7) | public enum UserControlMessageEvents : UInt16

FILE: Harmonic/Networking/Rtmp/Exceptions/UnknownMessageReceivedException.cs
  class UnknownMessageReceivedException (line 8) | public class UnknownMessageReceivedException : Exception
    method UnknownMessageReceivedException (line 12) | public UnknownMessageReceivedException(MessageHeader header)

FILE: Harmonic/Networking/Rtmp/HandshakeContext.cs
  class HandshakeContext (line 13) | sealed class HandshakeContext : IDisposable
    method HandshakeContext (line 22) | public HandshakeContext(IOPipeLine ioPipeline)
    method Dispose (line 29) | public void Dispose()
    method ProcessHandshakeC0C1 (line 38) | private bool ProcessHandshakeC0C1(ReadOnlySequence<byte> buffer, ref i...
    method ProcessHandshakeC2 (line 90) | private bool ProcessHandshakeC2(ReadOnlySequence<byte> buffer, ref int...

FILE: Harmonic/Networking/Rtmp/IOPipeLine.cs
  type ProcessState (line 31) | enum ProcessState
  class IOPipeLine (line 42) | class IOPipeLine : IDisposable
    method IOPipeLine (line 60) | public IOPipeLine(Socket socket, RtmpServerOptions options, int resume...
    method StartAsync (line 70) | public Task StartAsync(CancellationToken ct = default)
    method OnHandshakeSuccessful (line 118) | internal void OnHandshakeSuccessful()
    method SendRawData (line 127) | internal async Task SendRawData(ReadOnlyMemory<byte> data)
    method Writer (line 143) | private async Task Writer(CancellationToken ct)
    method Producer (line 166) | private async Task Producer(Socket s, PipeWriter writer, CancellationT...
    method Consumer (line 187) | private async Task Consumer(PipeReader reader, CancellationToken ct = ...
    method Disconnect (line 227) | internal void Disconnect()
    method Dispose (line 239) | protected virtual void Dispose(bool disposing)
    method Dispose (line 261) | public void Dispose()

FILE: Harmonic/Networking/Rtmp/MessageReadingState.cs
  class MessageReadingState (line 7) | class MessageReadingState

FILE: Harmonic/Networking/Rtmp/Messages/AbortMessage.cs
  class AbortMessage (line 11) | [RtmpMessage(MessageType.AbortMessage)]
    method AbortMessage (line 16) | public AbortMessage() : base()
    method Deserialize (line 20) | public override void Deserialize(SerializationContext context)
    method Serialize (line 25) | public override void Serialize(SerializationContext context)

FILE: Harmonic/Networking/Rtmp/Messages/AcknowledgementMessage.cs
  class AcknowledgementMessage (line 11) | [RtmpMessage(MessageType.Acknowledgement)]
    method AcknowledgementMessage (line 16) | public AcknowledgementMessage() : base()
    method Deserialize (line 20) | public override void Deserialize(SerializationContext context)
    method Serialize (line 25) | public override void Serialize(SerializationContext context)

FILE: Harmonic/Networking/Rtmp/Messages/AggregateMessage.cs
  class MessageData (line 12) | internal class MessageData
  class AggregateMessage (line 19) | [RtmpMessage(MessageType.AggregateMessage)]
    method AggregateMessage (line 25) | public AggregateMessage() : base()
    method DeserializeMessage (line 29) | private MessageData DeserializeMessage(Span<byte> buffer, out int cons...
    method Deserialize (line 59) | public override void Deserialize(SerializationContext context)
    method Serialize (line 69) | public override void Serialize(SerializationContext context)

FILE: Harmonic/Networking/Rtmp/Messages/AmfEncodingVersion.cs
  type AmfEncodingVersion (line 7) | public enum AmfEncodingVersion

FILE: Harmonic/Networking/Rtmp/Messages/AudioMessage.cs
  class AudioMessage (line 10) | [RtmpMessage(MessageType.AudioMessage)]
    method Clone (line 14) | public object Clone()
    method Deserialize (line 25) | public override void Deserialize(SerializationContext context)
    method Serialize (line 33) | public override void Serialize(SerializationContext context)

FILE: Harmonic/Networking/Rtmp/Messages/Commands/CallCommandMessage.cs
  class CallCommandMessage (line 14) | public abstract class CallCommandMessage : CommandMessage
    method CallCommandMessage (line 16) | public CallCommandMessage(AmfEncodingVersion encoding) : base(encoding)

FILE: Harmonic/Networking/Rtmp/Messages/Commands/CommandMessage.cs
  class CommandMessage (line 16) | [RtmpMessage(MessageType.Amf3Command, MessageType.Amf0Command)]
    method CommandMessage (line 24) | public CommandMessage(AmfEncodingVersion encoding) : base()
    method DeserializeAmf0 (line 30) | public void DeserializeAmf0(SerializationContext context)
    method DeserializeAmf3 (line 60) | public void DeserializeAmf3(SerializationContext context)
    method SerializeAmf0 (line 81) | public void SerializeAmf0(SerializationContext context)
    method SerializeAmf3 (line 101) | public void SerializeAmf3(SerializationContext context)
    method Deserialize (line 121) | public sealed override void Deserialize(SerializationContext context)
    method Serialize (line 133) | public sealed override void Serialize(SerializationContext context)

FILE: Harmonic/Networking/Rtmp/Messages/Commands/CommandMessageFactory.cs
  class CommandMessageFactory (line 14) | public class CommandMessageFactory
    method CommandMessageFactory (line 18) | public CommandMessageFactory()
    method RegisterMessage (line 34) | public void RegisterMessage<T>() where T: CommandMessage
    method Provide (line 45) | public Message Provide(MessageHeader header, SerializationContext cont...

FILE: Harmonic/Networking/Rtmp/Messages/Commands/ConnectCommandMessage.cs
  class ConnectCommandMessage (line 9) | [RtmpCommand(Name = "connect")]
    method ConnectCommandMessage (line 15) | public ConnectCommandMessage(AmfEncodingVersion encoding) : base(encod...

FILE: Harmonic/Networking/Rtmp/Messages/Commands/CreateStreamCommandMessage.cs
  class CreateStreamCommandMessage (line 9) | [RtmpCommand(Name = "createStream")]
    method CreateStreamCommandMessage (line 12) | public CreateStreamCommandMessage(AmfEncodingVersion encoding) : base(...

FILE: Harmonic/Networking/Rtmp/Messages/Commands/DeleteStreamCommandMessage.cs
  class DeleteStreamCommandMessage (line 9) | [RtmpCommand(Name = "deleteStream")]
    method DeleteStreamCommandMessage (line 15) | public DeleteStreamCommandMessage(AmfEncodingVersion encoding) : base(...

FILE: Harmonic/Networking/Rtmp/Messages/Commands/OnStatusCommandMessage.cs
  class OnStatusCommandMessage (line 10) | [RtmpCommand(Name = "onStatus")]
    method OnStatusCommandMessage (line 16) | public OnStatusCommandMessage(AmfEncodingVersion encoding) : base(enco...

FILE: Harmonic/Networking/Rtmp/Messages/Commands/PauseCommandMessage.cs
  class PauseCommandMessage (line 9) | [RtmpCommand(Name = "pause")]
    method PauseCommandMessage (line 17) | public PauseCommandMessage(AmfEncodingVersion encoding) : base(encoding)

FILE: Harmonic/Networking/Rtmp/Messages/Commands/Play2CommandMessage.cs
  class Play2CommandMessage (line 9) | [RtmpCommand(Name = "play2")]
    method Play2CommandMessage (line 15) | public Play2CommandMessage(AmfEncodingVersion encoding) : base(encoding)

FILE: Harmonic/Networking/Rtmp/Messages/Commands/PlayCommandMessage.cs
  class PlayCommandMessage (line 9) | [RtmpCommand(Name = "play")]
    method PlayCommandMessage (line 22) | public PlayCommandMessage(AmfEncodingVersion encoding) : base(encoding)

FILE: Harmonic/Networking/Rtmp/Messages/Commands/PublishCommandMessage.cs
  class PublishCommandMessage (line 9) | [RtmpCommand(Name = "publish")]
    method PublishCommandMessage (line 17) | public PublishCommandMessage(AmfEncodingVersion encoding) : base(encod...

FILE: Harmonic/Networking/Rtmp/Messages/Commands/ReceiveAudioCommandMessage.cs
  class ReceiveAudioCommandMessage (line 9) | [RtmpCommand(Name = "receiveAudio")]
    method ReceiveAudioCommandMessage (line 15) | public ReceiveAudioCommandMessage(AmfEncodingVersion encoding) : base(...

FILE: Harmonic/Networking/Rtmp/Messages/Commands/ReceiveVideoCommandMessage.cs
  class ReceiveVideoCommandMessage (line 9) | [RtmpCommand(Name = "receiveVideo")]
    method ReceiveVideoCommandMessage (line 15) | public ReceiveVideoCommandMessage(AmfEncodingVersion encoding) : base(...

FILE: Harmonic/Networking/Rtmp/Messages/Commands/ReturnResultCommandMessage.cs
  class ReturnResultCommandMessage (line 14) | public class ReturnResultCommandMessage : CallCommandMessage
    method ReturnResultCommandMessage (line 39) | public ReturnResultCommandMessage(AmfEncodingVersion encoding) : base(...

FILE: Harmonic/Networking/Rtmp/Messages/Commands/SeekCommandMessage.cs
  class SeekCommandMessage (line 9) | [RtmpCommand(Name = "seek")]
    method SeekCommandMessage (line 15) | public SeekCommandMessage(AmfEncodingVersion encoding) : base(encoding)

FILE: Harmonic/Networking/Rtmp/Messages/ControlMessage.cs
  class ControlMessage (line 8) | public abstract class ControlMessage : Message
    method ControlMessage (line 10) | internal ControlMessage() : base()

FILE: Harmonic/Networking/Rtmp/Messages/DataMessage.cs
  class DataMessage (line 11) | [RtmpMessage(MessageType.Amf0Data, MessageType.Amf3Data)]
    method DataMessage (line 15) | public DataMessage(AmfEncodingVersion encoding) : base()
    method Deserialize (line 20) | public override void Deserialize(SerializationContext context)
    method Serialize (line 52) | public override void Serialize(SerializationContext context)

FILE: Harmonic/Networking/Rtmp/Messages/SetChunkSizeMessage.cs
  class SetChunkSizeMessage (line 11) | [RtmpMessage(MessageType.SetChunkSize)]
    method SetChunkSizeMessage (line 16) | public SetChunkSizeMessage() : base()
    method Deserialize (line 21) | public override void Deserialize(SerializationContext context)
    method Serialize (line 27) | public override void Serialize(SerializationContext context)

FILE: Harmonic/Networking/Rtmp/Messages/SetPeerBandwidthMessage.cs
  type LimitType (line 11) | public enum LimitType : byte
  class SetPeerBandwidthMessage (line 18) | [RtmpMessage(MessageType.SetPeerBandwidth)]
    method SetPeerBandwidthMessage (line 24) | public SetPeerBandwidthMessage() : base()
    method Deserialize (line 28) | public override void Deserialize(SerializationContext context)
    method Serialize (line 34) | public override void Serialize(SerializationContext context)

FILE: Harmonic/Networking/Rtmp/Messages/UserControlMessages/PingRequestMessage.cs
  class PingRequestMessage (line 11) | [UserControlMessage(Type = UserControlEventType.PingRequest)]
    method PingRequestMessage (line 16) | public PingRequestMessage() : base()
    method Deserialize (line 21) | public override void Deserialize(SerializationContext context)
    method Serialize (line 30) | public override void Serialize(SerializationContext context)

FILE: Harmonic/Networking/Rtmp/Messages/UserControlMessages/PingResponseMessage.cs
  class PingResponseMessage (line 11) | [UserControlMessage(Type = UserControlEventType.PingResponse)]
    method PingResponseMessage (line 16) | public PingResponseMessage()
    method Deserialize (line 21) | public override void Deserialize(SerializationContext context)
    method Serialize (line 30) | public override void Serialize(SerializationContext context)

FILE: Harmonic/Networking/Rtmp/Messages/UserControlMessages/SetBufferLengthMessage.cs
  class SetBufferLengthMessage (line 11) | [UserControlMessage(Type = UserControlEventType.SetBufferLength)]
    method SetBufferLengthMessage (line 17) | public SetBufferLengthMessage()
    method Deserialize (line 22) | public override void Deserialize(SerializationContext context)
    method Serialize (line 33) | public override void Serialize(SerializationContext context)

FILE: Harmonic/Networking/Rtmp/Messages/UserControlMessages/StreamBeginMessage.cs
  class StreamBeginMessage (line 11) | [UserControlMessage(Type = UserControlEventType.StreamBegin)]
    method StreamBeginMessage (line 16) | public StreamBeginMessage()
    method Deserialize (line 21) | public override void Deserialize(SerializationContext context)
    method Serialize (line 30) | public override void Serialize(SerializationContext context)

FILE: Harmonic/Networking/Rtmp/Messages/UserControlMessages/StreamDryMessage.cs
  class StreamDryMessage (line 11) | [UserControlMessage(Type = UserControlEventType.StreamDry)]
    method StreamDryMessage (line 16) | public StreamDryMessage()
    method Deserialize (line 21) | public override void Deserialize(SerializationContext context)
    method Serialize (line 30) | public override void Serialize(SerializationContext context)

FILE: Harmonic/Networking/Rtmp/Messages/UserControlMessages/StreamEofMessage.cs
  class StreamEofMessage (line 11) | [UserControlMessage(Type = UserControlEventType.StreamEof)]
    method StreamEofMessage (line 16) | public StreamEofMessage() : base()
    method Deserialize (line 21) | public override void Deserialize(SerializationContext context)
    method Serialize (line 30) | public override void Serialize(SerializationContext context)

FILE: Harmonic/Networking/Rtmp/Messages/UserControlMessages/StreamIsRecordedMessage.cs
  class StreamIsRecordedMessage (line 11) | [UserControlMessage(Type = UserControlEventType.StreamIsRecorded)]
    method StreamIsRecordedMessage (line 16) | public StreamIsRecordedMessage() : base()
    method Deserialize (line 21) | public override void Deserialize(SerializationContext context)
    method Serialize (line 30) | public override void Serialize(SerializationContext context)

FILE: Harmonic/Networking/Rtmp/Messages/UserControlMessages/UserControlMessage.cs
  type UserControlEventType (line 11) | public enum UserControlEventType : ushort
  class UserControlMessage (line 22) | [RtmpMessage(MessageType.UserControlMessages)]
    method UserControlMessage (line 27) | public UserControlMessage() : base()

FILE: Harmonic/Networking/Rtmp/Messages/UserControlMessages/UserControlMessageFactory.cs
  class UserControlMessageFactory (line 11) | public class UserControlMessageFactory
    method RegisterMessage (line 15) | public void RegisterMessage<T>() where T: UserControlMessage, new()
    method Provide (line 26) | public Message Provide(MessageHeader header, SerializationContext cont...

FILE: Harmonic/Networking/Rtmp/Messages/VideoMessage.cs
  class VideoMessage (line 11) | [RtmpMessage(MessageType.VideoMessage)]
    method Clone (line 16) | public object Clone()
    method Deserialize (line 27) | public override void Deserialize(SerializationContext context)
    method Serialize (line 35) | public override void Serialize(SerializationContext context)

FILE: Harmonic/Networking/Rtmp/Messages/WindowAcknowledgementSizeMessage.cs
  class WindowAcknowledgementSizeMessage (line 11) | [RtmpMessage(MessageType.WindowAcknowledgementSize)]
    method WindowAcknowledgementSizeMessage (line 16) | public WindowAcknowledgementSizeMessage() : base()
    method Deserialize (line 20) | public override void Deserialize(SerializationContext context)
    method Serialize (line 25) | public override void Serialize(SerializationContext context)

FILE: Harmonic/Networking/Rtmp/NetConnection.cs
  class NetConnection (line 18) | public class NetConnection : IDisposable
    method NetConnection (line 49) | internal NetConnection(RtmpSession rtmpSession)
    method CommandHandler (line 57) | private void CommandHandler(CommandMessage command)
    method Connect (line 79) | public void Connect(CommandMessage command)
    method Close (line 128) | public void Close()
    method MessageStreamDestroying (line 133) | internal void MessageStreamDestroying(NetStream stream)
    method AddMessageStream (line 142) | internal void AddMessageStream(uint id, NetStream stream)
    method RemoveMessageStream (line 150) | internal void RemoveMessageStream(uint id)
    method Dispose (line 162) | protected virtual void Dispose(bool disposing)
    method Dispose (line 191) | public void Dispose()

FILE: Harmonic/Networking/Rtmp/NetStream.cs
  class NetStream (line 10) | public abstract class NetStream : RtmpController, IDisposable
    method DeleteStream (line 12) | [RpcMethod("deleteStream")]
    method Dispose (line 21) | protected virtual void Dispose(bool disposing)
    method Dispose (line 38) | public void Dispose()

FILE: Harmonic/Networking/Rtmp/RtmpChunkStream.cs
  class RtmpChunkStream (line 9) | public class RtmpChunkStream : IDisposable
    method RtmpChunkStream (line 14) | internal RtmpChunkStream(RtmpSession rtmpSession, uint chunkStreamId)
    method RtmpChunkStream (line 20) | internal RtmpChunkStream(RtmpSession rtmpSession)
    method RtmpChunkStream (line 26) | protected RtmpChunkStream()
    method Dispose (line 34) | protected virtual void Dispose(bool disposing)
    method Dispose (line 51) | public void Dispose()

FILE: Harmonic/Networking/Rtmp/RtmpControlChunkStream.cs
  class RtmpControlChunkStream (line 10) | class RtmpControlChunkStream : RtmpChunkStream
    method RtmpControlChunkStream (line 14) | internal RtmpControlChunkStream(RtmpSession rtmpSession) : base()

FILE: Harmonic/Networking/Rtmp/RtmpControlMessageStream.cs
  class RtmpControlMessageStream (line 10) | public class RtmpControlMessageStream : RtmpMessageStream
    method RtmpControlMessageStream (line 14) | internal RtmpControlMessageStream(RtmpSession rtmpSession) : base(rtmp...

FILE: Harmonic/Networking/Rtmp/RtmpMessageStream.cs
  class RtmpMessageStream (line 13) | public class RtmpMessageStream : IDisposable
    method RtmpMessageStream (line 19) | internal RtmpMessageStream(RtmpSession rtmpSession, uint messageStreamId)
    method RtmpMessageStream (line 25) | internal RtmpMessageStream(RtmpSession rtmpSession)
    method AttachMessage (line 31) | private void AttachMessage(Message message)
    method SendMessageAsync (line 36) | public virtual Task SendMessageAsync(RtmpChunkStream chunkStream, Mess...
    method RegisterMessageHandler (line 42) | internal void RegisterMessageHandler<T>(Action<T> handler) where T: Me...
    method RemoveMessageHandler (line 62) | protected void RemoveMessageHandler(MessageType messageType)
    method MessageArrived (line 67) | internal void MessageArrived(Message message)
    method Dispose (line 78) | protected virtual void Dispose(bool disposing)
    method Dispose (line 95) | public void Dispose()

FILE: Harmonic/Networking/Rtmp/RtmpSession.cs
  class RtmpSession (line 20) | public class RtmpSession : IDisposable
    method RtmpSession (line 33) | internal RtmpSession(IOPipeLine ioPipeline)
    method HandleAcknowledgement (line 47) | private void HandleAcknowledgement(AcknowledgementMessage ack)
    method AssertStreamId (line 52) | internal void AssertStreamId(uint msid)
    method MakeUniqueMessageStreamId (line 56) | internal uint MakeUniqueMessageStreamId()
    method MakeUniqueChunkStreamId (line 62) | internal uint MakeUniqueChunkStreamId()
    method CreateNetStream (line 87) | public T CreateNetStream<T>() where T: NetStream
    method DeleteNetStream (line 98) | public void DeleteNetStream(uint id)
    method CreateCommandMessage (line 110) | public T CreateCommandMessage<T>() where T: CommandMessage
    method CreateData (line 116) | public T CreateData<T>() where T : DataMessage
    method CommandHandler (line 122) | internal void CommandHandler(RtmpController controller, CommandMessage...
    method FindController (line 194) | internal bool FindController(string appName, out Type controllerType)
    method Close (line 199) | public void Close()
    method CreateMessageStream (line 204) | private RtmpMessageStream CreateMessageStream()
    method CreateChunkStream (line 211) | public RtmpChunkStream CreateChunkStream()
    method ChunkStreamDestroyed (line 216) | internal void ChunkStreamDestroyed(RtmpChunkStream rtmpChunkStream)
    method SendMessageAsync (line 224) | internal Task SendMessageAsync(uint chunkStreamId, Message message)
    method MessageStreamCreated (line 229) | internal void MessageStreamCreated(RtmpMessageStream messageStream)
    method MessageStreamDestroying (line 234) | internal void MessageStreamDestroying(RtmpMessageStream messageStream)
    method MessageArrived (line 239) | internal void MessageArrived(Message message)
    method Acknowledgement (line 251) | internal void Acknowledgement(uint bytesReceived)
    method HandleSetPeerBandwidth (line 259) | private void HandleSetPeerBandwidth(SetPeerBandwidthMessage message)
    method HandleWindowAcknowledgementSize (line 277) | private void HandleWindowAcknowledgementSize(WindowAcknowledgementSize...
    method HandleSetChunkSize (line 282) | private void HandleSetChunkSize(SetChunkSizeMessage setChunkSize)
    method SendControlMessageAsync (line 287) | public Task SendControlMessageAsync(Message message)
    method Dispose (line 299) | protected virtual void Dispose(bool disposing)
    method Dispose (line 318) | public void Dispose()

FILE: Harmonic/Networking/Rtmp/Serialization/OptionalArgumentAttribute.cs
  class OptionalArgumentAttribute (line 7) | [AttributeUsage(AttributeTargets.Property)]

FILE: Harmonic/Networking/Rtmp/Serialization/RtmpCommandAttribute.cs
  class RtmpCommandAttribute (line 7) | [AttributeUsage(AttributeTargets.Class)]

FILE: Harmonic/Networking/Rtmp/Serialization/RtmpMessageAttribute.cs
  class RtmpMessageAttribute (line 9) | [AttributeUsage(AttributeTargets.Class)]
    method RtmpMessageAttribute (line 12) | public RtmpMessageAttribute(params MessageType[] messageTypes)

FILE: Harmonic/Networking/Rtmp/Serialization/SerializationContext.cs
  class SerializationContext (line 10) | public class SerializationContext

FILE: Harmonic/Networking/Rtmp/Serialization/UserControlMessageAttribute.cs
  class UserControlMessageAttribute (line 8) | public class UserControlMessageAttribute : Attribute

FILE: Harmonic/Networking/Rtmp/Streaming/PublishingType.cs
  type PublishingType (line 7) | public enum PublishingType

FILE: Harmonic/Networking/Rtmp/Streaming/PublishingTypeNameAttribute.cs
  class PublishingTypeNameAttribute (line 9) | [AttributeUsage(AttributeTargets.Field)]
    method PublishingTypeNameAttribute (line 14) | public PublishingTypeNameAttribute(string name)
  class PublishingHelpers (line 20) | public static class PublishingHelpers
    method PublishingHelpers (line 24) | static PublishingHelpers()
    method IsTypeSupported (line 39) | public static bool IsTypeSupported(string type)

FILE: Harmonic/Networking/Rtmp/Supervisor.cs
  class Supervisor (line 10) | public class Supervisor
    class SessionState (line 12) | class SessionState
    method Supervisor (line 25) | public Supervisor(RtmpServer server)
    method StartAsync (line 29) | public void StartAsync(TimeSpan pingInterval, TimeSpan responseThresho...
    method ThreadEntry (line 41) | private void ThreadEntry()

FILE: Harmonic/Networking/Rtmp/WriteState.cs
  class WriteState (line 8) | class WriteState

FILE: Harmonic/Networking/Utils/NetworkBitConverter.cs
  class NetworkBitConverter (line 11) | public static class NetworkBitConverter
    method ToInt32 (line 15) | public static int ToInt32(Span<byte> buffer, bool littleEndian = false)
    method ToUInt32 (line 24) | public static uint ToUInt32(Span<byte> buffer, bool littleEndian = false)
    method ToUInt64 (line 32) | public static ulong ToUInt64(Span<byte> buffer, bool littleEndian = fa...
    method ToUInt16 (line 40) | public static ushort ToUInt16(Span<byte> buffer, bool littleEndian = f...
    method ToUInt24 (line 48) | public static uint ToUInt24(ReadOnlySpan<byte> buffer, bool littleEndi...
    method ToDouble (line 63) | public static double ToDouble(Span<byte> buffer, bool littleEndian = f...
    method TryGetUInt24Bytes (line 72) | public static bool TryGetUInt24Bytes(uint value, Span<byte> buffer, bo...
    method TryGetBytes (line 95) | public static bool TryGetBytes(int value, Span<byte> buffer, bool litt...
    method TryGetBytes (line 109) | public static bool TryGetBytes(double value, Span<byte> buffer, bool l...
    method TryGetBytes (line 123) | public static bool TryGetBytes(uint value, Span<byte> buffer, bool lit...
    method TryGetBytes (line 137) | public static bool TryGetBytes(byte value, Span<byte> buffer)
    method TryGetBytes (line 147) | public static bool TryGetBytes(ushort value, Span<byte> buffer, bool l...
    method TryGetBytes (line 161) | public static bool TryGetBytes(ulong value, Span<byte> buffer, bool li...

FILE: Harmonic/Networking/Utils/StreamHelper.cs
  class StreamHelper (line 9) | static class StreamHelper
    method ReadBytes (line 11) | public static byte[] ReadBytes(this Stream stream, int count)
    method ReadBytesAsync (line 35) | public static async Task ReadBytesAsync(this Stream stream, Memory<byt...

FILE: Harmonic/Networking/WebSocket/WebSocketSession.cs
  class WebSocketSession (line 23) | public class WebSocketSession
    method WebSocketSession (line 31) | public WebSocketSession(IWebSocketConnection connection, WebSocketOpti...
    method SendRawDataAsync (line 38) | public Task SendRawDataAsync(byte[] data)
    method Close (line 43) | public void Close()
    method SendString (line 48) | public void SendString(string str)
    method HandleOpen (line 53) | internal void HandleOpen()
    method SendFlvHeaderAsync (line 86) | public Task SendFlvHeaderAsync(bool hasAudio, bool hasVideo)
    method SendMessageAsync (line 91) | public Task SendMessageAsync(Message data)
    method HandleClose (line 96) | internal void HandleClose()
    method HandleMessage (line 105) | internal void HandleMessage(string msg)

FILE: Harmonic/Rpc/CommandObjectAttribute.cs
  class CommandObjectAttribute (line 7) | [AttributeUsage(AttributeTargets.Parameter)]

FILE: Harmonic/Rpc/FromCommandObjectAttribute.cs
  class FromCommandObjectAttribute (line 5) | [AttributeUsage(AttributeTargets.Parameter)]
    method FromCommandObjectAttribute (line 8) | public FromCommandObjectAttribute(string key = null)

FILE: Harmonic/Rpc/FromOptionalArgumentAttribute.cs
  class FromOptionalArgumentAttribute (line 7) | [AttributeUsage(AttributeTargets.Parameter)]

FILE: Harmonic/Rpc/RpcMethodAttribute.cs
  class RpcMethodAttribute (line 5) | public class RpcMethodAttribute : Attribute
    method RpcMethodAttribute (line 8) | public RpcMethodAttribute(string name = null)

FILE: Harmonic/Rpc/RpcService.cs
  class RpcParameter (line 14) | internal class RpcParameter
  class RpcMethod (line 25) | internal class RpcMethod
  class RpcService (line 33) | internal class RpcService
    method PrepareMethod (line 37) | public void PrepareMethod<T>(T instance, CommandMessage command, out M...
    method CleanupRegistration (line 127) | internal void CleanupRegistration()
    method RegeisterController (line 146) | internal void RegeisterController(Type controllerType)

FILE: Harmonic/Service/PublisherSessionService.cs
  class PublisherSessionService (line 9) | public class PublisherSessionService
    method RegisterPublisher (line 14) | internal void RegisterPublisher(string publishingName, LivingStream se...
    method RemovePublisher (line 28) | internal void RemovePublisher(LivingStream session)
    method FindPublisher (line 36) | public LivingStream FindPublisher(string publishingName)

FILE: Harmonic/Service/RecordService.cs
  class RecordService (line 8) | public class RecordService
    method RecordService (line 12) | public RecordService(RecordServiceConfiguration configuration)
    method GetRecordFilename (line 17) | public string GetRecordFilename(string streamName)

FILE: Harmonic/Service/RecordServiceConfiguration.cs
  class RecordServiceConfiguration (line 7) | public class RecordServiceConfiguration

FILE: UnitTest/TestAmf0Reader.cs
  class TestAmf0Reader (line 13) | [TestClass]
    method TestReadNumber (line 16) | [TestMethod]
    method TestReadString (line 37) | [TestMethod]
    method TestReadBoolean (line 58) | [TestMethod]
    method TestReadArray (line 79) | [TestMethod]
    method TestReadDate (line 96) | [TestMethod]
    method TestReadLongString (line 115) | [TestMethod]
    method TestReadNull (line 132) | [TestMethod]
    method TestReadNull2 (line 149) | [TestMethod]
    method TestReadXml (line 166) | [TestMethod]
    method TestReadUndefined (line 185) | [TestMethod]
    method TestReadEcmaArray (line 201) | [TestMethod]
    method TestReadObject (line 221) | [TestMethod]
    method TestPacket (line 241) | [TestMethod]

FILE: UnitTest/TestAmf0Writer.cs
  class TestAmf0Writer (line 16) | [TestClass]
    method TestNumber (line 19) | [TestMethod]
    method TestString (line 41) | [TestMethod]
    method TestLongString (line 62) | [TestMethod]
    method TestDate (line 85) | [TestMethod]
    method TestBoolean (line 110) | [TestMethod]
    method TestArray (line 137) | [TestMethod]
    method TestEcmaArray (line 169) | [TestMethod]
    method TestNull (line 200) | [TestMethod]
    method TestUndefined (line 219) | [TestMethod]
    method TestXml (line 238) | [TestMethod]
    method TestObject (line 261) | [TestMethod]
    class TypedClass (line 295) | [TypedObject(Name = "Another.Name")]
      method AddDynamic (line 317) | public void AddDynamic(string key, object data)
    method TestTypedObject (line 323) | [TestMethod]

FILE: UnitTest/TestAmf3Reader.cs
  class TestCls (line 18) | [TypedObject(Name = "TestClass")]
    method AddDynamic (line 34) | public void AddDynamic(string key, object data)
    method Equals (line 39) | public bool Equals(TestCls other)
    method Equals (line 44) | public override bool Equals(object obj)
  class iexternalizable (line 54) | public class iexternalizable : IExternalizable
    method TryEncodeData (line 59) | public bool TryEncodeData(ByteBuffer buffer)
    method TryDecodeData (line 68) | public bool TryDecodeData(Span<byte> buffer, out int consumed)
  class RemotingMessage (line 77) | [TypedObject(Name = "flex.messaging.messages.RemotingMessage")]
    method AddDynamic (line 103) | public void AddDynamic(string key, object data)
  class TestAmf3Reader (line 109) | [TestClass]
    method TestReadNumber (line 112) | [TestMethod]
    method TestReadInteger (line 133) | [TestMethod]
    method TestReadString (line 154) | [TestMethod]
    method TestReadBoolean (line 175) | [TestMethod]
    method TestReadPacket1 (line 196) | [TestMethod]
    method TestUndefined (line 212) | [TestMethod]
    method TestNull (line 227) | [TestMethod]
    method TestDate (line 242) | [TestMethod]
    method TestReadObject (line 260) | [TestMethod]
    method TestReadXml (line 311) | [TestMethod]
    method TestReadXmlDocument (line 330) | [TestMethod]
    method TestReadArray (line 351) | [TestMethod]
    method TestReadDictionary (line 375) | [TestMethod]
    method TestReadVectorInt (line 416) | [TestMethod]
    method TestReadVectorUint (line 436) | [TestMethod]
    method TestReadVectorDouble (line 456) | [TestMethod]
    method TestReadVectorTyped (line 477) | [TestMethod]
    method TestReadVectorAny (line 511) | [TestMethod]
    method TestReadByteArray (line 535) | [TestMethod]
    method TestReadExternalizable (line 555) | [TestMethod]

FILE: UnitTest/TestAmf3Writer.cs
  class TestAmf3Writer (line 17) | [TestClass]
    method TestDouble (line 20) | [TestMethod]
    method TestInteger (line 43) | [TestMethod]
    method TestBoolean (line 66) | [TestMethod]
    method TestNull (line 89) | [TestMethod]
    method TestUndefined (line 109) | [TestMethod]
    method TestArray (line 128) | [TestMethod]
    method TestByteArray (line 159) | [TestMethod]
    method TestDate (line 180) | [TestMethod]
    method TestDictionary (line 205) | [TestMethod]
    method TestIExternalizable (line 230) | [TestMethod]
    class TestCls2 (line 260) | public class TestCls2: IEquatable<TestCls2>
      method Equals (line 265) | public bool Equals(TestCls2 other)
      method Equals (line 270) | public override bool Equals(object obj)
      method GetHashCode (line 279) | public override int GetHashCode()
    method TestObject (line 285) | [TestMethod]
    method TestObject2 (line 313) | [TestMethod]
    method TestObject3 (line 337) | [TestMethod]
    method TestXmlDocument (line 364) | [TestMethod]
    method TestXml (line 387) | [TestMethod]
    method TestVectorUint (line 411) | [TestMethod]
    method TestVectorInt (line 431) | [TestMethod]
    method TestVectorDouble (line 451) | [TestMethod]
    method TestVectorTypedObject (line 471) | [TestMethod]
    method TestVectorAnyObject (line 503) | [TestMethod]
    method TestString (line 535) | [TestMethod]

FILE: UnitTest/TestUnlimitedBuffer.cs
  class TestUnlimitedBuffer (line 11) | [TestClass]
    method TestBufferSegmentSize (line 14) | [TestMethod]
    method TestBufferLengthDifferentBufferSegmentSize (line 46) | [TestMethod]
    method TestBufferLength (line 68) | [TestMethod]
    method TestWriteToBuffer4DifferentBufferSegmentSize (line 90) | [TestMethod]
    method TestWriteToBuffer5DifferentBufferSegmentSize (line 111) | [TestMethod]
    method TestParalleWriteAndRead (line 143) | [TestMethod]
    method TestAsyncWriteAndRead (line 193) | [TestMethod]
    method TestWriteToBuffer3DifferentBufferSegmentSize (line 241) | [TestMethod]
    method TestWriteToBuffer4 (line 262) | [TestMethod]
    method TestWriteToBuffer3 (line 280) | [TestMethod]
    method TestWriteToBuffer1DifferentBufferSegmentSize (line 298) | [TestMethod]
    method TestWriteToBuffer1 (line 320) | [TestMethod]
    method TestWriteToBuffer2 (line 339) | [TestMethod]
    method TestClearAndCopyToDifferentBufferSegmentSize (line 363) | [TestMethod]
    method TestClearAndCopyTo (line 380) | [TestMethod]

FILE: demo/MyLivingController.cs
  class MyLivingController (line 10) | [NeverRegister]
    method CreateStream (line 13) | [RpcMethod("createStream")]

FILE: demo/MyLivingStream.cs
  class MyLivingStream (line 12) | [NeverRegister]
    method MyLivingStream (line 15) | public MyLivingStream(PublisherSessionService publisherSessionService)...
    method Play (line 19) | [RpcMethod("play")]

FILE: demo/Program.cs
  class Program (line 7) | class Program
    method Main (line 9) | static void Main(string[] args)

FILE: demo/StartUp.cs
  class Startup (line 9) | class Startup : IStartup
    method ConfigureServices (line 11) | public void ConfigureServices(ContainerBuilder builder)
Condensed preview — 226 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (468K chars).
[
  {
    "path": ".github/workflows/dotnetcore.yml",
    "chars": 452,
    "preview": "name: .NET Core\n\non: [push]\n\njobs:\n  build:\n\n    runs-on: ubuntu-latest\n\n    steps:\n    - uses: actions/checkout@v1\n    "
  },
  {
    "path": ".gitignore",
    "chars": 4803,
    "preview": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n##\n## G"
  },
  {
    "path": "Harmonic/Buffers/ByteBuffer.cs",
    "chars": 15719,
    "preview": "using System;\nusing System.Buffers;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.Linq;\nusin"
  },
  {
    "path": "Harmonic/Controllers/Living/LivingController.cs",
    "chars": 444,
    "preview": "using Harmonic.Networking.Rtmp;\nusing Harmonic.Rpc;\nusing System;\nusing System.Collections.Generic;\nusing System.Text;\n"
  },
  {
    "path": "Harmonic/Controllers/Living/LivingStream.cs",
    "chars": 7456,
    "preview": "using Harmonic.Networking.Amf.Common;\nusing Harmonic.Networking.Rtmp;\nusing Harmonic.Networking.Rtmp.Data;\nusing Harmon"
  },
  {
    "path": "Harmonic/Controllers/NeverRegisterAttribute.cs",
    "chars": 214,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Harmonic.Controllers\n{\n    [AttributeUsag"
  },
  {
    "path": "Harmonic/Controllers/Record/RecordController.cs",
    "chars": 453,
    "preview": "using Harmonic.Networking.Rtmp.Messages;\nusing Harmonic.Rpc;\nusing System;\nusing System.Collections.Generic;\nusing Syst"
  },
  {
    "path": "Harmonic/Controllers/Record/RecordStream.cs",
    "chars": 13228,
    "preview": "using Harmonic.Networking.Flv;\nusing Harmonic.Networking.Amf.Common;\nusing Harmonic.Networking.Amf.Serialization.Amf0;\n"
  },
  {
    "path": "Harmonic/Controllers/RtmpController.cs",
    "chars": 1309,
    "preview": "using Harmonic.Networking.Flv;\nusing Harmonic.Networking.Rtmp;\nusing Harmonic.Rpc;\nusing System;\nusing System.Collectio"
  },
  {
    "path": "Harmonic/Controllers/WebSocketController.cs",
    "chars": 1251,
    "preview": "using Harmonic.Networking.Flv;\nusing Harmonic.Networking.Rtmp;\nusing Harmonic.Networking.WebSocket;\nusing System;\nusing"
  },
  {
    "path": "Harmonic/Controllers/WebSocketPlayController.cs",
    "chars": 4862,
    "preview": "using Harmonic.Networking;\nusing Harmonic.Networking.Rtmp.Messages;\nusing Harmonic.Service;\nusing Newtonsoft.Json;\nusin"
  },
  {
    "path": "Harmonic/Harmonic.csproj",
    "chars": 1275,
    "preview": "<Project Sdk=\"Microsoft.NET.Sdk\" \n  xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n\n\n  <PropertyGroup>\n  "
  },
  {
    "path": "Harmonic/Hosting/IStartup.cs",
    "chars": 161,
    "preview": "using System;\nusing Autofac;\n\nnamespace Harmonic.Hosting\n{\n    public interface IStartup\n    {\n        void ConfigureSer"
  },
  {
    "path": "Harmonic/Hosting/RtmpServer.cs",
    "chars": 4489,
    "preview": "using Autofac;\nusing Harmonic.Networking.Rtmp;\nusing Harmonic.Service;\nusing System;\nusing System.Collections.Generic;\n"
  },
  {
    "path": "Harmonic/Hosting/RtmpServerBuilder.cs",
    "chars": 3681,
    "preview": "using Harmonic.Controllers;\nusing Harmonic.Controllers.Living;\nusing Harmonic.Controllers.Record;\nusing Harmonic.Network"
  },
  {
    "path": "Harmonic/Hosting/RtmpServerOptions.cs",
    "chars": 6397,
    "preview": "using Autofac;\nusing Harmonic.Controllers;\nusing Harmonic.Controllers.Living;\nusing Harmonic.Networking.Rtmp;\nusing Har"
  },
  {
    "path": "Harmonic/Hosting/WebSocketOptions.cs",
    "chars": 1198,
    "preview": "using Autofac;\nusing Harmonic.Controllers;\nusing System;\nusing System.Collections.Generic;\nusing System.Net;\nusing Syst"
  },
  {
    "path": "Harmonic/Networking/Amf/Common/Amf3Object.cs",
    "chars": 1301,
    "preview": "using Harmonic.Networking.Amf.Data;\nusing System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing Sys"
  },
  {
    "path": "Harmonic/Networking/Amf/Common/TypeRegisterState.cs",
    "chars": 273,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Harmonic.Networking.Amf.Common\n{\n    clas"
  },
  {
    "path": "Harmonic/Networking/Amf/Common/Undefined.cs",
    "chars": 153,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Harmonic.Networking.Amf.Common\n{\n    publ"
  },
  {
    "path": "Harmonic/Networking/Amf/Common/Unsupported.cs",
    "chars": 155,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Harmonic.Networking.Amf.Common\n{\n    publ"
  },
  {
    "path": "Harmonic/Networking/Amf/Data/IDynamicObject.cs",
    "chars": 278,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Harmonic.Networking.Amf.Data\n{\n    public"
  },
  {
    "path": "Harmonic/Networking/Amf/Data/IExternalizable.cs",
    "chars": 298,
    "preview": "using Harmonic.Buffers;\nusing System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Harmonic.Networki"
  },
  {
    "path": "Harmonic/Networking/Amf/Data/Message.cs",
    "chars": 287,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Harmonic.Networking.Amf.Data\n{\n    public"
  },
  {
    "path": "Harmonic/Networking/Amf/Serialization/Amf0/Amf0CommonValues.cs",
    "chars": 598,
    "preview": "using Harmonic.Networking.Amf.Common;\nusing Harmonic.Networking.Rtmp.Data;\nusing Harmonic.Networking.Rtmp.Serialization"
  },
  {
    "path": "Harmonic/Networking/Amf/Serialization/Amf0/Amf0Reader.cs",
    "chars": 28756,
    "preview": "using Harmonic.Networking.Amf.Attributes;\nusing Harmonic.Networking.Amf.Common;\nusing Harmonic.Networking.Amf.Data;\nusi"
  },
  {
    "path": "Harmonic/Networking/Amf/Serialization/Amf0/Amf0Type.cs",
    "chars": 495,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Harmonic.Networking.Amf.Serialization.Amf"
  },
  {
    "path": "Harmonic/Networking/Amf/Serialization/Amf0/Amf0Writer.cs",
    "chars": 15073,
    "preview": "using Harmonic.Buffers;\nusing Harmonic.Networking.Amf.Attributes;\nusing Harmonic.Networking.Amf.Common;\nusing Harmonic."
  },
  {
    "path": "Harmonic/Networking/Amf/Serialization/Amf0/SerializationContext.cs",
    "chars": 993,
    "preview": "using Harmonic.Buffers;\nusing System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Harmonic.Networki"
  },
  {
    "path": "Harmonic/Networking/Amf/Serialization/Amf3/Amf3Array.cs",
    "chars": 836,
    "preview": "using System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Harmonic.Networ"
  },
  {
    "path": "Harmonic/Networking/Amf/Serialization/Amf3/Amf3ClassTraits.cs",
    "chars": 1298,
    "preview": "using System;\nusing System.Linq;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Harmonic.Networking.Am"
  },
  {
    "path": "Harmonic/Networking/Amf/Serialization/Amf3/Amf3CommonValues.cs",
    "chars": 340,
    "preview": "using System;\nusing System.Linq;\nusing System.Buffers;\nusing System.Collections.Generic;\nusing System.Text;\nusing Syste"
  },
  {
    "path": "Harmonic/Networking/Amf/Serialization/Amf3/Amf3Dictionary.cs",
    "chars": 1202,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Runtime.Serialization;\nusing System.Text;\n\nnamespace Harmo"
  },
  {
    "path": "Harmonic/Networking/Amf/Serialization/Amf3/Amf3Reader.cs",
    "chars": 39719,
    "preview": "using Harmonic.Networking.Amf.Common;\nusing System;\nusing System.Linq;\nusing System.Collections.Generic;\nusing System.T"
  },
  {
    "path": "Harmonic/Networking/Amf/Serialization/Amf3/Amf3Type.cs",
    "chars": 481,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Harmonic.Networking.Amf.Serialization.Amf"
  },
  {
    "path": "Harmonic/Networking/Amf/Serialization/Amf3/Amf3Writer.cs",
    "chars": 25619,
    "preview": "using Harmonic.Networking.Amf.Common;\nusing System;\nusing System.Linq;\nusing System.Buffers;\nusing System.Collections.G"
  },
  {
    "path": "Harmonic/Networking/Amf/Serialization/Amf3/Amf3Xml.cs",
    "chars": 364,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\nusing System.Xml;\n\nnamespace Harmonic.Networking.Amf"
  },
  {
    "path": "Harmonic/Networking/Amf/Serialization/Amf3/SerializationContext.cs",
    "chars": 1289,
    "preview": "using Harmonic.Buffers;\nusing System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Harmonic.Networki"
  },
  {
    "path": "Harmonic/Networking/Amf/Serialization/Amf3/Vector.cs",
    "chars": 1150,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\nusing System.Linq;\n\nnamespace Harmonic.Networking.Am"
  },
  {
    "path": "Harmonic/Networking/Amf/Serialization/Attributes/ClassFieldAttribute.cs",
    "chars": 290,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Harmonic.Networking.Amf.Serialization.Att"
  },
  {
    "path": "Harmonic/Networking/Amf/Serialization/Attributes/TypedObjectAttribute.cs",
    "chars": 274,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Harmonic.Networking.Amf.Attributes\n{\n    "
  },
  {
    "path": "Harmonic/Networking/ConnectionInformation.cs",
    "chars": 628,
    "preview": "\n\nusing Harmonic.Networking.Rtmp.Messages.Commands;\nusing Harmonic.Networking.Rtmp.Messages;\n\nnamespace Harmonic.Network"
  },
  {
    "path": "Harmonic/Networking/Flv/Data/AacPacketType.cs",
    "chars": 190,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Harmonic.Networking.Flv.Data\n{\n    public"
  },
  {
    "path": "Harmonic/Networking/Flv/Data/AudioData.cs",
    "chars": 272,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Harmonic.Networking.Flv.Data\n{\n    public"
  },
  {
    "path": "Harmonic/Networking/Flv/Data/CodecId.cs",
    "chars": 270,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Harmonic.Networking.Flv.Data\n{\n    public"
  },
  {
    "path": "Harmonic/Networking/Flv/Data/FlvAudioData.cs",
    "chars": 403,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Harmonic.Networking.Flv.Data\n{\n    public"
  },
  {
    "path": "Harmonic/Networking/Flv/Data/FlvVideoData.cs",
    "chars": 310,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Harmonic.Networking.Flv.Data\n{\n    public"
  },
  {
    "path": "Harmonic/Networking/Flv/Data/FrameType.cs",
    "chars": 281,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Harmonic.Networking.Flv.Data\n{\n    public"
  },
  {
    "path": "Harmonic/Networking/Flv/Data/SoundFormat.cs",
    "chars": 402,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Harmonic.Networking.Flv.Data\n{\n    public"
  },
  {
    "path": "Harmonic/Networking/Flv/Data/SoundRate.cs",
    "chars": 208,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Harmonic.Networking.Flv.Data\n{\n    public"
  },
  {
    "path": "Harmonic/Networking/Flv/Data/SoundSize.cs",
    "chars": 184,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Harmonic.Networking.Flv.Data\n{\n    public"
  },
  {
    "path": "Harmonic/Networking/Flv/Data/SoundType.cs",
    "chars": 185,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Harmonic.Networking.Flv.Data\n{\n    public"
  },
  {
    "path": "Harmonic/Networking/Flv/FlvDemuxer.cs",
    "chars": 6395,
    "preview": "using Harmonic.Buffers;\nusing Harmonic.Networking;\nusing Harmonic.Networking.Amf.Common;\nusing Harmonic.Networking.Amf."
  },
  {
    "path": "Harmonic/Networking/Flv/FlvMuxer.cs",
    "chars": 3672,
    "preview": "using Harmonic.Buffers;\nusing Harmonic.Networking.Amf.Serialization.Amf0;\nusing Harmonic.Networking.Amf.Serialization.A"
  },
  {
    "path": "Harmonic/Networking/Rtmp/ChunkStreamContext.cs",
    "chars": 26823,
    "preview": "using Harmonic.Buffers;\nusing Harmonic.Networking.Amf.Serialization.Amf0;\nusing Harmonic.Networking.Amf.Serialization.A"
  },
  {
    "path": "Harmonic/Networking/Rtmp/Data/ChunkBasicHeader.cs",
    "chars": 340,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Runtime.InteropServices;\nusing System.Runtime.Serializatio"
  },
  {
    "path": "Harmonic/Networking/Rtmp/Data/ChunkHeader.cs",
    "chars": 358,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Runtime.InteropServices;\nusing System.Text;\n\nnamespace Har"
  },
  {
    "path": "Harmonic/Networking/Rtmp/Data/ChunkHeaderType.cs",
    "chars": 426,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Harmonic.Networking.Rtmp.Data\n{\n    publi"
  },
  {
    "path": "Harmonic/Networking/Rtmp/Data/Message.cs",
    "chars": 616,
    "preview": "using Harmonic.Networking.Rtmp.Serialization;\nusing System;\nusing System.Buffers;\nusing System.Collections.Generic;\nusi"
  },
  {
    "path": "Harmonic/Networking/Rtmp/Data/MessageHeader.cs",
    "chars": 493,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Harmonic.Networking.Rtmp.Data\n{\n    publi"
  },
  {
    "path": "Harmonic/Networking/Rtmp/Data/MessageType.cs",
    "chars": 725,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Harmonic.Networking.Rtmp.Data\n{\n    publi"
  },
  {
    "path": "Harmonic/Networking/Rtmp/Data/SharedObjectMessage.cs",
    "chars": 319,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Runtime.InteropServices;\nusing System.Text;\n\nnamespace Har"
  },
  {
    "path": "Harmonic/Networking/Rtmp/Data/UserControlMessageEvents.cs",
    "chars": 327,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Harmonic.Networking.Rtmp.Data\n{\n    publi"
  },
  {
    "path": "Harmonic/Networking/Rtmp/Exceptions/UnknownMessageReceivedException.cs",
    "chars": 398,
    "preview": "using Harmonic.Networking.Rtmp.Data;\nusing System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Harm"
  },
  {
    "path": "Harmonic/Networking/Rtmp/HandshakeContext.cs",
    "chars": 3988,
    "preview": "using Harmonic.Buffers;\nusing Harmonic.Networking.Utils;\nusing System;\nusing System.Buffers;\nusing System.Collections.G"
  },
  {
    "path": "Harmonic/Networking/Rtmp/IOPipeLine.cs",
    "chars": 9022,
    "preview": "using Harmonic.Networking;\nusing Harmonic.Networking.Rtmp.Data;\nusing Harmonic.Networking.Rtmp.Exceptions;\nusing System"
  },
  {
    "path": "Harmonic/Networking/Rtmp/MessageReadingState.cs",
    "chars": 436,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Harmonic.Networking.Rtmp\n{\n    class Mess"
  },
  {
    "path": "Harmonic/Networking/Rtmp/Messages/AbortMessage.cs",
    "chars": 1074,
    "preview": "using Harmonic.Networking.Rtmp.Data;\nusing Harmonic.Networking.Rtmp.Serialization;\nusing Harmonic.Networking.Utils;\nusi"
  },
  {
    "path": "Harmonic/Networking/Rtmp/Messages/AcknowledgementMessage.cs",
    "chars": 1113,
    "preview": "using System;\nusing System.Buffers;\nusing System.Collections.Generic;\nusing System.Text;\nusing Harmonic.Networking.Rtmp"
  },
  {
    "path": "Harmonic/Networking/Rtmp/Messages/AggregateMessage.cs",
    "chars": 3632,
    "preview": "using Harmonic.Networking.Rtmp.Data;\nusing Harmonic.Networking.Rtmp.Serialization;\nusing Harmonic.Networking.Utils;\nusi"
  },
  {
    "path": "Harmonic/Networking/Rtmp/Messages/AmfEncodingVersion.cs",
    "chars": 191,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Harmonic.Networking.Rtmp.Messages\n{\n    p"
  },
  {
    "path": "Harmonic/Networking/Rtmp/Messages/AudioMessage.cs",
    "chars": 1172,
    "preview": "using Harmonic.Networking.Rtmp.Data;\nusing Harmonic.Networking.Rtmp.Serialization;\nusing System;\nusing System.Collectio"
  },
  {
    "path": "Harmonic/Networking/Rtmp/Messages/Commands/CallCommandMessage.cs",
    "chars": 526,
    "preview": "using System;\nusing System.Buffers;\nusing System.Collections.Generic;\nusing System.Diagnostics.Contracts;\nusing System."
  },
  {
    "path": "Harmonic/Networking/Rtmp/Messages/Commands/CommandMessage.cs",
    "chars": 5876,
    "preview": "using Harmonic.Networking.Amf.Common;\nusing Harmonic.Networking.Rtmp.Data;\nusing Harmonic.Networking.Rtmp.Serialization"
  },
  {
    "path": "Harmonic/Networking/Rtmp/Messages/Commands/CommandMessageFactory.cs",
    "chars": 2786,
    "preview": "using Harmonic.Networking.Rtmp.Data;\nusing Harmonic.Networking.Rtmp.Messages.Commands;\nusing Harmonic.Networking.Rtmp.S"
  },
  {
    "path": "Harmonic/Networking/Rtmp/Messages/Commands/ConnectCommandMessage.cs",
    "chars": 498,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\nusing Harmonic.Networking.Rtmp.Serialization;\nusing "
  },
  {
    "path": "Harmonic/Networking/Rtmp/Messages/Commands/CreateStreamCommandMessage.cs",
    "chars": 435,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\nusing Harmonic.Networking.Rtmp.Serialization;\nusing "
  },
  {
    "path": "Harmonic/Networking/Rtmp/Messages/Commands/DeleteStreamCommandMessage.cs",
    "chars": 508,
    "preview": "using Harmonic.Networking.Rtmp.Serialization;\nusing Harmonic.Networking.Rtmp.Messages;\nusing System;\nusing System.Colle"
  },
  {
    "path": "Harmonic/Networking/Rtmp/Messages/Commands/OnStatusCommandMessage.cs",
    "chars": 535,
    "preview": "using Harmonic.Networking.Rtmp.Data;\nusing Harmonic.Networking.Rtmp.Serialization;\nusing Harmonic.Networking.Rtmp.Messa"
  },
  {
    "path": "Harmonic/Networking/Rtmp/Messages/Commands/PauseCommandMessage.cs",
    "chars": 560,
    "preview": "using Harmonic.Networking.Rtmp.Serialization;\nusing Harmonic.Networking.Rtmp.Messages;\nusing System;\nusing System.Colle"
  },
  {
    "path": "Harmonic/Networking/Rtmp/Messages/Commands/Play2CommandMessage.cs",
    "chars": 489,
    "preview": "using Harmonic.Networking.Rtmp.Serialization;\nusing Harmonic.Networking.Rtmp.Messages;\nusing System;\nusing System.Colle"
  },
  {
    "path": "Harmonic/Networking/Rtmp/Messages/Commands/PlayCommandMessage.cs",
    "chars": 695,
    "preview": "using Harmonic.Networking.Rtmp.Serialization;\nusing Harmonic.Networking.Rtmp.Messages;\nusing System;\nusing System.Colle"
  },
  {
    "path": "Harmonic/Networking/Rtmp/Messages/Commands/PublishCommandMessage.cs",
    "chars": 577,
    "preview": "using Harmonic.Networking.Rtmp.Serialization;\nusing Harmonic.Networking.Rtmp.Messages;\nusing System;\nusing System.Colle"
  },
  {
    "path": "Harmonic/Networking/Rtmp/Messages/Commands/ReceiveAudioCommandMessage.cs",
    "chars": 507,
    "preview": "using Harmonic.Networking.Rtmp.Serialization;\nusing Harmonic.Networking.Rtmp.Messages;\nusing System;\nusing System.Colle"
  },
  {
    "path": "Harmonic/Networking/Rtmp/Messages/Commands/ReceiveVideoCommandMessage.cs",
    "chars": 507,
    "preview": "using Harmonic.Networking.Rtmp.Serialization;\nusing Harmonic.Networking.Rtmp.Messages;\nusing System;\nusing System.Colle"
  },
  {
    "path": "Harmonic/Networking/Rtmp/Messages/Commands/ReturnResultCommandMessage.cs",
    "chars": 1099,
    "preview": "using System;\nusing System.Buffers;\nusing System.Collections.Generic;\nusing System.Diagnostics.Contracts;\nusing System."
  },
  {
    "path": "Harmonic/Networking/Rtmp/Messages/Commands/SeekCommandMessage.cs",
    "chars": 488,
    "preview": "using Harmonic.Networking.Rtmp.Serialization;\nusing Harmonic.Networking.Rtmp.Messages;\nusing System;\nusing System.Colle"
  },
  {
    "path": "Harmonic/Networking/Rtmp/Messages/ControlMessage.cs",
    "chars": 272,
    "preview": "using Harmonic.Networking.Rtmp.Data;\nusing System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Harm"
  },
  {
    "path": "Harmonic/Networking/Rtmp/Messages/DataMessage.cs",
    "chars": 2395,
    "preview": "using Harmonic.Networking.Rtmp.Data;\nusing Harmonic.Networking.Rtmp.Serialization;\nusing Harmonic.Networking.Rtmp.Messa"
  },
  {
    "path": "Harmonic/Networking/Rtmp/Messages/SetChunkSizeMessage.cs",
    "chars": 1149,
    "preview": "using System;\nusing System.Buffers;\nusing System.Collections.Generic;\nusing System.Text;\nusing Harmonic.Networking.Rtmp"
  },
  {
    "path": "Harmonic/Networking/Rtmp/Messages/SetPeerBandwidthMessage.cs",
    "chars": 1412,
    "preview": "using System;\nusing System.Buffers;\nusing System.Collections.Generic;\nusing System.Text;\nusing Harmonic.Networking.Rtmp"
  },
  {
    "path": "Harmonic/Networking/Rtmp/Messages/UserControlMessages/PingRequestMessage.cs",
    "chars": 1596,
    "preview": "using Harmonic.Networking.Rtmp.Serialization;\nusing Harmonic.Networking.Utils;\nusing System;\nusing System.Buffers;\nusin"
  },
  {
    "path": "Harmonic/Networking/Rtmp/Messages/UserControlMessages/PingResponseMessage.cs",
    "chars": 1590,
    "preview": "using Harmonic.Networking.Rtmp.Serialization;\nusing Harmonic.Networking.Utils;\nusing System;\nusing System.Buffers;\nusin"
  },
  {
    "path": "Harmonic/Networking/Rtmp/Messages/UserControlMessages/SetBufferLengthMessage.cs",
    "chars": 1903,
    "preview": "using Harmonic.Networking.Rtmp.Serialization;\nusing Harmonic.Networking.Utils;\nusing System;\nusing System.Buffers;\nusin"
  },
  {
    "path": "Harmonic/Networking/Rtmp/Messages/UserControlMessages/StreamBeginMessage.cs",
    "chars": 1584,
    "preview": "using Harmonic.Networking.Rtmp.Serialization;\nusing Harmonic.Networking.Utils;\nusing System;\nusing System.Buffers;\nusin"
  },
  {
    "path": "Harmonic/Networking/Rtmp/Messages/UserControlMessages/StreamDryMessage.cs",
    "chars": 1578,
    "preview": "using Harmonic.Networking.Rtmp.Serialization;\nusing Harmonic.Networking.Utils;\nusing System;\nusing System.Buffers;\nusin"
  },
  {
    "path": "Harmonic/Networking/Rtmp/Messages/UserControlMessages/StreamEofMessage.cs",
    "chars": 1587,
    "preview": "using Harmonic.Networking.Rtmp.Serialization;\nusing Harmonic.Networking.Utils;\nusing System;\nusing System.Buffers;\nusin"
  },
  {
    "path": "Harmonic/Networking/Rtmp/Messages/UserControlMessages/StreamIsRecordedMessage.cs",
    "chars": 1608,
    "preview": "using Harmonic.Networking.Rtmp.Serialization;\nusing Harmonic.Networking.Utils;\nusing System;\nusing System.Buffers;\nusin"
  },
  {
    "path": "Harmonic/Networking/Rtmp/Messages/UserControlMessages/UserControlMessage.cs",
    "chars": 758,
    "preview": "using System;\nusing System.Buffers;\nusing System.Collections.Generic;\nusing System.Text;\nusing Harmonic.Networking.Rtmp"
  },
  {
    "path": "Harmonic/Networking/Rtmp/Messages/UserControlMessages/UserControlMessageFactory.cs",
    "chars": 1280,
    "preview": "using Harmonic.Networking.Rtmp.Data;\nusing Harmonic.Networking.Rtmp.Serialization;\nusing Harmonic.Networking.Utils;\nusi"
  },
  {
    "path": "Harmonic/Networking/Rtmp/Messages/VideoMessage.cs",
    "chars": 1200,
    "preview": "using Harmonic.Networking.Rtmp.Data;\nusing Harmonic.Networking.Rtmp.Serialization;\nusing System;\nusing System.Collectio"
  },
  {
    "path": "Harmonic/Networking/Rtmp/Messages/WindowAcknowledgementSizeMessage.cs",
    "chars": 1133,
    "preview": "using System;\nusing System.Buffers;\nusing System.Collections.Generic;\nusing System.Text;\nusing Harmonic.Networking.Rtmp"
  },
  {
    "path": "Harmonic/Networking/Rtmp/NetConnection.cs",
    "chars": 6307,
    "preview": "using Autofac;\nusing Harmonic.Controllers;\nusing Harmonic.Networking.Amf.Common;\nusing Harmonic.Networking.Rtmp.Data;\nu"
  },
  {
    "path": "Harmonic/Networking/Rtmp/NetStream.cs",
    "chars": 1009,
    "preview": "using Harmonic.Controllers;\nusing Harmonic.Networking.Amf.Common;\nusing Harmonic.Rpc;\nusing System;\nusing System.Collec"
  },
  {
    "path": "Harmonic/Networking/Rtmp/RtmpChunkStream.cs",
    "chars": 1377,
    "preview": "using Harmonic.Networking.Rtmp.Data;\nusing System;\nusing System.Collections.Generic;\nusing System.Text;\nusing System.Th"
  },
  {
    "path": "Harmonic/Networking/Rtmp/RtmpControlChunkStream.cs",
    "chars": 510,
    "preview": "using Harmonic.Networking.Rtmp.Data;\nusing Harmonic.Networking.Rtmp.Messages;\nusing System;\nusing System.Collections.Ge"
  },
  {
    "path": "Harmonic/Networking/Rtmp/RtmpControlMessageStream.cs",
    "chars": 467,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\nusing System.Threading.Tasks;\nusing Harmonic.Network"
  },
  {
    "path": "Harmonic/Networking/Rtmp/RtmpMessageStream.cs",
    "chars": 3094,
    "preview": "using Harmonic.Networking.Rtmp.Data;\nusing Harmonic.Networking.Rtmp.Messages;\nusing Harmonic.Networking.Rtmp.Serializat"
  },
  {
    "path": "Harmonic/Networking/Rtmp/RtmpSession.cs",
    "chars": 13174,
    "preview": "using Autofac;\nusing Harmonic.Controllers;\nusing Harmonic.Networking.Rtmp.Data;\nusing Harmonic.Networking.Rtmp.Messages"
  },
  {
    "path": "Harmonic/Networking/Rtmp/Serialization/OptionalArgumentAttribute.cs",
    "chars": 237,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Harmonic.Networking.Rtmp.Serialization\n{\n"
  },
  {
    "path": "Harmonic/Networking/Rtmp/Serialization/RtmpCommandAttribute.cs",
    "chars": 270,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Harmonic.Networking.Rtmp.Serialization\n{\n"
  },
  {
    "path": "Harmonic/Networking/Rtmp/Serialization/RtmpMessageAttribute.cs",
    "chars": 489,
    "preview": "using Harmonic.Networking.Rtmp.Data;\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Te"
  },
  {
    "path": "Harmonic/Networking/Rtmp/Serialization/SerializationContext.cs",
    "chars": 709,
    "preview": "using Harmonic.Buffers;\nusing Harmonic.Networking.Amf.Serialization.Amf0;\nusing Harmonic.Networking.Amf.Serialization.A"
  },
  {
    "path": "Harmonic/Networking/Rtmp/Serialization/UserControlMessageAttribute.cs",
    "chars": 307,
    "preview": "using Harmonic.Networking.Rtmp.Messages.UserControlMessages;\nusing System;\nusing System.Collections.Generic;\nusing Syst"
  },
  {
    "path": "Harmonic/Networking/Rtmp/Streaming/PublishingType.cs",
    "chars": 368,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Harmonic.Networking.Rtmp.Streaming\n{\n    "
  },
  {
    "path": "Harmonic/Networking/Rtmp/Streaming/PublishingTypeNameAttribute.cs",
    "chars": 1260,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Reflection;\nusing System.Text;\n\nnamespa"
  },
  {
    "path": "Harmonic/Networking/Rtmp/Supervisor.cs",
    "chars": 3684,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nusing Harmonic.Ho"
  },
  {
    "path": "Harmonic/Networking/Rtmp/WriteState.cs",
    "chars": 288,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\nusing System.Threading.Tasks;\n\nnamespace Harmonic.Ne"
  },
  {
    "path": "Harmonic/Networking/Utils/NetworkBitConverter.cs",
    "chars": 5033,
    "preview": "using System;\nusing System.Buffers;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System."
  },
  {
    "path": "Harmonic/Networking/Utils/StreamHelper.cs",
    "chars": 1501,
    "preview": "using System;\nusing System.Buffers;\nusing System.IO;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace H"
  },
  {
    "path": "Harmonic/Networking/WebSocket/WebSocketSession.cs",
    "chars": 3436,
    "preview": "using Autofac;\nusing Fleck;\nusing Harmonic.Buffers;\nusing Harmonic.Controllers;\nusing Harmonic.Hosting;\nusing Harmonic."
  },
  {
    "path": "Harmonic/Rpc/CommandObjectAttribute.cs",
    "chars": 221,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Harmonic.Networking.Rtmp\n{\n    [Attribute"
  },
  {
    "path": "Harmonic/Rpc/FromCommandObjectAttribute.cs",
    "chars": 311,
    "preview": "using System;\n\nnamespace Harmonic.Rpc\n{\n    [AttributeUsage(AttributeTargets.Parameter)]\n    public class FromCommandObj"
  },
  {
    "path": "Harmonic/Rpc/FromOptionalArgumentAttribute.cs",
    "chars": 216,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Harmonic.Rpc\n{\n    [AttributeUsage(Attrib"
  },
  {
    "path": "Harmonic/Rpc/RpcMethodAttribute.cs",
    "chars": 250,
    "preview": "using System;\n\nnamespace Harmonic.Rpc\n{\n    public class RpcMethodAttribute : Attribute\n    {\n        public string Name"
  },
  {
    "path": "Harmonic/Rpc/RpcService.cs",
    "chars": 8379,
    "preview": "using Harmonic.Controllers;\nusing Harmonic.Networking.Amf.Common;\nusing Harmonic.Networking.Rtmp;\nusing Harmonic.Networ"
  },
  {
    "path": "Harmonic/Service/PublisherSessionService.cs",
    "chars": 1568,
    "preview": "using System;\nusing System.Linq;\nusing System.Collections.Generic;\nusing Harmonic.Controllers.Living;\nusing Harmonic.Net"
  },
  {
    "path": "Harmonic/Service/RecordService.cs",
    "chars": 563,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Text;\n\nnamespace Harmonic.Service\n{\n    p"
  },
  {
    "path": "Harmonic/Service/RecordServiceConfiguration.cs",
    "chars": 311,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Harmonic.Service\n{\n    public class Recor"
  },
  {
    "path": "Harmonic.sln",
    "chars": 3023,
    "preview": "\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio Version 16\nVisualStudioVersion = 16.0.2880"
  },
  {
    "path": "LICENSE",
    "chars": 1066,
    "preview": "MIT License\n\nCopyright (c) 2019 a1q123456\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\n"
  },
  {
    "path": "README.md",
    "chars": 1860,
    "preview": "master is not a stable branch, you may want to see the latest [tag](https://github.com/a1q123456/rtmp-sharp-server/tree/"
  },
  {
    "path": "RoadMap.md",
    "chars": 426,
    "preview": "# Harmonic\n\na high performance RTMP streaming application framework\n\n# Road map\n\n- [x] Rtmp muxer/demuxer\n- [x] Amf0 ser"
  },
  {
    "path": "UnitTest/TestAmf0Reader.cs",
    "chars": 8961,
    "preview": "using Harmonic.Networking.Amf.Attributes;\nusing Harmonic.Networking.Amf.Data;\nusing Harmonic.Networking.Amf.Serializati"
  },
  {
    "path": "UnitTest/TestAmf0Writer.cs",
    "chars": 12225,
    "preview": "using Harmonic.Networking.Amf.Attributes;\nusing Harmonic.Networking.Amf.Common;\nusing Harmonic.Networking.Amf.Data;\nusi"
  },
  {
    "path": "UnitTest/TestAmf3Reader.cs",
    "chars": 20180,
    "preview": "using Harmonic.Buffers;\nusing Harmonic.Networking.Amf.Attributes;\nusing Harmonic.Networking.Amf.Common;\nusing Harmonic."
  },
  {
    "path": "UnitTest/TestAmf3Writer.cs",
    "chars": 18185,
    "preview": "using Harmonic.Buffers;\nusing Harmonic.Networking.Amf.Attributes;\nusing Harmonic.Networking.Amf.Common;\nusing Harmonic."
  },
  {
    "path": "UnitTest/TestUnlimitedBuffer.cs",
    "chars": 13939,
    "preview": "using Harmonic.Buffers;\nusing Microsoft.VisualStudio.TestTools.UnitTesting;\nusing System;\nusing System.Buffers;\nusing Sy"
  },
  {
    "path": "UnitTest/UnitTest.csproj",
    "chars": 643,
    "preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFramework>netcoreapp2.2</TargetFramework>\n\n    <IsPacka"
  },
  {
    "path": "demo/MyLivingController.cs",
    "chars": 475,
    "preview": "using Harmonic.Controllers;\nusing Harmonic.Controllers.Living;\nusing Harmonic.Rpc;\nusing System;\nusing System.Collectio"
  },
  {
    "path": "demo/MyLivingStream.cs",
    "chars": 850,
    "preview": "using Harmonic.Controllers;\nusing Harmonic.Controllers.Living;\nusing Harmonic.Rpc;\nusing Harmonic.Service;\nusing System"
  },
  {
    "path": "demo/Program.cs",
    "chars": 514,
    "preview": "using Harmonic.Hosting;\nusing System;\nusing System.Net;\n\nnamespace demo\n{\n    class Program\n    {\n        static void M"
  },
  {
    "path": "demo/StartUp.cs",
    "chars": 253,
    "preview": "using Autofac;\nusing Harmonic.Hosting;\nusing System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace de"
  },
  {
    "path": "demo/demo.csproj",
    "chars": 264,
    "preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <OutputType>Exe</OutputType>\n    <TargetFramework>netcoreapp2."
  },
  {
    "path": "docs/README.md",
    "chars": 7082,
    "preview": "# Harmonic\nA high performance RTMP live streaming application framework\n\n\n# Usage\n\n\nProgram.cs\n\n```csharp\nusing Harmonic"
  },
  {
    "path": "docs/api.md",
    "chars": 1327,
    "preview": "\n# NetConnection\n## IReadOnlyDictionary<uint, RtmpController> NetStreams { get; }\naccess all NetStreams that is managed "
  },
  {
    "path": "docs/rpc.md",
    "chars": 1561,
    "preview": "# Ways to map rpc method in a RtmpController\n\n## Attributes\n\n### RpcMethodAttribute\nmarks a method that can be invoked b"
  },
  {
    "path": "samples/amf0/boolean/true.amf0",
    "chars": 2,
    "preview": "\u0001\u0001"
  },
  {
    "path": "samples/amf0/misc/null.amf0",
    "chars": 1,
    "preview": "\u0005"
  },
  {
    "path": "samples/amf0/misc/undefined.amf0",
    "chars": 1,
    "preview": "\u0006"
  },
  {
    "path": "samples/amf3/boolean/false.amf3",
    "chars": 1,
    "preview": "\u0002"
  },
  {
    "path": "samples/amf3/boolean/true.amf3",
    "chars": 1,
    "preview": "\u0003"
  },
  {
    "path": "samples/amf3/intenger/56.amf3",
    "chars": 2,
    "preview": "\u00048"
  },
  {
    "path": "samples/amf3/intenger/57.amf3",
    "chars": 2,
    "preview": "\u00049"
  },
  {
    "path": "samples/amf3/intenger/60.amf3",
    "chars": 2,
    "preview": "\u0004<"
  },
  {
    "path": "samples/amf3/intenger/67.amf3",
    "chars": 2,
    "preview": "\u0004C"
  },
  {
    "path": "samples/amf3/intenger/72.amf3",
    "chars": 2,
    "preview": "\u0004H"
  },
  {
    "path": "samples/amf3/intenger/73.amf3",
    "chars": 2,
    "preview": "\u0004I"
  },
  {
    "path": "samples/amf3/intenger/75.amf3",
    "chars": 2,
    "preview": "\u0004K"
  },
  {
    "path": "samples/amf3/intenger/78.amf3",
    "chars": 2,
    "preview": "\u0004N"
  },
  {
    "path": "samples/amf3/intenger/82.amf3",
    "chars": 2,
    "preview": "\u0004R"
  },
  {
    "path": "samples/amf3/intenger/98.amf3",
    "chars": 2,
    "preview": "\u0004b"
  },
  {
    "path": "samples/amf3/misc/bytearray.amf3",
    "chars": 5,
    "preview": "\f\u0007\u0001\u0002\u0003"
  },
  {
    "path": "samples/amf3/misc/null.amf3",
    "chars": 1,
    "preview": "\u0001"
  },
  {
    "path": "samples/amf3/misc/xml.amf3",
    "chars": 24,
    "preview": "\u000b-<a><b value=\"1\" /></a>"
  },
  {
    "path": "samples/amf3/misc/xml_document.amf3",
    "chars": 28,
    "preview": "\u00075<a value=\"1\"><b >2</b></a>"
  },
  {
    "path": "samples/amf3/number/0.05806697191443333.amf3",
    "chars": 4,
    "preview": "\u0005?BR"
  },
  {
    "path": "samples/amf3/number/3.962148410082559.amf3",
    "chars": 5,
    "preview": "\u0005@\u000fzݙ"
  },
  {
    "path": "samples/amf3/number/4.465764800567858.amf3",
    "chars": 5,
    "preview": "\u0005@\u0011rD"
  },
  {
    "path": "samples/amf3/number/6.863435764713296.amf3",
    "chars": 6,
    "preview": "\u0005@\u001bt(N"
  },
  {
    "path": "samples/amf3/number/7.645173446829178.amf3",
    "chars": 6,
    "preview": "\u0005@\u001eY\u0019\u0002"
  },
  {
    "path": "samples/amf3/number/8.451623695104308.amf3",
    "chars": 6,
    "preview": "\u0005@ ;8$"
  },
  {
    "path": "samples/amf3/number/8.518697602984554.amf3",
    "chars": 6,
    "preview": "\u0005@!\tr\u001d"
  },
  {
    "path": "samples/amf3/number/8.85002823631796.amf3",
    "chars": 6,
    "preview": "\u0005@!6S\f"
  },
  {
    "path": "samples/amf3/number/9.838871036292584.amf3",
    "chars": 5,
    "preview": "\u0005@#$f"
  },
  {
    "path": "samples/amf3/number/9.98509389093438.amf3",
    "chars": 6,
    "preview": "\u0005@#^9\u001a"
  },
  {
    "path": "samples/amf3/string/aoxqmkvbxa.amf3",
    "chars": 12,
    "preview": "\u0006\u0015aoxqmkvbxa"
  },
  {
    "path": "samples/amf3/string/bghnwadduz.amf3",
    "chars": 12,
    "preview": "\u0006\u0015bghnwadduz"
  },
  {
    "path": "samples/amf3/string/cmaljzrwgc.amf3",
    "chars": 12,
    "preview": "\u0006\u0015cmaljzrwgc"
  },
  {
    "path": "samples/amf3/string/cuyerozwyf.amf3",
    "chars": 12,
    "preview": "\u0006\u0015cuyerozwyf"
  },
  {
    "path": "samples/amf3/string/dfjfucqvpr.amf3",
    "chars": 12,
    "preview": "\u0006\u0015dfjfucqvpr"
  },
  {
    "path": "samples/amf3/string/fxxcsjosdu.amf3",
    "chars": 12,
    "preview": "\u0006\u0015fxxcsjosdu"
  },
  {
    "path": "samples/amf3/string/korbgwizge.amf3",
    "chars": 12,
    "preview": "\u0006\u0015korbgwizge"
  },
  {
    "path": "samples/amf3/string/psvigwvvpx.amf3",
    "chars": 12,
    "preview": "\u0006\u0015psvigwvvpx"
  },
  {
    "path": "samples/amf3/string/ubteltbaku.amf3",
    "chars": 12,
    "preview": "\u0006\u0015ubteltbaku"
  },
  {
    "path": "samples/amf3/string/vqayztgtuf.amf3",
    "chars": 12,
    "preview": "\u0006\u0015vqayztgtuf"
  }
]

// ... and 40 more files (download for full content)

About this extraction

This page contains the full source code of the a1q123456/Harmonic GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 226 files (429.0 KB), approximately 94.9k tokens, and a symbol index with 675 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!