Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[new] PART-2 NamedPipeService #3456

Open
wants to merge 33 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
17129aa
Add `NamedPipeService` to `plugins`
cschuchardt88 Aug 6, 2024
d1c24da
Added Tests for `NamedPipeService`
cschuchardt88 Aug 6, 2024
e05af5c
Fixed `namespace` issue
cschuchardt88 Aug 6, 2024
324041b
Merge branch 'master' into add/plugins/namedpipe
cschuchardt88 Aug 6, 2024
e7449e8
Added `Plugins` Class
cschuchardt88 Aug 8, 2024
456e1a3
Merge branch 'master' into add/plugins/namedpipe
cschuchardt88 Aug 10, 2024
9fbd3ff
Added `PipeCount` for `ListenerQueueCount`
cschuchardt88 Aug 10, 2024
ef8b730
Merge branch 'add/plugins/namedpipe' of https://github.com/cschuchard…
cschuchardt88 Aug 10, 2024
b75fa89
Updated `main.yml` to enable test for `NamedPipes` plugin
cschuchardt88 Aug 10, 2024
7908274
Changed `NamedPipeEndPoint` to use `HashCode` class for `GetHashCode`…
cschuchardt88 Aug 10, 2024
8ffa63a
Fixed `GetHashCode`
cschuchardt88 Aug 10, 2024
7a33593
Added `Unmanaged` `Array` payload
cschuchardt88 Aug 10, 2024
4fb3351
Added `PipeMemoryPool` Payload
cschuchardt88 Aug 10, 2024
ce0ab72
Added more tests `GetBlockHeight` and `GetBlock` for server/client se…
cschuchardt88 Aug 11, 2024
50f7c0d
dotnet format
cschuchardt88 Aug 11, 2024
fc9a7b9
Added `MemoryPool` to `PipeServer`
cschuchardt88 Aug 14, 2024
711ea3b
Merge branch 'master' into add/plugins/namedpipe-part-2
cschuchardt88 Aug 14, 2024
eb569c5
Removed `PipeMemoryPool` payload
cschuchardt88 Aug 14, 2024
9664823
Added `RemoteNodePayload` and `StringPayload`
cschuchardt88 Aug 14, 2024
89a4078
Added `LastBlockIndex` to `PipeRemoteNodePayload`
cschuchardt88 Aug 15, 2024
da8cf81
Removed `Tell` command
cschuchardt88 Aug 16, 2024
74cb299
Renamed `RemoteNodePayload` to `PipeShowStatePayload`
cschuchardt88 Aug 16, 2024
0b8bc9e
Merge branch 'master' into add/plugins/namedpipe-part-2
cschuchardt88 Aug 25, 2024
1064b84
Added `UnitTest` for `Send_Damaged_Packet`
cschuchardt88 Aug 25, 2024
f695674
Added `UT_PipeMessage` tests
cschuchardt88 Aug 25, 2024
b1b3646
Fixed Tests and formating
cschuchardt88 Aug 25, 2024
5bf4e2d
Added `GetContractState` messages, `PipeContractState` payload and Te…
cschuchardt88 Aug 25, 2024
93527a2
Touch ups and bug fixes
cschuchardt88 Aug 26, 2024
5e2f28d
Fixed Test
cschuchardt88 Aug 26, 2024
ac40cd9
Moving code around
cschuchardt88 Aug 26, 2024
ea0363a
Added more error logic and unit tests
cschuchardt88 Aug 26, 2024
d9500db
Optimized `IPipeMessage`, `PipeArrayPayload` and `PipeSerializablePay…
cschuchardt88 Aug 27, 2024
2dbf89a
Merge branch 'master' into add/plugins/namedpipe-part-2
cschuchardt88 Sep 6, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ jobs:
dotnet test ./tests/Neo.Plugins.RpcServer.Tests --output ./bin/tests/Neo.Plugins.RpcServer.Tests
dotnet test ./tests/Neo.Plugins.Storage.Tests --output ./bin/tests/Neo.Plugins.Storage.Tests
dotnet test ./tests/Neo.Plugins.ApplicationLogs.Tests --output ./bin/tests/Neo.Plugins.ApplicationLogs.Tests
dotnet test ./tests/Neo.Plugins.NamedPipeService.Tests --output ./bin/tests/Neo.Plugins.NamedPipeService.Tests

- name: Coveralls
if: matrix.os == 'ubuntu-latest'
Expand All @@ -109,6 +110,7 @@ jobs:
${{ github.workspace }}/tests/Neo.Plugins.Storage.Tests/TestResults/coverage.info
${{ github.workspace }}/tests/Neo.Plugins.ApplicationLogs.Tests/TestResults/coverage.info
${{ github.workspace }}/tests/Neo.Extensions.Tests/TestResults/coverage.info
${{ github.workspace }}/tests/Neo.Plugins.NamedPipeService.Tests/TestResults/coverage.info

PublishPackage:
if: github.ref == 'refs/heads/master' && startsWith(github.repository, 'neo-project/')
Expand Down
16 changes: 15 additions & 1 deletion neo.sln
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RpcClient", "src\Plugins\Rp
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Neo.Plugins.ApplicationLogs.Tests", "tests\Neo.Plugins.ApplicationLogs.Tests\Neo.Plugins.ApplicationLogs.Tests.csproj", "{8C866DC8-2E55-4399-9563-2F47FD4602EC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Neo.Extensions.Tests", "tests\Neo.Extensions.Tests\Neo.Extensions.Tests.csproj", "{77FDEE2E-9381-4BFC-B9E6-741EDBD6B90F}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Neo.Extensions.Tests", "tests\Neo.Extensions.Tests\Neo.Extensions.Tests.csproj", "{77FDEE2E-9381-4BFC-B9E6-741EDBD6B90F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NamedPipeService", "src\Plugins\NamedPipeService\NamedPipeService.csproj", "{DACD4CFA-3D24-4329-A1D3-D5EE9E268CE3}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Neo.Plugins.NamedPipeService.Tests", "tests\Neo.Plugins.NamedPipeService.Tests\Neo.Plugins.NamedPipeService.Tests.csproj", "{38599EC3-D97C-408C-BD3B-E712831955D0}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down Expand Up @@ -228,6 +232,14 @@ Global
{77FDEE2E-9381-4BFC-B9E6-741EDBD6B90F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{77FDEE2E-9381-4BFC-B9E6-741EDBD6B90F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{77FDEE2E-9381-4BFC-B9E6-741EDBD6B90F}.Release|Any CPU.Build.0 = Release|Any CPU
{DACD4CFA-3D24-4329-A1D3-D5EE9E268CE3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DACD4CFA-3D24-4329-A1D3-D5EE9E268CE3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DACD4CFA-3D24-4329-A1D3-D5EE9E268CE3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DACD4CFA-3D24-4329-A1D3-D5EE9E268CE3}.Release|Any CPU.Build.0 = Release|Any CPU
{38599EC3-D97C-408C-BD3B-E712831955D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{38599EC3-D97C-408C-BD3B-E712831955D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{38599EC3-D97C-408C-BD3B-E712831955D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{38599EC3-D97C-408C-BD3B-E712831955D0}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -269,6 +281,8 @@ Global
{185ADAFC-BFC6-413D-BC2E-97F9FB0A8AF0} = {C2DC830A-327A-42A7-807D-295216D30DBB}
{8C866DC8-2E55-4399-9563-2F47FD4602EC} = {7F257712-D033-47FF-B439-9D4320D06599}
{77FDEE2E-9381-4BFC-B9E6-741EDBD6B90F} = {EDE05FA8-8E73-4924-BC63-DD117127EEE1}
{DACD4CFA-3D24-4329-A1D3-D5EE9E268CE3} = {C2DC830A-327A-42A7-807D-295216D30DBB}
{38599EC3-D97C-408C-BD3B-E712831955D0} = {7F257712-D033-47FF-B439-9D4320D06599}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {BCBA19D9-F868-4C6D-8061-A2B91E06E3EC}
Expand Down
30 changes: 30 additions & 0 deletions src/Neo.Extensions/ObjectExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright (C) 2015-2024 The Neo Project.
//
// ObjectExtensions.cs file belongs to the neo project and is free
// software distributed under the MIT software license, see the
// accompanying file LICENSE in the main directory of the
// repository or http://www.opensource.org/licenses/mit-license.php
// for more details.
//
// Redistribution and use in source and binary forms with or without
// modifications are permitted.

using System;

namespace Neo.Extensions
{
public static class ObjectExtensions
{
public static TResult TryCatch<TSource, TResult>(this TSource obj, Func<TSource, TResult> func, TResult defaultOnError)
{
try
{
return func(obj);
}
catch
{
return defaultOnError;
}
}
}
}
83 changes: 83 additions & 0 deletions src/Neo.Extensions/TaskExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// Copyright (C) 2015-2024 The Neo Project.
//
// TaskExtensions.cs file belongs to the neo project and is free
// software distributed under the MIT software license, see the
// accompanying file LICENSE in the main directory of the
// repository or http://www.opensource.org/licenses/mit-license.php
// for more details.
//
// Redistribution and use in source and binary forms with or without
// modifications are permitted.

using System;
using System.Threading.Tasks;

namespace Neo.Extensions
{
public static class TaskExtensions
{
private const int DefaultTimeoutSeconds = 10;

public static ValueTask<TResult> DefaultTimeout<TResult>(this ValueTask<TResult> valueTask) =>
TimeoutAfter(valueTask, TimeSpan.FromSeconds(DefaultTimeoutSeconds));

public static ValueTask DefaultTimeout(this ValueTask valueTask) =>
TimeoutAfter(valueTask, TimeSpan.FromSeconds(DefaultTimeoutSeconds));

public static Task<TResult> DefaultTimeout<TResult>(this Task<TResult> task) =>
TimeoutAfter(task, TimeSpan.FromSeconds(DefaultTimeoutSeconds));

public static Task DefaultTimeout(this Task task)
=> TimeoutAfter(task, TimeSpan.FromSeconds(DefaultTimeoutSeconds));

public static async ValueTask<TResult> TimeoutAfter<TResult>(this ValueTask<TResult> valueTask, TimeSpan timeout)
{
#if NET5_0_OR_GREATER
return await valueTask.AsTask().WaitAsync(timeout).ConfigureAwait(false);
#else
var task = valueTask.AsTask();
if (task.Wait(timeout))
return await task.ConfigureAwait(false);
else
throw new TimeoutException();
#endif
}

public static async ValueTask TimeoutAfter(this ValueTask valueTask, TimeSpan timeout)
{
#if NET5_0_OR_GREATER
await valueTask.AsTask().WaitAsync(timeout).ConfigureAwait(false);
#else
var task = valueTask.AsTask();
if (task.Wait(timeout))
await task.ConfigureAwait(false);
else
throw new TimeoutException();
#endif
}

public static async Task<TResult> TimeoutAfter<TResult>(this Task<TResult> task, TimeSpan timeout)
{
#if NET5_0_OR_GREATER
return await task.WaitAsync(timeout).ConfigureAwait(false);
#else
if (task.Wait(timeout))
return await task.ConfigureAwait(false);
else
throw new TimeoutException();
#endif
}

public static async Task TimeoutAfter(this Task task, TimeSpan timeout)
{
#if NET5_0_OR_GREATER
await task.WaitAsync(timeout).ConfigureAwait(false);
#else
if (task.Wait(timeout))
await task.ConfigureAwait(false);
else
throw new TimeoutException();
#endif
}
}
}
116 changes: 116 additions & 0 deletions src/Neo/Cryptography/Crc32.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
// Copyright (C) 2015-2024 The Neo Project.
//
// Crc32.cs file belongs to the neo project and is free
// software distributed under the MIT software license, see the
// accompanying file LICENSE in the main directory of the
// repository or http://www.opensource.org/licenses/mit-license.php
// for more details.
//
// Redistribution and use in source and binary forms with or without
// modifications are permitted.

using System;
using System.Collections.Generic;
using System.Security.Cryptography;

namespace Neo.Cryptography
{
public sealed class Crc32 : HashAlgorithm
{
public static readonly uint DefaultPolynomial = 0xedb88320u;
public static readonly uint DefaultSeed = 0xffffffffu;

private static uint[] s_defaultTable;

public override int HashSize => 32;

private readonly uint _seed;
private readonly uint[] _table;
private uint _hash;

public Crc32() : this(DefaultPolynomial, DefaultSeed)
{

}

public Crc32(
uint polynomial,
uint seed)
{
if (BitConverter.IsLittleEndian)
throw new PlatformNotSupportedException("Not supported on Big Endian processors");

_table = InitializeTable(polynomial);
_seed = seed;
}

public override void Initialize()
{
_hash = _seed;
}

protected override void HashCore(byte[] array, int ibStart, int cbSize)
{
_hash = CalculateHash(_table, _hash, array, ibStart, cbSize);
}

protected override byte[] HashFinal()
{
var hashBuffer = UInt32ToBigEndianBytes(~_hash);
HashValue = hashBuffer;
return hashBuffer;
}

public static uint Compute(byte[] buffer) =>
Compute(DefaultSeed, buffer);

public static uint Compute(uint seed, byte[] buffer) =>
Compute(DefaultPolynomial, seed, buffer);

public static uint Compute(uint polynomial, uint seed, byte[] buffer) =>
~CalculateHash(InitializeTable(polynomial), seed, buffer, 0, buffer.Length);

private static uint[] InitializeTable(uint polynomial)
{
if (polynomial == DefaultPolynomial && s_defaultTable != null)
return s_defaultTable;

var createTable = new uint[256];
for (var i = 0u; i < 256u; i++)
{
var entry = i;
for (var j = 0; j < 8; j++)
{
if ((entry & 1) == 1)
entry = (entry >> 1) ^ polynomial;
else
entry >>= 1;
}
createTable[i] = entry;
}

if (polynomial == DefaultPolynomial)
s_defaultTable = createTable;

return createTable;
}

private static uint CalculateHash(uint[] table, uint seed, IList<byte> buffer, int start, int size)
{
var hash = seed;
for (var i = start; i < start + size; i++)
hash = (hash >> 8) ^ table[buffer[i] ^ hash & 0xff];
return hash;
}

private static byte[] UInt32ToBigEndianBytes(uint value)
{
var result = BitConverter.GetBytes(value);

if (BitConverter.IsLittleEndian)
Array.Reverse(result);

return result;
}
}
}
44 changes: 44 additions & 0 deletions src/Plugins/NamedPipeService/Buffers/MemoryPoolBlock.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright (C) 2015-2024 The Neo Project.
//
// MemoryPoolBlock.cs file belongs to the neo project and is free
// software distributed under the MIT software license, see the
// accompanying file LICENSE in the main directory of the
// repository or http://www.opensource.org/licenses/mit-license.php
// for more details.
//
// Redistribution and use in source and binary forms with or without
// modifications are permitted.

using System;
using System.Buffers;
using System.Runtime.InteropServices;

namespace Neo.Plugins.Buffers
{
internal sealed class MemoryPoolBlock : IMemoryOwner<byte>
{
public PinnedBlockMemoryPool Pool { get; }

internal MemoryPoolBlock(
PinnedBlockMemoryPool pool,
int length)
{
Pool = pool;

var pinnedArray = GC.AllocateUninitializedArray<byte>(length, pinned: true);

Memory = MemoryMarshal.CreateFromPinnedArray(pinnedArray, 0, pinnedArray.Length);
}

#region IMemoryOwner

public Memory<byte> Memory { get; }

void IDisposable.Dispose()
{
Pool.Return(this);
}

#endregion
}
}
68 changes: 68 additions & 0 deletions src/Plugins/NamedPipeService/Buffers/PinnedBlockMemoryPool.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Copyright (C) 2015-2024 The Neo Project.
//
// PinnedBlockMemoryPool.cs file belongs to the neo project and is free
// software distributed under the MIT software license, see the
// accompanying file LICENSE in the main directory of the
// repository or http://www.opensource.org/licenses/mit-license.php
// for more details.
//
// Redistribution and use in source and binary forms with or without
// modifications are permitted.

using System;
using System.Buffers;
using System.Collections.Concurrent;

namespace Neo.Plugins.Buffers
{
internal sealed class PinnedBlockMemoryPool : MemoryPool<byte>
{
private const int AnySize = -1;

private static readonly int s_blockSize = 4096;

public static int BlockSize => s_blockSize;

public override int MaxBufferSize { get; } = s_blockSize;

private readonly ConcurrentQueue<MemoryPoolBlock> _blocks = new();
private readonly object _disposedSync = new();

private bool _isDisposed;

public override IMemoryOwner<byte> Rent(int size = AnySize)
{
ArgumentOutOfRangeException.ThrowIfGreaterThan(size, s_blockSize);
ObjectDisposedException.ThrowIf(_isDisposed, this);

if (_blocks.TryDequeue(out var block))
return block;

return new MemoryPoolBlock(this, BlockSize);
}

internal void Return(MemoryPoolBlock block)
{
if (_isDisposed == false)
_blocks.Enqueue(block);
}

protected override void Dispose(bool disposing)
{
if (_isDisposed)
return;

lock (_disposedSync)
{
_isDisposed = true;

if (disposing)
{
while (_blocks.TryDequeue(out _))
{
}
}
}
}
}
}
Loading
Loading