SecurityContextTokenCache.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / ServiceModel / System / ServiceModel / Security / SecurityContextTokenCache.cs / 1 / SecurityContextTokenCache.cs

                            //------------------------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------------------------

namespace System.ServiceModel.Security 
{
    using System; 
    using System.Collections; 
    using System.Collections.ObjectModel;
    using System.Collections.Generic; 
    using System.Runtime.InteropServices;
    using System.Threading;
    using System.Diagnostics;
    using System.ServiceModel.Diagnostics; 
    using System.ServiceModel.Security.Tokens;
    using System.Xml; 
 
    /// 
    /// This is the in-memory cache used for caching SCTs 
    /// 
    internal sealed class SecurityContextTokenCache : TimeBoundedCache
    {
        // if there are less than lowWaterMark entries, no purging is done 
        static int lowWaterMark = 50;
        // frequency of purging the cache of stale entries 
        // this is set to 10 mins as SCTs are expected to have long lifetimes 
        static TimeSpan purgingInterval = TimeSpan.FromMinutes(10);
        static double pruningFactor = 0.20; 
        bool replaceOldestEntries = true;
        static SctEffectiveTimeComparer sctEffectiveTimeComparer = new SctEffectiveTimeComparer();

        public SecurityContextTokenCache(int capacity, bool replaceOldestEntries) 
            : base(lowWaterMark, capacity, null, PurgingMode.TimerBasedPurge, purgingInterval, true)
        { 
            this.replaceOldestEntries = replaceOldestEntries; 
        }
 
        public void AddContext(SecurityContextSecurityToken token)
        {
            TryAddContext(token, true);
        } 

        public bool TryAddContext(SecurityContextSecurityToken token) 
        { 
            return TryAddContext(token, false);
        } 

