Skip to content

Commit

Permalink
Migrate SignalR feature into WebHost (#121)
Browse files Browse the repository at this point in the history
* Migrate SignalR feature into WebHost

- Migrate the SignalR feature into WebHost.
- Further refactor WebHost from "Api" to "WebHost.
- Remove the versioning support from REST API.
- Enable flags to enable/disable UI, API and WS.
- Generate and include XML documentation in the REST API for all features.
- Add a basic example on Web Socket listener.

* Improve the Web Socket event handling

- Return the EventBase directly to Web Socket consumers.
- Remove unused code.
- Remove references in WebHost project.

* created a class to handle swagger api documentation xml file inclusion.

* Fix issue with exceptions during type loading

- Move the Assembly extension from Swagger scaffolding to Utilities.
- Minor bug discovered in dispose when object is null (happened during an integration test).

* Rename WebHost to NodeHost

- Next commit will rename the physical folder.

* Rename WebHost folder to NodeHost

- Updates all references, etc. from WebHost to NodeHost.

* Removing the dependency on a static service provider

* Remove the Hash and Height

- We're returning the whole object in the evernt, no longer needed to read out hash and height.

* Revert "Remove the Hash and Height"

This reverts commit 4f8af1b.

* Move the resolving of HubContext so it only runs when WS is enabled

- Minor cleanup of events, removing older properties.

* Remove hardcoded URL to JS and WS endpoints

- Update to use relative path when hosted on the NodeHost.
- Add JsonIgnore on objects that can't serialize. This needs to be added to more.

* Handle serialization of IPAddress, add ignore on structures that crash node

- Certain types will crash the node when sent to the Web Socket consumer.
- Beware of this issue in the future when working on the event types.
- Remove the EventType and instead only have EventName.

* Fix dependency issue for broadcasters when no IEventsSubscriptionService is registered

- When using the node without .UseWebHost, no implementation of IEventsSubscriptionService is registered. This fixes the broadcasters by handling them as empty if one is not provided.

* Update InitialBlockDownloadState.cs

- Reverted the changes to check for nulls on IBD check.

Co-authored-by: Mithril Man <red.angel@libero.it>
Co-authored-by: dangershony <dan.gershony@gmail.com>
  • Loading branch information
3 people authored May 14, 2020
1 parent 9db4d40 commit 7917a2f
Show file tree
Hide file tree
Showing 138 changed files with 6,130 additions and 1,402 deletions.
11 changes: 2 additions & 9 deletions src/Blockcore.sln
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Blockcore.Tests", "Tests\Bl
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "External", "External", "{1B9A916F-DDAC-4675-B424-EDEDC1A58231}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Blockcore.Features.WebHost.Tests", "Tests\Blockcore.Features.WebHost.Tests\Blockcore.Features.WebHost.Tests.csproj", "{E538B76A-513F-46D5-9F14-E35E79B484CA}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Blockcore.Features.NodeHost.Tests", "Tests\Blockcore.Features.NodeHost.Tests\Blockcore.Features.NodeHost.Tests.csproj", "{E538B76A-513F-46D5-9F14-E35E79B484CA}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Blockcore.Features.RPC", "Features\Blockcore.Features.RPC\Blockcore.Features.RPC.csproj", "{5E0010F1-50B8-4FC5-A9C2-38D7DF73A0D2}"
EndProject
Expand Down Expand Up @@ -39,7 +39,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{EAE139C2
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Features", "Features", "{15D29FFD-6142-4DC5-AFFD-10BA0CA55C45}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Blockcore.Features.WebHost", "Features\Blockcore.Features.WebHost\Blockcore.Features.WebHost.csproj", "{FB78D861-F3DF-412D-8A3D-D1756ADA39D4}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Blockcore.Features.NodeHost", "Features\Blockcore.Features.NodeHost\Blockcore.Features.NodeHost.csproj", "{FB78D861-F3DF-412D-8A3D-D1756ADA39D4}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NBitcoin", "External\NBitcoin\NBitcoin.csproj", "{2051FCAC-D4C7-498D-B935-2E9E6DEA0C29}"
EndProject
Expand All @@ -63,8 +63,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Blockcore.Features.ColdStak
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Blockcore.Features.ColdStaking.Tests", "Tests\Blockcore.Features.ColdStaking.Tests\Blockcore.Features.ColdStaking.Tests.csproj", "{0FE19EFE-98D7-4243-A8CC-30BCFFFC4499}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Blockcore.Features.SignalR", "Features\Blockcore.Features.SignalR\Blockcore.Features.SignalR.csproj", "{6BBFFE59-0597-4ADA-A592-CED25C05C01A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Blockcore.Features.Diagnostic", "Features\Blockcore.Features.Diagnostic\Blockcore.Features.Diagnostic.csproj", "{53209209-7239-4FEB-BE8D-B2DF6145BBDA}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StratisD", "Networks\Stratis\Stratisd\StratisD.csproj", "{B69D6038-8731-4DF3-9D93-3045C77CBDE6}"
Expand Down Expand Up @@ -235,10 +233,6 @@ Global
{0FE19EFE-98D7-4243-A8CC-30BCFFFC4499}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0FE19EFE-98D7-4243-A8CC-30BCFFFC4499}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0FE19EFE-98D7-4243-A8CC-30BCFFFC4499}.Release|Any CPU.Build.0 = Release|Any CPU
{6BBFFE59-0597-4ADA-A592-CED25C05C01A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6BBFFE59-0597-4ADA-A592-CED25C05C01A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6BBFFE59-0597-4ADA-A592-CED25C05C01A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6BBFFE59-0597-4ADA-A592-CED25C05C01A}.Release|Any CPU.Build.0 = Release|Any CPU
{53209209-7239-4FEB-BE8D-B2DF6145BBDA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{53209209-7239-4FEB-BE8D-B2DF6145BBDA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{53209209-7239-4FEB-BE8D-B2DF6145BBDA}.Release|Any CPU.ActiveCfg = Release|Any CPU
Expand Down Expand Up @@ -334,7 +328,6 @@ Global
{A8EDFB26-17B5-48C0-BF38-E521EF5476E4} = {EAE139C2-B19C-4905-9117-8A4068ABD3D2}
{072C5F7C-4B75-46C9-A54D-774DA77ED1D1} = {15D29FFD-6142-4DC5-AFFD-10BA0CA55C45}
{0FE19EFE-98D7-4243-A8CC-30BCFFFC4499} = {EAE139C2-B19C-4905-9117-8A4068ABD3D2}
{6BBFFE59-0597-4ADA-A592-CED25C05C01A} = {15D29FFD-6142-4DC5-AFFD-10BA0CA55C45}
{53209209-7239-4FEB-BE8D-B2DF6145BBDA} = {15D29FFD-6142-4DC5-AFFD-10BA0CA55C45}
{B69D6038-8731-4DF3-9D93-3045C77CBDE6} = {0F6F0DC5-EC62-465B-8FC7-F24449CD7359}
{221FF9A3-4BE5-44CB-91C8-885EFE06CB2E} = {78DF115B-2471-41C3-8D9C-360720855CF5}
Expand Down
7 changes: 5 additions & 2 deletions src/Blockcore/Base/BaseFeature.cs
Original file line number Diff line number Diff line change
Expand Up @@ -311,8 +311,11 @@ private void StartAddressManager(NetworkPeerConnectionParameters connectionParam
/// <inheritdoc />
public override void Dispose()
{
this.logger.LogInformation("Flushing peers.");
this.flushAddressManagerLoop.Dispose();
if (this.flushAddressManagerLoop != null)
{
this.logger.LogInformation("Flushing peers.");
this.flushAddressManagerLoop.Dispose();
}

this.logger.LogInformation("Disposing peer address manager.");
this.peerAddressManager.Dispose();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,50 +1,55 @@
using System;
using System.Collections.Generic;
using Blockcore.AsyncWork;
using Blockcore.EventBus;
using Blockcore.Utilities;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Logging;

namespace Blockcore.Features.SignalR.Broadcasters
namespace Blockcore.Broadcasters
{
/// <summary>
/// Base class for all SignalR Broadcasters
/// Base class for all Web Socket Broadcasters
/// </summary>
public abstract class ClientBroadcasterBase : IClientEventBroadcaster
{
private readonly EventsHub eventsHub;
private readonly IEventsSubscriptionService eventsHub;
private readonly INodeLifetime nodeLifetime;
private readonly IAsyncProvider asyncProvider;
protected readonly ILogger logger;
private IAsyncLoop asyncLoop;
protected readonly ILogger log;

protected ClientBroadcasterBase(
EventsHub eventsHub,
ILoggerFactory loggerFactory,
INodeLifetime nodeLifetime,
IAsyncProvider asyncProvider)
IAsyncProvider asyncProvider,
IEventsSubscriptionService subscriptionService = null
)
{
this.eventsHub = eventsHub;
this.eventsHub = subscriptionService;
this.nodeLifetime = nodeLifetime;
this.asyncProvider = asyncProvider;
this.logger = loggerFactory.CreateLogger(this.GetType().FullName);
this.log = loggerFactory.CreateLogger(this.GetType().FullName);
}

public void Init(ClientEventBroadcasterSettings broadcasterSettings)
{
this.logger.LogDebug($"Initialising SignalR Broadcaster {this.GetType().Name}");
this.log.LogDebug($"Initialising Web Socket Broadcaster {this.GetType().Name}");

this.asyncLoop = this.asyncProvider.CreateAndRunAsyncLoop(
$"Broadcast {this.GetType().Name}",
async token =>
{
foreach (IClientEvent clientEvent in this.GetMessages())
foreach (EventBase clientEvent in this.GetMessages())
{
await this.eventsHub.SendToClientsAsync(clientEvent).ConfigureAwait(false);
this.eventsHub.OnEvent(clientEvent);
}
},
this.nodeLifetime.ApplicationStopping,
repeatEvery: TimeSpan.FromSeconds(Math.Max(broadcasterSettings.BroadcastFrequencySeconds, 5)));
repeatEvery: TimeSpan.FromSeconds(Math.Max(broadcasterSettings.BroadcastFrequencySeconds, 5)),
startAfter: TimeSpans.FiveSeconds);
}

protected abstract IEnumerable<IClientEvent> GetMessages();
protected abstract IEnumerable<EventBase> GetMessages();
}
}
7 changes: 7 additions & 0 deletions src/Blockcore/Broadcasters/ClientEventBroadcasterSettings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Blockcore.Broadcasters
{
public class ClientEventBroadcasterSettings
{
public int BroadcastFrequencySeconds { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
namespace Blockcore.Features.SignalR
using Microsoft.AspNetCore.SignalR;

namespace Blockcore.Broadcasters
{
public interface IClientEventBroadcaster
{
Expand Down
22 changes: 22 additions & 0 deletions src/Blockcore/Broadcasters/IEventsSubscriptionService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System.Threading.Tasks;
using Blockcore.Broadcasters;
using Blockcore.EventBus;
using Microsoft.AspNetCore.SignalR;

namespace Blockcore.Broadcasters
{
public interface IEventsSubscriptionService
{
void Init();

void Subscribe(string id, string name);

void Unsubscribe(string id, string name);

void UnsubscribeAll(string id);

void OnEvent(EventBase @event);

void SetHub<T>(IHubContext<T> hubContext) where T : Hub;
}
}
7 changes: 0 additions & 7 deletions src/Blockcore/Configuration/NodeSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,6 @@ public class NodeSettings : IDisposable
/// </summary>
public FeeRate MinRelayTxFeeRate { get; private set; }

/// <summary>
/// If true then the node will add and start the SignalR feature.
/// </summary>
public bool EnableSignalR { get; private set; }

/// <summary>
/// Initializes a new instance of the object.
/// </summary>
Expand Down Expand Up @@ -233,8 +228,6 @@ public NodeSettings(Network network = null, ProtocolVersion protocolVersion = Su
this.ReadConfigurationFile();
}

this.EnableSignalR = this.ConfigReader.GetOrDefault<bool>("enableSignalR", false, this.Logger);

// Create the custom logger factory.
this.LoggerFactory.AddFilters(this.Log, this.DataFolder);

Expand Down
11 changes: 11 additions & 0 deletions src/Blockcore/EventBus/CoreEvents/BlockConnected.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using Blockcore.Primitives;
using NBitcoin;
using Newtonsoft.Json;

namespace Blockcore.EventBus.CoreEvents
{
Expand All @@ -8,11 +10,20 @@ namespace Blockcore.EventBus.CoreEvents
/// <seealso cref="EventBase" />
public class BlockConnected : EventBase
{
[JsonIgnore]
public ChainedHeaderBlock ConnectedBlock { get; }

public uint256 Hash { get; set; }

public int Height { get; set; }

public BlockConnected(ChainedHeaderBlock connectedBlock)
{
this.ConnectedBlock = connectedBlock;

this.Hash = this.ConnectedBlock.ChainedHeader.HashBlock;

this.Height = this.ConnectedBlock.ChainedHeader.Height;
}
}
}
11 changes: 11 additions & 0 deletions src/Blockcore/EventBus/CoreEvents/BlockDisconnected.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using Blockcore.Primitives;
using NBitcoin;
using Newtonsoft.Json;

namespace Blockcore.EventBus.CoreEvents
{
Expand All @@ -8,11 +10,20 @@ namespace Blockcore.EventBus.CoreEvents
/// <seealso cref="EventBase" />
public class BlockDisconnected : EventBase
{
[JsonIgnore]
public ChainedHeaderBlock DisconnectedBlock { get; }

public uint256 Hash { get; set; }

public int Height { get; set; }

public BlockDisconnected(ChainedHeaderBlock disconnectedBlock)
{
this.DisconnectedBlock = disconnectedBlock;

this.Hash = this.DisconnectedBlock.ChainedHeader.HashBlock;

this.Height = this.DisconnectedBlock.ChainedHeader.Height;
}
}
}
1 change: 1 addition & 0 deletions src/Blockcore/EventBus/CoreEvents/Peer/PeerEventBase.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Net;
using Newtonsoft.Json;

namespace Blockcore.EventBus.CoreEvents.Peer
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Net;
using Blockcore.P2P.Protocol;
using Newtonsoft.Json;

namespace Blockcore.EventBus.CoreEvents.Peer
{
Expand All @@ -14,6 +15,7 @@ public class PeerMessageSendFailure : PeerEventBase
/// </value>
public Message Message { get; }

[JsonIgnore]
public System.Exception Exception { get; }

public PeerMessageSendFailure(IPEndPoint peerEndPoint, Message message, System.Exception exception) : base(peerEndPoint)
Expand Down
3 changes: 2 additions & 1 deletion src/Blockcore/EventBus/CoreEvents/TransactionReceived.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using NBitcoin;
using System;
using NBitcoin;

namespace Blockcore.EventBus.CoreEvents
{
Expand Down
7 changes: 3 additions & 4 deletions src/Blockcore/EventBus/EventBase.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
using System;
using Blockcore.Broadcasters;

namespace Blockcore.EventBus
{
/// <summary>
/// Basic abstract implementation of <see cref="IEvent"/>.
/// </summary>
/// <seealso cref="Blockcore.EventBus.IEvent" />
public abstract class EventBase
{
public Guid CorrelationId { get; }
Expand All @@ -20,5 +17,7 @@ public override string ToString()
{
return $"{this.CorrelationId.ToString()} - {this.GetType().Name}";
}

public string EventName { get { return this.GetType().Name.ToLowerInvariant(); } }
}
}
6 changes: 6 additions & 0 deletions src/Blockcore/EventBus/InMemoryEventBus.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,18 +87,24 @@ public void Unsubscribe(SubscriptionToken subscriptionToken)
public void Publish<TEvent>(TEvent @event) where TEvent : EventBase
{
if (@event == null)
{
throw new ArgumentNullException(nameof(@event));
}

List<ISubscription> allSubscriptions = new List<ISubscription>();

lock (this.subscriptionsLock)
{
if (this.subscriptions.ContainsKey(typeof(TEvent)))
{
allSubscriptions = this.subscriptions[typeof(TEvent)].ToList();
}
}

for (var index = 0; index < allSubscriptions.Count; index++)
{
var subscription = allSubscriptions[index];

try
{
subscription.Publish(@event);
Expand Down
26 changes: 26 additions & 0 deletions src/Blockcore/Utilities/Extensions/AssemblyExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;

namespace Blockcore.Utilities.Extensions
{
public static class AssemblyExtensions
{
/// <summary>
/// Gets the loadable types, ignoring assembly that can't be loaded for any reason.
/// </summary>
public static IEnumerable<Type> GetLoadableTypes(this Assembly assembly)
{
try
{
return assembly.GetTypes();
}
catch (ReflectionTypeLoadException e)
{
return e.Types.Where(t => t != null);
}
}
}
}
26 changes: 26 additions & 0 deletions src/Blockcore/Utilities/JsonConverters/IPAddressConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.Text;
using Newtonsoft.Json;

namespace Blockcore.Utilities.JsonConverters
{
public class IPAddressConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(IPAddress));
}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.WriteValue(value.ToString());
}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
return IPAddress.Parse((string)reader.Value);
}
}
}
2 changes: 2 additions & 0 deletions src/Blockcore/Utilities/JsonConverters/Serializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ public static void RegisterFrontConverters(JsonSerializerSettings settings, Netw
settings.Converters.Add(new TxDestinationJsonConverter());
settings.Converters.Add(new LockTimeJsonConverter());
settings.Converters.Add(new BitcoinStringJsonConverter(network));
settings.Converters.Add(new IPAddressConverter());
settings.Converters.Add(new IPEndPointConverter());

settings.ContractResolver = new CamelCasePropertyNamesContractResolver();
}
Expand Down
1 change: 1 addition & 0 deletions src/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
<PackageIcon></PackageIcon>
<PackageIconUrl>https://www.blockcore.net/assets/blockcore-256x256.png</PackageIconUrl>
<PackageTags>blockchain;cryptocurrency;crypto;C#;.NET;bitcoin;blockcore</PackageTags>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>

<Target Name="AddInternalsVisibleTo" BeforeTargets="CoreCompile">
Expand Down
Loading

0 comments on commit 7917a2f

Please sign in to comment.