Skip to content

Commit 6e603e9

Browse files
1. DistributionHandler no longer responsible for storing independent list of trusted peers for data exchange, this will now be solely handled by peer channel IsTrustedPeer and PeerNetwork trust policy. Internal GET accessor changed to use LINQ to get trusted peers from ActivePeerChannels.
2. DistributionHandler slightly refactored to use memory mapped files. MemoryEntry struct simplified to be stored in dictionary. 3. New DataPayloadFormat 'MiscData' that will be stored as simple Object in MemoryEntry 4. Clarifying documentation for the DataPayloadFormat structt in DataTransmissionPacket 5. Removing default fill in `ping` behavior built into PeerChannel. Handling of trusting peers has been delegated to public delegate `DefaultTrustProtocol` which runs based on value set in IncomingPeerTrustPolicy.RunDefaultTrustProtocol. Default implementation mimics the basic `ping` behavior but will allow for more advanced logic to be implemented by overriding delegate value 6. Added BlockedIP and BlockedIdentifiers lists to IncomingPeerTrustPolicy. Default DiscernPeerChannels routine now checks these lists along with inbound peer acceptance
1 parent a4ef558 commit 6e603e9

File tree

7 files changed

+250
-224
lines changed

7 files changed

+250
-224
lines changed

P2PNet/Distribution/DistributionHandler.cs

+35-136
Original file line numberDiff line numberDiff line change
@@ -2,35 +2,30 @@
22
using P2PNet.Peers;
33
using System;
44
using System.Collections.Concurrent;
5+
using System.IO.MemoryMappedFiles;
56
using System.Text;
67
using System.Timers;
78

89
namespace P2PNet.Distribution
910
{
10-
// Data structure for entries
11-
internal record struct MemoryEntry
12-
{
13-
public int StartPosition { get; }
14-
public int Length { get; }
15-
public DataPayloadFormat DataType { get; }
16-
public string AutoGenTags {get;}
17-
public MemoryEntry(int position, int length, DataPayloadFormat datatype)
18-
{
19-
StartPosition = position;
20-
Length = length;
21-
DataType = datatype;
22-
}
23-
}
24-
2511
/// <summary>
2612
/// Provides methods and properties to handle data distribution to trusted peer channels.
2713
/// </summary>
2814
public static class DistributionHandler
2915
{
16+
internal struct MemoryEntry
17+
{
18+
string Key { get; set; }
19+
object Data { get; set; }
20+
}
21+
3022
/// <summary>
31-
/// Gets or sets the list of trusted peer channels.
23+
/// Gets the list of trusted peer channels.
3224
/// </summary>
33-
static List<PeerChannel> TrustedPeerChannels { get; set; } = new List<PeerChannel>();
25+
static List<PeerChannel> TrustedPeerChannels
26+
{
27+
get { return PeerNetwork.ActivePeerChannels.Where(pc => pc.IsTrustedPeer).ToList(); }
28+
}
3429

3530
/// <summary>
3631
/// Queue for outgoing data packets to be distributed to trusted peers.
@@ -46,16 +41,6 @@ public static class DistributionHandler
4641
private static Timer _timer;
4742
private static Timer _queueChecker;
4843

49-
50-
/// <summary>
51-
/// Adds a peer channel to the list of trusted peer channels.
52-
/// </summary>
53-
/// <param name="peerChannel">The peer channel to add.</param>
54-
public static void AddTrustedPeer(PeerChannel peerChannel)
55-
{
56-
TrustedPeerChannels.Add(peerChannel);
57-
}
58-
5944
/// <summary>
6045
/// Queues a data packet for distribution.
6146
/// </summary>
@@ -130,138 +115,52 @@ private static async void HandleIncomingDataPackets(System.Object source, Elapse
130115
switch (packet.DataType)
131116
{
132117
case DataPayloadFormat.File:
133-
MemoryHandler.LoadDataToMemory(packet);
118+
MemoryHandler.LoadFileToMemoryMappedFile(packet);
134119
break;
135120
case DataPayloadFormat.Task:
136121

137122
break;
138-
}
123+
case DataPayloadFormat.MiscData:
124+
125+
break;
126+
}
139127
}
140128
}
141129
}
142130