        bool TryAddContext(SecurityContextSecurityToken token, bool throwOnFailure)
        {
            if (token == null) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("token"); 
            } 
            DateTime now = DateTime.UtcNow;
            if (now < token.ValidFrom || now > token.ValidTo) 
            {
                if (token.KeyGeneration == null)
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SR.GetString(SR.SecurityContextExpiredNoKeyGeneration, token.ContextId));
                else 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SR.GetString(SR.SecurityContextExpired, token.ContextId, token.KeyGeneration.ToString()));
            } 
 
            if (now < token.KeyEffectiveTime || now > token.KeyExpirationTime)
            { 
                if (token.KeyGeneration == null)
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SR.GetString(SR.SecurityContextKeyExpiredNoKeyGeneration, token.ContextId));
                else
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SR.GetString(SR.SecurityContextKeyExpired, token.ContextId, token.KeyGeneration.ToString())); 
            }
 
            object hashKey = GetHashKey(token.ContextId, token.KeyGeneration); 
            bool wasTokenAdded = base.TryAddItem(hashKey, (SecurityContextSecurityToken)token.Clone(), false);
            if (!wasTokenAdded) 
            {
                if (throwOnFailure)
                {
                    if (token.KeyGeneration == null) 
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ContextAlreadyRegisteredNoKeyGeneration, token.ContextId)));
                    else 
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ContextAlreadyRegistered, token.ContextId, token.KeyGeneration.ToString()))); 
                }
            } 
            return wasTokenAdded;
        }

        object GetHashKey(UniqueId contextId, UniqueId generation) 
        {
            if (generation == null) 
            { 
                return contextId;
            } 
            else
            {
                return new ContextAndGenerationKey(contextId, generation);
            } 
        }
 
        public void ClearContexts() 
        {
            base.ClearItems(); 
        }

        public SecurityContextSecurityToken GetContext(UniqueId contextId, UniqueId generation)
        { 
            if (contextId == null)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contextId"); 
            }
            object hashKey = GetHashKey(contextId, generation); 
            SecurityContextSecurityToken sct = (SecurityContextSecurityToken)base.GetItem(hashKey);
            return sct != null ? (SecurityContextSecurityToken)sct.Clone() : null;
        }
 
        public void RemoveContext(UniqueId contextId, UniqueId generation, bool throwIfNotPresent)
        { 
            if (contextId == null) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contextId"); 
            }
            object hashKey = GetHashKey(contextId, generation);
            if (!base.TryRemoveItem(hashKey) && throwIfNotPresent)
            { 
                if (generation == null)
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ContextNotPresentNoKeyGeneration, contextId))); 
                else 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ContextNotPresent, contextId, generation.ToString())));
            } 
        }

        ArrayList GetMatchingKeys(UniqueId contextId)
        { 
            if (contextId == null)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contextId"); 
            }
            ArrayList matchingKeys = new ArrayList(2); 

            bool lockHeld = false;
            try
            { 
                try { }
                finally 
                { 
                    base.CacheLock.AcquireReaderLock(-1);
                    lockHeld = true; 
                }
                foreach (object key in this.Entries.Keys)
                {
                    bool isMatch = false; 
                    if (key is UniqueId)
                    { 
                        isMatch = (((UniqueId)key) == contextId); 
                    }
                    else 
                    {
                        isMatch = (((ContextAndGenerationKey)key).ContextId == contextId);
                    }
                    if (isMatch) 
                    {
                        matchingKeys.Add(key); 
                    } 
                }
            } 
            finally
            {
                if (lockHeld)
                { 
                    base.CacheLock.ReleaseReaderLock();
                } 
            } 
            return matchingKeys;
        } 

        public void RemoveAllContexts(UniqueId contextId)
        {
            ArrayList matchingKeys = GetMatchingKeys(contextId); 
            for (int i = 0; i < matchingKeys.Count; ++i)
            { 
                base.TryRemoveItem(matchingKeys[i]); 
            }
 
        }

        public void UpdateContextCachingTime(SecurityContextSecurityToken token, DateTime expirationTime)
        { 
            if (token.ValidTo <= expirationTime.ToUniversalTime())
            { 
                return; 
            }
            base.TryReplaceItem(GetHashKey(token.ContextId, token.KeyGeneration), token, expirationTime); 
        }

        public Collection GetAllContexts(UniqueId contextId)
        { 
            ArrayList matchingKeys = GetMatchingKeys(contextId);
 
            Collection matchingContexts = new Collection(); 
            for (int i = 0; i < matchingKeys.Count; ++i)
            { 
                SecurityContextSecurityToken token = base.GetItem(matchingKeys[i]) as SecurityContextSecurityToken;
                if (token != null)
                {
                    matchingContexts.Add(token); 
                }
            } 
            return matchingContexts; 
        }
 
        protected override ArrayList OnQuotaReached(Hashtable cacheTable)
        {
            if (!this.replaceOldestEntries)
            { 
                SecurityTraceRecordHelper.TraceSecurityContextTokenCacheFull(this.Capacity, 0);
                return base.OnQuotaReached(cacheTable); 
            } 
            else
            { 
                List tokens = new List(cacheTable.Count);
                foreach (IExpirableItem value in cacheTable.Values)
                {
                    SecurityContextSecurityToken token = (SecurityContextSecurityToken)ExtractItem(value); 
                    tokens.Add(token);
                } 
                tokens.Sort(sctEffectiveTimeComparer); 
                int pruningAmount = (int)(((double)this.Capacity) * pruningFactor);
                pruningAmount = pruningAmount <= 0 ? this.Capacity : pruningAmount; 
                ArrayList keys = new ArrayList(pruningAmount);
                for (int i = 0; i < pruningAmount; ++i)
                {
                    keys.Add(GetHashKey(tokens[i].ContextId, tokens[i].KeyGeneration)); 
                    OnRemove(tokens[i]);
                } 
                SecurityTraceRecordHelper.TraceSecurityContextTokenCacheFull(this.Capacity, pruningAmount); 
                return keys;
            } 
        }

        sealed class SctEffectiveTimeComparer : IComparer
        { 
            public int Compare(SecurityContextSecurityToken sct1, SecurityContextSecurityToken sct2)
            { 
                if (sct1 == sct2) 
                {
                    return 0; 
                }
                if (sct1.ValidFrom.ToUniversalTime() < sct2.ValidFrom.ToUniversalTime())
                {
                    return -1; 
                }
                else if (sct1.ValidFrom.ToUniversalTime() > sct2.ValidFrom.ToUniversalTime()) 
                { 
                    return 1;
                } 
                else
                {
                    // compare the key effective times
                    if (sct1.KeyEffectiveTime.ToUniversalTime() < sct2.KeyEffectiveTime.ToUniversalTime()) 
                    {
                        return -1; 
                    } 
                    else if (sct1.KeyEffectiveTime.ToUniversalTime() > sct2.KeyEffectiveTime.ToUniversalTime())
                    { 
                        return 1;
                    }
                    else
                    { 
                        return 0;
                    } 
                } 
            }
        } 

        protected override void OnRemove(object item)
        {
            ((IDisposable)item).Dispose(); 
            base.OnRemove(item);
        } 
 
        struct ContextAndGenerationKey
        { 
            UniqueId contextId;
            UniqueId generation;

            public ContextAndGenerationKey(UniqueId contextId, UniqueId generation) 
            {
                DiagnosticUtility.DebugAssert(contextId != null && generation != null, ""); 
                this.contextId = contextId; 
                this.generation = generation;
            } 

            public UniqueId ContextId
            {
                get 
                {
                    return this.contextId; 
                } 
            }
 
            public UniqueId Generation
            {
                get
                { 
                    return this.generation;
                } 
            } 

            public override int GetHashCode() 
            {
                return this.contextId.GetHashCode() ^ this.generation.GetHashCode();
            }
 
            public override bool Equals(object obj)
            { 
                if (obj is ContextAndGenerationKey) 
                {
                    ContextAndGenerationKey key2 = ((ContextAndGenerationKey)obj); 
                    return (key2.ContextId == this.contextId && key2.Generation == this.generation);
                }
                else
                { 
                    return false;
                } 
            } 

            public static bool operator ==(ContextAndGenerationKey a, ContextAndGenerationKey b) 
            {
                if (object.ReferenceEquals(a, null))
                {
                    return object.ReferenceEquals(b, null); 
                }
 
                return (a.Equals(b)); 
            }
 
            public static bool operator !=(ContextAndGenerationKey a, ContextAndGenerationKey b)
            {
                return !(a == b);
            } 
        }
    } 
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK