root / trunk / Pithos.Network / MD5BlockCalculator.cs @ 796a7c29
History | View | Annotate | Download (2.7 kB)
1 |
using System; |
---|---|
2 |
using System.Collections.Generic; |
3 |
using System.Diagnostics; |
4 |
using System.Linq; |
5 |
using System.Security.Cryptography; |
6 |
using System.Text; |
7 |
using System.Threading; |
8 |
using System.Threading.Tasks; |
9 |
using System.Threading.Tasks.Dataflow; |
10 |
using OpenSSL.Core; |
11 |
using OpenSSL.Crypto; |
12 |
|
13 |
|
14 |
namespace Pithos.Network |
15 |
{ |
16 |
public class MD5BlockCalculator:IDisposable |
17 |
{ |
18 |
private MessageDigestContext _hasher ; |
19 |
|
20 |
private ActionBlock<Tuple<long, byte[],int>> _actionBlock; |
21 |
|
22 |
private long _currentBlock = 0; |
23 |
|
24 |
public MD5BlockCalculator(int capacity) |
25 |
{ |
26 |
var opt = new ExecutionDataflowBlockOptions {BoundedCapacity = capacity}; |
27 |
_actionBlock=new ActionBlock<Tuple<long, byte[],int>>(t=> ProcessBlock(t),opt); |
28 |
_hasher = new MessageDigestContext(MessageDigest.CreateByName("md5")); |
29 |
_hasher.Init(); |
30 |
} |
31 |
|
32 |
public MD5BlockCalculator() |
33 |
{ |
34 |
_actionBlock=new ActionBlock<Tuple<long, byte[],int>>(t=> ProcessBlock(t)); |
35 |
_hasher = new MessageDigestContext(MessageDigest.CreateByName("md5")); |
36 |
_hasher.Init(); |
37 |
} |
38 |
|
39 |
private void ProcessBlock(Tuple<long,byte[],int> tuple) |
40 |
{ |
41 |
if (tuple.Item1 == _currentBlock) |
42 |
{ |
43 |
var size = tuple.Item3; |
44 |
|
45 |
var buffer= tuple.Item2; |
46 |
if (size == buffer.Length) |
47 |
{ |
48 |
_hasher.Update(buffer); |
49 |
} |
50 |
else |
51 |
{ |
52 |
var block = new byte[size]; |
53 |
Buffer.BlockCopy(buffer, 0, block, 0, size); |
54 |
_hasher.Update(block); |
55 |
} |
56 |
Interlocked.Increment(ref _currentBlock); |
57 |
} |
58 |
else |
59 |
{ |
60 |
_actionBlock.Post(tuple); |
61 |
} |
62 |
} |
63 |
|
64 |
public void PostBlock(long blockIndex,byte[] buffer,int size) |
65 |
{ |
66 |
_actionBlock.Post(Tuple.Create(blockIndex, buffer, size)); |
67 |
} |
68 |
|
69 |
public async Task<string> GetHash() |
70 |
{ |
71 |
_actionBlock.Complete(); |
72 |
await _actionBlock.Completion; |
73 |
Debug.Assert(_actionBlock.InputCount == 0); |
74 |
var hashBytes=_hasher.DigestFinal(); |
75 |
var hash=hashBytes.ToHashString(); |
76 |
return hash; |
77 |
} |
78 |
|
79 |
public void Dispose() |
80 |
{ |
81 |
Dispose(true); |
82 |
GC.SuppressFinalize(this); |
83 |
} |
84 |
|
85 |
protected virtual void Dispose(bool disposing) |
86 |
{ |
87 |
if (disposing && _hasher!=null) |
88 |
_hasher.Dispose(); |
89 |
_hasher = null; |
90 |
} |
91 |
} |
92 |
} |