Пример #1
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);
            }
        }
Пример #2
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);
            }
        }
Пример #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;
            }
        }