Skip to content

Commit

Permalink
feat(swarm): better filtering #29
Browse files Browse the repository at this point in the history
Instead of equality compare between a filter and a multiaddres, check that filter
is a subset of the multiaddress.
  • Loading branch information
richardschneider committed Aug 19, 2019
1 parent cd37388 commit dd45333
Show file tree
Hide file tree
Showing 5 changed files with 216 additions and 4 deletions.
39 changes: 39 additions & 0 deletions src/MultiAddressBlackList.cs
Original file line number Diff line number Diff line change
@@ -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
{
/// <summary>
/// A sequence of filters that are not approved.
/// </summary>
/// <remarks>
/// Only targets that do match a filter will pass.
/// </remarks>
public class MultiAddressBlackList : ConcurrentBag<MultiAddress>, IPolicy<MultiAddress>
{
/// <inheritdoc />
public Task<bool> 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));
}

/// <inheritdoc />
public async Task<bool> IsNotAllowedAsync(MultiAddress target, CancellationToken cancel = default(CancellationToken))
{
return !await IsAllowedAsync(target, cancel).ConfigureAwait(false);
}
}
}
43 changes: 43 additions & 0 deletions src/MultiAddressWhiteList.cs
Original file line number Diff line number Diff line change
@@ -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
{
/// <summary>
/// A sequence of filters that are approved.
/// </summary>
/// <remarks>
/// Only targets that are a subset of any filters will pass. If no filters are defined, then anything
/// passes.
/// </remarks>
public class MultiAddressWhiteList : ConcurrentBag<MultiAddress>, IPolicy<MultiAddress>
{
/// <inheritdoc />
public Task<bool> 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));
}

/// <inheritdoc />
public async Task<bool> IsNotAllowedAsync(MultiAddress target, CancellationToken cancel = default(CancellationToken))
{
return !await IsAllowedAsync(target, cancel).ConfigureAwait(false);
}
}
}
8 changes: 4 additions & 4 deletions src/Swarm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -363,12 +363,12 @@ public bool HasPendingConnection(Peer peer)
/// <summary>
/// The addresses that cannot be used.
/// </summary>
public BlackList<MultiAddress> BlackList { get; set; } = new BlackList<MultiAddress>();
public MultiAddressBlackList BlackList { get; set; } = new MultiAddressBlackList();

/// <summary>
/// The addresses that can be used.
/// </summary>
public WhiteList<MultiAddress> WhiteList { get; set; } = new WhiteList<MultiAddress>();
public MultiAddressWhiteList WhiteList { get; set; } = new MultiAddressWhiteList();

/// <inheritdoc />
public Task StartAsync()
Expand Down Expand Up @@ -434,8 +434,8 @@ public async Task StopAsync()
listeners.Clear();
pendingConnections.Clear();
pendingRemoteConnections.Clear();
BlackList = new BlackList<MultiAddress>();
WhiteList = new WhiteList<MultiAddress>();
BlackList = new MultiAddressBlackList();
WhiteList = new MultiAddressWhiteList();

log.Debug($"Stopped {LocalPeer}");
}
Expand Down
65 changes: 65 additions & 0 deletions test/MultiAdressBlackListTest.cs
Original file line number Diff line number Diff line change
@@ -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));
}
}
}
65 changes: 65 additions & 0 deletions test/MultiAdressWhiteListTest.cs
Original file line number Diff line number Diff line change
@@ -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));
}
}
}

0 comments on commit dd45333

Please sign in to comment.