diff --git a/src/MultiAddressBlackList.cs b/src/MultiAddressBlackList.cs new file mode 100644 index 0000000..782ddab --- /dev/null +++ b/src/MultiAddressBlackList.cs @@ -0,0 +1,39 @@ +using Ipfs; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace PeerTalk +{ + /// + /// A sequence of filters that are not approved. + /// + /// + /// Only targets that do match a filter will pass. + /// + public class MultiAddressBlackList : ConcurrentBag, IPolicy + { + /// + public Task IsAllowedAsync(MultiAddress target, CancellationToken cancel = default(CancellationToken)) + { + return Task.FromResult(!this.Any(filter => Matches(filter, target))); + } + + bool Matches(MultiAddress filter, MultiAddress target) + { + return filter + .Protocols + .All(fp => target.Protocols.Any(tp => tp.Code == fp.Code && tp.Value == fp.Value)); + } + + /// + public async Task IsNotAllowedAsync(MultiAddress target, CancellationToken cancel = default(CancellationToken)) + { + return !await IsAllowedAsync(target, cancel).ConfigureAwait(false); + } + } +} diff --git a/src/MultiAddressWhiteList.cs b/src/MultiAddressWhiteList.cs new file mode 100644 index 0000000..e37c61f --- /dev/null +++ b/src/MultiAddressWhiteList.cs @@ -0,0 +1,43 @@ +using Ipfs; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace PeerTalk +{ + /// + /// A sequence of filters that are approved. + /// + /// + /// Only targets that are a subset of any filters will pass. If no filters are defined, then anything + /// passes. + /// + public class MultiAddressWhiteList : ConcurrentBag, IPolicy + { + /// + public Task IsAllowedAsync(MultiAddress target, CancellationToken cancel = default(CancellationToken)) + { + if (IsEmpty) + return Task.FromResult(true); + + return Task.FromResult(this.Any(filter => Matches(filter, target))); + } + + bool Matches(MultiAddress filter, MultiAddress target) + { + return filter + .Protocols + .All(fp => target.Protocols.Any(tp => tp.Code == fp.Code && tp.Value == fp.Value)); + } + + /// + public async Task IsNotAllowedAsync(MultiAddress target, CancellationToken cancel = default(CancellationToken)) + { + return !await IsAllowedAsync(target, cancel).ConfigureAwait(false); + } + } +} diff --git a/src/Swarm.cs b/src/Swarm.cs index 370ec3b..618478f 100644 --- a/src/Swarm.cs +++ b/src/Swarm.cs @@ -363,12 +363,12 @@ public bool HasPendingConnection(Peer peer) /// /// The addresses that cannot be used. /// - public BlackList BlackList { get; set; } = new BlackList(); + public MultiAddressBlackList BlackList { get; set; } = new MultiAddressBlackList(); /// /// The addresses that can be used. /// - public WhiteList WhiteList { get; set; } = new WhiteList(); + public MultiAddressWhiteList WhiteList { get; set; } = new MultiAddressWhiteList(); /// public Task StartAsync() @@ -434,8 +434,8 @@ public async Task StopAsync() listeners.Clear(); pendingConnections.Clear(); pendingRemoteConnections.Clear(); - BlackList = new BlackList(); - WhiteList = new WhiteList(); + BlackList = new MultiAddressBlackList(); + WhiteList = new MultiAddressWhiteList(); log.Debug($"Stopped {LocalPeer}"); } diff --git a/test/MultiAdressBlackListTest.cs b/test/MultiAdressBlackListTest.cs new file mode 100644 index 0000000..165677f --- /dev/null +++ b/test/MultiAdressBlackListTest.cs @@ -0,0 +1,65 @@ +using Ipfs; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace PeerTalk +{ + [TestClass] + public class MultiAddressBlackListTest + { + MultiAddress a = "/ipfs/QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3"; + MultiAddress a1 = "/ip4/127.0.0.1/ipfs/QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3"; + MultiAddress b = "/p2p/QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3"; + MultiAddress c = "/ipfs/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64"; + MultiAddress d = "/p2p/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64"; + + [TestMethod] + public async Task Allowed() + { + var policy = new MultiAddressBlackList(); + policy.Add(a); + policy.Add(b); + Assert.IsFalse(await policy.IsAllowedAsync(a)); + Assert.IsFalse(await policy.IsAllowedAsync(a1)); + Assert.IsFalse(await policy.IsAllowedAsync(b)); + Assert.IsTrue(await policy.IsAllowedAsync(c)); + Assert.IsTrue(await policy.IsAllowedAsync(d)); + } + + [TestMethod] + public async Task Allowed_Alias() + { + var policy = new MultiAddressBlackList(); + policy.Add(a); + Assert.IsFalse(await policy.IsAllowedAsync(a)); + Assert.IsFalse(await policy.IsAllowedAsync(a1)); + Assert.IsFalse(await policy.IsAllowedAsync(b)); + Assert.IsTrue(await policy.IsAllowedAsync(c)); + Assert.IsTrue(await policy.IsAllowedAsync(d)); + } + + [TestMethod] + public async Task NotAllowed() + { + var policy = new MultiAddressBlackList(); + policy.Add(a); + policy.Add(b); + Assert.IsTrue(await policy.IsNotAllowedAsync(a)); + Assert.IsTrue(await policy.IsNotAllowedAsync(a1)); + Assert.IsTrue(await policy.IsNotAllowedAsync(b)); + Assert.IsFalse(await policy.IsNotAllowedAsync(c)); + Assert.IsFalse(await policy.IsNotAllowedAsync(d)); + } + + [TestMethod] + public async Task Empty() + { + var policy = new MultiAddressBlackList(); + Assert.IsTrue(await policy.IsAllowedAsync(a)); + Assert.IsFalse(await policy.IsNotAllowedAsync(a)); + } + } +} diff --git a/test/MultiAdressWhiteListTest.cs b/test/MultiAdressWhiteListTest.cs new file mode 100644 index 0000000..e832617 --- /dev/null +++ b/test/MultiAdressWhiteListTest.cs @@ -0,0 +1,65 @@ +using Ipfs; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace PeerTalk +{ + [TestClass] + public class MultiAddressWhiteListTest + { + MultiAddress a = "/ipfs/QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3"; + MultiAddress a1 = "/ip4/127.0.0.1/ipfs/QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3"; + MultiAddress b = "/p2p/QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3"; + MultiAddress c = "/ipfs/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64"; + MultiAddress d = "/p2p/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64"; + + [TestMethod] + public async Task Allowed() + { + var policy = new MultiAddressWhiteList(); + policy.Add(a); + policy.Add(b); + Assert.IsTrue(await policy.IsAllowedAsync(a)); + Assert.IsTrue(await policy.IsAllowedAsync(a1)); + Assert.IsTrue(await policy.IsAllowedAsync(b)); + Assert.IsFalse(await policy.IsAllowedAsync(c)); + Assert.IsFalse(await policy.IsAllowedAsync(d)); + } + + [TestMethod] + public async Task Allowed_Alias() + { + var policy = new MultiAddressWhiteList(); + policy.Add(a); + Assert.IsTrue(await policy.IsAllowedAsync(a)); + Assert.IsTrue(await policy.IsAllowedAsync(a1)); + Assert.IsTrue(await policy.IsAllowedAsync(b)); + Assert.IsFalse(await policy.IsAllowedAsync(c)); + Assert.IsFalse(await policy.IsAllowedAsync(d)); + } + + [TestMethod] + public async Task NotAllowed() + { + var policy = new MultiAddressWhiteList(); + policy.Add(a); + policy.Add(b); + Assert.IsFalse(await policy.IsNotAllowedAsync(a)); + Assert.IsFalse(await policy.IsNotAllowedAsync(a1)); + Assert.IsFalse(await policy.IsNotAllowedAsync(b)); + Assert.IsTrue(await policy.IsNotAllowedAsync(c)); + Assert.IsTrue(await policy.IsNotAllowedAsync(d)); + } + + [TestMethod] + public async Task Empty() + { + var policy = new MultiAddressWhiteList(); + Assert.IsTrue(await policy.IsAllowedAsync(a)); + Assert.IsFalse(await policy.IsNotAllowedAsync(a)); + } + } +}