1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
using System;
using System.Collections.Generic;
using System.Threading;
namespace TwoStepsAuthenticator
{
public class UsedCodesManager : IUsedCodesManager
{
internal sealed class UsedCode
{
public UsedCode(long timestamp, String code, object user)
{
this.UseDate = DateTime.Now;
this.Code = code;
this.Timestamp = timestamp;
this.User = user;
}
internal DateTime UseDate { get; private set; }
internal long Timestamp { get; private set; }
internal String Code { get; private set; }
internal object User { get; private set; }
public override bool Equals(object obj)
{
if (Object.ReferenceEquals(this, obj))
{
return true;
}
var other = obj as UsedCode;
return (other != null) && this.Code.Equals(other.Code) && this.Timestamp.Equals(other.Timestamp) && this.User.Equals(other.User);
}
public override string ToString()
{
return String.Format("{0}: {1}", Timestamp, Code);
}
public override int GetHashCode()
{
return Code.GetHashCode() + (Timestamp.GetHashCode() + User.GetHashCode() * 17) * 17;
}
}
private readonly Queue<UsedCode> codes;
private readonly System.Threading.ReaderWriterLockSlim rwlock = new System.Threading.ReaderWriterLockSlim();
private readonly Timer cleaner;
public UsedCodesManager()
{
codes = new Queue<UsedCode>();
var delay = (int)TimeSpan.FromMinutes(5).TotalMilliseconds;
cleaner = new Timer(cleaner_Elapsed, null, delay, delay);
}
void cleaner_Elapsed(object state)
{
var timeToClean = DateTime.Now.AddMinutes(-5);
try
{
rwlock.EnterWriteLock();
while (codes.Count > 0 && codes.Peek().UseDate < timeToClean)
{
codes.Dequeue();
}
}
finally
{
rwlock.ExitWriteLock();
}
}
public void AddCode(long timestamp, String code, object user)
{
try
{
rwlock.EnterWriteLock();
codes.Enqueue(new UsedCode(timestamp, code, user));
}
finally
{
rwlock.ExitWriteLock();
}
}
public bool IsCodeUsed(long timestamp, String code, object user)
{
try
{
rwlock.EnterWriteLock();
return codes.Contains(new UsedCode(timestamp, code, user));
}
finally
{
rwlock.ExitWriteLock();
}
}
}
}
|