143131
internal static class MemoryHandler
144132
{
145-
private static Memory<byte> _data = new Memory<byte>(new byte[1024]); // change this later
146-
private static int _position = 0;
147133
private static object _lock = new object(); // For thread safety
148-
private static List<MemoryEntry> _entries = new List<MemoryEntry>();
149-
private static bool validentry = true;
150134

151-
public static async Task LoadDataToMemory(DataTransmissionPacket packet)
152-
{
153-
lock (_lock)
154-
{
155-
int startPosition = _position;
156-
int totallen = Encoding.UTF8.GetBytes(packet.Data.ToString()).Length;
157-
158-
MemoryEntry newentry = new MemoryEntry(startPosition, totallen, packet.DataType);
159-
// Resize if needed
160-
if (_data.Length - _position < packet.Data.Length)
161-
{
162-
ResizeInternalMemory(_data.Length + totallen);
163-
}
164-
165-
// Append data
166-
validentry = true;
167-
try
168-
{
169-
Encoding.UTF8.GetBytes(packet.Data.ToString()).AsSpan().CopyTo(_data.Span.Slice(_position));
170-
} catch
171-
{
172-
validentry = false;
173-
}
174-
finally
175-
{
176-
if (validentry == true)
177-
{
178-
_position += totallen; // Adjust position
135+
// memory mapped files dictionary
136+
private static readonly Dictionary<string, MemoryMappedFile> _memoryMappedFiles = new Dictionary<string, MemoryMappedFile>();
179137

180-
// Add entry
181-
_entries.Add(newentry);
138+
private static readonly Dictionary<string, MemoryEntry> _miscDataEntries = new Dictionary<string, MemoryEntry>();
182139

183-
DebugMessage($"\nLoaded {totallen} bytes into memory.\n", ConsoleColor.Magenta);
184-
185-
}
186-
}
187-
}
188-
}
189-
190-
public static async Task<byte[]> ReadDataFromMemory(int index)
191-
{
192-
lock (_lock)
193-
{
194-
if (index < 0 || index >= _entries.Count)
195-
{
196-
197-
DebugMessage($"Index out of range.\n", MessageType.Warning);
198-
199-
throw new ArgumentOutOfRangeException(nameof(index));
200-
}
201-
202-
var entry = _entries[index];
203-
return _data.Slice(entry.StartPosition, entry.Length).ToArray();
204-
}
205-
}
206-
207-
public static async Task<byte[]> ReadDataFromMemory(DataPayloadFormat dataType, string dataTag)
208-
{
140+
public static async Task LoadFileToMemoryMappedFile(DataTransmissionPacket packet)
141+
{
142+
byte[] fileData = UnwrapData(packet);
143+
string tempFileName = Path.GetTempFileName();
144+
await File.WriteAllBytesAsync(tempFileName, fileData);
145+
209146
lock (_lock)
210-
{
211-
var matchingEntry = _entries.FirstOrDefault(e => e.DataType == dataType);
212-
213-
if (matchingEntry.StartPosition == 0) // Check if entry was found
214-
{
215-
216-
DebugMessage($"Entry in memory not found.\n", MessageType.Warning);
217-
218-
}
219-
220-
return _data.Slice(matchingEntry.StartPosition, matchingEntry.Length).ToArray();
221-
}
222-
}
223-
224-
private static void ResizeInternalMemory(int newSize)
225147
{
226-
var newMemory = new Memory<byte>(new byte[newSize]);
227-
_data.Span.CopyTo(newMemory.Span);
228-
_data = newMemory;
229-
}
230-
231-
public static ReadOnlySpan<byte> Search(DataPayloadFormat datatype)
232-
{
233-
int startIndex = FindBlockStart(DataFormatTagMap[datatype].OpeningTag);
234-
if (startIndex == -1)
148+
if (!_memoryMappedFiles.ContainsKey(tempFileName))
235149
{
236-
237-
DebugMessage($"Tag not found.\n", MessageType.Warning);
238-
150+
var memoryMappedFile = MemoryMappedFile.CreateFromFile(tempFileName, FileMode.Open, tempFileName);
151+
_memoryMappedFiles[tempFileName] = memoryMappedFile;
152+
DebugMessage($"\nLoaded file into memory-mapped file.\n", ConsoleColor.Magenta);
239153
}
240-
241-
int endIndex = FindBlockEnd(startIndex + DataFormatTagMap[datatype].OpeningTag.Length);
242-
if (endIndex == -1)
154+
else
243155
{
244-
245-
DebugMessage($"Invalid data format: Missing TAGEND.\n", MessageType.Warning);
246-
247-
}
248-
249-
return _data.Span.Slice(startIndex + DataFormatTagMap[datatype].OpeningTag.Length, endIndex - startIndex - DataFormatTagMap[datatype].OpeningTag.Length);
250-
251-
// Helper to find the start of a data block
252-
int FindBlockStart(string tag)
253-
{
254-
return _data.Span.IndexOf(Encoding.UTF8.GetBytes(tag));
255-
}
256-
257-
// Helper to find the end of a data block
258-
int FindBlockEnd(int start)
259-
{
260-
return _data.Span.Slice(start).IndexOf(Encoding.UTF8.GetBytes(DataFormatTagMap[datatype].ClosingTag));
156+
DebugMessage($"\nFile is already loaded as a memory-mapped file.\n", ConsoleColor.Yellow);
261157
}
262158
}
263159
}
264160

161+
162+
}
163+
265164
private static void DistributeData(DataTransmissionPacket outgoingpacket)
266165
{
267166
string outdata = Serialize<DataTransmissionPacket>(outgoingpacket);

P2PNet/Distribution/DistributionProtocol.cs

+9-1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ public enum PacketType
4747
PureMessage,
4848
BADPACKET
4949
}
50+
/// <summary>
51+
/// Wraps the packet data with the appropriate tags for transmission through the network. This helps the receiving peer identify the packet type and data.
52+
/// </summary>
53+
/// <param name="packetType">The type of packet being readied for transmissiion through the network.</param>
54+
/// <param name="data">This should be the JSON serialized string of the packet before transmission.</param>
5055
public static void WrapPacket(PacketType packetType, ref string data)
5156
{
5257
string header = PacketTagMap[packetType].OpeningTag;
@@ -60,16 +65,19 @@ public enum DataPayloadFormat
6065
{
6166
File,
6267
Task,
68+
MiscData
6369
}
6470
public readonly static Dictionary<DataPayloadFormat, MessageTags> DataFormatTagMap = new Dictionary<DataPayloadFormat, MessageTags>()
6571
{
6672
{ DataPayloadFormat.File, new MessageTags() { OpeningTag = "<File>", ClosingTag = "</File>" } },
6773
{ DataPayloadFormat.Task, new MessageTags() { OpeningTag = "<Task>", ClosingTag = "</Task>" } },
74+
{ DataPayloadFormat.MiscData, new MessageTags() { OpeningTag = "<MiscData>", ClosingTag = "</MiscData>" } }
6875
};
6976

7077
/// <summary>
71-
/// Removes the <see cref="DataFormatTagMap"/> tags that are placed in the byte[] payload of the <see cref="DataTransmissionPacket"/>.
78+
/// Removes the <see cref="DistributionProtocol.DataFormatTagMap"/> tags that are placed in the byte[] payload of the <see cref="DataTransmissionPacket"/>.
7279
/// These tags are automatically placed upon instantiation in the constructor to help identify and handle the payload throughout its lifecycle.
80+
/// It is necessary to unwrap the data before processing it, which should be primarily done in the <see cref="DistributionHandler"/>
7381
/// </summary>
7482
/// <param name="packet">The packet whose payloads needs extracting</param>
7583
/// <returns>The payload of the packet with the opening and closing data format tags removed (ie the raw data).</returns>

P2PNet/NetworkPackets/DataTransmissionPacket.cs

+13-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ namespace P2PNet.NetworkPackets
1212
/// <summary>
1313
/// Represents a data transmission packet used for transmitting data throughout the peer-to-peer network.
1414
/// </summary>
15-
/// <remarks>This packet can be used to transmit <see cref="NetworkTask"/> and files throughout the network.</remarks>
15+
/// <remarks>This packet can be used to transmit files, data, and <see cref="NetworkTask"/> objects throughout the network.</remarks>
1616
public sealed class DataTransmissionPacket : INetworkPacket
1717
{
1818
/// <summary>
@@ -22,6 +22,18 @@ public sealed class DataTransmissionPacket : INetworkPacket
2222

2323
/// <summary>
2424
/// Gets or sets the format of the data.
25+
/// Acceptable data formats include:
26+
/// <list type="bullet">
27+
/// <item>
28+
/// <description>File - represents an in-memory file</description>
29+
/// </item>
30+
/// <item>
31+
/// <description>Task - represents a <see cref="NetworkTask"/></description>
32+
/// </item>
33+
/// <item>
34+
/// <description>MiscData - represents any other type of object or class</description>
35+
/// </item>
36+
/// </list>
2537
/// </summary>
2638
public DataPayloadFormat DataType { get; set; }
2739

0 commit comments

Comments
 (0)