<commit_before>﻿/*
 * Copyright (c) 2011-2013, <NAME> <<EMAIL>>,
 * SmeshLink Technology Co.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY.
 * 
 * This file is part of the CoAP.NET, a CoAP framework in C#.
 * Please see README for more information.
 */

using System;
using System.Timers;
using CoAP.Log;
using CoAP.Util;

namespace CoAP.Layers
{
    /// <summary>
    /// This class takes care of unique tokens for each sequence of request/response exchanges.
    /// Additionally, the TokenLayer takes care of an overall timeout for each request/response exchange.
    /// </summary>
    public class TokenLayer : UpperLayer
    {
        private static readonly ILogger log = LogManager.GetLogger(typeof(TokenLayer));

        private HashMap<String, RequestResponseSequence> _exchanges = new HashMap<String, RequestResponseSequence>();
        private Int32 _sequenceTimeout;

        public TokenLayer()
            : this(CoapConstants.DefaultOverallTimeout)
        { }

        public TokenLayer(Int32 sequenceTimeout)
        {
            _sequenceTimeout = sequenceTimeout;
        }

        protected override void DoSendMessage(Message msg)
        {
            if (msg.RequiresToken)
                msg.Token = TokenManager.Instance.AcquireToken(true);

            // use overall timeout for clients (e.g., server crash after separate response ACK)
            if (msg is Request)
            {
                if (log.IsDebugEnabled)
                    log.Debug(String.Format("TokenLayer - Requesting response for {0}: {1}", msg.UriPath, msg.SequenceKey));
                AddExchange((Request)msg);
            }
            else if (msg.Code == Code.Empty)
            {
                if (log.IsDebugEnabled)
                {
                    if (msg.Type == MessageType.RST)
                        log.Debug("TokenLayer - Rejecting request: " + msg.Key);
                    else
                        log.Debug("TokenLayer - Accepting request: " + msg.Key);
                }
            }
            else
            {
                if (log.IsDebugEnabled)
                    log.Debug("TokenLayer - Responding request: " + msg.SequenceKey);
            }

            SendMessageOverLowerLayer(msg);
        }

        protected override void DoReceiveMessage(Message msg)
        {
            if (msg is Response)
            {
                Response response = (Response)msg;
                RequestResponseSequence sequence = GetExchange(msg.SequenceKey);

                if (sequence == null && response.Token.Length == 0)
                {
                    if (log.IsWarnEnabled)
                        log.Warn("TokenLayer - Remote endpoint failed to echo token: " + msg.Key);
                    
                    // TODO try to recover from peerAddress

                    // let timeout handle the problem
                    return;
                }
                else if (sequence != null)
                {
                    if (!msg.IsEmptyACK)
                    {
                        sequence.Cancel();

                        // TODO separate observe registry
                        if (msg.GetFirstOption(OptionType.Observe) == null)
                        {
                            RemoveExchange(msg.SequenceKey);
                        }
                    }

                    if (log.IsDebugEnabled)
                        log.Debug(String.Format("TokenLayer - Incoming response from {0}: {1} // RTT: {2}ms",
                            ((Response)msg).Request.UriPath, msg.SequenceKey, ((Response)msg).RTT));

                    DeliverMessage(msg);
                }
                else
                {
                    if (log.IsWarnEnabled)
                        log.Warn("TokenLayer - Dropping unexpected response: " + response.SequenceKey);
                }
            }
            else if (msg is Request)
            {
                if (log.IsDebugEnabled)
                    log.Debug("TokenLayer - Incoming request: " + msg.SequenceKey);
                DeliverMessage(msg);
            }
        }

        private RequestResponseSequence AddExchange(Request request)
        {
            // be aware when manually setting tokens, as request/response will be replace
            RemoveExchange(request.SequenceKey);

            RequestResponseSequence sequence = new RequestResponseSequence();
            sequence.key = request.SequenceKey;
            sequence.request = request;
            sequence.timeoutHandler = RequestTimeout;

            lock (_exchanges)
            {
                _exchanges[sequence.key] = sequence;
            }

            sequence.Start(_sequenceTimeout);

            if (log.IsDebugEnabled)
                log.Debug("TokenLayer - Stored new exchange: " + sequence.key);

            return sequence;
        }

        private void RemoveExchange(String key)
        {
            lock (_exchanges)
            {
                if (_exchanges.ContainsKey(key))
                {
                    RequestResponseSequence exchange = _exchanges[key];
                    _exchanges.Remove(key);
                    exchange.Cancel();
                    TokenManager.Instance.ReleaseToken(exchange.request.Token);
                    if (log.IsDebugEnabled)
                        log.Debug("TokenLayer - Cleared exchange: " + exchange.key);
                }
            }
        }

