Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
BlockReader.cs
1using System;
2using System.IO;
3using System.Runtime.ExceptionServices;
4using System.Security.Cryptography;
5using System.Text;
6using System.Threading.Tasks;
9
11{
18 public delegate Task BinaryDataReadCallback(byte[] Data, bool More, object State);
19
23 public class BlockReader : IDisposable
24 {
25 private const int BufferSize = 65536;
26
27 private readonly byte[] buffer = new byte[BufferSize];
28 private readonly byte[] signature;
29 private readonly string collectionName;
30 private BinaryDeserializer reader;
31 private BlockHeader header = null;
32 private Stream input;
33 private readonly ulong bytes;
34 private long bytesLeft;
35 private int bufPos = 0;
36 private int bufLen = 0;
37
38 private BlockReader(Stream Input, long InputLength, string CollectionName, byte[] Signature, ulong Bytes)
39 {
40 this.input = Input;
41 this.bytesLeft = InputLength;
42 this.collectionName = CollectionName;
43 this.signature = Signature;
44 this.bytes = Bytes;
45 }
46
53 public static Stream GetStream(string FileName, NeuroLedgerProvider Provider)
54 {
55 FileStream fs = null;
56 ICryptoTransform Aes = null;
57
58 try
59 {
60 fs = File.OpenRead(FileName);
61 Aes = Provider.GetAes(FileName, false);
62 return new CryptoStream(fs, Aes, CryptoStreamMode.Read);
63 }
64 catch (Exception ex)
65 {
66 fs?.Dispose();
67 Aes?.Dispose();
68
69 ExceptionDispatchInfo.Capture(ex).Throw();
70 return null;
71 }
72 }
73
79 public static async Task<BlockReader> CreateAsync(string FileName, NeuroLedgerProvider Provider)
80 {
81 FileStream fs = null;
82 ICryptoTransform Aes = null;
83 CryptoStream cs = null;
84 BlockReader Result = null;
85
86 try
87 {
88 fs = File.OpenRead(FileName);
89 Aes = Provider.GetAes(FileName, false);
90 cs = new CryptoStream(fs, Aes, CryptoStreamMode.Read);
91
92 Result = await CreateAsync(cs, Provider);
93 }
94 catch (Exception ex)
95 {
96 cs?.Dispose();
97 fs?.Dispose();
98 Aes?.Dispose();
99
100 ExceptionDispatchInfo.Capture(ex).Throw();
101 }
102
103 return Result;
104 }
105
111 public static async Task<BlockReader> CreateAsync(Stream cs, NeuroLedgerProvider Provider)
112 {
113 int CollectionLen = cs.ReadByte();
114 if (CollectionLen == 0)
115 CollectionLen = 256;
116
117 byte[] CollectionBin = new byte[CollectionLen];
118 await cs.ReadAllAsync(CollectionBin, 0, CollectionLen);
119
120 string CollectionName = Encoding.UTF8.GetString(CollectionBin);
121
122 int Bytes = 1 + CollectionLen;
123
124 int SigLen = cs.ReadByte();
125 if (SigLen == 0)
126 SigLen = 256;
127
128 byte[] Signature = new byte[SigLen];
129 await cs.ReadAllAsync(Signature, 0, SigLen);
130
131 Bytes += 1 + SigLen;
132
133 // TODO: Validate signature before processing contents of file.
134
135 byte[] ContentLen = new byte[8];
136 await cs.ReadAllAsync(ContentLen, 0, 8);
137
138 long InputLength = BitConverter.ToInt64(ContentLen, 0);
139
140 Bytes += 8;
141
142 ObjectSerializer HeaderSerializer = await Provider.GetObjectSerializerEx(typeof(BlockHeader));
143 BlockReader Result = null;
144
145 try
146 {
147 Result = new BlockReader(cs, InputLength, CollectionName, Signature, (ulong)(InputLength + Bytes));
148
149 int Len = (int)Math.Min(1024, Result.bytesLeft);
150 byte[] Bin = await Result.ReadBytesAsync(Len);
151
152 Result.reader = new BinaryDeserializer(CollectionName, Encoding.UTF8, Bin, 0);
153 Result.header = (BlockHeader)await HeaderSerializer.Deserialize(Result.reader, ObjectSerializer.TYPE_OBJECT, false);
154
155 Result.bufPos -= Bin.Length - Result.reader.Position;
156 }
157 catch (Exception ex)
158 {
159 Result?.Dispose();
160 ExceptionDispatchInfo.Capture(ex).Throw();
161 }
162
163 return Result;
164 }
165
169 public ulong Bytes => this.bytes;
170
171 private async Task<byte[]> ReadBytesAsync(int Bytes)
172 {
173 byte[] Result = new byte[Bytes];
174 int Pos = 0;
175 int i;
176
177 while (Pos < Bytes)
178 {
179 if (this.bufPos >= this.bufLen)
180 await this.ReadMore();
181
182 i = Math.Min(Bytes - Pos, this.bufLen - this.bufPos);
183 Array.Copy(this.buffer, this.bufPos, Result, Pos, i);
184 Pos += i;
185 this.bufPos += i;
186 }
187
188 return Result;
189 }
190
191 private async Task ReadMore()
192 {
193 this.bufPos = 0;
194 this.bufLen = await this.input.TryReadAllAsync(this.buffer, 0, BufferSize);
195 if (this.bufLen <= 0)
196 throw new IOException("Unable to read from block.");
197
198 this.bytesLeft -= this.bufLen;
199 if (this.bytesLeft < 0)
200 {
201 this.bufLen += (int)this.bytesLeft;
202 this.bytesLeft = 0;
203 }
204 }
205
206 private async Task<byte> ReadByteAsync()
207 {
208 if (this.bufPos >= this.bufLen)
209 await this.ReadMore();
210
211 return this.buffer[this.bufPos++];
212 }
213
217 public bool EOF
218 {
219 get
220 {
221 return (this.bytesLeft <= 0 && this.bufPos >= this.bufLen);
222 }
223 }
224
228 public BlockHeader Header => this.header;
229
233 public string CollectionName => this.collectionName;
234
238 public byte[] Signature => this.signature;
239
243 public byte[] Buffer => this.buffer;
244
248 public int BufferPosition => this.bufPos;
249
253 public void Dispose()
254 {
255 this.input?.Dispose();
256 this.input = null;
257 }
258
264 {
265 return this.ReadEntryAsync().Result;
266 }
267
272 public async Task<Entry> ReadEntryAsync()
273 {
274 byte[] Buf = await this.ReadBytesAsync(10);
275
276 EntryType EntryType = (EntryType)Buf[0];
277 long Ticks = BitConverter.ToInt64(Buf, 1);
278 DateTime Timestamp = new DateTime(Ticks, DateTimeKind.Utc);
279 int b = Buf[9];
280 int Len = b & 127;
281 int Offset = 7;
282
283 while ((b & 128) != 0)
284 {
285 b = await this.ReadByteAsync();
286 Len |= (b & 127) << Offset;
287 Offset += 7;
288 }
289
290 Buf = await this.ReadBytesAsync(Len);
291
292 return new Entry(EntryType, Timestamp, Buf);
293 }
294
295 }
296}
static async Task< BlockReader > CreateAsync(string FileName, NeuroLedgerProvider Provider)
Creates a block reader.
Definition: BlockReader.cs:79
static async Task< BlockReader > CreateAsync(Stream cs, NeuroLedgerProvider Provider)
Creates a block reader.
Definition: BlockReader.cs:111
async Task< Entry > ReadEntryAsync()
Reads an entry from the block.
Definition: BlockReader.cs:272
Entry ReadEntry()
Reads an entry from the block.
Definition: BlockReader.cs:263
static Stream GetStream(string FileName, NeuroLedgerProvider Provider)
Gets a stream to the contents of the block.
Definition: BlockReader.cs:53
bool EOF
If the current position is at the end of the file.
Definition: BlockReader.cs:218
ulong Bytes
Size of block, in bytes
Definition: BlockReader.cs:169
int BufferPosition
Position in internal buffer.
Definition: BlockReader.cs:248
void Dispose()
IDisposable.Dispose
Definition: BlockReader.cs:253
byte[] Signature
Signature of block.
Definition: BlockReader.cs:238
Represents an entry in a block or bucket file.
Definition: Entry.cs:11
Task< ObjectSerializer > GetObjectSerializerEx(object Object)
Gets the object serializer corresponding to a specific object.
Manages binary deserialization of data.
Serializes a class, taking into account attributes defined in Attributes.
virtual async Task< object > Deserialize(IDeserializer Reader, uint? DataType, bool Embedded)
Deserializes a value.
delegate Task BinaryDataReadCallback(byte[] Data, bool More, object State)
Delegate for binary data callback methods.
EntryType
Ledger entry type.
Definition: ILedgerEntry.cs:9