protected virtual void WriteTransactionInfo(TransactionInfo command, BinaryWriter dataOut)
    {
        String type;

        switch ((TransactionType)command.Type)
        {
        case TransactionType.Commit:
            command.ResponseRequired = true;
            type = "COMMIT";
            break;

        case TransactionType.Rollback:
            command.ResponseRequired = true;
            type = "ABORT";
            break;

        case TransactionType.Begin:
            type = "BEGIN";
            break;

        default:
            throw new ArgumentOutOfRangeException();
        }

        var frame = new StompFrame(type, _encodeHeaders);

        if (command.ResponseRequired)
        {
            frame.SetProperty(PropertyKeys.Receipt, command.CommandId);
        }

        frame.SetProperty(PropertyKeys.Transaction, command.TransactionId.ToString());

        frame.ToStream(dataOut);
    }
    protected virtual void WriteRemoveInfo(RemoveInfo command, BinaryWriter dataOut)
    {
        var    frame = new StompFrame("UNSUBSCRIBE", _encodeHeaders);
        Object id    = command.ObjectId;

        if (id is not ConsumerId consumerId)
        {
            return;
        }
        if (command.ResponseRequired)
        {
            frame.SetProperty(PropertyKeys.Receipt, command.CommandId);
        }
        frame.SetProperty(PropertyKeys.Id, consumerId.ToString());

        frame.ToStream(dataOut);
    }
    protected virtual void WriteMessageAck(MessageAck command, BinaryWriter dataOut)
    {
        var frame = new StompFrame("ACK", _encodeHeaders);

        if (command.ResponseRequired)
        {
            frame.SetProperty(PropertyKeys.Receipt, "ignore:" + command.CommandId);
        }

        frame.SetProperty(PropertyKeys.MessageId, command.LastMessageId.ToString());
        frame.SetProperty(PropertyKeys.Subscription, command.ConsumerId.ToString());

        if (command.TransactionId != null)
        {
            frame.SetProperty(PropertyKeys.Transaction, command.TransactionId.ToString());
        }

        frame.ToStream(dataOut);
    }
    protected virtual void WriteConnectionInfo(ConnectionInfo command, BinaryWriter dataOut)
    {
        // lets force a receipt for the Connect Frame.
        var frame = new StompFrame("CONNECT", _encodeHeaders);

        frame.SetProperty(PropertyKeys.ClientId, command.ClientId);
        if (command.UserName.IsNotEmpty())
        {
            frame.SetProperty(PropertyKeys.Login, command.UserName);
        }
        if (command.Password.IsNotEmpty())
        {
            frame.SetProperty(PropertyKeys.Passcode, command.Password);
        }

        if (SetHostHeader)
        {
            frame.SetProperty(PropertyKeys.Host, HostHeaderOverride ?? command.Host);
        }

        frame.SetProperty(PropertyKeys.AcceptVersion, "1.0,1.1");

        if (MaxInactivityDuration != 0)
        {
            frame.SetProperty(PropertyKeys.HartBeat, WriteCheckInterval + "," + ReadCheckInterval);
        }

        _connectedResponseId = command.CommandId;

        frame.ToStream(dataOut);
    }
    protected virtual void WriteMessage(BytesMessage command, BinaryWriter dataOut)
    {
        var frame = new StompFrame("SEND", _encodeHeaders);

        if (command.ResponseRequired)
        {
            frame.SetProperty(PropertyKeys.Receipt, command.CommandId);
        }

        frame.SetProperty(PropertyKeys.Destination, command.Destination.ConvertToStompString());

        if (command.ReplyTo != null)
        {
            frame.SetProperty(PropertyKeys.ReplyTo, command.ReplyTo.ConvertToStompString());
        }
        if (command.CorrelationId != null)
        {
            frame.SetProperty(PropertyKeys.CorrelationId, command.CorrelationId);
        }
        if (command.Expiration != 0)
        {
            frame.SetProperty(PropertyKeys.Expires, command.Expiration);
        }
        if (command.Timestamp != 0)
        {
            frame.SetProperty(PropertyKeys.TimeStamp, command.Timestamp);
        }
        if (command.Priority != 4)
        {
            frame.SetProperty(PropertyKeys.Priority, command.Priority);
        }
        if (command.Type != null)
        {
            frame.SetProperty(PropertyKeys.Type, command.Type);
        }
        if (command.TransactionId != null)
        {
            frame.SetProperty(PropertyKeys.Transaction, command.TransactionId.ToString());
        }

        frame.SetProperty(PropertyKeys.Persistent,
                          command.Persistent.ToString()
                          .ToLower());
        frame.SetProperty(PropertyKeys.NmsxDeliveryMode,
                          command.Persistent.ToString()
                          .ToLower());

        if (command.StompGroupId != null)
        {
            frame.SetProperty(PropertyKeys.JmsxGroupId, command.StompGroupId);
            frame.SetProperty(PropertyKeys.NmsxGroupId, command.StompGroupId);
            frame.SetProperty(PropertyKeys.JmsxGroupSeq, command.StompGroupSeq);
            frame.SetProperty(PropertyKeys.NmsxGroupSeq, command.StompGroupSeq);
        }

        // Store the Marshaled Content.
        frame.Content = command.Content;

        if (command.Content?.Length > 0 && StompNetConfiguration.AddContentLengthHeader)
        {
            frame.SetProperty(PropertyKeys.ContentLength, command.Content.Length);
        }

        frame.SetProperty(PropertyKeys.Transformation, "jms-byte");

        // Marshal all properties to the Frame.
        var map = command.Headers;

        foreach (var key in map.Keys)
        {
            frame.SetProperty(key, map[key]);
        }

        frame.ToStream(dataOut);
    }
    protected virtual void WriteConsumerInfo(ConsumerInfo command, BinaryWriter dataOut)
    {
        var frame = new StompFrame("SUBSCRIBE", _encodeHeaders);

        if (command.ResponseRequired)
        {
            frame.SetProperty(PropertyKeys.Receipt, command.CommandId);
        }

        frame.SetProperty(PropertyKeys.Destination, command.Destination?.ConvertToStompString());
        frame.SetProperty(PropertyKeys.Id, command.ConsumerId.ToString());
        frame.SetProperty(PropertyKeys.DurableSubscriberName, command.SubscriptionName);
        frame.SetProperty(PropertyKeys.Selector, command.Selector);
        frame.SetProperty(PropertyKeys.Ack, StompHelper.ToStomp(command.AckMode));

        if (command.NoLocal)
        {
            frame.SetProperty(PropertyKeys.NoLocal, command.NoLocal.ToString());
        }

        // ActiveMQ extensions to STOMP
        frame.SetProperty(PropertyKeys.Transformation, command.Transformation ?? "jms-xml");

        frame.SetProperty(PropertyKeys.ActivemqDispatchAsync, command.DispatchAsync);

        if (command.Exclusive)
        {
            frame.SetProperty(PropertyKeys.ActivemqExclusive, command.Exclusive);
        }

        if (command.SubscriptionName != null)
        {
            frame.SetProperty(PropertyKeys.ActivemqSubscriptionName, command.SubscriptionName);
            // For an older 4.0 broker we need to set this header so they get the
            // subscription as well..
            frame.SetProperty(PropertyKeys.ActivemqSubcriptionName, command.SubscriptionName);
        }

        frame.SetProperty(PropertyKeys.ActivemqMaximumPendingMessageLimit, command.MaximumPendingMessageLimit);
        frame.SetProperty(PropertyKeys.ActivemqPrefetchSize, command.PrefetchSize);
        frame.SetProperty(PropertyKeys.ActivemqPriority, command.Priority);

        if (command.Retroactive)
        {
            frame.SetProperty(PropertyKeys.ActivemqRetroactive, command.Retroactive);
        }

        frame.ToStream(dataOut);
    }