        private RequestResponseSequence GetExchange(String key)
        {
            lock (_exchanges)
            {
                return _exchanges[key];
            }<commit_msg>Only timeouts requests if sequenceTimeout gt 0 in TokenLayer<commit_after>﻿/*
 * Copyright (c) 2011-2013, <NAME> <<EMAIL>>,
 * SmeshLink Technology Co.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY.
 * 
 * This file is part of the CoAP.NET, a CoAP framework in C#.
 * Please see README for more information.
 */

using System;
using System.Timers;
using CoAP.Log;
using CoAP.Util;

namespace CoAP.Layers
{
    /// <summary>
    /// This class takes care of unique tokens for each sequence of request/response exchanges.
    /// Additionally, the TokenLayer takes care of an overall timeout for each request/response exchange.
    /// </summary>
    public class TokenLayer : UpperLayer
    {
        private static readonly ILogger log = LogManager.GetLogger(typeof(TokenLayer));

        private HashMap<String, RequestResponseSequence> _exchanges = new HashMap<String, RequestResponseSequence>();
        private Int32 _sequenceTimeout;

        public TokenLayer()
            : this(CoapConstants.DefaultOverallTimeout)
        { }

        public TokenLayer(Int32 sequenceTimeout)
        {
            _sequenceTimeout = sequenceTimeout;
        }

        protected override void DoSendMessage(Message msg)
        {
            if (msg.RequiresToken)
                msg.Token = TokenManager.Instance.AcquireToken(true);

            // use overall timeout for clients (e.g., server crash after separate response ACK)
            if (msg is Request)
            {
                if (log.IsDebugEnabled)
                    log.Debug(String.Format("TokenLayer - Requesting response for {0}: {1}", msg.UriPath, msg.SequenceKey));
                AddExchange((Request)msg);
            }
            else if (msg.Code == Code.Empty)
            {
                if (log.IsDebugEnabled)
                {
                    if (msg.Type == MessageType.RST)
                        log.Debug("TokenLayer - Rejecting request: " + msg.Key);
                    else
                        log.Debug("TokenLayer - Accepting request: " + msg.Key);
                }
            }
            else
            {
                if (log.IsDebugEnabled)
                    log.Debug("TokenLayer - Responding request: " + msg.SequenceKey);
            }

            SendMessageOverLowerLayer(msg);
        }

        protected override void DoReceiveMessage(Message msg)
        {
            if (msg is Response)
            {
                Response response = (Response)msg;
                RequestResponseSequence sequence = GetExchange(msg.SequenceKey);

                if (sequence == null && response.Token.Length == 0)
                {
                    if (log.IsWarnEnabled)
                        log.Warn("TokenLayer - Remote endpoint failed to echo token: " + msg.Key);
                    
                    // TODO try to recover from peerAddress

                    // let timeout handle the problem
                    return;
                }
                else if (sequence != null)
                {
                    if (!msg.IsEmptyACK)
                    {
                        sequence.Cancel();

                        // TODO separate observe registry
                        if (msg.GetFirstOption(OptionType.Observe) == null)
                        {
                            RemoveExchange(msg.SequenceKey);
                        }
                    }

                    if (log.IsDebugEnabled)
                        log.Debug(String.Format("TokenLayer - Incoming response from {0}: {1} // RTT: {2}ms",
                            ((Response)msg).Request.UriPath, msg.SequenceKey, ((Response)msg).RTT));

                    DeliverMessage(msg);
                }
                else
                {
                    if (log.IsWarnEnabled)
                        log.Warn("TokenLayer - Dropping unexpected response: " + response.SequenceKey);
                }
            }
            else if (msg is Request)
            {
                if (log.IsDebugEnabled)
                    log.Debug("TokenLayer - Incoming request: " + msg.SequenceKey);
                DeliverMessage(msg);
            }
        }

        private RequestResponseSequence AddExchange(Request request)
        {
            // be aware when manually setting tokens, as request/response will be replace
            RemoveExchange(request.SequenceKey);

            RequestResponseSequence sequence = new RequestResponseSequence();
            sequence.key = request.SequenceKey;
            sequence.request = request;
            sequence.timeoutHandler = RequestTimeout;

            lock (_exchanges)
            {
                _exchanges[sequence.key] = sequence;
            }

            if (_sequenceTimeout >= 0)
                sequence.Start(_sequenceTimeout);

            if (log.IsDebugEnabled)
                log.Debug("TokenLayer - Stored new exchange: " + sequence.key);

            return sequence;
        }

        private void RemoveExchange(String key)
        {
            lock (_exchanges)
            {
                if (_exchanges.ContainsKey(key))
                {
                    RequestResponseSequence exchange = _exchanges[key];
                    _exchanges.Remove(key);
                    exchange.Cancel();
                    TokenManager.Instance.ReleaseToken(exchange.request.Token);
                    if (log.IsDebugEnabled)
                        log.Debug("TokenLayer - Cleared exchange: " + exchange.key);
                }
            }
        }

        private RequestResponseSequence GetExchange(String key)
        {
            lock (_exchanges)
            {
                return _exchanges[key];
            }
{'fraction_non_alphanumeric': 0.08301360306941054, 'fraction_numerical': 0.0033135681897453785, 'mean_word_length': 1.3681602312616148, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 18, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6317681', 'n_tokens_mistral': 2765, 'n_tokens_neox': 2562, 'n_words': 671}