public async Task SendMessage(Message message, CancellationToken ct)
        {
            int msgSize     = _minMsgSize;
            var payloadSize = 0;
            var payload     = message.Payload;

            if (payload != null)
            {
                payloadSize = payload.Length;
                msgSize    += payloadSize;
            }

            var buffer = ArrayPool <byte> .Shared.Rent(_sendBufferSize);

            var payloadIndex = 0;

            try
            {
                do
                {
                    var partialPayloadSize = Math.Min(payloadSize - payloadIndex, _availablePayloadSize);
                    var partialMsgSize     = _minPartialMsgSize + partialPayloadSize;

                    BufferHelper.CopyToIndex(BitConverter.GetBytes(partialMsgSize), buffer, _partialMsgSizeIndex);
                    BufferHelper.CopyToIndex(BitConverter.GetBytes(msgSize), buffer, _msgSizeIndex);
                    BufferHelper.CopyToIndex(BitConverter.GetBytes(payloadIndex), buffer, _fragmentIdIndex);
                    buffer[_partialMsgTypeIndex] = (byte)message.MessageType;
                    BufferHelper.CopyToIndex(message.Id.ToByteArray(), buffer, _msgIdIndex);
                    if (partialPayloadSize > 0)
                    {
                        Buffer.BlockCopy(payload, payloadIndex, buffer, _partialPayloadIndex, partialPayloadSize);
                    }
                    var segment = new ArraySegment <byte>(buffer, 0, partialMsgSize);
                    await _sendLock.WaitAsync();

                    try
                    {
                        await _transportChannel.SendAsync(segment, ct);
                    }
                    finally
                    {
                        _sendLock.Release();
                    }
                    payloadIndex += partialPayloadSize;
                }while (!ct.IsCancellationRequested && payloadIndex < payloadSize);
            }
            finally
            {
                ArrayPool <byte> .Shared.Return(buffer);
            }
        }
Exemple #2
0
        public async Task SendMessage(Message message, CancellationToken ct)
        {
            var msgSize     = _minMessageSize;
            var payloadSize = 0;
            var payload     = message.Payload;

            if (payload != null)
            {
                payloadSize = payload.Length;
                msgSize    += payloadSize;
            }

            var buffer = ArrayPool <byte> .Shared.Rent(msgSize);

            var locked = false;

            try
            {
                BufferHelper.CopyToIndex(BitConverter.GetBytes(msgSize), buffer, _sizeIndex);
                buffer[_messageTypeIndex] = (byte)message.MessageType;
                BufferHelper.CopyToIndex(message.Id.ToByteArray(), buffer, _idIndex);
                if (payloadSize > 0)
                {
                    BufferHelper.CopyToIndex(payload, buffer, _payloadIndex);
                }

                var offset = 0;
                await _sendLock.WaitAsync();

                locked = true;

                while (!ct.IsCancellationRequested && offset < msgSize)
                {
                    var left    = msgSize - offset;
                    var next    = Math.Min(_sendBufferSize, left);
                    var segment = new ArraySegment <byte>(buffer, offset, next);
                    await _transportChannel.SendAsync(segment, ct);

                    offset += next;
                }
            }
            finally
            {
                if (locked)
                {
                    _sendLock.Release();
                }

                ArrayPool <byte> .Shared.Return(buffer);
            }
        }