Exemplo n.º 1
0
        private BlockwiseStatus FindResponseBlockStatus(Exchange exchange, Response response)
        {
            // NOTICE: This method is used by sendResponse and receiveResponse. Be
            // careful, making changes to the status in here.
            BlockwiseStatus status = exchange.ResponseBlockStatus;

            if (status == null)
            {
                status                       = new BlockwiseStatus(response.ContentType);
                status.CurrentSZX            = BlockOption.EncodeSZX(_defaultBlockSize);
                exchange.ResponseBlockStatus = status;
                if (log.IsDebugEnabled)
                {
                    log.Debug("There is no blockwise status yet. Create and set new block2 status: " + status);
                }
            }
            else
            {
                if (log.IsDebugEnabled)
                {
                    log.Debug("Current blockwise status: " + status);
                }
            }
            return(status);
        }
Exemplo n.º 2
0
        public override void Send(Message message)
        {
            var blockInfo   = NegotiateBlockSize(message);
            var isBlockwise = message.Payload.Length > BlockOption.DecodeSzx(blockInfo.Szx);

            if (isBlockwise)
            {
                if (!message.HasToken)
                {
                    message.Token = _tokenManager.AcquireToken();
                }

                var block        = message.GetBlock(blockInfo);
                var optionNumber = message is Request ? OptionNumber.Block1 : OptionNumber.Block2;

                if (block.GetBlockOption(optionNumber).M > 0)
                {
                    _incomplete.Add(message.GetTransactionKey(), message);
                }

                SendMessageOverLowerLayer(block);
            }
            else
            {
                SendMessageOverLowerLayer(message);
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Initializes a transfer layer.
        /// </summary>
        /// <param name="defaultBlockSize">The default block size used for block-wise transfers or -1 to disable outgoing block-wise transfers</param>
        public TransferLayer(Int32 defaultBlockSize)
        {
            if (defaultBlockSize == 0)
            {
                defaultBlockSize = CoapConstants.DefaultBlockSize;
            }

            if (defaultBlockSize > 0)
            {
                _defaultSZX = BlockOption.EncodeSZX(defaultBlockSize);
                if (!BlockOption.ValidSZX(_defaultSZX))
                {
                    _defaultSZX = defaultBlockSize > 1024 ? 6 : BlockOption.EncodeSZX(defaultBlockSize & 0x07f0);
                    if (log.IsWarnEnabled)
                    {
                        log.Warn(String.Format("TransferLayer - Unsupported block size {0}, using {1} instead", defaultBlockSize, BlockOption.DecodeSZX(_defaultSZX)));
                    }
                }
            }
            else
            {
                // disable outgoing blockwise transfers
                _defaultSZX = -1;
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// Notice:
        /// This method is used by SendRequest and ReceiveRequest.
        /// Be careful, making changes to the status in here.
        /// </summary>
        private BlockwiseStatus FindRequestBlockStatus(Exchange exchange, Request request)
        {
            BlockwiseStatus status = exchange.RequestBlockStatus;

            if (status == null)
            {
                status                      = new BlockwiseStatus(request.ContentType);
                status.CurrentSZX           = BlockOption.EncodeSZX(_defaultBlockSize);
                exchange.RequestBlockStatus = status;
                if (log.IsDebugEnabled)
                {
                    log.Debug("There is no assembler status yet. Create and set new Block1 status: " + status);
                }
            }
            else
            {
                if (log.IsDebugEnabled)
                {
                    log.Debug("Current Block1 status: " + status);
                }
            }
            // sets a timeout to complete exchange
            PrepareBlockCleanup(exchange);
            return(status);
        }
Exemplo n.º 5
0
        /// <summary>
        /// Notice:
        /// This method is used by SendResponse and ReceiveResponse.
        /// Be careful, making changes to the status in here.
        /// </summary>
        private BlockwiseStatus FindResponseBlockStatus(Exchange exchange, Response response)
        {
            BlockwiseStatus status = exchange.ResponseBlockStatus;

            if (status == null)
            {
                int blockSize = _defaultBlockSize;
                if (response.Session != null && response.Session.IsReliable)
                {
                    blockSize = response.Session.MaxSendSize - 100;
                }
                status = new BlockwiseStatus(response.ContentType)
                {
                    CurrentSZX = BlockOption.EncodeSZX(blockSize)
                };
                exchange.ResponseBlockStatus = status;

                log.Debug(m => m("There is no blockwise status yet. Create and set new Block2 status: {0}", status));
            }
            else
            {
                log.Debug(m => m("Current Block2 status: {0}", status));
            }

            // sets a timeout to complete exchange
            PrepareBlockCleanup(exchange);

            return(status);
        }
Exemplo n.º 6
0
        public void Should_decode_szx()
        {
            var blockSize1 = BlockOption.DecodeSzx(1);
            var blockSize2 = BlockOption.DecodeSzx(3);

            Assert.AreEqual(32, blockSize1);
            Assert.AreEqual(128, blockSize2);
        }
Exemplo n.º 7
0
        public void Should_encode_szx()
        {
            var szx1 = BlockOption.EncodeSzx(16);
            var szx2 = BlockOption.EncodeSzx(1024);

            Assert.AreEqual(0, szx1);
            Assert.AreEqual(6, szx2);
        }
Exemplo n.º 8
0
        public void Should_construct_block1_option()
        {
            var option = new BlockOption(OptionNumber.Block1, 3, 1, BlockOption.EncodeSzx(128));

            Assert.AreEqual(59, ByteConverter.GetInt(option.Value));
            Assert.AreEqual(3, option.Num);
            Assert.AreEqual(1, option.M);
            Assert.AreEqual(128, BlockOption.DecodeSzx(option.Szx));
        }
Exemplo n.º 9
0
        public void Should_construct_block2_option()
        {
            var option = new BlockOption(OptionNumber.Block2, 2, 0, BlockOption.EncodeSzx(32));

            Assert.AreEqual(33, ByteConverter.GetInt(option.Value));
            Assert.AreEqual(2, option.Num);
            Assert.AreEqual(0, option.M);
            Assert.AreEqual(32, BlockOption.DecodeSzx(option.Szx));
        }
Exemplo n.º 10
0
        /// <inheritdoc/>
        public override void SendResponse(INextLayer nextLayer, Exchange exchange, Response response)
        {
            BlockOption block1 = exchange.Block1ToAck;

            if (block1 != null)
            {
                exchange.Block1ToAck = null;
            }

            if (RequiresBlockwise(exchange, response))
            {
                log.Debug(m => m("Response payload {0}/{1} requires Blockwise", response.PayloadSize, _maxMessageSize));

                BlockwiseStatus status = FindResponseBlockStatus(exchange, response);

                Response block = GetNextResponseBlock(response, status);

                if (block1 != null)
                {
                    // in case we still have to ack the last block1
                    block.SetOption(block1);
                }

                if (block.Token == null)
                {
                    block.Token = exchange.Request.Token;
                }

                if (status.Complete)
                {
                    // clean up blockwise status
                    log.Debug(m => m("Ongoing finished on first block {0}", status));
                    exchange.ResponseBlockStatus = null;
                    ClearBlockCleanup(exchange);
                }
                else
                {
                    log.Debug(m => m("Ongoing started {0}", status));
                }

                exchange.CurrentResponse = block;
                base.SendResponse(nextLayer, exchange, block);
            }
            else
            {
                if (block1 != null)
                {
                    response.SetOption(block1);
                }

                exchange.CurrentResponse = response;
                // Block1 transfer completed
                ClearBlockCleanup(exchange);
                base.SendResponse(nextLayer, exchange, response);
            }
        }
Exemplo n.º 11
0
        public static Response Simple_atomic_blockwise_put_response(int num)
        {
            var m        = num < 2 ? 1 : 0;
            var response = new Response(MessageType.Acknowledgement, CodeRegistry.Changed)
            {
                Id = 1234, Token = ByteConverter.GetBytes(0x17)
            };

            response.AddOption(new BlockOption(OptionNumber.Block1, num, m, BlockOption.EncodeSzx(128)));
            return(response);
        }
Exemplo n.º 12
0
        public TransferLayer(ILayer lowerLayer, int blockSize)
            : base(lowerLayer)
        {
            _tokenManager = new TokenManager();
            _incomplete   = new Dictionary <string, Message>();

            if (blockSize > 0)
            {
                _szx = BlockOption.EncodeSzx(blockSize);
            }
        }
Exemplo n.º 13
0
        // example 2 (figure 3): Blockwise GET with early negotiation
        public static Request Blockwise_get_with_early_negotiation(int num)
        {
            var id      = 1234 + num;
            var uri     = new Uri("coap://server/status");
            var request = new Request(CodeRegistry.Get, true)
            {
                Id = id, Uri = uri
            };

            request.AddOption(new BlockOption(OptionNumber.Block2, num, 0, BlockOption.EncodeSzx(64)));
            return(request);
        }
Exemplo n.º 14
0
        public static Response Simple_blockwise_get_block(int num)
        {
            var id    = 1234 + num;
            var m     = num < 2 ? 1 : 0;
            var block = new Response(MessageType.Acknowledgement, CodeRegistry.Content)
            {
                Id = id, Payload = new byte[128]
            };

            block.AddOption(new BlockOption(OptionNumber.Block2, num, m, BlockOption.EncodeSzx(128)));
            return(block);
        }
Exemplo n.º 15
0
 private void EarlyBlock2Negotiation(Exchange exchange, Request request)
 {
     // Call this method when a request has completely arrived (might have
     // been sent in one piece without blockwise).
     if (request.HasOption(OptionType.Block2))
     {
         BlockOption     block2  = request.Block2;
         BlockwiseStatus status2 = new BlockwiseStatus(request.ContentType, block2.NUM, block2.SZX);
         log.Debug(m => m("Request with early block negotiation " + block2 +
                          ". Create and set new Block2 status: " + status2));
         exchange.ResponseBlockStatus = status2;
     }
 }
Exemplo n.º 16
0
        /// <inheritdoc/>
        public override void SendResponse(INextLayer nextLayer, Exchange exchange, Response response)
        {
            BlockOption block1 = exchange.Block1ToAck;

            if (block1 != null)
            {
                exchange.Block1ToAck = null;
            }

            if (RequiresBlockwise(exchange, response))
            {
                // This must be a large response to a GET or POST request (PUT?)
                if (log.IsDebugEnabled)
                {
                    log.Debug("Response payload " + response.PayloadSize + "/" + _maxMessageSize + " requires Blockwise");
                }

                BlockwiseStatus status = FindResponseBlockStatus(exchange, response);

                Response block = GetNextResponseBlock(response, status);
                block.Type = response.Type; // This is only true for the first block
                if (block1 != null)         // in case we still have to ack the last block1
                {
                    block.SetOption(block1);
                }
                if (block.Token == null)
                {
                    block.Token = exchange.Request.Token;
                }

                if (response.HasOption(OptionType.Observe))
                {
                    // the ACK for the first block should acknowledge the whole notification
                    exchange.CurrentResponse = response;
                }
                else
                {
                    exchange.CurrentResponse = block;
                }
                base.SendResponse(nextLayer, exchange, block);
            }
            else
            {
                if (block1 != null)
                {
                    response.SetOption(block1);
                }
                exchange.CurrentResponse = response;
                base.SendResponse(nextLayer, exchange, response);
            }
        }
Exemplo n.º 17
0
        void SetProps(Player p, BlockProps[] scope, BlockID block, string[] args)
        {
            BlockOption opt = BlockOptions.Find(args[2]);

            if (opt == null)
            {
                Help(p); return;
            }
            string value = args.Length > 3 ? args[3] : "";

            opt.SetFunc(p, scope, block, value);
            scope[block].ChangedScope |= BlockOptions.ScopeId(scope);
            BlockOptions.ApplyChanges(scope, p.level, block, true);
        }
Exemplo n.º 18
0
 private void EarlyBlock2Negotiation(Exchange exchange, Request request)
 {
     // Call this method when a request has completely arrived (might have
     // been sent in one piece without blockwise).
     if (request.HasOption(OptionType.Block2))
     {
         BlockOption block2 = request.Block2;
         if (log.IsDebugEnabled)
         {
             log.Debug("Request demands blockwise transfer of response with option " + block2 + ". Create and set new block2 status");
         }
         BlockwiseStatus status2 = new BlockwiseStatus(request.ContentType, block2.NUM, block2.SZX);
         exchange.ResponseBlockStatus = status2;
     }
 }
Exemplo n.º 19
0
        /// <inheritdoc/>
        public override void SendRequest(INextLayer nextLayer, Exchange exchange, Request request)
        {
            //  This assumes we don't change individual options - if this is not true then we need to do a deep copy.
            exchange.PreSecurityOptions = request.GetOptions().ToList();

            if ((request.Oscoap == null) && (exchange.OscoreContext == null))
            {
                base.SendRequest(nextLayer, exchange, request);
            }
            else if (request.HasOption(OptionType.Block2) && request.Block2.NUM > 0)
            {
                // This is the case if the user has explicitly added a block option
                // for random access.
                // Note: We do not regard it as random access when the block num is
                // 0. This is because the user might just want to do early block
                // size negotiation but actually wants to receive all blocks.
                log.Debug("Request carries explicit defined block2 option: create random access blockwise status");

                BlockwiseStatus status = new BlockwiseStatus(request.ContentFormat);
                BlockOption     block2 = request.Block2;
                status.CurrentSZX     = block2.SZX;
                status.CurrentNUM     = block2.NUM;
                status.IsRandomAccess = true;
                exchange.OSCOAP_ResponseBlockStatus = status;
                base.SendRequest(nextLayer, exchange, request);
            }
            else if (RequiresBlockwise(request))
            {
                // This must be a large POST or PUT request
                log.Debug(m => m($"Request payload {request.PayloadSize}/{_maxMessageSize} requires Blockwise."));

                BlockwiseStatus status = FindRequestBlockStatus(exchange, request);
                Request         block  = GetNextRequestBlock(request, exchange.PreSecurityOptions, status);
                exchange.OscoreRequestBlockStatus = status;
                exchange.CurrentRequest           = block;

                log.Debug($"Block message to send: {block}");
                base.SendRequest(nextLayer, exchange, block);
            }
            else
            {
                exchange.CurrentRequest = request;
                base.SendRequest(nextLayer, exchange, request);
            }
        }
Exemplo n.º 20
0
 /// <inheritdoc/>
 public override void SendRequest(INextLayer nextLayer, Exchange exchange, Request request)
 {
     if ((request.Oscoap == null) && (exchange.OscoapContext == null))
     {
         base.SendRequest(nextLayer, exchange, request);
     }
     else if (request.HasOption(OptionType.Block2) && request.Block2.NUM > 0)
     {
         // This is the case if the user has explicitly added a block option
         // for random access.
         // Note: We do not regard it as random access when the block num is
         // 0. This is because the user might just want to do early block
         // size negotiation but actually wants to receive all blocks.
         if (log.IsDebugEnabled)
         {
             log.Debug("Request carries explicit defined block2 option: create random access blockwise status");
         }
         BlockwiseStatus status = new BlockwiseStatus(request.ContentFormat);
         BlockOption     block2 = request.Block2;
         status.CurrentSZX     = block2.SZX;
         status.CurrentNUM     = block2.NUM;
         status.IsRandomAccess = true;
         exchange.OSCOAP_ResponseBlockStatus = status;
         base.SendRequest(nextLayer, exchange, request);
     }
     else if (RequiresBlockwise(request))
     {
         // This must be a large POST or PUT request
         if (log.IsDebugEnabled)
         {
             log.Debug("Request payload " + request.PayloadSize + "/" + _maxMessageSize + " requires Blockwise.");
         }
         BlockwiseStatus status = FindRequestBlockStatus(exchange, request);
         Request         block  = GetNextRequestBlock(request, status);
         exchange.OSCOAP_RequestBlockStatus = status;
         exchange.CurrentRequest            = block;
         base.SendRequest(nextLayer, exchange, block);
     }
     else
     {
         exchange.CurrentRequest = request;
         base.SendRequest(nextLayer, exchange, request);
     }
 }
Exemplo n.º 21
0
        public void CanBlockUntilViewIsUpdated(BlockOption blockOption)
        {
            // arrange
            var slowView = new MongoDbViewManager <SlowView>(_mongoDatabase);

            _dispatcher.AddViewManager(slowView);

            _commandProcessor.ProcessCommand(new BitePotato("potato1", .1m));
            _commandProcessor.ProcessCommand(new BitePotato("potato1", .1m));
            _commandProcessor.ProcessCommand(new BitePotato("potato1", .1m));
            _commandProcessor.ProcessCommand(new BitePotato("potato1", .1m));

            var result = _commandProcessor.ProcessCommand(new BitePotato("potato1", 1));

            // act
            switch (blockOption)
            {
            case BlockOption.BlockOnViewManager:
                Console.WriteLine("Waiting for {0} on the view...", result.GetNewPosition());
                slowView.WaitUntilProcessed(result, TimeSpan.FromSeconds(2)).Wait();
                break;

            case BlockOption.BlockOnEventDispatcher:
                Console.WriteLine("Waiting for {0} on the dispatcher...", result.GetNewPosition());
                _dispatcher.WaitUntilProcessed <SlowView>(result, TimeSpan.FromSeconds(2)).Wait();
                break;
            }

            // assert
            var instance = slowView.Load(InstancePerAggregateRootLocator.GetViewIdFromAggregateRootId("potato1"));

            if (blockOption == BlockOption.NoBlock)
            {
                Assert.That(instance, Is.Null);
                Console.WriteLine("View instance was null, just as expected");
            }
            else
            {
                Assert.That(instance, Is.Not.Null);
                Console.WriteLine("View instance was properly updated, just as expected");
            }
        }
Exemplo n.º 22
0
        public override void Help(Player p, string message)
        {
            if (message.CaselessEq("props") || message.CaselessEq("properties"))
            {
                p.Message("&HProperties: &f{0}", BlockOptions.Options.Join(o => o.Name));
                p.Message("&HUse &T/Help BlockProps [property] &Hfor more details");
                return;
            }

            BlockOption opt = BlockOptions.Find(message);

            if (opt != null)
            {
                p.Message(opt.Help);
            }
            else
            {
                p.Message("&WUnrecognised property \"{0}\"", message);
            }
        }
Exemplo n.º 23
0
        public static Message GetBlock(this Message message, int num, int szx)
        {
            var blockSize     = BlockOption.DecodeSzx(szx);
            var payloadOffset = num * blockSize;
            var payloadLeft   = message.Payload.Length - payloadOffset;

            if (payloadLeft > 0)
            {
                var block = message is Request
                    ? (Message) new Request(message.Code, message.Type == MessageType.Confirmable)
                {
                    Id = message.Id
                }
                    : new Response(message.Type, message.Code)
                {
                    Id = message.Id
                };

                foreach (var option in message.Options)
                {
                    block.AddOption(option);
                }

                var m = blockSize < payloadLeft ? 1 : 0;

                if (m == 0)
                {
                    blockSize = payloadLeft;
                }

                var payload = new byte[blockSize];
                Buffer.BlockCopy(message.Payload, payloadOffset, payload, 0, blockSize);
                block.Payload = payload;
                var optionNumber = message is Request ? OptionNumber.Block1 : OptionNumber.Block2;
                block.AddOption(new BlockOption(optionNumber, num, m, szx));
                return(block);
            }

            return(null);
        }
Exemplo n.º 24
0
            public TransferContext(Message msg)
            {
                if (msg is Request)
                {
                    cache    = msg;
                    uriPath  = msg.UriPath;
                    uriQuery = msg.UriQuery;
                    current  = (BlockOption)msg.GetFirstOption(OptionType.Block1);
                }
                else if (msg is Response)
                {
                    msg.RequiresToken = false;
                    cache             = msg;
                    uriPath           = ((Response)msg).Request.UriPath;
                    uriQuery          = ((Response)msg).Request.UriQuery;
                    current           = (BlockOption)msg.GetFirstOption(OptionType.Block2);
                }

                if (log.IsDebugEnabled)
                {
                    log.Debug(String.Format("TransferLayer - Created new transfer context for {0}?{1}: {2}",
                                            uriPath, uriQuery, msg.SequenceKey));
                }
            }
Exemplo n.º 25
0
        private static Message GetBlock(Message msg, Int32 num, Int32 szx)
        {
            Int32 blockSize     = BlockOption.DecodeSZX(szx);
            Int32 payloadOffset = num * blockSize;
            Int32 payloadLeft   = msg.PayloadSize - payloadOffset;

            if (payloadLeft > 0)
            {
                Message block = null;
                if (msg is Request)
                {
                    block = new Request(msg.Code, msg.IsConfirmable);
                }
                else
                {
                    block = new Response(msg.Code);
                    if (num == 0 && msg.Type == MessageType.CON)
                    {
                        block.Type = MessageType.CON;
                    }
                    else
                    {
                        block.Type = msg.IsNonConfirmable ? MessageType.NON : MessageType.ACK;
                    }
                    block.ID = msg.ID;
                }

                block.PeerAddress = msg.PeerAddress;
                block.Token       = msg.Token;

                // use same options
                foreach (Option opt in msg.GetOptions())
                {
                    block.AddOption(opt);
                }

                // calculate 'more' bit
                Boolean m = blockSize < payloadLeft;
                // limit block size to size of payload left
                if (!m)
                {
                    blockSize = payloadLeft;
                }

                // copy payload block
                Byte[] blockPayload = new Byte[blockSize];
                Array.Copy(msg.Payload, payloadOffset, blockPayload, 0, blockSize);
                block.Payload = blockPayload;

                Option blockOpt = null;
                if (msg is Request)
                {
                    blockOpt = new BlockOption(OptionType.Block1, num, szx, m);
                }
                else
                {
                    blockOpt = new BlockOption(OptionType.Block2, num, szx, m);
                }
                block.SetOption(blockOpt);

                return(block);
            }
            else
            {
                return(null);
            }
        }
Exemplo n.º 26
0
        /// <inheritdoc/>
        public override void ReceiveResponse(INextLayer nextLayer, Exchange exchange, Response response)
        {
            // do not continue fetching blocks if canceled
            if (exchange.Request.IsCancelled)
            {
                // reject (in particular for Block+Observe)
                if (response.Type != MessageType.ACK)
                {
                    log.Debug("Rejecting blockwise transfer for canceled Exchange");
                    EmptyMessage rst = EmptyMessage.NewRST(response);
                    SendEmptyMessage(nextLayer, exchange, rst);
                    // Matcher sets exchange as complete when RST is sent
                }
                return;
            }

            if (!response.HasOption(OptionType.Block1) && !response.HasOption(OptionType.Block2))
            {
                // There is no block1 or block2 option, therefore it is a normal response
                exchange.Response = response;
                base.ReceiveResponse(nextLayer, exchange, response);
                return;
            }

            BlockOption block1 = response.Block1;

            if (block1 != null)
            {
                // TODO: What if request has not been sent blockwise (server error)
                log.Debug(m => m("Response acknowledges block " + block1));
                BlockwiseStatus status = exchange.RequestBlockStatus;

                if (exchange.Request.Session == null)
                {
                    exchange.Request.Session = exchange.CurrentRequest.Session;
                    if (exchange.Request.Session.IsReliable && exchange.Request.Session.MaxSendSize >= 1024)
                    {
                        status.CurrentSZX = 6;
                    }
                }

                if (!status.Complete)
                {
                    // TODO: the response code should be CONTINUE. Otherwise deliver
                    // Send next block
                    int currentSize = 1 << (4 + status.CurrentSZX);
                    int nextNum     = status.CurrentNUM + currentSize / block1.Size;
                    log.Debug(m => m("Send next block num = " + nextNum));
                    status.CurrentNUM = nextNum;
                    status.CurrentSZX = block1.SZX;
                    Request nextBlock = GetNextRequestBlock(exchange.Request, status);
                    if (exchange.Request.IsMulticast)
                    {
                        //  Multicast jumps to the Unicast address
                        exchange.Request.Destination = response.Source;
                    }
                    if (nextBlock.Token == null)
                    {
                        nextBlock.Token = response.Token; // reuse same token
                    }

                    nextBlock.RemoveOptions(OptionType.Observe);

                    exchange.CurrentRequest = nextBlock;
                    base.SendRequest(nextLayer, exchange, nextBlock);
                    // do not deliver response
                }
                else if (!response.HasOption(OptionType.Block2))
                {
                    // All request block have been acknowledged and we receive a piggy-backed
                    // response that needs no blockwise transfer. Thus, deliver it.
                    base.ReceiveResponse(nextLayer, exchange, response);
                }
                else
                {
                    log.Debug("Response has Block2 option and is therefore sent blockwise");
                }
            }

            BlockOption block2 = response.Block2;

            if (block2 != null)
            {
                BlockwiseStatus status = FindResponseBlockStatus(exchange, response);

                if (block2.NUM == status.CurrentNUM)
                {
                    // We got the block we expected :-)
                    int?obs = response.Observe;
                    if (obs.HasValue)
                    {
                        status.Observe = obs.Value;
                    }

                    //  Is the block sized as we expect it
                    int blockCount = 1;
                    int blockSize  = 1 << (block2.SZX + 4);

                    if (response.Payload != null)
                    {
                        if (block2.SZX == 7)
                        {
                            blockSize  = 1024;
                            blockCount = (response.Payload.Length + 1023) / 1024;
                        }

                        if (response.Payload.Length != blockSize * blockCount)
                        {
                            if (!block2.M)
                            {
                                if ((blockCount - 1) * blockSize >= response.Payload.Length ||
                                    response.Payload.Length >= blockSize * blockCount)
                                {
                                    //  This is problem as the body size is wrong.
                                    return;
                                }
                            }
                            else
                            {
                                //  The body size is wrong
                                return;
                            }
                        }
                    }

                    status.AddBlock(response.Payload);

                    // notify blocking progress
                    exchange.Request.FireResponding(response);

                    if (status.IsRandomAccess)
                    {
                        // The client has requested this specific block and we deliver it
                        exchange.Response = response;
                        base.ReceiveResponse(nextLayer, exchange, response);
                    }
                    else if (block2.M)
                    {
                        log.Debug("Request the next response block");
                        exchange.Complete = true;
                        exchange.Complete = false;

                        Request request = exchange.Request;
                        int     num     = block2.NUM + blockCount;
                        int     szx     = block2.SZX;
                        bool    m       = false;

                        Request block = new Request(request.Method)
                        {
                            Type        = request.Type,
                            Destination = request.IsMulticast ? response.Source : request.Destination,
                            Session     = request.Session
                        };
                        // NON could make sense over SMS or similar transports
                        block.SetOptions(request.GetOptions());
                        block.SetOption(new BlockOption(OptionType.Block2, num, szx, m));
                        // we use the same token to ease traceability (GET without Observe no longer cancels relations)
                        // block.Token = response.Token;
                        // make sure not to use Observe for block retrieval
                        block.RemoveOptions(OptionType.Observe);

                        status.CurrentNUM = num;

                        exchange.CurrentRequest = block;
                        base.SendRequest(nextLayer, exchange, block);
                    }
                    else
                    {
                        log.Debug(m => m("We have received all {0} blocks of the response. Assemble and deliver.",
                                         status.BlockCount));
                        Response assembled = new Response(response.StatusCode);
                        AssembleMessage(status, assembled, response);
                        assembled.Type = response.Type;

                        // set overall transfer RTT
                        assembled.RTT = (DateTime.Now - exchange.Timestamp).TotalMilliseconds;

                        // Check if this response is a notification
                        int observe = status.Observe;
                        if (observe != BlockwiseStatus.NoObserve)
                        {
                            assembled.AddOption(Option.Create(OptionType.Observe, observe));
                            // This is necessary for notifications that are sent blockwise:
                            // Reset block number AND container with all blocks
                            exchange.ResponseBlockStatus = null;
                        }

                        log.Debug(m => m("Assembled response: {0}", assembled));
                        exchange.Response = assembled;
                        base.ReceiveResponse(nextLayer, exchange, assembled);
                    }
                }
                else
                {
                    // ERROR, wrong block number (server error)
                    // TODO: This scenario is not specified in the draft.
                    // Currently, we reject it and cancel the request.
                    log.Warn(m => m("Wrong block number. Expected {0} but received {1}" +
                                    ". Reject response; exchange has failed.", status.CurrentNUM, block2.NUM));
                    if (response.Type == MessageType.CON)
                    {
                        EmptyMessage rst = EmptyMessage.NewRST(response);
                        base.SendEmptyMessage(nextLayer, exchange, rst);
                    }
                    exchange.Request.IsCancelled = true;
                }
            }
        }
Exemplo n.º 27
0
        /// <summary>
        /// Sending a message.
        /// </summary>
        /// <param name="msg">The message to be sent</param>
        protected override void DoSendMessage(Message msg)
        {
            int sendSZX = _defaultSZX;
            int sendNUM = 0;

            // block negotiation
            if ((msg is Response) && ((Response)msg).Request != null)
            {
                BlockOption buddyBlock = (BlockOption)((Response)msg).Request.GetFirstOption(OptionType.Block2);
                if (buddyBlock != null)
                {
                    if (buddyBlock.SZX < sendSZX)
                    {
                        sendSZX = buddyBlock.SZX;
                    }
                    sendNUM = buddyBlock.NUM;
                }
            }

            // check if transfer needs to be split up
            if (msg.PayloadSize > BlockOption.DecodeSZX(sendSZX))
            {
                // split message up using block1 for requests and block2 for responses
                Message msgBlock = GetBlock(msg, sendNUM, sendSZX);

                if (msgBlock != null)
                {
                    BlockOption block1 = (BlockOption)msgBlock.GetFirstOption(OptionType.Block1);
                    BlockOption block2 = (BlockOption)msgBlock.GetFirstOption(OptionType.Block2);

                    // only cache if blocks remaining for request
                    if ((block1 != null && block1.M) || (block2 != null && block2.M))
                    {
                        msg.SetOption(block1);
                        msg.SetOption(block2);

                        TransferContext transfer = new TransferContext(msg);
                        _outgoing[msg.SequenceKey] = transfer;

                        if (log.IsDebugEnabled)
                        {
                            log.Debug(String.Format("TransferLayer - Caching blockwise transfer for NUM {0} : {1}", sendNUM, msg.SequenceKey));
                        }
                    }
                    else
                    {
                        // must be block2 by client
                        if (log.IsDebugEnabled)
                        {
                            log.Debug(String.Format("TransferLayer - Answering block request without caching: {0} | {1}", msg.SequenceKey, block2));
                        }
                    }

                    // send block and wait for reply
                    SendMessageOverLowerLayer(msgBlock);
                }
                else
                {
                    // must be block2 by client
                    if (log.IsInfoEnabled)
                    {
                        log.Info(String.Format("TransferLayer - Rejecting initial out-of-scope request: {0} | NUM: {1}, SZX: {2} ({3} bytes), M: n/a, {4} bytes available",
                                               msg.SequenceKey, sendNUM, sendSZX, BlockOption.DecodeSZX(sendSZX), msg.PayloadSize));
                    }
                    HandleOutOfScopeError(msg.NewReply(true));
                }
            }
            else
            {
                // send complete message
                SendMessageOverLowerLayer(msg);
            }
        }
Exemplo n.º 28
0
        /// <inheritdoc/>
        public override void ReceiveRequest(INextLayer nextLayer, Exchange exchange, Request request)
        {
            if (request.HasOption(OptionType.Block1))
            {
                //  If this is a multicast address we are receiving this on, then we should ignore it
                if (request.IsMulticast)
                {
                    return;
                }

                // This must be a large POST or PUT request
                BlockOption block1 = request.Block1;
                log.Debug(m => m("Request contains block1 option {0}", block1));

                BlockwiseStatus status = FindRequestBlockStatus(exchange, request);
                if (block1.NUM == 0 && status.CurrentNUM > 0)
                {
                    // reset the blockwise transfer
                    log.Debug("Block1 num is 0, the client has restarted the blockwise transfer. Reset status.");
                    status = new BlockwiseStatus(request.ContentType);
                    exchange.RequestBlockStatus = status;
                }

                if (block1.NUM == status.CurrentNUM)
                {
                    if (request.ContentType == status.ContentFormat)
                    {
                        status.AddBlock(request.Payload);
                    }
                    else
                    {
                        Response error = Response.CreateResponse(request, StatusCode.RequestEntityIncomplete);
                        error.AddOption(new BlockOption(OptionType.Block1, block1.NUM, block1.SZX, block1.M));
                        error.SetPayload("Changed Content-Format");

                        exchange.CurrentResponse = error;
                        base.SendResponse(nextLayer, exchange, error);
                        return;
                    }

                    status.CurrentNUM += 1;
                    if (block1.M)
                    {
                        log.Debug("There are more blocks to come. Acknowledge this block.");

                        Response piggybacked = Response.CreateResponse(request, StatusCode.Continue);
                        piggybacked.AddOption(new BlockOption(OptionType.Block1, block1.NUM, block1.SZX, true));
                        piggybacked.Last = false;

                        exchange.CurrentResponse = piggybacked;
                        base.SendResponse(nextLayer, exchange, piggybacked);

                        // do not assemble and deliver the request yet
                    }
                    else
                    {
                        log.Debug("This was the last block. Deliver request");

                        // Remember block to acknowledge. TODO: We might make this a boolean flag in status.
                        exchange.Block1ToAck = block1;

                        // Block2 early negotiation
                        EarlyBlock2Negotiation(exchange, request);

                        // Assemble and deliver
                        Request assembled = new Request(request.Method);
                        AssembleMessage(status, assembled, request);

                        assembled.Session       = request.Session;
                        exchange.Request        = assembled;
                        exchange.CurrentRequest = assembled;
                        base.ReceiveRequest(nextLayer, exchange, assembled);
                    }
                }
                else
                {
                    // ERROR, wrong number, Incomplete
                    log.Warn(m => m("Wrong block number. Expected {0} but received {1}. Respond with 4.08 (Request Entity Incomplete).",
                                    status.CurrentNUM, block1.NUM));
                    Response error = Response.CreateResponse(request, StatusCode.RequestEntityIncomplete);
                    error.AddOption(new BlockOption(OptionType.Block1, block1.NUM, block1.SZX, block1.M));
                    error.SetPayload("Wrong block number");
                    exchange.CurrentResponse = error;
                    base.SendResponse(nextLayer, exchange, error);
                }
            }
            else if (exchange.Response != null && request.HasOption(OptionType.Block2))
            {
                // The response has already been generated and the client just wants
                // the next block of it
                BlockOption     block2   = request.Block2;
                Response        response = exchange.Response;
                BlockwiseStatus status   = FindResponseBlockStatus(exchange, response);
                status.CurrentNUM = block2.NUM;
                status.CurrentSZX = block2.SZX;

                Response block = GetNextResponseBlock(response, status);
                block.Token = request.Token;
                block.RemoveOptions(OptionType.Observe);

                if (status.Complete)
                {
                    // clean up blockwise status
                    log.Debug(m => m("Ongoing is complete {0}", status));
                    exchange.ResponseBlockStatus = null;
                    ClearBlockCleanup(exchange);
                }
                else
                {
                    log.Debug(m => m("Ongoing is continuing {0}", status));
                }

                exchange.CurrentResponse = block;
                base.SendResponse(nextLayer, exchange, block);
            }
            else
            {
                EarlyBlock2Negotiation(exchange, request);

                exchange.Request = request;
                base.ReceiveRequest(nextLayer, exchange, request);
            }
        }
Exemplo n.º 29
0
        /// <inheritdoc/>
        public override void ReceiveResponse(INextLayer nextLayer, Exchange exchange, Response response)
        {
            // do not continue fetching blocks if canceled
            if (exchange.Request.IsCancelled)
            {
                // reject (in particular for Block+Observe)
                if (response.Type != MessageType.ACK)
                {
                    if (log.IsDebugEnabled)
                    {
                        log.Debug("Rejecting blockwise transfer for canceled Exchange");
                    }
                    EmptyMessage rst = EmptyMessage.NewRST(response);
                    SendEmptyMessage(nextLayer, exchange, rst);
                    // Matcher sets exchange as complete when RST is sent
                }
                return;
            }

            if (!response.HasOption(OptionType.Block1) && !response.HasOption(OptionType.Block2))
            {
                // There is no block1 or block2 option, therefore it is a normal response
                exchange.Response = response;
                base.ReceiveResponse(nextLayer, exchange, response);
                return;
            }

            BlockOption block1 = response.Block1;

            if (block1 != null)
            {
                // TODO: What if request has not been sent blockwise (server error)
                if (log.IsDebugEnabled)
                {
                    log.Debug("Response acknowledges block " + block1);
                }

                BlockwiseStatus status = exchange.RequestBlockStatus;
                if (!status.Complete)
                {
                    // TODO: the response code should be CONTINUE. Otherwise deliver
                    // Send next block
                    Int32 currentSize = 1 << (4 + status.CurrentSZX);
                    Int32 nextNum     = status.CurrentNUM + currentSize / block1.Size;
                    if (log.IsDebugEnabled)
                    {
                        log.Debug("Send next block num = " + nextNum);
                    }
                    status.CurrentNUM = nextNum;
                    status.CurrentSZX = block1.SZX;
                    Request nextBlock = GetNextRequestBlock(exchange.Request, status);
                    if (nextBlock.Token == null)
                    {
                        nextBlock.Token = response.Token; // reuse same token
                    }
                    exchange.CurrentRequest = nextBlock;
                    base.SendRequest(nextLayer, exchange, nextBlock);
                    // do not deliver response
                }
                else if (!response.HasOption(OptionType.Block2))
                {
                    // All request block have been acknowledged and we receive a piggy-backed
                    // response that needs no blockwise transfer. Thus, deliver it.
                    base.ReceiveResponse(nextLayer, exchange, response);
                }
                else
                {
                    if (log.IsDebugEnabled)
                    {
                        log.Debug("Response has Block2 option and is therefore sent blockwise");
                    }
                }
            }

            BlockOption block2 = response.Block2;

            if (block2 != null)
            {
                BlockwiseStatus status = FindResponseBlockStatus(exchange, response);

                if (block2.NUM == status.CurrentNUM)
                {
                    // We got the block we expected :-)
                    status.AddBlock(response.Payload);
                    Int32?obs = response.Observe;
                    if (obs.HasValue)
                    {
                        status.Observe = obs.Value;
                    }

                    // notify blocking progress
                    exchange.Request.FireResponding(response);

                    if (status.IsRandomAccess)
                    {
                        // The client has requested this specifc block and we deliver it
                        exchange.Response = response;
                        base.ReceiveResponse(nextLayer, exchange, response);
                    }
                    else if (block2.M)
                    {
                        if (log.IsDebugEnabled)
                        {
                            log.Debug("Request the next response block");
                        }

                        Request request = exchange.Request;
                        Int32   num     = block2.NUM + 1;
                        Int32   szx     = block2.SZX;
                        Boolean m       = false;

                        Request block = new Request(request.Method);
                        // NON could make sense over SMS or similar transports
                        block.Type        = request.Type;
                        block.Destination = request.Destination;
                        block.SetOptions(request.GetOptions());
                        block.SetOption(new BlockOption(OptionType.Block2, num, szx, m));
                        // we use the same token to ease traceability (GET without Observe no longer cancels relations)
                        block.Token = response.Token;
                        // make sure not to use Observe for block retrieval
                        block.RemoveOptions(OptionType.Observe);

                        status.CurrentNUM = num;

                        exchange.CurrentRequest = block;
                        base.SendRequest(nextLayer, exchange, block);
                    }
                    else
                    {
                        if (log.IsDebugEnabled)
                        {
                            log.Debug("We have received all " + status.BlockCount + " blocks of the response. Assemble and deliver.");
                        }
                        Response assembled = new Response(response.StatusCode);
                        AssembleMessage(status, assembled, response);
                        assembled.Type = response.Type;

                        // set overall transfer RTT
                        assembled.RTT = (DateTime.Now - exchange.Timestamp).TotalMilliseconds;

                        // Check if this response is a notification
                        Int32 observe = status.Observe;
                        if (observe != BlockwiseStatus.NoObserve)
                        {
                            assembled.AddOption(Option.Create(OptionType.Observe, observe));
                            // This is necessary for notifications that are sent blockwise:
                            // Reset block number AND container with all blocks
                            exchange.ResponseBlockStatus = null;
                        }

                        if (log.IsDebugEnabled)
                        {
                            log.Debug("Assembled response: " + assembled);
                        }
                        exchange.Response = assembled;
                        base.ReceiveResponse(nextLayer, exchange, assembled);
                    }
                }
                else
                {
                    // ERROR, wrong block number (server error)
                    // TODO: This scenario is not specified in the draft.
                    // Currently, we reject it and cancel the request.
                    if (log.IsWarnEnabled)
                    {
                        log.Warn("Wrong block number. Expected " + status.CurrentNUM + " but received " + block2.NUM + ". Reject response; exchange has failed.");
                    }
                    if (response.Type == MessageType.CON)
                    {
                        EmptyMessage rst = EmptyMessage.NewRST(response);
                        base.SendEmptyMessage(nextLayer, exchange, rst);
                    }
                    exchange.Request.IsCancelled = true;
                }
            }
        }
        public void CanBlockUntilViewIsUpdated(BlockOption blockOption)
        {
            // arrange
            var slowView = new MongoDbViewManager<SlowView>(_mongoDatabase);
            _dispatcher.AddViewManager(slowView);

            _commandProcessor.ProcessCommand(new BitePotato("potato1", .1m));
            _commandProcessor.ProcessCommand(new BitePotato("potato1", .1m));
            _commandProcessor.ProcessCommand(new BitePotato("potato1", .1m));
            _commandProcessor.ProcessCommand(new BitePotato("potato1", .1m));

            var result = _commandProcessor.ProcessCommand(new BitePotato("potato1", 1));

            // act
            switch (blockOption)
            {
                case BlockOption.BlockOnViewManager:
                    Console.WriteLine("Waiting for {0} on the view...", result.GetNewPosition());
                    slowView.WaitUntilProcessed(result, TimeSpan.FromSeconds(2)).Wait();
                    break;

                case BlockOption.BlockOnEventDispatcher:
                    Console.WriteLine("Waiting for {0} on the dispatcher...", result.GetNewPosition());
                    _dispatcher.WaitUntilProcessed<SlowView>(result, TimeSpan.FromSeconds(2)).Wait();
                    break;
            }

            // assert
            var instance = slowView.Load(InstancePerAggregateRootLocator.GetViewIdFromAggregateRootId("potato1"));

            if (blockOption == BlockOption.NoBlock)
            {
                Assert.That(instance, Is.Null);
                Console.WriteLine("View instance was null, just as expected");
            }
            else
            {
                Assert.That(instance, Is.Not.Null);
                Console.WriteLine("View instance was properly updated, just as expected");
            }
        }
Exemplo n.º 31
0
        /// <inheritdoc/>
        public override void SendResponse(INextLayer nextLayer, Exchange exchange, Response response)
        {
            if ((exchange.OscoapContext == null) && (response.Oscoap == null))
            {
                base.SendResponse(nextLayer, exchange, response);
                return;
            }

            BlockOption block1 = exchange.Block1ToAck;

            if (block1 != null)
            {
                exchange.Block1ToAck = null;
            }

            if (RequiresBlockwise(exchange, response))
            {
                if (log.IsDebugEnabled)
                {
                    log.Debug("Response payload " + response.PayloadSize + "/" + _maxMessageSize + " requires Blockwise");
                }

                BlockwiseStatus status = FindResponseBlockStatus(exchange, response);

                Response block = GetNextResponseBlock(response, status);

                if (block1 != null) // in case we still have to ack the last block1
                {
                    block.SetOption(block1);
                }
                if (block.Token == null)
                {
                    block.Token = exchange.Request.Token;
                }

                if (status.Complete)
                {
                    // clean up blockwise status
                    if (log.IsDebugEnabled)
                    {
                        log.Debug("Ongoing finished on first block " + status);
                    }
                    exchange.OSCOAP_ResponseBlockStatus = null;
                    ClearBlockCleanup(exchange);
                }
                else
                {
                    if (log.IsDebugEnabled)
                    {
                        log.Debug("Ongoing started " + status);
                    }
                }

                exchange.CurrentResponse = block;
                base.SendResponse(nextLayer, exchange, block);
            }
            else
            {
                if (block1 != null)
                {
                    response.SetOption(block1);
                }
                exchange.CurrentResponse = response;
                // Block1 transfer completed
                ClearBlockCleanup(exchange);
                base.SendResponse(nextLayer, exchange, response);
            }
        }