private void SaveDigestContext(NTAuthentication digestContext)
{
if (_savedDigests == null)
{
Interlocked.CompareExchange<DigestContext[]>(ref _savedDigests, new DigestContext[MaximumDigests], null);
}
// We want to actually close the contexts outside the lock.
NTAuthentication oldContext = null;
ArrayList digestsToClose = null;
lock (_savedDigests)
{
// If we're stopped, just throw it away.
if (!IsListening)
{
digestContext.CloseContext();
return;
}
int now = ((now = Environment.TickCount) == 0 ? 1 : now);
_newestContext = (_newestContext + 1) & (MaximumDigests - 1);
int oldTimestamp = _savedDigests[_newestContext].timestamp;
oldContext = _savedDigests[_newestContext].context;
_savedDigests[_newestContext].timestamp = now;
_savedDigests[_newestContext].context = digestContext;
// May need to move this up.
if (_oldestContext == _newestContext)
{
_oldestContext = (_newestContext + 1) & (MaximumDigests - 1);
}
// Delete additional contexts older than five minutes.
while (unchecked(now - _savedDigests[_oldestContext].timestamp) >= DigestLifetimeSeconds && _savedDigests[_oldestContext].context != null)
{
if (digestsToClose == null)
{
digestsToClose = new ArrayList();
}
digestsToClose.Add(_savedDigests[_oldestContext].context);
_savedDigests[_oldestContext].context = null;
_oldestContext = (_oldestContext + 1) & (MaximumDigests - 1);
}
// If the old context is younger than 10 seconds, put it in the backup pile.
if (oldContext != null && unchecked(now - oldTimestamp) <= MinimumDigestLifetimeSeconds * 1000)
{
// Use a two-tier ArrayList system to guarantee each entry lives at least 10 seconds.
if (_extraSavedDigests == null ||
unchecked(now - _extraSavedDigestsTimestamp) > MinimumDigestLifetimeSeconds * 1000)
{
digestsToClose = _extraSavedDigestsBaking;
_extraSavedDigestsBaking = _extraSavedDigests;
_extraSavedDigestsTimestamp = now;
_extraSavedDigests = new ArrayList();
}
_extraSavedDigests.Add(oldContext);
oldContext = null;
}
}
if (oldContext != null)
{
oldContext.CloseContext();
}
if (digestsToClose != null)
{
for (int i = 0; i < digestsToClose.Count; i++)
{
((NTAuthentication)digestsToClose[i]).CloseContext();
}
}
}