private void SendImpl(string exchangeName, string routingKey, AbstractQmsMessage message, DeliveryMode deliveryMode, int priority, uint timeToLive, bool mandatory, bool immediate)
        {
            // todo: handle session access ticket
            AMQFrame publishFrame = BasicPublishBody.CreateAMQFrame(
                _channel.ChannelId, 0, exchangeName,
                routingKey, mandatory, immediate
                );

            // fix message properties
            if (!_disableTimestamps)
            {
                message.Timestamp = DateTime.UtcNow.Ticks;
                if (timeToLive != 0)
                {
                    message.Expiration = message.Timestamp + timeToLive;
                }
            }
            else
            {
                message.Expiration = 0;
            }
            message.DeliveryMode = deliveryMode;
            message.Priority     = (byte)priority;

            ByteBuffer payload       = message.Data;
            int        payloadLength = payload.Limit;

            ContentBody[] contentBodies = CreateContentBodies(payload);
            AMQFrame[]    frames        = new AMQFrame[2 + contentBodies.Length];
            for (int i = 0; i < contentBodies.Length; i++)
            {
                frames[2 + i] = ContentBody.CreateAMQFrame(_channelId, contentBodies[i]);
            }
            if (contentBodies.Length > 0 && _logger.IsDebugEnabled)
            {
                _logger.Debug(string.Format("Sending content body frames to {{exchangeName={0} routingKey={1}}}", exchangeName, routingKey));
            }

            // weight argument of zero indicates no child content headers, just bodies
            AMQFrame contentHeaderFrame = ContentHeaderBody.CreateAMQFrame(
                _channelId, AmqChannel.BASIC_CONTENT_TYPE, 0,
                message.ContentHeaderProperties, (uint)payloadLength
                );

            if (_logger.IsDebugEnabled)
            {
                _logger.Debug(string.Format("Sending content header frame to  {{exchangeName={0} routingKey={1}}}", exchangeName, routingKey));
            }

            frames[0] = publishFrame;
            frames[1] = contentHeaderFrame;
            CompositeAMQDataBlock compositeFrame = new CompositeAMQDataBlock(frames);

            lock (_channel.Connection.FailoverMutex)
            {
                _channel.Connection.ProtocolWriter.Write(compositeFrame);
            }
        }