Skip to content

Commit

Permalink
feat: add base tbc functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
rdavisau committed Feb 15, 2021
1 parent 94bea87 commit 70da01e
Show file tree
Hide file tree
Showing 69 changed files with 2,524 additions and 0 deletions.
56 changes: 56 additions & 0 deletions src/components/tbc.core/Protos/asm.proto
@@ -0,0 +1,56 @@
syntax = "proto3";

option csharp_namespace = "Tbc.Protocol";

package inject;

service AssemblyLoader {
rpc LoadAssembly (LoadDynamicAssemblyRequest) returns (Outcome);
rpc Exec (ExecuteCommandRequest) returns (Outcome);

rpc SynchronizeDependencies(CachedAssemblyState) returns (stream AssemblyReference);
rpc RequestCommand(Unit) returns (stream ExecuteCommandRequest);
}

message CachedAssemblyState
{
repeated CachedAssembly cachedAssemblies = 1;
}

message CachedAssembly
{
string assemblyName = 1;
uint64 modificationTime = 2;
}

message Outcome {
bool success = 1;
repeated Message messages = 2;
}

message Message {
string message = 1;
}

message AssemblyReference
{
string assemblyName = 1;
string assemblyLocation = 2;
uint64 modificationTime = 3;
bytes peBytes = 4;
}

message LoadDynamicAssemblyRequest {
bytes peBytes = 1;
bytes pdbBytes = 2;
string assemblyName = 3;
string primaryTypeName = 4;
}

message ExecuteCommandRequest {
string command = 1;
repeated string args = 2;
}

message Unit {
}
15 changes: 15 additions & 0 deletions src/components/tbc.core/tbc.core.csproj
@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<RootNamespace>Tbc.Core</RootNamespace>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Google.Protobuf" Version="3.12.3" />
<PackageReference Include="Grpc.Core" Version="2.30.0" />
<PackageReference Include="Grpc.Tools" Version="2.30.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.6.0" />
</ItemGroup>

</Project>
14 changes: 14 additions & 0 deletions src/components/tbc.host/Components/Abstractions/ComponentBase.cs
@@ -0,0 +1,14 @@
using Microsoft.Extensions.Logging;

namespace Tbc.Host.Components.Abstractions
{
public abstract class ComponentBase { }

public abstract class ComponentBase<T> : GenericComponentBase<T>
{
protected ComponentBase(ILogger<T> logger) : base(logger)
{
}
}

}
@@ -0,0 +1,14 @@
using Microsoft.Extensions.Logging;

namespace Tbc.Host.Components.Abstractions
{
public abstract class GenericComponentBase<T> : ComponentBase
{
protected ILogger<T> Logger { get; }

protected GenericComponentBase(ILogger<T> logger)
{
Logger = logger;
}
}
}
9 changes: 9 additions & 0 deletions src/components/tbc.host/Components/Abstractions/IHost.cs
@@ -0,0 +1,9 @@
using System.Threading.Tasks;

namespace Tbc.Host.Components.Abstractions
{
public interface IHost
{
Task Run();
}
}
@@ -0,0 +1,4 @@
namespace Tbc.Host.Components.Abstractions
{
public interface ITransientComponent { }
}
@@ -0,0 +1,11 @@
using Microsoft.Extensions.Logging;

namespace Tbc.Host.Components.Abstractions
{
public abstract class TransientComponentBase<T> : GenericComponentBase<T>, ITransientComponent
{
protected TransientComponentBase(ILogger<T> logger) : base(logger)
{
}
}
}
@@ -0,0 +1,90 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Tbc.Host.Components.Abstractions;
using Tbc.Host.Components.CommandProcessor.Models;

namespace Tbc.Host.Components.CommandProcessor
{
public class CommandProcessor : ComponentBase<CommandProcessor>, ICommandProcessor
{
public List<TbcComponentCommand> Commands { get; set; }

public CommandProcessor(ILogger<CommandProcessor> logger) : base(logger)
{
}

public void RegisterCommands(object context)
=> RegisterManyCommands(context);

public void RegisterManyCommands(params object[] context)
{
var commands = new List<TbcComponentCommand>();

foreach (var obj in context)
commands.AddRange(Descend(obj));

Commands = commands;
}

public void PrintCommands()
{
Logger.LogInformation(
JsonConvert.SerializeObject(
Commands
.GroupBy(x => x.ComponentIdentifier, x => x.Command)
.Select(x => new { Component = x.Key, Commands = x.ToList() })
, Formatting.Indented));
}

public async Task<object> HandleCommand(string command)
{
if (String.IsNullOrWhiteSpace(command))
return null;

Logger.LogInformation("Received command: {Command}", command);

var isCommandForTarget = command.StartsWith("!");
if (isCommandForTarget)
command = command[1..];

var parts = command.Split(' ');
var cmd = parts[0];
var args = parts[1..];

var handlers =

isCommandForTarget
? Commands.Where(x => x.Command.Command == "run-on-target").ToList()
: Commands
.Where(x => String.Equals(x.Command.Command, cmd, StringComparison.InvariantCultureIgnoreCase))
.ToList();

if (!handlers.Any())
{
Logger.LogWarning("No handler exists for command '{Command}' with arguments '{Arguments}'", cmd, args);
return null;
}

foreach (var handler in handlers)
await handler.Command.Execute(cmd, args);

return "cool";
}

private IEnumerable<TbcComponentCommand> Descend(object o)
{
if (o is IExposeCommands iec)
foreach (var cmd in iec.Commands)
yield return new TbcComponentCommand {ComponentIdentifier = iec.Identifier, Command = cmd};

if (o is IHaveComponentsThatExposeCommands ihctec)
foreach (var component in ihctec.Components)
foreach (var cmd in Descend(component))
yield return cmd;
}
}
}
@@ -0,0 +1,12 @@
using System.Threading.Tasks;

namespace Tbc.Host.Components.CommandProcessor
{
public interface ICommandProcessor
{
void RegisterCommands(object context);
void RegisterManyCommands(params object[] context);
Task<object> HandleCommand(string command);
void PrintCommands();
}
}
@@ -0,0 +1,6 @@
namespace Tbc.Host.Components.CommandProcessor.Models
{
public interface IExposeCommandInterface
{
}
}
@@ -0,0 +1,10 @@
using System.Collections.Generic;

namespace Tbc.Host.Components.CommandProcessor.Models
{
public interface IExposeCommands
{
string Identifier { get; }
IEnumerable<TbcCommand> Commands { get; }
}
}
@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Tbc.Protocol;

namespace Tbc.Host.Components.CommandProcessor.Models
{
public interface IHaveComponentsThatExposeCommands
{
IEnumerable<IExposeCommands> Components { get; }
}

public interface IWantToRequestCommands
{
Func<ExecuteCommandRequest, Task> RequestCommand { get; set; }
}
}
@@ -0,0 +1,14 @@
using System;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace Tbc.Host.Components.CommandProcessor.Models
{
public class TbcCommand
{
public string Command { get; set; }

[JsonIgnore]
public Func<string, string[], Task> Execute { get; set; }
}
}
@@ -0,0 +1,8 @@
namespace Tbc.Host.Components.CommandProcessor.Models
{
public class TbcComponentCommand
{
public string ComponentIdentifier { get; set; }
public TbcCommand Command { get; set; }
}
}

0 comments on commit 70da01e

Please sign in to comment.