/// <inheritdoc />
        public async Task WriteAsync(TWritePayloadBaseType payload)
        {
            //Serializer the payload first so we can build the header
            byte[] payloadData = Serializer.Serialize(payload);

            IPacketHeader header = PacketHeaderFactory.Create(payload, payloadData);

            //VERY critical we lock here otherwise we could write a header and then another unrelated body could be written inbetween
            using (await writeSynObj.LockAsync().ConfigureAwait(false))
            {
                //It's important to always write the header first
                await HeaderReaderWriter.WriteHeaderAsync(header)
                .ConfigureAwait(false);

                //Write the outgoing message, it will internally create the header and it will be serialized
                await DecoratedClient.WriteAsync(payloadData)
                .ConfigureAwait(false);
            }
        }
        public async Task <NetworkIncomingMessage <TReadPayloadBaseType> > ReadAsync(CancellationToken token)
        {
            IPacketHeader        header  = null;
            TReadPayloadBaseType payload = null;

            using (await readSynObj.LockAsync(token).ConfigureAwait(false))
            {
                //Read the header first
                header = await HeaderReaderWriter.ReadHeaderAsync(token)
                         .ConfigureAwait(false);

                //If the header is null it means the socket disconnected
                if (header == null)
                {
                    return(null);
                }

                //if was canceled the header reading probably returned null anyway
                if (token.IsCancellationRequested)
                {
                    return(null);
                }

                //We need to read enough bytes to deserialize the payload
                await ReadAsync(PacketPayloadReadBuffer, 0, header.PayloadSize, token)
                .ConfigureAwait(false);                        //TODO: Should we timeout?

                //If the token was canceled then the buffer isn't filled and we can't make a message
                if (token.IsCancellationRequested)
                {
                    return(null);
                }

                //WARNING: We must do deserialization inside of the lock otherwise we can encounter a race condition
                //Deserialize the bytes starting from the begining but ONLY read up to the payload size. We reuse this buffer and it's large
                //so if we don't specify the length we could end up with an issue.
                payload = Serializer.Deserialize <TReadPayloadBaseType>(PacketPayloadReadBuffer, 0, header.PayloadSize);
            }

            return(new NetworkIncomingMessage <TReadPayloadBaseType>(header, payload));
        }